fix(agent): retire superseded approvals

This commit is contained in:
RaresKeY
2026-08-15 07:49:52 +00:00
parent 105a7c0d96
commit d401e806d4
6 changed files with 89 additions and 3 deletions
@@ -50,6 +50,8 @@ def _patch_common(monkeypatch, exec_calls):
monkeypatch.setattr(al, "get_setting", lambda key, default=None: default, raising=False)
monkeypatch.setattr(al, "get_mcp_manager", lambda: None, raising=False)
monkeypatch.setattr(al, "estimate_tokens", lambda *a, **k: 10, raising=False)
# These tests exercise tool-channel parsing, not owner authorization.
monkeypatch.setattr(al, "blocked_tools_for_owner", lambda owner: set(), raising=False)
async def _fake_exec(block, *a, **k):
exec_calls.append(block)
+28
View File
@@ -376,6 +376,34 @@ async def test_chat_stream_denial_keeps_originating_run_tainted(monkeypatch):
assert chat_routes.tool_approval_store.peek(pending.approval_id) is None
@pytest.mark.asyncio
async def test_chat_stream_normal_reply_retires_pending_action_but_keeps_taint(
monkeypatch,
):
from src.tool_capabilities import capabilities_for_action
captured = {}
endpoint = _chat_stream_endpoint(monkeypatch, "agent", captured)
pending = chat_routes.tool_approval_store.create(
owner="alice",
session_id="session-1",
origin_run_id="run-1",
tool_name="bash",
content="printf retry",
workspace=None,
external_untrusted_context_seen=True,
capabilities=capabilities_for_action("bash", "printf retry"),
)
response = await endpoint(_RouteRequest("agent"))
async for _ in response.body_iterator:
pass
assert "exact_approval" not in captured
assert captured["agent_external_untrusted_context_seen"] is True
assert chat_routes.tool_approval_store.peek(pending.approval_id) is None
@pytest.mark.asyncio
async def test_chat_stream_approval_ignores_research_and_new_attachments(monkeypatch):
from src.tool_capabilities import capabilities_for_action
+11
View File
@@ -105,6 +105,17 @@ def test_new_session_approval_supersedes_prior_pending_action():
assert store.peek(second.approval_id) == second
def test_ordinary_session_turn_retires_pending_action_and_preserves_taint():
store = ToolApprovalStore()
pending = _pending(store, owner="Alice", session_id="session-1")
assert store.retire_for_session(owner="bob", session_id="session-1") is False
assert store.peek(pending.approval_id) == pending
assert store.retire_for_session(owner="alice", session_id="session-1") is True
assert store.peek(pending.approval_id) is None
assert store.retire_for_session(owner="alice", session_id=None) is False
def test_independent_headless_runs_do_not_supersede_each_other():
store = ToolApprovalStore()
first = _pending(store, session_id=None, origin_run_id="headless-1")
@@ -47,6 +47,8 @@ def test_tool_task_cancelled_on_generator_close(monkeypatch):
monkeypatch.setattr(al, "get_setting", lambda key, default=None: default, raising=False)
monkeypatch.setattr(al, "get_mcp_manager", lambda: None, raising=False)
monkeypatch.setattr(al, "estimate_tokens", lambda *a, **k: 10, raising=False)
# This test exercises task cancellation, not owner authorization.
monkeypatch.setattr(al, "blocked_tools_for_owner", lambda owner: set(), raising=False)
monkeypatch.setattr(al, "execute_tool_block", _slow_exec, raising=False)
native_calls = [{"name": "bash", "arguments": json.dumps({"command": "sleep 60"})}]