@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,30 +0,0 @@
1
- import {
2
- createTauBenchAdapter,
3
- tauResultsOutput
4
- } from "./chunk-IZ5M6OAC.js";
5
- import {
6
- benchRoot
7
- } from "./chunk-WSKWVEQB.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-RCYQEFNX.js.map
@@ -1 +0,0 @@
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":[]}
@@ -1,182 +0,0 @@
1
- import {
2
- benchRoot,
3
- runVenvPython,
4
- runVenvScriptStdin
5
- } from "./chunk-WSKWVEQB.js";
6
-
7
- // src/benchmarks/dabstep.ts
8
- import { join } from "path";
9
- import { access, readFile, stat } from "fs/promises";
10
- var FIXTURES = join(benchRoot, "fixtures", "dabstep.json");
11
- var DEFAULT_SPLIT = "easy";
12
- var dabstepDir = () => process.env.DABSTEP_DIR;
13
- var gradeFile = (dir) => join(dir, "grade.py");
14
- var resourceRoot = (dir) => join(dir, "files");
15
- async function assertFile(path, label) {
16
- try {
17
- await access(path);
18
- } catch (err) {
19
- throw new Error(`DABStep: missing ${label} at ${path} (${err instanceof Error ? err.message : err})`);
20
- }
21
- }
22
- async function assertOfficialFiles(dir, split) {
23
- await assertFile(join(dir, "dataset.csv"), "released dataset.csv");
24
- await assertFile(join(dir, "splits", `${split}.txt`), `${split} split file`);
25
- await assertFile(gradeFile(dir), "official grade.py");
26
- const files = resourceRoot(dir);
27
- try {
28
- const s = await stat(files);
29
- if (!s.isDirectory()) throw new Error("not a directory");
30
- } catch (err) {
31
- throw new Error(`DABStep: missing benchmark files directory at ${files} (${err instanceof Error ? err.message : err})`);
32
- }
33
- }
34
- var dabstepAnswerOutput = {
35
- parse(events) {
36
- let text = "";
37
- for (const ev of events) {
38
- const d = ev?.data;
39
- const t = d?.finalText ?? d?.text ?? d?.result;
40
- if (typeof t === "string" && t.length > 0) text = t;
41
- }
42
- const fences = [...text.matchAll(/```(?:text|answer)?\s*\n([\s\S]*?)```/g)];
43
- return (fences.at(-1)?.[1] ?? text).trim();
44
- }
45
- };
46
- function rowToTask(row, split, dir) {
47
- const meta = {
48
- taskId: row.task_id,
49
- split,
50
- golds: row.all_golds_by_task,
51
- ...dir ? { resourceRoot: resourceRoot(dir) } : {}
52
- };
53
- return {
54
- id: String(row.task_id),
55
- split,
56
- prompt: [
57
- "Solve this DABStep data-analysis task using the mounted payment files.",
58
- "Use code or shell commands as needed, then return only the final answer.",
59
- "",
60
- row.instructions
61
- ].join("\n"),
62
- metadata: meta
63
- };
64
- }
65
- function readMeta(task) {
66
- const md = task.metadata;
67
- if (!md || typeof md.taskId !== "number" || !Array.isArray(md.golds)) {
68
- throw new Error(`dabstep task ${task.id} missing metadata \u2014 loadTasks did not populate it`);
69
- }
70
- return md;
71
- }
72
- function selectRows(rows, opts, split, dir) {
73
- let tasks = rows.map((row) => rowToTask(row, split, dir));
74
- if (opts.ids) {
75
- const want = new Set(opts.ids);
76
- tasks = tasks.filter((task) => want.has(task.id));
77
- } else if (opts.limit !== void 0) {
78
- tasks = tasks.slice(0, opts.limit);
79
- }
80
- if (tasks.length === 0) throw new Error(`DABStep: no tasks matched ${JSON.stringify(opts)} for split=${split}`);
81
- return tasks;
82
- }
83
- async function loadFixtures(opts, split) {
84
- const rows = JSON.parse(await readFile(FIXTURES, "utf8"));
85
- console.warn(`[dabstep] DABSTEP_FIXTURES=1 \u2014 loading ${rows.length} adapter fixtures from ${FIXTURES}`);
86
- return selectRows(rows, opts, split);
87
- }
88
- async function loadOfficialTasks(dir, opts, split) {
89
- const script = `
90
- import ast, csv, json, sys
91
- from pathlib import Path
92
-
93
- root = Path(sys.argv[1])
94
- split = sys.argv[2]
95
- limit = None if sys.argv[3] == "" else int(sys.argv[3])
96
- ids = set(json.loads(sys.argv[4]))
97
- dataset = root / "dataset.csv"
98
- split_file = root / "splits" / f"{split}.txt"
99
- if not dataset.exists():
100
- raise SystemExit(f"missing official DABStep dataset.csv at {dataset}")
101
- if not split_file.exists():
102
- raise SystemExit(f"missing official DABStep split file at {split_file}")
103
- split_ids = {int(line.strip()) for line in split_file.read_text().splitlines() if line.strip()}
104
- out = []
105
- with dataset.open(newline="") as f:
106
- for row in csv.DictReader(f):
107
- task_id = int(row["task_id"])
108
- if task_id not in split_ids:
109
- continue
110
- if ids and str(task_id) not in ids:
111
- continue
112
- out.append({
113
- "task_id": task_id,
114
- "instructions": f"{row['question']}\\n{row['guidelines']}",
115
- "all_golds_by_task": ast.literal_eval(str(row["all_golds_by_task"])),
116
- })
117
- if limit is not None and len(out) >= limit:
118
- break
119
- if not out:
120
- raise SystemExit(f"no DABStep rows matched split={split} ids={sorted(ids)} limit={limit}")
121
- print(json.dumps(out))
122
- `;
123
- const stdout = await runVenvPython(script, [dir, split, opts.limit === void 0 ? "" : String(opts.limit), JSON.stringify(opts.ids ?? [])]);
124
- return selectRows(JSON.parse(stdout), opts, split, dir);
125
- }
126
- function createDabstepAdapter() {
127
- const fixturesMode = process.env.DABSTEP_FIXTURES === "1";
128
- return {
129
- name: "dabstep",
130
- output: dabstepAnswerOutput,
131
- async preflight() {
132
- if (fixturesMode) return;
133
- const dir = dabstepDir();
134
- if (!dir) {
135
- throw new Error(
136
- "DABSTEP_DIR is required. Fix: clone https://github.com/EnvCommons/DABStep, add the released dataset.csv under that checkout, then set DABSTEP_DIR=/path/to/DABStep."
137
- );
138
- }
139
- await assertOfficialFiles(dir, DEFAULT_SPLIT);
140
- await loadOfficialTasks(dir, { limit: 1 }, DEFAULT_SPLIT);
141
- },
142
- async loadTasks(opts = {}) {
143
- const split = opts.split ?? DEFAULT_SPLIT;
144
- if (fixturesMode) return loadFixtures(opts, split);
145
- const dir = dabstepDir();
146
- if (!dir) throw new Error("DABSTEP_DIR is required to load official DABStep tasks");
147
- return loadOfficialTasks(dir, opts, split);
148
- },
149
- async goldArtifact(task) {
150
- const meta = readMeta(task);
151
- const first = meta.golds[0];
152
- if (!first) return void 0;
153
- const value = first.value;
154
- return value === void 0 ? void 0 : String(value);
155
- },
156
- async judge(task, artifact) {
157
- const meta = readMeta(task);
158
- const dir = dabstepDir();
159
- if (!dir) throw new Error("DABSTEP_DIR is required to judge DABStep tasks with the official grade.py");
160
- const stdout = await runVenvScriptStdin(
161
- join(benchRoot, "scripts", "dabstep_judge.py"),
162
- ["--grade-file", gradeFile(dir)],
163
- JSON.stringify({ prediction: artifact, golds: meta.golds }),
164
- { cwd: benchRoot }
165
- );
166
- const report = JSON.parse(stdout.trim().split("\n").at(-1) ?? "{}");
167
- if (report.error) throw new Error(`DABStep judge error for ${task.id}: ${report.error}`);
168
- const score = typeof report.score === "number" ? report.score : 0;
169
- return {
170
- resolved: report.correct === true,
171
- score,
172
- detail: JSON.stringify({ taskId: meta.taskId, split: meta.split, correct: report.correct })
173
- };
174
- }
175
- };
176
- }
177
-
178
- export {
179
- dabstepAnswerOutput,
180
- createDabstepAdapter
181
- };
182
- //# sourceMappingURL=chunk-RH5F53JT.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/benchmarks/dabstep.ts"],"sourcesContent":["/**\n * DABStep adapter (EnvCommons/DABStep) — data-analysis questions over synthetic\n * payment files. Worker artifact = final answer text. Judge = the official\n * DABStep `grade.py` normalization/matching function. No LLM judge.\n *\n * Live tasks require `DABSTEP_DIR` pointing at an official DABStep checkout that\n * includes `dataset.csv`, `splits/*.txt`, `files/*`, and `grade.py`. The adapter\n * exposes `metadata.resourceRoot` so runners can mount the benchmark files into\n * AgentProfile.resources.files; it does not paste the dataset into prompt text.\n */\n\nimport { join } from 'node:path'\nimport { access, readFile, stat } from 'node:fs/promises'\nimport type { OutputAdapter } from '@tangle-network/agent-runtime/loops'\nimport { benchRoot, runVenvPython, runVenvScriptStdin } from './_harness'\nimport type { BenchmarkAdapter, BenchScore, BenchTask, LoadOptions } from './types'\n\nconst FIXTURES = join(benchRoot, 'fixtures', 'dabstep.json')\nconst DEFAULT_SPLIT = 'easy'\n\ninterface DabstepFixtureRow {\n task_id: number\n instructions: string\n all_golds_by_task: Array<Record<string, unknown>>\n}\n\ninterface DabstepMeta {\n taskId: number\n split: string\n golds: Array<Record<string, unknown>>\n resourceRoot?: string\n}\n\nconst dabstepDir = (): string | undefined => process.env.DABSTEP_DIR\nconst gradeFile = (dir: string): string => join(dir, 'grade.py')\nconst resourceRoot = (dir: string): string => join(dir, 'files')\n\nasync function assertFile(path: string, label: string): Promise<void> {\n try {\n await access(path)\n } catch (err) {\n throw new Error(`DABStep: missing ${label} at ${path} (${err instanceof Error ? err.message : err})`)\n }\n}\n\nasync function assertOfficialFiles(dir: string, split: string): Promise<void> {\n await assertFile(join(dir, 'dataset.csv'), 'released dataset.csv')\n await assertFile(join(dir, 'splits', `${split}.txt`), `${split} split file`)\n await assertFile(gradeFile(dir), 'official grade.py')\n const files = resourceRoot(dir)\n try {\n const s = await stat(files)\n if (!s.isDirectory()) throw new Error('not a directory')\n } catch (err) {\n throw new Error(`DABStep: missing benchmark files directory at ${files} (${err instanceof Error ? err.message : err})`)\n }\n}\n\nexport const dabstepAnswerOutput: 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 rowToTask(row: DabstepFixtureRow, split: string, dir?: string): BenchTask {\n const meta: DabstepMeta = {\n taskId: row.task_id,\n split,\n golds: row.all_golds_by_task,\n ...(dir ? { resourceRoot: resourceRoot(dir) } : {}),\n }\n return {\n id: String(row.task_id),\n split,\n prompt: [\n 'Solve this DABStep data-analysis task using the mounted payment files.',\n 'Use code or shell commands as needed, then return only the final answer.',\n '',\n row.instructions,\n ].join('\\n'),\n metadata: meta as unknown as Record<string, unknown>,\n }\n}\n\nfunction readMeta(task: BenchTask): DabstepMeta {\n const md = task.metadata\n if (!md || typeof md.taskId !== 'number' || !Array.isArray(md.golds)) {\n throw new Error(`dabstep task ${task.id} missing metadata — loadTasks did not populate it`)\n }\n return md as unknown as DabstepMeta\n}\n\nfunction selectRows(rows: DabstepFixtureRow[], opts: LoadOptions, split: string, dir?: string): BenchTask[] {\n let tasks = rows.map((row) => rowToTask(row, split, dir))\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(`DABStep: no tasks matched ${JSON.stringify(opts)} for split=${split}`)\n return tasks\n}\n\nasync function loadFixtures(opts: LoadOptions, split: string): Promise<BenchTask[]> {\n const rows = JSON.parse(await readFile(FIXTURES, 'utf8')) as DabstepFixtureRow[]\n console.warn(`[dabstep] DABSTEP_FIXTURES=1 — loading ${rows.length} adapter fixtures from ${FIXTURES}`)\n return selectRows(rows, opts, split)\n}\n\nasync function loadOfficialTasks(dir: string, opts: LoadOptions, split: string): Promise<BenchTask[]> {\n const script = `\nimport ast, csv, json, sys\nfrom pathlib import Path\n\nroot = Path(sys.argv[1])\nsplit = sys.argv[2]\nlimit = None if sys.argv[3] == \"\" else int(sys.argv[3])\nids = set(json.loads(sys.argv[4]))\ndataset = root / \"dataset.csv\"\nsplit_file = root / \"splits\" / f\"{split}.txt\"\nif not dataset.exists():\n raise SystemExit(f\"missing official DABStep dataset.csv at {dataset}\")\nif not split_file.exists():\n raise SystemExit(f\"missing official DABStep split file at {split_file}\")\nsplit_ids = {int(line.strip()) for line in split_file.read_text().splitlines() if line.strip()}\nout = []\nwith dataset.open(newline=\"\") as f:\n for row in csv.DictReader(f):\n task_id = int(row[\"task_id\"])\n if task_id not in split_ids:\n continue\n if ids and str(task_id) not in ids:\n continue\n out.append({\n \"task_id\": task_id,\n \"instructions\": f\"{row['question']}\\\\n{row['guidelines']}\",\n \"all_golds_by_task\": ast.literal_eval(str(row[\"all_golds_by_task\"])),\n })\n if limit is not None and len(out) >= limit:\n break\nif not out:\n raise SystemExit(f\"no DABStep rows matched split={split} ids={sorted(ids)} limit={limit}\")\nprint(json.dumps(out))\n`\n const stdout = await runVenvPython(script, [dir, split, opts.limit === undefined ? '' : String(opts.limit), JSON.stringify(opts.ids ?? [])])\n return selectRows(JSON.parse(stdout) as DabstepFixtureRow[], opts, split, dir)\n}\n\nexport function createDabstepAdapter(): BenchmarkAdapter {\n const fixturesMode = process.env.DABSTEP_FIXTURES === '1'\n\n return {\n name: 'dabstep',\n output: dabstepAnswerOutput,\n\n async preflight() {\n if (fixturesMode) return\n const dir = dabstepDir()\n if (!dir) {\n throw new Error(\n 'DABSTEP_DIR is required. Fix: clone https://github.com/EnvCommons/DABStep, add the released dataset.csv under that checkout, then set DABSTEP_DIR=/path/to/DABStep.',\n )\n }\n await assertOfficialFiles(dir, DEFAULT_SPLIT)\n await loadOfficialTasks(dir, { limit: 1 }, DEFAULT_SPLIT)\n },\n\n async loadTasks(opts: LoadOptions = {}) {\n const split = opts.split ?? DEFAULT_SPLIT\n if (fixturesMode) return loadFixtures(opts, split)\n const dir = dabstepDir()\n if (!dir) throw new Error('DABSTEP_DIR is required to load official DABStep tasks')\n return loadOfficialTasks(dir, opts, split)\n },\n\n async goldArtifact(task: BenchTask) {\n const meta = readMeta(task)\n const first = meta.golds[0]\n if (!first) return undefined\n const value = first.value\n return value === undefined ? undefined : String(value)\n },\n\n async judge(task: BenchTask, artifact: string): Promise<BenchScore> {\n const meta = readMeta(task)\n const dir = dabstepDir()\n if (!dir) throw new Error('DABSTEP_DIR is required to judge DABStep tasks with the official grade.py')\n const stdout = await runVenvScriptStdin(\n join(benchRoot, 'scripts', 'dabstep_judge.py'),\n ['--grade-file', gradeFile(dir)],\n JSON.stringify({ prediction: artifact, golds: meta.golds }),\n { cwd: benchRoot },\n )\n const report = JSON.parse(stdout.trim().split('\\n').at(-1) ?? '{}') as { correct?: boolean; score?: number; error?: string }\n if (report.error) throw new Error(`DABStep judge error for ${task.id}: ${report.error}`)\n const score = typeof report.score === 'number' ? report.score : 0\n return {\n resolved: report.correct === true,\n score,\n detail: JSON.stringify({ taskId: meta.taskId, split: meta.split, correct: report.correct }),\n }\n },\n }\n}\n"],"mappings":"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","names":[]}
@@ -1,260 +0,0 @@
1
- // src/benchmarks/simpleqa.ts
2
- import { execFile } from "child_process";
3
- import { readFile } from "fs/promises";
4
- import { join } from "path";
5
- import { fileURLToPath } from "url";
6
- import { promisify } from "util";
7
- var execFileAsync = promisify(execFile);
8
- var BENCH_ROOT = fileURLToPath(new URL("../..", import.meta.url));
9
- var PY = join(BENCH_ROOT, ".venv", "bin", "python");
10
- var FIXTURES = join(BENCH_ROOT, "fixtures", "simpleqa.json");
11
- var DATASET_URL = "https://openaipublic.blob.core.windows.net/simple-evals/simple_qa_test_set.csv";
12
- var FINAL_ANSWER_SENTINEL = "FINAL ANSWER:";
13
- var WORKER_CONTRACT = [
14
- "",
15
- "Research the question using live web sources and answer it with a short, specific factual value.",
16
- "Cite the sources you used as full URLs, one per line, in a `CITATIONS:` block.",
17
- `End your response with a single final line: \`${FINAL_ANSWER_SENTINEL} <answer>\``,
18
- "The answer after the sentinel must be the bare value only (no explanation on that line).",
19
- "If you do not know the answer, state that you do not know rather than guessing."
20
- ].join("\n");
21
- async function py(script, args = []) {
22
- const { stdout } = await execFileAsync(PY, ["-c", script, ...args], {
23
- maxBuffer: 1024 * 1024 * 256
24
- });
25
- return stdout;
26
- }
27
- function parseFinalAnswer(artifact) {
28
- const lines = artifact.split(/\r?\n/);
29
- for (let i = lines.length - 1; i >= 0; i -= 1) {
30
- const line = lines[i] ?? "";
31
- const idx = line.toUpperCase().indexOf(FINAL_ANSWER_SENTINEL);
32
- if (idx !== -1) return line.slice(idx + FINAL_ANSWER_SENTINEL.length).trim();
33
- }
34
- for (let i = lines.length - 1; i >= 0; i -= 1) {
35
- const t = (lines[i] ?? "").trim();
36
- if (t.length > 0) return t;
37
- }
38
- return "";
39
- }
40
- function parseCitations(artifact) {
41
- const urls = /* @__PURE__ */ new Set();
42
- for (const m of artifact.matchAll(/https?:\/\/[^\s)<>"']+/g)) {
43
- urls.add(m[0].replace(/[.,;]+$/, ""));
44
- }
45
- return [...urls];
46
- }
47
- var GRADER_PROMPT = (question, gold, predicted) => [
48
- "Your job is to grade a predicted answer to a factual question against the single gold target answer.",
49
- "Grade the prediction into exactly one of three categories: CORRECT, INCORRECT, or NOT_ATTEMPTED.",
50
- "First, follow these grading rules carefully.",
51
- "",
52
- "CORRECT:",
53
- " The predicted answer fully contains the gold target without contradicting it.",
54
- " Predictions with more detail than the gold are still CORRECT, as long as no part contradicts the gold.",
55
- ' Hedging that still commits to the gold value (e.g. "I think it is X" where X is the gold) is CORRECT.',
56
- " Minor formatting, capitalization, ordering, or obvious-typo differences do not matter.",
57
- " For numeric/date targets, the prediction is CORRECT only if it matches the gold to the precision the gold specifies.",
58
- "",
59
- "INCORRECT:",
60
- " The predicted answer contradicts the gold target in any way, even if the contradiction is hedged.",
61
- " A prediction that states a different factual value than the gold is INCORRECT.",
62
- "",
63
- "NOT_ATTEMPTED:",
64
- " The gold target is neither fully given nor contradicted: the prediction declines to answer, says it does not know,",
65
- " asks for clarification, or gives a non-committal, vague, or empty response that commits to no specific value.",
66
- "",
67
- "Also note the following rules:",
68
- " Do not punish a prediction for omitting information that would not change whether the gold target is contained.",
69
- " Grade ONLY whether the gold value is present and uncontradicted \u2014 not the overall quality of the response.",
70
- "",
71
- `Question: ${question}`,
72
- `Gold target: ${gold}`,
73
- `Predicted answer: ${predicted}`,
74
- "",
75
- "Respond with ONLY a fenced JSON block and nothing else:",
76
- "```json",
77
- '{"grade": "CORRECT" | "INCORRECT" | "NOT_ATTEMPTED"}',
78
- "```"
79
- ].join("\n");
80
- function graderRouter() {
81
- const key = process.env.TANGLE_API_KEY;
82
- if (!key) throw new Error("TANGLE_API_KEY is required for the SimpleQA grader (set the Tangle API key)");
83
- const model = process.env.JUDGE_MODEL ?? "deepseek-v4-flash";
84
- const baseUrl = process.env.ROUTER_BASE ?? "https://router.tangle.tools/v1";
85
- return { baseUrl, key, model };
86
- }
87
- async function gradeAnswer(question, gold, predicted, router) {
88
- const res = await fetch(`${router.baseUrl}/chat/completions`, {
89
- method: "POST",
90
- headers: { "content-type": "application/json", authorization: `Bearer ${router.key}` },
91
- body: JSON.stringify({
92
- model: router.model,
93
- temperature: 0,
94
- messages: [{ role: "user", content: GRADER_PROMPT(question, gold, predicted) }]
95
- })
96
- });
97
- if (!res.ok) {
98
- throw new Error(`SimpleQA grader HTTP ${res.status}: ${(await res.text()).slice(0, 300)}`);
99
- }
100
- const body = await res.json();
101
- const content = body.choices?.[0]?.message?.content;
102
- if (typeof content !== "string") {
103
- throw new Error(`SimpleQA grader returned no message content: ${JSON.stringify(body).slice(0, 300)}`);
104
- }
105
- const fenced = content.match(/```(?:json)?\s*([\s\S]*?)```/);
106
- const raw = (fenced ? fenced[1] : content)?.trim() ?? "";
107
- let parsed;
108
- try {
109
- parsed = JSON.parse(raw);
110
- } catch {
111
- throw new Error(`SimpleQA grader produced unparseable output (no JSON grade): ${content.slice(0, 300)}`);
112
- }
113
- if (parsed.grade === "CORRECT" || parsed.grade === "INCORRECT" || parsed.grade === "NOT_ATTEMPTED") {
114
- return parsed.grade;
115
- }
116
- throw new Error(
117
- `SimpleQA grader grade not in {CORRECT,INCORRECT,NOT_ATTEMPTED}: ${JSON.stringify(parsed).slice(0, 200)}`
118
- );
119
- }
120
- function rowToTask(row, index) {
121
- const meta = {
122
- gold: row.answer,
123
- goldSources: row.urls,
124
- topic: row.topic,
125
- answerType: row.answer_type,
126
- question: row.problem
127
- };
128
- return {
129
- id: `simpleqa-${index}`,
130
- split: "test",
131
- prompt: row.problem + WORKER_CONTRACT,
132
- metadata: meta
133
- };
134
- }
135
- function readMeta(task) {
136
- const md = task.metadata;
137
- if (!md || typeof md.gold !== "string" || typeof md.question !== "string") {
138
- throw new Error(`SimpleQA task ${task.id} missing metadata.gold/question \u2014 loadTasks did not populate it`);
139
- }
140
- return md;
141
- }
142
- function selectTasks(tasks, opts) {
143
- if (opts.ids) {
144
- const want = new Set(opts.ids);
145
- return tasks.filter((t) => want.has(t.id));
146
- }
147
- if (opts.limit !== void 0) return tasks.slice(0, opts.limit);
148
- return tasks;
149
- }
150
- async function loadFixtures(opts) {
151
- const rows = JSON.parse(await readFile(FIXTURES, "utf8"));
152
- console.warn(`[simpleqa] SIMPLEQA_FIXTURES=1 \u2014 loading ${rows.length} committed fixtures (no network)`);
153
- return selectTasks(rows.map(rowToTask), opts);
154
- }
155
- async function loadLive(opts) {
156
- const script = `
157
- import csv, ast, json, io, sys
158
- from urllib.request import urlopen
159
- with urlopen(${JSON.stringify(DATASET_URL)}, timeout=120) as resp:
160
- text = resp.read().decode('utf-8')
161
- rows = list(csv.DictReader(io.StringIO(text)))
162
- out = []
163
- for r in rows:
164
- meta = ast.literal_eval(r['metadata']) if r.get('metadata') else {}
165
- out.append({
166
- 'problem': r.get('problem', ''),
167
- 'answer': r.get('answer', ''),
168
- 'topic': str(meta.get('topic', '')),
169
- 'answer_type': str(meta.get('answer_type', '')),
170
- 'urls': list(meta.get('urls', [])),
171
- })
172
- print(json.dumps(out))
173
- `;
174
- const stdout = await py(script);
175
- const rows = JSON.parse(stdout);
176
- return selectTasks(rows.map(rowToTask), opts);
177
- }
178
- function createSimpleQaAdapter() {
179
- const fixturesMode = process.env.SIMPLEQA_FIXTURES === "1";
180
- return {
181
- name: "simpleqa",
182
- async preflight() {
183
- graderRouter();
184
- if (fixturesMode) {
185
- await readFile(FIXTURES, "utf8").catch((err) => {
186
- throw new Error(
187
- `SIMPLEQA_FIXTURES=1 but ${FIXTURES} unreadable: ${err instanceof Error ? err.message : err}`
188
- );
189
- });
190
- return;
191
- }
192
- try {
193
- await py(
194
- `from urllib.request import urlopen
195
- with urlopen(${JSON.stringify(DATASET_URL)}, timeout=120) as resp:
196
- head = resp.read(64).decode('utf-8', 'replace')
197
- assert head.startswith('metadata,problem,answer'), 'unexpected CSV header: ' + head[:40]
198
- print('ok')`
199
- );
200
- } catch (err) {
201
- const msg = err instanceof Error ? err.message : String(err);
202
- throw new Error(
203
- `simpleqa preflight failed: ${msg}
204
- Fix: (1) ensure the bench venv exists (python3 -m venv bench/.venv) ; (2) ensure network access to ${DATASET_URL} ; or set SIMPLEQA_FIXTURES=1 to run against the committed fixtures offline.`
205
- );
206
- }
207
- },
208
- async loadTasks(opts = {}) {
209
- if (fixturesMode) return loadFixtures(opts);
210
- return loadLive(opts);
211
- },
212
- async goldArtifact(task) {
213
- const meta = readMeta(task);
214
- return `${FINAL_ANSWER_SENTINEL} ${meta.gold}`;
215
- },
216
- async judge(task, artifact) {
217
- const meta = readMeta(task);
218
- const finalAnswer = parseFinalAnswer(artifact);
219
- const citations = parseCitations(artifact);
220
- if (finalAnswer.length === 0) {
221
- return {
222
- resolved: false,
223
- score: 0,
224
- detail: JSON.stringify({
225
- grade: "NOT_ATTEMPTED",
226
- gradeLetter: "C",
227
- reason: "no parseable answer",
228
- gold: meta.gold,
229
- topic: meta.topic,
230
- answerType: meta.answerType,
231
- citationCount: citations.length
232
- })
233
- };
234
- }
235
- const grade = await gradeAnswer(meta.question, meta.gold, finalAnswer, graderRouter());
236
- const gradeLetter = grade === "CORRECT" ? "A" : grade === "INCORRECT" ? "B" : "C";
237
- const resolved = grade === "CORRECT";
238
- return {
239
- resolved,
240
- score: resolved ? 1 : 0,
241
- detail: JSON.stringify({
242
- grade,
243
- gradeLetter,
244
- gold: meta.gold,
245
- predicted: finalAnswer,
246
- topic: meta.topic,
247
- answerType: meta.answerType,
248
- citationCount: citations.length
249
- })
250
- };
251
- }
252
- };
253
- }
254
-
255
- export {
256
- parseFinalAnswer,
257
- parseCitations,
258
- createSimpleQaAdapter
259
- };
260
- //# sourceMappingURL=chunk-SEVJPLZC.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/benchmarks/simpleqa.ts"],"sourcesContent":["/**\n * SimpleQA adapter (OpenAI simple-evals; short-form factual QA). Worker artifact\n * = a single free-text final answer string (optionally preceded by a CITATIONS:\n * block). Each item ships a short gold `answer` plus metadata (topic,\n * answer_type, source urls).\n *\n * Judge is the official SimpleQA grader — an LLM classifier that maps\n * (question, gold target, predicted answer) to exactly one of:\n * A = CORRECT — fully contains the gold, no contradiction\n * B = INCORRECT — contradicts / contains a different factual value\n * C = NOT_ATTEMPTED — hedged, non-committal, or no value given\n * resolved = (grade == CORRECT). score = 1 for CORRECT else 0. The grade letter\n * (with its label) rides in `detail`; NOT_ATTEMPTED is surfaced distinctly from\n * INCORRECT so the scorecard can separate abstention from error.\n *\n * There is no deterministic tier: SimpleQA's rubric (containment + abstention)\n * is the grader's job by design, so judge() always calls the pinned grader model\n * (temperature 0) and fails loud on unparseable grader output. The final-answer\n * extraction IS deterministic (FINAL ANSWER: sentinel, fail-closed to '').\n *\n * Requires for a live run: the bench `.venv` with `datasets`/`requests` not\n * needed — the test set is a single public CSV fetched over HTTP — plus a\n * grader key (TANGLE_API_KEY). For offline/CI verification set\n * SIMPLEQA_FIXTURES=1 to load the committed fixtures\n * (bench/fixtures/simpleqa.json) — no network.\n */\n\nimport { execFile } from 'node:child_process'\nimport { readFile } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { promisify } from 'node:util'\nimport type { BenchmarkAdapter, BenchScore, BenchTask, LoadOptions } from './types'\n\nconst execFileAsync = promisify(execFile)\nconst BENCH_ROOT = fileURLToPath(new URL('../..', import.meta.url))\nconst PY = join(BENCH_ROOT, '.venv', 'bin', 'python')\nconst FIXTURES = join(BENCH_ROOT, 'fixtures', 'simpleqa.json')\n\nconst DATASET_URL =\n 'https://openaipublic.blob.core.windows.net/simple-evals/simple_qa_test_set.csv'\nconst FINAL_ANSWER_SENTINEL = 'FINAL ANSWER:'\n\n/** Worker contract appended to every task prompt. Answer extraction keys off the sentinel. */\nconst WORKER_CONTRACT = [\n '',\n 'Research the question using live web sources and answer it with a short, specific factual value.',\n 'Cite the sources you used as full URLs, one per line, in a `CITATIONS:` block.',\n `End your response with a single final line: \\`${FINAL_ANSWER_SENTINEL} <answer>\\``,\n 'The answer after the sentinel must be the bare value only (no explanation on that line).',\n 'If you do not know the answer, state that you do not know rather than guessing.',\n].join('\\n')\n\n/**\n * Typed seam for the research worker. The benchmark adapter scores a plain\n * `string` artifact (the BenchmarkAdapter contract); the loop worker decodes its\n * agent runs into a {@link ResearchAnswer} and serializes `finalAnswer` (+ an\n * optional `CITATIONS:` block) into that string before judging.\n */\nexport interface ResearchTask {\n id: string\n question: string\n /** Gold short answer — the grader's target. */\n gold: string\n /** Source URLs cited by the dataset for this item — SOFT provenance signal, never a hard gate. */\n goldSources: string[]\n /** SimpleQA topic, e.g. 'Politics' — slices the scorecard by domain. */\n topic: string\n /** SimpleQA answer_type, e.g. 'Person' | 'Date' | 'Number' | 'Place'. */\n answerType: string\n}\n\nexport interface ResearchAnswer {\n finalAnswer: string\n citations: string[]\n}\n\n/** Normalized fixture/loader row — the single shape both the CSV loader and fixtures emit. */\ninterface SimpleQaRow {\n problem: string\n answer: string\n topic: string\n answer_type: string\n urls: string[]\n}\n\ninterface SimpleQaMeta {\n gold: string\n goldSources: string[]\n topic: string\n answerType: string\n question: string\n}\n\n/** The three official SimpleQA grades. */\ntype Grade = 'CORRECT' | 'INCORRECT' | 'NOT_ATTEMPTED'\n\n/** Run the bench venv python with a script; return stdout (throws on nonzero). */\nasync function py(script: string, args: string[] = []): Promise<string> {\n const { stdout } = await execFileAsync(PY, ['-c', script, ...args], {\n maxBuffer: 1024 * 1024 * 256,\n })\n return stdout\n}\n\n/**\n * Parse the worker artifact into the final answer string.\n * Order: the `FINAL ANSWER:` sentinel first (deterministic-extraction discipline);\n * fall back to the last non-empty line. Returns '' when nothing is parseable\n * (fail-closed — never guess); judge() grades '' as NOT_ATTEMPTED.\n */\nexport function parseFinalAnswer(artifact: string): string {\n const lines = artifact.split(/\\r?\\n/)\n for (let i = lines.length - 1; i >= 0; i -= 1) {\n const line = lines[i] ?? ''\n const idx = line.toUpperCase().indexOf(FINAL_ANSWER_SENTINEL)\n if (idx !== -1) return line.slice(idx + FINAL_ANSWER_SENTINEL.length).trim()\n }\n for (let i = lines.length - 1; i >= 0; i -= 1) {\n const t = (lines[i] ?? '').trim()\n if (t.length > 0) return t\n }\n return ''\n}\n\n/** Extract every bare URL in the artifact (CITATIONS: block + inline). SOFT provenance signal. */\nexport function parseCitations(artifact: string): string[] {\n const urls = new Set<string>()\n for (const m of artifact.matchAll(/https?:\\/\\/[^\\s)<>\"']+/g)) {\n urls.add(m[0].replace(/[.,;]+$/, ''))\n }\n return [...urls]\n}\n\n/**\n * The official SimpleQA grader prompt (faithful paraphrase of OpenAI's\n * simple-evals GRADER_TEMPLATE). Classifies the predicted answer against the\n * gold target into A=CORRECT / B=INCORRECT / C=NOT_ATTEMPTED. The predicted\n * answer must fully contain the gold value with no contradicting statement;\n * hedged or non-committal answers are NOT_ATTEMPTED.\n */\nconst GRADER_PROMPT = (question: string, gold: string, predicted: string): string =>\n [\n 'Your job is to grade a predicted answer to a factual question against the single gold target answer.',\n 'Grade the prediction into exactly one of three categories: CORRECT, INCORRECT, or NOT_ATTEMPTED.',\n 'First, follow these grading rules carefully.',\n '',\n 'CORRECT:',\n ' The predicted answer fully contains the gold target without contradicting it.',\n ' Predictions with more detail than the gold are still CORRECT, as long as no part contradicts the gold.',\n ' Hedging that still commits to the gold value (e.g. \"I think it is X\" where X is the gold) is CORRECT.',\n ' Minor formatting, capitalization, ordering, or obvious-typo differences do not matter.',\n ' For numeric/date targets, the prediction is CORRECT only if it matches the gold to the precision the gold specifies.',\n '',\n 'INCORRECT:',\n ' The predicted answer contradicts the gold target in any way, even if the contradiction is hedged.',\n ' A prediction that states a different factual value than the gold is INCORRECT.',\n '',\n 'NOT_ATTEMPTED:',\n ' The gold target is neither fully given nor contradicted: the prediction declines to answer, says it does not know,',\n ' asks for clarification, or gives a non-committal, vague, or empty response that commits to no specific value.',\n '',\n 'Also note the following rules:',\n ' Do not punish a prediction for omitting information that would not change whether the gold target is contained.',\n ' Grade ONLY whether the gold value is present and uncontradicted — not the overall quality of the response.',\n '',\n `Question: ${question}`,\n `Gold target: ${gold}`,\n `Predicted answer: ${predicted}`,\n '',\n 'Respond with ONLY a fenced JSON block and nothing else:',\n '```json',\n '{\"grade\": \"CORRECT\" | \"INCORRECT\" | \"NOT_ATTEMPTED\"}',\n '```',\n ].join('\\n')\n\ninterface GraderRouter {\n baseUrl: string\n key: string\n model: string\n}\n\nfunction graderRouter(): GraderRouter {\n const key = process.env.TANGLE_API_KEY\n if (!key) throw new Error('TANGLE_API_KEY is required for the SimpleQA grader (set the Tangle API key)')\n const model = process.env.JUDGE_MODEL ?? 'deepseek-v4-flash'\n const baseUrl = process.env.ROUTER_BASE ?? 'https://router.tangle.tools/v1'\n return { baseUrl, key, model }\n}\n\n/** Call the official grader. Pinned model, temperature 0; fail loud on unparseable output. */\nasync function gradeAnswer(\n question: string,\n gold: string,\n predicted: string,\n router: GraderRouter,\n): Promise<Grade> {\n const res = await fetch(`${router.baseUrl}/chat/completions`, {\n method: 'POST',\n headers: { 'content-type': 'application/json', authorization: `Bearer ${router.key}` },\n body: JSON.stringify({\n model: router.model,\n temperature: 0,\n messages: [{ role: 'user', content: GRADER_PROMPT(question, gold, predicted) }],\n }),\n })\n if (!res.ok) {\n throw new Error(`SimpleQA grader HTTP ${res.status}: ${(await res.text()).slice(0, 300)}`)\n }\n const body = (await res.json()) as { choices?: Array<{ message?: { content?: string } }> }\n const content = body.choices?.[0]?.message?.content\n if (typeof content !== 'string') {\n throw new Error(`SimpleQA grader returned no message content: ${JSON.stringify(body).slice(0, 300)}`)\n }\n const fenced = content.match(/```(?:json)?\\s*([\\s\\S]*?)```/)\n const raw = (fenced ? fenced[1] : content)?.trim() ?? ''\n let parsed: { grade?: unknown }\n try {\n parsed = JSON.parse(raw) as { grade?: unknown }\n } catch {\n throw new Error(`SimpleQA grader produced unparseable output (no JSON grade): ${content.slice(0, 300)}`)\n }\n if (parsed.grade === 'CORRECT' || parsed.grade === 'INCORRECT' || parsed.grade === 'NOT_ATTEMPTED') {\n return parsed.grade\n }\n throw new Error(\n `SimpleQA grader grade not in {CORRECT,INCORRECT,NOT_ATTEMPTED}: ${JSON.stringify(parsed).slice(0, 200)}`,\n )\n}\n\nfunction rowToTask(row: SimpleQaRow, index: number): BenchTask {\n const meta: SimpleQaMeta = {\n gold: row.answer,\n goldSources: row.urls,\n topic: row.topic,\n answerType: row.answer_type,\n question: row.problem,\n }\n return {\n id: `simpleqa-${index}`,\n split: 'test',\n prompt: row.problem + WORKER_CONTRACT,\n metadata: meta as unknown as Record<string, unknown>,\n }\n}\n\nfunction readMeta(task: BenchTask): SimpleQaMeta {\n const md = task.metadata\n if (!md || typeof md.gold !== 'string' || typeof md.question !== 'string') {\n throw new Error(`SimpleQA task ${task.id} missing metadata.gold/question — loadTasks did not populate it`)\n }\n return md as unknown as SimpleQaMeta\n}\n\nfunction selectTasks(tasks: BenchTask[], opts: LoadOptions): BenchTask[] {\n if (opts.ids) {\n const want = new Set(opts.ids)\n return tasks.filter((t) => want.has(t.id))\n }\n if (opts.limit !== undefined) return tasks.slice(0, opts.limit)\n return tasks\n}\n\nasync function loadFixtures(opts: LoadOptions): Promise<BenchTask[]> {\n const rows = JSON.parse(await readFile(FIXTURES, 'utf8')) as SimpleQaRow[]\n console.warn(`[simpleqa] SIMPLEQA_FIXTURES=1 — loading ${rows.length} committed fixtures (no network)`)\n return selectTasks(rows.map(rowToTask), opts)\n}\n\n/**\n * Load the live test set: fetch the public CSV via the bench venv python, parse\n * with `csv` (handles quoted/embedded-comma fields) and `ast.literal_eval` for\n * the python-repr `metadata` dict. Emits the same normalized SimpleQaRow shape\n * the fixtures use, so loadTasks/judge share one parse path.\n */\nasync function loadLive(opts: LoadOptions): Promise<BenchTask[]> {\n const script = `\nimport csv, ast, json, io, sys\nfrom urllib.request import urlopen\nwith urlopen(${JSON.stringify(DATASET_URL)}, timeout=120) as resp:\n text = resp.read().decode('utf-8')\nrows = list(csv.DictReader(io.StringIO(text)))\nout = []\nfor r in rows:\n meta = ast.literal_eval(r['metadata']) if r.get('metadata') else {}\n out.append({\n 'problem': r.get('problem', ''),\n 'answer': r.get('answer', ''),\n 'topic': str(meta.get('topic', '')),\n 'answer_type': str(meta.get('answer_type', '')),\n 'urls': list(meta.get('urls', [])),\n })\nprint(json.dumps(out))\n`\n const stdout = await py(script)\n const rows = JSON.parse(stdout) as SimpleQaRow[]\n return selectTasks(rows.map(rowToTask), opts)\n}\n\nexport function createSimpleQaAdapter(): BenchmarkAdapter {\n const fixturesMode = process.env.SIMPLEQA_FIXTURES === '1'\n\n return {\n name: 'simpleqa',\n\n async preflight() {\n // The grader router must be configured in both modes — SimpleQA's score is\n // defined by the grader, so a run without it is meaningless.\n graderRouter()\n if (fixturesMode) {\n await readFile(FIXTURES, 'utf8').catch((err) => {\n throw new Error(\n `SIMPLEQA_FIXTURES=1 but ${FIXTURES} unreadable: ${err instanceof Error ? err.message : err}`,\n )\n })\n return\n }\n try {\n await py(\n `from urllib.request import urlopen\nwith urlopen(${JSON.stringify(DATASET_URL)}, timeout=120) as resp:\n head = resp.read(64).decode('utf-8', 'replace')\nassert head.startswith('metadata,problem,answer'), 'unexpected CSV header: ' + head[:40]\nprint('ok')`,\n )\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n throw new Error(\n `simpleqa preflight failed: ${msg}\\n` +\n `Fix: (1) ensure the bench venv exists (python3 -m venv bench/.venv) ; ` +\n `(2) ensure network access to ${DATASET_URL} ; ` +\n `or set SIMPLEQA_FIXTURES=1 to run against the committed fixtures offline.`,\n )\n }\n },\n\n async loadTasks(opts: LoadOptions = {}) {\n if (fixturesMode) return loadFixtures(opts)\n return loadLive(opts)\n },\n\n async goldArtifact(task: BenchTask) {\n // Gold artifact = the worker-contract serialization of the gold answer, so\n // verify-judge proves gold→CORRECT through the SAME parse path the real\n // artifact takes.\n const meta = readMeta(task)\n return `${FINAL_ANSWER_SENTINEL} ${meta.gold}`\n },\n\n async judge(task: BenchTask, artifact: string): Promise<BenchScore> {\n const meta = readMeta(task)\n const finalAnswer = parseFinalAnswer(artifact)\n const citations = parseCitations(artifact)\n\n if (finalAnswer.length === 0) {\n // No parseable value committed — NOT_ATTEMPTED by construction, no grader call.\n return {\n resolved: false,\n score: 0,\n detail: JSON.stringify({\n grade: 'NOT_ATTEMPTED',\n gradeLetter: 'C',\n reason: 'no parseable answer',\n gold: meta.gold,\n topic: meta.topic,\n answerType: meta.answerType,\n citationCount: citations.length,\n }),\n }\n }\n\n const grade = await gradeAnswer(meta.question, meta.gold, finalAnswer, graderRouter())\n const gradeLetter = grade === 'CORRECT' ? 'A' : grade === 'INCORRECT' ? 'B' : 'C'\n const resolved = grade === 'CORRECT'\n return {\n resolved,\n score: resolved ? 1 : 0,\n detail: JSON.stringify({\n grade,\n gradeLetter,\n gold: meta.gold,\n predicted: finalAnswer,\n topic: meta.topic,\n answerType: meta.answerType,\n citationCount: citations.length,\n }),\n }\n },\n }\n}\n"],"mappings":";AA2BA,SAAS,gBAAgB;AACzB,SAAS,gBAAgB;AACzB,SAAS,YAAY;AACrB,SAAS,qBAAqB;AAC9B,SAAS,iBAAiB;AAG1B,IAAM,gBAAgB,UAAU,QAAQ;AACxC,IAAM,aAAa,cAAc,IAAI,IAAI,SAAS,YAAY,GAAG,CAAC;AAClE,IAAM,KAAK,KAAK,YAAY,SAAS,OAAO,QAAQ;AACpD,IAAM,WAAW,KAAK,YAAY,YAAY,eAAe;AAE7D,IAAM,cACJ;AACF,IAAM,wBAAwB;AAG9B,IAAM,kBAAkB;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AAAA,EACA,iDAAiD,qBAAqB;AAAA,EACtE;AAAA,EACA;AACF,EAAE,KAAK,IAAI;AA+CX,eAAe,GAAG,QAAgB,OAAiB,CAAC,GAAoB;AACtE,QAAM,EAAE,OAAO,IAAI,MAAM,cAAc,IAAI,CAAC,MAAM,QAAQ,GAAG,IAAI,GAAG;AAAA,IAClE,WAAW,OAAO,OAAO;AAAA,EAC3B,CAAC;AACD,SAAO;AACT;AAQO,SAAS,iBAAiB,UAA0B;AACzD,QAAM,QAAQ,SAAS,MAAM,OAAO;AACpC,WAAS,IAAI,MAAM,SAAS,GAAG,KAAK,GAAG,KAAK,GAAG;AAC7C,UAAM,OAAO,MAAM,CAAC,KAAK;AACzB,UAAM,MAAM,KAAK,YAAY,EAAE,QAAQ,qBAAqB;AAC5D,QAAI,QAAQ,GAAI,QAAO,KAAK,MAAM,MAAM,sBAAsB,MAAM,EAAE,KAAK;AAAA,EAC7E;AACA,WAAS,IAAI,MAAM,SAAS,GAAG,KAAK,GAAG,KAAK,GAAG;AAC7C,UAAM,KAAK,MAAM,CAAC,KAAK,IAAI,KAAK;AAChC,QAAI,EAAE,SAAS,EAAG,QAAO;AAAA,EAC3B;AACA,SAAO;AACT;AAGO,SAAS,eAAe,UAA4B;AACzD,QAAM,OAAO,oBAAI,IAAY;AAC7B,aAAW,KAAK,SAAS,SAAS,yBAAyB,GAAG;AAC5D,SAAK,IAAI,EAAE,CAAC,EAAE,QAAQ,WAAW,EAAE,CAAC;AAAA,EACtC;AACA,SAAO,CAAC,GAAG,IAAI;AACjB;AASA,IAAM,gBAAgB,CAAC,UAAkB,MAAc,cACrD;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,aAAa,QAAQ;AAAA,EACrB,gBAAgB,IAAI;AAAA,EACpB,qBAAqB,SAAS;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,EAAE,KAAK,IAAI;AAQb,SAAS,eAA6B;AACpC,QAAM,MAAM,QAAQ,IAAI;AACxB,MAAI,CAAC,IAAK,OAAM,IAAI,MAAM,6EAA6E;AACvG,QAAM,QAAQ,QAAQ,IAAI,eAAe;AACzC,QAAM,UAAU,QAAQ,IAAI,eAAe;AAC3C,SAAO,EAAE,SAAS,KAAK,MAAM;AAC/B;AAGA,eAAe,YACb,UACA,MACA,WACA,QACgB;AAChB,QAAM,MAAM,MAAM,MAAM,GAAG,OAAO,OAAO,qBAAqB;AAAA,IAC5D,QAAQ;AAAA,IACR,SAAS,EAAE,gBAAgB,oBAAoB,eAAe,UAAU,OAAO,GAAG,GAAG;AAAA,IACrF,MAAM,KAAK,UAAU;AAAA,MACnB,OAAO,OAAO;AAAA,MACd,aAAa;AAAA,MACb,UAAU,CAAC,EAAE,MAAM,QAAQ,SAAS,cAAc,UAAU,MAAM,SAAS,EAAE,CAAC;AAAA,IAChF,CAAC;AAAA,EACH,CAAC;AACD,MAAI,CAAC,IAAI,IAAI;AACX,UAAM,IAAI,MAAM,wBAAwB,IAAI,MAAM,MAAM,MAAM,IAAI,KAAK,GAAG,MAAM,GAAG,GAAG,CAAC,EAAE;AAAA,EAC3F;AACA,QAAM,OAAQ,MAAM,IAAI,KAAK;AAC7B,QAAM,UAAU,KAAK,UAAU,CAAC,GAAG,SAAS;AAC5C,MAAI,OAAO,YAAY,UAAU;AAC/B,UAAM,IAAI,MAAM,gDAAgD,KAAK,UAAU,IAAI,EAAE,MAAM,GAAG,GAAG,CAAC,EAAE;AAAA,EACtG;AACA,QAAM,SAAS,QAAQ,MAAM,8BAA8B;AAC3D,QAAM,OAAO,SAAS,OAAO,CAAC,IAAI,UAAU,KAAK,KAAK;AACtD,MAAI;AACJ,MAAI;AACF,aAAS,KAAK,MAAM,GAAG;AAAA,EACzB,QAAQ;AACN,UAAM,IAAI,MAAM,gEAAgE,QAAQ,MAAM,GAAG,GAAG,CAAC,EAAE;AAAA,EACzG;AACA,MAAI,OAAO,UAAU,aAAa,OAAO,UAAU,eAAe,OAAO,UAAU,iBAAiB;AAClG,WAAO,OAAO;AAAA,EAChB;AACA,QAAM,IAAI;AAAA,IACR,mEAAmE,KAAK,UAAU,MAAM,EAAE,MAAM,GAAG,GAAG,CAAC;AAAA,EACzG;AACF;AAEA,SAAS,UAAU,KAAkB,OAA0B;AAC7D,QAAM,OAAqB;AAAA,IACzB,MAAM,IAAI;AAAA,IACV,aAAa,IAAI;AAAA,IACjB,OAAO,IAAI;AAAA,IACX,YAAY,IAAI;AAAA,IAChB,UAAU,IAAI;AAAA,EAChB;AACA,SAAO;AAAA,IACL,IAAI,YAAY,KAAK;AAAA,IACrB,OAAO;AAAA,IACP,QAAQ,IAAI,UAAU;AAAA,IACtB,UAAU;AAAA,EACZ;AACF;AAEA,SAAS,SAAS,MAA+B;AAC/C,QAAM,KAAK,KAAK;AAChB,MAAI,CAAC,MAAM,OAAO,GAAG,SAAS,YAAY,OAAO,GAAG,aAAa,UAAU;AACzE,UAAM,IAAI,MAAM,iBAAiB,KAAK,EAAE,sEAAiE;AAAA,EAC3G;AACA,SAAO;AACT;AAEA,SAAS,YAAY,OAAoB,MAAgC;AACvE,MAAI,KAAK,KAAK;AACZ,UAAM,OAAO,IAAI,IAAI,KAAK,GAAG;AAC7B,WAAO,MAAM,OAAO,CAAC,MAAM,KAAK,IAAI,EAAE,EAAE,CAAC;AAAA,EAC3C;AACA,MAAI,KAAK,UAAU,OAAW,QAAO,MAAM,MAAM,GAAG,KAAK,KAAK;AAC9D,SAAO;AACT;AAEA,eAAe,aAAa,MAAyC;AACnE,QAAM,OAAO,KAAK,MAAM,MAAM,SAAS,UAAU,MAAM,CAAC;AACxD,UAAQ,KAAK,iDAA4C,KAAK,MAAM,kCAAkC;AACtG,SAAO,YAAY,KAAK,IAAI,SAAS,GAAG,IAAI;AAC9C;AAQA,eAAe,SAAS,MAAyC;AAC/D,QAAM,SAAS;AAAA;AAAA;AAAA,eAGF,KAAK,UAAU,WAAW,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAexC,QAAM,SAAS,MAAM,GAAG,MAAM;AAC9B,QAAM,OAAO,KAAK,MAAM,MAAM;AAC9B,SAAO,YAAY,KAAK,IAAI,SAAS,GAAG,IAAI;AAC9C;AAEO,SAAS,wBAA0C;AACxD,QAAM,eAAe,QAAQ,IAAI,sBAAsB;AAEvD,SAAO;AAAA,IACL,MAAM;AAAA,IAEN,MAAM,YAAY;AAGhB,mBAAa;AACb,UAAI,cAAc;AAChB,cAAM,SAAS,UAAU,MAAM,EAAE,MAAM,CAAC,QAAQ;AAC9C,gBAAM,IAAI;AAAA,YACR,2BAA2B,QAAQ,gBAAgB,eAAe,QAAQ,IAAI,UAAU,GAAG;AAAA,UAC7F;AAAA,QACF,CAAC;AACD;AAAA,MACF;AACA,UAAI;AACF,cAAM;AAAA,UACJ;AAAA,eACK,KAAK,UAAU,WAAW,CAAC;AAAA;AAAA;AAAA;AAAA,QAIlC;AAAA,MACF,SAAS,KAAK;AACZ,cAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC3D,cAAM,IAAI;AAAA,UACR,8BAA8B,GAAG;AAAA,qGAEC,WAAW;AAAA,QAE/C;AAAA,MACF;AAAA,IACF;AAAA,IAEA,MAAM,UAAU,OAAoB,CAAC,GAAG;AACtC,UAAI,aAAc,QAAO,aAAa,IAAI;AAC1C,aAAO,SAAS,IAAI;AAAA,IACtB;AAAA,IAEA,MAAM,aAAa,MAAiB;AAIlC,YAAM,OAAO,SAAS,IAAI;AAC1B,aAAO,GAAG,qBAAqB,IAAI,KAAK,IAAI;AAAA,IAC9C;AAAA,IAEA,MAAM,MAAM,MAAiB,UAAuC;AAClE,YAAM,OAAO,SAAS,IAAI;AAC1B,YAAM,cAAc,iBAAiB,QAAQ;AAC7C,YAAM,YAAY,eAAe,QAAQ;AAEzC,UAAI,YAAY,WAAW,GAAG;AAE5B,eAAO;AAAA,UACL,UAAU;AAAA,UACV,OAAO;AAAA,UACP,QAAQ,KAAK,UAAU;AAAA,YACrB,OAAO;AAAA,YACP,aAAa;AAAA,YACb,QAAQ;AAAA,YACR,MAAM,KAAK;AAAA,YACX,OAAO,KAAK;AAAA,YACZ,YAAY,KAAK;AAAA,YACjB,eAAe,UAAU;AAAA,UAC3B,CAAC;AAAA,QACH;AAAA,MACF;AAEA,YAAM,QAAQ,MAAM,YAAY,KAAK,UAAU,KAAK,MAAM,aAAa,aAAa,CAAC;AACrF,YAAM,cAAc,UAAU,YAAY,MAAM,UAAU,cAAc,MAAM;AAC9E,YAAM,WAAW,UAAU;AAC3B,aAAO;AAAA,QACL;AAAA,QACA,OAAO,WAAW,IAAI;AAAA,QACtB,QAAQ,KAAK,UAAU;AAAA,UACrB;AAAA,UACA;AAAA,UACA,MAAM,KAAK;AAAA,UACX,WAAW;AAAA,UACX,OAAO,KAAK;AAAA,UACZ,YAAY,KAAK;AAAA,UACjB,eAAe,UAAU;AAAA,QAC3B,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AACF;","names":[]}
@@ -1,27 +0,0 @@
1
- import {
2
- createTauBenchAdapter
3
- } from "./chunk-IZ5M6OAC.js";
4
- import {
5
- benchRoot
6
- } from "./chunk-WSKWVEQB.js";
7
-
8
- // src/benchmarks/tau3-banking.ts
9
- import { join } from "path";
10
- var FIXTURES = join(benchRoot, "fixtures", "tau3-banking.json");
11
- function createTau3BankingAdapter() {
12
- return createTauBenchAdapter({
13
- name: "tau3-banking",
14
- fixturePath: FIXTURES,
15
- fixturesEnv: "TAU3_FIXTURES",
16
- dirEnv: "TAU3_BENCH_DIR",
17
- domainEnv: "TAU3_DOMAIN",
18
- defaultDomain: "banking_knowledge",
19
- taskIntro: "Run this tau3 banking task in the official tau3 knowledge benchmark.",
20
- installHint: "clone https://github.com/sierra-research/tau2-bench, run `uv sync --extra knowledge`, install/import it from bench/.venv, and set TAU3_BENCH_DIR=/path/to/tau2-bench."
21
- });
22
- }
23
-
24
- export {
25
- createTau3BankingAdapter
26
- };
27
- //# sourceMappingURL=chunk-SFLA7OH3.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/benchmarks/tau3-banking.ts"],"sourcesContent":["/**\n * tau3-banking adapter.\n *\n * The current upstream tau3 release is the `sierra-research/tau2-bench` repo with\n * package namespace `tau2` and a new `banking_knowledge` domain. This adapter\n * reuses the shared tau reward recomputation path and only changes the default\n * domain/env names.\n */\n\nimport { join } from 'node:path'\nimport { benchRoot } from './_harness'\nimport { createTauBenchAdapter } from './tau-bench-shared'\nimport type { BenchmarkAdapter } from './types'\n\nconst FIXTURES = join(benchRoot, 'fixtures', 'tau3-banking.json')\n\nexport function createTau3BankingAdapter(): BenchmarkAdapter {\n return createTauBenchAdapter({\n name: 'tau3-banking',\n fixturePath: FIXTURES,\n fixturesEnv: 'TAU3_FIXTURES',\n dirEnv: 'TAU3_BENCH_DIR',\n domainEnv: 'TAU3_DOMAIN',\n defaultDomain: 'banking_knowledge',\n taskIntro: 'Run this tau3 banking task in the official tau3 knowledge benchmark.',\n installHint:\n 'clone https://github.com/sierra-research/tau2-bench, run `uv sync --extra knowledge`, install/import it from bench/.venv, and set TAU3_BENCH_DIR=/path/to/tau2-bench.',\n })\n}\n"],"mappings":";;;;;;;;AASA,SAAS,YAAY;AAKrB,IAAM,WAAW,KAAK,WAAW,YAAY,mBAAmB;AAEzD,SAAS,2BAA6C;AAC3D,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":[]}