Import AITURK IDE 1.0.0-beta.1 from Hermes 63279301; preserve MIT license
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
"""Every review path hands the fork a snapshot that cannot alias the live transcript.
|
||||
|
||||
``AIAgent._spawn_background_review`` is the single chokepoint the automatic
|
||||
post-turn review, the idle-queue deferral and both explicit ``/refine`` entry
|
||||
points (CLI mixin + gateway slash command) go through; it clones the snapshot
|
||||
structurally there. A shallow ``list()`` would share the nested
|
||||
``tool_calls`` / ``content`` containers with the persisted history, so the
|
||||
fork's in-place transcript sanitization would rewrite the parent's messages
|
||||
(#100795). These tests drive the real /refine handlers into the real
|
||||
chokepoint and capture what reaches the spawn.
|
||||
"""
|
||||
|
||||
import threading
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
def _agent_with_real_chokepoint():
|
||||
"""MagicMock agent whose _spawn_background_review is the REAL method.
|
||||
|
||||
Everything below the chokepoint (thread spawn) is captured at
|
||||
``_spawn_background_review_now`` so no fork actually runs.
|
||||
"""
|
||||
from run_agent import AIAgent
|
||||
|
||||
agent = MagicMock()
|
||||
agent.valid_tool_names = {"memory"}
|
||||
agent._delegate_depth = 0
|
||||
agent._spawn_background_review = AIAgent._spawn_background_review.__get__(agent)
|
||||
return agent
|
||||
|
||||
|
||||
def _nested_history():
|
||||
return [
|
||||
{"role": "user", "content": [{"type": "text", "text": "ask"}]},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "ok",
|
||||
"tool_calls": [{
|
||||
"id": "call-1",
|
||||
"function": {"name": "read_file", "arguments": '{"path":"x"}'},
|
||||
}],
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
def _assert_isolated(live, snapshot):
|
||||
assert snapshot == live # same shape/bytes …
|
||||
for live_msg, snap_msg in zip(live, snapshot):
|
||||
assert snap_msg is not live_msg # … but no shared containers
|
||||
for key in ("content", "tool_calls"):
|
||||
if isinstance(live_msg.get(key), (dict, list)):
|
||||
assert snap_msg[key] is not live_msg[key]
|
||||
# Mutating the snapshot the way the fork's sanitizers do must not leak.
|
||||
snapshot[0]["content"][0]["text"] = "mutated"
|
||||
snapshot[1]["tool_calls"][0]["function"]["arguments"] = "{}"
|
||||
assert live[0]["content"][0]["text"] == "ask"
|
||||
assert live[1]["tool_calls"][0]["function"]["arguments"] == '{"path":"x"}'
|
||||
|
||||
|
||||
def test_cli_refine_snapshot_does_not_alias_live_history(monkeypatch):
|
||||
from hermes_cli.cli_commands_mixin import CLICommandsMixin
|
||||
|
||||
monkeypatch.setattr("cli._cprint", lambda *a, **k: None, raising=False)
|
||||
agent = _agent_with_real_chokepoint()
|
||||
cli = object.__new__(CLICommandsMixin)
|
||||
cli.agent = agent
|
||||
cli.conversation_history = _nested_history()
|
||||
|
||||
cli._handle_refine_command("/refine")
|
||||
|
||||
agent._spawn_background_review_now.assert_called_once()
|
||||
snapshot = agent._spawn_background_review_now.call_args.kwargs["messages_snapshot"]
|
||||
_assert_isolated(cli.conversation_history, snapshot)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_gateway_refine_snapshot_does_not_alias_live_history():
|
||||
from gateway.run import GatewayRunner
|
||||
|
||||
key = "agent:main:test:dm:1"
|
||||
agent = _agent_with_real_chokepoint()
|
||||
agent._session_messages = _nested_history()
|
||||
|
||||
runner = object.__new__(GatewayRunner)
|
||||
runner._running_agents = {}
|
||||
runner._agent_cache = {key: agent}
|
||||
runner._agent_cache_lock = threading.Lock()
|
||||
runner._session_key_for_source = lambda source: key
|
||||
|
||||
event = MagicMock()
|
||||
event.source = object()
|
||||
event.get_command_args.return_value = ""
|
||||
|
||||
out = await runner._handle_refine_command(event)
|
||||
|
||||
assert out.startswith("⚗")
|
||||
agent._spawn_background_review_now.assert_called_once()
|
||||
snapshot = agent._spawn_background_review_now.call_args.kwargs["messages_snapshot"]
|
||||
_assert_isolated(agent._session_messages, snapshot)
|
||||
Reference in New Issue
Block a user