Skip to content

perf(web): typing in the composer no longer re-parses the whole draft - #29113

Closed
Yuruzuu wants to merge 1 commit into
pingdotgg:mainfrom
Yuruzuu:perf/editor-initial-document-parse
Closed

Yuruzuu wants to merge 1 commit into
pingdotgg:mainfrom
Yuruzuu:perf/editor-initial-document-parse

Conversation

@Yuruzuu

@Yuruzuu Yuruzuu commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

Problem

Each keystroke in the web composer re-parses the whole draft to build an initial document. The mounted editor never uses that document. The wasted work grows with draft length and token count.

Change

ComposerPromptEditorTiptap passed buildDocJson(value, ...) as the useEditor content option on every changed value. Tiptap only reads content when it creates an instance. The parse now runs in onBeforeCreate, which useEditor forwards to the latest render's options, so a recreated editor still gets current text, mode and skills.

The controlled setContent path, skill reconciliation, selection, focus, history and editor keys are unchanged. Desktop gets this through web. Mobile has its own editor, and providers are not involved. I added no cache and did not freeze first-render content.

Related: #22437 and #28071 also edit ComposerPromptEditorTiptap.tsx, so whichever lands second may need a rebase.

Scope and approval

This qualifies for the small, focused fix exception in CONTRIBUTING.md. It changes no feature, product default, or contract.

Verification

vp test run on the input and citation browser tests plus composer-rich-text-doc.test.ts: 273 passed. vp run check:changed passed.

parses the draft only when an editor is created, using the latest text and skills fails without the fix. Mount plus three typed changes made 4 buildDocJson calls before and 1 after. Recreating the editor through a hidden Activity adds one parse with the latest text and skills. A frozen-content variant fails this test.

Benchmark: mounted composer in Vitest Chromium with a dev React build and a controlled parent. It times one inserted character through act and commit. 10 alternating rounds per side. Values are the median of per-round means, with the range across rounds. The script is not committed.

Draft Before (ms/edit) After (ms/edit) Edits per round
11 chars 0.144 (0.132–0.166) 0.138 (0.123–0.157) 300
479 chars 0.169 (0.157–0.189) 0.149 (0.134–0.206) 300
19,389 chars, 250 plain lines 1.498 (1.345–1.749) 0.987 (0.936–1.283) 100
26,999 chars, 250 mixed-token lines 138.7 (132.7–144.6) 92.3 (89.5–95.1) 60

The 11- and 479-character ranges overlap, so treat them as ties. Mount time also ties: median 3.00 vs 3.05 ms at 11 chars, 290 vs 274 ms at 26,999 chars, with overlapping ranges. The large mixed draft still costs about 92 ms per edit, and this change does not address that.

An adversarial review found no regression, based on the Tiptap source and the focused test. It did not cover mounted StrictMode, initial update emissions, or undo history by test, and neither did I. I did not measure production-build keystroke latency, or run this in a real client.

Related: #29008 changes inline skill lookups in packages/shared. It does not overlap.

Adversarial review by GPT-6.1 Terra via Codex in T3 Code.
Made with Claude Opus 5.5 via Claude Code in T3 Code.

🤖 Generated with Claude Code

The mounted editor ignores the content option, yet each controlled value
change rebuilt it with buildDocJson. Build it in onBeforeCreate, which runs
once per editor instance with the latest text and skills.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:XS 0-9 changed lines (additions + deletions). labels Nov 2, 2026
@macroscopeapp

macroscopeapp Bot commented Nov 2, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved at 4c53069

Macroscope's review found this PR approvable — Draft parsing moves to editor creation instead of repeating during composer renders. The change is limited to client-side initialization, with existing controlled draft updates unchanged.

You can add or adjust custom eligibility rules. Learn more.

@coderabbitai

coderabbitai Bot commented Nov 2, 2026

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review.

Recent review info
Run configuration
Commits

Reviewing files that changed from the base of the PR and between c65f8d5 and 4c53069.

Files selected for processing: 2
  • apps/web/src/components/ComposerPromptEditorTiptap.input.browser.test.tsx
  • apps/web/src/components/ComposerPromptEditorTiptap.tsx

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 0 remain after this review.

Walkthrough

