@shop-os/modelkit 0.6.1 → 0.7.0
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 +12 -0
- package/README.md +3 -3
- package/dist/catalog.cjs +205 -46
- 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 +205 -46
- package/dist/catalog.js.map +1 -1
- package/dist/index.cjs +857 -90
- 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 +856 -90
- 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
|
|
@@ -6787,7 +6945,8 @@ var ADAPTER_IDS = [
|
|
|
6787
6945
|
"replicate",
|
|
6788
6946
|
"prodia",
|
|
6789
6947
|
"higgsfield",
|
|
6790
|
-
"xai-video"
|
|
6948
|
+
"xai-video",
|
|
6949
|
+
"luma"
|
|
6791
6950
|
];
|
|
6792
6951
|
var ModelTypeSchema = z3.enum([
|
|
6793
6952
|
"text",
|
|
@@ -13452,9 +13611,608 @@ var higgsfieldAdapter = {
|
|
|
13452
13611
|
}
|
|
13453
13612
|
};
|
|
13454
13613
|
|
|
13614
|
+
// src/adapters/luma.ts
|
|
13615
|
+
import { z as z25 } from "zod";
|
|
13616
|
+
|
|
13617
|
+
// src/adapters/mp4-duration.ts
|
|
13618
|
+
function mp4DurationSeconds(bytes) {
|
|
13619
|
+
const moov = findBox(bytes, 0, bytes.length, "moov");
|
|
13620
|
+
if (!moov) return void 0;
|
|
13621
|
+
const mvhd = findBox(bytes, moov.start + 8, moov.end, "mvhd");
|
|
13622
|
+
if (!mvhd) return void 0;
|
|
13623
|
+
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
13624
|
+
const size = mvhd.end - mvhd.start;
|
|
13625
|
+
if (size < 8 + 4) return void 0;
|
|
13626
|
+
const version = view.getUint8(mvhd.start + 8);
|
|
13627
|
+
if (version === 0) {
|
|
13628
|
+
if (size < 8 + 4 + 4 + 4 + 4 + 4) return void 0;
|
|
13629
|
+
const timescale = view.getUint32(mvhd.start + 8 + 4 + 4 + 4);
|
|
13630
|
+
const duration = view.getUint32(mvhd.start + 8 + 4 + 4 + 4 + 4);
|
|
13631
|
+
if (timescale === 0) return void 0;
|
|
13632
|
+
return duration / timescale;
|
|
13633
|
+
}
|
|
13634
|
+
if (version === 1) {
|
|
13635
|
+
if (size < 8 + 4 + 8 + 8 + 4 + 8) return void 0;
|
|
13636
|
+
const timescale = view.getUint32(mvhd.start + 8 + 4 + 8 + 8);
|
|
13637
|
+
const high = view.getUint32(mvhd.start + 8 + 4 + 8 + 8 + 4);
|
|
13638
|
+
const low = view.getUint32(mvhd.start + 8 + 4 + 8 + 8 + 4 + 4);
|
|
13639
|
+
if (timescale === 0) return void 0;
|
|
13640
|
+
return (high * 2 ** 32 + low) / timescale;
|
|
13641
|
+
}
|
|
13642
|
+
return void 0;
|
|
13643
|
+
}
|
|
13644
|
+
function findBox(bytes, from, to, type) {
|
|
13645
|
+
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
13646
|
+
let offset = from;
|
|
13647
|
+
while (offset + 8 <= to) {
|
|
13648
|
+
const size = view.getUint32(offset);
|
|
13649
|
+
const name = String.fromCharCode(
|
|
13650
|
+
view.getUint8(offset + 4),
|
|
13651
|
+
view.getUint8(offset + 5),
|
|
13652
|
+
view.getUint8(offset + 6),
|
|
13653
|
+
view.getUint8(offset + 7)
|
|
13654
|
+
);
|
|
13655
|
+
if (size < 8 || offset + size > to) return void 0;
|
|
13656
|
+
if (name === type) return { start: offset, end: offset + size };
|
|
13657
|
+
offset += size;
|
|
13658
|
+
}
|
|
13659
|
+
return void 0;
|
|
13660
|
+
}
|
|
13661
|
+
|
|
13662
|
+
// src/adapters/luma.ts
|
|
13663
|
+
var DEFAULT_BASE_URL = "https://agents.lumalabs.ai";
|
|
13664
|
+
var IMAGE_POLL_INTERVAL_MS = 3e3;
|
|
13665
|
+
var IMAGE_TIMEOUT_MS = 5 * 6e4;
|
|
13666
|
+
var VIDEO_POLL_INTERVAL_MS = 5e3;
|
|
13667
|
+
var VIDEO_TIMEOUT_MS = 20 * 6e4;
|
|
13668
|
+
var PROMPT_MAX_CHARS = 6e3;
|
|
13669
|
+
var LUMA_IMAGE_MODEL_IDS = /* @__PURE__ */ new Set(["uni-1", "uni-1-max"]);
|
|
13670
|
+
var LUMA_VIDEO_MODEL_ID = "ray-3.2";
|
|
13671
|
+
var LUMA_VIDEO_MODES = /* @__PURE__ */ new Map([
|
|
13672
|
+
["ray-3.2", "generate"],
|
|
13673
|
+
["ray-3.2-edit", "edit"],
|
|
13674
|
+
["ray-3.2-reframe", "reframe"]
|
|
13675
|
+
]);
|
|
13676
|
+
function lumaRowRefusal(row2) {
|
|
13677
|
+
const provider = row2.providerModelId.toLowerCase();
|
|
13678
|
+
if (row2.type === "image") {
|
|
13679
|
+
return LUMA_IMAGE_MODEL_IDS.has(provider) ? void 0 : "luma image rows need providerModelId uni-1 or uni-1-max";
|
|
13680
|
+
}
|
|
13681
|
+
if (row2.type === "video") {
|
|
13682
|
+
if (provider !== LUMA_VIDEO_MODEL_ID) return "luma video rows need providerModelId ray-3.2";
|
|
13683
|
+
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;
|
|
13684
|
+
}
|
|
13685
|
+
return `luma has no ${row2.type} rows`;
|
|
13686
|
+
}
|
|
13687
|
+
function lumaBase(ctx) {
|
|
13688
|
+
return ctx.endpoints?.luma ?? DEFAULT_BASE_URL;
|
|
13689
|
+
}
|
|
13690
|
+
function lumaKey(ctx) {
|
|
13691
|
+
const key = ctx.keys.luma;
|
|
13692
|
+
if (!key) {
|
|
13693
|
+
throw new ModelKitError({
|
|
13694
|
+
code: "auth",
|
|
13695
|
+
message: "Missing API key for luma",
|
|
13696
|
+
provider: "luma",
|
|
13697
|
+
model: ctx.model.id,
|
|
13698
|
+
retryable: false
|
|
13699
|
+
});
|
|
13700
|
+
}
|
|
13701
|
+
return key;
|
|
13702
|
+
}
|
|
13703
|
+
function checkPrompt(req, ctx) {
|
|
13704
|
+
const prompt = req.prompt.trim();
|
|
13705
|
+
if (prompt.length === 0) {
|
|
13706
|
+
throw new ModelKitError({
|
|
13707
|
+
code: "missing_input",
|
|
13708
|
+
message: `${ctx.model.id} needs a prompt`,
|
|
13709
|
+
provider: "luma",
|
|
13710
|
+
model: ctx.model.id,
|
|
13711
|
+
retryable: false
|
|
13712
|
+
});
|
|
13713
|
+
}
|
|
13714
|
+
if (req.prompt.length > PROMPT_MAX_CHARS) {
|
|
13715
|
+
throw new ModelKitError({
|
|
13716
|
+
code: "unsupported_option",
|
|
13717
|
+
message: `${ctx.model.id} takes a prompt of at most ${PROMPT_MAX_CHARS} characters`,
|
|
13718
|
+
provider: "luma",
|
|
13719
|
+
model: ctx.model.id,
|
|
13720
|
+
retryable: false
|
|
13721
|
+
});
|
|
13722
|
+
}
|
|
13723
|
+
return req.prompt;
|
|
13724
|
+
}
|
|
13725
|
+
function imageRef(ref) {
|
|
13726
|
+
if ("url" in ref) return { url: ref.url };
|
|
13727
|
+
return { data: mediaRefToBase64(ref.bytes), media_type: ref.mime };
|
|
13728
|
+
}
|
|
13729
|
+
function videoRef(ref) {
|
|
13730
|
+
if ("url" in ref) return { url: ref.url, media_type: "video/mp4" };
|
|
13731
|
+
const mediaType = ref.mime.startsWith("video/") ? ref.mime : "video/mp4";
|
|
13732
|
+
return { data: mediaRefToBase64(ref.bytes), media_type: mediaType };
|
|
13733
|
+
}
|
|
13734
|
+
function lumaOutputFormat(req, ctx) {
|
|
13735
|
+
const format = req.outputFormat;
|
|
13736
|
+
if (format === void 0 || format === "png" || format === "jpeg") return format;
|
|
13737
|
+
if ((ctx.call.onUnsupported ?? "error") === "error") {
|
|
13738
|
+
throw new ModelKitError({
|
|
13739
|
+
code: "unsupported_option",
|
|
13740
|
+
message: `${ctx.model.id} has no outputFormat "${format}". Supported: png, jpeg.`,
|
|
13741
|
+
provider: "luma",
|
|
13742
|
+
model: ctx.model.id,
|
|
13743
|
+
retryable: false
|
|
13744
|
+
});
|
|
13745
|
+
}
|
|
13746
|
+
ctx.warnings.push({
|
|
13747
|
+
code: "option_ignored",
|
|
13748
|
+
field: "outputFormat",
|
|
13749
|
+
from: format,
|
|
13750
|
+
to: "png",
|
|
13751
|
+
message: `${ctx.model.id} has no outputFormat "${format}"; using png`
|
|
13752
|
+
});
|
|
13753
|
+
return "png";
|
|
13754
|
+
}
|
|
13755
|
+
function refuseOrDrop(ctx, field, message) {
|
|
13756
|
+
if ((ctx.call.onUnsupported ?? "error") === "error") {
|
|
13757
|
+
throw new ModelKitError({
|
|
13758
|
+
code: "unsupported_option",
|
|
13759
|
+
message,
|
|
13760
|
+
provider: "luma",
|
|
13761
|
+
model: ctx.model.id,
|
|
13762
|
+
retryable: false
|
|
13763
|
+
});
|
|
13764
|
+
}
|
|
13765
|
+
ctx.warnings.push({ code: "option_ignored", field, message });
|
|
13766
|
+
}
|
|
13767
|
+
function lumaVideoMode(ctx) {
|
|
13768
|
+
const mode = LUMA_VIDEO_MODES.get(ctx.model.id);
|
|
13769
|
+
if (mode === void 0) {
|
|
13770
|
+
throw new ModelKitError({
|
|
13771
|
+
code: "unsupported_option",
|
|
13772
|
+
message: `luma routes ray-3.2 rows by catalog id; "${ctx.model.id}" is not a luma video row`,
|
|
13773
|
+
provider: "luma",
|
|
13774
|
+
model: ctx.model.id,
|
|
13775
|
+
retryable: false
|
|
13776
|
+
});
|
|
13777
|
+
}
|
|
13778
|
+
return mode;
|
|
13779
|
+
}
|
|
13780
|
+
function reframeTooTall(req) {
|
|
13781
|
+
const vertical = req.aspectRatio === "9:16" || req.aspectRatio === "3:4";
|
|
13782
|
+
return vertical && req.resolution === "1080p";
|
|
13783
|
+
}
|
|
13784
|
+
function sentResolution(req, mode) {
|
|
13785
|
+
return mode === "reframe" && reframeTooTall(req) ? "720p" : req.resolution;
|
|
13786
|
+
}
|
|
13787
|
+
function lumaReframeResolution(req, ctx) {
|
|
13788
|
+
const requested = req.resolution;
|
|
13789
|
+
if (requested === void 0 || !reframeTooTall(req)) return requested;
|
|
13790
|
+
const message = `${ctx.model.id} renders 9:16 and 3:4 reframes at up to 720p`;
|
|
13791
|
+
if ((ctx.call.onUnsupported ?? "error") === "error") {
|
|
13792
|
+
throw new ModelKitError({
|
|
13793
|
+
code: "unsupported_option",
|
|
13794
|
+
message,
|
|
13795
|
+
provider: "luma",
|
|
13796
|
+
model: ctx.model.id,
|
|
13797
|
+
retryable: false
|
|
13798
|
+
});
|
|
13799
|
+
}
|
|
13800
|
+
ctx.warnings.push({
|
|
13801
|
+
code: "resolution_coerced",
|
|
13802
|
+
field: "resolution",
|
|
13803
|
+
from: requested,
|
|
13804
|
+
to: "720p",
|
|
13805
|
+
message
|
|
13806
|
+
});
|
|
13807
|
+
return "720p";
|
|
13808
|
+
}
|
|
13809
|
+
var lumaGenerationSchema = z25.looseObject({
|
|
13810
|
+
id: z25.string(),
|
|
13811
|
+
state: z25.string().optional(),
|
|
13812
|
+
output: z25.array(
|
|
13813
|
+
z25.looseObject({
|
|
13814
|
+
type: z25.string().optional(),
|
|
13815
|
+
url: z25.string().optional()
|
|
13816
|
+
})
|
|
13817
|
+
).optional(),
|
|
13818
|
+
failure_reason: z25.string().optional().nullable(),
|
|
13819
|
+
failure_code: z25.string().optional().nullable()
|
|
13820
|
+
});
|
|
13821
|
+
function lumaFailure(ctx, code, reason) {
|
|
13822
|
+
const detail = reason ?? code ?? "unknown_error";
|
|
13823
|
+
const message = `Luma generation failed: ${detail}`;
|
|
13824
|
+
switch (code) {
|
|
13825
|
+
case "content_moderated":
|
|
13826
|
+
return new ModelKitError({
|
|
13827
|
+
code: "content_blocked",
|
|
13828
|
+
message,
|
|
13829
|
+
provider: "luma",
|
|
13830
|
+
model: ctx.model.id,
|
|
13831
|
+
retryable: false
|
|
13832
|
+
});
|
|
13833
|
+
case "rate_limited":
|
|
13834
|
+
return new ModelKitError({
|
|
13835
|
+
code: "rate_limited",
|
|
13836
|
+
message,
|
|
13837
|
+
provider: "luma",
|
|
13838
|
+
model: ctx.model.id
|
|
13839
|
+
});
|
|
13840
|
+
case "generation_failed":
|
|
13841
|
+
case "output_not_found":
|
|
13842
|
+
return new ModelKitError({
|
|
13843
|
+
code: "provider_rejected",
|
|
13844
|
+
message,
|
|
13845
|
+
provider: "luma",
|
|
13846
|
+
model: ctx.model.id,
|
|
13847
|
+
retryable: true
|
|
13848
|
+
});
|
|
13849
|
+
case "budget_exhausted":
|
|
13850
|
+
return new ModelKitError({
|
|
13851
|
+
code: "provider_billing",
|
|
13852
|
+
message,
|
|
13853
|
+
provider: "luma",
|
|
13854
|
+
model: ctx.model.id,
|
|
13855
|
+
retryable: false
|
|
13856
|
+
});
|
|
13857
|
+
case "image_too_large":
|
|
13858
|
+
case "unsupported_format":
|
|
13859
|
+
return new ModelKitError({
|
|
13860
|
+
code: "unsupported_option",
|
|
13861
|
+
message,
|
|
13862
|
+
provider: "luma",
|
|
13863
|
+
model: ctx.model.id,
|
|
13864
|
+
retryable: false
|
|
13865
|
+
});
|
|
13866
|
+
default:
|
|
13867
|
+
return new ModelKitError({
|
|
13868
|
+
code: "provider_rejected",
|
|
13869
|
+
message,
|
|
13870
|
+
provider: "luma",
|
|
13871
|
+
model: ctx.model.id,
|
|
13872
|
+
retryable: false
|
|
13873
|
+
});
|
|
13874
|
+
}
|
|
13875
|
+
}
|
|
13876
|
+
function requestInit2(ctx, key, body) {
|
|
13877
|
+
const init = {
|
|
13878
|
+
method: body !== void 0 ? "POST" : "GET",
|
|
13879
|
+
headers: { Authorization: `Bearer ${key}`, "Content-Type": "application/json" }
|
|
13880
|
+
};
|
|
13881
|
+
if (body !== void 0) init.body = body;
|
|
13882
|
+
if (ctx.signal !== void 0) init.signal = ctx.signal;
|
|
13883
|
+
return init;
|
|
13884
|
+
}
|
|
13885
|
+
async function lumaRequest(ctx, url, body) {
|
|
13886
|
+
const key = lumaKey(ctx);
|
|
13887
|
+
let res;
|
|
13888
|
+
try {
|
|
13889
|
+
res = await ctx.fetch(url, requestInit2(ctx, key, body));
|
|
13890
|
+
} catch (cause) {
|
|
13891
|
+
throw classifyThrown("luma", cause, ctx.model.id);
|
|
13892
|
+
}
|
|
13893
|
+
if (!res.ok) {
|
|
13894
|
+
throw classifyHttpError(res.status, await readBody(res), "luma", ctx.model.id);
|
|
13895
|
+
}
|
|
13896
|
+
return res;
|
|
13897
|
+
}
|
|
13898
|
+
async function submitGeneration(ctx, body) {
|
|
13899
|
+
const retryOptions = mediaRetryOptions(ctx.call, ctx.signal);
|
|
13900
|
+
const res = await withRetry(
|
|
13901
|
+
() => lumaRequest(ctx, `${lumaBase(ctx)}/v1/generations`, JSON.stringify(body)),
|
|
13902
|
+
retryOptions
|
|
13903
|
+
);
|
|
13904
|
+
const parsed = lumaGenerationSchema.safeParse(await res.json());
|
|
13905
|
+
if (!parsed.success) {
|
|
13906
|
+
throw new ModelKitError({
|
|
13907
|
+
code: "provider_rejected",
|
|
13908
|
+
message: "Luma submit returned no generation id",
|
|
13909
|
+
provider: "luma",
|
|
13910
|
+
model: ctx.model.id,
|
|
13911
|
+
retryable: false
|
|
13912
|
+
});
|
|
13913
|
+
}
|
|
13914
|
+
return parsed.data;
|
|
13915
|
+
}
|
|
13916
|
+
async function readGeneration(ctx, id) {
|
|
13917
|
+
const res = await lumaRequest(ctx, `${lumaBase(ctx)}/v1/generations/${id}`);
|
|
13918
|
+
const payload = JsonValueSchema.parse(await res.json());
|
|
13919
|
+
const parsed = lumaGenerationSchema.safeParse(payload);
|
|
13920
|
+
if (!parsed.success) {
|
|
13921
|
+
throw new ModelKitError({
|
|
13922
|
+
code: "provider_rejected",
|
|
13923
|
+
message: "Luma returned an unreadable generation",
|
|
13924
|
+
provider: "luma",
|
|
13925
|
+
model: ctx.model.id,
|
|
13926
|
+
retryable: false
|
|
13927
|
+
});
|
|
13928
|
+
}
|
|
13929
|
+
return parsed.data;
|
|
13930
|
+
}
|
|
13931
|
+
function outputUrl(generation, type) {
|
|
13932
|
+
const outputs = generation.output ?? [];
|
|
13933
|
+
const match = outputs.find((item) => item.type === type && item.url);
|
|
13934
|
+
if (match?.url) return match.url;
|
|
13935
|
+
const fallback = outputs.find((item) => item.url);
|
|
13936
|
+
return fallback?.url;
|
|
13937
|
+
}
|
|
13938
|
+
async function readGenerationOnce(ctx, id) {
|
|
13939
|
+
try {
|
|
13940
|
+
return await readGeneration(ctx, id);
|
|
13941
|
+
} catch (cause) {
|
|
13942
|
+
if (ctx.call.maxRetries === 0) throw cause;
|
|
13943
|
+
if (isModelKitError(cause) && (cause.code === "network" || cause.status === 429 || (cause.status ?? 0) >= 500)) {
|
|
13944
|
+
return void 0;
|
|
13945
|
+
}
|
|
13946
|
+
throw cause;
|
|
13947
|
+
}
|
|
13948
|
+
}
|
|
13949
|
+
async function checkGeneration(ctx, id, type) {
|
|
13950
|
+
const generation = await readGenerationOnce(ctx, id);
|
|
13951
|
+
if (generation === void 0) return void 0;
|
|
13952
|
+
if (generation.state === "completed") {
|
|
13953
|
+
const url = outputUrl(generation, type);
|
|
13954
|
+
if (!url) {
|
|
13955
|
+
throw new ModelKitError({
|
|
13956
|
+
code: "provider_rejected",
|
|
13957
|
+
message: "Luma completed without an output URL",
|
|
13958
|
+
provider: "luma",
|
|
13959
|
+
model: ctx.model.id,
|
|
13960
|
+
retryable: false
|
|
13961
|
+
});
|
|
13962
|
+
}
|
|
13963
|
+
return url;
|
|
13964
|
+
}
|
|
13965
|
+
if (generation.state === "failed") {
|
|
13966
|
+
throw lumaFailure(
|
|
13967
|
+
ctx,
|
|
13968
|
+
generation.failure_code ?? void 0,
|
|
13969
|
+
generation.failure_reason ?? void 0
|
|
13970
|
+
);
|
|
13971
|
+
}
|
|
13972
|
+
return void 0;
|
|
13973
|
+
}
|
|
13974
|
+
async function downloadBytes(ctx, url, fallback) {
|
|
13975
|
+
let bytes;
|
|
13976
|
+
let header;
|
|
13977
|
+
try {
|
|
13978
|
+
const out = await mediaRefToBytes({ url }, ctx.fetch, {
|
|
13979
|
+
...ctx.signal !== void 0 && { signal: ctx.signal },
|
|
13980
|
+
provider: "luma",
|
|
13981
|
+
model: ctx.model.id
|
|
13982
|
+
});
|
|
13983
|
+
bytes = out.bytes;
|
|
13984
|
+
header = out.mime;
|
|
13985
|
+
} catch (cause) {
|
|
13986
|
+
throw classifyThrown("luma", cause, ctx.model.id);
|
|
13987
|
+
}
|
|
13988
|
+
const kind = fallback.split("/")[0];
|
|
13989
|
+
const usable = header !== void 0 && header.startsWith(`${kind}/`);
|
|
13990
|
+
return { bytes, mime: usable ? header : fallback };
|
|
13991
|
+
}
|
|
13992
|
+
function imageUsage2(ctx) {
|
|
13993
|
+
return {
|
|
13994
|
+
model: ctx.model.id,
|
|
13995
|
+
provider: "luma",
|
|
13996
|
+
modality: "IMAGE",
|
|
13997
|
+
unit: "images",
|
|
13998
|
+
quantity: 1,
|
|
13999
|
+
imageSize: "2K"
|
|
14000
|
+
};
|
|
14001
|
+
}
|
|
14002
|
+
var GENERATE_SECONDS = 5;
|
|
14003
|
+
var MAX_PLAUSIBLE_SECONDS = 60;
|
|
14004
|
+
function billedSeconds(req, mode, bytes) {
|
|
14005
|
+
if (mode === "generate") return GENERATE_SECONDS;
|
|
14006
|
+
const measured = mp4DurationSeconds(bytes);
|
|
14007
|
+
const source2 = req.sourceVideo;
|
|
14008
|
+
const length = measured !== void 0 && measured > 0 && measured <= MAX_PLAUSIBLE_SECONDS ? measured : source2 !== void 0 && "url" in source2 ? source2.durationSeconds : void 0;
|
|
14009
|
+
return Math.max(length ?? 0, GENERATE_SECONDS);
|
|
14010
|
+
}
|
|
14011
|
+
function videoUsage4(ctx, req, mode, bytes) {
|
|
14012
|
+
const seconds3 = billedSeconds(req, mode, bytes);
|
|
14013
|
+
const event = {
|
|
14014
|
+
model: ctx.model.id,
|
|
14015
|
+
provider: "luma",
|
|
14016
|
+
modality: "VIDEO",
|
|
14017
|
+
unit: "seconds",
|
|
14018
|
+
quantity: seconds3,
|
|
14019
|
+
durationSeconds: seconds3
|
|
14020
|
+
};
|
|
14021
|
+
const resolution = sentResolution(req, mode);
|
|
14022
|
+
if (resolution !== void 0) event.resolution = resolution;
|
|
14023
|
+
return event;
|
|
14024
|
+
}
|
|
14025
|
+
function imageBody(req, ctx, outputFormat) {
|
|
14026
|
+
const prompt = checkPrompt(req, ctx);
|
|
14027
|
+
const model = ctx.model.providerModelId;
|
|
14028
|
+
const ratio = req.aspectRatio !== "adaptive" ? req.aspectRatio : void 0;
|
|
14029
|
+
const [source2, ...rest] = req.references ?? [];
|
|
14030
|
+
if (source2 === void 0) {
|
|
14031
|
+
const body2 = { model, type: "image", prompt };
|
|
14032
|
+
if (ratio !== void 0) body2["aspect_ratio"] = ratio;
|
|
14033
|
+
if (outputFormat !== void 0) body2["output_format"] = outputFormat;
|
|
14034
|
+
return body2;
|
|
14035
|
+
}
|
|
14036
|
+
if (ratio !== void 0) {
|
|
14037
|
+
ctx.warnings.push({
|
|
14038
|
+
code: "option_ignored",
|
|
14039
|
+
field: "aspectRatio",
|
|
14040
|
+
message: `${ctx.model.id} keeps the source image's aspect ratio on an edit`
|
|
14041
|
+
});
|
|
14042
|
+
}
|
|
14043
|
+
const body = {
|
|
14044
|
+
model,
|
|
14045
|
+
type: "image_edit",
|
|
14046
|
+
prompt,
|
|
14047
|
+
source: imageRef(source2)
|
|
14048
|
+
};
|
|
14049
|
+
if (rest.length > 0) body["image_ref"] = rest.map(imageRef);
|
|
14050
|
+
if (outputFormat !== void 0) body["output_format"] = outputFormat;
|
|
14051
|
+
return body;
|
|
14052
|
+
}
|
|
14053
|
+
function videoBody(req, ctx, mode) {
|
|
14054
|
+
const prompt = checkPrompt(req, ctx);
|
|
14055
|
+
const model = ctx.model.providerModelId;
|
|
14056
|
+
const hasReferences = (req.referenceImages ?? []).length + (req.referenceVideos ?? []).length + (req.referenceAudios ?? []).length > 0;
|
|
14057
|
+
if (hasReferences) {
|
|
14058
|
+
refuseOrDrop(
|
|
14059
|
+
ctx,
|
|
14060
|
+
"referenceImages",
|
|
14061
|
+
`${ctx.model.id} takes no reference images, videos or audio`
|
|
14062
|
+
);
|
|
14063
|
+
}
|
|
14064
|
+
if (mode === "generate") {
|
|
14065
|
+
const body = {
|
|
14066
|
+
model,
|
|
14067
|
+
type: "video",
|
|
14068
|
+
prompt,
|
|
14069
|
+
video: {
|
|
14070
|
+
...req.resolution !== void 0 && { resolution: req.resolution },
|
|
14071
|
+
duration: "5s",
|
|
14072
|
+
...req.firstFrame !== void 0 && { start_frame: imageRef(req.firstFrame) },
|
|
14073
|
+
...req.lastFrame !== void 0 && { end_frame: imageRef(req.lastFrame) }
|
|
14074
|
+
}
|
|
14075
|
+
};
|
|
14076
|
+
if (req.aspectRatio !== void 0 && req.aspectRatio !== "adaptive") {
|
|
14077
|
+
body["aspect_ratio"] = req.aspectRatio;
|
|
14078
|
+
}
|
|
14079
|
+
return body;
|
|
14080
|
+
}
|
|
14081
|
+
const sourceVideo = req.sourceVideo;
|
|
14082
|
+
if (!sourceVideo) {
|
|
14083
|
+
throw new ModelKitError({
|
|
14084
|
+
code: "missing_input",
|
|
14085
|
+
message: `${ctx.model.id} requires sourceVideo`,
|
|
14086
|
+
provider: "luma",
|
|
14087
|
+
model: ctx.model.id,
|
|
14088
|
+
retryable: false
|
|
14089
|
+
});
|
|
14090
|
+
}
|
|
14091
|
+
if (mode === "edit") {
|
|
14092
|
+
if (req.lastFrame !== void 0) {
|
|
14093
|
+
refuseOrDrop(ctx, "lastFrame", `${ctx.model.id} takes no end frame`);
|
|
14094
|
+
}
|
|
14095
|
+
const body = {
|
|
14096
|
+
model,
|
|
14097
|
+
type: "video_edit",
|
|
14098
|
+
prompt,
|
|
14099
|
+
source: videoRef(sourceVideo),
|
|
14100
|
+
video: {
|
|
14101
|
+
...req.resolution !== void 0 && { resolution: req.resolution },
|
|
14102
|
+
...req.firstFrame !== void 0 && { start_frame: imageRef(req.firstFrame) },
|
|
14103
|
+
edit: { auto_controls: true }
|
|
14104
|
+
}
|
|
14105
|
+
};
|
|
14106
|
+
return body;
|
|
14107
|
+
}
|
|
14108
|
+
if (req.firstFrame !== void 0) {
|
|
14109
|
+
refuseOrDrop(ctx, "firstFrame", `${ctx.model.id} takes no start frame`);
|
|
14110
|
+
}
|
|
14111
|
+
if (req.lastFrame !== void 0) {
|
|
14112
|
+
refuseOrDrop(ctx, "lastFrame", `${ctx.model.id} takes no end frame`);
|
|
14113
|
+
}
|
|
14114
|
+
const aspectRatio = req.aspectRatio;
|
|
14115
|
+
if (aspectRatio === void 0 || aspectRatio === "adaptive") {
|
|
14116
|
+
throw new ModelKitError({
|
|
14117
|
+
code: "missing_input",
|
|
14118
|
+
message: `${ctx.model.id} needs an aspectRatio target`,
|
|
14119
|
+
provider: "luma",
|
|
14120
|
+
model: ctx.model.id,
|
|
14121
|
+
retryable: false
|
|
14122
|
+
});
|
|
14123
|
+
}
|
|
14124
|
+
const resolution = lumaReframeResolution(req, ctx);
|
|
14125
|
+
return {
|
|
14126
|
+
model,
|
|
14127
|
+
type: "video_reframe",
|
|
14128
|
+
prompt,
|
|
14129
|
+
aspect_ratio: aspectRatio,
|
|
14130
|
+
source: videoRef(sourceVideo),
|
|
14131
|
+
video: { ...resolution !== void 0 && { resolution } }
|
|
14132
|
+
};
|
|
14133
|
+
}
|
|
14134
|
+
async function generateLumaImage(req, ctx) {
|
|
14135
|
+
throwIfAborted(ctx.signal);
|
|
14136
|
+
lumaKey(ctx);
|
|
14137
|
+
if (!LUMA_IMAGE_MODEL_IDS.has(ctx.model.providerModelId.toLowerCase())) {
|
|
14138
|
+
throw new ModelKitError({
|
|
14139
|
+
code: "unsupported_option",
|
|
14140
|
+
message: `luma has no image mapping for "${ctx.model.providerModelId}"`,
|
|
14141
|
+
provider: "luma",
|
|
14142
|
+
model: ctx.model.id,
|
|
14143
|
+
retryable: false
|
|
14144
|
+
});
|
|
14145
|
+
}
|
|
14146
|
+
const format = lumaOutputFormat(req, ctx);
|
|
14147
|
+
const created = await submitGeneration(ctx, imageBody(req, ctx, format));
|
|
14148
|
+
const url = await pollUntil(checkGeneration.bind(null, ctx, created.id, "image"), {
|
|
14149
|
+
intervalMs: IMAGE_POLL_INTERVAL_MS,
|
|
14150
|
+
timeoutMs: IMAGE_TIMEOUT_MS,
|
|
14151
|
+
...ctx.signal !== void 0 && { signal: ctx.signal }
|
|
14152
|
+
});
|
|
14153
|
+
const image = await downloadBytes(ctx, url, format === "jpeg" ? "image/jpeg" : "image/png");
|
|
14154
|
+
return {
|
|
14155
|
+
images: [image],
|
|
14156
|
+
usage: imageUsage2(ctx),
|
|
14157
|
+
raw: created
|
|
14158
|
+
};
|
|
14159
|
+
}
|
|
14160
|
+
function lumaVideoJob(ctx, req, mode, id) {
|
|
14161
|
+
return {
|
|
14162
|
+
jobId: id,
|
|
14163
|
+
async poll() {
|
|
14164
|
+
const generation = await readGenerationOnce(ctx, id);
|
|
14165
|
+
if (generation?.state === "failed") return { status: "failed" };
|
|
14166
|
+
if (generation?.state === "completed") return { status: "succeeded" };
|
|
14167
|
+
return { status: "pending" };
|
|
14168
|
+
},
|
|
14169
|
+
async result(opts) {
|
|
14170
|
+
const signal = opts?.signal ?? ctx.signal;
|
|
14171
|
+
const url = await pollUntil(checkGeneration.bind(null, ctx, id, "video"), {
|
|
14172
|
+
intervalMs: opts?.pollIntervalMs ?? VIDEO_POLL_INTERVAL_MS,
|
|
14173
|
+
timeoutMs: opts?.timeoutMs ?? VIDEO_TIMEOUT_MS,
|
|
14174
|
+
...signal !== void 0 && { signal }
|
|
14175
|
+
});
|
|
14176
|
+
const video = await downloadBytes(ctx, url, "video/mp4");
|
|
14177
|
+
const result = {
|
|
14178
|
+
video,
|
|
14179
|
+
usage: videoUsage4(ctx, req, mode, video.bytes),
|
|
14180
|
+
raw: { id }
|
|
14181
|
+
};
|
|
14182
|
+
return result;
|
|
14183
|
+
}
|
|
14184
|
+
};
|
|
14185
|
+
}
|
|
14186
|
+
async function generateLumaVideo(req, ctx) {
|
|
14187
|
+
throwIfAborted(ctx.signal);
|
|
14188
|
+
lumaKey(ctx);
|
|
14189
|
+
if (ctx.model.providerModelId.toLowerCase() !== LUMA_VIDEO_MODEL_ID) {
|
|
14190
|
+
throw new ModelKitError({
|
|
14191
|
+
code: "unsupported_option",
|
|
14192
|
+
message: `luma has no video mapping for "${ctx.model.providerModelId}"`,
|
|
14193
|
+
provider: "luma",
|
|
14194
|
+
model: ctx.model.id,
|
|
14195
|
+
retryable: false
|
|
14196
|
+
});
|
|
14197
|
+
}
|
|
14198
|
+
const mode = lumaVideoMode(ctx);
|
|
14199
|
+
const created = await submitGeneration(ctx, videoBody(req, ctx, mode));
|
|
14200
|
+
return lumaVideoJob(ctx, req, mode, created.id);
|
|
14201
|
+
}
|
|
14202
|
+
var lumaAdapter = {
|
|
14203
|
+
id: "luma",
|
|
14204
|
+
generateImage: generateLumaImage,
|
|
14205
|
+
generateVideo: generateLumaVideo,
|
|
14206
|
+
resumeVideo: (req, jobId, ctx) => {
|
|
14207
|
+
throwIfAborted(ctx.signal);
|
|
14208
|
+
lumaKey(ctx);
|
|
14209
|
+
return lumaVideoJob(ctx, req, lumaVideoMode(ctx), jobId);
|
|
14210
|
+
}
|
|
14211
|
+
};
|
|
14212
|
+
|
|
13455
14213
|
// src/adapters/openai-image.ts
|
|
13456
14214
|
import OpenAI from "openai";
|
|
13457
|
-
import { z as
|
|
14215
|
+
import { z as z26 } from "zod";
|
|
13458
14216
|
var MAX_EDIT_REFERENCES = 16;
|
|
13459
14217
|
function aspectRatioToSize(ratio, tier) {
|
|
13460
14218
|
const TIER_LONG_EDGE = {
|
|
@@ -13537,9 +14295,9 @@ function toProviderError2(cause, ctx) {
|
|
|
13537
14295
|
ctx.model.id
|
|
13538
14296
|
);
|
|
13539
14297
|
}
|
|
13540
|
-
var openaiUsageSchema =
|
|
13541
|
-
input_tokens:
|
|
13542
|
-
output_tokens:
|
|
14298
|
+
var openaiUsageSchema = z26.object({
|
|
14299
|
+
input_tokens: z26.number().optional(),
|
|
14300
|
+
output_tokens: z26.number().optional()
|
|
13543
14301
|
});
|
|
13544
14302
|
var openaiImageAdapter = {
|
|
13545
14303
|
id: "openai-image",
|
|
@@ -13951,13 +14709,13 @@ var prodiaAdapter = {
|
|
|
13951
14709
|
import Replicate from "replicate";
|
|
13952
14710
|
|
|
13953
14711
|
// src/adapters/replicate-http.ts
|
|
13954
|
-
import { z as
|
|
13955
|
-
var predictionSchema =
|
|
13956
|
-
id:
|
|
13957
|
-
status:
|
|
14712
|
+
import { z as z27 } from "zod";
|
|
14713
|
+
var predictionSchema = z27.object({
|
|
14714
|
+
id: z27.string(),
|
|
14715
|
+
status: z27.string(),
|
|
13958
14716
|
output: JsonValueSchema.optional(),
|
|
13959
14717
|
error: JsonValueSchema.optional(),
|
|
13960
|
-
metrics:
|
|
14718
|
+
metrics: z27.object({ predict_time: z27.number().optional() }).optional()
|
|
13961
14719
|
});
|
|
13962
14720
|
function createReplicateHttpClient(opts) {
|
|
13963
14721
|
async function request(path, body, signal) {
|
|
@@ -14008,7 +14766,7 @@ function createReplicateHttpClient(opts) {
|
|
|
14008
14766
|
}
|
|
14009
14767
|
|
|
14010
14768
|
// src/adapters/replicate.ts
|
|
14011
|
-
import { z as
|
|
14769
|
+
import { z as z28 } from "zod";
|
|
14012
14770
|
var POLL_INTERVAL_MS = 1e3;
|
|
14013
14771
|
var POLL_TIMEOUT_MS = 15 * 6e4;
|
|
14014
14772
|
var defaultReplicateDeps = {
|
|
@@ -14048,8 +14806,8 @@ function route(providerModelId) {
|
|
|
14048
14806
|
if (!providerModelId.includes("/")) return { version: providerModelId };
|
|
14049
14807
|
return { model: providerModelId };
|
|
14050
14808
|
}
|
|
14051
|
-
var replicateResponseStatusSchema =
|
|
14052
|
-
response:
|
|
14809
|
+
var replicateResponseStatusSchema = z28.object({
|
|
14810
|
+
response: z28.object({ status: z28.number() }).partial()
|
|
14053
14811
|
});
|
|
14054
14812
|
function replicateError(cause, ctx) {
|
|
14055
14813
|
if (isModelKitError(cause)) return cause;
|
|
@@ -14072,7 +14830,7 @@ function isUrlFn(value) {
|
|
|
14072
14830
|
function extractOutputUrl(output) {
|
|
14073
14831
|
const root = Array.isArray(output) ? output[0] : output;
|
|
14074
14832
|
if (root === void 0) throw noOutput();
|
|
14075
|
-
const asString =
|
|
14833
|
+
const asString = z28.string().safeParse(root);
|
|
14076
14834
|
if (asString.success && asString.data) return asString.data;
|
|
14077
14835
|
if (root instanceof URL) return root.href;
|
|
14078
14836
|
if (isObjectOutput(root)) {
|
|
@@ -14081,15 +14839,15 @@ function extractOutputUrl(output) {
|
|
|
14081
14839
|
if (urlValue !== void 0 && isUrlFn(urlValue)) {
|
|
14082
14840
|
const called = urlValue();
|
|
14083
14841
|
if (called instanceof URL) return called.href;
|
|
14084
|
-
const calledString =
|
|
14842
|
+
const calledString = z28.string().safeParse(called);
|
|
14085
14843
|
if (calledString.success && calledString.data) return calledString.data;
|
|
14086
14844
|
} else {
|
|
14087
|
-
const direct =
|
|
14845
|
+
const direct = z28.string().safeParse(urlValue);
|
|
14088
14846
|
if (direct.success && direct.data) return direct.data;
|
|
14089
14847
|
}
|
|
14090
14848
|
}
|
|
14091
14849
|
if ("default" in root) {
|
|
14092
|
-
const fallback =
|
|
14850
|
+
const fallback = z28.string().safeParse(root.default);
|
|
14093
14851
|
if (fallback.success && fallback.data) return fallback.data;
|
|
14094
14852
|
}
|
|
14095
14853
|
}
|
|
@@ -14150,7 +14908,7 @@ async function runPrediction(ctx, input, deps) {
|
|
|
14150
14908
|
}
|
|
14151
14909
|
return void 0;
|
|
14152
14910
|
}, pollOpts);
|
|
14153
|
-
const predictTime =
|
|
14911
|
+
const predictTime = z28.number().safeParse(done.metrics?.predict_time);
|
|
14154
14912
|
if (done.output === void 0) throw noOutput();
|
|
14155
14913
|
return {
|
|
14156
14914
|
url: extractOutputUrl(done.output),
|
|
@@ -14158,7 +14916,7 @@ async function runPrediction(ctx, input, deps) {
|
|
|
14158
14916
|
raw: done
|
|
14159
14917
|
};
|
|
14160
14918
|
}
|
|
14161
|
-
function
|
|
14919
|
+
function imageUsage3(ctx, req) {
|
|
14162
14920
|
const event = {
|
|
14163
14921
|
model: ctx.model.id,
|
|
14164
14922
|
provider: "replicate",
|
|
@@ -14170,7 +14928,7 @@ function imageUsage2(ctx, req) {
|
|
|
14170
14928
|
if (req.quality !== void 0) event.imageQuality = req.quality;
|
|
14171
14929
|
return event;
|
|
14172
14930
|
}
|
|
14173
|
-
function
|
|
14931
|
+
function videoUsage5(ctx, req) {
|
|
14174
14932
|
const event = {
|
|
14175
14933
|
model: ctx.model.id,
|
|
14176
14934
|
provider: "replicate",
|
|
@@ -14396,7 +15154,7 @@ async function generateReplicateImage(req, ctx, deps) {
|
|
|
14396
15154
|
}
|
|
14397
15155
|
const { url, predictTime, raw } = await runPrediction(ctx, input, deps);
|
|
14398
15156
|
const file = await download(ctx, url);
|
|
14399
|
-
const usage3 =
|
|
15157
|
+
const usage3 = imageUsage3(ctx, req);
|
|
14400
15158
|
usage3.quantity = predictTime;
|
|
14401
15159
|
return { images: [{ bytes: file.bytes, mime: file.mime }], usage: usage3, raw, outputUrl: url };
|
|
14402
15160
|
}
|
|
@@ -14503,7 +15261,7 @@ async function generateReplicateVideo(req, ctx, deps) {
|
|
|
14503
15261
|
throw replicateError(cause, ctx);
|
|
14504
15262
|
}
|
|
14505
15263
|
if (current.status === "succeeded") {
|
|
14506
|
-
const predictTime =
|
|
15264
|
+
const predictTime = z28.number().safeParse(current.metrics?.predict_time);
|
|
14507
15265
|
if (current.output === void 0) throw noOutput();
|
|
14508
15266
|
return {
|
|
14509
15267
|
url: extractOutputUrl(current.output),
|
|
@@ -14522,7 +15280,7 @@ async function generateReplicateVideo(req, ctx, deps) {
|
|
|
14522
15280
|
return void 0;
|
|
14523
15281
|
};
|
|
14524
15282
|
const toResult = (done) => {
|
|
14525
|
-
const usage3 =
|
|
15283
|
+
const usage3 = videoUsage5(ctx, req);
|
|
14526
15284
|
usage3.quantity = done.predictTime;
|
|
14527
15285
|
return { video: { url: done.url }, usage: usage3, raw: done.raw };
|
|
14528
15286
|
};
|
|
@@ -14645,7 +15403,7 @@ async function generateReplicateAudio(req, ctx, deps) {
|
|
|
14645
15403
|
// src/adapters/xai-video.ts
|
|
14646
15404
|
import { experimental_generateVideo } from "ai";
|
|
14647
15405
|
import { createXai as createXai2 } from "@ai-sdk/xai";
|
|
14648
|
-
import { z as
|
|
15406
|
+
import { z as z29 } from "zod";
|
|
14649
15407
|
var POLL_INTERVAL_MS2 = 1e4;
|
|
14650
15408
|
var POLL_TIMEOUT_MS2 = 15 * 6e4;
|
|
14651
15409
|
var defaultXaiDeps = {
|
|
@@ -14658,8 +15416,8 @@ function createXaiVideoAdapter(deps = defaultXaiDeps) {
|
|
|
14658
15416
|
};
|
|
14659
15417
|
}
|
|
14660
15418
|
var xaiVideoAdapter = createXaiVideoAdapter();
|
|
14661
|
-
var xaiResponseStatusSchema =
|
|
14662
|
-
response:
|
|
15419
|
+
var xaiResponseStatusSchema = z29.object({
|
|
15420
|
+
response: z29.object({ status: z29.number() }).partial()
|
|
14663
15421
|
});
|
|
14664
15422
|
function xaiError(cause, ctx) {
|
|
14665
15423
|
const info = describeThrown(cause);
|
|
@@ -14667,12 +15425,12 @@ function xaiError(cause, ctx) {
|
|
|
14667
15425
|
const status = info.status ?? (nested.success ? nested.data.response?.status : void 0);
|
|
14668
15426
|
return classifyThrown("xai-video", cause, ctx.model.id, { status, body: info.body });
|
|
14669
15427
|
}
|
|
14670
|
-
var xaiMetaSchema =
|
|
15428
|
+
var xaiMetaSchema = z29.object({
|
|
14671
15429
|
videoUrl: JsonValueSchema.optional(),
|
|
14672
15430
|
costInUsdTicks: JsonValueSchema.optional(),
|
|
14673
15431
|
duration: JsonValueSchema.optional()
|
|
14674
15432
|
});
|
|
14675
|
-
var xaiProviderMetadataSchema =
|
|
15433
|
+
var xaiProviderMetadataSchema = z29.object({ xai: xaiMetaSchema });
|
|
14676
15434
|
function metaOf(result) {
|
|
14677
15435
|
const parsed = xaiProviderMetadataSchema.partial().safeParse(result.providerMetadata);
|
|
14678
15436
|
if (!parsed.success) return {};
|
|
@@ -14788,7 +15546,7 @@ async function mapResult(ctx, req, result) {
|
|
|
14788
15546
|
};
|
|
14789
15547
|
}
|
|
14790
15548
|
const meta = metaOf(result);
|
|
14791
|
-
const videoUrl =
|
|
15549
|
+
const videoUrl = z29.string().safeParse(meta.videoUrl);
|
|
14792
15550
|
if (videoUrl.success && videoUrl.data) {
|
|
14793
15551
|
const res = await ctx.fetch(videoUrl.data);
|
|
14794
15552
|
if (!res.ok) {
|
|
@@ -14811,7 +15569,7 @@ async function mapResult(ctx, req, result) {
|
|
|
14811
15569
|
});
|
|
14812
15570
|
}
|
|
14813
15571
|
function usage2(ctx, req, meta) {
|
|
14814
|
-
const costTicks =
|
|
15572
|
+
const costTicks = z29.number().safeParse(meta.costInUsdTicks);
|
|
14815
15573
|
const cost = costTicks.success ? costTicks.data / 1e10 : void 0;
|
|
14816
15574
|
const event = {
|
|
14817
15575
|
model: ctx.model.id,
|
|
@@ -14859,7 +15617,8 @@ var DEFAULT_ADAPTERS = {
|
|
|
14859
15617
|
replicate: replicateAdapter,
|
|
14860
15618
|
prodia: prodiaAdapter,
|
|
14861
15619
|
higgsfield: higgsfieldAdapter,
|
|
14862
|
-
"xai-video": xaiVideoAdapter
|
|
15620
|
+
"xai-video": xaiVideoAdapter,
|
|
15621
|
+
luma: lumaAdapter
|
|
14863
15622
|
};
|
|
14864
15623
|
|
|
14865
15624
|
// src/catalog/data-only.ts
|
|
@@ -14975,6 +15734,10 @@ function dataOnlyCapable(row2) {
|
|
|
14975
15734
|
reason: "higgsfield providerModelId must be a platform path, not a URL"
|
|
14976
15735
|
};
|
|
14977
15736
|
}
|
|
15737
|
+
case "luma": {
|
|
15738
|
+
const reason = lumaRowRefusal(row2);
|
|
15739
|
+
return reason === void 0 ? { ok: true } : { ok: false, reason };
|
|
15740
|
+
}
|
|
14978
15741
|
default: {
|
|
14979
15742
|
return assertNever(row2.adapter);
|
|
14980
15743
|
}
|
|
@@ -14994,22 +15757,22 @@ var liveState = store[KEY] ??= {
|
|
|
14994
15757
|
var liveCatalog = liveState.catalog;
|
|
14995
15758
|
|
|
14996
15759
|
// src/catalog/load.ts
|
|
14997
|
-
import { z as
|
|
15760
|
+
import { z as z30 } from "zod";
|
|
14998
15761
|
function rowCount() {
|
|
14999
15762
|
return liveCatalog.list({ lifecycle: ["active", "deprecated", "retired"] }).length;
|
|
15000
15763
|
}
|
|
15001
15764
|
function authHeaders(auth) {
|
|
15002
15765
|
return "bearer" in auth ? { Authorization: `Bearer ${auth.bearer}` } : { "x-api-key": auth.apiKey };
|
|
15003
15766
|
}
|
|
15004
|
-
var EnvelopeSchema =
|
|
15005
|
-
rows:
|
|
15006
|
-
revision:
|
|
15767
|
+
var EnvelopeSchema = z30.object({
|
|
15768
|
+
rows: z30.array(JsonValueSchema),
|
|
15769
|
+
revision: z30.string().optional()
|
|
15007
15770
|
});
|
|
15008
15771
|
function dropReason(path, message) {
|
|
15009
15772
|
return path.length === 0 ? message : `${path.map((part) => String(part)).join(".")} ${message}`;
|
|
15010
15773
|
}
|
|
15011
15774
|
function rowId(raw) {
|
|
15012
|
-
const parsed =
|
|
15775
|
+
const parsed = z30.object({ id: z30.string().min(1) }).loose().safeParse(raw);
|
|
15013
15776
|
if (!parsed.success) return "?";
|
|
15014
15777
|
return parsed.data.id;
|
|
15015
15778
|
}
|
|
@@ -16058,7 +16821,8 @@ var ADAPTER_KEYS = {
|
|
|
16058
16821
|
replicate: ["replicate"],
|
|
16059
16822
|
prodia: ["prodia"],
|
|
16060
16823
|
higgsfield: ["higgsfield"],
|
|
16061
|
-
"xai-video": ["xai"]
|
|
16824
|
+
"xai-video": ["xai"],
|
|
16825
|
+
luma: ["luma"]
|
|
16062
16826
|
};
|
|
16063
16827
|
function hasAll(keys, names) {
|
|
16064
16828
|
if (!keys) return false;
|
|
@@ -16116,6 +16880,7 @@ function keysFromEnv(env, prefix = "") {
|
|
|
16116
16880
|
set("prodia", pick2("PRODIA_API_KEY", "PRODIA_TOKEN"));
|
|
16117
16881
|
set("higgsfield", pick2("HIGGSFIELD_API_KEY"));
|
|
16118
16882
|
set("higgsfieldSecret", pick2("HIGGSFIELD_API_SECRET"));
|
|
16883
|
+
set("luma", pick2("LUMA_API_KEY", "LUMA_AGENTS_API_KEY"));
|
|
16119
16884
|
set("cloudflare", pick2("CLOUDFLARE_AI_GATEWAY_TOKEN", "CF_AIG_TOKEN"));
|
|
16120
16885
|
const bearer = pick2("AWS_BEARER_TOKEN_BEDROCK");
|
|
16121
16886
|
const accessKeyId = pick2("AWS_ACCESS_KEY_ID");
|
|
@@ -16138,7 +16903,7 @@ function keysFromEnv(env, prefix = "") {
|
|
|
16138
16903
|
|
|
16139
16904
|
// src/text.ts
|
|
16140
16905
|
import "ai";
|
|
16141
|
-
import { z as
|
|
16906
|
+
import { z as z31 } from "zod";
|
|
16142
16907
|
function mergeTextProviderOptions(catalog, caller) {
|
|
16143
16908
|
const merged = {};
|
|
16144
16909
|
const catalogOptions = catalog.providerOptions ?? {};
|
|
@@ -16177,8 +16942,8 @@ function passthroughTextModel(model) {
|
|
|
16177
16942
|
pricingKind: "token"
|
|
16178
16943
|
};
|
|
16179
16944
|
}
|
|
16180
|
-
var perplexityCostSchema =
|
|
16181
|
-
perplexity:
|
|
16945
|
+
var perplexityCostSchema = z31.object({
|
|
16946
|
+
perplexity: z31.object({ cost: z31.object({ totalCost: z31.number().finite().nonnegative() }) })
|
|
16182
16947
|
});
|
|
16183
16948
|
function reportedCostUsd(metadata) {
|
|
16184
16949
|
const parsed = perplexityCostSchema.safeParse(metadata);
|
|
@@ -16258,7 +17023,7 @@ import {
|
|
|
16258
17023
|
streamObject as aiStreamObject2,
|
|
16259
17024
|
streamText as aiStreamText2
|
|
16260
17025
|
} from "ai";
|
|
16261
|
-
import { z as
|
|
17026
|
+
import { z as z32 } from "zod";
|
|
16262
17027
|
|
|
16263
17028
|
// src/generated-image.ts
|
|
16264
17029
|
function toGeneratedImage(image) {
|
|
@@ -16607,10 +17372,10 @@ function textAbortOptions(sdk, context) {
|
|
|
16607
17372
|
if (abortSignal) return { abortSignal };
|
|
16608
17373
|
return {};
|
|
16609
17374
|
}
|
|
16610
|
-
var catalogId =
|
|
16611
|
-
var exactSize =
|
|
16612
|
-
var sdkRatio =
|
|
16613
|
-
var sizeTier =
|
|
17375
|
+
var catalogId = z32.string();
|
|
17376
|
+
var exactSize = z32.templateLiteral([z32.number(), "x", z32.number()]);
|
|
17377
|
+
var sdkRatio = z32.templateLiteral([z32.number(), ":", z32.number()]);
|
|
17378
|
+
var sizeTier = z32.enum(["512", "1K", "2K", "4K"]);
|
|
16614
17379
|
function isCatalogId(model) {
|
|
16615
17380
|
return catalogId.safeParse(model).success;
|
|
16616
17381
|
}
|
|
@@ -17354,6 +18119,7 @@ export {
|
|
|
17354
18119
|
languageModel,
|
|
17355
18120
|
liveCatalog,
|
|
17356
18121
|
liveState,
|
|
18122
|
+
lumaAdapter,
|
|
17357
18123
|
mergeTextProviderOptions,
|
|
17358
18124
|
missingTierKeys,
|
|
17359
18125
|
model3dCall,
|