@assistant-ui/ai-sdk 0.0.6 → 0.0.7

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 (79) hide show
  1. package/dist/adapters/vercelAttachmentAdapter.d.ts +1 -2
  2. package/dist/adapters/vercelAttachmentAdapter.d.ts.map +1 -1
  3. package/dist/aiSDKExtras.d.ts +2 -3
  4. package/dist/aiSDKExtras.d.ts.map +1 -1
  5. package/dist/converters/convertMessage.d.ts +5 -4
  6. package/dist/converters/convertMessage.d.ts.map +1 -1
  7. package/dist/converters/convertMessage.js +39 -3
  8. package/dist/converters/convertMessage.js.map +1 -1
  9. package/dist/converters/modelContentEnvelope.d.ts +4 -5
  10. package/dist/converters/modelContentEnvelope.d.ts.map +1 -1
  11. package/dist/converters/toCreateMessage.d.ts +1 -2
  12. package/dist/converters/toCreateMessage.d.ts.map +1 -1
  13. package/dist/converters/toolOutputConversion.d.ts +2 -3
  14. package/dist/converters/toolOutputConversion.d.ts.map +1 -1
  15. package/dist/hooks.d.ts +2 -3
  16. package/dist/hooks.d.ts.map +1 -1
  17. package/dist/model-context/injectInteractableContext.d.ts +1 -2
  18. package/dist/model-context/injectInteractableContext.d.ts.map +1 -1
  19. package/dist/model-context/injectQuoteContext.d.ts +1 -2
  20. package/dist/model-context/injectQuoteContext.d.ts.map +1 -1
  21. package/dist/runtime/AISDKChat.d.ts +2 -3
  22. package/dist/runtime/AISDKChat.d.ts.map +1 -1
  23. package/dist/runtime/AISDKThreads.d.ts +2 -3
  24. package/dist/runtime/AISDKThreads.d.ts.map +1 -1
  25. package/dist/runtime/AISDKThreads.js +4 -10
  26. package/dist/runtime/AISDKThreads.js.map +1 -1
  27. package/dist/runtime/sdkIdentity.d.ts +1 -2
  28. package/dist/runtime/sdkIdentity.d.ts.map +1 -1
  29. package/dist/runtime/sdkIdentity.js +1 -1
  30. package/dist/runtime/useAISDKRuntime.d.ts +17 -5
  31. package/dist/runtime/useAISDKRuntime.d.ts.map +1 -1
  32. package/dist/runtime/useAISDKRuntime.js +95 -37
  33. package/dist/runtime/useAISDKRuntime.js.map +1 -1
  34. package/dist/runtime/useChatRuntime.d.ts +2 -3
  35. package/dist/runtime/useChatRuntime.d.ts.map +1 -1
  36. package/dist/runtime/useChatThread.d.ts +19 -5
  37. package/dist/runtime/useChatThread.d.ts.map +1 -1
  38. package/dist/runtime/useChatThread.js +30 -9
  39. package/dist/runtime/useChatThread.js.map +1 -1
  40. package/dist/runtime/useExternalHistory.d.ts +2 -3
  41. package/dist/runtime/useExternalHistory.d.ts.map +1 -1
  42. package/dist/runtime/useExternalHistory.js +28 -20
  43. package/dist/runtime/useExternalHistory.js.map +1 -1
  44. package/dist/runtime/useResourceCleanup.d.ts +1 -2
  45. package/dist/runtime/useResourceCleanup.d.ts.map +1 -1
  46. package/dist/runtime/useStreamingTiming.d.ts +2 -3
  47. package/dist/runtime/useStreamingTiming.d.ts.map +1 -1
  48. package/dist/tools/frontendTools.d.ts +3 -4
  49. package/dist/tools/frontendTools.d.ts.map +1 -1
  50. package/dist/tools/generativeTools.d.ts +5 -6
  51. package/dist/tools/generativeTools.d.ts.map +1 -1
  52. package/dist/tools/mcp-stdio.unsupported.d.ts +1 -2
  53. package/dist/tools/mcp-stdio.unsupported.d.ts.map +1 -1
  54. package/dist/transport/AssistantChatTransport.d.ts +3 -4
  55. package/dist/transport/AssistantChatTransport.d.ts.map +1 -1
  56. package/dist/transport/resumable.d.ts +4 -5
  57. package/dist/transport/resumable.d.ts.map +1 -1
  58. package/dist/usage.d.ts +4 -5
  59. package/dist/usage.d.ts.map +1 -1
  60. package/dist/utils/getVercelAIMessages.d.ts +1 -2
  61. package/dist/utils/getVercelAIMessages.d.ts.map +1 -1
  62. package/dist/utils/sliceMessagesUntil.d.ts +1 -2
  63. package/dist/utils/sliceMessagesUntil.d.ts.map +1 -1
  64. package/package.json +15 -14
  65. package/src/converters/convertMessage.test.ts +138 -0
  66. package/src/converters/convertMessage.ts +94 -5
  67. package/src/runtime/AISDKChat.test.ts +4 -5
  68. package/src/runtime/AISDKThreads.test.ts +9 -5
  69. package/src/runtime/AISDKThreads.ts +3 -12
  70. package/src/runtime/useAISDKRuntime.approval.integration.test.tsx +287 -0
  71. package/src/runtime/useAISDKRuntime.approval.test.tsx +257 -1
  72. package/src/runtime/useAISDKRuntime.test.ts +7 -3
  73. package/src/runtime/useAISDKRuntime.ts +147 -23
  74. package/src/runtime/useAISDKRuntime.voice.test.tsx +270 -0
  75. package/src/runtime/useChatRuntime.test.ts +72 -4
  76. package/src/runtime/useChatThread.ts +44 -5
  77. package/src/runtime/useExternalHistory.test.ts +46 -0
  78. package/src/runtime/useExternalHistory.ts +24 -10
  79. package/src/tools/generativeTools.test.ts +7 -1
@@ -1,10 +1,10 @@
1
1
  import { JoinStrategy } from "@assistant-ui/core/react";
2
- import { AppendMessage, AssistantRuntime, ExternalStoreAdapter, ExternalStoreSharedOptions, MessageFormatRepository, SuggestionAdapter, ThreadHistoryAdapter } from "@assistant-ui/core";
2
+ import { AppendMessage, AssistantRuntime, ExternalStoreAdapter, ExternalStoreSharedOptions, MessageFormatRepository, RespondToToolApprovalOptions, SuggestionAdapter, ThreadHistoryAdapter } from "@assistant-ui/core";
3
3
  import { MessageRepository } from "@assistant-ui/core/internal";
4
4
  import { CreateUIMessage, UIMessage, useChat } from "@ai-sdk/react";
5
5
  //#region src/runtime/useAISDKRuntime.d.ts
