/** * @license * Copyright 2025 Google LLC * SPDX-License-Identifier: Apache-2.0 */ import type { AnyDeclarativeTool, AnyToolInvocation } from '../index.js'; import { isTool } from '../index.js'; const SHELL_TOOL_NAMES = ['run_shell_command', 'ShellTool']; /** * Checks if a tool invocation matches any of a list of patterns. * * @param toolOrToolName The tool object or the name of the tool being invoked. * @param invocation The invocation object for the tool. * @param patterns A list of patterns to match against. * Patterns can be: * - A tool name (e.g., "ReadFileTool") to match any invocation of that tool. * - A tool name with a prefix (e.g., "ShellTool(git status)") to match * invocations where the arguments start with that prefix. * @returns True if the invocation matches any pattern, false otherwise. */ export function doesToolInvocationMatch( toolOrToolName: AnyDeclarativeTool | string, invocation: AnyToolInvocation, patterns: string[], ): boolean { let toolNames: string[]; if (isTool(toolOrToolName)) { toolNames = [toolOrToolName.name, toolOrToolName.constructor.name]; } else { toolNames = [toolOrToolName as string]; } if (toolNames.some((name) => SHELL_TOOL_NAMES.includes(name))) { toolNames = [...new Set([...toolNames, ...SHELL_TOOL_NAMES])]; } for (const pattern of patterns) { const openParen = pattern.indexOf('('); if (openParen === -1) { // No arguments, just a tool name if (toolNames.includes(pattern)) { return true; } continue; } const patternToolName = pattern.substring(0, openParen); if (!toolNames.includes(patternToolName)) { continue; } if (!pattern.endsWith(')')) { continue; } const argPattern = pattern.substring(openParen + 1, pattern.length - 1); if ( 'command' in invocation.params && toolNames.includes('run_shell_command') ) { const argValue = String( (invocation.params as { command: string }).command, ); if (argValue === argPattern || argValue.startsWith(argPattern + ' ')) { return true; } } } return false; }