diff --git a/src/extension/context/node/resolvers/test/vscodeContext.spec.ts b/src/extension/context/node/resolvers/test/vscodeContext.spec.ts index c500a7a038..8f716da219 100644 --- a/src/extension/context/node/resolvers/test/vscodeContext.spec.ts +++ b/src/extension/context/node/resolvers/test/vscodeContext.spec.ts @@ -130,7 +130,7 @@ describe('parseSettingsAndCommands', () => { expect(result[0].commandToRun?.arguments).toEqual(['@id:editor.fontSize ']); }); - it('returns empty array for unknown command', async () => { + it('returns empty quickOpen for unknown command', async () => { const mockService = new MockWorkbenchService({}, [ { label: 'Show All Commands', command: 'workbench.action.showCommands', keybinding: 'Ctrl+Shift+P' } ]); @@ -146,7 +146,10 @@ describe('parseSettingsAndCommands', () => { \`\`\``; const result = await parseSettingsAndCommands(mockService, codeBlock); - expect(result).toEqual([]); + expect(result).toHaveLength(1); + expect(result[0].commandToRun?.command).toBe('workbench.action.quickOpen'); + expect(result[0].commandToRun?.arguments).toEqual(['>']); + expect(result[0].commandToRun?.title).toBe('Open Command Palette'); }); it('processes extension search command', async () => { @@ -337,4 +340,4 @@ describe('parseSettingsAndCommands', () => { expect(result[0].commandToRun?.arguments).toEqual(['>']); expect(result[0].commandToRun?.title).toBe('Show in Command Palette'); }); -}); \ No newline at end of file +}); diff --git a/src/extension/context/node/resolvers/vscodeContext.ts b/src/extension/context/node/resolvers/vscodeContext.ts index 2aaadeb422..25a9bd7137 100644 --- a/src/extension/context/node/resolvers/vscodeContext.ts +++ b/src/extension/context/node/resolvers/vscodeContext.ts @@ -109,10 +109,20 @@ export async function parseSettingsAndCommands(workbenchService: IWorkbenchServi return parsedMetadata; } else { - const allcommands = (await workbenchService.getAllCommands(/* filterByPreCondition */true)); - const commandItem = allcommands.find(commandItem => commandItem.command === item.details?.key); + // Get all commands regardless of preconditions, because there are some commands that a user may meet the preconditions for, + // but Copilot not, so we still will show the command in the palette for the user to run. + const allCommandsNoFilter = (await workbenchService.getAllCommands(/* filterByPreCondition */false)); + const commandItem = allCommandsNoFilter.find(commandItem => commandItem.command === item.details?.key); if (!commandItem) { - return []; + // If we can't find the command on the list, just open the command palette without any pre-filled filter + parsedMetadata.push({ + commandToRun: { + command: 'workbench.action.quickOpen', + arguments: [`>`], + title: l10n.t("Open Command Palette"), + } + }); + return parsedMetadata; } parsedMetadata.push({ commandToRun: { diff --git a/src/extension/tools/node/vscodeCmdTool.tsx b/src/extension/tools/node/vscodeCmdTool.tsx index a0b216cbe2..5f70a0f8f3 100644 --- a/src/extension/tools/node/vscodeCmdTool.tsx +++ b/src/extension/tools/node/vscodeCmdTool.tsx @@ -34,18 +34,25 @@ class VSCodeCmdTool implements vscode.LanguageModelTool const command = options.input.commandId; const args = options.input.args ?? []; - const allcommands = (await this._workbenchService.getAllCommands(/* filterByPreCondition */true)); - const commandItem = allcommands.find(commandItem => commandItem.command === command); + const allCommands = (await this._workbenchService.getAllCommands(/* filterByPreCondition */true)); + const commandItem = allCommands.find(commandItem => commandItem.command === command); if (!commandItem) { - return new LanguageModelToolResult([new LanguageModelTextPart(`Failed to find ${options.input.name} command.`)]); + // Try again but without filtering by preconditions to see if the command exists at all + const allCommandsNoFilter = (await this._workbenchService.getAllCommands(/* filterByPreCondition */false)); + const commandItemNoFilter = allCommandsNoFilter.find(commandItem => commandItem.command === command); + if (commandItemNoFilter) { + return new LanguageModelToolResult([new LanguageModelTextPart(`Command \`${options.input.name}\` exists, but its preconditions are not currently met. Ask the user to try running it manually via the command palette.`)]); + } else { + return new LanguageModelToolResult([new LanguageModelTextPart(`Failed to find command \`${options.input.name}\`.`)]); + } } try { await this._commandService.executeCommand(command, ...args); - return new LanguageModelToolResult([new LanguageModelTextPart(`Finished running ${options.input.name} command`)]); + return new LanguageModelToolResult([new LanguageModelTextPart(`Finished running command \`${options.input.name}\`.`)]); } catch (error) { this._logService.error(`[VSCodeCmdTool] ${error}`); - return new LanguageModelToolResult([new LanguageModelTextPart(`Failed to run ${options.input.name} command.`)]); + return new LanguageModelToolResult([new LanguageModelTextPart(`Failed to run command \`${options.input.name}\`.`)]); } }