@tangle-network/agent-bench 0.4.1 → 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 (194) hide show
  1. package/CHANGELOG.md +9 -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 +48 -66
  6. package/dist/benchmarks/_harness.js +329 -33
  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/scripts/verify-packed-consumer.mjs +20 -17
  113. package/src/corpus.test.mts +13 -0
  114. package/src/corpus.ts +4 -0
  115. package/src/profile-coordinates.ts +2 -2
  116. package/src/rollout-ledger/backfill-swe-arena.mts +5 -1
  117. package/src/rollout-ledger/settle-capture.mts +7 -1
  118. package/src/search-bench/profiles.ts +1 -1
  119. package/src/skill-sandbox-smoke.mts +2 -1
  120. package/src/swe-arena/gepa-seat.mts +1 -1
  121. package/src/swe-arena/ledger-orphans.test.mts +36 -34
  122. package/dist/benchmarks/cadbench.js.map +0 -1
  123. package/dist/benchmarks/cadgenbench.js.map +0 -1
  124. package/dist/benchmarks/types.js.map +0 -1
  125. package/dist/chunk-53UPUNBZ.js +0 -325
  126. package/dist/chunk-53UPUNBZ.js.map +0 -1
  127. package/dist/chunk-5FEQDSCT.js +0 -211
  128. package/dist/chunk-5FEQDSCT.js.map +0 -1
  129. package/dist/chunk-5H5XV76F.js +0 -240
  130. package/dist/chunk-5H5XV76F.js.map +0 -1
  131. package/dist/chunk-67ACKDCX.js +0 -118
  132. package/dist/chunk-67ACKDCX.js.map +0 -1
  133. package/dist/chunk-7FKBWOQT.js +0 -147
  134. package/dist/chunk-7FKBWOQT.js.map +0 -1
  135. package/dist/chunk-BEN6IF2X.js +0 -221
  136. package/dist/chunk-BEN6IF2X.js.map +0 -1
  137. package/dist/chunk-BZY5QARD.js +0 -120
  138. package/dist/chunk-BZY5QARD.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-CLIKAXKH.js +0 -276
  142. package/dist/chunk-CLIKAXKH.js.map +0 -1
  143. package/dist/chunk-CWIOBFSP.js +0 -197
  144. package/dist/chunk-CWIOBFSP.js.map +0 -1
  145. package/dist/chunk-CXDUTWQE.js +0 -318
  146. package/dist/chunk-CXDUTWQE.js.map +0 -1
  147. package/dist/chunk-DWALFME7.js +0 -182
  148. package/dist/chunk-DWALFME7.js.map +0 -1
  149. package/dist/chunk-EEOC6QPJ.js +0 -144
  150. package/dist/chunk-EEOC6QPJ.js.map +0 -1
  151. package/dist/chunk-EIETHPD5.js +0 -321
  152. package/dist/chunk-EIETHPD5.js.map +0 -1
  153. package/dist/chunk-GC2EPS6L.js +0 -130
  154. package/dist/chunk-GC2EPS6L.js.map +0 -1
  155. package/dist/chunk-GCHL6XPM.js +0 -169
  156. package/dist/chunk-GCHL6XPM.js.map +0 -1
  157. package/dist/chunk-HQ5HCCKF.js +0 -142
  158. package/dist/chunk-HQ5HCCKF.js.map +0 -1
  159. package/dist/chunk-HVW25KSX.js +0 -208
  160. package/dist/chunk-HVW25KSX.js.map +0 -1
  161. package/dist/chunk-INNOYXCP.js +0 -387
  162. package/dist/chunk-INNOYXCP.js.map +0 -1
  163. package/dist/chunk-J6BU3NTM.js +0 -251
  164. package/dist/chunk-J6BU3NTM.js.map +0 -1
  165. package/dist/chunk-JSQOUKXS.js +0 -149
  166. package/dist/chunk-JSQOUKXS.js.map +0 -1
  167. package/dist/chunk-JTHWEDEW.js +0 -32
  168. package/dist/chunk-JTHWEDEW.js.map +0 -1
  169. package/dist/chunk-NRMGT25X.js +0 -116
  170. package/dist/chunk-NRMGT25X.js.map +0 -1
  171. package/dist/chunk-PA2ZKHJC.js +0 -230
  172. package/dist/chunk-PA2ZKHJC.js.map +0 -1
  173. package/dist/chunk-PUIRNYI7.js +0 -189
  174. package/dist/chunk-PUIRNYI7.js.map +0 -1
  175. package/dist/chunk-QZZEAHWJ.js +0 -136
  176. package/dist/chunk-QZZEAHWJ.js.map +0 -1
  177. package/dist/chunk-SEVJPLZC.js +0 -260
  178. package/dist/chunk-SEVJPLZC.js.map +0 -1
  179. package/dist/chunk-TBKU5XQI.js +0 -228
  180. package/dist/chunk-TBKU5XQI.js.map +0 -1
  181. package/dist/chunk-UPAMRDX4.js +0 -233
  182. package/dist/chunk-UPAMRDX4.js.map +0 -1
  183. package/dist/chunk-VQRS7VUC.js +0 -342
  184. package/dist/chunk-VQRS7VUC.js.map +0 -1
  185. package/dist/chunk-WG7TM7UV.js +0 -30
  186. package/dist/chunk-WG7TM7UV.js.map +0 -1
  187. package/dist/chunk-X3BTXCJ4.js +0 -262
  188. package/dist/chunk-X3BTXCJ4.js.map +0 -1
  189. package/dist/chunk-XXFF3RRD.js +0 -162
  190. package/dist/chunk-XXFF3RRD.js.map +0 -1
  191. package/dist/chunk-ZFNOM7WR.js +0 -27
  192. package/dist/chunk-ZFNOM7WR.js.map +0 -1
  193. package/dist/chunk-ZNCCYTFG.js +0 -170
  194. package/dist/chunk-ZNCCYTFG.js.map +0 -1
