@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,10 +1,265 @@
1
- import {
2
- bfclOutput,
3
- createBfclAdapter
4
- } from "../chunk-KP5KD6EN.js";
5
- import "../chunk-WSKWVEQB.js";
6
- export {
7
- bfclOutput,
8
- createBfclAdapter
9
- };
1
+ import { benchRoot } from "./_harness.js";
2
+ import { readFile, stat } from "node:fs/promises";
3
+ import { join } from "node:path";
4
+ //#region src/benchmarks/bfcl.ts
5
+ /**
6
+ * Berkeley Function Calling Leaderboard adapter.
7
+ *
8
+ * Scope: deterministic function-call ground-truth categories from the official
9
+ * BFCL data files. This is NOT the full live BFCL leaderboard evaluator: agentic
10
+ * web-search/memory categories and BFCL's own model-response harness remain
11
+ * upstream responsibilities. The adapter loads official JSONL rows plus their
12
+ * `possible_answer` file and scores structured function-call artifacts against
13
+ * allowed function/argument values.
14
+ */
15
+ const FIXTURES = join(benchRoot, "fixtures", "bfcl.json");
16
+ const DEFAULT_CATEGORY = "BFCL_v4_simple_python";
17
+ const bfclDir = () => process.env.BFCL_DIR;
18
+ const bfclCategory = () => process.env.BFCL_CATEGORY ?? DEFAULT_CATEGORY;
19
+ const bfclOutput = { parse(events) {
20
+ let text = "";
21
+ for (const ev of events) {
22
+ const d = ev?.data;
23
+ const t = d?.finalText ?? d?.text ?? d?.result;
24
+ if (typeof t === "string" && t.length > 0) text = t;
25
+ }
26
+ return text.trim();
27
+ } };
28
+ async function assertPath(path, label) {
29
+ try {
30
+ await stat(path);
31
+ } catch (err) {
32
+ throw new Error(`BFCL: missing ${label} at ${path} (${err instanceof Error ? err.message : err})`);
33
+ }
34
+ }
35
+ function readJsonl(raw) {
36
+ return raw.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0).map((line) => JSON.parse(line));
37
+ }
38
+ function taskFile(dir, category) {
39
+ return process.env.BFCL_DATA_FILE ?? join(dir, "bfcl_eval", "data", `${category}.json`);
40
+ }
41
+ function answerFile(dir, category) {
42
+ return process.env.BFCL_ANSWER_FILE ?? join(dir, "bfcl_eval", "data", "possible_answer", `${category}.json`);
43
+ }
44
+ function questionText(question) {
45
+ if (typeof question === "string") return question;
46
+ if (!Array.isArray(question)) return JSON.stringify(question, null, 2);
47
+ const turns = [];
48
+ for (const item of question.flat(3)) if (item && typeof item === "object") {
49
+ const role = typeof item.role === "string" ? item.role : "user";
50
+ const content = item.content;
51
+ if (typeof content === "string") turns.push(`${role}: ${content}`);
52
+ }
53
+ return turns.length > 0 ? turns.join("\n") : JSON.stringify(question, null, 2);
54
+ }
55
+ function normalizeScalar(value) {
56
+ if (typeof value === "number") return Number.isInteger(value) ? String(value) : String(Number(value.toFixed(8)));
57
+ if (typeof value === "string") return value.trim().toLowerCase();
58
+ return JSON.stringify(value);
59
+ }
60
+ function normalizeAllowed(value) {
61
+ return Array.isArray(value) ? value : [value];
62
+ }
63
+ function groundTruthToCalls(value) {
64
+ if (!Array.isArray(value)) return [];
65
+ const out = [];
66
+ for (const item of value) {
67
+ if (!item || typeof item !== "object") continue;
68
+ for (const [name, args] of Object.entries(item)) {
69
+ if (!args || typeof args !== "object" || Array.isArray(args)) continue;
70
+ const normalized = {};
71
+ for (const [argName, allowed] of Object.entries(args)) normalized[argName] = normalizeAllowed(allowed);
72
+ out.push({
73
+ name,
74
+ arguments: normalized
75
+ });
76
+ }
77
+ }
78
+ return out;
79
+ }
80
+ function rowToTask(row, answer, category) {
81
+ const expected = groundTruthToCalls(answer.ground_truth);
82
+ if (expected.length === 0) throw new Error(`BFCL ${row.id}: possible_answer has no deterministic ground_truth calls`);
83
+ const meta = {
84
+ rowId: row.id,
85
+ category,
86
+ functions: row.function,
87
+ expected,
88
+ scoring: "bfcl-ground-truth-subset"
89
+ };
90
+ return {
91
+ id: row.id,
92
+ split: category,
93
+ prompt: [
94
+ "Solve this BFCL function-calling task.",
95
+ "Return only JSON: {\"function_calls\":[{\"name\":\"...\",\"arguments\":{...}}]}.",
96
+ "",
97
+ questionText(row.question),
98
+ "",
99
+ `Available functions: ${JSON.stringify(row.function, null, 2)}`
100
+ ].join("\n"),
101
+ metadata: meta
102
+ };
103
+ }
104
+ function readMeta(task) {
105
+ const md = task.metadata;
106
+ if (!md || !Array.isArray(md.expected)) throw new Error(`BFCL task ${task.id} missing expected calls — loadTasks did not populate metadata`);
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) out = out.slice(0, opts.limit);
116
+ if (out.length === 0) throw new Error(`BFCL: no tasks matched ${JSON.stringify(opts)}`);
117
+ return out;
118
+ }
119
+ function buildTasks(rows, answers, category, opts) {
120
+ const byId = new Map(answers.map((answer) => [answer.id, answer]));
121
+ return selectTasks(rows.map((row) => {
122
+ const answer = byId.get(row.id);
123
+ if (!answer) throw new Error(`BFCL ${category}: missing possible_answer for ${row.id}`);
124
+ return rowToTask(row, answer, category);
125
+ }), opts);
126
+ }
127
+ async function loadFixtures(opts) {
128
+ const fixture = JSON.parse(await readFile(FIXTURES, "utf8"));
129
+ console.warn(`[bfcl] BFCL_FIXTURES=1 — loading ${fixture.rows.length} adapter fixtures`);
130
+ return buildTasks(fixture.rows, fixture.answers, fixture.category, opts);
131
+ }
132
+ async function loadOfficialTasks(dir, opts) {
133
+ const category = bfclCategory();
134
+ const dataPath = taskFile(dir, category);
135
+ const answersPath = answerFile(dir, category);
136
+ const [rawRows, rawAnswers] = await Promise.all([readFile(dataPath, "utf8"), readFile(answersPath, "utf8")]);
137
+ return buildTasks(readJsonl(rawRows), readJsonl(rawAnswers), category, opts);
138
+ }
139
+ function extractJsonBlock(text) {
140
+ const raw = ([...text.matchAll(/```(?:json)?\s*([\s\S]*?)```/g)].at(-1)?.[1] ?? text).trim();
141
+ try {
142
+ return JSON.parse(raw);
143
+ } catch {
144
+ return;
145
+ }
146
+ }
147
+ function normalizeArguments(value) {
148
+ if (typeof value === "string") try {
149
+ return normalizeArguments(JSON.parse(value));
150
+ } catch {
151
+ return {};
152
+ }
153
+ if (!value || typeof value !== "object" || Array.isArray(value)) return {};
154
+ return value;
155
+ }
156
+ function callFromObject(value) {
157
+ if (!value || typeof value !== "object") return void 0;
158
+ const raw = value;
159
+ if (raw.function && typeof raw.function === "object") {
160
+ const fn = raw.function;
161
+ if (typeof fn.name === "string") return {
162
+ name: fn.name,
163
+ arguments: normalizeArguments(fn.arguments)
164
+ };
165
+ }
166
+ 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;
167
+ if (!name) return void 0;
168
+ return {
169
+ name,
170
+ arguments: normalizeArguments(raw.arguments ?? raw.args ?? raw.parameters)
171
+ };
172
+ }
173
+ function extractActualCalls(artifact) {
174
+ const parsed = extractJsonBlock(artifact);
175
+ if (Array.isArray(parsed)) return parsed.map(callFromObject).filter((call) => Boolean(call));
176
+ if (parsed && typeof parsed === "object") {
177
+ const raw = parsed;
178
+ for (const key of [
179
+ "function_calls",
180
+ "tool_calls",
181
+ "calls"
182
+ ]) if (Array.isArray(raw[key])) return raw[key].map(callFromObject).filter((call) => Boolean(call));
183
+ const single = callFromObject(raw);
184
+ if (single) return [single];
185
+ }
186
+ return [];
187
+ }
188
+ function argMatches(expectedValues, actual) {
189
+ return expectedValues.some((expected) => normalizeScalar(expected) === normalizeScalar(actual));
190
+ }
191
+ function callMatches(expected, actual) {
192
+ if (expected.name !== actual.name) return false;
193
+ for (const [argName, allowed] of Object.entries(expected.arguments)) {
194
+ if (!(argName in actual.arguments)) {
195
+ if (allowed.some((value) => value === "" || value === null || value === void 0)) continue;
196
+ return false;
197
+ }
198
+ if (!argMatches(allowed, actual.arguments[argName])) return false;
199
+ }
200
+ return true;
201
+ }
202
+ function scoreCalls(task, artifact) {
203
+ const meta = readMeta(task);
204
+ const actual = extractActualCalls(artifact);
205
+ const used = /* @__PURE__ */ new Set();
206
+ let matched = 0;
207
+ for (const expected of meta.expected) {
208
+ const index = actual.findIndex((call, i) => !used.has(i) && callMatches(expected, call));
209
+ if (index >= 0) {
210
+ used.add(index);
211
+ matched += 1;
212
+ }
213
+ }
214
+ const recall = meta.expected.length === 0 ? 0 : matched / meta.expected.length;
215
+ const precision = actual.length === 0 ? 0 : matched / actual.length;
216
+ return {
217
+ resolved: recall === 1 && precision === 1,
218
+ score: recall,
219
+ detail: JSON.stringify({
220
+ scoring: meta.scoring,
221
+ category: meta.category,
222
+ expected: meta.expected,
223
+ actual,
224
+ precision,
225
+ recall,
226
+ fullBfclLeaderboardScore: null
227
+ })
228
+ };
229
+ }
230
+ function createBfclAdapter() {
231
+ const fixturesMode = process.env.BFCL_FIXTURES === "1";
232
+ return {
233
+ name: "bfcl",
234
+ output: bfclOutput,
235
+ async preflight() {
236
+ if (fixturesMode) return;
237
+ const dir = bfclDir();
238
+ if (!dir) throw new Error("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.");
239
+ const category = bfclCategory();
240
+ await assertPath(taskFile(dir, category), "BFCL task JSONL");
241
+ await assertPath(answerFile(dir, category), "BFCL possible_answer JSONL");
242
+ await loadOfficialTasks(dir, { limit: 1 });
243
+ },
244
+ async loadTasks(opts = {}) {
245
+ if (fixturesMode) return loadFixtures(opts);
246
+ const dir = bfclDir();
247
+ if (!dir) throw new Error("BFCL_DIR is required to load official BFCL rows");
248
+ return loadOfficialTasks(dir, opts);
249
+ },
250
+ async goldArtifact(task) {
251
+ const meta = readMeta(task);
252
+ return JSON.stringify({ function_calls: meta.expected.map((call) => ({
253
+ name: call.name,
254
+ arguments: Object.fromEntries(Object.entries(call.arguments).map(([key, values]) => [key, values[0]]))
255
+ })) }, null, 2);
256
+ },
257
+ async judge(task, artifact) {
258
+ return scoreCalls(task, artifact);
259
+ }
260
+ };
261
+ }
262
+ //#endregion
263
+ export { bfclOutput, createBfclAdapter };
264
+
10
265
  //# sourceMappingURL=bfcl.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
