fix(acp): bind session_id in session context for subprocess isolation
The ACP prompt path called set_session_vars(session_key=session_id, ...) without passing session_id, so the HERMES_SESSION_ID ContextVar was bound to its explicit "" default. Once the session-context machinery is engaged, _inject_session_context_env treats an explicitly-bound "" as authoritative and writes it to the child env — so subprocesses spawned during an ACP turn got an empty HERMES_SESSION_ID instead of the session's own id. Pass session_id through so child subprocesses carry the correct id. Salvage of the ACP half of #53454 by @necoweb3 (the V4A-path half is salvaged separately in the file-tools PR). Co-authored-by: necoweb3 <sswdarius@gmail.com>
This commit is contained in:
parent
ff6ed7c491
commit
a5f94e93ad
|
|
@ -1868,7 +1868,7 @@ class HermesACPAgent(acp.Agent):
|
|||
# model emits absolute paths under ~/.hermes/workspace and the
|
||||
# edit silently lands outside the editor's workspace.
|
||||
session_tokens = set_session_vars(
|
||||
session_key=session_id, cwd=state.cwd,
|
||||
session_key=session_id, session_id=session_id, cwd=state.cwd,
|
||||
)
|
||||
except Exception:
|
||||
session_tokens = None
|
||||
|
|
|
|||
|
|
@ -409,6 +409,43 @@ class TestPrompt:
|
|||
assert isinstance(resp, PromptResponse)
|
||||
assert resp.stop_reason == "refusal"
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_prompt_binds_session_id_into_subprocess_env(self, agent, mock_manager):
|
||||
"""The ACP prompt path must bridge the session id into child subprocesses.
|
||||
|
||||
Regression: ``set_session_vars`` was called with ``session_key`` only,
|
||||
leaving the ``HERMES_SESSION_ID`` ContextVar bound to the explicit ""
|
||||
default. Once the session-context machinery is engaged, that empty value
|
||||
is authoritative — so ``_make_run_env`` handed child subprocesses an
|
||||
empty ``HERMES_SESSION_ID`` instead of the session's own id.
|
||||
"""
|
||||
from tools.environments.local import _make_run_env
|
||||
|
||||
resp = await agent.new_session(cwd=".")
|
||||
state = mock_manager.get_session(resp.session_id)
|
||||
|
||||
captured: dict[str, str | None] = {}
|
||||
|
||||
def _run(*args, **kwargs):
|
||||
# Runs inside the session context copy set up by prompt().
|
||||
captured["child"] = _make_run_env({}).get("HERMES_SESSION_ID")
|
||||
return {"final_response": "ok", "messages": []}
|
||||
|
||||
state.agent.run_conversation = _run
|
||||
state.agent.model = "test-model"
|
||||
state.agent.provider = "openrouter"
|
||||
|
||||
mock_conn = MagicMock(spec=acp.Client)
|
||||
mock_conn.session_update = AsyncMock()
|
||||
agent._conn = mock_conn
|
||||
|
||||
await agent.prompt(
|
||||
prompt=[TextContentBlock(type="text", text="hi")],
|
||||
session_id=resp.session_id,
|
||||
)
|
||||
|
||||
assert captured.get("child") == resp.session_id
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue