@ggui-ai/mcp-server 0.24.0 → 0.26.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/README.md +2 -2
- package/dist/api-renders-routes.d.ts +46 -5
- package/dist/api-renders-routes.d.ts.map +1 -1
- package/dist/api-renders-routes.js +98 -39
- package/dist/api-renders-stream-route.d.ts +2 -1
- package/dist/api-renders-stream-route.d.ts.map +1 -1
- package/dist/api-renders-stream-route.js +14 -2
- package/dist/build-mcp.d.ts +16 -0
- package/dist/build-mcp.d.ts.map +1 -1
- package/dist/build-mcp.js +82 -12
- package/dist/console-auth.d.ts +10 -10
- package/dist/console-auth.d.ts.map +1 -1
- package/dist/control-service.d.ts.map +1 -1
- package/dist/control-service.js +0 -3
- package/dist/first-seen.d.ts +14 -0
- package/dist/first-seen.d.ts.map +1 -0
- package/dist/first-seen.js +19 -0
- package/dist/ggui-session-channel/action-ingress.d.ts.map +1 -1
- package/dist/ggui-session-channel/action-ingress.js +96 -8
- package/dist/ggui-session-channel/channel-subscriptions.d.ts +0 -1
- package/dist/ggui-session-channel/channel-subscriptions.d.ts.map +1 -1
- package/dist/ggui-session-channel/channel-subscriptions.js +4 -1
- package/dist/ggui-session-channel/internal-types.d.ts +20 -12
- package/dist/ggui-session-channel/internal-types.d.ts.map +1 -1
- package/dist/ggui-session-channel/outbound.d.ts.map +1 -1
- package/dist/ggui-session-channel/outbound.js +18 -6
- package/dist/ggui-session-channel/stream-epoch.d.ts +61 -0
- package/dist/ggui-session-channel/stream-epoch.d.ts.map +1 -0
- package/dist/ggui-session-channel/stream-epoch.js +47 -0
- package/dist/ggui-session-channel/subscribe.d.ts +40 -53
- package/dist/ggui-session-channel/subscribe.d.ts.map +1 -1
- package/dist/ggui-session-channel/subscribe.js +288 -124
- package/dist/ggui-session-channel/subscriber-lifecycle.d.ts.map +1 -1
- package/dist/ggui-session-channel/subscriber-lifecycle.js +17 -7
- package/dist/ggui-session-channel.d.ts +43 -7
- package/dist/ggui-session-channel.d.ts.map +1 -1
- package/dist/ggui-session-channel.js +7 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/instructions-presets.d.ts +22 -21
- package/dist/instructions-presets.d.ts.map +1 -1
- package/dist/instructions-presets.js +38 -38
- package/dist/llm-backed-negotiator.d.ts +4 -37
- package/dist/llm-backed-negotiator.d.ts.map +1 -1
- package/dist/llm-backed-negotiator.js +28 -210
- package/dist/mcp-apps-outbound.d.ts +40 -91
- package/dist/mcp-apps-outbound.d.ts.map +1 -1
- package/dist/mcp-apps-outbound.js +100 -15
- package/dist/mcp-endpoint-routes.d.ts +1 -0
- package/dist/mcp-endpoint-routes.d.ts.map +1 -1
- package/dist/mcp-endpoint-routes.js +38 -4
- package/dist/runtime-bundle-hash.d.ts +7 -0
- package/dist/runtime-bundle-hash.d.ts.map +1 -1
- package/dist/runtime-bundle-hash.js +8 -2
- package/dist/runtime-bundle-route.d.ts.map +1 -1
- package/dist/runtime-bundle-route.js +15 -0
- package/dist/server.d.ts +143 -85
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +224 -110
- package/dist/storage.d.ts +9 -1
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +4 -3
- package/dist/view-proof-gate.d.ts +96 -0
- package/dist/view-proof-gate.d.ts.map +1 -0
- package/dist/view-proof-gate.js +167 -0
- package/package.json +14 -15
- package/dist/render-read-gate.d.ts +0 -50
- package/dist/render-read-gate.d.ts.map +0 -1
- package/dist/render-read-gate.js +0 -36
|
@@ -59,7 +59,7 @@ import type { IncomingMessage } from "node:http";
|
|
|
59
59
|
import type { Duplex } from "node:stream";
|
|
60
60
|
import { type GguiSessionChannelLocalToolsOptions } from "./ggui-session-channel/channel-subscriptions.js";
|
|
61
61
|
import type { SubscriberSink } from "./ggui-session-channel/internal-types.js";
|
|
62
|
-
import { type GguiSessionChannelBootstrap, type GguiSessionChannelCookieAuth } from "./ggui-session-channel/subscribe.js";
|
|
62
|
+
import { type GguiSessionChannelBootstrap, type GguiSessionChannelCookieAuth, type SubscribeCredential } from "./ggui-session-channel/subscribe.js";
|
|
63
63
|
import type { Logger } from "./logger.js";
|
|
64
64
|
/** Default URL path for the channel endpoint. Operators can override. */
|
|
65
65
|
export declare const DEFAULT_RENDER_CHANNEL_PATH = "/ws";
|
|
@@ -112,7 +112,7 @@ export declare const DEFAULT_PRE_SUBSCRIBE_IDLE_MS = 30000;
|
|
|
112
112
|
*/
|
|
113
113
|
export declare const DEFAULT_MAX_PRE_SUBSCRIBE_CONNECTIONS = 1024;
|
|
114
114
|
export type { GguiSessionChannelLocalToolsOptions } from "./ggui-session-channel/channel-subscriptions.js";
|
|
115
|
-
export type { GguiSessionChannelBootstrap,
|
|
115
|
+
export type { GguiSessionChannelBootstrap, GguiSessionChannelBootstrapVerifyResult, GguiSessionChannelCookieAuth, SubscribeCredential, } from "./ggui-session-channel/subscribe.js";
|
|
116
116
|
export type { SubscriberSink } from "./ggui-session-channel/internal-types.js";
|
|
117
117
|
/**
|
|
118
118
|
* Thrown by {@link GguiSessionChannelServer.attachExternalSubscriber}
|
|
@@ -160,12 +160,40 @@ export interface GguiSessionChannelOptions {
|
|
|
160
160
|
readonly auth: AuthAdapter;
|
|
161
161
|
/**
|
|
162
162
|
* Maps resolved identity → the appId for subscribes that omit
|
|
163
|
-
* `payload.appId` (SPEC §12.2 identity-default resolution)
|
|
164
|
-
*
|
|
163
|
+
* `payload.appId` (SPEC §12.2 identity-default resolution), and on
|
|
164
|
+
* the bearer path decides whether a DECLARED appId is the identity's
|
|
165
|
+
* own or must pass {@link authorizeApp}. Defaults to
|
|
166
|
+
* `defaultAppIdFromIdentity` — same mapping the `/mcp` endpoint
|
|
165
167
|
* uses. Token-bound subscribes (wsToken / console cookie) never
|
|
166
168
|
* consult this seam: their credential already binds the appId.
|
|
167
169
|
*/
|
|
168
170
|
readonly appIdFromIdentity?: (result: AuthResult) => string;
|
|
171
|
+
/**
|
|
172
|
+
* Per-app authorization on the bearer path (SPEC §12.2). The channel
|
|
173
|
+
* awaits this with the subscribe's app and the identity before any
|
|
174
|
+
* store work — when the subscribe DECLARES an app other than the one
|
|
175
|
+
* `appIdFromIdentity` resolves (ggui#1480), and on EVERY subscribe
|
|
176
|
+
* from a {@link perAppOnlySources} credential, its identity-default
|
|
177
|
+
* app included (ggui#1482). A throw refuses with `APP_MISMATCH`.
|
|
178
|
+
* Wire the same check the `/mcp` endpoint runs on a URL-addressed
|
|
179
|
+
* app (`createGguiServer` threads `perAppRouting.authorize`). Absent
|
|
180
|
+
* → a declared appId is trusted, as the `/mcp` endpoint trusts a URL
|
|
181
|
+
* appId under per-app routing without an authorize callback.
|
|
182
|
+
* Credential-bound subscribes (wsToken / console cookie) never
|
|
183
|
+
* consult it: their credential already binds the app.
|
|
184
|
+
*/
|
|
185
|
+
readonly authorizeApp?: (appId: string, identity: AuthResult) => Promise<void>;
|
|
186
|
+
/**
|
|
187
|
+
* Credential sources that are valid only for their own app (ggui#1482).
|
|
188
|
+
* A bearer subscribe whose identity came from a listed source is sent
|
|
189
|
+
* to {@link authorizeApp} on EVERY subscribe — the identity-default
|
|
190
|
+
* app included, whether `payload.appId` is omitted or names it — so
|
|
191
|
+
* the checks that authorization runs cannot be skipped. Listing a
|
|
192
|
+
* source without an `authorizeApp` throws at construction: the list
|
|
193
|
+
* says these credentials must be authorized, so the channel never
|
|
194
|
+
* serves with nothing to authorize them.
|
|
195
|
+
*/
|
|
196
|
+
readonly perAppOnlySources?: readonly AuthResult["source"][];
|
|
169
197
|
/** Structured logger. */
|
|
170
198
|
readonly logger: Logger;
|
|
171
199
|
/** URL path to mount on. Defaults to `/ws`. */
|
|
@@ -195,9 +223,9 @@ export interface GguiSessionChannelOptions {
|
|
|
195
223
|
readonly streamFanout?: StreamFanout;
|
|
196
224
|
/**
|
|
197
225
|
* Optional bootstrap-auth plumbing. When present, the channel
|
|
198
|
-
* accepts `SubscribePayload.wsToken
|
|
199
|
-
*
|
|
200
|
-
*
|
|
226
|
+
* accepts `SubscribePayload.wsToken`; it mints no reconnect
|
|
227
|
+
* credential (ggui#1488). When absent, bootstrap tokens are rejected
|
|
228
|
+
* with `BOOTSTRAP_NOT_SUPPORTED`.
|
|
201
229
|
*/
|
|
202
230
|
readonly bootstrap?: GguiSessionChannelBootstrap;
|
|
203
231
|
/**
|
|
@@ -552,6 +580,14 @@ export interface GguiSessionChannelServer {
|
|
|
552
580
|
readonly sink: SubscriberSink;
|
|
553
581
|
readonly sinceSequence?: number;
|
|
554
582
|
readonly fromSeq?: number;
|
|
583
|
+
/** The epoch `fromSeq` was counted in (ggui#1531); read only beside it. */
|
|
584
|
+
readonly fromEpoch?: string;
|
|
585
|
+
/**
|
|
586
|
+
* The credential the transport authenticated (ggui#1488), logged as
|
|
587
|
+
* `render_channel_subscribed.source`; the SSE route passes
|
|
588
|
+
* `"ws_token"`. Absent: the identity's own auth source.
|
|
589
|
+
*/
|
|
590
|
+
readonly credential?: SubscribeCredential;
|
|
555
591
|
}): Promise<{
|
|
556
592
|
readonly detach: () => void;
|
|
557
593
|
}>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ggui-session-channel.d.ts","sourceRoot":"","sources":["../src/ggui-session-channel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AAEH,OAAO,KAAK,EACV,WAAW,EACX,UAAU,EACV,oBAAoB,EACpB,gBAAgB,EAChB,uBAAuB,EACvB,mBAAmB,EACnB,YAAY,EACZ,aAAa,EACd,MAAM,0BAA0B,CAAC;AAKlC,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAC3F,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAC;AAC9E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAI1C,OAAO,EAEL,KAAK,mCAAmC,EACzC,MAAM,iDAAiD,CAAC;AACzD,OAAO,KAAK,EAEV,cAAc,EAGf,MAAM,0CAA0C,CAAC;AAGlD,OAAO,EAEL,KAAK,2BAA2B,EAChC,KAAK,4BAA4B,
|
|
1
|
+
{"version":3,"file":"ggui-session-channel.d.ts","sourceRoot":"","sources":["../src/ggui-session-channel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AAEH,OAAO,KAAK,EACV,WAAW,EACX,UAAU,EACV,oBAAoB,EACpB,gBAAgB,EAChB,uBAAuB,EACvB,mBAAmB,EACnB,YAAY,EACZ,aAAa,EACd,MAAM,0BAA0B,CAAC;AAKlC,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAC3F,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAC;AAC9E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAI1C,OAAO,EAEL,KAAK,mCAAmC,EACzC,MAAM,iDAAiD,CAAC;AACzD,OAAO,KAAK,EAEV,cAAc,EAGf,MAAM,0CAA0C,CAAC;AAGlD,OAAO,EAEL,KAAK,2BAA2B,EAChC,KAAK,4BAA4B,EACjC,KAAK,mBAAmB,EACzB,MAAM,qCAAqC,CAAC;AAE7C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,yEAAyE;AACzE,eAAO,MAAM,2BAA2B,QAAQ,CAAC;AAEjD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,4BAA4B,UAAY,CAAC;AACtD;;;;;;GAMG;AACH,eAAO,MAAM,uCAAuC,QAAS,CAAC;AAC9D;;;;;GAKG;AACH,eAAO,MAAM,6BAA6B,QAAS,CAAC;AACpD;;;;;;GAMG;AACH,eAAO,MAAM,qCAAqC,OAAQ,CAAC;AAK3D,YAAY,EAAE,mCAAmC,EAAE,MAAM,iDAAiD,CAAC;AAK3G,YAAY,EACV,2BAA2B,EAC3B,uCAAuC,EACvC,4BAA4B,EAC5B,mBAAmB,GACpB,MAAM,qCAAqC,CAAC;AAM7C,YAAY,EAAE,cAAc,EAAE,MAAM,0CAA0C,CAAC;AAE/E;;;;;;GAMG;AACH,qBAAa,2BAA4B,SAAQ,KAAK;gBACxC,SAAS,EAAE,MAAM;CAI9B;AAED,MAAM,WAAW,yBAAyB;IACxC,kFAAkF;IAClF,QAAQ,CAAC,WAAW,EAAE,gBAAgB,CAAC;IACvC;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH,QAAQ,CAAC,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;IACrD;;;OAGG;IACH,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B;;;;;;;;OAQG;IACH,QAAQ,CAAC,iBAAiB,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,MAAM,CAAC;IAC5D;;;;;;;;;;;;;OAaG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/E;;;;;;;;;OASG;IACH,QAAQ,CAAC,iBAAiB,CAAC,EAAE,SAAS,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;IAC7D,yBAAyB;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,+CAA+C;IAC/C,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB;;;;;;;;;OASG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,uBAAuB,CAAC;IAChD;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,YAAY,CAAC;IACrC;;;;;OAKG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,2BAA2B,CAAC;IAEjD;;;;;;;;;;;;;;;OAeG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,4BAA4B,CAAC;IACnD;;;;;;;;;;;;;;;;;OAiBG;IACH,QAAQ,CAAC,uBAAuB,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,wBAAwB,CAAC,CAAC;IACjF;;;;;;;;;;;;;OAaG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,aAAa,CAAC;IACnC;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,yBAAyB,CAAC,EAAE,mCAAmC,CAAC;IACzE;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,UAAU,GAAG,QAAQ,CAAC;IAC/C;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC;;;;;;;;OAQG;IACH,QAAQ,CAAC,2BAA2B,CAAC,EAAE,MAAM,CAAC;IAC9C;;;;;;;;OAQG;IACH,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IACrC;;;;;;;;OAQG;IACH,QAAQ,CAAC,0BAA0B,CAAC,EAAE,MAAM,CAAC;IAC7C;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,QAAQ,CAAC,iBAAiB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACzD;;;;;;;OAOG;IACH,QAAQ,CAAC,oBAAoB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7D;AAED,MAAM,WAAW,wBAAwB;IACvC,4DAA4D;IAC5D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,aAAa,CAAC,GAAG,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACxE;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;IACH,iBAAiB,CAAC,QAAQ,EAAE,mBAAmB,GAAG,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC3E;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA4BG;IACH,uBAAuB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1F;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAkCG;IACH,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpF;;;;;;;;;;;;;;;;OAgBG;IACH,YAAY,CAAC,IAAI,EAAE;QACjB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;QAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;QACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;KAC5B,GAAG,IAAI,CAAC;IACT;;;;;;;;;;;;;;;;;;OAkBG;IACH,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACpE;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,wBAAwB,CAAC,IAAI,EAAE;QAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;QAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QACvB,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC;QAC9B,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;QAC9B,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;QAChC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QAC1B,2EAA2E;QAC3E,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAC5B;;;;WAIG;QACH,QAAQ,CAAC,UAAU,CAAC,EAAE,mBAAmB,CAAC;KAC3C,GAAG,OAAO,CAAC;QAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,IAAI,CAAA;KAAE,CAAC,CAAC;IAC7C,2EAA2E;IAC3E,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,+DAA+D;IAC/D,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B;;;;;;;;OAQG;IACH,QAAQ,CAAC,sBAAsB,EAAE;QAC/B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;QACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;KAC7B,CAAC;IACF;;OAEG;IACH,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED;;;GAGG;AACH,wBAAgB,8BAA8B,CAC5C,IAAI,EAAE,yBAAyB,GAC9B,wBAAwB,CA2Q1B"}
|
|
@@ -129,6 +129,9 @@ export class ChannelSessionNotFoundError extends Error {
|
|
|
129
129
|
* composed into `createGguiServer` — see `server.ts` for the wire-up.
|
|
130
130
|
*/
|
|
131
131
|
export function createGguiSessionChannelServer(opts) {
|
|
132
|
+
if ((opts.perAppOnlySources?.length ?? 0) > 0 && opts.authorizeApp === undefined) {
|
|
133
|
+
throw new Error("createGguiSessionChannelServer: perAppOnlySources lists credential sources that must be authorized on every subscribe, but no authorizeApp is wired");
|
|
134
|
+
}
|
|
132
135
|
const path = opts.path ?? DEFAULT_RENDER_CHANNEL_PATH;
|
|
133
136
|
// Outbound stream buffer — owns seq assignment + bounded replay
|
|
134
137
|
// storage. Default is in-memory; operators swap via `opts.streamBuffer`.
|
|
@@ -201,7 +204,6 @@ export function createGguiSessionChannelServer(opts) {
|
|
|
201
204
|
renderStore: opts.renderStore,
|
|
202
205
|
localTools: opts.streamWebSocketLocalTools,
|
|
203
206
|
subscribersByWs,
|
|
204
|
-
send,
|
|
205
207
|
sendChannelError,
|
|
206
208
|
});
|
|
207
209
|
// Action ingress + consume bridge — contract gate, ledger + pipe
|
|
@@ -225,6 +227,8 @@ export function createGguiSessionChannelServer(opts) {
|
|
|
225
227
|
bootstrap: opts.bootstrap,
|
|
226
228
|
cookieAuth: opts.cookieAuth,
|
|
227
229
|
appIdFromIdentity: opts.appIdFromIdentity,
|
|
230
|
+
...(opts.authorizeApp ? { authorizeApp: opts.authorizeApp } : {}),
|
|
231
|
+
...(opts.perAppOnlySources ? { perAppOnlySources: opts.perAppOnlySources } : {}),
|
|
228
232
|
versionPolicy: opts.versionPolicy,
|
|
229
233
|
sendError,
|
|
230
234
|
register,
|
|
@@ -307,6 +311,8 @@ export function createGguiSessionChannelServer(opts) {
|
|
|
307
311
|
transport: "sse",
|
|
308
312
|
...(args.sinceSequence !== undefined ? { sinceSequence: args.sinceSequence } : {}),
|
|
309
313
|
...(args.fromSeq !== undefined ? { fromSeq: args.fromSeq } : {}),
|
|
314
|
+
...(args.fromEpoch !== undefined ? { fromEpoch: args.fromEpoch } : {}),
|
|
315
|
+
...(args.credential !== undefined ? { credential: args.credential } : {}),
|
|
310
316
|
});
|
|
311
317
|
},
|
|
312
318
|
get subscriberCount() {
|
package/dist/index.d.ts
CHANGED
|
@@ -29,7 +29,7 @@ export type { HandlerContext, SharedHandler } from '@ggui-ai/mcp-server-handlers
|
|
|
29
29
|
export type { GadgetDescriptor, McpUiDisplayMode, GguiSession, SystemGguiSession, } from '@ggui-ai/protocol';
|
|
30
30
|
export type { GenerationDeps } from '@ggui-ai/mcp-server-handlers';
|
|
31
31
|
export { buildNoCredentialsGguiSession } from '@ggui-ai/mcp-server-handlers';
|
|
32
|
-
export { buildOpsBundleHandlers, createGguiServer, defaultHandlers } from './server.js';
|
|
32
|
+
export { buildOpsBundleHandlers, createGguiServer, defaultHandlers, DEFAULT_CLOSE_GRACE_MS } from './server.js';
|
|
33
33
|
export type { CreateGguiServerOptions, ErrorMapperResult, GguiServer, OpsBundleDeps, } from './server.js';
|
|
34
34
|
export { AnthropicStructuredCallError, buildLlmCaller } from './llm-backed-negotiator.js';
|
|
35
35
|
export type { AnthropicStructuredCallFailureKind, BuildLlmCallerOptions, } from './llm-backed-negotiator.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAKlF,YAAY,EACV,gBAAgB,EAChB,gBAAgB,EAChB,WAAW,EACX,iBAAiB,GAClB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAKnE,OAAO,EAAE,6BAA6B,EAAE,MAAM,8BAA8B,CAAC;AAC7E,OAAO,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
// `/settings` URL) without taking a direct `@ggui-ai/mcp-server-handlers`
|
|
31
31
|
// dependency.
|
|
32
32
|
export { buildNoCredentialsGguiSession } from '@ggui-ai/mcp-server-handlers';
|
|
33
|
-
export { buildOpsBundleHandlers, createGguiServer, defaultHandlers } from './server.js';
|
|
33
|
+
export { buildOpsBundleHandlers, createGguiServer, defaultHandlers, DEFAULT_CLOSE_GRACE_MS } from './server.js';
|
|
34
34
|
// The handshake negotiator's LLM caller (the rerank judge + the contract
|
|
35
35
|
// synthesizer). Exported so a deployment that builds its own negotiator
|
|
36
36
|
// reuses this one Anthropic structured-call implementation — and can bound
|
|
@@ -15,20 +15,21 @@
|
|
|
15
15
|
* this server, and how do its tools fit together?" Both are spec-
|
|
16
16
|
* defined hints, both compose into the same system prompt.
|
|
17
17
|
*
|
|
18
|
-
* **
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* the field has that pull
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
18
|
+
* **Behaviour, stated plainly**: the `default` body is not only a
|
|
19
|
+
* protocol explainer. Its opening paragraph is a rendering POLICY (every
|
|
20
|
+
* user message is answered through the ggui_* tools, with no plain-text
|
|
21
|
+
* reply path), and later sections tell the model when to call which
|
|
22
|
+
* tool. The spec does not promise the field has that pull, and a line in
|
|
23
|
+
* the agent's own system prompt is the stronger lever (the recommended
|
|
24
|
+
* prompts in `@ggui-ai/protocol` carry one). Everything else in the body
|
|
25
|
+
* must stay TRUE of the shipped tool surface: it reaches the host's
|
|
26
|
+
* model on every connection.
|
|
27
27
|
*
|
|
28
28
|
* **Preset depth**:
|
|
29
29
|
*
|
|
30
|
-
* - `'default'` —
|
|
31
|
-
*
|
|
30
|
+
* - `'default'` — the protocol primer (about 18 KB): the rendering
|
|
31
|
+
* policy, the four-spec model, the lifecycle, gesture
|
|
32
|
+
* and reload handling, host rendering, tool discovery.
|
|
32
33
|
* - `'aggressive'` — adds the action-routing detail.
|
|
33
34
|
* - `'always'` — adds a worked invocation example.
|
|
34
35
|
* - `'minimal'` — server identity only.
|
|
@@ -47,9 +48,9 @@
|
|
|
47
48
|
*/
|
|
48
49
|
export declare const MCP_INSTRUCTIONS_PRESETS: {
|
|
49
50
|
/**
|
|
50
|
-
*
|
|
51
|
-
* model, lifecycle with nextStep-driven routing,
|
|
52
|
-
*
|
|
51
|
+
* The protocol primer (about 18 KB): the rendering policy, the
|
|
52
|
+
* four-spec mental model, the lifecycle with nextStep-driven routing,
|
|
53
|
+
* gesture and reload handling, host rendering, tool discovery.
|
|
53
54
|
*/
|
|
54
55
|
readonly default: string;
|
|
55
56
|
/**
|
|
@@ -89,7 +90,7 @@ export type McpInstructionsPreset = keyof typeof MCP_INSTRUCTIONS_PRESETS;
|
|
|
89
90
|
*
|
|
90
91
|
* - One of the preset names: `'default' | 'aggressive' | 'always' | 'minimal' | 'off'`.
|
|
91
92
|
* - An arbitrary string — used verbatim as the `instructions` field.
|
|
92
|
-
* - `undefined` —
|
|
93
|
+
* - `undefined` — nothing is sent: the no-flag default is `'off'` (ggui#1579).
|
|
93
94
|
*
|
|
94
95
|
* @public
|
|
95
96
|
*/
|
|
@@ -99,12 +100,12 @@ export type McpInstructionsValue = McpInstructionsPreset | string;
|
|
|
99
100
|
* server should send. Returns `undefined` when the result is empty
|
|
100
101
|
* (the constructor should omit the field).
|
|
101
102
|
*
|
|
102
|
-
* **No-
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
*
|
|
103
|
+
* **No-flag default = `'off'`: nothing is sent.** Until ggui#1579 no
|
|
104
|
+
* server's instructions reached a host (they were passed where the MCP
|
|
105
|
+
* SDK does not read them), so "none" is the behaviour every host knows.
|
|
106
|
+
* The fix keeps it for an operator who sets nothing: a preset or a
|
|
107
|
+
* custom string is opt-in, and is then delivered in the `initialize`
|
|
108
|
+
* result.
|
|
108
109
|
*
|
|
109
110
|
* @public
|
|
110
111
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instructions-presets.d.ts","sourceRoot":"","sources":["../src/instructions-presets.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"instructions-presets.d.ts","sourceRoot":"","sources":["../src/instructions-presets.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AA8GH;;;;;;;GAOG;AACH,eAAO,MAAM,wBAAwB;IACnC;;;;OAIG;;IAGH;;;;;OAKG;;IAGH;;;;OAIG;;IASH;;;OAGG;;IAIH;;;;OAIG;;CAEK,CAAC;AAEX;;;;;GAKG;AACH,MAAM,MAAM,qBAAqB,GAAG,MAAM,OAAO,wBAAwB,CAAC;AAE1E;;;;;;;;GAQG;AACH,MAAM,MAAM,oBAAoB,GAAG,qBAAqB,GAAG,MAAM,CAAC;AAElE;;;;;;;;;;;;;GAaG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,oBAAoB,GAAG,SAAS,GACtC,MAAM,GAAG,SAAS,CASpB"}
|
|
@@ -15,20 +15,21 @@
|
|
|
15
15
|
* this server, and how do its tools fit together?" Both are spec-
|
|
16
16
|
* defined hints, both compose into the same system prompt.
|
|
17
17
|
*
|
|
18
|
-
* **
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* the field has that pull
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
18
|
+
* **Behaviour, stated plainly**: the `default` body is not only a
|
|
19
|
+
* protocol explainer. Its opening paragraph is a rendering POLICY (every
|
|
20
|
+
* user message is answered through the ggui_* tools, with no plain-text
|
|
21
|
+
* reply path), and later sections tell the model when to call which
|
|
22
|
+
* tool. The spec does not promise the field has that pull, and a line in
|
|
23
|
+
* the agent's own system prompt is the stronger lever (the recommended
|
|
24
|
+
* prompts in `@ggui-ai/protocol` carry one). Everything else in the body
|
|
25
|
+
* must stay TRUE of the shipped tool surface: it reaches the host's
|
|
26
|
+
* model on every connection.
|
|
27
27
|
*
|
|
28
28
|
* **Preset depth**:
|
|
29
29
|
*
|
|
30
|
-
* - `'default'` —
|
|
31
|
-
*
|
|
30
|
+
* - `'default'` — the protocol primer (about 18 KB): the rendering
|
|
31
|
+
* policy, the four-spec model, the lifecycle, gesture
|
|
32
|
+
* and reload handling, host rendering, tool discovery.
|
|
32
33
|
* - `'aggressive'` — adds the action-routing detail.
|
|
33
34
|
* - `'always'` — adds a worked invocation example.
|
|
34
35
|
* - `'minimal'` — server identity only.
|
|
@@ -45,13 +46,13 @@
|
|
|
45
46
|
* matter when an operator wants the LLM to also reason about how the
|
|
46
47
|
* underlying tools/call envelopes flow.
|
|
47
48
|
*/
|
|
48
|
-
const ACTION_ROUTING_PARAGRAPH = "Action routing: every actionSpec entry is a GESTURE — a discrete event the agent reacts to on its next turn. When the user interacts, the iframe relays the action through `ggui_runtime_submit_action` to the server, which appends the event onto a per-render pipe. Your `ggui_consume` long-poll unblocks mid-turn with the event payload plus a uiContext snapshot of every declared contextSpec slot. There is no synchronous server-side tool-fire — `actions drive turns` is a structural invariant (https://docs.ggui.ai/concepts/sessions-and-the-event-model/): an action always waits for the agent. Cross-MCP `nextStep` hints work the same way: the agent reads the event's `
|
|
49
|
+
const ACTION_ROUTING_PARAGRAPH = "Action routing: every actionSpec entry is a GESTURE — a discrete event the agent reacts to on its next turn. When the user interacts, the iframe relays the action through `ggui_runtime_submit_action` to the server, which appends the event onto a per-render pipe. Your `ggui_consume` long-poll unblocks mid-turn with the event payload plus a uiContext snapshot of every declared contextSpec slot. There is no synchronous server-side tool-fire — `actions drive turns` is a structural invariant (https://docs.ggui.ai/concepts/sessions-and-the-event-model/): an action always waits for the agent. Cross-MCP `nextStep` hints work the same way: the agent reads the `nextStep` its own actionSpec entry declares for the event's `intent`, decides whether to honor it, and calls the named tool on the next turn (the tool MAY live on a different MCP server — declare it in `agentCapabilities.tools` so the cross-ref invariant passes).";
|
|
49
50
|
/**
|
|
50
51
|
* Worked invocation example. Layered atop the `aggressive` content by
|
|
51
52
|
* `always` only — shows the literal handshake → render pattern an
|
|
52
53
|
* operator can copy.
|
|
53
54
|
*/
|
|
54
|
-
const WORKED_EXAMPLE_PARAGRAPH = "Example: ggui_handshake({ intent: 'a settings panel for notification preferences', blueprintDraft: { contract: {...}, variance: { persona: 'minimalist' } } }) returns { handshakeId: 'h_…', suggestion: { origin: 'cache' | 'agent' | 'synth', blueprintMeta: { blueprintId?, contractHash, codeHash?, source?, variance }, amendments?, validationFindings? }
|
|
55
|
+
const WORKED_EXAMPLE_PARAGRAPH = "Example: ggui_handshake({ intent: 'a settings panel for notification preferences', blueprintDraft: { contract: {...}, variance: { persona: 'minimalist' } } }) returns { handshakeId: 'h_…', suggestion: { origin: 'cache' | 'agent' | 'synth', blueprintMeta: { blueprintId?, contractHash, codeHash?, source?, variance }, amendments?, validationFindings? } }. props is REQUIRED on every render (pass props: {} when the contract declares no propsSpec). ACCEPT PATH: ggui_render({ handshakeId: 'h_…', props: {} }) — OMIT override to reuse the proposed blueprintId verbatim. Read the response's `outcome` first: it is one of `rendered` | `failed` | `refused`. A `rendered` response carries the minted sessionId + the mount URI; a `failed` one carries the sessionId plus an `error` and CONSUMES the handshake; a `refused` one carries only `refusal` ({code, message, fix, retry, handshake: 'intact'}) — nothing was committed, the handshake is NOT consumed, and the same handshakeId works again once the fix lands. Retry by its `retry` class: an `after-fix` refusal: retry only once you have performed `refusal.fix` yourself (a change to your own call); when it names a fix for the app's owner or the operator, surface `refusal.fix` instead — retrying does not perform someone else's fix; a `later` refusal retries after the delay it names; `next-period` and `never` are not retried. OVERRIDE PATH: ggui_render({ handshakeId: 'h_…', props: {}, override: { contract: { ...refined } } }) — STRICT fresh draft against override.contract (server does NOT repair). override: { variance: {...} } instead re-aims the variant (persona/aesthetic/context/seedPrompt) while keeping the agreed contract.";
|
|
55
56
|
/**
|
|
56
57
|
* The default-preset body, captured as a const so `aggressive` and
|
|
57
58
|
* `always` can layer additional paragraphs on top without diverging
|
|
@@ -62,11 +63,11 @@ const DEFAULT_PRESET_BODY = [
|
|
|
62
63
|
'',
|
|
63
64
|
'═══ MENTAL MODEL ═══',
|
|
64
65
|
'',
|
|
65
|
-
'Every UI you render is described by a DataContract
|
|
66
|
+
'Every UI you render is described by a DataContract, which you author at handshake time; the contract is what the renderer compiles + the agent later interacts with. Its four DATA specs each have one job (a contract can also declare `agentCapabilities`, the tools its specs name, and `clientCapabilities`):',
|
|
66
67
|
'',
|
|
67
|
-
' • propsSpec — agent → client (one-shot data). The initial values the rendered UI displays.
|
|
68
|
+
' • propsSpec — agent → client (one-shot data). The initial values the rendered UI displays. `ggui_render` sends these as `props`; ggui_amend / ggui_update mutate them after delivery. e.g. a weather card has {temperature, condition, city} on propsSpec.',
|
|
68
69
|
'',
|
|
69
|
-
' • actionSpec — client → agent (discrete events). User gestures (clicks, submits) that drive the agent\'s NEXT TURN. Each entry has a `label`, optional `schema` for the payload, and optional `nextStep: "<toolName>"`. When `nextStep` is present, it names the tool the agent SHOULD call next AND the same name MUST also appear in `agentCapabilities.tools` (cross-ref invariant;
|
|
70
|
+
' • actionSpec — client → agent (discrete events). User gestures (clicks, submits) that drive the agent\'s NEXT TURN. Each entry has a `label`, optional `schema` for the payload, and optional `nextStep: "<toolName>"`. When `nextStep` is present, it names the tool the agent SHOULD call next AND the same name MUST also appear in `agentCapabilities.tools` (cross-ref invariant; a draft that breaks it gets the validation finding `CTR_REF_NEXT_STEP`). Omit `nextStep` entirely when the agent should decide freely from broader context (open-ended form submits). e.g. a feedback form has `submit` on actionSpec with `nextStep:"record_feedback"` (and `record_feedback` listed under `agentCapabilities.tools`).',
|
|
70
71
|
'',
|
|
71
72
|
' • contextSpec — client → agent (observed state, not events). Continuous client state the agent observes — slider position, draft text, current selection. Use contextSpec when you need to KNOW the state but don\'t need to ACT on every change. On MCP Apps hosts the runtime auto-mirrors the snapshot into the host\'s widget-context surface (the agent sees it on the next turn without polling). On raw MCP clients there is no auto-mirror — ggui_get_session returns `contextSnapshot` (the last-known value of every contextSpec slot) when the render has one, and each ggui_consume event carries its own `uiContext` captured at gesture time. e.g. a calendar has `selectedDate` on contextSpec.',
|
|
72
73
|
'',
|
|
@@ -80,34 +81,34 @@ const DEFAULT_PRESET_BODY = [
|
|
|
80
81
|
'',
|
|
81
82
|
'TOOL PREREQUISITES (read once, internalize):',
|
|
82
83
|
' • `ggui_handshake` is a prerequisite for `ggui_render` ONLY. It returns the contract+code negotiation state (`handshakeId`) that `ggui_render` consumes. Call it BEFORE rendering a NEW UI.',
|
|
83
|
-
' • `ggui_consume`, `ggui_amend`, and `ggui_update` operate on EXISTING sessions identified by `sessionId` and require NO handshake. The `sessionId` was minted by an earlier `ggui_render` call; it identifies the live iframe the user is interacting with. Calling `ggui_handshake` before `ggui_consume`/`ggui_amend`/`ggui_update` is a category error —
|
|
84
|
+
' • `ggui_consume`, `ggui_amend`, and `ggui_update` operate on EXISTING sessions identified by `sessionId` and require NO handshake. The `sessionId` was minted by an earlier `ggui_render` call; it identifies the live iframe the user is interacting with. Calling `ggui_handshake` before `ggui_consume`/`ggui_amend`/`ggui_update` is a category error — a handshake starts a NEW UI, whose render mints a SEPARATE session the user can\'t see, orphaning whichever live iframe the gesture targeted.',
|
|
84
85
|
' • Each `sessionId` is the agent\'s persistent handle to one specific live iframe. Reuse it across consume/amend/update for as long as the user is interacting with that UI; only call `ggui_handshake` again when you need to spawn a genuinely new UI surface.',
|
|
85
86
|
'',
|
|
86
87
|
' 1. ggui_handshake — FIRST CALL for any UI. Negotiate a contract for the next render. Post {intent, blueprintDraft: {contract, variance?, generator?}}. `variance` is optional and steers cache lookup + gen by axis: `persona` ("minimalist", "playful"), `aesthetic` ("dense", "spacious"), `seedPrompt` (deterministic seed). HANDSHAKE IS FORGIVING — the server cache-matches an existing blueprint OR repairs your draft until it passes validation and returns a CONFORMING proposal, with two honest exceptions: `action: \'declined\'` (nothing in your draft passed the contract gate — NO proposal and NO ggui_render for that handshakeId; read `suggestion.validationFindings`, fix the draft, handshake once more) and a `proposedContractSummary` starting with `PARTIAL` (the proposal is your draft MINUS the entries the protocol refused — render it, then re-declare the dropped entries via `override: {contract}` or a corrected re-handshake). The suggestion carries origin: cache (an existing blueprint matched — delivered instantly) | agent (your draft was already clean) | synth (your draft had problems and the server repaired it; `suggestion.validationFindings` lists exactly what was wrong so you learn for next time). CRITICAL: a synth result is NOT an error and NOT a request to retry — the returned contract is READY. Accept it and call ggui_render. Do NOT re-call ggui_handshake hoping for a different origin — that is a loop that wastes turns and changes nothing.',
|
|
87
88
|
'',
|
|
88
|
-
' 2. ggui_render — deliver the UI. handshakeId is REQUIRED (from step 1): a call without `handshakeId` is rejected at input validation (-32602); an id that does not resolve fails as not found (`handshake_not_found` — call ggui_handshake again). props is ALSO REQUIRED on every call — send {handshakeId, props} (pass props: {} when the contract declares no propsSpec). OMIT `override` to use the handshake suggestion verbatim — THE NORMAL PATH, since the contract is already conforming. To commit to a FRESH draft of your own, add {handshakeId, props, override:{contract:{...}}}. OVERRIDE IS STRICT: a forced override.contract MUST already conform — the server does NOT repair it (override means "use mine exactly"). Alternatively {handshakeId, props, override:{variance:{...}}} re-aims the variant (persona/aesthetic/context/seedPrompt) while keeping the agreed contract. Prefer omitting override; override only when the suggestion genuinely is not what you want AND your replacement is correct. READ `outcome` FIRST — every render response carries it, and it is one of `rendered` | `failed` | `refused`. On `rendered` you get the minted `sessionId` — your handle for every follow-up call — plus the mount URI. On `failed` the sessionId is still there (the error session IS committed) alongside an `error` classification, and the handshake is consumed, so recovery starts at a fresh ggui_handshake. On `refused` the deployment declined BEFORE doing any work: the response carries only `refusal` ({code, message, fix, retry, handshake: \'intact\'}) — no sessionId, no cache, no error — nothing was committed and the handshake is NOT consumed: a `rendered` or `failed` render consumes the handshake; a `refused` render or a recoverable validation error leaves it intact, so the SAME handshakeId still works once the fix lands. Retry by its `retry` class: an `after-fix` refusal
|
|
89
|
+
' 2. ggui_render — deliver the UI. handshakeId is REQUIRED (from step 1): a call without `handshakeId` is rejected at input validation (-32602); an id that does not resolve fails as not found (`handshake_not_found` — call ggui_handshake again). props is ALSO REQUIRED on every call — send {handshakeId, props} (pass props: {} when the contract declares no propsSpec). OMIT `override` to use the handshake suggestion verbatim — THE NORMAL PATH, since the contract is already conforming. To commit to a FRESH draft of your own, add {handshakeId, props, override:{contract:{...}}}. OVERRIDE IS STRICT: a forced override.contract MUST already conform — the server does NOT repair it (override means "use mine exactly"). Alternatively {handshakeId, props, override:{variance:{...}}} re-aims the variant (persona/aesthetic/context/seedPrompt) while keeping the agreed contract. Prefer omitting override; override only when the suggestion genuinely is not what you want AND your replacement is correct. READ `outcome` FIRST — every render response carries it, and it is one of `rendered` | `failed` | `refused`. On `rendered` you get the minted `sessionId` — your handle for every follow-up call — plus the mount URI. On `failed` the sessionId is still there (the error session IS committed) alongside an `error` classification, and the handshake is consumed, so recovery starts at a fresh ggui_handshake. On `refused` the deployment declined BEFORE doing any work: the response carries only `refusal` ({code, message, fix, retry, handshake: \'intact\'}) — no sessionId, no cache, no error — nothing was committed and the handshake is NOT consumed: a `rendered` or `failed` render consumes the handshake; a `refused` render or a recoverable validation error leaves it intact, so the SAME handshakeId still works once the fix lands. Retry by its `retry` class: an `after-fix` refusal: retry only once you have performed `refusal.fix` yourself (a change to your own call); when it names a fix for the app\'s owner or the operator, surface `refusal.fix` instead — retrying does not perform someone else\'s fix; a `later` refusal retries after the delay it names; `next-period` and `never` are not retried. Handshake records are SINGLE-USE and expire. On error: `handshake_not_found` → call ggui_handshake again; `contract_violation` (props don\'t match propsSpec — a missing required prop is `contract_violation` too) → fix props and retry with the SAME handshakeId; `override_contract_invalid` (your override.contract failed validation) → drop override entirely, re-run ggui_handshake with that draft (which WILL repair it), and render the suggestion — do NOT retry override with the same draft.',
|
|
89
90
|
'',
|
|
90
91
|
' 3. NEXT STEP — read the render response. If it carries a `nextStep` field, call that tool with the given args: it names ggui_consume, emitted only with a non-empty actionSpec (the UI has interactive actions) and not when this host delivers gestures as new messages, so long-poll once for an immediate gesture and end your turn if none arrives. If the render response has NO nextStep, end your turn — either the UI has no actions, or this host delivers the user\'s gestures to you as new messages; the user reads the UI and interacts or types their next prompt when they\'re ready.',
|
|
91
92
|
'',
|
|
92
|
-
' 4. ggui_consume (when render said to) — long-poll for user interaction. Keyed by sessionId. `timeout` is an integer in [0, 25] seconds (default 0 — an instant non-blocking drain); pass `timeout: 25` to long-poll up to the server-enforced per-call cap, returning when an actionSpec event arrives or the window lapses. On an empty `events` array you may re-call once, then end your turn — when nobody is polling, a user gesture rings the chat as a new user message carrying its own consume directive. Each return carries `{events, status}`: `events[]` is the discrete action(s) the user just took. Each event is an envelope `{type: "action", sessionId, intent, actionData, uiContext, actionId, firedAt}` — `
|
|
93
|
+
' 4. ggui_consume (when render said to) — long-poll for user interaction. Keyed by sessionId. `timeout` is an integer in [0, 25] seconds (default 0 — an instant non-blocking drain); pass `timeout: 25` to long-poll up to the server-enforced per-call cap, returning when an actionSpec event arrives or the window lapses. On an empty `events` array you may re-call once, then end your turn — when nobody is polling, a user gesture rings the chat as a new user message carrying its own consume directive. Each return carries `{events, status}`: `events[]` is the discrete action(s) the user just took. Each event is an envelope `{type: "action", sessionId, intent, actionData, uiContext, actionId, firedAt}` — `intent` names the action (its actionSpec key) and `actionData` is WHAT the user did (the validated payload); `uiContext` is the iframe-local snapshot of every declared contextSpec slot AT THE MOMENT the action fired (form fields, selected tab, slider value, scroll position — whatever the contract declared). Both inform your reaction without a second round trip. When the actionSpec entry for the event\'s `intent` declares a `nextStep`, that names the tool the contract expects next — call it if it is available. Then show the result on the SAME card with `ggui_amend` (consume\'s response names it as its `nextStep`, step 5) and consume again. Start a new UI (step 1) only when the gesture asks for a structurally different surface. Continue until consume returns status:"expired" (the render is gone) or no further follow-up is needed.',
|
|
93
94
|
'',
|
|
94
95
|
' 5. ggui_amend — reflect the new state in the UI, in place. After ANY domain-tool call whose result changed data the rendered UI displays (e.g. `todo_toggle` flips a todo\'s `done`, `cart_add_item` extends a cart, `note_save` persists text), you MUST immediately call `ggui_amend` with the refreshed props so the user sees what just happened. The rendered UI does NOT auto-refresh — it only shows the props it was last given. Skipping this after a state-mutating tool call leaves the user staring at stale state and is the #1 wire bug. Pattern: `consume → domain-tool → ggui_amend → loop to consume`. Two modes: `{sessionId, kind:"replace", props}` sends the FULL new props map (use when most fields changed or you want deterministic restoration); `{sessionId, kind:"merge", patch}` sends ONLY the delta as RFC 7396 JSON Merge Patch (shallow merge, recurse on nested objects, `null` deletes a key, arrays fully replace — use when most props stay the same and only one or two fields changed). Prefer `merge` after a single domain-tool mutation. The only times you skip it: (a) the domain tool was pure-read (todo_list, search, etc.) AND its result wasn\'t for the UI, or (b) the contract has no propsSpec (pure-display with no mutable state). AMEND vs UPDATE vs NEW RENDER: `ggui_amend` repaints the SAME card quietly — no new card, the history number does not advance; it is the default move in gesture loops. `ggui_update` renders the updated state as a NEW card in the conversation and advances the history number — use it for state MILESTONES worth a card in the transcript, or when the original card is no longer visible/usable. When the user\'s gesture asks for a structurally DIFFERENT surface (picking from a menu, opening a detail view, navigating), run ggui_handshake + ggui_render for the next UI instead. If amend/update returns `updated: false` with a warning, your patch changed nothing: either send genuinely different values or render the next surface.',
|
|
95
96
|
'',
|
|
96
|
-
'In short: let the protocol\'s `nextStep` fields drive routing. Every ggui_* tool whose response logically chains forwards (handshake → render → consume) emits a nextStep when there IS a next step; the absence of nextStep means "you\'re done with this thread for now."',
|
|
97
|
+
'In short: let the protocol\'s `nextStep` fields drive routing. Every ggui_* tool whose response logically chains forwards (handshake → render → consume → amend) emits a nextStep when there IS a next step; the absence of nextStep means "you\'re done with this thread for now."',
|
|
97
98
|
'',
|
|
98
99
|
'═══ REHYDRATED USER GESTURES (sessionId-carrying user messages) ═══',
|
|
99
100
|
'',
|
|
100
|
-
'When the user
|
|
101
|
+
'When the user acts on a rendered UI and no `ggui_consume` long-poll is parked — you ended your turn, or the page was reloaded and the iframe re-mounted — the gesture is still queued, and the card itself rings the chat: it posts a USER MESSAGE that names the `sessionId` (the `ai.ggui/userAction` doorbell). Some hosts show it as a structured block, some as text. EITHER WAY, the rule is the same:',
|
|
101
102
|
'',
|
|
102
103
|
' • The named `sessionId` identifies an EXISTING live iframe. Treat the message as a continuation of THAT session, not as a fresh request.',
|
|
103
104
|
' • REQUIRED first tool call: `ggui_consume({sessionId: <the-named-id>})` to drain the queued gesture. This returns the event the user fired; act on it with the appropriate domain tool, then `ggui_amend({sessionId, ...})` on the SAME sessionId — the card the user is looking at repaints in place.',
|
|
104
|
-
' • DO NOT call `ggui_handshake` for a rehydrated-gesture message. Handshaking mints a SEPARATE
|
|
105
|
+
' • DO NOT call `ggui_handshake` for a rehydrated-gesture message. Handshaking starts a NEW UI whose render mints a SEPARATE session the user can\'t see, orphaning the live iframe they actually clicked. This is the most common reload-flow regression — when in doubt and you see a `sessionId` named in the user message, your first tool call is `ggui_consume({sessionId})`, full stop.',
|
|
105
106
|
'',
|
|
106
107
|
'Worked example — user reload + click:',
|
|
107
108
|
'',
|
|
108
109
|
' 1. User reloads the page; the iframe for session `s_abc123` re-mounts.',
|
|
109
110
|
' 2. User clicks "undo" in the iframe.',
|
|
110
|
-
' 3. Agent receives a user message
|
|
111
|
+
' 3. Agent receives a user message naming `sessionId: s_abc123` (the card\'s doorbell).',
|
|
111
112
|
' 4. Agent calls `ggui_consume({sessionId: "s_abc123"})` — NOT `ggui_handshake`.',
|
|
112
113
|
' 5. Consume returns the click event; agent calls `todo_toggle({id: 1, done: false})`.',
|
|
113
114
|
' 6. Agent calls `ggui_amend({sessionId: "s_abc123", kind: "merge", patch: {todos: [...]}})` — the mounted card repaints in place.',
|
|
@@ -120,7 +121,7 @@ const DEFAULT_PRESET_BODY = [
|
|
|
120
121
|
'',
|
|
121
122
|
' • ggui_emit — push frames to a streamSpec channel on a delivered UI. Use when the contract declared streamSpec (chat tokens, progress bars, live data). Frames must match the channel\'s declared `schema`. The live channel of the wire carries these.',
|
|
122
123
|
'',
|
|
123
|
-
' • ggui_get_session
|
|
124
|
+
' • ggui_get_session (and ggui_list_sessions, on servers that offer it) — inspect current session state if you\'ve lost track of what\'s on screen. ggui_get_session returns the wire projection — variant, id, appId, eventSequence, createdAt, lastActivityAt, expiresAt — plus `contextSnapshot` (the last-known contextSpec values) when the render has one: the read path for contextSpec values from a raw MCP client. ggui_list_sessions lists the caller\'s sessions — pass `hostName` + `hostSessionId` (the pair the host set on `_meta["ai.ggui/host-session"]` at render creation) to narrow to one chat conversation.',
|
|
124
125
|
'',
|
|
125
126
|
'═══ HOST RENDERING ═══',
|
|
126
127
|
'',
|
|
@@ -128,7 +129,7 @@ const DEFAULT_PRESET_BODY = [
|
|
|
128
129
|
'',
|
|
129
130
|
' • MCP Apps hosts (claude.ai, MCP-Apps-aware desktop clients) — render responses carry the rendered UI inline via `_meta["ai.ggui/render"]`; the host displays it automatically. The user interacts with the UI directly, and contextSpec snapshots flow back into your widget-context surface without any agent action.',
|
|
130
131
|
'',
|
|
131
|
-
' • Plain MCP clients (Claude Agent SDK without MCP Apps host adapter, raw CLI clients) — render responses carry
|
|
132
|
+
' • Plain MCP clients (Claude Agent SDK without MCP Apps host adapter, raw CLI clients) — render responses carry the `sessionId` and, when the UI is mountable, a `resourceUri` (`ui://…`); there is no URL to show the user, so never invent one. A client that can mount MCP Apps resources mounts the URI; a raw client reads state through ggui_get_session. Wire flow is identical (handshake → render → consume); only the rendering surface differs.',
|
|
132
133
|
'',
|
|
133
134
|
'Rendered UIs are LIVE — actionSpec entries route back to you as events you receive via consume (each gesture\'s payload validated against the entry\'s declared schema). You don\'t write glue code for any of this; declaring the spec at handshake time is enough.',
|
|
134
135
|
'',
|
|
@@ -138,7 +139,7 @@ const DEFAULT_PRESET_BODY = [
|
|
|
138
139
|
'',
|
|
139
140
|
'SYMPTOM: a tool call fails with a message like "tool has not been loaded yet — call tool_search first" or "you do not have the correct parameter names." RECOVERY: call `tool_search` with the tool name as a query (e.g. `tool_search({ query: "ggui_consume" })`), wait for the load to complete, then retry the original call with the same args. Same pattern for `ggui_amend` / `ggui_update`. After one successful `tool_search` per tool per conversation, subsequent calls work directly.',
|
|
140
141
|
'',
|
|
141
|
-
'WHEN IN DOUBT: if the render response carries `nextStep`, the host has effectively asked you to call that tool. Don\'t skip ggui_consume because the host whined about it being unloaded — `tool_search` first, then call. Skipping it leaves the user
|
|
142
|
+
'WHEN IN DOUBT: if the render response carries `nextStep`, the host has effectively asked you to call that tool. Don\'t skip ggui_consume because the host whined about it being unloaded — `tool_search` first, then call. Skipping it leaves the user\'s gestures waiting on the queue until the card\'s doorbell or a later consume brings them to you, so their clicks seem to go nowhere in the meantime.',
|
|
142
143
|
];
|
|
143
144
|
/**
|
|
144
145
|
* Preset name → instruction-string map. Operators select a preset by
|
|
@@ -150,9 +151,9 @@ const DEFAULT_PRESET_BODY = [
|
|
|
150
151
|
*/
|
|
151
152
|
export const MCP_INSTRUCTIONS_PRESETS = {
|
|
152
153
|
/**
|
|
153
|
-
*
|
|
154
|
-
* model, lifecycle with nextStep-driven routing,
|
|
155
|
-
*
|
|
154
|
+
* The protocol primer (about 18 KB): the rendering policy, the
|
|
155
|
+
* four-spec mental model, the lifecycle with nextStep-driven routing,
|
|
156
|
+
* gesture and reload handling, host rendering, tool discovery.
|
|
156
157
|
*/
|
|
157
158
|
default: DEFAULT_PRESET_BODY.join('\n'),
|
|
158
159
|
/**
|
|
@@ -191,19 +192,18 @@ export const MCP_INSTRUCTIONS_PRESETS = {
|
|
|
191
192
|
* server should send. Returns `undefined` when the result is empty
|
|
192
193
|
* (the constructor should omit the field).
|
|
193
194
|
*
|
|
194
|
-
* **No-
|
|
195
|
-
*
|
|
196
|
-
*
|
|
197
|
-
*
|
|
198
|
-
*
|
|
199
|
-
*
|
|
195
|
+
* **No-flag default = `'off'`: nothing is sent.** Until ggui#1579 no
|
|
196
|
+
* server's instructions reached a host (they were passed where the MCP
|
|
197
|
+
* SDK does not read them), so "none" is the behaviour every host knows.
|
|
198
|
+
* The fix keeps it for an operator who sets nothing: a preset or a
|
|
199
|
+
* custom string is opt-in, and is then delivered in the `initialize`
|
|
200
|
+
* result.
|
|
200
201
|
*
|
|
201
202
|
* @public
|
|
202
203
|
*/
|
|
203
204
|
export function resolveMcpInstructions(value) {
|
|
204
|
-
if (value === undefined)
|
|
205
|
-
return
|
|
206
|
-
}
|
|
205
|
+
if (value === undefined)
|
|
206
|
+
return undefined;
|
|
207
207
|
if (value in MCP_INSTRUCTIONS_PRESETS) {
|
|
208
208
|
const resolved = MCP_INSTRUCTIONS_PRESETS[value];
|
|
209
209
|
return resolved.length > 0 ? resolved : undefined;
|
|
@@ -25,28 +25,24 @@
|
|
|
25
25
|
* `ensureConformingContract`. Operational errors fail open; programmer
|
|
26
26
|
* errors re-throw. See `decide-handshake.ts` for the full contract.
|
|
27
27
|
*
|
|
28
|
-
* ## selectVariant
|
|
29
|
-
*
|
|
30
|
-
* The optional LLM-driven variant-selection seam is OSS-specific and
|
|
31
|
-
* stays on this binding (it is not part of the shared decide spine).
|
|
32
|
-
*
|
|
33
28
|
* ## Default binding
|
|
34
29
|
*
|
|
35
30
|
* Bound by default in `createGguiServer` when handshake is enabled AND a
|
|
36
31
|
* `resolveLlm` is wired into `generation`.
|
|
37
32
|
*/
|
|
38
|
-
import type { BlueprintIndex, EmbeddingProvider, LlmSelection, ProviderKeyRef,
|
|
33
|
+
import type { BlueprintIndex, EmbeddingProvider, LlmSelection, ProviderKeyRef, VectorStore } from "@ggui-ai/mcp-server-core";
|
|
39
34
|
import type { HandlerContext } from "@ggui-ai/mcp-server-handlers";
|
|
40
35
|
import { type BlueprintPool, type HandshakeNegotiator, type InstalledBlueprintsProvider, type ToolIdentityCatalogStore } from "@ggui-ai/mcp-server-handlers/renders";
|
|
41
36
|
import type { LLMCaller } from "@ggui-ai/negotiator";
|
|
42
|
-
import type { Blueprint } from "@ggui-ai/protocol";
|
|
43
37
|
/**
|
|
44
38
|
* Wrap a resolved BYOK credential pair into an `LLMCaller` the
|
|
45
39
|
* negotiator can call. The adapter is chosen via `selectAdapter`
|
|
46
40
|
* (anthropic / openai / google / openrouter / bedrock). `call` runs
|
|
47
41
|
* one `complete()` round-trip on the underlying adapter.
|
|
48
42
|
*
|
|
49
|
-
* `callStructured`
|
|
43
|
+
* `callStructured` (and `callStructuredMetered`, the same call with the
|
|
44
|
+
* response's token usage beside the tool input — ggui#1418) is wired for
|
|
45
|
+
* Anthropic only. Anthropic's
|
|
50
46
|
* `/v1/messages` natively supports forced tool use via `tools[] +
|
|
51
47
|
* tool_choice: {type:'tool', name}` — on the models that accept it; the
|
|
52
48
|
* always-thinking models refuse a forced tool (see
|
|
@@ -196,37 +192,8 @@ export declare function assembleHandshakePools(deps: Pick<LlmBackedHandshakeNego
|
|
|
196
192
|
* decision spine (find-similar → coverage guard → judge → atomic
|
|
197
193
|
* reuse, else synth-repair create) is shared verbatim across every
|
|
198
194
|
* negotiator binding; only the injected adapter differs.
|
|
199
|
-
* `selectVariant` is specific to this binding.
|
|
200
195
|
*
|
|
201
196
|
* @public
|
|
202
197
|
*/
|
|
203
198
|
export declare function createLlmBackedHandshakeNegotiator(deps: LlmBackedHandshakeNegotiatorDeps): HandshakeNegotiator;
|
|
204
|
-
/**
|
|
205
|
-
* The system prompt for the variant-selection LLM call. Calibration
|
|
206
|
-
* is load-bearing — the model is explicitly told to surface low
|
|
207
|
-
* confidence when signals are weak so the deterministic-ladder
|
|
208
|
-
* fallback takes over. The prompt is intentionally short: high
|
|
209
|
-
* token budget on the user message (candidate JSON) is more useful
|
|
210
|
-
* than verbose system framing.
|
|
211
|
-
*/
|
|
212
|
-
export declare const VARIANT_SELECTION_SYSTEM_PROMPT = "You are the variant selector for the ggui UI matcher. You receive a shortlist of pre-built UI blueprint variants and a request context. Pick the variant that best fits the request.\n\nEach variant carries:\n - blueprintId: stable identity (you MUST echo back exactly one of these).\n - source: provenance. {kind:\"llm\", generator, model} = engine-generated (advanced generators win on visual polish; default generators win on simplicity). {kind:\"user\"} = operator-registered hand-authored code. {kind:\"curated\"} = catalog-shipped system blueprint.\n - validatorScore: optional 0-1 self-assessed quality from the advanced generator's validators. Higher is better, undefined \u21D2 unknown.\n - isOperatorDefault: true \u21D2 the human operator pinned this as the default. Strong signal.\n - variance.persona: free-form tag (\"minimalist\", \"data-dense\", \"mobile-first\"\u2026).\n - variance.aesthetic: optional free-form tag (\"glassy\", \"flat\", \"editorial\"\u2026).\n - variance.context: small structured signal (theme, accent, \u2026).\n - variance.seedPrompt: the operator's original prose that produced this variant.\n\nThe request context carries the same fields. Match on:\n 1. variance.persona equality / closeness (strongest non-pin signal).\n 2. variance.aesthetic equality / closeness.\n 3. variance.context overlap (shared keys + values).\n 4. seedPrompt semantic similarity to context.intent.\n\nHonor operator pins (isOperatorDefault: true) unless variance.persona / variance.aesthetic on the request clearly contradicts the pinned variant \u2014 that's the only case where you should override the pin.\n\nCalibrate confidence honestly. Return high (\u2265 0.7) only when a clear best match exists. Return low (< 0.6) when signals are weak \u2014 the orchestration falls back to a deterministic ladder in that case. The fallback is safe; over-confident picks are NOT.";
|
|
213
|
-
/**
|
|
214
|
-
* Build the user-message payload for the variant-selection prompt.
|
|
215
|
-
* The candidate list is projected to a compact JSON shape that
|
|
216
|
-
* surfaces the decision-relevant fields only — full contract
|
|
217
|
-
* embedding is too much surface area for a sub-second pick.
|
|
218
|
-
*
|
|
219
|
-
* Exposed for testing — the prompt structure is load-bearing, so
|
|
220
|
-
* snapshot tests against this output anchor regressions.
|
|
221
|
-
*/
|
|
222
|
-
export declare function buildVariantSelectionUserMessage(candidates: readonly Blueprint[], context: VariantSelectionContext): string;
|
|
223
|
-
/**
|
|
224
|
-
* Parse + validate the LLM-tool-use response shape. Exposed for
|
|
225
|
-
* testing; in production it is only called via `runVariantSelectionLlm`.
|
|
226
|
-
*
|
|
227
|
-
* @throws Error on any shape violation. The caller catches and falls
|
|
228
|
-
* through to the deterministic ladder; the message is surfaced in
|
|
229
|
-
* `VariantSelectionResult.reason` for telemetry.
|
|
230
|
-
*/
|
|
231
|
-
export declare function parseVariantSelectionResponse(raw: unknown): VariantSelectionDecision;
|
|
232
199
|
//# sourceMappingURL=llm-backed-negotiator.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"llm-backed-negotiator.d.ts","sourceRoot":"","sources":["../src/llm-backed-negotiator.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"llm-backed-negotiator.d.ts","sourceRoot":"","sources":["../src/llm-backed-negotiator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,KAAK,EACV,cAAc,EACd,iBAAiB,EAEjB,YAAY,EACZ,cAAc,EACd,WAAW,EACZ,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAEL,KAAK,aAAa,EAElB,KAAK,mBAAmB,EACxB,KAAK,2BAA2B,EAChC,KAAK,wBAAwB,EAC9B,MAAM,sCAAsC,CAAC;AAC9C,OAAO,KAAK,EAAE,SAAS,EAAuB,MAAM,qBAAqB,CAAC;AAI1E;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;CAC/B;AAED,wBAAgB,cAAc,CAC5B,SAAS,EAAE,YAAY,EACvB,WAAW,EAAE,cAAc,EAC3B,OAAO,GAAE,qBAA0B,GAClC,SAAS,CAsDX;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,+BAA+B,QAAS,CAAC;AAEtD,uEAAuE;AACvE,MAAM,MAAM,kCAAkC;AAC5C,2EAA2E;AACzE,YAAY;AACd,2EAA2E;GACzE,cAAc;AAChB,mDAAmD;GACjD,SAAS;AACX,gCAAgC;GAC9B,MAAM;AACR,4CAA4C;GAC1C,WAAW,CAAC;AAEhB;;;;;GAKG;AACH,qBAAa,4BAA6B,SAAQ,KAAK;IACrD,QAAQ,CAAC,IAAI,EAAE,kCAAkC,CAAC;IAClD,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;gBAEtC,IAAI,EAAE,kCAAkC,EACxC,MAAM,EAAE,MAAM,EACd,KAAK,GAAE;QAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAO;CAQzE;AAgID;;;GAGG;AACH,MAAM,WAAW,gCAAgC;IAC/C;;;;;;OAMG;IACH,UAAU,EAAE,CACV,GAAG,EAAE,cAAc,KAEjB;QAAE,SAAS,EAAE,YAAY,CAAC;QAAC,WAAW,EAAE,cAAc,CAAA;KAAE,GACxD,OAAO,CAAC;QAAE,SAAS,EAAE,YAAY,CAAC;QAAC,WAAW,EAAE,cAAc,CAAA;KAAE,GAAG,IAAI,CAAC,GACxE,IAAI,CAAC;IACT;;;;;;;;;;;;OAYG;IACH,KAAK,CAAC,EAAE;QACN,QAAQ,CAAC,SAAS,EAAE,iBAAiB,CAAC;QACtC,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;QAClC,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;KAChC,CAAC;IACF;;;;;;;OAOG;IACH,mBAAmB,CAAC,EAAE,2BAA2B,CAAC;IAClD;;;;;;;;OAQG;IACH,YAAY,CAAC,EAAE,wBAAwB,CAAC;IACxC;;;;;OAKG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,aAAa,EAAE,CAAC;CAC/C;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,IAAI,CAAC,gCAAgC,EAAE,OAAO,GAAG,qBAAqB,GAAG,WAAW,CAAC,GAC1F,aAAa,EAAE,CAQjB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,kCAAkC,CAChD,IAAI,EAAE,gCAAgC,GACrC,mBAAmB,CAkCrB"}
|