@ulearning/ai-sdk-adapter 0.0.0-stage → 1.0.0-next.0

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 (210) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +29 -2
  3. package/dist/adapters/aiSDKFormatAdapter.d.ts +6 -0
  4. package/dist/adapters/aiSDKFormatAdapter.d.ts.map +1 -0
  5. package/dist/adapters/aiSDKFormatAdapter.js +17 -0
  6. package/dist/adapters/aiSDKFormatAdapter.js.map +1 -0
  7. package/dist/adapters/vercelAttachmentAdapter.d.ts +3 -0
  8. package/dist/adapters/vercelAttachmentAdapter.d.ts.map +1 -0
  9. package/dist/adapters/vercelAttachmentAdapter.js +36 -0
  10. package/dist/adapters/vercelAttachmentAdapter.js.map +1 -0
  11. package/dist/aiSDKExtras.d.ts +13 -0
  12. package/dist/aiSDKExtras.d.ts.map +1 -0
  13. package/dist/aiSDKExtras.js +6 -0
  14. package/dist/aiSDKExtras.js.map +1 -0
  15. package/dist/converters/convertMessage.d.ts +44 -0
  16. package/dist/converters/convertMessage.d.ts.map +1 -0
  17. package/dist/converters/convertMessage.js +465 -0
  18. package/dist/converters/convertMessage.js.map +1 -0
  19. package/dist/converters/toCreateMessage.d.ts +4 -0
  20. package/dist/converters/toCreateMessage.d.ts.map +1 -0
  21. package/dist/converters/toCreateMessage.js +65 -0
  22. package/dist/converters/toCreateMessage.js.map +1 -0
  23. package/dist/converters/toolApprovalAnswers.d.ts +3 -0
  24. package/dist/converters/toolApprovalAnswers.d.ts.map +1 -0
  25. package/dist/converters/toolApprovalAnswers.js +16 -0
  26. package/dist/converters/toolApprovalAnswers.js.map +1 -0
  27. package/dist/hooks.d.ts +17 -0
  28. package/dist/hooks.d.ts.map +1 -0
  29. package/dist/hooks.js +19 -0
  30. package/dist/hooks.js.map +1 -0
  31. package/dist/index.d.ts +17 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +13 -0
  34. package/dist/model-context/injectInteractableContext.d.ts +37 -0
  35. package/dist/model-context/injectInteractableContext.d.ts.map +1 -0
  36. package/dist/model-context/injectInteractableContext.js +54 -0
  37. package/dist/model-context/injectInteractableContext.js.map +1 -0
  38. package/dist/model-context/injectQuoteContext.d.ts +25 -0
  39. package/dist/model-context/injectQuoteContext.d.ts.map +1 -0
  40. package/dist/model-context/injectQuoteContext.js +51 -0
  41. package/dist/model-context/injectQuoteContext.js.map +1 -0
  42. package/dist/runtime/AISDKChat.d.ts +13 -0
  43. package/dist/runtime/AISDKChat.d.ts.map +1 -0
  44. package/dist/runtime/AISDKChat.js +34 -0
  45. package/dist/runtime/AISDKChat.js.map +1 -0
  46. package/dist/runtime/AISDKThreads.d.ts +24 -0
  47. package/dist/runtime/AISDKThreads.d.ts.map +1 -0
  48. package/dist/runtime/AISDKThreads.js +92 -0
  49. package/dist/runtime/AISDKThreads.js.map +1 -0
  50. package/dist/runtime/DynamicChatTransport.d.ts +50 -0
  51. package/dist/runtime/DynamicChatTransport.d.ts.map +1 -0
  52. package/dist/runtime/DynamicChatTransport.js +153 -0
  53. package/dist/runtime/DynamicChatTransport.js.map +1 -0
  54. package/dist/runtime/getResumableAdapter.d.ts +5 -0
  55. package/dist/runtime/getResumableAdapter.d.ts.map +1 -0
  56. package/dist/runtime/getResumableAdapter.js +11 -0
  57. package/dist/runtime/getResumableAdapter.js.map +1 -0
  58. package/dist/runtime/toolHistoryCodec.d.ts +20 -0
  59. package/dist/runtime/toolHistoryCodec.d.ts.map +1 -0
  60. package/dist/runtime/toolHistoryCodec.js +122 -0
  61. package/dist/runtime/toolHistoryCodec.js.map +1 -0
  62. package/dist/runtime/useAISDKRuntime.d.ts +95 -0
  63. package/dist/runtime/useAISDKRuntime.d.ts.map +1 -0
  64. package/dist/runtime/useAISDKRuntime.js +754 -0
  65. package/dist/runtime/useAISDKRuntime.js.map +1 -0
  66. package/dist/runtime/useChatRuntime.d.ts +17 -0
  67. package/dist/runtime/useChatRuntime.d.ts.map +1 -0
  68. package/dist/runtime/useChatRuntime.js +50 -0
  69. package/dist/runtime/useChatRuntime.js.map +1 -0
  70. package/dist/runtime/useChatSnapshot.d.ts +6 -0
  71. package/dist/runtime/useChatSnapshot.d.ts.map +1 -0
  72. package/dist/runtime/useChatSnapshot.js +62 -0
  73. package/dist/runtime/useChatSnapshot.js.map +1 -0
  74. package/dist/runtime/useChatThread.d.ts +121 -0
  75. package/dist/runtime/useChatThread.d.ts.map +1 -0
  76. package/dist/runtime/useChatThread.js +255 -0
  77. package/dist/runtime/useChatThread.js.map +1 -0
  78. package/dist/runtime/useDynamicChatTransport.d.ts +4 -0
  79. package/dist/runtime/useDynamicChatTransport.d.ts.map +1 -0
  80. package/dist/runtime/useDynamicChatTransport.js +26 -0
  81. package/dist/runtime/useDynamicChatTransport.js.map +1 -0
  82. package/dist/runtime/useExternalHistory.d.ts +12 -0
  83. package/dist/runtime/useExternalHistory.d.ts.map +1 -0
  84. package/dist/runtime/useExternalHistory.js +556 -0
  85. package/dist/runtime/useExternalHistory.js.map +1 -0
  86. package/dist/runtime/useMessageQueue.d.ts +14 -0
  87. package/dist/runtime/useMessageQueue.d.ts.map +1 -0
  88. package/dist/runtime/useMessageQueue.js +142 -0
  89. package/dist/runtime/useMessageQueue.js.map +1 -0
  90. package/dist/runtime/useResourceCleanup.d.ts +2 -0
  91. package/dist/runtime/useResourceCleanup.d.ts.map +1 -0
  92. package/dist/runtime/useResourceCleanup.js +47 -0
  93. package/dist/runtime/useResourceCleanup.js.map +1 -0
  94. package/dist/runtime/useStreamingTiming.d.ts +12 -0
  95. package/dist/runtime/useStreamingTiming.d.ts.map +1 -0
  96. package/dist/runtime/useStreamingTiming.js +36 -0
  97. package/dist/runtime/useStreamingTiming.js.map +1 -0
  98. package/dist/tools/generativeTools.d.ts +71 -0
  99. package/dist/tools/generativeTools.d.ts.map +1 -0
  100. package/dist/tools/generativeTools.js +258 -0
  101. package/dist/tools/generativeTools.js.map +1 -0
  102. package/dist/tools/mcp-stdio.node.d.ts +2 -0
  103. package/dist/tools/mcp-stdio.node.d.ts.map +1 -0
  104. package/dist/tools/mcp-stdio.node.js +1 -0
  105. package/dist/tools/mcp-stdio.unsupported.d.ts +3 -0
  106. package/dist/tools/mcp-stdio.unsupported.d.ts.map +1 -0
  107. package/dist/tools/mcp-stdio.unsupported.js +10 -0
  108. package/dist/tools/mcp-stdio.unsupported.js.map +1 -0
  109. package/dist/transport/AssistantChatTransport.d.ts +20 -0
  110. package/dist/transport/AssistantChatTransport.d.ts.map +1 -0
  111. package/dist/transport/AssistantChatTransport.js +151 -0
  112. package/dist/transport/AssistantChatTransport.js.map +1 -0
  113. package/dist/transport/resumable.d.ts +36 -0
  114. package/dist/transport/resumable.d.ts.map +1 -0
  115. package/dist/transport/resumable.js +112 -0
  116. package/dist/transport/resumable.js.map +1 -0
  117. package/dist/usage.d.ts +24 -0
  118. package/dist/usage.d.ts.map +1 -0
  119. package/dist/usage.js +121 -0
  120. package/dist/usage.js.map +1 -0
  121. package/dist/utils/getVercelAIMessages.d.ts +4 -0
  122. package/dist/utils/getVercelAIMessages.d.ts.map +1 -0
  123. package/dist/utils/getVercelAIMessages.js +8 -0
  124. package/dist/utils/getVercelAIMessages.js.map +1 -0
  125. package/dist/utils/sliceMessagesUntil.d.ts +3 -0
  126. package/dist/utils/sliceMessagesUntil.d.ts.map +1 -0
  127. package/dist/utils/sliceMessagesUntil.js +10 -0
  128. package/dist/utils/sliceMessagesUntil.js.map +1 -0
  129. package/package.json +96 -3
  130. package/src/__tests__/standalone.e2e.ts +118 -0
  131. package/src/adapters/aiSDKFormatAdapter.test.ts +36 -0
  132. package/src/adapters/aiSDKFormatAdapter.ts +18 -0
  133. package/src/adapters/vercelAttachmentAdapter.test.ts +52 -0
  134. package/src/adapters/vercelAttachmentAdapter.ts +36 -0
  135. package/src/aiSDKExtras.ts +31 -0
  136. package/src/converters/convertMessage.metadata-key.test.tsx +182 -0
  137. package/src/converters/convertMessage.test.ts +2428 -0
  138. package/src/converters/convertMessage.tool-args-status.test.tsx +185 -0
  139. package/src/converters/convertMessage.ts +919 -0
  140. package/src/converters/toCreateMessage.test.ts +716 -0
  141. package/src/converters/toCreateMessage.ts +110 -0
  142. package/src/converters/toolApprovalAnswers.ts +27 -0
  143. package/src/hooks.test.ts +168 -0
  144. package/src/hooks.ts +26 -0
  145. package/src/index.ts +29 -0
  146. package/src/model-context/injectInteractableContext.test.ts +167 -0
  147. package/src/model-context/injectInteractableContext.ts +64 -0
  148. package/src/model-context/injectQuoteContext.test.ts +33 -0
  149. package/src/model-context/injectQuoteContext.ts +63 -0
  150. package/src/runtime/AISDKChat.artifacts.test.ts +48 -0
  151. package/src/runtime/AISDKChat.integration.test.tsx +148 -0
  152. package/src/runtime/AISDKChat.test.ts +241 -0
  153. package/src/runtime/AISDKChat.ts +43 -0
  154. package/src/runtime/AISDKThreads.test.ts +811 -0
  155. package/src/runtime/AISDKThreads.ts +194 -0
  156. package/src/runtime/DynamicChatTransport.test.ts +228 -0
  157. package/src/runtime/DynamicChatTransport.ts +281 -0
  158. package/src/runtime/__tests__/controlled-transport.ts +70 -0
  159. package/src/runtime/__tests__/tap.ts +80 -0
  160. package/src/runtime/__tests__/vue.ts +46 -0
  161. package/src/runtime/getResumableAdapter.ts +16 -0
  162. package/src/runtime/toolHistoryCodec.test.ts +187 -0
  163. package/src/runtime/toolHistoryCodec.ts +245 -0
  164. package/src/runtime/useAISDKRuntime.approval.integration.test.tsx +1956 -0
  165. package/src/runtime/useAISDKRuntime.approval.test.tsx +580 -0
  166. package/src/runtime/useAISDKRuntime.denied-tool.test.tsx +122 -0
  167. package/src/runtime/useAISDKRuntime.fast-refresh.test.tsx +302 -0
  168. package/src/runtime/useAISDKRuntime.metadata-cache.test.tsx +157 -0
  169. package/src/runtime/useAISDKRuntime.queue.test.tsx +707 -0
  170. package/src/runtime/useAISDKRuntime.reload.test.tsx +217 -0
  171. package/src/runtime/useAISDKRuntime.test.ts +2345 -0
  172. package/src/runtime/useAISDKRuntime.tool-output.test.tsx +113 -0
  173. package/src/runtime/useAISDKRuntime.ts +1503 -0
  174. package/src/runtime/useAISDKRuntime.voice.test.tsx +319 -0
  175. package/src/runtime/useChatOnTap.test.ts +60 -0
  176. package/src/runtime/useChatRuntime.fast-refresh.test.tsx +83 -0
  177. package/src/runtime/useChatRuntime.integration.test.tsx +661 -0
  178. package/src/runtime/useChatRuntime.local-storage.test.tsx +114 -0
  179. package/src/runtime/useChatRuntime.native.test.ts +147 -0
  180. package/src/runtime/useChatRuntime.run-telemetry.test.tsx +226 -0
  181. package/src/runtime/useChatRuntime.test.ts +619 -0
  182. package/src/runtime/useChatRuntime.ts +80 -0
  183. package/src/runtime/useChatSnapshot.test.ts +60 -0
  184. package/src/runtime/useChatSnapshot.ts +86 -0
  185. package/src/runtime/useChatThread.binding.test.tsx +140 -0
  186. package/src/runtime/useChatThread.test.ts +993 -0
  187. package/src/runtime/useChatThread.transport.test.tsx +149 -0
  188. package/src/runtime/useChatThread.ts +533 -0
  189. package/src/runtime/useDynamicChatTransport.ts +26 -0
  190. package/src/runtime/useExternalHistory.test.ts +4187 -0
  191. package/src/runtime/useExternalHistory.ts +902 -0
  192. package/src/runtime/useMessageQueue.effects.test.tsx +88 -0
  193. package/src/runtime/useMessageQueue.test.tsx +256 -0
  194. package/src/runtime/useMessageQueue.ts +189 -0
  195. package/src/runtime/useResourceCleanup.ts +58 -0
  196. package/src/runtime/useStreamingTiming.test.tsx +96 -0
  197. package/src/runtime/useStreamingTiming.ts +69 -0
  198. package/src/tools/generativeTools.test.ts +1058 -0
  199. package/src/tools/generativeTools.ts +491 -0
  200. package/src/tools/mcp-stdio.node.ts +1 -0
  201. package/src/tools/mcp-stdio.unsupported.ts +12 -0
  202. package/src/transport/AssistantChatTransport.test.ts +631 -0
  203. package/src/transport/AssistantChatTransport.ts +236 -0
  204. package/src/transport/resumable.test.ts +262 -0
  205. package/src/transport/resumable.ts +162 -0
  206. package/src/usage.test.ts +204 -0
  207. package/src/usage.ts +179 -0
  208. package/src/utils/getVercelAIMessages.ts +11 -0
  209. package/src/utils/sliceMessagesUntil.test.ts +51 -0
  210. package/src/utils/sliceMessagesUntil.ts +16 -0
