@tangle-network/agent-bench 0.4.0 → 0.4.3

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.
Files changed (200) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/dist/adapters.d.ts +4 -11
  3. package/dist/adapters.js +78 -41
  4. package/dist/adapters.js.map +1 -1
  5. package/dist/benchmarks/_harness.d.ts +51 -66
  6. package/dist/benchmarks/_harness.js +329 -31
  7. package/dist/benchmarks/_harness.js.map +1 -1
  8. package/dist/benchmarks/aec-bench.d.ts +4 -25
  9. package/dist/benchmarks/aec-bench.js +242 -7
  10. package/dist/benchmarks/aec-bench.js.map +1 -1
  11. package/dist/benchmarks/agentbench.d.ts +5 -13
  12. package/dist/benchmarks/agentbench.js +114 -9
  13. package/dist/benchmarks/agentbench.js.map +1 -1
  14. package/dist/benchmarks/appworld.d.ts +9 -29
  15. package/dist/benchmarks/appworld.js +317 -12
  16. package/dist/benchmarks/appworld.js.map +1 -1
  17. package/dist/benchmarks/bfcl.d.ts +5 -15
  18. package/dist/benchmarks/bfcl.js +264 -9
  19. package/dist/benchmarks/bfcl.js.map +1 -1
  20. package/dist/benchmarks/cad-design.d.ts +16 -41
  21. package/dist/benchmarks/cad-design.js +512 -6
  22. package/dist/benchmarks/cad-design.js.map +1 -1
  23. package/dist/benchmarks/cadbench.d.ts +4 -17
  24. package/dist/benchmarks/cadbench.js +2 -8
  25. package/dist/benchmarks/cadgenbench.d.ts +4 -20
  26. package/dist/benchmarks/cadgenbench.js +2 -8
  27. package/dist/benchmarks/commit0.d.ts +5 -27
  28. package/dist/benchmarks/commit0.js +187 -9
  29. package/dist/benchmarks/commit0.js.map +1 -1
  30. package/dist/benchmarks/crag.d.ts +4 -12
  31. package/dist/benchmarks/crag.js +110 -8
  32. package/dist/benchmarks/crag.js.map +1 -1
  33. package/dist/benchmarks/dabstep.d.ts +5 -15
  34. package/dist/benchmarks/dabstep.js +177 -9
  35. package/dist/benchmarks/dabstep.js.map +1 -1
  36. package/dist/benchmarks/enterpriseops-gym.d.ts +5 -34
  37. package/dist/benchmarks/enterpriseops-gym.js +236 -9
  38. package/dist/benchmarks/enterpriseops-gym.js.map +1 -1
  39. package/dist/benchmarks/finresearchbench.d.ts +4 -13
  40. package/dist/benchmarks/finresearchbench.js +218 -7
  41. package/dist/benchmarks/finresearchbench.js.map +1 -1
  42. package/dist/benchmarks/finsearchcomp.d.ts +8 -39
  43. package/dist/benchmarks/finsearchcomp.js +267 -6
  44. package/dist/benchmarks/finsearchcomp.js.map +1 -1
  45. package/dist/benchmarks/frames.d.ts +15 -37
  46. package/dist/benchmarks/frames.js +408 -11
  47. package/dist/benchmarks/frames.js.map +1 -1
  48. package/dist/benchmarks/hotpotqa.d.ts +4 -24
  49. package/dist/benchmarks/hotpotqa.js +250 -14
  50. package/dist/benchmarks/hotpotqa.js.map +1 -1
  51. package/dist/benchmarks/humaneval.d.ts +19 -37
  52. package/dist/benchmarks/humaneval.js +279 -16
  53. package/dist/benchmarks/humaneval.js.map +1 -1
  54. package/dist/benchmarks/mind2web.d.ts +7 -34
  55. package/dist/benchmarks/mind2web.js +257 -8
  56. package/dist/benchmarks/mind2web.js.map +1 -1
  57. package/dist/benchmarks/nomiracl.d.ts +4 -13
  58. package/dist/benchmarks/nomiracl.js +146 -8
  59. package/dist/benchmarks/nomiracl.js.map +1 -1
  60. package/dist/benchmarks/open-rag-bench.d.ts +4 -12
  61. package/dist/benchmarks/open-rag-bench.js +110 -8
  62. package/dist/benchmarks/open-rag-bench.js.map +1 -1
  63. package/dist/benchmarks/programbench.d.ts +5 -29
  64. package/dist/benchmarks/programbench.js +161 -9
  65. package/dist/benchmarks/programbench.js.map +1 -1
  66. package/dist/benchmarks/rag-shared.d.ts +21 -20
  67. package/dist/benchmarks/rag-shared.js +245 -38
  68. package/dist/benchmarks/rag-shared.js.map +1 -1
  69. package/dist/benchmarks/ragbench.d.ts +4 -14
  70. package/dist/benchmarks/ragbench.js +127 -8
  71. package/dist/benchmarks/ragbench.js.map +1 -1
  72. package/dist/benchmarks/simpleqa.d.ts +17 -44
  73. package/dist/benchmarks/simpleqa.js +293 -10
  74. package/dist/benchmarks/simpleqa.js.map +1 -1
  75. package/dist/benchmarks/swe-bench.d.ts +23 -36
  76. package/dist/benchmarks/swe-bench.js +234 -13
  77. package/dist/benchmarks/swe-bench.js.map +1 -1
  78. package/dist/benchmarks/t2-ragbench.d.ts +4 -12
  79. package/dist/benchmarks/t2-ragbench.js +118 -8
  80. package/dist/benchmarks/t2-ragbench.js.map +1 -1
  81. package/dist/benchmarks/tau-bench-shared.d.ts +14 -22
  82. package/dist/benchmarks/tau-bench-shared.js +169 -9
  83. package/dist/benchmarks/tau-bench-shared.js.map +1 -1
  84. package/dist/benchmarks/tau2-bench.d.ts +5 -5
  85. package/dist/benchmarks/tau2-bench.js +28 -10
  86. package/dist/benchmarks/tau2-bench.js.map +1 -1
  87. package/dist/benchmarks/tau3-banking.d.ts +4 -13
  88. package/dist/benchmarks/tau3-banking.js +28 -8
  89. package/dist/benchmarks/tau3-banking.js.map +1 -1
  90. package/dist/benchmarks/terminal-bench.d.ts +4 -22
  91. package/dist/benchmarks/terminal-bench.js +140 -7
  92. package/dist/benchmarks/terminal-bench.js.map +1 -1
  93. package/dist/benchmarks/toollm.d.ts +5 -13
  94. package/dist/benchmarks/toollm.js +184 -9
  95. package/dist/benchmarks/toollm.js.map +1 -1
  96. package/dist/benchmarks/trata-hedge.d.ts +4 -30
  97. package/dist/benchmarks/trata-hedge.js +336 -6
  98. package/dist/benchmarks/trata-hedge.js.map +1 -1
  99. package/dist/benchmarks/types.d.ts +85 -94
  100. package/dist/benchmarks/types.js +1 -1
  101. package/dist/benchmarks/webarena-verified.d.ts +5 -13
  102. package/dist/benchmarks/webarena-verified.js +152 -9
  103. package/dist/benchmarks/webarena-verified.js.map +1 -1
  104. package/dist/cadbench-DpQWZHp4.js +285 -0
  105. package/dist/cadbench-DpQWZHp4.js.map +1 -0
  106. package/dist/cadgenbench-DRhczfsG.js +151 -0
  107. package/dist/cadgenbench-DRhczfsG.js.map +1 -0
  108. package/dist/index.d.ts +245 -293
  109. package/dist/index.js +1669 -1791
  110. package/dist/index.js.map +1 -1
  111. package/package.json +17 -14
  112. package/pier_agents/candidate_contract.py +238 -24
  113. package/pier_agents/tangle_candidate.py +75 -5
  114. package/scripts/verify-packed-consumer.mjs +84 -17
  115. package/scripts/verify-pier-agent.mts +6 -4
  116. package/src/benchmarks/_harness.test.mts +16 -1
  117. package/src/benchmarks/_harness.ts +9 -2
  118. package/src/benchmarks/terminal-bench.ts +2 -1
  119. package/src/corpus.test.mts +13 -0
  120. package/src/corpus.ts +4 -0
  121. package/src/profile-coordinates.ts +2 -2
  122. package/src/rollout-ledger/backfill-swe-arena.mts +5 -1
  123. package/src/rollout-ledger/settle-capture.mts +7 -1
  124. package/src/search-bench/profiles.ts +1 -1
  125. package/src/skill-sandbox-smoke.mts +2 -1
  126. package/src/swe-arena/gepa-seat.mts +1 -1
  127. package/src/swe-arena/ledger-orphans.test.mts +36 -34
  128. package/dist/benchmarks/cadbench.js.map +0 -1
  129. package/dist/benchmarks/cadgenbench.js.map +0 -1
  130. package/dist/benchmarks/types.js.map +0 -1
  131. package/dist/chunk-3U5TXJZS.js +0 -251
  132. package/dist/chunk-3U5TXJZS.js.map +0 -1
  133. package/dist/chunk-53UPUNBZ.js +0 -325
  134. package/dist/chunk-53UPUNBZ.js.map +0 -1
  135. package/dist/chunk-5H5XV76F.js +0 -240
  136. package/dist/chunk-5H5XV76F.js.map +0 -1
  137. package/dist/chunk-7GRVHU22.js +0 -208
  138. package/dist/chunk-7GRVHU22.js.map +0 -1
  139. package/dist/chunk-C7T7WEK2.js +0 -103
  140. package/dist/chunk-C7T7WEK2.js.map +0 -1
  141. package/dist/chunk-HWST3SED.js +0 -162
  142. package/dist/chunk-HWST3SED.js.map +0 -1
  143. package/dist/chunk-IA2FBTWC.js +0 -318
  144. package/dist/chunk-IA2FBTWC.js.map +0 -1
  145. package/dist/chunk-IFVINJ4B.js +0 -142
  146. package/dist/chunk-IFVINJ4B.js.map +0 -1
  147. package/dist/chunk-INNOYXCP.js +0 -387
  148. package/dist/chunk-INNOYXCP.js.map +0 -1
  149. package/dist/chunk-IZ5M6OAC.js +0 -169
  150. package/dist/chunk-IZ5M6OAC.js.map +0 -1
  151. package/dist/chunk-JTHWEDEW.js +0 -32
  152. package/dist/chunk-JTHWEDEW.js.map +0 -1
  153. package/dist/chunk-K3BQGZCT.js +0 -221
  154. package/dist/chunk-K3BQGZCT.js.map +0 -1
  155. package/dist/chunk-KP5KD6EN.js +0 -276
  156. package/dist/chunk-KP5KD6EN.js.map +0 -1
  157. package/dist/chunk-MQMRLGOG.js +0 -136
  158. package/dist/chunk-MQMRLGOG.js.map +0 -1
  159. package/dist/chunk-NQG5XDSB.js +0 -147
  160. package/dist/chunk-NQG5XDSB.js.map +0 -1
  161. package/dist/chunk-PA2ZKHJC.js +0 -230
  162. package/dist/chunk-PA2ZKHJC.js.map +0 -1
  163. package/dist/chunk-PB64GYIG.js +0 -118
  164. package/dist/chunk-PB64GYIG.js.map +0 -1
  165. package/dist/chunk-PUIRNYI7.js +0 -189
  166. package/dist/chunk-PUIRNYI7.js.map +0 -1
  167. package/dist/chunk-RCYQEFNX.js +0 -30
  168. package/dist/chunk-RCYQEFNX.js.map +0 -1
  169. package/dist/chunk-RH5F53JT.js +0 -182
  170. package/dist/chunk-RH5F53JT.js.map +0 -1
  171. package/dist/chunk-SEVJPLZC.js +0 -260
  172. package/dist/chunk-SEVJPLZC.js.map +0 -1
  173. package/dist/chunk-SFLA7OH3.js +0 -27
  174. package/dist/chunk-SFLA7OH3.js.map +0 -1
  175. package/dist/chunk-SHM6MRRF.js +0 -130
  176. package/dist/chunk-SHM6MRRF.js.map +0 -1
  177. package/dist/chunk-SHYIRB7I.js +0 -120
  178. package/dist/chunk-SHYIRB7I.js.map +0 -1
  179. package/dist/chunk-SVR2LKYI.js +0 -116
  180. package/dist/chunk-SVR2LKYI.js.map +0 -1
  181. package/dist/chunk-TBKU5XQI.js +0 -228
  182. package/dist/chunk-TBKU5XQI.js.map +0 -1
  183. package/dist/chunk-UPAMRDX4.js +0 -233
  184. package/dist/chunk-UPAMRDX4.js.map +0 -1
  185. package/dist/chunk-V7AEBY6U.js +0 -144
  186. package/dist/chunk-V7AEBY6U.js.map +0 -1
  187. package/dist/chunk-VQRS7VUC.js +0 -342
  188. package/dist/chunk-VQRS7VUC.js.map +0 -1
  189. package/dist/chunk-WSKWVEQB.js +0 -317
  190. package/dist/chunk-WSKWVEQB.js.map +0 -1
  191. package/dist/chunk-X3BTXCJ4.js +0 -262
  192. package/dist/chunk-X3BTXCJ4.js.map +0 -1
  193. package/dist/chunk-XKEFIFIC.js +0 -197
  194. package/dist/chunk-XKEFIFIC.js.map +0 -1
  195. package/dist/chunk-XYA4XSNU.js +0 -148
  196. package/dist/chunk-XYA4XSNU.js.map +0 -1
  197. package/dist/chunk-YSMEKBTD.js +0 -211
  198. package/dist/chunk-YSMEKBTD.js.map +0 -1
  199. package/dist/chunk-Z4TZ76N7.js +0 -170
  200. package/dist/chunk-Z4TZ76N7.js.map +0 -1
