@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
@@ -0,0 +1,24 @@
1
+ import { FORBIDDEN_IMPORT_SPECIFIERS } from '@ggui-ai/design/rendering';
2
+
3
+ // src/validation/allowed-imports.ts
4
+ var ALLOWED_IMPORT_BASES = [
5
+ "react",
6
+ "react-dom",
7
+ "@ggui-ai/design",
8
+ "@ggui-ai/wire",
9
+ "@ggui-ai/gadgets"
10
+ ];
11
+ function isAllowedImport(specifier, gadgetPackages) {
12
+ if (FORBIDDEN_IMPORT_SPECIFIERS.includes(specifier)) return false;
13
+ for (const base of ALLOWED_IMPORT_BASES) {
14
+ if (specifier === base || specifier.startsWith(`${base}/`)) return true;
15
+ }
16
+ return gadgetPackages?.has(specifier) ?? false;
17
+ }
18
+ function describeAllowedImports() {
19
+ return "react, @ggui-ai/design, @ggui-ai/wire, @ggui-ai/gadgets, or a gadget package declared on the contract \u2014 never @ggui-ai/wire/internal (the writer side of the wire; components read useRender().isConnected)";
20
+ }
21
+
22
+ export { describeAllowedImports, isAllowedImport };
23
+ //# sourceMappingURL=chunk-33B3BAWS.js.map
24
+ //# sourceMappingURL=chunk-33B3BAWS.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/validation/allowed-imports.ts"],"names":[],"mappings":";;;AA0BO,IAAM,oBAAA,GAAuB;AAAA,EAClC,OAAA;AAAA,EACA,WAAA;AAAA,EACA,iBAAA;AAAA,EACA,eAAA;AAAA,EACA;AACF,CAAA;AAUO,SAAS,eAAA,CACd,WACA,cAAA,EACS;AACT,EAAA,IAAI,2BAAA,CAA4B,QAAA,CAAS,SAAS,CAAA,EAAG,OAAO,KAAA;AAC5D,EAAA,KAAA,MAAW,QAAQ,oBAAA,EAAsB;AACvC,IAAA,IAAI,SAAA,KAAc,QAAQ,SAAA,CAAU,UAAA,CAAW,GAAG,IAAI,CAAA,CAAA,CAAG,GAAG,OAAO,IAAA;AAAA,EACrE;AACA,EAAA,OAAO,cAAA,EAAgB,GAAA,CAAI,SAAS,CAAA,IAAK,KAAA;AAC3C;AAMO,SAAS,sBAAA,GAAiC;AAC/C,EAAA,OAAO,kNAAA;AACT","file":"chunk-33B3BAWS.js","sourcesContent":["/**\n * The single source of truth for which packages LLM-generated\n * component code may import.\n *\n * Before this module the allowlist was duplicated — as `startsWith`\n * chains, as literal arrays, as hand-written error strings — across\n * `adapters/tools.ts`, `check/run-tier0.ts`, `check/type-checker.ts`\n * and `validation/component-detailed.ts`. The copies had already\n * drifted (one rejected `react-dom`, others allowed it). Every\n * import-validation site now derives from {@link isAllowedImport}.\n *\n * The design system is imported through ONE specifier — `@ggui-ai/design`\n * — never the `/primitives`, `/components`, `/compositions`, `/interact`\n * subpaths. The barrel re-exports every layer, so the generation LLM\n * never has to predict which subpath a component lives in. Subpaths\n * still resolve (the predicate allows any `@ggui-ai/design/...`), but\n * the prompt and catalog teach the barrel exclusively.\n */\n\n/**\n * Static package specifiers generated code may import. A subpath of\n * any base (`<base>/...`) is allowed too. Per-contract gadget packages\n * are dynamic — pass them to {@link isAllowedImport}.\n */\nimport { FORBIDDEN_IMPORT_SPECIFIERS } from '@ggui-ai/design/rendering';\n\nexport const ALLOWED_IMPORT_BASES = [\n 'react',\n 'react-dom',\n '@ggui-ai/design',\n '@ggui-ai/wire',\n '@ggui-ai/gadgets',\n] as const;\n\n/**\n * True if `specifier` is a package generated component code may import:\n * one of {@link ALLOWED_IMPORT_BASES} (or a subpath of one), or a\n * contract-declared gadget package — and never one of the design package's\n * `FORBIDDEN_IMPORT_SPECIFIERS` (ggui#843: `@ggui-ai/wire/internal` is the\n * writer side of the wire; the load-time rewriter refuses it from the same\n * list, so the two gates cannot drift apart).\n */\nexport function isAllowedImport(\n specifier: string,\n gadgetPackages?: ReadonlySet<string>,\n): boolean {\n if (FORBIDDEN_IMPORT_SPECIFIERS.includes(specifier)) return false;\n for (const base of ALLOWED_IMPORT_BASES) {\n if (specifier === base || specifier.startsWith(`${base}/`)) return true;\n }\n return gadgetPackages?.has(specifier) ?? false;\n}\n\n/**\n * Human-readable allowed-import list for error messages shown to the\n * generation LLM.\n */\nexport function describeAllowedImports(): string {\n return 'react, @ggui-ai/design, @ggui-ai/wire, @ggui-ai/gadgets, or a gadget package declared on the contract — never @ggui-ai/wire/internal (the writer side of the wire; components read useRender().isConnected)';\n}\n"]}
@@ -0,0 +1,591 @@
1
+ import { DEFAULT_DESIGN_SYSTEM_DOCS } from './chunk-56NJFD55.js';
2
+ import { PRIMITIVES_DOCUMENTATION, validateComponentDetailed, formatValidationResultForClaude } from './chunk-HD6ABIK7.js';
3
+ import { validateAllContracts, generateSampleProps, typecheck, lintReactHooks } from './chunk-FWJIMKFZ.js';
4
+ import { isAllowedImport, describeAllowedImports } from './chunk-33B3BAWS.js';
5
+ import { parseVerdictLine } from './chunk-FLRNMZV2.js';
6
+ import * as z from 'zod';
7
+ import * as esbuild from 'esbuild';
8
+ import ts from 'typescript';
9
+ import { existsSync } from 'fs';
10
+ import { createRequire } from 'module';
11
+ import { fileURLToPath, pathToFileURL } from 'url';
12
+ import { runSandboxed } from '@ggui-ai/sandbox';
13
+
14
+ var RENDER_TIMEOUT_MS = 12e3;
15
+ var RENDER_STDOUT_CAP = 512 * 1024;
16
+ var RENDER_NODE_HEAP_MB = 256;
17
+ function resolveWorkerSpawn() {
18
+ const jsCandidates = [
19
+ new URL("./render-check-worker.js", import.meta.url),
20
+ new URL("./tools/render-check-worker.js", import.meta.url),
21
+ new URL("../tools/render-check-worker.js", import.meta.url)
22
+ ];
23
+ const tsCandidates = [
24
+ new URL("./render-check-worker.ts", import.meta.url),
25
+ new URL("../tools/render-check-worker.ts", import.meta.url)
26
+ ];
27
+ for (const jsUrl of jsCandidates) {
28
+ const jsPath = fileURLToPath(jsUrl);
29
+ if (existsSync(jsPath)) {
30
+ return { command: process.execPath, args: [jsPath] };
31
+ }
32
+ }
33
+ for (const tsUrl of tsCandidates) {
34
+ const tsPath = fileURLToPath(tsUrl);
35
+ if (existsSync(tsPath)) {
36
+ const require_ = createRequire(import.meta.url);
37
+ const tsxLoader = pathToFileURL(require_.resolve("tsx")).href;
38
+ return {
39
+ command: process.execPath,
40
+ args: ["--import", tsxLoader, tsPath]
41
+ };
42
+ }
43
+ }
44
+ const tried = [...jsCandidates, ...tsCandidates].map((u) => fileURLToPath(u)).join(", ");
45
+ throw new Error(
46
+ `render-check: worker not found at any of: ${tried}. Did \`pnpm build\` run?`
47
+ );
48
+ }
49
+ async function tryRender(compiledCode, sourceCode, sampleProps) {
50
+ const payload = JSON.stringify({ sourceCode, sampleProps });
51
+ const spawn = resolveWorkerSpawn();
52
+ const result = await runSandboxed({
53
+ command: spawn.command,
54
+ args: spawn.args,
55
+ timeoutMs: RENDER_TIMEOUT_MS,
56
+ maxStdoutBytes: RENDER_STDOUT_CAP,
57
+ nodeHeapMb: RENDER_NODE_HEAP_MB,
58
+ stdin: payload,
59
+ // Forward only what the worker needs. NODE_ENV lets React pick
60
+ // production vs development builds; everything else stays at the
61
+ // sandbox's default allowlist (PATH/HOME/TMPDIR bootstrap).
62
+ env: {
63
+ NODE_ENV: process.env.NODE_ENV ?? "production"
64
+ }
65
+ });
66
+ if (result.outcome === "timeout") {
67
+ return `Render timeout: component did not finish within ${RENDER_TIMEOUT_MS}ms (likely infinite loop or runaway recursion).`;
68
+ }
69
+ if (result.outcome === "overflow-stdout" || result.outcome === "overflow-stderr") {
70
+ return `Render error: worker produced excessive output (${result.outcome}). The component is likely in a pathological state.`;
71
+ }
72
+ if (result.outcome === "canceled") {
73
+ return "Render error: smoke test was canceled before completing.";
74
+ }
75
+ if (result.outcome === "spawn-error") {
76
+ return `Render error: failed to start worker \u2014 ${result.errorMessage}`;
77
+ }
78
+ if (result.outcome !== "exit") {
79
+ return `Render error: unexpected sandbox outcome '${result.outcome}'.`;
80
+ }
81
+ if (result.exitCode !== 0) {
82
+ const tail = result.stderr.trim() || result.stdout.trim();
83
+ return `Render error: worker exited ${result.exitCode}${tail ? ` \u2014 ${tail}` : ""}`;
84
+ }
85
+ let verdict;
86
+ try {
87
+ verdict = parseVerdictLine(result.stdout);
88
+ } catch (err) {
89
+ return `Render error: malformed worker verdict \u2014 ${err instanceof Error ? err.message : String(err)}`;
90
+ }
91
+ if (verdict === void 0) {
92
+ return "Render error: worker exited without producing a verdict.";
93
+ }
94
+ return verdict.ok ? null : verdict.error;
95
+ }
96
+
97
+ // src/adapters/tools.ts
98
+ function createGeneratorTools(context = {}) {
99
+ const tools = [
100
+ // --- get_primitives ---
101
+ {
102
+ name: "get_primitives",
103
+ description: "Get the list of available ggui UI primitives (Container, Card, Stack, Button, Input, etc.) that can be used in components. Call this first to understand what components are available.",
104
+ inputSchema: z.object({}),
105
+ handler: async () => ({
106
+ content: [{ type: "text", text: PRIMITIVES_DOCUMENTATION }]
107
+ })
108
+ },
109
+ // --- get_design_system ---
110
+ {
111
+ name: "get_design_system",
112
+ description: "Get the design system tokens and CSS variables for this app. Use these CSS variables (var(--ggui-*)) for colors, spacing, typography, etc.",
113
+ inputSchema: z.object({}),
114
+ handler: async () => ({
115
+ content: [{
116
+ type: "text",
117
+ text: context.designContext ? `# App Theme Configuration
118
+
119
+ ${context.designContext}
120
+
121
+ **IMPORTANT:** Always use CSS variables (var(--ggui-*)) for colors, spacing, etc.` : DEFAULT_DESIGN_SYSTEM_DOCS
122
+ }]
123
+ })
124
+ },
125
+ // --- get_app_components ---
126
+ {
127
+ name: "get_app_components",
128
+ description: "Get predefined reusable components specific to this app. These can be imported and used in your generated component.",
129
+ inputSchema: z.object({}),
130
+ handler: async () => ({
131
+ content: [{
132
+ type: "text",
133
+ text: context.componentContext || "No predefined components available for this app."
134
+ }]
135
+ })
136
+ },
137
+ // --- validate_component ---
138
+ {
139
+ name: "validate_component",
140
+ description: "Validate component code before compilation. Checks for security issues, syntax errors, and best practices. Returns detailed feedback.",
141
+ inputSchema: z.object({
142
+ code: z.string().describe("The TypeScript/TSX component code to validate")
143
+ }),
144
+ handler: async (args) => {
145
+ const result = validateComponentDetailed(args.code);
146
+ return {
147
+ content: [
148
+ {
149
+ type: "text",
150
+ text: formatValidationResultForClaude(result)
151
+ }
152
+ ],
153
+ isError: !result.valid
154
+ };
155
+ }
156
+ },
157
+ // --- self_check ---
158
+ {
159
+ name: "self_check",
160
+ description: "Run deterministic quality checks on your code BEFORE compiling. Catches common issues instantly (zero cost). Returns pass/fail per check with line numbers and fix instructions. Call this after writing code, fix any failures, then compile.",
161
+ inputSchema: z.object({
162
+ code: z.string().describe("The TypeScript/TSX component code to check")
163
+ }),
164
+ handler: async (args) => {
165
+ const code = args.code;
166
+ const { issues, typeWarnings } = await runSelfChecks(code, context.contract);
167
+ if (context.contract) {
168
+ const contractIssues = validateAllContracts(code, context.contract);
169
+ for (const ci of contractIssues) {
170
+ issues.push({
171
+ check: `contract:${ci.field}`,
172
+ line: 0,
173
+ message: `[${ci.severity}] ${ci.message}`,
174
+ fix: ci.fix
175
+ });
176
+ }
177
+ }
178
+ if (issues.length === 0) {
179
+ const warningText = typeWarnings.length > 0 ? `
180
+
181
+ Type warnings (non-blocking):
182
+ ${typeWarnings.map((w) => `[${w.check}] ${w.line ? `Line ${w.line}: ` : ""}${w.message}`).join("\n")}` : "";
183
+ return {
184
+ content: [{ type: "text", text: `All checks passed. Ready to compile.${warningText}` }]
185
+ };
186
+ }
187
+ const report = issues.map((i) => `[${i.check}] ${i.line ? `Line ${i.line}: ` : ""}${i.message}
188
+ Fix: ${i.fix}`).join("\n\n");
189
+ return {
190
+ content: [{ type: "text", text: `${issues.length} issue(s) found:
191
+
192
+ ${report}` }],
193
+ isError: true
194
+ };
195
+ }
196
+ },
197
+ // --- compile_component ---
198
+ {
199
+ name: "compile_component",
200
+ description: "Compile a TypeScript/TSX component to JavaScript using esbuild. Returns the compiled code ready for browser execution. On failure, returns detailed error context with line numbers and fix suggestions.",
201
+ inputSchema: z.object({
202
+ code: z.string().describe("The TypeScript/TSX component code to compile"),
203
+ filename: z.string().default("Component.tsx").describe("Filename for error messages")
204
+ }),
205
+ handler: async (args) => {
206
+ const code = args.code;
207
+ const filename = args.filename || "Component.tsx";
208
+ const { issues: selfCheckIssues } = await runSelfChecks(code, context.contract);
209
+ if (context.contract) {
210
+ const contractIssues = validateAllContracts(code, context.contract);
211
+ for (const ci of contractIssues) {
212
+ selfCheckIssues.push({
213
+ check: `contract:${ci.field}`,
214
+ line: 0,
215
+ message: `[${ci.severity}] ${ci.message}`,
216
+ fix: ci.fix
217
+ });
218
+ }
219
+ }
220
+ if (selfCheckIssues.length > 0) {
221
+ const report = selfCheckIssues.map((i) => `[${i.check}] ${i.line ? `Line ${i.line}: ` : ""}${i.message}
222
+ Fix: ${i.fix}`).join("\n\n");
223
+ return {
224
+ content: [{
225
+ type: "text",
226
+ text: JSON.stringify({
227
+ success: false,
228
+ phase: "self_check",
229
+ error: `${selfCheckIssues.length} issue(s) found \u2014 fix these before recompiling:
230
+
231
+ ${report}`
232
+ }, null, 2)
233
+ }],
234
+ isError: true
235
+ };
236
+ }
237
+ const validation = validateComponentDetailed(code);
238
+ if (!validation.valid) {
239
+ return {
240
+ content: [
241
+ {
242
+ type: "text",
243
+ text: JSON.stringify(
244
+ {
245
+ success: false,
246
+ phase: "validation",
247
+ error: formatValidationResultForClaude(validation)
248
+ },
249
+ null,
250
+ 2
251
+ )
252
+ }
253
+ ],
254
+ isError: true
255
+ };
256
+ }
257
+ try {
258
+ const result = await esbuild.transform(code, {
259
+ loader: "tsx",
260
+ target: "es2020",
261
+ format: "esm",
262
+ jsx: "automatic",
263
+ jsxImportSource: "react",
264
+ minify: true,
265
+ sourcefile: filename
266
+ });
267
+ const warnings = [
268
+ ...result.warnings.map((w) => w.text),
269
+ ...validation.warnings.map(
270
+ (w) => `[${w.type}] ${w.message}: ${w.suggestion}`
271
+ )
272
+ ];
273
+ if (context.contract) {
274
+ const contractIssues = validateAllContracts(code, context.contract);
275
+ const errors = contractIssues.filter((i) => i.severity === "error");
276
+ const contractWarnings = contractIssues.filter((i) => i.severity === "warning");
277
+ if (errors.length > 0) {
278
+ const report = errors.map((i) => `- [${i.field}] ${i.message}
279
+ Fix: ${i.fix}`).join("\n");
280
+ return {
281
+ content: [{
282
+ type: "text",
283
+ text: JSON.stringify({
284
+ success: false,
285
+ phase: "contract_validation",
286
+ error: `Compilation succeeded but data contract validation failed:
287
+
288
+ ${report}
289
+
290
+ Fix the Props interface to match the data contract, then recompile.`
291
+ }, null, 2)
292
+ }],
293
+ isError: true
294
+ };
295
+ }
296
+ warnings.push(...contractWarnings.map((i) => `[contract:${i.field}] ${i.message}`));
297
+ }
298
+ const sampleProps = context.sampleProps ?? (context.contract?.propsSpec ? generateSampleProps(context.contract.propsSpec) : void 0);
299
+ const renderError = await tryRender(result.code, code, sampleProps);
300
+ if (renderError) {
301
+ return {
302
+ content: [{
303
+ type: "text",
304
+ text: JSON.stringify({
305
+ success: false,
306
+ phase: "render_smoke_test",
307
+ compiledCode: result.code,
308
+ error: `${renderError}
309
+
310
+ The component compiled but crashes at runtime. Fix the null/undefined access and recompile.`,
311
+ warnings
312
+ }, null, 2)
313
+ }],
314
+ isError: true
315
+ };
316
+ }
317
+ return {
318
+ content: [
319
+ {
320
+ type: "text",
321
+ text: JSON.stringify(
322
+ {
323
+ success: true,
324
+ compiledCode: result.code,
325
+ warnings
326
+ },
327
+ null,
328
+ 2
329
+ )
330
+ }
331
+ ]
332
+ };
333
+ } catch (error) {
334
+ return {
335
+ content: [
336
+ {
337
+ type: "text",
338
+ text: JSON.stringify(
339
+ { success: false, phase: "compilation", error: formatEsbuildError(error, code) },
340
+ null,
341
+ 2
342
+ )
343
+ }
344
+ ],
345
+ isError: true
346
+ };
347
+ }
348
+ }
349
+ }
350
+ ];
351
+ return tools;
352
+ }
353
+ function formatEsbuildError(error, sourceCode) {
354
+ const parts = [];
355
+ if (error && typeof error === "object" && "errors" in error && Array.isArray(error.errors)) {
356
+ const esbuildError = error;
357
+ for (const err of esbuildError.errors) {
358
+ const line = err.location?.line;
359
+ const col = err.location?.column;
360
+ parts.push(`**Error:** ${err.text}`);
361
+ if (line) {
362
+ parts.push(`**Location:** Line ${line}, Column ${col ?? 0}`);
363
+ const lines = sourceCode.split("\n");
364
+ const start = Math.max(0, line - 3);
365
+ const end = Math.min(lines.length, line + 2);
366
+ const context = lines.slice(start, end).map((l, i) => {
367
+ const ln = start + i + 1;
368
+ return `${ln === line ? ">>> " : " "}${ln} | ${l}`;
369
+ }).join("\n");
370
+ parts.push(`**Code:**
371
+ \`\`\`
372
+ ${context}
373
+ \`\`\``);
374
+ }
375
+ }
376
+ } else {
377
+ parts.push(`**Error:** ${error instanceof Error ? error.message : "Compilation failed"}`);
378
+ }
379
+ parts.push("\n**How to fix:** Review the error above, fix the code, then call compile_component again.");
380
+ return parts.join("\n");
381
+ }
382
+ var LABELED_COMPONENTS = /* @__PURE__ */ new Set(["Input", "TextArea", "Select"]);
383
+ function checkReactRules(code) {
384
+ const sf = ts.createSourceFile("component.tsx", code, ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX);
385
+ const issues = [];
386
+ function visit(node) {
387
+ if (ts.isJsxSelfClosingElement(node) || ts.isJsxOpeningElement(node)) {
388
+ const tagName = node.tagName.getText(sf);
389
+ if (LABELED_COMPONENTS.has(tagName)) {
390
+ const propNames = /* @__PURE__ */ new Set();
391
+ let hasSpread = false;
392
+ for (const attr of node.attributes.properties) {
393
+ if (ts.isJsxAttribute(attr)) {
394
+ propNames.add(attr.name.getText(sf));
395
+ } else if (ts.isJsxSpreadAttribute(attr)) {
396
+ hasSpread = true;
397
+ }
398
+ }
399
+ if (!hasSpread && !propNames.has("label") && !propNames.has("aria-label")) {
400
+ const line = sf.getLineAndCharacterOfPosition(node.getStart(sf)).line + 1;
401
+ issues.push({
402
+ check: "accessibility",
403
+ line,
404
+ message: `${tagName} missing label prop`,
405
+ fix: `Add label="..." prop directly on the ${tagName} component. The label prop is built into the primitive.`
406
+ });
407
+ }
408
+ }
409
+ }
410
+ ts.forEachChild(node, visit);
411
+ }
412
+ visit(sf);
413
+ return issues;
414
+ }
415
+ async function runSelfChecks(code, contract) {
416
+ const issues = [];
417
+ const lines = code.split("\n");
418
+ const allowedGadgetPackages = new Set(
419
+ Object.keys(contract?.clientCapabilities?.gadgets ?? {})
420
+ );
421
+ for (let i = 0; i < lines.length; i++) {
422
+ const line = lines[i];
423
+ const lineNum = i + 1;
424
+ const hexMatch = line.match(/#[0-9a-fA-F]{3,8}\b/);
425
+ if (hexMatch && !line.includes("var(--ggui-") && !line.includes("// fallback")) {
426
+ issues.push({
427
+ check: "hex-color",
428
+ line: lineNum,
429
+ message: `Hardcoded color "${hexMatch[0]}" \u2014 must use design tokens`,
430
+ fix: `Replace "${hexMatch[0]}" with a primitive variant OR a bare token reference such as var(--ggui-color-primary-500) \u2014 never a literal fallback inside var()`
431
+ });
432
+ }
433
+ const colorFnMatch = line.match(/\b(rgba?|hsla?)\s*\(/);
434
+ if (colorFnMatch && !line.includes("var(--ggui-") && !line.includes("// fallback") && !line.includes("$value")) {
435
+ issues.push({
436
+ check: "hardcoded-color-fn",
437
+ line: lineNum,
438
+ message: `Hardcoded ${colorFnMatch[1]}() \u2014 use design tokens instead`,
439
+ fix: `Replace with the layering roles: var(--ggui-color-container), var(--ggui-color-onContainer), var(--ggui-color-outline), etc.`
440
+ });
441
+ }
442
+ if (/--ggui-color-neutral-50[^0-9]/.test(line) && /background/i.test(line)) {
443
+ issues.push({
444
+ check: "prefer-semantic",
445
+ line: lineNum,
446
+ message: `neutral-50 for background \u2014 prefer semantic token for dark-theme compatibility`,
447
+ fix: `Replace with var(--ggui-color-container) or var(--ggui-color-sunken)`
448
+ });
449
+ }
450
+ if (/--ggui-color-neutral-900[^0-9]/.test(line) && /color/i.test(line) && !/background/i.test(line)) {
451
+ issues.push({
452
+ check: "prefer-semantic",
453
+ line: lineNum,
454
+ message: `neutral-900 for text color \u2014 prefer semantic token for dark-theme compatibility`,
455
+ fix: `Replace with var(--ggui-color-onContainer) or var(--ggui-color-onSunken)`
456
+ });
457
+ }
458
+ const pxMatch = line.match(/(?:padding|margin|gap|borderRadius)\s*:\s*['"]?\d+px/);
459
+ if (pxMatch && !line.includes("var(--ggui-")) {
460
+ issues.push({
461
+ check: "raw-pixels",
462
+ line: lineNum,
463
+ message: `Raw pixel value in spacing \u2014 must use design tokens`,
464
+ fix: `Replace with a bare var(--ggui-spacing-*) token \u2014 no literal fallback \u2014 or the scale name on the primitive prop (gap="md", padding="lg")`
465
+ });
466
+ }
467
+ if (/\beval\s*\(/.test(line)) {
468
+ issues.push({ check: "security", line: lineNum, message: "eval() is forbidden", fix: "Remove eval() call entirely" });
469
+ }
470
+ if (/\bfetch\s*\(/.test(line)) {
471
+ issues.push({ check: "security", line: lineNum, message: "fetch() is forbidden \u2014 use props for data", fix: "Remove fetch() and pass data via props" });
472
+ }
473
+ const importMatch = line.match(/import\s+.*from\s+['"]([^'"]+)['"]/);
474
+ if (importMatch) {
475
+ const pkg = importMatch[1];
476
+ if (!isAllowedImport(pkg, allowedGadgetPackages)) {
477
+ issues.push({
478
+ check: "import",
479
+ line: lineNum,
480
+ message: `Import from "${pkg}" is not allowed`,
481
+ fix: `Only import from: ${describeAllowedImports()}`
482
+ });
483
+ }
484
+ }
485
+ }
486
+ try {
487
+ const jsxIssues = checkReactRules(code);
488
+ issues.push(...jsxIssues);
489
+ } catch {
490
+ }
491
+ if (!code.includes("interface Props") && !code.includes("type Props")) {
492
+ issues.push({
493
+ check: "props-interface",
494
+ line: 1,
495
+ message: "No Props interface found \u2014 data is likely hardcoded",
496
+ fix: "Add interface Props { ... } with typed fields and default values in the function signature"
497
+ });
498
+ }
499
+ if (!code.includes("export default function")) {
500
+ issues.push({
501
+ check: "export",
502
+ line: 1,
503
+ message: "Missing default export function",
504
+ fix: "Add export default function GeneratedComponent(props: Props) { ... }"
505
+ });
506
+ }
507
+ const typeWarnings = [];
508
+ const [typeResult, reactResult] = await Promise.all([
509
+ typecheck(code).catch((err) => {
510
+ console.warn("[runSelfChecks] TypeChecker failed:", err instanceof Error ? err.message : String(err));
511
+ return null;
512
+ }),
513
+ lintReactHooks(code).catch((err) => {
514
+ console.warn("[runSelfChecks] React linter failed:", err instanceof Error ? err.message : String(err));
515
+ return [];
516
+ })
517
+ ]);
518
+ if (typeResult) {
519
+ for (const error of typeResult.errors) {
520
+ issues.push({
521
+ check: `ts${error.code}`,
522
+ line: error.line,
523
+ message: error.message,
524
+ fix: error.fix
525
+ });
526
+ }
527
+ for (const warning of typeResult.warnings) {
528
+ typeWarnings.push({
529
+ check: `ts${warning.code}`,
530
+ line: warning.line,
531
+ message: warning.message,
532
+ fix: warning.fix
533
+ });
534
+ }
535
+ }
536
+ const hasStateSetter = /\b(set[A-Z]\w*|dispatch)\s*\(/.test(code);
537
+ const isSetterLoopRisk = (diag) => {
538
+ if (diag.rule !== "react-hooks/exhaustive-deps") return false;
539
+ if (!hasStateSetter) return false;
540
+ return /missing dependenc|changes on every render|object makes the dependencies|array makes the dependencies/i.test(
541
+ diag.message
542
+ );
543
+ };
544
+ for (const diag of reactResult) {
545
+ const blocking = diag.severity === "error" || isSetterLoopRisk(diag);
546
+ if (blocking) {
547
+ issues.push({
548
+ check: diag.rule,
549
+ line: diag.line,
550
+ message: isSetterLoopRisk(diag) ? `${diag.message} (promoted to error: effect mutates state \u2014 missing/unstable deps cause infinite render loops)` : diag.message,
551
+ fix: diag.fix
552
+ });
553
+ } else {
554
+ typeWarnings.push({
555
+ check: diag.rule,
556
+ line: diag.line,
557
+ message: diag.message,
558
+ fix: diag.fix
559
+ });
560
+ }
561
+ }
562
+ const lineMap = /* @__PURE__ */ new Map();
563
+ for (const i of issues) {
564
+ const list = lineMap.get(i.line) ?? [];
565
+ list.push(i);
566
+ lineMap.set(i.line, list);
567
+ }
568
+ const deduped = [];
569
+ for (const [, group] of lineMap) {
570
+ if (group.length === 1) {
571
+ deduped.push(group[0]);
572
+ continue;
573
+ }
574
+ const primary = group.find((i) => !i.check.startsWith("ts")) ?? group[0];
575
+ const others = group.filter((i) => i !== primary);
576
+ if (others.length > 0) {
577
+ const alsoTags = others.map((o) => o.check).join(", ");
578
+ deduped.push({
579
+ ...primary,
580
+ message: `${primary.message} [also flagged by: ${alsoTags}]`
581
+ });
582
+ } else {
583
+ deduped.push(primary);
584
+ }
585
+ }
586
+ return { issues: deduped, typeWarnings };
587
+ }
588
+
589
+ export { createGeneratorTools };
590
+ //# sourceMappingURL=chunk-3HSGA6NI.js.map
591
+ //# sourceMappingURL=chunk-3HSGA6NI.js.map