fix(desktop): oversized sessions open without crashing the renderer - #78683
Merged
Conversation
…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>
8 tasks
Contributor
૮ >ﻌ< ა ci reviewran on 62012a5 all good! |
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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.tsxalready 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.
messageRenderWeightmoves out ofthread/list.tsxintolib/render-weight.tsand 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.
useRuntimeMessageRepositoryrecords 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.alignToBranchGroupwidens the cut backwards to the group start.Branch persistence stays wired.
setMessagesis never dropped, soswitchToBranchand theapplyBranchVisibilitywriteback 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 passbranchGroupIdkeeps the whole group or none of itnpx tsc --noEmit,npx eslintclean on every touched fileCloses #55191
Co-authored-by: HexLab 8422520+HexLab98@users.noreply.github.com