perf(staged): stop chat pane poll from re-rendering the whole transcript - #895
Merged
Conversation
While a session runs, SessionChatPane polls every 500 ms; each tick re-fetched the session's entire ACP metadata history (including raw tool inputs/outputs) and rebuilt every transcript group with fresh object identities, re-running markdown parse + sanitize, pikchr WASM renders, and raw-payload pretty-printing for the full transcript twice a second. In a WKWebView that synchronous work stalls painting, freezing the thinking spinner and composer caret in both the note dialog and the session dialog, which embed this shared pane. - Add get_session_acp_metadata_messages_since (store query, Tauri command, web dispatch arm): returns metadata rows past a cursor plus fresh copies of explicitly re-requested ids — rows for tool calls without a terminal status are mutated in place by the message writer, so the frontend re-requests those until they settle. - poll() now merges incremental metadata updates while preserving row and array identity on quiet ticks, and skips the session, queued message, and tail-message reassignment when the data is unchanged. - stabilizeAcpTranscriptGroups reuses group/item identities across rebuilds so the keyed each only re-evaluates groups that changed. - Collapsed tool cards decide expandability via a cheap toolHasDetails presence check; formatJson/toolResultText/diff formatting now runs only once a card is expanded. - renderMarkdown output is cached per content string (LRU), note indicator scans are cached per message row, and last-group checks go through a value-stable derived so streaming ticks no longer re-run splitAtNoteIndicator for every assistant message. Fixes the rhythmic UI freeze described in the branch note (chat dialogs hitch ~2x/sec while an agent runs) for both dialogs at once. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: Matt Toohey <contact@matttoohey.com>
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.
Summary
While a session runs,
SessionChatPanepolls every 500 ms; each tick re-fetched the session's entire ACP metadata history and rebuilt every transcript group with fresh object identities, re-running markdown parse + sanitize, pikchr WASM renders, and raw-payload pretty-printing for the full transcript twice a second. In a WKWebView that synchronous work stalls painting, causing the rhythmic UI freeze (~2x/sec hitches of the thinking spinner and composer caret) in both the note dialog and the session dialog, which embed this shared pane.Changes
get_session_acp_metadata_messages_since(store query, Tauri command, web dispatch arm) returns metadata rows past a cursor plus fresh copies of explicitly re-requested ids — rows for tool calls without a terminal status are mutated in place by the message writer, so the frontend re-requests those until they settle.poll()merges incremental metadata updates while preserving row and array identity on quiet ticks, and skips session/queued-message/tail-message reassignment when the data is unchanged.stabilizeAcpTranscriptGroupsreuses group/item identities across rebuilds so the keyed{#each}only re-evaluates groups that changed.toolHasDetailspresence check;formatJson/toolResultText/diff formatting now runs only once a card is expanded.renderMarkdownoutput is cached per content string (LRU), note-indicator scans are cached per message row, and last-group checks go through a value-stable derived so streaming ticks no longer re-runsplitAtNoteIndicatorfor every assistant message.Testing
acpTranscript.test.tscovering group stabilization, identity reuse, andtoolHasDetails.🤖 Generated with Claude Code