@convex-dev/agent 0.6.4 → 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 (225) 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/messages.d.ts +1252 -201
  11. package/dist/component/messages.d.ts.map +1 -1
  12. package/dist/component/messages.js +49 -23
  13. package/dist/component/messages.js.map +1 -1
  14. package/dist/component/schema.d.ts +2593 -332
  15. package/dist/component/schema.d.ts.map +1 -1
  16. package/dist/component/streams.d.ts +7 -1
  17. package/dist/component/streams.d.ts.map +1 -1
  18. package/dist/component/streams.js +24 -30
  19. package/dist/component/streams.js.map +1 -1
  20. package/dist/component/threads.d.ts.map +1 -1
  21. package/dist/component/threads.js +1 -2
  22. package/dist/component/threads.js.map +1 -1
  23. package/dist/react/index.d.ts +5 -5
  24. package/dist/react/index.d.ts.map +1 -1
  25. package/dist/react/index.js +5 -5
  26. package/dist/react/index.js.map +1 -1
  27. package/dist/shared.d.ts +19 -7
  28. package/dist/shared.d.ts.map +1 -1
  29. package/dist/shared.js +4 -4
  30. package/dist/shared.js.map +1 -1
  31. package/dist/streaming/materializePersistedUIMessageChunks.d.ts +16 -0
  32. package/dist/streaming/materializePersistedUIMessageChunks.d.ts.map +1 -0
  33. package/dist/streaming/materializePersistedUIMessageChunks.js +302 -0
  34. package/dist/streaming/materializePersistedUIMessageChunks.js.map +1 -0
  35. package/dist/streaming/persistedUIMessageChunks.d.ts +106 -0
  36. package/dist/streaming/persistedUIMessageChunks.d.ts.map +1 -0
  37. package/dist/streaming/persistedUIMessageChunks.js +475 -0
  38. package/dist/streaming/persistedUIMessageChunks.js.map +1 -0
  39. package/dist/validators.d.ts +10026 -1055
  40. package/dist/validators.d.ts.map +1 -1
  41. package/dist/validators.js +71 -9
  42. package/dist/validators.js.map +1 -1
  43. package/dist/{UIMessages.d.ts → vercel/UIMessages.d.ts} +1 -1
  44. package/dist/vercel/UIMessages.d.ts.map +1 -0
  45. package/dist/{UIMessages.js → vercel/UIMessages.js} +63 -1
  46. package/dist/vercel/UIMessages.js.map +1 -0
  47. package/dist/{client → vercel/client}/createTool.d.ts +23 -16
  48. package/dist/vercel/client/createTool.d.ts.map +1 -0
  49. package/dist/{client → vercel/client}/createTool.js +2 -0
  50. package/dist/vercel/client/createTool.js.map +1 -0
  51. package/dist/{client → vercel/client}/definePlaygroundAPI.d.ts +533 -79
  52. package/dist/{client → vercel/client}/definePlaygroundAPI.d.ts.map +1 -1
  53. package/dist/{client → vercel/client}/definePlaygroundAPI.js +8 -7
  54. package/dist/vercel/client/definePlaygroundAPI.js.map +1 -0
  55. package/dist/{client → vercel/client}/files.d.ts +2 -2
  56. package/dist/vercel/client/files.d.ts.map +1 -0
  57. package/dist/vercel/client/files.js.map +1 -0
  58. package/dist/vercel/client/messages.d.ts +542 -0
  59. package/dist/vercel/client/messages.d.ts.map +1 -0
  60. package/dist/vercel/client/messages.js +66 -0
  61. package/dist/vercel/client/messages.js.map +1 -0
  62. package/dist/{client → vercel/client}/mockModel.d.ts +17 -17
  63. package/dist/vercel/client/mockModel.d.ts.map +1 -0
  64. package/dist/{client → vercel/client}/mockModel.js +12 -13
  65. package/dist/vercel/client/mockModel.js.map +1 -0
  66. package/dist/{client → vercel/client}/saveInputMessages.d.ts +2 -2
  67. package/dist/vercel/client/saveInputMessages.d.ts.map +1 -0
  68. package/dist/vercel/client/saveInputMessages.js.map +1 -0
  69. package/dist/{client → vercel/client}/search.d.ts +119 -22
  70. package/dist/vercel/client/search.d.ts.map +1 -0
  71. package/dist/{client → vercel/client}/search.js +2 -2
  72. package/dist/vercel/client/search.js.map +1 -0
  73. package/dist/{client → vercel/client}/start.d.ts +26 -11
  74. package/dist/vercel/client/start.d.ts.map +1 -0
  75. package/dist/{client → vercel/client}/start.js +64 -22
  76. package/dist/vercel/client/start.js.map +1 -0
  77. package/dist/{client → vercel/client}/streamText.d.ts +13 -12
  78. package/dist/vercel/client/streamText.d.ts.map +1 -0
  79. package/dist/{client → vercel/client}/streamText.js +43 -9
  80. package/dist/vercel/client/streamText.js.map +1 -0
  81. package/dist/{client → vercel/client}/streaming.d.ts +1410 -183
  82. package/dist/vercel/client/streaming.d.ts.map +1 -0
  83. package/dist/{client → vercel/client}/streaming.js +120 -52
  84. package/dist/vercel/client/streaming.js.map +1 -0
  85. package/dist/vercel/client/types.d.ts +456 -0
  86. package/dist/vercel/client/types.d.ts.map +1 -0
  87. package/dist/vercel/client/types.js +3 -0
  88. package/dist/vercel/client/types.js.map +1 -0
  89. package/dist/{client → vercel/client}/utils.d.ts +3 -2
  90. package/dist/vercel/client/utils.d.ts.map +1 -0
  91. package/dist/{client → vercel/client}/utils.js +2 -2
  92. package/dist/vercel/client/utils.js.map +1 -0
  93. package/dist/{deltas.d.ts → vercel/deltas.d.ts} +3 -4
  94. package/dist/vercel/deltas.d.ts.map +1 -0
  95. package/dist/{deltas.js → vercel/deltas.js} +195 -99
  96. package/dist/vercel/deltas.js.map +1 -0
  97. package/dist/{client → vercel}/index.d.ts +482 -106
  98. package/dist/vercel/index.d.ts.map +1 -0
  99. package/dist/{client → vercel}/index.js +64 -46
  100. package/dist/vercel/index.js.map +1 -0
  101. package/dist/{mapping.d.ts → vercel/mapping.d.ts} +5 -19
  102. package/dist/vercel/mapping.d.ts.map +1 -0
  103. package/dist/{mapping.js → vercel/mapping.js} +411 -114
  104. package/dist/vercel/mapping.js.map +1 -0
  105. package/dist/{react → vercel/react}/optimisticallySendMessage.d.ts +2 -2
  106. package/dist/vercel/react/optimisticallySendMessage.d.ts.map +1 -0
  107. package/dist/vercel/react/optimisticallySendMessage.js.map +1 -0
  108. package/dist/{react → vercel/react}/types.d.ts +1 -1
  109. package/dist/vercel/react/types.d.ts.map +1 -0
  110. package/dist/{react → vercel/react}/types.js.map +1 -1
  111. package/dist/{react → vercel/react}/useDeltaStreams.d.ts +1 -1
  112. package/dist/vercel/react/useDeltaStreams.d.ts.map +1 -0
  113. package/dist/{react → vercel/react}/useDeltaStreams.js +1 -1
  114. package/dist/vercel/react/useDeltaStreams.js.map +1 -0
  115. package/dist/{react → vercel/react}/useStreamingUIMessages.d.ts +1 -1
  116. package/dist/vercel/react/useStreamingUIMessages.d.ts.map +1 -0
  117. package/dist/{react → vercel/react}/useStreamingUIMessages.js +7 -3
  118. package/dist/vercel/react/useStreamingUIMessages.js.map +1 -0
  119. package/dist/{react → vercel/react}/useThreadMessages.d.ts +1 -1
  120. package/dist/vercel/react/useThreadMessages.d.ts.map +1 -0
  121. package/dist/{react → vercel/react}/useThreadMessages.js +1 -1
  122. package/dist/vercel/react/useThreadMessages.js.map +1 -0
  123. package/dist/{react → vercel/react}/useUIMessages.d.ts +1 -1
  124. package/dist/vercel/react/useUIMessages.d.ts.map +1 -0
  125. package/dist/{react → vercel/react}/useUIMessages.js +1 -1
  126. package/dist/vercel/react/useUIMessages.js.map +1 -0
  127. package/package.json +29 -22
  128. package/src/client/messages.ts +5 -107
  129. package/src/client/types.ts +0 -608
  130. package/src/component/_generated/component.ts +1089 -48
  131. package/src/component/messages.test.ts +273 -1
  132. package/src/component/messages.ts +62 -32
  133. package/src/component/streams.ts +47 -47
  134. package/src/component/threads.ts +5 -2
  135. package/src/eslintConfig.test.ts +44 -0
  136. package/src/react/index.ts +8 -5
  137. package/src/shared.ts +26 -36
  138. package/src/streaming/materializePersistedUIMessageChunks.test.ts +513 -0
  139. package/src/streaming/materializePersistedUIMessageChunks.ts +398 -0
  140. package/src/streaming/persistedUIMessageChunks.test.ts +205 -0
  141. package/src/streaming/persistedUIMessageChunks.ts +658 -0
  142. package/src/validators.test.ts +4 -1
  143. package/src/validators.ts +89 -8
  144. package/src/{UIMessages.combineUIMessages.test.ts → vercel/UIMessages.combineUIMessages.test.ts} +4 -1
  145. package/src/{UIMessages.ts → vercel/UIMessages.ts} +95 -3
  146. package/src/{client → vercel/client}/approval.test.ts +23 -13
  147. package/src/{client → vercel/client}/createTool.ts +62 -22
  148. package/src/{client → vercel/client}/definePlaygroundAPI.ts +15 -16
  149. package/src/{client → vercel/client}/files.ts +2 -2
  150. package/src/{client → vercel/client}/index.test.ts +99 -31
  151. package/src/vercel/client/messages.ts +182 -0
  152. package/src/{client → vercel/client}/mockModel.ts +38 -39
  153. package/src/{client → vercel/client}/saveInputMessages.test.ts +1 -1
  154. package/src/{client → vercel/client}/saveInputMessages.ts +3 -3
  155. package/src/{client → vercel/client}/search.test.ts +3 -3
  156. package/src/{client → vercel/client}/search.ts +4 -4
  157. package/src/{client → vercel/client}/setup.test.ts +6 -3
  158. package/src/vercel/client/start.test.ts +14 -0
  159. package/src/{client → vercel/client}/start.ts +147 -36
  160. package/src/vercel/client/streamText.test.ts +223 -0
  161. package/src/{client → vercel/client}/streamText.ts +102 -31
  162. package/src/{client → vercel/client}/streaming.integration.test.ts +6 -3
  163. package/src/{client → vercel/client}/streaming.test.ts +178 -4
  164. package/src/{client → vercel/client}/streaming.ts +114 -52
  165. package/src/vercel/client/types.test.ts +13 -0
  166. package/src/vercel/client/types.ts +679 -0
  167. package/src/{client → vercel/client}/utils.ts +13 -7
  168. package/src/{deltas.test.ts → vercel/deltas.test.ts} +384 -93
  169. package/src/{deltas.ts → vercel/deltas.ts} +218 -115
  170. package/src/{fromUIMessages.test.ts → vercel/fromUIMessages.test.ts} +17 -1
  171. package/src/{client → vercel}/index.ts +167 -84
  172. package/src/{mapping.test.ts → vercel/mapping.test.ts} +377 -92
  173. package/src/{mapping.ts → vercel/mapping.ts} +501 -137
  174. package/src/{react → vercel/react}/optimisticallySendMessage.ts +2 -2
  175. package/src/{react → vercel/react}/types.ts +1 -1
  176. package/src/{react → vercel/react}/useDeltaStreams.ts +6 -2
  177. package/src/{react → vercel/react}/useStreamingUIMessages.ts +7 -3
  178. package/src/{react → vercel/react}/useThreadMessages.ts +2 -2
  179. package/src/{react → vercel/react}/useUIMessages.ts +2 -2
  180. package/src/{toUIMessages.test.ts → vercel/toUIMessages.test.ts} +49 -2
  181. package/dist/UIMessages.d.ts.map +0 -1
  182. package/dist/UIMessages.js.map +0 -1
  183. package/dist/client/createTool.d.ts.map +0 -1
  184. package/dist/client/createTool.js.map +0 -1
  185. package/dist/client/definePlaygroundAPI.js.map +0 -1
  186. package/dist/client/files.d.ts.map +0 -1
  187. package/dist/client/files.js.map +0 -1
  188. package/dist/client/index.d.ts.map +0 -1
  189. package/dist/client/index.js.map +0 -1
  190. package/dist/client/mockModel.d.ts.map +0 -1
  191. package/dist/client/mockModel.js.map +0 -1
  192. package/dist/client/saveInputMessages.d.ts.map +0 -1
  193. package/dist/client/saveInputMessages.js.map +0 -1
  194. package/dist/client/search.d.ts.map +0 -1
  195. package/dist/client/search.js.map +0 -1
  196. package/dist/client/start.d.ts.map +0 -1
  197. package/dist/client/start.js.map +0 -1
  198. package/dist/client/streamText.d.ts.map +0 -1
  199. package/dist/client/streamText.js.map +0 -1
  200. package/dist/client/streaming.d.ts.map +0 -1
  201. package/dist/client/streaming.js.map +0 -1
  202. package/dist/client/utils.d.ts.map +0 -1
  203. package/dist/client/utils.js.map +0 -1
  204. package/dist/deltas.d.ts.map +0 -1
  205. package/dist/deltas.js.map +0 -1
  206. package/dist/mapping.d.ts.map +0 -1
  207. package/dist/mapping.js.map +0 -1
  208. package/dist/react/optimisticallySendMessage.d.ts.map +0 -1
  209. package/dist/react/optimisticallySendMessage.js.map +0 -1
  210. package/dist/react/types.d.ts.map +0 -1
  211. package/dist/react/useDeltaStreams.d.ts.map +0 -1
  212. package/dist/react/useDeltaStreams.js.map +0 -1
  213. package/dist/react/useStreamingUIMessages.d.ts.map +0 -1
  214. package/dist/react/useStreamingUIMessages.js.map +0 -1
  215. package/dist/react/useThreadMessages.d.ts.map +0 -1
  216. package/dist/react/useThreadMessages.js.map +0 -1
  217. package/dist/react/useUIMessages.d.ts.map +0 -1
  218. package/dist/react/useUIMessages.js.map +0 -1
  219. package/src/client/streamText.test.ts +0 -102
  220. /package/dist/{client → vercel/client}/files.js +0 -0
  221. /package/dist/{client → vercel/client}/saveInputMessages.js +0 -0
  222. /package/dist/{react → vercel/react}/optimisticallySendMessage.js +0 -0
  223. /package/dist/{react → vercel/react}/types.js +0 -0
  224. /package/src/{UIMessages.test.ts → vercel/UIMessages.test.ts} +0 -0
  225. /package/src/{react → vercel/react}/useUIMessages.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,36 +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 response messages produced by this step.
