fix(delegation): route async delegate_task results back to originating session

The completion event already carries the dispatching session's session_key
(captured at dispatch time in delegate_tool.py:2798), but the delivery
router ignored it — results landed in whatever session was active at
completion time instead of the session that dispatched the subagent.

Changes:
- drain_notifications() in process_registry.py: optional session_key
  filter. Non-matching async_delegation events are re-queued instead of
  consumed, so they remain available for the correct session's drain.
- cli.py process_loop: passes active session_key to drain_notifications()
- tui_gateway/server.py post-turn drain: passes session_key from the
  TUI session dict
- gateway/run.py _build_process_event_source: logs warning when routing
  metadata is unresolvable (previously silent drop)
- Regression tests verifying session-scoped drain filtering

Fixes #58684
This commit is contained in:
Tony Simons 2026-07-05 01:43:37 -05:00 committed by Teknium
parent 5057f03bfd
commit f75f3cd713
5 changed files with 137 additions and 4 deletions

4
cli.py
View file

@ -15082,7 +15082,9 @@ class HermesCLI(CLIAgentSetupMixin, CLICommandsMixin):
# and watch pattern matches) while agent is idle.
try:
from tools.process_registry import process_registry
for _evt, _synth in process_registry.drain_notifications():
from tools.approval import get_current_session_key
_drain_sk = get_current_session_key(default="")
for _evt, _synth in process_registry.drain_notifications(session_key=_drain_sk):
self._pending_input.put(_synth)
except Exception:
pass