@ggui-ai/iframe-runtime 0.1.0-rc.3 → 0.2.0-alpha.1

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 (83) hide show
  1. package/README.md +7 -6
  2. package/dist/channel-transport.d.ts +15 -15
  3. package/dist/channel-transport.js +32 -35
  4. package/dist/channels/channel-payload.d.ts +2 -2
  5. package/dist/channels/channel-payload.js +1 -1
  6. package/dist/channels/data.d.ts +14 -19
  7. package/dist/channels/data.js +13 -31
  8. package/dist/channels/drain-ack.d.ts +2 -2
  9. package/dist/channels/drain-ack.js +1 -1
  10. package/dist/channels/feedback.d.ts +1 -1
  11. package/dist/channels/index.d.ts +1 -1
  12. package/dist/channels/index.js +1 -1
  13. package/dist/channels/props-update.d.ts +33 -37
  14. package/dist/channels/props-update.js +30 -106
  15. package/dist/channels/render-frame.d.ts +52 -0
  16. package/dist/channels/render-frame.js +53 -0
  17. package/dist/channels/system.d.ts +1 -1
  18. package/dist/compiled-validators.d.ts +15 -0
  19. package/dist/compiled-validators.js +31 -0
  20. package/dist/context-observer.d.ts +68 -8
  21. package/dist/context-observer.js +25 -45
  22. package/dist/events-polling.d.ts +95 -0
  23. package/dist/events-polling.js +143 -0
  24. package/dist/gadget-loader.d.ts +1 -1
  25. package/dist/globals.d.ts +4 -4
  26. package/dist/host-context-emitter.d.ts +84 -20
  27. package/dist/host-context-emitter.js +159 -29
  28. package/dist/iframe-runtime.js +98 -59
  29. package/dist/index.d.ts +18 -13
  30. package/dist/index.js +1 -1
  31. package/dist/lifecycle.d.ts +2 -2
  32. package/dist/lifecycle.js +5 -5
  33. package/dist/mcp-app-iframe-host.d.ts +9 -9
  34. package/dist/mcp-app-iframe-host.js +16 -17
  35. package/dist/meta-parse.d.ts +44 -0
  36. package/dist/meta-parse.js +390 -0
  37. package/dist/observability.d.ts +6 -6
  38. package/dist/protocol-error.d.ts +7 -7
  39. package/dist/provisional-renderer.d.ts +1 -1
  40. package/dist/provisional-renderer.js +1 -1
  41. package/dist/react-renderer.d.ts +10 -11
  42. package/dist/react-renderer.js +8 -8
  43. package/dist/registry-subscribe.d.ts +27 -9
  44. package/dist/registry-subscribe.js +32 -27
  45. package/dist/render-item.d.ts +83 -0
  46. package/dist/{stack-item-renderer.js → render-item.js} +106 -106
  47. package/dist/runtime.d.ts +183 -131
  48. package/dist/runtime.js +1264 -1330
  49. package/dist/status-dom.d.ts +52 -47
  50. package/dist/status-dom.js +51 -34
  51. package/dist/system-cards/NoCredentialsCard.d.ts +1 -1
  52. package/dist/system-cards/NoCredentialsCard.js +1 -1
  53. package/dist/system-cards/ProtocolProbeCard.js +2 -2
  54. package/dist/system-cards/index.d.ts +4 -4
  55. package/dist/system-cards/index.js +4 -4
  56. package/dist/types.d.ts +70 -34
  57. package/dist/types.js +1 -1
  58. package/dist/validation.d.ts +2 -2
  59. package/dist/validation.js +2 -2
  60. package/dist/wire-config.d.ts +54 -82
  61. package/dist/wire-config.js +61 -93
  62. package/package.json +9 -8
  63. package/dist/bootstrap.d.ts +0 -72
  64. package/dist/bootstrap.js +0 -500
  65. package/dist/canvas/animator/animator-host.d.ts +0 -63
  66. package/dist/canvas/animator/animator-host.js +0 -105
  67. package/dist/canvas/animator/animator-pill.d.ts +0 -42
  68. package/dist/canvas/animator/animator-pill.js +0 -119
  69. package/dist/canvas/animator/state-machine.d.ts +0 -106
  70. package/dist/canvas/animator/state-machine.js +0 -150
  71. package/dist/canvas/canvas-shell.d.ts +0 -77
  72. package/dist/canvas/canvas-shell.js +0 -117
  73. package/dist/canvas/display-mode-policy.d.ts +0 -104
  74. package/dist/canvas/display-mode-policy.js +0 -98
  75. package/dist/canvas/mount.d.ts +0 -150
  76. package/dist/canvas/mount.js +0 -202
  77. package/dist/canvas/nav-stack.d.ts +0 -133
  78. package/dist/canvas/nav-stack.js +0 -172
  79. package/dist/channels/push.d.ts +0 -47
  80. package/dist/channels/push.js +0 -54
  81. package/dist/stack-item-renderer.d.ts +0 -103
  82. package/dist/stack.d.ts +0 -90
  83. package/dist/stack.js +0 -118
