@ggui-ai/iframe-runtime 0.1.0-rc.3 → 0.2.0-alpha.3
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 +7 -6
- package/dist/channel-transport.d.ts +15 -15
- package/dist/channel-transport.js +32 -35
- package/dist/channels/channel-payload.d.ts +2 -2
- package/dist/channels/channel-payload.js +1 -1
- package/dist/channels/data.d.ts +14 -19
- package/dist/channels/data.js +13 -31
- package/dist/channels/drain-ack.d.ts +2 -2
- package/dist/channels/drain-ack.js +1 -1
- package/dist/channels/feedback.d.ts +1 -1
- package/dist/channels/index.d.ts +1 -1
- package/dist/channels/index.js +1 -1
- package/dist/channels/props-update.d.ts +33 -37
- package/dist/channels/props-update.js +30 -106
- package/dist/channels/render-frame.d.ts +52 -0
- package/dist/channels/render-frame.js +53 -0
- package/dist/channels/system.d.ts +1 -1
- package/dist/compiled-validators.d.ts +15 -0
- package/dist/compiled-validators.js +31 -0
- package/dist/context-observer.d.ts +68 -8
- package/dist/context-observer.js +25 -45
- package/dist/events-polling.d.ts +95 -0
- package/dist/events-polling.js +143 -0
- package/dist/gadget-loader.d.ts +1 -1
- package/dist/globals.d.ts +4 -4
- package/dist/host-context-emitter.d.ts +84 -20
- package/dist/host-context-emitter.js +159 -29
- package/dist/iframe-runtime.js +98 -59
- package/dist/index.d.ts +18 -13
- package/dist/index.js +1 -1
- package/dist/lifecycle.d.ts +2 -2
- package/dist/lifecycle.js +5 -5
- package/dist/mcp-app-iframe-host.d.ts +9 -9
- package/dist/mcp-app-iframe-host.js +16 -17
- package/dist/meta-parse.d.ts +44 -0
- package/dist/meta-parse.js +390 -0
- package/dist/observability.d.ts +6 -6
- package/dist/protocol-error.d.ts +7 -7
- package/dist/provisional-renderer.d.ts +1 -1
- package/dist/provisional-renderer.js +1 -1
- package/dist/react-renderer.d.ts +10 -11
- package/dist/react-renderer.js +8 -8
- package/dist/registry-subscribe.d.ts +27 -9
- package/dist/registry-subscribe.js +32 -27
- package/dist/render-item.d.ts +83 -0
- package/dist/{stack-item-renderer.js → render-item.js} +106 -106
- package/dist/runtime.d.ts +183 -131
- package/dist/runtime.js +1264 -1330
- package/dist/status-dom.d.ts +52 -47
- package/dist/status-dom.js +51 -34
- package/dist/system-cards/NoCredentialsCard.d.ts +1 -1
- package/dist/system-cards/NoCredentialsCard.js +1 -1
- package/dist/system-cards/ProtocolProbeCard.js +2 -2
- package/dist/system-cards/index.d.ts +4 -4
- package/dist/system-cards/index.js +4 -4
- package/dist/types.d.ts +70 -34
- package/dist/types.js +1 -1
- package/dist/validation.d.ts +2 -2
- package/dist/validation.js +2 -2
- package/dist/wire-config.d.ts +54 -82
- package/dist/wire-config.js +61 -93
- package/package.json +9 -8
- package/dist/bootstrap.d.ts +0 -72
- package/dist/bootstrap.js +0 -500
- package/dist/canvas/animator/animator-host.d.ts +0 -63
- package/dist/canvas/animator/animator-host.js +0 -105
- package/dist/canvas/animator/animator-pill.d.ts +0 -42
- package/dist/canvas/animator/animator-pill.js +0 -119
- package/dist/canvas/animator/state-machine.d.ts +0 -106
- package/dist/canvas/animator/state-machine.js +0 -150
- package/dist/canvas/canvas-shell.d.ts +0 -77
- package/dist/canvas/canvas-shell.js +0 -117
- package/dist/canvas/display-mode-policy.d.ts +0 -104
- package/dist/canvas/display-mode-policy.js +0 -98
- package/dist/canvas/mount.d.ts +0 -150
- package/dist/canvas/mount.js +0 -202
- package/dist/canvas/nav-stack.d.ts +0 -133
- package/dist/canvas/nav-stack.js +0 -172
- package/dist/channels/push.d.ts +0 -47
- package/dist/channels/push.js +0 -54
- package/dist/stack-item-renderer.d.ts +0 -103
- package/dist/stack.d.ts +0 -90
- package/dist/stack.js +0 -118
package/dist/status-dom.d.ts
CHANGED
|
@@ -1,72 +1,77 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* In-iframe status
|
|
3
|
-
* channel-client handlers can import the `setStatus` + status-refs
|
|
4
|
-
* helpers without a circular dep on the runtime module (which imports
|
|
5
|
-
* the handlers for registration at boot).
|
|
2
|
+
* In-iframe runtime status surface.
|
|
6
3
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
4
|
+
* Used to inject a visible `<div data-ggui-status>` banner ("Initializing
|
|
5
|
+
* renderer…", "Connected", etc.) into the iframe body alongside the
|
|
6
|
+
* user-rendered React tree. End users saw it as a stray label above
|
|
7
|
+
* their UI — production-unfriendly. As of the displayMode-divergence
|
|
8
|
+
* close-out we route status transitions to `console.log` and inject ONLY
|
|
9
|
+
* the React mount-target div (no banner, no list-item placeholder text).
|
|
9
10
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
11
|
+
* Post-stack-removal (2026-05-27): the iframe holds exactly one mounted
|
|
12
|
+
* render for its lifetime. The `setConnectedStatus` helper no longer takes
|
|
13
|
+
* a stack-model arg — there's nothing to count — and the placeholder
|
|
14
|
+
* `<li data-ggui-stack-item>` render path is gone.
|
|
15
|
+
*
|
|
16
|
+
* The exported names (`setStatus`, `setConnectedStatus`, `StatusRefs`)
|
|
17
|
+
* are preserved so the channel handlers + runtime keep their import
|
|
18
|
+
* shape.
|
|
15
19
|
*/
|
|
16
|
-
import type { StackModel } from './stack.js';
|
|
17
20
|
/**
|
|
18
|
-
* Closed union of values the
|
|
21
|
+
* Closed union of values the iframe's status surface carries. Kept on
|
|
22
|
+
* the runtime side as the canonical state vocabulary even though it no
|
|
23
|
+
* longer surfaces visibly.
|
|
19
24
|
*
|
|
20
|
-
* - `idle` — initial state before any boot IO.
|
|
21
|
-
*
|
|
22
|
-
* - `initializing` — same as `idle` (legacy alias kept for the rare
|
|
23
|
-
* external CSS hook in `e2e/`).
|
|
25
|
+
* - `idle` — initial state before any boot IO.
|
|
26
|
+
* - `initializing` — legacy alias for `idle`.
|
|
24
27
|
* - `connecting` — ui/initialize fired or WS handshake in flight.
|
|
25
28
|
* - `connected` — first ack landed + every subsequent successful
|
|
26
|
-
* push.
|
|
27
|
-
* - `reconnecting` — WS dropped;
|
|
28
|
-
* - `disconnected` — terminal close + ladder exhausted
|
|
29
|
-
*
|
|
30
|
-
* - `
|
|
31
|
-
* upgrade the client.
|
|
32
|
-
* - `error` — every other failure (ui/initialize, bootstrap parse,
|
|
33
|
-
* WS handshake non-version).
|
|
29
|
+
* push.
|
|
30
|
+
* - `reconnecting` — WS dropped; reconnect ladder running.
|
|
31
|
+
* - `disconnected` — terminal close + ladder exhausted.
|
|
32
|
+
* - `upgrade-required` — version handshake failed.
|
|
33
|
+
* - `error` — every other failure.
|
|
34
34
|
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
35
|
+
* Surfaces on `console.log` prefixed `[ggui:<state>]`; consumers
|
|
36
|
+
* (operators, e2e specs) MAY install a `console.log` interceptor or
|
|
37
|
+
* read `notifyParent('ggui:bootstrap-failed', …)` for failure paths.
|
|
37
38
|
*/
|
|
38
39
|
export type StatusKind = 'idle' | 'initializing' | 'connecting' | 'connected' | 'reconnecting' | 'disconnected' | 'upgrade-required' | 'error';
|
|
39
40
|
/**
|
|
40
|
-
* Refs handed back from {@link ensureStatusDom}.
|
|
41
|
-
*
|
|
42
|
-
*
|
|
41
|
+
* Refs handed back from {@link ensureStatusDom}. `status` is a detached
|
|
42
|
+
* element kept for backward compatibility with channel handlers that
|
|
43
|
+
* still pass `refs.status` through; it is NEVER appended to the
|
|
44
|
+
* document, so production iframes carry no diagnostic banner. `stack`
|
|
45
|
+
* is the React mount target — appended to `document.body` so renderer
|
|
46
|
+
* wiring has a container.
|
|
43
47
|
*/
|
|
44
48
|
export interface StatusRefs {
|
|
45
49
|
readonly status: HTMLElement;
|
|
46
50
|
readonly stack: HTMLElement;
|
|
47
51
|
}
|
|
48
52
|
/**
|
|
49
|
-
* Build the
|
|
50
|
-
*
|
|
51
|
-
*
|
|
53
|
+
* Build the React mount target. Reuses pre-existing `[data-ggui-stack]`
|
|
54
|
+
* if the shell already wrote one (cf. `buildSelfContainedShell`); else
|
|
55
|
+
* creates a fresh `<ul data-ggui-stack>` and appends it to `<body>`.
|
|
56
|
+
* The companion `status` element is created detached and never
|
|
57
|
+
* appended — consumers that still pass it through `StatusRefs` see no
|
|
58
|
+
* visible effect.
|
|
59
|
+
*
|
|
60
|
+
* The `<ul>` element name is preserved (legacy from the stack-of-N
|
|
61
|
+
* placeholder render path) but only ever holds a single React mount
|
|
62
|
+
* subtree post-stack-removal.
|
|
52
63
|
*/
|
|
53
64
|
export declare function ensureStatusDom(doc: Document): StatusRefs;
|
|
54
65
|
/**
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
66
|
+
* Log a status transition. The element is mutated for backward compat
|
|
67
|
+
* (some tests still hold a `refs.status` reference), but production
|
|
68
|
+
* users never see it because the element is detached from `document`.
|
|
58
69
|
*/
|
|
59
70
|
export declare function setStatus(refs: StatusRefs, text: string, state: StatusKind): void;
|
|
60
71
|
/**
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
|
|
65
|
-
export declare function setConnectedStatus(refs: StatusRefs, model: StackModel): void;
|
|
66
|
-
/**
|
|
67
|
-
* Re-render the stack DOM into the placeholder element. Wraps the
|
|
68
|
-
* standalone {@link renderStackInto} so callers can pass refs + model
|
|
69
|
-
* without unpacking; the standalone export stays for the legacy
|
|
70
|
-
* callers that have only the bare element in scope.
|
|
72
|
+
* Log the "connected" transition. Post-stack-removal the iframe always
|
|
73
|
+
* holds exactly one item; the message stays bare ("Connected.") since
|
|
74
|
+
* there's no count to surface. Consumers (devtools, e2e specs
|
|
75
|
+
* intercepting `console.log`) get a stable string on every push.
|
|
71
76
|
*/
|
|
72
|
-
export declare function
|
|
77
|
+
export declare function setConnectedStatus(refs: StatusRefs): void;
|
package/dist/status-dom.js
CHANGED
|
@@ -1,51 +1,68 @@
|
|
|
1
|
-
import { renderStackInto } from './stack.js';
|
|
2
1
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
2
|
+
* In-iframe runtime status surface.
|
|
3
|
+
*
|
|
4
|
+
* Used to inject a visible `<div data-ggui-status>` banner ("Initializing
|
|
5
|
+
* renderer…", "Connected", etc.) into the iframe body alongside the
|
|
6
|
+
* user-rendered React tree. End users saw it as a stray label above
|
|
7
|
+
* their UI — production-unfriendly. As of the displayMode-divergence
|
|
8
|
+
* close-out we route status transitions to `console.log` and inject ONLY
|
|
9
|
+
* the React mount-target div (no banner, no list-item placeholder text).
|
|
10
|
+
*
|
|
11
|
+
* Post-stack-removal (2026-05-27): the iframe holds exactly one mounted
|
|
12
|
+
* render for its lifetime. The `setConnectedStatus` helper no longer takes
|
|
13
|
+
* a stack-model arg — there's nothing to count — and the placeholder
|
|
14
|
+
* `<li data-ggui-stack-item>` render path is gone.
|
|
15
|
+
*
|
|
16
|
+
* The exported names (`setStatus`, `setConnectedStatus`, `StatusRefs`)
|
|
17
|
+
* are preserved so the channel handlers + runtime keep their import
|
|
18
|
+
* shape.
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* Build the React mount target. Reuses pre-existing `[data-ggui-stack]`
|
|
22
|
+
* if the shell already wrote one (cf. `buildSelfContainedShell`); else
|
|
23
|
+
* creates a fresh `<ul data-ggui-stack>` and appends it to `<body>`.
|
|
24
|
+
* The companion `status` element is created detached and never
|
|
25
|
+
* appended — consumers that still pass it through `StatusRefs` see no
|
|
26
|
+
* visible effect.
|
|
27
|
+
*
|
|
28
|
+
* The `<ul>` element name is preserved (legacy from the stack-of-N
|
|
29
|
+
* placeholder render path) but only ever holds a single React mount
|
|
30
|
+
* subtree post-stack-removal.
|
|
6
31
|
*/
|
|
7
32
|
export function ensureStatusDom(doc) {
|
|
8
|
-
// Reuse pre-existing nodes if the thin shell wrote them — lets the
|
|
9
|
-
// shell inline a status line if it wants to.
|
|
10
|
-
const existingStatus = doc.querySelector('[data-ggui-status]');
|
|
11
33
|
const existingStack = doc.querySelector('[data-ggui-stack]');
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
34
|
+
const stack = existingStack ??
|
|
35
|
+
(() => {
|
|
36
|
+
const el = doc.createElement('ul');
|
|
37
|
+
el.setAttribute('data-ggui-stack', '');
|
|
38
|
+
doc.body.appendChild(el);
|
|
39
|
+
return el;
|
|
40
|
+
})();
|
|
41
|
+
// Detached placeholder so legacy `setStatus(refs, …)` calls have
|
|
42
|
+
// somewhere to write without touching the visible DOM. `aria-hidden`
|
|
43
|
+
// + zero size belt-and-braces in case any path appends it later.
|
|
16
44
|
const status = doc.createElement('div');
|
|
17
45
|
status.setAttribute('data-ggui-status', 'idle');
|
|
18
|
-
status.
|
|
19
|
-
const stack = doc.createElement('ul');
|
|
20
|
-
stack.setAttribute('data-ggui-stack', '');
|
|
21
|
-
root.appendChild(status);
|
|
22
|
-
root.appendChild(stack);
|
|
46
|
+
status.setAttribute('aria-hidden', 'true');
|
|
23
47
|
return { status, stack };
|
|
24
48
|
}
|
|
25
49
|
/**
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
50
|
+
* Log a status transition. The element is mutated for backward compat
|
|
51
|
+
* (some tests still hold a `refs.status` reference), but production
|
|
52
|
+
* users never see it because the element is detached from `document`.
|
|
29
53
|
*/
|
|
30
54
|
export function setStatus(refs, text, state) {
|
|
31
55
|
refs.status.textContent = text;
|
|
32
56
|
refs.status.setAttribute('data-ggui-status', state);
|
|
57
|
+
// eslint-disable-next-line no-console
|
|
58
|
+
console.log(`[ggui:${state}]`, text);
|
|
33
59
|
}
|
|
34
60
|
/**
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
|
|
39
|
-
export function setConnectedStatus(refs, model) {
|
|
40
|
-
const size = model.size();
|
|
41
|
-
setStatus(refs, `Connected (${size} item${size === 1 ? '' : 's'}).`, 'connected');
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* Re-render the stack DOM into the placeholder element. Wraps the
|
|
45
|
-
* standalone {@link renderStackInto} so callers can pass refs + model
|
|
46
|
-
* without unpacking; the standalone export stays for the legacy
|
|
47
|
-
* callers that have only the bare element in scope.
|
|
61
|
+
* Log the "connected" transition. Post-stack-removal the iframe always
|
|
62
|
+
* holds exactly one item; the message stays bare ("Connected.") since
|
|
63
|
+
* there's no count to surface. Consumers (devtools, e2e specs
|
|
64
|
+
* intercepting `console.log`) get a stable string on every push.
|
|
48
65
|
*/
|
|
49
|
-
export function
|
|
50
|
-
|
|
66
|
+
export function setConnectedStatus(refs) {
|
|
67
|
+
setStatus(refs, 'Connected.', 'connected');
|
|
51
68
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* No-credentials system card.
|
|
3
3
|
*
|
|
4
|
-
* Rendered when the server processed a `
|
|
4
|
+
* Rendered when the server processed a `ggui_render` for a session whose
|
|
5
5
|
* LLM credentials are missing or unresolvable. The user needs to open
|
|
6
6
|
* the server's `/settings` page in a real browser tab to paste an API
|
|
7
7
|
* key.
|
|
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
/**
|
|
3
3
|
* No-credentials system card.
|
|
4
4
|
*
|
|
5
|
-
* Rendered when the server processed a `
|
|
5
|
+
* Rendered when the server processed a `ggui_render` for a session whose
|
|
6
6
|
* LLM credentials are missing or unresolvable. The user needs to open
|
|
7
7
|
* the server's `/settings` page in a real browser tab to paste an API
|
|
8
8
|
* key.
|
|
@@ -211,7 +211,7 @@ function defaultParams(method) {
|
|
|
211
211
|
intent: 'probe-click',
|
|
212
212
|
data: { note: 'hello from the protocol probe' },
|
|
213
213
|
},
|
|
214
|
-
|
|
214
|
+
renderId: 'probe-render',
|
|
215
215
|
appId: 'probe-app',
|
|
216
216
|
actionId: '00000000', // overwritten in onClick with real FNV-1a
|
|
217
217
|
firedAt: new Date().toISOString(),
|
|
@@ -312,7 +312,7 @@ function ProbeButtonRow({ method, description, call, }) {
|
|
|
312
312
|
const args = params
|
|
313
313
|
.arguments ?? {};
|
|
314
314
|
// New gesture-envelope shape (SPEC §4.6): `{kind, payload,
|
|
315
|
-
//
|
|
315
|
+
// renderId, appId, actionId, firedAt}`. For Pattern β the
|
|
316
316
|
// `payload` carries `{intent, data}`.
|
|
317
317
|
const payload = args['payload'] ?? {};
|
|
318
318
|
const intent = String(payload['intent'] ?? '?');
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* System-card registry.
|
|
3
3
|
*
|
|
4
|
-
* Central mapping from `
|
|
4
|
+
* Central mapping from `SystemRender.kind` (a stable wire string)
|
|
5
5
|
* to a real React component bundled inside the iframe-runtime. The
|
|
6
6
|
* runtime's self-contained boot path looks up the kind here when it
|
|
7
|
-
* sees a
|
|
7
|
+
* sees a render with `type: 'system'`. Unknown kinds fall through
|
|
8
8
|
* to {@link UnknownSystemCard} so an old runtime + new server still
|
|
9
9
|
* surfaces something visible (vs. a blank iframe).
|
|
10
10
|
*
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* 1. Author `MyNewCard.tsx` in this directory.
|
|
14
14
|
* 2. Add an entry to {@link SYSTEM_CARD_REGISTRY} below.
|
|
15
15
|
* 3. (Optional) Add the new kind string to
|
|
16
|
-
* `
|
|
16
|
+
* `SystemRenderKind` in `@ggui-ai/protocol` for IDE autocomplete.
|
|
17
17
|
*/
|
|
18
18
|
import * as React from 'react';
|
|
19
19
|
import { NoCredentialsCard, type NoCredentialsCardProps } from './NoCredentialsCard.js';
|
|
@@ -28,7 +28,7 @@ import { ProtocolProbeCard, type ProtocolProbeCardProps } from './ProtocolProbeC
|
|
|
28
28
|
export type SystemCardComponent = React.ComponentType<Record<string, unknown>>;
|
|
29
29
|
/**
|
|
30
30
|
* Registered system-card kinds. Keep keys aligned with
|
|
31
|
-
* `
|
|
31
|
+
* `SystemRenderKind` in `@ggui-ai/protocol` so wire + bundle stay
|
|
32
32
|
* in sync. New kinds added without a registry entry render as
|
|
33
33
|
* {@link UnknownSystemCard}.
|
|
34
34
|
*/
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* System-card registry.
|
|
3
3
|
*
|
|
4
|
-
* Central mapping from `
|
|
4
|
+
* Central mapping from `SystemRender.kind` (a stable wire string)
|
|
5
5
|
* to a real React component bundled inside the iframe-runtime. The
|
|
6
6
|
* runtime's self-contained boot path looks up the kind here when it
|
|
7
|
-
* sees a
|
|
7
|
+
* sees a render with `type: 'system'`. Unknown kinds fall through
|
|
8
8
|
* to {@link UnknownSystemCard} so an old runtime + new server still
|
|
9
9
|
* surfaces something visible (vs. a blank iframe).
|
|
10
10
|
*
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* 1. Author `MyNewCard.tsx` in this directory.
|
|
14
14
|
* 2. Add an entry to {@link SYSTEM_CARD_REGISTRY} below.
|
|
15
15
|
* 3. (Optional) Add the new kind string to
|
|
16
|
-
* `
|
|
16
|
+
* `SystemRenderKind` in `@ggui-ai/protocol` for IDE autocomplete.
|
|
17
17
|
*/
|
|
18
18
|
import * as React from 'react';
|
|
19
19
|
import { ThemeProvider, lightTheme, darkTheme } from '@ggui-ai/design/themes';
|
|
@@ -64,7 +64,7 @@ function UnknownSystemCard({ kind, props, }) {
|
|
|
64
64
|
}
|
|
65
65
|
/**
|
|
66
66
|
* Registered system-card kinds. Keep keys aligned with
|
|
67
|
-
* `
|
|
67
|
+
* `SystemRenderKind` in `@ggui-ai/protocol` so wire + bundle stay
|
|
68
68
|
* in sync. New kinds added without a registry entry render as
|
|
69
69
|
* {@link UnknownSystemCard}.
|
|
70
70
|
*/
|
package/dist/types.d.ts
CHANGED
|
@@ -2,22 +2,57 @@
|
|
|
2
2
|
* Internal types shared across the `@ggui-ai/iframe-runtime` runtime.
|
|
3
3
|
*
|
|
4
4
|
* These shapes describe the renderer's INTERNAL contracts — the
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
5
|
+
* slice-parse outcome union + the renderer-host postMessage frames.
|
|
6
|
+
* The wire shapes consumed FROM the network (`SubscribePayload`,
|
|
7
|
+
* `AckPayload`, `WebSocketMessage`, `McpAppAiGguiRenderMeta`) come from
|
|
8
|
+
* `@ggui-ai/protocol` and are imported as `type` only so esbuild
|
|
9
|
+
* emits no runtime require for the protocol package — the bundle
|
|
10
|
+
* stays self-contained.
|
|
11
11
|
*
|
|
12
|
-
* Post-B3b: the WS lifecycle lives inside `@ggui-ai/channel
|
|
12
|
+
* Post-B3b: the WS lifecycle lives inside `@ggui-ai/live-channel`'s
|
|
13
13
|
* `WSTransport`; the renderer no longer maintains its own manager
|
|
14
14
|
* class. The `RendererWebSocketManagerOptions` type that pre-B3b
|
|
15
15
|
* declared the manager's constructor bag has been retired.
|
|
16
16
|
*/
|
|
17
|
-
import type {
|
|
18
|
-
import type { HostContextProjection } from '@ggui-ai/protocol';
|
|
17
|
+
import type { McpAppAiGguiRenderMeta } from '@ggui-ai/protocol/integrations/mcp-apps';
|
|
18
|
+
import type { HostContextProjection, ComponentRender, SystemRender } from '@ggui-ai/protocol';
|
|
19
19
|
/**
|
|
20
|
-
*
|
|
20
|
+
* Post-Phase-B alias kept for ergonomic call sites — the wire-side
|
|
21
|
+
* `McpAppAiGguiRenderMeta` is the single source of truth, and the
|
|
22
|
+
* "validated" qualifier is a no-op now (no nested-optional-session
|
|
23
|
+
* narrowing left after the slice merge). Future callers SHOULD prefer
|
|
24
|
+
* `McpAppAiGguiRenderMeta` directly; the alias persists so the rename
|
|
25
|
+
* sweep can land incrementally without churn at every call site.
|
|
26
|
+
*/
|
|
27
|
+
export type ValidatedMcpAppAiGguiMeta = McpAppAiGguiRenderMeta;
|
|
28
|
+
/**
|
|
29
|
+
* The four server-assigned ledger fields on every wire-delivered
|
|
30
|
+
* {@link Render}. They're stamped by the server's per-render event
|
|
31
|
+
* ledger — NOT derivable from the inline `__GGUI_META__` bootstrap.
|
|
32
|
+
*/
|
|
33
|
+
type RenderLedgerFields = 'eventSequence' | 'createdAt' | 'lastActivityAt' | 'expiresAt';
|
|
34
|
+
/**
|
|
35
|
+
* The mount surface's INPUT contract — what `mountRender` / `applyRender`
|
|
36
|
+
* accept. It is a {@link Render} minus the four server-assigned ledger
|
|
37
|
+
* fields ({@link RenderLedgerFields}), so the runtime can mount the
|
|
38
|
+
* compiled component (or system card) carried inline by the resource
|
|
39
|
+
* shell BEFORE the authoritative wire `Render` arrives over the WS.
|
|
40
|
+
*
|
|
41
|
+
* A full `Render` is assignable to `RenderSeedInput` (it carries every
|
|
42
|
+
* field plus the ledger), so the WS-ack reconcile path passes a real
|
|
43
|
+
* `Render` here unchanged; the inline-seed path passes the projection
|
|
44
|
+
* built by `buildRenderSeedInput`. We do NOT fabricate the ledger fields
|
|
45
|
+
* (Strict-Typing-First / no-type-laundering) — the first ack replaces
|
|
46
|
+
* the seed with the authoritative `Render`.
|
|
47
|
+
*
|
|
48
|
+
* Carries the SAME contract-spec fields a full `ComponentRender` does
|
|
49
|
+
* (`propsSpec` / `streamSpec` / `actionSpec`), as `undefined` on a
|
|
50
|
+
* seed — so the channel handlers that read those after the
|
|
51
|
+
* `type !== 'mcpApps' && type !== 'system'` narrowing stay type-clean.
|
|
52
|
+
*/
|
|
53
|
+
export type RenderSeedInput = Omit<ComponentRender, RenderLedgerFields> | Omit<SystemRender, RenderLedgerFields>;
|
|
54
|
+
/**
|
|
55
|
+
* Why a slice-meta parse can fail. Closed union — every value is a
|
|
21
56
|
* canonical reason the renderer surfaces to the host via postMessage.
|
|
22
57
|
*
|
|
23
58
|
* This set is intentionally narrow — it covers only parse-time
|
|
@@ -28,42 +63,43 @@ import type { HostContextProjection } from '@ggui-ai/protocol';
|
|
|
28
63
|
* - `MISSING_TOOL_OUTPUT` — host echoed `ui/initialize` without a
|
|
29
64
|
* `result.toolOutput` object at all.
|
|
30
65
|
* - `MISSING_META_GGUI_BOOTSTRAP` — `result.toolOutput` exists but
|
|
31
|
-
* `_meta.ggui
|
|
32
|
-
* `BOOTSTRAP_META_MISSING`.
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
66
|
+
* `_meta["ai.ggui/render"]` is absent. The on-wire synonym is
|
|
67
|
+
* `BOOTSTRAP_META_MISSING`. (Name retained pre-R4 for the
|
|
68
|
+
* observability + host-postMessage protocol; cosmetic rename is
|
|
69
|
+
* deferred.)
|
|
70
|
+
* - `MALFORMED_BOOTSTRAP` — slice is present but fails business
|
|
71
|
+
* rules (no live mode and no static content, mode discriminators
|
|
72
|
+
* mutually exclusive, structural rejection by the combiner).
|
|
73
|
+
* - `EXPIRED_BOOTSTRAP` — `expiresAt` parses to a timestamp in the
|
|
74
|
+
* past AND there's no static content to degrade to.
|
|
40
75
|
*/
|
|
41
|
-
export type
|
|
76
|
+
export type McpAppAiGguiMetaParseFailureReason = 'MISSING_TOOL_OUTPUT' | 'MISSING_META_GGUI_BOOTSTRAP' | 'MALFORMED_BOOTSTRAP' | 'EXPIRED_BOOTSTRAP';
|
|
42
77
|
/**
|
|
43
|
-
* Result of a
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
78
|
+
* Result of a slice-meta extraction attempt. Discriminated on `ok`
|
|
79
|
+
* so call sites get exhaustive narrowing without a typed-error class
|
|
80
|
+
* — keeps the renderer's runtime cost tiny (no class metadata in the
|
|
81
|
+
* bundle).
|
|
47
82
|
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
* is extracted from the `ui/initialize` response (Reading-A path),
|
|
51
|
-
* parser opportunistically projects the surrounding
|
|
52
|
-
* into this field so the runtime can:
|
|
83
|
+
* The `ok: true` arm carries the validated {@link McpAppAiGguiRenderMeta}
|
|
84
|
+
* slice and optionally a `hostContext: HostContextProjection`. When the
|
|
85
|
+
* meta is extracted from the `ui/initialize` response (Reading-A path),
|
|
86
|
+
* the parser opportunistically projects the surrounding
|
|
87
|
+
* `McpUiHostContext` into this field so the runtime can:
|
|
53
88
|
* - drive canvas-mode display-mode escalation
|
|
54
89
|
* - echo to the server (live-channel `host_context_observed` envelope)
|
|
55
90
|
* - feed the agent on next handshake/consume
|
|
56
91
|
*
|
|
57
92
|
* Capture is best-effort: a malformed `HostContext` never blocks the
|
|
58
|
-
*
|
|
59
|
-
* (`
|
|
93
|
+
* slice parse. Absent for the other extraction paths
|
|
94
|
+
* (`__GGUI_META__` global, `ui/notifications/tool-result`) — those
|
|
60
95
|
* envelopes don't carry HostContext.
|
|
61
96
|
*/
|
|
62
|
-
export type
|
|
97
|
+
export type McpAppAiGguiMetaParseResult = {
|
|
63
98
|
readonly ok: true;
|
|
64
|
-
readonly
|
|
99
|
+
readonly meta: McpAppAiGguiRenderMeta;
|
|
65
100
|
readonly hostContext?: HostContextProjection;
|
|
66
101
|
} | {
|
|
67
102
|
readonly ok: false;
|
|
68
|
-
readonly reason:
|
|
103
|
+
readonly reason: McpAppAiGguiMetaParseFailureReason;
|
|
69
104
|
};
|
|
105
|
+
export {};
|
package/dist/types.js
CHANGED
package/dist/validation.d.ts
CHANGED
|
@@ -62,8 +62,8 @@ export interface RendererValidatorContext {
|
|
|
62
62
|
export declare function validateOutboundActionEnvelope(actionSpec: ActionSpec | undefined, envelope: ActionEnvelope): ValidationResult;
|
|
63
63
|
/**
|
|
64
64
|
* Validate an inbound stream-channel delivery before applying it to
|
|
65
|
-
*
|
|
66
|
-
* when the target
|
|
65
|
+
* render state. Known reserved channels (`_ggui:*`) validate even
|
|
66
|
+
* when the target render has no declared `streamSpec` — the
|
|
67
67
|
* payload shape is server-owned; user channels stay permissive without
|
|
68
68
|
* a contract.
|
|
69
69
|
*/
|
package/dist/validation.js
CHANGED
|
@@ -70,8 +70,8 @@ export function validateOutboundActionEnvelope(actionSpec, envelope) {
|
|
|
70
70
|
}
|
|
71
71
|
/**
|
|
72
72
|
* Validate an inbound stream-channel delivery before applying it to
|
|
73
|
-
*
|
|
74
|
-
* when the target
|
|
73
|
+
* render state. Known reserved channels (`_ggui:*`) validate even
|
|
74
|
+
* when the target render has no declared `streamSpec` — the
|
|
75
75
|
* payload shape is server-owned; user channels stay permissive without
|
|
76
76
|
* a contract.
|
|
77
77
|
*/
|