@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/CHANGELOG.md CHANGED
@@ -9,6 +9,28 @@ header in the release PR.
9
9
 
10
10
  ## [Unreleased]
11
11
 
12
+ ## [0.7.11] - Unreleased
13
+
14
+ Kling 4.0 on fal.
15
+
16
+ ### Added
17
+ - `kling-4.0` (fal `kling/v4`): one row for text-, image- and reference-to-video. Reference images or videos go to `kling/v4/reference-to-video` (`image_urls`, `video_urls`, and a start frame as `start_image_url`), else a start frame to `image-to-video` (with an optional end frame), else `text-to-video`. 720p / 1080p, 3-30 s (whole seconds), aspect ratios `adaptive` (fal's `auto` on reference-to-video), 16:9, 9:16, 1:1, 21:9. References: 10 images (the start frame counts toward them) and 5 videos, each 3-30.05 s and 30 s combined. An end frame with references, more than 10 images with the start frame, and a blank prompt are refused before the call.
18
+ - `kling-4.0-edit` (fal `kling/v4/video-to-video/edit`): a 3-30.05 s source plus up to 10 reference images, 720p / 1080p. `durationSeconds` 3-30 sets the output length; left out, the output (and its usage) is the source's length.
19
+ - Prompts name inputs `@Image1`, `@Video1` (no space); on an edit the source is `@Video1`. Kit requests send no Kling elements.
20
+ - Neither endpoint has a sound field, so both rows declare `audio: "always"` and drop `generateAudio` with an `option_ignored` warning.
21
+ - Usage reports the output seconds and resolution. fal bills a request with reference videos, and every edit, on input plus output seconds (at least twice the output) at a lower rate; pricing that is the consumer's job (pro-backend's video-input rate).
22
+
23
+ ## [0.7.10] - Unreleased
24
+
25
+ Kling V3 Omni moves from Replicate to fal at half the provider cost.
26
+
27
+ ### Changed
28
+ - `kling-v3-omni-video` runs on fal Kling O3 (`adapter: "fal"`, `providerModelId: "fal-ai/kling-video/o3"`) instead of Replicate `kwaivgi/kling-v3-omni-video`. The id, aliases, ratios, resolutions, durations, defaults and the `mode` to resolution rule stay. The tier picks the endpoint path (`standard` 720p, `pro` 1080p, `4k`), and the inputs pick the task: reference images go to `reference-to-video`, frames alone to `image-to-video`, a prompt alone to `text-to-video`. A lone end frame still goes as the start frame. fal cost per second: standard $0.084 silent / $0.112 sound, pro $0.112 / $0.14, 4k $0.42 (Replicate: $0.168 / $0.224, $0.224 / $0.28, $0.42).
29
+ - The row's usage unit is `seconds` (was Replicate `compute_seconds`): usage events now carry provider `fal`, the requested length and the rendered resolution.
30
+ - The row declares `videos: 0, audios: 0` (was no video slot and a dormant `imagesWithVideo: 4`). The Replicate adapter never sent a reference video, so nothing that worked is lost; the resolver now trims one with `references_trimmed` instead of passing it through. Frames and reference images share fal's cap of 7, as on `kling-o3`. The display description no longer claims editing or reference video.
31
+ - The Replicate `kwaivgi/kling-v3-omni-video` mapper stays. `seed-model-catalog` never updates an existing row, so each deployed `model_catalog` row keeps running on Replicate after the bump, until it is switched to this row's `adapter`, `providerModelId`, `references` and `usage` (pro-admin, per env). Reverting that edit rolls back.
32
+ - Consumers that branch on `adapter === "replicate"` for this row (shopos-ui vibe-triggers, the trigger-workflows wire test) must handle the fal row before an env is switched.
33
+
12
34
  ## [0.7.8] - Unreleased
13
35
 
14
36
  ENG-3324: Ray 3.2 offers 10 s clips.
package/dist/catalog.cjs CHANGED
@@ -4778,6 +4778,8 @@ function range(min, max) {
4778
4778
  }
4779
4779
  var KLING_PROMPT = { referenceSyntax: "numbered", maxChars: 2500 };
4780
4780
  var H3_PROMPT = { referenceSyntax: "numbered", maxChars: 5e4 };
4781
+ var KLING_V4_PROMPT = { referenceSyntax: "numbered", maxChars: 2500 };
4782
+ var KLING_V4_AUDIO = "always";
4781
4783
  var NO_REFERENCES = { images: 0, videos: 0, audios: 0 };
4782
4784
  function klingMotionControl(tier) {
4783
4785
  const label = tier === "pro" ? "Pro" : "Standard";
@@ -4878,6 +4880,79 @@ var VIDEO_FAMILY_MODELS = [
4878
4880
  },
4879
4881
  capabilities: { acceptsSourceVideo: true, videoEdit: true }
4880
4882
  },
