@ggui-ai/iframe-runtime 0.25.0 → 0.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/channels/data.d.ts +8 -0
- package/dist/channels/data.js +2 -0
- package/dist/credential-controller.d.ts +71 -0
- package/dist/credential-controller.js +135 -0
- package/dist/iframe-runtime.js +97 -94
- package/dist/iframe-runtime.meta.json +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/ladders.d.ts +77 -0
- package/dist/ladders.js +383 -0
- package/dist/meta-parse.js +38 -8
- package/dist/observability.d.ts +22 -1
- package/dist/react-renderer.d.ts +20 -0
- package/dist/react-renderer.js +22 -0
- package/dist/registry-subscribe.d.ts +37 -1
- package/dist/registry-subscribe.js +34 -8
- package/dist/render-failure-report.d.ts +15 -0
- package/dist/render-failure-report.js +61 -0
- package/dist/render-item.d.ts +3 -0
- package/dist/render-item.js +2 -0
- package/dist/runtime-telemetry.d.ts +28 -18
- package/dist/runtime-telemetry.js +68 -29
- package/dist/runtime.d.ts +114 -35
- package/dist/runtime.js +556 -309
- package/dist/stream-seq.d.ts +56 -0
- package/dist/stream-seq.js +46 -0
- package/dist/system-cards/ProtocolProbeCard.d.ts +16 -0
- package/dist/system-cards/ProtocolProbeCard.js +17 -14
- package/dist/tool-result-error.d.ts +6 -0
- package/dist/tool-result-error.js +32 -0
- package/dist/types.d.ts +49 -1
- package/dist/view-origin.d.ts +29 -0
- package/dist/view-origin.js +33 -0
- package/dist/view-proof-signer.d.ts +31 -0
- package/dist/view-proof-signer.js +99 -0
- package/dist/view-root.d.ts +51 -0
- package/dist/view-root.js +56 -0
- package/dist/wire-config.d.ts +13 -0
- package/dist/wire-config.js +39 -1
- package/package.json +8 -7
package/dist/runtime.d.ts
CHANGED
|
@@ -29,14 +29,16 @@ import type { DrainAckPayload, JsonValue, JsonObject, GguiSession } from '@ggui-
|
|
|
29
29
|
import type { WebSocketMessage } from '@ggui-ai/protocol/transport/websocket';
|
|
30
30
|
import { type McpAppAiGguiRenderMeta, type McpAppBootstrapFailedMessage, type McpAppRendererReadyMessage } from '@ggui-ai/protocol/integrations/mcp-apps';
|
|
31
31
|
import type { GguiSessionSeedInput } from './types.js';
|
|
32
|
-
import type { McpAppAiGguiMetaParseFailureReason } from './types.js';
|
|
32
|
+
import type { HeldCredential, McpAppAiGguiMetaParseFailureReason, ViewRoot } from './types.js';
|
|
33
|
+
import type { ViewRootHolder } from './view-root.js';
|
|
34
|
+
import { type StreamSeqTracker } from './stream-seq.js';
|
|
33
35
|
import { App } from '@modelcontextprotocol/ext-apps';
|
|
34
36
|
import type { McpUiDisplayMode } from '@modelcontextprotocol/ext-apps';
|
|
35
37
|
import type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';
|
|
36
38
|
import type { GadgetPackageRegistry } from './globals.js';
|
|
37
39
|
import { StreamBus } from './wire-config.js';
|
|
38
40
|
import { type ChannelTransportRouter } from './channel-transport.js';
|
|
39
|
-
import {
|
|
41
|
+
import type { ChannelHandler } from '@ggui-ai/live-channel';
|
|
40
42
|
import { type TelemetrySink } from './runtime-telemetry.js';
|
|
41
43
|
import { type ConnectFn } from './registry-subscribe.js';
|
|
42
44
|
import { type StatusRefs } from './status-dom.js';
|
|
@@ -45,6 +47,7 @@ import type { WireConfig } from '@ggui-ai/wire';
|
|
|
45
47
|
import { type ProtocolErrorEmitter } from './protocol-error.js';
|
|
46
48
|
import { type ObservabilityEmitter } from './observability.js';
|
|
47
49
|
import { type LifecycleEmitter } from './lifecycle.js';
|
|
50
|
+
import { type ContextSnapshotPoster } from './context-observer.js';
|
|
48
51
|
/**
|
|
49
52
|
* Drain-ack listener registry. Module-scoped so the dispatch path can
|
|
50
53
|
* register a frame-listener without threading it through the renderer.
|
|
@@ -337,8 +340,10 @@ export interface BootSequenceOptions {
|
|
|
337
340
|
* canonical async toolresult) are skipped. The App handshake still
|
|
338
341
|
* runs — spec mandates `ui/initialize` regardless of how slice meta
|
|
339
342
|
* arrives, and `hostContext` is captured from `app.getHostContext()`.
|
|
343
|
+
* The slice's held credential, when it has one, is refreshed exactly
|
|
344
|
+
* as a slice this boot resolved itself (ggui#1496).
|
|
340
345
|
*/
|
|
341
|
-
readonly
|
|
346
|
+
readonly preResolved?: BootMeta;
|
|
342
347
|
/**
|
|
343
348
|
* Autostart-layer pre-resolution of the read-plane door (ggui#537):
|
|
344
349
|
* a tool result that arrived before `bootSequence` ran carried the
|
|
@@ -347,9 +352,17 @@ export interface BootSequenceOptions {
|
|
|
347
352
|
* before the App is connected, so the locator is threaded here and
|
|
348
353
|
* resolved via {@link resolveMetaViaReadDoor} right after the
|
|
349
354
|
* handshake, ahead of the Tier 2 tool-result wait. Ignored when
|
|
350
|
-
* `
|
|
355
|
+
* `preResolved` is set.
|
|
351
356
|
*/
|
|
352
357
|
readonly preResolvedLocator?: string;
|
|
358
|
+
/**
|
|
359
|
+
* Test seam for the boot refresh's waits (ggui#1496): the retry delay's
|
|
360
|
+
* `sleep` and `random`. Defaults to a `setTimeout` wait and `Math.random`.
|
|
361
|
+
*/
|
|
362
|
+
readonly credentialTiming?: {
|
|
363
|
+
readonly sleep?: (ms: number) => Promise<void>;
|
|
364
|
+
readonly random?: () => number;
|
|
365
|
+
};
|
|
353
366
|
/**
|
|
354
367
|
* How long to wait for the spec-canonical `ui/notifications/tool-result`
|
|
355
368
|
* notification (Tier 2 of the resolver chain) before failing with
|
|
@@ -358,6 +371,12 @@ export interface BootSequenceOptions {
|
|
|
358
371
|
* timeout so the spec doesn't hang.
|
|
359
372
|
*/
|
|
360
373
|
readonly toolResultTimeoutMs?: number;
|
|
374
|
+
/**
|
|
375
|
+
* Test seam for the view's key root (ggui#1415): the holder the boot and
|
|
376
|
+
* every later tool result offer their slice's root to. Defaults to the
|
|
377
|
+
* document's one holder.
|
|
378
|
+
*/
|
|
379
|
+
readonly viewRoots?: ViewRootHolder;
|
|
361
380
|
}
|
|
362
381
|
/**
|
|
363
382
|
* Renderer hooks. The real iframe boot plumbs these via
|
|
@@ -449,20 +468,23 @@ export interface RendererHandle {
|
|
|
449
468
|
*/
|
|
450
469
|
readonly channelTransport: ChannelTransportRouter;
|
|
451
470
|
/**
|
|
452
|
-
*
|
|
453
|
-
*
|
|
454
|
-
* `
|
|
455
|
-
* registry-bound transport is the sole dispatch surface — frames
|
|
456
|
-
* arrive directly through registered handlers, no longer through a
|
|
471
|
+
* The handlers for every frame type the iframe routes (`render`,
|
|
472
|
+
* `data`, `props_update`, `drain_ack`, `channel_payload`,
|
|
473
|
+
* `channel_error`). Frames arrive directly through them, not through a
|
|
457
474
|
* separate `onMessage` callback.
|
|
458
475
|
*
|
|
459
|
-
* `bootSequence`
|
|
460
|
-
*
|
|
461
|
-
*
|
|
462
|
-
* `subscribe-handshake` handlers (`ack`, `error`)
|
|
463
|
-
|
|
476
|
+
* `bootSequence`'s ladder set (ggui#1496) registers these same objects
|
|
477
|
+
* on each ladder's registry, one per credential, behind a gate that
|
|
478
|
+
* lets only the ladder holding the data deliver. `connectViaRegistry`
|
|
479
|
+
* adds the per-ladder `subscribe-handshake` handlers (`ack`, `error`).
|
|
480
|
+
*/
|
|
481
|
+
readonly channelHandlers: readonly ChannelHandler[];
|
|
482
|
+
/**
|
|
483
|
+
* The view's stream cursor (ggui#1496): the highest stamped `data`
|
|
484
|
+
* envelope `seq` applied. The `data` handler dedupes on it, and a new
|
|
485
|
+
* subscribe resumes the stream from it (`fromSeq`).
|
|
464
486
|
*/
|
|
465
|
-
readonly
|
|
487
|
+
readonly streamSeq: StreamSeqTracker;
|
|
466
488
|
/**
|
|
467
489
|
* 3rd-party gadget-package merge promise. `installGlobalRegistry`
|
|
468
490
|
* seeds `__ggui__.gadgets` synchronously with the STDLIB namespace;
|
|
@@ -488,18 +510,35 @@ export interface BootSequenceResult {
|
|
|
488
510
|
readonly mountedRender: GguiSession | GguiSessionSeedInput | null;
|
|
489
511
|
}
|
|
490
512
|
export declare function bootSequence(opts: BootSequenceOptions): Promise<BootSequenceResult>;
|
|
513
|
+
/**
|
|
514
|
+
* A resolved boot slice (ggui#1496): the meta to mount, and the expired
|
|
515
|
+
* live credential the parse held back from it, when there was one. Every
|
|
516
|
+
* boot resolver returns this, so the held credential survives every path
|
|
517
|
+
* to {@link bootSequence}, which refreshes it once through the host.
|
|
518
|
+
*/
|
|
519
|
+
export interface BootMeta {
|
|
520
|
+
readonly meta: McpAppAiGguiRenderMeta;
|
|
521
|
+
readonly held?: HeldCredential;
|
|
522
|
+
/** The slice's view key root, when it carries one (ggui#1415). */
|
|
523
|
+
readonly viewRoot?: ViewRoot;
|
|
524
|
+
}
|
|
525
|
+
/**
|
|
526
|
+
* The bridge rung's `tools/call` over the host relay (ggui#1415): every
|
|
527
|
+
* `ggui_runtime_pull` it sends goes through {@link withViewProof}.
|
|
528
|
+
*
|
|
529
|
+
* @internal — exported for unit tests + production reuse.
|
|
530
|
+
*/
|
|
531
|
+
export declare function bridgeCallToolVia(app: App): (name: string, args: Record<string, unknown>) => ReturnType<App['callServerTool']>;
|
|
491
532
|
/**
|
|
492
533
|
* Read `globalThis.__GGUI_META__` synchronously, validate against
|
|
493
|
-
* the unified slice-meta shape, and return the
|
|
534
|
+
* the unified slice-meta shape, and return the boot slice (or null
|
|
494
535
|
* on absence / malformation).
|
|
495
536
|
*
|
|
496
|
-
* Thin wrapper around {@link parseMetaFromGlobal}
|
|
497
|
-
*
|
|
498
|
-
*
|
|
499
|
-
* reader contract — the autostart resolver only needs the "valid
|
|
500
|
-
* meta or fall through" signal.
|
|
537
|
+
* Thin wrapper around {@link parseMetaFromGlobal}. Returns `null`
|
|
538
|
+
* instead of {@link McpAppAiGguiMetaParseResult} because the autostart
|
|
539
|
+
* resolver only needs the "a slice to boot, or fall through" signal.
|
|
501
540
|
*/
|
|
502
|
-
export declare function readSelfContainedMeta():
|
|
541
|
+
export declare function readSelfContainedMeta(): BootMeta | null;
|
|
503
542
|
/**
|
|
504
543
|
* Project the inline `__GGUI_META__` bootstrap into a
|
|
505
544
|
* {@link GguiSessionSeedInput} the mount surface can paint immediately,
|
|
@@ -565,7 +604,7 @@ export declare function hasStaticContentMeta(meta: McpAppAiGguiRenderMeta): bool
|
|
|
565
604
|
* lagged the protocol" bug class: shell + runtime drift becomes
|
|
566
605
|
* impossible because the shell never inspects the slice-meta shape.
|
|
567
606
|
*/
|
|
568
|
-
export declare function extractMetaFromToolResult(params: unknown):
|
|
607
|
+
export declare function extractMetaFromToolResult(params: unknown): BootMeta | null;
|
|
569
608
|
/**
|
|
570
609
|
* Drain `window.__GGUI_PENDING_TOOL_RESULTS__` — the buffer the
|
|
571
610
|
* minimal shell populates while messages arrive between
|
|
@@ -584,7 +623,7 @@ export declare function extractMetaFromToolResult(params: unknown): McpAppAiGgui
|
|
|
584
623
|
* notifications, in arrival order (shells cap it newest-biased). The
|
|
585
624
|
* runtime reads it once at autostart.
|
|
586
625
|
*/
|
|
587
|
-
export declare function readPendingToolResults():
|
|
626
|
+
export declare function readPendingToolResults(): BootMeta | null;
|
|
588
627
|
/**
|
|
589
628
|
* Sibling of {@link readPendingToolResults} for the read-plane-only
|
|
590
629
|
* posture (ggui#537): the NEWEST buffered tool result that carries a
|
|
@@ -607,7 +646,20 @@ export declare function readPendingToolResultLocator(): string | null;
|
|
|
607
646
|
* slice would be. `null` on any miss (host cannot proxy reads, resource
|
|
608
647
|
* gone, no envelope) — the caller's other tiers still decide.
|
|
609
648
|
*/
|
|
610
|
-
export declare function resolveMetaViaReadDoor(app: App, locator: string): Promise<
|
|
649
|
+
export declare function resolveMetaViaReadDoor(app: App, locator: string): Promise<BootMeta | null>;
|
|
650
|
+
/**
|
|
651
|
+
* Production {@link ContextSnapshotPoster} — the seam the
|
|
652
|
+
* context-observer factories consume. Splits the two destinations:
|
|
653
|
+
*
|
|
654
|
+
* - `postUpdateModelContext` → spec-canonical
|
|
655
|
+
* `app.updateModelContext(...)` (via {@link callAppUpdateModelContext}).
|
|
656
|
+
* - `postContextMirror` → raw `tools/call ggui_runtime_sync_context`
|
|
657
|
+
* via {@link postToParent} (the host-relay mirror path; not yet
|
|
658
|
+
* migrated to `app.callServerTool` — see emitAudit for the same
|
|
659
|
+
* posture).
|
|
660
|
+
*/
|
|
661
|
+
/** @internal — exported for unit tests. */
|
|
662
|
+
export declare const productionContextSnapshotPoster: ContextSnapshotPoster;
|
|
611
663
|
/**
|
|
612
664
|
* Fire a single canonical action envelope (`tools/call
|
|
613
665
|
* ggui_runtime_submit_action`) carrying the typed `{kind, payload, …}` shape
|
|
@@ -670,17 +722,21 @@ interface ToastLiveRegions {
|
|
|
670
722
|
*/
|
|
671
723
|
export declare function ensureToastAnnouncer(doc: Document): ToastLiveRegions | null;
|
|
672
724
|
/**
|
|
673
|
-
*
|
|
674
|
-
*
|
|
675
|
-
*
|
|
676
|
-
* —
|
|
677
|
-
*
|
|
725
|
+
* The drawn toast for a dispatched action: a fixed-position element at
|
|
726
|
+
* the bottom of the iframe, drawn only when the visitor has to know or do
|
|
727
|
+
* something (the copy is {@link GESTURE_COPY}). Two kinds reach it:
|
|
728
|
+
* - `'error'` — the gesture did not go through: the relay refused it or
|
|
729
|
+
* could not be reached, or the card's own contract refused it. Nothing
|
|
730
|
+
* reached the pipe, so no `ui/message` doorbell fires (SPEC §4.7
|
|
731
|
+
* "Failure-soft client posture");
|
|
732
|
+
* - `'action_required'` — the gesture is queued but no consumer is
|
|
733
|
+
* listening and this host cannot take (or refused) the wake-up, so the
|
|
734
|
+
* visitor must send a message to continue.
|
|
735
|
+
* A tap that went through, or a wake-up the host took, is spoken, never
|
|
736
|
+
* drawn.
|
|
678
737
|
*
|
|
679
|
-
* Without
|
|
680
|
-
*
|
|
681
|
-
* agent is busy" from "click was lost". Especially load-bearing in
|
|
682
|
-
* the consume-pipe vs ui/message dual-path era — the toast tells
|
|
683
|
-
* the user which path the gesture actually took.
|
|
738
|
+
* Without it, a failed gesture would be silent: the visitor could not tell
|
|
739
|
+
* "the agent is busy" from "the tap was lost".
|
|
684
740
|
*
|
|
685
741
|
* Direct DOM (not React-managed) because:
|
|
686
742
|
* - Works during boot before React mounts.
|
|
@@ -712,6 +768,29 @@ export declare function ensureToastAnnouncer(doc: Document): ToastLiveRegions |
|
|
|
712
768
|
* @internal — exported for unit tests.
|
|
713
769
|
*/
|
|
714
770
|
export declare function declaredActionLabel(render: GguiSession | GguiSessionSeedInput | null, actionName: string): string | undefined;
|
|
771
|
+
/** @internal — exported for unit tests. */
|
|
772
|
+
export declare function isActionSpentByRefusal(renderId: string, actionName: string): boolean;
|
|
773
|
+
/**
|
|
774
|
+
* ggui#1424 — a post-ack `error` frame from the live channel. The channel
|
|
775
|
+
* door refuses a second gesture on a spent one-shot with its
|
|
776
|
+
* CONTRACT_VIOLATION frame and a violation at `actionSpec.<name>.oneShot`;
|
|
777
|
+
* that one means done, the same as the tool answer. Any other error frame
|
|
778
|
+
* changes nothing here.
|
|
779
|
+
*
|
|
780
|
+
* @internal — exported for unit tests.
|
|
781
|
+
*/
|
|
782
|
+
export declare function handlePostAckErrorFrame(renderId: string, payload: {
|
|
783
|
+
readonly code: string;
|
|
784
|
+
readonly message?: string;
|
|
785
|
+
readonly details?: unknown;
|
|
786
|
+
}): void;
|
|
787
|
+
/**
|
|
788
|
+
* The toast for a tap the outbound contract check refused (ggui#1536): the
|
|
789
|
+
* ordinary error toast, named by the action's declared label.
|
|
790
|
+
*
|
|
791
|
+
* @internal — exported for unit tests + production reuse.
|
|
792
|
+
*/
|
|
793
|
+
export declare function showRefusedDispatchToast(label: string | undefined): void;
|
|
715
794
|
/**
|
|
716
795
|
* Boot-time reset of the relay latch (ggui#670 Phase 3). A latch
|
|
717
796
|
* standing from a prior mount in a re-booted document is closed through
|