Skip to content

perf(staged): stop chat pane poll from re-rendering the whole transcript - #895

Merged
matt2e merged 1 commit into
mainfrom
note-slowdown
Jul 27, 2026
Merged

perf(staged): stop chat pane poll from re-rendering the whole transcript#895
matt2e merged 1 commit into
mainfrom
note-slowdown

Conversation

@matt2e

@matt2e matt2e commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Summary

While a session runs, SessionChatPane polls 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

  • Incremental metadata fetch: new 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.
  • Identity-preserving poll: 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.
  • Stable transcript groups: stabilizeAcpTranscriptGroups reuses group/item identities across rebuilds so the keyed {#each} only re-evaluates groups that changed.
  • Lazy tool-card formatting: collapsed tool cards decide expandability via a cheap toolHasDetails presence check; formatJson/toolResultText/diff formatting now runs only once a card is expanded.
  • Caching: 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.

Testing

  • New unit tests in acpTranscript.test.ts covering group stabilization, identity reuse, and toolHasDetails.
  • New Rust store tests for the incremental metadata query (cursor filtering, refetch ids, ordering).

🤖 Generated with Claude Code

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>
@matt2e
matt2e requested review from baxen and wesbillman as code owners July 27, 2026 09:05
@matt2e
matt2e merged commit ce91a0e into main Jul 27, 2026
4 checks passed
@matt2e
matt2e deleted the note-slowdown branch July 27, 2026 10:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant