@shop-os/modelkit 0.2.14 → 0.2.16

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
@@ -1362,7 +1362,8 @@ var VIDEO_MODELS = [
1362
1362
  // reference clip keeps its own framing.
1363
1363
  aspectRatios: [...OMNI_RATIOS],
1364
1364
  durations: [3, 4, 5, 6, 7, 8, 9, 10],
1365
- references: { images: 6, videos: 1 },
1365
+ references: { images: 6, videos: 1, videoSeconds: { max: 10 } },
1366
+ sourceVideoSeconds: { max: 10 },
1366
1367
  supports: []
1367
1368
  },
1368
1369
  defaults: {},
@@ -1388,8 +1389,16 @@ var VIDEO_MODELS = [
1388
1389
  aspectRatios: [...OMNI_RATIOS],
1389
1390
  resolutions: ["360p", "720p", "1080p", "4k"],
1390
1391
  durations: [3, 4, 5, 6, 7, 8, 9, 10],
1391
- references: { images: 6, videos: 1 },
1392
- supports: []
1392
+ references: { images: 6, videos: 1, videoSeconds: { max: 10 } },
1393
+ sourceVideoSeconds: { max: 10 },
1394
+ // Extension (probe 2026-09-24, 360p): each `taskType: "extend"` call
1395
+ // renders `durationSeconds` more and returns the FULL cumulative clip
1396
+ // (3 s -> 6 s -> 9 s); the provider caps the clip at 40 s. A first
1397
+ // extension can upload a <= 10 s source with task "extend"; later ones
1398
+ // chain by `previousInteractionId` (the API rejects the id together
1399
+ // with a video task, so those calls carry the prompt alone).
1400
+ supports: ["videoExtension"],
1401
+ extension: { segmentSeconds: 10, maxTotalSeconds: 40 }
1393
1402
  },
1394
1403
  defaults: {},
1395
1404
  usage: { ...VIDEO_USAGE },
@@ -1397,7 +1406,7 @@ var VIDEO_MODELS = [
1397
1406
  display: {
1398
1407
  provider: "google",
1399
1408
  logo: GOOGLE_LOGO2,
1400
- description: "Google Gemini Omni Flash 1.1 conversational video generation and editing; text, image, and up to 10-second video input, 3-10 second output at up to 4K and 24 FPS."
1409
+ description: "Google Gemini Omni Flash 1.1 conversational video generation, editing and extension; text, image, and up to 10-second video input, 3-10 second output at up to 4K and 24 FPS, extendable to 40 seconds."
1401
1410
  },
1402
1411
  capabilities: { acceptsSourceVideo: true }
1403
1412
  },
@@ -1416,7 +1425,14 @@ var VIDEO_MODELS = [
1416
1425
  resolutions: ["480p", "720p", "1080p", "4k"],
1417
1426
  durations: { min: 4, max: 15 },
1418
1427
  durationPresets: [4, 6, 8, 10, 12, 15],
1419
- references: { images: 9, videos: 3, audios: 3, audioOnly: false },
1428
+ references: {
1429
+ images: 9,
1430
+ videos: 3,
1431
+ audios: 3,
1432
+ audioOnly: false,
1433
+ videoSeconds: { min: 2, max: 15, total: 15 }
1434
+ },
1435
+ sourceVideoSeconds: { min: 2, max: 15, inReferenceTotal: true },
1420
1436
  ratioIgnoredWith: ["firstFrame", "sourceVideo"],
1421
1437
  supports: ["generateAudio", "seed", "lastFrame", "watermark"]
1422
1438
  },
@@ -1448,7 +1464,14 @@ var VIDEO_MODELS = [
1448
1464
  aspectRatios: [...SEEDANCE_RATIOS],
1449
1465
  resolutions: ["480p", "720p"],
1450
1466
  durations: { min: 4, max: 15 },
1451
- references: { images: 9, videos: 3, audios: 3, audioOnly: false },
1467
+ references: {
1468
+ images: 9,
1469
+ videos: 3,
1470
+ audios: 3,
1471
+ audioOnly: false,
1472
+ videoSeconds: { min: 2, max: 15, total: 15 }
1473
+ },
1474
+ sourceVideoSeconds: { min: 2, max: 15, inReferenceTotal: true },
1452
1475
  ratioIgnoredWith: ["firstFrame", "sourceVideo"],
1453
1476
  supports: ["generateAudio", "seed", "lastFrame", "watermark"]
1454
1477
  },
@@ -1482,7 +1505,13 @@ var VIDEO_MODELS = [
1482
1505
  aspectRatios: [...SEEDANCE_RATIOS],
1483
1506
  resolutions: ["480p", "720p", "1080p"],
1484
1507
  durations: { min: 4, max: 30 },
1485
- references: { images: 30, videos: 10, audios: 10 },
1508
+ references: {
1509
+ images: 30,
1510
+ videos: 10,
1511
+ audios: 10,
1512
+ videoSeconds: { min: 2, max: 30, total: 30, editMin: 4 }
1513
+ },
1514
+ sourceVideoSeconds: { min: 2, max: 30, editMin: 4, inReferenceTotal: true },
1486
1515
  ratioIgnoredWith: ["firstFrame", "sourceVideo"],
1487
1516
  supports: ["generateAudio", "seed", "lastFrame", "watermark", "taskType"]
1488
1517
  },
@@ -1694,7 +1723,14 @@ var VIDEO_MODELS = [
1694
1723
  aspectRatios: [...H3_REFERENCE_RATIOS],
1695
1724
  resolutions: ["480p", "768p", "2k", "4k"],
1696
1725
  durations: { min: 5, max: 15 },
1697
- references: { images: 9, videos: 3, audios: 3, total: 12, audioOnly: false },
1726
+ references: {
1727
+ images: 9,
1728
+ videos: 3,
1729
+ audios: 3,
1730
+ total: 12,
1731
+ audioOnly: false,
1732
+ videoSeconds: { min: 2, max: 15, total: 15 }
1733
+ },
1698
1734
  supports: ["seed", "promptExpansion", "safetyChecker"]
1699
1735
  },
