import { describe, expect, it } from 'bun:test' import { splitContext, applyHybridStrategy, optimizeForCost, optimizeForAccuracy, getHybridStats, } from './hybridContextStrategy.js' function createMessage(role: string, content: string, createdAt: number = Date.now()): any { return { message: { role, content, id: 'test', type: 'message', created_at: createdAt }, sender: role, } } describe('hybridContextStrategy', () => { describe('splitContext', () => { it('splits context into cached and fresh', () => { const messages = [ createMessage('system', 'System prompt', Date.now() - 86400000), createMessage('user', 'Hello'), createMessage('assistant', 'Hi there'), ] const split = splitContext(messages, { cacheWeight: 0.4, freshWeight: 0.6, maxTotalTokens: 10000, }) expect(split.cachedTokens).toBeGreaterThanOrEqual(0) expect(split.freshTokens).toBeGreaterThanOrEqual(0) expect(split.totalTokens).toBeGreaterThan(0) }) it('respects weight configuration', () => { const messages = [ createMessage('system', 'Old system', Date.now() - 86400000), createMessage('user', 'Recent message', Date.now()), ] const split = splitContext(messages, { cacheWeight: 0.5, freshWeight: 0.5, maxTotalTokens: 10000, }) expect(split.cached).toBeDefined() expect(split.fresh).toBeDefined() }) }) describe('applyHybridStrategy', () => { it('applies strategy and returns messages', () => { const messages = [ createMessage('user', 'Message 1'), createMessage('assistant', 'Response 1'), ] const result = applyHybridStrategy(messages, { cacheWeight: 0.5, freshWeight: 0.5, maxTotalTokens: 10000, }) expect(result.selectedMessages.length).toBeGreaterThan(0) expect(['cache_heavy', 'fresh_heavy', 'balanced']).toContain(result.strategy) }) it('calculates estimated cost', () => { const messages = [ createMessage('user', 'Test message'), ] const result = applyHybridStrategy(messages, { cacheWeight: 0.5, freshWeight: 0.5, maxTotalTokens: 10000, }) expect(result.estimatedCost).toBeGreaterThanOrEqual(0) }) }) describe('optimizeForCost', () => { it('returns messages within budget', () => { const messages = [ createMessage('user', 'Message 1'), createMessage('assistant', 'Response 1'), ] const result = optimizeForCost(messages, 0.001) expect(result.length).toBeGreaterThanOrEqual(0) }) }) describe('optimizeForAccuracy', () => { it('optimizes for accuracy with token limit', () => { const messages = [ createMessage('user', 'Message 1'), createMessage('assistant', 'Response 1'), ] const result = optimizeForAccuracy(messages, 5000) expect(result.length).toBeGreaterThan(0) }) }) describe('getHybridStats', () => { it('returns statistics', () => { const messages = [ createMessage('system', 'System', Date.now() - 86400000), createMessage('user', 'Hello'), ] const split = splitContext(messages, { cacheWeight: 0.5, freshWeight: 0.5, maxTotalTokens: 10000 }) const stats = getHybridStats(split) expect(stats.cacheRatio).toBeGreaterThanOrEqual(0) expect(stats.freshRatio).toBeGreaterThanOrEqual(0) expect(stats.totalTokens).toBeGreaterThan(0) }) }) describe('tool_use/tool_result pairing', () => { it('preserves tool_use and tool_result together', () => { const toolUseId = 'tool-use-123' const messages = [ { type: 'assistant', uuid: 'uuid-1', message: { role: 'assistant', content: [{ type: 'tool_use', id: toolUseId, name: 'Read' }], id: 'msg-1', created_at: 1000, }, }, { type: 'user', uuid: 'uuid-2', message: { role: 'user', content: [{ type: 'tool_result', tool_use_id: toolUseId, content: 'file content' }], id: 'msg-2', created_at: 2000, }, }, { type: 'assistant', uuid: 'uuid-3', message: { role: 'assistant', content: 'Response after tool', id: 'msg-3', created_at: 3000, }, }, ] as any[] const result = applyHybridStrategy(messages, { cacheWeight: 0.5, freshWeight: 0.5, maxTotalTokens: 10000, }) const hasToolUse = result.selectedMessages.some( m => Array.isArray(m.message?.content) && m.message.content.some((b: any) => b.type === 'tool_use') ) const hasToolResult = result.selectedMessages.some( m => Array.isArray(m.message?.content) && m.message.content.some((b: any) => b.type === 'tool_result') ) expect(hasToolUse).toBe(true) expect(hasToolResult).toBe(true) }) it('accounts for large tool_use input in token counting', () => { const largeInput = 'x'.repeat(5000) const messages = [ { type: 'assistant', message: { role: 'assistant', content: [ { type: 'tool_use', id: 'tu1', name: 'Edit', input: { path: 'test.js', content: largeInput } }, ], created_at: 1000, }, }, ] as any[] const result = applyHybridStrategy(messages, { cacheWeight: 0.5, freshWeight: 0.5, maxTotalTokens: 20000, }) expect(result.totalTokens).toBeGreaterThan(1000) }) it('accounts for large thinking blocks in token counting', () => { const longThinking = 'Thinking '.repeat(1000) const messages = [ { type: 'assistant', message: { role: 'assistant', content: [ { type: 'thinking', thinking: longThinking }, { type: 'text', text: 'Final response' }, ], created_at: 1000, }, }, ] as any[] const result = applyHybridStrategy(messages, { cacheWeight: 0.5, freshWeight: 0.5, maxTotalTokens: 20000, }) expect(result.totalTokens).toBeGreaterThan(500) }) }) })