@tangle-network/agent-bench 0.3.5 → 0.3.6

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 (182) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +13 -1
  3. package/dist/adapters.d.ts +15 -0
  4. package/dist/adapters.js +43 -0
  5. package/dist/adapters.js.map +1 -0
  6. package/dist/benchmarks/_harness.d.ts +125 -0
  7. package/dist/benchmarks/_harness.js +33 -0
  8. package/dist/benchmarks/_harness.js.map +1 -0
  9. package/dist/benchmarks/aec-bench.d.ts +27 -0
  10. package/dist/benchmarks/aec-bench.js +8 -0
  11. package/dist/benchmarks/aec-bench.js.map +1 -0
  12. package/dist/benchmarks/agentbench.d.ts +16 -0
  13. package/dist/benchmarks/agentbench.js +10 -0
  14. package/dist/benchmarks/agentbench.js.map +1 -0
  15. package/dist/benchmarks/appworld.d.ts +37 -0
  16. package/dist/benchmarks/appworld.js +14 -0
  17. package/dist/benchmarks/appworld.js.map +1 -0
  18. package/dist/benchmarks/bfcl.d.ts +18 -0
  19. package/dist/benchmarks/bfcl.js +10 -0
  20. package/dist/benchmarks/bfcl.js.map +1 -0
  21. package/dist/benchmarks/cad-design.d.ts +45 -0
  22. package/dist/benchmarks/cad-design.js +7 -0
  23. package/dist/benchmarks/cad-design.js.map +1 -0
  24. package/dist/benchmarks/cadbench.d.ts +19 -0
  25. package/dist/benchmarks/cadbench.js +8 -0
  26. package/dist/benchmarks/cadbench.js.map +1 -0
  27. package/dist/benchmarks/cadgenbench.d.ts +22 -0
  28. package/dist/benchmarks/cadgenbench.js +8 -0
  29. package/dist/benchmarks/cadgenbench.js.map +1 -0
  30. package/dist/benchmarks/commit0.d.ts +31 -0
  31. package/dist/benchmarks/commit0.js +10 -0
  32. package/dist/benchmarks/commit0.js.map +1 -0
  33. package/dist/benchmarks/crag.d.ts +14 -0
  34. package/dist/benchmarks/crag.js +9 -0
  35. package/dist/benchmarks/crag.js.map +1 -0
  36. package/dist/benchmarks/dabstep.d.ts +18 -0
  37. package/dist/benchmarks/dabstep.js +10 -0
  38. package/dist/benchmarks/dabstep.js.map +1 -0
  39. package/dist/benchmarks/enterpriseops-gym.d.ts +38 -0
  40. package/dist/benchmarks/enterpriseops-gym.js +10 -0
  41. package/dist/benchmarks/enterpriseops-gym.js.map +1 -0
  42. package/dist/benchmarks/finresearchbench.d.ts +15 -0
  43. package/dist/benchmarks/finresearchbench.js +8 -0
  44. package/dist/benchmarks/finresearchbench.js.map +1 -0
  45. package/dist/benchmarks/finsearchcomp.d.ts +49 -0
  46. package/dist/benchmarks/finsearchcomp.js +7 -0
  47. package/dist/benchmarks/finsearchcomp.js.map +1 -0
  48. package/dist/benchmarks/frames.d.ts +59 -0
  49. package/dist/benchmarks/frames.js +13 -0
  50. package/dist/benchmarks/frames.js.map +1 -0
  51. package/dist/benchmarks/hotpotqa.d.ts +48 -0
  52. package/dist/benchmarks/hotpotqa.js +15 -0
  53. package/dist/benchmarks/hotpotqa.js.map +1 -0
  54. package/dist/benchmarks/humaneval.d.ts +53 -0
  55. package/dist/benchmarks/humaneval.js +15 -0
  56. package/dist/benchmarks/humaneval.js.map +1 -0
  57. package/dist/benchmarks/mind2web.d.ts +41 -0
  58. package/dist/benchmarks/mind2web.js +9 -0
  59. package/dist/benchmarks/mind2web.js.map +1 -0
  60. package/dist/benchmarks/nomiracl.d.ts +15 -0
  61. package/dist/benchmarks/nomiracl.js +9 -0
  62. package/dist/benchmarks/nomiracl.js.map +1 -0
  63. package/dist/benchmarks/open-rag-bench.d.ts +14 -0
  64. package/dist/benchmarks/open-rag-bench.js +9 -0
  65. package/dist/benchmarks/open-rag-bench.js.map +1 -0
  66. package/dist/benchmarks/programbench.d.ts +38 -0
  67. package/dist/benchmarks/programbench.js +10 -0
  68. package/dist/benchmarks/programbench.js.map +1 -0
  69. package/dist/benchmarks/rag-shared.d.ts +42 -0
  70. package/dist/benchmarks/rag-shared.js +39 -0
  71. package/dist/benchmarks/rag-shared.js.map +1 -0
  72. package/dist/benchmarks/ragbench.d.ts +16 -0
  73. package/dist/benchmarks/ragbench.js +9 -0
  74. package/dist/benchmarks/ragbench.js.map +1 -0
  75. package/dist/benchmarks/simpleqa.d.ts +64 -0
  76. package/dist/benchmarks/simpleqa.js +11 -0
  77. package/dist/benchmarks/simpleqa.js.map +1 -0
  78. package/dist/benchmarks/swe-bench.d.ts +56 -0
  79. package/dist/benchmarks/swe-bench.js +14 -0
  80. package/dist/benchmarks/swe-bench.js.map +1 -0
  81. package/dist/benchmarks/t2-ragbench.d.ts +14 -0
  82. package/dist/benchmarks/t2-ragbench.js +9 -0
  83. package/dist/benchmarks/t2-ragbench.js.map +1 -0
  84. package/dist/benchmarks/tau-bench-shared.d.ts +26 -0
  85. package/dist/benchmarks/tau-bench-shared.js +10 -0
  86. package/dist/benchmarks/tau-bench-shared.js.map +1 -0
  87. package/dist/benchmarks/tau2-bench.d.ts +7 -0
  88. package/dist/benchmarks/tau2-bench.js +11 -0
  89. package/dist/benchmarks/tau2-bench.js.map +1 -0
  90. package/dist/benchmarks/tau3-banking.d.ts +15 -0
  91. package/dist/benchmarks/tau3-banking.js +9 -0
  92. package/dist/benchmarks/tau3-banking.js.map +1 -0
  93. package/dist/benchmarks/terminal-bench.d.ts +24 -0
  94. package/dist/benchmarks/terminal-bench.js +8 -0
  95. package/dist/benchmarks/terminal-bench.js.map +1 -0
  96. package/dist/benchmarks/toollm.d.ts +16 -0
  97. package/dist/benchmarks/toollm.js +10 -0
  98. package/dist/benchmarks/toollm.js.map +1 -0
  99. package/dist/benchmarks/trata-hedge.d.ts +32 -0
  100. package/dist/benchmarks/trata-hedge.js +7 -0
  101. package/dist/benchmarks/trata-hedge.js.map +1 -0
  102. package/dist/benchmarks/types.d.ts +107 -0
  103. package/dist/benchmarks/types.js +1 -0
  104. package/dist/benchmarks/types.js.map +1 -0
  105. package/dist/benchmarks/webarena-verified.d.ts +16 -0
  106. package/dist/benchmarks/webarena-verified.js +10 -0
  107. package/dist/benchmarks/webarena-verified.js.map +1 -0
  108. package/dist/chunk-2PVVP7GN.js +197 -0
  109. package/dist/chunk-2PVVP7GN.js.map +1 -0
  110. package/dist/chunk-2XU6OGEN.js +170 -0
  111. package/dist/chunk-2XU6OGEN.js.map +1 -0
  112. package/dist/chunk-53UPUNBZ.js +325 -0
  113. package/dist/chunk-53UPUNBZ.js.map +1 -0
  114. package/dist/chunk-5SBJCB6W.js +144 -0
  115. package/dist/chunk-5SBJCB6W.js.map +1 -0
  116. package/dist/chunk-7WSD27QQ.js +118 -0
  117. package/dist/chunk-7WSD27QQ.js.map +1 -0
  118. package/dist/chunk-C7T7WEK2.js +103 -0
  119. package/dist/chunk-C7T7WEK2.js.map +1 -0
  120. package/dist/chunk-CKUVRZ2T.js +251 -0
  121. package/dist/chunk-CKUVRZ2T.js.map +1 -0
  122. package/dist/chunk-HBSWHQNJ.js +30 -0
  123. package/dist/chunk-HBSWHQNJ.js.map +1 -0
  124. package/dist/chunk-HHXFIHXC.js +116 -0
  125. package/dist/chunk-HHXFIHXC.js.map +1 -0
  126. package/dist/chunk-IFAV6KEM.js +276 -0
  127. package/dist/chunk-IFAV6KEM.js.map +1 -0
  128. package/dist/chunk-INNOYXCP.js +387 -0
  129. package/dist/chunk-INNOYXCP.js.map +1 -0
  130. package/dist/chunk-J3KDJNX2.js +182 -0
  131. package/dist/chunk-J3KDJNX2.js.map +1 -0
  132. package/dist/chunk-JRWWGMK7.js +148 -0
  133. package/dist/chunk-JRWWGMK7.js.map +1 -0
  134. package/dist/chunk-JTHWEDEW.js +32 -0
  135. package/dist/chunk-JTHWEDEW.js.map +1 -0
  136. package/dist/chunk-KDIKRJGB.js +120 -0
  137. package/dist/chunk-KDIKRJGB.js.map +1 -0
  138. package/dist/chunk-LRRD7NAG.js +301 -0
  139. package/dist/chunk-LRRD7NAG.js.map +1 -0
  140. package/dist/chunk-ODT47UAY.js +221 -0
  141. package/dist/chunk-ODT47UAY.js.map +1 -0
  142. package/dist/chunk-PA2ZKHJC.js +230 -0
  143. package/dist/chunk-PA2ZKHJC.js.map +1 -0
  144. package/dist/chunk-PPYSEKFM.js +182 -0
  145. package/dist/chunk-PPYSEKFM.js.map +1 -0
  146. package/dist/chunk-PUIRNYI7.js +189 -0
  147. package/dist/chunk-PUIRNYI7.js.map +1 -0
  148. package/dist/chunk-R36V2VP7.js +169 -0
  149. package/dist/chunk-R36V2VP7.js.map +1 -0
  150. package/dist/chunk-R67DFVLO.js +142 -0
  151. package/dist/chunk-R67DFVLO.js.map +1 -0
  152. package/dist/chunk-SEVJPLZC.js +260 -0
  153. package/dist/chunk-SEVJPLZC.js.map +1 -0
  154. package/dist/chunk-SYDW647C.js +318 -0
  155. package/dist/chunk-SYDW647C.js.map +1 -0
  156. package/dist/chunk-TBKU5XQI.js +228 -0
  157. package/dist/chunk-TBKU5XQI.js.map +1 -0
  158. package/dist/chunk-TSWPNOYM.js +147 -0
  159. package/dist/chunk-TSWPNOYM.js.map +1 -0
  160. package/dist/chunk-UAIOHCUK.js +27 -0
  161. package/dist/chunk-UAIOHCUK.js.map +1 -0
  162. package/dist/chunk-UPAMRDX4.js +233 -0
  163. package/dist/chunk-UPAMRDX4.js.map +1 -0
  164. package/dist/chunk-VQRS7VUC.js +342 -0
  165. package/dist/chunk-VQRS7VUC.js.map +1 -0
  166. package/dist/chunk-X3BTXCJ4.js +262 -0
  167. package/dist/chunk-X3BTXCJ4.js.map +1 -0
  168. package/dist/chunk-X5YKXC6V.js +211 -0
  169. package/dist/chunk-X5YKXC6V.js.map +1 -0
  170. package/dist/chunk-Y6O2OCUO.js +130 -0
  171. package/dist/chunk-Y6O2OCUO.js.map +1 -0
  172. package/dist/chunk-YCGY7UIZ.js +208 -0
  173. package/dist/chunk-YCGY7UIZ.js.map +1 -0
  174. package/dist/chunk-Z7ML6L77.js +162 -0
  175. package/dist/chunk-Z7ML6L77.js.map +1 -0
  176. package/dist/chunk-ZEWMTR5M.js +136 -0
  177. package/dist/chunk-ZEWMTR5M.js.map +1 -0
  178. package/dist/index.d.ts +355 -0
  179. package/dist/index.js +1908 -0
  180. package/dist/index.js.map +1 -0
  181. package/package.json +22 -6
  182. package/scripts/verify-packed-consumer.mjs +12 -1
