ai 3.4.6 → 3.4.8

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/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # ai
2
2
 
3
+ ## 3.4.8
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [b5f577e]
8
+ - @ai-sdk/vue@0.0.54
9
+
10
+ ## 3.4.7
11
+
12
+ ### Patch Changes
13
+
14
+ - db04700: feat (core): support converting attachments to file parts
15
+ - 988707c: feat (ai/core): automatically download files from urls
16
+
3
17
  ## 3.4.6
4
18
 
5
19
  ### Patch Changes
package/dist/index.js CHANGED
@@ -900,6 +900,22 @@ var InvalidMessageRoleError = class extends import_provider5.AISDKError {
900
900
  };
901
901
  _a4 = symbol4;
902
902
 
903
+ // core/prompt/split-data-url.ts
904
+ function splitDataUrl(dataUrl) {
905
+ try {
906
+ const [header, base64Content] = dataUrl.split(",");
907
+ return {
908
+ mimeType: header.split(";")[0].split(":")[1],
909
+ base64Content
910
+ };
911
+ } catch (error) {
912
+ return {
913
+ mimeType: void 0,
914
+ base64Content: void 0
915
+ };
916
+ }
917
+ }
918
+
903
919
  // core/prompt/convert-to-language-model-prompt.ts
904
920
  async function convertToLanguageModelPrompt({
905
921
  prompt,
@@ -910,7 +926,7 @@ async function convertToLanguageModelPrompt({
910
926
  if (prompt.system != null) {
911
927
  languageModelMessages.push({ role: "system", content: prompt.system });
912
928
  }
913
- const downloadedImages = modelSupportsImageUrls || prompt.messages == null ? null : await downloadImages(prompt.messages, downloadImplementation);
929
+ const downloadedAssets = modelSupportsImageUrls || prompt.messages == null ? null : await downloadAssets(prompt.messages, downloadImplementation);
914
930
  const promptType = prompt.type;
915
931
  switch (promptType) {
916
932
  case "prompt": {
@@ -923,7 +939,7 @@ async function convertToLanguageModelPrompt({
923
939
  case "messages": {
924
940
  languageModelMessages.push(
925
941
  ...prompt.messages.map(
926
- (message) => convertToLanguageModelMessage(message, downloadedImages)
942
+ (message) => convertToLanguageModelMessage(message, downloadedAssets)
927
943
  )
928
944
  );
929
945
  break;
@@ -935,7 +951,7 @@ async function convertToLanguageModelPrompt({
935
951
  }
936
952
  return languageModelMessages;
937
953
  }
938
- function convertToLanguageModelMessage(message, downloadedImages) {
954
+ function convertToLanguageModelMessage(message, downloadedAssets) {
939
955
  const role = message.role;
940
956
  switch (role) {
941
957
  case "system": {
@@ -957,7 +973,7 @@ function convertToLanguageModelMessage(message, downloadedImages) {
957
973
  role: "user",
958
974
  content: message.content.map(
959
975
  (part) => {
960
- var _a11, _b, _c;
976
+ var _a11, _b, _c, _d, _e;
961
977
  switch (part.type) {
962
978
  case "text": {
963
979
  return {
@@ -968,7 +984,7 @@ function convertToLanguageModelMessage(message, downloadedImages) {
968
984
  }
969
985
  case "image": {
970
986
  if (part.image instanceof URL) {
971
- if (downloadedImages == null) {
987
+ if (downloadedAssets == null) {
972
988
  return {
973
989
  type: "image",
974
990
  image: part.image,
@@ -976,7 +992,7 @@ function convertToLanguageModelMessage(message, downloadedImages) {
976
992
  providerMetadata: part.experimental_providerMetadata
977
993
  };
978
994
  } else {
979
- const downloadedImage = downloadedImages[part.image.toString()];
995
+ const downloadedImage = downloadedAssets[part.image.toString()];
980
996
  return {
981
997
  type: "image",
982
998
  image: downloadedImage.data,
@@ -991,7 +1007,7 @@ function convertToLanguageModelMessage(message, downloadedImages) {
991
1007
  switch (url.protocol) {
992
1008
  case "http:":
993
1009
  case "https:": {
994
- if (downloadedImages == null) {
1010
+ if (downloadedAssets == null) {
995
1011
  return {
996
1012
  type: "image",
997
1013
  image: url,
@@ -999,7 +1015,7 @@ function convertToLanguageModelMessage(message, downloadedImages) {
999
1015
  providerMetadata: part.experimental_providerMetadata
1000
1016
  };
1001
1017
  } else {
1002
- const downloadedImage = downloadedImages[part.image];
1018
+ const downloadedImage = downloadedAssets[url.toString()];
1003
1019
  return {
1004
1020
  type: "image",
1005
1021
  image: downloadedImage.data,
@@ -1010,8 +1026,9 @@ function convertToLanguageModelMessage(message, downloadedImages) {
1010
1026
  }
1011
1027
  case "data:": {
1012
1028
  try {
1013
- const [header, base64Content] = part.image.split(",");
1014
- const mimeType = header.split(";")[0].split(":")[1];
1029
+ const { mimeType, base64Content } = splitDataUrl(
1030
+ part.image
1031
+ );
1015
1032
  if (mimeType == null || base64Content == null) {
1016
1033
  throw new Error("Invalid data URL format");
1017
1034
  }
@@ -1029,11 +1046,6 @@ function convertToLanguageModelMessage(message, downloadedImages) {
1029
1046
  );
1030
1047
  }
1031
1048
  }
1032
- default: {
1033
- throw new Error(
1034
- `Unsupported URL protocol: ${url.protocol}`
1035
- );
1036
- }
1037
1049
  }
1038
1050
  } catch (_ignored) {
1039
1051
  }
@@ -1048,12 +1060,75 @@ function convertToLanguageModelMessage(message, downloadedImages) {
1048
1060
  }
1049
1061
  case "file": {
1050
1062
  if (part.data instanceof URL) {
1051
- return {
1052
- type: "file",
1053
- data: part.data,
1054
- mimeType: part.mimeType,
1055
- providerMetadata: part.experimental_providerMetadata
1056
- };
1063
+ if (downloadedAssets == null) {
1064
+ return {
1065
+ type: "file",
1066
+ data: part.data,
1067
+ mimeType: part.mimeType,
1068
+ providerMetadata: part.experimental_providerMetadata
1069
+ };
1070
+ } else {
1071
+ const downloadedImage = downloadedAssets[part.data.toString()];
1072
+ return {
1073
+ type: "file",
1074
+ data: (0, import_provider_utils3.convertUint8ArrayToBase64)(downloadedImage.data),
1075
+ mimeType: (_d = part.mimeType) != null ? _d : downloadedImage.mimeType,
1076
+ providerMetadata: part.experimental_providerMetadata
1077
+ };
1078
+ }
1079
+ }
1080
+ if (typeof part.data === "string") {
1081
+ try {
1082
+ const url = new URL(part.data);
1083
+ switch (url.protocol) {
1084
+ case "http:":
1085
+ case "https:": {
1086
+ if (downloadedAssets == null) {
1087
+ return {
1088
+ type: "file",
1089
+ data: url,
1090
+ mimeType: part.mimeType,
1091
+ providerMetadata: part.experimental_providerMetadata
1092
+ };
1093
+ } else {
1094
+ const downloadedImage = downloadedAssets[url.toString()];
1095
+ return {
1096
+ type: "file",
1097
+ data: (0, import_provider_utils3.convertUint8ArrayToBase64)(
1098
+ downloadedImage.data
1099
+ ),
1100
+ mimeType: (_e = part.mimeType) != null ? _e : downloadedImage.mimeType,
1101
+ providerMetadata: part.experimental_providerMetadata
1102
+ };
1103
+ }
1104
+ }
1105
+ case "data:": {
1106
+ try {
1107
+ const { mimeType, base64Content } = splitDataUrl(
1108
+ part.data
1109
+ );
1110
+ if (mimeType == null || base64Content == null) {
1111
+ throw new Error("Invalid data URL format");
1112
+ }
1113
+ return {
1114
+ type: "file",
1115
+ data: convertDataContentToBase64String(
1116
+ base64Content
1117
+ ),
1118
+ mimeType,
1119
+ providerMetadata: part.experimental_providerMetadata
1120
+ };
1121
+ } catch (error) {
1122
+ throw new Error(
1123
+ `Error processing data URL: ${(0, import_provider_utils3.getErrorMessage)(
1124
+ message
1125
+ )}`
1126
+ );
1127
+ }
1128
+ }
1129
+ }
1130
+ } catch (_ignored) {
1131
+ }
1057
1132
  }
1058
1133
  const imageBase64 = convertDataContentToBase64String(
1059
1134
  part.data
@@ -1113,12 +1188,14 @@ function convertToLanguageModelMessage(message, downloadedImages) {
1113
1188
  }
1114
1189
  }
1115
1190
  }
1116
- async function downloadImages(messages, downloadImplementation) {
1191
+ async function downloadAssets(messages, downloadImplementation) {
1117
1192
  const urls = messages.filter((message) => message.role === "user").map((message) => message.content).filter(
1118
1193
  (content) => Array.isArray(content)
1119
- ).flat().filter((part) => part.type === "image").map((part) => part.image).map(
1194
+ ).flat().filter(
1195
+ (part) => part.type === "image" || part.type === "file"
1196
+ ).map((part) => part.type === "image" ? part.image : part.data).map(
1120
1197
  (part) => (
1121
- // support string urls in image parts:
1198
+ // support string urls:
1122
1199
  typeof part === "string" && (part.startsWith("http:") || part.startsWith("https:")) ? new URL(part) : part
1123
1200
  )
1124
1201
  ).filter((image) => image instanceof URL);
@@ -4687,6 +4764,17 @@ function attachmentsToParts(attachments) {
4687
4764
  case "https:": {
4688
4765
  if ((_a11 = attachment.contentType) == null ? void 0 : _a11.startsWith("image/")) {
4689
4766
  parts.push({ type: "image", image: url });
4767
+ } else {
4768
+ if (!attachment.contentType) {
4769
+ throw new Error(
4770
+ "If the attachment is not an image, it must specify a content type"
4771
+ );
4772
+ }
4773
+ parts.push({
4774
+ type: "file",
4775
+ data: url,
4776
+ mimeType: attachment.contentType
4777
+ });
4690
4778
  }
4691
4779
  break;
4692
4780
  }
@@ -4715,6 +4803,17 @@ function attachmentsToParts(attachments) {
4715
4803
  convertDataContentToUint8Array(base64Content)
4716
4804
  )
4717
4805
  });
4806
+ } else {
4807
+ if (!attachment.contentType) {
4808
+ throw new Error(
4809
+ "If the attachment is not an image or text, it must specify a content type"
4810
+ );
4811
+ }
4812
+ parts.push({
4813
+ type: "file",
4814
+ data: base64Content,
4815
+ mimeType: attachment.contentType
4816
+ });
4718
4817
  }
4719
4818
  break;
4720
4819
  }