@ai-sdk/alibaba 1.0.34 → 1.0.35

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/dist/index.mjs CHANGED
@@ -855,6 +855,7 @@ import {
855
855
  } from "@ai-sdk/provider";
856
856
  import {
857
857
  combineHeaders as combineHeaders3,
858
+ convertImageModelFileToDataUri,
858
859
  convertUint8ArrayToBase64,
859
860
  createJsonErrorResponseHandler as createJsonErrorResponseHandler3,
860
861
  createJsonResponseHandler as createJsonResponseHandler3,
@@ -877,6 +878,18 @@ var alibabaVideoModelOptionsSchema = lazySchema(
877
878
  watermark: z6.boolean().nullish(),
878
879
  audio: z6.boolean().nullish(),
879
880
  referenceUrls: z6.array(z6.string()).nullish(),
881
+ media: z6.array(
882
+ z6.object({
883
+ type: z6.enum([
884
+ "reference_image",
885
+ "reference_video",
886
+ "first_frame"
887
+ ]),
888
+ url: z6.string(),
889
+ referenceVoice: z6.string().nullish()
890
+ })
891
+ ).nullish(),
892
+ ratio: z6.enum(["16:9", "9:16", "1:1", "4:3", "3:4"]).nullish(),
880
893
  pollIntervalMs: z6.number().positive().nullish(),
881
894
  pollTimeoutMs: z6.number().positive().nullish()
882
895
  }).passthrough()
@@ -924,6 +937,38 @@ function detectMode(modelId) {
924
937
  if (modelId.includes("-r2v")) return "r2v";
925
938
  return "t2v";
926
939
  }
940
+ function isWan27Model(modelId) {
941
+ return modelId.startsWith("wan2.7");
942
+ }
943
+ var resolutionTierMap = {
944
+ "1280x720": "720P",
945
+ "720x1280": "720P",
946
+ "960x960": "720P",
947
+ "1088x832": "720P",
948
+ "832x1088": "720P",
949
+ "1920x1080": "1080P",
950
+ "1080x1920": "1080P",
951
+ "1440x1440": "1080P",
952
+ "1632x1248": "1080P",
953
+ "1248x1632": "1080P",
954
+ "832x480": "480P",
955
+ "480x832": "480P",
956
+ "624x624": "480P"
957
+ };
958
+ var supportedRatios = /* @__PURE__ */ new Set(["16:9", "9:16", "1:1", "4:3", "3:4"]);
959
+ function deriveRatioFromResolution(resolution) {
960
+ const [width, height] = resolution.split("x").map(Number);
961
+ if (!Number.isInteger(width) || !Number.isInteger(height) || width <= 0 || height <= 0) {
962
+ return void 0;
963
+ }
964
+ let a = width;
965
+ let b = height;
966
+ while (b !== 0) {
967
+ [a, b] = [b, a % b];
968
+ }
969
+ const ratio = `${width / a}:${height / a}`;
970
+ return supportedRatios.has(ratio) ? ratio : void 0;
971
+ }
927
972
  function fileToImageString(file) {
928
973
  if (file.type === "url") {
929
974
  return file.url;
@@ -938,6 +983,47 @@ function resolveStartImage(options) {
938
983
  var _a;
939
984
  return (_a = getFirstFrameImage(options)) != null ? _a : options.image;
940
985
  }
986
+ function isVideoUrl(url) {
987
+ return /\.(mp4|mov)([?#]|$)/i.test(url);
988
+ }
989
+ function resolveMedia(options, alibabaOptions, warnings) {
990
+ var _a;
991
+ if ((alibabaOptions == null ? void 0 : alibabaOptions.media) != null && alibabaOptions.media.length > 0) {
992
+ return alibabaOptions.media.map((item) => ({
993
+ type: item.type,
994
+ url: item.url,
995
+ ...item.referenceVoice != null ? { reference_voice: item.referenceVoice } : {}
996
+ }));
997
+ }
998
+ const media = [];
999
+ for (const reference of (_a = options.inputReferences) != null ? _a : []) {
1000
+ if (reference.type === "url") {
1001
+ media.push({
1002
+ type: isVideoUrl(reference.url) ? "reference_video" : "reference_image",
1003
+ url: reference.url
1004
+ });
1005
+ } else if (reference.mediaType.startsWith("image/")) {
1006
+ media.push({
1007
+ type: "reference_image",
1008
+ url: convertImageModelFileToDataUri(reference)
1009
+ });
1010
+ } else {
1011
+ warnings.push({
1012
+ type: "unsupported",
1013
+ feature: "inputReferences",
1014
+ details: "Alibaba reference-to-video requires URL references for videos. Non-URL video reference was skipped."
1015
+ });
1016
+ }
1017
+ }
1018
+ const firstFrame = getFirstFrameImage(options);
1019
+ if (firstFrame != null) {
1020
+ media.push({
1021
+ type: "first_frame",
1022
+ url: convertImageModelFileToDataUri(firstFrame)
1023
+ });
1024
+ }
1025
+ return media.length > 0 ? media : void 0;
1026
+ }
941
1027
  function resolveReferenceUrls(options, alibabaOptions, warnings) {
942
1028
  var _a;
943
1029
  if (options.frameImages != null && options.frameImages.length > 0) {
@@ -971,7 +1057,7 @@ var AlibabaVideoModel = class {
971
1057
  return this.config.provider;
972
1058
  }
973
1059
  async doGenerate(options) {
974
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
1060
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p;
975
1061
  const currentDate = (_c = (_b = (_a = this.config._internal) == null ? void 0 : _a.currentDate) == null ? void 0 : _b.call(_a)) != null ? _c : /* @__PURE__ */ new Date();
976
1062
  const warnings = [];
977
1063
  const mode = detectMode(this.modelId);
@@ -991,16 +1077,27 @@ var AlibabaVideoModel = class {
991
1077
  input.audio_url = alibabaOptions.audioUrl;
992
1078
  }
993
1079
  const startImage = resolveStartImage(options);
994
- const referenceUrls = resolveReferenceUrls(
995
- options,
996
- alibabaOptions,
997
- warnings
998
- );
1080
+ const wan27 = isWan27Model(this.modelId);
1081
+ const supportsRatio = wan27 && mode !== "i2v";
999
1082
  if (mode === "i2v" && startImage != null) {
1000
1083
  input.img_url = fileToImageString(startImage);
1001
1084
  }
1002
- if (mode === "r2v" && referenceUrls != null && referenceUrls.length > 0) {
1003
- input.reference_urls = referenceUrls;
1085
+ if (mode === "r2v") {
1086
+ if (wan27) {
1087
+ const media = resolveMedia(options, alibabaOptions, warnings);
1088
+ if (media != null) {
1089
+ input.media = media;
1090
+ }
1091
+ } else {
1092
+ const referenceUrls = resolveReferenceUrls(
1093
+ options,
1094
+ alibabaOptions,
1095
+ warnings
1096
+ );
1097
+ if (referenceUrls != null && referenceUrls.length > 0) {
1098
+ input.reference_urls = referenceUrls;
1099
+ }
1100
+ }
1004
1101
  }
1005
1102
  const lastFrame = (_e = (_d = options.frameImages) == null ? void 0 : _d.find(
1006
1103
  (frame) => frame.frameType === "last_frame"
@@ -1027,41 +1124,57 @@ var AlibabaVideoModel = class {
1027
1124
  parameters.seed = options.seed;
1028
1125
  }
1029
1126
  if (options.resolution != null) {
1030
- if (mode === "i2v") {
1031
- const resolutionMap = {
1032
- "1280x720": "720P",
1033
- "720x1280": "720P",
1034
- "960x960": "720P",
1035
- "1088x832": "720P",
1036
- "832x1088": "720P",
1037
- "1920x1080": "1080P",
1038
- "1080x1920": "1080P",
1039
- "1440x1440": "1080P",
1040
- "1632x1248": "1080P",
1041
- "1248x1632": "1080P",
1042
- "832x480": "480P",
1043
- "480x832": "480P",
1044
- "624x624": "480P"
1045
- };
1046
- parameters.resolution = resolutionMap[options.resolution] || options.resolution;
1127
+ if (mode === "i2v" || wan27) {
1128
+ const resolutionTier = resolutionTierMap[options.resolution] || options.resolution;
1129
+ if (wan27 && resolutionTier !== "720P" && resolutionTier !== "1080P") {
1130
+ warnings.push({
1131
+ type: "unsupported",
1132
+ feature: "resolution",
1133
+ details: `wan2.7 models only support 720P and 1080P resolutions. The resolution "${options.resolution}" was ignored.`
1134
+ });
1135
+ } else {
1136
+ parameters.resolution = resolutionTier;
1137
+ }
1047
1138
  } else {
1048
1139
  parameters.size = options.resolution.replace("x", "*");
1049
1140
  }
1050
1141
  }
1142
+ if (supportsRatio) {
1143
+ const ratio = (_g = (_f = alibabaOptions == null ? void 0 : alibabaOptions.ratio) != null ? _f : options.aspectRatio) != null ? _g : options.resolution != null ? deriveRatioFromResolution(options.resolution) : void 0;
1144
+ if (ratio != null) {
1145
+ parameters.ratio = ratio;
1146
+ }
1147
+ }
1051
1148
  if ((alibabaOptions == null ? void 0 : alibabaOptions.promptExtend) != null) {
1052
1149
  parameters.prompt_extend = alibabaOptions.promptExtend;
1053
1150
  }
1054
1151
  if ((alibabaOptions == null ? void 0 : alibabaOptions.shotType) != null) {
1055
- parameters.shot_type = alibabaOptions.shotType;
1152
+ if (wan27) {
1153
+ warnings.push({
1154
+ type: "unsupported",
1155
+ feature: "shotType",
1156
+ details: "wan2.7 models do not support the shotType option. Describe the shot structure in the prompt instead."
1157
+ });
1158
+ } else {
1159
+ parameters.shot_type = alibabaOptions.shotType;
1160
+ }
1056
1161
  }
1057
1162
  if ((alibabaOptions == null ? void 0 : alibabaOptions.watermark) != null) {
1058
1163
  parameters.watermark = alibabaOptions.watermark;
1059
1164
  }
1060
- const audio = (_f = options.generateAudio) != null ? _f : alibabaOptions == null ? void 0 : alibabaOptions.audio;
1165
+ const audio = (_h = options.generateAudio) != null ? _h : alibabaOptions == null ? void 0 : alibabaOptions.audio;
1061
1166
  if (audio != null) {
1062
- parameters.audio = audio;
1167
+ if (wan27) {
1168
+ warnings.push({
1169
+ type: "unsupported",
1170
+ feature: "generateAudio",
1171
+ details: "wan2.7 models always generate audio. The audio option was ignored."
1172
+ });
1173
+ } else {
1174
+ parameters.audio = audio;
1175
+ }
1063
1176
  }
1064
- if (options.aspectRatio) {
1177
+ if (options.aspectRatio && !supportsRatio) {
1065
1178
  warnings.push({
1066
1179
  type: "unsupported",
1067
1180
  feature: "aspectRatio",
@@ -1103,15 +1216,15 @@ var AlibabaVideoModel = class {
1103
1216
  abortSignal: options.abortSignal,
1104
1217
  fetch: this.config.fetch
1105
1218
  });
1106
- const taskId = (_g = createResponse.output) == null ? void 0 : _g.task_id;
1219
+ const taskId = (_i = createResponse.output) == null ? void 0 : _i.task_id;
1107
1220
  if (!taskId) {
1108
1221
  throw new AISDKError({
1109
1222
  name: "ALIBABA_VIDEO_GENERATION_ERROR",
1110
1223
  message: `No task_id returned from Alibaba API. Response: ${JSON.stringify(createResponse)}`
1111
1224
  });
1112
1225
  }
1113
- const pollIntervalMs = (_h = alibabaOptions == null ? void 0 : alibabaOptions.pollIntervalMs) != null ? _h : 5e3;
1114
- const pollTimeoutMs = (_i = alibabaOptions == null ? void 0 : alibabaOptions.pollTimeoutMs) != null ? _i : 6e5;
1226
+ const pollIntervalMs = (_j = alibabaOptions == null ? void 0 : alibabaOptions.pollIntervalMs) != null ? _j : 5e3;
1227
+ const pollTimeoutMs = (_k = alibabaOptions == null ? void 0 : alibabaOptions.pollTimeoutMs) != null ? _k : 6e5;
1115
1228
  const startTime = Date.now();
1116
1229
  let finalResponse;
1117
1230
  let responseHeaders;
@@ -1137,7 +1250,7 @@ var AlibabaVideoModel = class {
1137
1250
  fetch: this.config.fetch
1138
1251
  });
1139
1252
  responseHeaders = pollHeaders;
1140
- const taskStatus = (_j = statusResponse.output) == null ? void 0 : _j.task_status;
1253
+ const taskStatus = (_l = statusResponse.output) == null ? void 0 : _l.task_status;
1141
1254
  if (taskStatus === "SUCCEEDED") {
1142
1255
  finalResponse = statusResponse;
1143
1256
  break;
@@ -1145,11 +1258,11 @@ var AlibabaVideoModel = class {
1145
1258
  if (taskStatus === "FAILED" || taskStatus === "CANCELED") {
1146
1259
  throw new AISDKError({
1147
1260
  name: "ALIBABA_VIDEO_GENERATION_FAILED",
1148
- message: `Video generation ${taskStatus.toLowerCase()}. Task ID: ${taskId}. ${(_l = (_k = statusResponse.output) == null ? void 0 : _k.message) != null ? _l : ""}`
1261
+ message: `Video generation ${taskStatus.toLowerCase()}. Task ID: ${taskId}. ${(_n = (_m = statusResponse.output) == null ? void 0 : _m.message) != null ? _n : ""}`
1149
1262
  });
1150
1263
  }
1151
1264
  }
1152
- const videoUrl = (_m = finalResponse == null ? void 0 : finalResponse.output) == null ? void 0 : _m.video_url;
1265
+ const videoUrl = (_o = finalResponse == null ? void 0 : finalResponse.output) == null ? void 0 : _o.video_url;
1153
1266
  if (!videoUrl) {
1154
1267
  throw new AISDKError({
1155
1268
  name: "ALIBABA_VIDEO_GENERATION_ERROR",
@@ -1174,7 +1287,7 @@ var AlibabaVideoModel = class {
1174
1287
  alibaba: {
1175
1288
  taskId,
1176
1289
  videoUrl,
1177
- ...((_n = finalResponse == null ? void 0 : finalResponse.output) == null ? void 0 : _n.actual_prompt) ? { actualPrompt: finalResponse.output.actual_prompt } : {},
1290
+ ...((_p = finalResponse == null ? void 0 : finalResponse.output) == null ? void 0 : _p.actual_prompt) ? { actualPrompt: finalResponse.output.actual_prompt } : {},
1178
1291
  ...(finalResponse == null ? void 0 : finalResponse.usage) ? {
1179
1292
  usage: {
1180
1293
  duration: finalResponse.usage.duration,
@@ -1190,7 +1303,7 @@ var AlibabaVideoModel = class {
1190
1303
  };
1191
1304
 
1192
1305
  // src/version.ts
1193
- var VERSION = true ? "1.0.34" : "0.0.0-test";
1306
+ var VERSION = true ? "1.0.35" : "0.0.0-test";
1194
1307
 
1195
1308
  // src/alibaba-provider.ts
1196
1309
  function createAlibaba(options = {}) {