Skip to content

fix(desktop): stop background session messages bleeding into the active transcript#37975

Merged
kshitijk4poor merged 1 commit into
NousResearch:mainfrom
kshitijk4poor:fix/desktop-session-view-bleed
Jun 3, 2026
Merged

fix(desktop): stop background session messages bleeding into the active transcript#37975
kshitijk4poor merged 1 commit into
NousResearch:mainfrom
kshitijk4poor:fix/desktop-session-view-bleed

Conversation

@kshitijk4poor

Copy link
Copy Markdown
Collaborator

Summary

On the desktop app, a failed/queued turn from one session renders on top of every other session you toggle to. The screenshot symptom is stale user bubbles (e.g. the code is in the repo itself in: /apps, test) each followed by a red "session busy" error, persisting into unrelated sessions.

Root cause

The messages are real, correctly-keyed transcript entries belonging to one session (verified against Local Storage + state.db — the data layer is not bleeding). The bleed is in the render path.

A still-busy background session (the one the user toggled away from) keeps emitting updateSessionState() heartbeats — stream deltas, and especially the session busy prompt.submit rejection errors produced when a queued turn auto-drains while the backend is still busy. Each updateSessionState() called syncSessionStateToView() unconditionally, staging that background session's messages into the shared $messages view.

flushPendingViewState() does guard against the wrong session reaching the view — but only one requestAnimationFrame is scheduled per frame and pendingViewStateRef holds just the latest writer. So within a single frame a background write can overwrite an already-pending foreground write, and the stale background transcript renders on top of whatever session the user switched to.

Fix

Guard at the staging site (syncSessionStateToView): a session may only stage into $messages when it is the currently-active session. Background sessions still update their own cache entry (sessionStateByRuntimeIdRef); they just never touch the view. This mirrors the existing flushPendingViewState active-id check, moved earlier so a background write can't displace a pending foreground write within the same RAF window.

Pure render fix — no behavior change to queuing, interrupt/Stop (#37948), or drain. The active session's optimistic seeds and updates still reach the view because activeSessionIdRef.current is set to the runtime id before its updateSessionState calls run (create/resume paths).

Test plan

  • tsc -b clean.
  • Manual repro: session A busy + a queued turn that errors with session busy → toggle to session B → before: A's rows render over B; after: B shows only its own transcript, A's rows stay in A.

Local vitest jsdom suite is environment-broken in this checkout (window.localStorage.clear is not a function on node 25, fails identically on clean main), so relying on CI for the suite.

…ve transcript

A still-busy background session (one the user toggled away from) keeps
emitting updateSessionState() heartbeats — stream deltas, and especially
the 'session busy' prompt-rejection errors from auto-drained queued turns.
Each call invoked syncSessionStateToView() unconditionally, staging that
session's messages into the shared $messages view.

flushPendingViewState() guarded against the wrong session reaching the
view, but only one requestAnimationFrame is scheduled per frame and
pendingViewStateRef holds just the latest writer. So within a single
frame a background write could overwrite an already-pending foreground
write, and the stale background transcript (e.g. the red 'session busy'
rows) would render on top of whatever session the user switched to —
appearing to 'bleed' into every session.

Guard at the staging site: a session may only stage into the view when
it is the currently-active session. Background sessions still update
their own cache entry; they just never touch $messages. Pure render
fix, no behavior change to queuing, interrupt, or drain.
@alt-glitch alt-glitch added type/bug Something isn't working P3 Low — cosmetic, nice to have labels Jun 3, 2026
@kshitijk4poor kshitijk4poor merged commit f019a9c into NousResearch:main Jun 3, 2026
27 of 28 checks passed
davidgut1982 pushed a commit to davidgut1982/hermes-agent that referenced this pull request Jun 5, 2026
…session-view-bleed

fix(desktop): stop background session messages bleeding into the active transcript
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

P3 Low — cosmetic, nice to have type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants