@guuey/agent-client 0.3.0 → 0.3.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/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export { parseSseEvents, extractAssistantText, reduceAssistantText, stringField, parseConsentRequest, parseLinkRequest, type ParsedSseEvent, } from "./sse";
2
2
  export { dismissLinkPrompt } from "./link-prompt";
3
- export { createUiResourceReader, type CreateUiResourceReaderOptions, type ResolvedUiResourceMount, createWebAdapters, localStorageThreadStore, webGenerateId, fetchStreamTransport, AgentResponseError, type CreateWebAdaptersOptions, } from "./web-adapters";
3
+ export { createUiResourceReader, type CreateUiResourceReaderOptions, createWebAdapters, localStorageThreadStore, webGenerateId, fetchStreamTransport, AgentResponseError, type CreateWebAdaptersOptions, } from "./web-adapters";
4
4
  export { fetchThreadHistory, threadHistoryRowsToMessages, threadHistoryRowsToCards, HistoryUnauthorizedError, type ThreadHistoryRow, type ThreadHistoryFetchOptions, } from "./history";
5
5
  export { ingestMessageFrame } from "./blocks";
6
6
  export { sortHistoryCards, toolNameFor } from "./history";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,oBAAoB,EACpB,mBAAmB,EACnB,WAAW,EACX,mBAAmB,EACnB,gBAAgB,EAChB,KAAK,cAAc,GACpB,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EACL,sBAAsB,EACtB,KAAK,6BAA6B,EAClC,KAAK,uBAAuB,EAC5B,iBAAiB,EACjB,uBAAuB,EACvB,aAAa,EACb,oBAAoB,EACpB,kBAAkB,EAClB,KAAK,wBAAwB,GAC9B,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,kBAAkB,EAClB,2BAA2B,EAC3B,wBAAwB,EACxB,wBAAwB,EACxB,KAAK,gBAAgB,EACrB,KAAK,yBAAyB,GAC/B,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAK9C,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAI1D,YAAY,EAAE,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AACxF,YAAY,EACV,YAAY,EACZ,WAAW,EACX,qBAAqB,EACrB,kBAAkB,EAClB,aAAa,EACb,UAAU,EACV,aAAa,EACb,eAAe,EACf,mBAAmB,EACnB,yBAAyB,EACzB,iBAAiB,EACjB,iBAAiB,EACjB,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,oBAAoB,EACpB,mBAAmB,EACnB,WAAW,EACX,mBAAmB,EACnB,gBAAgB,EAChB,KAAK,cAAc,GACpB,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EACL,sBAAsB,EACtB,KAAK,6BAA6B,EAClC,iBAAiB,EACjB,uBAAuB,EACvB,aAAa,EACb,oBAAoB,EACpB,kBAAkB,EAClB,KAAK,wBAAwB,GAC9B,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,kBAAkB,EAClB,2BAA2B,EAC3B,wBAAwB,EACxB,wBAAwB,EACxB,KAAK,gBAAgB,EACrB,KAAK,yBAAyB,GAC/B,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAK9C,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAI1D,YAAY,EAAE,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AACxF,YAAY,EACV,YAAY,EACZ,WAAW,EACX,qBAAqB,EACrB,kBAAkB,EAClB,aAAa,EACb,UAAU,EACV,aAAa,EACb,eAAe,EACf,mBAAmB,EACnB,yBAAyB,EACzB,iBAAiB,EACjB,iBAAiB,EACjB,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,SAAS,CAAC"}
@@ -6,6 +6,7 @@
6
6
  * functions — never at module load — so this file is import-safe under SSR
7
7
  * (the functions guard on `typeof window`).
8
8
  */
9
+ import { type ResolvedViewMount } from "@guuey/mcp-apps-host";
9
10
  import type { AgentInvokeAdapters, InvokeRequest, ThreadIdStore } from "./types";
