import { StreamingToolCallBuffer } from '../StreamingToolCallBuffer'; describe('StreamingToolCallBuffer', () => { let buffer: StreamingToolCallBuffer; beforeEach(() => { buffer = new StreamingToolCallBuffer(); }); describe('append', () => { it('should accumulate arg chunks for a tool call ID', () => { buffer.append('tc_1', '{"action":"wri'); buffer.append('tc_1', 'te","content":"hello'); expect(buffer.getRawArgs('tc_1')).toBe( '{"action":"write","content":"hello' ); }); it('should track multiple tool calls independently', () => { buffer.append('tc_1', '{"action":"write"}'); buffer.append('tc_2', '{"action":"read"}'); expect(buffer.getRawArgs('tc_1')).toBe('{"action":"write"}'); expect(buffer.getRawArgs('tc_2')).toBe('{"action":"read"}'); }); it('should return undefined for unknown tool call IDs', () => { expect(buffer.getRawArgs('unknown')).toBeUndefined(); }); it('should skip exact duplicate fragments', () => { // First append succeeds expect(buffer.append('tc_1', '{"actio')).toBe(true); // Exact duplicate is skipped expect(buffer.append('tc_1', '{"actio')).toBe(false); // Next fragment is different — appended expect(buffer.append('tc_1', 'n": "wri')).toBe(true); // Duplicate of new fragment — skipped expect(buffer.append('tc_1', 'n": "wri')).toBe(false); // Final result has no duplicates expect(buffer.getRawArgs('tc_1')).toBe('{"action": "wri'); }); it('should handle alternating duplicate pairs (Bedrock pattern)', () => { // Simulate real Bedrock output: each fragment arrives twice const fragments = [ '{"a', 'ction', '": "w', 'rite"', ', "name"', ': "test.tsx"', ]; for (const frag of fragments) { buffer.append('tc_1', frag); // first — appended buffer.append('tc_1', frag); // duplicate — skipped } expect(buffer.getRawArgs('tc_1')).toBe( '{"action": "write", "name": "test.tsx"' ); }); it('should return false for empty args', () => { expect(buffer.append('tc_1', '')).toBe(false); }); it('should handle mixed fragment and accumulated patterns', () => { // Fragment mode (normal append) buffer.append('tc_1', '{"action":"wri'); buffer.append('tc_1', 'te"}'); expect(buffer.getRawArgs('tc_1')).toBe('{"action":"write"}'); }); }); describe('setToolName / getToolName', () => { it('should store and retrieve tool names', () => { buffer.setToolName('tc_1', 'content_tool'); expect(buffer.getToolName('tc_1')).toBe('content_tool'); }); it('should not overwrite an existing tool name', () => { buffer.setToolName('tc_1', 'content_tool'); buffer.setToolName('tc_1', 'other_tool'); expect(buffer.getToolName('tc_1')).toBe('content_tool'); }); it('should return undefined for unknown tool calls', () => { expect(buffer.getToolName('unknown')).toBeUndefined(); }); }); describe('extractFieldValue', () => { it('should extract a simple string field', () => { buffer.append('tc_1', '{"action":"write","filename":"test.tsx"}'); expect(buffer.extractFieldValue('tc_1', 'action')).toBe('write'); expect(buffer.extractFieldValue('tc_1', 'filename')).toBe('test.tsx'); }); it('should extract content with escaped characters', () => { buffer.append('tc_1', '{"content":"line1\\nline2\\ttab"}'); expect(buffer.extractFieldValue('tc_1', 'content')).toBe( 'line1\nline2\ttab' ); }); it('should extract content with escaped quotes', () => { buffer.append('tc_1', '{"content":"say \\"hello\\""}'); expect(buffer.extractFieldValue('tc_1', 'content')).toBe('say "hello"'); }); it('should extract content with escaped backslashes', () => { buffer.append('tc_1', '{"content":"path\\\\to\\\\file"}'); expect(buffer.extractFieldValue('tc_1', 'content')).toBe( 'path\\to\\file' ); }); it('should handle truncated content (no closing quote)', () => { buffer.append( 'tc_1', '{"action":"write","content":"function App() {\\n return