import { describe, it, expect, beforeEach, vi } from 'vitest'; import { agentOutputTool } from '../../../../src/tools/task/agent_output.js'; import { getAgentManager, resetAgentManager } from '../../../../src/agent/manager.js'; // Mock AgentExecutor - 使用延迟执行让测试更可控 vi.mock('../../../../src/agent/executor.js', () => ({ AgentExecutor: vi.fn().mockImplementation(() => ({ execute: vi.fn().mockImplementation(async () => { await new Promise((r) => setTimeout(r, 50)); return { success: true, text: '任务完成结果', steps: 3, sessionId: 'test-session', }; }), })), })); describe('agentOutputTool - Agent 输出工具', () => { beforeEach(() => { vi.clearAllMocks(); resetAgentManager(); }); describe('工具定义', () => { it('有正确的名称', () => { expect(agentOutputTool.name).toBe('agent_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'); }); it('agent_id 参数是必须的', () => { expect(agentOutputTool.parameters.agent_id.required).toBe(true); }); it('block 和 timeout 参数是可选的', () => { expect(agentOutputTool.parameters.block.required).toBe(false); expect(agentOutputTool.parameters.timeout.required).toBe(false); }); }); describe('execute - 执行', () => { it('Agent 不存在时返回错误', async () => { const result = await agentOutputTool.execute({ agent_id: 'non-existent-id', }); expect(result.success).toBe(false); expect(result.error).toContain('不存在'); }); it('返回 Agent 的状态', async () => { const manager = getAgentManager(); const agentId = await manager.runInBackground( { name: 'test-agent', description: '测试', mode: 'subagent', }, '测试任务', '执行测试', { provider: 'anthropic', apiKey: 'test', model: 'test', maxTokens: 1000, systemPrompt: 'test', }, {} as any, { parentSessionId: 'parent', workdir: '/test' } ); // 立即查询(不阻塞) const result = await agentOutputTool.execute({ agent_id: agentId, block: false, }); // 应该成功返回状态(可能是 running 或 completed) expect(result.output).toBeDefined(); expect(result.metadata?.agentId).toBe(agentId); }); it('阻塞等待后返回结果', async () => { const manager = getAgentManager(); const agentId = await manager.runInBackground( { name: 'test-agent', description: '测试', mode: 'subagent', }, '测试任务', '执行测试', { provider: 'anthropic', apiKey: 'test', model: 'test', maxTokens: 1000, systemPrompt: 'test', }, {} as any, { parentSessionId: 'parent', workdir: '/test' } ); // 使用阻塞模式等待 const result = await agentOutputTool.execute({ agent_id: agentId, block: true, timeout: 5, }); // 等待后应该有确定的状态 expect(result.metadata?.status).toBeDefined(); expect(['running', 'completed', 'failed']).toContain(result.metadata?.status); }); it('返回包含正确字段的输出', async () => { const manager = getAgentManager(); const agentId = await manager.runInBackground( { name: 'test-agent', description: '测试', mode: 'subagent', }, '测试任务', '执行测试', { provider: 'anthropic', apiKey: 'test', model: 'test', maxTokens: 1000, systemPrompt: 'test', }, {} as any, { parentSessionId: 'parent', workdir: '/test' } ); // 等待完成 await new Promise((r) => setTimeout(r, 200)); const result = await agentOutputTool.execute({ agent_id: agentId, block: false, }); // 检查返回了有效结果 expect(result.output).toBeDefined(); expect(result.metadata?.agentId).toBe(agentId); expect(result.metadata?.agentName).toBe('test-agent'); // 状态应该是完成或失败(由于 mock,可能会失败) expect(['completed', 'failed']).toContain(result.metadata?.status); }); }); });