| 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' }]); |
| }); |
| }); |
| }); |
|
|