mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-27 17:58:07 +00:00
fix(api): forward subagent lifecycle on run stream
This commit is contained in:
parent
a8c9ad0bcc
commit
4fbb86d2b8
2 changed files with 88 additions and 1 deletions
|
|
@ -5975,7 +5975,43 @@ class APIServerAdapter(BasePlatformAdapter):
|
|||
"timestamp": ts,
|
||||
"text": preview or "",
|
||||
})
|
||||
# _thinking and subagent_progress are intentionally not forwarded
|
||||
elif event_type in {"subagent.start", "subagent.complete"}:
|
||||
event = {
|
||||
"event": event_type,
|
||||
"run_id": run_id,
|
||||
"timestamp": ts,
|
||||
}
|
||||
if preview is not None:
|
||||
event["preview"] = preview
|
||||
for key in (
|
||||
"goal",
|
||||
"task_count",
|
||||
"task_index",
|
||||
"subagent_id",
|
||||
"parent_id",
|
||||
"depth",
|
||||
"model",
|
||||
"tool_count",
|
||||
"status",
|
||||
"summary",
|
||||
"duration_seconds",
|
||||
"input_tokens",
|
||||
"output_tokens",
|
||||
"reasoning_tokens",
|
||||
"api_calls",
|
||||
"cost_usd",
|
||||
"files_read",
|
||||
"files_written",
|
||||
"output_tail",
|
||||
):
|
||||
value = kwargs.get(key)
|
||||
if value is not None:
|
||||
event[key] = value
|
||||
_push(event)
|
||||
# _thinking, subagent.tool, and subagent_progress are intentionally
|
||||
# not forwarded on the /v1/runs stream: they are high-volume UI
|
||||
# noise. Lifecycle boundaries (start/complete) still need to land
|
||||
# so clients can observe delegate_task timeouts and failures.
|
||||
|
||||
return _callback
|
||||
|
||||
|
|
|
|||
|
|
@ -891,6 +891,57 @@ class TestAgentExecution:
|
|||
assert captured["service_tier"] == "priority"
|
||||
|
||||
|
||||
class TestRunEventCallback:
|
||||
@pytest.mark.asyncio
|
||||
async def test_forwards_subagent_lifecycle_events(self, adapter):
|
||||
run_id = "run_subagent_events"
|
||||
loop = asyncio.get_running_loop()
|
||||
queue = asyncio.Queue()
|
||||
adapter._run_streams[run_id] = queue
|
||||
adapter._run_statuses.pop(run_id, None)
|
||||
|
||||
callback = adapter._make_run_event_callback(run_id, loop)
|
||||
|
||||
callback(
|
||||
"subagent.start",
|
||||
preview="research candidate issue",
|
||||
goal="research candidate issue",
|
||||
task_index=0,
|
||||
task_count=1,
|
||||
subagent_id="deleg_123",
|
||||
)
|
||||
callback(
|
||||
"subagent.complete",
|
||||
preview="Timed out after 300s",
|
||||
goal="research candidate issue",
|
||||
task_index=0,
|
||||
task_count=1,
|
||||
subagent_id="deleg_123",
|
||||
status="timeout",
|
||||
duration_seconds=300.0,
|
||||
summary="Subagent timed out after 300s with 2 API call(s) completed.",
|
||||
api_calls=2,
|
||||
)
|
||||
|
||||
start_event = await asyncio.wait_for(queue.get(), timeout=1.0)
|
||||
complete_event = await asyncio.wait_for(queue.get(), timeout=1.0)
|
||||
|
||||
assert start_event["event"] == "subagent.start"
|
||||
assert start_event["preview"] == "research candidate issue"
|
||||
assert start_event["task_index"] == 0
|
||||
assert start_event["task_count"] == 1
|
||||
assert start_event["subagent_id"] == "deleg_123"
|
||||
|
||||
assert complete_event["event"] == "subagent.complete"
|
||||
assert complete_event["preview"] == "Timed out after 300s"
|
||||
assert complete_event["status"] == "timeout"
|
||||
assert complete_event["duration_seconds"] == 300.0
|
||||
assert complete_event["api_calls"] == 2
|
||||
assert "timed out after 300s" in complete_event["summary"]
|
||||
|
||||
assert adapter._run_statuses[run_id]["last_event"] == "subagent.complete"
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# /health endpoint
|
||||
# ---------------------------------------------------------------------------
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue