refactor(core): 重命名 agent_output 为 task_output
- 删除 agent_output.ts,新增 task_output.ts - 更新工具导出、注册和描述映射 - 更新 build/plan agent 预设的工具列表 - 更新 task 工具中的相关引用
This commit is contained in:
@@ -178,7 +178,7 @@ export const buildAgent: Omit<AgentInfo, 'name'> = {
|
|||||||
|
|
||||||
// ============ Task 子代理 ============
|
// ============ Task 子代理 ============
|
||||||
'task',
|
'task',
|
||||||
'agent_output',
|
'task_output',
|
||||||
|
|
||||||
// ============ Todo 任务管理 ============
|
// ============ Todo 任务管理 ============
|
||||||
'todowrite',
|
'todowrite',
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ export const planAgent: Omit<AgentInfo, 'name'> = {
|
|||||||
'checkpoint_diff',
|
'checkpoint_diff',
|
||||||
// Task 调用子代理
|
// Task 调用子代理
|
||||||
'task',
|
'task',
|
||||||
'agent_output',
|
'task_output',
|
||||||
// Web 搜索
|
// Web 搜索
|
||||||
'web_search',
|
'web_search',
|
||||||
'web_extract',
|
'web_extract',
|
||||||
|
|||||||
@@ -332,7 +332,7 @@ export const DEFAULT_TOOL_NAMES: ToolNameMapping = {
|
|||||||
exitPlanMode: 'exit_plan_mode',
|
exitPlanMode: 'exit_plan_mode',
|
||||||
enterPlanMode: 'enter_plan_mode',
|
enterPlanMode: 'enter_plan_mode',
|
||||||
task: 'task',
|
task: 'task',
|
||||||
agentOutput: 'agent_output',
|
taskOutput: 'task_output',
|
||||||
todoWrite: 'todowrite',
|
todoWrite: 'todowrite',
|
||||||
webSearch: 'web_search',
|
webSearch: 'web_search',
|
||||||
webExtract: 'web_extract',
|
webExtract: 'web_extract',
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ export interface ToolNameMapping {
|
|||||||
exitPlanMode: string;
|
exitPlanMode: string;
|
||||||
enterPlanMode: string;
|
enterPlanMode: string;
|
||||||
task: string;
|
task: string;
|
||||||
agentOutput: string;
|
taskOutput: string;
|
||||||
todoWrite: string;
|
todoWrite: string;
|
||||||
webSearch: string;
|
webSearch: string;
|
||||||
webExtract: string;
|
webExtract: string;
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { toolSearchTool } from './tool-search.js';
|
|||||||
import { todoWriteTool } from './todo/index.js';
|
import { todoWriteTool } from './todo/index.js';
|
||||||
|
|
||||||
// Task 工具(Agent 子任务)
|
// Task 工具(Agent 子任务)
|
||||||
import { taskTool, agentOutputTool } from './task/index.js';
|
import { taskTool, taskOutputTool } from './task/index.js';
|
||||||
|
|
||||||
// Skill 工具
|
// Skill 工具
|
||||||
import { skillTool, skillSearchTool } from './skill/index.js';
|
import { skillTool, skillSearchTool } from './skill/index.js';
|
||||||
@@ -67,7 +67,7 @@ const allToolsWithMetadata: ToolWithMetadata[] = [
|
|||||||
bashTool,
|
bashTool,
|
||||||
todoWriteTool,
|
todoWriteTool,
|
||||||
taskTool,
|
taskTool,
|
||||||
agentOutputTool,
|
taskOutputTool,
|
||||||
|
|
||||||
// Skill 工具 (deferLoading: false)
|
// Skill 工具 (deferLoading: false)
|
||||||
skillTool,
|
skillTool,
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ const TOOL_CATEGORY_MAP: Record<string, string> = {
|
|||||||
exit_plan_mode: 'plan',
|
exit_plan_mode: 'plan',
|
||||||
// task
|
// task
|
||||||
task: 'task',
|
task: 'task',
|
||||||
agent_output: 'task',
|
task_output: 'task',
|
||||||
// checkpoint
|
// checkpoint
|
||||||
checkpoint_create: 'checkpoint',
|
checkpoint_create: 'checkpoint',
|
||||||
checkpoint_list: 'checkpoint',
|
checkpoint_list: 'checkpoint',
|
||||||
|
|||||||
@@ -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,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
};
|
|
||||||
@@ -1,2 +1,2 @@
|
|||||||
export { taskTool, initTaskContext, updateTaskDescription, getTaskContext } from './task.js';
|
export { taskTool, initTaskContext, updateTaskDescription, getTaskContext } from './task.js';
|
||||||
export { agentOutputTool } from './agent_output.js';
|
export { taskOutputTool } from './task_output.js';
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ export const taskTool: ToolWithMetadata = {
|
|||||||
},
|
},
|
||||||
run_in_background: {
|
run_in_background: {
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
description: '是否后台运行。后台运行时立即返回 agentId,使用 agent_output 工具获取结果',
|
description: '是否后台运行。后台运行时立即返回 agentId,使用 task_output 工具获取结果',
|
||||||
required: false,
|
required: false,
|
||||||
},
|
},
|
||||||
images: {
|
images: {
|
||||||
@@ -248,7 +248,7 @@ export const taskTool: ToolWithMetadata = {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
success: true,
|
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: {
|
metadata: {
|
||||||
agentId,
|
agentId,
|
||||||
agent: agent.name,
|
agent: agent.name,
|
||||||
|
|||||||
+19
-19
@@ -1,5 +1,5 @@
|
|||||||
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
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';
|
import { getAgentManager, resetAgentManager } from '../../../../src/agent/manager.js';
|
||||||
|
|
||||||
// Mock AgentExecutor - 使用延迟执行让测试更可控
|
// Mock AgentExecutor - 使用延迟执行让测试更可控
|
||||||
@@ -17,7 +17,7 @@ vi.mock('../../../../src/agent/executor.js', () => ({
|
|||||||
})),
|
})),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
describe('agentOutputTool - Agent 输出工具', () => {
|
describe('taskOutputTool - Task 输出工具', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
vi.clearAllMocks();
|
vi.clearAllMocks();
|
||||||
resetAgentManager();
|
resetAgentManager();
|
||||||
@@ -25,30 +25,30 @@ describe('agentOutputTool - Agent 输出工具', () => {
|
|||||||
|
|
||||||
describe('工具定义', () => {
|
describe('工具定义', () => {
|
||||||
it('有正确的名称', () => {
|
it('有正确的名称', () => {
|
||||||
expect(agentOutputTool.name).toBe('agent_output');
|
expect(taskOutputTool.name).toBe('task_output');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('有正确的元数据', () => {
|
it('有正确的元数据', () => {
|
||||||
expect(agentOutputTool.metadata.category).toBe('agent');
|
expect(taskOutputTool.metadata.category).toBe('agent');
|
||||||
expect(agentOutputTool.metadata.keywords).toContain('agent');
|
expect(taskOutputTool.metadata.keywords).toContain('task');
|
||||||
expect(agentOutputTool.metadata.keywords).toContain('output');
|
expect(taskOutputTool.metadata.keywords).toContain('output');
|
||||||
expect(agentOutputTool.metadata.keywords).toContain('background');
|
expect(taskOutputTool.metadata.keywords).toContain('background');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('agent_id 参数是必须的', () => {
|
it('task_id 参数是必须的', () => {
|
||||||
expect(agentOutputTool.parameters.agent_id.required).toBe(true);
|
expect(taskOutputTool.parameters.task_id.required).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('block 和 timeout 参数是可选的', () => {
|
it('block 和 timeout 参数是可选的', () => {
|
||||||
expect(agentOutputTool.parameters.block.required).toBe(false);
|
expect(taskOutputTool.parameters.block.required).toBe(false);
|
||||||
expect(agentOutputTool.parameters.timeout.required).toBe(false);
|
expect(taskOutputTool.parameters.timeout.required).toBe(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('execute - 执行', () => {
|
describe('execute - 执行', () => {
|
||||||
it('Agent 不存在时返回错误', async () => {
|
it('Agent 不存在时返回错误', async () => {
|
||||||
const result = await agentOutputTool.execute({
|
const result = await taskOutputTool.execute({
|
||||||
agent_id: 'non-existent-id',
|
task_id: 'non-existent-id',
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(result.success).toBe(false);
|
expect(result.success).toBe(false);
|
||||||
@@ -77,8 +77,8 @@ describe('agentOutputTool - Agent 输出工具', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// 立即查询(不阻塞)
|
// 立即查询(不阻塞)
|
||||||
const result = await agentOutputTool.execute({
|
const result = await taskOutputTool.execute({
|
||||||
agent_id: agentId,
|
task_id: agentId,
|
||||||
block: false,
|
block: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -109,8 +109,8 @@ describe('agentOutputTool - Agent 输出工具', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// 使用阻塞模式等待
|
// 使用阻塞模式等待
|
||||||
const result = await agentOutputTool.execute({
|
const result = await taskOutputTool.execute({
|
||||||
agent_id: agentId,
|
task_id: agentId,
|
||||||
block: true,
|
block: true,
|
||||||
timeout: 5,
|
timeout: 5,
|
||||||
});
|
});
|
||||||
@@ -144,8 +144,8 @@ describe('agentOutputTool - Agent 输出工具', () => {
|
|||||||
// 等待完成
|
// 等待完成
|
||||||
await new Promise((r) => setTimeout(r, 200));
|
await new Promise((r) => setTimeout(r, 200));
|
||||||
|
|
||||||
const result = await agentOutputTool.execute({
|
const result = await taskOutputTool.execute({
|
||||||
agent_id: agentId,
|
task_id: agentId,
|
||||||
block: false,
|
block: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
Reference in New Issue
Block a user