import { describe, it, expect } from 'vitest'; import type { ConversationMessage } from '@automaker/types'; import { extractTextFromContent, normalizeContentBlocks, formatHistoryAsText, convertHistoryToMessages, } from '../src/conversation-utils'; describe('conversation-utils.ts', () => { describe('extractTextFromContent', () => { it('should extract text from string content', () => { const content = 'Hello, world!'; const result = extractTextFromContent(content); expect(result).toBe('Hello, world!'); }); it('should extract text from array content with text blocks', () => { const content = [ { type: 'text', text: 'First block' }, { type: 'text', text: 'Second block' }, ]; const result = extractTextFromContent(content); expect(result).toBe('First block\nSecond block'); }); it('should filter out non-text blocks', () => { const content = [ { type: 'text', text: 'Text block' }, { type: 'image', source: { data: '...' } }, { type: 'text', text: 'Another text' }, ]; const result = extractTextFromContent(content); expect(result).toBe('Text block\nAnother text'); }); it('should handle empty text blocks', () => { const content = [ { type: 'text', text: 'First' }, { type: 'text' }, { type: 'text', text: 'Third' }, ]; const result = extractTextFromContent(content); expect(result).toBe('First\n\nThird'); }); it('should return empty string for array with only non-text blocks', () => { const content = [ { type: 'image', source: {} }, { type: 'tool_use', source: {} }, ]; const result = extractTextFromContent(content); expect(result).toBe(''); }); it('should return empty string for empty array', () => { const content: Array<{ type: string; text?: string }> = []; const result = extractTextFromContent(content); expect(result).toBe(''); }); }); describe('normalizeContentBlocks', () => { it('should convert string to array of text blocks', () => { const content = 'Simple text'; const result = normalizeContentBlocks(content); expect(result).toEqual([{ type: 'text', text: 'Simple text' }]); }); it('should return array as-is', () => { const content = [ { type: 'text', text: 'First' }, { type: 'image', source: {} }, ]; const result = normalizeContentBlocks(content); expect(result).toBe(content); expect(result).toEqual(content); }); it('should handle empty string', () => { const content = ''; const result = normalizeContentBlocks(content); expect(result).toEqual([{ type: 'text', text: '' }]); }); it('should handle multiline string', () => { const content = 'Line 1\nLine 2\nLine 3'; const result = normalizeContentBlocks(content); expect(result).toEqual([{ type: 'text', text: 'Line 1\nLine 2\nLine 3' }]); }); }); describe('formatHistoryAsText', () => { it('should format empty history as empty string', () => { const history: ConversationMessage[] = []; const result = formatHistoryAsText(history); expect(result).toBe(''); }); it('should format single user message', () => { const history: ConversationMessage[] = [{ role: 'user', content: 'Hello!' }]; const result = formatHistoryAsText(history); expect(result).toBe('Previous conversation:\n\nUser: Hello!\n\n---\n\n'); }); it('should format single assistant message', () => { const history: ConversationMessage[] = [{ role: 'assistant', content: 'Hi there!' }]; const result = formatHistoryAsText(history); expect(result).toBe('Previous conversation:\n\nAssistant: Hi there!\n\n---\n\n'); }); it('should format conversation with multiple messages', () => { const history: ConversationMessage[] = [ { role: 'user', content: "What's 2+2?" }, { role: 'assistant', content: 'The answer is 4.' }, { role: 'user', content: 'Thanks!' }, ]; const result = formatHistoryAsText(history); expect(result).toBe( 'Previous conversation:\n\n' + "User: What's 2+2?\n\n" + 'Assistant: The answer is 4.\n\n' + 'User: Thanks!\n\n' + '---\n\n' ); }); it('should handle array content by extracting text', () => { const history: ConversationMessage[] = [ { role: 'user', content: [ { type: 'text', text: 'First part' }, { type: 'text', text: 'Second part' }, ], }, ]; const result = formatHistoryAsText(history); expect(result).toBe('Previous conversation:\n\nUser: First part\nSecond part\n\n---\n\n'); }); it('should handle mixed string and array content', () => { const history: ConversationMessage[] = [ { role: 'user', content: 'String message' }, { role: 'assistant', content: [{ type: 'text', text: 'Array message' }], }, ]; const result = formatHistoryAsText(history); expect(result).toContain('User: String message'); expect(result).toContain('Assistant: Array message'); }); }); describe('convertHistoryToMessages', () => { it('should convert empty history', () => { const history: ConversationMessage[] = []; const result = convertHistoryToMessages(history); expect(result).toEqual([]); }); it('should convert single user message', () => { const history: ConversationMessage[] = [{ role: 'user', content: 'Hello!' }]; const result = convertHistoryToMessages(history); expect(result).toHaveLength(1); expect(result[0]).toMatchObject({ type: 'user', session_id: '', message: { role: 'user', content: [{ type: 'text', text: 'Hello!' }], }, parent_tool_use_id: null, }); }); it('should convert single assistant message', () => { const history: ConversationMessage[] = [{ role: 'assistant', content: 'Hi there!' }]; const result = convertHistoryToMessages(history); expect(result).toHaveLength(1); expect(result[0]).toMatchObject({ type: 'assistant', session_id: '', message: { role: 'assistant', content: [{ type: 'text', text: 'Hi there!' }], }, parent_tool_use_id: null, }); }); it('should preserve array content as-is', () => { const content = [ { type: 'text', text: 'Text' }, { type: 'image', source: { data: '...' } }, ]; const history: ConversationMessage[] = [{ role: 'user', content }]; const result = convertHistoryToMessages(history); expect(result[0].message.content).toEqual(content); }); it('should convert multiple messages', () => { const history: ConversationMessage[] = [ { role: 'user', content: 'First' }, { role: 'assistant', content: 'Second' }, { role: 'user', content: 'Third' }, ]; const result = convertHistoryToMessages(history); expect(result).toHaveLength(3); expect(result[0].type).toBe('user'); expect(result[1].type).toBe('assistant'); expect(result[2].type).toBe('user'); }); it('should set session_id to empty string', () => { const history: ConversationMessage[] = [{ role: 'user', content: 'Test' }]; const result = convertHistoryToMessages(history); expect(result[0].session_id).toBe(''); }); it('should set parent_tool_use_id to null', () => { const history: ConversationMessage[] = [{ role: 'user', content: 'Test' }]; const result = convertHistoryToMessages(history); expect(result[0].parent_tool_use_id).toBeNull(); }); it('should normalize string content to blocks', () => { const history: ConversationMessage[] = [{ role: 'user', content: 'String content' }]; const result = convertHistoryToMessages(history); expect(result[0].message.content).toEqual([{ type: 'text', text: 'String content' }]); }); }); });