@guuey/mcp-apps-host 0.5.0 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/action.d.ts CHANGED
@@ -51,10 +51,33 @@ export type McpToolCallResult = {
51
51
  structuredContent?: McpToolStructuredContent;
52
52
  };
53
53
  /**
54
- * The runtime-action tools a card sandbox may relay — the client-side twin
55
- * of the server allowlist (defense in depth: the proxy enforces it again).
54
+ * The runtime tools a card sandbox may RELAY over `tools/call` — the
55
+ * client-side twin of the server allowlist (defense in depth: the proxy
56
+ * enforces it again). Exactly ggui's iframe-runtime surface, all declared
57
+ * `_meta.ui.visibility: ['app']` (never model-callable):
58
+ *
59
+ * - `ggui_runtime_submit_action` — the user's gesture (the SEMANTIC one);
60
+ * - `ggui_runtime_refresh_ws_token` — live-channel credential refresh
61
+ * (the wsToken TTL is 180 s; without the relay a view on SSE/polling
62
+ * dies at that mark — guuey#220);
63
+ * - `ggui_runtime_pull` — the host-relayed polling rung where the
64
+ * sandbox's own transports are blocked (bridge-pull, terminal rung).
65
+ *
66
+ * Two of these are transport plumbing whose arguments are opaque runtime
67
+ * state — see {@link UI_SEMANTIC_ACTION_TOOLS} for the ONLY set a host may
68
+ * treat as "the user did something".
56
69
  */
57
70
  export declare const UI_ACTION_TOOLS: ReadonlySet<string>;
71
+ /**
72
+ * The strict subset of {@link UI_ACTION_TOOLS} that carries a USER gesture —
73
+ * the only calls a host may project into user-facing affordances (composer
74
+ * staging, "the user selected X" copy, telemetry as intent). Every other
75
+ * relayed tool is runtime plumbing whose payload must NEVER reach the user
76
+ * verbatim (guuey#215/#218: a staged `sessionId …` was exactly that leak).
77
+ * A tool that is relayable is NOT thereby semantic; a host that widens
78
+ * this set is asserting the wire semantics of the new name.
79
+ */
80
+ export declare const UI_SEMANTIC_ACTION_TOOLS: ReadonlySet<string>;
58
81
  /** The in-band answer for anything the relay cannot (or will not) do. */
59
82
  export declare const UI_ACTION_UNAVAILABLE_TEXT = "This action isn't available right now.";