10
11
  /**
11
12
  * Thrown when the pod returns a non-2xx status on `/agent/invoke` (before any
@@ -136,36 +137,18 @@ export interface CreateUiResourceReaderOptions {
136
137
  fetchImpl?: typeof fetch;
137
138
  }
138
139
  /**
139
- * Build a `@guuey/mcp-apps-host` `UiResourceReader` over guuey's
140
- * authenticated resources/read proxy (guuey#122 Gap 1:
141
- * `GET /v1/threads/:threadId/ui-resource?uri=…`).
140
+ * Build a `UiResourceReader` over guuey's authenticated resources/read proxy
141
+ * (guuey#122 Gap 1: `GET /v1/threads/:threadId/ui-resource?uri=…`).
142
142
  *
143
+ * This is `@guuey/mcp-apps-host`'s `createMcpUiResourceReader` assembly over
144
+ * a guuey-platform transport (guuey#127) — channel resolution and payload
145
+ * narrowing live in the host package; only the transport is guuey-shaped.
143
146
  * The proxy owns EVERYTHING trust-shaped: caller identity (the same three
144
147
  * families as the history read), thread ownership, the locator-to-thread
145
- * scope guard, and the per-user federation mint. This reader only carries
148
+ * scope guard, and the per-user federation mint. This transport only carries
146
149
  * the surface's existing credential and maps EVERY non-OK — 401/403/404/502
147
150
  * alike — to `undefined`: deny is byte-identical to a miss, and a miss
148
151
  * renders the host's placeholder, never an error surface.
149
- *
150
- * Channel resolution is the phase-1 heuristic: a `ui://ggui/…` uri mounts in
151
- * the ggui-CSP sandbox page (`channel: "ggui"`), anything else in the
152
- * self-only page (`channel: "inline"`). Phase 2 (per-resource declared-CSP
153
- * construction from the response `_meta.ui.csp`) retires the heuristic —
154
- * conformance map, retirement step 3.
155
- */
156
- /**
157
- * The mount the reader resolves — structurally assignable to
158
- * `@guuey/mcp-apps-host`'s `ViewMount` mountable arms (typed inline so this
159
- * package carries no dependency on the host package; hosts that consume
160
- * both see one structural type).
161
152
  */
162
- export interface ResolvedUiResourceMount {
163
- channel: "inline" | "ggui";
164
- resource: {
165
- uri: string;
166
- mimeType?: string;
167
- text: string;
168
- };
169
- }
170
- export declare function createUiResourceReader(options: CreateUiResourceReaderOptions): (resourceUri: string) => Promise<ResolvedUiResourceMount | undefined>;
153
+ export declare function createUiResourceReader(options: CreateUiResourceReaderOptions): (resourceUri: string) => Promise<ResolvedViewMount | undefined>;
171
154
  //# sourceMappingURL=web-adapters.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"web-adapters.d.ts","sourceRoot":"","sources":["../src/web-adapters.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EACV,mBAAmB,EACnB,aAAa,EAEb,aAAa,EACd,MAAM,SAAS,CAAC;AAGjB;;;;;;GAMG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;IAGzC,QAAQ,CAAC,MAAM,EAAE,MAAM;IACvB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM;gBAFtB,OAAO,EAAE,MAAM,EACN,MAAM,EAAE,MAAM,EACd,IAAI,CAAC,EAAE,MAAM,YAAA;CAKzB;AAED,sEAAsE;AACtE,eAAO,MAAM,uBAAuB,EAAE,aAiBrC,CAAC;AAEF,mEAAmE;AACnE,wBAAgB,aAAa,IAAI,MAAM,CAKtC;AAwCD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAuB,oBAAoB,CACzC,GAAG,EAAE,aAAa,EAClB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,EAC3B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,GAC1B,cAAc,CAAC,MAAM,CAAC,CA4CxB;AAED,MAAM,WAAW,wBAAwB;IACvC;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;;;;;;;;;;;;;OAiBG;IACH,cAAc,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC/E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAuCG;IACH,cAAc,CAAC,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;CACtC;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,GAAE,wBAA6B,GAClC,mBAAmB,CAwErB;AAED,mGAAmG;AACnG,MAAM,WAAW,6BAA6B;IAC5C,0CAA0C;IAC1C,UAAU,EAAE,MAAM,CAAC;IACnB,mEAAmE;IACnE,QAAQ,EAAE,MAAM,CAAC;IACjB,kFAAkF;IAClF,cAAc,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC/E,iEAAiE;IACjE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,4BAA4B;IAC5B,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH;;;;;GAKG;AACH,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,QAAQ,GAAG,MAAM,CAAC;IAC3B,QAAQ,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CAC5D;AAED,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,6BAA6B,GACrC,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,uBAAuB,GAAG,SAAS,CAAC,CAkDvE"}
