@shop-os/modelkit 0.7.8 → 0.7.11

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/catalog.js CHANGED
@@ -4695,6 +4695,8 @@ function range(min, max) {
4695
4695
  }
4696
4696
  var KLING_PROMPT = { referenceSyntax: "numbered", maxChars: 2500 };
4697
4697
  var H3_PROMPT = { referenceSyntax: "numbered", maxChars: 5e4 };
4698
+ var KLING_V4_PROMPT = { referenceSyntax: "numbered", maxChars: 2500 };
4699
+ var KLING_V4_AUDIO = "always";
4698
4700
  var NO_REFERENCES = { images: 0, videos: 0, audios: 0 };
4699
4701
  function klingMotionControl(tier) {
4700
4702
  const label = tier === "pro" ? "Pro" : "Standard";
@@ -4795,6 +4797,79 @@ var VIDEO_FAMILY_MODELS = [
4795
4797
  },
4796
4798
  capabilities: { acceptsSourceVideo: true, videoEdit: true }
4797
4799
  },
4800
+ {
4801
+ // https://fal.ai/models/kling/v4/reference-to-video/api (+ /text-to-video,
4802
+ // /image-to-video): one row; references (images or videos) go to reference-to-video,
4803
+ // else a start frame to image-to-video, else text-to-video. Reference images: 10, the
4804
+ // start frame included (fal: "counts toward the image reference limit"), 300 px min.
4805
+ // Reference videos: 5, 3-30.05 s each and 30 s combined, 700 px min, 23.9-60.05 fps.
4806
+ // The prompt names references as @Image1, @Video1 (no space; @Element1 for elements,
4807
+ // which the kit does not send). No sound switch on any endpoint.
4808
+ id: "kling-4.0",
4809
+ aliases: ["kling-4", "kling-v4"],
4810
+ label: "Kling 4.0",
4811
+ type: "video",
4812
+ adapter: "fal",
4813
+ providerModelId: "kling/v4",
4814
+ lifecycle: "active",
4815
+ exposure: ["cowork", "space_builder"],
4816
+ constraints: {
4817
+ aspectRatios: ["adaptive", "16:9", "9:16", "1:1", "21:9"],
4818
+ resolutions: ["720p", "1080p"],
4819
+ durations: { min: 3, max: 30 },
4820
+ durationPresets: [5, 10, 15, 30],
4821
+ references: {
4822
+ ...NO_REFERENCES,
4823
+ images: 10,
4824
+ videos: 5,
4825
+ videoSeconds: { min: 3, max: 30.05, total: 30 }
4826
+ },
4827
+ supports: ["lastFrame"],
4828
+ prompt: KLING_V4_PROMPT,
4829
+ audio: KLING_V4_AUDIO
4830
+ },
4831
+ defaults: { durationSeconds: 5, resolution: "1080p", aspectRatio: "16:9" },
4832
+ usage: { ...VIDEO_USAGE },
4833
+ pricingKind: "video_per_second",
4834
+ display: {
4835
+ provider: "kuaishou",
4836
+ logo: KLING_LOGO,
4837
+ description: "Kuaishou Kling 4.0: text-to-video, start/end frames, or reference-to-video from up to 10 images and 5 videos (30 seconds combined), 3-30 seconds at 720p or 1080p. Prompts name references @Image1, @Video1."
4838
+ },
4839
+ capabilities: { lastFrameRequiresFirstFrame: true }
4840
+ },
4841
+ {
4842
+ // https://fal.ai/models/kling/v4/video-to-video/edit/api: source 3-30.05 s (700 px
4843
+ // min, 23.9-60.05 fps), up to 10 reference images. duration 3-30, or left out for the
4844
+ // source's length. The prompt names the source @Video1 and images @Image1, @Image2.
4845
+ id: "kling-4.0-edit",
4846
+ aliases: ["kling-4-edit", "kling-v4-edit"],
4847
+ label: "Kling 4.0 Edit",
4848
+ type: "video",
4849
+ adapter: "fal",
4850
+ providerModelId: "kling/v4/video-to-video/edit",
4851
+ lifecycle: "active",
4852
+ exposure: ["cowork", "space_builder"],
4853
+ constraints: {
4854
+ resolutions: ["720p", "1080p"],
4855
+ durations: { min: 3, max: 30 },
4856
+ references: { ...NO_REFERENCES, images: 10 },
4857
+ requires: ["sourceVideo"],
4858
+ sourceVideoSeconds: { min: 3, max: 30.05 },
4859
+ supports: [],
4860
+ prompt: KLING_V4_PROMPT,
4861
+ audio: KLING_V4_AUDIO
4862
+ },
4863
+ defaults: { resolution: "1080p" },
4864
+ usage: { ...VIDEO_USAGE },
4865
+ pricingKind: "video_per_second",
4866
+ display: {
4867
+ provider: "kuaishou",
4868
+ logo: KLING_LOGO,
4869
+ description: "Kuaishou Kling 4.0 video edit: change a 3-30 second clip with a prompt and up to 10 reference images, at 720p or 1080p, as long as the source or a set 3-30 seconds. Prompts name the source @Video1 and images @Image1."
4870
+ },
4871
+ capabilities: { acceptsSourceVideo: true, videoEdit: true }
4872
+ },
4798
4873
  {
4799
4874
  // https://fal.ai/models/minimax/h3-max-turbo/text-to-video/api (+ /image-to-video).
4800
4875
  // image-to-video takes a start frame, an end frame, or both, and no aspect_ratio.
@@ -5653,38 +5728,38 @@ var VIDEO_MODELS = [
5653
5728
  capabilities: { ...FRAMES_EXCLUDE_REFERENCES }
5654
5729
  },
5655
5730
  {
5656
- // mode standard/pro/4k selects 720p/1080p/4K; the endpoint takes no separate resolution.
5657
- // Replicate: "Max 7 [images] without video, 4 with video"; 4K does not support
5658
- // reference_video. No `videos` limit yet: the adapter sends no reference video,
5659
- // so `imagesWithVideo` stays dormant until one is wired through.
5731
+ // fal Kling O3 (adapters/fal-kling-omni.ts): mode standard/pro/4k selects 720p/1080p/4K
5732
+ // in the endpoint path. Moved off Replicate kwaivgi/kling-v3-omni-video, which fal sells
5733
+ // at half the price; the id and inputs stay. The Replicate mapper stays for deployed
5734
+ // model_catalog rows not yet switched. Frames and reference images share fal's cap of 7.
5735
+ // Reference video, multi-shot and keep-sound were never wired, so stay off.
5660
5736
  id: "kling-v3-omni-video",
5661
5737
  aliases: ["kwaivgi/kling-v3-omni-video", "kling-v3-omni"],
5662
5738
  label: "Kling V3 Omni",
5663
5739
  type: "video",
5664
- adapter: "replicate",
5665
- providerModelId: "kwaivgi/kling-v3-omni-video",
5740
+ adapter: "fal",
5741
+ providerModelId: "fal-ai/kling-video/o3",
5666
5742
  lifecycle: "active",
5667
5743
  exposure: ["cowork", "space_builder"],
5668
5744
  constraints: {
5669
5745
  aspectRatios: [...KLING_OMNI_RATIOS],
5670
5746
  resolutions: ["720p", "1080p", "4k"],
5671
5747
  durations: { min: 3, max: 15 },
5672
- references: { images: 7, imagesWithVideo: 4 },
5748
+ references: { images: 7, videos: 0, audios: 0 },
5673
5749
  supports: ["generateAudio", "lastFrame"],
5674
5750
  prompt: KLING_PROMPT2,
5675
5751
  audio: "optional"
5676
5752
  },
5677
5753
  defaults: { durationSeconds: 5, aspectRatio: "16:9", generateAudio: true, mode: "pro" },
5678
- usage: { unit: "compute_seconds" },
5754
+ usage: { ...VIDEO_USAGE3 },
5679
5755
  pricingKind: "video_per_second",
5680
5756
  display: {
5681
5757
  provider: "kuaishou",
5682
5758
  logo: "https://cdn.jsdelivr.net/npm/@lobehub/icons-static-png@1.97.0/light/kling-color.png",
5683
- description: "Kuaishou Kling Video 3.0 Omni unified generation and editing from text, start/end images, up to 7 reference images, and reference video; up to 15 seconds at up to 4K."
5759
+ description: "Kuaishou Kling Video 3.0 Omni generation from text, start/end images and up to 7 reference images, with optional native audio; up to 15 seconds at up to 4K."
5684
5760
  }
5685
- // end_image "Requires start_image", but no lastFrameRequiresFirstFrame: SpaceLab resolves
5686
- // replicate rows in error mode, so the flag would refuse its end-frame-only nodes, which
5687
- // the adapter sends as start_image.
5761
+ // No lastFrameRequiresFirstFrame: fal image-to-video needs a start frame, so the adapter
5762
+ // sends a lone end frame as the start frame, as the Replicate model took it.
5688
5763
  },
5689
5764
  {
5690
5765
  id: "minimax-h3",
@@ -8439,6 +8514,7 @@ var KLING_TIERS = [
8439
8514
  { mode: "pro", resolution: "1080p" },
8440
8515
  { mode: "4k", resolution: "4k" }
8441
8516
  ];
8517
+ var KLING_O3_OMNI = "fal-ai/kling-video/o3";
8442
8518
  function klingTier(req) {
8443
8519
  return KLING_TIERS.find((tier) => tier.resolution === req.resolution) ?? KLING_TIERS.find((tier) => tier.mode === req.mode) ?? KLING_TIERS[0];
8444
8520
  }
@@ -8448,6 +8524,8 @@ var MOTION_PRO = "fal-ai/kling-video/v3/pro/motion-control";
8448
8524
  var MOTION_STANDARD = "fal-ai/kling-video/v3/standard/motion-control";
8449
8525
  var O3_REFERENCE = "fal-ai/kling-video/o3/pro/reference-to-video";
8450
8526
  var O3_EDIT = "fal-ai/kling-video/o3/pro/video-to-video/edit";
8527
+ var KLING_V4 = "kling/v4";
8528
+ var KLING_V4_EDIT = "kling/v4/video-to-video/edit";
8451
8529
  var H3_TURBO = "minimax/h3-max-turbo";
8452
8530
  var H3_RECAST = "minimax/h3-max/recast";
8453
8531
  var H3_RELIGHT = "minimax/h3-max/relight";
@@ -8456,6 +8534,7 @@ var HAPPY_HORSE_EDIT = "alibaba/happy-horse/video-edit";
8456
8534
  var VIDU_Q4 = "fal-ai/vidu/q4";
8457
8535
  var OMNIHUMAN_V2 = "bytedance/omnihuman/v2";
8458
8536
  var KLING_O3_IMAGE_CAP = 7;
8537
+ var KLING_V4_IMAGE_CAP = 10;
8459
8538
  var TURBO_AUDIO_MIN_SECONDS = 2;
8460
8539
  var OMNIHUMAN_AUDIO_SECONDS = { min: 4, max: 300 };
8461
8540
  function missing(message) {
@@ -8511,6 +8590,23 @@ function o3Reference(req) {
8511
8590
  }
8512
8591
  return needsPrompt(req);
8513
8592
  }
8593
+ function hasReferences(req) {
8594
+ return count(req.referenceImages) + count(req.referenceVideos) > 0;
8595
+ }
8596
+ function klingV4(req) {
8597
+ if (hasReferences(req)) {
8598
+ if (req.lastFrame !== void 0) {
8599
+ return unsupported2("takes an end frame only without reference images or videos");
8600
+ }
8601
+ const images = count(req.referenceImages) + (req.firstFrame === void 0 ? 0 : 1);
8602
+ if (images > KLING_V4_IMAGE_CAP) {
8603
+ return unsupported2(
8604
+ `takes up to ${KLING_V4_IMAGE_CAP} images in all, the start frame included; this request has ${images}`
8605
+ );
8606
+ }
8607
+ }
8608
+ return needsPrompt(req);
8609
+ }
8514
8610
  function h3Turbo(req) {
8515
8611
  if (count(req.referenceImages) + count(req.referenceVideos) > 0) {
8516
8612
  return unsupported2("takes no reference images or videos");
@@ -8587,7 +8683,10 @@ var RULES = /* @__PURE__ */ new Map([
8587
8683
  [MOTION_PRO, motionControl],
8588
8684
  [MOTION_STANDARD, motionControl],
8589
8685
  [O3_REFERENCE, o3Reference],
8686
+ [KLING_O3_OMNI, o3Reference],
8590
8687
  [O3_EDIT, (req) => needsSource(req) ?? needsPrompt(req)],
8688
+ [KLING_V4, klingV4],
8689
+ [KLING_V4_EDIT, (req) => needsSource(req) ?? needsPrompt(req)],
8591
8690
  [H3_TURBO, h3Turbo],
8592
8691
  [MINIMAX_H3_INSERT, h3Insert],
8593
8692
  [H3_RECAST, h3Recast],
@@ -8616,13 +8715,14 @@ function h3EndFrameRatioWarning(model, ratio) {
8616
8715
  message: `${model.id} follows the end frame's aspect ratio`
8617
8716
  };
8618
8717
  }
8619
- function isReplicateKling(model) {
8718
+ function takesKlingMode(model) {
8719
+ if (model.adapter === "fal") return model.providerModelId.toLowerCase() === KLING_O3_OMNI;
8620
8720
  if (model.adapter !== "replicate") return false;
8621
8721
  const kind = videoKind(model.providerModelId);
8622
8722
  return kind === "kling" || kind === "kling-omni";
8623
8723
  }
8624
- function fillReplicateKlingResolution(model, req) {
8625
- if (isReplicateKling(model) && req.resolution === void 0) {
8724
+ function fillKlingModeResolution(model, req) {
8725
+ if (takesKlingMode(model) && req.resolution === void 0) {
8626
8726
  req.resolution = klingTier(req).resolution;
8627
8727
  }
8628
8728
  }
@@ -8636,6 +8736,19 @@ function applyFalVideoRules(model, req, callerRatio, warnings) {
8636
8736
  warnings.push(viduSilentWarning(model));
8637
8737
  req.generateAudio = false;
8638
8738
  }
8739
+ if (id === KLING_V4 && req.firstFrame !== void 0 && !hasReferences(req)) {
8740
+ if (req.aspectRatio !== void 0) {
8741
+ if (callerRatio !== void 0) {
8742
+ warnings.push({
8743
+ code: "ratio_dropped",
8744
+ field: "aspectRatio",
8745
+ from: req.aspectRatio,
8746
+ message: `${model.id} follows the start frame's aspect ratio`
8747
+ });
8748
+ }
8749
+ delete req.aspectRatio;
8750
+ }
8751
+ }
8639
8752
  const endFrameOnly = req.lastFrame !== void 0 && req.firstFrame === void 0;
8640
8753
  if (id === H3_TURBO && endFrameOnly && req.aspectRatio !== void 0) {
8641
8754
  if (callerRatio !== void 0 && callerRatio !== "adaptive") {
@@ -9015,10 +9128,10 @@ function resolveVideoOptions(model, request, onUnsupported = "error") {
9015
9128
  warnings
9016
9129
  );
9017
9130
  if (aspectRatio !== void 0) merged.aspectRatio = aspectRatio;
9018
- fillReplicateKlingResolution(model, merged);
9131
+ fillKlingModeResolution(model, merged);
9019
9132
  const resolution = resolveVideoResolution(merged.resolution, model, onUnsupported, warnings);
9020
9133
  if (resolution !== void 0) merged.resolution = resolution;
9021
- if (isReplicateKling(model)) delete merged.mode;
9134
+ if (takesKlingMode(model)) delete merged.mode;
9022
9135
  const duration = resolveDuration(
9023
9136
  merged.durationSeconds,
9024
9137
  c.durations,