@@ -1,7 +1,513 @@
1
- import {
2
- createCadDesignAdapter
3
- } from "../chunk-53UPUNBZ.js";
4
- export {
5
- createCadDesignAdapter
6
- };
1
+ import { mkdtemp, readFile, writeFile } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import { execFile } from "node:child_process";
4
+ import { tmpdir } from "node:os";
5
+ import { promisify } from "node:util";
6
+ //#region src/benchmarks/cad-design.ts
7
+ /**
8
+ * CAD-Design adapter. Worker artifact = OpenSCAD source (`.scad`). Judge = the
9
+ * REAL OpenSCAD engine: compile + export STL, then measure the produced solid
10
+ * geometry against the task's spec. Fully deterministic — the authoritative CAD
11
+ * kernel is the gate, not an LLM and not the agent's own claim.
12
+ *
13
+ * This is verifiable-reward CAD: an agent is far better at *writing* exact
14
+ * parametric code than at clicking a GUI, and the kernel either produces the
15
+ * specified geometry or it doesn't. Every judged artifact also renders a PNG,
16
+ * so a refine loop's attempts become a watchable "model getting better" reel
17
+ * (run-capsule consumes the renders).
18
+ *
19
+ * Spec checks are geometric and ungameable:
20
+ * - compiles : `openscad -o out.stl` exits 0 (hard gate)
21
+ * - volumes : disconnected-solid count within [min,max]
22
+ * - bbox : overall X/Y/Z extent within bounds (the thing is the right size)
23
+ * - detail : triangle count ≥ floor (not a degenerate single cube)
24
+ * - pitchedRoof : the top band's XY footprint NARROWS vs the base — a flat
25
+ * box can't fake this; a real gabled/hipped roof tapers
26
+ * - hollow : interior cavity present (walls, not a solid block) — the
27
+ * bbox volume materially exceeds the printed solid volume
28
+ *
29
+ * Requires only `openscad` + `xvfb-run` on PATH (no venv, no Docker, no network).
30
+ */
31
+ const execFileAsync = promisify(execFile);
32
+ /** Run openscad with xvfb (it needs a GL context even headless). */
33
+ async function openscad(args, cwd) {
34
+ const { stdout, stderr } = await execFileAsync("xvfb-run", [
35
+ "-a",
36
+ "openscad",
37
+ ...args
38
+ ], {
39
+ cwd,
40
+ maxBuffer: 1024 * 1024 * 64,
41
+ timeout: 12e4
42
+ });
43
+ return {
44
+ stdout,
45
+ stderr
46
+ };
47
+ }
48
+ /** Parse an ASCII STL into the geometric measures the spec checks. Pure. */
49
+ function measureStl(stl, volumesFromStderr) {
50
+ const verts = [];
51
+ const tris = [];
52
+ const re = /vertex\s+(-?[\d.eE+]+)\s+(-?[\d.eE+]+)\s+(-?[\d.eE+]+)/g;
53
+ let m;
54
+ const flat = [];
55
+ while (m = re.exec(stl)) flat.push([
56
+ Number(m[1]),
57
+ Number(m[2]),
58
+ Number(m[3])
59
+ ]);
60
+ for (let i = 0; i + 2 < flat.length; i += 3) tris.push([
61
+ flat[i],
62
+ flat[i + 1],
63
+ flat[i + 2]
64
+ ]);
65
+ for (const v of flat) verts.push(v);
66
+ const xs = verts.map((v) => v[0]);
67
+ const ys = verts.map((v) => v[1]);
68
+ const zs = verts.map((v) => v[2]);
69
+ const min = (a) => Math.min(...a);
70
+ const max = (a) => Math.max(...a);
71
+ const minZ = min(zs);
72
+ const maxZ = max(zs);
73
+ const h = maxZ - minZ || 1;
74
+ const footprint = (lo, hi) => {
75
+ const band = verts.filter((v) => v[2] >= minZ + lo * h && v[2] <= minZ + hi * h);
76
+ if (band.length < 3) return 0;
77
+ const bx = band.map((v) => v[0]);
78
+ const by = band.map((v) => v[1]);
79
+ return (max(bx) - min(bx)) * (max(by) - min(by));
80
+ };
81
+ let vol6 = 0;
82
+ for (const [a, b, c] of tris) vol6 += a[0] * (b[1] * c[2] - b[2] * c[1]) - a[1] * (b[0] * c[2] - b[2] * c[0]) + a[2] * (b[0] * c[1] - b[1] * c[0]);
83
+ const bbox = {
84
+ x: max(xs) - min(xs),
85
+ y: max(ys) - min(ys),
86
+ z: maxZ - minZ
87
+ };
88
+ return {
89
+ triangles: tris.length,
90
+ volumes: volumesFromStderr,
91
+ bbox,
92
+ baseFootprint: footprint(0, .6),
93
+ topFootprint: footprint(.75, 1),
94
+ solidVolume: Math.abs(vol6) / 6,
95
+ bboxVolume: bbox.x * bbox.y * bbox.z || 1
96
+ };
97
+ }
98
+ function inRange(v, [lo, hi]) {
99
+ return v >= lo && v <= hi;
100
+ }
101
+ /** Score the geometry against the spec — each check is a named pass/fail. */
102
+ function scoreGeometry(g, spec) {
103
+ const checks = {};
104
+ if (spec.volumes) checks.volumes = inRange(g.volumes, spec.volumes);
105
+ if (spec.minTriangles != null) checks.detail = g.triangles >= spec.minTriangles;
106
+ if (spec.bbox?.x) checks.bboxX = inRange(g.bbox.x, spec.bbox.x);
107
+ if (spec.bbox?.y) checks.bboxY = inRange(g.bbox.y, spec.bbox.y);
108
+ if (spec.bbox?.z) checks.bboxZ = inRange(g.bbox.z, spec.bbox.z);
109
+ if (spec.pitchedRoof != null) checks.pitchedRoof = g.baseFootprint > 0 && g.topFootprint < spec.pitchedRoof * g.baseFootprint;
110
+ if (spec.hollowBelow != null) checks.hollow = g.solidVolume < spec.hollowBelow * g.bboxVolume;
111
+ const vals = Object.values(checks);
112
+ return {
113
+ checks,
114
+ score: vals.length ? vals.filter(Boolean).length / vals.length : 0
115
+ };
116
+ }
117
+ /** A parametric multi-story gabled building — the gold generator for the
118
+ * building-family tasks. They share geometry (hollow stacked shells + a gabled
119
+ * roof that tapers to a ridge + cut openings) and differ only in dimensions, so
120
+ * one verified generator yields a spec-passing oracle for each. */
121
+ function buildingGold(w, d, sh, ns, rh, t = 3) {
122
+ return `
123
+ w=${w}; d=${d}; sh=${sh}; ns=${ns}; rh=${rh}; t=${t};
124
+ module shell(w,d,h,t){ difference(){ cube([w,d,h]); translate([t,t,-1]) cube([w-2*t,d-2*t,h+2]); } }
125
+ module roof(w,d,h){ rotate([90,0,90]) linear_extrude(height=w) polygon([[0,0],[d,0],[d/2,h]]); }
126
+ union(){
127
+ for(s=[0:ns-1]) translate([0,0,s*sh]) shell(w,d,sh,t);
128
+ for(s=[0:ns]) translate([0,0,s*sh-0.5]) cube([w,d,1]);
129
+ translate([0,0,ns*sh]) roof(w,d,rh);
130
+ for(s=[0:ns-1]) for(i=[0:floor((w-28)/22)]) translate([14+i*22,-1,s*sh+10]) cube([10,t+2,12]);
131
+ translate([w/2-7,-1,2]) cube([14,t+2,20]);
132
+ }
133
+ `.trim();
134
+ }
135
+ /** Build a building-family task (prompt + spec + gold) from its dimensions.
136
+ * The spec's bbox is derived from the dims with a ±~18% tolerance so the agent
137
+ * must respect the brief's size; the gold (buildingGold) lands exactly on the
138
+ * nominal dims, so it passes by construction. Keep rh > ns*sh/3 (else the roof
139
+ * base sits inside the top-25% band and pitchedRoof fails). */
140
+ function buildingTask(o) {
141
+ const { id, desc, w, d, sh, ns, rh } = o;
142
+ const totalWall = ns * sh;
143
+ const totalH = totalWall + rh;
144
+ const r = Math.round;
145
+ const spec = {
146
+ volumes: [1, ns * 4 + 6],
147
+ bbox: {
148
+ x: [r(w * .82), r(w * 1.18)],
149
+ y: [r(d * .82), r((d + 1) * 1.2)],
150
+ z: [r(totalH * .82), r((totalH + 1) * 1.2)]
151
+ },
152
+ minTriangles: 50,
153
+ pitchedRoof: .55,
154
+ hollowBelow: .72
155
+ };
156
+ return {
157
+ id,
158
+ prompt: [
159
+ `Write OpenSCAD source for ${desc}.`,
160
+ "Requirements:",
161
+ `- footprint roughly ${w} (X) by ${d} (Y) units`,
162
+ ns > 1 ? `- ${ns} stories, total wall height ~${totalWall} units` : `- one story, wall height ~${sh} units`,
163
+ "- a PITCHED / gabled roof on top that tapers toward a ridge (NOT flat)",
164
+ "- hollow shell (walls with an interior cavity), not a solid block",
165
+ "- a door opening and several windows",
166
+ "Output ONLY the .scad source, no prose, no code fences."
167
+ ].join("\n"),
168
+ meta: {
169
+ spec,
170
+ gold: buildingGold(w, d, sh, ns, rh)
171
+ }
172
+ };
173
+ }
174
+ /** The building family — one parametric skill (hit the bbox + pitched roof +
175
+ * hollow shell), sampled across footprints, heights, story counts, roof rises. */
176
+ const BUILDING_CONFIGS = [
177
+ {
178
+ id: "cottage",
179
+ desc: "a single-story cottage",
180
+ w: 50,
181
+ d: 40,
182
+ sh: 30,
183
+ ns: 1,
184
+ rh: 18
185
+ },
186
+ {
187
+ id: "cabin",
188
+ desc: "a small one-room cabin",
189
+ w: 44,
190
+ d: 36,
191
+ sh: 26,
192
+ ns: 1,
193
+ rh: 22
194
+ },
195
+ {
196
+ id: "bungalow",
197
+ desc: "a wide single-story bungalow",
198
+ w: 70,
199
+ d: 52,
200
+ sh: 28,
201
+ ns: 1,
202
+ rh: 20
203
+ },
204
+ {
205
+ id: "barn",
206
+ desc: "a long deep barn",
207
+ w: 60,
208
+ d: 96,
209
+ sh: 42,
210
+ ns: 1,
211
+ rh: 26
212
+ },
213
+ {
214
+ id: "warehouse",
215
+ desc: "a large warehouse",
216
+ w: 110,
217
+ d: 80,
218
+ sh: 40,
219
+ ns: 1,
220
+ rh: 26
221
+ },
222
+ {
223
+ id: "chapel",
224
+ desc: "a narrow tall chapel with a steep roof",
225
+ w: 40,
226
+ d: 72,
227
+ sh: 48,
228
+ ns: 1,
229
+ rh: 34
230
+ },
231
+ {
232
+ id: "farmhouse",
233
+ desc: "a two-story farmhouse",
234
+ w: 72,
235
+ d: 56,
236
+ sh: 30,
237
+ ns: 2,
238
+ rh: 26
239
+ },
240
+ {
241
+ id: "two-story-manor",
242
+ desc: "a wide two-story manor",
243
+ w: 96,
244
+ d: 64,
245
+ sh: 32,
246
+ ns: 2,
247
+ rh: 28
248
+ },
249
+ {
250
+ id: "townhouse",
251
+ desc: "a narrow three-story townhouse",
252
+ w: 42,
253
+ d: 52,
254
+ sh: 30,
255
+ ns: 3,
256
+ rh: 34
257
+ },
258
+ {
259
+ id: "watchtower",
260
+ desc: "a tall narrow three-story watchtower",
261
+ w: 34,
262
+ d: 34,
263
+ sh: 30,
264
+ ns: 3,
265
+ rh: 32
266
+ }
267
+ ];
268
+ /** A hollow cylindrical water tower with a conical roof — a non-box shape that
269
+ * still exercises pitched-roof (the cone tapers to an apex) + hollow + bbox. */
270
+ const WATER_TOWER_GOLD = `
271
+ $fn=48; r=24; bh=72; t=3; ch=26;
272
+ union(){
273
+ difference(){ cylinder(h=bh, r=r); translate([0,0,t]) cylinder(h=bh, r=r-t); }
274
+ translate([0,0,bh]) cylinder(h=ch, r1=r, r2=0);
275
+ }
276
+ `.trim();
277
+ /** An A-frame: the steep roof IS the walls — a hollow triangular prism. The most
278
+ * extreme taper in the set; tests that the agent can build a non-rectangular shell. */
279
+ const AFRAME_GOLD = `
280
+ w=44; d=60; h=66; t=3;
281
+ module tri(w,d,h){ rotate([90,0,90]) linear_extrude(height=w) polygon([[0,0],[d,0],[d/2,h]]); }
282
+ union(){
283
+ difference(){ tri(w,d,h); translate([t,0,0]) tri(w-2*t,d,h-2*t*h/d); }
284
+ translate([w/2-7,-1,0]) cube([14,t+2,24]);
285
+ }
286
+ `.trim();
287
+ const TASKS = [
288
+ {
289
+ id: "two-story-house",
290
+ prompt: [
291
+ "Write OpenSCAD source for a two-story house.",
292
+ "Requirements:",
293
+ "- footprint roughly 80 (X) by 60 (Y) units",
294
+ "- two stories, total wall height ~68 units",
295
+ "- a PITCHED / gabled roof on top (NOT a flat roof) — the roof must taper toward a ridge",
296
+ "- hollow shell (walls with an interior cavity), not a solid block",
297
+ "- at least one door opening and several windows",
298
+ "Output ONLY the .scad source, no prose, no code fences."
299
+ ].join("\n"),
300
+ meta: {
301
+ spec: {
302
+ volumes: [1, 12],
303
+ bbox: {
304
+ x: [70, 110],
305
+ y: [50, 80],
306
+ z: [80, 130]
307
+ },
308
+ minTriangles: 60,
309
+ pitchedRoof: .55,
310
+ hollowBelow: .7
311
+ },
312
+ gold: `
313
+ w=80; d=60; sh=34; t=3; rh=28;
314
+ module shell(w,d,h,t){ difference(){ cube([w,d,h]); translate([t,t,-1]) cube([w-2*t,d-2*t,h+2]); } }
315
+ module roof(w,d,h){ translate([0,0,0]) rotate([90,0,90]) linear_extrude(height=w) polygon([[0,0],[d,0],[d/2,h]]); }
316
+ union(){
317
+ for(s=[0,1]) translate([0,0,s*sh]) shell(w,d,sh,t);
318
+ for(s=[0,1,2]) translate([0,0,s*sh-1]) cube([w,d,1]);
319
+ translate([0,0,2*sh]) roof(w,d,rh);
320
+ for(s=[0,1]) for(i=[0:2]) translate([16+i*22,-1,s*sh+10]) cube([12,t+2,14]);
321
+ translate([w/2-8,-1,2]) cube([16,t+2,22]);
322
+ }
323
+ `.trim()
324
+ }
325
+ },
326
+ ...BUILDING_CONFIGS.map(buildingTask),
327
+ {
328
+ id: "water-tower",
329
+ prompt: [
330
+ "Write OpenSCAD source for a water tower: a tall hollow cylindrical tank with a conical roof.",
331
+ "Requirements:",
332
+ "- a hollow cylindrical tank, ~48 units in diameter, ~72 units tall, with an interior cavity",
333
+ "- a CONICAL roof on top that tapers to a point (a pitched roof)",
334
+ "- wall thickness around 3 units",
335
+ "Output ONLY the .scad source, no prose, no code fences."
336
+ ].join("\n"),
337
+ meta: {
338
+ spec: {
339
+ volumes: [1, 4],
340
+ bbox: {
341
+ x: [40, 56],
342
+ y: [40, 56],
343
+ z: [88, 110]
344
+ },
345
+ minTriangles: 60,
346
+ pitchedRoof: .55,
347
+ hollowBelow: .8
348
+ },
349
+ gold: WATER_TOWER_GOLD
350
+ }
351
+ },
352
+ {
353
+ id: "a-frame-cabin",
354
+ prompt: [
355
+ "Write OpenSCAD source for an A-frame cabin: a steep triangular shell where the roof forms the walls.",
356
+ "Requirements:",
357
+ "- footprint roughly 44 (X) by 60 (Y) units",
358
+ "- a STEEP triangular cross-section ~66 units tall that tapers to a ridge at the top",
359
+ "- hollow inside (an interior cavity), not a solid wedge",
360
+ "- a door opening at the front",
361
+ "Output ONLY the .scad source, no prose, no code fences."
362
+ ].join("\n"),
363
+ meta: {
364
+ spec: {
365
+ volumes: [1, 4],
366
+ bbox: {
367
+ x: [36, 52],
368
+ y: [50, 74],
369
+ z: [56, 80]
370
+ },
371
+ minTriangles: 30,
372
+ pitchedRoof: .45,
373
+ hollowBelow: .8
374
+ },
375
+ gold: AFRAME_GOLD
376
+ }
377
+ },
378
+ {
379
+ id: "hex-planter",
380
+ prompt: [
381
+ "Write OpenSCAD source for a hexagonal planter pot.",
382
+ "Requirements:",
383
+ "- a hollow hexagonal prism (6-sided), outer width ~50 units across, height ~45",
384
+ "- open at the top, closed at the bottom (a cavity for soil)",
385
+ "- a wall thickness around 3 units",
386
+ "Output ONLY the .scad source, no prose, no code fences."
387
+ ].join("\n"),
388
+ meta: {
389
+ spec: {
390
+ volumes: [1, 3],
391
+ bbox: {
392
+ x: [40, 60],
393
+ y: [40, 60],
394
+ z: [40, 55]
395
+ },
396
+ minTriangles: 30,
397
+ hollowBelow: .7
398
+ },
399
+ gold: `
400
+ $fn=6; or=25; h=45; t=3;
401
+ difference(){
402
+ cylinder(h=h, r=or);
403
+ translate([0,0,t]) cylinder(h=h, r=or-t);
404
+ }
405
+ `.trim()
406
+ }
407
+ }
408
+ ];
409
+ function createCadDesignAdapter() {
410
+ return {
411
+ name: "cad-design",
412
+ async preflight() {
413
+ try {
414
+ await execFileAsync("xvfb-run", [
415
+ "-a",
416
+ "openscad",
417
+ "--version"
418
+ ], { timeout: 3e4 });
419
+ } catch (err) {
420
+ const msg = err instanceof Error ? err.message : String(err);
421
+ throw new Error(`cad-design preflight failed: ${msg}\nFix: install OpenSCAD + Xvfb (Debian/Ubuntu: sudo apt-get install -y openscad xvfb). The judge runs \`xvfb-run -a openscad -o out.stl model.scad\` — both must be on PATH.`);
422
+ }
423
+ },
424
+ async loadTasks(opts = {}) {
425
+ let tasks = TASKS;
426
+ if (opts.ids) tasks = tasks.filter((t) => opts.ids.includes(t.id));
427
+ if (opts.limit != null) tasks = tasks.slice(0, opts.limit);
428
+ return tasks.map((t) => ({
429
+ id: t.id,
430
+ prompt: t.prompt,
431
+ metadata: t.meta
432
+ }));
433
+ },
434
+ async goldArtifact(task) {
435
+ return task.metadata?.gold;
436
+ },
437
+ async judge(task, artifact) {
438
+ const spec = task.metadata.spec;
439
+ const src = artifact.trim();
440
+ if (!src) return {
441
+ resolved: false,
442
+ score: 0,
443
+ detail: "empty artifact"
444
+ };
445
+ const dir = await mkdtemp(join(tmpdir(), "cad-"));
446
+ const scad = join(dir, "model.scad");
447
+ const stlPath = join(dir, "model.stl");
448
+ const pngPath = join(dir, "model.png");
449
+ await writeFile(scad, src);
450
+ let stderr = "";
451
+ try {
452
+ stderr = (await openscad([
453
+ "-o",
454
+ stlPath,
455
+ scad
456
+ ], dir)).stderr;
457
+ } catch (err) {
458
+ return {
459
+ resolved: false,
460
+ score: 0,
461
+ detail: `compile failed: ${(err instanceof Error ? err.message : String(err)).slice(0, 300)}`
462
+ };
463
+ }
464
+ try {
465
+ await openscad([
466
+ "-o",
467
+ pngPath,
468
+ "--imgsize=1100,850",
469
+ "--camera=40,30,40,55,0,25,260",
470
+ "--colorscheme=Tomorrow",
471
+ scad
472
+ ], dir);
473
+ } catch {}
474
+ let stl;
475
+ try {
476
+ stl = await readFile(stlPath, "utf8");
477
+ } catch {
478
+ return {
479
+ resolved: false,
480
+ score: 0,
481
+ detail: "compiled but produced no STL (empty geometry)"
482
+ };
483
+ }
484
+ const volumes = Number(/Volumes:\s*(\d+)/.exec(stderr)?.[1] ?? "1");
485
+ const geo = measureStl(stl, volumes);
486
+ const { checks, score } = scoreGeometry(geo, spec);
487
+ return {
488
+ resolved: score === 1,
489
+ score,
490
+ detail: JSON.stringify({
491
+ checks,
492
+ geo: {
493
+ triangles: geo.triangles,
494
+ volumes: geo.volumes,
495
+ bbox: {
496
+ x: +geo.bbox.x.toFixed(1),
497
+ y: +geo.bbox.y.toFixed(1),
498
+ z: +geo.bbox.z.toFixed(1)
499
+ },
500
+ hollowRatio: +(geo.solidVolume / geo.bboxVolume).toFixed(3),
501
+ topVsBaseFootprint: geo.baseFootprint ? +(geo.topFootprint / geo.baseFootprint).toFixed(3) : null
502
+ },
503
+ renderPath: pngPath,
504
+ stlPath
505
+ })
506
+ };
507
+ }
508
+ };
509
+ }
510
+ //#endregion
511
+ export { createCadDesignAdapter };
512
+
7
513
  //# sourceMappingURL=cad-design.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
1
+ {"version":3,"file":"cad-design.js","names":[],"sources":["../../src/benchmarks/cad-design.ts"],"sourcesContent":["/**\n * CAD-Design adapter. Worker artifact = OpenSCAD source (`.scad`). Judge = the\n * REAL OpenSCAD engine: compile + export STL, then measure the produced solid\n * geometry against the task's spec. Fully deterministic — the authoritative CAD\n * kernel is the gate, not an LLM and not the agent's own claim.\n *\n * This is verifiable-reward CAD: an agent is far better at *writing* exact\n * parametric code than at clicking a GUI, and the kernel either produces the\n * specified geometry or it doesn't. Every judged artifact also renders a PNG,\n * so a refine loop's attempts become a watchable \"model getting better\" reel\n * (run-capsule consumes the renders).\n *\n * Spec checks are geometric and ungameable:\n * - compiles : `openscad -o out.stl` exits 0 (hard gate)\n * - volumes : disconnected-solid count within [min,max]\n * - bbox : overall X/Y/Z extent within bounds (the thing is the right size)\n * - detail : triangle count ≥ floor (not a degenerate single cube)\n * - pitchedRoof : the top band's XY footprint NARROWS vs the base — a flat\n * box can't fake this; a real gabled/hipped roof tapers\n * - hollow : interior cavity present (walls, not a solid block) — the\n * bbox volume materially exceeds the printed solid volume\n *\n * Requires only `openscad` + `xvfb-run` on PATH (no venv, no Docker, no network).\n */\n\nimport { execFile } from 'node:child_process'\nimport { mkdtemp, readFile, writeFile } from 'node:fs/promises'\nimport { tmpdir } from 'node:os'\nimport { join } from 'node:path'\nimport { promisify } from 'node:util'\nimport type { BenchmarkAdapter, BenchScore, BenchTask, LoadOptions } from './types'\n\nconst execFileAsync = promisify(execFile)\n\n/** Spec assertions a CAD task can require. All are deterministic + geometric. */\nexport interface CadSpec {\n volumes?: [number, number]\n bbox?: { x?: [number, number]; y?: [number, number]; z?: [number, number] }\n minTriangles?: number\n /** Top-band XY footprint must be < this fraction of the base footprint. */\n pitchedRoof?: number\n /** Printed solid volume must be < this fraction of the bbox volume (hollow). */\n hollowBelow?: number\n}\n\ninterface CadTaskMeta {\n spec: CadSpec\n /** A known-good .scad that satisfies the spec — the oracle for verify-judge. */\n gold: string\n}\n\n/** Run openscad with xvfb (it needs a GL context even headless). */\nasync function openscad(args: string[], cwd: string): Promise<{ stdout: string; stderr: string }> {\n // -a => auto-pick a free display; openscad writes Facets/Volumes to stderr.\n const { stdout, stderr } = await execFileAsync('xvfb-run', ['-a', 'openscad', ...args], {\n cwd,\n maxBuffer: 1024 * 1024 * 64,\n timeout: 120_000,\n })\n return { stdout, stderr }\n}\n\ninterface Geometry {\n triangles: number\n volumes: number\n bbox: { x: number; y: number; z: number }\n /** XY footprint area (extent_x * extent_y) of the bottom 60% and top 25% z-bands. */\n baseFootprint: number\n topFootprint: number\n /** Convex-ish solid volume estimate from the STL (sum of signed tetra volumes). */\n solidVolume: number\n bboxVolume: number\n}\n\n/** Parse an ASCII STL into the geometric measures the spec checks. Pure. */\nfunction measureStl(stl: string, volumesFromStderr: number): Geometry {\n const verts: Array<[number, number, number]> = []\n const tris: Array<[[number, number, number], [number, number, number], [number, number, number]]> = []\n const re = /vertex\\s+(-?[\\d.eE+]+)\\s+(-?[\\d.eE+]+)\\s+(-?[\\d.eE+]+)/g\n let m: RegExpExecArray | null\n const flat: Array<[number, number, number]> = []\n while ((m = re.exec(stl))) flat.push([Number(m[1]), Number(m[2]), Number(m[3])])\n for (let i = 0; i + 2 < flat.length; i += 3) tris.push([flat[i]!, flat[i + 1]!, flat[i + 2]!])\n for (const v of flat) verts.push(v)\n\n const xs = verts.map((v) => v[0])\n const ys = verts.map((v) => v[1])\n const zs = verts.map((v) => v[2])\n const min = (a: number[]) => Math.min(...a)\n const max = (a: number[]) => Math.max(...a)\n const minZ = min(zs)\n const maxZ = max(zs)\n const h = maxZ - minZ || 1\n\n // Footprint of a z-band = XY extent of the vertices within it.\n const footprint = (lo: number, hi: number): number => {\n const band = verts.filter((v) => v[2] >= minZ + lo * h && v[2] <= minZ + hi * h)\n if (band.length < 3) return 0\n const bx = band.map((v) => v[0])\n const by = band.map((v) => v[1])\n return (max(bx) - min(bx)) * (max(by) - min(by))\n }\n\n // Signed volume via the divergence theorem over triangles (|Σ v0·(v1×v2)/6|).\n let vol6 = 0\n for (const [a, b, c] of tris) {\n vol6 +=\n a[0] * (b[1] * c[2] - b[2] * c[1]) -\n a[1] * (b[0] * c[2] - b[2] * c[0]) +\n a[2] * (b[0] * c[1] - b[1] * c[0])\n }\n const bbox = { x: max(xs) - min(xs), y: max(ys) - min(ys), z: maxZ - minZ }\n return {\n triangles: tris.length,\n volumes: volumesFromStderr,\n bbox,\n baseFootprint: footprint(0, 0.6),\n topFootprint: footprint(0.75, 1),\n solidVolume: Math.abs(vol6) / 6,\n bboxVolume: bbox.x * bbox.y * bbox.z || 1,\n }\n}\n\nfunction inRange(v: number, [lo, hi]: [number, number]): boolean {\n return v >= lo && v <= hi\n}\n\n/** Score the geometry against the spec — each check is a named pass/fail. */\nfunction scoreGeometry(g: Geometry, spec: CadSpec): { checks: Record<string, boolean>; score: number } {\n const checks: Record<string, boolean> = {}\n if (spec.volumes) checks.volumes = inRange(g.volumes, spec.volumes)\n if (spec.minTriangles != null) checks.detail = g.triangles >= spec.minTriangles\n if (spec.bbox?.x) checks.bboxX = inRange(g.bbox.x, spec.bbox.x)\n if (spec.bbox?.y) checks.bboxY = inRange(g.bbox.y, spec.bbox.y)\n if (spec.bbox?.z) checks.bboxZ = inRange(g.bbox.z, spec.bbox.z)\n if (spec.pitchedRoof != null)\n checks.pitchedRoof = g.baseFootprint > 0 && g.topFootprint < spec.pitchedRoof * g.baseFootprint\n if (spec.hollowBelow != null) checks.hollow = g.solidVolume < spec.hollowBelow * g.bboxVolume\n const vals = Object.values(checks)\n const score = vals.length ? vals.filter(Boolean).length / vals.length : 0\n return { checks, score }\n}\n\n/** A parametric multi-story gabled building — the gold generator for the\n * building-family tasks. They share geometry (hollow stacked shells + a gabled\n * roof that tapers to a ridge + cut openings) and differ only in dimensions, so\n * one verified generator yields a spec-passing oracle for each. */\nfunction buildingGold(w: number, d: number, sh: number, ns: number, rh: number, t = 3): string {\n return `\nw=${w}; d=${d}; sh=${sh}; ns=${ns}; rh=${rh}; t=${t};\nmodule shell(w,d,h,t){ difference(){ cube([w,d,h]); translate([t,t,-1]) cube([w-2*t,d-2*t,h+2]); } }\nmodule roof(w,d,h){ rotate([90,0,90]) linear_extrude(height=w) polygon([[0,0],[d,0],[d/2,h]]); }\nunion(){\n for(s=[0:ns-1]) translate([0,0,s*sh]) shell(w,d,sh,t);\n for(s=[0:ns]) translate([0,0,s*sh-0.5]) cube([w,d,1]);\n translate([0,0,ns*sh]) roof(w,d,rh);\n for(s=[0:ns-1]) for(i=[0:floor((w-28)/22)]) translate([14+i*22,-1,s*sh+10]) cube([10,t+2,12]);\n translate([w/2-7,-1,2]) cube([14,t+2,20]);\n}\n`.trim()\n}\n\n/** Build a building-family task (prompt + spec + gold) from its dimensions.\n * The spec's bbox is derived from the dims with a ±~18% tolerance so the agent\n * must respect the brief's size; the gold (buildingGold) lands exactly on the\n * nominal dims, so it passes by construction. Keep rh > ns*sh/3 (else the roof\n * base sits inside the top-25% band and pitchedRoof fails). */\nfunction buildingTask(o: { id: string; desc: string; w: number; d: number; sh: number; ns: number; rh: number }): {\n id: string\n prompt: string\n meta: CadTaskMeta\n} {\n const { id, desc, w, d, sh, ns, rh } = o\n const totalWall = ns * sh\n const totalH = totalWall + rh\n const r = Math.round\n const spec: CadSpec = {\n volumes: [1, ns * 4 + 6],\n bbox: {\n x: [r(w * 0.82), r(w * 1.18)],\n y: [r(d * 0.82), r((d + 1) * 1.2)],\n z: [r(totalH * 0.82), r((totalH + 1) * 1.2)],\n },\n minTriangles: 50,\n pitchedRoof: 0.55,\n hollowBelow: 0.72,\n }\n const prompt = [\n `Write OpenSCAD source for ${desc}.`,\n 'Requirements:',\n `- footprint roughly ${w} (X) by ${d} (Y) units`,\n ns > 1 ? `- ${ns} stories, total wall height ~${totalWall} units` : `- one story, wall height ~${sh} units`,\n '- a PITCHED / gabled roof on top that tapers toward a ridge (NOT flat)',\n '- hollow shell (walls with an interior cavity), not a solid block',\n '- a door opening and several windows',\n 'Output ONLY the .scad source, no prose, no code fences.',\n ].join('\\n')\n return { id, prompt, meta: { spec, gold: buildingGold(w, d, sh, ns, rh) } }\n}\n\n/** The building family — one parametric skill (hit the bbox + pitched roof +\n * hollow shell), sampled across footprints, heights, story counts, roof rises. */\nconst BUILDING_CONFIGS: Array<{ id: string; desc: string; w: number; d: number; sh: number; ns: number; rh: number }> = [\n { id: 'cottage', desc: 'a single-story cottage', w: 50, d: 40, sh: 30, ns: 1, rh: 18 },\n { id: 'cabin', desc: 'a small one-room cabin', w: 44, d: 36, sh: 26, ns: 1, rh: 22 },\n { id: 'bungalow', desc: 'a wide single-story bungalow', w: 70, d: 52, sh: 28, ns: 1, rh: 20 },\n { id: 'barn', desc: 'a long deep barn', w: 60, d: 96, sh: 42, ns: 1, rh: 26 },\n { id: 'warehouse', desc: 'a large warehouse', w: 110, d: 80, sh: 40, ns: 1, rh: 26 },\n { id: 'chapel', desc: 'a narrow tall chapel with a steep roof', w: 40, d: 72, sh: 48, ns: 1, rh: 34 },\n { id: 'farmhouse', desc: 'a two-story farmhouse', w: 72, d: 56, sh: 30, ns: 2, rh: 26 },\n { id: 'two-story-manor', desc: 'a wide two-story manor', w: 96, d: 64, sh: 32, ns: 2, rh: 28 },\n { id: 'townhouse', desc: 'a narrow three-story townhouse', w: 42, d: 52, sh: 30, ns: 3, rh: 34 },\n { id: 'watchtower', desc: 'a tall narrow three-story watchtower', w: 34, d: 34, sh: 30, ns: 3, rh: 32 },\n]\n\n/** A hollow cylindrical water tower with a conical roof — a non-box shape that\n * still exercises pitched-roof (the cone tapers to an apex) + hollow + bbox. */\nconst WATER_TOWER_GOLD = `\n$fn=48; r=24; bh=72; t=3; ch=26;\nunion(){\n difference(){ cylinder(h=bh, r=r); translate([0,0,t]) cylinder(h=bh, r=r-t); }\n translate([0,0,bh]) cylinder(h=ch, r1=r, r2=0);\n}\n`.trim()\n\n/** An A-frame: the steep roof IS the walls — a hollow triangular prism. The most\n * extreme taper in the set; tests that the agent can build a non-rectangular shell. */\nconst AFRAME_GOLD = `\nw=44; d=60; h=66; t=3;\nmodule tri(w,d,h){ rotate([90,0,90]) linear_extrude(height=w) polygon([[0,0],[d,0],[d/2,h]]); }\nunion(){\n difference(){ tri(w,d,h); translate([t,0,0]) tri(w-2*t,d,h-2*t*h/d); }\n translate([w/2-7,-1,0]) cube([14,t+2,24]);\n}\n`.trim()\n\nconst TASKS: Array<{ id: string; prompt: string; meta: CadTaskMeta }> = [\n {\n id: 'two-story-house',\n prompt: [\n 'Write OpenSCAD source for a two-story house.',\n 'Requirements:',\n '- footprint roughly 80 (X) by 60 (Y) units',\n '- two stories, total wall height ~68 units',\n '- a PITCHED / gabled roof on top (NOT a flat roof) — the roof must taper toward a ridge',\n '- hollow shell (walls with an interior cavity), not a solid block',\n '- at least one door opening and several windows',\n 'Output ONLY the .scad source, no prose, no code fences.',\n ].join('\\n'),\n meta: {\n spec: {\n volumes: [1, 12],\n bbox: { x: [70, 110], y: [50, 80], z: [80, 130] },\n minTriangles: 60,\n pitchedRoof: 0.55,\n hollowBelow: 0.7,\n },\n gold: `\nw=80; d=60; sh=34; t=3; rh=28;\nmodule shell(w,d,h,t){ difference(){ cube([w,d,h]); translate([t,t,-1]) cube([w-2*t,d-2*t,h+2]); } }\nmodule roof(w,d,h){ translate([0,0,0]) rotate([90,0,90]) linear_extrude(height=w) polygon([[0,0],[d,0],[d/2,h]]); }\nunion(){\n for(s=[0,1]) translate([0,0,s*sh]) shell(w,d,sh,t);\n for(s=[0,1,2]) translate([0,0,s*sh-1]) cube([w,d,1]);\n translate([0,0,2*sh]) roof(w,d,rh);\n for(s=[0,1]) for(i=[0:2]) translate([16+i*22,-1,s*sh+10]) cube([12,t+2,14]);\n translate([w/2-8,-1,2]) cube([16,t+2,22]);\n}\n`.trim(),\n },\n },\n ...BUILDING_CONFIGS.map(buildingTask),\n {\n id: 'water-tower',\n prompt: [\n 'Write OpenSCAD source for a water tower: a tall hollow cylindrical tank with a conical roof.',\n 'Requirements:',\n '- a hollow cylindrical tank, ~48 units in diameter, ~72 units tall, with an interior cavity',\n '- a CONICAL roof on top that tapers to a point (a pitched roof)',\n '- wall thickness around 3 units',\n 'Output ONLY the .scad source, no prose, no code fences.',\n ].join('\\n'),\n meta: {\n spec: {\n volumes: [1, 4],\n bbox: { x: [40, 56], y: [40, 56], z: [88, 110] },\n minTriangles: 60,\n pitchedRoof: 0.55,\n hollowBelow: 0.8,\n },\n gold: WATER_TOWER_GOLD,\n },\n },\n {\n id: 'a-frame-cabin',\n prompt: [\n 'Write OpenSCAD source for an A-frame cabin: a steep triangular shell where the roof forms the walls.',\n 'Requirements:',\n '- footprint roughly 44 (X) by 60 (Y) units',\n '- a STEEP triangular cross-section ~66 units tall that tapers to a ridge at the top',\n '- hollow inside (an interior cavity), not a solid wedge',\n '- a door opening at the front',\n 'Output ONLY the .scad source, no prose, no code fences.',\n ].join('\\n'),\n meta: {\n spec: {\n volumes: [1, 4],\n bbox: { x: [36, 52], y: [50, 74], z: [56, 80] },\n minTriangles: 30,\n pitchedRoof: 0.45,\n hollowBelow: 0.8,\n },\n gold: AFRAME_GOLD,\n },\n },\n {\n id: 'hex-planter',\n prompt: [\n 'Write OpenSCAD source for a hexagonal planter pot.',\n 'Requirements:',\n '- a hollow hexagonal prism (6-sided), outer width ~50 units across, height ~45',\n '- open at the top, closed at the bottom (a cavity for soil)',\n '- a wall thickness around 3 units',\n 'Output ONLY the .scad source, no prose, no code fences.',\n ].join('\\n'),\n meta: {\n spec: {\n volumes: [1, 3],\n bbox: { x: [40, 60], y: [40, 60], z: [40, 55] },\n minTriangles: 30,\n hollowBelow: 0.7,\n },\n gold: `\n$fn=6; or=25; h=45; t=3;\ndifference(){\n cylinder(h=h, r=or);\n translate([0,0,t]) cylinder(h=h, r=or-t);\n}\n`.trim(),\n },\n },\n]\n\nexport function createCadDesignAdapter(): BenchmarkAdapter {\n return {\n name: 'cad-design',\n\n async preflight() {\n try {\n await execFileAsync('xvfb-run', ['-a', 'openscad', '--version'], { timeout: 30_000 })\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n throw new Error(\n `cad-design preflight failed: ${msg}\\n` +\n `Fix: install OpenSCAD + Xvfb (Debian/Ubuntu: sudo apt-get install -y openscad xvfb). ` +\n `The judge runs \\`xvfb-run -a openscad -o out.stl model.scad\\` — both must be on PATH.`,\n )\n }\n },\n\n async loadTasks(opts: LoadOptions = {}) {\n let tasks = TASKS\n if (opts.ids) tasks = tasks.filter((t) => opts.ids!.includes(t.id))\n if (opts.limit != null) tasks = tasks.slice(0, opts.limit)\n return tasks.map((t): BenchTask => ({ id: t.id, prompt: t.prompt, metadata: t.meta as unknown as Record<string, unknown> }))\n },\n\n async goldArtifact(task: BenchTask) {\n const meta = task.metadata as unknown as CadTaskMeta | undefined\n return meta?.gold\n },\n\n async judge(task: BenchTask, artifact: string): Promise<BenchScore> {\n const spec = (task.metadata as unknown as CadTaskMeta).spec\n const src = artifact.trim()\n if (!src) return { resolved: false, score: 0, detail: 'empty artifact' }\n\n const dir = await mkdtemp(join(tmpdir(), 'cad-'))\n const scad = join(dir, 'model.scad')\n const stlPath = join(dir, 'model.stl')\n const pngPath = join(dir, 'model.png')\n await writeFile(scad, src)\n\n // GATE 1: compile + export STL. Nonzero exit / CGAL error => does not compile.\n let stderr = ''\n try {\n const r = await openscad(['-o', stlPath, scad], dir)\n stderr = r.stderr\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n return { resolved: false, score: 0, detail: `compile failed: ${msg.slice(0, 300)}` }\n }\n\n // Render a PNG alongside (the artifact run-capsule animates). Non-fatal.\n try {\n await openscad(\n ['-o', pngPath, '--imgsize=1100,850', '--camera=40,30,40,55,0,25,260', '--colorscheme=Tomorrow', scad],\n dir,\n )\n } catch {\n /* render is for the reel; geometry gate already has the STL */\n }\n\n let stl: string\n try {\n stl = await readFile(stlPath, 'utf8')\n } catch {\n return { resolved: false, score: 0, detail: 'compiled but produced no STL (empty geometry)' }\n }\n const volumes = Number(/Volumes:\\s*(\\d+)/.exec(stderr)?.[1] ?? '1')\n const geo = measureStl(stl, volumes)\n const { checks, score } = scoreGeometry(geo, spec)\n const resolved = score === 1\n const detail = JSON.stringify({\n checks,\n geo: {\n triangles: geo.triangles,\n volumes: geo.volumes,\n bbox: { x: +geo.bbox.x.toFixed(1), y: +geo.bbox.y.toFixed(1), z: +geo.bbox.z.toFixed(1) },\n hollowRatio: +(geo.solidVolume / geo.bboxVolume).toFixed(3),\n topVsBaseFootprint: geo.baseFootprint ? +(geo.topFootprint / geo.baseFootprint).toFixed(3) : null,\n },\n renderPath: pngPath,\n stlPath,\n })\n return { resolved, score, detail }\n },\n }\n}\n"],"mappings":"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"}
@@ -1,19 +1,6 @@
1
- import { BenchmarkAdapter } from './types.js';
2
- import '@tangle-network/agent-runtime/loops';
3
-
4
- /**
5
- * CADBench / BlenderLLM adapter (FreedomIntelligence/CADBench, arXiv:2412.14203).
6
- * Task = NL instruction → a Blender `bpy` script. Score = the paper's criteria
7
- * eval: render the produced model to standardized views, then a vision judge
8
- * (GPT-4o-class) marks each per-task criterion bullet pass/fail against the
9
- * rendered images + the script text. score = fraction of criteria satisfied.
10
- *
11
- * Data: the published dataset's `criteria` flattened to a bullet list (700 tasks,
12
- * 500 Simulative + 200 Wild). Point CADBENCH_PATH at the cleaned JSONL
13
- * ({id,name,instruction,type,criteria:string[]} per line). Judge creds from
14
- * TANGLE_API_KEY / ROUTER_BASE / JUDGE_MODEL (default gpt-4o).
15
- */
16
-
1
+ import { BenchmarkAdapter } from "./types.js";
2
+ //#region src/benchmarks/cadbench.d.ts
17
3
  declare function createCadBenchAdapter(): BenchmarkAdapter;
