( tools: Tools, getToolPermissionContext: () => Promise<ToolPermissionContext>, agentInfo: AgentDefinitionsResult | null, model?: string, messages?: Message[], )
| 361 | } |
| 362 | |
| 363 | async function countBuiltInToolTokens( |
| 364 | tools: Tools, |
| 365 | getToolPermissionContext: () => Promise<ToolPermissionContext>, |
| 366 | agentInfo: AgentDefinitionsResult | null, |
| 367 | model?: string, |
| 368 | messages?: Message[], |
| 369 | ): Promise<{ |
| 370 | builtInToolTokens: number |
| 371 | deferredBuiltinDetails: DeferredBuiltinTool[] |
| 372 | deferredBuiltinTokens: number |
| 373 | systemToolDetails: SystemToolDetail[] |
| 374 | }> { |
| 375 | const builtInTools = tools.filter(tool => !tool.isMcp) |
| 376 | if (builtInTools.length < 1) { |
| 377 | return { |
| 378 | builtInToolTokens: 0, |
| 379 | deferredBuiltinDetails: [], |
| 380 | deferredBuiltinTokens: 0, |
| 381 | systemToolDetails: [], |
| 382 | } |
| 383 | } |
| 384 | |
| 385 | // Check if tool search is enabled |
| 386 | const { isToolSearchEnabled } = await import('./toolSearch.js') |
| 387 | const { isDeferredTool } = await import('../tools/ToolSearchTool/prompt.js') |
| 388 | const isDeferred = await isToolSearchEnabled( |
| 389 | model ?? '', |
| 390 | tools, |
| 391 | getToolPermissionContext, |
| 392 | agentInfo?.activeAgents ?? [], |
| 393 | 'analyzeBuiltIn', |
| 394 | ) |
| 395 | |
| 396 | // Separate always-loaded and deferred builtin tools using dynamic isDeferredTool check |
| 397 | const alwaysLoadedTools = builtInTools.filter(t => !isDeferredTool(t)) |
| 398 | const deferredBuiltinTools = builtInTools.filter(t => isDeferredTool(t)) |
| 399 | |
| 400 | // Count always-loaded tools |
| 401 | const alwaysLoadedTokens = |
| 402 | alwaysLoadedTools.length > 0 |
| 403 | ? await countToolDefinitionTokens( |
| 404 | alwaysLoadedTools, |
| 405 | getToolPermissionContext, |
| 406 | agentInfo, |
| 407 | model, |
| 408 | ) |
| 409 | : 0 |
| 410 | |
| 411 | // Build per-tool breakdown for always-loaded tools (ant-only, proportional |
| 412 | // split of the bulk count based on rough schema size estimation). Excludes |
| 413 | // SkillTool since its tokens are shown in the separate Skills category. |
| 414 | let systemToolDetails: SystemToolDetail[] = [] |
| 415 | if (process.env.USER_TYPE === 'ant') { |
| 416 | const toolsForBreakdown = alwaysLoadedTools.filter( |
| 417 | t => !toolMatchesName(t, SKILL_TOOL_NAME), |
| 418 | ) |
| 419 | if (toolsForBreakdown.length > 0) { |
| 420 | const estimates = toolsForBreakdown.map(t => |
no test coverage detected