Files
hermes-webui/tests
webtecnica d9440e8654 fix(stream): rebuild the assistant body when a replay cursor outlives its live state
A transparent-mode SSE drop followed by a run-journal re-attach could settle a
turn with its footer (duration / model / TTFT / Done) painted over a blank
message body. The cached INFLIGHT entry kept `lastRunJournalSeq` (206 in the
report) while its live assistant projection was gone; re-attach passed that
cursor to the server as `after_seq`, so every journal event that rebuilds the
message body was skipped and only the tail came back. A manual reload - a
zero-floor replay - restored the message, which is what proves the server-side
journal was complete the whole time.

- `_inflightCanSeedJournalReplay()`: only recoverable live output (assistant
  content/reasoning, `lastAssistantText`/`lastReasoningText`, live DOM, tools,
  burst anchors, a populated anchor scene) authorises a nonzero replay floor.
- `_runJournalReplayFloorForInflight()` / `_runJournalReplayEventIdForInflight()`
  gate BOTH halves of the cursor. The server reads `after_event_id` before
  `after_seq`, so zeroing the seq alone would still resume at the stale event id
  and skip the same range.
- `_normalizeInflightReplayCursorForReattach()` re-validates the selected
  recovery object immediately before reattach (both `loadSession` reattach
  paths), so a cursor that outlived its projection cannot reach the wire.

`_inflightHasVisibleLiveState()` keeps its keep-vs-discard role: a bare user row
has to stay visible across a mid-turn reload until pending/live reconciliation
runs, so replay authority lives in the floor predicate rather than overloading
that contract.

Fixes #7640
2026-09-19 15:27:17 -03:00
..