@shop-os/modelkit 0.6.1 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/README.md +3 -3
- package/dist/catalog.cjs +210 -48
- package/dist/catalog.cjs.map +1 -1
- package/dist/catalog.d.cts +6 -3
- package/dist/catalog.d.ts +6 -3
- package/dist/catalog.js +210 -48
- package/dist/catalog.js.map +1 -1
- package/dist/index.cjs +862 -92
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +10 -5
- package/dist/index.d.ts +10 -5
- package/dist/index.js +861 -92
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -375,8 +375,59 @@ var FAL_IMAGE_MODELS = [
|
|
|
375
375
|
}
|
|
376
376
|
];
|
|
377
377
|
|
|
378
|
-
// src/catalog/image.ts
|
|
378
|
+
// src/catalog/image-luma.ts
|
|
379
379
|
var IMAGE_USAGE2 = { unit: "images" };
|
|
380
|
+
var EXPOSURE2 = ["cowork", "space_builder"];
|
|
381
|
+
var LOBE2 = "https://cdn.jsdelivr.net/npm/@lobehub/icons-static-png@1.97.0/light";
|
|
382
|
+
var LUMA_LOGO = `${LOBE2}/luma-color.png`;
|
|
383
|
+
var UNI_RATIOS = ["adaptive", "16:9", "3:2", "1:1", "2:3", "9:16"];
|
|
384
|
+
function uniImage(id, label, providerModelId, description) {
|
|
385
|
+
return {
|
|
386
|
+
// https://docs.agents.lumalabs.ai: type "image" without references, else
|
|
387
|
+
// "image_edit" with the first reference as source and up to 8 more as
|
|
388
|
+
// image_ref. The output is always 2048 px on the long side.
|
|
389
|
+
id,
|
|
390
|
+
aliases: [],
|
|
391
|
+
label,
|
|
392
|
+
type: "image",
|
|
393
|
+
adapter: "luma",
|
|
394
|
+
providerModelId,
|
|
395
|
+
lifecycle: "active",
|
|
396
|
+
exposure: EXPOSURE2,
|
|
397
|
+
constraints: {
|
|
398
|
+
aspectRatios: [...UNI_RATIOS],
|
|
399
|
+
sizes: ["2K"],
|
|
400
|
+
references: { images: 9 },
|
|
401
|
+
supports: ["outputFormat"],
|
|
402
|
+
prompt: { referenceSyntax: "numbered", maxChars: 6e3 }
|
|
403
|
+
},
|
|
404
|
+
defaults: { size: "2K", aspectRatio: "adaptive" },
|
|
405
|
+
usage: { ...IMAGE_USAGE2 },
|
|
406
|
+
pricingKind: "image_size",
|
|
407
|
+
display: {
|
|
408
|
+
provider: "luma",
|
|
409
|
+
description,
|
|
410
|
+
logo: LUMA_LOGO
|
|
411
|
+
}
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
var LUMA_IMAGE_MODELS = [
|
|
415
|
+
uniImage(
|
|
416
|
+
"uni-1",
|
|
417
|
+
"Uni-1",
|
|
418
|
+
"uni-1",
|
|
419
|
+
"Luma Uni-1 fast image generation and editing; takes a prompt and up to 9 reference images and outputs 2K."
|
|
420
|
+
),
|
|
421
|
+
uniImage(
|
|
422
|
+
"uni-1-max",
|
|
423
|
+
"Uni-1 Max",
|
|
424
|
+
"uni-1-max",
|
|
425
|
+
"Luma Uni-1 Max higher-quality image generation and editing; takes a prompt and up to 9 reference images and outputs 2K."
|
|
426
|
+
)
|
|
427
|
+
];
|
|
428
|
+
|
|
429
|
+
// src/catalog/image.ts
|
|
430
|
+
var IMAGE_USAGE3 = { unit: "images" };
|
|
380
431
|
var GEMINI_RATIOS = [
|
|
381
432
|
"1:1",
|
|
382
433
|
"2:3",
|
|
@@ -421,7 +472,7 @@ function geminiImage(id, label, aliases, sizes, display, exposure, references, p
|
|
|
421
472
|
exposure,
|
|
422
473
|
constraints,
|
|
423
474
|
defaults: { size: "1K", aspectRatio: "1:1" },
|
|
424
|
-
usage: { ...
|
|
475
|
+
usage: { ...IMAGE_USAGE3, slug: "gemini" },
|
|
425
476
|
pricingKind: "image_size",
|
|
426
477
|
display
|
|
427
478
|
};
|
|
@@ -534,7 +585,7 @@ var IMAGE_MODELS = [
|
|
|
534
585
|
prompt: GPT_IMAGE_PROMPT
|
|
535
586
|
},
|
|
536
587
|
defaults: { size: "1K", aspectRatio: "adaptive", quality: "auto" },
|
|
537
|
-
usage: { ...
|
|
588
|
+
usage: { ...IMAGE_USAGE3, slug: "gpt" },
|
|
538
589
|
pricingKind: "image_size",
|
|
539
590
|
display: {
|
|
540
591
|
provider: "openai",
|
|
@@ -570,7 +621,7 @@ var IMAGE_MODELS = [
|
|
|
570
621
|
prompt: GPT_IMAGE_PROMPT
|
|
571
622
|
},
|
|
572
623
|
defaults: { size: "1K", aspectRatio: "adaptive", quality: "auto" },
|
|
573
|
-
usage: { ...
|
|
624
|
+
usage: { ...IMAGE_USAGE3 },
|
|
574
625
|
pricingKind: "image_size",
|
|
575
626
|
display: {
|
|
576
627
|
provider: "openai",
|
|
@@ -605,7 +656,7 @@ var IMAGE_MODELS = [
|
|
|
605
656
|
prompt: GPT_IMAGE_PROMPT
|
|
606
657
|
},
|
|
607
658
|
defaults: { size: "1K", aspectRatio: "adaptive", quality: "auto" },
|
|
608
|
-
usage: { ...
|
|
659
|
+
usage: { ...IMAGE_USAGE3 },
|
|
609
660
|
pricingKind: "image_size",
|
|
610
661
|
display: {
|
|
611
662
|
provider: "openai",
|
|
@@ -640,7 +691,7 @@ var IMAGE_MODELS = [
|
|
|
640
691
|
supports: ["count", "outputFormat"]
|
|
641
692
|
},
|
|
642
693
|
defaults: { size: "1K", aspectRatio: "1:1", outputFormat: "png", count: 1 },
|
|
643
|
-
usage: { ...
|
|
694
|
+
usage: { ...IMAGE_USAGE3, slug: "muse" },
|
|
644
695
|
pricingKind: "image_size",
|
|
645
696
|
display: {
|
|
646
697
|
provider: "meta",
|
|
@@ -667,7 +718,7 @@ var IMAGE_MODELS = [
|
|
|
667
718
|
supports: ["quality", "count", "seed"]
|
|
668
719
|
},
|
|
669
720
|
defaults: { size: "2K", aspectRatio: "1:1", quality: "medium", count: 1 },
|
|
670
|
-
usage: { ...
|
|
721
|
+
usage: { ...IMAGE_USAGE3, slug: "ideogram" },
|
|
671
722
|
pricingKind: "image_size",
|
|
672
723
|
display: {
|
|
673
724
|
provider: "ideogram",
|
|
@@ -692,7 +743,7 @@ var IMAGE_MODELS = [
|
|
|
692
743
|
supports: ["seed", "outputFormat"]
|
|
693
744
|
},
|
|
694
745
|
defaults: { size: "1K", aspectRatio: "1:1" },
|
|
695
|
-
usage: { ...
|
|
746
|
+
usage: { ...IMAGE_USAGE3 },
|
|
696
747
|
pricingKind: "image_size",
|
|
697
748
|
display: {
|
|
698
749
|
provider: "bytedance",
|
|
@@ -730,7 +781,7 @@ var IMAGE_MODELS = [
|
|
|
730
781
|
supports: ["seed"]
|
|
731
782
|
},
|
|
732
783
|
defaults: { size: "1K", aspectRatio: "1:1" },
|
|
733
|
-
usage: { ...
|
|
784
|
+
usage: { ...IMAGE_USAGE3 },
|
|
734
785
|
pricingKind: "image_size",
|
|
735
786
|
display: {
|
|
736
787
|
provider: "bytedance",
|
|
@@ -756,7 +807,7 @@ var IMAGE_MODELS = [
|
|
|
756
807
|
prompt: { referenceSyntax: "numbered", maxChars: 32768 }
|
|
757
808
|
},
|
|
758
809
|
defaults: { size: "1K", aspectRatio: "1:1" },
|
|
759
|
-
usage: { ...
|
|
810
|
+
usage: { ...IMAGE_USAGE3 },
|
|
760
811
|
pricingKind: "image_size",
|
|
761
812
|
display: {
|
|
762
813
|
provider: "black-forest-labs",
|
|
@@ -783,7 +834,7 @@ var IMAGE_MODELS = [
|
|
|
783
834
|
supports: []
|
|
784
835
|
},
|
|
785
836
|
defaults: { size: "1K", aspectRatio: "1:1" },
|
|
786
|
-
usage: { ...
|
|
837
|
+
usage: { ...IMAGE_USAGE3 },
|
|
787
838
|
pricingKind: "image_size",
|
|
788
839
|
display: {
|
|
789
840
|
provider: "google",
|
|
@@ -808,7 +859,7 @@ var IMAGE_MODELS = [
|
|
|
808
859
|
supports: []
|
|
809
860
|
},
|
|
810
861
|
defaults: { size: "1K", aspectRatio: "1:1" },
|
|
811
|
-
usage: { ...
|
|
862
|
+
usage: { ...IMAGE_USAGE3 },
|
|
812
863
|
pricingKind: "image_size",
|
|
813
864
|
display: {
|
|
814
865
|
provider: "google",
|
|
@@ -894,7 +945,8 @@ var IMAGE_MODELS = [
|
|
|
894
945
|
description: "Alibaba Qwen Image Edit Plus with Lightning and a skin-retouching LoRA; takes one or more reference images plus an edit prompt and outputs webp, jpg, or png."
|
|
895
946
|
}
|
|
896
947
|
},
|
|
897
|
-
...FAL_IMAGE_MODELS
|
|
948
|
+
...FAL_IMAGE_MODELS,
|
|
949
|
+
...LUMA_IMAGE_MODELS
|
|
898
950
|
];
|
|
899
951
|
|
|
900
952
|
// src/catalog/audio-formats.ts
|
|
@@ -1090,7 +1142,7 @@ var VEED_SUBTITLE_LANGUAGES = [
|
|
|
1090
1142
|
];
|
|
1091
1143
|
|
|
1092
1144
|
// src/catalog/canvas-tools.ts
|
|
1093
|
-
var
|
|
1145
|
+
var EXPOSURE3 = ["cowork", "space_builder"];
|
|
1094
1146
|
var META_LOGO = "https://d31vvfpk2ppdyq.cloudfront.net/assets/characters/1787909065794-k9a7zz.png";
|
|
1095
1147
|
var VEED_SUBTITLE_PRESETS = [
|
|
1096
1148
|
"simple",
|
|
@@ -1132,7 +1184,7 @@ var SAM_3_IMAGE = {
|
|
|
1132
1184
|
adapter: "fal",
|
|
1133
1185
|
providerModelId: "fal-ai/sam-3/image",
|
|
1134
1186
|
lifecycle: "active",
|
|
1135
|
-
exposure:
|
|
1187
|
+
exposure: EXPOSURE3,
|
|
1136
1188
|
constraints: {
|
|
1137
1189
|
references: { images: 1 },
|
|
1138
1190
|
requires: ["references"],
|
|
@@ -1155,7 +1207,7 @@ var VEED_SUBTITLES = {
|
|
|
1155
1207
|
adapter: "fal",
|
|
1156
1208
|
providerModelId: "veed/subtitles",
|
|
1157
1209
|
lifecycle: "active",
|
|
1158
|
-
exposure:
|
|
1210
|
+
exposure: EXPOSURE3,
|
|
1159
1211
|
constraints: {
|
|
1160
1212
|
supports: [],
|
|
1161
1213
|
// fal: up to 2 hours at 1080p or below, 1 hour above.
|
|
@@ -3260,7 +3312,7 @@ var GOOGLE_LOGO = "https://d31vvfpk2ppdyq.cloudfront.net/assets/image/192485d2-a
|
|
|
3260
3312
|
var MINIMAX_LOGO = "https://d31vvfpk2ppdyq.cloudfront.net/assets/image/f4c2e906-28b7-4a4a-b491-df8fef7808ed.png";
|
|
3261
3313
|
var SYNC_LOGO = "https://cdn.jsdelivr.net/npm/@lobehub/icons-static-png@1.97.0/light/sync.png";
|
|
3262
3314
|
var PER_CALL = { unit: "images" };
|
|
3263
|
-
var
|
|
3315
|
+
var EXPOSURE4 = ["cowork", "space_builder"];
|
|
3264
3316
|
var LIPSYNC_AUDIO = { audioSeconds: { max: 30 } };
|
|
3265
3317
|
function elevenLabsTts(tts) {
|
|
3266
3318
|
return {
|
|
@@ -3271,7 +3323,7 @@ function elevenLabsTts(tts) {
|
|
|
3271
3323
|
adapter: "fal",
|
|
3272
3324
|
providerModelId: tts.providerModelId,
|
|
3273
3325
|
lifecycle: "active",
|
|
3274
|
-
exposure:
|
|
3326
|
+
exposure: EXPOSURE4,
|
|
3275
3327
|
constraints: {
|
|
3276
3328
|
voices: ELEVENLABS_VOICES,
|
|
3277
3329
|
languages: tts.languages,
|
|
@@ -3296,7 +3348,7 @@ function geminiTts(id, label, description) {
|
|
|
3296
3348
|
adapter: "fal",
|
|
3297
3349
|
providerModelId,
|
|
3298
3350
|
lifecycle: "active",
|
|
3299
|
-
exposure:
|
|
3351
|
+
exposure: EXPOSURE4,
|
|
3300
3352
|
constraints: {
|
|
3301
3353
|
voices: GEMINI_TTS_VOICES,
|
|
3302
3354
|
supports: ["style"],
|
|
@@ -3319,7 +3371,7 @@ function syncLipsync(id, label, providerModelId, syncModel, description) {
|
|
|
3319
3371
|
adapter: "fal",
|
|
3320
3372
|
providerModelId,
|
|
3321
3373
|
lifecycle: "active",
|
|
3322
|
-
exposure:
|
|
3374
|
+
exposure: EXPOSURE4,
|
|
3323
3375
|
constraints: {
|
|
3324
3376
|
requires: ["sourceVideo", "sourceAudio"],
|
|
3325
3377
|
references: LIPSYNC_AUDIO,
|
|
@@ -3380,7 +3432,7 @@ var MEDIA_NODE_MODELS = [
|
|
|
3380
3432
|
adapter: "fal",
|
|
3381
3433
|
providerModelId: "fal-ai/minimax/speech-2.8-hd",
|
|
3382
3434
|
lifecycle: "active",
|
|
3383
|
-
exposure:
|
|
3435
|
+
exposure: EXPOSURE4,
|
|
3384
3436
|
constraints: {
|
|
3385
3437
|
voices: MINIMAX_VOICES,
|
|
3386
3438
|
languages: MINIMAX_SPEECH_LANGUAGES,
|
|
@@ -3405,7 +3457,7 @@ var MEDIA_NODE_MODELS = [
|
|
|
3405
3457
|
adapter: "fal",
|
|
3406
3458
|
providerModelId: "fal-ai/elevenlabs/voice-changer",
|
|
3407
3459
|
lifecycle: "active",
|
|
3408
|
-
exposure:
|
|
3460
|
+
exposure: EXPOSURE4,
|
|
3409
3461
|
constraints: {
|
|
3410
3462
|
requires: ["sourceAudio"],
|
|
3411
3463
|
// The flat price assumes at most a minute of speech.
|
|
@@ -3432,7 +3484,7 @@ var MEDIA_NODE_MODELS = [
|
|
|
3432
3484
|
adapter: "fal",
|
|
3433
3485
|
providerModelId: "fal-ai/elevenlabs/dubbing",
|
|
3434
3486
|
lifecycle: "active",
|
|
3435
|
-
exposure:
|
|
3487
|
+
exposure: EXPOSURE4,
|
|
3436
3488
|
constraints: {
|
|
3437
3489
|
requiresOneOf: ["sourceVideo", "sourceAudio"],
|
|
3438
3490
|
// The flat price covers 60 s of source.
|
|
@@ -3480,7 +3532,7 @@ var MEDIA_NODE_MODELS = [
|
|
|
3480
3532
|
adapter: "fal",
|
|
3481
3533
|
providerModelId: "veed/lipsync/v2",
|
|
3482
3534
|
lifecycle: "active",
|
|
3483
|
-
exposure:
|
|
3535
|
+
exposure: EXPOSURE4,
|
|
3484
3536
|
constraints: {
|
|
3485
3537
|
requires: ["sourceVideo", "sourceAudio"],
|
|
3486
3538
|
references: LIPSYNC_AUDIO,
|
|
@@ -3506,7 +3558,7 @@ var MEDIA_NODE_MODELS = [
|
|
|
3506
3558
|
adapter: "fal",
|
|
3507
3559
|
providerModelId: "minimax/h3-max/lip-sync/image-to-video",
|
|
3508
3560
|
lifecycle: "active",
|
|
3509
|
-
exposure:
|
|
3561
|
+
exposure: EXPOSURE4,
|
|
3510
3562
|
constraints: {
|
|
3511
3563
|
requires: ["firstFrame", "sourceAudio"],
|
|
3512
3564
|
resolutions: ["480p", "768p", "1080p", "2k"],
|
|
@@ -3532,7 +3584,7 @@ var MEDIA_NODE_MODELS = [
|
|
|
3532
3584
|
adapter: "fal",
|
|
3533
3585
|
providerModelId: "fal-ai/elevenlabs/speech-to-text/scribe-v2",
|
|
3534
3586
|
lifecycle: "active",
|
|
3535
|
-
exposure:
|
|
3587
|
+
exposure: EXPOSURE4,
|
|
3536
3588
|
constraints: {
|
|
3537
3589
|
requires: ["sourceAudio"],
|
|
3538
3590
|
// The flat price covers 10 minutes of audio.
|
|
@@ -5068,8 +5120,113 @@ var VIDEO_FAMILY_MODELS = [
|
|
|
5068
5120
|
}
|
|
5069
5121
|
];
|
|
5070
5122
|
|
|
5071
|
-
// src/catalog/video.ts
|
|
5123
|
+
// src/catalog/video-luma.ts
|
|
5072
5124
|
var VIDEO_USAGE2 = { unit: "seconds" };
|
|
5125
|
+
var EXPOSURE5 = ["cowork", "space_builder"];
|
|
5126
|
+
var LUMA_LOGO2 = "https://cdn.jsdelivr.net/npm/@lobehub/icons-static-png@1.97.0/light/luma-color.png";
|
|
5127
|
+
var RAY_RATIOS = ["9:16", "3:4", "1:1", "4:3", "16:9", "21:9"];
|
|
5128
|
+
var RAY_RESOLUTIONS = ["360p", "720p", "1080p"];
|
|
5129
|
+
var RAY_PROMPT = { referenceSyntax: "numbered", maxChars: 6e3 };
|
|
5130
|
+
var LUMA_VIDEO_MODELS = [
|
|
5131
|
+
{
|
|
5132
|
+
// https://docs.agents.lumalabs.ai: type "video" with a fixed 5 s duration;
|
|
5133
|
+
// firstFrame and lastFrame ride as start_frame and end_frame.
|
|
5134
|
+
id: "ray-3.2",
|
|
5135
|
+
aliases: [],
|
|
5136
|
+
label: "Ray 3.2",
|
|
5137
|
+
type: "video",
|
|
5138
|
+
adapter: "luma",
|
|
5139
|
+
providerModelId: "ray-3.2",
|
|
5140
|
+
lifecycle: "active",
|
|
5141
|
+
exposure: EXPOSURE5,
|
|
5142
|
+
constraints: {
|
|
5143
|
+
aspectRatios: ["adaptive", ...RAY_RATIOS],
|
|
5144
|
+
resolutions: [...RAY_RESOLUTIONS],
|
|
5145
|
+
durations: [5],
|
|
5146
|
+
supports: ["lastFrame"],
|
|
5147
|
+
prompt: { ...RAY_PROMPT },
|
|
5148
|
+
audio: "never"
|
|
5149
|
+
},
|
|
5150
|
+
defaults: { durationSeconds: 5, resolution: "720p", aspectRatio: "adaptive" },
|
|
5151
|
+
usage: { ...VIDEO_USAGE2 },
|
|
5152
|
+
pricingKind: "video_per_second",
|
|
5153
|
+
display: {
|
|
5154
|
+
provider: "luma",
|
|
5155
|
+
description: "Luma Ray 3.2 text- and image-to-video with optional first and last frames, 5-second clips at up to 1080p.",
|
|
5156
|
+
logo: LUMA_LOGO2
|
|
5157
|
+
},
|
|
5158
|
+
capabilities: {}
|
|
5159
|
+
},
|
|
5160
|
+
{
|
|
5161
|
+
// https://docs.agents.lumalabs.ai: type "video_edit" with a source video of
|
|
5162
|
+
// up to 18 s; the output keeps the source length, so there is no durations
|
|
5163
|
+
// knob, no aspect_ratio and no end frame. Luma bills its 5 s price for any
|
|
5164
|
+
// source (live, 2026-10-21) and the row is priced per source second, so a
|
|
5165
|
+
// source under 5 s is refused: it would be billed below Luma's charge.
|
|
5166
|
+
id: "ray-3.2-edit",
|
|
5167
|
+
aliases: [],
|
|
5168
|
+
label: "Ray 3.2 Edit",
|
|
5169
|
+
type: "video",
|
|
5170
|
+
adapter: "luma",
|
|
5171
|
+
providerModelId: "ray-3.2",
|
|
5172
|
+
lifecycle: "active",
|
|
5173
|
+
exposure: EXPOSURE5,
|
|
5174
|
+
constraints: {
|
|
5175
|
+
resolutions: [...RAY_RESOLUTIONS],
|
|
5176
|
+
requires: ["sourceVideo"],
|
|
5177
|
+
sourceVideoSeconds: { min: 5, max: 18 },
|
|
5178
|
+
supports: [],
|
|
5179
|
+
prompt: { ...RAY_PROMPT },
|
|
5180
|
+
audio: "never"
|
|
5181
|
+
},
|
|
5182
|
+
defaults: { resolution: "720p" },
|
|
5183
|
+
usage: { ...VIDEO_USAGE2 },
|
|
5184
|
+
pricingKind: "video_per_second",
|
|
5185
|
+
display: {
|
|
5186
|
+
provider: "luma",
|
|
5187
|
+
description: "Luma Ray 3.2 video edit: changes a 5-18 second clip from a prompt, keeping its length.",
|
|
5188
|
+
logo: LUMA_LOGO2
|
|
5189
|
+
},
|
|
5190
|
+
capabilities: { acceptsSourceVideo: true, videoEdit: true }
|
|
5191
|
+
},
|
|
5192
|
+
{
|
|
5193
|
+
// https://docs.agents.lumalabs.ai: type "video_reframe" with a required
|
|
5194
|
+
// target aspect_ratio; the source is up to 10 s and the output keeps its
|
|
5195
|
+
// length whatever video.duration says, while Luma bills that duration
|
|
5196
|
+
// (live, 2026-10-21). So there is no durations knob, and a source under
|
|
5197
|
+
// 5 s is refused, as on ray-3.2-edit. 1080p is not offered for the
|
|
5198
|
+
// vertical targets 9:16 and 3:4.
|
|
5199
|
+
id: "ray-3.2-reframe",
|
|
5200
|
+
aliases: [],
|
|
5201
|
+
label: "Ray 3.2 Reframe",
|
|
5202
|
+
type: "video",
|
|
5203
|
+
adapter: "luma",
|
|
5204
|
+
providerModelId: "ray-3.2",
|
|
5205
|
+
lifecycle: "active",
|
|
5206
|
+
exposure: EXPOSURE5,
|
|
5207
|
+
constraints: {
|
|
5208
|
+
aspectRatios: [...RAY_RATIOS],
|
|
5209
|
+
resolutions: [...RAY_RESOLUTIONS],
|
|
5210
|
+
requires: ["sourceVideo"],
|
|
5211
|
+
sourceVideoSeconds: { min: 5, max: 10 },
|
|
5212
|
+
supports: [],
|
|
5213
|
+
prompt: { ...RAY_PROMPT },
|
|
5214
|
+
audio: "never"
|
|
5215
|
+
},
|
|
5216
|
+
defaults: { resolution: "720p", aspectRatio: "16:9" },
|
|
5217
|
+
usage: { ...VIDEO_USAGE2 },
|
|
5218
|
+
pricingKind: "video_per_second",
|
|
5219
|
+
display: {
|
|
5220
|
+
provider: "luma",
|
|
5221
|
+
description: "Luma Ray 3.2 Reframe: changes a 5-10 second clip to a new aspect ratio and fills the new area from the prompt.",
|
|
5222
|
+
logo: LUMA_LOGO2
|
|
5223
|
+
},
|
|
5224
|
+
capabilities: { acceptsSourceVideo: true, videoEdit: true }
|
|
5225
|
+
}
|
|
5226
|
+
];
|
|
5227
|
+
|
|
5228
|
+
// src/catalog/video.ts
|
|
5229
|
+
var VIDEO_USAGE3 = { unit: "seconds" };
|
|
5073
5230
|
var SEEDANCE_RATIOS = ["21:9", "16:9", "4:3", "1:1", "3:4", "9:16", "adaptive"];
|
|
5074
5231
|
var KLING_RATIOS2 = ["16:9", "9:16", "1:1", "adaptive"];
|
|
5075
5232
|
var KLING_OMNI_RATIOS = ["16:9", "9:16", "1:1"];
|
|
@@ -5122,7 +5279,7 @@ var VIDEO_MODELS = [
|
|
|
5122
5279
|
audio: "always"
|
|
5123
5280
|
},
|
|
5124
5281
|
defaults: { durationSeconds: 8, resolution: "720p", aspectRatio: "16:9" },
|
|
5125
|
-
usage: { ...
|
|
5282
|
+
usage: { ...VIDEO_USAGE3, slug: "veo" },
|
|
5126
5283
|
pricingKind: "video_per_second",
|
|
5127
5284
|
display: {
|
|
5128
5285
|
provider: "google",
|
|
@@ -5155,7 +5312,7 @@ var VIDEO_MODELS = [
|
|
|
5155
5312
|
audio: "always"
|
|
5156
5313
|
},
|
|
5157
5314
|
defaults: { durationSeconds: 8, resolution: "720p", aspectRatio: "16:9" },
|
|
5158
|
-
usage: { ...
|
|
5315
|
+
usage: { ...VIDEO_USAGE3 },
|
|
5159
5316
|
pricingKind: "video_per_second",
|
|
5160
5317
|
display: {
|
|
5161
5318
|
provider: "google",
|
|
@@ -5185,7 +5342,7 @@ var VIDEO_MODELS = [
|
|
|
5185
5342
|
audio: "always"
|
|
5186
5343
|
},
|
|
5187
5344
|
defaults: { durationSeconds: 8, resolution: "720p", aspectRatio: "16:9" },
|
|
5188
|
-
usage: { ...
|
|
5345
|
+
usage: { ...VIDEO_USAGE3 },
|
|
5189
5346
|
pricingKind: "video_per_second",
|
|
5190
5347
|
display: {
|
|
5191
5348
|
provider: "google",
|
|
@@ -5222,7 +5379,7 @@ var VIDEO_MODELS = [
|
|
|
5222
5379
|
audio: "always"
|
|
5223
5380
|
},
|
|
5224
5381
|
defaults: {},
|
|
5225
|
-
usage: { ...
|
|
5382
|
+
usage: { ...VIDEO_USAGE3, slug: "gemini_omni" },
|
|
5226
5383
|
pricingKind: "video_per_second",
|
|
5227
5384
|
display: {
|
|
5228
5385
|
provider: "google",
|
|
@@ -5259,7 +5416,7 @@ var VIDEO_MODELS = [
|
|
|
5259
5416
|
audio: "always"
|
|
5260
5417
|
},
|
|
5261
5418
|
defaults: {},
|
|
5262
|
-
usage: { ...
|
|
5419
|
+
usage: { ...VIDEO_USAGE3 },
|
|
5263
5420
|
pricingKind: "video_per_second",
|
|
5264
5421
|
display: {
|
|
5265
5422
|
provider: "google",
|
|
@@ -5308,7 +5465,7 @@ var VIDEO_MODELS = [
|
|
|
5308
5465
|
aspectRatio: "16:9",
|
|
5309
5466
|
generateAudio: true
|
|
5310
5467
|
},
|
|
5311
|
-
usage: { ...
|
|
5468
|
+
usage: { ...VIDEO_USAGE3, slug: "seedance2", providerLabel: "byteplus" },
|
|
5312
5469
|
pricingKind: "video_per_second",
|
|
5313
5470
|
display: {
|
|
5314
5471
|
provider: "bytedance",
|
|
@@ -5351,7 +5508,7 @@ var VIDEO_MODELS = [
|
|
|
5351
5508
|
aspectRatio: "16:9",
|
|
5352
5509
|
generateAudio: true
|
|
5353
5510
|
},
|
|
5354
|
-
usage: { ...
|
|
5511
|
+
usage: { ...VIDEO_USAGE3 },
|
|
5355
5512
|
pricingKind: "video_per_second",
|
|
5356
5513
|
display: {
|
|
5357
5514
|
provider: "bytedance",
|
|
@@ -5401,7 +5558,7 @@ var VIDEO_MODELS = [
|
|
|
5401
5558
|
aspectRatio: "16:9",
|
|
5402
5559
|
generateAudio: true
|
|
5403
5560
|
},
|
|
5404
|
-
usage: { ...
|
|
5561
|
+
usage: { ...VIDEO_USAGE3 },
|
|
5405
5562
|
pricingKind: "video_per_second",
|
|
5406
5563
|
display: {
|
|
5407
5564
|
provider: "bytedance",
|
|
@@ -5463,7 +5620,7 @@ var VIDEO_MODELS = [
|
|
|
5463
5620
|
cfgScale: 0.5,
|
|
5464
5621
|
negativePrompt: NEGATIVE_PROMPT
|
|
5465
5622
|
},
|
|
5466
|
-
usage: { ...
|
|
5623
|
+
usage: { ...VIDEO_USAGE3 },
|
|
5467
5624
|
pricingKind: "video_per_second",
|
|
5468
5625
|
display: {
|
|
5469
5626
|
provider: "kuaishou",
|
|
@@ -5495,7 +5652,7 @@ var VIDEO_MODELS = [
|
|
|
5495
5652
|
cfgScale: 0.5,
|
|
5496
5653
|
generateAudio: true
|
|
5497
5654
|
},
|
|
5498
|
-
usage: { ...
|
|
5655
|
+
usage: { ...VIDEO_USAGE3 },
|
|
5499
5656
|
pricingKind: "video_per_second",
|
|
5500
5657
|
display: {
|
|
5501
5658
|
provider: "kuaishou",
|
|
@@ -5563,7 +5720,7 @@ var VIDEO_MODELS = [
|
|
|
5563
5720
|
aspectRatio: "16:9",
|
|
5564
5721
|
promptExpansion: "balanced"
|
|
5565
5722
|
},
|
|
5566
|
-
usage: { ...
|
|
5723
|
+
usage: { ...VIDEO_USAGE3 },
|
|
5567
5724
|
pricingKind: "video_per_second",
|
|
5568
5725
|
display: {
|
|
5569
5726
|
provider: "minimax",
|
|
@@ -5597,7 +5754,7 @@ var VIDEO_MODELS = [
|
|
|
5597
5754
|
aspectRatio: "16:9",
|
|
5598
5755
|
promptExpansion: "balanced"
|
|
5599
5756
|
},
|
|
5600
|
-
usage: { ...
|
|
5757
|
+
usage: { ...VIDEO_USAGE3 },
|
|
5601
5758
|
pricingKind: "video_per_second",
|
|
5602
5759
|
display: {
|
|
5603
5760
|
provider: "minimax",
|
|
@@ -5639,7 +5796,7 @@ var VIDEO_MODELS = [
|
|
|
5639
5796
|
aspectRatio: "adaptive",
|
|
5640
5797
|
promptExpansion: "balanced"
|
|
5641
5798
|
},
|
|
5642
|
-
usage: { ...
|
|
5799
|
+
usage: { ...VIDEO_USAGE3 },
|
|
5643
5800
|
pricingKind: "video_per_second",
|
|
5644
5801
|
display: {
|
|
5645
5802
|
provider: "minimax",
|
|
@@ -5683,7 +5840,7 @@ var VIDEO_MODELS = [
|
|
|
5683
5840
|
aspectRatio: "adaptive",
|
|
5684
5841
|
promptExpansion: "balanced"
|
|
5685
5842
|
},
|
|
5686
|
-
usage: { ...
|
|
5843
|
+
usage: { ...VIDEO_USAGE3 },
|
|
5687
5844
|
pricingKind: "video_per_second",
|
|
5688
5845
|
display: {
|
|
5689
5846
|
provider: "minimax",
|
|
@@ -5728,7 +5885,7 @@ var VIDEO_MODELS = [
|
|
|
5728
5885
|
aspectRatio: "adaptive",
|
|
5729
5886
|
generateAudio: true
|
|
5730
5887
|
},
|
|
5731
|
-
usage: { ...
|
|
5888
|
+
usage: { ...VIDEO_USAGE3 },
|
|
5732
5889
|
pricingKind: "video_per_second",
|
|
5733
5890
|
display: {
|
|
5734
5891
|
provider: "alibaba",
|
|
@@ -5755,7 +5912,7 @@ var VIDEO_MODELS = [
|
|
|
5755
5912
|
audio: "never"
|
|
5756
5913
|
},
|
|
5757
5914
|
defaults: { durationSeconds: 5, aspectRatio: "16:9" },
|
|
5758
|
-
usage: { ...
|
|
5915
|
+
usage: { ...VIDEO_USAGE3 },
|
|
5759
5916
|
pricingKind: "video_per_second",
|
|
5760
5917
|
display: {
|
|
5761
5918
|
provider: "kuaishou",
|
|
@@ -5804,7 +5961,7 @@ var VIDEO_MODELS = [
|
|
|
5804
5961
|
audio: "never"
|
|
5805
5962
|
},
|
|
5806
5963
|
defaults: {},
|
|
5807
|
-
usage: { ...
|
|
5964
|
+
usage: { ...VIDEO_USAGE3 },
|
|
5808
5965
|
// Higgsfield bills DoP per generation: a fixed-length clip with no duration knob.
|
|
5809
5966
|
pricingKind: "flat",
|
|
5810
5967
|
display: {
|
|
@@ -5813,7 +5970,8 @@ var VIDEO_MODELS = [
|
|
|
5813
5970
|
},
|
|
5814
5971
|
capabilities: {}
|
|
5815
5972
|
},
|
|
5816
|
-
...VIDEO_FAMILY_MODELS
|
|
5973
|
+
...VIDEO_FAMILY_MODELS,
|
|
5974
|
+
...LUMA_VIDEO_MODELS
|
|
5817
5975
|
];
|
|
5818
5976
|
|
|
5819
5977
|
// src/catalog/video-tools.ts
|
|
@@ -5979,14 +6137,17 @@ var VIDEO_TOOL_MODELS = [
|
|
|
5979
6137
|
{
|
|
5980
6138
|
// https://fal.ai/models/fal-ai/flashvsr/upscale/video/api: upscale_factor 1-4, X264 MP4
|
|
5981
6139
|
// by default; fal bills $0.0005 per output megapixel-frame (width x height x frames).
|
|
6140
|
+
// Retired (ENG-3314): the price rows tier by short edge, which under-prices square, wide
|
|
6141
|
+
// and above-4k outputs.
|
|
5982
6142
|
id: "flashvsr",
|
|
5983
6143
|
aliases: ["flashvsr-upscale"],
|
|
5984
6144
|
label: "FlashVSR",
|
|
5985
6145
|
type: "video-tool",
|
|
5986
6146
|
adapter: "fal",
|
|
5987
6147
|
providerModelId: "fal-ai/flashvsr/upscale/video",
|
|
5988
|
-
lifecycle: "
|
|
5989
|
-
|
|
6148
|
+
lifecycle: "retired",
|
|
6149
|
+
replacedBy: "flux-video-upscale-precise",
|
|
6150
|
+
exposure: [],
|
|
5990
6151
|
constraints: {
|
|
5991
6152
|
supports: [],
|
|
5992
6153
|
tool: { kind: "upscale", upscaleFactor: { min: 1, max: 4 } }
|
|
@@ -6787,7 +6948,8 @@ var ADAPTER_IDS = [
|
|
|
6787
6948
|
"replicate",
|
|
6788
6949
|
"prodia",
|
|
6789
6950
|
"higgsfield",
|
|
6790
|
-
"xai-video"
|
|
6951
|
+
"xai-video",
|
|
6952
|
+
"luma"
|
|
6791
6953
|
];
|
|
6792
6954
|
var ModelTypeSchema = z3.enum([
|
|
6793
6955
|
"text",
|
|
@@ -13452,9 +13614,608 @@ var higgsfieldAdapter = {
|
|
|
13452
13614
|
}
|
|
13453
13615
|
};
|
|
13454
13616
|
|
|
13617
|
+
// src/adapters/luma.ts
|
|
13618
|
+
import { z as z25 } from "zod";
|
|
13619
|
+
|
|
13620
|
+
// src/adapters/mp4-duration.ts
|
|
13621
|
+
function mp4DurationSeconds(bytes) {
|
|
13622
|
+
const moov = findBox(bytes, 0, bytes.length, "moov");
|
|
13623
|
+
if (!moov) return void 0;
|
|
13624
|
+
const mvhd = findBox(bytes, moov.start + 8, moov.end, "mvhd");
|
|
13625
|
+
if (!mvhd) return void 0;
|
|
13626
|
+
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
13627
|
+
const size = mvhd.end - mvhd.start;
|
|
13628
|
+
if (size < 8 + 4) return void 0;
|
|
13629
|
+
const version = view.getUint8(mvhd.start + 8);
|
|
13630
|
+
if (version === 0) {
|
|
13631
|
+
if (size < 8 + 4 + 4 + 4 + 4 + 4) return void 0;
|
|
13632
|
+
const timescale = view.getUint32(mvhd.start + 8 + 4 + 4 + 4);
|
|
13633
|
+
const duration = view.getUint32(mvhd.start + 8 + 4 + 4 + 4 + 4);
|
|
13634
|
+
if (timescale === 0) return void 0;
|
|
13635
|
+
return duration / timescale;
|
|
13636
|
+
}
|
|
13637
|
+
if (version === 1) {
|
|
13638
|
+
if (size < 8 + 4 + 8 + 8 + 4 + 8) return void 0;
|
|
13639
|
+
const timescale = view.getUint32(mvhd.start + 8 + 4 + 8 + 8);
|
|
13640
|
+
const high = view.getUint32(mvhd.start + 8 + 4 + 8 + 8 + 4);
|
|
13641
|
+
const low = view.getUint32(mvhd.start + 8 + 4 + 8 + 8 + 4 + 4);
|
|
13642
|
+
if (timescale === 0) return void 0;
|
|
13643
|
+
return (high * 2 ** 32 + low) / timescale;
|
|
13644
|
+
}
|
|
13645
|
+
return void 0;
|
|
13646
|
+
}
|
|
13647
|
+
function findBox(bytes, from, to, type) {
|
|
13648
|
+
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
13649
|
+
let offset = from;
|
|
13650
|
+
while (offset + 8 <= to) {
|
|
13651
|
+
const size = view.getUint32(offset);
|
|
13652
|
+
const name = String.fromCharCode(
|
|
13653
|
+
view.getUint8(offset + 4),
|
|
13654
|
+
view.getUint8(offset + 5),
|
|
13655
|
+
view.getUint8(offset + 6),
|
|
13656
|
+
view.getUint8(offset + 7)
|
|
13657
|
+
);
|
|
13658
|
+
if (size < 8 || offset + size > to) return void 0;
|
|
13659
|
+
if (name === type) return { start: offset, end: offset + size };
|
|
13660
|
+
offset += size;
|
|
13661
|
+
}
|
|
13662
|
+
return void 0;
|
|
13663
|
+
}
|
|
13664
|
+
|
|
13665
|
+
// src/adapters/luma.ts
|
|
13666
|
+
var DEFAULT_BASE_URL = "https://agents.lumalabs.ai";
|
|
13667
|
+
var IMAGE_POLL_INTERVAL_MS = 3e3;
|
|
13668
|
+
var IMAGE_TIMEOUT_MS = 5 * 6e4;
|
|
13669
|
+
var VIDEO_POLL_INTERVAL_MS = 5e3;
|
|
13670
|
+
var VIDEO_TIMEOUT_MS = 20 * 6e4;
|
|
13671
|
+
var PROMPT_MAX_CHARS = 6e3;
|
|
13672
|
+
var LUMA_IMAGE_MODEL_IDS = /* @__PURE__ */ new Set(["uni-1", "uni-1-max"]);
|
|
13673
|
+
var LUMA_VIDEO_MODEL_ID = "ray-3.2";
|
|
13674
|
+
var LUMA_VIDEO_MODES = /* @__PURE__ */ new Map([
|
|
13675
|
+
["ray-3.2", "generate"],
|
|
13676
|
+
["ray-3.2-edit", "edit"],
|
|
13677
|
+
["ray-3.2-reframe", "reframe"]
|
|
13678
|
+
]);
|
|
13679
|
+
function lumaRowRefusal(row2) {
|
|
13680
|
+
const provider = row2.providerModelId.toLowerCase();
|
|
13681
|
+
if (row2.type === "image") {
|
|
13682
|
+
return LUMA_IMAGE_MODEL_IDS.has(provider) ? void 0 : "luma image rows need providerModelId uni-1 or uni-1-max";
|
|
13683
|
+
}
|
|
13684
|
+
if (row2.type === "video") {
|
|
13685
|
+
if (provider !== LUMA_VIDEO_MODEL_ID) return "luma video rows need providerModelId ray-3.2";
|
|
13686
|
+
return !LUMA_VIDEO_MODES.has(row2.id) ? `luma routes ray-3.2 rows by catalog id; it knows ${[...LUMA_VIDEO_MODES.keys()].join(", ")}` : void 0;
|
|
13687
|
+
}
|
|
13688
|
+
return `luma has no ${row2.type} rows`;
|
|
13689
|
+
}
|
|
13690
|
+
function lumaBase(ctx) {
|
|
13691
|
+
return ctx.endpoints?.luma ?? DEFAULT_BASE_URL;
|
|
13692
|
+
}
|
|
13693
|
+
function lumaKey(ctx) {
|
|
13694
|
+
const key = ctx.keys.luma;
|
|
13695
|
+
if (!key) {
|
|
13696
|
+
throw new ModelKitError({
|
|
13697
|
+
code: "auth",
|
|
13698
|
+
message: "Missing API key for luma",
|
|
13699
|
+
provider: "luma",
|
|
13700
|
+
model: ctx.model.id,
|
|
13701
|
+
retryable: false
|
|
13702
|
+
});
|
|
13703
|
+
}
|
|
13704
|
+
return key;
|
|
13705
|
+
}
|
|
13706
|
+
function checkPrompt(req, ctx) {
|
|
13707
|
+
const prompt = req.prompt.trim();
|
|
13708
|
+
if (prompt.length === 0) {
|
|
13709
|
+
throw new ModelKitError({
|
|
13710
|
+
code: "missing_input",
|
|
13711
|
+
message: `${ctx.model.id} needs a prompt`,
|
|
13712
|
+
provider: "luma",
|
|
13713
|
+
model: ctx.model.id,
|
|
13714
|
+
retryable: false
|
|
13715
|
+
});
|
|
13716
|
+
}
|
|
13717
|
+
if (req.prompt.length > PROMPT_MAX_CHARS) {
|
|
13718
|
+
throw new ModelKitError({
|
|
13719
|
+
code: "unsupported_option",
|
|
13720
|
+
message: `${ctx.model.id} takes a prompt of at most ${PROMPT_MAX_CHARS} characters`,
|
|
13721
|
+
provider: "luma",
|
|
13722
|
+
model: ctx.model.id,
|
|
13723
|
+
retryable: false
|
|
13724
|
+
});
|
|
13725
|
+
}
|
|
13726
|
+
return req.prompt;
|
|
13727
|
+
}
|
|
13728
|
+
function imageRef(ref) {
|
|
13729
|
+
if ("url" in ref) return { url: ref.url };
|
|
13730
|
+
return { data: mediaRefToBase64(ref.bytes), media_type: ref.mime };
|
|
13731
|
+
}
|
|
13732
|
+
function videoRef(ref) {
|
|
13733
|
+
if ("url" in ref) return { url: ref.url, media_type: "video/mp4" };
|
|
13734
|
+
const mediaType = ref.mime.startsWith("video/") ? ref.mime : "video/mp4";
|
|
13735
|
+
return { data: mediaRefToBase64(ref.bytes), media_type: mediaType };
|
|
13736
|
+
}
|
|
13737
|
+
function lumaOutputFormat(req, ctx) {
|
|
13738
|
+
const format = req.outputFormat;
|
|
13739
|
+
if (format === void 0 || format === "png" || format === "jpeg") return format;
|
|
13740
|
+
if ((ctx.call.onUnsupported ?? "error") === "error") {
|
|
13741
|
+
throw new ModelKitError({
|
|
13742
|
+
code: "unsupported_option",
|
|
13743
|
+
message: `${ctx.model.id} has no outputFormat "${format}". Supported: png, jpeg.`,
|
|
13744
|
+
provider: "luma",
|
|
13745
|
+
model: ctx.model.id,
|
|
13746
|
+
retryable: false
|
|
13747
|
+
});
|
|
13748
|
+
}
|
|
13749
|
+
ctx.warnings.push({
|
|
13750
|
+
code: "option_ignored",
|
|
13751
|
+
field: "outputFormat",
|
|
13752
|
+
from: format,
|
|
13753
|
+
to: "png",
|
|
13754
|
+
message: `${ctx.model.id} has no outputFormat "${format}"; using png`
|
|
13755
|
+
});
|
|
13756
|
+
return "png";
|
|
13757
|
+
}
|
|
13758
|
+
function refuseOrDrop(ctx, field, message) {
|
|
13759
|
+
if ((ctx.call.onUnsupported ?? "error") === "error") {
|
|
13760
|
+
throw new ModelKitError({
|
|
13761
|
+
code: "unsupported_option",
|
|
13762
|
+
message,
|
|
13763
|
+
provider: "luma",
|
|
13764
|
+
model: ctx.model.id,
|
|
13765
|
+
retryable: false
|
|
13766
|
+
});
|
|
13767
|
+
}
|
|
13768
|
+
ctx.warnings.push({ code: "option_ignored", field, message });
|
|
13769
|
+
}
|
|
13770
|
+
function lumaVideoMode(ctx) {
|
|
13771
|
+
const mode = LUMA_VIDEO_MODES.get(ctx.model.id);
|
|
13772
|
+
if (mode === void 0) {
|
|
13773
|
+
throw new ModelKitError({
|
|
13774
|
+
code: "unsupported_option",
|
|
13775
|
+
message: `luma routes ray-3.2 rows by catalog id; "${ctx.model.id}" is not a luma video row`,
|
|
13776
|
+
provider: "luma",
|
|
13777
|
+
model: ctx.model.id,
|
|
13778
|
+
retryable: false
|
|
13779
|
+
});
|
|
13780
|
+
}
|
|
13781
|
+
return mode;
|
|
13782
|
+
}
|
|
13783
|
+
function reframeTooTall(req) {
|
|
13784
|
+
const vertical = req.aspectRatio === "9:16" || req.aspectRatio === "3:4";
|
|
13785
|
+
return vertical && req.resolution === "1080p";
|
|
13786
|
+
}
|
|
13787
|
+
function sentResolution(req, mode) {
|
|
13788
|
+
return mode === "reframe" && reframeTooTall(req) ? "720p" : req.resolution;
|
|
13789
|
+
}
|
|
13790
|
+
function lumaReframeResolution(req, ctx) {
|
|
13791
|
+
const requested = req.resolution;
|
|
13792
|
+
if (requested === void 0 || !reframeTooTall(req)) return requested;
|
|
13793
|
+
const message = `${ctx.model.id} renders 9:16 and 3:4 reframes at up to 720p`;
|
|
13794
|
+
if ((ctx.call.onUnsupported ?? "error") === "error") {
|
|
13795
|
+
throw new ModelKitError({
|
|
13796
|
+
code: "unsupported_option",
|
|
13797
|
+
message,
|
|
13798
|
+
provider: "luma",
|
|
13799
|
+
model: ctx.model.id,
|
|
13800
|
+
retryable: false
|
|
13801
|
+
});
|
|
13802
|
+
}
|
|
13803
|
+
ctx.warnings.push({
|
|
13804
|
+
code: "resolution_coerced",
|
|
13805
|
+
field: "resolution",
|
|
13806
|
+
from: requested,
|
|
13807
|
+
to: "720p",
|
|
13808
|
+
message
|
|
13809
|
+
});
|
|
13810
|
+
return "720p";
|
|
13811
|
+
}
|
|
13812
|
+
var lumaGenerationSchema = z25.looseObject({
|
|
13813
|
+
id: z25.string(),
|
|
13814
|
+
state: z25.string().optional(),
|
|
13815
|
+
output: z25.array(
|
|
13816
|
+
z25.looseObject({
|
|
13817
|
+
type: z25.string().optional(),
|
|
13818
|
+
url: z25.string().optional()
|
|
13819
|
+
})
|
|
13820
|
+
).optional(),
|
|
13821
|
+
failure_reason: z25.string().optional().nullable(),
|
|
13822
|
+
failure_code: z25.string().optional().nullable()
|
|
13823
|
+
});
|
|
13824
|
+
function lumaFailure(ctx, code, reason) {
|
|
13825
|
+
const detail = reason ?? code ?? "unknown_error";
|
|
13826
|
+
const message = `Luma generation failed: ${detail}`;
|
|
13827
|
+
switch (code) {
|
|
13828
|
+
case "content_moderated":
|
|
13829
|
+
return new ModelKitError({
|
|
13830
|
+
code: "content_blocked",
|
|
13831
|
+
message,
|
|
13832
|
+
provider: "luma",
|
|
13833
|
+
model: ctx.model.id,
|
|
13834
|
+
retryable: false
|
|
13835
|
+
});
|
|
13836
|
+
case "rate_limited":
|
|
13837
|
+
return new ModelKitError({
|
|
13838
|
+
code: "rate_limited",
|
|
13839
|
+
message,
|
|
13840
|
+
provider: "luma",
|
|
13841
|
+
model: ctx.model.id
|
|
13842
|
+
});
|
|
13843
|
+
case "generation_failed":
|
|
13844
|
+
case "output_not_found":
|
|
13845
|
+
return new ModelKitError({
|
|
13846
|
+
code: "provider_rejected",
|
|
13847
|
+
message,
|
|
13848
|
+
provider: "luma",
|
|
13849
|
+
model: ctx.model.id,
|
|
13850
|
+
retryable: true
|
|
13851
|
+
});
|
|
13852
|
+
case "budget_exhausted":
|
|
13853
|
+
return new ModelKitError({
|
|
13854
|
+
code: "provider_billing",
|
|
13855
|
+
message,
|
|
13856
|
+
provider: "luma",
|
|
13857
|
+
model: ctx.model.id,
|
|
13858
|
+
retryable: false
|
|
13859
|
+
});
|
|
13860
|
+
case "image_too_large":
|
|
13861
|
+
case "unsupported_format":
|
|
13862
|
+
return new ModelKitError({
|
|
13863
|
+
code: "unsupported_option",
|
|
13864
|
+
message,
|
|
13865
|
+
provider: "luma",
|
|
13866
|
+
model: ctx.model.id,
|
|
13867
|
+
retryable: false
|
|
13868
|
+
});
|
|
13869
|
+
default:
|
|
13870
|
+
return new ModelKitError({
|
|
13871
|
+
code: "provider_rejected",
|
|
13872
|
+
message,
|
|
13873
|
+
provider: "luma",
|
|
13874
|
+
model: ctx.model.id,
|
|
13875
|
+
retryable: false
|
|
13876
|
+
});
|
|
13877
|
+
}
|
|
13878
|
+
}
|
|
13879
|
+
function requestInit2(ctx, key, body) {
|
|
13880
|
+
const init = {
|
|
13881
|
+
method: body !== void 0 ? "POST" : "GET",
|
|
13882
|
+
headers: { Authorization: `Bearer ${key}`, "Content-Type": "application/json" }
|
|
13883
|
+
};
|
|
13884
|
+
if (body !== void 0) init.body = body;
|
|
13885
|
+
if (ctx.signal !== void 0) init.signal = ctx.signal;
|
|
13886
|
+
return init;
|
|
13887
|
+
}
|
|
13888
|
+
async function lumaRequest(ctx, url, body) {
|
|
13889
|
+
const key = lumaKey(ctx);
|
|
13890
|
+
let res;
|
|
13891
|
+
try {
|
|
13892
|
+
res = await ctx.fetch(url, requestInit2(ctx, key, body));
|
|
13893
|
+
} catch (cause) {
|
|
13894
|
+
throw classifyThrown("luma", cause, ctx.model.id);
|
|
13895
|
+
}
|
|
13896
|
+
if (!res.ok) {
|
|
13897
|
+
throw classifyHttpError(res.status, await readBody(res), "luma", ctx.model.id);
|
|
13898
|
+
}
|
|
13899
|
+
return res;
|
|
13900
|
+
}
|
|
13901
|
+
async function submitGeneration(ctx, body) {
|
|
13902
|
+
const retryOptions = mediaRetryOptions(ctx.call, ctx.signal);
|
|
13903
|
+
const res = await withRetry(
|
|
13904
|
+
() => lumaRequest(ctx, `${lumaBase(ctx)}/v1/generations`, JSON.stringify(body)),
|
|
13905
|
+
retryOptions
|
|
13906
|
+
);
|
|
13907
|
+
const parsed = lumaGenerationSchema.safeParse(await res.json());
|
|
13908
|
+
if (!parsed.success) {
|
|
13909
|
+
throw new ModelKitError({
|
|
13910
|
+
code: "provider_rejected",
|
|
13911
|
+
message: "Luma submit returned no generation id",
|
|
13912
|
+
provider: "luma",
|
|
13913
|
+
model: ctx.model.id,
|
|
13914
|
+
retryable: false
|
|
13915
|
+
});
|
|
13916
|
+
}
|
|
13917
|
+
return parsed.data;
|
|
13918
|
+
}
|
|
13919
|
+
async function readGeneration(ctx, id) {
|
|
13920
|
+
const res = await lumaRequest(ctx, `${lumaBase(ctx)}/v1/generations/${id}`);
|
|
13921
|
+
const payload = JsonValueSchema.parse(await res.json());
|
|
13922
|
+
const parsed = lumaGenerationSchema.safeParse(payload);
|
|
13923
|
+
if (!parsed.success) {
|
|
13924
|
+
throw new ModelKitError({
|
|
13925
|
+
code: "provider_rejected",
|
|
13926
|
+
message: "Luma returned an unreadable generation",
|
|
13927
|
+
provider: "luma",
|
|
13928
|
+
model: ctx.model.id,
|
|
13929
|
+
retryable: false
|
|
13930
|
+
});
|
|
13931
|
+
}
|
|
13932
|
+
return parsed.data;
|
|
13933
|
+
}
|
|
13934
|
+
function outputUrl(generation, type) {
|
|
13935
|
+
const outputs = generation.output ?? [];
|
|
13936
|
+
const match = outputs.find((item) => item.type === type && item.url);
|
|
13937
|
+
if (match?.url) return match.url;
|
|
13938
|
+
const fallback = outputs.find((item) => item.url);
|
|
13939
|
+
return fallback?.url;
|
|
13940
|
+
}
|
|
13941
|
+
async function readGenerationOnce(ctx, id) {
|
|
13942
|
+
try {
|
|
13943
|
+
return await readGeneration(ctx, id);
|
|
13944
|
+
} catch (cause) {
|
|
13945
|
+
if (ctx.call.maxRetries === 0) throw cause;
|
|
13946
|
+
if (isModelKitError(cause) && (cause.code === "network" || cause.status === 429 || (cause.status ?? 0) >= 500)) {
|
|
13947
|
+
return void 0;
|
|
13948
|
+
}
|
|
13949
|
+
throw cause;
|
|
13950
|
+
}
|
|
13951
|
+
}
|
|
13952
|
+
async function checkGeneration(ctx, id, type) {
|
|
13953
|
+
const generation = await readGenerationOnce(ctx, id);
|
|
13954
|
+
if (generation === void 0) return void 0;
|
|
13955
|
+
if (generation.state === "completed") {
|
|
13956
|
+
const url = outputUrl(generation, type);
|
|
13957
|
+
if (!url) {
|
|
13958
|
+
throw new ModelKitError({
|
|
13959
|
+
code: "provider_rejected",
|
|
13960
|
+
message: "Luma completed without an output URL",
|
|
13961
|
+
provider: "luma",
|
|
13962
|
+
model: ctx.model.id,
|
|
13963
|
+
retryable: false
|
|
13964
|
+
});
|
|
13965
|
+
}
|
|
13966
|
+
return url;
|
|
13967
|
+
}
|
|
13968
|
+
if (generation.state === "failed") {
|
|
13969
|
+
throw lumaFailure(
|
|
13970
|
+
ctx,
|
|
13971
|
+
generation.failure_code ?? void 0,
|
|
13972
|
+
generation.failure_reason ?? void 0
|
|
13973
|
+
);
|
|
13974
|
+
}
|
|
13975
|
+
return void 0;
|
|
13976
|
+
}
|
|
13977
|
+
async function downloadBytes(ctx, url, fallback) {
|
|
13978
|
+
let bytes;
|
|
13979
|
+
let header;
|
|
13980
|
+
try {
|
|
13981
|
+
const out = await mediaRefToBytes({ url }, ctx.fetch, {
|
|
13982
|
+
...ctx.signal !== void 0 && { signal: ctx.signal },
|
|
13983
|
+
provider: "luma",
|
|
13984
|
+
model: ctx.model.id
|
|
13985
|
+
});
|
|
13986
|
+
bytes = out.bytes;
|
|
13987
|
+
header = out.mime;
|
|
13988
|
+
} catch (cause) {
|
|
13989
|
+
throw classifyThrown("luma", cause, ctx.model.id);
|
|
13990
|
+
}
|
|
13991
|
+
const kind = fallback.split("/")[0];
|
|
13992
|
+
const usable = header !== void 0 && header.startsWith(`${kind}/`);
|
|
13993
|
+
return { bytes, mime: usable ? header : fallback };
|
|
13994
|
+
}
|
|
13995
|
+
function imageUsage2(ctx) {
|
|
13996
|
+
return {
|
|
13997
|
+
model: ctx.model.id,
|
|
13998
|
+
provider: "luma",
|
|
13999
|
+
modality: "IMAGE",
|
|
14000
|
+
unit: "images",
|
|
14001
|
+
quantity: 1,
|
|
14002
|
+
imageSize: "2K"
|
|
14003
|
+
};
|
|
14004
|
+
}
|
|
14005
|
+
var GENERATE_SECONDS = 5;
|
|
14006
|
+
var MAX_PLAUSIBLE_SECONDS = 60;
|
|
14007
|
+
function billedSeconds(req, mode, bytes) {
|
|
14008
|
+
if (mode === "generate") return GENERATE_SECONDS;
|
|
14009
|
+
const measured = mp4DurationSeconds(bytes);
|
|
14010
|
+
const source2 = req.sourceVideo;
|
|
14011
|
+
const length = measured !== void 0 && measured > 0 && measured <= MAX_PLAUSIBLE_SECONDS ? measured : source2 !== void 0 && "url" in source2 ? source2.durationSeconds : void 0;
|
|
14012
|
+
return Math.max(length ?? 0, GENERATE_SECONDS);
|
|
14013
|
+
}
|
|
14014
|
+
function videoUsage4(ctx, req, mode, bytes) {
|
|
14015
|
+
const seconds3 = billedSeconds(req, mode, bytes);
|
|
14016
|
+
const event = {
|
|
14017
|
+
model: ctx.model.id,
|
|
14018
|
+
provider: "luma",
|
|
14019
|
+
modality: "VIDEO",
|
|
14020
|
+
unit: "seconds",
|
|
14021
|
+
quantity: seconds3,
|
|
14022
|
+
durationSeconds: seconds3
|
|
14023
|
+
};
|
|
14024
|
+
const resolution = sentResolution(req, mode);
|
|
14025
|
+
if (resolution !== void 0) event.resolution = resolution;
|
|
14026
|
+
return event;
|
|
14027
|
+
}
|
|
14028
|
+
function imageBody(req, ctx, outputFormat) {
|
|
14029
|
+
const prompt = checkPrompt(req, ctx);
|
|
14030
|
+
const model = ctx.model.providerModelId;
|
|
14031
|
+
const ratio = req.aspectRatio !== "adaptive" ? req.aspectRatio : void 0;
|
|
14032
|
+
const [source2, ...rest] = req.references ?? [];
|
|
14033
|
+
if (source2 === void 0) {
|
|
14034
|
+
const body2 = { model, type: "image", prompt };
|
|
14035
|
+
if (ratio !== void 0) body2["aspect_ratio"] = ratio;
|
|
14036
|
+
if (outputFormat !== void 0) body2["output_format"] = outputFormat;
|
|
14037
|
+
return body2;
|
|
14038
|
+
}
|
|
14039
|
+
if (ratio !== void 0) {
|
|
14040
|
+
ctx.warnings.push({
|
|
14041
|
+
code: "option_ignored",
|
|
14042
|
+
field: "aspectRatio",
|
|
14043
|
+
message: `${ctx.model.id} keeps the source image's aspect ratio on an edit`
|
|
14044
|
+
});
|
|
14045
|
+
}
|
|
14046
|
+
const body = {
|
|
14047
|
+
model,
|
|
14048
|
+
type: "image_edit",
|
|
14049
|
+
prompt,
|
|
14050
|
+
source: imageRef(source2)
|
|
14051
|
+
};
|
|
14052
|
+
if (rest.length > 0) body["image_ref"] = rest.map(imageRef);
|
|
14053
|
+
if (outputFormat !== void 0) body["output_format"] = outputFormat;
|
|
14054
|
+
return body;
|
|
14055
|
+
}
|
|
14056
|
+
function videoBody(req, ctx, mode) {
|
|
14057
|
+
const prompt = checkPrompt(req, ctx);
|
|
14058
|
+
const model = ctx.model.providerModelId;
|
|
14059
|
+
const hasReferences = (req.referenceImages ?? []).length + (req.referenceVideos ?? []).length + (req.referenceAudios ?? []).length > 0;
|
|
14060
|
+
if (hasReferences) {
|
|
14061
|
+
refuseOrDrop(
|
|
14062
|
+
ctx,
|
|
14063
|
+
"referenceImages",
|
|
14064
|
+
`${ctx.model.id} takes no reference images, videos or audio`
|
|
14065
|
+
);
|
|
14066
|
+
}
|
|
14067
|
+
if (mode === "generate") {
|
|
14068
|
+
const body = {
|
|
14069
|
+
model,
|
|
14070
|
+
type: "video",
|
|
14071
|
+
prompt,
|
|
14072
|
+
video: {
|
|
14073
|
+
...req.resolution !== void 0 && { resolution: req.resolution },
|
|
14074
|
+
duration: "5s",
|
|
14075
|
+
...req.firstFrame !== void 0 && { start_frame: imageRef(req.firstFrame) },
|
|
14076
|
+
...req.lastFrame !== void 0 && { end_frame: imageRef(req.lastFrame) }
|
|
14077
|
+
}
|
|
14078
|
+
};
|
|
14079
|
+
if (req.aspectRatio !== void 0 && req.aspectRatio !== "adaptive") {
|
|
14080
|
+
body["aspect_ratio"] = req.aspectRatio;
|
|
14081
|
+
}
|
|
14082
|
+
return body;
|
|
14083
|
+
}
|
|
14084
|
+
const sourceVideo = req.sourceVideo;
|
|
14085
|
+
if (!sourceVideo) {
|
|
14086
|
+
throw new ModelKitError({
|
|
14087
|
+
code: "missing_input",
|
|
14088
|
+
message: `${ctx.model.id} requires sourceVideo`,
|
|
14089
|
+
provider: "luma",
|
|
14090
|
+
model: ctx.model.id,
|
|
14091
|
+
retryable: false
|
|
14092
|
+
});
|
|
14093
|
+
}
|
|
14094
|
+
if (mode === "edit") {
|
|
14095
|
+
if (req.lastFrame !== void 0) {
|
|
14096
|
+
refuseOrDrop(ctx, "lastFrame", `${ctx.model.id} takes no end frame`);
|
|
14097
|
+
}
|
|
14098
|
+
const body = {
|
|
14099
|
+
model,
|
|
14100
|
+
type: "video_edit",
|
|
14101
|
+
prompt,
|
|
14102
|
+
source: videoRef(sourceVideo),
|
|
14103
|
+
video: {
|
|
14104
|
+
...req.resolution !== void 0 && { resolution: req.resolution },
|
|
14105
|
+
...req.firstFrame !== void 0 && { start_frame: imageRef(req.firstFrame) },
|
|
14106
|
+
edit: { auto_controls: true }
|
|
14107
|
+
}
|
|
14108
|
+
};
|
|
14109
|
+
return body;
|
|
14110
|
+
}
|
|
14111
|
+
if (req.firstFrame !== void 0) {
|
|
14112
|
+
refuseOrDrop(ctx, "firstFrame", `${ctx.model.id} takes no start frame`);
|
|
14113
|
+
}
|
|
14114
|
+
if (req.lastFrame !== void 0) {
|
|
14115
|
+
refuseOrDrop(ctx, "lastFrame", `${ctx.model.id} takes no end frame`);
|
|
14116
|
+
}
|
|
14117
|
+
const aspectRatio = req.aspectRatio;
|
|
14118
|
+
if (aspectRatio === void 0 || aspectRatio === "adaptive") {
|
|
14119
|
+
throw new ModelKitError({
|
|
14120
|
+
code: "missing_input",
|
|
14121
|
+
message: `${ctx.model.id} needs an aspectRatio target`,
|
|
14122
|
+
provider: "luma",
|
|
14123
|
+
model: ctx.model.id,
|
|
14124
|
+
retryable: false
|
|
14125
|
+
});
|
|
14126
|
+
}
|
|
14127
|
+
const resolution = lumaReframeResolution(req, ctx);
|
|
14128
|
+
return {
|
|
14129
|
+
model,
|
|
14130
|
+
type: "video_reframe",
|
|
14131
|
+
prompt,
|
|
14132
|
+
aspect_ratio: aspectRatio,
|
|
14133
|
+
source: videoRef(sourceVideo),
|
|
14134
|
+
video: { ...resolution !== void 0 && { resolution } }
|
|
14135
|
+
};
|
|
14136
|
+
}
|
|
14137
|
+
async function generateLumaImage(req, ctx) {
|
|
14138
|
+
throwIfAborted(ctx.signal);
|
|
14139
|
+
lumaKey(ctx);
|
|
14140
|
+
if (!LUMA_IMAGE_MODEL_IDS.has(ctx.model.providerModelId.toLowerCase())) {
|
|
14141
|
+
throw new ModelKitError({
|
|
14142
|
+
code: "unsupported_option",
|
|
14143
|
+
message: `luma has no image mapping for "${ctx.model.providerModelId}"`,
|
|
14144
|
+
provider: "luma",
|
|
14145
|
+
model: ctx.model.id,
|
|
14146
|
+
retryable: false
|
|
14147
|
+
});
|
|
14148
|
+
}
|
|
14149
|
+
const format = lumaOutputFormat(req, ctx);
|
|
14150
|
+
const created = await submitGeneration(ctx, imageBody(req, ctx, format));
|
|
14151
|
+
const url = await pollUntil(checkGeneration.bind(null, ctx, created.id, "image"), {
|
|
14152
|
+
intervalMs: IMAGE_POLL_INTERVAL_MS,
|
|
14153
|
+
timeoutMs: IMAGE_TIMEOUT_MS,
|
|
14154
|
+
...ctx.signal !== void 0 && { signal: ctx.signal }
|
|
14155
|
+
});
|
|
14156
|
+
const image = await downloadBytes(ctx, url, format === "jpeg" ? "image/jpeg" : "image/png");
|
|
14157
|
+
return {
|
|
14158
|
+
images: [image],
|
|
14159
|
+
usage: imageUsage2(ctx),
|
|
14160
|
+
raw: created
|
|
14161
|
+
};
|
|
14162
|
+
}
|
|
14163
|
+
function lumaVideoJob(ctx, req, mode, id) {
|
|
14164
|
+
return {
|
|
14165
|
+
jobId: id,
|
|
14166
|
+
async poll() {
|
|
14167
|
+
const generation = await readGenerationOnce(ctx, id);
|
|
14168
|
+
if (generation?.state === "failed") return { status: "failed" };
|
|
14169
|
+
if (generation?.state === "completed") return { status: "succeeded" };
|
|
14170
|
+
return { status: "pending" };
|
|
14171
|
+
},
|
|
14172
|
+
async result(opts) {
|
|
14173
|
+
const signal = opts?.signal ?? ctx.signal;
|
|
14174
|
+
const url = await pollUntil(checkGeneration.bind(null, ctx, id, "video"), {
|
|
14175
|
+
intervalMs: opts?.pollIntervalMs ?? VIDEO_POLL_INTERVAL_MS,
|
|
14176
|
+
timeoutMs: opts?.timeoutMs ?? VIDEO_TIMEOUT_MS,
|
|
14177
|
+
...signal !== void 0 && { signal }
|
|
14178
|
+
});
|
|
14179
|
+
const video = await downloadBytes(ctx, url, "video/mp4");
|
|
14180
|
+
const result = {
|
|
14181
|
+
video,
|
|
14182
|
+
usage: videoUsage4(ctx, req, mode, video.bytes),
|
|
14183
|
+
raw: { id }
|
|
14184
|
+
};
|
|
14185
|
+
return result;
|
|
14186
|
+
}
|
|
14187
|
+
};
|
|
14188
|
+
}
|
|
14189
|
+
async function generateLumaVideo(req, ctx) {
|
|
14190
|
+
throwIfAborted(ctx.signal);
|
|
14191
|
+
lumaKey(ctx);
|
|
14192
|
+
if (ctx.model.providerModelId.toLowerCase() !== LUMA_VIDEO_MODEL_ID) {
|
|
14193
|
+
throw new ModelKitError({
|
|
14194
|
+
code: "unsupported_option",
|
|
14195
|
+
message: `luma has no video mapping for "${ctx.model.providerModelId}"`,
|
|
14196
|
+
provider: "luma",
|
|
14197
|
+
model: ctx.model.id,
|
|
14198
|
+
retryable: false
|
|
14199
|
+
});
|
|
14200
|
+
}
|
|
14201
|
+
const mode = lumaVideoMode(ctx);
|
|
14202
|
+
const created = await submitGeneration(ctx, videoBody(req, ctx, mode));
|
|
14203
|
+
return lumaVideoJob(ctx, req, mode, created.id);
|
|
14204
|
+
}
|
|
14205
|
+
var lumaAdapter = {
|
|
14206
|
+
id: "luma",
|
|
14207
|
+
generateImage: generateLumaImage,
|
|
14208
|
+
generateVideo: generateLumaVideo,
|
|
14209
|
+
resumeVideo: (req, jobId, ctx) => {
|
|
14210
|
+
throwIfAborted(ctx.signal);
|
|
14211
|
+
lumaKey(ctx);
|
|
14212
|
+
return lumaVideoJob(ctx, req, lumaVideoMode(ctx), jobId);
|
|
14213
|
+
}
|
|
14214
|
+
};
|
|
14215
|
+
|
|
13455
14216
|
// src/adapters/openai-image.ts
|
|
13456
14217
|
import OpenAI from "openai";
|
|
13457
|
-
import { z as
|
|
14218
|
+
import { z as z26 } from "zod";
|
|
13458
14219
|
var MAX_EDIT_REFERENCES = 16;
|
|
13459
14220
|
function aspectRatioToSize(ratio, tier) {
|
|
13460
14221
|
const TIER_LONG_EDGE = {
|
|
@@ -13537,9 +14298,9 @@ function toProviderError2(cause, ctx) {
|
|
|
13537
14298
|
ctx.model.id
|
|
13538
14299
|
);
|
|
13539
14300
|
}
|
|
13540
|
-
var openaiUsageSchema =
|
|
13541
|
-
input_tokens:
|
|
13542
|
-
output_tokens:
|
|
14301
|
+
var openaiUsageSchema = z26.object({
|
|
14302
|
+
input_tokens: z26.number().optional(),
|
|
14303
|
+
output_tokens: z26.number().optional()
|
|
13543
14304
|
});
|
|
13544
14305
|
var openaiImageAdapter = {
|
|
13545
14306
|
id: "openai-image",
|
|
@@ -13951,13 +14712,13 @@ var prodiaAdapter = {
|
|
|
13951
14712
|
import Replicate from "replicate";
|
|
13952
14713
|
|
|
13953
14714
|
// src/adapters/replicate-http.ts
|
|
13954
|
-
import { z as
|
|
13955
|
-
var predictionSchema =
|
|
13956
|
-
id:
|
|
13957
|
-
status:
|
|
14715
|
+
import { z as z27 } from "zod";
|
|
14716
|
+
var predictionSchema = z27.object({
|
|
14717
|
+
id: z27.string(),
|
|
14718
|
+
status: z27.string(),
|
|
13958
14719
|
output: JsonValueSchema.optional(),
|
|
13959
14720
|
error: JsonValueSchema.optional(),
|
|
13960
|
-
metrics:
|
|
14721
|
+
metrics: z27.object({ predict_time: z27.number().optional() }).optional()
|
|
13961
14722
|
});
|
|
13962
14723
|
function createReplicateHttpClient(opts) {
|
|
13963
14724
|
async function request(path, body, signal) {
|
|
@@ -14008,7 +14769,7 @@ function createReplicateHttpClient(opts) {
|
|
|
14008
14769
|
}
|
|
14009
14770
|
|
|
14010
14771
|
// src/adapters/replicate.ts
|
|
14011
|
-
import { z as
|
|
14772
|
+
import { z as z28 } from "zod";
|
|
14012
14773
|
var POLL_INTERVAL_MS = 1e3;
|
|
14013
14774
|
var POLL_TIMEOUT_MS = 15 * 6e4;
|
|
14014
14775
|
var defaultReplicateDeps = {
|
|
@@ -14048,8 +14809,8 @@ function route(providerModelId) {
|
|
|
14048
14809
|
if (!providerModelId.includes("/")) return { version: providerModelId };
|
|
14049
14810
|
return { model: providerModelId };
|
|
14050
14811
|
}
|
|
14051
|
-
var replicateResponseStatusSchema =
|
|
14052
|
-
response:
|
|
14812
|
+
var replicateResponseStatusSchema = z28.object({
|
|
14813
|
+
response: z28.object({ status: z28.number() }).partial()
|
|
14053
14814
|
});
|
|
14054
14815
|
function replicateError(cause, ctx) {
|
|
14055
14816
|
if (isModelKitError(cause)) return cause;
|
|
@@ -14072,7 +14833,7 @@ function isUrlFn(value) {
|
|
|
14072
14833
|
function extractOutputUrl(output) {
|
|
14073
14834
|
const root = Array.isArray(output) ? output[0] : output;
|
|
14074
14835
|
if (root === void 0) throw noOutput();
|
|
14075
|
-
const asString =
|
|
14836
|
+
const asString = z28.string().safeParse(root);
|
|
14076
14837
|
if (asString.success && asString.data) return asString.data;
|
|
14077
14838
|
if (root instanceof URL) return root.href;
|
|
14078
14839
|
if (isObjectOutput(root)) {
|
|
@@ -14081,15 +14842,15 @@ function extractOutputUrl(output) {
|
|
|
14081
14842
|
if (urlValue !== void 0 && isUrlFn(urlValue)) {
|
|
14082
14843
|
const called = urlValue();
|
|
14083
14844
|
if (called instanceof URL) return called.href;
|
|
14084
|
-
const calledString =
|
|
14845
|
+
const calledString = z28.string().safeParse(called);
|
|
14085
14846
|
if (calledString.success && calledString.data) return calledString.data;
|
|
14086
14847
|
} else {
|
|
14087
|
-
const direct =
|
|
14848
|
+
const direct = z28.string().safeParse(urlValue);
|
|
14088
14849
|
if (direct.success && direct.data) return direct.data;
|
|
14089
14850
|
}
|
|
14090
14851
|
}
|
|
14091
14852
|
if ("default" in root) {
|
|
14092
|
-
const fallback =
|
|
14853
|
+
const fallback = z28.string().safeParse(root.default);
|
|
14093
14854
|
if (fallback.success && fallback.data) return fallback.data;
|
|
14094
14855
|
}
|
|
14095
14856
|
}
|
|
@@ -14150,7 +14911,7 @@ async function runPrediction(ctx, input, deps) {
|
|
|
14150
14911
|
}
|
|
14151
14912
|
return void 0;
|
|
14152
14913
|
}, pollOpts);
|
|
14153
|
-
const predictTime =
|
|
14914
|
+
const predictTime = z28.number().safeParse(done.metrics?.predict_time);
|
|
14154
14915
|
if (done.output === void 0) throw noOutput();
|
|
14155
14916
|
return {
|
|
14156
14917
|
url: extractOutputUrl(done.output),
|
|
@@ -14158,7 +14919,7 @@ async function runPrediction(ctx, input, deps) {
|
|
|
14158
14919
|
raw: done
|
|
14159
14920
|
};
|
|
14160
14921
|
}
|
|
14161
|
-
function
|
|
14922
|
+
function imageUsage3(ctx, req) {
|
|
14162
14923
|
const event = {
|
|
14163
14924
|
model: ctx.model.id,
|
|
14164
14925
|
provider: "replicate",
|
|
@@ -14170,7 +14931,7 @@ function imageUsage2(ctx, req) {
|
|
|
14170
14931
|
if (req.quality !== void 0) event.imageQuality = req.quality;
|
|
14171
14932
|
return event;
|
|
14172
14933
|
}
|
|
14173
|
-
function
|
|
14934
|
+
function videoUsage5(ctx, req) {
|
|
14174
14935
|
const event = {
|
|
14175
14936
|
model: ctx.model.id,
|
|
14176
14937
|
provider: "replicate",
|
|
@@ -14396,7 +15157,7 @@ async function generateReplicateImage(req, ctx, deps) {
|
|
|
14396
15157
|
}
|
|
14397
15158
|
const { url, predictTime, raw } = await runPrediction(ctx, input, deps);
|
|
14398
15159
|
const file = await download(ctx, url);
|
|
14399
|
-
const usage3 =
|
|
15160
|
+
const usage3 = imageUsage3(ctx, req);
|
|
14400
15161
|
usage3.quantity = predictTime;
|
|
14401
15162
|
return { images: [{ bytes: file.bytes, mime: file.mime }], usage: usage3, raw, outputUrl: url };
|
|
14402
15163
|
}
|
|
@@ -14503,7 +15264,7 @@ async function generateReplicateVideo(req, ctx, deps) {
|
|
|
14503
15264
|
throw replicateError(cause, ctx);
|
|
14504
15265
|
}
|
|
14505
15266
|
if (current.status === "succeeded") {
|
|
14506
|
-
const predictTime =
|
|
15267
|
+
const predictTime = z28.number().safeParse(current.metrics?.predict_time);
|
|
14507
15268
|
if (current.output === void 0) throw noOutput();
|
|
14508
15269
|
return {
|
|
14509
15270
|
url: extractOutputUrl(current.output),
|
|
@@ -14522,7 +15283,7 @@ async function generateReplicateVideo(req, ctx, deps) {
|
|
|
14522
15283
|
return void 0;
|
|
14523
15284
|
};
|
|
14524
15285
|
const toResult = (done) => {
|
|
14525
|
-
const usage3 =
|
|
15286
|
+
const usage3 = videoUsage5(ctx, req);
|
|
14526
15287
|
usage3.quantity = done.predictTime;
|
|
14527
15288
|
return { video: { url: done.url }, usage: usage3, raw: done.raw };
|
|
14528
15289
|
};
|
|
@@ -14645,7 +15406,7 @@ async function generateReplicateAudio(req, ctx, deps) {
|
|
|
14645
15406
|
// src/adapters/xai-video.ts
|
|
14646
15407
|
import { experimental_generateVideo } from "ai";
|
|
14647
15408
|
import { createXai as createXai2 } from "@ai-sdk/xai";
|
|
14648
|
-
import { z as
|
|
15409
|
+
import { z as z29 } from "zod";
|
|
14649
15410
|
var POLL_INTERVAL_MS2 = 1e4;
|
|
14650
15411
|
var POLL_TIMEOUT_MS2 = 15 * 6e4;
|
|
14651
15412
|
var defaultXaiDeps = {
|
|
@@ -14658,8 +15419,8 @@ function createXaiVideoAdapter(deps = defaultXaiDeps) {
|
|
|
14658
15419
|
};
|
|
14659
15420
|
}
|
|
14660
15421
|
var xaiVideoAdapter = createXaiVideoAdapter();
|
|
14661
|
-
var xaiResponseStatusSchema =
|
|
14662
|
-
response:
|
|
15422
|
+
var xaiResponseStatusSchema = z29.object({
|
|
15423
|
+
response: z29.object({ status: z29.number() }).partial()
|
|
14663
15424
|
});
|
|
14664
15425
|
function xaiError(cause, ctx) {
|
|
14665
15426
|
const info = describeThrown(cause);
|
|
@@ -14667,12 +15428,12 @@ function xaiError(cause, ctx) {
|
|
|
14667
15428
|
const status = info.status ?? (nested.success ? nested.data.response?.status : void 0);
|
|
14668
15429
|
return classifyThrown("xai-video", cause, ctx.model.id, { status, body: info.body });
|
|
14669
15430
|
}
|
|
14670
|
-
var xaiMetaSchema =
|
|
15431
|
+
var xaiMetaSchema = z29.object({
|
|
14671
15432
|
videoUrl: JsonValueSchema.optional(),
|
|
14672
15433
|
costInUsdTicks: JsonValueSchema.optional(),
|
|
14673
15434
|
duration: JsonValueSchema.optional()
|
|
14674
15435
|
});
|
|
14675
|
-
var xaiProviderMetadataSchema =
|
|
15436
|
+
var xaiProviderMetadataSchema = z29.object({ xai: xaiMetaSchema });
|
|
14676
15437
|
function metaOf(result) {
|
|
14677
15438
|
const parsed = xaiProviderMetadataSchema.partial().safeParse(result.providerMetadata);
|
|
14678
15439
|
if (!parsed.success) return {};
|
|
@@ -14788,7 +15549,7 @@ async function mapResult(ctx, req, result) {
|
|
|
14788
15549
|
};
|
|
14789
15550
|
}
|
|
14790
15551
|
const meta = metaOf(result);
|
|
14791
|
-
const videoUrl =
|
|
15552
|
+
const videoUrl = z29.string().safeParse(meta.videoUrl);
|
|
14792
15553
|
if (videoUrl.success && videoUrl.data) {
|
|
14793
15554
|
const res = await ctx.fetch(videoUrl.data);
|
|
14794
15555
|
if (!res.ok) {
|
|
@@ -14811,7 +15572,7 @@ async function mapResult(ctx, req, result) {
|
|
|
14811
15572
|
});
|
|
14812
15573
|
}
|
|
14813
15574
|
function usage2(ctx, req, meta) {
|
|
14814
|
-
const costTicks =
|
|
15575
|
+
const costTicks = z29.number().safeParse(meta.costInUsdTicks);
|
|
14815
15576
|
const cost = costTicks.success ? costTicks.data / 1e10 : void 0;
|
|
14816
15577
|
const event = {
|
|
14817
15578
|
model: ctx.model.id,
|
|
@@ -14859,7 +15620,8 @@ var DEFAULT_ADAPTERS = {
|
|
|
14859
15620
|
replicate: replicateAdapter,
|
|
14860
15621
|
prodia: prodiaAdapter,
|
|
14861
15622
|
higgsfield: higgsfieldAdapter,
|
|
14862
|
-
"xai-video": xaiVideoAdapter
|
|
15623
|
+
"xai-video": xaiVideoAdapter,
|
|
15624
|
+
luma: lumaAdapter
|
|
14863
15625
|
};
|
|
14864
15626
|
|
|
14865
15627
|
// src/catalog/data-only.ts
|
|
@@ -14975,6 +15737,10 @@ function dataOnlyCapable(row2) {
|
|
|
14975
15737
|
reason: "higgsfield providerModelId must be a platform path, not a URL"
|
|
14976
15738
|
};
|
|
14977
15739
|
}
|
|
15740
|
+
case "luma": {
|
|
15741
|
+
const reason = lumaRowRefusal(row2);
|
|
15742
|
+
return reason === void 0 ? { ok: true } : { ok: false, reason };
|
|
15743
|
+
}
|
|
14978
15744
|
default: {
|
|
14979
15745
|
return assertNever(row2.adapter);
|
|
14980
15746
|
}
|
|
@@ -14994,22 +15760,22 @@ var liveState = store[KEY] ??= {
|
|
|
14994
15760
|
var liveCatalog = liveState.catalog;
|
|
14995
15761
|
|
|
14996
15762
|
// src/catalog/load.ts
|
|
14997
|
-
import { z as
|
|
15763
|
+
import { z as z30 } from "zod";
|
|
14998
15764
|
function rowCount() {
|
|
14999
15765
|
return liveCatalog.list({ lifecycle: ["active", "deprecated", "retired"] }).length;
|
|
15000
15766
|
}
|
|
15001
15767
|
function authHeaders(auth) {
|
|
15002
15768
|
return "bearer" in auth ? { Authorization: `Bearer ${auth.bearer}` } : { "x-api-key": auth.apiKey };
|
|
15003
15769
|
}
|
|
15004
|
-
var EnvelopeSchema =
|
|
15005
|
-
rows:
|
|
15006
|
-
revision:
|
|
15770
|
+
var EnvelopeSchema = z30.object({
|
|
15771
|
+
rows: z30.array(JsonValueSchema),
|
|
15772
|
+
revision: z30.string().optional()
|
|
15007
15773
|
});
|
|
15008
15774
|
function dropReason(path, message) {
|
|
15009
15775
|
return path.length === 0 ? message : `${path.map((part) => String(part)).join(".")} ${message}`;
|
|
15010
15776
|
}
|
|
15011
15777
|
function rowId(raw) {
|
|
15012
|
-
const parsed =
|
|
15778
|
+
const parsed = z30.object({ id: z30.string().min(1) }).loose().safeParse(raw);
|
|
15013
15779
|
if (!parsed.success) return "?";
|
|
15014
15780
|
return parsed.data.id;
|
|
15015
15781
|
}
|
|
@@ -16058,7 +16824,8 @@ var ADAPTER_KEYS = {
|
|
|
16058
16824
|
replicate: ["replicate"],
|
|
16059
16825
|
prodia: ["prodia"],
|
|
16060
16826
|
higgsfield: ["higgsfield"],
|
|
16061
|
-
"xai-video": ["xai"]
|
|
16827
|
+
"xai-video": ["xai"],
|
|
16828
|
+
luma: ["luma"]
|
|
16062
16829
|
};
|
|
16063
16830
|
function hasAll(keys, names) {
|
|
16064
16831
|
if (!keys) return false;
|
|
@@ -16116,6 +16883,7 @@ function keysFromEnv(env, prefix = "") {
|
|
|
16116
16883
|
set("prodia", pick2("PRODIA_API_KEY", "PRODIA_TOKEN"));
|
|
16117
16884
|
set("higgsfield", pick2("HIGGSFIELD_API_KEY"));
|
|
16118
16885
|
set("higgsfieldSecret", pick2("HIGGSFIELD_API_SECRET"));
|
|
16886
|
+
set("luma", pick2("LUMA_API_KEY", "LUMA_AGENTS_API_KEY"));
|
|
16119
16887
|
set("cloudflare", pick2("CLOUDFLARE_AI_GATEWAY_TOKEN", "CF_AIG_TOKEN"));
|
|
16120
16888
|
const bearer = pick2("AWS_BEARER_TOKEN_BEDROCK");
|
|
16121
16889
|
const accessKeyId = pick2("AWS_ACCESS_KEY_ID");
|
|
@@ -16138,7 +16906,7 @@ function keysFromEnv(env, prefix = "") {
|
|
|
16138
16906
|
|
|
16139
16907
|
// src/text.ts
|
|
16140
16908
|
import "ai";
|
|
16141
|
-
import { z as
|
|
16909
|
+
import { z as z31 } from "zod";
|
|
16142
16910
|
function mergeTextProviderOptions(catalog, caller) {
|
|
16143
16911
|
const merged = {};
|
|
16144
16912
|
const catalogOptions = catalog.providerOptions ?? {};
|
|
@@ -16177,8 +16945,8 @@ function passthroughTextModel(model) {
|
|
|
16177
16945
|
pricingKind: "token"
|
|
16178
16946
|
};
|
|
16179
16947
|
}
|
|
16180
|
-
var perplexityCostSchema =
|
|
16181
|
-
perplexity:
|
|
16948
|
+
var perplexityCostSchema = z31.object({
|
|
16949
|
+
perplexity: z31.object({ cost: z31.object({ totalCost: z31.number().finite().nonnegative() }) })
|
|
16182
16950
|
});
|
|
16183
16951
|
function reportedCostUsd(metadata) {
|
|
16184
16952
|
const parsed = perplexityCostSchema.safeParse(metadata);
|
|
@@ -16258,7 +17026,7 @@ import {
|
|
|
16258
17026
|
streamObject as aiStreamObject2,
|
|
16259
17027
|
streamText as aiStreamText2
|
|
16260
17028
|
} from "ai";
|
|
16261
|
-
import { z as
|
|
17029
|
+
import { z as z32 } from "zod";
|
|
16262
17030
|
|
|
16263
17031
|
// src/generated-image.ts
|
|
16264
17032
|
function toGeneratedImage(image) {
|
|
@@ -16607,10 +17375,10 @@ function textAbortOptions(sdk, context) {
|
|
|
16607
17375
|
if (abortSignal) return { abortSignal };
|
|
16608
17376
|
return {};
|
|
16609
17377
|
}
|
|
16610
|
-
var catalogId =
|
|
16611
|
-
var exactSize =
|
|
16612
|
-
var sdkRatio =
|
|
16613
|
-
var sizeTier =
|
|
17378
|
+
var catalogId = z32.string();
|
|
17379
|
+
var exactSize = z32.templateLiteral([z32.number(), "x", z32.number()]);
|
|
17380
|
+
var sdkRatio = z32.templateLiteral([z32.number(), ":", z32.number()]);
|
|
17381
|
+
var sizeTier = z32.enum(["512", "1K", "2K", "4K"]);
|
|
16614
17382
|
function isCatalogId(model) {
|
|
16615
17383
|
return catalogId.safeParse(model).success;
|
|
16616
17384
|
}
|
|
@@ -17354,6 +18122,7 @@ export {
|
|
|
17354
18122
|
languageModel,
|
|
17355
18123
|
liveCatalog,
|
|
17356
18124
|
liveState,
|
|
18125
|
+
lumaAdapter,
|
|
17357
18126
|
mergeTextProviderOptions,
|
|
17358
18127
|
missingTierKeys,
|
|
17359
18128
|
model3dCall,
|