@@ -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":[]}
@@ -0,0 +1,30 @@
1
+ import {
2
+ createTauBenchAdapter,
3
+ tauResultsOutput
4
+ } from "./chunk-R36V2VP7.js";
5
+ import {
6
+ benchRoot
7
+ } from "./chunk-LRRD7NAG.js";
8
+
9
+ // src/benchmarks/tau2-bench.ts
10
+ import { join } from "path";
11
+ var FIXTURES = join(benchRoot, "fixtures", "tau2-bench.json");
12
+ var tau2ResultsOutput = tauResultsOutput;
13
+ function createTau2BenchAdapter() {
14
+ return createTauBenchAdapter({
15
+ name: "tau2-bench",
16
+ fixturePath: FIXTURES,
17
+ fixturesEnv: "TAU2_FIXTURES",
18
+ dirEnv: "TAU2_BENCH_DIR",
19
+ domainEnv: "TAU2_DOMAIN",
20
+ defaultDomain: "retail",
21
+ taskIntro: "Run this tau2 task in the official tau2 text benchmark.",
22
+ installHint: "clone https://github.com/sierra-research/tau2-bench, install its deps in bench/.venv, and set TAU2_BENCH_DIR=/path/to/tau2-bench."
23
+ });
24
+ }
25
+
26
+ export {
27
+ tau2ResultsOutput,
28
+ createTau2BenchAdapter
29
+ };
30
+ //# sourceMappingURL=chunk-HBSWHQNJ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/benchmarks/tau2-bench.ts"],"sourcesContent":["/**\n * tau2-bench adapter (Sierra tau2/tau-bench successor).\n *\n * Worker artifact = a tau2 `results.json`/trajectory file. Judge = tau2's own\n * reward recomputation over that trajectory. A normal final-answer transcript is\n * not a valid artifact for this benchmark.\n */\n\nimport { join } from 'node:path'\nimport { benchRoot } from './_harness'\nimport { createTauBenchAdapter, tauResultsOutput } from './tau-bench-shared'\nimport type { BenchmarkAdapter } from './types'\n\nconst FIXTURES = join(benchRoot, 'fixtures', 'tau2-bench.json')\n\nexport const tau2ResultsOutput = tauResultsOutput\n\nexport function createTau2BenchAdapter(): BenchmarkAdapter {\n return createTauBenchAdapter({\n name: 'tau2-bench',\n fixturePath: FIXTURES,\n fixturesEnv: 'TAU2_FIXTURES',\n dirEnv: 'TAU2_BENCH_DIR',\n domainEnv: 'TAU2_DOMAIN',\n defaultDomain: 'retail',\n taskIntro: 'Run this tau2 task in the official tau2 text benchmark.',\n installHint:\n 'clone https://github.com/sierra-research/tau2-bench, install its deps in bench/.venv, and set TAU2_BENCH_DIR=/path/to/tau2-bench.',\n })\n}\n"],"mappings":";;;;;;;;;AAQA,SAAS,YAAY;AAKrB,IAAM,WAAW,KAAK,WAAW,YAAY,iBAAiB;AAEvD,IAAM,oBAAoB;AAE1B,SAAS,yBAA2C;AACzD,SAAO,sBAAsB;AAAA,IAC3B,MAAM;AAAA,IACN,aAAa;AAAA,IACb,aAAa;AAAA,IACb,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,eAAe;AAAA,IACf,WAAW;AAAA,IACX,aACE;AAAA,EACJ,CAAC;AACH;","names":[]}
@@ -0,0 +1,116 @@
1
+ import {
2
+ FINAL_ANSWER_SENTINEL,
3
+ allStrings,
4
+ answerScoreToBenchScore,
5
+ firstString,
6
+ isObject,
7
+ ragAnswerOutput,
8
+ readJsonRows,
9
+ scoreAnswerArtifact,
10
+ selectTasks,
11
+ stringFrom
12
+ } from "./chunk-X3BTXCJ4.js";
13
+ import {
14
+ benchRoot
15
+ } from "./chunk-LRRD7NAG.js";
16
+
17
+ // src/benchmarks/crag.ts
18
+ import { readFile } from "fs/promises";
19
+ import { join } from "path";
20
+ var FIXTURES = join(benchRoot, "fixtures", "crag.json");
21
+ var dataFile = () => process.env.CRAG_DATA_FILE;
22
+ function rowToTask(raw, index) {
23
+ if (!isObject(raw)) throw new Error(`CRAG row ${index} must be an object`);
24
+ const query = firstString(raw, ["query", "question", "prompt"]);
25
+ const goldAnswers = allStrings(raw, ["answer", "answers", "gold", "gold_answer", "expected_answer"]);
26
+ if (!query) throw new Error(`CRAG row ${index} missing query`);
27
+ if (goldAnswers.length === 0) throw new Error(`CRAG row ${index} missing gold answer`);
28
+ const domain = stringFrom(raw.domain) ?? "unknown";
29
+ const questionType = stringFrom(raw.question_type) ?? stringFrom(raw.questionType) ?? "unknown";
30
+ const dynamism = stringFrom(raw.static_or_dynamic) ?? stringFrom(raw.dynamism) ?? "unknown";
31
+ const id = stringFrom(raw.id) ?? stringFrom(raw.query_id) ?? `crag-${index}`;
32
+ const meta = {
33
+ benchmark: "crag",
34
+ query,
35
+ goldAnswers,
36
+ domain,
37
+ questionType,
38
+ dynamism
39
+ };
40
+ return {
41
+ id,
42
+ split: stringFrom(raw.split) ?? domain,
43
+ prompt: [
44
+ "Answer this CRAG factual question.",
45
+ "Return a concise answer and do not guess when the evidence is insufficient.",
46
+ "End with a single final line: `FINAL ANSWER: <answer>`.",
47
+ "",
48
+ `Question: ${query}`,
49
+ `Domain: ${domain}`,
50
+ `Question type: ${questionType}`,
51
+ `Dynamism: ${dynamism}`
52
+ ].join("\n"),
53
+ metadata: meta
54
+ };
55
+ }
56
+ function readMeta(task) {
57
+ const md = task.metadata;
58
+ if (!md || !Array.isArray(md.goldAnswers)) {
59
+ throw new Error(`CRAG task ${task.id} missing metadata \u2014 loadTasks did not populate it`);
60
+ }
61
+ return md;
62
+ }
63
+ async function loadRows(path) {
64
+ const rows = await readJsonRows(path);
65
+ if (rows.length === 0) throw new Error(`CRAG: no rows in ${path}`);
66
+ return rows;
67
+ }
68
+ async function loadFixtures(opts) {
69
+ const rows = JSON.parse(await readFile(FIXTURES, "utf8"));
70
+ console.warn(`[crag] CRAG_FIXTURES=1 \u2014 loading ${rows.length} adapter fixtures`);
71
+ return selectTasks(rows.map(rowToTask), opts, "CRAG");
72
+ }
73
+ function createCragAdapter() {
74
+ const fixturesMode = process.env.CRAG_FIXTURES === "1";
75
+ return {
76
+ name: "crag",
77
+ output: ragAnswerOutput,
78
+ async preflight() {
79
+ if (fixturesMode) {
80
+ await readFile(FIXTURES, "utf8");
81
+ return;
82
+ }
83
+ const path = dataFile();
84
+ if (!path) {
85
+ throw new Error(
86
+ "CRAG_DATA_FILE is required. Fix: export facebookresearch/CRAG rows to JSONL and set CRAG_DATA_FILE=/path/to/crag.jsonl, or set CRAG_FIXTURES=1 for adapter plumbing."
87
+ );
88
+ }
89
+ await loadRows(path);
90
+ },
91
+ async loadTasks(opts = {}) {
92
+ if (fixturesMode) return loadFixtures(opts);
93
+ const path = dataFile();
94
+ if (!path) throw new Error("CRAG_DATA_FILE is required to load CRAG tasks");
95
+ return selectTasks((await loadRows(path)).map(rowToTask), opts, "CRAG");
96
+ },
97
+ async goldArtifact(task) {
98
+ return `${FINAL_ANSWER_SENTINEL} ${readMeta(task).goldAnswers[0] ?? ""}`;
99
+ },
100
+ async judge(task, artifact) {
101
+ const meta = readMeta(task);
102
+ const score = scoreAnswerArtifact(artifact, meta.goldAnswers);
103
+ return answerScoreToBenchScore(score, {
104
+ benchmark: meta.benchmark,
105
+ domain: meta.domain,
106
+ questionType: meta.questionType,
107
+ dynamism: meta.dynamism
108
+ });
109
+ }
110
+ };
111
+ }
112
+
113
+ export {
114
+ createCragAdapter
115
+ };
116
+ //# sourceMappingURL=chunk-HHXFIHXC.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/benchmarks/crag.ts"],"sourcesContent":["/**\n * CRAG adapter (Comprehensive RAG Benchmark).\n *\n * Live mode expects an official or compatible CRAG JSON/JSONL export. The\n * adapter preserves CRAG domain/type/dynamism tags in metadata and scores final\n * answers deterministically against the provided gold answer list.\n */\n\nimport { readFile } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport { benchRoot } from './_harness'\nimport type { BenchmarkAdapter, BenchScore, BenchTask, LoadOptions } from './types'\nimport {\n FINAL_ANSWER_SENTINEL,\n allStrings,\n answerScoreToBenchScore,\n firstString,\n isObject,\n ragAnswerOutput,\n readJsonRows,\n scoreAnswerArtifact,\n selectTasks,\n stringFrom,\n} from './rag-shared'\n\nconst FIXTURES = join(benchRoot, 'fixtures', 'crag.json')\n\ninterface CragMeta {\n benchmark: 'crag'\n query: string\n goldAnswers: string[]\n domain: string\n questionType: string\n dynamism: string\n}\n\nconst dataFile = (): string | undefined => process.env.CRAG_DATA_FILE\n\nfunction rowToTask(raw: unknown, index: number): BenchTask {\n if (!isObject(raw)) throw new Error(`CRAG row ${index} must be an object`)\n const query = firstString(raw, ['query', 'question', 'prompt'])\n const goldAnswers = allStrings(raw, ['answer', 'answers', 'gold', 'gold_answer', 'expected_answer'])\n if (!query) throw new Error(`CRAG row ${index} missing query`)\n if (goldAnswers.length === 0) throw new Error(`CRAG row ${index} missing gold answer`)\n const domain = stringFrom(raw.domain) ?? 'unknown'\n const questionType = stringFrom(raw.question_type) ?? stringFrom(raw.questionType) ?? 'unknown'\n const dynamism = stringFrom(raw.static_or_dynamic) ?? stringFrom(raw.dynamism) ?? 'unknown'\n const id = stringFrom(raw.id) ?? stringFrom(raw.query_id) ?? `crag-${index}`\n const meta: CragMeta = {\n benchmark: 'crag',\n query,\n goldAnswers,\n domain,\n questionType,\n dynamism,\n }\n return {\n id,\n split: stringFrom(raw.split) ?? domain,\n prompt: [\n 'Answer this CRAG factual question.',\n 'Return a concise answer and do not guess when the evidence is insufficient.',\n 'End with a single final line: `FINAL ANSWER: <answer>`.',\n '',\n `Question: ${query}`,\n `Domain: ${domain}`,\n `Question type: ${questionType}`,\n `Dynamism: ${dynamism}`,\n ].join('\\n'),\n metadata: meta as unknown as Record<string, unknown>,\n }\n}\n\nfunction readMeta(task: BenchTask): CragMeta {\n const md = task.metadata\n if (!md || !Array.isArray(md.goldAnswers)) {\n throw new Error(`CRAG task ${task.id} missing metadata — loadTasks did not populate it`)\n }\n return md as unknown as CragMeta\n}\n\nasync function loadRows(path: string): Promise<unknown[]> {\n const rows = await readJsonRows(path)\n if (rows.length === 0) throw new Error(`CRAG: no rows in ${path}`)\n return rows\n}\n\nasync function loadFixtures(opts: LoadOptions): Promise<BenchTask[]> {\n const rows = JSON.parse(await readFile(FIXTURES, 'utf8')) as unknown[]\n console.warn(`[crag] CRAG_FIXTURES=1 — loading ${rows.length} adapter fixtures`)\n return selectTasks(rows.map(rowToTask), opts, 'CRAG')\n}\n\nexport function createCragAdapter(): BenchmarkAdapter {\n const fixturesMode = process.env.CRAG_FIXTURES === '1'\n\n return {\n name: 'crag',\n output: ragAnswerOutput,\n\n async preflight() {\n if (fixturesMode) {\n await readFile(FIXTURES, 'utf8')\n return\n }\n const path = dataFile()\n if (!path) {\n throw new Error(\n 'CRAG_DATA_FILE is required. Fix: export facebookresearch/CRAG rows to JSONL and set CRAG_DATA_FILE=/path/to/crag.jsonl, or set CRAG_FIXTURES=1 for adapter plumbing.',\n )\n }\n await loadRows(path)\n },\n\n async loadTasks(opts: LoadOptions = {}) {\n if (fixturesMode) return loadFixtures(opts)\n const path = dataFile()\n if (!path) throw new Error('CRAG_DATA_FILE is required to load CRAG tasks')\n return selectTasks((await loadRows(path)).map(rowToTask), opts, 'CRAG')\n },\n\n async goldArtifact(task: BenchTask) {\n return `${FINAL_ANSWER_SENTINEL} ${readMeta(task).goldAnswers[0] ?? ''}`\n },\n\n async judge(task: BenchTask, artifact: string): Promise<BenchScore> {\n const meta = readMeta(task)\n const score = scoreAnswerArtifact(artifact, meta.goldAnswers)\n return answerScoreToBenchScore(score, {\n benchmark: meta.benchmark,\n domain: meta.domain,\n questionType: meta.questionType,\n dynamism: meta.dynamism,\n })\n },\n }\n}\n"],"mappings":"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","names":[]}