@ggui-ai/protocol 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.
Files changed (38) hide show
  1. package/dist/gadgets/stdlib-gadgets.d.ts +1 -1
  2. package/dist/gadgets/stdlib-gadgets.js +1 -1
  3. package/dist/integrations/epoch-uri.d.ts +42 -0
  4. package/dist/integrations/epoch-uri.d.ts.map +1 -0
  5. package/dist/integrations/epoch-uri.js +48 -0
  6. package/dist/integrations/mcp-apps.d.ts +89 -5
  7. package/dist/integrations/mcp-apps.d.ts.map +1 -1
  8. package/dist/integrations/mcp-apps.js +50 -1
  9. package/dist/schemas/invoke.d.ts +1 -1
  10. package/dist/schemas/invoke.js +1 -1
  11. package/dist/schemas/mcp.d.ts +218 -6
  12. package/dist/schemas/mcp.d.ts.map +1 -1
  13. package/dist/schemas/mcp.js +271 -13
  14. package/dist/types/data-contract.d.ts +2 -2
  15. package/dist/types/ggui-session-event.d.ts +42 -1
  16. package/dist/types/ggui-session-event.d.ts.map +1 -1
  17. package/dist/types/ggui-session-event.js +16 -1
  18. package/dist/types/live-channel.d.ts +8 -0
  19. package/dist/types/live-channel.d.ts.map +1 -1
  20. package/dist/types/llm-route.d.ts +2 -2
  21. package/dist/types/llm-route.d.ts.map +1 -1
  22. package/dist/types/llm-route.js +26 -8
  23. package/dist/types/mcp.d.ts +28 -1
  24. package/dist/types/mcp.d.ts.map +1 -1
  25. package/dist/types/render.d.ts +12 -0
  26. package/dist/types/render.d.ts.map +1 -1
  27. package/dist/types/ui-generator.d.ts +20 -3
  28. package/dist/types/ui-generator.d.ts.map +1 -1
  29. package/dist/validation/contract-validator.d.ts +2 -2
  30. package/dist/validation/contract-validator.d.ts.map +1 -1
  31. package/dist/validation/resolve-stream-channel.d.ts +2 -2
  32. package/dist/validation/resolve-stream-channel.js +2 -2
  33. package/dist/validation/ui-security.d.ts +2 -2
  34. package/dist/validation/ui-security.js +2 -2
  35. package/dist/version.d.ts +150 -0
  36. package/dist/version.d.ts.map +1 -1
  37. package/dist/version.js +150 -0
  38. package/package.json +1 -1