package/dist/runtime.d.ts CHANGED
@@ -1,22 +1,23 @@
1
- import type { DrainAckPayload } from '@ggui-ai/protocol';
1
+ import type { DrainAckPayload, Render } from '@ggui-ai/protocol';
2
2
  import type { WebSocketMessage } from '@ggui-ai/protocol/transport/websocket';
3
- import type { GguiBootstrapMeta } from '@ggui-ai/protocol/integrations/mcp-apps';
4
- import { StackModel } from './stack.js';
5
- import type { BootstrapParseFailureReason } from './types.js';
3
+ import type { ValidatedMcpAppAiGguiMeta, RenderSeedInput } from './types.js';
4
+ import type { McpAppAiGguiMetaParseFailureReason } from './types.js';
5
+ import { App } from '@modelcontextprotocol/ext-apps';
6
+ import type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';
7
+ import type { GadgetPackageRegistry } from './globals.js';
6
8
  import { StreamBus } from './wire-config.js';
7
9
  import { type ChannelTransportRouter } from './channel-transport.js';
8
- import { ChannelRegistry } from '@ggui-ai/channel-client';
10
+ import { ChannelRegistry } from '@ggui-ai/live-channel';
9
11
  import { type ConnectFn } from './registry-subscribe.js';
10
12
  import { type StatusRefs } from './status-dom.js';
11
13
  import { type RendererValidatorContext } from './validation.js';
12
- import { StackRenderer } from './stack-item-renderer.js';
13
14
  import type { WireConfig } from '@ggui-ai/wire';
14
15
  import { type ProtocolErrorEmitter } from './protocol-error.js';
15
16
  import { type ObservabilityEmitter } from './observability.js';
16
17
  import { type LifecycleEmitter } from './lifecycle.js';
17
18
  /**
18
19
  * Drain-ack listener registry. Module-scoped so the dispatch path can
19
- * register a frame-listener without threading it through the triad.
20
+ * register a frame-listener without threading it through the renderer.
20
21
  * Listeners are called in registration order on every inbound
21
22
  * `{type:'drain_ack'}` WS frame; a listener returning `true` claims
22
23
  * the frame (no further listeners fire). The active listener dismisses
@@ -27,24 +28,38 @@ import { type LifecycleEmitter } from './lifecycle.js';
27
28
  */
28
29
  type DrainAckListener = (payload: DrainAckPayload) => boolean | void;
29
30
  export declare function subscribeDrainAck(listener: DrainAckListener): () => void;
