@ggui-ai/ui-gen 0.28.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.
- package/dist/{adapter-h4_V69LI.d.ts → adapter-DLQ-5COm.d.ts} +1 -1
- package/dist/adapters/base.js +2 -27
- package/dist/adapters/base.js.map +1 -1
- package/dist/adapters/generation-dispatch.d.ts +14 -6
- package/dist/adapters/generation-dispatch.js +40 -19260
- package/dist/adapters/generation-dispatch.js.map +1 -1
- package/dist/adapters/index.d.ts +1 -1
- package/dist/adapters/index.js +25 -3561
- package/dist/adapters/index.js.map +1 -1
- package/dist/adapters/types.js +2 -9
- package/dist/adapters/types.js.map +1 -1
- package/dist/advanced/index.d.ts +13 -12
- package/dist/advanced/index.js +63 -21954
- package/dist/advanced/index.js.map +1 -1
- package/dist/{bank-Ctdp3FUA.d.ts → bank-LWaiAtaA.d.ts} +1 -1
- package/dist/blueprint-validator.js +6 -2301
- package/dist/blueprint-validator.js.map +1 -1
- package/dist/boilerplate.d.ts +3 -2
- package/dist/boilerplate.js +6 -1867
- package/dist/boilerplate.js.map +1 -1
- package/dist/check/index.d.ts +3 -2
- package/dist/check/index.js +6 -1923
- package/dist/check/index.js.map +1 -1
- package/dist/chunk-33B3BAWS.js +24 -0
- package/dist/chunk-33B3BAWS.js.map +1 -0
- package/dist/chunk-3HSGA6NI.js +591 -0
- package/dist/chunk-3HSGA6NI.js.map +1 -0
- package/dist/chunk-3NNNGNTO.js +1707 -0
- package/dist/chunk-3NNNGNTO.js.map +1 -0
- package/dist/chunk-3T2HMTON.js +79 -0
- package/dist/chunk-3T2HMTON.js.map +1 -0
- package/dist/chunk-3ZSSDV3L.js +123 -0
- package/dist/chunk-3ZSSDV3L.js.map +1 -0
- package/dist/chunk-4MBR5GA3.js +99 -0
- package/dist/chunk-4MBR5GA3.js.map +1 -0
- package/dist/chunk-56NJFD55.js +337 -0
- package/dist/chunk-56NJFD55.js.map +1 -0
- package/dist/chunk-5AGTY555.js +26 -0
- package/dist/chunk-5AGTY555.js.map +1 -0
- package/dist/chunk-5EJM7EGY.js +115 -0
- package/dist/chunk-5EJM7EGY.js.map +1 -0
- package/dist/chunk-5KXCQLLR.js +529 -0
- package/dist/chunk-5KXCQLLR.js.map +1 -0
- package/dist/chunk-5VBXHVEH.js +171 -0
- package/dist/chunk-5VBXHVEH.js.map +1 -0
- package/dist/chunk-6KDDEING.js +515 -0
- package/dist/chunk-6KDDEING.js.map +1 -0
- package/dist/chunk-6VDRWAP6.js +123 -0
- package/dist/chunk-6VDRWAP6.js.map +1 -0
- package/dist/chunk-732IBFEJ.js +2400 -0
- package/dist/chunk-732IBFEJ.js.map +1 -0
- package/dist/chunk-73AURS3I.js +46 -0
- package/dist/chunk-73AURS3I.js.map +1 -0
- package/dist/chunk-77H5SKLX.js +8 -0
- package/dist/chunk-77H5SKLX.js.map +1 -0
- package/dist/chunk-7QE3AHLE.js +35 -0
- package/dist/chunk-7QE3AHLE.js.map +1 -0
- package/dist/chunk-A375NNWN.js +11 -0
- package/dist/chunk-A375NNWN.js.map +1 -0
- package/dist/chunk-AOU33EFS.js +140 -0
- package/dist/chunk-AOU33EFS.js.map +1 -0
- package/dist/chunk-BA4QYA6E.js +461 -0
- package/dist/chunk-BA4QYA6E.js.map +1 -0
- package/dist/chunk-DBP764GL.js +3 -0
- package/dist/chunk-DBP764GL.js.map +1 -0
- package/dist/chunk-DUU3ZJDQ.js +41 -0
- package/dist/chunk-DUU3ZJDQ.js.map +1 -0
- package/dist/chunk-DXKRBXNU.js +30 -0
- package/dist/chunk-DXKRBXNU.js.map +1 -0
- package/dist/chunk-FB7OEEAH.js +1467 -0
- package/dist/chunk-FB7OEEAH.js.map +1 -0
- package/dist/chunk-FLRNMZV2.js +18 -0
- package/dist/chunk-FLRNMZV2.js.map +1 -0
- package/dist/chunk-FWJIMKFZ.js +2032 -0
- package/dist/chunk-FWJIMKFZ.js.map +1 -0
- package/dist/chunk-FXRHWYIQ.js +163 -0
- package/dist/chunk-FXRHWYIQ.js.map +1 -0
- package/dist/chunk-G3PMV62Z.js +33 -0
- package/dist/chunk-G3PMV62Z.js.map +1 -0
- package/dist/chunk-GAJI7Y3P.js +13 -0
- package/dist/chunk-GAJI7Y3P.js.map +1 -0
- package/dist/chunk-GYINWMPR.js +2052 -0
- package/dist/chunk-GYINWMPR.js.map +1 -0
- package/dist/chunk-HD6ABIK7.js +484 -0
- package/dist/chunk-HD6ABIK7.js.map +1 -0
- package/dist/chunk-HDQVHYO6.js +100 -0
- package/dist/chunk-HDQVHYO6.js.map +1 -0
- package/dist/chunk-IHUT3SIW.js +7 -0
- package/dist/chunk-IHUT3SIW.js.map +1 -0
- package/dist/chunk-JDH5EGNZ.js +126 -0
- package/dist/chunk-JDH5EGNZ.js.map +1 -0
- package/dist/chunk-JMD4RGSV.js +37 -0
- package/dist/chunk-JMD4RGSV.js.map +1 -0
- package/dist/chunk-KJWGZL5B.js +33 -0
- package/dist/chunk-KJWGZL5B.js.map +1 -0
- package/dist/chunk-MKMDQFZ7.js +86 -0
- package/dist/chunk-MKMDQFZ7.js.map +1 -0
- package/dist/chunk-NF6JUZWF.js +85 -0
- package/dist/chunk-NF6JUZWF.js.map +1 -0
- package/dist/chunk-O2YC6XDC.js +1933 -0
- package/dist/chunk-O2YC6XDC.js.map +1 -0
- package/dist/chunk-OVLH5ICV.js +29 -0
- package/dist/chunk-OVLH5ICV.js.map +1 -0
- package/dist/chunk-PBOYHGSD.js +106 -0
- package/dist/chunk-PBOYHGSD.js.map +1 -0
- package/dist/chunk-PJFH7QWA.js +81 -0
- package/dist/chunk-PJFH7QWA.js.map +1 -0
- package/dist/chunk-PUH4CXGZ.js +284 -0
- package/dist/chunk-PUH4CXGZ.js.map +1 -0
- package/dist/chunk-QLXXPGTV.js +18 -0
- package/dist/chunk-QLXXPGTV.js.map +1 -0
- package/dist/chunk-R5GIGPW2.js +2845 -0
- package/dist/chunk-R5GIGPW2.js.map +1 -0
- package/dist/chunk-RH4IUSTO.js +83 -0
- package/dist/chunk-RH4IUSTO.js.map +1 -0
- package/dist/chunk-S2GVXKKY.js +153 -0
- package/dist/chunk-S2GVXKKY.js.map +1 -0
- package/dist/chunk-TVHGKFJS.js +58 -0
- package/dist/chunk-TVHGKFJS.js.map +1 -0
- package/dist/chunk-U7GALWLG.js +66 -0
- package/dist/chunk-U7GALWLG.js.map +1 -0
- package/dist/chunk-VTC263LT.js +256 -0
- package/dist/chunk-VTC263LT.js.map +1 -0
- package/dist/chunk-WEOXFEVE.js +739 -0
- package/dist/chunk-WEOXFEVE.js.map +1 -0
- package/dist/chunk-WYHP46LT.js +28 -0
- package/dist/chunk-WYHP46LT.js.map +1 -0
- package/dist/chunk-XGLO5LGG.js +274 -0
- package/dist/chunk-XGLO5LGG.js.map +1 -0
- package/dist/chunk-XRBCRKA2.js +29 -0
- package/dist/chunk-XRBCRKA2.js.map +1 -0
- package/dist/chunk-XW7ADFFV.js +340 -0
- package/dist/chunk-XW7ADFFV.js.map +1 -0
- package/dist/chunk-YIQ42IUX.js +34 -0
- package/dist/chunk-YIQ42IUX.js.map +1 -0
- package/dist/chunk-YJZTUY7B.js +101 -0
- package/dist/chunk-YJZTUY7B.js.map +1 -0
- package/dist/chunk-Z3CXME3K.js +107 -0
- package/dist/chunk-Z3CXME3K.js.map +1 -0
- package/dist/classifier/index.js +2 -527
- package/dist/classifier/index.js.map +1 -1
- package/dist/client-JBPCXU7W.js +4 -0
- package/dist/client-JBPCXU7W.js.map +1 -0
- package/dist/compose.js +3 -367
- package/dist/compose.js.map +1 -1
- package/dist/cost-tracker-HHGQ4FTW.js +67 -0
- package/dist/cost-tracker-HHGQ4FTW.js.map +1 -0
- package/dist/{create-ui-generator-BrZHF0cf.d.ts → create-ui-generator-BY-WeaPi.d.ts} +3 -3
- package/dist/{design-mode-DGWN_Gkm.d.ts → design-mode-XyOQmzE0.d.ts} +4 -3
- package/dist/{dispatch-B07TI30d.d.ts → dispatch-8LzTddKw.d.ts} +3 -2
- package/dist/dist-UALN6ZVB.js +543 -0
- package/dist/dist-UALN6ZVB.js.map +1 -0
- package/dist/dupe-break-X6K7QFIS.js +4 -0
- package/dist/dupe-break-X6K7QFIS.js.map +1 -0
- package/dist/evaluation/axis-checks/index.d.ts +5 -4
- package/dist/evaluation/axis-checks/index.js +6 -1914
- package/dist/evaluation/axis-checks/index.js.map +1 -1
- package/dist/evaluation/axis-checks/registry.d.ts +3 -2
- package/dist/evaluation/axis-checks/registry.js +3 -1844
- package/dist/evaluation/axis-checks/registry.js.map +1 -1
- package/dist/evaluation/index.d.ts +49 -132
- package/dist/evaluation/index.js +302 -6466
- package/dist/evaluation/index.js.map +1 -1
- package/dist/evaluation/types.d.ts +3 -2
- package/dist/evaluation/types.js +2 -5
- package/dist/evaluation/types.js.map +1 -1
- package/dist/fragments/index.js +2 -338
- package/dist/fragments/index.js.map +1 -1
- package/dist/{generate-tSO_shQ0.d.ts → generate-DQ4ci90s.d.ts} +1 -1
- package/dist/harness/check/runtime-render/index.d.ts +35 -15
- package/dist/harness/check/runtime-render/index.js +6 -2390
- package/dist/harness/check/runtime-render/index.js.map +1 -1
- package/dist/harness/check/runtime-render/render-check-worker.js +4 -1739
- package/dist/harness/check/runtime-render/render-check-worker.js.map +1 -1
- package/dist/harness/index.d.ts +3 -2
- package/dist/harness/index.js +23 -5126
- package/dist/harness/index.js.map +1 -1
- package/dist/harness/llm-trace-sink.js +2 -24
- package/dist/harness/llm-trace-sink.js.map +1 -1
- package/dist/harness/prompts.d.ts +2 -2
- package/dist/harness/prompts.js +8 -324
- package/dist/harness/prompts.js.map +1 -1
- package/dist/harness/result-types.d.ts +6 -5
- package/dist/harness/result-types.js +2 -0
- package/dist/harness/result-types.js.map +1 -1
- package/dist/harness/runtime.d.ts +22 -5
- package/dist/harness/runtime.js +10 -2313
- package/dist/harness/runtime.js.map +1 -1
- package/dist/harness/types-public.d.ts +3 -2
- package/dist/harness/types-public.js +16 -2954
- package/dist/harness/types-public.js.map +1 -1
- package/dist/harness/validator-trace-sink.d.ts +3 -2
- package/dist/harness/validator-trace-sink.js +2 -26
- package/dist/harness/validator-trace-sink.js.map +1 -1
- package/dist/hash.js +2 -39
- package/dist/hash.js.map +1 -1
- package/dist/hashline-5OKREIRM.js +4 -0
- package/dist/hashline-5OKREIRM.js.map +1 -0
- package/dist/index.d.ts +50 -11
- package/dist/index.js +57 -22015
- package/dist/index.js.map +1 -1
- package/dist/llm-evaluator-PN3WFCS4.js +653 -0
- package/dist/llm-evaluator-PN3WFCS4.js.map +1 -0
- package/dist/magic-string.es-2NZTC4GZ.js +1307 -0
- package/dist/magic-string.es-2NZTC4GZ.js.map +1 -0
- package/dist/patch.d.ts +3 -2
- package/dist/patch.js +2 -56
- package/dist/patch.js.map +1 -1
- package/dist/policy-VCYKGSAC.js +5 -0
- package/dist/policy-VCYKGSAC.js.map +1 -0
- package/dist/policy.js +2 -35
- package/dist/policy.js.map +1 -1
- package/dist/primitive-index-2OF6F4TZ.js +131 -0
- package/dist/primitive-index-2OF6F4TZ.js.map +1 -0
- package/dist/primitive-slice-WTMBLYFJ.js +235 -0
- package/dist/primitive-slice-WTMBLYFJ.js.map +1 -0
- package/dist/{prompts-BhNUuRoZ.d.ts → prompts-CLZGywMP.d.ts} +1 -1
- package/dist/provider-adapter-contract.js +10407 -14204
- package/dist/provider-adapter-contract.js.map +1 -1
- package/dist/provider-adapter.js +2 -44
- package/dist/provider-adapter.js.map +1 -1
- package/dist/providers/index.d.ts +89 -1
- package/dist/providers/index.js +115 -44
- package/dist/providers/index.js.map +1 -1
- package/dist/raw-C6KBH5I3.js +141 -0
- package/dist/raw-C6KBH5I3.js.map +1 -0
- package/dist/raw-FXSBXQTZ.js +7 -0
- package/dist/raw-FXSBXQTZ.js.map +1 -0
- package/dist/raw-MURDUPGK.js +8 -0
- package/dist/raw-MURDUPGK.js.map +1 -0
- package/dist/raw-T3GW3UVX.js +8 -0
- package/dist/raw-T3GW3UVX.js.map +1 -0
- package/dist/render-check-host-ZNIS6BJ5.js +5 -0
- package/dist/render-check-host-ZNIS6BJ5.js.map +1 -0
- package/dist/sdk-4JNSDNSR.js +6 -0
- package/dist/sdk-4JNSDNSR.js.map +1 -0
- package/dist/sdk-DIVJMHCX.js +7 -0
- package/dist/sdk-DIVJMHCX.js.map +1 -0
- package/dist/sdk-QRJOCRTS.js +7 -0
- package/dist/sdk-QRJOCRTS.js.map +1 -0
- package/dist/tag-balance-CTHCTRJ7.js +123 -0
- package/dist/tag-balance-CTHCTRJ7.js.map +1 -0
- package/dist/tools/get-primitives-ts.d.ts +1 -1
- package/dist/tools/get-primitives-ts.js +3 -1
- package/dist/tools/get-primitives-ts.js.map +1 -1
- package/dist/tools/render-check-worker.js +3 -40
- package/dist/tools/render-check-worker.js.map +1 -1
- package/dist/{types-public-h8IMnYuh.d.ts → types-public-hYlrerZh.d.ts} +35 -2
- package/dist/validation/index.d.ts +2 -2
- package/dist/validation/index.js +3 -498
- package/dist/validation/index.js.map +1 -1
- package/dist/{visual-evaluator-C2strxqD.d.ts → visual-evaluator-KskajxD5.d.ts} +14 -4
- package/dist/visual-evaluator-TGEXYQTP.js +12 -0
- package/dist/visual-evaluator-TGEXYQTP.js.map +1 -0
- package/dist/workflows.d.ts +3 -2
- package/dist/workflows.js +2 -151
- package/dist/workflows.js.map +1 -1
- package/package.json +20 -16
- package/src/adapters/claude/sdk.ts +4 -2
- package/src/adapters/claude/tool-bridge.ts +2 -1
- package/src/adapters/generation-dispatch.ts +9 -0
- package/src/adapters/openai/raw.ts +4 -0
- package/src/adapters/openai/sdk.ts +6 -1
- package/src/adapters/openai/tokens.ts +21 -7
- package/src/adapters/tool-bridge.ts +1 -1
- package/src/adapters/tools.ts +1 -1
- package/src/advanced/feedback.ts +1 -2
- package/src/advanced/generator.ts +4 -3
- package/src/boilerplate/free-design-prompt.ts +7 -0
- package/src/boilerplate/generate.ts +18 -5
- package/src/boilerplate/hard-sections.ts +8 -3
- package/src/boilerplate/react-hooks.ts +56 -0
- package/src/boilerplate/system-prompt.ts +12 -3
- package/src/check/run-tier0.ts +233 -8
- package/src/check/type-checker.ts +128 -16
- package/src/coding-agent/tools.ts +26 -3
- package/src/design-mode.ts +4 -9
- package/src/evaluation/axis-checks/checks/state-merge.ts +2 -4
- package/src/evaluation/axis-checks/checks/state-payload.ts +1 -28
- package/src/evaluation/axis-checks/checks/tint.ts +197 -0
- package/src/evaluation/axis-checks/helpers.ts +121 -0
- package/src/evaluation/axis-checks/registry.ts +2 -0
- package/src/evaluation/criteria/__fixtures__/edge-v2-draw2.json +4629 -0
- package/src/evaluation/criteria/bank.ts +1 -1
- package/src/evaluation/criteria/edge-instruments.ts +14 -0
- package/src/evaluation/criteria/edge-probe-v2.ts +352 -0
- package/src/evaluation/criteria/edge-v2.ts +242 -0
- package/src/evaluation/criteria/resolve.ts +24 -5
- package/src/evaluation/index.ts +3 -5
- package/src/evaluation/mcp-server.ts +0 -50
- package/src/evaluation/types-public.ts +6 -1
- package/src/evaluation/visual-evaluator.ts +161 -30
- package/src/harness/check/runtime-render/index.ts +28 -4
- package/src/harness/check/runtime-render/render-check.ts +20 -21
- package/src/harness/claude-agent-sdk-loader.ts +93 -0
- package/src/harness/claude-code-login-query.ts +1 -1
- package/src/harness/coding/generate-task-runner.ts +1 -0
- package/src/harness/coding/run-coding-turn.ts +3 -0
- package/src/harness/coding/run-eval-round.ts +9 -0
- package/src/harness/llm-router.ts +50 -2
- package/src/harness/runtime.ts +17 -0
- package/src/index.ts +9 -0
- package/src/providers/anthropic-tool-call.ts +263 -0
- package/src/providers/index.ts +13 -0
- package/src/tools/get-primitives-ts.ts +1 -1
- package/src/tools/render-check.ts +4 -4
- package/src/validation/primitives.ts +2 -1
- package/src/evaluation/loop.ts +0 -218
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/design-system-docs.ts"],"names":[],"mappings":";AAeO,IAAM,0BAAA,GAA6B,CAAA;;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,cAAA","file":"chunk-56NJFD55.js","sourcesContent":["/**\n * Default design system documentation for the `get_design_system` MCP tool.\n *\n * This large string documents all available CSS variables, design tokens,\n * animation presets, elevation levels, and typography scales. It is served\n * to the LLM when no app-specific design context is configured.\n *\n * Any changes here must stay in sync with the design tokens, CSS\n * variables, and component APIs published by `@ggui-ai/design`\n * (`packages/design/`). A drift between this doc and the real design\n * system causes the LLM to emit styling that the renderer cannot\n * honor.\n */\n\n/** Default light-theme design system documentation served to the LLM. */\nexport const DEFAULT_DESIGN_SYSTEM_DOCS = `# Design System - Default Light Theme\n\n**IMPORTANT:** Always use CSS variables (var(--ggui-*)) for styling to ensure components respect the app theme.\n\n## Colors\n\n### Primary\n- var(--ggui-color-primary-50) - #f0f9ff\n- var(--ggui-color-primary-100) - #e0f2fe\n- var(--ggui-color-primary-200) - #bae6fd\n- var(--ggui-color-primary-300) - #7dd3fc\n- var(--ggui-color-primary-400) - #38bdf8\n- var(--ggui-color-primary-500) - #0ea5e9\n- var(--ggui-color-primary-600) - #0284c7 (main action FILL — buttons, borders, icon fills; accent TEXT takes the link role below)\n- var(--ggui-color-primary-700) - #0369a1\n- var(--ggui-color-primary-800) - #075985\n- var(--ggui-color-primary-900) - #0c4a6e\n\n### Semantic Surface & Text Colors (REQUIRED for theme compatibility)\nThese tokens adapt automatically to any theme (light, dark, branded). **ALWAYS use these for surfaces and text — never use raw neutral-* scale values.**\n\n| Token | CSS Variable | Default | Role |\n|-------|-------------|---------|------|\n| ground | var(--ggui-color-ground) | The page / canvas behind everything |\n| onGround | var(--ggui-color-onGround) | Text on the canvas |\n| container | var(--ggui-color-container) | A card, a bubble, a panel — the unit of content |\n| onContainer | var(--ggui-color-onContainer) | Body text on a card |\n| elevated | var(--ggui-color-elevated) | Menus, popovers, modals, toasts — floats above a card |\n| onElevated | var(--ggui-color-onElevated) | Text on an elevated surface |\n| heroGround | var(--ggui-color-heroGround) | A hero / greeting panel's ground — brand-tinted on a light host, the ink pair on a dark one (Card surface=\"hero\") |\n| onHeroGround | var(--ggui-color-onHeroGround) | Text on the hero ground |\n| sunken | var(--ggui-color-sunken) | Wells, inputs at rest, code blocks — recessed inside a card |\n| onSunken | var(--ggui-color-onSunken) | Muted / secondary text |\n| link | var(--ggui-color-link) | Accent TEXT — eyebrows, taglines, links, labels, inline arrows: the brand's readable ink, derived per mode to clear 4.5:1 on the container and the ground |\n| outline | var(--ggui-color-outline) | Borders, dividers |\n| outlineVariant | var(--ggui-color-outlineVariant) | Subtle borders |\n| controlOutline | var(--ggui-color-controlOutline) | A control's edge — clears 3:1 on its surface; kit controls draw it themselves |\n\n**Usage pattern:**\n- Page/section background → \\`var(--ggui-color-ground)\\`\n- Body text → \\`var(--ggui-color-onContainer)\\`\n- Card/panel background → \\`var(--ggui-color-container)\\`; recessed wells / inputs → \\`var(--ggui-color-sunken)\\`\n- Secondary/muted text → \\`var(--ggui-color-onSunken)\\`\n- Accent / branded text (eyebrow, tagline, link, label, inline arrow) → \\`var(--ggui-color-link)\\` or \\`<Text tone=\"emphasized\">\\` — never a bare \\`primary-<stop>\\` as a text color\n- Branded section/header → \\`var(--ggui-color-container)\\` bg + \\`var(--ggui-color-onContainer)\\` text\n- Borders/dividers → \\`var(--ggui-color-outline)\\` or \\`var(--ggui-color-outlineVariant)\\`\n\n### State Colors\nSemantic families ship as SCALES; the \\`500\\` stop is the role color (per-mode brightness), \\`50\\` the tint, \\`800\\` the on-tint text:\n- var(--ggui-color-success-500) — success states (tint bg: success-50, text on tint: success-800)\n- var(--ggui-color-warning-500) — warning states (warning-50 / warning-800)\n- var(--ggui-color-error-500) — error states, destructive actions (error-50 / error-800)\n- var(--ggui-color-info-500) — informational (info-50 / info-800)\nPrefer the primitives' \\`tone=\"success|warning|error|info\"\\` prop over hand-written vars — it resolves to the same stops.\n\n### IMPORTANT: Color Rules\n- **NEVER** use hardcoded hex colors. ONLY use var(--ggui-color-*) tokens.\n- **NEVER** use rgba(), hsl(), or other CSS color functions with hardcoded values.\n- **NEVER** use raw neutral-* or gray-* scale tokens (neutral-50, neutral-900, etc.) — these are internal to the theme and break in dark mode.\n- **ALWAYS** use semantic tokens for text and backgrounds:\n - Text: \\`var(--ggui-color-onContainer)\\` or \\`var(--ggui-color-onSunken)\\`\n - Backgrounds: \\`var(--ggui-color-container)\\` or \\`var(--ggui-color-sunken)\\`\n - Borders: \\`var(--ggui-color-outline)\\` or \\`var(--ggui-color-outlineVariant)\\`\n- For branded elements use \\`var(--ggui-color-primary-*)\\` scale tokens — these ARE safe because primary adapts per theme.\n- For card backgrounds use \\`var(--ggui-color-container)\\` or \\`var(--ggui-color-primary-50)\\`\n\n## Spacing\n\nUse \\`var(--ggui-spacing-N)\\` for all padding, gap, and margin values. **Never use raw numbers** like \\`padding={16}\\` — always use the token: \\`padding=\"var(--ggui-spacing-4)\"\\`.\n\n| Token | Value | Common use |\n|-------|-------|------------|\n| var(--ggui-spacing-1) | 4px | Icon gaps, tight spacing |\n| var(--ggui-spacing-2) | 8px | Button padding, small gaps |\n| var(--ggui-spacing-3) | 12px | List item spacing, form gaps |\n| var(--ggui-spacing-4) | 16px | Card padding, section gaps |\n| var(--ggui-spacing-5) | 20px | Medium padding |\n| var(--ggui-spacing-6) | 24px | Container padding, large gaps |\n| var(--ggui-spacing-8) | 32px | Section spacing |\n| var(--ggui-spacing-10) | 40px | Page margins |\n| var(--ggui-spacing-12) | 48px | Hero/large section spacing |\n\n**Quick lookup (px → token):** 4→1, 8→2, 12→3, 16→4, 20→5, 24→6, 28→7, 32→8, 36→9, 40→10, 48→12\n\n**Usage on primitives:**\n\\`\\`\\`tsx\n<Container padding=\"var(--ggui-spacing-6)\">\n <Stack gap=\"var(--ggui-spacing-4)\">\n <Card padding=\"var(--ggui-spacing-4)\">\n <Row gap=\"var(--ggui-spacing-2)\">...</Row>\n </Card>\n </Stack>\n</Container>\n\\`\\`\\`\n\n## Typography\n\n### Font Sizes\n- var(--ggui-font-size-xs) - 12px\n- var(--ggui-font-size-sm) - 14px\n- var(--ggui-font-size-base) - 16px\n- var(--ggui-font-size-lg) - 18px\n- var(--ggui-font-size-xl) - 20px\n- var(--ggui-font-size-2xl) - 24px\n- var(--ggui-font-size-3xl) - 30px\n- var(--ggui-font-size-4xl) - 36px\n\n### Font Weights\n- var(--ggui-font-weight-normal) - 400\n- var(--ggui-font-weight-medium) - 500\n- var(--ggui-font-weight-semibold) - 600\n- var(--ggui-font-weight-bold) - 700\n\n## Border Radius\n- var(--ggui-shape-radius-sm) - 4px\n- var(--ggui-shape-radius-md) - 8px\n- var(--ggui-shape-radius-lg) - 12px\n- var(--ggui-shape-radius-xl) - 16px\n- var(--ggui-shape-radius-full) - 9999px\n\n## Shadows\n- var(--ggui-shape-shadow-sm) - 0 1px 2px rgba(0,0,0,0.05)\n- var(--ggui-shape-shadow-md) - 0 4px 6px -1px rgba(0,0,0,0.1)\n- var(--ggui-shape-shadow-lg) - 0 10px 15px -3px rgba(0,0,0,0.1)\n- var(--ggui-shape-shadow-xl) - 0 20px 25px -5px rgba(0,0,0,0.1)\n\n## Usage Examples (always use ggui primitives — never raw <div>, <button>, <input>)\n\n### Branded section header\n\\`\\`\\`tsx\n<Box padding=\"var(--ggui-spacing-4)\" surface=\"accent\">\n <Heading level={2} tone=\"emphasized\">Contact Us</Heading>\n <Text tone=\"emphasized\">We'd love to hear from you</Text>\n</Box>\n\\`\\`\\`\n\n### Form input\n\\`\\`\\`tsx\n<Input label=\"Email\" placeholder=\"you@example.com\" />\n\\`\\`\\`\n\n### Buttons\n\\`\\`\\`tsx\n<Button variant=\"primary\">Submit</Button>\n<Button variant=\"outline\">Cancel</Button>\n<Button variant=\"ghost\">Skip</Button>\n\\`\\`\\`\n\n### Card with spacing tokens\n\\`\\`\\`tsx\n<Card padding=\"var(--ggui-spacing-4)\" shadow=\"md\">\n <Stack gap=\"var(--ggui-spacing-3)\">\n <Heading level={3}>Title</Heading>\n <Text tone=\"muted\">Description</Text>\n </Stack>\n</Card>\n\\`\\`\\`\n\n### Color usage guide\n- **Layering roles** (ground, container, elevated, sunken + their on* inks; outline): one kind of AREA each — use them for every background/text/border decision; they adapt to any theme\n- **primary-50/100**: Section backgrounds, highlight strips, card headers\n- **primary-200/300**: Dividers and section rules — never a control's border: kit controls draw their own edge (\\`controlOutline\\` / \\`controlAccentOutline\\`), so set no inline border on them\n- **primary-500/600**: Filled buttons, CTAs, badges, icon fills, active indicators — fills and borders, NOT a text color\n- **link**: Accent TEXT — eyebrows, taglines, links, labels, inline arrows; the brand's readable ink per mode (a bare \\`primary-300…600\\` as a text color fails tier-0: \\`universal.accent_text_ink\\`)\n- **primary-700/800/900**: Headings and text on light primary backgrounds\n- **neutral-***: Only when you need a specific shade that semantic tokens don't cover\n\nThe primary palette is the app's brand — use it throughout (headers, accents, borders, interactive elements), not just on the submit button.\n\n**Note:** Do NOT add fallback values to var() (e.g., var(--ggui-color-container, #fafafa)). Just use var(--ggui-color-container) — the theme provides all values.\n\n## Motion & Animation\n\n### Duration Scale\n- \\`instant\\`: 0ms\n- \\`fast\\`: 100ms\n- \\`normal\\`: 200ms\n- \\`slow\\`: 300ms\n- \\`slower\\`: 500ms\n\n### Easing Curves\n- \\`linear\\`: linear\n- \\`easeIn\\`: cubic-bezier(0.4, 0, 1, 1)\n- \\`easeOut\\`: cubic-bezier(0, 0, 0.2, 1)\n- \\`easeInOut\\`: cubic-bezier(0.4, 0, 0.2, 1)\n- \\`spring\\`: cubic-bezier(0.175, 0.885, 0.32, 1.275)\n\n### Transition Presets (import from '@ggui-ai/design/tokens')\n\\`\\`\\`tsx\nimport { duration, easing, transition } from '@ggui-ai/design/tokens';\n// transition.fast → \"100ms cubic-bezier(0.4, 0, 0.2, 1)\"\n// transition.normal → \"200ms cubic-bezier(0.4, 0, 0.2, 1)\"\n// transition.slow → \"300ms cubic-bezier(0.4, 0, 0.2, 1)\"\n// transition.colors → color + background-color + border-color (200ms each)\n// transition.opacity → opacity 200ms\n// transition.transform → transform 200ms\n\\`\\`\\`\n\n### Animation Keyframes\nUse \\`<MotionKeyframes />\\` once in your component to inject all keyframes, then reference by name.\n\n**Entrance / exit** (GPU-composited, transform + opacity):\n- \\`ggui-fadeIn\\` / \\`ggui-fadeOut\\`\n- \\`ggui-slideInUp\\` / \\`ggui-slideInDown\\`\n- \\`ggui-scaleIn\\` / \\`ggui-scaleOut\\`\n\n**State feedback** (color-based, for data-change highlights):\n- \\`ggui-flash\\` — background-color highlight that fades out. Set \\`--ggui-flash-color\\` on the element (default: \\`var(--ggui-color-primary-100)\\`)\n- \\`ggui-pulse\\` — gentle opacity breathing (infinite, for \"live\" indicators)\n- \\`ggui-bounce\\` — subtle scale overshoot (one-shot, for confirmations)\n\n\\`\\`\\`tsx\nimport { MotionKeyframes, useMotion, useAnimationKey } from '@ggui-ai/design';\nimport { animation } from '@ggui-ai/design/tokens';\n\nfunction MyComponent() {\n const { motionEnabled } = useMotion(); // respects prefers-reduced-motion\n return (\n <>\n <MotionKeyframes />\n {/* Entrance animation */}\n <div style={{ animation: motionEnabled ? animation.slideInUp : 'none' }}>\n Content slides in\n </div>\n </>\n );\n}\n\\`\\`\\`\n\n### Retriggering Animations on Data Changes\nWhen data updates (e.g., stock price from a stream), CSS animations don't replay automatically.\nUse \\`useAnimationKey(dep)\\` — returns a key that increments when \\`dep\\` changes, causing React to remount the element and replay the animation.\n\n\\`\\`\\`tsx\nimport { MotionKeyframes, useAnimationKey } from '@ggui-ai/design';\nimport { animation } from '@ggui-ai/design/tokens';\n\n// Flash a stock card green/red when the price changes\nconst priceKey = useAnimationKey(stock.price);\n<div\n key={priceKey}\n style={{\n animation: animation.flash,\n '--ggui-flash-color': stock.change > 0\n ? 'var(--ggui-color-success-100)'\n : 'var(--ggui-color-error-100)',\n } as React.CSSProperties}\n>\n {stock.price}\n</div>\n\\`\\`\\`\n\n## Chart / Data Visualization Colors\nSemantic chart tokens for data visualizations:\n- \\`var(--ggui-color-primary-600)\\` — primary series\n- \\`var(--ggui-color-success-500)\\` — positive / success\n- \\`var(--ggui-color-error-500)\\` — negative / error\n- \\`var(--ggui-color-warning-500)\\` — warning / caution\n- \\`var(--ggui-color-info-500)\\` — informational\n- \\`var(--ggui-color-neutral-400)\\` — neutral series\n- \\`var(--ggui-color-neutral-200)\\` — light background series\n- \\`var(--ggui-color-neutral-600)\\` — dark series\n\n## Accessibility Tokens\n\n### Focus Ring (for keyboard focus states)\n- Color: \\`var(--ggui-color-primary-600)\\`\n- Width: 2px\n- Offset: 2px\n- Style: solid\n\\`\\`\\`tsx\n// Apply to focusable elements:\noutline: '2px solid var(--ggui-color-primary-600)',\noutlineOffset: '2px',\n\\`\\`\\`\n\n### Reduced Motion\nUse \\`useMotion()\\` hook to check user preference. If disabled, set animation/transition to \\`none\\`.\n\n## Elevation System\nSemantic depth levels combining shadow + z-index:\n| Level | Shadow | Z-Index | Use For |\n|-------|--------|---------|---------|\n| 0 | none | 0 | Flat content |\n| 1 | sm | auto | Cards, slight lift |\n| 2 | md | 1000 | Dropdowns, popovers |\n| 3 | lg | 1200 | Banners, sticky bars |\n| 4 | xl | 1400 | Modals, dialogs |\n| 5 | 2xl | 1800 | Tooltips, toasts |\n\n\\`\\`\\`tsx\nimport { elevation } from '@ggui-ai/design/tokens';\n// elevation.level1 → { shadow: 'var(--ggui-shape-shadow-sm)', zIndex: 'auto' }\n// elevation.level2 → { shadow: 'var(--ggui-shape-shadow-md)', zIndex: 1000 }\n<div style={{ boxShadow: elevation.level1.shadow, zIndex: elevation.level1.zIndex }}>\n Card content\n</div>\n\\`\\`\\`\n\n## Typography Presets\n\n### Heading Styles (import { headingStyles } from '@ggui-ai/design/tokens')\n| Level | Size | Weight | Line Height | Letter Spacing |\n|-------|------|--------|-------------|----------------|\n| h1 | 36px | bold (700) | 1.25 | -0.025em |\n| h2 | 30px | bold (700) | 1.25 | -0.025em |\n| h3 | 24px | semibold (600) | 1.375 | 0 |\n| h4 | 20px | semibold (600) | 1.375 | 0 |\n| h5 | 18px | semibold (600) | 1.5 | 0 |\n| h6 | 16px | semibold (600) | 1.5 | 0 |\n\n### Text Sizing\n\\`<Text>\\` composes from \\`size\\` / \\`weight\\` / \\`tone\\` (+ \\`caps\\` for the\nuppercase eyebrow look) — there is no preset text-style table. Line\nheight derives from \\`size\\` automatically (1.5 for xs-base, 1.625 at lg,\ntighter on display sizes).\n\n### Letter Spacing Scale\n- \\`tighter\\`: -0.05em\n- \\`tight\\`: -0.025em\n- \\`normal\\`: 0\n- \\`wide\\`: 0.025em\n- \\`wider\\`: 0.05em\n- \\`widest\\`: 0.1em\n\n### Line Height Scale\n- \\`none\\`: 1\n- \\`tight\\`: 1.25\n- \\`snug\\`: 1.375\n- \\`normal\\`: 1.5\n- \\`relaxed\\`: 1.625\n- \\`loose\\`: 2`;\n"]}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// src/harness/llm-trace-sink.ts
|
|
2
|
+
var activeSink = null;
|
|
3
|
+
function setLlmTraceSink(sink) {
|
|
4
|
+
activeSink = sink;
|
|
5
|
+
}
|
|
6
|
+
function getLlmTraceSink() {
|
|
7
|
+
return activeSink;
|
|
8
|
+
}
|
|
9
|
+
function emitLlmTraceEvent(event) {
|
|
10
|
+
const sink = activeSink;
|
|
11
|
+
if (!sink) return;
|
|
12
|
+
try {
|
|
13
|
+
sink.emit(event);
|
|
14
|
+
} catch {
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
function summarizeTools(tools) {
|
|
18
|
+
return tools.map((t) => ({ name: t.name, description: t.description }));
|
|
19
|
+
}
|
|
20
|
+
function newLlmTraceId() {
|
|
21
|
+
return Date.now().toString(36) + Math.random().toString(36).slice(2, 10);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export { emitLlmTraceEvent, getLlmTraceSink, newLlmTraceId, setLlmTraceSink, summarizeTools };
|
|
25
|
+
//# sourceMappingURL=chunk-5AGTY555.js.map
|
|
26
|
+
//# sourceMappingURL=chunk-5AGTY555.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/harness/llm-trace-sink.ts"],"names":[],"mappings":";AA8GA,IAAI,UAAA,GAAkC,IAAA;AAM/B,SAAS,gBAAgB,IAAA,EAAiC;AAC/D,EAAA,UAAA,GAAa,IAAA;AACf;AAGO,SAAS,eAAA,GAAuC;AACrD,EAAA,OAAO,UAAA;AACT;AAOO,SAAS,kBAAkB,KAAA,EAA4B;AAC5D,EAAA,MAAM,IAAA,GAAO,UAAA;AACb,EAAA,IAAI,CAAC,IAAA,EAAM;AACX,EAAA,IAAI;AACF,IAAA,IAAA,CAAK,KAAK,KAAK,CAAA;AAAA,EACjB,CAAA,CAAA,MAAQ;AAAA,EAER;AACF;AAGO,SAAS,eACd,KAAA,EACwE;AACxE,EAAA,OAAO,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,MAAO,EAAE,IAAA,EAAM,CAAA,CAAE,IAAA,EAAM,WAAA,EAAa,CAAA,CAAE,WAAA,EAAY,CAAE,CAAA;AACxE;AAMO,SAAS,aAAA,GAAwB;AACtC,EAAA,OACE,IAAA,CAAK,GAAA,EAAI,CAAE,QAAA,CAAS,EAAE,CAAA,GACtB,IAAA,CAAK,MAAA,EAAO,CAAE,QAAA,CAAS,EAAE,CAAA,CAAE,KAAA,CAAM,GAAG,EAAE,CAAA;AAE1C","file":"chunk-5AGTY555.js","sourcesContent":["/**\n * Live LLM trace sink — devtools introspection of every LLM call the\n * generation harness makes.\n *\n * **Distinct from {@link TelemetrySink} and {@link AuditSink}.**\n * - **Telemetry** (mcp-server-core) = ops signals (`pair.completed`,\n * `render.duration_ms`). Sink may be lossy and drops on backpressure.\n * Attributes are flat scalars (`string | number | boolean`).\n * - **Audit** (mcp-server-core) = compliance log of privileged\n * mutations. Durable, async, may throw.\n * - **LLM trace** (this) = devtools-only, hostable in-memory ring\n * buffer of every LLM call's full payload (system prompt, user\n * prompt, tool defs, completion, token counts, cache hits, error).\n * Lossy by default. A hosted closed runtime may swap in a durable\n * sink for internal debugging; OSS ships an in-memory sink the\n * `/devtools/llm-trace` page reads.\n *\n * **Why module-level registry instead of constructor injection.** The\n * harness constructs LLM agents on every generation via\n * {@link createAgent}. Threading a sink through every call site\n * (createAgent → run-coding-turn → llm-evaluator → file-agent → …)\n * touches ~5 packages for a devtools-only surface. The OSS ggui server\n * is a single process per CLI invocation — global state has no\n * confusion-cost there. A hosted deployment isolates per request via a\n * process pool, so a global per-pool is also safe. If we ever serve\n * several apps inside one process we'll thread it then.\n *\n * **Default = no sink.** When unset, the router emits nothing and\n * spends no CPU formatting events. Passing `null` removes a previously\n * registered sink.\n */\nimport type { LLMToolDef } from '../llm.js';\n\n/** Provider tag that produced the call. Mirrors {@link AgentConfig.provider}. */\n/**\n * `claude-code-login` is the Anthropic model reached through the machine's\n * own Claude Code login (ggui#1185) rather than a key — a trace reader can\n * tell the two apart, which the routing vocabulary (`provider: 'anthropic'`)\n * deliberately does not.\n */\nexport type LlmTraceProvider = 'anthropic' | 'claude-code-login' | 'openai' | 'google' | 'openrouter';\n\n/** Which `LLMAgent` method initiated the call. */\nexport type LlmTraceKind =\n | 'callText'\n | 'callTools'\n | 'callWithTools'\n | 'callStructured'\n | 'callVision';\n\n/**\n * One LLM call. Emitted **after** the call completes (success or error)\n * — single event, not start/end split. Devtools UI is timeline-friendly\n * because each event carries `at` (start) + `endedAt` (end).\n */\nexport interface LlmTraceEvent {\n /** Random per-event ID. */\n readonly id: string;\n /** Epoch ms when the call was issued. */\n readonly at: number;\n /** Epoch ms when the call completed (success or error). */\n readonly endedAt: number;\n /** `endedAt - at` — convenience. */\n readonly durationMs: number;\n readonly provider: LlmTraceProvider;\n readonly model: string;\n readonly kind: LlmTraceKind;\n readonly systemPrompt?: string;\n readonly userPrompt?: string;\n /**\n * Tool defs sent on the call (if any). Stripped to `name + description`\n * — full JSON schema would balloon the trace and is rarely useful in\n * the operator UI.\n */\n readonly tools?: ReadonlyArray<{\n readonly name: string;\n readonly description: string;\n }>;\n /** Set on successful completion. */\n readonly result?: {\n readonly inputTokens: number;\n readonly outputTokens: number;\n /** Anthropic only. Bytes counted toward the cache write. */\n readonly cacheCreated?: number;\n /** Anthropic only. Bytes served from cache (90% discounted). */\n readonly cacheRead?: number;\n /** Set when the call returned text content. */\n readonly text?: string;\n /** Set when the call returned tool_use blocks. */\n readonly toolCalls?: ReadonlyArray<{\n readonly name: string;\n readonly input: unknown;\n }>;\n /** Set for `callWithTools` — number of agentic turns consumed. */\n readonly turnsUsed?: number;\n };\n /** Set on failure. `result` is undefined. */\n readonly error?: { readonly message: string };\n}\n\n/**\n * Sink that receives one event per LLM call. Implementations MUST be\n * sync + non-throwing — the harness fires events on the hot path and\n * cannot tolerate backpressure or rejected promises. Buffer + drop or\n * fan out to a queue inside the implementation.\n */\nexport interface LlmTraceSink {\n emit(event: LlmTraceEvent): void;\n}\n\nlet activeSink: LlmTraceSink | null = null;\n\n/**\n * Register the active sink. Pass `null` to remove. Subsequent\n * {@link emitLlmTraceEvent} calls dispatch to this sink.\n */\nexport function setLlmTraceSink(sink: LlmTraceSink | null): void {\n activeSink = sink;\n}\n\n/** Read the active sink. Mostly for tests. */\nexport function getLlmTraceSink(): LlmTraceSink | null {\n return activeSink;\n}\n\n/**\n * Internal — used by `LLMAgent` adapters. No-op when no sink is\n * registered. Swallows sink-thrown errors (a broken devtools sink must\n * not break generation).\n */\nexport function emitLlmTraceEvent(event: LlmTraceEvent): void {\n const sink = activeSink;\n if (!sink) return;\n try {\n sink.emit(event);\n } catch {\n // Devtools sink is allowed to be buggy — generation must not die.\n }\n}\n\n/** Strip `LLMToolDef[]` to the trace-friendly subset. */\nexport function summarizeTools(\n tools: ReadonlyArray<LLMToolDef>,\n): ReadonlyArray<{ readonly name: string; readonly description: string }> {\n return tools.map((t) => ({ name: t.name, description: t.description }));\n}\n\n/**\n * Crockford-style random ID. Crypto.randomUUID() would do, but we want\n * to keep this dep-free for non-Node runtimes the harness might run in.\n */\nexport function newLlmTraceId(): string {\n return (\n Date.now().toString(36) +\n Math.random().toString(36).slice(2, 10)\n );\n}\n"]}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { DEFAULT_DESIGN_SYSTEM_DOCS } from './chunk-56NJFD55.js';
|
|
2
|
+
import { PRIMITIVES_DOCUMENTATION } from './chunk-HD6ABIK7.js';
|
|
3
|
+
import { buildSystemPrompt } from './chunk-FB7OEEAH.js';
|
|
4
|
+
|
|
5
|
+
// src/tools/get-wire.ts
|
|
6
|
+
var WIRE_DOCUMENTATION = "# ggui Wire Hooks Reference\n\n> Wire hooks connect generated UI components to agent communication.\n> They are pre-imported in the boilerplate \u2014 use them directly.\n> All hooks must be called inside a GguiWireProvider (handled automatically by the renderer).\n\nImport: `import { useAction, useStream } from '@ggui-ai/wire'`\n\n## Communication Hooks\n\n\n\nThese are the wire primitives for component-agent communication. `useWiredTool` retired 2026-05-11 \u2014 agentCapabilities.tools is a catalog the AGENT invokes, not a component hook surface; user gestures use `useAction(name)` and the optional `nextStep` field on the action entry names the tool the agent SHOULD invoke next.\n\n### useAction\n\nFire an action to the agent. Fire-and-forget \u2014 no response, no pending state.\n\nEvery action is an event: it lands on the GguiSession's consume buffer and\nthe agent receives it on its next turn (via `ggui_consume`). The action\nentry's optional `nextStep` names the tool the agent SHOULD invoke in\nresponse \u2014 advisory only; the agent owns the call decision. Component code\nis identical either way: call `useAction(name)(payload)` and treat\n`nextStep` as informational (use it to inform button labels, icons, copy).\n\nRUNTIME DEDUP (backstop, not a feature). Same-`(name, payload)` calls within\none event-loop task are coalesced \u2014 the first wins, subsequent duplicates\nare suppressed. This is the structural defense against LLM-generated\nnested-interactive components where a Checkbox `onChange` and an outer\n`Card as={Clickable}` `onClick` both wire to the same `useAction` binding;\nthe inner gesture bubbles to the outer handler, so without dedup one user\nclick would fire the action twice (a toggle would run back-to-back and the\nuser's change would disappear). **Do not rely on this as a feature** \u2014 wire\neach `useAction` callback to exactly ONE interactive surface; the dedup\nexists only because the LLM's source code can be wrong in subtle ways and\nthe runtime is the only place that can see the actual event-bubble path.\nSee `dispatch-dedup.ts` for the full failure-mode rationale.\n\nNEVER SILENT. When the dedup fires, a `console.warn` is emitted in BOTH dev\nand prod with the full diagnostic. The suppression is always visible in\nbrowser DevTools; operators investigating a \"the second click does nothing\"\nreport see the warning immediately. A structured observer also exists as\n`WireConfig.onDispatchSuppressed`, but the first-party renderers never set\nit \u2014 it is reachable only from a hand-built `WireConfig` (see its\ndocstring), so the console signal is what operators get in practice.\n\n**Signature:** `useAction<T = unknown>(actionName: string): (data: T) => void`\n\n**Parameters:**\n\n| Param | Type | Description |\n|-------|------|-------------|\n| actionName | `string` | Action name from the action contract |\n\n**Returns:** `(data: T) => void`\n\n**Example:**\n```tsx\nconst submitForm = useAction<{name: string; email: string}>('formSubmit');\n\n// In JSX:\n<Button onClick={() => submitForm({ name, email })}>Submit</Button>\n```\n\n\n### useActionSpent\n\nWhether the card's `oneShot` action `actionName` is already spent, so a\ncomponent can paint its control as submitted on the first paint, with no\npress needed to find out.\n\n`true` iff the contract declares `actionName` `oneShot` and the card already\nfired it, either in this render or before a reload (the record the host\nre-serves). It is reactive, flipping to `true` when this card's own dispatch\ncommits. It returns data only: how a spent control looks (disabled,\n\"Submitted\", hidden) is the component's choice. Outside a runtime that\nprovides spent state, it is `false` and the dispatch guard still holds.\n\n**Signature:** `useActionSpent(actionName: string): boolean`\n\n**Parameters:**\n\n| Param | Type | Description |\n|-------|------|-------------|\n| actionName | `string` | actionName |\n\n**Returns:** `boolean`\n\n**Example:**\n```tsx\nconst confirm = useAction<ActionConfirmPayload>('confirm');\nconst spent = useActionSpent('confirm');\n\n// In JSX \u2014 the control paints spent on the first paint after a reload, with no press:\n<Button variant=\"primary\" disabled={spent} onClick={() => confirm({ bookingId })}>\n {spent ? 'Confirmed' : 'Confirm booking'}\n</Button>\n```\n\n\n### useActionPending\n\nWhether this card's action `actionName` was dispatched and is still waiting\nfor the agent's answer, so the control can show it is working (disabled,\n`aria-busy`, \"Sending\u2026\") instead of looking untouched while the agent\nreacts.\n\n`true` from the committed dispatch until the session's next frame lands, or\nthe bound elapses. It is reactive. It returns data only: how a pending\ncontrol looks is the component's choice. Outside a runtime that provides\npending state, it is `false`.\n\n**Signature:** `useActionPending(actionName: string): boolean`\n\n**Parameters:**\n\n| Param | Type | Description |\n|-------|------|-------------|\n| actionName | `string` | actionName |\n\n**Returns:** `boolean`\n\n**Example:**\n```tsx\nconst send = useAction<ActionSendPayload>('send');\nconst sending = useActionPending('send');\n\n// In JSX \u2014 the control shows it is working until the agent's answer repaints the card:\n<Button variant=\"primary\" disabled={sending} aria-busy={sending} onClick={() => send({ text })}>\n {sending ? 'Sending\u2026' : 'Send'}\n</Button>\n```\n\n\n### useStream\n\nSubscribe to deliveries on a named stream channel.\n\nHonors the channel's per-delivery `mode` ('append' vs 'replace')\nand the optional `complete` terminal marker. Channels declared\n`mode: 'replace'` on the spec typically emit every delivery with\n`mode: 'replace'` \u2014 this hook folds them into a single-latest\nvalue without accumulating history.\n\n**Signature:** `useStream<T = unknown>(channelName: string): StreamResult<T>`\n\n**Parameters:**\n\n| Param | Type | Description |\n|-------|------|-------------|\n| channelName | `string` | Channel name from the GguiSession's streamSpec |\n\n**Returns:** `StreamResult<T>`\n\n| Property | Type | Description |\n|----------|------|-------------|\n| latest | `T \\| null` | Most recent payload delivered on this channel, or null if none received yet. |\n| all | `T[]` | All payloads accumulated on this channel. - `mode: 'append'` deliveries are pushed to the tail (continuous stream). - `mode: 'replace'` deliveries collapse `all` to a single-element array containing the latest payload \u2014 matching the channel's \"full replacement\" semantics. |\n| isComplete | `boolean` | Truthy after the channel has delivered an envelope with `complete: true`. Subscribers flip into a \"channel closed\" rendering state based on this signal; further deliveries on a completed channel are still accumulated, since the underlying wire doesn't enforce quiescence. |\n\n**Example:**\n```tsx\nconst progress = useStream<{ percent: number; message: string }>('progress');\n\n// In JSX:\n{progress.latest && (\n <Progress value={progress.latest.percent} />\n)}\n<Text>{progress.all.length} updates received</Text>\n```\n\n\n## Context Hooks\n\n\n\nRead-only access to render, app, and auth context.\n\n### useAuth\n\nRead-only auth context. Token excluded \u2014 auth is added server-side.\n\n**Signature:** `useAuth(): AuthInfo`\n\n**Returns:** `AuthInfo`\n\n| Property | Type | Description |\n|----------|------|-------------|\n| userId | `string` | userId |\n| isAuthenticated | `boolean` | isAuthenticated |\n\n**Example:**\n```tsx\nconst auth = useAuth();\n\n// In JSX:\n{auth.isAuthenticated\n ? <Text>Welcome, user {auth.userId}</Text>\n : <Text>Please sign in</Text>\n}\n```\n\n\n### useApp\n\nRead-only app metadata.\n\n**Signature:** `useApp(): AppInfo`\n\n**Returns:** `AppInfo`\n\n| Property | Type | Description |\n|----------|------|-------------|\n| appId | `string` | appId |\n| appName | `string` | appName |\n| appDescription | `string` | appDescription |\n| appIcon | `string` | appIcon |\n\n**Example:**\n```tsx\nconst app = useApp();\n\n// In JSX:\n<Heading>{app.appName}</Heading>\n{app.appDescription && <Text>{app.appDescription}</Text>}\n```\n\n\n### useRender\n\nRead-only render context with connection status.\n\n**Signature:** `useRender(): GguiSessionInfo`\n\n**Returns:** `GguiSessionInfo`\n\n| Property | Type | Description |\n|----------|------|-------------|\n| sessionId | `string` | sessionId |\n| isConnected | `boolean` | isConnected |\n\n**Example:**\n```tsx\nconst render = useRender();\n\n// In JSX:\n<Badge variant={render.isConnected ? 'success' : 'error'}>\n {render.isConnected ? 'Connected' : 'Disconnected'}\n</Badge>\n```\n\n\n## Provider\n\n\n\nThe provider is set up automatically by the renderer. Generated components do not need to wrap themselves in a provider.\n\n### GguiWireProvider\n\nReact context provider that injects WireConfig for all wire hooks.\n\n**Props:**\n\n| Prop | Type | Description |\n|------|------|-------------|\n| config | `WireConfig` | config |\n| children | `ReactNode` | children |\n\n**Example:**\n```tsx\n<GguiWireProvider config={wireConfig}>\n <YourComponent />\n</GguiWireProvider>\n```\n\n\n## Internal: WireConfig\n\n\n\nThis is the configuration object passed to GguiWireProvider. Generated components do not interact with this directly \u2014 it is provided by the renderer.\n\n### WireConfig\n\nConfiguration injected by the provider \u2014 the renderer inside the\niframe.\n\nEvery method is typed against the contract generic `T` so typed\ncallers get compile-time enforcement:\n - `dispatch(name, data)` \u2014 `name` MUST be a declared actionSpec\n key; `data` MUST satisfy that action's schema.\n - `subscribe(channel, handler)` \u2014 same discipline for streamSpec.\n\nUntyped callers (`T = DataContract` default) degrade to the broad\nshape via the conditional `WireDispatchData` / `WireStreamPayload`\naliases \u2014 no call-site break.\n\nThe contract's `agentCapabilities.tools` catalog declares tools the AGENT\ninvokes (not the component); user gestures fire via\n`dispatch(name, data)` and the optional `nextStep` field on the\naction entry names the tool the agent SHOULD invoke next.\n\nThe renderer mounts exactly ONE GguiSession per iframe \u2014 `render.sessionId`\nis the stable identity the WireProvider was constructed with. No\nper-item scoping factory; with a one-GguiSession-per-mount lifecycle,\n\"scope\" collapses to identity.\n\n| Property | Type | Description |\n|----------|------|-------------|\n| app | `{ readonly appId: string; readonly appName: string; readonly appDescription?: string; readonly appIcon?: string; }` | app |\n| render | `{ readonly sessionId: string; readonly isConnected: boolean; }` | render |\n| auth | `{ readonly userId?: string; readonly isAuthenticated: boolean; }` | auth |\n| dispatch | `<N extends string>( actionName: N, data: WireDispatchData<T, N>, ) => void` | Fire an action to the agent (fire-and-forget over WS). Typed callers get compile-time checked `name` + `data`; untyped callers (`T = DataContract`) keep the broad shape. |\n| subscribe | `<N extends string>( channelName: N, handler: (delivery: StreamDelivery<WireStreamPayload<T, N>>) => void, ) => () => void` | Subscribe to deliveries on a named stream channel. |\n| onDispatchSuppressed | `(info: DispatchSuppressedInfo) => void` | Optional structured observability for the runtime's two dispatch- suppression invariants \u2014 the task-scoped duplicate backstop (`reason: 'duplicate-dispatch'`, fired by `useAction`) and the render-lifetime one-shot guard (`reason: 'one-shot-spent'`, fired by the config's own `dispatch` when a declared `oneShot` action is gestured a second time, ggui#1108). Both fire ALONGSIDE the always-on `console.warn`; neither reaches the agent. Reachability constraint: the first-party renderers do NOT set this field \u2014 `buildRootWireConfig` (`@ggui-ai/iframe-runtime`) and `<GguiRender>`'s internal config both omit it. It fires only when a host hand-builds a complete `WireConfig` (or passes `onDispatchSuppressed` to `buildWireConfig`). On every first-party render path the `console.warn` is the sole suppression signal \u2014 which is what the `oneShot` contract requires as its minimum trace. |\n";
|
|
7
|
+
|
|
8
|
+
// src/harness/pitfalls.ts
|
|
9
|
+
var PITFALLS = [
|
|
10
|
+
{
|
|
11
|
+
id: "stack-row-padding",
|
|
12
|
+
rule: '`Stack`/`Row` do NOT accept `padding` \u2014 wrap the children in `<Box padding="...">`.',
|
|
13
|
+
why: "Stack and Row are flex containers; padding would violate the gap-based spacing model.",
|
|
14
|
+
foundIn: "pre-#61 baseline"
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
id: "align-enum",
|
|
18
|
+
rule: "`align` accepts only `'start' | 'center' | 'end' | 'stretch'` (NEVER `flex-end`/`flex-start`).",
|
|
19
|
+
why: "Components use semantic enums, not raw CSS flex values.",
|
|
20
|
+
foundIn: "pre-#61 baseline"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
id: "justify-enum",
|
|
24
|
+
rule: "`justify` accepts only `'start' | 'center' | 'end' | 'between' | 'around' | 'evenly'`.",
|
|
25
|
+
why: "Semantic enum, not raw CSS flex values.",
|
|
26
|
+
foundIn: "pre-#61 baseline"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
id: "badge-variant",
|
|
30
|
+
rule: "`Badge variant` accepts `'default' | 'primary' | 'secondary' | 'success' | 'warning' | 'error' | 'info'`.",
|
|
31
|
+
why: "Badge has a fixed enum \u2014 LLMs sometimes invent variants like 'danger' or 'red'.",
|
|
32
|
+
foundIn: "pre-#61 baseline"
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
id: "imports-preimported",
|
|
36
|
+
rule: "All design-system primitives are pre-imported by the boilerplate \u2014 do NOT add imports unless absolutely needed.",
|
|
37
|
+
why: "Duplicate imports cause TS errors; the boilerplate already resolves the full primitive surface.",
|
|
38
|
+
foundIn: "pre-#61 baseline"
|
|
39
|
+
}
|
|
40
|
+
// ─── stepper-display-only: retired to the CHECK leg (Exp 47 P2) ─────────
|
|
41
|
+
//
|
|
42
|
+
// The 6th always-on pitfall ("Stepper is display-only…") was added with
|
|
43
|
+
// the #306 roster wave, but D8 measured Stepper adoption at 17/18 from
|
|
44
|
+
// fragment + JSDoc alone — the always-on rule was demonstrably not
|
|
45
|
+
// load-bearing, and exp66's factorial showed pitfall COUNT (5→6+) is
|
|
46
|
+
// the dilution-sensitive lever (~+9s blended). Its guidance now ships
|
|
47
|
+
// as the fix string of the `layout.multi_step.stepper_adopted` axis
|
|
48
|
+
// check (evaluation/axis-checks/extras.ts) — delivered only to the
|
|
49
|
+
// multi-step cells that actually violate it.
|
|
50
|
+
//
|
|
51
|
+
// ─── Provisional pitfalls considered + retired by exp66 n=6 factorial ───
|
|
52
|
+
//
|
|
53
|
+
// The 3 "new" pitfalls below were added in exp61 after OpenAI kanban
|
|
54
|
+
// error mining: useState typing, stream null-guard promotion, null-vs-
|
|
55
|
+
// undefined. Individual smokes suggested they helped, but the rigorous
|
|
56
|
+
// exp66 factorial (n=6, 3×2 pitfalls × batch-fix) showed they REGRESS
|
|
57
|
+
// blended ms by +8.8s (legacy5 29.3s → full8 38.1s, batch-off).
|
|
58
|
+
//
|
|
59
|
+
// Mechanism: attention dilution. Each added rule shifts LLM attention
|
|
60
|
+
// away from the 5 legacy pitfalls that catch the real error classes.
|
|
61
|
+
// Plus, "ALWAYS type useState" is too categorical — LLMs over-annotate
|
|
62
|
+
// in contexts that didn't need it.
|
|
63
|
+
//
|
|
64
|
+
// Retired from default. Kept as dormant comments so the next person
|
|
65
|
+
// investigating the same error classes knows this path was tried.
|
|
66
|
+
//
|
|
67
|
+
// usestate-type-annotation: "ALWAYS type useState: useState<T[]>([])..."
|
|
68
|
+
// stream-latest-null-guard: "useStream().latest is T|null — always null-guard..."
|
|
69
|
+
// null-vs-undefined: "Use undefined for optional props, not null..."
|
|
70
|
+
//
|
|
71
|
+
// If a future bench mines a new provider/fixture combination that
|
|
72
|
+
// reliably violates one of these, revisit with a targeted profile,
|
|
73
|
+
// not a global rule.
|
|
74
|
+
];
|
|
75
|
+
function renderPitfallsBlock() {
|
|
76
|
+
const disableAll = typeof process !== "undefined" && process.env?.GGUI_PITFALLS === "off";
|
|
77
|
+
if (disableAll) return "";
|
|
78
|
+
const disableNew = typeof process !== "undefined" && process.env?.GGUI_NEW_PITFALLS === "off";
|
|
79
|
+
const LEGACY_IDS = /* @__PURE__ */ new Set([
|
|
80
|
+
// Pre-exp61: original Common Pitfalls (5 rules)
|
|
81
|
+
"stack-row-padding",
|
|
82
|
+
"align-enum",
|
|
83
|
+
"justify-enum",
|
|
84
|
+
"badge-variant",
|
|
85
|
+
"imports-preimported"
|
|
86
|
+
]);
|
|
87
|
+
const entries = [...PITFALLS].filter((p) => !disableNew || LEGACY_IDS.has(p.id)).sort((a, b) => a.id.localeCompare(b.id));
|
|
88
|
+
const bullets = entries.map((p) => `- ${p.rule}`).join("\n");
|
|
89
|
+
return `## Common Pitfalls (each costs an iteration \u2014 avoid them up front)
|
|
90
|
+
${bullets}`;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// src/harness/runtime.ts
|
|
94
|
+
function buildSystemPrompt2(userRequest, shellType, screen, axisDelta, appGadgets, gadgetTypes, designMode, canvas, profile) {
|
|
95
|
+
return buildSystemPrompt({
|
|
96
|
+
userRequest,
|
|
97
|
+
shellType,
|
|
98
|
+
screen,
|
|
99
|
+
axisDelta,
|
|
100
|
+
pitfallsBlock: renderPitfallsBlock(),
|
|
101
|
+
designSystemDocs: DEFAULT_DESIGN_SYSTEM_DOCS,
|
|
102
|
+
primitivesDoc: PRIMITIVES_DOCUMENTATION,
|
|
103
|
+
wireDoc: WIRE_DOCUMENTATION,
|
|
104
|
+
appGadgets,
|
|
105
|
+
gadgetTypes,
|
|
106
|
+
designMode,
|
|
107
|
+
canvas,
|
|
108
|
+
profile
|
|
109
|
+
// criteriaBlock left undefined — ui-gen fills default from open CRITERIA.
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export { buildSystemPrompt2 as buildSystemPrompt };
|
|
114
|
+
//# sourceMappingURL=chunk-5EJM7EGY.js.map
|
|
115
|
+
//# sourceMappingURL=chunk-5EJM7EGY.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/tools/get-wire.ts","../src/harness/pitfalls.ts","../src/harness/runtime.ts"],"names":["buildSystemPrompt"],"mappings":";;;;;AAIO,IAAM,kBAAA,GAAqB,+jYAAA;;;AC4B3B,IAAM,QAAA,GAA+B;AAAA,EAC1C;AAAA,IACE,EAAA,EAAI,mBAAA;AAAA,IACJ,IAAA,EAAM,0FAAA;AAAA,IACN,GAAA,EAAK,uFAAA;AAAA,IACL,OAAA,EAAS;AAAA,GACX;AAAA,EACA;AAAA,IACE,EAAA,EAAI,YAAA;AAAA,IACJ,IAAA,EAAM,gGAAA;AAAA,IACN,GAAA,EAAK,yDAAA;AAAA,IACL,OAAA,EAAS;AAAA,GACX;AAAA,EACA;AAAA,IACE,EAAA,EAAI,cAAA;AAAA,IACJ,IAAA,EAAM,wFAAA;AAAA,IACN,GAAA,EAAK,yCAAA;AAAA,IACL,OAAA,EAAS;AAAA,GACX;AAAA,EACA;AAAA,IACE,EAAA,EAAI,eAAA;AAAA,IACJ,IAAA,EAAM,2GAAA;AAAA,IACN,GAAA,EAAK,sFAAA;AAAA,IACL,OAAA,EAAS;AAAA,GACX;AAAA,EACA;AAAA,IACE,EAAA,EAAI,qBAAA;AAAA,IACJ,IAAA,EAAM,sHAAA;AAAA,IACN,GAAA,EAAK,iGAAA;AAAA,IACL,OAAA,EAAS;AAAA;AACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAmCF,CAAA;AAOO,SAAS,mBAAA,GAA8B;AAQ5C,EAAA,MAAM,aACJ,OAAO,OAAA,KAAY,WAAA,IAAe,OAAA,CAAQ,KAAK,aAAA,KAAkB,KAAA;AACnE,EAAA,IAAI,YAAY,OAAO,EAAA;AACvB,EAAA,MAAM,aAAa,OAAO,OAAA,KAAY,WAAA,IAAe,OAAA,CAAQ,KAAK,iBAAA,KAAsB,KAAA;AACxF,EAAA,MAAM,UAAA,uBAAiB,GAAA,CAAI;AAAA;AAAA,IAEzB,mBAAA;AAAA,IACA,YAAA;AAAA,IACA,cAAA;AAAA,IACA,eAAA;AAAA,IACA;AAAA,GACD,CAAA;AACD,EAAA,MAAM,OAAA,GAAU,CAAC,GAAG,QAAQ,CAAA,CACzB,OAAO,CAAC,CAAA,KAAM,CAAC,UAAA,IAAc,UAAA,CAAW,GAAA,CAAI,EAAE,EAAE,CAAC,CAAA,CACjD,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,CAAA,CAAE,EAAA,CAAG,aAAA,CAAc,CAAA,CAAE,EAAE,CAAC,CAAA;AAC1C,EAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,EAAA,EAAK,CAAA,CAAE,IAAI,CAAA,CAAE,CAAA,CAAE,IAAA,CAAK,IAAI,CAAA;AAC3D,EAAA,OAAO,CAAA;AAAA,EAAuE,OAAO,CAAA,CAAA;AACvF;;;AC4CO,SAASA,kBAAAA,CACd,aACA,SAAA,EACA,MAAA,EACA,WACA,UAAA,EAQA,WAAA,EAMA,UAAA,EAEA,MAAA,EAEA,OAAA,EACQ;AACR,EAAA,OAAO,iBAAA,CAA0B;AAAA,IAC/B,WAAA;AAAA,IACA,SAAA;AAAA,IACA,MAAA;AAAA,IACA,SAAA;AAAA,IACA,eAAe,mBAAA,EAAoB;AAAA,IACnC,gBAAA,EAAkB,0BAAA;AAAA,IAClB,aAAA,EAAe,wBAAA;AAAA,IACf,OAAA,EAAS,kBAAA;AAAA,IACT,UAAA;AAAA,IACA,WAAA;AAAA,IACA,UAAA;AAAA,IACA,MAAA;AAAA,IACA;AAAA;AAAA,GAED,CAAA;AACH","file":"chunk-5EJM7EGY.js","sourcesContent":["/**\n * AUTO-GENERATED from @ggui-ai/wire JSDoc.\n * Do not edit manually. Run: pnpm --filter @ggui-ai/wire generate:docs\n */\nexport const WIRE_DOCUMENTATION = \"# ggui Wire Hooks Reference\\n\\n> Wire hooks connect generated UI components to agent communication.\\n> They are pre-imported in the boilerplate — use them directly.\\n> All hooks must be called inside a GguiWireProvider (handled automatically by the renderer).\\n\\nImport: `import { useAction, useStream } from '@ggui-ai/wire'`\\n\\n## Communication Hooks\\n\\n\\n\\nThese are the wire primitives for component-agent communication. `useWiredTool` retired 2026-05-11 — agentCapabilities.tools is a catalog the AGENT invokes, not a component hook surface; user gestures use `useAction(name)` and the optional `nextStep` field on the action entry names the tool the agent SHOULD invoke next.\\n\\n### useAction\\n\\nFire an action to the agent. Fire-and-forget — no response, no pending state.\\n\\nEvery action is an event: it lands on the GguiSession's consume buffer and\\nthe agent receives it on its next turn (via `ggui_consume`). The action\\nentry's optional `nextStep` names the tool the agent SHOULD invoke in\\nresponse — advisory only; the agent owns the call decision. Component code\\nis identical either way: call `useAction(name)(payload)` and treat\\n`nextStep` as informational (use it to inform button labels, icons, copy).\\n\\nRUNTIME DEDUP (backstop, not a feature). Same-`(name, payload)` calls within\\none event-loop task are coalesced — the first wins, subsequent duplicates\\nare suppressed. This is the structural defense against LLM-generated\\nnested-interactive components where a Checkbox `onChange` and an outer\\n`Card as={Clickable}` `onClick` both wire to the same `useAction` binding;\\nthe inner gesture bubbles to the outer handler, so without dedup one user\\nclick would fire the action twice (a toggle would run back-to-back and the\\nuser's change would disappear). **Do not rely on this as a feature** — wire\\neach `useAction` callback to exactly ONE interactive surface; the dedup\\nexists only because the LLM's source code can be wrong in subtle ways and\\nthe runtime is the only place that can see the actual event-bubble path.\\nSee `dispatch-dedup.ts` for the full failure-mode rationale.\\n\\nNEVER SILENT. When the dedup fires, a `console.warn` is emitted in BOTH dev\\nand prod with the full diagnostic. The suppression is always visible in\\nbrowser DevTools; operators investigating a \\\"the second click does nothing\\\"\\nreport see the warning immediately. A structured observer also exists as\\n`WireConfig.onDispatchSuppressed`, but the first-party renderers never set\\nit — it is reachable only from a hand-built `WireConfig` (see its\\ndocstring), so the console signal is what operators get in practice.\\n\\n**Signature:** `useAction<T = unknown>(actionName: string): (data: T) => void`\\n\\n**Parameters:**\\n\\n| Param | Type | Description |\\n|-------|------|-------------|\\n| actionName | `string` | Action name from the action contract |\\n\\n**Returns:** `(data: T) => void`\\n\\n**Example:**\\n```tsx\\nconst submitForm = useAction<{name: string; email: string}>('formSubmit');\\n\\n// In JSX:\\n<Button onClick={() => submitForm({ name, email })}>Submit</Button>\\n```\\n\\n\\n### useActionSpent\\n\\nWhether the card's `oneShot` action `actionName` is already spent, so a\\ncomponent can paint its control as submitted on the first paint, with no\\npress needed to find out.\\n\\n`true` iff the contract declares `actionName` `oneShot` and the card already\\nfired it, either in this render or before a reload (the record the host\\nre-serves). It is reactive, flipping to `true` when this card's own dispatch\\ncommits. It returns data only: how a spent control looks (disabled,\\n\\\"Submitted\\\", hidden) is the component's choice. Outside a runtime that\\nprovides spent state, it is `false` and the dispatch guard still holds.\\n\\n**Signature:** `useActionSpent(actionName: string): boolean`\\n\\n**Parameters:**\\n\\n| Param | Type | Description |\\n|-------|------|-------------|\\n| actionName | `string` | actionName |\\n\\n**Returns:** `boolean`\\n\\n**Example:**\\n```tsx\\nconst confirm = useAction<ActionConfirmPayload>('confirm');\\nconst spent = useActionSpent('confirm');\\n\\n// In JSX — the control paints spent on the first paint after a reload, with no press:\\n<Button variant=\\\"primary\\\" disabled={spent} onClick={() => confirm({ bookingId })}>\\n {spent ? 'Confirmed' : 'Confirm booking'}\\n</Button>\\n```\\n\\n\\n### useActionPending\\n\\nWhether this card's action `actionName` was dispatched and is still waiting\\nfor the agent's answer, so the control can show it is working (disabled,\\n`aria-busy`, \\\"Sending…\\\") instead of looking untouched while the agent\\nreacts.\\n\\n`true` from the committed dispatch until the session's next frame lands, or\\nthe bound elapses. It is reactive. It returns data only: how a pending\\ncontrol looks is the component's choice. Outside a runtime that provides\\npending state, it is `false`.\\n\\n**Signature:** `useActionPending(actionName: string): boolean`\\n\\n**Parameters:**\\n\\n| Param | Type | Description |\\n|-------|------|-------------|\\n| actionName | `string` | actionName |\\n\\n**Returns:** `boolean`\\n\\n**Example:**\\n```tsx\\nconst send = useAction<ActionSendPayload>('send');\\nconst sending = useActionPending('send');\\n\\n// In JSX — the control shows it is working until the agent's answer repaints the card:\\n<Button variant=\\\"primary\\\" disabled={sending} aria-busy={sending} onClick={() => send({ text })}>\\n {sending ? 'Sending…' : 'Send'}\\n</Button>\\n```\\n\\n\\n### useStream\\n\\nSubscribe to deliveries on a named stream channel.\\n\\nHonors the channel's per-delivery `mode` ('append' vs 'replace')\\nand the optional `complete` terminal marker. Channels declared\\n`mode: 'replace'` on the spec typically emit every delivery with\\n`mode: 'replace'` — this hook folds them into a single-latest\\nvalue without accumulating history.\\n\\n**Signature:** `useStream<T = unknown>(channelName: string): StreamResult<T>`\\n\\n**Parameters:**\\n\\n| Param | Type | Description |\\n|-------|------|-------------|\\n| channelName | `string` | Channel name from the GguiSession's streamSpec |\\n\\n**Returns:** `StreamResult<T>`\\n\\n| Property | Type | Description |\\n|----------|------|-------------|\\n| latest | `T \\\\| null` | Most recent payload delivered on this channel, or null if none received yet. |\\n| all | `T[]` | All payloads accumulated on this channel. - `mode: 'append'` deliveries are pushed to the tail (continuous stream). - `mode: 'replace'` deliveries collapse `all` to a single-element array containing the latest payload — matching the channel's \\\"full replacement\\\" semantics. |\\n| isComplete | `boolean` | Truthy after the channel has delivered an envelope with `complete: true`. Subscribers flip into a \\\"channel closed\\\" rendering state based on this signal; further deliveries on a completed channel are still accumulated, since the underlying wire doesn't enforce quiescence. |\\n\\n**Example:**\\n```tsx\\nconst progress = useStream<{ percent: number; message: string }>('progress');\\n\\n// In JSX:\\n{progress.latest && (\\n <Progress value={progress.latest.percent} />\\n)}\\n<Text>{progress.all.length} updates received</Text>\\n```\\n\\n\\n## Context Hooks\\n\\n\\n\\nRead-only access to render, app, and auth context.\\n\\n### useAuth\\n\\nRead-only auth context. Token excluded — auth is added server-side.\\n\\n**Signature:** `useAuth(): AuthInfo`\\n\\n**Returns:** `AuthInfo`\\n\\n| Property | Type | Description |\\n|----------|------|-------------|\\n| userId | `string` | userId |\\n| isAuthenticated | `boolean` | isAuthenticated |\\n\\n**Example:**\\n```tsx\\nconst auth = useAuth();\\n\\n// In JSX:\\n{auth.isAuthenticated\\n ? <Text>Welcome, user {auth.userId}</Text>\\n : <Text>Please sign in</Text>\\n}\\n```\\n\\n\\n### useApp\\n\\nRead-only app metadata.\\n\\n**Signature:** `useApp(): AppInfo`\\n\\n**Returns:** `AppInfo`\\n\\n| Property | Type | Description |\\n|----------|------|-------------|\\n| appId | `string` | appId |\\n| appName | `string` | appName |\\n| appDescription | `string` | appDescription |\\n| appIcon | `string` | appIcon |\\n\\n**Example:**\\n```tsx\\nconst app = useApp();\\n\\n// In JSX:\\n<Heading>{app.appName}</Heading>\\n{app.appDescription && <Text>{app.appDescription}</Text>}\\n```\\n\\n\\n### useRender\\n\\nRead-only render context with connection status.\\n\\n**Signature:** `useRender(): GguiSessionInfo`\\n\\n**Returns:** `GguiSessionInfo`\\n\\n| Property | Type | Description |\\n|----------|------|-------------|\\n| sessionId | `string` | sessionId |\\n| isConnected | `boolean` | isConnected |\\n\\n**Example:**\\n```tsx\\nconst render = useRender();\\n\\n// In JSX:\\n<Badge variant={render.isConnected ? 'success' : 'error'}>\\n {render.isConnected ? 'Connected' : 'Disconnected'}\\n</Badge>\\n```\\n\\n\\n## Provider\\n\\n\\n\\nThe provider is set up automatically by the renderer. Generated components do not need to wrap themselves in a provider.\\n\\n### GguiWireProvider\\n\\nReact context provider that injects WireConfig for all wire hooks.\\n\\n**Props:**\\n\\n| Prop | Type | Description |\\n|------|------|-------------|\\n| config | `WireConfig` | config |\\n| children | `ReactNode` | children |\\n\\n**Example:**\\n```tsx\\n<GguiWireProvider config={wireConfig}>\\n <YourComponent />\\n</GguiWireProvider>\\n```\\n\\n\\n## Internal: WireConfig\\n\\n\\n\\nThis is the configuration object passed to GguiWireProvider. Generated components do not interact with this directly — it is provided by the renderer.\\n\\n### WireConfig\\n\\nConfiguration injected by the provider — the renderer inside the\\niframe.\\n\\nEvery method is typed against the contract generic `T` so typed\\ncallers get compile-time enforcement:\\n - `dispatch(name, data)` — `name` MUST be a declared actionSpec\\n key; `data` MUST satisfy that action's schema.\\n - `subscribe(channel, handler)` — same discipline for streamSpec.\\n\\nUntyped callers (`T = DataContract` default) degrade to the broad\\nshape via the conditional `WireDispatchData` / `WireStreamPayload`\\naliases — no call-site break.\\n\\nThe contract's `agentCapabilities.tools` catalog declares tools the AGENT\\ninvokes (not the component); user gestures fire via\\n`dispatch(name, data)` and the optional `nextStep` field on the\\naction entry names the tool the agent SHOULD invoke next.\\n\\nThe renderer mounts exactly ONE GguiSession per iframe — `render.sessionId`\\nis the stable identity the WireProvider was constructed with. No\\nper-item scoping factory; with a one-GguiSession-per-mount lifecycle,\\n\\\"scope\\\" collapses to identity.\\n\\n| Property | Type | Description |\\n|----------|------|-------------|\\n| app | `{ readonly appId: string; readonly appName: string; readonly appDescription?: string; readonly appIcon?: string; }` | app |\\n| render | `{ readonly sessionId: string; readonly isConnected: boolean; }` | render |\\n| auth | `{ readonly userId?: string; readonly isAuthenticated: boolean; }` | auth |\\n| dispatch | `<N extends string>( actionName: N, data: WireDispatchData<T, N>, ) => void` | Fire an action to the agent (fire-and-forget over WS). Typed callers get compile-time checked `name` + `data`; untyped callers (`T = DataContract`) keep the broad shape. |\\n| subscribe | `<N extends string>( channelName: N, handler: (delivery: StreamDelivery<WireStreamPayload<T, N>>) => void, ) => () => void` | Subscribe to deliveries on a named stream channel. |\\n| onDispatchSuppressed | `(info: DispatchSuppressedInfo) => void` | Optional structured observability for the runtime's two dispatch- suppression invariants — the task-scoped duplicate backstop (`reason: 'duplicate-dispatch'`, fired by `useAction`) and the render-lifetime one-shot guard (`reason: 'one-shot-spent'`, fired by the config's own `dispatch` when a declared `oneShot` action is gestured a second time, ggui#1108). Both fire ALONGSIDE the always-on `console.warn`; neither reaches the agent. Reachability constraint: the first-party renderers do NOT set this field — `buildRootWireConfig` (`@ggui-ai/iframe-runtime`) and `<GguiRender>`'s internal config both omit it. It fires only when a host hand-builds a complete `WireConfig` (or passes `onDispatchSuppressed` to `buildWireConfig`). On every first-party render path the `console.warn` is the sole suppression signal — which is what the `oneShot` contract requires as its minimum trace. |\\n\";\n","// Common Pitfalls registry.\n//\n// Each entry is a rule the LLM should know up-front — it prevents an\n// error class that benchmarking has flagged as costing iterations. Keep\n// entries tight: the line that appears in the system prompt is the\n// entry's `rule`. Everything else is provenance + audit metadata.\n//\n// Growth path: when a benchmark run surfaces a new recurring error\n// class, add a pitfall entry with a short `foundIn` provenance note.\n//\n// The rules are rendered in the system prompt's `## Common Pitfalls`\n// block. Injection point: runtime.ts::buildSystemPrompt.\n\nexport interface Pitfall {\n /** Short id for logs / deduping. */\n readonly id: string;\n /** The one-line rule shown to the LLM. Uses backtick code spans. */\n readonly rule: string;\n /** Why this exists (developer note, not shown to LLM). */\n readonly why: string;\n /** Regex/substring the error message typically contains — used by\n * future analyzers to auto-detect \"this pitfall was violated\". */\n readonly errorPattern?: string | RegExp;\n /** Source: which experiment surfaced this. */\n readonly foundIn: string;\n}\n\n/**\n * Live registry. Append-only — never remove entries without a bench\n * that shows the rule no longer applies. Order doesn't matter (we\n * render alphabetically by id at emit time for determinism).\n */\nexport const PITFALLS: readonly Pitfall[] = [\n {\n id: \"stack-row-padding\",\n rule: \"`Stack`/`Row` do NOT accept `padding` — wrap the children in `<Box padding=\\\"...\\\">`.\",\n why: \"Stack and Row are flex containers; padding would violate the gap-based spacing model.\",\n foundIn: \"pre-#61 baseline\",\n },\n {\n id: \"align-enum\",\n rule: \"`align` accepts only `'start' | 'center' | 'end' | 'stretch'` (NEVER `flex-end`/`flex-start`).\",\n why: \"Components use semantic enums, not raw CSS flex values.\",\n foundIn: \"pre-#61 baseline\",\n },\n {\n id: \"justify-enum\",\n rule: \"`justify` accepts only `'start' | 'center' | 'end' | 'between' | 'around' | 'evenly'`.\",\n why: \"Semantic enum, not raw CSS flex values.\",\n foundIn: \"pre-#61 baseline\",\n },\n {\n id: \"badge-variant\",\n rule: \"`Badge variant` accepts `'default' | 'primary' | 'secondary' | 'success' | 'warning' | 'error' | 'info'`.\",\n why: \"Badge has a fixed enum — LLMs sometimes invent variants like 'danger' or 'red'.\",\n foundIn: \"pre-#61 baseline\",\n },\n {\n id: \"imports-preimported\",\n rule: \"All design-system primitives are pre-imported by the boilerplate — do NOT add imports unless absolutely needed.\",\n why: \"Duplicate imports cause TS errors; the boilerplate already resolves the full primitive surface.\",\n foundIn: \"pre-#61 baseline\",\n },\n // ─── stepper-display-only: retired to the CHECK leg (Exp 47 P2) ─────────\n //\n // The 6th always-on pitfall (\"Stepper is display-only…\") was added with\n // the #306 roster wave, but D8 measured Stepper adoption at 17/18 from\n // fragment + JSDoc alone — the always-on rule was demonstrably not\n // load-bearing, and exp66's factorial showed pitfall COUNT (5→6+) is\n // the dilution-sensitive lever (~+9s blended). Its guidance now ships\n // as the fix string of the `layout.multi_step.stepper_adopted` axis\n // check (evaluation/axis-checks/extras.ts) — delivered only to the\n // multi-step cells that actually violate it.\n //\n // ─── Provisional pitfalls considered + retired by exp66 n=6 factorial ───\n //\n // The 3 \"new\" pitfalls below were added in exp61 after OpenAI kanban\n // error mining: useState typing, stream null-guard promotion, null-vs-\n // undefined. Individual smokes suggested they helped, but the rigorous\n // exp66 factorial (n=6, 3×2 pitfalls × batch-fix) showed they REGRESS\n // blended ms by +8.8s (legacy5 29.3s → full8 38.1s, batch-off).\n //\n // Mechanism: attention dilution. Each added rule shifts LLM attention\n // away from the 5 legacy pitfalls that catch the real error classes.\n // Plus, \"ALWAYS type useState\" is too categorical — LLMs over-annotate\n // in contexts that didn't need it.\n //\n // Retired from default. Kept as dormant comments so the next person\n // investigating the same error classes knows this path was tried.\n //\n // usestate-type-annotation: \"ALWAYS type useState: useState<T[]>([])...\"\n // stream-latest-null-guard: \"useStream().latest is T|null — always null-guard...\"\n // null-vs-undefined: \"Use undefined for optional props, not null...\"\n //\n // If a future bench mines a new provider/fixture combination that\n // reliably violates one of these, revisit with a targeted profile,\n // not a global rule.\n];\n\n/**\n * Render the pitfalls as the Common Pitfalls block of the system prompt.\n * Called by runtime.ts::buildSystemPrompt. Deterministic ordering (by id)\n * so prompt-cache prefix stays stable across runs.\n */\nexport function renderPitfallsBlock(): string {\n // Experiment toggles:\n // GGUI_PITFALLS=off — suppress the entire Common Pitfalls block.\n // Tests whether any rules are load-bearing at all.\n // GGUI_NEW_PITFALLS=off — keep only the 5 legacy pitfalls, drop the\n // 3 added in #61 (useState typing, stream null\n // guard, null vs undefined). Tests whether the\n // new rules are a real win or noise.\n const disableAll =\n typeof process !== \"undefined\" && process.env?.GGUI_PITFALLS === \"off\";\n if (disableAll) return \"\";\n const disableNew = typeof process !== \"undefined\" && process.env?.GGUI_NEW_PITFALLS === \"off\";\n const LEGACY_IDS = new Set([\n // Pre-exp61: original Common Pitfalls (5 rules)\n \"stack-row-padding\",\n \"align-enum\",\n \"justify-enum\",\n \"badge-variant\",\n \"imports-preimported\",\n ]);\n const entries = [...PITFALLS]\n .filter((p) => !disableNew || LEGACY_IDS.has(p.id))\n .sort((a, b) => a.id.localeCompare(b.id));\n const bullets = entries.map((p) => `- ${p.rule}`).join(\"\\n\");\n return `## Common Pitfalls (each costs an iteration — avoid them up front)\\n${bullets}`;\n}\n","// Default single-component harness: prompt injection wrapper + agent params.\n//\n// `buildSystemPrompt` here is a positional wrapper over the skeleton\n// builder in `@ggui-ai/ui-gen/boilerplate`. It pre-fills every\n// injectable content block from the package's own content modules so\n// callers get a production-grade system prompt without supplying the\n// blocks themselves:\n// - `renderPitfallsBlock()` — common-pitfalls guidance.\n// - `DEFAULT_DESIGN_SYSTEM_DOCS` / `PRIMITIVES_DOCUMENTATION` /\n// `WIRE_DOCUMENTATION` — design-system, primitive, and wire docs.\n// - criteria block defaults from the CRITERIA registry.\n//\n// `generateBoilerplate` + the primitive constants + renderBoilerplate +\n// jsonSchemaTypeToTs are also re-exported here from\n// `@ggui-ai/ui-gen/boilerplate`.\n//\n// Pipeline: Boilerplate → unified coding + eval loop.\n// Turn 1: implement → self-check\n// Turns 2+: patch self-check issues → self-check\n// On first compile: deliver initial result → run eval\n// If eval issues: feed back → patch → self-check → re-eval\n//\n// Architectural guidance (primitives, CSS vars, planning hints) is given\n// directly to the coding agent in the system prompt — there is no\n// separate planner stage.\n\nimport type { GenerationProfileInput } from \"../boilerplate/styling-profile.js\";\nimport type { QualityConfig } from \"../evaluation/types-public.js\";\nimport { DEFAULT_DESIGN_SYSTEM_DOCS } from \"../design-system-docs.js\";\nimport { PRIMITIVES_DOCUMENTATION } from \"../validation/index.js\";\nimport { WIRE_DOCUMENTATION } from \"../tools/get-wire.js\";\nimport { renderPitfallsBlock } from \"./pitfalls.js\";\nimport type { GadgetDescriptor, DataContract, JsonObject } from \"@ggui-ai/protocol\";\nimport { buildSystemPrompt as buildSystemPromptSkeleton } from \"../boilerplate.js\";\nimport type { AgentConfig } from \"./llm-router.js\";\nimport type { CriteriaBank } from \"../evaluation/criteria/bank.js\";\nimport type { CanvasClass, DesignMode } from \"../design-mode.js\";\n\n// Re-export the boilerplate generator so existing internal importers\n// (create-harness.ts, benchmarks/preview-boilerplate.ts) keep working.\nexport { generateBoilerplate } from \"../boilerplate.js\";\n\n// =============================================================================\n// Config & Params\n// =============================================================================\n\ntype Provider = \"anthropic\" | \"openai\" | \"google\" | \"openrouter\";\n\n/** Agent config — provider + model pair. */\nexport interface AgentSpec {\n provider: Provider;\n model: string;\n /**\n * Explicit per-call credentials/routing (#484) — see\n * `AgentConfig.routeOverride`. Threaded through unchanged so\n * `createAgent()` can bypass `process.env` when the caller supplies\n * it. Absent for every pre-existing caller.\n */\n routeOverride?: AgentConfig[\"routeOverride\"];\n /**\n * Retry observer (#489) — see `AgentConfig.onRetry`. Threaded\n * through unchanged so `createAgent()` can notify the caller when\n * `apiCall()` retries a rate-limited request. Absent for every\n * pre-existing caller (no-op).\n */\n onRetry?: AgentConfig[\"onRetry\"];\n}\n\n/**\n * One coding turn's prompt, exactly as handed to the coding agent's tool call: the system prompt (after every\n * policy swap, e.g. the condensed component reference) and the turn's user message. Lets a caller audit the\n * prompt a generation actually sent rather than the templates it was built from.\n */\nexport interface CodingTurnPrompt {\n /** 1-indexed coding turn. */\n readonly turn: number;\n readonly systemPrompt: string;\n readonly userPrompt: string;\n}\n\nexport interface SingleComponentParams {\n userPrompt: string;\n contract?: DataContract;\n /** Shell type for layout-adaptive boilerplate */\n shellType?: \"chat\" | \"fullscreen\" | \"spatial\";\n /** Target screen size for responsive layout */\n screen?: \"mobile\" | \"tablet\" | \"desktop\" | \"universal\";\n evaluation?: {\n enabled: boolean;\n passThreshold: number;\n maxRounds?: number;\n maxBudgetPerEval?: number;\n maxBudgetPerFix?: number;\n };\n visualEvaluation?: {\n enabled: boolean;\n passThreshold?: number;\n sampleProps?: JsonObject;\n viewport?: { width: number; height: number };\n /**\n * Per-canvas judging — see `VisualEvalConfig.canvases`. When set, the\n * eval round screenshots + judges once per class and the harness\n * stamps `EvalResult.visual` with the PNG-free summary. Unset =\n * today's single screenshot at `viewport`.\n */\n canvases?: readonly CanvasClass[];\n /**\n * ggui#1195 — per-canvas viewport override for the in-loop round: the\n * box the composer targeted (`rendering.viewport`) so the round judges\n * the same box. See `VisualEvalConfig.canvasViewports`.\n */\n canvasViewports?: Partial<Readonly<Record<CanvasClass, { width: number; height: number }>>>;\n /**\n * The stylesheet the in-loop visual round renders under (a caller's\n * theme composed by `cssTokensForAppTheme`); absent = the design's\n * default tokens. Never part of the prompt or the identity.\n */\n cssTokens?: string;\n /** ggui#1436 — the visual criteria bank (data, parsed by `parseCriteriaBank`); absent = no block, today's judge. */\n criteriaBank?: CriteriaBank;\n /** ggui#1436 — the caller's item kind for the selector (a bootstrap mint's `hello`); absent = not gated by kind. */\n criteriaKind?: string;\n /**\n * ggui#1542 — which of the VISUAL leg's own findings may start another eval round when the quality mode is `fast`.\n * `'critical'` (the default, today's behaviour): only a critical finding, which the harness makes a blocking fail.\n * `'major'`: the visual JUDGE's major findings (tier-2 warns) too. The fit measurement's own warn-level overflow is\n * not among them (fit runs with or without a judge, so it is its own feedback source), and neither are the text\n * evaluator's warns. The other quality modes already act on every warn, so the setting changes nothing there. The\n * fix turn is fed as any continuing round is (fails first, then warns).\n */\n actOn?: \"critical\" | \"major\";\n };\n onProgress?: (event: unknown) => void;\n /**\n * Observer of what each coding turn sends the model — see {@link CodingTurnPrompt}. Read-only: the generation is\n * byte-identical with or without it. Absent = nothing reported.\n */\n onCodingTurnPrompt?: (sent: CodingTurnPrompt) => void;\n onInitialResult?: (result: {\n componentCode: string;\n sourceCode?: string;\n }) => void | Promise<void>;\n qualityConfig?: QualityConfig;\n /**\n * Optional fixture props (e.g., a benchmark commit's `props` field).\n * Forwarded to runCheck → runtimeRender for schema-first mockup synthesis.\n * Production callers omit this; benchmark runners pass commit.props.\n */\n fixtureProps?: JsonObject;\n}\n\n// =============================================================================\n// System Prompt (back-compat wrapper)\n// =============================================================================\n\n/**\n * Build the coding-agent system prompt using the full content stack:\n * env-gated pitfalls from `pitfalls.ts`, design-token reference from\n * `sdk/design-system-docs.ts`, primitives + wire auto-gen docs.\n *\n * Positional signature preserved for existing callers (create-harness.ts).\n * The underlying skeleton + criteria defaults live in\n * `@ggui-ai/ui-gen/boilerplate`. External OSS implementers calling\n * `buildSystemPrompt` from ui-gen directly get a clean default-empty prompt\n * with only the criteria block filled in.\n *\n * The optional `appGadgets` arg carries the operator-registered gadget\n * catalog. When provided, the prompt renders the registered catalog\n * (Leaflet, Mapbox, …) in the `clientCapabilities — registered catalog`\n * table; when omitted, it defaults to `STDLIB_GADGETS`. Production\n * callers (render, ops-generate) thread the resolved catalog from the\n * bound `AppMetadataStore`; benchmark / direct callers may omit it.\n */\nexport function buildSystemPrompt(\n userRequest: string,\n shellType?: string,\n screen?: string,\n axisDelta?: string,\n appGadgets?: readonly GadgetDescriptor[],\n /**\n * A `package -> .d.ts content` map for third-party gadget wrappers.\n * Forwarded to the skeleton builder so the gadget catalog renders a\n * `Type:` line per third-party gadget (its signature is extracted\n * from the `.d.ts`). When omitted, no `Type:` line is rendered —\n * stdlib gadgets do not need one.\n */\n gadgetTypes?: Readonly<Record<string, string>>,\n /**\n * Which triad to teach — see `SystemPromptInputs.designMode`. Omitted\n * (every pre-existing caller) means `constrained`, byte-identical to\n * the pre-`designMode` prompt.\n */\n designMode?: DesignMode,\n /** Rendering canvas class (`free` mode) — see `SystemPromptInputs.canvas`. */\n canvas?: CanvasClass,\n /** The app's generation profile (#991). */\n profile?: GenerationProfileInput,\n): string {\n return buildSystemPromptSkeleton({\n userRequest,\n shellType,\n screen,\n axisDelta,\n pitfallsBlock: renderPitfallsBlock(),\n designSystemDocs: DEFAULT_DESIGN_SYSTEM_DOCS,\n primitivesDoc: PRIMITIVES_DOCUMENTATION,\n wireDoc: WIRE_DOCUMENTATION,\n appGadgets,\n gadgetTypes,\n designMode,\n canvas,\n profile,\n // criteriaBlock left undefined — ui-gen fills default from open CRITERIA.\n });\n}\n"]}
|