@ggui-ai/ui-gen 0.24.0 → 0.26.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 (142) hide show
  1. package/README.md +2 -2
  2. package/dist/{adapter-Du7P_5Fx.d.ts → adapter-BJwn74rx.d.ts} +49 -1
  3. package/dist/adapters/generation-dispatch.d.ts +32 -7
  4. package/dist/adapters/generation-dispatch.js +1997 -216
  5. package/dist/adapters/generation-dispatch.js.map +1 -1
  6. package/dist/adapters/index.js +29 -6
  7. package/dist/adapters/index.js.map +1 -1
  8. package/dist/advanced/index.d.ts +15 -12
  9. package/dist/advanced/index.js +2013 -270
  10. package/dist/advanced/index.js.map +1 -1
  11. package/dist/{axes-CzLEMDeB.d.ts → axes-CKVCzR_x.d.ts} +1 -1
  12. package/dist/bank-Ctdp3FUA.d.ts +118 -0
  13. package/dist/blueprint-validator.js +416 -92
  14. package/dist/blueprint-validator.js.map +1 -1
  15. package/dist/boilerplate.d.ts +2 -2
  16. package/dist/boilerplate.js +34 -15
  17. package/dist/boilerplate.js.map +1 -1
  18. package/dist/check/index.d.ts +13 -5
  19. package/dist/check/index.js +56 -3
  20. package/dist/check/index.js.map +1 -1
  21. package/dist/classifier/index.d.ts +2 -2
  22. package/dist/compose.d.ts +2 -2
  23. package/dist/{create-ui-generator-GIhzx08x.d.ts → create-ui-generator-N4gRXpcL.d.ts} +11 -4
  24. package/dist/{design-mode-DLufhrNp.d.ts → design-mode-DGWN_Gkm.d.ts} +1 -1
  25. package/dist/{dispatch-BnAH56p4.d.ts → dispatch-BUoXRj_r.d.ts} +6 -4
  26. package/dist/evaluation/axis-checks/index.d.ts +7 -6
  27. package/dist/evaluation/axis-checks/index.js +90 -2
  28. package/dist/evaluation/axis-checks/index.js.map +1 -1
  29. package/dist/evaluation/axis-checks/registry.d.ts +6 -5
  30. package/dist/evaluation/axis-checks/registry.js +88 -1
  31. package/dist/evaluation/axis-checks/registry.js.map +1 -1
  32. package/dist/evaluation/index.d.ts +189 -344
  33. package/dist/evaluation/index.js +1272 -59
  34. package/dist/evaluation/index.js.map +1 -1
  35. package/dist/evaluation/types.d.ts +26 -1
  36. package/dist/evaluation/types.js.map +1 -1
  37. package/dist/fragments/index.d.ts +3 -3
  38. package/dist/{generate-9IeNT4ZY.d.ts → generate-tSO_shQ0.d.ts} +1 -1
  39. package/dist/harness/check/runtime-render/index.d.ts +7 -7
  40. package/dist/harness/check/runtime-render/index.js +416 -92
  41. package/dist/harness/check/runtime-render/index.js.map +1 -1
  42. package/dist/harness/check/runtime-render/render-check-worker.js +393 -88
  43. package/dist/harness/check/runtime-render/render-check-worker.js.map +1 -1
  44. package/dist/harness/index.d.ts +5 -6
  45. package/dist/harness/index.js +69 -20
  46. package/dist/harness/index.js.map +1 -1
  47. package/dist/harness/prompts.d.ts +2 -2
  48. package/dist/harness/prompts.js +10 -1
  49. package/dist/harness/prompts.js.map +1 -1
  50. package/dist/harness/result-types.d.ts +19 -5
  51. package/dist/harness/result-types.js.map +1 -1
  52. package/dist/harness/runtime.d.ts +21 -7
  53. package/dist/harness/runtime.js +36 -17
  54. package/dist/harness/runtime.js.map +1 -1
  55. package/dist/harness/types-public.d.ts +6 -4
  56. package/dist/harness/types-public.js +43 -18
  57. package/dist/harness/types-public.js.map +1 -1
  58. package/dist/harness/validator-trace-sink.d.ts +6 -5
  59. package/dist/hash.d.ts +1 -1
  60. package/dist/index.d.ts +64 -13
  61. package/dist/index.js +2023 -270
  62. package/dist/index.js.map +1 -1
  63. package/dist/patch.d.ts +5 -5
  64. package/dist/policy.d.ts +1 -1
  65. package/dist/{prompts-YU9piOgs.d.ts → prompts-BhNUuRoZ.d.ts} +1 -1
  66. package/dist/tools/get-primitives-ts.d.ts +1 -1
  67. package/dist/tools/get-primitives-ts.js +1 -1
  68. package/dist/tools/get-primitives-ts.js.map +1 -1
  69. package/dist/tools/render-check-worker.js +8 -1
  70. package/dist/tools/render-check-worker.js.map +1 -1
  71. package/dist/{types-BOvHNG7K.d.ts → types-Dh1s4K9j.d.ts} +1 -1
  72. package/dist/types-public-B7wn4ce5.d.ts +959 -0
  73. package/dist/validation/index.d.ts +1 -1
  74. package/dist/validation/index.js +1 -1
  75. package/dist/validation/index.js.map +1 -1
  76. package/dist/visual-evaluator-C9L-o6ap.d.ts +639 -0
  77. package/dist/workflows.d.ts +5 -5
  78. package/package.json +12 -12
  79. package/src/adapters/generation-dispatch.ts +38 -2
  80. package/src/adapters/tools.ts +2 -1
  81. package/src/boilerplate/free-design-prompt.ts +4 -4
  82. package/src/boilerplate/generate.ts +26 -1
  83. package/src/boilerplate/hard-sections.ts +14 -14
  84. package/src/boilerplate/system-prompt.ts +1 -1
  85. package/src/boilerplate/templates/layouts/chat-mobile.tsx.tmpl +3 -1
  86. package/src/boilerplate/templates/layouts/chat-universal.tsx.tmpl +3 -1
  87. package/src/boilerplate/templates/layouts/fullscreen-desktop.tsx.tmpl +3 -1
  88. package/src/boilerplate/templates/layouts/fullscreen-universal.tsx.tmpl +3 -1
  89. package/src/check/index.ts +1 -0
  90. package/src/check/run-tier0.ts +6 -3
  91. package/src/check/sample-props.ts +63 -0
  92. package/src/coding-agent/tools.ts +4 -1
  93. package/src/contract-context.ts +1 -1
  94. package/src/create-harness.ts +3 -3
  95. package/src/create-ui-generator.ts +20 -1
  96. package/src/evaluation/__fixtures__/png.ts +100 -0
  97. package/src/evaluation/axis-checks/checks/state-merge.ts +1 -1
  98. package/src/evaluation/axis-checks/checks/universal.ts +111 -0
  99. package/src/evaluation/axis-checks/dispatch.ts +4 -1
  100. package/src/evaluation/cost-tracker.ts +54 -6
  101. package/src/evaluation/criteria/bank.ts +85 -0
  102. package/src/evaluation/criteria/context.ts +52 -0
  103. package/src/evaluation/criteria/edge-probe.ts +286 -0
  104. package/src/evaluation/criteria/edge.ts +202 -0
  105. package/src/evaluation/criteria/resolve.ts +207 -0
  106. package/src/evaluation/criteria/select.ts +79 -0
  107. package/src/evaluation/index.ts +27 -0
  108. package/src/evaluation/ink-extent.ts +200 -0
  109. package/src/evaluation/judge-spend.ts +48 -0
  110. package/src/evaluation/theme-css.ts +12 -5
  111. package/src/evaluation/types-public.ts +221 -3
  112. package/src/evaluation/types.ts +19 -0
  113. package/src/evaluation/visual-evaluator.ts +853 -51
  114. package/src/harness/check/runtime-render/adapter.ts +18 -0
  115. package/src/harness/check/runtime-render/probe-pending.ts +111 -0
  116. package/src/harness/check/runtime-render/render-check-host.ts +10 -6
  117. package/src/harness/check/runtime-render/render-check-worker.ts +6 -3
  118. package/src/harness/check/runtime-render/render-check.ts +417 -133
  119. package/src/harness/check/runtime-render/walk.ts +200 -0
  120. package/src/harness/coding/assemble-result.ts +2 -0
  121. package/src/harness/coding/generate-task-runner.ts +30 -0
  122. package/src/harness/coding/init-session.ts +5 -3
  123. package/src/harness/coding/run-coding-turn.ts +12 -4
  124. package/src/harness/coding/run-eval-round.ts +82 -3
  125. package/src/harness/in-loop-evaluation.ts +39 -0
  126. package/src/harness/llm-router.ts +58 -1
  127. package/src/harness/result-types.ts +9 -0
  128. package/src/harness/runtime.ts +14 -0
  129. package/src/harness/types-public.ts +10 -1
  130. package/src/harness-tool-names.ts +38 -0
  131. package/src/index.ts +17 -0
  132. package/src/internal/verdict-line.ts +33 -0
  133. package/src/run-check.ts +2 -0
  134. package/src/taught-tokens.ts +32 -0
  135. package/src/tools/get-primitives-ts.ts +1 -1
  136. package/src/tools/get-wire.ts +1 -1
  137. package/src/tools/render-check-worker.ts +2 -1
  138. package/src/tools/render-check.ts +8 -67
  139. package/src/tools.ts +11 -1
  140. package/src/validation/primitives.ts +1 -1
  141. package/dist/llm-router-DwwUK1bz.d.ts +0 -265
  142. package/dist/types-public-Bk6d1WLN.d.ts +0 -451
@@ -198,6 +198,8 @@ export function createRuntimeRenderCheck(
198
198
  ...queuedField(queuedMs),
199
199
  renderMs: result.stats.renderMs,
200
200
  ...load,
201
+ // ggui#1398: report-only — carried to the probe's meta for the bench, never an issue.
202
+ ...(result.stats.pendingAffordance !== undefined ? { pendingAffordance: result.stats.pendingAffordance } : {}),
201
203
  };
202
204
  },
203
205
  };
@@ -376,6 +378,22 @@ export function toEvalIssue(issue: RenderCheckIssue): EvalIssue | null {
376
378
  : `input priming failed: ${diag.inputPriming.error}`
377
379
  );
378
380
  }
381
+ if (diag?.walk) {
382
+ // ggui#1652: how far the walk over the card's screens got, so a
383
+ // multi-step card reads differently from a control that never rendered.
384
+ const w = diag.walk;
385
+ const stopped = {
386
+ explored: "every reachable control pressed",
387
+ "press-cap": "stopped at the press cap",
388
+ deadline: "stopped at the time budget",
389
+ "no-mount": "the card could not be mounted for the walk",
390
+ }[w.stoppedBy];
391
+ const named = w.namedControlSeen
392
+ ? "a control naming the action rendered, but pressing it did not dispatch the action"
393
+ : "no screen rendered a control naming the action";
394
+ const last = w.lastPressed.length ? `; last pressed: ${w.lastPressed.join(", ")}` : "";
395
+ diagParts.push(`walk: ${w.presses} press(es) across ${w.screens} screen(s), ${stopped}; ${named}${last}`);
396
+ }
379
397
  const diagSuffix = diagParts.length ? ` [observed: ${diagParts.join("; ")}]` : "";
380
398
 
381
399
  switch (issue.check) {
@@ -0,0 +1,111 @@
1
+ /**
2
+ * ggui#1398 leg 3 — the render check's stand-in for the runtime's pending
3
+ * state, and the rule for "the control visibly changed".
4
+ *
5
+ * In a served card, the runtime marks an action pending when the card's
6
+ * dispatch of it commits, and clears it when the session's next frame lands;
7
+ * `useActionPending` reads that state through wire's `ActionPendingContext`.
8
+ * The probe has no transport and no next frame, so it marks an action pending
9
+ * right after its own synthetic click really fired the action, looks at the
10
+ * clicked control, then clears it: one dispatch, one answer.
11
+ */
12
+ import type { ActionPendingSource } from "@ggui-ai/wire";
13
+
14
+ /** An {@link ActionPendingSource} the probe drives by hand. */
15
+ export interface ProbePendingSource extends ActionPendingSource {
16
+ /** Mark `actionName` pending and notify subscribers. */
17
+ mark(actionName: string): void;
18
+ /** Clear every pending action (the "answer landed"), notifying only if something was pending. */
19
+ clear(): void;
20
+ }
21
+
22
+ export function createProbePendingSource(): ProbePendingSource {
23
+ const pending = new Set<string>();
24
+ const listeners = new Set<() => void>();
25
+ const notify = (): void => {
26
+ for (const listener of [...listeners]) listener();
27
+ };
28
+ return {
29
+ isPending: (actionName) => pending.has(actionName),
30
+ subscribe: (listener) => {
31
+ listeners.add(listener);
32
+ return () => {
33
+ listeners.delete(listener);
34
+ };
35
+ },
36
+ mark: (actionName) => {
37
+ pending.add(actionName);
38
+ notify();
39
+ },
40
+ clear: () => {
41
+ if (pending.size === 0) return;
42
+ pending.clear();
43
+ notify();
44
+ },
45
+ };
46
+ }
47
+
48
+ /** What a control shows, for a before/after comparison around a dispatch. */
49
+ export interface ControlLook {
50
+ /** Still in the document; `false` when the card replaced the control. */
51
+ readonly connected: boolean;
52
+ /** `disabled`, or `aria-disabled="true"`. */
53
+ readonly disabled: boolean;
54
+ /** `aria-busy="true"`. */
55
+ readonly ariaBusy: boolean;
56
+ /** The control's text. */
57
+ readonly text: string;
58
+ }
59
+
60
+ /**
61
+ * The DOM surface {@link lookOf} reads: the probe's `MinimalElement` plus
62
+ * the optional `isConnected` a live DOM node carries, and an input's live
63
+ * `value` (an `<input type="submit">` shows its label through it).
64
+ */
65
+ export interface LookableElement {
66
+ readonly tagName?: string;
67
+ readonly textContent: string | null;
68
+ getAttribute(name: string): string | null;
69
+ readonly isConnected?: boolean;
70
+ readonly value?: unknown;
71
+ }
72
+
73
+ export function lookOf(el: LookableElement): ControlLook {
74
+ return {
75
+ connected: el.isConnected !== false,
76
+ // React renders `disabled={true}` as `disabled=""`, so presence is the test.
77
+ disabled: el.getAttribute("disabled") !== null || el.getAttribute("aria-disabled") === "true",
78
+ ariaBusy: el.getAttribute("aria-busy") === "true",
79
+ text:
80
+ el.tagName?.toLowerCase() === "input"
81
+ ? String(typeof el.value === "string" ? el.value : (el.getAttribute("value") ?? ""))
82
+ : (el.textContent ?? ""),
83
+ };
84
+ }
85
+
86
+ /**
87
+ * Whether `work` settles within `ms`. It never cancels `work`; it only stops
88
+ * waiting for it, so a phase can give up on a card that stalls.
89
+ */
90
+ export async function settlesWithin(ms: number, work: Promise<unknown>): Promise<boolean> {
91
+ let timer: ReturnType<typeof setTimeout> | undefined;
92
+ const expired = new Promise<false>((resolve) => {
93
+ timer = setTimeout(() => resolve(false), Math.max(0, ms));
94
+ });
95
+ try {
96
+ return await Promise.race([work.then(() => true), expired]);
97
+ } finally {
98
+ if (timer !== undefined) clearTimeout(timer);
99
+ }
100
+ }
101
+
102
+ /**
103
+ * Whether the control visibly changed between two looks: it became disabled
104
+ * or busy, its text changed (whitespace aside), or the card replaced it.
105
+ */
106
+ export function lookChanged(before: ControlLook, after: ControlLook): boolean {
107
+ if (before.connected && !after.connected) return true;
108
+ if (!before.disabled && after.disabled) return true;
109
+ if (!before.ariaBusy && after.ariaBusy) return true;
110
+ return before.text.trim() !== after.text.trim();
111
+ }
@@ -46,6 +46,7 @@ import { runSandboxed } from '@ggui-ai/sandbox';
46
46
  import type { SandboxResult } from '@ggui-ai/sandbox';
47
47
  import type { ProbeHostLoad } from '../../../evaluation/types-public.js';
48
48
  import type { RenderCheckResult, RunRenderCheckInput } from './render-check.js';
49
+ import { parseVerdictLine } from '../../../internal/verdict-line.js';
49
50
 
50
51
  /**
51
52
  * The subprocess bounds of one isolated check (ggui#1380). They are
@@ -227,12 +228,9 @@ export function mapSandboxResultToCheckResult(
227
228
  t0,
228
229
  );
229
230
  }
230
- const stdout = result.stdout.trim();
231
- if (stdout.length === 0) {
232
- return unverified('render check worker exited without producing a verdict.', t0);
233
- }
231
+ let verdict: RenderCheckResult | undefined;
234
232
  try {
235
- return JSON.parse(stdout) as RenderCheckResult;
233
+ verdict = parseVerdictLine<RenderCheckResult>(result.stdout);
236
234
  } catch (err) {
237
235
  return unverified(
238
236
  `render check worker verdict was not valid JSON — ${
@@ -241,6 +239,10 @@ export function mapSandboxResultToCheckResult(
241
239
  t0,
242
240
  );
243
241
  }
242
+ if (verdict === undefined) {
243
+ return unverified('render check worker exited without producing a verdict.', t0);
244
+ }
245
+ return verdict;
244
246
  }
245
247
 
246
248
  /**
@@ -269,7 +271,9 @@ export async function runRenderCheckViaWorker(
269
271
  gracePeriodMs: bounds.gracePeriodMs,
270
272
  maxStdoutBytes: CHECK_STDOUT_CAP,
271
273
  nodeHeapMb: bounds.heapMb,
272
- stdin: JSON.stringify(input),
274
+ // ggui#1398: the check learns its own deadline, so its report-only
275
+ // pending phase can step aside instead of pushing it past the bound.
276
+ stdin: JSON.stringify({ ...input, deadlineAt: t0 + bounds.timeoutMs }),
273
277
  // NODE_ENV steers React's production vs development build — keep
274
278
  // parity with the caller; everything else stays on the sandbox's
275
279
  // default allowlist.
@@ -43,7 +43,8 @@ import { resolve as resolvePath } from 'node:path';
43
43
  import { fileURLToPath } from 'node:url';
44
44
  import * as esbuild from 'esbuild';
45
45
  import { runRenderCheckInProcess } from './render-check.js';
46
- import type { RunRenderCheckInput } from './render-check.js';
46
+ import type { RenderCheckResult, RunRenderCheckInput } from './render-check.js';
47
+ import { formatVerdictLine } from '../../../internal/verdict-line.js';
47
48
 
48
49
  async function readAllStdin(): Promise<string> {
49
50
  const chunks: Buffer[] = [];
@@ -53,8 +54,10 @@ async function readAllStdin(): Promise<string> {
53
54
  return Buffer.concat(chunks).toString('utf8');
54
55
  }
55
56
 
56
- function emit(value: unknown): void {
57
- process.stdout.write(`${JSON.stringify(value)}\n`);
57
+ function emit(value: RenderCheckResult): void {
58
+ // One prefixed line: the host reads the last such line, so a card that
59
+ // writes to stdout while it is checked cannot corrupt the verdict.
60
+ process.stdout.write(formatVerdictLine(value));
58
61
  }
59
62
 
60
63
  /**