@shop-os/modelkit 0.2.15 → 0.2.17
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 +13 -0
- package/dist/catalog.cjs +23 -4
- package/dist/catalog.cjs.map +1 -1
- package/dist/catalog.d.cts +25 -2
- package/dist/catalog.d.ts +25 -2
- package/dist/catalog.js +23 -4
- package/dist/catalog.js.map +1 -1
- package/dist/index.cjs +75 -23
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +25 -2
- package/dist/index.d.ts +25 -2
- package/dist/index.js +75 -23
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -110,8 +110,14 @@ interface VideoRequest {
|
|
|
110
110
|
watermark?: boolean;
|
|
111
111
|
/** Provider-side safety checker toggle (fal MiniMax). Provider default when unset. */
|
|
112
112
|
safetyChecker?: boolean;
|
|
113
|
-
/** Seedance omni-reference subtask hint. `edit` forces duration -1 and adaptive ratio.
|
|
113
|
+
/** Seedance omni-reference subtask hint. `edit` forces duration -1 and adaptive ratio.
|
|
114
|
+
* `extend` on a `videoExtension` row continues the clip by `durationSeconds` more. */
|
|
114
115
|
taskType?: "reference" | "edit" | "extend";
|
|
116
|
+
/** Continue a provider-side session instead of re-sending the clip (Gemini Omni
|
|
117
|
+
* Interactions `previous_interaction_id`). The prior call's `VideoResult.providerRef`
|
|
118
|
+
* carries it. The provider rejects it together with an explicit video task, so the
|
|
119
|
+
* adapter sends the prompt alone; `taskType: "extend"` still selects the extend path. */
|
|
120
|
+
previousInteractionId?: string;
|
|
115
121
|
mode?: "standard" | "pro";
|
|
116
122
|
}
|
|
117
123
|
/**
|
|
@@ -163,7 +169,9 @@ interface MediaPart {
|
|
|
163
169
|
cleanup?: () => Promise<void>;
|
|
164
170
|
}
|
|
165
171
|
type RequiredInput = "firstFrame" | "sourceVideo" | "references";
|
|
166
|
-
type SupportedOption = "seed" | "quality" | "negativePrompt" | "cfgScale" | "generateAudio" | "promptExpansion" | "lastFrame" | "count" | "outputFormat" | "scaleFactor" | "safetySettings" | "temperature" | "upscale" | "watermark" | "safetyChecker" | "taskType" | "instrumental"
|
|
172
|
+
type SupportedOption = "seed" | "quality" | "negativePrompt" | "cfgScale" | "generateAudio" | "promptExpansion" | "lastFrame" | "count" | "outputFormat" | "scaleFactor" | "safetySettings" | "temperature" | "upscale" | "watermark" | "safetyChecker" | "taskType" | "instrumental"
|
|
173
|
+
/** Video rows that extend a clip in fixed segments up to a cumulative cap (see `ModelConstraints.extension`). */
|
|
174
|
+
| "videoExtension";
|
|
167
175
|
interface VideoSecondsLimits {
|
|
168
176
|
/** Minimum length of each reference video, in seconds. */
|
|
169
177
|
min?: number;
|
|
@@ -213,6 +221,12 @@ interface ModelConstraints {
|
|
|
213
221
|
/** The provider sends the source as a reference video, so it counts toward `references.videoSeconds.total` (Seedance). */
|
|
214
222
|
inReferenceTotal?: boolean;
|
|
215
223
|
};
|
|
224
|
+
/** Video extension (rows with `supports: ["videoExtension"]`): each `taskType: "extend"`
|
|
225
|
+
* call adds up to `segmentSeconds` and the clip can grow to `maxTotalSeconds`. */
|
|
226
|
+
extension?: {
|
|
227
|
+
segmentSeconds: number;
|
|
228
|
+
maxTotalSeconds: number;
|
|
229
|
+
};
|
|
216
230
|
}
|
|
217
231
|
/** JSON-compatible value. Provider options and raw payloads carry these, never `unknown`. */
|
|
218
232
|
type JsonPrimitive = string | number | boolean | null;
|
|
@@ -354,6 +368,10 @@ interface VideoResult {
|
|
|
354
368
|
};
|
|
355
369
|
usage: UsageEvent;
|
|
356
370
|
raw?: unknown;
|
|
371
|
+
/** Provider handle for chaining a follow-up call (`VideoRequest.previousInteractionId`). */
|
|
372
|
+
providerRef?: {
|
|
373
|
+
interactionId: string;
|
|
374
|
+
};
|
|
357
375
|
}
|
|
358
376
|
interface VideoCallJob extends VideoJob {
|
|
359
377
|
warnings: Warning[];
|
|
@@ -640,6 +658,7 @@ declare const CatalogModelSchemaBase: z.ZodObject<{
|
|
|
640
658
|
safetyChecker: "safetyChecker";
|
|
641
659
|
taskType: "taskType";
|
|
642
660
|
instrumental: "instrumental";
|
|
661
|
+
videoExtension: "videoExtension";
|
|
643
662
|
}>>>;
|
|
644
663
|
ratioIgnoredWith: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
645
664
|
firstFrame: "firstFrame";
|
|
@@ -651,6 +670,10 @@ declare const CatalogModelSchemaBase: z.ZodObject<{
|
|
|
651
670
|
editMin: z.ZodOptional<z.ZodNumber>;
|
|
652
671
|
inReferenceTotal: z.ZodOptional<z.ZodBoolean>;
|
|
653
672
|
}, z.core.$loose>>;
|
|
673
|
+
extension: z.ZodOptional<z.ZodObject<{
|
|
674
|
+
segmentSeconds: z.ZodNumber;
|
|
675
|
+
maxTotalSeconds: z.ZodNumber;
|
|
676
|
+
}, z.core.$loose>>;
|
|
654
677
|
}, z.core.$loose>;
|
|
655
678
|
defaults: z.ZodObject<{
|
|
656
679
|
references: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
|
package/dist/index.d.ts
CHANGED
|
@@ -110,8 +110,14 @@ interface VideoRequest {
|
|
|
110
110
|
watermark?: boolean;
|
|
111
111
|
/** Provider-side safety checker toggle (fal MiniMax). Provider default when unset. */
|
|
112
112
|
safetyChecker?: boolean;
|
|
113
|
-
/** Seedance omni-reference subtask hint. `edit` forces duration -1 and adaptive ratio.
|
|
113
|
+
/** Seedance omni-reference subtask hint. `edit` forces duration -1 and adaptive ratio.
|
|
114
|
+
* `extend` on a `videoExtension` row continues the clip by `durationSeconds` more. */
|
|
114
115
|
taskType?: "reference" | "edit" | "extend";
|
|
116
|
+
/** Continue a provider-side session instead of re-sending the clip (Gemini Omni
|
|
117
|
+
* Interactions `previous_interaction_id`). The prior call's `VideoResult.providerRef`
|
|
118
|
+
* carries it. The provider rejects it together with an explicit video task, so the
|
|
119
|
+
* adapter sends the prompt alone; `taskType: "extend"` still selects the extend path. */
|
|
120
|
+
previousInteractionId?: string;
|
|
115
121
|
mode?: "standard" | "pro";
|
|
116
122
|
}
|
|
117
123
|
/**
|
|
@@ -163,7 +169,9 @@ interface MediaPart {
|
|
|
163
169
|
cleanup?: () => Promise<void>;
|
|
164
170
|
}
|
|
165
171
|
type RequiredInput = "firstFrame" | "sourceVideo" | "references";
|
|
166
|
-
type SupportedOption = "seed" | "quality" | "negativePrompt" | "cfgScale" | "generateAudio" | "promptExpansion" | "lastFrame" | "count" | "outputFormat" | "scaleFactor" | "safetySettings" | "temperature" | "upscale" | "watermark" | "safetyChecker" | "taskType" | "instrumental"
|
|
172
|
+
type SupportedOption = "seed" | "quality" | "negativePrompt" | "cfgScale" | "generateAudio" | "promptExpansion" | "lastFrame" | "count" | "outputFormat" | "scaleFactor" | "safetySettings" | "temperature" | "upscale" | "watermark" | "safetyChecker" | "taskType" | "instrumental"
|
|
173
|
+
/** Video rows that extend a clip in fixed segments up to a cumulative cap (see `ModelConstraints.extension`). */
|
|
174
|
+
| "videoExtension";
|
|
167
175
|
interface VideoSecondsLimits {
|
|
168
176
|
/** Minimum length of each reference video, in seconds. */
|
|
169
177
|
min?: number;
|
|
@@ -213,6 +221,12 @@ interface ModelConstraints {
|
|
|
213
221
|
/** The provider sends the source as a reference video, so it counts toward `references.videoSeconds.total` (Seedance). */
|
|
214
222
|
inReferenceTotal?: boolean;
|
|
215
223
|
};
|
|
224
|
+
/** Video extension (rows with `supports: ["videoExtension"]`): each `taskType: "extend"`
|
|
225
|
+
* call adds up to `segmentSeconds` and the clip can grow to `maxTotalSeconds`. */
|
|
226
|
+
extension?: {
|
|
227
|
+
segmentSeconds: number;
|
|
228
|
+
maxTotalSeconds: number;
|
|
229
|
+
};
|
|
216
230
|
}
|
|
217
231
|
/** JSON-compatible value. Provider options and raw payloads carry these, never `unknown`. */
|
|
218
232
|
type JsonPrimitive = string | number | boolean | null;
|
|
@@ -354,6 +368,10 @@ interface VideoResult {
|
|
|
354
368
|
};
|
|
355
369
|
usage: UsageEvent;
|
|
356
370
|
raw?: unknown;
|
|
371
|
+
/** Provider handle for chaining a follow-up call (`VideoRequest.previousInteractionId`). */
|
|
372
|
+
providerRef?: {
|
|
373
|
+
interactionId: string;
|
|
374
|
+
};
|
|
357
375
|
}
|
|
358
376
|
interface VideoCallJob extends VideoJob {
|
|
359
377
|
warnings: Warning[];
|
|
@@ -640,6 +658,7 @@ declare const CatalogModelSchemaBase: z.ZodObject<{
|
|
|
640
658
|
safetyChecker: "safetyChecker";
|
|
641
659
|
taskType: "taskType";
|
|
642
660
|
instrumental: "instrumental";
|
|
661
|
+
videoExtension: "videoExtension";
|
|
643
662
|
}>>>;
|
|
644
663
|
ratioIgnoredWith: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
645
664
|
firstFrame: "firstFrame";
|
|
@@ -651,6 +670,10 @@ declare const CatalogModelSchemaBase: z.ZodObject<{
|
|
|
651
670
|
editMin: z.ZodOptional<z.ZodNumber>;
|
|
652
671
|
inReferenceTotal: z.ZodOptional<z.ZodBoolean>;
|
|
653
672
|
}, z.core.$loose>>;
|
|
673
|
+
extension: z.ZodOptional<z.ZodObject<{
|
|
674
|
+
segmentSeconds: z.ZodNumber;
|
|
675
|
+
maxTotalSeconds: z.ZodNumber;
|
|
676
|
+
}, z.core.$loose>>;
|
|
654
677
|
}, z.core.$loose>;
|
|
655
678
|
defaults: z.ZodObject<{
|
|
656
679
|
references: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
|
package/dist/index.js
CHANGED
|
@@ -1402,7 +1402,14 @@ var VIDEO_MODELS = [
|
|
|
1402
1402
|
durations: [3, 4, 5, 6, 7, 8, 9, 10],
|
|
1403
1403
|
references: { images: 6, videos: 1, videoSeconds: { max: 10 } },
|
|
1404
1404
|
sourceVideoSeconds: { max: 10 },
|
|
1405
|
-
|
|
1405
|
+
// Extension (probe 2026-09-24, 360p): each `taskType: "extend"` call
|
|
1406
|
+
// renders `durationSeconds` more and returns the FULL cumulative clip
|
|
1407
|
+
// (3 s -> 6 s -> 9 s); the provider caps the clip at 40 s. A first
|
|
1408
|
+
// extension can upload a <= 10 s source with task "extend"; later ones
|
|
1409
|
+
// chain by `previousInteractionId` (the API rejects the id together
|
|
1410
|
+
// with a video task, so those calls carry the prompt alone).
|
|
1411
|
+
supports: ["videoExtension"],
|
|
1412
|
+
extension: { segmentSeconds: 10, maxTotalSeconds: 40 }
|
|
1406
1413
|
},
|
|
1407
1414
|
defaults: {},
|
|
1408
1415
|
usage: { ...VIDEO_USAGE },
|
|
@@ -1410,7 +1417,7 @@ var VIDEO_MODELS = [
|
|
|
1410
1417
|
display: {
|
|
1411
1418
|
provider: "google",
|
|
1412
1419
|
logo: GOOGLE_LOGO2,
|
|
1413
|
-
description: "Google Gemini Omni Flash 1.1 conversational video generation and
|
|
1420
|
+
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."
|
|
1414
1421
|
},
|
|
1415
1422
|
capabilities: { acceptsSourceVideo: true }
|
|
1416
1423
|
},
|
|
@@ -2144,6 +2151,7 @@ var SupportedOptionSchema = z2.enum([
|
|
|
2144
2151
|
"watermark",
|
|
2145
2152
|
"safetyChecker",
|
|
2146
2153
|
"taskType",
|
|
2154
|
+
"videoExtension",
|
|
2147
2155
|
"instrumental"
|
|
2148
2156
|
]);
|
|
2149
2157
|
var UsageUnitSchema = z2.enum([
|
|
@@ -2191,7 +2199,8 @@ var ModelConstraintsSchema = z2.looseObject({
|
|
|
2191
2199
|
requires: z2.array(RequiredInputSchema).optional(),
|
|
2192
2200
|
supports: z2.array(SupportedOptionSchema).optional(),
|
|
2193
2201
|
ratioIgnoredWith: z2.array(z2.enum(["firstFrame", "sourceVideo"])).optional(),
|
|
2194
|
-
sourceVideoSeconds: VideoSecondsLimitsSchema.omit({ total: true }).extend({ inReferenceTotal: z2.boolean().optional() }).optional()
|
|
2202
|
+
sourceVideoSeconds: VideoSecondsLimitsSchema.omit({ total: true }).extend({ inReferenceTotal: z2.boolean().optional() }).optional(),
|
|
2203
|
+
extension: z2.looseObject({ segmentSeconds: z2.number(), maxTotalSeconds: z2.number() }).optional()
|
|
2195
2204
|
});
|
|
2196
2205
|
var MediaRefSchema = z2.union([
|
|
2197
2206
|
z2.looseObject({
|
|
@@ -4460,12 +4469,34 @@ async function generateOmniVideo(req, ctx, createGenAIClient) {
|
|
|
4460
4469
|
const modelId = ctx.model.id;
|
|
4461
4470
|
const providerModelId = ctx.model.providerModelId;
|
|
4462
4471
|
const duration = req.durationSeconds ?? 10;
|
|
4463
|
-
const
|
|
4464
|
-
const
|
|
4465
|
-
const
|
|
4472
|
+
const extend = req.taskType === "extend";
|
|
4473
|
+
const previousId = extend ? req.previousInteractionId : void 0;
|
|
4474
|
+
const chained = previousId !== void 0;
|
|
4475
|
+
for (const field of ["referenceImages", "referenceVideos", "firstFrame"]) {
|
|
4476
|
+
const value = req[field];
|
|
4477
|
+
if (!chained || value === void 0 || Array.isArray(value) && value.length === 0)
|
|
4478
|
+
continue;
|
|
4479
|
+
ctx.warnings.push({
|
|
4480
|
+
code: "option_ignored",
|
|
4481
|
+
field,
|
|
4482
|
+
from: Array.isArray(value) ? value.length : "set",
|
|
4483
|
+
message: `${modelId} chained extension sends the prompt alone; ${field} ignored`
|
|
4484
|
+
});
|
|
4485
|
+
}
|
|
4486
|
+
const images = chained ? [] : req.referenceImages ?? [];
|
|
4487
|
+
const videos = chained ? [] : req.referenceVideos ?? [];
|
|
4488
|
+
const firstFrame = chained ? void 0 : req.firstFrame;
|
|
4489
|
+
if (extend && !chained && req.sourceVideo === void 0) {
|
|
4490
|
+
throw new ModelKitError({
|
|
4491
|
+
code: "missing_input",
|
|
4492
|
+
message: `${modelId} extend needs a source video or a previousInteractionId`,
|
|
4493
|
+
model: modelId
|
|
4494
|
+
});
|
|
4495
|
+
}
|
|
4496
|
+
const task = extend ? "extend" : req.sourceVideo ? "edit" : firstFrame ? "image_to_video" : images.length > 0 || videos.length > 0 ? "reference_to_video" : "text_to_video";
|
|
4466
4497
|
const isOmniV1 = providerModelId === "gemini-omni-flash-preview";
|
|
4467
4498
|
const responseFormat = { type: "video", delivery: "uri" };
|
|
4468
|
-
if (req.sourceVideo === void 0 && req.aspectRatio !== void 0 && req.aspectRatio !== "adaptive") {
|
|
4499
|
+
if (req.sourceVideo === void 0 && !extend && req.aspectRatio !== void 0 && req.aspectRatio !== "adaptive") {
|
|
4469
4500
|
responseFormat.aspect_ratio = toOmniAspect(req.aspectRatio);
|
|
4470
4501
|
}
|
|
4471
4502
|
if (!isOmniV1) {
|
|
@@ -4497,18 +4528,26 @@ async function generateOmniVideo(req, ctx, createGenAIClient) {
|
|
|
4497
4528
|
const cleanupUploads = async () => {
|
|
4498
4529
|
for (const fileName of uploadedNames) await deleteGoogleFile(fileName, apiKey, ctx.fetch);
|
|
4499
4530
|
};
|
|
4500
|
-
const callCreate = (input) => client2.interactions.create(
|
|
4501
|
-
|
|
4502
|
-
|
|
4503
|
-
|
|
4504
|
-
|
|
4505
|
-
|
|
4506
|
-
|
|
4531
|
+
const callCreate = (input) => client2.interactions.create(
|
|
4532
|
+
previousId !== void 0 ? {
|
|
4533
|
+
model: providerModelId,
|
|
4534
|
+
input,
|
|
4535
|
+
response_format: responseFormat,
|
|
4536
|
+
store: true,
|
|
4537
|
+
previous_interaction_id: previousId
|
|
4538
|
+
} : {
|
|
4539
|
+
model: providerModelId,
|
|
4540
|
+
input,
|
|
4541
|
+
response_format: responseFormat,
|
|
4542
|
+
generation_config: { video_config: { task } },
|
|
4543
|
+
store: true
|
|
4544
|
+
}
|
|
4545
|
+
);
|
|
4507
4546
|
const createRetryOptions = mediaRetryOptions(ctx.call, ctx.signal);
|
|
4508
4547
|
let interaction;
|
|
4509
4548
|
try {
|
|
4510
4549
|
const parts = [];
|
|
4511
|
-
if (req.sourceVideo) {
|
|
4550
|
+
if (req.sourceVideo && !chained) {
|
|
4512
4551
|
const media = await resolveMedia(
|
|
4513
4552
|
req.sourceVideo,
|
|
4514
4553
|
ctx.fetch,
|
|
@@ -4531,11 +4570,11 @@ async function generateOmniVideo(req, ctx, createGenAIClient) {
|
|
|
4531
4570
|
mime_type: media.mime
|
|
4532
4571
|
});
|
|
4533
4572
|
}
|
|
4534
|
-
if (
|
|
4535
|
-
if (
|
|
4536
|
-
parts.push({ type: "text", text:
|
|
4573
|
+
if (firstFrame) {
|
|
4574
|
+
if (firstFrame.label !== void 0)
|
|
4575
|
+
parts.push({ type: "text", text: firstFrame.label });
|
|
4537
4576
|
const media = await resolveMedia(
|
|
4538
|
-
|
|
4577
|
+
firstFrame,
|
|
4539
4578
|
ctx.fetch,
|
|
4540
4579
|
ctx.signal,
|
|
4541
4580
|
"image/png",
|
|
@@ -4594,7 +4633,7 @@ async function generateOmniVideo(req, ctx, createGenAIClient) {
|
|
|
4594
4633
|
}
|
|
4595
4634
|
}
|
|
4596
4635
|
} finally {
|
|
4597
|
-
await cleanupUploads();
|
|
4636
|
+
if (!(extend && !chained)) await cleanupUploads();
|
|
4598
4637
|
}
|
|
4599
4638
|
const jobId = interaction.id ?? crypto.randomUUID();
|
|
4600
4639
|
const usage2 = videoUsage2(ctx, req, duration);
|
|
@@ -4638,6 +4677,7 @@ async function generateOmniVideo(req, ctx, createGenAIClient) {
|
|
|
4638
4677
|
return void 0;
|
|
4639
4678
|
}, pollOptions);
|
|
4640
4679
|
const video = extractOmniVideo(done, modelId);
|
|
4680
|
+
const providerRef = { interactionId: done.id ?? jobId };
|
|
4641
4681
|
if (video.data) {
|
|
4642
4682
|
return {
|
|
4643
4683
|
video: {
|
|
@@ -4645,14 +4685,16 @@ async function generateOmniVideo(req, ctx, createGenAIClient) {
|
|
|
4645
4685
|
mime: video.mime_type ?? "video/mp4"
|
|
4646
4686
|
},
|
|
4647
4687
|
usage: usage2,
|
|
4648
|
-
raw: done
|
|
4688
|
+
raw: done,
|
|
4689
|
+
providerRef
|
|
4649
4690
|
};
|
|
4650
4691
|
}
|
|
4651
4692
|
if (video.uri)
|
|
4652
4693
|
return {
|
|
4653
4694
|
video: await downloadVideo(ctx, video.uri, apiKey, signal),
|
|
4654
4695
|
usage: usage2,
|
|
4655
|
-
raw: done
|
|
4696
|
+
raw: done,
|
|
4697
|
+
providerRef
|
|
4656
4698
|
};
|
|
4657
4699
|
throw classifyHttpError(
|
|
4658
4700
|
void 0,
|
|
@@ -7544,6 +7586,7 @@ function resolveVideoOptions(model, request, onUnsupported = "error") {
|
|
|
7544
7586
|
setOrDelete(merged, "referenceImages", images);
|
|
7545
7587
|
setOrDelete(merged, "referenceVideos", videos);
|
|
7546
7588
|
setOrDelete(merged, "referenceAudios", audios);
|
|
7589
|
+
const keepExtend = merged.taskType === "extend" && (model.constraints.supports ?? []).includes("videoExtension");
|
|
7547
7590
|
dropUnsupported(merged, model, warnings, [
|
|
7548
7591
|
"seed",
|
|
7549
7592
|
"negativePrompt",
|
|
@@ -7553,8 +7596,17 @@ function resolveVideoOptions(model, request, onUnsupported = "error") {
|
|
|
7553
7596
|
"lastFrame",
|
|
7554
7597
|
"watermark",
|
|
7555
7598
|
"safetyChecker",
|
|
7556
|
-
"taskType"
|
|
7599
|
+
...keepExtend ? [] : ["taskType"]
|
|
7557
7600
|
]);
|
|
7601
|
+
if (merged.previousInteractionId !== void 0 && !keepExtend) {
|
|
7602
|
+
warnings.push({
|
|
7603
|
+
code: "option_ignored",
|
|
7604
|
+
field: "previousInteractionId",
|
|
7605
|
+
from: merged.previousInteractionId,
|
|
7606
|
+
message: `${model.id} does not support previousInteractionId; ignored`
|
|
7607
|
+
});
|
|
7608
|
+
delete merged.previousInteractionId;
|
|
7609
|
+
}
|
|
7558
7610
|
return { request: merged, warnings };
|
|
7559
7611
|
}
|
|
7560
7612
|
function resolveAudioOptions(model, request, onUnsupported = "error") {
|