@shop-os/modelkit 0.7.7 → 0.7.10

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,24 @@ header in the release PR.
9
9
 
10
10
  ## [Unreleased]
11
11
 
12
+ ## [0.7.10] - Unreleased
13
+
14
+ Kling V3 Omni moves from Replicate to fal at half the provider cost.
15
+
16
+ ### Changed
17
+ - `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).
18
+ - The row's usage unit is `seconds` (was Replicate `compute_seconds`): usage events now carry provider `fal`, the requested length and the rendered resolution.
19
+ - 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.
20
+ - 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.
21
+ - 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.
22
+
23
+ ## [0.7.8] - Unreleased
24
+
25
+ ENG-3324: Ray 3.2 offers 10 s clips.
26
+
27
+ ### Changed
28
+ - `ray-3.2` offers `durations: [5, 10]` (was `[5]`); the default stays 5 s. The Luma adapter sends the requested length (`"10s"`) instead of a fixed `"5s"`, and a generate reports the block it asked for (5 or 10) as `durationSeconds`, never the measured frames. A generate of any other length is refused with `unsupported_option` before a request, since nothing prices it. Luma bills a 10 s clip at 3x the 5 s price; pro-backend prices it through its billed-seconds map (`{"10": 15}`), so usage keeps the real 10 s. Consumers must not offer this version before that pricing is deployed, or a 10 s clip bills 2x.
29
+
12
30
  ## [0.7.7] - Unreleased
13
31
 
14
32
  ### Fixed
package/dist/catalog.cjs CHANGED
@@ -5201,8 +5201,10 @@ var RAY_RESOLUTIONS = ["360p", "720p", "1080p"];
5201
5201
  var RAY_PROMPT = { referenceSyntax: "numbered", maxChars: 6e3 };
5202
5202
  var LUMA_VIDEO_MODELS = [
5203
5203
  {
5204
- // https://docs.agents.lumalabs.ai: type "video" with a fixed 5 s duration;
5205
- // firstFrame and lastFrame ride as start_frame and end_frame.
5204
+ // https://docs.agents.lumalabs.ai: type "video" with a 5 s or 10 s duration;
5205
+ // firstFrame and lastFrame ride as start_frame and end_frame. Luma bills a
5206
+ // 10 s clip at 3x the 5 s price; pro-backend prices it that way, so this row
5207
+ // must not offer 10 s before that pricing is deployed (ENG-3324).
5206
5208
  id: "ray-3.2",
5207
5209
  aliases: [],
5208
5210
  label: "Ray 3.2",
@@ -5214,7 +5216,7 @@ var LUMA_VIDEO_MODELS = [
5214
5216
  constraints: {
5215
5217
  aspectRatios: ["adaptive", ...RAY_RATIOS],
5216
5218
  resolutions: [...RAY_RESOLUTIONS],
5217
- durations: [5],
5219
+ durations: [5, 10],
5218
5220
  supports: ["lastFrame"],
5219
5221
  prompt: { ...RAY_PROMPT },
5220
5222
  audio: "never"
@@ -5224,7 +5226,7 @@ var LUMA_VIDEO_MODELS = [
5224
5226
  pricingKind: "video_per_second",
5225
5227
  display: {
5226
5228
  provider: "luma",
5227
- description: "Luma Ray 3.2 text- and image-to-video with optional first and last frames, 5-second clips at up to 1080p.",
5229
+ description: "Luma Ray 3.2 text- and image-to-video with optional first and last frames, 5- or 10-second clips at up to 1080p.",
5228
5230
  logo: LUMA_LOGO2
5229
5231
  },
5230
5232
  capabilities: {}
@@ -5734,38 +5736,38 @@ var VIDEO_MODELS = [
5734
5736
  capabilities: { ...FRAMES_EXCLUDE_REFERENCES }
5735
5737
  },
5736
5738
  {
5737
- // mode standard/pro/4k selects 720p/1080p/4K; the endpoint takes no separate resolution.
5738
- // Replicate: "Max 7 [images] without video, 4 with video"; 4K does not support
5739
- // reference_video. No `videos` limit yet: the adapter sends no reference video,
5740
- // so `imagesWithVideo` stays dormant until one is wired through.
5739
+ // fal Kling O3 (adapters/fal-kling-omni.ts): mode standard/pro/4k selects 720p/1080p/4K
5740
+ // in the endpoint path. Moved off Replicate kwaivgi/kling-v3-omni-video, which fal sells
5741
+ // at half the price; the id and inputs stay. The Replicate mapper stays for deployed
5742
+ // model_catalog rows not yet switched. Frames and reference images share fal's cap of 7.
5743
+ // Reference video, multi-shot and keep-sound were never wired, so stay off.
5741
5744
  id: "kling-v3-omni-video",
5742
5745
  aliases: ["kwaivgi/kling-v3-omni-video", "kling-v3-omni"],
5743
5746
  label: "Kling V3 Omni",
5744
5747
  type: "video",
5745
- adapter: "replicate",
5746
- providerModelId: "kwaivgi/kling-v3-omni-video",
5748
+ adapter: "fal",
5749
+ providerModelId: "fal-ai/kling-video/o3",
5747
5750
  lifecycle: "active",
5748
5751
  exposure: ["cowork", "space_builder"],
5749
5752
  constraints: {
5750
5753
  aspectRatios: [...KLING_OMNI_RATIOS],
5751
5754
  resolutions: ["720p", "1080p", "4k"],
5752
5755
  durations: { min: 3, max: 15 },
5753
- references: { images: 7, imagesWithVideo: 4 },
5756
+ references: { images: 7, videos: 0, audios: 0 },
5754
5757
  supports: ["generateAudio", "lastFrame"],
5755
5758
  prompt: KLING_PROMPT2,
5756
5759
  audio: "optional"
5757
5760
  },
5758
5761
  defaults: { durationSeconds: 5, aspectRatio: "16:9", generateAudio: true, mode: "pro" },
5759
- usage: { unit: "compute_seconds" },
5762
+ usage: { ...VIDEO_USAGE3 },
5760
5763
  pricingKind: "video_per_second",
5761
5764
  display: {
5762
5765
  provider: "kuaishou",
5763
5766
  logo: "https://cdn.jsdelivr.net/npm/@lobehub/icons-static-png@1.97.0/light/kling-color.png",
5764
- 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."
5767
+ 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."
5765
5768
  }
5766
- // end_image "Requires start_image", but no lastFrameRequiresFirstFrame: SpaceLab resolves
5767
- // replicate rows in error mode, so the flag would refuse its end-frame-only nodes, which
5768
- // the adapter sends as start_image.
5769
+ // No lastFrameRequiresFirstFrame: fal image-to-video needs a start frame, so the adapter
5770
+ // sends a lone end frame as the start frame, as the Replicate model took it.
5769
5771
  },
5770
5772
  {
5771
5773
  id: "minimax-h3",
@@ -8520,6 +8522,7 @@ var KLING_TIERS = [
8520
8522
  { mode: "pro", resolution: "1080p" },
8521
8523
  { mode: "4k", resolution: "4k" }
8522
8524
  ];
8525
+ var KLING_O3_OMNI = "fal-ai/kling-video/o3";
8523
8526
  function klingTier(req) {
8524
8527
  return KLING_TIERS.find((tier) => tier.resolution === req.resolution) ?? KLING_TIERS.find((tier) => tier.mode === req.mode) ?? KLING_TIERS[0];
8525
8528
  }
@@ -8668,6 +8671,7 @@ var RULES = /* @__PURE__ */ new Map([
8668
8671
  [MOTION_PRO, motionControl],
8669
8672
  [MOTION_STANDARD, motionControl],
8670
8673
  [O3_REFERENCE, o3Reference],
8674
+ [KLING_O3_OMNI, o3Reference],
8671
8675
  [O3_EDIT, (req) => needsSource(req) ?? needsPrompt(req)],
8672
8676
  [H3_TURBO, h3Turbo],
8673
8677
  [MINIMAX_H3_INSERT, h3Insert],
@@ -8697,13 +8701,14 @@ function h3EndFrameRatioWarning(model, ratio) {
8697
8701
  message: `${model.id} follows the end frame's aspect ratio`
