@ggui-ai/mcp-server-handlers 0.7.0 → 0.9.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/blueprints/index.d.ts +2 -2
- package/dist/blueprints/index.d.ts.map +1 -1
- package/dist/blueprints/index.js +1 -1
- package/dist/blueprints/search-blueprints.d.ts +64 -12
- package/dist/blueprints/search-blueprints.d.ts.map +1 -1
- package/dist/blueprints/search-blueprints.js +166 -16
- package/dist/renders/amend.d.ts +57 -0
- package/dist/renders/amend.d.ts.map +1 -0
- package/dist/renders/amend.js +64 -0
- package/dist/renders/apply-ggui-session-patch.d.ts +4 -0
- package/dist/renders/apply-ggui-session-patch.d.ts.map +1 -1
- package/dist/renders/apply-ggui-session-patch.js +1 -1
- package/dist/renders/assert-props-contract.d.ts +5 -4
- package/dist/renders/assert-props-contract.d.ts.map +1 -1
- package/dist/renders/assert-props-contract.js +6 -5
- package/dist/renders/code-delivery-events.d.ts +45 -29
- package/dist/renders/code-delivery-events.d.ts.map +1 -1
- package/dist/renders/code-delivery-events.js +42 -25
- package/dist/renders/consume.js +1 -1
- package/dist/renders/decide-handshake.d.ts +15 -0
- package/dist/renders/decide-handshake.d.ts.map +1 -1
- package/dist/renders/decide-handshake.js +18 -0
- package/dist/renders/declare-tool-catalog.js +1 -1
- package/dist/renders/handshake.d.ts.map +1 -1
- package/dist/renders/handshake.js +58 -12
- package/dist/renders/index.d.ts +5 -1
- package/dist/renders/index.d.ts.map +1 -1
- package/dist/renders/index.js +5 -1
- package/dist/renders/props-mutation-core.d.ts +60 -0
- package/dist/renders/props-mutation-core.d.ts.map +1 -0
- package/dist/renders/props-mutation-core.js +339 -0
- package/dist/renders/render.d.ts +2 -0
- package/dist/renders/render.d.ts.map +1 -1
- package/dist/renders/render.js +61 -32
- package/dist/renders/runtime-pull.d.ts +122 -0
- package/dist/renders/runtime-pull.d.ts.map +1 -0
- package/dist/renders/runtime-pull.js +178 -0
- package/dist/renders/runtime-telemetry.d.ts +60 -0
- package/dist/renders/runtime-telemetry.d.ts.map +1 -0
- package/dist/renders/runtime-telemetry.js +76 -0
- package/dist/renders/slice-meta-derivation.d.ts +146 -6
- package/dist/renders/slice-meta-derivation.d.ts.map +1 -1
- package/dist/renders/slice-meta-derivation.js +190 -8
- package/dist/renders/submit-action.d.ts +9 -0
- package/dist/renders/submit-action.d.ts.map +1 -1
- package/dist/renders/submit-action.js +70 -1
- package/dist/renders/update.d.ts +33 -42
- package/dist/renders/update.d.ts.map +1 -1
- package/dist/renders/update.js +99 -230
- package/package.json +7 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"slice-meta-derivation.d.ts","sourceRoot":"","sources":["../../src/renders/slice-meta-derivation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,OAAO,EAKL,KAAK,QAAQ,EACb,KAAK,gBAAgB,EACrB,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,WAAW,EACjB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,
|
|
1
|
+
{"version":3,"file":"slice-meta-derivation.d.ts","sourceRoot":"","sources":["../../src/renders/slice-meta-derivation.ts"],"names":[],"mappings":"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"}
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
* the render.
|
|
37
37
|
*/
|
|
38
38
|
import { bundleHostScheme, computeContractBundle, deriveContextDefault, DEFAULT_BUNDLE_HOST, } from '@ggui-ai/protocol';
|
|
39
|
-
import { deriveContextName, } from '@ggui-ai/protocol/integrations/mcp-apps';
|
|
39
|
+
import { composeSessionApiUrls, deriveContextName, } from '@ggui-ai/protocol/integrations/mcp-apps';
|
|
40
40
|
/**
|
|
41
41
|
* Resolve the canonical bundle URL + style URL for a gadget entry.
|
|
42
42
|
*
|
|
@@ -48,9 +48,13 @@ import { deriveContextName, } from '@ggui-ai/protocol/integrations/mcp-apps';
|
|
|
48
48
|
* ships via a non-registry CDN (esm.sh, jsdelivr, …).
|
|
49
49
|
* 2. `entry.bundleHost` + `entry.package` + `entry.version` —
|
|
50
50
|
* hostname resolution: server assembles
|
|
51
|
-
* `https://<bundleHost>/bundles/<scope>/<name>/<version>/bundle.js`
|
|
52
|
-
*
|
|
53
|
-
*
|
|
51
|
+
* `https://<bundleHost>/bundles/public/<scope>/<name>/<version>/bundle.js`
|
|
52
|
+
* — the PUBLIC prefix of `@ggui-ai/registry-core`'s
|
|
53
|
+
* visibility-split `BundleStorage` layout (H1). Host composition
|
|
54
|
+
* serves the anonymous render-time fetch, which only the public
|
|
55
|
+
* prefix answers; private artifacts always arrive as explicit
|
|
56
|
+
* `bundleUrl` values and are presign-rewritten at render-meta
|
|
57
|
+
* time ({@link rewritePrivateBundleUrls}).
|
|
54
58
|
* 3. Spec default `registry.ggui.ai` — applied when `entry.bundleHost`
|
|
55
59
|
* is absent but `package` + `version` are present (first-party
|
|
56
60
|
* hosted-registry default).
|
|
@@ -130,7 +134,15 @@ function resolveGadgetUrlsImpl(entry) {
|
|
|
130
134
|
const host = typeof bundleHost === 'string' && bundleHost.length > 0
|
|
131
135
|
? bundleHost
|
|
132
136
|
: DEFAULT_BUNDLE_HOST;
|
|
133
|
-
|
|
137
|
+
// H1 visibility split: bundleHost-tier composition serves the
|
|
138
|
+
// anonymous render-time fetch, which only the registry's PUBLIC
|
|
139
|
+
// prefix answers — the composed path carries the `public` segment
|
|
140
|
+
// (matches the visibility-split `BundleStorage` layout; pinned by
|
|
141
|
+
// the resolution-conformance catalog). Private artifacts reach
|
|
142
|
+
// the iframe via an explicit `bundleUrl` (presign-rewritten at
|
|
143
|
+
// render-meta time, see `rewritePrivateBundleUrls`), never via
|
|
144
|
+
// host composition.
|
|
145
|
+
return `${bundleHostScheme(host)}://${host}/bundles/public/${pkg}/${version}/${file}`;
|
|
134
146
|
};
|
|
135
147
|
const resolvedBundle = hasExplicitBundleUrl ? bundleUrl : computeFromHost('bundle.js');
|
|
136
148
|
// When the operator explicitly sets `bundleUrl` (the escape-hatch
|
|
@@ -149,6 +161,78 @@ function resolveGadgetUrlsImpl(entry) {
|
|
|
149
161
|
...(resolvedStyle !== undefined ? { styleUrl: resolvedStyle } : {}),
|
|
150
162
|
};
|
|
151
163
|
}
|
|
164
|
+
/**
|
|
165
|
+
* URL-path marker of the registry's PRIVATE bundle prefix (H1
|
|
166
|
+
* visibility split) — the substring {@link rewritePrivateBundleUrls}
|
|
167
|
+
* dispatches on.
|
|
168
|
+
*/
|
|
169
|
+
export const PRIVATE_BUNDLE_PREFIX = '/bundles/private/';
|
|
170
|
+
/**
|
|
171
|
+
* H1 ruling 1b — rewrite a render item's PRIVATE gadget bundle URLs
|
|
172
|
+
* into fetchable equivalents at render-meta time.
|
|
173
|
+
*
|
|
174
|
+
* A private artifact's explicit `bundleUrl` / `styleUrl` / `typesUrl`
|
|
175
|
+
* point at the registry's `bundles/private/` prefix, which serves no
|
|
176
|
+
* anonymous request — the sandboxed iframe (which sends no
|
|
177
|
+
* credentials) could never load it. When a `presign` function is
|
|
178
|
+
* supplied, every descriptor URL containing
|
|
179
|
+
* {@link PRIVATE_BUNDLE_PREFIX} is replaced by `await presign(url)` —
|
|
180
|
+
* the hosted deployment presigns a short-lived object-storage URL via
|
|
181
|
+
* its pod task role. Everything else is untouched: public explicit
|
|
182
|
+
* URLs, bundleHost-composed URLs (which are public-prefix by
|
|
183
|
+
* construction, see {@link resolveGadgetUrls}), and descriptors with
|
|
184
|
+
* no URLs at all.
|
|
185
|
+
*
|
|
186
|
+
* **OSS default: passthrough.** Without `presign` the item is returned
|
|
187
|
+
* unchanged — the self-hosted story is same-origin: a self-hoster's
|
|
188
|
+
* iframe and registry share an origin, so its `/bundles/private/…`
|
|
189
|
+
* route can authenticate the fetch itself (cookie/session) or the
|
|
190
|
+
* operator simply publishes render-consumed gadgets public. No
|
|
191
|
+
* presigning infrastructure is required to run the OSS stack.
|
|
192
|
+
*
|
|
193
|
+
* MUST run BEFORE {@link deriveRenderMeta}: both the CSP origin
|
|
194
|
+
* allowlist (`deriveBundleOrigins`) and the iframe registrations
|
|
195
|
+
* (`deriveGadgetRegistrations`) read the descriptor URLs, so the
|
|
196
|
+
* rewritten (presigned) origin lands in `script-src`/`style-src`
|
|
197
|
+
* automatically and the iframe fetches exactly what the CSP allows.
|
|
198
|
+
* Zero iframe changes — the client sees an ordinary absolute URL.
|
|
199
|
+
*
|
|
200
|
+
* Purity note: `deriveRenderMeta` stays pure; this pre-pass is the
|
|
201
|
+
* ONLY projection stage that may perform I/O, and it returns a new
|
|
202
|
+
* item (never mutates) so the WeakMap-memoized URL resolution keys
|
|
203
|
+
* stay correct.
|
|
204
|
+
*/
|
|
205
|
+
export async function rewritePrivateBundleUrls(item, presign) {
|
|
206
|
+
if (presign === undefined)
|
|
207
|
+
return item;
|
|
208
|
+
if (item.type === 'mcpApps' || item.type === 'system')
|
|
209
|
+
return item;
|
|
210
|
+
const descriptors = item.gadgetDescriptors;
|
|
211
|
+
if (descriptors === undefined || descriptors.length === 0)
|
|
212
|
+
return item;
|
|
213
|
+
const maybePresign = async (url) => typeof url === 'string' && url.includes(PRIVATE_BUNDLE_PREFIX)
|
|
214
|
+
? await presign(url)
|
|
215
|
+
: url;
|
|
216
|
+
let changed = false;
|
|
217
|
+
const rewritten = await Promise.all(descriptors.map(async (descriptor) => {
|
|
218
|
+
const bundleUrl = await maybePresign(descriptor.bundleUrl);
|
|
219
|
+
const styleUrl = await maybePresign(descriptor.styleUrl);
|
|
220
|
+
const typesUrl = await maybePresign(descriptor.typesUrl);
|
|
221
|
+
if (bundleUrl === descriptor.bundleUrl &&
|
|
222
|
+
styleUrl === descriptor.styleUrl &&
|
|
223
|
+
typesUrl === descriptor.typesUrl) {
|
|
224
|
+
return descriptor;
|
|
225
|
+
}
|
|
226
|
+
changed = true;
|
|
227
|
+
return {
|
|
228
|
+
...descriptor,
|
|
229
|
+
...(bundleUrl !== undefined ? { bundleUrl } : {}),
|
|
230
|
+
...(styleUrl !== undefined ? { styleUrl } : {}),
|
|
231
|
+
...(typesUrl !== undefined ? { typesUrl } : {}),
|
|
232
|
+
};
|
|
233
|
+
}));
|
|
234
|
+
return changed ? { ...item, gadgetDescriptors: rewritten } : item;
|
|
235
|
+
}
|
|
152
236
|
/**
|
|
153
237
|
* Per-slot contextSpec data for an active render, derived to a
|
|
154
238
|
* wire-friendly array. Returns `undefined` when no slots are declared.
|
|
@@ -601,17 +685,77 @@ export async function deriveContractBundle(item) {
|
|
|
601
685
|
contextSpec: item.contextSpec,
|
|
602
686
|
});
|
|
603
687
|
}
|
|
688
|
+
/**
|
|
689
|
+
* Ceiling on the base64 length {@link deriveRenderMeta} will inline as
|
|
690
|
+
* `codeB64` (256 KiB of base64 ≈ 192 KiB of source). Generated
|
|
691
|
+
* components run 5–50 KB; the cap exists so a pathological render
|
|
692
|
+
* cannot balloon every tool result and resource read it rides on.
|
|
693
|
+
* Over-cap renders keep their `codeUrl` / live-channel delivery.
|
|
694
|
+
*/
|
|
695
|
+
export const CODE_B64_MAX_CHARS = 262_144;
|
|
696
|
+
/**
|
|
697
|
+
* Base64-encode a component render's compiled source for the inline
|
|
698
|
+
* `codeB64` channel. `undefined` for non-component variants, empty
|
|
699
|
+
* source, or over-cap source (see {@link CODE_B64_MAX_CHARS}).
|
|
700
|
+
*/
|
|
701
|
+
function deriveCodeB64(item) {
|
|
702
|
+
if (item.type === 'mcpApps' || item.type === 'system')
|
|
703
|
+
return undefined;
|
|
704
|
+
const code = item.componentCode;
|
|
705
|
+
if (typeof code !== 'string' || code.length === 0)
|
|
706
|
+
return undefined;
|
|
707
|
+
const encoded = Buffer.from(code, 'utf8').toString('base64');
|
|
708
|
+
if (encoded.length > CODE_B64_MAX_CHARS)
|
|
709
|
+
return undefined;
|
|
710
|
+
return encoded;
|
|
711
|
+
}
|
|
604
712
|
/**
|
|
605
713
|
* Build the {@link RenderMetaView} for a render — the
|
|
606
714
|
* single-entry-point projection function every bootstrap transport
|
|
607
715
|
* SHOULD call. Composing transports take the view, spread it into
|
|
608
716
|
* their own envelope alongside render/auth/runtime concerns. The
|
|
609
|
-
* static-component code body
|
|
610
|
-
*
|
|
611
|
-
*
|
|
717
|
+
* static-component code body is delivered via the render handler's
|
|
718
|
+
* `codeUrl` channel (composed from `codeStore` + `codeBaseUrl`) AND —
|
|
719
|
+
* for fetch-blocked hosts — inline via the size-capped `codeB64`
|
|
720
|
+
* field this projection carries.
|
|
612
721
|
*
|
|
613
722
|
* Pure. Same input → identical output, byte-for-byte.
|
|
614
723
|
*/
|
|
724
|
+
/**
|
|
725
|
+
* Spread a {@link RenderMetaView}'s state + policy fields onto an
|
|
726
|
+
* `ai.ggui/render` slice literal — the ONE place the view→slice field
|
|
727
|
+
* list lives (#483 follow-up). Every slice emitter (ggui_render /
|
|
728
|
+
* ggui_update resultMeta, the resources/read shell, the /state route)
|
|
729
|
+
* MUST compose its envelope as `{ ...siteFields, ...spreadRenderMetaViewOntoSlice(view) }`
|
|
730
|
+
* instead of re-listing view fields: four emitters once re-spread the
|
|
731
|
+
* list by hand, and a field missing from one hand-copy is silently
|
|
732
|
+
* deleted for that transport (the `epoch` freeze-latch signal shipped
|
|
733
|
+
* exactly that way — probe 18). Mode discriminators (`kind`,
|
|
734
|
+
* `codeB64`/`codeUrl`) stay site-local on purpose: their mutual-
|
|
735
|
+
* exclusion logic differs per transport.
|
|
736
|
+
*
|
|
737
|
+
* Array fields are emitted only when non-empty (absent and `[]` are
|
|
738
|
+
* indistinguishable to every consumer's projection) and re-spread into
|
|
739
|
+
* fresh arrays so no emitter aliases the view's internals.
|
|
740
|
+
*/
|
|
741
|
+
export function spreadRenderMetaViewOntoSlice(view) {
|
|
742
|
+
if (view === undefined)
|
|
743
|
+
return {};
|
|
744
|
+
return {
|
|
745
|
+
...(view.epoch !== undefined ? { epoch: view.epoch } : {}),
|
|
746
|
+
...(view.propsJson !== undefined ? { propsJson: view.propsJson } : {}),
|
|
747
|
+
...(view.contextSlots !== undefined && view.contextSlots.length > 0
|
|
748
|
+
? { contextSlots: [...view.contextSlots] }
|
|
749
|
+
: {}),
|
|
750
|
+
...(view.permissionsPolicy !== undefined && view.permissionsPolicy.length > 0
|
|
751
|
+
? { permissionsPolicy: [...view.permissionsPolicy] }
|
|
752
|
+
: {}),
|
|
753
|
+
...(view.theme !== undefined ? { theme: view.theme } : {}),
|
|
754
|
+
...(view.gadgets !== undefined && view.gadgets.length > 0
|
|
755
|
+
? { gadgets: [...view.gadgets] }
|
|
756
|
+
: {}),
|
|
757
|
+
};
|
|
758
|
+
}
|
|
615
759
|
export function deriveRenderMeta(item) {
|
|
616
760
|
// MCP Apps items wire through their own shell — no projection here.
|
|
617
761
|
if (item.type === 'mcpApps')
|
|
@@ -644,8 +788,14 @@ export function deriveRenderMeta(item) {
|
|
|
644
788
|
// system cards theme via the SystemCardHost→ThemeProvider path, not
|
|
645
789
|
// this slice, so `SystemGguiSession` never carries a `theme` sidecar.
|
|
646
790
|
const theme = deriveTheme(item);
|
|
791
|
+
const codeB64 = deriveCodeB64(item);
|
|
647
792
|
return {
|
|
793
|
+
// History head epoch (#483) — the mount reads this as its OWN
|
|
794
|
+
// epoch for the freeze latch. Always projected (0 default) so a
|
|
795
|
+
// frame can never mistake "absent" for "epoch 0 vs a live head".
|
|
796
|
+
epoch: item.epoch ?? 0,
|
|
648
797
|
...(propsJson !== undefined ? { propsJson } : {}),
|
|
798
|
+
...(codeB64 !== undefined ? { codeB64 } : {}),
|
|
649
799
|
...(slots !== undefined ? { contextSlots: [...slots] } : {}),
|
|
650
800
|
...(permissionsPolicy !== undefined
|
|
651
801
|
? { permissionsPolicy: [...permissionsPolicy] }
|
|
@@ -657,6 +807,23 @@ export function deriveRenderMeta(item) {
|
|
|
657
807
|
...(theme !== undefined ? { theme } : {}),
|
|
658
808
|
};
|
|
659
809
|
}
|
|
810
|
+
/**
|
|
811
|
+
* Flip a WebSocket URL's origin to its HTTP twin —
|
|
812
|
+
* `wss://host/ws` → `https://host`, `ws://host/ws` → `http://host`.
|
|
813
|
+
* The fallback base for {@link composeSessionApiUrls} when no
|
|
814
|
+
* explicit `sessionApiBaseUrl` is configured (same derivation the
|
|
815
|
+
* cloud pod uses for its oauth issuerUrl). Total: a malformed
|
|
816
|
+
* `wsUrl` returns `undefined` so slice assembly degrades to
|
|
817
|
+
* no-channel-URLs instead of throwing mid-resultMeta.
|
|
818
|
+
*/
|
|
819
|
+
export function wsOriginToHttpOrigin(wsUrl) {
|
|
820
|
+
try {
|
|
821
|
+
return new URL(wsUrl).origin.replace(/^ws/, 'http');
|
|
822
|
+
}
|
|
823
|
+
catch {
|
|
824
|
+
return undefined;
|
|
825
|
+
}
|
|
826
|
+
}
|
|
660
827
|
/**
|
|
661
828
|
* Assemble the shared `ai.ggui/render` envelope base from the shared
|
|
662
829
|
* deps. ONE implementation of the three formerly hand-mirrored
|
|
@@ -691,12 +858,27 @@ export function assembleRenderSliceBase(deps, call) {
|
|
|
691
858
|
expiresAt: mintedTrio.expiresAt,
|
|
692
859
|
}
|
|
693
860
|
: {};
|
|
861
|
+
// Token-bearing session-API URL pair. Base resolution:
|
|
862
|
+
// explicit `sessionApiBaseUrl` dep (static or request-aware getter)
|
|
863
|
+
// wins; otherwise flip the minted trio's wsUrl origin ws→http (the
|
|
864
|
+
// session API is served on the WS origin for OSS defaults and the
|
|
865
|
+
// cloud pod's single ingress). No minted trio ⇒ `{}` — the URLs
|
|
866
|
+
// embed the token, so there is nothing honest to stamp.
|
|
867
|
+
const sessionApiBaseRaw = typeof deps.sessionApiBaseUrl === 'function'
|
|
868
|
+
? deps.sessionApiBaseUrl()
|
|
869
|
+
: deps.sessionApiBaseUrl;
|
|
870
|
+
const sessionApiBase = sessionApiBaseRaw ??
|
|
871
|
+
(mintedTrio !== undefined ? wsOriginToHttpOrigin(mintedTrio.wsUrl) : undefined);
|
|
872
|
+
const channelUrls = mintedTrio !== undefined && sessionApiBase !== undefined
|
|
873
|
+
? composeSessionApiUrls(sessionApiBase, call.sessionId, mintedTrio.token)
|
|
874
|
+
: {};
|
|
694
875
|
const liveTheme = deps.themeProvider?.();
|
|
695
876
|
const themeId = liveTheme?.id ?? call.renderThemeId ?? deps.themeId;
|
|
696
877
|
const themeMode = liveTheme?.mode ?? deps.themeMode;
|
|
697
878
|
return {
|
|
698
879
|
runtimeUrl,
|
|
699
880
|
authFields,
|
|
881
|
+
channelUrls,
|
|
700
882
|
...(themeId !== undefined ? { themeId } : {}),
|
|
701
883
|
...(themeMode !== undefined ? { themeMode } : {}),
|
|
702
884
|
};
|
|
@@ -143,6 +143,15 @@ export interface GguiSubmitActionHandlerDeps {
|
|
|
143
143
|
* is present and lets drain_ack dismiss the toast).
|
|
144
144
|
*/
|
|
145
145
|
readonly activeConsumerRegistry?: ActiveConsumerRegistry;
|
|
146
|
+
/**
|
|
147
|
+
* Doorbell-race grace OVERRIDE, ms. When set, replaces the adaptive
|
|
148
|
+
* policy entirely (see the handler body): the registry is waited on
|
|
149
|
+
* for exactly this long before answering `consumerPresent: false`.
|
|
150
|
+
* Unset → adaptive: 2s when a consume is plausibly imminent (recent
|
|
151
|
+
* exit, or first poll of a <60s-old render), 150ms otherwise. Test
|
|
152
|
+
* hook / operator escape hatch.
|
|
153
|
+
*/
|
|
154
|
+
readonly consumerGraceMs?: number;
|
|
146
155
|
/**
|
|
147
156
|
* Optional append-only event ledger. When wired, the handler
|
|
148
157
|
* dual-writes every successful dispatch envelope to BOTH:
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"submit-action.d.ts","sourceRoot":"","sources":["../../src/renders/submit-action.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4DG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAMxB,OAAO,EAEL,KAAK,sBAAsB,EAC5B,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAOjD,QAAA,MAAM,WAAW;;;;;;;CAoCP,CAAC;AAEX,QAAA,MAAM,YAAY;IAChB,yGAAyG;;IAEzG;;;;;;;OAOG;;;;;IAEH,+CAA+C;;IAE/C;;;;;;;;;;;;;;;;OAgBG;;CAEK,CAAC;AAEX,UAAU,kBAAkB;IAC1B,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAClB;;;;;OAKG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAC;CACpC;AAED,UAAU,kBAAkB;IAC1B,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IACnB,QAAQ,CAAC,IAAI,EAAE,qBAAqB,GAAG,gBAAgB,CAAC;IACxD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,KAAK,gBAAgB,GAAG,kBAAkB,GAAG,kBAAkB,CAAC;AAEhE;;;;;;;;;GASG;AACH,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,oBAAoB,CAAC,EAAE,OAAO,0BAA0B,EAAE,oBAAoB,CAAC;IACxF;;;;;;;OAOG;IACH,QAAQ,CAAC,sBAAsB,CAAC,EAAE,sBAAsB,CAAC;IACzD;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,0BAA0B,EAAE,gBAAgB,CAAC;IAC3E;;;;;OAKG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE;QAChB,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;KACvE,CAAC;CACH;AAED,wBAAgB,6BAA6B,CAC3C,IAAI,GAAE,2BAAgC,GACrC,aAAa,CAAC,OAAO,WAAW,EAAE,OAAO,YAAY,EAAE,gBAAgB,CAAC,
|
|
1
|
+
{"version":3,"file":"submit-action.d.ts","sourceRoot":"","sources":["../../src/renders/submit-action.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4DG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAMxB,OAAO,EAEL,KAAK,sBAAsB,EAC5B,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAOjD,QAAA,MAAM,WAAW;;;;;;;CAoCP,CAAC;AAEX,QAAA,MAAM,YAAY;IAChB,yGAAyG;;IAEzG;;;;;;;OAOG;;;;;IAEH,+CAA+C;;IAE/C;;;;;;;;;;;;;;;;OAgBG;;CAEK,CAAC;AAEX,UAAU,kBAAkB;IAC1B,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAClB;;;;;OAKG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAC;CACpC;AAED,UAAU,kBAAkB;IAC1B,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IACnB,QAAQ,CAAC,IAAI,EAAE,qBAAqB,GAAG,gBAAgB,CAAC;IACxD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,KAAK,gBAAgB,GAAG,kBAAkB,GAAG,kBAAkB,CAAC;AAEhE;;;;;;;;;GASG;AACH,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,oBAAoB,CAAC,EAAE,OAAO,0BAA0B,EAAE,oBAAoB,CAAC;IACxF;;;;;;;OAOG;IACH,QAAQ,CAAC,sBAAsB,CAAC,EAAE,sBAAsB,CAAC;IACzD;;;;;;;OAOG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,0BAA0B,EAAE,gBAAgB,CAAC;IAC3E;;;;;OAKG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE;QAChB,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;KACvE,CAAC;CACH;AAED,wBAAgB,6BAA6B,CAC3C,IAAI,GAAE,2BAAgC,GACrC,aAAa,CAAC,OAAO,WAAW,EAAE,OAAO,YAAY,EAAE,gBAAgB,CAAC,CAwO1E"}
|
|
@@ -250,10 +250,79 @@ export function createGguiSubmitActionHandler(deps = {}) {
|
|
|
250
250
|
// the pipe. When the seam isn't wired, the field is omitted
|
|
251
251
|
// and the iframe assumes a consumer is present (drain_ack
|
|
252
252
|
// will resolve the toast).
|
|
253
|
+
//
|
|
254
|
+
// GRACE WINDOW (doorbell race, observed live 2026-08-12):
|
|
255
|
+
// clicks routinely land a few hundred ms BEFORE the agent's
|
|
256
|
+
// next consume parks (live captures: 380ms and 371ms gaps).
|
|
257
|
+
// Answering `false` at the click instant makes the iframe
|
|
258
|
+
// ring the ui/message doorbell — and then the parked consume
|
|
259
|
+
// drains the SAME event, so the agent handles it twice (once
|
|
260
|
+
// from consume, once from the doorbell prompt). Instead of
|
|
261
|
+
// deciding at the instant, poll the registry briefly: a
|
|
262
|
+
// consumer parking inside the window drains this event and
|
|
263
|
+
// the honest answer is `true`. A full-window miss means no
|
|
264
|
+
// consume is coming this turn — `false`, ring away. The
|
|
265
|
+
// extra latency applies ONLY to the no-consumer case and is
|
|
266
|
+
// well under gesture-feedback tolerances.
|
|
253
267
|
if (deps.activeConsumerRegistry !== undefined) {
|
|
268
|
+
const registry = deps.activeConsumerRegistry;
|
|
269
|
+
// ADAPTIVE grace (2026-08-12 follow-up to the fixed
|
|
270
|
+
// window): wait only when a consume is plausibly imminent,
|
|
271
|
+
// judged from server-side facts — no environment guesses.
|
|
272
|
+
// - recent consumer exit (<10s): the agent is mid-loop
|
|
273
|
+
// (consume → act → consume); a re-poll is very likely
|
|
274
|
+
// → wait up to 2s.
|
|
275
|
+
// - no consumer EVER seen + render younger than 20s: the
|
|
276
|
+
// post-render FIRST poll is the classic 380ms race →
|
|
277
|
+
// wait up to 2s.
|
|
278
|
+
// - otherwise (idle card, agent long gone): 150ms —
|
|
279
|
+
// enough to absorb scheduling jitter, snappy enough
|
|
280
|
+
// that the doorbell (the only wake-up left) rings
|
|
281
|
+
// promptly.
|
|
282
|
+
// `waitForConsumer` is event-driven: a consumer parking
|
|
283
|
+
// mid-window flips the answer instantly, so the window is
|
|
284
|
+
// a CEILING, not a fixed cost. `consumerGraceMs` overrides
|
|
285
|
+
// the whole policy (test hook / operator escape).
|
|
286
|
+
let graceMs = deps.consumerGraceMs;
|
|
287
|
+
if (graceMs === undefined) {
|
|
288
|
+
const sinceExit = registry.msSinceLastExit(env.sessionId);
|
|
289
|
+
if (sinceExit !== undefined && sinceExit < 10_000) {
|
|
290
|
+
graceMs = 2_000;
|
|
291
|
+
}
|
|
292
|
+
else if (sinceExit === undefined) {
|
|
293
|
+
let renderAgeMs;
|
|
294
|
+
if (deps.renderStore !== undefined) {
|
|
295
|
+
try {
|
|
296
|
+
const row = await deps.renderStore.get(env.sessionId);
|
|
297
|
+
const createdAt = row?.render.createdAt;
|
|
298
|
+
renderAgeMs =
|
|
299
|
+
typeof createdAt === 'number'
|
|
300
|
+
? Math.max(0, Date.now() - createdAt)
|
|
301
|
+
: undefined;
|
|
302
|
+
}
|
|
303
|
+
catch {
|
|
304
|
+
// Best-effort age read — fall through to the
|
|
305
|
+
// fast-answer arm on store hiccups.
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
// 60s (was 20s): a live probe clicked 20.4s
|
|
309
|
+
// post-render — 400ms past the old threshold — and
|
|
310
|
+
// rang a duplicate doorbell while the first poll
|
|
311
|
+
// parked 462ms later. Waiting 2s on a genuinely dead
|
|
312
|
+
// card is cheap; a false ring is not.
|
|
313
|
+
graceMs =
|
|
314
|
+
renderAgeMs !== undefined && renderAgeMs < 60_000
|
|
315
|
+
? 2_000
|
|
316
|
+
: 150;
|
|
317
|
+
}
|
|
318
|
+
else {
|
|
319
|
+
graceMs = 150;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
const present = await registry.waitForConsumer(env.sessionId, graceMs);
|
|
254
323
|
return {
|
|
255
324
|
ok: true,
|
|
256
|
-
consumerPresent:
|
|
325
|
+
consumerPresent: present,
|
|
257
326
|
};
|
|
258
327
|
}
|
|
259
328
|
}
|
package/dist/renders/update.d.ts
CHANGED
|
@@ -81,9 +81,18 @@ import { GguiSessionNotFoundError } from './errors.js';
|
|
|
81
81
|
* handler awaits to surface unexpected errors via the structured logger
|
|
82
82
|
* (best-effort delivery; thrown errors in the seam don't fail the tool
|
|
83
83
|
* call).
|
|
84
|
+
*
|
|
85
|
+
* `epoch` is the history epoch of the commit this frame carries —
|
|
86
|
+
* `ggui_update` fans its freshly-advanced epoch, `ggui_amend` fans the
|
|
87
|
+
* unchanged head. The notifier MUST put it on the `props_update`
|
|
88
|
+
* payload verbatim: it is the freeze-latch signal (#483) that tells a
|
|
89
|
+
* lower-epoch mount it has been superseded. The mutation core passes
|
|
90
|
+
* the commit-time value so implementations never re-read the row (a
|
|
91
|
+
* re-read races a concurrent update and can stamp an amend's frame
|
|
92
|
+
* with a newer epoch, freezing the live head it belongs to).
|
|
84
93
|
*/
|
|
85
94
|
export interface PropsUpdateNotifier {
|
|
86
|
-
sendPropsUpdate(sessionId: string, props: JsonObject): Promise<void>;
|
|
95
|
+
sendPropsUpdate(sessionId: string, props: JsonObject, epoch: number): Promise<void>;
|
|
87
96
|
}
|
|
88
97
|
/** Re-exported for callers that prefer to import the error from this module.
|
|
89
98
|
* These are the two typed failure shapes `ggui_update` throws:
|
|
@@ -113,7 +122,7 @@ export interface BillingGate {
|
|
|
113
122
|
* different policies per call-site (e.g. update is free / render
|
|
114
123
|
* triggers a credit charge).
|
|
115
124
|
*/
|
|
116
|
-
readonly tool: 'ggui_update' | 'ggui_render';
|
|
125
|
+
readonly tool: 'ggui_update' | 'ggui_amend' | 'ggui_render';
|
|
117
126
|
}): Promise<void> | void;
|
|
118
127
|
}
|
|
119
128
|
/**
|
|
@@ -174,66 +183,48 @@ export interface GguiUpdateHandlerDeps extends RenderSliceMetaDeps {
|
|
|
174
183
|
*/
|
|
175
184
|
readonly description?: string;
|
|
176
185
|
}
|
|
177
|
-
/**
|
|
178
|
-
* Input raw-shape — discriminated on `kind`:
|
|
179
|
-
*
|
|
180
|
-
* - `kind:'replace'` + `props` — full props replacement. The new
|
|
181
|
-
* map IS the new state.
|
|
182
|
-
* - `kind:'merge'` + `patch` — RFC 7396 JSON Merge Patch.
|
|
183
|
-
*
|
|
184
|
-
* Both validate the FINAL props (post-merge for `merge`) against the
|
|
185
|
-
* render's `propsSpec`.
|
|
186
|
-
*/
|
|
187
186
|
declare const inputSchema: {
|
|
188
|
-
/**
|
|
189
|
-
* Globally-unique render id. Optional on the wire so an in-process
|
|
190
|
-
* dispatcher (live-channel dispatch / threaded mount) can populate it
|
|
191
|
-
* via `HandlerContext.sessionId` instead. Required at the handler
|
|
192
|
-
* level — see the resolve step inside `handler`.
|
|
193
|
-
*/
|
|
194
187
|
readonly sessionId: z.ZodOptional<z.ZodString>;
|
|
195
|
-
/**
|
|
196
|
-
* Mode discriminator. `'replace'` requires `props`; `'merge'`
|
|
197
|
-
* requires `patch`. The narrowing step inside `handler` enforces
|
|
198
|
-
* both presence + mutual exclusion.
|
|
199
|
-
*/
|
|
200
188
|
readonly kind: z.ZodEnum<{
|
|
201
189
|
replace: "replace";
|
|
202
190
|
merge: "merge";
|
|
203
191
|
}>;
|
|
204
|
-
/**
|
|
205
|
-
* Full new props map. Required when `kind === 'replace'`; rejected
|
|
206
|
-
* otherwise. Validated against the GguiSession's `propsSpec` after
|
|
207
|
-
* applying.
|
|
208
|
-
*/
|
|
209
192
|
readonly props: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
210
|
-
/**
|
|
211
|
-
* RFC 7396 JSON Merge Patch. Required when `kind === 'merge'`;
|
|
212
|
-
* rejected otherwise. The handler applies the patch to the existing
|
|
213
|
-
* props, then validates the merged result against `propsSpec`.
|
|
214
|
-
* `null` values in the patch DELETE the corresponding key.
|
|
215
|
-
*/
|
|
216
193
|
readonly patch: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
217
194
|
};
|
|
218
195
|
declare const outputSchema: {
|
|
219
196
|
readonly sessionId: z.ZodString;
|
|
220
197
|
readonly updated: z.ZodBoolean;
|
|
221
198
|
/**
|
|
222
|
-
*
|
|
223
|
-
*
|
|
224
|
-
*
|
|
225
|
-
*
|
|
226
|
-
*
|
|
227
|
-
*
|
|
228
|
-
* field; SDKs that preserve `_meta` also see it on
|
|
229
|
-
* `_meta.ui.resourceUri`.
|
|
199
|
+
* The epoch-pinned URI of the NEW history record this update minted
|
|
200
|
+
* (`ui://ggui/render/{id}[/{key}]#{epoch}` — #483). On a no-op
|
|
201
|
+
* (`updated: false`) no record is minted and this is the bare
|
|
202
|
+
* live-head URI. SDKs that strip `_meta` from tool_results (OpenAI
|
|
203
|
+
* Agents SDK, Google ADK) reach the URI via this LLM-visible field;
|
|
204
|
+
* SDKs that preserve `_meta` also see it on `_meta.ui.resourceUri`.
|
|
230
205
|
*/
|
|
231
206
|
readonly resourceUri: z.ZodString;
|
|
207
|
+
/**
|
|
208
|
+
* The session's head epoch after this call — advanced by one on a
|
|
209
|
+
* real update, unchanged on a no-op. `ggui_render` mints epoch 0;
|
|
210
|
+
* the row is the authority (#483).
|
|
211
|
+
*/
|
|
212
|
+
readonly epoch: z.ZodNumber;
|
|
213
|
+
/**
|
|
214
|
+
* Present ONLY on a no-op: the patch validated and conformed but
|
|
215
|
+
* left props identical to the current state, so nothing was written,
|
|
216
|
+
* nothing changes on screen, and NO history record was minted.
|
|
217
|
+
* Model-visible by design — the common producer of a no-op is an LLM
|
|
218
|
+
* echoing existing props back, and this is its only feedback channel.
|
|
219
|
+
*/
|
|
220
|
+
readonly warning: z.ZodOptional<z.ZodString>;
|
|
232
221
|
};
|
|
233
222
|
interface UpdateOutput {
|
|
234
223
|
sessionId: string;
|
|
235
224
|
updated: boolean;
|
|
236
225
|
resourceUri: string;
|
|
226
|
+
epoch: number;
|
|
227
|
+
warning?: string;
|
|
237
228
|
}
|
|
238
229
|
/**
|
|
239
230
|
* Build the OSS `ggui_update` handler. Handler is additive — declared
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../src/renders/update.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6DG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EACL,sBAAsB,EAEtB,KAAK,UAAU,
|
|
1
|
+
{"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../src/renders/update.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6DG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EACL,sBAAsB,EAEtB,KAAK,UAAU,EAChB,MAAM,mBAAmB,CAAC;AAO3B,OAAO,KAAK,EACV,gBAAgB,EAChB,mBAAmB,EACpB,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,EAKL,KAAK,mBAAmB,EACzB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AAMvD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,WAAW,mBAAmB;IAClC,eAAe,CACb,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,UAAU,EACjB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,IAAI,CAAC,CAAC;CAClB;AAED;;;wDAGwD;AACxD,OAAO,EAAE,wBAAwB,EAAE,sBAAsB,EAAE,CAAC;AAE5D;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,KAAK,EAAE;QACd,QAAQ,CAAC,GAAG,EAAE,cAAc,CAAC;QAC7B;;;;WAIG;QACH,QAAQ,CAAC,IAAI,EAAE,aAAa,GAAG,YAAY,GAAG,aAAa,CAAC;KAC7D,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CAC1B;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,qBAAsB,SAAQ,mBAAmB;IAChE,4EAA4E;IAC5E,QAAQ,CAAC,WAAW,EAAE,gBAAgB,CAAC;IACvC;;;;;;;;;;;;OAYG;IACH,QAAQ,CAAC,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;IACnD;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;IACnD;;;;;OAKG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC;IACnC;;;;OAIG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAO/B;AAMD,QAAA,MAAM,WAAW;;;;;;;;CAAsB,CAAC;AAExC,QAAA,MAAM,YAAY;;;IAGhB;;;;;;;OAOG;;IAEH;;;;OAIG;;IAEH;;;;;;OAMG;;CAEK,CAAC;AAEX,UAAU,YAAY;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,qBAAqB,GAC1B,aAAa,CAAC,OAAO,WAAW,EAAE,OAAO,YAAY,EAAE,YAAY,CAAC,CAwJtE"}
|