@shop-os/modelkit 0.2.14 → 0.2.15

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.cjs CHANGED
@@ -104,6 +104,7 @@ __export(index_exports, {
104
104
  textUsageEvent: () => textUsageEvent,
105
105
  toGeneratedImage: () => toGeneratedImage,
106
106
  validateInputSpec: () => validateInputSpec,
107
+ videoLengthViolation: () => videoLengthViolation,
107
108
  withRetry: () => withRetry,
108
109
  xaiVideoAdapter: () => xaiVideoAdapter
109
110
  });
@@ -1482,7 +1483,8 @@ var VIDEO_MODELS = [
1482
1483
  // reference clip keeps its own framing.
1483
1484
  aspectRatios: [...OMNI_RATIOS],
1484
1485
  durations: [3, 4, 5, 6, 7, 8, 9, 10],
1485
- references: { images: 6, videos: 1 },
1486
+ references: { images: 6, videos: 1, videoSeconds: { max: 10 } },
1487
+ sourceVideoSeconds: { max: 10 },
1486
1488
  supports: []
1487
1489
  },
1488
1490
  defaults: {},
@@ -1508,7 +1510,8 @@ var VIDEO_MODELS = [
1508
1510
  aspectRatios: [...OMNI_RATIOS],
1509
1511
  resolutions: ["360p", "720p", "1080p", "4k"],
1510
1512
  durations: [3, 4, 5, 6, 7, 8, 9, 10],
1511
- references: { images: 6, videos: 1 },
1513
+ references: { images: 6, videos: 1, videoSeconds: { max: 10 } },
1514
+ sourceVideoSeconds: { max: 10 },
1512
1515
  supports: []
1513
1516
  },
1514
1517
  defaults: {},
@@ -1536,7 +1539,14 @@ var VIDEO_MODELS = [
1536
1539
  resolutions: ["480p", "720p", "1080p", "4k"],
1537
1540
  durations: { min: 4, max: 15 },
1538
1541
  durationPresets: [4, 6, 8, 10, 12, 15],
1539
- references: { images: 9, videos: 3, audios: 3, audioOnly: false },
1542
+ references: {
1543
+ images: 9,
1544
+ videos: 3,
1545
+ audios: 3,
1546
+ audioOnly: false,
1547
+ videoSeconds: { min: 2, max: 15, total: 15 }
1548
+ },
1549
+ sourceVideoSeconds: { min: 2, max: 15, inReferenceTotal: true },
1540
1550
  ratioIgnoredWith: ["firstFrame", "sourceVideo"],
1541
1551
  supports: ["generateAudio", "seed", "lastFrame", "watermark"]
1542
1552
  },
@@ -1568,7 +1578,14 @@ var VIDEO_MODELS = [
1568
1578
  aspectRatios: [...SEEDANCE_RATIOS],
1569
1579
  resolutions: ["480p", "720p"],
1570
1580
  durations: { min: 4, max: 15 },
1571
- references: { images: 9, videos: 3, audios: 3, audioOnly: false },
1581
+ references: {
1582
+ images: 9,
1583
+ videos: 3,
1584
+ audios: 3,
1585
+ audioOnly: false,
1586
+ videoSeconds: { min: 2, max: 15, total: 15 }
1587
+ },
1588
+ sourceVideoSeconds: { min: 2, max: 15, inReferenceTotal: true },
1572
1589
  ratioIgnoredWith: ["firstFrame", "sourceVideo"],
1573
1590
  supports: ["generateAudio", "seed", "lastFrame", "watermark"]
1574
1591
  },
@@ -1602,7 +1619,13 @@ var VIDEO_MODELS = [
1602
1619
  aspectRatios: [...SEEDANCE_RATIOS],
1603
1620
  resolutions: ["480p", "720p", "1080p"],
1604
1621
  durations: { min: 4, max: 30 },
1605
- references: { images: 30, videos: 10, audios: 10 },
1622
+ references: {
1623
+ images: 30,
1624
+ videos: 10,
1625
+ audios: 10,
1626
+ videoSeconds: { min: 2, max: 30, total: 30, editMin: 4 }
1627
+ },
1628
+ sourceVideoSeconds: { min: 2, max: 30, editMin: 4, inReferenceTotal: true },
1606
1629
  ratioIgnoredWith: ["firstFrame", "sourceVideo"],
1607
1630
  supports: ["generateAudio", "seed", "lastFrame", "watermark", "taskType"]
1608
1631
  },