8698
8702
  };
8699
8703
  }
8700
- function isReplicateKling(model) {
8704
+ function takesKlingMode(model) {
8705
+ if (model.adapter === "fal") return model.providerModelId.toLowerCase() === KLING_O3_OMNI;
8701
8706
  if (model.adapter !== "replicate") return false;
8702
8707
  const kind = videoKind(model.providerModelId);
8703
8708
  return kind === "kling" || kind === "kling-omni";
8704
8709
  }
8705
- function fillReplicateKlingResolution(model, req) {
8706
- if (isReplicateKling(model) && req.resolution === void 0) {
8710
+ function fillKlingModeResolution(model, req) {
8711
+ if (takesKlingMode(model) && req.resolution === void 0) {
8707
8712
  req.resolution = klingTier(req).resolution;
8708
8713
  }
8709
8714
  }
@@ -9096,10 +9101,10 @@ function resolveVideoOptions(model, request, onUnsupported = "error") {
9096
9101
  warnings
9097
9102
  );
9098
9103
  if (aspectRatio !== void 0) merged.aspectRatio = aspectRatio;
9099
- fillReplicateKlingResolution(model, merged);
9104
+ fillKlingModeResolution(model, merged);
9100
9105
  const resolution = resolveVideoResolution(merged.resolution, model, onUnsupported, warnings);
9101
9106
  if (resolution !== void 0) merged.resolution = resolution;
9102
- if (isReplicateKling(model)) delete merged.mode;
9107
+ if (takesKlingMode(model)) delete merged.mode;
9103
9108
  const duration = resolveDuration(
9104
9109
  merged.durationSeconds,
9105
9110
  c.durations,