196
- *
197
- * `step.response.messages` is cumulative across steps in AI SDK v6 — each
198
- * step's array contains all messages from prior steps too. Pass
199
- * `previousResponseMessageCount` (the prior step's `response.messages.length`,
200
- * or `0` for the first step) so we slice only the new tail. The parameter is
201
- * required: defaulting it would silently duplicate every prior message on
202
- * every multi-step save.
203
- */
204
- export async function serializeNewMessagesInStep(ctx, component, step, model, previousResponseMessageCount) {
205
- const newMessages = step.response.messages.slice(previousResponseMessageCount);
206
- // Keep at least one message in the output so the step still anchors an
207
- // order slot — downstream `addMessages` relies on each step contributing a
208
- // row even when AI SDK produced no response messages.
209
- const messagesToSerialize = newMessages.length > 0
210
- ? newMessages
211
- : [{ role: "assistant", content: [] }];
212
- return serializeStepMessages(ctx, component, step, model, messagesToSerialize);
213
- }
214
172
  async function serializeStepMessages(ctx, component, step, model, messagesToSerialize) {
215
173
  // If there are tool results, there's another message with the tool results
216
174
  // ref: https://github.com/vercel/ai/blob/main/packages/ai/src/generate-text/to-response-messages.ts#L120
217
175
  const hasToolMessage = step.response.messages.at(-1)?.role === "tool";
176
+ const resolvedModel = step.model ?? model;
218
177
  const assistantFields = {
219
- model: model ? getModelName(model) : undefined,
220
- provider: model ? getProviderName(model) : undefined,
178
+ model: resolvedModel ? getModelName(resolvedModel) : undefined,
179
+ provider: resolvedModel ? getProviderName(resolvedModel) : undefined,
221
180
  providerMetadata: step.providerMetadata,
222
181
  reasoning: step.reasoningText,
223
- reasoningDetails: step.reasoning,
182
+ reasoningDetails: step.reasoning.filter((part) => part.type !== "reasoning-file"),
224
183
  usage: serializeUsage(step.usage),
225
184
  warnings: serializeWarnings(step.warnings),
226
185
  finishReason: step.finishReason,
@@ -237,7 +196,6 @@ async function serializeStepMessages(ctx, component, step, model, messagesToSeri
237
196
  fileIds,
238
197
  });
239
198
  }));
240
- // TODO: capture step.files separately?
241
199
  return { messages };
242
200
  }
243
201
  export async function serializeObjectResult(ctx, component, result, model) {
@@ -293,7 +251,8 @@ export async function serializeContent(ctx, component, content) {
293
251
  };
294
252
  }
295
253
  case "image": {
296
- let image = serializeDataOrUrl(part.image);
254
+ let image = toStoredProviderReference(part.image) ??
255
+ serializeDataOrUrl(part.image);
297
256
  if (image instanceof ArrayBuffer &&
298
257
  image.byteLength > MAX_FILE_SIZE) {
299
258
  const { file } = await storeFile(ctx, component, new Blob([image], {
@@ -310,7 +269,8 @@ export async function serializeContent(ctx, component, content) {
310
269
  };
311
270
  }
312
271
  case "file": {
313
- let data = serializeDataOrUrl(part.data);
272
+ let data = toStoredProviderReference(part.data) ??
273
+ serializeDataOrUrl(part.data);
314
274
  if (data instanceof ArrayBuffer && data.byteLength > MAX_FILE_SIZE) {
315
275
  const { file } = await storeFile(ctx, component, new Blob([data], { type: getMimeOrMediaType(part) }));
316
276
  data = file.url;
@@ -335,16 +295,36 @@ export async function serializeContent(ctx, component, content) {
335
295
  toolCallId: part.toolCallId,
336
296
  toolName: part.toolName,
337
297
  providerExecuted: part.providerExecuted,
298
+ title: "title" in part ? part.title : undefined,
299
+ toolMetadata: "toolMetadata" in part ? part.toolMetadata : undefined,
338
300
  ...metadata,
339
301
  };
340
302
  }
341
303
  case "tool-result": {
342
- return normalizeToolResult(part, metadata);
304
+ return serializeToolResult(part, metadata);
343
305
  }
344
306
  case "reasoning": {
345
307
  return {
346
308
  type: part.type,
347
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,
348
328
  ...metadata,
349
329
  };
350
330
  }
@@ -364,6 +344,8 @@ export async function serializeContent(ctx, component, content) {
364
344
  type: part.type,
365
345
  approvalId: part.approvalId,
366
346
  toolCallId: part.toolCallId,
347
+ isAutomatic: "isAutomatic" in part ? part.isAutomatic : undefined,
348
+ signature: "signature" in part ? part.signature : undefined,
367
349
  ...metadata,
368
350
  };
369
351
  }
@@ -407,12 +389,14 @@ export function fromModelMessageContent(content) {
407
389
  type: part.type,
408
390
  mediaType: getMimeOrMediaType(part),
409
391
  ...metadata,
410
- image: serializeDataOrUrl(part.image),
392
+ image: toStoredProviderReference(part.image) ??
393
+ serializeDataOrUrl(part.image),
411
394
  };
412
395
  case "file":
413
396
  return {
414
397
  type: part.type,
415
- data: serializeDataOrUrl(part.data),
398
+ data: toStoredProviderReference(part.data) ??
399
+ serializeDataOrUrl(part.data),
416
400
  filename: part.filename,
417
401
  mediaType: getMimeOrMediaType(part),
418
402
  ...metadata,
@@ -430,11 +414,28 @@ export function fromModelMessageContent(content) {
430
414
  ...metadata,
431
415
  };
432
416
  case "tool-result":
433
- return normalizeToolResult(part, metadata);
417
+ return serializeToolResult(part, metadata);
434
418
  case "reasoning":
435
419
  return {
436
420
  type: part.type,
437
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,
438
439
  ...metadata,
439
440
  };
440
441
  case "tool-approval-request":
@@ -442,6 +443,8 @@ export function fromModelMessageContent(content) {
442
443
  type: part.type,
443
444
  approvalId: part.approvalId,
444
445
  toolCallId: part.toolCallId,
446
+ isAutomatic: "isAutomatic" in part ? part.isAutomatic : undefined,
447
+ signature: "signature" in part ? part.signature : undefined,
445
448
  ...metadata,
446
449
  };
447
450
  case "tool-approval-response":
@@ -483,14 +486,18 @@ export function toModelMessageContent(content) {
483
486
  case "image":
484
487
  return {
485
488
  type: part.type,
486
- image: toModelMessageDataOrUrl(part.image),
489
+ image: (isStoredProviderReference(part.image)
490
+ ? part.image.reference
491
+ : toModelMessageDataOrUrl(part.image)),
487
492
  mediaType: getMimeOrMediaType(part),
488
493
  ...metadata,
489
494
  };
490
495
  case "file":
491
496
  return {
492
497
  type: part.type,
493
- data: toModelMessageDataOrUrl(part.data),
498
+ data: (isStoredProviderReference(part.data)
499
+ ? { type: "reference", reference: part.data.reference }
500
+ : toModelMessageDataOrUrl(part.data)),
494
501
  filename: part.filename,
495
502
  mediaType: getMimeOrMediaType(part),
496
503
  ...metadata,
@@ -508,7 +515,7 @@ export function toModelMessageContent(content) {
508
515
  };
509
516
  }
510
517
  case "tool-result": {
511
- return normalizeToolResult(part, metadata);
518
+ return deserializeToolResult(part, metadata);
512
519
  }
513
520
  case "reasoning":
514
521
  return {
@@ -516,19 +523,26 @@ export function toModelMessageContent(content) {
516
523
  text: part.text,
517
524
  ...metadata,
518
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 };
519
535
  case "redacted-reasoning":
520
- // TODO: should we just drop this?
536
+ // Legacy v5 part: round-trip the redacted payload via providerOptions.
521
537
  return {
522
538
  type: "reasoning",
523
539
  text: "",
524
540
  ...metadata,
525
541
  providerOptions: metadata.providerOptions
526
- ? {
527
- ...Object.fromEntries(Object.entries(metadata.providerOptions ?? {}).map(([key, value]) => [
528
- key,
529
- { ...value, redactedData: part.data },
530
- ])),
531
- }
542
+ ? Object.fromEntries(Object.entries(metadata.providerOptions ?? {}).map(([key, value]) => [
543
+ key,
544
+ { ...value, redactedData: part.data },
545
+ ]))
532
546
  : undefined,
533
547
  };
534
548
  case "source":
@@ -538,6 +552,8 @@ export function toModelMessageContent(content) {
538
552
  type: part.type,
539
553
  approvalId: part.approvalId,
540
554
  toolCallId: part.toolCallId,
555
+ isAutomatic: "isAutomatic" in part ? part.isAutomatic : undefined,
556
+ signature: "signature" in part ? part.signature : undefined,
541
557
  ...metadata,
542
558
  };
543
559
  case "tool-approval-response":
@@ -570,21 +586,238 @@ export function normalizeToolOutput(result) {
570
586
  value: result ?? null,
571
587
  };
572
588
  }
573
- function normalizeToolResult(part, metadata) {
589
+ function serializeToolResult(part, metadata) {
574
590
  return {
575
591
  type: part.type,
576
- output: part.output
577
- ? validate(vToolResultOutput, part.output)
578
- ? part.output
579
- : normalizeToolOutput(JSON.stringify(part.output))
592
+ output: "output" in part && part.output !== undefined
593
+ ? serializeToolResultOutput(part.output)
580
594
  : normalizeToolOutput("result" in part ? part.result : undefined),
581
595
  toolCallId: part.toolCallId,
582
596
  toolName: part.toolName,
597
+ ...("providerExecuted" in part
598
+ ? { providerExecuted: part.providerExecuted }
599
+ : {}),
583
600
  // Preserve isError flag for error reporting
584
601
  ...("isError" in part && part.isError ? { isError: true } : {}),
585
602
  ...metadata,
586
603
  };
587
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
+ }
588
821
  /**
589
822
  * Return a best-guess MIME type based on the magic-number signature
590
823
  * found at the start of an ArrayBuffer.
@@ -673,6 +906,21 @@ export function serializeDataOrUrl(dataOrUrl) {
673
906
  if (dataOrUrl instanceof URL) {
674
907
  return dataOrUrl.toString();
675
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
+ }
676
924
  return dataOrUrl.buffer.slice(dataOrUrl.byteOffset, dataOrUrl.byteOffset + dataOrUrl.byteLength);
677
925
  }
678
926
  export function toModelMessageDataOrUrl(urlOrString) {
@@ -688,35 +936,84 @@ export function toModelMessageDataOrUrl(urlOrString) {
688
936
  }
689
937
  return urlOrString;
690
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
+ }
691
972
  export function toUIFilePart(part) {
692
973
  const dataOrUrl = part.type === "image" ? part.image : part.data;
693
- const url = dataOrUrl instanceof ArrayBuffer
694
- ? convertUint8ArrayToBase64(new Uint8Array(dataOrUrl))
695
- : 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");
696
982
  return {
697
983
  type: "file",
698
984
  mediaType: part.mediaType,
699
985
  filename: part.type === "file" ? part.filename : undefined,
700
986
  url,
987
+ ...(providerReference !== undefined ? { providerReference } : {}),
701
988
  providerMetadata: part.providerOptions,
702
989
  };
703
990
  }
704
- // Currently unused
705
- // export function toModelMessages(args: {
706
- // messages?: ModelMessage[] | AIMessageWithoutId[];
707
- // }): ModelMessage[] {
708
- // const messages: ModelMessage[] = [];
709
- // if (args.messages) {
710
- // if (
711
- // args.messages.every(
712
- // (m) => typeof m === "object" && m !== null && "parts" in m,
713
- // )
714
- // ) {
715
- // messages.push(...convertToModelMessages(args.messages));
716
- // } else {
717
- // messages.push(...modelMessageSchema.array().parse(args.messages));
718
- // }
719
- // }
720
- // return messages;
721
- // }
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
+ }
722
1019
  //# sourceMappingURL=mapping.js.map