import { describe, it, expect, vi, beforeEach } from 'vitest'; import type { ChatMessageSchema } from '@insforge/shared-schemas'; // Mock dependencies before importing the service vi.mock('../../src/providers/ai/openrouter.provider.js', () => ({ OpenRouterProvider: { getInstance: () => ({}) }, })); vi.mock('../../src/utils/logger.js', () => ({ default: { error: vi.fn(), info: vi.fn(), warn: vi.fn() }, })); describe('ChatCompletionService - formatMessages', () => { // eslint-disable-next-line @typescript-eslint/no-explicit-any let service: any; beforeEach(async () => { const mod = await import('../../src/services/ai/chat-completion.service.js'); service = mod.ChatCompletionService.getInstance(); }); it('formats tool role messages with tool_call_id', () => { const messages: ChatMessageSchema[] = [ { role: 'tool', content: '{"temp":"22°C"}', tool_call_id: 'call_abc123', }, ]; const result = service.formatMessages(messages); expect(result).toHaveLength(1); expect(result[0]).toEqual({ role: 'tool', content: '{"temp":"22°C"}', tool_call_id: 'call_abc123', }); }); it('formats assistant messages with tool_calls', () => { const messages: ChatMessageSchema[] = [ { role: 'assistant', content: null, tool_calls: [ { id: 'call_abc123', type: 'function', function: { name: 'get_weather', arguments: '{"city":"Tokyo"}' }, }, ], }, ]; const result = service.formatMessages(messages); expect(result).toHaveLength(1); expect(result[0].role).toBe('assistant'); expect(result[0].content).toBeNull(); expect(result[0].tool_calls).toEqual([ { id: 'call_abc123', type: 'function', function: { name: 'get_weather', arguments: '{"city":"Tokyo"}' }, }, ]); }); it('formats regular user messages unchanged', () => { const messages: ChatMessageSchema[] = [{ role: 'user', content: 'Hello' }]; const result = service.formatMessages(messages); expect(result).toHaveLength(1); expect(result[0]).toEqual({ role: 'user', content: 'Hello' }); }); it('prepends system prompt when provided', () => { const messages: ChatMessageSchema[] = [{ role: 'user', content: 'Hi' }]; const result = service.formatMessages(messages, 'You are helpful.'); expect(result).toHaveLength(2); expect(result[0]).toEqual({ role: 'system', content: 'You are helpful.' }); expect(result[1]).toEqual({ role: 'user', content: 'Hi' }); }); it('handles a full multi-turn tool calling conversation', () => { const messages: ChatMessageSchema[] = [ { role: 'user', content: 'What is the weather in Tokyo?' }, { role: 'assistant', content: null, tool_calls: [ { id: 'call_1', type: 'function', function: { name: 'get_weather', arguments: '{"city":"Tokyo"}' }, }, ], }, { role: 'tool', content: '{"temp":"22°C","condition":"sunny"}', tool_call_id: 'call_1', }, ]; const result = service.formatMessages(messages); expect(result).toHaveLength(3); expect(result[0].role).toBe('user'); expect(result[1].role).toBe('assistant'); expect(result[1].tool_calls).toBeDefined(); expect(result[2].role).toBe('tool'); expect(result[2].tool_call_id).toBe('call_1'); }); it('throws on tool message with empty tool_call_id', () => { const messages: ChatMessageSchema[] = [ { role: 'tool', content: 'result', }, ]; expect(() => service.formatMessages(messages)).toThrow( 'Tool message is missing required tool_call_id' ); }); });