@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,317 +0,0 @@
1
- // src/benchmarks/_harness.ts
2
- import { execFile, spawn } from "child_process";
3
- import { createHash } from "crypto";
4
- import { existsSync, readFileSync } from "fs";
5
- import {
6
- cp,
7
- lstat,
8
- mkdir,
9
- mkdtemp,
10
- readFile,
11
- readlink,
12
- readdir,
13
- rename,
14
- rm,
15
- writeFile
16
- } from "fs/promises";
17
- import { tmpdir } from "os";
18
- import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "path";
19
- import { fileURLToPath } from "url";
20
- import { promisify } from "util";
21
- var execFileAsync = promisify(execFile);
22
- function resolveBenchRoot(moduleUrl) {
23
- let current = dirname(fileURLToPath(moduleUrl));
24
- while (true) {
25
- const manifestPath = join(current, "package.json");
26
- if (existsSync(manifestPath)) {
27
- const manifest = JSON.parse(readFileSync(manifestPath, "utf8"));
28
- if (manifest.name === "@tangle-network/agent-bench") return current;
29
- }
30
- const parent = dirname(current);
31
- if (parent === current) {
32
- throw new Error(`Unable to locate @tangle-network/agent-bench from ${moduleUrl}`);
33
- }
34
- current = parent;
35
- }
36
- }
37
- var benchRoot = resolveBenchRoot(import.meta.url);
38
- function resolveBenchPython(env = process.env, root = benchRoot) {
39
- const configured = env.AGENT_BENCH_PYTHON;
40
- if (configured === void 0) return join(root, ".venv", "bin", "python");
41
- if (!isAbsolute(configured)) {
42
- throw new Error("AGENT_BENCH_PYTHON must be an absolute path");
43
- }
44
- return configured;
45
- }
46
- var venvPython = resolveBenchPython();
47
- var venvPythonAt = (venvDir) => join(benchRoot, venvDir, "bin", "python");
48
- var bigBuffer = 1024 * 1024 * 256;
49
- function venvBin(name) {
50
- return join(benchRoot, ".venv", "bin", name);
51
- }
52
- async function runVenvPython(script, args = [], timeoutMs = 0, python = venvPython) {
53
- const { stdout } = await execFileAsync(python, ["-c", script, ...args], {
54
- maxBuffer: bigBuffer,
55
- timeout: timeoutMs
56
- });
57
- return stdout;
58
- }
59
- async function preflightVenvImports(opts) {
60
- const imports = opts.modules.filter((m) => m.length > 0);
61
- const lines = [...imports.map((m) => `import ${m}`)];
62
- if (opts.requireDocker) lines.push("import docker", "docker.from_env().ping()");
63
- lines.push("print('ok')");
64
- try {
65
- await runVenvPython(lines.join("\n"), [], 0, opts.python ?? venvPython);
66
- } catch (err) {
67
- const msg = err instanceof Error ? err.message : String(err);
68
- throw new Error(`${msg}
69
- ${opts.fix}`);
70
- }
71
- }
72
- function runVenvScriptStdin(scriptPath, args, input, opts = {}) {
73
- return new Promise((resolve2, reject) => {
74
- const child = spawn(opts.python ?? venvPython, [scriptPath, ...args], {
75
- cwd: opts.cwd ?? benchRoot,
76
- ...opts.timeoutMs ? { timeout: opts.timeoutMs } : {}
77
- });
78
- let stdout = "";
79
- let stderr = "";
80
- let bytes = 0;
81
- child.stdout.on("data", (c) => {
82
- bytes += c.length;
83
- if (bytes <= bigBuffer) stdout += c.toString("utf8");
84
- });
85
- child.stderr.on("data", (c) => {
86
- stderr += c.toString("utf8");
87
- });
88
- child.on("error", (err) => reject(err));
89
- child.on("close", (code) => {
90
- if (code === 0) resolve2(stdout);
91
- else reject(new Error((stderr || stdout || `exit ${code}`).slice(0, 1500)));
92
- });
93
- child.stdin.end(input);
94
- });
95
- }
96
- var StagedJudgeError = class extends Error {
97
- judgeArtifacts;
98
- constructor(message, judgeArtifacts, options) {
99
- super(message, options);
100
- this.name = "StagedJudgeError";
101
- this.judgeArtifacts = judgeArtifacts;
102
- }
103
- };
104
- function sha256(bytes) {
105
- return `sha256:${createHash("sha256").update(bytes).digest("hex")}`;
106
- }
107
- function portablePath(path) {
108
- return path.split(sep).join("/");
109
- }
110
- function compareText(left, right) {
111
- return left < right ? -1 : left > right ? 1 : 0;
112
- }
113
- async function collectArtifactFiles(root, current) {
114
- const absolute = join(root, current);
115
- const entries = await readdir(absolute, { withFileTypes: true });
116
- const files = [];
117
- for (const entry of entries.sort((left, right) => compareText(left.name, right.name))) {
118
- const relativePath = join(current, entry.name);
119
- const path = join(root, relativePath);
120
- if (entry.isDirectory()) {
121
- files.push(...await collectArtifactFiles(root, relativePath));
122
- continue;
123
- }
124
- if (entry.isFile()) {
125
- const bytes = await readFile(path);
126
- files.push({
127
- path: portablePath(relativePath),
128
- byteLength: bytes.byteLength,
129
- sha256: sha256(bytes),
130
- kind: "file"
131
- });
132
- continue;
133
- }
134
- if (entry.isSymbolicLink()) {
135
- const targetBytes = await readlink(path, { encoding: "buffer" });
136
- files.push({
137
- path: portablePath(relativePath),
138
- byteLength: targetBytes.byteLength,
139
- sha256: sha256(targetBytes),
140
- kind: "symlink"
141
- });
142
- continue;
143
- }
144
- throw new Error(`staged judge capture does not support ${relativePath}`);
145
- }
146
- return files;
147
- }
148
- function isWithin(parent, candidate) {
149
- const path = relative(parent, candidate);
150
- return path === "" || !path.startsWith(`..${sep}`) && path !== ".." && !isAbsolute(path);
151
- }
152
- async function assertDestinationAbsent(destination) {
153
- try {
154
- await lstat(destination);
155
- } catch (error) {
156
- if (error.code === "ENOENT") return;
157
- throw error;
158
- }
159
- throw new Error(`staged judge capture destination already exists: ${destination}`);
160
- }
161
- async function captureStagedRun(sourceDirectory, spec, processOutput, evaluatorSucceeded) {
162
- const source = resolve(sourceDirectory);
163
- const destination = resolve(spec.destination);
164
- if (isWithin(source, destination)) {
165
- throw new Error("staged judge capture destination must be outside the evaluator directory");
166
- }
167
- await mkdir(dirname(destination), { recursive: true });
168
- await assertDestinationAbsent(destination);
169
- const staging = await mkdtemp(join(dirname(destination), `.${basename(destination)}-capture-`));
170
- try {
171
- await cp(source, join(staging, "evaluator"), {
172
- recursive: true,
173
- errorOnExist: true,
174
- force: false,
175
- preserveTimestamps: true,
176
- verbatimSymlinks: true
177
- });
178
- await mkdir(join(staging, "process"));
179
- await writeFile(join(staging, "process", "stdout.bin"), processOutput.stdout);
180
- await writeFile(join(staging, "process", "stderr.bin"), processOutput.stderr);
181
- const files = [
182
- ...await collectArtifactFiles(staging, "evaluator"),
183
- ...await collectArtifactFiles(staging, "process")
184
- ].sort((left, right) => compareText(left.path, right.path));
185
- const byteLength = files.reduce((total, file) => total + file.byteLength, 0);
186
- const treeBytes = Buffer.from(
187
- files.map((file) => `${file.path}\0${file.kind}\0${file.byteLength}\0${file.sha256}
188
- `).join(""),
189
- "utf8"
190
- );
191
- const receipt = {
192
- schema: "agent-bench/judge-artifacts/v1",
193
- directory: destination,
194
- evaluatorDirectory: join(destination, "evaluator"),
195
- manifestPath: join(destination, "receipt.json"),
196
- evaluatorSucceeded,
197
- files,
198
- fileCount: files.length,
199
- byteLength,
200
- treeSha256: sha256(treeBytes)
201
- };
202
- await writeFile(join(staging, "receipt.json"), `${JSON.stringify(receipt, null, 2)}
203
- `);
204
- await rename(staging, destination);
205
- return receipt;
206
- } catch (error) {
207
- await rm(staging, { recursive: true, force: true }).catch(() => {
208
- });
209
- throw error;
210
- }
211
- }
212
- function processBytes(value) {
213
- if (Buffer.isBuffer(value)) return value;
214
- if (value === void 0 || value === null) return Buffer.alloc(0);
215
- return Buffer.from(String(value), "utf8");
216
- }
217
- async function runStagedJudge(spec) {
218
- const dir = await mkdtemp(join(tmpdir(), spec.tmpPrefix));
219
- let stdout = Buffer.alloc(0);
220
- let stderr = Buffer.alloc(0);
221
- let evaluatorSucceeded = false;
222
- let score;
223
- let failure;
224
- try {
225
- try {
226
- await spec.stage(dir);
227
- const bin = spec.bin ?? venvPython;
228
- const argv = spec.argv(dir);
229
- try {
230
- const output = await execFileAsync(bin, argv, {
231
- cwd: spec.cwd ? spec.cwd(dir) : dir,
232
- encoding: "buffer",
233
- maxBuffer: bigBuffer,
234
- ...spec.timeoutMs ? { timeout: spec.timeoutMs } : {}
235
- });
236
- stdout = processBytes(output.stdout);
237
- stderr = processBytes(output.stderr);
238
- evaluatorSucceeded = true;
239
- } catch (err) {
240
- const e = err;
241
- stdout = processBytes(e.stdout);
242
- stderr = processBytes(e.stderr);
243
- const detail = processBytes(e.stderr ?? e.stdout ?? e.message ?? String(err)).toString("utf8").slice(0, 2e3);
244
- throw new Error(`${spec.tmpPrefix.replace(/-$/, "")} evaluator failed (${bin} ${argv.join(" ")}):
245
- ${detail}`);
246
- }
247
- score = await spec.parseReport(dir);
248
- } catch (err) {
249
- failure = err;
250
- }
251
- } finally {
252
- let judgeArtifacts;
253
- if (spec.capture) {
254
- try {
255
- judgeArtifacts = await captureStagedRun(
256
- dir,
257
- spec.capture,
258
- { stdout, stderr },
259
- evaluatorSucceeded
260
- );
261
- } catch (captureError) {
262
- failure = new Error(
263
- `staged judge failed to capture evaluator artifacts: ${captureError instanceof Error ? captureError.message : captureError}`,
264
- { cause: failure ?? captureError }
265
- );
266
- }
267
- }
268
- if (!spec.keepTmp) await rm(dir, { recursive: true, force: true }).catch(() => {
269
- });
270
- if (failure) {
271
- throw new StagedJudgeError(
272
- failure instanceof Error ? failure.message : String(failure),
273
- judgeArtifacts,
274
- { cause: failure }
275
- );
276
- }
277
- if (!score) throw new StagedJudgeError("staged judge completed without a score", judgeArtifacts);
278
- return judgeArtifacts ? { ...score, judgeArtifacts } : score;
279
- }
280
- }
281
- async function readJsonReport(path) {
282
- let raw;
283
- try {
284
- raw = await readFile(path, "utf8");
285
- } catch (err) {
286
- throw new Error(`expected report not written: ${path} (${err instanceof Error ? err.message : err})`);
287
- }
288
- try {
289
- return JSON.parse(raw);
290
- } catch (err) {
291
- throw new Error(`report not valid JSON at ${path}: ${err instanceof Error ? err.message : err}`);
292
- }
293
- }
294
- async function stageFile(path, content) {
295
- await writeFile(path, content);
296
- }
297
- function safeRunId(prefix, id) {
298
- return `${prefix}-${id}`.replace(/[^a-zA-Z0-9_.-]/g, "_");
299
- }
300
-
301
- export {
302
- benchRoot,
303
- resolveBenchPython,
304
- venvPython,
305
- venvPythonAt,
306
- bigBuffer,
307
- venvBin,
308
- runVenvPython,
309
- preflightVenvImports,
310
- runVenvScriptStdin,
311
- StagedJudgeError,
312
- runStagedJudge,
313
- readJsonReport,
314
- stageFile,
315
- safeRunId
316
- };
317
- //# sourceMappingURL=chunk-WSKWVEQB.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/benchmarks/_harness.ts"],"sourcesContent":["/**\n * Shared code-bench harness. The \"stage the artifact → run the benchmark's own\n * evaluator in an external process (mkdtemp / execFile / .venv python / Docker)\n * → read its JSON report → { resolved, score }\" spine that swe-bench,\n * terminal-bench, commit0, programbench and aec-bench all need. Factored out so\n * the Docker/venv/report-reading logic lives in ONE place instead of being\n * copy-pasted per adapter.\n *\n * It owns NO benchmark policy: each adapter passes the argv for its evaluator\n * and a `parseReport` that maps that evaluator's report JSON → a BenchScore. The\n * harness owns process spawning, temp-dir lifecycle, large-buffer/timeout config\n * and fail-loud diagnostics.\n *\n * Fail-loud: an absent .venv / harness / Docker daemon THROWS from `preflight`\n * (the adapter passes the import line + the exact fix). A staged run that exits\n * nonzero throws with the captured stderr — never a fabricated score.\n */\n\nimport { execFile, spawn } from 'node:child_process'\nimport { createHash } from 'node:crypto'\nimport { existsSync, readFileSync } from 'node:fs'\nimport {\n cp,\n lstat,\n mkdir,\n mkdtemp,\n readFile,\n readlink,\n readdir,\n rename,\n rm,\n writeFile,\n} from 'node:fs/promises'\nimport { tmpdir } from 'node:os'\nimport { basename, dirname, isAbsolute, join, relative, resolve, sep } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { promisify } from 'node:util'\nimport type {\n BenchScore,\n JudgeArtifactFileReceipt,\n JudgeArtifactReceipt,\n} from './types'\n\nconst execFileAsync = promisify(execFile)\n\n/** Locate the package by identity because source files and compiled chunks have different depths. */\nfunction resolveBenchRoot(moduleUrl: string): string {\n let current = dirname(fileURLToPath(moduleUrl))\n while (true) {\n const manifestPath = join(current, 'package.json')\n if (existsSync(manifestPath)) {\n const manifest = JSON.parse(readFileSync(manifestPath, 'utf8')) as { name?: unknown }\n if (manifest.name === '@tangle-network/agent-bench') return current\n }\n const parent = dirname(current)\n if (parent === current) {\n throw new Error(`Unable to locate @tangle-network/agent-bench from ${moduleUrl}`)\n }\n current = parent\n }\n}\n\n/** Package root for agent-bench, so `.venv`, scripts, and fixtures resolve. */\nexport const benchRoot = resolveBenchRoot(import.meta.url)\n\n/** Resolve the shared interpreter without requiring an installed package to contain a venv. */\nexport function resolveBenchPython(\n env: Readonly<{ AGENT_BENCH_PYTHON?: string }> = process.env,\n root: string = benchRoot,\n): string {\n const configured = env.AGENT_BENCH_PYTHON\n if (configured === undefined) return join(root, '.venv', 'bin', 'python')\n if (!isAbsolute(configured)) {\n throw new Error('AGENT_BENCH_PYTHON must be an absolute path')\n }\n return configured\n}\n\n/** The shared interpreter every Python-backed evaluator runs through. */\nexport const venvPython = resolveBenchPython()\n\n/** Interpreter for a NAMED isolated venv (e.g. `.venv-commit0`). Benches whose pip\n * deps conflict with the shared `.venv` (commit0 downgrades pydantic/sqlalchemy)\n * get their own venv and pass its python explicitly — keeping the shared one clean. */\nexport const venvPythonAt = (venvDir: string): string => join(benchRoot, venvDir, 'bin', 'python')\n/** Report/transcript reads are large; 256 MiB matches the SWE harness budget. */\nexport const bigBuffer = 1024 * 1024 * 256\n\n/** Path to a named executable inside the bench venv (e.g. `venvBin('tb')`). */\nexport function venvBin(name: string): string {\n return join(benchRoot, '.venv', 'bin', name)\n}\n\n/**\n * Run the bench venv python with an inline script (`-c`); return stdout. Throws\n * (with stderr) on a nonzero exit — the loaders rely on this to fail loud rather\n * than parse a partial dump.\n */\nexport async function runVenvPython(\n script: string,\n args: string[] = [],\n timeoutMs = 0,\n python: string = venvPython,\n): Promise<string> {\n const { stdout } = await execFileAsync(python, ['-c', script, ...args], {\n maxBuffer: bigBuffer,\n timeout: timeoutMs,\n })\n return stdout\n}\n\n/**\n * Preflight a python-backed harness: import the module(s) and (optionally) ping\n * Docker, all inside the bench venv. On failure THROWS the captured error joined\n * to the adapter's `fix` guidance — the contract every code-bench preflight wants.\n */\nexport async function preflightVenvImports(opts: {\n /** Module names to `import` (e.g. ['swebench']); '' entries are ignored. */\n modules: string[]\n /** Also `docker.from_env().ping()` — true for Docker-backed evaluators. */\n requireDocker?: boolean\n /** Actionable remediation appended to the thrown message. */\n fix: string\n /** Override the interpreter (e.g. an isolated `.venv-commit0`). Default: shared `.venv`. */\n python?: string\n}): Promise<void> {\n const imports = opts.modules.filter((m) => m.length > 0)\n const lines = [...imports.map((m) => `import ${m}`)]\n if (opts.requireDocker) lines.push('import docker', 'docker.from_env().ping()')\n lines.push(\"print('ok')\")\n try {\n await runVenvPython(lines.join('\\n'), [], 0, opts.python ?? venvPython)\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n throw new Error(`${msg}\\n${opts.fix}`)\n }\n}\n\n/**\n * Run a bench-local python driver script (in the bench venv) while piping\n * `input` to its stdin, returning stdout. The driver's verdict JSON is its LAST\n * stdout line; callers parse that and inspect an `error` field (fail loud).\n *\n * Uses spawn + an explicit `stdin.end(input)` rather than promisify(execFile)'s\n * `input` option, because that option is NOT honored by async execFile — stdin\n * is left open and a driver that does `sys.stdin.read()` blocks forever. The\n * artifact-piping judges (commit0, appworld) MUST go through this.\n */\nexport function runVenvScriptStdin(\n scriptPath: string,\n args: string[],\n input: string,\n opts: { cwd?: string; timeoutMs?: number; python?: string } = {},\n): Promise<string> {\n return new Promise<string>((resolve, reject) => {\n const child = spawn(opts.python ?? venvPython, [scriptPath, ...args], {\n cwd: opts.cwd ?? benchRoot,\n ...(opts.timeoutMs ? { timeout: opts.timeoutMs } : {}),\n })\n let stdout = ''\n let stderr = ''\n let bytes = 0\n child.stdout.on('data', (c: Buffer) => {\n bytes += c.length\n if (bytes <= bigBuffer) stdout += c.toString('utf8')\n })\n child.stderr.on('data', (c: Buffer) => {\n stderr += c.toString('utf8')\n })\n child.on('error', (err) => reject(err))\n child.on('close', (code) => {\n if (code === 0) resolve(stdout)\n else reject(new Error((stderr || stdout || `exit ${code}`).slice(0, 1500)))\n })\n child.stdin.end(input)\n })\n}\n\nexport interface StagedRunSpec {\n /** mkdtemp prefix, e.g. 'swebench-' / 'commit0-'. */\n tmpPrefix: string\n /**\n * Write the artifact + any harness inputs into the temp dir. Returns nothing;\n * `argv`/`cwd` consume `dir` to point the evaluator at what was written.\n */\n stage(dir: string): Promise<void>\n /** The external evaluator to spawn. `bin` defaults to the bench venv python. */\n bin?: string\n /** argv for the evaluator, computed from the temp `dir`. */\n argv(dir: string): string[]\n /** Working directory for the evaluator. Defaults to the temp `dir`. */\n cwd?(dir: string): string\n /** Hard timeout for the evaluator (ms); 0 = none. */\n timeoutMs?: number\n /**\n * Read the evaluator's report(s) out of `dir` and map to a BenchScore. Throws\n * if the expected report is absent/malformed (fail loud — no default score).\n */\n parseReport(dir: string): Promise<BenchScore>\n /**\n * Copy the complete evaluator directory plus raw process stdout/stderr to this\n * caller-owned directory before cleanup. The destination must not exist.\n */\n capture?: StagedRunCaptureSpec\n /** Keep the temp dir on disk (debugging). Default false → always cleaned up. */\n keepTmp?: boolean\n}\n\nexport interface StagedRunCaptureSpec {\n /** Destination for `evaluator/`, `process/`, and the hashed `receipt.json`. */\n destination: string\n}\n\n/** A staged run failed after any requested evidence was durably retained. */\nexport class StagedJudgeError extends Error {\n readonly judgeArtifacts?: JudgeArtifactReceipt\n\n constructor(message: string, judgeArtifacts?: JudgeArtifactReceipt, options?: ErrorOptions) {\n super(message, options)\n this.name = 'StagedJudgeError'\n this.judgeArtifacts = judgeArtifacts\n }\n}\n\nfunction sha256(bytes: Uint8Array): `sha256:${string}` {\n return `sha256:${createHash('sha256').update(bytes).digest('hex')}`\n}\n\nfunction portablePath(path: string): string {\n return path.split(sep).join('/')\n}\n\nfunction compareText(left: string, right: string): number {\n return left < right ? -1 : left > right ? 1 : 0\n}\n\nasync function collectArtifactFiles(\n root: string,\n current: string,\n): Promise<JudgeArtifactFileReceipt[]> {\n const absolute = join(root, current)\n const entries = await readdir(absolute, { withFileTypes: true })\n const files: JudgeArtifactFileReceipt[] = []\n for (const entry of entries.sort((left, right) => compareText(left.name, right.name))) {\n const relativePath = join(current, entry.name)\n const path = join(root, relativePath)\n if (entry.isDirectory()) {\n files.push(...await collectArtifactFiles(root, relativePath))\n continue\n }\n if (entry.isFile()) {\n const bytes = await readFile(path)\n files.push({\n path: portablePath(relativePath),\n byteLength: bytes.byteLength,\n sha256: sha256(bytes),\n kind: 'file',\n })\n continue\n }\n if (entry.isSymbolicLink()) {\n const targetBytes = await readlink(path, { encoding: 'buffer' })\n files.push({\n path: portablePath(relativePath),\n byteLength: targetBytes.byteLength,\n sha256: sha256(targetBytes),\n kind: 'symlink',\n })\n continue\n }\n throw new Error(`staged judge capture does not support ${relativePath}`)\n }\n return files\n}\n\nfunction isWithin(parent: string, candidate: string): boolean {\n const path = relative(parent, candidate)\n return path === '' || (!path.startsWith(`..${sep}`) && path !== '..' && !isAbsolute(path))\n}\n\nasync function assertDestinationAbsent(destination: string): Promise<void> {\n try {\n await lstat(destination)\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return\n throw error\n }\n throw new Error(`staged judge capture destination already exists: ${destination}`)\n}\n\nasync function captureStagedRun(\n sourceDirectory: string,\n spec: StagedRunCaptureSpec,\n processOutput: Readonly<{ stdout: Buffer; stderr: Buffer }>,\n evaluatorSucceeded: boolean,\n): Promise<JudgeArtifactReceipt> {\n const source = resolve(sourceDirectory)\n const destination = resolve(spec.destination)\n if (isWithin(source, destination)) {\n throw new Error('staged judge capture destination must be outside the evaluator directory')\n }\n await mkdir(dirname(destination), { recursive: true })\n await assertDestinationAbsent(destination)\n const staging = await mkdtemp(join(dirname(destination), `.${basename(destination)}-capture-`))\n try {\n await cp(source, join(staging, 'evaluator'), {\n recursive: true,\n errorOnExist: true,\n force: false,\n preserveTimestamps: true,\n verbatimSymlinks: true,\n })\n await mkdir(join(staging, 'process'))\n await writeFile(join(staging, 'process', 'stdout.bin'), processOutput.stdout)\n await writeFile(join(staging, 'process', 'stderr.bin'), processOutput.stderr)\n\n const files = [\n ...await collectArtifactFiles(staging, 'evaluator'),\n ...await collectArtifactFiles(staging, 'process'),\n ].sort((left, right) => compareText(left.path, right.path))\n const byteLength = files.reduce((total, file) => total + file.byteLength, 0)\n const treeBytes = Buffer.from(\n files\n .map((file) => `${file.path}\\0${file.kind}\\0${file.byteLength}\\0${file.sha256}\\n`)\n .join(''),\n 'utf8',\n )\n const receipt: JudgeArtifactReceipt = {\n schema: 'agent-bench/judge-artifacts/v1',\n directory: destination,\n evaluatorDirectory: join(destination, 'evaluator'),\n manifestPath: join(destination, 'receipt.json'),\n evaluatorSucceeded,\n files,\n fileCount: files.length,\n byteLength,\n treeSha256: sha256(treeBytes),\n }\n await writeFile(join(staging, 'receipt.json'), `${JSON.stringify(receipt, null, 2)}\\n`)\n await rename(staging, destination)\n return receipt\n } catch (error) {\n await rm(staging, { recursive: true, force: true }).catch(() => {})\n throw error\n }\n}\n\nfunction processBytes(value: unknown): Buffer {\n if (Buffer.isBuffer(value)) return value\n if (value === undefined || value === null) return Buffer.alloc(0)\n return Buffer.from(String(value), 'utf8')\n}\n\n/**\n * The shared judge body: mkdtemp → stage → spawn evaluator → parseReport →\n * cleanup. The evaluator's stdout/stderr is surfaced on failure; the temp dir is\n * always removed in `finally` unless `keepTmp`.\n */\nexport async function runStagedJudge(spec: StagedRunSpec): Promise<BenchScore> {\n const dir = await mkdtemp(join(tmpdir(), spec.tmpPrefix))\n let stdout: Buffer<ArrayBufferLike> = Buffer.alloc(0)\n let stderr: Buffer<ArrayBufferLike> = Buffer.alloc(0)\n let evaluatorSucceeded = false\n let score: BenchScore | undefined\n let failure: unknown\n try {\n try {\n await spec.stage(dir)\n const bin = spec.bin ?? venvPython\n const argv = spec.argv(dir)\n try {\n const output = await execFileAsync(bin, argv, {\n cwd: spec.cwd ? spec.cwd(dir) : dir,\n encoding: 'buffer',\n maxBuffer: bigBuffer,\n ...(spec.timeoutMs ? { timeout: spec.timeoutMs } : {}),\n })\n stdout = processBytes(output.stdout)\n stderr = processBytes(output.stderr)\n evaluatorSucceeded = true\n } catch (err) {\n const e = err as { stderr?: unknown; stdout?: unknown; message?: string }\n stdout = processBytes(e.stdout)\n stderr = processBytes(e.stderr)\n const detail = processBytes(e.stderr ?? e.stdout ?? e.message ?? String(err))\n .toString('utf8')\n .slice(0, 2000)\n throw new Error(`${spec.tmpPrefix.replace(/-$/, '')} evaluator failed (${bin} ${argv.join(' ')}):\\n${detail}`)\n }\n score = await spec.parseReport(dir)\n } catch (err) {\n failure = err\n }\n } finally {\n let judgeArtifacts: JudgeArtifactReceipt | undefined\n if (spec.capture) {\n try {\n judgeArtifacts = await captureStagedRun(\n dir,\n spec.capture,\n { stdout, stderr },\n evaluatorSucceeded,\n )\n } catch (captureError) {\n failure = new Error(\n `staged judge failed to capture evaluator artifacts: ${captureError instanceof Error ? captureError.message : captureError}`,\n { cause: failure ?? captureError },\n )\n }\n }\n if (!spec.keepTmp) await rm(dir, { recursive: true, force: true }).catch(() => {})\n if (failure) {\n throw new StagedJudgeError(\n failure instanceof Error ? failure.message : String(failure),\n judgeArtifacts,\n { cause: failure },\n )\n }\n if (!score) throw new StagedJudgeError('staged judge completed without a score', judgeArtifacts)\n return judgeArtifacts ? { ...score, judgeArtifacts } : score\n }\n}\n\n/** Read + JSON.parse a report file from a staged run; throws with the path on failure. */\nexport async function readJsonReport<T>(path: string): Promise<T> {\n let raw: string\n try {\n raw = await readFile(path, 'utf8')\n } catch (err) {\n throw new Error(`expected report not written: ${path} (${err instanceof Error ? err.message : err})`)\n }\n try {\n return JSON.parse(raw) as T\n } catch (err) {\n throw new Error(`report not valid JSON at ${path}: ${err instanceof Error ? err.message : err}`)\n }\n}\n\n/** Write a UTF-8 file into a staged dir (artifact / preds.json / attempt.sh / …). */\nexport async function stageFile(path: string, content: string): Promise<void> {\n await writeFile(path, content)\n}\n\n/** Sanitize an instance id into a filesystem/run-id-safe token. */\nexport function safeRunId(prefix: string, id: string): string {\n return `${prefix}-${id}`.replace(/[^a-zA-Z0-9_.-]/g, '_')\n}\n"],"mappings":"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","names":["resolve"]}
@@ -1,262 +0,0 @@
1
- // src/benchmarks/rag-shared.ts
2
- import { readFile } from "fs/promises";
3
- var FINAL_ANSWER_SENTINEL = "FINAL ANSWER:";
4
- var ragAnswerOutput = {
5
- parse(events) {
6
- let text = "";
7
- for (const ev of events) {
8
- const d = ev?.data;
9
- const t = d?.finalText ?? d?.text ?? d?.result;
10
- if (typeof t === "string" && t.length > 0) text = t;
11
- }
12
- return text.trim();
13
- }
14
- };
15
- function parseFinalAnswer(artifact) {
16
- const lines = artifact.split(/\r?\n/);
17
- for (let i = lines.length - 1; i >= 0; i -= 1) {
18
- const line = lines[i] ?? "";
19
- const idx = line.toUpperCase().indexOf(FINAL_ANSWER_SENTINEL);
20
- if (idx !== -1) return line.slice(idx + FINAL_ANSWER_SENTINEL.length).trim();
21
- }
22
- for (let i = lines.length - 1; i >= 0; i -= 1) {
23
- const trimmed = (lines[i] ?? "").trim();
24
- if (trimmed.length > 0) return trimmed;
25
- }
26
- return "";
27
- }
28
- function parseCitations(artifact) {
29
- const urls = /* @__PURE__ */ new Set();
30
- for (const match of artifact.matchAll(/https?:\/\/[^\s)<>"']+/g)) {
31
- urls.add(match[0].replace(/[.,;]+$/, ""));
32
- }
33
- return [...urls];
34
- }
35
- function normalizeAnswer(input) {
36
- return input.toLowerCase().replace(/(\d),(?=\d{3}\b)/g, "$1").replace(/[^\p{L}\p{N}\s.-]+/gu, " ").split(/\s+/).filter((token) => token.length > 0).filter((token) => !["a", "an", "the"].includes(token)).join(" ").trim();
37
- }
38
- function tokens(input) {
39
- const normalized = normalizeAnswer(input);
40
- return normalized.length === 0 ? [] : normalized.split(/\s+/);
41
- }
42
- function tokenF1(candidate, gold) {
43
- const candidateTokens = tokens(candidate);
44
- const goldTokens = tokens(gold);
45
- if (candidateTokens.length === 0 || goldTokens.length === 0) {
46
- return candidateTokens.length === 0 && goldTokens.length === 0 ? 1 : 0;
47
- }
48
- const counts = /* @__PURE__ */ new Map();
49
- for (const token of goldTokens) counts.set(token, (counts.get(token) ?? 0) + 1);
50
- let common = 0;
51
- for (const token of candidateTokens) {
52
- const left = counts.get(token);
53
- if (left !== void 0 && left > 0) {
54
- common += 1;
55
- counts.set(token, left - 1);
56
- }
57
- }
58
- if (common === 0) return 0;
59
- const precision = common / candidateTokens.length;
60
- const recall = common / goldTokens.length;
61
- return 2 * precision * recall / (precision + recall);
62
- }
63
- function exactOrContains(candidate, gold) {
64
- const normalizedCandidate = normalizeAnswer(candidate);
65
- const normalizedGold = normalizeAnswer(gold);
66
- if (normalizedGold.length === 0) return false;
67
- if (normalizedCandidate === normalizedGold) return true;
68
- const escaped = normalizedGold.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
69
- return new RegExp(`(^|\\s)${escaped}(\\s|$)`).test(normalizedCandidate);
70
- }
71
- function numbers(input) {
72
- return [...input.replace(/,/g, "").matchAll(/-?\d+(?:\.\d+)?/g)].map((match) => Number(match[0])).filter(Number.isFinite);
73
- }
74
- function numericMatch(candidate, gold, relativeTolerance) {
75
- const got = numbers(candidate);
76
- const want = numbers(gold);
77
- if (got.length === 0 || want.length === 0) return false;
78
- return want.some(
79
- (expected) => got.some((actual) => {
80
- const tolerance = Math.max(Math.abs(expected) * relativeTolerance, relativeTolerance);
81
- return Math.abs(actual - expected) <= tolerance;
82
- })
83
- );
84
- }
85
- function scoreAnswerArtifact(artifact, golds, options = {}) {
86
- const finalAnswer = parseFinalAnswer(artifact);
87
- const threshold = options.threshold ?? 0.72;
88
- const numericTolerance = options.numericTolerance ?? 0.01;
89
- let best = {
90
- resolved: false,
91
- score: 0,
92
- finalAnswer,
93
- bestGold: null,
94
- exact: false,
95
- numeric: false,
96
- f1: 0,
97
- threshold
98
- };
99
- if (finalAnswer.length === 0 || golds.length === 0) return best;
100
- for (const gold of golds) {
101
- const exact = exactOrContains(finalAnswer, gold);
102
- const numeric = numericMatch(finalAnswer, gold, numericTolerance);
103
- const f1 = tokenF1(finalAnswer, gold);
104
- const resolved = exact || numeric || f1 >= threshold;
105
- const score = exact || numeric ? 1 : f1;
106
- if (score > best.score || resolved && !best.resolved) {
107
- best = { resolved, score, finalAnswer, bestGold: gold, exact, numeric, f1, threshold };
108
- }
109
- }
110
- return best;
111
- }
112
- function answerScoreToBenchScore(score, detail) {
113
- return {
114
- resolved: score.resolved,
115
- score: score.score,
116
- detail: JSON.stringify({
117
- ...detail,
118
- finalAnswer: score.finalAnswer,
119
- bestGold: score.bestGold,
120
- exact: score.exact,
121
- numeric: score.numeric,
122
- f1: score.f1,
123
- threshold: score.threshold
124
- })
125
- };
126
- }
127
- async function readJsonRows(path) {
128
- const raw = (await readFile(path, "utf8")).trim();
129
- if (raw.length === 0) return [];
130
- if (raw.startsWith("[")) {
131
- const parsed = JSON.parse(raw);
132
- if (Array.isArray(parsed)) return parsed;
133
- throw new Error(`${path} must contain a JSON array when it starts with [`);
134
- }
135
- if (raw.startsWith("{")) {
136
- try {
137
- const parsed = JSON.parse(raw);
138
- if (isObject(parsed)) {
139
- for (const key of ["rows", "data", "examples", "items"]) {
140
- const value = parsed[key];
141
- if (Array.isArray(value)) return value;
142
- }
143
- return [parsed];
144
- }
145
- throw new Error(`${path} must contain a JSON object, JSON array, JSONL rows, or an object with rows/data/examples/items`);
146
- } catch (err) {
147
- if (!raw.includes("\n")) throw err;
148
- }
149
- }
150
- return raw.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0).map((line) => JSON.parse(line));
151
- }
152
- function selectTasks(tasks, opts, label) {
153
- let selected = tasks;
154
- if (opts.split) selected = selected.filter((task) => task.split === opts.split);
155
- if (opts.ids) {
156
- const ids = new Set(opts.ids);
157
- selected = selected.filter((task) => ids.has(task.id));
158
- } else if (opts.limit !== void 0) {
159
- selected = selected.slice(0, opts.limit);
160
- }
161
- if (selected.length === 0) throw new Error(`${label}: no tasks matched ${JSON.stringify(opts)}`);
162
- return selected;
163
- }
164
- function stringFrom(value) {
165
- return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
166
- }
167
- function stringArrayFrom(value) {
168
- if (typeof value === "string" && value.trim().length > 0) return [value.trim()];
169
- if (!Array.isArray(value)) return [];
170
- return value.flatMap((entry) => {
171
- if (typeof entry === "string" && entry.trim().length > 0) return [entry.trim()];
172
- if (isObject(entry)) {
173
- const text = stringFrom(entry.answer) ?? stringFrom(entry.value) ?? stringFrom(entry.text);
174
- return text ? [text] : [];
175
- }
176
- return [];
177
- });
178
- }
179
- function firstString(row, keys) {
180
- for (const key of keys) {
181
- const value = stringFrom(row[key]);
182
- if (value) return value;
183
- }
184
- return "";
185
- }
186
- function allStrings(row, keys) {
187
- const out = [];
188
- for (const key of keys) out.push(...stringArrayFrom(row[key]));
189
- return [...new Set(out)];
190
- }
191
- function contextsFrom(value) {
192
- if (typeof value === "string" && value.trim().length > 0) {
193
- return [{ id: "ctx-1", text: value.trim() }];
194
- }
195
- if (!Array.isArray(value)) return [];
196
- return value.flatMap((entry, index) => {
197
- if (typeof entry === "string" && entry.trim().length > 0) {
198
- return [{ id: `ctx-${index + 1}`, text: entry.trim() }];
199
- }
200
- if (Array.isArray(entry)) {
201
- const [first, second] = entry;
202
- if (typeof first === "string" && typeof second === "string") {
203
- return [{ id: first, text: second.trim() }];
204
- }
205
- return entry.flatMap(
206
- (nested, nestedIndex) => contextsFrom([nested]).map((ctx) => ({
207
- ...ctx,
208
- id: ctx.id.startsWith("ctx-") ? `ctx-${index + 1}-${nestedIndex + 1}` : ctx.id
209
- }))
210
- );
211
- }
212
- if (!isObject(entry)) return [];
213
- const text = stringFrom(entry.text) ?? stringFrom(entry.context) ?? stringFrom(entry.content) ?? stringFrom(entry.passage) ?? stringFrom(entry.document) ?? stringFrom(entry.page_content) ?? stringFrom(entry.chunk);
214
- if (!text) return [];
215
- const id = stringFrom(entry.id) ?? stringFrom(entry.docid) ?? stringFrom(entry.doc_id) ?? stringFrom(entry.document_id) ?? `ctx-${index + 1}`;
216
- const relevantRaw = entry.relevant ?? entry.is_relevant ?? entry.label ?? entry.relevance;
217
- const relevant = typeof relevantRaw === "boolean" ? relevantRaw : typeof relevantRaw === "number" ? relevantRaw > 0 : void 0;
218
- return [
219
- {
220
- id,
221
- text,
222
- ...stringFrom(entry.title) ? { title: stringFrom(entry.title) } : {},
223
- ...stringFrom(entry.source) ?? stringFrom(entry.url) ? { source: stringFrom(entry.source) ?? stringFrom(entry.url) } : {},
224
- ...relevant !== void 0 ? { relevant } : {}
225
- }
226
- ];
227
- });
228
- }
229
- function contextBlock(contexts) {
230
- if (contexts.length === 0) return "";
231
- return contexts.map(
232
- (ctx, index) => [
233
- `[${index + 1}] ${ctx.title ?? ctx.id}`,
234
- ctx.source ? `Source: ${ctx.source}` : void 0,
235
- ctx.text
236
- ].filter(Boolean).join("\n")
237
- ).join("\n\n");
238
- }
239
- function isObject(value) {
240
- return Boolean(value) && typeof value === "object" && !Array.isArray(value);
241
- }
242
-
243
- export {
244
- FINAL_ANSWER_SENTINEL,
245
- ragAnswerOutput,
246
- parseFinalAnswer,
247
- parseCitations,
248
- normalizeAnswer,
249
- tokenF1,
250
- scoreAnswerArtifact,
251
- answerScoreToBenchScore,
252
- readJsonRows,
253
- selectTasks,
254
- stringFrom,
255
- stringArrayFrom,
256
- firstString,
257
- allStrings,
258
- contextsFrom,
259
- contextBlock,
260
- isObject
261
- };
262
- //# sourceMappingURL=chunk-X3BTXCJ4.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/benchmarks/rag-shared.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises'\nimport type { OutputAdapter } from '@tangle-network/agent-runtime/loops'\nimport type { BenchScore, BenchTask, LoadOptions } from './types'\n\nexport const FINAL_ANSWER_SENTINEL = 'FINAL ANSWER:'\n\nexport interface RagContext {\n id: string\n text: string\n title?: string\n source?: string\n relevant?: boolean\n}\n\nexport interface RagAnswerScore {\n resolved: boolean\n score: number\n finalAnswer: string\n bestGold: string | null\n exact: boolean\n numeric: boolean\n f1: number\n threshold: number\n}\n\nexport const ragAnswerOutput: 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 return text.trim()\n },\n}\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 trimmed = (lines[i] ?? '').trim()\n if (trimmed.length > 0) return trimmed\n }\n return ''\n}\n\nexport function parseCitations(artifact: string): string[] {\n const urls = new Set<string>()\n for (const match of artifact.matchAll(/https?:\\/\\/[^\\s)<>\"']+/g)) {\n urls.add(match[0].replace(/[.,;]+$/, ''))\n }\n return [...urls]\n}\n\nexport function normalizeAnswer(input: string): string {\n return input\n .toLowerCase()\n .replace(/(\\d),(?=\\d{3}\\b)/g, '$1')\n .replace(/[^\\p{L}\\p{N}\\s.-]+/gu, ' ')\n .split(/\\s+/)\n .filter((token) => token.length > 0)\n .filter((token) => !['a', 'an', 'the'].includes(token))\n .join(' ')\n .trim()\n}\n\nfunction tokens(input: string): string[] {\n const normalized = normalizeAnswer(input)\n return normalized.length === 0 ? [] : normalized.split(/\\s+/)\n}\n\nexport function tokenF1(candidate: string, gold: string): number {\n const candidateTokens = tokens(candidate)\n const goldTokens = tokens(gold)\n if (candidateTokens.length === 0 || goldTokens.length === 0) {\n return candidateTokens.length === 0 && goldTokens.length === 0 ? 1 : 0\n }\n const counts = new Map<string, number>()\n for (const token of goldTokens) counts.set(token, (counts.get(token) ?? 0) + 1)\n let common = 0\n for (const token of candidateTokens) {\n const left = counts.get(token)\n if (left !== undefined && left > 0) {\n common += 1\n counts.set(token, left - 1)\n }\n }\n if (common === 0) return 0\n const precision = common / candidateTokens.length\n const recall = common / goldTokens.length\n return (2 * precision * recall) / (precision + recall)\n}\n\nfunction exactOrContains(candidate: string, gold: string): boolean {\n const normalizedCandidate = normalizeAnswer(candidate)\n const normalizedGold = normalizeAnswer(gold)\n if (normalizedGold.length === 0) return false\n if (normalizedCandidate === normalizedGold) return true\n const escaped = normalizedGold.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n return new RegExp(`(^|\\\\s)${escaped}(\\\\s|$)`).test(normalizedCandidate)\n}\n\nfunction numbers(input: string): number[] {\n return [...input.replace(/,/g, '').matchAll(/-?\\d+(?:\\.\\d+)?/g)]\n .map((match) => Number(match[0]))\n .filter(Number.isFinite)\n}\n\nfunction numericMatch(candidate: string, gold: string, relativeTolerance: number): boolean {\n const got = numbers(candidate)\n const want = numbers(gold)\n if (got.length === 0 || want.length === 0) return false\n return want.some((expected) =>\n got.some((actual) => {\n const tolerance = Math.max(Math.abs(expected) * relativeTolerance, relativeTolerance)\n return Math.abs(actual - expected) <= tolerance\n }),\n )\n}\n\nexport function scoreAnswerArtifact(\n artifact: string,\n golds: readonly string[],\n options: { threshold?: number; numericTolerance?: number } = {},\n): RagAnswerScore {\n const finalAnswer = parseFinalAnswer(artifact)\n const threshold = options.threshold ?? 0.72\n const numericTolerance = options.numericTolerance ?? 0.01\n let best: RagAnswerScore = {\n resolved: false,\n score: 0,\n finalAnswer,\n bestGold: null,\n exact: false,\n numeric: false,\n f1: 0,\n threshold,\n }\n if (finalAnswer.length === 0 || golds.length === 0) return best\n\n for (const gold of golds) {\n const exact = exactOrContains(finalAnswer, gold)\n const numeric = numericMatch(finalAnswer, gold, numericTolerance)\n const f1 = tokenF1(finalAnswer, gold)\n const resolved = exact || numeric || f1 >= threshold\n const score = exact || numeric ? 1 : f1\n if (score > best.score || (resolved && !best.resolved)) {\n best = { resolved, score, finalAnswer, bestGold: gold, exact, numeric, f1, threshold }\n }\n }\n return best\n}\n\nexport function answerScoreToBenchScore(\n score: RagAnswerScore,\n detail: Record<string, unknown>,\n): BenchScore {\n return {\n resolved: score.resolved,\n score: score.score,\n detail: JSON.stringify({\n ...detail,\n finalAnswer: score.finalAnswer,\n bestGold: score.bestGold,\n exact: score.exact,\n numeric: score.numeric,\n f1: score.f1,\n threshold: score.threshold,\n }),\n }\n}\n\nexport async function readJsonRows(path: string): Promise<unknown[]> {\n const raw = (await readFile(path, 'utf8')).trim()\n if (raw.length === 0) return []\n if (raw.startsWith('[')) {\n const parsed = JSON.parse(raw) as unknown\n if (Array.isArray(parsed)) return parsed\n throw new Error(`${path} must contain a JSON array when it starts with [`)\n }\n if (raw.startsWith('{')) {\n try {\n const parsed = JSON.parse(raw) as unknown\n if (isObject(parsed)) {\n for (const key of ['rows', 'data', 'examples', 'items']) {\n const value = parsed[key]\n if (Array.isArray(value)) return value\n }\n return [parsed]\n }\n throw new Error(`${path} must contain a JSON object, JSON array, JSONL rows, or an object with rows/data/examples/items`)\n } catch (err) {\n if (!raw.includes('\\n')) throw err\n }\n }\n return raw\n .split(/\\r?\\n/)\n .map((line) => line.trim())\n .filter((line) => line.length > 0)\n .map((line) => JSON.parse(line) as unknown)\n}\n\nexport function selectTasks(tasks: BenchTask[], opts: LoadOptions, label: string): BenchTask[] {\n let selected = tasks\n if (opts.split) selected = selected.filter((task) => task.split === opts.split)\n if (opts.ids) {\n const ids = new Set(opts.ids)\n selected = selected.filter((task) => ids.has(task.id))\n } else if (opts.limit !== undefined) {\n selected = selected.slice(0, opts.limit)\n }\n if (selected.length === 0) throw new Error(`${label}: no tasks matched ${JSON.stringify(opts)}`)\n return selected\n}\n\nexport function stringFrom(value: unknown): string | undefined {\n return typeof value === 'string' && value.trim().length > 0 ? value.trim() : undefined\n}\n\nexport function stringArrayFrom(value: unknown): string[] {\n if (typeof value === 'string' && value.trim().length > 0) return [value.trim()]\n if (!Array.isArray(value)) return []\n return value.flatMap((entry) => {\n if (typeof entry === 'string' && entry.trim().length > 0) return [entry.trim()]\n if (isObject(entry)) {\n const text = stringFrom(entry.answer) ?? stringFrom(entry.value) ?? stringFrom(entry.text)\n return text ? [text] : []\n }\n return []\n })\n}\n\nexport function firstString(row: Record<string, unknown>, keys: readonly string[]): string {\n for (const key of keys) {\n const value = stringFrom(row[key])\n if (value) return value\n }\n return ''\n}\n\nexport function allStrings(row: Record<string, unknown>, keys: readonly string[]): string[] {\n const out: string[] = []\n for (const key of keys) out.push(...stringArrayFrom(row[key]))\n return [...new Set(out)]\n}\n\nexport function contextsFrom(value: unknown): RagContext[] {\n if (typeof value === 'string' && value.trim().length > 0) {\n return [{ id: 'ctx-1', text: value.trim() }]\n }\n if (!Array.isArray(value)) return []\n return value.flatMap((entry, index): RagContext[] => {\n if (typeof entry === 'string' && entry.trim().length > 0) {\n return [{ id: `ctx-${index + 1}`, text: entry.trim() }]\n }\n if (Array.isArray(entry)) {\n const [first, second] = entry\n if (typeof first === 'string' && typeof second === 'string') {\n return [{ id: first, text: second.trim() }]\n }\n return entry.flatMap((nested, nestedIndex) =>\n contextsFrom([nested]).map((ctx) => ({\n ...ctx,\n id: ctx.id.startsWith('ctx-') ? `ctx-${index + 1}-${nestedIndex + 1}` : ctx.id,\n })),\n )\n }\n if (!isObject(entry)) return []\n const text =\n stringFrom(entry.text) ??\n stringFrom(entry.context) ??\n stringFrom(entry.content) ??\n stringFrom(entry.passage) ??\n stringFrom(entry.document) ??\n stringFrom(entry.page_content) ??\n stringFrom(entry.chunk)\n if (!text) return []\n const id =\n stringFrom(entry.id) ??\n stringFrom(entry.docid) ??\n stringFrom(entry.doc_id) ??\n stringFrom(entry.document_id) ??\n `ctx-${index + 1}`\n const relevantRaw = entry.relevant ?? entry.is_relevant ?? entry.label ?? entry.relevance\n const relevant =\n typeof relevantRaw === 'boolean'\n ? relevantRaw\n : typeof relevantRaw === 'number'\n ? relevantRaw > 0\n : undefined\n return [\n {\n id,\n text,\n ...(stringFrom(entry.title) ? { title: stringFrom(entry.title) } : {}),\n ...(stringFrom(entry.source) ?? stringFrom(entry.url)\n ? { source: stringFrom(entry.source) ?? stringFrom(entry.url) }\n : {}),\n ...(relevant !== undefined ? { relevant } : {}),\n },\n ]\n })\n}\n\nexport function contextBlock(contexts: readonly RagContext[]): string {\n if (contexts.length === 0) return ''\n return contexts\n .map((ctx, index) =>\n [\n `[${index + 1}] ${ctx.title ?? ctx.id}`,\n ctx.source ? `Source: ${ctx.source}` : undefined,\n ctx.text,\n ]\n .filter(Boolean)\n .join('\\n'),\n )\n .join('\\n\\n')\n}\n\nexport function isObject(value: unknown): value is Record<string, unknown> {\n return Boolean(value) && typeof value === 'object' && !Array.isArray(value)\n}\n"],"mappings":"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","names":[]}