@ggui-ai/iframe-runtime 0.1.0-rc.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.
- package/LICENSE +201 -0
- package/README.md +33 -0
- package/dist/bootstrap.d.ts +72 -0
- package/dist/bootstrap.js +500 -0
- package/dist/canvas/animator/animator-host.d.ts +63 -0
- package/dist/canvas/animator/animator-host.js +105 -0
- package/dist/canvas/animator/animator-pill.d.ts +42 -0
- package/dist/canvas/animator/animator-pill.js +119 -0
- package/dist/canvas/animator/state-machine.d.ts +106 -0
- package/dist/canvas/animator/state-machine.js +150 -0
- package/dist/canvas/canvas-shell.d.ts +77 -0
- package/dist/canvas/canvas-shell.js +117 -0
- package/dist/canvas/display-mode-policy.d.ts +104 -0
- package/dist/canvas/display-mode-policy.js +98 -0
- package/dist/canvas/mount.d.ts +150 -0
- package/dist/canvas/mount.js +202 -0
- package/dist/canvas/nav-stack.d.ts +133 -0
- package/dist/canvas/nav-stack.js +172 -0
- package/dist/channel-transport.d.ts +182 -0
- package/dist/channel-transport.js +344 -0
- package/dist/channels/channel-payload.d.ts +20 -0
- package/dist/channels/channel-payload.js +34 -0
- package/dist/channels/data.d.ts +48 -0
- package/dist/channels/data.js +103 -0
- package/dist/channels/drain-ack.d.ts +13 -0
- package/dist/channels/drain-ack.js +15 -0
- package/dist/channels/feedback.d.ts +14 -0
- package/dist/channels/feedback.js +19 -0
- package/dist/channels/index.d.ts +7 -0
- package/dist/channels/index.js +7 -0
- package/dist/channels/props-update.d.ts +53 -0
- package/dist/channels/props-update.js +130 -0
- package/dist/channels/push.d.ts +47 -0
- package/dist/channels/push.js +54 -0
- package/dist/channels/system.d.ts +26 -0
- package/dist/channels/system.js +44 -0
- package/dist/compiled-validators.d.ts +40 -0
- package/dist/compiled-validators.js +74 -0
- package/dist/context-observer.d.ts +205 -0
- package/dist/context-observer.js +312 -0
- package/dist/gadget-loader.d.ts +118 -0
- package/dist/gadget-loader.js +136 -0
- package/dist/globals.d.ts +234 -0
- package/dist/globals.js +101 -0
- package/dist/host-context-emitter.d.ts +91 -0
- package/dist/host-context-emitter.js +213 -0
- package/dist/iframe-runtime.js +261 -0
- package/dist/index.d.ts +38 -0
- package/dist/index.js +4 -0
- package/dist/lifecycle.d.ts +66 -0
- package/dist/lifecycle.js +49 -0
- package/dist/mcp-app-iframe-host.d.ts +69 -0
- package/dist/mcp-app-iframe-host.js +214 -0
- package/dist/observability.d.ts +225 -0
- package/dist/observability.js +28 -0
- package/dist/protocol-error.d.ts +199 -0
- package/dist/protocol-error.js +116 -0
- package/dist/provisional-renderer.d.ts +62 -0
- package/dist/provisional-renderer.js +323 -0
- package/dist/react-renderer.d.ts +95 -0
- package/dist/react-renderer.js +343 -0
- package/dist/registry-subscribe.d.ts +102 -0
- package/dist/registry-subscribe.js +319 -0
- package/dist/runtime.d.ts +531 -0
- package/dist/runtime.js +2623 -0
- package/dist/server.d.ts +36 -0
- package/dist/server.js +72 -0
- package/dist/stack-item-renderer.d.ts +103 -0
- package/dist/stack-item-renderer.js +270 -0
- package/dist/stack.d.ts +90 -0
- package/dist/stack.js +118 -0
- package/dist/status-dom.d.ts +72 -0
- package/dist/status-dom.js +51 -0
- package/dist/system-cards/NoCredentialsCard.d.ts +33 -0
- package/dist/system-cards/NoCredentialsCard.js +189 -0
- package/dist/system-cards/ProtocolProbeCard.d.ts +64 -0
- package/dist/system-cards/ProtocolProbeCard.js +463 -0
- package/dist/system-cards/QrCode.d.ts +46 -0
- package/dist/system-cards/QrCode.js +55 -0
- package/dist/system-cards/host-detect.d.ts +31 -0
- package/dist/system-cards/host-detect.js +108 -0
- package/dist/system-cards/host-intents.d.ts +85 -0
- package/dist/system-cards/host-intents.js +170 -0
- package/dist/system-cards/index.d.ts +70 -0
- package/dist/system-cards/index.js +134 -0
- package/dist/types.d.ts +69 -0
- package/dist/types.js +3 -0
- package/dist/validation.d.ts +83 -0
- package/dist/validation.js +106 -0
- package/dist/wire-config.d.ts +214 -0
- package/dist/wire-config.js +290 -0
- package/package.json +81 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default emitter — posts an {@link ObservabilityMessage} to
|
|
3
|
+
* `window.parent`. Mirrors `postBootFailure` / `postRendererReady`
|
|
4
|
+
* posture in `runtime.ts`: swallows postMessage failure so a detached
|
|
5
|
+
* parent doesn't crash the iframe.
|
|
6
|
+
*
|
|
7
|
+
* Lives here (not in `runtime.ts`) so tests exercising individual
|
|
8
|
+
* emission sites can import the same default without dragging in the
|
|
9
|
+
* runtime's module side-effects.
|
|
10
|
+
*
|
|
11
|
+
* @public
|
|
12
|
+
*/
|
|
13
|
+
export function postObservabilityToParent(event) {
|
|
14
|
+
// A non-browser import graph (vitest + jsdom before a window is
|
|
15
|
+
// mocked in) has no `window.parent` — guard for that environment
|
|
16
|
+
// so tests importing this helper never throw before their mocks
|
|
17
|
+
// install.
|
|
18
|
+
if (typeof window === 'undefined' || window.parent === null)
|
|
19
|
+
return;
|
|
20
|
+
const message = { type: 'ggui:observe', event };
|
|
21
|
+
try {
|
|
22
|
+
window.parent.postMessage(message, '*');
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
// Parent unreachable (detached window). Best-effort fire-and-
|
|
26
|
+
// forget — matches postBootFailure's swallow posture.
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `ProtocolError` typed union — canonical shape for every error the
|
|
3
|
+
* renderer surfaces OUTWARD: to the host page via postMessage, to the
|
|
4
|
+
* session via the `_ggui:contract-error` channel, and to the
|
|
5
|
+
* in-iframe status DOM.
|
|
6
|
+
*
|
|
7
|
+
* The transport wiring around this union:
|
|
8
|
+
*
|
|
9
|
+
* - `postMessage({type:'ggui:protocol-error', error})` for every
|
|
10
|
+
* boot-path failure; the `_ggui:contract-error` envelope on the
|
|
11
|
+
* live channel for session-bound failures.
|
|
12
|
+
* - `<McpAppIframe onError={(err: ProtocolError) => …}>` surfaces
|
|
13
|
+
* these to embedding apps.
|
|
14
|
+
*
|
|
15
|
+
* The union is the failure-mode axis of `WireConfig`'s contract:
|
|
16
|
+
* named parties = renderer ↔ host; obligation = the renderer emits a
|
|
17
|
+
* ProtocolError for every failure class; failure mode = exhaustive
|
|
18
|
+
* on `kind`; observable = hosts can pattern-match `err.kind`.
|
|
19
|
+
*
|
|
20
|
+
* Extensibly-closed discipline: `kind: 'protocol'`'s `code` and the
|
|
21
|
+
* `BootstrapFailureReason` union both accept `(string & {})` so
|
|
22
|
+
* servers can introduce new codes without a client bump while IDE
|
|
23
|
+
* autocomplete still lists the canonical set. Every OTHER
|
|
24
|
+
* discriminator (`kind` itself, transport codes, auth codes, version
|
|
25
|
+
* fields) is fully closed — drift there is a real shape change, not
|
|
26
|
+
* a new code.
|
|
27
|
+
*/
|
|
28
|
+
import type { ContractErrorPayload } from '@ggui-ai/protocol';
|
|
29
|
+
import { ClientContractViolationError } from '@ggui-ai/wire';
|
|
30
|
+
/**
|
|
31
|
+
* Closed-or-extensibly-closed union of bootstrap-failure reasons.
|
|
32
|
+
*
|
|
33
|
+
* Consolidates three sources:
|
|
34
|
+
*
|
|
35
|
+
* 1. **Parse-time failures** — every member of
|
|
36
|
+
* `BootstrapParseFailureReason` (`MISSING_TOOL_OUTPUT` /
|
|
37
|
+
* `MISSING_META_GGUI_BOOTSTRAP` / `MALFORMED_BOOTSTRAP` /
|
|
38
|
+
* `EXPIRED_BOOTSTRAP`). `MISSING_META_GGUI_BOOTSTRAP` and
|
|
39
|
+
* `BOOTSTRAP_META_MISSING` are synonyms — the latter is the
|
|
40
|
+
* on-wire name, the former the parse-internal name.
|
|
41
|
+
*
|
|
42
|
+
* 2. **Post-parse orchestration failures** — `UI_INITIALIZE_FAILED`
|
|
43
|
+
* / `WS_HANDSHAKE_FAILED`. Matches `RendererBootFailureReason`.
|
|
44
|
+
*
|
|
45
|
+
* 3. **Transport-observable failures** — `BUNDLE_FETCH_FAILED` /
|
|
46
|
+
* `CSP_VIOLATION` / `SESSION_NOT_FOUND` / `AUTH_REJECTED`. These
|
|
47
|
+
* fire before the renderer parse path runs, so they're authored
|
|
48
|
+
* here rather than inside `BootstrapParseFailureReason`.
|
|
49
|
+
*
|
|
50
|
+
* `(string & {})` tail keeps the union extensibly-closed — new wire
|
|
51
|
+
* codes can land without a client bump, while IDE autocomplete
|
|
52
|
+
* surfaces the canonical set.
|
|
53
|
+
*/
|
|
54
|
+
export type BootstrapFailureReason = 'MISSING_TOOL_OUTPUT' | 'MISSING_META_GGUI_BOOTSTRAP' | 'BOOTSTRAP_META_MISSING' | 'MALFORMED_BOOTSTRAP' | 'EXPIRED_BOOTSTRAP' | 'UI_INITIALIZE_FAILED' | 'WS_HANDSHAKE_FAILED' | 'UPGRADE_REQUIRED' | 'BUNDLE_FETCH_FAILED' | 'CSP_VIOLATION' | 'SESSION_NOT_FOUND' | 'AUTH_REJECTED' | (string & {});
|
|
55
|
+
/**
|
|
56
|
+
* Every error the renderer surfaces outward flows through this union.
|
|
57
|
+
*
|
|
58
|
+
* Discriminated on `kind`:
|
|
59
|
+
*
|
|
60
|
+
* - `transport` — WebSocket-level failure (DISCONNECTED / TIMEOUT).
|
|
61
|
+
* Includes `retryable` so hosts can decide to reconnect
|
|
62
|
+
* vs. give up.
|
|
63
|
+
* - `auth` — session / token rejection pre-handshake.
|
|
64
|
+
* `SESSION_NOT_FOUND` / `TOKEN_EXPIRED` /
|
|
65
|
+
* `AUTH_REJECTED` — all terminal; hosts typically
|
|
66
|
+
* escalate to a login flow.
|
|
67
|
+
* - `protocol` — envelope / session-mismatch failures post-handshake.
|
|
68
|
+
* Extensibly-closed on `code` because servers may
|
|
69
|
+
* introduce new codes without a client bump.
|
|
70
|
+
* `details` carries opaque structured context.
|
|
71
|
+
* - `contract` — client-contract violation. Payload matches the
|
|
72
|
+
* protocol-owned `ContractErrorPayload` so the
|
|
73
|
+
* `_ggui:contract-error` envelope shape flows
|
|
74
|
+
* unchanged through this variant.
|
|
75
|
+
* - `bootstrap` — anything in {@link BootstrapFailureReason}.
|
|
76
|
+
* - `version` — `UPGRADE_REQUIRED` path (handshake rejection).
|
|
77
|
+
* `serverVersion` may be absent on the wire; callers
|
|
78
|
+
* tolerate `undefined` for legacy servers.
|
|
79
|
+
* - `unknown` — fallback for anything the renderer failed to
|
|
80
|
+
* classify. Always carries the raw value so hosts
|
|
81
|
+
* can at least log it.
|
|
82
|
+
*/
|
|
83
|
+
export type ProtocolError = {
|
|
84
|
+
readonly kind: 'transport';
|
|
85
|
+
readonly code: 'DISCONNECTED' | 'TIMEOUT';
|
|
86
|
+
readonly retryable: boolean;
|
|
87
|
+
readonly message?: string;
|
|
88
|
+
} | {
|
|
89
|
+
readonly kind: 'auth';
|
|
90
|
+
readonly code: 'SESSION_NOT_FOUND' | 'TOKEN_EXPIRED' | 'AUTH_REJECTED';
|
|
91
|
+
readonly message?: string;
|
|
92
|
+
} | {
|
|
93
|
+
readonly kind: 'protocol';
|
|
94
|
+
readonly code: 'SESSION_MISMATCH' | 'APP_MISMATCH' | 'MALFORMED_ENVELOPE' | (string & {});
|
|
95
|
+
readonly message?: string;
|
|
96
|
+
readonly details?: unknown;
|
|
97
|
+
} | {
|
|
98
|
+
readonly kind: 'contract';
|
|
99
|
+
readonly payload: ContractErrorPayload;
|
|
100
|
+
} | {
|
|
101
|
+
readonly kind: 'bootstrap';
|
|
102
|
+
readonly reason: BootstrapFailureReason;
|
|
103
|
+
readonly message: string;
|
|
104
|
+
} | {
|
|
105
|
+
readonly kind: 'version';
|
|
106
|
+
readonly serverVersion?: string;
|
|
107
|
+
readonly clientSupports: readonly string[];
|
|
108
|
+
readonly message?: string;
|
|
109
|
+
} | {
|
|
110
|
+
readonly kind: 'unknown';
|
|
111
|
+
readonly raw: unknown;
|
|
112
|
+
};
|
|
113
|
+
/**
|
|
114
|
+
* Caller sink for every `ProtocolError` the renderer classifies.
|
|
115
|
+
*
|
|
116
|
+
* This is OPTIONAL on every emitter site — the default is a tagged
|
|
117
|
+
* `console.warn` so operators see the error in dev. The
|
|
118
|
+
* `<McpAppIframe>` host wrapper bridges this to its `onError` prop;
|
|
119
|
+
* session-bound variants are ALSO routed to the
|
|
120
|
+
* `_ggui:contract-error` envelope over the WebSocket.
|
|
121
|
+
*
|
|
122
|
+
* Handlers MUST NOT throw — the emitter already fired the renderer's
|
|
123
|
+
* own fallback path; a throwing handler would mask the real error.
|
|
124
|
+
* Implementations that want to re-surface (e.g. console inspector)
|
|
125
|
+
* should `queueMicrotask(() => …)` before any heavier work.
|
|
126
|
+
*/
|
|
127
|
+
export type ProtocolErrorEmitter = (err: ProtocolError) => void;
|
|
128
|
+
/**
|
|
129
|
+
* Default emitter — operator-visible `console.warn` with a grep-
|
|
130
|
+
* friendly tag. Identical posture to `GguiSession.surfaceContractViolation`'s
|
|
131
|
+
* console.warn fallback. Callers override by injecting their own.
|
|
132
|
+
*/
|
|
133
|
+
export declare function defaultProtocolErrorEmitter(err: ProtocolError): void;
|
|
134
|
+
/**
|
|
135
|
+
* Map a client-side `ClientContractViolationError` (from
|
|
136
|
+
* `@ggui-ai/wire`, fired when a pre-dispatch validator rejects an
|
|
137
|
+
* outbound action, or when an inbound stream / props payload fails the
|
|
138
|
+
* local validator) onto a `ProtocolError`.
|
|
139
|
+
*
|
|
140
|
+
* Client-side violations do NOT ride the server-emitted
|
|
141
|
+
* `_ggui:contract-error` envelope — that shape (`ContractErrorPayload`)
|
|
142
|
+
* is tool-failure-scoped and authored by the session-channel router.
|
|
143
|
+
* A client-side violation is a DIFFERENT category: nothing reached the
|
|
144
|
+
* tool. We surface it as `{kind: 'protocol'; code:
|
|
145
|
+
* 'CLIENT_CONTRACT_VIOLATION'}` with structured `details` so hosts can
|
|
146
|
+
* render the same summary that `console.warn` would have produced.
|
|
147
|
+
*
|
|
148
|
+
* Server-emitted `ContractErrorPayload` landing on
|
|
149
|
+
* `_ggui:contract-error` rides the separate `{kind: 'contract'}`
|
|
150
|
+
* variant — that path activates when the renderer observes the
|
|
151
|
+
* reserved channel.
|
|
152
|
+
*/
|
|
153
|
+
export declare function fromClientContractViolation(err: ClientContractViolationError): ProtocolError;
|
|
154
|
+
/**
|
|
155
|
+
* Wrap a server-emitted `ContractErrorPayload` (received over the
|
|
156
|
+
* reserved `_ggui:contract-error` channel) as the 'contract' variant.
|
|
157
|
+
* Trivial wrapper — exists so call sites produce the union via a
|
|
158
|
+
* factory rather than an object literal (keeps emission uniform and
|
|
159
|
+
* makes grep for creation sites exact).
|
|
160
|
+
*/
|
|
161
|
+
export declare function fromContractErrorPayload(payload: ContractErrorPayload): ProtocolError;
|
|
162
|
+
/**
|
|
163
|
+
* Build a `ProtocolError` of kind 'version' from the existing
|
|
164
|
+
* `UpgradeRequiredError` class. Matches the `liftUpgradeRequiredFromError`
|
|
165
|
+
* shape already plumbed through `subscribe.ts`.
|
|
166
|
+
*
|
|
167
|
+
* `UpgradeRequiredError.observedVersion` can be `string` (one version)
|
|
168
|
+
* OR `readonly string[]` (the server advertised a set). We collapse
|
|
169
|
+
* the array form to a comma-separated string to keep the 'version'
|
|
170
|
+
* variant shape a single optional string — hosts render the observed
|
|
171
|
+
* set uniformly.
|
|
172
|
+
*/
|
|
173
|
+
export declare function fromUpgradeRequired(err: {
|
|
174
|
+
readonly observedVersion?: string | readonly string[];
|
|
175
|
+
readonly acceptedVersions: readonly string[];
|
|
176
|
+
readonly message: string;
|
|
177
|
+
}): ProtocolError;
|
|
178
|
+
/**
|
|
179
|
+
* Build a `ProtocolError` of kind 'bootstrap' — closed-or-extensibly-
|
|
180
|
+
* closed reason + operator-visible message.
|
|
181
|
+
*/
|
|
182
|
+
export declare function fromBootstrapFailure(reason: BootstrapFailureReason, message: string): ProtocolError;
|
|
183
|
+
/**
|
|
184
|
+
* Fallback constructor — wraps any raw value we can't classify.
|
|
185
|
+
* Keeps the emitter union total.
|
|
186
|
+
*/
|
|
187
|
+
export declare function fromUnknown(raw: unknown): ProtocolError;
|
|
188
|
+
/**
|
|
189
|
+
* Build a `ProtocolError` of kind 'transport' — disconnection /
|
|
190
|
+
* timeout paths. `retryable` differentiates the reconnection-eligible
|
|
191
|
+
* `DISCONNECTED` from terminal `TIMEOUT` states; hosts pattern-match
|
|
192
|
+
* on the flag.
|
|
193
|
+
*/
|
|
194
|
+
export declare function fromTransportFailure(code: 'DISCONNECTED' | 'TIMEOUT', retryable: boolean, message?: string): ProtocolError;
|
|
195
|
+
/**
|
|
196
|
+
* Build a `ProtocolError` of kind 'auth' — session / token rejection
|
|
197
|
+
* pre-handshake.
|
|
198
|
+
*/
|
|
199
|
+
export declare function fromAuthFailure(code: 'SESSION_NOT_FOUND' | 'TOKEN_EXPIRED' | 'AUTH_REJECTED', message?: string): ProtocolError;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default emitter — operator-visible `console.warn` with a grep-
|
|
3
|
+
* friendly tag. Identical posture to `GguiSession.surfaceContractViolation`'s
|
|
4
|
+
* console.warn fallback. Callers override by injecting their own.
|
|
5
|
+
*/
|
|
6
|
+
export function defaultProtocolErrorEmitter(err) {
|
|
7
|
+
// eslint-disable-next-line no-console -- dev-visible signal; mirrors
|
|
8
|
+
// the pre-ProtocolError console.warn fallbacks across renderer paths.
|
|
9
|
+
console.warn('[ggui:protocol-error]', err);
|
|
10
|
+
}
|
|
11
|
+
// =============================================================================
|
|
12
|
+
// Constructors — keep creation sites honest
|
|
13
|
+
// =============================================================================
|
|
14
|
+
/**
|
|
15
|
+
* Map a client-side `ClientContractViolationError` (from
|
|
16
|
+
* `@ggui-ai/wire`, fired when a pre-dispatch validator rejects an
|
|
17
|
+
* outbound action, or when an inbound stream / props payload fails the
|
|
18
|
+
* local validator) onto a `ProtocolError`.
|
|
19
|
+
*
|
|
20
|
+
* Client-side violations do NOT ride the server-emitted
|
|
21
|
+
* `_ggui:contract-error` envelope — that shape (`ContractErrorPayload`)
|
|
22
|
+
* is tool-failure-scoped and authored by the session-channel router.
|
|
23
|
+
* A client-side violation is a DIFFERENT category: nothing reached the
|
|
24
|
+
* tool. We surface it as `{kind: 'protocol'; code:
|
|
25
|
+
* 'CLIENT_CONTRACT_VIOLATION'}` with structured `details` so hosts can
|
|
26
|
+
* render the same summary that `console.warn` would have produced.
|
|
27
|
+
*
|
|
28
|
+
* Server-emitted `ContractErrorPayload` landing on
|
|
29
|
+
* `_ggui:contract-error` rides the separate `{kind: 'contract'}`
|
|
30
|
+
* variant — that path activates when the renderer observes the
|
|
31
|
+
* reserved channel.
|
|
32
|
+
*/
|
|
33
|
+
export function fromClientContractViolation(err) {
|
|
34
|
+
return {
|
|
35
|
+
kind: 'protocol',
|
|
36
|
+
code: 'CLIENT_CONTRACT_VIOLATION',
|
|
37
|
+
message: err.message,
|
|
38
|
+
details: {
|
|
39
|
+
direction: err.direction,
|
|
40
|
+
violations: err.violations,
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Wrap a server-emitted `ContractErrorPayload` (received over the
|
|
46
|
+
* reserved `_ggui:contract-error` channel) as the 'contract' variant.
|
|
47
|
+
* Trivial wrapper — exists so call sites produce the union via a
|
|
48
|
+
* factory rather than an object literal (keeps emission uniform and
|
|
49
|
+
* makes grep for creation sites exact).
|
|
50
|
+
*/
|
|
51
|
+
export function fromContractErrorPayload(payload) {
|
|
52
|
+
return { kind: 'contract', payload };
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Build a `ProtocolError` of kind 'version' from the existing
|
|
56
|
+
* `UpgradeRequiredError` class. Matches the `liftUpgradeRequiredFromError`
|
|
57
|
+
* shape already plumbed through `subscribe.ts`.
|
|
58
|
+
*
|
|
59
|
+
* `UpgradeRequiredError.observedVersion` can be `string` (one version)
|
|
60
|
+
* OR `readonly string[]` (the server advertised a set). We collapse
|
|
61
|
+
* the array form to a comma-separated string to keep the 'version'
|
|
62
|
+
* variant shape a single optional string — hosts render the observed
|
|
63
|
+
* set uniformly.
|
|
64
|
+
*/
|
|
65
|
+
export function fromUpgradeRequired(err) {
|
|
66
|
+
const serverVersion = err.observedVersion === undefined
|
|
67
|
+
? undefined
|
|
68
|
+
: typeof err.observedVersion === 'string'
|
|
69
|
+
? err.observedVersion
|
|
70
|
+
: err.observedVersion.join(', ');
|
|
71
|
+
return {
|
|
72
|
+
kind: 'version',
|
|
73
|
+
...(serverVersion !== undefined ? { serverVersion } : {}),
|
|
74
|
+
clientSupports: err.acceptedVersions,
|
|
75
|
+
message: err.message,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Build a `ProtocolError` of kind 'bootstrap' — closed-or-extensibly-
|
|
80
|
+
* closed reason + operator-visible message.
|
|
81
|
+
*/
|
|
82
|
+
export function fromBootstrapFailure(reason, message) {
|
|
83
|
+
return { kind: 'bootstrap', reason, message };
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Fallback constructor — wraps any raw value we can't classify.
|
|
87
|
+
* Keeps the emitter union total.
|
|
88
|
+
*/
|
|
89
|
+
export function fromUnknown(raw) {
|
|
90
|
+
return { kind: 'unknown', raw };
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Build a `ProtocolError` of kind 'transport' — disconnection /
|
|
94
|
+
* timeout paths. `retryable` differentiates the reconnection-eligible
|
|
95
|
+
* `DISCONNECTED` from terminal `TIMEOUT` states; hosts pattern-match
|
|
96
|
+
* on the flag.
|
|
97
|
+
*/
|
|
98
|
+
export function fromTransportFailure(code, retryable, message) {
|
|
99
|
+
return {
|
|
100
|
+
kind: 'transport',
|
|
101
|
+
code,
|
|
102
|
+
retryable,
|
|
103
|
+
...(message !== undefined ? { message } : {}),
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Build a `ProtocolError` of kind 'auth' — session / token rejection
|
|
108
|
+
* pre-handshake.
|
|
109
|
+
*/
|
|
110
|
+
export function fromAuthFailure(code, message) {
|
|
111
|
+
return {
|
|
112
|
+
kind: 'auth',
|
|
113
|
+
code,
|
|
114
|
+
...(message !== undefined ? { message } : {}),
|
|
115
|
+
};
|
|
116
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provisional (A2UI preview) renderer for the iframe runtime.
|
|
3
|
+
*
|
|
4
|
+
* Port of `@ggui-ai/react::components/ProvisionalRenderer.tsx` with
|
|
5
|
+
* the React-hook consumer stripped. The A2UI reduce + adjacency-list
|
|
6
|
+
* render is preserved verbatim; the inputs + mount lifecycle differ:
|
|
7
|
+
*
|
|
8
|
+
* - Host-SDK version reads via `useChannelStream(PREVIEW_CHANNEL)`
|
|
9
|
+
* (a React hook subscribed to a live-channel bridge event).
|
|
10
|
+
* - Iframe-renderer version is driven by an explicit
|
|
11
|
+
* `pushEnvelope(env)` entry point invoked by `subscribe.ts` on
|
|
12
|
+
* every validated inbound `data` envelope whose channel is
|
|
13
|
+
* `_ggui:preview`. The caller (runtime.ts) forwards envelopes
|
|
14
|
+
* after the reserved-channel A2UI validator has accepted them.
|
|
15
|
+
*
|
|
16
|
+
* Visual language: `PreviewSurface` / `PreviewFragmentEnter` /
|
|
17
|
+
* `StreamingText` from `@ggui-ai/design/preview`; primitive mapping
|
|
18
|
+
* from `@ggui-ai/design/primitives`. Matches the host-SDK output
|
|
19
|
+
* 1:1 — operator-visible preview DOM is identical on both paths.
|
|
20
|
+
*
|
|
21
|
+
* Lifecycle:
|
|
22
|
+
*
|
|
23
|
+
* - `mountProvisional(container)` → `{pushEnvelope, suspend,
|
|
24
|
+
* resume, unmount}` handle. The container renders the default
|
|
25
|
+
* loading fallback until A2UI's `root` fragment arrives; then
|
|
26
|
+
* the adjacency tree paints.
|
|
27
|
+
* - `suspend()` hides the surface (used when the authoritative
|
|
28
|
+
* render takes over — the stack-item dispatcher in Commit 4
|
|
29
|
+
* toggles this on ReactComponentRenderer mount).
|
|
30
|
+
* - `resume()` re-shows. Envelopes keep accumulating in state
|
|
31
|
+
* while suspended, matching host-SDK behavior.
|
|
32
|
+
*/
|
|
33
|
+
import React, { type ReactNode } from 'react';
|
|
34
|
+
import type { StreamEnvelope } from '@ggui-ai/protocol';
|
|
35
|
+
export interface ProvisionalMount {
|
|
36
|
+
/**
|
|
37
|
+
* Feed a stream envelope. Ignores non-PREVIEW_CHANNEL envelopes
|
|
38
|
+
* silently so callers can forward their full inbound stream
|
|
39
|
+
* without filtering first. Caller MUST run reserved-channel
|
|
40
|
+
* validation before pushing — the provisional renderer treats the
|
|
41
|
+
* payload as trusted.
|
|
42
|
+
*/
|
|
43
|
+
pushEnvelope(envelope: StreamEnvelope): void;
|
|
44
|
+
/** Hide the surface (authoritative render takes over). */
|
|
45
|
+
suspend(): void;
|
|
46
|
+
/** Re-show the surface. */
|
|
47
|
+
resume(): void;
|
|
48
|
+
/** Tear down the React root + release retained state. */
|
|
49
|
+
unmount(): void;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Mount the provisional surface into `container`. Returns a handle
|
|
53
|
+
* callers use to push envelopes + suspend/resume + unmount.
|
|
54
|
+
*
|
|
55
|
+
* Synchronous-ish — the React root renders on next microtask, so
|
|
56
|
+
* the `controlRef` is populated by the time the caller's next
|
|
57
|
+
* microtask runs. Tests use `await Promise.resolve()` to sync.
|
|
58
|
+
*/
|
|
59
|
+
export declare function mountProvisional(container: HTMLElement, opts?: {
|
|
60
|
+
fallback?: ReactNode;
|
|
61
|
+
}): ProvisionalMount;
|
|
62
|
+
export { React };
|