4883
+ {
4884
+ // https://fal.ai/models/kling/v4/reference-to-video/api (+ /text-to-video,
4885
+ // /image-to-video): one row; references (images or videos) go to reference-to-video,
4886
+ // else a start frame to image-to-video, else text-to-video. Reference images: 10, the
4887
+ // start frame included (fal: "counts toward the image reference limit"), 300 px min.
4888
+ // Reference videos: 5, 3-30.05 s each and 30 s combined, 700 px min, 23.9-60.05 fps.
4889
+ // The prompt names references as @Image1, @Video1 (no space; @Element1 for elements,
4890
+ // which the kit does not send). No sound switch on any endpoint.
4891
+ id: "kling-4.0",
4892
+ aliases: ["kling-4", "kling-v4"],
4893
+ label: "Kling 4.0",
4894
+ type: "video",
4895
+ adapter: "fal",
4896
+ providerModelId: "kling/v4",
4897
+ lifecycle: "active",
4898
+ exposure: ["cowork", "space_builder"],
4899
+ constraints: {
4900
+ aspectRatios: ["adaptive", "16:9", "9:16", "1:1", "21:9"],
4901
+ resolutions: ["720p", "1080p"],
4902
+ durations: { min: 3, max: 30 },
4903
+ durationPresets: [5, 10, 15, 30],
4904
+ references: {
4905
+ ...NO_REFERENCES,
4906
+ images: 10,
4907
+ videos: 5,
4908
+ videoSeconds: { min: 3, max: 30.05, total: 30 }
4909
+ },
4910
+ supports: ["lastFrame"],
4911
+ prompt: KLING_V4_PROMPT,
4912
+ audio: KLING_V4_AUDIO
4913
+ },
4914
+ defaults: { durationSeconds: 5, resolution: "1080p", aspectRatio: "16:9" },
4915
+ usage: { ...VIDEO_USAGE },
4916
+ pricingKind: "video_per_second",
4917
+ display: {
4918
+ provider: "kuaishou",
4919
+ logo: KLING_LOGO,
4920
+ 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."
4921
+ },
4922
+ capabilities: { lastFrameRequiresFirstFrame: true }
4923
+ },
4924
+ {
4925
+ // https://fal.ai/models/kling/v4/video-to-video/edit/api: source 3-30.05 s (700 px
4926
+ // min, 23.9-60.05 fps), up to 10 reference images. duration 3-30, or left out for the
4927
+ // source's length. The prompt names the source @Video1 and images @Image1, @Image2.
4928
+ id: "kling-4.0-edit",
4929
+ aliases: ["kling-4-edit", "kling-v4-edit"],
4930
+ label: "Kling 4.0 Edit",
4931
+ type: "video",
4932
+ adapter: "fal",
4933
+ providerModelId: "kling/v4/video-to-video/edit",
4934
+ lifecycle: "active",
4935
+ exposure: ["cowork", "space_builder"],
4936
+ constraints: {
4937
+ resolutions: ["720p", "1080p"],
4938
+ durations: { min: 3, max: 30 },
4939
+ references: { ...NO_REFERENCES, images: 10 },
4940
+ requires: ["sourceVideo"],
4941
+ sourceVideoSeconds: { min: 3, max: 30.05 },
4942
+ supports: [],
4943
+ prompt: KLING_V4_PROMPT,
4944
+ audio: KLING_V4_AUDIO
4945
+ },
4946
+ defaults: { resolution: "1080p" },
4947
+ usage: { ...VIDEO_USAGE },
4948
+ pricingKind: "video_per_second",
4949
+ display: {
4950
+ provider: "kuaishou",
4951
+ logo: KLING_LOGO,
4952
+ 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."
4953
+ },
4954
+ capabilities: { acceptsSourceVideo: true, videoEdit: true }
4955
+ },
4881
4956
  {
4882
4957
  // https://fal.ai/models/minimax/h3-max-turbo/text-to-video/api (+ /image-to-video).
4883
4958
  // image-to-video takes a start frame, an end frame, or both, and no aspect_ratio.
@@ -5736,38 +5811,38 @@ var VIDEO_MODELS = [
5736
5811
  capabilities: { ...FRAMES_EXCLUDE_REFERENCES }
5737
5812
  },
5738
5813
  {
5739
- // mode standard/pro/4k selects 720p/1080p/4K; the endpoint takes no separate resolution.
5740
- // Replicate: "Max 7 [images] without video, 4 with video"; 4K does not support
5741
- // reference_video. No `videos` limit yet: the adapter sends no reference video,
5742
- // so `imagesWithVideo` stays dormant until one is wired through.
5814
+ // fal Kling O3 (adapters/fal-kling-omni.ts): mode standard/pro/4k selects 720p/1080p/4K
5815
+ // in the endpoint path. Moved off Replicate kwaivgi/kling-v3-omni-video, which fal sells
5816
+ // at half the price; the id and inputs stay. The Replicate mapper stays for deployed
5817
+ // model_catalog rows not yet switched. Frames and reference images share fal's cap of 7.
5818
+ // Reference video, multi-shot and keep-sound were never wired, so stay off.
5743
5819
  id: "kling-v3-omni-video",
5744
5820
  aliases: ["kwaivgi/kling-v3-omni-video", "kling-v3-omni"],
5745
5821
  label: "Kling V3 Omni",
5746
5822
  type: "video",
5747
- adapter: "replicate",
5748
- providerModelId: "kwaivgi/kling-v3-omni-video",
5823
+ adapter: "fal",
5824
+ providerModelId: "fal-ai/kling-video/o3",
5749
5825
  lifecycle: "active",
5750
5826
  exposure: ["cowork", "space_builder"],
5751
5827
  constraints: {
5752
5828
  aspectRatios: [...KLING_OMNI_RATIOS],
5753
5829
  resolutions: ["720p", "1080p", "4k"],
5754
5830
  durations: { min: 3, max: 15 },
5755
- references: { images: 7, imagesWithVideo: 4 },
5831
+ references: { images: 7, videos: 0, audios: 0 },
5756
5832
  supports: ["generateAudio", "lastFrame"],
5757
5833
  prompt: KLING_PROMPT2,
5758
5834
  audio: "optional"
5759
5835
  },
5760
5836
  defaults: { durationSeconds: 5, aspectRatio: "16:9", generateAudio: true, mode: "pro" },
5761
- usage: { unit: "compute_seconds" },
5837
+ usage: { ...VIDEO_USAGE3 },
5762
5838
  pricingKind: "video_per_second",
5763
5839
  display: {
5764
5840
  provider: "kuaishou",
5765
5841
  logo: "https://cdn.jsdelivr.net/npm/@lobehub/icons-static-png@1.97.0/light/kling-color.png",
5766
- 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."
5842
+ 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."
5767
5843
  }
5768
- // end_image "Requires start_image", but no lastFrameRequiresFirstFrame: SpaceLab resolves
5769
- // replicate rows in error mode, so the flag would refuse its end-frame-only nodes, which
5770
- // the adapter sends as start_image.
5844
+ // No lastFrameRequiresFirstFrame: fal image-to-video needs a start frame, so the adapter
5845
+ // sends a lone end frame as the start frame, as the Replicate model took it.
5771
5846
  },
5772
5847
  {
5773
5848
  id: "minimax-h3",
@@ -8522,6 +8597,7 @@ var KLING_TIERS = [
8522
8597
  { mode: "pro", resolution: "1080p" },
8523
8598
  { mode: "4k", resolution: "4k" }
8524
8599
  ];
8600
+ var KLING_O3_OMNI = "fal-ai/kling-video/o3";
8525
8601
  function klingTier(req) {
8526
8602
  return KLING_TIERS.find((tier) => tier.resolution === req.resolution) ?? KLING_TIERS.find((tier) => tier.mode === req.mode) ?? KLING_TIERS[0];
8527
8603
  }
@@ -8531,6 +8607,8 @@ var MOTION_PRO = "fal-ai/kling-video/v3/pro/motion-control";
8531
8607
  var MOTION_STANDARD = "fal-ai/kling-video/v3/standard/motion-control";
8532
8608
  var O3_REFERENCE = "fal-ai/kling-video/o3/pro/reference-to-video";
8533
8609
  var O3_EDIT = "fal-ai/kling-video/o3/pro/video-to-video/edit";
8610
+ var KLING_V4 = "kling/v4";
8611
+ var KLING_V4_EDIT = "kling/v4/video-to-video/edit";
8534
8612
  var H3_TURBO = "minimax/h3-max-turbo";
8535
8613
  var H3_RECAST = "minimax/h3-max/recast";
8536
8614
  var H3_RELIGHT = "minimax/h3-max/relight";
@@ -8539,6 +8617,7 @@ var HAPPY_HORSE_EDIT = "alibaba/happy-horse/video-edit";
8539
8617
  var VIDU_Q4 = "fal-ai/vidu/q4";
8540
8618
  var OMNIHUMAN_V2 = "bytedance/omnihuman/v2";
8541
8619
  var KLING_O3_IMAGE_CAP = 7;
8620
+ var KLING_V4_IMAGE_CAP = 10;
8542
8621
  var TURBO_AUDIO_MIN_SECONDS = 2;
8543
8622
  var OMNIHUMAN_AUDIO_SECONDS = { min: 4, max: 300 };
8544
8623
  function missing(message) {
@@ -8594,6 +8673,23 @@ function o3Reference(req) {
8594
8673
  }
8595
8674
  return needsPrompt(req);
8596
8675
  }
8676
+ function hasReferences(req) {
8677
+ return count(req.referenceImages) + count(req.referenceVideos) > 0;
8678
+ }
8679
+ function klingV4(req) {
8680
+ if (hasReferences(req)) {
8681
+ if (req.lastFrame !== void 0) {
8682
+ return unsupported2("takes an end frame only without reference images or videos");
8683
+ }
8684
+ const images = count(req.referenceImages) + (req.firstFrame === void 0 ? 0 : 1);
8685
+ if (images > KLING_V4_IMAGE_CAP) {
8686
+ return unsupported2(
8687
+ `takes up to ${KLING_V4_IMAGE_CAP} images in all, the start frame included; this request has ${images}`
8688
+ );
8689
+ }
8690
+ }
8691
+ return needsPrompt(req);
8692
+ }
8597
8693
  function h3Turbo(req) {
8598
8694
  if (count(req.referenceImages) + count(req.referenceVideos) > 0) {
8599
8695
  return unsupported2("takes no reference images or videos");
@@ -8670,7 +8766,10 @@ var RULES = /* @__PURE__ */ new Map([
8670
8766
  [MOTION_PRO, motionControl],
8671
8767
  [MOTION_STANDARD, motionControl],
8672
8768
  [O3_REFERENCE, o3Reference],
8769
+ [KLING_O3_OMNI, o3Reference],
8673
8770
  [O3_EDIT, (req) => needsSource(req) ?? needsPrompt(req)],
8771
+ [KLING_V4, klingV4],
8772
+ [KLING_V4_EDIT, (req) => needsSource(req) ?? needsPrompt(req)],
8674
8773
  [H3_TURBO, h3Turbo],
8675
8774
  [MINIMAX_H3_INSERT, h3Insert],
8676
8775
  [H3_RECAST, h3Recast],
@@ -8699,13 +8798,14 @@ function h3EndFrameRatioWarning(model, ratio) {
8699
8798
  message: `${model.id} follows the end frame's aspect ratio`
8700
8799
  };
8701
8800
  }
8702
- function isReplicateKling(model) {
8801
+ function takesKlingMode(model) {
8802
+ if (model.adapter === "fal") return model.providerModelId.toLowerCase() === KLING_O3_OMNI;
8703
8803
  if (model.adapter !== "replicate") return false;
8704
8804
  const kind = videoKind(model.providerModelId);
8705
8805
  return kind === "kling" || kind === "kling-omni";
8706
8806
  }
8707
- function fillReplicateKlingResolution(model, req) {
8708
- if (isReplicateKling(model) && req.resolution === void 0) {
8807
+ function fillKlingModeResolution(model, req) {
8808
+ if (takesKlingMode(model) && req.resolution === void 0) {
8709
8809
  req.resolution = klingTier(req).resolution;
8710
8810
  }
8711
8811
  }
@@ -8719,6 +8819,19 @@ function applyFalVideoRules(model, req, callerRatio, warnings) {
8719
8819
  warnings.push(viduSilentWarning(model));
8720
8820
  req.generateAudio = false;
8721
8821
  }
8822
+ if (id === KLING_V4 && req.firstFrame !== void 0 && !hasReferences(req)) {
8823
+ if (req.aspectRatio !== void 0) {
8824
+ if (callerRatio !== void 0) {
8825
+ warnings.push({
8826
+ code: "ratio_dropped",
8827
+ field: "aspectRatio",
8828
+ from: req.aspectRatio,
8829
+ message: `${model.id} follows the start frame's aspect ratio`
8830
+ });
8831
+ }
8832
+ delete req.aspectRatio;
8833
+ }
8834
+ }
8722
8835
  const endFrameOnly = req.lastFrame !== void 0 && req.firstFrame === void 0;
8723
8836
  if (id === H3_TURBO && endFrameOnly && req.aspectRatio !== void 0) {
8724
8837
  if (callerRatio !== void 0 && callerRatio !== "adaptive") {
@@ -9098,10 +9211,10 @@ function resolveVideoOptions(model, request, onUnsupported = "error") {
9098
9211
  warnings
9099
9212
  );
9100
9213
  if (aspectRatio !== void 0) merged.aspectRatio = aspectRatio;
9101
- fillReplicateKlingResolution(model, merged);
9214
+ fillKlingModeResolution(model, merged);
9102
9215
  const resolution = resolveVideoResolution(merged.resolution, model, onUnsupported, warnings);
9103
9216
  if (resolution !== void 0) merged.resolution = resolution;
9104
- if (isReplicateKling(model)) delete merged.mode;
9217
+ if (takesKlingMode(model)) delete merged.mode;
9105
9218
  const duration = resolveDuration(
9106
9219
  merged.durationSeconds,
9107
9220
  c.durations,