fix(agent): propagate effective session key through subagent pipeline
The previous fix hardcoded session_key_override as channel:chat_id which broke unified session mode where pending queues use "unified:default". Propagate the effective key from _set_tool_context through SpawnTool into the origin dict so _announce_result routes to the correct pending queue in both normal and unified session modes.
This commit is contained in:
@@ -412,3 +412,91 @@ class TestSubagentCancellation:
|
||||
assert cancelled.is_set()
|
||||
assert task.cancelled()
|
||||
mgr._announce_result.assert_not_awaited()
|
||||
|
||||
|
||||
class TestSubagentAnnounceSessionKey:
|
||||
"""Verify _announce_result uses the effective session key for mid-turn routing."""
|
||||
|
||||
def _make_mgr(self):
|
||||
"""Create a SubagentManager with mocked deps and its bus."""
|
||||
from nanobot.agent.subagent import SubagentManager
|
||||
from nanobot.bus.queue import MessageBus
|
||||
|
||||
bus = MessageBus()
|
||||
provider = MagicMock()
|
||||
provider.get_default_model.return_value = "test-model"
|
||||
mgr = SubagentManager(
|
||||
provider=provider,
|
||||
workspace=MagicMock(),
|
||||
bus=bus,
|
||||
max_tool_result_chars=_MAX_TOOL_RESULT_CHARS,
|
||||
)
|
||||
return mgr, bus
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_announce_uses_effective_key_in_unified_mode(self):
|
||||
"""In unified session mode, session_key_override must be 'unified:default'
|
||||
so the result matches the pending queue key."""
|
||||
mgr, bus = self._make_mgr()
|
||||
|
||||
origin = {"channel": "telegram", "chat_id": "111", "session_key": "unified:default"}
|
||||
await mgr._announce_result("sub-1", "label", "task", "result", origin, "ok")
|
||||
|
||||
msg = await bus.consume_inbound()
|
||||
assert msg.session_key_override == "unified:default"
|
||||
assert msg.session_key == "unified:default"
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_announce_uses_raw_key_in_normal_mode(self):
|
||||
"""Without unified sessions, session_key_override is the raw channel:chat_id."""
|
||||
mgr, bus = self._make_mgr()
|
||||
|
||||
origin = {"channel": "telegram", "chat_id": "222", "session_key": "telegram:222"}
|
||||
await mgr._announce_result("sub-2", "label", "task", "result", origin, "ok")
|
||||
|
||||
msg = await bus.consume_inbound()
|
||||
assert msg.session_key_override == "telegram:222"
|
||||
assert msg.session_key == "telegram:222"
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_announce_falls_back_to_origin_when_no_session_key(self):
|
||||
"""When session_key is None, fallback to f'{channel}:{chat_id}'."""
|
||||
mgr, bus = self._make_mgr()
|
||||
|
||||
origin = {"channel": "discord", "chat_id": "333", "session_key": None}
|
||||
await mgr._announce_result("sub-3", "label", "task", "result", origin, "ok")
|
||||
|
||||
msg = await bus.consume_inbound()
|
||||
assert msg.session_key_override == "discord:333"
|
||||
assert msg.channel == "system"
|
||||
assert msg.chat_id == "discord:333"
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_session_key_flows_through_run_subagent(self):
|
||||
"""Verify session_key in origin propagates from _run_subagent to _announce_result."""
|
||||
from nanobot.agent.subagent import SubagentStatus
|
||||
|
||||
mgr, bus = self._make_mgr()
|
||||
|
||||
async def fake_run(spec):
|
||||
return SimpleNamespace(
|
||||
stop_reason="done",
|
||||
final_content="done",
|
||||
error=None,
|
||||
tool_events=[],
|
||||
)
|
||||
|
||||
mgr.runner.run = AsyncMock(side_effect=fake_run)
|
||||
|
||||
status = SubagentStatus(
|
||||
task_id="sub-4", label="label", task_description="task",
|
||||
started_at=time.monotonic(),
|
||||
)
|
||||
await mgr._run_subagent(
|
||||
"sub-4", "task", "label",
|
||||
{"channel": "telegram", "chat_id": "444", "session_key": "unified:default"},
|
||||
status,
|
||||
)
|
||||
|
||||
msg = await bus.consume_inbound()
|
||||
assert msg.session_key_override == "unified:default"
|
||||
|
||||
Reference in New Issue
Block a user