30
- interface JsonRpcResponse {
31
- readonly jsonrpc?: string;
32
- readonly id?: number;
33
- readonly result?: unknown;
34
- readonly error?: {
35
- readonly code?: number;
36
- readonly message?: string;
37
- };
38
- }
31
+ export type ConnectAppResult = {
32
+ readonly ok: true;
33
+ } | {
34
+ readonly ok: false;
35
+ readonly message: string;
36
+ };
37
+ /**
38
+ * Assign the module-level App handle. Replaces any previous handle —
39
+ * production runs bootSequence exactly once per iframe lifecycle, so
40
+ * a replace only happens in tests that reuse the module across
41
+ * scenarios (and want each spec to bind its own App).
42
+ *
43
+ * @internal — production callers are the boot paths
44
+ * (`bootProduction`, `bootSelfContained`); tests inject directly to
45
+ * drive outbound `tools/call` through a `MockTransport`-bound App
46
+ * without invoking the full boot pipeline.
47
+ */
48
+ export declare function setCurrentApp(app: App): void;
49
+ /**
50
+ * @internal — exported for unit tests to reset module state between
51
+ * scenarios.
52
+ */
53
+ export declare function __resetAppForTest(): void;
39
54
  /**
40
55
  * Closed union of failure reasons surfaceable from the boot path.
41
- * Maps the parse reasons (`BootstrapParseFailureReason`) plus three
42
- * boot-orchestration reasons that don't have a canonical wire code.
43
- * The broader `BootstrapFailureReason` extensibly-closed union in
44
- * `protocol-error.ts` folds these together with transport-observable
56
+ * Maps the parse reasons (`McpAppAiGguiMetaParseFailureReason`) plus
57
+ * three boot-orchestration reasons that don't have a canonical wire
58
+ * code. The broader `BootstrapFailureReason` extensibly-closed union
59
+ * in `protocol-error.ts` folds these together with transport-observable
45
60
  * codes.
46
61
  */
