@assistant-ui/ai-sdk 0.0.5 → 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 (92) hide show
  1. package/dist/adapters/aiSDKFormatAdapter.d.ts +2 -8
  2. package/dist/adapters/aiSDKFormatAdapter.js +1 -25
  3. package/dist/adapters/vercelAttachmentAdapter.d.ts +1 -2
  4. package/dist/adapters/vercelAttachmentAdapter.d.ts.map +1 -1
  5. package/dist/aiSDKExtras.d.ts +2 -3
  6. package/dist/aiSDKExtras.d.ts.map +1 -1
  7. package/dist/converters/convertMessage.d.ts +5 -4
  8. package/dist/converters/convertMessage.d.ts.map +1 -1
  9. package/dist/converters/convertMessage.js +40 -3
  10. package/dist/converters/convertMessage.js.map +1 -1
  11. package/dist/converters/modelContentEnvelope.d.ts +4 -5
  12. package/dist/converters/modelContentEnvelope.d.ts.map +1 -1
  13. package/dist/converters/toCreateMessage.d.ts +1 -2
  14. package/dist/converters/toCreateMessage.d.ts.map +1 -1
  15. package/dist/converters/toolOutputConversion.d.ts +2 -3
  16. package/dist/converters/toolOutputConversion.d.ts.map +1 -1
  17. package/dist/hooks.d.ts +2 -3
  18. package/dist/hooks.d.ts.map +1 -1
  19. package/dist/model-context/injectInteractableContext.d.ts +1 -2
  20. package/dist/model-context/injectInteractableContext.d.ts.map +1 -1
  21. package/dist/model-context/injectQuoteContext.d.ts +1 -2
  22. package/dist/model-context/injectQuoteContext.d.ts.map +1 -1
  23. package/dist/runtime/AISDKChat.d.ts +2 -3
  24. package/dist/runtime/AISDKChat.d.ts.map +1 -1
  25. package/dist/runtime/AISDKThreads.d.ts +2 -3
  26. package/dist/runtime/AISDKThreads.d.ts.map +1 -1
  27. package/dist/runtime/AISDKThreads.js +87 -68
  28. package/dist/runtime/AISDKThreads.js.map +1 -1
  29. package/dist/runtime/sdkIdentity.d.ts +5 -0
  30. package/dist/runtime/sdkIdentity.d.ts.map +1 -0
  31. package/dist/runtime/sdkIdentity.js +9 -0
  32. package/dist/runtime/sdkIdentity.js.map +1 -0
  33. package/dist/runtime/useAISDKRuntime.d.ts +17 -5
  34. package/dist/runtime/useAISDKRuntime.d.ts.map +1 -1
  35. package/dist/runtime/useAISDKRuntime.js +103 -38
  36. package/dist/runtime/useAISDKRuntime.js.map +1 -1
  37. package/dist/runtime/useChatRuntime.d.ts +2 -3
  38. package/dist/runtime/useChatRuntime.d.ts.map +1 -1
  39. package/dist/runtime/useChatRuntime.js +5 -1
  40. package/dist/runtime/useChatRuntime.js.map +1 -1
  41. package/dist/runtime/useChatThread.d.ts +19 -5
  42. package/dist/runtime/useChatThread.d.ts.map +1 -1
  43. package/dist/runtime/useChatThread.js +31 -10
  44. package/dist/runtime/useChatThread.js.map +1 -1
  45. package/dist/runtime/useExternalHistory.d.ts +2 -3
  46. package/dist/runtime/useExternalHistory.d.ts.map +1 -1
  47. package/dist/runtime/useExternalHistory.js +31 -20
  48. package/dist/runtime/useExternalHistory.js.map +1 -1
  49. package/dist/runtime/useResourceCleanup.d.ts +1 -2
  50. package/dist/runtime/useResourceCleanup.d.ts.map +1 -1
  51. package/dist/runtime/useStreamingTiming.d.ts +2 -3
  52. package/dist/runtime/useStreamingTiming.d.ts.map +1 -1
  53. package/dist/tools/frontendTools.d.ts +3 -4
  54. package/dist/tools/frontendTools.d.ts.map +1 -1
  55. package/dist/tools/generativeTools.d.ts +5 -6
  56. package/dist/tools/generativeTools.d.ts.map +1 -1
  57. package/dist/tools/mcp-stdio.unsupported.d.ts +1 -2
  58. package/dist/tools/mcp-stdio.unsupported.d.ts.map +1 -1
  59. package/dist/transport/AssistantChatTransport.d.ts +3 -4
  60. package/dist/transport/AssistantChatTransport.d.ts.map +1 -1
  61. package/dist/transport/resumable.d.ts +4 -5
  62. package/dist/transport/resumable.d.ts.map +1 -1
  63. package/dist/usage.d.ts +4 -5
  64. package/dist/usage.d.ts.map +1 -1
  65. package/dist/utils/getVercelAIMessages.d.ts +1 -2
  66. package/dist/utils/getVercelAIMessages.d.ts.map +1 -1
  67. package/dist/utils/sliceMessagesUntil.d.ts +1 -2
  68. package/dist/utils/sliceMessagesUntil.d.ts.map +1 -1
  69. package/package.json +15 -14
  70. package/src/adapters/aiSDKFormatAdapter.ts +4 -41
  71. package/src/converters/convertMessage.test.ts +152 -0
  72. package/src/converters/convertMessage.ts +95 -5
  73. package/src/runtime/AISDKChat.test.ts +4 -5
  74. package/src/runtime/AISDKThreads.cloud.test.ts +12 -3
  75. package/src/runtime/AISDKThreads.test.ts +140 -13
  76. package/src/runtime/AISDKThreads.ts +23 -4
  77. package/src/runtime/sdkIdentity.ts +9 -0
  78. package/src/runtime/useAISDKRuntime.approval.integration.test.tsx +287 -0
  79. package/src/runtime/useAISDKRuntime.approval.test.tsx +257 -1
  80. package/src/runtime/useAISDKRuntime.test.ts +46 -4
  81. package/src/runtime/useAISDKRuntime.ts +164 -24
  82. package/src/runtime/useAISDKRuntime.voice.test.tsx +270 -0
  83. package/src/runtime/useChatRuntime.test.ts +72 -5
  84. package/src/runtime/useChatRuntime.ts +2 -1
  85. package/src/runtime/useChatThread.test.ts +74 -0
  86. package/src/runtime/useChatThread.ts +45 -6
  87. package/src/runtime/useExternalHistory.test.ts +75 -0
  88. package/src/runtime/useExternalHistory.ts +28 -11
  89. package/src/tools/generativeTools.test.ts +7 -1
  90. package/src/transport/AssistantChatTransport.test.ts +1 -9
  91. package/dist/adapters/aiSDKFormatAdapter.d.ts.map +0 -1
  92. package/dist/adapters/aiSDKFormatAdapter.js.map +0 -1
@@ -1,29 +1,31 @@
1
1
  "use client";
2
2
  import { AssistantChatTransport } from "../transport/AssistantChatTransport.js";
3
3
  import { useResourceCleanup } from "./useResourceCleanup.js";
4
- import { splitChatThreadOptions, useChatThread } from "./useChatThread.js";
4
+ import { createChat, splitChatThreadOptions, useChatThread } from "./useChatThread.js";
5
+ import { AI_SDK_SDK } from "./sdkIdentity.js";
5
6
  import { useCloudThreadListAdapter } from "@assistant-ui/core/react";
6
7
  import { c } from "@assistant-ui/tap/react-shim/compiler-runtime";
7
8
  import { useEffect, useState } from "@assistant-ui/tap/react-shim";
8
9
  import { MessageRepository } from "@assistant-ui/core/internal";
9
10
  import { useAui } from "@assistant-ui/store";
10
- import { Chat } from "@ai-sdk/react";
11
11
  import { resource, useResource, withKey } from "@assistant-ui/tap";
12
12
  import { InMemoryThreadList, RemoteThreadList, inMemoryThreadListTransformScopes } from "@assistant-ui/core/store";
13
13
  import { attachTransformScopes, useAssistantClientRef, useAssistantScopeEffect } from "@assistant-ui/store/client";
14
14
  import { ThreadClient } from "@assistant-ui/core/store/internal";
15
15
  //#region src/runtime/AISDKThreads.ts
