* feat(cli): Ctrl+B promote keybind — wire UI to PR-2's promoteAbortController (#3831 PR-3 of 3)
Final piece of the foreground → background promote feature. PR-1
(#3842) landed the `signal.reason` foundation; PR-2 (#3894) wired
`shell.ts` to detect a `{ kind: 'background' }` abort, snapshot
output, register a `BackgroundShellEntry`, and stash the promote
`AbortController` on `TrackedExecutingToolCall`. This PR exposes
the user-visible surface: pressing Ctrl+B during an in-flight
foreground shell command transfers ownership to a background task
the user can inspect via `/tasks` or stop via `task_stop`.
## Changes
- `keyBindings.ts`: new `Command.PROMOTE_SHELL_TO_BACKGROUND` bound to
`Ctrl+B`. JSDoc explains the no-shell-running no-op semantics.
- `useReactToolScheduler.ts`: project `promoteAbortController` from
the core's `ExecutingToolCall` through `TrackedExecutingToolCall`
so the React layer (AppContainer keypress handler) can find it
by callId without re-plumbing through the scheduler.
- `AppContainer.tsx`: `handleGlobalKeypress` gains a
`PROMOTE_SHELL_TO_BACKGROUND` branch that walks
`pendingToolCallsRef.current` (the ref, not the destructured
array — keeps the deps list stable so the handler isn't re-bound
on every tool-call status update), finds the executing tool call
with a defined `promoteAbortController`, calls
`.abort({ kind: 'background' })`, and returns early.
No-op when no foreground shell is executing — Ctrl+B then falls
through to the input layer's existing cursor-left binding.
- `keyboard-shortcuts.md`: documents Ctrl+B with explicit
fall-through behavior so the conflict with the prompt-area
cursor-left binding is intentional + understandable.
## Tests
- `keyMatchers.test.ts` (+1): Ctrl+B positive / bare-b + meta+b +
Ctrl+other negatives.
- `AppContainer.test.tsx` (+2):
- **Ctrl+B promotes** — pendingToolCalls includes an executing
shell with a stubbed `AbortController` + spy; firing Ctrl+B
asserts `abort({ kind: 'background' })` is called once.
- **Ctrl+B no-op** — empty `pendingToolCalls` + Ctrl+B must NOT
throw (pins the safety contract for the typing-mid-prompt
case where the input layer's own Ctrl+B should still fire).
- 37/37 keyMatchers + 58/58 AppContainer pass; tsc + ESLint clean.
## E2E (manual, PR description guidance)
The unit / integration tests cover the keybind → abort wiring and
the promote handler's downstream behavior (PR-2's tests). Real-PTY
E2E is intentionally manual since headless test infrastructure
doesn't drive a real shell child + Ctrl+B keystroke; documented in
the PR description checklist.
Closes the 3-PR sequence for #3831 (Phase D part b of #3634).
* fix(cli): #3969 review wave — broadcast comment + debug log + redundancy
5 #3969 review threads addressed:
- **AppContainer.tsx Ctrl+B handler**: documented the
KeypressContext.broadcast caveat (after `return`, the same Ctrl+B
is still dispatched to text-buffer cursor-left + DebugProfiler;
visible cursor-left side effect is cosmetic) so future readers
understand why the prompt cursor moves on a successful promote.
Added `debugLogger.debug` calls on both branches (matched callId
on success; streamingState + pendingToolCalls.length on no-op
fall-through) so "Ctrl+B doesn't work" reports are debuggable.
- **useReactToolScheduler.ts TrackedExecutingToolCall**: dropped
the redundant `pid?` and `promoteAbortController?` declarations
— both come through the `& ExecutingToolCall` intersection
unchanged. Fixed the JSDoc that wrote `{ kind: 'background',
shellId }`: callers don't generate `shellId` (it's optional on
the abort-reason union and `handlePromotedForeground` produces
it downstream). The corresponding executing branch in
`toolCallsUpdateHandler` no longer projects pid /
promoteAbortController explicitly — `...coreTc` already spreads
them; the explicit-undefined clearing in the non-executing
branch is also dropped (those fields aren't on coreTc when
status !== 'executing', so `...coreTc` doesn't carry them).
- **AppContainer.test.tsx**: replaced two `as unknown as Key`
double-casts with direct `: Key` annotations on the literal —
the object already conforms to the Key interface, double-cast
was bypassing type safety needlessly.
Tests: 37/37 keyMatchers + 58/58 AppContainer pass; tsc + ESLint
clean. No behavior change beyond the new debug log lines.
* fix(cli): #3969 wave — tool-name guard + non-shell test + defensive clear
3 #3969 review threads addressed; 1 deferred:
- AppContainer.tsx: Ctrl+B `find()` predicate now also checks
`tc.request.name === ToolNames.SHELL` before matching the executing
tool call. Defense-in-depth — today only the shell tool wires
`promoteAbortController`, but a future copy-paste / type confusion
that adds the property to a non-shell tool would otherwise let
Ctrl+B mistakenly fire `abort({kind:'background'})` on a tool
whose service has no promote-handoff handler.
- useReactToolScheduler.ts: re-added explicit `pid: undefined` and
`promoteAbortController: undefined` to the non-executing return.
Previously dropped on the assumption that `...coreTc` doesn't
carry these fields when the status isn't `executing` — true today,
but the explicit clearing is defense-in-depth against a future
core change that adds either field to a non-executing status type
(would surface as a stuck PID display or a Ctrl+B handler that
matches a no-longer-executing tool call).
- AppContainer.test.tsx: replaced the placeholder "no-op when no
pending tool calls" framing on the empty-array case (it does
exercise the `executing-status` predicate but NOT the tool-name
guard) with TWO tests:
1. existing empty-array no-throw test (renamed for clarity)
2. NEW: executing non-shell tool with a hostile-shape
`promoteAbortController` — asserts `abortSpy` is NOT called.
This is the regression test for the new tool-name guard above.
Tests: 61/61 AppContainer.test.tsx pass; tsc + ESLint clean.
Deferred to follow-up (replied + tracked):
- `debugLogger.debug` is file-only; success-path "agent unblocks +
next message says 'promoted to bg_xxx'" is the user-visible signal.
Adding a synthetic history item or stderr line for the gap between
keypress and agent message conflicts with Ink rendering and is
better as a focused UX PR.
* test(cli): pin inheritance of pid + promoteAbortController via type assertions
#3969 review: the earlier "redundant declaration" review removed the
explicit `pid?: number` and `promoteAbortController?: AbortController`
from `TrackedExecutingToolCall`, relying on the `& ExecutingToolCall`
intersection to inherit them. Current review flags the type-safety
regression: if core renames or removes either field, the React-side
build won't catch it locally — Ctrl+B handler silently breaks at
runtime.
Compromise: keep the type minimal (no re-declaration noise the prior
review flagged) but add compile-time `extends keyof ExecutingToolCall`
assertions that fail loudly + locally if either field disappears.
The assertions are evaluated at compile time and zero-cost at
runtime; the dummy `const` pins them so they aren't dead code.
61/61 AppContainer tests pass; tsc clean.
The "Compact Mode" label is more intuitive than "Verbose Mode" for users,
as it directly describes the default compact view experience. This change
inverts the boolean semantics (compactMode=false means show full output)
and exposes the setting in the /settings dialog (showInDialog: true).
- Rename ui.verboseMode → ui.compactMode with inverted default (false)
- Rename VerboseModeContext → CompactModeContext (file and exports)
- Rename TOGGLE_VERBOSE_MODE → TOGGLE_COMPACT_MODE in key bindings
- Update all consumer components with inverted logic
- Update i18n keys across 6 locales (verbose → compact)
- Update VS Code settings schema
- Add ui.compactMode documentation to settings.md
- Fix Ctrl+O description in keyboard-shortcuts.md
* feat: add Ctrl+Y shortcut to retry failed requests
- Add Ctrl+Y keyboard shortcut for retrying the last failed request
- Add isNetworkError() to detect transient network failures (ECONNREFUSED, ETIMEDOUT, etc.)
- Add DashScope 1305 error code to rate limit detection
- Add error hint \"Press Ctrl+Y to retry\" in error messages
- Support user-defined error codes for retry via config
- Add retryLastPrompt() hook in useGeminiStream
- Update keyboard shortcuts documentation
* feat: improve Ctrl+Y retry feature with tests, docs, and rate limit config
- Add comprehensive tests for Ctrl+Y retry shortcut in InputPrompt
- Add unit tests for retryLastPrompt in useGeminiStream hook
- Add detailed JSDoc comments for retryLastPrompt function and Ctrl+Y shortcut
- Extend isRateLimitError to support custom error codes via retryErrorCodes config
- Fix rate limit retry log variable reference (RATE_LIMIT_RETRY_OPTIONS → maxRateLimitRetries)
- Add Eclipse IDE files to .gitignore
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
* refactor(ui): consolidate retry countdown as inline hint in error messages
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
* feat(cli): enhance error handling with improved retry mechanism
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
- Modify ErrorMessage component to remove dim color from hint text
- Update useGeminiStream hook to improve retry countdown behavior with option to preserve or clear hints
- Adjust tests to match new error handling implementation
* feat: add Ctrl+Y shortcut to retry the last failed request
When a request errors out, the error message shows an inline hint
"(Press Ctrl+Y to retry.)" in secondary color. Pressing Ctrl+Y
re-submits the same prompt, commits the error text to history
(without the hint), and clears the hint from the UI.
- Add retryLastPrompt action wired to Ctrl+Y via keyBindings and InputPrompt
- Track last submitted prompt and error state in useGeminiStream refs
- Show retry hint inline with error text in ErrorMessage component,
wrapping naturally on narrow terminals while preserving hint color
- Expose retryLastPrompt through UIActionsContext
- Add keyboard shortcut entry in KeyboardShortcuts display
- Add i18n strings for hint and no-retry-available message
- Document Ctrl+Y in keyboard-shortcuts.md
* docs(configuration): Update model provider configuration document
* chore: remove YOLO mode code from core
* fix: prevent Ctrl+Y hint from overriding auto-retry countdown
When an auto-retry countdown is active (retryCountdownTimerRef is set),
handleErrorEvent should not overwrite it with the Ctrl+Y hint. The auto-retry
hint ("retrying in Xs...") and manual retry hint ("Press Ctrl+Y to retry.")
are mutually exclusive:
- Auto-retry errors (e.g., rate limits): show countdown hint
- Other errors: show Ctrl+Y hint
Also removed retryErrorCodes from ContentGeneratorConfig as it's not part
of the minimal Ctrl+Y feature scope.
* simplify: remove complex options from clearRetryCountdown
Revert clearRetryCountdown to simplest form without options parameter.
The function now just clears the timer and pending item without any
automatic history commit logic.
* fix: restore pendingRetryCountdownItem as separate state from pendingRetryErrorItem
Auto-retry countdown and manual retry hint are now independent:
- pendingRetryErrorItem: displays error message with optional hint
- pendingRetryCountdownItem: displays separate countdown line for auto-retry
This ensures both can be shown simultaneously without overriding each other.
* fix: restore RetryCountdownMessage rendering in HistoryItemDisplay
The retry_countdown type should be rendered as a separate message,
not inline in ErrorMessage. This allows auto-retry countdown and
manual retry hint to coexist properly.
* fix(cli): properly commit retry error item to history before clearing
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
* fix(cli): remove trailing period from retry hint translations
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Remove unnecessary period from 'Press Ctrl+Y to retry' translation strings in both en.js and zh.js locales. Also update the corresponding usage in useGeminiStream hook.
* chore(sdk-java): add Eclipse project configuration files
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Add .project configuration files for client and qwencode modules to support Eclipse IDE development environment.
* feat(cli): add retry countdown hint to error message
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
* Revert "chore(sdk-java): add Eclipse project configuration files"
This reverts commit da83b5e571.
---------
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
- Introduced a comprehensive guide on the four permission modes: Plan, Default, Auto-Edit, and YOLO, including their use cases and risk levels.
- Updated the overview and quickstart documentation for clarity and consistency.
- Removed the outdated CLI reference document and integrated relevant content into the updated documentation.
- Improved command creation examples and best practices for custom commands.
- Introduced a new documentation file for Sub Agents, detailing their purpose, benefits, configuration, and usage examples.
- Updated the overview and quickstart guides to improve clarity and remove outdated information.
- Created a comprehensive command reference document for Qwen Code, detailing slash commands, at commands, and exclamation commands for better user guidance.
- Enhanced the formatting and organization of existing documentation for improved readability and usability.