@shop-os/modelkit 0.1.3 → 0.1.5
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/README.md +42 -19
- package/dist/index.cjs +500 -339
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -3
- package/dist/index.d.ts +14 -3
- package/dist/index.js +500 -339
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -83,7 +83,19 @@ var Catalog = class _Catalog {
|
|
|
83
83
|
|
|
84
84
|
// src/catalog/image.ts
|
|
85
85
|
var IMAGE_USAGE = { unit: "images", modality: "IMAGE" };
|
|
86
|
-
var GEMINI_RATIOS = [
|
|
86
|
+
var GEMINI_RATIOS = [
|
|
87
|
+
"1:1",
|
|
88
|
+
"2:3",
|
|
89
|
+
"3:2",
|
|
90
|
+
"16:9",
|
|
91
|
+
"9:16",
|
|
92
|
+
"4:3",
|
|
93
|
+
"3:4",
|
|
94
|
+
"21:9",
|
|
95
|
+
"4:5",
|
|
96
|
+
"5:4",
|
|
97
|
+
"adaptive"
|
|
98
|
+
];
|
|
87
99
|
function geminiImage(id, label, aliases, sizes) {
|
|
88
100
|
const model = {
|
|
89
101
|
id,
|
|
@@ -93,7 +105,7 @@ function geminiImage(id, label, aliases, sizes) {
|
|
|
93
105
|
adapter: "google-image",
|
|
94
106
|
providerModelId: id,
|
|
95
107
|
lifecycle: "active",
|
|
96
|
-
constraints: { aspectRatios: [...GEMINI_RATIOS], sizes },
|
|
108
|
+
constraints: { aspectRatios: [...GEMINI_RATIOS], sizes, supports: ["safetySettings"] },
|
|
97
109
|
defaults: { size: "1K", aspectRatio: "1:1" },
|
|
98
110
|
usage: { ...IMAGE_USAGE },
|
|
99
111
|
pricingKind: "image_size"
|
|
@@ -106,7 +118,8 @@ var IMAGE_MODELS = [
|
|
|
106
118
|
"gemini-3.1-flash-image-preview",
|
|
107
119
|
"Nano Banana Flash",
|
|
108
120
|
["nb-2"],
|
|
109
|
-
|
|
121
|
+
// Flash 3.1 is the only Gemini image model with the 512 tier.
|
|
122
|
+
["512", "1K", "2K", "4K"]
|
|
110
123
|
),
|
|
111
124
|
geminiImage("gemini-3.1-flash-lite-image", "Nano Banana Lite", ["nb-lite"], ["1K"]),
|
|
112
125
|
// trigger-workflows validates 1K only; pricing seeds 2K/4K rows so allow all three.
|
|
@@ -189,7 +202,8 @@ var IMAGE_MODELS = [
|
|
|
189
202
|
"9:16",
|
|
190
203
|
"4:5",
|
|
191
204
|
"5:4",
|
|
192
|
-
"9:21"
|
|
205
|
+
"9:21",
|
|
206
|
+
"adaptive"
|
|
193
207
|
],
|
|
194
208
|
sizes: ["1K"],
|
|
195
209
|
references: { images: 10 },
|
|
@@ -250,9 +264,10 @@ var IMAGE_MODELS = [
|
|
|
250
264
|
constraints: {
|
|
251
265
|
aspectRatios: ["1:1", "2:3", "3:2", "16:9", "9:16", "4:3", "3:4", "4:5", "5:4", "21:9"],
|
|
252
266
|
sizes: ["1K"],
|
|
253
|
-
|
|
267
|
+
// flux-2-pro's job type always returns image/png; only the seed is forwarded.
|
|
268
|
+
supports: ["seed"]
|
|
254
269
|
},
|
|
255
|
-
defaults: { size: "1K", aspectRatio: "1:1"
|
|
270
|
+
defaults: { size: "1K", aspectRatio: "1:1" },
|
|
256
271
|
usage: { ...IMAGE_USAGE },
|
|
257
272
|
pricingKind: "image_size"
|
|
258
273
|
},
|
|
@@ -270,7 +285,8 @@ var IMAGE_MODELS = [
|
|
|
270
285
|
constraints: {
|
|
271
286
|
aspectRatios: ["1:1", "2:3", "3:2", "4:3", "3:4", "4:5", "5:4", "9:16", "16:9", "21:9"],
|
|
272
287
|
sizes: ["1K", "2K", "4K"],
|
|
273
|
-
requires: ["references"]
|
|
288
|
+
requires: ["references"],
|
|
289
|
+
supports: ["seed"]
|
|
274
290
|
},
|
|
275
291
|
defaults: { size: "1K", aspectRatio: "1:1" },
|
|
276
292
|
usage: { ...IMAGE_USAGE },
|
|
@@ -289,7 +305,8 @@ var IMAGE_MODELS = [
|
|
|
289
305
|
constraints: {
|
|
290
306
|
aspectRatios: ["1:1", "2:3", "3:4", "4:3", "9:16", "16:9", "21:9"],
|
|
291
307
|
sizes: ["1K"],
|
|
292
|
-
requires: ["references"]
|
|
308
|
+
requires: ["references"],
|
|
309
|
+
supports: ["seed"]
|
|
293
310
|
},
|
|
294
311
|
defaults: { size: "1K", aspectRatio: "1:1" },
|
|
295
312
|
usage: { ...IMAGE_USAGE },
|
|
@@ -309,7 +326,8 @@ var IMAGE_MODELS = [
|
|
|
309
326
|
constraints: {
|
|
310
327
|
aspectRatios: ["1:1", "16:9", "9:16", "4:3", "3:4"],
|
|
311
328
|
sizes: ["1K", "2K", "4K"],
|
|
312
|
-
references: { images: 9 }
|
|
329
|
+
references: { images: 9 },
|
|
330
|
+
supports: []
|
|
313
331
|
},
|
|
314
332
|
defaults: { size: "1K", aspectRatio: "1:1" },
|
|
315
333
|
usage: { unit: "compute_seconds", modality: "IMAGE" },
|
|
@@ -330,7 +348,8 @@ var IMAGE_MODELS = [
|
|
|
330
348
|
aspectRatios: ["1:1", "16:9", "9:16", "4:3", "3:4", "3:2", "2:3"],
|
|
331
349
|
sizes: [],
|
|
332
350
|
references: { images: 1 },
|
|
333
|
-
requires: ["references"]
|
|
351
|
+
requires: ["references"],
|
|
352
|
+
supports: []
|
|
334
353
|
},
|
|
335
354
|
defaults: { aspectRatio: "1:1" },
|
|
336
355
|
usage: { unit: "compute_seconds", modality: "IMAGE" },
|
|
@@ -372,7 +391,8 @@ var OTHER_MODELS = [
|
|
|
372
391
|
lifecycle: "active",
|
|
373
392
|
constraints: {
|
|
374
393
|
durations: [30],
|
|
375
|
-
references: { images: 10 }
|
|
394
|
+
references: { images: 10 },
|
|
395
|
+
supports: []
|
|
376
396
|
},
|
|
377
397
|
defaults: {},
|
|
378
398
|
usage: { unit: "images", modality: "AUDIO" },
|
|
@@ -387,7 +407,8 @@ var OTHER_MODELS = [
|
|
|
387
407
|
providerModelId: "lyria-3-pro-preview",
|
|
388
408
|
lifecycle: "active",
|
|
389
409
|
constraints: {
|
|
390
|
-
references: { images: 10 }
|
|
410
|
+
references: { images: 10 },
|
|
411
|
+
supports: []
|
|
391
412
|
},
|
|
392
413
|
defaults: {},
|
|
393
414
|
usage: { unit: "images", modality: "AUDIO" },
|
|
@@ -451,8 +472,12 @@ var OTHER_MODELS = [
|
|
|
451
472
|
adapter: "replicate",
|
|
452
473
|
providerModelId: "topazlabs/image-upscale",
|
|
453
474
|
lifecycle: "active",
|
|
454
|
-
constraints: {
|
|
455
|
-
|
|
475
|
+
constraints: {
|
|
476
|
+
references: { images: 1 },
|
|
477
|
+
requires: ["references"],
|
|
478
|
+
supports: ["scaleFactor", "outputFormat"]
|
|
479
|
+
},
|
|
480
|
+
defaults: { scaleFactor: 2, outputFormat: "png" },
|
|
456
481
|
usage: { unit: "compute_seconds", modality: "IMAGE" },
|
|
457
482
|
pricingKind: "flat"
|
|
458
483
|
},
|
|
@@ -466,7 +491,8 @@ var OTHER_MODELS = [
|
|
|
466
491
|
lifecycle: "active",
|
|
467
492
|
constraints: {
|
|
468
493
|
references: { images: 1 },
|
|
469
|
-
requires: ["references"]
|
|
494
|
+
requires: ["references"],
|
|
495
|
+
supports: []
|
|
470
496
|
},
|
|
471
497
|
defaults: {},
|
|
472
498
|
usage: { unit: "images", modality: "IMAGE" },
|
|
@@ -485,7 +511,7 @@ function text(id, label, providerModelId, extra) {
|
|
|
485
511
|
adapter: "ai-sdk-text",
|
|
486
512
|
providerModelId,
|
|
487
513
|
lifecycle: "active",
|
|
488
|
-
constraints: {},
|
|
514
|
+
constraints: { supports: [] },
|
|
489
515
|
defaults: {},
|
|
490
516
|
usage: { ...TEXT_USAGE },
|
|
491
517
|
pricingKind: "token",
|
|
@@ -508,7 +534,7 @@ var TEXT_MODELS = [
|
|
|
508
534
|
text("gpt-5.6-sol", "GPT-5.6 Sol", "gpt-5.6-sol"),
|
|
509
535
|
// Library key "claude-sonnet-4.5" maps to the SDK id "claude-sonnet-4-5".
|
|
510
536
|
text("claude-sonnet-4-5", "Claude Sonnet 4.5", "claude-sonnet-4-5", {
|
|
511
|
-
aliases: ["claude-sonnet-4.5"]
|
|
537
|
+
aliases: ["claude-sonnet-4.5", "claude-sonnet-4-5-20250929"]
|
|
512
538
|
}),
|
|
513
539
|
// Anthropic retired the dated 4.0 ids; callers that still send them get 4.6.
|
|
514
540
|
text("claude-sonnet-4-6", "Claude Sonnet 4.6", "claude-sonnet-4-6", {
|
|
@@ -524,7 +550,7 @@ var TEXT_MODELS = [
|
|
|
524
550
|
aliases: ["claude-opus-4.8", "claude-opus-4", "claude-opus-4.0", "claude-opus-4-20250514"]
|
|
525
551
|
}),
|
|
526
552
|
text("claude-haiku-4-5", "Claude Haiku 4.5", "claude-haiku-4-5", {
|
|
527
|
-
aliases: ["claude-haiku-4.5", "claude-haiku-4-5-20251001"]
|
|
553
|
+
aliases: ["claude-haiku-4.5", "claude-haiku-4-5-20251001", "claude-haiku-4"]
|
|
528
554
|
}),
|
|
529
555
|
text("claude-opus-5", "Claude Opus 5", "claude-opus-5", {
|
|
530
556
|
aliases: ["claude-opus-5.0"]
|
|
@@ -558,7 +584,7 @@ var TEXT_MODELS = [
|
|
|
558
584
|
// src/catalog/video.ts
|
|
559
585
|
var VIDEO_USAGE = { unit: "seconds", modality: "VIDEO" };
|
|
560
586
|
var SEEDANCE_RATIOS = ["21:9", "16:9", "4:3", "1:1", "3:4", "9:16", "adaptive"];
|
|
561
|
-
var KLING_RATIOS = ["16:9", "9:16", "1:1"];
|
|
587
|
+
var KLING_RATIOS = ["16:9", "9:16", "1:1", "adaptive"];
|
|
562
588
|
var OMNI_RATIOS = ["16:9", "9:16"];
|
|
563
589
|
var GROK_RATIOS = ["1:1", "16:9", "9:16", "4:3", "3:4", "3:2", "2:3"];
|
|
564
590
|
var H3_RATIOS = ["21:9", "16:9", "4:3", "1:1", "3:4", "9:16"];
|
|
@@ -650,12 +676,15 @@ var VIDEO_MODELS = [
|
|
|
650
676
|
providerModelId: "gemini-omni-flash-preview",
|
|
651
677
|
lifecycle: "active",
|
|
652
678
|
constraints: {
|
|
679
|
+
// 1.0 rejects `resolution`; it renders 720p. No defaults: the adapter
|
|
680
|
+
// sends ratio and duration only when the caller set them, so a
|
|
681
|
+
// reference clip keeps its own framing.
|
|
653
682
|
aspectRatios: [...OMNI_RATIOS],
|
|
654
|
-
resolutions: ["720p"],
|
|
655
683
|
durations: [3, 4, 5, 6, 7, 8, 9, 10],
|
|
656
|
-
references: { images: 6, videos: 1 }
|
|
684
|
+
references: { images: 6, videos: 1 },
|
|
685
|
+
supports: []
|
|
657
686
|
},
|
|
658
|
-
defaults: {
|
|
687
|
+
defaults: {},
|
|
659
688
|
usage: { ...VIDEO_USAGE },
|
|
660
689
|
pricingKind: "video_per_second"
|
|
661
690
|
},
|
|
@@ -671,9 +700,10 @@ var VIDEO_MODELS = [
|
|
|
671
700
|
aspectRatios: [...OMNI_RATIOS],
|
|
672
701
|
resolutions: ["360p", "720p", "1080p", "4k"],
|
|
673
702
|
durations: [3, 4, 5, 6, 7, 8, 9, 10],
|
|
674
|
-
references: { images: 6, videos: 1 }
|
|
703
|
+
references: { images: 6, videos: 1 },
|
|
704
|
+
supports: []
|
|
675
705
|
},
|
|
676
|
-
defaults: {
|
|
706
|
+
defaults: {},
|
|
677
707
|
usage: { ...VIDEO_USAGE },
|
|
678
708
|
pricingKind: "video_per_second"
|
|
679
709
|
},
|
|
@@ -767,7 +797,8 @@ var VIDEO_MODELS = [
|
|
|
767
797
|
aspectRatios: [...GROK_RATIOS],
|
|
768
798
|
resolutions: ["480p", "720p"],
|
|
769
799
|
durations: { min: 1, max: 15 },
|
|
770
|
-
references: { images: 7 }
|
|
800
|
+
references: { images: 7 },
|
|
801
|
+
supports: []
|
|
771
802
|
},
|
|
772
803
|
defaults: { durationSeconds: 8, resolution: "720p", aspectRatio: "16:9" },
|
|
773
804
|
usage: { unit: "reported_cost_usd", modality: "VIDEO" },
|
|
@@ -957,7 +988,8 @@ var VIDEO_MODELS = [
|
|
|
957
988
|
constraints: {
|
|
958
989
|
aspectRatios: [...KLING_RATIOS],
|
|
959
990
|
durations: { min: 3, max: 10 },
|
|
960
|
-
requires: ["sourceVideo"]
|
|
991
|
+
requires: ["sourceVideo"],
|
|
992
|
+
supports: []
|
|
961
993
|
},
|
|
962
994
|
defaults: { durationSeconds: 5, aspectRatio: "16:9" },
|
|
963
995
|
usage: { ...VIDEO_USAGE },
|
|
@@ -990,7 +1022,7 @@ var VIDEO_MODELS = [
|
|
|
990
1022
|
lifecycle: "active",
|
|
991
1023
|
constraints: {
|
|
992
1024
|
requires: ["firstFrame"],
|
|
993
|
-
supports: ["seed"]
|
|
1025
|
+
supports: ["seed", "lastFrame"]
|
|
994
1026
|
},
|
|
995
1027
|
defaults: {},
|
|
996
1028
|
usage: { ...VIDEO_USAGE },
|
|
@@ -1007,7 +1039,7 @@ var MODELS = [
|
|
|
1007
1039
|
];
|
|
1008
1040
|
|
|
1009
1041
|
// src/resolve-options.ts
|
|
1010
|
-
var SIZE_ORDER = ["1K", "2K", "4K"];
|
|
1042
|
+
var SIZE_ORDER = ["512", "1K", "2K", "4K"];
|
|
1011
1043
|
var RESOLUTION_ORDER = ["360p", "480p", "720p", "768p", "1080p", "2k", "4k"];
|
|
1012
1044
|
function ratioValue(r) {
|
|
1013
1045
|
if (r === "adaptive") return 1;
|
|
@@ -1101,7 +1133,7 @@ function resolveImageOptions(model, request, onUnsupported = "error") {
|
|
|
1101
1133
|
const warnings = [];
|
|
1102
1134
|
const c = model.constraints;
|
|
1103
1135
|
const merged = { ...model.defaults, ...stripUndefined(request), model: model.id };
|
|
1104
|
-
if (merged.aspectRatio && c.aspectRatios && !c.aspectRatios.includes(merged.aspectRatio)) {
|
|
1136
|
+
if (merged.aspectRatio !== void 0 && merged.aspectRatio !== "adaptive" && c.aspectRatios !== void 0 && !c.aspectRatios.includes(merged.aspectRatio)) {
|
|
1105
1137
|
const to = nearestAspectRatio(merged.aspectRatio, c.aspectRatios);
|
|
1106
1138
|
warnings.push({
|
|
1107
1139
|
code: "ratio_coerced",
|
|
@@ -1139,7 +1171,14 @@ function resolveImageOptions(model, request, onUnsupported = "error") {
|
|
|
1139
1171
|
model: model.id
|
|
1140
1172
|
});
|
|
1141
1173
|
}
|
|
1142
|
-
dropUnsupported(merged, model, warnings, [
|
|
1174
|
+
dropUnsupported(merged, model, warnings, [
|
|
1175
|
+
"seed",
|
|
1176
|
+
"quality",
|
|
1177
|
+
"count",
|
|
1178
|
+
"outputFormat",
|
|
1179
|
+
"scaleFactor",
|
|
1180
|
+
"safetySettings"
|
|
1181
|
+
]);
|
|
1143
1182
|
return { request: merged, warnings };
|
|
1144
1183
|
}
|
|
1145
1184
|
function resolveVideoOptions(model, request, onUnsupported = "error") {
|
|
@@ -1168,7 +1207,7 @@ function resolveVideoOptions(model, request, onUnsupported = "error") {
|
|
|
1168
1207
|
delete merged.aspectRatio;
|
|
1169
1208
|
}
|
|
1170
1209
|
}
|
|
1171
|
-
if (merged.aspectRatio && c.aspectRatios && !c.aspectRatios.includes(merged.aspectRatio)) {
|
|
1210
|
+
if (merged.aspectRatio !== void 0 && merged.aspectRatio !== "adaptive" && c.aspectRatios !== void 0 && !c.aspectRatios.includes(merged.aspectRatio)) {
|
|
1172
1211
|
const to = nearestAspectRatio(merged.aspectRatio, c.aspectRatios);
|
|
1173
1212
|
warnings.push({
|
|
1174
1213
|
code: "ratio_coerced",
|
|
@@ -1250,8 +1289,7 @@ function resolveVideoOptions(model, request, onUnsupported = "error") {
|
|
|
1250
1289
|
return { request: merged, warnings };
|
|
1251
1290
|
}
|
|
1252
1291
|
function dropUnsupported(req, model, warnings, fields) {
|
|
1253
|
-
const supports = model.constraints.supports;
|
|
1254
|
-
if (!supports) return;
|
|
1292
|
+
const supports = model.constraints.supports ?? [];
|
|
1255
1293
|
for (const field of fields) {
|
|
1256
1294
|
if (req[field] !== void 0 && !supports.includes(field)) {
|
|
1257
1295
|
warnings.push({
|
|
@@ -1329,8 +1367,45 @@ function keysFromEnv(env, prefix = "") {
|
|
|
1329
1367
|
}
|
|
1330
1368
|
|
|
1331
1369
|
// src/retry.ts
|
|
1370
|
+
import { z as z2 } from "zod";
|
|
1371
|
+
|
|
1372
|
+
// src/json.ts
|
|
1332
1373
|
import { z } from "zod";
|
|
1333
|
-
var
|
|
1374
|
+
var JsonValueSchema = z.lazy(
|
|
1375
|
+
() => z.union([
|
|
1376
|
+
z.string(),
|
|
1377
|
+
z.number(),
|
|
1378
|
+
z.boolean(),
|
|
1379
|
+
z.null(),
|
|
1380
|
+
z.array(JsonValueSchema),
|
|
1381
|
+
z.record(z.string(), JsonValueSchema)
|
|
1382
|
+
])
|
|
1383
|
+
);
|
|
1384
|
+
var JsonObjectSchema = z.record(z.string(), JsonValueSchema);
|
|
1385
|
+
async function readErrorBody(res) {
|
|
1386
|
+
const text2 = await res.text().catch(() => "");
|
|
1387
|
+
try {
|
|
1388
|
+
return JsonValueSchema.parse(JSON.parse(text2));
|
|
1389
|
+
} catch {
|
|
1390
|
+
return text2;
|
|
1391
|
+
}
|
|
1392
|
+
}
|
|
1393
|
+
var thrownErrorSchema = z.object({
|
|
1394
|
+
message: z.string().optional(),
|
|
1395
|
+
status: z.number().optional(),
|
|
1396
|
+
statusCode: z.number().optional(),
|
|
1397
|
+
responseBody: z.string().optional()
|
|
1398
|
+
});
|
|
1399
|
+
function describeThrown(cause) {
|
|
1400
|
+
const parsed = thrownErrorSchema.safeParse(cause);
|
|
1401
|
+
if (!parsed.success) return { message: String(cause), status: void 0, body: String(cause) };
|
|
1402
|
+
const { message, status, statusCode, responseBody } = parsed.data;
|
|
1403
|
+
const body = responseBody ?? message ?? String(cause);
|
|
1404
|
+
return { message: message ?? String(cause), status: status ?? statusCode, body };
|
|
1405
|
+
}
|
|
1406
|
+
|
|
1407
|
+
// src/retry.ts
|
|
1408
|
+
var textBody = z2.string();
|
|
1334
1409
|
function classifyHttpError(status, body, provider, model) {
|
|
1335
1410
|
const asText = textBody.safeParse(body);
|
|
1336
1411
|
const text2 = asText.success ? asText.data : JSON.stringify(body);
|
|
@@ -1413,6 +1488,13 @@ function transportError(provider, cause, model) {
|
|
|
1413
1488
|
if (model !== void 0) init.model = model;
|
|
1414
1489
|
return new ModelKitError(init);
|
|
1415
1490
|
}
|
|
1491
|
+
function classifyThrown(provider, cause, model, override = {}) {
|
|
1492
|
+
if (cause instanceof ModelKitError) return cause;
|
|
1493
|
+
const info = describeThrown(cause);
|
|
1494
|
+
const status = override.status ?? info.status;
|
|
1495
|
+
if (status === void 0) return transportError(provider, cause, model);
|
|
1496
|
+
return classifyHttpError(status, override.body ?? info.body, provider, model);
|
|
1497
|
+
}
|
|
1416
1498
|
async function pollUntil(check, opts) {
|
|
1417
1499
|
const start = Date.now();
|
|
1418
1500
|
let interval = opts.intervalMs;
|
|
@@ -1535,7 +1617,7 @@ import {
|
|
|
1535
1617
|
streamObject as aiStreamObject2,
|
|
1536
1618
|
streamText as aiStreamText2
|
|
1537
1619
|
} from "ai";
|
|
1538
|
-
import { z as
|
|
1620
|
+
import { z as z4 } from "zod";
|
|
1539
1621
|
|
|
1540
1622
|
// src/adapters/media-ref.ts
|
|
1541
1623
|
function isUrlRef(ref) {
|
|
@@ -1590,7 +1672,7 @@ import { createPerplexity } from "@ai-sdk/perplexity";
|
|
|
1590
1672
|
import { createXai } from "@ai-sdk/xai";
|
|
1591
1673
|
import { createDeepSeek } from "@ai-sdk/deepseek";
|
|
1592
1674
|
import { createMoonshotAI } from "@ai-sdk/moonshotai";
|
|
1593
|
-
import { z as
|
|
1675
|
+
import { z as z3 } from "zod";
|
|
1594
1676
|
var TEXT_PROVIDERS = [
|
|
1595
1677
|
"openai",
|
|
1596
1678
|
"anthropic",
|
|
@@ -1601,7 +1683,7 @@ var TEXT_PROVIDERS = [
|
|
|
1601
1683
|
"moonshot",
|
|
1602
1684
|
"minimax"
|
|
1603
1685
|
];
|
|
1604
|
-
var textProviderSchema =
|
|
1686
|
+
var textProviderSchema = z3.enum(TEXT_PROVIDERS);
|
|
1605
1687
|
function isTextProvider(value) {
|
|
1606
1688
|
return textProviderSchema.safeParse(value).success;
|
|
1607
1689
|
}
|
|
@@ -1610,9 +1692,9 @@ var OPENAI_COMPATIBLE_BASE_URLS = {
|
|
|
1610
1692
|
};
|
|
1611
1693
|
var GATEWAY_SLUGS = {
|
|
1612
1694
|
openai: "openai",
|
|
1613
|
-
anthropic: "anthropic",
|
|
1695
|
+
anthropic: "anthropic/v1",
|
|
1614
1696
|
google: "google-ai-studio/v1beta",
|
|
1615
|
-
xai: "grok",
|
|
1697
|
+
xai: "grok/v1",
|
|
1616
1698
|
perplexity: "perplexity-ai",
|
|
1617
1699
|
deepseek: "deepseek"
|
|
1618
1700
|
};
|
|
@@ -1787,10 +1869,10 @@ function textAbortOptions(sdk, context) {
|
|
|
1787
1869
|
if (abortSignal) return { abortSignal };
|
|
1788
1870
|
return {};
|
|
1789
1871
|
}
|
|
1790
|
-
var catalogId =
|
|
1791
|
-
var exactSize =
|
|
1792
|
-
var sdkRatio =
|
|
1793
|
-
var sizeTier =
|
|
1872
|
+
var catalogId = z4.string();
|
|
1873
|
+
var exactSize = z4.templateLiteral([z4.number(), "x", z4.number()]);
|
|
1874
|
+
var sdkRatio = z4.templateLiteral([z4.number(), ":", z4.number()]);
|
|
1875
|
+
var sizeTier = z4.enum(["512", "1K", "2K", "4K"]);
|
|
1794
1876
|
function isCatalogId(model) {
|
|
1795
1877
|
return catalogId.safeParse(model).success;
|
|
1796
1878
|
}
|
|
@@ -1847,6 +1929,10 @@ function pushIgnored(warnings, field, from, modelId) {
|
|
|
1847
1929
|
message: `${modelId} provider instance does not support ${field}; ignored`
|
|
1848
1930
|
});
|
|
1849
1931
|
}
|
|
1932
|
+
function logCoercions(logger, modelId, warnings) {
|
|
1933
|
+
if (warnings.length === 0) return;
|
|
1934
|
+
logger.warn(`[modelkit] ${modelId} request coerced`, { model: modelId, warnings });
|
|
1935
|
+
}
|
|
1850
1936
|
function createModelKit(config, adapters) {
|
|
1851
1937
|
const catalog = new Catalog(MODELS).withOverrides(config.catalogOverride ?? []);
|
|
1852
1938
|
const logger = config.logger ?? console;
|
|
@@ -1880,6 +1966,10 @@ function createModelKit(config, adapters) {
|
|
|
1880
1966
|
logger.warn("[modelkit] usage emit failed", err);
|
|
1881
1967
|
}
|
|
1882
1968
|
}
|
|
1969
|
+
function withRowUnit(event) {
|
|
1970
|
+
const row = catalog.get(event.model);
|
|
1971
|
+
return row ? { ...event, unit: row.usage.unit } : event;
|
|
1972
|
+
}
|
|
1883
1973
|
function textTarget(model, call) {
|
|
1884
1974
|
if (!isCatalogId(model)) {
|
|
1885
1975
|
return {
|
|
@@ -1920,6 +2010,7 @@ function createModelKit(config, adapters) {
|
|
|
1920
2010
|
providerOptions,
|
|
1921
2011
|
references,
|
|
1922
2012
|
exactSize: exactSizeField,
|
|
2013
|
+
scaleFactor,
|
|
1923
2014
|
quality: _quality,
|
|
1924
2015
|
outputFormat: _outputFormat
|
|
1925
2016
|
} = req;
|
|
@@ -1945,6 +2036,9 @@ function createModelKit(config, adapters) {
|
|
|
1945
2036
|
if (_quality !== void 0) pushIgnored(warnings, "quality", _quality, model.modelId);
|
|
1946
2037
|
if (_outputFormat !== void 0)
|
|
1947
2038
|
pushIgnored(warnings, "outputFormat", _outputFormat, model.modelId);
|
|
2039
|
+
if (scaleFactor !== void 0)
|
|
2040
|
+
pushIgnored(warnings, "scaleFactor", scaleFactor, model.modelId);
|
|
2041
|
+
logCoercions(logger, model.modelId, warnings);
|
|
1948
2042
|
const abortSignal = combineSignals(req.abortSignal, call.signal);
|
|
1949
2043
|
if (abortSignal) options.abortSignal = abortSignal;
|
|
1950
2044
|
const result = await aiGenerateImage(options);
|
|
@@ -2028,6 +2122,7 @@ function createModelKit(config, adapters) {
|
|
|
2028
2122
|
if (_mode !== void 0) pushIgnored(warnings, "mode", _mode, model.modelId);
|
|
2029
2123
|
if (providerOptions) options.providerOptions = providerOptions;
|
|
2030
2124
|
if (abortSignal) options.abortSignal = abortSignal;
|
|
2125
|
+
logCoercions(logger, model.modelId, warnings);
|
|
2031
2126
|
const pending = aiGenerateVideo(options);
|
|
2032
2127
|
let settled;
|
|
2033
2128
|
let failed = false;
|
|
@@ -2086,6 +2181,7 @@ function createModelKit(config, adapters) {
|
|
|
2086
2181
|
call.onUnsupported ?? "error"
|
|
2087
2182
|
);
|
|
2088
2183
|
warnings.push(...inputWarnings);
|
|
2184
|
+
logCoercions(logger, model.id, warnings);
|
|
2089
2185
|
const signal = combineSignals(req.abortSignal, call.signal);
|
|
2090
2186
|
const { adapter, ctx } = context(model, signal ? { ...call, signal } : call, warnings);
|
|
2091
2187
|
if (!adapter.generateImage)
|
|
@@ -2095,7 +2191,7 @@ function createModelKit(config, adapters) {
|
|
|
2095
2191
|
model: model.id
|
|
2096
2192
|
});
|
|
2097
2193
|
const result = await adapter.generateImage(request, ctx);
|
|
2098
|
-
const usage2 = { ...result.usage, model: model.id };
|
|
2194
|
+
const usage2 = { ...result.usage, model: model.id, unit: model.usage.unit };
|
|
2099
2195
|
await emit(usage2);
|
|
2100
2196
|
const images = result.images.map(toGeneratedImage);
|
|
2101
2197
|
const first = images[0];
|
|
@@ -2128,6 +2224,7 @@ function createModelKit(config, adapters) {
|
|
|
2128
2224
|
call.onUnsupported ?? "error"
|
|
2129
2225
|
);
|
|
2130
2226
|
warnings.push(...inputWarnings);
|
|
2227
|
+
logCoercions(logger, model.id, warnings);
|
|
2131
2228
|
const signal = combineSignals(req.abortSignal, call.signal);
|
|
2132
2229
|
const { adapter, ctx } = context(model, signal ? { ...call, signal } : call, warnings);
|
|
2133
2230
|
if (!adapter.generateVideo)
|
|
@@ -2145,7 +2242,11 @@ function createModelKit(config, adapters) {
|
|
|
2145
2242
|
result(opts) {
|
|
2146
2243
|
if (settled) return settled;
|
|
2147
2244
|
const pending = result(opts).then(
|
|
2148
|
-
(out) => emit({
|
|
2245
|
+
(out) => emit({
|
|
2246
|
+
...out.usage,
|
|
2247
|
+
model: model.id,
|
|
2248
|
+
unit: model.usage.unit
|
|
2249
|
+
}).then(() => out),
|
|
2149
2250
|
(cause) => {
|
|
2150
2251
|
settled = void 0;
|
|
2151
2252
|
throw cause;
|
|
@@ -2165,7 +2266,8 @@ function createModelKit(config, adapters) {
|
|
|
2165
2266
|
model: model.id
|
|
2166
2267
|
});
|
|
2167
2268
|
}
|
|
2168
|
-
const
|
|
2269
|
+
const warnings = [];
|
|
2270
|
+
const { adapter, ctx } = context(model, call, warnings);
|
|
2169
2271
|
if (!adapter.generateAudio) {
|
|
2170
2272
|
throw new ModelKitError({
|
|
2171
2273
|
code: "unsupported_option",
|
|
@@ -2177,7 +2279,8 @@ function createModelKit(config, adapters) {
|
|
|
2177
2279
|
{ ...model.defaults, ...req, model: model.id },
|
|
2178
2280
|
ctx
|
|
2179
2281
|
);
|
|
2180
|
-
|
|
2282
|
+
logCoercions(logger, model.id, warnings);
|
|
2283
|
+
await emit({ ...result.usage, model: model.id, unit: model.usage.unit });
|
|
2181
2284
|
return result;
|
|
2182
2285
|
},
|
|
2183
2286
|
async prepareMediaPart(modelId, ref, mediaType, call = {}) {
|
|
@@ -2217,7 +2320,7 @@ function createModelKit(config, adapters) {
|
|
|
2217
2320
|
options.prepareStep ?? options.experimental_prepareStep
|
|
2218
2321
|
)
|
|
2219
2322
|
});
|
|
2220
|
-
for (const event of steps.usage(result.steps)) await emit(event);
|
|
2323
|
+
for (const event of steps.usage(result.steps)) await emit(withRowUnit(event));
|
|
2221
2324
|
return result;
|
|
2222
2325
|
},
|
|
2223
2326
|
streamText(options, call = {}) {
|
|
@@ -2235,7 +2338,7 @@ function createModelKit(config, adapters) {
|
|
|
2235
2338
|
providerOptions: {},
|
|
2236
2339
|
prepareStep: steps.wrap(options.prepareStep),
|
|
2237
2340
|
onFinish: async (event) => {
|
|
2238
|
-
for (const usage2 of steps.usage(event.steps)) await emit(usage2);
|
|
2341
|
+
for (const usage2 of steps.usage(event.steps)) await emit(withRowUnit(usage2));
|
|
2239
2342
|
await callerOnFinish?.(event);
|
|
2240
2343
|
}
|
|
2241
2344
|
});
|
|
@@ -2249,7 +2352,7 @@ function createModelKit(config, adapters) {
|
|
|
2249
2352
|
providerOptions: mergeTextProviderOptions(entry, options.providerOptions)
|
|
2250
2353
|
};
|
|
2251
2354
|
const result = await aiGenerateObject2(sdkOptions);
|
|
2252
|
-
await emit(textUsageEvent(entry, provider, result.usage));
|
|
2355
|
+
await emit(withRowUnit(textUsageEvent(entry, provider, result.usage)));
|
|
2253
2356
|
return result;
|
|
2254
2357
|
},
|
|
2255
2358
|
streamObject(options, call = {}) {
|
|
@@ -2261,7 +2364,7 @@ function createModelKit(config, adapters) {
|
|
|
2261
2364
|
model: languageModel2,
|
|
2262
2365
|
providerOptions: mergeTextProviderOptions(entry, options.providerOptions),
|
|
2263
2366
|
onFinish: async (event) => {
|
|
2264
|
-
await emit(textUsageEvent(entry, provider, event.usage));
|
|
2367
|
+
await emit(withRowUnit(textUsageEvent(entry, provider, event.usage)));
|
|
2265
2368
|
await callerOnFinish?.(event);
|
|
2266
2369
|
}
|
|
2267
2370
|
};
|
|
@@ -2271,7 +2374,7 @@ function createModelKit(config, adapters) {
|
|
|
2271
2374
|
}
|
|
2272
2375
|
|
|
2273
2376
|
// src/adapters/ark.ts
|
|
2274
|
-
import { z as
|
|
2377
|
+
import { z as z5 } from "zod";
|
|
2275
2378
|
var ARK_BASE_URL = "https://ark.ap-southeast.bytepluses.com/api/v3";
|
|
2276
2379
|
var SUBMIT_PATH = "/contents/generations/tasks";
|
|
2277
2380
|
var SEEDANCE_POLL_INTERVAL_MS = 15e3;
|
|
@@ -2329,7 +2432,7 @@ function arkKey(ctx) {
|
|
|
2329
2432
|
return key;
|
|
2330
2433
|
}
|
|
2331
2434
|
function throwArkError(status, body, model) {
|
|
2332
|
-
const parsed =
|
|
2435
|
+
const parsed = z5.string().safeParse(body);
|
|
2333
2436
|
const text2 = parsed.success ? parsed.data : JSON.stringify(body ?? "");
|
|
2334
2437
|
if (/sensitive.?content|inputimage|human.?face/i.test(text2)) {
|
|
2335
2438
|
const init = {
|
|
@@ -2343,6 +2446,16 @@ function throwArkError(status, body, model) {
|
|
|
2343
2446
|
if (status !== void 0) init.status = status;
|
|
2344
2447
|
throw new ModelKitError(init);
|
|
2345
2448
|
}
|
|
2449
|
+
if (status === void 0) {
|
|
2450
|
+
throw new ModelKitError({
|
|
2451
|
+
code: "provider_rejected",
|
|
2452
|
+
message: `ark rejected the request: ${text2.slice(0, 500)}`,
|
|
2453
|
+
provider: "ark",
|
|
2454
|
+
model,
|
|
2455
|
+
body,
|
|
2456
|
+
retryable: false
|
|
2457
|
+
});
|
|
2458
|
+
}
|
|
2346
2459
|
throw classifyHttpError(status, body, "ark", model);
|
|
2347
2460
|
}
|
|
2348
2461
|
function seedreamSize(aspect, size) {
|
|
@@ -2361,13 +2474,13 @@ function arkUrl(ref) {
|
|
|
2361
2474
|
if ("url" in ref) return ref.url;
|
|
2362
2475
|
return `data:${ref.mime};base64,${Buffer.from(ref.bytes).toString("base64")}`;
|
|
2363
2476
|
}
|
|
2364
|
-
var SeedreamImageSchema =
|
|
2365
|
-
url:
|
|
2366
|
-
b64_json:
|
|
2477
|
+
var SeedreamImageSchema = z5.object({
|
|
2478
|
+
url: z5.string().optional(),
|
|
2479
|
+
b64_json: z5.string().optional()
|
|
2367
2480
|
});
|
|
2368
|
-
var SeedreamResponseSchema =
|
|
2369
|
-
data:
|
|
2370
|
-
error:
|
|
2481
|
+
var SeedreamResponseSchema = z5.object({
|
|
2482
|
+
data: z5.array(SeedreamImageSchema).optional(),
|
|
2483
|
+
error: z5.object({ message: z5.string().optional(), code: z5.string().optional() }).optional()
|
|
2371
2484
|
});
|
|
2372
2485
|
function retryOptsFor(ctx, attempts = 3) {
|
|
2373
2486
|
const opts = { attempts };
|
|
@@ -2378,6 +2491,11 @@ function fetchInitFor(ctx, init) {
|
|
|
2378
2491
|
if (ctx.signal !== void 0) init.signal = ctx.signal;
|
|
2379
2492
|
return init;
|
|
2380
2493
|
}
|
|
2494
|
+
function arkFetch(ctx, url, init) {
|
|
2495
|
+
return ctx.fetch(url, fetchInitFor(ctx, init)).catch((cause) => {
|
|
2496
|
+
throw classifyThrown("ark", cause, ctx.model.id);
|
|
2497
|
+
});
|
|
2498
|
+
}
|
|
2381
2499
|
async function generateSeedreamImage(req, ctx) {
|
|
2382
2500
|
const key = arkKey(ctx);
|
|
2383
2501
|
const modelId = ctx.model.id;
|
|
@@ -2395,14 +2513,11 @@ async function generateSeedreamImage(req, ctx) {
|
|
|
2395
2513
|
if (refs.length === 1 && firstRef !== void 0) body.image = firstRef;
|
|
2396
2514
|
else if (refs.length > 1) body.image = refs;
|
|
2397
2515
|
const data = await withRetry(async () => {
|
|
2398
|
-
const res = await ctx
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
body: JSON.stringify(body)
|
|
2404
|
-
})
|
|
2405
|
-
);
|
|
2516
|
+
const res = await arkFetch(ctx, `${arkBaseUrl(ctx)}/images/generations`, {
|
|
2517
|
+
method: "POST",
|
|
2518
|
+
headers: { Authorization: `Bearer ${key}`, "Content-Type": "application/json" },
|
|
2519
|
+
body: JSON.stringify(body)
|
|
2520
|
+
});
|
|
2406
2521
|
if (!res.ok) {
|
|
2407
2522
|
const text2 = await res.text().catch(() => "");
|
|
2408
2523
|
throwArkError(res.status, text2, modelId);
|
|
@@ -2417,7 +2532,7 @@ async function generateSeedreamImage(req, ctx) {
|
|
|
2417
2532
|
bytes = Buffer.from(first.b64_json, "base64");
|
|
2418
2533
|
} else if (first?.url) {
|
|
2419
2534
|
const imageUrl = first.url;
|
|
2420
|
-
const res = await ctx
|
|
2535
|
+
const res = await arkFetch(ctx, imageUrl, {});
|
|
2421
2536
|
if (!res.ok) {
|
|
2422
2537
|
const text2 = await res.text().catch(() => "");
|
|
2423
2538
|
throwArkError(res.status, text2, modelId);
|
|
@@ -2437,13 +2552,13 @@ async function generateSeedreamImage(req, ctx) {
|
|
|
2437
2552
|
if (req.quality !== void 0) usage2.imageQuality = req.quality;
|
|
2438
2553
|
return { images: [{ bytes, mime: sniffedImageMime(bytes) }], usage: usage2, raw: data };
|
|
2439
2554
|
}
|
|
2440
|
-
var SeedanceResponseSchema =
|
|
2441
|
-
id:
|
|
2442
|
-
status:
|
|
2443
|
-
content:
|
|
2444
|
-
error:
|
|
2555
|
+
var SeedanceResponseSchema = z5.object({
|
|
2556
|
+
id: z5.string().optional(),
|
|
2557
|
+
status: z5.string().optional(),
|
|
2558
|
+
content: z5.object({ video_url: z5.string().optional() }).optional(),
|
|
2559
|
+
error: z5.union([z5.string(), z5.object({ message: z5.string().optional() })]).optional()
|
|
2445
2560
|
});
|
|
2446
|
-
var SeedanceErrorMessageSchema =
|
|
2561
|
+
var SeedanceErrorMessageSchema = z5.object({ message: z5.string().optional() });
|
|
2447
2562
|
function seedanceUsage(ctx, req, duration) {
|
|
2448
2563
|
const usage2 = {
|
|
2449
2564
|
model: ctx.model.id,
|
|
@@ -2457,7 +2572,7 @@ function seedanceUsage(ctx, req, duration) {
|
|
|
2457
2572
|
return usage2;
|
|
2458
2573
|
}
|
|
2459
2574
|
function seedanceErrorMessage(error, status) {
|
|
2460
|
-
const asString =
|
|
2575
|
+
const asString = z5.string().safeParse(error);
|
|
2461
2576
|
if (asString.success) return asString.data;
|
|
2462
2577
|
const asObject = SeedanceErrorMessageSchema.safeParse(error);
|
|
2463
2578
|
if (asObject.success && asObject.data.message !== void 0) return asObject.data.message;
|
|
@@ -2522,14 +2637,11 @@ async function generateSeedanceVideo(req, ctx) {
|
|
|
2522
2637
|
if (req.generateAudio !== void 0) body.generate_audio = req.generateAudio;
|
|
2523
2638
|
if (req.seed !== void 0) body.seed = req.seed;
|
|
2524
2639
|
const submit = await withRetry(async () => {
|
|
2525
|
-
const res = await ctx
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
body: JSON.stringify(body)
|
|
2531
|
-
})
|
|
2532
|
-
);
|
|
2640
|
+
const res = await arkFetch(ctx, `${arkBaseUrl(ctx)}${SUBMIT_PATH}`, {
|
|
2641
|
+
method: "POST",
|
|
2642
|
+
headers: { Authorization: `Bearer ${key}`, "Content-Type": "application/json" },
|
|
2643
|
+
body: JSON.stringify(body)
|
|
2644
|
+
});
|
|
2533
2645
|
if (!res.ok) {
|
|
2534
2646
|
const text2 = await res.text().catch(() => "");
|
|
2535
2647
|
throwArkError(res.status, text2, modelId);
|
|
@@ -2542,12 +2654,9 @@ async function generateSeedanceVideo(req, ctx) {
|
|
|
2542
2654
|
const jobId = submit.id;
|
|
2543
2655
|
const usage2 = seedanceUsage(ctx, req, duration);
|
|
2544
2656
|
const fetchStatus = async () => {
|
|
2545
|
-
const res = await ctx
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
headers: { Authorization: `Bearer ${key}` }
|
|
2549
|
-
})
|
|
2550
|
-
);
|
|
2657
|
+
const res = await arkFetch(ctx, `${arkBaseUrl(ctx)}${SUBMIT_PATH}/${jobId}`, {
|
|
2658
|
+
headers: { Authorization: `Bearer ${key}` }
|
|
2659
|
+
});
|
|
2551
2660
|
if (!res.ok) {
|
|
2552
2661
|
if (res.status === 429 || res.status >= 500) return void 0;
|
|
2553
2662
|
const text2 = await res.text().catch(() => "");
|
|
@@ -2608,43 +2717,6 @@ async function generateSeedanceVideo(req, ctx) {
|
|
|
2608
2717
|
// src/adapters/fal.ts
|
|
2609
2718
|
import { z as z6 } from "zod";
|
|
2610
2719
|
import { createFalClient } from "@fal-ai/client";
|
|
2611
|
-
|
|
2612
|
-
// src/json.ts
|
|
2613
|
-
import { z as z5 } from "zod";
|
|
2614
|
-
var JsonValueSchema = z5.lazy(
|
|
2615
|
-
() => z5.union([
|
|
2616
|
-
z5.string(),
|
|
2617
|
-
z5.number(),
|
|
2618
|
-
z5.boolean(),
|
|
2619
|
-
z5.null(),
|
|
2620
|
-
z5.array(JsonValueSchema),
|
|
2621
|
-
z5.record(z5.string(), JsonValueSchema)
|
|
2622
|
-
])
|
|
2623
|
-
);
|
|
2624
|
-
var JsonObjectSchema = z5.record(z5.string(), JsonValueSchema);
|
|
2625
|
-
async function readErrorBody(res) {
|
|
2626
|
-
const text2 = await res.text().catch(() => "");
|
|
2627
|
-
try {
|
|
2628
|
-
return JsonValueSchema.parse(JSON.parse(text2));
|
|
2629
|
-
} catch {
|
|
2630
|
-
return text2;
|
|
2631
|
-
}
|
|
2632
|
-
}
|
|
2633
|
-
var thrownErrorSchema = z5.object({
|
|
2634
|
-
message: z5.string().optional(),
|
|
2635
|
-
status: z5.number().optional(),
|
|
2636
|
-
statusCode: z5.number().optional(),
|
|
2637
|
-
responseBody: z5.string().optional()
|
|
2638
|
-
});
|
|
2639
|
-
function describeThrown(cause) {
|
|
2640
|
-
const parsed = thrownErrorSchema.safeParse(cause);
|
|
2641
|
-
if (!parsed.success) return { message: String(cause), status: void 0, body: String(cause) };
|
|
2642
|
-
const { message, status, statusCode, responseBody } = parsed.data;
|
|
2643
|
-
const body = responseBody ?? message ?? String(cause);
|
|
2644
|
-
return { message: message ?? String(cause), status: status ?? statusCode, body };
|
|
2645
|
-
}
|
|
2646
|
-
|
|
2647
|
-
// src/adapters/fal.ts
|
|
2648
2720
|
var MUSE_T2I_ENDPOINT = "meta/muse-image/text-to-image";
|
|
2649
2721
|
var MUSE_EDIT_ENDPOINT = "meta/muse-image/edit";
|
|
2650
2722
|
var KLING_O1_ENDPOINT = "fal-ai/kling-video/o1/video-to-video/reference";
|
|
@@ -2656,10 +2728,33 @@ function defaultCreateFalClient(opts) {
|
|
|
2656
2728
|
const client2 = createFalClient(opts);
|
|
2657
2729
|
return {
|
|
2658
2730
|
async subscribe(endpoint, options) {
|
|
2659
|
-
const outcome = await client2.subscribe(endpoint,
|
|
2731
|
+
const outcome = await client2.subscribe(endpoint, options);
|
|
2660
2732
|
const unwrapped = falSubscribePayloadSchema.safeParse(outcome);
|
|
2661
2733
|
if (unwrapped.success) return unwrapped.data.data;
|
|
2662
2734
|
return JsonValueSchema.parse(outcome);
|
|
2735
|
+
},
|
|
2736
|
+
queue: {
|
|
2737
|
+
async submit(endpoint, options) {
|
|
2738
|
+
const submitted = await client2.queue.submit(endpoint, {
|
|
2739
|
+
input: options.input,
|
|
2740
|
+
...options.abortSignal !== void 0 ? { abortSignal: options.abortSignal } : {}
|
|
2741
|
+
});
|
|
2742
|
+
return { requestId: submitted.request_id };
|
|
2743
|
+
},
|
|
2744
|
+
async status(endpoint, options) {
|
|
2745
|
+
const current = await client2.queue.status(endpoint, {
|
|
2746
|
+
requestId: options.requestId,
|
|
2747
|
+
...options.abortSignal !== void 0 ? { abortSignal: options.abortSignal } : {}
|
|
2748
|
+
});
|
|
2749
|
+
return { status: current.status };
|
|
2750
|
+
},
|
|
2751
|
+
async result(endpoint, options) {
|
|
2752
|
+
const outcome = await client2.queue.result(endpoint, {
|
|
2753
|
+
requestId: options.requestId,
|
|
2754
|
+
...options.abortSignal !== void 0 ? { abortSignal: options.abortSignal } : {}
|
|
2755
|
+
});
|
|
2756
|
+
return JsonValueSchema.parse(outcome.data);
|
|
2757
|
+
}
|
|
2663
2758
|
}
|
|
2664
2759
|
};
|
|
2665
2760
|
}
|
|
@@ -2701,15 +2796,17 @@ var falSdkThrownSchema = z6.object({
|
|
|
2701
2796
|
message: z6.string().optional()
|
|
2702
2797
|
});
|
|
2703
2798
|
function falSdkError(cause, model) {
|
|
2704
|
-
if (isModelKitError(cause)) return cause;
|
|
2705
2799
|
const parsed = falSdkThrownSchema.safeParse(cause);
|
|
2706
2800
|
if (parsed.success) {
|
|
2707
2801
|
const status = parsed.data.status ?? parsed.data.statusCode;
|
|
2708
2802
|
const body = parsed.data.body ?? parsed.data.message ?? String(cause);
|
|
2709
|
-
return
|
|
2803
|
+
return classifyThrown("fal", cause, model, { status, body: liftDetail(body) });
|
|
2710
2804
|
}
|
|
2711
2805
|
const info = describeThrown(cause);
|
|
2712
|
-
return
|
|
2806
|
+
return classifyThrown("fal", cause, model, {
|
|
2807
|
+
status: info.status,
|
|
2808
|
+
body: liftDetail(info.body)
|
|
2809
|
+
});
|
|
2713
2810
|
}
|
|
2714
2811
|
function gatewayConfig(ctx) {
|
|
2715
2812
|
const cf = ctx.routing.cloudflare;
|
|
@@ -2791,7 +2888,7 @@ async function passthroughRequest(ctx, endpoint, input) {
|
|
|
2791
2888
|
}
|
|
2792
2889
|
return JsonValueSchema.parse(await resultRes.json());
|
|
2793
2890
|
}
|
|
2794
|
-
|
|
2891
|
+
function falClientOf(ctx, deps) {
|
|
2795
2892
|
const falKey = ctx.keys.fal;
|
|
2796
2893
|
if (!falKey) {
|
|
2797
2894
|
throw new ModelKitError({
|
|
@@ -2802,12 +2899,19 @@ async function subscribe(ctx, deps, endpoint, input) {
|
|
|
2802
2899
|
retryable: false
|
|
2803
2900
|
});
|
|
2804
2901
|
}
|
|
2805
|
-
|
|
2902
|
+
return deps.createFalClient({ credentials: falKey, fetch: ctx.fetch });
|
|
2903
|
+
}
|
|
2904
|
+
async function subscribe(ctx, deps, endpoint, input) {
|
|
2905
|
+
const client2 = falClientOf(ctx, deps);
|
|
2906
|
+
const options = {
|
|
2907
|
+
input,
|
|
2908
|
+
...ctx.signal !== void 0 ? { abortSignal: ctx.signal } : {}
|
|
2909
|
+
};
|
|
2806
2910
|
try {
|
|
2807
2911
|
return await withRetry(
|
|
2808
2912
|
async () => {
|
|
2809
2913
|
try {
|
|
2810
|
-
return await client2.subscribe(endpoint,
|
|
2914
|
+
return await client2.subscribe(endpoint, options);
|
|
2811
2915
|
} catch (cause) {
|
|
2812
2916
|
throw falSdkError(cause, ctx.model.id);
|
|
2813
2917
|
}
|
|
@@ -2941,13 +3045,14 @@ function klingO1Input(req) {
|
|
|
2941
3045
|
});
|
|
2942
3046
|
}
|
|
2943
3047
|
const duration = Math.min(10, Math.max(3, Math.round(req.durationSeconds ?? 5)));
|
|
2944
|
-
const ratio = req.aspectRatio === "16:9" || req.aspectRatio === "9:16" || req.aspectRatio === "1:1" ? req.aspectRatio : "auto";
|
|
2945
3048
|
const input = {
|
|
2946
3049
|
prompt: req.prompt,
|
|
2947
3050
|
video_url: source,
|
|
2948
|
-
duration: String(duration)
|
|
2949
|
-
aspect_ratio: ratio
|
|
3051
|
+
duration: String(duration)
|
|
2950
3052
|
};
|
|
3053
|
+
if (req.aspectRatio !== "adaptive") {
|
|
3054
|
+
input.aspect_ratio = req.aspectRatio === "16:9" || req.aspectRatio === "9:16" || req.aspectRatio === "1:1" ? req.aspectRatio : "auto";
|
|
3055
|
+
}
|
|
2951
3056
|
const refs = (req.referenceImages ?? []).map(refToUrl);
|
|
2952
3057
|
if (refs.length > 0) input.image_urls = refs;
|
|
2953
3058
|
return input;
|
|
@@ -2976,13 +3081,7 @@ async function generateFalVideo(req, ctx, deps) {
|
|
|
2976
3081
|
if (ctx.routing.fal === "cloudflare-passthrough") {
|
|
2977
3082
|
return await passthroughVideoJob(ctx, req, KLING_O1_ENDPOINT, input);
|
|
2978
3083
|
}
|
|
2979
|
-
|
|
2980
|
-
return completedVideoJob(
|
|
2981
|
-
ctx,
|
|
2982
|
-
req,
|
|
2983
|
-
extractVideoUrl(result2, KLING_O1_ENDPOINT, ctx.model.id),
|
|
2984
|
-
result2
|
|
2985
|
-
);
|
|
3084
|
+
return await submitQueueJob(ctx, req, deps, KLING_O1_ENDPOINT, input);
|
|
2986
3085
|
}
|
|
2987
3086
|
const family = minimaxFamily(providerModelId);
|
|
2988
3087
|
const refs = {
|
|
@@ -3011,19 +3110,81 @@ async function generateFalVideo(req, ctx, deps) {
|
|
|
3011
3110
|
if (ctx.routing.fal === "cloudflare-passthrough") {
|
|
3012
3111
|
return await passthroughVideoJob(ctx, req, endpoint, base);
|
|
3013
3112
|
}
|
|
3014
|
-
|
|
3015
|
-
|
|
3113
|
+
return await submitQueueJob(ctx, req, deps, endpoint, base);
|
|
3114
|
+
}
|
|
3115
|
+
async function submitQueueJob(ctx, req, deps, endpoint, input) {
|
|
3116
|
+
const client2 = falClientOf(ctx, deps);
|
|
3117
|
+
let submitted;
|
|
3118
|
+
try {
|
|
3119
|
+
submitted = await withRetry(
|
|
3120
|
+
async () => {
|
|
3121
|
+
try {
|
|
3122
|
+
return await client2.queue.submit(endpoint, {
|
|
3123
|
+
input,
|
|
3124
|
+
...ctx.signal !== void 0 ? { abortSignal: ctx.signal } : {}
|
|
3125
|
+
});
|
|
3126
|
+
} catch (cause) {
|
|
3127
|
+
throw falSdkError(cause, ctx.model.id);
|
|
3128
|
+
}
|
|
3129
|
+
},
|
|
3130
|
+
ctx.signal !== void 0 ? { signal: ctx.signal } : {}
|
|
3131
|
+
);
|
|
3132
|
+
} catch (cause) {
|
|
3133
|
+
throw falSdkError(cause, ctx.model.id);
|
|
3134
|
+
}
|
|
3135
|
+
return queuedVideoJob(ctx, req, client2, endpoint, submitted.requestId);
|
|
3016
3136
|
}
|
|
3017
|
-
function
|
|
3137
|
+
function queuedVideoJob(ctx, req, client2, endpoint, requestId) {
|
|
3138
|
+
const readStatus = async () => {
|
|
3139
|
+
try {
|
|
3140
|
+
const options = {
|
|
3141
|
+
requestId,
|
|
3142
|
+
...ctx.signal !== void 0 ? { abortSignal: ctx.signal } : {}
|
|
3143
|
+
};
|
|
3144
|
+
return (await client2.queue.status(endpoint, options)).status;
|
|
3145
|
+
} catch (cause) {
|
|
3146
|
+
throw falSdkError(cause, ctx.model.id);
|
|
3147
|
+
}
|
|
3148
|
+
};
|
|
3018
3149
|
const duration = req.durationSeconds ?? 5;
|
|
3019
|
-
const result = { video: { url }, usage: videoUsage(ctx, req, duration), raw };
|
|
3020
3150
|
return {
|
|
3021
|
-
jobId:
|
|
3151
|
+
jobId: requestId,
|
|
3022
3152
|
async poll() {
|
|
3023
|
-
|
|
3153
|
+
try {
|
|
3154
|
+
const status = await readStatus();
|
|
3155
|
+
if (status === "COMPLETED") return { status: "succeeded" };
|
|
3156
|
+
if (status === "IN_QUEUE") return { status: "pending" };
|
|
3157
|
+
return { status: "running" };
|
|
3158
|
+
} catch (cause) {
|
|
3159
|
+
if (isModelKitError(cause) && !cause.retryable)
|
|
3160
|
+
return { status: "failed" };
|
|
3161
|
+
return { status: "pending" };
|
|
3162
|
+
}
|
|
3024
3163
|
},
|
|
3025
|
-
async result() {
|
|
3026
|
-
|
|
3164
|
+
async result(opts) {
|
|
3165
|
+
const signal = opts?.signal ?? ctx.signal;
|
|
3166
|
+
const pollOptions = {
|
|
3167
|
+
intervalMs: opts?.pollIntervalMs ?? PASSTHROUGH_POLL_MS,
|
|
3168
|
+
timeoutMs: opts?.timeoutMs ?? 15 * 6e4
|
|
3169
|
+
};
|
|
3170
|
+
if (signal !== void 0) pollOptions.signal = signal;
|
|
3171
|
+
const queueOptions = {
|
|
3172
|
+
requestId,
|
|
3173
|
+
...signal !== void 0 ? { abortSignal: signal } : {}
|
|
3174
|
+
};
|
|
3175
|
+
const payload = await pollUntil(async () => {
|
|
3176
|
+
try {
|
|
3177
|
+
const current = await client2.queue.status(endpoint, queueOptions);
|
|
3178
|
+
if (current.status !== "COMPLETED") return void 0;
|
|
3179
|
+
return await client2.queue.result(endpoint, queueOptions);
|
|
3180
|
+
} catch (cause) {
|
|
3181
|
+
const err = falSdkError(cause, ctx.model.id);
|
|
3182
|
+
if (err.retryable) return void 0;
|
|
3183
|
+
throw err;
|
|
3184
|
+
}
|
|
3185
|
+
}, pollOptions);
|
|
3186
|
+
const url = extractVideoUrl(payload, endpoint, ctx.model.id);
|
|
3187
|
+
return { video: { url }, usage: videoUsage(ctx, req, duration), raw: payload };
|
|
3027
3188
|
}
|
|
3028
3189
|
};
|
|
3029
3190
|
}
|
|
@@ -3376,9 +3537,7 @@ function sdkStatus(cause) {
|
|
|
3376
3537
|
return describeThrown(cause).status;
|
|
3377
3538
|
}
|
|
3378
3539
|
function throwSdkError(cause, model) {
|
|
3379
|
-
|
|
3380
|
-
const info = describeThrown(cause);
|
|
3381
|
-
throw classifyHttpError(info.status, info.body, "google-genai", model);
|
|
3540
|
+
throw classifyThrown("google-genai", cause, model);
|
|
3382
3541
|
}
|
|
3383
3542
|
function toBase64(bytes) {
|
|
3384
3543
|
return Buffer.from(bytes).toString("base64");
|
|
@@ -3582,12 +3741,17 @@ async function generateOmniVideo(req, ctx, createGenAIClient) {
|
|
|
3582
3741
|
const duration = req.durationSeconds ?? 8;
|
|
3583
3742
|
const images = req.referenceImages ?? [];
|
|
3584
3743
|
const videos = req.referenceVideos ?? [];
|
|
3585
|
-
const task = req.sourceVideo ? "edit" :
|
|
3586
|
-
const
|
|
3587
|
-
|
|
3588
|
-
|
|
3589
|
-
|
|
3590
|
-
|
|
3744
|
+
const task = req.sourceVideo ? "edit" : req.firstFrame ? "image_to_video" : images.length > 0 || videos.length > 0 ? "reference_to_video" : "text_to_video";
|
|
3745
|
+
const isOmniV1 = providerModelId === "gemini-omni-flash-preview";
|
|
3746
|
+
const responseFormat = { type: "video", delivery: "uri" };
|
|
3747
|
+
if (req.sourceVideo === void 0 && req.aspectRatio !== void 0 && req.aspectRatio !== "adaptive") {
|
|
3748
|
+
responseFormat.aspect_ratio = toOmniAspect(req.aspectRatio);
|
|
3749
|
+
}
|
|
3750
|
+
if (!isOmniV1) {
|
|
3751
|
+
const omniResolution = toOmniResolution(req.resolution);
|
|
3752
|
+
if (omniResolution !== void 0) responseFormat.resolution = omniResolution;
|
|
3753
|
+
}
|
|
3754
|
+
if (req.durationSeconds !== void 0) responseFormat.duration = `${req.durationSeconds}s`;
|
|
3591
3755
|
const client2 = createGenAIClient({ apiKey });
|
|
3592
3756
|
const uploadedByUri = /* @__PURE__ */ new Map();
|
|
3593
3757
|
const uploadedNames = [];
|
|
@@ -3611,7 +3775,8 @@ async function generateOmniVideo(req, ctx, createGenAIClient) {
|
|
|
3611
3775
|
model: providerModelId,
|
|
3612
3776
|
input,
|
|
3613
3777
|
response_format: responseFormat,
|
|
3614
|
-
generation_config: { video_config: { task } }
|
|
3778
|
+
generation_config: { video_config: { task } },
|
|
3779
|
+
store: true
|
|
3615
3780
|
});
|
|
3616
3781
|
const createRetryOptions = { attempts: 3 };
|
|
3617
3782
|
if (ctx.signal !== void 0) createRetryOptions.signal = ctx.signal;
|
|
@@ -3693,23 +3858,14 @@ async function generateOmniVideo(req, ctx, createGenAIClient) {
|
|
|
3693
3858
|
};
|
|
3694
3859
|
return inline;
|
|
3695
3860
|
});
|
|
3696
|
-
const inlineRetryOptions = { attempts: 3 };
|
|
3697
|
-
if (ctx.signal !== void 0) inlineRetryOptions.signal = ctx.signal;
|
|
3698
3861
|
try {
|
|
3699
|
-
interaction = await
|
|
3700
|
-
try {
|
|
3701
|
-
return await callCreate(inlineParts);
|
|
3702
|
-
} catch (inlineCause) {
|
|
3703
|
-
throwSdkError(inlineCause, modelId);
|
|
3704
|
-
}
|
|
3705
|
-
}, inlineRetryOptions);
|
|
3862
|
+
interaction = await callCreate(inlineParts);
|
|
3706
3863
|
} catch (inlineCause) {
|
|
3707
3864
|
throwSdkError(inlineCause, modelId);
|
|
3708
3865
|
}
|
|
3709
3866
|
}
|
|
3710
|
-
}
|
|
3867
|
+
} finally {
|
|
3711
3868
|
await cleanupUploads();
|
|
3712
|
-
throw cause;
|
|
3713
3869
|
}
|
|
3714
3870
|
const jobId = interaction.id ?? "gemini-omni-interaction";
|
|
3715
3871
|
const usage2 = videoUsage2(ctx, req, duration);
|
|
@@ -3738,47 +3894,43 @@ async function generateOmniVideo(req, ctx, createGenAIClient) {
|
|
|
3738
3894
|
timeoutMs: opts?.timeoutMs ?? RESULT_TIMEOUT_MS2
|
|
3739
3895
|
};
|
|
3740
3896
|
if (signal !== void 0) pollOptions.signal = signal;
|
|
3741
|
-
|
|
3742
|
-
const
|
|
3743
|
-
|
|
3744
|
-
|
|
3745
|
-
|
|
3746
|
-
|
|
3747
|
-
|
|
3748
|
-
|
|
3749
|
-
|
|
3750
|
-
|
|
3751
|
-
|
|
3752
|
-
);
|
|
3753
|
-
}
|
|
3754
|
-
return void 0;
|
|
3755
|
-
}, pollOptions);
|
|
3756
|
-
const video = extractOmniVideo(done, modelId);
|
|
3757
|
-
if (video.data) {
|
|
3758
|
-
return {
|
|
3759
|
-
video: {
|
|
3760
|
-
bytes: Buffer.from(video.data, "base64"),
|
|
3761
|
-
mime: video.mime_type ?? "video/mp4"
|
|
3762
|
-
},
|
|
3763
|
-
usage: usage2,
|
|
3764
|
-
raw: done
|
|
3765
|
-
};
|
|
3897
|
+
const done = await pollUntil(async () => {
|
|
3898
|
+
const current = await getInteraction();
|
|
3899
|
+
const status = (current.status ?? "").toUpperCase();
|
|
3900
|
+
if (status === "COMPLETED") return current;
|
|
3901
|
+
if (status === "FAILED") {
|
|
3902
|
+
throw classifyHttpError(
|
|
3903
|
+
void 0,
|
|
3904
|
+
`Gemini Omni interaction failed: ${JSON.stringify(current).slice(0, 500)}`,
|
|
3905
|
+
"google-genai",
|
|
3906
|
+
modelId
|
|
3907
|
+
);
|
|
3766
3908
|
}
|
|
3767
|
-
|
|
3768
|
-
|
|
3769
|
-
|
|
3770
|
-
|
|
3771
|
-
|
|
3772
|
-
|
|
3773
|
-
|
|
3774
|
-
|
|
3775
|
-
|
|
3776
|
-
|
|
3777
|
-
|
|
3778
|
-
|
|
3779
|
-
} finally {
|
|
3780
|
-
await cleanupUploads();
|
|
3909
|
+
return void 0;
|
|
3910
|
+
}, pollOptions);
|
|
3911
|
+
const video = extractOmniVideo(done, modelId);
|
|
3912
|
+
if (video.data) {
|
|
3913
|
+
return {
|
|
3914
|
+
video: {
|
|
3915
|
+
bytes: Buffer.from(video.data, "base64"),
|
|
3916
|
+
mime: video.mime_type ?? "video/mp4"
|
|
3917
|
+
},
|
|
3918
|
+
usage: usage2,
|
|
3919
|
+
raw: done
|
|
3920
|
+
};
|
|
3781
3921
|
}
|
|
3922
|
+
if (video.uri)
|
|
3923
|
+
return {
|
|
3924
|
+
video: await downloadVideo(ctx, video.uri, apiKey, signal),
|
|
3925
|
+
usage: usage2,
|
|
3926
|
+
raw: done
|
|
3927
|
+
};
|
|
3928
|
+
throw classifyHttpError(
|
|
3929
|
+
void 0,
|
|
3930
|
+
"No video content in Gemini Omni response",
|
|
3931
|
+
"google-genai",
|
|
3932
|
+
modelId
|
|
3933
|
+
);
|
|
3782
3934
|
}
|
|
3783
3935
|
};
|
|
3784
3936
|
}
|
|
@@ -3947,8 +4099,14 @@ function createGoogleImageAdapter(deps = defaultGoogleImageDeps) {
|
|
|
3947
4099
|
content.push({ type: "text", text: req.prompt });
|
|
3948
4100
|
void ctx.call.postCropToAspect;
|
|
3949
4101
|
const imageConfig = {};
|
|
3950
|
-
if (req.aspectRatio !== void 0
|
|
4102
|
+
if (req.aspectRatio !== void 0 && req.aspectRatio !== "adaptive")
|
|
4103
|
+
imageConfig.aspectRatio = req.aspectRatio;
|
|
3951
4104
|
if (req.size !== void 0) imageConfig.imageSize = req.size;
|
|
4105
|
+
const googleOptions = {
|
|
4106
|
+
imageConfig,
|
|
4107
|
+
responseModalities: ["IMAGE"]
|
|
4108
|
+
};
|
|
4109
|
+
if (req.safetySettings !== void 0) googleOptions.safetySettings = req.safetySettings;
|
|
3952
4110
|
const retryOptions = {};
|
|
3953
4111
|
if (ctx.signal !== void 0) retryOptions.signal = ctx.signal;
|
|
3954
4112
|
const result = await withRetry(async () => {
|
|
@@ -3960,22 +4118,7 @@ function createGoogleImageAdapter(deps = defaultGoogleImageDeps) {
|
|
|
3960
4118
|
messages: [{ role: "user", content }],
|
|
3961
4119
|
maxRetries: 0,
|
|
3962
4120
|
providerOptions: {
|
|
3963
|
-
google:
|
|
3964
|
-
imageConfig,
|
|
3965
|
-
responseModalities: ["IMAGE"],
|
|
3966
|
-
safetySettings: [
|
|
3967
|
-
{
|
|
3968
|
-
category: "HARM_CATEGORY_SEXUALLY_EXPLICIT",
|
|
3969
|
-
threshold: "OFF"
|
|
3970
|
-
},
|
|
3971
|
-
{ category: "HARM_CATEGORY_HATE_SPEECH", threshold: "OFF" },
|
|
3972
|
-
{
|
|
3973
|
-
category: "HARM_CATEGORY_DANGEROUS_CONTENT",
|
|
3974
|
-
threshold: "OFF"
|
|
3975
|
-
},
|
|
3976
|
-
{ category: "HARM_CATEGORY_HARASSMENT", threshold: "OFF" }
|
|
3977
|
-
]
|
|
3978
|
-
}
|
|
4121
|
+
google: googleOptions
|
|
3979
4122
|
},
|
|
3980
4123
|
abortSignal: signal
|
|
3981
4124
|
});
|
|
@@ -4004,6 +4147,10 @@ function createGoogleImageAdapter(deps = defaultGoogleImageDeps) {
|
|
|
4004
4147
|
imageQuality: "auto"
|
|
4005
4148
|
};
|
|
4006
4149
|
if (req.size !== void 0) usage2.imageSize = req.size;
|
|
4150
|
+
if (result.usage?.inputTokens !== void 0)
|
|
4151
|
+
usage2.inputTokens = result.usage.inputTokens;
|
|
4152
|
+
if (result.usage?.outputTokens !== void 0)
|
|
4153
|
+
usage2.outputTokens = result.usage.outputTokens;
|
|
4007
4154
|
return { images, usage: usage2, raw: result };
|
|
4008
4155
|
}
|
|
4009
4156
|
};
|
|
@@ -4158,6 +4305,7 @@ var KLING_MAX_INTERVAL_MS = 1e4;
|
|
|
4158
4305
|
var KLING_TIMEOUT_MS = 15 * 6e4;
|
|
4159
4306
|
var DOP_INTERVAL_MS = 5e3;
|
|
4160
4307
|
var DOP_TIMEOUT_MS = 5 * 6e4;
|
|
4308
|
+
var DOP_FALLBACK_DURATION_SECONDS = 5;
|
|
4161
4309
|
var DEFAULT_NEGATIVE_PROMPT = "text, watermark, copyright, blur, low quality, distortion, abstract, weird, deformed";
|
|
4162
4310
|
function credentials(ctx) {
|
|
4163
4311
|
const key = ctx.keys.higgsfield;
|
|
@@ -4232,6 +4380,18 @@ function requestInit(ctx, init) {
|
|
|
4232
4380
|
if (ctx.signal !== void 0) request.signal = ctx.signal;
|
|
4233
4381
|
return request;
|
|
4234
4382
|
}
|
|
4383
|
+
async function createRequest(ctx, url, init) {
|
|
4384
|
+
let res;
|
|
4385
|
+
try {
|
|
4386
|
+
res = await ctx.fetch(url, requestInit(ctx, init));
|
|
4387
|
+
} catch (cause) {
|
|
4388
|
+
throw classifyThrown("higgsfield", cause, ctx.model.id);
|
|
4389
|
+
}
|
|
4390
|
+
if (!res.ok) {
|
|
4391
|
+
throw classifyHttpError(res.status, await readBody2(res), "higgsfield", ctx.model.id);
|
|
4392
|
+
}
|
|
4393
|
+
return res;
|
|
4394
|
+
}
|
|
4235
4395
|
async function generateKlingVideo(req, ctx) {
|
|
4236
4396
|
const firstFrame = req.firstFrame ? refToUrl2(req.firstFrame) : void 0;
|
|
4237
4397
|
if (!firstFrame) {
|
|
@@ -4250,26 +4410,16 @@ async function generateKlingVideo(req, ctx) {
|
|
|
4250
4410
|
negative_prompt: req.negativePrompt ?? DEFAULT_NEGATIVE_PROMPT
|
|
4251
4411
|
};
|
|
4252
4412
|
if (req.durationSeconds !== void 0) body.duration = req.durationSeconds;
|
|
4253
|
-
if (req.aspectRatio !== void 0
|
|
4413
|
+
if (req.aspectRatio !== void 0 && req.aspectRatio !== "adaptive")
|
|
4414
|
+
body.aspect_ratio = req.aspectRatio;
|
|
4254
4415
|
if (req.lastFrame) body.last_image_url = refToUrl2(req.lastFrame);
|
|
4255
4416
|
const endpoint = klingEndpoint(ctx.model.providerModelId);
|
|
4256
|
-
|
|
4257
|
-
|
|
4258
|
-
|
|
4259
|
-
|
|
4260
|
-
|
|
4261
|
-
|
|
4262
|
-
} catch (cause) {
|
|
4263
|
-
throw networkError(cause, ctx);
|
|
4264
|
-
}
|
|
4265
|
-
if (!createRes.ok) {
|
|
4266
|
-
throw classifyHttpError(
|
|
4267
|
-
createRes.status,
|
|
4268
|
-
await readBody2(createRes),
|
|
4269
|
-
"higgsfield",
|
|
4270
|
-
ctx.model.id
|
|
4271
|
-
);
|
|
4272
|
-
}
|
|
4417
|
+
const retryOptions = {};
|
|
4418
|
+
if (ctx.signal !== void 0) retryOptions.signal = ctx.signal;
|
|
4419
|
+
const createRes = await withRetry(
|
|
4420
|
+
() => createRequest(ctx, endpoint, { method: "POST", body: JSON.stringify(body) }),
|
|
4421
|
+
retryOptions
|
|
4422
|
+
);
|
|
4273
4423
|
const created = klingCreateSchema.safeParse(await createRes.json());
|
|
4274
4424
|
if (!created.success) {
|
|
4275
4425
|
throw new ModelKitError({
|
|
@@ -4349,11 +4499,6 @@ async function generateKlingVideo(req, ctx) {
|
|
|
4349
4499
|
}
|
|
4350
4500
|
};
|
|
4351
4501
|
}
|
|
4352
|
-
function networkError(cause, ctx) {
|
|
4353
|
-
if (isModelKitError(cause)) return cause;
|
|
4354
|
-
const info = describeThrown(cause);
|
|
4355
|
-
return classifyHttpError(info.status, info.body, "higgsfield", ctx.model.id);
|
|
4356
|
-
}
|
|
4357
4502
|
var dopMotionOptionsSchema = z10.object({
|
|
4358
4503
|
modelkit: z10.object({ motion: z10.string().optional() }).optional()
|
|
4359
4504
|
});
|
|
@@ -4425,26 +4570,15 @@ async function generateDopVideo(req, ctx) {
|
|
|
4425
4570
|
params.input_images_end = [{ type: "image_url", image_url: refToUrl2(req.lastFrame) }];
|
|
4426
4571
|
}
|
|
4427
4572
|
if (req.seed !== void 0) params.seed = req.seed;
|
|
4428
|
-
|
|
4429
|
-
|
|
4430
|
-
|
|
4431
|
-
|
|
4432
|
-
|
|
4433
|
-
|
|
4434
|
-
|
|
4435
|
-
|
|
4436
|
-
|
|
4437
|
-
} catch (cause) {
|
|
4438
|
-
throw networkError(cause, ctx);
|
|
4439
|
-
}
|
|
4440
|
-
if (!createRes.ok) {
|
|
4441
|
-
throw classifyHttpError(
|
|
4442
|
-
createRes.status,
|
|
4443
|
-
await readBody2(createRes),
|
|
4444
|
-
"higgsfield",
|
|
4445
|
-
ctx.model.id
|
|
4446
|
-
);
|
|
4447
|
-
}
|
|
4573
|
+
const retryOptions = {};
|
|
4574
|
+
if (ctx.signal !== void 0) retryOptions.signal = ctx.signal;
|
|
4575
|
+
const createRes = await withRetry(
|
|
4576
|
+
() => createRequest(ctx, DOP_ENDPOINT, {
|
|
4577
|
+
method: "POST",
|
|
4578
|
+
body: JSON.stringify({ params, webhook: null })
|
|
4579
|
+
}),
|
|
4580
|
+
retryOptions
|
|
4581
|
+
);
|
|
4448
4582
|
const created = dopCreateSchema.safeParse(await createRes.json());
|
|
4449
4583
|
if (!created.success) {
|
|
4450
4584
|
throw new ModelKitError({
|
|
@@ -4513,7 +4647,10 @@ async function generateDopVideo(req, ctx) {
|
|
|
4513
4647
|
};
|
|
4514
4648
|
if (dopSignal !== void 0) pollSettings.signal = dopSignal;
|
|
4515
4649
|
const url = await pollUntil(check, pollSettings);
|
|
4516
|
-
const result = {
|
|
4650
|
+
const result = {
|
|
4651
|
+
video: { url },
|
|
4652
|
+
usage: videoUsage3(ctx, req, req.durationSeconds ?? DOP_FALLBACK_DURATION_SECONDS)
|
|
4653
|
+
};
|
|
4517
4654
|
return result;
|
|
4518
4655
|
}
|
|
4519
4656
|
};
|
|
@@ -4535,7 +4672,7 @@ function aspectRatioToSize(ratio, tier) {
|
|
|
4535
4672
|
};
|
|
4536
4673
|
const MIN_PIXELS = 655360;
|
|
4537
4674
|
const MAX_PIXELS = 8294400;
|
|
4538
|
-
const maxLong = TIER_LONG_EDGE[tier];
|
|
4675
|
+
const maxLong = TIER_LONG_EDGE[tier] ?? 1024;
|
|
4539
4676
|
const RATIO_MAP = /* @__PURE__ */ new Map([
|
|
4540
4677
|
["1:1", [1, 1]],
|
|
4541
4678
|
["16:9", [16, 9]],
|
|
@@ -4695,28 +4832,16 @@ var openaiImageAdapter = {
|
|
|
4695
4832
|
const usageParsed = openaiUsageSchema.safeParse(response.usage);
|
|
4696
4833
|
const inputTokens = usageParsed.success ? usageParsed.data.input_tokens : void 0;
|
|
4697
4834
|
const outputTokens = usageParsed.success ? usageParsed.data.output_tokens : void 0;
|
|
4698
|
-
|
|
4699
|
-
|
|
4700
|
-
|
|
4701
|
-
|
|
4702
|
-
|
|
4703
|
-
|
|
4704
|
-
|
|
4705
|
-
|
|
4706
|
-
|
|
4707
|
-
|
|
4708
|
-
if (inputTokens !== void 0) usage2.inputTokens = inputTokens;
|
|
4709
|
-
if (outputTokens !== void 0) usage2.outputTokens = outputTokens;
|
|
4710
|
-
} else {
|
|
4711
|
-
usage2 = {
|
|
4712
|
-
model: ctx.model.id,
|
|
4713
|
-
provider: "openai-image",
|
|
4714
|
-
modality: "IMAGE",
|
|
4715
|
-
unit: "images",
|
|
4716
|
-
quantity: images.length,
|
|
4717
|
-
imageQuality: quality
|
|
4718
|
-
};
|
|
4719
|
-
}
|
|
4835
|
+
const usage2 = {
|
|
4836
|
+
model: ctx.model.id,
|
|
4837
|
+
provider: "openai-image",
|
|
4838
|
+
modality: "IMAGE",
|
|
4839
|
+
unit: "images",
|
|
4840
|
+
quantity: images.length,
|
|
4841
|
+
imageQuality: quality
|
|
4842
|
+
};
|
|
4843
|
+
if (inputTokens !== void 0) usage2.inputTokens = inputTokens;
|
|
4844
|
+
if (outputTokens !== void 0) usage2.outputTokens = outputTokens;
|
|
4720
4845
|
if (req.size !== void 0) usage2.imageSize = req.size;
|
|
4721
4846
|
return { images, usage: usage2, raw: response };
|
|
4722
4847
|
}
|
|
@@ -4769,7 +4894,12 @@ var NANO_BANANA_RATIOS = /* @__PURE__ */ new Set([
|
|
|
4769
4894
|
]);
|
|
4770
4895
|
async function refToBytes(ctx, ref) {
|
|
4771
4896
|
if ("bytes" in ref) return { bytes: ref.bytes, mime: ref.mime };
|
|
4772
|
-
|
|
4897
|
+
let res;
|
|
4898
|
+
try {
|
|
4899
|
+
res = await ctx.fetch(ref.url);
|
|
4900
|
+
} catch (cause) {
|
|
4901
|
+
throw classifyThrown("prodia", cause, ctx.model.id);
|
|
4902
|
+
}
|
|
4773
4903
|
if (!res.ok) {
|
|
4774
4904
|
const text2 = await res.text().catch(() => "");
|
|
4775
4905
|
throw classifyHttpError(res.status, text2, "prodia", ctx.model.id);
|
|
@@ -4939,8 +5069,7 @@ async function generateProdiaImage(req, ctx) {
|
|
|
4939
5069
|
body: form
|
|
4940
5070
|
});
|
|
4941
5071
|
} catch (err) {
|
|
4942
|
-
|
|
4943
|
-
throw transportError("prodia", err, ctx.model.id);
|
|
5072
|
+
throw classifyThrown("prodia", err, ctx.model.id);
|
|
4944
5073
|
}
|
|
4945
5074
|
if (!attemptRes.ok) {
|
|
4946
5075
|
const text2 = await attemptRes.text().catch(() => "");
|
|
@@ -4949,8 +5078,7 @@ async function generateProdiaImage(req, ctx) {
|
|
|
4949
5078
|
return attemptRes;
|
|
4950
5079
|
}, retryOpts);
|
|
4951
5080
|
} catch (err) {
|
|
4952
|
-
|
|
4953
|
-
throw transportError("prodia", err, ctx.model.id);
|
|
5081
|
+
throw classifyThrown("prodia", err, ctx.model.id);
|
|
4954
5082
|
}
|
|
4955
5083
|
const bytes = parseImageResponse(
|
|
4956
5084
|
new Uint8Array(await res.arrayBuffer()),
|
|
@@ -5022,7 +5150,7 @@ function replicateError(cause, ctx) {
|
|
|
5022
5150
|
const info = describeThrown(cause);
|
|
5023
5151
|
const nested = replicateResponseStatusSchema.safeParse(cause);
|
|
5024
5152
|
const status = info.status ?? (nested.success ? nested.data.response?.status : void 0);
|
|
5025
|
-
return
|
|
5153
|
+
return classifyThrown("replicate", cause, ctx.model.id, { status, body: info.body });
|
|
5026
5154
|
}
|
|
5027
5155
|
function isLower(id) {
|
|
5028
5156
|
return id.toLowerCase();
|
|
@@ -5169,6 +5297,9 @@ function isUpscaler(providerModelId) {
|
|
|
5169
5297
|
const id = isLower(providerModelId);
|
|
5170
5298
|
return id.includes("upscal") || id.includes("crystal") || id.includes("topaz");
|
|
5171
5299
|
}
|
|
5300
|
+
function isTopazUpscaler(providerModelId) {
|
|
5301
|
+
return isLower(providerModelId).includes("topazlabs/image-upscale");
|
|
5302
|
+
}
|
|
5172
5303
|
function isQwen(providerModelId) {
|
|
5173
5304
|
return isLower(providerModelId).includes("qwen");
|
|
5174
5305
|
}
|
|
@@ -5218,8 +5349,36 @@ function wanImageSize(aspectRatio, size) {
|
|
|
5218
5349
|
}
|
|
5219
5350
|
async function generateReplicateImage(req, ctx, deps) {
|
|
5220
5351
|
const id = ctx.model.providerModelId;
|
|
5221
|
-
|
|
5222
|
-
if (
|
|
5352
|
+
let input;
|
|
5353
|
+
if (isTopazUpscaler(id)) {
|
|
5354
|
+
const first = (req.references ?? [])[0];
|
|
5355
|
+
if (!first) {
|
|
5356
|
+
throw new ModelKitError({
|
|
5357
|
+
code: "missing_input",
|
|
5358
|
+
message: `${ctx.model.id} requires a reference image to upscale`,
|
|
5359
|
+
provider: "replicate",
|
|
5360
|
+
model: ctx.model.id,
|
|
5361
|
+
retryable: false
|
|
5362
|
+
});
|
|
5363
|
+
}
|
|
5364
|
+
let format = req.outputFormat === "jpeg" ? "jpg" : req.outputFormat ?? "png";
|
|
5365
|
+
if (format !== "png" && format !== "jpg") {
|
|
5366
|
+
ctx.warnings.push({
|
|
5367
|
+
code: "option_ignored",
|
|
5368
|
+
field: "outputFormat",
|
|
5369
|
+
from: format,
|
|
5370
|
+
message: "topazlabs/image-upscale supports only png and jpg; using png"
|
|
5371
|
+
});
|
|
5372
|
+
format = "png";
|
|
5373
|
+
}
|
|
5374
|
+
input = {
|
|
5375
|
+
image: refToUrl3(first),
|
|
5376
|
+
enhance_model: "Standard V2",
|
|
5377
|
+
output_format: format,
|
|
5378
|
+
upscale_factor: `${req.scaleFactor ?? 2}x`,
|
|
5379
|
+
face_enhancement: true
|
|
5380
|
+
};
|
|
5381
|
+
} else if (isUpscaler(id)) {
|
|
5223
5382
|
const refs = req.references ?? [];
|
|
5224
5383
|
const first = refs[0];
|
|
5225
5384
|
if (!first) {
|
|
@@ -5231,24 +5390,29 @@ async function generateReplicateImage(req, ctx, deps) {
|
|
|
5231
5390
|
retryable: false
|
|
5232
5391
|
});
|
|
5233
5392
|
}
|
|
5234
|
-
|
|
5235
|
-
|
|
5236
|
-
|
|
5237
|
-
|
|
5393
|
+
const imageInput = { prompt: req.prompt };
|
|
5394
|
+
imageInput.image = refToUrl3(first);
|
|
5395
|
+
imageInput.creativity = 0;
|
|
5396
|
+
imageInput.scale_factor = 2;
|
|
5397
|
+
imageInput.output_format = "png";
|
|
5398
|
+
input = imageInput;
|
|
5238
5399
|
} else if (isWanImage(id)) {
|
|
5239
5400
|
const refs = (req.references ?? []).map(refToUrl3);
|
|
5240
|
-
|
|
5241
|
-
|
|
5401
|
+
const imageInput = { prompt: req.prompt };
|
|
5402
|
+
if (refs.length > 0) imageInput.images = refs;
|
|
5403
|
+
imageInput.size = wanImageSize(req.aspectRatio, req.size);
|
|
5404
|
+
input = imageInput;
|
|
5242
5405
|
} else if (isQwen(id)) {
|
|
5243
5406
|
const refs = (req.references ?? []).map(refToUrl3);
|
|
5244
5407
|
const firstUrl = refs[0];
|
|
5408
|
+
const imageInput = { prompt: req.prompt };
|
|
5245
5409
|
if (firstUrl !== void 0) {
|
|
5246
|
-
|
|
5247
|
-
if (!isQwenEditPlus(id))
|
|
5410
|
+
imageInput.image = firstUrl;
|
|
5411
|
+
if (!isQwenEditPlus(id)) imageInput.match_input_image = true;
|
|
5248
5412
|
}
|
|
5249
5413
|
const ratios = isQwenEditPlus(id) ? QWEN_EDIT_RATIOS : QWEN_IMAGE_RATIOS;
|
|
5250
5414
|
if (req.aspectRatio !== void 0) {
|
|
5251
|
-
if (ratios.has(req.aspectRatio))
|
|
5415
|
+
if (ratios.has(req.aspectRatio)) imageInput.aspect_ratio = req.aspectRatio;
|
|
5252
5416
|
else
|
|
5253
5417
|
ctx.warnings.push({
|
|
5254
5418
|
code: "option_ignored",
|
|
@@ -5258,18 +5422,21 @@ async function generateReplicateImage(req, ctx, deps) {
|
|
|
5258
5422
|
});
|
|
5259
5423
|
}
|
|
5260
5424
|
if (isQwenEditPlus(id) && req.outputFormat !== void 0) {
|
|
5261
|
-
|
|
5425
|
+
imageInput.output_format = req.outputFormat === "jpeg" ? "jpg" : req.outputFormat;
|
|
5262
5426
|
}
|
|
5427
|
+
input = imageInput;
|
|
5263
5428
|
} else {
|
|
5264
5429
|
const refs = req.references ?? [];
|
|
5265
5430
|
const first = refs[0];
|
|
5266
|
-
|
|
5431
|
+
const imageInput = { prompt: req.prompt };
|
|
5432
|
+
if (first) imageInput.image = refToUrl3(first);
|
|
5433
|
+
input = imageInput;
|
|
5267
5434
|
}
|
|
5268
5435
|
const { url, predictTime, raw } = await runPrediction(ctx, input, deps);
|
|
5269
5436
|
const file = await download(ctx, url);
|
|
5270
5437
|
const usage2 = imageUsage2(ctx, req);
|
|
5271
5438
|
usage2.quantity = predictTime;
|
|
5272
|
-
return { images: [{ bytes: file.bytes, mime: file.mime }], usage: usage2, raw };
|
|
5439
|
+
return { images: [{ bytes: file.bytes, mime: file.mime }], usage: usage2, raw, outputUrl: url };
|
|
5273
5440
|
}
|
|
5274
5441
|
function wanSize(aspectRatio) {
|
|
5275
5442
|
if (!aspectRatio || aspectRatio === "adaptive" || aspectRatio === "1:1") return "2K";
|
|
@@ -5293,7 +5460,7 @@ function klingInput(req) {
|
|
|
5293
5460
|
input.start_image = startImage;
|
|
5294
5461
|
const endImage = images[1];
|
|
5295
5462
|
if (endImage !== void 0) input.end_image = endImage;
|
|
5296
|
-
} else {
|
|
5463
|
+
} else if (req.aspectRatio !== "adaptive") {
|
|
5297
5464
|
input.aspect_ratio = req.aspectRatio ?? "16:9";
|
|
5298
5465
|
}
|
|
5299
5466
|
if (req.negativePrompt !== void 0) input.negative_prompt = req.negativePrompt;
|
|
@@ -5313,7 +5480,7 @@ function klingOmniInput(req) {
|
|
|
5313
5480
|
input.start_image = startImage;
|
|
5314
5481
|
const endImage = images[1];
|
|
5315
5482
|
if (endImage !== void 0) input.end_image = endImage;
|
|
5316
|
-
} else {
|
|
5483
|
+
} else if (req.aspectRatio !== "adaptive") {
|
|
5317
5484
|
input.aspect_ratio = req.aspectRatio ?? "16:9";
|
|
5318
5485
|
}
|
|
5319
5486
|
const refs = (req.referenceImages ?? []).map(refToUrl3);
|
|
@@ -5522,11 +5689,10 @@ var xaiResponseStatusSchema = z13.object({
|
|
|
5522
5689
|
response: z13.object({ status: z13.number() }).partial()
|
|
5523
5690
|
});
|
|
5524
5691
|
function xaiError(cause, ctx) {
|
|
5525
|
-
if (isModelKitError(cause)) return cause;
|
|
5526
5692
|
const info = describeThrown(cause);
|
|
5527
5693
|
const nested = xaiResponseStatusSchema.safeParse(cause);
|
|
5528
5694
|
const status = info.status ?? (nested.success ? nested.data.response?.status : void 0);
|
|
5529
|
-
return
|
|
5695
|
+
return classifyThrown("xai-video", cause, ctx.model.id, { status, body: info.body });
|
|
5530
5696
|
}
|
|
5531
5697
|
var xaiMetaSchema = z13.object({
|
|
5532
5698
|
videoUrl: JsonValueSchema.optional(),
|
|
@@ -5550,10 +5716,7 @@ async function generateXaiVideo(req, ctx, deps) {
|
|
|
5550
5716
|
retryable: false
|
|
5551
5717
|
});
|
|
5552
5718
|
}
|
|
5553
|
-
const
|
|
5554
|
-
(r) => r !== void 0
|
|
5555
|
-
);
|
|
5556
|
-
const refUrls = frames.map(refToUrl4).slice(0, 5);
|
|
5719
|
+
const refUrls = (req.referenceImages ?? []).map(refToUrl4).slice(0, 7);
|
|
5557
5720
|
const resolution = req.resolution === "480p" ? "480p" : "720p";
|
|
5558
5721
|
const xaiOptions = {
|
|
5559
5722
|
resolution,
|
|
@@ -5564,13 +5727,23 @@ async function generateXaiVideo(req, ctx, deps) {
|
|
|
5564
5727
|
xaiOptions.mode = "reference-to-video";
|
|
5565
5728
|
xaiOptions.referenceImageUrls = refUrls;
|
|
5566
5729
|
}
|
|
5730
|
+
if (req.lastFrame !== void 0) {
|
|
5731
|
+
ctx.warnings.push({
|
|
5732
|
+
code: "option_ignored",
|
|
5733
|
+
field: "lastFrame",
|
|
5734
|
+
message: "xai-video does not support lastFrame; ignored"
|
|
5735
|
+
});
|
|
5736
|
+
}
|
|
5567
5737
|
const client2 = deps.createXaiClient({ apiKey });
|
|
5568
|
-
const model = createXai2({ apiKey }).video(ctx.model.providerModelId);
|
|
5738
|
+
const model = createXai2({ apiKey, fetch: ctx.fetch }).video(ctx.model.providerModelId);
|
|
5569
5739
|
const callBody = {
|
|
5570
5740
|
model,
|
|
5571
5741
|
prompt: req.prompt,
|
|
5572
5742
|
providerOptions: { xai: xaiOptions }
|
|
5573
5743
|
};
|
|
5744
|
+
if (req.firstFrame) {
|
|
5745
|
+
callBody.frameImages = [{ image: refToUrl4(req.firstFrame), frameType: "first_frame" }];
|
|
5746
|
+
}
|
|
5574
5747
|
if (req.aspectRatio !== void 0 && req.aspectRatio !== "adaptive") {
|
|
5575
5748
|
callBody.aspectRatio = req.aspectRatio;
|
|
5576
5749
|
}
|
|
@@ -5656,26 +5829,14 @@ async function mapResult(ctx, req, result) {
|
|
|
5656
5829
|
function usage(ctx, req, meta) {
|
|
5657
5830
|
const costTicks = z13.number().safeParse(meta.costInUsdTicks);
|
|
5658
5831
|
const cost = costTicks.success ? costTicks.data / 1e10 : void 0;
|
|
5659
|
-
if (cost !== void 0) {
|
|
5660
|
-
const event2 = {
|
|
5661
|
-
model: ctx.model.id,
|
|
5662
|
-
provider: "xai-video",
|
|
5663
|
-
modality: "VIDEO",
|
|
5664
|
-
unit: "reported_cost_usd",
|
|
5665
|
-
quantity: cost,
|
|
5666
|
-
reportedCostUsd: cost
|
|
5667
|
-
};
|
|
5668
|
-
if (req.durationSeconds !== void 0) event2.durationSeconds = req.durationSeconds;
|
|
5669
|
-
if (req.resolution !== void 0) event2.resolution = req.resolution;
|
|
5670
|
-
return event2;
|
|
5671
|
-
}
|
|
5672
5832
|
const event = {
|
|
5673
5833
|
model: ctx.model.id,
|
|
5674
5834
|
provider: "xai-video",
|
|
5675
5835
|
modality: "VIDEO",
|
|
5676
|
-
unit: "
|
|
5677
|
-
quantity:
|
|
5836
|
+
unit: "reported_cost_usd",
|
|
5837
|
+
quantity: cost ?? 0
|
|
5678
5838
|
};
|
|
5839
|
+
if (cost !== void 0) event.reportedCostUsd = cost;
|
|
5679
5840
|
if (req.durationSeconds !== void 0) event.durationSeconds = req.durationSeconds;
|
|
5680
5841
|
if (req.resolution !== void 0) event.resolution = req.resolution;
|
|
5681
5842
|
return event;
|