@@ -1,103 +0,0 @@
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
@@ -1 +0,0 @@
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"]}
@@ -1,162 +0,0 @@
1
- import {
2
- benchRoot,
3
- runVenvPython
4
- } from "./chunk-WSKWVEQB.js";
5
-
6
- // src/benchmarks/webarena-verified.ts
7
- import { access, readFile, stat } from "fs/promises";
8
- import { join, resolve } from "path";
9
- var FIXTURES = join(benchRoot, "fixtures", "webarena-verified.json");
10
- var DATASET_REL = join("assets", "dataset", "webarena-verified.json");
11
- var webarenaDir = () => process.env.WEBARENA_VERIFIED_DIR;
12
- var webarenaOutputDirOutput = {
13
- parse(events) {
14
- let text = "";
15
- for (const ev of events) {
16
- const d = ev?.data;
17
- const t = d?.finalText ?? d?.text ?? d?.result;
18
- if (typeof t === "string" && t.length > 0) text = t;
19
- }
20
- const fences = [...text.matchAll(/```(?:text|path)?\s*\n([\s\S]*?)```/g)];
21
- return (fences.at(-1)?.[1] ?? text).trim();
22
- }
23
- };
24
- async function assertFile(path, label) {
25
- try {
26
- await access(path);
27
- } catch (err) {
28
- throw new Error(`WebArena-Verified: missing ${label} at ${path} (${err instanceof Error ? err.message : err})`);
29
- }
30
- }
31
- async function assertDir(path, label) {
32
- try {
33
- const s = await stat(path);
34
- if (!s.isDirectory()) throw new Error("not a directory");
35
- } catch (err) {
36
- throw new Error(`WebArena-Verified: missing ${label} at ${path} (${err instanceof Error ? err.message : err})`);
37
- }
38
- }
39
- function rowToTask(row) {
40
- const meta = {
41
- taskId: row.task_id,
42
- intentTemplateId: row.intent_template_id,
43
- sites: row.sites ?? [],
44
- startUrls: row.start_urls ?? [],
45
- revision: row.revision,
46
- eval: row.eval
47
- };
48
- return {
49
- id: String(row.task_id),
50
- prompt: [
51
- "Run this WebArena-Verified browser task in the official environment.",
52
- `Goal: ${row.intent}`,
53
- row.start_urls?.length ? `Start URL templates: ${row.start_urls.join(", ")}` : void 0,
54
- row.sites?.length ? `Sites: ${row.sites.join(", ")}` : void 0,
55
- "",
56
- "Return the path to the official WebArena-Verified run output directory for this task.",
57
- "The judge expects that directory to contain the task response and network trace files."
58
- ].filter(Boolean).join("\n"),
59
- metadata: meta
60
- };
61
- }
62
- function readMeta(task) {
63
- const md = task.metadata;
64
- if (!md || typeof md.taskId !== "number") {
65
- throw new Error(`webarena-verified task ${task.id} missing metadata \u2014 loadTasks did not populate it`);
66
- }
67
- return md;
68
- }
69
- function selectRows(rows, opts) {
70
- let tasks = rows.map(rowToTask);
71
- if (opts.ids) {
72
- const want = new Set(opts.ids);
73
- tasks = tasks.filter((task) => want.has(task.id));
74
- } else if (opts.limit !== void 0) {
75
- tasks = tasks.slice(0, opts.limit);
76
- }
77
- if (tasks.length === 0) throw new Error(`WebArena-Verified: no tasks matched ${JSON.stringify(opts)}`);
78
- return tasks;
79
- }
80
- async function loadFixtures(opts) {
81
- const rows = JSON.parse(await readFile(FIXTURES, "utf8"));
82
- console.warn(`[webarena-verified] WEBARENA_VERIFIED_FIXTURES=1 \u2014 loading ${rows.length} adapter fixtures`);
83
- return selectRows(rows, opts);
84
- }
85
- async function loadOfficialRows(dir, opts) {
86
- const rows = JSON.parse(await readFile(join(dir, DATASET_REL), "utf8"));
87
- return selectRows(rows, opts);
88
- }
89
- async function runOfficialEval(root, taskId, outputDir) {
90
- const script = `
91
- import json, os, subprocess, sys
92
- from pathlib import Path
93
-
94
- root = Path(sys.argv[1])
95
- task_id = sys.argv[2]
96
- output_dir = Path(sys.argv[3])
97
- env = os.environ.copy()
98
- env["PYTHONPATH"] = str(root / "src") + os.pathsep + env.get("PYTHONPATH", "")
99
- cmd = [sys.executable, "-m", "webarena_verified", "eval-tasks", "--task-ids", task_id, "--output-dir", str(output_dir)]
100
- proc = subprocess.run(cmd, cwd=root, env=env, text=True, capture_output=True)
101
- if proc.returncode != 0:
102
- raise SystemExit((proc.stderr or proc.stdout or f"exit {proc.returncode}")[:2000])
103
- result_path = output_dir / task_id / "eval_result.json"
104
- if not result_path.exists():
105
- raise SystemExit(f"official evaluator did not write {result_path}")
106
- print(json.dumps(json.loads(result_path.read_text())))
107
- `;
108
- const stdout = await runVenvPython(script, [root, String(taskId), outputDir], 0);
109
- return JSON.parse(stdout.trim().split("\n").at(-1) ?? "{}");
110
- }
111
- function createWebArenaVerifiedAdapter() {
112
- const fixturesMode = process.env.WEBARENA_VERIFIED_FIXTURES === "1";
113
- return {
114
- name: "webarena-verified",
115
- output: webarenaOutputDirOutput,
116
- async preflight() {
117
- if (fixturesMode) return;
118
- const dir = webarenaDir();
119
- if (!dir) {
120
- throw new Error(
121
- "WEBARENA_VERIFIED_DIR is required. Fix: clone https://github.com/ServiceNow/webarena-verified, install its deps in bench/.venv, and set WEBARENA_VERIFIED_DIR=/path/to/webarena-verified."
122
- );
123
- }
124
- await assertFile(join(dir, DATASET_REL), "official dataset");
125
- await assertFile(join(dir, "src", "webarena_verified", "__main__.py"), "official CLI module");
126
- await runVenvPython(
127
- 'import sys; sys.path.insert(0, sys.argv[1]); import webarena_verified; print("ok")',
128
- [join(dir, "src")]
129
- );
130
- },
131
- async loadTasks(opts = {}) {
132
- if (fixturesMode) return loadFixtures(opts);
133
- const dir = webarenaDir();
134
- if (!dir) throw new Error("WEBARENA_VERIFIED_DIR is required to load official WebArena-Verified tasks");
135
- return loadOfficialRows(dir, opts);
136
- },
137
- async goldArtifact() {
138
- return void 0;
139
- },
140
- async judge(task, artifact) {
141
- const dir = webarenaDir();
142
- if (!dir) throw new Error("WEBARENA_VERIFIED_DIR is required to judge WebArena-Verified artifacts");
143
- const outputDir = resolve(artifact.trim());
144
- await assertDir(outputDir, "run output directory");
145
- const meta = readMeta(task);
146
- const report = await runOfficialEval(dir, meta.taskId, outputDir);
147
- const score = typeof report.score === "number" ? report.score : 0;
148
- const status = typeof report.status === "string" ? report.status : "unknown";
149
- return {
150
- resolved: score === 1,
151
- score,
152
- detail: JSON.stringify({ taskId: meta.taskId, status, outputDir })
153
- };
154
- }
155
- };
156
- }
157
-
158
- export {
159
- webarenaOutputDirOutput,
160
- createWebArenaVerifiedAdapter
161
- };
162
- //# sourceMappingURL=chunk-HWST3SED.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/benchmarks/webarena-verified.ts"],"sourcesContent":["/**\n * WebArena-Verified adapter (ServiceNow/webarena-verified).\n *\n * Worker artifact = a WebArena-Verified run output directory, not final chat text.\n * Judge = the official `webarena_verified eval-tasks` evaluator over that output\n * directory. The adapter refuses to score a plain answer so we do not turn a DOM\n * benchmark into a fake text benchmark.\n */\n\nimport { access, readFile, stat } from 'node:fs/promises'\nimport { join, resolve } from 'node:path'\nimport type { OutputAdapter } from '@tangle-network/agent-runtime/loops'\nimport { benchRoot, runVenvPython } from './_harness'\nimport type { BenchmarkAdapter, BenchScore, BenchTask, LoadOptions } from './types'\n\nconst FIXTURES = join(benchRoot, 'fixtures', 'webarena-verified.json')\nconst DATASET_REL = join('assets', 'dataset', 'webarena-verified.json')\n\ninterface WebArenaRow {\n task_id: number\n intent: string\n intent_template_id?: number\n sites?: string[]\n start_urls?: string[]\n eval?: unknown[]\n revision?: number\n}\n\ninterface WebArenaMeta {\n taskId: number\n intentTemplateId?: number\n sites: string[]\n startUrls: string[]\n revision?: number\n eval?: unknown[]\n}\n\nconst webarenaDir = (): string | undefined => process.env.WEBARENA_VERIFIED_DIR\n\nexport const webarenaOutputDirOutput: 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|path)?\\s*\\n([\\s\\S]*?)```/g)]\n return (fences.at(-1)?.[1] ?? text).trim()\n },\n}\n\nasync function assertFile(path: string, label: string): Promise<void> {\n try {\n await access(path)\n } catch (err) {\n throw new Error(`WebArena-Verified: missing ${label} at ${path} (${err instanceof Error ? err.message : err})`)\n }\n}\n\nasync function assertDir(path: string, label: string): Promise<void> {\n try {\n const s = await stat(path)\n if (!s.isDirectory()) throw new Error('not a directory')\n } catch (err) {\n throw new Error(`WebArena-Verified: missing ${label} at ${path} (${err instanceof Error ? err.message : err})`)\n }\n}\n\nfunction rowToTask(row: WebArenaRow): BenchTask {\n const meta: WebArenaMeta = {\n taskId: row.task_id,\n intentTemplateId: row.intent_template_id,\n sites: row.sites ?? [],\n startUrls: row.start_urls ?? [],\n revision: row.revision,\n eval: row.eval,\n }\n return {\n id: String(row.task_id),\n prompt: [\n 'Run this WebArena-Verified browser task in the official environment.',\n `Goal: ${row.intent}`,\n row.start_urls?.length ? `Start URL templates: ${row.start_urls.join(', ')}` : undefined,\n row.sites?.length ? `Sites: ${row.sites.join(', ')}` : undefined,\n '',\n 'Return the path to the official WebArena-Verified run output directory for this task.',\n 'The judge expects that directory to contain the task response and network trace files.',\n ]\n .filter(Boolean)\n .join('\\n'),\n metadata: meta as unknown as Record<string, unknown>,\n }\n}\n\nfunction readMeta(task: BenchTask): WebArenaMeta {\n const md = task.metadata\n if (!md || typeof md.taskId !== 'number') {\n throw new Error(`webarena-verified task ${task.id} missing metadata — loadTasks did not populate it`)\n }\n return md as unknown as WebArenaMeta\n}\n\nfunction selectRows(rows: WebArenaRow[], opts: LoadOptions): BenchTask[] {\n let tasks = rows.map(rowToTask)\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(`WebArena-Verified: no tasks matched ${JSON.stringify(opts)}`)\n return tasks\n}\n\nasync function loadFixtures(opts: LoadOptions): Promise<BenchTask[]> {\n const rows = JSON.parse(await readFile(FIXTURES, 'utf8')) as WebArenaRow[]\n console.warn(`[webarena-verified] WEBARENA_VERIFIED_FIXTURES=1 — loading ${rows.length} adapter fixtures`)\n return selectRows(rows, opts)\n}\n\nasync function loadOfficialRows(dir: string, opts: LoadOptions): Promise<BenchTask[]> {\n const rows = JSON.parse(await readFile(join(dir, DATASET_REL), 'utf8')) as WebArenaRow[]\n return selectRows(rows, opts)\n}\n\nasync function runOfficialEval(root: string, taskId: number, outputDir: string): Promise<Record<string, unknown>> {\n const script = `\nimport json, os, subprocess, sys\nfrom pathlib import Path\n\nroot = Path(sys.argv[1])\ntask_id = sys.argv[2]\noutput_dir = Path(sys.argv[3])\nenv = os.environ.copy()\nenv[\"PYTHONPATH\"] = str(root / \"src\") + os.pathsep + env.get(\"PYTHONPATH\", \"\")\ncmd = [sys.executable, \"-m\", \"webarena_verified\", \"eval-tasks\", \"--task-ids\", task_id, \"--output-dir\", str(output_dir)]\nproc = subprocess.run(cmd, cwd=root, env=env, text=True, capture_output=True)\nif proc.returncode != 0:\n raise SystemExit((proc.stderr or proc.stdout or f\"exit {proc.returncode}\")[:2000])\nresult_path = output_dir / task_id / \"eval_result.json\"\nif not result_path.exists():\n raise SystemExit(f\"official evaluator did not write {result_path}\")\nprint(json.dumps(json.loads(result_path.read_text())))\n`\n const stdout = await runVenvPython(script, [root, String(taskId), outputDir], 0)\n return JSON.parse(stdout.trim().split('\\n').at(-1) ?? '{}') as Record<string, unknown>\n}\n\nexport function createWebArenaVerifiedAdapter(): BenchmarkAdapter {\n const fixturesMode = process.env.WEBARENA_VERIFIED_FIXTURES === '1'\n\n return {\n name: 'webarena-verified',\n output: webarenaOutputDirOutput,\n\n async preflight() {\n if (fixturesMode) return\n const dir = webarenaDir()\n if (!dir) {\n throw new Error(\n 'WEBARENA_VERIFIED_DIR is required. Fix: clone https://github.com/ServiceNow/webarena-verified, install its deps in bench/.venv, and set WEBARENA_VERIFIED_DIR=/path/to/webarena-verified.',\n )\n }\n await assertFile(join(dir, DATASET_REL), 'official dataset')\n await assertFile(join(dir, 'src', 'webarena_verified', '__main__.py'), 'official CLI module')\n await runVenvPython(\n 'import sys; sys.path.insert(0, sys.argv[1]); import webarena_verified; print(\"ok\")',\n [join(dir, 'src')],\n )\n },\n\n async loadTasks(opts: LoadOptions = {}) {\n if (fixturesMode) return loadFixtures(opts)\n const dir = webarenaDir()\n if (!dir) throw new Error('WEBARENA_VERIFIED_DIR is required to load official WebArena-Verified tasks')\n return loadOfficialRows(dir, opts)\n },\n\n async goldArtifact() {\n return undefined\n },\n\n async judge(task: BenchTask, artifact: string): Promise<BenchScore> {\n const dir = webarenaDir()\n if (!dir) throw new Error('WEBARENA_VERIFIED_DIR is required to judge WebArena-Verified artifacts')\n const outputDir = resolve(artifact.trim())\n await assertDir(outputDir, 'run output directory')\n const meta = readMeta(task)\n const report = await runOfficialEval(dir, meta.taskId, outputDir)\n const score = typeof report.score === 'number' ? report.score : 0\n const status = typeof report.status === 'string' ? report.status : 'unknown'\n return {\n resolved: score === 1,\n score,\n detail: JSON.stringify({ taskId: meta.taskId, status, outputDir }),\n }\n },\n }\n}\n"],"mappings":"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","names":[]}
@@ -1,318 +0,0 @@
1
- import {
2
- benchRoot,
3
- preflightVenvImports,
4
- runVenvScriptStdin,
5
- venvPython
6
- } from "./chunk-WSKWVEQB.js";
7
-
8
- // src/benchmarks/appworld.ts
9
- import { spawn } from "child_process";
10
- import { join } from "path";
11
- import { createInterface } from "readline";
12
- import { routerToolLoop } from "@tangle-network/agent-runtime/loops";
13
- var DRIVER = join(benchRoot, "scripts", "appworld_driver.py");
14
- var DEFAULT_SPLIT = "test_normal";
15
- var appworldSolutionOutput = {
16
- parse(events) {
17
- let text = "";
18
- for (const ev of events) {
19
- const d = ev?.data;
20
- const t = d?.finalText ?? d?.text ?? d?.result;
21
- if (typeof t === "string" && t.length > 0) text = t;
22
- }
23
- const fences = [...text.matchAll(/```(?:python|py)?\s*\n([\s\S]*?)```/g)];
24
- return (fences.at(-1)?.[1] ?? text).trim();
25
- }
26
- };
27
- var WORKER_CONTRACT = [
28
- "",
29
- "Solve this by writing Python that calls the available app APIs (the `apis.<app>.<function>(...)` surface). You may inspect API docs with `apis.api_docs.show_api_descriptions(app_name=...)` and `apis.api_docs.show_api_doc(app_name=..., api_name=...)`.",
30
- "Authenticate where needed via the supervisor-provided credentials, perform every step the task requires, and FINISH with `apis.supervisor.complete_task()`.",
31
- "Emit your COMPLETE solution as the LAST thing in your reply, in a single fenced ```python block. Nothing after the closing fence."
32
- ].join("\n");
33
- function readMeta(task) {
34
- const md = task.metadata;
35
- if (!md || typeof md.taskId !== "string") {
36
- throw new Error(`appworld task ${task.id} missing metadata.taskId \u2014 loadTasks did not populate it`);
37
- }
38
- return md;
39
- }
40
- async function driver(args, input = "") {
41
- let stdout;
42
- try {
43
- stdout = await runVenvScriptStdin(DRIVER, args, input, { cwd: benchRoot });
44
- } catch (err) {
45
- const e = err;
46
- throw new Error(`appworld driver failed (${args.join(" ")}): ${(e.message || String(err)).slice(0, 1500)}`);
47
- }
48
- const last = stdout.trim().split("\n").at(-1) ?? "{}";
49
- const parsed = JSON.parse(last);
50
- if (parsed.error) throw new Error(`appworld driver error: ${parsed.error}`);
51
- return parsed;
52
- }
53
- function createAppWorldAdapter() {
54
- return {
55
- name: "appworld",
56
- output: appworldSolutionOutput,
57
- async preflight() {
58
- await preflightVenvImports({
59
- modules: ["appworld"],
60
- requireDocker: false,
61
- fix: "Fix: bench/.venv/bin/pip install appworld ; bench/.venv/bin/appworld install ; bench/.venv/bin/appworld download data (unpacks the engine + downloads the simulated-app data/tasks). Set APPWORLD_ROOT to the data root if not the default."
62
- });
63
- },
64
- async loadTasks(opts = {}) {
65
- const split = opts.split ?? DEFAULT_SPLIT;
66
- const out = await driver([
67
- "load",
68
- "--split",
69
- split,
70
- ...opts.limit !== void 0 ? ["--limit", String(opts.limit)] : [],
71
- ...opts.ids ? ["--ids", opts.ids.join(",")] : []
72
- ]);
73
- const tasks = out.tasks ?? [];
74
- if (tasks.length === 0) {
75
- throw new Error(`appworld loadTasks returned no tasks for split=${split} ${JSON.stringify(opts)}`);
76
- }
77
- return tasks.map(
78
- (t) => ({
79
- id: t.task_id,
80
- split,
81
- prompt: t.instruction + WORKER_CONTRACT,
82
- metadata: { taskId: t.task_id, split }
83
- })
84
- );
85
- },
86
- async goldArtifact() {
87
- return void 0;
88
- },
89
- async judge(task, artifact) {
90
- const meta = readMeta(task);
91
- const out = await driver(["evaluate", "--task-id", meta.taskId, "--split", meta.split], artifact);
92
- const passes = out.passes ?? 0;
93
- const fails = out.fails ?? 0;
94
- const total = out.num_tests ?? passes + fails;
95
- const score = total > 0 ? passes / total : 0;
96
- const failures = Array.isArray(out.failure_names) ? out.failure_names : [];
97
- return {
98
- resolved: out.success === true,
99
- score,
100
- detail: JSON.stringify({
101
- taskId: meta.taskId,
102
- success: out.success,
103
- passes,
104
- fails,
105
- total,
106
- ...failures.length ? { failures } : {}
107
- })
108
- };
109
- }
110
- };
111
- }
112
- var REACT_HEADER = /^@appworld-react (\S+) (\S+)\n?/;
113
- var SESSION_SYSTEM = [
114
- "You are completing a task in AppWorld, a simulated multi-app environment.",
115
- "Use the execute_python tool to run Python that calls the app APIs (the `apis.<app>.<function>(...)` surface).",
116
- "Inspect API docs with `apis.api_docs.show_api_descriptions(app_name=...)` and `apis.api_docs.show_api_doc(app_name=..., api_name=...)`.",
117
- "Authenticate where needed via the supervisor-provided credentials (`apis.supervisor.show_account_passwords()`).",
118
- "Work incrementally: small snippets, read each output, correct course.",
119
- "When every step of the task is done, run `apis.supervisor.complete_task()` and then reply WITHOUT calling the tool again."
120
- ].join("\n");
121
- var EXECUTE_TOOL = {
122
- type: "function",
123
- function: {
124
- name: "execute_python",
125
- description: "Execute a Python snippet in the persistent AppWorld world. State persists across calls. Returns the execution output (API results or errors).",
126
- parameters: {
127
- type: "object",
128
- properties: { code: { type: "string", description: "Python code calling apis.<app>.<fn>(...)" } },
129
- required: ["code"]
130
- }
131
- }
132
- };
133
- async function withWorldSession(taskId, split, fn) {
134
- const child = spawn(venvPython, [DRIVER, "session", "--task-id", taskId, "--split", split], {
135
- cwd: benchRoot
136
- });
137
- const rl = createInterface({ input: child.stdout });
138
- const pending = [];
139
- const backlog = [];
140
- rl.on("line", (l) => {
141
- const next = pending.shift();
142
- if (next) next(l);
143
- else backlog.push(l);
144
- });
145
- let stderr = "";
146
- child.stderr.on("data", (c) => {
147
- stderr += c.toString("utf8");
148
- });
149
- const nextLine = (timeoutMs) => new Promise((resolve, reject) => {
150
- const fromBacklog = backlog.shift();
151
- if (fromBacklog !== void 0) return resolve(fromBacklog);
152
- const t = setTimeout(
153
- () => reject(new Error(`appworld session: no response in ${timeoutMs}ms; stderr: ${stderr.slice(-400)}`)),
154
- timeoutMs
155
- );
156
- const onExit = (code) => {
157
- clearTimeout(t);
158
- reject(new Error(`appworld session exited (${code}); stderr: ${stderr.slice(-400)}`));
159
- };
160
- pending.push((l) => {
161
- clearTimeout(t);
162
- child.removeListener("exit", onExit);
163
- resolve(l);
164
- });
165
- child.once("exit", onExit);
166
- });
167
- try {
168
- const ready = JSON.parse(await nextLine(12e4));
169
- if (!ready.ready) throw new Error(`appworld session failed to start: ${ready.error ?? "no ready line"}`);
170
- const call = async (cmd) => {
171
- child.stdin.write(`${JSON.stringify(cmd)}
172
- `);
173
- const res = JSON.parse(await nextLine(18e4));
174
- if (typeof res.error === "string") throw new Error(`appworld session op failed: ${res.error}`);
175
- return res;
176
- };
177
- return await fn(call, ready.instruction ?? "");
178
- } finally {
179
- child.stdin.end();
180
- child.kill("SIGTERM");
181
- }
182
- }
183
- function appworldToolLoopClient(cfg) {
184
- const maxTurns = cfg.maxTurns ?? Number(process.env.REACT_MAX_TURNS ?? 40);
185
- let seq = 0;
186
- return {
187
- async create() {
188
- const id = `appworld-toolloop-${seq++}`;
189
- return {
190
- id,
191
- async *streamPrompt(prompt) {
192
- const m = prompt.match(REACT_HEADER);
193
- if (!m) {
194
- throw new Error(
195
- `appworld-react leaf: prompt missing '@appworld-react <taskId> <split>' header \u2014 got: ${prompt.slice(0, 120)}`
196
- );
197
- }
198
- const [, taskId, split] = m;
199
- const directive = prompt.replace(REACT_HEADER, "").trim();
200
- const out = await withWorldSession(taskId, split, async (call, instruction) => {
201
- const system = directive ? `${SESSION_SYSTEM}
202
-
203
- ${directive}` : SESSION_SYSTEM;
204
- const loop = await routerToolLoop(
205
- { routerBaseUrl: cfg.routerBaseUrl, routerKey: cfg.routerKey, model: cfg.model },
206
- system,
207
- `Task: ${instruction}`,
208
- [EXECUTE_TOOL],
209
- async (name, args) => {
210
- if (name !== "execute_python") return `error: unknown tool ${name}`;
211
- const res = await call({ op: "execute", code: String(args.code ?? "") });
212
- const done = res.task_completed === true;
213
- return `${String(res.output ?? "")}${done ? "\n\n[TASK MARKED COMPLETE \u2014 reply with a final summary and do not call the tool again]" : ""}`;
214
- },
215
- { maxTurns }
216
- );
217
- const verdict = await call({ op: "evaluate" });
218
- const transcript = loop.toolTrace.slice(-3).map((t) => `CODE:
219
- ${t.args.slice(0, 600)}
220
- OUTPUT:
221
- ${t.result.slice(0, 600)}`).join("\n---\n").slice(0, 1600);
222
- return {
223
- ...verdict,
224
- turns: loop.turns,
225
- input_tokens: loop.usage.input,
226
- output_tokens: loop.usage.output,
227
- transcript
228
- };
229
- });
230
- if (out.input_tokens || out.output_tokens) {
231
- yield {
232
- type: "llm_call",
233
- data: { tokensIn: out.input_tokens ?? 0, tokensOut: out.output_tokens ?? 0, model: cfg.model }
234
- };
235
- }
236
- yield { type: "result", data: { finalText: JSON.stringify(out) } };
237
- },
238
- async delete() {
239
- }
240
- };
241
- }
242
- };
243
- }
244
- var reactEpisodeOutput = {
245
- parse(events) {
246
- let text = "";
247
- for (const ev of events) {
248
- const d = ev?.data;
249
- const t = d?.finalText;
250
- if (typeof t === "string" && t.length > 0) text = t;
251
- }
252
- return text;
253
- }
254
- };
255
- function createAppWorldReactAdapter() {
256
- const base = createAppWorldAdapter();
257
- return {
258
- name: "appworld-react",
259
- output: reactEpisodeOutput,
260
- preflight: () => base.preflight(),
261
- async loadTasks(opts = {}) {
262
- const tasks = await base.loadTasks(opts);
263
- return tasks.map((t) => {
264
- const meta = readMeta(t);
265
- return {
266
- ...t,
267
- // Header carries task identity to the leaf; the body (empty at round 0)
268
- // is the directive slot the arms append their steer into.
269
- prompt: `@appworld-react ${meta.taskId} ${meta.split}
270
- `
271
- };
272
- });
273
- },
274
- goldArtifact: () => Promise.resolve(void 0),
275
- async judge(task, artifact) {
276
- const meta = readMeta(task);
277
- let out;
278
- try {
279
- out = JSON.parse(artifact);
280
- } catch {
281
- throw new Error(
282
- `appworld-react judge: artifact is not the episode's evaluation JSON (task ${meta.taskId}): ${artifact.slice(0, 200)}`
283
- );
284
- }
285
- if (typeof out.success !== "boolean" || typeof out.num_tests !== "number") {
286
- throw new Error(
287
- `appworld-react judge: episode JSON missing success/num_tests (task ${meta.taskId}): ${artifact.slice(0, 200)}`
288
- );
289
- }
290
- const passes = out.passes ?? 0;
291
- const total = out.num_tests;
292
- const failures = Array.isArray(out.failure_names) ? out.failure_names : [];
293
- return {
294
- resolved: out.success === true,
295
- score: total > 0 ? passes / total : 0,
296
- detail: JSON.stringify({
297
- taskId: meta.taskId,
298
- success: out.success,
299
- passes,
300
- fails: out.fails ?? 0,
301
- total,
302
- turns: out.turns,
303
- ...failures.length ? { failures } : {},
304
- ...out.transcript ? { transcriptTail: out.transcript.slice(-800) } : {}
305
- })
306
- };
307
- },
308
- leafClient: (c) => appworldToolLoopClient(c)
309
- };
310
- }
311
-
312
- export {
313
- appworldSolutionOutput,
314
- createAppWorldAdapter,
315
- appworldToolLoopClient,
316
- createAppWorldReactAdapter
317
- };
318
- //# sourceMappingURL=chunk-IA2FBTWC.js.map