/** * Tool Registry — Master Agent 工具注册中心 * * 为 Master Agent(Claude CLI 会话)提供可调用的工具集。 * 工具以 JSON Schema 格式定义,注入到 Master 的 system prompt 中。 * Master 通过 [TOOL_CALL:] 格式调用工具,系统解析并执行。 */ class ToolRegistry { constructor() { /** @type {Map} */ this.tools = new Map(); } /** * 注册一个工具 * @param {ToolDefinition} tool */ register(tool) { if (!tool.name || !tool.execute) { throw new Error(`Tool must have name and execute: ${JSON.stringify(tool)}`); } this.tools.set(tool.name, tool); } /** * 批量注册工具 * @param {ToolDefinition[]} tools */ registerAll(tools) { for (const tool of tools) { this.register(tool); } } /** * 获取工具 * @param {string} name * @returns {ToolDefinition|undefined} */ get(name) { return this.tools.get(name); } /** * 执行工具调用 * @param {string} name - 工具名称 * @param {object} params - 调用参数 * @param {object} context - 执行上下文 { agentManager, workDir, ... } * @returns {Promise} 工具执行结果 */ async execute(name, params, context) { const tool = this.tools.get(name); if (!tool) { return { error: `Unknown tool: ${name}`, status: 'error' }; } try { const result = await tool.execute(params, context); return { result, status: 'success' }; } catch (err) { return { error: err.message, status: 'error' }; } } /** * 获取所有工具的 schema(用于注入 system prompt) * @returns {object[]} */ getSchemas() { return Array.from(this.tools.values()).map(t => ({ name: t.name, description: t.description, parameters: t.parameters || {}, })); } /** * 生成工具描述文本(注入 Master system prompt) * @returns {string} */ generateToolPrompt() { const schemas = this.getSchemas(); if (schemas.length === 0) return ''; const toolDescriptions = schemas.map(s => { const params = Object.entries(s.parameters.properties || {}) .map(([k, v]) => { const required = (s.parameters.required || []).includes(k); return ` - ${k} (${v.type}${required ? ', 必需' : ', 可选'}): ${v.description || ''}`; }) .join('\n'); return `### ${s.name}\n${s.description}\n\n**参数:**\n${params}`; }).join('\n\n---\n\n'); return `\ ## 可用工具 你可以通过以下格式调用工具: \`\`\` [TOOL_CALL: tool_name] { "param1": "value1", "param2": "value2" } [/TOOL_CALL] \`\`\` ${toolDescriptions}`; } /** * 解析 Master 输出中的工具调用 * @param {string} output - Master 输出文本 * @returns {Array<{tool: string, params: object}>} */ static parseToolCalls(output) { const regex = /\[TOOL_CALL:\s*([^\]]+)\]\s*([\s\S]*?)\[\/TOOL_CALL\]/g; const calls = []; let match; while ((match = regex.exec(output)) !== null) { const toolName = match[1].trim(); const rawParams = match[2].trim(); let params = {}; if (rawParams) { try { params = JSON.parse(rawParams); } catch { // 如果不是 JSON,尝试作为纯文本 task params = { task: rawParams }; } } calls.push({ tool: toolName, params }); } return calls; } } module.exports = { ToolRegistry };