Skip to content

Commit 3f487b2

Browse files
committed
Fix toolTokens over-counting when Anthropic Tool Search is enabled
When TST (Tool Search Tool) is enabled, most tools are sent with defer_loading: true and don't count against the context window until the model loads them via tool_search. However, the toolTokens calculation in agentIntent counted ALL available tools, over-estimating by ~25-30K tokens and causing premature compaction. Fix: filter availableTools to only non-deferred tools (via IToolDeferralService) before calling countToolTokens() when TST is enabled. This gives an accurate budget that reflects what the API actually charges against the context window.
1 parent 2702336 commit 3f487b2

4 files changed

Lines changed: 22 additions & 6 deletions

File tree

src/extension/intents/node/agentIntent.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ 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 } from '../../../platform/networking/common/anthropic';
19+
import { CUSTOM_TOOL_SEARCH_NAME, isAnthropicCustomToolSearchEnabled, isAnthropicToolSearchEnabled } from '../../../platform/networking/common/anthropic';
20+
import { IToolDeferralService } from '../../../platform/networking/common/toolDeferralService';
2021
import { IChatEndpoint } from '../../../platform/networking/common/networking';
2122
import { modelsWithoutResponsesContextManagement } from '../../../platform/networking/common/openai';
2223
import { INotebookService } from '../../../platform/notebook/common/notebookService';
@@ -363,6 +364,7 @@ export class AgentIntentInvocation extends EditCodeIntentInvocation implements I
363364
@IExperimentationService private readonly expService: IExperimentationService,
364365
@IAutomodeService private readonly automodeService: IAutomodeService,
365366
@IOTelService override readonly otelService: IOTelService,
367+
@IToolDeferralService private readonly toolDeferralService: IToolDeferralService,
366368
) {
367369
super(intent, location, endpoint, request, intentOptions, instantiationService, codeMapperService, envService, promptPathRepresentationService, endpointProvider, workspaceService, toolsService, configurationService, editLogService, commandService, telemetryService, notebookService, otelService);
368370
}
@@ -388,7 +390,15 @@ export class AgentIntentInvocation extends EditCodeIntentInvocation implements I
388390
}
389391

390392
const tools = promptContext.tools?.availableTools;
391-
const toolTokens = tools?.length ? await this.endpoint.acquireTokenizer().countToolTokens(tools) : 0;
393+
// When Anthropic tool search is enabled, deferred tools are sent with
394+
// defer_loading: true and don't count against the context window until
395+
// the model loads them via tool_search. Only count non-deferred tools
396+
// so the budget isn't artificially reduced.
397+
const toolSearchEnabled = isAnthropicToolSearchEnabled(this.endpoint, this.configurationService);
398+
const effectiveTools = tools && toolSearchEnabled
399+
? tools.filter(t => this.toolDeferralService.isNonDeferredTool(t.name))
400+
: tools;
401+
const toolTokens = effectiveTools?.length ? await this.endpoint.acquireTokenizer().countToolTokens(effectiveTools) : 0;
392402

