@assistant-ui/ai-sdk 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (167) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +32 -0
  3. package/dist/adapters/aiSDKFormatAdapter.d.ts +8 -0
  4. package/dist/adapters/aiSDKFormatAdapter.d.ts.map +1 -0
  5. package/dist/adapters/aiSDKFormatAdapter.js +26 -0
  6. package/dist/adapters/aiSDKFormatAdapter.js.map +1 -0
  7. package/dist/adapters/vercelAttachmentAdapter.d.ts +6 -0
  8. package/dist/adapters/vercelAttachmentAdapter.d.ts.map +1 -0
  9. package/dist/adapters/vercelAttachmentAdapter.js +37 -0
  10. package/dist/adapters/vercelAttachmentAdapter.js.map +1 -0
  11. package/dist/aiSDKExtras.d.ts +11 -0
  12. package/dist/aiSDKExtras.d.ts.map +1 -0
  13. package/dist/aiSDKExtras.js +7 -0
  14. package/dist/aiSDKExtras.js.map +1 -0
  15. package/dist/converters/convertMessage.d.ts +28 -0
  16. package/dist/converters/convertMessage.d.ts.map +1 -0
  17. package/dist/converters/convertMessage.js +249 -0
  18. package/dist/converters/convertMessage.js.map +1 -0
  19. package/dist/converters/modelContentEnvelope.d.ts +16 -0
  20. package/dist/converters/modelContentEnvelope.d.ts.map +1 -0
  21. package/dist/converters/modelContentEnvelope.js +22 -0
  22. package/dist/converters/modelContentEnvelope.js.map +1 -0
  23. package/dist/converters/toCreateMessage.d.ts +7 -0
  24. package/dist/converters/toCreateMessage.d.ts.map +1 -0
  25. package/dist/converters/toCreateMessage.js +58 -0
  26. package/dist/converters/toCreateMessage.js.map +1 -0
  27. package/dist/converters/toolOutputConversion.d.ts +29 -0
  28. package/dist/converters/toolOutputConversion.d.ts.map +1 -0
  29. package/dist/converters/toolOutputConversion.js +31 -0
  30. package/dist/converters/toolOutputConversion.js.map +1 -0
  31. package/dist/hooks.d.ts +19 -0
  32. package/dist/hooks.d.ts.map +1 -0
  33. package/dist/hooks.js +20 -0
  34. package/dist/hooks.js.map +1 -0
  35. package/dist/index.d.ts +14 -0
  36. package/dist/index.js +13 -0
  37. package/dist/index.native.d.ts +12 -0
  38. package/dist/index.native.js +11 -0
  39. package/dist/model-context/injectInteractableContext.d.ts +37 -0
  40. package/dist/model-context/injectInteractableContext.d.ts.map +1 -0
  41. package/dist/model-context/injectInteractableContext.js +52 -0
  42. package/dist/model-context/injectInteractableContext.js.map +1 -0
  43. package/dist/model-context/injectQuoteContext.d.ts +27 -0
  44. package/dist/model-context/injectQuoteContext.d.ts.map +1 -0
  45. package/dist/model-context/injectQuoteContext.js +51 -0
  46. package/dist/model-context/injectQuoteContext.js.map +1 -0
  47. package/dist/runtime/AISDKChat.d.ts +16 -0
  48. package/dist/runtime/AISDKChat.d.ts.map +1 -0
  49. package/dist/runtime/AISDKChat.js +69 -0
  50. package/dist/runtime/AISDKChat.js.map +1 -0
  51. package/dist/runtime/AISDKThreads.d.ts +45 -0
  52. package/dist/runtime/AISDKThreads.d.ts.map +1 -0
  53. package/dist/runtime/AISDKThreads.js +203 -0
  54. package/dist/runtime/AISDKThreads.js.map +1 -0
  55. package/dist/runtime/useAISDKRuntime.d.ts +49 -0
  56. package/dist/runtime/useAISDKRuntime.d.ts.map +1 -0
  57. package/dist/runtime/useAISDKRuntime.js +266 -0
  58. package/dist/runtime/useAISDKRuntime.js.map +1 -0
  59. package/dist/runtime/useChatRuntime.d.ts +13 -0
  60. package/dist/runtime/useChatRuntime.d.ts.map +1 -0
  61. package/dist/runtime/useChatRuntime.js +52 -0
  62. package/dist/runtime/useChatRuntime.js.map +1 -0
  63. package/dist/runtime/useChatThread.d.ts +77 -0
  64. package/dist/runtime/useChatThread.d.ts.map +1 -0
  65. package/dist/runtime/useChatThread.js +134 -0
  66. package/dist/runtime/useChatThread.js.map +1 -0
  67. package/dist/runtime/useExternalHistory.d.ts +11 -0
  68. package/dist/runtime/useExternalHistory.d.ts.map +1 -0
  69. package/dist/runtime/useExternalHistory.js +278 -0
  70. package/dist/runtime/useExternalHistory.js.map +1 -0
  71. package/dist/runtime/useResourceCleanup.d.ts +5 -0
  72. package/dist/runtime/useResourceCleanup.d.ts.map +1 -0
  73. package/dist/runtime/useResourceCleanup.js +47 -0
  74. package/dist/runtime/useResourceCleanup.js.map +1 -0
  75. package/dist/runtime/useStreamingTiming.d.ts +15 -0
  76. package/dist/runtime/useStreamingTiming.d.ts.map +1 -0
  77. package/dist/runtime/useStreamingTiming.js +38 -0
  78. package/dist/runtime/useStreamingTiming.js.map +1 -0
  79. package/dist/tools/frontendTools.d.ts +33 -0
  80. package/dist/tools/frontendTools.d.ts.map +1 -0
  81. package/dist/tools/frontendTools.js +33 -0
  82. package/dist/tools/frontendTools.js.map +1 -0
  83. package/dist/tools/generativeTools.d.ts +73 -0
  84. package/dist/tools/generativeTools.d.ts.map +1 -0
  85. package/dist/tools/generativeTools.js +245 -0
  86. package/dist/tools/generativeTools.js.map +1 -0
  87. package/dist/tools/mcp-stdio.node.d.ts +2 -0
  88. package/dist/tools/mcp-stdio.node.js +2 -0
  89. package/dist/tools/mcp-stdio.unsupported.d.ts +6 -0
  90. package/dist/tools/mcp-stdio.unsupported.d.ts.map +1 -0
  91. package/dist/tools/mcp-stdio.unsupported.js +11 -0
  92. package/dist/tools/mcp-stdio.unsupported.js.map +1 -0
  93. package/dist/transport/AssistantChatTransport.d.ts +23 -0
  94. package/dist/transport/AssistantChatTransport.d.ts.map +1 -0
  95. package/dist/transport/AssistantChatTransport.js +134 -0
  96. package/dist/transport/AssistantChatTransport.js.map +1 -0
  97. package/dist/transport/resumable.d.ts +38 -0
  98. package/dist/transport/resumable.d.ts.map +1 -0
  99. package/dist/transport/resumable.js +113 -0
  100. package/dist/transport/resumable.js.map +1 -0
  101. package/dist/usage.d.ts +19 -0
  102. package/dist/usage.d.ts.map +1 -0
  103. package/dist/usage.js +127 -0
  104. package/dist/usage.js.map +1 -0
  105. package/dist/utils/getVercelAIMessages.d.ts +7 -0
  106. package/dist/utils/getVercelAIMessages.d.ts.map +1 -0
  107. package/dist/utils/getVercelAIMessages.js +9 -0
  108. package/dist/utils/getVercelAIMessages.js.map +1 -0
  109. package/dist/utils/sliceMessagesUntil.d.ts +6 -0
  110. package/dist/utils/sliceMessagesUntil.d.ts.map +1 -0
  111. package/dist/utils/sliceMessagesUntil.js +12 -0
  112. package/dist/utils/sliceMessagesUntil.js.map +1 -0
  113. package/package.json +100 -0
  114. package/src/__tests__/standalone.e2e.ts +59 -0
  115. package/src/adapters/aiSDKFormatAdapter.ts +41 -0
  116. package/src/adapters/vercelAttachmentAdapter.test.ts +29 -0
  117. package/src/adapters/vercelAttachmentAdapter.ts +36 -0
  118. package/src/aiSDKExtras.ts +11 -0
  119. package/src/converters/convertMessage.test.ts +1130 -0
  120. package/src/converters/convertMessage.ts +457 -0
  121. package/src/converters/modelContentEnvelope.ts +41 -0
  122. package/src/converters/toCreateMessage.test.ts +596 -0
  123. package/src/converters/toCreateMessage.ts +99 -0
  124. package/src/converters/toolOutputConversion.ts +26 -0
  125. package/src/hooks.ts +23 -0
  126. package/src/index.native.ts +21 -0
  127. package/src/index.ts +29 -0
  128. package/src/model-context/injectInteractableContext.test.ts +167 -0
  129. package/src/model-context/injectInteractableContext.ts +61 -0
  130. package/src/model-context/injectQuoteContext.test.ts +33 -0
  131. package/src/model-context/injectQuoteContext.ts +62 -0
  132. package/src/runtime/AISDKChat.integration.test.tsx +47 -0
  133. package/src/runtime/AISDKChat.react-compiler.test.ts +49 -0
  134. package/src/runtime/AISDKChat.test.ts +193 -0
  135. package/src/runtime/AISDKChat.ts +47 -0
  136. package/src/runtime/AISDKThreads.cloud.test.ts +136 -0
  137. package/src/runtime/AISDKThreads.test.ts +548 -0
  138. package/src/runtime/AISDKThreads.ts +223 -0
  139. package/src/runtime/__tests__/controlled-transport.ts +43 -0
  140. package/src/runtime/useAISDKRuntime.approval.test.tsx +69 -0
  141. package/src/runtime/useAISDKRuntime.test.ts +1021 -0
  142. package/src/runtime/useAISDKRuntime.tool-output.test.tsx +113 -0
  143. package/src/runtime/useAISDKRuntime.ts +524 -0
  144. package/src/runtime/useChatOnTap.test.ts +58 -0
  145. package/src/runtime/useChatRuntime.integration.test.tsx +67 -0
  146. package/src/runtime/useChatRuntime.test.ts +522 -0
  147. package/src/runtime/useChatRuntime.ts +49 -0
  148. package/src/runtime/useChatThread.ts +286 -0
  149. package/src/runtime/useExternalHistory.test.ts +1289 -0
  150. package/src/runtime/useExternalHistory.ts +435 -0
  151. package/src/runtime/useResourceCleanup.ts +32 -0
  152. package/src/runtime/useStreamingTiming.ts +68 -0
  153. package/src/tools/frontendTools.test.ts +205 -0
  154. package/src/tools/frontendTools.ts +83 -0
  155. package/src/tools/generativeTools.test.ts +785 -0
  156. package/src/tools/generativeTools.ts +470 -0
  157. package/src/tools/mcp-stdio.node.ts +1 -0
  158. package/src/tools/mcp-stdio.unsupported.ts +12 -0
  159. package/src/transport/AssistantChatTransport.test.ts +300 -0
  160. package/src/transport/AssistantChatTransport.ts +204 -0
  161. package/src/transport/resumable.test.ts +262 -0
  162. package/src/transport/resumable.ts +161 -0
  163. package/src/usage.test.ts +186 -0
  164. package/src/usage.ts +174 -0
  165. package/src/utils/getVercelAIMessages.ts +11 -0
  166. package/src/utils/sliceMessagesUntil.test.ts +55 -0
  167. package/src/utils/sliceMessagesUntil.ts +20 -0
