@ggui-ai/ui-visual-tester 0.8.0 → 0.9.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.
@@ -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.9.0";
42348
42348
  var STDLIB_GADGETS = [
42349
42349
  {
42350
42350
  package: STDLIB_GADGETS_PACKAGE,
@@ -42961,10 +42961,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
42961
42961
  "PRODUCTION_FAILED",
42962
42962
  "VALIDATION_ERROR",
42963
42963
  "NO_PLATFORM_KEY",
42964
- "NO_CREDENTIALS"
42964
+ "NO_CREDENTIALS",
42965
+ "GENERATION_QUEUE_OVERLOADED"
42965
42966
  ]);
42966
42967
  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."),
42968
+ 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
42969
  message: external_exports.string().describe("Human-readable failure detail \u2014 fold into the next attempt or surface to the operator.")
42969
42970
  });
42970
42971
  var resourceReadErrorCodeSchema = external_exports.enum([
@@ -43022,33 +43023,78 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
43022
43023
  description: external_exports.string(),
43023
43024
  example: external_exports.string(),
43024
43025
  args: external_exports.object({
43025
- sessionId: external_exports.string()
43026
+ sessionId: external_exports.string(),
43027
+ // The per-call long-poll window in seconds. Carried on the hint
43028
+ // because consume's own default is 0 (single non-blocking
43029
+ // drain): an agent copying a timeout-less hint gets an instant
43030
+ // empty result and stops looping.
43031
+ timeout: external_exports.number()
43026
43032
  })
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.")
43033
+ }).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
43034
  });
43029
43035
  var updateInputSchema = external_exports.discriminatedUnion("kind", [
43030
43036
  external_exports.object({
43031
43037
  sessionId: external_exports.string().describe("GguiSession opaque id (UUID) \u2014 returned by ggui_render."),
43032
43038
  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.")
43039
+ 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
43040
  }).strict(),
43035
43041
  external_exports.object({
43036
43042
  sessionId: external_exports.string().describe("GguiSession opaque id (UUID) \u2014 returned by ggui_render."),
43037
43043
  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.")
43044
+ 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.")
43045
+ }).strict()
43046
+ ]);
43047
+ var amendInputSchema = external_exports.discriminatedUnion("kind", [
43048
+ external_exports.object({
43049
+ sessionId: external_exports.string().describe("GguiSession opaque id (UUID) \u2014 returned by ggui_render."),
43050
+ kind: external_exports.literal("replace"),
43051
+ props: external_exports.record(external_exports.string(), external_exports.unknown()).describe("Full replacement props map, applied to the currently mounted card in place.")
43052
+ }).strict(),
43053
+ external_exports.object({
43054
+ sessionId: external_exports.string().describe("GguiSession opaque id (UUID) \u2014 returned by ggui_render."),
43055
+ kind: external_exports.literal("merge"),
43056
+ 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
43057
  }).strict()
43040
43058
  ]);
43041
43059
  var updateOutputSchema = external_exports.object({
43042
43060
  sessionId: external_exports.string(),
43043
43061
  updated: external_exports.boolean(),
43044
43062
  /**
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
43063
+ * The epoch-pinned URI of the NEW history record this update minted
43064
+ * (`ui://ggui/render/{id}[/{key}]#{epoch}` — see epoch-uri.ts). On a
43065
+ * no-op (`updated: false`) no record is minted and this is the bare
43066
+ * live-head URI. Mirrored on the LLM-visible structuredContent so
43067
+ * SDKs that strip `_meta` from tool_results can still reach the
43048
43068
  * mount URI. Kept in sync with the update handler's wire shape —
43049
43069
  * this export and the handler's inline schema must not drift.
43050
43070
  */
43051
- resourceUri: external_exports.string()
43071
+ resourceUri: external_exports.string(),
43072
+ /**
43073
+ * The session's head epoch after this call: advanced by one on a
43074
+ * real update (`updated: true`), unchanged on a no-op. `ggui_render`
43075
+ * mints epoch 0. The session ROW is the authority
43076
+ * (`GguiSessionBase.epoch`, absent ⇒ 0); the ledger's `ui.reminted`
43077
+ * events are the wire signal only — the ledger is horizon-bounded
43078
+ * and must never be counted as the source of truth.
43079
+ */
43080
+ epoch: external_exports.number().int().min(0),
43081
+ /**
43082
+ * Present ONLY on a no-op (`updated: false`): the patch conformed to
43083
+ * the contract but left the final props semantically identical to
43084
+ * the current state, so nothing was written, nothing changes on
43085
+ * screen, and NO new history record was minted. Model-visible by
43086
+ * design — the common producer of a no-op is an agent echoing
43087
+ * existing props back believing it changed the UI, and this field is
43088
+ * its feedback channel.
43089
+ */
43090
+ warning: external_exports.string().optional()
43091
+ });
43092
+ var amendOutputSchema = external_exports.object({
43093
+ sessionId: external_exports.string(),
43094
+ updated: external_exports.boolean(),
43095
+ resourceUri: external_exports.string(),
43096
+ /** Same no-op feedback channel as ggui_update's `warning`. */
43097
+ warning: external_exports.string().optional()
43052
43098
  });
43053
43099
  var declareToolCatalogInputSchema = external_exports.object({
43054
43100
  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 +43103,45 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
43057
43103
  saved: external_exports.boolean(),
43058
43104
  appId: external_exports.string()
43059
43105
  }).strict();
43106
+ var RUNTIME_PULL_MAX_LIMIT = 100;
43107
+ var RUNTIME_PULL_MAX_WAIT_SECONDS = 20;
43108
+ var gguiSessionEventSchema = external_exports.object({
43109
+ 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).'),
43110
+ 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."),
43111
+ timestamp: external_exports.string().describe("ISO 8601 UTC timestamp the server stamped on emission."),
43112
+ data: external_exports.unknown().describe("Type-specific payload \u2014 structurally identical to the matching live-channel frame payload.")
43113
+ });
43114
+ var runtimePullInputShape = {
43115
+ 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.'),
43116
+ 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."),
43117
+ 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.`),
43118
+ 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.`)
43119
+ };
43120
+ var runtimePullInputSchema = external_exports.object(runtimePullInputShape);
43121
+ var runtimePullEventsPageSchema = external_exports.object({
43122
+ events: external_exports.array(gguiSessionEventSchema),
43123
+ lastSequence: external_exports.number().int().min(0),
43124
+ hasMore: external_exports.boolean()
43125
+ });
43126
+ var runtimePullHorizonSchema = external_exports.object({
43127
+ reason: external_exports.literal("REPLAY_HORIZON_PASSED"),
43128
+ currentSequence: external_exports.number().int().min(0)
43129
+ });
43130
+ var runtimePullOutputSchema = external_exports.union([
43131
+ runtimePullEventsPageSchema,
43132
+ runtimePullHorizonSchema
43133
+ ]);
43134
+ var RUNTIME_TELEMETRY_MAX_EVENTS = 40;
43135
+ var runtimeTelemetryInputShape = {
43136
+ 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."),
43137
+ events: external_exports.array(external_exports.object({
43138
+ at: external_exports.number().min(0).describe("Milliseconds since iframe boot (monotonic, client clock)."),
43139
+ kind: external_exports.string().min(1).max(64).describe("Event name \u2014 e.g. 'boot.path', 'status.connected', 'channel_failover_swap', 'doorbell.ring'."),
43140
+ detail: external_exports.string().max(512).optional().describe("Optional compact context (JSON fragment or message).")
43141
+ })).min(1).max(RUNTIME_TELEMETRY_MAX_EVENTS).describe("Batched ladder/doorbell events, oldest first.")
43142
+ };
43143
+ var runtimeTelemetryInputSchema = external_exports.object(runtimeTelemetryInputShape);
43144
+ var runtimeTelemetryOutputSchema = external_exports.object({ ok: external_exports.literal(true) });
43060
43145
 
43061
43146
  // ../protocol/dist/schemas/invoke.js
43062
43147
  var textBlockSchema = external_exports.object({
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.9.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/design": "0.9.0",
52
+ "@ggui-ai/protocol": "0.9.0",
53
+ "@ggui-ai/wire": "0.9.0"
54
54
  },
55
55
  "devDependencies": {
56
56
  "@playwright/test": "^1.60.0",