47
- export type RendererBootFailureReason = BootstrapParseFailureReason | 'UI_INITIALIZE_FAILED' | 'WS_HANDSHAKE_FAILED' | 'UPGRADE_REQUIRED';
62
+ export type RendererBootFailureReason = McpAppAiGguiMetaParseFailureReason | 'UI_INITIALIZE_FAILED' | 'WS_HANDSHAKE_FAILED' | 'UPGRADE_REQUIRED';
48
63
  export interface RendererBootFailedMessage {
49
64
  readonly type: 'ggui:bootstrap-failed';
50
65
  readonly reason: RendererBootFailureReason;
@@ -53,17 +68,27 @@ export interface RendererBootFailedMessage {
53
68
  export interface BootSequenceOptions {
54
69
  readonly doc: Document;
55
70
  /**
56
- * Issue `ui/initialize` against the parent host and return its
57
- * response. The default uses `makeJsonRpcCaller()` against
58
- * `window.parent`; tests inject a mock that returns a canned
59
- * `JsonRpcResponse`.
71
+ * Spec-canonical {@link App} instance + its {@link Transport}.
72
+ * `bootSequence` calls `app.connect(transport)` synchronously after
73
+ * the toolresult listener is installed (one-shot semantics: see
74
+ * App's `_assertHandlerTiming` warning — handlers registered AFTER
75
+ * connect risk missing the host's notification).
76
+ *
77
+ * Production passes the default (constructed against `window.parent`);
78
+ * tests inject `MockTransport` + a fresh App so the orchestration
79
+ * can be driven deterministically without `window.postMessage`.
80
+ *
81
+ * `App.connect` throws on initialize failure — bootSequence catches
82
+ * + surfaces the rejection's `message` on the `UI_INITIALIZE_FAILED`
83
+ * bootstrap envelope.
60
84
  */
61
- readonly callUiInitialize: () => Promise<JsonRpcResponse>;
85
+ readonly app: App;
86
+ readonly transport: Transport;
62
87
  /**
63
88
  * Stand-in for the package's own `connectViaRegistry()`. Tests inject
64
89
  * a mock so the boot smoke spec doesn't need a mock-WebSocket layer
65
90
  * — the WS lifecycle is already covered by `registry-subscribe.test.ts`
66
- * and `@ggui-ai/channel-client`'s transport tests.
91
+ * and `@ggui-ai/live-channel`'s transport tests.
67
92
  *
68
93
  * Default: `connectViaRegistry` from `./registry-subscribe.js`.
69
94
  */
@@ -126,10 +151,10 @@ export interface BootSequenceOptions {
126
151
  */
127
152
  readonly onLifecycle?: LifecycleEmitter;
128
153
  /**
129
- * Optional triad-wiring hook. When present, the boot sequence:
130
- * (1) calls `triadWiring.setup()` after bootstrap parse;
131
- * (2) replaces the placeholder `renderStackInto` path with the
132
- * real `StackRenderer` on ack + subsequent pushes; (3) routes
154
+ * Optional renderer hook. When present, the boot sequence:
155
+ * (1) calls `renderer.setup()` after bootstrap parse;
156
+ * (2) mounts the single stack entry into the renderer's slot on
157
+ * first ack + re-applies on every subsequent push; (3) routes
133
158
  * inbound `data` / `props_update` / `feedback` frames through the
134
159
  * supplied wire config + StreamBus.
135
160
  *
@@ -138,46 +163,46 @@ export interface BootSequenceOptions {
138
163
  * without pulling React + design + wire into the spec's import
139
164
  * graph.
140
165
  */
141
- readonly triadWiring?: TriadWiringHooks;
166
+ readonly renderer?: RendererHooks;
142
167
  /**
143
- * Optional canvas-mount hook. When the parsed bootstrap carries
144
- * `canvasMode: true` AND this hook is supplied, bootSequence mounts
145
- * the React-tree {@link CanvasShell} into `refs.stack` via the hook
146
- * and substitutes the hook's `contentEl` as the `renderInto`
147
- * passed to `triadWiring.setup()` — so the existing per-stack-item
148
- * renderer writes into the canvas's content slot rather than the
149
- * raw status DOM. Subsequent ack/push frames sync into the returned
150
- * {@link CanvasMountHandle.navStack}.
168
+ * Slice meta resolved BEFORE bootSequence — the autostart layer
169
+ * (in `runtime.ts`'s autostart resolver) catches an inline
170
+ * `__GGUI_META__` global or a buffered `ui/notifications/tool-result`
171
+ * postMessage early, parses it, and threads the result here so
172
+ * bootSequence doesn't re-await the same postMessage (the autostart
173
+ * has already drained it).
151
174
  *
152
- * Absent OR `bootstrap.canvasMode !== true` ⇒ the inline path
153
- * (per-push iframe).
175
+ * When present, both internal resolver tiers (inline global, spec-
176
+ * canonical async toolresult) are skipped. The App handshake still
177
+ * runs — spec mandates `ui/initialize` regardless of how slice meta
178
+ * arrives, and `hostContext` is captured from `app.getHostContext()`.
179
+ */
180
+ readonly preResolvedMeta?: ValidatedMcpAppAiGguiMeta;
181
+ /**
182
+ * How long to wait for the spec-canonical `ui/notifications/tool-result`
183
+ * notification (Tier 2 of the resolver chain) before failing with
184
+ * the synchronous tier's parse reason. Defaults to
185
+ * {@link POSTMESSAGE_BOOT_TIMEOUT_MS}; tests override to a short
186
+ * timeout so the spec doesn't hang.
154
187
  */
155
- readonly canvasMount?: CanvasMountHook;
188
+ readonly toolResultTimeoutMs?: number;
156
189
  }
157
190
  /**
158
- * Hook signature for the canvas-mode mount. Production wires this
159
- * through `bootProduction` (where React + canvas modules are already
160
- * dynamic-imported); tests pass a stub that fakes the React tree.
161
- */
162
- export type CanvasMountHook = (params: {
163
- readonly mountTarget: HTMLElement;
164
- readonly callbacks: import('./canvas/mount.js').CanvasMountCallbacks;
165
- }) => import('./canvas/mount.js').CanvasMountHandle;
166
- /**
167
- * Renderer-triad wiring hooks. The real iframe boot plumbs these via
191
+ * Renderer hooks. The real iframe boot plumbs these via
168
192
  * `autoBootSequence` below; tests may pass their own fakes when
169
193
  * exercising the full flow.
170
194
  */
171
- export interface TriadWiringHooks {
195
+ export interface RendererHooks {
172
196
  /**
173
197
  * Called after bootstrap parse succeeds. Return value threads the
174
- * root `WireConfig` + `StackRenderer` back into the runtime so the
175
- * server-message handler can route frames through them.
198
+ * root `WireConfig` + the single-render mount surface back into the
199
+ * runtime so the channel handlers can route frames through them.
176
200
  *
177
- * `renderInto` — a DOM element the stack renderer owns. The
178
- * placeholder `<ul data-ggui-stack>` is NOT reused; the triad
179
- * renderer mounts React roots per stack item into dedicated
180
- * containers (see `containerFor` below).
201
+ * `renderInto` — a DOM element the renderer owns. Post-stack-removal
202
+ * (2026-05-27) the iframe-runtime mounts exactly one React tree
203
+ * directly into `renderInto`; the earlier per-render
204
+ * `<div data-ggui-stack-item-root>` containers were retired along
205
+ * with `StackRenderer`.
181
206
  *
182
207
  * `onObserve` — optional observability emitter threaded down to
183
208
  * the root wire config so `wired-tool-invoked` events fire on
@@ -187,37 +212,43 @@ export interface TriadWiringHooks {
187
212
  * own emitters).
188
213
  */
189
214
  setup(params: {
190
- readonly bootstrap: GguiBootstrapMeta;
191
- readonly stackModel: StackModel;
215
+ readonly meta: ValidatedMcpAppAiGguiMeta;
192
216
  readonly renderInto: HTMLElement;
193
217
  readonly statusRefs: StatusRefs;
194
218
  readonly onObserve?: ObservabilityEmitter;
195
- /**
196
- * Canvas-mode lifecycle sink. When wired,
197
- * the triad's `data` channel handler forwards every envelope on
198
- * the reserved `_ggui:lifecycle` channel to this callback so the
199
- * canvas animator state machine advances. Absent ⇒ envelopes
200
- * still emit on `streamBus` for declarative consumers but no
201
- * animator-side dispatch fires (non-canvas iframes).
202
- */
203
- readonly onCanvasLifecycle?: (payload: import('@ggui-ai/protocol').CanvasLifecyclePayload) => void;
204
- }): TriadHandle;
219
+ }): RendererHandle;
205
220
  /**
206
- * Bind the real WS manager into the triad AFTER `connectFn` resolves.
221
+ * Bind the real WS manager into the renderer AFTER `connectFn` resolves.
207
222
  * The `setup()` step supplies a buffering shim — this hook flushes
208
- * the buffer + swaps in the real send surface. Optional: a triad
223
+ * the buffer + swaps in the real send surface. Optional: a renderer
209
224
  * that doesn't emit outbound frames can skip.
210
225
  */
211
- attachManager?(handle: TriadHandle, realManager: {
226
+ attachManager?(handle: RendererHandle, realManager: {
212
227
  send: (msg: WebSocketMessage) => void;
213
228
  }): void;
214
229
  /** Optional cleanup — called on boot failure paths. */
215
- teardown?(handle: TriadHandle): void;
230
+ teardown?(handle: RendererHandle): void;
216
231
  }
217
- export interface TriadHandle {
232
+ export interface RendererHandle {
218
233
  readonly rootWireConfig: WireConfig;
219
234
  readonly streamBus: StreamBus;
220
- readonly stackRenderer: StackRenderer;
235
+ /**
236
+ * Apply (mount-or-update) a render to the single mount slot.
237
+ * First call mounts the React tree into `renderInto`; subsequent
238
+ * calls re-apply through {@link RenderItemHandle.update} (same kind ⇒
239
+ * in-place; kind transition ⇒ tear-down + remount).
240
+ *
241
+ * Shared by the `render` and `props_update` channel handlers so React
242
+ * updates flow through one path.
243
+ */
244
+ applyRender(render: Render | RenderSeedInput): Promise<void>;
245
+ /**
246
+ * Read the currently-mounted render. `null` until the first
247
+ * render frame lands. Read by the `props_update` + `data` channel
248
+ * handlers to validate inbound payloads against the active render's
249
+ * `propsSpec` / `streamSpec`.
250
+ */
251
+ getCurrentRender(): Render | RenderSeedInput | null;
221
252
  readonly validatorCtx: RendererValidatorContext;
222
253
  /**
223
254
  * Send surface for outbound frames. Wired by `setup()` to the WS
@@ -229,11 +260,10 @@ export interface TriadHandle {
229
260
  };
230
261
  /**
231
262
  * Per-channel transport router. When the bootstrap carries
232
- * `streamWebSocketLocalTools` and the active
233
- * stack item declares `streamSpec[ch].source.tool`, the router
234
- * decides per-channel between WS subscribe + iframe-polling
235
- * fallback. Updated on every push via the stackRenderer's
236
- * `applyStack` hook.
263
+ * `streamWebSocketLocalTools` and the active render declares
264
+ * `streamSpec[ch].source.tool`, the router decides per-channel
265
+ * between WS subscribe + iframe-polling fallback. Updated on every
266
+ * render frame via the render handler.
237
267
  *
238
268
  * Always present — the router gracefully no-ops when no channel
239
269
  * declares `source.tool` (legacy data-frame path is unaffected).
@@ -241,7 +271,7 @@ export interface TriadHandle {
241
271
  readonly channelTransport: ChannelTransportRouter;
242
272
  /**
243
273
  * Channel-client registry holding handlers for every WS frame type
244
- * the iframe routes (`push`, `data`, `props_update`, `drain_ack`,
274
+ * the iframe routes (`render`, `data`, `props_update`, `drain_ack`,
245
275
  * `channel_payload`, `channel_error`, `system`, `feedback`). The
246
276
  * registry-bound transport is the sole dispatch surface — frames
247
277
  * arrive directly through registered handlers, no longer through a
@@ -254,56 +284,88 @@ export interface TriadHandle {
254
284
  * `connectViaRegistry` and consumed during handshake resolution.
255
285
  */
256
286
  readonly channelRegistry: ChannelRegistry;
287
+ /**
288
+ * 3rd-party gadget-package merge promise. `installGlobalRegistry`
289
+ * seeds `__ggui__.gadgets` synchronously with the STDLIB namespace;
290
+ * operator-registered packages merge in asynchronously. A static seed
291
+ * mount MUST `await` this (when the bootstrap declares `gadgets`)
292
+ * before the first `applyRender`, so a generated component importing a
293
+ * 3rd-party gadget sees a fully-populated catalog on first paint
294
+ * (otherwise the per-package data-URL shim resolves to `undefined` and
295
+ * crashes). Resolves to the STDLIB-only registry when no 3rd-party
296
+ * packages were declared.
297
+ */
298
+ readonly composedGadgets: Promise<GadgetPackageRegistry>;
257
299
  }
258
300
  export interface BootSequenceResult {
259
301
  readonly ok: boolean;
260
- readonly stack: StackModel;
302
+ /**
303
+ * The render that ended up mounted in this iframe, or `null` if
304
+ * the boot path bailed before the first ack landed. Post-render-
305
+ * identity-collapse (2026-05-27) every iframe holds at most one
306
+ * render; this replaces the earlier `StackModel` return that wrapped
307
+ * a multi-item model.
308
+ */
309
+ readonly mountedRender: Render | RenderSeedInput | null;
261
310
  }
262
311
  export declare function bootSequence(opts: BootSequenceOptions): Promise<BootSequenceResult>;
263
312
  /**
264
- * Self-contained bootstrap shape — alias for the protocol's unified
265
- * {@link GguiBootstrapMeta}. Earlier versions of this module had
266
- * separate `SelfContainedComponentBootstrap` /
267
- * `SelfContainedSystemBootstrap` narrowings; the protocol's
268
- * `GguiBootstrapMeta` now carries `codeUrl` / `kind` / `themeId`
269
- * / `themeMode` / `propsJson` directly (alongside the existing
270
- * live-mode `wsUrl` / `token` / `expiresAt` fields), so a single
271
- * shared validator ({@link validateBootstrapMeta} in `bootstrap.ts`)
272
- * can produce the full envelope from any of three delivery channels.
313
+ * Self-contained slice-meta shape — alias for {@link
314
+ * ValidatedMcpAppAiGguiMeta}. Post-Phase-B every delivery channel
315
+ * produces a single `McpAppAiGguiRenderMeta` slice.
273
316
  *
274
317
  * The export is kept so downstream consumers (`@ggui-ai/iframe-runtime`
275
318
  * barrel, dependent test suites) don't break.
276
319
  *
277
320
  * @public
278
321
  */
279
- export type SelfContainedBootstrap = GguiBootstrapMeta;
322
+ export type SelfContainedMcpAppAiGguiMeta = ValidatedMcpAppAiGguiMeta;
280
323
  /**
281
- * Read `globalThis.__GGUI_BOOTSTRAP__` synchronously, validate against
282
- * the unified bootstrap shape, and return the typed bootstrap (or null
324
+ * Read `globalThis.__GGUI_META__` synchronously, validate against
325
+ * the unified slice-meta shape, and return the typed meta (or null
283
326
  * on absence / malformation).
284
327
  *
285
- * Thin wrapper around {@link parseBootstrapFromGlobal}; preserved for
328
+ * Thin wrapper around {@link parseMetaFromGlobal}; preserved for
286
329
  * back-compat (downstream consumers + tests). Returns `null` instead
287
- * of `BootstrapParseResult` to match the historical reader contract
288
- * — the autostart resolver only needs the "valid bootstrap or fall
289
- * through" signal.
330
+ * of {@link McpAppAiGguiMetaParseResult} to match the historical
331
+ * reader contract — the autostart resolver only needs the "valid
332
+ * meta or fall through" signal.
333
+ */
334
+ export declare function readSelfContainedMeta(): SelfContainedMcpAppAiGguiMeta | null;
335
+ /**
336
+ * Project the inline `__GGUI_META__` bootstrap into a
337
+ * {@link RenderSeedInput} the mount surface can paint immediately,
338
+ * BEFORE the authoritative wire `Render` arrives over the WS — and with
339
+ * no WS at all for spec-compliant MCP-Apps hosts that expose no ggui
340
+ * live channel (claude.ai / ChatGPT / Claude Desktop).
341
+ *
342
+ * Two static-content shapes (the autostart discriminator):
343
+ * - `kind` → a system-card seed (`type:'system'`); no fetch.
344
+ * - `codeUrl` → a compiled-component seed; fetches the
345
+ * content-addressable component bytes.
346
+ *
347
+ * Returns `null` when the meta carries NEITHER (a live-only meta has
348
+ * nothing to seed — the first WS ack mounts it). Throws when a `codeUrl`
349
+ * fetch fails so the caller can surface a typed boot failure. The four
350
+ * server-assigned ledger fields are intentionally absent — the first
351
+ * ack reconciles the seed to a full `Render` (no fabrication).
290
352
  */
291
- export declare function readSelfContainedBootstrap(): SelfContainedBootstrap | null;
353
+ export declare function buildRenderSeedInput(meta: SelfContainedMcpAppAiGguiMeta): Promise<RenderSeedInput | null>;
292
354
  /**
293
- * Extract a {@link SelfContainedBootstrap} from a
355
+ * Extract a {@link SelfContainedMcpAppAiGguiMeta} from a
294
356
  * `ui/notifications/tool-result` JSON-RPC params payload — the
295
357
  * postMessage delivery shape MCP Apps hosts (Claude Desktop, claude.ai
296
358
  * web) use to push the active tool's `_meta` to the iframe.
297
359
  *
298
- * Thin wrapper around {@link parseBootstrapFromToolResult}; same
299
- * back-compat motivation as {@link readSelfContainedBootstrap}.
360
+ * Thin wrapper around {@link parseMetaFromToolResult}; same
361
+ * back-compat motivation as {@link readSelfContainedMeta}.
300
362
  *
301
363
  * Owning this extraction inside the runtime (instead of in the shell
302
364
  * HTML) is the architectural cure for the "shell-side validator
303
365
  * lagged the protocol" bug class: shell + runtime drift becomes
304
- * impossible because the shell never inspects the bootstrap shape.
366
+ * impossible because the shell never inspects the slice-meta shape.
305
367
  */
306
- export declare function extractBootstrapFromToolResult(params: unknown): SelfContainedBootstrap | null;
368
+ export declare function extractMetaFromToolResult(params: unknown): SelfContainedMcpAppAiGguiMeta | null;
307
369
  /**
308
370
  * Render a wired-action's `data` payload as a short inline string
309
371
  * for embedding in a `ui/message` consent prompt. Goal: human-
@@ -336,8 +398,7 @@ export declare function emitAudit(args: {
336
398
  readonly toolName: string;
337
399
  readonly kind: 'dispatch' | 'openLink' | 'requestDisplayMode';
338
400
  readonly payload: Record<string, unknown>;
339
- readonly sessionId: string;
340
- readonly stackItemId?: string;
401
+ readonly renderId: string;
341
402
  readonly appId: string;
342
403
  readonly actionId: string;
343
404
  readonly firedAt: string;
@@ -347,16 +408,8 @@ export declare function dispatchWiredAction(args: {
347
408
  readonly toolName: string;
348
409
  readonly intent: string;
349
410
  readonly data: unknown;
350
- readonly sessionId: string;
351
- readonly stackItemId?: string;
411
+ readonly renderId: string;
352
412
  readonly appId: string;
353
- /**
354
- * Optional `actionSpec[intent].nextStep` hint forwarded by the
355
- * caller. Surfaced on the inline-userAction envelope when the pipe
356
- * isn't available, so the agent has a strong steer toward the right
357
- * tool.
358
- */
359
- readonly nextStep?: string;
360
413
  }): void;
361
414
  /**
362
415
  * Fire a wired action via Pattern α — direct `tools/call` against a
@@ -369,7 +422,7 @@ export declare function dispatchWiredAction(args: {
369
422
  * PIPE-2 design note: Pattern α deliberately does NOT fire
370
423
  * `submit_action` — a pipe append would queue the gesture for the
371
424
  * agent's `ggui_consume` long-poll, causing double-processing
372
- * (host's tool relay AND agent's reaction). SessionInspector loses
425
+ * (host's tool relay AND agent's reaction). RenderInspector loses
373
426
  * Pattern α observability for now; re-add via a dedicated audit-only
374
427
  * gesture kind if operators need it.
375
428
  *
@@ -399,12 +452,15 @@ export declare function fireDirectToolCall(args: {
399
452
  *
400
453
  * @internal — exported for unit tests + production reuse.
401
454
  */
455
+ export declare function resolveDispatchToolName(): string;
456
+ /**
457
+ * @internal — exported for unit tests + production reuse.
458
+ */
402
459
  export declare function routeDispatch(args: {
403
460
  readonly actionName: string;
404
461
  readonly data: unknown;
405
- readonly bootstrap: {
406
- readonly sessionId: string;
407
- readonly stackItemId?: string;
462
+ readonly meta: {
463
+ readonly renderId: string;
408
464
  readonly appId: string;
409
465
  readonly appCallableTools?: readonly string[];
410
466
  readonly actionNextSteps?: Readonly<Record<string, string>>;
@@ -420,8 +476,7 @@ export declare function routeDispatch(args: {
420
476
  export declare function openLinkInParent(args: {
421
477
  readonly toolName: string;
422
478
  readonly url: string;
423
- readonly sessionId: string;
424
- readonly stackItemId?: string;
479
+ readonly renderId: string;
425
480
  readonly appId: string;
426
481
  }): void;
427
482
  /**
@@ -434,8 +489,7 @@ export declare function openLinkInParent(args: {
434
489
  export declare function requestDisplayModeInParent(args: {
435
490
  readonly toolName: string;
436
491
  readonly mode: 'fullscreen' | 'pip' | 'inline';
437
- readonly sessionId: string;
438
- readonly stackItemId?: string;
492
+ readonly renderId: string;
439
493
  readonly appId: string;
440
494
  }): void;
441
495
  /**
@@ -475,8 +529,7 @@ export declare function requestDisplayModeInParent(args: {
475
529
  /** @internal — exported for unit tests. */
476
530
  export declare function installAnchorClickInterceptor(args: {
477
531
  readonly dispatchToolName: string;
478
- readonly sessionId: string;
479
- readonly stackItemId?: string;
532
+ readonly renderId: string;
480
533
  readonly appId: string;
481
534
  }): void;
482
535
  /**
@@ -512,13 +565,12 @@ export declare function installAnchorClickInterceptor(args: {
512
565
  *
513
566
  * Idempotent: the {@link fullscreenInterceptInstalled} guard prevents
514
567
  * re-mounts from chaining wrappers (which would also leak the prior
515
- * mount's `sessionId`/`appId` if they ever differed).
568
+ * mount's `renderId`/`appId` if they ever differed).
516
569
  */
517
570
  /** @internal — exported for unit tests. */
518
571
  export declare function installFullscreenInterceptors(args: {
519
572
  readonly dispatchToolName: string;
520
- readonly sessionId: string;
521
- readonly stackItemId?: string;
573
+ readonly renderId: string;
522
574
  readonly appId: string;
523
575
  }): void;
524
576
  /**