@@ -0,0 +1,203 @@
1
+ "use client";
2
+ import { AssistantChatTransport } from "../transport/AssistantChatTransport.js";
3
+ import { useResourceCleanup } from "./useResourceCleanup.js";
4
+ import { splitChatThreadOptions, useChatThread } from "./useChatThread.js";
5
+ import { useCloudThreadListAdapter } from "@assistant-ui/core/react";
6
+ import { useEffect, useState } from "@assistant-ui/tap/react-shim";
7
+ import { useAui } from "@assistant-ui/store";
8
+ import { c } from "@assistant-ui/tap/react-shim/compiler-runtime";
9
+ import { Chat } from "@ai-sdk/react";
10
+ import { resource, useResource, withKey } from "@assistant-ui/tap";
11
+ import { InMemoryThreadList, RemoteThreadList, inMemoryThreadListTransformScopes } from "@assistant-ui/core/store";
12
+ import { attachTransformScopes, useAssistantClientRef, useAssistantScopeEffect } from "@assistant-ui/store/client";
13
+ import { ThreadClient } from "@assistant-ui/core/store/internal";
14
+ //#region src/runtime/AISDKThreads.ts
15
+ const createChatEntry = (threadId, options) => {
16
+ const { chatInit } = splitChatThreadOptions(options);
17
+ const transport = typeof options?.transport === "function" ? options.transport() : options?.transport === void 0 ? new AssistantChatTransport() : options.transport instanceof AssistantChatTransport ? options.transport.__internal_clone() : options.transport;
18
+ return {
19
+ chat: new Chat({
20
+ ...chatInit,
21
+ id: threadId,
22
+ transport
23
+ }),
24
+ transport
25
+ };
26
+ };
27
+ const getOrCreateChatEntry = (threadId, options, chats) => {
28
+ const existing = chats.get(threadId);
29
+ if (existing) return existing;
30
+ const created = createChatEntry(threadId, options);
31
+ chats.set(threadId, created);
32
+ return created;
33
+ };
34
+ const useAISDKChatThread = (t0) => {
35
+ const $ = c(34);
36
+ const { threadId, options, chats, cloud } = t0;
37
+ let t1;
38
+ if ($[0] !== cloud || $[1] !== options || $[2] !== threadId) {
39
+ t1 = () => cloud ? createChatEntry(threadId, options) : void 0;
40
+ $[0] = cloud;
41
+ $[1] = options;
42
+ $[2] = threadId;
43
+ $[3] = t1;
44
+ } else t1 = $[3];
45
+ const [owned] = useState(t1);
46
+ let t2;
47
+ if ($[4] !== chats || $[5] !== options || $[6] !== owned || $[7] !== threadId) {
48
+ t2 = owned ?? getOrCreateChatEntry(threadId, options, chats);
49
+ $[4] = chats;
50
+ $[5] = options;
51
+ $[6] = owned;
52
+ $[7] = threadId;
53
+ $[8] = t2;
54
+ } else t2 = $[8];
55
+ const { chat, transport } = t2;
56
+ let t3;
57
+ let t4;
58
+ if ($[9] !== chat || $[10] !== cloud) {
59
+ t3 = () => {
60
+ if (!cloud) return;
61
+ return () => {
62
+ chat.stop().catch(_temp);
63
+ };
64
+ };
65
+ t4 = [chat, cloud];
66
+ $[9] = chat;
67
+ $[10] = cloud;
68
+ $[11] = t3;
69
+ $[12] = t4;
70
+ } else {
71
+ t3 = $[11];
72
+ t4 = $[12];
73
+ }
74
+ useEffect(t3, t4);
75
+ const aui = useAui();
76
+ let t5;
77
+ if ($[13] !== threadId) {
78
+ t5 = { initialize: async () => ({
79
+ remoteId: threadId,
80
+ externalId: void 0
81
+ }) };
82
+ $[13] = threadId;
83
+ $[14] = t5;
84
+ } else t5 = $[14];
85
+ const fallbackItem = t5;
86
+ let t6;
87
+ if ($[15] !== options || $[16] !== transport) {
88
+ t6 = {
89
+ ...options,
90
+ transport
91
+ };
92
+ $[15] = options;
93
+ $[16] = transport;
94
+ $[17] = t6;
95
+ } else t6 = $[17];
96
+ let t7;
97
+ if ($[18] !== aui || $[19] !== cloud || $[20] !== fallbackItem) {
98
+ t7 = () => cloud ? aui.threadListItem.source ? aui.threadListItem : void 0 : fallbackItem;
99
+ $[18] = aui;
100
+ $[19] = cloud;
101
+ $[20] = fallbackItem;
102
+ $[21] = t7;
103
+ } else t7 = $[21];
104
+ let t8;
105
+ if ($[22] !== chat || $[23] !== cloud || $[24] !== t7 || $[25] !== threadId) {
106
+ t8 = {
107
+ id: threadId,
108
+ isMainThread: true,
109
+ getThreadListItem: t7,
110
+ chat,
111
+ stopOnClientDestroy: cloud
112
+ };
113
+ $[22] = chat;
114
+ $[23] = cloud;
115
+ $[24] = t7;
116
+ $[25] = threadId;
117
+ $[26] = t8;
118
+ } else t8 = $[26];
119
+ const runtime = useChatThread(t6, t8);
120
+ const clientRef = useAssistantClientRef();
121
+ let t9;
122
+ if ($[27] !== clientRef || $[28] !== runtime) {
123
+ t9 = () => runtime.registerModelContextProvider(clientRef.current.modelContext());
124
+ $[27] = clientRef;
125
+ $[28] = runtime;
126
+ $[29] = t9;
127
+ } else t9 = $[29];
128
+ let t10;
129
+ if ($[30] !== runtime) {
130
+ t10 = [runtime];
131
+ $[30] = runtime;
132
+ $[31] = t10;
133
+ } else t10 = $[31];
134
+ useAssistantScopeEffect("modelContext", t9, t10);
135
+ let t11;
136
+ if ($[32] !== runtime.thread) {
137
+ t11 = ThreadClient({ runtime: runtime.thread });
138
+ $[32] = runtime.thread;
139
+ $[33] = t11;
140
+ } else t11 = $[33];
141
+ return useResource(t11);
142
+ };
143
+ const AISDKChatThread = resource(useAISDKChatThread);
144
+ const useAISDKThreads = (options) => {
145
+ const $ = c(2);
146
+ const { cloud, threadId, onThreadIdChange, ...threadOptions } = options ?? {};
147
+ const [chats] = useState(_temp2);
148
+ const bindCloud = cloud !== void 0;
149
+ let t0;
150
+ if ($[0] !== chats) {
151
+ t0 = () => {
152
+ for (const { chat } of chats.values()) chat.stop().catch(_temp3);
153
+ };
154
+ $[0] = chats;
155
+ $[1] = t0;
156
+ } else t0 = $[1];
157
+ useResourceCleanup(true, t0);
158
+ const cloudAdapter = useCloudThreadListAdapter({ cloud });
159
+ const thread = (id) => {
160
+ const element = AISDKChatThread({
161
+ threadId: id,
162
+ options: threadOptions,
163
+ chats,
164
+ cloud: bindCloud
165
+ });
166
+ return bindCloud ? withKey(id, element) : element;
167
+ };
168
+ return useResource(bindCloud ? RemoteThreadList({
169
+ adapter: cloudAdapter,
170
+ thread,
171
+ threadId,
172
+ onThreadIdChange
173
+ }) : InMemoryThreadList({
174
+ thread,
175
+ onDelete: (id_0) => {
176
+ chats.get(id_0)?.chat.stop().catch(_temp4);
177
+ chats.delete(id_0);
178
+ }
179
+ }));
180
+ };
181
+ /**
182
+ * `AuiConfig` entry that runs one AI SDK chat per thread. Hosts the same
183
+ * per-thread orchestration as {@link AISDKChat} inside the client's own
184
+ * resource tree, so it works with any `AssistantClient` host, React or not.
185
+ * Without `cloud`, threads live in memory for the client's lifetime and keep
186
+ * their history across switches; each thread's chat id is its thread id.
187
+ * With `cloud`, the list is a `RemoteThreadList` and the factory is keyed so
188
+ * cloud history reloads on a switch. The store entry mounts only the visible
189
+ * thread, so a switch cancels an in-flight run. Model context is
190
+ * registered on the visible thread only.
191
+ */
192
+ const AISDKThreads = resource(useAISDKThreads);
193
+ attachTransformScopes(useAISDKThreads, inMemoryThreadListTransformScopes);
194
+ function _temp() {}
195
+ function _temp2() {
196
+ return /* @__PURE__ */ new Map();
197
+ }
198
+ function _temp3() {}
199
+ function _temp4() {}
200
+ //#endregion
201
+ export { AISDKThreads };
202
+
203
+ //# sourceMappingURL=AISDKThreads.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AISDKThreads.js","names":["c","_c","resource","useResource","withKey","useEffect","useMemo","useState","Chat","UIMessage","ChatTransport","AssistantCloud","InMemoryThreadList","RemoteThreadList","inMemoryThreadListTransformScopes","ThreadClient","useCloudThreadListAdapter","attachTransformScopes","useAssistantClientRef","useAssistantScopeEffect","useAui","AssistantChatTransport","splitChatThreadOptions","useChatThread","ChatThreadOptions","useResourceCleanup","AISDKThreadsOptions","Omit","UI_MESSAGE","transport","cloud","threadId","onThreadIdChange","AISDKThreadChatOptions","ChatEntry","chat","createChatEntry","options","chatInit","undefined","__internal_clone","id","getOrCreateChatEntry","chats","Map","existing","get","created","set","useAISDKChatThread","t0","$","t1","owned","t2","t3","t4","stop","catch","_temp","aui","t5","initialize","remoteId","externalId","fallbackItem","t6","t7","threadListItem","source","t8","isMainThread","getThreadListItem","stopOnClientDestroy","runtime","clientRef","t9","registerModelContextProvider","current","modelContext","t10","t11","thread","AISDKChatThread","useAISDKThreads","threadOptions","_temp2","bindCloud","values","_temp3","cloudAdapter","element","adapter","onDelete","id_0","_temp4","delete","AISDKThreads"],"sources":["../../src/runtime/AISDKThreads.ts"],"sourcesContent":["\"use client\";\n\nimport { resource, useResource, withKey } from \"@assistant-ui/tap\";\nimport { useEffect, useMemo, useState } from \"react\";\nimport { Chat, type UIMessage } from \"@ai-sdk/react\";\nimport type { ChatTransport } from \"ai\";\nimport type { AssistantCloud } from \"assistant-cloud\";\nimport {\n InMemoryThreadList,\n RemoteThreadList,\n inMemoryThreadListTransformScopes,\n} from \"@assistant-ui/core/store\";\nimport { ThreadClient } from \"@assistant-ui/core/store/internal\";\nimport { useCloudThreadListAdapter } from \"@assistant-ui/core/react\";\nimport {\n attachTransformScopes,\n useAssistantClientRef,\n useAssistantScopeEffect,\n} from \"@assistant-ui/store/client\";\nimport { useAui } from \"@assistant-ui/store\";\nimport { AssistantChatTransport } from \"../transport/AssistantChatTransport\";\nimport {\n splitChatThreadOptions,\n useChatThread,\n type ChatThreadOptions,\n} from \"./useChatThread\";\nimport { useResourceCleanup } from \"./useResourceCleanup\";\n\nexport type AISDKThreadsOptions<UI_MESSAGE extends UIMessage = UIMessage> =\n Omit<ChatThreadOptions<UI_MESSAGE>, \"id\" | \"transport\" | \"messages\"> & {\n /**\n * The transport threads send through. A factory is invoked once per\n * thread so each thread owns its instance. A plain\n * `AssistantChatTransport` instance is cloned per thread (its\n * assistant-ui wiring is per thread); any other transport instance is\n * shared as-is. Defaults to one `AssistantChatTransport` per thread.\n */\n transport?:\n | ChatTransport<UI_MESSAGE>\n | (() => ChatTransport<UI_MESSAGE>)\n | undefined;\n /**\n * When set, the thread list is a `RemoteThreadList` backed by this\n * assistant-cloud. Omit it to keep the in-memory list. The thread\n * factory is keyed so cloud history reloads on a switch, and an\n * in-flight run does not continue in the background.\n */\n cloud?: AssistantCloud | undefined;\n /**\n * Controlled thread id for the cloud list. Ignored without `cloud`.\n */\n threadId?: string | undefined;\n /**\n * Called with the settled remote id when the cloud list changes thread.\n */\n onThreadIdChange?: ((threadId: string | undefined) => void) | undefined;\n };\n\ntype AISDKThreadChatOptions<UI_MESSAGE extends UIMessage = UIMessage> = Omit<\n AISDKThreadsOptions<UI_MESSAGE>,\n \"cloud\" | \"threadId\" | \"onThreadIdChange\"\n>;\n\ntype ChatEntry<UI_MESSAGE extends UIMessage> = {\n chat: Chat<UI_MESSAGE>;\n transport: ChatTransport<UI_MESSAGE>;\n};\n\nconst createChatEntry = <UI_MESSAGE extends UIMessage>(\n threadId: string,\n options: AISDKThreadChatOptions<UI_MESSAGE> | undefined,\n): ChatEntry<UI_MESSAGE> => {\n const { chatInit } = splitChatThreadOptions(\n options as ChatThreadOptions<UI_MESSAGE> | undefined,\n );\n const transport =\n typeof options?.transport === \"function\"\n ? options.transport()\n : options?.transport === undefined\n ? new AssistantChatTransport()\n : options.transport instanceof AssistantChatTransport\n ? options.transport.__internal_clone()\n : options.transport;\n return {\n chat: new Chat<UI_MESSAGE>({ ...chatInit, id: threadId, transport }),\n transport,\n };\n};\n\nconst getOrCreateChatEntry = <UI_MESSAGE extends UIMessage>(\n threadId: string,\n options: AISDKThreadChatOptions<UI_MESSAGE> | undefined,\n chats: Map<string, ChatEntry<UI_MESSAGE>>,\n): ChatEntry<UI_MESSAGE> => {\n const existing = chats.get(threadId);\n if (existing) return existing;\n const created = createChatEntry(threadId, options);\n chats.set(threadId, created);\n return created;\n};\n\nconst useAISDKChatThread = <UI_MESSAGE extends UIMessage = UIMessage>({\n threadId,\n options,\n chats,\n cloud,\n}: {\n threadId: string;\n options: AISDKThreadChatOptions<UI_MESSAGE> | undefined;\n chats: Map<string, ChatEntry<UI_MESSAGE>>;\n cloud: boolean;\n}) => {\n const [owned] = useState(() =>\n cloud ? createChatEntry(threadId, options) : undefined,\n );\n const { chat, transport } =\n owned ?? getOrCreateChatEntry(threadId, options, chats);\n\n useEffect(() => {\n if (!cloud) return undefined;\n return () => {\n void chat.stop().catch(() => {});\n };\n }, [chat, cloud]);\n\n const aui = useAui();\n const fallbackItem = useMemo(\n () => ({\n initialize: async () => ({\n remoteId: threadId,\n externalId: undefined,\n }),\n }),\n [threadId],\n );\n const runtime = useChatThread(\n { ...options, transport } as ChatThreadOptions<UI_MESSAGE>,\n {\n id: threadId,\n isMainThread: true,\n getThreadListItem: () =>\n cloud\n ? aui.threadListItem.source\n ? aui.threadListItem\n : undefined\n : fallbackItem,\n chat,\n stopOnClientDestroy: cloud,\n },\n );\n\n const clientRef = useAssistantClientRef();\n useAssistantScopeEffect(\n \"modelContext\",\n () =>\n runtime.registerModelContextProvider(clientRef.current!.modelContext()),\n [runtime],\n );\n\n return useResource(ThreadClient({ runtime: runtime.thread }));\n};\n\nconst AISDKChatThread = resource(useAISDKChatThread);\n\nconst useAISDKThreads = <UI_MESSAGE extends UIMessage = UIMessage>(\n options?: AISDKThreadsOptions<UI_MESSAGE>,\n) => {\n const { cloud, threadId, onThreadIdChange, ...threadOptions } = options ?? {};\n const [chats] = useState(() => new Map<string, ChatEntry<UI_MESSAGE>>());\n const bindCloud = cloud !== undefined;\n\n useResourceCleanup(true, () => {\n for (const { chat } of chats.values()) {\n void chat.stop().catch(() => {});\n }\n });\n\n const cloudAdapter = useCloudThreadListAdapter({ cloud });\n const thread = (id: string) => {\n const element = AISDKChatThread({\n threadId: id,\n options: threadOptions,\n chats,\n cloud: bindCloud,\n });\n return bindCloud ? withKey(id, element) : element;\n };\n\n return useResource(\n bindCloud\n ? RemoteThreadList({\n adapter: cloudAdapter,\n thread,\n threadId,\n onThreadIdChange,\n })\n : InMemoryThreadList({\n thread,\n onDelete: (id) => {\n void chats\n .get(id)\n ?.chat.stop()\n .catch(() => {});\n chats.delete(id);\n },\n }),\n );\n};\n\n/**\n * `AuiConfig` entry that runs one AI SDK chat per thread. Hosts the same\n * per-thread orchestration as {@link AISDKChat} inside the client's own\n * resource tree, so it works with any `AssistantClient` host, React or not.\n * Without `cloud`, threads live in memory for the client's lifetime and keep\n * their history across switches; each thread's chat id is its thread id.\n * With `cloud`, the list is a `RemoteThreadList` and the factory is keyed so\n * cloud history reloads on a switch. The store entry mounts only the visible\n * thread, so a switch cancels an in-flight run. Model context is\n * registered on the visible thread only.\n */\nexport const AISDKThreads = resource(useAISDKThreads);\n\nattachTransformScopes(useAISDKThreads, inMemoryThreadListTransformScopes);\n"],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ import { JoinStrategy } from "@assistant-ui/core/react";
2
+ import { AppendMessage, AssistantRuntime, ExternalStoreAdapter, ExternalStoreSharedOptions, SuggestionAdapter, ThreadHistoryAdapter } from "@assistant-ui/core";
3
+ import { CreateUIMessage, UIMessage, useChat } from "@ai-sdk/react";
4
+ //#region src/runtime/useAISDKRuntime.d.ts
5
+ type CustomToCreateMessageFunction = <UI_MESSAGE extends UIMessage = UIMessage>(message: AppendMessage) => CreateUIMessage<UI_MESSAGE>;
6
+ type AISDKRuntimeAdapter = ExternalStoreSharedOptions & {
7
+ adapters?: (NonNullable<ExternalStoreAdapter["adapters"]> & {
8
+ history?: ThreadHistoryAdapter | undefined;
9
+ suggestion?: SuggestionAdapter | undefined;
10
+ }) | undefined;
11
+ toCreateMessage?: CustomToCreateMessageFunction;
12
+ /**
13
+ * Whether to automatically cancel pending interactive tool calls when the user sends a new message.
14
+ *
15
+ * When enabled (default), the pending tool calls will be marked as failed with an error message
16
+ * indicating the user cancelled the tool call by sending a new message.
17
+ *
18
+ * @default true
19
+ */
20
+ cancelPendingToolCallsOnSend?: boolean | undefined;
21
+ /**
22
+ * Called when `runtime.thread.resumeRun(config)` is invoked.
23
+ *
24
+ * When omitted, `resumeRun` throws `"Runtime does not support resuming runs."`.
25
+ * Provide this to bridge resume invocations into a custom replay channel
26
+ * (for example, an SSE reconnect endpoint keyed by turn id).
27
+ */
28
+ onResume?: ExternalStoreAdapter["onResume"];
29
+ /**
30
+ * Called when `runtime.thread.resumeToolCall(options)` is invoked for a tool call the in-process tracker does not own.
31
+ *
32
+ * When omitted, `resumeToolCall` throws `"Tool call ${toolCallId} is not waiting for resume."`.
33
+ * Provide this to bridge resume-tool-call invocations into a custom handler.
34
+ */
35
+ onResumeToolCall?: ExternalStoreAdapter["onResumeToolCall"];
36
+ /**
37
+ * How consecutive assistant messages are rendered.
38
+ *
39
+ * `"concat-content"` (the default) merges them into a single thread message.
40
+ * `"none"` keeps each assistant message as its own thread message, which is
41
+ * useful when a backend persists proactive or consecutive assistant messages
42
+ * as separate entries.
43
+ */
44
+ joinStrategy?: JoinStrategy | undefined;
45
+ };
46
+ declare const useAISDKRuntime: <UI_MESSAGE extends UIMessage = UIMessage>(chatHelpers: ReturnType<typeof useChat<UI_MESSAGE>>, adapter?: AISDKRuntimeAdapter) => AssistantRuntime;
47
+ //#endregion
48
+ export { AISDKRuntimeAdapter, CustomToCreateMessageFunction, useAISDKRuntime };
49
+ //# sourceMappingURL=useAISDKRuntime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAISDKRuntime.d.ts","names":[],"sources":["../../src/runtime/useAISDKRuntime.ts"],"mappings":";;;;KAwDY,iCACV,mBAAmB,YAAY,WAE/B,SAAS,kBACN,gBAAgB;KAYT,sBAAsB;EAChC,YACK,YAAY;IACX,UAAU;IACV,aAAa;;EAGnB,kBAAkB;;;;;;;;;EASlB;;;;;;;;EAQA,WAAW;;;;;;;EAOX,mBAAmB;;;;;;;;;EASnB,eAAe;;cA8EJ,kBAAmB,mBAAmB,YAAY,WAC7D,aAAa,kBAAkB,QAAQ,cACvC,UAAS,wBAAwB"}
@@ -0,0 +1,266 @@
1
+ "use client";
2
+ import { aiSDKExtras } from "../aiSDKExtras.js";
3
+ import { sliceMessagesUntil } from "../utils/sliceMessagesUntil.js";
4
+ import { toCreateMessage } from "../converters/toCreateMessage.js";
5
+ import { vercelAttachmentAdapter } from "../adapters/vercelAttachmentAdapter.js";
6
+ import { getVercelAIMessages } from "../utils/getVercelAIMessages.js";
7
+ import { wrapModelContentEnvelope } from "../converters/modelContentEnvelope.js";
8
+ import { AISDKMessageConverter } from "../converters/convertMessage.js";
9
+ import { aiSDKV6FormatAdapter } from "../adapters/aiSDKFormatAdapter.js";
10
+ import { toExportedMessageRepository, useExternalHistory } from "./useExternalHistory.js";
11
+ import { useStreamingTiming as useStreamingTiming$1 } from "./useStreamingTiming.js";
12
+ import { useExternalStoreRuntime, useRuntimeAdapters } from "@assistant-ui/core/react";
13
+ import { useEffect, useMemo, useRef, useState } from "@assistant-ui/tap/react-shim";
14
+ import { generateId, isToolUIPart } from "ai";
15
+ import { getExternalStoreMessages, pickExternalStoreSharedOptions } from "@assistant-ui/core";
16
+ import { consumeSuggestionResult } from "@assistant-ui/core/internal";
17
+ //#region src/runtime/useAISDKRuntime.ts
18
+ const toUIMessage = (createMessage, fallbackRole) => ({
19
+ ...createMessage,
20
+ id: createMessage.id ?? generateId(),
21
+ role: createMessage.role ?? fallbackRole
22
+ });
23
+ const EMPTY_SUGGESTIONS = [];
24
+ const useGeneratedSuggestions = (suggestionAdapter, messages, isRunning) => {
25
+ const [suggestions, setSuggestions] = useState(EMPTY_SUGGESTIONS);
26
+ const controllerRef = useRef(null);
27
+ const wasRunningRef = useRef(false);
28
+ const messagesRef = useRef(messages);
29
+ messagesRef.current = messages;
30
+ const adapterRef = useRef(suggestionAdapter);
31
+ adapterRef.current = suggestionAdapter;
32
+ useEffect(() => {
33
+ const clearSuggestions = () => {
34
+ controllerRef.current?.abort();
35
+ controllerRef.current = null;
36
+ setSuggestions((prev) => prev.length === 0 ? prev : EMPTY_SUGGESTIONS);
37
+ };
38
+ const adapter = adapterRef.current;
39
+ if (!adapter) {
40
+ clearSuggestions();
41
+ wasRunningRef.current = isRunning;
42
+ return;
43
+ }
44
+ if (isRunning) {
45
+ if (!wasRunningRef.current) clearSuggestions();
46
+ wasRunningRef.current = true;
47
+ return;
48
+ }
49
+ if (!wasRunningRef.current) return;
50
+ wasRunningRef.current = false;
51
+ const currentMessages = messagesRef.current;
52
+ const last = currentMessages.at(-1);
53
+ if (last?.role !== "assistant") return;
54
+ if (last.status?.type === "requires-action") return;
55
+ const controller = new AbortController();
56
+ controllerRef.current = controller;
57
+ const { signal } = controller;
58
+ (async () => {
59
+ try {
60
+ const promiseOrGenerator = adapter.generate({
61
+ messages: currentMessages,
62
+ signal
63
+ });
64
+ await consumeSuggestionResult(promiseOrGenerator, {
65
+ signal,
66
+ onUpdate: setSuggestions
67
+ });
68
+ } catch {}
69
+ })();
70
+ }, [suggestionAdapter != null, isRunning]);
71
+ useEffect(() => {
72
+ return () => {
73
+ controllerRef.current?.abort();
74
+ };
75
+ }, []);
76
+ return suggestions;
77
+ };
78
+ const useAISDKRuntime = (chatHelpers, adapter = {}) => {
79
+ const { adapters, toCreateMessage: customToCreateMessage, cancelPendingToolCallsOnSend = true, onResume, onResumeToolCall, joinStrategy } = adapter;
80
+ const suggestionAdapter = adapters?.suggestion;
81
+ const contextAdapters = useRuntimeAdapters();
82
+ const [toolStatuses, setToolStatuses] = useState({});
83
+ const toolArgsKeyOrderCacheRef = useRef(/* @__PURE__ */ new Map());
84
+ const toolLastInputCacheRef = useRef(/* @__PURE__ */ new Map());
85
+ const mcpAppMetadataCacheRef = useRef(/* @__PURE__ */ new Map());
86
+ const lastRunConfigRef = useRef(void 0);
87
+ const hasExecutingTools = Object.values(toolStatuses).some((s) => s?.type === "executing");
88
+ const isRunning = chatHelpers.status === "submitted" || chatHelpers.status === "streaming" || hasExecutingTools;
89
+ const messageTiming = useStreamingTiming$1(chatHelpers.messages, isRunning);
90
+ const lastMessage = chatHelpers.messages.at(-1);
91
+ const optimisticMessageId = isRunning && lastMessage?.role === "assistant" ? lastMessage.id : void 0;
92
+ const messages = AISDKMessageConverter.useThreadMessages({
93
+ isRunning,
94
+ messages: chatHelpers.messages,
95
+ joinStrategy,
96
+ metadata: useMemo(() => ({
97
+ toolStatuses,
98
+ messageTiming,
99
+ toolArgsKeyOrderCache: toolArgsKeyOrderCacheRef.current,
100
+ toolLastInputCache: toolLastInputCacheRef.current,
101
+ mcpAppMetadataCache: mcpAppMetadataCacheRef.current,
102
+ ...optimisticMessageId && { optimisticMessageId },
103
+ ...chatHelpers.error && { error: chatHelpers.error.message }
104
+ }), [
105
+ toolStatuses,
106
+ messageTiming,
107
+ optimisticMessageId,
108
+ chatHelpers.error
109
+ ])
110
+ });
111
+ const generatedSuggestions = useGeneratedSuggestions(suggestionAdapter, messages, isRunning);
112
+ const [runtimeRef] = useState(() => ({ get current() {
113
+ return runtime;
114
+ } }));
115
+ const { isLoading, deleteMessage: deleteHistoryMessage } = useExternalHistory(runtimeRef, adapters?.history ?? contextAdapters?.history, AISDKMessageConverter.toThreadMessages, aiSDKV6FormatAdapter, (messages_0) => {
116
+ chatHelpers.setMessages(messages_0);
117
+ });
118
+ const { id: chatId, messages: chatMessages, status: chatStatus, error } = chatHelpers;
119
+ const extras = useMemo(() => aiSDKExtras.provide({
120
+ chat: chatHelpers,
121
+ error
122
+ }), [
123
+ chatId,
124
+ chatMessages,
125
+ chatStatus,
126
+ error
127
+ ]);
128
+ const completePendingToolCalls = async () => {
129
+ if (!cancelPendingToolCallsOnSend) return;
130
+ chatHelpers.setMessages((messages_1) => {
131
+ const lastMessage_0 = messages_1.at(-1);
132
+ if (lastMessage_0?.role !== "assistant") return messages_1;
133
+ let hasChanges = false;
134
+ const parts = lastMessage_0.parts?.map((part) => {
135
+ if (!isToolUIPart(part)) return part;
136
+ if (part.state === "output-available" || part.state === "output-error") return part;
137
+ hasChanges = true;
138
+ const { approval: _approval, ...rest } = part;
139
+ return {
140
+ ...rest,
141
+ state: "output-error",
142
+ errorText: "User cancelled tool call by sending a new message."
143
+ };
144
+ });
145
+ if (!hasChanges) return messages_1;
146
+ return [...messages_1.slice(0, -1), {
147
+ ...lastMessage_0,
148
+ parts
149
+ }];
150
+ });
151
+ };
152
+ const runtime = useExternalStoreRuntime({
153
+ isRunning,
154
+ messages,
155
+ unstable_enableToolInvocations: true,
156
+ setToolStatuses,
157
+ setMessages: (messages_2) => chatHelpers.setMessages(messages_2.map(getVercelAIMessages).filter(Boolean).flat()),
158
+ onImport: (messages_3) => chatHelpers.setMessages(messages_3.map(getVercelAIMessages).filter(Boolean).flat()),
159
+ onExportExternalState: () => {
160
+ const exported = runtimeRef.current.thread.export();
161
+ const expandedMessages = [];
162
+ const lastInnerIdMap = /* @__PURE__ */ new Map();
163
+ for (const item of exported.messages) {
164
+ const innerMessages = getExternalStoreMessages(item.message);
165
+ let parentId = item.parentId != null ? lastInnerIdMap.get(item.parentId) ?? item.parentId : null;
166
+ for (const innerMessage of innerMessages) {
167
+ expandedMessages.push({
168
+ parentId,
169
+ message: innerMessage
170
+ });
171
+ parentId = aiSDKV6FormatAdapter.getId(innerMessage);
172
+ }
173
+ if (innerMessages.length > 0) lastInnerIdMap.set(item.message.id, aiSDKV6FormatAdapter.getId(innerMessages[innerMessages.length - 1]));
174
+ }
175
+ const result = { messages: expandedMessages };
176
+ if (exported.headId != null) result.headId = lastInnerIdMap.get(exported.headId) ?? exported.headId;
177
+ return result;
178
+ },
179
+ onLoadExternalState: (repo) => {
180
+ const exportedRepo = toExportedMessageRepository(AISDKMessageConverter.toThreadMessages, repo);
181
+ runtimeRef.current.thread.import(exportedRepo);
182
+ },
183
+ onCancel: async () => {
184
+ try {
185
+ await chatHelpers.stop();
186
+ } catch (error_0) {
187
+ if (!(error_0 instanceof Error && error_0.name === "AbortError")) throw error_0;
188
+ }
189
+ },
190
+ onNew: async (message) => {
191
+ const createMessage = (customToCreateMessage ?? toCreateMessage)(message);
192
+ if (!(message.startRun ?? message.role === "user")) {
193
+ chatHelpers.setMessages((current) => [...current, toUIMessage(createMessage, message.role)]);
194
+ return;
195
+ }
196
+ lastRunConfigRef.current = message.runConfig;
197
+ await completePendingToolCalls();
198
+ await chatHelpers.sendMessage(createMessage, { metadata: message.runConfig });
199
+ },
200
+ onEdit: async (message_0) => {
201
+ const createMessage_0 = (customToCreateMessage ?? toCreateMessage)(message_0);
202
+ if (!(message_0.startRun ?? message_0.role === "user")) {
203
+ chatHelpers.setMessages((current_0) => [...sliceMessagesUntil(current_0, message_0.parentId), toUIMessage(createMessage_0, message_0.role)]);
204
+ return;
205
+ }
206
+ lastRunConfigRef.current = message_0.runConfig;
207
+ chatHelpers.setMessages((current_1) => sliceMessagesUntil(current_1, message_0.parentId));
208
+ await chatHelpers.sendMessage(createMessage_0, { metadata: message_0.runConfig });
209
+ },
210
+ onDelete: async (messageId) => {
211
+ const threadMessages = runtimeRef.current.thread.getState().messages;
212
+ const messageIndex = threadMessages.findIndex((message_1) => message_1.id === messageId);
213
+ if (messageIndex === -1) return;
214
+ await deleteHistoryMessage(messageId);
215
+ const deleteIds = new Set(getExternalStoreMessages(threadMessages[messageIndex]).map((message_2) => message_2.id));
216
+ chatHelpers.setMessages((current_2) => current_2.filter((message_3) => !deleteIds.has(message_3.id)));
217
+ },
218
+ onReload: async (parentId_0, config) => {
219
+ lastRunConfigRef.current = config.runConfig;
220
+ const newMessages = sliceMessagesUntil(chatHelpers.messages, parentId_0);
221
+ chatHelpers.setMessages(newMessages);
222
+ await chatHelpers.regenerate({ metadata: config.runConfig });
223
+ },
224
+ onAddToolResult: ({ toolCallId, toolName, result: result_0, isError, modelContent }) => {
225
+ const options = { metadata: lastRunConfigRef.current };
226
+ if (isError) return Promise.resolve(chatHelpers.addToolOutput({
227
+ state: "output-error",
228
+ tool: toolName ?? toolCallId,
229
+ toolCallId,
230
+ errorText: typeof result_0 === "string" ? result_0 : JSON.stringify(result_0),
231
+ options
232
+ }));
233
+ else {
234
+ const output = modelContent !== void 0 ? wrapModelContentEnvelope(result_0, modelContent) : result_0;
235
+ return Promise.resolve(chatHelpers.addToolOutput({
236
+ tool: toolName,
237
+ toolCallId,
238
+ output,
239
+ options
240
+ }));
241
+ }
242
+ },
243
+ onRespondToToolApproval: ({ approvalId, approved, reason }) => Promise.resolve(chatHelpers.addToolApprovalResponse({
244
+ id: approvalId,
245
+ approved,
246
+ ...reason != null && { reason },
247
+ options: { metadata: lastRunConfigRef.current }
248
+ })),
249
+ ...pickExternalStoreSharedOptions(adapter),
250
+ ...suggestionAdapter ? { suggestions: generatedSuggestions } : {},
251
+ ...onResume && { onResume },
252
+ ...onResumeToolCall && { onResumeToolCall },
253
+ adapters: {
254
+ attachments: vercelAttachmentAdapter,
255
+ ...contextAdapters,
256
+ ...adapters
257
+ },
258
+ extras,
259
+ isLoading
260
+ });
261
+ return runtime;
262
+ };
263
+ //#endregion
264
+ export { useAISDKRuntime };
265
+
266
+ //# sourceMappingURL=useAISDKRuntime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAISDKRuntime.js","names":["useEffect","useMemo","useRef","useState","UIMessage","useChat","CreateUIMessage","UseChatHelpers","isToolUIPart","generateId","useExternalStoreRuntime","useRuntimeAdapters","JoinStrategy","SuggestionAdapter","ThreadSuggestion","ToolExecutionStatus","ExternalStoreAdapter","ExternalStoreSharedOptions","ThreadHistoryAdapter","AssistantRuntime","ThreadMessage","MessageFormatAdapter","MessageFormatItem","MessageFormatRepository","AppendMessage","RunConfig","McpAppMetadata","getExternalStoreMessages","pickExternalStoreSharedOptions","consumeSuggestionResult","ReadonlyJSONObject","sliceMessagesUntil","toCreateMessage","vercelAttachmentAdapter","getVercelAIMessages","AISDKMessageConverter","wrapModelContentEnvelope","AISDKStorageFormat","aiSDKV6FormatAdapter","useExternalHistory","toExportedMessageRepository","useStreamingTiming","aiSDKExtras","CustomToCreateMessageFunction","message","UI_MESSAGE","toUIMessage","createMessage","fallbackRole","id","role","AISDKRuntimeAdapter","adapters","NonNullable","history","suggestion","cancelPendingToolCallsOnSend","onResume","onResumeToolCall","joinStrategy","EMPTY_SUGGESTIONS","useGeneratedSuggestions","suggestionAdapter","messages","isRunning","suggestions","setSuggestions","controllerRef","AbortController","wasRunningRef","messagesRef","current","adapterRef","hasAdapter","clearSuggestions","abort","prev","length","adapter","currentMessages","last","at","status","type","controller","signal","promiseOrGenerator","generate","onUpdate","useAISDKRuntime","chatHelpers","ReturnType","customToCreateMessage","contextAdapters","toolStatuses","setToolStatuses","Record","toolArgsKeyOrderCacheRef","Map","toolLastInputCacheRef","mcpAppMetadataCacheRef","lastRunConfigRef","undefined","hasExecutingTools","Object","values","some","s","messageTiming","lastMessage","optimisticMessageId","useThreadMessages","metadata","toolArgsKeyOrderCache","toolLastInputCache","mcpAppMetadataCache","error","generatedSuggestions","runtimeRef","runtime","isLoading","deleteMessage","deleteHistoryMessage","toThreadMessages","setMessages","chatId","chatMessages","chatStatus","extras","provide","chat","completePendingToolCalls","hasChanges","parts","map","part","state","approval","_approval","rest","const","errorText","slice","unstable_enableToolInvocations","filter","Boolean","flat","onImport","onExportExternalState","exported","thread","export","expandedMessages","lastInnerIdMap","item","innerMessages","parentId","get","innerMessage","push","getId","set","result","headId","onLoadExternalState","repo","exportedRepo","import","onCancel","stop","Error","name","onNew","startRun","runConfig","sendMessage","onEdit","onDelete","messageId","threadMessages","getState","messageIndex","findIndex","deleteIds","Set","has","onReload","config","newMessages","regenerate","onAddToolResult","toolCallId","toolName","isError","modelContent","options","Promise","resolve","addToolOutput","tool","JSON","stringify","output","onRespondToToolApproval","approvalId","approved","reason","addToolApprovalResponse","attachments"],"sources":["../../src/runtime/useAISDKRuntime.ts"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useMemo, useRef, useState } from \"react\";\nimport type {\n UIMessage,\n useChat,\n CreateUIMessage,\n UseChatHelpers,\n} 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 {\n SuggestionAdapter,\n ThreadSuggestion,\n ToolExecutionStatus,\n} 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 { consumeSuggestionResult } from \"@assistant-ui/core/internal\";\nimport type { ReadonlyJSONObject } from \"assistant-stream/utils\";\nimport { sliceMessagesUntil } from \"../utils/sliceMessagesUntil\";\nimport { toCreateMessage } from \"../converters/toCreateMessage\";\nimport { vercelAttachmentAdapter } from \"../adapters/vercelAttachmentAdapter\";\nimport { getVercelAIMessages } from \"../utils/getVercelAIMessages\";\nimport { AISDKMessageConverter } from \"../converters/convertMessage\";\nimport { wrapModelContentEnvelope } from \"../converters/modelContentEnvelope\";\nimport {\n type AISDKStorageFormat,\n aiSDKV6FormatAdapter,\n} from \"../adapters/aiSDKFormatAdapter\";\nimport {\n useExternalHistory,\n toExportedMessageRepository,\n} from \"./useExternalHistory\";\nimport { useStreamingTiming } from \"./useStreamingTiming\";\nimport { aiSDKExtras } from \"../aiSDKExtras\";\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 suggestion?: SuggestionAdapter | 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 * Called when `runtime.thread.resumeToolCall(options)` is invoked for a tool call the in-process tracker does not own.\n *\n * When omitted, `resumeToolCall` throws `\"Tool call ${toolCallId} is not waiting for resume.\"`.\n * Provide this to bridge resume-tool-call invocations into a custom handler.\n */\n onResumeToolCall?: ExternalStoreAdapter[\"onResumeToolCall\"];\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\nconst EMPTY_SUGGESTIONS: readonly ThreadSuggestion[] = [];\n\nconst useGeneratedSuggestions = (\n suggestionAdapter: SuggestionAdapter | undefined,\n messages: readonly ThreadMessage[],\n isRunning: boolean,\n): readonly ThreadSuggestion[] => {\n const [suggestions, setSuggestions] =\n useState<readonly ThreadSuggestion[]>(EMPTY_SUGGESTIONS);\n const controllerRef = useRef<AbortController | null>(null);\n const wasRunningRef = useRef(false);\n const messagesRef = useRef(messages);\n messagesRef.current = messages;\n const adapterRef = useRef(suggestionAdapter);\n adapterRef.current = suggestionAdapter;\n const hasAdapter = suggestionAdapter != null;\n\n useEffect(() => {\n const clearSuggestions = () => {\n controllerRef.current?.abort();\n controllerRef.current = null;\n setSuggestions((prev) => (prev.length === 0 ? prev : EMPTY_SUGGESTIONS));\n };\n\n const adapter = adapterRef.current;\n if (!adapter) {\n clearSuggestions();\n wasRunningRef.current = isRunning;\n return;\n }\n\n if (isRunning) {\n if (!wasRunningRef.current) {\n clearSuggestions();\n }\n wasRunningRef.current = true;\n return;\n }\n\n if (!wasRunningRef.current) return;\n wasRunningRef.current = false;\n\n const currentMessages = messagesRef.current;\n const last = currentMessages.at(-1);\n if (last?.role !== \"assistant\") return;\n if (last.status?.type === \"requires-action\") return;\n\n const controller = new AbortController();\n controllerRef.current = controller;\n const { signal } = controller;\n\n void (async () => {\n try {\n const promiseOrGenerator = adapter.generate({\n messages: currentMessages,\n signal,\n });\n\n await consumeSuggestionResult(promiseOrGenerator, {\n signal,\n onUpdate: setSuggestions,\n });\n } catch {}\n })();\n }, [hasAdapter, isRunning]);\n\n useEffect(() => {\n return () => {\n controllerRef.current?.abort();\n };\n }, []);\n\n return suggestions;\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 onResumeToolCall,\n joinStrategy,\n } = adapter;\n const suggestionAdapter = adapters?.suggestion;\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 generatedSuggestions = useGeneratedSuggestions(\n suggestionAdapter,\n messages,\n isRunning,\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 {\n id: chatId,\n messages: chatMessages,\n status: chatStatus,\n error,\n } = chatHelpers;\n const extras = useMemo(\n () =>\n aiSDKExtras.provide({\n chat: chatHelpers as unknown as UseChatHelpers<UIMessage>,\n error,\n }),\n // oxlint-disable-next-line react/exhaustive-deps -- keyed on the chat's identity and reactive snapshots; useChat re-mints the helpers object every render while its remaining fields are instance-bound methods, and a render-stable extras identity is what lets the external-store core dedupe adapter updates\n [chatId, chatMessages, chatStatus, error],\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 try {\n await chatHelpers.stop();\n } catch (error) {\n if (!(error instanceof Error && error.name === \"AbortError\")) {\n throw error;\n }\n }\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 return Promise.resolve(\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 );\n } else {\n const output =\n modelContent !== undefined\n ? wrapModelContentEnvelope(result, modelContent)\n : result;\n return Promise.resolve(\n chatHelpers.addToolOutput({\n tool: toolName,\n toolCallId,\n output,\n options,\n }),\n );\n }\n },\n onRespondToToolApproval: ({ approvalId, approved, reason }) =>\n Promise.resolve(\n chatHelpers.addToolApprovalResponse({\n id: approvalId,\n approved,\n ...(reason != null && { reason }),\n options: { metadata: lastRunConfigRef.current },\n }),\n ),\n ...pickExternalStoreSharedOptions(adapter),\n ...(suggestionAdapter ? { suggestions: generatedSuggestions } : {}),\n ...(onResume && { onResume }),\n ...(onResumeToolCall && { onResumeToolCall }),\n adapters: {\n attachments: vercelAttachmentAdapter,\n ...contextAdapters,\n ...adapters,\n },\n extras,\n isLoading,\n });\n\n return runtime;\n};\n"],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import { ChatThreadOptions } from "./useChatThread.js";
2
+ import { AssistantRuntime } from "@assistant-ui/core";
3
+ import { UIMessage } from "@ai-sdk/react";
4
+ import { AssistantCloud } from "assistant-cloud";
5
+ //#region src/runtime/useChatRuntime.d.ts
6
+ type UseChatRuntimeOptions<UI_MESSAGE extends UIMessage = UIMessage> = ChatThreadOptions<UI_MESSAGE> & {
7
+ cloud?: AssistantCloud | undefined;
8
+ onThreadIdChange?: ((threadId: string | undefined) => void) | undefined;
9
+ };
10
+ declare const useChatRuntime: <UI_MESSAGE extends UIMessage = UIMessage>({ cloud, onThreadIdChange, ...options }?: UseChatRuntimeOptions<UI_MESSAGE>) => AssistantRuntime;
11
+ //#endregion
12
+ export { UseChatRuntimeOptions, useChatRuntime };
13
+ //# sourceMappingURL=useChatRuntime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useChatRuntime.d.ts","names":[],"sources":["../../src/runtime/useChatRuntime.ts"],"mappings":";;;;;KAYY,sBAAsB,mBAAmB,YAAY,aAC/D,kBAAkB;EAChB,QAAQ;EACR,qBAAqB;;cAmBZ,iBAAkB,mBAAmB,YAAY,aAAW,OAAA,qBAAA,YAItE,sBAAsB,gBAAmB"}