@ggui-ai/ui-gen 0.8.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/dist/adapters/generation-dispatch.d.ts +18 -1
  2. package/dist/adapters/generation-dispatch.js +819 -1577
  3. package/dist/adapters/generation-dispatch.js.map +1 -1
  4. package/dist/adapters/index.js +28 -11
  5. package/dist/adapters/index.js.map +1 -1
  6. package/dist/advanced/index.d.ts +5 -3
  7. package/dist/advanced/index.js +838 -1579
  8. package/dist/advanced/index.js.map +1 -1
  9. package/dist/blueprint-validator.js +109 -3
  10. package/dist/blueprint-validator.js.map +1 -1
  11. package/dist/boilerplate.js +17 -4
  12. package/dist/boilerplate.js.map +1 -1
  13. package/dist/check/index.d.ts +1 -1
  14. package/dist/check/index.js +11 -1
  15. package/dist/check/index.js.map +1 -1
  16. package/dist/compose.js +5 -5
  17. package/dist/compose.js.map +1 -1
  18. package/dist/{create-ui-generator-GX7tvbyH.d.ts → create-ui-generator-CF0EL0Li.d.ts} +26 -1
  19. package/dist/{dispatch-Deo9qzrG.d.ts → dispatch-D75M-OfZ.d.ts} +1 -1
  20. package/dist/evaluation/axis-checks/index.d.ts +3 -3
  21. package/dist/evaluation/axis-checks/index.js +133 -1
  22. package/dist/evaluation/axis-checks/index.js.map +1 -1
  23. package/dist/evaluation/axis-checks/registry.d.ts +1 -1
  24. package/dist/evaluation/axis-checks/registry.js +133 -1
  25. package/dist/evaluation/axis-checks/registry.js.map +1 -1
  26. package/dist/evaluation/index.d.ts +46 -3
  27. package/dist/evaluation/index.js +410 -24
  28. package/dist/evaluation/index.js.map +1 -1
  29. package/dist/fragments/index.js +5 -5
  30. package/dist/fragments/index.js.map +1 -1
  31. package/dist/harness/check/runtime-render/index.d.ts +2 -2
  32. package/dist/harness/check/runtime-render/index.js +110 -3
  33. package/dist/harness/check/runtime-render/index.js.map +1 -1
  34. package/dist/harness/index.d.ts +5 -126
  35. package/dist/harness/index.js +292 -32
  36. package/dist/harness/index.js.map +1 -1
  37. package/dist/harness/llm-trace-sink.d.ts +1 -1
  38. package/dist/harness/llm-trace-sink.js.map +1 -1
  39. package/dist/harness/prompts.js +17 -3
  40. package/dist/harness/prompts.js.map +1 -1
  41. package/dist/harness/result-types.d.ts +1 -1
  42. package/dist/harness/runtime.d.ts +17 -1
  43. package/dist/harness/runtime.js +23 -8
  44. package/dist/harness/runtime.js.map +1 -1
  45. package/dist/harness/types-public.d.ts +1 -1
  46. package/dist/harness/types-public.js +22 -9
  47. package/dist/harness/types-public.js.map +1 -1
  48. package/dist/harness/validator-trace-sink.d.ts +1 -1
  49. package/dist/index.d.ts +5 -3
  50. package/dist/index.js +838 -1579
  51. package/dist/index.js.map +1 -1
  52. package/dist/llm-router-BEVtbAb9.d.ts +213 -0
  53. package/dist/patch.d.ts +1 -1
  54. package/dist/provider-adapter.d.ts +16 -6
  55. package/dist/provider-adapter.js.map +1 -1
  56. package/dist/providers/index.d.ts +54 -99
  57. package/dist/providers/index.js +13 -8
  58. package/dist/providers/index.js.map +1 -1
  59. package/dist/{render-check-CNZjHD5g.d.ts → render-check-BNYGVDJd.d.ts} +1 -1
  60. package/dist/{types-public-C36k1q6s.d.ts → types-public-DIpjC-OA.d.ts} +1 -1
  61. package/dist/validation/index.js +2 -2
  62. package/dist/validation/index.js.map +1 -1
  63. package/dist/workflows.d.ts +1 -1
  64. package/package.json +18 -18
  65. package/src/adapters/generation-dispatch.ts +28 -2
  66. package/src/adapters/openrouter/client.ts +2 -2
  67. package/src/adapters/openrouter/types.ts +10 -0
  68. package/src/boilerplate/generate.ts +10 -2
  69. package/src/boilerplate/json-schema-ts.ts +22 -2
  70. package/src/boilerplate/system-prompt.ts +4 -2
  71. package/src/compile.ts +1 -1
  72. package/src/contract-context.ts +10 -2
  73. package/src/create-ui-generator.ts +58 -11
  74. package/src/design-system-docs.ts +6 -4
  75. package/src/evaluation/axis-checks/checks/state-merge.ts +1 -1
  76. package/src/evaluation/axis-checks/checks/state-ui-affordance.ts +162 -0
  77. package/src/evaluation/axis-checks/checks/universal.ts +39 -0
  78. package/src/evaluation/axis-checks/registry.ts +2 -0
  79. package/src/evaluation/index.ts +11 -0
  80. package/src/evaluation/llm-evaluator.ts +26 -3
  81. package/src/evaluation/visual-evaluator.ts +49 -66
  82. package/src/fragments/realtime.ts +3 -3
  83. package/src/fragments/state.ts +2 -2
  84. package/src/harness/check/runtime-render/adapter.ts +18 -0
  85. package/src/harness/check/runtime-render/index.ts +8 -0
  86. package/src/harness/check/runtime-render/prepare-mockup.ts +14 -0
  87. package/src/harness/check/runtime-render/production-act-shim.ts +158 -0
  88. package/src/harness/check/runtime-render/render-check.ts +72 -1
  89. package/src/harness/coding/init-session.ts +4 -1
  90. package/src/harness/coding/run-eval-round.ts +67 -5
  91. package/src/harness/index.ts +1 -1
  92. package/src/harness/llm-router.ts +451 -27
  93. package/src/harness/llm-trace-sink.ts +2 -1
  94. package/src/harness/runtime.ts +15 -0
  95. package/src/index.ts +5 -5
  96. package/src/provider-adapter.ts +16 -6
  97. package/src/providers/bedrock.ts +89 -26
  98. package/src/providers/index.ts +16 -4
  99. package/src/tools/render-check.ts +19 -7
  100. package/src/validation/ui-compiler.ts +2 -2
