@convex-dev/agent 0.6.3 → 0.7.0-alpha.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 (246) hide show
  1. package/MIGRATION.md +60 -116
  2. package/dist/client/messages.d.ts +1 -398
  3. package/dist/client/messages.d.ts.map +1 -1
  4. package/dist/client/messages.js +3 -47
  5. package/dist/client/messages.js.map +1 -1
  6. package/dist/client/types.d.ts +1 -455
  7. package/dist/client/types.d.ts.map +1 -1
  8. package/dist/component/_generated/component.d.ts +805 -45
  9. package/dist/component/_generated/component.d.ts.map +1 -1
  10. package/dist/component/apiKeys.js +5 -5
  11. package/dist/component/apiKeys.js.map +1 -1
  12. package/dist/component/files.d.ts.map +1 -1
  13. package/dist/component/files.js +13 -11
  14. package/dist/component/files.js.map +1 -1
  15. package/dist/component/messages.d.ts +1252 -201
  16. package/dist/component/messages.d.ts.map +1 -1
  17. package/dist/component/messages.js +83 -47
  18. package/dist/component/messages.js.map +1 -1
  19. package/dist/component/schema.d.ts +2593 -332
  20. package/dist/component/schema.d.ts.map +1 -1
  21. package/dist/component/streams.d.ts +7 -1
  22. package/dist/component/streams.d.ts.map +1 -1
  23. package/dist/component/streams.js +46 -47
  24. package/dist/component/streams.js.map +1 -1
  25. package/dist/component/threads.d.ts.map +1 -1
  26. package/dist/component/threads.js +8 -9
  27. package/dist/component/threads.js.map +1 -1
  28. package/dist/component/users.js +2 -2
  29. package/dist/component/users.js.map +1 -1
  30. package/dist/component/vector/index.d.ts.map +1 -1
  31. package/dist/component/vector/index.js +14 -8
  32. package/dist/component/vector/index.js.map +1 -1
  33. package/dist/react/index.d.ts +5 -5
  34. package/dist/react/index.d.ts.map +1 -1
  35. package/dist/react/index.js +5 -5
  36. package/dist/react/index.js.map +1 -1
  37. package/dist/shared.d.ts +19 -7
  38. package/dist/shared.d.ts.map +1 -1
  39. package/dist/shared.js +4 -4
  40. package/dist/shared.js.map +1 -1
  41. package/dist/streaming/materializePersistedUIMessageChunks.d.ts +16 -0
  42. package/dist/streaming/materializePersistedUIMessageChunks.d.ts.map +1 -0
  43. package/dist/streaming/materializePersistedUIMessageChunks.js +302 -0
  44. package/dist/streaming/materializePersistedUIMessageChunks.js.map +1 -0
  45. package/dist/streaming/persistedUIMessageChunks.d.ts +106 -0
  46. package/dist/streaming/persistedUIMessageChunks.d.ts.map +1 -0
  47. package/dist/streaming/persistedUIMessageChunks.js +475 -0
  48. package/dist/streaming/persistedUIMessageChunks.js.map +1 -0
  49. package/dist/validators.d.ts +10026 -1055
  50. package/dist/validators.d.ts.map +1 -1
  51. package/dist/validators.js +71 -9
  52. package/dist/validators.js.map +1 -1
  53. package/dist/{UIMessages.d.ts → vercel/UIMessages.d.ts} +1 -1
  54. package/dist/vercel/UIMessages.d.ts.map +1 -0
  55. package/dist/{UIMessages.js → vercel/UIMessages.js} +63 -1
  56. package/dist/vercel/UIMessages.js.map +1 -0
  57. package/dist/{client → vercel/client}/createTool.d.ts +23 -16
  58. package/dist/vercel/client/createTool.d.ts.map +1 -0
  59. package/dist/{client → vercel/client}/createTool.js +2 -0
  60. package/dist/vercel/client/createTool.js.map +1 -0
  61. package/dist/{client → vercel/client}/definePlaygroundAPI.d.ts +593 -134
  62. package/dist/{client → vercel/client}/definePlaygroundAPI.d.ts.map +1 -1
  63. package/dist/{client → vercel/client}/definePlaygroundAPI.js +13 -9
  64. package/dist/vercel/client/definePlaygroundAPI.js.map +1 -0
  65. package/dist/{client → vercel/client}/files.d.ts +2 -2
  66. package/dist/vercel/client/files.d.ts.map +1 -0
  67. package/dist/vercel/client/files.js.map +1 -0
  68. package/dist/vercel/client/messages.d.ts +542 -0
  69. package/dist/vercel/client/messages.d.ts.map +1 -0
  70. package/dist/vercel/client/messages.js +66 -0
  71. package/dist/vercel/client/messages.js.map +1 -0
  72. package/dist/{client → vercel/client}/mockModel.d.ts +17 -17
  73. package/dist/vercel/client/mockModel.d.ts.map +1 -0
  74. package/dist/{client → vercel/client}/mockModel.js +12 -13
  75. package/dist/vercel/client/mockModel.js.map +1 -0
  76. package/dist/{client → vercel/client}/saveInputMessages.d.ts +2 -2
  77. package/dist/vercel/client/saveInputMessages.d.ts.map +1 -0
  78. package/dist/vercel/client/saveInputMessages.js.map +1 -0
  79. package/dist/{client → vercel/client}/search.d.ts +119 -22
  80. package/dist/vercel/client/search.d.ts.map +1 -0
  81. package/dist/{client → vercel/client}/search.js +2 -2
  82. package/dist/vercel/client/search.js.map +1 -0
  83. package/dist/{client → vercel/client}/start.d.ts +26 -11
  84. package/dist/vercel/client/start.d.ts.map +1 -0
  85. package/dist/{client → vercel/client}/start.js +64 -22
  86. package/dist/vercel/client/start.js.map +1 -0
  87. package/dist/{client → vercel/client}/streamText.d.ts +13 -12
  88. package/dist/vercel/client/streamText.d.ts.map +1 -0
  89. package/dist/{client → vercel/client}/streamText.js +43 -9
  90. package/dist/vercel/client/streamText.js.map +1 -0
  91. package/dist/{client → vercel/client}/streaming.d.ts +1410 -183
  92. package/dist/vercel/client/streaming.d.ts.map +1 -0
  93. package/dist/{client → vercel/client}/streaming.js +120 -52
  94. package/dist/vercel/client/streaming.js.map +1 -0
  95. package/dist/vercel/client/types.d.ts +456 -0
  96. package/dist/vercel/client/types.d.ts.map +1 -0
  97. package/dist/vercel/client/types.js +3 -0
  98. package/dist/vercel/client/types.js.map +1 -0
  99. package/dist/{client → vercel/client}/utils.d.ts +3 -2
  100. package/dist/vercel/client/utils.d.ts.map +1 -0
  101. package/dist/{client → vercel/client}/utils.js +2 -2
  102. package/dist/vercel/client/utils.js.map +1 -0
  103. package/dist/vercel/deltas.d.ts +31 -0
  104. package/dist/vercel/deltas.d.ts.map +1 -0
  105. package/dist/vercel/deltas.js +525 -0
  106. package/dist/vercel/deltas.js.map +1 -0
  107. package/dist/{client → vercel}/index.d.ts +484 -97
  108. package/dist/vercel/index.d.ts.map +1 -0
  109. package/dist/{client → vercel}/index.js +65 -38
  110. package/dist/vercel/index.js.map +1 -0
  111. package/dist/{mapping.d.ts → vercel/mapping.d.ts} +5 -13
  112. package/dist/vercel/mapping.d.ts.map +1 -0
  113. package/dist/{mapping.js → vercel/mapping.js} +411 -112
  114. package/dist/vercel/mapping.js.map +1 -0
  115. package/dist/{react → vercel/react}/optimisticallySendMessage.d.ts +2 -2
  116. package/dist/vercel/react/optimisticallySendMessage.d.ts.map +1 -0
  117. package/dist/vercel/react/optimisticallySendMessage.js.map +1 -0
  118. package/dist/{react → vercel/react}/types.d.ts +1 -1
  119. package/dist/vercel/react/types.d.ts.map +1 -0
  120. package/dist/{react → vercel/react}/types.js.map +1 -1
  121. package/dist/{react → vercel/react}/useDeltaStreams.d.ts +1 -1
  122. package/dist/vercel/react/useDeltaStreams.d.ts.map +1 -0
  123. package/dist/{react → vercel/react}/useDeltaStreams.js +1 -1
  124. package/dist/vercel/react/useDeltaStreams.js.map +1 -0
  125. package/dist/{react → vercel/react}/useStreamingUIMessages.d.ts +1 -1
  126. package/dist/vercel/react/useStreamingUIMessages.d.ts.map +1 -0
  127. package/dist/vercel/react/useStreamingUIMessages.js +112 -0
  128. package/dist/vercel/react/useStreamingUIMessages.js.map +1 -0
  129. package/dist/{react → vercel/react}/useThreadMessages.d.ts +1 -1
  130. package/dist/vercel/react/useThreadMessages.d.ts.map +1 -0
  131. package/dist/{react → vercel/react}/useThreadMessages.js +1 -1
  132. package/dist/vercel/react/useThreadMessages.js.map +1 -0
  133. package/dist/{react → vercel/react}/useUIMessages.d.ts +2 -1
  134. package/dist/vercel/react/useUIMessages.d.ts.map +1 -0
  135. package/dist/{react → vercel/react}/useUIMessages.js +8 -4
  136. package/dist/vercel/react/useUIMessages.js.map +1 -0
  137. package/package.json +30 -22
  138. package/src/client/messages.ts +5 -107
  139. package/src/client/types.ts +0 -621
  140. package/src/component/_generated/component.ts +1089 -48
  141. package/src/component/apiKeys.ts +5 -5
  142. package/src/component/files.test.ts +1 -1
  143. package/src/component/files.ts +14 -12
  144. package/src/component/messages.test.ts +273 -1
  145. package/src/component/messages.ts +99 -57
  146. package/src/component/streams.ts +80 -64
  147. package/src/component/threads.ts +12 -9
  148. package/src/component/users.ts +2 -2
  149. package/src/component/vector/index.ts +14 -7
  150. package/src/eslintConfig.test.ts +44 -0
  151. package/src/react/index.ts +8 -5
  152. package/src/shared.ts +26 -36
  153. package/src/streaming/materializePersistedUIMessageChunks.test.ts +513 -0
  154. package/src/streaming/materializePersistedUIMessageChunks.ts +398 -0
  155. package/src/streaming/persistedUIMessageChunks.test.ts +205 -0
  156. package/src/streaming/persistedUIMessageChunks.ts +658 -0
  157. package/src/validators.test.ts +4 -1
  158. package/src/validators.ts +89 -8
  159. package/src/{UIMessages.combineUIMessages.test.ts → vercel/UIMessages.combineUIMessages.test.ts} +4 -1
  160. package/src/{UIMessages.ts → vercel/UIMessages.ts} +96 -5
  161. package/src/{client → vercel/client}/approval.test.ts +48 -19
  162. package/src/{client → vercel/client}/createTool.ts +63 -23
  163. package/src/{client → vercel/client}/definePlaygroundAPI.ts +44 -29
  164. package/src/{client → vercel/client}/files.ts +2 -2
  165. package/src/{client → vercel/client}/index.test.ts +162 -3
  166. package/src/vercel/client/messages.ts +182 -0
  167. package/src/{client → vercel/client}/mockModel.ts +38 -39
  168. package/src/{client → vercel/client}/saveInputMessages.test.ts +1 -1
  169. package/src/{client → vercel/client}/saveInputMessages.ts +7 -4
  170. package/src/{client → vercel/client}/search.test.ts +3 -3
  171. package/src/{client → vercel/client}/search.ts +4 -4
  172. package/src/{client → vercel/client}/setup.test.ts +6 -3
  173. package/src/vercel/client/start.test.ts +14 -0
  174. package/src/{client → vercel/client}/start.ts +147 -36
  175. package/src/vercel/client/streamText.test.ts +223 -0
  176. package/src/{client → vercel/client}/streamText.ts +102 -31
  177. package/src/{client → vercel/client}/streaming.integration.test.ts +40 -115
  178. package/src/{client → vercel/client}/streaming.test.ts +178 -4
  179. package/src/{client → vercel/client}/streaming.ts +114 -52
  180. package/src/vercel/client/types.test.ts +13 -0
  181. package/src/vercel/client/types.ts +679 -0
  182. package/src/{client → vercel/client}/utils.ts +13 -7
  183. package/src/vercel/deltas.test.ts +898 -0
  184. package/src/vercel/deltas.ts +633 -0
  185. package/src/{fromUIMessages.test.ts → vercel/fromUIMessages.test.ts} +17 -1
  186. package/src/{client → vercel}/index.ts +169 -62
  187. package/src/vercel/mapping.test.ts +965 -0
  188. package/src/{mapping.ts → vercel/mapping.ts} +501 -131
  189. package/src/{react → vercel/react}/optimisticallySendMessage.ts +2 -2
  190. package/src/{react → vercel/react}/types.ts +1 -1
  191. package/src/{react → vercel/react}/useDeltaStreams.ts +6 -2
  192. package/src/{react → vercel/react}/useStreamingUIMessages.ts +67 -35
  193. package/src/{react → vercel/react}/useThreadMessages.ts +2 -2
  194. package/src/{react → vercel/react}/useUIMessages.test.ts +80 -1
  195. package/src/{react → vercel/react}/useUIMessages.ts +13 -5
  196. package/src/{toUIMessages.test.ts → vercel/toUIMessages.test.ts} +49 -2
  197. package/dist/UIMessages.d.ts.map +0 -1
  198. package/dist/UIMessages.js.map +0 -1
  199. package/dist/client/createTool.d.ts.map +0 -1
  200. package/dist/client/createTool.js.map +0 -1
  201. package/dist/client/definePlaygroundAPI.js.map +0 -1
  202. package/dist/client/files.d.ts.map +0 -1
  203. package/dist/client/files.js.map +0 -1
  204. package/dist/client/index.d.ts.map +0 -1
  205. package/dist/client/index.js.map +0 -1
  206. package/dist/client/mockModel.d.ts.map +0 -1
  207. package/dist/client/mockModel.js.map +0 -1
  208. package/dist/client/saveInputMessages.d.ts.map +0 -1
  209. package/dist/client/saveInputMessages.js.map +0 -1
  210. package/dist/client/search.d.ts.map +0 -1
  211. package/dist/client/search.js.map +0 -1
  212. package/dist/client/start.d.ts.map +0 -1
  213. package/dist/client/start.js.map +0 -1
  214. package/dist/client/streamText.d.ts.map +0 -1
  215. package/dist/client/streamText.js.map +0 -1
  216. package/dist/client/streaming.d.ts.map +0 -1
  217. package/dist/client/streaming.js.map +0 -1
  218. package/dist/client/utils.d.ts.map +0 -1
  219. package/dist/client/utils.js.map +0 -1
  220. package/dist/deltas.d.ts +0 -43
  221. package/dist/deltas.d.ts.map +0 -1
  222. package/dist/deltas.js +0 -446
  223. package/dist/deltas.js.map +0 -1
  224. package/dist/mapping.d.ts.map +0 -1
  225. package/dist/mapping.js.map +0 -1
  226. package/dist/react/optimisticallySendMessage.d.ts.map +0 -1
  227. package/dist/react/optimisticallySendMessage.js.map +0 -1
  228. package/dist/react/types.d.ts.map +0 -1
  229. package/dist/react/useDeltaStreams.d.ts.map +0 -1
  230. package/dist/react/useDeltaStreams.js.map +0 -1
  231. package/dist/react/useStreamingUIMessages.d.ts.map +0 -1
  232. package/dist/react/useStreamingUIMessages.js +0 -92
  233. package/dist/react/useStreamingUIMessages.js.map +0 -1
  234. package/dist/react/useThreadMessages.d.ts.map +0 -1
  235. package/dist/react/useThreadMessages.js.map +0 -1
  236. package/dist/react/useUIMessages.d.ts.map +0 -1
  237. package/dist/react/useUIMessages.js.map +0 -1
  238. package/src/client/streamText.test.ts +0 -102
  239. package/src/deltas.test.ts +0 -626
  240. package/src/deltas.ts +0 -569
  241. package/src/mapping.test.ts +0 -402
  242. /package/dist/{client → vercel/client}/files.js +0 -0
  243. /package/dist/{client → vercel/client}/saveInputMessages.js +0 -0
  244. /package/dist/{react → vercel/react}/optimisticallySendMessage.js +0 -0
  245. /package/dist/{react → vercel/react}/types.js +0 -0
  246. /package/src/{UIMessages.test.ts → vercel/UIMessages.test.ts} +0 -0
