@shop-os/modelkit 0.7.8 → 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/dist/index.js CHANGED
@@ -5664,38 +5664,38 @@ var VIDEO_MODELS = [
5664
5664
  capabilities: { ...FRAMES_EXCLUDE_REFERENCES }
5665
5665
  },
5666
5666
  {
5667
- // mode standard/pro/4k selects 720p/1080p/4K; the endpoint takes no separate resolution.
5668
- // Replicate: "Max 7 [images] without video, 4 with video"; 4K does not support
5669
- // reference_video. No `videos` limit yet: the adapter sends no reference video,
5670
- // so `imagesWithVideo` stays dormant until one is wired through.
5667
+ // fal Kling O3 (adapters/fal-kling-omni.ts): mode standard/pro/4k selects 720p/1080p/4K
5668
+ // in the endpoint path. Moved off Replicate kwaivgi/kling-v3-omni-video, which fal sells
5669
+ // at half the price; the id and inputs stay. The Replicate mapper stays for deployed
5670
+ // model_catalog rows not yet switched. Frames and reference images share fal's cap of 7.
5671
+ // Reference video, multi-shot and keep-sound were never wired, so stay off.
5671
5672
  id: "kling-v3-omni-video",
5672
5673
  aliases: ["kwaivgi/kling-v3-omni-video", "kling-v3-omni"],
5673
5674
  label: "Kling V3 Omni",
5674
5675
  type: "video",
5675
- adapter: "replicate",
5676
- providerModelId: "kwaivgi/kling-v3-omni-video",
5676
+ adapter: "fal",
5677
+ providerModelId: "fal-ai/kling-video/o3",
5677
5678
  lifecycle: "active",
5678
5679
  exposure: ["cowork", "space_builder"],
5679
5680
  constraints: {
5680
5681
  aspectRatios: [...KLING_OMNI_RATIOS],
5681
5682
  resolutions: ["720p", "1080p", "4k"],
5682
5683
  durations: { min: 3, max: 15 },
5683
- references: { images: 7, imagesWithVideo: 4 },
5684
+ references: { images: 7, videos: 0, audios: 0 },
5684
5685
  supports: ["generateAudio", "lastFrame"],
5685
5686
  prompt: KLING_PROMPT2,
5686
5687
  audio: "optional"
5687
5688
  },
5688
5689
  defaults: { durationSeconds: 5, aspectRatio: "16:9", generateAudio: true, mode: "pro" },
5689
- usage: { unit: "compute_seconds" },
5690
+ usage: { ...VIDEO_USAGE3 },
5690
5691
  pricingKind: "video_per_second",
5691
5692
  display: {
5692
5693
  provider: "kuaishou",
5693
5694
  logo: "https://cdn.jsdelivr.net/npm/@lobehub/icons-static-png@1.97.0/light/kling-color.png",
5694
- 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."
5695
+ 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."
5695
5696
  }
5696
- // end_image "Requires start_image", but no lastFrameRequiresFirstFrame: SpaceLab resolves
5697
- // replicate rows in error mode, so the flag would refuse its end-frame-only nodes, which
5698
- // the adapter sends as start_image.
5697
+ // No lastFrameRequiresFirstFrame: fal image-to-video needs a start frame, so the adapter
5698
+ // sends a lone end frame as the start frame, as the Replicate model took it.
5699
5699
  },
