| import { describe, it, expect, vi } from 'vitest'; |
| import type { ConversationNode } from '@/lib/llm/multi-agent-orchestrator'; |
|
|
| const mockVfs = { |
| init: vi.fn(), |
| readFile: vi.fn(), |
| fileExists: vi.fn(), |
| }; |
|
|
| vi.mock('@/lib/vfs', () => ({ |
| vfs: mockVfs, |
| })); |
|
|
| function makeConversation(messages: Array<{ |
| role: string; |
| content?: string; |
| tool_calls?: Array<{ id: string; function: { name: string; arguments: string } }>; |
| tool_call_id?: string; |
| }>): ConversationNode[] { |
| return [{ |
| id: 'test-node', |
| agent_type: 'orchestrator', |
| messages: messages as any, |
| metadata: { started_at: Date.now(), cost: 0, status: 'completed' }, |
| }]; |
| } |
|
|
| describe('any_of assertion', () => { |
| it('passes when first sub-assertion matches', async () => { |
| const { runAssertions } = await import('../assertion-runner'); |
| const conversation = makeConversation([ |
| { |
| role: 'assistant', |
| tool_calls: [{ |
| id: 'tc1', |
| function: { name: 'bash', arguments: '{"command": "propose-create"}' }, |
| }], |
| }, |
| { role: 'tool', content: 'ok', tool_call_id: 'tc1' }, |
| ]); |
|
|
| const results = await runAssertions('test', conversation, [{ |
| type: 'any_of', |
| description: 'propose or ask', |
| assertions: [ |
| { type: 'tool_args_match', toolName: 'bash', pattern: 'propose-create', description: 'propose' }, |
| { type: 'output_matches', pattern: '\\?', description: 'question' }, |
| ], |
| }]); |
|
|
| expect(results).toHaveLength(1); |
| expect(results[0].passed).toBe(true); |
| expect(results[0].actual).toContain('propose-create'); |
| }); |
|
|
| it('passes when second sub-assertion matches', async () => { |
| const { runAssertions } = await import('../assertion-runner'); |
| const conversation = makeConversation([ |
| { role: 'assistant', content: 'What kind of site do you want?' }, |
| ]); |
|
|
| const results = await runAssertions('test', conversation, [{ |
| type: 'any_of', |
| description: 'propose or ask', |
| assertions: [ |
| { type: 'tool_args_match', toolName: 'bash', pattern: 'propose-create', description: 'propose' }, |
| { type: 'output_matches', pattern: '\\?', description: 'question' }, |
| ], |
| }]); |
|
|
| expect(results).toHaveLength(1); |
| expect(results[0].passed).toBe(true); |
| }); |
|
|
| it('fails and joins all sub-assertion failures', async () => { |
| const { runAssertions } = await import('../assertion-runner'); |
| const conversation = makeConversation([ |
| { role: 'assistant', content: 'I will build the site now.' }, |
| ]); |
|
|
| const results = await runAssertions('test', conversation, [{ |
| type: 'any_of', |
| description: 'propose or ask', |
| assertions: [ |
| { type: 'tool_args_match', toolName: 'bash', pattern: 'propose-create', description: 'propose' }, |
| { type: 'output_matches', pattern: '\\?', description: 'question' }, |
| ], |
| }]); |
|
|
| expect(results).toHaveLength(1); |
| expect(results[0].passed).toBe(false); |
| expect(results[0].actual).toContain('|'); |
| expect(results[0].actual).toContain('propose'); |
| expect(results[0].actual).toContain('question'); |
| }); |
|
|
| }); |
|
|