@ggui-ai/iframe-runtime 0.11.0 → 0.12.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-capabilities.d.ts +6 -4
- package/dist/iframe-runtime.js +65 -55
- package/dist/iframe-runtime.meta.json +1 -1
- package/dist/mcp-app-iframe-host.js +7 -2
- package/dist/react-renderer.d.ts +22 -0
- package/dist/react-renderer.js +20 -4
- package/dist/render-item.d.ts +9 -0
- package/dist/runtime.js +58 -21
- package/dist/ui-feedback-chrome.d.ts +16 -0
- package/dist/ui-feedback-chrome.js +20 -0
- package/dist/wire-config.d.ts +7 -3
- package/package.json +7 -7
|
@@ -77,8 +77,13 @@ export function mountMcpAppIframe(container, opts) {
|
|
|
77
77
|
iframe.style.maxWidth = dims.maxWidth !== undefined ? `${dims.maxWidth}px` : '100%';
|
|
78
78
|
if (dims.maxHeight !== undefined)
|
|
79
79
|
iframe.style.maxHeight = `${dims.maxHeight}px`;
|
|
80
|
-
|
|
81
|
-
|
|
80
|
+
// Round-6 doctrine (ggui#589 @6e15724a1, kit C1 grade): the helper
|
|
81
|
+
// paints CONTAINMENT ONLY — silhouette (border/radius) belongs to
|
|
82
|
+
// the embedding host's own chrome, tokens to the theme. The former
|
|
83
|
+
// 1px #e5e5e5 / radius-8 here was the same ungoverned-chrome class
|
|
84
|
+
// the RN helper shipped, surfaced by the host-helper catalog's
|
|
85
|
+
// first-party run (ggui#600 OPEN FINDING, closed here).
|
|
86
|
+
iframe.style.border = 'none';
|
|
82
87
|
iframe.style.display = 'block';
|
|
83
88
|
container.appendChild(iframe);
|
|
84
89
|
// Cache contentWindow — on detach, `iframe.contentWindow` is null
|
package/dist/react-renderer.d.ts
CHANGED
|
@@ -81,6 +81,28 @@ export interface ReactRootMountOptions {
|
|
|
81
81
|
readonly appTheme?: {
|
|
82
82
|
readonly mode: 'light' | 'dark';
|
|
83
83
|
readonly cssVariables: Record<string, string>;
|
|
84
|
+
/**
|
|
85
|
+
* The REGISTERED base ladder, delivered over the wire (ggui#598-C
|
|
86
|
+
* runtime theme registration — see protocol's `appThemeSchema`).
|
|
87
|
+
* BOTH modes' resolved variable sets ride the envelope; when
|
|
88
|
+
* present, the mode-selected set REPLACES the compiled ladder
|
|
89
|
+
* block (`getScopedThemeCss`/`getScopedCssTokens`) at the base
|
|
90
|
+
* position of the #573 precedence above — delivery changes WHERE
|
|
91
|
+
* the ladder's bytes come from, never WHICH layer wins. Mode
|
|
92
|
+
* selection reuses the mount's already-resolved `themeMode` (one
|
|
93
|
+
* projection — no second mode resolution here), and a mode switch
|
|
94
|
+
* re-paints from the retained other set with no network activity.
|
|
95
|
+
* Values are injection-safe by the wire schema — never
|
|
96
|
+
* re-validated here; serialization is key-sorted for byte-stable
|
|
97
|
+
* output. `documentHash` is the registration's identity (joins a
|
|
98
|
+
* painted ladder to its registration record); the renderer
|
|
99
|
+
* carries it but exposes no observability surface for it today.
|
|
100
|
+
*/
|
|
101
|
+
readonly base?: {
|
|
102
|
+
readonly documentHash: string;
|
|
103
|
+
readonly light: Readonly<Record<string, string>>;
|
|
104
|
+
readonly dark: Readonly<Record<string, string>>;
|
|
105
|
+
};
|
|
84
106
|
};
|
|
85
107
|
/**
|
|
86
108
|
* Host-announced palette, already translated onto `--ggui-*` tokens
|
package/dist/react-renderer.js
CHANGED
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
*/
|
|
32
32
|
import React, { Component, createElement, Fragment, } from 'react';
|
|
33
33
|
import { createRoot } from 'react-dom/client';
|
|
34
|
-
import { stripMarkers, rewriteImports, getScopedThemeCss, getScopedCssTokens, getThemeCss, getCssTokens, } from '@ggui-ai/design/rendering';
|
|
34
|
+
import { stripMarkers, rewriteImports, getScopedThemeCss, getScopedCssTokens, assembleDeliveredThemeCss, getThemeCss, getCssTokens, } from '@ggui-ai/design/rendering';
|
|
35
35
|
import { hoistImports, loadModule, loadModuleInline, probeUrlModuleLoad, } from '@ggui-ai/design/module-loader';
|
|
36
36
|
/**
|
|
37
37
|
* Document-lifetime verdict: URL-scheme module loading (`blob:` main
|
|
@@ -314,9 +314,25 @@ export async function mountReactRoot(container, opts) {
|
|
|
314
314
|
}
|
|
315
315
|
}
|
|
316
316
|
function renderTree(opts) {
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
317
|
+
// Delivered base ladder (ggui#598-C): when the slice theme carries
|
|
318
|
+
// `base`, the mode-selected set REPLACES the compiled ladder block
|
|
319
|
+
// at the base position — same precedence slot, different byte
|
|
320
|
+
// source. Mode selection reuses the already-resolved `themeMode`
|
|
321
|
+
// (one projection; absent means light — the same default
|
|
322
|
+
// `getScopedThemeCss` applies). Both sets stay retained on the
|
|
323
|
+
// options, so a mode-switch re-render picks the other ladder from
|
|
324
|
+
// memory — never the network.
|
|
325
|
+
const deliveredBase = opts.appTheme?.base;
|
|
326
|
+
let themeCss = deliveredBase !== undefined
|
|
327
|
+
? // Design-package assembler (ggui#598-C, injection-review flag 1):
|
|
328
|
+
// the delivered ladder gets the SAME scaffolding the compiled
|
|
329
|
+
// ladder gets — base inherits, derived gradient/effect tokens
|
|
330
|
+
// (color-mix fallback split), box-sizing, font-inherit — from
|
|
331
|
+
// ONE shared builder, so the two paths cannot drift.
|
|
332
|
+
assembleDeliveredThemeCss(scopeClass, opts.themeMode === 'dark' ? deliveredBase.dark : deliveredBase.light)
|
|
333
|
+
: opts.themeId
|
|
334
|
+
? getScopedThemeCss(opts.themeId, scopeClass, opts.themeMode)
|
|
335
|
+
: getScopedCssTokens(scopeClass, opts.themeMode);
|
|
320
336
|
if (opts.hostPalette) {
|
|
321
337
|
// Host palette = the fallback layer (ggui#572, #573 ruling):
|
|
322
338
|
// after the base scoped block so it can repaint at all (the base
|
package/dist/render-item.d.ts
CHANGED
|
@@ -51,10 +51,19 @@ export interface RenderItemOptions {
|
|
|
51
51
|
* so the renderer injects the `--ggui-*` overrides + `color-scheme` at
|
|
52
52
|
* `:root`. Sourced from the bootstrap's `_meta["ai.ggui/render"].theme`.
|
|
53
53
|
* A structural subset of protocol's `AppTheme` (`name` is display-only).
|
|
54
|
+
* `base` is the delivered registered ladder (ggui#598-C) — forwarded
|
|
55
|
+
* verbatim; the renderer injects the mode-selected set in place of
|
|
56
|
+
* the compiled ladder block (see
|
|
57
|
+
* {@link ReactRootMountOptions.appTheme}).
|
|
54
58
|
*/
|
|
55
59
|
readonly appTheme?: {
|
|
56
60
|
readonly mode: 'light' | 'dark';
|
|
57
61
|
readonly cssVariables: Record<string, string>;
|
|
62
|
+
readonly base?: {
|
|
63
|
+
readonly documentHash: string;
|
|
64
|
+
readonly light: Readonly<Record<string, string>>;
|
|
65
|
+
readonly dark: Readonly<Record<string, string>>;
|
|
66
|
+
};
|
|
58
67
|
};
|
|
59
68
|
/**
|
|
60
69
|
* Host-announced palette, pre-mapped onto `--ggui-*` tokens by the
|
package/dist/runtime.js
CHANGED
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
// schema-defining dependency initializes (see zod-jitless.ts).
|
|
29
29
|
import './zod-jitless.js';
|
|
30
30
|
import { MCP_APP_BOOTSTRAP_FAILED_TYPE, MCP_APP_RENDERER_READY_TYPE, parseMcpAppAiGguiRenderMeta, readGguiShellEnvelope, } from '@ggui-ai/protocol/integrations/mcp-apps';
|
|
31
|
+
import { effectiveThemeId, effectiveThemeMode, } from '@ggui-ai/protocol/integrations/theme-binding';
|
|
31
32
|
import { extractLocatorFromToolResult, parseMetaFromGlobal, parseMetaFromToolResult, validateMeta, } from './meta-parse.js';
|
|
32
33
|
import { projectHostContext } from '@ggui-ai/protocol';
|
|
33
34
|
import { App, PostMessageTransport } from '@modelcontextprotocol/ext-apps';
|
|
@@ -48,7 +49,7 @@ import { loadCompiledValidatorsFromUrl } from './compiled-validators.js';
|
|
|
48
49
|
import { mountRender, } from './render-item.js';
|
|
49
50
|
import { fromBootstrapFailure, } from './protocol-error.js';
|
|
50
51
|
import { postObservabilityToParent, } from './observability.js';
|
|
51
|
-
import { mountUiFeedbackChrome } from './ui-feedback-chrome.js';
|
|
52
|
+
import { ACTION_TOAST_Z_INDEX, mountUiFeedbackChrome } from './ui-feedback-chrome.js';
|
|
52
53
|
import { hostCanReceiveMessages, hostCanRelayToolCalls, hostCapabilitiesCaptured, setHostCapabilities, } from './host-capabilities.js';
|
|
53
54
|
import { makeLifecycleEvent, postLifecycleToParent, } from './lifecycle.js';
|
|
54
55
|
import { contextSlotLastValues, createContextStateHost, installContextRegistry, reemitLastContextValues, } from './context-observer.js';
|
|
@@ -213,7 +214,16 @@ export function hostAnnouncedThemeMode() {
|
|
|
213
214
|
* `buildOpts` inside `bootSequence`.
|
|
214
215
|
*/
|
|
215
216
|
export function resolveMountThemeMode(meta) {
|
|
216
|
-
|
|
217
|
+
// The CLIENT projection of the protocol's normative theme-binding
|
|
218
|
+
// total order (@ggui-ai/protocol/integrations/theme-binding,
|
|
219
|
+
// ggui#598 leg 4) — the server stamps via the sibling projection and
|
|
220
|
+
// the protocol's composition-law test pins that the two compose
|
|
221
|
+
// without rank drift.
|
|
222
|
+
return effectiveThemeMode({
|
|
223
|
+
stamped: meta.themeMode,
|
|
224
|
+
sessionSidecar: meta.theme?.mode,
|
|
225
|
+
hostAnnounced: hostAnnouncedThemeMode(),
|
|
226
|
+
});
|
|
217
227
|
}
|
|
218
228
|
/**
|
|
219
229
|
* Resolve the mount's base-theme id from the slice (ggui#589 ask 3):
|
|
@@ -235,7 +245,12 @@ export function resolveMountThemeMode(meta) {
|
|
|
235
245
|
* `buildOpts` inside `bootSequence`.
|
|
236
246
|
*/
|
|
237
247
|
export function resolveMountThemeId(meta) {
|
|
238
|
-
|
|
248
|
+
// Client projection of the normative theme-binding order — see
|
|
249
|
+
// resolveMountThemeMode above.
|
|
250
|
+
return effectiveThemeId({
|
|
251
|
+
stamped: meta.themeId,
|
|
252
|
+
sidecarName: meta.theme?.name,
|
|
253
|
+
});
|
|
239
254
|
}
|
|
240
255
|
/**
|
|
241
256
|
* The host's announced palette, read from the connected App's
|
|
@@ -1630,9 +1645,11 @@ export function emitAudit(args) {
|
|
|
1630
1645
|
* Returns `'success'` when the handler said `ok:true`. Returns
|
|
1631
1646
|
* `'fallback'` for any other outcome — pipe missing
|
|
1632
1647
|
* (`PIPE_NOT_FOUND`), envelope rejected (`INVALID_ACTION_KIND`),
|
|
1633
|
-
* relay error, no host relay wired, or any unexpected shape.
|
|
1634
|
-
*
|
|
1635
|
-
*
|
|
1648
|
+
* relay error, no host relay wired, or any unexpected shape. On
|
|
1649
|
+
* `'fallback'` the gesture was NOT enqueued and is dropped with local
|
|
1650
|
+
* feedback only (toast / #440 latch) — no `ui/message` fires (the
|
|
1651
|
+
* doorbell is success-path-only: there is nothing to point it at), and
|
|
1652
|
+
* no alternate transport is attempted today (ggui#599's open leg).
|
|
1636
1653
|
*/
|
|
1637
1654
|
/**
|
|
1638
1655
|
* Unwrap the payload record of a relayed submit-action tool result.
|
|
@@ -1698,6 +1715,16 @@ function isRelayShapedFailure(resp) {
|
|
|
1698
1715
|
* consumer" — the doorbell rings. Shares {@link submitActionPayload}
|
|
1699
1716
|
* with {@link classifySubmitActionResponse} so both reads agree on
|
|
1700
1717
|
* which envelope tier carries the payload.
|
|
1718
|
+
*
|
|
1719
|
+
* RELAY CONTRACT (ggui#603): this read only works when the host's
|
|
1720
|
+
* `tools/call` relay threads the server's tool result VERBATIM — the
|
|
1721
|
+
* `consumerPresent` marker rides `structuredContent` on the real
|
|
1722
|
+
* result. A relay that wraps or synthesizes the response silently
|
|
1723
|
+
* strips the marker, and every healthy gesture then misclassifies as
|
|
1724
|
+
* "agent not listening" (a persistent `action_required` toast per
|
|
1725
|
+
* gesture). Verbatim threading is the same obligation that keeps
|
|
1726
|
+
* `_meta` alive on `resources/read` relays; a conformance vector for
|
|
1727
|
+
* it is tracked on ggui#603.
|
|
1701
1728
|
*/
|
|
1702
1729
|
function extractConsumerPresent(resp) {
|
|
1703
1730
|
const inner = submitActionPayload(resp);
|
|
@@ -1908,7 +1935,7 @@ function showActionToast(text, kind, onDismiss) {
|
|
|
1908
1935
|
'bottom:16px',
|
|
1909
1936
|
'left:50%',
|
|
1910
1937
|
'transform:translateX(-50%)',
|
|
1911
|
-
|
|
1938
|
+
`z-index:${ACTION_TOAST_Z_INDEX}`,
|
|
1912
1939
|
'pointer-events:auto',
|
|
1913
1940
|
'max-width:90%',
|
|
1914
1941
|
'padding:8px 14px',
|
|
@@ -3404,20 +3431,30 @@ async function bootProduction(opts) {
|
|
|
3404
3431
|
}
|
|
3405
3432
|
},
|
|
3406
3433
|
};
|
|
3407
|
-
// Spec-canonical outbound dispatch
|
|
3408
|
-
//
|
|
3409
|
-
// `
|
|
3410
|
-
//
|
|
3411
|
-
//
|
|
3412
|
-
//
|
|
3413
|
-
//
|
|
3414
|
-
// `
|
|
3415
|
-
//
|
|
3416
|
-
// `
|
|
3417
|
-
//
|
|
3418
|
-
//
|
|
3419
|
-
//
|
|
3420
|
-
//
|
|
3434
|
+
// Spec-canonical outbound dispatch: user actions go through the
|
|
3435
|
+
// MCP-Apps host relay (SPEC §4.7): postMessage
|
|
3436
|
+
// `tools/call:ggui_runtime_submit_action` to the parent →
|
|
3437
|
+
// `AppRenderer.onCallTool` → host's MCP client → ggui MCP server
|
|
3438
|
+
// → `createGguiSubmitActionHandler.append` → `pendingEventConsumer`
|
|
3439
|
+
// → `ggui_consume` wakes the agent. NOTE (truth, ggui#596 +
|
|
3440
|
+
// adversarial-cycle correction): the server's WS ingress
|
|
3441
|
+
// dual-writes accepted `data:submit` frames onto the consume pipe
|
|
3442
|
+
// ONLY when the live channel is composed with a
|
|
3443
|
+
// `pendingEventConsumer` — which `createGguiServer` threads for
|
|
3444
|
+
// DEFAULT-handlers compositions only (a custom `handlers` list
|
|
3445
|
+
// drains its own pipe; bridging the channel onto an instance
|
|
3446
|
+
// nobody drains would buffer gestures into the void — see the
|
|
3447
|
+
// hoist note in server.ts). The hosted pod IS a custom-handlers
|
|
3448
|
+
// caller: on it, a WS gesture lands on the retained ledger only
|
|
3449
|
+
// and never reaches the agent. Any WS action fallback (ggui#599's
|
|
3450
|
+
// open design leg) therefore requires the server/pod bridge
|
|
3451
|
+
// FIRST — it is a capability gap on that composition today. The WS pipe otherwise carries
|
|
3452
|
+
// streamSpec subscriptions (inbound `ggui_emit` fanout +
|
|
3453
|
+
// `props_update` + `render` + `data` + `drain_ack` +
|
|
3454
|
+
// `channel_payload`). `routeDispatch` is the shared named-export
|
|
3455
|
+
// helper (production + tests exercise the same code path);
|
|
3456
|
+
// threading it here keeps LIVE-mode on the canonical dispatch
|
|
3457
|
+
// pipeline.
|
|
3421
3458
|
// Single mounted render — populated by `applyRender` on the first
|
|
3422
3459
|
// render frame. The wire config + data channel handler read it
|
|
3423
3460
|
// through `currentRender`-returning thunks so they always see the
|
|
@@ -1,4 +1,20 @@
|
|
|
1
1
|
import type { ObservabilityEmitter } from './observability.js';
|
|
2
|
+
/**
|
|
3
|
+
* Stacking contract between the two body-appended runtime layers
|
|
4
|
+
* (ggui#603): the feedback chrome must sit strictly ABOVE the action
|
|
5
|
+
* toast. The persistent `action_required` toast parks
|
|
6
|
+
* `pointer-events:auto` at fixed bottom-center — the same region this
|
|
7
|
+
* chrome occupies — and is re-armed per gesture; without this order an
|
|
8
|
+
* armed toast eats every tap aimed at the feedback controls. The toast
|
|
9
|
+
* remains dismissable on its own uncovered area (it accepts the click
|
|
10
|
+
* anywhere on itself), so partial occlusion costs it nothing.
|
|
11
|
+
*
|
|
12
|
+
* Single source: `runtime.ts`'s toast reads {@link ACTION_TOAST_Z_INDEX};
|
|
13
|
+
* this module applies {@link UI_FEEDBACK_CHROME_Z_INDEX} to the chrome
|
|
14
|
+
* container. The test suite pins the relationship, not the numbers.
|
|
15
|
+
*/
|
|
16
|
+
export declare const UI_FEEDBACK_CHROME_Z_INDEX = 2147483647;
|
|
17
|
+
export declare const ACTION_TOAST_Z_INDEX = 2147483646;
|
|
2
18
|
export interface UiFeedbackChromeOptions {
|
|
3
19
|
/**
|
|
4
20
|
* Observability sink the card emits `ui-feedback` events into.
|
|
@@ -36,6 +36,22 @@
|
|
|
36
36
|
* gate passes.
|
|
37
37
|
*/
|
|
38
38
|
import { createElement } from 'react';
|
|
39
|
+
/**
|
|
40
|
+
* Stacking contract between the two body-appended runtime layers
|
|
41
|
+
* (ggui#603): the feedback chrome must sit strictly ABOVE the action
|
|
42
|
+
* toast. The persistent `action_required` toast parks
|
|
43
|
+
* `pointer-events:auto` at fixed bottom-center — the same region this
|
|
44
|
+
* chrome occupies — and is re-armed per gesture; without this order an
|
|
45
|
+
* armed toast eats every tap aimed at the feedback controls. The toast
|
|
46
|
+
* remains dismissable on its own uncovered area (it accepts the click
|
|
47
|
+
* anywhere on itself), so partial occlusion costs it nothing.
|
|
48
|
+
*
|
|
49
|
+
* Single source: `runtime.ts`'s toast reads {@link ACTION_TOAST_Z_INDEX};
|
|
50
|
+
* this module applies {@link UI_FEEDBACK_CHROME_Z_INDEX} to the chrome
|
|
51
|
+
* container. The test suite pins the relationship, not the numbers.
|
|
52
|
+
*/
|
|
53
|
+
export const UI_FEEDBACK_CHROME_Z_INDEX = 2147483647;
|
|
54
|
+
export const ACTION_TOAST_Z_INDEX = 2147483646;
|
|
39
55
|
/**
|
|
40
56
|
* Mount the in-iframe UI-feedback affordance, or do nothing.
|
|
41
57
|
*
|
|
@@ -69,6 +85,10 @@ export async function mountUiFeedbackChrome(doc, opts) {
|
|
|
69
85
|
doc.querySelector('[data-ggui-ui-feedback-chrome]')?.remove();
|
|
70
86
|
const container = doc.createElement('div');
|
|
71
87
|
container.setAttribute('data-ggui-ui-feedback-chrome', '');
|
|
88
|
+
// Win the stacking race against the action toast (ggui#603 — see
|
|
89
|
+
// the constants' docblock above).
|
|
90
|
+
container.style.position = 'relative';
|
|
91
|
+
container.style.zIndex = String(UI_FEEDBACK_CHROME_Z_INDEX);
|
|
72
92
|
doc.body.appendChild(container);
|
|
73
93
|
const root = reactDomClient.createRoot(container);
|
|
74
94
|
root.render(createElement(cardMod.UiFeedbackCard, {
|
package/dist/wire-config.d.ts
CHANGED
|
@@ -95,9 +95,13 @@ export interface BuildRootWireConfigOptions {
|
|
|
95
95
|
*
|
|
96
96
|
* The default WS-frame send reaches the agent only on servers whose
|
|
97
97
|
* live channel bridges WS `data:submit` actions onto the same
|
|
98
|
-
* pending-events pipe
|
|
99
|
-
* `
|
|
100
|
-
*
|
|
98
|
+
* pending-events pipe. First-party `createGguiServer` bridges it
|
|
99
|
+
* ONLY when composed with DEFAULT handlers (`opts.handlers`
|
|
100
|
+
* undefined); a custom `handlers` list drains its own pipe, so the
|
|
101
|
+
* channel deliberately does not bridge — the hosted pod is such a
|
|
102
|
+
* caller, and on it a WS gesture lands on the retained ledger only.
|
|
103
|
+
* See `GguiSessionChannelOptions.pendingEventConsumer`. The default
|
|
104
|
+
* send remains the seam tests and direct-WS callers exercise.
|
|
101
105
|
*
|
|
102
106
|
* Called AFTER outbound validation passes. Receives the validated
|
|
103
107
|
* {@link ActionEnvelope}; caller extracts payload.action +
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ggui-ai/iframe-runtime",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.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",
|
|
@@ -36,12 +36,12 @@
|
|
|
36
36
|
"react": "^19.0.0",
|
|
37
37
|
"react-dom": "^19.0.0",
|
|
38
38
|
"zod": "^4.3.6",
|
|
39
|
-
"@ggui-ai/
|
|
40
|
-
"@ggui-ai/live-channel": "0.
|
|
41
|
-
"@ggui-ai/gadgets": "0.
|
|
42
|
-
"@ggui-ai/
|
|
43
|
-
"@ggui-ai/protocol": "0.
|
|
44
|
-
"@ggui-ai/wire": "0.
|
|
39
|
+
"@ggui-ai/design": "0.12.0",
|
|
40
|
+
"@ggui-ai/live-channel": "0.12.0",
|
|
41
|
+
"@ggui-ai/gadgets": "0.12.0",
|
|
42
|
+
"@ggui-ai/preview-a2ui": "0.12.0",
|
|
43
|
+
"@ggui-ai/protocol": "0.12.0",
|
|
44
|
+
"@ggui-ai/wire": "0.12.0"
|
|
45
45
|
},
|
|
46
46
|
"peerDependencies": {
|
|
47
47
|
"@modelcontextprotocol/sdk": "^1.27.0"
|