@ggui-ai/iframe-runtime 0.22.0 → 0.24.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/dist/host-fonts.d.ts +7 -0
- package/dist/host-fonts.js +29 -5
- package/dist/iframe-runtime.js +69 -69
- package/dist/iframe-runtime.meta.json +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/meta-parse.d.ts +7 -0
- package/dist/meta-parse.js +13 -0
- package/dist/observability.d.ts +13 -1
- package/dist/protocol-error.d.ts +5 -2
- package/dist/react-renderer.js +5 -0
- package/dist/render-item.d.ts +5 -3
- package/dist/render-item.js +7 -2
- package/dist/runtime.d.ts +6 -0
- package/dist/runtime.js +27 -3
- package/dist/shims/wire.js +1 -1
- package/dist/types.d.ts +7 -4
- package/dist/wire-config.d.ts +8 -2
- package/dist/wire-config.js +15 -0
- package/package.json +7 -7
package/dist/index.d.ts
CHANGED
|
@@ -37,7 +37,7 @@ export { parseMetaFromGlobal, parseMetaFromToolResult, validateMeta, } from './m
|
|
|
37
37
|
export type { RendererBootFailureReason, RendererBootFailedMessage, } from './runtime.js';
|
|
38
38
|
export type { ProtocolError, ProtocolErrorEmitter, BootstrapFailureReason, } from './protocol-error.js';
|
|
39
39
|
export { defaultProtocolErrorEmitter, fromBootstrapFailure, fromClientContractViolation, fromTransportFailure, fromAuthFailure, fromUpgradeRequired, fromUnknown, } from './protocol-error.js';
|
|
40
|
-
export type { ObservabilityEvent, ObservabilityEmitter, ObservabilityMessage, SchemaVersionMismatchEvent, FontFaceBlockedEvent, AppThemeInvalidEvent, AppThemeMemberStrippedEvent, ActionSpecInvalidEvent, ActionSpecMemberStrippedEvent, ThemeReinjectFailedEvent, SubscribeFailedEvent, ChannelTransportPickedEvent, ChannelTransportFallbackEvent, ChannelTransportResubscribedEvent, ChannelPollDegradedEvent, ChannelPollRecoveredEvent, UiFeedbackEvent, RelayDeadTapEvent, RelayIncapabilityEvent, RelayLatchTrigger, UnknownObservabilityEvent, } from './observability.js';
|
|
40
|
+
export type { ObservabilityEvent, ObservabilityEmitter, ObservabilityMessage, SchemaVersionMismatchEvent, FontFaceBlockedEvent, AppThemeInvalidEvent, AppThemeMemberStrippedEvent, ActionSpecInvalidEvent, ActionSpecMemberStrippedEvent, SpentOneShotsInvalidEvent, ThemeReinjectFailedEvent, SubscribeFailedEvent, ChannelTransportPickedEvent, ChannelTransportFallbackEvent, ChannelTransportResubscribedEvent, ChannelPollDegradedEvent, ChannelPollRecoveredEvent, UiFeedbackEvent, RelayDeadTapEvent, RelayIncapabilityEvent, RelayLatchTrigger, ComponentEmptyEvent, OneShotUnenforceableEvent, UnknownObservabilityEvent, } from './observability.js';
|
|
41
41
|
export { isObservabilityMessage, isRelayDeadTapEvent, isRelayIncapabilityEvent, postObservabilityToParent, } from './observability.js';
|
|
42
42
|
export type { LifecycleEmitter } from './lifecycle.js';
|
|
43
43
|
export { postLifecycleToParent, makeLifecycleEvent } from './lifecycle.js';
|
package/dist/meta-parse.d.ts
CHANGED
|
@@ -49,6 +49,13 @@ export declare function reportInvalidActionSpec(issues: readonly string[]): void
|
|
|
49
49
|
* `parseMcpAppAiGguiRenderMeta` call in this package.
|
|
50
50
|
*/
|
|
51
51
|
export declare function reportStrippedActionSpecMembers(keys: readonly string[]): void;
|
|
52
|
+
/**
|
|
53
|
+
* The wire parser refused the slice's `spentOneShots` (ggui#1223): report it
|
|
54
|
+
* to the embedding host as `spent-one-shots-invalid` and mount without it.
|
|
55
|
+
* The runtime keeps its in-memory guard alone, so a consumed action would
|
|
56
|
+
* look live again after a reload — never silently.
|
|
57
|
+
*/
|
|
58
|
+
export declare function reportInvalidSpentOneShots(issues: readonly string[]): void;
|
|
52
59
|
/**
|
|
53
60
|
* Every degradation the wire parser's read door can report, bound to its
|
|
54
61
|
* observability event — the ONE options object every
|
package/dist/meta-parse.js
CHANGED
|
@@ -255,6 +255,9 @@ function projectMeta(meta, hasStaticContent) {
|
|
|
255
255
|
// Already validated at the wire parser's tolerant read door, so no
|
|
256
256
|
// re-validation here.
|
|
257
257
|
...(meta.actionSpec !== undefined ? { actionSpec: meta.actionSpec } : {}),
|
|
258
|
+
// The card's spent oneShot names (ggui#1223), carried through whole —
|
|
259
|
+
// validated at the wire parser's tolerant read door.
|
|
260
|
+
...(meta.spentOneShots !== undefined ? { spentOneShots: meta.spentOneShots } : {}),
|
|
258
261
|
...(gadgets !== undefined ? { gadgets } : {}),
|
|
259
262
|
...(publicEnv !== undefined ? { publicEnv } : {}),
|
|
260
263
|
...(streamWebSocketLocalTools !== undefined
|
|
@@ -368,6 +371,15 @@ export function reportInvalidActionSpec(issues) {
|
|
|
368
371
|
export function reportStrippedActionSpecMembers(keys) {
|
|
369
372
|
postObservabilityToParent({ kind: 'action-spec-member-stripped', keys: [...keys] });
|
|
370
373
|
}
|
|
374
|
+
/**
|
|
375
|
+
* The wire parser refused the slice's `spentOneShots` (ggui#1223): report it
|
|
376
|
+
* to the embedding host as `spent-one-shots-invalid` and mount without it.
|
|
377
|
+
* The runtime keeps its in-memory guard alone, so a consumed action would
|
|
378
|
+
* look live again after a reload — never silently.
|
|
379
|
+
*/
|
|
380
|
+
export function reportInvalidSpentOneShots(issues) {
|
|
381
|
+
postObservabilityToParent({ kind: 'spent-one-shots-invalid', issues: [...issues] });
|
|
382
|
+
}
|
|
371
383
|
/**
|
|
372
384
|
* Every degradation the wire parser's read door can report, bound to its
|
|
373
385
|
* observability event — the ONE options object every
|
|
@@ -380,6 +392,7 @@ export const READ_DOOR_REPORTERS = {
|
|
|
380
392
|
onStrippedThemeMembers: reportStrippedThemeMembers,
|
|
381
393
|
onInvalidActionSpec: reportInvalidActionSpec,
|
|
382
394
|
onStrippedActionSpecMembers: reportStrippedActionSpecMembers,
|
|
395
|
+
onInvalidSpentOneShots: reportInvalidSpentOneShots,
|
|
383
396
|
};
|
|
384
397
|
/**
|
|
385
398
|
* Parse the render slice from `globalThis.__GGUI_META__` — the
|
package/dist/observability.d.ts
CHANGED
|
@@ -33,7 +33,7 @@ import { MCP_APP_OBSERVE_TYPE } from '@ggui-ai/protocol/integrations/mcp-apps';
|
|
|
33
33
|
*
|
|
34
34
|
* @public
|
|
35
35
|
*/
|
|
36
|
-
export type ObservabilityEvent = SchemaVersionMismatchEvent | FontFaceBlockedEvent | AppThemeInvalidEvent | AppThemeMemberStrippedEvent | ActionSpecInvalidEvent | ActionSpecMemberStrippedEvent | OneShotUnenforceableEvent | ThemeReinjectFailedEvent | SubscribeFailedEvent | ChannelTransportPickedEvent | ChannelTransportFallbackEvent | ChannelTransportResubscribedEvent | ChannelPollDegradedEvent | ChannelPollRecoveredEvent | UiFeedbackEvent | RelayIncapabilityEvent | RelayDeadTapEvent | ComponentEmptyEvent | UnknownObservabilityEvent;
|
|
36
|
+
export type ObservabilityEvent = SchemaVersionMismatchEvent | FontFaceBlockedEvent | AppThemeInvalidEvent | AppThemeMemberStrippedEvent | ActionSpecInvalidEvent | ActionSpecMemberStrippedEvent | OneShotUnenforceableEvent | SpentOneShotsInvalidEvent | ThemeReinjectFailedEvent | SubscribeFailedEvent | ChannelTransportPickedEvent | ChannelTransportFallbackEvent | ChannelTransportResubscribedEvent | ChannelPollDegradedEvent | ChannelPollRecoveredEvent | UiFeedbackEvent | RelayIncapabilityEvent | RelayDeadTapEvent | ComponentEmptyEvent | UnknownObservabilityEvent;
|
|
37
37
|
/**
|
|
38
38
|
* Fired when the protocol-version handshake rejects the connection.
|
|
39
39
|
* Parallel to `UpgradeRequiredError` — the host can choose to render
|
|
@@ -402,6 +402,18 @@ export interface OneShotUnenforceableEvent {
|
|
|
402
402
|
readonly renderId: string;
|
|
403
403
|
readonly actionName: string;
|
|
404
404
|
}
|
|
405
|
+
/**
|
|
406
|
+
* The render slice carried a `spentOneShots` the wire schema refused
|
|
407
|
+
* (ggui#1223): the parser dropped it, and the card mounted with only its
|
|
408
|
+
* in-memory one-shot guard — a consumed action reads as live again after a
|
|
409
|
+
* reload. `issues` are the schema's own messages.
|
|
410
|
+
*
|
|
411
|
+
* @public
|
|
412
|
+
*/
|
|
413
|
+
export interface SpentOneShotsInvalidEvent {
|
|
414
|
+
readonly kind: 'spent-one-shots-invalid';
|
|
415
|
+
readonly issues: readonly string[];
|
|
416
|
+
}
|
|
405
417
|
/**
|
|
406
418
|
* The live re-injection on a host theme flip (ggui#987 §4) failed: the
|
|
407
419
|
* renderer's update rejected, so the card kept its previous overlay /
|
package/dist/protocol-error.d.ts
CHANGED
|
@@ -38,8 +38,11 @@ import { ClientContractViolationError } from '@ggui-ai/wire';
|
|
|
38
38
|
* `McpAppAiGguiMetaParseFailureReason` (`MISSING_TOOL_OUTPUT` /
|
|
39
39
|
* `MISSING_META_GGUI_BOOTSTRAP` / `MALFORMED_BOOTSTRAP` /
|
|
40
40
|
* `EXPIRED_BOOTSTRAP`). `MISSING_META_GGUI_BOOTSTRAP` and
|
|
41
|
-
* `BOOTSTRAP_META_MISSING`
|
|
42
|
-
*
|
|
41
|
+
* `BOOTSTRAP_META_MISSING` name one condition. The runtime and the
|
|
42
|
+
* reference shell emit `MISSING_META_GGUI_BOOTSTRAP` on
|
|
43
|
+
* `ggui:bootstrap-failed`; `BOOTSTRAP_META_MISSING` stays a member
|
|
44
|
+
* so a host classifies either spelling as that condition
|
|
45
|
+
* (SPEC §5.5.2).
|
|
43
46
|
*
|
|
44
47
|
* 2. **Post-parse orchestration failures** — `UI_INITIALIZE_FAILED`
|
|
45
48
|
* / `WS_HANDSHAKE_FAILED`. Matches `RendererBootFailureReason`.
|
package/dist/react-renderer.js
CHANGED
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
import React, { Component, createElement, Fragment, } from 'react';
|
|
33
33
|
import { createRoot } from 'react-dom/client';
|
|
34
34
|
import { postObservabilityToParent } from './observability.js';
|
|
35
|
+
import { trackThemeFontFaces } from './host-fonts.js';
|
|
35
36
|
import { stripMarkers, rewriteImports, composeThemeCss, } from '@ggui-ai/design/rendering';
|
|
36
37
|
import { hoistImports, loadModule, loadModuleInline, probeUrlModuleLoad, } from '@ggui-ai/design/module-loader';
|
|
37
38
|
/**
|
|
@@ -367,6 +368,10 @@ export async function mountReactRoot(container, opts) {
|
|
|
367
368
|
if (styleEl.textContent !== rootCss) {
|
|
368
369
|
styleEl.textContent = rootCss;
|
|
369
370
|
}
|
|
371
|
+
// ggui#1147: the chrome CSS carries the stored theme's @font-face rules,
|
|
372
|
+
// mid-session included, while `font-src` was fixed at mount. Track them so
|
|
373
|
+
// a blocked face is reported as `font-face-blocked`, not lost silently.
|
|
374
|
+
trackThemeFontFaces(rootCss);
|
|
370
375
|
}
|
|
371
376
|
const componentElement = currentComponent === null
|
|
372
377
|
? null
|
package/dist/render-item.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
2
|
import type { AppTheme, GguiSession } from '@ggui-ai/protocol/wire';
|
|
3
3
|
import type { GguiSessionSeedInput } from './types.js';
|
|
4
|
-
import { type
|
|
4
|
+
import { type BuiltWireConfig } from '@ggui-ai/wire';
|
|
5
5
|
import type { StreamBus } from './wire-config.js';
|
|
6
6
|
export interface RenderItemOptions {
|
|
7
7
|
/** The render to mount. */
|
|
@@ -10,8 +10,10 @@ export interface RenderItemOptions {
|
|
|
10
10
|
* `buildRootWireConfig(...)` (see `wire-config.ts`). `null` ⇒ the
|
|
11
11
|
* component mounts without a wire provider (standalone — matches
|
|
12
12
|
* today's DynamicComponent fallback when no GguiRender parent is
|
|
13
|
-
* present).
|
|
14
|
-
|
|
13
|
+
* present). The config carries the card's `actionSpent` source
|
|
14
|
+
* (ggui#1223), and the component mounts inside `ActionSpentContext` too,
|
|
15
|
+
* so `useActionSpent` reads the one-shot guard's own spent set. */
|
|
16
|
+
readonly scopedWireConfig: BuiltWireConfig | null;
|
|
15
17
|
/** Shared stream bus — provisional renderer subscribes to
|
|
16
18
|
* `_ggui:preview` for this render. */
|
|
17
19
|
readonly streamBus: StreamBus;
|
package/dist/render-item.js
CHANGED
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
*/
|
|
40
40
|
import { createElement } from 'react';
|
|
41
41
|
import { GguiWireProvider } from '@ggui-ai/wire';
|
|
42
|
+
import { ActionSpentContext } from '@ggui-ai/wire/internal';
|
|
42
43
|
import { mountReactRoot } from './react-renderer.js';
|
|
43
44
|
import { mountProvisional, } from './provisional-renderer.js';
|
|
44
45
|
import { mountMcpAppIframe, } from './mcp-app-iframe-host.js';
|
|
@@ -208,9 +209,13 @@ export async function mountRender(container, opts) {
|
|
|
208
209
|
* mount. When absent, the wire provider is the only wrapper.
|
|
209
210
|
*/
|
|
210
211
|
function wrapInScopedProvider(mountedComponent) {
|
|
211
|
-
const
|
|
212
|
+
const config = currentOpts.scopedWireConfig;
|
|
213
|
+
const wireWrapped = config === null
|
|
212
214
|
? mountedComponent
|
|
213
|
-
: createElement(GguiWireProvider, {
|
|
215
|
+
: createElement(GguiWireProvider, {
|
|
216
|
+
config,
|
|
217
|
+
children: createElement(ActionSpentContext.Provider, { value: config.actionSpent, children: mountedComponent }),
|
|
218
|
+
});
|
|
214
219
|
return currentOpts.wrapOuter !== undefined
|
|
215
220
|
? currentOpts.wrapOuter(wireWrapped)
|
|
216
221
|
: wireWrapped;
|
package/dist/runtime.d.ts
CHANGED
|
@@ -529,6 +529,12 @@ export declare function readSelfContainedMeta(): McpAppAiGguiRenderMeta | null;
|
|
|
529
529
|
* (ggui#1178): a mount with no live session frame paints from this seed, and
|
|
530
530
|
* the one-shot guard reads the current render's spec, so a seed without it
|
|
531
531
|
* could not enforce `oneShot`. A system seed never carries one.
|
|
532
|
+
*
|
|
533
|
+
* It also carries the card's `epoch` and, when the slice lists them, the
|
|
534
|
+
* `oneShot` names this card already spent, as the render's record
|
|
535
|
+
* `{ epoch, actions }` (ggui#1223). `deriveRenderMeta` projected those names
|
|
536
|
+
* for this card only, so the record's epoch is the card's own and the guard
|
|
537
|
+
* stops the first gesture on a spent action after a reload.
|
|
532
538
|
*/
|
|
533
539
|
export declare function buildGguiSessionSeedInput(meta: McpAppAiGguiRenderMeta): Promise<GguiSessionSeedInput | null>;
|
|
534
540
|
/**
|
package/dist/runtime.js
CHANGED
|
@@ -1180,10 +1180,22 @@ function parseSeedProps(propsJson) {
|
|
|
1180
1180
|
* (ggui#1178): a mount with no live session frame paints from this seed, and
|
|
1181
1181
|
* the one-shot guard reads the current render's spec, so a seed without it
|
|
1182
1182
|
* could not enforce `oneShot`. A system seed never carries one.
|
|
1183
|
+
*
|
|
1184
|
+
* It also carries the card's `epoch` and, when the slice lists them, the
|
|
1185
|
+
* `oneShot` names this card already spent, as the render's record
|
|
1186
|
+
* `{ epoch, actions }` (ggui#1223). `deriveRenderMeta` projected those names
|
|
1187
|
+
* for this card only, so the record's epoch is the card's own and the guard
|
|
1188
|
+
* stops the first gesture on a spent action after a reload.
|
|
1183
1189
|
*/
|
|
1184
1190
|
export async function buildGguiSessionSeedInput(meta) {
|
|
1185
1191
|
const props = parseSeedProps(meta.propsJson);
|
|
1186
|
-
const
|
|
1192
|
+
const componentFields = {
|
|
1193
|
+
...(meta.actionSpec !== undefined ? { actionSpec: meta.actionSpec } : {}),
|
|
1194
|
+
...(typeof meta.epoch === 'number' ? { epoch: meta.epoch } : {}),
|
|
1195
|
+
...(meta.spentOneShots !== undefined
|
|
1196
|
+
? { spentOneShots: { epoch: meta.epoch ?? 0, actions: meta.spentOneShots } }
|
|
1197
|
+
: {}),
|
|
1198
|
+
};
|
|
1187
1199
|
// System-card mode — `kind` keyed against the built-in registry.
|
|
1188
1200
|
if (meta.kind !== undefined) {
|
|
1189
1201
|
return {
|
|
@@ -1201,7 +1213,7 @@ export async function buildGguiSessionSeedInput(meta) {
|
|
|
1201
1213
|
appId: meta.appId,
|
|
1202
1214
|
componentCode: decodeCodeB64(meta.codeB64),
|
|
1203
1215
|
...(props !== undefined ? { props } : {}),
|
|
1204
|
-
...
|
|
1216
|
+
...componentFields,
|
|
1205
1217
|
};
|
|
1206
1218
|
}
|
|
1207
1219
|
// Compiled-component mode — fetch the content-addressable bytes.
|
|
@@ -1217,7 +1229,7 @@ export async function buildGguiSessionSeedInput(meta) {
|
|
|
1217
1229
|
appId: meta.appId,
|
|
1218
1230
|
componentCode,
|
|
1219
1231
|
...(props !== undefined ? { props } : {}),
|
|
1220
|
-
...
|
|
1232
|
+
...componentFields,
|
|
1221
1233
|
};
|
|
1222
1234
|
}
|
|
1223
1235
|
/**
|
|
@@ -3782,6 +3794,15 @@ async function bootProduction(opts) {
|
|
|
3782
3794
|
// through `currentRender`-returning thunks so they always see the
|
|
3783
3795
|
// latest snapshot without holding stale refs.
|
|
3784
3796
|
let currentRender = null;
|
|
3797
|
+
// ggui#1223 — who to tell when `currentRender` is replaced, so the card's
|
|
3798
|
+
// spent state (read through `getCurrentGguiSession`) is re-read at once.
|
|
3799
|
+
const renderListeners = new Set();
|
|
3800
|
+
const onRenderChange = (listener) => {
|
|
3801
|
+
renderListeners.add(listener);
|
|
3802
|
+
return () => {
|
|
3803
|
+
renderListeners.delete(listener);
|
|
3804
|
+
};
|
|
3805
|
+
};
|
|
3785
3806
|
let renderHandle = null;
|
|
3786
3807
|
const dispatchToolName = resolveDispatchToolName();
|
|
3787
3808
|
// Native-idiom interceptors — the replacement for the retired
|
|
@@ -3829,6 +3850,7 @@ async function bootProduction(opts) {
|
|
|
3829
3850
|
sessionId: meta.sessionId,
|
|
3830
3851
|
appId: meta.appId,
|
|
3831
3852
|
getCurrentGguiSession: () => currentRender,
|
|
3853
|
+
renderChanges: onRenderChange,
|
|
3832
3854
|
manager,
|
|
3833
3855
|
streamBus,
|
|
3834
3856
|
onDispatchEnvelope: (envelope) => {
|
|
@@ -3986,6 +4008,8 @@ async function bootProduction(opts) {
|
|
|
3986
4008
|
};
|
|
3987
4009
|
const applyRender = async (render) => {
|
|
3988
4010
|
currentRender = render;
|
|
4011
|
+
for (const listener of [...renderListeners])
|
|
4012
|
+
listener();
|
|
3989
4013
|
if (renderHandle === null) {
|
|
3990
4014
|
renderHandle = await mountRender(renderInto, buildOpts(render));
|
|
3991
4015
|
return;
|
package/dist/shims/wire.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const w = globalThis.__ggui__.wire; export const useAction = w.useAction; export const useStream = w.useStream; export const useAuth = w.useAuth; export const useApp = w.useApp; export const useRender = w.useRender; export const useGguiContext = w.useGguiContext; export const useContract = w.useContract; export const useWireContext = w.useWireContext; export const GguiWireProvider = w.GguiWireProvider; export default w;
|
|
1
|
+
const w = globalThis.__ggui__.wire; export const useAction = w.useAction; export const useStream = w.useStream; export const useAuth = w.useAuth; export const useApp = w.useApp; export const useRender = w.useRender; export const useGguiContext = w.useGguiContext; export const useContract = w.useContract; export const useWireContext = w.useWireContext; export const useActionSpent = w.useActionSpent; export const GguiWireProvider = w.GguiWireProvider; export default w;
|
package/dist/types.d.ts
CHANGED
|
@@ -40,7 +40,9 @@ type GguiSessionLedgerFields = 'eventSequence' | 'createdAt' | 'lastActivityAt'
|
|
|
40
40
|
* (`propsSpec` / `streamSpec` / `actionSpec`), so the channel handlers that
|
|
41
41
|
* read those after the `type !== 'mcpApps' && type !== 'system'` narrowing
|
|
42
42
|
* stay type-clean. On a seed, `propsSpec` and `streamSpec` are `undefined`;
|
|
43
|
-
* `actionSpec` is the slice's own when the slice carried one (ggui#1178)
|
|
43
|
+
* `actionSpec` is the slice's own when the slice carried one (ggui#1178), and
|
|
44
|
+
* so are `epoch` and the spent-`oneShot` record built from the slice's
|
|
45
|
+
* `spentOneShots` (ggui#1223).
|
|
44
46
|
*/
|
|
45
47
|
export type GguiSessionSeedInput = Omit<ComponentGguiSession, GguiSessionLedgerFields> | Omit<SystemGguiSession, GguiSessionLedgerFields>;
|
|
46
48
|
/**
|
|
@@ -59,9 +61,10 @@ export type GguiSessionSeedInput = Omit<ComponentGguiSession, GguiSessionLedgerF
|
|
|
59
61
|
* deferred.)
|
|
60
62
|
* - `MISSING_META_GGUI_BOOTSTRAP` — `params` is an object but
|
|
61
63
|
* `params._meta` is absent or carries no `ai.ggui/render` slice.
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
64
|
+
* This is the spelling emitted on `ggui:bootstrap-failed`;
|
|
65
|
+
* `BOOTSTRAP_META_MISSING` is a synonym a host classifies alike
|
|
66
|
+
* (SPEC §5.5.2). (Name retained pre-R4 for the observability +
|
|
67
|
+
* host-postMessage protocol; cosmetic rename is deferred.)
|
|
65
68
|
* - `MALFORMED_BOOTSTRAP` — slice is present but fails business
|
|
66
69
|
* rules (no live mode and no static content, mode discriminators
|
|
67
70
|
* mutually exclusive, structural rejection by the combiner).
|
package/dist/wire-config.d.ts
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
*/
|
|
19
19
|
import type { ActionEnvelope, GguiSession } from '@ggui-ai/protocol/wire';
|
|
20
20
|
import type { GguiSessionSeedInput } from './types.js';
|
|
21
|
-
import { ClientContractViolationError, StreamBus, type
|
|
21
|
+
import { ClientContractViolationError, StreamBus, type BuiltWireConfig } from '@ggui-ai/wire';
|
|
22
22
|
import type { WebSocketMessage } from '@ggui-ai/protocol/transport/websocket';
|
|
23
23
|
/**
|
|
24
24
|
* Outbound send surface — the minimal shape wire-config calls on the
|
|
@@ -48,6 +48,12 @@ export interface BuildRootWireConfigOptions {
|
|
|
48
48
|
* WireConfig.
|
|
49
49
|
*/
|
|
50
50
|
readonly getCurrentGguiSession: () => GguiSession | GguiSessionSeedInput | null;
|
|
51
|
+
/**
|
|
52
|
+
* The runtime's notice that the current render was replaced (a props
|
|
53
|
+
* update, a later live frame), so the card's spent state is re-read at
|
|
54
|
+
* once (ggui#1223). Passed through as wire's `spentInputsChanged`.
|
|
55
|
+
*/
|
|
56
|
+
readonly renderChanges?: (listener: () => void) => () => void;
|
|
51
57
|
/** Handle to the renderer's WS manager; used for outbound `action` frames. */
|
|
52
58
|
readonly manager: RendererSendSurface;
|
|
53
59
|
/** Shared bus for inbound stream deliveries. */
|
|
@@ -124,4 +130,4 @@ export interface BuildRootWireConfigOptions {
|
|
|
124
130
|
* `RootWireConfigBundle` / `scopeWireConfig` / `buildScopedConfig`
|
|
125
131
|
* indirection collapsed to a single `WireConfig`.
|
|
126
132
|
*/
|
|
127
|
-
export declare function buildRootWireConfig(opts: BuildRootWireConfigOptions):
|
|
133
|
+
export declare function buildRootWireConfig(opts: BuildRootWireConfigOptions): BuiltWireConfig;
|
package/dist/wire-config.js
CHANGED
|
@@ -87,6 +87,21 @@ export function buildRootWireConfig(opts) {
|
|
|
87
87
|
: undefined;
|
|
88
88
|
},
|
|
89
89
|
onActionSpecAbsent: nameUnenforceableOnce,
|
|
90
|
+
...(opts.renderChanges !== undefined ? { spentInputsChanged: opts.renderChanges } : {}),
|
|
91
|
+
// ggui#1223 — the card's persisted spent `oneShot` names. A re-served card
|
|
92
|
+
// boots a new iframe, so the guard's in-memory set starts empty; the
|
|
93
|
+
// render's record says what this card already spent. It counts only when
|
|
94
|
+
// written on THIS card (its epoch is the render's own; absent ⇒ 0), the
|
|
95
|
+
// same gate `deriveRenderMeta` applies, since a `ggui_update` mints a fresh
|
|
96
|
+
// card whose record would otherwise carry over.
|
|
97
|
+
getSpentOneShots: () => {
|
|
98
|
+
const currentRender = opts.getCurrentGguiSession();
|
|
99
|
+
if (currentRender === null || currentRender.type === 'mcpApps' || currentRender.type === 'system') {
|
|
100
|
+
return undefined;
|
|
101
|
+
}
|
|
102
|
+
const record = currentRender.spentOneShots;
|
|
103
|
+
return record !== undefined && record.epoch === (currentRender.epoch ?? 0) ? record.actions : undefined;
|
|
104
|
+
},
|
|
90
105
|
// The iframe's precompiled-validator variant — the dispatch never
|
|
91
106
|
// trips the iframe's no-`unsafe-eval` CSP.
|
|
92
107
|
validateEnvelope: validateOutboundActionEnvelope,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ggui-ai/iframe-runtime",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.24.0",
|
|
4
4
|
"description": "The iframe-local ggui runtime: a self-contained ESM bundle that boots inside an MCP Apps host iframe, runs the protocol-version handshake, opens the live-channel WebSocket, and mounts the rendered UI. Bundles React, ReactDOM, and the ggui design system so generated component code has a single seam to read from.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ggui",
|
|
@@ -41,12 +41,12 @@
|
|
|
41
41
|
"react": "^19.0.0",
|
|
42
42
|
"react-dom": "^19.0.0",
|
|
43
43
|
"zod": "^4.3.6",
|
|
44
|
-
"@ggui-ai/design": "0.
|
|
45
|
-
"@ggui-ai/
|
|
46
|
-
"@ggui-ai/
|
|
47
|
-
"@ggui-ai/
|
|
48
|
-
"@ggui-ai/protocol": "0.
|
|
49
|
-
"@ggui-ai/wire": "0.
|
|
44
|
+
"@ggui-ai/design": "0.24.0",
|
|
45
|
+
"@ggui-ai/gadgets": "0.24.0",
|
|
46
|
+
"@ggui-ai/live-channel": "0.24.0",
|
|
47
|
+
"@ggui-ai/preview-a2ui": "0.24.0",
|
|
48
|
+
"@ggui-ai/protocol": "0.24.0",
|
|
49
|
+
"@ggui-ai/wire": "0.24.0"
|
|
50
50
|
},
|
|
51
51
|
"peerDependencies": {
|
|
52
52
|
"@modelcontextprotocol/sdk": "^1.27.0"
|