@ggui-ai/mcp-server-handlers 0.17.0 → 0.18.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.
|
@@ -117,6 +117,8 @@ declare const outputSchema: {
|
|
|
117
117
|
overlayHash: z.ZodLiteral<"mismatch">;
|
|
118
118
|
}, z.core.$strict>, z.ZodObject<{
|
|
119
119
|
refused: z.ZodLiteral<"v1 shape">;
|
|
120
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
121
|
+
wouldDrop: z.ZodArray<z.ZodString>;
|
|
120
122
|
}, z.core.$strict>]>>;
|
|
121
123
|
/** Present on a shape refusal the schema itself raised — its messages, one per issue. */
|
|
122
124
|
readonly issues: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
@@ -271,6 +273,8 @@ export declare function createSetAppThemeHandler(deps: SetAppThemeDeps): import(
|
|
|
271
273
|
overlayHash: z.ZodLiteral<"mismatch">;
|
|
272
274
|
}, z.core.$strict>, z.ZodObject<{
|
|
273
275
|
refused: z.ZodLiteral<"v1 shape">;
|
|
276
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
277
|
+
wouldDrop: z.ZodArray<z.ZodString>;
|
|
274
278
|
}, z.core.$strict>]>>;
|
|
275
279
|
/** Present on a shape refusal the schema itself raised — its messages, one per issue. */
|
|
276
280
|
readonly issues: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
@@ -332,6 +336,8 @@ export declare function createSetAppThemeHandler(deps: SetAppThemeDeps): import(
|
|
|
332
336
|
overlayHash: "mismatch";
|
|
333
337
|
} | {
|
|
334
338
|
refused: "v1 shape";
|
|
339
|
+
} | {
|
|
340
|
+
wouldDrop: string[];
|
|
335
341
|
} | undefined;
|
|
336
342
|
issues?: string[] | undefined;
|
|
337
343
|
}>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"set-app-theme.d.ts","sourceRoot":"","sources":["../../src/ops-apps/set-app-theme.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,OAAO,EAIL,KAAK,QAAQ,EACb,KAAK,mBAAmB,
|
|
1
|
+
{"version":3,"file":"set-app-theme.d.ts","sourceRoot":"","sources":["../../src/ops-apps/set-app-theme.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,OAAO,EAIL,KAAK,QAAQ,EACb,KAAK,mBAAmB,EAEzB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAIL,KAAK,mBAAmB,EACzB,MAAM,aAAa,CAAC;AAGrB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C;;;;GAIG;AACH,MAAM,MAAM,wBAAwB,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,KAAK;IACpF,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC,CAAC;AAcF,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAKhB,mEAAmE;;IAEnE,sGAAsG;;;;;;;;;;;;;;;;;;IAEtG,yFAAyF;;CAEjF,CAAC;AAEX,uEAAuE;AACvE,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,YAAY,CAAC,CAAC,CAAC;AAE1E,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,8FAA8F;IAC9F,QAAQ,CAAC,eAAe,EAAE,wBAAwB,CAAC;CACpD;AAED,0EAA0E;AAC1E,MAAM,MAAM,iBAAiB,GACzB;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAA;CAAE,GAC/C;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,mBAAmB,CAAA;CAAE,GAC7D;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAAC;AAY/D;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,GAAG,EAAE,OAAO,EACZ,eAAe,EAAE,wBAAwB,GACxC,OAAO,CAAC,iBAAiB,CAAC,CAsB5B;AAmBD,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAnF5D,mEAAmE;;IAEnE,sGAAsG;;;;;;;;;;;;;;;;;;IAEtG,yFAAyF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAoH1F"}
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
*
|
|
32
32
|
* Pure over the {@link AppsSource} seam + the injected validator.
|
|
33
33
|
*/
|
|
34
|
-
import { appThemeSchema, appThemeRefusalBodySchema, canonicalOverlayHash, } from '@ggui-ai/protocol';
|
|
34
|
+
import { appThemeSchema, appThemeRefusalBodySchema, canonicalOverlayHash, appThemeWouldDropRefusalText, } from '@ggui-ai/protocol';
|
|
35
35
|
import { z } from 'zod';
|
|
36
36
|
import { defineHandler, handlerFailure, } from '../types.js';
|
|
37
37
|
import { resolveOwnerSub } from './identity.js';
|
|
@@ -101,6 +101,14 @@ function refusalText(admission) {
|
|
|
101
101
|
return 'invalid_app_config: the one-palette theme body is retired — send { overlays: { light, dark }, overlayHash, … }';
|
|
102
102
|
if ('overlayHash' in r)
|
|
103
103
|
return 'invalid_app_config: overlayHash does not match canonicalOverlayHash({ overlays, cssVariables, keyframes })';
|
|
104
|
+
if ('wouldDrop' in r) {
|
|
105
|
+
// ggui#1124 — the write would have DESTROYED stored members it did not
|
|
106
|
+
// carry. The wording is the protocol's ONE text, not this handler's:
|
|
107
|
+
// every door that refuses a destructive write says the same words, and
|
|
108
|
+
// the refusal names the compliance path so it is an instruction rather
|
|
109
|
+
// than a verdict (founder's ruling, 2026-09-16).
|
|
110
|
+
return `invalid_app_config: ${appThemeWouldDropRefusalText(r.wouldDrop)}`;
|
|
111
|
+
}
|
|
104
112
|
if ('unknown' in r)
|
|
105
113
|
return `invalid_app_config: keys outside the consumed-token manifest — light: [${r.unknown.light.join(', ')}] dark: [${r.unknown.dark.join(', ')}]`;
|
|
106
114
|
return `invalid_app_config: consumed tokens left uncovered — light: [${r.uncovered.light.join(', ')}] dark: [${r.uncovered.dark.join(', ')}]`;
|
package/dist/renders/consume.js
CHANGED
|
@@ -68,7 +68,7 @@ export function createGguiConsumeHandler(deps) {
|
|
|
68
68
|
name: 'ggui_consume',
|
|
69
69
|
title: 'Consume',
|
|
70
70
|
audience: ['agent'],
|
|
71
|
-
description: 'Long-poll for buffered events on a GguiSession. CALL THIS RIGHT AFTER EVERY `ggui_render` THAT RETURNS `nextStep.tool === "ggui_consume"` — that hint is your cue to start listening for the user\'s gesture. Keyed by sessionId (global UUID); app-scoped via ctx.appId. Inline long-poll: `timeout` is an integer in [0, 25] seconds (default 0 — an instant non-blocking drain; values outside reject INVALID_PARAMS — host MCP clients abort longer tool calls; pick 5-15s typical, 25 max). Returns `{events, status}` — each event carries `{type: "action", sessionId, intent, actionData, uiContext, actionId, firedAt}`: `actionData` is WHAT the user did, `uiContext` is the iframe-local snapshot of the contract\'s contextSpec slots AT THE MOMENT they did it. Both inform your reaction without a second round trip. Returns immediately when an action event arrives OR the render completes OR the timeout elapses. On timeout with no event you may re-call once, then end your turn — a later gesture arrives as a new user message. THE LOOP: when `events` is non-empty, REACT, then re-call `ggui_consume` for the next gesture; when `events` is empty, end your turn — a later gesture arrives as a new user message carrying its own consume directive. status:"expired" means the render is gone. IMPORTANT — the iframe state is independent of your backend state: after you mutate via domain tools (todo_toggle, cart_add, etc.), the UI still shows the OLD props until you call `ggui_amend`. If the events caused observable state changes the user is looking at, your reaction MUST include `ggui_amend` somewhere before re-consuming; otherwise the user sees stale props (the #1 wire compliance bug). Pure-info events that don\'t change displayed state can skip it. `ggui_amend` repaints the SAME card in place (the default move in this loop); `ggui_update` instead renders the state as a NEW card and advances the history number — reserve it for milestones worth a card in the transcript. HOSTS WITH PROGRESSIVE TOOL DISCOVERY (claude.ai-style connectors): if a call here errors with "tool not loaded yet" or "wrong parameter names," call `tool_search({query:"ggui_consume"})` once to warm the tool, then retry with the same args. DO NOT skip the consume — silent gesture drops are the worst protocol failure.',
|
|
71
|
+
description: 'Long-poll for buffered events on a GguiSession. CALL THIS RIGHT AFTER EVERY `ggui_render` THAT RETURNS `nextStep.tool === "ggui_consume"` — that hint is your cue to start listening for the user\'s gesture. Keyed by sessionId (global UUID); app-scoped via ctx.appId. Inline long-poll: `timeout` is an integer in [0, 25] seconds (default 0 — an instant non-blocking drain; values outside reject INVALID_PARAMS — host MCP clients abort longer tool calls; pick 5-15s typical, 25 max). Returns `{events, status}` — each event carries `{type: "action", sessionId, intent, actionData, uiContext, actionId, firedAt}`: `actionData` is WHAT the user did, `uiContext` is the iframe-local snapshot of the contract\'s contextSpec slots AT THE MOMENT they did it. Both inform your reaction without a second round trip. Returns immediately when an action event arrives OR the render completes OR the timeout elapses. On timeout with no event you may re-call once, then end your turn — a later gesture arrives as a new user message. THE LOOP: when `events` is non-empty, REACT, then re-call `ggui_consume` for the next gesture; when `events` is empty, end your turn — a later gesture arrives as a new user message carrying its own consume directive. status:"expired" means the render is gone. IMPORTANT — the iframe state is independent of your backend state: after you mutate via domain tools (todo_toggle, cart_add, etc.), the UI still shows the OLD props until you call `ggui_amend`. If the events caused observable state changes the user is looking at, your reaction MUST include `ggui_amend` somewhere before re-consuming; otherwise the user sees stale props (the #1 wire compliance bug). Pure-info events that don\'t change displayed state can skip it. `ggui_amend` repaints the SAME card in place (the default move in this loop); `ggui_update` instead renders the state as a NEW card and advances the history number — reserve it for milestones worth a card in the transcript. HOSTS WITH PROGRESSIVE TOOL DISCOVERY (claude.ai-style connectors): if a call here errors with "tool not loaded yet" or "wrong parameter names," call `tool_search({query:"ggui_consume"})` once to warm the tool, then retry with the same args. DO NOT skip the consume — silent gesture drops are the worst protocol failure. IDEMPOTENCY: treat the `actionId` on each entry as an idempotency key and apply a side-effecting action AT MOST ONCE per `actionId` — the same id delivered twice is one gesture replayed, never two. This holds for EVERY action, not only those a contract marks `oneShot`: a card served mid-rollout may be running a runtime that suppresses nothing, and keying on the marker would leave a hole exactly there. Two DISTINCT ids are two distinct gestures and both are real.',
|
|
72
72
|
inputSchema,
|
|
73
73
|
outputSchema,
|
|
74
74
|
async handler(rawInput, ctx) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ggui-ai/mcp-server-handlers",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.18.0",
|
|
4
4
|
"description": "MCP tool handler logic for the ggui protocol. Pure over @ggui-ai/mcp-server-core seams and consumed by @ggui-ai/mcp-server. Never imports AWS, HTTP transports, or CLI concerns.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ggui",
|
|
@@ -70,18 +70,18 @@
|
|
|
70
70
|
"dependencies": {
|
|
71
71
|
"canonicalize": "^2.0.0",
|
|
72
72
|
"zod": "^4.3.6",
|
|
73
|
-
"@ggui-ai/mcp-server-core": "0.
|
|
74
|
-
"@ggui-ai/negotiator": "0.
|
|
75
|
-
"@ggui-ai/
|
|
76
|
-
"@ggui-ai/
|
|
77
|
-
"@ggui-ai/ui-registry": "0.
|
|
73
|
+
"@ggui-ai/mcp-server-core": "0.18.0",
|
|
74
|
+
"@ggui-ai/negotiator": "0.18.0",
|
|
75
|
+
"@ggui-ai/ui-gen": "0.18.0",
|
|
76
|
+
"@ggui-ai/protocol": "0.18.0",
|
|
77
|
+
"@ggui-ai/ui-registry": "0.18.0"
|
|
78
78
|
},
|
|
79
79
|
"devDependencies": {
|
|
80
80
|
"@types/node": "^22.0.0",
|
|
81
81
|
"typescript": "^5.0.0",
|
|
82
82
|
"vitest": "^3.2.6",
|
|
83
|
-
"@ggui-ai/embedding-local": "0.
|
|
84
|
-
"@ggui-ai/protocol-conformance": "0.
|
|
83
|
+
"@ggui-ai/embedding-local": "0.18.0",
|
|
84
|
+
"@ggui-ai/protocol-conformance": "0.18.0"
|
|
85
85
|
},
|
|
86
86
|
"repository": {
|
|
87
87
|
"type": "git",
|