393403
const summarizeThresholdOverride = this.configurationService.getConfig<number | undefined>(ConfigKey.Advanced.SummarizeAgentConversationHistoryThreshold);
394404
if (typeof summarizeThresholdOverride === 'number' && summarizeThresholdOverride < 100 && summarizeThresholdOverride > 0) {
@@ -414,7 +424,7 @@ export class AgentIntentInvocation extends EditCodeIntentInvocation implements I
414424
const safeBudget = useTruncation ? Number.MAX_SAFE_INTEGER : messageBudget;
415425
const endpoint = toolTokens > 0 ? this.endpoint.cloneWithTokenOverride(safeBudget) : this.endpoint;
416426

417-
this.logService.debug(`AgentIntent: rendering with budget=${safeBudget} (baseBudget: ${baseBudget}, toolTokens: ${toolTokens}), summarizationEnabled=${summarizationEnabled}`);
427+
this.logService.debug(`AgentIntent: rendering with budget=${safeBudget} (baseBudget: ${baseBudget}, toolTokens: ${toolTokens}${toolSearchEnabled ? `, totalTools: ${tools?.length ?? 0}, nonDeferredTools: ${effectiveTools?.length ?? 0}` : ''}), summarizationEnabled=${summarizationEnabled}`);
418428
let result: RenderPromptResult;
419429
const props: AgentPromptProps = {
420430
endpoint,

src/extension/intents/node/askAgentIntent.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { IEnvService } from '../../../platform/env/common/envService';
1212
import { ILogService } from '../../../platform/log/common/logService';
1313
import { IEditLogService } from '../../../platform/multiFileEdit/common/editLogService';
1414
import { IChatEndpoint } from '../../../platform/networking/common/networking';
15+
import { IToolDeferralService } from '../../../platform/networking/common/toolDeferralService';
1516
import { INotebookService } from '../../../platform/notebook/common/notebookService';
1617
import { IOTelService } from '../../../platform/otel/common/otelService';
1718
import { IPromptPathRepresentationService } from '../../../platform/prompts/common/promptPathRepresentationService';
@@ -128,8 +129,9 @@ export class AskAgentIntentInvocation extends AgentIntentInvocation {
128129
@IExperimentationService expService: IExperimentationService,
129130
@IAutomodeService automodeService: IAutomodeService,
130131
@IOTelService otelService: IOTelService,
132+
@IToolDeferralService toolDeferralService: IToolDeferralService,
131133
) {
132-
super(intent, location, endpoint, request, { processCodeblocks: true }, instantiationService, codeMapperService, envService, promptPathRepresentationService, endpointProvider, workspaceService, toolsService, configurationService, editLogService, commandService, telemetryService, notebookService, logService, expService, automodeService, otelService);
134+
super(intent, location, endpoint, request, { processCodeblocks: true }, instantiationService, codeMapperService, envService, promptPathRepresentationService, endpointProvider, workspaceService, toolsService, configurationService, editLogService, commandService, telemetryService, notebookService, logService, expService, automodeService, otelService, toolDeferralService);
133135
}
134136

135137
public override async getAvailableTools(): Promise<vscode.LanguageModelToolInformation[]> {

src/extension/intents/node/editCodeIntent2.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { IEnvService } from '../../../platform/env/common/envService';
1313
import { ILogService } from '../../../platform/log/common/logService';
1414
import { IEditLogService } from '../../../platform/multiFileEdit/common/editLogService';
1515
import { IChatEndpoint } from '../../../platform/networking/common/networking';
16+
import { IToolDeferralService } from '../../../platform/networking/common/toolDeferralService';
1617
import { requestHasNotebookRefs } from '../../../platform/notebook/common/helpers';
1718
import { INotebookService } from '../../../platform/notebook/common/notebookService';
1819
import { IOTelService } from '../../../platform/otel/common/otelService';
@@ -89,8 +90,9 @@ export class EditCode2IntentInvocation extends AgentIntentInvocation {
8990
@IExperimentationService expService: IExperimentationService,
9091
@IAutomodeService automodeService: IAutomodeService,
9192
@IOTelService otelService: IOTelService,
93+
@IToolDeferralService toolDeferralService: IToolDeferralService,
9294
) {
93-
super(intent, location, endpoint, request, intentOptions, instantiationService, codeMapperService, envService, promptPathRepresentationService, endpointProvider, workspaceService, toolsService, configurationService, editLogService, commandService, telemetryService, notebookService, logService, expService, automodeService, otelService);
95+
super(intent, location, endpoint, request, intentOptions, instantiationService, codeMapperService, envService, promptPathRepresentationService, endpointProvider, workspaceService, toolsService, configurationService, editLogService, commandService, telemetryService, notebookService, logService, expService, automodeService, otelService, toolDeferralService);
9496
}
9597

9698
public override async getAvailableTools(): Promise<vscode.LanguageModelToolInformation[]> {

src/extension/intents/node/notebookEditorIntent.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { IEnvService } from '../../../platform/env/common/envService';
1212
import { ILogService } from '../../../platform/log/common/logService';
1313
import { IEditLogService } from '../../../platform/multiFileEdit/common/editLogService';
1414
import { IChatEndpoint } from '../../../platform/networking/common/networking';
15+
import { IToolDeferralService } from '../../../platform/networking/common/toolDeferralService';
1516
import { IAlternativeNotebookContentService } from '../../../platform/notebook/common/alternativeContent';
1617
import { getCellId } from '../../../platform/notebook/common/helpers';
1718
import { INotebookService } from '../../../platform/notebook/common/notebookService';
@@ -107,8 +108,9 @@ export class NotebookEditorIntentInvocation extends EditCode2IntentInvocation {
107108
@IExperimentationService expService: IExperimentationService,
108109
@IAutomodeService automodeService: IAutomodeService,
109110
@IOTelService otelService: IOTelService,
111+
@IToolDeferralService toolDeferralService: IToolDeferralService,
110112
) {
111-
super(intent, location, endpoint, request, intentOptions, instantiationService, codeMapperService, envService, promptPathRepresentationService, endpointProvider, workspaceService, toolsService, configurationService, editLogService, commandService, telemetryService, notebookService, logService, expService, automodeService, otelService);
113+
super(intent, location, endpoint, request, intentOptions, instantiationService, codeMapperService, envService, promptPathRepresentationService, endpointProvider, workspaceService, toolsService, configurationService, editLogService, commandService, telemetryService, notebookService, logService, expService, automodeService, otelService, toolDeferralService);
112114
}
113115

114116
protected override prompt = NotebookInlinePrompt;

0 commit comments

Comments
 (0)