qwen-code/packages/cli/src
jinye afa7fc3855
feat(cli): add early input capture to prevent keystroke loss during startup (#3319)
* feat(cli): add early input capture to prevent keystroke loss during startup (#3224)

Start raw mode stdin listening immediately after setRawMode(true), buffer
user input during REPL initialization (200-500ms), then replay it once
KeypressProvider is mounted. Prevents keystrokes typed before the REPL
is ready from being silently dropped.

- Filter out terminal response sequences (DA, DA2, OSC, DCS, APC)
  while preserving real user input (arrow keys, function keys, etc.)
- 64KB buffer limit for safety
- Replay via setImmediate() to ensure subscribers are registered first
- Disable via QWEN_CODE_DISABLE_EARLY_CAPTURE=1
- Add benchmark-startup.sh / benchmark-startup-simple.sh for baseline
  startup time measurement

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): fix bugs and optimize early input capture

- Fix getAndClearCapturedInput resetting captured flag, preventing potential re-arm
- Fix passthrough mode replay bypassing paste marker handling in KeypressContext
- Optimize buffer storage from O(n^2) concat to chunked collection
- Optimize filterTerminalResponses to use pre-allocated Buffer instead of number[]
- Add atomic stopAndGetCapturedInput API to prevent two-step usage errors
- Remove unrelated benchmark shell scripts
- Add test for stopAndGetCapturedInput

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): fix listener leak, silent failures, and error handling in early input capture

- Register cleanup for stdin listener in gemini.tsx to prevent orphaned
  listener on any error path before UI mounts
- Add try-catch and cancellation guard to setImmediate replay in
  KeypressContext to handle component unmount and replay errors gracefully
- Stop capture immediately and warn when buffer limit is reached instead
  of silently dropping data with a debug-level log
- Capture stdin reference at registration time so removeListener always
  operates on the correct stream instance
- Add debug log when early capture is skipped due to non-TTY stdin

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): fix early input capture being lost under React StrictMode

Move stopAndGetCapturedInput() from inside KeypressProvider's useEffect
to before render() in startInteractiveUI. When DEBUG=1, React StrictMode
deliberately runs effect→cleanup→effect, causing the first mount to drain
the buffer and schedule a replay that the cleanup immediately cancels. The
second mount found an empty buffer, silently discarding startup keystrokes.

By draining once before render() and passing the bytes as a stable prop,
StrictMode remounts always read the same data and can schedule replay on
the second (stable) mount.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix: handle split ESC prefixes in early input capture

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix: conditionally flush pending startup capture bytes

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix: drop incomplete escape sequences instead of replaying as user input

When capture stops with an incomplete ESC sequence in pendingTerminalResponse
(e.g. lone \x1b or \x1b[), classifyEscapeSequence returns 'incomplete'.
Previously shouldReplayPendingAtStop used !== 'terminal' which treated
incomplete sequences as user input. Changed to === 'user' so only
definitively-user input is replayed; ambiguous sequences are safely dropped.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

---------

Co-authored-by: jinye.djy <jinye.djy@alibaba-inc.com>
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
2026-04-19 00:40:44 +08:00
..
acp-integration fix(tool-registry): add lazy factory registration with inflight concurrency dedup (#3297) 2026-04-18 10:31:50 +08:00
commands fix(channels): re-attach bridge disconnect handler after crash recovery (#2975) 2026-04-18 09:42:32 +08:00
config fix(tool-registry): add lazy factory registration with inflight concurrency dedup (#3297) 2026-04-18 10:31:50 +08:00
constants fix(cli): set qwen3.5-plus as default model for Coding Plan (#3193) 2026-04-13 17:11:50 +08:00
core test: add tests for confirmation-bus, prompt-registry, and cli/core modules (#2272) 2026-04-09 13:54:59 +08:00
dualOutput fix(cli): wait for dual output stream shutdown (#3416) 2026-04-18 18:11:19 +08:00
i18n feat(mcp): add OSC 52 copy hotkey for OAuth authorization URL (#3337) (#3393) 2026-04-18 20:22:06 +08:00
nonInteractive feat(cli): add dual-output sidecar mode for TUI (#3352) 2026-04-18 02:14:53 +08:00
patches adh/bugfix/1563 (#4822) 2025-07-25 16:39:37 +00:00
remoteInput feat(cli): add dual-output sidecar mode for TUI (#3352) 2026-04-18 02:14:53 +08:00
services feat(memory): managed auto-memory and auto-dream system (#3087) 2026-04-16 20:05:45 +08:00
test-utils feat(cli): make /btw command non-blocking with parallel execution 2026-03-20 00:25:51 +08:00
ui feat(cli): add early input capture to prevent keystroke loss during startup (#3319) 2026-04-19 00:40:44 +08:00
utils feat(cli): add early input capture to prevent keystroke loss during startup (#3319) 2026-04-19 00:40:44 +08:00
gemini.test.tsx feat(hooks): Add HTTP Hook, Function Hook and Async Hook support (#2827) 2026-04-16 10:10:33 +08:00
gemini.tsx feat(cli): add early input capture to prevent keystroke loss during startup (#3319) 2026-04-19 00:40:44 +08:00
nonInteractiveCli.test.ts feat: background subagents with headless and SDK support (#3076) 2026-04-17 18:23:06 +08:00
nonInteractiveCli.ts feat: background subagents with headless and SDK support (#3076) 2026-04-17 18:23:06 +08:00
nonInteractiveCliCommands.test.ts feat(cli): make /btw command non-blocking with parallel execution 2026-03-20 00:25:51 +08:00
nonInteractiveCliCommands.ts feat(cli/sdk): expose /context usage data in non-interactive mode and SDK API (#2916) 2026-04-14 03:28:32 +08:00
validateNonInterActiveAuth.test.ts feat(auth): discontinue Qwen OAuth free tier (2026-04-15 cutoff) (#3291) 2026-04-15 22:30:20 +08:00
validateNonInterActiveAuth.ts Merge branch 'main' into feat/debug-logging-refactor 2026-02-01 20:47:38 +08:00