diff --git a/src/agent/mock-manager.test.ts b/src/agent/mock-manager.test.ts index c52a60b..c7aecbd 100644 --- a/src/agent/mock-manager.test.ts +++ b/src/agent/mock-manager.test.ts @@ -262,8 +262,8 @@ describe('MockAgentManager', () => { const waitingAgent = await manager.get(agent.id); expect(waitingAgent?.status).toBe('waiting_for_input'); - // Resume the agent - await manager.resume(agent.id, 'Continue with this input'); + // Resume the agent with answers map + await manager.resume(agent.id, { q1: 'Continue with this input' }); // Check agent:resumed event emitted const resumedEvent = eventBus.emittedEvents.find((e) => e.type === 'agent:resumed'); @@ -292,13 +292,13 @@ describe('MockAgentManager', () => { prompt: 'Work', }); - await expect(manager.resume(agent.id, 'input')).rejects.toThrow( + await expect(manager.resume(agent.id, { q1: 'input' })).rejects.toThrow( 'is not waiting for input' ); }); it('should throw if agent not found', async () => { - await expect(manager.resume('non-existent-id', 'input')).rejects.toThrow( + await expect(manager.resume('non-existent-id', { q1: 'input' })).rejects.toThrow( 'not found' ); }); @@ -668,8 +668,8 @@ describe('MockAgentManager', () => { expect(pendingBefore).not.toBeNull(); expect(pendingBefore?.questions[0].question).toBe('Need your input'); - // Resume the agent - await manager.resume(agent.id, 'Option A'); + // Resume the agent with answers map + await manager.resume(agent.id, { q1: 'Option A' }); // Pending questions should be cleared const pendingAfter = await manager.getPendingQuestions(agent.id); @@ -688,5 +688,69 @@ describe('MockAgentManager', () => { const pending = await manager.getPendingQuestions(agent.id); expect(pending).toBeNull(); }); + + it('handles multiple questions in single scenario', async () => { + manager.setScenario('multi-q-agent', { + status: 'questions', + questions: [ + { + id: 'q1', + question: 'Which database should we use?', + options: [ + { label: 'PostgreSQL', description: 'Full-featured relational DB' }, + { label: 'SQLite', description: 'Lightweight embedded DB' }, + ], + }, + { + id: 'q2', + question: 'Which ORM do you prefer?', + options: [ + { label: 'Drizzle', description: 'TypeScript-first ORM' }, + { label: 'Prisma', description: 'Popular Node.js ORM' }, + ], + }, + { + id: 'q3', + question: 'Any additional notes?', + // No options - free-form text question + }, + ], + }); + + const agent = await manager.spawn({ name: 'multi-q-agent', taskId: 'task-1', prompt: 'test' }); + await vi.runAllTimersAsync(); + + // Check status + const updated = await manager.get(agent.id); + expect(updated?.status).toBe('waiting_for_input'); + + // Check event has all questions + const waitingEvent = eventBus.emittedEvents.find((e) => e.type === 'agent:waiting'); + expect(waitingEvent).toBeDefined(); + expect((waitingEvent as any).payload.questions).toHaveLength(3); + expect((waitingEvent as any).payload.questions[0].id).toBe('q1'); + expect((waitingEvent as any).payload.questions[1].id).toBe('q2'); + expect((waitingEvent as any).payload.questions[2].id).toBe('q3'); + + // Check pending questions retrieval + const pending = await manager.getPendingQuestions(agent.id); + expect(pending?.questions).toHaveLength(3); + expect(pending?.questions[0].question).toBe('Which database should we use?'); + expect(pending?.questions[1].question).toBe('Which ORM do you prefer?'); + expect(pending?.questions[2].question).toBe('Any additional notes?'); + expect(pending?.questions[2].options).toBeUndefined(); + + // Resume with answers to all questions + await manager.resume(agent.id, { q1: 'PostgreSQL', q2: 'Drizzle', q3: 'Use WAL mode' }); + await vi.runAllTimersAsync(); + + // Agent should complete + const completed = await manager.get(agent.id); + expect(completed?.status).toBe('idle'); + + // Pending questions should be cleared + const clearedPending = await manager.getPendingQuestions(agent.id); + expect(clearedPending).toBeNull(); + }); }); }); diff --git a/src/agent/mock-manager.ts b/src/agent/mock-manager.ts index 0a15c5d..b29ed40 100644 --- a/src/agent/mock-manager.ts +++ b/src/agent/mock-manager.ts @@ -330,8 +330,11 @@ export class MockAgentManager implements AgentManager { * * Re-runs the scenario for the resumed agent. Emits agent:resumed event. * Agent must be in 'waiting_for_input' status. + * + * @param agentId - Agent to resume + * @param answers - Map of question ID to user's answer */ - async resume(agentId: string, prompt: string): Promise { + async resume(agentId: string, answers: Record): Promise { const record = this.agents.get(agentId); if (!record) { throw new Error(`Agent '${agentId}' not found`);