mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-05-05 07:10:55 +00:00
feat(vscode): expose /skills as slash command with secondary picker (#2548)
Some checks are pending
Qwen Code CI / Lint (push) Waiting to run
Qwen Code CI / Test (push) Blocked by required conditions
Qwen Code CI / Test-1 (push) Blocked by required conditions
Qwen Code CI / Test-2 (push) Blocked by required conditions
Qwen Code CI / Test-3 (push) Blocked by required conditions
Qwen Code CI / Test-4 (push) Blocked by required conditions
Qwen Code CI / Test-5 (push) Blocked by required conditions
Qwen Code CI / Test-6 (push) Blocked by required conditions
Qwen Code CI / Test-7 (push) Blocked by required conditions
Qwen Code CI / Test-8 (push) Blocked by required conditions
Qwen Code CI / Post Coverage Comment (push) Blocked by required conditions
Qwen Code CI / CodeQL (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:none (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:docker (push) Waiting to run
E2E Tests / E2E Test - macOS (push) Waiting to run
Some checks are pending
Qwen Code CI / Lint (push) Waiting to run
Qwen Code CI / Test (push) Blocked by required conditions
Qwen Code CI / Test-1 (push) Blocked by required conditions
Qwen Code CI / Test-2 (push) Blocked by required conditions
Qwen Code CI / Test-3 (push) Blocked by required conditions
Qwen Code CI / Test-4 (push) Blocked by required conditions
Qwen Code CI / Test-5 (push) Blocked by required conditions
Qwen Code CI / Test-6 (push) Blocked by required conditions
Qwen Code CI / Test-7 (push) Blocked by required conditions
Qwen Code CI / Test-8 (push) Blocked by required conditions
Qwen Code CI / Post Coverage Comment (push) Blocked by required conditions
Qwen Code CI / CodeQL (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:none (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:docker (push) Waiting to run
E2E Tests / E2E Test - macOS (push) Waiting to run
* feat(vscode): expose /skills as slash command with secondary picker Add a secondary completion picker for the /skills slash command in the VSCode IDE companion, allowing users to browse and select skills from a dropdown before sending. Changes: - CLI: add 'skills' to ALLOWED_BUILTIN_COMMANDS_NON_INTERACTIVE whitelist - CLI: send available_skills_update via ACP with skill names/descriptions - Extension: handle available_skills_update in session update handler - Webview: implement secondary picker that triggers after selecting /skills - Webview: allow spaces in completion trigger for /skills sub-queries Closes #1562 Made-with: Cursor * feat(vscode-ide-companion): embed skills in commands update metadata - Move available skills from separate session update to _meta field of available_commands_update for more efficient delivery - Simplify skill data to just skill names (string array) - Add skillsCompletion utility for secondary picker logic - Cache available skills in WebViewProvider for replay on webview ready - Update all related types and handlers to support the new structure Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * refactor(vscode-ide-companion): simplify skills picker flow * refactor(vscode-ide-companion): extract skills completion utils to shared module Move `isSkillsSecondaryQuery`, `shouldOpenSkillsSecondaryPicker`, and `SKILL_ITEM_ID_PREFIX` from App.tsx and useCompletionTrigger.ts into a shared `completionUtils.ts` file to eliminate duplication. * fix(vscode-ide-companion): restore skills picker state on reload Cache and replay available skills when the webview becomes ready again. Clear stale skills when commands metadata does not include availableSkills. * fix(vscode-ide-companion): replay slash commands after webview reload Cache available commands in the webview provider. Replay them on webviewReady so slash command state survives reloads. * fix(vscode-ide-companion): import AvailableCommand from ACP SDK * fix(vscode-ide-companion): fallback /skills to direct command * test(vscode-ide-companion): cover skills secondary picker flow * test(vscode-ide-companion): guard App mock initialization * fix(vscode-ide-companion): remove duplicate AvailableCommand import The auto-merge introduced a duplicate AvailableCommand in the @agentclientprotocol/sdk import block, causing TS2300. * fix(vscode-ide-companion): remove duplicate availableCommands replay in handleWebviewReady The handleWebviewReady method was sending cachedAvailableCommands twice on every webview-ready handshake, causing an unnecessary extra state update in the webview. --------- Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
parent
3a2ee4ac1d
commit
202be6ec7d
25 changed files with 1006 additions and 98 deletions
|
|
@ -246,6 +246,43 @@ describe('Session', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('attaches available skills to available_commands_update metadata', async () => {
|
||||
getAvailableCommandsSpy.mockResolvedValueOnce([
|
||||
{
|
||||
name: 'init',
|
||||
description: 'Initialize project context',
|
||||
},
|
||||
]);
|
||||
mockConfig.getSkillManager = vi.fn().mockReturnValue({
|
||||
listSkills: vi
|
||||
.fn()
|
||||
.mockResolvedValue([
|
||||
{ name: 'code-review-expert' },
|
||||
{ name: 'verification-pack' },
|
||||
]),
|
||||
});
|
||||
|
||||
await session.sendAvailableCommandsUpdate();
|
||||
|
||||
expect(mockClient.sessionUpdate).toHaveBeenCalledTimes(1);
|
||||
expect(mockClient.sessionUpdate).toHaveBeenCalledWith({
|
||||
sessionId: 'test-session-id',
|
||||
update: {
|
||||
sessionUpdate: 'available_commands_update',
|
||||
availableCommands: [
|
||||
{
|
||||
name: 'init',
|
||||
description: 'Initialize project context',
|
||||
input: null,
|
||||
},
|
||||
],
|
||||
_meta: {
|
||||
availableSkills: ['code-review-expert', 'verification-pack'],
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('swallows errors and does not throw', async () => {
|
||||
getAvailableCommandsSpy.mockRejectedValueOnce(
|
||||
new Error('Command discovery failed'),
|
||||
|
|
|
|||
|
|
@ -985,9 +985,27 @@ export class Session implements SessionContext {
|
|||
}),
|
||||
);
|
||||
|
||||
let availableSkills: string[] | undefined;
|
||||
try {
|
||||
const skillManager = this.config.getSkillManager();
|
||||
if (skillManager) {
|
||||
const skills = await skillManager.listSkills();
|
||||
availableSkills = skills.map((skill) => skill.name);
|
||||
}
|
||||
} catch (error) {
|
||||
debugLogger.error('Error loading available skills:', error);
|
||||
}
|
||||
|
||||
const update: SessionUpdate = {
|
||||
sessionUpdate: 'available_commands_update',
|
||||
availableCommands,
|
||||
...(availableSkills
|
||||
? {
|
||||
_meta: {
|
||||
availableSkills,
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
};
|
||||
|
||||
await this.sendUpdate(update);
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ export const skillsCommand: SlashCommand = {
|
|||
return t('List available skills.');
|
||||
},
|
||||
kind: CommandKind.BUILT_IN,
|
||||
supportedModes: ['interactive'] as const,
|
||||
supportedModes: ['interactive', 'acp'] as const,
|
||||
action: async (context: CommandContext, args?: string) => {
|
||||
const rawArgs = args?.trim() ?? '';
|
||||
const [skillName = ''] = rawArgs.split(/\s+/);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue