@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.js CHANGED
@@ -1378,6 +1378,7 @@ var OMNI_RATIOS = ["16:9", "9:16"];
1378
1378
  var GROK_RATIOS = ["1:1", "16:9", "9:16", "4:3", "3:4", "3:2", "2:3"];
1379
1379
  var H3_RATIOS = ["21:9", "16:9", "4:3", "1:1", "3:4", "9:16"];
1380
1380
  var H3_REFERENCE_RATIOS = ["adaptive", ...H3_RATIOS];
1381
+ var WAN_RATIOS = ["adaptive", "16:9", "4:3", "1:1", "3:4", "9:16"];
1381
1382
  var NEGATIVE_PROMPT = "blur, distort, and low quality";
1382
1383
  var FRAMES_EXCLUDE_REFERENCES = { framesExcludeReferences: true };
1383
1384
  var KLING_PROMPT = { referenceSyntax: "numbered", maxChars: 2500 };
@@ -1388,6 +1389,7 @@ var SEEDANCE_2_AUDIO = {
1388
1389
  audioMaxBytes: 15 * 1024 * 1024
1389
1390
  };
1390
1391
  var H3_PROMPT = { referenceSyntax: "numbered", maxChars: 5e4 };
1392
+ var WAN_PROMPT = { referenceSyntax: "numbered", maxChars: 2e4 };
1391
1393
  var OMNI_PROMPT = { referenceSyntax: "caption", maxChars: 5e4 };
1392
1394
  var BYTEDANCE_LOGO = "https://d31vvfpk2ppdyq.cloudfront.net/assets/image/3bba5d81-4e57-4e71-911b-cdfa05acca2c_compressed.png";
1393
1395
  var GOOGLE_LOGO2 = "https://d31vvfpk2ppdyq.cloudfront.net/assets/image/192485d2-a76a-4657-9c06-930b2c70badd_compressed.png";
@@ -1993,6 +1995,48 @@ var VIDEO_MODELS = [
1993
1995
  // references instead of the adapter silently dropping the frame.
1994
1996
  capabilities: { ...FRAMES_EXCLUDE_REFERENCES }
1995
1997
  },
1998
+ {
1999
+ // One row for fal's three Wan 3.0 endpoints; the adapter picks text-, image- or
2000
+ // reference-to-video from the inputs. Each takes aspect_ratio, so none is ignored.
2001
+ // https://fal.ai/models/alibaba/wan-3.0/reference-to-video/api
2002
+ id: "wan-3.0",
2003
+ aliases: ["wan-3", "wan3"],
2004
+ label: "Wan 3",
2005
+ type: "video",
2006
+ adapter: "fal",
2007
+ providerModelId: "alibaba/wan-3.0",
2008
+ lifecycle: "active",
2009
+ exposure: ["cowork", "space_builder"],
2010
+ constraints: {
2011
+ aspectRatios: [...WAN_RATIOS],
2012
+ resolutions: ["480p", "720p", "1080p"],
2013
+ durations: { min: 2, max: 30 },
2014
+ durationPresets: [5, 10, 15, 30],
2015
+ references: {
2016
+ images: 10,
2017
+ videos: 5,
2018
+ audios: 5,
2019
+ videoSeconds: { total: 15 },
2020
+ audioSeconds: { total: 15 }
2021
+ },
2022
+ supports: ["seed", "lastFrame", "generateAudio", "safetyChecker"],
2023
+ prompt: WAN_PROMPT,
2024
+ audio: "optional"
2025
+ },
2026
+ defaults: {
2027
+ durationSeconds: 5,
2028
+ resolution: "1080p",
2029
+ aspectRatio: "adaptive",
2030
+ generateAudio: true
2031
+ },
2032
+ usage: { ...VIDEO_USAGE },
2033
+ pricingKind: "video_per_second",
2034
+ display: {
2035
+ provider: "alibaba",
2036
+ 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."
2037
+ },
2038
+ capabilities: { ...FRAMES_EXCLUDE_REFERENCES, lastFrameRequiresFirstFrame: true }
2039
+ },
1996
2040
  {
1997
2041
  // Duration 3-10s per trigger-workflows mapDuration; the endpoint takes no resolution.
1998
2042
  id: "kling-o1-v2v",
@@ -4789,7 +4833,7 @@ function isMinimax(providerModelId) {
4789
4833
  return MINIMAX_MODEL_IDS.has(providerModelId.toLowerCase());
4790
4834
  }
4791
4835
  function isFalVideoKnown(providerModelId) {
4792
- return isKling(providerModelId) || isMinimax(providerModelId);
4836
+ return isKling(providerModelId) || isMinimax(providerModelId) || isWan(providerModelId);
4793
4837
  }
4794
4838
  function minimaxFamily(providerModelId) {
4795
4839
  return H3_MAX_MODEL_IDS.has(providerModelId.toLowerCase()) ? "h3-max" : "h3";
@@ -4806,6 +4850,44 @@ function minimaxBase(req, family) {
4806
4850
  if (req.seed !== void 0) input.seed = req.seed;
4807
4851
  return input;
4808
4852
  }
4853
+ var WAN_MODEL_IDS = /* @__PURE__ */ new Set(["alibaba/wan-3.0"]);
4854
+ function isWan(providerModelId) {
4855
+ return WAN_MODEL_IDS.has(providerModelId.toLowerCase());
4856
+ }
4857
+ function wanVideo(req, family) {
4858
+ const input = {
4859
+ prompt: req.prompt.trim(),
4860
+ duration: req.durationSeconds ?? 5,
4861
+ resolution: req.resolution ?? "1080p",
4862
+ aspect_ratio: req.aspectRatio ?? "adaptive",
4863
+ audio: req.generateAudio ?? true
4864
+ };
4865
+ if (req.safetyChecker !== void 0) input.enable_safety_checker = req.safetyChecker;
4866
+ if (req.seed !== void 0) input.seed = req.seed;
4867
+ const images = (req.referenceImages ?? []).map(refToUrl);
4868
+ const videos = (req.referenceVideos ?? []).map(refToUrl);
4869
+ const audios = (req.referenceAudios ?? []).map(refToUrl);
4870
+ if (images.length + videos.length + audios.length > 0) {
4871
+ if (images.length > 0) input.reference_image_urls = images;
4872
+ if (videos.length > 0) input.reference_video_urls = videos;
4873
+ if (audios.length > 0) input.reference_audio_urls = audios;
4874
+ return { endpoint: `${family}/reference-to-video`, input };
4875
+ }
4876
+ if (req.firstFrame) {
4877
+ input.start_image_url = refToUrl(req.firstFrame);
4878
+ if (req.lastFrame) input.end_image_url = refToUrl(req.lastFrame);
4879
+ return { endpoint: `${family}/image-to-video`, input };
4880
+ }
4881
+ if (req.lastFrame) {
4882
+ throw new ModelKitError({
4883
+ code: "missing_input",
4884
+ message: `${family} takes a last frame only together with a first frame`,
4885
+ provider: "fal",
4886
+ retryable: false
4887
+ });
4888
+ }
4889
+ return { endpoint: `${family}/text-to-video`, input };
4890
+ }
4809
4891
  var KLING_MODEL_IDS = /* @__PURE__ */ new Set([
4810
4892
  "fal-ai/kling-video/o1/video-to-video/reference"
4811
4893
  ]);
@@ -4861,10 +4943,17 @@ async function generateFalVideo(req, ctx, deps) {
4861
4943
  }
4862
4944
  return await submitQueueJob(ctx, req, deps, KLING_O1_ENDPOINT, input);
4863
4945
  }
4946
+ if (isWan(providerModelId)) {
4947
+ const { endpoint: endpoint2, input } = wanVideo(req, providerModelId.toLowerCase());
4948
+ if (ctx.routing.fal === "cloudflare-passthrough") {
4949
+ return await passthroughVideoJob(ctx, req, endpoint2, input);
4950
+ }
4951
+ return await submitQueueJob(ctx, req, deps, endpoint2, input);
4952
+ }
4864
4953
  if (!isMinimax(providerModelId)) {
4865
4954
  throw new ModelKitError({
4866
4955
  code: "unsupported_option",
4867
- message: `fal has no input mapper for "${providerModelId}"; add the id to KLING_MODEL_IDS or MINIMAX_MODEL_IDS`,
4956
+ message: `fal has no input mapper for "${providerModelId}"; add the id to KLING_MODEL_IDS, MINIMAX_MODEL_IDS or WAN_MODEL_IDS`,
4868
4957
  provider: "fal",
4869
4958
  model: ctx.model.id,
4870
4959
  retryable: false
@@ -5551,8 +5640,10 @@ async function generateOmniVideo(req, ctx, createGenAIClient) {
5551
5640
  const apiKey = googleKey(ctx);
5552
5641
  const modelId = ctx.model.id;
5553
5642
  const providerModelId = ctx.model.providerModelId;
5554
- const duration = req.durationSeconds ?? 10;
5555
5643
  const extend = req.taskType === "extend";
5644
+ const sourceSeconds = extend ? void 0 : req.sourceVideo?.durationSeconds;
5645
+ const editSeconds = sourceSeconds !== void 0 && Number.isFinite(sourceSeconds) && sourceSeconds > 0 ? sourceSeconds : void 0;
5646
+ const duration = req.durationSeconds ?? editSeconds ?? 10;
5556
5647
  const previousId = extend ? req.previousInteractionId : void 0;
5557
5648
  const chained = previousId !== void 0;
5558
5649
  for (const field of [
@@ -8031,7 +8122,7 @@ function dataOnlyCapable(row) {
8031
8122
  }
8032
8123
  case "fal": {
8033
8124
  if (row.type === "video") {
8034
- return isFalVideoKnown(row.providerModelId) ? { ok: true } : { ok: false, reason: "fal video needs a Kling or MiniMax id" };
8125
+ return isFalVideoKnown(row.providerModelId) ? { ok: true } : { ok: false, reason: "fal video needs a Kling, MiniMax or Wan id" };
8035
8126
  }
8036
8127
  return { ok: true };
8037
8128
  }