mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-24 16:54:43 +00:00
fix(gateway): deliver kanban/delegate wake-ups to api_server sessions
Wake-ups for kanban notifications and background delegation completions were injected via handle_message() using a build_session_key()-derived key, which can never match the raw X-Hermes-Session-Id key that api_server sessions run under — so the wake landed in a session nobody was reading. On top of that, ApiServerAdapter.send() reports failure without raising, and that was treated as a successful delivery, so the notify cursor advanced past events that were permanently lost; and background delegation was forced synchronous on api_server since there was no way to wake the session afterward. Fix: route wake-ups for non-push adapters through a self-post to /v1/chat/completions with the original session id, treat non-raising send failures as failures (rewind instead of advancing the cursor), and re-enable background delegation whenever a session id is available to wake. The origin session id is captured from the request-scoped api_server chat_id binding rather than HERMES_SESSION_ID: constructing a child agent calls set_current_session_id() with the subagent's internal id, clobbering that variable right before dispatch would read it and misrouting the wake into the subagent's own session. Related: #56580, #64609, #53027, #63169, #56531, #50319, #64113
This commit is contained in:
parent
185b08a2eb
commit
246eacea7b
10 changed files with 979 additions and 7 deletions
|
|
@ -2583,6 +2583,18 @@ def delegate_task(
|
|||
|
||||
_parent_tool_names = list(_model_tools._last_resolved_tool_names)
|
||||
|
||||
# Capture the ORIGINATING session's wake target BEFORE any child agent is
|
||||
# constructed: _build_child_agent() -> AIAgent() -> agent_init calls
|
||||
# set_current_session_id(child.session_id), which clobbers the
|
||||
# HERMES_SESSION_ID ContextVar and os.environ with the subagent's internal
|
||||
# id before the background-dispatch code below would read it. The
|
||||
# request-scoped chat_id binding (the raw X-Hermes-Session-Id on
|
||||
# api_server) is untouched by child construction, so read it here and
|
||||
# thread it through the dispatch.
|
||||
from tools.async_delegation import _current_origin_session_id
|
||||
|
||||
_origin_wake_sid = _current_origin_session_id()
|
||||
|
||||
# Build all child agents on the main thread (thread-safe construction)
|
||||
# Wrapped in try/finally so the global is always restored even if a
|
||||
# child build raises (otherwise _last_resolved_tool_names stays corrupted).
|
||||
|
|
@ -2921,6 +2933,30 @@ def delegate_task(
|
|||
_async_ok = async_delivery_supported()
|
||||
except Exception:
|
||||
_async_ok = True
|
||||
|
||||
_wake_sid = ""
|
||||
if not _async_ok:
|
||||
# The adapter itself cannot push, but if a raw session id is
|
||||
# bound (the API server always binds one — see
|
||||
# ApiServerAdapter._bind_api_server_session), gateway.wake can
|
||||
# still reach the session by self-POSTing /v1/chat/completions
|
||||
# with that id in X-Hermes-Session-Id once the batch completes.
|
||||
# Only fall back to forced-sync execution when there is truly no
|
||||
# session id to wake. Uses the origin captured before child
|
||||
# construction (see _origin_wake_sid above) — reading
|
||||
# HERMES_SESSION_ID here would return the subagent's internal id.
|
||||
_wake_sid = _origin_wake_sid
|
||||
if _wake_sid:
|
||||
logger.info(
|
||||
"delegate_task: async delivery unsupported on this "
|
||||
"session, but a session id is bound (%s) — dispatching "
|
||||
"in the background and waking the session via self-post "
|
||||
"when it completes instead of forcing synchronous "
|
||||
"execution.",
|
||||
_wake_sid,
|
||||
)
|
||||
_async_ok = True
|
||||
|
||||
if not _async_ok:
|
||||
logger.info(
|
||||
"delegate_task: async delivery unsupported on this session "
|
||||
|
|
@ -3013,6 +3049,7 @@ def delegate_task(
|
|||
model=creds["model"],
|
||||
session_key=_session_key,
|
||||
origin_ui_session_id=_origin_ui_session_id,
|
||||
origin_session_id=_wake_sid,
|
||||
parent_session_id=_parent_session_id,
|
||||
runner=_batch_runner,
|
||||
interrupt_fn=_batch_interrupt,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue