@shop-os/modelkit 0.7.1 → 0.7.3
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 +27 -0
- package/dist/catalog.cjs +54 -0
- package/dist/catalog.cjs.map +1 -1
- package/dist/catalog.d.cts +36 -27
- package/dist/catalog.d.ts +36 -27
- package/dist/catalog.js +54 -0
- package/dist/catalog.js.map +1 -1
- package/dist/index.cjs +159 -60
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +10 -1
- package/dist/index.d.ts +10 -1
- package/dist/index.js +157 -60
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -89,6 +89,7 @@ __export(index_exports, {
|
|
|
89
89
|
liveCatalog: () => liveCatalog,
|
|
90
90
|
liveState: () => liveState,
|
|
91
91
|
lumaAdapter: () => lumaAdapter,
|
|
92
|
+
lumaReframeTooTall: () => lumaReframeTooTall,
|
|
92
93
|
mergeTextProviderOptions: () => mergeTextProviderOptions,
|
|
93
94
|
missingTierKeys: () => missingTierKeys,
|
|
94
95
|
model3dCall: () => model3dCall,
|
|
@@ -126,6 +127,7 @@ __export(index_exports, {
|
|
|
126
127
|
sortCatalogRows: () => sortCatalogRows,
|
|
127
128
|
streamObject: () => streamObject,
|
|
128
129
|
streamText: () => streamText,
|
|
130
|
+
takesTargetAspectRatio: () => takesTargetAspectRatio,
|
|
129
131
|
textUsageEvent: () => textUsageEvent,
|
|
130
132
|
toGeneratedImage: () => toGeneratedImage,
|
|
131
133
|
validateInputSpec: () => validateInputSpec,
|
|
@@ -6486,6 +6488,57 @@ function applyXaiVideoRules(model, req, onUnsupported, warnings) {
|
|
|
6486
6488
|
});
|
|
6487
6489
|
req.resolution = XAI_REFERENCE_MAX_RESOLUTION;
|
|
6488
6490
|
}
|
|
6491
|
+
function takesTargetAspectRatio(model) {
|
|
6492
|
+
const ratios = model.constraints.aspectRatios ?? [];
|
|
6493
|
+
return (model.constraints.requires ?? []).includes("sourceVideo") && ratios.length > 0 && !ratios.includes("adaptive");
|
|
6494
|
+
}
|
|
6495
|
+
var LUMA_REFRAME_VERTICAL_MAX_RESOLUTION = "720p";
|
|
6496
|
+
function lumaReframeTooTall(req) {
|
|
6497
|
+
const vertical = req.aspectRatio === "9:16" || req.aspectRatio === "3:4";
|
|
6498
|
+
return vertical && req.resolution === "1080p";
|
|
6499
|
+
}
|
|
6500
|
+
function applyLumaVideoRules(model, req, onUnsupported, warnings) {
|
|
6501
|
+
if (model.adapter !== "luma" || !takesTargetAspectRatio(model)) return;
|
|
6502
|
+
if (req.aspectRatio === void 0 || req.aspectRatio === "adaptive") {
|
|
6503
|
+
const listed2 = model.constraints.aspectRatios ?? [];
|
|
6504
|
+
const fallback = model.defaults.aspectRatio !== void 0 && model.defaults.aspectRatio !== "adaptive" ? model.defaults.aspectRatio : listed2[0];
|
|
6505
|
+
const message2 = `${model.id} needs a target aspect ratio: ${listed2.join(", ")}`;
|
|
6506
|
+
if (onUnsupported === "error" || fallback === void 0) {
|
|
6507
|
+
throw new ModelKitError({
|
|
6508
|
+
code: "unsupported_option",
|
|
6509
|
+
message: message2,
|
|
6510
|
+
model: model.id,
|
|
6511
|
+
retryable: false
|
|
6512
|
+
});
|
|
6513
|
+
}
|
|
6514
|
+
warnings.push({
|
|
6515
|
+
code: "ratio_coerced",
|
|
6516
|
+
field: "aspectRatio",
|
|
6517
|
+
from: req.aspectRatio ?? "adaptive",
|
|
6518
|
+
to: fallback,
|
|
6519
|
+
message: message2
|
|
6520
|
+
});
|
|
6521
|
+
req.aspectRatio = fallback;
|
|
6522
|
+
}
|
|
6523
|
+
if (!lumaReframeTooTall(req)) return;
|
|
6524
|
+
const message = `${model.id} renders 9:16 and 3:4 reframes at up to ${LUMA_REFRAME_VERTICAL_MAX_RESOLUTION}`;
|
|
6525
|
+
if (onUnsupported === "error") {
|
|
6526
|
+
throw new ModelKitError({
|
|
6527
|
+
code: "unsupported_option",
|
|
6528
|
+
message,
|
|
6529
|
+
model: model.id,
|
|
6530
|
+
retryable: false
|
|
6531
|
+
});
|
|
6532
|
+
}
|
|
6533
|
+
warnings.push({
|
|
6534
|
+
code: "resolution_coerced",
|
|
6535
|
+
field: "resolution",
|
|
6536
|
+
from: req.resolution,
|
|
6537
|
+
to: LUMA_REFRAME_VERTICAL_MAX_RESOLUTION,
|
|
6538
|
+
message
|
|
6539
|
+
});
|
|
6540
|
+
req.resolution = LUMA_REFRAME_VERTICAL_MAX_RESOLUTION;
|
|
6541
|
+
}
|
|
6489
6542
|
var MINIMAX_H3_INSERT = "minimax/h3-max/insert-video";
|
|
6490
6543
|
var INSERT_MIN = 1.625;
|
|
6491
6544
|
var INSERT_MAX = 60;
|
|
@@ -13755,24 +13808,24 @@ var import_zod25 = require("zod");
|
|
|
13755
13808
|
function mp4DurationSeconds(bytes) {
|
|
13756
13809
|
const moov = findBox(bytes, 0, bytes.length, "moov");
|
|
13757
13810
|
if (!moov) return void 0;
|
|
13758
|
-
const mvhd = findBox(bytes, moov.
|
|
13811
|
+
const mvhd = findBox(bytes, moov.body, moov.end, "mvhd");
|
|
13759
13812
|
if (!mvhd) return void 0;
|
|
13760
13813
|
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
13761
|
-
const size = mvhd.end - mvhd.
|
|
13762
|
-
if (size <
|
|
13763
|
-
const version = view.getUint8(mvhd.
|
|
13814
|
+
const size = mvhd.end - mvhd.body;
|
|
13815
|
+
if (size < 4) return void 0;
|
|
13816
|
+
const version = view.getUint8(mvhd.body);
|
|
13764
13817
|
if (version === 0) {
|
|
13765
|
-
if (size <
|
|
13766
|
-
const timescale = view.getUint32(mvhd.
|
|
13767
|
-
const duration = view.getUint32(mvhd.
|
|
13818
|
+
if (size < 4 + 4 + 4 + 4 + 4) return void 0;
|
|
13819
|
+
const timescale = view.getUint32(mvhd.body + 4 + 4 + 4);
|
|
13820
|
+
const duration = view.getUint32(mvhd.body + 4 + 4 + 4 + 4);
|
|
13768
13821
|
if (timescale === 0) return void 0;
|
|
13769
13822
|
return duration / timescale;
|
|
13770
13823
|
}
|
|
13771
13824
|
if (version === 1) {
|
|
13772
|
-
if (size <
|
|
13773
|
-
const timescale = view.getUint32(mvhd.
|
|
13774
|
-
const high = view.getUint32(mvhd.
|
|
13775
|
-
const low = view.getUint32(mvhd.
|
|
13825
|
+
if (size < 4 + 8 + 8 + 4 + 8) return void 0;
|
|
13826
|
+
const timescale = view.getUint32(mvhd.body + 4 + 8 + 8);
|
|
13827
|
+
const high = view.getUint32(mvhd.body + 4 + 8 + 8 + 4);
|
|
13828
|
+
const low = view.getUint32(mvhd.body + 4 + 8 + 8 + 4 + 4);
|
|
13776
13829
|
if (timescale === 0) return void 0;
|
|
13777
13830
|
return (high * 2 ** 32 + low) / timescale;
|
|
13778
13831
|
}
|
|
@@ -13782,15 +13835,23 @@ function findBox(bytes, from, to, type) {
|
|
|
13782
13835
|
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
13783
13836
|
let offset = from;
|
|
13784
13837
|
while (offset + 8 <= to) {
|
|
13785
|
-
|
|
13838
|
+
let size = view.getUint32(offset);
|
|
13839
|
+
let header = 8;
|
|
13786
13840
|
const name = String.fromCharCode(
|
|
13787
13841
|
view.getUint8(offset + 4),
|
|
13788
13842
|
view.getUint8(offset + 5),
|
|
13789
13843
|
view.getUint8(offset + 6),
|
|
13790
13844
|
view.getUint8(offset + 7)
|
|
13791
13845
|
);
|
|
13792
|
-
if (size
|
|
13793
|
-
|
|
13846
|
+
if (size === 1) {
|
|
13847
|
+
if (offset + 16 > to) return void 0;
|
|
13848
|
+
size = view.getUint32(offset + 8) * 2 ** 32 + view.getUint32(offset + 12);
|
|
13849
|
+
header = 16;
|
|
13850
|
+
} else if (size === 0) {
|
|
13851
|
+
size = to - offset;
|
|
13852
|
+
}
|
|
13853
|
+
if (size < header || offset + size > to) return void 0;
|
|
13854
|
+
if (name === type) return { body: offset + header, end: offset + size };
|
|
13794
13855
|
offset += size;
|
|
13795
13856
|
}
|
|
13796
13857
|
return void 0;
|
|
@@ -13803,6 +13864,7 @@ var IMAGE_TIMEOUT_MS = 5 * 6e4;
|
|
|
13803
13864
|
var VIDEO_POLL_INTERVAL_MS = 5e3;
|
|
13804
13865
|
var VIDEO_TIMEOUT_MS = 20 * 6e4;
|
|
13805
13866
|
var PROMPT_MAX_CHARS = 6e3;
|
|
13867
|
+
var OUTPUT_URL_TTL_MS = 55 * 6e4;
|
|
13806
13868
|
var LUMA_IMAGE_MODEL_IDS = /* @__PURE__ */ new Set(["uni-1", "uni-1-max"]);
|
|
13807
13869
|
var LUMA_VIDEO_MODEL_ID = "ray-3.2";
|
|
13808
13870
|
var LUMA_VIDEO_MODES = /* @__PURE__ */ new Map([
|
|
@@ -13821,6 +13883,9 @@ function lumaRowRefusal(row2) {
|
|
|
13821
13883
|
}
|
|
13822
13884
|
return `luma has no ${row2.type} rows`;
|
|
13823
13885
|
}
|
|
13886
|
+
function lumaModel(ctx) {
|
|
13887
|
+
return ctx.model.providerModelId.toLowerCase();
|
|
13888
|
+
}
|
|
13824
13889
|
function lumaBase(ctx) {
|
|
13825
13890
|
return ctx.endpoints?.luma ?? DEFAULT_BASE_URL;
|
|
13826
13891
|
}
|
|
@@ -13863,8 +13928,23 @@ function imageRef(ref) {
|
|
|
13863
13928
|
if ("url" in ref) return { url: ref.url };
|
|
13864
13929
|
return { data: mediaRefToBase64(ref.bytes), media_type: ref.mime };
|
|
13865
13930
|
}
|
|
13931
|
+
var VIDEO_TYPES_BY_EXTENSION = /* @__PURE__ */ new Map([
|
|
13932
|
+
["mp4", "video/mp4"],
|
|
13933
|
+
["m4v", "video/mp4"],
|
|
13934
|
+
["mov", "video/quicktime"],
|
|
13935
|
+
["webm", "video/webm"]
|
|
13936
|
+
]);
|
|
13937
|
+
function videoUrlType(url) {
|
|
13938
|
+
let path = url;
|
|
13939
|
+
try {
|
|
13940
|
+
path = new URL(url).pathname;
|
|
13941
|
+
} catch {
|
|
13942
|
+
}
|
|
13943
|
+
const extension = path.slice(path.lastIndexOf(".") + 1).toLowerCase();
|
|
13944
|
+
return VIDEO_TYPES_BY_EXTENSION.get(extension) ?? "video/mp4";
|
|
13945
|
+
}
|
|
13866
13946
|
function videoRef(ref) {
|
|
13867
|
-
if ("url" in ref) return { url: ref.url, media_type:
|
|
13947
|
+
if ("url" in ref) return { url: ref.url, media_type: videoUrlType(ref.url) };
|
|
13868
13948
|
const mediaType = ref.mime.startsWith("video/") ? ref.mime : "video/mp4";
|
|
13869
13949
|
return { data: mediaRefToBase64(ref.bytes), media_type: mediaType };
|
|
13870
13950
|
}
|
|
@@ -13914,16 +13994,12 @@ function lumaVideoMode(ctx) {
|
|
|
13914
13994
|
}
|
|
13915
13995
|
return mode;
|
|
13916
13996
|
}
|
|
13917
|
-
function reframeTooTall(req) {
|
|
13918
|
-
const vertical = req.aspectRatio === "9:16" || req.aspectRatio === "3:4";
|
|
13919
|
-
return vertical && req.resolution === "1080p";
|
|
13920
|
-
}
|
|
13921
13997
|
function sentResolution(req, mode) {
|
|
13922
|
-
return mode === "reframe" &&
|
|
13998
|
+
return mode === "reframe" && lumaReframeTooTall(req) ? "720p" : req.resolution;
|
|
13923
13999
|
}
|
|
13924
14000
|
function lumaReframeResolution(req, ctx) {
|
|
13925
14001
|
const requested = req.resolution;
|
|
13926
|
-
if (requested === void 0 || !
|
|
14002
|
+
if (requested === void 0 || !lumaReframeTooTall(req)) return requested;
|
|
13927
14003
|
const message = `${ctx.model.id} renders 9:16 and 3:4 reframes at up to 720p`;
|
|
13928
14004
|
if ((ctx.call.onUnsupported ?? "error") === "error") {
|
|
13929
14005
|
throw new ModelKitError({
|
|
@@ -14032,14 +14108,22 @@ async function lumaRequest(ctx, url, body) {
|
|
|
14032
14108
|
}
|
|
14033
14109
|
return res;
|
|
14034
14110
|
}
|
|
14111
|
+
async function parseGeneration(res) {
|
|
14112
|
+
try {
|
|
14113
|
+
const parsed = lumaGenerationSchema.safeParse(await res.json());
|
|
14114
|
+
return parsed.success ? parsed.data : void 0;
|
|
14115
|
+
} catch {
|
|
14116
|
+
return "not_json";
|
|
14117
|
+
}
|
|
14118
|
+
}
|
|
14035
14119
|
async function submitGeneration(ctx, body) {
|
|
14036
14120
|
const retryOptions = mediaRetryOptions(ctx.call, ctx.signal);
|
|
14037
14121
|
const res = await withRetry(
|
|
14038
14122
|
() => lumaRequest(ctx, `${lumaBase(ctx)}/v1/generations`, JSON.stringify(body)),
|
|
14039
14123
|
retryOptions
|
|
14040
14124
|
);
|
|
14041
|
-
const
|
|
14042
|
-
if (
|
|
14125
|
+
const generation = await parseGeneration(res);
|
|
14126
|
+
if (generation === void 0 || generation === "not_json") {
|
|
14043
14127
|
throw new ModelKitError({
|
|
14044
14128
|
code: "provider_rejected",
|
|
14045
14129
|
message: "Luma submit returned no generation id",
|
|
@@ -14048,13 +14132,20 @@ async function submitGeneration(ctx, body) {
|
|
|
14048
14132
|
retryable: false
|
|
14049
14133
|
});
|
|
14050
14134
|
}
|
|
14051
|
-
return
|
|
14135
|
+
return generation;
|
|
14052
14136
|
}
|
|
14053
14137
|
async function readGeneration(ctx, id) {
|
|
14054
14138
|
const res = await lumaRequest(ctx, `${lumaBase(ctx)}/v1/generations/${id}`);
|
|
14055
|
-
const
|
|
14056
|
-
|
|
14057
|
-
|
|
14139
|
+
const generation = await parseGeneration(res);
|
|
14140
|
+
if (generation === "not_json") {
|
|
14141
|
+
throw new ModelKitError({
|
|
14142
|
+
code: "network",
|
|
14143
|
+
message: "Luma returned a poll response that is not JSON",
|
|
14144
|
+
provider: "luma",
|
|
14145
|
+
model: ctx.model.id
|
|
14146
|
+
});
|
|
14147
|
+
}
|
|
14148
|
+
if (generation === void 0) {
|
|
14058
14149
|
throw new ModelKitError({
|
|
14059
14150
|
code: "provider_rejected",
|
|
14060
14151
|
message: "Luma returned an unreadable generation",
|
|
@@ -14063,14 +14154,12 @@ async function readGeneration(ctx, id) {
|
|
|
14063
14154
|
retryable: false
|
|
14064
14155
|
});
|
|
14065
14156
|
}
|
|
14066
|
-
return
|
|
14157
|
+
return generation;
|
|
14067
14158
|
}
|
|
14068
14159
|
function outputUrl(generation, type) {
|
|
14069
14160
|
const outputs = generation.output ?? [];
|
|
14070
|
-
const match = outputs.find((item) => item.type === type && item.url);
|
|
14071
|
-
|
|
14072
|
-
const fallback = outputs.find((item) => item.url);
|
|
14073
|
-
return fallback?.url;
|
|
14161
|
+
const match = outputs.find((item) => item.type === type && item.url) ?? outputs.find((item) => item.type === void 0 && item.url);
|
|
14162
|
+
return match?.url;
|
|
14074
14163
|
}
|
|
14075
14164
|
async function readGenerationOnce(ctx, id) {
|
|
14076
14165
|
try {
|
|
@@ -14109,21 +14198,22 @@ async function checkGeneration(ctx, id, type) {
|
|
|
14109
14198
|
return void 0;
|
|
14110
14199
|
}
|
|
14111
14200
|
async function downloadBytes(ctx, url, fallback) {
|
|
14112
|
-
|
|
14113
|
-
|
|
14114
|
-
|
|
14115
|
-
|
|
14116
|
-
|
|
14117
|
-
|
|
14118
|
-
|
|
14119
|
-
|
|
14120
|
-
|
|
14121
|
-
|
|
14122
|
-
|
|
14123
|
-
|
|
14124
|
-
|
|
14201
|
+
const { bytes, mime: header } = await withRetry(
|
|
14202
|
+
async () => {
|
|
14203
|
+
try {
|
|
14204
|
+
return await mediaRefToBytes({ url }, ctx.fetch, {
|
|
14205
|
+
...ctx.signal !== void 0 && { signal: ctx.signal },
|
|
14206
|
+
provider: "luma",
|
|
14207
|
+
model: ctx.model.id
|
|
14208
|
+
});
|
|
14209
|
+
} catch (cause) {
|
|
14210
|
+
throw classifyThrown("luma", cause, ctx.model.id);
|
|
14211
|
+
}
|
|
14212
|
+
},
|
|
14213
|
+
mediaRetryOptions(ctx.call, ctx.signal)
|
|
14214
|
+
);
|
|
14125
14215
|
const kind = fallback.split("/")[0];
|
|
14126
|
-
const usable = header
|
|
14216
|
+
const usable = header.startsWith(`${kind}/`);
|
|
14127
14217
|
return { bytes, mime: usable ? header : fallback };
|
|
14128
14218
|
}
|
|
14129
14219
|
function imageUsage2(ctx) {
|
|
@@ -14138,15 +14228,12 @@ function imageUsage2(ctx) {
|
|
|
14138
14228
|
}
|
|
14139
14229
|
var GENERATE_SECONDS = 5;
|
|
14140
14230
|
var MAX_PLAUSIBLE_SECONDS = 60;
|
|
14141
|
-
function
|
|
14142
|
-
if (mode === "generate") return GENERATE_SECONDS;
|
|
14231
|
+
function editedSeconds(req, bytes) {
|
|
14143
14232
|
const measured = mp4DurationSeconds(bytes);
|
|
14144
|
-
const
|
|
14145
|
-
const length = measured !== void 0 && measured > 0 && measured <= MAX_PLAUSIBLE_SECONDS ? measured : source2 !== void 0 && "url" in source2 ? source2.durationSeconds : void 0;
|
|
14233
|
+
const length = measured !== void 0 && measured > 0 && measured <= MAX_PLAUSIBLE_SECONDS ? measured : req.sourceVideo?.durationSeconds;
|
|
14146
14234
|
return Math.max(length ?? 0, GENERATE_SECONDS);
|
|
14147
14235
|
}
|
|
14148
|
-
function videoUsage4(ctx, req, mode,
|
|
14149
|
-
const seconds3 = billedSeconds(req, mode, bytes);
|
|
14236
|
+
function videoUsage4(ctx, req, mode, seconds3) {
|
|
14150
14237
|
const event = {
|
|
14151
14238
|
model: ctx.model.id,
|
|
14152
14239
|
provider: "luma",
|
|
@@ -14161,7 +14248,7 @@ function videoUsage4(ctx, req, mode, bytes) {
|
|
|
14161
14248
|
}
|
|
14162
14249
|
function imageBody(req, ctx, outputFormat) {
|
|
14163
14250
|
const prompt = checkPrompt(req, ctx);
|
|
14164
|
-
const model = ctx
|
|
14251
|
+
const model = lumaModel(ctx);
|
|
14165
14252
|
const ratio = req.aspectRatio !== "adaptive" ? req.aspectRatio : void 0;
|
|
14166
14253
|
const [source2, ...rest] = req.references ?? [];
|
|
14167
14254
|
if (source2 === void 0) {
|
|
@@ -14189,7 +14276,7 @@ function imageBody(req, ctx, outputFormat) {
|
|
|
14189
14276
|
}
|
|
14190
14277
|
function videoBody(req, ctx, mode) {
|
|
14191
14278
|
const prompt = checkPrompt(req, ctx);
|
|
14192
|
-
const model = ctx
|
|
14279
|
+
const model = lumaModel(ctx);
|
|
14193
14280
|
const hasReferences = (req.referenceImages ?? []).length + (req.referenceVideos ?? []).length + (req.referenceAudios ?? []).length > 0;
|
|
14194
14281
|
if (hasReferences) {
|
|
14195
14282
|
refuseOrDrop(
|
|
@@ -14271,7 +14358,7 @@ function videoBody(req, ctx, mode) {
|
|
|
14271
14358
|
async function generateLumaImage(req, ctx) {
|
|
14272
14359
|
throwIfAborted(ctx.signal);
|
|
14273
14360
|
lumaKey(ctx);
|
|
14274
|
-
if (!LUMA_IMAGE_MODEL_IDS.has(ctx
|
|
14361
|
+
if (!LUMA_IMAGE_MODEL_IDS.has(lumaModel(ctx))) {
|
|
14275
14362
|
throw new ModelKitError({
|
|
14276
14363
|
code: "unsupported_option",
|
|
14277
14364
|
message: `luma has no image mapping for "${ctx.model.providerModelId}"`,
|
|
@@ -14304,16 +14391,25 @@ function lumaVideoJob(ctx, req, mode, id) {
|
|
|
14304
14391
|
return { status: "pending" };
|
|
14305
14392
|
},
|
|
14306
14393
|
async result(opts) {
|
|
14307
|
-
const signal = opts?.signal
|
|
14308
|
-
const
|
|
14394
|
+
const signal = combineSignals(ctx.signal, opts?.signal);
|
|
14395
|
+
const jobCtx = { ...ctx, ...signal !== void 0 && { signal } };
|
|
14396
|
+
const url = await pollUntil(checkGeneration.bind(null, jobCtx, id, "video"), {
|
|
14309
14397
|
intervalMs: opts?.pollIntervalMs ?? VIDEO_POLL_INTERVAL_MS,
|
|
14310
14398
|
timeoutMs: opts?.timeoutMs ?? VIDEO_TIMEOUT_MS,
|
|
14311
14399
|
...signal !== void 0 && { signal }
|
|
14312
14400
|
});
|
|
14313
|
-
|
|
14401
|
+
if (mode === "generate") {
|
|
14402
|
+
const result2 = {
|
|
14403
|
+
video: { url, expiresAt: new Date(Date.now() + OUTPUT_URL_TTL_MS) },
|
|
14404
|
+
usage: videoUsage4(jobCtx, req, mode, GENERATE_SECONDS),
|
|
14405
|
+
raw: { id }
|
|
14406
|
+
};
|
|
14407
|
+
return result2;
|
|
14408
|
+
}
|
|
14409
|
+
const video = await downloadBytes(jobCtx, url, "video/mp4");
|
|
14314
14410
|
const result = {
|
|
14315
14411
|
video,
|
|
14316
|
-
usage: videoUsage4(
|
|
14412
|
+
usage: videoUsage4(jobCtx, req, mode, editedSeconds(req, video.bytes)),
|
|
14317
14413
|
raw: { id }
|
|
14318
14414
|
};
|
|
14319
14415
|
return result;
|
|
@@ -14323,7 +14419,7 @@ function lumaVideoJob(ctx, req, mode, id) {
|
|
|
14323
14419
|
async function generateLumaVideo(req, ctx) {
|
|
14324
14420
|
throwIfAborted(ctx.signal);
|
|
14325
14421
|
lumaKey(ctx);
|
|
14326
|
-
if (ctx
|
|
14422
|
+
if (lumaModel(ctx) !== LUMA_VIDEO_MODEL_ID) {
|
|
14327
14423
|
throw new ModelKitError({
|
|
14328
14424
|
code: "unsupported_option",
|
|
14329
14425
|
message: `luma has no video mapping for "${ctx.model.providerModelId}"`,
|
|
@@ -16653,6 +16749,7 @@ function resolveVideoOptions(model, request, onUnsupported = "error") {
|
|
|
16653
16749
|
delete merged.previousInteractionId;
|
|
16654
16750
|
}
|
|
16655
16751
|
applyXaiVideoRules(model, merged, onUnsupported, warnings);
|
|
16752
|
+
applyLumaVideoRules(model, merged, onUnsupported, warnings);
|
|
16656
16753
|
checkVideoRequired(model, merged);
|
|
16657
16754
|
applyFalVideoRules(model, merged, request.aspectRatio, warnings);
|
|
16658
16755
|
return { request: merged, warnings };
|
|
@@ -18251,6 +18348,7 @@ var describe = (modelId) => createDefaultModelKit().describe(modelId);
|
|
|
18251
18348
|
liveCatalog,
|
|
18252
18349
|
liveState,
|
|
18253
18350
|
lumaAdapter,
|
|
18351
|
+
lumaReframeTooTall,
|
|
18254
18352
|
mergeTextProviderOptions,
|
|
18255
18353
|
missingTierKeys,
|
|
18256
18354
|
model3dCall,
|
|
@@ -18288,6 +18386,7 @@ var describe = (modelId) => createDefaultModelKit().describe(modelId);
|
|
|
18288
18386
|
sortCatalogRows,
|
|
18289
18387
|
streamObject,
|
|
18290
18388
|
streamText,
|
|
18389
|
+
takesTargetAspectRatio,
|
|
18291
18390
|
textUsageEvent,
|
|
18292
18391
|
toGeneratedImage,
|
|
18293
18392
|
validateInputSpec,
|