@@ -316,7 +316,7 @@ export declare const renderCacheMarkerSchema: z.ZodObject<{
316
316
  /**
317
317
  * Canonical failure codes for the in-result `ggui_render` failure
318
318
  * envelope (SPEC §7.9 Plane 3). Closed enum — a failed render's
319
- * `error.code` is always one of these four; finer-grained diagnostics
319
+ * `error.code` is always one of these five; finer-grained diagnostics
320
320
  * ride on `error.message`.
321
321
  *
322
322
  * - `PRODUCTION_FAILED` — generation ran but did not produce a
@@ -328,12 +328,21 @@ export declare const renderCacheMarkerSchema: z.ZodObject<{
328
328
  * configuration has no key for the resolved route.
329
329
  * - `NO_CREDENTIALS` — no generation credentials are configured on
330
330
  * the server at all.
331
+ * - `GENERATION_QUEUE_OVERLOADED` — the deployment's generation
332
+ * admission gate rejected this request before any generation
333
+ * attempt started (concurrent-request queue full, or wait for a
334
+ * free slot exceeded the configured timeout). Distinct from
335
+ * `PRODUCTION_FAILED` by design: generation never ran, so callers
336
+ * MUST NOT bill or count it as a failed attempt. See
337
+ * {@link GenerationError} in `types/ui-generator.ts` for the full
338
+ * contract.
331
339
  */
332
340
  export declare const renderErrorCodeSchema: z.ZodEnum<{
333
341
  PRODUCTION_FAILED: "PRODUCTION_FAILED";
334
342
  VALIDATION_ERROR: "VALIDATION_ERROR";
335
343
  NO_PLATFORM_KEY: "NO_PLATFORM_KEY";
336
344
  NO_CREDENTIALS: "NO_CREDENTIALS";
345
+ GENERATION_QUEUE_OVERLOADED: "GENERATION_QUEUE_OVERLOADED";
337
346
  }>;
338
347
  /**
339
348
  * In-result failure marker for `ggui_render`. Present on the wire
@@ -347,6 +356,7 @@ export declare const renderErrorSchema: z.ZodObject<{
347
356
  VALIDATION_ERROR: "VALIDATION_ERROR";
348
357
  NO_PLATFORM_KEY: "NO_PLATFORM_KEY";
349
358
  NO_CREDENTIALS: "NO_CREDENTIALS";
359
+ GENERATION_QUEUE_OVERLOADED: "GENERATION_QUEUE_OVERLOADED";
350
360
  }>;
351
361
  message: z.ZodString;
352
362
  }, z.core.$strip>;
@@ -458,6 +468,7 @@ export declare const renderOutputSchema: z.ZodObject<{
458
468
  VALIDATION_ERROR: "VALIDATION_ERROR";
459
469
  NO_PLATFORM_KEY: "NO_PLATFORM_KEY";
460
470
  NO_CREDENTIALS: "NO_CREDENTIALS";
471
+ GENERATION_QUEUE_OVERLOADED: "GENERATION_QUEUE_OVERLOADED";
461
472
  }>;
462
473
  message: z.ZodString;
463
474
  }, z.core.$strip>>;
@@ -467,6 +478,7 @@ export declare const renderOutputSchema: z.ZodObject<{
467
478
  example: z.ZodString;
468
479
  args: z.ZodObject<{
469
480
  sessionId: z.ZodString;
481
+ timeout: z.ZodNumber;
470
482
  }, z.core.$strip>;
471
483
  }, z.core.$strip>>;
472
484
  }, z.core.$strip>;
@@ -510,21 +522,55 @@ export declare const updateInputSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
510
522
  kind: z.ZodLiteral<"merge">;
511
523
  patch: z.ZodRecord<z.ZodString, z.ZodUnknown>;
512
524
  }, z.core.$strict>], "kind">;
525
+ /**
526
+ * `ggui_amend` wire input (#483) — same replace/merge mutation
527
+ * grammar as `ggui_update`, different mount identity: amend targets
528
+ * the ALREADY-MOUNTED card. No new card, no history entry, the
529
+ * history number does not advance. Git reading: `ggui_update` =
530
+ * commit; `ggui_amend` = commit --amend.
531
+ */
532
+ export declare const amendInputSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
533
+ sessionId: z.ZodString;
534
+ kind: z.ZodLiteral<"replace">;
535
+ props: z.ZodRecord<z.ZodString, z.ZodUnknown>;
536
+ }, z.core.$strict>, z.ZodObject<{
537
+ sessionId: z.ZodString;
538
+ kind: z.ZodLiteral<"merge">;
539
+ patch: z.ZodRecord<z.ZodString, z.ZodUnknown>;
540
+ }, z.core.$strict>], "kind">;
513
541
  /**
514
542
  * Wire-output shape — minimal acknowledgement. The handler carries
515
543
  * `decision`, `contract`, `contractHash` on its internal `UpdateOutput`
516
544
  * TS shape — zod strips them before structuredContent serialization.
517
545
  *
518
- * Post-update the iframe receives the new props via the live-channel
519
- * `props_update` WS frame; the cross-host fallback path receives them
520
- * via the `ai.ggui/render.propsJson` slice field (see
521
- * `update.resultMeta`). The wire response itself is just
522
- * acknowledgement.
546
+ * Every REAL update (`updated: true`) mints a new history record and
547
+ * its result carries the `ai.ggui/render` slice as a FULL bootable
548
+ * mount package (#483 — hosts mint a per-result view for the new
549
+ * card); a no-op (`updated: false`) carries NO result `_meta`.
550
+ * Already-mounted frames are not repainted by update — they freeze as
551
+ * history when its higher-epoch `props_update` frame lands; the
552
+ * in-place repaint over the live-channel ladder (WS / SSE / polling /
553
+ * bridge-pull) is `ggui_amend`'s job.
523
554
  */
524
555
  export declare const updateOutputSchema: z.ZodObject<{
525
556
  sessionId: z.ZodString;
526
557
  updated: z.ZodBoolean;
527
558
  resourceUri: z.ZodString;
559
+ epoch: z.ZodNumber;
560
+ warning: z.ZodOptional<z.ZodString>;
561
+ }, z.core.$strip>;
562
+ /**
563
+ * `ggui_amend` wire output (#483) — acknowledgement only. `resourceUri`
564
+ * is the BARE live-head URI (amend targets the mounted card; it never
565
+ * mints a record, so there is no pinned URI to return and no epoch
566
+ * field — the history number is untouched by construction). The
567
+ * mounted card receives the new props over the live channels.
568
+ */
569
+ export declare const amendOutputSchema: z.ZodObject<{
570
+ sessionId: z.ZodString;
571
+ updated: z.ZodBoolean;
572
+ resourceUri: z.ZodString;
573
+ warning: z.ZodOptional<z.ZodString>;
528
574
  }, z.core.$strip>;
