@shop-os/modelkit 0.1.4 → 0.1.6
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 +36 -13
- package/dist/index.cjs +938 -609
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +48 -9
- package/dist/index.d.ts +48 -9
- package/dist/index.js +937 -609
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -68,6 +68,7 @@ __export(index_exports, {
|
|
|
68
68
|
prodiaAdapter: () => prodiaAdapter,
|
|
69
69
|
readErrorBody: () => readErrorBody,
|
|
70
70
|
replicateAdapter: () => replicateAdapter,
|
|
71
|
+
resolveAudioOptions: () => resolveAudioOptions,
|
|
71
72
|
resolveImageOptions: () => resolveImageOptions,
|
|
72
73
|
resolveKeys: () => resolveKeys,
|
|
73
74
|
resolveVideoOptions: () => resolveVideoOptions,
|
|
@@ -175,7 +176,8 @@ var GEMINI_RATIOS = [
|
|
|
175
176
|
"3:4",
|
|
176
177
|
"21:9",
|
|
177
178
|
"4:5",
|
|
178
|
-
"5:4"
|
|
179
|
+
"5:4",
|
|
180
|
+
"adaptive"
|
|
179
181
|
];
|
|
180
182
|
function geminiImage(id, label, aliases, sizes) {
|
|
181
183
|
const model = {
|
|
@@ -186,7 +188,11 @@ function geminiImage(id, label, aliases, sizes) {
|
|
|
186
188
|
adapter: "google-image",
|
|
187
189
|
providerModelId: id,
|
|
188
190
|
lifecycle: "active",
|
|
189
|
-
constraints: {
|
|
191
|
+
constraints: {
|
|
192
|
+
aspectRatios: [...GEMINI_RATIOS],
|
|
193
|
+
sizes,
|
|
194
|
+
supports: ["safetySettings", "temperature"]
|
|
195
|
+
},
|
|
190
196
|
defaults: { size: "1K", aspectRatio: "1:1" },
|
|
191
197
|
usage: { ...IMAGE_USAGE },
|
|
192
198
|
pricingKind: "image_size"
|
|
@@ -283,7 +289,8 @@ var IMAGE_MODELS = [
|
|
|
283
289
|
"9:16",
|
|
284
290
|
"4:5",
|
|
285
291
|
"5:4",
|
|
286
|
-
"9:21"
|
|
292
|
+
"9:21",
|
|
293
|
+
"adaptive"
|
|
287
294
|
],
|
|
288
295
|
sizes: ["1K"],
|
|
289
296
|
references: { images: 10 },
|
|
@@ -324,8 +331,20 @@ var IMAGE_MODELS = [
|
|
|
324
331
|
constraints: {
|
|
325
332
|
// 97:30 has no Ark size spelling; the A+ flow pads inputs to 97:30 and
|
|
326
333
|
// omits the ratio instead. Advertise only sizes the adapter can send.
|
|
327
|
-
aspectRatios: [
|
|
328
|
-
|
|
334
|
+
aspectRatios: [
|
|
335
|
+
"1:1",
|
|
336
|
+
"2:3",
|
|
337
|
+
"3:2",
|
|
338
|
+
"4:3",
|
|
339
|
+
"3:4",
|
|
340
|
+
"4:5",
|
|
341
|
+
"5:4",
|
|
342
|
+
"9:16",
|
|
343
|
+
"16:9",
|
|
344
|
+
"21:9",
|
|
345
|
+
"9:21"
|
|
346
|
+
],
|
|
347
|
+
sizes: ["1K", "2K", "4K"],
|
|
329
348
|
references: { images: 10 },
|
|
330
349
|
supports: ["seed"]
|
|
331
350
|
},
|
|
@@ -344,9 +363,10 @@ var IMAGE_MODELS = [
|
|
|
344
363
|
constraints: {
|
|
345
364
|
aspectRatios: ["1:1", "2:3", "3:2", "16:9", "9:16", "4:3", "3:4", "4:5", "5:4", "21:9"],
|
|
346
365
|
sizes: ["1K"],
|
|
347
|
-
|
|
366
|
+
// flux-2-pro's job type always returns image/png; only the seed is forwarded.
|
|
367
|
+
supports: ["seed"]
|
|
348
368
|
},
|
|
349
|
-
defaults: { size: "1K", aspectRatio: "1:1"
|
|
369
|
+
defaults: { size: "1K", aspectRatio: "1:1" },
|
|
350
370
|
usage: { ...IMAGE_USAGE },
|
|
351
371
|
pricingKind: "image_size"
|
|
352
372
|
},
|
|
@@ -364,7 +384,8 @@ var IMAGE_MODELS = [
|
|
|
364
384
|
constraints: {
|
|
365
385
|
aspectRatios: ["1:1", "2:3", "3:2", "4:3", "3:4", "4:5", "5:4", "9:16", "16:9", "21:9"],
|
|
366
386
|
sizes: ["1K", "2K", "4K"],
|
|
367
|
-
requires: ["references"]
|
|
387
|
+
requires: ["references"],
|
|
388
|
+
supports: ["seed"]
|
|
368
389
|
},
|
|
369
390
|
defaults: { size: "1K", aspectRatio: "1:1" },
|
|
370
391
|
usage: { ...IMAGE_USAGE },
|
|
@@ -383,7 +404,8 @@ var IMAGE_MODELS = [
|
|
|
383
404
|
constraints: {
|
|
384
405
|
aspectRatios: ["1:1", "2:3", "3:4", "4:3", "9:16", "16:9", "21:9"],
|
|
385
406
|
sizes: ["1K"],
|
|
386
|
-
requires: ["references"]
|
|
407
|
+
requires: ["references"],
|
|
408
|
+
supports: ["seed"]
|
|
387
409
|
},
|
|
388
410
|
defaults: { size: "1K", aspectRatio: "1:1" },
|
|
389
411
|
usage: { ...IMAGE_USAGE },
|
|
@@ -403,7 +425,8 @@ var IMAGE_MODELS = [
|
|
|
403
425
|
constraints: {
|
|
404
426
|
aspectRatios: ["1:1", "16:9", "9:16", "4:3", "3:4"],
|
|
405
427
|
sizes: ["1K", "2K", "4K"],
|
|
406
|
-
references: { images: 9 }
|
|
428
|
+
references: { images: 9 },
|
|
429
|
+
supports: []
|
|
407
430
|
},
|
|
408
431
|
defaults: { size: "1K", aspectRatio: "1:1" },
|
|
409
432
|
usage: { unit: "compute_seconds", modality: "IMAGE" },
|
|
@@ -424,7 +447,8 @@ var IMAGE_MODELS = [
|
|
|
424
447
|
aspectRatios: ["1:1", "16:9", "9:16", "4:3", "3:4", "3:2", "2:3"],
|
|
425
448
|
sizes: [],
|
|
426
449
|
references: { images: 1 },
|
|
427
|
-
requires: ["references"]
|
|
450
|
+
requires: ["references"],
|
|
451
|
+
supports: []
|
|
428
452
|
},
|
|
429
453
|
defaults: { aspectRatio: "1:1" },
|
|
430
454
|
usage: { unit: "compute_seconds", modality: "IMAGE" },
|
|
@@ -466,7 +490,8 @@ var OTHER_MODELS = [
|
|
|
466
490
|
lifecycle: "active",
|
|
467
491
|
constraints: {
|
|
468
492
|
durations: [30],
|
|
469
|
-
references: { images: 10 }
|
|
493
|
+
references: { images: 10 },
|
|
494
|
+
supports: []
|
|
470
495
|
},
|
|
471
496
|
defaults: {},
|
|
472
497
|
usage: { unit: "images", modality: "AUDIO" },
|
|
@@ -481,7 +506,8 @@ var OTHER_MODELS = [
|
|
|
481
506
|
providerModelId: "lyria-3-pro-preview",
|
|
482
507
|
lifecycle: "active",
|
|
483
508
|
constraints: {
|
|
484
|
-
references: { images: 10 }
|
|
509
|
+
references: { images: 10 },
|
|
510
|
+
supports: []
|
|
485
511
|
},
|
|
486
512
|
defaults: {},
|
|
487
513
|
usage: { unit: "images", modality: "AUDIO" },
|
|
@@ -548,7 +574,7 @@ var OTHER_MODELS = [
|
|
|
548
574
|
constraints: {
|
|
549
575
|
references: { images: 1 },
|
|
550
576
|
requires: ["references"],
|
|
551
|
-
supports: ["scaleFactor", "outputFormat"]
|
|
577
|
+
supports: ["scaleFactor", "outputFormat", "upscale"]
|
|
552
578
|
},
|
|
553
579
|
defaults: { scaleFactor: 2, outputFormat: "png" },
|
|
554
580
|
usage: { unit: "compute_seconds", modality: "IMAGE" },
|
|
@@ -564,7 +590,8 @@ var OTHER_MODELS = [
|
|
|
564
590
|
lifecycle: "active",
|
|
565
591
|
constraints: {
|
|
566
592
|
references: { images: 1 },
|
|
567
|
-
requires: ["references"]
|
|
593
|
+
requires: ["references"],
|
|
594
|
+
supports: []
|
|
568
595
|
},
|
|
569
596
|
defaults: {},
|
|
570
597
|
usage: { unit: "images", modality: "IMAGE" },
|
|
@@ -583,7 +610,7 @@ function text(id, label, providerModelId, extra) {
|
|
|
583
610
|
adapter: "ai-sdk-text",
|
|
584
611
|
providerModelId,
|
|
585
612
|
lifecycle: "active",
|
|
586
|
-
constraints: {},
|
|
613
|
+
constraints: { supports: [] },
|
|
587
614
|
defaults: {},
|
|
588
615
|
usage: { ...TEXT_USAGE },
|
|
589
616
|
pricingKind: "token",
|
|
@@ -656,7 +683,7 @@ var TEXT_MODELS = [
|
|
|
656
683
|
// src/catalog/video.ts
|
|
657
684
|
var VIDEO_USAGE = { unit: "seconds", modality: "VIDEO" };
|
|
658
685
|
var SEEDANCE_RATIOS = ["21:9", "16:9", "4:3", "1:1", "3:4", "9:16", "adaptive"];
|
|
659
|
-
var KLING_RATIOS = ["16:9", "9:16", "1:1"];
|
|
686
|
+
var KLING_RATIOS = ["16:9", "9:16", "1:1", "adaptive"];
|
|
660
687
|
var OMNI_RATIOS = ["16:9", "9:16"];
|
|
661
688
|
var GROK_RATIOS = ["1:1", "16:9", "9:16", "4:3", "3:4", "3:2", "2:3"];
|
|
662
689
|
var H3_RATIOS = ["21:9", "16:9", "4:3", "1:1", "3:4", "9:16"];
|
|
@@ -748,12 +775,15 @@ var VIDEO_MODELS = [
|
|
|
748
775
|
providerModelId: "gemini-omni-flash-preview",
|
|
749
776
|
lifecycle: "active",
|
|
750
777
|
constraints: {
|
|
778
|
+
// 1.0 rejects `resolution`; it renders 720p. No defaults: the adapter
|
|
779
|
+
// sends ratio and duration only when the caller set them, so a
|
|
780
|
+
// reference clip keeps its own framing.
|
|
751
781
|
aspectRatios: [...OMNI_RATIOS],
|
|
752
|
-
resolutions: ["720p"],
|
|
753
782
|
durations: [3, 4, 5, 6, 7, 8, 9, 10],
|
|
754
|
-
references: { images: 6, videos: 1 }
|
|
783
|
+
references: { images: 6, videos: 1 },
|
|
784
|
+
supports: []
|
|
755
785
|
},
|
|
756
|
-
defaults: {
|
|
786
|
+
defaults: {},
|
|
757
787
|
usage: { ...VIDEO_USAGE },
|
|
758
788
|
pricingKind: "video_per_second"
|
|
759
789
|
},
|
|
@@ -769,9 +799,10 @@ var VIDEO_MODELS = [
|
|
|
769
799
|
aspectRatios: [...OMNI_RATIOS],
|
|
770
800
|
resolutions: ["360p", "720p", "1080p", "4k"],
|
|
771
801
|
durations: [3, 4, 5, 6, 7, 8, 9, 10],
|
|
772
|
-
references: { images: 6, videos: 1 }
|
|
802
|
+
references: { images: 6, videos: 1 },
|
|
803
|
+
supports: []
|
|
773
804
|
},
|
|
774
|
-
defaults: {
|
|
805
|
+
defaults: {},
|
|
775
806
|
usage: { ...VIDEO_USAGE },
|
|
776
807
|
pricingKind: "video_per_second"
|
|
777
808
|
},
|
|
@@ -790,7 +821,7 @@ var VIDEO_MODELS = [
|
|
|
790
821
|
durations: [4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
|
|
791
822
|
references: { images: 9, videos: 3, audios: 3, audioOnly: false },
|
|
792
823
|
ratioIgnoredWith: ["firstFrame"],
|
|
793
|
-
supports: ["generateAudio", "seed", "lastFrame"]
|
|
824
|
+
supports: ["generateAudio", "seed", "lastFrame", "watermark"]
|
|
794
825
|
},
|
|
795
826
|
defaults: {
|
|
796
827
|
durationSeconds: 5,
|
|
@@ -815,7 +846,7 @@ var VIDEO_MODELS = [
|
|
|
815
846
|
durations: [4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
|
|
816
847
|
references: { images: 9, videos: 3, audios: 3, audioOnly: false },
|
|
817
848
|
ratioIgnoredWith: ["firstFrame"],
|
|
818
|
-
supports: ["generateAudio", "seed", "lastFrame"]
|
|
849
|
+
supports: ["generateAudio", "seed", "lastFrame", "watermark"]
|
|
819
850
|
},
|
|
820
851
|
defaults: {
|
|
821
852
|
durationSeconds: 5,
|
|
@@ -841,7 +872,7 @@ var VIDEO_MODELS = [
|
|
|
841
872
|
durations: { min: 4, max: 30 },
|
|
842
873
|
references: { images: 30, videos: 10, audios: 10 },
|
|
843
874
|
ratioIgnoredWith: ["firstFrame"],
|
|
844
|
-
supports: ["generateAudio", "seed", "lastFrame"]
|
|
875
|
+
supports: ["generateAudio", "seed", "lastFrame", "watermark"]
|
|
845
876
|
},
|
|
846
877
|
defaults: {
|
|
847
878
|
durationSeconds: 5,
|
|
@@ -865,9 +896,11 @@ var VIDEO_MODELS = [
|
|
|
865
896
|
aspectRatios: [...GROK_RATIOS],
|
|
866
897
|
resolutions: ["480p", "720p"],
|
|
867
898
|
durations: { min: 1, max: 15 },
|
|
868
|
-
references: { images: 7 }
|
|
899
|
+
references: { images: 7 },
|
|
900
|
+
supports: []
|
|
869
901
|
},
|
|
870
|
-
|
|
902
|
+
// No resolution default: xAI picks its own unless the caller asks.
|
|
903
|
+
defaults: { durationSeconds: 8, aspectRatio: "16:9" },
|
|
871
904
|
usage: { unit: "reported_cost_usd", modality: "VIDEO" },
|
|
872
905
|
pricingKind: "video_per_second"
|
|
873
906
|
},
|
|
@@ -961,7 +994,7 @@ var VIDEO_MODELS = [
|
|
|
961
994
|
aspectRatios: [...H3_RATIOS],
|
|
962
995
|
resolutions: ["480p", "768p", "2k", "4k"],
|
|
963
996
|
durations: { min: 5, max: 15 },
|
|
964
|
-
supports: ["seed", "promptExpansion"]
|
|
997
|
+
supports: ["seed", "promptExpansion", "lastFrame", "safetyChecker"]
|
|
965
998
|
},
|
|
966
999
|
defaults: {
|
|
967
1000
|
durationSeconds: 5,
|
|
@@ -984,7 +1017,7 @@ var VIDEO_MODELS = [
|
|
|
984
1017
|
aspectRatios: [...H3_RATIOS],
|
|
985
1018
|
resolutions: ["480p", "768p"],
|
|
986
1019
|
durations: { min: 5, max: 15 },
|
|
987
|
-
supports: ["seed", "promptExpansion"]
|
|
1020
|
+
supports: ["seed", "promptExpansion", "lastFrame", "safetyChecker"]
|
|
988
1021
|
},
|
|
989
1022
|
defaults: {
|
|
990
1023
|
durationSeconds: 5,
|
|
@@ -1008,7 +1041,7 @@ var VIDEO_MODELS = [
|
|
|
1008
1041
|
resolutions: ["480p", "768p", "2k", "4k"],
|
|
1009
1042
|
durations: { min: 5, max: 15 },
|
|
1010
1043
|
references: { images: 9, videos: 3, audios: 3, total: 12, audioOnly: false },
|
|
1011
|
-
supports: ["seed", "promptExpansion"]
|
|
1044
|
+
supports: ["seed", "promptExpansion", "safetyChecker"]
|
|
1012
1045
|
},
|
|
1013
1046
|
defaults: {
|
|
1014
1047
|
durationSeconds: 5,
|
|
@@ -1032,7 +1065,7 @@ var VIDEO_MODELS = [
|
|
|
1032
1065
|
resolutions: ["480p", "768p"],
|
|
1033
1066
|
durations: { min: 5, max: 15 },
|
|
1034
1067
|
references: { images: 9, videos: 3, audios: 3, total: 12, audioOnly: false },
|
|
1035
|
-
supports: ["seed", "promptExpansion"]
|
|
1068
|
+
supports: ["seed", "promptExpansion", "safetyChecker"]
|
|
1036
1069
|
},
|
|
1037
1070
|
defaults: {
|
|
1038
1071
|
durationSeconds: 5,
|
|
@@ -1055,7 +1088,8 @@ var VIDEO_MODELS = [
|
|
|
1055
1088
|
constraints: {
|
|
1056
1089
|
aspectRatios: [...KLING_RATIOS],
|
|
1057
1090
|
durations: { min: 3, max: 10 },
|
|
1058
|
-
requires: ["sourceVideo"]
|
|
1091
|
+
requires: ["sourceVideo"],
|
|
1092
|
+
supports: []
|
|
1059
1093
|
},
|
|
1060
1094
|
defaults: { durationSeconds: 5, aspectRatio: "16:9" },
|
|
1061
1095
|
usage: { ...VIDEO_USAGE },
|
|
@@ -1088,7 +1122,7 @@ var VIDEO_MODELS = [
|
|
|
1088
1122
|
lifecycle: "active",
|
|
1089
1123
|
constraints: {
|
|
1090
1124
|
requires: ["firstFrame"],
|
|
1091
|
-
supports: ["seed"]
|
|
1125
|
+
supports: ["seed", "lastFrame"]
|
|
1092
1126
|
},
|
|
1093
1127
|
defaults: {},
|
|
1094
1128
|
usage: { ...VIDEO_USAGE },
|
|
@@ -1159,19 +1193,22 @@ function resolveTier(field, code, requested, supported, order, model, onUnsuppor
|
|
|
1159
1193
|
});
|
|
1160
1194
|
return to;
|
|
1161
1195
|
}
|
|
1162
|
-
function resolveDuration(requested, durations, model, warnings) {
|
|
1196
|
+
function resolveDuration(requested, durations, model, onUnsupported, warnings) {
|
|
1163
1197
|
if (requested === void 0 || !durations) return requested;
|
|
1164
|
-
|
|
1165
|
-
if (
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
if (to === requested) return requested;
|
|
1198
|
+
const inSet = Array.isArray(durations) ? durations.includes(requested) : requested >= durations.min && requested <= durations.max;
|
|
1199
|
+
if (inSet) return requested;
|
|
1200
|
+
if (onUnsupported === "error") {
|
|
1201
|
+
const supported = Array.isArray(durations) ? `Supported: ${durations.join(", ")}.` : `Supported range: ${durations.min}-${durations.max}.`;
|
|
1202
|
+
throw new ModelKitError({
|
|
1203
|
+
code: "unsupported_option",
|
|
1204
|
+
message: `${model.id} does not support durationSeconds ${requested}. ${supported}`,
|
|
1205
|
+
model: model.id
|
|
1206
|
+
});
|
|
1174
1207
|
}
|
|
1208
|
+
const to = Array.isArray(durations) ? durations.reduce(
|
|
1209
|
+
(best, d) => Math.abs(d - requested) < Math.abs(best - requested) ? d : best,
|
|
1210
|
+
durations[0] ?? requested
|
|
1211
|
+
) : Math.min(Math.max(requested, durations.min), durations.max);
|
|
1175
1212
|
warnings.push({
|
|
1176
1213
|
code: "duration_coerced",
|
|
1177
1214
|
field: "durationSeconds",
|
|
@@ -1181,6 +1218,26 @@ function resolveDuration(requested, durations, model, warnings) {
|
|
|
1181
1218
|
});
|
|
1182
1219
|
return to;
|
|
1183
1220
|
}
|
|
1221
|
+
function resolveAspectRatio(requested, supported, model, onUnsupported, warnings) {
|
|
1222
|
+
if (requested === void 0 || requested === "adaptive" || !supported) return requested;
|
|
1223
|
+
if (supported.includes(requested)) return requested;
|
|
1224
|
+
if (onUnsupported === "error") {
|
|
1225
|
+
throw new ModelKitError({
|
|
1226
|
+
code: "unsupported_option",
|
|
1227
|
+
message: `${model.id} does not support aspectRatio "${requested}". Supported: ${supported.join(", ")}.`,
|
|
1228
|
+
model: model.id
|
|
1229
|
+
});
|
|
1230
|
+
}
|
|
1231
|
+
const to = nearestAspectRatio(requested, supported);
|
|
1232
|
+
warnings.push({
|
|
1233
|
+
code: "ratio_coerced",
|
|
1234
|
+
field: "aspectRatio",
|
|
1235
|
+
from: requested,
|
|
1236
|
+
to,
|
|
1237
|
+
message: `aspect ratio ${requested} coerced to ${to} for ${model.id}`
|
|
1238
|
+
});
|
|
1239
|
+
return to;
|
|
1240
|
+
}
|
|
1184
1241
|
function compact(refs) {
|
|
1185
1242
|
return (refs ?? []).filter((r) => Boolean(r));
|
|
1186
1243
|
}
|
|
@@ -1199,17 +1256,14 @@ function resolveImageOptions(model, request, onUnsupported = "error") {
|
|
|
1199
1256
|
const warnings = [];
|
|
1200
1257
|
const c = model.constraints;
|
|
1201
1258
|
const merged = { ...model.defaults, ...stripUndefined(request), model: model.id };
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
});
|
|
1211
|
-
merged.aspectRatio = to;
|
|
1212
|
-
}
|
|
1259
|
+
const aspectRatio = resolveAspectRatio(
|
|
1260
|
+
merged.aspectRatio,
|
|
1261
|
+
c.aspectRatios,
|
|
1262
|
+
model,
|
|
1263
|
+
onUnsupported,
|
|
1264
|
+
warnings
|
|
1265
|
+
);
|
|
1266
|
+
if (aspectRatio !== void 0) merged.aspectRatio = aspectRatio;
|
|
1213
1267
|
const size = resolveTier(
|
|
1214
1268
|
"size",
|
|
1215
1269
|
"size_coerced",
|
|
@@ -1242,7 +1296,10 @@ function resolveImageOptions(model, request, onUnsupported = "error") {
|
|
|
1242
1296
|
"quality",
|
|
1243
1297
|
"count",
|
|
1244
1298
|
"outputFormat",
|
|
1245
|
-
"scaleFactor"
|
|
1299
|
+
"scaleFactor",
|
|
1300
|
+
"safetySettings",
|
|
1301
|
+
"temperature",
|
|
1302
|
+
"upscale"
|
|
1246
1303
|
]);
|
|
1247
1304
|
return { request: merged, warnings };
|
|
1248
1305
|
}
|
|
@@ -1272,17 +1329,14 @@ function resolveVideoOptions(model, request, onUnsupported = "error") {
|
|
|
1272
1329
|
delete merged.aspectRatio;
|
|
1273
1330
|
}
|
|
1274
1331
|
}
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
});
|
|
1284
|
-
merged.aspectRatio = to;
|
|
1285
|
-
}
|
|
1332
|
+
const aspectRatio = resolveAspectRatio(
|
|
1333
|
+
merged.aspectRatio,
|
|
1334
|
+
c.aspectRatios,
|
|
1335
|
+
model,
|
|
1336
|
+
onUnsupported,
|
|
1337
|
+
warnings
|
|
1338
|
+
);
|
|
1339
|
+
if (aspectRatio !== void 0) merged.aspectRatio = aspectRatio;
|
|
1286
1340
|
const resolution = resolveTier(
|
|
1287
1341
|
"resolution",
|
|
1288
1342
|
"resolution_coerced",
|
|
@@ -1294,7 +1348,13 @@ function resolveVideoOptions(model, request, onUnsupported = "error") {
|
|
|
1294
1348
|
warnings
|
|
1295
1349
|
);
|
|
1296
1350
|
if (resolution !== void 0) merged.resolution = resolution;
|
|
1297
|
-
const duration = resolveDuration(
|
|
1351
|
+
const duration = resolveDuration(
|
|
1352
|
+
merged.durationSeconds,
|
|
1353
|
+
c.durations,
|
|
1354
|
+
model,
|
|
1355
|
+
onUnsupported,
|
|
1356
|
+
warnings
|
|
1357
|
+
);
|
|
1298
1358
|
if (duration !== void 0) merged.durationSeconds = duration;
|
|
1299
1359
|
const limits = c.references ?? {};
|
|
1300
1360
|
let images = trim(
|
|
@@ -1349,13 +1409,47 @@ function resolveVideoOptions(model, request, onUnsupported = "error") {
|
|
|
1349
1409
|
"cfgScale",
|
|
1350
1410
|
"generateAudio",
|
|
1351
1411
|
"promptExpansion",
|
|
1352
|
-
"lastFrame"
|
|
1412
|
+
"lastFrame",
|
|
1413
|
+
"watermark",
|
|
1414
|
+
"safetyChecker"
|
|
1353
1415
|
]);
|
|
1354
1416
|
return { request: merged, warnings };
|
|
1355
1417
|
}
|
|
1418
|
+
function resolveAudioOptions(model, request, onUnsupported = "error") {
|
|
1419
|
+
const warnings = [];
|
|
1420
|
+
const c = model.constraints;
|
|
1421
|
+
const merged = { ...model.defaults, ...stripUndefined(request), model: model.id };
|
|
1422
|
+
for (const input of c.requires ?? []) {
|
|
1423
|
+
const present = input === "references" ? compact(merged.references).length > 0 : input === "sourceVideo" && merged.sourceVideo !== void 0;
|
|
1424
|
+
if (!present)
|
|
1425
|
+
throw new ModelKitError({
|
|
1426
|
+
code: "missing_input",
|
|
1427
|
+
message: `${model.id} requires ${input}`,
|
|
1428
|
+
model: model.id
|
|
1429
|
+
});
|
|
1430
|
+
}
|
|
1431
|
+
const duration = resolveDuration(
|
|
1432
|
+
merged.durationSeconds,
|
|
1433
|
+
c.durations,
|
|
1434
|
+
model,
|
|
1435
|
+
onUnsupported,
|
|
1436
|
+
warnings
|
|
1437
|
+
);
|
|
1438
|
+
if (duration !== void 0) merged.durationSeconds = duration;
|
|
1439
|
+
const references = trim(
|
|
1440
|
+
"references",
|
|
1441
|
+
compact(merged.references),
|
|
1442
|
+
c.references?.images ?? c.references?.total,
|
|
1443
|
+
model,
|
|
1444
|
+
warnings
|
|
1445
|
+
);
|
|
1446
|
+
if (references.length > 0) merged.references = references;
|
|
1447
|
+
else delete merged.references;
|
|
1448
|
+
dropUnsupported(merged, model, warnings, ["seed", "negativePrompt", "instrumental"]);
|
|
1449
|
+
return { request: merged, warnings };
|
|
1450
|
+
}
|
|
1356
1451
|
function dropUnsupported(req, model, warnings, fields) {
|
|
1357
|
-
const supports = model.constraints.supports;
|
|
1358
|
-
if (!supports) return;
|
|
1452
|
+
const supports = model.constraints.supports ?? [];
|
|
1359
1453
|
for (const field of fields) {
|
|
1360
1454
|
if (req[field] !== void 0 && !supports.includes(field)) {
|
|
1361
1455
|
warnings.push({
|
|
@@ -1395,6 +1489,9 @@ function hasAll(keys, names) {
|
|
|
1395
1489
|
(n) => Boolean(keys[n]) && (n !== "higgsfield" || Boolean(keys.higgsfieldSecret))
|
|
1396
1490
|
);
|
|
1397
1491
|
}
|
|
1492
|
+
function missingEnterpriseKeys(config, names) {
|
|
1493
|
+
return names.filter((name) => !hasAll(config.keys.enterprise, [name]));
|
|
1494
|
+
}
|
|
1398
1495
|
function resolveKeys(config, names, tier = "pro") {
|
|
1399
1496
|
if (tier === "enterprise" && hasAll(config.keys.enterprise, names))
|
|
1400
1497
|
return config.keys.enterprise;
|
|
@@ -1427,18 +1524,56 @@ function keysFromEnv(env, prefix = "") {
|
|
|
1427
1524
|
set("prodia", pick("PRODIA_API_KEY", "PRODIA_TOKEN"));
|
|
1428
1525
|
set("higgsfield", pick("HIGGSFIELD_API_KEY"));
|
|
1429
1526
|
set("higgsfieldSecret", pick("HIGGSFIELD_API_SECRET"));
|
|
1430
|
-
set("openrouter", pick("OPENROUTER_API_KEY"));
|
|
1431
1527
|
set("cloudflare", pick("CLOUDFLARE_AI_GATEWAY_TOKEN", "CF_AIG_TOKEN"));
|
|
1432
1528
|
return keys;
|
|
1433
1529
|
}
|
|
1434
1530
|
|
|
1435
1531
|
// src/retry.ts
|
|
1532
|
+
var import_zod2 = require("zod");
|
|
1533
|
+
|
|
1534
|
+
// src/json.ts
|
|
1436
1535
|
var import_zod = require("zod");
|
|
1437
|
-
var
|
|
1536
|
+
var JsonValueSchema = import_zod.z.lazy(
|
|
1537
|
+
() => import_zod.z.union([
|
|
1538
|
+
import_zod.z.string(),
|
|
1539
|
+
import_zod.z.number(),
|
|
1540
|
+
import_zod.z.boolean(),
|
|
1541
|
+
import_zod.z.null(),
|
|
1542
|
+
import_zod.z.array(JsonValueSchema),
|
|
1543
|
+
import_zod.z.record(import_zod.z.string(), JsonValueSchema)
|
|
1544
|
+
])
|
|
1545
|
+
);
|
|
1546
|
+
var JsonObjectSchema = import_zod.z.record(import_zod.z.string(), JsonValueSchema);
|
|
1547
|
+
async function readErrorBody(res) {
|
|
1548
|
+
const text2 = await res.text().catch(() => "");
|
|
1549
|
+
try {
|
|
1550
|
+
return JsonValueSchema.parse(JSON.parse(text2));
|
|
1551
|
+
} catch {
|
|
1552
|
+
return text2;
|
|
1553
|
+
}
|
|
1554
|
+
}
|
|
1555
|
+
var thrownErrorSchema = import_zod.z.object({
|
|
1556
|
+
message: import_zod.z.string().optional(),
|
|
1557
|
+
status: import_zod.z.number().optional(),
|
|
1558
|
+
statusCode: import_zod.z.number().optional(),
|
|
1559
|
+
responseBody: import_zod.z.string().optional()
|
|
1560
|
+
});
|
|
1561
|
+
function describeThrown(cause) {
|
|
1562
|
+
const parsed = thrownErrorSchema.safeParse(cause);
|
|
1563
|
+
if (!parsed.success) return { message: String(cause), status: void 0, body: String(cause) };
|
|
1564
|
+
const { message, status, statusCode, responseBody } = parsed.data;
|
|
1565
|
+
const body = responseBody ?? message ?? String(cause);
|
|
1566
|
+
return { message: message ?? String(cause), status: status ?? statusCode, body };
|
|
1567
|
+
}
|
|
1568
|
+
|
|
1569
|
+
// src/retry.ts
|
|
1570
|
+
var textBody = import_zod2.z.string();
|
|
1438
1571
|
function classifyHttpError(status, body, provider, model) {
|
|
1439
1572
|
const asText = textBody.safeParse(body);
|
|
1440
1573
|
const text2 = asText.success ? asText.data : JSON.stringify(body);
|
|
1441
|
-
const blocked = /
|
|
1574
|
+
const blocked = /content_policy_violation|blockReason|PROHIBITED_CONTENT|moderation_blocked|safety(?![_A-Za-z])/i.test(
|
|
1575
|
+
text2
|
|
1576
|
+
);
|
|
1442
1577
|
let code = "provider_rejected";
|
|
1443
1578
|
if (blocked) code = "content_blocked";
|
|
1444
1579
|
else if (status === 401 || status === 403) code = "auth";
|
|
@@ -1459,8 +1594,8 @@ function classifyHttpError(status, body, provider, model) {
|
|
|
1459
1594
|
}
|
|
1460
1595
|
function shouldRetry(err) {
|
|
1461
1596
|
if (err instanceof ModelKitError) return err.retryable;
|
|
1462
|
-
if (err.name === "AbortError"
|
|
1463
|
-
|
|
1597
|
+
if (err.name === "AbortError") return false;
|
|
1598
|
+
if (/ECONNRESET|ETIMEDOUT|fetch failed|socket hang up/i.test(err.message)) return true;
|
|
1464
1599
|
return false;
|
|
1465
1600
|
}
|
|
1466
1601
|
async function withRetry(fn, opts = {}) {
|
|
@@ -1517,6 +1652,13 @@ function transportError(provider, cause, model) {
|
|
|
1517
1652
|
if (model !== void 0) init.model = model;
|
|
1518
1653
|
return new ModelKitError(init);
|
|
1519
1654
|
}
|
|
1655
|
+
function classifyThrown(provider, cause, model, override = {}) {
|
|
1656
|
+
if (cause instanceof ModelKitError) return cause;
|
|
1657
|
+
const info = describeThrown(cause);
|
|
1658
|
+
const status = override.status ?? info.status;
|
|
1659
|
+
if (status === void 0) return transportError(provider, cause, model);
|
|
1660
|
+
return classifyHttpError(status, override.body ?? info.body, provider, model);
|
|
1661
|
+
}
|
|
1520
1662
|
async function pollUntil(check, opts) {
|
|
1521
1663
|
const start = Date.now();
|
|
1522
1664
|
let interval = opts.intervalMs;
|
|
@@ -1632,12 +1774,18 @@ function createTextSteps(initial, resolve, callerProviderOptions) {
|
|
|
1632
1774
|
|
|
1633
1775
|
// src/client.ts
|
|
1634
1776
|
var import_ai2 = require("ai");
|
|
1635
|
-
var
|
|
1777
|
+
var import_zod4 = require("zod");
|
|
1636
1778
|
|
|
1637
1779
|
// src/adapters/media-ref.ts
|
|
1638
1780
|
function isUrlRef(ref) {
|
|
1639
1781
|
return "url" in ref;
|
|
1640
1782
|
}
|
|
1783
|
+
function abortedError() {
|
|
1784
|
+
return new ModelKitError({ code: "timeout", message: "aborted", retryable: false });
|
|
1785
|
+
}
|
|
1786
|
+
function throwIfAborted(signal) {
|
|
1787
|
+
if (signal?.aborted) throw abortedError();
|
|
1788
|
+
}
|
|
1641
1789
|
function mediaRefToBase64(bytes) {
|
|
1642
1790
|
let binary = "";
|
|
1643
1791
|
const CHUNK = 32768;
|
|
@@ -1652,10 +1800,34 @@ function base64ToBytes(b64) {
|
|
|
1652
1800
|
for (let i = 0; i < binary.length; i++) out[i] = binary.charCodeAt(i);
|
|
1653
1801
|
return out;
|
|
1654
1802
|
}
|
|
1655
|
-
|
|
1803
|
+
function mediaRefToDataUrl(ref) {
|
|
1804
|
+
if (isUrlRef(ref)) return ref.url;
|
|
1805
|
+
return `data:${ref.mime};base64,${mediaRefToBase64(ref.bytes)}`;
|
|
1806
|
+
}
|
|
1807
|
+
var refToUrl = mediaRefToDataUrl;
|
|
1808
|
+
async function readBody(res) {
|
|
1809
|
+
const text2 = await res.text().catch(() => "");
|
|
1810
|
+
try {
|
|
1811
|
+
const decoded = JsonValueSchema.safeParse(JSON.parse(text2));
|
|
1812
|
+
return decoded.success ? decoded.data : text2;
|
|
1813
|
+
} catch {
|
|
1814
|
+
return text2;
|
|
1815
|
+
}
|
|
1816
|
+
}
|
|
1817
|
+
async function mediaRefToBytes(ref, fetch, options = {}) {
|
|
1656
1818
|
if (!isUrlRef(ref)) return { bytes: ref.bytes, mime: ref.mime };
|
|
1657
|
-
const
|
|
1658
|
-
if (
|
|
1819
|
+
const init = {};
|
|
1820
|
+
if (options.signal !== void 0) init.signal = options.signal;
|
|
1821
|
+
const res = await fetch(ref.url, init);
|
|
1822
|
+
if (!res.ok) {
|
|
1823
|
+
const text2 = await res.text().catch(() => "");
|
|
1824
|
+
throw classifyHttpError(
|
|
1825
|
+
res.status,
|
|
1826
|
+
text2,
|
|
1827
|
+
options.provider ?? "media-reference",
|
|
1828
|
+
options.model
|
|
1829
|
+
);
|
|
1830
|
+
}
|
|
1659
1831
|
const mime = res.headers.get("content-type")?.split(";")[0]?.trim().toLowerCase() || "image/png";
|
|
1660
1832
|
return { bytes: new Uint8Array(await res.arrayBuffer()), mime };
|
|
1661
1833
|
}
|
|
@@ -1687,7 +1859,7 @@ var import_perplexity = require("@ai-sdk/perplexity");
|
|
|
1687
1859
|
var import_xai = require("@ai-sdk/xai");
|
|
1688
1860
|
var import_deepseek = require("@ai-sdk/deepseek");
|
|
1689
1861
|
var import_moonshotai = require("@ai-sdk/moonshotai");
|
|
1690
|
-
var
|
|
1862
|
+
var import_zod3 = require("zod");
|
|
1691
1863
|
var TEXT_PROVIDERS = [
|
|
1692
1864
|
"openai",
|
|
1693
1865
|
"anthropic",
|
|
@@ -1698,7 +1870,7 @@ var TEXT_PROVIDERS = [
|
|
|
1698
1870
|
"moonshot",
|
|
1699
1871
|
"minimax"
|
|
1700
1872
|
];
|
|
1701
|
-
var textProviderSchema =
|
|
1873
|
+
var textProviderSchema = import_zod3.z.enum(TEXT_PROVIDERS);
|
|
1702
1874
|
function isTextProvider(value) {
|
|
1703
1875
|
return textProviderSchema.safeParse(value).success;
|
|
1704
1876
|
}
|
|
@@ -1707,22 +1879,12 @@ var OPENAI_COMPATIBLE_BASE_URLS = {
|
|
|
1707
1879
|
};
|
|
1708
1880
|
var GATEWAY_SLUGS = {
|
|
1709
1881
|
openai: "openai",
|
|
1710
|
-
anthropic: "anthropic",
|
|
1882
|
+
anthropic: "anthropic/v1",
|
|
1711
1883
|
google: "google-ai-studio/v1beta",
|
|
1712
|
-
xai: "grok",
|
|
1884
|
+
xai: "grok/v1",
|
|
1713
1885
|
perplexity: "perplexity-ai",
|
|
1714
1886
|
deepseek: "deepseek"
|
|
1715
1887
|
};
|
|
1716
|
-
var OPENROUTER_VENDORS = {
|
|
1717
|
-
openai: "openai",
|
|
1718
|
-
anthropic: "anthropic",
|
|
1719
|
-
google: "google",
|
|
1720
|
-
xai: "x-ai",
|
|
1721
|
-
perplexity: "perplexity",
|
|
1722
|
-
deepseek: "deepseek",
|
|
1723
|
-
moonshot: "moonshotai",
|
|
1724
|
-
minimax: "minimax"
|
|
1725
|
-
};
|
|
1726
1888
|
function detectTextProvider(modelId) {
|
|
1727
1889
|
const id = modelId.toLowerCase();
|
|
1728
1890
|
if (id.startsWith("claude") || id.includes("anthropic.")) return "anthropic";
|
|
@@ -1739,14 +1901,17 @@ function detectTextProvider(modelId) {
|
|
|
1739
1901
|
message: `ai-sdk-text cannot detect a provider for "${modelId}". Set providerOptions.provider to one of ${TEXT_PROVIDERS.join(", ")}.`
|
|
1740
1902
|
});
|
|
1741
1903
|
}
|
|
1742
|
-
function textKeyName(model,
|
|
1743
|
-
if (routing.text === "openrouter") return "openrouter";
|
|
1904
|
+
function textKeyName(model, _routing) {
|
|
1744
1905
|
return textProviderOf(model);
|
|
1745
1906
|
}
|
|
1746
1907
|
function textProviderOf(model) {
|
|
1747
1908
|
const explicit = model.providerOptions?.["modelkit"]?.["provider"];
|
|
1748
1909
|
return isTextProvider(explicit) ? explicit : detectTextProvider(model.providerModelId);
|
|
1749
1910
|
}
|
|
1911
|
+
function textUsesCloudflareGateway(model, routing) {
|
|
1912
|
+
if (routing.text !== "cloudflare") return false;
|
|
1913
|
+
return GATEWAY_SLUGS[textProviderOf(model)] !== void 0;
|
|
1914
|
+
}
|
|
1750
1915
|
function nativeClientFor(provider) {
|
|
1751
1916
|
switch (provider) {
|
|
1752
1917
|
case "openai":
|
|
@@ -1779,16 +1944,6 @@ function resolveTextRoute(ctx) {
|
|
|
1779
1944
|
retryable: false
|
|
1780
1945
|
});
|
|
1781
1946
|
}
|
|
1782
|
-
if (mode === "openrouter") {
|
|
1783
|
-
const modelId = ctx.model.providerModelId.includes("/") ? ctx.model.providerModelId : `${OPENROUTER_VENDORS[provider]}/${ctx.model.providerModelId}`;
|
|
1784
|
-
return {
|
|
1785
|
-
provider,
|
|
1786
|
-
client: "openai-compatible",
|
|
1787
|
-
modelId,
|
|
1788
|
-
keyName: "openrouter",
|
|
1789
|
-
baseURL: "https://openrouter.ai/api/v1"
|
|
1790
|
-
};
|
|
1791
|
-
}
|
|
1792
1947
|
const compatBase = OPENAI_COMPATIBLE_BASE_URLS[provider];
|
|
1793
1948
|
const route2 = {
|
|
1794
1949
|
provider,
|
|
@@ -1856,7 +2011,7 @@ var aiSdkTextAdapter = {
|
|
|
1856
2011
|
case "openai-compatible":
|
|
1857
2012
|
return (0, import_openai.createOpenAI)({
|
|
1858
2013
|
...settings,
|
|
1859
|
-
name: route2.provider
|
|
2014
|
+
name: route2.provider
|
|
1860
2015
|
}).chat(route2.modelId);
|
|
1861
2016
|
case "openai":
|
|
1862
2017
|
return (0, import_openai.createOpenAI)(settings)(route2.modelId);
|
|
@@ -1869,8 +2024,9 @@ function requiredKeys(model, config) {
|
|
|
1869
2024
|
if (model.adapter === "fal" && config.routing?.fal === "cloudflare-passthrough")
|
|
1870
2025
|
return ["cloudflare"];
|
|
1871
2026
|
if (model.adapter === "ai-sdk-text") {
|
|
1872
|
-
const
|
|
1873
|
-
|
|
2027
|
+
const routing = config.routing ?? {};
|
|
2028
|
+
const names = [textKeyName(model, routing)];
|
|
2029
|
+
if (textUsesCloudflareGateway(model, routing)) names.push("cloudflare");
|
|
1874
2030
|
return names;
|
|
1875
2031
|
}
|
|
1876
2032
|
return ADAPTER_KEYS[model.adapter];
|
|
@@ -1884,10 +2040,10 @@ function textAbortOptions(sdk, context) {
|
|
|
1884
2040
|
if (abortSignal) return { abortSignal };
|
|
1885
2041
|
return {};
|
|
1886
2042
|
}
|
|
1887
|
-
var catalogId =
|
|
1888
|
-
var exactSize =
|
|
1889
|
-
var sdkRatio =
|
|
1890
|
-
var sizeTier =
|
|
2043
|
+
var catalogId = import_zod4.z.string();
|
|
2044
|
+
var exactSize = import_zod4.z.templateLiteral([import_zod4.z.number(), "x", import_zod4.z.number()]);
|
|
2045
|
+
var sdkRatio = import_zod4.z.templateLiteral([import_zod4.z.number(), ":", import_zod4.z.number()]);
|
|
2046
|
+
var sizeTier = import_zod4.z.enum(["512", "1K", "2K", "4K"]);
|
|
1891
2047
|
function isCatalogId(model) {
|
|
1892
2048
|
return catalogId.safeParse(model).success;
|
|
1893
2049
|
}
|
|
@@ -1944,6 +2100,15 @@ function pushIgnored(warnings, field, from, modelId) {
|
|
|
1944
2100
|
message: `${modelId} provider instance does not support ${field}; ignored`
|
|
1945
2101
|
});
|
|
1946
2102
|
}
|
|
2103
|
+
function withoutModelkit(options) {
|
|
2104
|
+
if (!options) return {};
|
|
2105
|
+
const { modelkit: _modelkit, ...rest } = options;
|
|
2106
|
+
return rest;
|
|
2107
|
+
}
|
|
2108
|
+
function logCoercions(logger, modelId, warnings) {
|
|
2109
|
+
if (warnings.length === 0) return;
|
|
2110
|
+
logger.warn(`[modelkit] ${modelId} request coerced`, { model: modelId, warnings });
|
|
2111
|
+
}
|
|
1947
2112
|
function createModelKit(config, adapters) {
|
|
1948
2113
|
const catalog = new Catalog(MODELS).withOverrides(config.catalogOverride ?? []);
|
|
1949
2114
|
const logger = config.logger ?? console;
|
|
@@ -1956,7 +2121,16 @@ function createModelKit(config, adapters) {
|
|
|
1956
2121
|
message: `No adapter registered for ${model.adapter}`,
|
|
1957
2122
|
model: model.id
|
|
1958
2123
|
});
|
|
1959
|
-
const
|
|
2124
|
+
const names = requiredKeys(model, config);
|
|
2125
|
+
if (call.tier === "enterprise") {
|
|
2126
|
+
const missing = missingEnterpriseKeys(config, names);
|
|
2127
|
+
if (missing.length > 0)
|
|
2128
|
+
logger.warn(
|
|
2129
|
+
`[modelkit] enterprise keys incomplete for ${model.adapter}; using pro`,
|
|
2130
|
+
{ missing }
|
|
2131
|
+
);
|
|
2132
|
+
}
|
|
2133
|
+
const keys = resolveKeys(config, names, call.tier);
|
|
1960
2134
|
const ctx = {
|
|
1961
2135
|
model,
|
|
1962
2136
|
keys,
|
|
@@ -1977,6 +2151,10 @@ function createModelKit(config, adapters) {
|
|
|
1977
2151
|
logger.warn("[modelkit] usage emit failed", err);
|
|
1978
2152
|
}
|
|
1979
2153
|
}
|
|
2154
|
+
function withRowUnit(event) {
|
|
2155
|
+
const row = catalog.get(event.model);
|
|
2156
|
+
return row ? { ...event, unit: row.usage.unit } : event;
|
|
2157
|
+
}
|
|
1980
2158
|
function textTarget(model, call) {
|
|
1981
2159
|
if (!isCatalogId(model)) {
|
|
1982
2160
|
return {
|
|
@@ -2045,6 +2223,7 @@ function createModelKit(config, adapters) {
|
|
|
2045
2223
|
pushIgnored(warnings, "outputFormat", _outputFormat, model.modelId);
|
|
2046
2224
|
if (scaleFactor !== void 0)
|
|
2047
2225
|
pushIgnored(warnings, "scaleFactor", scaleFactor, model.modelId);
|
|
2226
|
+
logCoercions(logger, model.modelId, warnings);
|
|
2048
2227
|
const abortSignal = combineSignals(req.abortSignal, call.signal);
|
|
2049
2228
|
if (abortSignal) options.abortSignal = abortSignal;
|
|
2050
2229
|
const result = await (0, import_ai2.generateImage)(options);
|
|
@@ -2128,6 +2307,7 @@ function createModelKit(config, adapters) {
|
|
|
2128
2307
|
if (_mode !== void 0) pushIgnored(warnings, "mode", _mode, model.modelId);
|
|
2129
2308
|
if (providerOptions) options.providerOptions = providerOptions;
|
|
2130
2309
|
if (abortSignal) options.abortSignal = abortSignal;
|
|
2310
|
+
logCoercions(logger, model.modelId, warnings);
|
|
2131
2311
|
const pending = (0, import_ai2.experimental_generateVideo)(options);
|
|
2132
2312
|
let settled;
|
|
2133
2313
|
let failed = false;
|
|
@@ -2186,6 +2366,7 @@ function createModelKit(config, adapters) {
|
|
|
2186
2366
|
call.onUnsupported ?? "error"
|
|
2187
2367
|
);
|
|
2188
2368
|
warnings.push(...inputWarnings);
|
|
2369
|
+
logCoercions(logger, model.id, warnings);
|
|
2189
2370
|
const signal = combineSignals(req.abortSignal, call.signal);
|
|
2190
2371
|
const { adapter, ctx } = context(model, signal ? { ...call, signal } : call, warnings);
|
|
2191
2372
|
if (!adapter.generateImage)
|
|
@@ -2195,7 +2376,7 @@ function createModelKit(config, adapters) {
|
|
|
2195
2376
|
model: model.id
|
|
2196
2377
|
});
|
|
2197
2378
|
const result = await adapter.generateImage(request, ctx);
|
|
2198
|
-
const usage2 = { ...result.usage, model: model.id };
|
|
2379
|
+
const usage2 = { ...result.usage, model: model.id, unit: model.usage.unit };
|
|
2199
2380
|
await emit(usage2);
|
|
2200
2381
|
const images = result.images.map(toGeneratedImage);
|
|
2201
2382
|
const first = images[0];
|
|
@@ -2228,6 +2409,7 @@ function createModelKit(config, adapters) {
|
|
|
2228
2409
|
call.onUnsupported ?? "error"
|
|
2229
2410
|
);
|
|
2230
2411
|
warnings.push(...inputWarnings);
|
|
2412
|
+
logCoercions(logger, model.id, warnings);
|
|
2231
2413
|
const signal = combineSignals(req.abortSignal, call.signal);
|
|
2232
2414
|
const { adapter, ctx } = context(model, signal ? { ...call, signal } : call, warnings);
|
|
2233
2415
|
if (!adapter.generateVideo)
|
|
@@ -2245,7 +2427,11 @@ function createModelKit(config, adapters) {
|
|
|
2245
2427
|
result(opts) {
|
|
2246
2428
|
if (settled) return settled;
|
|
2247
2429
|
const pending = result(opts).then(
|
|
2248
|
-
(out) => emit({
|
|
2430
|
+
(out) => emit({
|
|
2431
|
+
...out.usage,
|
|
2432
|
+
model: model.id,
|
|
2433
|
+
unit: model.usage.unit
|
|
2434
|
+
}).then(() => out),
|
|
2249
2435
|
(cause) => {
|
|
2250
2436
|
settled = void 0;
|
|
2251
2437
|
throw cause;
|
|
@@ -2265,7 +2451,15 @@ function createModelKit(config, adapters) {
|
|
|
2265
2451
|
model: model.id
|
|
2266
2452
|
});
|
|
2267
2453
|
}
|
|
2268
|
-
const {
|
|
2454
|
+
const { abortSignal: _signal, ...request } = req;
|
|
2455
|
+
const { request: resolved, warnings } = resolveAudioOptions(
|
|
2456
|
+
model,
|
|
2457
|
+
request,
|
|
2458
|
+
call.onUnsupported ?? "error"
|
|
2459
|
+
);
|
|
2460
|
+
logCoercions(logger, model.id, warnings);
|
|
2461
|
+
const signal = combineSignals(req.abortSignal, call.signal);
|
|
2462
|
+
const { adapter, ctx } = context(model, signal ? { ...call, signal } : call, warnings);
|
|
2269
2463
|
if (!adapter.generateAudio) {
|
|
2270
2464
|
throw new ModelKitError({
|
|
2271
2465
|
code: "unsupported_option",
|
|
@@ -2273,11 +2467,8 @@ function createModelKit(config, adapters) {
|
|
|
2273
2467
|
model: model.id
|
|
2274
2468
|
});
|
|
2275
2469
|
}
|
|
2276
|
-
const result = await adapter.generateAudio(
|
|
2277
|
-
|
|
2278
|
-
ctx
|
|
2279
|
-
);
|
|
2280
|
-
await emit({ ...result.usage, model: model.id });
|
|
2470
|
+
const result = await adapter.generateAudio(resolved, ctx);
|
|
2471
|
+
await emit({ ...result.usage, model: model.id, unit: model.usage.unit });
|
|
2281
2472
|
return result;
|
|
2282
2473
|
},
|
|
2283
2474
|
async prepareMediaPart(modelId, ref, mediaType, call = {}) {
|
|
@@ -2297,7 +2488,7 @@ function createModelKit(config, adapters) {
|
|
|
2297
2488
|
});
|
|
2298
2489
|
return {
|
|
2299
2490
|
model,
|
|
2300
|
-
providerOptions: entry.providerOptions
|
|
2491
|
+
providerOptions: withoutModelkit(entry.providerOptions),
|
|
2301
2492
|
catalog: entry
|
|
2302
2493
|
};
|
|
2303
2494
|
},
|
|
@@ -2317,7 +2508,7 @@ function createModelKit(config, adapters) {
|
|
|
2317
2508
|
options.prepareStep ?? options.experimental_prepareStep
|
|
2318
2509
|
)
|
|
2319
2510
|
});
|
|
2320
|
-
for (const event of steps.usage(result.steps)) await emit(event);
|
|
2511
|
+
for (const event of steps.usage(result.steps)) await emit(withRowUnit(event));
|
|
2321
2512
|
return result;
|
|
2322
2513
|
},
|
|
2323
2514
|
streamText(options, call = {}) {
|
|
@@ -2333,9 +2524,11 @@ function createModelKit(config, adapters) {
|
|
|
2333
2524
|
...textAbortOptions(options.abortSignal, call.signal),
|
|
2334
2525
|
model: target.languageModel,
|
|
2335
2526
|
providerOptions: {},
|
|
2336
|
-
prepareStep: steps.wrap(
|
|
2527
|
+
prepareStep: steps.wrap(
|
|
2528
|
+
options.prepareStep ?? options.experimental_prepareStep
|
|
2529
|
+
),
|
|
2337
2530
|
onFinish: async (event) => {
|
|
2338
|
-
for (const usage2 of steps.usage(event.steps)) await emit(usage2);
|
|
2531
|
+
for (const usage2 of steps.usage(event.steps)) await emit(withRowUnit(usage2));
|
|
2339
2532
|
await callerOnFinish?.(event);
|
|
2340
2533
|
}
|
|
2341
2534
|
});
|
|
@@ -2349,7 +2542,7 @@ function createModelKit(config, adapters) {
|
|
|
2349
2542
|
providerOptions: mergeTextProviderOptions(entry, options.providerOptions)
|
|
2350
2543
|
};
|
|
2351
2544
|
const result = await (0, import_ai2.generateObject)(sdkOptions);
|
|
2352
|
-
await emit(textUsageEvent(entry, provider, result.usage));
|
|
2545
|
+
await emit(withRowUnit(textUsageEvent(entry, provider, result.usage)));
|
|
2353
2546
|
return result;
|
|
2354
2547
|
},
|
|
2355
2548
|
streamObject(options, call = {}) {
|
|
@@ -2361,7 +2554,7 @@ function createModelKit(config, adapters) {
|
|
|
2361
2554
|
model: languageModel2,
|
|
2362
2555
|
providerOptions: mergeTextProviderOptions(entry, options.providerOptions),
|
|
2363
2556
|
onFinish: async (event) => {
|
|
2364
|
-
await emit(textUsageEvent(entry, provider, event.usage));
|
|
2557
|
+
await emit(withRowUnit(textUsageEvent(entry, provider, event.usage)));
|
|
2365
2558
|
await callerOnFinish?.(event);
|
|
2366
2559
|
}
|
|
2367
2560
|
};
|
|
@@ -2371,7 +2564,7 @@ function createModelKit(config, adapters) {
|
|
|
2371
2564
|
}
|
|
2372
2565
|
|
|
2373
2566
|
// src/adapters/ark.ts
|
|
2374
|
-
var
|
|
2567
|
+
var import_zod5 = require("zod");
|
|
2375
2568
|
var ARK_BASE_URL = "https://ark.ap-southeast.bytepluses.com/api/v3";
|
|
2376
2569
|
var SUBMIT_PATH = "/contents/generations/tasks";
|
|
2377
2570
|
var SEEDANCE_POLL_INTERVAL_MS = 15e3;
|
|
@@ -2390,6 +2583,7 @@ var SEEDREAM_SIZES = {
|
|
|
2390
2583
|
"3:2": "1248x832",
|
|
2391
2584
|
"2:3": "832x1248",
|
|
2392
2585
|
"21:9": "1568x672",
|
|
2586
|
+
"9:21": "672x1568",
|
|
2393
2587
|
"4:5": "864x1080",
|
|
2394
2588
|
"5:4": "1080x864"
|
|
2395
2589
|
},
|
|
@@ -2402,16 +2596,34 @@ var SEEDREAM_SIZES = {
|
|
|
2402
2596
|
"3:2": "2496x1664",
|
|
2403
2597
|
"2:3": "1664x2496",
|
|
2404
2598
|
"21:9": "3136x1344",
|
|
2599
|
+
"9:21": "1344x3136",
|
|
2405
2600
|
"4:5": "1728x2160",
|
|
2406
2601
|
"5:4": "2160x1728"
|
|
2602
|
+
},
|
|
2603
|
+
// 4K keeps the long edge at Ark's 4096 cap (a doubled 2K entry would exceed
|
|
2604
|
+
// it); sides are multiples of 16.
|
|
2605
|
+
"4K": {
|
|
2606
|
+
"1:1": "4096x4096",
|
|
2607
|
+
"4:3": "4096x3072",
|
|
2608
|
+
"3:4": "3072x4096",
|
|
2609
|
+
"16:9": "4096x2304",
|
|
2610
|
+
"9:16": "2304x4096",
|
|
2611
|
+
"3:2": "4096x2736",
|
|
2612
|
+
"2:3": "2736x4096",
|
|
2613
|
+
"21:9": "4096x1760",
|
|
2614
|
+
"9:21": "1760x4096",
|
|
2615
|
+
"4:5": "3280x4096",
|
|
2616
|
+
"5:4": "4096x3280"
|
|
2407
2617
|
}
|
|
2408
2618
|
};
|
|
2409
2619
|
var arkAdapter = {
|
|
2410
2620
|
id: "ark",
|
|
2411
2621
|
async generateImage(req, ctx) {
|
|
2622
|
+
throwIfAborted(ctx.signal);
|
|
2412
2623
|
return generateSeedreamImage(req, ctx);
|
|
2413
2624
|
},
|
|
2414
2625
|
async generateVideo(req, ctx) {
|
|
2626
|
+
throwIfAborted(ctx.signal);
|
|
2415
2627
|
return generateSeedanceVideo(req, ctx);
|
|
2416
2628
|
}
|
|
2417
2629
|
};
|
|
@@ -2429,9 +2641,9 @@ function arkKey(ctx) {
|
|
|
2429
2641
|
return key;
|
|
2430
2642
|
}
|
|
2431
2643
|
function throwArkError(status, body, model) {
|
|
2432
|
-
const parsed =
|
|
2644
|
+
const parsed = import_zod5.z.string().safeParse(body);
|
|
2433
2645
|
const text2 = parsed.success ? parsed.data : JSON.stringify(body ?? "");
|
|
2434
|
-
if (/sensitive.?content|
|
|
2646
|
+
if (/sensitive.?content|human.?face/i.test(text2)) {
|
|
2435
2647
|
const init = {
|
|
2436
2648
|
code: "content_blocked",
|
|
2437
2649
|
message: `ark rejected the request: ${text2.slice(0, 500)}`,
|
|
@@ -2443,10 +2655,20 @@ function throwArkError(status, body, model) {
|
|
|
2443
2655
|
if (status !== void 0) init.status = status;
|
|
2444
2656
|
throw new ModelKitError(init);
|
|
2445
2657
|
}
|
|
2658
|
+
if (status === void 0) {
|
|
2659
|
+
throw new ModelKitError({
|
|
2660
|
+
code: "provider_rejected",
|
|
2661
|
+
message: `ark rejected the request: ${text2.slice(0, 500)}`,
|
|
2662
|
+
provider: "ark",
|
|
2663
|
+
model,
|
|
2664
|
+
body,
|
|
2665
|
+
retryable: false
|
|
2666
|
+
});
|
|
2667
|
+
}
|
|
2446
2668
|
throw classifyHttpError(status, body, "ark", model);
|
|
2447
2669
|
}
|
|
2448
2670
|
function seedreamSize(aspect, size) {
|
|
2449
|
-
const tier = size === "
|
|
2671
|
+
const tier = size === "4K" || size === "1K" ? size : "2K";
|
|
2450
2672
|
const table = SEEDREAM_SIZES[tier];
|
|
2451
2673
|
return table[aspect ?? ""] ?? table["1:1"] ?? "2048x2048";
|
|
2452
2674
|
}
|
|
@@ -2457,17 +2679,13 @@ function sniffedImageMime(bytes) {
|
|
|
2457
2679
|
return "image/webp";
|
|
2458
2680
|
return "image/jpeg";
|
|
2459
2681
|
}
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
}
|
|
2464
|
-
var SeedreamImageSchema = import_zod4.z.object({
|
|
2465
|
-
url: import_zod4.z.string().optional(),
|
|
2466
|
-
b64_json: import_zod4.z.string().optional()
|
|
2682
|
+
var SeedreamImageSchema = import_zod5.z.object({
|
|
2683
|
+
url: import_zod5.z.string().optional(),
|
|
2684
|
+
b64_json: import_zod5.z.string().optional()
|
|
2467
2685
|
});
|
|
2468
|
-
var SeedreamResponseSchema =
|
|
2469
|
-
data:
|
|
2470
|
-
error:
|
|
2686
|
+
var SeedreamResponseSchema = import_zod5.z.object({
|
|
2687
|
+
data: import_zod5.z.array(SeedreamImageSchema).optional(),
|
|
2688
|
+
error: import_zod5.z.object({ message: import_zod5.z.string().optional(), code: import_zod5.z.string().optional() }).optional()
|
|
2471
2689
|
});
|
|
2472
2690
|
function retryOptsFor(ctx, attempts = 3) {
|
|
2473
2691
|
const opts = { attempts };
|
|
@@ -2478,11 +2696,16 @@ function fetchInitFor(ctx, init) {
|
|
|
2478
2696
|
if (ctx.signal !== void 0) init.signal = ctx.signal;
|
|
2479
2697
|
return init;
|
|
2480
2698
|
}
|
|
2699
|
+
function arkFetch(ctx, url, init) {
|
|
2700
|
+
return ctx.fetch(url, fetchInitFor(ctx, init)).catch((cause) => {
|
|
2701
|
+
throw classifyThrown("ark", cause, ctx.model.id);
|
|
2702
|
+
});
|
|
2703
|
+
}
|
|
2481
2704
|
async function generateSeedreamImage(req, ctx) {
|
|
2482
2705
|
const key = arkKey(ctx);
|
|
2483
2706
|
const modelId = ctx.model.id;
|
|
2484
2707
|
const size = seedreamSize(req.aspectRatio, req.size);
|
|
2485
|
-
const refs = (req.references ?? []).map(
|
|
2708
|
+
const refs = (req.references ?? []).map(refToUrl);
|
|
2486
2709
|
const body = {
|
|
2487
2710
|
model: ctx.model.providerModelId,
|
|
2488
2711
|
prompt: req.prompt,
|
|
@@ -2495,14 +2718,11 @@ async function generateSeedreamImage(req, ctx) {
|
|
|
2495
2718
|
if (refs.length === 1 && firstRef !== void 0) body.image = firstRef;
|
|
2496
2719
|
else if (refs.length > 1) body.image = refs;
|
|
2497
2720
|
const data = await withRetry(async () => {
|
|
2498
|
-
const res = await ctx
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
body: JSON.stringify(body)
|
|
2504
|
-
})
|
|
2505
|
-
);
|
|
2721
|
+
const res = await arkFetch(ctx, `${arkBaseUrl(ctx)}/images/generations`, {
|
|
2722
|
+
method: "POST",
|
|
2723
|
+
headers: { Authorization: `Bearer ${key}`, "Content-Type": "application/json" },
|
|
2724
|
+
body: JSON.stringify(body)
|
|
2725
|
+
});
|
|
2506
2726
|
if (!res.ok) {
|
|
2507
2727
|
const text2 = await res.text().catch(() => "");
|
|
2508
2728
|
throwArkError(res.status, text2, modelId);
|
|
@@ -2517,7 +2737,7 @@ async function generateSeedreamImage(req, ctx) {
|
|
|
2517
2737
|
bytes = Buffer.from(first.b64_json, "base64");
|
|
2518
2738
|
} else if (first?.url) {
|
|
2519
2739
|
const imageUrl = first.url;
|
|
2520
|
-
const res = await ctx
|
|
2740
|
+
const res = await arkFetch(ctx, imageUrl, {});
|
|
2521
2741
|
if (!res.ok) {
|
|
2522
2742
|
const text2 = await res.text().catch(() => "");
|
|
2523
2743
|
throwArkError(res.status, text2, modelId);
|
|
@@ -2537,13 +2757,21 @@ async function generateSeedreamImage(req, ctx) {
|
|
|
2537
2757
|
if (req.quality !== void 0) usage2.imageQuality = req.quality;
|
|
2538
2758
|
return { images: [{ bytes, mime: sniffedImageMime(bytes) }], usage: usage2, raw: data };
|
|
2539
2759
|
}
|
|
2540
|
-
var
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
content: import_zod4.z.object({ video_url: import_zod4.z.string().optional() }).optional(),
|
|
2544
|
-
error: import_zod4.z.union([import_zod4.z.string(), import_zod4.z.object({ message: import_zod4.z.string().optional() })]).optional()
|
|
2760
|
+
var SeedanceUsageSchema = import_zod5.z.object({
|
|
2761
|
+
total_tokens: import_zod5.z.number().optional(),
|
|
2762
|
+
completion_tokens: import_zod5.z.number().optional()
|
|
2545
2763
|
});
|
|
2546
|
-
var
|
|
2764
|
+
var SeedanceResponseSchema = import_zod5.z.object({
|
|
2765
|
+
id: import_zod5.z.string().optional(),
|
|
2766
|
+
status: import_zod5.z.string().optional(),
|
|
2767
|
+
content: import_zod5.z.object({ video_url: import_zod5.z.string().optional() }).optional(),
|
|
2768
|
+
usage: SeedanceUsageSchema.optional(),
|
|
2769
|
+
duration: import_zod5.z.number().optional(),
|
|
2770
|
+
framespersecond: import_zod5.z.number().optional(),
|
|
2771
|
+
resolution: import_zod5.z.string().optional(),
|
|
2772
|
+
error: import_zod5.z.union([import_zod5.z.string(), import_zod5.z.object({ message: import_zod5.z.string().optional() })]).optional()
|
|
2773
|
+
});
|
|
2774
|
+
var SeedanceErrorMessageSchema = import_zod5.z.object({ message: import_zod5.z.string().optional() });
|
|
2547
2775
|
function seedanceUsage(ctx, req, duration) {
|
|
2548
2776
|
const usage2 = {
|
|
2549
2777
|
model: ctx.model.id,
|
|
@@ -2557,7 +2785,7 @@ function seedanceUsage(ctx, req, duration) {
|
|
|
2557
2785
|
return usage2;
|
|
2558
2786
|
}
|
|
2559
2787
|
function seedanceErrorMessage(error, status) {
|
|
2560
|
-
const asString =
|
|
2788
|
+
const asString = import_zod5.z.string().safeParse(error);
|
|
2561
2789
|
if (asString.success) return asString.data;
|
|
2562
2790
|
const asObject = SeedanceErrorMessageSchema.safeParse(error);
|
|
2563
2791
|
if (asObject.success && asObject.data.message !== void 0) return asObject.data.message;
|
|
@@ -2572,42 +2800,42 @@ async function generateSeedanceVideo(req, ctx) {
|
|
|
2572
2800
|
if (req.firstFrame) {
|
|
2573
2801
|
content.push({
|
|
2574
2802
|
type: "image_url",
|
|
2575
|
-
image_url: { url:
|
|
2803
|
+
image_url: { url: refToUrl(req.firstFrame) },
|
|
2576
2804
|
role: "first_frame"
|
|
2577
2805
|
});
|
|
2578
2806
|
}
|
|
2579
2807
|
if (req.lastFrame) {
|
|
2580
2808
|
content.push({
|
|
2581
2809
|
type: "image_url",
|
|
2582
|
-
image_url: { url:
|
|
2810
|
+
image_url: { url: refToUrl(req.lastFrame) },
|
|
2583
2811
|
role: "last_frame"
|
|
2584
2812
|
});
|
|
2585
2813
|
}
|
|
2586
2814
|
for (const ref of req.referenceImages ?? []) {
|
|
2587
2815
|
content.push({
|
|
2588
2816
|
type: "image_url",
|
|
2589
|
-
image_url: { url:
|
|
2817
|
+
image_url: { url: refToUrl(ref) },
|
|
2590
2818
|
role: "reference_image"
|
|
2591
2819
|
});
|
|
2592
2820
|
}
|
|
2593
2821
|
if (req.sourceVideo) {
|
|
2594
2822
|
content.push({
|
|
2595
2823
|
type: "video_url",
|
|
2596
|
-
video_url: { url:
|
|
2824
|
+
video_url: { url: refToUrl(req.sourceVideo) },
|
|
2597
2825
|
role: "reference_video"
|
|
2598
2826
|
});
|
|
2599
2827
|
}
|
|
2600
2828
|
for (const ref of req.referenceVideos ?? []) {
|
|
2601
2829
|
content.push({
|
|
2602
2830
|
type: "video_url",
|
|
2603
|
-
video_url: { url:
|
|
2831
|
+
video_url: { url: refToUrl(ref) },
|
|
2604
2832
|
role: "reference_video"
|
|
2605
2833
|
});
|
|
2606
2834
|
}
|
|
2607
2835
|
for (const ref of req.referenceAudios ?? []) {
|
|
2608
2836
|
content.push({
|
|
2609
2837
|
type: "audio_url",
|
|
2610
|
-
audio_url: { url:
|
|
2838
|
+
audio_url: { url: refToUrl(ref) },
|
|
2611
2839
|
role: "reference_audio"
|
|
2612
2840
|
});
|
|
2613
2841
|
}
|
|
@@ -2621,15 +2849,13 @@ async function generateSeedanceVideo(req, ctx) {
|
|
|
2621
2849
|
if (!hasFrameAnchor && req.aspectRatio !== void 0) body.ratio = req.aspectRatio;
|
|
2622
2850
|
if (req.generateAudio !== void 0) body.generate_audio = req.generateAudio;
|
|
2623
2851
|
if (req.seed !== void 0) body.seed = req.seed;
|
|
2852
|
+
if (req.watermark !== void 0) body.watermark = req.watermark;
|
|
2624
2853
|
const submit = await withRetry(async () => {
|
|
2625
|
-
const res = await ctx
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
body: JSON.stringify(body)
|
|
2631
|
-
})
|
|
2632
|
-
);
|
|
2854
|
+
const res = await arkFetch(ctx, `${arkBaseUrl(ctx)}${SUBMIT_PATH}`, {
|
|
2855
|
+
method: "POST",
|
|
2856
|
+
headers: { Authorization: `Bearer ${key}`, "Content-Type": "application/json" },
|
|
2857
|
+
body: JSON.stringify(body)
|
|
2858
|
+
});
|
|
2633
2859
|
if (!res.ok) {
|
|
2634
2860
|
const text2 = await res.text().catch(() => "");
|
|
2635
2861
|
throwArkError(res.status, text2, modelId);
|
|
@@ -2642,12 +2868,9 @@ async function generateSeedanceVideo(req, ctx) {
|
|
|
2642
2868
|
const jobId = submit.id;
|
|
2643
2869
|
const usage2 = seedanceUsage(ctx, req, duration);
|
|
2644
2870
|
const fetchStatus = async () => {
|
|
2645
|
-
const res = await ctx
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
headers: { Authorization: `Bearer ${key}` }
|
|
2649
|
-
})
|
|
2650
|
-
);
|
|
2871
|
+
const res = await arkFetch(ctx, `${arkBaseUrl(ctx)}${SUBMIT_PATH}/${jobId}`, {
|
|
2872
|
+
headers: { Authorization: `Bearer ${key}` }
|
|
2873
|
+
});
|
|
2651
2874
|
if (!res.ok) {
|
|
2652
2875
|
if (res.status === 429 || res.status >= 500) return void 0;
|
|
2653
2876
|
const text2 = await res.text().catch(() => "");
|
|
@@ -2690,6 +2913,11 @@ async function generateSeedanceVideo(req, ctx) {
|
|
|
2690
2913
|
"Seedance task succeeded but returned no video_url",
|
|
2691
2914
|
modelId
|
|
2692
2915
|
);
|
|
2916
|
+
const tokens = polled.usage;
|
|
2917
|
+
if (tokens?.total_tokens !== void 0 && tokens.completion_tokens !== void 0) {
|
|
2918
|
+
usage2.inputTokens = tokens.total_tokens - tokens.completion_tokens;
|
|
2919
|
+
usage2.outputTokens = tokens.completion_tokens;
|
|
2920
|
+
}
|
|
2693
2921
|
return {
|
|
2694
2922
|
video: { url, expiresAt: new Date(Date.now() + VIDEO_URL_TTL_MS) },
|
|
2695
2923
|
usage: usage2,
|
|
@@ -2708,43 +2936,6 @@ async function generateSeedanceVideo(req, ctx) {
|
|
|
2708
2936
|
// src/adapters/fal.ts
|
|
2709
2937
|
var import_zod6 = require("zod");
|
|
2710
2938
|
var import_client = require("@fal-ai/client");
|
|
2711
|
-
|
|
2712
|
-
// src/json.ts
|
|
2713
|
-
var import_zod5 = require("zod");
|
|
2714
|
-
var JsonValueSchema = import_zod5.z.lazy(
|
|
2715
|
-
() => import_zod5.z.union([
|
|
2716
|
-
import_zod5.z.string(),
|
|
2717
|
-
import_zod5.z.number(),
|
|
2718
|
-
import_zod5.z.boolean(),
|
|
2719
|
-
import_zod5.z.null(),
|
|
2720
|
-
import_zod5.z.array(JsonValueSchema),
|
|
2721
|
-
import_zod5.z.record(import_zod5.z.string(), JsonValueSchema)
|
|
2722
|
-
])
|
|
2723
|
-
);
|
|
2724
|
-
var JsonObjectSchema = import_zod5.z.record(import_zod5.z.string(), JsonValueSchema);
|
|
2725
|
-
async function readErrorBody(res) {
|
|
2726
|
-
const text2 = await res.text().catch(() => "");
|
|
2727
|
-
try {
|
|
2728
|
-
return JsonValueSchema.parse(JSON.parse(text2));
|
|
2729
|
-
} catch {
|
|
2730
|
-
return text2;
|
|
2731
|
-
}
|
|
2732
|
-
}
|
|
2733
|
-
var thrownErrorSchema = import_zod5.z.object({
|
|
2734
|
-
message: import_zod5.z.string().optional(),
|
|
2735
|
-
status: import_zod5.z.number().optional(),
|
|
2736
|
-
statusCode: import_zod5.z.number().optional(),
|
|
2737
|
-
responseBody: import_zod5.z.string().optional()
|
|
2738
|
-
});
|
|
2739
|
-
function describeThrown(cause) {
|
|
2740
|
-
const parsed = thrownErrorSchema.safeParse(cause);
|
|
2741
|
-
if (!parsed.success) return { message: String(cause), status: void 0, body: String(cause) };
|
|
2742
|
-
const { message, status, statusCode, responseBody } = parsed.data;
|
|
2743
|
-
const body = responseBody ?? message ?? String(cause);
|
|
2744
|
-
return { message: message ?? String(cause), status: status ?? statusCode, body };
|
|
2745
|
-
}
|
|
2746
|
-
|
|
2747
|
-
// src/adapters/fal.ts
|
|
2748
2939
|
var MUSE_T2I_ENDPOINT = "meta/muse-image/text-to-image";
|
|
2749
2940
|
var MUSE_EDIT_ENDPOINT = "meta/muse-image/edit";
|
|
2750
2941
|
var KLING_O1_ENDPOINT = "fal-ai/kling-video/o1/video-to-video/reference";
|
|
@@ -2756,10 +2947,33 @@ function defaultCreateFalClient(opts) {
|
|
|
2756
2947
|
const client2 = (0, import_client.createFalClient)(opts);
|
|
2757
2948
|
return {
|
|
2758
2949
|
async subscribe(endpoint, options) {
|
|
2759
|
-
const outcome = await client2.subscribe(endpoint,
|
|
2950
|
+
const outcome = await client2.subscribe(endpoint, options);
|
|
2760
2951
|
const unwrapped = falSubscribePayloadSchema.safeParse(outcome);
|
|
2761
2952
|
if (unwrapped.success) return unwrapped.data.data;
|
|
2762
2953
|
return JsonValueSchema.parse(outcome);
|
|
2954
|
+
},
|
|
2955
|
+
queue: {
|
|
2956
|
+
async submit(endpoint, options) {
|
|
2957
|
+
const submitted = await client2.queue.submit(endpoint, {
|
|
2958
|
+
input: options.input,
|
|
2959
|
+
...options.abortSignal !== void 0 ? { abortSignal: options.abortSignal } : {}
|
|
2960
|
+
});
|
|
2961
|
+
return { requestId: submitted.request_id };
|
|
2962
|
+
},
|
|
2963
|
+
async status(endpoint, options) {
|
|
2964
|
+
const current = await client2.queue.status(endpoint, {
|
|
2965
|
+
requestId: options.requestId,
|
|
2966
|
+
...options.abortSignal !== void 0 ? { abortSignal: options.abortSignal } : {}
|
|
2967
|
+
});
|
|
2968
|
+
return { status: current.status };
|
|
2969
|
+
},
|
|
2970
|
+
async result(endpoint, options) {
|
|
2971
|
+
const outcome = await client2.queue.result(endpoint, {
|
|
2972
|
+
requestId: options.requestId,
|
|
2973
|
+
...options.abortSignal !== void 0 ? { abortSignal: options.abortSignal } : {}
|
|
2974
|
+
});
|
|
2975
|
+
return JsonValueSchema.parse(outcome.data);
|
|
2976
|
+
}
|
|
2763
2977
|
}
|
|
2764
2978
|
};
|
|
2765
2979
|
}
|
|
@@ -2767,24 +2981,17 @@ var defaultDeps = { createFalClient: defaultCreateFalClient };
|
|
|
2767
2981
|
function createFalAdapter(deps = defaultDeps) {
|
|
2768
2982
|
return {
|
|
2769
2983
|
id: "fal",
|
|
2770
|
-
generateImage: (req, ctx) =>
|
|
2771
|
-
|
|
2984
|
+
generateImage: (req, ctx) => {
|
|
2985
|
+
throwIfAborted(ctx.signal);
|
|
2986
|
+
return generateMuseImage(req, ctx, deps);
|
|
2987
|
+
},
|
|
2988
|
+
generateVideo: (req, ctx) => {
|
|
2989
|
+
throwIfAborted(ctx.signal);
|
|
2990
|
+
return generateFalVideo(req, ctx, deps);
|
|
2991
|
+
}
|
|
2772
2992
|
};
|
|
2773
2993
|
}
|
|
2774
2994
|
var falAdapter = createFalAdapter();
|
|
2775
|
-
function refToUrl(ref) {
|
|
2776
|
-
if ("url" in ref) return ref.url;
|
|
2777
|
-
return `data:${ref.mime};base64,${Buffer.from(ref.bytes).toString("base64")}`;
|
|
2778
|
-
}
|
|
2779
|
-
async function readBody(res) {
|
|
2780
|
-
const text2 = await res.text().catch(() => "");
|
|
2781
|
-
try {
|
|
2782
|
-
const decoded = JsonValueSchema.safeParse(JSON.parse(text2));
|
|
2783
|
-
return decoded.success ? decoded.data : text2;
|
|
2784
|
-
} catch {
|
|
2785
|
-
return text2;
|
|
2786
|
-
}
|
|
2787
|
-
}
|
|
2788
2995
|
var falDetailSchema = import_zod6.z.object({ detail: JsonValueSchema });
|
|
2789
2996
|
function liftDetail(body) {
|
|
2790
2997
|
const parsed = falDetailSchema.safeParse(body);
|
|
@@ -2801,15 +3008,17 @@ var falSdkThrownSchema = import_zod6.z.object({
|
|
|
2801
3008
|
message: import_zod6.z.string().optional()
|
|
2802
3009
|
});
|
|
2803
3010
|
function falSdkError(cause, model) {
|
|
2804
|
-
if (isModelKitError(cause)) return cause;
|
|
2805
3011
|
const parsed = falSdkThrownSchema.safeParse(cause);
|
|
2806
3012
|
if (parsed.success) {
|
|
2807
3013
|
const status = parsed.data.status ?? parsed.data.statusCode;
|
|
2808
3014
|
const body = parsed.data.body ?? parsed.data.message ?? String(cause);
|
|
2809
|
-
return
|
|
3015
|
+
return classifyThrown("fal", cause, model, { status, body: liftDetail(body) });
|
|
2810
3016
|
}
|
|
2811
3017
|
const info = describeThrown(cause);
|
|
2812
|
-
return
|
|
3018
|
+
return classifyThrown("fal", cause, model, {
|
|
3019
|
+
status: info.status,
|
|
3020
|
+
body: liftDetail(info.body)
|
|
3021
|
+
});
|
|
2813
3022
|
}
|
|
2814
3023
|
function gatewayConfig(ctx) {
|
|
2815
3024
|
const cf = ctx.routing.cloudflare;
|
|
@@ -2891,7 +3100,7 @@ async function passthroughRequest(ctx, endpoint, input) {
|
|
|
2891
3100
|
}
|
|
2892
3101
|
return JsonValueSchema.parse(await resultRes.json());
|
|
2893
3102
|
}
|
|
2894
|
-
|
|
3103
|
+
function falClientOf(ctx, deps) {
|
|
2895
3104
|
const falKey = ctx.keys.fal;
|
|
2896
3105
|
if (!falKey) {
|
|
2897
3106
|
throw new ModelKitError({
|
|
@@ -2902,12 +3111,19 @@ async function subscribe(ctx, deps, endpoint, input) {
|
|
|
2902
3111
|
retryable: false
|
|
2903
3112
|
});
|
|
2904
3113
|
}
|
|
2905
|
-
|
|
3114
|
+
return deps.createFalClient({ credentials: falKey, fetch: ctx.fetch });
|
|
3115
|
+
}
|
|
3116
|
+
async function subscribe(ctx, deps, endpoint, input) {
|
|
3117
|
+
const client2 = falClientOf(ctx, deps);
|
|
3118
|
+
const options = {
|
|
3119
|
+
input,
|
|
3120
|
+
...ctx.signal !== void 0 ? { abortSignal: ctx.signal } : {}
|
|
3121
|
+
};
|
|
2906
3122
|
try {
|
|
2907
3123
|
return await withRetry(
|
|
2908
3124
|
async () => {
|
|
2909
3125
|
try {
|
|
2910
|
-
return await client2.subscribe(endpoint,
|
|
3126
|
+
return await client2.subscribe(endpoint, options);
|
|
2911
3127
|
} catch (cause) {
|
|
2912
3128
|
throw falSdkError(cause, ctx.model.id);
|
|
2913
3129
|
}
|
|
@@ -3012,8 +3228,12 @@ async function generateMuseImage(req, ctx, deps) {
|
|
|
3012
3228
|
raw: payload
|
|
3013
3229
|
};
|
|
3014
3230
|
}
|
|
3231
|
+
var H3_MAX_MODEL_IDS = /* @__PURE__ */ new Set([
|
|
3232
|
+
"minimax/h3-max",
|
|
3233
|
+
"minimax/h3-max/reference-to-video"
|
|
3234
|
+
]);
|
|
3015
3235
|
function minimaxFamily(providerModelId) {
|
|
3016
|
-
return providerModelId.toLowerCase()
|
|
3236
|
+
return H3_MAX_MODEL_IDS.has(providerModelId.toLowerCase()) ? "h3-max" : "h3";
|
|
3017
3237
|
}
|
|
3018
3238
|
function minimaxBase(req, family) {
|
|
3019
3239
|
const resolution = (family === "h3-max" ? req.resolution ?? "768p" : req.resolution ?? "2k").toUpperCase();
|
|
@@ -3021,14 +3241,17 @@ function minimaxBase(req, family) {
|
|
|
3021
3241
|
prompt: req.prompt.trim(),
|
|
3022
3242
|
duration: req.durationSeconds ?? 5,
|
|
3023
3243
|
resolution,
|
|
3024
|
-
prompt_expansion_mode: req.promptExpansion ?? "balanced"
|
|
3025
|
-
enable_safety_checker: true
|
|
3244
|
+
prompt_expansion_mode: req.promptExpansion ?? "balanced"
|
|
3026
3245
|
};
|
|
3246
|
+
if (req.safetyChecker !== void 0) input.enable_safety_checker = req.safetyChecker;
|
|
3027
3247
|
if (req.seed !== void 0) input.seed = req.seed;
|
|
3028
3248
|
return input;
|
|
3029
3249
|
}
|
|
3250
|
+
var KLING_MODEL_IDS = /* @__PURE__ */ new Set([
|
|
3251
|
+
"fal-ai/kling-video/o1/video-to-video/reference"
|
|
3252
|
+
]);
|
|
3030
3253
|
function isKling(providerModelId) {
|
|
3031
|
-
return providerModelId.toLowerCase()
|
|
3254
|
+
return KLING_MODEL_IDS.has(providerModelId.toLowerCase());
|
|
3032
3255
|
}
|
|
3033
3256
|
function klingO1Input(req) {
|
|
3034
3257
|
const source = req.sourceVideo ? refToUrl(req.sourceVideo) : void 0;
|
|
@@ -3041,13 +3264,14 @@ function klingO1Input(req) {
|
|
|
3041
3264
|
});
|
|
3042
3265
|
}
|
|
3043
3266
|
const duration = Math.min(10, Math.max(3, Math.round(req.durationSeconds ?? 5)));
|
|
3044
|
-
const ratio = req.aspectRatio === "16:9" || req.aspectRatio === "9:16" || req.aspectRatio === "1:1" ? req.aspectRatio : "auto";
|
|
3045
3267
|
const input = {
|
|
3046
3268
|
prompt: req.prompt,
|
|
3047
3269
|
video_url: source,
|
|
3048
|
-
duration: String(duration)
|
|
3049
|
-
aspect_ratio: ratio
|
|
3270
|
+
duration: String(duration)
|
|
3050
3271
|
};
|
|
3272
|
+
if (req.aspectRatio !== "adaptive") {
|
|
3273
|
+
input.aspect_ratio = req.aspectRatio === "16:9" || req.aspectRatio === "9:16" || req.aspectRatio === "1:1" ? req.aspectRatio : "auto";
|
|
3274
|
+
}
|
|
3051
3275
|
const refs = (req.referenceImages ?? []).map(refToUrl);
|
|
3052
3276
|
if (refs.length > 0) input.image_urls = refs;
|
|
3053
3277
|
return input;
|
|
@@ -3076,13 +3300,7 @@ async function generateFalVideo(req, ctx, deps) {
|
|
|
3076
3300
|
if (ctx.routing.fal === "cloudflare-passthrough") {
|
|
3077
3301
|
return await passthroughVideoJob(ctx, req, KLING_O1_ENDPOINT, input);
|
|
3078
3302
|
}
|
|
3079
|
-
|
|
3080
|
-
return completedVideoJob(
|
|
3081
|
-
ctx,
|
|
3082
|
-
req,
|
|
3083
|
-
extractVideoUrl(result2, KLING_O1_ENDPOINT, ctx.model.id),
|
|
3084
|
-
result2
|
|
3085
|
-
);
|
|
3303
|
+
return await submitQueueJob(ctx, req, deps, KLING_O1_ENDPOINT, input);
|
|
3086
3304
|
}
|
|
3087
3305
|
const family = minimaxFamily(providerModelId);
|
|
3088
3306
|
const refs = {
|
|
@@ -3106,24 +3324,88 @@ async function generateFalVideo(req, ctx, deps) {
|
|
|
3106
3324
|
if (lastFrame) base.end_image_url = lastFrame;
|
|
3107
3325
|
} else {
|
|
3108
3326
|
endpoint = `minimax/${family}/text-to-video`;
|
|
3109
|
-
|
|
3327
|
+
if (req.aspectRatio !== void 0 && req.aspectRatio !== "adaptive") {
|
|
3328
|
+
base.aspect_ratio = req.aspectRatio;
|
|
3329
|
+
}
|
|
3110
3330
|
}
|
|
3111
3331
|
if (ctx.routing.fal === "cloudflare-passthrough") {
|
|
3112
3332
|
return await passthroughVideoJob(ctx, req, endpoint, base);
|
|
3113
3333
|
}
|
|
3114
|
-
|
|
3115
|
-
|
|
3334
|
+
return await submitQueueJob(ctx, req, deps, endpoint, base);
|
|
3335
|
+
}
|
|
3336
|
+
async function submitQueueJob(ctx, req, deps, endpoint, input) {
|
|
3337
|
+
const client2 = falClientOf(ctx, deps);
|
|
3338
|
+
let submitted;
|
|
3339
|
+
try {
|
|
3340
|
+
submitted = await withRetry(
|
|
3341
|
+
async () => {
|
|
3342
|
+
try {
|
|
3343
|
+
return await client2.queue.submit(endpoint, {
|
|
3344
|
+
input,
|
|
3345
|
+
...ctx.signal !== void 0 ? { abortSignal: ctx.signal } : {}
|
|
3346
|
+
});
|
|
3347
|
+
} catch (cause) {
|
|
3348
|
+
throw falSdkError(cause, ctx.model.id);
|
|
3349
|
+
}
|
|
3350
|
+
},
|
|
3351
|
+
ctx.signal !== void 0 ? { signal: ctx.signal } : {}
|
|
3352
|
+
);
|
|
3353
|
+
} catch (cause) {
|
|
3354
|
+
throw falSdkError(cause, ctx.model.id);
|
|
3355
|
+
}
|
|
3356
|
+
return queuedVideoJob(ctx, req, client2, endpoint, submitted.requestId);
|
|
3116
3357
|
}
|
|
3117
|
-
function
|
|
3358
|
+
function queuedVideoJob(ctx, req, client2, endpoint, requestId) {
|
|
3359
|
+
const readStatus = async () => {
|
|
3360
|
+
try {
|
|
3361
|
+
const options = {
|
|
3362
|
+
requestId,
|
|
3363
|
+
...ctx.signal !== void 0 ? { abortSignal: ctx.signal } : {}
|
|
3364
|
+
};
|
|
3365
|
+
return (await client2.queue.status(endpoint, options)).status;
|
|
3366
|
+
} catch (cause) {
|
|
3367
|
+
throw falSdkError(cause, ctx.model.id);
|
|
3368
|
+
}
|
|
3369
|
+
};
|
|
3118
3370
|
const duration = req.durationSeconds ?? 5;
|
|
3119
|
-
const result = { video: { url }, usage: videoUsage(ctx, req, duration), raw };
|
|
3120
3371
|
return {
|
|
3121
|
-
jobId:
|
|
3372
|
+
jobId: requestId,
|
|
3122
3373
|
async poll() {
|
|
3123
|
-
|
|
3374
|
+
try {
|
|
3375
|
+
const status = await readStatus();
|
|
3376
|
+
if (status === "COMPLETED") return { status: "succeeded" };
|
|
3377
|
+
if (status === "IN_QUEUE") return { status: "pending" };
|
|
3378
|
+
return { status: "running" };
|
|
3379
|
+
} catch (cause) {
|
|
3380
|
+
if (isModelKitError(cause) && !cause.retryable)
|
|
3381
|
+
return { status: "failed" };
|
|
3382
|
+
return { status: "pending" };
|
|
3383
|
+
}
|
|
3124
3384
|
},
|
|
3125
|
-
async result() {
|
|
3126
|
-
|
|
3385
|
+
async result(opts) {
|
|
3386
|
+
const signal = opts?.signal ?? ctx.signal;
|
|
3387
|
+
const pollOptions = {
|
|
3388
|
+
intervalMs: opts?.pollIntervalMs ?? PASSTHROUGH_POLL_MS,
|
|
3389
|
+
timeoutMs: opts?.timeoutMs ?? 15 * 6e4
|
|
3390
|
+
};
|
|
3391
|
+
if (signal !== void 0) pollOptions.signal = signal;
|
|
3392
|
+
const queueOptions = {
|
|
3393
|
+
requestId,
|
|
3394
|
+
...signal !== void 0 ? { abortSignal: signal } : {}
|
|
3395
|
+
};
|
|
3396
|
+
const payload = await pollUntil(async () => {
|
|
3397
|
+
try {
|
|
3398
|
+
const current = await client2.queue.status(endpoint, queueOptions);
|
|
3399
|
+
if (current.status !== "COMPLETED") return void 0;
|
|
3400
|
+
return await client2.queue.result(endpoint, queueOptions);
|
|
3401
|
+
} catch (cause) {
|
|
3402
|
+
const err = falSdkError(cause, ctx.model.id);
|
|
3403
|
+
if (err.retryable) return void 0;
|
|
3404
|
+
throw err;
|
|
3405
|
+
}
|
|
3406
|
+
}, pollOptions);
|
|
3407
|
+
const url = extractVideoUrl(payload, endpoint, ctx.model.id);
|
|
3408
|
+
return { video: { url }, usage: videoUsage(ctx, req, duration), raw: payload };
|
|
3127
3409
|
}
|
|
3128
3410
|
};
|
|
3129
3411
|
}
|
|
@@ -3474,9 +3756,7 @@ function sdkStatus(cause) {
|
|
|
3474
3756
|
return describeThrown(cause).status;
|
|
3475
3757
|
}
|
|
3476
3758
|
function throwSdkError(cause, model) {
|
|
3477
|
-
|
|
3478
|
-
const info = describeThrown(cause);
|
|
3479
|
-
throw classifyHttpError(info.status, info.body, "google-genai", model);
|
|
3759
|
+
throw classifyThrown("google-genai", cause, model);
|
|
3480
3760
|
}
|
|
3481
3761
|
function toBase64(bytes) {
|
|
3482
3762
|
return Buffer.from(bytes).toString("base64");
|
|
@@ -3532,6 +3812,14 @@ async function generateVeoVideo(req, ctx, createGenAIClient) {
|
|
|
3532
3812
|
model: modelId
|
|
3533
3813
|
});
|
|
3534
3814
|
}
|
|
3815
|
+
if (req.lastFrame !== void 0 && req.firstFrame === void 0) {
|
|
3816
|
+
throw new ModelKitError({
|
|
3817
|
+
code: "missing_input",
|
|
3818
|
+
message: `${modelId} requires firstFrame when lastFrame is set`,
|
|
3819
|
+
provider: "google-genai",
|
|
3820
|
+
model: modelId
|
|
3821
|
+
});
|
|
3822
|
+
}
|
|
3535
3823
|
const duration = req.durationSeconds ?? 8;
|
|
3536
3824
|
const personGeneration = req.firstFrame ?? refs.length > 0 ? "allow_adult" : "allow_all";
|
|
3537
3825
|
let image;
|
|
@@ -3598,7 +3886,7 @@ async function generateVeoVideo(req, ctx, createGenAIClient) {
|
|
|
3598
3886
|
throwSdkError(cause, modelId);
|
|
3599
3887
|
}
|
|
3600
3888
|
};
|
|
3601
|
-
const jobId = operation.name ??
|
|
3889
|
+
const jobId = operation.name ?? crypto.randomUUID();
|
|
3602
3890
|
const usage2 = videoUsage2(ctx, req, duration);
|
|
3603
3891
|
return {
|
|
3604
3892
|
jobId,
|
|
@@ -3680,12 +3968,17 @@ async function generateOmniVideo(req, ctx, createGenAIClient) {
|
|
|
3680
3968
|
const duration = req.durationSeconds ?? 8;
|
|
3681
3969
|
const images = req.referenceImages ?? [];
|
|
3682
3970
|
const videos = req.referenceVideos ?? [];
|
|
3683
|
-
const task = req.sourceVideo ? "edit" :
|
|
3684
|
-
const
|
|
3685
|
-
|
|
3686
|
-
|
|
3687
|
-
|
|
3688
|
-
|
|
3971
|
+
const task = req.sourceVideo ? "edit" : req.firstFrame ? "image_to_video" : images.length > 0 || videos.length > 0 ? "reference_to_video" : "text_to_video";
|
|
3972
|
+
const isOmniV1 = providerModelId === "gemini-omni-flash-preview";
|
|
3973
|
+
const responseFormat = { type: "video", delivery: "uri" };
|
|
3974
|
+
if (req.sourceVideo === void 0 && req.aspectRatio !== void 0 && req.aspectRatio !== "adaptive") {
|
|
3975
|
+
responseFormat.aspect_ratio = toOmniAspect(req.aspectRatio);
|
|
3976
|
+
}
|
|
3977
|
+
if (!isOmniV1) {
|
|
3978
|
+
const omniResolution = toOmniResolution(req.resolution);
|
|
3979
|
+
if (omniResolution !== void 0) responseFormat.resolution = omniResolution;
|
|
3980
|
+
}
|
|
3981
|
+
if (req.durationSeconds !== void 0) responseFormat.duration = `${req.durationSeconds}s`;
|
|
3689
3982
|
const client2 = createGenAIClient({ apiKey });
|
|
3690
3983
|
const uploadedByUri = /* @__PURE__ */ new Map();
|
|
3691
3984
|
const uploadedNames = [];
|
|
@@ -3709,7 +4002,8 @@ async function generateOmniVideo(req, ctx, createGenAIClient) {
|
|
|
3709
4002
|
model: providerModelId,
|
|
3710
4003
|
input,
|
|
3711
4004
|
response_format: responseFormat,
|
|
3712
|
-
generation_config: { video_config: { task } }
|
|
4005
|
+
generation_config: { video_config: { task } },
|
|
4006
|
+
store: true
|
|
3713
4007
|
});
|
|
3714
4008
|
const createRetryOptions = { attempts: 3 };
|
|
3715
4009
|
if (ctx.signal !== void 0) createRetryOptions.signal = ctx.signal;
|
|
@@ -3731,6 +4025,7 @@ async function generateOmniVideo(req, ctx, createGenAIClient) {
|
|
|
3731
4025
|
});
|
|
3732
4026
|
}
|
|
3733
4027
|
for (const ref of videos) {
|
|
4028
|
+
if (ref.label !== void 0) parts.push({ type: "text", text: ref.label });
|
|
3734
4029
|
const media = await resolveMedia(ref, ctx.fetch, ctx.signal, "video/mp4", modelId);
|
|
3735
4030
|
parts.push({
|
|
3736
4031
|
type: "video",
|
|
@@ -3739,6 +4034,8 @@ async function generateOmniVideo(req, ctx, createGenAIClient) {
|
|
|
3739
4034
|
});
|
|
3740
4035
|
}
|
|
3741
4036
|
if (req.firstFrame) {
|
|
4037
|
+
if (req.firstFrame.label !== void 0)
|
|
4038
|
+
parts.push({ type: "text", text: req.firstFrame.label });
|
|
3742
4039
|
const media = await resolveMedia(
|
|
3743
4040
|
req.firstFrame,
|
|
3744
4041
|
ctx.fetch,
|
|
@@ -3757,6 +4054,7 @@ async function generateOmniVideo(req, ctx, createGenAIClient) {
|
|
|
3757
4054
|
}
|
|
3758
4055
|
}
|
|
3759
4056
|
for (const ref of images) {
|
|
4057
|
+
if (ref.label !== void 0) parts.push({ type: "text", text: ref.label });
|
|
3760
4058
|
const media = await resolveMedia(ref, ctx.fetch, ctx.signal, "image/png", modelId);
|
|
3761
4059
|
if (media.bytes.length > OMNI_INLINE_LIMIT_BYTES) {
|
|
3762
4060
|
parts.push({
|
|
@@ -3791,25 +4089,16 @@ async function generateOmniVideo(req, ctx, createGenAIClient) {
|
|
|
3791
4089
|
};
|
|
3792
4090
|
return inline;
|
|
3793
4091
|
});
|
|
3794
|
-
const inlineRetryOptions = { attempts: 3 };
|
|
3795
|
-
if (ctx.signal !== void 0) inlineRetryOptions.signal = ctx.signal;
|
|
3796
4092
|
try {
|
|
3797
|
-
interaction = await
|
|
3798
|
-
try {
|
|
3799
|
-
return await callCreate(inlineParts);
|
|
3800
|
-
} catch (inlineCause) {
|
|
3801
|
-
throwSdkError(inlineCause, modelId);
|
|
3802
|
-
}
|
|
3803
|
-
}, inlineRetryOptions);
|
|
4093
|
+
interaction = await callCreate(inlineParts);
|
|
3804
4094
|
} catch (inlineCause) {
|
|
3805
4095
|
throwSdkError(inlineCause, modelId);
|
|
3806
4096
|
}
|
|
3807
4097
|
}
|
|
3808
|
-
}
|
|
4098
|
+
} finally {
|
|
3809
4099
|
await cleanupUploads();
|
|
3810
|
-
throw cause;
|
|
3811
4100
|
}
|
|
3812
|
-
const jobId = interaction.id ??
|
|
4101
|
+
const jobId = interaction.id ?? crypto.randomUUID();
|
|
3813
4102
|
const usage2 = videoUsage2(ctx, req, duration);
|
|
3814
4103
|
const getInteraction = async () => {
|
|
3815
4104
|
try {
|
|
@@ -3836,47 +4125,43 @@ async function generateOmniVideo(req, ctx, createGenAIClient) {
|
|
|
3836
4125
|
timeoutMs: opts?.timeoutMs ?? RESULT_TIMEOUT_MS2
|
|
3837
4126
|
};
|
|
3838
4127
|
if (signal !== void 0) pollOptions.signal = signal;
|
|
3839
|
-
|
|
3840
|
-
const
|
|
3841
|
-
|
|
3842
|
-
|
|
3843
|
-
|
|
3844
|
-
|
|
3845
|
-
|
|
3846
|
-
|
|
3847
|
-
|
|
3848
|
-
|
|
3849
|
-
|
|
3850
|
-
);
|
|
3851
|
-
}
|
|
3852
|
-
return void 0;
|
|
3853
|
-
}, pollOptions);
|
|
3854
|
-
const video = extractOmniVideo(done, modelId);
|
|
3855
|
-
if (video.data) {
|
|
3856
|
-
return {
|
|
3857
|
-
video: {
|
|
3858
|
-
bytes: Buffer.from(video.data, "base64"),
|
|
3859
|
-
mime: video.mime_type ?? "video/mp4"
|
|
3860
|
-
},
|
|
3861
|
-
usage: usage2,
|
|
3862
|
-
raw: done
|
|
3863
|
-
};
|
|
4128
|
+
const done = await pollUntil(async () => {
|
|
4129
|
+
const current = await getInteraction();
|
|
4130
|
+
const status = (current.status ?? "").toUpperCase();
|
|
4131
|
+
if (status === "COMPLETED") return current;
|
|
4132
|
+
if (status === "FAILED") {
|
|
4133
|
+
throw classifyHttpError(
|
|
4134
|
+
void 0,
|
|
4135
|
+
`Gemini Omni interaction failed: ${JSON.stringify(current).slice(0, 500)}`,
|
|
4136
|
+
"google-genai",
|
|
4137
|
+
modelId
|
|
4138
|
+
);
|
|
3864
4139
|
}
|
|
3865
|
-
|
|
3866
|
-
|
|
3867
|
-
|
|
3868
|
-
|
|
3869
|
-
|
|
3870
|
-
|
|
3871
|
-
|
|
3872
|
-
|
|
3873
|
-
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
|
|
3877
|
-
} finally {
|
|
3878
|
-
await cleanupUploads();
|
|
4140
|
+
return void 0;
|
|
4141
|
+
}, pollOptions);
|
|
4142
|
+
const video = extractOmniVideo(done, modelId);
|
|
4143
|
+
if (video.data) {
|
|
4144
|
+
return {
|
|
4145
|
+
video: {
|
|
4146
|
+
bytes: Buffer.from(video.data, "base64"),
|
|
4147
|
+
mime: video.mime_type ?? "video/mp4"
|
|
4148
|
+
},
|
|
4149
|
+
usage: usage2,
|
|
4150
|
+
raw: done
|
|
4151
|
+
};
|
|
3879
4152
|
}
|
|
4153
|
+
if (video.uri)
|
|
4154
|
+
return {
|
|
4155
|
+
video: await downloadVideo(ctx, video.uri, apiKey, signal),
|
|
4156
|
+
usage: usage2,
|
|
4157
|
+
raw: done
|
|
4158
|
+
};
|
|
4159
|
+
throw classifyHttpError(
|
|
4160
|
+
void 0,
|
|
4161
|
+
"No video content in Gemini Omni response",
|
|
4162
|
+
"google-genai",
|
|
4163
|
+
modelId
|
|
4164
|
+
);
|
|
3880
4165
|
}
|
|
3881
4166
|
};
|
|
3882
4167
|
}
|
|
@@ -4039,44 +4324,37 @@ function createGoogleImageAdapter(deps = defaultGoogleImageDeps) {
|
|
|
4039
4324
|
const model = google(ctx.model.providerModelId);
|
|
4040
4325
|
const content = [];
|
|
4041
4326
|
for (const ref of req.references ?? []) {
|
|
4327
|
+
if (ref.label !== void 0) content.push({ type: "text", text: ref.label });
|
|
4042
4328
|
if ("url" in ref) content.push({ type: "image", image: ref.url });
|
|
4043
4329
|
else content.push({ type: "image", image: ref.bytes, mediaType: ref.mime });
|
|
4044
4330
|
}
|
|
4045
4331
|
content.push({ type: "text", text: req.prompt });
|
|
4046
|
-
void ctx.call.postCropToAspect;
|
|
4047
4332
|
const imageConfig = {};
|
|
4048
|
-
if (req.aspectRatio !== void 0
|
|
4333
|
+
if (req.aspectRatio !== void 0 && req.aspectRatio !== "adaptive")
|
|
4334
|
+
imageConfig.aspectRatio = req.aspectRatio;
|
|
4049
4335
|
if (req.size !== void 0) imageConfig.imageSize = req.size;
|
|
4336
|
+
const googleOptions = {
|
|
4337
|
+
imageConfig,
|
|
4338
|
+
responseModalities: ["IMAGE"]
|
|
4339
|
+
};
|
|
4340
|
+
if (req.safetySettings !== void 0) googleOptions.safetySettings = req.safetySettings;
|
|
4050
4341
|
const retryOptions = {};
|
|
4051
4342
|
if (ctx.signal !== void 0) retryOptions.signal = ctx.signal;
|
|
4052
4343
|
const result = await withRetry(async () => {
|
|
4053
4344
|
const timeout = AbortSignal.timeout(GEMINI_IMAGE_TIMEOUT_MS);
|
|
4054
4345
|
const signal = ctx.signal !== void 0 ? AbortSignal.any([ctx.signal, timeout]) : timeout;
|
|
4055
4346
|
try {
|
|
4056
|
-
|
|
4347
|
+
const genOptions = {
|
|
4057
4348
|
model,
|
|
4058
4349
|
messages: [{ role: "user", content }],
|
|
4059
4350
|
maxRetries: 0,
|
|
4060
4351
|
providerOptions: {
|
|
4061
|
-
google:
|
|
4062
|
-
imageConfig,
|
|
4063
|
-
responseModalities: ["IMAGE"],
|
|
4064
|
-
safetySettings: [
|
|
4065
|
-
{
|
|
4066
|
-
category: "HARM_CATEGORY_SEXUALLY_EXPLICIT",
|
|
4067
|
-
threshold: "OFF"
|
|
4068
|
-
},
|
|
4069
|
-
{ category: "HARM_CATEGORY_HATE_SPEECH", threshold: "OFF" },
|
|
4070
|
-
{
|
|
4071
|
-
category: "HARM_CATEGORY_DANGEROUS_CONTENT",
|
|
4072
|
-
threshold: "OFF"
|
|
4073
|
-
},
|
|
4074
|
-
{ category: "HARM_CATEGORY_HARASSMENT", threshold: "OFF" }
|
|
4075
|
-
]
|
|
4076
|
-
}
|
|
4352
|
+
google: googleOptions
|
|
4077
4353
|
},
|
|
4078
4354
|
abortSignal: signal
|
|
4079
|
-
}
|
|
4355
|
+
};
|
|
4356
|
+
if (req.temperature !== void 0) genOptions.temperature = req.temperature;
|
|
4357
|
+
return await deps.runTextGeneration(genOptions);
|
|
4080
4358
|
} catch (cause) {
|
|
4081
4359
|
throw toProviderError(cause, ctx);
|
|
4082
4360
|
}
|
|
@@ -4260,6 +4538,7 @@ var KLING_MAX_INTERVAL_MS = 1e4;
|
|
|
4260
4538
|
var KLING_TIMEOUT_MS = 15 * 6e4;
|
|
4261
4539
|
var DOP_INTERVAL_MS = 5e3;
|
|
4262
4540
|
var DOP_TIMEOUT_MS = 5 * 6e4;
|
|
4541
|
+
var DOP_FALLBACK_DURATION_SECONDS = 5;
|
|
4263
4542
|
var DEFAULT_NEGATIVE_PROMPT = "text, watermark, copyright, blur, low quality, distortion, abstract, weird, deformed";
|
|
4264
4543
|
function credentials(ctx) {
|
|
4265
4544
|
const key = ctx.keys.higgsfield;
|
|
@@ -4279,26 +4558,14 @@ function headers(ctx) {
|
|
|
4279
4558
|
const { key, secret } = credentials(ctx);
|
|
4280
4559
|
return { "Content-Type": "application/json", "hf-api-key": key, "hf-secret": secret };
|
|
4281
4560
|
}
|
|
4282
|
-
function refToUrl2(ref) {
|
|
4283
|
-
if ("url" in ref) return ref.url;
|
|
4284
|
-
return `data:${ref.mime};base64,${Buffer.from(ref.bytes).toString("base64")}`;
|
|
4285
|
-
}
|
|
4286
|
-
async function readBody2(res) {
|
|
4287
|
-
const text2 = await res.text().catch(() => "");
|
|
4288
|
-
try {
|
|
4289
|
-
const decoded = JsonValueSchema.safeParse(JSON.parse(text2));
|
|
4290
|
-
return decoded.success ? decoded.data : text2;
|
|
4291
|
-
} catch {
|
|
4292
|
-
return text2;
|
|
4293
|
-
}
|
|
4294
|
-
}
|
|
4295
4561
|
function klingEndpoint(providerModelId) {
|
|
4296
4562
|
if (providerModelId.startsWith("http")) return providerModelId;
|
|
4297
4563
|
const path = providerModelId.startsWith("/") ? providerModelId.slice(1) : providerModelId;
|
|
4298
4564
|
return `${PLATFORM}/${path}`;
|
|
4299
4565
|
}
|
|
4300
|
-
|
|
4301
|
-
|
|
4566
|
+
var DOP_MODEL_IDS = /* @__PURE__ */ new Set(["dop", "dop-preview"]);
|
|
4567
|
+
function higgsfieldVideoKind(providerModelId) {
|
|
4568
|
+
return DOP_MODEL_IDS.has(providerModelId.toLowerCase()) ? "dop" : "kling";
|
|
4302
4569
|
}
|
|
4303
4570
|
function videoUsage3(ctx, req, duration) {
|
|
4304
4571
|
const event = {
|
|
@@ -4334,8 +4601,20 @@ function requestInit(ctx, init) {
|
|
|
4334
4601
|
if (ctx.signal !== void 0) request.signal = ctx.signal;
|
|
4335
4602
|
return request;
|
|
4336
4603
|
}
|
|
4604
|
+
async function createRequest(ctx, url, init) {
|
|
4605
|
+
let res;
|
|
4606
|
+
try {
|
|
4607
|
+
res = await ctx.fetch(url, requestInit(ctx, init));
|
|
4608
|
+
} catch (cause) {
|
|
4609
|
+
throw classifyThrown("higgsfield", cause, ctx.model.id);
|
|
4610
|
+
}
|
|
4611
|
+
if (!res.ok) {
|
|
4612
|
+
throw classifyHttpError(res.status, await readBody(res), "higgsfield", ctx.model.id);
|
|
4613
|
+
}
|
|
4614
|
+
return res;
|
|
4615
|
+
}
|
|
4337
4616
|
async function generateKlingVideo(req, ctx) {
|
|
4338
|
-
const firstFrame = req.firstFrame ?
|
|
4617
|
+
const firstFrame = req.firstFrame ? refToUrl(req.firstFrame) : void 0;
|
|
4339
4618
|
if (!firstFrame) {
|
|
4340
4619
|
throw new ModelKitError({
|
|
4341
4620
|
code: "missing_input",
|
|
@@ -4352,26 +4631,16 @@ async function generateKlingVideo(req, ctx) {
|
|
|
4352
4631
|
negative_prompt: req.negativePrompt ?? DEFAULT_NEGATIVE_PROMPT
|
|
4353
4632
|
};
|
|
4354
4633
|
if (req.durationSeconds !== void 0) body.duration = req.durationSeconds;
|
|
4355
|
-
if (req.aspectRatio !== void 0
|
|
4356
|
-
|
|
4634
|
+
if (req.aspectRatio !== void 0 && req.aspectRatio !== "adaptive")
|
|
4635
|
+
body.aspect_ratio = req.aspectRatio;
|
|
4636
|
+
if (req.lastFrame) body.last_image_url = refToUrl(req.lastFrame);
|
|
4357
4637
|
const endpoint = klingEndpoint(ctx.model.providerModelId);
|
|
4358
|
-
|
|
4359
|
-
|
|
4360
|
-
|
|
4361
|
-
|
|
4362
|
-
|
|
4363
|
-
|
|
4364
|
-
} catch (cause) {
|
|
4365
|
-
throw networkError(cause, ctx);
|
|
4366
|
-
}
|
|
4367
|
-
if (!createRes.ok) {
|
|
4368
|
-
throw classifyHttpError(
|
|
4369
|
-
createRes.status,
|
|
4370
|
-
await readBody2(createRes),
|
|
4371
|
-
"higgsfield",
|
|
4372
|
-
ctx.model.id
|
|
4373
|
-
);
|
|
4374
|
-
}
|
|
4638
|
+
const retryOptions = {};
|
|
4639
|
+
if (ctx.signal !== void 0) retryOptions.signal = ctx.signal;
|
|
4640
|
+
const createRes = await withRetry(
|
|
4641
|
+
() => createRequest(ctx, endpoint, { method: "POST", body: JSON.stringify(body) }),
|
|
4642
|
+
retryOptions
|
|
4643
|
+
);
|
|
4375
4644
|
const created = klingCreateSchema.safeParse(await createRes.json());
|
|
4376
4645
|
if (!created.success) {
|
|
4377
4646
|
throw new ModelKitError({
|
|
@@ -4390,9 +4659,9 @@ async function generateKlingVideo(req, ctx) {
|
|
|
4390
4659
|
} catch {
|
|
4391
4660
|
return void 0;
|
|
4392
4661
|
}
|
|
4393
|
-
if (res.status >= 500) return void 0;
|
|
4662
|
+
if (res.status === 429 || res.status >= 500) return void 0;
|
|
4394
4663
|
if (!res.ok) {
|
|
4395
|
-
throw classifyHttpError(res.status, await
|
|
4664
|
+
throw classifyHttpError(res.status, await readBody(res), "higgsfield", ctx.model.id);
|
|
4396
4665
|
}
|
|
4397
4666
|
const payload = JsonValueSchema.parse(await res.json());
|
|
4398
4667
|
const parsed = klingStatusSchema.safeParse(payload);
|
|
@@ -4451,11 +4720,6 @@ async function generateKlingVideo(req, ctx) {
|
|
|
4451
4720
|
}
|
|
4452
4721
|
};
|
|
4453
4722
|
}
|
|
4454
|
-
function networkError(cause, ctx) {
|
|
4455
|
-
if (isModelKitError(cause)) return cause;
|
|
4456
|
-
const info = describeThrown(cause);
|
|
4457
|
-
return classifyHttpError(info.status, info.body, "higgsfield", ctx.model.id);
|
|
4458
|
-
}
|
|
4459
4723
|
var dopMotionOptionsSchema = import_zod10.z.object({
|
|
4460
4724
|
modelkit: import_zod10.z.object({ motion: import_zod10.z.string().optional() }).optional()
|
|
4461
4725
|
});
|
|
@@ -4504,7 +4768,7 @@ function dopUrl(body) {
|
|
|
4504
4768
|
var dopCreateSchema = import_zod10.z.object({ id: import_zod10.z.string() });
|
|
4505
4769
|
var dopStatusSchema = import_zod10.z.object({ status: import_zod10.z.string().optional() });
|
|
4506
4770
|
async function generateDopVideo(req, ctx) {
|
|
4507
|
-
const firstFrame = req.firstFrame ?
|
|
4771
|
+
const firstFrame = req.firstFrame ? refToUrl(req.firstFrame) : void 0;
|
|
4508
4772
|
if (!firstFrame) {
|
|
4509
4773
|
throw new ModelKitError({
|
|
4510
4774
|
code: "missing_input",
|
|
@@ -4524,29 +4788,18 @@ async function generateDopVideo(req, ctx) {
|
|
|
4524
4788
|
webhook: null
|
|
4525
4789
|
};
|
|
4526
4790
|
if (req.lastFrame) {
|
|
4527
|
-
params.input_images_end = [{ type: "image_url", image_url:
|
|
4791
|
+
params.input_images_end = [{ type: "image_url", image_url: refToUrl(req.lastFrame) }];
|
|
4528
4792
|
}
|
|
4529
4793
|
if (req.seed !== void 0) params.seed = req.seed;
|
|
4530
|
-
|
|
4531
|
-
|
|
4532
|
-
|
|
4533
|
-
|
|
4534
|
-
|
|
4535
|
-
|
|
4536
|
-
|
|
4537
|
-
|
|
4538
|
-
|
|
4539
|
-
} catch (cause) {
|
|
4540
|
-
throw networkError(cause, ctx);
|
|
4541
|
-
}
|
|
4542
|
-
if (!createRes.ok) {
|
|
4543
|
-
throw classifyHttpError(
|
|
4544
|
-
createRes.status,
|
|
4545
|
-
await readBody2(createRes),
|
|
4546
|
-
"higgsfield",
|
|
4547
|
-
ctx.model.id
|
|
4548
|
-
);
|
|
4549
|
-
}
|
|
4794
|
+
const retryOptions = {};
|
|
4795
|
+
if (ctx.signal !== void 0) retryOptions.signal = ctx.signal;
|
|
4796
|
+
const createRes = await withRetry(
|
|
4797
|
+
() => createRequest(ctx, DOP_ENDPOINT, {
|
|
4798
|
+
method: "POST",
|
|
4799
|
+
body: JSON.stringify({ params, webhook: null })
|
|
4800
|
+
}),
|
|
4801
|
+
retryOptions
|
|
4802
|
+
);
|
|
4550
4803
|
const created = dopCreateSchema.safeParse(await createRes.json());
|
|
4551
4804
|
if (!created.success) {
|
|
4552
4805
|
throw new ModelKitError({
|
|
@@ -4615,14 +4868,20 @@ async function generateDopVideo(req, ctx) {
|
|
|
4615
4868
|
};
|
|
4616
4869
|
if (dopSignal !== void 0) pollSettings.signal = dopSignal;
|
|
4617
4870
|
const url = await pollUntil(check, pollSettings);
|
|
4618
|
-
const result = {
|
|
4871
|
+
const result = {
|
|
4872
|
+
video: { url },
|
|
4873
|
+
usage: videoUsage3(ctx, req, req.durationSeconds ?? DOP_FALLBACK_DURATION_SECONDS)
|
|
4874
|
+
};
|
|
4619
4875
|
return result;
|
|
4620
4876
|
}
|
|
4621
4877
|
};
|
|
4622
4878
|
}
|
|
4623
4879
|
var higgsfieldAdapter = {
|
|
4624
4880
|
id: "higgsfield",
|
|
4625
|
-
generateVideo: (req, ctx) =>
|
|
4881
|
+
generateVideo: (req, ctx) => {
|
|
4882
|
+
throwIfAborted(ctx.signal);
|
|
4883
|
+
return higgsfieldVideoKind(ctx.model.providerModelId) === "dop" ? generateDopVideo(req, ctx) : generateKlingVideo(req, ctx);
|
|
4884
|
+
}
|
|
4626
4885
|
};
|
|
4627
4886
|
|
|
4628
4887
|
// src/adapters/openai-image.ts
|
|
@@ -4717,6 +4976,7 @@ var openaiUsageSchema = import_zod11.z.object({
|
|
|
4717
4976
|
var openaiImageAdapter = {
|
|
4718
4977
|
id: "openai-image",
|
|
4719
4978
|
async generateImage(req, ctx) {
|
|
4979
|
+
throwIfAborted(ctx.signal);
|
|
4720
4980
|
const apiKey = ctx.keys.openai;
|
|
4721
4981
|
if (!apiKey)
|
|
4722
4982
|
throw new ModelKitError({
|
|
@@ -4726,6 +4986,13 @@ var openaiImageAdapter = {
|
|
|
4726
4986
|
model: ctx.model.id,
|
|
4727
4987
|
retryable: false
|
|
4728
4988
|
});
|
|
4989
|
+
if ((req.references ?? []).some((ref) => ref.label !== void 0)) {
|
|
4990
|
+
ctx.warnings.push({
|
|
4991
|
+
code: "option_ignored",
|
|
4992
|
+
field: "references.label",
|
|
4993
|
+
message: "openai-image cannot express reference labels; ignoring them"
|
|
4994
|
+
});
|
|
4995
|
+
}
|
|
4729
4996
|
const client2 = new import_openai2.default({ apiKey, fetch: ctx.fetch, maxRetries: 0 });
|
|
4730
4997
|
const size = req.exactSize !== void 0 ? req.exactSize : req.aspectRatio === void 0 || req.aspectRatio === "adaptive" ? void 0 : aspectRatioToSize(req.aspectRatio, req.size ?? "1K");
|
|
4731
4998
|
const refs = req.references ?? [];
|
|
@@ -4739,24 +5006,34 @@ var openaiImageAdapter = {
|
|
|
4739
5006
|
try {
|
|
4740
5007
|
if (!isEdit) {
|
|
4741
5008
|
if (size !== void 0) {
|
|
4742
|
-
return await client2.images.generate(
|
|
5009
|
+
return await client2.images.generate(
|
|
5010
|
+
{
|
|
5011
|
+
model: ctx.model.providerModelId,
|
|
5012
|
+
prompt: req.prompt,
|
|
5013
|
+
size,
|
|
5014
|
+
quality: sdkQuality,
|
|
5015
|
+
...count
|
|
5016
|
+
},
|
|
5017
|
+
{ signal: ctx.signal }
|
|
5018
|
+
);
|
|
5019
|
+
}
|
|
5020
|
+
return await client2.images.generate(
|
|
5021
|
+
{
|
|
4743
5022
|
model: ctx.model.providerModelId,
|
|
4744
5023
|
prompt: req.prompt,
|
|
4745
|
-
size,
|
|
4746
5024
|
quality: sdkQuality,
|
|
4747
5025
|
...count
|
|
4748
|
-
}
|
|
4749
|
-
|
|
4750
|
-
|
|
4751
|
-
model: ctx.model.providerModelId,
|
|
4752
|
-
prompt: req.prompt,
|
|
4753
|
-
quality: sdkQuality,
|
|
4754
|
-
...count
|
|
4755
|
-
});
|
|
5026
|
+
},
|
|
5027
|
+
{ signal: ctx.signal }
|
|
5028
|
+
);
|
|
4756
5029
|
}
|
|
4757
5030
|
const files = await Promise.all(
|
|
4758
5031
|
refs.slice(0, MAX_EDIT_REFERENCES).map(async (ref, i) => {
|
|
4759
|
-
const { bytes, mime } = await mediaRefToBytes(ref, ctx.fetch
|
|
5032
|
+
const { bytes, mime } = await mediaRefToBytes(ref, ctx.fetch, {
|
|
5033
|
+
signal: ctx.signal,
|
|
5034
|
+
provider: "openai-image",
|
|
5035
|
+
model: ctx.model.id
|
|
5036
|
+
});
|
|
4760
5037
|
const ext = mime.includes("jpeg") ? "jpg" : mime.includes("webp") ? "webp" : "png";
|
|
4761
5038
|
return new File([bytes], `ref-${i}.${ext}`, { type: mime });
|
|
4762
5039
|
})
|
|
@@ -4764,22 +5041,28 @@ var openaiImageAdapter = {
|
|
|
4764
5041
|
const single = files.length === 1 ? files[0] : void 0;
|
|
4765
5042
|
const imageInput = single ?? files;
|
|
4766
5043
|
if (size !== void 0) {
|
|
4767
|
-
return await client2.images.edit(
|
|
5044
|
+
return await client2.images.edit(
|
|
5045
|
+
{
|
|
5046
|
+
model: ctx.model.providerModelId,
|
|
5047
|
+
image: imageInput,
|
|
5048
|
+
prompt: req.prompt,
|
|
5049
|
+
size,
|
|
5050
|
+
quality: sdkQuality,
|
|
5051
|
+
...count
|
|
5052
|
+
},
|
|
5053
|
+
{ signal: ctx.signal }
|
|
5054
|
+
);
|
|
5055
|
+
}
|
|
5056
|
+
return await client2.images.edit(
|
|
5057
|
+
{
|
|
4768
5058
|
model: ctx.model.providerModelId,
|
|
4769
5059
|
image: imageInput,
|
|
4770
5060
|
prompt: req.prompt,
|
|
4771
|
-
size,
|
|
4772
5061
|
quality: sdkQuality,
|
|
4773
5062
|
...count
|
|
4774
|
-
}
|
|
4775
|
-
|
|
4776
|
-
|
|
4777
|
-
model: ctx.model.providerModelId,
|
|
4778
|
-
image: imageInput,
|
|
4779
|
-
prompt: req.prompt,
|
|
4780
|
-
quality: sdkQuality,
|
|
4781
|
-
...count
|
|
4782
|
-
});
|
|
5063
|
+
},
|
|
5064
|
+
{ signal: ctx.signal }
|
|
5065
|
+
);
|
|
4783
5066
|
} catch (cause) {
|
|
4784
5067
|
throw toProviderError2(cause, ctx);
|
|
4785
5068
|
}
|
|
@@ -4797,28 +5080,16 @@ var openaiImageAdapter = {
|
|
|
4797
5080
|
const usageParsed = openaiUsageSchema.safeParse(response.usage);
|
|
4798
5081
|
const inputTokens = usageParsed.success ? usageParsed.data.input_tokens : void 0;
|
|
4799
5082
|
const outputTokens = usageParsed.success ? usageParsed.data.output_tokens : void 0;
|
|
4800
|
-
|
|
4801
|
-
|
|
4802
|
-
|
|
4803
|
-
|
|
4804
|
-
|
|
4805
|
-
|
|
4806
|
-
|
|
4807
|
-
|
|
4808
|
-
|
|
4809
|
-
|
|
4810
|
-
if (inputTokens !== void 0) usage2.inputTokens = inputTokens;
|
|
4811
|
-
if (outputTokens !== void 0) usage2.outputTokens = outputTokens;
|
|
4812
|
-
} else {
|
|
4813
|
-
usage2 = {
|
|
4814
|
-
model: ctx.model.id,
|
|
4815
|
-
provider: "openai-image",
|
|
4816
|
-
modality: "IMAGE",
|
|
4817
|
-
unit: "images",
|
|
4818
|
-
quantity: images.length,
|
|
4819
|
-
imageQuality: quality
|
|
4820
|
-
};
|
|
4821
|
-
}
|
|
5083
|
+
const usage2 = {
|
|
5084
|
+
model: ctx.model.id,
|
|
5085
|
+
provider: "openai-image",
|
|
5086
|
+
modality: "IMAGE",
|
|
5087
|
+
unit: "images",
|
|
5088
|
+
quantity: images.length,
|
|
5089
|
+
imageQuality: quality
|
|
5090
|
+
};
|
|
5091
|
+
if (inputTokens !== void 0) usage2.inputTokens = inputTokens;
|
|
5092
|
+
if (outputTokens !== void 0) usage2.outputTokens = outputTokens;
|
|
4822
5093
|
if (req.size !== void 0) usage2.imageSize = req.size;
|
|
4823
5094
|
return { images, usage: usage2, raw: response };
|
|
4824
5095
|
}
|
|
@@ -4871,7 +5142,12 @@ var NANO_BANANA_RATIOS = /* @__PURE__ */ new Set([
|
|
|
4871
5142
|
]);
|
|
4872
5143
|
async function refToBytes(ctx, ref) {
|
|
4873
5144
|
if ("bytes" in ref) return { bytes: ref.bytes, mime: ref.mime };
|
|
4874
|
-
|
|
5145
|
+
let res;
|
|
5146
|
+
try {
|
|
5147
|
+
res = await ctx.fetch(ref.url, ctx.signal ? { signal: ctx.signal } : {});
|
|
5148
|
+
} catch (cause) {
|
|
5149
|
+
throw classifyThrown("prodia", cause, ctx.model.id);
|
|
5150
|
+
}
|
|
4875
5151
|
if (!res.ok) {
|
|
4876
5152
|
const text2 = await res.text().catch(() => "");
|
|
4877
5153
|
throw classifyHttpError(res.status, text2, "prodia", ctx.model.id);
|
|
@@ -4914,6 +5190,12 @@ function emptyImage() {
|
|
|
4914
5190
|
retryable: false
|
|
4915
5191
|
});
|
|
4916
5192
|
}
|
|
5193
|
+
function inputExtension(mime) {
|
|
5194
|
+
if (mime.includes("jpeg") || mime.includes("jpg")) return "jpg";
|
|
5195
|
+
if (mime.includes("webp")) return "webp";
|
|
5196
|
+
if (mime.includes("gif")) return "gif";
|
|
5197
|
+
return "png";
|
|
5198
|
+
}
|
|
4917
5199
|
function isBgRemove(providerModelId) {
|
|
4918
5200
|
const id = providerModelId.toLowerCase();
|
|
4919
5201
|
return id.includes("remove-background") || id.includes("bg-remove");
|
|
@@ -4922,6 +5204,7 @@ function isKlein(providerModelId) {
|
|
|
4922
5204
|
return providerModelId.toLowerCase().includes("klein");
|
|
4923
5205
|
}
|
|
4924
5206
|
async function generateProdiaImage(req, ctx) {
|
|
5207
|
+
throwIfAborted(ctx.signal);
|
|
4925
5208
|
const key = ctx.keys.prodia;
|
|
4926
5209
|
if (!key) {
|
|
4927
5210
|
throw new ModelKitError({
|
|
@@ -5020,7 +5303,9 @@ async function generateProdiaImage(req, ctx) {
|
|
|
5020
5303
|
"input",
|
|
5021
5304
|
// Uint8Array<ArrayBufferLike> is not a valid BlobPart under the
|
|
5022
5305
|
// strict lib types; copy into a fresh ArrayBuffer-backed view.
|
|
5023
|
-
new File([new Uint8Array(input.bytes)], `input-${i}.
|
|
5306
|
+
new File([new Uint8Array(input.bytes)], `input-${i}.${inputExtension(input.mime)}`, {
|
|
5307
|
+
type: input.mime
|
|
5308
|
+
})
|
|
5024
5309
|
);
|
|
5025
5310
|
});
|
|
5026
5311
|
const retryOpts = {
|
|
@@ -5035,14 +5320,15 @@ async function generateProdiaImage(req, ctx) {
|
|
|
5035
5320
|
res = await withRetry(async () => {
|
|
5036
5321
|
let attemptRes;
|
|
5037
5322
|
try {
|
|
5038
|
-
|
|
5323
|
+
const init = {
|
|
5039
5324
|
method: "POST",
|
|
5040
5325
|
headers: { Authorization: `Bearer ${key}`, Accept: accept },
|
|
5041
5326
|
body: form
|
|
5042
|
-
}
|
|
5327
|
+
};
|
|
5328
|
+
if (ctx.signal !== void 0) init.signal = ctx.signal;
|
|
5329
|
+
attemptRes = await ctx.fetch(PRODIA_JOB_URL, init);
|
|
5043
5330
|
} catch (err) {
|
|
5044
|
-
|
|
5045
|
-
throw transportError("prodia", err, ctx.model.id);
|
|
5331
|
+
throw classifyThrown("prodia", err, ctx.model.id);
|
|
5046
5332
|
}
|
|
5047
5333
|
if (!attemptRes.ok) {
|
|
5048
5334
|
const text2 = await attemptRes.text().catch(() => "");
|
|
@@ -5051,8 +5337,7 @@ async function generateProdiaImage(req, ctx) {
|
|
|
5051
5337
|
return attemptRes;
|
|
5052
5338
|
}, retryOpts);
|
|
5053
5339
|
} catch (err) {
|
|
5054
|
-
|
|
5055
|
-
throw transportError("prodia", err, ctx.model.id);
|
|
5340
|
+
throw classifyThrown("prodia", err, ctx.model.id);
|
|
5056
5341
|
}
|
|
5057
5342
|
const bytes = parseImageResponse(
|
|
5058
5343
|
new Uint8Array(await res.arrayBuffer()),
|
|
@@ -5102,11 +5387,7 @@ function client(ctx, deps) {
|
|
|
5102
5387
|
retryable: false
|
|
5103
5388
|
});
|
|
5104
5389
|
}
|
|
5105
|
-
return deps.createReplicateClient({ auth: token });
|
|
5106
|
-
}
|
|
5107
|
-
function refToUrl3(ref) {
|
|
5108
|
-
if ("url" in ref) return ref.url;
|
|
5109
|
-
return `data:${ref.mime};base64,${Buffer.from(ref.bytes).toString("base64")}`;
|
|
5390
|
+
return deps.createReplicateClient({ auth: token, fetch: ctx.fetch });
|
|
5110
5391
|
}
|
|
5111
5392
|
function route(providerModelId) {
|
|
5112
5393
|
if (providerModelId.includes(":")) {
|
|
@@ -5124,10 +5405,11 @@ function replicateError(cause, ctx) {
|
|
|
5124
5405
|
const info = describeThrown(cause);
|
|
5125
5406
|
const nested = replicateResponseStatusSchema.safeParse(cause);
|
|
5126
5407
|
const status = info.status ?? (nested.success ? nested.data.response?.status : void 0);
|
|
5127
|
-
return
|
|
5408
|
+
return classifyThrown("replicate", cause, ctx.model.id, { status, body: info.body });
|
|
5128
5409
|
}
|
|
5129
|
-
function
|
|
5130
|
-
|
|
5410
|
+
function baseModelId(providerModelId) {
|
|
5411
|
+
const colon = providerModelId.indexOf(":");
|
|
5412
|
+
return colon === -1 ? providerModelId : providerModelId.slice(0, colon);
|
|
5131
5413
|
}
|
|
5132
5414
|
function predictionErrorBody(cause) {
|
|
5133
5415
|
const parsed = JsonValueSchema.safeParse(cause);
|
|
@@ -5175,6 +5457,7 @@ function noOutput() {
|
|
|
5175
5457
|
});
|
|
5176
5458
|
}
|
|
5177
5459
|
async function runPrediction(ctx, input, deps) {
|
|
5460
|
+
throwIfAborted(ctx.signal);
|
|
5178
5461
|
const api = client(ctx, deps);
|
|
5179
5462
|
const createOptions = { ...route(ctx.model.providerModelId), input };
|
|
5180
5463
|
let prediction;
|
|
@@ -5182,12 +5465,14 @@ async function runPrediction(ctx, input, deps) {
|
|
|
5182
5465
|
prediction = await withRetry(
|
|
5183
5466
|
async () => {
|
|
5184
5467
|
try {
|
|
5185
|
-
return await api.predictions.create(
|
|
5468
|
+
return await api.predictions.create(
|
|
5469
|
+
ctx.signal ? { ...createOptions, signal: ctx.signal } : createOptions
|
|
5470
|
+
);
|
|
5186
5471
|
} catch (cause) {
|
|
5187
5472
|
throw replicateError(cause, ctx);
|
|
5188
5473
|
}
|
|
5189
5474
|
},
|
|
5190
|
-
|
|
5475
|
+
{ attempts: 1 }
|
|
5191
5476
|
);
|
|
5192
5477
|
} catch (cause) {
|
|
5193
5478
|
throw replicateError(cause, ctx);
|
|
@@ -5200,7 +5485,10 @@ async function runPrediction(ctx, input, deps) {
|
|
|
5200
5485
|
const done = await pollUntil(async () => {
|
|
5201
5486
|
let current;
|
|
5202
5487
|
try {
|
|
5203
|
-
current = await api.predictions.get(
|
|
5488
|
+
current = await api.predictions.get(
|
|
5489
|
+
prediction.id,
|
|
5490
|
+
ctx.signal ? { signal: ctx.signal } : void 0
|
|
5491
|
+
);
|
|
5204
5492
|
} catch (cause) {
|
|
5205
5493
|
throw replicateError(cause, ctx);
|
|
5206
5494
|
}
|
|
@@ -5267,21 +5555,32 @@ async function download(ctx, url) {
|
|
|
5267
5555
|
const mime = res.headers.get("content-type") ?? "image/png";
|
|
5268
5556
|
return { bytes: new Uint8Array(await res.arrayBuffer()), mime };
|
|
5269
5557
|
}
|
|
5270
|
-
|
|
5271
|
-
|
|
5272
|
-
|
|
5273
|
-
|
|
5274
|
-
|
|
5275
|
-
|
|
5276
|
-
}
|
|
5277
|
-
function
|
|
5278
|
-
return
|
|
5279
|
-
}
|
|
5280
|
-
|
|
5281
|
-
|
|
5558
|
+
var REPLICATE_IMAGE_KINDS = {
|
|
5559
|
+
"topazlabs/image-upscale": "topaz",
|
|
5560
|
+
"philz1337x/crystal-upscaler": "upscaler",
|
|
5561
|
+
"wan-video/wan-2.7-image-pro": "wan",
|
|
5562
|
+
"qwen/qwen-image-2-pro": "qwen-image",
|
|
5563
|
+
"qwen-edit-apps/qwen-image-edit-plus-lora-skin": "qwen-edit"
|
|
5564
|
+
};
|
|
5565
|
+
function imageKind(providerModelId) {
|
|
5566
|
+
return REPLICATE_IMAGE_KINDS[baseModelId(providerModelId)] ?? "generic";
|
|
5567
|
+
}
|
|
5568
|
+
var REPLICATE_VIDEO_KINDS = {
|
|
5569
|
+
"kling-video/v2.5-turbo/pro/image-to-video": "kling",
|
|
5570
|
+
"kling-video/v3.0/pro/image-to-video": "kling",
|
|
5571
|
+
"kwaivgi/kling-v3-video": "kling",
|
|
5572
|
+
"kwaivgi/kling-v3-omni-video": "kling-omni",
|
|
5573
|
+
"minimax/hailuo-02": "hailuo"
|
|
5574
|
+
};
|
|
5575
|
+
function videoKind(providerModelId) {
|
|
5576
|
+
return REPLICATE_VIDEO_KINDS[baseModelId(providerModelId)] ?? "wan";
|
|
5282
5577
|
}
|
|
5283
|
-
|
|
5284
|
-
|
|
5578
|
+
var REPLICATE_AUDIO_KINDS = {
|
|
5579
|
+
"zsxkib/mmaudio": "mmaudio",
|
|
5580
|
+
"elevenlabs/music": "elevenlabs"
|
|
5581
|
+
};
|
|
5582
|
+
function audioKind(providerModelId) {
|
|
5583
|
+
return REPLICATE_AUDIO_KINDS[baseModelId(providerModelId)] ?? "lyria";
|
|
5285
5584
|
}
|
|
5286
5585
|
var QWEN_IMAGE_RATIOS = /* @__PURE__ */ new Set([
|
|
5287
5586
|
"1:1",
|
|
@@ -5324,87 +5623,113 @@ function wanImageSize(aspectRatio, size) {
|
|
|
5324
5623
|
async function generateReplicateImage(req, ctx, deps) {
|
|
5325
5624
|
const id = ctx.model.providerModelId;
|
|
5326
5625
|
let input;
|
|
5327
|
-
|
|
5328
|
-
|
|
5329
|
-
|
|
5330
|
-
|
|
5331
|
-
|
|
5332
|
-
|
|
5333
|
-
|
|
5334
|
-
|
|
5335
|
-
|
|
5336
|
-
|
|
5626
|
+
switch (imageKind(id)) {
|
|
5627
|
+
case "topaz": {
|
|
5628
|
+
const first = (req.references ?? [])[0];
|
|
5629
|
+
if (!first) {
|
|
5630
|
+
throw new ModelKitError({
|
|
5631
|
+
code: "missing_input",
|
|
5632
|
+
message: `${ctx.model.id} requires a reference image to upscale`,
|
|
5633
|
+
provider: "replicate",
|
|
5634
|
+
model: ctx.model.id,
|
|
5635
|
+
retryable: false
|
|
5636
|
+
});
|
|
5637
|
+
}
|
|
5638
|
+
let format = req.outputFormat === "jpeg" ? "jpg" : req.outputFormat ?? "png";
|
|
5639
|
+
if (format !== "png" && format !== "jpg") {
|
|
5640
|
+
ctx.warnings.push({
|
|
5641
|
+
code: "option_ignored",
|
|
5642
|
+
field: "outputFormat",
|
|
5643
|
+
from: format,
|
|
5644
|
+
message: "topazlabs/image-upscale supports only png and jpg; using png"
|
|
5645
|
+
});
|
|
5646
|
+
format = "png";
|
|
5647
|
+
}
|
|
5648
|
+
const upscale = req.upscale;
|
|
5649
|
+
const topaz = {
|
|
5650
|
+
image: refToUrl(first),
|
|
5651
|
+
enhance_model: upscale?.enhanceModel ?? "Standard V2",
|
|
5652
|
+
output_format: format,
|
|
5653
|
+
upscale_factor: `${req.scaleFactor ?? 2}x`,
|
|
5654
|
+
face_enhancement: upscale?.faceEnhancement ?? false
|
|
5655
|
+
};
|
|
5656
|
+
if (upscale?.subjectDetection !== void 0)
|
|
5657
|
+
topaz.subject_detection = upscale.subjectDetection;
|
|
5658
|
+
if (upscale?.faceEnhancementCreativity !== void 0)
|
|
5659
|
+
topaz.face_enhancement_creativity = upscale.faceEnhancementCreativity;
|
|
5660
|
+
if (upscale?.faceEnhancementStrength !== void 0)
|
|
5661
|
+
topaz.face_enhancement_strength = upscale.faceEnhancementStrength;
|
|
5662
|
+
input = topaz;
|
|
5663
|
+
break;
|
|
5337
5664
|
}
|
|
5338
|
-
|
|
5339
|
-
|
|
5340
|
-
|
|
5341
|
-
|
|
5342
|
-
|
|
5343
|
-
|
|
5344
|
-
|
|
5345
|
-
|
|
5346
|
-
|
|
5665
|
+
case "upscaler": {
|
|
5666
|
+
const first = (req.references ?? [])[0];
|
|
5667
|
+
if (!first) {
|
|
5668
|
+
throw new ModelKitError({
|
|
5669
|
+
code: "missing_input",
|
|
5670
|
+
message: `${ctx.model.id} requires a reference image to upscale`,
|
|
5671
|
+
provider: "replicate",
|
|
5672
|
+
model: ctx.model.id,
|
|
5673
|
+
retryable: false
|
|
5674
|
+
});
|
|
5675
|
+
}
|
|
5676
|
+
const imageInput = { prompt: req.prompt };
|
|
5677
|
+
imageInput.image = refToUrl(first);
|
|
5678
|
+
imageInput.creativity = 0;
|
|
5679
|
+
imageInput.scale_factor = 2;
|
|
5680
|
+
imageInput.output_format = "png";
|
|
5681
|
+
input = imageInput;
|
|
5682
|
+
break;
|
|
5347
5683
|
}
|
|
5348
|
-
|
|
5349
|
-
|
|
5350
|
-
|
|
5351
|
-
|
|
5352
|
-
|
|
5353
|
-
|
|
5354
|
-
|
|
5355
|
-
} else if (isUpscaler(id)) {
|
|
5356
|
-
const refs = req.references ?? [];
|
|
5357
|
-
const first = refs[0];
|
|
5358
|
-
if (!first) {
|
|
5359
|
-
throw new ModelKitError({
|
|
5360
|
-
code: "missing_input",
|
|
5361
|
-
message: `${ctx.model.id} requires a reference image to upscale`,
|
|
5362
|
-
provider: "replicate",
|
|
5363
|
-
model: ctx.model.id,
|
|
5364
|
-
retryable: false
|
|
5365
|
-
});
|
|
5684
|
+
case "wan": {
|
|
5685
|
+
const refs = (req.references ?? []).map(refToUrl);
|
|
5686
|
+
const imageInput = { prompt: req.prompt };
|
|
5687
|
+
if (refs.length > 0) imageInput.images = refs;
|
|
5688
|
+
imageInput.size = wanImageSize(req.aspectRatio, req.size);
|
|
5689
|
+
input = imageInput;
|
|
5690
|
+
break;
|
|
5366
5691
|
}
|
|
5367
|
-
|
|
5368
|
-
|
|
5369
|
-
|
|
5370
|
-
|
|
5371
|
-
|
|
5372
|
-
|
|
5373
|
-
|
|
5374
|
-
|
|
5375
|
-
|
|
5376
|
-
|
|
5377
|
-
|
|
5378
|
-
|
|
5379
|
-
} else if (isQwen(id)) {
|
|
5380
|
-
const refs = (req.references ?? []).map(refToUrl3);
|
|
5381
|
-
const firstUrl = refs[0];
|
|
5382
|
-
const imageInput = { prompt: req.prompt };
|
|
5383
|
-
if (firstUrl !== void 0) {
|
|
5384
|
-
imageInput.image = firstUrl;
|
|
5385
|
-
if (!isQwenEditPlus(id)) imageInput.match_input_image = true;
|
|
5692
|
+
case "qwen-image": {
|
|
5693
|
+
const refs = (req.references ?? []).map(refToUrl);
|
|
5694
|
+
const firstUrl = refs[0];
|
|
5695
|
+
const imageInput = { prompt: req.prompt };
|
|
5696
|
+
if (firstUrl !== void 0) {
|
|
5697
|
+
imageInput.image = firstUrl;
|
|
5698
|
+
imageInput.match_input_image = true;
|
|
5699
|
+
} else if (req.aspectRatio !== void 0 && QWEN_IMAGE_RATIOS.has(req.aspectRatio)) {
|
|
5700
|
+
imageInput.aspect_ratio = req.aspectRatio;
|
|
5701
|
+
}
|
|
5702
|
+
input = imageInput;
|
|
5703
|
+
break;
|
|
5386
5704
|
}
|
|
5387
|
-
|
|
5388
|
-
|
|
5389
|
-
|
|
5390
|
-
|
|
5391
|
-
|
|
5392
|
-
|
|
5393
|
-
|
|
5394
|
-
|
|
5395
|
-
|
|
5396
|
-
|
|
5705
|
+
case "qwen-edit": {
|
|
5706
|
+
const refs = (req.references ?? []).map(refToUrl);
|
|
5707
|
+
const firstUrl = refs[0];
|
|
5708
|
+
const imageInput = { prompt: req.prompt };
|
|
5709
|
+
if (firstUrl !== void 0) imageInput.image = firstUrl;
|
|
5710
|
+
if (req.aspectRatio !== void 0) {
|
|
5711
|
+
if (QWEN_EDIT_RATIOS.has(req.aspectRatio))
|
|
5712
|
+
imageInput.aspect_ratio = req.aspectRatio;
|
|
5713
|
+
else
|
|
5714
|
+
ctx.warnings.push({
|
|
5715
|
+
code: "option_ignored",
|
|
5716
|
+
field: "aspectRatio",
|
|
5717
|
+
from: req.aspectRatio,
|
|
5718
|
+
message: `${id} has no ${req.aspectRatio} aspect_ratio; using the provider default`
|
|
5719
|
+
});
|
|
5720
|
+
}
|
|
5721
|
+
if (req.outputFormat !== void 0) {
|
|
5722
|
+
imageInput.output_format = req.outputFormat === "jpeg" ? "jpg" : req.outputFormat;
|
|
5723
|
+
}
|
|
5724
|
+
input = imageInput;
|
|
5725
|
+
break;
|
|
5397
5726
|
}
|
|
5398
|
-
|
|
5399
|
-
|
|
5727
|
+
default: {
|
|
5728
|
+
const first = (req.references ?? [])[0];
|
|
5729
|
+
const imageInput = { prompt: req.prompt };
|
|
5730
|
+
if (first) imageInput.image = refToUrl(first);
|
|
5731
|
+
input = imageInput;
|
|
5400
5732
|
}
|
|
5401
|
-
input = imageInput;
|
|
5402
|
-
} else {
|
|
5403
|
-
const refs = req.references ?? [];
|
|
5404
|
-
const first = refs[0];
|
|
5405
|
-
const imageInput = { prompt: req.prompt };
|
|
5406
|
-
if (first) imageInput.image = refToUrl3(first);
|
|
5407
|
-
input = imageInput;
|
|
5408
5733
|
}
|
|
5409
5734
|
const { url, predictTime, raw } = await runPrediction(ctx, input, deps);
|
|
5410
5735
|
const file = await download(ctx, url);
|
|
@@ -5421,8 +5746,8 @@ function wanSize(aspectRatio) {
|
|
|
5421
5746
|
return w > h ? "2048*1152" : "1536*2048";
|
|
5422
5747
|
}
|
|
5423
5748
|
function klingInput(req) {
|
|
5424
|
-
const images = (req.firstFrame ? [req.firstFrame] : []).map(
|
|
5425
|
-
if (req.lastFrame) images.push(
|
|
5749
|
+
const images = (req.firstFrame ? [req.firstFrame] : []).map(refToUrl);
|
|
5750
|
+
if (req.lastFrame) images.push(refToUrl(req.lastFrame));
|
|
5426
5751
|
const input = {
|
|
5427
5752
|
prompt: req.prompt,
|
|
5428
5753
|
duration: req.durationSeconds ?? 10,
|
|
@@ -5434,19 +5759,24 @@ function klingInput(req) {
|
|
|
5434
5759
|
input.start_image = startImage;
|
|
5435
5760
|
const endImage = images[1];
|
|
5436
5761
|
if (endImage !== void 0) input.end_image = endImage;
|
|
5437
|
-
} else {
|
|
5762
|
+
} else if (req.aspectRatio !== "adaptive") {
|
|
5438
5763
|
input.aspect_ratio = req.aspectRatio ?? "16:9";
|
|
5439
5764
|
}
|
|
5440
5765
|
if (req.negativePrompt !== void 0) input.negative_prompt = req.negativePrompt;
|
|
5441
5766
|
return input;
|
|
5442
5767
|
}
|
|
5768
|
+
function klingOmniMode(req) {
|
|
5769
|
+
if (req.resolution === "1080p") return "pro";
|
|
5770
|
+
if (req.resolution === "720p") return "standard";
|
|
5771
|
+
return req.mode ?? "standard";
|
|
5772
|
+
}
|
|
5443
5773
|
function klingOmniInput(req) {
|
|
5444
|
-
const images = (req.firstFrame ? [req.firstFrame] : []).map(
|
|
5445
|
-
if (req.lastFrame) images.push(
|
|
5774
|
+
const images = (req.firstFrame ? [req.firstFrame] : []).map(refToUrl);
|
|
5775
|
+
if (req.lastFrame) images.push(refToUrl(req.lastFrame));
|
|
5446
5776
|
const input = {
|
|
5447
5777
|
prompt: req.prompt,
|
|
5448
5778
|
duration: req.durationSeconds ?? 10,
|
|
5449
|
-
mode: req
|
|
5779
|
+
mode: klingOmniMode(req),
|
|
5450
5780
|
generate_audio: req.generateAudio ?? false
|
|
5451
5781
|
};
|
|
5452
5782
|
const startImage = images[0];
|
|
@@ -5454,10 +5784,10 @@ function klingOmniInput(req) {
|
|
|
5454
5784
|
input.start_image = startImage;
|
|
5455
5785
|
const endImage = images[1];
|
|
5456
5786
|
if (endImage !== void 0) input.end_image = endImage;
|
|
5457
|
-
} else {
|
|
5787
|
+
} else if (req.aspectRatio !== "adaptive") {
|
|
5458
5788
|
input.aspect_ratio = req.aspectRatio ?? "16:9";
|
|
5459
5789
|
}
|
|
5460
|
-
const refs = (req.referenceImages ?? []).map(
|
|
5790
|
+
const refs = (req.referenceImages ?? []).map(refToUrl);
|
|
5461
5791
|
if (refs.length > 0) input.reference_images = refs;
|
|
5462
5792
|
return input;
|
|
5463
5793
|
}
|
|
@@ -5468,8 +5798,8 @@ function hailuoInput(req) {
|
|
|
5468
5798
|
resolution: req.resolution ?? "768p",
|
|
5469
5799
|
prompt_optimizer: true
|
|
5470
5800
|
};
|
|
5471
|
-
if (req.firstFrame) input.first_frame_image =
|
|
5472
|
-
if (req.lastFrame) input.last_frame_image =
|
|
5801
|
+
if (req.firstFrame) input.first_frame_image = refToUrl(req.firstFrame);
|
|
5802
|
+
if (req.lastFrame) input.last_frame_image = refToUrl(req.lastFrame);
|
|
5473
5803
|
return input;
|
|
5474
5804
|
}
|
|
5475
5805
|
function wanInput(req) {
|
|
@@ -5478,12 +5808,13 @@ function wanInput(req) {
|
|
|
5478
5808
|
duration: req.durationSeconds ?? 5,
|
|
5479
5809
|
size: wanSize(req.aspectRatio)
|
|
5480
5810
|
};
|
|
5481
|
-
if (req.firstFrame) input.image =
|
|
5811
|
+
if (req.firstFrame) input.image = refToUrl(req.firstFrame);
|
|
5482
5812
|
return input;
|
|
5483
5813
|
}
|
|
5484
5814
|
async function generateReplicateVideo(req, ctx, deps) {
|
|
5485
|
-
|
|
5486
|
-
const
|
|
5815
|
+
throwIfAborted(ctx.signal);
|
|
5816
|
+
const kind = videoKind(ctx.model.providerModelId);
|
|
5817
|
+
const input = kind === "kling" ? klingInput(req) : kind === "kling-omni" ? klingOmniInput(req) : kind === "hailuo" ? hailuoInput(req) : wanInput(req);
|
|
5487
5818
|
const api = client(ctx, deps);
|
|
5488
5819
|
const createOptions = { ...route(ctx.model.providerModelId), input };
|
|
5489
5820
|
let prediction;
|
|
@@ -5491,12 +5822,14 @@ async function generateReplicateVideo(req, ctx, deps) {
|
|
|
5491
5822
|
prediction = await withRetry(
|
|
5492
5823
|
async () => {
|
|
5493
5824
|
try {
|
|
5494
|
-
return await api.predictions.create(
|
|
5825
|
+
return await api.predictions.create(
|
|
5826
|
+
ctx.signal ? { ...createOptions, signal: ctx.signal } : createOptions
|
|
5827
|
+
);
|
|
5495
5828
|
} catch (cause) {
|
|
5496
5829
|
throw replicateError(cause, ctx);
|
|
5497
5830
|
}
|
|
5498
5831
|
},
|
|
5499
|
-
|
|
5832
|
+
{ attempts: 1 }
|
|
5500
5833
|
);
|
|
5501
5834
|
} catch (cause) {
|
|
5502
5835
|
throw replicateError(cause, ctx);
|
|
@@ -5505,7 +5838,10 @@ async function generateReplicateVideo(req, ctx, deps) {
|
|
|
5505
5838
|
const check = async () => {
|
|
5506
5839
|
let current;
|
|
5507
5840
|
try {
|
|
5508
|
-
current = await api.predictions.get(
|
|
5841
|
+
current = await api.predictions.get(
|
|
5842
|
+
jobId,
|
|
5843
|
+
ctx.signal ? { signal: ctx.signal } : void 0
|
|
5844
|
+
);
|
|
5509
5845
|
} catch (cause) {
|
|
5510
5846
|
throw replicateError(cause, ctx);
|
|
5511
5847
|
}
|
|
@@ -5606,7 +5942,7 @@ function mmaudioInput(req, ctx) {
|
|
|
5606
5942
|
});
|
|
5607
5943
|
}
|
|
5608
5944
|
const input = {
|
|
5609
|
-
video:
|
|
5945
|
+
video: refToUrl(video),
|
|
5610
5946
|
duration: req.durationSeconds ?? 8,
|
|
5611
5947
|
seed: req.seed ?? -1
|
|
5612
5948
|
};
|
|
@@ -5625,8 +5961,8 @@ function predictionRaw(prediction) {
|
|
|
5625
5961
|
return raw;
|
|
5626
5962
|
}
|
|
5627
5963
|
async function generateReplicateAudio(req, ctx, deps) {
|
|
5628
|
-
const
|
|
5629
|
-
const input =
|
|
5964
|
+
const kind = audioKind(ctx.model.providerModelId);
|
|
5965
|
+
const input = kind === "mmaudio" ? mmaudioInput(req, ctx) : kind === "elevenlabs" ? elevenLabsMusicInput(req, ctx) : lyriaAudioInput(req, ctx);
|
|
5630
5966
|
const { url, predictTime, raw } = await runPrediction(ctx, input, deps);
|
|
5631
5967
|
const usage2 = audioUsage(ctx, req);
|
|
5632
5968
|
if (ctx.model.usage.unit === "seconds") {
|
|
@@ -5655,19 +5991,14 @@ function createXaiVideoAdapter(deps = defaultXaiDeps) {
|
|
|
5655
5991
|
};
|
|
5656
5992
|
}
|
|
5657
5993
|
var xaiVideoAdapter = createXaiVideoAdapter();
|
|
5658
|
-
function refToUrl4(ref) {
|
|
5659
|
-
if ("url" in ref) return ref.url;
|
|
5660
|
-
return `data:${ref.mime};base64,${Buffer.from(ref.bytes).toString("base64")}`;
|
|
5661
|
-
}
|
|
5662
5994
|
var xaiResponseStatusSchema = import_zod13.z.object({
|
|
5663
5995
|
response: import_zod13.z.object({ status: import_zod13.z.number() }).partial()
|
|
5664
5996
|
});
|
|
5665
5997
|
function xaiError(cause, ctx) {
|
|
5666
|
-
if (isModelKitError(cause)) return cause;
|
|
5667
5998
|
const info = describeThrown(cause);
|
|
5668
5999
|
const nested = xaiResponseStatusSchema.safeParse(cause);
|
|
5669
6000
|
const status = info.status ?? (nested.success ? nested.data.response?.status : void 0);
|
|
5670
|
-
return
|
|
6001
|
+
return classifyThrown("xai-video", cause, ctx.model.id, { status, body: info.body });
|
|
5671
6002
|
}
|
|
5672
6003
|
var xaiMetaSchema = import_zod13.z.object({
|
|
5673
6004
|
videoUrl: JsonValueSchema.optional(),
|
|
@@ -5691,27 +6022,35 @@ async function generateXaiVideo(req, ctx, deps) {
|
|
|
5691
6022
|
retryable: false
|
|
5692
6023
|
});
|
|
5693
6024
|
}
|
|
5694
|
-
const
|
|
5695
|
-
(r) => r !== void 0
|
|
5696
|
-
);
|
|
5697
|
-
const refUrls = frames.map(refToUrl4).slice(0, 5);
|
|
5698
|
-
const resolution = req.resolution === "480p" ? "480p" : "720p";
|
|
6025
|
+
const refUrls = (req.referenceImages ?? []).map(refToUrl).slice(0, 7);
|
|
5699
6026
|
const xaiOptions = {
|
|
5700
|
-
resolution,
|
|
5701
6027
|
pollIntervalMs: POLL_INTERVAL_MS2,
|
|
5702
6028
|
pollTimeoutMs: POLL_TIMEOUT_MS2
|
|
5703
6029
|
};
|
|
6030
|
+
if (req.resolution === "480p" || req.resolution === "720p" || req.resolution === "1080p") {
|
|
6031
|
+
xaiOptions.resolution = req.resolution;
|
|
6032
|
+
}
|
|
5704
6033
|
if (refUrls.length > 0) {
|
|
5705
6034
|
xaiOptions.mode = "reference-to-video";
|
|
5706
6035
|
xaiOptions.referenceImageUrls = refUrls;
|
|
5707
6036
|
}
|
|
6037
|
+
if (req.lastFrame !== void 0) {
|
|
6038
|
+
ctx.warnings.push({
|
|
6039
|
+
code: "option_ignored",
|
|
6040
|
+
field: "lastFrame",
|
|
6041
|
+
message: "xai-video does not support lastFrame; ignored"
|
|
6042
|
+
});
|
|
6043
|
+
}
|
|
5708
6044
|
const client2 = deps.createXaiClient({ apiKey });
|
|
5709
|
-
const model = (0, import_xai2.createXai)({ apiKey }).video(ctx.model.providerModelId);
|
|
6045
|
+
const model = (0, import_xai2.createXai)({ apiKey, fetch: ctx.fetch }).video(ctx.model.providerModelId);
|
|
5710
6046
|
const callBody = {
|
|
5711
6047
|
model,
|
|
5712
6048
|
prompt: req.prompt,
|
|
5713
6049
|
providerOptions: { xai: xaiOptions }
|
|
5714
6050
|
};
|
|
6051
|
+
if (req.firstFrame) {
|
|
6052
|
+
callBody.frameImages = [{ image: refToUrl(req.firstFrame), frameType: "first_frame" }];
|
|
6053
|
+
}
|
|
5715
6054
|
if (req.aspectRatio !== void 0 && req.aspectRatio !== "adaptive") {
|
|
5716
6055
|
callBody.aspectRatio = req.aspectRatio;
|
|
5717
6056
|
}
|
|
@@ -5746,7 +6085,8 @@ async function generateXaiVideo(req, ctx, deps) {
|
|
|
5746
6085
|
return settled;
|
|
5747
6086
|
};
|
|
5748
6087
|
return {
|
|
5749
|
-
|
|
6088
|
+
// xAI exposes no request id on the synchronous handle, so each job gets a fresh one.
|
|
6089
|
+
jobId: crypto.randomUUID(),
|
|
5750
6090
|
async poll() {
|
|
5751
6091
|
if (failed !== void 0) return { status: "failed" };
|
|
5752
6092
|
return settled ? { status: "succeeded" } : { status: "pending" };
|
|
@@ -5797,26 +6137,14 @@ async function mapResult(ctx, req, result) {
|
|
|
5797
6137
|
function usage(ctx, req, meta) {
|
|
5798
6138
|
const costTicks = import_zod13.z.number().safeParse(meta.costInUsdTicks);
|
|
5799
6139
|
const cost = costTicks.success ? costTicks.data / 1e10 : void 0;
|
|
5800
|
-
if (cost !== void 0) {
|
|
5801
|
-
const event2 = {
|
|
5802
|
-
model: ctx.model.id,
|
|
5803
|
-
provider: "xai-video",
|
|
5804
|
-
modality: "VIDEO",
|
|
5805
|
-
unit: "reported_cost_usd",
|
|
5806
|
-
quantity: cost,
|
|
5807
|
-
reportedCostUsd: cost
|
|
5808
|
-
};
|
|
5809
|
-
if (req.durationSeconds !== void 0) event2.durationSeconds = req.durationSeconds;
|
|
5810
|
-
if (req.resolution !== void 0) event2.resolution = req.resolution;
|
|
5811
|
-
return event2;
|
|
5812
|
-
}
|
|
5813
6140
|
const event = {
|
|
5814
6141
|
model: ctx.model.id,
|
|
5815
6142
|
provider: "xai-video",
|
|
5816
6143
|
modality: "VIDEO",
|
|
5817
|
-
unit: "
|
|
5818
|
-
quantity:
|
|
6144
|
+
unit: "reported_cost_usd",
|
|
6145
|
+
quantity: cost ?? 0
|
|
5819
6146
|
};
|
|
6147
|
+
if (cost !== void 0) event.reportedCostUsd = cost;
|
|
5820
6148
|
if (req.durationSeconds !== void 0) event.durationSeconds = req.durationSeconds;
|
|
5821
6149
|
if (req.resolution !== void 0) event.resolution = req.resolution;
|
|
5822
6150
|
return event;
|
|
@@ -5893,6 +6221,7 @@ var describe = (modelId) => createDefaultModelKit().describe(modelId);
|
|
|
5893
6221
|
prodiaAdapter,
|
|
5894
6222
|
readErrorBody,
|
|
5895
6223
|
replicateAdapter,
|
|
6224
|
+
resolveAudioOptions,
|
|
5896
6225
|
resolveImageOptions,
|
|
5897
6226
|
resolveKeys,
|
|
5898
6227
|
resolveVideoOptions,
|