Files
sausage/host/js/p4-test.ts
T

87 lines
3.9 KiB
TypeScript

/** P4 fixture provider for the real console: all project work uses the installed bash tool. */
import { fauxProvider, fauxAssistantMessage, fauxToolCall } from '@earendil-works/pi-ai/providers/faux';
const main = `fn greeting(name: &str) -> String { format!("hello {name}") }
fn main() {
let Some(name) = std::env::args().nth(1) else { std::process::exit(7) };
println!("{}", serde_json::json!({"greeting": greeting(&name)}));
}
#[test]
fn greeting_test() { assert_eq!(greeting("world"), "hello world", "P4_expected_failure"); }
`;
const write = (path: string, text: string) => `cat > ${path} <<'P4_FILE'\n${text}\nP4_FILE\n`;
const phases = [
`set -e
mkdir -p /src/demo-cli/src /src/demo-node /tmp
cd /src/demo-cli
if test -d target; then cargo clean; fi
${write('Cargo.toml', '[package]\nname="demo-cli"\nversion="0.1.0"\nedition="2024"\n[workspace]\n')}
${write('src/main.rs', main.replace('"hello world", "P4_expected_failure"', '"hello wrong", "P4_expected_failure"'))}
cargo add serde_json
cargo fmt
set +e
cargo test -- --nocapture > /tmp/p4-fail.stdout 2> /tmp/p4-fail.stderr
code=$?
set -e
cat /tmp/p4-fail.stdout /tmp/p4-fail.stderr
test "$code" = 101
case "$(cat /tmp/p4-fail.stderr)" in *P4_expected_failure*) ;; *) exit 1 ;; esac
printf 'P4_PHASE_0_OK\n'`,
`set -e
cd /src/demo-cli
${write('src/main.rs', main)}
cargo fmt
cargo test -- --nocapture
cargo build --release
test -f target/wasm32-wasip2/release/demo-cli.wasm
sh -c '/src/demo-cli/target/wasm32-wasip2/release/demo-cli.wasm world' > /tmp/p4-cli.json
case "$(cat /tmp/p4-cli.json)" in *'"greeting":"hello world"'*) ;; *) exit 1 ;; esac
set +e
sh -c '/src/demo-cli/target/wasm32-wasip2/release/demo-cli.wasm'
code=$?
set -e
test "$code" = 7
printf 'P4_PHASE_1_OK\n'`,
`set -e
${write('/src/demo-node/package.json', '{"scripts":{"test":"node test.cjs"}}')}
${write('/src/demo-node/test.cjs', 'const fs = require("node:fs");\nrequire("node:assert/strict").equal(2 + 2, 4);\nfs.writeFileSync("result.txt", "P4 npm test passed\\n");')}
id=$(box create --ttl 600)
printf '%s\n' "$id" > /tmp/p4-box-id
trap 'box rm "$id"' EXIT
box put "$id" /src/demo-node /work
box exec "$id" --timeout 120 -- sh -c 'cd /work && npm test'
box get "$id" /work/result.txt /src/demo-node/result.txt
test "$(cat /src/demo-node/result.txt)" = 'P4 npm test passed'
box rm "$id"
trap - EXIT
printf 'P4_PHASE_2_OK\n'`,
`set -e
undo list > /tmp/p4-undo.json
box ls > /tmp/p4-boxes
printf 'P4_PHASE_3_OK\n'`,
];
export default function p4(host: any) {
// Replace the console's transport before resume. No real model request can occur.
const faux = fauxProvider({ provider: 'openai', models: [{ id: 'gpt-6.1-sol' }], tokensPerSecond: 1000000 });
const respond = (transcript: any): any => {
faux.appendResponses([respond]);
const messages = transcript.messages;
const input = messages.findLast((message: any) => message.role === 'user');
const text = (message: any) => typeof message.content === 'string' ? message.content : (message.content ?? []).filter((part: any) => part.type === 'text').map((part: any) => part.text).join('\n');
const round = /P4 start (\d+)/.exec(text(input))?.[1];
if (!round) throw new Error(`Unexpected P4 input: ${JSON.stringify(input)}`);
const last = messages.findLast((message: any) => message.role !== 'system');
let phase = 0;
if (last.role !== 'user') {
const prior = /p4-\d+-(\d+)/.exec(last.toolCallId)?.[1];
if (last.isError || prior === undefined || !text(last).includes(`P4_PHASE_${prior}_OK`)) throw new Error(`P4 bash failed: ${JSON.stringify(last)}`);
phase = Number(prior) + 1;
}
if (phase === phases.length) return fauxAssistantMessage(`P4_COMPLETE_${round}`);
return fauxAssistantMessage([fauxToolCall('bash', { command: phases[phase], timeout: 300 }, { id: `p4-${round}-${phase}` })], { stopReason: 'toolUse' });
};
faux.setResponses([respond]);
host.models().setProvider(faux.provider);
return { name: 'p4' };
}