1
+ {"version":3,"file":"web-adapters.d.ts","sourceRoot":"","sources":["../src/web-adapters.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAGL,KAAK,iBAAiB,EACvB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EACV,mBAAmB,EACnB,aAAa,EAEb,aAAa,EACd,MAAM,SAAS,CAAC;AAGjB;;;;;;GAMG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;IAGzC,QAAQ,CAAC,MAAM,EAAE,MAAM;IACvB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM;gBAFtB,OAAO,EAAE,MAAM,EACN,MAAM,EAAE,MAAM,EACd,IAAI,CAAC,EAAE,MAAM,YAAA;CAKzB;AAED,sEAAsE;AACtE,eAAO,MAAM,uBAAuB,EAAE,aAiBrC,CAAC;AAEF,mEAAmE;AACnE,wBAAgB,aAAa,IAAI,MAAM,CAKtC;AAwCD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAuB,oBAAoB,CACzC,GAAG,EAAE,aAAa,EAClB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,EAC3B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,GAC1B,cAAc,CAAC,MAAM,CAAC,CA4CxB;AAED,MAAM,WAAW,wBAAwB;IACvC;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;;;;;;;;;;;;;OAiBG;IACH,cAAc,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC/E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAuCG;IACH,cAAc,CAAC,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;CACtC;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,GAAE,wBAA6B,GAClC,mBAAmB,CAwErB;AAED,mGAAmG;AACnG,MAAM,WAAW,6BAA6B;IAC5C,0CAA0C;IAC1C,UAAU,EAAE,MAAM,CAAC;IACnB,mEAAmE;IACnE,QAAQ,EAAE,MAAM,CAAC;IACjB,kFAAkF;IAClF,cAAc,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC/E,iEAAiE;IACjE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,4BAA4B;IAC5B,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,6BAA6B,GACrC,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,iBAAiB,GAAG,SAAS,CAAC,CAoDjE"}
@@ -1,3 +1,12 @@
1
+ /**
2
+ * Web (browser / Next.js) host adapters for {@link useAgentInvoke}.
3
+ *
4
+ * Studio builds its bundle via {@link createWebAdapters}. The implementations
5
+ * touch `window.localStorage`, `crypto`, and `fetch` only inside their
6
+ * functions — never at module load — so this file is import-safe under SSR
7
+ * (the functions guard on `typeof window`).
8
+ */
9
+ import { createMcpUiResourceReader, } from "@guuey/mcp-apps-host";
1
10
  import { fetchThreadHistory, HistoryUnauthorizedError } from "./history";
2
11
  /**
3
12
  * Thrown when the pod returns a non-2xx status on `/agent/invoke` (before any
@@ -227,9 +236,23 @@ export function createWebAdapters(opts = {}) {
227
236
  }
228
237
  return adapters;
229
238
  }
239
+ /**
240
+ * Build a `UiResourceReader` over guuey's authenticated resources/read proxy
241
+ * (guuey#122 Gap 1: `GET /v1/threads/:threadId/ui-resource?uri=…`).
242
+ *
243
+ * This is `@guuey/mcp-apps-host`'s `createMcpUiResourceReader` assembly over
244
+ * a guuey-platform transport (guuey#127) — channel resolution and payload
245
+ * narrowing live in the host package; only the transport is guuey-shaped.
246
+ * The proxy owns EVERYTHING trust-shaped: caller identity (the same three
247
+ * families as the history read), thread ownership, the locator-to-thread
248
+ * scope guard, and the per-user federation mint. This transport only carries
249
+ * the surface's existing credential and maps EVERY non-OK — 401/403/404/502
250
+ * alike — to `undefined`: deny is byte-identical to a miss, and a miss
251
+ * renders the host's placeholder, never an error surface.
252
+ */
230
253
  export function createUiResourceReader(options) {
231
254
  const fetchImpl = options.fetchImpl ?? fetch;
232
- return async (resourceUri) => {
255
+ const readResource = async (resourceUri) => {
233
256
  const headers = {};
234
257
  const token = options.getAccessToken ? await options.getAccessToken() : null;
235
258
  const guest = sendableGuestSecret(options.guestSecret);
@@ -272,15 +295,18 @@ export function createUiResourceReader(options) {
272
295
  catch {
273
296
  return undefined;
274
297
  }
275
- if (typeof body.uri !== "string" || typeof body.text !== "string")
298
+ // The proxy passes the blob arm through (a blob-only resource is not
299
+ // silently a miss — its route contract); mirror that here.
300
+ if (typeof body.uri !== "string")
301
+ return undefined;
302
+ if (typeof body.text !== "string" && typeof body.blob !== "string")
276
303
  return undefined;
277
304
  return {
278
- channel: resourceUri.startsWith("ui://ggui/") ? "ggui" : "inline",
279
- resource: {
280
- uri: body.uri,
281
- ...(typeof body.mimeType === "string" ? { mimeType: body.mimeType } : {}),
282
- text: body.text,
283
- },
305
+ uri: body.uri,
306
+ ...(typeof body.mimeType === "string" ? { mimeType: body.mimeType } : {}),
307
+ ...(typeof body.text === "string" ? { text: body.text } : {}),
308
+ ...(typeof body.blob === "string" ? { blob: body.blob } : {}),
284
309
  };
285
310
  };
311
+ return createMcpUiResourceReader({ readResource });
286
312
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@guuey/agent-client",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "Client SDK for Guuey's agent runtime: the `useAgentInvoke` React hook + pure SSE helpers that speak the /agent/invoke streaming contract, plus the paginated thread-history read plane. Host adapters (storage / id / transport) are injected, so it runs on web (Next) and React Native alike.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -28,7 +28,8 @@
28
28
  }
29
29
  },
30
30
  "dependencies": {
31
- "@silverprotocol/core": "0.4.1"
31
+ "@silverprotocol/core": "0.4.1",
32
+ "@guuey/mcp-apps-host": "0.3.1"
32
33
  },
33
34
  "peerDependencies": {
34
35
  "react": ">=18"
package/src/index.ts CHANGED
@@ -11,7 +11,6 @@ export { dismissLinkPrompt } from "./link-prompt";
11
11
  export {
12
12
  createUiResourceReader,
13
13
  type CreateUiResourceReaderOptions,
14
- type ResolvedUiResourceMount,
15
14
  createWebAdapters,
16
15
  localStorageThreadStore,
17
16
  webGenerateId,
@@ -6,6 +6,11 @@
6
6
  * functions — never at module load — so this file is import-safe under SSR
7
7
  * (the functions guard on `typeof window`).
8
8
  */
9
+ import {
10
+ createMcpUiResourceReader,
11
+ type McpResourceReadResult,
12
+ type ResolvedViewMount,
13
+ } from "@guuey/mcp-apps-host";
9
14
  import type {
10
15
  AgentInvokeAdapters,
11
16
  InvokeRequest,
@@ -333,39 +338,24 @@ export interface CreateUiResourceReaderOptions {
333
338
  }
334
339
 
335
340
  /**
336
- * Build a `@guuey/mcp-apps-host` `UiResourceReader` over guuey's
337
- * authenticated resources/read proxy (guuey#122 Gap 1:
338
- * `GET /v1/threads/:threadId/ui-resource?uri=…`).
341
+ * Build a `UiResourceReader` over guuey's authenticated resources/read proxy
342
+ * (guuey#122 Gap 1: `GET /v1/threads/:threadId/ui-resource?uri=…`).
339
343
  *
344
+ * This is `@guuey/mcp-apps-host`'s `createMcpUiResourceReader` assembly over
345
+ * a guuey-platform transport (guuey#127) — channel resolution and payload
346
+ * narrowing live in the host package; only the transport is guuey-shaped.
340
347
  * The proxy owns EVERYTHING trust-shaped: caller identity (the same three
341
348
  * families as the history read), thread ownership, the locator-to-thread
342
- * scope guard, and the per-user federation mint. This reader only carries
349
+ * scope guard, and the per-user federation mint. This transport only carries
343
350
  * the surface's existing credential and maps EVERY non-OK — 401/403/404/502
344
351
  * alike — to `undefined`: deny is byte-identical to a miss, and a miss
345
352
  * renders the host's placeholder, never an error surface.
346
- *
347
- * Channel resolution is the phase-1 heuristic: a `ui://ggui/…` uri mounts in
348
- * the ggui-CSP sandbox page (`channel: "ggui"`), anything else in the
349
- * self-only page (`channel: "inline"`). Phase 2 (per-resource declared-CSP
350
- * construction from the response `_meta.ui.csp`) retires the heuristic —
351
- * conformance map, retirement step 3.
352
- */
353
- /**
354
- * The mount the reader resolves — structurally assignable to
355
- * `@guuey/mcp-apps-host`'s `ViewMount` mountable arms (typed inline so this
356
- * package carries no dependency on the host package; hosts that consume
357
- * both see one structural type).
358
353
  */
359
- export interface ResolvedUiResourceMount {
360
- channel: "inline" | "ggui";
361
- resource: { uri: string; mimeType?: string; text: string };
362
- }
363
-
364
354
  export function createUiResourceReader(
365
355
  options: CreateUiResourceReaderOptions,
366
- ): (resourceUri: string) => Promise<ResolvedUiResourceMount | undefined> {
356
+ ): (resourceUri: string) => Promise<ResolvedViewMount | undefined> {
367
357
  const fetchImpl = options.fetchImpl ?? fetch;
368
- return async (resourceUri) => {
358
+ const readResource = async (resourceUri: string): Promise<McpResourceReadResult | undefined> => {
369
359
  const headers: Record<string, string> = {};
370
360
  const token = options.getAccessToken ? await options.getAccessToken() : null;
371
361
  const guest = sendableGuestSecret(options.guestSecret);
@@ -397,20 +387,22 @@ export function createUiResourceReader(
397
387
  }
398
388
  }
399
389
  if (!res.ok) return undefined;
400
- let body: { uri?: unknown; mimeType?: unknown; text?: unknown };
390
+ let body: { uri?: unknown; mimeType?: unknown; text?: unknown; blob?: unknown };
401
391
  try {
402
392
  body = (await res.json()) as typeof body;
403
393
  } catch {
404
394
  return undefined;
405
395
  }
406
- if (typeof body.uri !== "string" || typeof body.text !== "string") return undefined;
396
+ // The proxy passes the blob arm through (a blob-only resource is not
397
+ // silently a miss — its route contract); mirror that here.
398
+ if (typeof body.uri !== "string") return undefined;
399
+ if (typeof body.text !== "string" && typeof body.blob !== "string") return undefined;
407
400
  return {
408
- channel: resourceUri.startsWith("ui://ggui/") ? "ggui" : "inline",
409
- resource: {
410
- uri: body.uri,
411
- ...(typeof body.mimeType === "string" ? { mimeType: body.mimeType } : {}),
412
- text: body.text,
413
- },
401
+ uri: body.uri,
402
+ ...(typeof body.mimeType === "string" ? { mimeType: body.mimeType } : {}),
403
+ ...(typeof body.text === "string" ? { text: body.text } : {}),
404
+ ...(typeof body.blob === "string" ? { blob: body.blob } : {}),
414
405
  };
415
406
  };
407
+ return createMcpUiResourceReader({ readResource });
416
408
  }