@assistant-ui/react-ai-sdk 1.3.32 → 1.3.35
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/client.d.ts +9 -0
- package/dist/client.js +8 -0
- package/dist/frontendTools.d.ts +1 -1
- package/dist/frontendTools.js.map +1 -1
- package/dist/generativeTools.d.ts +18 -4
- package/dist/generativeTools.d.ts.map +1 -1
- package/dist/generativeTools.js +14 -5
- package/dist/generativeTools.js.map +1 -1
- package/dist/index.d.ts +3 -4
- package/dist/index.js +3 -4
- package/dist/index.native.d.ts +9 -0
- package/dist/index.native.js +8 -0
- package/dist/injectQuoteContext.js.map +1 -1
- package/dist/mcp-stdio.node.d.ts +2 -0
- package/dist/mcp-stdio.node.js +2 -0
- package/dist/mcp-stdio.unsupported.d.ts +7 -0
- package/dist/mcp-stdio.unsupported.d.ts.map +1 -0
- package/dist/mcp-stdio.unsupported.js +11 -0
- package/dist/mcp-stdio.unsupported.js.map +1 -0
- package/dist/modelContentEnvelope.d.ts +2 -1
- package/dist/modelContentEnvelope.d.ts.map +1 -1
- package/dist/toolOutputConversion.d.ts +1 -1
- package/dist/ui/resumable.d.ts +2 -1
- package/dist/ui/resumable.d.ts.map +1 -1
- package/dist/ui/resumable.js +1 -1
- package/dist/ui/use-chat/AssistantChatTransport.js +2 -2
- package/dist/ui/use-chat/AssistantChatTransport.js.map +1 -1
- package/dist/ui/use-chat/useAISDKRuntime.d.ts +10 -0
- package/dist/ui/use-chat/useAISDKRuntime.d.ts.map +1 -1
- package/dist/ui/use-chat/useAISDKRuntime.js +13 -4
- package/dist/ui/use-chat/useAISDKRuntime.js.map +1 -1
- package/dist/ui/use-chat/useChatRuntime.d.ts +1 -0
- package/dist/ui/use-chat/useChatRuntime.d.ts.map +1 -1
- package/dist/ui/use-chat/useChatRuntime.js +3 -2
- package/dist/ui/use-chat/useChatRuntime.js.map +1 -1
- package/dist/ui/use-chat/useExternalHistory.d.ts +4 -1
- package/dist/ui/use-chat/useExternalHistory.d.ts.map +1 -1
- package/dist/ui/use-chat/useExternalHistory.js +25 -1
- package/dist/ui/use-chat/useExternalHistory.js.map +1 -1
- package/dist/ui/use-chat/useStreamingTiming.js +1 -1
- package/dist/ui/utils/convertMessage.d.ts +2 -2
- package/dist/ui/utils/convertMessage.d.ts.map +1 -1
- package/dist/ui/utils/convertMessage.js +5 -2
- package/dist/ui/utils/convertMessage.js.map +1 -1
- package/dist/ui/utils/sliceMessagesUntil.js.map +1 -1
- package/dist/ui/utils/toCreateMessage.js.map +1 -1
- package/dist/usage.js.map +1 -1
- package/package.json +28 -12
- package/src/client.ts +18 -0
- package/src/generativeTools.test.ts +29 -47
- package/src/generativeTools.ts +18 -4
- package/src/index.native.ts +3 -0
- package/src/index.ts +1 -16
- package/src/mcp-stdio.node.ts +1 -0
- package/src/mcp-stdio.unsupported.ts +12 -0
- package/src/ui/use-chat/useAISDKRuntime.test.ts +104 -1
- package/src/ui/use-chat/useAISDKRuntime.ts +31 -1
- package/src/ui/use-chat/useChatRuntime.ts +3 -0
- package/src/ui/use-chat/useExternalHistory.ts +30 -1
- package/src/ui/utils/convertMessage.test.ts +36 -5
- package/src/ui/utils/convertMessage.ts +9 -1
- package/dist/assistant-stream/dist/core/AssistantStream.d.ts +0 -1
- package/dist/assistant-stream/dist/core/AssistantStreamChunk.d.ts +0 -1
- package/dist/assistant-stream/dist/core/accumulators/AssistantMessageStream.d.ts +0 -1
- package/dist/assistant-stream/dist/core/accumulators/assistant-message-accumulator.d.ts +0 -1
- package/dist/assistant-stream/dist/core/modules/assistant-stream.d.ts +0 -1
- package/dist/assistant-stream/dist/core/modules/text.d.ts +0 -1
- package/dist/assistant-stream/dist/core/modules/tool-call.d.ts +0 -1
- package/dist/assistant-stream/dist/core/serialization/PlainText.d.ts +0 -1
- package/dist/assistant-stream/dist/core/serialization/assistant-transport/AssistantTransport.d.ts +0 -1
- package/dist/assistant-stream/dist/core/serialization/data-stream/DataStream.d.ts +0 -1
- package/dist/assistant-stream/dist/core/serialization/ui-message-stream/UIMessageStream.d.ts +0 -1
- package/dist/assistant-stream/dist/core/tool/ToolExecutionStream.d.ts +0 -1
- package/dist/assistant-stream/dist/core/tool/schema-utils.d.ts +0 -15
- package/dist/assistant-stream/dist/core/tool/schema-utils.d.ts.map +0 -1
- package/dist/assistant-stream/dist/core/tool/schema-utils.js +0 -59
- package/dist/assistant-stream/dist/core/tool/schema-utils.js.map +0 -1
- package/dist/assistant-stream/dist/core/tool/tool-types.d.ts +0 -69
- package/dist/assistant-stream/dist/core/tool/tool-types.d.ts.map +0 -1
- package/dist/assistant-stream/dist/core/tool/toolResultStream.d.ts +0 -1
- package/dist/assistant-stream/dist/core/utils/stream/AssistantMetaTransformStream.d.ts +0 -1
- package/dist/assistant-stream/dist/core/utils/stream/AssistantTransformStream.d.ts +0 -1
- package/dist/assistant-stream/dist/core/utils/types.d.ts +0 -1
- package/dist/assistant-stream/dist/index.d.ts +0 -2
- package/dist/assistant-stream/dist/node_modules/.pnpm/@types_json-schema@7.0.15/node_modules/@types/json-schema/index.d.ts +0 -140
- package/dist/assistant-stream/dist/node_modules/.pnpm/@types_json-schema@7.0.15/node_modules/@types/json-schema/index.d.ts.map +0 -1
- package/dist/assistant-stream/dist/resumable/createResumableAssistantStreamResponse.d.ts +0 -6
- package/dist/assistant-stream/dist/resumable/createResumableAssistantStreamResponse.d.ts.map +0 -1
- package/dist/assistant-stream/dist/resumable/createResumableAssistantStreamResponse.js +0 -6
- package/dist/assistant-stream/dist/resumable/createResumableAssistantStreamResponse.js.map +0 -1
- package/dist/assistant-stream/dist/resumable/index.d.ts +0 -1
- package/dist/assistant-stream/dist/utils/json/json-value.d.ts +0 -10
- package/dist/assistant-stream/dist/utils/json/json-value.d.ts.map +0 -1
- package/dist/assistant-stream/dist/utils.d.ts +0 -1
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/// <reference types="@assistant-ui/core/react" />
|
|
2
|
+
import { useAISDKRuntime } from "./ui/use-chat/useAISDKRuntime.js";
|
|
3
|
+
import { UseChatRuntimeOptions, useChatRuntime } from "./ui/use-chat/useChatRuntime.js";
|
|
4
|
+
import { AssistantChatResumableOptions, RESUMABLE_STREAM_ID_HEADER, ResumableClientStorage, createResumableSessionStorage } from "./ui/resumable.js";
|
|
5
|
+
import { AssistantChatTransport } from "./ui/use-chat/AssistantChatTransport.js";
|
|
6
|
+
import { frontendTools } from "./frontendTools.js";
|
|
7
|
+
import { injectQuoteContext } from "./injectQuoteContext.js";
|
|
8
|
+
import { ThreadTokenUsage, TokenUsageExtractableMessage, getThreadMessageTokenUsage, useThreadTokenUsage } from "./usage.js";
|
|
9
|
+
export { type AssistantChatResumableOptions, AssistantChatTransport, RESUMABLE_STREAM_ID_HEADER, type ResumableClientStorage, type ThreadTokenUsage, type TokenUsageExtractableMessage, type UseChatRuntimeOptions, createResumableSessionStorage, frontendTools, getThreadMessageTokenUsage, injectQuoteContext, useAISDKRuntime, useChatRuntime, useThreadTokenUsage };
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { useAISDKRuntime } from "./ui/use-chat/useAISDKRuntime.js";
|
|
2
|
+
import { RESUMABLE_STREAM_ID_HEADER, createResumableSessionStorage } from "./ui/resumable.js";
|
|
3
|
+
import { AssistantChatTransport } from "./ui/use-chat/AssistantChatTransport.js";
|
|
4
|
+
import { useChatRuntime } from "./ui/use-chat/useChatRuntime.js";
|
|
5
|
+
import { frontendTools } from "./frontendTools.js";
|
|
6
|
+
import { injectQuoteContext } from "./injectQuoteContext.js";
|
|
7
|
+
import { getThreadMessageTokenUsage, useThreadTokenUsage } from "./usage.js";
|
|
8
|
+
export { AssistantChatTransport, RESUMABLE_STREAM_ID_HEADER, createResumableSessionStorage, frontendTools, getThreadMessageTokenUsage, injectQuoteContext, useAISDKRuntime, useChatRuntime, useThreadTokenUsage };
|
package/dist/frontendTools.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frontendTools.js","names":[],"sources":["../src/frontendTools.ts"],"sourcesContent":["import { jsonSchema, type ToolSet } from \"ai\";\nimport type { ToolJSONSchema } from \"assistant-stream\";\nimport { unwrapModelContentEnvelope } from \"./modelContentEnvelope\";\nimport { toAISDKContent, toAISDKDefaultOutput } from \"./toolOutputConversion\";\n\nexport const defaultToModelOutput = ({ output }: { output: unknown }) => {\n const { result, modelContent } = unwrapModelContentEnvelope(output);\n if (modelContent !== undefined) {\n return toAISDKContent(modelContent);\n }\n return toAISDKDefaultOutput(result);\n};\n\nexport const frontendTools = (tools: Record<string, ToolJSONSchema>): ToolSet =>\n Object.fromEntries(\n Object.entries(tools).map(([name, t]) => [\n name,\n {\n ...(t.description !== undefined && { description: t.description }),\n inputSchema: jsonSchema(t.parameters),\n toModelOutput: defaultToModelOutput,\n ...(t.providerOptions && { providerOptions: t.providerOptions }),\n },\n ]),\n ) as ToolSet;\n"],"mappings":";;;;AAKA,MAAa,wBAAwB,EAAE,aAAkC;CACvE,MAAM,EAAE,QAAQ,iBAAiB,2BAA2B,MAAM;CAClE,IAAI,iBAAiB,KAAA,GACnB,OAAO,eAAe,YAAY;CAEpC,OAAO,qBAAqB,MAAM;AACpC;AAEA,MAAa,iBAAiB,UAC5B,OAAO,YACL,OAAO,QAAQ,KAAK,
|
|
1
|
+
{"version":3,"file":"frontendTools.js","names":[],"sources":["../src/frontendTools.ts"],"sourcesContent":["import { jsonSchema, type ToolSet } from \"ai\";\nimport type { ToolJSONSchema } from \"assistant-stream\";\nimport { unwrapModelContentEnvelope } from \"./modelContentEnvelope\";\nimport { toAISDKContent, toAISDKDefaultOutput } from \"./toolOutputConversion\";\n\nexport const defaultToModelOutput = ({ output }: { output: unknown }) => {\n const { result, modelContent } = unwrapModelContentEnvelope(output);\n if (modelContent !== undefined) {\n return toAISDKContent(modelContent);\n }\n return toAISDKDefaultOutput(result);\n};\n\nexport const frontendTools = (tools: Record<string, ToolJSONSchema>): ToolSet =>\n Object.fromEntries(\n Object.entries(tools).map(([name, t]) => [\n name,\n {\n ...(t.description !== undefined && { description: t.description }),\n inputSchema: jsonSchema(t.parameters),\n toModelOutput: defaultToModelOutput,\n ...(t.providerOptions && { providerOptions: t.providerOptions }),\n },\n ]),\n ) as ToolSet;\n"],"mappings":";;;;AAKA,MAAa,wBAAwB,EAAE,aAAkC;CACvE,MAAM,EAAE,QAAQ,iBAAiB,2BAA2B,MAAM;CAClE,IAAI,iBAAiB,KAAA,GACnB,OAAO,eAAe,YAAY;CAEpC,OAAO,qBAAqB,MAAM;AACpC;AAEA,MAAa,iBAAiB,UAC5B,OAAO,YACL,OAAO,QAAQ,KAAK,CAAC,CAAC,KAAK,CAAC,MAAM,OAAO,CACvC,MACA;CACE,GAAI,EAAE,gBAAgB,KAAA,KAAa,EAAE,aAAa,EAAE,YAAY;CAChE,aAAa,WAAW,EAAE,UAAU;CACpC,eAAe;CACf,GAAI,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,gBAAgB;AAChE,CACF,CAAC,CACH"}
|
|
@@ -1,8 +1,13 @@
|
|
|
1
|
-
import { ToolJSONSchema } from "./assistant-stream/dist/core/tool/schema-utils.js";
|
|
2
1
|
import { ToolSet } from "ai";
|
|
3
2
|
import { Toolkit } from "@assistant-ui/core/react";
|
|
3
|
+
import { ToolJSONSchema } from "assistant-stream";
|
|
4
4
|
|
|
5
5
|
//#region src/generativeTools.d.ts
|
|
6
|
+
/**
|
|
7
|
+
* @deprecated Options for the deprecated {@link generativeTools}. Use
|
|
8
|
+
* {@link AISDKToolkit} with {@link AISDKToolkitOptions} /
|
|
9
|
+
* {@link AISDKToolkitToolsOptions} instead.
|
|
10
|
+
*/
|
|
6
11
|
interface GenerativeToolsOptions {
|
|
7
12
|
/**
|
|
8
13
|
* The server build of a generative toolkit (schema + server `execute`). Typed
|
|
@@ -35,16 +40,25 @@ type AISDKToolkitToolsOptions = {
|
|
|
35
40
|
* resolves to the server build — schema + `execute`, with `render` stripped) and
|
|
36
41
|
* pass it here. Tools without an `execute` are still exposed to the model but
|
|
37
42
|
* left for the client to fulfill. `frontendTools` lets the client contribute
|
|
38
|
-
* tools that aren't in the static toolkit.
|
|
39
|
-
*
|
|
43
|
+
* tools that aren't in the static toolkit.
|
|
44
|
+
*
|
|
45
|
+
* @deprecated Use {@link AISDKToolkit} instead:
|
|
46
|
+
* `new AISDKToolkit({ toolkit }).tools({ frontend })`. It is a strict superset
|
|
47
|
+
* (it also opens MCP server connections), so it replaces `generativeTools`
|
|
48
|
+
* everywhere. The `frontendTools` option is named `frontend` on `.tools()`, and
|
|
49
|
+
* `.tools()` is async. `generativeTools` will be removed in a future version.
|
|
40
50
|
*
|
|
41
51
|
* @example
|
|
42
52
|
* ```ts
|
|
53
|
+
* // Define once at module scope so any MCP connections pool across requests.
|
|
54
|
+
* const aiToolkit = new AISDKToolkit({ toolkit: docsToolkit });
|
|
55
|
+
*
|
|
56
|
+
* // In your route handler:
|
|
43
57
|
* const { tools } = await req.json();
|
|
44
58
|
* streamText({
|
|
45
59
|
* model,
|
|
46
60
|
* messages,
|
|
47
|
-
* tools:
|
|
61
|
+
* tools: await aiToolkit.tools({ frontend: tools }),
|
|
48
62
|
* });
|
|
49
63
|
* ```
|
|
50
64
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generativeTools.d.ts","names":[],"sources":["../src/generativeTools.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"generativeTools.d.ts","names":[],"sources":["../src/generativeTools.ts"],"mappings":";;;;;;;AAsCA;;;UAAiB,sBAAA;EAYgB;;;;;EAN/B,OAAA,EAAS,OAAA;EAMT;;;;AAA6C;EAA7C,aAAA,GAAgB,MAAA,SAAe,cAAA;AAAA;AAAA,KAGrB,mBAAA;EACV,OAAA,EAAS,OAAO;AAAA;AAAA,KAGN,wBAAA;EAAwB;;;EAIlC,QAAA,GAAW,MAAM,SAAS,cAAA;AAAA;;;AAAc;AAkC1C;;;;;;;;AAUC;AAED;;;;;;;;;;;;;;;;;;;cAZa,eAAA,GAAmB,OAAA,EAAS,sBAAA,KAAyB,OAUjE;AAAA,cAEY,YAAA;EAAA;cAIC,OAAA,EAAS,mBAAA;EAIf,KAAA,CAAM,OAAA,GAAS,wBAAA,GAAgC,OAAA,CAAQ,OAAA;EASvD,KAAA,IAAS,OAAA;AAAA"}
|
package/dist/generativeTools.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { unwrapModelContentEnvelope } from "./modelContentEnvelope.js";
|
|
2
2
|
import { toAISDKContent, toAISDKDefaultOutput } from "./toolOutputConversion.js";
|
|
3
3
|
import { frontendTools } from "./frontendTools.js";
|
|
4
|
-
import { toJSONSchema } from "./assistant-stream/dist/core/tool/schema-utils.js";
|
|
5
4
|
import { jsonSchema } from "ai";
|
|
5
|
+
import { toJSONSchema } from "assistant-stream";
|
|
6
6
|
import { createMCPClient } from "@ai-sdk/mcp";
|
|
7
|
-
import { Experimental_StdioMCPTransport } from "
|
|
7
|
+
import { Experimental_StdioMCPTransport } from "#mcp-stdio";
|
|
8
8
|
//#region src/generativeTools.ts
|
|
9
9
|
const EMPTY_SCHEMA = {
|
|
10
10
|
type: "object",
|
|
@@ -24,16 +24,25 @@ const parametersToInputSchema = (parameters) => jsonSchema(parameters ? toJSONSc
|
|
|
24
24
|
* resolves to the server build — schema + `execute`, with `render` stripped) and
|
|
25
25
|
* pass it here. Tools without an `execute` are still exposed to the model but
|
|
26
26
|
* left for the client to fulfill. `frontendTools` lets the client contribute
|
|
27
|
-
* tools that aren't in the static toolkit.
|
|
28
|
-
*
|
|
27
|
+
* tools that aren't in the static toolkit.
|
|
28
|
+
*
|
|
29
|
+
* @deprecated Use {@link AISDKToolkit} instead:
|
|
30
|
+
* `new AISDKToolkit({ toolkit }).tools({ frontend })`. It is a strict superset
|
|
31
|
+
* (it also opens MCP server connections), so it replaces `generativeTools`
|
|
32
|
+
* everywhere. The `frontendTools` option is named `frontend` on `.tools()`, and
|
|
33
|
+
* `.tools()` is async. `generativeTools` will be removed in a future version.
|
|
29
34
|
*
|
|
30
35
|
* @example
|
|
31
36
|
* ```ts
|
|
37
|
+
* // Define once at module scope so any MCP connections pool across requests.
|
|
38
|
+
* const aiToolkit = new AISDKToolkit({ toolkit: docsToolkit });
|
|
39
|
+
*
|
|
40
|
+
* // In your route handler:
|
|
32
41
|
* const { tools } = await req.json();
|
|
33
42
|
* streamText({
|
|
34
43
|
* model,
|
|
35
44
|
* messages,
|
|
36
|
-
* tools:
|
|
45
|
+
* tools: await aiToolkit.tools({ frontend: tools }),
|
|
37
46
|
* });
|
|
38
47
|
* ```
|
|
39
48
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generativeTools.js","names":["#toolkit","#mcpClients","#mcpTools","#mcpClient"],"sources":["../src/generativeTools.ts"],"sourcesContent":["import { jsonSchema, type ToolSet } from \"ai\";\nimport type { MCPClient, MCPClientConfig } from \"@ai-sdk/mcp\";\nimport { createMCPClient } from \"@ai-sdk/mcp\";\nimport { Experimental_StdioMCPTransport } from \"@ai-sdk/mcp/mcp-stdio\";\nimport {\n toJSONSchema,\n type Tool,\n type McpServerConfig,\n type ToolJSONSchema,\n type ToolModelOutputFunction,\n} from \"assistant-stream\";\nimport type { Toolkit, ToolkitDefinition } from \"@assistant-ui/core/react\";\nimport { frontendTools } from \"./frontendTools\";\nimport { toAISDKContent, toAISDKDefaultOutput } from \"./toolOutputConversion\";\nimport {\n unwrapModelContentEnvelope,\n type ModelContentEnvelope,\n} from \"./modelContentEnvelope\";\n\nconst EMPTY_SCHEMA = { type: \"object\" as const, properties: {} };\n\nconst humanNotSupported = (): never => {\n throw new Error(\n \"`human()` is not available during server-side tool execution.\",\n );\n};\n\n// AI SDK leaves `abortSignal` optional; assistant-ui's execute requires one.\nconst neverAbort = new AbortController().signal;\n\nconst parametersToInputSchema = (parameters: Tool[\"parameters\"] | undefined) =>\n jsonSchema(parameters ? toJSONSchema(parameters) : EMPTY_SCHEMA);\n\nexport interface GenerativeToolsOptions {\n /**\n * The server build of a generative toolkit (schema + server `execute`). Typed\n * as the canonical {@link Toolkit} so callers don't need to cast; the server\n * build carries `execute`, recovered internally as {@link ToolkitDefinition}.\n */\n toolkit: Toolkit;\n /**\n * Tools uploaded by the frontend (the request body's `tools`). Merged in\n * alongside the `toolkit`; a server `execute` from `toolkit` takes precedence\n * over an uploaded entry of the same name.\n */\n frontendTools?: Record<string, ToolJSONSchema>;\n}\n\nexport type AISDKToolkitOptions = {\n toolkit: Toolkit;\n};\n\nexport type AISDKToolkitToolsOptions = {\n /**\n * Tools uploaded by the frontend request body.\n */\n frontend?: Record<string, ToolJSONSchema>;\n};\n\n/**\n * Builds an AI SDK `ToolSet` for server-side use with `streamText` /\n * `generateText` from a generative `toolkit` and the frontend-uploaded tools.\n *\n * Each toolkit tool's `execute` runs on the server. Pair this with the\n * `\"use generative\"` compiler: import the toolkit in a server route (where it\n * resolves to the server build — schema + `execute`, with `render` stripped) and\n * pass it here. Tools without an `execute` are still exposed to the model but\n * left for the client to fulfill. `frontendTools` lets the client contribute\n * tools that aren't in the static toolkit. Use {@link AISDKToolkit} when the\n * toolkit contains MCP entries.\n *\n * @example\n * ```ts\n * const { tools } = await req.json();\n * streamText({\n * model,\n * messages,\n * tools: generativeTools({ toolkit: docsToolkit, frontendTools: tools }),\n * });\n * ```\n */\nexport const generativeTools = (options: GenerativeToolsOptions): ToolSet => {\n assertNoMcpToolkitTools(options.toolkit);\n return {\n ...(options.frontendTools ? frontendTools(options.frontendTools) : {}),\n // `toolkit` last so its server-side `execute` wins over an uploaded entry of\n // the same name. The cast recovers the declaration shape — the server build\n // carries `execute`, which the canonical `Toolkit` type erases.\n ...toProviderToolSet(options.toolkit),\n ...toServerToolSet(options.toolkit as ToolkitDefinition),\n };\n};\n\nexport class AISDKToolkit {\n readonly #toolkit: Toolkit;\n readonly #mcpClients = new Map<string, Promise<MCPClient>>();\n\n constructor(options: AISDKToolkitOptions) {\n this.#toolkit = options.toolkit;\n }\n\n async tools(options: AISDKToolkitToolsOptions = {}): Promise<ToolSet> {\n return {\n ...(options.frontend ? frontendTools(options.frontend) : {}),\n ...(await this.#mcpTools()),\n ...toProviderToolSet(this.#toolkit),\n ...toServerToolSet(this.#toolkit as ToolkitDefinition),\n };\n }\n\n async close(): Promise<void> {\n const clientPromises = [...this.#mcpClients.values()];\n this.#mcpClients.clear();\n const results = await Promise.allSettled(clientPromises);\n const clients = results.flatMap((result) =>\n result.status === \"fulfilled\" ? [result.value] : [],\n );\n const closeResults = await Promise.allSettled(\n clients.map((client) => client.close()),\n );\n const errors = [\n ...results.flatMap((result) =>\n result.status === \"rejected\" ? [result.reason] : [],\n ),\n ...closeResults.flatMap((result) =>\n result.status === \"rejected\" ? [result.reason] : [],\n ),\n ];\n if (errors.length === 1) throw errors[0];\n if (errors.length > 1) {\n throw new AggregateError(\n errors,\n \"Failed to close one or more MCP clients\",\n );\n }\n }\n\n async #mcpTools(): Promise<ToolSet> {\n const toolSets = await Promise.all(\n Object.entries(this.#toolkit)\n .filter((entry): entry is [string, McpToolkitTool] =>\n isMcpToolkitTool(entry[1]),\n )\n .map(async ([name, tool]) => {\n const client = await this.#mcpClient(name, tool.server);\n return [name, await client.tools()] as const;\n }),\n );\n\n const tools: ToolSet = {};\n const toolSources = new Map<string, string>();\n for (const [serverName, toolSet] of toolSets) {\n for (const [toolName, tool] of Object.entries(toolSet)) {\n const existingServerName = toolSources.get(toolName);\n if (existingServerName) {\n throw new Error(\n `MCP tool name collision: \"${toolName}\" is exposed by both \"${existingServerName}\" and \"${serverName}\". Rename one of the toolkit entries or expose distinct MCP tool names.`,\n );\n }\n toolSources.set(toolName, serverName);\n tools[toolName] = tool;\n }\n }\n return tools;\n }\n\n #mcpClient(name: string, config: McpServerConfig): Promise<MCPClient> {\n const existing = this.#mcpClients.get(name);\n if (existing) return existing;\n let next: Promise<MCPClient>;\n next = createMCPClient(toMCPClientConfig(config)).catch((error) => {\n if (this.#mcpClients.get(name) === next) {\n this.#mcpClients.delete(name);\n }\n throw error;\n });\n this.#mcpClients.set(name, next);\n return next;\n }\n}\n\nconst toMCPClientConfig = (config: McpServerConfig): MCPClientConfig => {\n if (config.type === \"stdio\") {\n return {\n transport: new Experimental_StdioMCPTransport({\n command: config.command,\n ...(config.args && { args: [...config.args] }),\n ...(config.env && { env: config.env }),\n ...(config.cwd && { cwd: config.cwd }),\n }),\n };\n }\n\n return {\n transport: {\n type: config.type,\n url: config.url,\n ...(config.headers && { headers: config.headers }),\n ...(config.redirect && { redirect: config.redirect }),\n },\n };\n};\n\ntype ToolkitTool = Toolkit[string];\n\ntype McpToolkitTool = ToolkitTool & {\n type: \"mcp\";\n server: McpServerConfig;\n};\n\nconst isMcpToolkitTool = (tool: ToolkitTool): tool is McpToolkitTool =>\n tool.type === \"mcp\" && !tool.disabled;\n\nconst assertNoMcpToolkitTools = (toolkit: Toolkit): void => {\n const mcpToolName = Object.entries(toolkit).find(([, tool]) =>\n isMcpToolkitTool(tool),\n )?.[0];\n if (!mcpToolName) return;\n\n throw new Error(\n `MCP toolkit entry \"${mcpToolName}\" requires AISDKToolkit. Use new AISDKToolkit({ toolkit }).tools(...) instead of generativeTools(...).`,\n );\n};\n\ntype AISDKToModelOutputOptions<TArgs, TResult> = Omit<\n Parameters<ToolModelOutputFunction<TArgs, TResult>>[0],\n \"output\"\n> & {\n output: TResult | ModelContentEnvelope<TResult>;\n};\n\nconst toAISDKToModelOutput =\n <TArgs, TResult>(toModelOutput?: ToolModelOutputFunction<TArgs, TResult>) =>\n async (options: AISDKToModelOutputOptions<TArgs, TResult>) => {\n const { result, modelContent } = unwrapModelContentEnvelope(options.output);\n\n if (modelContent !== undefined) {\n return toAISDKContent(modelContent);\n }\n\n if (!toModelOutput) {\n return toAISDKDefaultOutput(result);\n }\n\n const parts = await toModelOutput({\n ...options,\n output: result,\n });\n return toAISDKContent(parts);\n };\n\nconst toServerToolSet = (toolkit: ToolkitDefinition): ToolSet =>\n Object.fromEntries(\n Object.entries(toolkit)\n .filter(\n ([, t]) => t.type !== \"mcp\" && t.type !== \"provider\" && !t.disabled,\n )\n .map(([name, t]) => {\n const execute = t.execute;\n return [\n name,\n {\n ...(t.description !== undefined && { description: t.description }),\n inputSchema: parametersToInputSchema(t.parameters),\n toModelOutput: toAISDKToModelOutput(t.toModelOutput),\n ...(t.providerOptions && { providerOptions: t.providerOptions }),\n ...(execute && {\n execute: (\n args: unknown,\n callOptions: { toolCallId: string; abortSignal?: AbortSignal },\n ) =>\n execute(args as never, {\n toolCallId: callOptions.toolCallId,\n abortSignal: callOptions.abortSignal ?? neverAbort,\n human: humanNotSupported,\n }),\n }),\n },\n ];\n }),\n ) as ToolSet;\n\nconst toProviderToolSet = (toolkit: Toolkit): ToolSet =>\n Object.fromEntries(\n Object.entries(toolkit)\n .filter((entry): entry is [string, ProviderToolkitTool] =>\n isProviderToolkitTool(entry[1]),\n )\n .map(([name, t]) => [\n name,\n {\n type: \"provider\",\n id: t.providerId,\n args: t.args,\n ...(t.parameters && {\n inputSchema: parametersToInputSchema(t.parameters),\n }),\n ...(t.providerOptions && { providerOptions: t.providerOptions }),\n ...(t.supportsDeferredResults !== undefined && {\n supportsDeferredResults: t.supportsDeferredResults,\n }),\n },\n ]),\n ) as ToolSet;\n\ntype ProviderToolkitTool = Extract<Toolkit[string], { type: \"provider\" }>;\n\nconst isProviderToolkitTool = (\n tool: Toolkit[string],\n): tool is ProviderToolkitTool => tool.type === \"provider\" && !tool.disabled;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"generativeTools.js","names":["#toolkit","#mcpClients","#mcpTools","#mcpClient"],"sources":["../src/generativeTools.ts"],"sourcesContent":["import { jsonSchema, type ToolSet } from \"ai\";\nimport type { MCPClient, MCPClientConfig } from \"@ai-sdk/mcp\";\nimport { createMCPClient } from \"@ai-sdk/mcp\";\nimport { Experimental_StdioMCPTransport } from \"#mcp-stdio\";\nimport {\n toJSONSchema,\n type Tool,\n type McpServerConfig,\n type ToolJSONSchema,\n type ToolModelOutputFunction,\n} from \"assistant-stream\";\nimport type { Toolkit, ToolkitDefinition } from \"@assistant-ui/core/react\";\nimport { frontendTools } from \"./frontendTools\";\nimport { toAISDKContent, toAISDKDefaultOutput } from \"./toolOutputConversion\";\nimport {\n unwrapModelContentEnvelope,\n type ModelContentEnvelope,\n} from \"./modelContentEnvelope\";\n\nconst EMPTY_SCHEMA = { type: \"object\" as const, properties: {} };\n\nconst humanNotSupported = (): never => {\n throw new Error(\n \"`human()` is not available during server-side tool execution.\",\n );\n};\n\n// AI SDK leaves `abortSignal` optional; assistant-ui's execute requires one.\nconst neverAbort = new AbortController().signal;\n\nconst parametersToInputSchema = (parameters: Tool[\"parameters\"] | undefined) =>\n jsonSchema(parameters ? toJSONSchema(parameters) : EMPTY_SCHEMA);\n\n/**\n * @deprecated Options for the deprecated {@link generativeTools}. Use\n * {@link AISDKToolkit} with {@link AISDKToolkitOptions} /\n * {@link AISDKToolkitToolsOptions} instead.\n */\nexport interface GenerativeToolsOptions {\n /**\n * The server build of a generative toolkit (schema + server `execute`). Typed\n * as the canonical {@link Toolkit} so callers don't need to cast; the server\n * build carries `execute`, recovered internally as {@link ToolkitDefinition}.\n */\n toolkit: Toolkit;\n /**\n * Tools uploaded by the frontend (the request body's `tools`). Merged in\n * alongside the `toolkit`; a server `execute` from `toolkit` takes precedence\n * over an uploaded entry of the same name.\n */\n frontendTools?: Record<string, ToolJSONSchema>;\n}\n\nexport type AISDKToolkitOptions = {\n toolkit: Toolkit;\n};\n\nexport type AISDKToolkitToolsOptions = {\n /**\n * Tools uploaded by the frontend request body.\n */\n frontend?: Record<string, ToolJSONSchema>;\n};\n\n/**\n * Builds an AI SDK `ToolSet` for server-side use with `streamText` /\n * `generateText` from a generative `toolkit` and the frontend-uploaded tools.\n *\n * Each toolkit tool's `execute` runs on the server. Pair this with the\n * `\"use generative\"` compiler: import the toolkit in a server route (where it\n * resolves to the server build — schema + `execute`, with `render` stripped) and\n * pass it here. Tools without an `execute` are still exposed to the model but\n * left for the client to fulfill. `frontendTools` lets the client contribute\n * tools that aren't in the static toolkit.\n *\n * @deprecated Use {@link AISDKToolkit} instead:\n * `new AISDKToolkit({ toolkit }).tools({ frontend })`. It is a strict superset\n * (it also opens MCP server connections), so it replaces `generativeTools`\n * everywhere. The `frontendTools` option is named `frontend` on `.tools()`, and\n * `.tools()` is async. `generativeTools` will be removed in a future version.\n *\n * @example\n * ```ts\n * // Define once at module scope so any MCP connections pool across requests.\n * const aiToolkit = new AISDKToolkit({ toolkit: docsToolkit });\n *\n * // In your route handler:\n * const { tools } = await req.json();\n * streamText({\n * model,\n * messages,\n * tools: await aiToolkit.tools({ frontend: tools }),\n * });\n * ```\n */\nexport const generativeTools = (options: GenerativeToolsOptions): ToolSet => {\n assertNoMcpToolkitTools(options.toolkit);\n return {\n ...(options.frontendTools ? frontendTools(options.frontendTools) : {}),\n // `toolkit` last so its server-side `execute` wins over an uploaded entry of\n // the same name. The cast recovers the declaration shape — the server build\n // carries `execute`, which the canonical `Toolkit` type erases.\n ...toProviderToolSet(options.toolkit),\n ...toServerToolSet(options.toolkit as ToolkitDefinition),\n };\n};\n\nexport class AISDKToolkit {\n readonly #toolkit: Toolkit;\n readonly #mcpClients = new Map<string, Promise<MCPClient>>();\n\n constructor(options: AISDKToolkitOptions) {\n this.#toolkit = options.toolkit;\n }\n\n async tools(options: AISDKToolkitToolsOptions = {}): Promise<ToolSet> {\n return {\n ...(options.frontend ? frontendTools(options.frontend) : {}),\n ...(await this.#mcpTools()),\n ...toProviderToolSet(this.#toolkit),\n ...toServerToolSet(this.#toolkit as ToolkitDefinition),\n };\n }\n\n async close(): Promise<void> {\n const clientPromises = [...this.#mcpClients.values()];\n this.#mcpClients.clear();\n const results = await Promise.allSettled(clientPromises);\n const clients = results.flatMap((result) =>\n result.status === \"fulfilled\" ? [result.value] : [],\n );\n const closeResults = await Promise.allSettled(\n clients.map((client) => client.close()),\n );\n const errors = [\n ...results.flatMap((result) =>\n result.status === \"rejected\" ? [result.reason] : [],\n ),\n ...closeResults.flatMap((result) =>\n result.status === \"rejected\" ? [result.reason] : [],\n ),\n ];\n if (errors.length === 1) throw errors[0];\n if (errors.length > 1) {\n throw new AggregateError(\n errors,\n \"Failed to close one or more MCP clients\",\n );\n }\n }\n\n async #mcpTools(): Promise<ToolSet> {\n const toolSets = await Promise.all(\n Object.entries(this.#toolkit)\n .filter((entry): entry is [string, McpToolkitTool] =>\n isMcpToolkitTool(entry[1]),\n )\n .map(async ([name, tool]) => {\n const client = await this.#mcpClient(name, tool.server);\n return [name, await client.tools()] as const;\n }),\n );\n\n const tools: ToolSet = {};\n const toolSources = new Map<string, string>();\n for (const [serverName, toolSet] of toolSets) {\n for (const [toolName, tool] of Object.entries(toolSet)) {\n const existingServerName = toolSources.get(toolName);\n if (existingServerName) {\n throw new Error(\n `MCP tool name collision: \"${toolName}\" is exposed by both \"${existingServerName}\" and \"${serverName}\". Rename one of the toolkit entries or expose distinct MCP tool names.`,\n );\n }\n toolSources.set(toolName, serverName);\n tools[toolName] = tool;\n }\n }\n return tools;\n }\n\n #mcpClient(name: string, config: McpServerConfig): Promise<MCPClient> {\n const existing = this.#mcpClients.get(name);\n if (existing) return existing;\n let next: Promise<MCPClient>;\n next = createMCPClient(toMCPClientConfig(config)).catch((error) => {\n if (this.#mcpClients.get(name) === next) {\n this.#mcpClients.delete(name);\n }\n throw error;\n });\n this.#mcpClients.set(name, next);\n return next;\n }\n}\n\nconst toMCPClientConfig = (config: McpServerConfig): MCPClientConfig => {\n if (config.type === \"stdio\") {\n return {\n transport: new Experimental_StdioMCPTransport({\n command: config.command,\n ...(config.args && { args: [...config.args] }),\n ...(config.env && { env: config.env }),\n ...(config.cwd && { cwd: config.cwd }),\n }),\n };\n }\n\n return {\n transport: {\n type: config.type,\n url: config.url,\n ...(config.headers && { headers: config.headers }),\n ...(config.redirect && { redirect: config.redirect }),\n },\n };\n};\n\ntype ToolkitTool = Toolkit[string];\n\ntype McpToolkitTool = ToolkitTool & {\n type: \"mcp\";\n server: McpServerConfig;\n};\n\nconst isMcpToolkitTool = (tool: ToolkitTool): tool is McpToolkitTool =>\n tool.type === \"mcp\" && !tool.disabled;\n\nconst assertNoMcpToolkitTools = (toolkit: Toolkit): void => {\n const mcpToolName = Object.entries(toolkit).find(([, tool]) =>\n isMcpToolkitTool(tool),\n )?.[0];\n if (!mcpToolName) return;\n\n throw new Error(\n `MCP toolkit entry \"${mcpToolName}\" requires AISDKToolkit. Use new AISDKToolkit({ toolkit }).tools(...) instead of generativeTools(...).`,\n );\n};\n\ntype AISDKToModelOutputOptions<TArgs, TResult> = Omit<\n Parameters<ToolModelOutputFunction<TArgs, TResult>>[0],\n \"output\"\n> & {\n output: TResult | ModelContentEnvelope<TResult>;\n};\n\nconst toAISDKToModelOutput =\n <TArgs, TResult>(toModelOutput?: ToolModelOutputFunction<TArgs, TResult>) =>\n async (options: AISDKToModelOutputOptions<TArgs, TResult>) => {\n const { result, modelContent } = unwrapModelContentEnvelope(options.output);\n\n if (modelContent !== undefined) {\n return toAISDKContent(modelContent);\n }\n\n if (!toModelOutput) {\n return toAISDKDefaultOutput(result);\n }\n\n const parts = await toModelOutput({\n ...options,\n output: result,\n });\n return toAISDKContent(parts);\n };\n\nconst toServerToolSet = (toolkit: ToolkitDefinition): ToolSet =>\n Object.fromEntries(\n Object.entries(toolkit)\n .filter(\n ([, t]) => t.type !== \"mcp\" && t.type !== \"provider\" && !t.disabled,\n )\n .map(([name, t]) => {\n const execute = t.execute;\n return [\n name,\n {\n ...(t.description !== undefined && { description: t.description }),\n inputSchema: parametersToInputSchema(t.parameters),\n toModelOutput: toAISDKToModelOutput(t.toModelOutput),\n ...(t.providerOptions && { providerOptions: t.providerOptions }),\n ...(execute && {\n execute: (\n args: unknown,\n callOptions: { toolCallId: string; abortSignal?: AbortSignal },\n ) =>\n execute(args as never, {\n toolCallId: callOptions.toolCallId,\n abortSignal: callOptions.abortSignal ?? neverAbort,\n human: humanNotSupported,\n }),\n }),\n },\n ];\n }),\n ) as ToolSet;\n\nconst toProviderToolSet = (toolkit: Toolkit): ToolSet =>\n Object.fromEntries(\n Object.entries(toolkit)\n .filter((entry): entry is [string, ProviderToolkitTool] =>\n isProviderToolkitTool(entry[1]),\n )\n .map(([name, t]) => [\n name,\n {\n type: \"provider\",\n id: t.providerId,\n args: t.args,\n ...(t.parameters && {\n inputSchema: parametersToInputSchema(t.parameters),\n }),\n ...(t.providerOptions && { providerOptions: t.providerOptions }),\n ...(t.supportsDeferredResults !== undefined && {\n supportsDeferredResults: t.supportsDeferredResults,\n }),\n },\n ]),\n ) as ToolSet;\n\ntype ProviderToolkitTool = Extract<Toolkit[string], { type: \"provider\" }>;\n\nconst isProviderToolkitTool = (\n tool: Toolkit[string],\n): tool is ProviderToolkitTool => tool.type === \"provider\" && !tool.disabled;\n"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
/// <reference types="@assistant-ui/core/react" />
|
|
2
|
-
import { frontendTools } from "./frontendTools.js";
|
|
3
|
-
import { AISDKToolkit, AISDKToolkitOptions, AISDKToolkitToolsOptions, GenerativeToolsOptions, generativeTools } from "./generativeTools.js";
|
|
4
2
|
import { useAISDKRuntime } from "./ui/use-chat/useAISDKRuntime.js";
|
|
5
3
|
import { UseChatRuntimeOptions, useChatRuntime } from "./ui/use-chat/useChatRuntime.js";
|
|
6
|
-
import { RESUMABLE_STREAM_ID_HEADER } from "./
|
|
7
|
-
import { AssistantChatResumableOptions, ResumableClientStorage, createResumableSessionStorage } from "./ui/resumable.js";
|
|
4
|
+
import { AssistantChatResumableOptions, RESUMABLE_STREAM_ID_HEADER, ResumableClientStorage, createResumableSessionStorage } from "./ui/resumable.js";
|
|
8
5
|
import { AssistantChatTransport } from "./ui/use-chat/AssistantChatTransport.js";
|
|
6
|
+
import { frontendTools } from "./frontendTools.js";
|
|
9
7
|
import { injectQuoteContext } from "./injectQuoteContext.js";
|
|
10
8
|
import { ThreadTokenUsage, TokenUsageExtractableMessage, getThreadMessageTokenUsage, useThreadTokenUsage } from "./usage.js";
|
|
9
|
+
import { AISDKToolkit, AISDKToolkitOptions, AISDKToolkitToolsOptions, GenerativeToolsOptions, generativeTools } from "./generativeTools.js";
|
|
11
10
|
export { AISDKToolkit, type AISDKToolkitOptions, type AISDKToolkitToolsOptions, type AssistantChatResumableOptions, AssistantChatTransport, type GenerativeToolsOptions, RESUMABLE_STREAM_ID_HEADER, type ResumableClientStorage, type ThreadTokenUsage, type TokenUsageExtractableMessage, type UseChatRuntimeOptions, createResumableSessionStorage, frontendTools, generativeTools, getThreadMessageTokenUsage, injectQuoteContext, useAISDKRuntime, useChatRuntime, useThreadTokenUsage };
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import { frontendTools } from "./frontendTools.js";
|
|
2
|
-
import { AISDKToolkit, generativeTools } from "./generativeTools.js";
|
|
3
1
|
import { useAISDKRuntime } from "./ui/use-chat/useAISDKRuntime.js";
|
|
4
|
-
import { RESUMABLE_STREAM_ID_HEADER } from "./
|
|
5
|
-
import { createResumableSessionStorage } from "./ui/resumable.js";
|
|
2
|
+
import { RESUMABLE_STREAM_ID_HEADER, createResumableSessionStorage } from "./ui/resumable.js";
|
|
6
3
|
import { AssistantChatTransport } from "./ui/use-chat/AssistantChatTransport.js";
|
|
7
4
|
import { useChatRuntime } from "./ui/use-chat/useChatRuntime.js";
|
|
5
|
+
import { frontendTools } from "./frontendTools.js";
|
|
8
6
|
import { injectQuoteContext } from "./injectQuoteContext.js";
|
|
9
7
|
import { getThreadMessageTokenUsage, useThreadTokenUsage } from "./usage.js";
|
|
8
|
+
import { AISDKToolkit, generativeTools } from "./generativeTools.js";
|
|
10
9
|
export { AISDKToolkit, AssistantChatTransport, RESUMABLE_STREAM_ID_HEADER, createResumableSessionStorage, frontendTools, generativeTools, getThreadMessageTokenUsage, injectQuoteContext, useAISDKRuntime, useChatRuntime, useThreadTokenUsage };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/// <reference types="@assistant-ui/core/react" />
|
|
2
|
+
import { useAISDKRuntime } from "./ui/use-chat/useAISDKRuntime.js";
|
|
3
|
+
import { UseChatRuntimeOptions, useChatRuntime } from "./ui/use-chat/useChatRuntime.js";
|
|
4
|
+
import { AssistantChatResumableOptions, RESUMABLE_STREAM_ID_HEADER, ResumableClientStorage, createResumableSessionStorage } from "./ui/resumable.js";
|
|
5
|
+
import { AssistantChatTransport } from "./ui/use-chat/AssistantChatTransport.js";
|
|
6
|
+
import { frontendTools } from "./frontendTools.js";
|
|
7
|
+
import { injectQuoteContext } from "./injectQuoteContext.js";
|
|
8
|
+
import { ThreadTokenUsage, TokenUsageExtractableMessage, getThreadMessageTokenUsage, useThreadTokenUsage } from "./usage.js";
|
|
9
|
+
export { type AssistantChatResumableOptions, AssistantChatTransport, RESUMABLE_STREAM_ID_HEADER, type ResumableClientStorage, type ThreadTokenUsage, type TokenUsageExtractableMessage, type UseChatRuntimeOptions, createResumableSessionStorage, frontendTools, getThreadMessageTokenUsage, injectQuoteContext, useAISDKRuntime, useChatRuntime, useThreadTokenUsage };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { useAISDKRuntime } from "./ui/use-chat/useAISDKRuntime.js";
|
|
2
|
+
import { RESUMABLE_STREAM_ID_HEADER, createResumableSessionStorage } from "./ui/resumable.js";
|
|
3
|
+
import { AssistantChatTransport } from "./ui/use-chat/AssistantChatTransport.js";
|
|
4
|
+
import { useChatRuntime } from "./ui/use-chat/useChatRuntime.js";
|
|
5
|
+
import { frontendTools } from "./frontendTools.js";
|
|
6
|
+
import { injectQuoteContext } from "./injectQuoteContext.js";
|
|
7
|
+
import { getThreadMessageTokenUsage, useThreadTokenUsage } from "./usage.js";
|
|
8
|
+
export { AssistantChatTransport, RESUMABLE_STREAM_ID_HEADER, createResumableSessionStorage, frontendTools, getThreadMessageTokenUsage, injectQuoteContext, useAISDKRuntime, useChatRuntime, useThreadTokenUsage };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"injectQuoteContext.js","names":[],"sources":["../src/injectQuoteContext.ts"],"sourcesContent":["import type { UIMessage } from \"ai\";\n\nconst getQuoteText = (metadata: unknown): string | undefined => {\n if (!metadata || typeof metadata !== \"object\") return undefined;\n\n const custom = (metadata as Record<string, unknown>).custom;\n if (!custom || typeof custom !== \"object\") return undefined;\n\n const quote = (custom as Record<string, unknown>).quote;\n if (!quote || typeof quote !== \"object\") return undefined;\n\n const text = (quote as Record<string, unknown>).text;\n return typeof text === \"string\" ? text : undefined;\n};\n\n/**\n * Injects quote context into messages as markdown blockquotes.\n *\n * Use this in your route handler before `convertToModelMessages` so the LLM\n * sees the quoted text that the user is referring to.\n *\n * @example\n * ```ts\n * import { convertToModelMessages, streamText } from \"ai\";\n * import { injectQuoteContext } from \"@assistant-ui/react-ai-sdk\";\n *\n * export async function POST(req: Request) {\n * const { messages } = await req.json();\n * const result = streamText({\n * model: myModel,\n * messages: await convertToModelMessages(injectQuoteContext(messages)),\n * });\n * return result.toUIMessageStreamResponse();\n * }\n * ```\n */\nexport function injectQuoteContext(messages: UIMessage[]): UIMessage[] {\n return messages.map((msg) => {\n if (msg.role !== \"user\") return msg;\n\n const text = getQuoteText(msg.metadata);\n if (!text) return msg;\n\n const blockquote = text\n .split(/\\r?\\n/)\n .map((line) => `> ${line}`)\n .join(\"\\n\");\n\n const alreadyInjected =\n msg.parts[0]?.type === \"text\" &&\n msg.parts[0].text === `${blockquote}\\n\\n`;\n if (alreadyInjected) return msg;\n\n return {\n ...msg,\n parts: [\n { type: \"text\" as const, text: `${blockquote}\\n\\n` },\n ...(msg.parts ?? []),\n ],\n };\n });\n}\n"],"mappings":";AAEA,MAAM,gBAAgB,aAA0C;CAC9D,IAAI,CAAC,YAAY,OAAO,aAAa,UAAU,OAAO,KAAA;CAEtD,MAAM,SAAU,SAAqC;CACrD,IAAI,CAAC,UAAU,OAAO,WAAW,UAAU,OAAO,KAAA;CAElD,MAAM,QAAS,OAAmC;CAClD,IAAI,CAAC,SAAS,OAAO,UAAU,UAAU,OAAO,KAAA;CAEhD,MAAM,OAAQ,MAAkC;CAChD,OAAO,OAAO,SAAS,WAAW,OAAO,KAAA;AAC3C;;;;;;;;;;;;;;;;;;;;;;AAuBA,SAAgB,mBAAmB,UAAoC;CACrE,OAAO,SAAS,KAAK,QAAQ;EAC3B,IAAI,IAAI,SAAS,QAAQ,OAAO;EAEhC,MAAM,OAAO,aAAa,IAAI,QAAQ;EACtC,IAAI,CAAC,MAAM,OAAO;EAElB,MAAM,aAAa,KAChB,MAAM,OAAO,
|
|
1
|
+
{"version":3,"file":"injectQuoteContext.js","names":[],"sources":["../src/injectQuoteContext.ts"],"sourcesContent":["import type { UIMessage } from \"ai\";\n\nconst getQuoteText = (metadata: unknown): string | undefined => {\n if (!metadata || typeof metadata !== \"object\") return undefined;\n\n const custom = (metadata as Record<string, unknown>).custom;\n if (!custom || typeof custom !== \"object\") return undefined;\n\n const quote = (custom as Record<string, unknown>).quote;\n if (!quote || typeof quote !== \"object\") return undefined;\n\n const text = (quote as Record<string, unknown>).text;\n return typeof text === \"string\" ? text : undefined;\n};\n\n/**\n * Injects quote context into messages as markdown blockquotes.\n *\n * Use this in your route handler before `convertToModelMessages` so the LLM\n * sees the quoted text that the user is referring to.\n *\n * @example\n * ```ts\n * import { convertToModelMessages, streamText } from \"ai\";\n * import { injectQuoteContext } from \"@assistant-ui/react-ai-sdk\";\n *\n * export async function POST(req: Request) {\n * const { messages } = await req.json();\n * const result = streamText({\n * model: myModel,\n * messages: await convertToModelMessages(injectQuoteContext(messages)),\n * });\n * return result.toUIMessageStreamResponse();\n * }\n * ```\n */\nexport function injectQuoteContext(messages: UIMessage[]): UIMessage[] {\n return messages.map((msg) => {\n if (msg.role !== \"user\") return msg;\n\n const text = getQuoteText(msg.metadata);\n if (!text) return msg;\n\n const blockquote = text\n .split(/\\r?\\n/)\n .map((line) => `> ${line}`)\n .join(\"\\n\");\n\n const alreadyInjected =\n msg.parts[0]?.type === \"text\" &&\n msg.parts[0].text === `${blockquote}\\n\\n`;\n if (alreadyInjected) return msg;\n\n return {\n ...msg,\n parts: [\n { type: \"text\" as const, text: `${blockquote}\\n\\n` },\n ...(msg.parts ?? []),\n ],\n };\n });\n}\n"],"mappings":";AAEA,MAAM,gBAAgB,aAA0C;CAC9D,IAAI,CAAC,YAAY,OAAO,aAAa,UAAU,OAAO,KAAA;CAEtD,MAAM,SAAU,SAAqC;CACrD,IAAI,CAAC,UAAU,OAAO,WAAW,UAAU,OAAO,KAAA;CAElD,MAAM,QAAS,OAAmC;CAClD,IAAI,CAAC,SAAS,OAAO,UAAU,UAAU,OAAO,KAAA;CAEhD,MAAM,OAAQ,MAAkC;CAChD,OAAO,OAAO,SAAS,WAAW,OAAO,KAAA;AAC3C;;;;;;;;;;;;;;;;;;;;;;AAuBA,SAAgB,mBAAmB,UAAoC;CACrE,OAAO,SAAS,KAAK,QAAQ;EAC3B,IAAI,IAAI,SAAS,QAAQ,OAAO;EAEhC,MAAM,OAAO,aAAa,IAAI,QAAQ;EACtC,IAAI,CAAC,MAAM,OAAO;EAElB,MAAM,aAAa,KAChB,MAAM,OAAO,CAAC,CACd,KAAK,SAAS,KAAK,MAAM,CAAC,CAC1B,KAAK,IAAI;EAKZ,IAFE,IAAI,MAAM,EAAE,EAAE,SAAS,UACvB,IAAI,MAAM,EAAE,CAAC,SAAS,GAAG,WAAW,OACjB,OAAO;EAE5B,OAAO;GACL,GAAG;GACH,OAAO,CACL;IAAE,MAAM;IAAiB,MAAM,GAAG,WAAW;GAAM,GACnD,GAAI,IAAI,SAAS,CAAC,CACpB;EACF;CACF,CAAC;AACH"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Experimental_StdioMCPTransport as Experimental_StdioMCPTransport$1 } from "@ai-sdk/mcp/mcp-stdio";
|
|
2
|
+
|
|
3
|
+
//#region src/mcp-stdio.unsupported.d.ts
|
|
4
|
+
declare const Experimental_StdioMCPTransport: typeof Experimental_StdioMCPTransport$1;
|
|
5
|
+
//#endregion
|
|
6
|
+
export { Experimental_StdioMCPTransport };
|
|
7
|
+
//# sourceMappingURL=mcp-stdio.unsupported.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-stdio.unsupported.d.ts","names":[],"sources":["../src/mcp-stdio.unsupported.ts"],"mappings":";;;cAUa,8BAAA,SACuC,gCAAqB"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//#region src/mcp-stdio.unsupported.ts
|
|
2
|
+
var UnsupportedStdioMCPTransport = class {
|
|
3
|
+
constructor() {
|
|
4
|
+
throw new Error("stdio MCP transport requires a runtime that can spawn a subprocess, such as Node, Bun, or Deno (with --allow-run). Use an HTTP or SSE MCP server config in browser, React Native, edge, or worker runtimes.");
|
|
5
|
+
}
|
|
6
|
+
};
|
|
7
|
+
const Experimental_StdioMCPTransport = UnsupportedStdioMCPTransport;
|
|
8
|
+
//#endregion
|
|
9
|
+
export { Experimental_StdioMCPTransport };
|
|
10
|
+
|
|
11
|
+
//# sourceMappingURL=mcp-stdio.unsupported.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-stdio.unsupported.js","names":[],"sources":["../src/mcp-stdio.unsupported.ts"],"sourcesContent":["import type { Experimental_StdioMCPTransport as NodeStdioMCPTransport } from \"@ai-sdk/mcp/mcp-stdio\";\n\nclass UnsupportedStdioMCPTransport {\n constructor() {\n throw new Error(\n \"stdio MCP transport requires a runtime that can spawn a subprocess, such as Node, Bun, or Deno (with --allow-run). Use an HTTP or SSE MCP server config in browser, React Native, edge, or worker runtimes.\",\n );\n }\n}\n\nexport const Experimental_StdioMCPTransport =\n UnsupportedStdioMCPTransport as unknown as typeof NodeStdioMCPTransport;\n"],"mappings":";AAEA,IAAM,+BAAN,MAAmC;CACjC,cAAc;EACZ,MAAM,IAAI,MACR,6MACF;CACF;AACF;AAEA,MAAa,iCACX"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { ToolModelContentPart } from "
|
|
1
|
+
import { ToolModelContentPart } from "assistant-stream";
|
|
2
|
+
|
|
2
3
|
//#region src/modelContentEnvelope.d.ts
|
|
3
4
|
declare const ENVELOPE_KEY = "__aui_modelContent";
|
|
4
5
|
type ModelContentEnvelope<TResult = unknown> = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"modelContentEnvelope.d.ts","names":[],"sources":["../src/modelContentEnvelope.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"modelContentEnvelope.d.ts","names":[],"sources":["../src/modelContentEnvelope.ts"],"mappings":";;;cAEM,YAAA;AAAA,KAEM,oBAAA;EAAA,UACA,YAAA,YAAwB,oBAAA;EAAA,SACzB,KAAA,EAAO,OAAA;AAAA;AAAA,iBAGF,sBAAA,oBACd,KAAA,EAAO,OAAA,GAAU,oBAAA,CAAqB,OAAA,IACrC,KAAA,IAAS,oBAAA,CAAqB,OAAA;AAAA,iBASjB,wBAAA,UACd,MAAA,EAAQ,OAAA,EACR,YAAA,WAAuB,oBAAA,KACtB,oBAAA,CAAqB,OAAA;AAAA,iBAIR,0BAAA,UACd,MAAA,EAAQ,OAAA,GAAU,oBAAA,CAAqB,OAAA;EAEvC,MAAA,EAAQ,OAAA;EACR,YAAA,YAAwB,oBAAA;AAAA"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ToolModelContentPart } from "./assistant-stream/dist/core/tool/tool-types.js";
|
|
2
1
|
import { JSONValue } from "ai";
|
|
2
|
+
import { ToolModelContentPart } from "assistant-stream";
|
|
3
3
|
|
|
4
4
|
//#region src/toolOutputConversion.d.ts
|
|
5
5
|
declare const toAISDKContent: (parts: readonly ToolModelContentPart[]) => {
|
package/dist/ui/resumable.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { RESUMABLE_STREAM_ID_HEADER } from "
|
|
1
|
+
import { RESUMABLE_STREAM_ID_HEADER } from "assistant-stream/resumable";
|
|
2
|
+
|
|
2
3
|
//#region src/ui/resumable.d.ts
|
|
3
4
|
type ResumableClientStorage = {
|
|
4
5
|
getStreamId(): string | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resumable.d.ts","names":[],"sources":["../../src/ui/resumable.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"resumable.d.ts","names":[],"sources":["../../src/ui/resumable.ts"],"mappings":";;;KAMY,sBAAA;EACV,WAAA;EACA,WAAA,CAAY,EAAA;EACZ,KAAA;AAAA;;iBAIc,6BAAA,CAA8B,OAAA;EAC5C,GAAA;AAAA,IACE,sBAAsB;AAAA,KAkBd,6BAAA;EACV,OAAA,EAAS,sBAAA;EACT,SAAA,aAAsB,QAAA;EAtBR;;;;EA2Bd,aAAA,IAAiB,KAAA,EAAO,UAAU,EAAE,WAAA;AAAA"}
|
package/dist/ui/resumable.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { RESUMABLE_STREAM_ID_HEADER } from "
|
|
2
|
+
import { RESUMABLE_STREAM_ID_HEADER } from "assistant-stream/resumable";
|
|
3
3
|
//#region src/ui/resumable.ts
|
|
4
4
|
const DEFAULT_STORAGE_KEY = "aui-resumable-stream-id";
|
|
5
5
|
/** `sessionStorage`-backed storage for the pending resumable stream id. */
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { RESUMABLE_STREAM_ID_HEADER } from "../../assistant-stream/dist/resumable/createResumableAssistantStreamResponse.js";
|
|
1
|
+
import { RESUMABLE_STREAM_ID_HEADER } from "../resumable.js";
|
|
3
2
|
import { DefaultChatTransport } from "ai";
|
|
3
|
+
import { toToolsJSONSchema } from "assistant-stream";
|
|
4
4
|
//#region src/ui/use-chat/AssistantChatTransport.ts
|
|
5
5
|
const FINISH_MARKER = "\"type\":\"finish\"";
|
|
6
6
|
const FINISH_BUFFER_LIMIT = 4096;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AssistantChatTransport.js","names":[],"sources":["../../../src/ui/use-chat/AssistantChatTransport.ts"],"sourcesContent":["import type {\n AssistantRuntime,\n ThreadListItemRuntime,\n} from \"@assistant-ui/core\";\nimport {\n DefaultChatTransport,\n type HttpChatTransportInitOptions,\n type UIMessage,\n} from \"ai\";\nimport { toToolsJSONSchema } from \"assistant-stream\";\nimport {\n RESUMABLE_STREAM_ID_HEADER,\n type AssistantChatResumableOptions,\n} from \"../resumable\";\n\ntype InitializableThreadListItem = Pick<ThreadListItemRuntime, \"initialize\">;\n\nconst FINISH_MARKER = '\"type\":\"finish\"';\nconst FINISH_BUFFER_LIMIT = 4096;\nconst FINISH_BUFFER_TAIL = 1024;\n\nexport type AssistantChatTransportInitOptions<UI_MESSAGE extends UIMessage> =\n HttpChatTransportInitOptions<UI_MESSAGE> & {\n resumable?: AssistantChatResumableOptions;\n };\n\nexport class AssistantChatTransport<\n UI_MESSAGE extends UIMessage,\n> extends DefaultChatTransport<UI_MESSAGE> {\n private runtime: AssistantRuntime | undefined;\n private getThreadListItem:\n | (() => InitializableThreadListItem | undefined)\n | undefined;\n private readonly resumable: AssistantChatResumableOptions | undefined;\n\n constructor(initOptions?: AssistantChatTransportInitOptions<UI_MESSAGE>) {\n const { resumable, ...rest } = initOptions ?? {};\n const userFetch = rest.fetch;\n const userPrepareReconnect = rest.prepareReconnectToStreamRequest;\n\n super({\n ...rest,\n ...(resumable && {\n fetch: wrapFetchWithResumable(resumable, userFetch),\n prepareReconnectToStreamRequest: wrapPrepareReconnect(\n resumable,\n userPrepareReconnect,\n ),\n }),\n prepareSendMessagesRequest: async (options) => {\n const context = this.runtime?.thread.getModelContext();\n const threadListItem =\n this.getThreadListItem?.() ?? this.runtime?.threads.mainItem;\n const id = (await threadListItem?.initialize())?.remoteId ?? options.id;\n\n const optionsEx = {\n ...options,\n body: {\n callSettings: context?.callSettings,\n system: context?.system,\n config: context?.config,\n tools: toToolsJSONSchema(context?.tools ?? {}),\n ...options?.body,\n },\n };\n const preparedRequest =\n await rest.prepareSendMessagesRequest?.(optionsEx);\n\n return {\n ...preparedRequest,\n body: preparedRequest?.body ?? {\n ...optionsEx.body,\n id,\n messages: options.messages,\n trigger: options.trigger,\n messageId: options.messageId,\n metadata: options.requestMetadata,\n },\n };\n },\n });\n\n this.resumable = resumable;\n }\n\n setRuntime(runtime: AssistantRuntime) {\n this.runtime = runtime;\n }\n\n getResumableAdapter(): AssistantChatResumableOptions | undefined {\n return this.resumable;\n }\n\n __internal_setGetThreadListItem(\n getter: () => InitializableThreadListItem | undefined,\n ) {\n this.getThreadListItem = getter;\n }\n}\n\nfunction wrapFetchWithResumable(\n resumable: AssistantChatResumableOptions,\n userFetch: HttpChatTransportInitOptions<UIMessage>[\"fetch\"],\n): NonNullable<HttpChatTransportInitOptions<UIMessage>[\"fetch\"]> {\n const baseFetch: typeof globalThis.fetch = userFetch\n ? (input, init) => userFetch(input as RequestInfo | URL, init)\n : globalThis.fetch.bind(globalThis);\n\n return async (input, init) => {\n const res = await baseFetch(input, init);\n const id = res.headers.get(RESUMABLE_STREAM_ID_HEADER);\n if (id) resumable.storage.setStreamId(id);\n if (!res.body) return res;\n\n const detectFinish = resumable.isFinishEvent ?? defaultIsFinishEvent;\n // a single decoder is required so multi-byte sequences split across\n // chunks buffer via stream: true rather than getting dropped.\n const decoder = new TextDecoder();\n let accumulator = \"\";\n const tap = new TransformStream<Uint8Array, Uint8Array>({\n transform(chunk, controller) {\n controller.enqueue(chunk);\n accumulator += decoder.decode(chunk, { stream: true });\n if (detectFinish(chunk, accumulator)) {\n resumable.storage.clear();\n accumulator = \"\";\n } else if (accumulator.length > FINISH_BUFFER_LIMIT) {\n accumulator = accumulator.slice(-FINISH_BUFFER_TAIL);\n }\n },\n });\n\n return new Response(res.body.pipeThrough(tap), {\n status: res.status,\n statusText: res.statusText,\n headers: res.headers,\n });\n };\n}\n\nfunction defaultIsFinishEvent(_chunk: Uint8Array, accumulator: string) {\n return accumulator.includes(FINISH_MARKER);\n}\n\nfunction wrapPrepareReconnect(\n resumable: AssistantChatResumableOptions,\n userPrepareReconnect: HttpChatTransportInitOptions<UIMessage>[\"prepareReconnectToStreamRequest\"],\n): NonNullable<\n HttpChatTransportInitOptions<UIMessage>[\"prepareReconnectToStreamRequest\"]\n> {\n return async (options) => {\n const streamId = resumable.storage.getStreamId();\n if (!streamId) {\n throw new Error(\n \"AssistantChatTransport: no resumable stream id available; nothing to resume\",\n );\n }\n const api =\n typeof resumable.resumeApi === \"function\"\n ? resumable.resumeApi(streamId)\n : resumable.resumeApi;\n const userPrepared = await userPrepareReconnect?.({ ...options, api });\n return {\n ...userPrepared,\n api: userPrepared?.api ?? api,\n };\n };\n}\n"],"mappings":";;;;AAiBA,MAAM,gBAAgB;AACtB,MAAM,sBAAsB;AAQ5B,IAAa,yBAAb,cAEU,qBAAiC;CACzC;CACA;CAGA;CAEA,YAAY,aAA6D;EACvE,MAAM,EAAE,WAAW,GAAG,SAAS,eAAe,CAAC;EAC/C,MAAM,YAAY,KAAK;EACvB,MAAM,uBAAuB,KAAK;EAElC,MAAM;GACJ,GAAG;GACH,GAAI,aAAa;IACf,OAAO,uBAAuB,WAAW,SAAS;IAClD,iCAAiC,qBAC/B,WACA,oBACF;GACF;GACA,4BAA4B,OAAO,YAAY;IAC7C,MAAM,UAAU,KAAK,SAAS,OAAO,gBAAgB;IAGrD,MAAM,MAAM,OADV,KAAK,oBAAoB,KAAK,KAAK,SAAS,QAAQ,
|
|
1
|
+
{"version":3,"file":"AssistantChatTransport.js","names":[],"sources":["../../../src/ui/use-chat/AssistantChatTransport.ts"],"sourcesContent":["import type {\n AssistantRuntime,\n ThreadListItemRuntime,\n} from \"@assistant-ui/core\";\nimport {\n DefaultChatTransport,\n type HttpChatTransportInitOptions,\n type UIMessage,\n} from \"ai\";\nimport { toToolsJSONSchema } from \"assistant-stream\";\nimport {\n RESUMABLE_STREAM_ID_HEADER,\n type AssistantChatResumableOptions,\n} from \"../resumable\";\n\ntype InitializableThreadListItem = Pick<ThreadListItemRuntime, \"initialize\">;\n\nconst FINISH_MARKER = '\"type\":\"finish\"';\nconst FINISH_BUFFER_LIMIT = 4096;\nconst FINISH_BUFFER_TAIL = 1024;\n\nexport type AssistantChatTransportInitOptions<UI_MESSAGE extends UIMessage> =\n HttpChatTransportInitOptions<UI_MESSAGE> & {\n resumable?: AssistantChatResumableOptions;\n };\n\nexport class AssistantChatTransport<\n UI_MESSAGE extends UIMessage,\n> extends DefaultChatTransport<UI_MESSAGE> {\n private runtime: AssistantRuntime | undefined;\n private getThreadListItem:\n | (() => InitializableThreadListItem | undefined)\n | undefined;\n private readonly resumable: AssistantChatResumableOptions | undefined;\n\n constructor(initOptions?: AssistantChatTransportInitOptions<UI_MESSAGE>) {\n const { resumable, ...rest } = initOptions ?? {};\n const userFetch = rest.fetch;\n const userPrepareReconnect = rest.prepareReconnectToStreamRequest;\n\n super({\n ...rest,\n ...(resumable && {\n fetch: wrapFetchWithResumable(resumable, userFetch),\n prepareReconnectToStreamRequest: wrapPrepareReconnect(\n resumable,\n userPrepareReconnect,\n ),\n }),\n prepareSendMessagesRequest: async (options) => {\n const context = this.runtime?.thread.getModelContext();\n const threadListItem =\n this.getThreadListItem?.() ?? this.runtime?.threads.mainItem;\n const id = (await threadListItem?.initialize())?.remoteId ?? options.id;\n\n const optionsEx = {\n ...options,\n body: {\n callSettings: context?.callSettings,\n system: context?.system,\n config: context?.config,\n tools: toToolsJSONSchema(context?.tools ?? {}),\n ...options?.body,\n },\n };\n const preparedRequest =\n await rest.prepareSendMessagesRequest?.(optionsEx);\n\n return {\n ...preparedRequest,\n body: preparedRequest?.body ?? {\n ...optionsEx.body,\n id,\n messages: options.messages,\n trigger: options.trigger,\n messageId: options.messageId,\n metadata: options.requestMetadata,\n },\n };\n },\n });\n\n this.resumable = resumable;\n }\n\n setRuntime(runtime: AssistantRuntime) {\n this.runtime = runtime;\n }\n\n getResumableAdapter(): AssistantChatResumableOptions | undefined {\n return this.resumable;\n }\n\n __internal_setGetThreadListItem(\n getter: () => InitializableThreadListItem | undefined,\n ) {\n this.getThreadListItem = getter;\n }\n}\n\nfunction wrapFetchWithResumable(\n resumable: AssistantChatResumableOptions,\n userFetch: HttpChatTransportInitOptions<UIMessage>[\"fetch\"],\n): NonNullable<HttpChatTransportInitOptions<UIMessage>[\"fetch\"]> {\n const baseFetch: typeof globalThis.fetch = userFetch\n ? (input, init) => userFetch(input as RequestInfo | URL, init)\n : globalThis.fetch.bind(globalThis);\n\n return async (input, init) => {\n const res = await baseFetch(input, init);\n const id = res.headers.get(RESUMABLE_STREAM_ID_HEADER);\n if (id) resumable.storage.setStreamId(id);\n if (!res.body) return res;\n\n const detectFinish = resumable.isFinishEvent ?? defaultIsFinishEvent;\n // a single decoder is required so multi-byte sequences split across\n // chunks buffer via stream: true rather than getting dropped.\n const decoder = new TextDecoder();\n let accumulator = \"\";\n const tap = new TransformStream<Uint8Array, Uint8Array>({\n transform(chunk, controller) {\n controller.enqueue(chunk);\n accumulator += decoder.decode(chunk, { stream: true });\n if (detectFinish(chunk, accumulator)) {\n resumable.storage.clear();\n accumulator = \"\";\n } else if (accumulator.length > FINISH_BUFFER_LIMIT) {\n accumulator = accumulator.slice(-FINISH_BUFFER_TAIL);\n }\n },\n });\n\n return new Response(res.body.pipeThrough(tap), {\n status: res.status,\n statusText: res.statusText,\n headers: res.headers,\n });\n };\n}\n\nfunction defaultIsFinishEvent(_chunk: Uint8Array, accumulator: string) {\n return accumulator.includes(FINISH_MARKER);\n}\n\nfunction wrapPrepareReconnect(\n resumable: AssistantChatResumableOptions,\n userPrepareReconnect: HttpChatTransportInitOptions<UIMessage>[\"prepareReconnectToStreamRequest\"],\n): NonNullable<\n HttpChatTransportInitOptions<UIMessage>[\"prepareReconnectToStreamRequest\"]\n> {\n return async (options) => {\n const streamId = resumable.storage.getStreamId();\n if (!streamId) {\n throw new Error(\n \"AssistantChatTransport: no resumable stream id available; nothing to resume\",\n );\n }\n const api =\n typeof resumable.resumeApi === \"function\"\n ? resumable.resumeApi(streamId)\n : resumable.resumeApi;\n const userPrepared = await userPrepareReconnect?.({ ...options, api });\n return {\n ...userPrepared,\n api: userPrepared?.api ?? api,\n };\n };\n}\n"],"mappings":";;;;AAiBA,MAAM,gBAAgB;AACtB,MAAM,sBAAsB;AAQ5B,IAAa,yBAAb,cAEU,qBAAiC;CACzC;CACA;CAGA;CAEA,YAAY,aAA6D;EACvE,MAAM,EAAE,WAAW,GAAG,SAAS,eAAe,CAAC;EAC/C,MAAM,YAAY,KAAK;EACvB,MAAM,uBAAuB,KAAK;EAElC,MAAM;GACJ,GAAG;GACH,GAAI,aAAa;IACf,OAAO,uBAAuB,WAAW,SAAS;IAClD,iCAAiC,qBAC/B,WACA,oBACF;GACF;GACA,4BAA4B,OAAO,YAAY;IAC7C,MAAM,UAAU,KAAK,SAAS,OAAO,gBAAgB;IAGrD,MAAM,MAAM,OADV,KAAK,oBAAoB,KAAK,KAAK,SAAS,QAAQ,SAAA,EACpB,WAAW,EAAA,EAAI,YAAY,QAAQ;IAErE,MAAM,YAAY;KAChB,GAAG;KACH,MAAM;MACJ,cAAc,SAAS;MACvB,QAAQ,SAAS;MACjB,QAAQ,SAAS;MACjB,OAAO,kBAAkB,SAAS,SAAS,CAAC,CAAC;MAC7C,GAAG,SAAS;KACd;IACF;IACA,MAAM,kBACJ,MAAM,KAAK,6BAA6B,SAAS;IAEnD,OAAO;KACL,GAAG;KACH,MAAM,iBAAiB,QAAQ;MAC7B,GAAG,UAAU;MACb;MACA,UAAU,QAAQ;MAClB,SAAS,QAAQ;MACjB,WAAW,QAAQ;MACnB,UAAU,QAAQ;KACpB;IACF;GACF;EACF,CAAC;EAED,KAAK,YAAY;CACnB;CAEA,WAAW,SAA2B;EACpC,KAAK,UAAU;CACjB;CAEA,sBAAiE;EAC/D,OAAO,KAAK;CACd;CAEA,gCACE,QACA;EACA,KAAK,oBAAoB;CAC3B;AACF;AAEA,SAAS,uBACP,WACA,WAC+D;CAC/D,MAAM,YAAqC,aACtC,OAAO,SAAS,UAAU,OAA4B,IAAI,IAC3D,WAAW,MAAM,KAAK,UAAU;CAEpC,OAAO,OAAO,OAAO,SAAS;EAC5B,MAAM,MAAM,MAAM,UAAU,OAAO,IAAI;EACvC,MAAM,KAAK,IAAI,QAAQ,IAAI,0BAA0B;EACrD,IAAI,IAAI,UAAU,QAAQ,YAAY,EAAE;EACxC,IAAI,CAAC,IAAI,MAAM,OAAO;EAEtB,MAAM,eAAe,UAAU,iBAAiB;EAGhD,MAAM,UAAU,IAAI,YAAY;EAChC,IAAI,cAAc;EAClB,MAAM,MAAM,IAAI,gBAAwC,EACtD,UAAU,OAAO,YAAY;GAC3B,WAAW,QAAQ,KAAK;GACxB,eAAe,QAAQ,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC;GACrD,IAAI,aAAa,OAAO,WAAW,GAAG;IACpC,UAAU,QAAQ,MAAM;IACxB,cAAc;GAChB,OAAO,IAAI,YAAY,SAAS,qBAC9B,cAAc,YAAY,MAAM,KAAmB;EAEvD,EACF,CAAC;EAED,OAAO,IAAI,SAAS,IAAI,KAAK,YAAY,GAAG,GAAG;GAC7C,QAAQ,IAAI;GACZ,YAAY,IAAI;GAChB,SAAS,IAAI;EACf,CAAC;CACH;AACF;AAEA,SAAS,qBAAqB,QAAoB,aAAqB;CACrE,OAAO,YAAY,SAAS,aAAa;AAC3C;AAEA,SAAS,qBACP,WACA,sBAGA;CACA,OAAO,OAAO,YAAY;EACxB,MAAM,WAAW,UAAU,QAAQ,YAAY;EAC/C,IAAI,CAAC,UACH,MAAM,IAAI,MACR,6EACF;EAEF,MAAM,MACJ,OAAO,UAAU,cAAc,aAC3B,UAAU,UAAU,QAAQ,IAC5B,UAAU;EAChB,MAAM,eAAe,MAAM,uBAAuB;GAAE,GAAG;GAAS;EAAI,CAAC;EACrE,OAAO;GACL,GAAG;GACH,KAAK,cAAc,OAAO;EAC5B;CACF;AACF"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { JoinStrategy } from "@assistant-ui/core/react";
|
|
1
2
|
import { AppendMessage, AssistantRuntime, ExternalStoreAdapter, ExternalStoreSharedOptions, ThreadHistoryAdapter } from "@assistant-ui/core";
|
|
2
3
|
import { CreateUIMessage, UIMessage, useChat } from "@ai-sdk/react";
|
|
3
4
|
|
|
@@ -25,6 +26,15 @@ type AISDKRuntimeAdapter = ExternalStoreSharedOptions & {
|
|
|
25
26
|
* (for example, an SSE reconnect endpoint keyed by turn id).
|
|
26
27
|
*/
|
|
27
28
|
onResume?: ExternalStoreAdapter["onResume"];
|
|
29
|
+
/**
|
|
30
|
+
* How consecutive assistant messages are rendered.
|
|
31
|
+
*
|
|
32
|
+
* `"concat-content"` (the default) merges them into a single thread message.
|
|
33
|
+
* `"none"` keeps each assistant message as its own thread message, which is
|
|
34
|
+
* useful when a backend persists proactive or consecutive assistant messages
|
|
35
|
+
* as separate entries.
|
|
36
|
+
*/
|
|
37
|
+
joinStrategy?: JoinStrategy | undefined;
|
|
28
38
|
};
|
|
29
39
|
declare const useAISDKRuntime: <UI_MESSAGE extends UIMessage = UIMessage>(chatHelpers: ReturnType<typeof useChat<UI_MESSAGE>>, adapter?: AISDKRuntimeAdapter) => AssistantRuntime;
|
|
30
40
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAISDKRuntime.d.ts","names":[],"sources":["../../../src/ui/use-chat/useAISDKRuntime.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"useAISDKRuntime.d.ts","names":[],"sources":["../../../src/ui/use-chat/useAISDKRuntime.ts"],"mappings":";;;;;KA6CY,6BAAA,uBACS,SAAA,GAAY,SAAA,EAE/B,OAAA,EAAS,aAAA,KACN,eAAA,CAAgB,UAAA;AAAA,KAYT,mBAAA,GAAsB,0BAAA;EAChC,QAAA,IACK,WAAA,CAAY,oBAAA;IACX,OAAA,GAAU,oBAAA;EAAA;EAGhB,eAAA,GAAkB,6BAAA;EArBa;;;;;;;;EA8B/B,4BAAA;EA5BS;;;;;AACoB;AAY/B;EAuBE,QAAA,GAAW,oBAAA;;;;;;;;;EASX,YAAA,GAAe,YAAA;AAAA;AAAA,cAGJ,eAAA,sBAAsC,SAAA,GAAY,SAAA,EAC7D,WAAA,EAAa,UAAA,QAAkB,OAAA,CAAQ,UAAA,IACvC,OAAA,GAAS,mBAAA,KAAwB,gBAAA"}
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { wrapModelContentEnvelope } from "../../modelContentEnvelope.js";
|
|
3
2
|
import { sliceMessagesUntil } from "../utils/sliceMessagesUntil.js";
|
|
4
3
|
import { toCreateMessage } from "../utils/toCreateMessage.js";
|
|
5
4
|
import { vercelAttachmentAdapter } from "../utils/vercelAttachmentAdapter.js";
|
|
6
5
|
import { getVercelAIMessages } from "../getVercelAIMessages.js";
|
|
6
|
+
import { wrapModelContentEnvelope } from "../../modelContentEnvelope.js";
|
|
7
7
|
import { AISDKMessageConverter } from "../utils/convertMessage.js";
|
|
8
8
|
import { aiSDKV6FormatAdapter } from "../adapters/aiSDKFormatAdapter.js";
|
|
9
9
|
import { toExportedMessageRepository, useExternalHistory } from "./useExternalHistory.js";
|
|
10
10
|
import { useStreamingTiming } from "./useStreamingTiming.js";
|
|
11
|
-
import { generateId, isToolUIPart } from "ai";
|
|
12
11
|
import { useMemo, useRef, useState } from "react";
|
|
12
|
+
import { generateId, isToolUIPart } from "ai";
|
|
13
13
|
import { useExternalStoreRuntime, useRuntimeAdapters } from "@assistant-ui/core/react";
|
|
14
14
|
import { getExternalStoreMessages, pickExternalStoreSharedOptions } from "@assistant-ui/core";
|
|
15
15
|
//#region src/ui/use-chat/useAISDKRuntime.ts
|
|
@@ -19,7 +19,7 @@ const toUIMessage = (createMessage, fallbackRole) => ({
|
|
|
19
19
|
role: createMessage.role ?? fallbackRole
|
|
20
20
|
});
|
|
21
21
|
const useAISDKRuntime = (chatHelpers, adapter = {}) => {
|
|
22
|
-
const { adapters, toCreateMessage: customToCreateMessage, cancelPendingToolCallsOnSend = true, onResume } = adapter;
|
|
22
|
+
const { adapters, toCreateMessage: customToCreateMessage, cancelPendingToolCallsOnSend = true, onResume, joinStrategy } = adapter;
|
|
23
23
|
const contextAdapters = useRuntimeAdapters();
|
|
24
24
|
const [toolStatuses, setToolStatuses] = useState({});
|
|
25
25
|
const toolArgsKeyOrderCacheRef = useRef(/* @__PURE__ */ new Map());
|
|
@@ -34,6 +34,7 @@ const useAISDKRuntime = (chatHelpers, adapter = {}) => {
|
|
|
34
34
|
const messages = AISDKMessageConverter.useThreadMessages({
|
|
35
35
|
isRunning,
|
|
36
36
|
messages: chatHelpers.messages,
|
|
37
|
+
joinStrategy,
|
|
37
38
|
metadata: useMemo(() => ({
|
|
38
39
|
toolStatuses,
|
|
39
40
|
messageTiming,
|
|
@@ -52,7 +53,7 @@ const useAISDKRuntime = (chatHelpers, adapter = {}) => {
|
|
|
52
53
|
const [runtimeRef] = useState(() => ({ get current() {
|
|
53
54
|
return runtime;
|
|
54
55
|
} }));
|
|
55
|
-
const isLoading = useExternalHistory(runtimeRef, adapters?.history ?? contextAdapters?.history, AISDKMessageConverter.toThreadMessages, aiSDKV6FormatAdapter, (messages) => {
|
|
56
|
+
const { isLoading, deleteMessage: deleteHistoryMessage } = useExternalHistory(runtimeRef, adapters?.history ?? contextAdapters?.history, AISDKMessageConverter.toThreadMessages, aiSDKV6FormatAdapter, (messages) => {
|
|
56
57
|
chatHelpers.setMessages(messages);
|
|
57
58
|
});
|
|
58
59
|
const completePendingToolCalls = async () => {
|
|
@@ -133,6 +134,14 @@ const useAISDKRuntime = (chatHelpers, adapter = {}) => {
|
|
|
133
134
|
chatHelpers.setMessages((current) => sliceMessagesUntil(current, message.parentId));
|
|
134
135
|
await chatHelpers.sendMessage(createMessage, { metadata: message.runConfig });
|
|
135
136
|
},
|
|
137
|
+
onDelete: async (messageId) => {
|
|
138
|
+
const threadMessages = runtimeRef.current.thread.getState().messages;
|
|
139
|
+
const messageIndex = threadMessages.findIndex((message) => message.id === messageId);
|
|
140
|
+
if (messageIndex === -1) return;
|
|
141
|
+
await deleteHistoryMessage(messageId);
|
|
142
|
+
const deleteIds = new Set(getExternalStoreMessages(threadMessages[messageIndex]).map((message) => message.id));
|
|
143
|
+
chatHelpers.setMessages((current) => current.filter((message) => !deleteIds.has(message.id)));
|
|
144
|
+
},
|
|
136
145
|
onReload: async (parentId, config) => {
|
|
137
146
|
lastRunConfigRef.current = config.runConfig;
|
|
138
147
|
const newMessages = sliceMessagesUntil(chatHelpers.messages, parentId);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAISDKRuntime.js","names":[],"sources":["../../../src/ui/use-chat/useAISDKRuntime.ts"],"sourcesContent":["\"use client\";\n\nimport { useMemo, useRef, useState } from \"react\";\nimport type { UIMessage, useChat, CreateUIMessage } from \"@ai-sdk/react\";\nimport { isToolUIPart, generateId } from \"ai\";\nimport {\n useExternalStoreRuntime,\n useRuntimeAdapters,\n} from \"@assistant-ui/core/react\";\nimport type { ToolExecutionStatus } from \"@assistant-ui/core\";\nimport type {\n ExternalStoreAdapter,\n ExternalStoreSharedOptions,\n ThreadHistoryAdapter,\n AssistantRuntime,\n ThreadMessage,\n MessageFormatAdapter,\n MessageFormatItem,\n MessageFormatRepository,\n AppendMessage,\n RunConfig,\n McpAppMetadata,\n} from \"@assistant-ui/core\";\nimport {\n getExternalStoreMessages,\n pickExternalStoreSharedOptions,\n} from \"@assistant-ui/core\";\nimport type { ReadonlyJSONObject } from \"assistant-stream/utils\";\nimport { sliceMessagesUntil } from \"../utils/sliceMessagesUntil\";\nimport { toCreateMessage } from \"../utils/toCreateMessage\";\nimport { vercelAttachmentAdapter } from \"../utils/vercelAttachmentAdapter\";\nimport { getVercelAIMessages } from \"../getVercelAIMessages\";\nimport { AISDKMessageConverter } from \"../utils/convertMessage\";\nimport { wrapModelContentEnvelope } from \"../../modelContentEnvelope\";\nimport {\n type AISDKStorageFormat,\n aiSDKV6FormatAdapter,\n} from \"../adapters/aiSDKFormatAdapter\";\nimport {\n useExternalHistory,\n toExportedMessageRepository,\n} from \"./useExternalHistory\";\nimport { useStreamingTiming } from \"./useStreamingTiming\";\n\nexport type CustomToCreateMessageFunction = <\n UI_MESSAGE extends UIMessage = UIMessage,\n>(\n message: AppendMessage,\n) => CreateUIMessage<UI_MESSAGE>;\n\nconst toUIMessage = <UI_MESSAGE extends UIMessage>(\n createMessage: CreateUIMessage<UI_MESSAGE>,\n fallbackRole: UI_MESSAGE[\"role\"],\n): UI_MESSAGE =>\n ({\n ...createMessage,\n id: createMessage.id ?? generateId(),\n role: createMessage.role ?? fallbackRole,\n }) as UI_MESSAGE;\n\nexport type AISDKRuntimeAdapter = ExternalStoreSharedOptions & {\n adapters?:\n | (NonNullable<ExternalStoreAdapter[\"adapters\"]> & {\n history?: ThreadHistoryAdapter | undefined;\n })\n | undefined;\n toCreateMessage?: CustomToCreateMessageFunction;\n /**\n * Whether to automatically cancel pending interactive tool calls when the user sends a new message.\n *\n * When enabled (default), the pending tool calls will be marked as failed with an error message\n * indicating the user cancelled the tool call by sending a new message.\n *\n * @default true\n */\n cancelPendingToolCallsOnSend?: boolean | undefined;\n /**\n * Called when `runtime.thread.resumeRun(config)` is invoked.\n *\n * When omitted, `resumeRun` throws `\"Runtime does not support resuming runs.\"`.\n * Provide this to bridge resume invocations into a custom replay channel\n * (for example, an SSE reconnect endpoint keyed by turn id).\n */\n onResume?: ExternalStoreAdapter[\"onResume\"];\n};\n\nexport const useAISDKRuntime = <UI_MESSAGE extends UIMessage = UIMessage>(\n chatHelpers: ReturnType<typeof useChat<UI_MESSAGE>>,\n adapter: AISDKRuntimeAdapter = {},\n) => {\n const {\n adapters,\n toCreateMessage: customToCreateMessage,\n cancelPendingToolCallsOnSend = true,\n onResume,\n } = adapter;\n const contextAdapters = useRuntimeAdapters();\n const [toolStatuses, setToolStatuses] = useState<\n Record<string, ToolExecutionStatus>\n >({});\n const toolArgsKeyOrderCacheRef = useRef<Map<string, Map<string, string[]>>>(\n new Map(),\n );\n const toolLastInputCacheRef = useRef<Map<string, ReadonlyJSONObject>>(\n new Map(),\n );\n const mcpAppMetadataCacheRef = useRef<Map<string, McpAppMetadata>>(new Map());\n const lastRunConfigRef = useRef<RunConfig | undefined>(undefined);\n\n const hasExecutingTools = Object.values(toolStatuses).some(\n (s) => s?.type === \"executing\",\n );\n const isRunning =\n chatHelpers.status === \"submitted\" ||\n chatHelpers.status === \"streaming\" ||\n hasExecutingTools;\n\n const messageTiming = useStreamingTiming(chatHelpers.messages, isRunning);\n\n // Flag the streaming message optimistic: its id can be swapped for a server\n // id mid-run, and the repository then drops the orphaned pre-swap id (#4037).\n const lastMessage = chatHelpers.messages.at(-1);\n const optimisticMessageId =\n isRunning && lastMessage?.role === \"assistant\" ? lastMessage.id : undefined;\n\n const messages = AISDKMessageConverter.useThreadMessages({\n isRunning,\n messages: chatHelpers.messages,\n metadata: useMemo(\n () => ({\n toolStatuses,\n messageTiming,\n toolArgsKeyOrderCache: toolArgsKeyOrderCacheRef.current,\n toolLastInputCache: toolLastInputCacheRef.current,\n mcpAppMetadataCache: mcpAppMetadataCacheRef.current,\n ...(optimisticMessageId && { optimisticMessageId }),\n ...(chatHelpers.error && { error: chatHelpers.error.message }),\n }),\n [toolStatuses, messageTiming, optimisticMessageId, chatHelpers.error],\n ),\n });\n\n const [runtimeRef] = useState(() => ({\n get current(): AssistantRuntime {\n return runtime;\n },\n }));\n\n const isLoading = useExternalHistory(\n runtimeRef,\n adapters?.history ?? contextAdapters?.history,\n AISDKMessageConverter.toThreadMessages as (\n messages: UI_MESSAGE[],\n ) => ThreadMessage[],\n aiSDKV6FormatAdapter as MessageFormatAdapter<\n UI_MESSAGE,\n AISDKStorageFormat\n >,\n (messages) => {\n chatHelpers.setMessages(messages);\n },\n );\n\n const completePendingToolCalls = async () => {\n if (!cancelPendingToolCallsOnSend) return;\n\n // The runtime auto-aborts in-flight tool invocations when a new run\n // is dispatched (append() / startRun()). All we need to do here is\n // mark any tool without a result as cancelled in the UI message list.\n\n // Mark any tool without a result as cancelled (uses setMessages to avoid triggering sendAutomaticallyWhen)\n chatHelpers.setMessages((messages) => {\n const lastMessage = messages.at(-1);\n if (lastMessage?.role !== \"assistant\") return messages;\n\n let hasChanges = false;\n const parts = lastMessage.parts?.map((part) => {\n if (!isToolUIPart(part)) return part;\n if (part.state === \"output-available\" || part.state === \"output-error\")\n return part;\n\n hasChanges = true;\n const { approval: _approval, ...rest } = part;\n return {\n ...rest,\n state: \"output-error\" as const,\n errorText: \"User cancelled tool call by sending a new message.\",\n };\n });\n\n if (!hasChanges) return messages;\n return [...messages.slice(0, -1), { ...lastMessage, parts }];\n });\n };\n\n const runtime = useExternalStoreRuntime({\n isRunning,\n messages,\n unstable_enableToolInvocations: true,\n setToolStatuses,\n setMessages: (messages) =>\n chatHelpers.setMessages(\n messages\n .map(getVercelAIMessages<UI_MESSAGE>)\n .filter(Boolean)\n .flat(),\n ),\n onImport: (messages) =>\n chatHelpers.setMessages(\n messages\n .map(getVercelAIMessages<UI_MESSAGE>)\n .filter(Boolean)\n .flat(),\n ),\n onExportExternalState: (): MessageFormatRepository<UI_MESSAGE> => {\n const exported = runtimeRef.current.thread.export();\n\n const expandedMessages: MessageFormatItem<UI_MESSAGE>[] = [];\n const lastInnerIdMap = new Map<string, string>();\n\n for (const item of exported.messages) {\n const innerMessages = getExternalStoreMessages<UI_MESSAGE>(\n item.message,\n );\n let parentId =\n item.parentId != null\n ? (lastInnerIdMap.get(item.parentId) ?? item.parentId)\n : null;\n for (const innerMessage of innerMessages) {\n expandedMessages.push({ parentId, message: innerMessage });\n parentId = aiSDKV6FormatAdapter.getId(innerMessage as UIMessage);\n }\n if (innerMessages.length > 0) {\n lastInnerIdMap.set(\n item.message.id,\n aiSDKV6FormatAdapter.getId(\n innerMessages[innerMessages.length - 1]! as UIMessage,\n ),\n );\n }\n }\n\n const result: MessageFormatRepository<UI_MESSAGE> = {\n messages: expandedMessages,\n };\n\n if (exported.headId != null) {\n result.headId = lastInnerIdMap.get(exported.headId) ?? exported.headId;\n }\n\n return result;\n },\n onLoadExternalState: (repo: MessageFormatRepository<UI_MESSAGE>) => {\n // Convert MessageFormatRepository to ExportedMessageRepository\n const exportedRepo = toExportedMessageRepository(\n AISDKMessageConverter.toThreadMessages,\n repo,\n );\n\n // Import into the thread's MessageRepository\n runtimeRef.current.thread.import(exportedRepo);\n },\n onCancel: async () => {\n chatHelpers.stop();\n },\n onNew: async (message) => {\n const createMessage = (\n customToCreateMessage ?? toCreateMessage\n )<UI_MESSAGE>(message);\n\n if (!(message.startRun ?? message.role === \"user\")) {\n chatHelpers.setMessages((current) => [\n ...current,\n toUIMessage<UI_MESSAGE>(createMessage, message.role),\n ]);\n return;\n }\n\n lastRunConfigRef.current = message.runConfig;\n await completePendingToolCalls();\n await chatHelpers.sendMessage(createMessage, {\n metadata: message.runConfig,\n });\n },\n onEdit: async (message) => {\n const createMessage = (\n customToCreateMessage ?? toCreateMessage\n )<UI_MESSAGE>(message);\n\n if (!(message.startRun ?? message.role === \"user\")) {\n chatHelpers.setMessages((current) => [\n ...sliceMessagesUntil(current, message.parentId),\n toUIMessage<UI_MESSAGE>(createMessage, message.role),\n ]);\n return;\n }\n\n lastRunConfigRef.current = message.runConfig;\n chatHelpers.setMessages((current) =>\n sliceMessagesUntil(current, message.parentId),\n );\n await chatHelpers.sendMessage(createMessage, {\n metadata: message.runConfig,\n });\n },\n onReload: async (parentId: string | null, config) => {\n lastRunConfigRef.current = config.runConfig;\n const newMessages = sliceMessagesUntil(chatHelpers.messages, parentId);\n chatHelpers.setMessages(newMessages);\n\n await chatHelpers.regenerate({ metadata: config.runConfig });\n },\n onAddToolResult: ({\n toolCallId,\n toolName,\n result,\n isError,\n modelContent,\n }) => {\n const options = { metadata: lastRunConfigRef.current };\n if (isError) {\n chatHelpers.addToolOutput({\n state: \"output-error\",\n tool: toolName ?? toolCallId,\n toolCallId,\n errorText:\n typeof result === \"string\" ? result : JSON.stringify(result),\n options,\n });\n } else {\n const output =\n modelContent !== undefined\n ? wrapModelContentEnvelope(result, modelContent)\n : result;\n chatHelpers.addToolResult({\n tool: toolName,\n toolCallId,\n output,\n options,\n });\n }\n },\n onRespondToToolApproval: ({ approvalId, approved, reason }) => {\n void chatHelpers.addToolApprovalResponse({\n id: approvalId,\n approved,\n ...(reason != null && { reason }),\n options: { metadata: lastRunConfigRef.current },\n });\n },\n ...pickExternalStoreSharedOptions(adapter),\n ...(onResume && { onResume }),\n adapters: {\n attachments: vercelAttachmentAdapter,\n ...contextAdapters,\n ...adapters,\n },\n isLoading,\n });\n\n return runtime;\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useAISDKRuntime.js","names":[],"sources":["../../../src/ui/use-chat/useAISDKRuntime.ts"],"sourcesContent":["\"use client\";\n\nimport { useMemo, useRef, useState } from \"react\";\nimport type { UIMessage, useChat, CreateUIMessage } from \"@ai-sdk/react\";\nimport { isToolUIPart, generateId } from \"ai\";\nimport {\n useExternalStoreRuntime,\n useRuntimeAdapters,\n type JoinStrategy,\n} from \"@assistant-ui/core/react\";\nimport type { ToolExecutionStatus } from \"@assistant-ui/core\";\nimport type {\n ExternalStoreAdapter,\n ExternalStoreSharedOptions,\n ThreadHistoryAdapter,\n AssistantRuntime,\n ThreadMessage,\n MessageFormatAdapter,\n MessageFormatItem,\n MessageFormatRepository,\n AppendMessage,\n RunConfig,\n McpAppMetadata,\n} from \"@assistant-ui/core\";\nimport {\n getExternalStoreMessages,\n pickExternalStoreSharedOptions,\n} from \"@assistant-ui/core\";\nimport type { ReadonlyJSONObject } from \"assistant-stream/utils\";\nimport { sliceMessagesUntil } from \"../utils/sliceMessagesUntil\";\nimport { toCreateMessage } from \"../utils/toCreateMessage\";\nimport { vercelAttachmentAdapter } from \"../utils/vercelAttachmentAdapter\";\nimport { getVercelAIMessages } from \"../getVercelAIMessages\";\nimport { AISDKMessageConverter } from \"../utils/convertMessage\";\nimport { wrapModelContentEnvelope } from \"../../modelContentEnvelope\";\nimport {\n type AISDKStorageFormat,\n aiSDKV6FormatAdapter,\n} from \"../adapters/aiSDKFormatAdapter\";\nimport {\n useExternalHistory,\n toExportedMessageRepository,\n} from \"./useExternalHistory\";\nimport { useStreamingTiming } from \"./useStreamingTiming\";\n\nexport type CustomToCreateMessageFunction = <\n UI_MESSAGE extends UIMessage = UIMessage,\n>(\n message: AppendMessage,\n) => CreateUIMessage<UI_MESSAGE>;\n\nconst toUIMessage = <UI_MESSAGE extends UIMessage>(\n createMessage: CreateUIMessage<UI_MESSAGE>,\n fallbackRole: UI_MESSAGE[\"role\"],\n): UI_MESSAGE =>\n ({\n ...createMessage,\n id: createMessage.id ?? generateId(),\n role: createMessage.role ?? fallbackRole,\n }) as UI_MESSAGE;\n\nexport type AISDKRuntimeAdapter = ExternalStoreSharedOptions & {\n adapters?:\n | (NonNullable<ExternalStoreAdapter[\"adapters\"]> & {\n history?: ThreadHistoryAdapter | undefined;\n })\n | undefined;\n toCreateMessage?: CustomToCreateMessageFunction;\n /**\n * Whether to automatically cancel pending interactive tool calls when the user sends a new message.\n *\n * When enabled (default), the pending tool calls will be marked as failed with an error message\n * indicating the user cancelled the tool call by sending a new message.\n *\n * @default true\n */\n cancelPendingToolCallsOnSend?: boolean | undefined;\n /**\n * Called when `runtime.thread.resumeRun(config)` is invoked.\n *\n * When omitted, `resumeRun` throws `\"Runtime does not support resuming runs.\"`.\n * Provide this to bridge resume invocations into a custom replay channel\n * (for example, an SSE reconnect endpoint keyed by turn id).\n */\n onResume?: ExternalStoreAdapter[\"onResume\"];\n /**\n * How consecutive assistant messages are rendered.\n *\n * `\"concat-content\"` (the default) merges them into a single thread message.\n * `\"none\"` keeps each assistant message as its own thread message, which is\n * useful when a backend persists proactive or consecutive assistant messages\n * as separate entries.\n */\n joinStrategy?: JoinStrategy | undefined;\n};\n\nexport const useAISDKRuntime = <UI_MESSAGE extends UIMessage = UIMessage>(\n chatHelpers: ReturnType<typeof useChat<UI_MESSAGE>>,\n adapter: AISDKRuntimeAdapter = {},\n) => {\n const {\n adapters,\n toCreateMessage: customToCreateMessage,\n cancelPendingToolCallsOnSend = true,\n onResume,\n joinStrategy,\n } = adapter;\n const contextAdapters = useRuntimeAdapters();\n const [toolStatuses, setToolStatuses] = useState<\n Record<string, ToolExecutionStatus>\n >({});\n const toolArgsKeyOrderCacheRef = useRef<Map<string, Map<string, string[]>>>(\n new Map(),\n );\n const toolLastInputCacheRef = useRef<Map<string, ReadonlyJSONObject>>(\n new Map(),\n );\n const mcpAppMetadataCacheRef = useRef<Map<string, McpAppMetadata>>(new Map());\n const lastRunConfigRef = useRef<RunConfig | undefined>(undefined);\n\n const hasExecutingTools = Object.values(toolStatuses).some(\n (s) => s?.type === \"executing\",\n );\n const isRunning =\n chatHelpers.status === \"submitted\" ||\n chatHelpers.status === \"streaming\" ||\n hasExecutingTools;\n\n const messageTiming = useStreamingTiming(chatHelpers.messages, isRunning);\n\n // Flag the streaming message optimistic: its id can be swapped for a server\n // id mid-run, and the repository then drops the orphaned pre-swap id (#4037).\n const lastMessage = chatHelpers.messages.at(-1);\n const optimisticMessageId =\n isRunning && lastMessage?.role === \"assistant\" ? lastMessage.id : undefined;\n\n const messages = AISDKMessageConverter.useThreadMessages({\n isRunning,\n messages: chatHelpers.messages,\n joinStrategy,\n metadata: useMemo(\n () => ({\n toolStatuses,\n messageTiming,\n toolArgsKeyOrderCache: toolArgsKeyOrderCacheRef.current,\n toolLastInputCache: toolLastInputCacheRef.current,\n mcpAppMetadataCache: mcpAppMetadataCacheRef.current,\n ...(optimisticMessageId && { optimisticMessageId }),\n ...(chatHelpers.error && { error: chatHelpers.error.message }),\n }),\n [toolStatuses, messageTiming, optimisticMessageId, chatHelpers.error],\n ),\n });\n\n const [runtimeRef] = useState(() => ({\n get current(): AssistantRuntime {\n return runtime;\n },\n }));\n\n const { isLoading, deleteMessage: deleteHistoryMessage } = useExternalHistory(\n runtimeRef,\n adapters?.history ?? contextAdapters?.history,\n AISDKMessageConverter.toThreadMessages as (\n messages: UI_MESSAGE[],\n ) => ThreadMessage[],\n aiSDKV6FormatAdapter as MessageFormatAdapter<\n UI_MESSAGE,\n AISDKStorageFormat\n >,\n (messages) => {\n chatHelpers.setMessages(messages);\n },\n );\n\n const completePendingToolCalls = async () => {\n if (!cancelPendingToolCallsOnSend) return;\n\n // The runtime auto-aborts in-flight tool invocations when a new run\n // is dispatched (append() / startRun()). All we need to do here is\n // mark any tool without a result as cancelled in the UI message list.\n\n // Mark any tool without a result as cancelled (uses setMessages to avoid triggering sendAutomaticallyWhen)\n chatHelpers.setMessages((messages) => {\n const lastMessage = messages.at(-1);\n if (lastMessage?.role !== \"assistant\") return messages;\n\n let hasChanges = false;\n const parts = lastMessage.parts?.map((part) => {\n if (!isToolUIPart(part)) return part;\n if (part.state === \"output-available\" || part.state === \"output-error\")\n return part;\n\n hasChanges = true;\n const { approval: _approval, ...rest } = part;\n return {\n ...rest,\n state: \"output-error\" as const,\n errorText: \"User cancelled tool call by sending a new message.\",\n };\n });\n\n if (!hasChanges) return messages;\n return [...messages.slice(0, -1), { ...lastMessage, parts }];\n });\n };\n\n const runtime = useExternalStoreRuntime({\n isRunning,\n messages,\n unstable_enableToolInvocations: true,\n setToolStatuses,\n setMessages: (messages) =>\n chatHelpers.setMessages(\n messages\n .map(getVercelAIMessages<UI_MESSAGE>)\n .filter(Boolean)\n .flat(),\n ),\n onImport: (messages) =>\n chatHelpers.setMessages(\n messages\n .map(getVercelAIMessages<UI_MESSAGE>)\n .filter(Boolean)\n .flat(),\n ),\n onExportExternalState: (): MessageFormatRepository<UI_MESSAGE> => {\n const exported = runtimeRef.current.thread.export();\n\n const expandedMessages: MessageFormatItem<UI_MESSAGE>[] = [];\n const lastInnerIdMap = new Map<string, string>();\n\n for (const item of exported.messages) {\n const innerMessages = getExternalStoreMessages<UI_MESSAGE>(\n item.message,\n );\n let parentId =\n item.parentId != null\n ? (lastInnerIdMap.get(item.parentId) ?? item.parentId)\n : null;\n for (const innerMessage of innerMessages) {\n expandedMessages.push({ parentId, message: innerMessage });\n parentId = aiSDKV6FormatAdapter.getId(innerMessage as UIMessage);\n }\n if (innerMessages.length > 0) {\n lastInnerIdMap.set(\n item.message.id,\n aiSDKV6FormatAdapter.getId(\n innerMessages[innerMessages.length - 1]! as UIMessage,\n ),\n );\n }\n }\n\n const result: MessageFormatRepository<UI_MESSAGE> = {\n messages: expandedMessages,\n };\n\n if (exported.headId != null) {\n result.headId = lastInnerIdMap.get(exported.headId) ?? exported.headId;\n }\n\n return result;\n },\n onLoadExternalState: (repo: MessageFormatRepository<UI_MESSAGE>) => {\n // Convert MessageFormatRepository to ExportedMessageRepository\n const exportedRepo = toExportedMessageRepository(\n AISDKMessageConverter.toThreadMessages,\n repo,\n );\n\n // Import into the thread's MessageRepository\n runtimeRef.current.thread.import(exportedRepo);\n },\n onCancel: async () => {\n chatHelpers.stop();\n },\n onNew: async (message) => {\n const createMessage = (\n customToCreateMessage ?? toCreateMessage\n )<UI_MESSAGE>(message);\n\n if (!(message.startRun ?? message.role === \"user\")) {\n chatHelpers.setMessages((current) => [\n ...current,\n toUIMessage<UI_MESSAGE>(createMessage, message.role),\n ]);\n return;\n }\n\n lastRunConfigRef.current = message.runConfig;\n await completePendingToolCalls();\n await chatHelpers.sendMessage(createMessage, {\n metadata: message.runConfig,\n });\n },\n onEdit: async (message) => {\n const createMessage = (\n customToCreateMessage ?? toCreateMessage\n )<UI_MESSAGE>(message);\n\n if (!(message.startRun ?? message.role === \"user\")) {\n chatHelpers.setMessages((current) => [\n ...sliceMessagesUntil(current, message.parentId),\n toUIMessage<UI_MESSAGE>(createMessage, message.role),\n ]);\n return;\n }\n\n lastRunConfigRef.current = message.runConfig;\n chatHelpers.setMessages((current) =>\n sliceMessagesUntil(current, message.parentId),\n );\n await chatHelpers.sendMessage(createMessage, {\n metadata: message.runConfig,\n });\n },\n onDelete: async (messageId) => {\n const threadMessages = runtimeRef.current.thread.getState().messages;\n const messageIndex = threadMessages.findIndex(\n (message) => message.id === messageId,\n );\n if (messageIndex === -1) return;\n\n await deleteHistoryMessage(messageId);\n\n const deleteIds = new Set(\n getExternalStoreMessages<UI_MESSAGE>(threadMessages[messageIndex]!).map(\n (message) => message.id,\n ),\n );\n chatHelpers.setMessages((current) =>\n current.filter((message) => !deleteIds.has(message.id)),\n );\n },\n onReload: async (parentId: string | null, config) => {\n lastRunConfigRef.current = config.runConfig;\n const newMessages = sliceMessagesUntil(chatHelpers.messages, parentId);\n chatHelpers.setMessages(newMessages);\n\n await chatHelpers.regenerate({ metadata: config.runConfig });\n },\n onAddToolResult: ({\n toolCallId,\n toolName,\n result,\n isError,\n modelContent,\n }) => {\n const options = { metadata: lastRunConfigRef.current };\n if (isError) {\n chatHelpers.addToolOutput({\n state: \"output-error\",\n tool: toolName ?? toolCallId,\n toolCallId,\n errorText:\n typeof result === \"string\" ? result : JSON.stringify(result),\n options,\n });\n } else {\n const output =\n modelContent !== undefined\n ? wrapModelContentEnvelope(result, modelContent)\n : result;\n chatHelpers.addToolResult({\n tool: toolName,\n toolCallId,\n output,\n options,\n });\n }\n },\n onRespondToToolApproval: ({ approvalId, approved, reason }) => {\n void chatHelpers.addToolApprovalResponse({\n id: approvalId,\n approved,\n ...(reason != null && { reason }),\n options: { metadata: lastRunConfigRef.current },\n });\n },\n ...pickExternalStoreSharedOptions(adapter),\n ...(onResume && { onResume }),\n adapters: {\n attachments: vercelAttachmentAdapter,\n ...contextAdapters,\n ...adapters,\n },\n isLoading,\n });\n\n return runtime;\n};\n"],"mappings":";;;;;;;;;;;;;;;AAmDA,MAAM,eACJ,eACA,kBAEC;CACC,GAAG;CACH,IAAI,cAAc,MAAM,WAAW;CACnC,MAAM,cAAc,QAAQ;AAC9B;AAqCF,MAAa,mBACX,aACA,UAA+B,CAAC,MAC7B;CACH,MAAM,EACJ,UACA,iBAAiB,uBACjB,+BAA+B,MAC/B,UACA,iBACE;CACJ,MAAM,kBAAkB,mBAAmB;CAC3C,MAAM,CAAC,cAAc,mBAAmB,SAEtC,CAAC,CAAC;CACJ,MAAM,2BAA2B,uBAC/B,IAAI,IAAI,CACV;CACA,MAAM,wBAAwB,uBAC5B,IAAI,IAAI,CACV;CACA,MAAM,yBAAyB,uBAAoC,IAAI,IAAI,CAAC;CAC5E,MAAM,mBAAmB,OAA8B,KAAA,CAAS;CAEhE,MAAM,oBAAoB,OAAO,OAAO,YAAY,CAAC,CAAC,MACnD,MAAM,GAAG,SAAS,WACrB;CACA,MAAM,YACJ,YAAY,WAAW,eACvB,YAAY,WAAW,eACvB;CAEF,MAAM,gBAAgB,mBAAmB,YAAY,UAAU,SAAS;CAIxE,MAAM,cAAc,YAAY,SAAS,GAAG,EAAE;CAC9C,MAAM,sBACJ,aAAa,aAAa,SAAS,cAAc,YAAY,KAAK,KAAA;CAEpE,MAAM,WAAW,sBAAsB,kBAAkB;EACvD;EACA,UAAU,YAAY;EACtB;EACA,UAAU,eACD;GACL;GACA;GACA,uBAAuB,yBAAyB;GAChD,oBAAoB,sBAAsB;GAC1C,qBAAqB,uBAAuB;GAC5C,GAAI,uBAAuB,EAAE,oBAAoB;GACjD,GAAI,YAAY,SAAS,EAAE,OAAO,YAAY,MAAM,QAAQ;EAC9D,IACA;GAAC;GAAc;GAAe;GAAqB,YAAY;EAAK,CACtE;CACF,CAAC;CAED,MAAM,CAAC,cAAc,gBAAgB,EACnC,IAAI,UAA4B;EAC9B,OAAO;CACT,EACF,EAAE;CAEF,MAAM,EAAE,WAAW,eAAe,yBAAyB,mBACzD,YACA,UAAU,WAAW,iBAAiB,SACtC,sBAAsB,kBAGtB,uBAIC,aAAa;EACZ,YAAY,YAAY,QAAQ;CAClC,CACF;CAEA,MAAM,2BAA2B,YAAY;EAC3C,IAAI,CAAC,8BAA8B;EAOnC,YAAY,aAAa,aAAa;GACpC,MAAM,cAAc,SAAS,GAAG,EAAE;GAClC,IAAI,aAAa,SAAS,aAAa,OAAO;GAE9C,IAAI,aAAa;GACjB,MAAM,QAAQ,YAAY,OAAO,KAAK,SAAS;IAC7C,IAAI,CAAC,aAAa,IAAI,GAAG,OAAO;IAChC,IAAI,KAAK,UAAU,sBAAsB,KAAK,UAAU,gBACtD,OAAO;IAET,aAAa;IACb,MAAM,EAAE,UAAU,WAAW,GAAG,SAAS;IACzC,OAAO;KACL,GAAG;KACH,OAAO;KACP,WAAW;IACb;GACF,CAAC;GAED,IAAI,CAAC,YAAY,OAAO;GACxB,OAAO,CAAC,GAAG,SAAS,MAAM,GAAG,EAAE,GAAG;IAAE,GAAG;IAAa;GAAM,CAAC;EAC7D,CAAC;CACH;CAEA,MAAM,UAAU,wBAAwB;EACtC;EACA;EACA,gCAAgC;EAChC;EACA,cAAc,aACZ,YAAY,YACV,SACG,IAAI,mBAA+B,CAAC,CACpC,OAAO,OAAO,CAAC,CACf,KAAK,CACV;EACF,WAAW,aACT,YAAY,YACV,SACG,IAAI,mBAA+B,CAAC,CACpC,OAAO,OAAO,CAAC,CACf,KAAK,CACV;EACF,6BAAkE;GAChE,MAAM,WAAW,WAAW,QAAQ,OAAO,OAAO;GAElD,MAAM,mBAAoD,CAAC;GAC3D,MAAM,iCAAiB,IAAI,IAAoB;GAE/C,KAAK,MAAM,QAAQ,SAAS,UAAU;IACpC,MAAM,gBAAgB,yBACpB,KAAK,OACP;IACA,IAAI,WACF,KAAK,YAAY,OACZ,eAAe,IAAI,KAAK,QAAQ,KAAK,KAAK,WAC3C;IACN,KAAK,MAAM,gBAAgB,eAAe;KACxC,iBAAiB,KAAK;MAAE;MAAU,SAAS;KAAa,CAAC;KACzD,WAAW,qBAAqB,MAAM,YAAyB;IACjE;IACA,IAAI,cAAc,SAAS,GACzB,eAAe,IACb,KAAK,QAAQ,IACb,qBAAqB,MACnB,cAAc,cAAc,SAAS,EACvC,CACF;GAEJ;GAEA,MAAM,SAA8C,EAClD,UAAU,iBACZ;GAEA,IAAI,SAAS,UAAU,MACrB,OAAO,SAAS,eAAe,IAAI,SAAS,MAAM,KAAK,SAAS;GAGlE,OAAO;EACT;EACA,sBAAsB,SAA8C;GAElE,MAAM,eAAe,4BACnB,sBAAsB,kBACtB,IACF;GAGA,WAAW,QAAQ,OAAO,OAAO,YAAY;EAC/C;EACA,UAAU,YAAY;GACpB,YAAY,KAAK;EACnB;EACA,OAAO,OAAO,YAAY;GACxB,MAAM,iBACJ,yBAAyB,gBAAA,CACb,OAAO;GAErB,IAAI,EAAE,QAAQ,YAAY,QAAQ,SAAS,SAAS;IAClD,YAAY,aAAa,YAAY,CACnC,GAAG,SACH,YAAwB,eAAe,QAAQ,IAAI,CACrD,CAAC;IACD;GACF;GAEA,iBAAiB,UAAU,QAAQ;GACnC,MAAM,yBAAyB;GAC/B,MAAM,YAAY,YAAY,eAAe,EAC3C,UAAU,QAAQ,UACpB,CAAC;EACH;EACA,QAAQ,OAAO,YAAY;GACzB,MAAM,iBACJ,yBAAyB,gBAAA,CACb,OAAO;GAErB,IAAI,EAAE,QAAQ,YAAY,QAAQ,SAAS,SAAS;IAClD,YAAY,aAAa,YAAY,CACnC,GAAG,mBAAmB,SAAS,QAAQ,QAAQ,GAC/C,YAAwB,eAAe,QAAQ,IAAI,CACrD,CAAC;IACD;GACF;GAEA,iBAAiB,UAAU,QAAQ;GACnC,YAAY,aAAa,YACvB,mBAAmB,SAAS,QAAQ,QAAQ,CAC9C;GACA,MAAM,YAAY,YAAY,eAAe,EAC3C,UAAU,QAAQ,UACpB,CAAC;EACH;EACA,UAAU,OAAO,cAAc;GAC7B,MAAM,iBAAiB,WAAW,QAAQ,OAAO,SAAS,CAAC,CAAC;GAC5D,MAAM,eAAe,eAAe,WACjC,YAAY,QAAQ,OAAO,SAC9B;GACA,IAAI,iBAAiB,IAAI;GAEzB,MAAM,qBAAqB,SAAS;GAEpC,MAAM,YAAY,IAAI,IACpB,yBAAqC,eAAe,aAAc,CAAC,CAAC,KACjE,YAAY,QAAQ,EACvB,CACF;GACA,YAAY,aAAa,YACvB,QAAQ,QAAQ,YAAY,CAAC,UAAU,IAAI,QAAQ,EAAE,CAAC,CACxD;EACF;EACA,UAAU,OAAO,UAAyB,WAAW;GACnD,iBAAiB,UAAU,OAAO;GAClC,MAAM,cAAc,mBAAmB,YAAY,UAAU,QAAQ;GACrE,YAAY,YAAY,WAAW;GAEnC,MAAM,YAAY,WAAW,EAAE,UAAU,OAAO,UAAU,CAAC;EAC7D;EACA,kBAAkB,EAChB,YACA,UACA,QACA,SACA,mBACI;GACJ,MAAM,UAAU,EAAE,UAAU,iBAAiB,QAAQ;GACrD,IAAI,SACF,YAAY,cAAc;IACxB,OAAO;IACP,MAAM,YAAY;IAClB;IACA,WACE,OAAO,WAAW,WAAW,SAAS,KAAK,UAAU,MAAM;IAC7D;GACF,CAAC;QACI;IACL,MAAM,SACJ,iBAAiB,KAAA,IACb,yBAAyB,QAAQ,YAAY,IAC7C;IACN,YAAY,cAAc;KACxB,MAAM;KACN;KACA;KACA;IACF,CAAC;GACH;EACF;EACA,0BAA0B,EAAE,YAAY,UAAU,aAAa;GAC7D,YAAiB,wBAAwB;IACvC,IAAI;IACJ;IACA,GAAI,UAAU,QAAQ,EAAE,OAAO;IAC/B,SAAS,EAAE,UAAU,iBAAiB,QAAQ;GAChD,CAAC;EACH;EACA,GAAG,+BAA+B,OAAO;EACzC,GAAI,YAAY,EAAE,SAAS;EAC3B,UAAU;GACR,aAAa;GACb,GAAG;GACH,GAAG;EACL;EACA;CACF,CAAC;CAED,OAAO;AACT"}
|
|
@@ -10,6 +10,7 @@ type UseChatRuntimeOptions<UI_MESSAGE extends UIMessage$1 = UIMessage$1> = ChatI
|
|
|
10
10
|
adapters?: AISDKRuntimeAdapter["adapters"] | undefined;
|
|
11
11
|
toCreateMessage?: CustomToCreateMessageFunction;
|
|
12
12
|
onResume?: AISDKRuntimeAdapter["onResume"];
|
|
13
|
+
joinStrategy?: AISDKRuntimeAdapter["joinStrategy"];
|
|
13
14
|
};
|
|
14
15
|
declare const useChatRuntime: <UI_MESSAGE extends UIMessage$1 = UIMessage$1>({
|
|
15
16
|
cloud,
|