fix(vscode-companion): fill slash commands into input on Enter instead of auto-submitting#3618
Conversation
643d982 to
716c082
Compare
…d of auto-submitting (#1990) Previously, selecting any slash command from the VSCode completion menu via Enter would immediately send it to the agent, giving users no chance to append arguments. This was especially problematic for skills and custom commands that accept parameters. Changes: - Commands that accept input (skills, commands with completion) now fill into the input box on Enter, letting users type arguments before submitting - No-arg built-in commands (/clear, /doctor, etc.) still auto-submit on Enter for convenience - Tab always fills without submitting (unchanged) - Client-side commands (/auth, /account, /model) still execute immediately (unchanged) The distinction is driven by the ACP `input` field: Session.ts now sets `input: { hint }` for commands that accept arguments (non-BUILT_IN kind or commands with completion functions), and `input: null` for the rest. Also fixes: - /auth + /login unified handling in useMessageSubmit.ts - authCancelled message now clears waiting state (prevents input lockup) - Stale /login comment updated to /auth in WebViewProvider.ts Resolves #1990
716c082 to
5eb5a17
Compare
Code Coverage Summary
CLI Package - Full Text ReportCore Package - Full Text ReportFor detailed HTML reports, please see the 'coverage-reports-22.x-ubuntu-latest' artifact from the main CI run. |
wenshao
left a comment
There was a problem hiding this comment.
No issues found. LGTM! ✅ — gpt-5.5 via Qwen Code /review
|
Hi @yiliang114, this PR has been approved but currently has merge conflicts with the base branch. Could you rebase and resolve the conflicts so we can get it merged? Thanks! |
Merge origin/main into the PR branch, resolving conflicts: - Session.ts: keep PR's input logic (kind+completion based) over main's argumentHint-only logic - Session.test.ts: combine both sides (kind from PR + argumentHint from main), update assertion to match PR's input resolution rules
| description: cmd.description, | ||
| input: cmd.argumentHint ? { hint: cmd.argumentHint } : null, | ||
| input: | ||
| cmd.kind !== CommandKind.BUILT_IN || cmd.completion != null |
There was a problem hiding this comment.
[Critical] This now marks every built-in command without a completion function as input: null, so the webview auto-submits it on Enter. Some ACP-supported built-ins still accept meaningful arguments without exposing completion—for example /bug uses its args as the issue title and /context detail enables the detailed view. After this change, selecting those commands from the completion menu sends only /<command> immediately, preventing users from filling the arguments that the command supports. Please derive this from explicit input metadata (or preserve argumentHint/subcommand-aware input support for these built-ins) instead of defaulting all built-ins without completion to no-input.
— gpt-5.5 via Qwen Code /review
…ust kind+completion The previous logic only checked `kind !== BUILT_IN || completion != null` to decide whether a command accepts arguments. This caused built-in commands like /bug, /context, /export, /language, and /stats to be marked as no-input (auto-submit on Enter), even though they accept meaningful arguments or have subcommands. Now a command is considered to accept input when any of: - it is not a BUILT_IN command - it has a completion function - it declares an argumentHint - it has subCommands Also adds argumentHint to /bug since it accepts a description but has neither completion nor subCommands.
wenshao
left a comment
There was a problem hiding this comment.
Two additional critical findings from the review could not be mapped to current diff lines via GitHub's review API, so they are included here instead of inline:
packages/cli/src/utils/modelConfigUtils.ts:resolveCliGenerationConfig()no longer includesOPENAI_MODEL/QWEN_MODELwhen selecting the matchingmodelProvider; restore the OpenAI precedenceargv.model || env['OPENAI_MODEL'] || env['QWEN_MODEL'] || settings.model?.name.packages/core/src/skills/skill-manager.test.ts: the new genericargument-hint:YAML mock branch returnsname: test-skillbefore recognizingname: review, causing bundled review skill tests to fail.
— gpt-5.5 via Qwen Code /review
| closeCompletion(); | ||
| return; | ||
| } | ||
| // Command accepts input — fall through to fill the input box. |
There was a problem hiding this comment.
[Critical] Falling through here uses the generic insertion path, which reads inputElement.textContent directly. If the empty editor contains the U+200B height placeholder, filling a slash command can preserve that hidden character and produce text like \u200B/commit . shouldSendMessage strips the placeholder only for the emptiness check, but the actual sendMessage payload still uses the raw text, so downstream slash-command handling may not recognize the command.
Please normalize the text used for completion insertion, for example by stripping U+200B before computing textBeforeCursor/newText, and ensure the value passed to setInputText is placeholder-free. Be careful to adjust cursor offsets after normalization.
— gpt-5.5 via Qwen Code /review
The contentEditable input uses U+200B as a height placeholder. When selecting a completion item, the raw textContent was used directly for computing trigger position and building the new text, which could preserve the hidden character and produce text like "\u200B/commit" that downstream slash-command handling may not recognize. Now strip zero-width spaces from the text before computing cursor position and trigger offsets, and adjust the cursor for any removed characters so the final inserted text is placeholder-free.
|
Verified locally on macOS. Built from HEAD ( Tested cases:
No Two review items from the previous round are addressed:
One non-blocking note: |
…ock in App.test.tsx The test mock for @qwen-code/webui was missing the newly imported stripZeroWidthSpaces function, causing 4 test failures in CI.
…d of auto-submitting (QwenLM#3618) * fix(vscode-companion): fill slash commands into input on Enter instead of auto-submitting (QwenLM#1990) Previously, selecting any slash command from the VSCode completion menu via Enter would immediately send it to the agent, giving users no chance to append arguments. This was especially problematic for skills and custom commands that accept parameters. Changes: - Commands that accept input (skills, commands with completion) now fill into the input box on Enter, letting users type arguments before submitting - No-arg built-in commands (/clear, /doctor, etc.) still auto-submit on Enter for convenience - Tab always fills without submitting (unchanged) - Client-side commands (/auth, /account, /model) still execute immediately (unchanged) The distinction is driven by the ACP `input` field: Session.ts now sets `input: { hint }` for commands that accept arguments (non-BUILT_IN kind or commands with completion functions), and `input: null` for the rest. Also fixes: - /auth + /login unified handling in useMessageSubmit.ts - authCancelled message now clears waiting state (prevents input lockup) - Stale /login comment updated to /auth in WebViewProvider.ts Resolves QwenLM#1990 * fix(acp): derive input field from argumentHint and subCommands, not just kind+completion The previous logic only checked `kind !== BUILT_IN || completion != null` to decide whether a command accepts arguments. This caused built-in commands like /bug, /context, /export, /language, and /stats to be marked as no-input (auto-submit on Enter), even though they accept meaningful arguments or have subcommands. Now a command is considered to accept input when any of: - it is not a BUILT_IN command - it has a completion function - it declares an argumentHint - it has subCommands Also adds argumentHint to /bug since it accepts a description but has neither completion nor subCommands. * fix(vscode-companion): strip U+200B from completion insertion path The contentEditable input uses U+200B as a height placeholder. When selecting a completion item, the raw textContent was used directly for computing trigger position and building the new text, which could preserve the hidden character and produce text like "\u200B/commit" that downstream slash-command handling may not recognize. Now strip zero-width spaces from the text before computing cursor position and trigger offsets, and adjust the cursor for any removed characters so the final inserted text is placeholder-free. * fix(vscode-companion): add stripZeroWidthSpaces to @qwen-code/webui mock in App.test.tsx The test mock for @qwen-code/webui was missing the newly imported stripZeroWidthSpaces function, causing 4 test failures in CI.
TLDR
/clear,/doctor, etc.) still auto-submit.inputfield propagation fromSession.ts→ webviewApp.tsx, and theclientActionsrefactor.Screenshots / Video Demo
Dive Deeper
Protocol-level change.
Session.tsnow populates the ACPAvailableCommand.inputfield based on the command definition: commands withkind !== BUILT_INor acompletionfunction getinput: { hint }, signaling they accept arguments. Built-in commands without completion getinput: null.Webview selection logic.
App.tsxuses theinputfield to decide behavior on Enter:inputis falsy + Enter → auto-submit (no-arg commands like/clear)inputis truthy + Enter → fill into input box (skills, commands with completion)/auth,/account,/model) → immediate action viaclientActionsmap, unchangedAlso fixed:
useMessageSubmit.ts:/login→/auth+/login(legacy alias preserved)useWebViewMessages.ts: addedauthCancelledhandler to clear waiting state when auth picker is dismissedWebViewProvider.ts: stale/logincomment updated to/authReviewer Test Plan
npm run build && npm run bundle/to open the completion menu/clear): should execute immediately/commit): should fill/commitinto input, cursor at end, user can type args then press Enter/model: should open model selector immediately/export: should fill and expand subcommand completion/authmanually and press Enter: should trigger auth flowUnit tests:
npx vitest run packages/vscode-ide-companion/src/webview/ # 21 files, 106 tests — all passTesting Matrix
Testing matrix notes:
Linked issues / bugs
Resolves #1990