@@ -48,10 +48,12 @@ These tokens adapt automatically to any theme (light, dark, branded). **ALWAYS u
48
48
  - Borders/dividers \u2192 \`var(--ggui-color-outline)\` or \`var(--ggui-color-outlineVariant)\`
49
49
 
50
50
  ### State Colors
51
- - var(--ggui-color-success) \u2014 success states
52
- - var(--ggui-color-warning) \u2014 warning states
53
- - var(--ggui-color-error) \u2014 error states, destructive actions
54
- - var(--ggui-color-info) \u2014 informational
51
+ Semantic families ship as SCALES; the \`500\` stop is the role color (per-mode brightness), \`50\` the tint, \`800\` the on-tint text:
52
+ - var(--ggui-color-success-500) \u2014 success states (tint bg: success-50, text on tint: success-800)
53
+ - var(--ggui-color-warning-500) \u2014 warning states (warning-50 / warning-800)
54
+ - var(--ggui-color-error-500) \u2014 error states, destructive actions (error-50 / error-800)
55
+ - var(--ggui-color-info-500) \u2014 informational (info-50 / info-800)
56
+ Prefer the primitives' \`tone="success|warning|error|info"\` prop over hand-written vars \u2014 it resolves to the same stops.
55
57
 
56
58
  ### IMPORTANT: Color Rules
57
59
  - **NEVER** use hardcoded hex colors. ONLY use var(--ggui-color-*) tokens.
@@ -487,6 +489,15 @@ function jsonSchemaTypeToTs(schema) {
487
489
  if (schema.enum?.length) {
488
490
  return schema.enum.map((v) => typeof v === "string" ? `'${v}'` : String(v)).join(" | ");
489
491
  }
492
+ if (Array.isArray(schema.type)) {
493
+ const { nullable: _nullable, ...rest } = schema;
494
+ const members = [...new Set(schema.type)].map(
495
+ (member) => jsonSchemaTypeToTs({ ...rest, type: member })
496
+ );
497
+ const unique = [...new Set(members)];
498
+ if (schema.nullable && !unique.includes("null")) unique.push("null");
499
+ return unique.join(" | ");
500
+ }
490
501
  let result;
491
502
  switch (schema.type) {
492
503
  case "string":
@@ -504,7 +515,8 @@ function jsonSchemaTypeToTs(schema) {
504
515
  case "array": {
505
516
  if (schema.items) {
506
517
  const itemType = jsonSchemaTypeToTs(schema.items);
507
- result = schema.items.type === "object" && schema.items.properties ? `Array<${itemType}>` : itemType.includes("|") ? `(${itemType})[]` : `${itemType}[]`;
518
+ const itemsDeclareObject = Array.isArray(schema.items.type) ? schema.items.type.includes("object") : schema.items.type === "object";
519
+ result = itemsDeclareObject && schema.items.properties ? `Array<${itemType}>` : itemType.includes("|") ? `(${itemType})[]` : `${itemType}[]`;
508
520
  } else {
509
521
  result = "unknown[]";
510
522
  }
@@ -637,13 +649,14 @@ function generateBoilerplate(_userPrompt, contract, shellType, screen, composedS
637
649
  const propsFields = [];
638
650
  const propsProperties = contract?.propsSpec?.properties ?? {};
639
651
  for (const [key, entry] of Object.entries(propsProperties)) {
640
- const required = entry.required !== false;
652
+ const required = entry.required === true;
641
653
  const nullable = entry.schema.nullable === true;
642
654
  const tsType = jsonSchemaTypeToTs(entry.schema);
643
655
  const fullType = nullable ? `${tsType} | null` : tsType;
644
656
  const parts = [];
645
657
  if (entry.description) parts.push(entry.description);
646
658
  if (entry.default !== void 0) parts.push(`(default: ${JSON.stringify(entry.default)})`);
659
+ if (!required) parts.push("(optional \u2014 the agent may omit it; guard or fall back)");
647
660
  const desc = parts.length > 0 ? ` // ${parts.join(" ")}` : "";
648
661
  propsFields.push(` ${key}${required ? "" : "?"}: ${fullType};${desc}`);
649
662
  }
@@ -1389,13 +1402,15 @@ A \`DataContract\` declares everything a GguiSession exchanges with the outside
1389
1402
 
1390
1403
  ## Defensive coding for absent / late-arriving data
1391
1404
 
1392
- Props arrive via \`ggui_update\` and may be partial on first render. Stream channels start empty and fill over time. Context slots start at their declared default (often \`null\`). **Never assume a field exists before you read it.**
1405
+ Props arrive at mount and may be partial on first render; later prop changes reach the SAME mounted component via \`ggui_amend\` (in-place repaint) on the live channel. Stream channels start empty and fill over time. Context slots start at their declared default (often \`null\`). **Never assume a field exists before you read it.**
1393
1406
 
1407
+ - **Optional contract props**: a \`Props\` field marked \`?\` in the boilerplate may be omitted by the agent ENTIRELY \u2014 the wire gate only enforces \`required: true\` entries, and the harness verifies your component with those props stripped. Guard them (\`?? default\`, \`?.\`, or an empty-state branch) from the FIRST render.
1394
1408
  - **Array iteration**: always default to \`[]\` before \`.map\`/\`.filter\`/\`.length\`. Use \`(props.items ?? []).map(...)\` not \`props.items.map(...)\`. Same for stream.all, stream.latest, etc.
1395
1409
  - **Object access**: optional-chain through nested fields. \`props.user?.name ?? 'Anonymous'\` not \`props.user.name\`.
1396
1410
  - **Number ops**: default before arithmetic. \`(props.count ?? 0) + 1\` not \`props.count + 1\`.
1397
1411
  - **Stream latest**: \`useStream\` returns \`{latest: T | null, all: T[], isComplete: boolean}\`. The default \`all\` is \`[]\` so it's safe to map; \`latest\` is null until the first frame arrives \u2014 guard before reading \`.foo\`.
1398
1412
  - **Stream reconciliation**: when a stream event carries an \`action\` discriminant (e.g. \`create | move | edit | delete\`), the channel is a CRUD feed \u2014 your handler MUST branch on EVERY value: append on \`create\`, drop on \`delete\`, replace-by-id on \`move\` / \`edit\`. Merging only the "edit" case silently loses created and deleted items. Reconcile into the SAME state that seeds from \`props\` (e.g. \`useState(() => props.tasks ?? [])\`) so the seed data and the live feed render as one list \u2014 and handle an event whose id is not yet present (a \`create\` for an unknown item) by inserting it, not ignoring it.
1413
+ - **Props re-sync on repaint**: props the agent owns are the source of truth for display \u2014 prefer rendering DIRECTLY from \`props\` (controlled, no local copy). When local optimistic state genuinely needs a prop seed (a click bumps a count before the agent confirms), it MUST re-sync on prop change \u2014 \`useEffect(() => setCount(props.count ?? 0), [props.count])\` \u2014 or a \`ggui_amend\` repaint applies the new props while the display keeps the stale local value. BAD: \`const [count, setCount] = useState(props.count ?? 0)\` alone. GOOD: the same seed + the one-line re-sync effect.
1399
1414
  - **Loading state**: while data is still absent, render \`<Skeleton>\` placeholders \u2014 never a blank screen. \`<Skeleton variant="text" />\` for a text line, \`variant="circle"\` for an avatar slot, default \`rect\` for a block.
1400
1415
  - **Empty state**: when a list or results array is empty, render \`<EmptyState title="\u2026" description="\u2026" />\` \u2014 a region that renders nothing when empty looks broken to the user.
1401
1416
 
@@ -1523,7 +1538,7 @@ Every value change is mirrored to the host LLM's context automatically (debounce
1523
1538
 
1524
1539
  **When NOT to use it.** Local UI state the contract did NOT declare \u2014 \`isDropdownOpen\`, hover flags, animation phase, ephemeral toggles. For those, use a plain \`useState\` directly. The runtime ignores undeclared state.
1525
1540
 
1526
- **\`contextSpec\` direction is one-way: client \u2192 agent.** The agent uses \`propsSpec\` (via \`ggui_update\`) and \`streamSpec\` (via the live channel) to push state TO the client. Don't try to write to the agent via \`contextSpec\` \u2014 there is no return path.
1541
+ **\`contextSpec\` direction is one-way: client \u2192 agent.** The agent uses \`propsSpec\` (via \`ggui_amend\` for in-place repaints of this mount, or \`ggui_update\` when it mints a new history card) and \`streamSpec\` (via the live channel) to push state TO the client. Don't try to write to the agent via \`contextSpec\` \u2014 there is no return path.
1527
1542
 
1528
1543
  **Schema mismatches drop silently.** If you set a value that doesn't match the slot's schema (e.g. a string into a \`{type: 'number'}\` slot), the runtime logs a dev \`console.warn\` and skips the post. Make sure your setter calls produce values that match the declared shape.
1529
1544