// P2 rehearsal: real bash tools pause for two passkey approvals and resume durably. 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'; import { CredentialRequests, startRequests } from './credentials'; const models = createModels(); const faux = fauxProvider({ tokensPerSecond: 100000 }); models.setProvider(faux.provider); const bash = (command: string, id: string) => fauxAssistantMessage([fauxToolCall('bash', { command }, { id })], { stopReason: 'toolUse' }); const curl = `curl -i http://127.0.0.1:${globalThis.p2Http}/whoami`; const push = 'cd /repo && git push origin main'; faux.setResponses([ bash(curl, 'curl-denied'), fauxAssistantMessage([fauxText('Wait for HTTP approval.')]), bash(curl, 'curl-approved'), bash(push, 'ssh-denied'), fauxAssistantMessage([fauxText('Wait for SSH approval.')]), bash(push, 'ssh-approved'), fauxAssistantMessage([fauxText('P2 complete.')]), ]); const registry = createRegistry(); registry.install(CodingTools); registry.install(CredentialRequests); const harness = await Harness.open(await openStorage(globalThis.storagePath), { models, registry, env: (target: any) => environment('/', target.conversationId), }, context); const root = await harness.root(context, { agent: { model: { provider: 'faux', modelId: 'faux-1' }, extensions: [CodingTools, CredentialRequests], cwd: '/', } }); const stop = await startRequests(harness, context); harness.resume(); await (await root.submit({ type: 'input', content: 'Rehearse P2', requestId: 'p2' }, context)).wait(context); await Deno.core.ops.op_file('write', '/p2-http-idle', []); const watch = await root.watch(context); let sshIdle = false; await new Promise((resolve, reject) => { const check = async (event: any) => { if (event.kind !== 'value') return; const transcript = JSON.stringify(event.value.entries); if (!sshIdle && transcript.includes('Wait for SSH approval.')) { sshIdle = true; await harness.waitForIdle(context); await Deno.core.ops.op_file('write', '/p2-ssh-idle', []); } const approvals = event.value.entries.filter((entry: any) => JSON.stringify(entry).includes('Your request for')); if (approvals.length > 2) reject(new Error('Duplicate approval wake-up')); if (transcript.includes('P2 complete.')) resolve(); }; watch.start(check); check({ kind: 'value', value: watch.value }); }); await harness.waitForIdle(context); const transcript = JSON.stringify(watch.value.entries); for (const expected of ['403', 'demo-api', 'demo-ssh', 'Bearer accepted', 'P2 complete.']) { if (!transcript.includes(expected)) throw new Error(`Missing rehearsal result: ${expected}`); } if (watch.value.entries.filter((entry: any) => JSON.stringify(entry).includes('Your request for')).length !== 2) { throw new Error('Expected exactly two approval inputs'); } await Deno.core.ops.op_file('write', '/p2-transcript', [...new TextEncoder().encode(transcript)]); await watch.stop(); await stop(); await harness.close(context);