Skip to content

fix(desktop): oversized sessions open without crashing the renderer - #78683

Merged
OutThisLife merged 3 commits into
mainfrom
bb/55191-transcript-window
Aug 4, 2026
Merged

fix(desktop): oversized sessions open without crashing the renderer#78683
OutThisLife merged 3 commits into
mainfrom
bb/55191-transcript-window

Conversation

@OutThisLife

Copy link
Copy Markdown
Collaborator

An oversized Desktop session crash-looped the Electron renderer: the full transcript was normalized into the assistant-ui runtime repository on every store update, exhausting V8's heap inside GC. The DOM budget in thread/list.tsx already bounded what paints, but every message reached the repository first — so a session only had to be heavy, not visible, to kill the window.

The transcript now reaches assistant-ui through a window bounded by the same currency the DOM budget spends: render cost. Show earlier pages the DOM first and pulls another page from the session store when that runs out, with no ceiling — paging always terminates at the full transcript.

Supersedes #76868, which established the windowed-transcript approach and the DOM-then-store paging ladder. Both are kept here. Three things changed:

The budget is render weight, not message count. messageRenderWeight moves out of thread/list.tsx into lib/render-weight.ts and both layers share it. The comment on that function already recorded why a count is the wrong unit — counting parts underpriced a 51KB tool result as "1", which is how a 600KB transcript slipped through the old 300-part cap. Measured against a 1,175-session store, a 400-message cap disengages on 37 sessions that are heavy but short (one is 133 messages / 1.05MB, another 110 / 0.84MB) while firing on 92 long-but-light sessions that were never at risk. The reported crash shape — ~231K tokens — lands at roughly 2,260 weight units and is now windowed.

The cut can't split a branch group. useRuntimeMessageRepository records a group's fork point the first time it sees the group, so a window starting mid-group anchors the surviving branches to whatever precedes them in the window. alignToBranchGroup widens the cut backwards to the group start.

Branch persistence stays wired. setMessages is never dropped, so switchToBranch and the applyBranchVisibility writeback keep working on a windowed session rather than going quiet once a session crosses a threshold.

The 2,000-message soft max is gone with it — it was a dead end that told the user older history existed while offering no way to reach it.

Test plan

  • npm run check:test:ui — 3,380 tests pass
  • Heavy-but-short transcript windows; long-but-light one does not
  • Light messages keep 10x more of the transcript than heavy ones at the same budget
  • A cut landing inside a branchGroupId keeps the whole group or none of it
  • Repeated expands terminate at the full transcript
  • Branch groups keep their fork point through a windowed cut
  • npx tsc --noEmit, npx eslint clean on every touched file

Closes #55191

Co-authored-by: HexLab 8422520+HexLab98@users.noreply.github.com

OutThisLife and others added 3 commits August 4, 2026 11:31
…gets

messageRenderWeight moves out of thread/list.tsx into lib/render-weight.ts.
The DOM page budget already spends render cost rather than message count —
the store window added next needs the same currency, and one weight function
keeps the two layers from drifting apart.

No behavior change.
…st (#55191)

An oversized session rebuilt an unbounded runtime repository on every store
update and exhausted the renderer's V8 heap, crash-looping the window. The DOM
budget in thread/list.tsx bounds what PAINTS, but every message was still
normalized into the repository first, so a session only had to be heavy — not
visible — to kill the renderer.

selectTranscriptWindow keeps the tail that fits one render-weight page. Weight,
not message count: measured against a real 1,175-session store, a 400-message
cap disengages on 37 sessions that are heavy but short (one is 133 messages /
1.05MB) while firing on 92 long-but-light sessions that were never at risk.

The cut aligns off branch-group boundaries. useRuntimeMessageRepository records
a group's fork point the first time it sees the group, so a window starting
mid-group would re-parent the surviving branches to whatever happened to
precede them.

Co-authored-by: HexLab <8422520+HexLab98@users.noreply.github.com>
…rom the store

Show earlier spends the already-materialized DOM budget first and only asks the
session store for another page once that is exhausted, so the click stays cheap
and the store window stays as small as it can be.

Paging has no ceiling: each expand grows the window by one budget page until the
whole transcript is loaded. Branch persistence stays wired throughout —
setMessages is never dropped, so switchToBranch and applyBranchVisibility keep
working on a windowed session.

Co-authored-by: HexLab <8422520+HexLab98@users.noreply.github.com>
@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

૮ >ﻌ< ა ci review

ran on 62012a5

all good!

@alt-glitch alt-glitch added type/bug Something isn't working P3 Low — cosmetic, nice to have comp/desktop Electron desktop app (apps/desktop/*) labels Aug 4, 2026
@OutThisLife
OutThisLife merged commit b281b2c into main Aug 4, 2026
37 checks passed
@OutThisLife
OutThisLife deleted the bb/55191-transcript-window branch August 4, 2026 17:57
randlee pushed a commit to randlee/hermes-agent that referenced this pull request Aug 11, 2026
…script-window

fix(desktop): oversized sessions open without crashing the renderer
33hodl pushed a commit to 33hodl/hermes-agent that referenced this pull request Aug 12, 2026
…script-window

fix(desktop): oversized sessions open without crashing the renderer
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/desktop Electron desktop app (apps/desktop/*) 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.

Desktop (macOS): renderer crash-loops to frozen window when a conversation reaches the ~128K-token compaction threshold

2 participants