feat: add conversation-scoped yolo controls
This commit is contained in:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user