@ggui-ai/ui-gen 0.27.0 → 0.29.0

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 (315) hide show
  1. package/dist/{adapter-h4_V69LI.d.ts → adapter-DLQ-5COm.d.ts} +1 -1
  2. package/dist/adapters/base.js +2 -27
  3. package/dist/adapters/base.js.map +1 -1
  4. package/dist/adapters/generation-dispatch.d.ts +14 -6
  5. package/dist/adapters/generation-dispatch.js +40 -19095
  6. package/dist/adapters/generation-dispatch.js.map +1 -1
  7. package/dist/adapters/index.d.ts +1 -1
  8. package/dist/adapters/index.js +25 -3561
  9. package/dist/adapters/index.js.map +1 -1
  10. package/dist/adapters/types.js +2 -9
  11. package/dist/adapters/types.js.map +1 -1
  12. package/dist/advanced/index.d.ts +13 -12
  13. package/dist/advanced/index.js +63 -21789
  14. package/dist/advanced/index.js.map +1 -1
  15. package/dist/{bank-Ctdp3FUA.d.ts → bank-LWaiAtaA.d.ts} +1 -1
  16. package/dist/blueprint-validator.js +6 -2301
  17. package/dist/blueprint-validator.js.map +1 -1
  18. package/dist/boilerplate.d.ts +3 -2
  19. package/dist/boilerplate.js +6 -1867
  20. package/dist/boilerplate.js.map +1 -1
  21. package/dist/check/index.d.ts +3 -2
  22. package/dist/check/index.js +6 -1923
  23. package/dist/check/index.js.map +1 -1
  24. package/dist/chunk-33B3BAWS.js +24 -0
  25. package/dist/chunk-33B3BAWS.js.map +1 -0
  26. package/dist/chunk-3HSGA6NI.js +591 -0
  27. package/dist/chunk-3HSGA6NI.js.map +1 -0
  28. package/dist/chunk-3NNNGNTO.js +1707 -0
  29. package/dist/chunk-3NNNGNTO.js.map +1 -0
  30. package/dist/chunk-3T2HMTON.js +79 -0
  31. package/dist/chunk-3T2HMTON.js.map +1 -0
  32. package/dist/chunk-3ZSSDV3L.js +123 -0
  33. package/dist/chunk-3ZSSDV3L.js.map +1 -0
  34. package/dist/chunk-4MBR5GA3.js +99 -0
  35. package/dist/chunk-4MBR5GA3.js.map +1 -0
  36. package/dist/chunk-56NJFD55.js +337 -0
  37. package/dist/chunk-56NJFD55.js.map +1 -0
  38. package/dist/chunk-5AGTY555.js +26 -0
  39. package/dist/chunk-5AGTY555.js.map +1 -0
  40. package/dist/chunk-5EJM7EGY.js +115 -0
  41. package/dist/chunk-5EJM7EGY.js.map +1 -0
  42. package/dist/chunk-5KXCQLLR.js +529 -0
  43. package/dist/chunk-5KXCQLLR.js.map +1 -0
  44. package/dist/chunk-5VBXHVEH.js +171 -0
  45. package/dist/chunk-5VBXHVEH.js.map +1 -0
  46. package/dist/chunk-6KDDEING.js +515 -0
  47. package/dist/chunk-6KDDEING.js.map +1 -0
  48. package/dist/chunk-6VDRWAP6.js +123 -0
  49. package/dist/chunk-6VDRWAP6.js.map +1 -0
  50. package/dist/chunk-732IBFEJ.js +2400 -0
  51. package/dist/chunk-732IBFEJ.js.map +1 -0
  52. package/dist/chunk-73AURS3I.js +46 -0
  53. package/dist/chunk-73AURS3I.js.map +1 -0
  54. package/dist/chunk-77H5SKLX.js +8 -0
  55. package/dist/chunk-77H5SKLX.js.map +1 -0
  56. package/dist/chunk-7QE3AHLE.js +35 -0
  57. package/dist/chunk-7QE3AHLE.js.map +1 -0
  58. package/dist/chunk-A375NNWN.js +11 -0
  59. package/dist/chunk-A375NNWN.js.map +1 -0
  60. package/dist/chunk-AOU33EFS.js +140 -0
  61. package/dist/chunk-AOU33EFS.js.map +1 -0
  62. package/dist/chunk-BA4QYA6E.js +461 -0
  63. package/dist/chunk-BA4QYA6E.js.map +1 -0
  64. package/dist/chunk-DBP764GL.js +3 -0
  65. package/dist/chunk-DBP764GL.js.map +1 -0
  66. package/dist/chunk-DUU3ZJDQ.js +41 -0
  67. package/dist/chunk-DUU3ZJDQ.js.map +1 -0
  68. package/dist/chunk-DXKRBXNU.js +30 -0
  69. package/dist/chunk-DXKRBXNU.js.map +1 -0
  70. package/dist/chunk-FB7OEEAH.js +1467 -0
  71. package/dist/chunk-FB7OEEAH.js.map +1 -0
  72. package/dist/chunk-FLRNMZV2.js +18 -0
  73. package/dist/chunk-FLRNMZV2.js.map +1 -0
  74. package/dist/chunk-FWJIMKFZ.js +2032 -0
  75. package/dist/chunk-FWJIMKFZ.js.map +1 -0
  76. package/dist/chunk-FXRHWYIQ.js +163 -0
  77. package/dist/chunk-FXRHWYIQ.js.map +1 -0
  78. package/dist/chunk-G3PMV62Z.js +33 -0
  79. package/dist/chunk-G3PMV62Z.js.map +1 -0
  80. package/dist/chunk-GAJI7Y3P.js +13 -0
  81. package/dist/chunk-GAJI7Y3P.js.map +1 -0
  82. package/dist/chunk-GYINWMPR.js +2052 -0
  83. package/dist/chunk-GYINWMPR.js.map +1 -0
  84. package/dist/chunk-HD6ABIK7.js +484 -0
  85. package/dist/chunk-HD6ABIK7.js.map +1 -0
  86. package/dist/chunk-HDQVHYO6.js +100 -0
  87. package/dist/chunk-HDQVHYO6.js.map +1 -0
  88. package/dist/chunk-IHUT3SIW.js +7 -0
  89. package/dist/chunk-IHUT3SIW.js.map +1 -0
  90. package/dist/chunk-JDH5EGNZ.js +126 -0
  91. package/dist/chunk-JDH5EGNZ.js.map +1 -0
  92. package/dist/chunk-JMD4RGSV.js +37 -0
  93. package/dist/chunk-JMD4RGSV.js.map +1 -0
  94. package/dist/chunk-KJWGZL5B.js +33 -0
  95. package/dist/chunk-KJWGZL5B.js.map +1 -0
  96. package/dist/chunk-MKMDQFZ7.js +86 -0
  97. package/dist/chunk-MKMDQFZ7.js.map +1 -0
  98. package/dist/chunk-NF6JUZWF.js +85 -0
  99. package/dist/chunk-NF6JUZWF.js.map +1 -0
  100. package/dist/chunk-O2YC6XDC.js +1933 -0
  101. package/dist/chunk-O2YC6XDC.js.map +1 -0
  102. package/dist/chunk-OVLH5ICV.js +29 -0
  103. package/dist/chunk-OVLH5ICV.js.map +1 -0
  104. package/dist/chunk-PBOYHGSD.js +106 -0
  105. package/dist/chunk-PBOYHGSD.js.map +1 -0
  106. package/dist/chunk-PJFH7QWA.js +81 -0
  107. package/dist/chunk-PJFH7QWA.js.map +1 -0
  108. package/dist/chunk-PUH4CXGZ.js +284 -0
  109. package/dist/chunk-PUH4CXGZ.js.map +1 -0
  110. package/dist/chunk-QLXXPGTV.js +18 -0
  111. package/dist/chunk-QLXXPGTV.js.map +1 -0
  112. package/dist/chunk-R5GIGPW2.js +2845 -0
  113. package/dist/chunk-R5GIGPW2.js.map +1 -0
  114. package/dist/chunk-RH4IUSTO.js +83 -0
  115. package/dist/chunk-RH4IUSTO.js.map +1 -0
  116. package/dist/chunk-S2GVXKKY.js +153 -0
  117. package/dist/chunk-S2GVXKKY.js.map +1 -0
  118. package/dist/chunk-TVHGKFJS.js +58 -0
  119. package/dist/chunk-TVHGKFJS.js.map +1 -0
  120. package/dist/chunk-U7GALWLG.js +66 -0
  121. package/dist/chunk-U7GALWLG.js.map +1 -0
  122. package/dist/chunk-VTC263LT.js +256 -0
  123. package/dist/chunk-VTC263LT.js.map +1 -0
  124. package/dist/chunk-WEOXFEVE.js +739 -0
  125. package/dist/chunk-WEOXFEVE.js.map +1 -0
  126. package/dist/chunk-WYHP46LT.js +28 -0
  127. package/dist/chunk-WYHP46LT.js.map +1 -0
  128. package/dist/chunk-XGLO5LGG.js +274 -0
  129. package/dist/chunk-XGLO5LGG.js.map +1 -0
  130. package/dist/chunk-XRBCRKA2.js +29 -0
  131. package/dist/chunk-XRBCRKA2.js.map +1 -0
  132. package/dist/chunk-XW7ADFFV.js +340 -0
  133. package/dist/chunk-XW7ADFFV.js.map +1 -0
  134. package/dist/chunk-YIQ42IUX.js +34 -0
  135. package/dist/chunk-YIQ42IUX.js.map +1 -0
  136. package/dist/chunk-YJZTUY7B.js +101 -0
  137. package/dist/chunk-YJZTUY7B.js.map +1 -0
  138. package/dist/chunk-Z3CXME3K.js +107 -0
  139. package/dist/chunk-Z3CXME3K.js.map +1 -0
  140. package/dist/classifier/index.js +2 -527
  141. package/dist/classifier/index.js.map +1 -1
  142. package/dist/client-JBPCXU7W.js +4 -0
  143. package/dist/client-JBPCXU7W.js.map +1 -0
  144. package/dist/compose.js +3 -367
  145. package/dist/compose.js.map +1 -1
  146. package/dist/cost-tracker-HHGQ4FTW.js +67 -0
  147. package/dist/cost-tracker-HHGQ4FTW.js.map +1 -0
  148. package/dist/{create-ui-generator-BrZHF0cf.d.ts → create-ui-generator-BY-WeaPi.d.ts} +3 -3
  149. package/dist/{design-mode-DGWN_Gkm.d.ts → design-mode-XyOQmzE0.d.ts} +4 -3
  150. package/dist/{dispatch-B07TI30d.d.ts → dispatch-8LzTddKw.d.ts} +3 -2
  151. package/dist/dist-UALN6ZVB.js +543 -0
  152. package/dist/dist-UALN6ZVB.js.map +1 -0
  153. package/dist/dupe-break-X6K7QFIS.js +4 -0
  154. package/dist/dupe-break-X6K7QFIS.js.map +1 -0
  155. package/dist/evaluation/axis-checks/index.d.ts +5 -4
  156. package/dist/evaluation/axis-checks/index.js +6 -1818
  157. package/dist/evaluation/axis-checks/index.js.map +1 -1
  158. package/dist/evaluation/axis-checks/registry.d.ts +3 -2
  159. package/dist/evaluation/axis-checks/registry.js +3 -1748
  160. package/dist/evaluation/axis-checks/registry.js.map +1 -1
  161. package/dist/evaluation/index.d.ts +49 -132
  162. package/dist/evaluation/index.js +302 -6368
  163. package/dist/evaluation/index.js.map +1 -1
  164. package/dist/evaluation/types.d.ts +3 -2
  165. package/dist/evaluation/types.js +2 -5
  166. package/dist/evaluation/types.js.map +1 -1
  167. package/dist/fragments/index.js +2 -338
  168. package/dist/fragments/index.js.map +1 -1
  169. package/dist/{generate-tSO_shQ0.d.ts → generate-DQ4ci90s.d.ts} +1 -1
  170. package/dist/harness/check/runtime-render/index.d.ts +35 -15
  171. package/dist/harness/check/runtime-render/index.js +6 -2390
  172. package/dist/harness/check/runtime-render/index.js.map +1 -1
  173. package/dist/harness/check/runtime-render/render-check-worker.js +4 -1739
  174. package/dist/harness/check/runtime-render/render-check-worker.js.map +1 -1
  175. package/dist/harness/index.d.ts +3 -2
  176. package/dist/harness/index.js +23 -5124
  177. package/dist/harness/index.js.map +1 -1
  178. package/dist/harness/llm-trace-sink.js +2 -24
  179. package/dist/harness/llm-trace-sink.js.map +1 -1
  180. package/dist/harness/prompts.d.ts +2 -2
  181. package/dist/harness/prompts.js +8 -324
  182. package/dist/harness/prompts.js.map +1 -1
  183. package/dist/harness/result-types.d.ts +18 -6
  184. package/dist/harness/result-types.js +2 -0
  185. package/dist/harness/result-types.js.map +1 -1
  186. package/dist/harness/runtime.d.ts +22 -5
  187. package/dist/harness/runtime.js +10 -2313
  188. package/dist/harness/runtime.js.map +1 -1
  189. package/dist/harness/types-public.d.ts +3 -2
  190. package/dist/harness/types-public.js +16 -2954
  191. package/dist/harness/types-public.js.map +1 -1
  192. package/dist/harness/validator-trace-sink.d.ts +3 -2
  193. package/dist/harness/validator-trace-sink.js +2 -26
  194. package/dist/harness/validator-trace-sink.js.map +1 -1
  195. package/dist/hash.js +2 -39
  196. package/dist/hash.js.map +1 -1
  197. package/dist/hashline-5OKREIRM.js +4 -0
  198. package/dist/hashline-5OKREIRM.js.map +1 -0
  199. package/dist/index.d.ts +51 -12
  200. package/dist/index.js +57 -21850
  201. package/dist/index.js.map +1 -1
  202. package/dist/llm-evaluator-PN3WFCS4.js +653 -0
  203. package/dist/llm-evaluator-PN3WFCS4.js.map +1 -0
  204. package/dist/magic-string.es-2NZTC4GZ.js +1307 -0
  205. package/dist/magic-string.es-2NZTC4GZ.js.map +1 -0
  206. package/dist/patch.d.ts +3 -2
  207. package/dist/patch.js +2 -56
  208. package/dist/patch.js.map +1 -1
  209. package/dist/policy-VCYKGSAC.js +5 -0
  210. package/dist/policy-VCYKGSAC.js.map +1 -0
  211. package/dist/policy.js +2 -35
  212. package/dist/policy.js.map +1 -1
  213. package/dist/primitive-index-2OF6F4TZ.js +131 -0
  214. package/dist/primitive-index-2OF6F4TZ.js.map +1 -0
  215. package/dist/primitive-slice-WTMBLYFJ.js +235 -0
  216. package/dist/primitive-slice-WTMBLYFJ.js.map +1 -0
  217. package/dist/{prompts-BhNUuRoZ.d.ts → prompts-CLZGywMP.d.ts} +1 -1
  218. package/dist/provider-adapter-contract.js +10407 -14204
  219. package/dist/provider-adapter-contract.js.map +1 -1
  220. package/dist/provider-adapter.js +2 -44
  221. package/dist/provider-adapter.js.map +1 -1
  222. package/dist/providers/index.d.ts +89 -1
  223. package/dist/providers/index.js +115 -44
  224. package/dist/providers/index.js.map +1 -1
  225. package/dist/raw-C6KBH5I3.js +141 -0
  226. package/dist/raw-C6KBH5I3.js.map +1 -0
  227. package/dist/raw-FXSBXQTZ.js +7 -0
  228. package/dist/raw-FXSBXQTZ.js.map +1 -0
  229. package/dist/raw-MURDUPGK.js +8 -0
  230. package/dist/raw-MURDUPGK.js.map +1 -0
  231. package/dist/raw-T3GW3UVX.js +8 -0
  232. package/dist/raw-T3GW3UVX.js.map +1 -0
  233. package/dist/render-check-host-ZNIS6BJ5.js +5 -0
  234. package/dist/render-check-host-ZNIS6BJ5.js.map +1 -0
  235. package/dist/sdk-4JNSDNSR.js +6 -0
  236. package/dist/sdk-4JNSDNSR.js.map +1 -0
  237. package/dist/sdk-DIVJMHCX.js +7 -0
  238. package/dist/sdk-DIVJMHCX.js.map +1 -0
  239. package/dist/sdk-QRJOCRTS.js +7 -0
  240. package/dist/sdk-QRJOCRTS.js.map +1 -0
  241. package/dist/tag-balance-CTHCTRJ7.js +123 -0
  242. package/dist/tag-balance-CTHCTRJ7.js.map +1 -0
  243. package/dist/tools/get-primitives-ts.d.ts +1 -1
  244. package/dist/tools/get-primitives-ts.js +3 -1
  245. package/dist/tools/get-primitives-ts.js.map +1 -1
  246. package/dist/tools/render-check-worker.js +3 -40
  247. package/dist/tools/render-check-worker.js.map +1 -1
  248. package/dist/{types-public-h8IMnYuh.d.ts → types-public-hYlrerZh.d.ts} +35 -2
  249. package/dist/validation/index.d.ts +2 -2
  250. package/dist/validation/index.js +3 -498
  251. package/dist/validation/index.js.map +1 -1
  252. package/dist/{visual-evaluator-C2strxqD.d.ts → visual-evaluator-KskajxD5.d.ts} +14 -4
  253. package/dist/visual-evaluator-TGEXYQTP.js +12 -0
  254. package/dist/visual-evaluator-TGEXYQTP.js.map +1 -0
  255. package/dist/workflows.d.ts +3 -2
  256. package/dist/workflows.js +2 -151
  257. package/dist/workflows.js.map +1 -1
  258. package/package.json +21 -17
  259. package/src/adapters/claude/sdk.ts +4 -2
  260. package/src/adapters/claude/tool-bridge.ts +2 -1
  261. package/src/adapters/generation-dispatch.ts +9 -0
  262. package/src/adapters/openai/raw.ts +4 -0
  263. package/src/adapters/openai/sdk.ts +6 -1
  264. package/src/adapters/openai/tokens.ts +21 -7
  265. package/src/adapters/provider-router.ts +1 -0
  266. package/src/adapters/tool-bridge.ts +1 -1
  267. package/src/adapters/tools.ts +1 -1
  268. package/src/advanced/feedback.ts +1 -2
  269. package/src/advanced/generator.ts +4 -3
  270. package/src/boilerplate/free-design-prompt.ts +7 -0
  271. package/src/boilerplate/generate.ts +18 -5
  272. package/src/boilerplate/hard-sections.ts +8 -3
  273. package/src/boilerplate/react-hooks.ts +56 -0
  274. package/src/boilerplate/system-prompt.ts +12 -3
  275. package/src/check/run-tier0.ts +233 -8
  276. package/src/check/type-checker.ts +128 -16
  277. package/src/coding-agent/tools.ts +26 -3
  278. package/src/create-ui-generator.ts +4 -2
  279. package/src/design-mode.ts +4 -9
  280. package/src/evaluation/axis-checks/checks/state-merge.ts +3 -5
  281. package/src/evaluation/axis-checks/checks/state-payload.ts +1 -28
  282. package/src/evaluation/axis-checks/checks/tint.ts +197 -0
  283. package/src/evaluation/axis-checks/helpers.ts +246 -0
  284. package/src/evaluation/axis-checks/registry.ts +2 -0
  285. package/src/evaluation/criteria/__fixtures__/edge-v2-draw2.json +4629 -0
  286. package/src/evaluation/criteria/bank.ts +1 -1
  287. package/src/evaluation/criteria/edge-instruments.ts +14 -0
  288. package/src/evaluation/criteria/edge-probe-v2.ts +352 -0
  289. package/src/evaluation/criteria/edge-v2.ts +242 -0
  290. package/src/evaluation/criteria/resolve.ts +24 -5
  291. package/src/evaluation/evaluator.ts +2 -2
  292. package/src/evaluation/index.ts +3 -5
  293. package/src/evaluation/llm-evaluator.ts +2 -2
  294. package/src/evaluation/mcp-server.ts +0 -50
  295. package/src/evaluation/types-public.ts +6 -1
  296. package/src/evaluation/visual-evaluator.ts +162 -31
  297. package/src/harness/check/runtime-render/index.ts +28 -4
  298. package/src/harness/check/runtime-render/render-check.ts +20 -21
  299. package/src/harness/claude-agent-sdk-loader.ts +93 -0
  300. package/src/harness/claude-code-login-query.ts +1 -1
  301. package/src/harness/coding/assemble-result.ts +1 -0
  302. package/src/harness/coding/dupe-break.ts +70 -0
  303. package/src/harness/coding/generate-task-runner.ts +6 -1
  304. package/src/harness/coding/run-coding-turn.ts +59 -1
  305. package/src/harness/coding/run-eval-round.ts +9 -0
  306. package/src/harness/llm-router.ts +50 -2
  307. package/src/harness/result-types.ts +12 -0
  308. package/src/harness/runtime.ts +17 -0
  309. package/src/index.ts +10 -1
  310. package/src/providers/anthropic-tool-call.ts +263 -0
  311. package/src/providers/index.ts +13 -0
  312. package/src/tools/get-primitives-ts.ts +1 -1
  313. package/src/tools/render-check.ts +4 -4
  314. package/src/validation/primitives.ts +2 -1
  315. package/src/evaluation/loop.ts +0 -218
package/dist/workflows.js CHANGED
@@ -1,153 +1,4 @@
1
- // src/workflows.ts
2
- var identityParser = (raw) => raw;
3
- var SINGLE_PASS = {
4
- id: "single_pass@1",
5
- name: "single_pass",
6
- description: "One LLM-driven impl loop. Used for risk:low + risk:medium contract.",
7
- phases: [
8
- {
9
- id: "impl",
10
- tasks: [
11
- {
12
- id: "generate",
13
- systemPrompt: (ctx) => ctx.harness.how.systemPrompt,
14
- contextBuilder: (ctx) => `User prompt: ${ctx.prompt}
15
-
16
- Boilerplate is pre-written. Fill it in with apply_changes.`,
17
- outputFormat: "tool-call",
18
- outputParser: identityParser,
19
- outputName: "source"
20
- }
21
- ]
22
- }
23
- ]
24
- };
25
- var STAGED = {
26
- id: "staged@1",
27
- name: "staged",
28
- description: "plan \u2192 execute. One architect task then one coder task.",
29
- phases: [
30
- {
31
- id: "plan",
32
- tasks: [
33
- {
34
- id: "architect",
35
- systemPrompt: "You are a UI architect. Produce a plan, no code.",
36
- contextBuilder: (ctx) => `Plan the UI for: ${ctx.prompt}`,
37
- outputFormat: "structured",
38
- outputParser: identityParser,
39
- outputName: "plan",
40
- maxTokens: 800
41
- }
42
- ]
43
- },
44
- {
45
- id: "execute",
46
- tasks: [
47
- {
48
- id: "coder",
49
- systemPrompt: (ctx) => ctx.harness.how.systemPrompt,
50
- contextBuilder: (ctx) => `User prompt: ${ctx.prompt}
51
-
52
- Plan:
53
- ${ctx.priorResults.plan ?? "(no plan)"}
54
-
55
- Implement per plan with apply_changes.`,
56
- inputs: ["plan"],
57
- outputFormat: "tool-call",
58
- outputParser: identityParser,
59
- outputName: "source"
60
- }
61
- ]
62
- }
63
- ]
64
- };
65
- var STAGED_CONCURRENT = {
66
- id: "staged_concurrent@1",
67
- name: "staged-concurrent",
68
- description: "plan \u2192 [types \u2225 hooks \u2225 jsx] \u2192 integrate. DAG with parallel skeleton phase.",
69
- phases: [
70
- {
71
- id: "plan",
72
- tasks: [
73
- {
74
- id: "architect",
75
- systemPrompt: "Plan the UI. No code.",
76
- contextBuilder: (ctx) => `Plan the UI for: ${ctx.prompt}`,
77
- outputFormat: "structured",
78
- outputParser: identityParser,
79
- outputName: "plan",
80
- maxTokens: 600
81
- }
82
- ]
83
- },
84
- {
85
- id: "skeleton",
86
- tasks: [
87
- {
88
- id: "types",
89
- systemPrompt: "Emit only type declarations for the contract.",
90
- contextBuilder: (ctx) => `Emit TypeScript types for: ${ctx.prompt}. Plan: ${ctx.priorResults.plan ?? "(n/a)"}`,
91
- inputs: ["plan"],
92
- outputFormat: "structured",
93
- outputParser: identityParser,
94
- outputName: "types",
95
- maxTokens: 400
96
- },
97
- {
98
- id: "hooks",
99
- systemPrompt: "Emit only hook declarations (useState/useEffect/useStream).",
100
- contextBuilder: (ctx) => `Emit hooks for: ${ctx.prompt}. Plan: ${ctx.priorResults.plan ?? "(n/a)"}`,
101
- inputs: ["plan"],
102
- outputFormat: "structured",
103
- outputParser: identityParser,
104
- outputName: "hooks",
105
- maxTokens: 400
106
- },
107
- {
108
- id: "jsx",
109
- systemPrompt: "Emit only the render JSX tree skeleton.",
110
- contextBuilder: (ctx) => `Emit JSX for: ${ctx.prompt}. Plan: ${ctx.priorResults.plan ?? "(n/a)"}`,
111
- inputs: ["plan"],
112
- outputFormat: "structured",
113
- outputParser: identityParser,
114
- outputName: "jsx",
115
- maxTokens: 400
116
- }
117
- ]
118
- },
119
- {
120
- id: "integrate",
121
- tasks: [
122
- {
123
- id: "glue",
124
- systemPrompt: (ctx) => ctx.harness.how.systemPrompt,
125
- contextBuilder: (ctx) => `Combine into one component. Types:
126
- ${ctx.priorResults.types}
127
-
128
- Hooks:
129
- ${ctx.priorResults.hooks}
130
-
131
- JSX:
132
- ${ctx.priorResults.jsx}`,
133
- inputs: ["types", "hooks", "jsx"],
134
- outputFormat: "tool-call",
135
- outputParser: identityParser,
136
- outputName: "source"
137
- }
138
- ]
139
- }
140
- ]
141
- };
142
- var WORKFLOWS = {
143
- single_pass: SINGLE_PASS,
144
- staged: STAGED,
145
- staged_concurrent: STAGED_CONCURRENT
146
- };
147
- function pickWorkflow(_classification) {
148
- return WORKFLOWS.single_pass;
149
- }
150
-
151
- export { WORKFLOWS, pickWorkflow };
1
+ export { WORKFLOWS, pickWorkflow } from './chunk-S2GVXKKY.js';
2
+ import './chunk-G3PMV62Z.js';
152
3
  //# sourceMappingURL=workflows.js.map
153
4
  //# sourceMappingURL=workflows.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/workflows.ts"],"names":[],"mappings":"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","file":"workflows.js","sourcesContent":["// packages/ui-gen/src/workflows.ts\n//\n// Workflow registry + classification-driven picker. Each workflow\n// describes an execution topology (phases × tasks) for producing source\n// from a contract + prompt; the harness runtime owns actual LLM calls.\n//\n// Workflow shapes are validated shipping defaults — even `staged` /\n// `staged-concurrent` are reserved-but-registered topologies the picker\n// may route to in future risk-tier routing. Classification-driven\n// routing itself is deliberately conservative today (always\n// `single_pass`); changing the picker is a behavior change that should\n// be validated against the generation benchmark suite.\n//\n// Public surface is intentionally minimal: consumers import `WORKFLOWS`\n// (the map) + `pickWorkflow` (the router) + `WorkflowId` (the key\n// type). Individual topology constants (SINGLE_PASS, STAGED,\n// STAGED_CONCURRENT) are internal — access them via\n// `WORKFLOWS.single_pass` etc.\n\nimport type { Classification } from \"./classifier/axes.js\";\nimport type { Workflow } from \"./harness/types-public.js\";\n\n/** Identity parser — used for tasks whose output is already a string. */\nconst identityParser = (raw: unknown): string => raw as string;\n\n/**\n * single_pass — one phase, one task. The current default. The task runs\n * the existing impl/patch/eval-fix loop as a single atomic block.\n */\nconst SINGLE_PASS: Workflow = {\n id: \"single_pass@1\",\n name: \"single_pass\",\n description: \"One LLM-driven impl loop. Used for risk:low + risk:medium contract.\",\n phases: [\n {\n id: \"impl\",\n tasks: [\n {\n id: \"generate\",\n systemPrompt: (ctx) => ctx.harness.how.systemPrompt,\n contextBuilder: (ctx) =>\n `User prompt: ${ctx.prompt}\\n\\nBoilerplate is pre-written. Fill it in with apply_changes.`,\n outputFormat: \"tool-call\",\n outputParser: identityParser,\n outputName: \"source\",\n },\n ],\n },\n ],\n};\n\n/**\n * staged — plan phase then execute phase. For risk:high contract where\n * decomposing planning from authoring reduces light-model cognitive load.\n *\n * Registered but not yet routed by `pickWorkflow` — the executor wires\n * architect/coder TaskRunners through a separate dispatch path in core/.\n */\nconst STAGED: Workflow = {\n id: \"staged@1\",\n name: \"staged\",\n description: \"plan → execute. One architect task then one coder task.\",\n phases: [\n {\n id: \"plan\",\n tasks: [\n {\n id: \"architect\",\n systemPrompt: \"You are a UI architect. Produce a plan, no code.\",\n contextBuilder: (ctx) => `Plan the UI for: ${ctx.prompt}`,\n outputFormat: \"structured\",\n outputParser: identityParser,\n outputName: \"plan\",\n maxTokens: 800,\n },\n ],\n },\n {\n id: \"execute\",\n tasks: [\n {\n id: \"coder\",\n systemPrompt: (ctx) => ctx.harness.how.systemPrompt,\n contextBuilder: (ctx) =>\n `User prompt: ${ctx.prompt}\\n\\nPlan:\\n${ctx.priorResults.plan ?? \"(no plan)\"}\\n\\nImplement per plan with apply_changes.`,\n inputs: [\"plan\"],\n outputFormat: \"tool-call\",\n outputParser: identityParser,\n outputName: \"source\",\n },\n ],\n },\n ],\n};\n\n/**\n * staged-concurrent — plan, then parallel skeleton tasks, then integrate.\n * Reserved shape for risk:high + multi-axis contract where the LLM\n * benefits from breaking structural concerns apart.\n */\nconst STAGED_CONCURRENT: Workflow = {\n id: \"staged_concurrent@1\",\n name: \"staged-concurrent\",\n description: \"plan → [types ∥ hooks ∥ jsx] → integrate. DAG with parallel skeleton phase.\",\n phases: [\n {\n id: \"plan\",\n tasks: [\n {\n id: \"architect\",\n systemPrompt: \"Plan the UI. No code.\",\n contextBuilder: (ctx) => `Plan the UI for: ${ctx.prompt}`,\n outputFormat: \"structured\",\n outputParser: identityParser,\n outputName: \"plan\",\n maxTokens: 600,\n },\n ],\n },\n {\n id: \"skeleton\",\n tasks: [\n {\n id: \"types\",\n systemPrompt: \"Emit only type declarations for the contract.\",\n contextBuilder: (ctx) =>\n `Emit TypeScript types for: ${ctx.prompt}. Plan: ${ctx.priorResults.plan ?? \"(n/a)\"}`,\n inputs: [\"plan\"],\n outputFormat: \"structured\",\n outputParser: identityParser,\n outputName: \"types\",\n maxTokens: 400,\n },\n {\n id: \"hooks\",\n systemPrompt: \"Emit only hook declarations (useState/useEffect/useStream).\",\n contextBuilder: (ctx) =>\n `Emit hooks for: ${ctx.prompt}. Plan: ${ctx.priorResults.plan ?? \"(n/a)\"}`,\n inputs: [\"plan\"],\n outputFormat: \"structured\",\n outputParser: identityParser,\n outputName: \"hooks\",\n maxTokens: 400,\n },\n {\n id: \"jsx\",\n systemPrompt: \"Emit only the render JSX tree skeleton.\",\n contextBuilder: (ctx) =>\n `Emit JSX for: ${ctx.prompt}. Plan: ${ctx.priorResults.plan ?? \"(n/a)\"}`,\n inputs: [\"plan\"],\n outputFormat: \"structured\",\n outputParser: identityParser,\n outputName: \"jsx\",\n maxTokens: 400,\n },\n ],\n },\n {\n id: \"integrate\",\n tasks: [\n {\n id: \"glue\",\n systemPrompt: (ctx) => ctx.harness.how.systemPrompt,\n contextBuilder: (ctx) =>\n `Combine into one component. Types:\\n${ctx.priorResults.types}\\n\\nHooks:\\n${ctx.priorResults.hooks}\\n\\nJSX:\\n${ctx.priorResults.jsx}`,\n inputs: [\"types\", \"hooks\", \"jsx\"],\n outputFormat: \"tool-call\",\n outputParser: identityParser,\n outputName: \"source\",\n },\n ],\n },\n ],\n};\n\nexport const WORKFLOWS = {\n single_pass: SINGLE_PASS,\n staged: STAGED,\n staged_concurrent: STAGED_CONCURRENT,\n} as const;\n\nexport type WorkflowId = keyof typeof WORKFLOWS;\n\n/**\n * Pick a workflow based on classification shape. One dispatch rule —\n * kept small on purpose. Changing this mapping is a first-class\n * experiment.\n *\n * Deliberately conservative — always `single_pass`. Classification-\n * driven routing to `staged` / `staged-concurrent` will follow once\n * the workflow executor can actually run non-single_pass shapes end-\n * to-end on the dispatch path.\n */\nexport function pickWorkflow(_classification: Classification): Workflow {\n return WORKFLOWS.single_pass;\n}\n"]}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"workflows.js"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ggui-ai/ui-gen",
3
- "version": "0.27.0",
4
- "description": "UI generation harness for ggui — the LLM system prompt, multi-turn coding loop, and evaluation engine that turn a DataContract into a React component. Implements the UiGenerator contract from @ggui-ai/mcp-server-core; consumed by @ggui-ai/mcp-server.",
3
+ "version": "0.29.0",
4
+ "description": "UI generation harness for GGUI — the LLM system prompt, multi-turn coding loop, and evaluation engine that turn a DataContract into a React component. Implements the UiGenerator contract from @ggui-ai/mcp-server-core; consumed by @ggui-ai/mcp-server.",
5
5
  "license": "Apache-2.0",
6
6
  "keywords": [
7
7
  "ggui",
@@ -183,17 +183,21 @@
183
183
  }
184
184
  },
185
185
  "peerDependencies": {
186
+ "@anthropic-ai/claude-agent-sdk": "0.3.229",
186
187
  "@google/adk": "^2.0.0",
187
188
  "@openai/agents": "^0.17.0",
188
189
  "@sparticuz/chromium": "^149.0.0",
189
190
  "puppeteer-core": "^24.40.0 || ^25.0.0",
190
191
  "react": "^18.0.0 || ^19.0.0",
191
192
  "react-dom": "^18.0.0 || ^19.0.0",
192
- "@ggui-ai/mcp-server-core": "0.27.0",
193
- "@ggui-ai/project-config": "0.27.0",
194
- "@ggui-ai/protocol": "0.27.0"
193
+ "@ggui-ai/mcp-server-core": "0.29.0",
194
+ "@ggui-ai/project-config": "0.29.0",
195
+ "@ggui-ai/protocol": "0.29.0"
195
196
  },
196
197
  "peerDependenciesMeta": {
198
+ "@anthropic-ai/claude-agent-sdk": {
199
+ "optional": true
200
+ },
197
201
  "@google/adk": {
198
202
  "optional": true
199
203
  },
@@ -215,12 +219,12 @@
215
219
  },
216
220
  "dependencies": {
217
221
  "@anthropic-ai/bedrock-sdk": "^0.33.3",
218
- "@anthropic-ai/claude-agent-sdk": "0.3.229",
219
222
  "@anthropic-ai/sdk": "^0.123.0",
220
223
  "@google/genai": "^2.8.0",
221
224
  "@testing-library/dom": "^10.4.0",
222
225
  "@testing-library/react": "^16.0.0",
223
226
  "@testing-library/user-event": "^14.6.1",
227
+ "@types/react": "^19.0.0",
224
228
  "@typescript-eslint/parser": "^8.0.0",
225
229
  "diff": "^8.0.3",
226
230
  "esbuild": "^0.28.2",
@@ -232,29 +236,29 @@
232
236
  "memfs": "^4.56.11",
233
237
  "openai": "^7.9.0",
234
238
  "typescript": "^5.0.0",
235
- "zod": "^4.3.6",
236
- "@ggui-ai/design": "0.27.0",
237
- "@ggui-ai/sandbox": "0.27.0",
238
- "@ggui-ai/gadgets": "0.27.0",
239
- "@ggui-ai/ui-visual-tester": "0.27.0",
240
- "@ggui-ai/wire": "0.27.0"
239
+ "zod": "^4.6.6",
240
+ "@ggui-ai/design": "0.29.0",
241
+ "@ggui-ai/gadgets": "0.29.0",
242
+ "@ggui-ai/sandbox": "0.29.0",
243
+ "@ggui-ai/ui-visual-tester": "0.29.0",
244
+ "@ggui-ai/wire": "0.29.0"
241
245
  },
