Skip to content

perf(app): virtualize session timeline rows#26949

Open
Hona wants to merge 3 commits into
anomalyco:devfrom
Hona:perf/session-timeline-virtua
Open

perf(app): virtualize session timeline rows#26949
Hona wants to merge 3 commits into
anomalyco:devfrom
Hona:perf/session-timeline-virtua

Conversation

@Hona
Copy link
Copy Markdown
Member

@Hona Hona commented May 11, 2026

Summary

  • upgrade virtua and virtualize the session timeline at timeline-row granularity instead of full turns
  • flatten loaded user/assistant messages into row keys while preserving message anchors, hash reveal, prepend loading, context tool groups, diffs, retry/thinking/error rows
  • keep existing message-page data loading for now with TODOs for upcoming cursor-paged timeline parts

Validation

  • bun typecheck (packages/app)
  • bun typecheck (packages/ui)
  • pushed hook: bun turbo typecheck
  • headed smoke: session-timeline on latest upstream/dev passed (2.3m)
  • headed smoke: session-timeline on this branch passed (1.4m)

Notes

  • This draft currently includes the BasicTool deferred default-open body work that the timeline perf depends on; if perf(ui): defer default-open tool bodies #26813 lands first, this PR should be rebased to drop the duplicate diff.
  • virtua 0.49.1 still emits a Vite JSX import-source warning from virtua/lib/solid/index.jsx during dev/smoke; smoke passes despite it.

@Hona Hona marked this pull request as ready for review May 11, 2026 23:56
@Hona Hona requested a review from adamdotdevin as a code owner May 11, 2026 23:56
Copilot AI review requested due to automatic review settings May 11, 2026 23:56
@Hona Hona added beta labels May 11, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves session timeline render performance in the app by upgrading virtua and switching the session timeline rendering model to virtualize at “timeline row” granularity (user message row, assistant part rows, thinking/retry/error rows, diff summaries, etc.) rather than rendering full turns.

Changes:

  • Upgrade virtua and refactor the session timeline to produce a flattened list of keyed TimelineRows rendered via Virtualizer.
  • Add timeline-part ID data attributes and export part-grouping utilities from @opencode-ai/ui/message-part to support row-level virtualization and anchoring.
  • Defer default-open tool body mounting in BasicTool to reduce first-paint cost.

Reviewed changes

Copilot reviewed 7 out of 8 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
packages/ui/src/components/message-part.tsx Exports part grouping helpers/types and adds timeline-part data attributes used for row virtualization/anchoring.
packages/ui/src/components/basic-tool.tsx Defers mounting heavy tool bodies (including default-open) using a global deferred mount queue.
packages/ui/package.json Exposes ./session-diff as a package export for app-side use.
packages/app/src/pages/session/use-session-hash-scroll.ts Integrates “reveal” hook so hash scrolling can work with virtualization.
packages/app/src/pages/session/message-timeline.tsx Major refactor: builds flattened timeline rows and renders them through virtua Virtualizer, including diff summaries and turn status rows.
packages/app/src/pages/session.tsx Replaces “history window” logic with a history loader that coordinates prepend + virtualization shift, and wires reveal callback into hash scrolling.
package.json Bumps virtua version to 0.49.1.
bun.lock Lockfile update for virtua@0.49.1.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +127 to 131
cancelShiftReset()
setState("shift", true)

while (true) {
await input.loadMore(id)
Comment on lines +982 to +986
part={part}
message={message}
showAssistantCopyPartID={assistantCopyPartID(row.userMessageID)}
turnDurationMs={turnDurationMs(row.userMessageID)}
defaultOpen={partDefaultOpen(part, settings.general.shellToolPartsExpanded(), settings.general.editToolPartsExpanded())}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants