fix(delegation): route async results to origin session

Carry the live TUI session id with async delegation completion events and prefer the commissioning UI session when desktop pollers share the completion queue. Resolve compressed session keys to their continuation before treating events as orphaned, and capture the live parent agent session id for TUI/ACP dispatch.
This commit is contained in:
Dan Schnurbusch 2026-07-06 12:09:57 -05:00 committed by Teknium
parent ac6dd598a4
commit aab351bfa6
6 changed files with 262 additions and 20 deletions

View file

@ -2796,6 +2796,25 @@ def delegate_task(
return json.dumps(_sync_result, ensure_ascii=False)
_session_key = get_current_session_key(default="")
_origin_ui_session_id = ""
try:
from gateway.session_context import get_session_env
_source = get_session_env("HERMES_SESSION_SOURCE", "")
_origin_ui_session_id = get_session_env("HERMES_UI_SESSION_ID", "")
# In desktop/TUI, the routable session key is the durable
# AIAgent.session_id. Context compression can rotate that id during
# the same turn before the TUI-side session dict is re-anchored;
# if we capture the stale approval/session context key here, the
# async completion becomes an orphan and any desktop poller may
# consume it. Gateway chats are different: their session_key is the
# platform conversation key (agent:main:...), so keep it there.
if _source == "tui":
_agent_session_id = str(getattr(parent_agent, "session_id", "") or "")
if _agent_session_id:
_session_key = _agent_session_id
except Exception:
_origin_ui_session_id = ""
_child_agents = [c for (_, _, c) in children]
# Detach every child from the parent's interrupt-propagation list — the
@ -2836,6 +2855,7 @@ def delegate_task(
role=top_role,
model=creds["model"],
session_key=_session_key,
origin_ui_session_id=_origin_ui_session_id,
runner=_batch_runner,
interrupt_fn=_batch_interrupt,
max_async_children=_get_max_async_children(),