Skip to content

perf(app): virtualize session timeline rows - #26949

Merged
Hona merged 30 commits into
anomalyco:devfrom
Hona:perf/session-timeline-virtua
May 18, 2026
Merged

Hona merged 30 commits into
anomalyco:devfrom
Hona:perf/session-timeline-virtua

Conversation

@Hona

@Hona Hona commented May 11, 2026

Copy link
Copy Markdown
Member

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

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 [email protected].

💡 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())}
…virtualiser

cleanup(app): wrap entire MessageTimeline in ScrollView
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.

3 participants