Skip to content

fix(api-server): emit tool.completed lifecycle SSE for chat completions (#16588)#17505

Merged
teknium1 merged 1 commit into
mainfrom
hermes/hermes-a524e63a
Apr 29, 2026
Merged

fix(api-server): emit tool.completed lifecycle SSE for chat completions (#16588)#17505
teknium1 merged 1 commit into
mainfrom
hermes/hermes-a524e63a

Conversation

@teknium1

Copy link
Copy Markdown
Contributor

Salvage of #16666 by @briandevans onto current main.

Fixes #16588/v1/chat/completions streaming emits event: hermes.tool.progress with status: running for tool starts, and a matching status: completed event carrying the same toolCallId. Frontends rendering tool cards can now mark tools finished without guessing.

Why this over #16591

run_agent.py fires BOTH tool_progress_callback("tool.started", ...) AND tool_start_callback(id, name, args) for every tool start. #16591 wired both on the chat branch without dedup, producing 3 SSE events per tool (legacy running with null toolCallId + structured running + completed). Verified empirically by cherry-picking #16591 and probing with both callbacks firing — got ('running', None), ('running', 'call_x'), ('completed', 'call_x').

This PR (from #16666) drops tool_progress_callback entirely on the chat branch, wires only the structured pair, and tracks _started_tool_call_ids so orphan completes (internal tools, never-started IDs) are silently dropped instead of reaching the wire.

Changes

  • gateway/platforms/api_server.py: replace _on_tool_progress with _on_tool_start / _on_tool_complete on the chat stream; tool_progress_callback intentionally not wired (comment explains why); payload now carries toolCallId + status on the existing hermes.tool.progress event.
  • tests/gateway/test_api_server.py: updated existing tool-progress tests for the new callback shape; added test_stream_emits_tool_lifecycle_with_call_id (asserts exactly 2 per-event correlated pairs — would fail under fix(api-server): emit chat tool completion progress #16591's dup-emit) and test_stream_tool_lifecycle_skips_internal_and_orphan_completes.

Validation

scripts/run_tests.sh tests/gateway/test_api_server.py → 123/123 passing.

Closes #16591 (superseded).

Address Copilot review on PR #16666:

1. **Duplicate event on every tool start** — both ``tool_progress_callback``
   and ``tool_start_callback`` fire side-by-side in ``run_agent.py``, so
   wiring both into chat completions emitted *two* ``hermes.tool.progress``
   events per real tool call. Drop the legacy ``_on_tool_progress`` emit
   entirely; ``_on_tool_start`` now produces a single unified event that
   carries the legacy ``tool``/``emoji``/``label`` fields plus the new
   ``toolCallId``/``status`` correlation fields. Label is computed inline
   via ``build_tool_preview`` so callers do not need to pre-format it.

2. **Weak per-event correlation in the regression test** — the previous
   assertion checked that a ``toolCallId`` appeared *somewhere* in the
   aggregate, which would have passed even if ``running`` lacked the id.
   Collect ``(status, toolCallId)`` per event and assert each event
   carries the correct pair, plus exactly two events on the wire (no
   silent duplication regression).

The two existing chat-completions tool-progress tests are updated to fire
``tool_start_callback`` instead of ``tool_progress_callback``, matching
production reality where ``run_agent`` always pairs them.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

🚨 CRITICAL Supply Chain Risk Detected

This PR contains a pattern that has been used in real supply chain attacks. A maintainer must review the flagged code carefully before merging.

🚨 CRITICAL: Install-hook file added or modified

These files can execute code during package installation or interpreter startup.

Files:

hermes_cli/setup.py

Scanner only fires on high-signal indicators: .pth files, base64+exec/eval combos, subprocess with encoded commands, or install-hook files. Low-signal warnings were removed intentionally — if you're seeing this comment, the finding is worth inspecting.

@teknium1 teknium1 merged commit e0a03f3 into main Apr 29, 2026
10 of 12 checks passed
@teknium1 teknium1 deleted the hermes/hermes-a524e63a branch April 29, 2026 15:08
@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/gateway Gateway runner, session dispatch, delivery labels Apr 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/gateway Gateway runner, session dispatch, delivery P2 Medium — degraded but workaround exists type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: chat completions SSE does not emit tool completion progress

3 participants