Repository navigation
perf(client-runtime): batch terminal input writes - #9456
burnmandont wants to merge 1 commit into
Conversation
ApprovabilityVerdict: Not approved Macroscope's review found this PR not approvable — Interactive terminal writes on web and mobile are rerouted through a new stateful batching, backpressure, and discard-mode RPC path, changing existing runtime behavior rather than adding an opt-in capability. The implementation is substantial and carries an unresolved high-severity edge case in the review record. Not approved because:
Adjust the Minimum Blocking Severity for this repo — including turning it Off — in Settings. You can add or adjust custom eligibility rules. Learn more. |
e6749f3 to
fb0f72a
Compare
fb0f72a to
7bab8fd
Compare
| const maxBatchChars = options.maxBatchChars ?? TERMINAL_INPUT_MAX_BATCH_CHARS; | ||
| const maxBufferedChars = options.maxBufferedChars ?? TERMINAL_INPUT_MAX_BUFFERED_CHARS; |
There was a problem hiding this comment.
🟠 High state/terminalInput.ts:56
With maxBatchChars: 0, any nonempty input enters the oversized path, sends an empty data payload, and never advances offset, so the command promise never settles. Validate that maxBatchChars is positive before scheduling chunks.
const maxBatchChars = options.maxBatchChars ?? TERMINAL_INPUT_MAX_BATCH_CHARS;
+ if (maxBatchChars <= 0) throw new RangeError("maxBatchChars must be positive");
const maxBufferedChars = options.maxBufferedChars ?? TERMINAL_INPUT_MAX_BUFFERED_CHARS;🤖 Copy this AI Prompt to have your agent fix this:
In file @packages/client-runtime/src/state/terminalInput.ts around lines 56-57:
With `maxBatchChars: 0`, any nonempty input enters the oversized path, sends an empty `data` payload, and never advances `offset`, so the command promise never settles. Validate that `maxBatchChars` is positive before scheduling chunks.
|
Note This comment is posted by Julius' dot Closing for missing prior scope approval. Interactive terminal writes now use a new buffered lane, discard response frames, and reject input at the buffer limit. Those transport and failure-behavior choices need maintainer agreement; no approval is linked or recorded here. Establish the performance problem and agree on that scope in an Ideas discussion before requesting reconsideration. |
Interactive terminal input currently sends every terminal-emulator callback through a separate unary request/response lifecycle. Rapid typing, escape sequences, and paste bursts can create many small RPCs, adding avoidable transport and bookkeeping overhead—especially for remote environments.
This adds a bounded, ordered input lane per environment/thread/terminal. Input queued in the same JavaScript task is coalesced into batches of up to 65,536 characters, batches are sent serially without waiting for response frames, and each lane rejects new input after 512 KiB is buffered. Web/Desktop and Mobile interactive terminal surfaces use the batched command; the existing direct write command remains available for one-off launch input.
Verification:
vp test run packages/client-runtime/src/state/terminalInput.test.ts— 4 passedModel: GPT-5.6 Sol
Harness: Sovereign / Codex
Note
Medium Risk
Changes how terminal input reaches remote PTYs (ordering, batching, backpressure failures, discard RPCs); mistakes could drop or reorder keystrokes under load.
Overview
Interactive terminal keystrokes and pastes no longer trigger one unary RPC per emulator callback. The PR adds
terminalEnvironment.input, which batches and serializes writes per environment/thread/terminal while sending them in discard mode so the client does not wait on response frames.Client runtime:
createTerminalInputCommandcoalesces input queued in the same microtask, splits payloads over 65 KiB (UTF-16 surrogate-safe), enforces a 512 KiB per-lane buffer withTerminalInputBackpressureErrorwhen exceeded, and chains sends on a per-terminal promise tail.requestDiscardis the new RPC helper used for these fire-and-forgetterminalWritecalls.terminalEnvironment.writestays for one-off writes (e.g. mobile launchinitialInput, chat-driven writes).UI: Web
ThreadTerminalDrawerand mobileThreadTerminalRouteScreenroute live keyboard/toolbar input throughinputinstead ofwrite.Reviewed by Cursor Bugbot for commit 7bab8fd. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Batch terminal input writes through
terminalEnvironment.inputrequestDiscardin client.ts — a unary RPC helper that fires the request in discard mode without waiting for a response frame.terminalEnvironment.inputinto terminal.ts and switches the mobile (ThreadTerminalRouteScreen.tsx) and web (ThreadTerminalDrawer.tsx) terminal writers fromwritetoinput.TerminalInputBackpressureError.writepath; failure reporting in the web drawer was already disabled and remains so.Macroscope summarized 7bab8fd.