diff options
Diffstat (limited to 'packages/server/src/tools/tool-registry.ts')
| -rw-r--r-- | packages/server/src/tools/tool-registry.ts | 187 |
1 files changed, 0 insertions, 187 deletions
diff --git a/packages/server/src/tools/tool-registry.ts b/packages/server/src/tools/tool-registry.ts deleted file mode 100644 index e241ada5..00000000 --- a/packages/server/src/tools/tool-registry.ts +++ /dev/null @@ -1,187 +0,0 @@ -/** - * @license - * Copyright 2025 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { FunctionDeclaration } from '@google/genai'; -import { Tool, ToolResult, BaseTool } from './tools.js'; -import { Config } from '../config/config.js'; -import { spawn, execSync } from 'node:child_process'; -import { discoverMcpTools } from './mcp-client.js'; -import { DiscoveredMCPTool } from './mcp-tool.js'; - -type ToolParams = Record<string, unknown>; - -export class DiscoveredTool extends BaseTool<ToolParams, ToolResult> { - constructor( - private readonly config: Config, - readonly name: string, - readonly description: string, - readonly parameterSchema: Record<string, unknown>, - ) { - const discoveryCmd = config.getToolDiscoveryCommand()!; - const callCommand = config.getToolCallCommand()!; - description += ` - -This tool was discovered from the project by executing the command \`${discoveryCmd}\` on project root. -When called, this tool will execute the command \`${callCommand} ${name}\` on project root. -Tool discovery and call commands can be configured in project or user settings. - -When called, the tool call command is executed as a subprocess. -On success, tool output is returned as a json string. -Otherwise, the following information is returned: - -Stdout: Output on stdout stream. Can be \`(empty)\` or partial. -Stderr: Output on stderr stream. Can be \`(empty)\` or partial. -Error: Error or \`(none)\` if no error was reported for the subprocess. -Exit Code: Exit code or \`(none)\` if terminated by signal. -Signal: Signal number or \`(none)\` if no signal was received. -`; - super( - name, - name, - description, - parameterSchema, - false, // isOutputMarkdown - false, // canUpdateOutput - ); - } - - async execute(params: ToolParams): Promise<ToolResult> { - const callCommand = this.config.getToolCallCommand()!; - const child = spawn(callCommand, [this.name]); - child.stdin.write(JSON.stringify(params)); - child.stdin.end(); - let stdout = ''; - let stderr = ''; - child.stdout.on('data', (data) => { - stdout += data.toString(); - }); - child.stderr.on('data', (data) => { - stderr += data.toString(); - }); - let error: Error | null = null; - child.on('error', (err: Error) => { - error = err; - }); - let code: number | null = null; - let signal: NodeJS.Signals | null = null; - child.on( - 'close', - (_code: number | null, _signal: NodeJS.Signals | null) => { - code = _code; - signal = _signal; - }, - ); - await new Promise((resolve) => child.on('close', resolve)); - - // if there is any error, non-zero exit code, signal, or stderr, return error details instead of stdout - if (error || code !== 0 || signal || stderr) { - const llmContent = [ - `Stdout: ${stdout || '(empty)'}`, - `Stderr: ${stderr || '(empty)'}`, - `Error: ${error ?? '(none)'}`, - `Exit Code: ${code ?? '(none)'}`, - `Signal: ${signal ?? '(none)'}`, - ].join('\n'); - return { - llmContent, - returnDisplay: llmContent, - }; - } - - return { - llmContent: stdout, - returnDisplay: stdout, - }; - } -} - -export class ToolRegistry { - private tools: Map<string, Tool> = new Map(); - private config: Config; - - constructor(config: Config) { - this.config = config; - } - - /** - * Registers a tool definition. - * @param tool - The tool object containing schema and execution logic. - */ - registerTool(tool: Tool): void { - if (this.tools.has(tool.name)) { - // Decide on behavior: throw error, log warning, or allow overwrite - console.warn( - `Tool with name "${tool.name}" is already registered. Overwriting.`, - ); - } - this.tools.set(tool.name, tool); - } - - /** - * Discovers tools from project, if a discovery command is configured. - * Can be called multiple times to update discovered tools. - */ - async discoverTools(): Promise<void> { - // remove any previously discovered tools - for (const tool of this.tools.values()) { - if (tool instanceof DiscoveredTool || tool instanceof DiscoveredMCPTool) { - this.tools.delete(tool.name); - } else { - // Keep manually registered tools - } - } - // discover tools using discovery command, if configured - const discoveryCmd = this.config.getToolDiscoveryCommand(); - if (discoveryCmd) { - // execute discovery command and extract function declarations - const functions: FunctionDeclaration[] = []; - for (const tool of JSON.parse(execSync(discoveryCmd).toString().trim())) { - functions.push(...tool['function_declarations']); - } - // register each function as a tool - for (const func of functions) { - this.registerTool( - new DiscoveredTool( - this.config, - func.name!, - func.description!, - func.parameters! as Record<string, unknown>, - ), - ); - } - } - // discover tools using MCP servers, if configured - await discoverMcpTools(this.config, this); - } - - /** - * Retrieves the list of tool schemas (FunctionDeclaration array). - * Extracts the declarations from the ToolListUnion structure. - * Includes discovered (vs registered) tools if configured. - * @returns An array of FunctionDeclarations. - */ - getFunctionDeclarations(): FunctionDeclaration[] { - const declarations: FunctionDeclaration[] = []; - this.tools.forEach((tool) => { - declarations.push(tool.schema); - }); - return declarations; - } - - /** - * Returns an array of all registered and discovered tool instances. - */ - getAllTools(): Tool[] { - return Array.from(this.tools.values()); - } - - /** - * Get the definition of a specific tool. - */ - getTool(name: string): Tool | undefined { - return this.tools.get(name); - } -} |
