T8: sausage:process WIT (spawn, wait, kill), one store per process over the shared root, /proc/processes, /run, pipeline and cancellation groups, Exec. brush and 78 uutils commands; the shared cwd-init object sets the cwd from PWD and keeps numeric exit codes. The corpus matches native bash. T9: V8 (deno_core) runs pi-durable, pi-ai and chord; SQLite storage in <dir>/host/harness.sqlite (WAL, synchronous=FULL); file tools on the VFS, bash through Exec; resumes after SIGKILL.
55 lines
3.1 KiB
TypeScript
55 lines
3.1 KiB
TypeScript
// 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);
|