@@ -0,0 +1,153 @@
1
+ import { AssistantChatTransport } from "../transport/AssistantChatTransport.js";
2
+ import { getResumableAdapter } from "./getResumableAdapter.js";
3
+ // src/runtime/DynamicChatTransport.ts
4
+ const resumedStreamIdsByStorage = /* @__PURE__ */ new WeakMap();
5
+ const getResumedStreamIds = (storage) => {
6
+ if (!storage) return /* @__PURE__ */ new Set();
7
+ let resumedStreamIds = resumedStreamIdsByStorage.get(storage);
8
+ if (!resumedStreamIds) {
9
+ resumedStreamIds = /* @__PURE__ */ new Set();
10
+ resumedStreamIdsByStorage.set(storage, resumedStreamIds);
11
+ }
12
+ return resumedStreamIds;
13
+ };
14
+ var DynamicResumableStorage = class {
15
+ subscriptions = /* @__PURE__ */ new Set();
16
+ storage;
17
+ resumedStreamIds;
18
+ hasPendingNotification = false;
19
+ constructor(storage) {
20
+ this.storage = storage;
21
+ this.resumedStreamIds = getResumedStreamIds(storage);
22
+ }
23
+ setStorage(storage) {
24
+ if (this.storage === storage) return;
25
+ this.storage = storage;
26
+ const nextResumedStreamIds = getResumedStreamIds(storage);
27
+ for (const streamId of this.resumedStreamIds) nextResumedStreamIds.add(streamId);
28
+ this.resumedStreamIds = nextResumedStreamIds;
29
+ this.hasPendingNotification = true;
30
+ }
31
+ flushChange() {
32
+ if (!this.hasPendingNotification) return;
33
+ this.hasPendingNotification = false;
34
+ for (const subscription of this.subscriptions) {
35
+ subscription.unsubscribe?.();
36
+ subscription.unsubscribe = this.storage?.subscribe?.(subscription.listener, subscription.threadId);
37
+ subscription.listener();
38
+ }
39
+ }
40
+ getResumedStreamIds() {
41
+ return this.resumedStreamIds;
42
+ }
43
+ getStreamId(threadId) {
44
+ return this.storage?.getStreamId(threadId) ?? null;
45
+ }
46
+ setStreamId(id, threadId) {
47
+ this.storage?.setStreamId(id, threadId);
48
+ }
49
+ clear(threadId) {
50
+ this.storage?.clear(threadId);
51
+ }
52
+ subscribe(listener, threadId) {
53
+ const subscription = {
54
+ listener,
55
+ threadId,
56
+ unsubscribe: this.storage?.subscribe?.(listener, threadId)
57
+ };
58
+ this.subscriptions.add(subscription);
59
+ return () => {
60
+ this.subscriptions.delete(subscription);
61
+ subscription.unsubscribe?.();
62
+ };
63
+ }
64
+ };
65
+ var DynamicChatTransport = class {
66
+ threadContexts = /* @__PURE__ */ new Map();
67
+ transport;
68
+ resumableStorage;
69
+ constructor(transport) {
70
+ this.transport = transport;
71
+ this.resumableStorage = new DynamicResumableStorage(getResumableAdapter(transport)?.storage);
72
+ }
73
+ sendMessages = (options) => this.getTransport(options.chatId).sendMessages(options);
74
+ reconnectToStream = (options) => this.getTransport(options.chatId).reconnectToStream(options);
75
+ get resumeStreamIsReplay() {
76
+ return this.transport.resumeStreamIsReplay ?? false;
77
+ }
78
+ getCurrentTransport = (chatId) => this.getThreadTransport(this.threadContexts.get(chatId)) ?? this.transport;
79
+ getCurrentResumableStorage = () => this.resumableStorage;
80
+ getResumedStreamIds = () => this.resumableStorage.getResumedStreamIds();
81
+ createThreadProxy(owner, getBinding) {
82
+ const dynamicTransport = this;
83
+ return {
84
+ get resumeStreamIsReplay() {
85
+ return dynamicTransport.resumeStreamIsReplay;
86
+ },
87
+ sendMessages: (options) => this.getOrCreateBoundTransport(options.chatId, owner, getBinding).sendMessages(options),
88
+ reconnectToStream: (options) => this.getOrCreateBoundTransport(options.chatId, owner, getBinding).reconnectToStream(options)
89
+ };
90
+ }
91
+ setTransport(transport) {
92
+ if (this.transport === transport) return;
93
+ this.transport = transport;
94
+ this.resumableStorage.setStorage(getResumableAdapter(transport)?.storage);
95
+ }
96
+ flushTransportChange() {
97
+ this.resumableStorage.flushChange();
98
+ }
99
+ registerThread(chatId, owner) {
100
+ if (this.threadContexts.get(chatId)?.owner === owner) return;
101
+ this.threadContexts.set(chatId, { owner });
102
+ }
103
+ setThreadContext(chatId, owner, runtime, getThreadListItem) {
104
+ this.registerThread(chatId, owner);
105
+ const context = this.threadContexts.get(chatId);
106
+ context.runtime = runtime;
107
+ context.getThreadListItem = getThreadListItem;
108
+ if (context.transport === void 0) {
109
+ this.getThreadTransport(context);
110
+ return;
111
+ }
112
+ if (context.sourceTransport === this.transport && context.transport !== void 0) this.wireTransport(context, context.transport);
113
+ }
114
+ unregisterThread(chatId, owner) {
115
+ if (this.threadContexts.get(chatId)?.owner === owner) this.threadContexts.delete(chatId);
116
+ }
117
+ getTransport(chatId) {
118
+ const context = this.threadContexts.get(chatId);
119
+ if (!context) throw new Error(`DynamicChatTransport has no registered context for chat "${chatId}"`);
120
+ return this.getThreadTransport(context);
121
+ }
122
+ getBoundTransport(chatId, owner, binding) {
123
+ this.registerThread(chatId, owner);
124
+ const context = this.threadContexts.get(chatId);
125
+ context.runtime = binding.runtime;
126
+ context.getThreadListItem = binding.getThreadListItem;
127
+ return this.getThreadTransport(context);
128
+ }
129
+ getOrCreateBoundTransport(chatId, owner, getBinding) {
130
+ const context = this.threadContexts.get(chatId);
131
+ return context?.owner === owner ? this.getThreadTransport(context) : this.getBoundTransport(chatId, owner, getBinding());
132
+ }
133
+ getThreadTransport(context) {
134
+ if (!context) return void 0;
135
+ if (context.sourceTransport !== this.transport) {
136
+ context.transport = this.createThreadTransport(this.transport);
137
+ context.sourceTransport = this.transport;
138
+ }
139
+ this.wireTransport(context, context.transport);
140
+ return context.transport;
141
+ }
142
+ createThreadTransport(transport) {
143
+ return transport instanceof AssistantChatTransport ? transport.__internal_clone() : transport;
144
+ }
145
+ wireTransport(context, transport) {
146
+ if (!(transport instanceof AssistantChatTransport)) return;
147
+ if (context.runtime) transport.setRuntime(context.runtime);
148
+ if (context.getThreadListItem) transport.__internal_setGetThreadListItem(context.getThreadListItem);
149
+ }
150
+ };
151
+ export { DynamicChatTransport, getResumedStreamIds };
152
+
153
+ //# sourceMappingURL=DynamicChatTransport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DynamicChatTransport.js","names":[],"sources":["../../src/runtime/DynamicChatTransport.ts"],"sourcesContent":["import type { AssistantRuntime } from \"@ulearning/ai-core\";\nimport type { UIMessage } from \"ai\";\nimport type { ChatTransport } from \"ai\";\nimport {\n AssistantChatTransport,\n type InitializableThreadListItem,\n} from \"../transport/AssistantChatTransport\";\nimport type { ResumableClientStorage } from \"../transport/resumable\";\nimport { getResumableAdapter } from \"./getResumableAdapter\";\n\nconst resumedStreamIdsByStorage = new WeakMap<\n ResumableClientStorage,\n Set<string>\n>();\n\nexport const getResumedStreamIds = (\n storage: ResumableClientStorage | undefined,\n) => {\n if (!storage) return new Set<string>();\n let resumedStreamIds = resumedStreamIdsByStorage.get(storage);\n if (!resumedStreamIds) {\n resumedStreamIds = new Set();\n resumedStreamIdsByStorage.set(storage, resumedStreamIds);\n }\n return resumedStreamIds;\n};\n\ntype ResumableStorageSubscription = {\n listener: () => void;\n threadId: string | undefined;\n unsubscribe: (() => void) | undefined;\n};\n\nclass DynamicResumableStorage implements ResumableClientStorage {\n private readonly subscriptions = new Set<ResumableStorageSubscription>();\n private storage: ResumableClientStorage | undefined;\n private resumedStreamIds: Set<string>;\n private hasPendingNotification = false;\n\n constructor(storage: ResumableClientStorage | undefined) {\n this.storage = storage;\n this.resumedStreamIds = getResumedStreamIds(storage);\n }\n\n public setStorage(storage: ResumableClientStorage | undefined) {\n if (this.storage === storage) return;\n this.storage = storage;\n const nextResumedStreamIds = getResumedStreamIds(storage);\n for (const streamId of this.resumedStreamIds) {\n nextResumedStreamIds.add(streamId);\n }\n this.resumedStreamIds = nextResumedStreamIds;\n this.hasPendingNotification = true;\n }\n\n public flushChange() {\n if (!this.hasPendingNotification) return;\n this.hasPendingNotification = false;\n for (const subscription of this.subscriptions) {\n subscription.unsubscribe?.();\n subscription.unsubscribe = this.storage?.subscribe?.(\n subscription.listener,\n subscription.threadId,\n );\n subscription.listener();\n }\n }\n\n public getResumedStreamIds() {\n return this.resumedStreamIds;\n }\n\n public getStreamId(threadId?: string) {\n return this.storage?.getStreamId(threadId) ?? null;\n }\n\n public setStreamId(id: string, threadId?: string) {\n this.storage?.setStreamId(id, threadId);\n }\n\n public clear(threadId?: string) {\n this.storage?.clear(threadId);\n }\n\n public subscribe(listener: () => void, threadId?: string) {\n const subscription: ResumableStorageSubscription = {\n listener,\n threadId,\n unsubscribe: this.storage?.subscribe?.(listener, threadId),\n };\n this.subscriptions.add(subscription);\n return () => {\n this.subscriptions.delete(subscription);\n subscription.unsubscribe?.();\n };\n }\n}\n\ntype ThreadTransportContext<UI_MESSAGE extends UIMessage> = {\n owner: object;\n sourceTransport?: ChatTransport<UI_MESSAGE> | undefined;\n transport?: ChatTransport<UI_MESSAGE> | undefined;\n runtime?: AssistantRuntime | undefined;\n getThreadListItem?:\n | (() => InitializableThreadListItem | undefined)\n | undefined;\n};\n\ntype ThreadTransportBinding = {\n runtime: AssistantRuntime;\n getThreadListItem: () => InitializableThreadListItem | undefined;\n};\n\nexport class DynamicChatTransport<\n UI_MESSAGE extends UIMessage,\n> implements ChatTransport<UI_MESSAGE> {\n private readonly threadContexts = new Map<\n string,\n ThreadTransportContext<UI_MESSAGE>\n >();\n private transport: ChatTransport<UI_MESSAGE>;\n private readonly resumableStorage: DynamicResumableStorage;\n\n constructor(transport: ChatTransport<UI_MESSAGE>) {\n this.transport = transport;\n this.resumableStorage = new DynamicResumableStorage(\n getResumableAdapter(transport)?.storage,\n );\n }\n\n public readonly sendMessages: ChatTransport<UI_MESSAGE>[\"sendMessages\"] = (\n options,\n ) => this.getTransport(options.chatId).sendMessages(options);\n\n public readonly reconnectToStream: ChatTransport<UI_MESSAGE>[\"reconnectToStream\"] =\n (options) => this.getTransport(options.chatId).reconnectToStream(options);\n\n public get resumeStreamIsReplay() {\n return this.transport.resumeStreamIsReplay ?? false;\n }\n\n public readonly getCurrentTransport = (chatId: string) =>\n this.getThreadTransport(this.threadContexts.get(chatId)) ?? this.transport;\n\n public readonly getCurrentResumableStorage = () => this.resumableStorage;\n\n public readonly getResumedStreamIds = () =>\n this.resumableStorage.getResumedStreamIds();\n\n public createThreadProxy(\n owner: object,\n getBinding: () => ThreadTransportBinding,\n ): ChatTransport<UI_MESSAGE> {\n const dynamicTransport = this;\n return {\n get resumeStreamIsReplay() {\n return dynamicTransport.resumeStreamIsReplay;\n },\n sendMessages: (options) =>\n this.getOrCreateBoundTransport(\n options.chatId,\n owner,\n getBinding,\n ).sendMessages(options),\n reconnectToStream: (options) =>\n this.getOrCreateBoundTransport(\n options.chatId,\n owner,\n getBinding,\n ).reconnectToStream(options),\n };\n }\n\n public setTransport(transport: ChatTransport<UI_MESSAGE>) {\n if (this.transport === transport) return;\n this.transport = transport;\n this.resumableStorage.setStorage(getResumableAdapter(transport)?.storage);\n }\n\n public flushTransportChange() {\n this.resumableStorage.flushChange();\n }\n\n public registerThread(chatId: string, owner: object) {\n const existing = this.threadContexts.get(chatId);\n if (existing?.owner === owner) return;\n this.threadContexts.set(chatId, {\n owner,\n });\n }\n\n public setThreadContext(\n chatId: string,\n owner: object,\n runtime: AssistantRuntime,\n getThreadListItem: () => InitializableThreadListItem | undefined,\n ) {\n this.registerThread(chatId, owner);\n const context = this.threadContexts.get(chatId)!;\n context.runtime = runtime;\n context.getThreadListItem = getThreadListItem;\n if (context.transport === undefined) {\n this.getThreadTransport(context);\n return;\n }\n if (\n context.sourceTransport === this.transport &&\n context.transport !== undefined\n ) {\n this.wireTransport(context, context.transport);\n }\n }\n\n public unregisterThread(chatId: string, owner: object) {\n if (this.threadContexts.get(chatId)?.owner === owner) {\n this.threadContexts.delete(chatId);\n }\n }\n\n private getTransport(chatId: string) {\n const context = this.threadContexts.get(chatId);\n if (!context) {\n throw new Error(\n `DynamicChatTransport has no registered context for chat \"${chatId}\"`,\n );\n }\n return this.getThreadTransport(context)!;\n }\n\n private getBoundTransport(\n chatId: string,\n owner: object,\n binding: ThreadTransportBinding,\n ) {\n this.registerThread(chatId, owner);\n const context = this.threadContexts.get(chatId)!;\n context.runtime = binding.runtime;\n context.getThreadListItem = binding.getThreadListItem;\n return this.getThreadTransport(context)!;\n }\n\n private getOrCreateBoundTransport(\n chatId: string,\n owner: object,\n getBinding: () => ThreadTransportBinding,\n ) {\n const context = this.threadContexts.get(chatId);\n return context?.owner === owner\n ? this.getThreadTransport(context)!\n : this.getBoundTransport(chatId, owner, getBinding());\n }\n\n private getThreadTransport(\n context: ThreadTransportContext<UI_MESSAGE> | undefined,\n ) {\n if (!context) return undefined;\n if (context.sourceTransport !== this.transport) {\n context.transport = this.createThreadTransport(this.transport);\n context.sourceTransport = this.transport;\n }\n this.wireTransport(context, context.transport!);\n return context.transport!;\n }\n\n private createThreadTransport(transport: ChatTransport<UI_MESSAGE>) {\n return transport instanceof AssistantChatTransport\n ? transport.__internal_clone()\n : transport;\n }\n\n private wireTransport(\n context: ThreadTransportContext<UI_MESSAGE>,\n transport: ChatTransport<UI_MESSAGE>,\n ) {\n if (!(transport instanceof AssistantChatTransport)) return;\n if (context.runtime) transport.setRuntime(context.runtime);\n if (context.getThreadListItem) {\n transport.__internal_setGetThreadListItem(context.getThreadListItem);\n }\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { UIMessage } from "ai";
2
+ import type { ChatTransport } from "ai";
3
+ import type { AssistantChatResumableOptions } from "../transport/resumable.js";
4
+ export declare const getResumableAdapter: <UI_MESSAGE extends UIMessage>(transport: ChatTransport<UI_MESSAGE>) => AssistantChatResumableOptions | undefined;
5
+ //# sourceMappingURL=getResumableAdapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getResumableAdapter.d.ts","mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,IAAI;AACnC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,IAAI;AAEvC,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,2BAAwB;AAE3E,eAAO,MAAM,mBAAmB,GAAI,UAAU,SAAS,SAAS,EAC9D,WAAW,aAAa,CAAC,UAAU,CAAC,KACnC,6BAA6B,GAAG,SAQlC","names":[],"ignoreList":[],"sources":["../../src/runtime/getResumableAdapter.ts"],"sourcesContent":[null]}
@@ -0,0 +1,11 @@
1
+ import { AssistantChatTransport } from "../transport/AssistantChatTransport.js";
2
+ // src/runtime/getResumableAdapter.ts
3
+ const getResumableAdapter = (transport) => {
4
+ if (transport instanceof AssistantChatTransport) return transport.getResumableAdapter();
5
+ const candidate = transport.getResumableAdapter;
6
+ if (typeof candidate !== "function") return void 0;
7
+ return candidate.call(transport);
8
+ };
9
+ export { getResumableAdapter };
10
+
11
+ //# sourceMappingURL=getResumableAdapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getResumableAdapter.js","names":[],"sources":["../../src/runtime/getResumableAdapter.ts"],"sourcesContent":["import type { UIMessage } from \"ai\";\nimport type { ChatTransport } from \"ai\";\nimport { AssistantChatTransport } from \"../transport/AssistantChatTransport\";\nimport type { AssistantChatResumableOptions } from \"../transport/resumable\";\n\nexport const getResumableAdapter = <UI_MESSAGE extends UIMessage>(\n transport: ChatTransport<UI_MESSAGE>,\n): AssistantChatResumableOptions | undefined => {\n if (transport instanceof AssistantChatTransport) {\n return transport.getResumableAdapter();\n }\n const candidate = (transport as { getResumableAdapter?: () => unknown })\n .getResumableAdapter;\n if (typeof candidate !== \"function\") return undefined;\n return candidate.call(transport) as AssistantChatResumableOptions | undefined;\n};\n"],"mappings":";;AAKA,MAAa,uBACX,cAC8C;CAC9C,IAAI,qBAAqB,wBACvB,OAAO,UAAU,oBAAoB;CAEvC,MAAM,YAAa,UAChB;CACH,IAAI,OAAO,cAAc,YAAY,OAAO,KAAA;CAC5C,OAAO,UAAU,KAAK,SAAS;AACjC"}
@@ -0,0 +1,20 @@
1
+ import type { RespondToToolApprovalOptions, ThreadMessage, Unstable_ToolInteractionLog } from "@ulearning/ai-core";
2
+ export type StoredToolApprovalResponse = Omit<RespondToToolApprovalOptions, "approvalId">;
3
+ export declare const collectToolArtifacts: (message: ThreadMessage, toolArtifacts: ReadonlyMap<string, unknown> | undefined) => {
4
+ [k: string]: {} | null;
5
+ } | undefined;
6
+ export declare const collectToolInteractions: (message: ThreadMessage, toolInteractions: ReadonlyMap<string, Unstable_ToolInteractionLog> | undefined) => {
7
+ [k: string]: Unstable_ToolInteractionLog;
8
+ } | undefined;
9
+ export declare const collectToolApprovalResponses: (message: ThreadMessage, toolApprovalResponses: ReadonlyMap<string, RespondToToolApprovalOptions> | undefined) => {
10
+ [k: string]: {
11
+ readonly reason?: string;
12
+ readonly answers?: Readonly<Record<string, import("@ulearning/ai-core").ToolApprovalAnswer>>;
13
+ readonly text?: string;
14
+ readonly optionId?: string;
15
+ readonly approved: boolean;
16
+ };
17
+ } | undefined;
18
+ export declare const addToolData: <TMessage>(message: TMessage, toolArtifacts: Record<string, unknown> | undefined, toolInteractions: Record<string, Unstable_ToolInteractionLog> | undefined, toolApprovalResponses: Record<string, StoredToolApprovalResponse> | undefined) => TMessage;
19
+ export declare const restoreToolData: <TMessage>(message: TMessage, toolArtifacts: Map<string, unknown> | undefined, toolInteractions: Map<string, Unstable_ToolInteractionLog> | undefined, toolApprovalResponses: Map<string, RespondToToolApprovalOptions> | undefined) => TMessage;
20
+ //# sourceMappingURL=toolHistoryCodec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toolHistoryCodec.d.ts","mappings":"AAAA,OAAO,KAAK,EACV,4BAA4B,EAC5B,aAAa,EACb,2BAA2B,EAC5B,MAAM,oBAAoB;AAa3B,MAAM,MAAM,0BAA0B,GAAG,IAAI,CAC3C,4BAA4B,EAC5B,YAAY,CACb;AA6BD,eAAO,MAAM,oBAAoB,GAC/B,SAAS,aAAa,EACtB,eAAe,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS;;aASxD;AAED,eAAO,MAAM,uBAAuB,GAClC,SAAS,aAAa,EACtB,kBACI,WAAW,CAAC,MAAM,EAAE,2BAA2B,CAAC,GAChD,SAAS;;aAWd;AAED,eAAO,MAAM,4BAA4B,GACvC,SAAS,aAAa,EACtB,uBACI,WAAW,CAAC,MAAM,EAAE,4BAA4B,CAAC,GACjD,SAAS;;;;;;;;aAqBd;AAED,eAAO,MAAM,WAAW,GAAI,QAAQ,EAClC,SAAS,QAAQ,EACjB,eAAe,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAClD,kBAAkB,MAAM,CAAC,MAAM,EAAE,2BAA2B,CAAC,GAAG,SAAS,EACzE,uBAAuB,MAAM,CAAC,MAAM,EAAE,0BAA0B,CAAC,GAAG,SAAS,KAC5E,QAgEF;AAED,eAAO,MAAM,eAAe,GAAI,QAAQ,EACtC,SAAS,QAAQ,EACjB,eAAe,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAC/C,kBAAkB,GAAG,CAAC,MAAM,EAAE,2BAA2B,CAAC,GAAG,SAAS,EACtE,uBAAuB,GAAG,CAAC,MAAM,EAAE,4BAA4B,CAAC,GAAG,SAAS,KAC3E,QA8DF","names":[],"ignoreList":[],"sources":["../../src/runtime/toolHistoryCodec.ts"],"sourcesContent":[null]}
@@ -0,0 +1,122 @@
1
+ import { normalizeToolApprovalAnswers } from "../converters/toolApprovalAnswers.js";
2
+ import { appendToolInteraction, isJSONValueEqual, isRecord, readToolInteractionLog } from "@ulearning/ai-core/internal";
3
+ // src/runtime/toolHistoryCodec.ts
4
+ const TOOL_ARTIFACTS_METADATA_KEY = "__aui_toolArtifacts";
5
+ const TOOL_INTERACTIONS_METADATA_KEY = "__aui_toolInteractions";
6
+ const TOOL_APPROVAL_RESPONSES_METADATA_KEY = "__aui_toolApprovalResponses";
7
+ const mergeInteractionLogs = (stored, current) => {
8
+ const incoming = readToolInteractionLog(current);
9
+ if (!incoming) return stored;
10
+ const omitted = Math.max(stored.omitted ?? 0, incoming.omitted ?? 0);
11
+ let merged = {
12
+ entries: stored.entries,
13
+ ...omitted ? { omitted } : void 0
14
+ };
15
+ for (const entry of incoming.entries) {
16
+ if (merged.entries.some((existing) => existing.type === entry.type && existing.occurredAt === entry.occurredAt && isJSONValueEqual(existing.payload, entry.payload))) continue;
17
+ merged = appendToolInteraction(merged, entry);
18
+ }
19
+ return merged;
20
+ };
21
+ const collectToolArtifacts = (message, toolArtifacts) => {
22
+ if (!toolArtifacts) return void 0;
23
+ const entries = message.content.flatMap((part) => {
24
+ if (part.type !== "tool-call") return [];
25
+ const artifact = toolArtifacts.get(part.toolCallId);
26
+ return artifact === void 0 ? [] : [[part.toolCallId, artifact]];
27
+ });
28
+ return entries.length > 0 ? Object.fromEntries(entries) : void 0;
29
+ };
30
+ const collectToolInteractions = (message, toolInteractions) => {
31
+ if (!toolInteractions) return void 0;
32
+ const entries = message.content.flatMap((part) => {
33
+ if (part.type !== "tool-call") return [];
34
+ const interactions = toolInteractions.get(part.toolCallId);
35
+ return interactions === void 0 ? [] : [[part.toolCallId, interactions]];
36
+ });
37
+ return entries.length > 0 ? Object.fromEntries(entries) : void 0;
38
+ };
39
+ const collectToolApprovalResponses = (message, toolApprovalResponses) => {
40
+ if (!toolApprovalResponses) return void 0;
41
+ const entries = message.content.flatMap((part) => {
42
+ if (part.type !== "tool-call" || !part.approval) return [];
43
+ const response = toolApprovalResponses.get(part.approval.id);
44
+ if (!response) return [];
45
+ return [[part.approval.id, {
46
+ approved: response.approved,
47
+ ...response.optionId != null && { optionId: response.optionId },
48
+ ...response.text != null && { text: response.text },
49
+ ...response.answers != null && { answers: response.answers },
50
+ ...response.reason != null && { reason: response.reason }
51
+ }]];
52
+ });
53
+ return entries.length > 0 ? Object.fromEntries(entries) : void 0;
54
+ };
55
+ const addToolData = (message, toolArtifacts, toolInteractions, toolApprovalResponses) => {
56
+ if (!toolArtifacts && !toolInteractions && !toolApprovalResponses || !isRecord(message) || !Array.isArray(message.parts)) return message;
57
+ const toolCallIds = message.parts.flatMap((part) => {
58
+ if (!isRecord(part) || typeof part.toolCallId !== "string") return [];
59
+ return [part.toolCallId];
60
+ });
61
+ const artifacts = toolArtifacts ? Object.fromEntries(toolCallIds.flatMap((toolCallId) => Object.hasOwn(toolArtifacts, toolCallId) ? [[toolCallId, toolArtifacts[toolCallId]]] : [])) : void 0;
62
+ const interactions = toolInteractions ? Object.fromEntries(toolCallIds.flatMap((toolCallId) => Object.hasOwn(toolInteractions, toolCallId) ? [[toolCallId, toolInteractions[toolCallId]]] : [])) : void 0;
63
+ const approvalIds = message.parts.flatMap((part) => {
64
+ if (!isRecord(part) || !isRecord(part.approval)) return [];
65
+ const approvalId = part.approval.id;
66
+ return typeof approvalId === "string" ? [approvalId] : [];
67
+ });
68
+ const approvalResponses = toolApprovalResponses ? Object.fromEntries(approvalIds.flatMap((approvalId) => Object.hasOwn(toolApprovalResponses, approvalId) ? [[approvalId, toolApprovalResponses[approvalId]]] : [])) : void 0;
69
+ const hasArtifacts = !!artifacts && Object.keys(artifacts).length > 0;
70
+ const hasInteractions = !!interactions && Object.keys(interactions).length > 0;
71
+ const hasApprovalResponses = !!approvalResponses && Object.keys(approvalResponses).length > 0;
72
+ if (!hasArtifacts && !hasInteractions && !hasApprovalResponses) return message;
73
+ const metadata = isRecord(message.metadata) ? message.metadata : {};
74
+ return {
75
+ ...message,
76
+ metadata: {
77
+ ...metadata,
78
+ ...hasArtifacts && { [TOOL_ARTIFACTS_METADATA_KEY]: artifacts },
79
+ ...hasInteractions && { [TOOL_INTERACTIONS_METADATA_KEY]: interactions },
80
+ ...hasApprovalResponses && { [TOOL_APPROVAL_RESPONSES_METADATA_KEY]: approvalResponses }
81
+ }
82
+ };
83
+ };
84
+ const restoreToolData = (message, toolArtifacts, toolInteractions, toolApprovalResponses) => {
85
+ if (!isRecord(message) || !isRecord(message.metadata)) return message;
86
+ const metadata = message.metadata;
87
+ const hasArtifacts = Object.hasOwn(metadata, TOOL_ARTIFACTS_METADATA_KEY);
88
+ const hasInteractions = Object.hasOwn(metadata, TOOL_INTERACTIONS_METADATA_KEY);
89
+ const hasApprovalResponses = Object.hasOwn(metadata, TOOL_APPROVAL_RESPONSES_METADATA_KEY);
90
+ if (!hasArtifacts && !hasInteractions && !hasApprovalResponses) return message;
91
+ const artifacts = metadata[TOOL_ARTIFACTS_METADATA_KEY];
92
+ if (toolArtifacts && isRecord(artifacts)) {
93
+ for (const [toolCallId, artifact] of Object.entries(artifacts)) if (!toolArtifacts.has(toolCallId)) toolArtifacts.set(toolCallId, artifact);
94
+ }
95
+ const interactions = metadata[TOOL_INTERACTIONS_METADATA_KEY];
96
+ if (toolInteractions && isRecord(interactions)) for (const [toolCallId, value] of Object.entries(interactions)) {
97
+ const log = readToolInteractionLog(value);
98
+ if (log) toolInteractions.set(toolCallId, mergeInteractionLogs(log, toolInteractions.get(toolCallId)));
99
+ }
100
+ const approvalResponses = metadata[TOOL_APPROVAL_RESPONSES_METADATA_KEY];
101
+ if (toolApprovalResponses && isRecord(approvalResponses)) for (const [approvalId, value] of Object.entries(approvalResponses)) {
102
+ if (!isRecord(value) || typeof value.approved !== "boolean") continue;
103
+ const answers = normalizeToolApprovalAnswers(value.answers);
104
+ toolApprovalResponses.set(approvalId, {
105
+ approvalId,
106
+ approved: value.approved,
107
+ ...typeof value.optionId === "string" && { optionId: value.optionId },
108
+ ...typeof value.text === "string" && { text: value.text },
109
+ ...answers && Object.keys(answers).length > 0 && { answers },
110
+ ...typeof value.reason === "string" && { reason: value.reason }
111
+ });
112
+ }
113
+ const { [TOOL_ARTIFACTS_METADATA_KEY]: _, [TOOL_INTERACTIONS_METADATA_KEY]: __, [TOOL_APPROVAL_RESPONSES_METADATA_KEY]: ___, ...restMetadata } = metadata;
114
+ const { metadata: _metadata, ...restMessage } = message;
115
+ return Object.keys(restMetadata).length === 0 ? restMessage : {
116
+ ...restMessage,
117
+ metadata: restMetadata
118
+ };
119
+ };
120
+ export { addToolData, collectToolApprovalResponses, collectToolArtifacts, collectToolInteractions, restoreToolData };
121
+
122
+ //# sourceMappingURL=toolHistoryCodec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toolHistoryCodec.js","names":[],"sources":["../../src/runtime/toolHistoryCodec.ts"],"sourcesContent":["import type {\n RespondToToolApprovalOptions,\n ThreadMessage,\n Unstable_ToolInteractionLog,\n} from \"@ulearning/ai-core\";\nimport {\n appendToolInteraction,\n isJSONValueEqual,\n isRecord,\n readToolInteractionLog,\n} from \"@ulearning/ai-core/internal\";\nimport { normalizeToolApprovalAnswers } from \"../converters/toolApprovalAnswers\";\n\nconst TOOL_ARTIFACTS_METADATA_KEY = \"__aui_toolArtifacts\";\nconst TOOL_INTERACTIONS_METADATA_KEY = \"__aui_toolInteractions\";\nconst TOOL_APPROVAL_RESPONSES_METADATA_KEY = \"__aui_toolApprovalResponses\";\n\nexport type StoredToolApprovalResponse = Omit<\n RespondToToolApprovalOptions,\n \"approvalId\"\n>;\n\nconst mergeInteractionLogs = (\n stored: Unstable_ToolInteractionLog,\n current: Unstable_ToolInteractionLog | undefined,\n): Unstable_ToolInteractionLog => {\n const incoming = readToolInteractionLog(current);\n if (!incoming) return stored;\n const omitted = Math.max(stored.omitted ?? 0, incoming.omitted ?? 0);\n let merged: Unstable_ToolInteractionLog = {\n entries: stored.entries,\n ...(omitted ? { omitted } : undefined),\n };\n for (const entry of incoming.entries) {\n if (\n merged.entries.some(\n (existing) =>\n existing.type === entry.type &&\n existing.occurredAt === entry.occurredAt &&\n isJSONValueEqual(existing.payload, entry.payload),\n )\n ) {\n continue;\n }\n merged = appendToolInteraction(merged, entry);\n }\n return merged;\n};\n\nexport const collectToolArtifacts = (\n message: ThreadMessage,\n toolArtifacts: ReadonlyMap<string, unknown> | undefined,\n) => {\n if (!toolArtifacts) return undefined;\n const entries = message.content.flatMap((part) => {\n if (part.type !== \"tool-call\") return [];\n const artifact = toolArtifacts.get(part.toolCallId);\n return artifact === undefined ? [] : [[part.toolCallId, artifact] as const];\n });\n return entries.length > 0 ? Object.fromEntries(entries) : undefined;\n};\n\nexport const collectToolInteractions = (\n message: ThreadMessage,\n toolInteractions:\n | ReadonlyMap<string, Unstable_ToolInteractionLog>\n | undefined,\n) => {\n if (!toolInteractions) return undefined;\n const entries = message.content.flatMap((part) => {\n if (part.type !== \"tool-call\") return [];\n const interactions = toolInteractions.get(part.toolCallId);\n return interactions === undefined\n ? []\n : [[part.toolCallId, interactions] as const];\n });\n return entries.length > 0 ? Object.fromEntries(entries) : undefined;\n};\n\nexport const collectToolApprovalResponses = (\n message: ThreadMessage,\n toolApprovalResponses:\n | ReadonlyMap<string, RespondToToolApprovalOptions>\n | undefined,\n) => {\n if (!toolApprovalResponses) return undefined;\n const entries = message.content.flatMap((part) => {\n if (part.type !== \"tool-call\" || !part.approval) return [];\n const response = toolApprovalResponses.get(part.approval.id);\n if (!response) return [];\n return [\n [\n part.approval.id,\n {\n approved: response.approved,\n ...(response.optionId != null && { optionId: response.optionId }),\n ...(response.text != null && { text: response.text }),\n ...(response.answers != null && { answers: response.answers }),\n ...(response.reason != null && { reason: response.reason }),\n },\n ] as const,\n ];\n });\n return entries.length > 0 ? Object.fromEntries(entries) : undefined;\n};\n\nexport const addToolData = <TMessage>(\n message: TMessage,\n toolArtifacts: Record<string, unknown> | undefined,\n toolInteractions: Record<string, Unstable_ToolInteractionLog> | undefined,\n toolApprovalResponses: Record<string, StoredToolApprovalResponse> | undefined,\n): TMessage => {\n if (\n (!toolArtifacts && !toolInteractions && !toolApprovalResponses) ||\n !isRecord(message) ||\n !Array.isArray(message.parts)\n )\n return message;\n const toolCallIds = message.parts.flatMap((part) => {\n if (!isRecord(part) || typeof part.toolCallId !== \"string\") return [];\n return [part.toolCallId];\n });\n const artifacts = toolArtifacts\n ? Object.fromEntries(\n toolCallIds.flatMap((toolCallId) =>\n Object.hasOwn(toolArtifacts, toolCallId)\n ? [[toolCallId, toolArtifacts[toolCallId]] as const]\n : [],\n ),\n )\n : undefined;\n const interactions = toolInteractions\n ? Object.fromEntries(\n toolCallIds.flatMap((toolCallId) =>\n Object.hasOwn(toolInteractions, toolCallId)\n ? [[toolCallId, toolInteractions[toolCallId]] as const]\n : [],\n ),\n )\n : undefined;\n const approvalIds = message.parts.flatMap((part) => {\n if (!isRecord(part) || !isRecord(part.approval)) return [];\n const approvalId = part.approval.id;\n return typeof approvalId === \"string\" ? [approvalId] : [];\n });\n const approvalResponses = toolApprovalResponses\n ? Object.fromEntries(\n approvalIds.flatMap((approvalId) =>\n Object.hasOwn(toolApprovalResponses, approvalId)\n ? [[approvalId, toolApprovalResponses[approvalId]] as const]\n : [],\n ),\n )\n : undefined;\n const hasArtifacts = !!artifacts && Object.keys(artifacts).length > 0;\n const hasInteractions =\n !!interactions && Object.keys(interactions).length > 0;\n const hasApprovalResponses =\n !!approvalResponses && Object.keys(approvalResponses).length > 0;\n if (!hasArtifacts && !hasInteractions && !hasApprovalResponses)\n return message;\n const metadata = isRecord(message.metadata) ? message.metadata : {};\n return {\n ...message,\n metadata: {\n ...metadata,\n ...(hasArtifacts && { [TOOL_ARTIFACTS_METADATA_KEY]: artifacts }),\n ...(hasInteractions && {\n [TOOL_INTERACTIONS_METADATA_KEY]: interactions,\n }),\n ...(hasApprovalResponses && {\n [TOOL_APPROVAL_RESPONSES_METADATA_KEY]: approvalResponses,\n }),\n },\n } as TMessage;\n};\n\nexport const restoreToolData = <TMessage>(\n message: TMessage,\n toolArtifacts: Map<string, unknown> | undefined,\n toolInteractions: Map<string, Unstable_ToolInteractionLog> | undefined,\n toolApprovalResponses: Map<string, RespondToToolApprovalOptions> | undefined,\n): TMessage => {\n if (!isRecord(message) || !isRecord(message.metadata)) return message;\n const metadata = message.metadata;\n const hasArtifacts = Object.hasOwn(metadata, TOOL_ARTIFACTS_METADATA_KEY);\n const hasInteractions = Object.hasOwn(\n metadata,\n TOOL_INTERACTIONS_METADATA_KEY,\n );\n const hasApprovalResponses = Object.hasOwn(\n metadata,\n TOOL_APPROVAL_RESPONSES_METADATA_KEY,\n );\n if (!hasArtifacts && !hasInteractions && !hasApprovalResponses)\n return message;\n const artifacts = metadata[TOOL_ARTIFACTS_METADATA_KEY];\n if (toolArtifacts && isRecord(artifacts)) {\n for (const [toolCallId, artifact] of Object.entries(artifacts)) {\n if (!toolArtifacts.has(toolCallId))\n toolArtifacts.set(toolCallId, artifact);\n }\n }\n const interactions = metadata[TOOL_INTERACTIONS_METADATA_KEY];\n if (toolInteractions && isRecord(interactions)) {\n for (const [toolCallId, value] of Object.entries(interactions)) {\n const log = readToolInteractionLog(value);\n if (log) {\n toolInteractions.set(\n toolCallId,\n mergeInteractionLogs(log, toolInteractions.get(toolCallId)),\n );\n }\n }\n }\n const approvalResponses = metadata[TOOL_APPROVAL_RESPONSES_METADATA_KEY];\n if (toolApprovalResponses && isRecord(approvalResponses)) {\n for (const [approvalId, value] of Object.entries(approvalResponses)) {\n if (!isRecord(value) || typeof value.approved !== \"boolean\") continue;\n const answers = normalizeToolApprovalAnswers(value.answers);\n toolApprovalResponses.set(approvalId, {\n approvalId,\n approved: value.approved,\n ...(typeof value.optionId === \"string\" && {\n optionId: value.optionId,\n }),\n ...(typeof value.text === \"string\" && { text: value.text }),\n ...(answers && Object.keys(answers).length > 0 && { answers }),\n ...(typeof value.reason === \"string\" && { reason: value.reason }),\n });\n }\n }\n const {\n [TOOL_ARTIFACTS_METADATA_KEY]: _,\n [TOOL_INTERACTIONS_METADATA_KEY]: __,\n [TOOL_APPROVAL_RESPONSES_METADATA_KEY]: ___,\n ...restMetadata\n } = metadata;\n const { metadata: _metadata, ...restMessage } = message;\n return (\n Object.keys(restMetadata).length === 0\n ? restMessage\n : { ...restMessage, metadata: restMetadata }\n ) as TMessage;\n};\n"],"mappings":"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"}
@@ -0,0 +1,95 @@
1
+ import type { UIMessage, CreateUIMessage } from "ai";
2
+ import { type JoinStrategy } from "@ulearning/ai-core/vue";
3
+ import type { SuggestionAdapter } from "@ulearning/ai-core";
4
+ import type { ExternalStoreAdapter, ExternalStoreSharedOptions, ThreadHistoryAdapter, AssistantRuntime, MessageFormatRepository, AppendMessage, RespondToToolApprovalOptions } from "@ulearning/ai-core";
5
+ import { MessageRepository } from "@ulearning/ai-core/internal";
6
+ import { type MaybeRefOrGetter } from "vue";
7
+ import { type AISDKChatHelpers } from "../aiSDKExtras.js";
8
+ export type CustomToCreateMessageFunction = <UI_MESSAGE extends UIMessage = UIMessage>(message: AppendMessage) => CreateUIMessage<UI_MESSAGE>;
9
+ export type AISDKRuntimeAdapter<UI_MESSAGE extends UIMessage = UIMessage> = ExternalStoreSharedOptions & {
10
+ adapters?: (NonNullable<ExternalStoreAdapter["adapters"]> & {
11
+ history?: ThreadHistoryAdapter | undefined;
12
+ suggestion?: SuggestionAdapter | undefined;
13
+ }) | undefined;
14
+ toCreateMessage?: CustomToCreateMessageFunction;
15
+ /** @deprecated Experimental since 2026-08-28. Not scheduled for removal; the API may change in any release. */
16
+ unstable_messageRepositoryInstance?: MessageRepository | undefined;
17
+ /**
18
+ * The object a host answer belongs to, normally the `Chat` the runtime
19
+ * renders. A host answer never reaches the `useChat` messages, so without
20
+ * an owner it lives only as long as this runtime. With an owner, it
21
+ * survives runtime remounts over the same chat.
22
+ *
23
+ * @deprecated Experimental since 2026-09-29. Not scheduled for removal; the API may change in any release.
24
+ */
25
+ unstable_hostApprovalOwner?: object | undefined;
26
+ /**
27
+ * Whether to automatically cancel pending interactive tool calls when the user sends a new message.
28
+ *
29
+ * When enabled (default), the pending tool calls will be marked as failed with an error message
30
+ * indicating the user cancelled the tool call by sending a new message.
31
+ *
32
+ * @default true
33
+ */
34
+ cancelPendingToolCallsOnSend?: boolean | undefined;
35
+ /**
36
+ * Holds messages sent during a run in `composer.queue` until the run
37
+ * settles. Steered messages dispatch before queued follow-ups.
38
+ * @deprecated Experimental since 2026-10-15. Not scheduled for removal; the API may change in any release.
39
+ */
40
+ unstable_enableMessageQueue?: boolean | undefined;
41
+ /**
42
+ * Called when `runtime.thread.resumeRun(config)` is invoked.
43
+ *
44
+ * When omitted, `resumeRun` throws `"Runtime does not support resuming runs."`.
45
+ * Provide this to bridge resume invocations into a custom replay channel
46
+ * (for example, an SSE reconnect endpoint keyed by turn id).
47
+ */
48
+ onResume?: ExternalStoreAdapter["onResume"];
49
+ canResume?: ExternalStoreAdapter["canResume"];
50
+ /**
51
+ * Called when `runtime.thread.resumeToolCall(options)` is invoked for a tool call the in-process tracker does not own.
52
+ *
53
+ * When omitted, `resumeToolCall` throws `"Tool call ${toolCallId} is not waiting for resume."`.
54
+ * Provide this to bridge resume-tool-call invocations into a custom handler.
55
+ */
56
+ onResumeToolCall?: ExternalStoreAdapter["onResumeToolCall"];
57
+ /**
58
+ * Answers tool approval requests through a host-owned channel instead of the AI SDK's `addToolApprovalResponse`.
59
+ *
60
+ * 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. With a history adapter, the answer is stored with its message once the handler resolves and returns on reload. With `unstable_hostApprovalOwner`, in-memory answers survive runtime remounts over the same chat; without an owner or history adapter, they last only as long as the runtime. Bring the resumed run back into the chat, for example with `resumeStream`, and have the endpoint refuse a second resume.
61
+ *
62
+ * While a handler is set, an approval's `display`, `allowFreeform`, `dismissible` and `options` reach the renderer, because the handler can receive answers the AI SDK cannot carry. A stream declares them through the `approvalDescriptor` of its `tool-approval-request` chunk, the one approval field the AI SDK keeps opaque; the converter reads the request and answer fields from that descriptor when the approval itself lacks them.
63
+ */
64
+ onRespondToToolApproval?: ((response: RespondToToolApprovalOptions, context: {
65
+ toolCallId: string;
66
+ toolName: string;
67
+ /** Sends this response through the AI SDK's `addToolApprovalResponse`, which carries only `approved` and `reason`. */
68
+ respondViaAISDK: () => Promise<void>;
69
+ }) => Promise<void> | void) | undefined;
70
+ /**
71
+ * How consecutive assistant messages are rendered.
72
+ *
73
+ * `"concat-content"` (the default) merges them into a single thread message.
74
+ * `"none"` keeps each assistant message as its own thread message, which is
75
+ * useful when a backend persists proactive or consecutive assistant messages
76
+ * as separate entries.
77
+ */
78
+ joinStrategy?: JoinStrategy | undefined;
79
+ /**
80
+ * A branch-aware AI SDK message tree seeded once when `useChat` is empty.
81
+ * After that seed, live updates come only from `useChat`. A later empty
82
+ * chat or a new object identity does not reload the tree.
83
+ */
84
+ messageRepository?: MessageFormatRepository<UI_MESSAGE>;
85
+ /**
86
+ * Called after an explicit `switchToBranch` (for example a BranchPicker
87
+ * click). Complements `setMessages` and does not enable switching by itself.
88
+ *
89
+ * @deprecated Experimental since 2026-06-23. Not scheduled for removal; the API may change in any release.
90
+ */
91
+ unstable_onBranchChange?: ExternalStoreAdapter["unstable_onBranchChange"];
92
+ };
93
+ /** Vue setup owns the resource; reactive helper/adapter getters stay live. */
94
+ export declare const useAISDKRuntime: <UI_MESSAGE extends UIMessage = UIMessage>(helpers: MaybeRefOrGetter<AISDKChatHelpers<UI_MESSAGE>>, adapter?: MaybeRefOrGetter<AISDKRuntimeAdapter<UI_MESSAGE>>) => AssistantRuntime;
95
+ //# sourceMappingURL=useAISDKRuntime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAISDKRuntime.d.ts","mappings":"AAWA,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,IAAI;AAEpD,OAAO,EAEL,KAAK,YAAY,EAClB,MAAM,wBAAwB;AAE/B,OAAO,KAAK,EACV,iBAAiB,EAGlB,MAAM,oBAAoB;AAC3B,OAAO,KAAK,EACV,oBAAoB,EACpB,0BAA0B,EAC1B,oBAAoB,EACpB,gBAAgB,EAIhB,uBAAuB,EACvB,aAAa,EAGb,4BAA4B,EAE7B,MAAM,oBAAoB;AAW3B,OAAO,EAGL,iBAAiB,EAClB,MAAM,6BAA6B;AAwBpC,OAAO,EAAW,KAAK,gBAAgB,EAAE,MAAM,KAAK;AAEpD,OAAO,EAAe,KAAK,gBAAgB,EAAE,MAAM,mBAAgB;AAEnE,MAAM,MAAM,6BAA6B,GAAG,CAC1C,UAAU,SAAS,SAAS,GAAG,SAAS,EAExC,OAAO,EAAE,aAAa,KACnB,eAAe,CAAC,UAAU,CAAC;AA6BhC,MAAM,MAAM,mBAAmB,CAAC,UAAU,SAAS,SAAS,GAAG,SAAS,IACtE,0BAA0B,GAAG;IAC3B,QAAQ,CAAC,EACL,CAAC,WAAW,CAAC,oBAAoB,CAAC,UAAU,CAAC,CAAC,GAAG;QAC/C,OAAO,CAAC,EAAE,oBAAoB,GAAG,SAAS;QAC1C,UAAU,CAAC,EAAE,iBAAiB,GAAG,SAAS;KAC3C,CAAC,GACF,SAAS;IACb,eAAe,CAAC,EAAE,6BAA6B;IAC/C;IACA,kCAAkC,CAAC,EAAE,iBAAiB,GAAG,SAAS;IAClE;;;;;;;;IAQA,0BAA0B,CAAC,EAAE,MAAM,GAAG,SAAS;IAC/C;;;;;;;;IAQA,4BAA4B,CAAC,EAAE,OAAO,GAAG,SAAS;IAClD;;;;;IAKA,2BAA2B,CAAC,EAAE,OAAO,GAAG,SAAS;IACjD;;;;;;;IAOA,QAAQ,CAAC,EAAE,oBAAoB,CAAC,UAAU,CAAC;IAC3C,SAAS,CAAC,EAAE,oBAAoB,CAAC,WAAW,CAAC;IAC7C;;;;;;IAMA,gBAAgB,CAAC,EAAE,oBAAoB,CAAC,kBAAkB,CAAC;IAC3D;;;;;;;IAOA,uBAAuB,CAAC,EACpB,CAAC,CACC,QAAQ,EAAE,4BAA4B,EACtC,OAAO,EAAE;QACP,UAAU,EAAE,MAAM;QAClB,QAAQ,EAAE,MAAM;QAChB;QACA,eAAe,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC;KACrC,KACE,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,GAC1B,SAAS;IACb;;;;;;;;IAQA,YAAY,CAAC,EAAE,YAAY,GAAG,SAAS;IACvC;;;;;IAKA,iBAAiB,CAAC,EAAE,uBAAuB,CAAC,UAAU,CAAC;IACvD;;;;;;IAMA,uBAAuB,CAAC,EAAE,oBAAoB,CAAC,yBAAyB,CAAC;CAC1E;AAwwCH;AACA,eAAO,MAAM,eAAe,GAAI,UAAU,SAAS,SAAS,GAAG,SAAS,EACtE,SAAS,gBAAgB,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC,EACvD,UAAS,gBAAgB,CAAC,mBAAmB,CAAC,UAAU,CAAC,CAAM,KAC9D,gBAMF","names":[],"ignoreList":[],"sources":["../../src/runtime/useAISDKRuntime.ts"],"sourcesContent":[null]}