import { test } from "node:test"; import assert from "node:assert/strict"; import { withResultV1, membersDigest, typedErrorCode, capPatches, truncateExecutionLogContent, estimateWireBytes, MAX_RESULT_MEMBER_BYTES, MAX_RESULT_WIRE_BYTES, EXECUTION_LOG_PATCH_BYTES, } from "./result-v1.mjs"; test("withResultV1 is additive and strips stderr", () => { const out = withResultV1({ ok: true, run_id: "run-1", stderr: "secret-trace", patches: [{ rel_path: "output.md", content: "hello" }], }); assert.equal(out.ok, true); assert.equal(out.patches[0].rel_path, "output.md"); assert.equal(out.stderr, undefined); assert.equal(out.capabilities.typed_result, true); assert.equal(out.runner_protocol, "typed-v1"); assert.equal(out.result_v1.schema_version, 1); assert.equal(out.result_v1.run_id, "run-1"); assert.equal(out.result_v1.outcome, "success"); assert.equal(out.result_v1.members.length, 1); assert.equal(out.result_v1.content_digest, membersDigest(out.result_v1.members)); }); test("typedErrorCode is allowlisted and ignores raw stderr", () => { assert.equal(typedErrorCode({ ok: false, fallback_reason: "prompt_empty" }), "PROMPT_EMPTY"); assert.equal(typedErrorCode({ ok: false, fallback_reason: "Connection error." }), "TRANSIENT"); const out = withResultV1({ ok: false, run_id: "run-2", retryable: true, fallback_reason: "Connection error. /tmp/secret", stderr: "token=abc", patches: [], }); assert.equal(out.stderr, undefined); assert.equal(out.result_v1.error_code, "TRANSIENT"); assert.equal(out.result_v1.retryable, true); assert.equal(out.result_v1.outcome, "error"); }); test("path escape members are omitted", () => { const out = withResultV1({ ok: true, run_id: "run-3", patches: [ { rel_path: "../etc/passwd", content: "x" }, { rel_path: "/abs.md", content: "y" }, { rel_path: "output.md", content: "ok" }, ], }); assert.deepEqual(out.result_v1.members.map((m) => m.path), ["output.md"]); assert.deepEqual(out.patches.map((p) => p.rel_path), ["output.md"]); }); test("truncateExecutionLogContent keeps only the tail", () => { const big = "A".repeat(EXECUTION_LOG_PATCH_BYTES + 4096); const out = truncateExecutionLogContent(big); assert.ok(out.startsWith("[truncated ")); assert.ok(out.length < big.length); assert.ok(Buffer.byteLength(out, "utf8") <= EXECUTION_LOG_PATCH_BYTES + 64); }); test("oversized patch content is dropped from both members and patches", () => { const huge = "x".repeat(MAX_RESULT_MEMBER_BYTES + 1); const out = withResultV1({ ok: true, run_id: "run-4", patches: [ { rel_path: "output.md", content: "# ok\n" }, { rel_path: "blob.bin", content: huge }, ], }); assert.deepEqual(out.patches.map((p) => p.rel_path), ["output.md"]); assert.deepEqual(out.result_v1.members.map((m) => m.path), ["output.md"]); }); test("capPatches truncates execution.log and enforces total wire budget", () => { const log = "L".repeat(EXECUTION_LOG_PATCH_BYTES * 4); const patches = capPatches([ { rel_path: "output.md", content: "# deliverable\n" }, { rel_path: "execution.log", content: log }, ]); assert.equal(patches.length, 2); assert.ok(patches.find((p) => p.rel_path === "execution.log").content.startsWith("[truncated ")); const total = patches.reduce((n, p) => n + Buffer.byteLength(p.content, "utf8"), 0); assert.ok(total <= MAX_RESULT_WIRE_BYTES); // Force total budget with a custom soft cap under the member limit. const budget = 1024; const filler = "F".repeat(budget - 2); const tight = capPatches( [ { rel_path: "a.md", content: filler }, { rel_path: "b.md", content: "too-much" }, ], { maxTotalBytes: budget, maxMemberBytes: budget }, ); assert.deepEqual(tight.map((p) => p.rel_path), ["a.md"]); }); test("withResultV1 wire estimate stays under soft budget for truncated logs", () => { const log = "E".repeat(8 * 1024 * 1024); const out = withResultV1({ ok: true, run_id: "run-big", patches: [ { rel_path: "output.md", content: "# intake\n".repeat(100) }, { rel_path: "execution.log", content: log }, ], }); assert.ok(estimateWireBytes(out) < MAX_RESULT_WIRE_BYTES); assert.equal(out.result_v1.members.length, out.patches.length); for (const m of out.result_v1.members) { const body = out.patches.find((p) => p.rel_path === m.path); assert.ok(body); assert.equal(Buffer.byteLength(body.content, "utf8"), m.size); } });