5700
5700
  {
5701
5701
  id: "minimax-h3",
@@ -9310,11 +9310,11 @@ function toolInput(ctx, req, output) {
9310
9310
  }
9311
9311
  var EXR_DEFAULT_PROMPT = "The same video in high dynamic range, with unchanged content, motion, framing and timing.";
9312
9312
  async function submitFalVideoTool(req, ctx, opts) {
9313
- const plan3 = planVideoTool(ctx.model, req);
9314
- if (!plan3.ok) {
9313
+ const plan4 = planVideoTool(ctx.model, req);
9314
+ if (!plan4.ok) {
9315
9315
  throw new ModelKitError({
9316
9316
  code: "unsupported_option",
9317
- message: plan3.error,
9317
+ message: plan4.error,
9318
9318
  provider: "fal",
9319
9319
  model: ctx.model.id,
9320
9320
  retryable: false
@@ -9322,7 +9322,7 @@ async function submitFalVideoTool(req, ctx, opts) {
9322
9322
  }
9323
9323
  const target = new URL(`${FAL_QUEUE_ORIGIN}/${ctx.model.providerModelId}`);
9324
9324
  if (opts.webhookUrl !== void 0) target.searchParams.set("fal_webhook", opts.webhookUrl);
9325
- const res = await queueFetch(ctx, target.toString(), "POST", toolInput(ctx, req, plan3.output));
9325
+ const res = await queueFetch(ctx, target.toString(), "POST", toolInput(ctx, req, plan4.output));
9326
9326
  const parsed = submitResponseSchema.safeParse(await readJson(ctx, res));
9327
9327
  if (!parsed.success) {
9328
9328
  throw new ModelKitError({
@@ -9340,7 +9340,7 @@ async function submitFalVideoTool(req, ctx, opts) {
9340
9340
  statusUrl: parsed.data.status_url,
9341
9341
  responseUrl: parsed.data.response_url,
9342
9342
  cancelUrl: parsed.data.cancel_url,
9343
- output: plan3.output
9343
+ output: plan4.output
9344
9344
  };
9345
9345
  }
9346
9346
  async function falVideoToolStatus(sub, ctx) {
@@ -10029,14 +10029,14 @@ function planFalImage(req, providerModelId, model) {
10029
10029
  const exact = falExactSize(spec, req);
10030
10030
  const call = { label: spec.label, req, refs, edit: edit2, ...exact !== void 0 && { exact } };
10031
10031
  const built = family.build(call, model);
10032
- const plan3 = {
10032
+ const plan4 = {
10033
10033
  endpoint: edit2 && family.editEndpoint !== void 0 ? family.editEndpoint : id,
10034
10034
  input: built.input,
10035
10035
  output: family.output ?? "images"
10036
10036
  };
10037
- if (built.imageQuality !== void 0) plan3.imageQuality = built.imageQuality;
10038
- if (built.imageSize !== void 0) plan3.imageSize = built.imageSize;
10039
- return plan3;
10037
+ if (built.imageQuality !== void 0) plan4.imageQuality = built.imageQuality;
10038
+ if (built.imageSize !== void 0) plan4.imageSize = built.imageSize;
10039
+ return plan4;
10040
10040
  }
10041
10041
  var FalFileSchema = z14.object({ url: z14.string(), content_type: z14.string().nullish() });
10042
10042
  var ImagesPayloadSchema = z14.object({ images: z14.array(FalFileSchema) });
@@ -10058,18 +10058,18 @@ async function downloadFalFile(ctx, file) {
10058
10058
  const mime = res.headers.get("content-type") ?? file.content_type ?? "";
10059
10059
  return { bytes: new Uint8Array(await res.arrayBuffer()), mime };
10060
10060
  }
10061
- function filesOf(payload, plan3) {
10062
- if (plan3.output === "image") {
10061
+ function filesOf(payload, plan4) {
10062
+ if (plan4.output === "image") {
10063
10063
  const parsed2 = ImagePayloadSchema.safeParse(payload);
10064
10064
  return parsed2.success ? [parsed2.data.image] : [];
10065
10065
  }
10066
10066
  const parsed = ImagesPayloadSchema.safeParse(payload);
10067
10067
  return parsed.success ? parsed.data.images : [];
10068
10068
  }
10069
- async function collectFalPlanImages(payload, plan3, ctx, req) {
10070
- const files = filesOf(payload, plan3);
10069
+ async function collectFalPlanImages(payload, plan4, ctx, req) {
10070
+ const files = filesOf(payload, plan4);
10071
10071
  if (files.length === 0) {
10072
- throw fail2(ctx.model.id, `fal ${plan3.endpoint} returned no image`, "provider_rejected");
10072
+ throw fail2(ctx.model.id, `fal ${plan4.endpoint} returned no image`, "provider_rejected");
10073
10073
  }
10074
10074
  const images = await Promise.all(
10075
10075
  files.map(async (file) => {
@@ -10084,18 +10084,18 @@ async function collectFalPlanImages(payload, plan3, ctx, req) {
10084
10084
  unit: "images",
10085
10085
  quantity: images.length
10086
10086
  };
10087
- const billedSize = plan3.imageSize ?? req.size;
10087
+ const billedSize = plan4.imageSize ?? req.size;
10088
10088
  if (billedSize !== void 0 && ctx.model.type === "image") usage3.imageSize = billedSize;
10089
- if (plan3.imageQuality !== void 0) usage3.imageQuality = plan3.imageQuality;
10089
+ if (plan4.imageQuality !== void 0) usage3.imageQuality = plan4.imageQuality;
10090
10090
  const result = { images, usage: usage3, raw: payload };
10091
10091
  const remote = files.find((f) => !f.url.startsWith("data:"));
10092
10092
  if (remote !== void 0) result.outputUrl = remote.url;
10093
10093
  return result;
10094
10094
  }
10095
10095
  async function generateFalFamilyImage(req, ctx, run) {
10096
- const plan3 = planFalImage(req, ctx.model.providerModelId, ctx.model.id);
10097
- const payload = await run(plan3.endpoint, plan3.input);
10098
- return collectFalPlanImages(payload, plan3, ctx, req);
10096
+ const plan4 = planFalImage(req, ctx.model.providerModelId, ctx.model.id);
10097
+ const payload = await run(plan4.endpoint, plan4.input);
10098
+ return collectFalPlanImages(payload, plan4, ctx, req);
10099
10099
  }
10100
10100
 
10101
10101
  // src/adapters/fal-mask.ts
@@ -11193,10 +11193,50 @@ var KLING_TIERS = [
11193
11193
  { mode: "pro", resolution: "1080p" },
11194
11194
  { mode: "4k", resolution: "4k" }
11195
11195
  ];
11196
+ var KLING_O3_OMNI = "fal-ai/kling-video/o3";
11196
11197
  function klingTier(req) {
11197
11198
  return KLING_TIERS.find((tier) => tier.resolution === req.resolution) ?? KLING_TIERS.find((tier) => tier.mode === req.mode) ?? KLING_TIERS[0];
11198
11199
  }
11199
11200
 
11201
+ // src/adapters/fal-kling-omni.ts
11202
+ function plan(req, ctx) {
11203
+ const tier = klingTier(req);
11204
+ const duration = wholeSeconds(req, ctx);
11205
+ const input = {
11206
+ prompt: req.prompt.trim(),
11207
+ duration: String(duration),
11208
+ generate_audio: req.generateAudio ?? true
11209
+ };
11210
+ const start = req.firstFrame ?? req.lastFrame;
11211
+ const end = req.firstFrame ? req.lastFrame : void 0;
11212
+ const images = urls(req.referenceImages);
11213
+ let task;
11214
+ if (images.length > 0) {
11215
+ task = "reference-to-video";
11216
+ input["image_urls"] = images;
11217
+ if (start) input["start_image_url"] = refToUrl(start);
11218
+ if (end) input["end_image_url"] = refToUrl(end);
11219
+ } else if (start) {
11220
+ task = "image-to-video";
11221
+ input["image_url"] = refToUrl(start);
11222
+ if (end) input["end_image_url"] = refToUrl(end);
11223
+ } else {
11224
+ task = "text-to-video";
11225
+ }
11226
+ const ratio = concreteRatio(req);
11227
+ if (ratio !== void 0 && start === void 0) input["aspect_ratio"] = ratio;
11228
+ return {
11229
+ endpoint: `${KLING_O3_OMNI}/${tier.mode}/${task}`,
11230
+ input,
11231
+ resolution: tier.resolution,
11232
+ seconds: requestedSeconds(duration)
11233
+ };
11234
+ }
11235
+ var klingOmniFamily = {
11236
+ ids: /* @__PURE__ */ new Set([KLING_O3_OMNI]),
11237
+ plan
11238
+ };
11239
+
11200
11240
  // src/resolve-video-rules.ts
11201
11241
  var MOTION_PRO2 = "fal-ai/kling-video/v3/pro/motion-control";
11202
11242
  var MOTION_STANDARD2 = "fal-ai/kling-video/v3/standard/motion-control";
@@ -11341,6 +11381,7 @@ var RULES = /* @__PURE__ */ new Map([
11341
11381
  [MOTION_PRO2, motionControl2],
11342
11382
  [MOTION_STANDARD2, motionControl2],
11343
11383
  [O3_REFERENCE2, o3Reference2],
11384
+ [KLING_O3_OMNI, o3Reference2],
11344
11385
  [O3_EDIT2, (req) => needsSource(req) ?? needsPrompt(req)],
11345
11386
  [H3_TURBO, h3Turbo],
11346
11387
  [MINIMAX_H3_INSERT, h3Insert],
@@ -11370,13 +11411,14 @@ function h3EndFrameRatioWarning(model, ratio) {
11370
11411
  message: `${model.id} follows the end frame's aspect ratio`
11371
11412
  };
11372
11413
  }
11373
- function isReplicateKling(model) {
11414
+ function takesKlingMode(model) {
11415
+ if (model.adapter === "fal") return model.providerModelId.toLowerCase() === KLING_O3_OMNI;
11374
11416
  if (model.adapter !== "replicate") return false;
11375
11417
  const kind = videoKind(model.providerModelId);
11376
11418
  return kind === "kling" || kind === "kling-omni";
11377
11419
  }
11378
- function fillReplicateKlingResolution(model, req) {
11379
- if (isReplicateKling(model) && req.resolution === void 0) {
11420
+ function fillKlingModeResolution(model, req) {
11421
+ if (takesKlingMode(model) && req.resolution === void 0) {
11380
11422
  req.resolution = klingTier(req).resolution;
11381
11423
  }
11382
11424
  }
@@ -11515,7 +11557,7 @@ var minimaxH3MaxFamily = {
11515
11557
 
11516
11558
  // src/adapters/fal-omnihuman.ts
11517
11559
  var OMNIHUMAN_V22 = "bytedance/omnihuman/v2";
11518
- function plan(req, ctx) {
11560
+ function plan2(req, ctx) {
11519
11561
  const [image] = req.referenceImages ?? [];
11520
11562
  const [audio] = req.referenceAudios ?? [];
11521
11563
  if (image === void 0 || audio === void 0) {
@@ -11526,14 +11568,14 @@ function plan(req, ctx) {
11526
11568
  return { endpoint: OMNIHUMAN_V22, input, seconds: inputLengthSeconds(req, audio) };
11527
11569
  }
11528
11570
  var OMNIHUMAN_MODEL_IDS = /* @__PURE__ */ new Set([OMNIHUMAN_V22]);
11529
- var omnihumanFamily = { ids: OMNIHUMAN_MODEL_IDS, plan };
11571
+ var omnihumanFamily = { ids: OMNIHUMAN_MODEL_IDS, plan: plan2 };
11530
11572
 
11531
11573
  // src/adapters/fal-vidu.ts
11532
11574
  var FAMILY2 = "fal-ai/vidu/q4";
11533
11575
  function viduTier(resolution) {
11534
11576
  return resolution === "2k" || resolution === "4k" ? upperTier(resolution) : resolution;
11535
11577
  }
11536
- function plan2(req, ctx) {
11578
+ function plan3(req, ctx) {
11537
11579
  const images = urls(req.referenceImages);
11538
11580
  const audios = urls(req.referenceAudios);
11539
11581
  const duration = wholeSeconds(req, ctx);
@@ -11560,11 +11602,12 @@ function plan2(req, ctx) {
11560
11602
  return { endpoint, input, resolution, seconds: requestedSeconds(duration) };
11561
11603
  }
11562
11604
  var VIDU_MODEL_IDS = /* @__PURE__ */ new Set([FAMILY2]);
11563
- var viduFamily = { ids: VIDU_MODEL_IDS, plan: plan2 };
11605
+ var viduFamily = { ids: VIDU_MODEL_IDS, plan: plan3 };
11564
11606
 
11565
11607
  // src/adapters/fal-video-families.ts
11566
11608
  var FAMILIES2 = [
11567
11609
  klingV3Family,
11610
+ klingOmniFamily,
11568
11611
  minimaxH3MaxFamily,
11569
11612
  happyHorseFamily,
11570
11613
  viduFamily,
@@ -12041,7 +12084,7 @@ function extractVideoUrl(result, endpoint, model) {
12041
12084
  }
12042
12085
  async function generateFalVideo(req, ctx, deps) {
12043
12086
  const providerModelId = ctx.model.providerModelId;
12044
- const plan3 = planFalFamilyVideo(req, ctx);
12087
+ const plan4 = planFalFamilyVideo(req, ctx);
12045
12088
  const start = (endpoint2, input, usageOf2) => startFalVideoJob(
12046
12089
  ctx,
12047
12090
  () => falClientOf(ctx, deps),
@@ -12049,7 +12092,7 @@ async function generateFalVideo(req, ctx, deps) {
12049
12092
  input,
12050
12093
  videoFileDecoder(ctx, req, endpoint2, usageOf2)
12051
12094
  );
12052
- if (plan3 !== void 0) return start(plan3.endpoint, plan3.input, planUsage(ctx, plan3));
12095
+ if (plan4 !== void 0) return start(plan4.endpoint, plan4.input, planUsage(ctx, plan4));
12053
12096
  if (isKling(providerModelId)) return start(KLING_O1_ENDPOINT, klingO1Input(req));
12054
12097
  if (isWan(providerModelId)) {
12055
12098
  const { endpoint: endpoint2, input } = wanVideo(req, providerModelId.toLowerCase());
@@ -12099,9 +12142,9 @@ function videoFileDecoder(ctx, req, endpoint, usageOf2) {
12099
12142
  raw: payload
12100
12143
  });
12101
12144
  }
12102
- function planUsage(ctx, plan3) {
12145
+ function planUsage(ctx, plan4) {
12103
12146
  return (payload) => {
12104
- const seconds3 = plan3.seconds(payload);
12147
+ const seconds3 = plan4.seconds(payload);
12105
12148
  return {
12106
12149
  model: ctx.model.id,
12107
12150
  provider: "fal",
@@ -12109,7 +12152,7 @@ function planUsage(ctx, plan3) {
12109
12152
  unit: "seconds",
12110
12153
  quantity: seconds3,
12111
12154
  durationSeconds: seconds3,
12112
- ...plan3.resolution !== void 0 && { resolution: plan3.resolution }
12155
+ ...plan4.resolution !== void 0 && { resolution: plan4.resolution }
12113
12156
  };
12114
12157
  };
12115
12158
  }
@@ -16563,10 +16606,10 @@ function resolveVideoOptions(model, request, onUnsupported = "error") {
16563
16606
  warnings
16564
16607
  );
16565
16608
  if (aspectRatio !== void 0) merged.aspectRatio = aspectRatio;
16566
- fillReplicateKlingResolution(model, merged);
16609
+ fillKlingModeResolution(model, merged);
16567
16610
  const resolution = resolveVideoResolution(merged.resolution, model, onUnsupported, warnings);
16568
16611
  if (resolution !== void 0) merged.resolution = resolution;
16569
- if (isReplicateKling(model)) delete merged.mode;
16612
+ if (takesKlingMode(model)) delete merged.mode;
16570
16613
  const duration = resolveDuration(
16571
16614
  merged.durationSeconds,
16572
16615
  c.durations,