@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/adapters/google/sdk.ts"],"names":[],"mappings":"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","file":"chunk-PBOYHGSD.js","sourcesContent":["// packages/ui-gen/src/adapters/google/sdk.ts\n//\n// Google adapter using @google/adk (Agent Development Kit).\n// Uses LlmAgent + InMemoryRunner + FunctionTool for agent-managed tool execution.\n\nimport { GeneratorAdapter, hasCredentials } from '../base';\nimport type { AdapterConfig, GenerateParams } from '../base';\nimport type { AdapterResult, ProviderName, AdapterMode } from '../types';\nimport { createCapture, captureSourceCode, captureCompiledCode, captureMarkers } from '../extract-code';\nimport type { Content, Part } from '@google/genai';\nimport type { JsonObject } from '@ggui-ai/protocol';\nimport type { ToolInputParameters } from '@google/adk';\n\nexport class GoogleSdkAdapter extends GeneratorAdapter {\n readonly provider: ProviderName = 'google';\n readonly mode: AdapterMode = 'sdk';\n readonly displayName = 'Google Gemini (ADK)';\n\n constructor(config: AdapterConfig = {}) {\n super(config);\n }\n\n isAvailable(): boolean {\n return hasCredentials(this.config, 'GEMINI_API_KEY', 'GOOGLE_API_KEY');\n }\n\n async generate(params: GenerateParams): Promise<AdapterResult> {\n const apiKey = this.config.apiKey || process.env.GEMINI_API_KEY || process.env.GOOGLE_API_KEY;\n\n return runAdkLoop({\n systemPrompt: params.systemPrompt,\n userPrompt: params.userPrompt,\n model: params.model,\n tools: params.tools,\n apiKey,\n });\n }\n}\n\n// =============================================================================\n// Core agentic loop — Google ADK (LlmAgent + InMemoryRunner)\n// =============================================================================\n\nimport type { ToolDefinition } from '../types';\n\nexport interface AdkLoopParams {\n systemPrompt: string;\n userPrompt: string;\n model: string;\n tools: ToolDefinition[];\n apiKey?: string;\n}\n\n/**\n * Run a single agentic loop using Google ADK.\n *\n * Uses InMemoryRunner.runAsync() which returns an async iterator of events.\n * FunctionTool wraps our ToolDefinition handlers with capture logic.\n */\nexport async function runAdkLoop(\n params: AdkLoopParams,\n): Promise<AdapterResult> {\n const startTime = Date.now();\n\n const { FunctionTool, Gemini, LlmAgent, InMemoryRunner, isFinalResponse } = await import('@google/adk');\n\n const capture = createCapture();\n\n // Build tools with capture wrappers\n const adkTools = params.tools.map((def) =>\n new FunctionTool({\n name: def.name,\n description: def.description,\n // Pass Zod schema directly — ADK accepts ZodObject natively\n parameters: def.inputSchema as ToolInputParameters,\n execute: async (args: unknown) => {\n const typedArgs = (args ?? {}) as JsonObject;\n captureSourceCode(capture, def.name, typedArgs);\n const result = await def.handler(typedArgs);\n captureCompiledCode(capture, def.name, result);\n return result.content[0]?.text ?? '';\n },\n }),\n );\n\n // The key the caller passed WINS, handed to the model directly (ggui#1132).\n // The ADK resolves GOOGLE_GENAI_API_KEY || GOOGLE_API_KEY || GEMINI_API_KEY\n // on its own when no key is given, so writing GOOGLE_GENAI_API_KEY here —\n // a variable this adapter does not own — let a stale ambient value beat a\n // fresh key, and no rotation could reach it. Precedence is fixed at the\n // source: an explicit key never touches process.env; no key defers to the\n // ADK's order untouched.\n const model = params.apiKey ? new Gemini({ model: params.model, apiKey: params.apiKey }) : params.model;\n\n const agent = new LlmAgent({\n name: 'ui_generator',\n model,\n instruction: params.systemPrompt,\n tools: adkTools,\n });\n\n const runner = new InMemoryRunner({ agent, appName: 'ggui_generator' });\n const session = await runner.sessionService.createSession({\n appName: 'ggui_generator',\n userId: 'benchmark',\n });\n\n const userMessage: Content = {\n role: 'user',\n parts: [{ text: params.userPrompt }],\n };\n\n let finalText = '';\n let turnCount = 0;\n let totalInputTokens = 0;\n let totalOutputTokens = 0;\n\n for await (const event of runner.runAsync({\n userId: 'benchmark',\n sessionId: session.id,\n newMessage: userMessage,\n })) {\n turnCount++;\n\n // Extract token usage from event's underlying LLM response\n const usage = event.usageMetadata;\n if (usage) {\n totalInputTokens += usage.promptTokenCount ?? 0;\n totalOutputTokens += usage.candidatesTokenCount ?? 0;\n }\n\n // Scan every event's content for markers and code\n if (event.content?.parts) {\n const text = event.content.parts.map((p: Part) => p.text ?? '').join('');\n if (text) captureMarkers(capture, text);\n }\n\n if (isFinalResponse(event)) {\n const parts = event.content?.parts;\n finalText = parts?.map((p: Part) => p.text ?? '').join('') ?? '';\n }\n }\n\n // Final scan of accumulated text\n if (finalText) captureMarkers(capture, finalText);\n\n if (!capture.compiledCode) {\n throw new Error('Google ADK adapter: no compiled code produced after all turns');\n }\n\n return {\n compiledCode: capture.compiledCode,\n sourceCode: capture.sourceCode,\n stream: capture.stream,\n generatorMeta: capture.generatorMeta,\n tokens: {\n input: totalInputTokens,\n output: totalOutputTokens,\n total: totalInputTokens + totalOutputTokens,\n },\n generationTimeMs: Date.now() - startTime,\n turnsUsed: turnCount,\n };\n}\n"]}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { createCapture, captureSourceCode, captureCompiledCode, captureMarkers, extractCodeFromText } from './chunk-YJZTUY7B.js';
|
|
2
|
+
import { GeneratorAdapter, hasCredentials } from './chunk-XRBCRKA2.js';
|
|
3
|
+
import { splitOpenAiUsage } from './chunk-OVLH5ICV.js';
|
|
4
|
+
|
|
5
|
+
// src/adapters/openai/sdk.ts
|
|
6
|
+
async function loadOpenAIAgents() {
|
|
7
|
+
return import('@openai/agents');
|
|
8
|
+
}
|
|
9
|
+
var OpenAiSdkAdapter = class extends GeneratorAdapter {
|
|
10
|
+
provider = "openai";
|
|
11
|
+
mode = "sdk";
|
|
12
|
+
displayName = "OpenAI (Agents SDK)";
|
|
13
|
+
constructor(config = {}) {
|
|
14
|
+
super(config);
|
|
15
|
+
}
|
|
16
|
+
isAvailable() {
|
|
17
|
+
return hasCredentials(this.config, "OPENAI_API_KEY");
|
|
18
|
+
}
|
|
19
|
+
async generate(params) {
|
|
20
|
+
const startTime = Date.now();
|
|
21
|
+
const apiKey = this.config.apiKey || process.env.OPENAI_API_KEY;
|
|
22
|
+
if (apiKey) process.env.OPENAI_API_KEY = apiKey;
|
|
23
|
+
const capture = createCapture();
|
|
24
|
+
const { Agent, run, tool } = await loadOpenAIAgents();
|
|
25
|
+
const wiredTools = params.tools.map(
|
|
26
|
+
(def) => tool({
|
|
27
|
+
name: def.name,
|
|
28
|
+
description: def.description,
|
|
29
|
+
parameters: def.inputSchema,
|
|
30
|
+
execute: async (args) => {
|
|
31
|
+
const typedArgs = args ?? {};
|
|
32
|
+
captureSourceCode(capture, def.name, typedArgs);
|
|
33
|
+
const result2 = await def.handler(typedArgs);
|
|
34
|
+
captureCompiledCode(capture, def.name, result2);
|
|
35
|
+
return result2.content[0]?.text ?? "";
|
|
36
|
+
}
|
|
37
|
+
})
|
|
38
|
+
);
|
|
39
|
+
const agent = new Agent({
|
|
40
|
+
name: "ui-generator",
|
|
41
|
+
instructions: params.systemPrompt,
|
|
42
|
+
model: params.model,
|
|
43
|
+
tools: wiredTools
|
|
44
|
+
});
|
|
45
|
+
const result = await run(agent, params.userPrompt, {
|
|
46
|
+
maxTurns: params.maxTurns
|
|
47
|
+
});
|
|
48
|
+
const finalOutput = String(result.finalOutput ?? "");
|
|
49
|
+
if (finalOutput) captureMarkers(capture, finalOutput);
|
|
50
|
+
if (!capture.compiledCode) {
|
|
51
|
+
await extractCodeFromText(finalOutput, params.tools, capture);
|
|
52
|
+
if (!capture.compiledCode) {
|
|
53
|
+
throw new Error("OpenAI SDK adapter: no compiled code produced after all turns");
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
const usage = result.state.usage;
|
|
57
|
+
const inputTokens = usage.inputTokens;
|
|
58
|
+
const outputTokens = usage.outputTokens;
|
|
59
|
+
const cachedInputTokens = (usage.inputTokensDetails ?? []).reduce(
|
|
60
|
+
(sum, details) => sum + (details.cached_tokens ?? 0),
|
|
61
|
+
0
|
|
62
|
+
);
|
|
63
|
+
const cacheWriteTokens = (usage.inputTokensDetails ?? []).reduce(
|
|
64
|
+
(sum, details) => sum + (details.cache_write_tokens ?? 0),
|
|
65
|
+
0
|
|
66
|
+
);
|
|
67
|
+
return {
|
|
68
|
+
compiledCode: capture.compiledCode,
|
|
69
|
+
sourceCode: capture.sourceCode,
|
|
70
|
+
stream: capture.stream,
|
|
71
|
+
generatorMeta: capture.generatorMeta,
|
|
72
|
+
...splitOpenAiUsage(inputTokens, outputTokens, cachedInputTokens, cacheWriteTokens),
|
|
73
|
+
generationTimeMs: Date.now() - startTime,
|
|
74
|
+
turnsUsed: result.rawResponses?.length ?? 0
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export { OpenAiSdkAdapter };
|
|
80
|
+
//# sourceMappingURL=chunk-PJFH7QWA.js.map
|
|
81
|
+
//# sourceMappingURL=chunk-PJFH7QWA.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/adapters/openai/sdk.ts"],"names":["result"],"mappings":"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","file":"chunk-PJFH7QWA.js","sourcesContent":["// packages/ui-gen/src/adapters/openai/sdk.ts\n//\n// OpenAI adapter using @openai/agents SDK.\n// Creates an Agent with function tools and runs it via run().\n\nimport { GeneratorAdapter, hasCredentials } from '../base';\nimport type { AdapterConfig, GenerateParams } from '../base';\nimport type { AdapterResult, ProviderName, AdapterMode } from '../types';\nimport { splitOpenAiUsage } from './tokens';\nimport {\n createCapture,\n captureSourceCode,\n captureCompiledCode,\n captureMarkers,\n extractCodeFromText,\n} from '../extract-code';\nimport type { JsonObject } from '@ggui-ai/protocol';\n\nasync function loadOpenAIAgents() {\n return import('@openai/agents');\n}\n\nexport class OpenAiSdkAdapter extends GeneratorAdapter {\n readonly provider: ProviderName = 'openai';\n readonly mode: AdapterMode = 'sdk';\n readonly displayName = 'OpenAI (Agents SDK)';\n\n constructor(config: AdapterConfig = {}) {\n super(config);\n }\n\n isAvailable(): boolean {\n return hasCredentials(this.config, 'OPENAI_API_KEY');\n }\n\n async generate(params: GenerateParams): Promise<AdapterResult> {\n const startTime = Date.now();\n\n const apiKey = this.config.apiKey || process.env.OPENAI_API_KEY;\n if (apiKey) process.env.OPENAI_API_KEY = apiKey;\n\n const capture = createCapture();\n\n // Build tools that call our handlers and capture compile results\n const { Agent, run, tool } = await loadOpenAIAgents();\n\n const wiredTools = params.tools.map((def) =>\n tool({\n name: def.name,\n description: def.description,\n parameters: def.inputSchema,\n execute: async (args) => {\n const typedArgs = (args ?? {}) as JsonObject;\n captureSourceCode(capture, def.name, typedArgs);\n\n const result = await def.handler(typedArgs);\n captureCompiledCode(capture, def.name, result);\n\n return result.content[0]?.text ?? '';\n },\n }),\n );\n\n const agent = new Agent({\n name: 'ui-generator',\n instructions: params.systemPrompt,\n model: params.model,\n tools: wiredTools,\n });\n\n const result = await run(agent, params.userPrompt, {\n maxTurns: params.maxTurns,\n });\n\n const finalOutput = String(result.finalOutput ?? '');\n\n // Scan final output for streamSpec/generatorMeta markers\n if (finalOutput) captureMarkers(capture, finalOutput);\n\n // Fallback: extract code from text output if no tool call produced it\n if (!capture.compiledCode) {\n await extractCodeFromText(finalOutput, params.tools, capture);\n\n if (!capture.compiledCode) {\n throw new Error('OpenAI SDK adapter: no compiled code produced after all turns');\n }\n }\n const usage = result.state.usage;\n const inputTokens = usage.inputTokens;\n const outputTokens = usage.outputTokens;\n // OpenAI's input token count INCLUDES cached tokens; sum the cached\n // subset across per-request details (ggui#1186).\n const cachedInputTokens = (usage.inputTokensDetails ?? []).reduce(\n (sum, details) => sum + (details.cached_tokens ?? 0),\n 0,\n );\n // ggui#1957 — and the cache writes, the same kind of subset.\n const cacheWriteTokens = (usage.inputTokensDetails ?? []).reduce(\n (sum, details) => sum + (details.cache_write_tokens ?? 0),\n 0,\n );\n\n return {\n compiledCode: capture.compiledCode,\n sourceCode: capture.sourceCode,\n stream: capture.stream,\n generatorMeta: capture.generatorMeta,\n ...splitOpenAiUsage(inputTokens, outputTokens, cachedInputTokens, cacheWriteTokens),\n generationTimeMs: Date.now() - startTime,\n turnsUsed: result.rawResponses?.length ?? 0,\n };\n }\n}\n"]}
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
// src/evaluation/types-public.ts
|
|
2
|
+
var LLM_EVAL_STATIC_CRITERIA = [
|
|
3
|
+
{ criterion: "functionality", tier: 1 },
|
|
4
|
+
{ criterion: "crash", tier: 1 },
|
|
5
|
+
{ criterion: "interactivity", tier: 2 },
|
|
6
|
+
{ criterion: "accessibility", tier: 2 },
|
|
7
|
+
{ criterion: "layout", tier: 2 },
|
|
8
|
+
{ criterion: "loading", tier: 2 },
|
|
9
|
+
{ criterion: "visual", tier: 2 }
|
|
10
|
+
];
|
|
11
|
+
function notApplicableCoverage(reason) {
|
|
12
|
+
return LLM_EVAL_STATIC_CRITERIA.map(({ criterion, tier }) => ({
|
|
13
|
+
criterion,
|
|
14
|
+
tier,
|
|
15
|
+
status: "not-applicable",
|
|
16
|
+
reason
|
|
17
|
+
}));
|
|
18
|
+
}
|
|
19
|
+
var DEFAULT_QUALITY_CONFIG = {
|
|
20
|
+
quality: "fast",
|
|
21
|
+
visualEval: false,
|
|
22
|
+
maxCostPerGeneration: 3
|
|
23
|
+
};
|
|
24
|
+
function matches(vector, check) {
|
|
25
|
+
const primary = vector[check.axis];
|
|
26
|
+
if (!check.values.includes(primary)) return false;
|
|
27
|
+
if (check.and) {
|
|
28
|
+
const sibling = vector[check.and.axis];
|
|
29
|
+
if (!check.and.values.includes(sibling)) return false;
|
|
30
|
+
}
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
function priorityForIssue(category) {
|
|
34
|
+
if (category === "interactivity" || category === "accessibility" || category === "layout" || category === "loading" || category === "visual") {
|
|
35
|
+
return "P2";
|
|
36
|
+
}
|
|
37
|
+
if (category === "tokens" || category === "crash" || category === "functionality") {
|
|
38
|
+
return "P1";
|
|
39
|
+
}
|
|
40
|
+
return "P0";
|
|
41
|
+
}
|
|
42
|
+
function isBlocked(result) {
|
|
43
|
+
return result.issues.some((i) => i.result === "fail");
|
|
44
|
+
}
|
|
45
|
+
function getActionableIssues(result, mode) {
|
|
46
|
+
if (mode === "fast") {
|
|
47
|
+
return result.issues.filter((i) => i.result === "fail");
|
|
48
|
+
}
|
|
49
|
+
return result.issues.filter((i) => i.result === "fail" || i.result === "warn");
|
|
50
|
+
}
|
|
51
|
+
var CRITERIA = [
|
|
52
|
+
// ── P0: Correctness (must satisfy — failure = broken component) ──
|
|
53
|
+
{
|
|
54
|
+
id: "compile",
|
|
55
|
+
name: "Compile & type-check",
|
|
56
|
+
priority: "P0",
|
|
57
|
+
tier: 0,
|
|
58
|
+
failOutcome: "fail",
|
|
59
|
+
codingGuidance: "Code must compile. The typed Props and wire hook generics are enforced by the compiler.",
|
|
60
|
+
evalInstruction: "Checked automatically by esbuild + TypeScript. No LLM evaluation needed."
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
id: "render-props",
|
|
64
|
+
name: "Render all Props fields",
|
|
65
|
+
priority: "P0",
|
|
66
|
+
tier: 0,
|
|
67
|
+
failOutcome: "warn",
|
|
68
|
+
codingGuidance: "Render every Props field in JSX. Access via props.fieldName.",
|
|
69
|
+
evalInstruction: "Check that every field from interface Props appears as props.fieldName in the function body."
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
id: "wire-hooks",
|
|
73
|
+
name: "Wire all contract hooks",
|
|
74
|
+
priority: "P0",
|
|
75
|
+
tier: 0,
|
|
76
|
+
failOutcome: "warn",
|
|
77
|
+
codingGuidance: "Wire every useAction/useStream and every clientCapabilities.gadgets hook (e.g., useGeolocation) to a UI element. `agentCapabilities.tools` is a catalog the AGENT invokes \u2014 NOT a component hook surface.",
|
|
78
|
+
evalInstruction: "Check that every hook variable from the boilerplate appears in the JSX or an effect."
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
id: "imports",
|
|
82
|
+
name: "Valid imports only",
|
|
83
|
+
priority: "P0",
|
|
84
|
+
tier: 0,
|
|
85
|
+
failOutcome: "fail",
|
|
86
|
+
codingGuidance: "Only import from react, @ggui-ai/design/*, and @ggui-ai/wire.",
|
|
87
|
+
evalInstruction: "Flag any import from a package not in the allowlist."
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
id: "security",
|
|
91
|
+
name: "No eval/fetch/window",
|
|
92
|
+
priority: "P0",
|
|
93
|
+
tier: 0,
|
|
94
|
+
failOutcome: "fail",
|
|
95
|
+
codingGuidance: "Never use eval(), fetch(), or window. Data comes from props and hooks.",
|
|
96
|
+
evalInstruction: "Flag any call to eval(), fetch(), or window access."
|
|
97
|
+
},
|
|
98
|
+
// ── P1: Safety (should satisfy — failure = crash or bad UX) ──
|
|
99
|
+
{
|
|
100
|
+
id: "functionality",
|
|
101
|
+
name: "All features implemented",
|
|
102
|
+
priority: "P1",
|
|
103
|
+
tier: 1,
|
|
104
|
+
failOutcome: "fail",
|
|
105
|
+
codingGuidance: "Implement ALL features from the request AND the data contract.",
|
|
106
|
+
evalInstruction: `Evaluate FUNCTIONALITY: Does this component implement ALL features from the request AND the data contract?
|
|
107
|
+
|
|
108
|
+
Check against BOTH sources:
|
|
109
|
+
1. Original request \u2014 each feature must be coded AND rendered in JSX
|
|
110
|
+
2. Data contract (if present) \u2014 verify:
|
|
111
|
+
- Props fields are rendered in the UI. EXCEPTION: pure identifier fields (\`id\`, \`*Id\`, keys) that exist only to be echoed back inside an action payload do NOT need to be visibly rendered.
|
|
112
|
+
- ALL useAction hooks are wired to clickable UI elements
|
|
113
|
+
- ALL useStream hooks are consumed \u2014 the streamed data must reach the UI. Merging stream events into rendered state (a list, a counter, the displayed records) COUNTS as consuming the stream; it need not be a literal \`.latest\` render.
|
|
114
|
+
- ALL clientCapabilities gadgets are used. \`clientCapabilities.gadgets\` is keyed by npm package: built-in browser capabilities (useGeolocation / useCamera / \u2026) import from @ggui-ai/gadgets; registered third-party gadgets (e.g. useChartTheme) import from their OWN package. Any gadget the contract declares IS a contract feature \u2014 NEVER flag it as "not part of the contract".
|
|
115
|
+
- \`agentCapabilities.tools\` is a catalog declaration only; do NOT flag missing component-side calls for it
|
|
116
|
+
|
|
117
|
+
A contract hook that is declared but never used at all is a MISSING feature.
|
|
118
|
+
|
|
119
|
+
CRITICAL: The "issues" array must ONLY contain features you are CERTAIN are missing or broken \u2014 never an implemented feature. (See "Issue-array discipline" above: no speculative, self-negating, or "verify that\u2026" entries.)`
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
id: "crash",
|
|
123
|
+
name: "No crash scenarios",
|
|
124
|
+
priority: "P1",
|
|
125
|
+
tier: 1,
|
|
126
|
+
failOutcome: "fail",
|
|
127
|
+
codingGuidance: "Guard optional props (props.field?.x). stream.latest is T|null \u2014 always null-guard. .all is always an array.",
|
|
128
|
+
evalInstruction: `Evaluate CRASH SAFETY: Are there ACTUAL runtime crash scenarios?
|
|
129
|
+
|
|
130
|
+
WILL crash (include in issues):
|
|
131
|
+
- .map()/.filter()/.length on an uninitialized variable
|
|
132
|
+
- Accessing property of undefined without guard
|
|
133
|
+
- useStream().latest.field WITHOUT null guard \u2014 .latest is T | null
|
|
134
|
+
- Optional Props field accessed as props.field.x without guard
|
|
135
|
+
- Array item optional field: items.map(item => item.priority.toUpperCase()) when priority is optional
|
|
136
|
+
|
|
137
|
+
SAFE (do NOT include):
|
|
138
|
+
- Optional chaining: props.items?.map() \u2014 SAFE
|
|
139
|
+
- Fallback: items || [] \u2014 SAFE
|
|
140
|
+
- useState initializer: useState([]) \u2014 SAFE
|
|
141
|
+
- Null check: items && items.map() \u2014 SAFE
|
|
142
|
+
- stream.latest && stream.latest.field \u2014 SAFE, guarded
|
|
143
|
+
- stream.all.map(...) \u2014 SAFE, .all is always an array
|
|
144
|
+
- stream.all.length \u2014 SAFE, always a number
|
|
145
|
+
|
|
146
|
+
The "issues" array is ONLY for a specific line that WILL throw at runtime. NEVER put a line you have determined is safe into the issues array \u2014 not even to note that it is safe ("\u2026so this is safely guarded", "\u2026so there is no crash"). If you cannot name a concrete line that will throw, the answer is {"pass": true} \u2014 return that and an empty issues array.`
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
id: "tokens",
|
|
150
|
+
name: "Design system tokens",
|
|
151
|
+
priority: "P1",
|
|
152
|
+
tier: 0,
|
|
153
|
+
failOutcome: "warn",
|
|
154
|
+
codingGuidance: 'Use CSS variables for colors (var(--ggui-color-*)); use the spacing scale for gap/padding/margin (gap="md", padding="lg").',
|
|
155
|
+
evalInstruction: 'Flag hardcoded hex colors, rgba/hsl functions, and numeric or raw-CSS-length spacing props. A t-shirt-scale spacing name (gap="md") IS a token \u2014 never flag it.'
|
|
156
|
+
},
|
|
157
|
+
// ── P2: Quality (nice to have — failure = lower score, not broken) ──
|
|
158
|
+
{
|
|
159
|
+
id: "interactivity",
|
|
160
|
+
name: "Sufficient interactive elements",
|
|
161
|
+
priority: "P2",
|
|
162
|
+
tier: 2,
|
|
163
|
+
failOutcome: "warn",
|
|
164
|
+
codingGuidance: "Add appropriate interactive elements for the component purpose.",
|
|
165
|
+
evalInstruction: `Evaluate INTERACTIVITY: Does this component have sufficient interactive elements?
|
|
166
|
+
|
|
167
|
+
Consider: forms need submit buttons, lists need selection, editable content needs save/cancel.
|
|
168
|
+
Contract actions (if present): every useAction hook should be triggered by a visible UI element.
|
|
169
|
+
|
|
170
|
+
Only list MISSING interactive elements. Use 'fail' only for issues blocking core purpose.`
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
id: "accessibility",
|
|
174
|
+
name: "Accessible markup",
|
|
175
|
+
priority: "P2",
|
|
176
|
+
tier: 2,
|
|
177
|
+
failOutcome: "warn",
|
|
178
|
+
codingGuidance: "Add labels on form inputs, alt text on images, semantic HTML, and state ARIA (aria-checked/pressed/selected/expanded) on hand-rolled interactive controls.",
|
|
179
|
+
evalInstruction: `Evaluate ACCESSIBILITY: missing labels, alt text, semantic HTML, keyboard support, ARIA state.
|
|
180
|
+
|
|
181
|
+
ggui primitives bake in their own ARIA \u2014 see "Primitive Accessibility" in the Design System context above. NEVER flag a ggui primitive (Input/Select/TextArea, RadioGroup, Checkbox, Toggle, Progress, Slider, Spinner, Skeleton, Tabs, Accordion, Alert, Toast, Tooltip, Clickable, Icon) for a missing role / aria-* / label / keyboard handler \u2014 it is already there and not visible in the source you are reading.
|
|
182
|
+
|
|
183
|
+
Flag ONLY real gaps: a raw div/span used as an interactive control; a hand-rolled control whose checked/selected/expanded/pressed state is conveyed only by styling (strikethrough, color, a check icon) with no \`aria-checked\` / \`aria-pressed\` / \`aria-selected\` / \`aria-expanded\`; an image with no alt text; an Input/Select/TextArea with no \`label\` prop; an icon-only Button with no aria-label; live/streaming data not wrapped in an aria-live region; inverted heading hierarchy.
|
|
184
|
+
|
|
185
|
+
Only list MISSING accessibility features. Use 'fail' only if it blocks delivery.`
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
id: "layout",
|
|
189
|
+
name: "Clean layout",
|
|
190
|
+
priority: "P2",
|
|
191
|
+
tier: 2,
|
|
192
|
+
failOutcome: "warn",
|
|
193
|
+
codingGuidance: "Use proper spacing and visual grouping.",
|
|
194
|
+
evalInstruction: `Evaluate LAYOUT: Check spacing, alignment, visual grouping, and composition.
|
|
195
|
+
|
|
196
|
+
Only list ACTUAL layout problems. Use 'fail' only for fundamentally broken layouts.`
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
id: "loading",
|
|
200
|
+
name: "Loading/empty/error states",
|
|
201
|
+
priority: "P2",
|
|
202
|
+
tier: 2,
|
|
203
|
+
failOutcome: "warn",
|
|
204
|
+
codingGuidance: "Handle async data, empty collections, and error cases.",
|
|
205
|
+
evalInstruction: `Evaluate LOADING/EMPTY/ERROR STATES: Does the component handle async data and edge cases?
|
|
206
|
+
|
|
207
|
+
Contract-specific: useStream should handle pre-data state. clientCapabilities hooks may return undefined / permission-denied \u2014 defensive guards expected before threading values into JSX.
|
|
208
|
+
Props-only components (no async, no streams, no client capabilities) do NOT need loading states \u2014 return pass.
|
|
209
|
+
|
|
210
|
+
Only list MISSING states.`
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
id: "visual",
|
|
214
|
+
name: "Design system consistency",
|
|
215
|
+
priority: "P2",
|
|
216
|
+
tier: 2,
|
|
217
|
+
failOutcome: "warn",
|
|
218
|
+
codingGuidance: "Use design system tokens consistently.",
|
|
219
|
+
evalInstruction: `Evaluate VISUAL CONSISTENCY: Is the component using the design system correctly?
|
|
220
|
+
|
|
221
|
+
Flag: hardcoded colors instead of CSS variables, numeric or raw-CSS-length spacing instead of the t-shirt scale, style objects bypassing design system.
|
|
222
|
+
A t-shirt-scale spacing name (gap="md", padding="lg") IS correct token usage \u2014 never flag it.
|
|
223
|
+
Intentional custom colors (status indicators) are acceptable when no semantic token fits.
|
|
224
|
+
|
|
225
|
+
Only list ACTUAL violations. Use 'fail' only for pervasive violations.`
|
|
226
|
+
}
|
|
227
|
+
];
|
|
228
|
+
var FREE_DESIGN_CRITERIA_OVERRIDES = [
|
|
229
|
+
{
|
|
230
|
+
id: "tokens",
|
|
231
|
+
name: "Color tokens",
|
|
232
|
+
priority: "P1",
|
|
233
|
+
tier: 0,
|
|
234
|
+
failOutcome: "warn",
|
|
235
|
+
codingGuidance: "Every color is a bare var(--ggui-color-*) from the token manifest \u2014 no hex, rgb()/hsl(), CSS named colors or literal fallbacks, in style props and <style> blocks alike. Spacing, typography, radius and shadow geometry may be literals.",
|
|
236
|
+
evalInstruction: "Flag hardcoded hex colors, rgba/hsl functions, CSS named colors, and literal fallbacks inside var(--ggui-*) references. Do NOT flag literal spacing, font sizes, radii or pixel values \u2014 they are allowed in this mode."
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
id: "visual",
|
|
240
|
+
name: "Visual composition",
|
|
241
|
+
priority: "P2",
|
|
242
|
+
tier: 2,
|
|
243
|
+
failOutcome: "warn",
|
|
244
|
+
codingGuidance: "Compose deliberately: one clear focal point, consistent spacing rhythm, a coherent theme-token palette, a fit to the rendering canvas.",
|
|
245
|
+
evalInstruction: `Evaluate VISUAL COMPOSITION: Is the component composed deliberately for its canvas?
|
|
246
|
+
|
|
247
|
+
Judge: visual hierarchy (one clear focal point, headings distinct from body text), consistent spacing rhythm and alignment, a coherent palette drawn from the theme tokens, fit to the canvas (fluid width, no fixed widths, nothing cramped or stretched).
|
|
248
|
+
Do NOT reward or penalise the use of design-system primitives \u2014 raw HTML with inline CSS is a first-class choice here. Literal spacing / typography / radius values are fine.
|
|
249
|
+
|
|
250
|
+
Only list ACTUAL composition problems. Use 'fail' only for a fundamentally incoherent composition.`
|
|
251
|
+
}
|
|
252
|
+
];
|
|
253
|
+
function criteriaFor(designMode = "constrained") {
|
|
254
|
+
if (designMode === "constrained") return CRITERIA;
|
|
255
|
+
return CRITERIA.map(
|
|
256
|
+
(c) => FREE_DESIGN_CRITERIA_OVERRIDES.find((o) => o.id === c.id) ?? c
|
|
257
|
+
);
|
|
258
|
+
}
|
|
259
|
+
function getCriteriaByPriority(priority, designMode = "constrained") {
|
|
260
|
+
return criteriaFor(designMode).filter((c) => c.priority === priority);
|
|
261
|
+
}
|
|
262
|
+
function getCriterionById(id, designMode = "constrained") {
|
|
263
|
+
return criteriaFor(designMode).find((c) => c.id === id);
|
|
264
|
+
}
|
|
265
|
+
function getLLMCriteria(designMode = "constrained") {
|
|
266
|
+
return criteriaFor(designMode).filter((c) => c.tier > 0);
|
|
267
|
+
}
|
|
268
|
+
function buildCodingCriteriaSummary(designMode = "constrained") {
|
|
269
|
+
const lines = ["## Priority (P0 first, then P1, then P2)", ""];
|
|
270
|
+
for (const priority of ["P0", "P1", "P2"]) {
|
|
271
|
+
const label = priority === "P0" ? "Must (compile + complete)" : priority === "P1" ? "Should (safety)" : "Nice (quality)";
|
|
272
|
+
const criteria = getCriteriaByPriority(priority, designMode);
|
|
273
|
+
lines.push(`**${priority} \u2014 ${label}:**`);
|
|
274
|
+
for (const c of criteria) {
|
|
275
|
+
lines.push(`- ${c.codingGuidance}`);
|
|
276
|
+
}
|
|
277
|
+
lines.push("");
|
|
278
|
+
}
|
|
279
|
+
return lines.join("\n");
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
export { CRITERIA, DEFAULT_QUALITY_CONFIG, LLM_EVAL_STATIC_CRITERIA, buildCodingCriteriaSummary, criteriaFor, getActionableIssues, getCriteriaByPriority, getCriterionById, getLLMCriteria, isBlocked, matches, notApplicableCoverage, priorityForIssue };
|
|
283
|
+
//# sourceMappingURL=chunk-PUH4CXGZ.js.map
|
|
284
|
+
//# sourceMappingURL=chunk-PUH4CXGZ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/evaluation/types-public.ts"],"names":[],"mappings":"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","file":"chunk-PUH4CXGZ.js","sourcesContent":["// Evaluation type vocabulary shared between the harness runtime and its\n// check/evaluator surfaces. This is the narrow contract layer — the\n// type language every harness leg is written against:\n//\n// - `EvalIssue` — the single issue shape everything produces.\n// - `EvalTier` / `EvalOutcome` / `EvalCategory` — the issue's axes.\n// - `Priority` — P0/P1/P2 ranking referenced by the retry formatter.\n// - `EvalResult` — aggregate shape a runner returns.\n// - `QualityMode` / `QualityConfig` / `DEFAULT_QUALITY_CONFIG` —\n// the quality-mode knob the adapter surface consumes.\n// - `priorityForIssue` / `isBlocked` / `getActionableIssues` — the\n// purely-typed helpers over the vocabulary.\n//\n// `EvalIssue` is referenced by `PatchFn`, `TierCheck`, `LLMEvaluator`,\n// and `RuntimeRenderCheck` in the harness types hub.\n\n// ─── Priority ──────────────────────────────────────────────────────────────\n// P0 = must (compile + complete), P1 = should (safety), P2 = nice (quality).\n// Single source of truth for the retry-formatter ranking.\n\nexport type Priority = \"P0\" | \"P1\" | \"P2\";\n\nimport type { VisionFinishReason } from '../harness/llm-router.js';\nimport type { GenerationRuntimeProbeOutcome, GenerationRuntimeProbeStatus } from \"@ggui-ai/mcp-server-core\";\nimport type { CanvasClass, DesignMode } from \"../design-mode.js\";\n\n// ─── Issue shape ───────────────────────────────────────────────────────────\n\nexport type EvalTier = 0 | 1 | 2;\nexport type EvalOutcome = \"fail\" | \"warn\" | \"pass\";\n\nexport type EvalCategory =\n | \"compile\"\n | \"security\"\n | \"contract\"\n | \"types\"\n | \"imports\"\n | \"tokens\" // tier 0\n | \"mode\" // tier 0 — per-mode deterministic\n | \"functionality\"\n | \"crash\" // tier 1\n | \"interactivity\"\n | \"accessibility\"\n | \"layout\"\n | \"loading\"\n | \"visual\"; // tier 2\n\nexport interface EvalIssue {\n tier: EvalTier;\n result: EvalOutcome;\n category: EvalCategory;\n /**\n * Priority tier — threaded through to the retry formatter so the LLM can\n * rank its next patch against the prompt's P0/P1/P2 priority schema.\n * Derived from (category, result) via {@link priorityForIssue} when not\n * explicitly set. Optional on construction; check-runners typically\n * populate it before returning.\n */\n priority?: Priority;\n subcategory?: string;\n severity?: \"critical\" | \"major\";\n description: string;\n fix: string;\n line?: number;\n /**\n * The visual leg's provenance (ggui#1545): `judge` (the model's finding) or `instrument` (a deterministic\n * measurement). Absent on every other leg's issues. `visualEvaluation.actOn` acts on `judge` only.\n */\n origin?: \"judge\" | \"instrument\";\n}\n\n/**\n * Runtime-render probe execution status — four-valued so \"the probe\n * never ran\" is never conflated with \"the probe ran clean\". ONE union: the\n * same values a generation's metadata reports (`GenerationRuntimeProbeStatus`\n * in `@ggui-ai/mcp-server-core`), declared there and named here.\n *\n * - `ran` — probe executed; its findings (possibly none) are\n * in the issue stream under `runtime:*` subcategories.\n * - `infra-skipped` — probe could NOT execute (environment failure:\n * happy-dom load, user-event document capture,\n * ESM/CJS interop). Carries ZERO probe evidence;\n * consumers MUST NOT count it as a pass.\n * - `not-applicable`— nothing to probe (no compiled code, no contract\n * surface, or no runtimeRender check configured).\n * - `timed-out` — probe started but did not finish inside its\n * wall-clock bound (ggui#1299). Carries ZERO\n * evidence about the component: on a contended\n * host an ordinary component crosses the bound.\n * Consumers MUST NOT count it as a pass, and MUST\n * NOT count it as a crash either. `elapsedMs` and\n * `hostLoad` say how long it ran and how busy the\n * host was, so a reader can tell the two cases apart.\n */\nexport type RuntimeProbeStatus = GenerationRuntimeProbeStatus;\n\n/**\n * The host's 1-minute load average at a probe's start and end, beside the\n * number of CPUs the process can use (ggui#1299). A load well above\n * `cores` means the probe competed for CPU; a wall-clock bound crossed\n * there says more about the host than about the component.\n */\nexport interface ProbeHostLoad {\n readonly start: number;\n readonly end: number;\n readonly cores: number;\n}\n\n/**\n * ggui#1398 — whether the controls the probe clicked showed they were\n * working once their action was pending. Report-only: it is read by the\n * benchmark and never counted into the probe's warnings or fed back to\n * the coding loop.\n */\nexport interface ProbePendingAffordance {\n /** Controls the pending phase marked pending: those whose click dispatched their action (click or submit wiring) and that were still in the page. `visible + missing.length === dispatched`. */\n readonly dispatched: number;\n /** Of those, how many visibly changed while pending (disabled, busy, text, or replaced). */\n readonly visible: number;\n /** The actions whose control did not visibly change, including one whose card threw while pending. */\n readonly missing: readonly string[];\n /** Actions whose control was no longer in the page when its turn came (the card replaced it, or blanked after a throw): never marked, not counted as dispatched. */\n readonly gone: readonly string[];\n}\n\n/**\n * The engine's own fields on a probe's meta, beside the outcome a\n * generation's metadata reports: why a probe did not finish, its render\n * time, the host's load around it. Present on every arm of\n * {@link RuntimeProbeMeta}; each is absent when the probe had nothing to\n * say about it.\n */\nexport interface RuntimeProbeMetaDetail {\n /** Populated for `infra-skipped` / `not-applicable` / `timed-out` — why the probe didn't finish. */\n readonly reason?: string;\n /** `ran` only: the check's own render time, inside `elapsedMs`. */\n readonly renderMs?: number;\n /** Host load around the probe, when it ran isolated (absent for an in-process probe). */\n readonly hostLoad?: ProbeHostLoad;\n /** Time the check waited for a probe slot before it started, ms; present only when > 0 (ggui#1380 C2b). */\n readonly queuedMs?: number;\n /**\n * `ran` only: the pending-affordance walk (ggui#1398). Absent when no\n * action walk ran, so \"no data\" and \"0 of 0\" read differently.\n */\n readonly pendingAffordance?: ProbePendingAffordance;\n}\n\n/**\n * Probe execution meta stamped onto an `EvalResult` at the exit-decision\n * points that invoke the probe. Absence of this field means the eval\n * path never reached a probe invocation at all — consumers treat that\n * the same as not-run, never as a pass.\n *\n * ONE union with the generation metadata's probe outcome\n * (`GenerationRuntimeProbeOutcome` in `@ggui-ai/mcp-server-core`, declared\n * there and carried here with {@link RuntimeProbeMetaDetail} on every arm),\n * so the round's stamp and the metadata's record cannot say different\n * things (ggui#1380):\n *\n * - `ran` + `verdict: 'pass'` — the probe executed and no check failed;\n * - `ran` + `verdict: 'fail'` — ANY check failed; `failChecks` lists the\n * distinct check kinds that did (`RenderCheckKind`, the engine's name\n * for the same union), never empty, in the order `RENDER_CHECK_KINDS`\n * declares them, parsed from the probe's own\n * `runtime:<check>[:<subject>]` issues;\n * - `timed-out` / `infra-skipped` / `not-applicable` — no verdict, and the\n * type carries none. `elapsedMs` (on every status that reached the\n * check) and `hostLoad` say how long it ran and how busy the host was.\n *\n * The verdict and the repair trigger are two different questions. The\n * verdict is `fail` on any failing check. The one repair turn a probe-only\n * round buys fires on a `render-no-throw` fail the engine recognises\n * (`isRecoverableRenderCrash`) and on nothing else: on the PROBE-ONLY round a\n * `fail` verdict whose checks are `prop-sensitivity`, `action-wiring` or any\n * other kind is recorded here and never fed back. The same meta is stamped on\n * the EVALUATION lane, where a `prop-sensitivity` fail buys that lane's own\n * contract-feedback round (ggui#1261, `FEEDBACK_PROBE_CHECKS`) — a different\n * turn under a different rule, not the repair turn.\n */\nexport type RuntimeProbeMeta = GenerationRuntimeProbeOutcome & RuntimeProbeMetaDetail;\n\n/**\n * The one repair turn a probe-only round buys (ggui#1380). A serving\n * deployment that wires the runtime probe and configures no evaluator runs\n * the probe once after the coding turns; a render crash the engine\n * recognises buys exactly one repair turn, then one re-probe. This records\n * what came of it:\n * - `compiled: false` — the repair turn's code did not pass self-check, so\n * no re-probe ran (there is no `after`) and the pre-repair card is the\n * one served;\n * - `compiled: true` — the re-probe ran and `after` is its whole meta:\n * its status, its verdict when it ran, and the checks that still fail.\n * Whether the crash class the turn was bought for is still there is\n * `after.verdict === 'fail' && after.failChecks.includes('render-no-throw')`.\n * The two arms are exclusive by type.\n */\nexport type RuntimeProbeRepair =\n | { readonly attempted: true; readonly compiled: false; readonly trigger?: never }\n | { readonly attempted: true; readonly compiled: true; readonly trigger: RuntimeProbeMeta };\n\n/**\n * Per-criterion execution status — three-valued so \"the criterion\n * silently produced no verdict\" is never conflated with \"the criterion\n * ran clean\", and neither is conflated with \"not evaluated by design\".\n * Same doctrine and vocabulary family as `RuntimeProbeStatus` above.\n *\n * - `ran` — the LLM call completed and returned a verdict\n * for this criterion; its findings (possibly\n * none) are in `issues`.\n * - `skipped` — the call errored or returned no tool call. The\n * criterion carries ZERO evidence; the evaluator\n * fail-opens it into `pass` to avoid blocking\n * generation on flaky LLM calls, so consumers\n * MUST consult this field before treating `pass`\n * membership as a verdict. Counts AGAINST\n * coverage.\n * - `not-applicable` — the evaluator was bypassed by design for this\n * cell (e.g. the same-image low-risk bypass:\n * axis checks clean, tier-1/2 never invoked).\n * `reason` names the bypass. Excluded from\n * coverage denominators — it is neither evidence\n * nor a silent absence.\n */\nexport type CriterionRunStatus = \"ran\" | \"skipped\" | \"not-applicable\";\n\n/** Coverage row for one evaluation criterion of one eval run. */\nexport interface CriterionCoverage {\n readonly criterion: string;\n readonly tier: 1 | 2;\n readonly status: CriterionRunStatus;\n /** Populated for `skipped` / `not-applicable` — why no verdict. */\n readonly reason?: string;\n}\n\n/**\n * Coverage of the screenshot JUDGE leg for one eval round (ggui#1221) — a\n * different surface from the `visual` CRITERION in `criteriaCoverage` (the\n * LLM evaluator's read of the source). `ran` = a frame was captured and\n * judged; `skipped` = the leg was configured but produced no verdict\n * (no browser, a launch or in-page failure, an unbundlable component, an\n * unparsable judge answer) with `reason` naming why; `not-applicable` =\n * the round had no visual leg configured. Before this row a skipped leg\n * left NO trace on the result — `{ issues: [] }` read exactly like a\n * clean run, and every bootstrap mint on a browserless runtime \"passed\"\n * its visual round that way.\n */\nexport interface VisualCoverage {\n readonly status: CriterionRunStatus;\n /** Populated for `skipped` / `not-applicable` — why no verdict. */\n readonly reason?: string;\n}\n\n/**\n * The static criteria `runLLMEvaluation` runs, in stamp order — the\n * ONE list both the evaluator's coverage stamp and the harness's\n * bypass stamp derive from, so the two can never disagree on the set.\n * Tier 1 = binary pass/fail gates; tier 2 = fail/warn/pass quality.\n */\nexport const LLM_EVAL_STATIC_CRITERIA: ReadonlyArray<{ readonly criterion: string; readonly tier: 1 | 2 }> = [\n { criterion: \"functionality\", tier: 1 },\n { criterion: \"crash\", tier: 1 },\n { criterion: \"interactivity\", tier: 2 },\n { criterion: \"accessibility\", tier: 2 },\n { criterion: \"layout\", tier: 2 },\n { criterion: \"loading\", tier: 2 },\n { criterion: \"visual\", tier: 2 },\n];\n\n/**\n * Coverage rows for a cell where the evaluator was BYPASSED BY DESIGN\n * (never invoked) — one `not-applicable` row per static criterion, all\n * carrying `reason`. Harness exits that skip tier-1/2 evaluation stamp\n * this so the cell is neither a silent absence (field missing) nor\n * evidence. Same shape contract as `runLLMEvaluation`'s stamp: always\n * every criterion. Lives here (not in llm-evaluator) because the bypass\n * exit runs before the evaluator module is lazily loaded.\n */\nexport function notApplicableCoverage(reason: string): CriterionCoverage[] {\n return LLM_EVAL_STATIC_CRITERIA.map(({ criterion, tier }) => ({\n criterion,\n tier,\n status: \"not-applicable\",\n reason,\n }));\n}\n\n/** One contract-feedback round (ggui#1261): what bought it, and the source it was fed back on. */\nexport interface ContractFeedbackRecord {\n /** The exit-probe issue subcategories that bought the round, e.g. `runtime:prop-sensitivity:currentUser`. */\n readonly firedOn: readonly string[];\n /** The component source as it stood when the model was told — the round's BEFORE. */\n readonly sourceBefore: string;\n}\n\nexport interface EvalResult {\n issues: EvalIssue[];\n pass: string[];\n /**\n * Per-criterion coverage for this eval run — one row per static\n * criterion, ALWAYS all of them when present. Stamped by\n * `runLLMEvaluation` (`ran` / `skipped`) and by the harness on\n * evaluator-bypass exits (`not-applicable` + reason). The harness\n * carries it unchanged through every later re-stamp of this result.\n * Absent = coverage UNKNOWN (paths that predate the instrument, e.g.\n * `parseEvalResponse` replays) — never assume `ran`, never assume\n * bypass.\n */\n criteriaCoverage?: CriterionCoverage[];\n /**\n * Runtime-render probe execution meta. Stamped by the exit-decision\n * probe runner; absent on eval paths that never invoke the probe.\n */\n runtimeProbe?: RuntimeProbeMeta;\n /**\n * The probe-only round's repair record (ggui#1380) — present only when a\n * recoverable render crash bought the one repair turn. See\n * {@link RuntimeProbeRepair}. `runtimeProbe` beside it is the re-probe's\n * verdict when the repair compiled, else the pre-repair probe's.\n */\n runtimeProbeRepair?: RuntimeProbeRepair;\n /**\n * The contract-feedback round, when one fired this generation (ggui#1261):\n * which exit-probe findings bought it and the source as it stood when the\n * model was told. `runtimeProbe` and the `runtime:*` issues on this result\n * are the probe's verdict AFTER that round; `sourceBefore` beside the final\n * source is the round's before/after. Absent when no such round fired.\n */\n contractFeedback?: ContractFeedbackRecord;\n /**\n * Per-canvas visual verdicts. Stamped by the harness ONLY when the\n * visual leg ran with `visualEvaluation.canvases` set (arm-neutral —\n * the same judge in every design mode); absent on the single-shot\n * visual path and whenever the visual leg did not run. PNGs stay on\n * `runVisualEvaluation`'s own result (`VisualEvaluationResult.canvases[*].screenshotPng`),\n * never here — this object is serialized into reports.\n */\n visual?: VisualEvalSummary;\n /**\n * Whether the screenshot judge leg ran, was skipped (with the reason) or\n * was not configured — ALWAYS stamped by the harness's eval round\n * (ggui#1221), so a consumer can tell a clean visual run from a leg\n * that silently could not run. See {@link VisualCoverage}.\n */\n visualCoverage?: VisualCoverage;\n}\n\n/** One canvas's visual verdict, PNG-free — see `EvalResult.visual`. */\n/**\n * How one canvas's `score` was reached (ggui#1072): `k` vision calls on the\n * SAME captured frame, aggregated by `rule`. Always present — `k: 1` ⇒\n * `samples: [score]`, `sigma: 0`, `notes: [critique]` — so one shape serves\n * a single judgement and a median of many. `samples`/`notes` carry only the\n * calls the judge could parse (in call order); `k` stays the requested count,\n * so a short `samples` is visible on the row rather than filled in.\n */\nexport interface CanvasJudgeRecord {\n readonly k: number;\n readonly rule: 'median';\n readonly samples: number[];\n /** Population σ of `samples` (0 when one sample). */\n readonly sigma: number;\n /** The judge's per-canvas critique per sample — the words beside a swing. */\n readonly notes: string[];\n /**\n * ggui#1127 — the cause of each scoring sample whose answer failed to parse and was SALVAGED: its four dimensions\n * were recovered from the closed prefix, its issues kept only as far as they closed, its critique lost. One entry\n * per salvaged sample; absent when every sample parsed. The salvaged sample's score still counts.\n */\n readonly salvaged?: readonly JudgeSalvageCause[];\n /**\n * ggui#1127 — the criteria call's answer was salvaged. A salvage keeps no criteria, so that frame's judge rows read\n * \"not answered\" with this cause rather than a clean `n/a`. Absent when the call parsed or was not asked.\n */\n readonly criteriaSalvaged?: JudgeSalvageCause;\n /**\n * ggui#1687 — the model asked for, and every model the provider said answered this canvas's calls (scoring and\n * criteria), deduplicated. `served` is empty when no provider named one: unknown, never \"the requested model\".\n * When the request names an alias and the provider echoes the alias (measured on a hosted route, 125 of 125\n * canvases), `served` confirms the alias was honoured but cannot tell two snapshots behind it apart. A judge that\n * must is pinned to a dated snapshot id instead. With the alias, a snapshot change shows only as a step on a date in\n * the judge's pooled within-call spread, read by week. That is a read someone runs, not a monitor.\n */\n readonly models?: { readonly requested: string; readonly served: readonly string[] };\n}\n\n/**\n * ggui#1687 — what the criteria call's answer held, before resolution. A row the judge left unanswered reads `n/a`\n * either way; this says whether the call came back empty, cut, or with entries the parser had to drop.\n */\nexport interface CriteriaAnswerCounts {\n /** The answer carried a `criteria` array. `false`: absent or not an array, so no row was read from it. */\n readonly array: boolean;\n /** Entries in the array. */\n readonly received: number;\n /** Entries kept: an object with a string id and a verdict of pass, fail or n/a. */\n readonly kept: number;\n /** Entries dropped, by why. */\n readonly dropped: { readonly notObject: number; readonly badId: number; readonly badVerdict: number };\n}\n\n/**\n * ggui#1127 — why a judge answer that failed to parse had to be salvaged. `output-cap`: the provider reported it\n * stopped at the output cap. `malformed`: the provider reported a normal stop, so the answer ended but did not\n * parse. `stopped`: the provider stopped it for another reason it named (a safety stop, or one it reports as\n * other), so it is cut, not malformed. `unknown`: the provider or route reported no stop reason. Never inferred\n * from the answer's length.\n */\nexport type JudgeSalvageCause = \"output-cap\" | \"malformed\" | \"stopped\" | \"unknown\";\n\n/** ggui#1127 — salvaged judge answers across a canvas run, per leg, as N of M. */\nexport interface JudgeSalvageCounts {\n /** Scoring answers: `answers` = samples that parsed or were salvaged, `salvaged` = those salvaged. */\n readonly scoring: { readonly salvaged: number; readonly answers: number };\n /** Criteria calls: `answered` = calls that parsed or were salvaged, `salvaged` = those salvaged (criteria lost). */\n readonly criteria: { readonly salvaged: number; readonly answered: number };\n}\n\n// ─── Visual criteria (ggui#1436) ──────────────────────────────────────────\n// The judge's typed criteria block per canvas — report-only beside the score\n// until a later word flips a gate to it. Every field below is optional on the\n// stamps so yesterday's `eval.json` and an old judge answer still parse (N−1).\nimport type { FetchShape, LayoutShape, RenderShape, RiskTier, StateShape, WriteShape } from \"../classifier/axes.js\";\n\nexport type CriteriaSeverity = \"must\" | \"should\";\nexport type CriteriaVerdict = \"pass\" | \"fail\" | \"n/a\";\n/** The method that produces a verdict: an instrument's measurement, the vision judge off the frame, or a person's eye. */\nexport type CriteriaMethod = \"instrument\" | \"judge\" | \"human\";\n/** The method's readiness, as the bank's author wrote it — the only source of an `n/a` that is not the judge's own. */\nexport type CriteriaStatus = \"live\" | \"reference\" | \"planned\" | \"manual\";\n/**\n * How a criterion entered the selection: bank-level (`static`, an empty scope) or by the selector's\n * rules for this card (`context`). A model PROPOSING a criterion at judge time is RESERVED and not a\n * member until a consumer exists — it would be `should`-only, recorded verbatim, never a gate.\n */\nexport type CriteriaSource = \"static\" | \"context\";\nexport type CriteriaChroma = \"achromatic\" | \"chromatic\" | \"unknown\";\n/** The classifier's shape axes, as hashed into the set id. */\nexport interface CriteriaAxes {\n render: RenderShape;\n state: StateShape;\n writes: WriteShape;\n fetch: FetchShape;\n layout: LayoutShape;\n}\n/** The selector's inputs, stored with the verdict so a reader recomputes `criteriaSetId` from the record alone. */\nexport interface CriteriaContext {\n canvas: CanvasClass;\n hasActions: boolean;\n riskTier: RiskTier;\n axes: CriteriaAxes;\n chroma: CriteriaChroma;\n profilePresent: boolean;\n /** The harness's shell as named; `unknown` when the round carries none. */\n shell: string;\n /** The caller's item kind (a bootstrap mint's `hello`); hashed when present. */\n kind?: string;\n /** The styling preset in force (the profile's aesthetic id); a recipe is selected only under its preset. */\n preset?: string;\n}\n/** What was asked and why — recorded BEFORE the judge runs. Omission is the selector's decision. */\nexport interface CriteriaSelection {\n id: string;\n source: CriteriaSource;\n reason: string;\n}\n/** One criterion's verdict; `n/a` is the judge's answer (\"cannot read this off the frame\"), an unanswered id, a tie, or a method whose `status` is not live. */\nexport interface CriterionVerdict {\n id: string;\n severity: CriteriaSeverity;\n method: CriteriaMethod;\n status: CriteriaStatus;\n source: CriteriaSource;\n verdict: CriteriaVerdict;\n evidence: string;\n /**\n * ggui#1663 — a measured reading beside a judge row, REPORT-ONLY: the row's `verdict` stays the judge's, so this\n * changes no verdict, score or bar. Present only on rows an instrument answers beside the judge (`space.edge`).\n */\n instrument?: { verdict: CriteriaVerdict; evidence: string; id?: string };\n /**\n * #1765 — the rewritten edge rule (`space.edge.v2`), a SEPARATE instrument read beside v1 on the same capture,\n * REPORT-ONLY like `instrument`; `id` names the probe that produced it. Present only beside `space.edge`.\n */\n instrumentV2?: { verdict: CriteriaVerdict; evidence: string; id: string };\n}\n/** ggui#1687 — the criteria call as it came back: its answer's counts, ids it answered outside the bank, its stop. */\nexport interface CriteriaCallRecord {\n readonly answer: CriteriaAnswerCounts;\n /** Kept entries whose id names no row of the bank. */\n readonly unknownIds: number;\n /** The provider's normalized stop reason (`length` = the output cap); absent when it reported none. */\n readonly finishReason?: VisionFinishReason;\n}\nexport interface CriteriaBlock {\n /** sha256(bank version | selector version | canonical context), 16 hex — the block's own digest. */\n criteriaSetId: string;\n bankVersion: string;\n selectorVersion: string;\n context: CriteriaContext;\n selection: CriteriaSelection[];\n verdicts: CriterionVerdict[];\n /** ggui#1687 — the call that answered this block, when one did. Absent for a block resolved with no call. */\n call?: CriteriaCallRecord;\n}\n/** The roll-up across canvases; a `must` at `n/a` is listed, never counted as a pass. */\nexport interface CriteriaRollup {\n mustFailed: string[];\n shouldFailed: string[];\n mustNa: string[];\n}\n\n/** ggui#1492 — a host\"s frame round the inline card, as data. Colours are `#rrggbb`; the ring\"s `alpha` is 0..1. */\nexport interface HostInlineFrame {\n /** The frame\"s surface — what shows behind a transparent card, and under the floor\"s residual. */\n readonly surface: string;\n /** The room the frame sits in (the page ground round it). */\n readonly ground: string;\n readonly ring: { readonly widthPx: number; readonly color: string; readonly alpha: number };\n readonly radiusPx: number;\n /** The host\"s minimum frame height: a card shorter than it sits in a frame this tall, and the visitor sees the rest as void. */\n readonly minHeightPx?: number;\n}\n/** ggui#1492 — how a host presents one canvas: the label the judge is told, the page ground, and (the inline card only) its frame. */\nexport interface CanvasHostPresentation {\n readonly label: string;\n /** The page ground under a fill canvas\"s panel; the inline card\"s ground lives on its {@link HostInlineFrame}. */\n readonly ground?: string;\n readonly frame?: HostInlineFrame;\n}\n/** ggui#1492 — why the judge did not draw a canvas's host presentation. The codes are the lane reader's own. */\nexport type HostPresentationIgnoredReason = \"label_missing\" | \"color_not_hex\" | \"frame_off_inline\" | \"frame_malformed\" | \"ground_on_inline\";\n/**\n * ggui#1492 — what the judge DID with a canvas's host presentation, read from the judge itself: `applied` carries\n * the presentation it drew, `ignored` the reason it drew none. Absent when the caller supplied no presentation.\n */\nexport type CanvasPresentationOutcome =\n | { readonly status: \"applied\"; readonly applied: CanvasHostPresentation }\n | { readonly status: \"ignored\"; readonly reason: HostPresentationIgnoredReason };\n\nexport interface CanvasVisualSummary {\n canvas: CanvasClass;\n viewport: { width: number; height: number };\n /** The judge's weighted score at this canvas (0-100). */\n score: number;\n /** `score >= passThreshold`, and on the inline card: no overflow (ggui#1027). */\n passed: boolean;\n /** The document's scroll height at this canvas, CSS px; `null` when unmeasurable (ggui#1027). */\n contentHeight: number | null;\n /** `contentHeight > viewport.height` — measured on every canvas, judged per `canvasFitPolicy`. */\n overflow: boolean;\n /**\n * ggui#1120 — how far down the capture anything was painted: the last inked row over the measured\n * region's height (inside a drawn host panel's chrome on md/lg/xl), read from the screenshot's\n * pixels against their dominant colour. `0` is the blank the judge fails (`canvas-blank`); every\n * other value is reported, never scored. `null` when the capture could not be read.\n */\n inkRatio: number | null;\n /** How `score` was reached — always present (ggui#1072). */\n judge: CanvasJudgeRecord;\n /** ggui#1436 — the typed criteria block, when a bank was configured; report-only. */\n criteria?: CriteriaBlock;\n /** ggui#1492 — what the judge did with this canvas's host presentation, when one was supplied. */\n presentation?: CanvasPresentationOutcome;\n /**\n * How the judge composed the mount (ggui#1100): `'fill'` on every\n * fullscreen canvas — the served runtime's fit, the root stretched to\n * the frame; absent on the inline card, which keeps its natural height.\n */\n fit?: 'fill';\n}\n\n/**\n * ggui#1195 — the fit reading on the canvas whose policy FAILS an overflow\n * (the inline chat card): the box it was judged at (`ceiling` — the order's\n * declared viewport when one was carried, else the class box), whether that\n * box was declared, and how many px of content sit below it (0 = fits).\n * Present only when such a canvas was judged with a measurable height, so\n * the bar and the ledger read one number for \"does the hello fit\".\n */\nexport interface VisualFitStamp {\n readonly canvas: CanvasClass;\n readonly ceiling: { readonly width: number; readonly height: number };\n readonly declared: boolean;\n readonly overflowPx: number;\n}\n\n/** The visual leg's per-canvas summary — see `EvalResult.visual`. */\nexport interface VisualEvalSummary {\n /** Mean of the canvas scores (rounded). */\n score: number;\n /** Every canvas passed. */\n passed: boolean;\n canvases: CanvasVisualSummary[];\n /** ggui#1195 — see {@link VisualFitStamp}; absent when no fail-policy canvas was judged. */\n fit?: VisualFitStamp;\n /** The design tree the judge painted with (ggui#1042): `src` + `srcSha256` — `design@judge`. */\n design?: { readonly src: string; readonly srcSha256: string };\n /** The mode the judge's tokens were composed in, when the caller said (ggui#1076). */\n themeMode?: 'light' | 'dark';\n /** ggui#1436 — the criteria roll-up across canvases, when any canvas carries a block; report-only. */\n criteria?: CriteriaRollup;\n}\n\n// ─── Quality mode ──────────────────────────────────────────────────────────\n\nexport type QualityMode = \"fast\" | \"auto-improve\" | \"high-quality\";\n\nexport interface QualityConfig {\n quality: QualityMode;\n visualEval: boolean;\n maxCostPerGeneration: number;\n model?: { provider?: string; model?: string };\n}\n\nexport const DEFAULT_QUALITY_CONFIG: QualityConfig = {\n quality: \"fast\",\n visualEval: false,\n maxCostPerGeneration: 3,\n};\n\n// ─── Axis-check types ──────────────────────────────────────────────────────\n// The `AxisCheck` type vocabulary lives here. The check bodies\n// themselves (REGISTRY, per-axis implementations) live under\n// `./axis-checks/`.\n\nimport type { DataContract } from \"@ggui-ai/protocol\";\nimport type { JsonObject } from \"@ggui-ai/protocol\";\nimport type { AxisVector, Classification } from \"../classifier/axes.js\";\nimport type { AxisKey } from \"../fragments/index.js\";\n\nexport interface AxisCheckInput {\n sourceCode: string;\n compiledCode: string | null;\n contract?: DataContract;\n originalPrompt: string;\n /** Full classification — checks may read sibling axes. */\n classification: Classification;\n /**\n * Which triad produced the source. Checks that assert a design-package\n * component (e.g. `layout.multi_step.stepper_adopted`) read it and\n * stand down in `free` mode, where the primitive is optional. Absent\n * means `constrained`.\n */\n designMode?: DesignMode;\n /**\n * The rendering canvas the source is judged FOR (ggui#1117). A width cap on\n * the outermost element is a defect on a fullscreen canvas and a no-op in a\n * chat bubble, so a check that reads width must know the surface. Populated\n * where the harness is built (`Harness.canvas`); ABSENT for callers with no\n * rendering context — a check handles `undefined`, it never assumes a\n * default (a silent `lg` would be the same guess with a nicer face).\n */\n canvas?: CanvasClass;\n /**\n * The props the probe and the judge RENDERED the source with (ggui#1285) — a bootstrap order's\n * `sampleProps`, the bench commit's fixture. They are judging data, not the request: a literal in\n * the source that equals one of these values, and that the request never stated, is baked copy a\n * visitor sees whenever the agent leaves the prop out. Populated on the served loop and at\n * auto-commit; ABSENT where the caller has none — the check stands down, it never guesses.\n */\n fixtureProps?: JsonObject;\n}\n\n/**\n * A gated check. Runs only when the classification's axis value matches\n * one of the gate's accepted values. Multiple gates (implicit AND) support\n * cross-axis combinations.\n */\nexport interface AxisCheck {\n /** Stable id used in issue subcategories. */\n id: string;\n /** Primary axis this check gates on. */\n axis: AxisKey;\n /** Which values of that axis activate the check. */\n values: readonly string[];\n /** Optional extra gate on a sibling axis (e.g., only when state=merge AND writes=per-item). */\n and?: { axis: AxisKey; values: readonly string[] };\n /** Execute the check and emit zero or more issues. */\n run(input: AxisCheckInput): EvalIssue[];\n}\n\n/**\n * Whether a check's gate(s) match the given axis vector. Pure function,\n * no issue emission.\n */\nexport function matches(vector: AxisVector, check: AxisCheck): boolean {\n const primary = vector[check.axis] as string;\n if (!check.values.includes(primary)) return false;\n if (check.and) {\n const sibling = vector[check.and.axis] as string;\n if (!check.and.values.includes(sibling)) return false;\n }\n return true;\n}\n\n// ─── Purely-typed helpers ──────────────────────────────────────────────────\n\n/**\n * Map a tier-0 issue category to the canonical P0/P1/P2 priority.\n *\n * Sourced from the criteria priority assignments:\n * - P0 (must): compile, security, imports, contract, types, mode\n * - P1 (safety): tokens, crash, functionality\n * - P2 (quality): interactivity, accessibility, layout, loading, visual\n */\nexport function priorityForIssue(category: EvalCategory): Priority {\n if (\n category === \"interactivity\" ||\n category === \"accessibility\" ||\n category === \"layout\" ||\n category === \"loading\" ||\n category === \"visual\"\n ) {\n return \"P2\";\n }\n if (category === \"tokens\" || category === \"crash\" || category === \"functionality\") {\n return \"P1\";\n }\n // compile, security, imports, contract, types, mode → P0.\n return \"P0\";\n}\n\n/** Whether any issue blocks shipping (has result = 'fail'). */\nexport function isBlocked(result: EvalResult): boolean {\n return result.issues.some((i) => i.result === \"fail\");\n}\n\n/**\n * Return the issues the agent should act on, depending on quality mode.\n * - fast: only fails (blocking issues)\n * - auto-improve / high-quality: fails + warns\n */\nexport function getActionableIssues(result: EvalResult, mode: QualityMode): EvalIssue[] {\n if (mode === \"fast\") {\n return result.issues.filter((i) => i.result === \"fail\");\n }\n return result.issues.filter((i) => i.result === \"fail\" || i.result === \"warn\");\n}\n\n// ─── Criteria (single source of truth for coding + eval sides) ─────────────\n//\n// Each criterion is defined ONCE with both sides of the contract:\n// - codingGuidance: what the coding agent should DO\n// - evalInstruction: what the eval agent should CHECK\n// They must be compatible — changing one means reviewing the other.\n//\n// This is *validated* shipping content: it's what the hosted runtime sends\n// to every generation today. External OSS implementers building their own\n// prompts should be able to use the same rubric — hence it's open.\n\nexport interface EvalCriterion {\n /** Unique identifier matching the eval tool name (e.g., 'functionality') */\n id: string;\n /** Human-readable name shown to both agents */\n name: string;\n /** Priority tier — P0 must, P1 should, P2 nice */\n priority: Priority;\n /** What the coding agent should DO to satisfy this criterion */\n codingGuidance: string;\n /** What the eval agent should CHECK — the evaluation prompt */\n evalInstruction: string;\n /** Tier 0 = programmatic, Tier 1 = LLM critical, Tier 2 = LLM quality */\n tier: 0 | 1 | 2;\n /** Eval outcome when this criterion fails */\n failOutcome: \"fail\" | \"warn\";\n}\n\nexport const CRITERIA: readonly EvalCriterion[] = [\n // ── P0: Correctness (must satisfy — failure = broken component) ──\n\n {\n id: \"compile\",\n name: \"Compile & type-check\",\n priority: \"P0\",\n tier: 0,\n failOutcome: \"fail\",\n codingGuidance:\n \"Code must compile. The typed Props and wire hook generics are enforced by the compiler.\",\n evalInstruction: \"Checked automatically by esbuild + TypeScript. No LLM evaluation needed.\",\n },\n {\n id: \"render-props\",\n name: \"Render all Props fields\",\n priority: \"P0\",\n tier: 0,\n failOutcome: \"warn\",\n codingGuidance: \"Render every Props field in JSX. Access via props.fieldName.\",\n evalInstruction:\n \"Check that every field from interface Props appears as props.fieldName in the function body.\",\n },\n {\n id: \"wire-hooks\",\n name: \"Wire all contract hooks\",\n priority: \"P0\",\n tier: 0,\n failOutcome: \"warn\",\n codingGuidance:\n \"Wire every useAction/useStream and every clientCapabilities.gadgets hook (e.g., useGeolocation) to a UI element. `agentCapabilities.tools` is a catalog the AGENT invokes — NOT a component hook surface.\",\n evalInstruction:\n \"Check that every hook variable from the boilerplate appears in the JSX or an effect.\",\n },\n {\n id: \"imports\",\n name: \"Valid imports only\",\n priority: \"P0\",\n tier: 0,\n failOutcome: \"fail\",\n codingGuidance: \"Only import from react, @ggui-ai/design/*, and @ggui-ai/wire.\",\n evalInstruction: \"Flag any import from a package not in the allowlist.\",\n },\n {\n id: \"security\",\n name: \"No eval/fetch/window\",\n priority: \"P0\",\n tier: 0,\n failOutcome: \"fail\",\n codingGuidance: \"Never use eval(), fetch(), or window. Data comes from props and hooks.\",\n evalInstruction: \"Flag any call to eval(), fetch(), or window access.\",\n },\n\n // ── P1: Safety (should satisfy — failure = crash or bad UX) ──\n\n {\n id: \"functionality\",\n name: \"All features implemented\",\n priority: \"P1\",\n tier: 1,\n failOutcome: \"fail\",\n codingGuidance: \"Implement ALL features from the request AND the data contract.\",\n evalInstruction: `Evaluate FUNCTIONALITY: Does this component implement ALL features from the request AND the data contract?\n\nCheck against BOTH sources:\n1. Original request — each feature must be coded AND rendered in JSX\n2. Data contract (if present) — verify:\n - Props fields are rendered in the UI. EXCEPTION: pure identifier fields (\\`id\\`, \\`*Id\\`, keys) that exist only to be echoed back inside an action payload do NOT need to be visibly rendered.\n - ALL useAction hooks are wired to clickable UI elements\n - ALL useStream hooks are consumed — the streamed data must reach the UI. Merging stream events into rendered state (a list, a counter, the displayed records) COUNTS as consuming the stream; it need not be a literal \\`.latest\\` render.\n - ALL clientCapabilities gadgets are used. \\`clientCapabilities.gadgets\\` is keyed by npm package: built-in browser capabilities (useGeolocation / useCamera / …) import from @ggui-ai/gadgets; registered third-party gadgets (e.g. useChartTheme) import from their OWN package. Any gadget the contract declares IS a contract feature — NEVER flag it as \"not part of the contract\".\n - \\`agentCapabilities.tools\\` is a catalog declaration only; do NOT flag missing component-side calls for it\n\nA contract hook that is declared but never used at all is a MISSING feature.\n\nCRITICAL: The \"issues\" array must ONLY contain features you are CERTAIN are missing or broken — never an implemented feature. (See \"Issue-array discipline\" above: no speculative, self-negating, or \"verify that…\" entries.)`,\n },\n {\n id: \"crash\",\n name: \"No crash scenarios\",\n priority: \"P1\",\n tier: 1,\n failOutcome: \"fail\",\n codingGuidance:\n \"Guard optional props (props.field?.x). stream.latest is T|null — always null-guard. .all is always an array.\",\n evalInstruction: `Evaluate CRASH SAFETY: Are there ACTUAL runtime crash scenarios?\n\nWILL crash (include in issues):\n- .map()/.filter()/.length on an uninitialized variable\n- Accessing property of undefined without guard\n- useStream().latest.field WITHOUT null guard — .latest is T | null\n- Optional Props field accessed as props.field.x without guard\n- Array item optional field: items.map(item => item.priority.toUpperCase()) when priority is optional\n\nSAFE (do NOT include):\n- Optional chaining: props.items?.map() — SAFE\n- Fallback: items || [] — SAFE\n- useState initializer: useState([]) — SAFE\n- Null check: items && items.map() — SAFE\n- stream.latest && stream.latest.field — SAFE, guarded\n- stream.all.map(...) — SAFE, .all is always an array\n- stream.all.length — SAFE, always a number\n\nThe \"issues\" array is ONLY for a specific line that WILL throw at runtime. NEVER put a line you have determined is safe into the issues array — not even to note that it is safe (\"…so this is safely guarded\", \"…so there is no crash\"). If you cannot name a concrete line that will throw, the answer is {\"pass\": true} — return that and an empty issues array.`,\n },\n {\n id: \"tokens\",\n name: \"Design system tokens\",\n priority: \"P1\",\n tier: 0,\n failOutcome: \"warn\",\n codingGuidance:\n \"Use CSS variables for colors (var(--ggui-color-*)); use the spacing scale for gap/padding/margin (gap=\\\"md\\\", padding=\\\"lg\\\").\",\n evalInstruction:\n \"Flag hardcoded hex colors, rgba/hsl functions, and numeric or raw-CSS-length spacing props. A t-shirt-scale spacing name (gap=\\\"md\\\") IS a token — never flag it.\",\n },\n\n // ── P2: Quality (nice to have — failure = lower score, not broken) ──\n\n {\n id: \"interactivity\",\n name: \"Sufficient interactive elements\",\n priority: \"P2\",\n tier: 2,\n failOutcome: \"warn\",\n codingGuidance: \"Add appropriate interactive elements for the component purpose.\",\n evalInstruction: `Evaluate INTERACTIVITY: Does this component have sufficient interactive elements?\n\nConsider: forms need submit buttons, lists need selection, editable content needs save/cancel.\nContract actions (if present): every useAction hook should be triggered by a visible UI element.\n\nOnly list MISSING interactive elements. Use 'fail' only for issues blocking core purpose.`,\n },\n {\n id: \"accessibility\",\n name: \"Accessible markup\",\n priority: \"P2\",\n tier: 2,\n failOutcome: \"warn\",\n codingGuidance:\n \"Add labels on form inputs, alt text on images, semantic HTML, and state ARIA (aria-checked/pressed/selected/expanded) on hand-rolled interactive controls.\",\n evalInstruction: `Evaluate ACCESSIBILITY: missing labels, alt text, semantic HTML, keyboard support, ARIA state.\n\nggui primitives bake in their own ARIA — see \"Primitive Accessibility\" in the Design System context above. NEVER flag a ggui primitive (Input/Select/TextArea, RadioGroup, Checkbox, Toggle, Progress, Slider, Spinner, Skeleton, Tabs, Accordion, Alert, Toast, Tooltip, Clickable, Icon) for a missing role / aria-* / label / keyboard handler — it is already there and not visible in the source you are reading.\n\nFlag ONLY real gaps: a raw div/span used as an interactive control; a hand-rolled control whose checked/selected/expanded/pressed state is conveyed only by styling (strikethrough, color, a check icon) with no \\`aria-checked\\` / \\`aria-pressed\\` / \\`aria-selected\\` / \\`aria-expanded\\`; an image with no alt text; an Input/Select/TextArea with no \\`label\\` prop; an icon-only Button with no aria-label; live/streaming data not wrapped in an aria-live region; inverted heading hierarchy.\n\nOnly list MISSING accessibility features. Use 'fail' only if it blocks delivery.`,\n },\n {\n id: \"layout\",\n name: \"Clean layout\",\n priority: \"P2\",\n tier: 2,\n failOutcome: \"warn\",\n codingGuidance: \"Use proper spacing and visual grouping.\",\n evalInstruction: `Evaluate LAYOUT: Check spacing, alignment, visual grouping, and composition.\n\nOnly list ACTUAL layout problems. Use 'fail' only for fundamentally broken layouts.`,\n },\n {\n id: \"loading\",\n name: \"Loading/empty/error states\",\n priority: \"P2\",\n tier: 2,\n failOutcome: \"warn\",\n codingGuidance: \"Handle async data, empty collections, and error cases.\",\n evalInstruction: `Evaluate LOADING/EMPTY/ERROR STATES: Does the component handle async data and edge cases?\n\nContract-specific: useStream should handle pre-data state. clientCapabilities hooks may return undefined / permission-denied — defensive guards expected before threading values into JSX.\nProps-only components (no async, no streams, no client capabilities) do NOT need loading states — return pass.\n\nOnly list MISSING states.`,\n },\n {\n id: \"visual\",\n name: \"Design system consistency\",\n priority: \"P2\",\n tier: 2,\n failOutcome: \"warn\",\n codingGuidance: \"Use design system tokens consistently.\",\n evalInstruction: `Evaluate VISUAL CONSISTENCY: Is the component using the design system correctly?\n\nFlag: hardcoded colors instead of CSS variables, numeric or raw-CSS-length spacing instead of the t-shirt scale, style objects bypassing design system.\nA t-shirt-scale spacing name (gap=\"md\", padding=\"lg\") IS correct token usage — never flag it.\nIntentional custom colors (status indicators) are acceptable when no semantic token fits.\n\nOnly list ACTUAL violations. Use 'fail' only for pervasive violations.`,\n },\n] as const;\n\n/**\n * `designMode: 'free'` overrides — ONLY the two criteria whose text\n * encodes the design vocabulary. `tokens` narrows to COLOR (the free arm\n * relaxes spacing / typography / radius / shadow to literals but keeps\n * brand-bearing color on the closed `--ggui-color-*` manifest, no\n * fallbacks); `visual` becomes arm-neutral (composition, hierarchy,\n * consistency, fit to canvas — no reward or penalty for design-system\n * usage). Every other criterion is shared verbatim between the modes.\n * Constraint alignment: what the free prompt says, the free evaluator\n * checks — and nothing more.\n */\nconst FREE_DESIGN_CRITERIA_OVERRIDES: readonly EvalCriterion[] = [\n {\n id: \"tokens\",\n name: \"Color tokens\",\n priority: \"P1\",\n tier: 0,\n failOutcome: \"warn\",\n codingGuidance:\n \"Every color is a bare var(--ggui-color-*) from the token manifest — no hex, rgb()/hsl(), CSS named colors or literal fallbacks, in style props and <style> blocks alike. Spacing, typography, radius and shadow geometry may be literals.\",\n evalInstruction:\n \"Flag hardcoded hex colors, rgba/hsl functions, CSS named colors, and literal fallbacks inside var(--ggui-*) references. Do NOT flag literal spacing, font sizes, radii or pixel values — they are allowed in this mode.\",\n },\n {\n id: \"visual\",\n name: \"Visual composition\",\n priority: \"P2\",\n tier: 2,\n failOutcome: \"warn\",\n codingGuidance:\n \"Compose deliberately: one clear focal point, consistent spacing rhythm, a coherent theme-token palette, a fit to the rendering canvas.\",\n evalInstruction: `Evaluate VISUAL COMPOSITION: Is the component composed deliberately for its canvas?\n\nJudge: visual hierarchy (one clear focal point, headings distinct from body text), consistent spacing rhythm and alignment, a coherent palette drawn from the theme tokens, fit to the canvas (fluid width, no fixed widths, nothing cramped or stretched).\nDo NOT reward or penalise the use of design-system primitives — raw HTML with inline CSS is a first-class choice here. Literal spacing / typography / radius values are fine.\n\nOnly list ACTUAL composition problems. Use 'fail' only for a fundamentally incoherent composition.`,\n },\n];\n\n/**\n * The criteria registry for a design mode. `constrained` IS `CRITERIA`\n * (same array, byte-identical summary); `free` swaps in the two\n * overrides above by id, preserving order.\n */\nexport function criteriaFor(designMode: DesignMode = \"constrained\"): readonly EvalCriterion[] {\n if (designMode === \"constrained\") return CRITERIA;\n return CRITERIA.map(\n (c) => FREE_DESIGN_CRITERIA_OVERRIDES.find((o) => o.id === c.id) ?? c,\n );\n}\n\n/** Get all criteria for a specific priority level */\nexport function getCriteriaByPriority(\n priority: Priority,\n designMode: DesignMode = \"constrained\",\n): EvalCriterion[] {\n return criteriaFor(designMode).filter((c) => c.priority === priority);\n}\n\n/** Get a specific criterion by ID */\nexport function getCriterionById(\n id: string,\n designMode: DesignMode = \"constrained\",\n): EvalCriterion | undefined {\n return criteriaFor(designMode).find((c) => c.id === id);\n}\n\n/** Get all LLM-evaluated criteria (tier 1 + 2) */\nexport function getLLMCriteria(designMode: DesignMode = \"constrained\"): EvalCriterion[] {\n return criteriaFor(designMode).filter((c) => c.tier > 0);\n}\n\n/**\n * Build the coding agent's criteria summary from the single source of truth.\n * Grouped by priority for the P0→P1→P2 hierarchy.\n */\nexport function buildCodingCriteriaSummary(designMode: DesignMode = \"constrained\"): string {\n const lines: string[] = [\"## Priority (P0 first, then P1, then P2)\", \"\"];\n\n for (const priority of [\"P0\", \"P1\", \"P2\"] as Priority[]) {\n const label =\n priority === \"P0\"\n ? \"Must (compile + complete)\"\n : priority === \"P1\"\n ? \"Should (safety)\"\n : \"Nice (quality)\";\n const criteria = getCriteriaByPriority(priority, designMode);\n lines.push(`**${priority} — ${label}:**`);\n for (const c of criteria) {\n lines.push(`- ${c.codingGuidance}`);\n }\n lines.push(\"\");\n }\n\n return lines.join(\"\\n\");\n}\n"]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import Anthropic from '@anthropic-ai/sdk';
|
|
2
|
+
|
|
3
|
+
// src/adapters/claude/client.ts
|
|
4
|
+
function createAnthropicClient(rawKey) {
|
|
5
|
+
if (rawKey === void 0) {
|
|
6
|
+
return new Anthropic({
|
|
7
|
+
baseURL: "https://api.anthropic.com"
|
|
8
|
+
});
|
|
9
|
+
}
|
|
10
|
+
return new Anthropic({
|
|
11
|
+
apiKey: rawKey,
|
|
12
|
+
baseURL: "https://api.anthropic.com"
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export { createAnthropicClient };
|
|
17
|
+
//# sourceMappingURL=chunk-QLXXPGTV.js.map
|
|
18
|
+
//# sourceMappingURL=chunk-QLXXPGTV.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/adapters/claude/client.ts"],"names":[],"mappings":";;;AAuBO,SAAS,sBACd,MAAA,EACW;AACX,EAAA,IAAI,WAAW,MAAA,EAAW;AACxB,IAAA,OAAO,IAAI,SAAA,CAAU;AAAA,MACnB,OAAA,EAAS;AAAA,KACV,CAAA;AAAA,EACH;AACA,EAAA,OAAO,IAAI,SAAA,CAAU;AAAA,IACnB,MAAA,EAAQ,MAAA;AAAA,IACR,OAAA,EAAS;AAAA,GACV,CAAA;AACH","file":"chunk-QLXXPGTV.js","sourcesContent":["// packages/ui-gen/src/adapters/claude/client.ts\n//\n// SINGLE SOURCE OF TRUTH for Anthropic SDK construction.\n//\n// The BYOK resolver writes the raw credential string into\n// `process.env.ANTHROPIC_API_KEY`, which the Anthropic SDK auto-reads as\n// `x-api-key`. Adapters MUST go through `createAnthropicClient` (no\n// inline `new Anthropic(...)`) so future header / baseURL tweaks land\n// in one place.\n\nimport Anthropic from '@anthropic-ai/sdk';\n\n/**\n * Construct an Anthropic SDK client from a raw API key string.\n *\n * - `string` → standard `apiKey` path (sends `x-api-key`).\n * - `undefined` → still construct a client; SDK auto-reads\n * `process.env.ANTHROPIC_API_KEY` or throws on first call.\n *\n * **SINGLE SOURCE OF TRUTH for Anthropic client construction.** Every\n * adapter that constructs an Anthropic client MUST go through this\n * helper — no inline `new Anthropic(...)` allowed in adapter code.\n */\nexport function createAnthropicClient(\n rawKey: string | undefined,\n): Anthropic {\n if (rawKey === undefined) {\n return new Anthropic({\n baseURL: 'https://api.anthropic.com',\n });\n }\n return new Anthropic({\n apiKey: rawKey,\n baseURL: 'https://api.anthropic.com',\n });\n}\n"]}
|