16
16
  const createChatEntry = (threadId, options) => {
17
+ const optionsRef = { current: options };
17
18
  const { chatInit } = splitChatThreadOptions(options);
18
19
  const transport = typeof options?.transport === "function" ? options.transport() : options?.transport === void 0 ? new AssistantChatTransport() : options.transport instanceof AssistantChatTransport ? options.transport.__internal_clone() : options.transport;
19
20
  return {
20
- chat: new Chat({
21
+ chat: createChat({
21
22
  ...chatInit,
22
23
  id: threadId,
23
24
  transport
24
- }),
25
+ }, optionsRef),
25
26
  transport,
26
- repository: new MessageRepository()
27
+ repository: new MessageRepository(),
28
+ optionsRef
27
29
  };
28
30
  };
29
31
  const getOrCreateChatEntry = (threadId, options, chats) => {
@@ -34,7 +36,7 @@ const getOrCreateChatEntry = (threadId, options, chats) => {
34
36
  return created;
35
37
  };
36
38
  const useAISDKChatThread = (t0) => {
37
- const $ = c(35);
39
+ const $ = c(39);
38
40
  const { threadId, options, chats, cloud } = t0;
39
41
  let t1;
40
42
  if ($[0] !== cloud || $[1] !== options || $[2] !== threadId) {
@@ -54,95 +56,106 @@ const useAISDKChatThread = (t0) => {
54
56
  $[7] = threadId;
55
57
  $[8] = t2;
56
58
  } else t2 = $[8];
57
- const { chat, transport, repository } = t2;
59
+ const { chat, transport, repository, optionsRef } = t2;
58
60
  let t3;
59
- let t4;
60
- if ($[9] !== chat || $[10] !== cloud) {
61
+ if ($[9] !== cloud || $[10] !== options || $[11] !== optionsRef) {
61
62
  t3 = () => {
63
+ if (cloud) optionsRef.current = options;
64
+ };
65
+ $[9] = cloud;
66
+ $[10] = options;
67
+ $[11] = optionsRef;
68
+ $[12] = t3;
69
+ } else t3 = $[12];
70
+ useEffect(t3);
71
+ let t4;
72
+ let t5;
73
+ if ($[13] !== chat || $[14] !== cloud) {
74
+ t4 = () => {
62
75
  if (!cloud) return;
63
76
  return () => {
64
77
  chat.stop().catch(_temp);
65
78
  };
66
79
  };
67
- t4 = [chat, cloud];
68
- $[9] = chat;
69
- $[10] = cloud;
70
- $[11] = t3;
71
- $[12] = t4;
80
+ t5 = [chat, cloud];
81
+ $[13] = chat;
82
+ $[14] = cloud;
83
+ $[15] = t4;
84
+ $[16] = t5;
72
85
  } else {
73
- t3 = $[11];
74
- t4 = $[12];
86
+ t4 = $[15];
87
+ t5 = $[16];
75
88
  }
76
- useEffect(t3, t4);
89
+ useEffect(t4, t5);
77
90
  const aui = useAui();
78
- let t5;
79
- if ($[13] !== threadId) {
80
- t5 = { initialize: async () => ({
91
+ let t6;
92
+ if ($[17] !== threadId) {
93
+ t6 = { initialize: async () => ({
81
94
  remoteId: threadId,
82
95
  externalId: void 0
83
96
  }) };
84
- $[13] = threadId;
85
- $[14] = t5;
86
- } else t5 = $[14];
87
- const fallbackItem = t5;
88
- let t6;
89
- if ($[15] !== options || $[16] !== transport) {
90
- t6 = {
97
+ $[17] = threadId;
98
+ $[18] = t6;
99
+ } else t6 = $[18];
100
+ const fallbackItem = t6;
101
+ let t7;
102
+ if ($[19] !== options || $[20] !== transport) {
103
+ t7 = {
91
104
  ...options,
92
105
  transport
93
106
  };
94
- $[15] = options;
95
- $[16] = transport;
96
- $[17] = t6;
97
- } else t6 = $[17];
98
- let t7;
99
- if ($[18] !== aui || $[19] !== cloud || $[20] !== fallbackItem) {
100
- t7 = () => cloud ? aui.threadListItem.source ? aui.threadListItem : void 0 : fallbackItem;
101
- $[18] = aui;
102
- $[19] = cloud;
103
- $[20] = fallbackItem;
107
+ $[19] = options;
108
+ $[20] = transport;
104
109
  $[21] = t7;
105
110
  } else t7 = $[21];
106
111
  let t8;
107
- if ($[22] !== chat || $[23] !== cloud || $[24] !== repository || $[25] !== t7 || $[26] !== threadId) {
108
- t8 = {
112
+ if ($[22] !== aui || $[23] !== cloud || $[24] !== fallbackItem) {
113
+ t8 = () => cloud ? aui.threadListItem.source ? aui.threadListItem : void 0 : fallbackItem;
114
+ $[22] = aui;
115
+ $[23] = cloud;
116
+ $[24] = fallbackItem;
117
+ $[25] = t8;
118
+ } else t8 = $[25];
119
+ let t9;
120
+ if ($[26] !== chat || $[27] !== cloud || $[28] !== repository || $[29] !== t8 || $[30] !== threadId) {
121
+ t9 = {
109
122
  id: threadId,
110
123
  isMainThread: true,
111
- getThreadListItem: t7,
124
+ getThreadListItem: t8,
112
125
  chat,
113
126
  messageRepositoryInstance: repository,
114
127
  stopOnClientDestroy: cloud
115
128
  };
116
- $[22] = chat;
117
- $[23] = cloud;
118
- $[24] = repository;
119
- $[25] = t7;
120
- $[26] = threadId;
121
- $[27] = t8;
122
- } else t8 = $[27];
123
- const runtime = useChatThread(t6, t8);
129
+ $[26] = chat;
130
+ $[27] = cloud;
131
+ $[28] = repository;
132
+ $[29] = t8;
133
+ $[30] = threadId;
134
+ $[31] = t9;
135
+ } else t9 = $[31];
136
+ const runtime = useChatThread(t7, t9);
124
137
  const clientRef = useAssistantClientRef();
125
- let t9;
126
- if ($[28] !== clientRef || $[29] !== runtime) {
127
- t9 = () => runtime.registerModelContextProvider(clientRef.current.modelContext());
128
- $[28] = clientRef;
129
- $[29] = runtime;
130
- $[30] = t9;
131
- } else t9 = $[30];
132
138
  let t10;
133
- if ($[31] !== runtime) {
134
- t10 = [runtime];
135
- $[31] = runtime;
136
- $[32] = t10;
137
- } else t10 = $[32];
138
- useAssistantScopeEffect("modelContext", t9, t10);
139
+ if ($[32] !== clientRef || $[33] !== runtime) {
140
+ t10 = () => runtime.registerModelContextProvider(clientRef.current.modelContext());
141
+ $[32] = clientRef;
142
+ $[33] = runtime;
143
+ $[34] = t10;
144
+ } else t10 = $[34];
139
145
  let t11;
140
- if ($[33] !== runtime.thread) {
141
- t11 = ThreadClient({ runtime: runtime.thread });
142
- $[33] = runtime.thread;
143
- $[34] = t11;
144
- } else t11 = $[34];
145
- return useResource(t11);
146
+ if ($[35] !== runtime) {
147
+ t11 = [runtime];
148
+ $[35] = runtime;
149
+ $[36] = t11;
150
+ } else t11 = $[36];
151
+ useAssistantScopeEffect("modelContext", t10, t11);
152
+ let t12;
153
+ if ($[37] !== runtime.thread) {
154
+ t12 = ThreadClient({ runtime: runtime.thread });
155
+ $[37] = runtime.thread;
156
+ $[38] = t12;
157
+ } else t12 = $[38];
158
+ return useResource(t12);
146
159
  };
147
160
  const AISDKChatThread = resource(useAISDKChatThread);
148
161
  const useAISDKThreads = (options) => {
@@ -150,6 +163,9 @@ const useAISDKThreads = (options) => {
150
163
  const { cloud, threadId, onThreadIdChange, ...threadOptions } = options ?? {};
151
164
  const [chats] = useState(_temp2);
152
165
  const bindCloud = cloud !== void 0;
166
+ useEffect(() => {
167
+ for (const { optionsRef } of chats.values()) optionsRef.current = threadOptions;
168
+ });
153
169
  let t0;
154
170
  if ($[0] !== chats) {
155
171
  t0 = () => {
@@ -159,7 +175,10 @@ const useAISDKThreads = (options) => {
159
175
  $[1] = t0;
160
176
  } else t0 = $[1];
161
177
  useResourceCleanup(true, t0);
162
- const cloudAdapter = useCloudThreadListAdapter({ cloud });
178
+ const cloudAdapter = useCloudThreadListAdapter({
179
+ cloud,
180
+ sdk: AI_SDK_SDK
181
+ });
163
182
  const thread = (id) => {
164
183
  const element = AISDKChatThread({
165
184
  threadId: id,
@@ -1 +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","MessageRepository","useResourceCleanup","AISDKThreadsOptions","Omit","UI_MESSAGE","transport","cloud","threadId","onThreadIdChange","AISDKThreadChatOptions","ChatEntry","chat","repository","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","messageRepositoryInstance","stopOnClientDestroy","runtime","clientRef","t9","registerModelContextProvider","current","modelContext","t10","t11","thread","AISDKChatThread","useAISDKThreads","threadOptions","_temp2","bindCloud","values","_temp3","cloudAdapter","element","adapter","backgroundThreads","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 { MessageRepository } from \"@assistant-ui/core/internal\";\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. Every visited\n * cloud thread stays mounted, so an in-flight run continues after a\n * switch and stops on delete; per-thread history loads once per thread.\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 repository: MessageRepository;\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 repository: new MessageRepository(),\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, repository } =\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 messageRepositoryInstance: repository,\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 backgroundThreads: true,\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; only the visible thread is mounted, and a\n * switched-away chat keeps streaming into its stored state until it settles\n * or the thread is deleted. With `cloud`, the list is a\n * `RemoteThreadList` with `backgroundThreads`: every visited thread stays\n * mounted with its own history, a run continues after a switch and stops on\n * delete, and a freshly created thread titles itself. Model context is\n * registered on every mounted thread.\n */\nexport const AISDKThreads = resource(useAISDKThreads);\n\nattachTransformScopes(useAISDKThreads, inMemoryThreadListTransformScopes);\n"],"mappings":"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"}
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","createChat","splitChatThreadOptions","useChatThread","ChatThreadOptions","MessageRepository","useResourceCleanup","AI_SDK_SDK","AISDKThreadsOptions","Omit","UI_MESSAGE","transport","cloud","threadId","onThreadIdChange","AISDKThreadChatOptions","ChatOptionsRef","current","ChatEntry","chat","repository","optionsRef","createChatEntry","options","chatInit","undefined","__internal_clone","id","getOrCreateChatEntry","chats","Map","existing","get","created","set","useAISDKChatThread","t0","$","t1","owned","t2","t3","t4","t5","stop","catch","_temp","aui","t6","initialize","remoteId","externalId","fallbackItem","t7","t8","threadListItem","source","t9","isMainThread","getThreadListItem","messageRepositoryInstance","stopOnClientDestroy","runtime","clientRef","t10","registerModelContextProvider","modelContext","t11","t12","thread","AISDKChatThread","useAISDKThreads","threadOptions","_temp2","bindCloud","values","_temp3","cloudAdapter","sdk","element","adapter","backgroundThreads","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 type { Chat, 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 createChat,\n splitChatThreadOptions,\n useChatThread,\n type ChatThreadOptions,\n} from \"./useChatThread\";\nimport { MessageRepository } from \"@assistant-ui/core/internal\";\nimport { useResourceCleanup } from \"./useResourceCleanup\";\nimport { AI_SDK_SDK } from \"./sdkIdentity\";\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. Every visited\n * cloud thread stays mounted, so an in-flight run continues after a\n * switch and stops on delete; per-thread history loads once per thread.\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 ChatOptionsRef<UI_MESSAGE extends UIMessage> = {\n current: AISDKThreadChatOptions<UI_MESSAGE> | undefined;\n};\n\ntype ChatEntry<UI_MESSAGE extends UIMessage> = {\n chat: Chat<UI_MESSAGE>;\n transport: ChatTransport<UI_MESSAGE>;\n repository: MessageRepository;\n optionsRef: ChatOptionsRef<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 optionsRef: ChatOptionsRef<UI_MESSAGE> = { current: options };\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: createChat({ ...chatInit, id: threadId, transport }, optionsRef),\n transport,\n repository: new MessageRepository(),\n optionsRef,\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, repository, optionsRef } =\n owned ?? getOrCreateChatEntry(threadId, options, chats);\n\n useEffect(() => {\n if (cloud) optionsRef.current = options;\n });\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 messageRepositoryInstance: repository,\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 useEffect(() => {\n for (const { optionsRef } of chats.values()) {\n optionsRef.current = threadOptions;\n }\n });\n\n useResourceCleanup(true, () => {\n for (const { chat } of chats.values()) {\n void chat.stop().catch(() => {});\n }\n });\n\n const cloudAdapter = useCloudThreadListAdapter({ cloud, sdk: AI_SDK_SDK });\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 backgroundThreads: true,\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; only the visible thread is mounted, and a\n * switched-away chat keeps streaming into its stored state until it settles\n * or the thread is deleted. With `cloud`, the list is a\n * `RemoteThreadList` with `backgroundThreads`: every visited thread stays\n * mounted with its own history, a run continues after a switch and stops on\n * delete, and a freshly created thread titles itself. Model context is\n * registered on every mounted thread.\n */\nexport const AISDKThreads = resource(useAISDKThreads);\n\nattachTransformScopes(useAISDKThreads, inMemoryThreadListTransformScopes);\n"],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import { SdkIdentity } from "assistant-cloud";
2
+ //#region src/runtime/sdkIdentity.d.ts
3
+ export declare const AI_SDK_SDK: SdkIdentity;
4
+ //#endregion
5
+ //# sourceMappingURL=sdkIdentity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sdkIdentity.d.ts","names":[],"sources":["../../src/runtime/sdkIdentity.ts"],"mappings":";;qBAEa,YAAY"}
@@ -0,0 +1,9 @@
1
+ //#region src/runtime/sdkIdentity.ts
2
+ const AI_SDK_SDK = {
3
+ name: "@assistant-ui/ai-sdk",
4
+ version: "0.0.7"
5
+ };
6
+ //#endregion
7
+ export { AI_SDK_SDK };
8
+
9
+ //# sourceMappingURL=sdkIdentity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sdkIdentity.js","names":["SdkIdentity","AI_SDK_SDK","name","version","__AUI_PACKAGE_VERSION__"],"sources":["../../src/runtime/sdkIdentity.ts"],"sourcesContent":["import type { SdkIdentity } from \"assistant-cloud\";\n\nexport const AI_SDK_SDK: SdkIdentity = {\n name: \"@assistant-ui/ai-sdk\",\n version:\n typeof __AUI_PACKAGE_VERSION__ === \"string\"\n ? __AUI_PACKAGE_VERSION__\n : \"0.0.0\",\n};\n"],"mappings":";AAEA,MAAaC,aAA0B;CACrCC,MAAM;CACNC,SAAAA;AAIF"}
@@ -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":";;;;;KAkEY,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;;cAoFjB,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,12 +141,22 @@ 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();
145
+ const toChatError = (error) => {
146
+ const code = error.code;
147
+ return {
148
+ code: typeof code === "string" ? code : error.name !== "Error" ? error.name : "unknown",
149
+ message: error.message
150
+ };
151
+ };
132
152
  const useAISDKRuntime = (chatHelpers, adapter = {}) => {
133
- 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;
134
154
  const suggestionAdapter = adapters?.suggestion;
135
155
  const contextAdapters = useRuntimeAdapters();
136
156
  const [toolStatuses, setToolStatuses] = useState({});
137
157
  const [cancelledMessages, setCancelledMessages] = useState(null);
158
+ const [toolApprovalResponses, setToolApprovalResponses] = useState(NO_TOOL_APPROVAL_RESPONSES);
159
+ const hostApprovalIdsRef = useRef(/* @__PURE__ */ new Set());
138
160
  const toolArgsKeyOrderCacheRef = useRef(/* @__PURE__ */ new Map());
139
161
  const toolLastInputCacheRef = useRef(/* @__PURE__ */ new Map());
140
162
  const mcpAppMetadataCacheRef = useRef(/* @__PURE__ */ new Map());
@@ -147,6 +169,11 @@ const useAISDKRuntime = (chatHelpers, adapter = {}) => {
147
169
  const lastMessage = chatHelpers.messages.at(-1);
148
170
  const optimisticMessageId = isRunning && lastMessage?.role === "assistant" ? lastMessage.id : void 0;
149
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]);
150
177
  const retractCancellation = useCallback((chatId, messageId) => {
151
178
  setCancelledMessages((prev) => {
152
179
  if (prev?.chatId !== chatId || !prev.ids.has(messageId)) return prev;
@@ -180,27 +207,31 @@ const useAISDKRuntime = (chatHelpers, adapter = {}) => {
180
207
  toolArgsKeyOrderCache: toolArgsKeyOrderCacheRef.current,
181
208
  toolLastInputCache: toolLastInputCacheRef.current,
182
209
  mcpAppMetadataCache: mcpAppMetadataCacheRef.current,
210
+ supportsRichToolApprovalResponses,
183
211
  ...optimisticMessageId && { optimisticMessageId },
184
- ...chatHelpers.error && { error: chatHelpers.error.message },
185
- ...cancelledMessageIds.size > 0 && { cancelledMessageIds }
212
+ ...chatHelpers.error && { error: toChatError(chatHelpers.error) },
213
+ ...cancelledMessageIds.size > 0 && { cancelledMessageIds },
214
+ ...toolApprovalResponses.size > 0 && { toolApprovalResponses }
186
215
  }), [
187
216
  toolStatuses,
188
217
  messageTiming,
189
218
  optimisticMessageId,
190
219
  chatHelpers.error,
191
- cancelledMessageIds
220
+ cancelledMessageIds,
221
+ toolApprovalResponses,
222
+ supportsRichToolApprovalResponses
192
223
  ])
193
224
  });
194
225
  const exportedMessageRepository = useMemo(() => {
195
226
  if (!messageRepository) return void 0;
196
- const converted = toExportedMessageRepository(AISDKMessageConverter.toThreadMessages, messageRepository);
227
+ const converted = toExportedMessageRepository(toThreadMessages, messageRepository);
197
228
  return converted.messages.length > 0 ? converted : void 0;
198
- }, [messageRepository]);
229
+ }, [messageRepository, toThreadMessages]);
199
230
  const generatedSuggestions = useGeneratedSuggestions(suggestionAdapter, messages, isRunning);
200
231
  const [runtimeRef] = useState(() => ({ get current() {
201
232
  return runtime;
202
233
  } }));
203
- 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) => {
204
235
  chatHelpers.setMessages(messages_0);
205
236
  });
206
237
  const { id: chatId_0, messages: chatMessages, status: chatStatus, error } = chatHelpers;
@@ -237,6 +268,44 @@ const useAISDKRuntime = (chatHelpers, adapter = {}) => {
237
268
  }];
238
269
  });
239
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
+ };
240
309
  const hasSeededRepositoryRef = useRef(false);
241
310
  const shouldFeedRepository = exportedMessageRepository != null && !hasSeededRepositoryRef.current && messages.length === 0;
242
311
  const runtime = useExternalStoreRuntime({
@@ -246,6 +315,7 @@ const useAISDKRuntime = (chatHelpers, adapter = {}) => {
246
315
  setToolStatuses,
247
316
  setMessages: (messages_2) => chatHelpers.setMessages(messages_2.map(getVercelAIMessages).filter(Boolean).flat()),
248
317
  onImport: (messages_3) => chatHelpers.setMessages(messages_3.map(getVercelAIMessages).filter(Boolean).flat()),
318
+ onVoiceTranscript: (message_0) => chatHelpers.setMessages((current) => [...current, toVoiceTranscriptUIMessage(message_0)]),
249
319
  onExportExternalState: () => {
250
320
  const exported = runtimeRef.current.thread.export();
251
321
  const expandedMessages = [];
@@ -267,16 +337,16 @@ const useAISDKRuntime = (chatHelpers, adapter = {}) => {
267
337
  return result;
268
338
  },
269
339
  onLoadExternalState: (repo) => {
270
- const exportedRepo = toExportedMessageRepository(AISDKMessageConverter.toThreadMessages, repo);
340
+ const exportedRepo = toExportedMessageRepository(toThreadMessages, repo);
271
341
  runtimeRef.current.thread.import(exportedRepo);
272
342
  },
273
343
  onCancel: async () => {
274
- const message = chatHelpers.messages.at(-1);
275
- 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;
276
346
  if (cancelledId) {
277
347
  const liveIds = new Set(chatHelpers.messages.map((m) => m.id));
278
- setCancelledMessages((prev_0) => {
279
- 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)) : [];
280
350
  return {
281
351
  chatId: chatHelpers.id,
282
352
  ids: /* @__PURE__ */ new Set([...kept, cancelledId])
@@ -285,40 +355,40 @@ const useAISDKRuntime = (chatHelpers, adapter = {}) => {
285
355
  }
286
356
  try {
287
357
  await chatHelpers.stop();
288
- } catch (error_0) {
289
- if (!(error_0 instanceof Error && error_0.name === "AbortError")) {
358
+ } catch (error_1) {
359
+ if (!(error_1 instanceof Error && error_1.name === "AbortError")) {
290
360
  if (cancelledId) retractCancellation(chatHelpers.id, cancelledId);
291
- throw error_0;
361
+ throw error_1;
292
362
  }
293
363
  }
294
364
  },
295
- onNew: async (message_0) => {
296
- const createMessage = (customToCreateMessage ?? toCreateMessage)(message_0);
297
- if (!(message_0.startRun ?? message_0.role === "user")) {
298
- 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)]);
299
369
  return;
300
370
  }
301
- lastRunConfigRef.current = message_0.runConfig;
371
+ lastRunConfigRef.current = message_2.runConfig;
302
372
  await completePendingToolCalls();
303
- await chatHelpers.sendMessage(createMessage, { metadata: message_0.runConfig });
373
+ await chatHelpers.sendMessage(createMessage, { metadata: message_2.runConfig });
304
374
  },
305
- onEdit: async (message_1) => {
306
- const createMessage_0 = (customToCreateMessage ?? toCreateMessage)(message_1);
307
- if (!(message_1.startRun ?? message_1.role === "user")) {
308
- 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)]);
309
379
  return;
310
380
  }
311
- lastRunConfigRef.current = message_1.runConfig;
312
- chatHelpers.setMessages((current_1) => sliceMessagesUntil(current_1, message_1.parentId));
313
- 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 });
314
384
  },
315
385
  onDelete: async (messageId_0) => {
316
386
  const threadMessages = runtimeRef.current.thread.getState().messages;
317
- const messageIndex = threadMessages.findIndex((message_2) => message_2.id === messageId_0);
387
+ const messageIndex = threadMessages.findIndex((message_4) => message_4.id === messageId_0);
318
388
  if (messageIndex === -1) return;
319
389
  await deleteHistoryMessage(messageId_0);
320
- const deleteIds = new Set(getExternalStoreMessages(threadMessages[messageIndex]).map((message_3) => message_3.id));
321
- 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)));
322
392
  },
323
393
  onReload: async (parentId_0, config) => {
324
394
  lastRunConfigRef.current = config.runConfig;
@@ -345,12 +415,7 @@ const useAISDKRuntime = (chatHelpers, adapter = {}) => {
345
415
  }));
346
416
  }
347
417
  },
348
- onRespondToToolApproval: ({ approvalId, approved, reason }) => Promise.resolve(chatHelpers.addToolApprovalResponse({
349
- id: approvalId,
350
- approved,
351
- ...reason != null && { reason },
352
- options: { metadata: lastRunConfigRef.current }
353
- })),
418
+ onRespondToToolApproval: customOnRespondToToolApproval ? (response_0) => respondViaHost(customOnRespondToToolApproval, response_0) : respondViaAISDK,
354
419
  ...pickExternalStoreSharedOptions(adapter),
355
420
  ...adapter.unstable_messageRepositoryInstance && { unstable_messageRepositoryInstance: adapter.unstable_messageRepositoryInstance },
356
421
  ...suggestionAdapter ? { suggestions: generatedSuggestions } : {},