@@ -1814,7 +1837,14 @@ var VIDEO_MODELS = [
1814
1837
  aspectRatios: [...H3_REFERENCE_RATIOS],
1815
1838
  resolutions: ["480p", "768p", "2k", "4k"],
1816
1839
  durations: { min: 5, max: 15 },
1817
- references: { images: 9, videos: 3, audios: 3, total: 12, audioOnly: false },
1840
+ references: {
1841
+ images: 9,
1842
+ videos: 3,
1843
+ audios: 3,
1844
+ total: 12,
1845
+ audioOnly: false,
1846
+ videoSeconds: { min: 2, max: 15, total: 15 }
1847
+ },
1818
1848
  supports: ["seed", "promptExpansion", "safetyChecker"]
1819
1849
  },
1820
1850
  defaults: {
@@ -1845,7 +1875,14 @@ var VIDEO_MODELS = [
1845
1875
  aspectRatios: [...H3_REFERENCE_RATIOS],
1846
1876
  resolutions: ["480p", "768p"],
1847
1877
  durations: { min: 5, max: 15 },
1848
- references: { images: 9, videos: 3, audios: 3, total: 12, audioOnly: false },
1878
+ references: {
1879
+ images: 9,
1880
+ videos: 3,
1881
+ audios: 3,
1882
+ total: 12,
1883
+ audioOnly: false,
1884
+ videoSeconds: { min: 2, max: 15, total: 15 }
1885
+ },
1849
1886
  supports: ["seed", "promptExpansion", "safetyChecker"]
1850
1887
  },
1851
1888
  defaults: {
@@ -1877,6 +1914,7 @@ var VIDEO_MODELS = [
1877
1914
  aspectRatios: [...KLING_RATIOS],
1878
1915
  durations: { min: 3, max: 10 },
1879
1916
  requires: ["sourceVideo"],
1917
+ sourceVideoSeconds: { min: 3, max: 10.05 },
1880
1918
  supports: []
1881
1919
  },
1882
1920
  defaults: { durationSeconds: 5, aspectRatio: "16:9" },
@@ -2236,13 +2274,20 @@ var ProviderOptionValueSchema = import_zod2.z.lazy(
2236
2274
  ])
2237
2275
  );
2238
2276
  var ProviderOptionsSchema = import_zod2.z.record(import_zod2.z.string(), import_zod2.z.record(import_zod2.z.string(), ProviderOptionValueSchema));
2277
+ var VideoSecondsLimitsSchema = import_zod2.z.looseObject({
2278
+ min: import_zod2.z.number().optional(),
2279
+ max: import_zod2.z.number().optional(),
2280
+ total: import_zod2.z.number().optional(),
2281
+ editMin: import_zod2.z.number().optional()
2282
+ });
2239
2283
  var ReferenceLimitsSchema = import_zod2.z.looseObject({
2240
2284
  images: import_zod2.z.number().optional(),
2241
2285
  imagesWithVideo: import_zod2.z.number().optional(),
2242
2286
  videos: import_zod2.z.number().optional(),
2243
2287
  audios: import_zod2.z.number().optional(),
2244
2288
  total: import_zod2.z.number().optional(),
2245
- audioOnly: import_zod2.z.boolean().optional()
2289
+ audioOnly: import_zod2.z.boolean().optional(),
2290
+ videoSeconds: VideoSecondsLimitsSchema.optional()
2246
2291
  });