1700
1736
  defaults: {
@@ -1725,7 +1761,14 @@ var VIDEO_MODELS = [
1725
1761
  aspectRatios: [...H3_REFERENCE_RATIOS],
1726
1762
  resolutions: ["480p", "768p"],
1727
1763
  durations: { min: 5, max: 15 },
1728
- references: { images: 9, videos: 3, audios: 3, total: 12, audioOnly: false },
1764
+ references: {
1765
+ images: 9,
1766
+ videos: 3,
1767
+ audios: 3,
1768
+ total: 12,
1769
+ audioOnly: false,
1770
+ videoSeconds: { min: 2, max: 15, total: 15 }
1771
+ },
1729
1772
  supports: ["seed", "promptExpansion", "safetyChecker"]
1730
1773
  },
1731
1774
  defaults: {
@@ -1757,6 +1800,7 @@ var VIDEO_MODELS = [
1757
1800
  aspectRatios: [...KLING_RATIOS],
1758
1801
  durations: { min: 3, max: 10 },
1759
1802
  requires: ["sourceVideo"],
1803
+ sourceVideoSeconds: { min: 3, max: 10.05 },
1760
1804
  supports: []
1761
1805
  },
1762
1806
  defaults: { durationSeconds: 5, aspectRatio: "16:9" },
@@ -2093,6 +2137,7 @@ var SupportedOptionSchema = z2.enum([
2093
2137
  "watermark",
2094
2138
  "safetyChecker",
2095
2139
  "taskType",
2140
+ "videoExtension",
2096
2141
  "instrumental"
2097
2142
  ]);
2098
2143
  var UsageUnitSchema = z2.enum([
@@ -2113,13 +2158,20 @@ var ProviderOptionValueSchema = z2.lazy(
2113
2158
  ])
2114
2159
  );
2115
2160
  var ProviderOptionsSchema = z2.record(z2.string(), z2.record(z2.string(), ProviderOptionValueSchema));
2161
+ var VideoSecondsLimitsSchema = z2.looseObject({
2162
+ min: z2.number().optional(),
2163
+ max: z2.number().optional(),
2164
+ total: z2.number().optional(),
2165
+ editMin: z2.number().optional()
2166
+ });
2116
2167
  var ReferenceLimitsSchema = z2.looseObject({
2117
2168
  images: z2.number().optional(),
2118
2169
  imagesWithVideo: z2.number().optional(),
2119
2170
  videos: z2.number().optional(),
2120
2171
  audios: z2.number().optional(),
2121
2172
  total: z2.number().optional(),
2122
- audioOnly: z2.boolean().optional()
2173
+ audioOnly: z2.boolean().optional(),
2174
+ videoSeconds: VideoSecondsLimitsSchema.optional()
2123
2175
  });
2124
2176
  var ModelConstraintsSchema = z2.looseObject({
2125
2177
  aspectRatios: z2.array(AspectRatioSchema).optional(),
@@ -2132,14 +2184,21 @@ var ModelConstraintsSchema = z2.looseObject({
2132
2184
  references: ReferenceLimitsSchema.optional(),
2133
2185
  requires: z2.array(RequiredInputSchema).optional(),
2134
2186
  supports: z2.array(SupportedOptionSchema).optional(),
2135
- ratioIgnoredWith: z2.array(z2.enum(["firstFrame", "sourceVideo"])).optional()
2187
+ ratioIgnoredWith: z2.array(z2.enum(["firstFrame", "sourceVideo"])).optional(),
2188
+ sourceVideoSeconds: VideoSecondsLimitsSchema.omit({ total: true }).extend({ inReferenceTotal: z2.boolean().optional() }).optional(),
2189
+ extension: z2.looseObject({ segmentSeconds: z2.number(), maxTotalSeconds: z2.number() }).optional()
2136
2190
  });
2137
2191
  var MediaRefSchema = z2.union([
2138
- z2.looseObject({ url: z2.string(), label: z2.string().optional() }),
2192
+ z2.looseObject({
2193
+ url: z2.string(),
2194
+ label: z2.string().optional(),
2195
+ durationSeconds: z2.number().optional()
2196
+ }),
2139
2197
  z2.looseObject({
2140
2198
  bytes: z2.instanceof(Uint8Array),
2141
2199
  mime: z2.string(),
2142
- label: z2.string().optional()
2200
+ label: z2.string().optional(),
2201
+ durationSeconds: z2.number().optional()
2143
2202
  })
2144
2203
  ]);
2145
2204
  var ImageSafetySettingSchema = z2.looseObject({ category: z2.string(), threshold: z2.string() });
@@ -2628,6 +2687,49 @@ function trim(field, refs, limit, model, warnings) {
2628
2687
  });
2629
2688
  return refs.slice(0, limit);
2630
2689
  }
2690
+ function knownLength(value) {
2691
+ return value !== void 0 && Number.isFinite(value) ? value : void 0;
2692
+ }
2693
+ function seconds(len, limit) {
2694
+ let digits = 1;
2695
+ while (digits < 3 && Number(len.toFixed(digits)) === limit) digits++;
2696
+ return len.toFixed(digits);
2697
+ }
2698
+ function effectiveMin(limits, taskType) {
2699
+ if (taskType !== "edit" || limits?.editMin === void 0) return limits?.min;
2700
+ return Math.max(limits.min ?? 0, limits.editMin);
2701
+ }
2702
+ function videoLengthViolation(model, input) {
2703
+ const limits = model.constraints.references?.videoSeconds;
2704
+ const refMin = effectiveMin(limits, input.taskType);
2705
+ const lengths = (input.referenceVideos ?? []).map(knownLength);
2706
+ if (limits?.max !== void 0) {
2707
+ const max = limits.max;
2708
+ const i = lengths.findIndex((len) => len !== void 0 && len > max);
2709
+ if (i >= 0)
2710
+ return `${model.label} takes reference videos up to ${String(max)} s each; video ${i + 1} is ${seconds(lengths[i], max)} s.`;
2711
+ }
2712
+ if (refMin !== void 0) {
2713
+ const i = lengths.findIndex((len) => len !== void 0 && len < refMin);
2714
+ if (i >= 0)
2715
+ return `${model.label} takes reference videos of at least ${String(refMin)} s each; video ${i + 1} is ${seconds(lengths[i], refMin)} s.`;
2716
+ }
2717
+ const source = knownLength(input.sourceVideo);
2718
+ const sourceLimits = model.constraints.sourceVideoSeconds;
2719
+ if (limits?.total !== void 0) {
2720
+ const refSum = lengths.reduce((acc, len) => acc + (len ?? 0), 0);
2721
+ const sum = refSum + (sourceLimits?.inReferenceTotal ? source ?? 0 : 0);
2722
+ if (sum > limits.total)
2723
+ return `${model.label} takes reference videos up to ${String(limits.total)} s combined; these add up to ${seconds(sum, limits.total)} s.`;
2724
+ }
2725
+ if (source === void 0) return void 0;
2726
+ const sourceMin = effectiveMin(sourceLimits, input.taskType);
2727
+ if (sourceLimits?.max !== void 0 && source > sourceLimits.max)
2728
+ return `${model.label} takes a source video up to ${String(sourceLimits.max)} s; this one is ${seconds(source, sourceLimits.max)} s.`;
2729
+ if (sourceMin !== void 0 && source < sourceMin)
2730
+ return `${model.label} takes a source video of at least ${String(sourceMin)} s; this one is ${seconds(source, sourceMin)} s.`;
2731
+ return void 0;
2732
+ }
2631
2733
  function resolveImageOptions(model, request, onUnsupported = "error") {
2632
2734
  const warnings = [];
2633
2735
  const c = model.constraints;
@@ -2813,9 +2915,25 @@ function resolveVideoOptions(model, request, onUnsupported = "error") {
2813
2915
  model: model.id
2814
2916
  });
2815
2917
  }
2918
+ const lengthViolation = videoLengthViolation(model, {
2919
+ referenceVideos: videos.map((v) => v.durationSeconds),
2920
+ taskType: merged.taskType,
2921
+ ...merged.sourceVideo?.durationSeconds !== void 0 && {
2922
+ sourceVideo: merged.sourceVideo.durationSeconds
2923
+ }
2924
+ });
2925
+ if (lengthViolation !== void 0) {
2926
+ throw new ModelKitError({
2927
+ code: "unsupported_option",
2928
+ message: lengthViolation,
2929
+ model: model.id,
2930
+ retryable: false
2931
+ });
2932
+ }
2816
2933
  setOrDelete(merged, "referenceImages", images);
2817
2934
  setOrDelete(merged, "referenceVideos", videos);
2818
2935
  setOrDelete(merged, "referenceAudios", audios);
2936
+ const keepExtend = merged.taskType === "extend" && (model.constraints.supports ?? []).includes("videoExtension");
2819
2937
  dropUnsupported(merged, model, warnings, [
2820
2938
  "seed",
2821
2939
  "negativePrompt",
@@ -2825,8 +2943,17 @@ function resolveVideoOptions(model, request, onUnsupported = "error") {
2825
2943
  "lastFrame",
2826
2944
  "watermark",
2827
2945
  "safetyChecker",
2828
- "taskType"
2946
+ ...keepExtend ? [] : ["taskType"]
2829
2947
  ]);
2948
+ if (merged.previousInteractionId !== void 0 && !keepExtend) {
2949
+ warnings.push({
2950
+ code: "option_ignored",
2951
+ field: "previousInteractionId",
2952
+ from: merged.previousInteractionId,
2953
+ message: `${model.id} does not support previousInteractionId; ignored`
2954
+ });
2955
+ delete merged.previousInteractionId;
2956
+ }
2830
2957
  return { request: merged, warnings };
2831
2958
  }
2832
2959
  function resolveAudioOptions(model, request, onUnsupported = "error") {
@@ -2928,6 +3055,7 @@ export {
2928
3055
  resolveImageOptions,
2929
3056
  resolveOptions,
2930
3057
  resolveVideoOptions,
2931
- sortCatalogRows
3058
+ sortCatalogRows,
3059
+ videoLengthViolation
2932
3060
  };
2933
3061
  //# sourceMappingURL=catalog.js.map