mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-04-28 11:41:04 +00:00
* refactor(cli): replace slash command whitelist with capability-based filtering (Phase 1)
## Summary
Replace the hardcoded ALLOWED_BUILTIN_COMMANDS_NON_INTERACTIVE whitelist with a
unified, capability-based command metadata model. This is Phase 1 of the slash
command architecture refactor described in docs/design/slash-command/.
## Key changes
### New types (types.ts)
- Add ExecutionMode ('interactive' | 'non_interactive' | 'acp')
- Add CommandSource ('builtin-command' | 'bundled-skill' | 'skill-dir-command' |
'plugin-command' | 'mcp-prompt')
- Add CommandType ('prompt' | 'local' | 'local-jsx')
- Extend SlashCommand interface with: source, sourceLabel, commandType,
supportedModes, userInvocable, modelInvocable, argumentHint, whenToUse,
examples (all optional, backward-compatible)
### New module (commandUtils.ts + commandUtils.test.ts)
- getEffectiveSupportedModes(): 3-priority inference
(explicit supportedModes > commandType > CommandKind fallback)
- filterCommandsForMode(): replaces filterCommandsForNonInteractive()
- 18 unit tests
### Whitelist removal (nonInteractiveCliCommands.ts)
- Remove ALLOWED_BUILTIN_COMMANDS_NON_INTERACTIVE constant
- Remove filterCommandsForNonInteractive() function
- Replace with CommandService.getCommandsForMode(mode)
### CommandService enhancements (CommandService.ts)
- Add getCommandsForMode(mode: ExecutionMode): filters by mode, excludes hidden
- Add getModelInvocableCommands(): reserved for Phase 3 model tool-call use
### Built-in command annotations (41 files)
Annotate every built-in command with commandType:
- commandType='local' + supportedModes all-modes: btw, bug, compress, context,
init, summary (replaces the 6-command whitelist)
- commandType='local' interactive-only: export, memory, plan, insight
- commandType='local-jsx' interactive-only: all remaining ~31 commands
### Loader metadata injection (4 files)
Each loader stamps source/sourceLabel/commandType/modelInvocable on every
command it emits:
- BuiltinCommandLoader: source='builtin-command', modelInvocable=false
- BundledSkillLoader: source='bundled-skill', commandType='prompt',
modelInvocable=true
- command-factory (FileCommandLoader): source per extension/user origin,
commandType='prompt', modelInvocable=!extensionName
- McpPromptLoader: source='mcp-prompt', commandType='prompt', modelInvocable=true
### Bug fix
MCP_PROMPT commands were incorrectly excluded from non-interactive/ACP modes by
the old whitelist logic. commandType='prompt' now correctly allows them in all
modes.
### Session.ts / nonInteractiveHelpers.ts
- ACP session calls getAvailableCommands with explicit 'acp' mode
- Remove allowedBuiltinCommandNames parameter from buildSystemMessage() —
capability filtering is now self-contained in CommandService
* fix test ci
* fix memory command
* fix: pass 'non_interactive' mode explicitly to getAvailableCommands
- Fix critical bug in nonInteractiveHelpers.ts: loadSlashCommandNames was
calling getAvailableCommands without specifying mode, causing it to default
to 'acp' instead of 'non_interactive'. Commands with supportedModes that
include 'non_interactive' but not 'acp' would be silently excluded.
- Apply the same fix in systemController.ts for the same reason.
- Update test mock to delegate filtering to production filterCommandsForMode()
instead of duplicating the logic inline, preventing divergence.
Fixes review comments by wenshao and tanzhenxin on PR #3283.
* fix: resolve TypeScript type error in nonInteractiveHelpers.test.ts
* fix test ci
54 lines
1.4 KiB
TypeScript
54 lines
1.4 KiB
TypeScript
/**
|
|
* @license
|
|
* Copyright 2025 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
import type { MessageActionReturn, SlashCommand } from './types.js';
|
|
import { CommandKind } from './types.js';
|
|
import { terminalSetup } from '../utils/terminalSetup.js';
|
|
import { t } from '../../i18n/index.js';
|
|
|
|
/**
|
|
* Command to configure terminal keybindings for multiline input support.
|
|
*
|
|
* This command automatically detects and configures VS Code, Cursor, and Windsurf
|
|
* to support Shift+Enter and Ctrl+Enter for multiline input.
|
|
*/
|
|
export const terminalSetupCommand: SlashCommand = {
|
|
name: 'terminal-setup',
|
|
get description() {
|
|
return t(
|
|
'Configure terminal keybindings for multiline input (VS Code, Cursor, Windsurf, Trae)',
|
|
);
|
|
},
|
|
kind: CommandKind.BUILT_IN,
|
|
commandType: 'local-jsx',
|
|
|
|
action: async (): Promise<MessageActionReturn> => {
|
|
try {
|
|
const result = await terminalSetup();
|
|
|
|
let content = result.message;
|
|
if (result.requiresRestart) {
|
|
content +=
|
|
'\n\n' +
|
|
t('Please restart your terminal for the changes to take effect.');
|
|
}
|
|
|
|
return {
|
|
type: 'message',
|
|
content,
|
|
messageType: result.success ? 'info' : 'error',
|
|
};
|
|
} catch (error) {
|
|
return {
|
|
type: 'message',
|
|
content: t('Failed to configure terminal: {{error}}', {
|
|
error: String(error),
|
|
}),
|
|
messageType: 'error',
|
|
};
|
|
}
|
|
},
|
|
};
|