Path: blob/main/extensions/copilot/src/extension/prompts/node/agent/toolSearchInstructions.tsx
13405 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { BasePromptElementProps, PromptElement, PromptElementProps, PromptSizing } from '@vscode/prompt-tsx';6import type { LanguageModelToolInformation } from 'vscode';7import { CUSTOM_TOOL_SEARCH_NAME } from '../../../../platform/networking/common/anthropic';8import { IChatEndpoint } from '../../../../platform/networking/common/networking';9import { IToolDeferralService } from '../../../../platform/networking/common/toolDeferralService';10import { Tag } from '../base/tag';1112export interface ToolSearchToolPromptProps extends BasePromptElementProps {13readonly availableTools: readonly LanguageModelToolInformation[] | undefined;14}1516export interface DeferredToolListReminderProps extends BasePromptElementProps {17readonly availableTools: readonly LanguageModelToolInformation[] | undefined;18}1920/**21* True when `availableTools` contains at least one tool that the deferral22* service treats as deferred. Shared between the system-prompt guidance and23* the global-context list so they appear/disappear together.24*/25export function hasDeferredTool(26availableTools: readonly LanguageModelToolInformation[] | undefined,27toolDeferralService: IToolDeferralService,28): boolean {29return !!availableTools?.some(tool => !toolDeferralService.isNonDeferredTool(tool.name));30}3132/**33* Condensed tool search instructions shared across model prompts.34* Renders deferred-tool search *guidance* when the endpoint supports tool35* search and at least one deferred tool is available. The list itself is36* rendered by `DeferredToolListReminder` inside the global agent context.37*/38export class ToolSearchToolPromptOptimized extends PromptElement<ToolSearchToolPromptProps> {39constructor(40props: PromptElementProps<ToolSearchToolPromptProps>,41@IToolDeferralService private readonly toolDeferralService: IToolDeferralService,42) {43super(props);44}4546async render(state: void, sizing: PromptSizing) {47const endpoint = sizing.endpoint as IChatEndpoint | undefined;48if (!endpoint?.supportsToolSearch || !hasDeferredTool(this.props.availableTools, this.toolDeferralService)) {49return;50}5152return <Tag name='toolSearchInstructions'>53You MUST use {CUSTOM_TOOL_SEARCH_NAME} to load deferred tools BEFORE calling them. Calling a deferred tool without loading it first will fail.<br />54<br />55Describe what capability you need in natural language. The search uses semantic similarity to find the most relevant tools.<br />56<br />57Do NOT call {CUSTOM_TOOL_SEARCH_NAME} again for a tool already returned by a previous search. If a search returns no matching tools, the tool is not available. Do not retry with different patterns.<br />58</Tag>;59}60}6162/**63* Emits the list of deferred tools. Rendered inside `GlobalAgentContext` so it64* appears once at the start of the conversation and is then frozen for the65* remainder of the session via `GlobalContextMessageMetadata` — keeps the66* list out of every per-turn user message and out of the system prompt prefix.67*68* Self-gates on `endpoint.supportsToolSearch`. The surrounding `<Tag>` name69* matches the reference used by `tool_search`'s tool description.70*71* Note: the snapshot is taken at first render. Tools that become available72* later in the conversation (e.g. MCP servers connecting mid-session) won't73* appear in this list.74*/75export class DeferredToolListReminder extends PromptElement<DeferredToolListReminderProps> {76constructor(77props: PromptElementProps<DeferredToolListReminderProps>,78@IToolDeferralService private readonly toolDeferralService: IToolDeferralService,79) {80super(props);81}8283async render(state: void, sizing: PromptSizing) {84const endpoint = sizing.endpoint as IChatEndpoint | undefined;85if (!endpoint?.supportsToolSearch || !this.props.availableTools) {86return;87}8889const deferredTools = this.props.availableTools90.filter(tool => !this.toolDeferralService.isNonDeferredTool(tool.name))91.map(tool => tool.name)92.sort();9394if (deferredTools.length === 0) {95return;96}9798return <Tag name='availableDeferredTools'>99Available deferred tools (must be loaded with {CUSTOM_TOOL_SEARCH_NAME} before use):<br />100{deferredTools.join('\n')}101</Tag>;102}103}104105export { CUSTOM_TOOL_SEARCH_NAME };106107108