2247
2292
  var ModelConstraintsSchema = import_zod2.z.looseObject({
2248
2293
  aspectRatios: import_zod2.z.array(AspectRatioSchema).optional(),
@@ -2255,14 +2300,20 @@ var ModelConstraintsSchema = import_zod2.z.looseObject({
2255
2300
  references: ReferenceLimitsSchema.optional(),
2256
2301
  requires: import_zod2.z.array(RequiredInputSchema).optional(),
2257
2302
  supports: import_zod2.z.array(SupportedOptionSchema).optional(),
2258
- ratioIgnoredWith: import_zod2.z.array(import_zod2.z.enum(["firstFrame", "sourceVideo"])).optional()
2303
+ ratioIgnoredWith: import_zod2.z.array(import_zod2.z.enum(["firstFrame", "sourceVideo"])).optional(),
2304
+ sourceVideoSeconds: VideoSecondsLimitsSchema.omit({ total: true }).extend({ inReferenceTotal: import_zod2.z.boolean().optional() }).optional()
2259
2305
  });
2260
2306
  var MediaRefSchema = import_zod2.z.union([
2261
- import_zod2.z.looseObject({ url: import_zod2.z.string(), label: import_zod2.z.string().optional() }),
2307
+ import_zod2.z.looseObject({
2308
+ url: import_zod2.z.string(),
2309
+ label: import_zod2.z.string().optional(),
2310
+ durationSeconds: import_zod2.z.number().optional()
2311
+ }),
2262
2312
  import_zod2.z.looseObject({
2263
2313
  bytes: import_zod2.z.instanceof(Uint8Array),
2264
2314
  mime: import_zod2.z.string(),
2265
- label: import_zod2.z.string().optional()
2315
+ label: import_zod2.z.string().optional(),
2316
+ durationSeconds: import_zod2.z.number().optional()
2266
2317
  })
2267
2318
  ]);
2268
2319
  var ImageSafetySettingSchema = import_zod2.z.looseObject({ category: import_zod2.z.string(), threshold: import_zod2.z.string() });
@@ -6647,8 +6698,8 @@ function lyriaAudioInput(req, ctx) {
6647
6698
  if (negative) input.negative_prompt = negative;
6648
6699
  return input;
6649
6700
  }
6650
- function elevenLabsMusicDuration(seconds) {
6651
- return Math.min(300, Math.max(5, seconds ?? 15));
6701
+ function elevenLabsMusicDuration(seconds2) {
6702
+ return Math.min(300, Math.max(5, seconds2 ?? 15));
6652
6703
  }
6653
6704
  function elevenLabsMusicInput(req, ctx) {
6654
6705
  const prompt = req.prompt.trim();
@@ -6713,9 +6764,9 @@ async function generateReplicateAudio(req, ctx, deps) {
6713
6764
  const { url, predictTime, raw } = await runPrediction(ctx, input, deps);
6714
6765
  const usage2 = audioUsage(ctx, req);
6715
6766
  if (ctx.model.usage.unit === "seconds") {
6716
- const seconds = elevenLabsMusicDuration(req.durationSeconds);
6717
- usage2.quantity = seconds;
6718
- usage2.durationSeconds = seconds;
6767
+ const seconds2 = elevenLabsMusicDuration(req.durationSeconds);
6768
+ usage2.quantity = seconds2;
6769
+ usage2.durationSeconds = seconds2;
6719
6770
  } else {
6720
6771
  usage2.quantity = predictTime;
6721
6772
  }
@@ -7355,6 +7406,49 @@ function trim(field, refs, limit, model, warnings) {
7355
7406
  });
7356
7407
  return refs.slice(0, limit);
7357
7408
  }
7409
+ function knownLength(value) {
7410
+ return value !== void 0 && Number.isFinite(value) ? value : void 0;
7411
+ }
7412
+ function seconds(len, limit) {
7413
+ let digits = 1;
7414
+ while (digits < 3 && Number(len.toFixed(digits)) === limit) digits++;
7415
+ return len.toFixed(digits);
7416
+ }
7417
+ function effectiveMin(limits, taskType) {
7418
+ if (taskType !== "edit" || limits?.editMin === void 0) return limits?.min;
7419
+ return Math.max(limits.min ?? 0, limits.editMin);
7420
+ }
7421
+ function videoLengthViolation(model, input) {
7422
+ const limits = model.constraints.references?.videoSeconds;
7423
+ const refMin = effectiveMin(limits, input.taskType);
7424
+ const lengths = (input.referenceVideos ?? []).map(knownLength);
7425
+ if (limits?.max !== void 0) {
7426
+ const max = limits.max;
7427
+ const i = lengths.findIndex((len) => len !== void 0 && len > max);
7428
+ if (i >= 0)
7429
+ return `${model.label} takes reference videos up to ${String(max)} s each; video ${i + 1} is ${seconds(lengths[i], max)} s.`;
7430
+ }
7431
+ if (refMin !== void 0) {
7432
+ const i = lengths.findIndex((len) => len !== void 0 && len < refMin);
7433
+ if (i >= 0)
7434
+ return `${model.label} takes reference videos of at least ${String(refMin)} s each; video ${i + 1} is ${seconds(lengths[i], refMin)} s.`;
7435
+ }
7436
+ const source = knownLength(input.sourceVideo);
7437
+ const sourceLimits = model.constraints.sourceVideoSeconds;
7438
+ if (limits?.total !== void 0) {
7439
+ const refSum = lengths.reduce((acc, len) => acc + (len ?? 0), 0);
7440
+ const sum = refSum + (sourceLimits?.inReferenceTotal ? source ?? 0 : 0);
7441
+ if (sum > limits.total)
7442
+ return `${model.label} takes reference videos up to ${String(limits.total)} s combined; these add up to ${seconds(sum, limits.total)} s.`;
7443
+ }
7444
+ if (source === void 0) return void 0;
7445
+ const sourceMin = effectiveMin(sourceLimits, input.taskType);
7446
+ if (sourceLimits?.max !== void 0 && source > sourceLimits.max)
7447
+ return `${model.label} takes a source video up to ${String(sourceLimits.max)} s; this one is ${seconds(source, sourceLimits.max)} s.`;
7448
+ if (sourceMin !== void 0 && source < sourceMin)
7449
+ return `${model.label} takes a source video of at least ${String(sourceMin)} s; this one is ${seconds(source, sourceMin)} s.`;
7450
+ return void 0;
7451
+ }
7358
7452
  function resolveImageOptions(model, request, onUnsupported = "error") {
7359
7453
  const warnings = [];
7360
7454
  const c = model.constraints;
@@ -7540,6 +7634,21 @@ function resolveVideoOptions(model, request, onUnsupported = "error") {
7540
7634
  model: model.id
7541
7635
  });
7542
7636
  }
7637
+ const lengthViolation = videoLengthViolation(model, {
7638
+ referenceVideos: videos.map((v) => v.durationSeconds),
7639
+ taskType: merged.taskType,
7640
+ ...merged.sourceVideo?.durationSeconds !== void 0 && {
7641
+ sourceVideo: merged.sourceVideo.durationSeconds
7642
+ }
7643
+ });
7644
+ if (lengthViolation !== void 0) {
7645
+ throw new ModelKitError({
7646
+ code: "unsupported_option",
7647
+ message: lengthViolation,
7648
+ model: model.id,
7649
+ retryable: false
7650
+ });
7651
+ }
7543
7652
  setOrDelete(merged, "referenceImages", images);
7544
7653
  setOrDelete(merged, "referenceVideos", videos);
7545
7654
  setOrDelete(merged, "referenceAudios", audios);
@@ -8090,7 +8199,7 @@ function createModelKit(config, adapters) {
8090
8199
  promptExpansion: _promptExpansion,
8091
8200
  mode: _mode
8092
8201
  } = req;
8093
- const seconds = duration ?? durationSeconds;
8202
+ const seconds2 = duration ?? durationSeconds;
8094
8203
  const abortSignal = combineSignals(req.abortSignal, call.signal);
8095
8204
  const options = { model, prompt };
8096
8205
  if (call.maxRetries !== void 0) options.maxRetries = call.maxRetries;
@@ -8099,7 +8208,7 @@ function createModelKit(config, adapters) {
8099
8208
  if (ratio) options.aspectRatio = ratio;
8100
8209
  else if (aspectRatio !== void 0)
8101
8210
  pushIgnored(warnings, "aspectRatio", aspectRatio, model.modelId);
8102
- if (seconds !== void 0) options.duration = seconds;
8211
+ if (seconds2 !== void 0) options.duration = seconds2;
8103
8212
  if (seed !== void 0) options.seed = seed;
8104
8213
  if (generateAudio2 !== void 0) options.generateAudio = generateAudio2;
8105
8214
  const frames = [
@@ -8146,8 +8255,8 @@ function createModelKit(config, adapters) {
8146
8255
  provider: model.provider,
8147
8256
  modality: "VIDEO",
8148
8257
  unit: "seconds",
8149
- quantity: seconds ?? 0,
8150
- ...seconds !== void 0 && { durationSeconds: seconds }
8258
+ quantity: seconds2 ?? 0,
8259
+ ...seconds2 !== void 0 && { durationSeconds: seconds2 }
8151
8260
  };
8152
8261
  settled = {
8153
8262
  video: { bytes: result.video.uint8Array, mime: result.video.mediaType },
@@ -8498,6 +8607,7 @@ var describe = (modelId) => createDefaultModelKit().describe(modelId);
8498
8607
  textUsageEvent,
8499
8608
  toGeneratedImage,
8500
8609
  validateInputSpec,
8610
+ videoLengthViolation,
8501
8611
  withRetry,
8502
8612
  xaiVideoAdapter,
8503
8613
  ...require("ai")