@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.
- package/CHANGELOG.md +15 -0
- package/dist/adapters.d.ts +4 -11
- package/dist/adapters.js +78 -41
- package/dist/adapters.js.map +1 -1
- package/dist/benchmarks/_harness.d.ts +51 -66
- package/dist/benchmarks/_harness.js +329 -31
- package/dist/benchmarks/_harness.js.map +1 -1
- package/dist/benchmarks/aec-bench.d.ts +4 -25
- package/dist/benchmarks/aec-bench.js +242 -7
- package/dist/benchmarks/aec-bench.js.map +1 -1
- package/dist/benchmarks/agentbench.d.ts +5 -13
- package/dist/benchmarks/agentbench.js +114 -9
- package/dist/benchmarks/agentbench.js.map +1 -1
- package/dist/benchmarks/appworld.d.ts +9 -29
- package/dist/benchmarks/appworld.js +317 -12
- package/dist/benchmarks/appworld.js.map +1 -1
- package/dist/benchmarks/bfcl.d.ts +5 -15
- package/dist/benchmarks/bfcl.js +264 -9
- package/dist/benchmarks/bfcl.js.map +1 -1
- package/dist/benchmarks/cad-design.d.ts +16 -41
- package/dist/benchmarks/cad-design.js +512 -6
- package/dist/benchmarks/cad-design.js.map +1 -1
- package/dist/benchmarks/cadbench.d.ts +4 -17
- package/dist/benchmarks/cadbench.js +2 -8
- package/dist/benchmarks/cadgenbench.d.ts +4 -20
- package/dist/benchmarks/cadgenbench.js +2 -8
- package/dist/benchmarks/commit0.d.ts +5 -27
- package/dist/benchmarks/commit0.js +187 -9
- package/dist/benchmarks/commit0.js.map +1 -1
- package/dist/benchmarks/crag.d.ts +4 -12
- package/dist/benchmarks/crag.js +110 -8
- package/dist/benchmarks/crag.js.map +1 -1
- package/dist/benchmarks/dabstep.d.ts +5 -15
- package/dist/benchmarks/dabstep.js +177 -9
- package/dist/benchmarks/dabstep.js.map +1 -1
- package/dist/benchmarks/enterpriseops-gym.d.ts +5 -34
- package/dist/benchmarks/enterpriseops-gym.js +236 -9
- package/dist/benchmarks/enterpriseops-gym.js.map +1 -1
- package/dist/benchmarks/finresearchbench.d.ts +4 -13
- package/dist/benchmarks/finresearchbench.js +218 -7
- package/dist/benchmarks/finresearchbench.js.map +1 -1
- package/dist/benchmarks/finsearchcomp.d.ts +8 -39
- package/dist/benchmarks/finsearchcomp.js +267 -6
- package/dist/benchmarks/finsearchcomp.js.map +1 -1
- package/dist/benchmarks/frames.d.ts +15 -37
- package/dist/benchmarks/frames.js +408 -11
- package/dist/benchmarks/frames.js.map +1 -1
- package/dist/benchmarks/hotpotqa.d.ts +4 -24
- package/dist/benchmarks/hotpotqa.js +250 -14
- package/dist/benchmarks/hotpotqa.js.map +1 -1
- package/dist/benchmarks/humaneval.d.ts +19 -37
- package/dist/benchmarks/humaneval.js +279 -16
- package/dist/benchmarks/humaneval.js.map +1 -1
- package/dist/benchmarks/mind2web.d.ts +7 -34
- package/dist/benchmarks/mind2web.js +257 -8
- package/dist/benchmarks/mind2web.js.map +1 -1
- package/dist/benchmarks/nomiracl.d.ts +4 -13
- package/dist/benchmarks/nomiracl.js +146 -8
- package/dist/benchmarks/nomiracl.js.map +1 -1
- package/dist/benchmarks/open-rag-bench.d.ts +4 -12
- package/dist/benchmarks/open-rag-bench.js +110 -8
- package/dist/benchmarks/open-rag-bench.js.map +1 -1
- package/dist/benchmarks/programbench.d.ts +5 -29
- package/dist/benchmarks/programbench.js +161 -9
- package/dist/benchmarks/programbench.js.map +1 -1
- package/dist/benchmarks/rag-shared.d.ts +21 -20
- package/dist/benchmarks/rag-shared.js +245 -38
- package/dist/benchmarks/rag-shared.js.map +1 -1
- package/dist/benchmarks/ragbench.d.ts +4 -14
- package/dist/benchmarks/ragbench.js +127 -8
- package/dist/benchmarks/ragbench.js.map +1 -1
- package/dist/benchmarks/simpleqa.d.ts +17 -44
- package/dist/benchmarks/simpleqa.js +293 -10
- package/dist/benchmarks/simpleqa.js.map +1 -1
- package/dist/benchmarks/swe-bench.d.ts +23 -36
- package/dist/benchmarks/swe-bench.js +234 -13
- package/dist/benchmarks/swe-bench.js.map +1 -1
- package/dist/benchmarks/t2-ragbench.d.ts +4 -12
- package/dist/benchmarks/t2-ragbench.js +118 -8
- package/dist/benchmarks/t2-ragbench.js.map +1 -1
- package/dist/benchmarks/tau-bench-shared.d.ts +14 -22
- package/dist/benchmarks/tau-bench-shared.js +169 -9
- package/dist/benchmarks/tau-bench-shared.js.map +1 -1
- package/dist/benchmarks/tau2-bench.d.ts +5 -5
- package/dist/benchmarks/tau2-bench.js +28 -10
- package/dist/benchmarks/tau2-bench.js.map +1 -1
- package/dist/benchmarks/tau3-banking.d.ts +4 -13
- package/dist/benchmarks/tau3-banking.js +28 -8
- package/dist/benchmarks/tau3-banking.js.map +1 -1
- package/dist/benchmarks/terminal-bench.d.ts +4 -22
- package/dist/benchmarks/terminal-bench.js +140 -7
- package/dist/benchmarks/terminal-bench.js.map +1 -1
- package/dist/benchmarks/toollm.d.ts +5 -13
- package/dist/benchmarks/toollm.js +184 -9
- package/dist/benchmarks/toollm.js.map +1 -1
- package/dist/benchmarks/trata-hedge.d.ts +4 -30
- package/dist/benchmarks/trata-hedge.js +336 -6
- package/dist/benchmarks/trata-hedge.js.map +1 -1
- package/dist/benchmarks/types.d.ts +85 -94
- package/dist/benchmarks/types.js +1 -1
- package/dist/benchmarks/webarena-verified.d.ts +5 -13
- package/dist/benchmarks/webarena-verified.js +152 -9
- package/dist/benchmarks/webarena-verified.js.map +1 -1
- package/dist/cadbench-DpQWZHp4.js +285 -0
- package/dist/cadbench-DpQWZHp4.js.map +1 -0
- package/dist/cadgenbench-DRhczfsG.js +151 -0
- package/dist/cadgenbench-DRhczfsG.js.map +1 -0
- package/dist/index.d.ts +245 -293
- package/dist/index.js +1669 -1791
- package/dist/index.js.map +1 -1
- package/package.json +17 -14
- package/pier_agents/candidate_contract.py +238 -24
- package/pier_agents/tangle_candidate.py +75 -5
- package/scripts/verify-packed-consumer.mjs +84 -17
- package/scripts/verify-pier-agent.mts +6 -4
- package/src/benchmarks/_harness.test.mts +16 -1
- package/src/benchmarks/_harness.ts +9 -2
- package/src/benchmarks/terminal-bench.ts +2 -1
- package/src/corpus.test.mts +13 -0
- package/src/corpus.ts +4 -0
- package/src/profile-coordinates.ts +2 -2
- package/src/rollout-ledger/backfill-swe-arena.mts +5 -1
- package/src/rollout-ledger/settle-capture.mts +7 -1
- package/src/search-bench/profiles.ts +1 -1
- package/src/skill-sandbox-smoke.mts +2 -1
- package/src/swe-arena/gepa-seat.mts +1 -1
- package/src/swe-arena/ledger-orphans.test.mts +36 -34
- package/dist/benchmarks/cadbench.js.map +0 -1
- package/dist/benchmarks/cadgenbench.js.map +0 -1
- package/dist/benchmarks/types.js.map +0 -1
- package/dist/chunk-3U5TXJZS.js +0 -251
- package/dist/chunk-3U5TXJZS.js.map +0 -1
- package/dist/chunk-53UPUNBZ.js +0 -325
- package/dist/chunk-53UPUNBZ.js.map +0 -1
- package/dist/chunk-5H5XV76F.js +0 -240
- package/dist/chunk-5H5XV76F.js.map +0 -1
- package/dist/chunk-7GRVHU22.js +0 -208
- package/dist/chunk-7GRVHU22.js.map +0 -1
- package/dist/chunk-C7T7WEK2.js +0 -103
- package/dist/chunk-C7T7WEK2.js.map +0 -1
- package/dist/chunk-HWST3SED.js +0 -162
- package/dist/chunk-HWST3SED.js.map +0 -1
- package/dist/chunk-IA2FBTWC.js +0 -318
- package/dist/chunk-IA2FBTWC.js.map +0 -1
- package/dist/chunk-IFVINJ4B.js +0 -142
- package/dist/chunk-IFVINJ4B.js.map +0 -1
- package/dist/chunk-INNOYXCP.js +0 -387
- package/dist/chunk-INNOYXCP.js.map +0 -1
- package/dist/chunk-IZ5M6OAC.js +0 -169
- package/dist/chunk-IZ5M6OAC.js.map +0 -1
- package/dist/chunk-JTHWEDEW.js +0 -32
- package/dist/chunk-JTHWEDEW.js.map +0 -1
- package/dist/chunk-K3BQGZCT.js +0 -221
- package/dist/chunk-K3BQGZCT.js.map +0 -1
- package/dist/chunk-KP5KD6EN.js +0 -276
- package/dist/chunk-KP5KD6EN.js.map +0 -1
- package/dist/chunk-MQMRLGOG.js +0 -136
- package/dist/chunk-MQMRLGOG.js.map +0 -1
- package/dist/chunk-NQG5XDSB.js +0 -147
- package/dist/chunk-NQG5XDSB.js.map +0 -1
- package/dist/chunk-PA2ZKHJC.js +0 -230
- package/dist/chunk-PA2ZKHJC.js.map +0 -1
- package/dist/chunk-PB64GYIG.js +0 -118
- package/dist/chunk-PB64GYIG.js.map +0 -1
- package/dist/chunk-PUIRNYI7.js +0 -189
- package/dist/chunk-PUIRNYI7.js.map +0 -1
- package/dist/chunk-RCYQEFNX.js +0 -30
- package/dist/chunk-RCYQEFNX.js.map +0 -1
- package/dist/chunk-RH5F53JT.js +0 -182
- package/dist/chunk-RH5F53JT.js.map +0 -1
- package/dist/chunk-SEVJPLZC.js +0 -260
- package/dist/chunk-SEVJPLZC.js.map +0 -1
- package/dist/chunk-SFLA7OH3.js +0 -27
- package/dist/chunk-SFLA7OH3.js.map +0 -1
- package/dist/chunk-SHM6MRRF.js +0 -130
- package/dist/chunk-SHM6MRRF.js.map +0 -1
- package/dist/chunk-SHYIRB7I.js +0 -120
- package/dist/chunk-SHYIRB7I.js.map +0 -1
- package/dist/chunk-SVR2LKYI.js +0 -116
- package/dist/chunk-SVR2LKYI.js.map +0 -1
- package/dist/chunk-TBKU5XQI.js +0 -228
- package/dist/chunk-TBKU5XQI.js.map +0 -1
- package/dist/chunk-UPAMRDX4.js +0 -233
- package/dist/chunk-UPAMRDX4.js.map +0 -1
- package/dist/chunk-V7AEBY6U.js +0 -144
- package/dist/chunk-V7AEBY6U.js.map +0 -1
- package/dist/chunk-VQRS7VUC.js +0 -342
- package/dist/chunk-VQRS7VUC.js.map +0 -1
- package/dist/chunk-WSKWVEQB.js +0 -317
- package/dist/chunk-WSKWVEQB.js.map +0 -1
- package/dist/chunk-X3BTXCJ4.js +0 -262
- package/dist/chunk-X3BTXCJ4.js.map +0 -1
- package/dist/chunk-XKEFIFIC.js +0 -197
- package/dist/chunk-XKEFIFIC.js.map +0 -1
- package/dist/chunk-XYA4XSNU.js +0 -148
- package/dist/chunk-XYA4XSNU.js.map +0 -1
- package/dist/chunk-YSMEKBTD.js +0 -211
- package/dist/chunk-YSMEKBTD.js.map +0 -1
- package/dist/chunk-Z4TZ76N7.js +0 -170
- package/dist/chunk-Z4TZ76N7.js.map +0 -1
package/dist/chunk-KP5KD6EN.js
DELETED
|
@@ -1,276 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
benchRoot
|
|
3
|
-
} from "./chunk-WSKWVEQB.js";
|
|
4
|
-
|
|
5
|
-
// src/benchmarks/bfcl.ts
|
|
6
|
-
import { readFile, stat } from "fs/promises";
|
|
7
|
-
import { join } from "path";
|
|
8
|
-
var FIXTURES = join(benchRoot, "fixtures", "bfcl.json");
|
|
9
|
-
var DEFAULT_CATEGORY = "BFCL_v4_simple_python";
|
|
10
|
-
var bfclDir = () => process.env.BFCL_DIR;
|
|
11
|
-
var bfclCategory = () => process.env.BFCL_CATEGORY ?? DEFAULT_CATEGORY;
|
|
12
|
-
var bfclOutput = {
|
|
13
|
-
parse(events) {
|
|
14
|
-
let text = "";
|
|
15
|
-
for (const ev of events) {
|
|
16
|
-
const d = ev?.data;
|
|
17
|
-
const t = d?.finalText ?? d?.text ?? d?.result;
|
|
18
|
-
if (typeof t === "string" && t.length > 0) text = t;
|
|
19
|
-
}
|
|
20
|
-
return text.trim();
|
|
21
|
-
}
|
|
22
|
-
};
|
|
23
|
-
async function assertPath(path, label) {
|
|
24
|
-
try {
|
|
25
|
-
await stat(path);
|
|
26
|
-
} catch (err) {
|
|
27
|
-
throw new Error(`BFCL: missing ${label} at ${path} (${err instanceof Error ? err.message : err})`);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
function readJsonl(raw) {
|
|
31
|
-
return raw.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0).map((line) => JSON.parse(line));
|
|
32
|
-
}
|
|
33
|
-
function taskFile(dir, category) {
|
|
34
|
-
return process.env.BFCL_DATA_FILE ?? join(dir, "bfcl_eval", "data", `${category}.json`);
|
|
35
|
-
}
|
|
36
|
-
function answerFile(dir, category) {
|
|
37
|
-
return process.env.BFCL_ANSWER_FILE ?? join(dir, "bfcl_eval", "data", "possible_answer", `${category}.json`);
|
|
38
|
-
}
|
|
39
|
-
function questionText(question) {
|
|
40
|
-
if (typeof question === "string") return question;
|
|
41
|
-
if (!Array.isArray(question)) return JSON.stringify(question, null, 2);
|
|
42
|
-
const turns = [];
|
|
43
|
-
for (const item of question.flat(3)) {
|
|
44
|
-
if (item && typeof item === "object") {
|
|
45
|
-
const role = typeof item.role === "string" ? item.role : "user";
|
|
46
|
-
const content = item.content;
|
|
47
|
-
if (typeof content === "string") turns.push(`${role}: ${content}`);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
return turns.length > 0 ? turns.join("\n") : JSON.stringify(question, null, 2);
|
|
51
|
-
}
|
|
52
|
-
function normalizeScalar(value) {
|
|
53
|
-
if (typeof value === "number") return Number.isInteger(value) ? String(value) : String(Number(value.toFixed(8)));
|
|
54
|
-
if (typeof value === "string") return value.trim().toLowerCase();
|
|
55
|
-
return JSON.stringify(value);
|
|
56
|
-
}
|
|
57
|
-
function normalizeAllowed(value) {
|
|
58
|
-
return Array.isArray(value) ? value : [value];
|
|
59
|
-
}
|
|
60
|
-
function groundTruthToCalls(value) {
|
|
61
|
-
if (!Array.isArray(value)) return [];
|
|
62
|
-
const out = [];
|
|
63
|
-
for (const item of value) {
|
|
64
|
-
if (!item || typeof item !== "object") continue;
|
|
65
|
-
for (const [name, args] of Object.entries(item)) {
|
|
66
|
-
if (!args || typeof args !== "object" || Array.isArray(args)) continue;
|
|
67
|
-
const normalized = {};
|
|
68
|
-
for (const [argName, allowed] of Object.entries(args)) {
|
|
69
|
-
normalized[argName] = normalizeAllowed(allowed);
|
|
70
|
-
}
|
|
71
|
-
out.push({ name, arguments: normalized });
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
return out;
|
|
75
|
-
}
|
|
76
|
-
function rowToTask(row, answer, category) {
|
|
77
|
-
const expected = groundTruthToCalls(answer.ground_truth);
|
|
78
|
-
if (expected.length === 0) {
|
|
79
|
-
throw new Error(`BFCL ${row.id}: possible_answer has no deterministic ground_truth calls`);
|
|
80
|
-
}
|
|
81
|
-
const meta = {
|
|
82
|
-
rowId: row.id,
|
|
83
|
-
category,
|
|
84
|
-
functions: row.function,
|
|
85
|
-
expected,
|
|
86
|
-
scoring: "bfcl-ground-truth-subset"
|
|
87
|
-
};
|
|
88
|
-
return {
|
|
89
|
-
id: row.id,
|
|
90
|
-
split: category,
|
|
91
|
-
prompt: [
|
|
92
|
-
"Solve this BFCL function-calling task.",
|
|
93
|
-
'Return only JSON: {"function_calls":[{"name":"...","arguments":{...}}]}.',
|
|
94
|
-
"",
|
|
95
|
-
questionText(row.question),
|
|
96
|
-
"",
|
|
97
|
-
`Available functions: ${JSON.stringify(row.function, null, 2)}`
|
|
98
|
-
].join("\n"),
|
|
99
|
-
metadata: meta
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
|
-
function readMeta(task) {
|
|
103
|
-
const md = task.metadata;
|
|
104
|
-
if (!md || !Array.isArray(md.expected)) {
|
|
105
|
-
throw new Error(`BFCL task ${task.id} missing expected calls \u2014 loadTasks did not populate metadata`);
|
|
106
|
-
}
|
|
107
|
-
return md;
|
|
108
|
-
}
|
|
109
|
-
function selectTasks(tasks, opts) {
|
|
110
|
-
let out = tasks;
|
|
111
|
-
if (opts.split) out = out.filter((task) => task.split === opts.split);
|
|
112
|
-
if (opts.ids) {
|
|
113
|
-
const want = new Set(opts.ids);
|
|
114
|
-
out = out.filter((task) => want.has(task.id));
|
|
115
|
-
} else if (opts.limit !== void 0) {
|
|
116
|
-
out = out.slice(0, opts.limit);
|
|
117
|
-
}
|
|
118
|
-
if (out.length === 0) throw new Error(`BFCL: no tasks matched ${JSON.stringify(opts)}`);
|
|
119
|
-
return out;
|
|
120
|
-
}
|
|
121
|
-
function buildTasks(rows, answers, category, opts) {
|
|
122
|
-
const byId = new Map(answers.map((answer) => [answer.id, answer]));
|
|
123
|
-
const tasks = rows.map((row) => {
|
|
124
|
-
const answer = byId.get(row.id);
|
|
125
|
-
if (!answer) throw new Error(`BFCL ${category}: missing possible_answer for ${row.id}`);
|
|
126
|
-
return rowToTask(row, answer, category);
|
|
127
|
-
});
|
|
128
|
-
return selectTasks(tasks, opts);
|
|
129
|
-
}
|
|
130
|
-
async function loadFixtures(opts) {
|
|
131
|
-
const fixture = JSON.parse(await readFile(FIXTURES, "utf8"));
|
|
132
|
-
console.warn(`[bfcl] BFCL_FIXTURES=1 \u2014 loading ${fixture.rows.length} adapter fixtures`);
|
|
133
|
-
return buildTasks(fixture.rows, fixture.answers, fixture.category, opts);
|
|
134
|
-
}
|
|
135
|
-
async function loadOfficialTasks(dir, opts) {
|
|
136
|
-
const category = bfclCategory();
|
|
137
|
-
const dataPath = taskFile(dir, category);
|
|
138
|
-
const answersPath = answerFile(dir, category);
|
|
139
|
-
const [rawRows, rawAnswers] = await Promise.all([readFile(dataPath, "utf8"), readFile(answersPath, "utf8")]);
|
|
140
|
-
const rows = readJsonl(rawRows);
|
|
141
|
-
const answers = readJsonl(rawAnswers);
|
|
142
|
-
return buildTasks(rows, answers, category, opts);
|
|
143
|
-
}
|
|
144
|
-
function extractJsonBlock(text) {
|
|
145
|
-
const fences = [...text.matchAll(/```(?:json)?\s*([\s\S]*?)```/g)];
|
|
146
|
-
const raw = (fences.at(-1)?.[1] ?? text).trim();
|
|
147
|
-
try {
|
|
148
|
-
return JSON.parse(raw);
|
|
149
|
-
} catch {
|
|
150
|
-
return void 0;
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
function normalizeArguments(value) {
|
|
154
|
-
if (typeof value === "string") {
|
|
155
|
-
try {
|
|
156
|
-
return normalizeArguments(JSON.parse(value));
|
|
157
|
-
} catch {
|
|
158
|
-
return {};
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) return {};
|
|
162
|
-
return value;
|
|
163
|
-
}
|
|
164
|
-
function callFromObject(value) {
|
|
165
|
-
if (!value || typeof value !== "object") return void 0;
|
|
166
|
-
const raw = value;
|
|
167
|
-
if (raw.function && typeof raw.function === "object") {
|
|
168
|
-
const fn = raw.function;
|
|
169
|
-
if (typeof fn.name === "string") return { name: fn.name, arguments: normalizeArguments(fn.arguments) };
|
|
170
|
-
}
|
|
171
|
-
const name = typeof raw.name === "string" ? raw.name : typeof raw.function_name === "string" ? raw.function_name : typeof raw.tool_name === "string" ? raw.tool_name : void 0;
|
|
172
|
-
if (!name) return void 0;
|
|
173
|
-
return { name, arguments: normalizeArguments(raw.arguments ?? raw.args ?? raw.parameters) };
|
|
174
|
-
}
|
|
175
|
-
function extractActualCalls(artifact) {
|
|
176
|
-
const parsed = extractJsonBlock(artifact);
|
|
177
|
-
if (Array.isArray(parsed)) return parsed.map(callFromObject).filter((call) => Boolean(call));
|
|
178
|
-
if (parsed && typeof parsed === "object") {
|
|
179
|
-
const raw = parsed;
|
|
180
|
-
for (const key of ["function_calls", "tool_calls", "calls"]) {
|
|
181
|
-
if (Array.isArray(raw[key])) {
|
|
182
|
-
return raw[key].map(callFromObject).filter((call) => Boolean(call));
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
const single = callFromObject(raw);
|
|
186
|
-
if (single) return [single];
|
|
187
|
-
}
|
|
188
|
-
return [];
|
|
189
|
-
}
|
|
190
|
-
function argMatches(expectedValues, actual) {
|
|
191
|
-
return expectedValues.some((expected) => normalizeScalar(expected) === normalizeScalar(actual));
|
|
192
|
-
}
|
|
193
|
-
function callMatches(expected, actual) {
|
|
194
|
-
if (expected.name !== actual.name) return false;
|
|
195
|
-
for (const [argName, allowed] of Object.entries(expected.arguments)) {
|
|
196
|
-
if (!(argName in actual.arguments)) {
|
|
197
|
-
if (allowed.some((value) => value === "" || value === null || value === void 0)) continue;
|
|
198
|
-
return false;
|
|
199
|
-
}
|
|
200
|
-
if (!argMatches(allowed, actual.arguments[argName])) return false;
|
|
201
|
-
}
|
|
202
|
-
return true;
|
|
203
|
-
}
|
|
204
|
-
function scoreCalls(task, artifact) {
|
|
205
|
-
const meta = readMeta(task);
|
|
206
|
-
const actual = extractActualCalls(artifact);
|
|
207
|
-
const used = /* @__PURE__ */ new Set();
|
|
208
|
-
let matched = 0;
|
|
209
|
-
for (const expected of meta.expected) {
|
|
210
|
-
const index = actual.findIndex((call, i) => !used.has(i) && callMatches(expected, call));
|
|
211
|
-
if (index >= 0) {
|
|
212
|
-
used.add(index);
|
|
213
|
-
matched += 1;
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
const recall = meta.expected.length === 0 ? 0 : matched / meta.expected.length;
|
|
217
|
-
const precision = actual.length === 0 ? 0 : matched / actual.length;
|
|
218
|
-
const score = recall;
|
|
219
|
-
return {
|
|
220
|
-
resolved: recall === 1 && precision === 1,
|
|
221
|
-
score,
|
|
222
|
-
detail: JSON.stringify({
|
|
223
|
-
scoring: meta.scoring,
|
|
224
|
-
category: meta.category,
|
|
225
|
-
expected: meta.expected,
|
|
226
|
-
actual,
|
|
227
|
-
precision,
|
|
228
|
-
recall,
|
|
229
|
-
fullBfclLeaderboardScore: null
|
|
230
|
-
})
|
|
231
|
-
};
|
|
232
|
-
}
|
|
233
|
-
function createBfclAdapter() {
|
|
234
|
-
const fixturesMode = process.env.BFCL_FIXTURES === "1";
|
|
235
|
-
return {
|
|
236
|
-
name: "bfcl",
|
|
237
|
-
output: bfclOutput,
|
|
238
|
-
async preflight() {
|
|
239
|
-
if (fixturesMode) return;
|
|
240
|
-
const dir = bfclDir();
|
|
241
|
-
if (!dir) {
|
|
242
|
-
throw new Error(
|
|
243
|
-
"BFCL_DIR is required. Fix: clone https://github.com/ShishirPatil/gorilla, set BFCL_DIR=/path/to/gorilla/berkeley-function-call-leaderboard, and optionally set BFCL_CATEGORY=BFCL_v4_simple_python."
|
|
244
|
-
);
|
|
245
|
-
}
|
|
246
|
-
const category = bfclCategory();
|
|
247
|
-
await assertPath(taskFile(dir, category), "BFCL task JSONL");
|
|
248
|
-
await assertPath(answerFile(dir, category), "BFCL possible_answer JSONL");
|
|
249
|
-
await loadOfficialTasks(dir, { limit: 1 });
|
|
250
|
-
},
|
|
251
|
-
async loadTasks(opts = {}) {
|
|
252
|
-
if (fixturesMode) return loadFixtures(opts);
|
|
253
|
-
const dir = bfclDir();
|
|
254
|
-
if (!dir) throw new Error("BFCL_DIR is required to load official BFCL rows");
|
|
255
|
-
return loadOfficialTasks(dir, opts);
|
|
256
|
-
},
|
|
257
|
-
async goldArtifact(task) {
|
|
258
|
-
const meta = readMeta(task);
|
|
259
|
-
return JSON.stringify({
|
|
260
|
-
function_calls: meta.expected.map((call) => ({
|
|
261
|
-
name: call.name,
|
|
262
|
-
arguments: Object.fromEntries(Object.entries(call.arguments).map(([key, values]) => [key, values[0]]))
|
|
263
|
-
}))
|
|
264
|
-
}, null, 2);
|
|
265
|
-
},
|
|
266
|
-
async judge(task, artifact) {
|
|
267
|
-
return scoreCalls(task, artifact);
|
|
268
|
-
}
|
|
269
|
-
};
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
export {
|
|
273
|
-
bfclOutput,
|
|
274
|
-
createBfclAdapter
|
|
275
|
-
};
|
|
276
|
-
//# sourceMappingURL=chunk-KP5KD6EN.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/benchmarks/bfcl.ts"],"sourcesContent":["/**\n * Berkeley Function Calling Leaderboard adapter.\n *\n * Scope: deterministic function-call ground-truth categories from the official\n * BFCL data files. This is NOT the full live BFCL leaderboard evaluator: agentic\n * web-search/memory categories and BFCL's own model-response harness remain\n * upstream responsibilities. The adapter loads official JSONL rows plus their\n * `possible_answer` file and scores structured function-call artifacts against\n * allowed function/argument values.\n */\n\nimport { readFile, stat } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport type { OutputAdapter } from '@tangle-network/agent-runtime/loops'\nimport { benchRoot } from './_harness'\nimport type { BenchmarkAdapter, BenchScore, BenchTask, LoadOptions } from './types'\n\nconst FIXTURES = join(benchRoot, 'fixtures', 'bfcl.json')\nconst DEFAULT_CATEGORY = 'BFCL_v4_simple_python'\n\ninterface BfclRow {\n id: string\n question: unknown\n function: unknown\n}\n\ninterface BfclAnswerRow {\n id: string\n ground_truth: unknown\n}\n\ninterface BfclAllowedCall {\n name: string\n arguments: Record<string, unknown[]>\n}\n\ninterface BfclMeta {\n rowId: string\n category: string\n functions: unknown\n expected: BfclAllowedCall[]\n scoring: 'bfcl-ground-truth-subset'\n}\n\ninterface BfclActualCall {\n name: string\n arguments: Record<string, unknown>\n}\n\nconst bfclDir = (): string | undefined => process.env.BFCL_DIR\nconst bfclCategory = (): string => process.env.BFCL_CATEGORY ?? DEFAULT_CATEGORY\n\nexport const bfclOutput: 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\nasync function assertPath(path: string, label: string): Promise<void> {\n try {\n await stat(path)\n } catch (err) {\n throw new Error(`BFCL: missing ${label} at ${path} (${err instanceof Error ? err.message : err})`)\n }\n}\n\nfunction readJsonl(raw: string): unknown[] {\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\nfunction taskFile(dir: string, category: string): string {\n return process.env.BFCL_DATA_FILE ?? join(dir, 'bfcl_eval', 'data', `${category}.json`)\n}\n\nfunction answerFile(dir: string, category: string): string {\n return process.env.BFCL_ANSWER_FILE ?? join(dir, 'bfcl_eval', 'data', 'possible_answer', `${category}.json`)\n}\n\nfunction questionText(question: unknown): string {\n if (typeof question === 'string') return question\n if (!Array.isArray(question)) return JSON.stringify(question, null, 2)\n const turns: string[] = []\n for (const item of question.flat(3)) {\n if (item && typeof item === 'object') {\n const role = typeof (item as { role?: unknown }).role === 'string' ? (item as { role: string }).role : 'user'\n const content = (item as { content?: unknown }).content\n if (typeof content === 'string') turns.push(`${role}: ${content}`)\n }\n }\n return turns.length > 0 ? turns.join('\\n') : JSON.stringify(question, null, 2)\n}\n\nfunction normalizeScalar(value: unknown): string {\n if (typeof value === 'number') return Number.isInteger(value) ? String(value) : String(Number(value.toFixed(8)))\n if (typeof value === 'string') return value.trim().toLowerCase()\n return JSON.stringify(value)\n}\n\nfunction normalizeAllowed(value: unknown): unknown[] {\n return Array.isArray(value) ? value : [value]\n}\n\nfunction groundTruthToCalls(value: unknown): BfclAllowedCall[] {\n if (!Array.isArray(value)) return []\n const out: BfclAllowedCall[] = []\n for (const item of value) {\n if (!item || typeof item !== 'object') continue\n for (const [name, args] of Object.entries(item as Record<string, unknown>)) {\n if (!args || typeof args !== 'object' || Array.isArray(args)) continue\n const normalized: Record<string, unknown[]> = {}\n for (const [argName, allowed] of Object.entries(args as Record<string, unknown>)) {\n normalized[argName] = normalizeAllowed(allowed)\n }\n out.push({ name, arguments: normalized })\n }\n }\n return out\n}\n\nfunction rowToTask(row: BfclRow, answer: BfclAnswerRow, category: string): BenchTask {\n const expected = groundTruthToCalls(answer.ground_truth)\n if (expected.length === 0) {\n throw new Error(`BFCL ${row.id}: possible_answer has no deterministic ground_truth calls`)\n }\n const meta: BfclMeta = {\n rowId: row.id,\n category,\n functions: row.function,\n expected,\n scoring: 'bfcl-ground-truth-subset',\n }\n return {\n id: row.id,\n split: category,\n prompt: [\n 'Solve this BFCL function-calling task.',\n 'Return only JSON: {\"function_calls\":[{\"name\":\"...\",\"arguments\":{...}}]}.',\n '',\n questionText(row.question),\n '',\n `Available functions: ${JSON.stringify(row.function, null, 2)}`,\n ].join('\\n'),\n metadata: meta as unknown as Record<string, unknown>,\n }\n}\n\nfunction readMeta(task: BenchTask): BfclMeta {\n const md = task.metadata\n if (!md || !Array.isArray(md.expected)) {\n throw new Error(`BFCL task ${task.id} missing expected calls — loadTasks did not populate metadata`)\n }\n return md as unknown as BfclMeta\n}\n\nfunction selectTasks(tasks: BenchTask[], opts: LoadOptions): BenchTask[] {\n let out = tasks\n if (opts.split) out = out.filter((task) => task.split === opts.split)\n if (opts.ids) {\n const want = new Set(opts.ids)\n out = out.filter((task) => want.has(task.id))\n } else if (opts.limit !== undefined) {\n out = out.slice(0, opts.limit)\n }\n if (out.length === 0) throw new Error(`BFCL: no tasks matched ${JSON.stringify(opts)}`)\n return out\n}\n\nfunction buildTasks(rows: BfclRow[], answers: BfclAnswerRow[], category: string, opts: LoadOptions): BenchTask[] {\n const byId = new Map(answers.map((answer) => [answer.id, answer]))\n const tasks = rows.map((row) => {\n const answer = byId.get(row.id)\n if (!answer) throw new Error(`BFCL ${category}: missing possible_answer for ${row.id}`)\n return rowToTask(row, answer, category)\n })\n return selectTasks(tasks, opts)\n}\n\nasync function loadFixtures(opts: LoadOptions): Promise<BenchTask[]> {\n const fixture = JSON.parse(await readFile(FIXTURES, 'utf8')) as { rows: BfclRow[]; answers: BfclAnswerRow[]; category: string }\n console.warn(`[bfcl] BFCL_FIXTURES=1 — loading ${fixture.rows.length} adapter fixtures`)\n return buildTasks(fixture.rows, fixture.answers, fixture.category, opts)\n}\n\nasync function loadOfficialTasks(dir: string, opts: LoadOptions): Promise<BenchTask[]> {\n const category = bfclCategory()\n const dataPath = taskFile(dir, category)\n const answersPath = answerFile(dir, category)\n const [rawRows, rawAnswers] = await Promise.all([readFile(dataPath, 'utf8'), readFile(answersPath, 'utf8')])\n const rows = readJsonl(rawRows) as BfclRow[]\n const answers = readJsonl(rawAnswers) as BfclAnswerRow[]\n return buildTasks(rows, answers, category, opts)\n}\n\nfunction extractJsonBlock(text: string): unknown {\n const fences = [...text.matchAll(/```(?:json)?\\s*([\\s\\S]*?)```/g)]\n const raw = (fences.at(-1)?.[1] ?? text).trim()\n try {\n return JSON.parse(raw)\n } catch {\n return undefined\n }\n}\n\nfunction normalizeArguments(value: unknown): Record<string, unknown> {\n if (typeof value === 'string') {\n try {\n return normalizeArguments(JSON.parse(value))\n } catch {\n return {}\n }\n }\n if (!value || typeof value !== 'object' || Array.isArray(value)) return {}\n return value as Record<string, unknown>\n}\n\nfunction callFromObject(value: unknown): BfclActualCall | undefined {\n if (!value || typeof value !== 'object') return undefined\n const raw = value as Record<string, unknown>\n if (raw.function && typeof raw.function === 'object') {\n const fn = raw.function as Record<string, unknown>\n if (typeof fn.name === 'string') return { name: fn.name, arguments: normalizeArguments(fn.arguments) }\n }\n const name =\n typeof raw.name === 'string' ? raw.name\n : typeof raw.function_name === 'string' ? raw.function_name\n : typeof raw.tool_name === 'string' ? raw.tool_name\n : undefined\n if (!name) return undefined\n return { name, arguments: normalizeArguments(raw.arguments ?? raw.args ?? raw.parameters) }\n}\n\nfunction extractActualCalls(artifact: string): BfclActualCall[] {\n const parsed = extractJsonBlock(artifact)\n if (Array.isArray(parsed)) return parsed.map(callFromObject).filter((call): call is BfclActualCall => Boolean(call))\n if (parsed && typeof parsed === 'object') {\n const raw = parsed as Record<string, unknown>\n for (const key of ['function_calls', 'tool_calls', 'calls']) {\n if (Array.isArray(raw[key])) {\n return raw[key].map(callFromObject).filter((call): call is BfclActualCall => Boolean(call))\n }\n }\n const single = callFromObject(raw)\n if (single) return [single]\n }\n return []\n}\n\nfunction argMatches(expectedValues: unknown[], actual: unknown): boolean {\n return expectedValues.some((expected) => normalizeScalar(expected) === normalizeScalar(actual))\n}\n\nfunction callMatches(expected: BfclAllowedCall, actual: BfclActualCall): boolean {\n if (expected.name !== actual.name) return false\n for (const [argName, allowed] of Object.entries(expected.arguments)) {\n if (!(argName in actual.arguments)) {\n if (allowed.some((value) => value === '' || value === null || value === undefined)) continue\n return false\n }\n if (!argMatches(allowed, actual.arguments[argName])) return false\n }\n return true\n}\n\nfunction scoreCalls(task: BenchTask, artifact: string): BenchScore {\n const meta = readMeta(task)\n const actual = extractActualCalls(artifact)\n const used = new Set<number>()\n let matched = 0\n for (const expected of meta.expected) {\n const index = actual.findIndex((call, i) => !used.has(i) && callMatches(expected, call))\n if (index >= 0) {\n used.add(index)\n matched += 1\n }\n }\n const recall = meta.expected.length === 0 ? 0 : matched / meta.expected.length\n const precision = actual.length === 0 ? 0 : matched / actual.length\n const score = recall\n return {\n resolved: recall === 1 && precision === 1,\n score,\n detail: JSON.stringify({\n scoring: meta.scoring,\n category: meta.category,\n expected: meta.expected,\n actual,\n precision,\n recall,\n fullBfclLeaderboardScore: null,\n }),\n }\n}\n\nexport function createBfclAdapter(): BenchmarkAdapter {\n const fixturesMode = process.env.BFCL_FIXTURES === '1'\n\n return {\n name: 'bfcl',\n output: bfclOutput,\n\n async preflight() {\n if (fixturesMode) return\n const dir = bfclDir()\n if (!dir) {\n throw new Error(\n 'BFCL_DIR is required. Fix: clone https://github.com/ShishirPatil/gorilla, set BFCL_DIR=/path/to/gorilla/berkeley-function-call-leaderboard, and optionally set BFCL_CATEGORY=BFCL_v4_simple_python.',\n )\n }\n const category = bfclCategory()\n await assertPath(taskFile(dir, category), 'BFCL task JSONL')\n await assertPath(answerFile(dir, category), 'BFCL possible_answer JSONL')\n await loadOfficialTasks(dir, { limit: 1 })\n },\n\n async loadTasks(opts: LoadOptions = {}) {\n if (fixturesMode) return loadFixtures(opts)\n const dir = bfclDir()\n if (!dir) throw new Error('BFCL_DIR is required to load official BFCL rows')\n return loadOfficialTasks(dir, opts)\n },\n\n async goldArtifact(task: BenchTask) {\n const meta = readMeta(task)\n return JSON.stringify({\n function_calls: meta.expected.map((call) => ({\n name: call.name,\n arguments: Object.fromEntries(Object.entries(call.arguments).map(([key, values]) => [key, values[0]])),\n })),\n }, null, 2)\n },\n\n async judge(task: BenchTask, artifact: string): Promise<BenchScore> {\n return scoreCalls(task, artifact)\n },\n }\n}\n"],"mappings":"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","names":[]}
|
package/dist/chunk-MQMRLGOG.js
DELETED
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
benchRoot,
|
|
3
|
-
preflightVenvImports,
|
|
4
|
-
runVenvScriptStdin
|
|
5
|
-
} from "./chunk-WSKWVEQB.js";
|
|
6
|
-
|
|
7
|
-
// src/benchmarks/programbench.ts
|
|
8
|
-
import { join } from "path";
|
|
9
|
-
import { readFile } from "fs/promises";
|
|
10
|
-
var FIXTURES = join(benchRoot, "fixtures", "programbench.json");
|
|
11
|
-
var TESTS_DATASET = "programbench/ProgramBench-Tests";
|
|
12
|
-
var TREE_API = `https://huggingface.co/api/datasets/${TESTS_DATASET}/tree/main`;
|
|
13
|
-
var PROMPT = [
|
|
14
|
-
"This is a cleanroom reverse-engineering task. You are given a compiled black-box `./executable` (run-only) and stripped documentation in the workspace.",
|
|
15
|
-
"Write an ORIGINAL codebase from scratch that, when built, produces an `./executable` with byte-for-byte identical observable behavior (stdout/stderr/exit codes/filesystem effects) to the original. You may run `./executable` to probe its behavior.",
|
|
16
|
-
"You MUST include a `./compile.sh` at the workspace root that builds your source into `./executable` at the workspace root.",
|
|
17
|
-
"Emit your COMPLETE submission as the LAST thing in your reply: one fenced block per file, each opening fence line being exactly ```path:<relative/path>``` followed by the file contents, then a closing fence. Include compile.sh and every source file. Nothing after the final closing fence."
|
|
18
|
-
].join("\n");
|
|
19
|
-
function fixtureToTask(f) {
|
|
20
|
-
const meta = { instanceId: f.instance_id, imageName: f.image_name };
|
|
21
|
-
return {
|
|
22
|
-
id: f.instance_id,
|
|
23
|
-
prompt: PROMPT,
|
|
24
|
-
metadata: meta
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
function readMeta(task) {
|
|
28
|
-
const md = task.metadata;
|
|
29
|
-
if (!md || typeof md.instanceId !== "string") {
|
|
30
|
-
throw new Error(`programbench task ${task.id} missing metadata.instanceId \u2014 loadTasks did not populate it`);
|
|
31
|
-
}
|
|
32
|
-
return md;
|
|
33
|
-
}
|
|
34
|
-
function selectTasks(fixtures, opts) {
|
|
35
|
-
let tasks = fixtures.map(fixtureToTask);
|
|
36
|
-
if (opts.ids) {
|
|
37
|
-
const want = new Set(opts.ids);
|
|
38
|
-
tasks = tasks.filter((t) => want.has(t.id));
|
|
39
|
-
} else if (opts.limit !== void 0) {
|
|
40
|
-
tasks = tasks.slice(0, opts.limit);
|
|
41
|
-
}
|
|
42
|
-
return tasks;
|
|
43
|
-
}
|
|
44
|
-
function imageName(instanceId) {
|
|
45
|
-
return instanceId.split(".")[0].replace("__", "/");
|
|
46
|
-
}
|
|
47
|
-
async function loadFixtures(opts) {
|
|
48
|
-
const fixtures = JSON.parse(await readFile(FIXTURES, "utf8"));
|
|
49
|
-
console.warn(
|
|
50
|
-
`[programbench] PROGRAMBENCH_FIXTURES=1 \u2014 loading ${fixtures.length} committed instance ids from ${FIXTURES} (no HF tree fetch)`
|
|
51
|
-
);
|
|
52
|
-
return selectTasks(fixtures, opts);
|
|
53
|
-
}
|
|
54
|
-
async function fetchInstanceIds() {
|
|
55
|
-
const res = await fetch(TREE_API);
|
|
56
|
-
if (!res.ok) throw new Error(`programbench tree HTTP ${res.status}: ${TREE_API}`);
|
|
57
|
-
const tree = await res.json();
|
|
58
|
-
const ids = tree.filter((e) => e.type === "directory" && e.path.includes("__")).map((e) => e.path);
|
|
59
|
-
if (ids.length === 0) throw new Error(`programbench: no instance dirs in ${TESTS_DATASET} tree`);
|
|
60
|
-
return ids.map((id) => ({ instance_id: id, image_name: imageName(id) }));
|
|
61
|
-
}
|
|
62
|
-
async function runHarness(meta, submission) {
|
|
63
|
-
const judge = join(benchRoot, "scripts", "programbench_judge.py");
|
|
64
|
-
let stdout;
|
|
65
|
-
try {
|
|
66
|
-
stdout = await runVenvScriptStdin(judge, ["--instance", meta.instanceId], submission, { cwd: benchRoot });
|
|
67
|
-
} catch (err) {
|
|
68
|
-
const e = err;
|
|
69
|
-
throw new Error(`programbench harness failed for ${meta.instanceId}: ${(e.message || String(err)).slice(0, 1500)}`);
|
|
70
|
-
}
|
|
71
|
-
const report = JSON.parse(stdout.trim().split("\n").at(-1) ?? "{}");
|
|
72
|
-
if (report.error) throw new Error(`programbench harness error for ${meta.instanceId}: ${report.error}`);
|
|
73
|
-
if (typeof report.passed !== "number" || typeof report.total !== "number") {
|
|
74
|
-
throw new Error(`programbench judge returned no {passed,total}: ${stdout.slice(0, 400)}`);
|
|
75
|
-
}
|
|
76
|
-
const score = report.total > 0 ? report.passed / report.total : 0;
|
|
77
|
-
return {
|
|
78
|
-
resolved: report.resolved ?? (report.total > 0 && report.passed === report.total),
|
|
79
|
-
score,
|
|
80
|
-
detail: JSON.stringify({ instanceId: meta.instanceId, passed: report.passed, total: report.total })
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
var programbenchSubmissionOutput = {
|
|
84
|
-
parse(events) {
|
|
85
|
-
let text = "";
|
|
86
|
-
for (const ev of events) {
|
|
87
|
-
const d = ev?.data;
|
|
88
|
-
const t = d?.finalText ?? d?.text ?? d?.result;
|
|
89
|
-
if (typeof t === "string" && t.length > 0) text = t;
|
|
90
|
-
}
|
|
91
|
-
const blocks = [...text.matchAll(/```path:([^\n`]+)\n([\s\S]*?)```/g)];
|
|
92
|
-
if (blocks.length === 0) return "";
|
|
93
|
-
return blocks.map((m) => `===FILE:${m[1].trim()}===
|
|
94
|
-
${m[2]}`).join("\n");
|
|
95
|
-
}
|
|
96
|
-
};
|
|
97
|
-
function createProgrambenchAdapter() {
|
|
98
|
-
const fixturesMode = process.env.PROGRAMBENCH_FIXTURES === "1";
|
|
99
|
-
return {
|
|
100
|
-
name: "programbench",
|
|
101
|
-
output: programbenchSubmissionOutput,
|
|
102
|
-
async preflight() {
|
|
103
|
-
await preflightVenvImports({
|
|
104
|
-
modules: ["programbench"],
|
|
105
|
-
requireDocker: true,
|
|
106
|
-
fix: `Fix: (1) python3 -m venv bench/.venv && bench/.venv/bin/pip install programbench ; (2) Docker on linux/amd64 (per-task <image>:task_cleanroom images; will NOT run on ARM) ; (3) HF access for the hidden test blobs (the driver runs \`programbench blob sync\`). Set PROGRAMBENCH_FIXTURES=1 to list the committed instance ids offline.`
|
|
107
|
-
});
|
|
108
|
-
},
|
|
109
|
-
async loadTasks(opts = {}) {
|
|
110
|
-
if (fixturesMode) return loadFixtures(opts);
|
|
111
|
-
let fixtures;
|
|
112
|
-
try {
|
|
113
|
-
fixtures = await fetchInstanceIds();
|
|
114
|
-
} catch (err) {
|
|
115
|
-
console.warn(
|
|
116
|
-
`[programbench] live tree fetch failed (${err instanceof Error ? err.message : err}); falling back to committed fixtures at ${FIXTURES}`
|
|
117
|
-
);
|
|
118
|
-
return loadFixtures(opts);
|
|
119
|
-
}
|
|
120
|
-
return selectTasks(fixtures, opts);
|
|
121
|
-
},
|
|
122
|
-
async goldArtifact() {
|
|
123
|
-
return void 0;
|
|
124
|
-
},
|
|
125
|
-
async judge(task, artifact) {
|
|
126
|
-
const meta = readMeta(task);
|
|
127
|
-
return runHarness(meta, artifact);
|
|
128
|
-
}
|
|
129
|
-
};
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
export {
|
|
133
|
-
programbenchSubmissionOutput,
|
|
134
|
-
createProgrambenchAdapter
|
|
135
|
-
};
|
|
136
|
-
//# sourceMappingURL=chunk-MQMRLGOG.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/benchmarks/programbench.ts"],"sourcesContent":["/**\n * ProgramBench adapter (facebookresearch/ProgramBench) — cleanroom\n * reverse-engineering: rebuild a black-box executable's behavior from scratch.\n * The agent is given only the gold `./executable` (run-only) + stripped docs and\n * must produce a `submission.tar.gz` whose `./compile.sh` builds an `./executable`\n * with identical observable behavior. Judge = the official `programbench`\n * harness: it extracts the submission, runs compile.sh in the per-task cleanroom\n * Docker image, then runs the HIDDEN behavioral pytest suites (pulled via\n * `programbench blob sync`). Score = fraction of non-ignored tests passed\n * (GRADED, applying the tests.json ignore mask); resolved = all non-ignored tests\n * pass. Fully deterministic — no LLM judge.\n *\n * OutputAdapter is stream-only, so the worker emits its codebase as fenced\n * `path:`-prefixed file blocks (including compile.sh); the adapter materializes\n * those into submission.tar.gz. Test execution is delegated to the real\n * `programbench eval`/`info` harness — pytest scoring + the ignore mask are NOT\n * reimplemented here.\n *\n * Requires for a live run: the bench `.venv` with `programbench` installed +\n * Docker on linux/amd64 (per-task `<image>:task_cleanroom` images) + HF access for\n * the hidden test blobs. For offline/CI listing set PROGRAMBENCH_FIXTURES=1 to load\n * the committed instance ids (bench/fixtures/programbench.json); judging still\n * needs the harness + Docker and fails loud without them — never a fabricated score.\n */\n\nimport { join } from 'node:path'\nimport { readFile } from 'node:fs/promises'\nimport type { OutputAdapter } from '@tangle-network/agent-runtime/loops'\nimport { benchRoot, preflightVenvImports, runVenvScriptStdin } from './_harness'\nimport type { BenchmarkAdapter, BenchScore, BenchTask, LoadOptions } from './types'\n\nconst FIXTURES = join(benchRoot, 'fixtures', 'programbench.json')\n\nconst TESTS_DATASET = 'programbench/ProgramBench-Tests'\nconst TREE_API = `https://huggingface.co/api/datasets/${TESTS_DATASET}/tree/main`\n\ninterface PbFixture {\n instance_id: string\n image_name: string\n note?: string\n}\n\ninterface PbMeta {\n instanceId: string\n imageName: string\n}\n\nconst PROMPT = [\n 'This is a cleanroom reverse-engineering task. You are given a compiled black-box `./executable` (run-only) and stripped documentation in the workspace.',\n 'Write an ORIGINAL codebase from scratch that, when built, produces an `./executable` with byte-for-byte identical observable behavior (stdout/stderr/exit codes/filesystem effects) to the original. You may run `./executable` to probe its behavior.',\n 'You MUST include a `./compile.sh` at the workspace root that builds your source into `./executable` at the workspace root.',\n 'Emit your COMPLETE submission as the LAST thing in your reply: one fenced block per file, each opening fence line being exactly ```path:<relative/path>``` followed by the file contents, then a closing fence. Include compile.sh and every source file. Nothing after the final closing fence.',\n].join('\\n')\n\nfunction fixtureToTask(f: PbFixture): BenchTask {\n const meta: PbMeta = { instanceId: f.instance_id, imageName: f.image_name }\n return {\n id: f.instance_id,\n prompt: PROMPT,\n metadata: meta as unknown as Record<string, unknown>,\n }\n}\n\nfunction readMeta(task: BenchTask): PbMeta {\n const md = task.metadata\n if (!md || typeof md.instanceId !== 'string') {\n throw new Error(`programbench task ${task.id} missing metadata.instanceId — loadTasks did not populate it`)\n }\n return md as unknown as PbMeta\n}\n\nfunction selectTasks(fixtures: PbFixture[], opts: LoadOptions): BenchTask[] {\n let tasks = fixtures.map(fixtureToTask)\n if (opts.ids) {\n const want = new Set(opts.ids)\n tasks = tasks.filter((t) => want.has(t.id))\n } else if (opts.limit !== undefined) {\n tasks = tasks.slice(0, opts.limit)\n }\n return tasks\n}\n\n/** `owner__repo.commit` → DockerHub image name `owner/repo` for `<image>:task_cleanroom`. */\nfunction imageName(instanceId: string): string {\n return instanceId.split('.')[0].replace('__', '/')\n}\n\nasync function loadFixtures(opts: LoadOptions): Promise<BenchTask[]> {\n const fixtures = JSON.parse(await readFile(FIXTURES, 'utf8')) as PbFixture[]\n console.warn(\n `[programbench] PROGRAMBENCH_FIXTURES=1 — loading ${fixtures.length} committed instance ids from ${FIXTURES} (no HF tree fetch)`,\n )\n return selectTasks(fixtures, opts)\n}\n\n/** Enumerate real instance ids from the HF Tests dataset tree (one dir per\n * instance). Throws on a non-OK response (fail loud). */\nasync function fetchInstanceIds(): Promise<PbFixture[]> {\n const res = await fetch(TREE_API)\n if (!res.ok) throw new Error(`programbench tree HTTP ${res.status}: ${TREE_API}`)\n const tree = (await res.json()) as Array<{ path: string; type: string }>\n const ids = tree.filter((e) => e.type === 'directory' && e.path.includes('__')).map((e) => e.path)\n if (ids.length === 0) throw new Error(`programbench: no instance dirs in ${TESTS_DATASET} tree`)\n return ids.map((id) => ({ instance_id: id, image_name: imageName(id) }))\n}\n\n/**\n * Run the official programbench harness for one instance over the worker's\n * file-manifest submission. The driver builds the run-dir layout (one folder\n * holding submission.tar.gz), runs `programbench blob sync` + `programbench eval`,\n * then parses <instance_id>.eval.json applying the tests.json ignore mask via\n * `programbench info` logic. Emits {passed,total,resolved} as the last stdout line.\n */\nasync function runHarness(meta: PbMeta, submission: string): Promise<BenchScore> {\n const judge = join(benchRoot, 'scripts', 'programbench_judge.py')\n let stdout: string\n try {\n // The submission manifest is piped to the driver's stdin via the shared\n // stdin-aware runner — execFile's `input` option is not honored async and\n // hangs the driver's sys.stdin.read() forever.\n stdout = await runVenvScriptStdin(judge, ['--instance', meta.instanceId], submission, { cwd: benchRoot })\n } catch (err) {\n const e = err as { message?: string }\n throw new Error(`programbench harness failed for ${meta.instanceId}: ${(e.message || String(err)).slice(0, 1500)}`)\n }\n const report = JSON.parse(stdout.trim().split('\\n').at(-1) ?? '{}') as {\n passed?: number\n total?: number\n resolved?: boolean\n error?: string\n }\n if (report.error) throw new Error(`programbench harness error for ${meta.instanceId}: ${report.error}`)\n if (typeof report.passed !== 'number' || typeof report.total !== 'number') {\n throw new Error(`programbench judge returned no {passed,total}: ${stdout.slice(0, 400)}`)\n }\n const score = report.total > 0 ? report.passed / report.total : 0\n return {\n resolved: report.resolved ?? (report.total > 0 && report.passed === report.total),\n score,\n detail: JSON.stringify({ instanceId: meta.instanceId, passed: report.passed, total: report.total }),\n }\n}\n\n/**\n * Parse the worker stream into the submission text the driver materializes: the\n * concatenation of every ```path:<p>``` fenced block. Passed through verbatim to\n * the python driver, which tars it. Empty when the worker emitted no file block\n * (fail-closed → the harness scores a missing compile.sh as 0).\n */\nexport const programbenchSubmissionOutput: 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 blocks = [...text.matchAll(/```path:([^\\n`]+)\\n([\\s\\S]*?)```/g)]\n if (blocks.length === 0) return ''\n // Re-serialize in the same path:<p> envelope the driver splits on.\n return blocks.map((m) => `===FILE:${m[1].trim()}===\\n${m[2]}`).join('\\n')\n },\n}\n\nexport function createProgrambenchAdapter(): BenchmarkAdapter {\n const fixturesMode = process.env.PROGRAMBENCH_FIXTURES === '1'\n\n return {\n name: 'programbench',\n output: programbenchSubmissionOutput,\n\n async preflight() {\n await preflightVenvImports({\n modules: ['programbench'],\n requireDocker: true,\n fix:\n `Fix: (1) python3 -m venv bench/.venv && bench/.venv/bin/pip install programbench ; ` +\n `(2) Docker on linux/amd64 (per-task <image>:task_cleanroom images; will NOT run on ARM) ; ` +\n `(3) HF access for the hidden test blobs (the driver runs \\`programbench blob sync\\`). ` +\n `Set PROGRAMBENCH_FIXTURES=1 to list the committed instance ids offline.`,\n })\n },\n\n async loadTasks(opts: LoadOptions = {}) {\n if (fixturesMode) return loadFixtures(opts)\n let fixtures: PbFixture[]\n try {\n fixtures = await fetchInstanceIds()\n } catch (err) {\n console.warn(\n `[programbench] live tree fetch failed (${err instanceof Error ? err.message : err}); falling back to committed fixtures at ${FIXTURES}`,\n )\n return loadFixtures(opts)\n }\n return selectTasks(fixtures, opts)\n },\n\n async goldArtifact() {\n // The oracle is the original repo's source (stripped from the task image),\n // not redistributable as a portable submission string. Judge correctness is\n // proven by running the real harness on a real solve, not a synthetic gold.\n return undefined\n },\n\n async judge(task: BenchTask, artifact: string): Promise<BenchScore> {\n const meta = readMeta(task)\n return runHarness(meta, artifact)\n },\n }\n}\n"],"mappings":"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","names":[]}
|
package/dist/chunk-NQG5XDSB.js
DELETED
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
contextBlock,
|
|
3
|
-
contextsFrom,
|
|
4
|
-
firstString,
|
|
5
|
-
isObject,
|
|
6
|
-
ragAnswerOutput,
|
|
7
|
-
readJsonRows,
|
|
8
|
-
selectTasks,
|
|
9
|
-
stringFrom
|
|
10
|
-
} from "./chunk-X3BTXCJ4.js";
|
|
11
|
-
import {
|
|
12
|
-
benchRoot
|
|
13
|
-
} from "./chunk-WSKWVEQB.js";
|
|
14
|
-
|
|
15
|
-
// src/benchmarks/nomiracl.ts
|
|
16
|
-
import { readFile } from "fs/promises";
|
|
17
|
-
import { join } from "path";
|
|
18
|
-
var FIXTURES = join(benchRoot, "fixtures", "nomiracl.json");
|
|
19
|
-
var dataFile = () => process.env.NOMIRACL_DATA_FILE;
|
|
20
|
-
function passagesFrom(value, relevant) {
|
|
21
|
-
return contextsFrom(value).map((context) => ({ ...context, relevant }));
|
|
22
|
-
}
|
|
23
|
-
function answerableFrom(raw, contexts) {
|
|
24
|
-
const direct = raw.answerable ?? raw.is_answerable ?? raw.has_answer ?? raw.label ?? raw.relevant;
|
|
25
|
-
if (typeof direct === "boolean") return direct;
|
|
26
|
-
if (typeof direct === "number") return direct > 0;
|
|
27
|
-
if (typeof direct === "string") {
|
|
28
|
-
const normalized = direct.toLowerCase();
|
|
29
|
-
if (["true", "t", "relevant", "answerable", "positive", "1", "yes"].includes(normalized)) return true;
|
|
30
|
-
if (["false", "f", "non-relevant", "non_relevant", "unanswerable", "negative", "0", "no"].includes(normalized)) {
|
|
31
|
-
return false;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
return contexts.some((context) => context.relevant === true);
|
|
35
|
-
}
|
|
36
|
-
function rowToTask(raw, index) {
|
|
37
|
-
if (!isObject(raw)) throw new Error(`NoMIRACL row ${index} must be an object`);
|
|
38
|
-
const query = firstString(raw, ["query", "question"]);
|
|
39
|
-
if (!query) throw new Error(`NoMIRACL row ${index} missing query`);
|
|
40
|
-
const labelledPassages = [
|
|
41
|
-
...passagesFrom(raw.positive_passages, true),
|
|
42
|
-
...passagesFrom(raw.negative_passages, false)
|
|
43
|
-
];
|
|
44
|
-
const contexts = labelledPassages.length > 0 ? labelledPassages : contextsFrom(raw.passages).length > 0 ? contextsFrom(raw.passages) : contextsFrom(raw.contexts).length > 0 ? contextsFrom(raw.contexts) : contextsFrom(raw.documents);
|
|
45
|
-
const answerable = answerableFrom(raw, contexts);
|
|
46
|
-
const language = stringFrom(raw.lang) ?? stringFrom(raw.language) ?? "unknown";
|
|
47
|
-
const subset = stringFrom(raw.subset) ?? (answerable ? "relevant" : "non-relevant");
|
|
48
|
-
const id = stringFrom(raw.id) ?? stringFrom(raw.query_id) ?? `nomiracl-${index}`;
|
|
49
|
-
const meta = {
|
|
50
|
-
benchmark: "nomiracl",
|
|
51
|
-
query,
|
|
52
|
-
answerable,
|
|
53
|
-
language,
|
|
54
|
-
subset,
|
|
55
|
-
contexts
|
|
56
|
-
};
|
|
57
|
-
return {
|
|
58
|
-
id,
|
|
59
|
-
split: stringFrom(raw.split) ?? language,
|
|
60
|
-
prompt: [
|
|
61
|
-
"Classify this NoMIRACL RAG relevance case.",
|
|
62
|
-
"Return exactly one word: ANSWERABLE if at least one supplied passage contains enough evidence to answer the query, otherwise UNANSWERABLE.",
|
|
63
|
-
"",
|
|
64
|
-
`Query: ${query}`,
|
|
65
|
-
contexts.length > 0 ? `
|
|
66
|
-
Passages:
|
|
67
|
-
${contextBlock(contexts)}` : void 0
|
|
68
|
-
].filter(Boolean).join("\n"),
|
|
69
|
-
metadata: meta
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
function readMeta(task) {
|
|
73
|
-
const md = task.metadata;
|
|
74
|
-
if (!md || typeof md.answerable !== "boolean") {
|
|
75
|
-
throw new Error(`NoMIRACL task ${task.id} missing metadata \u2014 loadTasks did not populate it`);
|
|
76
|
-
}
|
|
77
|
-
return md;
|
|
78
|
-
}
|
|
79
|
-
function parseClassification(artifact) {
|
|
80
|
-
const normalized = artifact.toLowerCase().replace(/[^a-z0-9]+/g, " ").trim();
|
|
81
|
-
if (/\bunanswerable\b|\bnot answerable\b|\bno answer\b|\bnegative\b|\bfalse\b/.test(normalized)) {
|
|
82
|
-
return false;
|
|
83
|
-
}
|
|
84
|
-
if (/\banswerable\b|\brelevant\b|\bpositive\b|\btrue\b|\byes\b/.test(normalized)) return true;
|
|
85
|
-
return null;
|
|
86
|
-
}
|
|
87
|
-
async function loadRows(path) {
|
|
88
|
-
const rows = await readJsonRows(path);
|
|
89
|
-
if (rows.length === 0) throw new Error(`NoMIRACL: no rows in ${path}`);
|
|
90
|
-
return rows;
|
|
91
|
-
}
|
|
92
|
-
async function loadFixtures(opts) {
|
|
93
|
-
const rows = JSON.parse(await readFile(FIXTURES, "utf8"));
|
|
94
|
-
console.warn(`[nomiracl] NOMIRACL_FIXTURES=1 \u2014 loading ${rows.length} adapter fixtures`);
|
|
95
|
-
return selectTasks(rows.map(rowToTask), opts, "NoMIRACL");
|
|
96
|
-
}
|
|
97
|
-
function createNoMiraclAdapter() {
|
|
98
|
-
const fixturesMode = process.env.NOMIRACL_FIXTURES === "1";
|
|
99
|
-
return {
|
|
100
|
-
name: "nomiracl",
|
|
101
|
-
output: ragAnswerOutput,
|
|
102
|
-
async preflight() {
|
|
103
|
-
if (fixturesMode) {
|
|
104
|
-
await readFile(FIXTURES, "utf8");
|
|
105
|
-
return;
|
|
106
|
-
}
|
|
107
|
-
const path = dataFile();
|
|
108
|
-
if (!path) {
|
|
109
|
-
throw new Error(
|
|
110
|
-
"NOMIRACL_DATA_FILE is required. Fix: export project-miracl/nomiracl rows to JSONL and set NOMIRACL_DATA_FILE=/path/to/nomiracl.jsonl, or set NOMIRACL_FIXTURES=1 for adapter plumbing."
|
|
111
|
-
);
|
|
112
|
-
}
|
|
113
|
-
await loadRows(path);
|
|
114
|
-
},
|
|
115
|
-
async loadTasks(opts = {}) {
|
|
116
|
-
if (fixturesMode) return loadFixtures(opts);
|
|
117
|
-
const path = dataFile();
|
|
118
|
-
if (!path) throw new Error("NOMIRACL_DATA_FILE is required to load NoMIRACL tasks");
|
|
119
|
-
return selectTasks((await loadRows(path)).map(rowToTask), opts, "NoMIRACL");
|
|
120
|
-
},
|
|
121
|
-
async goldArtifact(task) {
|
|
122
|
-
return readMeta(task).answerable ? "ANSWERABLE" : "UNANSWERABLE";
|
|
123
|
-
},
|
|
124
|
-
async judge(task, artifact) {
|
|
125
|
-
const meta = readMeta(task);
|
|
126
|
-
const got = parseClassification(artifact);
|
|
127
|
-
const resolved = got === meta.answerable;
|
|
128
|
-
return {
|
|
129
|
-
resolved,
|
|
130
|
-
score: resolved ? 1 : 0,
|
|
131
|
-
detail: JSON.stringify({
|
|
132
|
-
benchmark: meta.benchmark,
|
|
133
|
-
language: meta.language,
|
|
134
|
-
subset: meta.subset,
|
|
135
|
-
expected: meta.answerable ? "ANSWERABLE" : "UNANSWERABLE",
|
|
136
|
-
got: got === null ? null : got ? "ANSWERABLE" : "UNANSWERABLE",
|
|
137
|
-
contextCount: meta.contexts.length
|
|
138
|
-
})
|
|
139
|
-
};
|
|
140
|
-
}
|
|
141
|
-
};
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
export {
|
|
145
|
-
createNoMiraclAdapter
|
|
146
|
-
};
|
|
147
|
-
//# sourceMappingURL=chunk-NQG5XDSB.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/benchmarks/nomiracl.ts"],"sourcesContent":["/**\n * NoMIRACL adapter.\n *\n * NoMIRACL tests robustness to irrelevant retrieved passages. The worker does\n * not generate an answer here; it classifies whether the supplied passages\n * contain enough evidence to answer the query. This directly measures false\n * positive / false negative behavior for RAG abstention.\n */\n\nimport { readFile } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport { benchRoot } from './_harness'\nimport type { BenchmarkAdapter, BenchScore, BenchTask, LoadOptions } from './types'\nimport {\n contextBlock,\n contextsFrom,\n firstString,\n isObject,\n ragAnswerOutput,\n readJsonRows,\n selectTasks,\n stringFrom,\n type RagContext,\n} from './rag-shared'\n\nconst FIXTURES = join(benchRoot, 'fixtures', 'nomiracl.json')\n\ninterface NoMiraclMeta {\n benchmark: 'nomiracl'\n query: string\n answerable: boolean\n language: string\n subset: string\n contexts: RagContext[]\n}\n\nconst dataFile = (): string | undefined => process.env.NOMIRACL_DATA_FILE\n\nfunction passagesFrom(value: unknown, relevant: boolean): RagContext[] {\n return contextsFrom(value).map((context) => ({ ...context, relevant }))\n}\n\nfunction answerableFrom(raw: Record<string, unknown>, contexts: readonly RagContext[]): boolean {\n const direct = raw.answerable ?? raw.is_answerable ?? raw.has_answer ?? raw.label ?? raw.relevant\n if (typeof direct === 'boolean') return direct\n if (typeof direct === 'number') return direct > 0\n if (typeof direct === 'string') {\n const normalized = direct.toLowerCase()\n if (['true', 't', 'relevant', 'answerable', 'positive', '1', 'yes'].includes(normalized)) return true\n if (['false', 'f', 'non-relevant', 'non_relevant', 'unanswerable', 'negative', '0', 'no'].includes(normalized)) {\n return false\n }\n }\n return contexts.some((context) => context.relevant === true)\n}\n\nfunction rowToTask(raw: unknown, index: number): BenchTask {\n if (!isObject(raw)) throw new Error(`NoMIRACL row ${index} must be an object`)\n const query = firstString(raw, ['query', 'question'])\n if (!query) throw new Error(`NoMIRACL row ${index} missing query`)\n const labelledPassages = [\n ...passagesFrom(raw.positive_passages, true),\n ...passagesFrom(raw.negative_passages, false),\n ]\n const contexts =\n labelledPassages.length > 0\n ? labelledPassages\n : contextsFrom(raw.passages).length > 0\n ? contextsFrom(raw.passages)\n : contextsFrom(raw.contexts).length > 0\n ? contextsFrom(raw.contexts)\n : contextsFrom(raw.documents)\n const answerable = answerableFrom(raw, contexts)\n const language = stringFrom(raw.lang) ?? stringFrom(raw.language) ?? 'unknown'\n const subset = stringFrom(raw.subset) ?? (answerable ? 'relevant' : 'non-relevant')\n const id = stringFrom(raw.id) ?? stringFrom(raw.query_id) ?? `nomiracl-${index}`\n const meta: NoMiraclMeta = {\n benchmark: 'nomiracl',\n query,\n answerable,\n language,\n subset,\n contexts,\n }\n return {\n id,\n split: stringFrom(raw.split) ?? language,\n prompt: [\n 'Classify this NoMIRACL RAG relevance case.',\n 'Return exactly one word: ANSWERABLE if at least one supplied passage contains enough evidence to answer the query, otherwise UNANSWERABLE.',\n '',\n `Query: ${query}`,\n contexts.length > 0 ? `\\nPassages:\\n${contextBlock(contexts)}` : undefined,\n ]\n .filter(Boolean)\n .join('\\n'),\n metadata: meta as unknown as Record<string, unknown>,\n }\n}\n\nfunction readMeta(task: BenchTask): NoMiraclMeta {\n const md = task.metadata\n if (!md || typeof md.answerable !== 'boolean') {\n throw new Error(`NoMIRACL task ${task.id} missing metadata — loadTasks did not populate it`)\n }\n return md as unknown as NoMiraclMeta\n}\n\nfunction parseClassification(artifact: string): boolean | null {\n const normalized = artifact.toLowerCase().replace(/[^a-z0-9]+/g, ' ').trim()\n if (/\\bunanswerable\\b|\\bnot answerable\\b|\\bno answer\\b|\\bnegative\\b|\\bfalse\\b/.test(normalized)) {\n return false\n }\n if (/\\banswerable\\b|\\brelevant\\b|\\bpositive\\b|\\btrue\\b|\\byes\\b/.test(normalized)) return true\n return null\n}\n\nasync function loadRows(path: string): Promise<unknown[]> {\n const rows = await readJsonRows(path)\n if (rows.length === 0) throw new Error(`NoMIRACL: no rows in ${path}`)\n return rows\n}\n\nasync function loadFixtures(opts: LoadOptions): Promise<BenchTask[]> {\n const rows = JSON.parse(await readFile(FIXTURES, 'utf8')) as unknown[]\n console.warn(`[nomiracl] NOMIRACL_FIXTURES=1 — loading ${rows.length} adapter fixtures`)\n return selectTasks(rows.map(rowToTask), opts, 'NoMIRACL')\n}\n\nexport function createNoMiraclAdapter(): BenchmarkAdapter {\n const fixturesMode = process.env.NOMIRACL_FIXTURES === '1'\n\n return {\n name: 'nomiracl',\n output: ragAnswerOutput,\n\n async preflight() {\n if (fixturesMode) {\n await readFile(FIXTURES, 'utf8')\n return\n }\n const path = dataFile()\n if (!path) {\n throw new Error(\n 'NOMIRACL_DATA_FILE is required. Fix: export project-miracl/nomiracl rows to JSONL and set NOMIRACL_DATA_FILE=/path/to/nomiracl.jsonl, or set NOMIRACL_FIXTURES=1 for adapter plumbing.',\n )\n }\n await loadRows(path)\n },\n\n async loadTasks(opts: LoadOptions = {}) {\n if (fixturesMode) return loadFixtures(opts)\n const path = dataFile()\n if (!path) throw new Error('NOMIRACL_DATA_FILE is required to load NoMIRACL tasks')\n return selectTasks((await loadRows(path)).map(rowToTask), opts, 'NoMIRACL')\n },\n\n async goldArtifact(task: BenchTask) {\n return readMeta(task).answerable ? 'ANSWERABLE' : 'UNANSWERABLE'\n },\n\n async judge(task: BenchTask, artifact: string): Promise<BenchScore> {\n const meta = readMeta(task)\n const got = parseClassification(artifact)\n const resolved = got === meta.answerable\n return {\n resolved,\n score: resolved ? 1 : 0,\n detail: JSON.stringify({\n benchmark: meta.benchmark,\n language: meta.language,\n subset: meta.subset,\n expected: meta.answerable ? 'ANSWERABLE' : 'UNANSWERABLE',\n got: got === null ? null : got ? 'ANSWERABLE' : 'UNANSWERABLE',\n contextCount: meta.contexts.length,\n }),\n }\n },\n }\n}\n"],"mappings":"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","names":[]}
|