Files
Hermes-ui/packages
paulocavallari cb410e5007 fix(bridge): preserve text/tool-call ordering to stop split narration (#1145)
When the model interleaves narration text with tool calls within one
turn ("text → tool → more text"), the assistant text was rendered split
across the tool boundary — a word could be cut in half, e.g. the part
before the tool call ending mid-word and the remainder appearing after
the tool card.

Root cause: the agent bridge (`hermes_bridge.py`) accumulated streamed
text in `RunRecord.deltas` and tool/lifecycle events in
`RunRecord.events` as two parallel lists with no relative ordering. On
poll, the aggregated text (`"".join(deltas)`) and the events were
delivered separately, and the Node consumer (`handle-bridge-run.ts`)
processed all `chunk.events` (including `tool.started`) before the
aggregated `chunk.delta`. The real interleaving of text and tool calls
was therefore lost, splitting the text around the tool boundary.

Fix:
- Bridge: `stream_callback` now also appends each text chunk as an
  ordered `stream.delta` event into the same `events` list as
  tool.started/tool.completed, preserving true interleaving. `deltas`
  is still kept for the aggregated `output`/resume snapshot.
- Node: process `stream.delta` events inline within the events loop (in
  true order), and skip the aggregated `chunk.delta` when ordered
  `stream.delta` events were present for that chunk (avoids duplicate
  text). Text-delta handling was extracted into `processBridgeTextDelta`
  and reused by both paths.

Verified end-to-end: narration that calls a tool mid-sentence now
streams and persists as coherent text in the exact order produced, with
no word split across the tool boundary.

Co-authored-by: Paulo Cavallari <paulocavallari@users.noreply.github.com>
2026-05-30 11:49:50 +08:00
..
2026-05-30 11:46:32 +08:00