@shop-os/modelkit 0.4.1 → 0.4.3

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.cjs CHANGED
@@ -1497,6 +1497,7 @@ var OMNI_RATIOS = ["16:9", "9:16"];
1497
1497
  var GROK_RATIOS = ["1:1", "16:9", "9:16", "4:3", "3:4", "3:2", "2:3"];
1498
1498
  var H3_RATIOS = ["21:9", "16:9", "4:3", "1:1", "3:4", "9:16"];
1499
1499
  var H3_REFERENCE_RATIOS = ["adaptive", ...H3_RATIOS];
1500
+ var WAN_RATIOS = ["adaptive", "16:9", "4:3", "1:1", "3:4", "9:16"];
1500
1501
  var NEGATIVE_PROMPT = "blur, distort, and low quality";
1501
1502
  var FRAMES_EXCLUDE_REFERENCES = { framesExcludeReferences: true };
1502
1503
  var KLING_PROMPT = { referenceSyntax: "numbered", maxChars: 2500 };
@@ -1507,6 +1508,7 @@ var SEEDANCE_2_AUDIO = {
1507
1508
  audioMaxBytes: 15 * 1024 * 1024
1508
1509
  };
1509
1510
  var H3_PROMPT = { referenceSyntax: "numbered", maxChars: 5e4 };
1511
+ var WAN_PROMPT = { referenceSyntax: "numbered", maxChars: 2e4 };
1510
1512
  var OMNI_PROMPT = { referenceSyntax: "caption", maxChars: 5e4 };
1511
1513
  var BYTEDANCE_LOGO = "https://d31vvfpk2ppdyq.cloudfront.net/assets/image/3bba5d81-4e57-4e71-911b-cdfa05acca2c_compressed.png";
1512
1514
  var GOOGLE_LOGO2 = "https://d31vvfpk2ppdyq.cloudfront.net/assets/image/192485d2-a76a-4657-9c06-930b2c70badd_compressed.png";
@@ -2112,6 +2114,48 @@ var VIDEO_MODELS = [
2112
2114
  // references instead of the adapter silently dropping the frame.
2113
2115
  capabilities: { ...FRAMES_EXCLUDE_REFERENCES }
2114
2116
  },
2117
+ {
2118
+ // One row for fal's three Wan 3.0 endpoints; the adapter picks text-, image- or
2119
+ // reference-to-video from the inputs. Each takes aspect_ratio, so none is ignored.
2120
+ // https://fal.ai/models/alibaba/wan-3.0/reference-to-video/api
2121
+ id: "wan-3.0",
2122
+ aliases: ["wan-3", "wan3"],
2123
+ label: "Wan 3",
2124
+ type: "video",
2125
+ adapter: "fal",
2126
+ providerModelId: "alibaba/wan-3.0",
2127
+ lifecycle: "active",
2128
+ exposure: ["cowork", "space_builder"],
2129
+ constraints: {
2130
+ aspectRatios: [...WAN_RATIOS],
2131
+ resolutions: ["480p", "720p", "1080p"],
2132
+ durations: { min: 2, max: 30 },
2133
+ durationPresets: [5, 10, 15, 30],
2134
+ references: {
2135
+ images: 10,
2136
+ videos: 5,
2137
+ audios: 5,
2138
+ videoSeconds: { total: 15 },
2139
+ audioSeconds: { total: 15 }
2140
+ },
2141
+ supports: ["seed", "lastFrame", "generateAudio", "safetyChecker"],
2142
+ prompt: WAN_PROMPT,
2143
+ audio: "optional"
2144
+ },
2145
+ defaults: {
2146
+ durationSeconds: 5,
2147
+ resolution: "1080p",
2148
+ aspectRatio: "adaptive",
2149
+ generateAudio: true
2150
+ },
2151
+ usage: { ...VIDEO_USAGE },
2152
+ pricingKind: "video_per_second",
2153
+ display: {
2154
+ provider: "alibaba",
2155
+ description: "Alibaba Wan 3 video model for text-to-video, image-to-video (start/end frame), and reference-to-video from up to 10 images, 5 videos and 5 audio clips, with native audio; 2-30 seconds at up to 1080p."
2156
+ },
2157
+ capabilities: { ...FRAMES_EXCLUDE_REFERENCES, lastFrameRequiresFirstFrame: true }
2158
+ },
2115
2159
  {
2116
2160
  // Duration 3-10s per trigger-workflows mapDuration; the endpoint takes no resolution.
2117
2161
  id: "kling-o1-v2v",
@@ -4908,7 +4952,7 @@ function isMinimax(providerModelId) {
4908
4952
  return MINIMAX_MODEL_IDS.has(providerModelId.toLowerCase());
4909
4953
  }
4910
4954
  function isFalVideoKnown(providerModelId) {
4911
- return isKling(providerModelId) || isMinimax(providerModelId);
4955
+ return isKling(providerModelId) || isMinimax(providerModelId) || isWan(providerModelId);
4912
4956
  }
4913
4957
  function minimaxFamily(providerModelId) {
4914
4958
  return H3_MAX_MODEL_IDS.has(providerModelId.toLowerCase()) ? "h3-max" : "h3";
@@ -4925,6 +4969,44 @@ function minimaxBase(req, family) {
4925
4969
  if (req.seed !== void 0) input.seed = req.seed;
4926
4970
  return input;
4927
4971
  }
4972
+ var WAN_MODEL_IDS = /* @__PURE__ */ new Set(["alibaba/wan-3.0"]);
4973
+ function isWan(providerModelId) {
4974
+ return WAN_MODEL_IDS.has(providerModelId.toLowerCase());
4975
+ }
4976
+ function wanVideo(req, family) {
4977
+ const input = {
4978
+ prompt: req.prompt.trim(),
4979
+ duration: req.durationSeconds ?? 5,
4980
+ resolution: req.resolution ?? "1080p",
4981
+ aspect_ratio: req.aspectRatio ?? "adaptive",
4982
+ audio: req.generateAudio ?? true
4983
+ };
4984
+ if (req.safetyChecker !== void 0) input.enable_safety_checker = req.safetyChecker;
4985
+ if (req.seed !== void 0) input.seed = req.seed;
4986
+ const images = (req.referenceImages ?? []).map(refToUrl);
4987
+ const videos = (req.referenceVideos ?? []).map(refToUrl);
4988
+ const audios = (req.referenceAudios ?? []).map(refToUrl);
4989
+ if (images.length + videos.length + audios.length > 0) {
4990
+ if (images.length > 0) input.reference_image_urls = images;
4991
+ if (videos.length > 0) input.reference_video_urls = videos;
4992
+ if (audios.length > 0) input.reference_audio_urls = audios;
4993
+ return { endpoint: `${family}/reference-to-video`, input };
4994
+ }
4995
+ if (req.firstFrame) {
4996
+ input.start_image_url = refToUrl(req.firstFrame);
4997
+ if (req.lastFrame) input.end_image_url = refToUrl(req.lastFrame);
4998
+ return { endpoint: `${family}/image-to-video`, input };
4999
+ }
5000
+ if (req.lastFrame) {
5001
+ throw new ModelKitError({
5002
+ code: "missing_input",
5003
+ message: `${family} takes a last frame only together with a first frame`,
5004
+ provider: "fal",
5005
+ retryable: false
5006
+ });
5007
+ }
5008
+ return { endpoint: `${family}/text-to-video`, input };
5009
+ }
4928
5010
  var KLING_MODEL_IDS = /* @__PURE__ */ new Set([
4929
5011
  "fal-ai/kling-video/o1/video-to-video/reference"
4930
5012
  ]);
@@ -4980,10 +5062,17 @@ async function generateFalVideo(req, ctx, deps) {
4980
5062
  }
4981
5063
  return await submitQueueJob(ctx, req, deps, KLING_O1_ENDPOINT, input);
4982
5064
  }
5065
+ if (isWan(providerModelId)) {
5066
+ const { endpoint: endpoint2, input } = wanVideo(req, providerModelId.toLowerCase());
5067
+ if (ctx.routing.fal === "cloudflare-passthrough") {
5068
+ return await passthroughVideoJob(ctx, req, endpoint2, input);
5069
+ }
5070
+ return await submitQueueJob(ctx, req, deps, endpoint2, input);
5071
+ }
4983
5072
  if (!isMinimax(providerModelId)) {
4984
5073
  throw new ModelKitError({
4985
5074
  code: "unsupported_option",
4986
- message: `fal has no input mapper for "${providerModelId}"; add the id to KLING_MODEL_IDS or MINIMAX_MODEL_IDS`,
5075
+ message: `fal has no input mapper for "${providerModelId}"; add the id to KLING_MODEL_IDS, MINIMAX_MODEL_IDS or WAN_MODEL_IDS`,
4987
5076
  provider: "fal",
4988
5077
  model: ctx.model.id,
4989
5078
  retryable: false
@@ -5668,8 +5757,10 @@ async function generateOmniVideo(req, ctx, createGenAIClient) {
5668
5757
  const apiKey = googleKey(ctx);
5669
5758
  const modelId = ctx.model.id;
5670
5759
  const providerModelId = ctx.model.providerModelId;
5671
- const duration = req.durationSeconds ?? 10;
5672
5760
  const extend = req.taskType === "extend";
5761
+ const sourceSeconds = extend ? void 0 : req.sourceVideo?.durationSeconds;
5762
+ const editSeconds = sourceSeconds !== void 0 && Number.isFinite(sourceSeconds) && sourceSeconds > 0 ? sourceSeconds : void 0;
5763
+ const duration = req.durationSeconds ?? editSeconds ?? 10;
5673
5764
  const previousId = extend ? req.previousInteractionId : void 0;
5674
5765
  const chained = previousId !== void 0;
5675
5766
  for (const field of [
@@ -8148,7 +8239,7 @@ function dataOnlyCapable(row) {
8148
8239
  }
8149
8240
  case "fal": {
8150
8241
  if (row.type === "video") {
8151
- return isFalVideoKnown(row.providerModelId) ? { ok: true } : { ok: false, reason: "fal video needs a Kling or MiniMax id" };
8242
+ return isFalVideoKnown(row.providerModelId) ? { ok: true } : { ok: false, reason: "fal video needs a Kling, MiniMax or Wan id" };
8152
8243
  }
8153
8244
  return { ok: true };
8154
8245
  }