529
575
  /**
530
576
  * `ggui_runtime_declare_tool_catalog` — the host runtime declares its
@@ -560,4 +606,170 @@ export declare const declareToolCatalogOutputSchema: z.ZodObject<{
560
606
  saved: z.ZodBoolean;
561
607
  appId: z.ZodString;
562
608
  }, z.core.$strict>;
609
+ /**
610
+ * Server-side page cap for `ggui_runtime_pull`. A `limit` above this is
611
+ * CLAMPED (not rejected) — the tool mirrors the cursor-walk posture of
612
+ * the `/events` HTTP route, where a too-eager page size is a tuning
613
+ * knob, not a caller bug. Shared so the pulling client and the serving
614
+ * handler agree on the effective page ceiling from one constant.
615
+ */
616
+ export declare const RUNTIME_PULL_MAX_LIMIT = 100;
617
+ /**
618
+ * Server-side ceiling on `ggui_runtime_pull`'s `wait` hold, in seconds.
619
+ * Chosen under `ggui_consume`'s proven 25-second host tolerance for
620
+ * held tool calls — the hold must resolve before any host-side
621
+ * `tools/call` timeout fires, or the transport counts a failure the
622
+ * server intended as a quiet success.
623
+ */
624
+ export declare const RUNTIME_PULL_MAX_WAIT_SECONDS = 20;
625
+ /**
626
+ * One `GguiSessionEvent` ledger row on the `ggui_runtime_pull` wire —
627
+ * the zod mirror of the canonical `GguiSessionEvent` interface in
628
+ * `types/ggui-session-event.ts` (which stays the type-level source of
629
+ * truth; `mcp.test.ts` pins the two together in both directions).
630
+ */
631
+ export declare const gguiSessionEventSchema: z.ZodObject<{
632
+ seq: z.ZodNumber;
633
+ type: z.ZodString;
634
+ timestamp: z.ZodString;
635
+ data: z.ZodUnknown;
636
+ }, z.core.$strip>;
637
+ /**
638
+ * `ggui_runtime_pull` input — the terminal bridge-pull rung of the
639
+ * live-channel failover ladder (WS → SSE → HTTP polling → bridge-pull).
640
+ *
641
+ * Two named parties:
642
+ *
643
+ * - **Puller** — the `@ggui-ai/iframe-runtime` bridge rung. In a
644
+ * CSP-jailed MCP Apps host the iframe can reach no network origin
645
+ * at all, so it pulls the event ledger by issuing `tools/call`
646
+ * postMessages that the host's MCP client relays (the tool
647
+ * registers `_meta.ui.visibility: ['app']` per MCP Apps spec §401
648
+ * — hosts MUST route view-issued calls to it and MUST reject
649
+ * view-issued calls to tools without it).
650
+ * - **Server** — the MCP server hosting the render. It serves the
651
+ * SAME `GguiSessionEvent` ledger `GET
652
+ * /api/sessions/:sessionId/events` serves, through the same
653
+ * `listEventsSince` read, and MUST answer with the same shapes
654
+ * (see {@link runtimePullOutputSchema}) so one client parse core
655
+ * handles both carriers.
656
+ *
657
+ * Divergences from the HTTP route, both deliberate: `sinceSequence` is
658
+ * OPTIONAL here (the bridge rung owns its cursor and seeds from 0; the
659
+ * route requires it because a bare browser GET has no cursor owner),
660
+ * and `limit` is clamped to {@link RUNTIME_PULL_MAX_LIMIT} instead of
661
+ * rejecting above it. Tenancy violations and unknown sessionIds
662
+ * surface uniformly as the `session_not_found` error — existence of
663
+ * other tenants' renders is never leaked.
664
+ */
665
+ export declare const runtimePullInputShape: {
666
+ readonly sessionId: z.ZodString;
667
+ readonly sinceSequence: z.ZodOptional<z.ZodNumber>;
668
+ readonly limit: z.ZodOptional<z.ZodNumber>;
669
+ readonly wait: z.ZodOptional<z.ZodNumber>;
670
+ };
671
+ export declare const runtimePullInputSchema: z.ZodObject<{
672
+ sessionId: z.ZodString;
673
+ sinceSequence: z.ZodOptional<z.ZodNumber>;
674
+ limit: z.ZodOptional<z.ZodNumber>;
675
+ wait: z.ZodOptional<z.ZodNumber>;
676
+ }, z.core.$strip>;
677
+ /**
678
+ * Normal-page arm — EXACT `EventsResponse` parity with
679
+ * `GET /api/sessions/:sessionId/events` (same keys, same semantics):
680
+ * `events` strictly ascending by seq, `lastSequence` = the render's
681
+ * current high-water mark (NOT the page's last seq — advances the
682
+ * cursor on empty pages), `hasMore` = the page was truncated by
683
+ * `limit`.
684
+ */
685
+ export declare const runtimePullEventsPageSchema: z.ZodObject<{
686
+ events: z.ZodArray<z.ZodObject<{
687
+ seq: z.ZodNumber;
688
+ type: z.ZodString;
689
+ timestamp: z.ZodString;
690
+ data: z.ZodUnknown;
691
+ }, z.core.$strip>>;
692
+ lastSequence: z.ZodNumber;
693
+ hasMore: z.ZodBoolean;
694
+ }, z.core.$strip>;
695
+ /**
696
+ * Replay-horizon arm — parity with the route's 410 body, but on this
697
+ * carrier it is a NORMAL result arm, not an error: the bridge rung is
698
+ * terminal and treats it as a re-sync instruction. Returned when the
699
+ * cursor fell out of the replayable window on EITHER side
700
+ * (`sinceSequence` above the server's `lastSequence` — a cursor from a
701
+ * different deployment/reset render — or below the retention horizon).
702
+ * Client recovery: re-mount state from a fresh snapshot and reset the
703
+ * cursor to `currentSequence`.
704
+ */
705
+ export declare const runtimePullHorizonSchema: z.ZodObject<{
706
+ reason: z.ZodLiteral<"REPLAY_HORIZON_PASSED">;
707
+ currentSequence: z.ZodNumber;
708
+ }, z.core.$strip>;
709
+ /**
710
+ * `ggui_runtime_pull` output — the canonical strict wire contract, a
711
+ * two-arm union: {@link runtimePullEventsPageSchema} (normal page) |
712
+ * {@link runtimePullHorizonSchema} (cursor out of window). The handler
713
+ * registers a flat raw shape (MCP tool registration takes a
714
+ * `ZodRawShape`, which cannot express a top-level union) and its
715
+ * alignment test pins that shape to this union — same posture as
716
+ * `updateInputSchema`.
717
+ */
718
+ export declare const runtimePullOutputSchema: z.ZodUnion<readonly [z.ZodObject<{
719
+ events: z.ZodArray<z.ZodObject<{
720
+ seq: z.ZodNumber;
721
+ type: z.ZodString;
722
+ timestamp: z.ZodString;
723
+ data: z.ZodUnknown;
724
+ }, z.core.$strip>>;
725
+ lastSequence: z.ZodNumber;
726
+ hasMore: z.ZodBoolean;
727
+ }, z.core.$strip>, z.ZodObject<{
728
+ reason: z.ZodLiteral<"REPLAY_HORIZON_PASSED">;
729
+ currentSequence: z.ZodNumber;
730
+ }, z.core.$strip>]>;
731
+ /**
732
+ * Per-batch event cap on `ggui_runtime_telemetry` — a bounded
733
+ * fire-and-forget diagnostic channel, never a data plane.
734
+ */
735
+ export declare const RUNTIME_TELEMETRY_MAX_EVENTS = 40;
736
+ /**
737
+ * `ggui_runtime_telemetry` input — the iframe runtime's transport
738
+ * self-report (`_meta.ui.visibility: ['app']`, view-callable only).
739
+ *
740
+ * Contract (both parties named): the IFRAME RUNTIME batches short
741
+ * `{at, kind, detail?}` events describing its delivery-ladder journey
742
+ * (boot-path decision, per-rung status transitions and failures —
743
+ * `channel_failover_swap`, `channel_polling_budget_exhausted`, … —
744
+ * and outbound doorbell rings) and flushes them over the host's
745
+ * `tools/call` postMessage bridge; the SERVER logs one structured
746
+ * line per batch for operator forensics and stores NOTHING. Sandboxed
747
+ * hosts (claude.ai's `claudemcpcontent.com` frames) expose no
748
+ * readable console and no network — this tool is the ONLY way the
749
+ * ladder's behavior on such hosts reaches an operator. `sessionId` is
750
+ * client-claimed (log-tagged, never trusted for reads); events are
751
+ * bounded (≤ {@link RUNTIME_TELEMETRY_MAX_EVENTS} per batch, `kind` ≤
752
+ * 64 chars, `detail` ≤ 512) so a hostile view cannot use the channel
753
+ * for bulk exfiltration or log flooding.
754
+ */
755
+ export declare const runtimeTelemetryInputShape: {
756
+ readonly sessionId: z.ZodString;
757
+ readonly events: z.ZodArray<z.ZodObject<{
758
+ at: z.ZodNumber;
759
+ kind: z.ZodString;
760
+ detail: z.ZodOptional<z.ZodString>;
761
+ }, z.core.$strip>>;
762
+ };
763
+ export declare const runtimeTelemetryInputSchema: z.ZodObject<{
764
+ sessionId: z.ZodString;
765
+ events: z.ZodArray<z.ZodObject<{
766
+ at: z.ZodNumber;
767
+ kind: z.ZodString;
768
+ detail: z.ZodOptional<z.ZodString>;
769
+ }, z.core.$strip>>;
770
+ }, z.core.$strip>;
771
+ /** `ggui_runtime_telemetry` output — bare acknowledgement. */
772
+ export declare const runtimeTelemetryOutputSchema: z.ZodObject<{
773
+ ok: z.ZodLiteral<true>;
774
+ }, z.core.$strip>;
563
775
  //# sourceMappingURL=mcp.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../../src/schemas/mcp.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAUxB,eAAO,MAAM,cAAc;;;iBAGzB,CAAC;AAEH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAUnB,CAAC;AAYjB;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB;;;CAgBpB,CAAC;AAEX,eAAO,MAAM,kBAAkB;;;iBAA8B,CAAC;AAE9D;;;GAGG;AACH,eAAO,MAAM,cAAc;;;;;CAKjB,CAAC;AAEX,eAAO,MAAM,eAAe;;;;;iBAA2B,CAAC;AAExD,eAAO,MAAM,oBAAoB;;CAKvB,CAAC;AAEX,eAAO,MAAM,qBAAqB;;iBAAiC,CAAC;AAEpE;;;;;GAKG;AACH,eAAO,MAAM,gCAAgC,IAAc,CAAC;AAE5D,eAAO,MAAM,iCAAiC,gCAE7C,CAAC;AAEF,eAAO,MAAM,0BAA0B;;;;;CAwB7B,CAAC;AAEX,eAAO,MAAM,2BAA2B;;;;;iBAAuC,CAAC;AAEhF,eAAO,MAAM,yBAAyB;;CAO5B,CAAC;AAEX,eAAO,MAAM,0BAA0B;;iBAAsC,CAAC;AAE9E,eAAO,MAAM,kBAAkB,IAAc,CAAC;AAE9C,eAAO,MAAM,mBAAmB,gCAA+B,CAAC;AAahE;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,oBAAoB;;;;kBA0BtB,CAAC;AAEZ;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;iBAgChC,CAAC;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,eAAO,MAAM,gBAAgB;;IAO3B;;;;;;;;OAQG;;IAEH;;;;;OAKG;;IAQH;;;;;;;;;;OAUG;;;;IAaH;;;;;;;;;;;OAWG;;;;;CAuBK,CAAC;AAEX,eAAO,MAAM,iBAAiB;;;;;;;;;;;iBAA6B,CAAC;AAE5D;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;;;iBAyBlC,CAAC;AAEH;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,qBAAqB;;;;;EAKhC,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;iBAS5B,CAAC;AAEH;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,2BAA2B;;;;;EAKtC,CAAC;AAEH;;;;;;;;;;GAUG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;;iBAalC,CAAC;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAwE7B,CAAC;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;4BAa5B,CAAC;AAEH;;;;;;;;;;GAUG;AACH,eAAO,MAAM,kBAAkB;;;;iBAW7B,CAAC;AAEH;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,6BAA6B;;;;;kBAW/B,CAAC;AAEZ,eAAO,MAAM,8BAA8B;;;kBAKhC,CAAC"}
1
+ {"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../../src/schemas/mcp.ts"],"names":[],"mappings":"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"}
@@ -391,7 +391,7 @@ export const renderCacheMarkerSchema = z.object({
391
391
  /**
392
392
  * Canonical failure codes for the in-result `ggui_render` failure
393
393
  * envelope (SPEC §7.9 Plane 3). Closed enum — a failed render's
394
- * `error.code` is always one of these four; finer-grained diagnostics
394
+ * `error.code` is always one of these five; finer-grained diagnostics
395
395
  * ride on `error.message`.
396
396
  *
397
397
  * - `PRODUCTION_FAILED` — generation ran but did not produce a
@@ -403,12 +403,21 @@ export const renderCacheMarkerSchema = z.object({
403
403
  * configuration has no key for the resolved route.
404
404
  * - `NO_CREDENTIALS` — no generation credentials are configured on
405
405
  * the server at all.
406
+ * - `GENERATION_QUEUE_OVERLOADED` — the deployment's generation
407
+ * admission gate rejected this request before any generation
408
+ * attempt started (concurrent-request queue full, or wait for a
409
+ * free slot exceeded the configured timeout). Distinct from
410
+ * `PRODUCTION_FAILED` by design: generation never ran, so callers
411
+ * MUST NOT bill or count it as a failed attempt. See
412
+ * {@link GenerationError} in `types/ui-generator.ts` for the full
413
+ * contract.
406
414
  */
407
415
  export const renderErrorCodeSchema = z.enum([
408
416
  'PRODUCTION_FAILED',
409
417
  'VALIDATION_ERROR',
410
418
  'NO_PLATFORM_KEY',
411
419
  'NO_CREDENTIALS',
420
+ 'GENERATION_QUEUE_OVERLOADED',
412
421
  ]);
413
422
  /**
414
423
  * In-result failure marker for `ggui_render`. Present on the wire
@@ -417,7 +426,7 @@ export const renderErrorCodeSchema = z.enum([
417
426
  * canonical failure classification.
418
427
  */
419
428
  export const renderErrorSchema = z.object({
420
- 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.'),
429
+ 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) — not a failed attempt; safe to retry immediately.'),
421
430
  message: z
422
431
  .string()
423
432
  .describe('Human-readable failure detail — fold into the next attempt or surface to the operator.'),
@@ -556,8 +565,13 @@ export const renderOutputSchema = z.object({
556
565
  example: z.string(),
557
566
  args: z.object({
558
567
  sessionId: z.string(),
568
+ // The per-call long-poll window in seconds. Carried on the hint
569
+ // because consume's own default is 0 (single non-blocking
570
+ // drain): an agent copying a timeout-less hint gets an instant
571
+ // empty result and stops looping.
572
+ timeout: z.number(),
559
573
  }),
560
- }).optional().describe('Recovery hint — when the rendered contract has actions, points the agent at ggui_consume({sessionId}) for the inbound action loop. Absent for pure-display renders.'),
574
+ }).optional().describe('Required-next-call hint — when the rendered contract has actions, points the agent at ggui_consume({sessionId, timeout}) for the inbound action loop. Absent for pure-display renders.'),
561
575
  });
562
576
  /**
563
577
  * `ggui_update` — refresh the rendered UI with new state.
@@ -595,13 +609,34 @@ export const updateInputSchema = z.discriminatedUnion('kind', [
595
609
  sessionId: z.string().describe('GguiSession opaque id (UUID) — returned by ggui_render.'),
596
610
  kind: z.literal('replace'),
597
611
  props: z.record(z.string(), z.unknown())
598
- .describe('Full replacement props map. New map IS the new state.'),
612
+ .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.'),
599
613
  }).strict(),
600
614
  z.object({
601
615
  sessionId: z.string().describe('GguiSession opaque id (UUID) — returned by ggui_render.'),
602
616
  kind: z.literal('merge'),
603
617
  patch: z.record(z.string(), z.unknown())
604
- .describe('RFC 7396 JSON Merge Patch — null deletes a key; arrays fully replace.'),
618
+ .describe('RFC 7396 JSON Merge Patch — 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.'),
619
+ }).strict(),
620
+ ]);
621
+ /**
622
+ * `ggui_amend` wire input (#483) — same replace/merge mutation
623
+ * grammar as `ggui_update`, different mount identity: amend targets
624
+ * the ALREADY-MOUNTED card. No new card, no history entry, the
625
+ * history number does not advance. Git reading: `ggui_update` =
626
+ * commit; `ggui_amend` = commit --amend.
627
+ */
628
+ export const amendInputSchema = z.discriminatedUnion('kind', [
629
+ z.object({
630
+ sessionId: z.string().describe('GguiSession opaque id (UUID) — returned by ggui_render.'),
631
+ kind: z.literal('replace'),
632
+ props: z.record(z.string(), z.unknown())
633
+ .describe('Full replacement props map, applied to the currently mounted card in place.'),
634
+ }).strict(),
635
+ z.object({
636
+ sessionId: z.string().describe('GguiSession opaque id (UUID) — returned by ggui_render.'),
637
+ kind: z.literal('merge'),
638
+ patch: z.record(z.string(), z.unknown())
639
+ .describe('RFC 7396 JSON Merge Patch — null deletes a key; arrays fully replace. Applied to the currently mounted card in place.'),
605
640
  }).strict(),
606
641
  ]);
607
642
  /**
@@ -609,23 +644,61 @@ export const updateInputSchema = z.discriminatedUnion('kind', [
609
644
  * `decision`, `contract`, `contractHash` on its internal `UpdateOutput`
610
645
  * TS shape — zod strips them before structuredContent serialization.
611
646
  *
612
- * Post-update the iframe receives the new props via the live-channel
613
- * `props_update` WS frame; the cross-host fallback path receives them
614
- * via the `ai.ggui/render.propsJson` slice field (see
615
- * `update.resultMeta`). The wire response itself is just
616
- * acknowledgement.
647
+ * Every REAL update (`updated: true`) mints a new history record and
648
+ * its result carries the `ai.ggui/render` slice as a FULL bootable
649
+ * mount package (#483 — hosts mint a per-result view for the new
650
+ * card); a no-op (`updated: false`) carries NO result `_meta`.
651
+ * Already-mounted frames are not repainted by update — they freeze as
652
+ * history when its higher-epoch `props_update` frame lands; the
653
+ * in-place repaint over the live-channel ladder (WS / SSE / polling /
654
+ * bridge-pull) is `ggui_amend`'s job.
617
655
  */
618
656
  export const updateOutputSchema = z.object({
619
657
  sessionId: z.string(),
620
658
  updated: z.boolean(),
621
659
  /**
622
- * Unchanged from the initial render — the same `ui://ggui/render/{id}`
623
- * URI the mount stamped. Mirrored on the LLM-visible structuredContent
624
- * so SDKs that strip `_meta` from tool_results can still reach the
660
+ * The epoch-pinned URI of the NEW history record this update minted
661
+ * (`ui://ggui/render/{id}[/{key}]#{epoch}` — see epoch-uri.ts). On a
662
+ * no-op (`updated: false`) no record is minted and this is the bare
663
+ * live-head URI. Mirrored on the LLM-visible structuredContent so
664
+ * SDKs that strip `_meta` from tool_results can still reach the
625
665
  * mount URI. Kept in sync with the update handler's wire shape —
626
666
  * this export and the handler's inline schema must not drift.
627
667
  */
628
668
  resourceUri: z.string(),
669
+ /**
670
+ * The session's head epoch after this call: advanced by one on a
671
+ * real update (`updated: true`), unchanged on a no-op. `ggui_render`
672
+ * mints epoch 0. The session ROW is the authority
673
+ * (`GguiSessionBase.epoch`, absent ⇒ 0); the ledger's `ui.reminted`
674
+ * events are the wire signal only — the ledger is horizon-bounded
675
+ * and must never be counted as the source of truth.
676
+ */
677
+ epoch: z.number().int().min(0),
678
+ /**
679
+ * Present ONLY on a no-op (`updated: false`): the patch conformed to
680
+ * the contract but left the final props semantically identical to
681
+ * the current state, so nothing was written, nothing changes on
682
+ * screen, and NO new history record was minted. Model-visible by
683
+ * design — the common producer of a no-op is an agent echoing
684
+ * existing props back believing it changed the UI, and this field is
685
+ * its feedback channel.
686
+ */
687
+ warning: z.string().optional(),
688
+ });
689
+ /**
690
+ * `ggui_amend` wire output (#483) — acknowledgement only. `resourceUri`
691
+ * is the BARE live-head URI (amend targets the mounted card; it never
692
+ * mints a record, so there is no pinned URI to return and no epoch
693
+ * field — the history number is untouched by construction). The
694
+ * mounted card receives the new props over the live channels.
695
+ */
696
+ export const amendOutputSchema = z.object({
697
+ sessionId: z.string(),
698
+ updated: z.boolean(),
699
+ resourceUri: z.string(),
700
+ /** Same no-op feedback channel as ggui_update's `warning`. */
701
+ warning: z.string().optional(),
629
702
  });
