ai 3.2.34 → 3.2.36

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai",
3
- "version": "3.2.34",
3
+ "version": "3.2.36",
4
4
  "description": "Vercel AI SDK - The AI Toolkit for TypeScript and JavaScript",
5
5
  "license": "Apache-2.0",
6
6
  "sideEffects": false,
@@ -58,20 +58,19 @@
58
58
  }
59
59
  },
60
60
  "dependencies": {
61
- "@ai-sdk/provider": "0.0.13",
62
- "@ai-sdk/provider-utils": "1.0.3",
63
- "@ai-sdk/react": "0.0.27",
64
- "@ai-sdk/solid": "0.0.20",
65
- "@ai-sdk/svelte": "0.0.21",
66
- "@ai-sdk/ui-utils": "0.0.18",
67
- "@ai-sdk/vue": "0.0.22",
61
+ "@ai-sdk/provider": "0.0.14",
62
+ "@ai-sdk/provider-utils": "1.0.5",
63
+ "@ai-sdk/react": "0.0.29",
64
+ "@ai-sdk/solid": "0.0.22",
65
+ "@ai-sdk/svelte": "0.0.23",
66
+ "@ai-sdk/ui-utils": "0.0.20",
67
+ "@ai-sdk/vue": "0.0.24",
68
68
  "@opentelemetry/api": "1.9.0",
69
69
  "eventsource-parser": "1.1.2",
70
70
  "jsondiffpatch": "0.6.0",
71
71
  "json-schema": "0.4.0",
72
72
  "nanoid": "3.3.6",
73
73
  "secure-json-parse": "2.7.0",
74
- "sswr": "2.1.0",
75
74
  "zod-to-json-schema": "3.22.5"
76
75
  },
77
76
  "devDependencies": {
@@ -97,6 +96,7 @@
97
96
  "openai": "4.52.6",
98
97
  "react-dom": "^18",
99
98
  "react-server-dom-webpack": "18.3.0-canary-eb33bd747-20240312",
99
+ "sswr": "2.1.0",
100
100
  "tsup": "^7.2.0",
101
101
  "typescript": "5.1.3",
102
102
  "zod": "3.23.8",
@@ -107,6 +107,7 @@
107
107
  "openai": "^4.42.0",
108
108
  "react": "^18 || ^19",
109
109
  "zod": "^3.0.0",
110
+ "sswr": "^2.1.0",
110
111
  "svelte": "^3.0.0 || ^4.0.0"
111
112
  },
112
113
  "peerDependenciesMeta": {
@@ -119,6 +120,9 @@
119
120
  "openai": {
120
121
  "optional": true
121
122
  },
123
+ "sswr": {
124
+ "optional": true
125
+ },
122
126
  "svelte": {
123
127
  "optional": true
124
128
  }
@@ -239,6 +239,9 @@ async function _retryWithExponentialBackoff(f, {
239
239
  }
240
240
  }
241
241
 
242
+ // core/prompt/convert-to-language-model-prompt.ts
243
+ import { getErrorMessage as getErrorMessage2 } from "@ai-sdk/provider-utils";
244
+
242
245
  // core/util/detect-image-mimetype.ts
243
246
  var mimeTypeSignatures = [
244
247
  { mimeType: "image/gif", bytes: [71, 73, 70] },
@@ -255,6 +258,35 @@ function detectImageMimeType(image) {
255
258
  return void 0;
256
259
  }
257
260
 
261
+ // core/util/download.ts
262
+ import { DownloadError } from "@ai-sdk/provider";
263
+ async function download({
264
+ url,
265
+ fetchImplementation = fetch
266
+ }) {
267
+ var _a;
268
+ const urlText = url.toString();
269
+ try {
270
+ const response = await fetchImplementation(urlText);
271
+ if (!response.ok) {
272
+ throw new DownloadError({
273
+ url: urlText,
274
+ statusCode: response.status,
275
+ statusText: response.statusText
276
+ });
277
+ }
278
+ return {
279
+ data: new Uint8Array(await response.arrayBuffer()),
280
+ mimeType: (_a = response.headers.get("content-type")) != null ? _a : void 0
281
+ };
282
+ } catch (error) {
283
+ if (DownloadError.isDownloadError(error)) {
284
+ throw error;
285
+ }
286
+ throw new DownloadError({ url: urlText, cause: error });
287
+ }
288
+ }
289
+
258
290
  // core/prompt/data-content.ts
259
291
  import { InvalidDataContentError } from "@ai-sdk/provider";
260
292
  import {
@@ -306,12 +338,16 @@ var InvalidMessageRoleError = class extends Error {
306
338
  };
307
339
 
308
340
  // core/prompt/convert-to-language-model-prompt.ts
309
- import { getErrorMessage as getErrorMessage2 } from "@ai-sdk/provider-utils";
310
- function convertToLanguageModelPrompt(prompt) {
341
+ async function convertToLanguageModelPrompt({
342
+ prompt,
343
+ modelSupportsImageUrls = true,
344
+ downloadImplementation = download
345
+ }) {
311
346
  const languageModelMessages = [];
312
347
  if (prompt.system != null) {
313
348
  languageModelMessages.push({ role: "system", content: prompt.system });
314
349
  }
350
+ const downloadedImages = modelSupportsImageUrls || prompt.messages == null ? null : await downloadImages(prompt.messages, downloadImplementation);
315
351
  const promptType = prompt.type;
316
352
  switch (promptType) {
317
353
  case "prompt": {
@@ -323,7 +359,9 @@ function convertToLanguageModelPrompt(prompt) {
323
359
  }
324
360
  case "messages": {
325
361
  languageModelMessages.push(
326
- ...prompt.messages.map(convertToLanguageModelMessage)
362
+ ...prompt.messages.map(
363
+ (message) => convertToLanguageModelMessage(message, downloadedImages)
364
+ )
327
365
  );
328
366
  break;
329
367
  }
@@ -334,7 +372,7 @@ function convertToLanguageModelPrompt(prompt) {
334
372
  }
335
373
  return languageModelMessages;
336
374
  }
337
- function convertToLanguageModelMessage(message) {
375
+ function convertToLanguageModelMessage(message, downloadedImages) {
338
376
  const role = message.role;
339
377
  switch (role) {
340
378
  case "system": {
@@ -351,18 +389,27 @@ function convertToLanguageModelMessage(message) {
351
389
  role: "user",
352
390
  content: message.content.map(
353
391
  (part) => {
354
- var _a;
392
+ var _a, _b, _c;
355
393
  switch (part.type) {
356
394
  case "text": {
357
395
  return part;
358
396
  }
359
397
  case "image": {
360
398
  if (part.image instanceof URL) {
361
- return {
362
- type: "image",
363
- image: part.image,
364
- mimeType: part.mimeType
365
- };
399
+ if (downloadedImages == null) {
400
+ return {
401
+ type: "image",
402
+ image: part.image,
403
+ mimeType: part.mimeType
404
+ };
405
+ } else {
406
+ const downloadedImage = downloadedImages[part.image.toString()];
407
+ return {
408
+ type: "image",
409
+ image: downloadedImage.data,
410
+ mimeType: (_a = part.mimeType) != null ? _a : downloadedImage.mimeType
411
+ };
412
+ }
366
413
  }
367
414
  if (typeof part.image === "string") {
368
415
  try {
@@ -370,11 +417,20 @@ function convertToLanguageModelMessage(message) {
370
417
  switch (url.protocol) {
371
418
  case "http:":
372
419
  case "https:": {
373
- return {
374
- type: "image",
375
- image: url,
376
- mimeType: part.mimeType
377
- };
420
+ if (downloadedImages == null) {
421
+ return {
422
+ type: "image",
423
+ image: url,
424
+ mimeType: part.mimeType
425
+ };
426
+ } else {
427
+ const downloadedImage = downloadedImages[part.image];
428
+ return {
429
+ type: "image",
430
+ image: downloadedImage.data,
431
+ mimeType: (_b = part.mimeType) != null ? _b : downloadedImage.mimeType
432
+ };
433
+ }
378
434
  }
379
435
  case "data:": {
380
436
  try {
@@ -409,7 +465,7 @@ function convertToLanguageModelMessage(message) {
409
465
  return {
410
466
  type: "image",
411
467
  image: imageUint8,
412
- mimeType: (_a = part.mimeType) != null ? _a : detectImageMimeType(imageUint8)
468
+ mimeType: (_c = part.mimeType) != null ? _c : detectImageMimeType(imageUint8)
413
469
  };
414
470
  }
415
471
  }
@@ -441,6 +497,25 @@ function convertToLanguageModelMessage(message) {
441
497
  }
442
498
  }
443
499
  }
500
+ async function downloadImages(messages, downloadImplementation) {
501
+ const urls = messages.filter((message) => message.role === "user").map((message) => message.content).filter(
502
+ (content) => Array.isArray(content)
503
+ ).flat().filter((part) => part.type === "image").map((part) => part.image).map(
504
+ (part) => (
505
+ // support string urls in image parts:
506
+ typeof part === "string" && (part.startsWith("http:") || part.startsWith("https:")) ? new URL(part) : part
507
+ )
508
+ ).filter((image) => image instanceof URL);
509
+ const downloadedImages = await Promise.all(
510
+ urls.map(async (url) => ({
511
+ url,
512
+ data: await downloadImplementation({ url })
513
+ }))
514
+ );
515
+ return Object.fromEntries(
516
+ downloadedImages.map(({ url, data }) => [url.toString(), data])
517
+ );
518
+ }
444
519
 
445
520
  // core/prompt/get-validated-prompt.ts
446
521
  import { InvalidPromptError } from "@ai-sdk/provider";
@@ -591,10 +666,39 @@ function calculateCompletionTokenUsage(usage) {
591
666
  };
592
667
  }
593
668
 
594
- // core/util/convert-zod-to-json-schema.ts
669
+ // core/util/schema.ts
670
+ import { validatorSymbol } from "@ai-sdk/provider-utils";
595
671
  import zodToJsonSchema from "zod-to-json-schema";
596
- function convertZodToJSONSchema(zodSchema) {
597
- return zodToJsonSchema(zodSchema);
672
+ var schemaSymbol = Symbol("vercel.ai.schema");
673
+ function jsonSchema(jsonSchema2, {
674
+ validate
675
+ } = {}) {
676
+ return {
677
+ [schemaSymbol]: true,
678
+ _type: void 0,
679
+ // should never be used directly
680
+ [validatorSymbol]: true,
681
+ jsonSchema: jsonSchema2,
682
+ validate
683
+ };
684
+ }
685
+ function isSchema(value) {
686
+ return typeof value === "object" && value !== null && schemaSymbol in value && value[schemaSymbol] === true && "jsonSchema" in value && "validate" in value;
687
+ }
688
+ function asSchema(schema) {
689
+ return isSchema(schema) ? schema : zodSchema(schema);
690
+ }
691
+ function zodSchema(zodSchema2) {
692
+ return jsonSchema(
693
+ // we assume that zodToJsonSchema will return a valid JSONSchema7:
694
+ zodToJsonSchema(zodSchema2),
695
+ {
696
+ validate: (value) => {
697
+ const result = zodSchema2.safeParse(value);
698
+ return result.success ? { success: true, value: result.data } : { success: false, error: result.error };
699
+ }
700
+ }
701
+ );
598
702
  }
599
703
 
600
704
  // core/util/is-non-empty-object.ts
@@ -618,7 +722,7 @@ function prepareToolsAndToolChoice({
618
722
  type: "function",
619
723
  name,
620
724
  description: tool.description,
621
- parameters: convertZodToJSONSchema(tool.parameters)
725
+ parameters: asSchema(tool.parameters).jsonSchema
622
726
  })),
623
727
  toolChoice: toolChoice == null ? { type: "auto" } : typeof toolChoice === "string" ? { type: toolChoice } : { type: "tool", toolName: toolChoice.toolName }
624
728
  };
@@ -1564,14 +1668,17 @@ async function streamUI({
1564
1668
  const retry = retryWithExponentialBackoff({ maxRetries });
1565
1669
  const validatedPrompt = getValidatedPrompt({ system, prompt, messages });
1566
1670
  const result = await retry(
1567
- () => model.doStream({
1671
+ async () => model.doStream({
1568
1672
  mode: {
1569
1673
  type: "regular",
1570
1674
  ...prepareToolsAndToolChoice({ tools, toolChoice })
1571
1675
  },
1572
1676
  ...prepareCallSettings(settings),
1573
1677
  inputFormat: validatedPrompt.type,
1574
- prompt: convertToLanguageModelPrompt(validatedPrompt),
1678
+ prompt: await convertToLanguageModelPrompt({
1679
+ prompt: validatedPrompt,
1680
+ modelSupportsImageUrls: model.supportsImageUrls
1681
+ }),
1575
1682
  abortSignal,
1576
1683
  headers
1577
1684
  })