Add 'isExclusive' flag for tool selection (#247267)

* Add 'isExclusive' flag for tool selection
For prompts with tools to exclude non-selected tools

* Fix
This commit is contained in:
Rob Lourens
2025-04-23 18:42:00 -07:00
committed by GitHub
parent ed40c856ec
commit d9bc5b09ea
9 changed files with 36 additions and 20 deletions
@@ -36,7 +36,7 @@ const _allApiProposals = {
}, },
chatParticipantPrivate: { chatParticipantPrivate: {
proposal: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.chatParticipantPrivate.d.ts', proposal: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.chatParticipantPrivate.d.ts',
version: 8 version: 9
}, },
chatProvider: { chatProvider: {
proposal: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.chatProvider.d.ts', proposal: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.chatProvider.d.ts',
@@ -560,12 +560,16 @@ export class ExtHostChatAgents2 extends Disposable implements ExtHostChatAgentsS
return this._diagnostics.getDiagnostics(); return this._diagnostics.getDiagnostics();
} }
private getToolsForRequest(extension: IExtensionDescription, request: Dto<IChatAgentRequest>) { private getToolsForRequest(extension: IExtensionDescription, request: Dto<IChatAgentRequest>): vscode.ChatRequestToolSelection | undefined {
if (!isNonEmptyArray(request.userSelectedTools)) { if (!isNonEmptyArray(request.userSelectedTools)) {
return undefined; return undefined;
} }
const selector = new Set(request.userSelectedTools); 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<IRelaxedExtensionDescription>, agentId: string, context: { history: IChatAgentHistoryEntryDto[] }): Promise<(vscode.ChatRequestTurn | vscode.ChatResponseTurn)[]> { private async prepareHistoryTurns(extension: Readonly<IRelaxedExtensionDescription>, agentId: string, context: { history: IChatAgentHistoryEntryDto[] }): Promise<(vscode.ChatRequestTurn | vscode.ChatResponseTurn)[]> {
@@ -2898,7 +2898,7 @@ export namespace ChatResponsePart {
} }
export namespace ChatAgentRequest { 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 toolReferences = request.variables.variables.filter(v => v.kind === 'tool');
const variableReferences = request.variables.variables.filter(v => v.kind !== 'tool'); const variableReferences = request.variables.variables.filter(v => v.kind !== 'tool');
const requestWithAllProps: vscode.ChatRequest = { const requestWithAllProps: vscode.ChatRequest = {
@@ -2915,7 +2915,7 @@ export namespace ChatAgentRequest {
rejectedConfirmationData: request.rejectedConfirmationData, rejectedConfirmationData: request.rejectedConfirmationData,
location2, location2,
toolInvocationToken: Object.freeze({ sessionId: request.sessionId }) as never, toolInvocationToken: Object.freeze({ sessionId: request.sessionId }) as never,
tools, toolSelection,
model, model,
editedFileEvents: request.editedFileEvents, editedFileEvents: request.editedFileEvents,
}; };
@@ -1243,7 +1243,7 @@ export class ChatWidget extends Disposable implements IChatWidget {
parserContext: { selectedAgent: this._lastSelectedAgent, mode: this.inputPart.currentMode }, parserContext: { selectedAgent: this._lastSelectedAgent, mode: this.inputPart.currentMode },
attachedContext, attachedContext,
noCommandDetection: options?.noCommandDetection, 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) { if (result) {
@@ -138,6 +138,7 @@ export interface IChatAgentRequest {
rejectedConfirmationData?: any[]; rejectedConfirmationData?: any[];
userSelectedModelId?: string; userSelectedModelId?: string;
userSelectedTools?: string[]; userSelectedTools?: string[];
toolSelectionIsExclusive?: boolean;
editedFileEvents?: IChatAgentEditedFileEvent[]; editedFileEvents?: IChatAgentEditedFileEvent[];
} }
@@ -466,6 +466,7 @@ export interface IChatSendRequestOptions {
mode?: ChatMode; mode?: ChatMode;
userSelectedModelId?: string; userSelectedModelId?: string;
userSelectedTools?: string[]; userSelectedTools?: string[];
toolSelectionIsExclusive?: boolean;
location?: ChatAgentLocation; location?: ChatAgentLocation;
locationData?: IChatLocationData; locationData?: IChatLocationData;
parserContext?: IChatParserContext; parserContext?: IChatParserContext;
@@ -768,6 +768,7 @@ export class ChatService extends Disposable implements IChatService {
rejectedConfirmationData: options?.rejectedConfirmationData, rejectedConfirmationData: options?.rejectedConfirmationData,
userSelectedModelId: options?.userSelectedModelId, userSelectedModelId: options?.userSelectedModelId,
userSelectedTools: options?.userSelectedTools, userSelectedTools: options?.userSelectedTools,
toolSelectionIsExclusive: options?.toolSelectionIsExclusive,
editedFileEvents: request.editedFileEvents editedFileEvents: request.editedFileEvents
} satisfies IChatAgentRequest; } satisfies IChatAgentRequest;
}; };
@@ -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 this piggy-back on the existing ChatRequest, or is it a different type of request entirely?
* Does it show up in history? * Does it show up in history?
+23 -1
View File
@@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information. * Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
// version: 8 // version: 9
declare module 'vscode' { declare module 'vscode' {
@@ -240,4 +240,26 @@ declare module 'vscode' {
} }
// #endregion // #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;
}
} }