@ggui-ai/ui-gen 0.27.0 → 0.28.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/index.d.ts CHANGED
@@ -2,7 +2,7 @@ export { C as CreateUiGeneratorOptions, c as createUiGenerator, e as extractComp
2
2
  export { R as RuntimeRenderProbeConfig } from './adapter-h4_V69LI.js';
3
3
  import { Q as QualityConfig } from './types-public-h8IMnYuh.js';
4
4
  export { P as ProviderRetryInfo } from './types-public-h8IMnYuh.js';
5
- export { GenerationResult, SameExchangeBreak } from './harness/result-types.js';
5
+ export { GenerationResult, SameExchangeBreak, SameFailureBreak } from './harness/result-types.js';
6
6
  import { GeneratorBuild, UiGenerator } from '@ggui-ai/mcp-server-core';
7
7
  import { D as DesignMode } from './design-mode-DGWN_Gkm.js';
8
8
  export { b as CANVAS_BREAKPOINTS, c as CANVAS_CLASSES, d as CANVAS_DESCRIPTORS, e as CANVAS_VIEWPORTS, C as CanvasClass, f as CanvasDescriptor, g as CanvasDisplayMode, a as CanvasViewport, h as DEFAULT_DESIGN_MODE, i as DESIGN_MODES, j as canvasDisplayModeForShell, k as canvasForRendering, l as canvasForViewportWidth, m as describeCanvas } from './design-mode-DGWN_Gkm.js';
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@ import * as esbuild2 from 'esbuild';
3
3
  import { build } from 'esbuild';
4
4
  import Anthropic from '@anthropic-ai/sdk';
5
5
  import { EXPANDED_FRAME, getCssTokens, expandedFrameScrimDecls, fillFitRule, expandedFramePanelRule, FORBIDDEN_IMPORT_SPECIFIERS } from '@ggui-ai/design/rendering';
6
- import { listContractGadgets, HOOK_NAME_RE, classifyUi, MODEL_REGISTRY, modelRefOfRoute, isGeneratorId, DANGEROUS_PATTERNS as DANGEROUS_PATTERNS$1, resolveAppGadgets, APP_GENERATION_PROFILE_BOUNDS, STDLIB_GADGETS_PACKAGE, anthropicRejectsForcedToolChoice, normalizeAnthropicModelId, anthropicRejectsSamplingParams, isRecord } from '@ggui-ai/protocol';
6
+ import { listContractGadgets, HOOK_NAME_RE, classifyUi, MODEL_REGISTRY, modelRefOfRoute, isGeneratorId, DEFAULT_MODEL as DEFAULT_MODEL$1, DANGEROUS_PATTERNS as DANGEROUS_PATTERNS$1, resolveAppGadgets, APP_GENERATION_PROFILE_BOUNDS, STDLIB_GADGETS_PACKAGE, anthropicRejectsForcedToolChoice, normalizeAnthropicModelId, anthropicRejectsSamplingParams, isRecord } from '@ggui-ai/protocol';
7
7
  import fs, { existsSync, mkdtempSync, writeFileSync, rmSync, readFileSync, readdirSync, statSync } from 'fs';
8
8
  import { contentHash } from '@ggui-ai/protocol/content-hash';
9
9
  import ts4 from 'typescript';
@@ -4535,6 +4535,8 @@ var init_policy = __esm({
4535
4535
  function getBedrockModelId(model) {
4536
4536
  const BEDROCK_MAP = {
4537
4537
  "anthropic/claude-haiku-4-5": "us.anthropic.claude-haiku-4-5-20251001-v1:0",
4538
+ "anthropic/claude-haiku-5-5": "us.anthropic.claude-haiku-5-5",
4539
+ // listed ACTIVE in us-east-1 (ggui#1743)
4538
4540
  "anthropic/claude-sonnet-4-6": "us.anthropic.claude-sonnet-4-6",
4539
4541
  "anthropic/claude-opus-4-6": "us.anthropic.claude-opus-4-6-v1:0",
4540
4542
  // Claude 5-family (ggui#706, strings verified 2026-09-02 against
@@ -7051,10 +7053,16 @@ var dupe_break_exports = {};
7051
7053
  __export(dupe_break_exports, {
7052
7054
  SAME_EXCHANGE_BREAK_AT: () => SAME_EXCHANGE_BREAK_AT,
7053
7055
  SAME_EXCHANGE_NUDGE: () => SAME_EXCHANGE_NUDGE,
7056
+ SAME_FAILURE_BREAK_AT: () => SAME_FAILURE_BREAK_AT,
7057
+ SAME_FAILURE_NUDGE: () => SAME_FAILURE_NUDGE,
7058
+ SAME_FAILURE_NUDGE_AT: () => SAME_FAILURE_NUDGE_AT,
7059
+ clearWriteFailures: () => clearWriteFailures,
7054
7060
  computePatchFingerprint: () => computePatchFingerprint,
7055
7061
  createDupeBreakState: () => createDupeBreakState,
7056
7062
  errorClassBucket: () => errorClassBucket,
7057
- recordToolExchange: () => recordToolExchange
7063
+ failureSignatures: () => failureSignatures,
7064
+ recordToolExchange: () => recordToolExchange,
7065
+ recordWriteFailure: () => recordWriteFailure
7058
7066
  });
7059
7067
  function recordToolExchange(state, name, input, resultText) {
7060
7068
  const key = createHash("sha256").update(name).update("\0").update(JSON.stringify(input) ?? "undefined").update("\0").update(resultText).digest("hex");
@@ -7066,6 +7074,25 @@ function recordToolExchange(state, name, input, resultText) {
7066
7074
  }
7067
7075
  return state.consecutiveIdenticalExchanges;
7068
7076
  }
7077
+ function failureSignatures(resultText) {
7078
+ const norm = (text) => text.replace(/[0-9]+/g, "#").replace(/\s+/g, " ").trim();
7079
+ const violations = [...resultText.matchAll(/^\[[^\]\n]+\] [^\n]+/gm)].map((m) => norm(m[0]));
7080
+ if (violations.length > 0) return [...new Set(violations)];
7081
+ const rest = norm(resultText.replace(/^Committed [^\n]*\n/, ""));
7082
+ return rest.length > 0 ? [rest] : [];
7083
+ }
7084
+ function recordWriteFailure(state, resultText) {
7085
+ let top;
7086
+ for (const signature of failureSignatures(resultText)) {
7087
+ const repeats = (state.failureCounts.get(signature) ?? 0) + 1;
7088
+ state.failureCounts.set(signature, repeats);
7089
+ if (top === void 0 || repeats > top.repeats) top = { signature, repeats };
7090
+ }
7091
+ return top;
7092
+ }
7093
+ function clearWriteFailures(state) {
7094
+ state.failureCounts.clear();
7095
+ }
7069
7096
  function createDupeBreakState() {
7070
7097
  return {
7071
7098
  lastFailedPatchFingerprint: null,
@@ -7082,7 +7109,8 @@ function createDupeBreakState() {
7082
7109
  consecutiveBrokenApplies: 0,
7083
7110
  consecutiveNoToolCalls: 0,
7084
7111
  lastExchangeKey: null,
7085
- consecutiveIdenticalExchanges: 0
7112
+ consecutiveIdenticalExchanges: 0,
7113
+ failureCounts: /* @__PURE__ */ new Map()
7086
7114
  };
7087
7115
  }
7088
7116
  function errorClassBucket(errText) {
@@ -7107,11 +7135,14 @@ function computePatchFingerprint(changes, errText) {
7107
7135
  h.update(errBucket);
7108
7136
  return h.digest("hex");
7109
7137
  }
7110
- var SAME_EXCHANGE_BREAK_AT, SAME_EXCHANGE_NUDGE;
7138
+ var SAME_EXCHANGE_BREAK_AT, SAME_EXCHANGE_NUDGE, SAME_FAILURE_NUDGE_AT, SAME_FAILURE_BREAK_AT, SAME_FAILURE_NUDGE;
7111
7139
  var init_dupe_break = __esm({
7112
7140
  "src/harness/coding/dupe-break.ts"() {
7113
7141
  SAME_EXCHANGE_BREAK_AT = 3;
7114
7142
  SAME_EXCHANGE_NUDGE = "\n\n[harness] This is the SAME tool call with the SAME result as your previous turn \u2014 repeating it cannot produce new information. Use what you already have and emit an apply_changes (or scoped) call now; one more identical repeat terminates the run.";
7143
+ SAME_FAILURE_NUDGE_AT = 3;
7144
+ SAME_FAILURE_BREAK_AT = 5;
7145
+ SAME_FAILURE_NUDGE = "\n\n[harness] This same failure has now been reported for three of your patches. Changing other code does not clear it: re-read that check above and change exactly what it names. Two more reports of it end the run.";
7115
7146
  }
7116
7147
  });
7117
7148
 
@@ -7503,13 +7534,13 @@ Return your evaluation using the evaluate_${criterion} tool.`;
7503
7534
  function getDefaultEvalModel(provider) {
7504
7535
  switch (provider) {
7505
7536
  case "claude":
7506
- return "claude-haiku-4-5-20251001";
7537
+ return "claude-haiku-5-5";
7507
7538
  case "openai":
7508
7539
  return "gpt-5.6-luna";
7509
7540
  case "google":
7510
7541
  return "gemini-3.5-flash-lite";
7511
7542
  default:
7512
- return "claude-haiku-4-5-20251001";
7543
+ return "claude-haiku-5-5";
7513
7544
  }
7514
7545
  }
7515
7546
  function callTokens(response) {
@@ -9587,7 +9618,7 @@ function parseCriteriaAnswers(raw) {
9587
9618
  function getDefaultVisualModel(provider) {
9588
9619
  switch (provider) {
9589
9620
  case "claude":
9590
- return "claude-haiku-4-5-20251001";
9621
+ return "claude-haiku-5-5";
9591
9622
  case "google":
9592
9623
  return "gemini-3-flash-preview";
9593
9624
  }
@@ -11831,10 +11862,96 @@ function getInitialValuePropNames(contract) {
11831
11862
  }
11832
11863
  return names;
11833
11864
  }
11865
+ function objectLiteralKeysAt(src, open) {
11866
+ if (src[open] !== "{") return void 0;
11867
+ const keys = [];
11868
+ let depth = 0;
11869
+ let expectKey = true;
11870
+ for (let i = open; i < src.length; i++) {
11871
+ const c = src[i];
11872
+ if (c === '"' || c === "'" || c === "`") {
11873
+ let j = i + 1;
11874
+ while (j < src.length && src[j] !== c) j += src[j] === "\\" ? 2 : 1;
11875
+ if (depth === 1 && expectKey && /^\s*:/.test(src.slice(j + 1))) keys.push(src.slice(i + 1, j));
11876
+ i = j;
11877
+ expectKey = false;
11878
+ continue;
11879
+ }
11880
+ if (c === "{" || c === "[" || c === "(") {
11881
+ depth++;
11882
+ if (depth === 1) expectKey = true;
11883
+ continue;
11884
+ }
11885
+ if (c === "}" || c === "]" || c === ")") {
11886
+ depth--;
11887
+ if (depth === 0) return keys;
11888
+ continue;
11889
+ }
11890
+ if (depth !== 1) continue;
11891
+ if (c === ",") {
11892
+ expectKey = true;
11893
+ continue;
11894
+ }
11895
+ if (expectKey && /[A-Za-z_$]/.test(c ?? "")) {
11896
+ const m = /^([A-Za-z_$][\w$]*)\s*(:|,|\})/.exec(src.slice(i));
11897
+ if (m !== null && m[1] !== void 0) keys.push(m[1]);
11898
+ expectKey = false;
11899
+ }
11900
+ }
11901
+ return keys;
11902
+ }
11903
+ function callArgsAt(src, open) {
11904
+ const args = [];
11905
+ let depth = 0;
11906
+ let start = open + 1;
11907
+ for (let i = open; i < src.length; i++) {
11908
+ const c = src[i];
11909
+ if (c === '"' || c === "'" || c === "`") {
11910
+ let j = i + 1;
11911
+ while (j < src.length && src[j] !== c) j += src[j] === "\\" ? 2 : 1;
11912
+ i = j;
11913
+ continue;
11914
+ }
11915
+ if (c === "(" || c === "{" || c === "[") depth++;
11916
+ else if (c === ")" || c === "}" || c === "]") {
11917
+ depth--;
11918
+ if (depth === 0) {
11919
+ args.push(src.slice(start, i));
11920
+ return args;
11921
+ }
11922
+ } else if (c === "," && depth === 1) {
11923
+ args.push(src.slice(start, i));
11924
+ start = i + 1;
11925
+ }
11926
+ }
11927
+ return args;
11928
+ }
11929
+ function initialStateKeys(src, argStart, argText) {
11930
+ const lead = argText.length - argText.trimStart().length;
11931
+ let at = argStart + lead;
11932
+ let text = argText.trim();
11933
+ const lazy = /^\(\s*\)\s*=>\s*\(?\s*/.exec(text);
11934
+ if (lazy !== null) {
11935
+ at += lazy[0].length;
11936
+ text = text.slice(lazy[0].length);
11937
+ }
11938
+ if (text.startsWith("{")) return objectLiteralKeysAt(src, at) ?? [];
11939
+ const ident = /^([A-Za-z_$][\w$]*)\s*\)?\s*$/.exec(text);
11940
+ if (ident === null || ident[1] === void 0) return [];
11941
+ const decls = [...src.matchAll(new RegExp(`(?:const|let|var)\\s+${ident[1]}\\s*(?::[^=]{1,200})?=\\s*`, "g"))];
11942
+ const decl = decls.length === 1 ? decls[0] : void 0;
11943
+ if (decl === void 0) return [];
11944
+ return objectLiteralKeysAt(src, (decl.index ?? 0) + decl[0].length) ?? [];
11945
+ }
11834
11946
  function collectStateKeys(src) {
11835
11947
  const keys = /* @__PURE__ */ new Set();
11836
11948
  const varRe = /const\s*\[\s*(\w+)\s*,\s*(\w+)\s*\]\s*=\s*useState/g;
11837
11949
  for (const m of src.matchAll(varRe)) keys.add(m[1]);
11950
+ const contextRe = /const\s*\[\s*(\w+)\s*,\s*\w+\s*\]\s*=\s*useGguiContext\s*(?:<[^>]*>)?\s*\(\s*['"`](\w+)['"`]/g;
11951
+ for (const m of src.matchAll(contextRe)) {
11952
+ keys.add(m[1]);
11953
+ keys.add(m[2]);
11954
+ }
11838
11955
  const objRe = /useState(?:<[^>]*>)?\s*\(\s*\{([\s\S]*?)\}\s*\)/g;
11839
11956
  for (const m of src.matchAll(objRe)) {
11840
11957
  const keyRe = /(?:^|,)\s*(\w+)\s*:/g;
@@ -11845,6 +11962,16 @@ function collectStateKeys(src) {
11845
11962
  const keyRe = /(?:^|,)\s*(\w+)\s*:/g;
11846
11963
  for (const km of m[1].matchAll(keyRe)) keys.add(km[1]);
11847
11964
  }
11965
+ for (const m of src.matchAll(/\b(useState|useReducer)\s*(?:<[^>]*>)?\s*\(/g)) {
11966
+ const open = (m.index ?? 0) + m[0].length - 1;
11967
+ const args = callArgsAt(src, open);
11968
+ const which = m[1] === "useReducer" ? 1 : 0;
11969
+ const arg = args[which];
11970
+ if (arg === void 0) continue;
11971
+ let argStart = open + 1;
11972
+ for (let k = 0; k < which; k++) argStart += (args[k]?.length ?? 0) + 1;
11973
+ for (const key of initialStateKeys(src, argStart, arg)) keys.add(key);
11974
+ }
11848
11975
  return keys;
11849
11976
  }
11850
11977
  function mkIssue(subcategory, description, fix, result = "fail") {
@@ -12457,7 +12584,7 @@ function runNoHardcodedEntities(input) {
12457
12584
  mkIssue(
12458
12585
  "state.merge.no_hardcoded_entities",
12459
12586
  `Hardcoded entity array literal (multiple objects with "${idField}") in the component \u2014 entity data should come from state/props.`,
12460
- `Remove the literal array. Seed state from props.{entityProp} and merge updates via stream.`
12587
+ `Remove the literal array: this data comes from ${all.filter((e) => e.idField === idField).map((e) => `props.${e.name}`).join(" / ") || "props"}. Read it there (\`?? []\` for an absent value, never a literal default), seed state from it, and merge updates via stream.`
12461
12588
  )
12462
12589
  );
12463
12590
  }
@@ -18349,6 +18476,7 @@ async function assembleGenerationResult(input) {
18349
18476
  evalResult: telemetry.evalResult !== void 0 && telemetry.contractFeedback !== void 0 ? { ...telemetry.evalResult, contractFeedback: telemetry.contractFeedback } : telemetry.evalResult,
18350
18477
  // ggui#404 — present only when the same-exchange guard ended the run.
18351
18478
  ...telemetry.sameExchangeBreak !== void 0 ? { sameExchangeBreak: telemetry.sameExchangeBreak } : {},
18479
+ ...telemetry.sameFailureBreak !== void 0 ? { sameFailureBreak: telemetry.sameFailureBreak } : {},
18352
18480
  needsBackgroundImprovement,
18353
18481
  selfCheckPassed: telemetry.selfCheckPassed,
18354
18482
  timing,
@@ -19288,6 +19416,18 @@ Repeated error: ${errText}
19288
19416
  augmentedResultText += SAME_EXCHANGE_NUDGE;
19289
19417
  }
19290
19418
  }
19419
+ const isWrite = call.name === "apply_changes" || call.name === "rewrite";
19420
+ let repeatedFailure;
19421
+ if (ctx.dupeBreak && isWrite) {
19422
+ if (result.done) {
19423
+ clearWriteFailures(ctx.dupeBreak);
19424
+ } else {
19425
+ repeatedFailure = recordWriteFailure(ctx.dupeBreak, result.result);
19426
+ if (repeatedFailure?.repeats === SAME_FAILURE_NUDGE_AT) {
19427
+ augmentedResultText += SAME_FAILURE_NUDGE;
19428
+ }
19429
+ }
19430
+ }
19291
19431
  await codingAgent.sendToolResult([{
19292
19432
  callId: call.id,
19293
19433
  name: call.name,
@@ -19316,6 +19456,29 @@ Repeated error: ${errText}
19316
19456
  sameExchangeBreak: { tool: call.name, repeats: sameExchangeRepeats }
19317
19457
  };
19318
19458
  }
19459
+ if (repeatedFailure !== void 0 && repeatedFailure.repeats >= SAME_FAILURE_BREAK_AT) {
19460
+ const signature = repeatedFailure.signature.slice(0, 160);
19461
+ console.log(
19462
+ `[coding-agent] SAME_FAILURE_BREAK | tool=${call.name} | repeats=${repeatedFailure.repeats} | failure=${JSON.stringify(signature.slice(0, 80))} \u2014 terminating run (ggui#1791)`
19463
+ );
19464
+ return {
19465
+ control: "break",
19466
+ compiledCode: "",
19467
+ selfCheckPassed: false,
19468
+ outcome: void 0,
19469
+ phase: void 0,
19470
+ tokens,
19471
+ ...cacheTokens,
19472
+ llmMs,
19473
+ toolMs,
19474
+ lastResultText: augmentedResultText,
19475
+ lastDiffFailed: false,
19476
+ isEvalFeedback: false,
19477
+ iconNamesCache,
19478
+ preWarmedContext,
19479
+ sameFailureBreak: { signature, repeats: repeatedFailure.repeats }
19480
+ };
19481
+ }
19319
19482
  const turnDiffFailed = !!result.error && result.result.includes("DIFF");
19320
19483
  const isDiffFail = turnDiffFailed && !isPatchInvalid;
19321
19484
  const outcome = result.done ? "PASS" : isPatchInvalid ? "PATCH_INVALID" : isDiffFail ? "DIFF_FAIL" : "SELF_CHECK_FAIL";
@@ -20303,6 +20466,7 @@ function createTelemetry() {
20303
20466
  probeRepairTrigger: void 0,
20304
20467
  contractFeedback: void 0,
20305
20468
  sameExchangeBreak: void 0,
20469
+ sameFailureBreak: void 0,
20306
20470
  compiledCode: "",
20307
20471
  pairedSource: "",
20308
20472
  selfCheckPassed: false,
@@ -20358,6 +20522,7 @@ function absorbTurn(telemetry, turn) {
20358
20522
  else telemetry.counters.outcomes.selfCheckFail++;
20359
20523
  }
20360
20524
  if (turn.sameExchangeBreak !== void 0) telemetry.sameExchangeBreak = turn.sameExchangeBreak;
20525
+ if (turn.sameFailureBreak !== void 0) telemetry.sameFailureBreak = turn.sameFailureBreak;
20361
20526
  }
20362
20527
  function createGenerateTaskRunner(input) {
20363
20528
  const { session, params, classification, telemetry } = input;
@@ -21517,7 +21682,7 @@ function injectVariance(userPrompt, variance, options) {
21517
21682
  init_design_mode();
21518
21683
  init_provider_router();
21519
21684
  var DEFAULT_TIER = "default";
21520
- var DEFAULT_MODEL = "anthropic/claude-haiku-4-5";
21685
+ var DEFAULT_MODEL = DEFAULT_MODEL$1;
21521
21686
  function createUiGenerator(options = {}) {
21522
21687
  const {
21523
21688
  enableRuntimeRender = false,