18
-
4
+ //#endregion
19
5
  export { createCadBenchAdapter };
6
+ //# sourceMappingURL=cadbench.d.ts.map
@@ -1,8 +1,2 @@
1
- import {
2
- createCadBenchAdapter
3
- } from "../chunk-PUIRNYI7.js";
4
- import "../chunk-JTHWEDEW.js";
5
- export {
6
- createCadBenchAdapter
7
- };
8
- //# sourceMappingURL=cadbench.js.map
1
+ import { t as createCadBenchAdapter } from "../cadbench-DpQWZHp4.js";
2
+ export { createCadBenchAdapter };
@@ -1,22 +1,6 @@
1
- import { BenchmarkAdapter } from './types.js';
2
- import '@tangle-network/agent-runtime/loops';
3
-
4
- /**
5
- * CADGenBench adapter (huggingface/cadgenbench, Apache-2.0). Task = a part
6
- * description → a STEP B-rep solid (output.step). Score = the benchmark's OWN
7
- * deterministic geometric metric (cad_score): validity gate → PCA/ICP align to
8
- * the ground truth → point-cloud F1 + volume IoU + edge F1 + topology match.
9
- * NOT an LLM judge, NOT self-defined checks — the published CAD kernel decides.
10
- *
11
- * The official task set (private GT, server-side graded) isn't released yet, so
12
- * tasks here are seeded from the repo's dimension-named geometry fixtures (real
13
- * GT STEPs scored by the real scorer). When CADGENBENCH_DATA_DIR is set, swap
14
- * loadTasks to read the published fixtures' description.yaml + ground_truth.step.
15
- *
16
- * Requires the CADGenBench venv (CADGENBENCH_VENV) + clone (CADGENBENCH_DIR) +
17
- * xvfb (the scorer's alignment renders need a display).
18
- */
19
-
1
+ import { BenchmarkAdapter } from "./types.js";
2
+ //#region src/benchmarks/cadgenbench.d.ts
20
3
  declare function createCadGenBenchAdapter(): BenchmarkAdapter;
21
-
4
+ //#endregion
22
5
  export { createCadGenBenchAdapter };
6
+ //# sourceMappingURL=cadgenbench.d.ts.map
@@ -1,8 +1,2 @@
1
- import {
2
- createCadGenBenchAdapter
3
- } from "../chunk-C7T7WEK2.js";
4
- import "../chunk-JTHWEDEW.js";
5
- export {
6
- createCadGenBenchAdapter
7
- };
8
- //# sourceMappingURL=cadgenbench.js.map
1
+ import { t as createCadGenBenchAdapter } from "../cadgenbench-DRhczfsG.js";
2
+ export { createCadGenBenchAdapter };