@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/CHANGELOG.md +18 -0
- package/dist/catalog.cjs +143 -15
- package/dist/catalog.cjs.map +1 -1
- package/dist/catalog.d.cts +79 -3
- package/dist/catalog.d.ts +79 -3
- package/dist/catalog.js +143 -15
- package/dist/catalog.js.map +1 -1
- package/dist/index.cjs +203 -41
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +79 -3
- package/dist/index.d.ts +79 -3
- package/dist/index.js +202 -41
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -9,6 +9,24 @@ header in the release PR.
|
|
|
9
9
|
|
|
10
10
|
## [Unreleased]
|
|
11
11
|
|
|
12
|
+
## [0.2.16] - Unreleased
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
- Gemini Omni 1.1 Flash video extension. The row declares `supports: ["videoExtension"]` and `constraints.extension: { segmentSeconds: 10, maxTotalSeconds: 40 }`. A `taskType: "extend"` request continues the clip by `durationSeconds` and the result is the **full cumulative clip** (probe 2026-09-24). The first extension may upload a source video (≤ 10 s, `sourceVideo`); follow-ups chain with `VideoRequest.previousInteractionId`, taken from the previous result's new `VideoResult.providerRef.interactionId`. The Interactions API rejects `previous_interaction_id` together with a video task, so chained calls carry only the prompt (no `generation_config`) and no aspect ratio.
|
|
16
|
+
- `SupportedOption` / catalog `supports` gain `"videoExtension"`; `ModelConstraints.extension` is typed and validated.
|
|
17
|
+
- A chained extension (`previousInteractionId` set) sends the prompt alone: `referenceImages`, `referenceVideos` and `firstFrame` are dropped with an `option_ignored` warning each, since the API rejects the id next to a video task.
|
|
18
|
+
- `resolveVideoOptions` keeps `taskType: "extend"` on a `videoExtension` row (it is otherwise dropped as unsupported) and drops `previousInteractionId` with an `option_ignored` warning on rows without the capability.
|
|
19
|
+
|
|
20
|
+
## [0.2.15] - Unreleased
|
|
21
|
+
|
|
22
|
+
### Added
|
|
23
|
+
- `MediaRef.durationSeconds`: the measured length of a video or audio ref. The kit never measures it; callers pass it when known.
|
|
24
|
+
- `ReferenceLimits.videoSeconds` (`VideoSecondsLimits`: `min`, `max`, `total`, `editMin`): per-video and combined length limits for reference videos. `editMin` raises the per-video minimum when `taskType` is `edit` (Seedance 2.5: 4 s). Rows without it accept any length.
|
|
25
|
+
- `ModelConstraints.sourceVideoSeconds` (`min`, `max`, `editMin`, `inReferenceTotal`): length limits for the source video. `inReferenceTotal` counts the source toward the combined reference limit where the provider sends it as a reference video (Seedance).
|
|
26
|
+
- `videoLengthViolation(model, input)`: pure checker that returns the first length violation as a user-facing message, else `undefined`. Unknown lengths are skipped. Exported from the root and `/catalog` entries.
|
|
27
|
+
- `resolveVideoOptions` rejects a reference or source video outside the row limits with a non-retryable `unsupported_option` error before any provider call. Videos dropped by the reference caps do not count.
|
|
28
|
+
- Snapshot rows carry the provider limits: MiniMax H3 and H3 Max reference (2-15 s each, 15 s combined), Seedance 2.0 and 2.0 Fast (2-15 s each, 15 s combined), Seedance 2.5 (2-30 s each, 30 s combined, 4 s minimum for edit), Gemini Omni 1.0 and 1.1 (10 s), Kling O1 v2v source video (3-10.05 s).
|
|
29
|
+
|
|
12
30
|
## [0.2.14] - Unreleased
|
|
13
31
|
|
|
14
32
|
- Keep AI SDK 6 and its compatible provider packages, including Bedrock and usage tracking.
|
package/dist/catalog.cjs
CHANGED
|
@@ -48,7 +48,8 @@ __export(catalog_entry_exports, {
|
|
|
48
48
|
resolveImageOptions: () => resolveImageOptions,
|
|
49
49
|
resolveOptions: () => resolveOptions,
|
|
50
50
|
resolveVideoOptions: () => resolveVideoOptions,
|
|
51
|
-
sortCatalogRows: () => sortCatalogRows
|
|
51
|
+
sortCatalogRows: () => sortCatalogRows,
|
|
52
|
+
videoLengthViolation: () => videoLengthViolation
|
|
52
53
|
});
|
|
53
54
|
module.exports = __toCommonJS(catalog_entry_exports);
|
|
54
55
|
|
|
@@ -1416,7 +1417,8 @@ var VIDEO_MODELS = [
|
|
|
1416
1417
|
// reference clip keeps its own framing.
|
|
1417
1418
|
aspectRatios: [...OMNI_RATIOS],
|
|
1418
1419
|
durations: [3, 4, 5, 6, 7, 8, 9, 10],
|
|
1419
|
-
references: { images: 6, videos: 1 },
|
|
1420
|
+
references: { images: 6, videos: 1, videoSeconds: { max: 10 } },
|
|
1421
|
+
sourceVideoSeconds: { max: 10 },
|
|
1420
1422
|
supports: []
|
|
1421
1423
|
},
|
|
1422
1424
|
defaults: {},
|
|
@@ -1442,8 +1444,16 @@ var VIDEO_MODELS = [
|
|
|
1442
1444
|
aspectRatios: [...OMNI_RATIOS],
|
|
1443
1445
|
resolutions: ["360p", "720p", "1080p", "4k"],
|
|
1444
1446
|
durations: [3, 4, 5, 6, 7, 8, 9, 10],
|
|
1445
|
-
references: { images: 6, videos: 1 },
|
|
1446
|
-
|
|
1447
|
+
references: { images: 6, videos: 1, videoSeconds: { max: 10 } },
|
|
1448
|
+
sourceVideoSeconds: { max: 10 },
|
|
1449
|
+
// Extension (probe 2026-09-24, 360p): each `taskType: "extend"` call
|
|
1450
|
+
// renders `durationSeconds` more and returns the FULL cumulative clip
|
|
1451
|
+
// (3 s -> 6 s -> 9 s); the provider caps the clip at 40 s. A first
|
|
1452
|
+
// extension can upload a <= 10 s source with task "extend"; later ones
|
|
1453
|
+
// chain by `previousInteractionId` (the API rejects the id together
|
|
1454
|
+
// with a video task, so those calls carry the prompt alone).
|
|
1455
|
+
supports: ["videoExtension"],
|
|
1456
|
+
extension: { segmentSeconds: 10, maxTotalSeconds: 40 }
|
|
1447
1457
|
},
|
|
1448
1458
|
defaults: {},
|
|
1449
1459
|
usage: { ...VIDEO_USAGE },
|
|
@@ -1451,7 +1461,7 @@ var VIDEO_MODELS = [
|
|
|
1451
1461
|
display: {
|
|
1452
1462
|
provider: "google",
|
|
1453
1463
|
logo: GOOGLE_LOGO2,
|
|
1454
|
-
description: "Google Gemini Omni Flash 1.1 conversational video generation and
|
|
1464
|
+
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."
|
|
1455
1465
|
},
|
|
1456
1466
|
capabilities: { acceptsSourceVideo: true }
|
|
1457
1467
|
},
|
|
@@ -1470,7 +1480,14 @@ var VIDEO_MODELS = [
|
|
|
1470
1480
|
resolutions: ["480p", "720p", "1080p", "4k"],
|
|
1471
1481
|
durations: { min: 4, max: 15 },
|
|
1472
1482
|
durationPresets: [4, 6, 8, 10, 12, 15],
|
|
1473
|
-
references: {
|
|
1483
|
+
references: {
|
|
1484
|
+
images: 9,
|
|
1485
|
+
videos: 3,
|
|
1486
|
+
audios: 3,
|
|
1487
|
+
audioOnly: false,
|
|
1488
|
+
videoSeconds: { min: 2, max: 15, total: 15 }
|
|
1489
|
+
},
|
|
1490
|
+
sourceVideoSeconds: { min: 2, max: 15, inReferenceTotal: true },
|
|
1474
1491
|
ratioIgnoredWith: ["firstFrame", "sourceVideo"],
|
|
1475
1492
|
supports: ["generateAudio", "seed", "lastFrame", "watermark"]
|
|
1476
1493
|
},
|
|
@@ -1502,7 +1519,14 @@ var VIDEO_MODELS = [
|
|
|
1502
1519
|
aspectRatios: [...SEEDANCE_RATIOS],
|
|
1503
1520
|
resolutions: ["480p", "720p"],
|
|
1504
1521
|
durations: { min: 4, max: 15 },
|
|
1505
|
-
references: {
|
|
1522
|
+
references: {
|
|
1523
|
+
images: 9,
|
|
1524
|
+
videos: 3,
|
|
1525
|
+
audios: 3,
|
|
1526
|
+
audioOnly: false,
|
|
1527
|
+
videoSeconds: { min: 2, max: 15, total: 15 }
|
|
1528
|
+
},
|
|
1529
|
+
sourceVideoSeconds: { min: 2, max: 15, inReferenceTotal: true },
|
|
1506
1530
|
ratioIgnoredWith: ["firstFrame", "sourceVideo"],
|
|
1507
1531
|
supports: ["generateAudio", "seed", "lastFrame", "watermark"]
|
|
1508
1532
|
},
|
|
@@ -1536,7 +1560,13 @@ var VIDEO_MODELS = [
|
|
|
1536
1560
|
aspectRatios: [...SEEDANCE_RATIOS],
|
|
1537
1561
|
resolutions: ["480p", "720p", "1080p"],
|
|
1538
1562
|
durations: { min: 4, max: 30 },
|
|
1539
|
-
references: {
|
|
1563
|
+
references: {
|
|
1564
|
+
images: 30,
|
|
1565
|
+
videos: 10,
|
|
1566
|
+
audios: 10,
|
|
1567
|
+
videoSeconds: { min: 2, max: 30, total: 30, editMin: 4 }
|
|
1568
|
+
},
|
|
1569
|
+
sourceVideoSeconds: { min: 2, max: 30, editMin: 4, inReferenceTotal: true },
|
|
1540
1570
|
ratioIgnoredWith: ["firstFrame", "sourceVideo"],
|
|
1541
1571
|
supports: ["generateAudio", "seed", "lastFrame", "watermark", "taskType"]
|
|
1542
1572
|
},
|
|
@@ -1748,7 +1778,14 @@ var VIDEO_MODELS = [
|
|
|
1748
1778
|
aspectRatios: [...H3_REFERENCE_RATIOS],
|
|
1749
1779
|
resolutions: ["480p", "768p", "2k", "4k"],
|
|
1750
1780
|
durations: { min: 5, max: 15 },
|
|
1751
|
-
references: {
|
|
1781
|
+
references: {
|
|
1782
|
+
images: 9,
|
|
1783
|
+
videos: 3,
|
|
1784
|
+
audios: 3,
|
|
1785
|
+
total: 12,
|
|
1786
|
+
audioOnly: false,
|
|
1787
|
+
videoSeconds: { min: 2, max: 15, total: 15 }
|
|
1788
|
+
},
|
|
1752
1789
|
supports: ["seed", "promptExpansion", "safetyChecker"]
|
|
1753
1790
|
},
|
|
1754
1791
|
defaults: {
|
|
@@ -1779,7 +1816,14 @@ var VIDEO_MODELS = [
|
|
|
1779
1816
|
aspectRatios: [...H3_REFERENCE_RATIOS],
|
|
1780
1817
|
resolutions: ["480p", "768p"],
|
|
1781
1818
|
durations: { min: 5, max: 15 },
|
|
1782
|
-
references: {
|
|
1819
|
+
references: {
|
|
1820
|
+
images: 9,
|
|
1821
|
+
videos: 3,
|
|
1822
|
+
audios: 3,
|
|
1823
|
+
total: 12,
|
|
1824
|
+
audioOnly: false,
|
|
1825
|
+
videoSeconds: { min: 2, max: 15, total: 15 }
|
|
1826
|
+
},
|
|
1783
1827
|
supports: ["seed", "promptExpansion", "safetyChecker"]
|
|
1784
1828
|
},
|
|
1785
1829
|
defaults: {
|
|
@@ -1811,6 +1855,7 @@ var VIDEO_MODELS = [
|
|
|
1811
1855
|
aspectRatios: [...KLING_RATIOS],
|
|
1812
1856
|
durations: { min: 3, max: 10 },
|
|
1813
1857
|
requires: ["sourceVideo"],
|
|
1858
|
+
sourceVideoSeconds: { min: 3, max: 10.05 },
|
|
1814
1859
|
supports: []
|
|
1815
1860
|
},
|
|
1816
1861
|
defaults: { durationSeconds: 5, aspectRatio: "16:9" },
|
|
@@ -2147,6 +2192,7 @@ var SupportedOptionSchema = import_zod2.z.enum([
|
|
|
2147
2192
|
"watermark",
|
|
2148
2193
|
"safetyChecker",
|
|
2149
2194
|
"taskType",
|
|
2195
|
+
"videoExtension",
|
|
2150
2196
|
"instrumental"
|
|
2151
2197
|
]);
|
|
2152
2198
|
var UsageUnitSchema = import_zod2.z.enum([
|
|
@@ -2167,13 +2213,20 @@ var ProviderOptionValueSchema = import_zod2.z.lazy(
|
|
|
2167
2213
|
])
|
|
2168
2214
|
);
|
|
2169
2215
|
var ProviderOptionsSchema = import_zod2.z.record(import_zod2.z.string(), import_zod2.z.record(import_zod2.z.string(), ProviderOptionValueSchema));
|
|
2216
|
+
var VideoSecondsLimitsSchema = import_zod2.z.looseObject({
|
|
2217
|
+
min: import_zod2.z.number().optional(),
|
|
2218
|
+
max: import_zod2.z.number().optional(),
|
|
2219
|
+
total: import_zod2.z.number().optional(),
|
|
2220
|
+
editMin: import_zod2.z.number().optional()
|
|
2221
|
+
});
|
|
2170
2222
|
var ReferenceLimitsSchema = import_zod2.z.looseObject({
|
|
2171
2223
|
images: import_zod2.z.number().optional(),
|
|
2172
2224
|
imagesWithVideo: import_zod2.z.number().optional(),
|
|
2173
2225
|
videos: import_zod2.z.number().optional(),
|
|
2174
2226
|
audios: import_zod2.z.number().optional(),
|
|
2175
2227
|
total: import_zod2.z.number().optional(),
|
|
2176
|
-
audioOnly: import_zod2.z.boolean().optional()
|
|
2228
|
+
audioOnly: import_zod2.z.boolean().optional(),
|
|
2229
|
+
videoSeconds: VideoSecondsLimitsSchema.optional()
|
|
2177
2230
|
});
|
|
2178
2231
|
var ModelConstraintsSchema = import_zod2.z.looseObject({
|
|
2179
2232
|
aspectRatios: import_zod2.z.array(AspectRatioSchema).optional(),
|
|
@@ -2186,14 +2239,21 @@ var ModelConstraintsSchema = import_zod2.z.looseObject({
|
|
|
2186
2239
|
references: ReferenceLimitsSchema.optional(),
|
|
2187
2240
|
requires: import_zod2.z.array(RequiredInputSchema).optional(),
|
|
2188
2241
|
supports: import_zod2.z.array(SupportedOptionSchema).optional(),
|
|
2189
|
-
ratioIgnoredWith: import_zod2.z.array(import_zod2.z.enum(["firstFrame", "sourceVideo"])).optional()
|
|
2242
|
+
ratioIgnoredWith: import_zod2.z.array(import_zod2.z.enum(["firstFrame", "sourceVideo"])).optional(),
|
|
2243
|
+
sourceVideoSeconds: VideoSecondsLimitsSchema.omit({ total: true }).extend({ inReferenceTotal: import_zod2.z.boolean().optional() }).optional(),
|
|
2244
|
+
extension: import_zod2.z.looseObject({ segmentSeconds: import_zod2.z.number(), maxTotalSeconds: import_zod2.z.number() }).optional()
|
|
2190
2245
|
});
|
|
2191
2246
|
var MediaRefSchema = import_zod2.z.union([
|
|
2192
|
-
import_zod2.z.looseObject({
|
|
2247
|
+
import_zod2.z.looseObject({
|
|
2248
|
+
url: import_zod2.z.string(),
|
|
2249
|
+
label: import_zod2.z.string().optional(),
|
|
2250
|
+
durationSeconds: import_zod2.z.number().optional()
|
|
2251
|
+
}),
|
|
2193
2252
|
import_zod2.z.looseObject({
|
|
2194
2253
|
bytes: import_zod2.z.instanceof(Uint8Array),
|
|
2195
2254
|
mime: import_zod2.z.string(),
|
|
2196
|
-
label: import_zod2.z.string().optional()
|
|
2255
|
+
label: import_zod2.z.string().optional(),
|
|
2256
|
+
durationSeconds: import_zod2.z.number().optional()
|
|
2197
2257
|
})
|
|
2198
2258
|
]);
|
|
2199
2259
|
var ImageSafetySettingSchema = import_zod2.z.looseObject({ category: import_zod2.z.string(), threshold: import_zod2.z.string() });
|
|
@@ -2682,6 +2742,49 @@ function trim(field, refs, limit, model, warnings) {
|
|
|
2682
2742
|
});
|
|
2683
2743
|
return refs.slice(0, limit);
|
|
2684
2744
|
}
|
|
2745
|
+
function knownLength(value) {
|
|
2746
|
+
return value !== void 0 && Number.isFinite(value) ? value : void 0;
|
|
2747
|
+
}
|
|
2748
|
+
function seconds(len, limit) {
|
|
2749
|
+
let digits = 1;
|
|
2750
|
+
while (digits < 3 && Number(len.toFixed(digits)) === limit) digits++;
|
|
2751
|
+
return len.toFixed(digits);
|
|
2752
|
+
}
|
|
2753
|
+
function effectiveMin(limits, taskType) {
|
|
2754
|
+
if (taskType !== "edit" || limits?.editMin === void 0) return limits?.min;
|
|
2755
|
+
return Math.max(limits.min ?? 0, limits.editMin);
|
|
2756
|
+
}
|
|
2757
|
+
function videoLengthViolation(model, input) {
|
|
2758
|
+
const limits = model.constraints.references?.videoSeconds;
|
|
2759
|
+
const refMin = effectiveMin(limits, input.taskType);
|
|
2760
|
+
const lengths = (input.referenceVideos ?? []).map(knownLength);
|
|
2761
|
+
if (limits?.max !== void 0) {
|
|
2762
|
+
const max = limits.max;
|
|
2763
|
+
const i = lengths.findIndex((len) => len !== void 0 && len > max);
|
|
2764
|
+
if (i >= 0)
|
|
2765
|
+
return `${model.label} takes reference videos up to ${String(max)} s each; video ${i + 1} is ${seconds(lengths[i], max)} s.`;
|
|
2766
|
+
}
|
|
2767
|
+
if (refMin !== void 0) {
|
|
2768
|
+
const i = lengths.findIndex((len) => len !== void 0 && len < refMin);
|
|
2769
|
+
if (i >= 0)
|
|
2770
|
+
return `${model.label} takes reference videos of at least ${String(refMin)} s each; video ${i + 1} is ${seconds(lengths[i], refMin)} s.`;
|
|
2771
|
+
}
|
|
2772
|
+
const source = knownLength(input.sourceVideo);
|
|
2773
|
+
const sourceLimits = model.constraints.sourceVideoSeconds;
|
|
2774
|
+
if (limits?.total !== void 0) {
|
|
2775
|
+
const refSum = lengths.reduce((acc, len) => acc + (len ?? 0), 0);
|
|
2776
|
+
const sum = refSum + (sourceLimits?.inReferenceTotal ? source ?? 0 : 0);
|
|
2777
|
+
if (sum > limits.total)
|
|
2778
|
+
return `${model.label} takes reference videos up to ${String(limits.total)} s combined; these add up to ${seconds(sum, limits.total)} s.`;
|
|
2779
|
+
}
|
|
2780
|
+
if (source === void 0) return void 0;
|
|
2781
|
+
const sourceMin = effectiveMin(sourceLimits, input.taskType);
|
|
2782
|
+
if (sourceLimits?.max !== void 0 && source > sourceLimits.max)
|
|
2783
|
+
return `${model.label} takes a source video up to ${String(sourceLimits.max)} s; this one is ${seconds(source, sourceLimits.max)} s.`;
|
|
2784
|
+
if (sourceMin !== void 0 && source < sourceMin)
|
|
2785
|
+
return `${model.label} takes a source video of at least ${String(sourceMin)} s; this one is ${seconds(source, sourceMin)} s.`;
|
|
2786
|
+
return void 0;
|
|
2787
|
+
}
|
|
2685
2788
|
function resolveImageOptions(model, request, onUnsupported = "error") {
|
|
2686
2789
|
const warnings = [];
|
|
2687
2790
|
const c = model.constraints;
|
|
@@ -2867,9 +2970,25 @@ function resolveVideoOptions(model, request, onUnsupported = "error") {
|
|
|
2867
2970
|
model: model.id
|
|
2868
2971
|
});
|
|
2869
2972
|
}
|
|
2973
|
+
const lengthViolation = videoLengthViolation(model, {
|
|
2974
|
+
referenceVideos: videos.map((v) => v.durationSeconds),
|
|
2975
|
+
taskType: merged.taskType,
|
|
2976
|
+
...merged.sourceVideo?.durationSeconds !== void 0 && {
|
|
2977
|
+
sourceVideo: merged.sourceVideo.durationSeconds
|
|
2978
|
+
}
|
|
2979
|
+
});
|
|
2980
|
+
if (lengthViolation !== void 0) {
|
|
2981
|
+
throw new ModelKitError({
|
|
2982
|
+
code: "unsupported_option",
|
|
2983
|
+
message: lengthViolation,
|
|
2984
|
+
model: model.id,
|
|
2985
|
+
retryable: false
|
|
2986
|
+
});
|
|
2987
|
+
}
|
|
2870
2988
|
setOrDelete(merged, "referenceImages", images);
|
|
2871
2989
|
setOrDelete(merged, "referenceVideos", videos);
|
|
2872
2990
|
setOrDelete(merged, "referenceAudios", audios);
|
|
2991
|
+
const keepExtend = merged.taskType === "extend" && (model.constraints.supports ?? []).includes("videoExtension");
|
|
2873
2992
|
dropUnsupported(merged, model, warnings, [
|
|
2874
2993
|
"seed",
|
|
2875
2994
|
"negativePrompt",
|
|
@@ -2879,8 +2998,17 @@ function resolveVideoOptions(model, request, onUnsupported = "error") {
|
|
|
2879
2998
|
"lastFrame",
|
|
2880
2999
|
"watermark",
|
|
2881
3000
|
"safetyChecker",
|
|
2882
|
-
"taskType"
|
|
3001
|
+
...keepExtend ? [] : ["taskType"]
|
|
2883
3002
|
]);
|
|
3003
|
+
if (merged.previousInteractionId !== void 0 && !keepExtend) {
|
|
3004
|
+
warnings.push({
|
|
3005
|
+
code: "option_ignored",
|
|
3006
|
+
field: "previousInteractionId",
|
|
3007
|
+
from: merged.previousInteractionId,
|
|
3008
|
+
message: `${model.id} does not support previousInteractionId; ignored`
|
|
3009
|
+
});
|
|
3010
|
+
delete merged.previousInteractionId;
|
|
3011
|
+
}
|
|
2884
3012
|
return { request: merged, warnings };
|
|
2885
3013
|
}
|
|
2886
3014
|
function resolveAudioOptions(model, request, onUnsupported = "error") {
|