Add "(--fast for suggestion model)" to the /model command description
so users can discover the feature from the command list, since --fast
completion no longer appears on empty input.
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Compact mode confirmation dialog uses ProceedAlways for "Allow always"
option, but persistPermissionOutcome() only handled ProceedAlwaysProject
and ProceedAlwaysUser, causing the permission to never be saved.
Now ProceedAlways is treated as project scope (same as ProceedAlwaysProject).
Replace vague "background tasks" with specific "prompt suggestions and speculative
execution" in the --fast flag description across all i18n locales, docs, and VS Code
schema. Update example model name from qwen3.5-flash to qwen3-coder-flash. Also fix
completion logic to require a non-empty partial arg before suggesting --fast, preventing
Tab+Enter from accidentally entering fast model mode.
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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
PR #2943 fixed headers in buildHeaders() but the login flow in
waitForLogin() still used a hardcoded incomplete header object.
Reuse the shared buildHeaders() so all endpoints send consistent
iLink-App-Id and iLink-App-ClientVersion headers.
Also wrap channel.connect() in startSingle() with a try/catch so
configuration errors print a clean message instead of dumping the
yargs help text and a stack trace.
Add !key.shift guard to the Tab key handler for prompt suggestion
acceptance, so Shift+Tab only toggles approval mode without inserting
the placeholder text into the input.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Cover config validation, command execution with exec options, stdin JSON
payload, stale generation rejection, debouncing, config removal, cleanup
on unmount, EPIPE handling, command hot-reload, all state change triggers
(token count, model, branch, vim toggle, file lines), and process management.
The previous commit reverted the code to use the original i18n key
but the locale files still had the renamed key, causing translations
to not resolve.
* feat(plan): add "Yes, restore previous mode" option when exiting plan mode
When exiting plan mode, users previously had no way to restore their
original approval mode (e.g. YOLO). Add a new default option that
restores the pre-plan approval mode, with a dynamic label showing
which mode will be restored.
Closes#3002
* test: add fallback test for RestorePrevious when no prePlanMode recorded
* fix: handle RestorePrevious in telemetry and ACP mode notification
- Add RestorePrevious to telemetry decision mapping as ACCEPT
- Fix sendCurrentModeUpdateNotification to read actual mode for
RestorePrevious instead of defaulting to 'default'
* test: add plan confirmation tests for RestorePrevious in permissionUtils
* fix(permissions): match env-prefixed shell commands
Fixes#2846
* fix(core): improve shell command parsing for env vars and multiline commands
- Add dotAll flag to matchesCommandPattern for matching commands with embedded newlines
- Support newline operators in SHELL_OPERATORS for splitCompoundCommand
- Refactor getCommandRoot to skip leading VAR=value assignments
- Add test coverage for multiline commands and env var prefixed commands
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
* fix(permissions): tighten shell command parsing
Handle env-prefixed commands and quoted Windows paths consistently.
Keep newline splitting heredoc-aware and avoid false heredoc detection in comments or arithmetic expressions.
* refactor(permissions): simplify fix by reverting splitCompoundCommand rewrite
Remove ~350 lines of heredoc/comment/arithmetic parsing from
splitCompoundCommand that were not needed to fix#2846. Revert to
the original main version, keeping only the core env-var stripping
logic in matchesCommandPattern and getCommandRoot.
This addresses both reviewer concerns:
- heredoc breakage: no longer an issue since splitCompoundCommand is unchanged
- Windows quoted paths: handled correctly by shell-quote parse in getCommandRoot
---------
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
* fix: serialize subagent confirmation focus to prevent concurrent input conflicts
When multiple subagents run in parallel and each triggers a confirmation
prompt, all prompts previously received keyboard focus simultaneously,
causing a single keypress to be dispatched to every active confirmation.
This change introduces a first-come-first-served focus lock mechanism:
- Track subagents with pending confirmations via a type guard
- Use a useRef-based lock so only one confirmation is focused at a time
- Automatically promote focus to the next pending subagent on resolution
- Show a waiting indicator on non-focused confirmations
Fixes#2929
* fix(cli): use dedicated prop for subagent approval waiting state
---------
Co-authored-by: 思晗 <housihan.hsh@alibaba-inc.com>
- Move openDiff/confirmation handling from edit.ts and write-file.ts into
CoreToolScheduler.openIdeDiffIfEnabled(), called after permission hooks
- Use structuredClone in buildInvocation to prevent params mutation leaking
to LLM history (fixes#2709 token waste)
- Use confirmationDetails as single data source for IDE diff content,
only rely on ModifyContext.createUpdatedParams() for parameter transform
- Skip inline modify when IDE content unchanged, preserving original tool
params for multi-edit-on-same-file scenarios (mitigates #2702)
- Remove ideConfirmation field from ToolEditConfirmationDetails
- Remove dead resolveIdeDiffForOutcome from ACP Session.ts
- Fix memory tool scope fallback in createUpdatedParams
Closes#2709Closes#2673
* test: add tests for confirmation-bus, prompt-registry, and cli/core modules
Add 42 new tests covering previously untested core modules:
- MessageBus: publish, subscribe/unsubscribe, request-response pattern (13 tests)
- PromptRegistry: register, dedup, query by server, clear, remove (11 tests)
- performInitialAuth: success, failure, no authType cases (3 tests)
- validateTheme: found, not found, no config cases (4 tests)
- initializeApp: i18n, auth, theme, IDE mode, auth dialog logic (11 tests)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: improve test quality - copyright headers, env safety, cleanup
- Fix copyright headers from Google LLC to Qwen Code in all 5 test files
- Use vi.stubEnv() instead of manual process.env mutation in initializer test
- Add removeAllListeners() cleanup in message-bus debug test
- Add void prefix to un-awaited publish() calls in message-bus test
- Verify invoke reference preserved after prompt rename in prompt-registry test
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test(message-bus): add AbortSignal coverage for request()
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
The /context command was missing the subcommand autocomplete feature
that other commands like /stats have. Now users can type '/context '
and see 'detail' as a suggestion in the dropdown.
- Added 'detail' subCommand to contextCommand with its own description
- Subcommand delegates to main action with 'detail' arg
- Added missing translation key for full description in zh.js
- Updated commands.md documentation
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
* chore: remove outdated pr-review skill
The .qwen/skills/pr-review skill is outdated and no longer needed.
Also removes the dangling reference from terminal-capture skill.
* chore: add token-stats script to e2e-testing skill
* fix(test): remove flaky AskUserQuestionDialog Submit tab test
The "shows Submit tab for multiple questions" test fails on macOS CI
due to terminal width truncation causing "Submit answers" to render
as just "Submit".
The gradient overlay div at the bottom of the chat input was intercepting
mouse events, preventing users from dragging the scrollbar. Add
pointer-events-none to the overlay and pointer-events-auto to the inner
content to allow scrollbar interaction while preserving the gradient effect.
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
LLM was putting findings in the comments array WITHOUT line numbers,
creating orphaned PR comments. Clarified: comments array entries MUST
have a valid line. Findings without a mappable diff line go in body.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Two rules repeatedly violated by LLMs despite being documented:
1. Language matching (Chinese output on English PRs)
2. Create Review API (falling back to individual gh api comments)
Moved both to a "Critical rules" section at the very top of the
prompt, before the design philosophy. Early placement = higher
attention from the LLM.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The APPROVE path for zero findings was missing the model footer.
Added YOUR_MODEL_ID to the body.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
replaceAll('YOUR_MODEL_ID', modelId) was also replacing the instruction
"The variable YOUR_MODEL_ID is declared..." → nonsensical text.
Removed the literal reference from the instruction line.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Some models (e.g., glm-5.1) ignore the {{model}} template in code
blocks and write their own footer without the model name. Fix:
1. BundledSkillLoader prepends YOUR_MODEL_ID="glm-5.1" as a top-level
declaration at the start of the skill body — impossible to miss
2. SKILL.md references YOUR_MODEL_ID in footer instructions
3. Empty model → empty string (no "unknown" — prefer omission)
4. YOUR_MODEL_ID declaration only prepended when model is available
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(core): prevent followup suggestion input/output from appearing in tool call UI
The follow-up suggestion generation was leaking into the conversation UI
through three channels:
1. The forked query included tools in its generation config, allowing the
model to produce function calls during suggestion generation. Fixed by
setting `tools: []` in runForkedQuery's per-request config (kept in
createForkedChat for speculation which needs tools).
2. logApiResponse and logApiError recorded suggestion API events to the
chatRecordingService, causing them to appear in session JSONL files
and the WebUI. Fixed by adding isInternalPromptId() guard that skips
chatRecordingService for 'prompt_suggestion' and 'forked_query' IDs.
uiTelemetryService.addEvent() is preserved so /stats still tracks
suggestion token usage.
3. LoggingContentGenerator logged suggestion requests/responses to the
OpenAI logger and telemetry pipeline. Fixed by skipping logApiRequest,
buildOpenAIRequestForLogging, and logOpenAIInteraction for internal
prompt IDs. _logApiResponse is preserved (for /stats) but its
chatRecordingService path is filtered by fix#2.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor: deduplicate isInternalPromptId into shared export from loggers.ts
Address review feedback: extract isInternalPromptId() to a single
exported function in telemetry/loggers.ts and import it in
LoggingContentGenerator, eliminating the duplicate private method.
Also update loggingContentGenerator.test.ts mock to use importOriginal
so the real isInternalPromptId is available during tests.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor: extract isInternalPromptId to shared utils, add tests
Address maintainer review feedback:
1. Move isInternalPromptId() to packages/core/src/utils/internalPromptIds.ts
using a ReadonlySet for the ID registry. Adding new internal prompt IDs
only requires changing one file. loggers.ts re-exports for compatibility,
loggingContentGenerator.ts imports directly from utils.
2. Extract `tools: []` magic value to a frozen NO_TOOLS constant in
forkedQuery.ts.
3. Add unit tests for isInternalPromptId: prompt_suggestion → true,
forked_query → true, user_query → false, empty string → false.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: address Copilot review — docs, stream optimization, tests
1. Update forkedQuery.ts module docs to reflect that runForkedQuery
overrides tools: [] at the per-request level while createForkedChat
retains the full generationConfig for speculation callers.
2. Propagate isInternal into loggingStreamWrapper to skip response
collection and consolidation for internal prompts, avoiding
unnecessary CPU/memory overhead.
3. Add logApiResponse chatRecordingService filter tests: verify
prompt_suggestion/forked_query skip recording while normal IDs
still record.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: deep-freeze NO_TOOLS, add internal prompt guard tests
Address Copilot review round 3:
1. Deep-freeze NO_TOOLS.tools array to prevent shared mutable state
across forked query calls.
2. Add LoggingContentGenerator tests verifying that internal prompt IDs
(prompt_suggestion, forked_query) skip logApiRequest and OpenAI
interaction logging while preserving logApiResponse.
3. Add logApiError chatRecordingService filter tests matching the
existing logApiResponse coverage.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs: reconcile createForkedChat JSDoc with module header
Clarify that createForkedChat retains the full generationConfig
(including tools) for speculation callers, while runForkedQuery
strips tools at the per-request level via NO_TOOLS.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: build errors and Copilot round 4 feedback
1. Fix NO_TOOLS type: Object.freeze produces readonly array incompatible
with ToolUnion[]. Use Readonly<Pick<>> instead; spread in requestConfig
already creates a fresh mutable copy per call.
2. Fix test missing required 'model' field in ContentGeneratorConfig.
3. Track firstResponseId/firstModelVersion in loggingStreamWrapper so
_logApiResponse/_logApiError have accurate values even when full
response collection is skipped for internal prompts.
4. Strengthen OpenAI logger test assertion: assert OpenAILogger was
constructed (not guarded by if), then assert logInteraction was
not called.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: remove dead Object.keys check, add streaming internal prompt test
1. Simplify runForkedQuery: requestConfig always has tools:[] from
NO_TOOLS spread, so the Object.keys().length > 0 ternary is dead
code. Pass requestConfig directly.
2. Add generateContentStream test for internal prompt IDs to match
the existing generateContent coverage, ensuring the streaming
wrapper also skips logApiRequest and OpenAI interaction logging.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: prevent Enter accept from re-inserting suggestion into buffer
When accepting a followup suggestion via Enter, accept() queued
buffer.insert(suggestion) in a microtask that executed after
handleSubmitAndClear had already cleared the buffer, leaving the
suggestion text stuck in the input.
Add skipOnAccept option to accept() so the Enter path bypasses the
onAccept callback. Also add runForkedQuery unit tests verifying
tools: [] is passed in per-request config.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(core): add speculation to internal IDs, fix logToolCall filtering, improve suggestion prompt
- Add 'speculation' to INTERNAL_PROMPT_IDS so speculation API traffic
and tool calls are hidden from chat recordings and tool call UI
- Add isInternalPromptId check to logToolCall() for consistency with
logApiError/logApiResponse
- Improve SUGGESTION_PROMPT: prioritize assistant's last few lines and
extract actionable text from explicit tips (e.g. "Tip: type X")
- Fix garbled unicode in prompt text
- Update design docs and user docs to reflect changes
- Add test coverage for all new behavior
* fix(core): deep-freeze NO_TOOLS, add speculation to loggingContentGenerator tests
- Object.freeze NO_TOOLS and its tools array to prevent runtime mutation
- Add 'speculation' to loggingContentGenerator internal prompt ID tests
for consistency with loggers.test.ts and internalPromptIds.ts
* fix(core): fix NO_TOOLS Object.freeze type error
Use `as const` with type assertion to satisfy TypeScript while keeping
runtime immutability via Object.freeze.
* refactor(core): remove unused isInternalPromptId re-export from loggers.ts
All consumers import directly from utils/internalPromptIds.js.
The re-export was dead code with no importers.
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(ui): prevent useEffect from running every render in InputPrompt
getDirectories() returns a new array reference each call, causing the
useEffect dependency check to fail on every render. Move the call
inside the effect body and use stable dependencies [config, dirs] so
the effect only re-runs when they actually change.
* fix(ui): use serialized dep key for directory change detection
Move from [config, dirs] deps (both stable refs that miss external
changes) to a dirKey string (join of current directories). This
preserves the perf fix (no new array ref in deps) while still
detecting directory additions/removals from /add-dir etc.
* refactor(cli): remove unused dirs state from InputPrompt
The dirs parameter passed to useCommandCompletion() was never read
inside that hook, making the dirs state and sync effect in InputPrompt
dead code. Remove the parameter, the state, the effect, and all test
call-site args.
The previous version bump commit (bb4376c) only updated the root
package.json but did not run `npm run release:version` to propagate
the version and sandboxImageUri to all workspace packages.
This caused Docker sandbox integration tests to fail in CI with
"manifest unknown" because build_sandbox.js built image 0.14.1
(from packages/cli/package.json) while sandboxConfig.ts expected
image 0.14.2 (from root package.json).
Fixes: https://github.com/QwenLM/qwen-code/actions/runs/24135197272/job/70424966323
- Update architecture diagram to show status line in footer left
section instead of separate row below
- Document 1-row (default mode) and 2-row (non-default mode) layouts
- Note suppressHint behavior and truncation
- Update settings reference description
- Hide "? for shortcuts" when a custom status line is configured
(status line already occupies the top row, hint is redundant)
- Hide status line during Ctrl+C/D exit prompts to keep footer
at one row during exit flow
- Matches upstream Claude Code suppressHint + exitMessage behavior
AutoAcceptIndicator and ShellModeIndicator returned Box>Text, which
prevented the parent Text wrap="truncate" from working (ink cannot
nest Box inside Text). Change both to return plain Text elements
so the footer's truncation applies correctly on narrow terminals.
Wrap leftBottomContent in Text with wrap="truncate" so the
hints/mode row stays on a single line, matching upstream behavior.
This guarantees the footer is at most 2 rows (status line + hints).
Restructure footer to match Claude Code's layout:
- Left column: status line (top, truncated) + hints/mode (bottom)
- Both rows coexist instead of being mutually exclusive
- Status line uses wrap="truncate" to guarantee single line
- Approval mode returns to the hints row (inline, not separate row)
- Left column uses flexShrink for narrow terminals
Add flexGrow/flexShrink to left section so it takes available space
but yields to right items. Add flexShrink={0} to right section so
context usage, verbose, sandbox indicators are never compressed.
Add overflow="hidden" to left section for clean truncation.
The status line is now inlined in the footer's left section,
so horizontal padding is no longer applicable. Remove padding
from StatusLineConfig, settings schema, JSON schema, and docs.
Move status line from a dedicated row below the footer into the
footer's left section, replacing "? for shortcuts" when active.
High-priority messages (Ctrl+C/D, Esc, vim INSERT, shell mode)
still override the status line.
Move approval mode indicator to a separate row below the footer,
shown only when mode is non-default. This eliminates the empty
gap in default mode and matches upstream layout.
- Instruct agent to use "bash script.sh" pattern instead of direct
execution (agent cannot chmod +x without SHELL tool)
- Replace vague "skip optional locks" with concrete GIT_OPTIONAL_LOCKS=0
- Simplify "parent agent" framing to direct user-facing message
- Compute remaining_percentage as round(100 - used) to guarantee
used + remaining always sums to exactly 100.0
- Reject empty or whitespace-only command strings in config validation
- Add qwen3.6-plus to both China and Global/Intl regions as the first
model in the Coding Plan template (1M context, enable_thinking)
- Set qwen3.6-plus as the new default MAINLINE_CODER_MODEL
- Add image+video input modality support for qwen3.6-plus
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>