// Faux-provider integration test. The Rust test checks VFS effects and Exec arguments. import { BACKGROUND_CONTEXT as context } from '@earendil-works/chord/context'; import { createModels } from '@earendil-works/pi-ai/models'; import { fauxProvider, fauxAssistantMessage, fauxToolCall, fauxText } from '@earendil-works/pi-ai/providers/faux'; import { Harness, createRegistry } from '@earendil-works/pi-durable'; import { CodingTools } from '@earendil-works/pi-durable/tools'; import { environment } from './environment'; import { openStorage } from './sqlite'; const models = createModels(); const crash = globalThis.testCrash; const faux = fauxProvider({ tokensPerSecond: crash === 'model' ? 1 : 100000 }); models.setProvider(faux.provider); faux.setResponses([ fauxAssistantMessage([fauxToolCall('write', { path: '/test.txt', content: 'before\n' }, { id: 'write' })], { stopReason: 'toolUse' }), fauxAssistantMessage([fauxToolCall('read', { path: '/test.txt' }, { id: 'read' })], { stopReason: 'toolUse' }), fauxAssistantMessage([fauxToolCall('edit', { path: '/test.txt', edits: [{ oldText: 'before', newText: 'after' }] }, { id: 'edit' })], { stopReason: 'toolUse' }), fauxAssistantMessage([fauxToolCall('bash', { command: 'echo test' }, { id: 'bash' })], { stopReason: 'toolUse' }), fauxAssistantMessage([fauxText('done')]), ]); if (crash) { faux.setResponses(crash === 'tool' ? [ fauxAssistantMessage([fauxToolCall('bash', { command: 'echo test' }, { id: 'crash' })], { stopReason: 'toolUse' }), ] : crash === 'model' ? [ fauxAssistantMessage([fauxText('A long response that the test interrupts before it completes.')]), ] : [fauxAssistantMessage([fauxText('resumed done')])]); } const registry = createRegistry(); registry.install(CodingTools); const harness = await Harness.open(await openStorage(globalThis.storagePath), { models, registry, env: () => environment('/') }, context); const root = await harness.root(context, { agent: { model: { provider: 'faux', modelId: 'faux-1' }, extensions: [CodingTools], cwd: '/' } }); if (crash === 'model') { const progress = await root.watch(context); let ready = false; progress.start((event: any) => { if (event.kind !== 'value' || ready) return; const message = event.value.docs['pi.live']?.generation?.message; if (message?.content?.some((block: any) => block.type === 'text' && block.text.length > 0)) { ready = true; console.log('CRASH_READY'); } }); } harness.resume(); const result = await (await root.submit({ type: 'input', content: 'Exercise tools', requestId: 'test' }, context)).wait(context); if (result.status !== 'done') throw new Error(JSON.stringify(result)); await harness.waitForIdle(context); const watch = await root.watch(context); const transcript = JSON.stringify(watch.value.entries); if (!crash && transcript.includes('"isError":true')) throw new Error(transcript); for (const expected of crash ? ['resumed done'] : ['before', 'after', 'streamed stdout', 'streamed stderr', 'done']) { if (!transcript.includes(expected)) throw new Error(`Missing ${expected}: ${transcript}`); } await watch.stop(); await harness.close(context);