@guuey/mcp-apps-host 0.14.1 → 0.15.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.
@@ -104,7 +104,18 @@ export interface LocatorViewMount {
104
104
  * transport knows which sandbox trust the fetched HTML needs (a ggui shell
105
105
  * wants the ggui-CSP page; arbitrary tenant HTML wants the self-only page).
106
106
  */
107
- export type UiResourceReader = (resourceUri: string) => Promise<ViewMount | undefined>;
107
+ export type UiResourceReader = (resourceUri: string, hints?: UiResourceReadHints) => Promise<ViewMount | undefined>;
108
+ /**
109
+ * Optional per-read hints (guuey#421). `origin: "history"` tells a
110
+ * two-door reader the locator came from a PERSISTED card — the pod door
111
+ * serves live turns only and 404s such reads by construction, so a
112
+ * history read may go straight to the platform door (kills the 2×404
113
+ * noise on every old-conversation load). Absent/`"live"` keeps pod-first.
114
+ * Purely advisory: a reader that ignores hints stays correct.
115
+ */
116
+ export interface UiResourceReadHints {
117
+ origin?: "live" | "history";
118
+ }
108
119
  /**
109
120
  * A live `tool-result` block → the card to mount: an inline resource, else the
110
121
  * `ui://` locator (either channel — see `toolResultLocator`), else `undefined`
@@ -146,5 +157,5 @@ export declare function snapshotViewMount(cardSnapshot: JsonValue): ViewMount |
146
157
  * `toolResultViewMount`/`snapshotViewMount` without a narrowing dance at
147
158
  * the call site.
148
159
  */
149
- export declare function resolveViewMount(mount: ViewMount | undefined, reader?: UiResourceReader): Promise<ResolvedViewMount | undefined>;
160
+ export declare function resolveViewMount(mount: ViewMount | undefined, reader?: UiResourceReader, hints?: UiResourceReadHints): Promise<ResolvedViewMount | undefined>;
150
161
  //# sourceMappingURL=card-mount.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"card-mount.d.ts","sourceRoot":"","sources":["../src/card-mount.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,OAAO,EAA+D,KAAK,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACvH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAE/D;;;;;GAKG;AACH,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,CAAC;AAE7D;;;;;;;;;;;;;;;GAeG;AACH,MAAM,MAAM,SAAS,GAAG,iBAAiB,GAAG,gBAAgB,CAAC;AAE7D;;;;;;GAMG;AACH,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,QAAQ,GAAG,MAAM,CAAC;IAC3B,+EAA+E;IAC/E,QAAQ,EAAE,oBAAoB,CAAC;IAC/B;;;;;;;;OAQG;IACH,GAAG,CAAC,EAAE,gBAAgB,CAAC;CACxB;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;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,OAAO,CAAC,OAAO,EAAE;IAAE,IAAI,EAAE,aAAa,CAAA;CAAE,CAAC,GAC/C,SAAS,GAAG,SAAS,CAKvB;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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,OAAO,EAA+D,KAAK,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACvH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAE/D;;;;;GAKG;AACH,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,CAAC;AAE7D;;;;;;;;;;;;;;;GAeG;AACH,MAAM,MAAM,SAAS,GAAG,iBAAiB,GAAG,gBAAgB,CAAC;AAE7D;;;;;;GAMG;AACH,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,QAAQ,GAAG,MAAM,CAAC;IAC3B,+EAA+E;IAC/E,QAAQ,EAAE,oBAAoB,CAAC;IAC/B;;;;;;;;OAQG;IACH,GAAG,CAAC,EAAE,gBAAgB,CAAC;CACxB;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,CAC7B,WAAW,EAAE,MAAM,EACnB,KAAK,CAAC,EAAE,mBAAmB,KACxB,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC,CAAC;AAEpC;;;;;;;GAOG;AACH,MAAM,WAAW,mBAAmB;IAClC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC7B;AAED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,OAAO,CAAC,OAAO,EAAE;IAAE,IAAI,EAAE,aAAa,CAAA;CAAE,CAAC,GAC/C,SAAS,GAAG,SAAS,CAKvB;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,EACzB,KAAK,CAAC,EAAE,mBAAmB,GAC1B,OAAO,CAAC,iBAAiB,GAAG,SAAS,CAAC,CAKxC"}
@@ -100,12 +100,12 @@ export function snapshotViewMount(cardSnapshot) {
100
100
  * `toolResultViewMount`/`snapshotViewMount` without a narrowing dance at
101
101
  * the call site.
102
102
  */
103
- export async function resolveViewMount(mount, reader) {
103
+ export async function resolveViewMount(mount, reader, hints) {
104
104
  if (mount === undefined || mount.channel !== "locator")
105
105
  return mount;
106
106
  if (reader === undefined)
107
107
  return undefined;
108
- const read = await reader(mount.resourceUri);
108
+ const read = await reader(mount.resourceUri, hints);
109
109
  return read === undefined || read.channel === "locator" ? undefined : read;
110
110
  }
111
111
  /**
package/dist/index.d.ts CHANGED
@@ -4,7 +4,7 @@
4
4
  * the conformance map (guuey#123).
5
5
  */
6
6
  export { asResourcePayload, asUiResource, blockUiResource, isJsonObject, resourceHtml, scanProviderRawForUiResource, snapshotUiResource, toolResultLocator, toolResultUiResource, uiLocator, type McpUiResourcePayload, } from "./block-ui.js";
7
- export { resolveViewMount, snapshotViewMount, toolResultViewMount, type LocatorViewMount, type ResolvedViewMount, type UiResourceReader, type ViewMount, type ViewMountChannel, } from "./card-mount.js";
7
+ export { resolveViewMount, snapshotViewMount, toolResultViewMount, type LocatorViewMount, type ResolvedViewMount, type UiResourceReader, type UiResourceReadHints, type ViewMount, type ViewMountChannel, } from "./card-mount.js";
8
8
  export { ACTION_STAGED_MSG, isStageableAction, stagedActionText, withActionStaging, type ActionStaging, } from "./action-staging.js";
9
9
  export { createMcpUiResourceReader, declaredResourceCsp, uiResourceChannel, type CreateMcpUiResourceReaderDeps, type McpResourceReadResult, } from "./reader.js";
10
10
  export type { McpUiResourceCsp } from "@modelcontextprotocol/ext-apps";
@@ -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,iBAAiB,EACjB,oBAAoB,EACpB,SAAS,EACT,KAAK,oBAAoB,GAC1B,MAAM,eAAe,CAAC;AACvB,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,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,KAAK,aAAa,GACnB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,yBAAyB,EACzB,mBAAmB,EACnB,iBAAiB,EACjB,KAAK,6BAA6B,EAClC,KAAK,qBAAqB,GAC3B,MAAM,aAAa,CAAC;AAIrB,YAAY,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACvE,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,oBAAoB,EACpB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,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,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,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EACnB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,KAAK,SAAS,EACd,KAAK,gBAAgB,GACtB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,KAAK,aAAa,GACnB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,yBAAyB,EACzB,mBAAmB,EACnB,iBAAiB,EACjB,KAAK,6BAA6B,EAClC,KAAK,qBAAqB,GAC3B,MAAM,aAAa,CAAC;AAIrB,YAAY,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACvE,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,oBAAoB,EACpB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,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,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/react.d.ts CHANGED
@@ -41,7 +41,7 @@ export type { AttachViewHostConfig, ViewCspEvents, ViewFrameLike, ViewHostEvents
41
41
  export { attachSandboxPageDelivery, isSandboxProxyReady, SANDBOX_PROXY_READY_METHOD, SANDBOX_RESOURCE_READY_METHOD, type SandboxPageDeliveryConfig, } from "./sandbox-page.js";
42
42
  export type { ViewCspDiagnosis, ViewCspOrigins, 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" | "onUpdateModelContext" | "onReadResource" | "onSizeChanged" | "negotiationTimeoutMs" | "cspOrigins" | "onCspDiagnosis"> {
44
+ export interface GuueyViewProps extends Pick<AttachViewHostConfig, "hostCapabilities" | "hostInfo" | "hostContext" | "onCallTool" | "onUpdateModelContext" | "onUserMessage" | "onReadResource" | "onSizeChanged" | "negotiationTimeoutMs" | "cspOrigins" | "onCspDiagnosis"> {
45
45
  /** The resolved card to mount (see `toolResultViewMount`/`resolveViewMount`). */
46
46
  mount: ResolvedViewMount;
47
47
  /**
@@ -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,gBAAgB,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC/E,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,aAAa,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACzG,OAAO,EACL,yBAAyB,EACzB,mBAAmB,EACnB,0BAA0B,EAC1B,6BAA6B,EAC7B,KAAK,yBAAyB,GAC/B,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,gBAAgB,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC/F,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,sBAAsB,GACtB,gBAAgB,GAChB,eAAe,GACf,sBAAsB,GACtB,YAAY,GACZ,gBAAgB,CACnB;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;;;;;;;;;OASG;IACH,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,EAAE,SAAS,CAAC,EAAE,gBAAgB,KAAK,SAAS,CAAC;CAClF;AA8CD;;;GAGG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,SAAS,CA0K1D"}
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,gBAAgB,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC/E,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,aAAa,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACzG,OAAO,EACL,yBAAyB,EACzB,mBAAmB,EACnB,0BAA0B,EAC1B,6BAA6B,EAC7B,KAAK,yBAAyB,GAC/B,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,gBAAgB,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC/F,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,sBAAsB,GACtB,eAAe,GACf,gBAAgB,GAChB,eAAe,GACf,sBAAsB,GACtB,YAAY,GACZ,gBAAgB,CACnB;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;;;;;;;;;OASG;IACH,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,EAAE,SAAS,CAAC,EAAE,gBAAgB,KAAK,SAAS,CAAC;CAClF;AA8CD;;;GAGG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,SAAS,CA0K1D"}
package/dist/reader.d.ts CHANGED
@@ -25,7 +25,7 @@
25
25
  * must not steer its HTML into the ggui-CSP host page.
26
26
  */
27
27
  import { type McpUiResourceCsp } from "@modelcontextprotocol/ext-apps";
28
- import type { ResolvedViewMount, ViewMountChannel } from "./card-mount.js";
28
+ import type { ResolvedViewMount, UiResourceReadHints, ViewMountChannel } from "./card-mount.js";
29
29
  /**
30
30
  * One `resources/read` `contents[]` entry, structurally (SEP-1865). Kept a
31
31
  * separate type from {@link McpUiResourcePayload} even though the shapes
@@ -78,7 +78,7 @@ export interface CreateMcpUiResourceReaderDeps {
78
78
  * equivalent authenticated proxy), returning the first `contents[]` entry —
79
79
  * or `undefined` when the read yields none. Throwing is treated as a miss.
80
80
  */
81
- readResource: (uri: string) => Promise<McpResourceReadResult | undefined>;
81
+ readResource: (uri: string, hints?: UiResourceReadHints) => Promise<McpResourceReadResult | undefined>;
82
82
  }
83
83
  /**
84
84
  * Assemble a `UiResourceReader` from a host-supplied `resources/read`
@@ -86,5 +86,5 @@ export interface CreateMcpUiResourceReaderDeps {
86
86
  * either yields mount material or the honest placeholder, never another
87
87
  * locator.
88
88
  */
89
- export declare function createMcpUiResourceReader(deps: CreateMcpUiResourceReaderDeps): (resourceUri: string) => Promise<ResolvedViewMount | undefined>;
89
+ export declare function createMcpUiResourceReader(deps: CreateMcpUiResourceReaderDeps): (resourceUri: string, hints?: UiResourceReadHints) => Promise<ResolvedViewMount | undefined>;
90
90
  //# sourceMappingURL=reader.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"reader.d.ts","sourceRoot":"","sources":["../src/reader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,OAAO,EAA0B,KAAK,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAE/F,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAE3E;;;;;;;;;GASG;AACH,MAAM,WAAW,qBAAqB;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kEAAkE;IAClE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,qBAAqB,GAAG,gBAAgB,GAAG,SAAS,CAW9F;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,EAAE,SAAS,CAAC,CAE3F;AAED,oFAAoF;AACpF,MAAM,WAAW,6BAA6B;IAC5C;;;;OAIG;IACH,YAAY,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,qBAAqB,GAAG,SAAS,CAAC,CAAC;CAC3E;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,6BAA6B,GAClC,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,iBAAiB,GAAG,SAAS,CAAC,CA+BjE"}
1
+ {"version":3,"file":"reader.d.ts","sourceRoot":"","sources":["../src/reader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,OAAO,EAA0B,KAAK,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAE/F,OAAO,KAAK,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEhG;;;;;;;;;GASG;AACH,MAAM,WAAW,qBAAqB;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kEAAkE;IAClE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,qBAAqB,GAAG,gBAAgB,GAAG,SAAS,CAW9F;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,EAAE,SAAS,CAAC,CAE3F;AAED,oFAAoF;AACpF,MAAM,WAAW,6BAA6B;IAC5C;;;;OAIG;IACH,YAAY,EAAE,CACZ,GAAG,EAAE,MAAM,EACX,KAAK,CAAC,EAAE,mBAAmB,KACxB,OAAO,CAAC,qBAAqB,GAAG,SAAS,CAAC,CAAC;CACjD;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,6BAA6B,GAClC,CACD,WAAW,EAAE,MAAM,EACnB,KAAK,CAAC,EAAE,mBAAmB,KACxB,OAAO,CAAC,iBAAiB,GAAG,SAAS,CAAC,CA+B1C"}
package/dist/reader.js CHANGED
@@ -67,10 +67,10 @@ export function uiResourceChannel(resourceUri) {
67
67
  * locator.
68
68
  */
69
69
  export function createMcpUiResourceReader(deps) {
70
- return async (resourceUri) => {
70
+ return async (resourceUri, hints) => {
71
71
  let entry;
72
72
  try {
73
- entry = await deps.readResource(resourceUri);
73
+ entry = await deps.readResource(resourceUri, hints);
74
74
  }
75
75
  catch {
76
76
  return undefined; // transport failure == deny == miss → placeholder
@@ -54,6 +54,15 @@ export declare const TOOLS_CALL_METHOD = "tools/call";
54
54
  * channel ("Actions drive turns; context observes state").
55
55
  */
56
56
  export declare const UPDATE_MODEL_CONTEXT_METHOD = "ui/update-model-context";
57
+ /**
58
+ * The spec method a view uses to hand the HOST a user-channel message
59
+ * (`McpUiMessageRequest` — role "user" + content blocks). ggui's #440
60
+ * post-turn doorbell rides this: when a gesture needs an agent turn and
61
+ * no consume long-poll is live, the runtime sends the model directive
62
+ * here and the host starts the turn (guuey#422). Local constant, same
63
+ * mirror rationale as the siblings.
64
+ */
65
+ export declare const MESSAGE_METHOD_LOCAL = "ui/message";
57
66
  /**
58
67
  * The standard MCP method a view uses to read host-proxied resources —
59
68
  * `ReadResourceRequest` in the spec's App→Host request union
@@ -150,6 +159,20 @@ export type ViewHostEffect = {
150
159
  params: {
151
160
  [key: string]: unknown;
152
161
  };
162
+ } | {
163
+ /**
164
+ * A `ui/message` the view handed the host (guuey#422): role-user
165
+ * content blocks the host forwards into ITS conversation loop (the
166
+ * composer's send gate — a real turn starts). ggui's #440 post-turn
167
+ * doorbell rides this. The machine already ANSWERED the view (`{}` —
168
+ * accepted); delivery is this effect. Only emitted when
169
+ * {@link ViewHostBehavior.messageSink} is true.
170
+ */
171
+ kind: "user-message";
172
+ id: ViewRequestId;
173
+ params: {
174
+ [key: string]: unknown;
175
+ };
153
176
  } | {
154
177
  /**
155
178
  * The view reported its content size (`ui/notifications/size-changed`
@@ -185,6 +208,8 @@ export interface ViewHostBehavior {
185
208
  toolRelay: boolean;
186
209
  /** Whether a model-context sink is wired (see `view-host.ts`, guuey#335). */
187
210
  modelContextSink: boolean;
211
+ /** Whether a ui/message sink is wired (see `view-host.ts`, guuey#422). */
212
+ messageSink: boolean;
188
213
  /** Whether a `resources/read` relay hook is wired (see `view-host.ts`). */
189
214
  resourceRelay: boolean;
190
215
  }
@@ -1 +1 @@
1
- {"version":3,"file":"view-host-protocol.d.ts","sourceRoot":"","sources":["../src/view-host-protocol.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"view-host-protocol.d.ts","sourceRoot":"","sources":["../src/view-host-protocol.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,OAAO,EAKL,KAAK,qBAAqB,EAC1B,KAAK,gBAAgB,EACrB,KAAK,qBAAqB,EAC1B,KAAK,gBAAgB,EACtB,MAAM,gCAAgC,CAAC;AACxC,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAEzD;;;;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;;;;;;;GAOG;AACH,eAAO,MAAM,2BAA2B,4BAA4B,CAAC;AAErE;;;;;;;GAOG;AACH,eAAO,MAAM,oBAAoB,eAAe,CAAC;AAEjD;;;;;;;GAOG;AACH,eAAO,MAAM,qBAAqB,mBAAmB,CAAC;AAStD,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,GACD;IACE;;;;;;;OAOG;IACH,IAAI,EAAE,qBAAqB,CAAC;IAC5B,EAAE,EAAE,aAAa,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;CACb,GACD;IACE;;;;;;;OAOG;IACH,IAAI,EAAE,sBAAsB,CAAC;IAC7B,MAAM,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC;CACpC,GACD;IACE;;;;;;;OAOG;IACH,IAAI,EAAE,cAAc,CAAC;IACrB,EAAE,EAAE,aAAa,CAAC;IAClB,MAAM,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC;CACpC,GACD;IACE;;;;;;;;OAQG;IACH,IAAI,EAAE,cAAc,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,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;IACnB,6EAA6E;IAC7E,gBAAgB,EAAE,OAAO,CAAC;IAC1B,0EAA0E;IAC1E,WAAW,EAAE,OAAO,CAAC;IACrB,2EAA2E;IAC3E,aAAa,EAAE,OAAO,CAAC;CACxB;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,oBAAoB,CAClC,EAAE,EAAE,aAAa,EACjB,KAAK,EAAE,qBAAqB,GAAG,SAAS,GACvC,gBAAgB,CASlB;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,CAsHpB;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,aAAa,GAAG,aAAa,CAEnE;AAID;;;;;;;;GAQG;AACH,MAAM,MAAM,cAAc,GAAG,gBAAgB,CAAC;AAE9C;;;;;;GAMG;AACH,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,uFAAuF;IACvF,cAAc,EAAE,MAAM,CAAC;IACvB,gDAAgD;IAChD,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,6CAA6C;IAC7C,iBAAiB,EAAE,MAAM,CAAC;IAC1B,0FAA0F;IAC1F,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAyBD;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,gBAAgB,EAC3B,OAAO,EAAE,cAAc,GAAG,SAAS,GAClC,gBAAgB,GAAG,SAAS,CAqB9B"}
@@ -45,6 +45,15 @@ export const TOOLS_CALL_METHOD = "tools/call";
45
45
  * channel ("Actions drive turns; context observes state").
46
46
  */
47
47
  export const UPDATE_MODEL_CONTEXT_METHOD = "ui/update-model-context";
48
+ /**
49
+ * The spec method a view uses to hand the HOST a user-channel message
50
+ * (`McpUiMessageRequest` — role "user" + content blocks). ggui's #440
51
+ * post-turn doorbell rides this: when a gesture needs an agent turn and
52
+ * no consume long-poll is live, the runtime sends the model directive
53
+ * here and the host starts the turn (guuey#422). Local constant, same
54
+ * mirror rationale as the siblings.
55
+ */
56
+ export const MESSAGE_METHOD_LOCAL = "ui/message";
48
57
  /**
49
58
  * The standard MCP method a view uses to read host-proxied resources —
50
59
  * `ReadResourceRequest` in the spec's App→Host request union
@@ -215,6 +224,19 @@ export function viewHostReceive(state, behavior, data) {
215
224
  ],
216
225
  };
217
226
  }
227
+ if (req.method === MESSAGE_METHOD_LOCAL && behavior.messageSink) {
228
+ // Answer accepted FIRST (spec result: rejected-flag absent = delivered)
229
+ // and deliver as an effect — the sink starting a turn must never make
230
+ // the view wait on the model.
231
+ const params = isPlainObject(req.params) ? req.params : {};
232
+ return {
233
+ state,
234
+ effects: [
235
+ { kind: "respond", message: { jsonrpc: "2.0", id: req.id, result: {} } },
236
+ { kind: "user-message", id: req.id, params },
237
+ ],
238
+ };
239
+ }
218
240
  if (req.method === RESOURCES_READ_METHOD && behavior.resourceRelay) {
219
241
  const uri = req.params?.["uri"];
220
242
  if (typeof uri === "string") {
@@ -227,6 +249,7 @@ export function viewHostReceive(state, behavior, data) {
227
249
  ...(behavior.toolRelay ? [TOOLS_CALL_METHOD] : []),
228
250
  ...(behavior.resourceRelay ? [RESOURCES_READ_METHOD] : []),
229
251
  ...(behavior.modelContextSink ? [UPDATE_MODEL_CONTEXT_METHOD] : []),
252
+ ...(behavior.messageSink ? [MESSAGE_METHOD_LOCAL] : []),
230
253
  ];
231
254
  return {
232
255
  state,
@@ -109,6 +109,17 @@ export interface AttachViewHostConfig {
109
109
  onUpdateModelContext?: (params: {
110
110
  [key: string]: unknown;
111
111
  }) => void;
112
+ /**
113
+ * Sink for `ui/message` (guuey#422): the view hands the host role-user
114
+ * content blocks to forward into the HOST's conversation (start a
115
+ * turn). ggui's #440 post-turn doorbell depends on this — without it,
116
+ * a successfully-relayed post-turn gesture dead-ends in their
117
+ * 'cannot relay actions' latch. Wiring it advertises `message`
118
+ * (text modality); the machine answers the view BEFORE delivery.
119
+ */
120
+ onUserMessage?: (params: {
121
+ [key: string]: unknown;
122
+ }) => void;
112
123
  /**
113
124
  * The mounted resource's `ui://` locator — the scope stamped on every
114
125
  * relayed {@link UiActionRequest}. Required for the relay to fire;
@@ -1 +1 @@
1
- {"version":3,"file":"view-host.d.ts","sourceRoot":"","sources":["../src/view-host.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"view-host.d.ts","sourceRoot":"","sources":["../src/view-host.ts"],"names":[],"mappings":"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"}
package/dist/view-host.js CHANGED
@@ -45,6 +45,7 @@ function behaviorFor(frame, config) {
45
45
  const relayWired = config.onCallTool !== undefined && config.resourceUri !== undefined;
46
46
  const readWired = config.onReadResource !== undefined;
47
47
  const contextSinkWired = config.onUpdateModelContext !== undefined;
48
+ const messageSinkWired = config.onUserMessage !== undefined;
48
49
  return {
49
50
  hostInfo: config.hostInfo ?? DEFAULT_HOST_INFO,
50
51
  hostCapabilities: {
@@ -53,12 +54,14 @@ function behaviorFor(frame, config) {
53
54
  ...(relayWired ? { serverTools: {} } : {}),
54
55
  ...(readWired ? { serverResources: {} } : {}),
55
56
  ...(contextSinkWired ? { updateModelContext: { text: {} } } : {}),
57
+ ...(messageSinkWired ? { message: { text: {} } } : {}),
56
58
  ...config.hostCapabilities,
57
59
  },
58
60
  hostContext: hostContextFor(frame, config),
59
61
  toolRelay: relayWired,
60
62
  resourceRelay: readWired,
61
63
  modelContextSink: contextSinkWired,
64
+ messageSink: messageSinkWired,
62
65
  };
63
66
  }
64
67
  /**
@@ -132,6 +135,14 @@ export function attachViewHost(frame, config = {}) {
132
135
  relay(effect.id, effect.name, effect.arguments);
133
136
  else if (effect.kind === "relay-resource-read")
134
137
  relayRead(effect.id, effect.uri);
138
+ else if (effect.kind === "user-message") {
139
+ try {
140
+ config.onUserMessage?.(effect.params);
141
+ }
142
+ catch {
143
+ // Observer failure is the embedder's bug; the view is answered.
144
+ }
145
+ }
135
146
  else if (effect.kind === "model-context-update") {
136
147
  // Delivery only — the machine already answered the view. Contained:
137
148
  // a throwing embedder sink must not unwind the message pump.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@guuey/mcp-apps-host",
3
- "version": "0.14.1",
3
+ "version": "0.15.0",
4
4
  "description": "The MCP Apps (SEP-1865) Host role for guuey's chat surfaces — view-mount narrowing across UI channels, ui:// locator rehydration by resources/read, and the sandbox-trust channel contract. Vendor-neutral: any spec-following MCP App mounts through it.",
5
5
  "license": "MIT",
6
6
  "type": "module",
package/src/card-mount.ts CHANGED
@@ -109,7 +109,22 @@ export interface LocatorViewMount {
109
109
  * transport knows which sandbox trust the fetched HTML needs (a ggui shell
110
110
  * wants the ggui-CSP page; arbitrary tenant HTML wants the self-only page).
111
111
  */
112
- export type UiResourceReader = (resourceUri: string) => Promise<ViewMount | undefined>;
112
+ export type UiResourceReader = (
113
+ resourceUri: string,
114
+ hints?: UiResourceReadHints,
115
+ ) => Promise<ViewMount | undefined>;
116
+
117
+ /**
118
+ * Optional per-read hints (guuey#421). `origin: "history"` tells a
119
+ * two-door reader the locator came from a PERSISTED card — the pod door
120
+ * serves live turns only and 404s such reads by construction, so a
121
+ * history read may go straight to the platform door (kills the 2×404
122
+ * noise on every old-conversation load). Absent/`"live"` keeps pod-first.
123
+ * Purely advisory: a reader that ignores hints stays correct.
124
+ */
125
+ export interface UiResourceReadHints {
126
+ origin?: "live" | "history";
127
+ }
113
128
 
114
129
  /**
115
130
  * A live `tool-result` block → the card to mount: an inline resource, else the
@@ -172,10 +187,11 @@ export function snapshotViewMount(cardSnapshot: JsonValue): ViewMount | undefine
172
187
  export async function resolveViewMount(
173
188
  mount: ViewMount | undefined,
174
189
  reader?: UiResourceReader,
190
+ hints?: UiResourceReadHints,
175
191
  ): Promise<ResolvedViewMount | undefined> {
176
192
  if (mount === undefined || mount.channel !== "locator") return mount;
177
193
  if (reader === undefined) return undefined;
178
- const read = await reader(mount.resourceUri);
194
+ const read = await reader(mount.resourceUri, hints);
179
195
  return read === undefined || read.channel === "locator" ? undefined : read;
180
196
  }
181
197
 
package/src/index.ts CHANGED
@@ -23,6 +23,7 @@ export {
23
23
  type LocatorViewMount,
24
24
  type ResolvedViewMount,
25
25
  type UiResourceReader,
26
+ type UiResourceReadHints,
26
27
  type ViewMount,
27
28
  type ViewMountChannel,
28
29
  } from "./card-mount.js";
package/src/react.tsx CHANGED
@@ -61,6 +61,7 @@ export interface GuueyViewProps
61
61
  | "hostContext"
62
62
  | "onCallTool"
63
63
  | "onUpdateModelContext"
64
+ | "onUserMessage"
64
65
  | "onReadResource"
65
66
  | "onSizeChanged"
66
67
  | "negotiationTimeoutMs"
package/src/reader.ts CHANGED
@@ -26,7 +26,7 @@
26
26
  */
27
27
  import { McpUiResourceCspSchema, type McpUiResourceCsp } from "@modelcontextprotocol/ext-apps";
28
28
  import type { McpUiResourcePayload } from "./block-ui.js";
29
- import type { ResolvedViewMount, ViewMountChannel } from "./card-mount.js";
29
+ import type { ResolvedViewMount, UiResourceReadHints, ViewMountChannel } from "./card-mount.js";
30
30
 
31
31
  /**
32
32
  * One `resources/read` `contents[]` entry, structurally (SEP-1865). Kept a
@@ -96,7 +96,10 @@ export interface CreateMcpUiResourceReaderDeps {
96
96
  * equivalent authenticated proxy), returning the first `contents[]` entry —
97
97
  * or `undefined` when the read yields none. Throwing is treated as a miss.
98
98
  */
99
- readResource: (uri: string) => Promise<McpResourceReadResult | undefined>;
99
+ readResource: (
100
+ uri: string,
101
+ hints?: UiResourceReadHints,
102
+ ) => Promise<McpResourceReadResult | undefined>;
100
103
  }
101
104
 
102
105
  /**
@@ -107,11 +110,14 @@ export interface CreateMcpUiResourceReaderDeps {
107
110
  */
108
111
  export function createMcpUiResourceReader(
109
112
  deps: CreateMcpUiResourceReaderDeps,
110
- ): (resourceUri: string) => Promise<ResolvedViewMount | undefined> {
111
- return async (resourceUri) => {
113
+ ): (
114
+ resourceUri: string,
115
+ hints?: UiResourceReadHints,
116
+ ) => Promise<ResolvedViewMount | undefined> {
117
+ return async (resourceUri, hints) => {
112
118
  let entry: McpResourceReadResult | undefined;
113
119
  try {
114
- entry = await deps.readResource(resourceUri);
120
+ entry = await deps.readResource(resourceUri, hints);
115
121
  } catch {
116
122
  return undefined; // transport failure == deny == miss → placeholder
117
123
  }
@@ -70,6 +70,16 @@ export const TOOLS_CALL_METHOD = "tools/call";
70
70
  */
71
71
  export const UPDATE_MODEL_CONTEXT_METHOD = "ui/update-model-context";
72
72
 
73
+ /**
74
+ * The spec method a view uses to hand the HOST a user-channel message
75
+ * (`McpUiMessageRequest` — role "user" + content blocks). ggui's #440
76
+ * post-turn doorbell rides this: when a gesture needs an agent turn and
77
+ * no consume long-poll is live, the runtime sends the model directive
78
+ * here and the host starts the turn (guuey#422). Local constant, same
79
+ * mirror rationale as the siblings.
80
+ */
81
+ export const MESSAGE_METHOD_LOCAL = "ui/message";
82
+
73
83
  /**
74
84
  * The standard MCP method a view uses to read host-proxied resources —
75
85
  * `ReadResourceRequest` in the spec's App→Host request union
@@ -174,6 +184,19 @@ export type ViewHostEffect =
174
184
  kind: "model-context-update";
175
185
  params: { [key: string]: unknown };
176
186
  }
187
+ | {
188
+ /**
189
+ * A `ui/message` the view handed the host (guuey#422): role-user
190
+ * content blocks the host forwards into ITS conversation loop (the
191
+ * composer's send gate — a real turn starts). ggui's #440 post-turn
192
+ * doorbell rides this. The machine already ANSWERED the view (`{}` —
193
+ * accepted); delivery is this effect. Only emitted when
194
+ * {@link ViewHostBehavior.messageSink} is true.
195
+ */
196
+ kind: "user-message";
197
+ id: ViewRequestId;
198
+ params: { [key: string]: unknown };
199
+ }
177
200
  | {
178
201
  /**
179
202
  * The view reported its content size (`ui/notifications/size-changed`
@@ -210,6 +233,8 @@ export interface ViewHostBehavior {
210
233
  toolRelay: boolean;
211
234
  /** Whether a model-context sink is wired (see `view-host.ts`, guuey#335). */
212
235
  modelContextSink: boolean;
236
+ /** Whether a ui/message sink is wired (see `view-host.ts`, guuey#422). */
237
+ messageSink: boolean;
213
238
  /** Whether a `resources/read` relay hook is wired (see `view-host.ts`). */
214
239
  resourceRelay: boolean;
215
240
  }
@@ -399,6 +424,20 @@ export function viewHostReceive(
399
424
  };
400
425
  }
401
426
 
427
+ if (req.method === MESSAGE_METHOD_LOCAL && behavior.messageSink) {
428
+ // Answer accepted FIRST (spec result: rejected-flag absent = delivered)
429
+ // and deliver as an effect — the sink starting a turn must never make
430
+ // the view wait on the model.
431
+ const params = isPlainObject(req.params) ? req.params : {};
432
+ return {
433
+ state,
434
+ effects: [
435
+ { kind: "respond", message: { jsonrpc: "2.0", id: req.id, result: {} } },
436
+ { kind: "user-message", id: req.id, params },
437
+ ],
438
+ };
439
+ }
440
+
402
441
  if (req.method === RESOURCES_READ_METHOD && behavior.resourceRelay) {
403
442
  const uri = req.params?.["uri"];
404
443
  if (typeof uri === "string") {
@@ -412,6 +451,7 @@ export function viewHostReceive(
412
451
  ...(behavior.toolRelay ? [TOOLS_CALL_METHOD] : []),
413
452
  ...(behavior.resourceRelay ? [RESOURCES_READ_METHOD] : []),
414
453
  ...(behavior.modelContextSink ? [UPDATE_MODEL_CONTEXT_METHOD] : []),
454
+ ...(behavior.messageSink ? [MESSAGE_METHOD_LOCAL] : []),
415
455
  ];
416
456
  return {
417
457
  state,
package/src/view-host.ts CHANGED
@@ -129,6 +129,15 @@ export interface AttachViewHostConfig {
129
129
  * channel), so a sink that only records is honest.
130
130
  */
131
131
  onUpdateModelContext?: (params: { [key: string]: unknown }) => void;
132
+ /**
133
+ * Sink for `ui/message` (guuey#422): the view hands the host role-user
134
+ * content blocks to forward into the HOST's conversation (start a
135
+ * turn). ggui's #440 post-turn doorbell depends on this — without it,
136
+ * a successfully-relayed post-turn gesture dead-ends in their
137
+ * 'cannot relay actions' latch. Wiring it advertises `message`
138
+ * (text modality); the machine answers the view BEFORE delivery.
139
+ */
140
+ onUserMessage?: (params: { [key: string]: unknown }) => void;
132
141
  /**
133
142
  * The mounted resource's `ui://` locator — the scope stamped on every
134
143
  * relayed {@link UiActionRequest}. Required for the relay to fire;
@@ -220,6 +229,7 @@ function behaviorFor(frame: ViewFrameLike, config: AttachViewHostConfig): ViewHo
220
229
  const relayWired = config.onCallTool !== undefined && config.resourceUri !== undefined;
221
230
  const readWired = config.onReadResource !== undefined;
222
231
  const contextSinkWired = config.onUpdateModelContext !== undefined;
232
+ const messageSinkWired = config.onUserMessage !== undefined;
223
233
  return {
224
234
  hostInfo: config.hostInfo ?? DEFAULT_HOST_INFO,
225
235
  hostCapabilities: {
@@ -228,12 +238,14 @@ function behaviorFor(frame: ViewFrameLike, config: AttachViewHostConfig): ViewHo
228
238
  ...(relayWired ? { serverTools: {} } : {}),
229
239
  ...(readWired ? { serverResources: {} } : {}),
230
240
  ...(contextSinkWired ? { updateModelContext: { text: {} } } : {}),
241
+ ...(messageSinkWired ? { message: { text: {} } } : {}),
231
242
  ...config.hostCapabilities,
232
243
  },
233
244
  hostContext: hostContextFor(frame, config),
234
245
  toolRelay: relayWired,
235
246
  resourceRelay: readWired,
236
247
  modelContextSink: contextSinkWired,
248
+ messageSink: messageSinkWired,
237
249
  };
238
250
  }
239
251
 
@@ -310,7 +322,13 @@ export function attachViewHost(frame: ViewFrameLike, config: AttachViewHostConfi
310
322
  if (effect.kind === "respond") post(effect.message);
311
323
  else if (effect.kind === "relay-tool-call") relay(effect.id, effect.name, effect.arguments);
312
324
  else if (effect.kind === "relay-resource-read") relayRead(effect.id, effect.uri);
313
- else if (effect.kind === "model-context-update") {
325
+ else if (effect.kind === "user-message") {
326
+ try {
327
+ config.onUserMessage?.(effect.params);
328
+ } catch {
329
+ // Observer failure is the embedder's bug; the view is answered.
330
+ }
331
+ } else if (effect.kind === "model-context-update") {
314
332
  // Delivery only — the machine already answered the view. Contained:
315
333
  // a throwing embedder sink must not unwind the message pump.
316
334
  try {