@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.js
CHANGED
|
@@ -93,7 +93,8 @@ var GEMINI_RATIOS = [
|
|
|
93
93
|
"3:4",
|
|
94
94
|
"21:9",
|
|
95
95
|
"4:5",
|
|
96
|
-
"5:4"
|
|
96
|
+
"5:4",
|
|
97
|
+
"adaptive"
|
|
97
98
|
];
|
|
98
99
|
function geminiImage(id, label, aliases, sizes) {
|
|
99
100
|
const model = {
|
|
@@ -104,7 +105,11 @@ function geminiImage(id, label, aliases, sizes) {
|
|
|
104
105
|
adapter: "google-image",
|
|
105
106
|
providerModelId: id,
|
|
106
107
|
lifecycle: "active",
|
|
107
|
-
constraints: {
|
|
108
|
+
constraints: {
|
|
109
|
+
aspectRatios: [...GEMINI_RATIOS],
|
|
110
|
+
sizes,
|
|
111
|
+
supports: ["safetySettings", "temperature"]
|
|
112
|
+
},
|
|
108
113
|
defaults: { size: "1K", aspectRatio: "1:1" },
|
|
109
114
|
usage: { ...IMAGE_USAGE },
|
|
110
115
|
pricingKind: "image_size"
|
|
@@ -201,7 +206,8 @@ var IMAGE_MODELS = [
|
|
|
201
206
|
"9:16",
|
|
202
207
|
"4:5",
|
|
203
208
|
"5:4",
|
|
204
|
-
"9:21"
|
|
209
|
+
"9:21",
|
|
210
|
+
"adaptive"
|
|
205
211
|
],
|
|
206
212
|
sizes: ["1K"],
|
|
207
213
|
references: { images: 10 },
|
|
@@ -242,8 +248,20 @@ var IMAGE_MODELS = [
|
|
|
242
248
|
constraints: {
|
|
243
249
|
// 97:30 has no Ark size spelling; the A+ flow pads inputs to 97:30 and
|
|
244
250
|
// omits the ratio instead. Advertise only sizes the adapter can send.
|
|
245
|
-
aspectRatios: [
|
|
246
|
-
|
|
251
|
+
aspectRatios: [
|
|
252
|
+
"1:1",
|
|
253
|
+
"2:3",
|
|
254
|
+
"3:2",
|
|
255
|
+
"4:3",
|
|
256
|
+
"3:4",
|
|
257
|
+
"4:5",
|
|
258
|
+
"5:4",
|
|
259
|
+
"9:16",
|
|
260
|
+
"16:9",
|
|
261
|
+
"21:9",
|
|
262
|
+
"9:21"
|
|
263
|
+
],
|
|
264
|
+
sizes: ["1K", "2K", "4K"],
|
|
247
265
|
references: { images: 10 },
|
|
248
266
|
supports: ["seed"]
|
|
249
267
|
},
|
|
@@ -262,9 +280,10 @@ var IMAGE_MODELS = [
|
|
|
262
280
|
constraints: {
|
|
263
281
|
aspectRatios: ["1:1", "2:3", "3:2", "16:9", "9:16", "4:3", "3:4", "4:5", "5:4", "21:9"],
|
|
264
282
|
sizes: ["1K"],
|
|
265
|
-
|
|
283
|
+
// flux-2-pro's job type always returns image/png; only the seed is forwarded.
|
|
284
|
+
supports: ["seed"]
|
|
266
285
|
},
|
|
267
|
-
defaults: { size: "1K", aspectRatio: "1:1"
|
|
286
|
+
defaults: { size: "1K", aspectRatio: "1:1" },
|
|
268
287
|
usage: { ...IMAGE_USAGE },
|
|
269
288
|
pricingKind: "image_size"
|
|
270
289
|
},
|
|
@@ -282,7 +301,8 @@ var IMAGE_MODELS = [
|
|
|
282
301
|
constraints: {
|
|
283
302
|
aspectRatios: ["1:1", "2:3", "3:2", "4:3", "3:4", "4:5", "5:4", "9:16", "16:9", "21:9"],
|
|
284
303
|
sizes: ["1K", "2K", "4K"],
|
|
285
|
-
requires: ["references"]
|
|
304
|
+
requires: ["references"],
|
|
305
|
+
supports: ["seed"]
|
|
286
306
|
},
|
|
287
307
|
defaults: { size: "1K", aspectRatio: "1:1" },
|
|
288
308
|
usage: { ...IMAGE_USAGE },
|
|
@@ -301,7 +321,8 @@ var IMAGE_MODELS = [
|
|
|
301
321
|
constraints: {
|
|
302
322
|
aspectRatios: ["1:1", "2:3", "3:4", "4:3", "9:16", "16:9", "21:9"],
|
|
303
323
|
sizes: ["1K"],
|
|
304
|
-
requires: ["references"]
|
|
324
|
+
requires: ["references"],
|
|
325
|
+
supports: ["seed"]
|
|
305
326
|
},
|
|
306
327
|
defaults: { size: "1K", aspectRatio: "1:1" },
|
|
307
328
|
usage: { ...IMAGE_USAGE },
|
|
@@ -321,7 +342,8 @@ var IMAGE_MODELS = [
|
|
|
321
342
|
constraints: {
|
|
322
343
|
aspectRatios: ["1:1", "16:9", "9:16", "4:3", "3:4"],
|
|
323
344
|
sizes: ["1K", "2K", "4K"],
|
|
324
|
-
references: { images: 9 }
|
|
345
|
+
references: { images: 9 },
|
|
346
|
+
supports: []
|
|
325
347
|
},
|
|
326
348
|
defaults: { size: "1K", aspectRatio: "1:1" },
|
|
327
349
|
usage: { unit: "compute_seconds", modality: "IMAGE" },
|
|
@@ -342,7 +364,8 @@ var IMAGE_MODELS = [
|
|
|
342
364
|
aspectRatios: ["1:1", "16:9", "9:16", "4:3", "3:4", "3:2", "2:3"],
|
|
343
365
|
sizes: [],
|
|
344
366
|
references: { images: 1 },
|
|
345
|
-
requires: ["references"]
|
|
367
|
+
requires: ["references"],
|
|
368
|
+
supports: []
|
|
346
369
|
},
|
|
347
370
|
defaults: { aspectRatio: "1:1" },
|
|
348
371
|
usage: { unit: "compute_seconds", modality: "IMAGE" },
|
|
@@ -384,7 +407,8 @@ var OTHER_MODELS = [
|
|
|
384
407
|
lifecycle: "active",
|
|
385
408
|
constraints: {
|
|
386
409
|
durations: [30],
|
|
387
|
-
references: { images: 10 }
|
|
410
|
+
references: { images: 10 },
|
|
411
|
+
supports: []
|
|
388
412
|
},
|
|
389
413
|
defaults: {},
|
|
390
414
|
usage: { unit: "images", modality: "AUDIO" },
|
|
@@ -399,7 +423,8 @@ var OTHER_MODELS = [
|
|
|
399
423
|
providerModelId: "lyria-3-pro-preview",
|
|
400
424
|
lifecycle: "active",
|
|
401
425
|
constraints: {
|
|
402
|
-
references: { images: 10 }
|
|
426
|
+
references: { images: 10 },
|
|
427
|
+
supports: []
|
|
403
428
|
},
|
|
404
429
|
defaults: {},
|
|
405
430
|
usage: { unit: "images", modality: "AUDIO" },
|
|
@@ -466,7 +491,7 @@ var OTHER_MODELS = [
|
|
|
466
491
|
constraints: {
|
|
467
492
|
references: { images: 1 },
|
|
468
493
|
requires: ["references"],
|
|
469
|
-
supports: ["scaleFactor", "outputFormat"]
|
|
494
|
+
supports: ["scaleFactor", "outputFormat", "upscale"]
|
|
470
495
|
},
|
|
471
496
|
defaults: { scaleFactor: 2, outputFormat: "png" },
|
|
472
497
|
usage: { unit: "compute_seconds", modality: "IMAGE" },
|
|
@@ -482,7 +507,8 @@ var OTHER_MODELS = [
|
|
|
482
507
|
lifecycle: "active",
|
|
483
508
|
constraints: {
|
|
484
509
|
references: { images: 1 },
|
|
485
|
-
requires: ["references"]
|
|
510
|
+
requires: ["references"],
|
|
511
|
+
supports: []
|
|
486
512
|
},
|
|
487
513
|
defaults: {},
|
|
488
514
|
usage: { unit: "images", modality: "IMAGE" },
|
|
@@ -501,7 +527,7 @@ function text(id, label, providerModelId, extra) {
|
|
|
501
527
|
adapter: "ai-sdk-text",
|
|
502
528
|
providerModelId,
|
|
503
529
|
lifecycle: "active",
|
|
504
|
-
constraints: {},
|
|
530
|
+
constraints: { supports: [] },
|
|
505
531
|
defaults: {},
|
|
506
532
|
usage: { ...TEXT_USAGE },
|
|
507
533
|
pricingKind: "token",
|
|
@@ -574,7 +600,7 @@ var TEXT_MODELS = [
|
|
|
574
600
|
// src/catalog/video.ts
|
|
575
601
|
var VIDEO_USAGE = { unit: "seconds", modality: "VIDEO" };
|
|
576
602
|
var SEEDANCE_RATIOS = ["21:9", "16:9", "4:3", "1:1", "3:4", "9:16", "adaptive"];
|
|
577
|
-
var KLING_RATIOS = ["16:9", "9:16", "1:1"];
|
|
603
|
+
var KLING_RATIOS = ["16:9", "9:16", "1:1", "adaptive"];
|
|
578
604
|
var OMNI_RATIOS = ["16:9", "9:16"];
|
|
579
605
|
var GROK_RATIOS = ["1:1", "16:9", "9:16", "4:3", "3:4", "3:2", "2:3"];
|
|
580
606
|
var H3_RATIOS = ["21:9", "16:9", "4:3", "1:1", "3:4", "9:16"];
|
|
@@ -666,12 +692,15 @@ var VIDEO_MODELS = [
|
|
|
666
692
|
providerModelId: "gemini-omni-flash-preview",
|
|
667
693
|
lifecycle: "active",
|
|
668
694
|
constraints: {
|
|
695
|
+
// 1.0 rejects `resolution`; it renders 720p. No defaults: the adapter
|
|
696
|
+
// sends ratio and duration only when the caller set them, so a
|
|
697
|
+
// reference clip keeps its own framing.
|
|
669
698
|
aspectRatios: [...OMNI_RATIOS],
|
|
670
|
-
resolutions: ["720p"],
|
|
671
699
|
durations: [3, 4, 5, 6, 7, 8, 9, 10],
|
|
672
|
-
references: { images: 6, videos: 1 }
|
|
700
|
+
references: { images: 6, videos: 1 },
|
|
701
|
+
supports: []
|
|
673
702
|
},
|
|
674
|
-
defaults: {
|
|
703
|
+
defaults: {},
|
|
675
704
|
usage: { ...VIDEO_USAGE },
|
|
676
705
|
pricingKind: "video_per_second"
|
|
677
706
|
},
|
|
@@ -687,9 +716,10 @@ var VIDEO_MODELS = [
|
|
|
687
716
|
aspectRatios: [...OMNI_RATIOS],
|
|
688
717
|
resolutions: ["360p", "720p", "1080p", "4k"],
|
|
689
718
|
durations: [3, 4, 5, 6, 7, 8, 9, 10],
|
|
690
|
-
references: { images: 6, videos: 1 }
|
|
719
|
+
references: { images: 6, videos: 1 },
|
|
720
|
+
supports: []
|
|
691
721
|
},
|
|
692
|
-
defaults: {
|
|
722
|
+
defaults: {},
|
|
693
723
|
usage: { ...VIDEO_USAGE },
|
|
694
724
|
pricingKind: "video_per_second"
|
|
695
725
|
},
|
|
@@ -708,7 +738,7 @@ var VIDEO_MODELS = [
|
|
|
708
738
|
durations: [4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
|
|
709
739
|
references: { images: 9, videos: 3, audios: 3, audioOnly: false },
|
|
710
740
|
ratioIgnoredWith: ["firstFrame"],
|
|
711
|
-
supports: ["generateAudio", "seed", "lastFrame"]
|
|
741
|
+
supports: ["generateAudio", "seed", "lastFrame", "watermark"]
|
|
712
742
|
},
|
|
713
743
|
defaults: {
|
|
714
744
|
durationSeconds: 5,
|
|
@@ -733,7 +763,7 @@ var VIDEO_MODELS = [
|
|
|
733
763
|
durations: [4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
|
|
734
764
|
references: { images: 9, videos: 3, audios: 3, audioOnly: false },
|
|
735
765
|
ratioIgnoredWith: ["firstFrame"],
|
|
736
|
-
supports: ["generateAudio", "seed", "lastFrame"]
|
|
766
|
+
supports: ["generateAudio", "seed", "lastFrame", "watermark"]
|
|
737
767
|
},
|
|
738
768
|
defaults: {
|
|
739
769
|
durationSeconds: 5,
|
|
@@ -759,7 +789,7 @@ var VIDEO_MODELS = [
|
|
|
759
789
|
durations: { min: 4, max: 30 },
|
|
760
790
|
references: { images: 30, videos: 10, audios: 10 },
|
|
761
791
|
ratioIgnoredWith: ["firstFrame"],
|
|
762
|
-
supports: ["generateAudio", "seed", "lastFrame"]
|
|
792
|
+
supports: ["generateAudio", "seed", "lastFrame", "watermark"]
|
|
763
793
|
},
|
|
764
794
|
defaults: {
|
|
765
795
|
durationSeconds: 5,
|
|
@@ -783,9 +813,11 @@ var VIDEO_MODELS = [
|
|
|
783
813
|
aspectRatios: [...GROK_RATIOS],
|
|
784
814
|
resolutions: ["480p", "720p"],
|
|
785
815
|
durations: { min: 1, max: 15 },
|
|
786
|
-
references: { images: 7 }
|
|
816
|
+
references: { images: 7 },
|
|
817
|
+
supports: []
|
|
787
818
|
},
|
|
788
|
-
|
|
819
|
+
// No resolution default: xAI picks its own unless the caller asks.
|
|
820
|
+
defaults: { durationSeconds: 8, aspectRatio: "16:9" },
|
|
789
821
|
usage: { unit: "reported_cost_usd", modality: "VIDEO" },
|
|
790
822
|
pricingKind: "video_per_second"
|
|
791
823
|
},
|
|
@@ -879,7 +911,7 @@ var VIDEO_MODELS = [
|
|
|
879
911
|
aspectRatios: [...H3_RATIOS],
|
|
880
912
|
resolutions: ["480p", "768p", "2k", "4k"],
|
|
881
913
|
durations: { min: 5, max: 15 },
|
|
882
|
-
supports: ["seed", "promptExpansion"]
|
|
914
|
+
supports: ["seed", "promptExpansion", "lastFrame", "safetyChecker"]
|
|
883
915
|
},
|
|
884
916
|
defaults: {
|
|
885
917
|
durationSeconds: 5,
|
|
@@ -902,7 +934,7 @@ var VIDEO_MODELS = [
|
|
|
902
934
|
aspectRatios: [...H3_RATIOS],
|
|
903
935
|
resolutions: ["480p", "768p"],
|
|
904
936
|
durations: { min: 5, max: 15 },
|
|
905
|
-
supports: ["seed", "promptExpansion"]
|
|
937
|
+
supports: ["seed", "promptExpansion", "lastFrame", "safetyChecker"]
|
|
906
938
|
},
|
|
907
939
|
defaults: {
|
|
908
940
|
durationSeconds: 5,
|
|
@@ -926,7 +958,7 @@ var VIDEO_MODELS = [
|
|
|
926
958
|
resolutions: ["480p", "768p", "2k", "4k"],
|
|
927
959
|
durations: { min: 5, max: 15 },
|
|
928
960
|
references: { images: 9, videos: 3, audios: 3, total: 12, audioOnly: false },
|
|
929
|
-
supports: ["seed", "promptExpansion"]
|
|
961
|
+
supports: ["seed", "promptExpansion", "safetyChecker"]
|
|
930
962
|
},
|
|
931
963
|
defaults: {
|
|
932
964
|
durationSeconds: 5,
|
|
@@ -950,7 +982,7 @@ var VIDEO_MODELS = [
|
|
|
950
982
|
resolutions: ["480p", "768p"],
|
|
951
983
|
durations: { min: 5, max: 15 },
|
|
952
984
|
references: { images: 9, videos: 3, audios: 3, total: 12, audioOnly: false },
|
|
953
|
-
supports: ["seed", "promptExpansion"]
|
|
985
|
+
supports: ["seed", "promptExpansion", "safetyChecker"]
|
|
954
986
|
},
|
|
955
987
|
defaults: {
|
|
956
988
|
durationSeconds: 5,
|
|
@@ -973,7 +1005,8 @@ var VIDEO_MODELS = [
|
|
|
973
1005
|
constraints: {
|
|
974
1006
|
aspectRatios: [...KLING_RATIOS],
|
|
975
1007
|
durations: { min: 3, max: 10 },
|
|
976
|
-
requires: ["sourceVideo"]
|
|
1008
|
+
requires: ["sourceVideo"],
|
|
1009
|
+
supports: []
|
|
977
1010
|
},
|
|
978
1011
|
defaults: { durationSeconds: 5, aspectRatio: "16:9" },
|
|
979
1012
|
usage: { ...VIDEO_USAGE },
|
|
@@ -1006,7 +1039,7 @@ var VIDEO_MODELS = [
|
|
|
1006
1039
|
lifecycle: "active",
|
|
1007
1040
|
constraints: {
|
|
1008
1041
|
requires: ["firstFrame"],
|
|
1009
|
-
supports: ["seed"]
|
|
1042
|
+
supports: ["seed", "lastFrame"]
|
|
1010
1043
|
},
|
|
1011
1044
|
defaults: {},
|
|
1012
1045
|
usage: { ...VIDEO_USAGE },
|
|
@@ -1077,19 +1110,22 @@ function resolveTier(field, code, requested, supported, order, model, onUnsuppor
|
|
|
1077
1110
|
});
|
|
1078
1111
|
return to;
|
|
1079
1112
|
}
|
|
1080
|
-
function resolveDuration(requested, durations, model, warnings) {
|
|
1113
|
+
function resolveDuration(requested, durations, model, onUnsupported, warnings) {
|
|
1081
1114
|
if (requested === void 0 || !durations) return requested;
|
|
1082
|
-
|
|
1083
|
-
if (
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
if (to === requested) return requested;
|
|
1115
|
+
const inSet = Array.isArray(durations) ? durations.includes(requested) : requested >= durations.min && requested <= durations.max;
|
|
1116
|
+
if (inSet) return requested;
|
|
1117
|
+
if (onUnsupported === "error") {
|
|
1118
|
+
const supported = Array.isArray(durations) ? `Supported: ${durations.join(", ")}.` : `Supported range: ${durations.min}-${durations.max}.`;
|
|
1119
|
+
throw new ModelKitError({
|
|
1120
|
+
code: "unsupported_option",
|
|
1121
|
+
message: `${model.id} does not support durationSeconds ${requested}. ${supported}`,
|
|
1122
|
+
model: model.id
|
|
1123
|
+
});
|
|
1092
1124
|
}
|
|
1125
|
+
const to = Array.isArray(durations) ? durations.reduce(
|
|
1126
|
+
(best, d) => Math.abs(d - requested) < Math.abs(best - requested) ? d : best,
|
|
1127
|
+
durations[0] ?? requested
|
|
1128
|
+
) : Math.min(Math.max(requested, durations.min), durations.max);
|
|
1093
1129
|
warnings.push({
|
|
1094
1130
|
code: "duration_coerced",
|
|
1095
1131
|
field: "durationSeconds",
|
|
@@ -1099,6 +1135,26 @@ function resolveDuration(requested, durations, model, warnings) {
|
|
|
1099
1135
|
});
|
|
1100
1136
|
return to;
|
|
1101
1137
|
}
|
|
1138
|
+
function resolveAspectRatio(requested, supported, model, onUnsupported, warnings) {
|
|
1139
|
+
if (requested === void 0 || requested === "adaptive" || !supported) return requested;
|
|
1140
|
+
if (supported.includes(requested)) return requested;
|
|
1141
|
+
if (onUnsupported === "error") {
|
|
1142
|
+
throw new ModelKitError({
|
|
1143
|
+
code: "unsupported_option",
|
|
1144
|
+
message: `${model.id} does not support aspectRatio "${requested}". Supported: ${supported.join(", ")}.`,
|
|
1145
|
+
model: model.id
|
|
1146
|
+
});
|
|
1147
|
+
}
|
|
1148
|
+
const to = nearestAspectRatio(requested, supported);
|
|
1149
|
+
warnings.push({
|
|
1150
|
+
code: "ratio_coerced",
|
|
1151
|
+
field: "aspectRatio",
|
|
1152
|
+
from: requested,
|
|
1153
|
+
to,
|
|
1154
|
+
message: `aspect ratio ${requested} coerced to ${to} for ${model.id}`
|
|
1155
|
+
});
|
|
1156
|
+
return to;
|
|
1157
|
+
}
|
|
1102
1158
|
function compact(refs) {
|
|
1103
1159
|
return (refs ?? []).filter((r) => Boolean(r));
|
|
1104
1160
|
}
|
|
@@ -1117,17 +1173,14 @@ function resolveImageOptions(model, request, onUnsupported = "error") {
|
|
|
1117
1173
|
const warnings = [];
|
|
1118
1174
|
const c = model.constraints;
|
|
1119
1175
|
const merged = { ...model.defaults, ...stripUndefined(request), model: model.id };
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
});
|
|
1129
|
-
merged.aspectRatio = to;
|
|
1130
|
-
}
|
|
1176
|
+
const aspectRatio = resolveAspectRatio(
|
|
1177
|
+
merged.aspectRatio,
|
|
1178
|
+
c.aspectRatios,
|
|
1179
|
+
model,
|
|
1180
|
+
onUnsupported,
|
|
1181
|
+
warnings
|
|
1182
|
+
);
|
|
1183
|
+
if (aspectRatio !== void 0) merged.aspectRatio = aspectRatio;
|
|
1131
1184
|
const size = resolveTier(
|
|
1132
1185
|
"size",
|
|
1133
1186
|
"size_coerced",
|
|
@@ -1160,7 +1213,10 @@ function resolveImageOptions(model, request, onUnsupported = "error") {
|
|
|
1160
1213
|
"quality",
|
|
1161
1214
|
"count",
|
|
1162
1215
|
"outputFormat",
|
|
1163
|
-
"scaleFactor"
|
|
1216
|
+
"scaleFactor",
|
|
1217
|
+
"safetySettings",
|
|
1218
|
+
"temperature",
|
|
1219
|
+
"upscale"
|
|
1164
1220
|
]);
|
|
1165
1221
|
return { request: merged, warnings };
|
|
1166
1222
|
}
|
|
@@ -1190,17 +1246,14 @@ function resolveVideoOptions(model, request, onUnsupported = "error") {
|
|
|
1190
1246
|
delete merged.aspectRatio;
|
|
1191
1247
|
}
|
|
1192
1248
|
}
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
});
|
|
1202
|
-
merged.aspectRatio = to;
|
|
1203
|
-
}
|
|
1249
|
+
const aspectRatio = resolveAspectRatio(
|
|
1250
|
+
merged.aspectRatio,
|
|
1251
|
+
c.aspectRatios,
|
|
1252
|
+
model,
|
|
1253
|
+
onUnsupported,
|
|
1254
|
+
warnings
|
|
1255
|
+
);
|
|
1256
|
+
if (aspectRatio !== void 0) merged.aspectRatio = aspectRatio;
|
|
1204
1257
|
const resolution = resolveTier(
|
|
1205
1258
|
"resolution",
|
|
1206
1259
|
"resolution_coerced",
|
|
@@ -1212,7 +1265,13 @@ function resolveVideoOptions(model, request, onUnsupported = "error") {
|
|
|
1212
1265
|
warnings
|
|
1213
1266
|
);
|
|
1214
1267
|
if (resolution !== void 0) merged.resolution = resolution;
|
|
1215
|
-
const duration = resolveDuration(
|
|
1268
|
+
const duration = resolveDuration(
|
|
1269
|
+
merged.durationSeconds,
|
|
1270
|
+
c.durations,
|
|
1271
|
+
model,
|
|
1272
|
+
onUnsupported,
|
|
1273
|
+
warnings
|
|
1274
|
+
);
|
|
1216
1275
|
if (duration !== void 0) merged.durationSeconds = duration;
|
|
1217
1276
|
const limits = c.references ?? {};
|
|
1218
1277
|
let images = trim(
|
|
@@ -1267,13 +1326,47 @@ function resolveVideoOptions(model, request, onUnsupported = "error") {
|
|
|
1267
1326
|
"cfgScale",
|
|
1268
1327
|
"generateAudio",
|
|
1269
1328
|
"promptExpansion",
|
|
1270
|
-
"lastFrame"
|
|
1329
|
+
"lastFrame",
|
|
1330
|
+
"watermark",
|
|
1331
|
+
"safetyChecker"
|
|
1271
1332
|
]);
|
|
1272
1333
|
return { request: merged, warnings };
|
|
1273
1334
|
}
|
|
1335
|
+
function resolveAudioOptions(model, request, onUnsupported = "error") {
|
|
1336
|
+
const warnings = [];
|
|
1337
|
+
const c = model.constraints;
|
|
1338
|
+
const merged = { ...model.defaults, ...stripUndefined(request), model: model.id };
|
|
1339
|
+
for (const input of c.requires ?? []) {
|
|
1340
|
+
const present = input === "references" ? compact(merged.references).length > 0 : input === "sourceVideo" && merged.sourceVideo !== void 0;
|
|
1341
|
+
if (!present)
|
|
1342
|
+
throw new ModelKitError({
|
|
1343
|
+
code: "missing_input",
|
|
1344
|
+
message: `${model.id} requires ${input}`,
|
|
1345
|
+
model: model.id
|
|
1346
|
+
});
|
|
1347
|
+
}
|
|
1348
|
+
const duration = resolveDuration(
|
|
1349
|
+
merged.durationSeconds,
|
|
1350
|
+
c.durations,
|
|
1351
|
+
model,
|
|
1352
|
+
onUnsupported,
|
|
1353
|
+
warnings
|
|
1354
|
+
);
|
|
1355
|
+
if (duration !== void 0) merged.durationSeconds = duration;
|
|
1356
|
+
const references = trim(
|
|
1357
|
+
"references",
|
|
1358
|
+
compact(merged.references),
|
|
1359
|
+
c.references?.images ?? c.references?.total,
|
|
1360
|
+
model,
|
|
1361
|
+
warnings
|
|
1362
|
+
);
|
|
1363
|
+
if (references.length > 0) merged.references = references;
|
|
1364
|
+
else delete merged.references;
|
|
1365
|
+
dropUnsupported(merged, model, warnings, ["seed", "negativePrompt", "instrumental"]);
|
|
1366
|
+
return { request: merged, warnings };
|
|
1367
|
+
}
|
|
1274
1368
|
function dropUnsupported(req, model, warnings, fields) {
|
|
1275
|
-
const supports = model.constraints.supports;
|
|
1276
|
-
if (!supports) return;
|
|
1369
|
+
const supports = model.constraints.supports ?? [];
|
|
1277
1370
|
for (const field of fields) {
|
|
1278
1371
|
if (req[field] !== void 0 && !supports.includes(field)) {
|
|
1279
1372
|
warnings.push({
|
|
@@ -1313,6 +1406,9 @@ function hasAll(keys, names) {
|
|
|
1313
1406
|
(n) => Boolean(keys[n]) && (n !== "higgsfield" || Boolean(keys.higgsfieldSecret))
|
|
1314
1407
|
);
|
|
1315
1408
|
}
|
|
1409
|
+
function missingEnterpriseKeys(config, names) {
|
|
1410
|
+
return names.filter((name) => !hasAll(config.keys.enterprise, [name]));
|
|
1411
|
+
}
|
|
1316
1412
|
function resolveKeys(config, names, tier = "pro") {
|
|
1317
1413
|
if (tier === "enterprise" && hasAll(config.keys.enterprise, names))
|
|
1318
1414
|
return config.keys.enterprise;
|
|
@@ -1345,18 +1441,56 @@ function keysFromEnv(env, prefix = "") {
|
|
|
1345
1441
|
set("prodia", pick("PRODIA_API_KEY", "PRODIA_TOKEN"));
|
|
1346
1442
|
set("higgsfield", pick("HIGGSFIELD_API_KEY"));
|
|
1347
1443
|
set("higgsfieldSecret", pick("HIGGSFIELD_API_SECRET"));
|
|
1348
|
-
set("openrouter", pick("OPENROUTER_API_KEY"));
|
|
1349
1444
|
set("cloudflare", pick("CLOUDFLARE_AI_GATEWAY_TOKEN", "CF_AIG_TOKEN"));
|
|
1350
1445
|
return keys;
|
|
1351
1446
|
}
|
|
1352
1447
|
|
|
1353
1448
|
// src/retry.ts
|
|
1449
|
+
import { z as z2 } from "zod";
|
|
1450
|
+
|
|
1451
|
+
// src/json.ts
|
|
1354
1452
|
import { z } from "zod";
|
|
1355
|
-
var
|
|
1453
|
+
var JsonValueSchema = z.lazy(
|
|
1454
|
+
() => z.union([
|
|
1455
|
+
z.string(),
|
|
1456
|
+
z.number(),
|
|
1457
|
+
z.boolean(),
|
|
1458
|
+
z.null(),
|
|
1459
|
+
z.array(JsonValueSchema),
|
|
1460
|
+
z.record(z.string(), JsonValueSchema)
|
|
1461
|
+
])
|
|
1462
|
+
);
|
|
1463
|
+
var JsonObjectSchema = z.record(z.string(), JsonValueSchema);
|
|
1464
|
+
async function readErrorBody(res) {
|
|
1465
|
+
const text2 = await res.text().catch(() => "");
|
|
1466
|
+
try {
|
|
1467
|
+
return JsonValueSchema.parse(JSON.parse(text2));
|
|
1468
|
+
} catch {
|
|
1469
|
+
return text2;
|
|
1470
|
+
}
|
|
1471
|
+
}
|
|
1472
|
+
var thrownErrorSchema = z.object({
|
|
1473
|
+
message: z.string().optional(),
|
|
1474
|
+
status: z.number().optional(),
|
|
1475
|
+
statusCode: z.number().optional(),
|
|
1476
|
+
responseBody: z.string().optional()
|
|
1477
|
+
});
|
|
1478
|
+
function describeThrown(cause) {
|
|
1479
|
+
const parsed = thrownErrorSchema.safeParse(cause);
|
|
1480
|
+
if (!parsed.success) return { message: String(cause), status: void 0, body: String(cause) };
|
|
1481
|
+
const { message, status, statusCode, responseBody } = parsed.data;
|
|
1482
|
+
const body = responseBody ?? message ?? String(cause);
|
|
1483
|
+
return { message: message ?? String(cause), status: status ?? statusCode, body };
|
|
1484
|
+
}
|
|
1485
|
+
|
|
1486
|
+
// src/retry.ts
|
|
1487
|
+
var textBody = z2.string();
|
|
1356
1488
|
function classifyHttpError(status, body, provider, model) {
|
|
1357
1489
|
const asText = textBody.safeParse(body);
|
|
1358
1490
|
const text2 = asText.success ? asText.data : JSON.stringify(body);
|
|
1359
|
-
const blocked = /
|
|
1491
|
+
const blocked = /content_policy_violation|blockReason|PROHIBITED_CONTENT|moderation_blocked|safety(?![_A-Za-z])/i.test(
|
|
1492
|
+
text2
|
|
1493
|
+
);
|
|
1360
1494
|
let code = "provider_rejected";
|
|
1361
1495
|
if (blocked) code = "content_blocked";
|
|
1362
1496
|
else if (status === 401 || status === 403) code = "auth";
|
|
@@ -1377,8 +1511,8 @@ function classifyHttpError(status, body, provider, model) {
|
|
|
1377
1511
|
}
|
|
1378
1512
|
function shouldRetry(err) {
|
|
1379
1513
|
if (err instanceof ModelKitError) return err.retryable;
|
|
1380
|
-
if (err.name === "AbortError"
|
|
1381
|
-
|
|
1514
|
+
if (err.name === "AbortError") return false;
|
|
1515
|
+
if (/ECONNRESET|ETIMEDOUT|fetch failed|socket hang up/i.test(err.message)) return true;
|
|
1382
1516
|
return false;
|
|
1383
1517
|
}
|
|
1384
1518
|
async function withRetry(fn, opts = {}) {
|
|
@@ -1435,6 +1569,13 @@ function transportError(provider, cause, model) {
|
|
|
1435
1569
|
if (model !== void 0) init.model = model;
|
|
1436
1570
|
return new ModelKitError(init);
|
|
1437
1571
|
}
|
|
1572
|
+
function classifyThrown(provider, cause, model, override = {}) {
|
|
1573
|
+
if (cause instanceof ModelKitError) return cause;
|
|
1574
|
+
const info = describeThrown(cause);
|
|
1575
|
+
const status = override.status ?? info.status;
|
|
1576
|
+
if (status === void 0) return transportError(provider, cause, model);
|
|
1577
|
+
return classifyHttpError(status, override.body ?? info.body, provider, model);
|
|
1578
|
+
}
|
|
1438
1579
|
async function pollUntil(check, opts) {
|
|
1439
1580
|
const start = Date.now();
|
|
1440
1581
|
let interval = opts.intervalMs;
|
|
@@ -1557,12 +1698,18 @@ import {
|
|
|
1557
1698
|
streamObject as aiStreamObject2,
|
|
1558
1699
|
streamText as aiStreamText2
|
|
1559
1700
|
} from "ai";
|
|
1560
|
-
import { z as
|
|
1701
|
+
import { z as z4 } from "zod";
|
|
1561
1702
|
|
|
1562
1703
|
// src/adapters/media-ref.ts
|
|
1563
1704
|
function isUrlRef(ref) {
|
|
1564
1705
|
return "url" in ref;
|
|
1565
1706
|
}
|
|
1707
|
+
function abortedError() {
|
|
1708
|
+
return new ModelKitError({ code: "timeout", message: "aborted", retryable: false });
|
|
1709
|
+
}
|
|
1710
|
+
function throwIfAborted(signal) {
|
|
1711
|
+
if (signal?.aborted) throw abortedError();
|
|
1712
|
+
}
|
|
1566
1713
|
function mediaRefToBase64(bytes) {
|
|
1567
1714
|
let binary = "";
|
|
1568
1715
|
const CHUNK = 32768;
|
|
@@ -1577,10 +1724,34 @@ function base64ToBytes(b64) {
|
|
|
1577
1724
|
for (let i = 0; i < binary.length; i++) out[i] = binary.charCodeAt(i);
|
|
1578
1725
|
return out;
|
|
1579
1726
|
}
|
|
1580
|
-
|
|
1727
|
+
function mediaRefToDataUrl(ref) {
|
|
1728
|
+
if (isUrlRef(ref)) return ref.url;
|
|
1729
|
+
return `data:${ref.mime};base64,${mediaRefToBase64(ref.bytes)}`;
|
|
1730
|
+
}
|
|
1731
|
+
var refToUrl = mediaRefToDataUrl;
|
|
1732
|
+
async function readBody(res) {
|
|
1733
|
+
const text2 = await res.text().catch(() => "");
|
|
1734
|
+
try {
|
|
1735
|
+
const decoded = JsonValueSchema.safeParse(JSON.parse(text2));
|
|
1736
|
+
return decoded.success ? decoded.data : text2;
|
|
1737
|
+
} catch {
|
|
1738
|
+
return text2;
|
|
1739
|
+
}
|
|
1740
|
+
}
|
|
1741
|
+
async function mediaRefToBytes(ref, fetch, options = {}) {
|
|
1581
1742
|
if (!isUrlRef(ref)) return { bytes: ref.bytes, mime: ref.mime };
|
|
1582
|
-
const
|
|
1583
|
-
if (
|
|
1743
|
+
const init = {};
|
|
1744
|
+
if (options.signal !== void 0) init.signal = options.signal;
|
|
1745
|
+
const res = await fetch(ref.url, init);
|
|
1746
|
+
if (!res.ok) {
|
|
1747
|
+
const text2 = await res.text().catch(() => "");
|
|
1748
|
+
throw classifyHttpError(
|
|
1749
|
+
res.status,
|
|
1750
|
+
text2,
|
|
1751
|
+
options.provider ?? "media-reference",
|
|
1752
|
+
options.model
|
|
1753
|
+
);
|
|
1754
|
+
}
|
|
1584
1755
|
const mime = res.headers.get("content-type")?.split(";")[0]?.trim().toLowerCase() || "image/png";
|
|
1585
1756
|
return { bytes: new Uint8Array(await res.arrayBuffer()), mime };
|
|
1586
1757
|
}
|
|
@@ -1612,7 +1783,7 @@ import { createPerplexity } from "@ai-sdk/perplexity";
|
|
|
1612
1783
|
import { createXai } from "@ai-sdk/xai";
|
|
1613
1784
|
import { createDeepSeek } from "@ai-sdk/deepseek";
|
|
1614
1785
|
import { createMoonshotAI } from "@ai-sdk/moonshotai";
|
|
1615
|
-
import { z as
|
|
1786
|
+
import { z as z3 } from "zod";
|
|
1616
1787
|
var TEXT_PROVIDERS = [
|
|
1617
1788
|
"openai",
|
|
1618
1789
|
"anthropic",
|
|
@@ -1623,7 +1794,7 @@ var TEXT_PROVIDERS = [
|
|
|
1623
1794
|
"moonshot",
|
|
1624
1795
|
"minimax"
|
|
1625
1796
|
];
|
|
1626
|
-
var textProviderSchema =
|
|
1797
|
+
var textProviderSchema = z3.enum(TEXT_PROVIDERS);
|
|
1627
1798
|
function isTextProvider(value) {
|
|
1628
1799
|
return textProviderSchema.safeParse(value).success;
|
|
1629
1800
|
}
|
|
@@ -1632,22 +1803,12 @@ var OPENAI_COMPATIBLE_BASE_URLS = {
|
|
|
1632
1803
|
};
|
|
1633
1804
|
var GATEWAY_SLUGS = {
|
|
1634
1805
|
openai: "openai",
|
|
1635
|
-
anthropic: "anthropic",
|
|
1806
|
+
anthropic: "anthropic/v1",
|
|
1636
1807
|
google: "google-ai-studio/v1beta",
|
|
1637
|
-
xai: "grok",
|
|
1808
|
+
xai: "grok/v1",
|
|
1638
1809
|
perplexity: "perplexity-ai",
|
|
1639
1810
|
deepseek: "deepseek"
|
|
1640
1811
|
};
|
|
1641
|
-
var OPENROUTER_VENDORS = {
|
|
1642
|
-
openai: "openai",
|
|
1643
|
-
anthropic: "anthropic",
|
|
1644
|
-
google: "google",
|
|
1645
|
-
xai: "x-ai",
|
|
1646
|
-
perplexity: "perplexity",
|
|
1647
|
-
deepseek: "deepseek",
|
|
1648
|
-
moonshot: "moonshotai",
|
|
1649
|
-
minimax: "minimax"
|
|
1650
|
-
};
|
|
1651
1812
|
function detectTextProvider(modelId) {
|
|
1652
1813
|
const id = modelId.toLowerCase();
|
|
1653
1814
|
if (id.startsWith("claude") || id.includes("anthropic.")) return "anthropic";
|
|
@@ -1664,14 +1825,17 @@ function detectTextProvider(modelId) {
|
|
|
1664
1825
|
message: `ai-sdk-text cannot detect a provider for "${modelId}". Set providerOptions.provider to one of ${TEXT_PROVIDERS.join(", ")}.`
|
|
1665
1826
|
});
|
|
1666
1827
|
}
|
|
1667
|
-
function textKeyName(model,
|
|
1668
|
-
if (routing.text === "openrouter") return "openrouter";
|
|
1828
|
+
function textKeyName(model, _routing) {
|
|
1669
1829
|
return textProviderOf(model);
|
|
1670
1830
|
}
|
|
1671
1831
|
function textProviderOf(model) {
|
|
1672
1832
|
const explicit = model.providerOptions?.["modelkit"]?.["provider"];
|
|
1673
1833
|
return isTextProvider(explicit) ? explicit : detectTextProvider(model.providerModelId);
|
|
1674
1834
|
}
|
|
1835
|
+
function textUsesCloudflareGateway(model, routing) {
|
|
1836
|
+
if (routing.text !== "cloudflare") return false;
|
|
1837
|
+
return GATEWAY_SLUGS[textProviderOf(model)] !== void 0;
|
|
1838
|
+
}
|
|
1675
1839
|
function nativeClientFor(provider) {
|
|
1676
1840
|
switch (provider) {
|
|
1677
1841
|
case "openai":
|
|
@@ -1704,16 +1868,6 @@ function resolveTextRoute(ctx) {
|
|
|
1704
1868
|
retryable: false
|
|
1705
1869
|
});
|
|
1706
1870
|
}
|
|
1707
|
-
if (mode === "openrouter") {
|
|
1708
|
-
const modelId = ctx.model.providerModelId.includes("/") ? ctx.model.providerModelId : `${OPENROUTER_VENDORS[provider]}/${ctx.model.providerModelId}`;
|
|
1709
|
-
return {
|
|
1710
|
-
provider,
|
|
1711
|
-
client: "openai-compatible",
|
|
1712
|
-
modelId,
|
|
1713
|
-
keyName: "openrouter",
|
|
1714
|
-
baseURL: "https://openrouter.ai/api/v1"
|
|
1715
|
-
};
|
|
1716
|
-
}
|
|
1717
1871
|
const compatBase = OPENAI_COMPATIBLE_BASE_URLS[provider];
|
|
1718
1872
|
const route2 = {
|
|
1719
1873
|
provider,
|
|
@@ -1781,7 +1935,7 @@ var aiSdkTextAdapter = {
|
|
|
1781
1935
|
case "openai-compatible":
|
|
1782
1936
|
return createOpenAI({
|
|
1783
1937
|
...settings,
|
|
1784
|
-
name: route2.provider
|
|
1938
|
+
name: route2.provider
|
|
1785
1939
|
}).chat(route2.modelId);
|
|
1786
1940
|
case "openai":
|
|
1787
1941
|
return createOpenAI(settings)(route2.modelId);
|
|
@@ -1794,8 +1948,9 @@ function requiredKeys(model, config) {
|
|
|
1794
1948
|
if (model.adapter === "fal" && config.routing?.fal === "cloudflare-passthrough")
|
|
1795
1949
|
return ["cloudflare"];
|
|
1796
1950
|
if (model.adapter === "ai-sdk-text") {
|
|
1797
|
-
const
|
|
1798
|
-
|
|
1951
|
+
const routing = config.routing ?? {};
|
|
1952
|
+
const names = [textKeyName(model, routing)];
|
|
1953
|
+
if (textUsesCloudflareGateway(model, routing)) names.push("cloudflare");
|
|
1799
1954
|
return names;
|
|
1800
1955
|
}
|
|
1801
1956
|
return ADAPTER_KEYS[model.adapter];
|
|
@@ -1809,10 +1964,10 @@ function textAbortOptions(sdk, context) {
|
|
|
1809
1964
|
if (abortSignal) return { abortSignal };
|
|
1810
1965
|
return {};
|
|
1811
1966
|
}
|
|
1812
|
-
var catalogId =
|
|
1813
|
-
var exactSize =
|
|
1814
|
-
var sdkRatio =
|
|
1815
|
-
var sizeTier =
|
|
1967
|
+
var catalogId = z4.string();
|
|
1968
|
+
var exactSize = z4.templateLiteral([z4.number(), "x", z4.number()]);
|
|
1969
|
+
var sdkRatio = z4.templateLiteral([z4.number(), ":", z4.number()]);
|
|
1970
|
+
var sizeTier = z4.enum(["512", "1K", "2K", "4K"]);
|
|
1816
1971
|
function isCatalogId(model) {
|
|
1817
1972
|
return catalogId.safeParse(model).success;
|
|
1818
1973
|
}
|
|
@@ -1869,6 +2024,15 @@ function pushIgnored(warnings, field, from, modelId) {
|
|
|
1869
2024
|
message: `${modelId} provider instance does not support ${field}; ignored`
|
|
1870
2025
|
});
|
|
1871
2026
|
}
|
|
2027
|
+
function withoutModelkit(options) {
|
|
2028
|
+
if (!options) return {};
|
|
2029
|
+
const { modelkit: _modelkit, ...rest } = options;
|
|
2030
|
+
return rest;
|
|
2031
|
+
}
|
|
2032
|
+
function logCoercions(logger, modelId, warnings) {
|
|
2033
|
+
if (warnings.length === 0) return;
|
|
2034
|
+
logger.warn(`[modelkit] ${modelId} request coerced`, { model: modelId, warnings });
|
|
2035
|
+
}
|
|
1872
2036
|
function createModelKit(config, adapters) {
|
|
1873
2037
|
const catalog = new Catalog(MODELS).withOverrides(config.catalogOverride ?? []);
|
|
1874
2038
|
const logger = config.logger ?? console;
|
|
@@ -1881,7 +2045,16 @@ function createModelKit(config, adapters) {
|
|
|
1881
2045
|
message: `No adapter registered for ${model.adapter}`,
|
|
1882
2046
|
model: model.id
|
|
1883
2047
|
});
|
|
1884
|
-
const
|
|
2048
|
+
const names = requiredKeys(model, config);
|
|
2049
|
+
if (call.tier === "enterprise") {
|
|
2050
|
+
const missing = missingEnterpriseKeys(config, names);
|
|
2051
|
+
if (missing.length > 0)
|
|
2052
|
+
logger.warn(
|
|
2053
|
+
`[modelkit] enterprise keys incomplete for ${model.adapter}; using pro`,
|
|
2054
|
+
{ missing }
|
|
2055
|
+
);
|
|
2056
|
+
}
|
|
2057
|
+
const keys = resolveKeys(config, names, call.tier);
|
|
1885
2058
|
const ctx = {
|
|
1886
2059
|
model,
|
|
1887
2060
|
keys,
|
|
@@ -1902,6 +2075,10 @@ function createModelKit(config, adapters) {
|
|
|
1902
2075
|
logger.warn("[modelkit] usage emit failed", err);
|
|
1903
2076
|
}
|
|
1904
2077
|
}
|
|
2078
|
+
function withRowUnit(event) {
|
|
2079
|
+
const row = catalog.get(event.model);
|
|
2080
|
+
return row ? { ...event, unit: row.usage.unit } : event;
|
|
2081
|
+
}
|
|
1905
2082
|
function textTarget(model, call) {
|
|
1906
2083
|
if (!isCatalogId(model)) {
|
|
1907
2084
|
return {
|
|
@@ -1970,6 +2147,7 @@ function createModelKit(config, adapters) {
|
|
|
1970
2147
|
pushIgnored(warnings, "outputFormat", _outputFormat, model.modelId);
|
|
1971
2148
|
if (scaleFactor !== void 0)
|
|
1972
2149
|
pushIgnored(warnings, "scaleFactor", scaleFactor, model.modelId);
|
|
2150
|
+
logCoercions(logger, model.modelId, warnings);
|
|
1973
2151
|
const abortSignal = combineSignals(req.abortSignal, call.signal);
|
|
1974
2152
|
if (abortSignal) options.abortSignal = abortSignal;
|
|
1975
2153
|
const result = await aiGenerateImage(options);
|
|
@@ -2053,6 +2231,7 @@ function createModelKit(config, adapters) {
|
|
|
2053
2231
|
if (_mode !== void 0) pushIgnored(warnings, "mode", _mode, model.modelId);
|
|
2054
2232
|
if (providerOptions) options.providerOptions = providerOptions;
|
|
2055
2233
|
if (abortSignal) options.abortSignal = abortSignal;
|
|
2234
|
+
logCoercions(logger, model.modelId, warnings);
|
|
2056
2235
|
const pending = aiGenerateVideo(options);
|
|
2057
2236
|
let settled;
|
|
2058
2237
|
let failed = false;
|
|
@@ -2111,6 +2290,7 @@ function createModelKit(config, adapters) {
|
|
|
2111
2290
|
call.onUnsupported ?? "error"
|
|
2112
2291
|
);
|
|
2113
2292
|
warnings.push(...inputWarnings);
|
|
2293
|
+
logCoercions(logger, model.id, warnings);
|
|
2114
2294
|
const signal = combineSignals(req.abortSignal, call.signal);
|
|
2115
2295
|
const { adapter, ctx } = context(model, signal ? { ...call, signal } : call, warnings);
|
|
2116
2296
|
if (!adapter.generateImage)
|
|
@@ -2120,7 +2300,7 @@ function createModelKit(config, adapters) {
|
|
|
2120
2300
|
model: model.id
|
|
2121
2301
|
});
|
|
2122
2302
|
const result = await adapter.generateImage(request, ctx);
|
|
2123
|
-
const usage2 = { ...result.usage, model: model.id };
|
|
2303
|
+
const usage2 = { ...result.usage, model: model.id, unit: model.usage.unit };
|
|
2124
2304
|
await emit(usage2);
|
|
2125
2305
|
const images = result.images.map(toGeneratedImage);
|
|
2126
2306
|
const first = images[0];
|
|
@@ -2153,6 +2333,7 @@ function createModelKit(config, adapters) {
|
|
|
2153
2333
|
call.onUnsupported ?? "error"
|
|
2154
2334
|
);
|
|
2155
2335
|
warnings.push(...inputWarnings);
|
|
2336
|
+
logCoercions(logger, model.id, warnings);
|
|
2156
2337
|
const signal = combineSignals(req.abortSignal, call.signal);
|
|
2157
2338
|
const { adapter, ctx } = context(model, signal ? { ...call, signal } : call, warnings);
|
|
2158
2339
|
if (!adapter.generateVideo)
|
|
@@ -2170,7 +2351,11 @@ function createModelKit(config, adapters) {
|
|
|
2170
2351
|
result(opts) {
|
|
2171
2352
|
if (settled) return settled;
|
|
2172
2353
|
const pending = result(opts).then(
|
|
2173
|
-
(out) => emit({
|
|
2354
|
+
(out) => emit({
|
|
2355
|
+
...out.usage,
|
|
2356
|
+
model: model.id,
|
|
2357
|
+
unit: model.usage.unit
|
|
2358
|
+
}).then(() => out),
|
|
2174
2359
|
(cause) => {
|
|
2175
2360
|
settled = void 0;
|
|
2176
2361
|
throw cause;
|
|
@@ -2190,7 +2375,15 @@ function createModelKit(config, adapters) {
|
|
|
2190
2375
|
model: model.id
|
|
2191
2376
|
});
|
|
2192
2377
|
}
|
|
2193
|
-
const {
|
|
2378
|
+
const { abortSignal: _signal, ...request } = req;
|
|
2379
|
+
const { request: resolved, warnings } = resolveAudioOptions(
|
|
2380
|
+
model,
|
|
2381
|
+
request,
|
|
2382
|
+
call.onUnsupported ?? "error"
|
|
2383
|
+
);
|
|
2384
|
+
logCoercions(logger, model.id, warnings);
|
|
2385
|
+
const signal = combineSignals(req.abortSignal, call.signal);
|
|
2386
|
+
const { adapter, ctx } = context(model, signal ? { ...call, signal } : call, warnings);
|
|
2194
2387
|
if (!adapter.generateAudio) {
|
|
2195
2388
|
throw new ModelKitError({
|
|
2196
2389
|
code: "unsupported_option",
|
|
@@ -2198,11 +2391,8 @@ function createModelKit(config, adapters) {
|
|
|
2198
2391
|
model: model.id
|
|
2199
2392
|
});
|
|
2200
2393
|
}
|
|
2201
|
-
const result = await adapter.generateAudio(
|
|
2202
|
-
|
|
2203
|
-
ctx
|
|
2204
|
-
);
|
|
2205
|
-
await emit({ ...result.usage, model: model.id });
|
|
2394
|
+
const result = await adapter.generateAudio(resolved, ctx);
|
|
2395
|
+
await emit({ ...result.usage, model: model.id, unit: model.usage.unit });
|
|
2206
2396
|
return result;
|
|
2207
2397
|
},
|
|
2208
2398
|
async prepareMediaPart(modelId, ref, mediaType, call = {}) {
|
|
@@ -2222,7 +2412,7 @@ function createModelKit(config, adapters) {
|
|
|
2222
2412
|
});
|
|
2223
2413
|
return {
|
|
2224
2414
|
model,
|
|
2225
|
-
providerOptions: entry.providerOptions
|
|
2415
|
+
providerOptions: withoutModelkit(entry.providerOptions),
|
|
2226
2416
|
catalog: entry
|
|
2227
2417
|
};
|
|
2228
2418
|
},
|
|
@@ -2242,7 +2432,7 @@ function createModelKit(config, adapters) {
|
|
|
2242
2432
|
options.prepareStep ?? options.experimental_prepareStep
|
|
2243
2433
|
)
|
|
2244
2434
|
});
|
|
2245
|
-
for (const event of steps.usage(result.steps)) await emit(event);
|
|
2435
|
+
for (const event of steps.usage(result.steps)) await emit(withRowUnit(event));
|
|
2246
2436
|
return result;
|
|
2247
2437
|
},
|
|
2248
2438
|
streamText(options, call = {}) {
|
|
@@ -2258,9 +2448,11 @@ function createModelKit(config, adapters) {
|
|
|
2258
2448
|
...textAbortOptions(options.abortSignal, call.signal),
|
|
2259
2449
|
model: target.languageModel,
|
|
2260
2450
|
providerOptions: {},
|
|
2261
|
-
prepareStep: steps.wrap(
|
|
2451
|
+
prepareStep: steps.wrap(
|
|
2452
|
+
options.prepareStep ?? options.experimental_prepareStep
|
|
2453
|
+
),
|
|
2262
2454
|
onFinish: async (event) => {
|
|
2263
|
-
for (const usage2 of steps.usage(event.steps)) await emit(usage2);
|
|
2455
|
+
for (const usage2 of steps.usage(event.steps)) await emit(withRowUnit(usage2));
|
|
2264
2456
|
await callerOnFinish?.(event);
|
|
2265
2457
|
}
|
|
2266
2458
|
});
|
|
@@ -2274,7 +2466,7 @@ function createModelKit(config, adapters) {
|
|
|
2274
2466
|
providerOptions: mergeTextProviderOptions(entry, options.providerOptions)
|
|
2275
2467
|
};
|
|
2276
2468
|
const result = await aiGenerateObject2(sdkOptions);
|
|
2277
|
-
await emit(textUsageEvent(entry, provider, result.usage));
|
|
2469
|
+
await emit(withRowUnit(textUsageEvent(entry, provider, result.usage)));
|
|
2278
2470
|
return result;
|
|
2279
2471
|
},
|
|
2280
2472
|
streamObject(options, call = {}) {
|
|
@@ -2286,7 +2478,7 @@ function createModelKit(config, adapters) {
|
|
|
2286
2478
|
model: languageModel2,
|
|
2287
2479
|
providerOptions: mergeTextProviderOptions(entry, options.providerOptions),
|
|
2288
2480
|
onFinish: async (event) => {
|
|
2289
|
-
await emit(textUsageEvent(entry, provider, event.usage));
|
|
2481
|
+
await emit(withRowUnit(textUsageEvent(entry, provider, event.usage)));
|
|
2290
2482
|
await callerOnFinish?.(event);
|
|
2291
2483
|
}
|
|
2292
2484
|
};
|
|
@@ -2296,7 +2488,7 @@ function createModelKit(config, adapters) {
|
|
|
2296
2488
|
}
|
|
2297
2489
|
|
|
2298
2490
|
// src/adapters/ark.ts
|
|
2299
|
-
import { z as
|
|
2491
|
+
import { z as z5 } from "zod";
|
|
2300
2492
|
var ARK_BASE_URL = "https://ark.ap-southeast.bytepluses.com/api/v3";
|
|
2301
2493
|
var SUBMIT_PATH = "/contents/generations/tasks";
|
|
2302
2494
|
var SEEDANCE_POLL_INTERVAL_MS = 15e3;
|
|
@@ -2315,6 +2507,7 @@ var SEEDREAM_SIZES = {
|
|
|
2315
2507
|
"3:2": "1248x832",
|
|
2316
2508
|
"2:3": "832x1248",
|
|
2317
2509
|
"21:9": "1568x672",
|
|
2510
|
+
"9:21": "672x1568",
|
|
2318
2511
|
"4:5": "864x1080",
|
|
2319
2512
|
"5:4": "1080x864"
|
|
2320
2513
|
},
|
|
@@ -2327,16 +2520,34 @@ var SEEDREAM_SIZES = {
|
|
|
2327
2520
|
"3:2": "2496x1664",
|
|
2328
2521
|
"2:3": "1664x2496",
|
|
2329
2522
|
"21:9": "3136x1344",
|
|
2523
|
+
"9:21": "1344x3136",
|
|
2330
2524
|
"4:5": "1728x2160",
|
|
2331
2525
|
"5:4": "2160x1728"
|
|
2526
|
+
},
|
|
2527
|
+
// 4K keeps the long edge at Ark's 4096 cap (a doubled 2K entry would exceed
|
|
2528
|
+
// it); sides are multiples of 16.
|
|
2529
|
+
"4K": {
|
|
2530
|
+
"1:1": "4096x4096",
|
|
2531
|
+
"4:3": "4096x3072",
|
|
2532
|
+
"3:4": "3072x4096",
|
|
2533
|
+
"16:9": "4096x2304",
|
|
2534
|
+
"9:16": "2304x4096",
|
|
2535
|
+
"3:2": "4096x2736",
|
|
2536
|
+
"2:3": "2736x4096",
|
|
2537
|
+
"21:9": "4096x1760",
|
|
2538
|
+
"9:21": "1760x4096",
|
|
2539
|
+
"4:5": "3280x4096",
|
|
2540
|
+
"5:4": "4096x3280"
|
|
2332
2541
|
}
|
|
2333
2542
|
};
|
|
2334
2543
|
var arkAdapter = {
|
|
2335
2544
|
id: "ark",
|
|
2336
2545
|
async generateImage(req, ctx) {
|
|
2546
|
+
throwIfAborted(ctx.signal);
|
|
2337
2547
|
return generateSeedreamImage(req, ctx);
|
|
2338
2548
|
},
|
|
2339
2549
|
async generateVideo(req, ctx) {
|
|
2550
|
+
throwIfAborted(ctx.signal);
|
|
2340
2551
|
return generateSeedanceVideo(req, ctx);
|
|
2341
2552
|
}
|
|
2342
2553
|
};
|
|
@@ -2354,9 +2565,9 @@ function arkKey(ctx) {
|
|
|
2354
2565
|
return key;
|
|
2355
2566
|
}
|
|
2356
2567
|
function throwArkError(status, body, model) {
|
|
2357
|
-
const parsed =
|
|
2568
|
+
const parsed = z5.string().safeParse(body);
|
|
2358
2569
|
const text2 = parsed.success ? parsed.data : JSON.stringify(body ?? "");
|
|
2359
|
-
if (/sensitive.?content|
|
|
2570
|
+
if (/sensitive.?content|human.?face/i.test(text2)) {
|
|
2360
2571
|
const init = {
|
|
2361
2572
|
code: "content_blocked",
|
|
2362
2573
|
message: `ark rejected the request: ${text2.slice(0, 500)}`,
|
|
@@ -2368,10 +2579,20 @@ function throwArkError(status, body, model) {
|
|
|
2368
2579
|
if (status !== void 0) init.status = status;
|
|
2369
2580
|
throw new ModelKitError(init);
|
|
2370
2581
|
}
|
|
2582
|
+
if (status === void 0) {
|
|
2583
|
+
throw new ModelKitError({
|
|
2584
|
+
code: "provider_rejected",
|
|
2585
|
+
message: `ark rejected the request: ${text2.slice(0, 500)}`,
|
|
2586
|
+
provider: "ark",
|
|
2587
|
+
model,
|
|
2588
|
+
body,
|
|
2589
|
+
retryable: false
|
|
2590
|
+
});
|
|
2591
|
+
}
|
|
2371
2592
|
throw classifyHttpError(status, body, "ark", model);
|
|
2372
2593
|
}
|
|
2373
2594
|
function seedreamSize(aspect, size) {
|
|
2374
|
-
const tier = size === "
|
|
2595
|
+
const tier = size === "4K" || size === "1K" ? size : "2K";
|
|
2375
2596
|
const table = SEEDREAM_SIZES[tier];
|
|
2376
2597
|
return table[aspect ?? ""] ?? table["1:1"] ?? "2048x2048";
|
|
2377
2598
|
}
|
|
@@ -2382,17 +2603,13 @@ function sniffedImageMime(bytes) {
|
|
|
2382
2603
|
return "image/webp";
|
|
2383
2604
|
return "image/jpeg";
|
|
2384
2605
|
}
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
}
|
|
2389
|
-
var SeedreamImageSchema = z4.object({
|
|
2390
|
-
url: z4.string().optional(),
|
|
2391
|
-
b64_json: z4.string().optional()
|
|
2606
|
+
var SeedreamImageSchema = z5.object({
|
|
2607
|
+
url: z5.string().optional(),
|
|
2608
|
+
b64_json: z5.string().optional()
|
|
2392
2609
|
});
|
|
2393
|
-
var SeedreamResponseSchema =
|
|
2394
|
-
data:
|
|
2395
|
-
error:
|
|
2610
|
+
var SeedreamResponseSchema = z5.object({
|
|
2611
|
+
data: z5.array(SeedreamImageSchema).optional(),
|
|
2612
|
+
error: z5.object({ message: z5.string().optional(), code: z5.string().optional() }).optional()
|
|
2396
2613
|
});
|
|
2397
2614
|
function retryOptsFor(ctx, attempts = 3) {
|
|
2398
2615
|
const opts = { attempts };
|
|
@@ -2403,11 +2620,16 @@ function fetchInitFor(ctx, init) {
|
|
|
2403
2620
|
if (ctx.signal !== void 0) init.signal = ctx.signal;
|
|
2404
2621
|
return init;
|
|
2405
2622
|
}
|
|
2623
|
+
function arkFetch(ctx, url, init) {
|
|
2624
|
+
return ctx.fetch(url, fetchInitFor(ctx, init)).catch((cause) => {
|
|
2625
|
+
throw classifyThrown("ark", cause, ctx.model.id);
|
|
2626
|
+
});
|
|
2627
|
+
}
|
|
2406
2628
|
async function generateSeedreamImage(req, ctx) {
|
|
2407
2629
|
const key = arkKey(ctx);
|
|
2408
2630
|
const modelId = ctx.model.id;
|
|
2409
2631
|
const size = seedreamSize(req.aspectRatio, req.size);
|
|
2410
|
-
const refs = (req.references ?? []).map(
|
|
2632
|
+
const refs = (req.references ?? []).map(refToUrl);
|
|
2411
2633
|
const body = {
|
|
2412
2634
|
model: ctx.model.providerModelId,
|
|
2413
2635
|
prompt: req.prompt,
|
|
@@ -2420,14 +2642,11 @@ async function generateSeedreamImage(req, ctx) {
|
|
|
2420
2642
|
if (refs.length === 1 && firstRef !== void 0) body.image = firstRef;
|
|
2421
2643
|
else if (refs.length > 1) body.image = refs;
|
|
2422
2644
|
const data = await withRetry(async () => {
|
|
2423
|
-
const res = await ctx
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
body: JSON.stringify(body)
|
|
2429
|
-
})
|
|
2430
|
-
);
|
|
2645
|
+
const res = await arkFetch(ctx, `${arkBaseUrl(ctx)}/images/generations`, {
|
|
2646
|
+
method: "POST",
|
|
2647
|
+
headers: { Authorization: `Bearer ${key}`, "Content-Type": "application/json" },
|
|
2648
|
+
body: JSON.stringify(body)
|
|
2649
|
+
});
|
|
2431
2650
|
if (!res.ok) {
|
|
2432
2651
|
const text2 = await res.text().catch(() => "");
|
|
2433
2652
|
throwArkError(res.status, text2, modelId);
|
|
@@ -2442,7 +2661,7 @@ async function generateSeedreamImage(req, ctx) {
|
|
|
2442
2661
|
bytes = Buffer.from(first.b64_json, "base64");
|
|
2443
2662
|
} else if (first?.url) {
|
|
2444
2663
|
const imageUrl = first.url;
|
|
2445
|
-
const res = await ctx
|
|
2664
|
+
const res = await arkFetch(ctx, imageUrl, {});
|
|
2446
2665
|
if (!res.ok) {
|
|
2447
2666
|
const text2 = await res.text().catch(() => "");
|
|
2448
2667
|
throwArkError(res.status, text2, modelId);
|
|
@@ -2462,13 +2681,21 @@ async function generateSeedreamImage(req, ctx) {
|
|
|
2462
2681
|
if (req.quality !== void 0) usage2.imageQuality = req.quality;
|
|
2463
2682
|
return { images: [{ bytes, mime: sniffedImageMime(bytes) }], usage: usage2, raw: data };
|
|
2464
2683
|
}
|
|
2465
|
-
var
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
content: z4.object({ video_url: z4.string().optional() }).optional(),
|
|
2469
|
-
error: z4.union([z4.string(), z4.object({ message: z4.string().optional() })]).optional()
|
|
2684
|
+
var SeedanceUsageSchema = z5.object({
|
|
2685
|
+
total_tokens: z5.number().optional(),
|
|
2686
|
+
completion_tokens: z5.number().optional()
|
|
2470
2687
|
});
|
|
2471
|
-
var
|
|
2688
|
+
var SeedanceResponseSchema = z5.object({
|
|
2689
|
+
id: z5.string().optional(),
|
|
2690
|
+
status: z5.string().optional(),
|
|
2691
|
+
content: z5.object({ video_url: z5.string().optional() }).optional(),
|
|
2692
|
+
usage: SeedanceUsageSchema.optional(),
|
|
2693
|
+
duration: z5.number().optional(),
|
|
2694
|
+
framespersecond: z5.number().optional(),
|
|
2695
|
+
resolution: z5.string().optional(),
|
|
2696
|
+
error: z5.union([z5.string(), z5.object({ message: z5.string().optional() })]).optional()
|
|
2697
|
+
});
|
|
2698
|
+
var SeedanceErrorMessageSchema = z5.object({ message: z5.string().optional() });
|
|
2472
2699
|
function seedanceUsage(ctx, req, duration) {
|
|
2473
2700
|
const usage2 = {
|
|
2474
2701
|
model: ctx.model.id,
|
|
@@ -2482,7 +2709,7 @@ function seedanceUsage(ctx, req, duration) {
|
|
|
2482
2709
|
return usage2;
|
|
2483
2710
|
}
|
|
2484
2711
|
function seedanceErrorMessage(error, status) {
|
|
2485
|
-
const asString =
|
|
2712
|
+
const asString = z5.string().safeParse(error);
|
|
2486
2713
|
if (asString.success) return asString.data;
|
|
2487
2714
|
const asObject = SeedanceErrorMessageSchema.safeParse(error);
|
|
2488
2715
|
if (asObject.success && asObject.data.message !== void 0) return asObject.data.message;
|
|
@@ -2497,42 +2724,42 @@ async function generateSeedanceVideo(req, ctx) {
|
|
|
2497
2724
|
if (req.firstFrame) {
|
|
2498
2725
|
content.push({
|
|
2499
2726
|
type: "image_url",
|
|
2500
|
-
image_url: { url:
|
|
2727
|
+
image_url: { url: refToUrl(req.firstFrame) },
|
|
2501
2728
|
role: "first_frame"
|
|
2502
2729
|
});
|
|
2503
2730
|
}
|
|
2504
2731
|
if (req.lastFrame) {
|
|
2505
2732
|
content.push({
|
|
2506
2733
|
type: "image_url",
|
|
2507
|
-
image_url: { url:
|
|
2734
|
+
image_url: { url: refToUrl(req.lastFrame) },
|
|
2508
2735
|
role: "last_frame"
|
|
2509
2736
|
});
|
|
2510
2737
|
}
|
|
2511
2738
|
for (const ref of req.referenceImages ?? []) {
|
|
2512
2739
|
content.push({
|
|
2513
2740
|
type: "image_url",
|
|
2514
|
-
image_url: { url:
|
|
2741
|
+
image_url: { url: refToUrl(ref) },
|
|
2515
2742
|
role: "reference_image"
|
|
2516
2743
|
});
|
|
2517
2744
|
}
|
|
2518
2745
|
if (req.sourceVideo) {
|
|
2519
2746
|
content.push({
|
|
2520
2747
|
type: "video_url",
|
|
2521
|
-
video_url: { url:
|
|
2748
|
+
video_url: { url: refToUrl(req.sourceVideo) },
|
|
2522
2749
|
role: "reference_video"
|
|
2523
2750
|
});
|
|
2524
2751
|
}
|
|
2525
2752
|
for (const ref of req.referenceVideos ?? []) {
|
|
2526
2753
|
content.push({
|
|
2527
2754
|
type: "video_url",
|
|
2528
|
-
video_url: { url:
|
|
2755
|
+
video_url: { url: refToUrl(ref) },
|
|
2529
2756
|
role: "reference_video"
|
|
2530
2757
|
});
|
|
2531
2758
|
}
|
|
2532
2759
|
for (const ref of req.referenceAudios ?? []) {
|
|
2533
2760
|
content.push({
|
|
2534
2761
|
type: "audio_url",
|
|
2535
|
-
audio_url: { url:
|
|
2762
|
+
audio_url: { url: refToUrl(ref) },
|
|
2536
2763
|
role: "reference_audio"
|
|
2537
2764
|
});
|
|
2538
2765
|
}
|
|
@@ -2546,15 +2773,13 @@ async function generateSeedanceVideo(req, ctx) {
|
|
|
2546
2773
|
if (!hasFrameAnchor && req.aspectRatio !== void 0) body.ratio = req.aspectRatio;
|
|
2547
2774
|
if (req.generateAudio !== void 0) body.generate_audio = req.generateAudio;
|
|
2548
2775
|
if (req.seed !== void 0) body.seed = req.seed;
|
|
2776
|
+
if (req.watermark !== void 0) body.watermark = req.watermark;
|
|
2549
2777
|
const submit = await withRetry(async () => {
|
|
2550
|
-
const res = await ctx
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
body: JSON.stringify(body)
|
|
2556
|
-
})
|
|
2557
|
-
);
|
|
2778
|
+
const res = await arkFetch(ctx, `${arkBaseUrl(ctx)}${SUBMIT_PATH}`, {
|
|
2779
|
+
method: "POST",
|
|
2780
|
+
headers: { Authorization: `Bearer ${key}`, "Content-Type": "application/json" },
|
|
2781
|
+
body: JSON.stringify(body)
|
|
2782
|
+
});
|
|
2558
2783
|
if (!res.ok) {
|
|
2559
2784
|
const text2 = await res.text().catch(() => "");
|
|
2560
2785
|
throwArkError(res.status, text2, modelId);
|
|
@@ -2567,12 +2792,9 @@ async function generateSeedanceVideo(req, ctx) {
|
|
|
2567
2792
|
const jobId = submit.id;
|
|
2568
2793
|
const usage2 = seedanceUsage(ctx, req, duration);
|
|
2569
2794
|
const fetchStatus = async () => {
|
|
2570
|
-
const res = await ctx
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
headers: { Authorization: `Bearer ${key}` }
|
|
2574
|
-
})
|
|
2575
|
-
);
|
|
2795
|
+
const res = await arkFetch(ctx, `${arkBaseUrl(ctx)}${SUBMIT_PATH}/${jobId}`, {
|
|
2796
|
+
headers: { Authorization: `Bearer ${key}` }
|
|
2797
|
+
});
|
|
2576
2798
|
if (!res.ok) {
|
|
2577
2799
|
if (res.status === 429 || res.status >= 500) return void 0;
|
|
2578
2800
|
const text2 = await res.text().catch(() => "");
|
|
@@ -2615,6 +2837,11 @@ async function generateSeedanceVideo(req, ctx) {
|
|
|
2615
2837
|
"Seedance task succeeded but returned no video_url",
|
|
2616
2838
|
modelId
|
|
2617
2839
|
);
|
|
2840
|
+
const tokens = polled.usage;
|
|
2841
|
+
if (tokens?.total_tokens !== void 0 && tokens.completion_tokens !== void 0) {
|
|
2842
|
+
usage2.inputTokens = tokens.total_tokens - tokens.completion_tokens;
|
|
2843
|
+
usage2.outputTokens = tokens.completion_tokens;
|
|
2844
|
+
}
|
|
2618
2845
|
return {
|
|
2619
2846
|
video: { url, expiresAt: new Date(Date.now() + VIDEO_URL_TTL_MS) },
|
|
2620
2847
|
usage: usage2,
|
|
@@ -2633,43 +2860,6 @@ async function generateSeedanceVideo(req, ctx) {
|
|
|
2633
2860
|
// src/adapters/fal.ts
|
|
2634
2861
|
import { z as z6 } from "zod";
|
|
2635
2862
|
import { createFalClient } from "@fal-ai/client";
|
|
2636
|
-
|
|
2637
|
-
// src/json.ts
|
|
2638
|
-
import { z as z5 } from "zod";
|
|
2639
|
-
var JsonValueSchema = z5.lazy(
|
|
2640
|
-
() => z5.union([
|
|
2641
|
-
z5.string(),
|
|
2642
|
-
z5.number(),
|
|
2643
|
-
z5.boolean(),
|
|
2644
|
-
z5.null(),
|
|
2645
|
-
z5.array(JsonValueSchema),
|
|
2646
|
-
z5.record(z5.string(), JsonValueSchema)
|
|
2647
|
-
])
|
|
2648
|
-
);
|
|
2649
|
-
var JsonObjectSchema = z5.record(z5.string(), JsonValueSchema);
|
|
2650
|
-
async function readErrorBody(res) {
|
|
2651
|
-
const text2 = await res.text().catch(() => "");
|
|
2652
|
-
try {
|
|
2653
|
-
return JsonValueSchema.parse(JSON.parse(text2));
|
|
2654
|
-
} catch {
|
|
2655
|
-
return text2;
|
|
2656
|
-
}
|
|
2657
|
-
}
|
|
2658
|
-
var thrownErrorSchema = z5.object({
|
|
2659
|
-
message: z5.string().optional(),
|
|
2660
|
-
status: z5.number().optional(),
|
|
2661
|
-
statusCode: z5.number().optional(),
|
|
2662
|
-
responseBody: z5.string().optional()
|
|
2663
|
-
});
|
|
2664
|
-
function describeThrown(cause) {
|
|
2665
|
-
const parsed = thrownErrorSchema.safeParse(cause);
|
|
2666
|
-
if (!parsed.success) return { message: String(cause), status: void 0, body: String(cause) };
|
|
2667
|
-
const { message, status, statusCode, responseBody } = parsed.data;
|
|
2668
|
-
const body = responseBody ?? message ?? String(cause);
|
|
2669
|
-
return { message: message ?? String(cause), status: status ?? statusCode, body };
|
|
2670
|
-
}
|
|
2671
|
-
|
|
2672
|
-
// src/adapters/fal.ts
|
|
2673
2863
|
var MUSE_T2I_ENDPOINT = "meta/muse-image/text-to-image";
|
|
2674
2864
|
var MUSE_EDIT_ENDPOINT = "meta/muse-image/edit";
|
|
2675
2865
|
var KLING_O1_ENDPOINT = "fal-ai/kling-video/o1/video-to-video/reference";
|
|
@@ -2681,10 +2871,33 @@ function defaultCreateFalClient(opts) {
|
|
|
2681
2871
|
const client2 = createFalClient(opts);
|
|
2682
2872
|
return {
|
|
2683
2873
|
async subscribe(endpoint, options) {
|
|
2684
|
-
const outcome = await client2.subscribe(endpoint,
|
|
2874
|
+
const outcome = await client2.subscribe(endpoint, options);
|
|
2685
2875
|
const unwrapped = falSubscribePayloadSchema.safeParse(outcome);
|
|
2686
2876
|
if (unwrapped.success) return unwrapped.data.data;
|
|
2687
2877
|
return JsonValueSchema.parse(outcome);
|
|
2878
|
+
},
|
|
2879
|
+
queue: {
|
|
2880
|
+
async submit(endpoint, options) {
|
|
2881
|
+
const submitted = await client2.queue.submit(endpoint, {
|
|
2882
|
+
input: options.input,
|
|
2883
|
+
...options.abortSignal !== void 0 ? { abortSignal: options.abortSignal } : {}
|
|
2884
|
+
});
|
|
2885
|
+
return { requestId: submitted.request_id };
|
|
2886
|
+
},
|
|
2887
|
+
async status(endpoint, options) {
|
|
2888
|
+
const current = await client2.queue.status(endpoint, {
|
|
2889
|
+
requestId: options.requestId,
|
|
2890
|
+
...options.abortSignal !== void 0 ? { abortSignal: options.abortSignal } : {}
|
|
2891
|
+
});
|
|
2892
|
+
return { status: current.status };
|
|
2893
|
+
},
|
|
2894
|
+
async result(endpoint, options) {
|
|
2895
|
+
const outcome = await client2.queue.result(endpoint, {
|
|
2896
|
+
requestId: options.requestId,
|
|
2897
|
+
...options.abortSignal !== void 0 ? { abortSignal: options.abortSignal } : {}
|
|
2898
|
+
});
|
|
2899
|
+
return JsonValueSchema.parse(outcome.data);
|
|
2900
|
+
}
|
|
2688
2901
|
}
|
|
2689
2902
|
};
|
|
2690
2903
|
}
|
|
@@ -2692,24 +2905,17 @@ var defaultDeps = { createFalClient: defaultCreateFalClient };
|
|
|
2692
2905
|
function createFalAdapter(deps = defaultDeps) {
|
|
2693
2906
|
return {
|
|
2694
2907
|
id: "fal",
|
|
2695
|
-
generateImage: (req, ctx) =>
|
|
2696
|
-
|
|
2908
|
+
generateImage: (req, ctx) => {
|
|
2909
|
+
throwIfAborted(ctx.signal);
|
|
2910
|
+
return generateMuseImage(req, ctx, deps);
|
|
2911
|
+
},
|
|
2912
|
+
generateVideo: (req, ctx) => {
|
|
2913
|
+
throwIfAborted(ctx.signal);
|
|
2914
|
+
return generateFalVideo(req, ctx, deps);
|
|
2915
|
+
}
|
|
2697
2916
|
};
|
|
2698
2917
|
}
|
|
2699
2918
|
var falAdapter = createFalAdapter();
|
|
2700
|
-
function refToUrl(ref) {
|
|
2701
|
-
if ("url" in ref) return ref.url;
|
|
2702
|
-
return `data:${ref.mime};base64,${Buffer.from(ref.bytes).toString("base64")}`;
|
|
2703
|
-
}
|
|
2704
|
-
async function readBody(res) {
|
|
2705
|
-
const text2 = await res.text().catch(() => "");
|
|
2706
|
-
try {
|
|
2707
|
-
const decoded = JsonValueSchema.safeParse(JSON.parse(text2));
|
|
2708
|
-
return decoded.success ? decoded.data : text2;
|
|
2709
|
-
} catch {
|
|
2710
|
-
return text2;
|
|
2711
|
-
}
|
|
2712
|
-
}
|
|
2713
2919
|
var falDetailSchema = z6.object({ detail: JsonValueSchema });
|
|
2714
2920
|
function liftDetail(body) {
|
|
2715
2921
|
const parsed = falDetailSchema.safeParse(body);
|
|
@@ -2726,15 +2932,17 @@ var falSdkThrownSchema = z6.object({
|
|
|
2726
2932
|
message: z6.string().optional()
|
|
2727
2933
|
});
|
|
2728
2934
|
function falSdkError(cause, model) {
|
|
2729
|
-
if (isModelKitError(cause)) return cause;
|
|
2730
2935
|
const parsed = falSdkThrownSchema.safeParse(cause);
|
|
2731
2936
|
if (parsed.success) {
|
|
2732
2937
|
const status = parsed.data.status ?? parsed.data.statusCode;
|
|
2733
2938
|
const body = parsed.data.body ?? parsed.data.message ?? String(cause);
|
|
2734
|
-
return
|
|
2939
|
+
return classifyThrown("fal", cause, model, { status, body: liftDetail(body) });
|
|
2735
2940
|
}
|
|
2736
2941
|
const info = describeThrown(cause);
|
|
2737
|
-
return
|
|
2942
|
+
return classifyThrown("fal", cause, model, {
|
|
2943
|
+
status: info.status,
|
|
2944
|
+
body: liftDetail(info.body)
|
|
2945
|
+
});
|
|
2738
2946
|
}
|
|
2739
2947
|
function gatewayConfig(ctx) {
|
|
2740
2948
|
const cf = ctx.routing.cloudflare;
|
|
@@ -2816,7 +3024,7 @@ async function passthroughRequest(ctx, endpoint, input) {
|
|
|
2816
3024
|
}
|
|
2817
3025
|
return JsonValueSchema.parse(await resultRes.json());
|
|
2818
3026
|
}
|
|
2819
|
-
|
|
3027
|
+
function falClientOf(ctx, deps) {
|
|
2820
3028
|
const falKey = ctx.keys.fal;
|
|
2821
3029
|
if (!falKey) {
|
|
2822
3030
|
throw new ModelKitError({
|
|
@@ -2827,12 +3035,19 @@ async function subscribe(ctx, deps, endpoint, input) {
|
|
|
2827
3035
|
retryable: false
|
|
2828
3036
|
});
|
|
2829
3037
|
}
|
|
2830
|
-
|
|
3038
|
+
return deps.createFalClient({ credentials: falKey, fetch: ctx.fetch });
|
|
3039
|
+
}
|
|
3040
|
+
async function subscribe(ctx, deps, endpoint, input) {
|
|
3041
|
+
const client2 = falClientOf(ctx, deps);
|
|
3042
|
+
const options = {
|
|
3043
|
+
input,
|
|
3044
|
+
...ctx.signal !== void 0 ? { abortSignal: ctx.signal } : {}
|
|
3045
|
+
};
|
|
2831
3046
|
try {
|
|
2832
3047
|
return await withRetry(
|
|
2833
3048
|
async () => {
|
|
2834
3049
|
try {
|
|
2835
|
-
return await client2.subscribe(endpoint,
|
|
3050
|
+
return await client2.subscribe(endpoint, options);
|
|
2836
3051
|
} catch (cause) {
|
|
2837
3052
|
throw falSdkError(cause, ctx.model.id);
|
|
2838
3053
|
}
|
|
@@ -2937,8 +3152,12 @@ async function generateMuseImage(req, ctx, deps) {
|
|
|
2937
3152
|
raw: payload
|
|
2938
3153
|
};
|
|
2939
3154
|
}
|
|
3155
|
+
var H3_MAX_MODEL_IDS = /* @__PURE__ */ new Set([
|
|
3156
|
+
"minimax/h3-max",
|
|
3157
|
+
"minimax/h3-max/reference-to-video"
|
|
3158
|
+
]);
|
|
2940
3159
|
function minimaxFamily(providerModelId) {
|
|
2941
|
-
return providerModelId.toLowerCase()
|
|
3160
|
+
return H3_MAX_MODEL_IDS.has(providerModelId.toLowerCase()) ? "h3-max" : "h3";
|
|
2942
3161
|
}
|
|
2943
3162
|
function minimaxBase(req, family) {
|
|
2944
3163
|
const resolution = (family === "h3-max" ? req.resolution ?? "768p" : req.resolution ?? "2k").toUpperCase();
|
|
@@ -2946,14 +3165,17 @@ function minimaxBase(req, family) {
|
|
|
2946
3165
|
prompt: req.prompt.trim(),
|
|
2947
3166
|
duration: req.durationSeconds ?? 5,
|
|
2948
3167
|
resolution,
|
|
2949
|
-
prompt_expansion_mode: req.promptExpansion ?? "balanced"
|
|
2950
|
-
enable_safety_checker: true
|
|
3168
|
+
prompt_expansion_mode: req.promptExpansion ?? "balanced"
|
|
2951
3169
|
};
|
|
3170
|
+
if (req.safetyChecker !== void 0) input.enable_safety_checker = req.safetyChecker;
|
|
2952
3171
|
if (req.seed !== void 0) input.seed = req.seed;
|
|
2953
3172
|
return input;
|
|
2954
3173
|
}
|
|
3174
|
+
var KLING_MODEL_IDS = /* @__PURE__ */ new Set([
|
|
3175
|
+
"fal-ai/kling-video/o1/video-to-video/reference"
|
|
3176
|
+
]);
|
|
2955
3177
|
function isKling(providerModelId) {
|
|
2956
|
-
return providerModelId.toLowerCase()
|
|
3178
|
+
return KLING_MODEL_IDS.has(providerModelId.toLowerCase());
|
|
2957
3179
|
}
|
|
2958
3180
|
function klingO1Input(req) {
|
|
2959
3181
|
const source = req.sourceVideo ? refToUrl(req.sourceVideo) : void 0;
|
|
@@ -2966,13 +3188,14 @@ function klingO1Input(req) {
|
|
|
2966
3188
|
});
|
|
2967
3189
|
}
|
|
2968
3190
|
const duration = Math.min(10, Math.max(3, Math.round(req.durationSeconds ?? 5)));
|
|
2969
|
-
const ratio = req.aspectRatio === "16:9" || req.aspectRatio === "9:16" || req.aspectRatio === "1:1" ? req.aspectRatio : "auto";
|
|
2970
3191
|
const input = {
|
|
2971
3192
|
prompt: req.prompt,
|
|
2972
3193
|
video_url: source,
|
|
2973
|
-
duration: String(duration)
|
|
2974
|
-
aspect_ratio: ratio
|
|
3194
|
+
duration: String(duration)
|
|
2975
3195
|
};
|
|
3196
|
+
if (req.aspectRatio !== "adaptive") {
|
|
3197
|
+
input.aspect_ratio = req.aspectRatio === "16:9" || req.aspectRatio === "9:16" || req.aspectRatio === "1:1" ? req.aspectRatio : "auto";
|
|
3198
|
+
}
|
|
2976
3199
|
const refs = (req.referenceImages ?? []).map(refToUrl);
|
|
2977
3200
|
if (refs.length > 0) input.image_urls = refs;
|
|
2978
3201
|
return input;
|
|
@@ -3001,13 +3224,7 @@ async function generateFalVideo(req, ctx, deps) {
|
|
|
3001
3224
|
if (ctx.routing.fal === "cloudflare-passthrough") {
|
|
3002
3225
|
return await passthroughVideoJob(ctx, req, KLING_O1_ENDPOINT, input);
|
|
3003
3226
|
}
|
|
3004
|
-
|
|
3005
|
-
return completedVideoJob(
|
|
3006
|
-
ctx,
|
|
3007
|
-
req,
|
|
3008
|
-
extractVideoUrl(result2, KLING_O1_ENDPOINT, ctx.model.id),
|
|
3009
|
-
result2
|
|
3010
|
-
);
|
|
3227
|
+
return await submitQueueJob(ctx, req, deps, KLING_O1_ENDPOINT, input);
|
|
3011
3228
|
}
|
|
3012
3229
|
const family = minimaxFamily(providerModelId);
|
|
3013
3230
|
const refs = {
|
|
@@ -3031,24 +3248,88 @@ async function generateFalVideo(req, ctx, deps) {
|
|
|
3031
3248
|
if (lastFrame) base.end_image_url = lastFrame;
|
|
3032
3249
|
} else {
|
|
3033
3250
|
endpoint = `minimax/${family}/text-to-video`;
|
|
3034
|
-
|
|
3251
|
+
if (req.aspectRatio !== void 0 && req.aspectRatio !== "adaptive") {
|
|
3252
|
+
base.aspect_ratio = req.aspectRatio;
|
|
3253
|
+
}
|
|
3035
3254
|
}
|
|
3036
3255
|
if (ctx.routing.fal === "cloudflare-passthrough") {
|
|
3037
3256
|
return await passthroughVideoJob(ctx, req, endpoint, base);
|
|
3038
3257
|
}
|
|
3039
|
-
|
|
3040
|
-
|
|
3258
|
+
return await submitQueueJob(ctx, req, deps, endpoint, base);
|
|
3259
|
+
}
|
|
3260
|
+
async function submitQueueJob(ctx, req, deps, endpoint, input) {
|
|
3261
|
+
const client2 = falClientOf(ctx, deps);
|
|
3262
|
+
let submitted;
|
|
3263
|
+
try {
|
|
3264
|
+
submitted = await withRetry(
|
|
3265
|
+
async () => {
|
|
3266
|
+
try {
|
|
3267
|
+
return await client2.queue.submit(endpoint, {
|
|
3268
|
+
input,
|
|
3269
|
+
...ctx.signal !== void 0 ? { abortSignal: ctx.signal } : {}
|
|
3270
|
+
});
|
|
3271
|
+
} catch (cause) {
|
|
3272
|
+
throw falSdkError(cause, ctx.model.id);
|
|
3273
|
+
}
|
|
3274
|
+
},
|
|
3275
|
+
ctx.signal !== void 0 ? { signal: ctx.signal } : {}
|
|
3276
|
+
);
|
|
3277
|
+
} catch (cause) {
|
|
3278
|
+
throw falSdkError(cause, ctx.model.id);
|
|
3279
|
+
}
|
|
3280
|
+
return queuedVideoJob(ctx, req, client2, endpoint, submitted.requestId);
|
|
3041
3281
|
}
|
|
3042
|
-
function
|
|
3282
|
+
function queuedVideoJob(ctx, req, client2, endpoint, requestId) {
|
|
3283
|
+
const readStatus = async () => {
|
|
3284
|
+
try {
|
|
3285
|
+
const options = {
|
|
3286
|
+
requestId,
|
|
3287
|
+
...ctx.signal !== void 0 ? { abortSignal: ctx.signal } : {}
|
|
3288
|
+
};
|
|
3289
|
+
return (await client2.queue.status(endpoint, options)).status;
|
|
3290
|
+
} catch (cause) {
|
|
3291
|
+
throw falSdkError(cause, ctx.model.id);
|
|
3292
|
+
}
|
|
3293
|
+
};
|
|
3043
3294
|
const duration = req.durationSeconds ?? 5;
|
|
3044
|
-
const result = { video: { url }, usage: videoUsage(ctx, req, duration), raw };
|
|
3045
3295
|
return {
|
|
3046
|
-
jobId:
|
|
3296
|
+
jobId: requestId,
|
|
3047
3297
|
async poll() {
|
|
3048
|
-
|
|
3298
|
+
try {
|
|
3299
|
+
const status = await readStatus();
|
|
3300
|
+
if (status === "COMPLETED") return { status: "succeeded" };
|
|
3301
|
+
if (status === "IN_QUEUE") return { status: "pending" };
|
|
3302
|
+
return { status: "running" };
|
|
3303
|
+
} catch (cause) {
|
|
3304
|
+
if (isModelKitError(cause) && !cause.retryable)
|
|
3305
|
+
return { status: "failed" };
|
|
3306
|
+
return { status: "pending" };
|
|
3307
|
+
}
|
|
3049
3308
|
},
|
|
3050
|
-
async result() {
|
|
3051
|
-
|
|
3309
|
+
async result(opts) {
|
|
3310
|
+
const signal = opts?.signal ?? ctx.signal;
|
|
3311
|
+
const pollOptions = {
|
|
3312
|
+
intervalMs: opts?.pollIntervalMs ?? PASSTHROUGH_POLL_MS,
|
|
3313
|
+
timeoutMs: opts?.timeoutMs ?? 15 * 6e4
|
|
3314
|
+
};
|
|
3315
|
+
if (signal !== void 0) pollOptions.signal = signal;
|
|
3316
|
+
const queueOptions = {
|
|
3317
|
+
requestId,
|
|
3318
|
+
...signal !== void 0 ? { abortSignal: signal } : {}
|
|
3319
|
+
};
|
|
3320
|
+
const payload = await pollUntil(async () => {
|
|
3321
|
+
try {
|
|
3322
|
+
const current = await client2.queue.status(endpoint, queueOptions);
|
|
3323
|
+
if (current.status !== "COMPLETED") return void 0;
|
|
3324
|
+
return await client2.queue.result(endpoint, queueOptions);
|
|
3325
|
+
} catch (cause) {
|
|
3326
|
+
const err = falSdkError(cause, ctx.model.id);
|
|
3327
|
+
if (err.retryable) return void 0;
|
|
3328
|
+
throw err;
|
|
3329
|
+
}
|
|
3330
|
+
}, pollOptions);
|
|
3331
|
+
const url = extractVideoUrl(payload, endpoint, ctx.model.id);
|
|
3332
|
+
return { video: { url }, usage: videoUsage(ctx, req, duration), raw: payload };
|
|
3052
3333
|
}
|
|
3053
3334
|
};
|
|
3054
3335
|
}
|
|
@@ -3401,9 +3682,7 @@ function sdkStatus(cause) {
|
|
|
3401
3682
|
return describeThrown(cause).status;
|
|
3402
3683
|
}
|
|
3403
3684
|
function throwSdkError(cause, model) {
|
|
3404
|
-
|
|
3405
|
-
const info = describeThrown(cause);
|
|
3406
|
-
throw classifyHttpError(info.status, info.body, "google-genai", model);
|
|
3685
|
+
throw classifyThrown("google-genai", cause, model);
|
|
3407
3686
|
}
|
|
3408
3687
|
function toBase64(bytes) {
|
|
3409
3688
|
return Buffer.from(bytes).toString("base64");
|
|
@@ -3459,6 +3738,14 @@ async function generateVeoVideo(req, ctx, createGenAIClient) {
|
|
|
3459
3738
|
model: modelId
|
|
3460
3739
|
});
|
|
3461
3740
|
}
|
|
3741
|
+
if (req.lastFrame !== void 0 && req.firstFrame === void 0) {
|
|
3742
|
+
throw new ModelKitError({
|
|
3743
|
+
code: "missing_input",
|
|
3744
|
+
message: `${modelId} requires firstFrame when lastFrame is set`,
|
|
3745
|
+
provider: "google-genai",
|
|
3746
|
+
model: modelId
|
|
3747
|
+
});
|
|
3748
|
+
}
|
|
3462
3749
|
const duration = req.durationSeconds ?? 8;
|
|
3463
3750
|
const personGeneration = req.firstFrame ?? refs.length > 0 ? "allow_adult" : "allow_all";
|
|
3464
3751
|
let image;
|
|
@@ -3525,7 +3812,7 @@ async function generateVeoVideo(req, ctx, createGenAIClient) {
|
|
|
3525
3812
|
throwSdkError(cause, modelId);
|
|
3526
3813
|
}
|
|
3527
3814
|
};
|
|
3528
|
-
const jobId = operation.name ??
|
|
3815
|
+
const jobId = operation.name ?? crypto.randomUUID();
|
|
3529
3816
|
const usage2 = videoUsage2(ctx, req, duration);
|
|
3530
3817
|
return {
|
|
3531
3818
|
jobId,
|
|
@@ -3607,12 +3894,17 @@ async function generateOmniVideo(req, ctx, createGenAIClient) {
|
|
|
3607
3894
|
const duration = req.durationSeconds ?? 8;
|
|
3608
3895
|
const images = req.referenceImages ?? [];
|
|
3609
3896
|
const videos = req.referenceVideos ?? [];
|
|
3610
|
-
const task = req.sourceVideo ? "edit" :
|
|
3611
|
-
const
|
|
3612
|
-
|
|
3613
|
-
|
|
3614
|
-
|
|
3615
|
-
|
|
3897
|
+
const task = req.sourceVideo ? "edit" : req.firstFrame ? "image_to_video" : images.length > 0 || videos.length > 0 ? "reference_to_video" : "text_to_video";
|
|
3898
|
+
const isOmniV1 = providerModelId === "gemini-omni-flash-preview";
|
|
3899
|
+
const responseFormat = { type: "video", delivery: "uri" };
|
|
3900
|
+
if (req.sourceVideo === void 0 && req.aspectRatio !== void 0 && req.aspectRatio !== "adaptive") {
|
|
3901
|
+
responseFormat.aspect_ratio = toOmniAspect(req.aspectRatio);
|
|
3902
|
+
}
|
|
3903
|
+
if (!isOmniV1) {
|
|
3904
|
+
const omniResolution = toOmniResolution(req.resolution);
|
|
3905
|
+
if (omniResolution !== void 0) responseFormat.resolution = omniResolution;
|
|
3906
|
+
}
|
|
3907
|
+
if (req.durationSeconds !== void 0) responseFormat.duration = `${req.durationSeconds}s`;
|
|
3616
3908
|
const client2 = createGenAIClient({ apiKey });
|
|
3617
3909
|
const uploadedByUri = /* @__PURE__ */ new Map();
|
|
3618
3910
|
const uploadedNames = [];
|
|
@@ -3636,7 +3928,8 @@ async function generateOmniVideo(req, ctx, createGenAIClient) {
|
|
|
3636
3928
|
model: providerModelId,
|
|
3637
3929
|
input,
|
|
3638
3930
|
response_format: responseFormat,
|
|
3639
|
-
generation_config: { video_config: { task } }
|
|
3931
|
+
generation_config: { video_config: { task } },
|
|
3932
|
+
store: true
|
|
3640
3933
|
});
|
|
3641
3934
|
const createRetryOptions = { attempts: 3 };
|
|
3642
3935
|
if (ctx.signal !== void 0) createRetryOptions.signal = ctx.signal;
|
|
@@ -3658,6 +3951,7 @@ async function generateOmniVideo(req, ctx, createGenAIClient) {
|
|
|
3658
3951
|
});
|
|
3659
3952
|
}
|
|
3660
3953
|
for (const ref of videos) {
|
|
3954
|
+
if (ref.label !== void 0) parts.push({ type: "text", text: ref.label });
|
|
3661
3955
|
const media = await resolveMedia(ref, ctx.fetch, ctx.signal, "video/mp4", modelId);
|
|
3662
3956
|
parts.push({
|
|
3663
3957
|
type: "video",
|
|
@@ -3666,6 +3960,8 @@ async function generateOmniVideo(req, ctx, createGenAIClient) {
|
|
|
3666
3960
|
});
|
|
3667
3961
|
}
|
|
3668
3962
|
if (req.firstFrame) {
|
|
3963
|
+
if (req.firstFrame.label !== void 0)
|
|
3964
|
+
parts.push({ type: "text", text: req.firstFrame.label });
|
|
3669
3965
|
const media = await resolveMedia(
|
|
3670
3966
|
req.firstFrame,
|
|
3671
3967
|
ctx.fetch,
|
|
@@ -3684,6 +3980,7 @@ async function generateOmniVideo(req, ctx, createGenAIClient) {
|
|
|
3684
3980
|
}
|
|
3685
3981
|
}
|
|
3686
3982
|
for (const ref of images) {
|
|
3983
|
+
if (ref.label !== void 0) parts.push({ type: "text", text: ref.label });
|
|
3687
3984
|
const media = await resolveMedia(ref, ctx.fetch, ctx.signal, "image/png", modelId);
|
|
3688
3985
|
if (media.bytes.length > OMNI_INLINE_LIMIT_BYTES) {
|
|
3689
3986
|
parts.push({
|
|
@@ -3718,25 +4015,16 @@ async function generateOmniVideo(req, ctx, createGenAIClient) {
|
|
|
3718
4015
|
};
|
|
3719
4016
|
return inline;
|
|
3720
4017
|
});
|
|
3721
|
-
const inlineRetryOptions = { attempts: 3 };
|
|
3722
|
-
if (ctx.signal !== void 0) inlineRetryOptions.signal = ctx.signal;
|
|
3723
4018
|
try {
|
|
3724
|
-
interaction = await
|
|
3725
|
-
try {
|
|
3726
|
-
return await callCreate(inlineParts);
|
|
3727
|
-
} catch (inlineCause) {
|
|
3728
|
-
throwSdkError(inlineCause, modelId);
|
|
3729
|
-
}
|
|
3730
|
-
}, inlineRetryOptions);
|
|
4019
|
+
interaction = await callCreate(inlineParts);
|
|
3731
4020
|
} catch (inlineCause) {
|
|
3732
4021
|
throwSdkError(inlineCause, modelId);
|
|
3733
4022
|
}
|
|
3734
4023
|
}
|
|
3735
|
-
}
|
|
4024
|
+
} finally {
|
|
3736
4025
|
await cleanupUploads();
|
|
3737
|
-
throw cause;
|
|
3738
4026
|
}
|
|
3739
|
-
const jobId = interaction.id ??
|
|
4027
|
+
const jobId = interaction.id ?? crypto.randomUUID();
|
|
3740
4028
|
const usage2 = videoUsage2(ctx, req, duration);
|
|
3741
4029
|
const getInteraction = async () => {
|
|
3742
4030
|
try {
|
|
@@ -3763,47 +4051,43 @@ async function generateOmniVideo(req, ctx, createGenAIClient) {
|
|
|
3763
4051
|
timeoutMs: opts?.timeoutMs ?? RESULT_TIMEOUT_MS2
|
|
3764
4052
|
};
|
|
3765
4053
|
if (signal !== void 0) pollOptions.signal = signal;
|
|
3766
|
-
|
|
3767
|
-
const
|
|
3768
|
-
|
|
3769
|
-
|
|
3770
|
-
|
|
3771
|
-
|
|
3772
|
-
|
|
3773
|
-
|
|
3774
|
-
|
|
3775
|
-
|
|
3776
|
-
|
|
3777
|
-
);
|
|
3778
|
-
}
|
|
3779
|
-
return void 0;
|
|
3780
|
-
}, pollOptions);
|
|
3781
|
-
const video = extractOmniVideo(done, modelId);
|
|
3782
|
-
if (video.data) {
|
|
3783
|
-
return {
|
|
3784
|
-
video: {
|
|
3785
|
-
bytes: Buffer.from(video.data, "base64"),
|
|
3786
|
-
mime: video.mime_type ?? "video/mp4"
|
|
3787
|
-
},
|
|
3788
|
-
usage: usage2,
|
|
3789
|
-
raw: done
|
|
3790
|
-
};
|
|
4054
|
+
const done = await pollUntil(async () => {
|
|
4055
|
+
const current = await getInteraction();
|
|
4056
|
+
const status = (current.status ?? "").toUpperCase();
|
|
4057
|
+
if (status === "COMPLETED") return current;
|
|
4058
|
+
if (status === "FAILED") {
|
|
4059
|
+
throw classifyHttpError(
|
|
4060
|
+
void 0,
|
|
4061
|
+
`Gemini Omni interaction failed: ${JSON.stringify(current).slice(0, 500)}`,
|
|
4062
|
+
"google-genai",
|
|
4063
|
+
modelId
|
|
4064
|
+
);
|
|
3791
4065
|
}
|
|
3792
|
-
|
|
3793
|
-
|
|
3794
|
-
|
|
3795
|
-
|
|
3796
|
-
|
|
3797
|
-
|
|
3798
|
-
|
|
3799
|
-
|
|
3800
|
-
|
|
3801
|
-
|
|
3802
|
-
|
|
3803
|
-
|
|
3804
|
-
} finally {
|
|
3805
|
-
await cleanupUploads();
|
|
4066
|
+
return void 0;
|
|
4067
|
+
}, pollOptions);
|
|
4068
|
+
const video = extractOmniVideo(done, modelId);
|
|
4069
|
+
if (video.data) {
|
|
4070
|
+
return {
|
|
4071
|
+
video: {
|
|
4072
|
+
bytes: Buffer.from(video.data, "base64"),
|
|
4073
|
+
mime: video.mime_type ?? "video/mp4"
|
|
4074
|
+
},
|
|
4075
|
+
usage: usage2,
|
|
4076
|
+
raw: done
|
|
4077
|
+
};
|
|
3806
4078
|
}
|
|
4079
|
+
if (video.uri)
|
|
4080
|
+
return {
|
|
4081
|
+
video: await downloadVideo(ctx, video.uri, apiKey, signal),
|
|
4082
|
+
usage: usage2,
|
|
4083
|
+
raw: done
|
|
4084
|
+
};
|
|
4085
|
+
throw classifyHttpError(
|
|
4086
|
+
void 0,
|
|
4087
|
+
"No video content in Gemini Omni response",
|
|
4088
|
+
"google-genai",
|
|
4089
|
+
modelId
|
|
4090
|
+
);
|
|
3807
4091
|
}
|
|
3808
4092
|
};
|
|
3809
4093
|
}
|
|
@@ -3966,44 +4250,37 @@ function createGoogleImageAdapter(deps = defaultGoogleImageDeps) {
|
|
|
3966
4250
|
const model = google(ctx.model.providerModelId);
|
|
3967
4251
|
const content = [];
|
|
3968
4252
|
for (const ref of req.references ?? []) {
|
|
4253
|
+
if (ref.label !== void 0) content.push({ type: "text", text: ref.label });
|
|
3969
4254
|
if ("url" in ref) content.push({ type: "image", image: ref.url });
|
|
3970
4255
|
else content.push({ type: "image", image: ref.bytes, mediaType: ref.mime });
|
|
3971
4256
|
}
|
|
3972
4257
|
content.push({ type: "text", text: req.prompt });
|
|
3973
|
-
void ctx.call.postCropToAspect;
|
|
3974
4258
|
const imageConfig = {};
|
|
3975
|
-
if (req.aspectRatio !== void 0
|
|
4259
|
+
if (req.aspectRatio !== void 0 && req.aspectRatio !== "adaptive")
|
|
4260
|
+
imageConfig.aspectRatio = req.aspectRatio;
|
|
3976
4261
|
if (req.size !== void 0) imageConfig.imageSize = req.size;
|
|
4262
|
+
const googleOptions = {
|
|
4263
|
+
imageConfig,
|
|
4264
|
+
responseModalities: ["IMAGE"]
|
|
4265
|
+
};
|
|
4266
|
+
if (req.safetySettings !== void 0) googleOptions.safetySettings = req.safetySettings;
|
|
3977
4267
|
const retryOptions = {};
|
|
3978
4268
|
if (ctx.signal !== void 0) retryOptions.signal = ctx.signal;
|
|
3979
4269
|
const result = await withRetry(async () => {
|
|
3980
4270
|
const timeout = AbortSignal.timeout(GEMINI_IMAGE_TIMEOUT_MS);
|
|
3981
4271
|
const signal = ctx.signal !== void 0 ? AbortSignal.any([ctx.signal, timeout]) : timeout;
|
|
3982
4272
|
try {
|
|
3983
|
-
|
|
4273
|
+
const genOptions = {
|
|
3984
4274
|
model,
|
|
3985
4275
|
messages: [{ role: "user", content }],
|
|
3986
4276
|
maxRetries: 0,
|
|
3987
4277
|
providerOptions: {
|
|
3988
|
-
google:
|
|
3989
|
-
imageConfig,
|
|
3990
|
-
responseModalities: ["IMAGE"],
|
|
3991
|
-
safetySettings: [
|
|
3992
|
-
{
|
|
3993
|
-
category: "HARM_CATEGORY_SEXUALLY_EXPLICIT",
|
|
3994
|
-
threshold: "OFF"
|
|
3995
|
-
},
|
|
3996
|
-
{ category: "HARM_CATEGORY_HATE_SPEECH", threshold: "OFF" },
|
|
3997
|
-
{
|
|
3998
|
-
category: "HARM_CATEGORY_DANGEROUS_CONTENT",
|
|
3999
|
-
threshold: "OFF"
|
|
4000
|
-
},
|
|
4001
|
-
{ category: "HARM_CATEGORY_HARASSMENT", threshold: "OFF" }
|
|
4002
|
-
]
|
|
4003
|
-
}
|
|
4278
|
+
google: googleOptions
|
|
4004
4279
|
},
|
|
4005
4280
|
abortSignal: signal
|
|
4006
|
-
}
|
|
4281
|
+
};
|
|
4282
|
+
if (req.temperature !== void 0) genOptions.temperature = req.temperature;
|
|
4283
|
+
return await deps.runTextGeneration(genOptions);
|
|
4007
4284
|
} catch (cause) {
|
|
4008
4285
|
throw toProviderError(cause, ctx);
|
|
4009
4286
|
}
|
|
@@ -4187,6 +4464,7 @@ var KLING_MAX_INTERVAL_MS = 1e4;
|
|
|
4187
4464
|
var KLING_TIMEOUT_MS = 15 * 6e4;
|
|
4188
4465
|
var DOP_INTERVAL_MS = 5e3;
|
|
4189
4466
|
var DOP_TIMEOUT_MS = 5 * 6e4;
|
|
4467
|
+
var DOP_FALLBACK_DURATION_SECONDS = 5;
|
|
4190
4468
|
var DEFAULT_NEGATIVE_PROMPT = "text, watermark, copyright, blur, low quality, distortion, abstract, weird, deformed";
|
|
4191
4469
|
function credentials(ctx) {
|
|
4192
4470
|
const key = ctx.keys.higgsfield;
|
|
@@ -4206,26 +4484,14 @@ function headers(ctx) {
|
|
|
4206
4484
|
const { key, secret } = credentials(ctx);
|
|
4207
4485
|
return { "Content-Type": "application/json", "hf-api-key": key, "hf-secret": secret };
|
|
4208
4486
|
}
|
|
4209
|
-
function refToUrl2(ref) {
|
|
4210
|
-
if ("url" in ref) return ref.url;
|
|
4211
|
-
return `data:${ref.mime};base64,${Buffer.from(ref.bytes).toString("base64")}`;
|
|
4212
|
-
}
|
|
4213
|
-
async function readBody2(res) {
|
|
4214
|
-
const text2 = await res.text().catch(() => "");
|
|
4215
|
-
try {
|
|
4216
|
-
const decoded = JsonValueSchema.safeParse(JSON.parse(text2));
|
|
4217
|
-
return decoded.success ? decoded.data : text2;
|
|
4218
|
-
} catch {
|
|
4219
|
-
return text2;
|
|
4220
|
-
}
|
|
4221
|
-
}
|
|
4222
4487
|
function klingEndpoint(providerModelId) {
|
|
4223
4488
|
if (providerModelId.startsWith("http")) return providerModelId;
|
|
4224
4489
|
const path = providerModelId.startsWith("/") ? providerModelId.slice(1) : providerModelId;
|
|
4225
4490
|
return `${PLATFORM}/${path}`;
|
|
4226
4491
|
}
|
|
4227
|
-
|
|
4228
|
-
|
|
4492
|
+
var DOP_MODEL_IDS = /* @__PURE__ */ new Set(["dop", "dop-preview"]);
|
|
4493
|
+
function higgsfieldVideoKind(providerModelId) {
|
|
4494
|
+
return DOP_MODEL_IDS.has(providerModelId.toLowerCase()) ? "dop" : "kling";
|
|
4229
4495
|
}
|
|
4230
4496
|
function videoUsage3(ctx, req, duration) {
|
|
4231
4497
|
const event = {
|
|
@@ -4261,8 +4527,20 @@ function requestInit(ctx, init) {
|
|
|
4261
4527
|
if (ctx.signal !== void 0) request.signal = ctx.signal;
|
|
4262
4528
|
return request;
|
|
4263
4529
|
}
|
|
4530
|
+
async function createRequest(ctx, url, init) {
|
|
4531
|
+
let res;
|
|
4532
|
+
try {
|
|
4533
|
+
res = await ctx.fetch(url, requestInit(ctx, init));
|
|
4534
|
+
} catch (cause) {
|
|
4535
|
+
throw classifyThrown("higgsfield", cause, ctx.model.id);
|
|
4536
|
+
}
|
|
4537
|
+
if (!res.ok) {
|
|
4538
|
+
throw classifyHttpError(res.status, await readBody(res), "higgsfield", ctx.model.id);
|
|
4539
|
+
}
|
|
4540
|
+
return res;
|
|
4541
|
+
}
|
|
4264
4542
|
async function generateKlingVideo(req, ctx) {
|
|
4265
|
-
const firstFrame = req.firstFrame ?
|
|
4543
|
+
const firstFrame = req.firstFrame ? refToUrl(req.firstFrame) : void 0;
|
|
4266
4544
|
if (!firstFrame) {
|
|
4267
4545
|
throw new ModelKitError({
|
|
4268
4546
|
code: "missing_input",
|
|
@@ -4279,26 +4557,16 @@ async function generateKlingVideo(req, ctx) {
|
|
|
4279
4557
|
negative_prompt: req.negativePrompt ?? DEFAULT_NEGATIVE_PROMPT
|
|
4280
4558
|
};
|
|
4281
4559
|
if (req.durationSeconds !== void 0) body.duration = req.durationSeconds;
|
|
4282
|
-
if (req.aspectRatio !== void 0
|
|
4283
|
-
|
|
4560
|
+
if (req.aspectRatio !== void 0 && req.aspectRatio !== "adaptive")
|
|
4561
|
+
body.aspect_ratio = req.aspectRatio;
|
|
4562
|
+
if (req.lastFrame) body.last_image_url = refToUrl(req.lastFrame);
|
|
4284
4563
|
const endpoint = klingEndpoint(ctx.model.providerModelId);
|
|
4285
|
-
|
|
4286
|
-
|
|
4287
|
-
|
|
4288
|
-
|
|
4289
|
-
|
|
4290
|
-
|
|
4291
|
-
} catch (cause) {
|
|
4292
|
-
throw networkError(cause, ctx);
|
|
4293
|
-
}
|
|
4294
|
-
if (!createRes.ok) {
|
|
4295
|
-
throw classifyHttpError(
|
|
4296
|
-
createRes.status,
|
|
4297
|
-
await readBody2(createRes),
|
|
4298
|
-
"higgsfield",
|
|
4299
|
-
ctx.model.id
|
|
4300
|
-
);
|
|
4301
|
-
}
|
|
4564
|
+
const retryOptions = {};
|
|
4565
|
+
if (ctx.signal !== void 0) retryOptions.signal = ctx.signal;
|
|
4566
|
+
const createRes = await withRetry(
|
|
4567
|
+
() => createRequest(ctx, endpoint, { method: "POST", body: JSON.stringify(body) }),
|
|
4568
|
+
retryOptions
|
|
4569
|
+
);
|
|
4302
4570
|
const created = klingCreateSchema.safeParse(await createRes.json());
|
|
4303
4571
|
if (!created.success) {
|
|
4304
4572
|
throw new ModelKitError({
|
|
@@ -4317,9 +4585,9 @@ async function generateKlingVideo(req, ctx) {
|
|
|
4317
4585
|
} catch {
|
|
4318
4586
|
return void 0;
|
|
4319
4587
|
}
|
|
4320
|
-
if (res.status >= 500) return void 0;
|
|
4588
|
+
if (res.status === 429 || res.status >= 500) return void 0;
|
|
4321
4589
|
if (!res.ok) {
|
|
4322
|
-
throw classifyHttpError(res.status, await
|
|
4590
|
+
throw classifyHttpError(res.status, await readBody(res), "higgsfield", ctx.model.id);
|
|
4323
4591
|
}
|
|
4324
4592
|
const payload = JsonValueSchema.parse(await res.json());
|
|
4325
4593
|
const parsed = klingStatusSchema.safeParse(payload);
|
|
@@ -4378,11 +4646,6 @@ async function generateKlingVideo(req, ctx) {
|
|
|
4378
4646
|
}
|
|
4379
4647
|
};
|
|
4380
4648
|
}
|
|
4381
|
-
function networkError(cause, ctx) {
|
|
4382
|
-
if (isModelKitError(cause)) return cause;
|
|
4383
|
-
const info = describeThrown(cause);
|
|
4384
|
-
return classifyHttpError(info.status, info.body, "higgsfield", ctx.model.id);
|
|
4385
|
-
}
|
|
4386
4649
|
var dopMotionOptionsSchema = z10.object({
|
|
4387
4650
|
modelkit: z10.object({ motion: z10.string().optional() }).optional()
|
|
4388
4651
|
});
|
|
@@ -4431,7 +4694,7 @@ function dopUrl(body) {
|
|
|
4431
4694
|
var dopCreateSchema = z10.object({ id: z10.string() });
|
|
4432
4695
|
var dopStatusSchema = z10.object({ status: z10.string().optional() });
|
|
4433
4696
|
async function generateDopVideo(req, ctx) {
|
|
4434
|
-
const firstFrame = req.firstFrame ?
|
|
4697
|
+
const firstFrame = req.firstFrame ? refToUrl(req.firstFrame) : void 0;
|
|
4435
4698
|
if (!firstFrame) {
|
|
4436
4699
|
throw new ModelKitError({
|
|
4437
4700
|
code: "missing_input",
|
|
@@ -4451,29 +4714,18 @@ async function generateDopVideo(req, ctx) {
|
|
|
4451
4714
|
webhook: null
|
|
4452
4715
|
};
|
|
4453
4716
|
if (req.lastFrame) {
|
|
4454
|
-
params.input_images_end = [{ type: "image_url", image_url:
|
|
4717
|
+
params.input_images_end = [{ type: "image_url", image_url: refToUrl(req.lastFrame) }];
|
|
4455
4718
|
}
|
|
4456
4719
|
if (req.seed !== void 0) params.seed = req.seed;
|
|
4457
|
-
|
|
4458
|
-
|
|
4459
|
-
|
|
4460
|
-
|
|
4461
|
-
|
|
4462
|
-
|
|
4463
|
-
|
|
4464
|
-
|
|
4465
|
-
|
|
4466
|
-
} catch (cause) {
|
|
4467
|
-
throw networkError(cause, ctx);
|
|
4468
|
-
}
|
|
4469
|
-
if (!createRes.ok) {
|
|
4470
|
-
throw classifyHttpError(
|
|
4471
|
-
createRes.status,
|
|
4472
|
-
await readBody2(createRes),
|
|
4473
|
-
"higgsfield",
|
|
4474
|
-
ctx.model.id
|
|
4475
|
-
);
|
|
4476
|
-
}
|
|
4720
|
+
const retryOptions = {};
|
|
4721
|
+
if (ctx.signal !== void 0) retryOptions.signal = ctx.signal;
|
|
4722
|
+
const createRes = await withRetry(
|
|
4723
|
+
() => createRequest(ctx, DOP_ENDPOINT, {
|
|
4724
|
+
method: "POST",
|
|
4725
|
+
body: JSON.stringify({ params, webhook: null })
|
|
4726
|
+
}),
|
|
4727
|
+
retryOptions
|
|
4728
|
+
);
|
|
4477
4729
|
const created = dopCreateSchema.safeParse(await createRes.json());
|
|
4478
4730
|
if (!created.success) {
|
|
4479
4731
|
throw new ModelKitError({
|
|
@@ -4542,14 +4794,20 @@ async function generateDopVideo(req, ctx) {
|
|
|
4542
4794
|
};
|
|
4543
4795
|
if (dopSignal !== void 0) pollSettings.signal = dopSignal;
|
|
4544
4796
|
const url = await pollUntil(check, pollSettings);
|
|
4545
|
-
const result = {
|
|
4797
|
+
const result = {
|
|
4798
|
+
video: { url },
|
|
4799
|
+
usage: videoUsage3(ctx, req, req.durationSeconds ?? DOP_FALLBACK_DURATION_SECONDS)
|
|
4800
|
+
};
|
|
4546
4801
|
return result;
|
|
4547
4802
|
}
|
|
4548
4803
|
};
|
|
4549
4804
|
}
|
|
4550
4805
|
var higgsfieldAdapter = {
|
|
4551
4806
|
id: "higgsfield",
|
|
4552
|
-
generateVideo: (req, ctx) =>
|
|
4807
|
+
generateVideo: (req, ctx) => {
|
|
4808
|
+
throwIfAborted(ctx.signal);
|
|
4809
|
+
return higgsfieldVideoKind(ctx.model.providerModelId) === "dop" ? generateDopVideo(req, ctx) : generateKlingVideo(req, ctx);
|
|
4810
|
+
}
|
|
4553
4811
|
};
|
|
4554
4812
|
|
|
4555
4813
|
// src/adapters/openai-image.ts
|
|
@@ -4644,6 +4902,7 @@ var openaiUsageSchema = z11.object({
|
|
|
4644
4902
|
var openaiImageAdapter = {
|
|
4645
4903
|
id: "openai-image",
|
|
4646
4904
|
async generateImage(req, ctx) {
|
|
4905
|
+
throwIfAborted(ctx.signal);
|
|
4647
4906
|
const apiKey = ctx.keys.openai;
|
|
4648
4907
|
if (!apiKey)
|
|
4649
4908
|
throw new ModelKitError({
|
|
@@ -4653,6 +4912,13 @@ var openaiImageAdapter = {
|
|
|
4653
4912
|
model: ctx.model.id,
|
|
4654
4913
|
retryable: false
|
|
4655
4914
|
});
|
|
4915
|
+
if ((req.references ?? []).some((ref) => ref.label !== void 0)) {
|
|
4916
|
+
ctx.warnings.push({
|
|
4917
|
+
code: "option_ignored",
|
|
4918
|
+
field: "references.label",
|
|
4919
|
+
message: "openai-image cannot express reference labels; ignoring them"
|
|
4920
|
+
});
|
|
4921
|
+
}
|
|
4656
4922
|
const client2 = new OpenAI({ apiKey, fetch: ctx.fetch, maxRetries: 0 });
|
|
4657
4923
|
const size = req.exactSize !== void 0 ? req.exactSize : req.aspectRatio === void 0 || req.aspectRatio === "adaptive" ? void 0 : aspectRatioToSize(req.aspectRatio, req.size ?? "1K");
|
|
4658
4924
|
const refs = req.references ?? [];
|
|
@@ -4666,24 +4932,34 @@ var openaiImageAdapter = {
|
|
|
4666
4932
|
try {
|
|
4667
4933
|
if (!isEdit) {
|
|
4668
4934
|
if (size !== void 0) {
|
|
4669
|
-
return await client2.images.generate(
|
|
4935
|
+
return await client2.images.generate(
|
|
4936
|
+
{
|
|
4937
|
+
model: ctx.model.providerModelId,
|
|
4938
|
+
prompt: req.prompt,
|
|
4939
|
+
size,
|
|
4940
|
+
quality: sdkQuality,
|
|
4941
|
+
...count
|
|
4942
|
+
},
|
|
4943
|
+
{ signal: ctx.signal }
|
|
4944
|
+
);
|
|
4945
|
+
}
|
|
4946
|
+
return await client2.images.generate(
|
|
4947
|
+
{
|
|
4670
4948
|
model: ctx.model.providerModelId,
|
|
4671
4949
|
prompt: req.prompt,
|
|
4672
|
-
size,
|
|
4673
4950
|
quality: sdkQuality,
|
|
4674
4951
|
...count
|
|
4675
|
-
}
|
|
4676
|
-
|
|
4677
|
-
|
|
4678
|
-
model: ctx.model.providerModelId,
|
|
4679
|
-
prompt: req.prompt,
|
|
4680
|
-
quality: sdkQuality,
|
|
4681
|
-
...count
|
|
4682
|
-
});
|
|
4952
|
+
},
|
|
4953
|
+
{ signal: ctx.signal }
|
|
4954
|
+
);
|
|
4683
4955
|
}
|
|
4684
4956
|
const files = await Promise.all(
|
|
4685
4957
|
refs.slice(0, MAX_EDIT_REFERENCES).map(async (ref, i) => {
|
|
4686
|
-
const { bytes, mime } = await mediaRefToBytes(ref, ctx.fetch
|
|
4958
|
+
const { bytes, mime } = await mediaRefToBytes(ref, ctx.fetch, {
|
|
4959
|
+
signal: ctx.signal,
|
|
4960
|
+
provider: "openai-image",
|
|
4961
|
+
model: ctx.model.id
|
|
4962
|
+
});
|
|
4687
4963
|
const ext = mime.includes("jpeg") ? "jpg" : mime.includes("webp") ? "webp" : "png";
|
|
4688
4964
|
return new File([bytes], `ref-${i}.${ext}`, { type: mime });
|
|
4689
4965
|
})
|
|
@@ -4691,22 +4967,28 @@ var openaiImageAdapter = {
|
|
|
4691
4967
|
const single = files.length === 1 ? files[0] : void 0;
|
|
4692
4968
|
const imageInput = single ?? files;
|
|
4693
4969
|
if (size !== void 0) {
|
|
4694
|
-
return await client2.images.edit(
|
|
4970
|
+
return await client2.images.edit(
|
|
4971
|
+
{
|
|
4972
|
+
model: ctx.model.providerModelId,
|
|
4973
|
+
image: imageInput,
|
|
4974
|
+
prompt: req.prompt,
|
|
4975
|
+
size,
|
|
4976
|
+
quality: sdkQuality,
|
|
4977
|
+
...count
|
|
4978
|
+
},
|
|
4979
|
+
{ signal: ctx.signal }
|
|
4980
|
+
);
|
|
4981
|
+
}
|
|
4982
|
+
return await client2.images.edit(
|
|
4983
|
+
{
|
|
4695
4984
|
model: ctx.model.providerModelId,
|
|
4696
4985
|
image: imageInput,
|
|
4697
4986
|
prompt: req.prompt,
|
|
4698
|
-
size,
|
|
4699
4987
|
quality: sdkQuality,
|
|
4700
4988
|
...count
|
|
4701
|
-
}
|
|
4702
|
-
|
|
4703
|
-
|
|
4704
|
-
model: ctx.model.providerModelId,
|
|
4705
|
-
image: imageInput,
|
|
4706
|
-
prompt: req.prompt,
|
|
4707
|
-
quality: sdkQuality,
|
|
4708
|
-
...count
|
|
4709
|
-
});
|
|
4989
|
+
},
|
|
4990
|
+
{ signal: ctx.signal }
|
|
4991
|
+
);
|
|
4710
4992
|
} catch (cause) {
|
|
4711
4993
|
throw toProviderError2(cause, ctx);
|
|
4712
4994
|
}
|
|
@@ -4724,28 +5006,16 @@ var openaiImageAdapter = {
|
|
|
4724
5006
|
const usageParsed = openaiUsageSchema.safeParse(response.usage);
|
|
4725
5007
|
const inputTokens = usageParsed.success ? usageParsed.data.input_tokens : void 0;
|
|
4726
5008
|
const outputTokens = usageParsed.success ? usageParsed.data.output_tokens : void 0;
|
|
4727
|
-
|
|
4728
|
-
|
|
4729
|
-
|
|
4730
|
-
|
|
4731
|
-
|
|
4732
|
-
|
|
4733
|
-
|
|
4734
|
-
|
|
4735
|
-
|
|
4736
|
-
|
|
4737
|
-
if (inputTokens !== void 0) usage2.inputTokens = inputTokens;
|
|
4738
|
-
if (outputTokens !== void 0) usage2.outputTokens = outputTokens;
|
|
4739
|
-
} else {
|
|
4740
|
-
usage2 = {
|
|
4741
|
-
model: ctx.model.id,
|
|
4742
|
-
provider: "openai-image",
|
|
4743
|
-
modality: "IMAGE",
|
|
4744
|
-
unit: "images",
|
|
4745
|
-
quantity: images.length,
|
|
4746
|
-
imageQuality: quality
|
|
4747
|
-
};
|
|
4748
|
-
}
|
|
5009
|
+
const usage2 = {
|
|
5010
|
+
model: ctx.model.id,
|
|
5011
|
+
provider: "openai-image",
|
|
5012
|
+
modality: "IMAGE",
|
|
5013
|
+
unit: "images",
|
|
5014
|
+
quantity: images.length,
|
|
5015
|
+
imageQuality: quality
|
|
5016
|
+
};
|
|
5017
|
+
if (inputTokens !== void 0) usage2.inputTokens = inputTokens;
|
|
5018
|
+
if (outputTokens !== void 0) usage2.outputTokens = outputTokens;
|
|
4749
5019
|
if (req.size !== void 0) usage2.imageSize = req.size;
|
|
4750
5020
|
return { images, usage: usage2, raw: response };
|
|
4751
5021
|
}
|
|
@@ -4798,7 +5068,12 @@ var NANO_BANANA_RATIOS = /* @__PURE__ */ new Set([
|
|
|
4798
5068
|
]);
|
|
4799
5069
|
async function refToBytes(ctx, ref) {
|
|
4800
5070
|
if ("bytes" in ref) return { bytes: ref.bytes, mime: ref.mime };
|
|
4801
|
-
|
|
5071
|
+
let res;
|
|
5072
|
+
try {
|
|
5073
|
+
res = await ctx.fetch(ref.url, ctx.signal ? { signal: ctx.signal } : {});
|
|
5074
|
+
} catch (cause) {
|
|
5075
|
+
throw classifyThrown("prodia", cause, ctx.model.id);
|
|
5076
|
+
}
|
|
4802
5077
|
if (!res.ok) {
|
|
4803
5078
|
const text2 = await res.text().catch(() => "");
|
|
4804
5079
|
throw classifyHttpError(res.status, text2, "prodia", ctx.model.id);
|
|
@@ -4841,6 +5116,12 @@ function emptyImage() {
|
|
|
4841
5116
|
retryable: false
|
|
4842
5117
|
});
|
|
4843
5118
|
}
|
|
5119
|
+
function inputExtension(mime) {
|
|
5120
|
+
if (mime.includes("jpeg") || mime.includes("jpg")) return "jpg";
|
|
5121
|
+
if (mime.includes("webp")) return "webp";
|
|
5122
|
+
if (mime.includes("gif")) return "gif";
|
|
5123
|
+
return "png";
|
|
5124
|
+
}
|
|
4844
5125
|
function isBgRemove(providerModelId) {
|
|
4845
5126
|
const id = providerModelId.toLowerCase();
|
|
4846
5127
|
return id.includes("remove-background") || id.includes("bg-remove");
|
|
@@ -4849,6 +5130,7 @@ function isKlein(providerModelId) {
|
|
|
4849
5130
|
return providerModelId.toLowerCase().includes("klein");
|
|
4850
5131
|
}
|
|
4851
5132
|
async function generateProdiaImage(req, ctx) {
|
|
5133
|
+
throwIfAborted(ctx.signal);
|
|
4852
5134
|
const key = ctx.keys.prodia;
|
|
4853
5135
|
if (!key) {
|
|
4854
5136
|
throw new ModelKitError({
|
|
@@ -4947,7 +5229,9 @@ async function generateProdiaImage(req, ctx) {
|
|
|
4947
5229
|
"input",
|
|
4948
5230
|
// Uint8Array<ArrayBufferLike> is not a valid BlobPart under the
|
|
4949
5231
|
// strict lib types; copy into a fresh ArrayBuffer-backed view.
|
|
4950
|
-
new File([new Uint8Array(input.bytes)], `input-${i}.
|
|
5232
|
+
new File([new Uint8Array(input.bytes)], `input-${i}.${inputExtension(input.mime)}`, {
|
|
5233
|
+
type: input.mime
|
|
5234
|
+
})
|
|
4951
5235
|
);
|
|
4952
5236
|
});
|
|
4953
5237
|
const retryOpts = {
|
|
@@ -4962,14 +5246,15 @@ async function generateProdiaImage(req, ctx) {
|
|
|
4962
5246
|
res = await withRetry(async () => {
|
|
4963
5247
|
let attemptRes;
|
|
4964
5248
|
try {
|
|
4965
|
-
|
|
5249
|
+
const init = {
|
|
4966
5250
|
method: "POST",
|
|
4967
5251
|
headers: { Authorization: `Bearer ${key}`, Accept: accept },
|
|
4968
5252
|
body: form
|
|
4969
|
-
}
|
|
5253
|
+
};
|
|
5254
|
+
if (ctx.signal !== void 0) init.signal = ctx.signal;
|
|
5255
|
+
attemptRes = await ctx.fetch(PRODIA_JOB_URL, init);
|
|
4970
5256
|
} catch (err) {
|
|
4971
|
-
|
|
4972
|
-
throw transportError("prodia", err, ctx.model.id);
|
|
5257
|
+
throw classifyThrown("prodia", err, ctx.model.id);
|
|
4973
5258
|
}
|
|
4974
5259
|
if (!attemptRes.ok) {
|
|
4975
5260
|
const text2 = await attemptRes.text().catch(() => "");
|
|
@@ -4978,8 +5263,7 @@ async function generateProdiaImage(req, ctx) {
|
|
|
4978
5263
|
return attemptRes;
|
|
4979
5264
|
}, retryOpts);
|
|
4980
5265
|
} catch (err) {
|
|
4981
|
-
|
|
4982
|
-
throw transportError("prodia", err, ctx.model.id);
|
|
5266
|
+
throw classifyThrown("prodia", err, ctx.model.id);
|
|
4983
5267
|
}
|
|
4984
5268
|
const bytes = parseImageResponse(
|
|
4985
5269
|
new Uint8Array(await res.arrayBuffer()),
|
|
@@ -5029,11 +5313,7 @@ function client(ctx, deps) {
|
|
|
5029
5313
|
retryable: false
|
|
5030
5314
|
});
|
|
5031
5315
|
}
|
|
5032
|
-
return deps.createReplicateClient({ auth: token });
|
|
5033
|
-
}
|
|
5034
|
-
function refToUrl3(ref) {
|
|
5035
|
-
if ("url" in ref) return ref.url;
|
|
5036
|
-
return `data:${ref.mime};base64,${Buffer.from(ref.bytes).toString("base64")}`;
|
|
5316
|
+
return deps.createReplicateClient({ auth: token, fetch: ctx.fetch });
|
|
5037
5317
|
}
|
|
5038
5318
|
function route(providerModelId) {
|
|
5039
5319
|
if (providerModelId.includes(":")) {
|
|
@@ -5051,10 +5331,11 @@ function replicateError(cause, ctx) {
|
|
|
5051
5331
|
const info = describeThrown(cause);
|
|
5052
5332
|
const nested = replicateResponseStatusSchema.safeParse(cause);
|
|
5053
5333
|
const status = info.status ?? (nested.success ? nested.data.response?.status : void 0);
|
|
5054
|
-
return
|
|
5334
|
+
return classifyThrown("replicate", cause, ctx.model.id, { status, body: info.body });
|
|
5055
5335
|
}
|
|
5056
|
-
function
|
|
5057
|
-
|
|
5336
|
+
function baseModelId(providerModelId) {
|
|
5337
|
+
const colon = providerModelId.indexOf(":");
|
|
5338
|
+
return colon === -1 ? providerModelId : providerModelId.slice(0, colon);
|
|
5058
5339
|
}
|
|
5059
5340
|
function predictionErrorBody(cause) {
|
|
5060
5341
|
const parsed = JsonValueSchema.safeParse(cause);
|
|
@@ -5102,6 +5383,7 @@ function noOutput() {
|
|
|
5102
5383
|
});
|
|
5103
5384
|
}
|
|
5104
5385
|
async function runPrediction(ctx, input, deps) {
|
|
5386
|
+
throwIfAborted(ctx.signal);
|
|
5105
5387
|
const api = client(ctx, deps);
|
|
5106
5388
|
const createOptions = { ...route(ctx.model.providerModelId), input };
|
|
5107
5389
|
let prediction;
|
|
@@ -5109,12 +5391,14 @@ async function runPrediction(ctx, input, deps) {
|
|
|
5109
5391
|
prediction = await withRetry(
|
|
5110
5392
|
async () => {
|
|
5111
5393
|
try {
|
|
5112
|
-
return await api.predictions.create(
|
|
5394
|
+
return await api.predictions.create(
|
|
5395
|
+
ctx.signal ? { ...createOptions, signal: ctx.signal } : createOptions
|
|
5396
|
+
);
|
|
5113
5397
|
} catch (cause) {
|
|
5114
5398
|
throw replicateError(cause, ctx);
|
|
5115
5399
|
}
|
|
5116
5400
|
},
|
|
5117
|
-
|
|
5401
|
+
{ attempts: 1 }
|
|
5118
5402
|
);
|
|
5119
5403
|
} catch (cause) {
|
|
5120
5404
|
throw replicateError(cause, ctx);
|
|
@@ -5127,7 +5411,10 @@ async function runPrediction(ctx, input, deps) {
|
|
|
5127
5411
|
const done = await pollUntil(async () => {
|
|
5128
5412
|
let current;
|
|
5129
5413
|
try {
|
|
5130
|
-
current = await api.predictions.get(
|
|
5414
|
+
current = await api.predictions.get(
|
|
5415
|
+
prediction.id,
|
|
5416
|
+
ctx.signal ? { signal: ctx.signal } : void 0
|
|
5417
|
+
);
|
|
5131
5418
|
} catch (cause) {
|
|
5132
5419
|
throw replicateError(cause, ctx);
|
|
5133
5420
|
}
|
|
@@ -5194,21 +5481,32 @@ async function download(ctx, url) {
|
|
|
5194
5481
|
const mime = res.headers.get("content-type") ?? "image/png";
|
|
5195
5482
|
return { bytes: new Uint8Array(await res.arrayBuffer()), mime };
|
|
5196
5483
|
}
|
|
5197
|
-
|
|
5198
|
-
|
|
5199
|
-
|
|
5200
|
-
|
|
5201
|
-
|
|
5202
|
-
|
|
5203
|
-
}
|
|
5204
|
-
function
|
|
5205
|
-
return
|
|
5206
|
-
}
|
|
5207
|
-
|
|
5208
|
-
|
|
5484
|
+
var REPLICATE_IMAGE_KINDS = {
|
|
5485
|
+
"topazlabs/image-upscale": "topaz",
|
|
5486
|
+
"philz1337x/crystal-upscaler": "upscaler",
|
|
5487
|
+
"wan-video/wan-2.7-image-pro": "wan",
|
|
5488
|
+
"qwen/qwen-image-2-pro": "qwen-image",
|
|
5489
|
+
"qwen-edit-apps/qwen-image-edit-plus-lora-skin": "qwen-edit"
|
|
5490
|
+
};
|
|
5491
|
+
function imageKind(providerModelId) {
|
|
5492
|
+
return REPLICATE_IMAGE_KINDS[baseModelId(providerModelId)] ?? "generic";
|
|
5493
|
+
}
|
|
5494
|
+
var REPLICATE_VIDEO_KINDS = {
|
|
5495
|
+
"kling-video/v2.5-turbo/pro/image-to-video": "kling",
|
|
5496
|
+
"kling-video/v3.0/pro/image-to-video": "kling",
|
|
5497
|
+
"kwaivgi/kling-v3-video": "kling",
|
|
5498
|
+
"kwaivgi/kling-v3-omni-video": "kling-omni",
|
|
5499
|
+
"minimax/hailuo-02": "hailuo"
|
|
5500
|
+
};
|
|
5501
|
+
function videoKind(providerModelId) {
|
|
5502
|
+
return REPLICATE_VIDEO_KINDS[baseModelId(providerModelId)] ?? "wan";
|
|
5209
5503
|
}
|
|
5210
|
-
|
|
5211
|
-
|
|
5504
|
+
var REPLICATE_AUDIO_KINDS = {
|
|
5505
|
+
"zsxkib/mmaudio": "mmaudio",
|
|
5506
|
+
"elevenlabs/music": "elevenlabs"
|
|
5507
|
+
};
|
|
5508
|
+
function audioKind(providerModelId) {
|
|
5509
|
+
return REPLICATE_AUDIO_KINDS[baseModelId(providerModelId)] ?? "lyria";
|
|
5212
5510
|
}
|
|
5213
5511
|
var QWEN_IMAGE_RATIOS = /* @__PURE__ */ new Set([
|
|
5214
5512
|
"1:1",
|
|
@@ -5251,87 +5549,113 @@ function wanImageSize(aspectRatio, size) {
|
|
|
5251
5549
|
async function generateReplicateImage(req, ctx, deps) {
|
|
5252
5550
|
const id = ctx.model.providerModelId;
|
|
5253
5551
|
let input;
|
|
5254
|
-
|
|
5255
|
-
|
|
5256
|
-
|
|
5257
|
-
|
|
5258
|
-
|
|
5259
|
-
|
|
5260
|
-
|
|
5261
|
-
|
|
5262
|
-
|
|
5263
|
-
|
|
5552
|
+
switch (imageKind(id)) {
|
|
5553
|
+
case "topaz": {
|
|
5554
|
+
const first = (req.references ?? [])[0];
|
|
5555
|
+
if (!first) {
|
|
5556
|
+
throw new ModelKitError({
|
|
5557
|
+
code: "missing_input",
|
|
5558
|
+
message: `${ctx.model.id} requires a reference image to upscale`,
|
|
5559
|
+
provider: "replicate",
|
|
5560
|
+
model: ctx.model.id,
|
|
5561
|
+
retryable: false
|
|
5562
|
+
});
|
|
5563
|
+
}
|
|
5564
|
+
let format = req.outputFormat === "jpeg" ? "jpg" : req.outputFormat ?? "png";
|
|
5565
|
+
if (format !== "png" && format !== "jpg") {
|
|
5566
|
+
ctx.warnings.push({
|
|
5567
|
+
code: "option_ignored",
|
|
5568
|
+
field: "outputFormat",
|
|
5569
|
+
from: format,
|
|
5570
|
+
message: "topazlabs/image-upscale supports only png and jpg; using png"
|
|
5571
|
+
});
|
|
5572
|
+
format = "png";
|
|
5573
|
+
}
|
|
5574
|
+
const upscale = req.upscale;
|
|
5575
|
+
const topaz = {
|
|
5576
|
+
image: refToUrl(first),
|
|
5577
|
+
enhance_model: upscale?.enhanceModel ?? "Standard V2",
|
|
5578
|
+
output_format: format,
|
|
5579
|
+
upscale_factor: `${req.scaleFactor ?? 2}x`,
|
|
5580
|
+
face_enhancement: upscale?.faceEnhancement ?? false
|
|
5581
|
+
};
|
|
5582
|
+
if (upscale?.subjectDetection !== void 0)
|
|
5583
|
+
topaz.subject_detection = upscale.subjectDetection;
|
|
5584
|
+
if (upscale?.faceEnhancementCreativity !== void 0)
|
|
5585
|
+
topaz.face_enhancement_creativity = upscale.faceEnhancementCreativity;
|
|
5586
|
+
if (upscale?.faceEnhancementStrength !== void 0)
|
|
5587
|
+
topaz.face_enhancement_strength = upscale.faceEnhancementStrength;
|
|
5588
|
+
input = topaz;
|
|
5589
|
+
break;
|
|
5264
5590
|
}
|
|
5265
|
-
|
|
5266
|
-
|
|
5267
|
-
|
|
5268
|
-
|
|
5269
|
-
|
|
5270
|
-
|
|
5271
|
-
|
|
5272
|
-
|
|
5273
|
-
|
|
5591
|
+
case "upscaler": {
|
|
5592
|
+
const first = (req.references ?? [])[0];
|
|
5593
|
+
if (!first) {
|
|
5594
|
+
throw new ModelKitError({
|
|
5595
|
+
code: "missing_input",
|
|
5596
|
+
message: `${ctx.model.id} requires a reference image to upscale`,
|
|
5597
|
+
provider: "replicate",
|
|
5598
|
+
model: ctx.model.id,
|
|
5599
|
+
retryable: false
|
|
5600
|
+
});
|
|
5601
|
+
}
|
|
5602
|
+
const imageInput = { prompt: req.prompt };
|
|
5603
|
+
imageInput.image = refToUrl(first);
|
|
5604
|
+
imageInput.creativity = 0;
|
|
5605
|
+
imageInput.scale_factor = 2;
|
|
5606
|
+
imageInput.output_format = "png";
|
|
5607
|
+
input = imageInput;
|
|
5608
|
+
break;
|
|
5274
5609
|
}
|
|
5275
|
-
|
|
5276
|
-
|
|
5277
|
-
|
|
5278
|
-
|
|
5279
|
-
|
|
5280
|
-
|
|
5281
|
-
|
|
5282
|
-
} else if (isUpscaler(id)) {
|
|
5283
|
-
const refs = req.references ?? [];
|
|
5284
|
-
const first = refs[0];
|
|
5285
|
-
if (!first) {
|
|
5286
|
-
throw new ModelKitError({
|
|
5287
|
-
code: "missing_input",
|
|
5288
|
-
message: `${ctx.model.id} requires a reference image to upscale`,
|
|
5289
|
-
provider: "replicate",
|
|
5290
|
-
model: ctx.model.id,
|
|
5291
|
-
retryable: false
|
|
5292
|
-
});
|
|
5610
|
+
case "wan": {
|
|
5611
|
+
const refs = (req.references ?? []).map(refToUrl);
|
|
5612
|
+
const imageInput = { prompt: req.prompt };
|
|
5613
|
+
if (refs.length > 0) imageInput.images = refs;
|
|
5614
|
+
imageInput.size = wanImageSize(req.aspectRatio, req.size);
|
|
5615
|
+
input = imageInput;
|
|
5616
|
+
break;
|
|
5293
5617
|
}
|
|
5294
|
-
|
|
5295
|
-
|
|
5296
|
-
|
|
5297
|
-
|
|
5298
|
-
|
|
5299
|
-
|
|
5300
|
-
|
|
5301
|
-
|
|
5302
|
-
|
|
5303
|
-
|
|
5304
|
-
|
|
5305
|
-
|
|
5306
|
-
} else if (isQwen(id)) {
|
|
5307
|
-
const refs = (req.references ?? []).map(refToUrl3);
|
|
5308
|
-
const firstUrl = refs[0];
|
|
5309
|
-
const imageInput = { prompt: req.prompt };
|
|
5310
|
-
if (firstUrl !== void 0) {
|
|
5311
|
-
imageInput.image = firstUrl;
|
|
5312
|
-
if (!isQwenEditPlus(id)) imageInput.match_input_image = true;
|
|
5618
|
+
case "qwen-image": {
|
|
5619
|
+
const refs = (req.references ?? []).map(refToUrl);
|
|
5620
|
+
const firstUrl = refs[0];
|
|
5621
|
+
const imageInput = { prompt: req.prompt };
|
|
5622
|
+
if (firstUrl !== void 0) {
|
|
5623
|
+
imageInput.image = firstUrl;
|
|
5624
|
+
imageInput.match_input_image = true;
|
|
5625
|
+
} else if (req.aspectRatio !== void 0 && QWEN_IMAGE_RATIOS.has(req.aspectRatio)) {
|
|
5626
|
+
imageInput.aspect_ratio = req.aspectRatio;
|
|
5627
|
+
}
|
|
5628
|
+
input = imageInput;
|
|
5629
|
+
break;
|
|
5313
5630
|
}
|
|
5314
|
-
|
|
5315
|
-
|
|
5316
|
-
|
|
5317
|
-
|
|
5318
|
-
|
|
5319
|
-
|
|
5320
|
-
|
|
5321
|
-
|
|
5322
|
-
|
|
5323
|
-
|
|
5631
|
+
case "qwen-edit": {
|
|
5632
|
+
const refs = (req.references ?? []).map(refToUrl);
|
|
5633
|
+
const firstUrl = refs[0];
|
|
5634
|
+
const imageInput = { prompt: req.prompt };
|
|
5635
|
+
if (firstUrl !== void 0) imageInput.image = firstUrl;
|
|
5636
|
+
if (req.aspectRatio !== void 0) {
|
|
5637
|
+
if (QWEN_EDIT_RATIOS.has(req.aspectRatio))
|
|
5638
|
+
imageInput.aspect_ratio = req.aspectRatio;
|
|
5639
|
+
else
|
|
5640
|
+
ctx.warnings.push({
|
|
5641
|
+
code: "option_ignored",
|
|
5642
|
+
field: "aspectRatio",
|
|
5643
|
+
from: req.aspectRatio,
|
|
5644
|
+
message: `${id} has no ${req.aspectRatio} aspect_ratio; using the provider default`
|
|
5645
|
+
});
|
|
5646
|
+
}
|
|
5647
|
+
if (req.outputFormat !== void 0) {
|
|
5648
|
+
imageInput.output_format = req.outputFormat === "jpeg" ? "jpg" : req.outputFormat;
|
|
5649
|
+
}
|
|
5650
|
+
input = imageInput;
|
|
5651
|
+
break;
|
|
5324
5652
|
}
|
|
5325
|
-
|
|
5326
|
-
|
|
5653
|
+
default: {
|
|
5654
|
+
const first = (req.references ?? [])[0];
|
|
5655
|
+
const imageInput = { prompt: req.prompt };
|
|
5656
|
+
if (first) imageInput.image = refToUrl(first);
|
|
5657
|
+
input = imageInput;
|
|
5327
5658
|
}
|
|
5328
|
-
input = imageInput;
|
|
5329
|
-
} else {
|
|
5330
|
-
const refs = req.references ?? [];
|
|
5331
|
-
const first = refs[0];
|
|
5332
|
-
const imageInput = { prompt: req.prompt };
|
|
5333
|
-
if (first) imageInput.image = refToUrl3(first);
|
|
5334
|
-
input = imageInput;
|
|
5335
5659
|
}
|
|
5336
5660
|
const { url, predictTime, raw } = await runPrediction(ctx, input, deps);
|
|
5337
5661
|
const file = await download(ctx, url);
|
|
@@ -5348,8 +5672,8 @@ function wanSize(aspectRatio) {
|
|
|
5348
5672
|
return w > h ? "2048*1152" : "1536*2048";
|
|
5349
5673
|
}
|
|
5350
5674
|
function klingInput(req) {
|
|
5351
|
-
const images = (req.firstFrame ? [req.firstFrame] : []).map(
|
|
5352
|
-
if (req.lastFrame) images.push(
|
|
5675
|
+
const images = (req.firstFrame ? [req.firstFrame] : []).map(refToUrl);
|
|
5676
|
+
if (req.lastFrame) images.push(refToUrl(req.lastFrame));
|
|
5353
5677
|
const input = {
|
|
5354
5678
|
prompt: req.prompt,
|
|
5355
5679
|
duration: req.durationSeconds ?? 10,
|
|
@@ -5361,19 +5685,24 @@ function klingInput(req) {
|
|
|
5361
5685
|
input.start_image = startImage;
|
|
5362
5686
|
const endImage = images[1];
|
|
5363
5687
|
if (endImage !== void 0) input.end_image = endImage;
|
|
5364
|
-
} else {
|
|
5688
|
+
} else if (req.aspectRatio !== "adaptive") {
|
|
5365
5689
|
input.aspect_ratio = req.aspectRatio ?? "16:9";
|
|
5366
5690
|
}
|
|
5367
5691
|
if (req.negativePrompt !== void 0) input.negative_prompt = req.negativePrompt;
|
|
5368
5692
|
return input;
|
|
5369
5693
|
}
|
|
5694
|
+
function klingOmniMode(req) {
|
|
5695
|
+
if (req.resolution === "1080p") return "pro";
|
|
5696
|
+
if (req.resolution === "720p") return "standard";
|
|
5697
|
+
return req.mode ?? "standard";
|
|
5698
|
+
}
|
|
5370
5699
|
function klingOmniInput(req) {
|
|
5371
|
-
const images = (req.firstFrame ? [req.firstFrame] : []).map(
|
|
5372
|
-
if (req.lastFrame) images.push(
|
|
5700
|
+
const images = (req.firstFrame ? [req.firstFrame] : []).map(refToUrl);
|
|
5701
|
+
if (req.lastFrame) images.push(refToUrl(req.lastFrame));
|
|
5373
5702
|
const input = {
|
|
5374
5703
|
prompt: req.prompt,
|
|
5375
5704
|
duration: req.durationSeconds ?? 10,
|
|
5376
|
-
mode: req
|
|
5705
|
+
mode: klingOmniMode(req),
|
|
5377
5706
|
generate_audio: req.generateAudio ?? false
|
|
5378
5707
|
};
|
|
5379
5708
|
const startImage = images[0];
|
|
@@ -5381,10 +5710,10 @@ function klingOmniInput(req) {
|
|
|
5381
5710
|
input.start_image = startImage;
|
|
5382
5711
|
const endImage = images[1];
|
|
5383
5712
|
if (endImage !== void 0) input.end_image = endImage;
|
|
5384
|
-
} else {
|
|
5713
|
+
} else if (req.aspectRatio !== "adaptive") {
|
|
5385
5714
|
input.aspect_ratio = req.aspectRatio ?? "16:9";
|
|
5386
5715
|
}
|
|
5387
|
-
const refs = (req.referenceImages ?? []).map(
|
|
5716
|
+
const refs = (req.referenceImages ?? []).map(refToUrl);
|
|
5388
5717
|
if (refs.length > 0) input.reference_images = refs;
|
|
5389
5718
|
return input;
|
|
5390
5719
|
}
|
|
@@ -5395,8 +5724,8 @@ function hailuoInput(req) {
|
|
|
5395
5724
|
resolution: req.resolution ?? "768p",
|
|
5396
5725
|
prompt_optimizer: true
|
|
5397
5726
|
};
|
|
5398
|
-
if (req.firstFrame) input.first_frame_image =
|
|
5399
|
-
if (req.lastFrame) input.last_frame_image =
|
|
5727
|
+
if (req.firstFrame) input.first_frame_image = refToUrl(req.firstFrame);
|
|
5728
|
+
if (req.lastFrame) input.last_frame_image = refToUrl(req.lastFrame);
|
|
5400
5729
|
return input;
|
|
5401
5730
|
}
|
|
5402
5731
|
function wanInput(req) {
|
|
@@ -5405,12 +5734,13 @@ function wanInput(req) {
|
|
|
5405
5734
|
duration: req.durationSeconds ?? 5,
|
|
5406
5735
|
size: wanSize(req.aspectRatio)
|
|
5407
5736
|
};
|
|
5408
|
-
if (req.firstFrame) input.image =
|
|
5737
|
+
if (req.firstFrame) input.image = refToUrl(req.firstFrame);
|
|
5409
5738
|
return input;
|
|
5410
5739
|
}
|
|
5411
5740
|
async function generateReplicateVideo(req, ctx, deps) {
|
|
5412
|
-
|
|
5413
|
-
const
|
|
5741
|
+
throwIfAborted(ctx.signal);
|
|
5742
|
+
const kind = videoKind(ctx.model.providerModelId);
|
|
5743
|
+
const input = kind === "kling" ? klingInput(req) : kind === "kling-omni" ? klingOmniInput(req) : kind === "hailuo" ? hailuoInput(req) : wanInput(req);
|
|
5414
5744
|
const api = client(ctx, deps);
|
|
5415
5745
|
const createOptions = { ...route(ctx.model.providerModelId), input };
|
|
5416
5746
|
let prediction;
|
|
@@ -5418,12 +5748,14 @@ async function generateReplicateVideo(req, ctx, deps) {
|
|
|
5418
5748
|
prediction = await withRetry(
|
|
5419
5749
|
async () => {
|
|
5420
5750
|
try {
|
|
5421
|
-
return await api.predictions.create(
|
|
5751
|
+
return await api.predictions.create(
|
|
5752
|
+
ctx.signal ? { ...createOptions, signal: ctx.signal } : createOptions
|
|
5753
|
+
);
|
|
5422
5754
|
} catch (cause) {
|
|
5423
5755
|
throw replicateError(cause, ctx);
|
|
5424
5756
|
}
|
|
5425
5757
|
},
|
|
5426
|
-
|
|
5758
|
+
{ attempts: 1 }
|
|
5427
5759
|
);
|
|
5428
5760
|
} catch (cause) {
|
|
5429
5761
|
throw replicateError(cause, ctx);
|
|
@@ -5432,7 +5764,10 @@ async function generateReplicateVideo(req, ctx, deps) {
|
|
|
5432
5764
|
const check = async () => {
|
|
5433
5765
|
let current;
|
|
5434
5766
|
try {
|
|
5435
|
-
current = await api.predictions.get(
|
|
5767
|
+
current = await api.predictions.get(
|
|
5768
|
+
jobId,
|
|
5769
|
+
ctx.signal ? { signal: ctx.signal } : void 0
|
|
5770
|
+
);
|
|
5436
5771
|
} catch (cause) {
|
|
5437
5772
|
throw replicateError(cause, ctx);
|
|
5438
5773
|
}
|
|
@@ -5533,7 +5868,7 @@ function mmaudioInput(req, ctx) {
|
|
|
5533
5868
|
});
|
|
5534
5869
|
}
|
|
5535
5870
|
const input = {
|
|
5536
|
-
video:
|
|
5871
|
+
video: refToUrl(video),
|
|
5537
5872
|
duration: req.durationSeconds ?? 8,
|
|
5538
5873
|
seed: req.seed ?? -1
|
|
5539
5874
|
};
|
|
@@ -5552,8 +5887,8 @@ function predictionRaw(prediction) {
|
|
|
5552
5887
|
return raw;
|
|
5553
5888
|
}
|
|
5554
5889
|
async function generateReplicateAudio(req, ctx, deps) {
|
|
5555
|
-
const
|
|
5556
|
-
const input =
|
|
5890
|
+
const kind = audioKind(ctx.model.providerModelId);
|
|
5891
|
+
const input = kind === "mmaudio" ? mmaudioInput(req, ctx) : kind === "elevenlabs" ? elevenLabsMusicInput(req, ctx) : lyriaAudioInput(req, ctx);
|
|
5557
5892
|
const { url, predictTime, raw } = await runPrediction(ctx, input, deps);
|
|
5558
5893
|
const usage2 = audioUsage(ctx, req);
|
|
5559
5894
|
if (ctx.model.usage.unit === "seconds") {
|
|
@@ -5582,19 +5917,14 @@ function createXaiVideoAdapter(deps = defaultXaiDeps) {
|
|
|
5582
5917
|
};
|
|
5583
5918
|
}
|
|
5584
5919
|
var xaiVideoAdapter = createXaiVideoAdapter();
|
|
5585
|
-
function refToUrl4(ref) {
|
|
5586
|
-
if ("url" in ref) return ref.url;
|
|
5587
|
-
return `data:${ref.mime};base64,${Buffer.from(ref.bytes).toString("base64")}`;
|
|
5588
|
-
}
|
|
5589
5920
|
var xaiResponseStatusSchema = z13.object({
|
|
5590
5921
|
response: z13.object({ status: z13.number() }).partial()
|
|
5591
5922
|
});
|
|
5592
5923
|
function xaiError(cause, ctx) {
|
|
5593
|
-
if (isModelKitError(cause)) return cause;
|
|
5594
5924
|
const info = describeThrown(cause);
|
|
5595
5925
|
const nested = xaiResponseStatusSchema.safeParse(cause);
|
|
5596
5926
|
const status = info.status ?? (nested.success ? nested.data.response?.status : void 0);
|
|
5597
|
-
return
|
|
5927
|
+
return classifyThrown("xai-video", cause, ctx.model.id, { status, body: info.body });
|
|
5598
5928
|
}
|
|
5599
5929
|
var xaiMetaSchema = z13.object({
|
|
5600
5930
|
videoUrl: JsonValueSchema.optional(),
|
|
@@ -5618,27 +5948,35 @@ async function generateXaiVideo(req, ctx, deps) {
|
|
|
5618
5948
|
retryable: false
|
|
5619
5949
|
});
|
|
5620
5950
|
}
|
|
5621
|
-
const
|
|
5622
|
-
(r) => r !== void 0
|
|
5623
|
-
);
|
|
5624
|
-
const refUrls = frames.map(refToUrl4).slice(0, 5);
|
|
5625
|
-
const resolution = req.resolution === "480p" ? "480p" : "720p";
|
|
5951
|
+
const refUrls = (req.referenceImages ?? []).map(refToUrl).slice(0, 7);
|
|
5626
5952
|
const xaiOptions = {
|
|
5627
|
-
resolution,
|
|
5628
5953
|
pollIntervalMs: POLL_INTERVAL_MS2,
|
|
5629
5954
|
pollTimeoutMs: POLL_TIMEOUT_MS2
|
|
5630
5955
|
};
|
|
5956
|
+
if (req.resolution === "480p" || req.resolution === "720p" || req.resolution === "1080p") {
|
|
5957
|
+
xaiOptions.resolution = req.resolution;
|
|
5958
|
+
}
|
|
5631
5959
|
if (refUrls.length > 0) {
|
|
5632
5960
|
xaiOptions.mode = "reference-to-video";
|
|
5633
5961
|
xaiOptions.referenceImageUrls = refUrls;
|
|
5634
5962
|
}
|
|
5963
|
+
if (req.lastFrame !== void 0) {
|
|
5964
|
+
ctx.warnings.push({
|
|
5965
|
+
code: "option_ignored",
|
|
5966
|
+
field: "lastFrame",
|
|
5967
|
+
message: "xai-video does not support lastFrame; ignored"
|
|
5968
|
+
});
|
|
5969
|
+
}
|
|
5635
5970
|
const client2 = deps.createXaiClient({ apiKey });
|
|
5636
|
-
const model = createXai2({ apiKey }).video(ctx.model.providerModelId);
|
|
5971
|
+
const model = createXai2({ apiKey, fetch: ctx.fetch }).video(ctx.model.providerModelId);
|
|
5637
5972
|
const callBody = {
|
|
5638
5973
|
model,
|
|
5639
5974
|
prompt: req.prompt,
|
|
5640
5975
|
providerOptions: { xai: xaiOptions }
|
|
5641
5976
|
};
|
|
5977
|
+
if (req.firstFrame) {
|
|
5978
|
+
callBody.frameImages = [{ image: refToUrl(req.firstFrame), frameType: "first_frame" }];
|
|
5979
|
+
}
|
|
5642
5980
|
if (req.aspectRatio !== void 0 && req.aspectRatio !== "adaptive") {
|
|
5643
5981
|
callBody.aspectRatio = req.aspectRatio;
|
|
5644
5982
|
}
|
|
@@ -5673,7 +6011,8 @@ async function generateXaiVideo(req, ctx, deps) {
|
|
|
5673
6011
|
return settled;
|
|
5674
6012
|
};
|
|
5675
6013
|
return {
|
|
5676
|
-
|
|
6014
|
+
// xAI exposes no request id on the synchronous handle, so each job gets a fresh one.
|
|
6015
|
+
jobId: crypto.randomUUID(),
|
|
5677
6016
|
async poll() {
|
|
5678
6017
|
if (failed !== void 0) return { status: "failed" };
|
|
5679
6018
|
return settled ? { status: "succeeded" } : { status: "pending" };
|
|
@@ -5724,26 +6063,14 @@ async function mapResult(ctx, req, result) {
|
|
|
5724
6063
|
function usage(ctx, req, meta) {
|
|
5725
6064
|
const costTicks = z13.number().safeParse(meta.costInUsdTicks);
|
|
5726
6065
|
const cost = costTicks.success ? costTicks.data / 1e10 : void 0;
|
|
5727
|
-
if (cost !== void 0) {
|
|
5728
|
-
const event2 = {
|
|
5729
|
-
model: ctx.model.id,
|
|
5730
|
-
provider: "xai-video",
|
|
5731
|
-
modality: "VIDEO",
|
|
5732
|
-
unit: "reported_cost_usd",
|
|
5733
|
-
quantity: cost,
|
|
5734
|
-
reportedCostUsd: cost
|
|
5735
|
-
};
|
|
5736
|
-
if (req.durationSeconds !== void 0) event2.durationSeconds = req.durationSeconds;
|
|
5737
|
-
if (req.resolution !== void 0) event2.resolution = req.resolution;
|
|
5738
|
-
return event2;
|
|
5739
|
-
}
|
|
5740
6066
|
const event = {
|
|
5741
6067
|
model: ctx.model.id,
|
|
5742
6068
|
provider: "xai-video",
|
|
5743
6069
|
modality: "VIDEO",
|
|
5744
|
-
unit: "
|
|
5745
|
-
quantity:
|
|
6070
|
+
unit: "reported_cost_usd",
|
|
6071
|
+
quantity: cost ?? 0
|
|
5746
6072
|
};
|
|
6073
|
+
if (cost !== void 0) event.reportedCostUsd = cost;
|
|
5747
6074
|
if (req.durationSeconds !== void 0) event.durationSeconds = req.durationSeconds;
|
|
5748
6075
|
if (req.resolution !== void 0) event.resolution = req.resolution;
|
|
5749
6076
|
return event;
|
|
@@ -5819,6 +6146,7 @@ export {
|
|
|
5819
6146
|
prodiaAdapter,
|
|
5820
6147
|
readErrorBody,
|
|
5821
6148
|
replicateAdapter,
|
|
6149
|
+
resolveAudioOptions,
|
|
5822
6150
|
resolveImageOptions,
|
|
5823
6151
|
resolveKeys,
|
|
5824
6152
|
resolveVideoOptions,
|