From f55bd8f52606203f9888c69e6928882c61bd423a Mon Sep 17 00:00:00 2001 From: kurihada Date: Wed, 17 Dec 2025 14:15:49 +0800 Subject: [PATCH] =?UTF-8?q?refactor(core):=20=E9=87=8D=E5=91=BD=E5=90=8D?= =?UTF-8?q?=20agent=5Foutput=20=E4=B8=BA=20task=5Foutput?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 删除 agent_output.ts,新增 task_output.ts - 更新工具导出、注册和描述映射 - 更新 build/plan agent 预设的工具列表 - 更新 task 工具中的相关引用 --- packages/core/src/agent/presets/build.ts | 2 +- packages/core/src/agent/presets/plan.ts | 2 +- packages/core/src/template/renderer.ts | 2 +- packages/core/src/template/types.ts | 2 +- packages/core/src/tools/index.ts | 4 +- packages/core/src/tools/load_description.ts | 2 +- packages/core/src/tools/task/agent_output.ts | 132 ------------------ packages/core/src/tools/task/index.ts | 2 +- packages/core/src/tools/task/task.ts | 4 +- ...ent_output.test.ts => task_output.test.ts} | 38 ++--- 10 files changed, 29 insertions(+), 161 deletions(-) delete mode 100644 packages/core/src/tools/task/agent_output.ts rename packages/core/tests/unit/tools/task/{agent_output.test.ts => task_output.test.ts} (78%) diff --git a/packages/core/src/agent/presets/build.ts b/packages/core/src/agent/presets/build.ts index f0f9e50..a9a32da 100644 --- a/packages/core/src/agent/presets/build.ts +++ b/packages/core/src/agent/presets/build.ts @@ -178,7 +178,7 @@ export const buildAgent: Omit = { // ============ Task 子代理 ============ 'task', - 'agent_output', + 'task_output', // ============ Todo 任务管理 ============ 'todowrite', diff --git a/packages/core/src/agent/presets/plan.ts b/packages/core/src/agent/presets/plan.ts index 54f3a22..fd752e4 100644 --- a/packages/core/src/agent/presets/plan.ts +++ b/packages/core/src/agent/presets/plan.ts @@ -103,7 +103,7 @@ export const planAgent: Omit = { 'checkpoint_diff', // Task 调用子代理 'task', - 'agent_output', + 'task_output', // Web 搜索 'web_search', 'web_extract', diff --git a/packages/core/src/template/renderer.ts b/packages/core/src/template/renderer.ts index 1cc614e..9c1da08 100644 --- a/packages/core/src/template/renderer.ts +++ b/packages/core/src/template/renderer.ts @@ -332,7 +332,7 @@ export const DEFAULT_TOOL_NAMES: ToolNameMapping = { exitPlanMode: 'exit_plan_mode', enterPlanMode: 'enter_plan_mode', task: 'task', - agentOutput: 'agent_output', + taskOutput: 'task_output', todoWrite: 'todowrite', webSearch: 'web_search', webExtract: 'web_extract', diff --git a/packages/core/src/template/types.ts b/packages/core/src/template/types.ts index de00daf..4b186a1 100644 --- a/packages/core/src/template/types.ts +++ b/packages/core/src/template/types.ts @@ -78,7 +78,7 @@ export interface ToolNameMapping { exitPlanMode: string; enterPlanMode: string; task: string; - agentOutput: string; + taskOutput: string; todoWrite: string; webSearch: string; webExtract: string; diff --git a/packages/core/src/tools/index.ts b/packages/core/src/tools/index.ts index 42464fb..dbae134 100644 --- a/packages/core/src/tools/index.ts +++ b/packages/core/src/tools/index.ts @@ -9,7 +9,7 @@ import { toolSearchTool } from './tool-search.js'; import { todoWriteTool } from './todo/index.js'; // Task 工具(Agent 子任务) -import { taskTool, agentOutputTool } from './task/index.js'; +import { taskTool, taskOutputTool } from './task/index.js'; // Skill 工具 import { skillTool, skillSearchTool } from './skill/index.js'; @@ -67,7 +67,7 @@ const allToolsWithMetadata: ToolWithMetadata[] = [ bashTool, todoWriteTool, taskTool, - agentOutputTool, + taskOutputTool, // Skill 工具 (deferLoading: false) skillTool, diff --git a/packages/core/src/tools/load_description.ts b/packages/core/src/tools/load_description.ts index ff041d2..4330d82 100644 --- a/packages/core/src/tools/load_description.ts +++ b/packages/core/src/tools/load_description.ts @@ -38,7 +38,7 @@ const TOOL_CATEGORY_MAP: Record = { exit_plan_mode: 'plan', // task task: 'task', - agent_output: 'task', + task_output: 'task', // checkpoint checkpoint_create: 'checkpoint', checkpoint_list: 'checkpoint', diff --git a/packages/core/src/tools/task/agent_output.ts b/packages/core/src/tools/task/agent_output.ts deleted file mode 100644 index b28c105..0000000 --- a/packages/core/src/tools/task/agent_output.ts +++ /dev/null @@ -1,132 +0,0 @@ -import type { ToolWithMetadata } from '../types.js'; -import { getAgentManager } from '../../agent/manager.js'; - -/** - * Agent Output 工具 - * 用于获取后台 Agent 的执行结果 - */ -export const agentOutputTool: ToolWithMetadata = { - name: 'agent_output', - description: `获取后台运行的 Agent 执行结果。 - -当使用 task 工具的 run_in_background 参数启动后台 Agent 后, -使用此工具查询执行状态和结果。 - -使用示例: -- 查询结果(阻塞等待): agent_output({ agent_id: "abc123" }) -- 检查状态(不阻塞): agent_output({ agent_id: "abc123", block: false }) -- 设置超时: agent_output({ agent_id: "abc123", timeout: 60 })`, - parameters: { - agent_id: { - type: 'string', - description: 'Agent ID(由 task 工具返回)', - required: true, - }, - block: { - type: 'boolean', - description: '是否阻塞等待结果完成(默认 true)。设为 false 可立即获取当前状态', - required: false, - }, - timeout: { - type: 'number', - description: '等待超时时间(秒),默认 150,最大 300', - required: false, - }, - }, - metadata: { - name: 'agent_output', - category: 'agent', - description: '获取后台 Agent 执行结果', - keywords: ['agent', 'output', 'result', 'background', '结果', '后台', '查询'], - deferLoading: false, // 核心工具,始终加载 - }, - async execute(params) { - const { - agent_id, - block = true, - timeout = 150, - } = params as { - agent_id: string; - block?: boolean; - timeout?: number; - }; - - const agentManager = getAgentManager(); - - // 验证超时参数 - const effectiveTimeout = Math.min(Math.max(timeout, 1), 300); - - // 获取 Agent 输出 - const agent = await agentManager.getAgentOutput(agent_id, block, effectiveTimeout); - - if (!agent) { - return { - success: false, - output: '', - error: `Agent ${agent_id} 不存在。请检查 agent_id 是否正确。`, - }; - } - - // 根据状态返回不同结果 - if (agent.status === 'running') { - const runningTime = Math.round((Date.now() - agent.startedAt.getTime()) / 1000); - return { - success: true, - output: `Agent ${agent_id} 仍在运行中...\n` + - `- 类型: ${agent.agentName}\n` + - `- 任务: ${agent.description}\n` + - `- 已运行: ${runningTime} 秒\n\n` + - `稍后再次调用 agent_output 查询结果,或使用 block: true 等待完成。`, - metadata: { - agentId: agent.id, - status: 'running', - agentName: agent.agentName, - runningTime, - }, - }; - } - - if (agent.status === 'failed') { - const duration = agent.completedAt - ? Math.round((agent.completedAt.getTime() - agent.startedAt.getTime()) / 1000) - : 0; - return { - success: false, - output: '', - error: `Agent ${agent_id} 执行失败:\n` + - `- 类型: ${agent.agentName}\n` + - `- 任务: ${agent.description}\n` + - `- 耗时: ${duration} 秒\n` + - `- 错误: ${agent.error || '未知错误'}`, - metadata: { - agentId: agent.id, - status: 'failed', - agentName: agent.agentName, - duration, - }, - }; - } - - // completed - const duration = agent.completedAt - ? Math.round((agent.completedAt.getTime() - agent.startedAt.getTime()) / 1000) - : 0; - - return { - success: true, - output: `## Agent ${agent_id} 执行完成\n\n` + - `- 类型: ${agent.agentName}\n` + - `- 任务: ${agent.description}\n` + - `- 耗时: ${duration} 秒\n` + - `- 步数: ${agent.steps || 0}\n\n` + - `### 结果\n\n${agent.result || '(无输出)'}`, - metadata: { - agentId: agent.id, - status: 'completed', - agentName: agent.agentName, - duration, - steps: agent.steps, - }, - }; - }, -}; diff --git a/packages/core/src/tools/task/index.ts b/packages/core/src/tools/task/index.ts index cadf427..df984ce 100644 --- a/packages/core/src/tools/task/index.ts +++ b/packages/core/src/tools/task/index.ts @@ -1,2 +1,2 @@ export { taskTool, initTaskContext, updateTaskDescription, getTaskContext } from './task.js'; -export { agentOutputTool } from './agent_output.js'; +export { taskOutputTool } from './task_output.js'; diff --git a/packages/core/src/tools/task/task.ts b/packages/core/src/tools/task/task.ts index baf8ac4..1f74607 100644 --- a/packages/core/src/tools/task/task.ts +++ b/packages/core/src/tools/task/task.ts @@ -128,7 +128,7 @@ export const taskTool: ToolWithMetadata = { }, run_in_background: { type: 'boolean', - description: '是否后台运行。后台运行时立即返回 agentId,使用 agent_output 工具获取结果', + description: '是否后台运行。后台运行时立即返回 agentId,使用 task_output 工具获取结果', required: false, }, images: { @@ -248,7 +248,7 @@ export const taskTool: ToolWithMetadata = { return { success: true, - output: `Agent ${agentId} 已在后台启动 (@${agent.name})。\n使用 agent_output 工具查询结果: agent_output({ agent_id: "${agentId}" })`, + output: `Agent ${agentId} 已在后台启动 (@${agent.name})。\n使用 task_output 工具查询结果: task_output({ agent_id: "${agentId}" })`, metadata: { agentId, agent: agent.name, diff --git a/packages/core/tests/unit/tools/task/agent_output.test.ts b/packages/core/tests/unit/tools/task/task_output.test.ts similarity index 78% rename from packages/core/tests/unit/tools/task/agent_output.test.ts rename to packages/core/tests/unit/tools/task/task_output.test.ts index 02aa251..710c9ee 100644 --- a/packages/core/tests/unit/tools/task/agent_output.test.ts +++ b/packages/core/tests/unit/tools/task/task_output.test.ts @@ -1,5 +1,5 @@ import { describe, it, expect, beforeEach, vi } from 'vitest'; -import { agentOutputTool } from '../../../../src/tools/task/agent_output.js'; +import { taskOutputTool } from '../../../../src/tools/task/task_output.js'; import { getAgentManager, resetAgentManager } from '../../../../src/agent/manager.js'; // Mock AgentExecutor - 使用延迟执行让测试更可控 @@ -17,7 +17,7 @@ vi.mock('../../../../src/agent/executor.js', () => ({ })), })); -describe('agentOutputTool - Agent 输出工具', () => { +describe('taskOutputTool - Task 输出工具', () => { beforeEach(() => { vi.clearAllMocks(); resetAgentManager(); @@ -25,30 +25,30 @@ describe('agentOutputTool - Agent 输出工具', () => { describe('工具定义', () => { it('有正确的名称', () => { - expect(agentOutputTool.name).toBe('agent_output'); + expect(taskOutputTool.name).toBe('task_output'); }); it('有正确的元数据', () => { - expect(agentOutputTool.metadata.category).toBe('agent'); - expect(agentOutputTool.metadata.keywords).toContain('agent'); - expect(agentOutputTool.metadata.keywords).toContain('output'); - expect(agentOutputTool.metadata.keywords).toContain('background'); + expect(taskOutputTool.metadata.category).toBe('agent'); + expect(taskOutputTool.metadata.keywords).toContain('task'); + expect(taskOutputTool.metadata.keywords).toContain('output'); + expect(taskOutputTool.metadata.keywords).toContain('background'); }); - it('agent_id 参数是必须的', () => { - expect(agentOutputTool.parameters.agent_id.required).toBe(true); + it('task_id 参数是必须的', () => { + expect(taskOutputTool.parameters.task_id.required).toBe(true); }); it('block 和 timeout 参数是可选的', () => { - expect(agentOutputTool.parameters.block.required).toBe(false); - expect(agentOutputTool.parameters.timeout.required).toBe(false); + expect(taskOutputTool.parameters.block.required).toBe(false); + expect(taskOutputTool.parameters.timeout.required).toBe(false); }); }); describe('execute - 执行', () => { it('Agent 不存在时返回错误', async () => { - const result = await agentOutputTool.execute({ - agent_id: 'non-existent-id', + const result = await taskOutputTool.execute({ + task_id: 'non-existent-id', }); expect(result.success).toBe(false); @@ -77,8 +77,8 @@ describe('agentOutputTool - Agent 输出工具', () => { ); // 立即查询(不阻塞) - const result = await agentOutputTool.execute({ - agent_id: agentId, + const result = await taskOutputTool.execute({ + task_id: agentId, block: false, }); @@ -109,8 +109,8 @@ describe('agentOutputTool - Agent 输出工具', () => { ); // 使用阻塞模式等待 - const result = await agentOutputTool.execute({ - agent_id: agentId, + const result = await taskOutputTool.execute({ + task_id: agentId, block: true, timeout: 5, }); @@ -144,8 +144,8 @@ describe('agentOutputTool - Agent 输出工具', () => { // 等待完成 await new Promise((r) => setTimeout(r, 200)); - const result = await agentOutputTool.execute({ - agent_id: agentId, + const result = await taskOutputTool.execute({ + task_id: agentId, block: false, });