@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.
Files changed (70) hide show
  1. package/README.md +2 -2
  2. package/dist/api-renders-routes.d.ts +46 -5
  3. package/dist/api-renders-routes.d.ts.map +1 -1
  4. package/dist/api-renders-routes.js +98 -39
  5. package/dist/api-renders-stream-route.d.ts +2 -1
  6. package/dist/api-renders-stream-route.d.ts.map +1 -1
  7. package/dist/api-renders-stream-route.js +14 -2
  8. package/dist/build-mcp.d.ts +16 -0
  9. package/dist/build-mcp.d.ts.map +1 -1
  10. package/dist/build-mcp.js +82 -12
  11. package/dist/console-auth.d.ts +10 -10
  12. package/dist/console-auth.d.ts.map +1 -1
  13. package/dist/control-service.d.ts.map +1 -1
  14. package/dist/control-service.js +0 -3
  15. package/dist/first-seen.d.ts +14 -0
  16. package/dist/first-seen.d.ts.map +1 -0
  17. package/dist/first-seen.js +19 -0
  18. package/dist/ggui-session-channel/action-ingress.d.ts.map +1 -1
  19. package/dist/ggui-session-channel/action-ingress.js +96 -8
  20. package/dist/ggui-session-channel/channel-subscriptions.d.ts +0 -1
  21. package/dist/ggui-session-channel/channel-subscriptions.d.ts.map +1 -1
  22. package/dist/ggui-session-channel/channel-subscriptions.js +4 -1
  23. package/dist/ggui-session-channel/internal-types.d.ts +20 -12
  24. package/dist/ggui-session-channel/internal-types.d.ts.map +1 -1
  25. package/dist/ggui-session-channel/outbound.d.ts.map +1 -1
  26. package/dist/ggui-session-channel/outbound.js +18 -6
  27. package/dist/ggui-session-channel/stream-epoch.d.ts +61 -0
  28. package/dist/ggui-session-channel/stream-epoch.d.ts.map +1 -0
  29. package/dist/ggui-session-channel/stream-epoch.js +47 -0
  30. package/dist/ggui-session-channel/subscribe.d.ts +40 -53
  31. package/dist/ggui-session-channel/subscribe.d.ts.map +1 -1
  32. package/dist/ggui-session-channel/subscribe.js +288 -124
  33. package/dist/ggui-session-channel/subscriber-lifecycle.d.ts.map +1 -1
  34. package/dist/ggui-session-channel/subscriber-lifecycle.js +17 -7
  35. package/dist/ggui-session-channel.d.ts +43 -7
  36. package/dist/ggui-session-channel.d.ts.map +1 -1
  37. package/dist/ggui-session-channel.js +7 -1
  38. package/dist/index.d.ts +1 -1
  39. package/dist/index.d.ts.map +1 -1
  40. package/dist/index.js +1 -1
  41. package/dist/instructions-presets.d.ts +22 -21
  42. package/dist/instructions-presets.d.ts.map +1 -1
  43. package/dist/instructions-presets.js +38 -38
  44. package/dist/llm-backed-negotiator.d.ts +4 -37
  45. package/dist/llm-backed-negotiator.d.ts.map +1 -1
  46. package/dist/llm-backed-negotiator.js +28 -210
  47. package/dist/mcp-apps-outbound.d.ts +40 -91
  48. package/dist/mcp-apps-outbound.d.ts.map +1 -1
  49. package/dist/mcp-apps-outbound.js +100 -15
  50. package/dist/mcp-endpoint-routes.d.ts +1 -0
  51. package/dist/mcp-endpoint-routes.d.ts.map +1 -1
  52. package/dist/mcp-endpoint-routes.js +38 -4
  53. package/dist/runtime-bundle-hash.d.ts +7 -0
  54. package/dist/runtime-bundle-hash.d.ts.map +1 -1
  55. package/dist/runtime-bundle-hash.js +8 -2
  56. package/dist/runtime-bundle-route.d.ts.map +1 -1
  57. package/dist/runtime-bundle-route.js +15 -0
  58. package/dist/server.d.ts +143 -85
  59. package/dist/server.d.ts.map +1 -1
  60. package/dist/server.js +224 -110
  61. package/dist/storage.d.ts +9 -1
  62. package/dist/storage.d.ts.map +1 -1
  63. package/dist/storage.js +4 -3
  64. package/dist/view-proof-gate.d.ts +96 -0
  65. package/dist/view-proof-gate.d.ts.map +1 -0
  66. package/dist/view-proof-gate.js +167 -0
  67. package/package.json +14 -15
  68. package/dist/render-read-gate.d.ts +0 -50
  69. package/dist/render-read-gate.d.ts.map +0 -1
  70. 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, GguiSessionChannelBootstrapRefreshResult, GguiSessionChannelBootstrapVerifyResult, GguiSessionChannelCookieAuth, } from "./ggui-session-channel/subscribe.js";
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). Defaults
164
- * to `defaultAppIdFromIdentity` — same mapping the `/mcp` endpoint
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` and issues reconnect
199
- * credentials in `AckPayload.sessionToken`. When absent, bootstrap
200
- * tokens are rejected with `BOOTSTRAP_NOT_SUPPORTED`.
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":"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"}
1
+ {"version":3,"file":"ggui-session-channel.d.ts","sourceRoot":"","sources":["../src/ggui-session-channel.ts"],"names":[],"mappings":"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"}
@@ -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';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
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
- * **Why presets explain protocol, not behavior**: previous iterations
19
- * tried to nudge the LLM to "render every response" via imperative
20
- * language. In observed practice this is worth less than a single
21
- * line of user-side custom instruction, AND the spec doesn't promise
22
- * the field has that pull. Honest framing: the presets explain what
23
- * ggui is, how the three lifecycle tools relate, and how rendered UIs
24
- * route actions/streams back. The LLM picks tools when its judgment
25
- * matches; for stronger pull, ship a recommended user-instruction
26
- * snippet (see the console `/settings` onboarding card).
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'` — concise protocol explainer (server identity +
31
- * live-UI mechanism + lifecycle bullets).
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
- * Concise protocol explainer — what ggui is, four-spec mental
51
- * model, lifecycle with nextStep-driven routing, complementary
52
- * tools. No-preset default.
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` — falls through to the no-preset default (`'default'`).
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-preset default = `'default'`.** All behavior-text presets
103
- * explain the protocol now (vs nudging tool-use), so the previous
104
- * "aggressive as no-preset default" rationale no longer applies —
105
- * `'default'` is the appropriate baseline. Operators who want fuller
106
- * protocol detail opt into `'aggressive'` or `'always'`. To turn
107
- * instructions off entirely, pass `'off'`.
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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;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,CAWpB"}
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
- * **Why presets explain protocol, not behavior**: previous iterations
19
- * tried to nudge the LLM to "render every response" via imperative
20
- * language. In observed practice this is worth less than a single
21
- * line of user-side custom instruction, AND the spec doesn't promise
22
- * the field has that pull. Honest framing: the presets explain what
23
- * ggui is, how the three lifecycle tools relate, and how rendered UIs
24
- * route actions/streams back. The LLM picks tools when its judgment
25
- * matches; for stronger pull, ship a recommended user-instruction
26
- * snippet (see the console `/settings` onboarding card).
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'` — concise protocol explainer (server identity +
31
- * live-UI mechanism + lifecycle bullets).
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 `actionData.nextStep`, 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
+ 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? }, contractHash: '<hex>' }. 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 is yours to retry only when its `fixBy` is `caller` (otherwise surface `refusal.fix` — 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
+ 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 — a typed declaration of four data surfaces. You author the contract at handshake time; the contract is what the renderer compiles + the agent later interacts with. Four specs, each with one job:',
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. Push sends these as `props`; ggui_amend / ggui_update mutate them after delivery. e.g. a weather card has {temperature, condition, city} on propsSpec.',
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; rejection code `cross_reference_unresolved`). 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
+ ' • 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 — it would mint a SEPARATE new session that the user can\'t see, orphaning whichever live iframe the gesture targeted.',
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 is yours to retry only when its `fixBy` is `caller` (otherwise surface `refusal.fix` — 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
+ ' 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}` — `actionData` is WHAT the user did (action name + validated payload, plus `nextStep` hint if the author declared one); `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. Honor each event\'s `actionData.nextStep` hint if the tool is available, then loop back to step 1 to render the response. Continue until consume returns status:"expired" (the render is gone) or no further follow-up is needed.',
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 reloads the page after interacting with a rendered UI, the iframe re-mounts but the agent process may have lost its `ggui_consume` long-poll. Subsequent clicks in the rehydrated iframe arrive as a USER MESSAGE that carries an explicit `sessionId` — either as a structured directive block (host-synthesized prefix wrapping the user prose) or as a typed slice the host passes through. EITHER WAY, the rule is the same:',
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 new 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
+ ' • 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 containing `sessionId: s_abc123` (in a host-synthesized directive or as a structured slice).',
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 / ggui_list_sessions — 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
+ ' • 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 a renderer URL in the structured content; the host either embeds it as an iframe or displays it as a link. Wire flow is identical (handshake → render → consume); only the rendering surface differs.',
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 staring at a UI whose actions silently never reach the agent — the worst protocol failure mode.',
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
- * Concise protocol explainer — what ggui is, four-spec mental
154
- * model, lifecycle with nextStep-driven routing, complementary
155
- * tools. No-preset default.
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-preset default = `'default'`.** All behavior-text presets
195
- * explain the protocol now (vs nudging tool-use), so the previous
196
- * "aggressive as no-preset default" rationale no longer applies —
197
- * `'default'` is the appropriate baseline. Operators who want fuller
198
- * protocol detail opt into `'aggressive'` or `'always'`. To turn
199
- * instructions off entirely, pass `'off'`.
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 MCP_INSTRUCTIONS_PRESETS.default;
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, VariantSelectionContext, VariantSelectionDecision, VectorStore } from "@ggui-ai/mcp-server-core";
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` is wired for Anthropic only. Anthropic's
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":"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"}
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"}