242
246
  "devDependencies": {
247
+ "@anthropic-ai/claude-agent-sdk": "0.3.229",
243
248
  "@google/adk": "^2.0.0",
244
249
  "@openai/agents": "^0.17.0",
245
250
  "@sparticuz/chromium": "^149.0.0",
246
251
  "@types/eslint": "^9.6.1",
247
252
  "@types/node": "^22.0.0",
248
- "@types/react": "^19.0.0",
249
253
  "@types/react-dom": "^19.0.0",
250
254
  "puppeteer-core": "^25.6.0",
251
255
  "react": "^19.0.0",
252
256
  "react-dom": "^19.0.0",
253
257
  "tsup": "^8.5.0",
254
- "vitest": "^3.2.6",
255
- "@ggui-ai/mcp-server-core": "0.27.0",
256
- "@ggui-ai/project-config": "0.27.0",
257
- "@ggui-ai/protocol": "0.27.0"
258
+ "vitest": "^4.1.11",
259
+ "@ggui-ai/mcp-server-core": "0.29.0",
260
+ "@ggui-ai/protocol": "0.29.0",
261
+ "@ggui-ai/project-config": "0.29.0"
258
262
  },
259
263
  "engines": {
260
264
  "node": ">=22.0.0"
@@ -15,6 +15,7 @@ import { createArtifacts, processMessage } from './message-parser';
15
15
  import { createToolMcpServer } from './tool-bridge';
16
16
  import { claudeCodeLoginQueryOptions, loginChildEnv } from './claude-code-login';
17
17
  import { sdkToolPins } from './sdk-tool-pins';
18
+ import { loadClaudeAgentSdk } from '../../harness/claude-agent-sdk-loader';
18
19
 
19
20
  export class ClaudeSdkAdapter extends GeneratorAdapter {
20
21
  readonly provider: ProviderName = 'claude';
@@ -38,8 +39,9 @@ export class ClaudeSdkAdapter extends GeneratorAdapter {
38
39
  const startTime = Date.now();
39
40
  const cfg = this.sdkConfig;
40
41
 
41
- // Dynamic import to avoid loading claude-agent-sdk in non-Claude contexts
42
- const { query } = await import('@anthropic-ai/claude-agent-sdk');
42
+ // The SDK is an optional peer (ggui#1951): loaded on first use, and a
43
+ // missing one fails with the install line.
44
+ const { query } = await loadClaudeAgentSdk();
43
45
 
44
46
  // Build environment from config or process.env
45
47
  // ggui#1185/#1278 — on the login path the binary sees an allowlisted
@@ -13,6 +13,7 @@
13
13
  import type { ToolDefinition } from '../types';
14
14
  import type { McpSdkServerConfigWithInstance } from '@anthropic-ai/claude-agent-sdk';
15
15
  import type { JsonObject } from '@ggui-ai/protocol';
16
+ import { loadClaudeAgentSdk } from '../../harness/claude-agent-sdk-loader';
16
17
 
17
18
  /** Name used for the in-process MCP server. */
18
19
  export const MCP_SERVER_NAME = 'ggui';
@@ -30,7 +31,7 @@ export async function createToolMcpServer(
30
31
  server: McpSdkServerConfigWithInstance;
31
32
  allowedToolNames: string[];
32
33
  }> {
33
- const { tool, createSdkMcpServer } = await import('@anthropic-ai/claude-agent-sdk');
34
+ const { tool, createSdkMcpServer } = await loadClaudeAgentSdk();
34
35
 
35
36
  const mcpTools = tools.map((def) => {
36
37
  // Extract Zod shape from the input schema
@@ -28,6 +28,9 @@ import { resolveHarnessPolicy } from "../harness/policy.js";
28
28
  // prompts carry pitfalls + design-system docs + primitives + wire
29
29
  // content.
30
30
  import { buildSystemPrompt as buildSystemPromptWithFunnel } from "../harness/runtime.js";
31
+ import type { CodingTurnPrompt } from "../harness/runtime.js";
32
+
33
+ export type { CodingTurnPrompt };
31
34
  // Axis-check registry filter. The `createHarness` constructor accepts a
32
35
  // pre-filtered axisChecks list; this callsite runs the `matches()`
33
36
  // predicate against the full registry and passes the filtered result.
@@ -137,6 +140,11 @@ export interface GenerationDispatchParams {
137
140
  * Production callers can omit this; benchmark runners should pass commit.props.
138
141
  */
139
142
  fixtureProps?: JsonObject;
143
+ /**
144
+ * Observer of the exact prompt each coding turn sends — the system prompt after the component-reference swap
145
+ * below, and the turn's user message (see `CodingTurnPrompt`). Read-only; nothing sent changes. Absent = no report.
146
+ */
147
+ onCodingTurnPrompt?: (sent: CodingTurnPrompt) => void;
140
148
  /**
141
149
  * Whether to wire the runtime-render check (`runtimeRender` when given,
142
150
  * else `DEFAULT_RUNTIME_RENDER_CHECK`) into the harness's check leg.
@@ -332,6 +340,7 @@ export async function dispatchGeneration(
332
340
  visualEvaluation: params.visualEvaluation,
333
341
  qualityConfig: params.qualityConfig,
334
342
  fixtureProps: params.fixtureProps,
343
+ ...(params.onCodingTurnPrompt !== undefined ? { onCodingTurnPrompt: params.onCodingTurnPrompt } : {}),
335
344
  };
336
345
 
337
346
  // ── Classify + build harness.
@@ -58,6 +58,7 @@ export class OpenAiRawAdapter extends GeneratorAdapter {
58
58
  // OpenAI's input token count INCLUDES cached tokens; track the cached
59
59
  // subset so tokens.input reports NON-cached input (ggui#1186).
60
60
  let totalCachedInputTokens = 0;
61
+ let totalCacheWriteTokens = 0;
61
62
  let turnsUsed = 0;
62
63
  let allTextOutput = '';
63
64
 
@@ -80,6 +81,8 @@ export class OpenAiRawAdapter extends GeneratorAdapter {
80
81
  totalOutputTokens += response.usage.output_tokens ?? 0;
81
82
  totalCachedInputTokens +=
82
83
  response.usage.input_tokens_details?.cached_tokens ?? 0;
84
+ totalCacheWriteTokens +=
85
+ response.usage.input_tokens_details?.cache_write_tokens ?? 0;
83
86
  }
84
87
 
85
88
  // Process output items
@@ -166,6 +169,7 @@ export class OpenAiRawAdapter extends GeneratorAdapter {
166
169
  totalInputTokens,
167
170
  totalOutputTokens,
168
171
  totalCachedInputTokens,
172
+ totalCacheWriteTokens,
169
173
  ),
170
174
  generationTimeMs: Date.now() - startTime,
171
175
  turnsUsed,
@@ -94,13 +94,18 @@ export class OpenAiSdkAdapter extends GeneratorAdapter {
94
94
  (sum, details) => sum + (details.cached_tokens ?? 0),
95
95
  0,
96
96
  );
97
+ // ggui#1957 — and the cache writes, the same kind of subset.
98
+ const cacheWriteTokens = (usage.inputTokensDetails ?? []).reduce(
99
+ (sum, details) => sum + (details.cache_write_tokens ?? 0),
100
+ 0,
101
+ );
97
102
 
98
103
  return {
99
104
  compiledCode: capture.compiledCode,
100
105
  sourceCode: capture.sourceCode,
101
106
  stream: capture.stream,
102
107
  generatorMeta: capture.generatorMeta,
103
- ...splitOpenAiUsage(inputTokens, outputTokens, cachedInputTokens),
108
+ ...splitOpenAiUsage(inputTokens, outputTokens, cachedInputTokens, cacheWriteTokens),
104
109
  generationTimeMs: Date.now() - startTime,
105
110
  turnsUsed: result.rawResponses?.length ?? 0,
106
111
  };
@@ -21,18 +21,32 @@ import type { AdapterResult } from '../types';
21
21
  * inflates `$/gen` and breaks `render_cache_metric`'s `cacheReadPct`
22
22
  * denominator). So the OpenAI adapters subtract the cached subset here.
23
23
  *
24
- * `total` is the full processed footprint (non-cached input + cache
25
- * reads + output = `inputTokensInclCached + outputTokens`), matching the
26
- * Claude adapter's `total` (input + cacheCreation + cacheRead + output);
27
- * OpenAI has no explicit cache-creation step, so there is no
28
- * `cacheCreationTokens` term.
24
+ * Cache WRITES are the same kind of subset (ggui#1957): OpenAI bills them on
25
+ * GPT-5.6 and later (1.25× input) and reports them as
26
+ * `input_tokens_details.cache_write_tokens`, "the number of input tokens
27
+ * that were written to the cache", inside the same input total. They are
28
+ * subtracted from `input` as the reads are and reported as
29
+ * `cacheCreationTokens`, so a consumer prices them at the cache-write rate,
30
+ * exactly once.
31
+ *
32
+ * `total` is the full processed footprint (non-cached input + cache reads +
33
+ * cache writes + output = `inputTokensInclCached + outputTokens`), matching
34
+ * the Claude adapter's `total` (input + cacheCreation + cacheRead + output).
29
35
  */
30
36
  export function splitOpenAiUsage(
31
37
  inputTokensInclCached: number,
32
38
  outputTokens: number,
33
39
  cachedTokens: number,
34
- ): { tokens: AdapterResult['tokens']; cacheReadTokens: number } {
35
- return splitCacheInclusiveUsage(inputTokensInclCached, outputTokens, cachedTokens);
40
+ cacheWriteTokens: number,
41
+ ): { tokens: AdapterResult['tokens']; cacheReadTokens: number; cacheCreationTokens: number } {
42
+ const split = splitCacheInclusiveUsage(inputTokensInclCached, outputTokens, cachedTokens);
43
+ // Never let a malformed usage report drive input negative: the writes are at most what remains after the reads.
44
+ const cacheCreation = Math.min(Math.max(cacheWriteTokens, 0), split.tokens.input);
45
+ return {
46
+ tokens: { input: split.tokens.input - cacheCreation, output: split.tokens.output, total: split.tokens.total },
47
+ cacheReadTokens: split.cacheReadTokens,
48
+ cacheCreationTokens: cacheCreation,
49
+ };
36
50
  }
37
51
 
38
52
  /**
@@ -29,6 +29,7 @@ import type { LlmRoute } from '@ggui-ai/protocol';
29
29
  export function getBedrockModelId(model: string): string {
30
30
  const BEDROCK_MAP: Record<string, string> = {
31
31
  'anthropic/claude-haiku-4-5': 'us.anthropic.claude-haiku-4-5-20251001-v1:0',
32
+ 'anthropic/claude-haiku-5-5': 'us.anthropic.claude-haiku-5-5', // listed ACTIVE in us-east-1 (ggui#1743)
32
33
  'anthropic/claude-sonnet-4-6': 'us.anthropic.claude-sonnet-4-6',
33
34
  'anthropic/claude-opus-4-6': 'us.anthropic.claude-opus-4-6-v1:0',
34
35
  // Claude 5-family (ggui#706, strings verified 2026-09-02 against
@@ -4,7 +4,7 @@
4
4
  // Zod → JSON Schema for tool declarations, and validated narrowing of
5
5
  // decoded tool-call arguments to `JsonObject`.
6
6
 
7
- import { z } from 'zod';
7
+ import * as z from 'zod';
8
8
  import type { JsonObject, JsonValue } from '@ggui-ai/protocol';
9
9
 
10
10
  /**
@@ -5,7 +5,7 @@
5
5
  // but without Claude Agent SDK dependencies, making them portable across
6
6
  // OpenAI, Google, and Anthropic SDKs.
7
7
 
8
- import { z } from 'zod';
8
+ import * as z from 'zod';
9
9
  import * as esbuild from 'esbuild';
10
10
  import { PRIMITIVES_DOCUMENTATION } from '../validation/index.js';
11
11
  import {
@@ -7,8 +7,7 @@
7
7
  * (`validateContractBehavior`) returns structured
8
8
  * {@link BehaviorFailure}s. This module converts both into
9
9
  * prompt-augmenting text fragments the regen call appends to the
10
- * user prompt — same shape the existing `runEvaluationLoop` uses
11
- * for LLM-eval complaints.
10
+ * user prompt.
12
11
  *
13
12
  * Format mirrors the diagnostic format the runtime-render adapter
14
13
  * already produces (see `harness/check/runtime-render/adapter.ts`),
@@ -64,7 +64,7 @@ import {
64
64
  /** Generator identity — slug, tier, and model. */
65
65
  export const ADVANCED_GENERATOR_SLUG = 'ui-gen-advanced' as const;
66
66
  export const ADVANCED_GENERATOR_TIER: GeneratorTier = 'advanced';
67
- export const ADVANCED_GENERATOR_MODEL: ModelRef = 'anthropic/claude-opus-4-7';
67
+ export const ADVANCED_GENERATOR_MODEL: ModelRef = 'anthropic/claude-opus-5-5';
68
68
 
69
69
  /**
70
70
  * Re-exported under a friendlier name for callers wiring deploys.
@@ -134,8 +134,9 @@ export interface CreateAdvancedUiGeneratorOptions
134
134
 
135
135
  /**
136
136
  * Inner generator. Defaults to a fresh `createUiGenerator({tier:
137
- * 'advanced', model: 'opus-4-7'})` so the BYOK route resolves to an
138
- * Opus model on Anthropic. Tests can inject a stub.
137
+ * 'advanced', model: ADVANCED_GENERATOR_MODEL})`. That model is the
138
+ * generator's declared identity only: each request runs on the model
139
+ * its own `input.llm` route names. Tests can inject a stub.
139
140
  *
140
141
  * The inner generator's identity (slug/tier/model) is irrelevant —
141
142
  * this advanced wrapper exposes its own fixed identity.
@@ -96,6 +96,13 @@ const SEMANTIC_ROLES: ReadonlyArray<{ readonly names: readonly string[]; readonl
96
96
  { names: ["onPrimary"], role: "text on the brand color" },
97
97
  { names: ["outline", "outlineVariant"], role: "borders + dividers" },
98
98
  { names: ["onError"], role: "text on an error fill" },
99
+ {
100
+ names: ["tint-1", "tint-2", "tint-3", "tint-4", "tint-5", "tint-6", "tint-7", "tint-8"],
101
+ role:
102
+ "categorical fills for DATA categories only (series, lanes, kinds, element groups) — never for state, never as decoration; " +
103
+ "the text on a tint is `onContainer` only, one short line, never muted text; the category is always also in words (a label or a legend); " +
104
+ "a category keeps its tint for the life of the card (assign from the data's order, never render order); more than eight categories: group to eight, or words only",
105
+ },
99
106
  ];
100
107
 
101
108
  /** Split the manifest's `--ggui-color-*` names into ramps (family + numeric steps) and semantic roles. */
@@ -35,8 +35,10 @@ import type {
35
35
  } from "@ggui-ai/protocol";
36
36
  import { HOOK_NAME_RE, listContractGadgets } from "@ggui-ai/protocol";
37
37
  import { renderBoilerplate } from "./render.js";
38
+ import { BOILERPLATE_REACT_IMPORT } from "./react-hooks.js";
38
39
  import { jsonSchemaTypeToTs } from "./json-schema-ts.js";
39
- import { DEFAULT_DESIGN_MODE, type DesignMode } from "../design-mode.js";
40
+ import { GGUI_MOUNT_CANVAS_EXPORT } from "@ggui-ai/design/rendering";
41
+ import { DEFAULT_DESIGN_MODE, canvasForRendering, type DesignMode } from "../design-mode.js";
40
42
 
41
43
  /** Shell layout modes supported by the boilerplate templates. */
42
44
  export type ShellType = "chat" | "fullscreen" | "spatial";
@@ -544,9 +546,10 @@ export function generateBoilerplate(
544
546
  const gadgetImport =
545
547
  gadgetImportLine.length > 0 ? `${gadgetImportLine}\n` : "";
546
548
 
547
- // ── React import — only include hooks that are actually needed ──
548
- const reactHooks = ["useState", "useCallback", "useMemo", "useEffect", "useRef"];
549
- const reactImport = `import React, { ${reactHooks.join(", ")} } from 'react';`;
549
+ // ── React import — the hooks generated code may use, always listed (the line is DO NOT EDIT) ──
550
+ // `useLayoutEffect` (ggui#1896): the prompt seeds a context slot from a prop with it, so the
551
+ // first frame never paints the slot's contract default.
552
+ const reactImport = BOILERPLATE_REACT_IMPORT;
550
553
 
551
554
  // ── Hook body ──────────────────────────────────────────
552
555
  // Wire hooks are placed inside render(), before the return statement.
@@ -603,11 +606,21 @@ export function generateBoilerplate(
603
606
  // hooks own their typed return shape internally; the contract surface
604
607
  // is pure declaration.
605
608
 
609
+ // The canvas this card is composed for, as a named export the runtime reads at mount
610
+ // (`resolveMountFit`): a chat-width card on a fullscreen surface keeps its natural height in its
611
+ // own frame instead of filling the surface. The compile step writes it; the model never does.
612
+ // It follows the shell × screen descriptors, which is what makes a chat shell `xs-chat-card`.
613
+ // An explicit canvas (the free prompt's) is not consulted: it can disagree with the shell, and the
614
+ // constrained boilerplate stays byte-identical whatever canvas is passed (INVARIANT 1).
615
+ const mountCanvas =
616
+ `\n\n// DO NOT EDIT — the canvas this card is composed for; the runtime reads it at mount.\n` +
617
+ `export const ${GGUI_MOUNT_CANVAS_EXPORT} = "${canvasForRendering(shellType, screen)}";`;
618
+
606
619
  return renderBoilerplate(shellType ?? "fullscreen", screen ?? "universal", {
607
620
  REACT_IMPORT: reactImport,
608
621
  ALL_DESIGN,
609
622
  WIRE_IMPORT: wireImport + gadgetImport,
610
- PROPS_INTERFACE: propsInterface,
623
+ PROPS_INTERFACE: propsInterface + mountCanvas,
611
624
  ACTION_TYPES: actionTypesBlock,
612
625
  STREAM_TYPES: streamTypesBlock,
613
626
  CONTEXT_HOOKS: contextHooks,
@@ -168,7 +168,7 @@ export default function Component(props: Props) {
168
168
  return (
169
169
  <Container>
170
170
  <Text>Step {currentStep}</Text>
171
- <Input value={draftText} onChange={(e) => setDraftText(e.target.value)} />
171
+ <Input value={draftText} onChange={setDraftText} />
172
172
  <Button onClick={() => setCurrentStep((s) => s + 1)}>Next</Button>
173
173
  </Container>
174
174
  );
@@ -181,7 +181,9 @@ For every declared slot you have **\`slotName\` + \`setSlotName\`** in scope:
181
181
 
182
182
  Every value change is mirrored to the host LLM's context automatically (debounced, default 300ms — adjustable per-slot via \`entry.debounceMs\` in the contract). The agent sees the user's interaction state — drafts, current step, hover, selection — without you calling any API.
183
183
 
184
- **When to use the auto-generated state.** Any slot the contract declared. If \`contextSpec.draftText\` exists, bind \`<Input value={draftText} onChange={e => setDraftText(e.target.value)}>\` so the agent sees the typing live. If \`contextSpec.currentStep\` exists, render the step indicator from \`currentStep\` and bump it via \`setCurrentStep\` in your "next" callback.
184
+ **When to use the auto-generated state.** Any slot the contract declared. If \`contextSpec.draftText\` exists, bind \`<Input value={draftText} onChange={setDraftText}>\` so the agent sees the typing live (a design control's \`onChange\` hands you the value, never an event). If \`contextSpec.currentStep\` exists, render the step indicator from \`currentStep\` and bump it via \`setCurrentStep\` in your "next" callback.
185
+
186
+ **Seeding a slot from a prop.** A slot starts at the contract's default, never at a prop. When a slot must start from a prop (a form pre-filled from \`props\`), seed it with \`useLayoutEffect(() => setName(props.name ?? ''), [props.name])\` — \`useLayoutEffect\`, not \`useEffect\`: \`useEffect\` lets the first frame paint the empty default before the prop arrives. The dependency array re-seeds the slot when the agent repaints with new props.
185
187
 
186
188
  **When NOT to use it.** Local UI state the contract did NOT declare — \`isDropdownOpen\`, hover flags, animation phase, ephemeral toggles. For those, use a plain \`useState\` directly. The runtime ignores undeclared state.
187
189
 
@@ -250,7 +252,10 @@ export const FRAME_SIZING = `## Sizing — the frame owns the height and the wid
250
252
  The host sizes the iframe; the component never sizes itself to the viewport. NEVER write \`100vh\` / \`100dvh\` / \`100svh\` (or an \`h-screen\` / \`min-h-screen\` class) as a height on any element:
251
253
  - An inline card takes its natural height. A content-sized frame is measured FROM the content, so a \`100vh\` root can never shrink and grows the frame on every re-measure.
252
254
  - Under fullscreen the frame already stretches your root to its full height. Centre inside it with flex (\`display: flex; flex-direction: column; justify-content: center\`), never with a viewport height.
253
- - Under fullscreen the frame also keeps a 16 px inset between your content and the panel's edge — leave it. A \`surface="hero"\` band that OPENS the card runs edge to edge on its own. Any other band that is MEANT to run edge to edge (a full-width strip of rows, a closing action bar) takes \`bleed\` (\`<Box surface="sunken" bleed>…</Box>\`); only such a band should, and \`bleed\` is ignored outside fullscreen.
255
+ - In EVERY fit (an inline card, a framed card, fullscreen) the card keeps ONE content edge: the runtime insets your root's content from the card's edge. Leave it, and never pad it back out. Only two things run edge to edge, in every fit:
256
+ - a \`surface="hero"\` band that is your root's FIRST child, opening the card (\`<Box surface="hero">…</Box>\` directly inside the root, not wrapped in a \`Stack\`, not second);
257
+ - any other band that declares \`bleed\` (\`<Box surface="sunken" bleed>…</Box>\`). Only a band MEANT to run edge to edge takes it: a full-width strip of rows, a closing action bar.
258
+ A band you paint yourself (a \`Box\` with a \`background\`) is NOT an edge-to-edge band. It sits inside the inset with the card's corners showing around it, like a box floating in the card. An opening band is always the kit's \`surface="hero"\`, never your own colour.
254
259
  - To fill a parent that has a height use \`height: 100%\` or \`flex: 1\`; a viewport unit is only ever a \`max-height\` cap on a scroll region.
255
260
 
256
261
  The width works the same way, and the mistake is the mirror image: **your outermost element FILLS the frame; a width cap belongs INSIDE it, on the column that holds text.**