@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 +0,0 @@
1
- {"version":3,"sources":["../src/benchmarks/appworld.ts"],"sourcesContent":["/**\n * AppWorld adapter (StonyBrookNLP/appworld). Worker artifact = the agent's\n * Python solution that calls the simulated apps' APIs (the same `apis.<app>.<fn>`\n * surface AppWorld exposes inside `world.execute(...)`), ending in\n * `apis.supervisor.complete_task()`. Judge = AppWorld's OWN programmatic\n * evaluator: a driver runs the solution in a fresh `AppWorld(task_id=...)` world,\n * then `world.evaluate().to_dict()` reports `success` (binary TGC), `num_tests`\n * (per-requirement total) and the `passes`/`failures` lists. Score =\n * passes / num_tests — GRADED; resolved = success. Fully deterministic — no LLM judge.\n *\n * loadTasks enumerates the real task suite via `load_task_ids(split)`\n * (train|dev|test_normal|test_challenge); the prompt = `world.task.instruction`.\n * The OutputAdapter is stream-only, so the worker emits its solution as a fenced\n * ```python block which the driver executes.\n *\n * Requires for a live run: the bench `.venv` with `appworld` installed + the\n * unpacked engine + downloaded data (`appworld install` ; `appworld download\n * data`). preflight + loadTasks + judge all fail loud with the exact step when the\n * engine/data is absent — never a fabricated score.\n */\n\nimport { spawn } from 'node:child_process'\nimport { join } from 'node:path'\nimport { createInterface } from 'node:readline'\nimport { type OutputAdapter, routerToolLoop, type ToolSpec } from '@tangle-network/agent-runtime/loops'\nimport { benchRoot, preflightVenvImports, runVenvScriptStdin, venvPython } from './_harness'\nimport type { BenchmarkAdapter, BenchScore, BenchTask, LoadOptions } from './types'\n\nconst DRIVER = join(benchRoot, 'scripts', 'appworld_driver.py')\n\n/** AppWorld splits; only the test splits ship evaluation-only (no setup/solution). */\nconst DEFAULT_SPLIT = 'test_normal'\n\ninterface AppWorldMeta {\n taskId: string\n split: string\n}\n\n/** Worker solution code = the last fenced ```python block, else the raw text. */\nexport const appworldSolutionOutput: OutputAdapter<string> = {\n parse(events) {\n let text = ''\n for (const ev of events) {\n const d = (ev as { data?: Record<string, unknown> })?.data\n const t = d?.finalText ?? d?.text ?? d?.result\n if (typeof t === 'string' && t.length > 0) text = t\n }\n const fences = [...text.matchAll(/```(?:python|py)?\\s*\\n([\\s\\S]*?)```/g)]\n return (fences.at(-1)?.[1] ?? text).trim()\n },\n}\n\nconst WORKER_CONTRACT = [\n '',\n 'Solve this by writing Python that calls the available app APIs (the `apis.<app>.<function>(...)` surface). You may inspect API docs with `apis.api_docs.show_api_descriptions(app_name=...)` and `apis.api_docs.show_api_doc(app_name=..., api_name=...)`.',\n 'Authenticate where needed via the supervisor-provided credentials, perform every step the task requires, and FINISH with `apis.supervisor.complete_task()`.',\n 'Emit your COMPLETE solution as the LAST thing in your reply, in a single fenced ```python block. Nothing after the closing fence.',\n].join('\\n')\n\nfunction readMeta(task: BenchTask): AppWorldMeta {\n const md = task.metadata\n if (!md || typeof md.taskId !== 'string') {\n throw new Error(`appworld task ${task.id} missing metadata.taskId — loadTasks did not populate it`)\n }\n return md as unknown as AppWorldMeta\n}\n\n/**\n * Run the appworld engine driver with a subcommand; JSON on the LAST stdout line.\n * The solution code (evaluate) is piped to stdin via the shared stdin-aware runner —\n * execFile's `input` option is not honored async and hangs the driver's\n * sys.stdin.read() forever. `load` ignores stdin, so an empty pipe is harmless.\n */\nasync function driver(args: string[], input = ''): Promise<unknown> {\n let stdout: string\n try {\n stdout = await runVenvScriptStdin(DRIVER, args, input, { cwd: benchRoot })\n } catch (err) {\n const e = err as { message?: string }\n throw new Error(`appworld driver failed (${args.join(' ')}): ${(e.message || String(err)).slice(0, 1500)}`)\n }\n const last = stdout.trim().split('\\n').at(-1) ?? '{}'\n const parsed = JSON.parse(last) as { error?: string }\n if (parsed.error) throw new Error(`appworld driver error: ${parsed.error}`)\n return parsed\n}\n\nexport function createAppWorldAdapter(): BenchmarkAdapter {\n return {\n name: 'appworld',\n output: appworldSolutionOutput,\n\n async preflight() {\n await preflightVenvImports({\n modules: ['appworld'],\n requireDocker: false,\n fix:\n 'Fix: bench/.venv/bin/pip install appworld ; ' +\n 'bench/.venv/bin/appworld install ; bench/.venv/bin/appworld download data ' +\n '(unpacks the engine + downloads the simulated-app data/tasks). ' +\n 'Set APPWORLD_ROOT to the data root if not the default.',\n })\n },\n\n async loadTasks(opts: LoadOptions = {}): Promise<BenchTask[]> {\n const split = opts.split ?? DEFAULT_SPLIT\n const out = (await driver([\n 'load',\n '--split', split,\n ...(opts.limit !== undefined ? ['--limit', String(opts.limit)] : []),\n ...(opts.ids ? ['--ids', opts.ids.join(',')] : []),\n ])) as { tasks?: Array<{ task_id: string; instruction: string }> }\n const tasks = out.tasks ?? []\n if (tasks.length === 0) {\n throw new Error(`appworld loadTasks returned no tasks for split=${split} ${JSON.stringify(opts)}`)\n }\n return tasks.map(\n (t): BenchTask => ({\n id: t.task_id,\n split,\n prompt: t.instruction + WORKER_CONTRACT,\n metadata: { taskId: t.task_id, split } as unknown as Record<string, unknown>,\n }),\n )\n },\n\n async goldArtifact() {\n // Reference solution code ships only for train/dev, and only inside the\n // engine's decrypted `.bundle` (it is not a portable string this adapter can\n // emit across splits). The test splits are evaluation-only. So verify-judge\n // here requires a real solve on a train/dev task through the live engine\n // rather than a synthetic gold — returning a fabricated artifact would be a\n // fake. Returns undefined.\n return undefined\n },\n\n async judge(task: BenchTask, artifact: string): Promise<BenchScore> {\n const meta = readMeta(task)\n const out = (await driver(['evaluate', '--task-id', meta.taskId, '--split', meta.split], artifact)) as {\n success?: boolean\n passes?: number\n fails?: number\n num_tests?: number\n failure_names?: string[]\n }\n const passes = out.passes ?? 0\n const fails = out.fails ?? 0\n // num_tests is the evaluator's authoritative per-requirement count; prefer it\n // over passes+fails (which can disagree if a requirement neither passed nor\n // failed). Never default the total to a phantom denominator.\n const total = out.num_tests ?? passes + fails\n const score = total > 0 ? passes / total : 0\n // failure_names = WHICH sub-tests failed — the evidence a trace analyst\n // steers on. Carried in `detail` so it reaches the verdict's `notes`.\n const failures = Array.isArray(out.failure_names) ? out.failure_names : []\n return {\n resolved: out.success === true,\n score,\n detail: JSON.stringify({\n taskId: meta.taskId,\n success: out.success,\n passes,\n fails,\n total,\n ...(failures.length ? { failures } : {}),\n }),\n }\n },\n }\n}\n\n/**\n * AppWorld in its NATIVE protocol, run by OUR runtime: the worker is\n * `routerToolLoop` (the runtime's off-box agentic tool loop) with one tool —\n * `execute_python` — bound to a persistent AppWorld world session. The driver's\n * `session` subcommand is a dumb world shim (stdin JSONL: execute → output,\n * evaluate → verdict); every inference turn, the metering, and the typed\n * toolTrace the analyst steers on belong to the runtime, so runtime\n * improvements are what this benchmark measures.\n *\n * The one-shot codegen adapter above plays a strictly harder game (no execution\n * feedback — the first wrong API call kills the whole program at judge time),\n * which flatlines the score against ANY steering; this mode is what the\n * benchmark's published baselines use, where behavior can move sub-tests.\n *\n * Protocol: the round task string is `@appworld-react <taskId> <split>` on\n * line 1; everything after line 1 is the steer (an analyst correction, a push\n * directive) appended to the system prompt — so the existing arms steer this\n * worker without modification. The artifact is the episode evaluation JSON\n * (AppWorld's evaluator ran in-world); judge() parses it, never re-executes.\n */\n\ninterface ReactResult {\n success?: boolean\n passes?: number\n fails?: number\n num_tests?: number\n failure_names?: string[]\n turns?: number\n input_tokens?: number\n output_tokens?: number\n transcript?: string\n}\n\nconst REACT_HEADER = /^@appworld-react (\\S+) (\\S+)\\n?/\n\nconst SESSION_SYSTEM = [\n 'You are completing a task in AppWorld, a simulated multi-app environment.',\n 'Use the execute_python tool to run Python that calls the app APIs (the `apis.<app>.<function>(...)` surface).',\n 'Inspect API docs with `apis.api_docs.show_api_descriptions(app_name=...)` and `apis.api_docs.show_api_doc(app_name=..., api_name=...)`.',\n 'Authenticate where needed via the supervisor-provided credentials (`apis.supervisor.show_account_passwords()`).',\n 'Work incrementally: small snippets, read each output, correct course.',\n 'When every step of the task is done, run `apis.supervisor.complete_task()` and then reply WITHOUT calling the tool again.',\n].join('\\n')\n\nconst EXECUTE_TOOL: ToolSpec = {\n type: 'function',\n function: {\n name: 'execute_python',\n description:\n 'Execute a Python snippet in the persistent AppWorld world. State persists across calls. Returns the execution output (API results or errors).',\n parameters: {\n type: 'object',\n properties: { code: { type: 'string', description: 'Python code calling apis.<app>.<fn>(...)' } },\n required: ['code'],\n },\n },\n}\n\n/** One persistent world session: line-JSONL request/response over the driver. */\nasync function withWorldSession<T>(\n taskId: string,\n split: string,\n fn: (call: (cmd: Record<string, unknown>) => Promise<Record<string, unknown>>, instruction: string) => Promise<T>,\n): Promise<T> {\n const child = spawn(venvPython, [DRIVER, 'session', '--task-id', taskId, '--split', split], {\n cwd: benchRoot,\n })\n const rl = createInterface({ input: child.stdout })\n const pending: Array<(line: string) => void> = []\n const backlog: string[] = []\n rl.on('line', (l) => {\n const next = pending.shift()\n if (next) next(l)\n else backlog.push(l)\n })\n let stderr = ''\n child.stderr.on('data', (c: Buffer) => {\n stderr += c.toString('utf8')\n })\n const nextLine = (timeoutMs: number): Promise<string> =>\n new Promise((resolve, reject) => {\n const fromBacklog = backlog.shift()\n if (fromBacklog !== undefined) return resolve(fromBacklog)\n const t = setTimeout(\n () => reject(new Error(`appworld session: no response in ${timeoutMs}ms; stderr: ${stderr.slice(-400)}`)),\n timeoutMs,\n )\n // One exit listener per await leaks (25-turn episodes blow the listener\n // cap) — remove it on the resolve path.\n const onExit = (code: number | null): void => {\n clearTimeout(t)\n reject(new Error(`appworld session exited (${code}); stderr: ${stderr.slice(-400)}`))\n }\n pending.push((l) => {\n clearTimeout(t)\n child.removeListener('exit', onExit)\n resolve(l)\n })\n child.once('exit', onExit)\n })\n try {\n const ready = JSON.parse(await nextLine(120_000)) as { ready?: boolean; instruction?: string; error?: string }\n if (!ready.ready) throw new Error(`appworld session failed to start: ${ready.error ?? 'no ready line'}`)\n const call = async (cmd: Record<string, unknown>): Promise<Record<string, unknown>> => {\n child.stdin.write(`${JSON.stringify(cmd)}\\n`)\n const res = JSON.parse(await nextLine(180_000)) as Record<string, unknown>\n if (typeof res.error === 'string') throw new Error(`appworld session op failed: ${res.error}`)\n return res\n }\n return await fn(call, ready.instruction ?? '')\n } finally {\n child.stdin.end()\n child.kill('SIGTERM')\n }\n}\n\n/** SandboxClient whose leaf is OUR routerToolLoop driving a persistent world session. */\nexport function appworldToolLoopClient(cfg: {\n model: string\n routerBaseUrl: string\n routerKey: string\n maxTurns?: number\n}): unknown {\n const maxTurns = cfg.maxTurns ?? Number(process.env.REACT_MAX_TURNS ?? 40)\n let seq = 0\n return {\n async create() {\n const id = `appworld-toolloop-${seq++}`\n return {\n id,\n async *streamPrompt(prompt: string) {\n const m = prompt.match(REACT_HEADER)\n if (!m) {\n throw new Error(\n `appworld-react leaf: prompt missing '@appworld-react <taskId> <split>' header — got: ${prompt.slice(0, 120)}`,\n )\n }\n const [, taskId, split] = m\n const directive = prompt.replace(REACT_HEADER, '').trim()\n const out = await withWorldSession(taskId as string, split as string, async (call, instruction) => {\n const system = directive ? `${SESSION_SYSTEM}\\n\\n${directive}` : SESSION_SYSTEM\n const loop = await routerToolLoop(\n { routerBaseUrl: cfg.routerBaseUrl, routerKey: cfg.routerKey, model: cfg.model },\n system,\n `Task: ${instruction}`,\n [EXECUTE_TOOL],\n async (name, args) => {\n if (name !== 'execute_python') return `error: unknown tool ${name}`\n const res = await call({ op: 'execute', code: String(args.code ?? '') })\n const done = res.task_completed === true\n return `${String(res.output ?? '')}${done ? '\\n\\n[TASK MARKED COMPLETE — reply with a final summary and do not call the tool again]' : ''}`\n },\n { maxTurns },\n )\n const verdict = (await call({ op: 'evaluate' })) as unknown as ReactResult\n const transcript = loop.toolTrace\n .slice(-3)\n .map((t) => `CODE:\\n${t.args.slice(0, 600)}\\nOUTPUT:\\n${t.result.slice(0, 600)}`)\n .join('\\n---\\n')\n .slice(0, 1600)\n return {\n ...verdict,\n turns: loop.turns,\n input_tokens: loop.usage.input,\n output_tokens: loop.usage.output,\n transcript,\n } satisfies ReactResult\n })\n // Real usage from the episode — flat llm_call so the kernel meters it.\n if (out.input_tokens || out.output_tokens) {\n yield {\n type: 'llm_call',\n data: { tokensIn: out.input_tokens ?? 0, tokensOut: out.output_tokens ?? 0, model: cfg.model },\n }\n }\n yield { type: 'result', data: { finalText: JSON.stringify(out) } }\n },\n async delete() {},\n }\n },\n }\n}\n\n/** Artifact = the episode's evaluation JSON, verbatim (no fence extraction). */\nconst reactEpisodeOutput: 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\n if (typeof t === 'string' && t.length > 0) text = t\n }\n return text\n },\n}\n\nexport function createAppWorldReactAdapter(): BenchmarkAdapter {\n const base = createAppWorldAdapter()\n return {\n name: 'appworld-react',\n output: reactEpisodeOutput,\n preflight: () => base.preflight(),\n\n async loadTasks(opts: LoadOptions = {}): Promise<BenchTask[]> {\n const tasks = await base.loadTasks(opts)\n return tasks.map((t) => {\n const meta = readMeta(t)\n return {\n ...t,\n // Header carries task identity to the leaf; the body (empty at round 0)\n // is the directive slot the arms append their steer into.\n prompt: `@appworld-react ${meta.taskId} ${meta.split}\\n`,\n }\n })\n },\n\n goldArtifact: () => Promise.resolve(undefined),\n\n async judge(task: BenchTask, artifact: string): Promise<BenchScore> {\n const meta = readMeta(task)\n let out: ReactResult\n try {\n out = JSON.parse(artifact) as ReactResult\n } catch {\n throw new Error(\n `appworld-react judge: artifact is not the episode's evaluation JSON (task ${meta.taskId}): ${artifact.slice(0, 200)}`,\n )\n }\n if (typeof out.success !== 'boolean' || typeof out.num_tests !== 'number') {\n throw new Error(\n `appworld-react judge: episode JSON missing success/num_tests (task ${meta.taskId}): ${artifact.slice(0, 200)}`,\n )\n }\n const passes = out.passes ?? 0\n const total = out.num_tests\n const failures = Array.isArray(out.failure_names) ? out.failure_names : []\n return {\n resolved: out.success === true,\n score: total > 0 ? passes / total : 0,\n detail: JSON.stringify({\n taskId: meta.taskId,\n success: out.success,\n passes,\n fails: out.fails ?? 0,\n total,\n turns: out.turns,\n ...(failures.length ? { failures } : {}),\n ...(out.transcript ? { transcriptTail: out.transcript.slice(-800) } : {}),\n }),\n }\n },\n\n leafClient: (c) => appworldToolLoopClient(c),\n }\n}\n"],"mappings":"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","names":[]}
@@ -1,142 +0,0 @@
1
- import {
2
- FINAL_ANSWER_SENTINEL,
3
- allStrings,
4
- answerScoreToBenchScore,
5
- contextBlock,
6
- contextsFrom,
7
- firstString,
8
- isObject,
9
- ragAnswerOutput,
10
- readJsonRows,
11
- scoreAnswerArtifact,
12
- selectTasks,
13
- stringFrom
14
- } from "./chunk-X3BTXCJ4.js";
15
- import {
16
- benchRoot
17
- } from "./chunk-WSKWVEQB.js";
18
-
19
- // src/benchmarks/ragbench.ts
20
- import { readFile } from "fs/promises";
21
- import { join } from "path";
22
- var FIXTURES = join(benchRoot, "fixtures", "ragbench.json");
23
- var dataFile = () => process.env.RAGBENCH_DATA_FILE;
24
- function rowToTask(raw, index) {
25
- if (!isObject(raw)) throw new Error(`RAGBench row ${index} must be an object`);
26
- const query = firstString(raw, ["question", "query", "user_input", "prompt"]);
27
- const goldAnswers = allStrings(raw, [
28
- "response",
29
- "responses",
30
- "model_response",
31
- "generated_response",
32
- "reference",
33
- "references",
34
- "reference_answer",
35
- "reference_answers",
36
- "answer",
37
- "answers",
38
- "gold",
39
- "gold_answer",
40
- "ground_truth",
41
- "expected_answer"
42
- ]);
43
- if (!query) throw new Error(`RAGBench row ${index} missing question/query`);
44
- if (goldAnswers.length === 0) throw new Error(`RAGBench row ${index} missing reference answer`);
45
- const contexts = contextsFrom(raw.contexts).length > 0 ? contextsFrom(raw.contexts) : contextsFrom(raw.retrieved_contexts).length > 0 ? contextsFrom(raw.retrieved_contexts) : contextsFrom(raw.documents);
46
- const traceLabels = {};
47
- for (const key of [
48
- "adherence",
49
- "completeness",
50
- "relevance",
51
- "utilization",
52
- "all_relevant_sentence_keys",
53
- "all_utilized_sentence_keys"
54
- ]) {
55
- if (raw[key] !== void 0) traceLabels[key] = raw[key];
56
- }
57
- const dataset = stringFrom(raw.dataset) ?? stringFrom(raw.source_dataset);
58
- const id = stringFrom(raw.id) ?? stringFrom(raw.example_id) ?? `ragbench-${index}`;
59
- const meta = {
60
- benchmark: "ragbench",
61
- query,
62
- goldAnswers,
63
- contexts,
64
- ...dataset ? { dataset } : {},
65
- traceLabels
66
- };
67
- return {
68
- id,
69
- split: stringFrom(raw.split) ?? dataset ?? "ragbench",
70
- prompt: [
71
- "Answer this RAGBench question using the supplied retrieved context.",
72
- "End with a single final line: `FINAL ANSWER: <answer>`.",
73
- "",
74
- `Question: ${query}`,
75
- contexts.length > 0 ? `
76
- Retrieved context:
77
- ${contextBlock(contexts)}` : void 0
78
- ].filter(Boolean).join("\n"),
79
- metadata: meta
80
- };
81
- }
82
- function readMeta(task) {
83
- const md = task.metadata;
84
- if (!md || !Array.isArray(md.goldAnswers)) {
85
- throw new Error(`RAGBench task ${task.id} missing metadata \u2014 loadTasks did not populate it`);
86
- }
87
- return md;
88
- }
89
- async function loadRows(path) {
90
- const rows = await readJsonRows(path);
91
- if (rows.length === 0) throw new Error(`RAGBench: no rows in ${path}`);
92
- return rows;
93
- }
94
- async function loadFixtures(opts) {
95
- const rows = JSON.parse(await readFile(FIXTURES, "utf8"));
96
- console.warn(`[ragbench] RAGBENCH_FIXTURES=1 \u2014 loading ${rows.length} adapter fixtures`);
97
- return selectTasks(rows.map(rowToTask), opts, "RAGBench");
98
- }
99
- function createRagBenchAdapter() {
100
- const fixturesMode = process.env.RAGBENCH_FIXTURES === "1";
101
- return {
102
- name: "ragbench",
103
- output: ragAnswerOutput,
104
- async preflight() {
105
- if (fixturesMode) {
106
- await readFile(FIXTURES, "utf8");
107
- return;
108
- }
109
- const path = dataFile();
110
- if (!path) {
111
- throw new Error(
112
- "RAGBENCH_DATA_FILE is required. Fix: export rungalileo/ragbench rows to JSONL and set RAGBENCH_DATA_FILE=/path/to/ragbench.jsonl, or set RAGBENCH_FIXTURES=1 for adapter plumbing."
113
- );
114
- }
115
- await loadRows(path);
116
- },
117
- async loadTasks(opts = {}) {
118
- if (fixturesMode) return loadFixtures(opts);
119
- const path = dataFile();
120
- if (!path) throw new Error("RAGBENCH_DATA_FILE is required to load RAGBench tasks");
121
- return selectTasks((await loadRows(path)).map(rowToTask), opts, "RAGBench");
122
- },
123
- async goldArtifact(task) {
124
- return `${FINAL_ANSWER_SENTINEL} ${readMeta(task).goldAnswers[0] ?? ""}`;
125
- },
126
- async judge(task, artifact) {
127
- const meta = readMeta(task);
128
- const score = scoreAnswerArtifact(artifact, meta.goldAnswers);
129
- return answerScoreToBenchScore(score, {
130
- benchmark: meta.benchmark,
131
- dataset: meta.dataset ?? null,
132
- traceLabels: meta.traceLabels,
133
- contextCount: meta.contexts.length
134
- });
135
- }
136
- };
137
- }
138
-
139
- export {
140
- createRagBenchAdapter
141
- };
142
- //# sourceMappingURL=chunk-IFVINJ4B.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/benchmarks/ragbench.ts"],"sourcesContent":["/**\n * RAGBench-compatible adapter.\n *\n * Live mode expects a local JSON/JSONL export from rungalileo/ragbench or a\n * compatible table. Rows must carry a query and at least one reference answer.\n * Contexts, TRACe labels, and source metadata are preserved in task metadata\n * for diagnostics; the deterministic judge scores the worker's final answer\n * against the reference answer(s).\n */\n\nimport { readFile } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport { benchRoot } from './_harness'\nimport type { BenchmarkAdapter, BenchScore, BenchTask, LoadOptions } from './types'\nimport {\n FINAL_ANSWER_SENTINEL,\n allStrings,\n answerScoreToBenchScore,\n contextBlock,\n contextsFrom,\n firstString,\n isObject,\n ragAnswerOutput,\n readJsonRows,\n scoreAnswerArtifact,\n selectTasks,\n stringFrom,\n type RagContext,\n} from './rag-shared'\n\nconst FIXTURES = join(benchRoot, 'fixtures', 'ragbench.json')\n\ninterface RagBenchMeta {\n benchmark: 'ragbench'\n query: string\n goldAnswers: string[]\n contexts: RagContext[]\n dataset?: string\n traceLabels: Record<string, unknown>\n}\n\nconst dataFile = (): string | undefined => process.env.RAGBENCH_DATA_FILE\n\nfunction rowToTask(raw: unknown, index: number): BenchTask {\n if (!isObject(raw)) throw new Error(`RAGBench row ${index} must be an object`)\n const query = firstString(raw, ['question', 'query', 'user_input', 'prompt'])\n const goldAnswers = allStrings(raw, [\n 'response',\n 'responses',\n 'model_response',\n 'generated_response',\n 'reference',\n 'references',\n 'reference_answer',\n 'reference_answers',\n 'answer',\n 'answers',\n 'gold',\n 'gold_answer',\n 'ground_truth',\n 'expected_answer',\n ])\n if (!query) throw new Error(`RAGBench row ${index} missing question/query`)\n if (goldAnswers.length === 0) throw new Error(`RAGBench row ${index} missing reference answer`)\n const contexts =\n contextsFrom(raw.contexts).length > 0\n ? contextsFrom(raw.contexts)\n : contextsFrom(raw.retrieved_contexts).length > 0\n ? contextsFrom(raw.retrieved_contexts)\n : contextsFrom(raw.documents)\n const traceLabels: Record<string, unknown> = {}\n for (const key of [\n 'adherence',\n 'completeness',\n 'relevance',\n 'utilization',\n 'all_relevant_sentence_keys',\n 'all_utilized_sentence_keys',\n ]) {\n if (raw[key] !== undefined) traceLabels[key] = raw[key]\n }\n const dataset = stringFrom(raw.dataset) ?? stringFrom(raw.source_dataset)\n const id = stringFrom(raw.id) ?? stringFrom(raw.example_id) ?? `ragbench-${index}`\n const meta: RagBenchMeta = {\n benchmark: 'ragbench',\n query,\n goldAnswers,\n contexts,\n ...(dataset ? { dataset } : {}),\n traceLabels,\n }\n return {\n id,\n split: stringFrom(raw.split) ?? dataset ?? 'ragbench',\n prompt: [\n 'Answer this RAGBench question using the supplied retrieved context.',\n 'End with a single final line: `FINAL ANSWER: <answer>`.',\n '',\n `Question: ${query}`,\n contexts.length > 0 ? `\\nRetrieved context:\\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): RagBenchMeta {\n const md = task.metadata\n if (!md || !Array.isArray(md.goldAnswers)) {\n throw new Error(`RAGBench task ${task.id} missing metadata — loadTasks did not populate it`)\n }\n return md as unknown as RagBenchMeta\n}\n\nasync function loadRows(path: string): Promise<unknown[]> {\n const rows = await readJsonRows(path)\n if (rows.length === 0) throw new Error(`RAGBench: 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(`[ragbench] RAGBENCH_FIXTURES=1 — loading ${rows.length} adapter fixtures`)\n return selectTasks(rows.map(rowToTask), opts, 'RAGBench')\n}\n\nexport function createRagBenchAdapter(): BenchmarkAdapter {\n const fixturesMode = process.env.RAGBENCH_FIXTURES === '1'\n\n return {\n name: 'ragbench',\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 'RAGBENCH_DATA_FILE is required. Fix: export rungalileo/ragbench rows to JSONL and set RAGBENCH_DATA_FILE=/path/to/ragbench.jsonl, or set RAGBENCH_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('RAGBENCH_DATA_FILE is required to load RAGBench tasks')\n return selectTasks((await loadRows(path)).map(rowToTask), opts, 'RAGBench')\n },\n\n async goldArtifact(task: BenchTask) {\n return `${FINAL_ANSWER_SENTINEL} ${readMeta(task).goldAnswers[0] ?? ''}`\n },\n\n async judge(task: BenchTask, artifact: string): Promise<BenchScore> {\n const meta = readMeta(task)\n const score = scoreAnswerArtifact(artifact, meta.goldAnswers)\n return answerScoreToBenchScore(score, {\n benchmark: meta.benchmark,\n dataset: meta.dataset ?? null,\n traceLabels: meta.traceLabels,\n contextCount: meta.contexts.length,\n })\n },\n }\n}\n"],"mappings":"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","names":[]}
@@ -1,387 +0,0 @@
1
- // src/benchmarks/frames.ts
2
- import { execFile } from "child_process";
3
- import { readFile } from "fs/promises";
4
- import { join } from "path";
5
- import { fileURLToPath } from "url";
6
- import { promisify } from "util";
7
- var execFileAsync = promisify(execFile);
8
- var BENCH_ROOT = fileURLToPath(new URL("../..", import.meta.url));
9
- var PY = join(BENCH_ROOT, ".venv", "bin", "python");
10
- var FIXTURES = join(BENCH_ROOT, "fixtures", "frames.json");
11
- var DATASET = "google/frames-benchmark";
12
- var DATASET_REVISION = "main";
13
- var FINAL_ANSWER_SENTINEL = "FINAL ANSWER:";
14
- var WORKER_CONTRACT = [
15
- "",
16
- "Research the question using live web sources and answer it.",
17
- "Cite the sources you used as full URLs, one per line, in a `CITATIONS:` block.",
18
- `End your response with a single final line: \`${FINAL_ANSWER_SENTINEL} <answer>\``,
19
- "The answer after the sentinel must be the bare value only (no explanation on that line)."
20
- ].join("\n");
21
- async function py(script, args = []) {
22
- const { stdout } = await execFileAsync(PY, ["-c", script, ...args], {
23
- maxBuffer: 1024 * 1024 * 256
24
- });
25
- return stdout;
26
- }
27
- var ARTICLES = /* @__PURE__ */ new Set(["a", "an", "the"]);
28
- var UNIT_WORDS = /* @__PURE__ */ new Set([
29
- "years",
30
- "year",
31
- "months",
32
- "month",
33
- "days",
34
- "day",
35
- "people",
36
- "percent",
37
- "dollars",
38
- "meters",
39
- "metres",
40
- "kilometers",
41
- "kilometres",
42
- "miles",
43
- "km",
44
- "m"
45
- ]);
46
- var WRITTEN_NUMBERS = {
47
- zero: 0,
48
- one: 1,
49
- two: 2,
50
- three: 3,
51
- four: 4,
52
- five: 5,
53
- six: 6,
54
- seven: 7,
55
- eight: 8,
56
- nine: 9,
57
- ten: 10,
58
- eleven: 11,
59
- twelve: 12,
60
- thirteen: 13,
61
- fourteen: 14,
62
- fifteen: 15,
63
- sixteen: 16,
64
- seventeen: 17,
65
- eighteen: 18,
66
- nineteen: 19,
67
- twenty: 20,
68
- thirty: 30,
69
- forty: 40,
70
- fifty: 50,
71
- sixty: 60,
72
- seventy: 70,
73
- eighty: 80,
74
- ninety: 90,
75
- hundred: 100,
76
- thousand: 1e3,
77
- million: 1e6,
78
- billion: 1e9
79
- };
80
- var MONTHS = {
81
- january: "01",
82
- february: "02",
83
- march: "03",
84
- april: "04",
85
- may: "05",
86
- june: "06",
87
- july: "07",
88
- august: "08",
89
- september: "09",
90
- october: "10",
91
- november: "11",
92
- december: "12"
93
- };
94
- var SCALES = /* @__PURE__ */ new Set(["hundred", "thousand", "million", "billion"]);
95
- function composeWrittenRun(words) {
96
- let total = 0;
97
- let current = 0;
98
- for (const w of words) {
99
- const v = WRITTEN_NUMBERS[w];
100
- if (v === void 0) continue;
101
- if (w === "hundred") {
102
- current = (current === 0 ? 1 : current) * 100;
103
- } else if (SCALES.has(w)) {
104
- current = (current === 0 ? 1 : current) * v;
105
- total += current;
106
- current = 0;
107
- } else {
108
- current += v;
109
- }
110
- }
111
- return total + current;
112
- }
113
- function canonicalizeNumbers(s) {
114
- let out = s.replace(/(\d),(?=\d{3}\b)/g, "$1");
115
- out = out.replace(/\b(\d+(?:\.\d+)?)\s+(hundred|thousand|million|billion)\b/g, (_m, num, scaleWord) => {
116
- const scale = WRITTEN_NUMBERS[scaleWord] ?? 1;
117
- return String(Number(num) * scale);
118
- });
119
- out = out.replace(/\b[a-z]+(?:[\s-]+[a-z]+)*\b/g, (run) => {
120
- const words = run.split(/[\s-]+/);
121
- if (!words.every((w) => w in WRITTEN_NUMBERS)) return run;
122
- return String(composeWrittenRun(words));
123
- });
124
- return out;
125
- }
126
- function canonicalizeDates(s) {
127
- let out = s.replace(
128
- /\b(january|february|march|april|may|june|july|august|september|october|november|december)\s+(\d{1,2}),?\s+(\d{4})\b/g,
129
- (_m, mon, day, year) => `${year}-${MONTHS[mon]}-${day.padStart(2, "0")}`
130
- );
131
- out = out.replace(
132
- /\b(\d{1,2})\s+(january|february|march|april|may|june|july|august|september|october|november|december)\s+(\d{4})\b/g,
133
- (_m, day, mon, year) => `${year}-${MONTHS[mon]}-${day.padStart(2, "0")}`
134
- );
135
- return out;
136
- }
137
- function normalizeAnswer(input) {
138
- let s = input.toLowerCase();
139
- s = canonicalizeDates(s);
140
- s = canonicalizeNumbers(s);
141
- s = s.replace(/[^\w\s-]/g, " ");
142
- const tokens = s.split(/\s+/).filter((t) => t.length > 0).filter((t) => !ARTICLES.has(t)).filter((t) => !UNIT_WORDS.has(t));
143
- return tokens.join(" ").trim();
144
- }
145
- function tier1Match(candidate, gold) {
146
- const nc = normalizeAnswer(candidate);
147
- const ng = normalizeAnswer(gold);
148
- if (ng.length === 0) return false;
149
- if (nc === ng) return true;
150
- const re = new RegExp(`(^|\\s)${ng.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}(\\s|$)`);
151
- return re.test(nc);
152
- }
153
- function parseFinalAnswer(artifact) {
154
- const lines = artifact.split(/\r?\n/);
155
- for (let i = lines.length - 1; i >= 0; i -= 1) {
156
- const line = lines[i] ?? "";
157
- const idx = line.toUpperCase().indexOf(FINAL_ANSWER_SENTINEL);
158
- if (idx !== -1) return line.slice(idx + FINAL_ANSWER_SENTINEL.length).trim();
159
- }
160
- for (let i = lines.length - 1; i >= 0; i -= 1) {
161
- const t = (lines[i] ?? "").trim();
162
- if (t.length > 0) return t;
163
- }
164
- return "";
165
- }
166
- function parseCitations(artifact) {
167
- const urls = /* @__PURE__ */ new Set();
168
- for (const m of artifact.matchAll(/https?:\/\/[^\s)<>"']+/g)) {
169
- urls.add(m[0].replace(/[.,;]+$/, ""));
170
- }
171
- return [...urls];
172
- }
173
- function citationCoverage(citations, goldSources) {
174
- if (goldSources.length === 0) return 1;
175
- const slug = (u) => {
176
- const m = u.match(/\/wiki\/([^#?]+)/);
177
- return m ? decodeURIComponent(m[1] ?? "").toLowerCase() : u.toLowerCase();
178
- };
179
- const got = new Set(citations.map(slug));
180
- let hit = 0;
181
- for (const g of goldSources) if (got.has(slug(g))) hit += 1;
182
- return hit / goldSources.length;
183
- }
184
- var JUDGE_PROMPT = (question, gold, candidate) => [
185
- "You are a strict answer-equivalence checker for a factual question-answering benchmark.",
186
- "Decide ONLY whether the candidate answer is semantically equivalent to the gold answer for this question.",
187
- "It is CORRECT iff it contains the same factual value as the gold answer. Extra correct detail is fine.",
188
- "A different value, a missing value, or a wrong value is INCORRECT.",
189
- "",
190
- `Question: ${question}`,
191
- `Gold answer: ${gold}`,
192
- `Candidate answer: ${candidate}`,
193
- "",
194
- "Respond with ONLY a fenced JSON block and nothing else:",
195
- "```json",
196
- '{"verdict": "correct" | "incorrect"}',
197
- "```"
198
- ].join("\n");
199
- function judgeRouter() {
200
- const model = process.env.JUDGE_MODEL;
201
- if (!model) throw new Error("JUDGE_MODEL is required for the FRAMES Tier-2 equivalence judge");
202
- const key = process.env.TANGLE_API_KEY;
203
- if (!key) throw new Error("TANGLE_API_KEY is required for the FRAMES Tier-2 judge");
204
- const baseUrl = process.env.JUDGE_ROUTER_BASE ?? process.env.ROUTER_BASE ?? "https://router.tangle.tools/v1";
205
- return { baseUrl, key, model };
206
- }
207
- async function tier2Judge(question, gold, candidate, router) {
208
- const res = await fetch(`${router.baseUrl}/chat/completions`, {
209
- method: "POST",
210
- headers: { "content-type": "application/json", authorization: `Bearer ${router.key}` },
211
- body: JSON.stringify({
212
- model: router.model,
213
- temperature: 0,
214
- seed: 0,
215
- messages: [{ role: "user", content: JUDGE_PROMPT(question, gold, candidate) }]
216
- })
217
- });
218
- if (!res.ok) {
219
- throw new Error(`FRAMES Tier-2 judge HTTP ${res.status}: ${(await res.text()).slice(0, 300)}`);
220
- }
221
- const body = await res.json();
222
- const content = body.choices?.[0]?.message?.content;
223
- if (typeof content !== "string") {
224
- throw new Error(`FRAMES Tier-2 judge returned no message content: ${JSON.stringify(body).slice(0, 300)}`);
225
- }
226
- const fenced = content.match(/```(?:json)?\s*([\s\S]*?)```/);
227
- const raw = (fenced ? fenced[1] : content)?.trim() ?? "";
228
- let parsed;
229
- try {
230
- parsed = JSON.parse(raw);
231
- } catch {
232
- throw new Error(`FRAMES Tier-2 judge produced unparseable output (no JSON verdict): ${content.slice(0, 300)}`);
233
- }
234
- if (parsed.verdict === "correct") return true;
235
- if (parsed.verdict === "incorrect") return false;
236
- throw new Error(`FRAMES Tier-2 judge verdict not in {correct,incorrect}: ${JSON.stringify(parsed).slice(0, 200)}`);
237
- }
238
- function parseWikiLinks(raw) {
239
- if (!raw) return [];
240
- const out = [];
241
- for (const m of raw.matchAll(/https?:\/\/[^\s'"\]]+/g)) out.push(m[0]);
242
- return out;
243
- }
244
- function rowToTask(row, index) {
245
- const goldSources = parseWikiLinks(row.wiki_links);
246
- const meta = {
247
- gold: row.Answer,
248
- goldSources,
249
- reasoningTypes: row.reasoning_types ?? "",
250
- rawPrompt: row.Prompt
251
- };
252
- return {
253
- id: `frames-${index}`,
254
- split: "test",
255
- prompt: row.Prompt + WORKER_CONTRACT,
256
- metadata: meta
257
- };
258
- }
259
- function readMeta(task) {
260
- const md = task.metadata;
261
- if (!md || typeof md.gold !== "string") {
262
- throw new Error(`FRAMES task ${task.id} missing metadata.gold \u2014 loadTasks did not populate it`);
263
- }
264
- return md;
265
- }
266
- async function loadFixtures(opts) {
267
- const rows = JSON.parse(await readFile(FIXTURES, "utf8"));
268
- console.log(`[frames] FRAMES_FIXTURES=1 \u2014 loading ${rows.length} committed fixtures (no HF download)`);
269
- let tasks = rows.map(rowToTask);
270
- if (opts.ids) {
271
- const want = new Set(opts.ids);
272
- tasks = tasks.filter((t) => want.has(t.id));
273
- } else if (opts.limit !== void 0) {
274
- tasks = tasks.slice(0, opts.limit);
275
- }
276
- return tasks;
277
- }
278
- function createFramesAdapter() {
279
- const fixturesMode = process.env.FRAMES_FIXTURES === "1";
280
- return {
281
- name: "frames",
282
- async preflight() {
283
- judgeRouter();
284
- if (fixturesMode) {
285
- await readFile(FIXTURES, "utf8").catch((err) => {
286
- throw new Error(`FRAMES_FIXTURES=1 but ${FIXTURES} unreadable: ${err instanceof Error ? err.message : err}`);
287
- });
288
- return;
289
- }
290
- try {
291
- await py(
292
- `from datasets import load_dataset
293
- load_dataset(${JSON.stringify(DATASET)}, split='test', revision=${JSON.stringify(DATASET_REVISION)})
294
- print('ok')`
295
- );
296
- } catch (err) {
297
- const msg = err instanceof Error ? err.message : String(err);
298
- throw new Error(
299
- `frames preflight failed: ${msg}
300
- Fix: (1) python3 -m venv bench/.venv && bench/.venv/bin/pip install datasets ; (2) ensure network access to Hugging Face for ${DATASET} ; or set FRAMES_FIXTURES=1 to run against the committed fixtures offline.`
301
- );
302
- }
303
- },
304
- async loadTasks(opts = {}) {
305
- if (fixturesMode) return loadFixtures(opts);
306
- const limit = opts.limit ?? 10;
307
- const script = `
308
- import json, sys
309
- from datasets import load_dataset
310
- ds = load_dataset(${JSON.stringify(DATASET)}, split='test', revision=${JSON.stringify(DATASET_REVISION)})
311
- ids = set(json.loads(sys.argv[1])) if len(sys.argv) > 1 and sys.argv[1] else None
312
- out = []
313
- for i, r in enumerate(ds):
314
- rid = f"frames-{i}"
315
- if ids is not None and rid not in ids:
316
- continue
317
- out.append({
318
- "_index": i,
319
- "Prompt": r.get("Prompt", ""),
320
- "Answer": r.get("Answer", ""),
321
- "wiki_links": str(r.get("wiki_links", "")),
322
- "reasoning_types": str(r.get("reasoning_types", "")),
323
- })
324
- if ids is None and len(out) >= ${limit}:
325
- break
326
- print(json.dumps(out))
327
- `;
328
- const stdout = await py(script, [opts.ids ? JSON.stringify(opts.ids) : ""]);
329
- const rows = JSON.parse(stdout);
330
- return rows.map((r) => rowToTask(r, r._index));
331
- },
332
- async goldArtifact(task) {
333
- const meta = readMeta(task);
334
- return `${FINAL_ANSWER_SENTINEL} ${meta.gold}`;
335
- },
336
- async judge(task, artifact) {
337
- const meta = readMeta(task);
338
- const finalAnswer = parseFinalAnswer(artifact);
339
- const citations = parseCitations(artifact);
340
- const coverage = citationCoverage(citations, meta.goldSources);
341
- if (finalAnswer.length === 0) {
342
- return {
343
- resolved: false,
344
- score: 0,
345
- detail: JSON.stringify({
346
- tier: "none",
347
- reason: "no parseable answer",
348
- normalizedGold: normalizeAnswer(meta.gold),
349
- citationCoverage: coverage
350
- })
351
- };
352
- }
353
- if (tier1Match(finalAnswer, meta.gold)) {
354
- return {
355
- resolved: true,
356
- score: 1,
357
- detail: JSON.stringify({
358
- tier: 1,
359
- normalizedAnswer: normalizeAnswer(finalAnswer),
360
- normalizedGold: normalizeAnswer(meta.gold),
361
- citationCoverage: coverage
362
- })
363
- };
364
- }
365
- const verdict = await tier2Judge(meta.rawPrompt, meta.gold, finalAnswer, judgeRouter());
366
- return {
367
- resolved: verdict,
368
- score: verdict ? 1 : 0,
369
- detail: JSON.stringify({
370
- tier: 2,
371
- normalizedAnswer: normalizeAnswer(finalAnswer),
372
- normalizedGold: normalizeAnswer(meta.gold),
373
- judgeVerdict: verdict ? "correct" : "incorrect",
374
- citationCoverage: coverage
375
- })
376
- };
377
- }
378
- };
379
- }
380
-
381
- export {
382
- normalizeAnswer,
383
- parseFinalAnswer,
384
- parseCitations,
385
- createFramesAdapter
386
- };
387
- //# sourceMappingURL=chunk-INNOYXCP.js.map