Skip to content

Preserve live stream output across session switches#3427

Open
t3chn0pr13st wants to merge 1 commit into
nesquena:masterfrom
t3chn0pr13st:codex/server-side-live-stream-cache-upstream-20260602124636
Open

Preserve live stream output across session switches#3427
t3chn0pr13st wants to merge 1 commit into
nesquena:masterfrom
t3chn0pr13st:codex/server-side-live-stream-cache-upstream-20260602124636

Conversation

@t3chn0pr13st
Copy link
Copy Markdown
Contributor

@t3chn0pr13st t3chn0pr13st commented Jun 2, 2026

Thinking Path

  • Hermes WebUI relies on long-running SSE chat turns where the visible transcript, live stream state, run journal, and session metadata must stay coherent.
  • The reported failure was that switching away from an active session, then returning later or opening the same session from another client, could lose already-streamed assistant text and live tool activity.
  • The WebUI had durable transcript data and an active stream id, but previously emitted in-flight events were only represented in browser-local memory.
  • The fix makes the server-side run journal snapshot/replay path available to session reloads and stream reattachments, so already-visible progress is recoverable instead of being tied to one browser tab.
  • Attachment previews are part of the same visible-turn recovery surface, so this PR also preserves uploaded attachment metadata and safe attachment serving for recovered sessions.

What Changed

  • Add server-side run journal snapshot/replay support for active streams so GET /api/session can restore already-visible assistant text and live tool cards.
  • Reattach live SSE streams with journal cursors so replayed events are cursor-safe and do not duplicate already-rendered output.
  • Preserve structured uploaded attachment metadata through optimistic UI, inflight state, backend finalization, and reload rendering.
  • Allow /api/file/raw to serve session-referenced absolute attachment paths under the WebUI attachment root, including legacy [Attached files: ...] markers.
  • Redact runtime journal snapshots in API responses before returning session data.
  • Add regression coverage for live stream recovery, tool-card restoration, attachment preview paths, and runtime journal redaction.

Why It Matters

Users often leave a long-running turn open while the agent is still working. The visible progress text and tool activity are part of the conversation timeline, not disposable local UI state. After this change, switching sessions, refreshing, or opening the same active session from another browser/device can recover the already-emitted work instead of showing only new events.

This also prevents uploaded screenshots from degrading into broken image previews after reload/session switches when the original attachment path was only available before finalization.

Contract Routing

Task type: runtime / streaming / recovery / replay / attachment recovery.

Touched areas:

  • api/routes.py
  • api/streaming.py
  • api/helpers.py
  • static/messages.js
  • static/sessions.js
  • static/ui.js
  • recovery and attachment regression tests

Relevant public docs:

  • CONTRIBUTING.md
  • docs/CONTRACTS.md
  • docs/rfcs/README.md
  • docs/rfcs/webui-run-state-consistency-contract.md

State layers affected:

  • visible transcript
  • live stream / SSE
  • run journal / replay
  • live UI scene/cache
  • uploaded attachment metadata used by recovered visible messages

Evidence used:

  • Regression tests verify session-switch recovery preserves partial assistant text and live tool cards.
  • Replay cursor tests verify reattached streams avoid duplicate or missing events.
  • Attachment path tests verify uploaded media previews remain renderable and traversal attempts are rejected.
  • Redaction tests verify runtime journal snapshot data is sanitized before API responses leave the server.

No intentional contract change is made. This PR preserves the existing run-state consistency invariant that replay/reconnect must not silently lose already-visible active-turn content.

Verification

After rebasing on upstream v0.51.230 / 2d20d336:

node --check static/messages.js
node --check static/sessions.js
node --check static/ui.js
python3 -m py_compile api/helpers.py api/routes.py api/streaming.py
uv run --with pytest pytest \
  tests/test_chat_upload_attachment_paths.py \
  tests/test_inflight_stream_reuse.py \
  tests/test_regressions.py \
  tests/test_run_journal_frontend_static.py \
  tests/test_run_journal_routes.py \
  tests/test_security_redaction.py \
  -q
rm -f uv.lock
git diff --check

Result: 159 passed, 2 skipped.

Manual checks performed locally:

  • Started long-running WebUI turns, switched away from the active session, then returned after text and tools had already streamed.
  • Opened an active session from another browser context after the run had already emitted output.
  • Verified prior assistant progress text, live tool activity, and uploaded screenshot previews remained visible after reattach/reload.

Risks / Follow-ups

  • This touches high-risk streaming and recovery paths. The change is intentionally scoped to replaying already-emitted journal state and preserving attachment metadata; it does not introduce a new runner, sidecar, framework, or build step.
  • /api/file/raw attachment fallback remains constrained to session-referenced paths under the WebUI attachment root and has traversal rejection coverage.
  • If future work moves WebUI execution behind an adapter boundary, this replay contract should be kept as an invariant for the adapter-backed path too.

Model Used

  • Provider/model/mode: OpenAI Codex GPT-5.5 xhigh
  • Notable tool use: local repository inspection, browser-based local verification, pytest/node/python checks, GitHub CLI for PR updates.

@t3chn0pr13st t3chn0pr13st force-pushed the codex/server-side-live-stream-cache-upstream-20260602124636 branch 3 times, most recently from 50f7e3c to 861a675 Compare June 2, 2026 22:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant