Skip to content

Commit 769c962

Browse files
committed
Remove server-side tool search and consolidate on client-side tool_search
- Remove all server-side tool_search_tool_regex types, handlers, and stream processing from messagesApi.ts - Remove isAnthropicToolSearchEnabled/isAnthropicCustomToolSearchEnabled functions - Remove AnthropicToolSearchEnabled and AnthropicToolSearchMode settings - Remove TOOL_SEARCH_TOOL_NAME, TOOL_SEARCH_TOOL_TYPE, TOOL_SEARCH_SUPPORTED_MODELS constants - Refactor modelSupportsToolSearch to use version parsing instead of prefix list - Add models filter to ToolSearchTool registration for Claude Sonnet/Opus 4.5+ - Fix MockEndpoint to derive supportsToolSearch from model family - Gate advanced-tool-use beta header directly on endpoint.supportsToolSearch - Update prompts to use client-side tool_search name and semantic search instructions - Update 24 snapshot files to reflect new tool name and instructions
1 parent 4b5765f commit 769c962

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+212
-521
lines changed

extensions/copilot/package.json

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3211,27 +3211,6 @@
32113211
"preview",
32123212
"onExp"
32133213
]
3214-
},
3215-
"github.copilot.chat.anthropic.toolSearchTool.enabled": {
3216-
"type": "boolean",
3217-
"default": true,
3218-
"markdownDescription": "%github.copilot.config.anthropic.toolSearchTool.enabled%",
3219-
"tags": [
3220-
"preview"
3221-
]
3222-
},
3223-
"github.copilot.chat.anthropic.toolSearchTool.mode": {
3224-
"type": "string",
3225-
"enum": [
3226-
"server",
3227-
"client"
3228-
],
3229-
"default": "server",
3230-
"markdownDescription": "%github.copilot.config.anthropic.toolSearchTool.mode%",
3231-
"tags": [
3232-
"preview",
3233-
"onExp"
3234-
]
32353214
}
32363215
}
32373216
},

extensions/copilot/package.nls.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -335,8 +335,6 @@
335335
"copilot.toolSet.web.description": "Fetch information from the web",
336336
"github.copilot.config.useMessagesApi": "Use the Messages API instead of the Chat Completions API when supported.",
337337
"github.copilot.config.anthropic.contextEditing.mode": "Select the context editing mode for Anthropic models. Automatically manages conversation context as it grows, helping optimize costs and stay within context window limits.\n\n- `off`: Context editing is disabled.\n- `clear-thinking`: Clears thinking blocks while preserving tool uses.\n- `clear-tooluse`: Clears tool uses while preserving thinking blocks.\n- `clear-both`: Clears both thinking blocks and tool uses.\n\n**Note**: This is an experimental feature. Context editing may cause additional cache rewrites. Enable with caution.",
338-
"github.copilot.config.anthropic.toolSearchTool.enabled": "Enable tool search tool for Anthropic models. When enabled, tools are dynamically discovered and loaded on-demand using natural language search, reducing context window usage when many tools are available.",
339-
"github.copilot.config.anthropic.toolSearchTool.mode": "Controls how tool search works for Anthropic models. 'server' uses Anthropic's built-in regex-based tool search. 'client' uses local embeddings-based semantic search for more accurate tool discovery.",
340338
"github.copilot.config.useResponsesApi": "Use the Responses API instead of the Chat Completions API when supported. Enables reasoning and reasoning summaries.\n\n**Note**: This is an experimental feature that is not yet activated for all users.\n\n**Important**: URL API path resolution for custom OpenAI-compatible and Azure models is independent of this setting and fully determined by `url` property of `#github.copilot.chat.customOAIModels#` or `#github.copilot.chat.azureModels#` respectively.",
341339
"github.copilot.config.responsesApiReasoningSummary": "Sets the reasoning summary style used for the Responses API. Requires `#github.copilot.chat.useResponsesApi#`.",
342340
"github.copilot.config.responsesApiContextManagement.enabled": "Enables context management for the Responses API. Requires `#github.copilot.chat.useResponsesApi#`.",

extensions/copilot/src/extension/byok/vscode-node/anthropicProvider.ts

Lines changed: 6 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,10 @@ import { CancellationToken, LanguageModelChatInformation, LanguageModelChatMessa
99
import { ChatFetchResponseType, ChatLocation } from '../../../platform/chat/common/commonTypes';
1010
import { ConfigKey, IConfigurationService } from '../../../platform/configuration/common/configurationService';
1111
import { CustomDataPartMimeTypes } from '../../../platform/endpoint/common/endpointTypes';
12+
import { modelSupportsToolSearch } from '../../../platform/endpoint/common/chatModelCapabilities';
1213
import { buildToolInputSchema } from '../../../platform/endpoint/node/messagesApi';
1314
import { ILogService } from '../../../platform/log/common/logService';
14-
import { ContextManagementResponse, getContextManagementFromConfig, isAnthropicContextEditingEnabled, isAnthropicMemoryToolEnabled, isAnthropicToolSearchEnabled, TOOL_SEARCH_TOOL_NAME, TOOL_SEARCH_TOOL_TYPE, ToolSearchToolResult, ToolSearchToolSearchResult } from '../../../platform/networking/common/anthropic';
15+
import { ContextManagementResponse, CUSTOM_TOOL_SEARCH_NAME, getContextManagementFromConfig, isAnthropicContextEditingEnabled, isAnthropicMemoryToolEnabled } from '../../../platform/networking/common/anthropic';
1516
import { IToolDeferralService } from '../../../platform/networking/common/toolDeferralService';
1617
import { IResponseDelta, OpenAiFunctionTool } from '../../../platform/networking/common/fetch';
1718
import { APIUsage } from '../../../platform/networking/common/openai';
@@ -146,19 +147,14 @@ export class AnthropicLMProvider extends AbstractLanguageModelChatProvider {
146147

147148
const memoryToolEnabled = isAnthropicMemoryToolEnabled(model.id, this._configurationService, this._experimentationService);
148149

149-
const toolSearchEnabled = isAnthropicToolSearchEnabled(model.id.replace(/-/g, '.'), this._configurationService);
150+
// Requires the client-side tool_search tool in the request: without it, defer-loaded tools can't be retrieved.
151+
// If the user disables tool_search in the tool picker, it won't be present here and tool search is skipped.
152+
const toolSearchEnabled = modelSupportsToolSearch(model.id)
153+
&& !!options.tools?.some(t => t.name === CUSTOM_TOOL_SEARCH_NAME);
150154

151155
// Build tools array, handling both standard tools and native Anthropic tools
152156
const tools: Anthropic.Beta.BetaToolUnion[] = [];
153157

154-
// Add tool search tool if enabled (must be first in the array)
155-
if (toolSearchEnabled) {
156-
tools.push({
157-
name: TOOL_SEARCH_TOOL_NAME,
158-
type: TOOL_SEARCH_TOOL_TYPE,
159-
defer_loading: false
160-
} as Anthropic.Beta.BetaToolUnion);
161-
}
162158
let hasMemoryTool = false;
163159
for (const tool of (options.tools ?? [])) {
164160
// Handle native Anthropic memory tool (only for models that support it)
@@ -637,33 +633,6 @@ export class AnthropicLMProvider extends AbstractLanguageModelChatProvider {
637633
[new LanguageModelTextPart(searchResults)]
638634
));
639635
pendingServerToolCall = undefined;
640-
} else if ('content_block' in chunk && chunk.content_block.type === 'tool_search_tool_result') {
641-
const toolSearchResult = chunk.content_block as unknown as ToolSearchToolResult;
642-
if (toolSearchResult.content.type === 'tool_search_tool_search_result') {
643-
const searchResult = toolSearchResult.content as ToolSearchToolSearchResult;
644-
const toolNames = searchResult.tool_references.map(ref => ref.tool_name);
645-
646-
this._logService.trace(`Tool search discovered ${toolNames.length} tools: ${toolNames.join(', ')}`);
647-
648-
let query: string | undefined;
649-
if (pendingServerToolCall) {
650-
try {
651-
const parsed = JSON.parse(pendingServerToolCall.jsonInput || '{}');
652-
query = parsed.query;
653-
} catch {
654-
// Ignore parse errors
655-
}
656-
}
657-
658-
progress.report(new LanguageModelToolResultPart(
659-
toolSearchResult.tool_use_id,
660-
[new LanguageModelTextPart(JSON.stringify({ query, discovered_tools: toolNames }))]
661-
));
662-
pendingServerToolCall = undefined;
663-
} else if (toolSearchResult.content.type === 'tool_search_tool_result_error') {
664-
this._logService.warn(`Tool search error: ${toolSearchResult.content.error_code}`);
665-
pendingServerToolCall = undefined;
666-
}
667636
}
668637
continue;
669638
}

extensions/copilot/src/extension/conversation/vscode-node/languageModelAccess.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import { CopilotToken } from '../../../platform/authentication/common/copilotTok
1111
import { IBlockedExtensionService } from '../../../platform/chat/common/blockedExtensionService';
1212
import { ChatFetchResponseType, ChatLocation, getErrorDetailsFromChatFetchError } from '../../../platform/chat/common/commonTypes';
1313
import { getTextPart } from '../../../platform/chat/common/globalStringUtils';
14-
import { IConfigurationService } from '../../../platform/configuration/common/configurationService';
1514
import { EmbeddingType, getWellKnownEmbeddingTypeInfo, IEmbeddingsComputer } from '../../../platform/embeddings/common/embeddingsComputer';
1615
import { IEndpointProvider } from '../../../platform/endpoint/common/endpointProvider';
1716
import { CustomDataPartMimeTypes } from '../../../platform/endpoint/common/endpointTypes';
@@ -23,7 +22,6 @@ import { IEnvService, isScenarioAutomation } from '../../../platform/env/common/
2322
import { IVSCodeExtensionContext } from '../../../platform/extContext/common/extensionContext';
2423
import { IOctoKitService } from '../../../platform/github/common/githubService';
2524
import { ILogService } from '../../../platform/log/common/logService';
26-
import { isAnthropicToolSearchEnabled } from '../../../platform/networking/common/anthropic';
2725
import { FinishedCallback, OpenAiFunctionTool, OptionalChatRequestParams } from '../../../platform/networking/common/fetch';
2826
import { IChatEndpoint, IEndpoint } from '../../../platform/networking/common/networking';
2927
import { IOTelService, type OTelModelOptions } from '../../../platform/otel/common/otelService';
@@ -504,7 +502,6 @@ export class CopilotLanguageModelWrapper extends Disposable {
504502
@ILogService private readonly _logService: ILogService,
505503
@IAuthenticationService private readonly _authenticationService: IAuthenticationService,
506504
@IEnvService private readonly _envService: IEnvService,
507-
@IConfigurationService private readonly _configurationService: IConfigurationService,
508505
@IOTelService private readonly _otelService: IOTelService,
509506
@IOctoKitService private readonly _octoKitService: IOctoKitService,
510507
) {
@@ -570,7 +567,7 @@ export class CopilotLanguageModelWrapper extends Disposable {
570567
throw new Error('Message exceeds token limit.');
571568
}
572569

573-
if (_options.tools && _options.tools.length > 128 && !isAnthropicToolSearchEnabled(_endpoint, this._configurationService)) {
570+
if (_options.tools && _options.tools.length > 128 && !_endpoint.supportsToolSearch) {
574571
throw new Error('Cannot have more than 128 tools per request.');
575572
}
576573

extensions/copilot/src/extension/intents/node/agentIntent.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import { IAutomodeService } from '../../../platform/endpoint/node/automodeServic
1616
import { IEnvService } from '../../../platform/env/common/envService';
1717
import { ILogService } from '../../../platform/log/common/logService';
1818
import { IEditLogService } from '../../../platform/multiFileEdit/common/editLogService';
19-
import { CUSTOM_TOOL_SEARCH_NAME, isAnthropicCustomToolSearchEnabled, isAnthropicContextEditingEnabled, isAnthropicToolSearchEnabled } from '../../../platform/networking/common/anthropic';
19+
import { CUSTOM_TOOL_SEARCH_NAME, isAnthropicContextEditingEnabled } from '../../../platform/networking/common/anthropic';
2020
import { IChatEndpoint } from '../../../platform/networking/common/networking';
2121
import { modelsWithoutResponsesContextManagement } from '../../../platform/networking/common/openai';
2222
import { INotebookService } from '../../../platform/notebook/common/notebookService';
@@ -139,7 +139,7 @@ export const getAgentTools = async (accessor: ServicesAccessor, request: vscode.
139139
allowTools[ToolName.MultiReplaceString] = true;
140140
}
141141

142-
allowTools[CUSTOM_TOOL_SEARCH_NAME] = isAnthropicCustomToolSearchEnabled(model, configurationService, experimentationService);
142+
allowTools[CUSTOM_TOOL_SEARCH_NAME] = !!model.supportsToolSearch;
143143

144144
const tools = toolsService.getEnabledTools(request, model, tool => {
145145
if (typeof allowTools[tool.name] === 'boolean') {
@@ -406,7 +406,7 @@ export class AgentIntentInvocation extends EditCodeIntentInvocation implements I
406406
}
407407

408408
const tools = promptContext.tools?.availableTools;
409-
const toolSearchEnabled = isAnthropicToolSearchEnabled(this.endpoint, this.configurationService);
409+
const toolSearchEnabled = !!this.endpoint.supportsToolSearch;
410410
const toolTokens = tools?.length ? await this.endpoint.acquireTokenizer().countToolTokens(tools) : 0;
411411

412412
const summarizeThresholdOverride = this.configurationService.getConfig<number | undefined>(ConfigKey.Advanced.SummarizeAgentConversationHistoryThreshold);
@@ -674,7 +674,7 @@ export class AgentIntentInvocation extends EditCodeIntentInvocation implements I
674674
this._lastModelCapabilities = {
675675
enableThinking: !isAnthropicFamily(this.endpoint) || ToolCallingLoop.messagesContainThinking(strippedMessages),
676676
reasoningEffort: typeof rawEffort === 'string' ? rawEffort : undefined,
677-
enableToolSearch: !isSubagent && isAnthropicToolSearchEnabled(this.endpoint, this.configurationService),
677+
enableToolSearch: !isSubagent && !!this.endpoint.supportsToolSearch,
678678
enableContextEditing: !isSubagent && isAnthropicContextEditingEnabled(this.endpoint, this.configurationService, this.expService),
679679
};
680680
}

extensions/copilot/src/extension/prompt/node/chatMLFetcher.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import { ICAPIClientService } from '../../../platform/endpoint/common/capiClient
1919
import { isAutoModel } from '../../../platform/endpoint/node/autoChatEndpoint';
2020
import { getResponsesApiCompactionThresholdFromBody, OpenAIResponsesProcessor, responseApiInputToRawMessagesForLogging, sendCompletionOutputTelemetry } from '../../../platform/endpoint/node/responsesApi';
2121
import { collectSingleLineErrorMessage, ILogService } from '../../../platform/log/common/logService';
22-
import { isAnthropicToolSearchEnabled } from '../../../platform/networking/common/anthropic';
2322
import { FinishedCallback, getRequestId, IResponseDelta, OptionalChatRequestParams, RequestId } from '../../../platform/networking/common/fetch';
2423
import { FetcherId, IFetcherService, Response } from '../../../platform/networking/common/fetcherService';
2524
import { IBackgroundRequestOptions, IChatEndpoint, IEndpointBody, ISubagentRequestOptions, postRequest, stringifyUrlOrRequestMetadata } from '../../../platform/networking/common/networking';
@@ -2172,7 +2171,7 @@ function isValidChatPayload(messages: Raw.ChatMessage[], postOptions: OptionalCh
21722171
return { isValid: false, reason: asUnexpected('Function names must match ^[a-zA-Z0-9_-]+$') };
21732172
}
21742173

2175-
if (postOptions?.tools && postOptions.tools.length > HARD_TOOL_LIMIT && !isAnthropicToolSearchEnabled(endpoint, configurationService)) {
2174+
if (postOptions?.tools && postOptions.tools.length > HARD_TOOL_LIMIT && !endpoint.supportsToolSearch) {
21762175
return { isValid: false, reason: `Tool limit exceeded (${postOptions.tools.length}/${HARD_TOOL_LIMIT}). Click "Configure Tools" in the chat input to disable ${postOptions.tools.length - HARD_TOOL_LIMIT} tools and retry.` };
21772176
}
21782177

extensions/copilot/src/extension/prompt/node/defaultIntentRequestHandler.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import { IGitService } from '../../../platform/git/common/gitService';
2121
import { IOctoKitService } from '../../../platform/github/common/githubService';
2222
import { HAS_IGNORED_FILES_MESSAGE } from '../../../platform/ignore/common/ignoreService';
2323
import { ILogService } from '../../../platform/log/common/logService';
24-
import { isAnthropicContextEditingEnabled, isAnthropicToolSearchEnabled } from '../../../platform/networking/common/anthropic';
24+
import { isAnthropicContextEditingEnabled } from '../../../platform/networking/common/anthropic';
2525
import { FilterReason } from '../../../platform/networking/common/openai';
2626
import { IOTelService } from '../../../platform/otel/common/otelService';
2727
import { CapturingToken } from '../../../platform/requestLogger/common/capturingToken';
@@ -701,7 +701,7 @@ class DefaultToolCallingLoop extends ToolCallingLoop<IDefaultToolLoopOptions> {
701701
...opts.modelCapabilities,
702702
enableThinking: isThinkingLocation && opts.modelCapabilities?.enableThinking,
703703
reasoningEffort,
704-
enableToolSearch: !isSubagent && isAnthropicToolSearchEnabled(this.options.invocation.endpoint, this._configurationService),
704+
enableToolSearch: !isSubagent && !!this.options.invocation.endpoint.supportsToolSearch,
705705
enableContextEditing: !isSubagent && isAnthropicContextEditingEnabled(this.options.invocation.endpoint, this._configurationService, this._experimentationService),
706706
},
707707
debugName,
@@ -741,7 +741,7 @@ class DefaultToolCallingLoop extends ToolCallingLoop<IDefaultToolLoopOptions> {
741741
const tools = await this.options.invocation.getAvailableTools?.() ?? [];
742742

743743
// Skip tool grouping when Anthropic tool search is enabled
744-
if (isAnthropicFamily(this.options.invocation.endpoint) && isAnthropicToolSearchEnabled(this.options.invocation.endpoint, this._configurationService)) {
744+
if (isAnthropicFamily(this.options.invocation.endpoint) && this.options.invocation.endpoint.supportsToolSearch) {
745745
return tools;
746746
}
747747

0 commit comments

Comments
 (0)