import { describe, expect, it } from 'vitest'; import releaseManifest from '../../public/manifest/models.json'; import { EngineClientError } from '../engine'; import { applyToolExecutionToMessages, buildEngineHistory, DEFAULT_CONTEXT_SIZE, DEFAULT_MAX_TOKENS, DEFAULT_MODEL_ID, modelArchitectureLabel, publishBackendReport, reconcileCompletionTokens, reconcileTotalTokens, reportsModelWeightProgress, requiresModelReload, } from './App'; import { prepareHtmlArtifact, type ToolExecution } from '../lib/agent-tools'; function engineError(code: string): EngineClientError { return new EngineClientError({ code, message: code }); } describe('App model invalidation policy', () => { it.each([ 'WEBGPU_DEVICE_LOST', 'ENGINE_WORKER_FAILED', 'MODEL_NOT_LOADED', ])('requires an explicit reload after %s', (code) => { expect(requiresModelReload(engineError(code))).toBe(true); }); it('keeps an otherwise healthy loaded model after a responsive abort', () => { expect(requiresModelReload(engineError('ABORTED'))).toBe(false); }); }); describe('App release defaults', () => { it('opens on the flagship tier required by the product contract', () => { expect(DEFAULT_MODEL_ID).toBe('bonsai-27b'); }); it('shows manifest architecture instead of invented model aliases', () => { expect(modelArchitectureLabel('qwen3')).toBe('Qwen3 dense'); expect(modelArchitectureLabel('qwen35')).toBe('Qwen3.5 hybrid'); }); it('uses one 4K ceiling for context allocation and completion requests', () => { expect(DEFAULT_CONTEXT_SIZE).toBe(4096); expect(DEFAULT_MAX_TOKENS).toBe(4096); expect(DEFAULT_CONTEXT_SIZE).toBe(DEFAULT_MAX_TOKENS); expect(releaseManifest.models.find((model) => model.id === '27b')?.defaultContext) .toBe(DEFAULT_CONTEXT_SIZE); }); }); describe('App model-load progress', () => { it('does not turn pinned manifest metadata reads into model-weight download state', () => { expect(reportsModelWeightProgress('manifest')).toBe(false); expect(reportsModelWeightProgress('download')).toBe(true); expect(reportsModelWeightProgress('load')).toBe(true); }); }); describe('App streamed completion telemetry', () => { it('uses observed stream events when final engine usage is incomplete', () => { expect(reconcileCompletionTokens(5, 64)).toBe(64); }); it('keeps the engine count when one stream event contains multiple tokens', () => { expect(reconcileCompletionTokens(12, 8)).toBe(12); }); it('fails closed to the observed count for invalid engine usage', () => { expect(reconcileCompletionTokens(Number.NaN, 7)).toBe(7); }); it('keeps context usage consistent with a reconciled completion count', () => { expect(reconcileTotalTokens(5, 5, 64)).toBe(69); expect(reconcileTotalTokens(80, 5, 64)).toBe(80); }); }); describe('App backend diagnostics', () => { it('publishes the complete backend report for the browser gate without rendering it', () => { const report = { backends: ['WebGPU'], nGraphSplits: 1, opsOnCpu: 0, layersGpu: { offloaded: 65, total: 65 }, flashAttention: false, cacheTypeK: 'f16', cacheTypeV: 'f16', webgpuKvBufferBytes: 1024, webgpuTrace: ['@@WEBGPU_TRACE@@completion_end id=1 steps=65 error=0'], }; publishBackendReport(report); expect(globalThis.__bonsaiBackendReport).toEqual(report); delete globalThis.__bonsaiBackendReport; }); }); describe('App artifact identity', () => { it('replaces an existing artifact in its original message while completing the current tool run', () => { const original = prepareHtmlArtifact('
old
', 'Demo', 'stable-artifact', 'old-runtime'); const replacement = prepareHtmlArtifact('new
', 'Demo', 'stable-artifact', 'new-runtime'); const execution: ToolExecution = { call: { id: 'update-call', type: 'function', function: { name: 'artifact_update', arguments: '{}' }, }, artifact: replacement, output: '{"ok":true}', failed: false, }; const next = applyToolExecutionToMessages([ { id: 'older', role: 'assistant', content: '', timestamp: '10:00', artifacts: [original] }, { id: 'current', role: 'assistant', content: '', timestamp: '10:01', tools: [{ id: 'update-call', name: 'artifact_update', input: '{}', state: 'running' }], }, ], 'current', 'update-call', execution); expect(next[0]?.artifacts).toEqual([replacement]); expect(next[1]?.artifacts).toBeUndefined(); expect(next[1]?.tools?.[0]).toMatchObject({ state: 'complete', output: '{"ok":true}', artifactId: 'stable-artifact', }); }); it('attaches a newly created artifact to the current assistant message', () => { const artifact = prepareHtmlArtifact('new
', 'Demo', 'new-artifact', 'runtime'); const execution: ToolExecution = { call: { id: 'create-call', type: 'function', function: { name: 'html_artifact', arguments: '{}' } }, artifact, output: '{"ok":true}', failed: false, }; const next = applyToolExecutionToMessages([{ id: 'current', role: 'assistant', content: '', timestamp: '10:01', tools: [{ id: 'create-call', name: 'html_artifact', input: '{}', state: 'running' }], }], 'current', 'create-call', execution); expect(next[0]?.artifacts).toEqual([artifact]); expect(next[0]?.tools?.[0]?.artifactId).toBe('new-artifact'); }); }); describe('App persisted agent history', () => { it('reconstructs separate assistant and tool rounds from ordered segments', () => { expect(buildEngineHistory([{ id: 'assistant', role: 'assistant', content: 'I will calculate. The first result is ready. Final answer.', timestamp: '10:00', segments: [ { id: 'text-0', kind: 'text', content: 'I will calculate.' }, { id: 'tool-1', kind: 'tool', toolCallId: 'call-1', roundId: 'round-0' }, { id: 'reasoning-1', kind: 'reasoning', content: 'Checking the first result.' }, { id: 'text-1', kind: 'text', content: 'The first result is ready.' }, { id: 'tool-2', kind: 'tool', toolCallId: 'call-2', roundId: 'round-1' }, { id: 'tool-3', kind: 'tool', toolCallId: 'call-3', roundId: 'round-1' }, { id: 'reasoning-2', kind: 'reasoning', content: 'Combining results.' }, { id: 'text-2', kind: 'text', content: 'Final answer.' }, ], tools: [ { id: 'call-1', name: 'js_eval', input: '{"code":"1+1"}', output: '{"value":2}', state: 'complete' }, { id: 'call-2', name: 'js_eval', input: '{"code":"2+2"}', output: '{"value":4}', state: 'complete' }, { id: 'call-3', name: 'js_eval', input: '{"code":"3+3"}', output: '{"value":6}', state: 'complete' }, ], }], 'System')).toEqual([ { role: 'system', content: 'System' }, { role: 'assistant', content: 'I will calculate.', tool_calls: [{ id: 'call-1', type: 'function', function: { name: 'js_eval', arguments: '{"code":"1+1"}' }, }], }, { role: 'tool', content: '{"value":2}', tool_call_id: 'call-1' }, { role: 'assistant', content: 'The first result is ready.', tool_calls: [ { id: 'call-2', type: 'function', function: { name: 'js_eval', arguments: '{"code":"2+2"}' } }, { id: 'call-3', type: 'function', function: { name: 'js_eval', arguments: '{"code":"3+3"}' } }, ], }, { role: 'tool', content: '{"value":4}', tool_call_id: 'call-2' }, { role: 'tool', content: '{"value":6}', tool_call_id: 'call-3' }, { role: 'assistant', content: 'Final answer.' }, ]); }); });