The editor now builds its initial document in onBeforeCreate. A browser test checks that document construction runs on editor creation and replacement, but not during text edits.

Changes: Composer editor

Layer / File(s) Summary
Initialize editor document content
apps/web/src/components/ComposerPromptEditorTiptap.tsx, apps/web/src/components/ComposerPromptEditorTiptap.input.browser.test.tsx
The editor builds its initial document in onBeforeCreate using the existing inputs. The browser test checks that buildDocJson runs at creation and replacement, not during text edits, and receives updated text and skills.

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Refactor

Suggested reviewers: tris203, juliusmarminge

Merge Risk: Minimal · up to 4c530

The editor initialization change is consistent with the Tiptap lifecycle and no actionable merge risk remains.

Pre-merge checks: Passed 4
Check name Status Explanation
Title check Passed The title names the main change: the composer no longer re-parses the whole draft on each keystroke. The PR moves buildDocJson from the useEditor content option to onBeforeCreate, which matches the ti…
Description check Passed The description follows the template sections: Problem, Change, Scope and approval, and Verification. The Problem section states the wasted parse work. The Change section explains the move to onBefore…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Title check

Explanation

The title names the main change: the composer no longer re-parses the whole draft on each keystroke. The PR moves buildDocJson from the useEditor content option to onBeforeCreate, which matches the title. The title follows the conventional commit format and is specific.

Full details: Description check

Explanation

The description follows the template sections: Problem, Change, Scope and approval, and Verification. The Problem section states the wasted parse work. The Change section explains the move to onBeforeCreate and why the mounted editor ignores content. The Scope section cites the small, focused fix exception and explains why it qualifies. The Verification section gives focused test results, a before/after benchmark table, and stated limits, including what was not checked. The description also links related PRs and notes the adversarial review and tooling. The template's optional closing line about the agent model is present. The description is thorough and mostly complete.

Finishing Touches
Generate unit tests (beta)
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

@maria-rcks

maria-rcks commented Nov 2, 2026 •

Copy link
Copy Markdown
Collaborator

Note

Written by gpt-6.1-sol on behalf of Maria

Verified in a real dev environment

Verified as-is at 4c53069d533abc6319b0069190ad019befd2a75e on Linux, using repo Playwright and /usr/bin/google-chrome against real background dev servers. Main was 60aec28a9c6f in a separate worktree; its server was stopped before starting the PR. Projects and threads were created through the app, pointing at a real git repository. No mocks or seeded conversations.

  • Reproduced on main: typing typing verification caused 19 buildDocJson calls. The same 19 characters on this head caused zero calls in the mounted composer. Counts came from a non-pausing Chrome debugger breakpoint in the unchanged running module; screenshot banners display the observed counts. This proves removal of redundant parsing, not a latency percentage.
  • Codex gpt-6.1-sol turns completed through the web composer, server and local provider proxy on both revisions. A second PR turn returned editor send verified. and cleared the composer.
  • Undo removed the typed suffix; redo restored it. Reload restored the draft. A 22,293-character, 250-line mixed-markdown draft, including inline code and mentions, serialized exactly after reload. Typing its suffix caused zero draft parses.
  • Blacksmith: vp test run apps/web/src/components/ComposerPromptEditorTiptap.input.browser.test.tsx apps/web/src/composer-rich-text-doc.test.ts passed, 272 tests. Chromium was installed on the worker after the first launch reported it missing. All 31 reported PR checks passed. No code changes were needed.

main: 19 characters cause 19 draft parses

pr: the same 19 characters cause zero draft parses

typing, undo, redo, and a real codex send

The recording is embedded as an animated GIF because GitHub filters externally hosted video. The MP4 was played through and seeking checked in Chrome.

Not verified

Native Electron, iOS and Android clients; macOS/Windows; remote/relay/tunnel connections; other providers; production-build keystroke latency. This VM exercised the Linux web client with Codex. Mobile uses a separate editor. Skill reconciliation and editor recreation were covered by the existing browser test, not a live installed-skill scenario.

@Yuruzuu

Yuruzuu commented Nov 3, 2026

Copy link
Copy Markdown
Contributor Author

Closing this myself. After measuring, the saving is too small for users to notice, so it isn't worth a reviewer's time. Thanks to anyone who looked at it.

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

Labels

size:XS 0-9 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants