@ggui-ai/ui-visual-tester 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.
@@ -19836,7 +19836,7 @@
19836
19836
  case "warning":
19837
19837
  case "error":
19838
19838
  case "info":
19839
- return `var(--ggui-color-${tone}, ${SEMANTIC_TONE_FALLBACK[tone]})`;
19839
+ return `var(--ggui-color-${tone}-500, ${SEMANTIC_TONE_FALLBACK[tone]})`;
19840
19840
  case "inverse":
19841
19841
  return "var(--ggui-color-surface, #ffffff)";
19842
19842
  case "inherit":
@@ -27817,7 +27817,7 @@
27817
27817
  }
27818
27818
 
27819
27819
  // ../protocol/dist/version.js
27820
- var PROTOCOL_VERSION = "draft-2026-06-12";
27820
+ var PROTOCOL_VERSION = "draft-2026-08-19";
27821
27821
  var PROTOCOL_SCHEMA_VERSION = PROTOCOL_VERSION;
27822
27822
  var CLIENT_SUPPORTED_VERSIONS = Object.freeze([
27823
27823
  PROTOCOL_SCHEMA_VERSION
@@ -42344,7 +42344,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
42344
42344
 
42345
42345
  // ../protocol/dist/gadgets/stdlib-gadgets.js
42346
42346
  var STDLIB_GADGETS_PACKAGE = "@ggui-ai/gadgets";
42347
- var STDLIB_GADGETS_VERSION = "0.8.0";
42347
+ var STDLIB_GADGETS_VERSION = "0.10.0";
42348
42348
  var STDLIB_GADGETS = [
42349
42349
  {
42350
42350
  package: STDLIB_GADGETS_PACKAGE,
@@ -42495,15 +42495,24 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
42495
42495
  // surface as `undefined` at runtime which JSON.stringify drops.
42496
42496
  external_exports.record(external_exports.string(), jsonValueSchema)
42497
42497
  ]));
42498
+ var jsonSchemaTypeNameSchema = external_exports.enum([
42499
+ "string",
42500
+ "number",
42501
+ "integer",
42502
+ "boolean",
42503
+ "array",
42504
+ "object",
42505
+ "null"
42506
+ ]);
42498
42507
  var jsonSchemaSchema = external_exports.lazy(() => external_exports.object({
42499
- type: external_exports.enum([
42500
- "string",
42501
- "number",
42502
- "integer",
42503
- "boolean",
42504
- "array",
42505
- "object",
42506
- "null"
42508
+ // Single type OR a draft-07 type array (`['string','null']` —
42509
+ // the canonical nullability form the enforced-props-schema
42510
+ // emission produces). Mirrors `JsonSchemaTypeName | JsonSchemaTypeName[]`
42511
+ // on the TS type — the zod and TS sides are an SSoT pair; widen
42512
+ // both or neither.
42513
+ type: external_exports.union([
42514
+ jsonSchemaTypeNameSchema,
42515
+ external_exports.array(jsonSchemaTypeNameSchema)
42507
42516
  ]).optional(),
42508
42517
  description: external_exports.string().optional(),
42509
42518
  enum: external_exports.array(jsonValueSchema).optional(),
@@ -42671,12 +42680,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
42671
42680
  }).strict();
42672
42681
  var appPublicEnvSchema = external_exports.record(external_exports.string().regex(PUBLIC_ENV_APP_KEY_RE), external_exports.string()).readonly();
42673
42682
  var dataContractSchema = external_exports.object({
42674
- propsSpec: propsSpecSchema.optional(),
42675
- actionSpec: actionSpecSchema.optional(),
42676
- streamSpec: streamSpecSchema.optional(),
42677
- contextSpec: contextSpecSchema.optional(),
42678
- agentCapabilities: agentCapabilitiesSpecSchema.optional(),
42679
- clientCapabilities: clientCapabilitiesSpecSchema.optional()
42683
+ propsSpec: propsSpecSchema.optional().describe("Initial render data: {description?, properties: {<name>: {schema: <JSON Schema>, required?: boolean, description?, default?, example?}}}. A prop is required at the wire gate ONLY when `required: true`; omitted \u21D2 optional (declare `required: true` for props the render must always pass)."),
42684
+ actionSpec: actionSpecSchema.optional().describe("User gestures the agent reacts to on its next turn: {<action>: {label: string (REQUIRED \u2014 button copy / accessible name), schema?: <payload JSON Schema>, description?, example?, icon?, confirm?, nextStep?: '<agentCapabilities.tools key>'}}. Every action is agent-routed; `nextStep` is a hint, not a dispatch."),
42685
+ streamSpec: streamSpecSchema.optional().describe("Live update channels the agent emits into: {<channel>: {schema: <JSON Schema>, description?, example?, mode?: append|replace, replay?: latest|all|none, complete?, source?: {tool, args?}}}. `source.tool` must be declared in agentCapabilities.tools."),
42686
+ contextSpec: contextSpecSchema.optional().describe("Observable client state the agent reads alongside each action: {<slot>: {schema: <JSON Schema>, description?, default?, debounceMs?, example?}}. State that needs no next-turn reasoning belongs here, not in actionSpec."),
42687
+ agentCapabilities: agentCapabilitiesSpecSchema.optional().describe("MCP tools the AGENT may call: {tools: {<bareToolName>: {toolInfo: {inputSchema (REQUIRED), description?, outputSchema?}, serverInfo?: {name, version?}, usage?, example?: {input, output}}}}. Key by the BARE tool name (after any `mcp__<server>__` prefix); the component never calls these."),
42688
+ clientCapabilities: clientCapabilitiesSpecSchema.optional().describe("Browser-capability gadgets the COMPONENT imports: {gadgets: {<npm package>: {<exportName>: {description?, usage?}}}} \u2014 `use`-prefixed export keys are hooks, PascalCase keys are components; version and transport resolve from the app's registered catalog, never on the wire.")
42680
42689
  }).passthrough();
42681
42690
 
42682
42691
  // ../protocol/dist/schemas/blueprint.js
@@ -42692,11 +42701,17 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
42692
42701
  userBlueprintSourceSchema,
42693
42702
  curatedBlueprintSourceSchema
42694
42703
  ]);
42704
+ var BLUEPRINT_VARIANCE_KEYS = ["persona", "aesthetic", "context", "seedPrompt"];
42695
42705
  var blueprintVarianceSchema = external_exports.object({
42696
42706
  persona: external_exports.string().optional().describe('Design persona, e.g. "minimalist" / "data-dense". Part of cache identity.'),
42697
42707
  aesthetic: external_exports.string().optional().describe('Visual aesthetic, e.g. "calm" / "ornate". Part of cache identity.'),
42698
42708
  context: external_exports.record(external_exports.string(), jsonValueSchema).optional().describe('Deliberate design-shaping signals (e.g. {situation:"sad"}) \u2014 part of cache identity. NOT for per-user runtime data; put that in propsSpec/contextSpec.'),
42699
42709
  seedPrompt: external_exports.string().optional().describe("Generation seed directive. Part of cache identity.")
42710
+ }, {
42711
+ // A rejection that teaches (ggui#523 item 2): the first live guest
42712
+ // turn sent `mood` and got a bare "Unrecognized key" — name the
42713
+ // legal set and where the misplaced intent belongs.
42714
+ error: (issue2) => issue2.code === "unrecognized_keys" ? `variance: unknown key(s) ${issue2.keys.map((k) => JSON.stringify(k)).join(", ")} \u2014 variance is EXACTLY {${BLUEPRINT_VARIANCE_KEYS.join(", ")}}; put tonal intent in \`aesthetic\`, and per-user runtime data in props / contextSpec, never in variance` : void 0
42700
42715
  }).strict();
42701
42716
  var blueprintSchema = external_exports.object({
42702
42717
  blueprintId: external_exports.string().min(1),
@@ -42757,15 +42772,17 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
42757
42772
  }).strict()
42758
42773
  ]);
42759
42774
  var jsonPatchSchema = external_exports.array(jsonPatchOpSchema);
42775
+ var BLUEPRINT_DRAFT_KEYS = ["contract", "variance", "generator"];
42760
42776
  var blueprintDraftObjectSchema = external_exports.object({
42761
42777
  contract: dataContractSchema,
42762
- variance: external_exports.object({
42763
- persona: external_exports.string().optional(),
42764
- aesthetic: external_exports.string().optional(),
42765
- context: external_exports.record(external_exports.string(), jsonValueSchema).optional(),
42766
- seedPrompt: external_exports.string().optional()
42767
- }).strict().optional(),
42778
+ // ONE declaration of the variance shape, protocol-wide: the same
42779
+ // schema (with its `.describe()` teaching and its legal-set
42780
+ // rejection message) that `blueprintMeta.variance` projects on the
42781
+ // way back out (ggui#523 item 1 — the mirror-of-a-mirror is gone).
42782
+ variance: blueprintVarianceSchema.optional(),
42768
42783
  generator: external_exports.string().optional()
42784
+ }, {
42785
+ error: (issue2) => issue2.code === "unrecognized_keys" ? `blueprintDraft: unknown key(s) ${issue2.keys.map((k) => JSON.stringify(k)).join(", ")} \u2014 a draft is EXACTLY {${BLUEPRINT_DRAFT_KEYS.join(", ")}}; \`intent\` is a top-level ggui_handshake field, not a draft field, and the four specs live INSIDE \`contract\`` : void 0
42769
42786
  }).strict();
42770
42787
  var blueprintDraftSchema = blueprintDraftObjectSchema;
42771
42788
  var blueprintMetaSchema = external_exports.object({
@@ -42827,6 +42844,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
42827
42844
  sessionId: external_exports.string().min(1).describe("GguiSession opaque id (UUID) \u2014 returned by ggui_render.")
42828
42845
  };
42829
42846
  var getSessionInputSchema = external_exports.object(getSessionInputShape);
42847
+ var getRenderSourceInputShape = {
42848
+ sessionId: external_exports.string().min(1).describe("GguiSession opaque id (UUID) \u2014 returned by ggui_render.")
42849
+ };
42850
+ var getRenderSourceInputSchema = external_exports.object(getRenderSourceInputShape);
42830
42851
  var listFeaturedBlueprintsInputShape = {};
42831
42852
  var listFeaturedBlueprintsInputSchema = external_exports.object(listFeaturedBlueprintsInputShape);
42832
42853
  var searchBlueprintsInputShape = {
@@ -42861,7 +42882,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
42861
42882
  * and the contract validators; variance feeds the variance axis
42862
42883
  * and rides through to the suggestion's `blueprintMeta`.
42863
42884
  */
42864
- blueprintDraft: blueprintDraftSchema.describe("Agent's draft: contract (required) + optional variance + optional generator slug hint. The server combines this with cached blueprints + validator outcomes to produce a three-mode suggestion (cache / agent / synth)."),
42885
+ blueprintDraft: blueprintDraftSchema.describe(`Agent's draft \u2014 a JSON OBJECT, never a JSON-encoded string (pass {contract: {...}}, not "{\\"contract\\":...}"; a string fails input validation with -32602). Fields: contract (required) + optional variance + optional generator slug hint. The server combines this with cached blueprints + validator outcomes to produce a three-mode suggestion (cache / agent / synth).`),
42865
42886
  /**
42866
42887
  * Skip blueprint-search on step-2 and route straight to validation
42867
42888
  * + (if validation passes) agent-mode suggestion against the draft.
@@ -42961,10 +42982,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
42961
42982
  "PRODUCTION_FAILED",
42962
42983
  "VALIDATION_ERROR",
42963
42984
  "NO_PLATFORM_KEY",
42964
- "NO_CREDENTIALS"
42985
+ "NO_CREDENTIALS",
42986
+ "GENERATION_QUEUE_OVERLOADED"
42965
42987
  ]);
42966
42988
  var renderErrorSchema = external_exports.object({
42967
- code: renderErrorCodeSchema.describe("Canonical failure class. PRODUCTION_FAILED: generation did not produce a component. VALIDATION_ERROR: a server-side precondition rejected the render before generation. NO_PLATFORM_KEY: the server's managed provider-key configuration has no key for the resolved route. NO_CREDENTIALS: no generation credentials are configured on the server."),
42989
+ code: renderErrorCodeSchema.describe("Canonical failure class. PRODUCTION_FAILED: generation did not produce a component. VALIDATION_ERROR: a server-side precondition rejected the render before generation. NO_PLATFORM_KEY: the server's managed provider-key configuration has no key for the resolved route. NO_CREDENTIALS: no generation credentials are configured on the server. GENERATION_QUEUE_OVERLOADED: the deployment's admission gate rejected the request before generation started (queue full or wait timed out) \u2014 not a failed attempt; safe to retry immediately."),
42968
42990
  message: external_exports.string().describe("Human-readable failure detail \u2014 fold into the next attempt or surface to the operator.")
42969
42991
  });
42970
42992
  var resourceReadErrorCodeSchema = external_exports.enum([
@@ -43022,33 +43044,78 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
43022
43044
  description: external_exports.string(),
43023
43045
  example: external_exports.string(),
43024
43046
  args: external_exports.object({
43025
- sessionId: external_exports.string()
43047
+ sessionId: external_exports.string(),
43048
+ // The per-call long-poll window in seconds. Carried on the hint
43049
+ // because consume's own default is 0 (single non-blocking
43050
+ // drain): an agent copying a timeout-less hint gets an instant
43051
+ // empty result and stops looping.
43052
+ timeout: external_exports.number()
43026
43053
  })
43027
- }).optional().describe("Recovery hint \u2014 when the rendered contract has actions, points the agent at ggui_consume({sessionId}) for the inbound action loop. Absent for pure-display renders.")
43054
+ }).optional().describe("Required-next-call hint \u2014 when the rendered contract has actions, points the agent at ggui_consume({sessionId, timeout}) for the inbound action loop. Absent for pure-display renders.")
43028
43055
  });
43029
43056
  var updateInputSchema = external_exports.discriminatedUnion("kind", [
43030
43057
  external_exports.object({
43031
43058
  sessionId: external_exports.string().describe("GguiSession opaque id (UUID) \u2014 returned by ggui_render."),
43032
43059
  kind: external_exports.literal("replace"),
43033
- props: external_exports.record(external_exports.string(), external_exports.unknown()).describe("Full replacement props map. New map IS the new state.")
43060
+ props: external_exports.record(external_exports.string(), external_exports.unknown()).describe("Full replacement props map. New map IS the new state, rendered as a NEW card (a new history entry). For an in-place repaint of the mounted card use ggui_amend.")
43034
43061
  }).strict(),
43035
43062
  external_exports.object({
43036
43063
  sessionId: external_exports.string().describe("GguiSession opaque id (UUID) \u2014 returned by ggui_render."),
43037
43064
  kind: external_exports.literal("merge"),
43038
- patch: external_exports.record(external_exports.string(), external_exports.unknown()).describe("RFC 7396 JSON Merge Patch \u2014 null deletes a key; arrays fully replace.")
43065
+ patch: external_exports.record(external_exports.string(), external_exports.unknown()).describe("RFC 7396 JSON Merge Patch \u2014 null deletes a key; arrays fully replace. The merged state renders as a NEW card (a new history entry). For an in-place repaint of the mounted card use ggui_amend.")
43066
+ }).strict()
43067
+ ]);
43068
+ var amendInputSchema = external_exports.discriminatedUnion("kind", [
43069
+ external_exports.object({
43070
+ sessionId: external_exports.string().describe("GguiSession opaque id (UUID) \u2014 returned by ggui_render."),
43071
+ kind: external_exports.literal("replace"),
43072
+ props: external_exports.record(external_exports.string(), external_exports.unknown()).describe("Full replacement props map, applied to the currently mounted card in place.")
43073
+ }).strict(),
43074
+ external_exports.object({
43075
+ sessionId: external_exports.string().describe("GguiSession opaque id (UUID) \u2014 returned by ggui_render."),
43076
+ kind: external_exports.literal("merge"),
43077
+ patch: external_exports.record(external_exports.string(), external_exports.unknown()).describe("RFC 7396 JSON Merge Patch \u2014 null deletes a key; arrays fully replace. Applied to the currently mounted card in place.")
43039
43078
  }).strict()
43040
43079
  ]);
43041
43080
  var updateOutputSchema = external_exports.object({
43042
43081
  sessionId: external_exports.string(),
43043
43082
  updated: external_exports.boolean(),
43044
43083
  /**
43045
- * Unchanged from the initial render — the same `ui://ggui/render/{id}`
43046
- * URI the mount stamped. Mirrored on the LLM-visible structuredContent
43047
- * so SDKs that strip `_meta` from tool_results can still reach the
43084
+ * The epoch-pinned URI of the NEW history record this update minted
43085
+ * (`ui://ggui/render/{id}[/{key}]#{epoch}` — see epoch-uri.ts). On a
43086
+ * no-op (`updated: false`) no record is minted and this is the bare
43087
+ * live-head URI. Mirrored on the LLM-visible structuredContent so
43088
+ * SDKs that strip `_meta` from tool_results can still reach the
43048
43089
  * mount URI. Kept in sync with the update handler's wire shape —
43049
43090
  * this export and the handler's inline schema must not drift.
43050
43091
  */
43051
- resourceUri: external_exports.string()
43092
+ resourceUri: external_exports.string(),
43093
+ /**
43094
+ * The session's head epoch after this call: advanced by one on a
43095
+ * real update (`updated: true`), unchanged on a no-op. `ggui_render`
43096
+ * mints epoch 0. The session ROW is the authority
43097
+ * (`GguiSessionBase.epoch`, absent ⇒ 0); the ledger's `ui.reminted`
43098
+ * events are the wire signal only — the ledger is horizon-bounded
43099
+ * and must never be counted as the source of truth.
43100
+ */
43101
+ epoch: external_exports.number().int().min(0),
43102
+ /**
43103
+ * Present ONLY on a no-op (`updated: false`): the patch conformed to
43104
+ * the contract but left the final props semantically identical to
43105
+ * the current state, so nothing was written, nothing changes on
43106
+ * screen, and NO new history record was minted. Model-visible by
43107
+ * design — the common producer of a no-op is an agent echoing
43108
+ * existing props back believing it changed the UI, and this field is
43109
+ * its feedback channel.
43110
+ */
43111
+ warning: external_exports.string().optional()
43112
+ });
43113
+ var amendOutputSchema = external_exports.object({
43114
+ sessionId: external_exports.string(),
43115
+ updated: external_exports.boolean(),
43116
+ resourceUri: external_exports.string(),
43117
+ /** Same no-op feedback channel as ggui_update's `warning`. */
43118
+ warning: external_exports.string().optional()
43052
43119
  });
43053
43120
  var declareToolCatalogInputSchema = external_exports.object({
43054
43121
  toolCatalog: external_exports.record(external_exports.string(), external_exports.object({ name: external_exports.string(), version: external_exports.string().optional() }).strict()).describe("Per-app canonical tool identities: bare tool name -> its server's initialize-declared serverInfo. Host/library-supplied; not an agent action.")
@@ -43057,6 +43124,45 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
43057
43124
  saved: external_exports.boolean(),
43058
43125
  appId: external_exports.string()
43059
43126
  }).strict();
43127
+ var RUNTIME_PULL_MAX_LIMIT = 100;
43128
+ var RUNTIME_PULL_MAX_WAIT_SECONDS = 20;
43129
+ var gguiSessionEventSchema = external_exports.object({
43130
+ seq: external_exports.number().int().min(1).describe('Monotonic, gap-free per render; starts at 1 (0 is the "no events yet" cursor sentinel, never an event).'),
43131
+ type: external_exports.string().min(1).describe("Wire-frame type \u2014 see the canonical GguiSessionEventType taxonomy; plain string so servers can mint new types without a protocol bump."),
43132
+ timestamp: external_exports.string().describe("ISO 8601 UTC timestamp the server stamped on emission."),
43133
+ data: external_exports.unknown().describe("Type-specific payload \u2014 structurally identical to the matching live-channel frame payload.")
43134
+ });
43135
+ var runtimePullInputShape = {
43136
+ sessionId: external_exports.string().min(1).describe('Active render id \u2014 sourced from `_meta["ai.ggui/render"].sessionId` on the iframe boot envelope. Unknown and cross-tenant ids surface uniformly as session_not_found.'),
43137
+ sinceSequence: external_exports.number().int().min(0).optional().describe("Replay cursor \u2014 only events with seq > sinceSequence return. Omit (= 0) on first pull; advance to the last event's seq (or lastSequence on an empty page) on every subsequent pull."),
43138
+ limit: external_exports.number().int().min(1).optional().describe(`Max events per page. Values above ${RUNTIME_PULL_MAX_LIMIT} are clamped to ${RUNTIME_PULL_MAX_LIMIT}; omit for the default ${RUNTIME_PULL_MAX_LIMIT}. When hasMore is true, immediately re-pull with the advanced cursor.`),
43139
+ wait: external_exports.number().min(0).optional().describe(`Subscription-mode hold, in seconds. When set and the cursor page is empty, the server holds this call until an event lands or the hold elapses (values above ${RUNTIME_PULL_MAX_WAIT_SECONDS} are clamped to ${RUNTIME_PULL_MAX_WAIT_SECONDS}). An empty page after a full hold is a NORMAL result \u2014 immediately re-pull to stay subscribed, or back off to sparse un-held pulls after a few consecutive empties. Omit (= 0) for an immediate return.`)
43140
+ };
43141
+ var runtimePullInputSchema = external_exports.object(runtimePullInputShape);
43142
+ var runtimePullEventsPageSchema = external_exports.object({
43143
+ events: external_exports.array(gguiSessionEventSchema),
43144
+ lastSequence: external_exports.number().int().min(0),
43145
+ hasMore: external_exports.boolean()
43146
+ });
43147
+ var runtimePullHorizonSchema = external_exports.object({
43148
+ reason: external_exports.literal("REPLAY_HORIZON_PASSED"),
43149
+ currentSequence: external_exports.number().int().min(0)
43150
+ });
43151
+ var runtimePullOutputSchema = external_exports.union([
43152
+ runtimePullEventsPageSchema,
43153
+ runtimePullHorizonSchema
43154
+ ]);
43155
+ var RUNTIME_TELEMETRY_MAX_EVENTS = 40;
43156
+ var runtimeTelemetryInputShape = {
43157
+ sessionId: external_exports.string().min(1).describe("Render id the report concerns \u2014 sourced from the boot envelope. Client-claimed: used as a log tag only."),
43158
+ events: external_exports.array(external_exports.object({
43159
+ at: external_exports.number().min(0).describe("Milliseconds since iframe boot (monotonic, client clock)."),
43160
+ kind: external_exports.string().min(1).max(64).describe("Event name \u2014 e.g. 'boot.path', 'status.connected', 'channel_failover_swap', 'doorbell.ring'."),
43161
+ detail: external_exports.string().max(512).optional().describe("Optional compact context (JSON fragment or message).")
43162
+ })).min(1).max(RUNTIME_TELEMETRY_MAX_EVENTS).describe("Batched ladder/doorbell events, oldest first.")
43163
+ };
43164
+ var runtimeTelemetryInputSchema = external_exports.object(runtimeTelemetryInputShape);
43165
+ var runtimeTelemetryOutputSchema = external_exports.object({ ok: external_exports.literal(true) });
43060
43166
 
43061
43167
  // ../protocol/dist/schemas/invoke.js
43062
43168
  var textBlockSchema = external_exports.object({
@@ -43182,87 +43288,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
43182
43288
  // ../protocol/dist/registry/canonicalize-contract.js
43183
43289
  var import_canonicalize = __toESM(require_canonicalize(), 1);
43184
43290
 
43291
+ // ../protocol/dist/validation/enforced-props-schema.js
43292
+ var import_canonicalize2 = __toESM(require_canonicalize(), 1);
43293
+
43185
43294
  // ../protocol/dist/types/data-contract.js
43186
43295
  var CONTEXT_SLOT_VALUE_MAX_BYTES = 16 * 1024;
43187
43296
  var CONTEXT_SNAPSHOT_MAX_BYTES = 64 * 1024;
43188
43297
 
43189
- // ../protocol/dist/schemas/ops-blueprint.js
43190
- var opsGenerateBlueprintInputSchema = external_exports.object({
43191
- contract: dataContractSchema,
43192
- generator: external_exports.string().min(1).optional().describe("Generator slug (e.g. `ui-gen-default-haiku-4-5`). When omitted, dispatches through `GeneratorRegistry.defaultGenerator()`."),
43193
- persona: external_exports.string().optional().describe("Free-form persona tag (e.g. 'minimalist', 'data-dense'). Normalized via lowercase+trim before persistence; logged as a warning when within Levenshtein distance < 2 of an existing tag for the same appId."),
43194
- aesthetic: external_exports.string().optional().describe("Free-form aesthetic tag (e.g. 'glassmorphic', 'brutalist', 'editorial'). Persisted on `Blueprint.variance.aesthetic`. Distinct from persona \u2014 persona names the user mental model; aesthetic names the visual treatment."),
43195
- context: external_exports.record(external_exports.string(), jsonValueSchema).optional().describe("Small structured signal carried alongside the persona. Persisted on `Blueprint.variance.context`."),
43196
- seedPrompt: external_exports.string().optional().describe("The raw operator prompt that produced this variant. Round-trip input for the variant-selector + audit trail."),
43197
- setAsOperatorDefault: external_exports.boolean().optional().describe("When true, pins the new blueprint as the operator default for its `(appId, contractHash)` group, clearing any prior default in the same group.")
43198
- }).strict();
43199
- var opsGenerateBlueprintOutputSchema = external_exports.object({
43200
- blueprintId: external_exports.string().min(1),
43201
- codeHash: external_exports.string().optional().describe("Content hash of the generated code body. Absent when the generator returned a non-`ok` result and persistence skipped \u2014 the failure mode is surfaced through generator-level error reporting elsewhere."),
43202
- validatorScore: external_exports.number().min(0).max(1).optional().describe("Advanced generator's iterative-loop validator score (0-1). Absent for default-generator output."),
43203
- source: llmBlueprintSourceSchema.describe("Provenance stamped on the persisted `Blueprint.source` \u2014 always the `llm` arm on this path: `generator` is the engine slug the dispatch resolved to (stamped from the engine's own metadata claim); `model` is the LLM model id the engine called.")
43204
- }).strict();
43205
- var opsRegisterBlueprintInputSchema = external_exports.object({
43206
- contract: dataContractSchema,
43207
- componentCode: external_exports.string().min(1).describe("Verbatim component-code body to persist. Stored as-is \u2014 no LLM call, no validator pass. Operator owns correctness; the handler computes the canonical sha256 codeHash and routes the bytes through the same persistence seams as `*_generate_*`."),
43208
- persona: external_exports.string().optional().describe("Free-form persona tag (e.g. 'minimalist', 'data-dense'). Normalized via lowercase+trim before persistence; logged as a warning when within Levenshtein distance < 2 of an existing tag for the same appId."),
43209
- aesthetic: external_exports.string().optional().describe("Free-form aesthetic tag. Persisted on `Blueprint.variance.aesthetic`."),
43210
- context: external_exports.record(external_exports.string(), jsonValueSchema).optional().describe("Small structured signal carried alongside the persona. Persisted on `Blueprint.variance.context`."),
43211
- seedPrompt: external_exports.string().optional().describe("Optional originating prompt for audit + round-tripping (e.g. the prose the operator originally fed into `*_generate_*` before exporting)."),
43212
- setAsOperatorDefault: external_exports.boolean().optional().describe("When true, pins the new blueprint as the operator default for its `(appId, contractHash)` group, clearing any prior default in the same group.")
43213
- }).strict();
43214
- var opsRegisterBlueprintOutputSchema = external_exports.object({
43215
- blueprintId: external_exports.string().min(1),
43216
- codeHash: external_exports.string().min(1).describe("Content hash of the persisted code body (full sha256 hex)."),
43217
- source: userBlueprintSourceSchema.describe('Provenance stamped on the persisted `Blueprint.source` \u2014 always `{kind: "user"}` on this path: operator-supplied bytes, no LLM dispatch, no engine claim to record.')
43218
- }).strict();
43219
- var opsListBlueprintsInputSchema = external_exports.object({
43220
- contractHash: external_exports.string().min(1).optional().describe("Filter to a single `(appId, contractHash)` group. Combine with `generator` / `persona` to narrow within the group."),
43221
- generator: external_exports.string().min(1).optional().describe('Filter to engine-generated blueprints (`source.kind === "llm"`) whose `source.generator` equals this slug. `user`-sourced rows never match (they carry no engine provenance).'),
43222
- persona: external_exports.string().optional().describe("Filter on `variance.persona`. Normalized to match persisted form (lowercase+trim)."),
43223
- intentKeywords: external_exports.array(external_exports.string().min(1)).optional().describe("Semantic-search tokens. When set, dispatches through `BlueprintSearch.search()` rather than indexed `list()`.")
43224
- }).strict();
43225
- var opsListBlueprintsOutputSchema = external_exports.object({
43226
- blueprints: external_exports.array(blueprintSchema)
43227
- }).strict();
43228
- var opsUpdateBlueprintInputSchema = external_exports.object({
43229
- blueprintId: external_exports.string().min(1),
43230
- isOperatorDefault: external_exports.literal(true).optional().describe("When `true`, pins this blueprint as the operator default for its `(appId, contractHash)` group. Clears any prior default. Cannot set to `false` \u2014 to unpin, set another blueprint in the same group as default, or delete this one."),
43231
- variance: blueprintVarianceSchema.optional().describe('Partial-merge into the existing variance. Supplied keys overwrite; omitted keys preserve. Pass `{persona: ""}` to clear a persona (handler treats empty string as removal).')
43232
- }).strict();
43233
- var opsUpdateBlueprintOutputSchema = external_exports.object({
43234
- blueprintId: external_exports.string().min(1),
43235
- updatedAt: external_exports.string().min(1)
43236
- }).strict();
43237
- var opsDeleteBlueprintInputSchema = external_exports.object({
43238
- blueprintId: external_exports.string().min(1)
43239
- }).strict();
43240
- var opsDeleteBlueprintOutputSchema = external_exports.object({
43241
- deleted: external_exports.literal(true)
43242
- }).strict();
43243
-
43244
- // ../protocol/dist/envelopes/builders.js
43245
- function resolveSchemaVersion(parts) {
43246
- if ("schemaVersion" in parts) {
43247
- return parts.schemaVersion;
43248
- }
43249
- return PROTOCOL_SCHEMA_VERSION;
43250
- }
43251
- function makeActionEnvelope(parts) {
43252
- const envelope = {
43253
- sessionId: parts.sessionId,
43254
- type: parts.type
43255
- };
43256
- if (parts.payload !== void 0)
43257
- envelope.payload = parts.payload;
43258
- if (parts.clientSeq !== void 0)
43259
- envelope.clientSeq = parts.clientSeq;
43260
- const stamp = resolveSchemaVersion(parts);
43261
- if (stamp !== void 0)
43262
- envelope.schemaVersion = stamp;
43263
- return envelope;
43264
- }
43265
-
43266
43298
  // ../protocol/dist/validation/ajv-runtime.js
43267
43299
  var import_ajv = __toESM(require_ajv(), 1);
43268
43300
  var import_ajv_formats = __toESM(require_dist(), 1);
@@ -43305,8 +43337,20 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
43305
43337
  if (!standaloneAjv.getKeyword("nullable")) {
43306
43338
  standaloneAjv.addKeyword({ keyword: "nullable" });
43307
43339
  }
43340
+ var standaloneCjsAjv = new import_ajv.default({
43341
+ ...AJV_OPTIONS,
43342
+ code: { source: true }
43343
+ });
43344
+ (0, import_ajv_formats.default)(standaloneCjsAjv);
43345
+ if (!standaloneCjsAjv.getKeyword("example")) {
43346
+ standaloneCjsAjv.addKeyword({ keyword: "example" });
43347
+ }
43348
+ if (!standaloneCjsAjv.getKeyword("nullable")) {
43349
+ standaloneCjsAjv.addKeyword({ keyword: "nullable" });
43350
+ }
43308
43351
  function injectClosedShape(schema) {
43309
- const isObjectNode = schema.type === "object" || schema.properties !== void 0;
43352
+ const typeSet = new Set(Array.isArray(schema.type) ? schema.type : schema.type ? [schema.type] : []);
43353
+ const isObjectNode = typeSet.has("object") || schema.properties !== void 0;
43310
43354
  if (isObjectNode) {
43311
43355
  const out = { ...schema };
43312
43356
  if (out.properties) {
@@ -43327,7 +43371,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
43327
43371
  out.anyOf = out.anyOf.map(injectClosedShape);
43328
43372
  return out;
43329
43373
  }
43330
- if (schema.type === "array" && schema.items) {
43374
+ if (typeSet.has("array") && schema.items) {
43331
43375
  return { ...schema, items: injectClosedShape(schema.items) };
43332
43376
  }
43333
43377
  if (schema.oneOf || schema.anyOf) {
@@ -43347,7 +43391,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
43347
43391
  function mapAjvErrorsToViolations(errors, data) {
43348
43392
  if (!errors)
43349
43393
  return [];
43350
- return errors.map((err) => mapOne(err, data));
43394
+ return errors.map((err) => ({
43395
+ ...mapOne(err, data),
43396
+ ...err.keyword ? { keyword: err.keyword } : {}
43397
+ }));
43351
43398
  }
43352
43399
  function prefixViolations(violations, prefix) {
43353
43400
  if (!prefix)
@@ -43694,6 +43741,88 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
43694
43741
  return validateActionData(envelope.payload, spec, precompiledActions);
43695
43742
  }
43696
43743
 
43744
+ // ../protocol/dist/schemas/ops-blueprint.js
43745
+ var opsGenerateBlueprintInputSchema = external_exports.object({
43746
+ appId: external_exports.string().min(1).optional().describe("Target app for this curation call. Defaults to the caller's bound app identity; callers not bound to an app must provide it. The deployment's authorization policy decides whether the caller may curate the named app."),
43747
+ contract: dataContractSchema,
43748
+ generator: external_exports.string().min(1).optional().describe("Generator slug (e.g. `ui-gen-default-haiku-4-5`). When omitted, dispatches through `GeneratorRegistry.defaultGenerator()`."),
43749
+ persona: external_exports.string().optional().describe("Free-form persona tag (e.g. 'minimalist', 'data-dense'). Normalized via lowercase+trim before persistence; logged as a warning when within Levenshtein distance < 2 of an existing tag for the same appId."),
43750
+ aesthetic: external_exports.string().optional().describe("Free-form aesthetic tag (e.g. 'glassmorphic', 'brutalist', 'editorial'). Persisted on `Blueprint.variance.aesthetic`. Distinct from persona \u2014 persona names the user mental model; aesthetic names the visual treatment."),
43751
+ context: external_exports.record(external_exports.string(), jsonValueSchema).optional().describe("Small structured signal carried alongside the persona. Persisted on `Blueprint.variance.context`."),
43752
+ seedPrompt: external_exports.string().optional().describe("The raw operator prompt that produced this variant. Round-trip input for the variant-selector + audit trail."),
43753
+ setAsOperatorDefault: external_exports.boolean().optional().describe("When true, pins the new blueprint as the operator default for its `(appId, contractHash)` group, clearing any prior default in the same group.")
43754
+ }).strict();
43755
+ var opsGenerateBlueprintOutputSchema = external_exports.object({
43756
+ blueprintId: external_exports.string().min(1),
43757
+ codeHash: external_exports.string().optional().describe("Content hash of the generated code body. Absent when the generator returned a non-`ok` result and persistence skipped \u2014 the failure mode is surfaced through generator-level error reporting elsewhere."),
43758
+ validatorScore: external_exports.number().min(0).max(1).optional().describe("Advanced generator's iterative-loop validator score (0-1). Absent for default-generator output."),
43759
+ source: llmBlueprintSourceSchema.describe("Provenance stamped on the persisted `Blueprint.source` \u2014 always the `llm` arm on this path: `generator` is the engine slug the dispatch resolved to (stamped from the engine's own metadata claim); `model` is the LLM model id the engine called.")
43760
+ }).strict();
43761
+ var opsRegisterBlueprintInputSchema = external_exports.object({
43762
+ appId: external_exports.string().min(1).optional().describe("Target app for this curation call. Defaults to the caller's bound app identity; callers not bound to an app must provide it. The deployment's authorization policy decides whether the caller may curate the named app."),
43763
+ contract: dataContractSchema,
43764
+ componentCode: external_exports.string().min(1).describe("Verbatim component-code body to persist. Stored as-is \u2014 no LLM call, no validator pass. Operator owns correctness; the handler computes the canonical sha256 codeHash and routes the bytes through the same persistence seams as `*_generate_*`."),
43765
+ persona: external_exports.string().optional().describe("Free-form persona tag (e.g. 'minimalist', 'data-dense'). Normalized via lowercase+trim before persistence; logged as a warning when within Levenshtein distance < 2 of an existing tag for the same appId."),
43766
+ aesthetic: external_exports.string().optional().describe("Free-form aesthetic tag. Persisted on `Blueprint.variance.aesthetic`."),
43767
+ context: external_exports.record(external_exports.string(), jsonValueSchema).optional().describe("Small structured signal carried alongside the persona. Persisted on `Blueprint.variance.context`."),
43768
+ seedPrompt: external_exports.string().optional().describe("Optional originating prompt for audit + round-tripping (e.g. the prose the operator originally fed into `*_generate_*` before exporting)."),
43769
+ setAsOperatorDefault: external_exports.boolean().optional().describe("When true, pins the new blueprint as the operator default for its `(appId, contractHash)` group, clearing any prior default in the same group.")
43770
+ }).strict();
43771
+ var opsRegisterBlueprintOutputSchema = external_exports.object({
43772
+ blueprintId: external_exports.string().min(1),
43773
+ codeHash: external_exports.string().min(1).describe("Content hash of the persisted code body (full sha256 hex)."),
43774
+ source: userBlueprintSourceSchema.describe('Provenance stamped on the persisted `Blueprint.source` \u2014 always `{kind: "user"}` on this path: operator-supplied bytes, no LLM dispatch, no engine claim to record.')
43775
+ }).strict();
43776
+ var opsListBlueprintsInputSchema = external_exports.object({
43777
+ appId: external_exports.string().min(1).optional().describe("Target app for this curation call. Defaults to the caller's bound app identity; callers not bound to an app must provide it. The deployment's authorization policy decides whether the caller may curate the named app."),
43778
+ contractHash: external_exports.string().min(1).optional().describe("Filter to a single `(appId, contractHash)` group. Combine with `generator` / `persona` to narrow within the group."),
43779
+ generator: external_exports.string().min(1).optional().describe('Filter to engine-generated blueprints (`source.kind === "llm"`) whose `source.generator` equals this slug. `user`-sourced rows never match (they carry no engine provenance).'),
43780
+ persona: external_exports.string().optional().describe("Filter on `variance.persona`. Normalized to match persisted form (lowercase+trim)."),
43781
+ intentKeywords: external_exports.array(external_exports.string().min(1)).optional().describe("Semantic-search tokens. When set, dispatches through `BlueprintSearch.search()` rather than indexed `list()`.")
43782
+ }).strict();
43783
+ var opsListBlueprintsOutputSchema = external_exports.object({
43784
+ blueprints: external_exports.array(blueprintSchema)
43785
+ }).strict();
43786
+ var opsUpdateBlueprintInputSchema = external_exports.object({
43787
+ appId: external_exports.string().min(1).optional().describe("Target app for this curation call. Defaults to the caller's bound app identity; callers not bound to an app must provide it. The deployment's authorization policy decides whether the caller may curate the named app. Must match the app the addressed blueprint belongs to."),
43788
+ blueprintId: external_exports.string().min(1),
43789
+ isOperatorDefault: external_exports.literal(true).optional().describe("When `true`, pins this blueprint as the operator default for its `(appId, contractHash)` group. Clears any prior default. Cannot set to `false` \u2014 to unpin, set another blueprint in the same group as default, or delete this one."),
43790
+ variance: blueprintVarianceSchema.optional().describe('Partial-merge into the existing variance. Supplied keys overwrite; omitted keys preserve. Pass `{persona: ""}` to clear a persona (handler treats empty string as removal).')
43791
+ }).strict();
43792
+ var opsUpdateBlueprintOutputSchema = external_exports.object({
43793
+ blueprintId: external_exports.string().min(1),
43794
+ updatedAt: external_exports.string().min(1)
43795
+ }).strict();
43796
+ var opsDeleteBlueprintInputSchema = external_exports.object({
43797
+ appId: external_exports.string().min(1).optional().describe("Target app for this curation call. Defaults to the caller's bound app identity; callers not bound to an app must provide it. The deployment's authorization policy decides whether the caller may curate the named app. Must match the app the addressed blueprint belongs to."),
43798
+ blueprintId: external_exports.string().min(1)
43799
+ }).strict();
43800
+ var opsDeleteBlueprintOutputSchema = external_exports.object({
43801
+ deleted: external_exports.literal(true)
43802
+ }).strict();
43803
+
43804
+ // ../protocol/dist/envelopes/builders.js
43805
+ function resolveSchemaVersion(parts) {
43806
+ if ("schemaVersion" in parts) {
43807
+ return parts.schemaVersion;
43808
+ }
43809
+ return PROTOCOL_SCHEMA_VERSION;
43810
+ }
43811
+ function makeActionEnvelope(parts) {
43812
+ const envelope = {
43813
+ sessionId: parts.sessionId,
43814
+ type: parts.type
43815
+ };
43816
+ if (parts.payload !== void 0)
43817
+ envelope.payload = parts.payload;
43818
+ if (parts.clientSeq !== void 0)
43819
+ envelope.clientSeq = parts.clientSeq;
43820
+ const stamp = resolveSchemaVersion(parts);
43821
+ if (stamp !== void 0)
43822
+ envelope.schemaVersion = stamp;
43823
+ return envelope;
43824
+ }
43825
+
43697
43826
  // ../wire/dist/contract.js
43698
43827
  var ClientContractViolationError = class extends Error {
43699
43828
  direction;
@@ -46764,19 +46893,26 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
46764
46893
  function globalExpr(gguiKey, legacyName) {
46765
46894
  return `(globalThis.__ggui__&&globalThis.__ggui__["${gguiKey}"]||window["${legacyName}"])`;
46766
46895
  }
46767
- function buildDataUrlReactShim(globalName) {
46896
+ function toDataUrl(js) {
46897
+ return `data:text/javascript,${encodeURIComponent(js)}`;
46898
+ }
46899
+ function jsReactShim(globalName) {
46768
46900
  const namedExports = REACT_EXPORTS.map((e) => `export const ${e} = R.${e};`).join(" ");
46769
46901
  const resolve = globalExpr("react", globalName);
46770
- const js = `const R = ${resolve}; export default R; ${namedExports}`;
46771
- return `data:text/javascript,${encodeURIComponent(js)}`;
46902
+ return `const R = ${resolve}; export default R; ${namedExports}`;
46772
46903
  }
46773
- function buildDataUrlReactDomShim() {
46904
+ function buildDataUrlReactShim(globalName) {
46905
+ return toDataUrl(jsReactShim(globalName));
46906
+ }
46907
+ function jsReactDomShim() {
46774
46908
  const REACT_DOM_EXPORTS = ["createPortal", "flushSync", "unstable_batchedUpdates"];
46775
46909
  const namedExports = REACT_DOM_EXPORTS.map((e) => `export const ${e} = D.${e};`).join(" ");
46776
- const js = `const D = globalThis.__ggui__["reactDom"]; export default D; ${namedExports}`;
46777
- return `data:text/javascript,${encodeURIComponent(js)}`;
46910
+ return `const D = globalThis.__ggui__["reactDom"]; export default D; ${namedExports}`;
46778
46911
  }
46779
- function buildDataUrlJsxShim(globalName) {
46912
+ function buildDataUrlReactDomShim() {
46913
+ return toDataUrl(jsReactDomShim());
46914
+ }
46915
+ function jsJsxShim(globalName) {
46780
46916
  const resolve = globalExpr("react", globalName);
46781
46917
  const js = [
46782
46918
  `const R = ${resolve};`,
@@ -46789,9 +46925,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
46789
46925
  `export{jsx,jsx as jsxs,jsx as jsxDEV};`,
46790
46926
  `export const Fragment=R.Fragment;`
46791
46927
  ].join("");
46792
- return `data:text/javascript,${encodeURIComponent(js)}`;
46928
+ return js;
46793
46929
  }
46794
- function buildDataUrlGlobalShim(globalName, gguiKey, exportNames, fallbackGlobals, fallbackGguiKeys) {
46930
+ function buildDataUrlJsxShim(globalName) {
46931
+ return toDataUrl(jsJsxShim(globalName));
46932
+ }
46933
+ function jsGlobalShim(globalName, gguiKey, exportNames, fallbackGlobals, fallbackGguiKeys) {
46795
46934
  if (exportNames && exportNames.length > 0) {
46796
46935
  const globals = [globalName, ...fallbackGlobals || []];
46797
46936
  const gguiKeys = [gguiKey, ...fallbackGguiKeys || []];
@@ -46802,17 +46941,20 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
46802
46941
  ));
46803
46942
  const mergeExpr = resolveExprs.join(",");
46804
46943
  const named = exportNames.map((n) => `export const ${n} = M["${n}"];`).join(" ");
46805
- const js2 = resolveExprs.length > 1 ? `const M = Object.assign({}, ${mergeExpr}); ${named} export default M;` : `const M = ${resolveExprs[0]}; ${named} export default M;`;
46806
- return `data:text/javascript,${encodeURIComponent(js2)}`;
46944
+ return resolveExprs.length > 1 ? `const M = Object.assign({}, ${mergeExpr}); ${named} export default M;` : `const M = ${resolveExprs[0]}; ${named} export default M;`;
46807
46945
  }
46808
46946
  const resolve = globalExpr(gguiKey, globalName);
46809
- const js = `const M = ${resolve} || {}; const handler = { get(_, key) { return M[key]; } }; export default new Proxy({}, handler);`;
46810
- return `data:text/javascript,${encodeURIComponent(js)}`;
46947
+ return `const M = ${resolve} || {}; const handler = { get(_, key) { return M[key]; } }; export default new Proxy({}, handler);`;
46811
46948
  }
46812
- function buildDataUrlWireShim() {
46949
+ function buildDataUrlGlobalShim(globalName, gguiKey, exportNames, fallbackGlobals, fallbackGguiKeys) {
46950
+ return toDataUrl(jsGlobalShim(globalName, gguiKey, exportNames, fallbackGlobals, fallbackGguiKeys));
46951
+ }
46952
+ function jsWireShim() {
46813
46953
  const named = WIRE_EXPORTS.map((e) => `export const ${e} = w.${e};`).join(" ");
46814
- const js = `const w = globalThis.__ggui__.wire; ${named} export default w;`;
46815
- return `data:text/javascript,${encodeURIComponent(js)}`;
46954
+ return `const w = globalThis.__ggui__.wire; ${named} export default w;`;
46955
+ }
46956
+ function buildDataUrlWireShim() {
46957
+ return toDataUrl(jsWireShim());
46816
46958
  }
46817
46959
  function extractNamedImports(code, specifier) {
46818
46960
  const esc2 = specifier.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
@@ -46829,7 +46971,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
46829
46971
  }
46830
46972
  return [...names];
46831
46973
  }
46832
- function buildGadgetPackageShim(packageName, exportNames) {
46974
+ function jsGadgetPackageShim(packageName, exportNames) {
46833
46975
  const pkgLit = JSON.stringify(packageName);
46834
46976
  const hasComponent = exportNames.some((n) => /^[A-Z]/.test(n));
46835
46977
  const parts = [];
@@ -46846,7 +46988,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
46846
46988
  parts.push(`export const ${name}=${factory}(${JSON.stringify(name)});`);
46847
46989
  }
46848
46990
  parts.push(`export default new Proxy({},{get:function(_,k){return NS()[k];}});`);
46849
- return `data:text/javascript,${encodeURIComponent(parts.join(""))}`;
46991
+ return parts.join("");
46992
+ }
46993
+ function buildGadgetPackageShim(packageName, exportNames) {
46994
+ return toDataUrl(jsGadgetPackageShim(packageName, exportNames));
46850
46995
  }
46851
46996
  function rewriteDataUrl(code, opts) {
46852
46997
  const reactGlobal = opts.reactGlobal ?? "__REACT";
@@ -46881,6 +47026,29 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
46881
47026
  }
46882
47027
  return code;
46883
47028
  }
47029
+ var ASSET_SHIM_FOR_SPECIFIER = {
47030
+ "react/jsx-runtime": "jsx-runtime",
47031
+ "react/jsx-dev-runtime": "jsx-runtime",
47032
+ "react-dom": "react-dom",
47033
+ react: "react",
47034
+ "@ggui-ai/design/primitives": "primitives",
47035
+ "@ggui-ai/design/components": "components",
47036
+ "@ggui-ai/design/compositions": "compositions",
47037
+ "@ggui-ai/design/interact": "interact",
47038
+ "@ggui-ai/design/templates": "templates",
47039
+ "@ggui-ai/design/app-components": "app-components",
47040
+ "@ggui-ai/design/tokens": "tokens",
47041
+ "@ggui-ai/design": "design",
47042
+ "@ggui-ai/wire": "wire",
47043
+ "@ggui-ai/gadgets": "gadgets"
47044
+ };
47045
+ function rewriteAssetUrl(code, opts) {
47046
+ const base = opts.shimBaseUrl.replace(/\/$/, "");
47047
+ for (const [specifier, shimName] of Object.entries(ASSET_SHIM_FOR_SPECIFIER)) {
47048
+ code = replaceSpecifier(code, specifier, `${base}/${shimName}.js`);
47049
+ }
47050
+ return code;
47051
+ }
46884
47052
  function rewriteImportmap(code, opts) {
46885
47053
  const base = opts.reactBaseUrl ?? "https://esm.sh/react@18.2.0";
46886
47054
  code = replaceSpecifier(code, "react/jsx-runtime", `${base}/jsx-runtime`);
@@ -46894,6 +47062,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
46894
47062
  return rewriteDataUrl(code, options);
46895
47063
  case "importmap":
46896
47064
  return rewriteImportmap(code, options);
47065
+ case "asset-url":
47066
+ return rewriteAssetUrl(code, options);
46897
47067
  }
46898
47068
  }
46899
47069
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ggui-ai/ui-visual-tester",
3
- "version": "0.8.0",
3
+ "version": "0.10.0",
4
4
  "description": "Behavioral validator for ggui-generated component code. Renders a component in real Chromium via Playwright, clicks each action declared in its contract, and verifies the action actually does something — mutating bound state or dispatching to the agent. Catches buttons wired to no-op handlers that structural validators miss. Playwright is an optional peer dependency, injected by the caller.",
5
5
  "keywords": [
6
6
  "ggui",
@@ -48,9 +48,9 @@
48
48
  "dependencies": {
49
49
  "react": "^19.0.0",
50
50
  "react-dom": "^19.0.0",
51
- "@ggui-ai/design": "0.8.0",
52
- "@ggui-ai/wire": "0.8.0",
53
- "@ggui-ai/protocol": "0.8.0"
51
+ "@ggui-ai/protocol": "0.10.0",
52
+ "@ggui-ai/wire": "0.10.0",
53
+ "@ggui-ai/design": "0.10.0"
54
54
  },
55
55
  "devDependencies": {
56
56
  "@playwright/test": "^1.60.0",