Skip to content

Keep Sidekick typing responsive as chat history grows #1048

Closed

Description

@taras

Story

Typing into the Sidekick message editor stays responsive as the conversation and its displayed round results grow. A person can keep working in the same REPL session without input waiting for off-screen chat rows to be rebuilt.

The Sidekick pane already windows its content: only visible rows are mounted and drawn. The expensive row construction currently happens before that window is selected.

Measured failure

An isolated reproduction using a copy of session ff8c0643cd866de47c653b8735a304cd measured:

Test session Median edit-to-visible-write p95
Full saved session 314.9 ms 341.0 ms
Identical round journal, empty Sidekick history 10.7 ms 11.5 ms
Fresh session 8.8 ms 9.4 ms

Revision: 2b783c3a11754cb46b5e42c6d73495d4a41c19b8; Deno 2.9.7 / V8 15.0.245.2-rusty, macOS ARM64; terminal size 200×52.

These unprofiled runs type 40 individual characters through the existing mounted REPL/page support, discard the first 10 as warmup, and measure until a completed terminal-emulator write shows the accumulated text. Each measured edit produces one write averaging 88 bytes. The measurement includes the test terminal adapter/emulator; it does not measure physical keyboard or iTerm compositor latency. All runs make zero provider creations and zero agent prompts.

The saved history contains 52 round closes, a 76 MB round journal and a 4.2 MB Sidekick journal. Root round outputs contain about 1.22 million characters and 19,082 newlines; those are stored-output counts, not measured displayed-row counts. The empty-chat control establishes that round-journal size alone does not explain this typing cost.

A separate CPU-profile run reproduces roughly 320 ms median edits. About 69.5% of sampled time is within sidekickReadingRows; self time in detach accounts for 24.2%, and garbage collection for 9.2%. Inclusive percentages overlap.

Existing rendering path

At the measured revision:

  • Chat row construction precedes viewport selection: shown(sidekickReadingRows(...), ...).
  • sidekickReadingRows constructs descriptions for logical and wrapped chat rows before the visible range is selected.
  • workComposed includes associated round output in the chat and repeatedly splits, prefixes and joins its lines.
  • The wrapping cache in fitPlain reuses geometric cuts, but fitted row objects and component descriptions are still reconstructed.
  • History projection is cached while record count and selected position are unchanged. This investigation does not establish a full journal reread on each keystroke.

Contract and acceptance

  • Apply the existing window before constructing expensive chat row descriptions. Ordinary message edits construct rows in proportion to the visible range and changed editor content, rather than the entire accumulated chat/output.
  • Reuse unchanged content and wrapping information where appropriate, with bounded cache retention and correct invalidation when content or terminal width changes.
  • Preserve the complete conversation and associated round results. Scrolling, selecting historical conversations, resizing, focus, caret movement and streaming updates remain correct; no content is silently truncated or discarded.
  • Preserve component input isolation, journal formats, saved history and execution behavior. Avoid removing defensive copying globally to conceal unnecessary row construction.
  • Publish comparable before/after edit latency samples, including median and p95, for a large history and the small-history control. Confirm that improvement does not trade repeated allocation for unbounded retained memory.
  • Add a focused regression showing that increasing off-screen chat/output does not proportionally increase row-description construction on an ordinary edit. Include a negative control that fails with the old construction order and a scrolling/resize journey demonstrating that previously off-screen content remains reachable.

Verification

Use the existing mounted REPL/page and terminal test support with a fake provider. Generate representative long conversation/output content instead of committing the user's journals or a large golden layout fixture. Run the focused regression with deno task test <test-path>; retain the repository's normal delivery checks.

Local diagnostic artifacts are in /private/tmp/xmd-input-perf-dnep3w7i/: analysis.md, measure.ts, per-edit timing JSON and CPU profiles. The issue's evidence above is self-contained; these private temporary files are not a required fixture or portable reproduction. The original live session and its journals were not changed.

Related: #1001 measures large-binding inspection, #992 addresses history memory costs, and #971 owns the accepted layout. This issue owns Sidekick chat preparation cost during editing and does not depend on those broader changes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions