From d9bc5b09ea14b6ff9d95445ce87de052d0ad9165 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Wed, 23 Apr 2025 18:42:00 -0700 Subject: [PATCH] Add 'isExclusive' flag for tool selection (#247267) * Add 'isExclusive' flag for tool selection For prompts with tools to exclude non-selected tools * Fix --- .../common/extensionsApiProposals.ts | 2 +- .../api/common/extHostChatAgents2.ts | 8 +++++-- .../api/common/extHostTypeConverters.ts | 4 ++-- .../contrib/chat/browser/chatWidget.ts | 2 +- .../contrib/chat/common/chatAgents.ts | 1 + .../contrib/chat/common/chatService.ts | 1 + .../contrib/chat/common/chatServiceImpl.ts | 1 + ...ode.proposed.chatParticipantAdditions.d.ts | 13 ---------- ...scode.proposed.chatParticipantPrivate.d.ts | 24 ++++++++++++++++++- 9 files changed, 36 insertions(+), 20 deletions(-) diff --git a/src/vs/platform/extensions/common/extensionsApiProposals.ts b/src/vs/platform/extensions/common/extensionsApiProposals.ts index c825f45db15..35d88b02170 100644 --- a/src/vs/platform/extensions/common/extensionsApiProposals.ts +++ b/src/vs/platform/extensions/common/extensionsApiProposals.ts @@ -36,7 +36,7 @@ const _allApiProposals = { }, chatParticipantPrivate: { proposal: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.chatParticipantPrivate.d.ts', - version: 8 + version: 9 }, chatProvider: { proposal: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.chatProvider.d.ts', diff --git a/src/vs/workbench/api/common/extHostChatAgents2.ts b/src/vs/workbench/api/common/extHostChatAgents2.ts index 49c7a5feff3..00b6c7d69c9 100644 --- a/src/vs/workbench/api/common/extHostChatAgents2.ts +++ b/src/vs/workbench/api/common/extHostChatAgents2.ts @@ -560,12 +560,16 @@ export class ExtHostChatAgents2 extends Disposable implements ExtHostChatAgentsS return this._diagnostics.getDiagnostics(); } - private getToolsForRequest(extension: IExtensionDescription, request: Dto) { + private getToolsForRequest(extension: IExtensionDescription, request: Dto): vscode.ChatRequestToolSelection | undefined { if (!isNonEmptyArray(request.userSelectedTools)) { return undefined; } const selector = new Set(request.userSelectedTools); - return this._tools.getTools(extension).filter(candidate => selector.has(candidate.name)); + const tools = this._tools.getTools(extension).filter(candidate => selector.has(candidate.name)); + return { + tools, + isExclusive: request.toolSelectionIsExclusive, + }; } private async prepareHistoryTurns(extension: Readonly, agentId: string, context: { history: IChatAgentHistoryEntryDto[] }): Promise<(vscode.ChatRequestTurn | vscode.ChatResponseTurn)[]> { diff --git a/src/vs/workbench/api/common/extHostTypeConverters.ts b/src/vs/workbench/api/common/extHostTypeConverters.ts index 1bab9eeac00..a4c356ad7fb 100644 --- a/src/vs/workbench/api/common/extHostTypeConverters.ts +++ b/src/vs/workbench/api/common/extHostTypeConverters.ts @@ -2898,7 +2898,7 @@ export namespace ChatResponsePart { } export namespace ChatAgentRequest { - export function to(request: IChatAgentRequest, location2: vscode.ChatRequestEditorData | vscode.ChatRequestNotebookData | undefined, model: vscode.LanguageModelChat, diagnostics: readonly [vscode.Uri, readonly vscode.Diagnostic[]][], tools: vscode.LanguageModelToolInformation[] | undefined, extension: IRelaxedExtensionDescription): vscode.ChatRequest { + export function to(request: IChatAgentRequest, location2: vscode.ChatRequestEditorData | vscode.ChatRequestNotebookData | undefined, model: vscode.LanguageModelChat, diagnostics: readonly [vscode.Uri, readonly vscode.Diagnostic[]][], toolSelection: vscode.ChatRequestToolSelection | undefined, extension: IRelaxedExtensionDescription): vscode.ChatRequest { const toolReferences = request.variables.variables.filter(v => v.kind === 'tool'); const variableReferences = request.variables.variables.filter(v => v.kind !== 'tool'); const requestWithAllProps: vscode.ChatRequest = { @@ -2915,7 +2915,7 @@ export namespace ChatAgentRequest { rejectedConfirmationData: request.rejectedConfirmationData, location2, toolInvocationToken: Object.freeze({ sessionId: request.sessionId }) as never, - tools, + toolSelection, model, editedFileEvents: request.editedFileEvents, }; diff --git a/src/vs/workbench/contrib/chat/browser/chatWidget.ts b/src/vs/workbench/contrib/chat/browser/chatWidget.ts index d6bae7b8045..c0edee9fa9e 100644 --- a/src/vs/workbench/contrib/chat/browser/chatWidget.ts +++ b/src/vs/workbench/contrib/chat/browser/chatWidget.ts @@ -1243,7 +1243,7 @@ export class ChatWidget extends Disposable implements IChatWidget { parserContext: { selectedAgent: this._lastSelectedAgent, mode: this.inputPart.currentMode }, attachedContext, noCommandDetection: options?.noCommandDetection, - userSelectedTools: this.input.currentMode === ChatMode.Agent ? this.inputPart.selectedToolsModel.tools.get().map(tool => tool.id) : undefined + userSelectedTools: this.input.currentMode === ChatMode.Agent ? this.inputPart.selectedToolsModel.tools.get().map(tool => tool.id) : undefined, }); if (result) { diff --git a/src/vs/workbench/contrib/chat/common/chatAgents.ts b/src/vs/workbench/contrib/chat/common/chatAgents.ts index 9fe6e516395..7017c466ff8 100644 --- a/src/vs/workbench/contrib/chat/common/chatAgents.ts +++ b/src/vs/workbench/contrib/chat/common/chatAgents.ts @@ -138,6 +138,7 @@ export interface IChatAgentRequest { rejectedConfirmationData?: any[]; userSelectedModelId?: string; userSelectedTools?: string[]; + toolSelectionIsExclusive?: boolean; editedFileEvents?: IChatAgentEditedFileEvent[]; } diff --git a/src/vs/workbench/contrib/chat/common/chatService.ts b/src/vs/workbench/contrib/chat/common/chatService.ts index 9e9cead60f9..4a2512cf13e 100644 --- a/src/vs/workbench/contrib/chat/common/chatService.ts +++ b/src/vs/workbench/contrib/chat/common/chatService.ts @@ -466,6 +466,7 @@ export interface IChatSendRequestOptions { mode?: ChatMode; userSelectedModelId?: string; userSelectedTools?: string[]; + toolSelectionIsExclusive?: boolean; location?: ChatAgentLocation; locationData?: IChatLocationData; parserContext?: IChatParserContext; diff --git a/src/vs/workbench/contrib/chat/common/chatServiceImpl.ts b/src/vs/workbench/contrib/chat/common/chatServiceImpl.ts index cd07a81b1f0..a55f2ca360e 100644 --- a/src/vs/workbench/contrib/chat/common/chatServiceImpl.ts +++ b/src/vs/workbench/contrib/chat/common/chatServiceImpl.ts @@ -768,6 +768,7 @@ export class ChatService extends Disposable implements IChatService { rejectedConfirmationData: options?.rejectedConfirmationData, userSelectedModelId: options?.userSelectedModelId, userSelectedTools: options?.userSelectedTools, + toolSelectionIsExclusive: options?.toolSelectionIsExclusive, editedFileEvents: request.editedFileEvents } satisfies IChatAgentRequest; }; diff --git a/src/vscode-dts/vscode.proposed.chatParticipantAdditions.d.ts b/src/vscode-dts/vscode.proposed.chatParticipantAdditions.d.ts index 6dce17bb29e..ffe4e988fea 100644 --- a/src/vscode-dts/vscode.proposed.chatParticipantAdditions.d.ts +++ b/src/vscode-dts/vscode.proposed.chatParticipantAdditions.d.ts @@ -227,19 +227,6 @@ declare module 'vscode' { } - export interface ChatRequest { - - /** - * A list of tools that the user selected for this request, when `undefined` any tool - * from {@link lm.tools} should be used. - * - * Tools can be called with {@link lm.invokeTool} with input that match their - * declared `inputSchema`. - */ - readonly tools: readonly LanguageModelToolInformation[] | undefined; - } - - /** * Does this piggy-back on the existing ChatRequest, or is it a different type of request entirely? * Does it show up in history? diff --git a/src/vscode-dts/vscode.proposed.chatParticipantPrivate.d.ts b/src/vscode-dts/vscode.proposed.chatParticipantPrivate.d.ts index 43010b7300c..8b0d17fa0ca 100644 --- a/src/vscode-dts/vscode.proposed.chatParticipantPrivate.d.ts +++ b/src/vscode-dts/vscode.proposed.chatParticipantPrivate.d.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -// version: 8 +// version: 9 declare module 'vscode' { @@ -240,4 +240,26 @@ declare module 'vscode' { } // #endregion + + export interface ChatRequestToolSelection { + /** + * A list of tools that the user selected for this request. + * Tools can be called with {@link lm.invokeTool} with input that match their + * declared `inputSchema`. + */ + readonly tools: readonly LanguageModelToolInformation[]; + + /** + * When true, only this set of tools (and toolReferences) should be used. When false, the base set of agent tools can also be included. + */ + readonly isExclusive?: boolean; + } + + export interface ChatRequest { + /** + * A list of tools that the user selected for this request, when `undefined` any tool + * from {@link lm.tools} should be used. + */ + readonly toolSelection: ChatRequestToolSelection | undefined; + } }