Skip to content

fix(chat): stop re-rendering every answer on each custom panel keystroke (#1005) - #1121

Open
agegr wants to merge 1 commit into
mainfrom
fix/panel-keystroke-rerender
Open

agegr wants to merge 1 commit into
mainfrom
fix/panel-keystroke-rerender

Conversation

@agegr

@agegr agegr commented Oct 8, 2026

Copy link
Copy Markdown
Owner

Typing into an extension's custom panel (a pi-tui Input in a ctx.ui.custom overlay) lagged per keystroke while the composer stayed instant.

Measured with a tiny overlay extension on a scratch server and headless Chromium: the server side is fast (key sent → panel update back: 4.5 ms median); the cost was in the browser. Every key re-rendered ChatWindow, and for each grouped turn ChatWindow built fresh copies of the final message (answer part and process part) and a fresh written-files list on every render. That defeated MessageView's memo, so every visible answer re-ran its markdown pipeline (highlighting, KaTeX) per keystroke, and per streamed chunk or notice too.

  • lib/turn-views.ts (new): getFinalAnswerViews() keeps those copies per stored message in a WeakMap (stored messages are replaced, never mutated); keepWrittenFiles() returns the previous list while the turn wrote the same files.
  • components/ChatWindow.tsx uses them; docs/agents/sessions.md note.

After the fix an unchanged transcript re-renders no MessageView per key; in a dev build with a 400-message session key-to-paint went from ~71 ms to ~20 ms (answers with code and math save more).

Tests: lib/turn-views.test.mjs, a guard in components/ChatWindow.process-details.test.mjs. tsc, eslint, npm test pass.

Not done: the server still sends two panel updates per key (requestRender() and after the input handler; pi's TUI coalesces them), and keys go out as parallel requests.

Closes #1005

🤖 Generated with Claude Code

…oke (#1005)

Each key typed into an extension's custom panel round-trips to the server
in a few ms, but the render it sends back re-renders ChatWindow, and a
grouped turn handed MessageView fresh copies of its final message and a
fresh written-files list on every render. That defeated MessageView's memo,
so every visible answer ran its markdown again per keystroke (and per
streamed chunk or notice). The copies and the list are now kept per stored
message, so an unchanged transcript re-renders no MessageView: in a dev
build with a 400-message session the key-to-paint time went from ~71 ms
to ~20 ms, and real answers with code and math save far more.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
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.

Extension panel: typing lags 1-2 s while the main terminal input is instant (0.9.3)

1 participant