6
- type CustomToCreateMessageFunction = <UI_MESSAGE extends UIMessage = UIMessage>(message: AppendMessage) => CreateUIMessage<UI_MESSAGE>;
7
- type AISDKRuntimeAdapter<UI_MESSAGE extends UIMessage = UIMessage> = ExternalStoreSharedOptions & {
6
+ export type CustomToCreateMessageFunction = <UI_MESSAGE extends UIMessage = UIMessage>(message: AppendMessage) => CreateUIMessage<UI_MESSAGE>;
7
+ export type AISDKRuntimeAdapter<UI_MESSAGE extends UIMessage = UIMessage> = ExternalStoreSharedOptions & {
8
8
  adapters?: (NonNullable<ExternalStoreAdapter["adapters"]> & {
9
9
  history?: ThreadHistoryAdapter | undefined;
10
10
  suggestion?: SuggestionAdapter | undefined;
@@ -35,6 +35,19 @@ type AISDKRuntimeAdapter<UI_MESSAGE extends UIMessage = UIMessage> = ExternalSto
35
35
  * Provide this to bridge resume-tool-call invocations into a custom handler.
36
36
  */
37
37
  onResumeToolCall?: ExternalStoreAdapter["onResumeToolCall"];
38
+ /**
39
+ * Answers tool approval requests through a host-owned channel instead of the AI SDK's `addToolApprovalResponse`.
40
+ *
41
+ * Called for every approval request in the thread with the complete response, including option and free-form answers. Hand requests the host does not own to `respondViaAISDK`, which is what runs when this option is omitted. The answer applies to the approval when the handler starts and is removed if it throws. It is never written into the `useChat` messages, so `sendAutomaticallyWhen` cannot forward it, and it lasts as long as this runtime: until then a second response to the same request rejects, and a runtime mounted again over the same chat shows the request open until the resumed run records its resolution in the chat.
42
+ *
43
+ * While a handler is set, an approval's `display`, `allowFreeform` and `options` reach the renderer, because the handler can receive answers the AI SDK cannot carry.
44
+ */
45
+ onRespondToToolApproval?: ((response: RespondToToolApprovalOptions, context: {
46
+ toolCallId: string;
47
+ toolName: string;
48
+ /** Sends this response through the AI SDK's `addToolApprovalResponse`, which carries only `approved` and `reason`. */
49
+ respondViaAISDK: () => Promise<void>;
50
+ }) => Promise<void> | void) | undefined;
38
51
  /**
39
52
  * How consecutive assistant messages are rendered.
40
53
  *
@@ -58,7 +71,6 @@ type AISDKRuntimeAdapter<UI_MESSAGE extends UIMessage = UIMessage> = ExternalSto
58
71
  */
59
72
  unstable_onBranchChange?: ExternalStoreAdapter["unstable_onBranchChange"];
60
73
  };
61
- declare const useAISDKRuntime: <UI_MESSAGE extends UIMessage = UIMessage>(chatHelpers: ReturnType<typeof useChat<UI_MESSAGE>>, adapter?: AISDKRuntimeAdapter<UI_MESSAGE>) => AssistantRuntime;
74
+ export declare const useAISDKRuntime: <UI_MESSAGE extends UIMessage = UIMessage>(chatHelpers: ReturnType<typeof useChat<UI_MESSAGE>>, adapter?: AISDKRuntimeAdapter<UI_MESSAGE>) => AssistantRuntime;
62
75
  //#endregion
63
- export { AISDKRuntimeAdapter, CustomToCreateMessageFunction, useAISDKRuntime };
64
76
  //# sourceMappingURL=useAISDKRuntime.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useAISDKRuntime.d.ts","names":[],"sources":["../../src/runtime/useAISDKRuntime.ts"],"mappings":";;;;;KAmEY,iCACV,mBAAmB,YAAY,WAE/B,SAAS,kBACN,gBAAgB;KAYT,oBAAoB,mBAAmB,YAAY,aAC7D;EACE,YACK,YAAY;IACX,UAAU;IACV,aAAa;;EAGnB,kBAAkB;EAClB,qCAAqC;;;;;;;;;EASrC;;;;;;;;EAQA,WAAW;;;;;;;EAOX,mBAAmB;;;;;;;;;EASnB,eAAe;;;;;;EAMf,oBAAoB,wBAAwB;;;;;;;EAO5C,0BAA0B;;cAiGjB,kBAAmB,mBAAmB,YAAY,WAC7D,aAAa,kBAAkB,QAAQ,cACvC,UAAS,oBAAoB,gBAAgB"}
1
+ {"version":3,"file":"useAISDKRuntime.d.ts","names":[],"sources":["../../src/runtime/useAISDKRuntime.ts"],"mappings":";;;;;YAuEY,iCACV,mBAAmB,YAAY,WAE/B,SAAS,kBACN,gBAAgB;YA6BT,oBAAoB,mBAAmB,YAAY,aAC7D;EACE,YACK,YAAY;IACX,UAAU;IACV,aAAa;;EAGnB,kBAAkB;EAClB,qCAAqC;;;;;;;;;EASrC;;;;;;;;EAQA,WAAW;;;;;;;EAOX,mBAAmB;;;;;;;;EAQnB,4BAEM,UAAU,8BACV;IACE;IACA;;IAEA,uBAAuB;QAEtB;;;;;;;;;EAUT,eAAe;;;;;;EAMf,oBAAoB,wBAAwB;;;;;;;EAO5C,0BAA0B;;qBAsGjB,kBAAmB,mBAAmB,YAAY,WAC7D,aAAa,kBAAkB,QAAQ,cACvC,UAAS,oBAAoB,gBAAgB"}
@@ -12,7 +12,7 @@ import { useStreamingTiming as useStreamingTiming$1 } from "./useStreamingTiming
12
12
  import { useExternalStoreRuntime, useRuntimeAdapters } from "@assistant-ui/core/react";
13
13
  import { c } from "@assistant-ui/tap/react-shim/compiler-runtime";
14
14
  import { useCallback, useEffect, useInsertionEffect, useMemo, useRef, useState } from "@assistant-ui/tap/react-shim";
15
- import { generateId, isToolUIPart } from "ai";
15
+ import { generateId, getToolName, isToolUIPart } from "ai";
16
16
  import { getExternalStoreMessages, pickExternalStoreSharedOptions } from "@assistant-ui/core";
17
17
  import { MessageRepository, consumeSuggestionResult } from "@assistant-ui/core/internal";
18
18
  //#region src/runtime/useAISDKRuntime.ts
@@ -21,6 +21,18 @@ const toUIMessage = (createMessage, fallbackRole) => ({
21
21
  id: createMessage.id ?? generateId(),
22
22
  role: createMessage.role ?? fallbackRole
23
23
  });
24
+ const toVoiceTranscriptUIMessage = (message) => ({
25
+ id: message.id,
26
+ role: message.role,
27
+ parts: message.content.filter((part) => part.type === "text").map((part) => ({
28
+ type: "text",
29
+ text: part.text
30
+ })),
31
+ metadata: {
32
+ modality: "voice",
33
+ ...Object.keys(message.metadata.custom).length > 0 && { custom: message.metadata.custom }
34
+ }
35
+ });
24
36
  const EMPTY_SUGGESTIONS = [];
25
37
  const useGeneratedSuggestions = (suggestionAdapter, messages, isRunning) => {
26
38
  const $ = c(13);
@@ -129,6 +141,7 @@ const useGeneratedSuggestions = (suggestionAdapter, messages, isRunning) => {
129
141
  return suggestions;
130
142
  };
131
143
  const NO_CANCELLED_MESSAGE_IDS = /* @__PURE__ */ new Set();
144
+ const NO_TOOL_APPROVAL_RESPONSES = /* @__PURE__ */ new Map();
132
145
  const toChatError = (error) => {
133
146
  const code = error.code;
134
147
  return {
@@ -137,11 +150,13 @@ const toChatError = (error) => {
137
150
  };
138
151
  };
139
152
  const useAISDKRuntime = (chatHelpers, adapter = {}) => {
140
- const { adapters, toCreateMessage: customToCreateMessage, cancelPendingToolCallsOnSend = true, onResume, onResumeToolCall, joinStrategy, messageRepository, unstable_onBranchChange } = adapter;
153
+ const { adapters, toCreateMessage: customToCreateMessage, cancelPendingToolCallsOnSend = true, onResume, onResumeToolCall, onRespondToToolApproval: customOnRespondToToolApproval, joinStrategy, messageRepository, unstable_onBranchChange } = adapter;
141
154
  const suggestionAdapter = adapters?.suggestion;
142
155
  const contextAdapters = useRuntimeAdapters();
143
156
  const [toolStatuses, setToolStatuses] = useState({});
144
157
  const [cancelledMessages, setCancelledMessages] = useState(null);
158
+ const [toolApprovalResponses, setToolApprovalResponses] = useState(NO_TOOL_APPROVAL_RESPONSES);
159
+ const hostApprovalIdsRef = useRef(/* @__PURE__ */ new Set());
145
160
  const toolArgsKeyOrderCacheRef = useRef(/* @__PURE__ */ new Map());
146
161
  const toolLastInputCacheRef = useRef(/* @__PURE__ */ new Map());
147
162
  const mcpAppMetadataCacheRef = useRef(/* @__PURE__ */ new Map());
@@ -154,6 +169,11 @@ const useAISDKRuntime = (chatHelpers, adapter = {}) => {
154
169
  const lastMessage = chatHelpers.messages.at(-1);
155
170
  const optimisticMessageId = isRunning && lastMessage?.role === "assistant" ? lastMessage.id : void 0;
156
171
  const cancelledMessageIds = cancelledMessages?.chatId === chatHelpers.id ? cancelledMessages.ids : NO_CANCELLED_MESSAGE_IDS;
172
+ const supportsRichToolApprovalResponses = customOnRespondToToolApproval != null;
173
+ const toThreadMessages = useCallback((sourceMessages) => {
174
+ const metadata = { supportsRichToolApprovalResponses };
175
+ return AISDKMessageConverter.toThreadMessages(sourceMessages, false, metadata);
176
+ }, [supportsRichToolApprovalResponses]);
157
177
  const retractCancellation = useCallback((chatId, messageId) => {
158
178
  setCancelledMessages((prev) => {
159
179
  if (prev?.chatId !== chatId || !prev.ids.has(messageId)) return prev;
@@ -187,27 +207,31 @@ const useAISDKRuntime = (chatHelpers, adapter = {}) => {
187
207
  toolArgsKeyOrderCache: toolArgsKeyOrderCacheRef.current,
188
208
  toolLastInputCache: toolLastInputCacheRef.current,
189
209
  mcpAppMetadataCache: mcpAppMetadataCacheRef.current,
210
+ supportsRichToolApprovalResponses,
190
211
  ...optimisticMessageId && { optimisticMessageId },
191
212
  ...chatHelpers.error && { error: toChatError(chatHelpers.error) },
192
- ...cancelledMessageIds.size > 0 && { cancelledMessageIds }
213
+ ...cancelledMessageIds.size > 0 && { cancelledMessageIds },
214
+ ...toolApprovalResponses.size > 0 && { toolApprovalResponses }
193
215
  }), [
194
216
  toolStatuses,
195
217
  messageTiming,
196
218
  optimisticMessageId,
197
219
  chatHelpers.error,
198
- cancelledMessageIds
220
+ cancelledMessageIds,
221
+ toolApprovalResponses,
222
+ supportsRichToolApprovalResponses
199
223
  ])
200
224
  });
201
225
  const exportedMessageRepository = useMemo(() => {
202
226
  if (!messageRepository) return void 0;
203
- const converted = toExportedMessageRepository(AISDKMessageConverter.toThreadMessages, messageRepository);
227
+ const converted = toExportedMessageRepository(toThreadMessages, messageRepository);
204
228
  return converted.messages.length > 0 ? converted : void 0;
205
- }, [messageRepository]);
229
+ }, [messageRepository, toThreadMessages]);
206
230
  const generatedSuggestions = useGeneratedSuggestions(suggestionAdapter, messages, isRunning);
207
231
  const [runtimeRef] = useState(() => ({ get current() {
208
232
  return runtime;
209
233
  } }));
210
- const { isLoading, deleteMessage: deleteHistoryMessage } = useExternalHistory(runtimeRef, adapters?.history ?? contextAdapters?.history, AISDKMessageConverter.toThreadMessages, aiSDKV6FormatAdapter, (messages_0) => {
234
+ const { isLoading, deleteMessage: deleteHistoryMessage } = useExternalHistory(runtimeRef, adapters?.history ?? contextAdapters?.history, toThreadMessages, aiSDKV6FormatAdapter, (messages_0) => {
211
235
  chatHelpers.setMessages(messages_0);
212
236
  });
213
237
  const { id: chatId_0, messages: chatMessages, status: chatStatus, error } = chatHelpers;
@@ -244,6 +268,44 @@ const useAISDKRuntime = (chatHelpers, adapter = {}) => {
244
268
  }];
245
269
  });
246
270
  };
271
+ const respondViaAISDK = ({ approvalId, approved, reason }) => Promise.resolve(chatHelpers.addToolApprovalResponse({
272
+ id: approvalId,
273
+ approved,
274
+ ...reason != null && { reason },
275
+ options: { metadata: lastRunConfigRef.current }
276
+ }));
277
+ const respondViaHost = async (onRespond, response) => {
278
+ const { approvalId: approvalId_0 } = response;
279
+ const requested = chatHelpers.messages.flatMap((message) => message.parts).filter(isToolUIPart).find((part_0) => part_0.state === "approval-requested" && part_0.approval.id === approvalId_0);
280
+ if (!requested || hostApprovalIdsRef.current.has(approvalId_0)) throw new Error(`Tool approval ${approvalId_0} is not waiting for a response.`);
281
+ const applyResponse = (applied) => {
282
+ if (applied) hostApprovalIdsRef.current.add(approvalId_0);
283
+ else hostApprovalIdsRef.current.delete(approvalId_0);
284
+ setToolApprovalResponses((prev_0) => {
285
+ const responses = new Map(prev_0);
286
+ if (applied) responses.set(approvalId_0, response);
287
+ else responses.delete(approvalId_0);
288
+ return responses;
289
+ });
290
+ };
291
+ applyResponse(true);
292
+ try {
293
+ await onRespond(response, {
294
+ toolCallId: requested.toolCallId,
295
+ toolName: getToolName(requested),
296
+ respondViaAISDK: async () => {
297
+ try {
298
+ await respondViaAISDK(response);
299
+ } finally {
300
+ applyResponse(false);
301
+ }
302
+ }
303
+ });
304
+ } catch (error_0) {
305
+ if (hostApprovalIdsRef.current.has(approvalId_0)) applyResponse(false);
306
+ throw error_0;
307
+ }
308
+ };
247
309
  const hasSeededRepositoryRef = useRef(false);
248
310
  const shouldFeedRepository = exportedMessageRepository != null && !hasSeededRepositoryRef.current && messages.length === 0;
249
311
  const runtime = useExternalStoreRuntime({
@@ -253,6 +315,7 @@ const useAISDKRuntime = (chatHelpers, adapter = {}) => {
253
315
  setToolStatuses,
254
316
  setMessages: (messages_2) => chatHelpers.setMessages(messages_2.map(getVercelAIMessages).filter(Boolean).flat()),
255
317
  onImport: (messages_3) => chatHelpers.setMessages(messages_3.map(getVercelAIMessages).filter(Boolean).flat()),
318
+ onVoiceTranscript: (message_0) => chatHelpers.setMessages((current) => [...current, toVoiceTranscriptUIMessage(message_0)]),
256
319
  onExportExternalState: () => {
257
320
  const exported = runtimeRef.current.thread.export();
258
321
  const expandedMessages = [];
@@ -274,16 +337,16 @@ const useAISDKRuntime = (chatHelpers, adapter = {}) => {
274
337
  return result;
275
338
  },
276
339
  onLoadExternalState: (repo) => {
277
- const exportedRepo = toExportedMessageRepository(AISDKMessageConverter.toThreadMessages, repo);
340
+ const exportedRepo = toExportedMessageRepository(toThreadMessages, repo);
278
341
  runtimeRef.current.thread.import(exportedRepo);
279
342
  },
280
343
  onCancel: async () => {
281
- const message = chatHelpers.messages.at(-1);
282
- const cancelledId = isRunning && message?.role === "assistant" ? message.id : void 0;
344
+ const message_1 = chatHelpers.messages.at(-1);
345
+ const cancelledId = isRunning && message_1?.role === "assistant" ? message_1.id : void 0;
283
346
  if (cancelledId) {
284
347
  const liveIds = new Set(chatHelpers.messages.map((m) => m.id));
285
- setCancelledMessages((prev_0) => {
286
- const kept = prev_0?.chatId === chatHelpers.id ? [...prev_0.ids].filter((id) => liveIds.has(id)) : [];
348
+ setCancelledMessages((prev_1) => {
349
+ const kept = prev_1?.chatId === chatHelpers.id ? [...prev_1.ids].filter((id) => liveIds.has(id)) : [];
287
350
  return {
288
351
  chatId: chatHelpers.id,
289
352
  ids: /* @__PURE__ */ new Set([...kept, cancelledId])
@@ -292,40 +355,40 @@ const useAISDKRuntime = (chatHelpers, adapter = {}) => {
292
355
  }
293
356
  try {
294
357
  await chatHelpers.stop();
295
- } catch (error_0) {
296
- if (!(error_0 instanceof Error && error_0.name === "AbortError")) {
358
+ } catch (error_1) {
359
+ if (!(error_1 instanceof Error && error_1.name === "AbortError")) {
297
360
  if (cancelledId) retractCancellation(chatHelpers.id, cancelledId);
298
- throw error_0;
361
+ throw error_1;
299
362
  }
300
363
  }
301
364
  },
302
- onNew: async (message_0) => {
303
- const createMessage = (customToCreateMessage ?? toCreateMessage)(message_0);
304
- if (!(message_0.startRun ?? message_0.role === "user")) {
305
- chatHelpers.setMessages((current) => [...current, toUIMessage(createMessage, message_0.role)]);
365
+ onNew: async (message_2) => {
366
+ const createMessage = (customToCreateMessage ?? toCreateMessage)(message_2);
367
+ if (!(message_2.startRun ?? message_2.role === "user")) {
368
+ chatHelpers.setMessages((current_0) => [...current_0, toUIMessage(createMessage, message_2.role)]);
306
369
  return;
307
370
  }
308
- lastRunConfigRef.current = message_0.runConfig;
371
+ lastRunConfigRef.current = message_2.runConfig;
309
372
  await completePendingToolCalls();
310
- await chatHelpers.sendMessage(createMessage, { metadata: message_0.runConfig });
373
+ await chatHelpers.sendMessage(createMessage, { metadata: message_2.runConfig });
311
374
  },
312
- onEdit: async (message_1) => {
313
- const createMessage_0 = (customToCreateMessage ?? toCreateMessage)(message_1);
314
- if (!(message_1.startRun ?? message_1.role === "user")) {
315
- chatHelpers.setMessages((current_0) => [...sliceMessagesUntil(current_0, message_1.parentId), toUIMessage(createMessage_0, message_1.role)]);
375
+ onEdit: async (message_3) => {
376
+ const createMessage_0 = (customToCreateMessage ?? toCreateMessage)(message_3);
377
+ if (!(message_3.startRun ?? message_3.role === "user")) {
378
+ chatHelpers.setMessages((current_1) => [...sliceMessagesUntil(current_1, message_3.parentId), toUIMessage(createMessage_0, message_3.role)]);
316
379
  return;
317
380
  }
318
- lastRunConfigRef.current = message_1.runConfig;
319
- chatHelpers.setMessages((current_1) => sliceMessagesUntil(current_1, message_1.parentId));
320
- await chatHelpers.sendMessage(createMessage_0, { metadata: message_1.runConfig });
381
+ lastRunConfigRef.current = message_3.runConfig;
382
+ chatHelpers.setMessages((current_2) => sliceMessagesUntil(current_2, message_3.parentId));
383
+ await chatHelpers.sendMessage(createMessage_0, { metadata: message_3.runConfig });
321
384
  },
322
385
  onDelete: async (messageId_0) => {
323
386
  const threadMessages = runtimeRef.current.thread.getState().messages;
324
- const messageIndex = threadMessages.findIndex((message_2) => message_2.id === messageId_0);
387
+ const messageIndex = threadMessages.findIndex((message_4) => message_4.id === messageId_0);
325
388
  if (messageIndex === -1) return;
326
389
  await deleteHistoryMessage(messageId_0);
327
- const deleteIds = new Set(getExternalStoreMessages(threadMessages[messageIndex]).map((message_3) => message_3.id));
328
- chatHelpers.setMessages((current_2) => current_2.filter((message_4) => !deleteIds.has(message_4.id)));
390
+ const deleteIds = new Set(getExternalStoreMessages(threadMessages[messageIndex]).map((message_5) => message_5.id));
391
+ chatHelpers.setMessages((current_3) => current_3.filter((message_6) => !deleteIds.has(message_6.id)));
329
392
  },
330
393
  onReload: async (parentId_0, config) => {
331
394
  lastRunConfigRef.current = config.runConfig;
@@ -352,12 +415,7 @@ const useAISDKRuntime = (chatHelpers, adapter = {}) => {
352
415
  }));
353
416
  }
354
417
  },
355
- onRespondToToolApproval: ({ approvalId, approved, reason }) => Promise.resolve(chatHelpers.addToolApprovalResponse({
356
- id: approvalId,
357
- approved,
358
- ...reason != null && { reason },
359
- options: { metadata: lastRunConfigRef.current }
360
- })),
418
+ onRespondToToolApproval: customOnRespondToToolApproval ? (response_0) => respondViaHost(customOnRespondToToolApproval, response_0) : respondViaAISDK,
361
419
  ...pickExternalStoreSharedOptions(adapter),
362
420
  ...adapter.unstable_messageRepositoryInstance && { unstable_messageRepositoryInstance: adapter.unstable_messageRepositoryInstance },
363
421
  ...suggestionAdapter ? { suggestions: generatedSuggestions } : {},
@@ -1 +1 @@
1
- {"version":3,"file":"useAISDKRuntime.js","names":["c","_c","useCallback","useEffect","useInsertionEffect","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","MessageRepository","ReadonlyJSONObject","AssistantError","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","unstable_messageRepositoryInstance","cancelPendingToolCallsOnSend","onResume","onResumeToolCall","joinStrategy","messageRepository","unstable_onBranchChange","EMPTY_SUGGESTIONS","useGeneratedSuggestions","suggestionAdapter","messages","isRunning","$","suggestions","setSuggestions","controllerRef","wasRunningRef","messagesRef","t0","t1","current","adapterRef","t2","t3","hasAdapter","t4","clearSuggestions","abort","_temp","adapter","currentMessages","last","at","status","type","controller","AbortController","signal","promiseOrGenerator","generate","onUpdate","t5","t6","t7","Symbol","for","NO_CANCELLED_MESSAGE_IDS","ReadonlySet","Set","toChatError","error","Error","code","name","useAISDKRuntime","chatHelpers","ReturnType","customToCreateMessage","contextAdapters","toolStatuses","setToolStatuses","Record","cancelledMessages","setCancelledMessages","chatId","ids","toolArgsKeyOrderCacheRef","Map","toolLastInputCacheRef","mcpAppMetadataCacheRef","lastRunConfigRef","undefined","hasExecutingTools","Object","values","some","s","providerIsRunning","wasProviderRunningRef","messageTiming","lastMessage","optimisticMessageId","cancelledMessageIds","retractCancellation","messageId","prev","has","delete","resumedMessageId","wasProviderRunning","useThreadMessages","metadata","toolArgsKeyOrderCache","toolLastInputCache","mcpAppMetadataCache","size","exportedMessageRepository","converted","toThreadMessages","length","generatedSuggestions","runtimeRef","runtime","isLoading","deleteMessage","deleteHistoryMessage","setMessages","chatMessages","chatStatus","extras","provide","chat","completePendingToolCalls","hasChanges","parts","map","part","state","approval","_approval","rest","const","errorText","slice","hasSeededRepositoryRef","shouldFeedRepository","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","cancelledId","liveIds","m","kept","stop","onNew","startRun","runConfig","sendMessage","onEdit","onDelete","threadMessages","getState","messageIndex","findIndex","deleteIds","onReload","config","newMessages","regenerate","onAddToolResult","toolCallId","toolName","isError","modelContent","options","Promise","resolve","addToolOutput","tool","JSON","stringify","output","onRespondToToolApproval","approvalId","approved","reason","addToolApprovalResponse","attachments","setMessagesRef","tempRepo","getMessages","flatMap"],"sources":["../../src/runtime/useAISDKRuntime.ts"],"sourcesContent":["\"use client\";\n\nimport {\n useCallback,\n useEffect,\n useInsertionEffect,\n useMemo,\n useRef,\n useState,\n} 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 {\n consumeSuggestionResult,\n MessageRepository,\n} from \"@assistant-ui/core/internal\";\nimport type { ReadonlyJSONObject } from \"assistant-stream/utils\";\nimport type { AssistantError } from \"@assistant-ui/core\";\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<UI_MESSAGE extends UIMessage = UIMessage> =\n ExternalStoreSharedOptions & {\n adapters?:\n | (NonNullable<ExternalStoreAdapter[\"adapters\"]> & {\n history?: ThreadHistoryAdapter | undefined;\n suggestion?: SuggestionAdapter | undefined;\n })\n | undefined;\n toCreateMessage?: CustomToCreateMessageFunction;\n unstable_messageRepositoryInstance?: MessageRepository | undefined;\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 * A branch-aware AI SDK message tree seeded once when `useChat` is empty.\n * After that seed, live updates come only from `useChat`. A later empty\n * chat or a new object identity does not reload the tree.\n */\n messageRepository?: MessageFormatRepository<UI_MESSAGE>;\n /**\n * Called after an explicit `switchToBranch` (for example a BranchPicker\n * click). Complements `setMessages` and does not enable switching by itself.\n *\n * @deprecated This API is still under active development and might change without notice.\n */\n unstable_onBranchChange?: ExternalStoreAdapter[\"unstable_onBranchChange\"];\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 useInsertionEffect(() => {\n messagesRef.current = messages;\n }, [messages]);\n const adapterRef = useRef(suggestionAdapter);\n useInsertionEffect(() => {\n adapterRef.current = suggestionAdapter;\n }, [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\nconst NO_CANCELLED_MESSAGE_IDS: ReadonlySet<string> = new Set();\n\nconst toChatError = (error: Error): AssistantError => {\n const code = (error as { code?: unknown }).code;\n return {\n code:\n typeof code === \"string\"\n ? code\n : error.name !== \"Error\"\n ? error.name\n : \"unknown\",\n message: error.message,\n };\n};\n\nexport const useAISDKRuntime = <UI_MESSAGE extends UIMessage = UIMessage>(\n chatHelpers: ReturnType<typeof useChat<UI_MESSAGE>>,\n adapter: AISDKRuntimeAdapter<UI_MESSAGE> = {},\n) => {\n const {\n adapters,\n toCreateMessage: customToCreateMessage,\n cancelPendingToolCallsOnSend = true,\n onResume,\n onResumeToolCall,\n joinStrategy,\n messageRepository,\n unstable_onBranchChange,\n } = adapter;\n const suggestionAdapter = adapters?.suggestion;\n const contextAdapters = useRuntimeAdapters();\n const [toolStatuses, setToolStatuses] = useState<\n Record<string, ToolExecutionStatus>\n >({});\n const [cancelledMessages, setCancelledMessages] = useState<{\n chatId: string;\n ids: ReadonlySet<string>;\n } | null>(null);\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 providerIsRunning =\n chatHelpers.status === \"submitted\" || chatHelpers.status === \"streaming\";\n const isRunning = providerIsRunning || hasExecutingTools;\n const wasProviderRunningRef = useRef(providerIsRunning);\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 cancelledMessageIds =\n cancelledMessages?.chatId === chatHelpers.id\n ? cancelledMessages.ids\n : NO_CANCELLED_MESSAGE_IDS;\n\n const retractCancellation = useCallback(\n (chatId: string, messageId: string) => {\n setCancelledMessages((prev) => {\n if (prev?.chatId !== chatId || !prev.ids.has(messageId)) return prev;\n const ids = new Set(prev.ids);\n ids.delete(messageId);\n return { chatId, ids };\n });\n },\n [],\n );\n\n // A provider run that resumes the stopped response retracts its cancellation;\n // a run that starts a new response leaves the stopped one marked.\n const resumedMessageId =\n providerIsRunning && lastMessage?.role === \"assistant\"\n ? lastMessage.id\n : undefined;\n\n useEffect(() => {\n const wasProviderRunning = wasProviderRunningRef.current;\n wasProviderRunningRef.current = providerIsRunning;\n if (wasProviderRunning || !resumedMessageId) return;\n retractCancellation(chatHelpers.id, resumedMessageId);\n }, [\n providerIsRunning,\n resumedMessageId,\n chatHelpers.id,\n retractCancellation,\n ]);\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 && {\n error: toChatError(chatHelpers.error),\n }),\n ...(cancelledMessageIds.size > 0 && { cancelledMessageIds }),\n }),\n [\n toolStatuses,\n messageTiming,\n optimisticMessageId,\n chatHelpers.error,\n cancelledMessageIds,\n ],\n ),\n });\n\n const exportedMessageRepository = useMemo(() => {\n if (!messageRepository) return undefined;\n const converted = toExportedMessageRepository(\n AISDKMessageConverter.toThreadMessages as (\n messages: UI_MESSAGE[],\n ) => ThreadMessage[],\n messageRepository,\n );\n return converted.messages.length > 0 ? converted : undefined;\n }, [messageRepository]);\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 (\n part.state === \"output-available\" ||\n part.state === \"output-error\" ||\n part.state === \"output-denied\"\n )\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 hasSeededRepositoryRef = useRef(false);\n const shouldFeedRepository =\n exportedMessageRepository != null &&\n !hasSeededRepositoryRef.current &&\n messages.length === 0;\n\n const runtime = useExternalStoreRuntime({\n isRunning: providerIsRunning,\n ...(shouldFeedRepository\n ? { messageRepository: exportedMessageRepository }\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 const message = chatHelpers.messages.at(-1);\n const cancelledId =\n isRunning && message?.role === \"assistant\" ? message.id : undefined;\n if (cancelledId) {\n const liveIds = new Set(chatHelpers.messages.map((m) => m.id));\n setCancelledMessages((prev) => {\n const kept =\n prev?.chatId === chatHelpers.id\n ? [...prev.ids].filter((id) => liveIds.has(id))\n : [];\n return {\n chatId: chatHelpers.id,\n ids: new Set([...kept, cancelledId]),\n };\n });\n }\n try {\n await chatHelpers.stop();\n } catch (error) {\n if (!(error instanceof Error && error.name === \"AbortError\")) {\n if (cancelledId) retractCancellation(chatHelpers.id, cancelledId);\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 ...(adapter.unstable_messageRepositoryInstance && {\n unstable_messageRepositoryInstance:\n adapter.unstable_messageRepositoryInstance,\n }),\n ...(suggestionAdapter ? { suggestions: generatedSuggestions } : {}),\n ...(onResume && { onResume }),\n ...(onResumeToolCall && { onResumeToolCall }),\n ...(unstable_onBranchChange && { unstable_onBranchChange }),\n adapters: {\n attachments: vercelAttachmentAdapter,\n ...contextAdapters,\n ...adapters,\n },\n extras,\n isLoading,\n });\n\n const setMessagesRef = useRef(chatHelpers.setMessages);\n useInsertionEffect(() => {\n setMessagesRef.current = chatHelpers.setMessages;\n }, [chatHelpers.setMessages]);\n\n useEffect(() => {\n if (hasSeededRepositoryRef.current) return;\n if (!exportedMessageRepository) return;\n if (chatHelpers.messages.length > 0) {\n hasSeededRepositoryRef.current = true;\n return;\n }\n const tempRepo = new MessageRepository();\n tempRepo.import(exportedMessageRepository);\n setMessagesRef.current(\n tempRepo.getMessages().flatMap(getExternalStoreMessages<UI_MESSAGE>),\n );\n hasSeededRepositoryRef.current = true;\n }, [exportedMessageRepository, chatHelpers.messages.length]);\n return runtime;\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"useAISDKRuntime.js","names":["c","_c","useCallback","useEffect","useInsertionEffect","useMemo","useRef","useState","UIMessage","useChat","CreateUIMessage","UseChatHelpers","isToolUIPart","generateId","getToolName","useExternalStoreRuntime","useRuntimeAdapters","JoinStrategy","SuggestionAdapter","ThreadSuggestion","ToolExecutionStatus","ExternalStoreAdapter","ExternalStoreSharedOptions","ThreadHistoryAdapter","AssistantRuntime","ThreadMessage","MessageFormatAdapter","MessageFormatItem","MessageFormatRepository","AppendMessage","RunConfig","McpAppMetadata","RespondToToolApprovalOptions","getExternalStoreMessages","pickExternalStoreSharedOptions","consumeSuggestionResult","MessageRepository","ReadonlyJSONObject","AssistantError","sliceMessagesUntil","toCreateMessage","vercelAttachmentAdapter","getVercelAIMessages","AISDKMessageConverter","AISDKMessageConverterMetadata","wrapModelContentEnvelope","AISDKStorageFormat","aiSDKV6FormatAdapter","useExternalHistory","toExportedMessageRepository","useStreamingTiming","aiSDKExtras","CustomToCreateMessageFunction","message","UI_MESSAGE","toUIMessage","createMessage","fallbackRole","id","role","toVoiceTranscriptUIMessage","parts","content","filter","part","type","map","text","metadata","modality","Object","keys","custom","length","AISDKRuntimeAdapter","adapters","NonNullable","history","suggestion","unstable_messageRepositoryInstance","cancelPendingToolCallsOnSend","onResume","onResumeToolCall","onRespondToToolApproval","response","context","toolCallId","toolName","respondViaAISDK","Promise","joinStrategy","messageRepository","unstable_onBranchChange","EMPTY_SUGGESTIONS","useGeneratedSuggestions","suggestionAdapter","messages","isRunning","$","suggestions","setSuggestions","controllerRef","wasRunningRef","messagesRef","t0","t1","current","adapterRef","t2","t3","hasAdapter","t4","clearSuggestions","abort","_temp","adapter","currentMessages","last","at","status","controller","AbortController","signal","promiseOrGenerator","generate","onUpdate","t5","t6","t7","Symbol","for","NO_CANCELLED_MESSAGE_IDS","ReadonlySet","Set","NO_TOOL_APPROVAL_RESPONSES","ReadonlyMap","Map","toChatError","error","Error","code","name","useAISDKRuntime","chatHelpers","ReturnType","customToCreateMessage","customOnRespondToToolApproval","contextAdapters","toolStatuses","setToolStatuses","Record","cancelledMessages","setCancelledMessages","chatId","ids","toolApprovalResponses","setToolApprovalResponses","hostApprovalIdsRef","toolArgsKeyOrderCacheRef","toolLastInputCacheRef","mcpAppMetadataCacheRef","lastRunConfigRef","undefined","hasExecutingTools","values","some","s","providerIsRunning","wasProviderRunningRef","messageTiming","lastMessage","optimisticMessageId","cancelledMessageIds","supportsRichToolApprovalResponses","toThreadMessages","sourceMessages","retractCancellation","messageId","prev","has","delete","resumedMessageId","wasProviderRunning","useThreadMessages","toolArgsKeyOrderCache","toolLastInputCache","mcpAppMetadataCache","size","exportedMessageRepository","converted","generatedSuggestions","runtimeRef","runtime","isLoading","deleteMessage","deleteHistoryMessage","setMessages","chatMessages","chatStatus","extras","provide","chat","completePendingToolCalls","hasChanges","state","approval","_approval","rest","const","errorText","slice","approvalId","approved","reason","resolve","addToolApprovalResponse","options","respondViaHost","onRespond","requested","flatMap","find","applyResponse","applied","add","responses","set","hasSeededRepositoryRef","shouldFeedRepository","unstable_enableToolInvocations","Boolean","flat","onImport","onVoiceTranscript","onExportExternalState","exported","thread","export","expandedMessages","lastInnerIdMap","item","innerMessages","parentId","get","innerMessage","push","getId","result","headId","onLoadExternalState","repo","exportedRepo","import","onCancel","cancelledId","liveIds","m","kept","stop","onNew","startRun","runConfig","sendMessage","onEdit","onDelete","threadMessages","getState","messageIndex","findIndex","deleteIds","onReload","config","newMessages","regenerate","onAddToolResult","isError","modelContent","addToolOutput","tool","JSON","stringify","output","attachments","setMessagesRef","tempRepo","getMessages"],"sources":["../../src/runtime/useAISDKRuntime.ts"],"sourcesContent":["\"use client\";\n\nimport {\n useCallback,\n useEffect,\n useInsertionEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport type {\n UIMessage,\n useChat,\n CreateUIMessage,\n UseChatHelpers,\n} from \"@ai-sdk/react\";\nimport { isToolUIPart, generateId, getToolName } 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 RespondToToolApprovalOptions,\n} from \"@assistant-ui/core\";\nimport {\n getExternalStoreMessages,\n pickExternalStoreSharedOptions,\n} from \"@assistant-ui/core\";\nimport {\n consumeSuggestionResult,\n MessageRepository,\n} from \"@assistant-ui/core/internal\";\nimport type { ReadonlyJSONObject } from \"assistant-stream/utils\";\nimport type { AssistantError } from \"@assistant-ui/core\";\nimport { sliceMessagesUntil } from \"../utils/sliceMessagesUntil\";\nimport { toCreateMessage } from \"../converters/toCreateMessage\";\nimport { vercelAttachmentAdapter } from \"../adapters/vercelAttachmentAdapter\";\nimport { getVercelAIMessages } from \"../utils/getVercelAIMessages\";\nimport {\n AISDKMessageConverter,\n type AISDKMessageConverterMetadata,\n} 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\nconst toVoiceTranscriptUIMessage = <UI_MESSAGE extends UIMessage>(\n message: ThreadMessage,\n): UI_MESSAGE =>\n ({\n id: message.id,\n role: message.role,\n parts: message.content\n .filter((part) => part.type === \"text\")\n .map((part) => ({ type: \"text\", text: part.text })),\n metadata: {\n modality: \"voice\",\n ...(Object.keys(message.metadata.custom).length > 0 && {\n custom: message.metadata.custom,\n }),\n },\n }) as UI_MESSAGE;\n\nexport type AISDKRuntimeAdapter<UI_MESSAGE extends UIMessage = UIMessage> =\n ExternalStoreSharedOptions & {\n adapters?:\n | (NonNullable<ExternalStoreAdapter[\"adapters\"]> & {\n history?: ThreadHistoryAdapter | undefined;\n suggestion?: SuggestionAdapter | undefined;\n })\n | undefined;\n toCreateMessage?: CustomToCreateMessageFunction;\n unstable_messageRepositoryInstance?: MessageRepository | undefined;\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 * Answers tool approval requests through a host-owned channel instead of the AI SDK's `addToolApprovalResponse`.\n *\n * Called for every approval request in the thread with the complete response, including option and free-form answers. Hand requests the host does not own to `respondViaAISDK`, which is what runs when this option is omitted. The answer applies to the approval when the handler starts and is removed if it throws. It is never written into the `useChat` messages, so `sendAutomaticallyWhen` cannot forward it, and it lasts as long as this runtime: until then a second response to the same request rejects, and a runtime mounted again over the same chat shows the request open until the resumed run records its resolution in the chat.\n *\n * While a handler is set, an approval's `display`, `allowFreeform` and `options` reach the renderer, because the handler can receive answers the AI SDK cannot carry.\n */\n onRespondToToolApproval?:\n | ((\n response: RespondToToolApprovalOptions,\n context: {\n toolCallId: string;\n toolName: string;\n /** Sends this response through the AI SDK's `addToolApprovalResponse`, which carries only `approved` and `reason`. */\n respondViaAISDK: () => Promise<void>;\n },\n ) => Promise<void> | void)\n | undefined;\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 * A branch-aware AI SDK message tree seeded once when `useChat` is empty.\n * After that seed, live updates come only from `useChat`. A later empty\n * chat or a new object identity does not reload the tree.\n */\n messageRepository?: MessageFormatRepository<UI_MESSAGE>;\n /**\n * Called after an explicit `switchToBranch` (for example a BranchPicker\n * click). Complements `setMessages` and does not enable switching by itself.\n *\n * @deprecated This API is still under active development and might change without notice.\n */\n unstable_onBranchChange?: ExternalStoreAdapter[\"unstable_onBranchChange\"];\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 useInsertionEffect(() => {\n messagesRef.current = messages;\n }, [messages]);\n const adapterRef = useRef(suggestionAdapter);\n useInsertionEffect(() => {\n adapterRef.current = suggestionAdapter;\n }, [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\nconst NO_CANCELLED_MESSAGE_IDS: ReadonlySet<string> = new Set();\n\nconst NO_TOOL_APPROVAL_RESPONSES: ReadonlyMap<\n string,\n RespondToToolApprovalOptions\n> = new Map();\n\nconst toChatError = (error: Error): AssistantError => {\n const code = (error as { code?: unknown }).code;\n return {\n code:\n typeof code === \"string\"\n ? code\n : error.name !== \"Error\"\n ? error.name\n : \"unknown\",\n message: error.message,\n };\n};\n\nexport const useAISDKRuntime = <UI_MESSAGE extends UIMessage = UIMessage>(\n chatHelpers: ReturnType<typeof useChat<UI_MESSAGE>>,\n adapter: AISDKRuntimeAdapter<UI_MESSAGE> = {},\n) => {\n const {\n adapters,\n toCreateMessage: customToCreateMessage,\n cancelPendingToolCallsOnSend = true,\n onResume,\n onResumeToolCall,\n onRespondToToolApproval: customOnRespondToToolApproval,\n joinStrategy,\n messageRepository,\n unstable_onBranchChange,\n } = adapter;\n const suggestionAdapter = adapters?.suggestion;\n const contextAdapters = useRuntimeAdapters();\n const [toolStatuses, setToolStatuses] = useState<\n Record<string, ToolExecutionStatus>\n >({});\n const [cancelledMessages, setCancelledMessages] = useState<{\n chatId: string;\n ids: ReadonlySet<string>;\n } | null>(null);\n const [toolApprovalResponses, setToolApprovalResponses] = useState<\n ReadonlyMap<string, RespondToToolApprovalOptions>\n >(NO_TOOL_APPROVAL_RESPONSES);\n const hostApprovalIdsRef = useRef(new Set<string>());\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 providerIsRunning =\n chatHelpers.status === \"submitted\" || chatHelpers.status === \"streaming\";\n const isRunning = providerIsRunning || hasExecutingTools;\n const wasProviderRunningRef = useRef(providerIsRunning);\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 cancelledMessageIds =\n cancelledMessages?.chatId === chatHelpers.id\n ? cancelledMessages.ids\n : NO_CANCELLED_MESSAGE_IDS;\n const supportsRichToolApprovalResponses =\n customOnRespondToToolApproval != null;\n\n const toThreadMessages = useCallback(\n (sourceMessages: UI_MESSAGE[]) => {\n const metadata: AISDKMessageConverterMetadata = {\n supportsRichToolApprovalResponses,\n };\n return AISDKMessageConverter.toThreadMessages(\n sourceMessages,\n false,\n metadata,\n );\n },\n [supportsRichToolApprovalResponses],\n );\n\n const retractCancellation = useCallback(\n (chatId: string, messageId: string) => {\n setCancelledMessages((prev) => {\n if (prev?.chatId !== chatId || !prev.ids.has(messageId)) return prev;\n const ids = new Set(prev.ids);\n ids.delete(messageId);\n return { chatId, ids };\n });\n },\n [],\n );\n\n // A provider run that resumes the stopped response retracts its cancellation;\n // a run that starts a new response leaves the stopped one marked.\n const resumedMessageId =\n providerIsRunning && lastMessage?.role === \"assistant\"\n ? lastMessage.id\n : undefined;\n\n useEffect(() => {\n const wasProviderRunning = wasProviderRunningRef.current;\n wasProviderRunningRef.current = providerIsRunning;\n if (wasProviderRunning || !resumedMessageId) return;\n retractCancellation(chatHelpers.id, resumedMessageId);\n }, [\n providerIsRunning,\n resumedMessageId,\n chatHelpers.id,\n retractCancellation,\n ]);\n\n const messages = AISDKMessageConverter.useThreadMessages({\n isRunning,\n messages: chatHelpers.messages,\n joinStrategy,\n metadata: useMemo<AISDKMessageConverterMetadata>(\n () => ({\n toolStatuses,\n messageTiming,\n toolArgsKeyOrderCache: toolArgsKeyOrderCacheRef.current,\n toolLastInputCache: toolLastInputCacheRef.current,\n mcpAppMetadataCache: mcpAppMetadataCacheRef.current,\n supportsRichToolApprovalResponses,\n ...(optimisticMessageId && { optimisticMessageId }),\n ...(chatHelpers.error && {\n error: toChatError(chatHelpers.error),\n }),\n ...(cancelledMessageIds.size > 0 && { cancelledMessageIds }),\n ...(toolApprovalResponses.size > 0 && { toolApprovalResponses }),\n }),\n [\n toolStatuses,\n messageTiming,\n optimisticMessageId,\n chatHelpers.error,\n cancelledMessageIds,\n toolApprovalResponses,\n supportsRichToolApprovalResponses,\n ],\n ),\n });\n\n const exportedMessageRepository = useMemo(() => {\n if (!messageRepository) return undefined;\n const converted = toExportedMessageRepository(\n toThreadMessages,\n messageRepository,\n );\n return converted.messages.length > 0 ? converted : undefined;\n }, [messageRepository, toThreadMessages]);\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 toThreadMessages,\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 (\n part.state === \"output-available\" ||\n part.state === \"output-error\" ||\n part.state === \"output-denied\"\n )\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 respondViaAISDK = ({\n approvalId,\n approved,\n reason,\n }: RespondToToolApprovalOptions) =>\n Promise.resolve(\n chatHelpers.addToolApprovalResponse({\n id: approvalId,\n approved,\n ...(reason != null && { reason }),\n options: { metadata: lastRunConfigRef.current },\n }),\n );\n\n const respondViaHost = async (\n onRespond: NonNullable<AISDKRuntimeAdapter[\"onRespondToToolApproval\"]>,\n response: RespondToToolApprovalOptions,\n ) => {\n const { approvalId } = response;\n const requested = chatHelpers.messages\n .flatMap((message) => message.parts)\n .filter(isToolUIPart)\n .find(\n (part) =>\n part.state === \"approval-requested\" &&\n part.approval.id === approvalId,\n );\n if (!requested || hostApprovalIdsRef.current.has(approvalId))\n throw new Error(\n `Tool approval ${approvalId} is not waiting for a response.`,\n );\n\n // A host answer stays out of the useChat messages, where sendAutomaticallyWhen would forward it to the chat route.\n const applyResponse = (applied: boolean) => {\n if (applied) hostApprovalIdsRef.current.add(approvalId);\n else hostApprovalIdsRef.current.delete(approvalId);\n setToolApprovalResponses((prev) => {\n const responses = new Map(prev);\n if (applied) responses.set(approvalId, response);\n else responses.delete(approvalId);\n return responses;\n });\n };\n\n applyResponse(true);\n try {\n await onRespond(response, {\n toolCallId: requested.toolCallId,\n toolName: getToolName(requested),\n respondViaAISDK: async () => {\n try {\n await respondViaAISDK(response);\n } finally {\n applyResponse(false);\n }\n },\n });\n } catch (error) {\n if (hostApprovalIdsRef.current.has(approvalId)) applyResponse(false);\n throw error;\n }\n };\n\n const hasSeededRepositoryRef = useRef(false);\n const shouldFeedRepository =\n exportedMessageRepository != null &&\n !hasSeededRepositoryRef.current &&\n messages.length === 0;\n\n const runtime = useExternalStoreRuntime({\n isRunning: providerIsRunning,\n ...(shouldFeedRepository\n ? { messageRepository: exportedMessageRepository }\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 onVoiceTranscript: (message: ThreadMessage) =>\n chatHelpers.setMessages((current) => [\n ...current,\n toVoiceTranscriptUIMessage<UI_MESSAGE>(message),\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(toThreadMessages, repo);\n\n // Import into the thread's MessageRepository\n runtimeRef.current.thread.import(exportedRepo);\n },\n onCancel: async () => {\n const message = chatHelpers.messages.at(-1);\n const cancelledId =\n isRunning && message?.role === \"assistant\" ? message.id : undefined;\n if (cancelledId) {\n const liveIds = new Set(chatHelpers.messages.map((m) => m.id));\n setCancelledMessages((prev) => {\n const kept =\n prev?.chatId === chatHelpers.id\n ? [...prev.ids].filter((id) => liveIds.has(id))\n : [];\n return {\n chatId: chatHelpers.id,\n ids: new Set([...kept, cancelledId]),\n };\n });\n }\n try {\n await chatHelpers.stop();\n } catch (error) {\n if (!(error instanceof Error && error.name === \"AbortError\")) {\n if (cancelledId) retractCancellation(chatHelpers.id, cancelledId);\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: customOnRespondToToolApproval\n ? (response) => respondViaHost(customOnRespondToToolApproval, response)\n : respondViaAISDK,\n ...pickExternalStoreSharedOptions(adapter),\n ...(adapter.unstable_messageRepositoryInstance && {\n unstable_messageRepositoryInstance:\n adapter.unstable_messageRepositoryInstance,\n }),\n ...(suggestionAdapter ? { suggestions: generatedSuggestions } : {}),\n ...(onResume && { onResume }),\n ...(onResumeToolCall && { onResumeToolCall }),\n ...(unstable_onBranchChange && { unstable_onBranchChange }),\n adapters: {\n attachments: vercelAttachmentAdapter,\n ...contextAdapters,\n ...adapters,\n },\n extras,\n isLoading,\n });\n\n const setMessagesRef = useRef(chatHelpers.setMessages);\n useInsertionEffect(() => {\n setMessagesRef.current = chatHelpers.setMessages;\n }, [chatHelpers.setMessages]);\n\n useEffect(() => {\n if (hasSeededRepositoryRef.current) return;\n if (!exportedMessageRepository) return;\n if (chatHelpers.messages.length > 0) {\n hasSeededRepositoryRef.current = true;\n return;\n }\n const tempRepo = new MessageRepository();\n tempRepo.import(exportedMessageRepository);\n setMessagesRef.current(\n tempRepo.getMessages().flatMap(getExternalStoreMessages<UI_MESSAGE>),\n );\n hasSeededRepositoryRef.current = true;\n }, [exportedMessageRepository, chatHelpers.messages.length]);\n return runtime;\n};\n"],"mappings":"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"}
@@ -3,11 +3,10 @@ import { AssistantRuntime } from "@assistant-ui/core";
3
3
  import { UIMessage } from "@ai-sdk/react";
4
4
  import { AssistantCloud } from "assistant-cloud";
5
5
  //#region src/runtime/useChatRuntime.d.ts
6
- type UseChatRuntimeOptions<UI_MESSAGE extends UIMessage = UIMessage> = ChatThreadOptions<UI_MESSAGE> & {
6
+ export type UseChatRuntimeOptions<UI_MESSAGE extends UIMessage = UIMessage> = ChatThreadOptions<UI_MESSAGE> & {
7
7
  cloud?: AssistantCloud | undefined;
8
8
  onThreadIdChange?: ((threadId: string | undefined) => void) | undefined;
9
9
  };
10
- declare const useChatRuntime: <UI_MESSAGE extends UIMessage = UIMessage>({ cloud, onThreadIdChange, ...options }?: UseChatRuntimeOptions<UI_MESSAGE>) => AssistantRuntime;
10
+ export declare const useChatRuntime: <UI_MESSAGE extends UIMessage = UIMessage>({ cloud, onThreadIdChange, ...options }?: UseChatRuntimeOptions<UI_MESSAGE>) => AssistantRuntime;
11
11
  //#endregion
12
- export { UseChatRuntimeOptions, useChatRuntime };
13
12
  //# sourceMappingURL=useChatRuntime.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useChatRuntime.d.ts","names":[],"sources":["../../src/runtime/useChatRuntime.ts"],"mappings":";;;;;KAaY,sBAAsB,mBAAmB,YAAY,aAC/D,kBAAkB;EAChB,QAAQ;EACR,qBAAqB;;cAoBZ,iBAAkB,mBAAmB,YAAY,aAAW,OAAA,qBAAA,YAItE,sBAAsB,gBAAmB"}
1
+ {"version":3,"file":"useChatRuntime.d.ts","names":[],"sources":["../../src/runtime/useChatRuntime.ts"],"mappings":";;;;;YAaY,sBAAsB,mBAAmB,YAAY,aAC/D,kBAAkB;EAChB,QAAQ;EACR,qBAAqB;;qBAoBZ,iBAAkB,mBAAmB,YAAY,aAAW,OAAA,qBAAA,YAItE,sBAAsB,gBAAmB"}
@@ -5,12 +5,13 @@ import { AssistantRuntime, ExternalStoreSharedOptions } from "@assistant-ui/core
5
5
  import { MessageRepository } from "@assistant-ui/core/internal";
6
6
  import { Chat, UIMessage as UIMessage$1 } from "@ai-sdk/react";
7
7
  //#region src/runtime/useChatThread.d.ts
8
- type ChatThreadOptions<UI_MESSAGE extends UIMessage$1 = UIMessage$1> = ChatInit<UI_MESSAGE> & ExternalStoreSharedOptions & {
8
+ export type ChatThreadOptions<UI_MESSAGE extends UIMessage$1 = UIMessage$1> = ChatInit<UI_MESSAGE> & ExternalStoreSharedOptions & {
9
9
  throttle?: number | undefined;
10
10
  adapters?: AISDKRuntimeAdapter["adapters"] | undefined;
11
11
  toCreateMessage?: CustomToCreateMessageFunction;
12
12
  onResume?: AISDKRuntimeAdapter["onResume"];
13
13
  onResumeToolCall?: AISDKRuntimeAdapter["onResumeToolCall"];
14
+ onRespondToToolApproval?: AISDKRuntimeAdapter["onRespondToToolApproval"];
14
15
  /**
15
16
  * Called when an automatic resumable stream reconnect fails. Use this to
16
17
  * surface a toast, report telemetry, or mark the thread as needing a
@@ -22,7 +23,7 @@ type ChatThreadOptions<UI_MESSAGE extends UIMessage$1 = UIMessage$1> = ChatInit<
22
23
  messageRepository?: AISDKRuntimeAdapter<UI_MESSAGE>["messageRepository"];
23
24
  unstable_onBranchChange?: AISDKRuntimeAdapter["unstable_onBranchChange"];
24
25
  };
25
- type ChatThreadEnvironment<UI_MESSAGE extends UIMessage$1 = UIMessage$1> = {
26
+ export type ChatThreadEnvironment<UI_MESSAGE extends UIMessage$1 = UIMessage$1> = {
26
27
  id: string;
27
28
  isMainThread: boolean;
28
29
  getThreadListItem: () => InitializableThreadListItem | undefined;
@@ -45,7 +46,7 @@ type ChatThreadEnvironment<UI_MESSAGE extends UIMessage$1 = UIMessage$1> = {
45
46
  * remainder the AI SDK consumes, so external `Chat` construction forwards the
46
47
  * same fields `useChat` would.
47
48
  */
48
- declare const splitChatThreadOptions: <UI_MESSAGE extends UIMessage$1>(options: ChatThreadOptions<UI_MESSAGE> | undefined) => {
49
+ export declare const splitChatThreadOptions: <UI_MESSAGE extends UIMessage$1>(options: ChatThreadOptions<UI_MESSAGE> | undefined) => {
49
50
  adapters: ({
50
51
  attachments?: import("@assistant-ui/core").AttachmentAdapter | undefined;
51
52
  speech?: import("@assistant-ui/core").SpeechSynthesisAdapter | undefined;
@@ -65,6 +66,11 @@ declare const splitChatThreadOptions: <UI_MESSAGE extends UIMessage$1>(options:
65
66
  toolCallId: string;
66
67
  payload: unknown;
67
68
  }) => void) | undefined;
69
+ onRespondToToolApproval: ((response: import("@assistant-ui/core").RespondToToolApprovalOptions, context: {
70
+ toolCallId: string;
71
+ toolName: string;
72
+ respondViaAISDK: () => Promise<void>;
73
+ }) => Promise<void> | void) | undefined;
68
74
  onResumeError: ((error: unknown) => void) | undefined;
69
75
  joinStrategy: import("@assistant-ui/core/store").JoinStrategy | undefined;
70
76
  messageRepository: import("@assistant-ui/core").MessageFormatRepository<UI_MESSAGE> | undefined;
@@ -84,7 +90,15 @@ declare const splitChatThreadOptions: <UI_MESSAGE extends UIMessage$1>(options:
84
90
  }) => boolean | PromiseLike<boolean>;
85
91
  };
86
92
  };
87
- declare const useChatThread: <UI_MESSAGE extends UIMessage$1 = UIMessage$1>(options: ChatThreadOptions<UI_MESSAGE> | undefined, env: ChatThreadEnvironment<UI_MESSAGE>) => AssistantRuntime;
93
+ type ChatCallbacks<UI_MESSAGE extends UIMessage$1> = Pick<ChatInit<UI_MESSAGE>, "onToolCall" | "onData" | "onFinish" | "onError" | "sendAutomaticallyWhen">;
94
+ /**
95
+ * Constructs a `Chat` whose callbacks read the latest options through
96
+ * `callbacksRef`, the forwarding `useChat` applies only to a chat it
97
+ * constructs itself.
98
+ */
99
+ export declare const createChat: <UI_MESSAGE extends UIMessage$1>(init: ChatInit<UI_MESSAGE>, callbacksRef: {
100
+ readonly current: ChatCallbacks<UI_MESSAGE> | undefined;
101
+ }) => Chat<UI_MESSAGE>;
102
+ export declare const useChatThread: <UI_MESSAGE extends UIMessage$1 = UIMessage$1>(options: ChatThreadOptions<UI_MESSAGE> | undefined, env: ChatThreadEnvironment<UI_MESSAGE>) => AssistantRuntime;
88
103
  //#endregion
89
- export { ChatThreadEnvironment, ChatThreadOptions, splitChatThreadOptions, useChatThread };
90
104
  //# sourceMappingURL=useChatThread.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useChatThread.d.ts","names":[],"sources":["../../src/runtime/useChatThread.ts"],"mappings":";;;;;;;KAgCY,kBAAkB,mBAAmB,cAAY,eAC3D,SAAS,cACP;EACE;EACA,WAAW;EACX,kBAAkB;EAClB,WAAW;EACX,mBAAmB;;;;;;;EAOnB,kBAAkB;EAClB,eAAe;EACf,oBAAoB,oBAAoB;EACxC,0BAA0B;;KAGpB,sBAAsB,mBAAmB,cAAY;EAC/D;EACA;EACA,yBAAyB;EACzB;;;;;;EAMA,OAAO,KAAK;;;;;;EAMZ,4BAA4B;;;;;;;cA4DjB,yBAA0B,mBAAmB,aACxD,SAAS,kBAAkB;;;;;;;;;;;;;;;;;;;;EAnFE,iBAAA;;;;;;;;;;;;;;;;;;;cA0HlB,gBAAiB,mBAAmB,cAAY,aAC3D,SAAS,kBAAkB,yBAC3B,KAAK,sBAAsB,gBAC1B"}
1
+ {"version":3,"file":"useChatThread.d.ts","names":[],"sources":["../../src/runtime/useChatThread.ts"],"mappings":";;;;;;;YAiCY,kBAAkB,mBAAmB,cAAY,eAC3D,SAAS,cACP;EACE;EACA,WAAW;EACX,kBAAkB;EAClB,WAAW;EACX,mBAAmB;EACnB,0BAA0B;;;;;;;EAO1B,kBAAkB;EAClB,eAAe;EACf,oBAAoB,oBAAoB;EACxC,0BAA0B;;YAGpB,sBAAsB,mBAAmB,cAAY;EAC/D;EACA;EACA,yBAAyB;EACzB;;;;;;EAMA,OAAO,KAAK;;;;;;EAMZ,4BAA4B;;;;;;;qBA4DjB,yBAA0B,mBAAmB,aACxD,SAAS,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;EAnFE,iBAAA;;;;;;;;;;;;;;;;;;;KA4H1B,cAAc,mBAAmB,eAAa,KACjD,SAAS;;;;;;qBASE,aAAc,mBAAmB,aAC5C,MAAM,SAAS,aACf;WAAyB,SAAS,cAAc;MAC/C,KAAK;qBAWK,gBAAiB,mBAAmB,cAAY,aAC3D,SAAS,kBAAkB,yBAC3B,KAAK,sBAAsB,gBAC1B"}