feat: add conversation-scoped yolo controls

This commit is contained in:
2026-09-22 08:12:07 +00:00
parent b672762be8
commit 18c4b34d08
5 changed files with 218 additions and 2 deletions
+80
View File
@@ -585,6 +585,86 @@ class TestBridge:
ev = client.ws.events()[-1]
assert ev["error"]["code"] == proto.ERR_APPROVAL_NOT_FOUND
@pytest.mark.asyncio
async def test_yolo_state_is_conversation_scoped_and_persisted(self, monkeypatch):
from pheby import hermes_bridge as hb
import tools.approval
conversation_id = "a" * 32
session_key = f"agent:main:pheby:dm:{conversation_id}"
persisted = []
class Store:
def peek_session_id(self, key):
assert key == session_key
return "session-1"
class DB:
def set_session_yolo(self, session_id, enabled):
persisted.append((session_id, enabled))
monkeypatch.setattr(hb, "_session_store", lambda: Store())
monkeypatch.setattr(hb, "_session_db", lambda: DB())
tools.approval.clear_session(session_key)
try:
assert (await hb.yolo_snapshot(conversation_id))["enabled"] is False
enabled = await hb.set_yolo(conversation_id, True)
assert enabled == {
"ok": True,
"enabled": True,
"scope": "conversation",
"conversation_id": conversation_id,
}
assert tools.approval.is_session_yolo_enabled(session_key) is True
assert (await hb.yolo_snapshot(conversation_id))["enabled"] is True
disabled = await hb.set_yolo(conversation_id, False)
assert disabled["enabled"] is False
assert tools.approval.is_session_yolo_enabled(session_key) is False
assert persisted == [("session-1", True), ("session-1", False)]
finally:
tools.approval.clear_session(session_key)
@pytest.mark.asyncio
async def test_yolo_websocket_handlers_return_snapshot_and_changed(self, tmp_path,
monkeypatch):
server = make_server(tmp_path)
client = FakeClientConnection()
conversation_id = "b" * 32
calls = []
async def snapshot(cid):
calls.append(("current", cid))
return {"ok": True, "enabled": False, "scope": "conversation",
"conversation_id": cid}
async def change(cid, enabled):
calls.append(("set", cid, enabled))
return {"ok": True, "enabled": enabled, "scope": "conversation",
"conversation_id": cid}
monkeypatch.setattr(server.bridge, "yolo_snapshot", snapshot)
monkeypatch.setattr(server.bridge, "set_yolo", change)
await server._handle_yolo_current(client, {
"type": proto.C_YOLO_CURRENT,
"conversation_id": conversation_id,
}, "r-yolo-current")
await server._handle_yolo_set(client, {
"type": proto.C_YOLO_SET,
"conversation_id": conversation_id,
"enabled": True,
}, "r-yolo-set")
events = client.ws.events()
assert events[0]["type"] == proto.S_YOLO_SNAPSHOT
assert events[0]["request_id"] == "r-yolo-current"
assert events[1]["type"] == proto.S_YOLO_CHANGED
assert events[1]["enabled"] is True
assert events[1]["request_id"] == "r-yolo-set"
assert calls == [("current", conversation_id), ("set", conversation_id, True)]
@pytest.mark.asyncio
async def test_clarify_push_and_resolve_roundtrip(self, tmp_path):
server = make_server(tmp_path)