@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/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # @ai-sdk/alibaba
2
2
 
3
+ ## 1.0.35
4
+
5
+ ### Patch Changes
6
+
7
+ - 7dea716: feat(alibaba): support wan2.7 text-to-video and reference-to-video models with the new protocol (`input.media`, `resolution` + `ratio`)
8
+ - Updated dependencies [0952964]
9
+ - @ai-sdk/provider-utils@4.0.36
10
+ - @ai-sdk/openai-compatible@2.0.57
11
+
3
12
  ## 1.0.34
4
13
 
5
14
  ### Patch Changes
package/dist/index.d.mts CHANGED
@@ -29,7 +29,7 @@ declare const alibabaEmbeddingModelOptions: z.ZodObject<{
29
29
  }, z.core.$strip>;
30
30
  type AlibabaEmbeddingModelOptions = z.infer<typeof alibabaEmbeddingModelOptions>;
31
31
 
32
- type AlibabaVideoModelId = 'wan2.6-t2v' | 'wan2.5-t2v-preview' | 'wan2.6-i2v' | 'wan2.6-i2v-flash' | 'wan2.6-r2v' | 'wan2.6-r2v-flash' | (string & {});
32
+ type AlibabaVideoModelId = 'wan2.6-t2v' | 'wan2.5-t2v-preview' | 'wan2.7-t2v' | 'wan2.7-t2v-2026-06-12' | 'wan2.6-i2v' | 'wan2.6-i2v-flash' | 'wan2.6-r2v' | 'wan2.6-r2v-flash' | 'wan2.7-r2v' | 'wan2.7-r2v-2026-06-12' | (string & {});
33
33
 
34
34
  interface AlibabaProvider extends ProviderV3 {
35
35
  (modelId: AlibabaChatModelId): LanguageModelV3;
@@ -135,6 +135,23 @@ type AlibabaVideoModelOptions = {
135
135
  * Use character identifiers (character1, character2) in prompts to reference them.
136
136
  */
137
137
  referenceUrls?: string[] | null;
138
+ /**
139
+ * Explicit media array for reference-to-video mode (wan2.7 models).
140
+ * Overrides the automatic mapping from `inputReferences` and `frameImages`.
141
+ * Use `Image 1`, `Video 1`, etc. in prompts to reference media items
142
+ * (images and videos are counted separately, in array order).
143
+ */
144
+ media?: Array<{
145
+ type: 'reference_image' | 'reference_video' | 'first_frame';
146
+ /** Public URL, or a `data:{mime};base64,{data}` URI for images. */
147
+ url: string;
148
+ /** URL to an audio file used as voice reference for this media item. */
149
+ referenceVoice?: string | null;
150
+ }> | null;
151
+ /**
152
+ * Aspect ratio (wan2.7 text-to-video and reference-to-video models).
153
+ */
154
+ ratio?: '16:9' | '9:16' | '1:1' | '4:3' | '3:4' | null;
138
155
  /** Polling interval in milliseconds. Defaults to 5000 (5 seconds). */
139
156
  pollIntervalMs?: number | null;
140
157
  /** Maximum wait time in milliseconds for video generation. Defaults to 600000 (10 minutes). */
package/dist/index.d.ts CHANGED
@@ -29,7 +29,7 @@ declare const alibabaEmbeddingModelOptions: z.ZodObject<{
29
29
  }, z.core.$strip>;
30
30
  type AlibabaEmbeddingModelOptions = z.infer<typeof alibabaEmbeddingModelOptions>;
31
31
 
32
- type AlibabaVideoModelId = 'wan2.6-t2v' | 'wan2.5-t2v-preview' | 'wan2.6-i2v' | 'wan2.6-i2v-flash' | 'wan2.6-r2v' | 'wan2.6-r2v-flash' | (string & {});
32
+ type AlibabaVideoModelId = 'wan2.6-t2v' | 'wan2.5-t2v-preview' | 'wan2.7-t2v' | 'wan2.7-t2v-2026-06-12' | 'wan2.6-i2v' | 'wan2.6-i2v-flash' | 'wan2.6-r2v' | 'wan2.6-r2v-flash' | 'wan2.7-r2v' | 'wan2.7-r2v-2026-06-12' | (string & {});
33
33
 
34
34
  interface AlibabaProvider extends ProviderV3 {
35
35
  (modelId: AlibabaChatModelId): LanguageModelV3;
@@ -135,6 +135,23 @@ type AlibabaVideoModelOptions = {
135
135
  * Use character identifiers (character1, character2) in prompts to reference them.
136
136
  */
137
137
  referenceUrls?: string[] | null;
138
+ /**
139
+ * Explicit media array for reference-to-video mode (wan2.7 models).
140
+ * Overrides the automatic mapping from `inputReferences` and `frameImages`.
141
+ * Use `Image 1`, `Video 1`, etc. in prompts to reference media items
142
+ * (images and videos are counted separately, in array order).
143
+ */
144
+ media?: Array<{
145
+ type: 'reference_image' | 'reference_video' | 'first_frame';
146
+ /** Public URL, or a `data:{mime};base64,{data}` URI for images. */
147
+ url: string;
148
+ /** URL to an audio file used as voice reference for this media item. */
149
+ referenceVoice?: string | null;
150
+ }> | null;
151
+ /**
152
+ * Aspect ratio (wan2.7 text-to-video and reference-to-video models).
153
+ */
154
+ ratio?: '16:9' | '9:16' | '1:1' | '4:3' | '3:4' | null;
138
155
  /** Polling interval in milliseconds. Defaults to 5000 (5 seconds). */
139
156
  pollIntervalMs?: number | null;
140
157
  /** Maximum wait time in milliseconds for video generation. Defaults to 600000 (10 minutes). */
package/dist/index.js CHANGED
@@ -860,6 +860,18 @@ var alibabaVideoModelOptionsSchema = (0, import_provider_utils5.lazySchema)(
860
860
  watermark: import_v46.z.boolean().nullish(),
861
861
  audio: import_v46.z.boolean().nullish(),
862
862
  referenceUrls: import_v46.z.array(import_v46.z.string()).nullish(),
863
+ media: import_v46.z.array(
864
+ import_v46.z.object({
865
+ type: import_v46.z.enum([
866
+ "reference_image",
867
+ "reference_video",
868
+ "first_frame"
869
+ ]),
870
+ url: import_v46.z.string(),
871
+ referenceVoice: import_v46.z.string().nullish()
872
+ })
873
+ ).nullish(),
874
+ ratio: import_v46.z.enum(["16:9", "9:16", "1:1", "4:3", "3:4"]).nullish(),
863
875
  pollIntervalMs: import_v46.z.number().positive().nullish(),
864
876
  pollTimeoutMs: import_v46.z.number().positive().nullish()
865
877
  }).passthrough()
@@ -907,6 +919,38 @@ function detectMode(modelId) {
907
919
  if (modelId.includes("-r2v")) return "r2v";
908
920
  return "t2v";
909
921
  }
922
+ function isWan27Model(modelId) {
923
+ return modelId.startsWith("wan2.7");
924
+ }
925
+ var resolutionTierMap = {
926
+ "1280x720": "720P",
927
+ "720x1280": "720P",
928
+ "960x960": "720P",
929
+ "1088x832": "720P",
930
+ "832x1088": "720P",
931
+ "1920x1080": "1080P",
932
+ "1080x1920": "1080P",
933
+ "1440x1440": "1080P",
934
+ "1632x1248": "1080P",
935
+ "1248x1632": "1080P",
936
+ "832x480": "480P",
937
+ "480x832": "480P",
938
+ "624x624": "480P"
939
+ };
940
+ var supportedRatios = /* @__PURE__ */ new Set(["16:9", "9:16", "1:1", "4:3", "3:4"]);
941
+ function deriveRatioFromResolution(resolution) {
942
+ const [width, height] = resolution.split("x").map(Number);
943
+ if (!Number.isInteger(width) || !Number.isInteger(height) || width <= 0 || height <= 0) {
944
+ return void 0;
945
+ }
946
+ let a = width;
947
+ let b = height;
948
+ while (b !== 0) {
949
+ [a, b] = [b, a % b];
950
+ }
951
+ const ratio = `${width / a}:${height / a}`;
952
+ return supportedRatios.has(ratio) ? ratio : void 0;
953
+ }
910
954
  function fileToImageString(file) {
911
955
  if (file.type === "url") {
912
956
  return file.url;
@@ -921,6 +965,47 @@ function resolveStartImage(options) {
921
965
  var _a;
922
966
  return (_a = getFirstFrameImage(options)) != null ? _a : options.image;
923
967
  }
968
+ function isVideoUrl(url) {
969
+ return /\.(mp4|mov)([?#]|$)/i.test(url);
970
+ }
971
+ function resolveMedia(options, alibabaOptions, warnings) {
972
+ var _a;
973
+ if ((alibabaOptions == null ? void 0 : alibabaOptions.media) != null && alibabaOptions.media.length > 0) {
974
+ return alibabaOptions.media.map((item) => ({
975
+ type: item.type,
976
+ url: item.url,
977
+ ...item.referenceVoice != null ? { reference_voice: item.referenceVoice } : {}
978
+ }));
979
+ }
980
+ const media = [];
981
+ for (const reference of (_a = options.inputReferences) != null ? _a : []) {
982
+ if (reference.type === "url") {
983
+ media.push({
984
+ type: isVideoUrl(reference.url) ? "reference_video" : "reference_image",
985
+ url: reference.url
986
+ });
987
+ } else if (reference.mediaType.startsWith("image/")) {
988
+ media.push({
989
+ type: "reference_image",
990
+ url: (0, import_provider_utils5.convertImageModelFileToDataUri)(reference)
991
+ });
992
+ } else {
993
+ warnings.push({
994
+ type: "unsupported",
995
+ feature: "inputReferences",
996
+ details: "Alibaba reference-to-video requires URL references for videos. Non-URL video reference was skipped."
997
+ });
998
+ }
999
+ }
1000
+ const firstFrame = getFirstFrameImage(options);
1001
+ if (firstFrame != null) {
1002
+ media.push({
1003
+ type: "first_frame",
1004
+ url: (0, import_provider_utils5.convertImageModelFileToDataUri)(firstFrame)
1005
+ });
1006
+ }
1007
+ return media.length > 0 ? media : void 0;
1008
+ }
924
1009
  function resolveReferenceUrls(options, alibabaOptions, warnings) {
925
1010
  var _a;
926
1011
  if (options.frameImages != null && options.frameImages.length > 0) {
@@ -954,7 +1039,7 @@ var AlibabaVideoModel = class {
954
1039
  return this.config.provider;
955
1040
  }
956
1041
  async doGenerate(options) {
957
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
1042
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p;
958
1043
  const currentDate = (_c = (_b = (_a = this.config._internal) == null ? void 0 : _a.currentDate) == null ? void 0 : _b.call(_a)) != null ? _c : /* @__PURE__ */ new Date();
959
1044
  const warnings = [];
960
1045
  const mode = detectMode(this.modelId);
@@ -974,16 +1059,27 @@ var AlibabaVideoModel = class {
974
1059
  input.audio_url = alibabaOptions.audioUrl;
975
1060
  }
976
1061
  const startImage = resolveStartImage(options);
977
- const referenceUrls = resolveReferenceUrls(
978
- options,
979
- alibabaOptions,
980
- warnings
981
- );
1062
+ const wan27 = isWan27Model(this.modelId);
1063
+ const supportsRatio = wan27 && mode !== "i2v";
982
1064
  if (mode === "i2v" && startImage != null) {
983
1065
  input.img_url = fileToImageString(startImage);
984
1066
  }
985
- if (mode === "r2v" && referenceUrls != null && referenceUrls.length > 0) {
986
- input.reference_urls = referenceUrls;
1067
+ if (mode === "r2v") {
1068
+ if (wan27) {
1069
+ const media = resolveMedia(options, alibabaOptions, warnings);
1070
+ if (media != null) {
1071
+ input.media = media;
1072
+ }
1073
+ } else {
1074
+ const referenceUrls = resolveReferenceUrls(
1075
+ options,
1076
+ alibabaOptions,
1077
+ warnings
1078
+ );
1079
+ if (referenceUrls != null && referenceUrls.length > 0) {
1080
+ input.reference_urls = referenceUrls;
1081
+ }
1082
+ }
987
1083
  }
988
1084
  const lastFrame = (_e = (_d = options.frameImages) == null ? void 0 : _d.find(
989
1085
  (frame) => frame.frameType === "last_frame"
@@ -1010,41 +1106,57 @@ var AlibabaVideoModel = class {
1010
1106
  parameters.seed = options.seed;
1011
1107
  }
1012
1108
  if (options.resolution != null) {
1013
- if (mode === "i2v") {
1014
- const resolutionMap = {
1015
- "1280x720": "720P",
1016
- "720x1280": "720P",
1017
- "960x960": "720P",
1018
- "1088x832": "720P",
1019
- "832x1088": "720P",
1020
- "1920x1080": "1080P",
1021
- "1080x1920": "1080P",
1022
- "1440x1440": "1080P",
1023
- "1632x1248": "1080P",
1024
- "1248x1632": "1080P",
1025
- "832x480": "480P",
1026
- "480x832": "480P",
1027
- "624x624": "480P"
1028
- };
1029
- parameters.resolution = resolutionMap[options.resolution] || options.resolution;
1109
+ if (mode === "i2v" || wan27) {
1110
+ const resolutionTier = resolutionTierMap[options.resolution] || options.resolution;
1111
+ if (wan27 && resolutionTier !== "720P" && resolutionTier !== "1080P") {
1112
+ warnings.push({
1113
+ type: "unsupported",
1114
+ feature: "resolution",
1115
+ details: `wan2.7 models only support 720P and 1080P resolutions. The resolution "${options.resolution}" was ignored.`
1116
+ });
1117
+ } else {
1118
+ parameters.resolution = resolutionTier;
1119
+ }
1030
1120
  } else {
1031
1121
  parameters.size = options.resolution.replace("x", "*");
1032
1122
  }
1033
1123
  }
1124
+ if (supportsRatio) {
1125
+ const ratio = (_g = (_f = alibabaOptions == null ? void 0 : alibabaOptions.ratio) != null ? _f : options.aspectRatio) != null ? _g : options.resolution != null ? deriveRatioFromResolution(options.resolution) : void 0;
1126
+ if (ratio != null) {
1127
+ parameters.ratio = ratio;
1128
+ }
1129
+ }
1034
1130
  if ((alibabaOptions == null ? void 0 : alibabaOptions.promptExtend) != null) {
1035
1131
  parameters.prompt_extend = alibabaOptions.promptExtend;
1036
1132
  }
1037
1133
  if ((alibabaOptions == null ? void 0 : alibabaOptions.shotType) != null) {
1038
- parameters.shot_type = alibabaOptions.shotType;
1134
+ if (wan27) {
1135
+ warnings.push({
1136
+ type: "unsupported",
1137
+ feature: "shotType",
1138
+ details: "wan2.7 models do not support the shotType option. Describe the shot structure in the prompt instead."
1139
+ });
1140
+ } else {
1141
+ parameters.shot_type = alibabaOptions.shotType;
1142
+ }
1039
1143
  }
1040
1144
  if ((alibabaOptions == null ? void 0 : alibabaOptions.watermark) != null) {
1041
1145
  parameters.watermark = alibabaOptions.watermark;
1042
1146
  }
1043
- const audio = (_f = options.generateAudio) != null ? _f : alibabaOptions == null ? void 0 : alibabaOptions.audio;
1147
+ const audio = (_h = options.generateAudio) != null ? _h : alibabaOptions == null ? void 0 : alibabaOptions.audio;
1044
1148
  if (audio != null) {
1045
- parameters.audio = audio;
1149
+ if (wan27) {
1150
+ warnings.push({
1151
+ type: "unsupported",
1152
+ feature: "generateAudio",
1153
+ details: "wan2.7 models always generate audio. The audio option was ignored."
1154
+ });
1155
+ } else {
1156
+ parameters.audio = audio;
1157
+ }
1046
1158
  }
1047
- if (options.aspectRatio) {
1159
+ if (options.aspectRatio && !supportsRatio) {
1048
1160
  warnings.push({
1049
1161
  type: "unsupported",
1050
1162
  feature: "aspectRatio",
@@ -1086,15 +1198,15 @@ var AlibabaVideoModel = class {
1086
1198
  abortSignal: options.abortSignal,
1087
1199
  fetch: this.config.fetch
1088
1200
  });
1089
- const taskId = (_g = createResponse.output) == null ? void 0 : _g.task_id;
1201
+ const taskId = (_i = createResponse.output) == null ? void 0 : _i.task_id;
1090
1202
  if (!taskId) {
1091
1203
  throw new import_provider4.AISDKError({
1092
1204
  name: "ALIBABA_VIDEO_GENERATION_ERROR",
1093
1205
  message: `No task_id returned from Alibaba API. Response: ${JSON.stringify(createResponse)}`
1094
1206
  });
1095
1207
  }
1096
- const pollIntervalMs = (_h = alibabaOptions == null ? void 0 : alibabaOptions.pollIntervalMs) != null ? _h : 5e3;
1097
- const pollTimeoutMs = (_i = alibabaOptions == null ? void 0 : alibabaOptions.pollTimeoutMs) != null ? _i : 6e5;
1208
+ const pollIntervalMs = (_j = alibabaOptions == null ? void 0 : alibabaOptions.pollIntervalMs) != null ? _j : 5e3;
1209
+ const pollTimeoutMs = (_k = alibabaOptions == null ? void 0 : alibabaOptions.pollTimeoutMs) != null ? _k : 6e5;
1098
1210
  const startTime = Date.now();
1099
1211
  let finalResponse;
1100
1212
  let responseHeaders;
@@ -1120,7 +1232,7 @@ var AlibabaVideoModel = class {
1120
1232
  fetch: this.config.fetch
1121
1233
  });
1122
1234
  responseHeaders = pollHeaders;
1123
- const taskStatus = (_j = statusResponse.output) == null ? void 0 : _j.task_status;
1235
+ const taskStatus = (_l = statusResponse.output) == null ? void 0 : _l.task_status;
1124
1236
  if (taskStatus === "SUCCEEDED") {
1125
1237
  finalResponse = statusResponse;
1126
1238
  break;
@@ -1128,11 +1240,11 @@ var AlibabaVideoModel = class {
1128
1240
  if (taskStatus === "FAILED" || taskStatus === "CANCELED") {
1129
1241
  throw new import_provider4.AISDKError({
1130
1242
  name: "ALIBABA_VIDEO_GENERATION_FAILED",
1131
- message: `Video generation ${taskStatus.toLowerCase()}. Task ID: ${taskId}. ${(_l = (_k = statusResponse.output) == null ? void 0 : _k.message) != null ? _l : ""}`
1243
+ message: `Video generation ${taskStatus.toLowerCase()}. Task ID: ${taskId}. ${(_n = (_m = statusResponse.output) == null ? void 0 : _m.message) != null ? _n : ""}`
1132
1244
  });
1133
1245
  }
1134
1246
  }
1135
- const videoUrl = (_m = finalResponse == null ? void 0 : finalResponse.output) == null ? void 0 : _m.video_url;
1247
+ const videoUrl = (_o = finalResponse == null ? void 0 : finalResponse.output) == null ? void 0 : _o.video_url;
1136
1248
  if (!videoUrl) {
1137
1249
  throw new import_provider4.AISDKError({
1138
1250
  name: "ALIBABA_VIDEO_GENERATION_ERROR",
@@ -1157,7 +1269,7 @@ var AlibabaVideoModel = class {
1157
1269
  alibaba: {
1158
1270
  taskId,
1159
1271
  videoUrl,
1160
- ...((_n = finalResponse == null ? void 0 : finalResponse.output) == null ? void 0 : _n.actual_prompt) ? { actualPrompt: finalResponse.output.actual_prompt } : {},
1272
+ ...((_p = finalResponse == null ? void 0 : finalResponse.output) == null ? void 0 : _p.actual_prompt) ? { actualPrompt: finalResponse.output.actual_prompt } : {},
1161
1273
  ...(finalResponse == null ? void 0 : finalResponse.usage) ? {
1162
1274
  usage: {
1163
1275
  duration: finalResponse.usage.duration,
@@ -1173,7 +1285,7 @@ var AlibabaVideoModel = class {
1173
1285
  };
1174
1286
 
1175
1287
  // src/version.ts
1176
- var VERSION = true ? "1.0.34" : "0.0.0-test";
1288
+ var VERSION = true ? "1.0.35" : "0.0.0-test";
1177
1289
 
1178
1290
  // src/alibaba-provider.ts
1179
1291
  function createAlibaba(options = {}) {