( model: string, tools: Tools, getToolPermissionContext: () => Promise<ToolPermissionContext>, agents: AgentDefinition[], source?: string, )
| 383 | * @returns true if tool search should be enabled for this request |
| 384 | */ |
| 385 | export async function isToolSearchEnabled( |
| 386 | model: string, |
| 387 | tools: Tools, |
| 388 | getToolPermissionContext: () => Promise<ToolPermissionContext>, |
| 389 | agents: AgentDefinition[], |
| 390 | source?: string, |
| 391 | ): Promise<boolean> { |
| 392 | const mcpToolCount = count(tools, t => t.isMcp) |
| 393 | |
| 394 | // Helper to log the mode decision event |
| 395 | function logModeDecision( |
| 396 | enabled: boolean, |
| 397 | mode: ToolSearchMode, |
| 398 | reason: string, |
| 399 | extraProps?: Record<string, number>, |
| 400 | ): void { |
| 401 | logEvent('tengu_tool_search_mode_decision', { |
| 402 | enabled, |
| 403 | mode: mode as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, |
| 404 | reason: |
| 405 | reason as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, |
| 406 | // Log the actual model being checked, not the session's main model. |
| 407 | // This is important for debugging subagent tool search decisions where |
| 408 | // the subagent model (e.g., haiku) differs from the session model (e.g., opus). |
| 409 | checkedModel: |
| 410 | model as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, |
| 411 | mcpToolCount, |
| 412 | userType: (process.env.USER_TYPE ?? |
| 413 | 'external') as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, |
| 414 | ...extraProps, |
| 415 | }) |
| 416 | } |
| 417 | |
| 418 | // Check if model supports tool_reference |
| 419 | if (!modelSupportsToolReference(model)) { |
| 420 | logForDebugging( |
| 421 | `Tool search disabled for model '${model}': model does not support tool_reference blocks. ` + |
| 422 | `This feature is only available on Claude Sonnet 4+, Opus 4+, and newer models.`, |
| 423 | ) |
| 424 | logModeDecision(false, 'standard', 'model_unsupported') |
| 425 | return false |
| 426 | } |
| 427 | |
| 428 | // Check if ToolSearchTool is available (respects disallowedTools) |
| 429 | if (!isToolSearchToolAvailable(tools)) { |
| 430 | logForDebugging( |
| 431 | `Tool search disabled: ToolSearchTool is not available (may have been disallowed via disallowedTools).`, |
| 432 | ) |
| 433 | logModeDecision(false, 'standard', 'mcp_search_unavailable') |
| 434 | return false |
| 435 | } |
| 436 | |
| 437 | const mode = getToolSearchMode() |
| 438 | |
| 439 | switch (mode) { |
| 440 | case 'tst': |
| 441 | logModeDecision(true, mode, 'tst_enabled') |
| 442 | return true |
no test coverage detected