60
83
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"action.d.ts","sourceRoot":"","sources":["../src/action.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,oFAAoF;AACpF,MAAM,MAAM,kBAAkB,GAC1B;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACjD;IACE,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,CAC3C;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,GAChB;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CACnB,CAAC;CACH,CAAC;AAEN;;;;GAIG;AACH,MAAM,MAAM,wBAAwB,GAAG;IACrC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,OAAO,EAAE,kBAAkB,EAAE,CAAC;IAC9B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,iBAAiB,CAAC,EAAE,wBAAwB,CAAC;CAC9C,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,WAAW,CAAC,MAAM,CAE9C,CAAC;AAEH,yEAAyE;AACzE,eAAO,MAAM,0BAA0B,2CACG,CAAC;AAE3C;;;;GAIG;AACH,wBAAgB,yBAAyB,IAAI,iBAAiB,CAK7D;AAkCD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,iBAAiB,GAAG,SAAS,CAgB9E;AAED,iFAAiF;AACjF,MAAM,WAAW,0BAA0B;IACzC;;;;;OAKG;IACH,QAAQ,EAAE,CACR,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,wBAAwB,GAAG,SAAS,KACvC,OAAO,CAAC,OAAO,CAAC,CAAC;CACvB;AAED,uEAAuE;AACvE,MAAM,WAAW,eAAe;IAC9B,yEAAyE;IACzE,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,wBAAwB,CAAC;CACtC;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,0BAA0B,GAC/B,CAAC,OAAO,EAAE,eAAe,KAAK,OAAO,CAAC,iBAAiB,CAAC,CAa1D"}
1
+ {"version":3,"file":"action.d.ts","sourceRoot":"","sources":["../src/action.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,oFAAoF;AACpF,MAAM,MAAM,kBAAkB,GAC1B;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACjD;IACE,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,CAC3C;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,GAChB;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CACnB,CAAC;CACH,CAAC;AAEN;;;;GAIG;AACH,MAAM,MAAM,wBAAwB,GAAG;IACrC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,OAAO,EAAE,kBAAkB,EAAE,CAAC;IAC9B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,iBAAiB,CAAC,EAAE,wBAAwB,CAAC;CAC9C,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,eAAe,EAAE,WAAW,CAAC,MAAM,CAI9C,CAAC;AAEH;;;;;;;;GAQG;AACH,eAAO,MAAM,wBAAwB,EAAE,WAAW,CAAC,MAAM,CAEvD,CAAC;AAEH,yEAAyE;AACzE,eAAO,MAAM,0BAA0B,2CACG,CAAC;AAE3C;;;;GAIG;AACH,wBAAgB,yBAAyB,IAAI,iBAAiB,CAK7D;AAkCD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,iBAAiB,GAAG,SAAS,CAgB9E;AAED,iFAAiF;AACjF,MAAM,WAAW,0BAA0B;IACzC;;;;;OAKG;IACH,QAAQ,EAAE,CACR,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,wBAAwB,GAAG,SAAS,KACvC,OAAO,CAAC,OAAO,CAAC,CAAC;CACvB;AAED,uEAAuE;AACvE,MAAM,WAAW,eAAe;IAC9B,yEAAyE;IACzE,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,wBAAwB,CAAC;CACtC;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,0BAA0B,GAC/B,CAAC,OAAO,EAAE,eAAe,KAAK,OAAO,CAAC,iBAAiB,CAAC,CAa1D"}
package/dist/action.js CHANGED
@@ -13,11 +13,38 @@
13
13
  * it crosses into the sandbox.
14
14
  */
15
15
  /**
16
- * The runtime-action tools a card sandbox may relay — the client-side twin
17
- * of the server allowlist (defense in depth: the proxy enforces it again).
16
+ * The runtime tools a card sandbox may RELAY over `tools/call` — the
17
+ * client-side twin of the server allowlist (defense in depth: the proxy
18
+ * enforces it again). Exactly ggui's iframe-runtime surface, all declared
19
+ * `_meta.ui.visibility: ['app']` (never model-callable):
20
+ *
21
+ * - `ggui_runtime_submit_action` — the user's gesture (the SEMANTIC one);
22
+ * - `ggui_runtime_refresh_ws_token` — live-channel credential refresh
23
+ * (the wsToken TTL is 180 s; without the relay a view on SSE/polling
24
+ * dies at that mark — guuey#220);
25
+ * - `ggui_runtime_pull` — the host-relayed polling rung where the
26
+ * sandbox's own transports are blocked (bridge-pull, terminal rung).
27
+ *
28
+ * Two of these are transport plumbing whose arguments are opaque runtime
29
+ * state — see {@link UI_SEMANTIC_ACTION_TOOLS} for the ONLY set a host may
30
+ * treat as "the user did something".
18
31
  */
19
32
  export const UI_ACTION_TOOLS = new Set([
20
33
  "ggui_runtime_submit_action",
34
+ "ggui_runtime_refresh_ws_token",
35
+ "ggui_runtime_pull",
36
+ ]);
37
+ /**
38
+ * The strict subset of {@link UI_ACTION_TOOLS} that carries a USER gesture —
39
+ * the only calls a host may project into user-facing affordances (composer
40
+ * staging, "the user selected X" copy, telemetry as intent). Every other
41
+ * relayed tool is runtime plumbing whose payload must NEVER reach the user
42
+ * verbatim (guuey#215/#218: a staged `sessionId …` was exactly that leak).
43
+ * A tool that is relayable is NOT thereby semantic; a host that widens
44
+ * this set is asserting the wire semantics of the new name.
45
+ */
46
+ export const UI_SEMANTIC_ACTION_TOOLS = new Set([
47
+ "ggui_runtime_submit_action",
21
48
  ]);
22
49
  /** The in-band answer for anything the relay cannot (or will not) do. */
23
50
  export const UI_ACTION_UNAVAILABLE_TEXT = "This action isn't available right now.";
@@ -104,6 +104,24 @@ export declare function toolResultUiResource(block: Extract<AgBlock, {
104
104
  * are one producer of this shape.
105
105
  */
106
106
  export declare function uiLocator(uiData: JsonValue | undefined): string | undefined;
107
+ /**
108
+ * The `ui://` locator a `tool-result` block carries, from EITHER channel it
109
+ * can arrive on — the single seam every locator reader goes through.
110
+ *
111
+ * AgJSON §2.1 routes a tool result's `structuredContent` by its `_meta.ui`
112
+ * sibling: WITH the sibling it is surface data and the normalizer stamps
113
+ * `uiData`; WITHOUT it, it is model-channel data and lands in
114
+ * `structuredContent`. A producer that withholds `_meta` (ggui's non-prod
115
+ * posture; any plain-locator MCP server) therefore delivers a locator that
116
+ * is byte-identical in shape but lives one field over — reading `uiData`
117
+ * alone renders NOTHING for it (dark, not "expired"), and the persistence
118
+ * projector minted no placeholder row (the read plane 404s). `uiData` wins
119
+ * when both carry one (guuey#209 route-A finding).
120
+ */
121
+ export declare function toolResultLocator(block: {
122
+ uiData?: JsonValue;
123
+ structuredContent?: JsonValue;
124
+ }): string | undefined;
107
125
  export declare function snapshotUiResource(cardSnapshot: JsonValue): McpUiResourcePayload | undefined;
108
126
  /**
109
127
  * The resource's HTML: inline `text` wins; else base64-decode `blob`. `atob`
@@ -1 +1 @@
1
- {"version":3,"file":"block-ui.d.ts","sourceRoot":"","sources":["../src/block-ui.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAE/D;;;;;GAKG;AACH,MAAM,WAAW,oBAAoB;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,uEAAuE;AACvE,wBAAgB,YAAY,CAAC,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,CAAC,IAAI;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAExF;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,oBAAoB,GAAG,SAAS,CAU5F;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,oBAAoB,GAAG,SAAS,CAK5F;AAED;;;;;;GAMG;AACH,wBAAgB,4BAA4B,CAC1C,GAAG,EAAE,SAAS,GAAG,SAAS,GACzB,oBAAoB,GAAG,SAAS,CAMlC;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,GAAG,oBAAoB,GAAG,SAAS,CAyBlF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,OAAO,CAAC,OAAO,EAAE;IAAE,IAAI,EAAE,aAAa,CAAA;CAAE,CAAC,GAC/C,oBAAoB,GAAG,SAAS,CAUlC;AAED;;;;;;;;;;;GAWG;AACH;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAI3E;AAED,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,SAAS,GAAG,oBAAoB,GAAG,SAAS,CAU5F;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,oBAAoB,GAAG,MAAM,GAAG,SAAS,CAU/E"}
1
+ {"version":3,"file":"block-ui.d.ts","sourceRoot":"","sources":["../src/block-ui.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAE/D;;;;;GAKG;AACH,MAAM,WAAW,oBAAoB;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,uEAAuE;AACvE,wBAAgB,YAAY,CAAC,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,CAAC,IAAI;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAExF;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,oBAAoB,GAAG,SAAS,CAU5F;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,oBAAoB,GAAG,SAAS,CAK5F;AAED;;;;;;GAMG;AACH,wBAAgB,4BAA4B,CAC1C,GAAG,EAAE,SAAS,GAAG,SAAS,GACzB,oBAAoB,GAAG,SAAS,CAMlC;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,GAAG,oBAAoB,GAAG,SAAS,CAyBlF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,OAAO,CAAC,OAAO,EAAE;IAAE,IAAI,EAAE,aAAa,CAAA;CAAE,CAAC,GAC/C,oBAAoB,GAAG,SAAS,CAUlC;AAED;;;;;;;;;;;GAWG;AACH;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAI3E;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE;IACvC,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,iBAAiB,CAAC,EAAE,SAAS,CAAC;CAC/B,GAAG,MAAM,GAAG,SAAS,CAErB;AAED,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,SAAS,GAAG,oBAAoB,GAAG,SAAS,CAU5F;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,oBAAoB,GAAG,MAAM,GAAG,SAAS,CAU/E"}
package/dist/block-ui.js CHANGED
@@ -140,6 +140,23 @@ export function uiLocator(uiData) {
140
140
  const uri = uiData.resourceUri;
141
141
  return typeof uri === "string" && uri.startsWith("ui://") ? uri : undefined;
142
142
  }
143
+ /**
144
+ * The `ui://` locator a `tool-result` block carries, from EITHER channel it
145
+ * can arrive on — the single seam every locator reader goes through.
146
+ *
147
+ * AgJSON §2.1 routes a tool result's `structuredContent` by its `_meta.ui`
148
+ * sibling: WITH the sibling it is surface data and the normalizer stamps
149
+ * `uiData`; WITHOUT it, it is model-channel data and lands in
150
+ * `structuredContent`. A producer that withholds `_meta` (ggui's non-prod
151
+ * posture; any plain-locator MCP server) therefore delivers a locator that
152
+ * is byte-identical in shape but lives one field over — reading `uiData`
153
+ * alone renders NOTHING for it (dark, not "expired"), and the persistence
154
+ * projector minted no placeholder row (the read plane 404s). `uiData` wins
155
+ * when both carry one (guuey#209 route-A finding).
156
+ */
157
+ export function toolResultLocator(block) {
158
+ return uiLocator(block.uiData) ?? uiLocator(block.structuredContent);
159
+ }
143
160
  export function snapshotUiResource(cardSnapshot) {
144
161
  if (!isJsonObject(cardSnapshot))
145
162
  return undefined;
@@ -44,7 +44,9 @@ export type ViewMountChannel = "inline" | "ggui" | "locator";
44
44
  * `"ggui"` — a shell that boots the ggui runtime from a platform-pinned
45
45
  * origin, and therefore needs a host page whose CSP allows that origin.
46
46
  * `"locator"` — no mount material in hand, only the durable `ui://`
47
- * identity (guuey#122): the host resolves it with a fresh, authenticated
47
+ * identity (guuey#122) read from `uiData` OR, for a producer that
48
+ * withheld `_meta` (AgJSON §2.1 then routes it to `structuredContent`),
49
+ * from `structuredContent` (guuey#209): the host resolves it with a fresh, authenticated
48
50
  * `resources/read` of the uri ({@link UiResourceReader}) — the spec-consistent
49
51
  * template fetch, vendor-neutral. (The spec defers persistence/restoration
50
52
  * itself; a full remount additionally owes the View `ui/notifications/tool-input`
@@ -65,7 +67,7 @@ export interface ResolvedViewMount {
65
67
  /** The durable-identity arm: no mount material, only the uri to re-fetch. */
66
68
  export interface LocatorViewMount {
67
69
  channel: "locator";
68
- /** The persisted `uiData.resourceUri` (`ui://` scheme) to re-fetch. */
70
+ /** The durable `ui://` locator to re-fetch (`uiData.resourceUri`, else `structuredContent.resourceUri`). */
69
71
  resourceUri: string;
70
72
  }
71
73
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"card-mount.d.ts","sourceRoot":"","sources":["../src/card-mount.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,OAAO,EAAuD,KAAK,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAE/G,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAW/D,8EAA8E;AAC9E,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,CAAC;AAE7D;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,SAAS,GAAG,iBAAiB,GAAG,gBAAgB,CAAC;AAE7D;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,QAAQ,GAAG,MAAM,CAAC;IAC3B,+EAA+E;IAC/E,QAAQ,EAAE,oBAAoB,CAAC;CAChC;AAED,6EAA6E;AAC7E,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,SAAS,CAAC;IACnB,uEAAuE;IACvE,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC,CAAC;AAEvF;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,OAAO,CAAC,OAAO,EAAE;IAAE,IAAI,EAAE,aAAa,CAAA;CAAE,CAAC,GAC/C,SAAS,GAAG,SAAS,CAkBvB;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,CAUhF;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,SAAS,GAAG,SAAS,EAC5B,MAAM,CAAC,EAAE,gBAAgB,GACxB,OAAO,CAAC,iBAAiB,GAAG,SAAS,CAAC,CAKxC"}
1
+ {"version":3,"file":"card-mount.d.ts","sourceRoot":"","sources":["../src/card-mount.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,OAAO,EAA+D,KAAK,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAEvH,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAW/D,8EAA8E;AAC9E,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,CAAC;AAE7D;;;;;;;;;;;;;;;GAeG;AACH,MAAM,MAAM,SAAS,GAAG,iBAAiB,GAAG,gBAAgB,CAAC;AAE7D;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,QAAQ,GAAG,MAAM,CAAC;IAC3B,+EAA+E;IAC/E,QAAQ,EAAE,oBAAoB,CAAC;CAChC;AAED,6EAA6E;AAC7E,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,SAAS,CAAC;IACnB,4GAA4G;IAC5G,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC,CAAC;AAEvF;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,OAAO,CAAC,OAAO,EAAE;IAAE,IAAI,EAAE,aAAa,CAAA;CAAE,CAAC,GAC/C,SAAS,GAAG,SAAS,CAoBvB;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,CAUhF;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,SAAS,GAAG,SAAS,EAC5B,MAAM,CAAC,EAAE,gBAAgB,GACxB,OAAO,CAAC,iBAAiB,GAAG,SAAS,CAAC,CAKxC"}
@@ -33,7 +33,7 @@
33
33
  * keeps that one narrowing in one place — the alternative was for every host
34
34
  * to re-run `toolResultGguiRender` beside this call and ask again.
35
35
  */
36
- import { snapshotUiResource, toolResultUiResource, uiLocator } from "./block-ui.js";
36
+ import { snapshotUiResource, toolResultLocator, toolResultUiResource } from "./block-ui.js";
37
37
  import { GGUI_RENDER_META_KEY, gguiRenderResource, toolResultGguiRender } from "./ggui-render.js";
38
38
  /** Does the block's `_meta` carry the ggui render key at all (valid or not)? */
39
39
  function blockCarriesGguiMetaKey(block) {
@@ -54,14 +54,16 @@ export function toolResultViewMount(block) {
54
54
  if (resource)
55
55
  return { resource, channel: "ggui" };
56
56
  // A live locator whose mount material didn't reach us (a fold that
57
- // dropped `_meta`): re-fetch works on live turns too — the resource is
58
- // freshly minted (guuey#122). One diagnostic when `_meta` DID carry the
57
+ // dropped `_meta`, or a producer that never sent it — the locator then
58
+ // rides `structuredContent`, see `toolResultLocator`): re-fetch works on
59
+ // live turns too — the resource is freshly minted (guuey#122). One
60
+ // diagnostic when `_meta` DID carry the
59
61
  // vendor key but failed validation — a producer bug would otherwise be
60
62
  // indistinguishable from a meta-less fold (blank UI, zero errors).
61
63
  if (ggui && !ggui.bootstrap && blockCarriesGguiMetaKey(block)) {
62
64
  console.warn(`mcp-apps-host: tool result ${block.toolCallId} carries a malformed ggui render bootstrap — degrading to the locator channel`);
63
65
  }
64
- const locator = uiLocator(block.uiData);
66
+ const locator = toolResultLocator(block);
65
67
  return locator !== undefined ? { channel: "locator", resourceUri: locator } : undefined;
66
68
  }
67
69
  /**
@@ -83,7 +85,7 @@ export function snapshotViewMount(cardSnapshot) {
83
85
  continue;
84
86
  if (block.type !== "tool-result")
85
87
  continue;
86
- const locator = uiLocator(block.uiData);
88
+ const locator = toolResultLocator(block);
87
89
  if (locator !== undefined)
88
90
  return { channel: "locator", resourceUri: locator };
89
91
  }
package/dist/index.d.ts CHANGED
@@ -3,12 +3,12 @@
3
3
  * narrowing, ui:// locator rehydration, sandbox-trust channels. See README +
4
4
  * the conformance map (guuey#123).
5
5
  */
6
- export { asResourcePayload, asUiResource, blockUiResource, isJsonObject, resourceHtml, scanProviderRawForUiResource, snapshotUiResource, toolResultUiResource, uiLocator, type McpUiResourcePayload, } from "./block-ui.js";
6
+ export { asResourcePayload, asUiResource, blockUiResource, isJsonObject, resourceHtml, scanProviderRawForUiResource, snapshotUiResource, toolResultLocator, toolResultUiResource, uiLocator, type McpUiResourcePayload, } from "./block-ui.js";
7
7
  export { asGguiRender, asGguiRenderBootstrap, blockGguiRender, gguiRenderResource, gguiShellHtml, toolResultGguiRender, GGUI_RENDER_META_KEY, type GguiRenderBootstrap, type GguiRenderDescriptor, type GguiShellHtmlOptions, } from "./ggui-render.js";
8
8
  export { resolveViewMount, snapshotViewMount, toolResultViewMount, type LocatorViewMount, type ResolvedViewMount, type UiResourceReader, type ViewMount, type ViewMountChannel, } from "./card-mount.js";
9
9
  export { createMcpUiResourceReader, uiResourceChannel, type CreateMcpUiResourceReaderDeps, type McpResourceReadResult, } from "./reader.js";
10
- export { asToolCallResult, createMcpUiActionRelay, unavailableToolCallResult, UI_ACTION_TOOLS, UI_ACTION_UNAVAILABLE_TEXT, type CreateMcpUiActionRelayDeps, type McpToolCallContent, type McpToolCallResult, type McpToolStructuredContent, type UiActionRequest, } from "./action.js";
11
- export { initializeResult, initialViewHostState, teardownMessage, toolCallResponse, TOOLS_CALL_METHOD, viewHostElapsed, viewHostReceive, type ViewHostBehavior, type ViewHostEffect, type ViewHostOutbound, type ViewHostPhase, type ViewHostInfo, type ViewHostState, type ViewHostTransition, type ViewRequestId, } from "./view-host-protocol.js";
10
+ export { asToolCallResult, createMcpUiActionRelay, unavailableToolCallResult, UI_ACTION_TOOLS, UI_ACTION_UNAVAILABLE_TEXT, UI_SEMANTIC_ACTION_TOOLS, type CreateMcpUiActionRelayDeps, type McpToolCallContent, type McpToolCallResult, type McpToolStructuredContent, type UiActionRequest, } from "./action.js";
11
+ export { initializeResult, initialViewHostState, resourceReadResponse, RESOURCES_READ_METHOD, teardownMessage, toolCallResponse, TOOLS_CALL_METHOD, viewHostElapsed, viewHostReceive, type ViewHostBehavior, type ViewHostEffect, type ViewHostOutbound, type ViewHostPhase, type ViewHostInfo, type ViewHostState, type ViewHostTransition, type ViewRequestId, } from "./view-host-protocol.js";
12
12
  export { attachViewHost, viewDocumentHtml, type AttachViewHostConfig, type ViewFrameLike, type ViewHostEvents, } from "./view-host.js";
13
13
  export { attachSandboxPageDelivery, isSandboxProxyReady, SANDBOX_PROXY_READY_METHOD, SANDBOX_RESOURCE_READY_METHOD, type SandboxPageDeliveryConfig, } from "./sandbox-page.js";
14
14
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EACL,iBAAiB,EACjB,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,4BAA4B,EAC5B,kBAAkB,EAClB,oBAAoB,EACpB,SAAS,EACT,KAAK,oBAAoB,GAC1B,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,YAAY,EACZ,qBAAqB,EACrB,eAAe,EACf,kBAAkB,EAClB,aAAa,EACb,oBAAoB,EACpB,oBAAoB,EACpB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,GAC1B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EACnB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,SAAS,EACd,KAAK,gBAAgB,GACtB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,yBAAyB,EACzB,iBAAiB,EACjB,KAAK,6BAA6B,EAClC,KAAK,qBAAqB,GAC3B,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,gBAAgB,EAChB,sBAAsB,EACtB,yBAAyB,EACzB,eAAe,EACf,0BAA0B,EAC1B,KAAK,0BAA0B,EAC/B,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,wBAAwB,EAC7B,KAAK,eAAe,GACrB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,eAAe,EACf,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,eAAe,EACf,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACvB,KAAK,aAAa,GACnB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,KAAK,oBAAoB,EACzB,KAAK,aAAa,EAClB,KAAK,cAAc,GACpB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,yBAAyB,EACzB,mBAAmB,EACnB,0BAA0B,EAC1B,6BAA6B,EAC7B,KAAK,yBAAyB,GAC/B,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EACL,iBAAiB,EACjB,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,4BAA4B,EAC5B,kBAAkB,EAClB,iBAAiB,EACjB,oBAAoB,EACpB,SAAS,EACT,KAAK,oBAAoB,GAC1B,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,YAAY,EACZ,qBAAqB,EACrB,eAAe,EACf,kBAAkB,EAClB,aAAa,EACb,oBAAoB,EACpB,oBAAoB,EACpB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,GAC1B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EACnB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,SAAS,EACd,KAAK,gBAAgB,GACtB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,yBAAyB,EACzB,iBAAiB,EACjB,KAAK,6BAA6B,EAClC,KAAK,qBAAqB,GAC3B,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,gBAAgB,EAChB,sBAAsB,EACtB,yBAAyB,EACzB,eAAe,EACf,0BAA0B,EAC1B,wBAAwB,EACxB,KAAK,0BAA0B,EAC/B,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,wBAAwB,EAC7B,KAAK,eAAe,GACrB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,oBAAoB,EACpB,qBAAqB,EACrB,eAAe,EACf,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,eAAe,EACf,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACvB,KAAK,aAAa,GACnB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,KAAK,oBAAoB,EACzB,KAAK,aAAa,EAClB,KAAK,cAAc,GACpB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,yBAAyB,EACzB,mBAAmB,EACnB,0BAA0B,EAC1B,6BAA6B,EAC7B,KAAK,yBAAyB,GAC/B,MAAM,mBAAmB,CAAC"}
package/dist/index.js CHANGED
@@ -3,11 +3,11 @@
3
3
  * narrowing, ui:// locator rehydration, sandbox-trust channels. See README +
4
4
  * the conformance map (guuey#123).
5
5
  */
6
- export { asResourcePayload, asUiResource, blockUiResource, isJsonObject, resourceHtml, scanProviderRawForUiResource, snapshotUiResource, toolResultUiResource, uiLocator, } from "./block-ui.js";
6
+ export { asResourcePayload, asUiResource, blockUiResource, isJsonObject, resourceHtml, scanProviderRawForUiResource, snapshotUiResource, toolResultLocator, toolResultUiResource, uiLocator, } from "./block-ui.js";
7
7
  export { asGguiRender, asGguiRenderBootstrap, blockGguiRender, gguiRenderResource, gguiShellHtml, toolResultGguiRender, GGUI_RENDER_META_KEY, } from "./ggui-render.js";
8
8
  export { resolveViewMount, snapshotViewMount, toolResultViewMount, } from "./card-mount.js";
9
9
  export { createMcpUiResourceReader, uiResourceChannel, } from "./reader.js";
10
- export { asToolCallResult, createMcpUiActionRelay, unavailableToolCallResult, UI_ACTION_TOOLS, UI_ACTION_UNAVAILABLE_TEXT, } from "./action.js";
11
- export { initializeResult, initialViewHostState, teardownMessage, toolCallResponse, TOOLS_CALL_METHOD, viewHostElapsed, viewHostReceive, } from "./view-host-protocol.js";
10
+ export { asToolCallResult, createMcpUiActionRelay, unavailableToolCallResult, UI_ACTION_TOOLS, UI_ACTION_UNAVAILABLE_TEXT, UI_SEMANTIC_ACTION_TOOLS, } from "./action.js";
11
+ export { initializeResult, initialViewHostState, resourceReadResponse, RESOURCES_READ_METHOD, teardownMessage, toolCallResponse, TOOLS_CALL_METHOD, viewHostElapsed, viewHostReceive, } from "./view-host-protocol.js";
12
12
  export { attachViewHost, viewDocumentHtml, } from "./view-host.js";
13
13
  export { attachSandboxPageDelivery, isSandboxProxyReady, SANDBOX_PROXY_READY_METHOD, SANDBOX_RESOURCE_READY_METHOD, } from "./sandbox-page.js";
@@ -5,5 +5,5 @@
5
5
  * graph through the barrel (which re-exports the ggui render arm until its
6
6
  * retirement — conformance-map step 4).
7
7
  */
8
- export { asResourcePayload, asUiResource, blockUiResource, isJsonObject, resourceHtml, scanProviderRawForUiResource, snapshotUiResource, toolResultUiResource, uiLocator, type McpUiResourcePayload, } from "./block-ui.js";
8
+ export { asResourcePayload, asUiResource, blockUiResource, isJsonObject, resourceHtml, scanProviderRawForUiResource, snapshotUiResource, toolResultLocator, toolResultUiResource, uiLocator, type McpUiResourcePayload, } from "./block-ui.js";
9
9
  //# sourceMappingURL=narrowing.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"narrowing.d.ts","sourceRoot":"","sources":["../src/narrowing.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EACL,iBAAiB,EACjB,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,4BAA4B,EAC5B,kBAAkB,EAClB,oBAAoB,EACpB,SAAS,EACT,KAAK,oBAAoB,GAC1B,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"narrowing.d.ts","sourceRoot":"","sources":["../src/narrowing.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EACL,iBAAiB,EACjB,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,4BAA4B,EAC5B,kBAAkB,EAClB,iBAAiB,EACjB,oBAAoB,EACpB,SAAS,EACT,KAAK,oBAAoB,GAC1B,MAAM,eAAe,CAAC"}
package/dist/narrowing.js CHANGED
@@ -5,4 +5,4 @@
5
5
  * graph through the barrel (which re-exports the ggui render arm until its
6
6
  * retirement — conformance-map step 4).
7
7
  */
8
- export { asResourcePayload, asUiResource, blockUiResource, isJsonObject, resourceHtml, scanProviderRawForUiResource, snapshotUiResource, toolResultUiResource, uiLocator, } from "./block-ui.js";
8
+ export { asResourcePayload, asUiResource, blockUiResource, isJsonObject, resourceHtml, scanProviderRawForUiResource, snapshotUiResource, toolResultLocator, toolResultUiResource, uiLocator, } from "./block-ui.js";
package/dist/react.d.ts CHANGED
@@ -41,7 +41,7 @@ export type { AttachViewHostConfig, ViewFrameLike, ViewHostEvents } from "./view
41
41
  export { attachSandboxPageDelivery, isSandboxProxyReady, SANDBOX_PROXY_READY_METHOD, SANDBOX_RESOURCE_READY_METHOD, type SandboxPageDeliveryConfig, } from "./sandbox-page.js";
42
42
  export type { ViewHostPhase } from "./view-host-protocol.js";
43
43
  export type { ResolvedViewMount, ViewMount, ViewMountChannel } from "./card-mount.js";
44
- export interface GuueyViewProps extends Pick<AttachViewHostConfig, "hostCapabilities" | "hostInfo" | "hostContext" | "onCallTool" | "negotiationTimeoutMs"> {
44
+ export interface GuueyViewProps extends Pick<AttachViewHostConfig, "hostCapabilities" | "hostInfo" | "hostContext" | "onCallTool" | "onReadResource" | "onSizeChanged" | "negotiationTimeoutMs"> {
45
45
  /** The resolved card to mount (see `toolResultViewMount`/`resolveViewMount`). */
46
46
  mount: ResolvedViewMount;
47
47
  /**
@@ -59,8 +59,23 @@ export interface GuueyViewProps extends Pick<AttachViewHostConfig, "hostCapabili
59
59
  * for its CSP + referrer checks to mean anything), never agent HTML.
60
60
  * The page must be a genuinely different origin; a same-origin URL is
61
61
  * refused with a labeled state, never mounted.
62
+ *
63
+ * `null` (as opposed to absent) means the two-origin mount is REQUIRED
64
+ * by the embedder's posture but no page is configured — the mount is
65
+ * refused with the same labeled state, and srcdoc is NEVER fallen back
66
+ * to (falling back would silently trade the caller's egress confinement
67
+ * for the page's CSP; the widget/Studio convergence posture).
62
68
  */
63
- sandboxPageUrl?: string;
69
+ sandboxPageUrl?: string | null;
70
+ /**
71
+ * Apply the view's own size reports (`ui/notifications/size-changed` —
72
+ * spec surface) to the frame: a reported HEIGHT becomes the frame's
73
+ * height; width stays the container's (a transcript column owns its
74
+ * width). Default OFF — the primitive changes nothing for existing
75
+ * hosts; a caller's {@link AttachViewHostConfig.onSizeChanged} observer
76
+ * fires either way.
77
+ */
78
+ autoResize?: boolean;
64
79
  /**
65
80
  * Sandbox flags appended to the safe default (`allow-scripts`). Every
66
81
  * entry widens what agent-generated HTML may do — `allow-same-origin`
@@ -1 +1 @@
1
- {"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../src/react.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,OAAO,EAAwC,KAAK,aAAa,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACjG,OAAO,EAAoC,KAAK,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAE7F,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEzD,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClE,YAAY,EAAE,oBAAoB,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAC1F,OAAO,EACL,yBAAyB,EACzB,mBAAmB,EACnB,0BAA0B,EAC1B,6BAA6B,EAC7B,KAAK,yBAAyB,GAC/B,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC7D,YAAY,EAAE,iBAAiB,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAKtF,MAAM,WAAW,cACf,SAAQ,IAAI,CACV,oBAAoB,EACpB,kBAAkB,GAAG,UAAU,GAAG,aAAa,GAAG,YAAY,GAAG,sBAAsB,CACxF;IACD,iFAAiF;IACjF,KAAK,EAAE,iBAAiB,CAAC;IACzB;;;;;;;;;;;;;;;OAeG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;;OAMG;IACH,0BAA0B,CAAC,EAAE,MAAM,EAAE,CAAC;IACtC,8EAA8E;IAC9E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wDAAwD;IACxD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,6EAA6E;IAC7E,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IAC/C;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,SAAS,CAAC;CACpD;AA+BD;;;GAGG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,SAAS,CAiI1D"}
1
+ {"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../src/react.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,OAAO,EAAwC,KAAK,aAAa,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACjG,OAAO,EAAoC,KAAK,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAE7F,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEzD,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClE,YAAY,EAAE,oBAAoB,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAC1F,OAAO,EACL,yBAAyB,EACzB,mBAAmB,EACnB,0BAA0B,EAC1B,6BAA6B,EAC7B,KAAK,yBAAyB,GAC/B,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC7D,YAAY,EAAE,iBAAiB,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAKtF,MAAM,WAAW,cACf,SAAQ,IAAI,CACV,oBAAoB,EAClB,kBAAkB,GAClB,UAAU,GACV,aAAa,GACb,YAAY,GACZ,gBAAgB,GAChB,eAAe,GACf,sBAAsB,CACzB;IACD,iFAAiF;IACjF,KAAK,EAAE,iBAAiB,CAAC;IACzB;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;;;OAMG;IACH,0BAA0B,CAAC,EAAE,MAAM,EAAE,CAAC;IACtC,8EAA8E;IAC9E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wDAAwD;IACxD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,6EAA6E;IAC7E,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IAC/C;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,SAAS,CAAC;CACpD;AA+BD;;;GAGG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,SAAS,CA0J1D"}
package/dist/react.js CHANGED
@@ -68,18 +68,23 @@ function defaultStatus(phase, channel) {
68
68
  * docblock for the sandbox and state contracts.
69
69
  */
70
70
  export function GuueyView(props) {
71
- const { mount, sandboxPageUrl, dangerouslyAddSandboxFlags, allow, title, className, style, onPhaseChange, renderStatus, ...hostConfig } = props;
71
+ const { mount, sandboxPageUrl, autoResize, dangerouslyAddSandboxFlags, allow, title, className, style, onPhaseChange, renderStatus, ...hostConfig } = props;
72
72
  const frameRef = useRef(null);
73
73
  const [phase, setPhase] = useState("negotiating");
74
+ // The view's own size report, applied only under `autoResize`.
75
+ const [reportedHeight, setReportedHeight] = useState(undefined);
74
76
  const html = viewDocumentHtml(mount.resource);
75
77
  // Vet the sandbox page once per URL. Same-origin is REFUSED (the widget's
76
78
  // ResourceMount precedent, generalized): the whole point of the page is
77
79
  // being a different origin — same-origin would hand the relay page (and
78
80
  // through `allow-same-origin`, everything it can reach) the embedder's
79
- // own origin.
81
+ // own origin. `null` — page mode required but unconfigured — refuses the
82
+ // same way: srcdoc is never a silent fallback for a confinement posture.
80
83
  const sandboxPage = useMemo(() => {
81
84
  if (sandboxPageUrl === undefined)
82
85
  return undefined;
86
+ if (sandboxPageUrl === null)
87
+ return "refused";
83
88
  let url;
84
89
  try {
85
90
  url = new URL(sandboxPageUrl);
@@ -95,13 +100,14 @@ export function GuueyView(props) {
95
100
  // The attachment is keyed to the mounted DOCUMENT, not to every render's
96
101
  // fresh callback identities — host config rides a ref so the effect's
97
102
  // dependency list is honestly just the document identity.
98
- const latest = useRef({ hostConfig, onPhaseChange, dangerouslyAddSandboxFlags });
99
- latest.current = { hostConfig, onPhaseChange, dangerouslyAddSandboxFlags };
103
+ const latest = useRef({ hostConfig, onPhaseChange, dangerouslyAddSandboxFlags, autoResize });
104
+ latest.current = { hostConfig, onPhaseChange, dangerouslyAddSandboxFlags, autoResize };
100
105
  useEffect(() => {
101
106
  // Keyed to the same identity the frame is (the resource uri): a new
102
107
  // document boots fresh, and the previous negotiation's phase must not
103
- // paper over it.
108
+ // paper over it — nor must the previous document's reported size.
104
109
  setPhase("negotiating");
110
+ setReportedHeight(undefined);
105
111
  const frame = frameRef.current;
106
112
  if (frame === null || html === undefined)
107
113
  return;
@@ -115,6 +121,12 @@ export function GuueyView(props) {
115
121
  setPhase(next);
116
122
  latest.current.onPhaseChange?.(next);
117
123
  },
124
+ onSizeChanged: (size) => {
125
+ if (latest.current.autoResize === true && size.height !== undefined) {
126
+ setReportedHeight(size.height);
127
+ }
128
+ latest.current.hostConfig.onSizeChanged?.(size);
129
+ },
118
130
  });
119
131
  if (page === undefined)
120
132
  return detachHost;
@@ -141,9 +153,14 @@ export function GuueyView(props) {
141
153
  return (_jsx("div", { className: className, style: { position: "relative", ...style }, children: _jsx("p", { role: "alert", style: { ...statusLineStyle, opacity: 1, pointerEvents: "auto" }, children: "This view could not be displayed \u2014 its resource carries no document." }) }));
142
154
  }
143
155
  if (sandboxPageUrl !== undefined && page === undefined) {
144
- // A malformed or SAME-ORIGIN sandbox page is a configuration state, not
145
- // a property of the card — refused, labeled, never mounted.
146
- return (_jsx("div", { className: className, style: { position: "relative", ...style }, children: _jsx("p", { role: "alert", style: { ...statusLineStyle, opacity: 1, pointerEvents: "auto" }, children: "Interactive view unavailable \u2014 the sandbox page is not usable from this origin." }) }));
156
+ // A missing (null), malformed, or SAME-ORIGIN sandbox page is a
157
+ // configuration state, not a property of the card — refused, labeled,
158
+ // never mounted, and never silently downgraded to srcdoc. The copy
159
+ // names the configuration cause (an operator can act on it) without
160
+ // ever printing the offending URL.
161
+ return (_jsx("div", { className: className, style: { position: "relative", ...style }, children: _jsx("p", { role: "alert", style: { ...statusLineStyle, opacity: 1, pointerEvents: "auto" }, children: sandboxPageUrl === null
162
+ ? "Interactive view unavailable — no sandbox page is configured."
163
+ : "Interactive view unavailable — the sandbox page is not usable from this origin." }) }));
147
164
  }
148
165
  return (_jsxs("div", { className: className, style: { position: "relative", ...style }, children: [_jsx("iframe", { ref: frameRef, ...(page !== undefined ? { src: page.href } : { srcDoc: html }), title: title ?? DEFAULT_TITLE,
149
166
  // srcdoc mode: the INVARIANT — agent HTML in an opaque origin, extra
@@ -154,5 +171,14 @@ export function GuueyView(props) {
154
171
  // and the caller's extra flags travel to THAT frame via the relay.
155
172
  sandbox: page !== undefined
156
173
  ? "allow-scripts allow-same-origin allow-forms"
157
- : ["allow-scripts", ...(dangerouslyAddSandboxFlags ?? [])].join(" "), allow: allow ?? "clipboard-write", style: { display: "block", width: "100%", height: "100%", border: 0 } }, `${page?.href ?? "srcdoc"}::${mount.resource.uri}`), renderStatus !== undefined ? renderStatus(phase) : defaultStatus(phase, mount.channel)] }));
174
+ : ["allow-scripts", ...(dangerouslyAddSandboxFlags ?? [])].join(" "), allow: allow ?? "clipboard-write",
175
+ // Under `autoResize`, the view's own height report wins over the
176
+ // fill-the-container default (width stays the container's — a
177
+ // transcript column owns its width).
178
+ style: {
179
+ display: "block",
180
+ width: "100%",
181
+ height: autoResize === true && reportedHeight !== undefined ? reportedHeight : "100%",
182
+ border: 0,
183
+ } }, `${page?.href ?? "srcdoc"}::${mount.resource.uri}`), renderStatus !== undefined ? renderStatus(phase) : defaultStatus(phase, mount.channel)] }));
158
184
  }
@@ -32,6 +32,7 @@
32
32
  */
33
33
  import { type McpUiHostCapabilities, type McpUiHostContext, type McpUiInitializeResult } from "@modelcontextprotocol/ext-apps";
34
34
  import type { McpToolStructuredContent } from "./action.js";
35
+ import type { McpResourceReadResult } from "./reader.js";
35
36
  /**
36
37
  * The host identity in the initialize result — structurally the spec's
37
38
  * `Implementation` (which the ext-apps root does not re-export), narrowed
@@ -43,6 +44,15 @@ export interface ViewHostInfo {
43
44
  }
44
45
  /** The standard MCP method a view uses to reach host-proxied tools. */
45
46
  export declare const TOOLS_CALL_METHOD = "tools/call";
47
+ /**
48
+ * The standard MCP method a view uses to read host-proxied resources —
49
+ * `ReadResourceRequest` in the spec's App→Host request union
50
+ * (`@modelcontextprotocol/ext-apps` `AppRequest`). A local constant, same
51
+ * as {@link TOOLS_CALL_METHOD}: the string is MCP-core vocabulary the
52
+ * ext-apps root does not re-export, and this package deliberately carries
53
+ * no `@modelcontextprotocol/sdk` dependency.
54
+ */
55
+ export declare const RESOURCES_READ_METHOD = "resources/read";
46
56
  /** A JSON-RPC id as the wire allows it. */
47
57
  export type ViewRequestId = number | string;
48
58
  /** The messages this host posts INTO the view frame. */
@@ -105,6 +115,31 @@ export type ViewHostEffect = {
105
115
  id: ViewRequestId;
106
116
  name: string;
107
117
  arguments?: McpToolStructuredContent;
118
+ } | {
119
+ /**
120
+ * A `resources/read` the config accepted for relaying (spec surface:
121
+ * `ReadResourceRequest` rides the App→Host union, and the matching
122
+ * advertisement is `hostCapabilities.serverResources`). The glue runs
123
+ * the read hook and posts {@link resourceReadResponse}. Only emitted
124
+ * when {@link ViewHostBehavior.resourceRelay} is true — unwired, the
125
+ * machine refuses in-band like every other unsupported request.
126
+ */
127
+ kind: "relay-resource-read";
128
+ id: ViewRequestId;
129
+ uri: string;
130
+ } | {
131
+ /**
132
+ * The view reported its content size (`ui/notifications/size-changed`
133
+ * — spec notification, App → Host). At least one of the two fields is
134
+ * a finite number; a notification carrying neither is consumed
135
+ * silently instead. The glue forwards this to the embedder
136
+ * ({@link AttachViewHostConfig.onSizeChanged} in `view-host.ts`) —
137
+ * whether/how to resize the frame is the embedder's layout decision,
138
+ * never the machine's.
139
+ */
140
+ kind: "size-changed";
141
+ width?: number;
142
+ height?: number;
108
143
  };
109
144
  /**
110
145
  * The host identity/behavior the machine answers with. Everything here is
@@ -125,6 +160,8 @@ export interface ViewHostBehavior {
125
160
  hostContext: McpUiHostContext;
126
161
  /** Whether a `tools/call` relay hook is wired (see `view-host.ts`). */
127
162
  toolRelay: boolean;
163
+ /** Whether a `resources/read` relay hook is wired (see `view-host.ts`). */
164
+ resourceRelay: boolean;
128
165
  }
129
166
  /** The result of feeding one inbound frame (or the timeout) to the machine. */
130
167
  export interface ViewHostTransition {
@@ -137,6 +174,13 @@ export declare function initializeResult(behavior: ViewHostBehavior, requestedPr
137
174
  export declare function toolCallResponse(id: ViewRequestId, result: {
138
175
  [key: string]: unknown;
139
176
  }): ViewHostOutbound;
177
+ /**
178
+ * Build the in-band response for a relayed `resources/read`. An entry
179
+ * becomes the spec's `ReadResourceResult` (`contents: [entry]`); `undefined`
180
+ * — a miss, a deny, or a relay failure alike — becomes the one
181
+ * `Resource not found` error (deny == miss, {@link RESOURCE_NOT_FOUND}).
182
+ */
183
+ export declare function resourceReadResponse(id: ViewRequestId, entry: McpResourceReadResult | undefined): ViewHostOutbound;
140
184
  /**
141
185
  * The spec-mannered farewell a detaching host posts (`ui/resource-teardown`).
142
186
  * Sent WITHOUT an id — a host that is tearing the frame down cannot await a
@@ -1 +1 @@
1
- {"version":3,"file":"view-host-protocol.d.ts","sourceRoot":"","sources":["../src/view-host-protocol.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,OAAO,EAIL,KAAK,qBAAqB,EAC1B,KAAK,gBAAgB,EACrB,KAAK,qBAAqB,EAC3B,MAAM,gCAAgC,CAAC;AACxC,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AAE5D;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAKD,uEAAuE;AACvE,eAAO,MAAM,iBAAiB,eAAe,CAAC;AAE9C,2CAA2C;AAC3C,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,MAAM,CAAC;AAE5C,wDAAwD;AACxD,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,KAAK,CAAC;IACf,EAAE,CAAC,EAAE,aAAa,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC;IACpC,MAAM,CAAC,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC;IACpC,KAAK,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3C;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,MAAM,aAAa,GAAG,aAAa,GAAG,WAAW,GAAG,cAAc,CAAC;AAEzE,iFAAiF;AACjF,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,aAAa,CAAC;IACrB,0EAA0E;IAC1E,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED,wBAAgB,oBAAoB,IAAI,aAAa,CAEpD;AAED;;;GAGG;AACH,MAAM,MAAM,cAAc,GACtB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,gBAAgB,CAAA;CAAE,GAC9C;IACE;;;;;;OAMG;IACH,IAAI,EAAE,iBAAiB,CAAC;IACxB,EAAE,EAAE,aAAa,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,wBAAwB,CAAC;CACtC,CAAC;AAEN;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,YAAY,CAAC;IACvB;;;;;;;OAOG;IACH,gBAAgB,EAAE,qBAAqB,CAAC;IACxC,+DAA+D;IAC/D,WAAW,EAAE,gBAAgB,CAAC;IAC9B,uEAAuE;IACvE,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,+EAA+E;AAC/E,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,aAAa,CAAC;IACrB,OAAO,EAAE,cAAc,EAAE,CAAC;CAC3B;AAiCD,iFAAiF;AACjF,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,gBAAgB,EAC1B,wBAAwB,EAAE,OAAO,GAChC,qBAAqB,CAcvB;AAED,8EAA8E;AAC9E,wBAAgB,gBAAgB,CAC9B,EAAE,EAAE,aAAa,EACjB,MAAM,EAAE;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,GACjC,gBAAgB,CAElB;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,IAAI,gBAAgB,CAElD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,aAAa,EACpB,QAAQ,EAAE,gBAAgB,EAC1B,IAAI,EAAE,OAAO,GACZ,kBAAkB,CAuDpB;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,aAAa,GAAG,aAAa,CAEnE"}
1
+ {"version":3,"file":"view-host-protocol.d.ts","sourceRoot":"","sources":["../src/view-host-protocol.ts"],"names":[],"mappings":"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"}
@@ -30,11 +30,26 @@
30
30
  * view; everything ggui-specific stays in `ggui-render.ts` behind ggui's
31
31
  * own published protocol package.
32
32
  */
33
- import { INITIALIZE_METHOD, LATEST_PROTOCOL_VERSION, RESOURCE_TEARDOWN_METHOD, } from "@modelcontextprotocol/ext-apps";
33
+ import { INITIALIZE_METHOD, LATEST_PROTOCOL_VERSION, RESOURCE_TEARDOWN_METHOD, SIZE_CHANGED_METHOD, } from "@modelcontextprotocol/ext-apps";
34
34
  /** JSON-RPC `method not found` — the spec's code, not an invented one. */
35
35
  const METHOD_NOT_SUPPORTED = -32601;
36
36
  /** The standard MCP method a view uses to reach host-proxied tools. */
37
37
  export const TOOLS_CALL_METHOD = "tools/call";
38
+ /**
39
+ * The standard MCP method a view uses to read host-proxied resources —
40
+ * `ReadResourceRequest` in the spec's App→Host request union
41
+ * (`@modelcontextprotocol/ext-apps` `AppRequest`). A local constant, same
42
+ * as {@link TOOLS_CALL_METHOD}: the string is MCP-core vocabulary the
43
+ * ext-apps root does not re-export, and this package deliberately carries
44
+ * no `@modelcontextprotocol/sdk` dependency.
45
+ */
46
+ export const RESOURCES_READ_METHOD = "resources/read";
47
+ /**
48
+ * MCP's `Resource not found` JSON-RPC code — the one answer for a miss, a
49
+ * transport deny, AND a relay failure (deny == miss: the reader discipline,
50
+ * `reader.ts` — the view gets no oracle for which locators resolve).
51
+ */
52
+ const RESOURCE_NOT_FOUND = -32002;
38
53
  export function initialViewHostState() {
39
54
  return { phase: "negotiating", initializedSeen: false };
40
55
  }
@@ -83,6 +98,22 @@ export function initializeResult(behavior, requestedProtocolVersion) {
83
98
  export function toolCallResponse(id, result) {
84
99
  return { jsonrpc: "2.0", id, result };
85
100
  }
101
+ /**
102
+ * Build the in-band response for a relayed `resources/read`. An entry
103
+ * becomes the spec's `ReadResourceResult` (`contents: [entry]`); `undefined`
104
+ * — a miss, a deny, or a relay failure alike — becomes the one
105
+ * `Resource not found` error (deny == miss, {@link RESOURCE_NOT_FOUND}).
106
+ */
107
+ export function resourceReadResponse(id, entry) {
108
+ if (entry === undefined) {
109
+ return {
110
+ jsonrpc: "2.0",
111
+ id,
112
+ error: { code: RESOURCE_NOT_FOUND, message: "resource unavailable" },
113
+ };
114
+ }
115
+ return { jsonrpc: "2.0", id, result: { contents: [entry] } };
116
+ }
86
117
  /**
87
118
  * The spec-mannered farewell a detaching host posts (`ui/resource-teardown`).
88
119
  * Sent WITHOUT an id — a host that is tearing the frame down cannot await a
@@ -110,10 +141,29 @@ export function viewHostReceive(state, behavior, data) {
110
141
  if (req === undefined)
111
142
  return { state, effects: [] };
112
143
  if (req.id === undefined) {
113
- // A notification. Track the one the handshake defines; consume the rest.
144
+ // A notification. Track the one the handshake defines, surface the one
145
+ // the embedder may act on; consume the rest.
114
146
  if (req.method === "ui/notifications/initialized" && !state.initializedSeen) {
115
147
  return { state: { ...state, initializedSeen: true }, effects: [] };
116
148
  }
149
+ if (req.method === SIZE_CHANGED_METHOD) {
150
+ const width = req.params?.["width"];
151
+ const height = req.params?.["height"];
152
+ const validWidth = typeof width === "number" && Number.isFinite(width);
153
+ const validHeight = typeof height === "number" && Number.isFinite(height);
154
+ if (validWidth || validHeight) {
155
+ return {
156
+ state,
157
+ effects: [
158
+ {
159
+ kind: "size-changed",
160
+ ...(validWidth ? { width } : {}),
161
+ ...(validHeight ? { height } : {}),
162
+ },
163
+ ],
164
+ };
165
+ }
166
+ }
117
167
  return { state, effects: [] };
118
168
  }
119
169
  if (req.method === INITIALIZE_METHOD) {
@@ -141,6 +191,18 @@ export function viewHostReceive(state, behavior, data) {
141
191
  }
142
192
  // fall through: a nameless tools/call is not a call we can relay.
143
193
  }
194
+ if (req.method === RESOURCES_READ_METHOD && behavior.resourceRelay) {
195
+ const uri = req.params?.["uri"];
196
+ if (typeof uri === "string") {
197
+ return { state, effects: [{ kind: "relay-resource-read", id: req.id, uri }] };
198
+ }
199
+ // fall through: a uri-less read is not a read we can relay.
200
+ }
201
+ const answered = [
202
+ INITIALIZE_METHOD,
203
+ ...(behavior.toolRelay ? [TOOLS_CALL_METHOD] : []),
204
+ ...(behavior.resourceRelay ? [RESOURCES_READ_METHOD] : []),
205
+ ];
144
206
  return {
145
207
  state,
146
208
  effects: [
@@ -151,7 +213,7 @@ export function viewHostReceive(state, behavior, data) {
151
213
  id: req.id,
152
214
  error: {
153
215
  code: METHOD_NOT_SUPPORTED,
154
- message: `method_not_supported: ${req.method} — this host answers ${INITIALIZE_METHOD}${behavior.toolRelay ? ` and ${TOOLS_CALL_METHOD}` : ""} only`,
216
+ message: `method_not_supported: ${req.method} — this host answers ${answered.join(", ")} only`,
155
217
  },
156
218
  },
157
219
  },