@@ -1,9 +1,9 @@
1
1
  import {} from "ai";
2
- import { vMessageWithMetadata, vToolResultOutput, vToolApprovalRequest, vToolApprovalResponse, } from "./validators.js";
2
+ import { vMessageWithMetadata, vToolResultOutput, vToolApprovalRequest, vToolApprovalResponse, vProviderReference, } from "../validators.js";
3
3
  import { MAX_FILE_SIZE, storeFile } from "./client/files.js";
4
4
  import { convertUint8ArrayToBase64, } from "@ai-sdk/provider-utils";
5
5
  import { parse, validate } from "convex-helpers/validators";
6
- import { getModelName, getProviderName, } from "./shared.js";
6
+ import { getModelName, getProviderName, } from "../shared.js";
7
7
  export async function serializeMessage(ctx, component, message) {
8
8
  const { content, fileIds } = await serializeContent(ctx, component, message.content);
9
9
  return {
@@ -126,31 +126,15 @@ export function autoDenyUnresolvedApprovals(messages) {
126
126
  }
127
127
  export function serializeUsage(usage) {
128
128
  return {
129
- promptTokens: usage.inputTokens ?? 0,
130
- completionTokens: usage.outputTokens ?? 0,
131
- totalTokens: usage.totalTokens ?? 0,
132
- reasoningTokens: usage.reasoningTokens,
133
- cachedInputTokens: usage.cachedInputTokens,
134
- };
135
- }
136
- export function toModelMessageUsage(usage) {
137
- return {
138
- inputTokens: usage.promptTokens,
139
- outputTokens: usage.completionTokens,
129
+ promptTokens: usage.inputTokens,
130
+ completionTokens: usage.outputTokens,
140
131
  totalTokens: usage.totalTokens,
141
- reasoningTokens: usage.reasoningTokens,
142
- cachedInputTokens: usage.cachedInputTokens,
143
- // These detail fields are required by LanguageModelUsage type but we don't
144
- // have the granular data, so we provide empty objects with undefined values.
145
- inputTokenDetails: {
146
- cacheReadTokens: undefined,
147
- cacheWriteTokens: undefined,
148
- noCacheTokens: undefined,
149
- },
150
- outputTokenDetails: {
151
- textTokens: undefined,
152
- reasoningTokens: undefined,
153
- },
132
+ reasoningTokens: usage.outputTokenDetails?.reasoningTokens,
133
+ cachedInputTokens: usage.inputTokenDetails?.cacheReadTokens,
134
+ nonCachedInputTokens: usage.inputTokenDetails?.noCacheTokens,
135
+ cacheWriteInputTokens: usage.inputTokenDetails?.cacheWriteTokens,
136
+ textOutputTokens: usage.outputTokenDetails?.textTokens,
137
+ raw: usage.raw,
154
138
  };
155
139
  }
156
140
  export function serializeWarnings(warnings) {
@@ -158,29 +142,23 @@ export function serializeWarnings(warnings) {
158
142
  return undefined;
159
143
  }
160
144
  return warnings.map((warning) => {
161
- if (warning.type === "compatibility") {
162
- return {
163
- type: "unsupported-setting",
164
- setting: warning.feature,
165
- details: warning.details,
166
- };
167
- }
168
- return warning;
169
- });
170
- }
171
- export function toModelMessageWarnings(warnings) {
172
- if (!warnings) {
173
- return undefined;
174
- }
175
- return warnings.map((warning) => {
176
- if (warning.type === "unsupported-setting") {
177
- return {
178
- type: "compatibility",
179
- feature: warning.setting,
180
- details: warning.details,
181
- };
145
+ switch (warning.type) {
146
+ case "unsupported":
147
+ case "compatibility":
148
+ return {
149
+ type: warning.type,
150
+ feature: warning.feature,
151
+ details: warning.details,
152
+ };
153
+ case "deprecated":
154
+ return {
155
+ type: warning.type,
156
+ setting: warning.setting,
157
+ message: warning.message,
158
+ };
159
+ case "other":
160
+ return { type: warning.type, message: warning.message };
182
161
  }
183
- return warning;
184
162
  });
185
163
  }
186
164
  /**
@@ -191,34 +169,17 @@ export function toModelMessageWarnings(warnings) {
191
169
  export async function serializeResponseMessages(ctx, component, step, model, responseMessages) {
192
170
  return serializeStepMessages(ctx, component, step, model, responseMessages);
193
171
  }
194
- /**
195
- * Serialize the new messages from a step using a heuristic to determine
196
- * which response messages are new (last 1-2 messages).
197
- */
198
- export async function serializeNewMessagesInStep(ctx, component, step, model) {
199
- const hasToolMessage = step.response.messages.at(-1)?.role === "tool";
200
- let messagesToSerialize;
201
- if (hasToolMessage) {
202
- messagesToSerialize = step.response.messages.slice(-2);
203
- }
204
- else if (step.content.length) {
205
- messagesToSerialize = step.response.messages.slice(-1);
206
- }
207
- else {
208
- messagesToSerialize = [{ role: "assistant", content: [] }];
209
- }
210
- return serializeStepMessages(ctx, component, step, model, messagesToSerialize);
211
- }
212
172
  async function serializeStepMessages(ctx, component, step, model, messagesToSerialize) {
213
173
  // If there are tool results, there's another message with the tool results
214
174
  // ref: https://github.com/vercel/ai/blob/main/packages/ai/src/generate-text/to-response-messages.ts#L120
215
175
  const hasToolMessage = step.response.messages.at(-1)?.role === "tool";
176
+ const resolvedModel = step.model ?? model;
216
177
  const assistantFields = {
217
- model: model ? getModelName(model) : undefined,
218
- provider: model ? getProviderName(model) : undefined,
178
+ model: resolvedModel ? getModelName(resolvedModel) : undefined,
179
+ provider: resolvedModel ? getProviderName(resolvedModel) : undefined,
219
180
  providerMetadata: step.providerMetadata,
220
181
  reasoning: step.reasoningText,
221
- reasoningDetails: step.reasoning,
182
+ reasoningDetails: step.reasoning.filter((part) => part.type !== "reasoning-file"),
222
183
  usage: serializeUsage(step.usage),
223
184
  warnings: serializeWarnings(step.warnings),
224
185
  finishReason: step.finishReason,
@@ -235,7 +196,6 @@ async function serializeStepMessages(ctx, component, step, model, messagesToSeri
235
196
  fileIds,
236
197
  });
237
198
  }));
238
- // TODO: capture step.files separately?
239
199
  return { messages };
240
200
  }
241
201
  export async function serializeObjectResult(ctx, component, result, model) {
@@ -291,7 +251,8 @@ export async function serializeContent(ctx, component, content) {
291
251
  };
292
252
  }
293
253
  case "image": {
294
- let image = serializeDataOrUrl(part.image);
254
+ let image = toStoredProviderReference(part.image) ??
255
+ serializeDataOrUrl(part.image);
295
256
  if (image instanceof ArrayBuffer &&
296
257
  image.byteLength > MAX_FILE_SIZE) {
297
258
  const { file } = await storeFile(ctx, component, new Blob([image], {
@@ -308,7 +269,8 @@ export async function serializeContent(ctx, component, content) {
308
269
  };
309
270
  }
310
271
  case "file": {
311
- let data = serializeDataOrUrl(part.data);
272
+ let data = toStoredProviderReference(part.data) ??
273
+ serializeDataOrUrl(part.data);
312
274
  if (data instanceof ArrayBuffer && data.byteLength > MAX_FILE_SIZE) {
313
275
  const { file } = await storeFile(ctx, component, new Blob([data], { type: getMimeOrMediaType(part) }));
314
276
  data = file.url;
@@ -333,16 +295,36 @@ export async function serializeContent(ctx, component, content) {
333
295
  toolCallId: part.toolCallId,
334
296
  toolName: part.toolName,
335
297
  providerExecuted: part.providerExecuted,
298
+ title: "title" in part ? part.title : undefined,
299
+ toolMetadata: "toolMetadata" in part ? part.toolMetadata : undefined,
336
300
  ...metadata,
337
301
  };
338
302
  }
339
303
  case "tool-result": {
340
- return normalizeToolResult(part, metadata);
304
+ return serializeToolResult(part, metadata);
341
305
  }
342
306
  case "reasoning": {
343
307
  return {
344
308
  type: part.type,
345
309
  text: part.text,
310
+ signature: "signature" in part && typeof part.signature === "string"
311
+ ? part.signature
312
+ : undefined,
313
+ ...metadata,
314
+ };
315
+ }
316
+ case "reasoning-file": {
317
+ return {
318
+ type: part.type,
319
+ ...serializeReasoningFile(part),
320
+ mediaType: part.mediaType,
321
+ ...metadata,
322
+ };
323
+ }
324
+ case "custom": {
325
+ return {
326
+ type: part.type,
327
+ kind: part.kind,
346
328
  ...metadata,
347
329
  };
348
330
  }
@@ -362,6 +344,8 @@ export async function serializeContent(ctx, component, content) {
362
344
  type: part.type,
363
345
  approvalId: part.approvalId,
364
346
  toolCallId: part.toolCallId,
347
+ isAutomatic: "isAutomatic" in part ? part.isAutomatic : undefined,
348
+ signature: "signature" in part ? part.signature : undefined,
365
349
  ...metadata,
366
350
  };
367
351
  }
@@ -405,12 +389,14 @@ export function fromModelMessageContent(content) {
405
389
  type: part.type,
406
390
  mediaType: getMimeOrMediaType(part),
407
391
  ...metadata,
408
- image: serializeDataOrUrl(part.image),
392
+ image: toStoredProviderReference(part.image) ??
393
+ serializeDataOrUrl(part.image),
409
394
  };
410
395
  case "file":
411
396
  return {
412
397
  type: part.type,
413
- data: serializeDataOrUrl(part.data),
398
+ data: toStoredProviderReference(part.data) ??
399
+ serializeDataOrUrl(part.data),
414
400
  filename: part.filename,
415
401
  mediaType: getMimeOrMediaType(part),
416
402
  ...metadata,
@@ -428,11 +414,28 @@ export function fromModelMessageContent(content) {
428
414
  ...metadata,
429
415
  };
430
416
  case "tool-result":
431
- return normalizeToolResult(part, metadata);
417
+ return serializeToolResult(part, metadata);
432
418
  case "reasoning":
433
419
  return {
434
420
  type: part.type,
435
421
  text: part.text,
422
+ signature: "signature" in part && typeof part.signature === "string"
423
+ ? part.signature
424
+ : undefined,
425
+ ...metadata,
426
+ };
427
+ case "reasoning-file": {
428
+ return {
429
+ type: part.type,
430
+ ...serializeReasoningFile(part),
431
+ mediaType: part.mediaType,
432
+ ...metadata,
433
+ };
434
+ }
435
+ case "custom":
436
+ return {
437
+ type: part.type,
438
+ kind: part.kind,
436
439
  ...metadata,
437
440
  };
438
441
  case "tool-approval-request":
@@ -440,6 +443,8 @@ export function fromModelMessageContent(content) {
440
443
  type: part.type,
441
444
  approvalId: part.approvalId,
442
445
  toolCallId: part.toolCallId,
446
+ isAutomatic: "isAutomatic" in part ? part.isAutomatic : undefined,
447
+ signature: "signature" in part ? part.signature : undefined,
443
448
  ...metadata,
444
449
  };
445
450
  case "tool-approval-response":
@@ -481,14 +486,18 @@ export function toModelMessageContent(content) {
481
486
  case "image":
482
487
  return {
483
488
  type: part.type,
484
- image: toModelMessageDataOrUrl(part.image),
489
+ image: (isStoredProviderReference(part.image)
490
+ ? part.image.reference
491
+ : toModelMessageDataOrUrl(part.image)),
485
492
  mediaType: getMimeOrMediaType(part),
486
493
  ...metadata,
487
494
  };
488
495
  case "file":
489
496
  return {
490
497
  type: part.type,
491
- data: toModelMessageDataOrUrl(part.data),
498
+ data: (isStoredProviderReference(part.data)
499
+ ? { type: "reference", reference: part.data.reference }
500
+ : toModelMessageDataOrUrl(part.data)),
492
501
  filename: part.filename,
493
502
  mediaType: getMimeOrMediaType(part),
494
503
  ...metadata,
@@ -506,7 +515,7 @@ export function toModelMessageContent(content) {
506
515
  };
507
516
  }
508
517
  case "tool-result": {
509
- return normalizeToolResult(part, metadata);
518
+ return deserializeToolResult(part, metadata);
510
519
  }
511
520
  case "reasoning":
512
521
  return {
@@ -514,19 +523,26 @@ export function toModelMessageContent(content) {
514
523
  text: part.text,
515
524
  ...metadata,
516
525
  };
526
+ case "reasoning-file":
527
+ return {
528
+ type: "reasoning-file",
529
+ data: deserializeReasoningFile(part),
530
+ mediaType: part.mediaType,
531
+ ...metadata,
532
+ };
533
+ case "custom":
534
+ return { type: "custom", kind: part.kind, ...metadata };
517
535
  case "redacted-reasoning":
518
- // TODO: should we just drop this?
536
+ // Legacy v5 part: round-trip the redacted payload via providerOptions.
519
537
  return {
520
538
  type: "reasoning",
521
539
  text: "",
522
540
  ...metadata,
523
541
  providerOptions: metadata.providerOptions
524
- ? {
525
- ...Object.fromEntries(Object.entries(metadata.providerOptions ?? {}).map(([key, value]) => [
526
- key,
527
- { ...value, redactedData: part.data },
528
- ])),
529
- }
542
+ ? Object.fromEntries(Object.entries(metadata.providerOptions ?? {}).map(([key, value]) => [
543
+ key,
544
+ { ...value, redactedData: part.data },
545
+ ]))
530
546
  : undefined,
531
547
  };
532
548
  case "source":
@@ -536,6 +552,8 @@ export function toModelMessageContent(content) {
536
552
  type: part.type,
537
553
  approvalId: part.approvalId,
538
554
  toolCallId: part.toolCallId,
555
+ isAutomatic: "isAutomatic" in part ? part.isAutomatic : undefined,
556
+ signature: "signature" in part ? part.signature : undefined,
539
557
  ...metadata,
540
558
  };
541
559
  case "tool-approval-response":
@@ -568,21 +586,238 @@ export function normalizeToolOutput(result) {
568
586
  value: result ?? null,
569
587
  };
570
588
  }
571
- function normalizeToolResult(part, metadata) {
589
+ function serializeToolResult(part, metadata) {
572
590
  return {
573
591
  type: part.type,
574
- output: part.output
575
- ? validate(vToolResultOutput, part.output)
576
- ? part.output
577
- : normalizeToolOutput(JSON.stringify(part.output))
592
+ output: "output" in part && part.output !== undefined
593
+ ? serializeToolResultOutput(part.output)
578
594
  : normalizeToolOutput("result" in part ? part.result : undefined),
579
595
  toolCallId: part.toolCallId,
580
596
  toolName: part.toolName,
597
+ ...("providerExecuted" in part
598
+ ? { providerExecuted: part.providerExecuted }
599
+ : {}),
581
600
  // Preserve isError flag for error reporting
582
601
  ...("isError" in part && part.isError ? { isError: true } : {}),
583
602
  ...metadata,
584
603
  };
585
604
  }
605
+ function deserializeToolResult(part, metadata) {
606
+ return {
607
+ type: part.type,
608
+ output: "output" in part && part.output !== undefined
609
+ ? deserializeToolResultOutput(part.output)
610
+ : normalizeToolOutput("result" in part ? part.result : undefined),
611
+ toolCallId: part.toolCallId,
612
+ toolName: part.toolName,
613
+ ...("isError" in part && part.isError ? { isError: true } : {}),
614
+ ...metadata,
615
+ };
616
+ }
617
+ function serializeToolResultOutput(output) {
618
+ if (output === undefined) {
619
+ return normalizeToolOutput(undefined);
620
+ }
621
+ if (!isRecord(output) || typeof output.type !== "string") {
622
+ return normalizeToolOutput(output);
623
+ }
624
+ if (output.type !== "content") {
625
+ if (validate(vToolResultOutput, output)) {
626
+ return output;
627
+ }
628
+ throw new Error(`Invalid AI SDK 7 tool-result output: ${output.type}`);
629
+ }
630
+ if (!Array.isArray(output.value)) {
631
+ throw new Error("Invalid AI SDK 7 tool-result content output");
632
+ }
633
+ const serialized = {
634
+ ...output,
635
+ value: output.value.map(serializeToolResultContentPart),
636
+ };
637
+ if (!validate(vToolResultOutput, serialized)) {
638
+ throw new Error("Invalid AI SDK 7 tool-result content part");
639
+ }
640
+ return serialized;
641
+ }
642
+ function serializeToolResultContentPart(part) {
643
+ if (!isRecord(part) || typeof part.type !== "string") {
644
+ throw new Error("Invalid AI SDK 7 tool-result content part");
645
+ }
646
+ if (part.type !== "file")
647
+ return part;
648
+ if (!isRecord(part.data) || typeof part.data.type !== "string") {
649
+ throw new Error("Invalid AI SDK 7 tool-result file data");
650
+ }
651
+ const common = {
652
+ type: "file",
653
+ mediaType: part.mediaType,
654
+ ...(typeof part.filename === "string" ? { filename: part.filename } : {}),
655
+ ...(isRecord(part.providerOptions)
656
+ ? { providerOptions: part.providerOptions }
657
+ : {}),
658
+ };
659
+ switch (part.data.type) {
660
+ case "data":
661
+ return {
662
+ ...common,
663
+ data: {
664
+ type: "data",
665
+ data: serializeDataOrUrl(part.data.data),
666
+ },
667
+ };
668
+ case "url": {
669
+ const { url } = part.data;
670
+ if (typeof url !== "string" && !(url instanceof URL)) {
671
+ throw new Error("Invalid AI SDK 7 tool-result file URL");
672
+ }
673
+ return { ...common, data: { type: "url", url: url.toString() } };
674
+ }
675
+ case "text":
676
+ if (typeof part.data.text !== "string") {
677
+ throw new Error("Invalid AI SDK 7 tool-result file text");
678
+ }
679
+ return {
680
+ ...common,
681
+ data: { type: "text", text: part.data.text },
682
+ };
683
+ case "reference":
684
+ if (!isProviderReference(part.data.reference)) {
685
+ throw new Error("Invalid AI SDK 7 tool-result file reference");
686
+ }
687
+ return {
688
+ ...common,
689
+ data: { type: "reference", reference: part.data.reference },
690
+ };
691
+ default:
692
+ throw new Error(`Invalid AI SDK 7 tool-result file data: ${part.data.type}`);
693
+ }
694
+ }
695
+ function deserializeToolResultOutput(output) {
696
+ if (!validate(vToolResultOutput, output)) {
697
+ return normalizeToolOutput(output);
698
+ }
699
+ const stored = output;
700
+ if (stored.type !== "content")
701
+ return stored;
702
+ return {
703
+ type: "content",
704
+ value: stored.value.map(deserializeToolResultContentPart),
705
+ };
706
+ }
707
+ function deserializeToolResultContentPart(part) {
708
+ if (part.type === "file") {
709
+ return {
710
+ ...part,
711
+ data: part.data.type === "url"
712
+ ? { type: "url", url: new URL(part.data.url) }
713
+ : part.data,
714
+ };
715
+ }
716
+ switch (part.type) {
717
+ case "media":
718
+ return {
719
+ type: "file",
720
+ data: { type: "data", data: part.data },
721
+ mediaType: part.mediaType,
722
+ };
723
+ case "file-data":
724
+ return {
725
+ type: "file",
726
+ data: { type: "data", data: part.data },
727
+ mediaType: part.mediaType,
728
+ ...(part.filename !== undefined ? { filename: part.filename } : {}),
729
+ ...(part.providerOptions !== undefined
730
+ ? { providerOptions: part.providerOptions }
731
+ : {}),
732
+ };
733
+ case "file-url":
734
+ return {
735
+ type: "file",
736
+ data: { type: "url", url: new URL(part.url) },
737
+ mediaType: part.mediaType ?? "application/octet-stream",
738
+ ...(part.providerOptions !== undefined
739
+ ? { providerOptions: part.providerOptions }
740
+ : {}),
741
+ };
742
+ case "file-id":
743
+ case "image-file-id":
744
+ if (typeof part.fileId === "string")
745
+ return part;
746
+ return {
747
+ type: "file",
748
+ data: {
749
+ type: "reference",
750
+ reference: part.fileId,
751
+ },
752
+ mediaType: part.type === "image-file-id" ? "image" : "application/octet-stream",
753
+ ...(part.providerOptions !== undefined
754
+ ? { providerOptions: part.providerOptions }
755
+ : {}),
756
+ };
757
+ case "file-reference":
758
+ case "image-file-reference":
759
+ return {
760
+ type: "file",
761
+ data: { type: "reference", reference: part.providerReference },
762
+ mediaType: part.type === "image-file-reference"
763
+ ? "image"
764
+ : "application/octet-stream",
765
+ ...(part.providerOptions !== undefined
766
+ ? { providerOptions: part.providerOptions }
767
+ : {}),
768
+ };
769
+ case "image-data":
770
+ return {
771
+ type: "file",
772
+ data: { type: "data", data: part.data },
773
+ mediaType: part.mediaType,
774
+ ...(part.providerOptions !== undefined
775
+ ? { providerOptions: part.providerOptions }
776
+ : {}),
777
+ };
778
+ case "image-url":
779
+ return {
780
+ type: "file",
781
+ data: { type: "url", url: new URL(part.url) },
782
+ mediaType: "image",
783
+ ...(part.providerOptions !== undefined
784
+ ? { providerOptions: part.providerOptions }
785
+ : {}),
786
+ };
787
+ default:
788
+ return part;
789
+ }
790
+ }
791
+ function serializeReasoningFile(part) {
792
+ if ("url" in part && part.url !== undefined) {
793
+ return { url: part.url.toString() };
794
+ }
795
+ if (!("data" in part) || part.data === undefined) {
796
+ throw new Error("reasoning-file requires data or url");
797
+ }
798
+ const { data } = part;
799
+ if (data instanceof URL)
800
+ return { url: data.toString() };
801
+ if (isRecord(data) && data.type === "url" && data.url instanceof URL) {
802
+ return { url: data.url.toString() };
803
+ }
804
+ if (isRecord(data) && data.type === "data") {
805
+ return { data: serializeDataOrUrl(data.data) };
806
+ }
807
+ if (isRecord(data) && "type" in data) {
808
+ throw new Error("Invalid AI SDK 7 reasoning-file data");
809
+ }
810
+ return { data: serializeDataOrUrl(data) };
811
+ }
812
+ function deserializeReasoningFile(part) {
813
+ if (part.url !== undefined) {
814
+ return { type: "url", url: new URL(part.url) };
815
+ }
816
+ if (part.data !== undefined) {
817
+ return { type: "data", data: part.data };
818
+ }
819
+ throw new Error("reasoning-file requires data or url");
820
+ }
586
821
  /**
587
822
  * Return a best-guess MIME type based on the magic-number signature
588
823
  * found at the start of an ArrayBuffer.
@@ -671,6 +906,21 @@ export function serializeDataOrUrl(dataOrUrl) {
671
906
  if (dataOrUrl instanceof URL) {
672
907
  return dataOrUrl.toString();
673
908
  }
909
+ if ("type" in dataOrUrl) {
910
+ switch (dataOrUrl.type) {
911
+ case "data":
912
+ return serializeDataOrUrl(dataOrUrl.data);
913
+ case "url":
914
+ return dataOrUrl.url.toString();
915
+ case "text":
916
+ return convertUint8ArrayToBase64(new TextEncoder().encode(dataOrUrl.text));
917
+ case "reference":
918
+ throw new Error("Provider references must be stored as references");
919
+ }
920
+ }
921
+ if (!(dataOrUrl instanceof Uint8Array)) {
922
+ throw new Error("Unsupported provider reference");
923
+ }
674
924
  return dataOrUrl.buffer.slice(dataOrUrl.byteOffset, dataOrUrl.byteOffset + dataOrUrl.byteLength);
675
925
  }
676
926
  export function toModelMessageDataOrUrl(urlOrString) {
@@ -686,35 +936,84 @@ export function toModelMessageDataOrUrl(urlOrString) {
686
936
  }
687
937
  return urlOrString;
688
938
  }
939
+ function isRecord(value) {
940
+ return typeof value === "object" && value !== null;
941
+ }
942
+ function isProviderReference(value) {
943
+ return (isRecord(value) &&
944
+ !(value instanceof ArrayBuffer) &&
945
+ !(value instanceof Uint8Array) &&
946
+ !(value instanceof URL) &&
947
+ !("type" in value) &&
948
+ Object.values(value).every((id) => typeof id === "string"));
949
+ }
950
+ function isStoredProviderReference(value) {
951
+ return (isRecord(value) &&
952
+ value.type === "reference" &&
953
+ isProviderReference(value.reference));
954
+ }
955
+ function toStoredProviderReference(value) {
956
+ if (isStoredProviderReference(value))
957
+ return value;
958
+ if (isProviderReference(value))
959
+ return { type: "reference", reference: value };
960
+ if (isRecord(value) &&
961
+ value.type === "reference" &&
962
+ isProviderReference(value.reference)) {
963
+ return { type: "reference", reference: value.reference };
964
+ }
965
+ return undefined;
966
+ }
967
+ function isFileReference(value) {
968
+ return (isRecord(value) &&
969
+ value.type === "reference" &&
970
+ isProviderReference(value.reference));
971
+ }
689
972
  export function toUIFilePart(part) {
690
973
  const dataOrUrl = part.type === "image" ? part.image : part.data;
691
- const url = dataOrUrl instanceof ArrayBuffer
692
- ? convertUint8ArrayToBase64(new Uint8Array(dataOrUrl))
693
- : dataOrUrl.toString();
974
+ const providerReference = isProviderReference(dataOrUrl)
975
+ ? dataOrUrl
976
+ : isFileReference(dataOrUrl)
977
+ ? dataOrUrl.reference
978
+ : undefined;
979
+ const url = providerReference
980
+ ? ""
981
+ : toUIFileUrl(dataOrUrl, part.mediaType ?? "application/octet-stream");
694
982
  return {
695
983
  type: "file",
696
984
  mediaType: part.mediaType,
697
985
  filename: part.type === "file" ? part.filename : undefined,
698
986
  url,
987
+ ...(providerReference !== undefined ? { providerReference } : {}),
699
988
  providerMetadata: part.providerOptions,
700
989
  };
701
990
  }
702
- // Currently unused
703
- // export function toModelMessages(args: {
704
- // messages?: ModelMessage[] | AIMessageWithoutId[];
705
- // }): ModelMessage[] {
706
- // const messages: ModelMessage[] = [];
707
- // if (args.messages) {
708
- // if (
709
- // args.messages.every(
710
- // (m) => typeof m === "object" && m !== null && "parts" in m,
711
- // )
712
- // ) {
713
- // messages.push(...convertToModelMessages(args.messages));
714
- // } else {
715
- // messages.push(...modelMessageSchema.array().parse(args.messages));
716
- // }
717
- // }
718
- // return messages;
719
- // }
991
+ function toUIFileUrl(data, mediaType) {
992
+ if (isFileReference(data))
993
+ return "";
994
+ if (isRecord(data) && typeof data.type === "string") {
995
+ switch (data.type) {
996
+ case "url":
997
+ return data.url.toString();
998
+ case "data":
999
+ return toUIFileDataUrl(data.data, mediaType);
1000
+ case "text":
1001
+ return toUIFileDataUrl(new TextEncoder().encode(data.text), mediaType);
1002
+ }
1003
+ }
1004
+ if (data instanceof URL)
1005
+ return data.toString();
1006
+ if (typeof data === "string")
1007
+ return data;
1008
+ return toUIFileDataUrl(data, mediaType);
1009
+ }
1010
+ function toUIFileDataUrl(data, mediaType) {
1011
+ if (typeof data === "string") {
1012
+ return data.startsWith("data:") ? data : `data:${mediaType};base64,${data}`;
1013
+ }
1014
+ const bytes = data instanceof ArrayBuffer
1015
+ ? new Uint8Array(data)
1016
+ : new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
1017
+ return `data:${mediaType};base64,${convertUint8ArrayToBase64(bytes)}`;
1018
+ }
720
1019
  //# sourceMappingURL=mapping.js.map