Adds a distinct two-tone attention sound (880->660Hz) for approval and clarify prompts so they are not confused with the existing completion sound, plus sidebar attention badges + colored rails driven by `attention` metadata on /api/sessions. Includes lock-safety note: the in-lock publish_session_list_changed() calls in clarify.py are safe because publish() only takes the leaf _SESSION_EVENTS_LOCK and never re-acquires clarify._lock (verified by Opus advisor review). Co-authored-by: ai-ag2026 <261867348+ai-ag2026@users.noreply.github.com>
69 lines
2.3 KiB
Python
69 lines
2.3 KiB
Python
"""Attention badges must refresh the session sidebar immediately.
|
|
|
|
Approval/clarify queues already notify the per-session card SSE stream. The
|
|
sidebar, however, listens to the global session-events stream and then reloads
|
|
``/api/sessions``. Without publishing on queue transitions, the badge and
|
|
attention sound only appear after the user opens the affected thread.
|
|
"""
|
|
|
|
|
|
def test_clarify_pending_and_resolved_publish_session_list_changed(monkeypatch):
|
|
import api.clarify as clarify
|
|
|
|
events = []
|
|
monkeypatch.setattr(
|
|
clarify,
|
|
"publish_session_list_changed",
|
|
lambda reason: events.append(reason),
|
|
)
|
|
sid = "test-attention-clarify"
|
|
|
|
with clarify._lock:
|
|
clarify._pending.pop(sid, None)
|
|
clarify._gateway_queues.pop(sid, None)
|
|
clarify._gateway_notify_cbs.pop(sid, None)
|
|
|
|
try:
|
|
entry = clarify.submit_pending(sid, {"question": "Need input?"})
|
|
assert events == ["attention_pending"]
|
|
pending = clarify.get_pending(sid)
|
|
assert pending is not None
|
|
assert pending["clarify_id"] == entry.clarify_id
|
|
|
|
assert clarify.resolve_clarify_by_id(sid, entry.clarify_id, "yes") is True
|
|
assert events == ["attention_pending", "attention_resolved"]
|
|
assert clarify.get_pending(sid) is None
|
|
finally:
|
|
with clarify._lock:
|
|
clarify._pending.pop(sid, None)
|
|
clarify._gateway_queues.pop(sid, None)
|
|
clarify._gateway_notify_cbs.pop(sid, None)
|
|
|
|
|
|
def test_approval_pending_and_resolved_publish_session_list_changed(monkeypatch):
|
|
import api.routes as routes
|
|
|
|
events = []
|
|
monkeypatch.setattr(
|
|
routes,
|
|
"publish_session_list_changed",
|
|
lambda reason: events.append(reason),
|
|
)
|
|
sid = "test-attention-approval"
|
|
|
|
with routes._lock:
|
|
routes._pending.pop(sid, None)
|
|
routes._gateway_queues.pop(sid, None)
|
|
|
|
try:
|
|
routes.submit_pending(sid, {"command": "echo ok", "pattern_key": "test-key"})
|
|
assert events == ["attention_pending"]
|
|
|
|
ok = routes._resolve_approval_legacy(sid, "", "deny")
|
|
assert ok is True
|
|
assert events == ["attention_pending", "attention_resolved"]
|
|
finally:
|
|
with routes._lock:
|
|
routes._pending.pop(sid, None)
|
|
routes._gateway_queues.pop(sid, None)
|