Nudge WhatsApp group ops asks that skip @mention.

When require_mention drops an ops short-intent, send one throttled @sender tip instead of silent ignore; casual chat stays quiet.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
oliver 2026-08-10 23:41:48 +08:00
parent 94a1b5b26c
commit 6c5536b758
4 changed files with 201 additions and 0 deletions

View file

@ -653,6 +653,47 @@ def test_inbound_group_without_mention_is_silent(monkeypatch: pytest.MonkeyPatch
)
assert out.get("ok") is True
assert out.get("replies") == []
assert out.get("delivery") != "mention_nudge"
def test_inbound_group_ops_without_mention_gets_throttled_nudge(
monkeypatch: pytest.MonkeyPatch, fresh_sqlite_store: SqliteStore
) -> None:
from runtime.application.gateway.ops_short_intent import reset_group_mention_nudge_throttle_for_tests
store = fresh_sqlite_store
_setup_whatsapp_identity(store)
monkeypatch.setattr("svc.persistence.assistant_store.get_assistant_store", lambda: store)
reset_group_mention_nudge_throttle_for_tests()
payload = {
"channel": "whatsapp",
"account_id": "wa-default",
"user_id": "111@s.whatsapp.net",
"chat_id": "120363012345678@g.us",
"text": "fiber cut sites",
"is_group": True,
"mentions": [],
"metadata": {"bot_jid": "999@s.whatsapp.net", "source": "test"},
}
first = process_inbound_payload(payload)
assert first.get("delivery") == "mention_nudge"
assert first.get("ops_intent") == "fiber_cut"
assert first.get("replies") == []
outbound = store.list_channel_outbound_messages(limit=20) if hasattr(store, "list_channel_outbound_messages") else []
if not outbound:
# Fallback: inspect via raw SQL if list helper missing
with store._connect() as conn: # noqa: SLF001
rows = conn.execute(
"SELECT text, source FROM channel_outbound_message ORDER BY created_at DESC LIMIT 5"
).fetchall()
outbound = [{"text": r[0], "source": r[1]} for r in rows]
assert outbound
assert any("@mention" in str(o.get("text") or "").lower() or "@me" in str(o.get("text") or "").lower() for o in outbound)
second = process_inbound_payload(payload)
assert second.get("delivery") != "mention_nudge"
assert second.get("replies") == []
def test_inbound_dm_still_processes_without_mention(monkeypatch: pytest.MonkeyPatch, fresh_sqlite_store: SqliteStore) -> None:

View file

@ -1,8 +1,11 @@
from __future__ import annotations
from runtime.application.gateway.ops_short_intent import (
build_group_mention_nudge_text,
detect_ops_short_intent,
maybe_ops_short_intent_system_hint,
reset_group_mention_nudge_throttle_for_tests,
should_send_group_mention_nudge,
)
from runtime.tools.tool_error_hints import enrich_exec_managed_ne_error
@ -17,6 +20,29 @@ def test_detect_ops_short_intent_english_field() -> None:
assert detect_ops_short_intent("hello there how are you doing today with something else") is None
def test_group_mention_nudge_text_english() -> None:
text = build_group_mention_nudge_text(intent="fiber_cut", lang="en", triggers=["/oclaw"])
assert "@mentioned" in text.lower() or "@me" in text.lower()
assert "/oclaw" in text
assert "fiber" in text.lower()
def test_group_mention_nudge_throttle() -> None:
reset_group_mention_nudge_throttle_for_tests()
assert should_send_group_mention_nudge(
account_id="wa", chat_id="g1", user_id="u1", now=100.0, ttl_s=60.0
)
assert not should_send_group_mention_nudge(
account_id="wa", chat_id="g1", user_id="u1", now=130.0, ttl_s=60.0
)
assert should_send_group_mention_nudge(
account_id="wa", chat_id="g1", user_id="u2", now=130.0, ttl_s=60.0
)
assert should_send_group_mention_nudge(
account_id="wa", chat_id="g1", user_id="u1", now=170.0, ttl_s=60.0
)
def test_ops_short_intent_hint_english_default() -> None:
hint = maybe_ops_short_intent_system_hint(text="LOS on these sites", lang="en")
assert "fiber" in hint.lower() or "LOS" in hint