@tanstack/ai-react 0.16.1 → 0.16.2

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.
@@ -0,0 +1,20 @@
1
+ import { UIResourcePart } from '@tanstack/ai';
2
+ import { McpAppBridge } from '@tanstack/ai-client';
3
+ import { JSX } from 'react';
4
+ export interface MCPAppResourceProps {
5
+ /** The ui-resource part from a UIMessage assistant part. */
6
+ part: UIResourcePart;
7
+ /**
8
+ * Framework-agnostic bridge for tool calls, prompt sending, and link opening.
9
+ * Omit it to render the widget in display-only mode — iframe interactions
10
+ * that would trigger tool calls or prompts are ignored.
11
+ */
12
+ bridge?: McpAppBridge;
13
+ /** Sandbox iframe configuration — must include the proxy page URL. */
14
+ sandbox: {
15
+ url: URL;
16
+ };
17
+ /** Optional structured arguments forwarded to the guest UI once it's ready. */
18
+ toolInput?: Record<string, unknown>;
19
+ }
20
+ export declare function MCPAppResource(props: MCPAppResourceProps): JSX.Element;
@@ -0,0 +1,52 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { AppRenderer } from "@mcp-ui/client";
3
+ function isRecord(value) {
4
+ return typeof value === "object" && value !== null && !Array.isArray(value);
5
+ }
6
+ function resultToText(result) {
7
+ if (typeof result === "string") return result;
8
+ const stringify = JSON.stringify;
9
+ return stringify(result) ?? "null";
10
+ }
11
+ function MCPAppResource(props) {
12
+ const { bridge } = props;
13
+ return /* @__PURE__ */ jsx(
14
+ AppRenderer,
15
+ {
16
+ toolName: props.part.toolName,
17
+ sandbox: props.sandbox,
18
+ html: props.part.resource.text,
19
+ toolResourceUri: props.part.resource.uri,
20
+ toolInput: props.toolInput,
21
+ onCallTool: bridge ? async ({ name, arguments: args }) => {
22
+ const result = await bridge.callTool({
23
+ serverId: props.part.serverId,
24
+ toolName: name,
25
+ args
26
+ });
27
+ const structuredContent = isRecord(result) ? result : void 0;
28
+ return {
29
+ content: [
30
+ {
31
+ type: "text",
32
+ text: resultToText(result)
33
+ }
34
+ ],
35
+ structuredContent
36
+ };
37
+ } : void 0,
38
+ onMessage: bridge ? async ({ content }) => {
39
+ const text = content.filter(
40
+ (c) => c.type === "text"
41
+ ).map((c) => c.text).join("");
42
+ if (text) await bridge.sendPrompt(text);
43
+ return {};
44
+ } : void 0,
45
+ onOpenLink: bridge ? ({ url }) => Promise.resolve(bridge.openLink(url)) : void 0
46
+ }
47
+ );
48
+ }
49
+ export {
50
+ MCPAppResource
51
+ };
52
+ //# sourceMappingURL=mcp-app-resource.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-app-resource.js","sources":["../../src/mcp-app-resource.tsx"],"sourcesContent":["import { AppRenderer } from '@mcp-ui/client'\nimport type { UIResourcePart } from '@tanstack/ai'\nimport type { McpAppBridge } from '@tanstack/ai-client'\nimport type { JSX } from 'react'\n\nexport interface MCPAppResourceProps {\n /** The ui-resource part from a UIMessage assistant part. */\n part: UIResourcePart\n /**\n * Framework-agnostic bridge for tool calls, prompt sending, and link opening.\n * Omit it to render the widget in display-only mode — iframe interactions\n * that would trigger tool calls or prompts are ignored.\n */\n bridge?: McpAppBridge\n /** Sandbox iframe configuration — must include the proxy page URL. */\n sandbox: { url: URL }\n /** Optional structured arguments forwarded to the guest UI once it's ready. */\n toolInput?: Record<string, unknown>\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\n/**\n * Coalesce an arbitrary bridge result into the `string` required by the\n * `CallToolResult` text content block. `JSON.stringify` is typed to return\n * `string` but actually returns `undefined` for inputs like `undefined` or a\n * function, so we narrow explicitly to avoid `text: undefined`.\n */\nfunction resultToText(result: unknown): string {\n if (typeof result === 'string') return result\n // `JSON.stringify`'s lib signature claims `string`, but it returns\n // `undefined` for `undefined`/function inputs; type the call honestly.\n const stringify: (value: unknown) => string | undefined = JSON.stringify\n return stringify(result) ?? 'null'\n}\n\nexport function MCPAppResource(props: MCPAppResourceProps): JSX.Element {\n const { bridge } = props\n return (\n <AppRenderer\n toolName={props.part.toolName}\n sandbox={props.sandbox}\n html={props.part.resource.text}\n toolResourceUri={props.part.resource.uri}\n toolInput={props.toolInput}\n onCallTool={\n bridge\n ? async ({ name, arguments: args }) => {\n const result = await bridge.callTool({\n serverId: props.part.serverId,\n toolName: name,\n args,\n })\n const structuredContent = isRecord(result) ? result : undefined\n return {\n content: [\n {\n type: 'text' as const,\n text: resultToText(result),\n },\n ],\n structuredContent,\n }\n }\n : undefined\n }\n onMessage={\n bridge\n ? async ({ content }) => {\n const text = content\n .filter(\n (c): c is { type: 'text'; text: string } => c.type === 'text',\n )\n .map((c) => c.text)\n .join('')\n if (text) await bridge.sendPrompt(text)\n return {}\n }\n : undefined\n }\n onOpenLink={\n bridge ? ({ url }) => Promise.resolve(bridge.openLink(url)) : undefined\n }\n />\n )\n}\n"],"names":[],"mappings":";;AAoBA,SAAS,SAAS,OAAkD;AAClE,SAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAC5E;AAQA,SAAS,aAAa,QAAyB;AAC7C,MAAI,OAAO,WAAW,SAAU,QAAO;AAGvC,QAAM,YAAoD,KAAK;AAC/D,SAAO,UAAU,MAAM,KAAK;AAC9B;AAEO,SAAS,eAAe,OAAyC;AACtE,QAAM,EAAE,WAAW;AACnB,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,UAAU,MAAM,KAAK;AAAA,MACrB,SAAS,MAAM;AAAA,MACf,MAAM,MAAM,KAAK,SAAS;AAAA,MAC1B,iBAAiB,MAAM,KAAK,SAAS;AAAA,MACrC,WAAW,MAAM;AAAA,MACjB,YACE,SACI,OAAO,EAAE,MAAM,WAAW,WAAW;AACnC,cAAM,SAAS,MAAM,OAAO,SAAS;AAAA,UACnC,UAAU,MAAM,KAAK;AAAA,UACrB,UAAU;AAAA,UACV;AAAA,QAAA,CACD;AACD,cAAM,oBAAoB,SAAS,MAAM,IAAI,SAAS;AACtD,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM,aAAa,MAAM;AAAA,YAAA;AAAA,UAC3B;AAAA,UAEF;AAAA,QAAA;AAAA,MAEJ,IACA;AAAA,MAEN,WACE,SACI,OAAO,EAAE,cAAc;AACrB,cAAM,OAAO,QACV;AAAA,UACC,CAAC,MAA2C,EAAE,SAAS;AAAA,QAAA,EAExD,IAAI,CAAC,MAAM,EAAE,IAAI,EACjB,KAAK,EAAE;AACV,YAAI,KAAM,OAAM,OAAO,WAAW,IAAI;AACtC,eAAO,CAAA;AAAA,MACT,IACA;AAAA,MAEN,YACE,SAAS,CAAC,EAAE,UAAU,QAAQ,QAAQ,OAAO,SAAS,GAAG,CAAC,IAAI;AAAA,IAAA;AAAA,EAAA;AAItE;"}
@@ -1,20 +1,2 @@
1
- import { UIResourcePart } from '@tanstack/ai';
2
- import { McpAppBridge } from '@tanstack/ai-client';
3
- import { JSX } from 'react';
4
- export interface MCPAppResourceProps {
5
- /** The ui-resource part from a UIMessage assistant part. */
6
- part: UIResourcePart;
7
- /**
8
- * Framework-agnostic bridge for tool calls, prompt sending, and link opening.
9
- * Omit it to render the widget in display-only mode — iframe interactions
10
- * that would trigger tool calls or prompts are ignored.
11
- */
12
- bridge?: McpAppBridge;
13
- /** Sandbox iframe configuration — must include the proxy page URL. */
14
- sandbox: {
15
- url: URL;
16
- };
17
- /** Optional structured arguments forwarded to the guest UI once it's ready. */
18
- toolInput?: Record<string, unknown>;
19
- }
20
- export declare function MCPAppResource(props: MCPAppResourceProps): JSX.Element;
1
+ export type { MCPAppResourceProps } from './mcp-app-resource.js';
2
+ export { MCPAppResource } from './mcp-app-resource.js';
@@ -1,51 +1,4 @@
1
- import { jsx } from "react/jsx-runtime";
2
- import { AppRenderer } from "@mcp-ui/client";
3
- function isRecord(value) {
4
- return typeof value === "object" && value !== null && !Array.isArray(value);
5
- }
6
- function resultToText(result) {
7
- if (typeof result === "string") return result;
8
- const stringify = JSON.stringify;
9
- return stringify(result) ?? "null";
10
- }
11
- function MCPAppResource(props) {
12
- const { bridge } = props;
13
- return /* @__PURE__ */ jsx(
14
- AppRenderer,
15
- {
16
- toolName: props.part.toolName,
17
- sandbox: props.sandbox,
18
- html: props.part.resource.text,
19
- toolResourceUri: props.part.resource.uri,
20
- toolInput: props.toolInput,
21
- onCallTool: bridge ? async ({ name, arguments: args }) => {
22
- const result = await bridge.callTool({
23
- serverId: props.part.serverId,
24
- toolName: name,
25
- args
26
- });
27
- const structuredContent = isRecord(result) ? result : void 0;
28
- return {
29
- content: [
30
- {
31
- type: "text",
32
- text: resultToText(result)
33
- }
34
- ],
35
- structuredContent
36
- };
37
- } : void 0,
38
- onMessage: bridge ? async ({ content }) => {
39
- const text = content.filter(
40
- (c) => c.type === "text"
41
- ).map((c) => c.text).join("");
42
- if (text) await bridge.sendPrompt(text);
43
- return {};
44
- } : void 0,
45
- onOpenLink: bridge ? ({ url }) => Promise.resolve(bridge.openLink(url)) : void 0
46
- }
47
- );
48
- }
1
+ import { MCPAppResource } from "./mcp-app-resource.js";
49
2
  export {
50
3
  MCPAppResource
51
4
  };
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-apps.js","sources":["../../src/mcp-apps.tsx"],"sourcesContent":["import { AppRenderer } from '@mcp-ui/client'\nimport type { UIResourcePart } from '@tanstack/ai'\nimport type { McpAppBridge } from '@tanstack/ai-client'\nimport type { JSX } from 'react'\n\nexport interface MCPAppResourceProps {\n /** The ui-resource part from a UIMessage assistant part. */\n part: UIResourcePart\n /**\n * Framework-agnostic bridge for tool calls, prompt sending, and link opening.\n * Omit it to render the widget in display-only mode — iframe interactions\n * that would trigger tool calls or prompts are ignored.\n */\n bridge?: McpAppBridge\n /** Sandbox iframe configuration — must include the proxy page URL. */\n sandbox: { url: URL }\n /** Optional structured arguments forwarded to the guest UI once it's ready. */\n toolInput?: Record<string, unknown>\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\n/**\n * Coalesce an arbitrary bridge result into the `string` required by the\n * `CallToolResult` text content block. `JSON.stringify` is typed to return\n * `string` but actually returns `undefined` for inputs like `undefined` or a\n * function, so we narrow explicitly to avoid `text: undefined`.\n */\nfunction resultToText(result: unknown): string {\n if (typeof result === 'string') return result\n // `JSON.stringify`'s lib signature claims `string`, but it returns\n // `undefined` for `undefined`/function inputs; type the call honestly.\n const stringify: (value: unknown) => string | undefined = JSON.stringify\n return stringify(result) ?? 'null'\n}\n\nexport function MCPAppResource(props: MCPAppResourceProps): JSX.Element {\n const { bridge } = props\n return (\n <AppRenderer\n toolName={props.part.toolName}\n sandbox={props.sandbox}\n html={props.part.resource.text}\n toolResourceUri={props.part.resource.uri}\n toolInput={props.toolInput}\n onCallTool={\n bridge\n ? async ({ name, arguments: args }) => {\n const result = await bridge.callTool({\n serverId: props.part.serverId,\n toolName: name,\n args,\n })\n const structuredContent = isRecord(result) ? result : undefined\n return {\n content: [\n {\n type: 'text' as const,\n text: resultToText(result),\n },\n ],\n structuredContent,\n }\n }\n : undefined\n }\n onMessage={\n bridge\n ? async ({ content }) => {\n const text = content\n .filter(\n (c): c is { type: 'text'; text: string } => c.type === 'text',\n )\n .map((c) => c.text)\n .join('')\n if (text) await bridge.sendPrompt(text)\n return {}\n }\n : undefined\n }\n onOpenLink={\n bridge ? ({ url }) => Promise.resolve(bridge.openLink(url)) : undefined\n }\n />\n )\n}\n"],"names":[],"mappings":";;AAoBA,SAAS,SAAS,OAAkD;AAClE,SAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAC5E;AAQA,SAAS,aAAa,QAAyB;AAC7C,MAAI,OAAO,WAAW,SAAU,QAAO;AAGvC,QAAM,YAAoD,KAAK;AAC/D,SAAO,UAAU,MAAM,KAAK;AAC9B;AAEO,SAAS,eAAe,OAAyC;AACtE,QAAM,EAAE,WAAW;AACnB,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,UAAU,MAAM,KAAK;AAAA,MACrB,SAAS,MAAM;AAAA,MACf,MAAM,MAAM,KAAK,SAAS;AAAA,MAC1B,iBAAiB,MAAM,KAAK,SAAS;AAAA,MACrC,WAAW,MAAM;AAAA,MACjB,YACE,SACI,OAAO,EAAE,MAAM,WAAW,WAAW;AACnC,cAAM,SAAS,MAAM,OAAO,SAAS;AAAA,UACnC,UAAU,MAAM,KAAK;AAAA,UACrB,UAAU;AAAA,UACV;AAAA,QAAA,CACD;AACD,cAAM,oBAAoB,SAAS,MAAM,IAAI,SAAS;AACtD,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM,aAAa,MAAM;AAAA,YAAA;AAAA,UAC3B;AAAA,UAEF;AAAA,QAAA;AAAA,MAEJ,IACA;AAAA,MAEN,WACE,SACI,OAAO,EAAE,cAAc;AACrB,cAAM,OAAO,QACV;AAAA,UACC,CAAC,MAA2C,EAAE,SAAS;AAAA,QAAA,EAExD,IAAI,CAAC,MAAM,EAAE,IAAI,EACjB,KAAK,EAAE;AACV,YAAI,KAAM,OAAM,OAAO,WAAW,IAAI;AACtC,eAAO,CAAA;AAAA,MACT,IACA;AAAA,MAEN,YACE,SAAS,CAAC,EAAE,UAAU,QAAQ,QAAQ,OAAO,SAAS,GAAG,CAAC,IAAI;AAAA,IAAA;AAAA,EAAA;AAItE;"}
1
+ {"version":3,"file":"mcp-apps.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/ai-react",
3
- "version": "0.16.1",
3
+ "version": "0.16.2",
4
4
  "description": "React hooks for TanStack AI streaming chat, realtime voice, structured outputs, and media generation.",
5
5
  "author": "Tanner Linsley",
6
6
  "license": "MIT",
@@ -0,0 +1,7 @@
1
+ // Barrel entry for the `@tanstack/ai-react/mcp-apps` subpath. The JSX
2
+ // implementation lives in the sibling `.tsx` file; this `.ts` re-export exists
3
+ // so kiira's dist->src resolution (which maps `dist/esm/mcp-apps.d.ts` to
4
+ // `src/mcp-apps.ts`, never `.tsx`) can type-check the docs snippets that import
5
+ // from this subpath.
6
+ export type { MCPAppResourceProps } from './mcp-app-resource'
7
+ export { MCPAppResource } from './mcp-app-resource'
File without changes