import { describe, it, expect, vi, beforeEach } from 'vitest'; const AgentManager = require('../../core/agent-manager'); // Mock logging to prevent initialization issues vi.mock('../../core/logging', () => ({ getGlobalLogManager: () => ({ initialized: false, getOrCreateSession: () => null, }), waitForGlobalLogManager: () => Promise.resolve(), })); describe('AgentManager ACP session reuse', () => { let manager; const testConfig = { clients: { 'claude-local': { type: 'process', command: 'claude', args: ['--print'], }, }, agents: { 'claude-coder': { type: 'executor', protocol: 'acp', transport: 'pipe', client: 'claude-local', prompt: './agents/coder.md', }, }, }; beforeEach(() => { manager = new AgentManager(testConfig, '/tmp/test-workdir'); // Mock hookRunner to return Promises manager.hookRunner = { run: vi.fn().mockResolvedValue(undefined), }; // Mock prompt builder manager.buildFullPrompt = vi.fn((name, task) => task); }); it('reuses session pool for repeated calls of the same agent', async () => { let callCount = 0; // Mock _runViaProtocol to bypass SessionPool and stream-executor manager._runViaProtocol = vi.fn(async (agentName, agent, resolved, fullPrompt) => { callCount++; return { agent: agentName, output: `OUTPUT:${fullPrompt}`, status: 'success' }; }); const r1 = await manager.callAgent('claude-coder', 'P1'); const r2 = await manager.callAgent('claude-coder', 'P2'); expect(r1.output).toBe('OUTPUT:P1'); expect(r2.output).toBe('OUTPUT:P2'); expect(manager._runViaProtocol).toHaveBeenCalledTimes(2); }); it('propagates transport error and calls post-task-failure hook', async () => { const transportError = new Error('Transport closed'); manager._runViaProtocol = vi.fn() .mockRejectedValueOnce(transportError); await expect(manager.callAgent('claude-coder', 'P1')).rejects.toThrow('Transport closed'); // post-task-failure hook should have been called const failureCalls = manager.hookRunner.run.mock.calls.filter( c => c[0] === 'post-task-failure' ); expect(failureCalls.length).toBe(1); }); });