@tangle-network/agent-bench 0.3.5 → 0.3.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/README.md +13 -1
- package/dist/adapters.d.ts +15 -0
- package/dist/adapters.js +43 -0
- package/dist/adapters.js.map +1 -0
- package/dist/benchmarks/_harness.d.ts +125 -0
- package/dist/benchmarks/_harness.js +33 -0
- package/dist/benchmarks/_harness.js.map +1 -0
- package/dist/benchmarks/aec-bench.d.ts +27 -0
- package/dist/benchmarks/aec-bench.js +8 -0
- package/dist/benchmarks/aec-bench.js.map +1 -0
- package/dist/benchmarks/agentbench.d.ts +16 -0
- package/dist/benchmarks/agentbench.js +10 -0
- package/dist/benchmarks/agentbench.js.map +1 -0
- package/dist/benchmarks/appworld.d.ts +37 -0
- package/dist/benchmarks/appworld.js +14 -0
- package/dist/benchmarks/appworld.js.map +1 -0
- package/dist/benchmarks/bfcl.d.ts +18 -0
- package/dist/benchmarks/bfcl.js +10 -0
- package/dist/benchmarks/bfcl.js.map +1 -0
- package/dist/benchmarks/cad-design.d.ts +45 -0
- package/dist/benchmarks/cad-design.js +7 -0
- package/dist/benchmarks/cad-design.js.map +1 -0
- package/dist/benchmarks/cadbench.d.ts +19 -0
- package/dist/benchmarks/cadbench.js +8 -0
- package/dist/benchmarks/cadbench.js.map +1 -0
- package/dist/benchmarks/cadgenbench.d.ts +22 -0
- package/dist/benchmarks/cadgenbench.js +8 -0
- package/dist/benchmarks/cadgenbench.js.map +1 -0
- package/dist/benchmarks/commit0.d.ts +31 -0
- package/dist/benchmarks/commit0.js +10 -0
- package/dist/benchmarks/commit0.js.map +1 -0
- package/dist/benchmarks/crag.d.ts +14 -0
- package/dist/benchmarks/crag.js +9 -0
- package/dist/benchmarks/crag.js.map +1 -0
- package/dist/benchmarks/dabstep.d.ts +18 -0
- package/dist/benchmarks/dabstep.js +10 -0
- package/dist/benchmarks/dabstep.js.map +1 -0
- package/dist/benchmarks/enterpriseops-gym.d.ts +38 -0
- package/dist/benchmarks/enterpriseops-gym.js +10 -0
- package/dist/benchmarks/enterpriseops-gym.js.map +1 -0
- package/dist/benchmarks/finresearchbench.d.ts +15 -0
- package/dist/benchmarks/finresearchbench.js +8 -0
- package/dist/benchmarks/finresearchbench.js.map +1 -0
- package/dist/benchmarks/finsearchcomp.d.ts +49 -0
- package/dist/benchmarks/finsearchcomp.js +7 -0
- package/dist/benchmarks/finsearchcomp.js.map +1 -0
- package/dist/benchmarks/frames.d.ts +59 -0
- package/dist/benchmarks/frames.js +13 -0
- package/dist/benchmarks/frames.js.map +1 -0
- package/dist/benchmarks/hotpotqa.d.ts +48 -0
- package/dist/benchmarks/hotpotqa.js +15 -0
- package/dist/benchmarks/hotpotqa.js.map +1 -0
- package/dist/benchmarks/humaneval.d.ts +62 -0
- package/dist/benchmarks/humaneval.js +17 -0
- package/dist/benchmarks/humaneval.js.map +1 -0
- package/dist/benchmarks/mind2web.d.ts +41 -0
- package/dist/benchmarks/mind2web.js +9 -0
- package/dist/benchmarks/mind2web.js.map +1 -0
- package/dist/benchmarks/nomiracl.d.ts +15 -0
- package/dist/benchmarks/nomiracl.js +9 -0
- package/dist/benchmarks/nomiracl.js.map +1 -0
- package/dist/benchmarks/open-rag-bench.d.ts +14 -0
- package/dist/benchmarks/open-rag-bench.js +9 -0
- package/dist/benchmarks/open-rag-bench.js.map +1 -0
- package/dist/benchmarks/programbench.d.ts +38 -0
- package/dist/benchmarks/programbench.js +10 -0
- package/dist/benchmarks/programbench.js.map +1 -0
- package/dist/benchmarks/rag-shared.d.ts +42 -0
- package/dist/benchmarks/rag-shared.js +39 -0
- package/dist/benchmarks/rag-shared.js.map +1 -0
- package/dist/benchmarks/ragbench.d.ts +16 -0
- package/dist/benchmarks/ragbench.js +9 -0
- package/dist/benchmarks/ragbench.js.map +1 -0
- package/dist/benchmarks/simpleqa.d.ts +64 -0
- package/dist/benchmarks/simpleqa.js +11 -0
- package/dist/benchmarks/simpleqa.js.map +1 -0
- package/dist/benchmarks/swe-bench.d.ts +56 -0
- package/dist/benchmarks/swe-bench.js +14 -0
- package/dist/benchmarks/swe-bench.js.map +1 -0
- package/dist/benchmarks/t2-ragbench.d.ts +14 -0
- package/dist/benchmarks/t2-ragbench.js +9 -0
- package/dist/benchmarks/t2-ragbench.js.map +1 -0
- package/dist/benchmarks/tau-bench-shared.d.ts +26 -0
- package/dist/benchmarks/tau-bench-shared.js +10 -0
- package/dist/benchmarks/tau-bench-shared.js.map +1 -0
- package/dist/benchmarks/tau2-bench.d.ts +7 -0
- package/dist/benchmarks/tau2-bench.js +11 -0
- package/dist/benchmarks/tau2-bench.js.map +1 -0
- package/dist/benchmarks/tau3-banking.d.ts +15 -0
- package/dist/benchmarks/tau3-banking.js +9 -0
- package/dist/benchmarks/tau3-banking.js.map +1 -0
- package/dist/benchmarks/terminal-bench.d.ts +24 -0
- package/dist/benchmarks/terminal-bench.js +8 -0
- package/dist/benchmarks/terminal-bench.js.map +1 -0
- package/dist/benchmarks/toollm.d.ts +16 -0
- package/dist/benchmarks/toollm.js +10 -0
- package/dist/benchmarks/toollm.js.map +1 -0
- package/dist/benchmarks/trata-hedge.d.ts +32 -0
- package/dist/benchmarks/trata-hedge.js +7 -0
- package/dist/benchmarks/trata-hedge.js.map +1 -0
- package/dist/benchmarks/types.d.ts +107 -0
- package/dist/benchmarks/types.js +1 -0
- package/dist/benchmarks/types.js.map +1 -0
- package/dist/benchmarks/webarena-verified.d.ts +16 -0
- package/dist/benchmarks/webarena-verified.js +10 -0
- package/dist/benchmarks/webarena-verified.js.map +1 -0
- package/dist/chunk-2PVVP7GN.js +197 -0
- package/dist/chunk-2PVVP7GN.js.map +1 -0
- package/dist/chunk-2XU6OGEN.js +170 -0
- package/dist/chunk-2XU6OGEN.js.map +1 -0
- package/dist/chunk-53UPUNBZ.js +325 -0
- package/dist/chunk-53UPUNBZ.js.map +1 -0
- package/dist/chunk-5H5XV76F.js +240 -0
- package/dist/chunk-5H5XV76F.js.map +1 -0
- package/dist/chunk-7WSD27QQ.js +118 -0
- package/dist/chunk-7WSD27QQ.js.map +1 -0
- package/dist/chunk-C7T7WEK2.js +103 -0
- package/dist/chunk-C7T7WEK2.js.map +1 -0
- package/dist/chunk-CKUVRZ2T.js +251 -0
- package/dist/chunk-CKUVRZ2T.js.map +1 -0
- package/dist/chunk-HBSWHQNJ.js +30 -0
- package/dist/chunk-HBSWHQNJ.js.map +1 -0
- package/dist/chunk-HHXFIHXC.js +116 -0
- package/dist/chunk-HHXFIHXC.js.map +1 -0
- package/dist/chunk-IFAV6KEM.js +276 -0
- package/dist/chunk-IFAV6KEM.js.map +1 -0
- package/dist/chunk-INNOYXCP.js +387 -0
- package/dist/chunk-INNOYXCP.js.map +1 -0
- package/dist/chunk-J3KDJNX2.js +182 -0
- package/dist/chunk-J3KDJNX2.js.map +1 -0
- package/dist/chunk-JRWWGMK7.js +148 -0
- package/dist/chunk-JRWWGMK7.js.map +1 -0
- package/dist/chunk-JTHWEDEW.js +32 -0
- package/dist/chunk-JTHWEDEW.js.map +1 -0
- package/dist/chunk-KDIKRJGB.js +120 -0
- package/dist/chunk-KDIKRJGB.js.map +1 -0
- package/dist/chunk-LRRD7NAG.js +301 -0
- package/dist/chunk-LRRD7NAG.js.map +1 -0
- package/dist/chunk-ODT47UAY.js +221 -0
- package/dist/chunk-ODT47UAY.js.map +1 -0
- package/dist/chunk-PA2ZKHJC.js +230 -0
- package/dist/chunk-PA2ZKHJC.js.map +1 -0
- package/dist/chunk-PUIRNYI7.js +189 -0
- package/dist/chunk-PUIRNYI7.js.map +1 -0
- package/dist/chunk-PWQVGAJB.js +144 -0
- package/dist/chunk-PWQVGAJB.js.map +1 -0
- package/dist/chunk-R36V2VP7.js +169 -0
- package/dist/chunk-R36V2VP7.js.map +1 -0
- package/dist/chunk-R67DFVLO.js +142 -0
- package/dist/chunk-R67DFVLO.js.map +1 -0
- package/dist/chunk-SEVJPLZC.js +260 -0
- package/dist/chunk-SEVJPLZC.js.map +1 -0
- package/dist/chunk-SYDW647C.js +318 -0
- package/dist/chunk-SYDW647C.js.map +1 -0
- package/dist/chunk-TBKU5XQI.js +228 -0
- package/dist/chunk-TBKU5XQI.js.map +1 -0
- package/dist/chunk-TSWPNOYM.js +147 -0
- package/dist/chunk-TSWPNOYM.js.map +1 -0
- package/dist/chunk-UAIOHCUK.js +27 -0
- package/dist/chunk-UAIOHCUK.js.map +1 -0
- package/dist/chunk-UPAMRDX4.js +233 -0
- package/dist/chunk-UPAMRDX4.js.map +1 -0
- package/dist/chunk-VQRS7VUC.js +342 -0
- package/dist/chunk-VQRS7VUC.js.map +1 -0
- package/dist/chunk-X3BTXCJ4.js +262 -0
- package/dist/chunk-X3BTXCJ4.js.map +1 -0
- package/dist/chunk-X5YKXC6V.js +211 -0
- package/dist/chunk-X5YKXC6V.js.map +1 -0
- package/dist/chunk-Y6O2OCUO.js +130 -0
- package/dist/chunk-Y6O2OCUO.js.map +1 -0
- package/dist/chunk-YCGY7UIZ.js +208 -0
- package/dist/chunk-YCGY7UIZ.js.map +1 -0
- package/dist/chunk-Z7ML6L77.js +162 -0
- package/dist/chunk-Z7ML6L77.js.map +1 -0
- package/dist/chunk-ZEWMTR5M.js +136 -0
- package/dist/chunk-ZEWMTR5M.js.map +1 -0
- package/dist/index.d.ts +355 -0
- package/dist/index.js +1908 -0
- package/dist/index.js.map +1 -0
- package/package.json +26 -9
- package/scripts/run-package-tests.mjs +30 -8
- package/scripts/verify-packed-consumer.mjs +12 -1
- package/scripts/verify-pier-agent.mts +1 -0
- package/src/benchmarks/humaneval.test.mts +122 -0
- package/src/benchmarks/humaneval.ts +100 -27
- package/src/david-attribution.mts +78 -0
- package/src/david-goliath.mts +149 -0
- package/src/hev-improve.mts +25 -6
- package/src/humaneval-object-ablation.mts +201 -0
- package/src/live-improve-campaign-mbpp.mts +641 -0
- package/src/live-improve-campaign.mts +500 -0
- package/src/mbpp-structural.mts +12 -7
- package/src/stream-observe.py +45 -0
- package/src/stream-observe.tpl.html +247 -0
- package/src/supervisor-arena.mts +816 -0
- package/src/swe-arena/analyze.ts +211 -0
- package/src/swe-arena/arms.ts +788 -0
- package/src/swe-arena/bootstrap-meta.mts +188 -0
- package/src/swe-arena/bootstrap-meta.test.mts +51 -0
- package/src/swe-arena/calibrate.ts +116 -0
- package/src/swe-arena/capabilities.mts +76 -0
- package/src/swe-arena/capabilities.test.mts +57 -0
- package/src/swe-arena/capacity.ts +194 -0
- package/src/swe-arena/cell-evidence.mts +405 -0
- package/src/swe-arena/cell-evidence.test.mts +248 -0
- package/src/swe-arena/diagnosis-ensemble.test.mts +210 -0
- package/src/swe-arena/diagnosis-ensemble.ts +520 -0
- package/src/swe-arena/execution.test.mts +1170 -0
- package/src/swe-arena/fixtures/analyze.py +80 -0
- package/src/swe-arena/fixtures/excludes.txt +8 -0
- package/src/swe-arena/fixtures/gen1-salvage/README.md +45 -0
- package/src/swe-arena/fixtures/gen1-salvage/cand0-e6d7361.diff +116 -0
- package/src/swe-arena/fixtures/gen1-salvage/cand1-76a8590.diff +293 -0
- package/src/swe-arena/fixtures/holdout-preregister.log +12 -0
- package/src/swe-arena/fixtures/holdout.json +44 -0
- package/src/swe-arena/fixtures/instances.json +146 -0
- package/src/swe-arena/fixtures/ledger.jsonl +12 -0
- package/src/swe-arena/fixtures/patches/pallets__flask-5014.solo.patch +36 -0
- package/src/swe-arena/fixtures/patches/pydata__xarray-4687.sup.patch +33 -0
- package/src/swe-arena/fixtures/rejudge.jsonl +15 -0
- package/src/swe-arena/fixtures/rematch.jsonl +3 -0
- package/src/swe-arena/fixtures/rematch2.jsonl +3 -0
- package/src/swe-arena/fixtures/rematch3.jsonl +3 -0
- package/src/swe-arena/fixtures/sup-journal-true.json +19 -0
- package/src/swe-arena/fixtures/verify/astropy__astropy-13033.sh +48 -0
- package/src/swe-arena/fixtures/verify/django__django-11532.sh +50 -0
- package/src/swe-arena/fixtures/verify/matplotlib__matplotlib-20826.sh +76 -0
- package/src/swe-arena/fixtures/verify/pydata__xarray-4687.sh +44 -0
- package/src/swe-arena/fixtures/verify/pytest-dev__pytest-6197.sh +32 -0
- package/src/swe-arena/fixtures/verify/sphinx-doc__sphinx-9658.sh +51 -0
- package/src/swe-arena/fixtures/worker-tokens.json +42 -0
- package/src/swe-arena/fixtures.ts +104 -0
- package/src/swe-arena/holdout-certify.mts +408 -0
- package/src/swe-arena/holdout-certify.test.mts +160 -0
- package/src/swe-arena/judge-child.mts +37 -0
- package/src/swe-arena/manifest.mts +293 -0
- package/src/swe-arena/manifest.test.mts +169 -0
- package/src/swe-arena/materialize.ts +142 -0
- package/src/swe-arena/outer-loop.mts +2145 -0
- package/src/swe-arena/outer-loop.test.mts +696 -0
- package/src/swe-arena/parity.test.mts +87 -0
- package/src/swe-arena/proc.test.mts +174 -0
- package/src/swe-arena/proc.ts +260 -0
- package/src/swe-arena/profiles/default-author.profile.json +4 -0
- package/src/swe-arena/proposer-fanout.mts +489 -0
- package/src/swe-arena/proposer-fanout.test.mts +372 -0
- package/src/swe-arena/reconcile.ts +0 -0
- package/src/swe-arena/replay.mts +183 -0
- package/src/swe-arena/replay.test.mts +300 -0
- package/src/swe-arena/run-experiment.mts +361 -0
- package/src/swe-arena/run-supervisor.mjs +297 -0
- package/src/swe-arena/run-supervisor.test.mts +498 -0
- package/src/swe-arena/serialized-judge.ts +414 -0
- package/src/swe-arena/types.ts +166 -0
- package/src/swe-code-improve.mts +328 -0
- package/src/swe-emit-patch.mts +104 -0
- package/src/swe-improve.mts +232 -0
- package/src/swe-jail.ts +2 -2
- package/src/swe-local-proof.mts +169 -0
- package/src/swe-repro-calibrate.mts +446 -0
- package/src/swe-stream.mts +1497 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/benchmarks/humaneval.ts"],"sourcesContent":["/**\n * HumanEval adapter — the deployable-checker domain as a `BenchmarkAdapter`, so the\n * gate runner (`runGate`) can A/B the STEERING regime on it: a real rollout\n * through the `Supervisor` that self-corrects across rounds, vs blind\n * random@k. This is the experiment `humaneval-gate.mts` names as \"the next one\" —\n * the gate measures SELECTION over stateless single completions; this measures\n * whether observe→steer (self-correction) beats blind compute at equal k.\n *\n * Worker artifact = the model's reply (a Python function, fenced or raw). The\n * DETERMINISTIC judge runs the candidate against the task's own `test` in an\n * isolated `--network=none` python container — exit 0 = pass. No gold\n * `canonical_solution` is ever shown to the model; `goldArtifact` returns it only\n * to self-verify the judge before spending tokens.\n *\n * The primitives (loader / extractor / Docker checker) live here and are reused by\n * `humaneval-gate.mts` — one home, no duplication.\n */\n\nimport { execFile } from 'node:child_process'\nimport { chmodSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs'\nimport { tmpdir } from 'node:os'\nimport { join } from 'node:path'\nimport { gunzipSync } from 'node:zlib'\nimport type { BenchmarkAdapter, BenchScore, BenchTask, LoadOptions } from './types'\n\nconst humanevalUrl = 'https://github.com/openai/human-eval/raw/master/data/HumanEval.jsonl.gz'\nconst dockerImage = 'python:3.12-slim'\nconst dockerTimeoutMs = Number(process.env.DOCKER_TIMEOUT_MS ?? 20000)\n\nexport interface HumanEvalTask {\n taskId: string\n prompt: string\n test: string\n entryPoint: string\n /** Reference solution body — used ONLY to self-verify the judge, never shown to the worker. */\n canonicalSolution?: string\n}\n\n/** Pull the 164-task HumanEval JSONL.gz and parse it. Fail loud on a non-OK fetch\n * or a malformed line — a silently-short task set would poison the gate. `offset`\n * selects a deeper slice (the later tasks are harder) so the worker has a\n * correctable middle band rather than a saturated easy prefix. */\nexport async function loadHumanEval(limit: number, offset = 0): Promise<HumanEvalTask[]> {\n // Prefer a locally-cached .jsonl.gz (HUMANEVAL_GZ) — the GitHub raw URL rate-limits\n // (429) under repeated runs. Fall back to the network fetch when unset.\n const localGz = process.env.HUMANEVAL_GZ\n let gz: Buffer\n if (localGz) {\n gz = readFileSync(localGz)\n } else {\n const res = await fetch(humanevalUrl)\n if (!res.ok) throw new Error(`HumanEval fetch HTTP ${res.status}: ${humanevalUrl}`)\n gz = Buffer.from(await res.arrayBuffer())\n }\n const text = gunzipSync(gz).toString('utf8')\n const tasks: HumanEvalTask[] = []\n for (const line of text.split('\\n')) {\n if (line.trim() === '') continue\n const d = JSON.parse(line) as {\n task_id?: string\n prompt?: string\n test?: string\n entry_point?: string\n canonical_solution?: string\n }\n if (!d.task_id || !d.prompt || !d.test || !d.entry_point) {\n throw new Error(`malformed HumanEval record: ${line.slice(0, 120)}`)\n }\n tasks.push({\n taskId: d.task_id,\n prompt: d.prompt,\n test: d.test,\n entryPoint: d.entry_point,\n ...(d.canonical_solution ? { canonicalSolution: d.canonical_solution } : {}),\n })\n }\n if (tasks.length === 0) throw new Error('HumanEval parsed to 0 tasks')\n if (offset >= tasks.length) throw new Error(`OFFSET ${offset} >= dataset size ${tasks.length}`)\n return tasks.slice(offset, offset + limit)\n}\n\nconst solveInstruction =\n 'Complete the following Python function. Output the COMPLETE function definition (signature, docstring optional, body) inside a single ```python code block. Include any imports the function needs. Do not write tests or example calls.'\n\nexport function basePrompt(task: HumanEvalTask): string {\n return `${solveInstruction}\\n\\n\\`\\`\\`python\\n${task.prompt}\\`\\`\\``\n}\n\n/** Extract the function source from a model reply: prefer a fenced ```python (or\n * bare ```) block, else fall back to the raw text. The deployable program adds the\n * prompt header (imports + signature context), so a candidate that returns only a\n * body still runs; a candidate that re-defines the function shadows the header. */\nexport function extractCode(reply: string): string {\n const fenced = reply.match(/```(?:python|py)?\\s*\\n([\\s\\S]*?)```/i)\n if (fenced && typeof fenced[1] === 'string') return fenced[1].trim()\n return reply.trim()\n}\n\n/** The deployable test program: the prompt header (imports + signature/docstring the\n * model was given), then the candidate (its def shadows the header's stub), then the\n * task's own check() suite and the call. No gold solution anywhere. */\nfunction buildProgram(task: HumanEvalTask, candidate: string): string {\n return `${task.prompt}\\n${candidate}\\n\\n${task.test}\\n\\ncheck(${task.entryPoint})\\n`\n}\n\nexport interface CheckResult {\n /** {0,1} pass-count for this candidate (1 = the check() suite passed). */\n pass: number\n /** On failure: the interpreter stderr tail (traceback / failing assertion). The\n * execution-grounded feedback a self-repair loop steers on; ignored by selection. */\n detail?: string\n}\n\nexport interface PythonProgramResult {\n exitCode: number\n stdout: string\n stderr: string\n}\n\n/** Run one candidate's deployable test program in an isolated container:\n * read-only root, bounded writable `/tmp`, no network, one CPU, and 512 MiB.\n * Exit 0 → pass. A docker invocation error (binary missing, daemon down, image\n * unavailable) is NOT a test failure — it throws so the harness fails loud rather\n * than scoring every candidate 0 from a broken checker. */\nlet dockerRunSeq = 0\n\n/** Run arbitrary Python in the same isolated container used by the HumanEval\n * checker. This is also the execution-tool primitive for experiments that let\n * a model test its own snippets; model-written code must never run on the host. */\nexport function runPythonProgram(\n program: string,\n timeoutMs = dockerTimeoutMs,\n): Promise<PythonProgramResult> {\n const dir = mkdtempSync(join(tmpdir(), 'hev-'))\n // Rootless Docker maps container root to a subordinate host uid that cannot\n // traverse mkdtemp's default 0700 directory. The directory contains only the\n // disposable candidate script and is mounted read-only into the container.\n chmodSync(dir, 0o755)\n writeFileSync(join(dir, 'p.py'), program, { mode: 0o644 })\n // Unique container name so we can force-reap it regardless of the docker client's state.\n const name = `hev-${process.pid}-${dockerRunSeq++}`\n const startMarker = `__AGENT_RUNTIME_CANDIDATE_STARTED_${name}__`\n return new Promise<PythonProgramResult>((resolvePromise, reject) => {\n let settled = false\n const cleanup = () => {\n rmSync(dir, { recursive: true, force: true })\n // `execFile`'s `timeout` kills the docker CLIENT, not the container — a hung\n // `python` would otherwise pin a CPU forever. Force-reap by name (fire-and-forget;\n // the name is unique, so no reuse race).\n execFile('docker', ['rm', '-f', name], () => {})\n }\n const finish = (res: PythonProgramResult) => {\n if (settled) return\n settled = true\n clearTimeout(backstop)\n cleanup()\n resolvePromise(res)\n }\n const fail = (e: Error) => {\n if (settled) return\n settled = true\n clearTimeout(backstop)\n cleanup()\n reject(e)\n }\n // Candidate timeouts are enforced inside the container. If the outer Docker\n // client or daemon misses this larger deadline, that is infrastructure failure,\n // not a wrong answer.\n const outerTimeoutMs = timeoutMs + 3_000\n const backstop = setTimeout(\n () => fail(new Error(`docker checker did not return within ${outerTimeoutMs + 3_000}ms`)),\n outerTimeoutMs + 3_000,\n )\n const inContainerSeconds = Math.max(1, Math.ceil(timeoutMs / 1_000))\n execFile(\n 'docker',\n [\n 'run',\n '--rm',\n '--pull=never',\n '--name',\n name,\n '--network=none',\n '--cpus=1',\n '--memory=512m',\n '--pids-limit=64',\n '--cap-drop=ALL',\n '--security-opt=no-new-privileges',\n '--read-only',\n '--tmpfs',\n '/tmp:rw,nosuid,nodev,noexec,size=64m,mode=1777',\n '--user',\n '65534:65534',\n '-v',\n `${dir}:/w:ro`,\n '-w',\n '/w',\n dockerImage,\n 'sh',\n '-c',\n 'command -v timeout >/dev/null 2>&1 && command -v python >/dev/null 2>&1 && [ -r /w/p.py ] || exit 126; printf \"%s\\\\n\" \"$1\"; exec timeout -s KILL \"$2\" python /w/p.py',\n 'agent-runtime-checker',\n startMarker,\n `${inContainerSeconds}s`,\n ],\n { timeout: outerTimeoutMs, killSignal: 'SIGKILL', maxBuffer: 4 * 1024 * 1024 },\n (err, stdout, stderr) => {\n const markerLine = `${startMarker}\\n`\n const candidateStarted = stdout?.startsWith(markerLine) === true\n const candidateStdout = candidateStarted ? stdout.slice(markerLine.length) : (stdout ?? '')\n if (err) {\n const e = err as Error & { killed?: boolean; code?: number | string }\n if (e.code === 'ENOENT') {\n fail(new Error('docker binary not found on PATH — cannot run the deployable checker'))\n return\n }\n if (e.killed) {\n fail(new Error(`docker checker exceeded its ${outerTimeoutMs}ms outer timeout`))\n return\n }\n if (!candidateStarted) {\n if (\n /cannot connect to the docker daemon|is the docker daemon running|permission denied while trying to connect/i.test(\n stderr,\n )\n ) {\n fail(new Error(`docker daemon unreachable: ${stderr.slice(0, 200)}`))\n return\n }\n if (/unable to find image|no such image|pull access denied|manifest unknown/i.test(stderr)) {\n fail(new Error(`docker image ${dockerImage} unavailable: ${stderr.slice(0, 200)}`))\n return\n }\n fail(\n new Error(\n `docker checker did not start the candidate: ${stderr.slice(0, 200) || e.message}`,\n ),\n )\n return\n }\n const exitCode = typeof e.code === 'number' ? e.code : 1\n finish({\n exitCode,\n stdout: candidateStdout,\n stderr: stderr ?? '',\n })\n return\n }\n if (!candidateStarted) {\n fail(new Error('docker checker exited without starting the candidate'))\n return\n }\n finish({ exitCode: 0, stdout: candidateStdout, stderr: stderr ?? '' })\n },\n )\n })\n}\n\nexport async function runChecker(task: HumanEvalTask, candidate: string): Promise<CheckResult> {\n const result = await runPythonProgram(buildProgram(task, candidate))\n return result.exitCode === 0\n ? { pass: 1 }\n : { pass: 0, detail: result.stderr.slice(-600) || 'timed out (no output)' }\n}\n\n/** A HumanEval task carries its checker inputs in metadata so the deterministic\n * judge can rebuild the deployable program from a `BenchTask` alone. */\ninterface HumanEvalMeta extends Record<string, unknown> {\n promptHeader: string\n test: string\n entryPoint: string\n canonicalSolution?: string\n}\n\nfunction toBenchTask(t: HumanEvalTask): BenchTask {\n const metadata: HumanEvalMeta = {\n promptHeader: t.prompt,\n test: t.test,\n entryPoint: t.entryPoint,\n ...(t.canonicalSolution ? { canonicalSolution: t.canonicalSolution } : {}),\n }\n return { id: t.taskId, prompt: basePrompt(t), metadata }\n}\n\nfunction taskFromMeta(task: BenchTask): HumanEvalTask {\n const m = task.metadata as HumanEvalMeta | undefined\n if (!m?.promptHeader || !m.test || !m.entryPoint) {\n throw new Error(`HumanEval judge: task ${task.id} missing checker metadata`)\n }\n return { taskId: task.id, prompt: m.promptHeader, test: m.test, entryPoint: m.entryPoint }\n}\n\n/** The HumanEval `BenchmarkAdapter`. OFFSET (env) selects the correctable middle\n * band; loadTasks honors `limit`/`ids`. The judge is the Docker deployable checker. */\nexport function createHumanEvalAdapter(): BenchmarkAdapter {\n return {\n name: 'humaneval',\n async preflight() {\n // Prove the daemon and exact local image before any model call. Scoring uses\n // --pull=never so a registry or cold pull cannot become a candidate outcome.\n await new Promise<void>((resolve, reject) => {\n execFile('docker', ['version', '--format', '{{.Server.Version}}'], (err) => {\n if (err) reject(new Error('HumanEval judge needs a running Docker daemon (python:3.12-slim, --network=none)'))\n else resolve()\n })\n })\n await new Promise<void>((resolve, reject) => {\n execFile('docker', ['image', 'inspect', dockerImage], (err) => {\n if (err) reject(new Error(`HumanEval judge needs the cached Docker image ${dockerImage}`))\n else resolve()\n })\n })\n },\n async loadTasks(opts?: LoadOptions) {\n const offset = Number(process.env.OFFSET ?? 0)\n // Pull a generous window when filtering by id, else exactly `limit` from offset.\n const all = await loadHumanEval(opts?.ids ? 164 : (opts?.limit ?? 8), offset)\n const picked = opts?.ids ? all.filter((t) => opts.ids?.includes(t.taskId)) : all\n return picked.map(toBenchTask)\n },\n async judge(task: BenchTask, artifact: string): Promise<BenchScore> {\n const { pass } = await runChecker(taskFromMeta(task), extractCode(artifact))\n return { resolved: pass === 1, score: pass, detail: pass === 1 ? 'tests passed' : 'tests failed' }\n },\n async goldArtifact(task: BenchTask) {\n const m = task.metadata as HumanEvalMeta | undefined\n const sol = m?.canonicalSolution\n // Return the COMPLETE function (signature header + canonical body), i.e. what a\n // real worker emits — NOT the body alone. The judge runs `extractCode`, whose\n // unfenced fallback is `reply.trim()`; trimming a body-only string strips its\n // leading indent and breaks it, so a body-only gold fails its own judge. A full\n // def starts at column 0, trims safely, and self-verifies.\n return sol ? `${m!.promptHeader}${sol}` : undefined\n },\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import {
|
|
2
|
+
benchRoot
|
|
3
|
+
} from "./chunk-LRRD7NAG.js";
|
|
4
|
+
|
|
5
|
+
// src/benchmarks/agentbench.ts
|
|
6
|
+
import { readFile } from "fs/promises";
|
|
7
|
+
import { join } from "path";
|
|
8
|
+
var FIXTURES = join(benchRoot, "fixtures", "agentbench-dbbench.json");
|
|
9
|
+
var DEFAULT_SPLIT = "dev";
|
|
10
|
+
var agentbenchDir = () => process.env.AGENTBENCH_DIR;
|
|
11
|
+
var agentbenchAnswerOutput = {
|
|
12
|
+
parse(events) {
|
|
13
|
+
let text = "";
|
|
14
|
+
for (const ev of events) {
|
|
15
|
+
const d = ev?.data;
|
|
16
|
+
const t = d?.finalText ?? d?.text ?? d?.result;
|
|
17
|
+
if (typeof t === "string" && t.length > 0) text = t;
|
|
18
|
+
}
|
|
19
|
+
const fences = [...text.matchAll(/```(?:text|answer)?\s*\n([\s\S]*?)```/g)];
|
|
20
|
+
return (fences.at(-1)?.[1] ?? text).trim();
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
function normalizeAnswer(value) {
|
|
24
|
+
return value.toLowerCase().replace(/\s+/g, " ").replace(/^["'`]+|["'`]+$/g, "").trim();
|
|
25
|
+
}
|
|
26
|
+
function rowToTask(row, index, split) {
|
|
27
|
+
const columns = row.table?.table_info?.columns?.map((c) => `${c.name}${c.type ? ` (${c.type})` : ""}`).join(", ");
|
|
28
|
+
const sampleRows = row.table?.table_info?.rows?.slice(0, 40);
|
|
29
|
+
const meta = {
|
|
30
|
+
labels: row.label,
|
|
31
|
+
split,
|
|
32
|
+
subset: "dbbench",
|
|
33
|
+
table: row.table
|
|
34
|
+
};
|
|
35
|
+
return {
|
|
36
|
+
id: `dbbench-${split}-${index}`,
|
|
37
|
+
split,
|
|
38
|
+
prompt: [
|
|
39
|
+
"Answer this AgentBench DBBench question using the table below.",
|
|
40
|
+
"Return only the answer value.",
|
|
41
|
+
"",
|
|
42
|
+
`Question: ${row.description}`,
|
|
43
|
+
row.table?.table_name ? `Table: ${row.table.table_name}` : void 0,
|
|
44
|
+
columns ? `Columns: ${columns}` : void 0,
|
|
45
|
+
sampleRows ? `Rows JSON: ${JSON.stringify(sampleRows)}` : void 0
|
|
46
|
+
].filter(Boolean).join("\n"),
|
|
47
|
+
metadata: meta
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function readMeta(task) {
|
|
51
|
+
const md = task.metadata;
|
|
52
|
+
if (!md || !Array.isArray(md.labels)) {
|
|
53
|
+
throw new Error(`agentbench task ${task.id} missing metadata \u2014 loadTasks did not populate it`);
|
|
54
|
+
}
|
|
55
|
+
return md;
|
|
56
|
+
}
|
|
57
|
+
function selectRows(rows, opts, split) {
|
|
58
|
+
let tasks = rows.map((row, index) => rowToTask(row, index, split));
|
|
59
|
+
if (opts.ids) {
|
|
60
|
+
const want = new Set(opts.ids);
|
|
61
|
+
tasks = tasks.filter((task) => want.has(task.id));
|
|
62
|
+
} else if (opts.limit !== void 0) {
|
|
63
|
+
tasks = tasks.slice(0, opts.limit);
|
|
64
|
+
}
|
|
65
|
+
if (tasks.length === 0) throw new Error(`AgentBench DBBench: no tasks matched ${JSON.stringify(opts)}`);
|
|
66
|
+
return tasks;
|
|
67
|
+
}
|
|
68
|
+
async function loadJsonl(path) {
|
|
69
|
+
const raw = await readFile(path, "utf8");
|
|
70
|
+
return raw.split("\n").map((line) => line.trim()).filter(Boolean).map((line) => JSON.parse(line));
|
|
71
|
+
}
|
|
72
|
+
async function loadFixtures(opts, split) {
|
|
73
|
+
const rows = JSON.parse(await readFile(FIXTURES, "utf8"));
|
|
74
|
+
console.warn(`[agentbench] AGENTBENCH_FIXTURES=1 \u2014 loading ${rows.length} DBBench adapter fixtures`);
|
|
75
|
+
return selectRows(rows, opts, split);
|
|
76
|
+
}
|
|
77
|
+
function createAgentBenchAdapter() {
|
|
78
|
+
const fixturesMode = process.env.AGENTBENCH_FIXTURES === "1";
|
|
79
|
+
return {
|
|
80
|
+
name: "agentbench",
|
|
81
|
+
output: agentbenchAnswerOutput,
|
|
82
|
+
async preflight() {
|
|
83
|
+
if (fixturesMode) return;
|
|
84
|
+
const dir = agentbenchDir();
|
|
85
|
+
if (!dir) {
|
|
86
|
+
throw new Error("AGENTBENCH_DIR is required. Fix: clone https://github.com/THUDM/AgentBench and set AGENTBENCH_DIR=/path/to/AgentBench.");
|
|
87
|
+
}
|
|
88
|
+
await loadJsonl(join(dir, "data", "dbbench", `${DEFAULT_SPLIT}.jsonl`));
|
|
89
|
+
},
|
|
90
|
+
async loadTasks(opts = {}) {
|
|
91
|
+
const split = opts.split ?? DEFAULT_SPLIT;
|
|
92
|
+
if (fixturesMode) return loadFixtures(opts, split);
|
|
93
|
+
const dir = agentbenchDir();
|
|
94
|
+
if (!dir) throw new Error("AGENTBENCH_DIR is required to load AgentBench DBBench tasks");
|
|
95
|
+
return selectRows(await loadJsonl(join(dir, "data", "dbbench", `${split}.jsonl`)), opts, split);
|
|
96
|
+
},
|
|
97
|
+
async goldArtifact(task) {
|
|
98
|
+
return readMeta(task).labels[0];
|
|
99
|
+
},
|
|
100
|
+
async judge(task, artifact) {
|
|
101
|
+
const meta = readMeta(task);
|
|
102
|
+
const got = normalizeAnswer(artifact);
|
|
103
|
+
const expected = meta.labels.map(normalizeAnswer);
|
|
104
|
+
const resolved = expected.includes(got);
|
|
105
|
+
return {
|
|
106
|
+
resolved,
|
|
107
|
+
score: resolved ? 1 : 0,
|
|
108
|
+
detail: JSON.stringify({ subset: meta.subset, split: meta.split, expected: meta.labels, got: artifact })
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export {
|
|
115
|
+
agentbenchAnswerOutput,
|
|
116
|
+
createAgentBenchAdapter
|
|
117
|
+
};
|
|
118
|
+
//# sourceMappingURL=chunk-7WSD27QQ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/benchmarks/agentbench.ts"],"sourcesContent":["/**\n * AgentBench deterministic subset adapter.\n *\n * This targets AgentBench DBBench rows only: question + table + published label.\n * It does not wrap AgentBench's controller protocol or the non-deterministic game\n * environments. Worker artifact = final answer text. Judge = exact match against\n * the official DBBench label list after light whitespace/case normalization.\n */\n\nimport { readFile } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport type { OutputAdapter } from '@tangle-network/agent-runtime/loops'\nimport { benchRoot } from './_harness'\nimport type { BenchmarkAdapter, BenchScore, BenchTask, LoadOptions } from './types'\n\nconst FIXTURES = join(benchRoot, 'fixtures', 'agentbench-dbbench.json')\nconst DEFAULT_SPLIT = 'dev'\n\ninterface AgentBenchDbRow {\n description: string\n label: string[]\n table?: {\n table_name?: string\n table_info?: {\n columns?: Array<{ name: string; type?: string }>\n rows?: unknown[][]\n }\n }\n}\n\ninterface AgentBenchMeta {\n labels: string[]\n split: string\n subset: 'dbbench'\n table?: AgentBenchDbRow['table']\n}\n\nconst agentbenchDir = (): string | undefined => process.env.AGENTBENCH_DIR\n\nexport const agentbenchAnswerOutput: OutputAdapter<string> = {\n parse(events) {\n let text = ''\n for (const ev of events) {\n const d = (ev as { data?: Record<string, unknown> })?.data\n const t = d?.finalText ?? d?.text ?? d?.result\n if (typeof t === 'string' && t.length > 0) text = t\n }\n const fences = [...text.matchAll(/```(?:text|answer)?\\s*\\n([\\s\\S]*?)```/g)]\n return (fences.at(-1)?.[1] ?? text).trim()\n },\n}\n\nfunction normalizeAnswer(value: string): string {\n return value\n .toLowerCase()\n .replace(/\\s+/g, ' ')\n .replace(/^[\"'`]+|[\"'`]+$/g, '')\n .trim()\n}\n\nfunction rowToTask(row: AgentBenchDbRow, index: number, split: string): BenchTask {\n const columns = row.table?.table_info?.columns?.map((c) => `${c.name}${c.type ? ` (${c.type})` : ''}`).join(', ')\n const sampleRows = row.table?.table_info?.rows?.slice(0, 40)\n const meta: AgentBenchMeta = {\n labels: row.label,\n split,\n subset: 'dbbench',\n table: row.table,\n }\n return {\n id: `dbbench-${split}-${index}`,\n split,\n prompt: [\n 'Answer this AgentBench DBBench question using the table below.',\n 'Return only the answer value.',\n '',\n `Question: ${row.description}`,\n row.table?.table_name ? `Table: ${row.table.table_name}` : undefined,\n columns ? `Columns: ${columns}` : undefined,\n sampleRows ? `Rows JSON: ${JSON.stringify(sampleRows)}` : undefined,\n ]\n .filter(Boolean)\n .join('\\n'),\n metadata: meta as unknown as Record<string, unknown>,\n }\n}\n\nfunction readMeta(task: BenchTask): AgentBenchMeta {\n const md = task.metadata\n if (!md || !Array.isArray(md.labels)) {\n throw new Error(`agentbench task ${task.id} missing metadata — loadTasks did not populate it`)\n }\n return md as unknown as AgentBenchMeta\n}\n\nfunction selectRows(rows: AgentBenchDbRow[], opts: LoadOptions, split: string): BenchTask[] {\n let tasks = rows.map((row, index) => rowToTask(row, index, split))\n if (opts.ids) {\n const want = new Set(opts.ids)\n tasks = tasks.filter((task) => want.has(task.id))\n } else if (opts.limit !== undefined) {\n tasks = tasks.slice(0, opts.limit)\n }\n if (tasks.length === 0) throw new Error(`AgentBench DBBench: no tasks matched ${JSON.stringify(opts)}`)\n return tasks\n}\n\nasync function loadJsonl(path: string): Promise<AgentBenchDbRow[]> {\n const raw = await readFile(path, 'utf8')\n return raw\n .split('\\n')\n .map((line) => line.trim())\n .filter(Boolean)\n .map((line) => JSON.parse(line) as AgentBenchDbRow)\n}\n\nasync function loadFixtures(opts: LoadOptions, split: string): Promise<BenchTask[]> {\n const rows = JSON.parse(await readFile(FIXTURES, 'utf8')) as AgentBenchDbRow[]\n console.warn(`[agentbench] AGENTBENCH_FIXTURES=1 — loading ${rows.length} DBBench adapter fixtures`)\n return selectRows(rows, opts, split)\n}\n\nexport function createAgentBenchAdapter(): BenchmarkAdapter {\n const fixturesMode = process.env.AGENTBENCH_FIXTURES === '1'\n\n return {\n name: 'agentbench',\n output: agentbenchAnswerOutput,\n\n async preflight() {\n if (fixturesMode) return\n const dir = agentbenchDir()\n if (!dir) {\n throw new Error('AGENTBENCH_DIR is required. Fix: clone https://github.com/THUDM/AgentBench and set AGENTBENCH_DIR=/path/to/AgentBench.')\n }\n await loadJsonl(join(dir, 'data', 'dbbench', `${DEFAULT_SPLIT}.jsonl`))\n },\n\n async loadTasks(opts: LoadOptions = {}) {\n const split = opts.split ?? DEFAULT_SPLIT\n if (fixturesMode) return loadFixtures(opts, split)\n const dir = agentbenchDir()\n if (!dir) throw new Error('AGENTBENCH_DIR is required to load AgentBench DBBench tasks')\n return selectRows(await loadJsonl(join(dir, 'data', 'dbbench', `${split}.jsonl`)), opts, split)\n },\n\n async goldArtifact(task: BenchTask) {\n return readMeta(task).labels[0]\n },\n\n async judge(task: BenchTask, artifact: string): Promise<BenchScore> {\n const meta = readMeta(task)\n const got = normalizeAnswer(artifact)\n const expected = meta.labels.map(normalizeAnswer)\n const resolved = expected.includes(got)\n return {\n resolved,\n score: resolved ? 1 : 0,\n detail: JSON.stringify({ subset: meta.subset, split: meta.split, expected: meta.labels, got: artifact }),\n }\n },\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
// src/benchmarks/cadgenbench.ts
|
|
2
|
+
import { execFile as execFile2 } from "child_process";
|
|
3
|
+
import { mkdtemp as mkdtemp2, rm as rm2, writeFile as writeFile2 } from "fs/promises";
|
|
4
|
+
import { tmpdir as tmpdir2 } from "os";
|
|
5
|
+
import { join as join2 } from "path";
|
|
6
|
+
import { promisify as promisify2 } from "util";
|
|
7
|
+
|
|
8
|
+
// src/worker-build123d.ts
|
|
9
|
+
import { execFile } from "child_process";
|
|
10
|
+
import { existsSync, readFileSync } from "fs";
|
|
11
|
+
import { mkdtemp, readFile, rm, writeFile } from "fs/promises";
|
|
12
|
+
import { tmpdir } from "os";
|
|
13
|
+
import { join } from "path";
|
|
14
|
+
import { promisify } from "util";
|
|
15
|
+
import { routerChatWithUsage } from "@tangle-network/agent-runtime/loops";
|
|
16
|
+
var execFileAsync = promisify(execFile);
|
|
17
|
+
var CGB_VENV_PY = process.env.CADGENBENCH_VENV ?? "/tmp/cgb-venv/bin/python";
|
|
18
|
+
var CGB_DIR = process.env.CADGENBENCH_DIR ?? "/tmp/cadgenbench";
|
|
19
|
+
|
|
20
|
+
// src/benchmarks/cadgenbench.ts
|
|
21
|
+
var execFileAsync2 = promisify2(execFile2);
|
|
22
|
+
var SCORE_PY = `
|
|
23
|
+
import sys, json, tempfile, shutil
|
|
24
|
+
from pathlib import Path
|
|
25
|
+
from cadgenbench.eval.evaluate import evaluate_result
|
|
26
|
+
cand, gt = Path(sys.argv[1]), Path(sys.argv[2])
|
|
27
|
+
with tempfile.TemporaryDirectory() as rd, tempfile.TemporaryDirectory() as gd:
|
|
28
|
+
rd, gd = Path(rd), Path(gd)
|
|
29
|
+
(rd / 'result.json').write_text('{}')
|
|
30
|
+
shutil.copy(gt, gd / 'ground_truth.step')
|
|
31
|
+
try:
|
|
32
|
+
evaluate_result(rd, gd, candidate_step=cand)
|
|
33
|
+
d = json.loads((rd / 'result.json').read_text())
|
|
34
|
+
print('CGB_SCORE ' + json.dumps({'cad_score': d.get('cad_score', 0.0), 'status': d.get('status', 'unknown')}))
|
|
35
|
+
except Exception as e:
|
|
36
|
+
print('CGB_SCORE ' + json.dumps({'cad_score': 0.0, 'status': 'error', 'error': str(e)[:200]}))
|
|
37
|
+
`.trim();
|
|
38
|
+
function fixtureTasks() {
|
|
39
|
+
const g = join2(CGB_DIR, "tests/fixtures/geometry");
|
|
40
|
+
return [
|
|
41
|
+
{ id: "box-10x20x30", prompt: "A rectangular solid box, 10 units wide (X), 20 units deep (Y), and 30 units tall (Z).", gtStep: join2(g, "box_10_20_30.step") },
|
|
42
|
+
{ id: "cube-10", prompt: "A cube, 10 units on every side.", gtStep: join2(g, "box_10_10_10.step") },
|
|
43
|
+
{ id: "sphere-10", prompt: "A sphere of radius 10 units, centered at the origin.", gtStep: join2(g, "sphere_10.step") }
|
|
44
|
+
];
|
|
45
|
+
}
|
|
46
|
+
function createCadGenBenchAdapter() {
|
|
47
|
+
return {
|
|
48
|
+
name: "cadgenbench",
|
|
49
|
+
async preflight() {
|
|
50
|
+
const r = await execFileAsync2(CGB_VENV_PY, ["-c", 'import cadgenbench.eval.evaluate, build123d, trimesh, manifold3d; print("ok")'], { timeout: 6e4 }).catch(
|
|
51
|
+
(e) => ({ stdout: "", stderr: e instanceof Error ? e.message : String(e) })
|
|
52
|
+
);
|
|
53
|
+
if (!/ok/.test(r.stdout)) {
|
|
54
|
+
throw new Error(
|
|
55
|
+
`cadgenbench preflight failed (venv=${CGB_VENV_PY}): ${r.stderr.slice(0, 200)}
|
|
56
|
+
Fix: git clone https://github.com/huggingface/cadgenbench ${CGB_DIR}; python3 -m venv $CADGENBENCH_VENV; $CADGENBENCH_VENV/bin/pip install -e ${CGB_DIR}`
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
async loadTasks(opts = {}) {
|
|
61
|
+
let tasks = fixtureTasks();
|
|
62
|
+
const hard = process.env.CGB_HARD_DIR;
|
|
63
|
+
if (hard) {
|
|
64
|
+
const { readFile: readFile2 } = await import("fs/promises");
|
|
65
|
+
tasks = JSON.parse(await readFile2(join2(hard, "tasks.json"), "utf8"));
|
|
66
|
+
}
|
|
67
|
+
if (opts.ids) tasks = tasks.filter((t) => opts.ids.includes(t.id));
|
|
68
|
+
if (opts.limit != null) tasks = tasks.slice(0, opts.limit);
|
|
69
|
+
const meta = (gtStep) => ({ gtStep, resolveThreshold: Number(process.env.CGB_RESOLVE_THRESHOLD ?? 0.9) });
|
|
70
|
+
return tasks.map((t) => ({ id: t.id, prompt: t.prompt, metadata: meta(t.gtStep) }));
|
|
71
|
+
},
|
|
72
|
+
async goldArtifact() {
|
|
73
|
+
return void 0;
|
|
74
|
+
},
|
|
75
|
+
async judge(task, artifact) {
|
|
76
|
+
const { gtStep, resolveThreshold } = task.metadata;
|
|
77
|
+
if (!artifact.includes("ISO-10303-21")) return { resolved: false, score: 0, detail: "artifact is not a STEP file" };
|
|
78
|
+
const dir = await mkdtemp2(join2(tmpdir2(), "cgb-judge-"));
|
|
79
|
+
const cand = join2(dir, "candidate.step");
|
|
80
|
+
const scorer = join2(dir, "score.py");
|
|
81
|
+
try {
|
|
82
|
+
await writeFile2(cand, artifact);
|
|
83
|
+
await writeFile2(scorer, SCORE_PY);
|
|
84
|
+
const r = await execFileAsync2("xvfb-run", ["-a", CGB_VENV_PY, scorer, cand, gtStep], { maxBuffer: 1 << 26, timeout: 18e4 }).catch(
|
|
85
|
+
(e) => ({ stdout: e.stdout ?? "", stderr: e instanceof Error ? e.message : String(e) })
|
|
86
|
+
);
|
|
87
|
+
const m = /CGB_SCORE (\{.*\})/.exec(r.stdout);
|
|
88
|
+
if (!m) return { resolved: false, score: 0, detail: `scorer produced no verdict: ${(r.stderr || r.stdout).slice(0, 160)}` };
|
|
89
|
+
const v = JSON.parse(m[1]);
|
|
90
|
+
const score = typeof v.cad_score === "number" ? v.cad_score : 0;
|
|
91
|
+
return { resolved: score >= resolveThreshold, score, detail: `cad_score=${score.toFixed(3)} status=${v.status}${v.error ? ` (${v.error})` : ""}` };
|
|
92
|
+
} finally {
|
|
93
|
+
await rm2(dir, { recursive: true, force: true }).catch(() => {
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export {
|
|
101
|
+
createCadGenBenchAdapter
|
|
102
|
+
};
|
|
103
|
+
//# sourceMappingURL=chunk-C7T7WEK2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/benchmarks/cadgenbench.ts","../src/worker-build123d.ts"],"sourcesContent":["/**\n * CADGenBench adapter (huggingface/cadgenbench, Apache-2.0). Task = a part\n * description → a STEP B-rep solid (output.step). Score = the benchmark's OWN\n * deterministic geometric metric (cad_score): validity gate → PCA/ICP align to\n * the ground truth → point-cloud F1 + volume IoU + edge F1 + topology match.\n * NOT an LLM judge, NOT self-defined checks — the published CAD kernel decides.\n *\n * The official task set (private GT, server-side graded) isn't released yet, so\n * tasks here are seeded from the repo's dimension-named geometry fixtures (real\n * GT STEPs scored by the real scorer). When CADGENBENCH_DATA_DIR is set, swap\n * loadTasks to read the published fixtures' description.yaml + ground_truth.step.\n *\n * Requires the CADGenBench venv (CADGENBENCH_VENV) + clone (CADGENBENCH_DIR) +\n * xvfb (the scorer's alignment renders need a display).\n */\n\nimport { execFile } from 'node:child_process'\nimport { mkdtemp, rm, writeFile } from 'node:fs/promises'\nimport { tmpdir } from 'node:os'\nimport { join } from 'node:path'\nimport { promisify } from 'node:util'\nimport type { BenchScore, BenchTask, BenchmarkAdapter, LoadOptions } from './types'\nimport { CGB_DIR, CGB_VENV_PY } from '../worker-build123d'\n\nconst execFileAsync = promisify(execFile)\n\n/** Self-contained scorer wrapper (written to a temp file, run in the venv).\n * Scores a candidate STEP against a ground-truth STEP via the benchmark's own\n * evaluate_result, printing the cad_score line. */\nconst SCORE_PY = `\nimport sys, json, tempfile, shutil\nfrom pathlib import Path\nfrom cadgenbench.eval.evaluate import evaluate_result\ncand, gt = Path(sys.argv[1]), Path(sys.argv[2])\nwith tempfile.TemporaryDirectory() as rd, tempfile.TemporaryDirectory() as gd:\n rd, gd = Path(rd), Path(gd)\n (rd / 'result.json').write_text('{}')\n shutil.copy(gt, gd / 'ground_truth.step')\n try:\n evaluate_result(rd, gd, candidate_step=cand)\n d = json.loads((rd / 'result.json').read_text())\n print('CGB_SCORE ' + json.dumps({'cad_score': d.get('cad_score', 0.0), 'status': d.get('status', 'unknown')}))\n except Exception as e:\n print('CGB_SCORE ' + json.dumps({'cad_score': 0.0, 'status': 'error', 'error': str(e)[:200]}))\n`.trim()\n\ninterface CgbMeta {\n gtStep: string\n resolveThreshold: number\n}\n\n/** Fixture-seeded tasks (real GT STEPs from the repo, dim-named so the spec is\n * exact). Replaced by the published dataset when CADGENBENCH_DATA_DIR is set. */\nfunction fixtureTasks(): Array<{ id: string; prompt: string; gtStep: string }> {\n const g = join(CGB_DIR, 'tests/fixtures/geometry')\n return [\n { id: 'box-10x20x30', prompt: 'A rectangular solid box, 10 units wide (X), 20 units deep (Y), and 30 units tall (Z).', gtStep: join(g, 'box_10_20_30.step') },\n { id: 'cube-10', prompt: 'A cube, 10 units on every side.', gtStep: join(g, 'box_10_10_10.step') },\n { id: 'sphere-10', prompt: 'A sphere of radius 10 units, centered at the origin.', gtStep: join(g, 'sphere_10.step') },\n ]\n}\n\nexport function createCadGenBenchAdapter(): BenchmarkAdapter {\n return {\n name: 'cadgenbench',\n\n async preflight() {\n const r = await execFileAsync(CGB_VENV_PY, ['-c', 'import cadgenbench.eval.evaluate, build123d, trimesh, manifold3d; print(\"ok\")'], { timeout: 60_000 }).catch(\n (e) => ({ stdout: '', stderr: e instanceof Error ? e.message : String(e) }),\n )\n if (!/ok/.test(r.stdout)) {\n throw new Error(\n `cadgenbench preflight failed (venv=${CGB_VENV_PY}): ${r.stderr.slice(0, 200)}\\n` +\n `Fix: git clone https://github.com/huggingface/cadgenbench ${CGB_DIR}; python3 -m venv $CADGENBENCH_VENV; $CADGENBENCH_VENV/bin/pip install -e ${CGB_DIR}`,\n )\n }\n },\n\n async loadTasks(opts: LoadOptions = {}) {\n // CGB_HARD_DIR (a dir with tasks.json = [{id,prompt,gtStep}]) overrides the\n // trivial fixture primitives with hard multi-feature parts (real headroom).\n let tasks = fixtureTasks()\n const hard = process.env.CGB_HARD_DIR\n if (hard) {\n const { readFile } = await import('node:fs/promises')\n tasks = JSON.parse(await readFile(join(hard, 'tasks.json'), 'utf8')) as Array<{ id: string; prompt: string; gtStep: string }>\n }\n if (opts.ids) tasks = tasks.filter((t) => opts.ids!.includes(t.id))\n if (opts.limit != null) tasks = tasks.slice(0, opts.limit)\n const meta = (gtStep: string): CgbMeta => ({ gtStep, resolveThreshold: Number(process.env.CGB_RESOLVE_THRESHOLD ?? 0.9) })\n return tasks.map((t): BenchTask => ({ id: t.id, prompt: t.prompt, metadata: meta(t.gtStep) as unknown as Record<string, unknown> }))\n },\n\n async goldArtifact() {\n return undefined // GT is a STEP file scored by the kernel, not a returnable artifact\n },\n\n async judge(task: BenchTask, artifact: string): Promise<BenchScore> {\n const { gtStep, resolveThreshold } = task.metadata as unknown as CgbMeta\n if (!artifact.includes('ISO-10303-21')) return { resolved: false, score: 0, detail: 'artifact is not a STEP file' }\n const dir = await mkdtemp(join(tmpdir(), 'cgb-judge-'))\n const cand = join(dir, 'candidate.step')\n const scorer = join(dir, 'score.py')\n try {\n await writeFile(cand, artifact)\n await writeFile(scorer, SCORE_PY)\n // xvfb: the scorer's alignment step renders; needs a display.\n const r = await execFileAsync('xvfb-run', ['-a', CGB_VENV_PY, scorer, cand, gtStep], { maxBuffer: 1 << 26, timeout: 180_000 }).catch(\n (e) => ({ stdout: (e as { stdout?: string }).stdout ?? '', stderr: e instanceof Error ? e.message : String(e) }),\n )\n const m = /CGB_SCORE (\\{.*\\})/.exec(r.stdout)\n if (!m) return { resolved: false, score: 0, detail: `scorer produced no verdict: ${(r.stderr || r.stdout).slice(0, 160)}` }\n const v = JSON.parse(m[1]) as { cad_score: number; status: string; error?: string }\n const score = typeof v.cad_score === 'number' ? v.cad_score : 0\n return { resolved: score >= resolveThreshold, score, detail: `cad_score=${score.toFixed(3)} status=${v.status}${v.error ? ` (${v.error})` : ''}` }\n } finally {\n await rm(dir, { recursive: true, force: true }).catch(() => {})\n }\n },\n }\n}\n","/**\n * CADGenBench worker. The deliverable is a STEP B-rep solid (output.step). We\n * author a build123d (Python on the OpenCascade kernel) script via the router,\n * execute it in the CADGenBench venv, and read back the produced output.step —\n * exactly the reference baseline's contract. The artifact returned IS the STEP\n * text, which the CADGenBench geometric scorer grades against the ground truth.\n *\n * The build123d authoring directive is the GEPA-optimizable surface; the\n * build123d API cheat sheet (shipped in the cadgenbench package) is appended as\n * fixed reference context. Requires the CADGenBench venv (CADGENBENCH_VENV) +\n * its clone (CADGENBENCH_DIR for the cheat sheet).\n */\n\nimport { execFile } from 'node:child_process'\nimport { existsSync, readFileSync } from 'node:fs'\nimport { mkdtemp, readFile, rm, writeFile } from 'node:fs/promises'\nimport { tmpdir } from 'node:os'\nimport { join } from 'node:path'\nimport { promisify } from 'node:util'\nimport type { Span } from '@tangle-network/agent-eval'\nimport type { BenchTask } from './benchmarks/types'\nimport { DEFAULT_BUILD123D_DIRECTIVE } from './directives'\nimport { runRefineLoop } from './refine-loop'\nimport { routerChatWithUsage } from '@tangle-network/agent-runtime/loops'\n\nexport { DEFAULT_BUILD123D_DIRECTIVE } from './directives'\n\nconst execFileAsync = promisify(execFile)\n\nexport const CGB_VENV_PY = process.env.CADGENBENCH_VENV ?? '/tmp/cgb-venv/bin/python'\nexport const CGB_DIR = process.env.CADGENBENCH_DIR ?? '/tmp/cadgenbench'\n\nasync function runLocal(cmd: string, args: string[], cwd: string, timeoutMs = 120_000): Promise<{ code: number; stdout: string; stderr: string }> {\n try {\n const { stdout, stderr } = await execFileAsync(cmd, args, { cwd, maxBuffer: 1 << 26, timeout: timeoutMs })\n return { code: 0, stdout, stderr }\n } catch (err) {\n const e = err as { code?: number; stdout?: string; stderr?: string; message?: string }\n return { code: typeof e.code === 'number' ? e.code : 1, stdout: e.stdout ?? '', stderr: e.stderr ?? e.message ?? String(err) }\n }\n}\n\nfunction extractPy(text: string): string {\n const fence = /```(?:python|py)?\\s*\\n([\\s\\S]*?)```/i.exec(text)\n return (fence ? fence[1] : text).trim()\n}\n\nlet _cheat: string | null = null\nfunction cheatSheet(): string {\n if (_cheat != null) return _cheat\n const p = join(CGB_DIR, 'src/cadgenbench/baseline/build123d_cheat_sheet.md')\n _cheat = existsSync(p) ? readFileSync(p, 'utf8').slice(0, 12000) : ''\n return _cheat\n}\n\nexport interface Build123dConfig {\n routerBaseUrl: string\n routerKey: string\n model: string\n rounds?: number\n /** The build123d authoring directive — the GEPA-optimizable surface. */\n directive?: string\n}\n\nexport interface Build123dShot {\n /** The produced STEP text (the artifact the CADGenBench scorer grades). */\n artifact: string\n /** The Python source the agent wrote. */\n source: string\n trace: Span[]\n usage: { input: number; output: number }\n ok: boolean\n built: boolean\n detail?: string\n}\n\n/** Author a build123d script via the router, execute it in the CADGenBench venv,\n * read back output.step. Refine on execution error / missing STEP. */\nexport async function solveBuild123dLocal(task: BenchTask, cfg: Build123dConfig): Promise<Build123dShot> {\n const rounds = Math.max(1, cfg.rounds ?? 2)\n const directive = cfg.directive ?? DEFAULT_BUILD123D_DIRECTIVE\n const sys = `${directive}\\n\\nbuild123d API reference:\\n${cheatSheet()}`\n const trace: Span[] = []\n const runId = `cadgenbench-${task.id}`\n let ts = Date.now()\n const tick = () => (ts += 1)\n const usage = { input: 0, output: 0 }\n // Carried across rounds in closures (the round Artifact is the Python source; the\n // STEP text + built flag + lastErr persist outside the loop). usage is REAL.\n let step = ''\n let built = false\n let lastErr = ''\n\n trace.push({ spanId: 's-brief', runId, kind: 'llm', name: 'brief', model: cfg.model, messages: [{ role: 'user', content: task.prompt }], startedAt: tick(), endedAt: tick(), status: 'ok' } as Span)\n\n // Migrated onto runRefineLoop: the mkdtemp scratch dir is the Ctx; built (STEP\n // produced) is the early-stop, modeled as a judge so default-decide stops the\n // loop. The round-2+ steer carries lastErr + the prior source verbatim.\n const res = await runRefineLoop<string, string>({\n rounds,\n setup: () => mkdtemp(join(tmpdir(), 'b123d-')),\n prompt: (round, history) =>\n round === 1\n ? task.prompt\n : `Your previous build123d script failed:\\n${lastErr}\\n\\nPrevious script:\\n${history[history.length - 1]?.artifact ?? ''}\\n\\nFix it so it runs in python and writes a valid output.step. Brief:\\n${task.prompt}`,\n runShot: async (user, round, dir) => {\n const scriptPath = join(dir, 'build.py')\n const stepPath = join(dir, 'output.step')\n const { content, usage: u } = await routerChatWithUsage(cfg, [\n { role: 'system', content: sys },\n { role: 'user', content: user },\n ])\n if (u) {\n usage.input += u.input\n usage.output += u.output\n }\n const source = extractPy(content)\n trace.push({ spanId: `s-author-${round}`, runId, kind: 'llm', name: `author r${round}`, model: cfg.model, messages: [{ role: 'user', content: round === 1 ? task.prompt : 'refine' }], output: content.slice(0, 600), startedAt: tick(), endedAt: tick(), status: 'ok' } as Span)\n trace.push({ spanId: `s-write-${round}`, runId, kind: 'tool', name: 'write_file', toolName: 'create_file', args: { path: 'build.py', content: source }, startedAt: tick(), endedAt: tick(), status: 'ok' } as Span)\n\n await writeFile(scriptPath, source)\n const run = await runLocal(CGB_VENV_PY, [scriptPath], dir)\n const got = existsSync(stepPath) ? await readFile(stepPath, 'utf8').catch(() => '') : ''\n built = got.includes('ISO-10303-21') && got.length > 200\n lastErr = built ? '' : `${run.stdout}\\n${run.stderr}`.trim().slice(-800) || 'no output.step written'\n if (built) step = got\n trace.push({ spanId: `s-exec-${round}`, runId, kind: 'tool', name: `build123d r${round}`, toolName: 'shell.exec', args: 'python build.py', result: (built ? 'wrote output.step' : lastErr).slice(0, 1500), startedAt: tick(), endedAt: tick(), status: built ? 'ok' : 'error', error: built ? undefined : `exit ${run.code}` } as Span)\n return { artifact: source }\n },\n judge: async () => ({ valid: built }),\n teardown: (dir) => rm(dir, { recursive: true, force: true }).then(() => {}, () => {}),\n })\n\n return {\n artifact: step,\n source: res.final.artifact,\n trace,\n usage,\n ok: res.final.artifact.trim().length > 0,\n built,\n detail: built ? 'exported output.step' : `did not produce a STEP in ${rounds} rounds${lastErr ? `; last: ${lastErr.slice(0, 140)}` : ''}`,\n }\n}\n"],"mappings":"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","names":["execFile","mkdtemp","rm","writeFile","tmpdir","join","promisify","execFileAsync","promisify","execFile","join","readFile","mkdtemp","tmpdir","writeFile","rm"]}
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
import {
|
|
2
|
+
preflightVenvImports,
|
|
3
|
+
readJsonReport,
|
|
4
|
+
runStagedJudge,
|
|
5
|
+
runVenvPython,
|
|
6
|
+
safeRunId,
|
|
7
|
+
stageFile
|
|
8
|
+
} from "./chunk-LRRD7NAG.js";
|
|
9
|
+
|
|
10
|
+
// src/benchmarks/swe-bench.ts
|
|
11
|
+
import { join } from "path";
|
|
12
|
+
var SWE_REPO_DIR = "/work";
|
|
13
|
+
var swePatchOutput = {
|
|
14
|
+
parse(events) {
|
|
15
|
+
let text = "";
|
|
16
|
+
for (const ev of events) {
|
|
17
|
+
const d = ev?.data;
|
|
18
|
+
const t = d?.finalText ?? d?.text ?? d?.result;
|
|
19
|
+
if (typeof t === "string" && t.length > 0) text = t;
|
|
20
|
+
}
|
|
21
|
+
const fences = [...text.matchAll(/```(?:diff|patch)?\s*\n([\s\S]*?)```/g)];
|
|
22
|
+
const last = fences.at(-1)?.[1];
|
|
23
|
+
return (last ?? text).trim();
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
var DATASET = "princeton-nlp/SWE-bench_Verified";
|
|
27
|
+
var SWE_CACHE_LEVELS = /* @__PURE__ */ new Set(["none", "base", "env", "instance"]);
|
|
28
|
+
function scorerNamespace() {
|
|
29
|
+
const namespace = process.env.SWEBENCH_NAMESPACE ?? "swebench";
|
|
30
|
+
if (namespace !== "swebench" && namespace !== "none") {
|
|
31
|
+
throw new Error(`SWEBENCH_NAMESPACE must be swebench|none, got "${namespace}"`);
|
|
32
|
+
}
|
|
33
|
+
return namespace;
|
|
34
|
+
}
|
|
35
|
+
var TEST_FILE_EXCLUDES = [
|
|
36
|
+
"':(exclude,glob)**/tests/**'",
|
|
37
|
+
"':(exclude,glob)**/test/**'",
|
|
38
|
+
"':(exclude,glob)test_*.py'",
|
|
39
|
+
"':(exclude,glob)**/test_*.py'",
|
|
40
|
+
"':(exclude,glob)*_test.py'",
|
|
41
|
+
"':(exclude,glob)**/*_test.py'",
|
|
42
|
+
"':(exclude,glob)conftest.py'",
|
|
43
|
+
"':(exclude,glob)**/conftest.py'"
|
|
44
|
+
].join(" ");
|
|
45
|
+
function stringIds(report, key) {
|
|
46
|
+
const value = report[key];
|
|
47
|
+
if (value === void 0) return [];
|
|
48
|
+
if (!Array.isArray(value) || value.some((entry) => typeof entry !== "string")) {
|
|
49
|
+
throw new Error(`swe-bench: malformed ${key}`);
|
|
50
|
+
}
|
|
51
|
+
return value;
|
|
52
|
+
}
|
|
53
|
+
function scoreSweReport(taskId, value) {
|
|
54
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
55
|
+
throw new Error("swe-bench: report must be an object");
|
|
56
|
+
}
|
|
57
|
+
const report = value;
|
|
58
|
+
const statusIds = {
|
|
59
|
+
resolved: stringIds(report, "resolved_ids"),
|
|
60
|
+
unresolved: stringIds(report, "unresolved_ids"),
|
|
61
|
+
emptyPatch: stringIds(report, "empty_patch_ids"),
|
|
62
|
+
completed: stringIds(report, "completed_ids"),
|
|
63
|
+
incomplete: stringIds(report, "incomplete_ids"),
|
|
64
|
+
error: stringIds(report, "error_ids")
|
|
65
|
+
};
|
|
66
|
+
const submitted = stringIds(report, "submitted_ids");
|
|
67
|
+
const mentioned = Object.values(statusIds).flat();
|
|
68
|
+
if (mentioned.some((id) => id !== taskId) || submitted.length > 0 && (submitted.length !== 1 || submitted[0] !== taskId)) {
|
|
69
|
+
throw new Error(`swe-bench: report identity mismatch for ${taskId}`);
|
|
70
|
+
}
|
|
71
|
+
if (statusIds.error.includes(taskId) || statusIds.incomplete.includes(taskId)) {
|
|
72
|
+
throw new Error(`swe-bench: evaluator failed for ${taskId}`);
|
|
73
|
+
}
|
|
74
|
+
const outcomes = [
|
|
75
|
+
statusIds.resolved.includes(taskId),
|
|
76
|
+
statusIds.unresolved.includes(taskId),
|
|
77
|
+
statusIds.emptyPatch.includes(taskId)
|
|
78
|
+
];
|
|
79
|
+
if (outcomes.filter(Boolean).length !== 1) {
|
|
80
|
+
throw new Error(`swe-bench: report has no unique outcome for ${taskId}`);
|
|
81
|
+
}
|
|
82
|
+
if ((outcomes[0] || outcomes[1]) && !statusIds.completed.includes(taskId)) {
|
|
83
|
+
throw new Error(`swe-bench: report lacks a completed evaluation for ${taskId}`);
|
|
84
|
+
}
|
|
85
|
+
const resolved = outcomes[0];
|
|
86
|
+
return { resolved, score: resolved ? 1 : 0, detail: JSON.stringify(report) };
|
|
87
|
+
}
|
|
88
|
+
function sweEvaluationArgv(args) {
|
|
89
|
+
return [
|
|
90
|
+
"-m",
|
|
91
|
+
"swebench.harness.run_evaluation",
|
|
92
|
+
"--dataset_name",
|
|
93
|
+
DATASET,
|
|
94
|
+
"--predictions_path",
|
|
95
|
+
args.predictionsPath,
|
|
96
|
+
"--run_id",
|
|
97
|
+
args.runId,
|
|
98
|
+
"--instance_ids",
|
|
99
|
+
args.instanceId,
|
|
100
|
+
"--max_workers",
|
|
101
|
+
"1",
|
|
102
|
+
"--namespace",
|
|
103
|
+
args.namespace ?? scorerNamespace(),
|
|
104
|
+
"--cache_level",
|
|
105
|
+
args.cacheLevel
|
|
106
|
+
];
|
|
107
|
+
}
|
|
108
|
+
function shellQuote(value) {
|
|
109
|
+
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
110
|
+
}
|
|
111
|
+
function sweMetadata(task) {
|
|
112
|
+
const repo = String(task.metadata?.repo ?? "");
|
|
113
|
+
const base = String(task.metadata?.base_commit ?? "");
|
|
114
|
+
if (!/^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/.test(repo)) {
|
|
115
|
+
throw new Error(`swe-bench: invalid repo metadata for ${task.id}: ${repo}`);
|
|
116
|
+
}
|
|
117
|
+
if (!/^[0-9a-f]{7,40}$/i.test(base)) {
|
|
118
|
+
throw new Error(`swe-bench: invalid base_commit metadata for ${task.id}: ${base}`);
|
|
119
|
+
}
|
|
120
|
+
return { repo, base };
|
|
121
|
+
}
|
|
122
|
+
function createSweBenchAdapter(options = {}) {
|
|
123
|
+
if (options.timeoutMs !== void 0 && (!Number.isSafeInteger(options.timeoutMs) || options.timeoutMs <= 0)) throw new Error("swe-bench: timeoutMs must be a positive integer");
|
|
124
|
+
const cacheLevel = options.cacheLevel ?? "env";
|
|
125
|
+
if (!SWE_CACHE_LEVELS.has(cacheLevel)) throw new Error("swe-bench: invalid cacheLevel");
|
|
126
|
+
if (options.captureEvaluatorArtifacts !== void 0 && typeof options.captureEvaluatorArtifacts !== "function") throw new Error("swe-bench: captureEvaluatorArtifacts must be a function");
|
|
127
|
+
let attemptSequence = 0;
|
|
128
|
+
return {
|
|
129
|
+
name: "swe-bench-verified",
|
|
130
|
+
output: swePatchOutput,
|
|
131
|
+
// Extract the patch from repo STATE, not printed text: stage every edit the
|
|
132
|
+
// agent made in the cloned repo and diff it against the checked-out
|
|
133
|
+
// base_commit (`HEAD`). Test files are excluded — the judge applies the gold
|
|
134
|
+
// `test_patch` itself, so an agent edit to a test would collide on apply. The
|
|
135
|
+
// paths come out `a/<repo-relative>` (cwd = repo root), matching the gold
|
|
136
|
+
// patch format the swebench judge's `git apply` expects.
|
|
137
|
+
// Pre-stage: clone the instance repo at base_commit into SWE_REPO_DIR so the
|
|
138
|
+
// agent only edits (the harness owns the checkout — a stochastic model can't be
|
|
139
|
+
// trusted to clone to an exact path). `--quiet` keeps the exec output small.
|
|
140
|
+
boxSetup(task) {
|
|
141
|
+
const { repo, base } = sweMetadata(task);
|
|
142
|
+
return {
|
|
143
|
+
command: `rm -rf ${shellQuote(SWE_REPO_DIR)} && git clone --quiet ${shellQuote(`https://github.com/${repo}`)} ${shellQuote(SWE_REPO_DIR)} && git -C ${shellQuote(SWE_REPO_DIR)} checkout --quiet ${shellQuote(base)}`
|
|
144
|
+
};
|
|
145
|
+
},
|
|
146
|
+
boxExtract() {
|
|
147
|
+
return {
|
|
148
|
+
command: `git -C ${shellQuote(SWE_REPO_DIR)} add -A && git -C ${shellQuote(SWE_REPO_DIR)} diff --cached -- . ${TEST_FILE_EXCLUDES}`
|
|
149
|
+
};
|
|
150
|
+
},
|
|
151
|
+
async preflight() {
|
|
152
|
+
await preflightVenvImports({
|
|
153
|
+
modules: ["swebench"],
|
|
154
|
+
requireDocker: true,
|
|
155
|
+
fix: `Fix: (1) python3 -m venv bench/.venv && bench/.venv/bin/pip install swebench ; (2) ensure the Docker daemon is running (the judge builds per-instance images).`
|
|
156
|
+
});
|
|
157
|
+
},
|
|
158
|
+
async loadTasks(opts = {}) {
|
|
159
|
+
const limit = opts.limit ?? 10;
|
|
160
|
+
const split = opts.split ?? "test";
|
|
161
|
+
const script = `
|
|
162
|
+
import json, sys
|
|
163
|
+
from datasets import load_dataset
|
|
164
|
+
ds = load_dataset(${JSON.stringify(DATASET)}, split=${JSON.stringify(split)})
|
|
165
|
+
ids = set(json.loads(sys.argv[1])) if len(sys.argv) > 1 and sys.argv[1] else None
|
|
166
|
+
out = []
|
|
167
|
+
for r in ds:
|
|
168
|
+
if ids is not None and r["instance_id"] not in ids:
|
|
169
|
+
continue
|
|
170
|
+
out.append({
|
|
171
|
+
"instance_id": r["instance_id"], "repo": r["repo"], "base_commit": r["base_commit"],
|
|
172
|
+
"problem_statement": r["problem_statement"], "patch": r["patch"], "test_patch": r["test_patch"],
|
|
173
|
+
"FAIL_TO_PASS": r["FAIL_TO_PASS"], "PASS_TO_PASS": r["PASS_TO_PASS"],
|
|
174
|
+
"version": r.get("version"), "environment_setup_commit": r.get("environment_setup_commit"),
|
|
175
|
+
})
|
|
176
|
+
if ids is None and len(out) >= ${limit}:
|
|
177
|
+
break
|
|
178
|
+
print(json.dumps(out))
|
|
179
|
+
`;
|
|
180
|
+
const stdout = await runVenvPython(script, [opts.ids ? JSON.stringify(opts.ids) : ""]);
|
|
181
|
+
const rows = JSON.parse(stdout);
|
|
182
|
+
return rows.map(
|
|
183
|
+
(r) => ({
|
|
184
|
+
id: String(r.instance_id),
|
|
185
|
+
split,
|
|
186
|
+
prompt: [
|
|
187
|
+
`Repository: ${r.repo} @ ${r.base_commit}`,
|
|
188
|
+
"",
|
|
189
|
+
`The repository is ALREADY cloned at ${SWE_REPO_DIR}, checked out at commit ${r.base_commit}. Work there directly (\`cd ${SWE_REPO_DIR}\`); do not re-clone.`,
|
|
190
|
+
"",
|
|
191
|
+
"Resolve this issue by editing the repository SOURCE so the failing tests pass without breaking the passing ones. Do NOT edit test files \u2014 the evaluation runs hidden tests on a fresh checkout, so editing tests does not count. Keep the change minimal and confined to the cloned repo.",
|
|
192
|
+
"Work iteratively: reproduce the issue, implement the fix in the source, and re-run the relevant tests until they pass. You do NOT need to print the diff \u2014 the harness reads your committed edits directly from the repo.",
|
|
193
|
+
"",
|
|
194
|
+
"--- Issue ---",
|
|
195
|
+
String(r.problem_statement ?? "")
|
|
196
|
+
].join("\n"),
|
|
197
|
+
metadata: r
|
|
198
|
+
})
|
|
199
|
+
);
|
|
200
|
+
},
|
|
201
|
+
async goldArtifact(task) {
|
|
202
|
+
const gold = task.metadata?.patch;
|
|
203
|
+
return typeof gold === "string" ? gold : void 0;
|
|
204
|
+
},
|
|
205
|
+
async judge(task, artifact) {
|
|
206
|
+
const runId = safeRunId("bench", task.id);
|
|
207
|
+
const capture = options.captureEvaluatorArtifacts?.({
|
|
208
|
+
taskId: task.id,
|
|
209
|
+
runId,
|
|
210
|
+
attemptSequence: ++attemptSequence
|
|
211
|
+
});
|
|
212
|
+
return runStagedJudge({
|
|
213
|
+
tmpPrefix: "swebench-",
|
|
214
|
+
...options.timeoutMs === void 0 ? {} : { timeoutMs: options.timeoutMs },
|
|
215
|
+
...capture === void 0 ? {} : { capture },
|
|
216
|
+
// Debug: retain the staged dir (holds swebench's per-instance apply/run
|
|
217
|
+
// logs) for post-mortem when SWEBENCH_KEEP_TMP is set. Off by default.
|
|
218
|
+
...process.env.SWEBENCH_KEEP_TMP ? { keepTmp: true } : {},
|
|
219
|
+
async stage(dir) {
|
|
220
|
+
await stageFile(
|
|
221
|
+
join(dir, "preds.json"),
|
|
222
|
+
JSON.stringify([
|
|
223
|
+
{ instance_id: task.id, model_name_or_path: "agent-runtime-bench", model_patch: artifact }
|
|
224
|
+
])
|
|
225
|
+
);
|
|
226
|
+
},
|
|
227
|
+
// The official evaluation harness. Pulls/builds the instance image, applies
|
|
228
|
+
// the patch, runs the test spec, writes a per-run report JSON in cwd.
|
|
229
|
+
argv: (dir) => sweEvaluationArgv({
|
|
230
|
+
predictionsPath: join(dir, "preds.json"),
|
|
231
|
+
runId,
|
|
232
|
+
instanceId: task.id,
|
|
233
|
+
cacheLevel,
|
|
234
|
+
namespace: scorerNamespace()
|
|
235
|
+
}),
|
|
236
|
+
async parseReport(dir) {
|
|
237
|
+
const report = await readJsonReport(join(dir, `agent-runtime-bench.${runId}.json`));
|
|
238
|
+
return scoreSweReport(task.id, report);
|
|
239
|
+
}
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
export {
|
|
246
|
+
swePatchOutput,
|
|
247
|
+
scoreSweReport,
|
|
248
|
+
sweEvaluationArgv,
|
|
249
|
+
createSweBenchAdapter
|
|
250
|
+
};
|
|
251
|
+
//# sourceMappingURL=chunk-CKUVRZ2T.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/benchmarks/swe-bench.ts"],"sourcesContent":["/**\n * SWE-bench Verified adapter. Worker artifact = a unified-diff patch. Judge =\n * the official `swebench` harness: apply the patch in the instance's Docker\n * image, run FAIL_TO_PASS + PASS_TO_PASS, report `resolved`. Fully deterministic\n * — no LLM judge.\n *\n * Requires: the bench `.venv` with `swebench` installed + a running Docker\n * daemon (per-instance images are pulled/built on first run).\n *\n * Process/Docker/report plumbing is shared via ./_harness; this file owns the\n * SWE-specific pieces: the patch OutputAdapter, the dataset dump, and the\n * predictions-file → run_evaluation argv → report-shape mapping.\n */\n\nimport { join } from 'node:path'\nimport type { OutputAdapter } from '@tangle-network/agent-runtime/loops'\nimport {\n preflightVenvImports,\n readJsonReport,\n runStagedJudge,\n runVenvPython,\n safeRunId,\n stageFile,\n type StagedRunCaptureSpec,\n} from './_harness'\nimport type { BenchmarkAdapter, BenchScore, BenchTask, LoadOptions } from './types'\n\n/**\n * Fixed in-box path the agent clones the instance repo into. It is the SINGLE\n * source of truth shared by the prompt template (which tells the agent to clone\n * here) and `boxExtract` (which runs `git diff` here after the shot) — so the\n * harness always knows exactly where the agent's edits live, for any instance.\n */\nconst SWE_REPO_DIR = '/work'\n\n/**\n * The SWE deliverable's FALLBACK parser, from the agent's event STREAM.\n *\n * The PRIMARY deliverable is `boxExtract` below: a `git diff` of the agent's\n * actual edits, read from the cloned repo's STATE inside the box (standard\n * SWE-bench practice). This event-stream parse only runs when that diff is empty\n * — a model that edited the source correctly but never printed a fenced diff (the\n * exact failure this replaces) still scores off its real changes, not its prose.\n */\nexport const swePatchOutput: OutputAdapter<string> = {\n parse(events) {\n let text = ''\n for (const ev of events) {\n const d = (ev as { data?: Record<string, unknown> })?.data\n const t = d?.finalText ?? d?.text ?? d?.result\n if (typeof t === 'string' && t.length > 0) text = t\n }\n // Last ```diff/```patch fenced block (the contract the prompt asks for);\n // fall back to the raw text so a fence-less but valid diff still reaches the judge.\n const fences = [...text.matchAll(/```(?:diff|patch)?\\s*\\n([\\s\\S]*?)```/g)]\n const last = fences.at(-1)?.[1]\n return (last ?? text).trim()\n },\n}\n\nconst DATASET = 'princeton-nlp/SWE-bench_Verified'\nexport type SweBenchCacheLevel = 'none' | 'base' | 'env' | 'instance'\n\nexport interface SweBenchArtifactCaptureContext {\n readonly taskId: string\n readonly runId: string\n /** One-based sequence unique within this adapter instance. */\n readonly attemptSequence: number\n}\n\nexport interface SweBenchAdapterOptions {\n readonly timeoutMs?: number\n readonly cacheLevel?: SweBenchCacheLevel\n /**\n * Return a unique destination for any attempt whose complete official\n * evaluator directory and process logs should be retained.\n */\n readonly captureEvaluatorArtifacts?: (\n context: SweBenchArtifactCaptureContext,\n ) => StagedRunCaptureSpec | undefined\n}\n\nconst SWE_CACHE_LEVELS = new Set<SweBenchCacheLevel>(['none', 'base', 'env', 'instance'])\n\nfunction scorerNamespace(): 'swebench' | 'none' {\n const namespace = process.env.SWEBENCH_NAMESPACE ?? 'swebench'\n if (namespace !== 'swebench' && namespace !== 'none') {\n throw new Error(`SWEBENCH_NAMESPACE must be swebench|none, got \"${namespace}\"`)\n }\n return namespace\n}\nconst TEST_FILE_EXCLUDES = [\n \"':(exclude,glob)**/tests/**'\",\n \"':(exclude,glob)**/test/**'\",\n \"':(exclude,glob)test_*.py'\",\n \"':(exclude,glob)**/test_*.py'\",\n \"':(exclude,glob)*_test.py'\",\n \"':(exclude,glob)**/*_test.py'\",\n \"':(exclude,glob)conftest.py'\",\n \"':(exclude,glob)**/conftest.py'\",\n].join(' ')\n\ninterface SweReport {\n resolved_instances?: number\n resolved_ids?: string[]\n unresolved_ids?: string[]\n empty_patch_ids?: string[]\n completed_ids?: string[]\n incomplete_ids?: string[]\n error_ids?: string[]\n submitted_ids?: string[]\n}\n\nfunction stringIds(report: Record<string, unknown>, key: keyof SweReport): string[] {\n const value = report[key]\n if (value === undefined) return []\n if (!Array.isArray(value) || value.some((entry) => typeof entry !== 'string')) {\n throw new Error(`swe-bench: malformed ${key}`)\n }\n return value\n}\n\n/** Convert one official report into a score without turning evaluator failures into agent failures. */\nexport function scoreSweReport(taskId: string, value: unknown): BenchScore {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n throw new Error('swe-bench: report must be an object')\n }\n const report = value as Record<string, unknown>\n const statusIds = {\n resolved: stringIds(report, 'resolved_ids'),\n unresolved: stringIds(report, 'unresolved_ids'),\n emptyPatch: stringIds(report, 'empty_patch_ids'),\n completed: stringIds(report, 'completed_ids'),\n incomplete: stringIds(report, 'incomplete_ids'),\n error: stringIds(report, 'error_ids'),\n }\n const submitted = stringIds(report, 'submitted_ids')\n const mentioned = Object.values(statusIds).flat()\n if (\n mentioned.some((id) => id !== taskId)\n || (submitted.length > 0 && (submitted.length !== 1 || submitted[0] !== taskId))\n ) {\n throw new Error(`swe-bench: report identity mismatch for ${taskId}`)\n }\n if (statusIds.error.includes(taskId) || statusIds.incomplete.includes(taskId)) {\n throw new Error(`swe-bench: evaluator failed for ${taskId}`)\n }\n const outcomes = [\n statusIds.resolved.includes(taskId),\n statusIds.unresolved.includes(taskId),\n statusIds.emptyPatch.includes(taskId),\n ]\n if (outcomes.filter(Boolean).length !== 1) {\n throw new Error(`swe-bench: report has no unique outcome for ${taskId}`)\n }\n if ((outcomes[0] || outcomes[1]) && !statusIds.completed.includes(taskId)) {\n throw new Error(`swe-bench: report lacks a completed evaluation for ${taskId}`)\n }\n const resolved = outcomes[0]\n return { resolved, score: resolved ? 1 : 0, detail: JSON.stringify(report) }\n}\n\nexport function sweEvaluationArgv(args: {\n readonly predictionsPath: string\n readonly runId: string\n readonly instanceId: string\n readonly cacheLevel: SweBenchCacheLevel\n readonly namespace?: 'swebench' | 'none'\n}): string[] {\n return [\n '-m', 'swebench.harness.run_evaluation',\n '--dataset_name', DATASET,\n '--predictions_path', args.predictionsPath,\n '--run_id', args.runId,\n '--instance_ids', args.instanceId,\n '--max_workers', '1',\n '--namespace', args.namespace ?? scorerNamespace(),\n '--cache_level', args.cacheLevel,\n ]\n}\n\nfunction shellQuote(value: string): string {\n return `'${value.replace(/'/g, `'\\\\''`)}'`\n}\n\nfunction sweMetadata(task: BenchTask): { repo: string; base: string } {\n const repo = String(task.metadata?.repo ?? '')\n const base = String(task.metadata?.base_commit ?? '')\n if (!/^[A-Za-z0-9_.-]+\\/[A-Za-z0-9_.-]+$/.test(repo)) {\n throw new Error(`swe-bench: invalid repo metadata for ${task.id}: ${repo}`)\n }\n if (!/^[0-9a-f]{7,40}$/i.test(base)) {\n throw new Error(`swe-bench: invalid base_commit metadata for ${task.id}: ${base}`)\n }\n return { repo, base }\n}\n\nexport function createSweBenchAdapter(options: SweBenchAdapterOptions = {}): BenchmarkAdapter {\n if (\n options.timeoutMs !== undefined\n && (!Number.isSafeInteger(options.timeoutMs) || options.timeoutMs <= 0)\n ) throw new Error('swe-bench: timeoutMs must be a positive integer')\n const cacheLevel = options.cacheLevel ?? 'env'\n if (!SWE_CACHE_LEVELS.has(cacheLevel)) throw new Error('swe-bench: invalid cacheLevel')\n if (\n options.captureEvaluatorArtifacts !== undefined\n && typeof options.captureEvaluatorArtifacts !== 'function'\n ) throw new Error('swe-bench: captureEvaluatorArtifacts must be a function')\n let attemptSequence = 0\n return {\n name: 'swe-bench-verified',\n output: swePatchOutput,\n\n // Extract the patch from repo STATE, not printed text: stage every edit the\n // agent made in the cloned repo and diff it against the checked-out\n // base_commit (`HEAD`). Test files are excluded — the judge applies the gold\n // `test_patch` itself, so an agent edit to a test would collide on apply. The\n // paths come out `a/<repo-relative>` (cwd = repo root), matching the gold\n // patch format the swebench judge's `git apply` expects.\n // Pre-stage: clone the instance repo at base_commit into SWE_REPO_DIR so the\n // agent only edits (the harness owns the checkout — a stochastic model can't be\n // trusted to clone to an exact path). `--quiet` keeps the exec output small.\n boxSetup(task) {\n const { repo, base } = sweMetadata(task)\n return {\n command: `rm -rf ${shellQuote(SWE_REPO_DIR)} && git clone --quiet ${shellQuote(`https://github.com/${repo}`)} ${shellQuote(SWE_REPO_DIR)} && git -C ${shellQuote(SWE_REPO_DIR)} checkout --quiet ${shellQuote(base)}`,\n }\n },\n boxExtract() {\n return {\n command: `git -C ${shellQuote(SWE_REPO_DIR)} add -A && git -C ${shellQuote(SWE_REPO_DIR)} diff --cached -- . ${TEST_FILE_EXCLUDES}`,\n }\n },\n\n async preflight() {\n await preflightVenvImports({\n modules: ['swebench'],\n requireDocker: true,\n fix:\n `Fix: (1) python3 -m venv bench/.venv && bench/.venv/bin/pip install swebench ; ` +\n `(2) ensure the Docker daemon is running (the judge builds per-instance images).`,\n })\n },\n\n async loadTasks(opts: LoadOptions = {}) {\n const limit = opts.limit ?? 10\n const split = opts.split ?? 'test'\n // Dump instances as JSON via the datasets loader (HF download on first run).\n const script = `\nimport json, sys\nfrom datasets import load_dataset\nds = load_dataset(${JSON.stringify(DATASET)}, split=${JSON.stringify(split)})\nids = set(json.loads(sys.argv[1])) if len(sys.argv) > 1 and sys.argv[1] else None\nout = []\nfor r in ds:\n if ids is not None and r[\"instance_id\"] not in ids:\n continue\n out.append({\n \"instance_id\": r[\"instance_id\"], \"repo\": r[\"repo\"], \"base_commit\": r[\"base_commit\"],\n \"problem_statement\": r[\"problem_statement\"], \"patch\": r[\"patch\"], \"test_patch\": r[\"test_patch\"],\n \"FAIL_TO_PASS\": r[\"FAIL_TO_PASS\"], \"PASS_TO_PASS\": r[\"PASS_TO_PASS\"],\n \"version\": r.get(\"version\"), \"environment_setup_commit\": r.get(\"environment_setup_commit\"),\n })\n if ids is None and len(out) >= ${limit}:\n break\nprint(json.dumps(out))\n`\n const stdout = await runVenvPython(script, [opts.ids ? JSON.stringify(opts.ids) : ''])\n const rows = JSON.parse(stdout) as Array<Record<string, unknown>>\n return rows.map(\n (r): BenchTask => ({\n id: String(r.instance_id),\n split,\n prompt: [\n `Repository: ${r.repo} @ ${r.base_commit}`,\n '',\n `The repository is ALREADY cloned at ${SWE_REPO_DIR}, checked out at commit ${r.base_commit}. Work there directly (\\`cd ${SWE_REPO_DIR}\\`); do not re-clone.`,\n '',\n 'Resolve this issue by editing the repository SOURCE so the failing tests pass without breaking the passing ones. Do NOT edit test files — the evaluation runs hidden tests on a fresh checkout, so editing tests does not count. Keep the change minimal and confined to the cloned repo.',\n 'Work iteratively: reproduce the issue, implement the fix in the source, and re-run the relevant tests until they pass. You do NOT need to print the diff — the harness reads your committed edits directly from the repo.',\n '',\n '--- Issue ---',\n String(r.problem_statement ?? ''),\n ].join('\\n'),\n metadata: r,\n }),\n )\n },\n\n async goldArtifact(task: BenchTask) {\n const gold = task.metadata?.patch\n return typeof gold === 'string' ? gold : undefined\n },\n\n async judge(task: BenchTask, artifact: string): Promise<BenchScore> {\n const runId = safeRunId('bench', task.id)\n const capture = options.captureEvaluatorArtifacts?.({\n taskId: task.id,\n runId,\n attemptSequence: ++attemptSequence,\n })\n return runStagedJudge({\n tmpPrefix: 'swebench-',\n ...(options.timeoutMs === undefined ? {} : { timeoutMs: options.timeoutMs }),\n ...(capture === undefined ? {} : { capture }),\n // Debug: retain the staged dir (holds swebench's per-instance apply/run\n // logs) for post-mortem when SWEBENCH_KEEP_TMP is set. Off by default.\n ...(process.env.SWEBENCH_KEEP_TMP ? { keepTmp: true } : {}),\n async stage(dir) {\n await stageFile(\n join(dir, 'preds.json'),\n JSON.stringify([\n { instance_id: task.id, model_name_or_path: 'agent-runtime-bench', model_patch: artifact },\n ]),\n )\n },\n // The official evaluation harness. Pulls/builds the instance image, applies\n // the patch, runs the test spec, writes a per-run report JSON in cwd.\n argv: (dir) => sweEvaluationArgv({\n predictionsPath: join(dir, 'preds.json'),\n runId,\n instanceId: task.id,\n cacheLevel,\n namespace: scorerNamespace(),\n }),\n async parseReport(dir) {\n // Report file: agent-runtime-bench.<run_id>.json\n const report = await readJsonReport<SweReport>(join(dir, `agent-runtime-bench.${runId}.json`))\n return scoreSweReport(task.id, report)\n },\n })\n },\n }\n}\n"],"mappings":"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","names":[]}
|