ulysses/static
Kenny Van de Maele 66fba78011
fix: live-resume chat stream on session re-entry (#2539) (#2561)
* fix: live-resume chat stream on session re-entry (#2539)

When a session was re-entered after a page refresh or in a new tab while
its agent run was still streaming, the UI showed a frozen "Generating
response..." spinner, polled stream_status until the run finished, and
then did a full reload. The live tokens were never shown.

Add resumeStream() in chat.js: it consumes GET /api/chat/resume/{id}
(which replays the run's buffer then streams live), renders reply tokens
as they arrive, and reloads the session on completion for the canonical
final render. sessions.js _checkServerStream now calls it on re-entry and
falls back to the previous spinner+poll path if it is unavailable.

* Finalize plain-text resume in place instead of reloading

On stream completion, resumeStream() called selectSession(), forcing a full
history re-fetch and a visible flicker right as the stream finished.

For plain text replies (no tool calls, sources, doc streaming, or multi-round
output) the live tokens are already rendered, so finalize in place: replace the
live bubble with a canonical single message via chatRenderer.addMessage (markdown
+ footer actions + metrics, the same renderer history uses), captured from the
streamed metrics event. No history refetch, no extra round-trip, no flicker.

Rich responses still reload, since their canonical render (tool bubbles, sources,
multi-bubble) is rebuilt from the saved DB record.

* Use a dedicated set for the resume re-attach lock; fix stale docblock

resumeStream() marked its re-attach lock in _backgroundStreams, which
checkBackgroundStream() also reads. On a second re-entry of the same session
while a resume was still live, checkBackgroundStream() mistook that entry for a
same-tab POST stream and spawned its own spinner+poll bubble. Move the lock to a
dedicated _resumingStreams set (also covered by hasActiveStream) so the two paths
no longer collide. Also update the resumeStream docblock to describe the
in-place finalize vs reload split.
2026-06-04 17:56:15 +02:00
..
fonts Odysseus v1.0 2026-05-31 23:58:26 +09:00
js fix: live-resume chat stream on session re-entry (#2539) (#2561) 2026-06-04 17:56:15 +02:00
lib Odysseus v1.0 2026-05-31 23:58:26 +09:00
app.js fix(ui): use raw data for 'Copy Chat' to avoid extra newlines (#1391) 2026-06-03 14:12:28 +09:00
index.html fix(models): stabilize proxy endpoint refresh behavior 2026-06-04 04:56:11 +01:00
landing.html feat: Add mobile hamburger navigation menu and toggle functionality 2026-06-01 15:57:01 +04:00
login.html fix(login): keep inputs >=16px on touch so iOS doesn't zoom on focus (#1632) 2026-06-03 14:23:24 +09:00
manifest.json Odysseus v1.0 2026-05-31 23:58:26 +09:00
style.css feat: Claude Agent integration + cookbook reconnect + UI polish 2026-06-04 08:27:26 +09:00
sw.js Odysseus v1.0 2026-05-31 23:58:26 +09:00