import assert from "node:assert/strict"; import { test } from "node:test"; import { parseScriptAssignmentPayload, runScriptSandbox, ScriptRequestBudget, validateScriptIpcEnvelope, } from "./script-runtime.ts"; function run( source: string, overrides: Partial[0]> = {}, ) { const abort = new AbortController(); return runScriptSandbox({ source, args: undefined, cwd: process.cwd(), signal: abort.signal, onAssign: async (role, prompt) => ({ ok: true, output: `${role}:${prompt}`, }), onStage: () => {}, ...overrides, }); } test("script sandbox exposes only stage, assign, parallel, and immutable args", async () => { const stages: string[] = []; const result = await run( ` stage("Audit"); const replies = await parallel([ () => assign("review", "one"), () => assign("review", "two"), ], { concurrency: 99 }); return { replies: replies.map((reply) => reply.output), processType: typeof process, requireType: typeof require, fetchType: typeof fetch, nestedArgsFrozen: Object.isFrozen(args.nested), }; `, { args: { nested: { value: "immutable" } }, onStage: (title) => stages.push(title), }, ); assert.deepEqual(result, { replies: ["review:one", "review:two"], processType: "undefined", requireType: "undefined", fetchType: "undefined", nestedArgsFrozen: true, }); assert.deepEqual(stages, ["Audit"]); }); test("script sandbox rejects unawaited assignments and synchronous loops", async () => { let calls = 0; await assert.rejects( run(`assign("review", "orphan"); return "done";`, { onAssign: async () => { calls++; return { ok: true, output: "unexpected" }; }, }), /unawaited assign/, ); assert.equal(calls, 0); await assert.rejects(run(`while (true) {}`), /timed out/); }); test("script cancellation aborts active assignments and terminates execution", async () => { const controller = new AbortController(); let startedResolve: (() => void) | undefined; const started = new Promise((resolve) => { startedResolve = resolve; }); let requestAborted = false; const pending = run(`return await assign("review", "pending");`, { signal: controller.signal, onAssign: async (_role, _prompt, signal) => { startedResolve?.(); await new Promise((resolve) => { signal.addEventListener( "abort", () => { requestAborted = true; resolve(); }, { once: true }, ); }); return { ok: false, output: "", error: "Assignment was aborted" }; }, }); await started; controller.abort(new Error("cancel fixture")); await assert.rejects(pending, /Script was aborted/); assert.equal(requestAborted, true); }); test("script IPC rejects unauthenticated, malformed, oversized, duplicate, and over-budget requests", () => { assert.throws( () => validateScriptIpcEnvelope({ token: "wrong", kind: "assign" }, "right"), /invalid IPC message/, ); assert.throws(() => parseScriptAssignmentPayload("{"), /malformed assignment JSON/); assert.throws( () => parseScriptAssignmentPayload("x".repeat(512 * 1024 + 1)), /oversized assignment request/, ); assert.throws( () => parseScriptAssignmentPayload(JSON.stringify({ id: 1, role: "", prompt: "x" })), /invalid assignment request/, ); const duplicate = new ScriptRequestBudget(); duplicate.accept(1); assert.throws(() => duplicate.accept(1), /duplicate assignment request/); const budget = new ScriptRequestBudget(); for (let id = 1; id <= 32; id++) budget.accept(id); assert.throws(() => budget.accept(33), /request budget/); }); test("script stage updates and total runtime are bounded", async () => { await assert.rejects( run(`for (let index = 0; index < 65; index++) stage("flood-" + index);`), /stage update budget/, ); await assert.rejects( run(`while (true) { await Promise.resolve(); }`, { runtimeTimeoutMs: 20 }), /wall-clock time limit/, ); }); test("script source and args are bounded", async () => { await assert.rejects(run("x".repeat(512 * 1024 + 1)), /source exceeds/); await assert.rejects( run("return null", { args: "x".repeat(256 * 1024 + 1) }), /args exceed/, ); });