ai 5.0.0-canary.9 → 5.0.1

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.
@@ -1,31 +1,131 @@
1
- // core/prompt/standardize-prompt.ts
2
- import { InvalidPromptError } from "@ai-sdk/provider";
3
- import { safeValidateTypes } from "@ai-sdk/provider-utils";
4
- import { z as z7 } from "zod";
1
+ // internal/index.ts
2
+ import { convertAsyncIteratorToReadableStream } from "@ai-sdk/provider-utils";
5
3
 
6
- // core/prompt/data-content.ts
7
- import { AISDKError as AISDKError2 } from "@ai-sdk/provider";
4
+ // src/prompt/convert-to-language-model-prompt.ts
8
5
  import {
9
- convertBase64ToUint8Array,
10
- convertUint8ArrayToBase64
6
+ isUrlSupported
11
7
  } from "@ai-sdk/provider-utils";
12
- import { z } from "zod";
13
8
 
14
- // core/prompt/invalid-data-content-error.ts
9
+ // src/util/detect-media-type.ts
10
+ import { convertBase64ToUint8Array } from "@ai-sdk/provider-utils";
11
+ var imageMediaTypeSignatures = [
12
+ {
13
+ mediaType: "image/gif",
14
+ bytesPrefix: [71, 73, 70],
15
+ base64Prefix: "R0lG"
16
+ },
17
+ {
18
+ mediaType: "image/png",
19
+ bytesPrefix: [137, 80, 78, 71],
20
+ base64Prefix: "iVBORw"
21
+ },
22
+ {
23
+ mediaType: "image/jpeg",
24
+ bytesPrefix: [255, 216],
25
+ base64Prefix: "/9j/"
26
+ },
27
+ {
28
+ mediaType: "image/webp",
29
+ bytesPrefix: [82, 73, 70, 70],
30
+ base64Prefix: "UklGRg"
31
+ },
32
+ {
33
+ mediaType: "image/bmp",
34
+ bytesPrefix: [66, 77],
35
+ base64Prefix: "Qk"
36
+ },
37
+ {
38
+ mediaType: "image/tiff",
39
+ bytesPrefix: [73, 73, 42, 0],
40
+ base64Prefix: "SUkqAA"
41
+ },
42
+ {
43
+ mediaType: "image/tiff",
44
+ bytesPrefix: [77, 77, 0, 42],
45
+ base64Prefix: "TU0AKg"
46
+ },
47
+ {
48
+ mediaType: "image/avif",
49
+ bytesPrefix: [
50
+ 0,
51
+ 0,
52
+ 0,
53
+ 32,
54
+ 102,
55
+ 116,
56
+ 121,
57
+ 112,
58
+ 97,
59
+ 118,
60
+ 105,
61
+ 102
62
+ ],
63
+ base64Prefix: "AAAAIGZ0eXBhdmlm"
64
+ },
65
+ {
66
+ mediaType: "image/heic",
67
+ bytesPrefix: [
68
+ 0,
69
+ 0,
70
+ 0,
71
+ 32,
72
+ 102,
73
+ 116,
74
+ 121,
75
+ 112,
76
+ 104,
77
+ 101,
78
+ 105,
79
+ 99
80
+ ],
81
+ base64Prefix: "AAAAIGZ0eXBoZWlj"
82
+ }
83
+ ];
84
+ var stripID3 = (data) => {
85
+ const bytes = typeof data === "string" ? convertBase64ToUint8Array(data) : data;
86
+ const id3Size = (bytes[6] & 127) << 21 | (bytes[7] & 127) << 14 | (bytes[8] & 127) << 7 | bytes[9] & 127;
87
+ return bytes.slice(id3Size + 10);
88
+ };
89
+ function stripID3TagsIfPresent(data) {
90
+ const hasId3 = typeof data === "string" && data.startsWith("SUQz") || typeof data !== "string" && data.length > 10 && data[0] === 73 && // 'I'
91
+ data[1] === 68 && // 'D'
92
+ data[2] === 51;
93
+ return hasId3 ? stripID3(data) : data;
94
+ }
95
+ function detectMediaType({
96
+ data,
97
+ signatures
98
+ }) {
99
+ const processedData = stripID3TagsIfPresent(data);
100
+ for (const signature of signatures) {
101
+ if (typeof processedData === "string" ? processedData.startsWith(signature.base64Prefix) : processedData.length >= signature.bytesPrefix.length && signature.bytesPrefix.every(
102
+ (byte, index) => processedData[index] === byte
103
+ )) {
104
+ return signature.mediaType;
105
+ }
106
+ }
107
+ return void 0;
108
+ }
109
+
110
+ // src/util/download-error.ts
15
111
  import { AISDKError } from "@ai-sdk/provider";
16
- var name = "AI_InvalidDataContentError";
112
+ var name = "AI_DownloadError";
17
113
  var marker = `vercel.ai.error.${name}`;
18
114
  var symbol = Symbol.for(marker);
19
115
  var _a;
20
- var InvalidDataContentError = class extends AISDKError {
116
+ var DownloadError = class extends AISDKError {
21
117
  constructor({
22
- content,
118
+ url,
119
+ statusCode,
120
+ statusText,
23
121
  cause,
24
- message = `Invalid data content. Expected a base64 string, Uint8Array, ArrayBuffer, or Buffer, but got ${typeof content}.`
122
+ message = cause == null ? `Failed to download ${url}: ${statusCode} ${statusText}` : `Failed to download ${url}: ${cause}`
25
123
  }) {
26
124
  super({ name, message, cause });
27
125
  this[_a] = true;
28
- this.content = content;
126
+ this.url = url;
127
+ this.statusCode = statusCode;
128
+ this.statusText = statusText;
29
129
  }
30
130
  static isInstance(error) {
31
131
  return AISDKError.hasMarker(error, marker);
@@ -33,7 +133,40 @@ var InvalidDataContentError = class extends AISDKError {
33
133
  };
34
134
  _a = symbol;
35
135
 
36
- // core/prompt/split-data-url.ts
136
+ // src/util/download.ts
137
+ async function download({ url }) {
138
+ var _a5;
139
+ const urlText = url.toString();
140
+ try {
141
+ const response = await fetch(urlText);
142
+ if (!response.ok) {
143
+ throw new DownloadError({
144
+ url: urlText,
145
+ statusCode: response.status,
146
+ statusText: response.statusText
147
+ });
148
+ }
149
+ return {
150
+ data: new Uint8Array(await response.arrayBuffer()),
151
+ mediaType: (_a5 = response.headers.get("content-type")) != null ? _a5 : void 0
152
+ };
153
+ } catch (error) {
154
+ if (DownloadError.isInstance(error)) {
155
+ throw error;
156
+ }
157
+ throw new DownloadError({ url: urlText, cause: error });
158
+ }
159
+ }
160
+
161
+ // src/prompt/data-content.ts
162
+ import { AISDKError as AISDKError2 } from "@ai-sdk/provider";
163
+ import {
164
+ convertBase64ToUint8Array as convertBase64ToUint8Array2,
165
+ convertUint8ArrayToBase64
166
+ } from "@ai-sdk/provider-utils";
167
+ import { z } from "zod/v4";
168
+
169
+ // src/prompt/split-data-url.ts
37
170
  function splitDataUrl(dataUrl) {
38
171
  try {
39
172
  const [header, base64Content] = dataUrl.split(",");
@@ -49,7 +182,7 @@ function splitDataUrl(dataUrl) {
49
182
  }
50
183
  }
51
184
 
52
- // core/prompt/data-content.ts
185
+ // src/prompt/data-content.ts
53
186
  var dataContentSchema = z.union([
54
187
  z.string(),
55
188
  z.instanceof(Uint8Array),
@@ -57,8 +190,8 @@ var dataContentSchema = z.union([
57
190
  z.custom(
58
191
  // Buffer might not be available in some environments such as CloudFlare:
59
192
  (value) => {
60
- var _a7, _b;
61
- return (_b = (_a7 = globalThis.Buffer) == null ? void 0 : _a7.isBuffer(value)) != null ? _b : false;
193
+ var _a5, _b;
194
+ return (_b = (_a5 = globalThis.Buffer) == null ? void 0 : _a5.isBuffer(value)) != null ? _b : false;
62
195
  },
63
196
  { message: "Must be a Buffer" }
64
197
  )
@@ -90,125 +223,21 @@ function convertToLanguageModelV2DataContent(content) {
90
223
  }
91
224
  return { data: content, mediaType: void 0 };
92
225
  }
93
- function convertDataContentToUint8Array(content) {
94
- if (content instanceof Uint8Array) {
95
- return content;
96
- }
97
- if (typeof content === "string") {
98
- try {
99
- return convertBase64ToUint8Array(content);
100
- } catch (error) {
101
- throw new InvalidDataContentError({
102
- message: "Invalid data content. Content string is not a base64-encoded media.",
103
- content,
104
- cause: error
105
- });
106
- }
107
- }
108
- if (content instanceof ArrayBuffer) {
109
- return new Uint8Array(content);
110
- }
111
- throw new InvalidDataContentError({ content });
112
- }
113
- function convertUint8ArrayToText(uint8Array) {
114
- try {
115
- return new TextDecoder().decode(uint8Array);
116
- } catch (error) {
117
- throw new Error("Error decoding Uint8Array to text");
118
- }
119
- }
120
-
121
- // core/prompt/attachments-to-parts.ts
122
- function attachmentsToParts(attachments) {
123
- var _a7, _b, _c;
124
- const parts = [];
125
- for (const attachment of attachments) {
126
- let url;
127
- try {
128
- url = new URL(attachment.url);
129
- } catch (error) {
130
- throw new Error(`Invalid URL: ${attachment.url}`);
131
- }
132
- switch (url.protocol) {
133
- case "http:":
134
- case "https:": {
135
- if ((_a7 = attachment.contentType) == null ? void 0 : _a7.startsWith("image/")) {
136
- parts.push({ type: "image", image: url });
137
- } else {
138
- if (!attachment.contentType) {
139
- throw new Error(
140
- "If the attachment is not an image, it must specify a content type"
141
- );
142
- }
143
- parts.push({
144
- type: "file",
145
- data: url,
146
- mediaType: attachment.contentType
147
- });
148
- }
149
- break;
150
- }
151
- case "data:": {
152
- let header;
153
- let base64Content;
154
- let mediaType;
155
- try {
156
- [header, base64Content] = attachment.url.split(",");
157
- mediaType = header.split(";")[0].split(":")[1];
158
- } catch (error) {
159
- throw new Error(`Error processing data URL: ${attachment.url}`);
160
- }
161
- if (mediaType == null || base64Content == null) {
162
- throw new Error(`Invalid data URL format: ${attachment.url}`);
163
- }
164
- if ((_b = attachment.contentType) == null ? void 0 : _b.startsWith("image/")) {
165
- parts.push({
166
- type: "image",
167
- image: convertDataContentToUint8Array(base64Content)
168
- });
169
- } else if ((_c = attachment.contentType) == null ? void 0 : _c.startsWith("text/")) {
170
- parts.push({
171
- type: "text",
172
- text: convertUint8ArrayToText(
173
- convertDataContentToUint8Array(base64Content)
174
- )
175
- });
176
- } else {
177
- if (!attachment.contentType) {
178
- throw new Error(
179
- "If the attachment is not an image or text, it must specify a content type"
180
- );
181
- }
182
- parts.push({
183
- type: "file",
184
- data: base64Content,
185
- mediaType: attachment.contentType
186
- });
187
- }
188
- break;
189
- }
190
- default: {
191
- throw new Error(`Unsupported URL protocol: ${url.protocol}`);
192
- }
193
- }
194
- }
195
- return parts;
196
- }
197
226
 
198
- // core/prompt/message-conversion-error.ts
227
+ // src/prompt/invalid-message-role-error.ts
199
228
  import { AISDKError as AISDKError3 } from "@ai-sdk/provider";
200
- var name2 = "AI_MessageConversionError";
229
+ var name2 = "AI_InvalidMessageRoleError";
201
230
  var marker2 = `vercel.ai.error.${name2}`;
202
231
  var symbol2 = Symbol.for(marker2);
203
232
  var _a2;
204
- var MessageConversionError = class extends AISDKError3 {
233
+ var InvalidMessageRoleError = class extends AISDKError3 {
205
234
  constructor({
206
- originalMessage,
207
- message
235
+ role,
236
+ message = `Invalid message role: '${role}'. Must be one of: "system", "user", "assistant", "tool".`
208
237
  }) {
209
238
  super({ name: name2, message });
210
239
  this[_a2] = true;
211
- this.originalMessage = originalMessage;
240
+ this.role = role;
212
241
  }
213
242
  static isInstance(error) {
214
243
  return AISDKError3.hasMarker(error, marker2);
@@ -216,292 +245,296 @@ var MessageConversionError = class extends AISDKError3 {
216
245
  };
217
246
  _a2 = symbol2;
218
247
 
219
- // core/prompt/convert-to-core-messages.ts
220
- function convertToCoreMessages(messages, options) {
221
- var _a7, _b;
222
- const tools = (_a7 = options == null ? void 0 : options.tools) != null ? _a7 : {};
223
- const coreMessages = [];
224
- for (let i = 0; i < messages.length; i++) {
225
- const message = messages[i];
226
- const isLastMessage = i === messages.length - 1;
227
- const { role, content, experimental_attachments } = message;
228
- switch (role) {
229
- case "system": {
230
- coreMessages.push({
231
- role: "system",
232
- content
233
- });
234
- break;
248
+ // src/prompt/convert-to-language-model-prompt.ts
249
+ async function convertToLanguageModelPrompt({
250
+ prompt,
251
+ supportedUrls,
252
+ downloadImplementation = download
253
+ }) {
254
+ const downloadedAssets = await downloadAssets(
255
+ prompt.messages,
256
+ downloadImplementation,
257
+ supportedUrls
258
+ );
259
+ return [
260
+ ...prompt.system != null ? [{ role: "system", content: prompt.system }] : [],
261
+ ...prompt.messages.map(
262
+ (message) => convertToLanguageModelMessage({ message, downloadedAssets })
263
+ )
264
+ ];
265
+ }
266
+ function convertToLanguageModelMessage({
267
+ message,
268
+ downloadedAssets
269
+ }) {
270
+ const role = message.role;
271
+ switch (role) {
272
+ case "system": {
273
+ return {
274
+ role: "system",
275
+ content: message.content,
276
+ providerOptions: message.providerOptions
277
+ };
278
+ }
279
+ case "user": {
280
+ if (typeof message.content === "string") {
281
+ return {
282
+ role: "user",
283
+ content: [{ type: "text", text: message.content }],
284
+ providerOptions: message.providerOptions
285
+ };
235
286
  }
236
- case "user": {
237
- if (message.parts == null) {
238
- coreMessages.push({
239
- role: "user",
240
- content: experimental_attachments ? [
241
- { type: "text", text: content },
242
- ...attachmentsToParts(experimental_attachments)
243
- ] : content
244
- });
245
- } else {
246
- const textParts = message.parts.filter((part) => part.type === "text").map((part) => ({
247
- type: "text",
248
- text: part.text
249
- }));
250
- coreMessages.push({
251
- role: "user",
252
- content: experimental_attachments ? [...textParts, ...attachmentsToParts(experimental_attachments)] : textParts
253
- });
254
- }
255
- break;
287
+ return {
288
+ role: "user",
289
+ content: message.content.map((part) => convertPartToLanguageModelPart(part, downloadedAssets)).filter((part) => part.type !== "text" || part.text !== ""),
290
+ providerOptions: message.providerOptions
291
+ };
292
+ }
293
+ case "assistant": {
294
+ if (typeof message.content === "string") {
295
+ return {
296
+ role: "assistant",
297
+ content: [{ type: "text", text: message.content }],
298
+ providerOptions: message.providerOptions
299
+ };
256
300
  }
257
- case "assistant": {
258
- if (message.parts != null) {
259
- let processBlock2 = function() {
260
- var _a8;
261
- const content2 = [];
262
- for (const part of block) {
263
- switch (part.type) {
264
- case "text": {
265
- content2.push(part);
266
- break;
267
- }
268
- case "file": {
269
- content2.push({
270
- type: "file",
271
- data: part.data,
272
- mediaType: (_a8 = part.mediaType) != null ? _a8 : part.mimeType
273
- // TODO migration, remove
274
- });
275
- break;
276
- }
277
- case "reasoning": {
278
- for (const detail of part.details) {
279
- switch (detail.type) {
280
- case "text":
281
- content2.push({
282
- type: "reasoning",
283
- text: detail.text,
284
- signature: detail.signature
285
- });
286
- break;
287
- case "redacted":
288
- content2.push({
289
- type: "redacted-reasoning",
290
- data: detail.data
291
- });
292
- break;
293
- }
294
- }
295
- break;
296
- }
297
- case "tool-invocation":
298
- content2.push({
299
- type: "tool-call",
300
- toolCallId: part.toolInvocation.toolCallId,
301
- toolName: part.toolInvocation.toolName,
302
- args: part.toolInvocation.args
303
- });
304
- break;
305
- default: {
306
- const _exhaustiveCheck = part;
307
- throw new Error(`Unsupported part: ${_exhaustiveCheck}`);
308
- }
309
- }
301
+ return {
302
+ role: "assistant",
303
+ content: message.content.filter(
304
+ // remove empty text parts:
305
+ (part) => part.type !== "text" || part.text !== ""
306
+ ).map((part) => {
307
+ const providerOptions = part.providerOptions;
308
+ switch (part.type) {
309
+ case "file": {
310
+ const { data, mediaType } = convertToLanguageModelV2DataContent(
311
+ part.data
312
+ );
313
+ return {
314
+ type: "file",
315
+ data,
316
+ filename: part.filename,
317
+ mediaType: mediaType != null ? mediaType : part.mediaType,
318
+ providerOptions
319
+ };
310
320
  }
311
- coreMessages.push({
312
- role: "assistant",
313
- content: content2
314
- });
315
- const stepInvocations = block.filter(
316
- (part) => part.type === "tool-invocation"
317
- ).map((part) => part.toolInvocation);
318
- if (stepInvocations.length > 0) {
319
- coreMessages.push({
320
- role: "tool",
321
- content: stepInvocations.map(
322
- (toolInvocation) => {
323
- if (!("result" in toolInvocation)) {
324
- throw new MessageConversionError({
325
- originalMessage: message,
326
- message: "ToolInvocation must have a result: " + JSON.stringify(toolInvocation)
327
- });
328
- }
329
- const { toolCallId, toolName, result } = toolInvocation;
330
- const tool = tools[toolName];
331
- return (tool == null ? void 0 : tool.experimental_toToolResultContent) != null ? {
332
- type: "tool-result",
333
- toolCallId,
334
- toolName,
335
- result: tool.experimental_toToolResultContent(result),
336
- experimental_content: tool.experimental_toToolResultContent(result)
337
- } : {
338
- type: "tool-result",
339
- toolCallId,
340
- toolName,
341
- result
342
- };
343
- }
344
- )
345
- });
321
+ case "reasoning": {
322
+ return {
323
+ type: "reasoning",
324
+ text: part.text,
325
+ providerOptions
326
+ };
346
327
  }
347
- block = [];
348
- blockHasToolInvocations = false;
349
- currentStep++;
350
- };
351
- var processBlock = processBlock2;
352
- let currentStep = 0;
353
- let blockHasToolInvocations = false;
354
- let block = [];
355
- for (const part of message.parts) {
356
- switch (part.type) {
357
- case "text": {
358
- if (blockHasToolInvocations) {
359
- processBlock2();
360
- }
361
- block.push(part);
362
- break;
363
- }
364
- case "file":
365
- case "reasoning": {
366
- block.push(part);
367
- break;
368
- }
369
- case "tool-invocation": {
370
- if (((_b = part.toolInvocation.step) != null ? _b : 0) !== currentStep) {
371
- processBlock2();
372
- }
373
- block.push(part);
374
- blockHasToolInvocations = true;
375
- break;
376
- }
328
+ case "text": {
329
+ return {
330
+ type: "text",
331
+ text: part.text,
332
+ providerOptions
333
+ };
377
334
  }
378
- }
379
- processBlock2();
380
- break;
381
- }
382
- const toolInvocations = message.toolInvocations;
383
- if (toolInvocations == null || toolInvocations.length === 0) {
384
- coreMessages.push({ role: "assistant", content });
385
- break;
386
- }
387
- const maxStep = toolInvocations.reduce((max, toolInvocation) => {
388
- var _a8;
389
- return Math.max(max, (_a8 = toolInvocation.step) != null ? _a8 : 0);
390
- }, 0);
391
- for (let i2 = 0; i2 <= maxStep; i2++) {
392
- const stepInvocations = toolInvocations.filter(
393
- (toolInvocation) => {
394
- var _a8;
395
- return ((_a8 = toolInvocation.step) != null ? _a8 : 0) === i2;
335
+ case "tool-call": {
336
+ return {
337
+ type: "tool-call",
338
+ toolCallId: part.toolCallId,
339
+ toolName: part.toolName,
340
+ input: part.input,
341
+ providerExecuted: part.providerExecuted,
342
+ providerOptions
343
+ };
396
344
  }
397
- );
398
- if (stepInvocations.length === 0) {
399
- continue;
400
- }
401
- coreMessages.push({
402
- role: "assistant",
403
- content: [
404
- ...isLastMessage && content && i2 === 0 ? [{ type: "text", text: content }] : [],
405
- ...stepInvocations.map(
406
- ({ toolCallId, toolName, args }) => ({
407
- type: "tool-call",
408
- toolCallId,
409
- toolName,
410
- args
411
- })
412
- )
413
- ]
414
- });
415
- coreMessages.push({
416
- role: "tool",
417
- content: stepInvocations.map((toolInvocation) => {
418
- if (!("result" in toolInvocation)) {
419
- throw new MessageConversionError({
420
- originalMessage: message,
421
- message: "ToolInvocation must have a result: " + JSON.stringify(toolInvocation)
422
- });
423
- }
424
- const { toolCallId, toolName, result } = toolInvocation;
425
- const tool = tools[toolName];
426
- return (tool == null ? void 0 : tool.experimental_toToolResultContent) != null ? {
427
- type: "tool-result",
428
- toolCallId,
429
- toolName,
430
- result: tool.experimental_toToolResultContent(result),
431
- experimental_content: tool.experimental_toToolResultContent(result)
432
- } : {
345
+ case "tool-result": {
346
+ return {
433
347
  type: "tool-result",
434
- toolCallId,
435
- toolName,
436
- result
348
+ toolCallId: part.toolCallId,
349
+ toolName: part.toolName,
350
+ output: part.output,
351
+ providerOptions
437
352
  };
438
- })
439
- });
440
- }
441
- if (content && !isLastMessage) {
442
- coreMessages.push({ role: "assistant", content });
443
- }
444
- break;
445
- }
446
- case "data": {
447
- break;
448
- }
449
- default: {
450
- const _exhaustiveCheck = role;
451
- throw new MessageConversionError({
452
- originalMessage: message,
453
- message: `Unsupported role: ${_exhaustiveCheck}`
454
- });
455
- }
353
+ }
354
+ }
355
+ }),
356
+ providerOptions: message.providerOptions
357
+ };
358
+ }
359
+ case "tool": {
360
+ return {
361
+ role: "tool",
362
+ content: message.content.map((part) => ({
363
+ type: "tool-result",
364
+ toolCallId: part.toolCallId,
365
+ toolName: part.toolName,
366
+ output: part.output,
367
+ providerOptions: part.providerOptions
368
+ })),
369
+ providerOptions: message.providerOptions
370
+ };
371
+ }
372
+ default: {
373
+ const _exhaustiveCheck = role;
374
+ throw new InvalidMessageRoleError({ role: _exhaustiveCheck });
456
375
  }
457
376
  }
458
- return coreMessages;
459
377
  }
460
-
461
- // core/prompt/detect-prompt-type.ts
462
- function detectPromptType(prompt) {
463
- if (!Array.isArray(prompt)) {
464
- return "other";
378
+ async function downloadAssets(messages, downloadImplementation, supportedUrls) {
379
+ const urls = messages.filter((message) => message.role === "user").map((message) => message.content).filter(
380
+ (content) => Array.isArray(content)
381
+ ).flat().filter(
382
+ (part) => part.type === "image" || part.type === "file"
383
+ ).map((part) => {
384
+ var _a5;
385
+ const mediaType = (_a5 = part.mediaType) != null ? _a5 : part.type === "image" ? "image/*" : void 0;
386
+ let data = part.type === "image" ? part.image : part.data;
387
+ if (typeof data === "string") {
388
+ try {
389
+ data = new URL(data);
390
+ } catch (ignored) {
391
+ }
392
+ }
393
+ return { mediaType, data };
394
+ }).filter(
395
+ (part) => part.data instanceof URL && part.mediaType != null && !isUrlSupported({
396
+ url: part.data.toString(),
397
+ mediaType: part.mediaType,
398
+ supportedUrls
399
+ })
400
+ ).map((part) => part.data);
401
+ const downloadedImages = await Promise.all(
402
+ urls.map(async (url) => ({
403
+ url,
404
+ data: await downloadImplementation({ url })
405
+ }))
406
+ );
407
+ return Object.fromEntries(
408
+ downloadedImages.map(({ url, data }) => [url.toString(), data])
409
+ );
410
+ }
411
+ function convertPartToLanguageModelPart(part, downloadedAssets) {
412
+ var _a5;
413
+ if (part.type === "text") {
414
+ return {
415
+ type: "text",
416
+ text: part.text,
417
+ providerOptions: part.providerOptions
418
+ };
465
419
  }
466
- if (prompt.length === 0) {
467
- return "messages";
420
+ let originalData;
421
+ const type = part.type;
422
+ switch (type) {
423
+ case "image":
424
+ originalData = part.image;
425
+ break;
426
+ case "file":
427
+ originalData = part.data;
428
+ break;
429
+ default:
430
+ throw new Error(`Unsupported part type: ${type}`);
468
431
  }
469
- const characteristics = prompt.map(detectSingleMessageCharacteristics);
470
- if (characteristics.some((c) => c === "has-ui-specific-parts")) {
471
- return "ui-messages";
472
- } else if (characteristics.every(
473
- (c) => c === "has-core-specific-parts" || c === "message"
474
- )) {
475
- return "messages";
476
- } else {
477
- return "other";
432
+ const { data: convertedData, mediaType: convertedMediaType } = convertToLanguageModelV2DataContent(originalData);
433
+ let mediaType = convertedMediaType != null ? convertedMediaType : part.mediaType;
434
+ let data = convertedData;
435
+ if (data instanceof URL) {
436
+ const downloadedFile = downloadedAssets[data.toString()];
437
+ if (downloadedFile) {
438
+ data = downloadedFile.data;
439
+ mediaType != null ? mediaType : mediaType = downloadedFile.mediaType;
440
+ }
441
+ }
442
+ switch (type) {
443
+ case "image": {
444
+ if (data instanceof Uint8Array || typeof data === "string") {
445
+ mediaType = (_a5 = detectMediaType({ data, signatures: imageMediaTypeSignatures })) != null ? _a5 : mediaType;
446
+ }
447
+ return {
448
+ type: "file",
449
+ mediaType: mediaType != null ? mediaType : "image/*",
450
+ // any image
451
+ filename: void 0,
452
+ data,
453
+ providerOptions: part.providerOptions
454
+ };
455
+ }
456
+ case "file": {
457
+ if (mediaType == null) {
458
+ throw new Error(`Media type is missing for file part`);
459
+ }
460
+ return {
461
+ type: "file",
462
+ mediaType,
463
+ filename: part.filename,
464
+ data,
465
+ providerOptions: part.providerOptions
466
+ };
467
+ }
478
468
  }
479
469
  }
480
- function detectSingleMessageCharacteristics(message) {
481
- if (typeof message === "object" && message !== null && (message.role === "function" || // UI-only role
482
- message.role === "data" || // UI-only role
483
- "toolInvocations" in message || // UI-specific field
484
- "parts" in message || // UI-specific field
485
- "experimental_attachments" in message)) {
486
- return "has-ui-specific-parts";
487
- } else if (typeof message === "object" && message !== null && "content" in message && (Array.isArray(message.content) || // Core messages can have array content
488
- "providerOptions" in message)) {
489
- return "has-core-specific-parts";
490
- } else if (typeof message === "object" && message !== null && "role" in message && "content" in message && typeof message.content === "string" && ["system", "user", "assistant", "tool"].includes(message.role)) {
491
- return "message";
492
- } else {
493
- return "other";
470
+
471
+ // src/prompt/prepare-tools-and-tool-choice.ts
472
+ import { asSchema } from "@ai-sdk/provider-utils";
473
+
474
+ // src/util/is-non-empty-object.ts
475
+ function isNonEmptyObject(object) {
476
+ return object != null && Object.keys(object).length > 0;
477
+ }
478
+
479
+ // src/prompt/prepare-tools-and-tool-choice.ts
480
+ function prepareToolsAndToolChoice({
481
+ tools,
482
+ toolChoice,
483
+ activeTools
484
+ }) {
485
+ if (!isNonEmptyObject(tools)) {
486
+ return {
487
+ tools: void 0,
488
+ toolChoice: void 0
489
+ };
494
490
  }
491
+ const filteredTools = activeTools != null ? Object.entries(tools).filter(
492
+ ([name5]) => activeTools.includes(name5)
493
+ ) : Object.entries(tools);
494
+ return {
495
+ tools: filteredTools.map(([name5, tool]) => {
496
+ const toolType = tool.type;
497
+ switch (toolType) {
498
+ case void 0:
499
+ case "dynamic":
500
+ case "function":
501
+ return {
502
+ type: "function",
503
+ name: name5,
504
+ description: tool.description,
505
+ inputSchema: asSchema(tool.inputSchema).jsonSchema,
506
+ providerOptions: tool.providerOptions
507
+ };
508
+ case "provider-defined":
509
+ return {
510
+ type: "provider-defined",
511
+ name: name5,
512
+ id: tool.id,
513
+ args: tool.args
514
+ };
515
+ default: {
516
+ const exhaustiveCheck = toolType;
517
+ throw new Error(`Unsupported tool type: ${exhaustiveCheck}`);
518
+ }
519
+ }
520
+ }),
521
+ toolChoice: toolChoice == null ? { type: "auto" } : typeof toolChoice === "string" ? { type: toolChoice } : { type: "tool", toolName: toolChoice.toolName }
522
+ };
495
523
  }
496
524
 
497
- // core/prompt/message.ts
498
- import { z as z6 } from "zod";
525
+ // src/prompt/standardize-prompt.ts
526
+ import { InvalidPromptError } from "@ai-sdk/provider";
527
+ import { safeValidateTypes } from "@ai-sdk/provider-utils";
528
+ import { z as z6 } from "zod/v4";
529
+
530
+ // src/prompt/message.ts
531
+ import { z as z5 } from "zod/v4";
499
532
 
500
- // core/types/provider-metadata.ts
501
- import { z as z3 } from "zod";
533
+ // src/types/provider-metadata.ts
534
+ import { z as z3 } from "zod/v4";
502
535
 
503
- // core/types/json-value.ts
504
- import { z as z2 } from "zod";
536
+ // src/types/json-value.ts
537
+ import { z as z2 } from "zod/v4";
505
538
  var jsonValueSchema = z2.lazy(
506
539
  () => z2.union([
507
540
  z2.null(),
@@ -513,123 +546,133 @@ var jsonValueSchema = z2.lazy(
513
546
  ])
514
547
  );
515
548
 
516
- // core/types/provider-metadata.ts
549
+ // src/types/provider-metadata.ts
517
550
  var providerMetadataSchema = z3.record(
518
551
  z3.string(),
519
552
  z3.record(z3.string(), jsonValueSchema)
520
553
  );
521
554
 
522
- // core/prompt/content-part.ts
523
- import { z as z5 } from "zod";
524
-
525
- // core/prompt/tool-result-content.ts
526
- import { z as z4 } from "zod";
527
- var toolResultContentSchema = z4.array(
528
- z4.union([
529
- z4.object({ type: z4.literal("text"), text: z4.string() }),
530
- z4.object({
531
- type: z4.literal("image"),
532
- data: z4.string(),
533
- mediaType: z4.string().optional()
534
- })
535
- ])
536
- );
537
-
538
- // core/prompt/content-part.ts
539
- var textPartSchema = z5.object({
540
- type: z5.literal("text"),
541
- text: z5.string(),
542
- providerOptions: providerMetadataSchema.optional()
543
- });
544
- var imagePartSchema = z5.object({
545
- type: z5.literal("image"),
546
- image: z5.union([dataContentSchema, z5.instanceof(URL)]),
547
- mediaType: z5.string().optional(),
548
- mimeType: z5.string().optional(),
555
+ // src/prompt/content-part.ts
556
+ import { z as z4 } from "zod/v4";
557
+ var textPartSchema = z4.object({
558
+ type: z4.literal("text"),
559
+ text: z4.string(),
549
560
  providerOptions: providerMetadataSchema.optional()
550
561
  });
551
- var filePartSchema = z5.object({
552
- type: z5.literal("file"),
553
- data: z5.union([dataContentSchema, z5.instanceof(URL)]),
554
- filename: z5.string().optional(),
555
- mediaType: z5.string(),
556
- mimeType: z5.string().optional(),
562
+ var imagePartSchema = z4.object({
563
+ type: z4.literal("image"),
564
+ image: z4.union([dataContentSchema, z4.instanceof(URL)]),
565
+ mediaType: z4.string().optional(),
557
566
  providerOptions: providerMetadataSchema.optional()
558
567
  });
559
- var reasoningPartSchema = z5.object({
560
- type: z5.literal("reasoning"),
561
- text: z5.string(),
568
+ var filePartSchema = z4.object({
569
+ type: z4.literal("file"),
570
+ data: z4.union([dataContentSchema, z4.instanceof(URL)]),
571
+ filename: z4.string().optional(),
572
+ mediaType: z4.string(),
562
573
  providerOptions: providerMetadataSchema.optional()
563
574
  });
564
- var redactedReasoningPartSchema = z5.object({
565
- type: z5.literal("redacted-reasoning"),
566
- data: z5.string(),
575
+ var reasoningPartSchema = z4.object({
576
+ type: z4.literal("reasoning"),
577
+ text: z4.string(),
567
578
  providerOptions: providerMetadataSchema.optional()
568
579
  });
569
- var toolCallPartSchema = z5.object({
570
- type: z5.literal("tool-call"),
571
- toolCallId: z5.string(),
572
- toolName: z5.string(),
573
- args: z5.unknown(),
574
- providerOptions: providerMetadataSchema.optional()
580
+ var toolCallPartSchema = z4.object({
581
+ type: z4.literal("tool-call"),
582
+ toolCallId: z4.string(),
583
+ toolName: z4.string(),
584
+ input: z4.unknown(),
585
+ providerOptions: providerMetadataSchema.optional(),
586
+ providerExecuted: z4.boolean().optional()
575
587
  });
576
- var toolResultPartSchema = z5.object({
577
- type: z5.literal("tool-result"),
578
- toolCallId: z5.string(),
579
- toolName: z5.string(),
580
- result: z5.unknown(),
581
- content: toolResultContentSchema.optional(),
582
- isError: z5.boolean().optional(),
588
+ var outputSchema = z4.discriminatedUnion("type", [
589
+ z4.object({
590
+ type: z4.literal("text"),
591
+ value: z4.string()
592
+ }),
593
+ z4.object({
594
+ type: z4.literal("json"),
595
+ value: jsonValueSchema
596
+ }),
597
+ z4.object({
598
+ type: z4.literal("error-text"),
599
+ value: z4.string()
600
+ }),
601
+ z4.object({
602
+ type: z4.literal("error-json"),
603
+ value: jsonValueSchema
604
+ }),
605
+ z4.object({
606
+ type: z4.literal("content"),
607
+ value: z4.array(
608
+ z4.union([
609
+ z4.object({
610
+ type: z4.literal("text"),
611
+ text: z4.string()
612
+ }),
613
+ z4.object({
614
+ type: z4.literal("media"),
615
+ data: z4.string(),
616
+ mediaType: z4.string()
617
+ })
618
+ ])
619
+ )
620
+ })
621
+ ]);
622
+ var toolResultPartSchema = z4.object({
623
+ type: z4.literal("tool-result"),
624
+ toolCallId: z4.string(),
625
+ toolName: z4.string(),
626
+ output: outputSchema,
583
627
  providerOptions: providerMetadataSchema.optional()
584
628
  });
585
629
 
586
- // core/prompt/message.ts
587
- var coreSystemMessageSchema = z6.object({
588
- role: z6.literal("system"),
589
- content: z6.string(),
590
- providerOptions: providerMetadataSchema.optional()
591
- });
592
- var coreUserMessageSchema = z6.object({
593
- role: z6.literal("user"),
594
- content: z6.union([
595
- z6.string(),
596
- z6.array(z6.union([textPartSchema, imagePartSchema, filePartSchema]))
630
+ // src/prompt/message.ts
631
+ var systemModelMessageSchema = z5.object(
632
+ {
633
+ role: z5.literal("system"),
634
+ content: z5.string(),
635
+ providerOptions: providerMetadataSchema.optional()
636
+ }
637
+ );
638
+ var userModelMessageSchema = z5.object({
639
+ role: z5.literal("user"),
640
+ content: z5.union([
641
+ z5.string(),
642
+ z5.array(z5.union([textPartSchema, imagePartSchema, filePartSchema]))
597
643
  ]),
598
644
  providerOptions: providerMetadataSchema.optional()
599
645
  });
600
- var coreAssistantMessageSchema = z6.object({
601
- role: z6.literal("assistant"),
602
- content: z6.union([
603
- z6.string(),
604
- z6.array(
605
- z6.union([
646
+ var assistantModelMessageSchema = z5.object({
647
+ role: z5.literal("assistant"),
648
+ content: z5.union([
649
+ z5.string(),
650
+ z5.array(
651
+ z5.union([
606
652
  textPartSchema,
607
653
  filePartSchema,
608
654
  reasoningPartSchema,
609
- redactedReasoningPartSchema,
610
- toolCallPartSchema
655
+ toolCallPartSchema,
656
+ toolResultPartSchema
611
657
  ])
612
658
  )
613
659
  ]),
614
660
  providerOptions: providerMetadataSchema.optional()
615
661
  });
616
- var coreToolMessageSchema = z6.object({
617
- role: z6.literal("tool"),
618
- content: z6.array(toolResultPartSchema),
662
+ var toolModelMessageSchema = z5.object({
663
+ role: z5.literal("tool"),
664
+ content: z5.array(toolResultPartSchema),
619
665
  providerOptions: providerMetadataSchema.optional()
620
666
  });
621
- var coreMessageSchema = z6.union([
622
- coreSystemMessageSchema,
623
- coreUserMessageSchema,
624
- coreAssistantMessageSchema,
625
- coreToolMessageSchema
667
+ var modelMessageSchema = z5.union([
668
+ systemModelMessageSchema,
669
+ userModelMessageSchema,
670
+ assistantModelMessageSchema,
671
+ toolModelMessageSchema
626
672
  ]);
627
673
 
628
- // core/prompt/standardize-prompt.ts
629
- function standardizePrompt({
630
- prompt,
631
- tools
632
- }) {
674
+ // src/prompt/standardize-prompt.ts
675
+ async function standardizePrompt(prompt) {
633
676
  if (prompt.prompt == null && prompt.messages == null) {
634
677
  throw new InvalidPromptError({
635
678
  prompt,
@@ -648,161 +691,43 @@ function standardizePrompt({
648
691
  message: "system must be a string"
649
692
  });
650
693
  }
651
- if (prompt.prompt != null) {
652
- if (typeof prompt.prompt !== "string") {
653
- throw new InvalidPromptError({
654
- prompt,
655
- message: "prompt must be a string"
656
- });
657
- }
658
- return {
659
- type: "prompt",
660
- system: prompt.system,
661
- messages: [
662
- {
663
- role: "user",
664
- content: prompt.prompt
665
- }
666
- ]
667
- };
694
+ let messages;
695
+ if (prompt.prompt != null && typeof prompt.prompt === "string") {
696
+ messages = [{ role: "user", content: prompt.prompt }];
697
+ } else if (prompt.prompt != null && Array.isArray(prompt.prompt)) {
698
+ messages = prompt.prompt;
699
+ } else if (prompt.messages != null) {
700
+ messages = prompt.messages;
701
+ } else {
702
+ throw new InvalidPromptError({
703
+ prompt,
704
+ message: "prompt or messages must be defined"
705
+ });
668
706
  }
669
- if (prompt.messages != null) {
670
- const promptType = detectPromptType(prompt.messages);
671
- if (promptType === "other") {
672
- throw new InvalidPromptError({
673
- prompt,
674
- message: "messages must be an array of CoreMessage or UIMessage"
675
- });
676
- }
677
- const messages = promptType === "ui-messages" ? convertToCoreMessages(prompt.messages, {
678
- tools
679
- }) : prompt.messages;
680
- if (messages.length === 0) {
681
- throw new InvalidPromptError({
682
- prompt,
683
- message: "messages must not be empty"
684
- });
685
- }
686
- const validationResult = safeValidateTypes({
687
- value: messages,
688
- schema: z7.array(coreMessageSchema)
707
+ if (messages.length === 0) {
708
+ throw new InvalidPromptError({
709
+ prompt,
710
+ message: "messages must not be empty"
689
711
  });
690
- if (!validationResult.success) {
691
- throw new InvalidPromptError({
692
- prompt,
693
- message: "messages must be an array of CoreMessage or UIMessage",
694
- cause: validationResult.error
695
- });
696
- }
697
- return {
698
- type: "messages",
699
- messages,
700
- system: prompt.system
701
- };
702
712
  }
703
- throw new Error("unreachable");
704
- }
705
-
706
- // core/util/index.ts
707
- import { generateId } from "@ai-sdk/provider-utils";
708
-
709
- // core/util/schema.ts
710
- import { validatorSymbol } from "@ai-sdk/provider-utils";
711
-
712
- // core/util/zod-schema.ts
713
- import zodToJsonSchema from "zod-to-json-schema";
714
- function zodSchema(zodSchema2, options) {
715
- var _a7;
716
- const useReferences = (_a7 = options == null ? void 0 : options.useReferences) != null ? _a7 : false;
717
- return jsonSchema(
718
- zodToJsonSchema(zodSchema2, {
719
- $refStrategy: useReferences ? "root" : "none",
720
- target: "jsonSchema7"
721
- // note: openai mode breaks various gemini conversions
722
- }),
723
- {
724
- validate: (value) => {
725
- const result = zodSchema2.safeParse(value);
726
- return result.success ? { success: true, value: result.data } : { success: false, error: result.error };
727
- }
728
- }
729
- );
730
- }
731
-
732
- // core/util/schema.ts
733
- var schemaSymbol = Symbol.for("vercel.ai.schema");
734
- function jsonSchema(jsonSchema2, {
735
- validate
736
- } = {}) {
737
- return {
738
- [schemaSymbol]: true,
739
- _type: void 0,
740
- // should never be used directly
741
- [validatorSymbol]: true,
742
- jsonSchema: jsonSchema2,
743
- validate
744
- };
745
- }
746
- function isSchema(value) {
747
- return typeof value === "object" && value !== null && schemaSymbol in value && value[schemaSymbol] === true && "jsonSchema" in value && "validate" in value;
748
- }
749
- function asSchema(schema) {
750
- return schema == null ? jsonSchema({
751
- properties: {},
752
- additionalProperties: false
753
- }) : isSchema(schema) ? schema : zodSchema(schema);
754
- }
755
-
756
- // core/util/is-non-empty-object.ts
757
- function isNonEmptyObject(object) {
758
- return object != null && Object.keys(object).length > 0;
759
- }
760
-
761
- // core/prompt/prepare-tools-and-tool-choice.ts
762
- function prepareToolsAndToolChoice({
763
- tools,
764
- toolChoice,
765
- activeTools
766
- }) {
767
- if (!isNonEmptyObject(tools)) {
768
- return {
769
- tools: void 0,
770
- toolChoice: void 0
771
- };
713
+ const validationResult = await safeValidateTypes({
714
+ value: messages,
715
+ schema: z6.array(modelMessageSchema)
716
+ });
717
+ if (!validationResult.success) {
718
+ throw new InvalidPromptError({
719
+ prompt,
720
+ message: "The messages must be a ModelMessage[]. If you have passed a UIMessage[], you can use convertToModelMessages to convert them.",
721
+ cause: validationResult.error
722
+ });
772
723
  }
773
- const filteredTools = activeTools != null ? Object.entries(tools).filter(
774
- ([name7]) => activeTools.includes(name7)
775
- ) : Object.entries(tools);
776
724
  return {
777
- tools: filteredTools.map(([name7, tool]) => {
778
- const toolType = tool.type;
779
- switch (toolType) {
780
- case void 0:
781
- case "function":
782
- return {
783
- type: "function",
784
- name: name7,
785
- description: tool.description,
786
- parameters: asSchema(tool.parameters).jsonSchema
787
- };
788
- case "provider-defined":
789
- return {
790
- type: "provider-defined",
791
- name: name7,
792
- id: tool.id,
793
- args: tool.args
794
- };
795
- default: {
796
- const exhaustiveCheck = toolType;
797
- throw new Error(`Unsupported tool type: ${exhaustiveCheck}`);
798
- }
799
- }
800
- }),
801
- toolChoice: toolChoice == null ? { type: "auto" } : typeof toolChoice === "string" ? { type: toolChoice } : { type: "tool", toolName: toolChoice.toolName }
725
+ messages,
726
+ system: prompt.system
802
727
  };
803
728
  }
804
729
 
805
- // errors/invalid-argument-error.ts
730
+ // src/error/invalid-argument-error.ts
806
731
  import { AISDKError as AISDKError4 } from "@ai-sdk/provider";
807
732
  var name3 = "AI_InvalidArgumentError";
808
733
  var marker3 = `vercel.ai.error.${name3}`;
@@ -828,115 +753,7 @@ var InvalidArgumentError = class extends AISDKError4 {
828
753
  };
829
754
  _a3 = symbol3;
830
755
 
831
- // util/retry-with-exponential-backoff.ts
832
- import { APICallError } from "@ai-sdk/provider";
833
- import { delay, getErrorMessage, isAbortError } from "@ai-sdk/provider-utils";
834
-
835
- // util/retry-error.ts
836
- import { AISDKError as AISDKError5 } from "@ai-sdk/provider";
837
- var name4 = "AI_RetryError";
838
- var marker4 = `vercel.ai.error.${name4}`;
839
- var symbol4 = Symbol.for(marker4);
840
- var _a4;
841
- var RetryError = class extends AISDKError5 {
842
- constructor({
843
- message,
844
- reason,
845
- errors
846
- }) {
847
- super({ name: name4, message });
848
- this[_a4] = true;
849
- this.reason = reason;
850
- this.errors = errors;
851
- this.lastError = errors[errors.length - 1];
852
- }
853
- static isInstance(error) {
854
- return AISDKError5.hasMarker(error, marker4);
855
- }
856
- };
857
- _a4 = symbol4;
858
-
859
- // util/retry-with-exponential-backoff.ts
860
- var retryWithExponentialBackoff = ({
861
- maxRetries = 2,
862
- initialDelayInMs = 2e3,
863
- backoffFactor = 2
864
- } = {}) => async (f) => _retryWithExponentialBackoff(f, {
865
- maxRetries,
866
- delayInMs: initialDelayInMs,
867
- backoffFactor
868
- });
869
- async function _retryWithExponentialBackoff(f, {
870
- maxRetries,
871
- delayInMs,
872
- backoffFactor
873
- }, errors = []) {
874
- try {
875
- return await f();
876
- } catch (error) {
877
- if (isAbortError(error)) {
878
- throw error;
879
- }
880
- if (maxRetries === 0) {
881
- throw error;
882
- }
883
- const errorMessage = getErrorMessage(error);
884
- const newErrors = [...errors, error];
885
- const tryNumber = newErrors.length;
886
- if (tryNumber > maxRetries) {
887
- throw new RetryError({
888
- message: `Failed after ${tryNumber} attempts. Last error: ${errorMessage}`,
889
- reason: "maxRetriesExceeded",
890
- errors: newErrors
891
- });
892
- }
893
- if (error instanceof Error && APICallError.isInstance(error) && error.isRetryable === true && tryNumber <= maxRetries) {
894
- await delay(delayInMs);
895
- return _retryWithExponentialBackoff(
896
- f,
897
- { maxRetries, delayInMs: backoffFactor * delayInMs, backoffFactor },
898
- newErrors
899
- );
900
- }
901
- if (tryNumber === 1) {
902
- throw error;
903
- }
904
- throw new RetryError({
905
- message: `Failed after ${tryNumber} attempts with non-retryable error: '${errorMessage}'`,
906
- reason: "errorNotRetryable",
907
- errors: newErrors
908
- });
909
- }
910
- }
911
-
912
- // core/prompt/prepare-retries.ts
913
- function prepareRetries({
914
- maxRetries
915
- }) {
916
- if (maxRetries != null) {
917
- if (!Number.isInteger(maxRetries)) {
918
- throw new InvalidArgumentError({
919
- parameter: "maxRetries",
920
- value: maxRetries,
921
- message: "maxRetries must be an integer"
922
- });
923
- }
924
- if (maxRetries < 0) {
925
- throw new InvalidArgumentError({
926
- parameter: "maxRetries",
927
- value: maxRetries,
928
- message: "maxRetries must be >= 0"
929
- });
930
- }
931
- }
932
- const maxRetriesResult = maxRetries != null ? maxRetries : 2;
933
- return {
934
- maxRetries: maxRetriesResult,
935
- retry: retryWithExponentialBackoff({ maxRetries: maxRetriesResult })
936
- };
937
- }
938
-
939
- // core/prompt/prepare-call-settings.ts
756
+ // src/prompt/prepare-call-settings.ts
940
757
  function prepareCallSettings({
941
758
  maxOutputTokens,
942
759
  temperature,
@@ -944,8 +761,8 @@ function prepareCallSettings({
944
761
  topK,
945
762
  presencePenalty,
946
763
  frequencyPenalty,
947
- stopSequences,
948
- seed
764
+ seed,
765
+ stopSequences
949
766
  }) {
950
767
  if (maxOutputTokens != null) {
951
768
  if (!Number.isInteger(maxOutputTokens)) {
@@ -1019,405 +836,172 @@ function prepareCallSettings({
1019
836
  }
1020
837
  return {
1021
838
  maxOutputTokens,
1022
- // TODO v5 remove default 0 for temperature
1023
- temperature: temperature != null ? temperature : 0,
839
+ temperature,
1024
840
  topP,
1025
841
  topK,
1026
842
  presencePenalty,
1027
843
  frequencyPenalty,
1028
- stopSequences: stopSequences != null && stopSequences.length > 0 ? stopSequences : void 0,
844
+ stopSequences,
1029
845
  seed
1030
846
  };
1031
847
  }
1032
848
 
1033
- // util/download-error.ts
1034
- import { AISDKError as AISDKError6 } from "@ai-sdk/provider";
1035
- var name5 = "AI_DownloadError";
1036
- var marker5 = `vercel.ai.error.${name5}`;
1037
- var symbol5 = Symbol.for(marker5);
1038
- var _a5;
1039
- var DownloadError = class extends AISDKError6 {
849
+ // src/util/retry-with-exponential-backoff.ts
850
+ import { APICallError } from "@ai-sdk/provider";
851
+ import { delay, getErrorMessage, isAbortError } from "@ai-sdk/provider-utils";
852
+
853
+ // src/util/retry-error.ts
854
+ import { AISDKError as AISDKError5 } from "@ai-sdk/provider";
855
+ var name4 = "AI_RetryError";
856
+ var marker4 = `vercel.ai.error.${name4}`;
857
+ var symbol4 = Symbol.for(marker4);
858
+ var _a4;
859
+ var RetryError = class extends AISDKError5 {
1040
860
  constructor({
1041
- url,
1042
- statusCode,
1043
- statusText,
1044
- cause,
1045
- message = cause == null ? `Failed to download ${url}: ${statusCode} ${statusText}` : `Failed to download ${url}: ${cause}`
861
+ message,
862
+ reason,
863
+ errors
1046
864
  }) {
1047
- super({ name: name5, message, cause });
1048
- this[_a5] = true;
1049
- this.url = url;
1050
- this.statusCode = statusCode;
1051
- this.statusText = statusText;
865
+ super({ name: name4, message });
866
+ this[_a4] = true;
867
+ this.reason = reason;
868
+ this.errors = errors;
869
+ this.lastError = errors[errors.length - 1];
1052
870
  }
1053
871
  static isInstance(error) {
1054
- return AISDKError6.hasMarker(error, marker5);
872
+ return AISDKError5.hasMarker(error, marker4);
1055
873
  }
1056
874
  };
1057
- _a5 = symbol5;
875
+ _a4 = symbol4;
1058
876
 
1059
- // util/download.ts
1060
- async function download({ url }) {
1061
- var _a7;
1062
- const urlText = url.toString();
877
+ // src/util/retry-with-exponential-backoff.ts
878
+ function getRetryDelayInMs({
879
+ error,
880
+ exponentialBackoffDelay
881
+ }) {
882
+ const headers = error.responseHeaders;
883
+ if (!headers)
884
+ return exponentialBackoffDelay;
885
+ let ms;
886
+ const retryAfterMs = headers["retry-after-ms"];
887
+ if (retryAfterMs) {
888
+ const timeoutMs = parseFloat(retryAfterMs);
889
+ if (!Number.isNaN(timeoutMs)) {
890
+ ms = timeoutMs;
891
+ }
892
+ }
893
+ const retryAfter = headers["retry-after"];
894
+ if (retryAfter && ms === void 0) {
895
+ const timeoutSeconds = parseFloat(retryAfter);
896
+ if (!Number.isNaN(timeoutSeconds)) {
897
+ ms = timeoutSeconds * 1e3;
898
+ } else {
899
+ ms = Date.parse(retryAfter) - Date.now();
900
+ }
901
+ }
902
+ if (ms != null && !Number.isNaN(ms) && 0 <= ms && (ms < 60 * 1e3 || ms < exponentialBackoffDelay)) {
903
+ return ms;
904
+ }
905
+ return exponentialBackoffDelay;
906
+ }
907
+ var retryWithExponentialBackoffRespectingRetryHeaders = ({
908
+ maxRetries = 2,
909
+ initialDelayInMs = 2e3,
910
+ backoffFactor = 2,
911
+ abortSignal
912
+ } = {}) => async (f) => _retryWithExponentialBackoff(f, {
913
+ maxRetries,
914
+ delayInMs: initialDelayInMs,
915
+ backoffFactor,
916
+ abortSignal
917
+ });
918
+ async function _retryWithExponentialBackoff(f, {
919
+ maxRetries,
920
+ delayInMs,
921
+ backoffFactor,
922
+ abortSignal
923
+ }, errors = []) {
1063
924
  try {
1064
- const response = await fetch(urlText);
1065
- if (!response.ok) {
1066
- throw new DownloadError({
1067
- url: urlText,
1068
- statusCode: response.status,
1069
- statusText: response.statusText
1070
- });
1071
- }
1072
- return {
1073
- data: new Uint8Array(await response.arrayBuffer()),
1074
- mediaType: (_a7 = response.headers.get("content-type")) != null ? _a7 : void 0
1075
- };
925
+ return await f();
1076
926
  } catch (error) {
1077
- if (DownloadError.isInstance(error)) {
927
+ if (isAbortError(error)) {
1078
928
  throw error;
1079
929
  }
1080
- throw new DownloadError({ url: urlText, cause: error });
1081
- }
1082
- }
1083
-
1084
- // core/util/detect-media-type.ts
1085
- var imageMediaTypeSignatures = [
1086
- {
1087
- mediaType: "image/gif",
1088
- bytesPrefix: [71, 73, 70],
1089
- base64Prefix: "R0lG"
1090
- },
1091
- {
1092
- mediaType: "image/png",
1093
- bytesPrefix: [137, 80, 78, 71],
1094
- base64Prefix: "iVBORw"
1095
- },
1096
- {
1097
- mediaType: "image/jpeg",
1098
- bytesPrefix: [255, 216],
1099
- base64Prefix: "/9j/"
1100
- },
1101
- {
1102
- mediaType: "image/webp",
1103
- bytesPrefix: [82, 73, 70, 70],
1104
- base64Prefix: "UklGRg"
1105
- },
1106
- {
1107
- mediaType: "image/bmp",
1108
- bytesPrefix: [66, 77],
1109
- base64Prefix: "Qk"
1110
- },
1111
- {
1112
- mediaType: "image/tiff",
1113
- bytesPrefix: [73, 73, 42, 0],
1114
- base64Prefix: "SUkqAA"
1115
- },
1116
- {
1117
- mediaType: "image/tiff",
1118
- bytesPrefix: [77, 77, 0, 42],
1119
- base64Prefix: "TU0AKg"
1120
- },
1121
- {
1122
- mediaType: "image/avif",
1123
- bytesPrefix: [
1124
- 0,
1125
- 0,
1126
- 0,
1127
- 32,
1128
- 102,
1129
- 116,
1130
- 121,
1131
- 112,
1132
- 97,
1133
- 118,
1134
- 105,
1135
- 102
1136
- ],
1137
- base64Prefix: "AAAAIGZ0eXBhdmlm"
1138
- },
1139
- {
1140
- mediaType: "image/heic",
1141
- bytesPrefix: [
1142
- 0,
1143
- 0,
1144
- 0,
1145
- 32,
1146
- 102,
1147
- 116,
1148
- 121,
1149
- 112,
1150
- 104,
1151
- 101,
1152
- 105,
1153
- 99
1154
- ],
1155
- base64Prefix: "AAAAIGZ0eXBoZWlj"
1156
- }
1157
- ];
1158
- function detectMediaType({
1159
- data,
1160
- signatures
1161
- }) {
1162
- for (const signature of signatures) {
1163
- if (typeof data === "string" ? data.startsWith(signature.base64Prefix) : data.length >= signature.bytesPrefix.length && signature.bytesPrefix.every((byte, index) => data[index] === byte)) {
1164
- return signature.mediaType;
1165
- }
1166
- }
1167
- return void 0;
1168
- }
1169
-
1170
- // core/prompt/invalid-message-role-error.ts
1171
- import { AISDKError as AISDKError7 } from "@ai-sdk/provider";
1172
- var name6 = "AI_InvalidMessageRoleError";
1173
- var marker6 = `vercel.ai.error.${name6}`;
1174
- var symbol6 = Symbol.for(marker6);
1175
- var _a6;
1176
- var InvalidMessageRoleError = class extends AISDKError7 {
1177
- constructor({
1178
- role,
1179
- message = `Invalid message role: '${role}'. Must be one of: "system", "user", "assistant", "tool".`
1180
- }) {
1181
- super({ name: name6, message });
1182
- this[_a6] = true;
1183
- this.role = role;
1184
- }
1185
- static isInstance(error) {
1186
- return AISDKError7.hasMarker(error, marker6);
1187
- }
1188
- };
1189
- _a6 = symbol6;
1190
-
1191
- // core/prompt/convert-to-language-model-prompt.ts
1192
- async function convertToLanguageModelPrompt({
1193
- prompt,
1194
- modelSupportsImageUrls = true,
1195
- modelSupportsUrl = () => false,
1196
- downloadImplementation = download
1197
- }) {
1198
- const downloadedAssets = await downloadAssets(
1199
- prompt.messages,
1200
- downloadImplementation,
1201
- modelSupportsImageUrls,
1202
- modelSupportsUrl
1203
- );
1204
- return [
1205
- ...prompt.system != null ? [{ role: "system", content: prompt.system }] : [],
1206
- ...prompt.messages.map(
1207
- (message) => convertToLanguageModelMessage(message, downloadedAssets)
1208
- )
1209
- ];
1210
- }
1211
- function convertToLanguageModelMessage(message, downloadedAssets) {
1212
- const role = message.role;
1213
- switch (role) {
1214
- case "system": {
1215
- return {
1216
- role: "system",
1217
- content: message.content,
1218
- providerOptions: message.providerOptions
1219
- };
930
+ if (maxRetries === 0) {
931
+ throw error;
1220
932
  }
1221
- case "user": {
1222
- if (typeof message.content === "string") {
1223
- return {
1224
- role: "user",
1225
- content: [{ type: "text", text: message.content }],
1226
- providerOptions: message.providerOptions
1227
- };
1228
- }
1229
- return {
1230
- role: "user",
1231
- content: message.content.map((part) => convertPartToLanguageModelPart(part, downloadedAssets)).filter((part) => part.type !== "text" || part.text !== ""),
1232
- providerOptions: message.providerOptions
1233
- };
933
+ const errorMessage = getErrorMessage(error);
934
+ const newErrors = [...errors, error];
935
+ const tryNumber = newErrors.length;
936
+ if (tryNumber > maxRetries) {
937
+ throw new RetryError({
938
+ message: `Failed after ${tryNumber} attempts. Last error: ${errorMessage}`,
939
+ reason: "maxRetriesExceeded",
940
+ errors: newErrors
941
+ });
1234
942
  }
1235
- case "assistant": {
1236
- if (typeof message.content === "string") {
1237
- return {
1238
- role: "assistant",
1239
- content: [{ type: "text", text: message.content }],
1240
- providerOptions: message.providerOptions
1241
- };
1242
- }
1243
- return {
1244
- role: "assistant",
1245
- content: message.content.filter(
1246
- // remove empty text parts:
1247
- (part) => part.type !== "text" || part.text !== ""
1248
- ).map((part) => {
1249
- var _a7;
1250
- const providerOptions = part.providerOptions;
1251
- switch (part.type) {
1252
- case "file": {
1253
- const { data, mediaType } = convertToLanguageModelV2DataContent(
1254
- part.data
1255
- );
1256
- return {
1257
- type: "file",
1258
- data,
1259
- filename: part.filename,
1260
- mediaType: (_a7 = mediaType != null ? mediaType : part.mediaType) != null ? _a7 : part.mimeType,
1261
- providerOptions
1262
- };
1263
- }
1264
- case "reasoning": {
1265
- return {
1266
- type: "reasoning",
1267
- text: part.text,
1268
- signature: part.signature,
1269
- providerOptions
1270
- };
1271
- }
1272
- case "redacted-reasoning": {
1273
- return {
1274
- type: "redacted-reasoning",
1275
- data: part.data,
1276
- providerOptions
1277
- };
1278
- }
1279
- case "text": {
1280
- return {
1281
- type: "text",
1282
- text: part.text,
1283
- providerOptions
1284
- };
1285
- }
1286
- case "tool-call": {
1287
- return {
1288
- type: "tool-call",
1289
- toolCallId: part.toolCallId,
1290
- toolName: part.toolName,
1291
- args: part.args,
1292
- providerOptions
1293
- };
1294
- }
1295
- }
943
+ if (error instanceof Error && APICallError.isInstance(error) && error.isRetryable === true && tryNumber <= maxRetries) {
944
+ await delay(
945
+ getRetryDelayInMs({
946
+ error,
947
+ exponentialBackoffDelay: delayInMs
1296
948
  }),
1297
- providerOptions: message.providerOptions
1298
- };
1299
- }
1300
- case "tool": {
1301
- return {
1302
- role: "tool",
1303
- content: message.content.map((part) => ({
1304
- type: "tool-result",
1305
- toolCallId: part.toolCallId,
1306
- toolName: part.toolName,
1307
- result: part.result,
1308
- content: part.experimental_content,
1309
- isError: part.isError,
1310
- providerOptions: part.providerOptions
1311
- })),
1312
- providerOptions: message.providerOptions
1313
- };
949
+ { abortSignal }
950
+ );
951
+ return _retryWithExponentialBackoff(
952
+ f,
953
+ {
954
+ maxRetries,
955
+ delayInMs: backoffFactor * delayInMs,
956
+ backoffFactor,
957
+ abortSignal
958
+ },
959
+ newErrors
960
+ );
1314
961
  }
1315
- default: {
1316
- const _exhaustiveCheck = role;
1317
- throw new InvalidMessageRoleError({ role: _exhaustiveCheck });
962
+ if (tryNumber === 1) {
963
+ throw error;
1318
964
  }
965
+ throw new RetryError({
966
+ message: `Failed after ${tryNumber} attempts with non-retryable error: '${errorMessage}'`,
967
+ reason: "errorNotRetryable",
968
+ errors: newErrors
969
+ });
1319
970
  }
1320
971
  }
1321
- async function downloadAssets(messages, downloadImplementation, modelSupportsImageUrls, modelSupportsUrl) {
1322
- const urls = messages.filter((message) => message.role === "user").map((message) => message.content).filter(
1323
- (content) => Array.isArray(content)
1324
- ).flat().filter(
1325
- (part) => part.type === "image" || part.type === "file"
1326
- ).filter(
1327
- (part) => !(part.type === "image" && modelSupportsImageUrls === true)
1328
- ).map((part) => part.type === "image" ? part.image : part.data).map(
1329
- (part) => (
1330
- // support string urls:
1331
- typeof part === "string" && (part.startsWith("http:") || part.startsWith("https:")) ? new URL(part) : part
1332
- )
1333
- ).filter((image) => image instanceof URL).filter((url) => !modelSupportsUrl(url));
1334
- const downloadedImages = await Promise.all(
1335
- urls.map(async (url) => ({
1336
- url,
1337
- data: await downloadImplementation({ url })
1338
- }))
1339
- );
1340
- return Object.fromEntries(
1341
- downloadedImages.map(({ url, data }) => [url.toString(), data])
1342
- );
1343
- }
1344
- function convertPartToLanguageModelPart(part, downloadedAssets) {
1345
- var _a7, _b, _c;
1346
- if (part.type === "text") {
1347
- return {
1348
- type: "text",
1349
- text: part.text,
1350
- providerOptions: part.providerOptions
1351
- };
1352
- }
1353
- let originalData;
1354
- const type = part.type;
1355
- switch (type) {
1356
- case "image":
1357
- originalData = part.image;
1358
- break;
1359
- case "file":
1360
- originalData = part.data;
1361
- break;
1362
- default:
1363
- throw new Error(`Unsupported part type: ${type}`);
1364
- }
1365
- const { data: convertedData, mediaType: convertedMediaType } = convertToLanguageModelV2DataContent(originalData);
1366
- let mediaType = (_a7 = convertedMediaType != null ? convertedMediaType : part.mediaType) != null ? _a7 : part.mimeType;
1367
- let data = convertedData;
1368
- if (data instanceof URL) {
1369
- const downloadedFile = downloadedAssets[data.toString()];
1370
- if (downloadedFile) {
1371
- data = downloadedFile.data;
1372
- mediaType = (_b = downloadedFile.mediaType) != null ? _b : mediaType;
1373
- }
1374
- }
1375
- switch (type) {
1376
- case "image": {
1377
- if (data instanceof Uint8Array || typeof data === "string") {
1378
- mediaType = (_c = detectMediaType({ data, signatures: imageMediaTypeSignatures })) != null ? _c : mediaType;
1379
- }
1380
- return {
1381
- type: "file",
1382
- mediaType: mediaType != null ? mediaType : "image/*",
1383
- // any image
1384
- filename: void 0,
1385
- data,
1386
- providerOptions: part.providerOptions
1387
- };
972
+
973
+ // src/util/prepare-retries.ts
974
+ function prepareRetries({
975
+ maxRetries,
976
+ abortSignal
977
+ }) {
978
+ if (maxRetries != null) {
979
+ if (!Number.isInteger(maxRetries)) {
980
+ throw new InvalidArgumentError({
981
+ parameter: "maxRetries",
982
+ value: maxRetries,
983
+ message: "maxRetries must be an integer"
984
+ });
1388
985
  }
1389
- case "file": {
1390
- if (mediaType == null) {
1391
- throw new Error(`Media type is missing for file part`);
1392
- }
1393
- return {
1394
- type: "file",
1395
- mediaType,
1396
- filename: part.filename,
1397
- data,
1398
- providerOptions: part.providerOptions
1399
- };
986
+ if (maxRetries < 0) {
987
+ throw new InvalidArgumentError({
988
+ parameter: "maxRetries",
989
+ value: maxRetries,
990
+ message: "maxRetries must be >= 0"
991
+ });
1400
992
  }
1401
993
  }
1402
- }
1403
-
1404
- // core/types/usage.ts
1405
- function calculateLanguageModelUsage({
1406
- inputTokens,
1407
- outputTokens
1408
- }) {
994
+ const maxRetriesResult = maxRetries != null ? maxRetries : 2;
1409
995
  return {
1410
- promptTokens: inputTokens != null ? inputTokens : NaN,
1411
- completionTokens: outputTokens != null ? outputTokens : NaN,
1412
- totalTokens: (inputTokens != null ? inputTokens : 0) + (outputTokens != null ? outputTokens : 0)
996
+ maxRetries: maxRetriesResult,
997
+ retry: retryWithExponentialBackoffRespectingRetryHeaders({
998
+ maxRetries: maxRetriesResult,
999
+ abortSignal
1000
+ })
1413
1001
  };
1414
1002
  }
1415
-
1416
- // util/constants.ts
1417
- var HANGING_STREAM_WARNING_TIME_MS = 15 * 1e3;
1418
1003
  export {
1419
- HANGING_STREAM_WARNING_TIME_MS,
1420
- calculateLanguageModelUsage,
1004
+ convertAsyncIteratorToReadableStream,
1421
1005
  convertToLanguageModelPrompt,
1422
1006
  prepareCallSettings,
1423
1007
  prepareRetries,