1
+ {"version":3,"file":"bfcl.js","names":[],"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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"}
@@ -1,45 +1,20 @@
1
- import { BenchmarkAdapter } from './types.js';
2
- import '@tangle-network/agent-runtime/loops';
3
-
4
- /**
5
- * CAD-Design adapter. Worker artifact = OpenSCAD source (`.scad`). Judge = the
6
- * REAL OpenSCAD engine: compile + export STL, then measure the produced solid
7
- * geometry against the task's spec. Fully deterministic — the authoritative CAD
8
- * kernel is the gate, not an LLM and not the agent's own claim.
9
- *
10
- * This is verifiable-reward CAD: an agent is far better at *writing* exact
11
- * parametric code than at clicking a GUI, and the kernel either produces the
12
- * specified geometry or it doesn't. Every judged artifact also renders a PNG,
13
- * so a refine loop's attempts become a watchable "model getting better" reel
14
- * (run-capsule consumes the renders).
15
- *
16
- * Spec checks are geometric and ungameable:
17
- * - compiles : `openscad -o out.stl` exits 0 (hard gate)
18
- * - volumes : disconnected-solid count within [min,max]
19
- * - bbox : overall X/Y/Z extent within bounds (the thing is the right size)
20
- * - detail : triangle count ≥ floor (not a degenerate single cube)
21
- * - pitchedRoof : the top band's XY footprint NARROWS vs the base — a flat
22
- * box can't fake this; a real gabled/hipped roof tapers
23
- * - hollow : interior cavity present (walls, not a solid block) — the
24
- * bbox volume materially exceeds the printed solid volume
25
- *
26
- * Requires only `openscad` + `xvfb-run` on PATH (no venv, no Docker, no network).
27
- */
28
-
1
+ import { BenchmarkAdapter } from "./types.js";
2
+ //#region src/benchmarks/cad-design.d.ts
29
3
  /** Spec assertions a CAD task can require. All are deterministic + geometric. */
30
4
  interface CadSpec {
31
- volumes?: [number, number];
32
- bbox?: {
33
- x?: [number, number];
34
- y?: [number, number];
35
- z?: [number, number];
36
- };
37
- minTriangles?: number;
38
- /** Top-band XY footprint must be < this fraction of the base footprint. */
39
- pitchedRoof?: number;
40
- /** Printed solid volume must be < this fraction of the bbox volume (hollow). */
41
- hollowBelow?: number;
5
+ volumes?: [number, number];
6
+ bbox?: {
7
+ x?: [number, number];
8
+ y?: [number, number];
9
+ z?: [number, number];
10
+ };
11
+ minTriangles?: number;
12
+ /** Top-band XY footprint must be < this fraction of the base footprint. */
13
+ pitchedRoof?: number;
14
+ /** Printed solid volume must be < this fraction of the bbox volume (hollow). */
15
+ hollowBelow?: number;
42
16
  }
43
17
  declare function createCadDesignAdapter(): BenchmarkAdapter;
44
-
45
- export { type CadSpec, createCadDesignAdapter };
18
+ //#endregion
19
+ export { CadSpec, createCadDesignAdapter };
20
+ //# sourceMappingURL=cad-design.d.ts.map