630
703
  /**
631
704
  * `ggui_runtime_declare_tool_catalog` — the host runtime declares its
@@ -664,3 +737,188 @@ export const declareToolCatalogOutputSchema = z
664
737
  appId: z.string(),
665
738
  })
666
739
  .strict();
740
+ // ── `ggui_runtime_pull` — bridge-pull rung of the live-channel ladder ──
741
+ /**
742
+ * Server-side page cap for `ggui_runtime_pull`. A `limit` above this is
743
+ * CLAMPED (not rejected) — the tool mirrors the cursor-walk posture of
744
+ * the `/events` HTTP route, where a too-eager page size is a tuning
745
+ * knob, not a caller bug. Shared so the pulling client and the serving
746
+ * handler agree on the effective page ceiling from one constant.
747
+ */
748
+ export const RUNTIME_PULL_MAX_LIMIT = 100;
749
+ /**
750
+ * Server-side ceiling on `ggui_runtime_pull`'s `wait` hold, in seconds.
751
+ * Chosen under `ggui_consume`'s proven 25-second host tolerance for
752
+ * held tool calls — the hold must resolve before any host-side
753
+ * `tools/call` timeout fires, or the transport counts a failure the
754
+ * server intended as a quiet success.
755
+ */
756
+ export const RUNTIME_PULL_MAX_WAIT_SECONDS = 20;
757
+ /**
758
+ * One `GguiSessionEvent` ledger row on the `ggui_runtime_pull` wire —
759
+ * the zod mirror of the canonical `GguiSessionEvent` interface in
760
+ * `types/ggui-session-event.ts` (which stays the type-level source of
761
+ * truth; `mcp.test.ts` pins the two together in both directions).
762
+ */
763
+ export const gguiSessionEventSchema = z.object({
764
+ seq: z
765
+ .number()
766
+ .int()
767
+ .min(1)
768
+ .describe('Monotonic, gap-free per render; starts at 1 (0 is the "no events yet" cursor sentinel, never an event).'),
769
+ type: z
770
+ .string()
771
+ .min(1)
772
+ .describe('Wire-frame type — see the canonical GguiSessionEventType taxonomy; plain string so servers can mint new types without a protocol bump.'),
773
+ timestamp: z
774
+ .string()
775
+ .describe('ISO 8601 UTC timestamp the server stamped on emission.'),
776
+ data: z
777
+ .unknown()
778
+ .describe('Type-specific payload — structurally identical to the matching live-channel frame payload.'),
779
+ });
780
+ /**
781
+ * `ggui_runtime_pull` input — the terminal bridge-pull rung of the
782
+ * live-channel failover ladder (WS → SSE → HTTP polling → bridge-pull).
783
+ *
784
+ * Two named parties:
785
+ *
786
+ * - **Puller** — the `@ggui-ai/iframe-runtime` bridge rung. In a
787
+ * CSP-jailed MCP Apps host the iframe can reach no network origin
788
+ * at all, so it pulls the event ledger by issuing `tools/call`
789
+ * postMessages that the host's MCP client relays (the tool
790
+ * registers `_meta.ui.visibility: ['app']` per MCP Apps spec §401
791
+ * — hosts MUST route view-issued calls to it and MUST reject
792
+ * view-issued calls to tools without it).
793
+ * - **Server** — the MCP server hosting the render. It serves the
794
+ * SAME `GguiSessionEvent` ledger `GET
795
+ * /api/sessions/:sessionId/events` serves, through the same
796
+ * `listEventsSince` read, and MUST answer with the same shapes
797
+ * (see {@link runtimePullOutputSchema}) so one client parse core
798
+ * handles both carriers.
799
+ *
800
+ * Divergences from the HTTP route, both deliberate: `sinceSequence` is
801
+ * OPTIONAL here (the bridge rung owns its cursor and seeds from 0; the
802
+ * route requires it because a bare browser GET has no cursor owner),
803
+ * and `limit` is clamped to {@link RUNTIME_PULL_MAX_LIMIT} instead of
804
+ * rejecting above it. Tenancy violations and unknown sessionIds
805
+ * surface uniformly as the `session_not_found` error — existence of
806
+ * other tenants' renders is never leaked.
807
+ */
808
+ export const runtimePullInputShape = {
809
+ sessionId: z
810
+ .string()
811
+ .min(1)
812
+ .describe('Active render id — sourced from `_meta["ai.ggui/render"].sessionId` on the iframe boot envelope. Unknown and cross-tenant ids surface uniformly as session_not_found.'),
813
+ sinceSequence: z
814
+ .number()
815
+ .int()
816
+ .min(0)
817
+ .optional()
818
+ .describe('Replay cursor — 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.'),
819
+ limit: z
820
+ .number()
821
+ .int()
822
+ .min(1)
823
+ .optional()
824
+ .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.`),
825
+ wait: z
826
+ .number()
827
+ .min(0)
828
+ .optional()
829
+ .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 — 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.`),
830
+ };
831
+ export const runtimePullInputSchema = z.object(runtimePullInputShape);
832
+ /**
833
+ * Normal-page arm — EXACT `EventsResponse` parity with
834
+ * `GET /api/sessions/:sessionId/events` (same keys, same semantics):
835
+ * `events` strictly ascending by seq, `lastSequence` = the render's
836
+ * current high-water mark (NOT the page's last seq — advances the
837
+ * cursor on empty pages), `hasMore` = the page was truncated by
838
+ * `limit`.
839
+ */
840
+ export const runtimePullEventsPageSchema = z.object({
841
+ events: z.array(gguiSessionEventSchema),
842
+ lastSequence: z.number().int().min(0),
843
+ hasMore: z.boolean(),
844
+ });
845
+ /**
846
+ * Replay-horizon arm — parity with the route's 410 body, but on this
847
+ * carrier it is a NORMAL result arm, not an error: the bridge rung is
848
+ * terminal and treats it as a re-sync instruction. Returned when the
849
+ * cursor fell out of the replayable window on EITHER side
850
+ * (`sinceSequence` above the server's `lastSequence` — a cursor from a
851
+ * different deployment/reset render — or below the retention horizon).
852
+ * Client recovery: re-mount state from a fresh snapshot and reset the
853
+ * cursor to `currentSequence`.
854
+ */
855
+ export const runtimePullHorizonSchema = z.object({
856
+ reason: z.literal('REPLAY_HORIZON_PASSED'),
857
+ currentSequence: z.number().int().min(0),
858
+ });
859
+ /**
860
+ * `ggui_runtime_pull` output — the canonical strict wire contract, a
861
+ * two-arm union: {@link runtimePullEventsPageSchema} (normal page) |
862
+ * {@link runtimePullHorizonSchema} (cursor out of window). The handler
863
+ * registers a flat raw shape (MCP tool registration takes a
864
+ * `ZodRawShape`, which cannot express a top-level union) and its
865
+ * alignment test pins that shape to this union — same posture as
866
+ * `updateInputSchema`.
867
+ */
868
+ export const runtimePullOutputSchema = z.union([
869
+ runtimePullEventsPageSchema,
870
+ runtimePullHorizonSchema,
871
+ ]);
872
+ /**
873
+ * Per-batch event cap on `ggui_runtime_telemetry` — a bounded
874
+ * fire-and-forget diagnostic channel, never a data plane.
875
+ */
876
+ export const RUNTIME_TELEMETRY_MAX_EVENTS = 40;
877
+ /**
878
+ * `ggui_runtime_telemetry` input — the iframe runtime's transport
879
+ * self-report (`_meta.ui.visibility: ['app']`, view-callable only).
880
+ *
881
+ * Contract (both parties named): the IFRAME RUNTIME batches short
882
+ * `{at, kind, detail?}` events describing its delivery-ladder journey
883
+ * (boot-path decision, per-rung status transitions and failures —
884
+ * `channel_failover_swap`, `channel_polling_budget_exhausted`, … —
885
+ * and outbound doorbell rings) and flushes them over the host's
886
+ * `tools/call` postMessage bridge; the SERVER logs one structured
887
+ * line per batch for operator forensics and stores NOTHING. Sandboxed
888
+ * hosts (claude.ai's `claudemcpcontent.com` frames) expose no
889
+ * readable console and no network — this tool is the ONLY way the
890
+ * ladder's behavior on such hosts reaches an operator. `sessionId` is
891
+ * client-claimed (log-tagged, never trusted for reads); events are
892
+ * bounded (≤ {@link RUNTIME_TELEMETRY_MAX_EVENTS} per batch, `kind` ≤
893
+ * 64 chars, `detail` ≤ 512) so a hostile view cannot use the channel
894
+ * for bulk exfiltration or log flooding.
895
+ */
896
+ export const runtimeTelemetryInputShape = {
897
+ sessionId: z
898
+ .string()
899
+ .min(1)
900
+ .describe('Render id the report concerns — sourced from the boot envelope. Client-claimed: used as a log tag only.'),
901
+ events: z
902
+ .array(z.object({
903
+ at: z
904
+ .number()
905
+ .min(0)
906
+ .describe('Milliseconds since iframe boot (monotonic, client clock).'),
907
+ kind: z
908
+ .string()
909
+ .min(1)
910
+ .max(64)
911
+ .describe("Event name — e.g. 'boot.path', 'status.connected', 'channel_failover_swap', 'doorbell.ring'."),
912
+ detail: z
913
+ .string()
914
+ .max(512)
915
+ .optional()
916
+ .describe('Optional compact context (JSON fragment or message).'),
917
+ }))
918
+ .min(1)
919
+ .max(RUNTIME_TELEMETRY_MAX_EVENTS)
920
+ .describe('Batched ladder/doorbell events, oldest first.'),
921
+ };
922
+ export const runtimeTelemetryInputSchema = z.object(runtimeTelemetryInputShape);
923
+ /** `ggui_runtime_telemetry` output — bare acknowledgement. */
924
+ export const runtimeTelemetryOutputSchema = z.object({ ok: z.literal(true) });
@@ -170,8 +170,8 @@ export interface StreamChannelEntry {
170
170
  /**
171
171
  * JSON Schema for the channel payload. This is the authoritative
172
172
  * shape guard for every delivery on this channel — live-channel
173
- * enforcement points (hosted fan-out, OSS `/ws`, `@ggui-ai/react`
174
- * data receipt, `@ggui-ai/react-native` data receipt) all validate
173
+ * enforcement points (hosted fan-out, OSS `/ws`, `@ggui-ai/mcp-apps-react`
174
+ * data receipt, `@ggui-ai/mcp-apps-react-native` data receipt) all validate
175
175
  * deliveries against it.
176
176
  *
177
177
  * When the channel declares a `source.tool` feed, the protocol-level