@vibeframe/mcp-server 0.115.2 → 0.115.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.js +1127 -752
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -191,8 +191,8 @@ var init_api_keys = __esm({
|
|
|
191
191
|
envVar: "OPENAI_API_KEY",
|
|
192
192
|
label: "OpenAI",
|
|
193
193
|
showInSetup: true,
|
|
194
|
-
setupDescription: "gpt-image-2 image gen (
|
|
195
|
-
envExampleComment: "OpenAI API Key (Whisper transcription, gpt-4o-mini-tts narration, gpt-image-2
|
|
194
|
+
setupDescription: "gpt-image-2.5 image gen ($), gpt-4o-mini-tts narration, Whisper transcribe, Agent",
|
|
195
|
+
envExampleComment: "OpenAI API Key (Whisper transcription, gpt-4o-mini-tts narration, gpt-image-2.5 text-to-image)",
|
|
196
196
|
envExampleUrl: "https://platform.openai.com/api-keys",
|
|
197
197
|
keyFormat: { prefix: /^sk-/, example: "sk-..." }
|
|
198
198
|
});
|
|
@@ -267,8 +267,7 @@ var init_api_keys = __esm({
|
|
|
267
267
|
setupDescription: "v2.5/v3 video \u2014 std ($$) and pro ($$$) modes",
|
|
268
268
|
envExampleComment: "Kling API Key (Kling video generation)",
|
|
269
269
|
envExampleUrl: "https://platform.klingai.com/",
|
|
270
|
-
envExampleExtraLines: ["
|
|
271
|
-
keyFormat: { prefix: /:/, example: "ACCESS_KEY:SECRET_KEY" }
|
|
270
|
+
envExampleExtraLines: ["API key from the Kling console (legacy ACCESS_KEY:SECRET_KEY also works)"]
|
|
272
271
|
});
|
|
273
272
|
defineApiKey({
|
|
274
273
|
configKey: "replicate",
|
|
@@ -440,6 +439,82 @@ var init_whisper = __esm({
|
|
|
440
439
|
}
|
|
441
440
|
});
|
|
442
441
|
|
|
442
|
+
// ../ai-providers/dist/catalog/catalog.js
|
|
443
|
+
function listModels(filter3 = {}) {
|
|
444
|
+
return MODEL_CATALOG.filter((m2) => (!filter3.provider || m2.provider === filter3.provider) && (!filter3.kind || m2.kind === filter3.kind));
|
|
445
|
+
}
|
|
446
|
+
function defaultModel(provider, kind3) {
|
|
447
|
+
const found = MODEL_CATALOG.find((m2) => m2.provider === provider && m2.kind === kind3 && m2.default);
|
|
448
|
+
if (!found)
|
|
449
|
+
throw new Error(`Model catalog has no default ${kind3} model for ${provider}`);
|
|
450
|
+
return found;
|
|
451
|
+
}
|
|
452
|
+
function findModel(provider, kind3, aliasOrId) {
|
|
453
|
+
const key2 = aliasOrId?.trim();
|
|
454
|
+
if (!key2)
|
|
455
|
+
return defaultModel(provider, kind3);
|
|
456
|
+
const lower = key2.toLowerCase();
|
|
457
|
+
return listModels({ provider, kind: kind3 }).find((m2) => m2.id === key2 || m2.aliases?.includes(lower));
|
|
458
|
+
}
|
|
459
|
+
function modelAliases(provider, kind3) {
|
|
460
|
+
return listModels({ provider, kind: kind3 }).flatMap((m2) => m2.aliases ?? []);
|
|
461
|
+
}
|
|
462
|
+
var MODEL_CATALOG;
|
|
463
|
+
var init_catalog = __esm({
|
|
464
|
+
"../ai-providers/dist/catalog/catalog.js"() {
|
|
465
|
+
"use strict";
|
|
466
|
+
MODEL_CATALOG = [
|
|
467
|
+
// ── LLMs ──────────────────────────────────────────────────────────────
|
|
468
|
+
{ id: "claude-sonnet-5-5", provider: "claude", kind: "llm", label: "Claude Sonnet 5.5", aliases: ["sonnet"], default: true, status: "ga", price: { usd: 2, per: "1M input tokens" }, note: "Agent, storyboard, translate-srt, motion default" },
|
|
469
|
+
{ id: "claude-opus-5-5", provider: "claude", kind: "llm", label: "Claude Opus 5.5", aliases: ["opus"], status: "ga", price: { usd: 4, per: "1M input tokens" } },
|
|
470
|
+
{ id: "claude-opus-4-6", provider: "claude", kind: "llm", label: "Claude Opus 4.6", aliases: ["opus-4-6"], status: "legacy", price: { usd: 5, per: "1M input tokens" } },
|
|
471
|
+
{ id: "gpt-5.4-mini", provider: "openai", kind: "llm", label: "GPT-5.4 mini", default: true, status: "ga", price: { usd: 0.75, per: "1M input tokens" }, note: "Agent and storyboard default (tools on Chat Completions)" },
|
|
472
|
+
{ id: "gemini-3.8-flash", provider: "gemini", kind: "llm", label: "Gemini 3.8 Flash", aliases: ["flash", "latest", "flash-3.8", "gemini"], default: true, status: "ga", price: { usd: 0.75, per: "1M input tokens", basis: "until 2026-12-31, then $1.50" } },
|
|
473
|
+
{ id: "gemini-3.5-flash", provider: "gemini", kind: "llm", label: "Gemini 3.5 Flash", aliases: ["flash-3.5"], status: "ga" },
|
|
474
|
+
{ id: "gemini-3-flash-preview", provider: "gemini", kind: "llm", label: "Gemini 3 Flash (preview)", aliases: ["flash-3"], status: "preview" },
|
|
475
|
+
{ id: "gemini-3.1-pro-preview", provider: "gemini", kind: "llm", label: "Gemini 3.1 Pro (preview)", aliases: ["pro", "pro-3.1", "3.1-pro", "gemini-3.1-pro"], status: "preview" },
|
|
476
|
+
{ id: "gemini-2.5-flash", provider: "gemini", kind: "llm", label: "Gemini 2.5 Flash", aliases: ["flash-2.5"], status: "legacy", note: "New projects cannot use 2.5 models since 2026-09-18" },
|
|
477
|
+
{ id: "gemini-2.5-pro", provider: "gemini", kind: "llm", label: "Gemini 2.5 Pro", aliases: ["pro-2.5", "2.5-pro"], status: "legacy" },
|
|
478
|
+
{ id: "grok-4.3", provider: "grok", kind: "llm", label: "Grok 4.3", default: true, status: "ga", price: { usd: 1.25, per: "1M input tokens" } },
|
|
479
|
+
{ id: "grok-4.7", provider: "grok", kind: "llm", label: "Grok 4.7", status: "ga", price: { usd: 2, per: "1M input tokens" } },
|
|
480
|
+
// ── Images ────────────────────────────────────────────────────────────
|
|
481
|
+
{ id: "gpt-image-2.5-sunburst", provider: "openai", kind: "image", label: "GPT Image 2.5 Sunburst", aliases: ["2.5", "sunburst"], default: true, status: "ga", price: { usd: 0.211, per: "image", basis: "high, 1024x1024" } },
|
|
482
|
+
{ id: "gpt-image-2.5-flare", provider: "openai", kind: "image", label: "GPT Image 2.5 Flare", aliases: ["flare", "2.5-flare"], status: "ga", price: { usd: 0.211, per: "image", basis: "high, 1024x1024" } },
|
|
483
|
+
{ id: "gpt-image-2", provider: "openai", kind: "image", label: "GPT Image 2", aliases: ["2"], status: "ga", price: { usd: 0.211, per: "image", basis: "high, 1024x1024" } },
|
|
484
|
+
{ id: "gpt-image-1.5", provider: "openai", kind: "image", label: "GPT Image 1.5", aliases: ["1.5"], status: "deprecated", shutdown: "2026-12-01", price: { usd: 0.133, per: "image", basis: "high, 1024x1024" } },
|
|
485
|
+
{ id: "gemini-3.1-flash-image", provider: "gemini", kind: "image", label: "Nano Banana 2", aliases: ["flash", "3.1-flash", "latest"], default: true, status: "ga", price: { usd: 0.067, per: "image", basis: "1K" } },
|
|
486
|
+
{ id: "gemini-3.1-flash-lite-image", provider: "gemini", kind: "image", label: "Nano Banana 2 Lite", aliases: ["lite"], status: "ga", price: { usd: 0.034, per: "image", basis: "1K" } },
|
|
487
|
+
{ id: "gemini-3-pro-image", provider: "gemini", kind: "image", label: "Nano Banana Pro", aliases: ["pro"], status: "ga", price: { usd: 0.134, per: "image", basis: "1K-2K" } },
|
|
488
|
+
{ id: "gemini-2.5-flash-image", provider: "gemini", kind: "image", label: "Nano Banana (2.5 Flash Image)", status: "deprecated", shutdown: "2026-10-02" },
|
|
489
|
+
{ id: "gemini-3.1-flash-image-preview", provider: "gemini", kind: "image", label: "Nano Banana 2 (preview)", status: "deprecated", shutdown: "2026-06-25" },
|
|
490
|
+
{ id: "gemini-3-pro-image-preview", provider: "gemini", kind: "image", label: "Nano Banana Pro (preview)", status: "deprecated", shutdown: "2026-06-25" },
|
|
491
|
+
{ id: "grok-imagine-image", provider: "grok", kind: "image", label: "Grok Imagine Image", default: true, status: "ga", price: { usd: 0.02, per: "image" } },
|
|
492
|
+
{ id: "grok-imagine-image-2.0", provider: "grok", kind: "image", label: "Grok Imagine Image 2.0", aliases: ["pro", "2.0", "quality"], status: "ga", price: { usd: 0.08, per: "image", basis: "medium, 2K" } },
|
|
493
|
+
// ── Video ─────────────────────────────────────────────────────────────
|
|
494
|
+
{ id: "seedance-2.0", provider: "seedance", kind: "video", label: "Seedance 2.0", aliases: ["quality", "2.0"], default: true, status: "ga", price: { usd: 0.3024, per: "second", basis: "720p 16:9" }, note: "4-15 s, native audio" },
|
|
495
|
+
{ id: "seedance-2.0-fast", provider: "seedance", kind: "video", label: "Seedance 2.0 Fast", aliases: ["fast"], status: "ga", price: { usd: 0.2419, per: "second", basis: "720p 16:9" }, note: "4-15 s, up to 720p, native audio" },
|
|
496
|
+
{ id: "seedance-2.5", provider: "seedance", kind: "video", label: "Seedance 2.5", aliases: ["2.5"], status: "ga", price: { usd: 0.473, per: "second", basis: "720p 16:9" }, note: "Opt-in; 4-30 s, native audio" },
|
|
497
|
+
{ id: "gemini-omni-1.1-flash", provider: "omni", kind: "video", label: "Gemini Omni 1.1 Flash", default: true, status: "ga", price: { usd: 0.1, per: "second", basis: "720p" }, note: "Google video default; the model picks 3-10 s; native audio" },
|
|
498
|
+
{ id: "veo-3.1-generate-preview", provider: "veo", kind: "video", label: "Veo 3.1", aliases: ["3.1"], status: "deprecated", shutdown: "2026-10-22", price: { usd: 0.4, per: "second", basis: "720p/1080p" }, note: "4-8 s, native audio; explicit `-p veo` only" },
|
|
499
|
+
{ id: "veo-3.1-fast-generate-preview", provider: "veo", kind: "video", label: "Veo 3.1 Fast", aliases: ["3.1-fast"], default: true, status: "deprecated", shutdown: "2026-10-22", price: { usd: 0.1, per: "second", basis: "720p" }, note: "4-8 s, native audio; explicit `-p veo` only" },
|
|
500
|
+
{ id: "grok-imagine-video-1.5", provider: "grok", kind: "video", label: "Grok Imagine Video 1.5", aliases: ["1.5"], default: true, status: "ga", price: { usd: 0.14, per: "second", basis: "720p" }, note: "1-15 s, native audio; 720p unless `--resolution` says otherwise" },
|
|
501
|
+
{ id: "grok-imagine-video-1.5-lite", provider: "grok", kind: "video", label: "Grok Imagine Video 1.5 Lite", aliases: ["lite", "1.5-lite"], status: "ga", price: { usd: 0.03, per: "second", basis: "720p" }, note: "1-15 s, native audio" },
|
|
502
|
+
{ id: "grok-imagine-video", provider: "grok", kind: "video", label: "Grok Imagine Video", aliases: ["classic"], status: "legacy", price: { usd: 0.05, per: "second", basis: "480p" }, note: "Previous generation" },
|
|
503
|
+
{ id: "kling-v3", provider: "kling", kind: "video", label: "Kling v3", aliases: ["v3"], default: true, status: "ga", price: { usd: 0.084, per: "second", basis: "std, silent" }, note: "3-15 s, multi-shot; `std` 720p, `pro` 1080p" },
|
|
504
|
+
{ id: "kling-v2-6", provider: "kling", kind: "video", label: "Kling v2.6", aliases: ["v2.6"], status: "ga", price: { usd: 0.042, per: "second", basis: "std 720p" }, note: "5 or 10 s" },
|
|
505
|
+
{ id: "kling-v2-5-turbo", provider: "kling", kind: "video", label: "Kling v2.5 Turbo", aliases: ["v2.5-turbo", "v2.5"], status: "ga", price: { usd: 0.042, per: "second", basis: "std" }, note: "5 or 10 s, no audio" },
|
|
506
|
+
{ id: "gen4.5", provider: "runway", kind: "video", label: "Runway Gen-4.5", default: true, status: "ga", price: { usd: 0.12, per: "second" }, note: "2-10 s, no audio" },
|
|
507
|
+
{ id: "gen4_turbo", provider: "runway", kind: "video", label: "Runway Gen-4 Turbo", status: "ga", price: { usd: 0.05, per: "second" }, note: "Image-to-video only, no audio" },
|
|
508
|
+
// ── Audio ─────────────────────────────────────────────────────────────
|
|
509
|
+
{ id: "eleven_v3", provider: "elevenlabs", kind: "speech", label: "ElevenLabs v3", default: true, status: "ga", price: { usd: 0.08, per: "1K characters" } },
|
|
510
|
+
{ id: "gpt-4o-mini-tts", provider: "openai", kind: "speech", label: "GPT-4o mini TTS", default: true, status: "deprecated", shutdown: "2027-01-06" },
|
|
511
|
+
{ id: "music_v2_5", provider: "elevenlabs", kind: "music", label: "ElevenLabs Music v2.5", default: true, status: "ga", price: { usd: 0.15, per: "minute" } },
|
|
512
|
+
{ id: "eleven_text_to_sound_v2", provider: "elevenlabs", kind: "sound-effect", label: "ElevenLabs Sound Effects v2", default: true, status: "ga", price: { usd: 0.12, per: "minute" }, note: "0.5-30 s" },
|
|
513
|
+
{ id: "whisper-1", provider: "openai", kind: "transcription", label: "Whisper", default: true, status: "deprecated", shutdown: "2027-02-26", note: "Only OpenAI model with word timestamps" }
|
|
514
|
+
];
|
|
515
|
+
}
|
|
516
|
+
});
|
|
517
|
+
|
|
443
518
|
// ../ai-providers/dist/gemini/gemini-models.js
|
|
444
519
|
function isGeminiTextModelAlias(model) {
|
|
445
520
|
return Object.prototype.hasOwnProperty.call(GEMINI_TEXT_MODEL_ALIASES, model);
|
|
@@ -458,18 +533,11 @@ var GEMINI_DEFAULT_TEXT_MODEL, GEMINI_AGENT_DEFAULT_TEXT_MODEL, GEMINI_TEXT_MODE
|
|
|
458
533
|
var init_gemini_models = __esm({
|
|
459
534
|
"../ai-providers/dist/gemini/gemini-models.js"() {
|
|
460
535
|
"use strict";
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
"flash-3.5": GEMINI_DEFAULT_TEXT_MODEL,
|
|
467
|
-
"flash-3": "gemini-3-flash-preview",
|
|
468
|
-
"flash-2.5": "gemini-2.5-flash",
|
|
469
|
-
pro: "gemini-2.5-pro",
|
|
470
|
-
"pro-3.1": "gemini-3.1-pro-preview"
|
|
471
|
-
};
|
|
472
|
-
GEMINI_TEXT_MODEL_HELP = "flash/latest (Gemini 3.5 Flash), flash-3.5, flash-3, flash-2.5, pro, pro-3.1, or a full gemini-* model ID";
|
|
536
|
+
init_catalog();
|
|
537
|
+
GEMINI_DEFAULT_TEXT_MODEL = defaultModel("gemini", "llm").id;
|
|
538
|
+
GEMINI_AGENT_DEFAULT_TEXT_MODEL = GEMINI_DEFAULT_TEXT_MODEL;
|
|
539
|
+
GEMINI_TEXT_MODEL_ALIASES = Object.fromEntries(listModels({ provider: "gemini", kind: "llm" }).flatMap((m2) => (m2.aliases ?? []).map((a4) => [a4, m2.id])));
|
|
540
|
+
GEMINI_TEXT_MODEL_HELP = "flash/latest (Gemini 3.8 Flash), flash-3.8, flash-3.5, flash-3, flash-2.5, pro (Gemini 3.1 Pro), pro-3.1, pro-2.5, or a full gemini-* model ID";
|
|
473
541
|
}
|
|
474
542
|
});
|
|
475
543
|
|
|
@@ -656,7 +724,6 @@ UNIVERSAL RULES:
|
|
|
656
724
|
system_instruction: { parts: [{ text: systemPrompt }] },
|
|
657
725
|
contents: [{ role: "user", parts: [{ text: userPrompt }] }],
|
|
658
726
|
generationConfig: {
|
|
659
|
-
temperature: 0.8,
|
|
660
727
|
maxOutputTokens: 16384
|
|
661
728
|
}
|
|
662
729
|
})
|
|
@@ -757,7 +824,7 @@ Return the complete modified component as JSON.`
|
|
|
757
824
|
]
|
|
758
825
|
}
|
|
759
826
|
],
|
|
760
|
-
generationConfig: {
|
|
827
|
+
generationConfig: { maxOutputTokens: 16384 }
|
|
761
828
|
})
|
|
762
829
|
});
|
|
763
830
|
if (!response.ok) {
|
|
@@ -803,18 +870,7 @@ var init_gemini_motion = __esm({
|
|
|
803
870
|
"../ai-providers/dist/gemini/gemini-motion.js"() {
|
|
804
871
|
"use strict";
|
|
805
872
|
init_gemini_models();
|
|
806
|
-
GEMINI_MOTION_MODELS =
|
|
807
|
-
gemini: GEMINI_DEFAULT_TEXT_MODEL,
|
|
808
|
-
flash: GEMINI_DEFAULT_TEXT_MODEL,
|
|
809
|
-
latest: GEMINI_DEFAULT_TEXT_MODEL,
|
|
810
|
-
"flash-3.5": GEMINI_DEFAULT_TEXT_MODEL,
|
|
811
|
-
"flash-3": "gemini-3-flash-preview",
|
|
812
|
-
"flash-2.5": "gemini-2.5-flash",
|
|
813
|
-
pro: "gemini-2.5-pro",
|
|
814
|
-
"2.5-pro": "gemini-2.5-pro",
|
|
815
|
-
"3.1-pro": "gemini-3.1-pro-preview",
|
|
816
|
-
"pro-3.1": "gemini-3.1-pro-preview"
|
|
817
|
-
};
|
|
873
|
+
GEMINI_MOTION_MODELS = GEMINI_TEXT_MODEL_ALIASES;
|
|
818
874
|
STYLE_USER_INSTRUCTIONS = {
|
|
819
875
|
minimal: "CENTER-ALIGNED pure typography. Thin lines + large title + subtitle. NO glass panels, NO bokeh, NO dark bars. Breathing pulse during hold.",
|
|
820
876
|
corporate: "Data-rich info bar at bottom + top-right badge. Animated number counter. Brand color stripe. Progress bar.",
|
|
@@ -922,7 +978,6 @@ var init_storyboard_prompt = __esm({
|
|
|
922
978
|
async function analyzeContent(api, content, targetDuration, options) {
|
|
923
979
|
const creativity = options?.creativity || "low";
|
|
924
980
|
const systemPrompt = buildStoryboardSystemPrompt(targetDuration, creativity);
|
|
925
|
-
const temperature = creativity === "high" ? 1 : 0.7;
|
|
926
981
|
try {
|
|
927
982
|
const payload = {
|
|
928
983
|
system_instruction: {
|
|
@@ -932,7 +987,6 @@ async function analyzeContent(api, content, targetDuration, options) {
|
|
|
932
987
|
parts: [{ text: buildStoryboardUserMessage(content) }]
|
|
933
988
|
}],
|
|
934
989
|
generationConfig: {
|
|
935
|
-
temperature,
|
|
936
990
|
maxOutputTokens: 4096
|
|
937
991
|
}
|
|
938
992
|
};
|
|
@@ -1003,7 +1057,15 @@ var init_http = __esm({
|
|
|
1003
1057
|
});
|
|
1004
1058
|
|
|
1005
1059
|
// ../ai-providers/dist/gemini/GeminiProvider.js
|
|
1006
|
-
|
|
1060
|
+
function resolveVeoModel(alias) {
|
|
1061
|
+
if (Object.hasOwn(VEO_MODEL_ALIASES, alias)) {
|
|
1062
|
+
return VEO_MODEL_ALIASES[alias];
|
|
1063
|
+
}
|
|
1064
|
+
const valid = Object.keys(VEO_MODEL_ALIASES).join(", ");
|
|
1065
|
+
const hint = alias === "3.0" ? " Veo 3.0 was shut down by Google on 2025-11-12." : "";
|
|
1066
|
+
throw new Error(`Unknown Veo model "${alias}". Valid: ${valid}.${hint}`);
|
|
1067
|
+
}
|
|
1068
|
+
var VEO_MODEL_ALIASES, GeminiProvider, geminiProvider;
|
|
1007
1069
|
var init_GeminiProvider = __esm({
|
|
1008
1070
|
"../ai-providers/dist/gemini/GeminiProvider.js"() {
|
|
1009
1071
|
"use strict";
|
|
@@ -1011,15 +1073,8 @@ var init_GeminiProvider = __esm({
|
|
|
1011
1073
|
init_gemini_models();
|
|
1012
1074
|
init_gemini_storyboard();
|
|
1013
1075
|
init_http();
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
"3.1-flash": "gemini-3.1-flash-image-preview",
|
|
1017
|
-
"latest": "gemini-3.1-flash-image-preview",
|
|
1018
|
-
"pro": "gemini-3-pro-image-preview",
|
|
1019
|
-
"gemini-2.5-flash-image": "gemini-2.5-flash-image",
|
|
1020
|
-
"gemini-3.1-flash-image-preview": "gemini-3.1-flash-image-preview",
|
|
1021
|
-
"gemini-3-pro-image-preview": "gemini-3-pro-image-preview"
|
|
1022
|
-
};
|
|
1076
|
+
init_catalog();
|
|
1077
|
+
VEO_MODEL_ALIASES = Object.fromEntries(listModels({ provider: "veo", kind: "video" }).flatMap((m2) => (m2.aliases ?? []).map((a4) => [a4, m2.id])));
|
|
1023
1078
|
GeminiProvider = class {
|
|
1024
1079
|
constructor() {
|
|
1025
1080
|
this.id = "gemini";
|
|
@@ -1278,9 +1333,7 @@ var init_GeminiProvider = __esm({
|
|
|
1278
1333
|
* Resolve model alias to full model ID
|
|
1279
1334
|
*/
|
|
1280
1335
|
resolveModel(model) {
|
|
1281
|
-
|
|
1282
|
-
return MODEL_MAP["flash"];
|
|
1283
|
-
return MODEL_MAP[model] || MODEL_MAP["flash"];
|
|
1336
|
+
return (findModel("gemini", "image", model) ?? defaultModel("gemini", "image")).id;
|
|
1284
1337
|
}
|
|
1285
1338
|
/**
|
|
1286
1339
|
* Check if model is Pro
|
|
@@ -1324,7 +1377,7 @@ var init_GeminiProvider = __esm({
|
|
|
1324
1377
|
contents: [{ parts: [{ text: prompt3 }] }],
|
|
1325
1378
|
generationConfig
|
|
1326
1379
|
};
|
|
1327
|
-
const is31Flash = modelId
|
|
1380
|
+
const is31Flash = modelId.startsWith("gemini-3.1-flash-image");
|
|
1328
1381
|
if (options.imageSearchGrounding && is31Flash) {
|
|
1329
1382
|
payload.tools = [{ googleSearch: { searchTypes: { webSearch: {}, imageSearch: {} } } }];
|
|
1330
1383
|
} else if (options.grounding && isPro) {
|
|
@@ -1552,7 +1605,6 @@ var init_GeminiProvider = __esm({
|
|
|
1552
1605
|
videoPart.video_metadata = videoMetadata;
|
|
1553
1606
|
}
|
|
1554
1607
|
const generationConfig = {
|
|
1555
|
-
temperature: 0.4,
|
|
1556
1608
|
maxOutputTokens: 8192
|
|
1557
1609
|
};
|
|
1558
1610
|
if (options.lowResolution) {
|
|
@@ -1634,7 +1686,6 @@ var init_GeminiProvider = __esm({
|
|
|
1634
1686
|
}
|
|
1635
1687
|
}));
|
|
1636
1688
|
const generationConfig = {
|
|
1637
|
-
temperature: 0.4,
|
|
1638
1689
|
maxOutputTokens: 8192
|
|
1639
1690
|
};
|
|
1640
1691
|
if (options.lowResolution) {
|
|
@@ -1734,7 +1785,6 @@ Respond with ONLY the JSON array, no other text.`;
|
|
|
1734
1785
|
body: JSON.stringify({
|
|
1735
1786
|
contents: [{ parts: [{ text: prompt3 }] }],
|
|
1736
1787
|
generationConfig: {
|
|
1737
|
-
temperature: 0.3,
|
|
1738
1788
|
maxOutputTokens: 1024
|
|
1739
1789
|
}
|
|
1740
1790
|
})
|
|
@@ -1828,7 +1878,7 @@ Respond with ONLY the JSON array, no other text.`;
|
|
|
1828
1878
|
return refineMotion({ apiKey: this.apiKey, baseUrl: this.baseUrl }, existingCode, instructions, options);
|
|
1829
1879
|
}
|
|
1830
1880
|
/**
|
|
1831
|
-
* Generate a storyboard from script content using Gemini
|
|
1881
|
+
* Generate a storyboard from script content using the default Gemini Flash model.
|
|
1832
1882
|
* Alternative to ClaudeProvider.analyzeContent for when Claude is unavailable.
|
|
1833
1883
|
*/
|
|
1834
1884
|
async analyzeContent(content, targetDuration, options) {
|
|
@@ -1843,43 +1893,48 @@ Respond with ONLY the JSON array, no other text.`;
|
|
|
1843
1893
|
});
|
|
1844
1894
|
|
|
1845
1895
|
// ../ai-providers/dist/gemini/gemini-omni.js
|
|
1846
|
-
function
|
|
1847
|
-
const
|
|
1848
|
-
|
|
1849
|
-
return refs3[0];
|
|
1850
|
-
const ref2 = options.referenceImage;
|
|
1851
|
-
if (typeof ref2 === "string" && ref2) {
|
|
1896
|
+
function frameImages(options) {
|
|
1897
|
+
const frames = [];
|
|
1898
|
+
const toInline = (ref2) => {
|
|
1852
1899
|
const m2 = ref2.match(/^data:(.+?);base64,(.*)$/);
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1900
|
+
return m2 ? { mimeType: m2[1], base64: m2[2] } : { mimeType: "image/png", base64: ref2 };
|
|
1901
|
+
};
|
|
1902
|
+
if (options.referenceImages?.[0]?.base64)
|
|
1903
|
+
frames.push(options.referenceImages[0]);
|
|
1904
|
+
else if (typeof options.referenceImage === "string" && options.referenceImage) {
|
|
1905
|
+
frames.push(toInline(options.referenceImage));
|
|
1856
1906
|
}
|
|
1857
|
-
|
|
1907
|
+
if (frames.length > 0 && options.lastFrame)
|
|
1908
|
+
frames.push(toInline(options.lastFrame));
|
|
1909
|
+
return frames;
|
|
1858
1910
|
}
|
|
1859
|
-
function
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
const nested = findVideoUrl(v4);
|
|
1867
|
-
if (nested)
|
|
1868
|
-
return nested;
|
|
1869
|
-
}
|
|
1911
|
+
function findOmniVideo(response) {
|
|
1912
|
+
for (const step of response.steps ?? []) {
|
|
1913
|
+
if (step.type !== "model_output")
|
|
1914
|
+
continue;
|
|
1915
|
+
const video = step.content?.find((c2) => c2.type === "video");
|
|
1916
|
+
if (video)
|
|
1917
|
+
return video;
|
|
1870
1918
|
}
|
|
1871
|
-
return
|
|
1919
|
+
return response.output_video;
|
|
1920
|
+
}
|
|
1921
|
+
function fileIdFromUri(uri) {
|
|
1922
|
+
return uri.match(/files\/([^/?:]+)/)?.[1];
|
|
1872
1923
|
}
|
|
1873
|
-
var OMNI_MODEL,
|
|
1924
|
+
var OMNI_MODEL, API_ROOT, FILE_POLL_INTERVAL_MS, FILE_POLL_TIMEOUT_MS, OmniProvider, omniProvider;
|
|
1874
1925
|
var init_gemini_omni = __esm({
|
|
1875
1926
|
"../ai-providers/dist/gemini/gemini-omni.js"() {
|
|
1876
1927
|
"use strict";
|
|
1877
|
-
|
|
1878
|
-
|
|
1928
|
+
init_http();
|
|
1929
|
+
init_catalog();
|
|
1930
|
+
OMNI_MODEL = defaultModel("omni", "video").id;
|
|
1931
|
+
API_ROOT = "https://generativelanguage.googleapis.com";
|
|
1932
|
+
FILE_POLL_INTERVAL_MS = 3e3;
|
|
1933
|
+
FILE_POLL_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
1879
1934
|
OmniProvider = class {
|
|
1880
1935
|
constructor() {
|
|
1881
1936
|
this.id = "omni";
|
|
1882
|
-
this.label = "Gemini Omni
|
|
1937
|
+
this.label = "Gemini Omni 1.1 Flash";
|
|
1883
1938
|
}
|
|
1884
1939
|
async initialize(config4) {
|
|
1885
1940
|
this.apiKey = config4.apiKey;
|
|
@@ -1892,22 +1947,23 @@ var init_gemini_omni = __esm({
|
|
|
1892
1947
|
return { id: "", status: "failed", error: "GOOGLE_API_KEY not configured for Gemini Omni" };
|
|
1893
1948
|
}
|
|
1894
1949
|
const opts = options ?? { prompt: prompt3 };
|
|
1895
|
-
const
|
|
1896
|
-
const
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
inputs.push({ inline_data: { mime_type: image.mimeType, data: image.base64 } });
|
|
1901
|
-
}
|
|
1950
|
+
const frames = frameImages(opts);
|
|
1951
|
+
const input3 = frames.length === 0 ? prompt3 : [
|
|
1952
|
+
...frames.map((f2) => ({ type: "image", data: f2.base64, mime_type: f2.mimeType })),
|
|
1953
|
+
{ type: "text", text: prompt3 }
|
|
1954
|
+
];
|
|
1902
1955
|
const body = {
|
|
1903
1956
|
model: OMNI_MODEL,
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1957
|
+
input: input3,
|
|
1958
|
+
response_format: {
|
|
1959
|
+
type: "video",
|
|
1960
|
+
aspect_ratio: opts.aspectRatio === "9:16" ? "9:16" : "16:9",
|
|
1961
|
+
resolution: opts.resolution ?? "720p",
|
|
1962
|
+
delivery: "uri"
|
|
1907
1963
|
}
|
|
1908
1964
|
};
|
|
1909
1965
|
try {
|
|
1910
|
-
const res = await fetch(
|
|
1966
|
+
const res = await fetch(`${API_ROOT}/v1beta/interactions`, {
|
|
1911
1967
|
method: "POST",
|
|
1912
1968
|
headers: { "Content-Type": "application/json", "x-goog-api-key": this.apiKey },
|
|
1913
1969
|
body: JSON.stringify(body)
|
|
@@ -1917,33 +1973,52 @@ var init_gemini_omni = __esm({
|
|
|
1917
1973
|
return {
|
|
1918
1974
|
id: "",
|
|
1919
1975
|
status: "failed",
|
|
1920
|
-
error: `Gemini Omni
|
|
1976
|
+
error: `Gemini Omni request failed: HTTP ${res.status} - ${text.slice(0, 300)}`
|
|
1921
1977
|
};
|
|
1922
1978
|
}
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1979
|
+
const parsed = JSON.parse(text);
|
|
1980
|
+
const id = parsed.id ?? "";
|
|
1981
|
+
const video = findOmniVideo(parsed);
|
|
1982
|
+
if (!video?.uri) {
|
|
1983
|
+
const reason = parsed.error?.message ?? `status ${parsed.status ?? "unknown"}`;
|
|
1984
|
+
return { id, status: "failed", error: `Gemini Omni returned no video (${reason})` };
|
|
1928
1985
|
}
|
|
1929
|
-
const
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
};
|
|
1986
|
+
const fileId = fileIdFromUri(video.uri);
|
|
1987
|
+
if (!fileId) {
|
|
1988
|
+
return { id, status: "failed", error: `Gemini Omni returned an unexpected video URI: ${video.uri}` };
|
|
1989
|
+
}
|
|
1990
|
+
const ready = await this.waitForFile(fileId);
|
|
1991
|
+
if (ready !== "ACTIVE") {
|
|
1992
|
+
return { id, status: "failed", error: `Gemini Omni video file ended in state ${ready}` };
|
|
1937
1993
|
}
|
|
1938
|
-
return {
|
|
1994
|
+
return {
|
|
1995
|
+
id,
|
|
1996
|
+
status: "completed",
|
|
1997
|
+
videoUrl: `${API_ROOT}/download/v1beta/files/${fileId}:download?alt=media`
|
|
1998
|
+
};
|
|
1939
1999
|
} catch (err) {
|
|
1940
2000
|
return {
|
|
1941
2001
|
id: "",
|
|
1942
2002
|
status: "failed",
|
|
1943
|
-
error: `Gemini Omni
|
|
2003
|
+
error: `Gemini Omni error: ${err instanceof Error ? err.message : String(err)}`
|
|
1944
2004
|
};
|
|
1945
2005
|
}
|
|
1946
2006
|
}
|
|
2007
|
+
/** Poll the Files API until the generated video is downloadable. */
|
|
2008
|
+
async waitForFile(fileId) {
|
|
2009
|
+
const deadline = Date.now() + FILE_POLL_TIMEOUT_MS;
|
|
2010
|
+
for (; ; ) {
|
|
2011
|
+
const res = await fetch(`${API_ROOT}/v1beta/files/${fileId}`, {
|
|
2012
|
+
headers: { "x-goog-api-key": this.apiKey }
|
|
2013
|
+
});
|
|
2014
|
+
const state = res.ok ? (await res.json()).state : `HTTP ${res.status}`;
|
|
2015
|
+
if (state !== "PROCESSING")
|
|
2016
|
+
return state ?? "UNKNOWN";
|
|
2017
|
+
if (Date.now() > deadline)
|
|
2018
|
+
return "TIMEOUT";
|
|
2019
|
+
await sleep(FILE_POLL_INTERVAL_MS);
|
|
2020
|
+
}
|
|
2021
|
+
}
|
|
1947
2022
|
};
|
|
1948
2023
|
omniProvider = new OmniProvider();
|
|
1949
2024
|
}
|
|
@@ -1977,24 +2052,33 @@ var init_gemini = __esm({
|
|
|
1977
2052
|
label: "Veo",
|
|
1978
2053
|
apiKey: "google",
|
|
1979
2054
|
kinds: ["video"],
|
|
1980
|
-
resolverPriority:
|
|
2055
|
+
// No resolverPriority: the Veo 3.1 previews shut down on 2026-10-22, so
|
|
2056
|
+
// Veo is explicit-only (`-p veo`) and Omni is the Google default.
|
|
1981
2057
|
commandsUnlocked: ["generate video -p veo"]
|
|
1982
2058
|
});
|
|
1983
2059
|
defineProvider({
|
|
1984
2060
|
id: "omni",
|
|
1985
|
-
label: "Gemini Omni
|
|
2061
|
+
label: "Gemini Omni",
|
|
1986
2062
|
apiKey: "google",
|
|
1987
2063
|
kinds: ["video"],
|
|
2064
|
+
resolverPriority: { video: 3 },
|
|
1988
2065
|
commandsUnlocked: ["generate video -p omni"]
|
|
1989
2066
|
});
|
|
1990
2067
|
}
|
|
1991
2068
|
});
|
|
1992
2069
|
|
|
2070
|
+
// ../ai-providers/dist/catalog/index.js
|
|
2071
|
+
var init_catalog2 = __esm({
|
|
2072
|
+
"../ai-providers/dist/catalog/index.js"() {
|
|
2073
|
+
"use strict";
|
|
2074
|
+
init_catalog();
|
|
2075
|
+
}
|
|
2076
|
+
});
|
|
2077
|
+
|
|
1993
2078
|
// ../ai-providers/dist/openai/openai-storyboard.js
|
|
1994
2079
|
async function analyzeContent2(apiKey, content, targetDuration, options) {
|
|
1995
2080
|
const creativity = options?.creativity || "low";
|
|
1996
|
-
const systemPrompt = buildStoryboardSystemPrompt(targetDuration, creativity);
|
|
1997
|
-
const temperature = creativity === "high" ? 1 : 0.7;
|
|
2081
|
+
const systemPrompt = buildStoryboardSystemPrompt(targetDuration, creativity) + '\n\nWrap the array in a JSON object: {"segments": [ ...segment objects... ]}.';
|
|
1998
2082
|
try {
|
|
1999
2083
|
const response = await fetch("https://api.openai.com/v1/chat/completions", {
|
|
2000
2084
|
method: "POST",
|
|
@@ -2003,13 +2087,13 @@ async function analyzeContent2(apiKey, content, targetDuration, options) {
|
|
|
2003
2087
|
Authorization: `Bearer ${apiKey}`
|
|
2004
2088
|
},
|
|
2005
2089
|
body: JSON.stringify({
|
|
2006
|
-
model: "
|
|
2090
|
+
model: defaultModel("openai", "llm").id,
|
|
2007
2091
|
messages: [
|
|
2008
2092
|
{ role: "system", content: systemPrompt },
|
|
2009
2093
|
{ role: "user", content: buildStoryboardUserMessage(content) }
|
|
2010
2094
|
],
|
|
2011
|
-
|
|
2012
|
-
|
|
2095
|
+
// Reasoning tokens count against this cap.
|
|
2096
|
+
max_completion_tokens: 16384,
|
|
2013
2097
|
response_format: { type: "json_object" }
|
|
2014
2098
|
})
|
|
2015
2099
|
});
|
|
@@ -2048,6 +2132,7 @@ var init_openai_storyboard = __esm({
|
|
|
2048
2132
|
"../ai-providers/dist/openai/openai-storyboard.js"() {
|
|
2049
2133
|
"use strict";
|
|
2050
2134
|
init_storyboard_prompt();
|
|
2135
|
+
init_catalog();
|
|
2051
2136
|
}
|
|
2052
2137
|
});
|
|
2053
2138
|
|
|
@@ -2057,6 +2142,7 @@ var init_OpenAIProvider = __esm({
|
|
|
2057
2142
|
"../ai-providers/dist/openai/OpenAIProvider.js"() {
|
|
2058
2143
|
"use strict";
|
|
2059
2144
|
init_openai_storyboard();
|
|
2145
|
+
init_catalog();
|
|
2060
2146
|
OpenAIProvider = class {
|
|
2061
2147
|
constructor() {
|
|
2062
2148
|
this.id = "openai-gpt";
|
|
@@ -2066,7 +2152,7 @@ var init_OpenAIProvider = __esm({
|
|
|
2066
2152
|
this.iconUrl = "/icons/openai.svg";
|
|
2067
2153
|
this.isAvailable = true;
|
|
2068
2154
|
this.baseUrl = "https://api.openai.com/v1";
|
|
2069
|
-
this.model = "
|
|
2155
|
+
this.model = defaultModel("openai", "llm").id;
|
|
2070
2156
|
}
|
|
2071
2157
|
async initialize(config4) {
|
|
2072
2158
|
this.apiKey = config4.apiKey;
|
|
@@ -2162,7 +2248,6 @@ Or if clarification needed:
|
|
|
2162
2248
|
{ role: "system", content: systemPrompt },
|
|
2163
2249
|
{ role: "user", content: instruction }
|
|
2164
2250
|
],
|
|
2165
|
-
temperature: 0.2,
|
|
2166
2251
|
response_format: { type: "json_object" }
|
|
2167
2252
|
})
|
|
2168
2253
|
});
|
|
@@ -2373,8 +2458,9 @@ Each segment should be 3-10 seconds long.`;
|
|
|
2373
2458
|
Authorization: `Bearer ${this.apiKey}`
|
|
2374
2459
|
},
|
|
2375
2460
|
body: JSON.stringify({
|
|
2376
|
-
model: "
|
|
2377
|
-
|
|
2461
|
+
model: defaultModel("openai", "llm").id,
|
|
2462
|
+
// Reasoning tokens count against this cap.
|
|
2463
|
+
max_completion_tokens: 16384,
|
|
2378
2464
|
response_format: { type: "json_object" },
|
|
2379
2465
|
messages: [
|
|
2380
2466
|
{ role: "system", content: systemPrompt },
|
|
@@ -2407,7 +2493,7 @@ ${videoAnalysis}` }
|
|
|
2407
2493
|
}
|
|
2408
2494
|
}
|
|
2409
2495
|
/**
|
|
2410
|
-
* Generate a storyboard from script content using GPT-5
|
|
2496
|
+
* Generate a storyboard from script content using GPT-5.4 mini.
|
|
2411
2497
|
* Alternative to ClaudeProvider.analyzeContent for when Claude is unavailable.
|
|
2412
2498
|
*/
|
|
2413
2499
|
async analyzeContent(content, targetDuration, options) {
|
|
@@ -2455,10 +2541,12 @@ async function callClaude(params, opts) {
|
|
|
2455
2541
|
},
|
|
2456
2542
|
body: JSON.stringify({
|
|
2457
2543
|
model: params.model,
|
|
2458
|
-
|
|
2459
|
-
|
|
2544
|
+
// Claude 5.x thinks by default and thinking tokens count against
|
|
2545
|
+
// max_tokens, so a small cap can end before any text is written.
|
|
2546
|
+
max_tokens: Math.max(opts.maxTokens, CLAUDE_MIN_MAX_TOKENS),
|
|
2460
2547
|
messages: opts.messages,
|
|
2461
|
-
system: opts.system
|
|
2548
|
+
system: opts.system,
|
|
2549
|
+
...opts.jsonSchema ? { output_config: { format: { type: "json_schema", schema: opts.jsonSchema } } } : {}
|
|
2462
2550
|
})
|
|
2463
2551
|
});
|
|
2464
2552
|
if (!response.ok) {
|
|
@@ -2480,9 +2568,11 @@ function extractJsonArray(text) {
|
|
|
2480
2568
|
const match2 = text.match(/\[[\s\S]*\]/);
|
|
2481
2569
|
return match2 ? match2[0] : null;
|
|
2482
2570
|
}
|
|
2571
|
+
var CLAUDE_MIN_MAX_TOKENS;
|
|
2483
2572
|
var init_claude_api = __esm({
|
|
2484
2573
|
"../ai-providers/dist/claude/claude-api.js"() {
|
|
2485
2574
|
"use strict";
|
|
2575
|
+
CLAUDE_MIN_MAX_TOKENS = 16e3;
|
|
2486
2576
|
}
|
|
2487
2577
|
});
|
|
2488
2578
|
|
|
@@ -2518,7 +2608,8 @@ MANDATORY ADAPTATION RULES:
|
|
|
2518
2608
|
const text = await callClaude(api, {
|
|
2519
2609
|
system: systemPrompt,
|
|
2520
2610
|
messages: [{ role: "user", content: userContent }],
|
|
2521
|
-
maxTokens: 16e3
|
|
2611
|
+
maxTokens: 16e3,
|
|
2612
|
+
jsonSchema: MOTION_COMPONENT_SCHEMA
|
|
2522
2613
|
});
|
|
2523
2614
|
const jsonStr = extractJsonObject(text);
|
|
2524
2615
|
if (!jsonStr) {
|
|
@@ -2593,7 +2684,8 @@ Modification instructions: ${instructions}
|
|
|
2593
2684
|
|
|
2594
2685
|
Return the complete modified component as JSON.`
|
|
2595
2686
|
}],
|
|
2596
|
-
maxTokens: 16e3
|
|
2687
|
+
maxTokens: 16e3,
|
|
2688
|
+
jsonSchema: MOTION_COMPONENT_SCHEMA
|
|
2597
2689
|
});
|
|
2598
2690
|
const jsonStr = extractJsonObject(text);
|
|
2599
2691
|
if (!jsonStr)
|
|
@@ -2622,15 +2714,13 @@ async function analyzeContent3(api, content, targetDuration, options) {
|
|
|
2622
2714
|
const creativity = options?.creativity || "low";
|
|
2623
2715
|
const systemPrompt = buildStoryboardSystemPrompt(targetDuration, creativity);
|
|
2624
2716
|
try {
|
|
2625
|
-
const temperature = creativity === "high" ? 1 : 0.7;
|
|
2626
2717
|
const text = await callClaude(api, {
|
|
2627
2718
|
system: systemPrompt,
|
|
2628
2719
|
messages: [{
|
|
2629
2720
|
role: "user",
|
|
2630
2721
|
content: buildStoryboardUserMessage(content)
|
|
2631
2722
|
}],
|
|
2632
|
-
maxTokens: 4096
|
|
2633
|
-
temperature
|
|
2723
|
+
maxTokens: 4096
|
|
2634
2724
|
});
|
|
2635
2725
|
const jsonStr = extractJsonArray(text);
|
|
2636
2726
|
if (!jsonStr) {
|
|
@@ -2987,11 +3077,22 @@ UNIVERSAL RULES:
|
|
|
2987
3077
|
- Both entrance AND exit animations
|
|
2988
3078
|
- whiteSpace: "nowrap" on all text`;
|
|
2989
3079
|
}
|
|
3080
|
+
var MOTION_COMPONENT_SCHEMA;
|
|
2990
3081
|
var init_claude_motion = __esm({
|
|
2991
3082
|
"../ai-providers/dist/claude/claude-motion.js"() {
|
|
2992
3083
|
"use strict";
|
|
2993
3084
|
init_claude_api();
|
|
2994
3085
|
init_storyboard_prompt();
|
|
3086
|
+
MOTION_COMPONENT_SCHEMA = {
|
|
3087
|
+
type: "object",
|
|
3088
|
+
properties: {
|
|
3089
|
+
name: { type: "string" },
|
|
3090
|
+
code: { type: "string" },
|
|
3091
|
+
description: { type: "string" }
|
|
3092
|
+
},
|
|
3093
|
+
required: ["name", "code", "description"],
|
|
3094
|
+
additionalProperties: false
|
|
3095
|
+
};
|
|
2995
3096
|
}
|
|
2996
3097
|
});
|
|
2997
3098
|
|
|
@@ -3753,10 +3854,12 @@ var ClaudeProvider, claudeProvider;
|
|
|
3753
3854
|
var init_ClaudeProvider = __esm({
|
|
3754
3855
|
"../ai-providers/dist/claude/ClaudeProvider.js"() {
|
|
3755
3856
|
"use strict";
|
|
3857
|
+
init_claude_api();
|
|
3756
3858
|
init_claude_motion();
|
|
3757
3859
|
init_claude_analysis();
|
|
3758
3860
|
init_claude_viral();
|
|
3759
3861
|
init_claude_visual_fx();
|
|
3862
|
+
init_catalog();
|
|
3760
3863
|
ClaudeProvider = class {
|
|
3761
3864
|
constructor() {
|
|
3762
3865
|
this.id = "claude";
|
|
@@ -3766,7 +3869,7 @@ var init_ClaudeProvider = __esm({
|
|
|
3766
3869
|
this.iconUrl = "/icons/claude.svg";
|
|
3767
3870
|
this.isAvailable = true;
|
|
3768
3871
|
this.baseUrl = "https://api.anthropic.com/v1";
|
|
3769
|
-
this.model = "claude
|
|
3872
|
+
this.model = defaultModel("claude", "llm").id;
|
|
3770
3873
|
}
|
|
3771
3874
|
async initialize(config4) {
|
|
3772
3875
|
this.apiKey = config4.apiKey;
|
|
@@ -3870,7 +3973,7 @@ Or if clarification needed:
|
|
|
3870
3973
|
},
|
|
3871
3974
|
body: JSON.stringify({
|
|
3872
3975
|
model: this.model,
|
|
3873
|
-
max_tokens:
|
|
3976
|
+
max_tokens: CLAUDE_MIN_MAX_TOKENS,
|
|
3874
3977
|
messages: [{ role: "user", content: instruction }],
|
|
3875
3978
|
system: systemPrompt
|
|
3876
3979
|
})
|
|
@@ -3940,7 +4043,7 @@ Respond with JSON array:
|
|
|
3940
4043
|
},
|
|
3941
4044
|
body: JSON.stringify({
|
|
3942
4045
|
model: this.model,
|
|
3943
|
-
max_tokens:
|
|
4046
|
+
max_tokens: CLAUDE_MIN_MAX_TOKENS,
|
|
3944
4047
|
messages: [{
|
|
3945
4048
|
role: "user",
|
|
3946
4049
|
content: `Clips: ${JSON.stringify(clipsInfo)}
|
|
@@ -4068,11 +4171,7 @@ Instruction: ${instruction}`
|
|
|
4068
4171
|
return generateNarrationScript(this.api, videoAnalysis, duration, style, language);
|
|
4069
4172
|
}
|
|
4070
4173
|
};
|
|
4071
|
-
ClaudeProvider.MOTION_MODELS = {
|
|
4072
|
-
sonnet: "claude-sonnet-4-6",
|
|
4073
|
-
opus: "claude-opus-4-7",
|
|
4074
|
-
"opus-4-6": "claude-opus-4-6"
|
|
4075
|
-
};
|
|
4174
|
+
ClaudeProvider.MOTION_MODELS = Object.fromEntries(listModels({ provider: "claude", kind: "llm" }).flatMap((m2) => (m2.aliases ?? []).map((a4) => [a4, m2.id])));
|
|
4076
4175
|
claudeProvider = new ClaudeProvider();
|
|
4077
4176
|
}
|
|
4078
4177
|
});
|
|
@@ -4408,10 +4507,11 @@ function resolveVoiceId(input3) {
|
|
|
4408
4507
|
const availableVoices = Object.keys(KNOWN_VOICES).join(", ");
|
|
4409
4508
|
throw new Error(`Unknown voice "${input3}". Available voices: ${availableVoices}. You can also use a custom voice ID from your ElevenLabs account.`);
|
|
4410
4509
|
}
|
|
4411
|
-
var KNOWN_VOICES, TTS_429_MAX_RETRIES, TTS_429_RETRY_DELAY_MS, ElevenLabsProvider, elevenLabsProvider;
|
|
4510
|
+
var KNOWN_VOICES, TTS_429_MAX_RETRIES, TTS_429_RETRY_DELAY_MS, ELEVENLABS_MUSIC_MODEL, ElevenLabsProvider, elevenLabsProvider;
|
|
4412
4511
|
var init_ElevenLabsProvider = __esm({
|
|
4413
4512
|
"../ai-providers/dist/elevenlabs/ElevenLabsProvider.js"() {
|
|
4414
4513
|
"use strict";
|
|
4514
|
+
init_catalog();
|
|
4415
4515
|
KNOWN_VOICES = {
|
|
4416
4516
|
// Default/popular voices
|
|
4417
4517
|
rachel: "21m00Tcm4TlvDq8ikWAM",
|
|
@@ -4445,6 +4545,7 @@ var init_ElevenLabsProvider = __esm({
|
|
|
4445
4545
|
};
|
|
4446
4546
|
TTS_429_MAX_RETRIES = 1;
|
|
4447
4547
|
TTS_429_RETRY_DELAY_MS = 2e3;
|
|
4548
|
+
ELEVENLABS_MUSIC_MODEL = defaultModel("elevenlabs", "music").id;
|
|
4448
4549
|
ElevenLabsProvider = class {
|
|
4449
4550
|
constructor() {
|
|
4450
4551
|
this.id = "elevenlabs";
|
|
@@ -4525,9 +4626,10 @@ var init_ElevenLabsProvider = __esm({
|
|
|
4525
4626
|
stability: options.stability ?? 0.5,
|
|
4526
4627
|
similarity_boost: options.similarityBoost ?? 0.75,
|
|
4527
4628
|
style: options.style ?? 0,
|
|
4528
|
-
use_speaker_boost: true
|
|
4529
|
-
|
|
4530
|
-
|
|
4629
|
+
use_speaker_boost: true,
|
|
4630
|
+
// The API reads speed only inside voice_settings.
|
|
4631
|
+
...options.speed !== void 0 && { speed: options.speed }
|
|
4632
|
+
}
|
|
4531
4633
|
})
|
|
4532
4634
|
});
|
|
4533
4635
|
if (response.status === 429 && attempt < TTS_429_MAX_RETRIES) {
|
|
@@ -4597,7 +4699,7 @@ var init_ElevenLabsProvider = __esm({
|
|
|
4597
4699
|
prompt_influence: options.promptInfluence ?? 0.3
|
|
4598
4700
|
};
|
|
4599
4701
|
if (options.duration !== void 0) {
|
|
4600
|
-
const duration = Math.max(0.5, Math.min(
|
|
4702
|
+
const duration = Math.max(0.5, Math.min(30, options.duration));
|
|
4601
4703
|
body.duration_seconds = duration;
|
|
4602
4704
|
}
|
|
4603
4705
|
const response = await fetch(`${this.baseUrl}/sound-generation`, {
|
|
@@ -4642,7 +4744,7 @@ var init_ElevenLabsProvider = __esm({
|
|
|
4642
4744
|
try {
|
|
4643
4745
|
const body = {
|
|
4644
4746
|
prompt: prompt3,
|
|
4645
|
-
model_id:
|
|
4747
|
+
model_id: ELEVENLABS_MUSIC_MODEL
|
|
4646
4748
|
};
|
|
4647
4749
|
if (options.duration !== void 0) {
|
|
4648
4750
|
const duration = Math.max(3, Math.min(600, options.duration));
|
|
@@ -4853,6 +4955,55 @@ var init_elevenlabs = __esm({
|
|
|
4853
4955
|
});
|
|
4854
4956
|
|
|
4855
4957
|
// ../ai-providers/dist/kokoro/KokoroProvider.js
|
|
4958
|
+
function splitForKokoro(text, maxChars = KOKORO_MAX_CHUNK_CHARS) {
|
|
4959
|
+
const pieces = (part, pattern) => part.length <= maxChars ? [part] : part.split(pattern).filter((p2) => p2.trim().length > 0);
|
|
4960
|
+
const units2 = text.trim().split(/(?<=[.!?…])\s+/).flatMap((sentence) => pieces(sentence, /(?<=[,;:])\s+/)).flatMap((clause) => {
|
|
4961
|
+
if (clause.length <= maxChars)
|
|
4962
|
+
return [clause];
|
|
4963
|
+
const words = [];
|
|
4964
|
+
let line = "";
|
|
4965
|
+
for (const word of clause.split(/\s+/)) {
|
|
4966
|
+
if (line && line.length + word.length + 1 > maxChars) {
|
|
4967
|
+
words.push(line);
|
|
4968
|
+
line = word;
|
|
4969
|
+
} else {
|
|
4970
|
+
line = line ? `${line} ${word}` : word;
|
|
4971
|
+
}
|
|
4972
|
+
}
|
|
4973
|
+
if (line)
|
|
4974
|
+
words.push(line);
|
|
4975
|
+
return words;
|
|
4976
|
+
});
|
|
4977
|
+
const chunks = [];
|
|
4978
|
+
for (const unit of units2) {
|
|
4979
|
+
const last3 = chunks.at(-1);
|
|
4980
|
+
if (last3 !== void 0 && last3.length + unit.length + 1 <= maxChars) {
|
|
4981
|
+
chunks[chunks.length - 1] = `${last3} ${unit}`;
|
|
4982
|
+
} else {
|
|
4983
|
+
chunks.push(unit);
|
|
4984
|
+
}
|
|
4985
|
+
}
|
|
4986
|
+
return chunks;
|
|
4987
|
+
}
|
|
4988
|
+
function encodeFloatWav(samples, sampleRate) {
|
|
4989
|
+
const dataBytes = samples.length * 4;
|
|
4990
|
+
const buffer = Buffer.alloc(44 + dataBytes);
|
|
4991
|
+
buffer.write("RIFF", 0, "ascii");
|
|
4992
|
+
buffer.writeUInt32LE(36 + dataBytes, 4);
|
|
4993
|
+
buffer.write("WAVE", 8, "ascii");
|
|
4994
|
+
buffer.write("fmt ", 12, "ascii");
|
|
4995
|
+
buffer.writeUInt32LE(16, 16);
|
|
4996
|
+
buffer.writeUInt16LE(3, 20);
|
|
4997
|
+
buffer.writeUInt16LE(1, 22);
|
|
4998
|
+
buffer.writeUInt32LE(sampleRate, 24);
|
|
4999
|
+
buffer.writeUInt32LE(sampleRate * 4, 28);
|
|
5000
|
+
buffer.writeUInt16LE(4, 32);
|
|
5001
|
+
buffer.writeUInt16LE(32, 34);
|
|
5002
|
+
buffer.write("data", 36, "ascii");
|
|
5003
|
+
buffer.writeUInt32LE(dataBytes, 40);
|
|
5004
|
+
Buffer.from(samples.buffer, samples.byteOffset, dataBytes).copy(buffer, 44);
|
|
5005
|
+
return buffer;
|
|
5006
|
+
}
|
|
4856
5007
|
async function loadKokoroRuntime() {
|
|
4857
5008
|
if (factoryOverride)
|
|
4858
5009
|
return { factory: factoryOverride, device: "cpu" };
|
|
@@ -4890,7 +5041,7 @@ async function loadBundledKokoroRuntime(runtimeDir = process.env.VIBE_KOKORO_RUN
|
|
|
4890
5041
|
if (!base2)
|
|
4891
5042
|
return null;
|
|
4892
5043
|
try {
|
|
4893
|
-
const { readFile: readFile48, writeFile:
|
|
5044
|
+
const { readFile: readFile48, writeFile: writeFile51, mkdir: mkdir33 } = await import("node:fs/promises");
|
|
4894
5045
|
const { join: join79, resolve: resolve86 } = await import("node:path");
|
|
4895
5046
|
const { pathToFileURL: pathToFileURL2 } = await import("node:url");
|
|
4896
5047
|
const { homedir: homedir8 } = await import("node:os");
|
|
@@ -4911,8 +5062,8 @@ async function loadBundledKokoroRuntime(runtimeDir = process.env.VIBE_KOKORO_RUN
|
|
|
4911
5062
|
async put(key2, response) {
|
|
4912
5063
|
try {
|
|
4913
5064
|
const buf = Buffer.from(await response.arrayBuffer());
|
|
4914
|
-
await
|
|
4915
|
-
await
|
|
5065
|
+
await mkdir33(cacheRoot, { recursive: true });
|
|
5066
|
+
await writeFile51(join79(cacheRoot, encodeURIComponent(String(key2))), buf);
|
|
4916
5067
|
} catch {
|
|
4917
5068
|
}
|
|
4918
5069
|
}
|
|
@@ -4961,12 +5112,13 @@ function normaliseEvent(raw2) {
|
|
|
4961
5112
|
total: typeof r2.total === "number" ? r2.total : void 0
|
|
4962
5113
|
};
|
|
4963
5114
|
}
|
|
4964
|
-
var KOKORO_DEFAULT_VOICE, KOKORO_MODEL_ID, modelPromise, factoryOverride, KokoroProvider, kokoroProvider;
|
|
5115
|
+
var KOKORO_DEFAULT_VOICE, KOKORO_MODEL_ID, KOKORO_MAX_CHUNK_CHARS, modelPromise, factoryOverride, KokoroProvider, kokoroProvider;
|
|
4965
5116
|
var init_KokoroProvider = __esm({
|
|
4966
5117
|
"../ai-providers/dist/kokoro/KokoroProvider.js"() {
|
|
4967
5118
|
"use strict";
|
|
4968
5119
|
KOKORO_DEFAULT_VOICE = "af_heart";
|
|
4969
5120
|
KOKORO_MODEL_ID = "onnx-community/Kokoro-82M-v1.0-ONNX";
|
|
5121
|
+
KOKORO_MAX_CHUNK_CHARS = 300;
|
|
4970
5122
|
modelPromise = null;
|
|
4971
5123
|
factoryOverride = null;
|
|
4972
5124
|
KokoroProvider = class {
|
|
@@ -4993,11 +5145,32 @@ var init_KokoroProvider = __esm({
|
|
|
4993
5145
|
}
|
|
4994
5146
|
try {
|
|
4995
5147
|
const model = await loadModel(options.onProgress);
|
|
4996
|
-
const
|
|
5148
|
+
const voiceOptions = {
|
|
4997
5149
|
voice: options.voice ?? KOKORO_DEFAULT_VOICE,
|
|
4998
5150
|
speed: options.speed ?? 1
|
|
4999
|
-
}
|
|
5000
|
-
const
|
|
5151
|
+
};
|
|
5152
|
+
const chunks = splitForKokoro(text);
|
|
5153
|
+
let buffer;
|
|
5154
|
+
if (chunks.length === 1) {
|
|
5155
|
+
buffer = Buffer.from((await model.generate(chunks[0], voiceOptions)).toWav());
|
|
5156
|
+
} else {
|
|
5157
|
+
const parts = [];
|
|
5158
|
+
let sampleRate = 24e3;
|
|
5159
|
+
for (const chunk of chunks) {
|
|
5160
|
+
const audio = await model.generate(chunk, voiceOptions);
|
|
5161
|
+
if (!audio.audio)
|
|
5162
|
+
throw new Error("Kokoro returned no raw samples to join");
|
|
5163
|
+
parts.push(audio.audio);
|
|
5164
|
+
sampleRate = audio.sampling_rate ?? sampleRate;
|
|
5165
|
+
}
|
|
5166
|
+
const samples = new Float32Array(parts.reduce((n2, part) => n2 + part.length, 0));
|
|
5167
|
+
let offset = 0;
|
|
5168
|
+
for (const part of parts) {
|
|
5169
|
+
samples.set(part, offset);
|
|
5170
|
+
offset += part.length;
|
|
5171
|
+
}
|
|
5172
|
+
buffer = encodeFloatWav(samples, sampleRate);
|
|
5173
|
+
}
|
|
5001
5174
|
return {
|
|
5002
5175
|
success: true,
|
|
5003
5176
|
audioBuffer: buffer,
|
|
@@ -5032,11 +5205,13 @@ var init_kokoro = __esm({
|
|
|
5032
5205
|
});
|
|
5033
5206
|
|
|
5034
5207
|
// ../ai-providers/dist/openai-image/OpenAIImageProvider.js
|
|
5035
|
-
var DEFAULT_MODEL, OpenAIImageProvider, openaiImageProvider;
|
|
5208
|
+
var OPENAI_IMAGE_DEFAULT_MODEL, DEFAULT_MODEL, OpenAIImageProvider, openaiImageProvider;
|
|
5036
5209
|
var init_OpenAIImageProvider = __esm({
|
|
5037
5210
|
"../ai-providers/dist/openai-image/OpenAIImageProvider.js"() {
|
|
5038
5211
|
"use strict";
|
|
5039
|
-
|
|
5212
|
+
init_catalog();
|
|
5213
|
+
OPENAI_IMAGE_DEFAULT_MODEL = defaultModel("openai", "image").id;
|
|
5214
|
+
DEFAULT_MODEL = OPENAI_IMAGE_DEFAULT_MODEL;
|
|
5040
5215
|
OpenAIImageProvider = class {
|
|
5041
5216
|
constructor() {
|
|
5042
5217
|
this.id = "openai-image";
|
|
@@ -5058,7 +5233,7 @@ var init_OpenAIImageProvider = __esm({
|
|
|
5058
5233
|
}
|
|
5059
5234
|
/**
|
|
5060
5235
|
* Generate images from text prompt
|
|
5061
|
-
* Uses GPT Image
|
|
5236
|
+
* Uses GPT Image 2.5 Sunburst by default
|
|
5062
5237
|
*/
|
|
5063
5238
|
async generateImage(prompt3, options = {}) {
|
|
5064
5239
|
if (!this.apiKey) {
|
|
@@ -5068,28 +5243,20 @@ var init_OpenAIImageProvider = __esm({
|
|
|
5068
5243
|
};
|
|
5069
5244
|
}
|
|
5070
5245
|
const model = options.model || DEFAULT_MODEL;
|
|
5071
|
-
const isGPTImage = model === "gpt-image-1.5" || model === "gpt-image-2";
|
|
5072
5246
|
try {
|
|
5073
5247
|
const body = {
|
|
5074
5248
|
model,
|
|
5075
5249
|
prompt: prompt3,
|
|
5076
5250
|
n: options.n || 1
|
|
5077
5251
|
};
|
|
5078
|
-
|
|
5079
|
-
|
|
5080
|
-
|
|
5081
|
-
|
|
5082
|
-
|
|
5083
|
-
|
|
5084
|
-
|
|
5085
|
-
|
|
5086
|
-
body.size = options.size;
|
|
5087
|
-
}
|
|
5088
|
-
} else {
|
|
5089
|
-
body.response_format = "url";
|
|
5090
|
-
body.size = options.size || "1024x1024";
|
|
5091
|
-
body.quality = options.quality === "high" ? "hd" : options.quality || "standard";
|
|
5092
|
-
body.style = options.style || "vivid";
|
|
5252
|
+
const qualityMap = {
|
|
5253
|
+
standard: "medium",
|
|
5254
|
+
hd: "high"
|
|
5255
|
+
};
|
|
5256
|
+
const quality = options.quality || "medium";
|
|
5257
|
+
body.quality = qualityMap[quality] || quality;
|
|
5258
|
+
if (options.size && options.size !== "auto") {
|
|
5259
|
+
body.size = options.size;
|
|
5093
5260
|
}
|
|
5094
5261
|
const response = await fetch(`${this.baseUrl}/images/generations`, {
|
|
5095
5262
|
method: "POST",
|
|
@@ -5242,49 +5409,6 @@ var init_OpenAIImageProvider = __esm({
|
|
|
5242
5409
|
};
|
|
5243
5410
|
}
|
|
5244
5411
|
}
|
|
5245
|
-
/**
|
|
5246
|
-
* Create image variations (uses DALL-E 2)
|
|
5247
|
-
*/
|
|
5248
|
-
async createVariation(imageBuffer, options = {}) {
|
|
5249
|
-
if (!this.apiKey) {
|
|
5250
|
-
return {
|
|
5251
|
-
success: false,
|
|
5252
|
-
error: "OpenAI API key not configured"
|
|
5253
|
-
};
|
|
5254
|
-
}
|
|
5255
|
-
try {
|
|
5256
|
-
const formData = new FormData();
|
|
5257
|
-
const uint8Array = new Uint8Array(imageBuffer);
|
|
5258
|
-
formData.append("image", new Blob([uint8Array], { type: "image/png" }), "image.png");
|
|
5259
|
-
formData.append("model", "dall-e-2");
|
|
5260
|
-
formData.append("n", String(options.n || 1));
|
|
5261
|
-
formData.append("size", options.size || "1024x1024");
|
|
5262
|
-
const response = await fetch(`${this.baseUrl}/images/variations`, {
|
|
5263
|
-
method: "POST",
|
|
5264
|
-
headers: {
|
|
5265
|
-
Authorization: `Bearer ${this.apiKey}`
|
|
5266
|
-
},
|
|
5267
|
-
body: formData
|
|
5268
|
-
});
|
|
5269
|
-
if (!response.ok) {
|
|
5270
|
-
const error = await response.text();
|
|
5271
|
-
return {
|
|
5272
|
-
success: false,
|
|
5273
|
-
error: `API error: ${response.status} - ${error}`
|
|
5274
|
-
};
|
|
5275
|
-
}
|
|
5276
|
-
const data2 = await response.json();
|
|
5277
|
-
return {
|
|
5278
|
-
success: true,
|
|
5279
|
-
images: data2.data.map((img) => ({ url: img.url }))
|
|
5280
|
-
};
|
|
5281
|
-
} catch (error) {
|
|
5282
|
-
return {
|
|
5283
|
-
success: false,
|
|
5284
|
-
error: error instanceof Error ? error.message : "Unknown error"
|
|
5285
|
-
};
|
|
5286
|
-
}
|
|
5287
|
-
}
|
|
5288
5412
|
};
|
|
5289
5413
|
openaiImageProvider = new OpenAIImageProvider();
|
|
5290
5414
|
}
|
|
@@ -5410,7 +5534,8 @@ var DEFAULT_MODEL3, RunwayProvider, runwayProvider;
|
|
|
5410
5534
|
var init_RunwayProvider = __esm({
|
|
5411
5535
|
"../ai-providers/dist/runway/RunwayProvider.js"() {
|
|
5412
5536
|
"use strict";
|
|
5413
|
-
|
|
5537
|
+
init_catalog();
|
|
5538
|
+
DEFAULT_MODEL3 = defaultModel("runway", "video").id;
|
|
5414
5539
|
RunwayProvider = class _RunwayProvider {
|
|
5415
5540
|
constructor() {
|
|
5416
5541
|
this.id = "runway";
|
|
@@ -5463,6 +5588,13 @@ var init_RunwayProvider = __esm({
|
|
|
5463
5588
|
}
|
|
5464
5589
|
const hasImage = !!options?.referenceImage;
|
|
5465
5590
|
const endpoint = hasImage ? "image_to_video" : "text_to_video";
|
|
5591
|
+
if (!hasImage && apiRatio === "960:960") {
|
|
5592
|
+
return {
|
|
5593
|
+
id: "",
|
|
5594
|
+
status: "failed",
|
|
5595
|
+
error: "Runway text-to-video supports 16:9 and 9:16 only. Use 16:9 or 9:16, or pass an image (-i) for square output."
|
|
5596
|
+
};
|
|
5597
|
+
}
|
|
5466
5598
|
const body = {
|
|
5467
5599
|
model,
|
|
5468
5600
|
promptText: prompt3,
|
|
@@ -5563,7 +5695,9 @@ var init_RunwayProvider = __esm({
|
|
|
5563
5695
|
SUCCEEDED: "completed",
|
|
5564
5696
|
FAILED: "failed",
|
|
5565
5697
|
CANCELLED: "cancelled",
|
|
5566
|
-
THROTTLED
|
|
5698
|
+
// THROTTLED means queued behind the account's concurrency limit; the
|
|
5699
|
+
// task starts on its own, so keep polling.
|
|
5700
|
+
THROTTLED: "pending"
|
|
5567
5701
|
};
|
|
5568
5702
|
const result = {
|
|
5569
5703
|
id: data2.id,
|
|
@@ -5573,8 +5707,9 @@ var init_RunwayProvider = __esm({
|
|
|
5573
5707
|
if (data2.status === "SUCCEEDED" && data2.output && data2.output.length > 0) {
|
|
5574
5708
|
result.videoUrl = data2.output[0];
|
|
5575
5709
|
}
|
|
5576
|
-
if (data2.status === "FAILED"
|
|
5577
|
-
|
|
5710
|
+
if (data2.status === "FAILED") {
|
|
5711
|
+
const reason = data2.failure || "Generation failed";
|
|
5712
|
+
result.error = data2.failureCode ? `${reason} (${data2.failureCode})` : reason;
|
|
5578
5713
|
}
|
|
5579
5714
|
return result;
|
|
5580
5715
|
} catch (error) {
|
|
@@ -5586,27 +5721,14 @@ var init_RunwayProvider = __esm({
|
|
|
5586
5721
|
}
|
|
5587
5722
|
}
|
|
5588
5723
|
/**
|
|
5589
|
-
* Cancel
|
|
5724
|
+
* Cancel a pending or running task. Runway documents cancellation as
|
|
5725
|
+
* `DELETE /v1/tasks/{id}` (there is no `/cancel` route).
|
|
5590
5726
|
*/
|
|
5591
5727
|
async cancelGeneration(id) {
|
|
5592
|
-
|
|
5593
|
-
return false;
|
|
5594
|
-
}
|
|
5595
|
-
try {
|
|
5596
|
-
const response = await fetch(`${this.baseUrl}/tasks/${id}/cancel`, {
|
|
5597
|
-
method: "POST",
|
|
5598
|
-
headers: {
|
|
5599
|
-
Authorization: `Bearer ${this.apiKey}`,
|
|
5600
|
-
"X-Runway-Version": _RunwayProvider.API_VERSION
|
|
5601
|
-
}
|
|
5602
|
-
});
|
|
5603
|
-
return response.ok;
|
|
5604
|
-
} catch {
|
|
5605
|
-
return false;
|
|
5606
|
-
}
|
|
5728
|
+
return this.deleteTask(id);
|
|
5607
5729
|
}
|
|
5608
5730
|
/**
|
|
5609
|
-
*
|
|
5731
|
+
* Cancel a running task, or delete a finished one (`DELETE /v1/tasks/{id}`).
|
|
5610
5732
|
*/
|
|
5611
5733
|
async deleteTask(id) {
|
|
5612
5734
|
if (!this.apiKey) {
|
|
@@ -5715,12 +5837,25 @@ var init_runway = __esm({
|
|
|
5715
5837
|
|
|
5716
5838
|
// ../ai-providers/dist/kling/KlingProvider.js
|
|
5717
5839
|
import { createHmac } from "node:crypto";
|
|
5840
|
+
function resolveKlingModel(alias) {
|
|
5841
|
+
const model = findModel("kling", "video", alias);
|
|
5842
|
+
if (model)
|
|
5843
|
+
return model.id;
|
|
5844
|
+
throw new Error(`Unknown Kling model "${alias}". Valid: ${modelAliases("kling", "video").join(", ")}.`);
|
|
5845
|
+
}
|
|
5846
|
+
function klingDuration(model, seconds) {
|
|
5847
|
+
const requested = typeof seconds === "number" && Number.isFinite(seconds) ? Math.round(seconds) : 5;
|
|
5848
|
+
if (model === "kling-v3")
|
|
5849
|
+
return String(Math.max(3, Math.min(15, requested)));
|
|
5850
|
+
return requested >= 10 ? "10" : "5";
|
|
5851
|
+
}
|
|
5718
5852
|
var DEFAULT_MODEL4, STD_MODE_MODELS, KlingProvider, klingProvider;
|
|
5719
5853
|
var init_KlingProvider = __esm({
|
|
5720
5854
|
"../ai-providers/dist/kling/KlingProvider.js"() {
|
|
5721
5855
|
"use strict";
|
|
5722
|
-
|
|
5723
|
-
|
|
5856
|
+
init_catalog();
|
|
5857
|
+
DEFAULT_MODEL4 = defaultModel("kling", "video").id;
|
|
5858
|
+
STD_MODE_MODELS = ["kling-v2-5-turbo", "kling-v2-6", "kling-v3"];
|
|
5724
5859
|
KlingProvider = class {
|
|
5725
5860
|
constructor() {
|
|
5726
5861
|
this.id = "kling";
|
|
@@ -5735,11 +5870,11 @@ var init_KlingProvider = __esm({
|
|
|
5735
5870
|
async initialize(config4) {
|
|
5736
5871
|
if (config4.apiKey) {
|
|
5737
5872
|
const parts = config4.apiKey.split(":");
|
|
5738
|
-
if (parts.length === 2) {
|
|
5873
|
+
if (parts.length === 2 && parts[0] && parts[1]) {
|
|
5739
5874
|
this.accessKey = parts[0];
|
|
5740
5875
|
this.secretKey = parts[1];
|
|
5741
5876
|
} else {
|
|
5742
|
-
this.
|
|
5877
|
+
this.apiKey = config4.apiKey;
|
|
5743
5878
|
}
|
|
5744
5879
|
}
|
|
5745
5880
|
if (config4.baseUrl) {
|
|
@@ -5747,7 +5882,11 @@ var init_KlingProvider = __esm({
|
|
|
5747
5882
|
}
|
|
5748
5883
|
}
|
|
5749
5884
|
isConfigured() {
|
|
5750
|
-
return !!(this.accessKey && this.secretKey);
|
|
5885
|
+
return !!(this.apiKey || this.accessKey && this.secretKey);
|
|
5886
|
+
}
|
|
5887
|
+
/** Bearer value: the API key itself, or a JWT signed from the legacy pair. */
|
|
5888
|
+
bearerToken() {
|
|
5889
|
+
return this.apiKey ?? this.generateToken();
|
|
5751
5890
|
}
|
|
5752
5891
|
/**
|
|
5753
5892
|
* Generate JWT token for Kling API authentication
|
|
@@ -5777,11 +5916,11 @@ var init_KlingProvider = __esm({
|
|
|
5777
5916
|
return {
|
|
5778
5917
|
id: "",
|
|
5779
5918
|
status: "failed",
|
|
5780
|
-
error: "Kling API credentials not configured.
|
|
5919
|
+
error: "Kling API credentials not configured. Set KLING_API_KEY to your Kling API key (or the legacy ACCESS_KEY:SECRET_KEY pair)."
|
|
5781
5920
|
};
|
|
5782
5921
|
}
|
|
5783
5922
|
try {
|
|
5784
|
-
const token = this.
|
|
5923
|
+
const token = this.bearerToken();
|
|
5785
5924
|
const model = options?.model || DEFAULT_MODEL4;
|
|
5786
5925
|
let mode = options?.mode || "std";
|
|
5787
5926
|
if (!STD_MODE_MODELS.includes(model) && mode === "std") {
|
|
@@ -5799,7 +5938,7 @@ var init_KlingProvider = __esm({
|
|
|
5799
5938
|
model_name: model,
|
|
5800
5939
|
mode,
|
|
5801
5940
|
aspect_ratio: aspectRatioMap[options?.aspectRatio || "16:9"] || "16:9",
|
|
5802
|
-
duration: options?.duration
|
|
5941
|
+
duration: klingDuration(model, options?.duration)
|
|
5803
5942
|
};
|
|
5804
5943
|
if (options?.negativePrompt) {
|
|
5805
5944
|
body.negative_prompt = options.negativePrompt;
|
|
@@ -5911,7 +6050,7 @@ var init_KlingProvider = __esm({
|
|
|
5911
6050
|
};
|
|
5912
6051
|
}
|
|
5913
6052
|
try {
|
|
5914
|
-
const token = this.
|
|
6053
|
+
const token = this.bearerToken();
|
|
5915
6054
|
const response = await fetch(`${this.baseUrl}/videos/${type}/${id}`, {
|
|
5916
6055
|
headers: {
|
|
5917
6056
|
"Content-Type": "application/json",
|
|
@@ -5993,11 +6132,11 @@ var init_KlingProvider = __esm({
|
|
|
5993
6132
|
return {
|
|
5994
6133
|
id: "",
|
|
5995
6134
|
status: "failed",
|
|
5996
|
-
error: "Kling API credentials not configured.
|
|
6135
|
+
error: "Kling API credentials not configured. Set KLING_API_KEY to your Kling API key (or the legacy ACCESS_KEY:SECRET_KEY pair)."
|
|
5997
6136
|
};
|
|
5998
6137
|
}
|
|
5999
6138
|
try {
|
|
6000
|
-
const token = this.
|
|
6139
|
+
const token = this.bearerToken();
|
|
6001
6140
|
const body = {
|
|
6002
6141
|
video_id: videoId,
|
|
6003
6142
|
duration: options?.duration || "5"
|
|
@@ -6037,7 +6176,7 @@ var init_KlingProvider = __esm({
|
|
|
6037
6176
|
};
|
|
6038
6177
|
}
|
|
6039
6178
|
try {
|
|
6040
|
-
const token = this.
|
|
6179
|
+
const token = this.bearerToken();
|
|
6041
6180
|
const response = await fetch(`${this.baseUrl}/videos/video-extend/${id}`, {
|
|
6042
6181
|
headers: {
|
|
6043
6182
|
"Content-Type": "application/json",
|
|
@@ -6153,11 +6292,24 @@ var init_kling = __esm({
|
|
|
6153
6292
|
});
|
|
6154
6293
|
|
|
6155
6294
|
// ../ai-providers/dist/grok/GrokProvider.js
|
|
6156
|
-
|
|
6295
|
+
function resolveGrokVideoModel(alias) {
|
|
6296
|
+
const model = findModel("grok", "video", alias);
|
|
6297
|
+
if (model)
|
|
6298
|
+
return model.id;
|
|
6299
|
+
throw new Error(`Unknown Grok video model "${alias}". Valid: ${modelAliases("grok", "video").join(", ")}.`);
|
|
6300
|
+
}
|
|
6301
|
+
function resolveGrokImageModel(alias) {
|
|
6302
|
+
const model = (findModel("grok", "image", alias) ?? defaultModel("grok", "image")).id;
|
|
6303
|
+
return model === "grok-imagine-image-2.0" ? { model, quality: "medium" } : { model };
|
|
6304
|
+
}
|
|
6305
|
+
var DEFAULT_MODEL5, DEFAULT_VIDEO_RESOLUTION, GROK_VIDEO_RESOLUTIONS, GrokProvider, grokProvider;
|
|
6157
6306
|
var init_GrokProvider = __esm({
|
|
6158
6307
|
"../ai-providers/dist/grok/GrokProvider.js"() {
|
|
6159
6308
|
"use strict";
|
|
6160
|
-
|
|
6309
|
+
init_catalog();
|
|
6310
|
+
DEFAULT_MODEL5 = defaultModel("grok", "video").id;
|
|
6311
|
+
DEFAULT_VIDEO_RESOLUTION = "720p";
|
|
6312
|
+
GROK_VIDEO_RESOLUTIONS = ["480p", "720p", "1080p"];
|
|
6161
6313
|
GrokProvider = class {
|
|
6162
6314
|
constructor() {
|
|
6163
6315
|
this.id = "grok";
|
|
@@ -6191,6 +6343,7 @@ var init_GrokProvider = __esm({
|
|
|
6191
6343
|
try {
|
|
6192
6344
|
const body = {
|
|
6193
6345
|
model: options.model || "grok-imagine-image",
|
|
6346
|
+
...options.quality ? { quality: options.quality } : {},
|
|
6194
6347
|
prompt: prompt3,
|
|
6195
6348
|
n: options.n || 1,
|
|
6196
6349
|
response_format: options.responseFormat || "url"
|
|
@@ -6258,6 +6411,7 @@ var init_GrokProvider = __esm({
|
|
|
6258
6411
|
const dataUri = `data:image/png;base64,${base64}`;
|
|
6259
6412
|
const body = {
|
|
6260
6413
|
model: options.model || "grok-imagine-image",
|
|
6414
|
+
...options.quality ? { quality: options.quality } : {},
|
|
6261
6415
|
prompt: prompt3,
|
|
6262
6416
|
image: {
|
|
6263
6417
|
url: dataUri,
|
|
@@ -6324,11 +6478,15 @@ var init_GrokProvider = __esm({
|
|
|
6324
6478
|
try {
|
|
6325
6479
|
const duration = Math.round(Math.min(15, Math.max(1, options?.duration || 5)));
|
|
6326
6480
|
const body = {
|
|
6327
|
-
model: DEFAULT_MODEL5,
|
|
6481
|
+
model: options?.model || DEFAULT_MODEL5,
|
|
6328
6482
|
prompt: prompt3,
|
|
6329
6483
|
duration,
|
|
6330
|
-
aspect_ratio: options?.aspectRatio || "16:9"
|
|
6484
|
+
aspect_ratio: options?.aspectRatio || "16:9",
|
|
6485
|
+
resolution: GROK_VIDEO_RESOLUTIONS.includes(options?.resolution ?? "") ? options.resolution : DEFAULT_VIDEO_RESOLUTION
|
|
6331
6486
|
};
|
|
6487
|
+
if (typeof options?.generateAudio === "boolean") {
|
|
6488
|
+
body.generate_audio = options.generateAudio;
|
|
6489
|
+
}
|
|
6332
6490
|
if (options?.referenceImage) {
|
|
6333
6491
|
body.image = { url: options.referenceImage };
|
|
6334
6492
|
}
|
|
@@ -6390,13 +6548,14 @@ var init_GrokProvider = __esm({
|
|
|
6390
6548
|
const statusMap = {
|
|
6391
6549
|
pending: "pending",
|
|
6392
6550
|
done: "completed",
|
|
6393
|
-
expired: "failed"
|
|
6551
|
+
expired: "failed",
|
|
6552
|
+
failed: "failed"
|
|
6394
6553
|
};
|
|
6395
6554
|
return {
|
|
6396
6555
|
id,
|
|
6397
6556
|
status: statusMap[data2.status] || "pending",
|
|
6398
6557
|
videoUrl: data2.video?.url,
|
|
6399
|
-
error: data2.status === "expired" ? "Generation expired" : void 0
|
|
6558
|
+
error: data2.status === "expired" ? "Generation expired" : data2.status === "failed" ? `Generation failed: ${data2.error?.message ?? data2.error?.code ?? "unknown error"}` : void 0
|
|
6400
6559
|
};
|
|
6401
6560
|
} catch (error) {
|
|
6402
6561
|
return {
|
|
@@ -10590,14 +10749,21 @@ var require_src = __commonJS({
|
|
|
10590
10749
|
});
|
|
10591
10750
|
|
|
10592
10751
|
// ../ai-providers/dist/fal/FalProvider.js
|
|
10752
|
+
function resolveSeedanceVariant(alias) {
|
|
10753
|
+
const model = findModel("seedance", "video", alias);
|
|
10754
|
+
if (model)
|
|
10755
|
+
return model.id;
|
|
10756
|
+
throw new Error(`Unknown Seedance model "${alias}". Valid: ${modelAliases("seedance", "video").join(", ")}.`);
|
|
10757
|
+
}
|
|
10593
10758
|
function estimateSeedanceVideoCostUsd(opts) {
|
|
10594
10759
|
const shortSide = SEEDANCE_SHORT_SIDE[opts.resolution ?? "720p"] ?? 720;
|
|
10595
10760
|
const [a4, b4] = (opts.aspectRatio ?? "16:9").split(":").map(Number);
|
|
10596
10761
|
const ratioFactor = a4 > 0 && b4 > 0 ? Math.max(a4, b4) / Math.min(a4, b4) : 16 / 9;
|
|
10597
10762
|
const longSide = Math.round(shortSide * ratioFactor);
|
|
10598
10763
|
const tokensPerSecond = shortSide * longSide * 24 / 1024;
|
|
10599
|
-
|
|
10600
|
-
|
|
10764
|
+
const rate = opts.v25 ? shortSide >= 1080 ? SEEDANCE_25_1080P_USD_PER_1K_TOKENS : SEEDANCE_25_USD_PER_1K_TOKENS : SEEDANCE_USD_PER_1K_TOKENS;
|
|
10765
|
+
let usdPerSecond = tokensPerSecond / 1e3 * rate;
|
|
10766
|
+
if (opts.fast && !opts.v25 && shortSide <= 720)
|
|
10601
10767
|
usdPerSecond *= SEEDANCE_FAST_FACTOR;
|
|
10602
10768
|
if (opts.hasVideoReference)
|
|
10603
10769
|
usdPerSecond *= SEEDANCE_VIDEO_REF_FACTOR;
|
|
@@ -10705,34 +10871,43 @@ function normaliseResolution(value) {
|
|
|
10705
10871
|
return "1080p";
|
|
10706
10872
|
return "720p";
|
|
10707
10873
|
}
|
|
10708
|
-
function normaliseDuration(value) {
|
|
10709
|
-
if (typeof value !== "number")
|
|
10874
|
+
function normaliseDuration(value, maxSec) {
|
|
10875
|
+
if (typeof value !== "number" || !Number.isFinite(value))
|
|
10710
10876
|
return "auto";
|
|
10711
|
-
|
|
10712
|
-
return "auto";
|
|
10713
|
-
return Math.max(4, Math.min(15, Math.round(value)));
|
|
10877
|
+
return String(Math.max(4, Math.min(maxSec, Math.round(value))));
|
|
10714
10878
|
}
|
|
10715
|
-
var import_client, ENDPOINT_TEXT_TO_VIDEO, ENDPOINT_IMAGE_TO_VIDEO, ENDPOINT_REFERENCE_TO_VIDEO, DEFAULT_VARIANT, VALID_RESOLUTIONS, VALID_ASPECTS, SEEDANCE_USD_PER_1K_TOKENS, SEEDANCE_FAST_FACTOR, SEEDANCE_VIDEO_REF_FACTOR, SEEDANCE_SHORT_SIDE, FalProvider, falProvider;
|
|
10879
|
+
var import_client, ENDPOINT_TEXT_TO_VIDEO, ENDPOINT_IMAGE_TO_VIDEO, ENDPOINT_REFERENCE_TO_VIDEO, DEFAULT_VARIANT, MAX_DURATION_SEC, VALID_RESOLUTIONS, VALID_ASPECTS, SEEDANCE_USD_PER_1K_TOKENS, SEEDANCE_25_USD_PER_1K_TOKENS, SEEDANCE_25_1080P_USD_PER_1K_TOKENS, SEEDANCE_FAST_FACTOR, SEEDANCE_VIDEO_REF_FACTOR, SEEDANCE_SHORT_SIDE, FalProvider, falProvider;
|
|
10716
10880
|
var init_FalProvider = __esm({
|
|
10717
10881
|
"../ai-providers/dist/fal/FalProvider.js"() {
|
|
10718
10882
|
"use strict";
|
|
10719
10883
|
import_client = __toESM(require_src(), 1);
|
|
10884
|
+
init_catalog();
|
|
10720
10885
|
ENDPOINT_TEXT_TO_VIDEO = {
|
|
10721
10886
|
"seedance-2.0": "bytedance/seedance-2.0/text-to-video",
|
|
10722
|
-
"seedance-2.0-fast": "bytedance/seedance-2.0/fast/text-to-video"
|
|
10887
|
+
"seedance-2.0-fast": "bytedance/seedance-2.0/fast/text-to-video",
|
|
10888
|
+
"seedance-2.5": "bytedance/seedance-2.5/text-to-video"
|
|
10723
10889
|
};
|
|
10724
10890
|
ENDPOINT_IMAGE_TO_VIDEO = {
|
|
10725
10891
|
"seedance-2.0": "bytedance/seedance-2.0/image-to-video",
|
|
10726
|
-
"seedance-2.0-fast": "bytedance/seedance-2.0/fast/image-to-video"
|
|
10892
|
+
"seedance-2.0-fast": "bytedance/seedance-2.0/fast/image-to-video",
|
|
10893
|
+
"seedance-2.5": "bytedance/seedance-2.5/image-to-video"
|
|
10727
10894
|
};
|
|
10728
10895
|
ENDPOINT_REFERENCE_TO_VIDEO = {
|
|
10729
10896
|
"seedance-2.0": "bytedance/seedance-2.0/reference-to-video",
|
|
10730
|
-
"seedance-2.0-fast": "bytedance/seedance-2.0/fast/reference-to-video"
|
|
10897
|
+
"seedance-2.0-fast": "bytedance/seedance-2.0/fast/reference-to-video",
|
|
10898
|
+
"seedance-2.5": "bytedance/seedance-2.5/reference-to-video"
|
|
10731
10899
|
};
|
|
10732
10900
|
DEFAULT_VARIANT = "seedance-2.0";
|
|
10901
|
+
MAX_DURATION_SEC = {
|
|
10902
|
+
"seedance-2.0": 15,
|
|
10903
|
+
"seedance-2.0-fast": 15,
|
|
10904
|
+
"seedance-2.5": 30
|
|
10905
|
+
};
|
|
10733
10906
|
VALID_RESOLUTIONS = ["480p", "720p", "1080p"];
|
|
10734
10907
|
VALID_ASPECTS = ["21:9", "16:9", "4:3", "1:1", "3:4", "9:16", "auto"];
|
|
10735
10908
|
SEEDANCE_USD_PER_1K_TOKENS = 0.014;
|
|
10909
|
+
SEEDANCE_25_USD_PER_1K_TOKENS = 0.0214;
|
|
10910
|
+
SEEDANCE_25_1080P_USD_PER_1K_TOKENS = 0.0234;
|
|
10736
10911
|
SEEDANCE_FAST_FACTOR = 0.8;
|
|
10737
10912
|
SEEDANCE_VIDEO_REF_FACTOR = 0.6;
|
|
10738
10913
|
SEEDANCE_SHORT_SIDE = { "480p": 480, "720p": 720, "1080p": 1080 };
|
|
@@ -10787,7 +10962,7 @@ var init_FalProvider = __esm({
|
|
|
10787
10962
|
const endpointId = hasReferences ? ENDPOINT_REFERENCE_TO_VIDEO[variant] : isImageToVideo ? ENDPOINT_IMAGE_TO_VIDEO[variant] : ENDPOINT_TEXT_TO_VIDEO[variant];
|
|
10788
10963
|
const aspect = normaliseAspect(options?.aspectRatio);
|
|
10789
10964
|
const resolution = normaliseResolution(options?.resolution);
|
|
10790
|
-
const duration = normaliseDuration(options?.duration);
|
|
10965
|
+
const duration = normaliseDuration(options?.duration, MAX_DURATION_SEC[variant]);
|
|
10791
10966
|
const input3 = {
|
|
10792
10967
|
prompt: prompt3,
|
|
10793
10968
|
aspect_ratio: aspect,
|
|
@@ -10805,10 +10980,12 @@ var init_FalProvider = __esm({
|
|
|
10805
10980
|
} else if (referenceImage) {
|
|
10806
10981
|
input3.image_url = referenceImage;
|
|
10807
10982
|
}
|
|
10808
|
-
if (
|
|
10809
|
-
|
|
10810
|
-
|
|
10811
|
-
|
|
10983
|
+
if (variant !== "seedance-2.5") {
|
|
10984
|
+
if (options?.negativePrompt)
|
|
10985
|
+
input3.negative_prompt = options.negativePrompt;
|
|
10986
|
+
if (typeof options?.seed === "number")
|
|
10987
|
+
input3.seed = options.seed;
|
|
10988
|
+
}
|
|
10812
10989
|
if (typeof options?.generateAudio === "boolean")
|
|
10813
10990
|
input3.generate_audio = options.generateAudio;
|
|
10814
10991
|
if (options?.endUserId)
|
|
@@ -11535,6 +11712,7 @@ var init_replicate = __esm({
|
|
|
11535
11712
|
var dist_exports = {};
|
|
11536
11713
|
__export(dist_exports, {
|
|
11537
11714
|
ClaudeProvider: () => ClaudeProvider,
|
|
11715
|
+
ELEVENLABS_MUSIC_MODEL: () => ELEVENLABS_MUSIC_MODEL,
|
|
11538
11716
|
ElevenLabsProvider: () => ElevenLabsProvider,
|
|
11539
11717
|
FalProvider: () => FalProvider,
|
|
11540
11718
|
GEMINI_AGENT_DEFAULT_TEXT_MODEL: () => GEMINI_AGENT_DEFAULT_TEXT_MODEL,
|
|
@@ -11548,6 +11726,8 @@ __export(dist_exports, {
|
|
|
11548
11726
|
KOKORO_MODEL_ID: () => KOKORO_MODEL_ID,
|
|
11549
11727
|
KlingProvider: () => KlingProvider,
|
|
11550
11728
|
KokoroProvider: () => KokoroProvider,
|
|
11729
|
+
MODEL_CATALOG: () => MODEL_CATALOG,
|
|
11730
|
+
OPENAI_IMAGE_DEFAULT_MODEL: () => OPENAI_IMAGE_DEFAULT_MODEL,
|
|
11551
11731
|
OPENAI_TTS_VOICES: () => OPENAI_TTS_VOICES,
|
|
11552
11732
|
OllamaProvider: () => OllamaProvider,
|
|
11553
11733
|
OmniProvider: () => OmniProvider,
|
|
@@ -11556,13 +11736,16 @@ __export(dist_exports, {
|
|
|
11556
11736
|
OpenAiTtsProvider: () => OpenAiTtsProvider,
|
|
11557
11737
|
ReplicateProvider: () => ReplicateProvider,
|
|
11558
11738
|
RunwayProvider: () => RunwayProvider,
|
|
11739
|
+
VEO_MODEL_ALIASES: () => VEO_MODEL_ALIASES,
|
|
11559
11740
|
WhisperProvider: () => WhisperProvider,
|
|
11560
11741
|
claudeProvider: () => claudeProvider,
|
|
11742
|
+
defaultModel: () => defaultModel,
|
|
11561
11743
|
defineApiKey: () => defineApiKey,
|
|
11562
11744
|
defineProvider: () => defineProvider,
|
|
11563
11745
|
elevenLabsProvider: () => elevenLabsProvider,
|
|
11564
11746
|
estimateSeedanceVideoCostUsd: () => estimateSeedanceVideoCostUsd,
|
|
11565
11747
|
falProvider: () => falProvider,
|
|
11748
|
+
findModel: () => findModel,
|
|
11566
11749
|
geminiProvider: () => geminiProvider,
|
|
11567
11750
|
getAllApiKeys: () => getAllApiKeys,
|
|
11568
11751
|
getAllProviders: () => getAllProviders,
|
|
@@ -11576,10 +11759,13 @@ __export(dist_exports, {
|
|
|
11576
11759
|
getSetupProviders: () => getSetupProviders,
|
|
11577
11760
|
grokProvider: () => grokProvider,
|
|
11578
11761
|
isGeminiTextModelAlias: () => isGeminiTextModelAlias,
|
|
11762
|
+
klingDuration: () => klingDuration,
|
|
11579
11763
|
klingProvider: () => klingProvider,
|
|
11580
11764
|
kokoroProvider: () => kokoroProvider,
|
|
11765
|
+
listModels: () => listModels,
|
|
11581
11766
|
loadBundledKokoroRuntime: () => loadBundledKokoroRuntime,
|
|
11582
11767
|
loadKokoroFromWorkspace: () => loadKokoroFromWorkspace,
|
|
11768
|
+
modelAliases: () => modelAliases,
|
|
11583
11769
|
ollamaProvider: () => ollamaProvider,
|
|
11584
11770
|
omniProvider: () => omniProvider,
|
|
11585
11771
|
openaiImageProvider: () => openaiImageProvider,
|
|
@@ -11588,6 +11774,11 @@ __export(dist_exports, {
|
|
|
11588
11774
|
providerRegistry: () => providerRegistry,
|
|
11589
11775
|
replicateProvider: () => replicateProvider,
|
|
11590
11776
|
resolveGeminiTextModel: () => resolveGeminiTextModel,
|
|
11777
|
+
resolveGrokImageModel: () => resolveGrokImageModel,
|
|
11778
|
+
resolveGrokVideoModel: () => resolveGrokVideoModel,
|
|
11779
|
+
resolveKlingModel: () => resolveKlingModel,
|
|
11780
|
+
resolveSeedanceVariant: () => resolveSeedanceVariant,
|
|
11781
|
+
resolveVeoModel: () => resolveVeoModel,
|
|
11591
11782
|
resolveVoiceId: () => resolveVoiceId,
|
|
11592
11783
|
runwayProvider: () => runwayProvider,
|
|
11593
11784
|
whisperProvider: () => whisperProvider
|
|
@@ -11601,6 +11792,7 @@ var init_dist = __esm({
|
|
|
11601
11792
|
init_define_provider();
|
|
11602
11793
|
init_whisper();
|
|
11603
11794
|
init_gemini();
|
|
11795
|
+
init_catalog2();
|
|
11604
11796
|
init_openai();
|
|
11605
11797
|
init_claude();
|
|
11606
11798
|
init_ollama();
|
|
@@ -19843,12 +20035,15 @@ var init_ai_helpers = __esm({
|
|
|
19843
20035
|
});
|
|
19844
20036
|
|
|
19845
20037
|
// ../cli/src/commands/_shared/video-utils.ts
|
|
19846
|
-
async function uploadToImgbb(imageBuffer, apiKey) {
|
|
20038
|
+
async function uploadToImgbb(imageBuffer, apiKey, expirationSeconds) {
|
|
19847
20039
|
try {
|
|
19848
20040
|
const base64Image = imageBuffer.toString("base64");
|
|
19849
20041
|
const formData = new URLSearchParams();
|
|
19850
20042
|
formData.append("key", apiKey);
|
|
19851
20043
|
formData.append("image", base64Image);
|
|
20044
|
+
if (expirationSeconds !== void 0) {
|
|
20045
|
+
formData.append("expiration", String(expirationSeconds));
|
|
20046
|
+
}
|
|
19852
20047
|
const response = await fetch("https://api.imgbb.com/1/upload", {
|
|
19853
20048
|
method: "POST",
|
|
19854
20049
|
body: formData
|
|
@@ -19911,7 +20106,10 @@ function awsEncode(value) {
|
|
|
19911
20106
|
(c2) => `%${c2.charCodeAt(0).toString(16).toUpperCase()}`
|
|
19912
20107
|
);
|
|
19913
20108
|
}
|
|
19914
|
-
function
|
|
20109
|
+
function clamp(value, min, max) {
|
|
20110
|
+
return Math.min(max, Math.max(min, Math.round(value)));
|
|
20111
|
+
}
|
|
20112
|
+
function presignS3Url(params) {
|
|
19915
20113
|
const now = /* @__PURE__ */ new Date();
|
|
19916
20114
|
const amzDate = now.toISOString().replace(/[:-]|\.\d{3}/g, "");
|
|
19917
20115
|
const dateStamp = amzDate.slice(0, 8);
|
|
@@ -19922,7 +20120,7 @@ function presignS3PutUrl(params) {
|
|
|
19922
20120
|
"X-Amz-Algorithm": "AWS4-HMAC-SHA256",
|
|
19923
20121
|
"X-Amz-Credential": `${params.accessKeyId}/${credentialScope}`,
|
|
19924
20122
|
"X-Amz-Date": amzDate,
|
|
19925
|
-
"X-Amz-Expires": String(params.ttlSeconds),
|
|
20123
|
+
"X-Amz-Expires": String(clamp(params.ttlSeconds, 1, S3_MAX_PRESIGN_SECONDS)),
|
|
19926
20124
|
"X-Amz-SignedHeaders": "host"
|
|
19927
20125
|
};
|
|
19928
20126
|
if (params.sessionToken) {
|
|
@@ -19930,7 +20128,7 @@ function presignS3PutUrl(params) {
|
|
|
19930
20128
|
}
|
|
19931
20129
|
const canonicalQuery = Object.entries(query2).sort(([a4], [b4]) => a4.localeCompare(b4)).map(([key2, value]) => `${awsEncode(key2)}=${awsEncode(value)}`).join("&");
|
|
19932
20130
|
const canonicalRequest = [
|
|
19933
|
-
|
|
20131
|
+
params.method,
|
|
19934
20132
|
canonicalUri,
|
|
19935
20133
|
canonicalQuery,
|
|
19936
20134
|
`host:${host}`,
|
|
@@ -19989,7 +20187,8 @@ async function resolveUploadHost() {
|
|
|
19989
20187
|
const ext = extensionFor(opts);
|
|
19990
20188
|
const prefix = safePrefix(settings.s3.prefix);
|
|
19991
20189
|
const key2 = `${prefix}/${Date.now()}-${randomUUID()}.${ext}`;
|
|
19992
|
-
const presignedUrl =
|
|
20190
|
+
const presignedUrl = presignS3Url({
|
|
20191
|
+
method: "PUT",
|
|
19993
20192
|
accessKeyId,
|
|
19994
20193
|
secretAccessKey,
|
|
19995
20194
|
sessionToken,
|
|
@@ -20008,10 +20207,26 @@ async function resolveUploadHost() {
|
|
|
20008
20207
|
if (!response.ok) {
|
|
20009
20208
|
throw new Error(`S3 upload failed (${response.status}): ${response.statusText}`);
|
|
20010
20209
|
}
|
|
20210
|
+
if (settings.s3.publicBaseUrl) {
|
|
20211
|
+
return {
|
|
20212
|
+
provider: "s3",
|
|
20213
|
+
url: publicS3Url({ region, bucket, key: key2, publicBaseUrl: settings.s3.publicBaseUrl })
|
|
20214
|
+
};
|
|
20215
|
+
}
|
|
20216
|
+
const ttlSeconds = clamp(settings.ttlSeconds, 1, S3_MAX_PRESIGN_SECONDS);
|
|
20011
20217
|
return {
|
|
20012
20218
|
provider: "s3",
|
|
20013
|
-
url:
|
|
20014
|
-
|
|
20219
|
+
url: presignS3Url({
|
|
20220
|
+
method: "GET",
|
|
20221
|
+
accessKeyId,
|
|
20222
|
+
secretAccessKey,
|
|
20223
|
+
sessionToken,
|
|
20224
|
+
region,
|
|
20225
|
+
bucket,
|
|
20226
|
+
key: key2,
|
|
20227
|
+
ttlSeconds
|
|
20228
|
+
}),
|
|
20229
|
+
expiresAt: new Date(Date.now() + ttlSeconds * 1e3).toISOString()
|
|
20015
20230
|
};
|
|
20016
20231
|
}
|
|
20017
20232
|
};
|
|
@@ -20023,19 +20238,28 @@ async function resolveUploadHost() {
|
|
|
20023
20238
|
if (!imgbbKey) {
|
|
20024
20239
|
throw new Error("IMGBB_API_KEY required for image-to-video uploads.");
|
|
20025
20240
|
}
|
|
20026
|
-
const
|
|
20241
|
+
const expiration = clamp(settings.ttlSeconds, IMGBB_MIN_EXPIRATION_SECONDS, IMGBB_MAX_EXPIRATION_SECONDS);
|
|
20242
|
+
const result = await uploadToImgbb(imageBuffer, imgbbKey, expiration);
|
|
20027
20243
|
if (!result.success || !result.url) {
|
|
20028
20244
|
throw new Error(`ImgBB upload failed: ${result.error ?? "unknown error"}`);
|
|
20029
20245
|
}
|
|
20030
|
-
return {
|
|
20246
|
+
return {
|
|
20247
|
+
provider: "imgbb",
|
|
20248
|
+
url: result.url,
|
|
20249
|
+
expiresAt: new Date(Date.now() + expiration * 1e3).toISOString()
|
|
20250
|
+
};
|
|
20031
20251
|
}
|
|
20032
20252
|
};
|
|
20033
20253
|
}
|
|
20254
|
+
var S3_MAX_PRESIGN_SECONDS, IMGBB_MIN_EXPIRATION_SECONDS, IMGBB_MAX_EXPIRATION_SECONDS;
|
|
20034
20255
|
var init_upload_host = __esm({
|
|
20035
20256
|
"../cli/src/utils/upload-host.ts"() {
|
|
20036
20257
|
"use strict";
|
|
20037
20258
|
init_config();
|
|
20038
20259
|
init_video_utils();
|
|
20260
|
+
S3_MAX_PRESIGN_SECONDS = 7 * 24 * 60 * 60;
|
|
20261
|
+
IMGBB_MIN_EXPIRATION_SECONDS = 60;
|
|
20262
|
+
IMGBB_MAX_EXPIRATION_SECONDS = 15552e3;
|
|
20039
20263
|
}
|
|
20040
20264
|
});
|
|
20041
20265
|
|
|
@@ -20653,8 +20877,14 @@ __export(ai_video_exports, {
|
|
|
20653
20877
|
executeVideoGenerate: () => executeVideoGenerate,
|
|
20654
20878
|
executeVideoStatus: () => executeVideoStatus
|
|
20655
20879
|
});
|
|
20656
|
-
import { readFile as readFile3, writeFile as writeFile3 } from "node:fs/promises";
|
|
20657
|
-
import { resolve as resolve3 } from "node:path";
|
|
20880
|
+
import { mkdir as mkdir2, readFile as readFile3, writeFile as writeFile3 } from "node:fs/promises";
|
|
20881
|
+
import { dirname as dirname2, resolve as resolve3 } from "node:path";
|
|
20882
|
+
async function saveOutput(output3, buffer) {
|
|
20883
|
+
const outputPath = resolve3(process.cwd(), output3);
|
|
20884
|
+
await mkdir2(dirname2(outputPath), { recursive: true });
|
|
20885
|
+
await writeFile3(outputPath, buffer);
|
|
20886
|
+
return outputPath;
|
|
20887
|
+
}
|
|
20658
20888
|
async function executeVideoGenerate(options) {
|
|
20659
20889
|
const {
|
|
20660
20890
|
prompt: prompt3,
|
|
@@ -20670,7 +20900,10 @@ async function executeVideoGenerate(options) {
|
|
|
20670
20900
|
negative,
|
|
20671
20901
|
resolution,
|
|
20672
20902
|
veoModel = "3.1-fast",
|
|
20903
|
+
runwayModel,
|
|
20673
20904
|
seedanceModel = "quality",
|
|
20905
|
+
grokModel,
|
|
20906
|
+
klingModel,
|
|
20674
20907
|
generateAudio,
|
|
20675
20908
|
output: output3,
|
|
20676
20909
|
wait = true,
|
|
@@ -20725,7 +20958,7 @@ async function executeVideoGenerate(options) {
|
|
|
20725
20958
|
});
|
|
20726
20959
|
falImage = upload.url;
|
|
20727
20960
|
}
|
|
20728
|
-
const model = seedanceModel
|
|
20961
|
+
const model = resolveSeedanceVariant(seedanceModel);
|
|
20729
20962
|
const result = await fal.generateVideo(prompt3, {
|
|
20730
20963
|
prompt: prompt3,
|
|
20731
20964
|
referenceImage: references.length > 0 ? void 0 : falImage,
|
|
@@ -20742,8 +20975,7 @@ async function executeVideoGenerate(options) {
|
|
|
20742
20975
|
let outputPath;
|
|
20743
20976
|
if (output3 && result.videoUrl) {
|
|
20744
20977
|
const buffer = await downloadVideo(result.videoUrl, key2);
|
|
20745
|
-
outputPath =
|
|
20746
|
-
await writeFile3(outputPath, buffer);
|
|
20978
|
+
outputPath = await saveOutput(output3, buffer);
|
|
20747
20979
|
}
|
|
20748
20980
|
return {
|
|
20749
20981
|
success: true,
|
|
@@ -20758,6 +20990,7 @@ async function executeVideoGenerate(options) {
|
|
|
20758
20990
|
await runway.initialize({ apiKey: key2 });
|
|
20759
20991
|
const result = await runway.generateVideo(prompt3, {
|
|
20760
20992
|
prompt: prompt3,
|
|
20993
|
+
model: runwayModel,
|
|
20761
20994
|
referenceImage,
|
|
20762
20995
|
duration,
|
|
20763
20996
|
aspectRatio: ratio,
|
|
@@ -20774,8 +21007,7 @@ async function executeVideoGenerate(options) {
|
|
|
20774
21007
|
let outputPath;
|
|
20775
21008
|
if (output3 && finalResult.videoUrl) {
|
|
20776
21009
|
const buffer = await downloadVideo(finalResult.videoUrl, key2);
|
|
20777
|
-
outputPath =
|
|
20778
|
-
await writeFile3(outputPath, buffer);
|
|
21010
|
+
outputPath = await saveOutput(output3, buffer);
|
|
20779
21011
|
}
|
|
20780
21012
|
return {
|
|
20781
21013
|
success: true,
|
|
@@ -20801,6 +21033,7 @@ async function executeVideoGenerate(options) {
|
|
|
20801
21033
|
}
|
|
20802
21034
|
const result = await kling.generateVideo(prompt3, {
|
|
20803
21035
|
prompt: prompt3,
|
|
21036
|
+
model: resolveKlingModel(klingModel),
|
|
20804
21037
|
referenceImage: klingImage,
|
|
20805
21038
|
duration,
|
|
20806
21039
|
aspectRatio: ratio,
|
|
@@ -20819,8 +21052,7 @@ async function executeVideoGenerate(options) {
|
|
|
20819
21052
|
let outputPath;
|
|
20820
21053
|
if (output3 && finalResult.videoUrl) {
|
|
20821
21054
|
const buffer = await downloadVideo(finalResult.videoUrl, key2);
|
|
20822
|
-
outputPath =
|
|
20823
|
-
await writeFile3(outputPath, buffer);
|
|
21055
|
+
outputPath = await saveOutput(output3, buffer);
|
|
20824
21056
|
}
|
|
20825
21057
|
return {
|
|
20826
21058
|
success: true,
|
|
@@ -20834,12 +21066,7 @@ async function executeVideoGenerate(options) {
|
|
|
20834
21066
|
} else if (provider === "veo") {
|
|
20835
21067
|
const gemini = new GeminiProvider();
|
|
20836
21068
|
await gemini.initialize({ apiKey: key2 });
|
|
20837
|
-
const
|
|
20838
|
-
"3.0": "veo-3.0-generate-preview",
|
|
20839
|
-
"3.1": "veo-3.1-generate-preview",
|
|
20840
|
-
"3.1-fast": "veo-3.1-fast-generate-preview"
|
|
20841
|
-
};
|
|
20842
|
-
const model = veoModelMap[veoModel] || "veo-3.1-fast-generate-preview";
|
|
21069
|
+
const model = resolveVeoModel(veoModel);
|
|
20843
21070
|
const veoDuration = duration <= 6 ? 6 : 8;
|
|
20844
21071
|
const result = await gemini.generateVideo(prompt3, {
|
|
20845
21072
|
prompt: prompt3,
|
|
@@ -20860,8 +21087,7 @@ async function executeVideoGenerate(options) {
|
|
|
20860
21087
|
let outputPath;
|
|
20861
21088
|
if (output3 && finalResult.videoUrl) {
|
|
20862
21089
|
const buffer = await downloadVideo(finalResult.videoUrl, key2);
|
|
20863
|
-
outputPath =
|
|
20864
|
-
await writeFile3(outputPath, buffer);
|
|
21090
|
+
outputPath = await saveOutput(output3, buffer);
|
|
20865
21091
|
}
|
|
20866
21092
|
return {
|
|
20867
21093
|
success: true,
|
|
@@ -20876,9 +21102,12 @@ async function executeVideoGenerate(options) {
|
|
|
20876
21102
|
await grok.initialize({ apiKey: key2 });
|
|
20877
21103
|
const result = await grok.generateVideo(prompt3, {
|
|
20878
21104
|
prompt: prompt3,
|
|
21105
|
+
model: resolveGrokVideoModel(grokModel),
|
|
20879
21106
|
referenceImage,
|
|
20880
21107
|
duration,
|
|
20881
|
-
aspectRatio: ratio
|
|
21108
|
+
aspectRatio: ratio,
|
|
21109
|
+
resolution,
|
|
21110
|
+
generateAudio
|
|
20882
21111
|
});
|
|
20883
21112
|
if (result.status === "failed")
|
|
20884
21113
|
return { success: false, error: result.error || "Grok generation failed" };
|
|
@@ -20891,8 +21120,7 @@ async function executeVideoGenerate(options) {
|
|
|
20891
21120
|
let outputPath;
|
|
20892
21121
|
if (output3 && finalResult.videoUrl) {
|
|
20893
21122
|
const buffer = await downloadVideo(finalResult.videoUrl, key2);
|
|
20894
|
-
outputPath =
|
|
20895
|
-
await writeFile3(outputPath, buffer);
|
|
21123
|
+
outputPath = await saveOutput(output3, buffer);
|
|
20896
21124
|
}
|
|
20897
21125
|
return {
|
|
20898
21126
|
success: true,
|
|
@@ -20909,7 +21137,8 @@ async function executeVideoGenerate(options) {
|
|
|
20909
21137
|
const result = await omni.generateVideo(prompt3, {
|
|
20910
21138
|
prompt: prompt3,
|
|
20911
21139
|
referenceImage,
|
|
20912
|
-
aspectRatio: ratio
|
|
21140
|
+
aspectRatio: ratio,
|
|
21141
|
+
resolution
|
|
20913
21142
|
});
|
|
20914
21143
|
if (result.status !== "completed" || !result.videoUrl) {
|
|
20915
21144
|
return { success: false, error: result.error || "Gemini Omni generation failed" };
|
|
@@ -20917,8 +21146,7 @@ async function executeVideoGenerate(options) {
|
|
|
20917
21146
|
let outputPath;
|
|
20918
21147
|
if (output3) {
|
|
20919
21148
|
const buffer = await downloadVideo(result.videoUrl, key2);
|
|
20920
|
-
outputPath =
|
|
20921
|
-
await writeFile3(outputPath, buffer);
|
|
21149
|
+
outputPath = await saveOutput(output3, buffer);
|
|
20922
21150
|
}
|
|
20923
21151
|
return {
|
|
20924
21152
|
success: true,
|
|
@@ -21014,8 +21242,7 @@ async function executeVideoStatus(options) {
|
|
|
21014
21242
|
let outputPath;
|
|
21015
21243
|
if (output3 && result.videoUrl) {
|
|
21016
21244
|
const buffer = await downloadVideo(result.videoUrl);
|
|
21017
|
-
outputPath =
|
|
21018
|
-
await writeFile3(outputPath, buffer);
|
|
21245
|
+
outputPath = await saveOutput(output3, buffer);
|
|
21019
21246
|
}
|
|
21020
21247
|
return {
|
|
21021
21248
|
success: true,
|
|
@@ -21037,8 +21264,7 @@ async function executeVideoStatus(options) {
|
|
|
21037
21264
|
let outputPath;
|
|
21038
21265
|
if (output3 && result.videoUrl) {
|
|
21039
21266
|
const buffer = await downloadVideo(result.videoUrl, key2);
|
|
21040
|
-
outputPath =
|
|
21041
|
-
await writeFile3(outputPath, buffer);
|
|
21267
|
+
outputPath = await saveOutput(output3, buffer);
|
|
21042
21268
|
}
|
|
21043
21269
|
return {
|
|
21044
21270
|
success: true,
|
|
@@ -21059,8 +21285,7 @@ async function executeVideoStatus(options) {
|
|
|
21059
21285
|
let outputPath;
|
|
21060
21286
|
if (output3 && result.videoUrl) {
|
|
21061
21287
|
const buffer = await downloadVideo(result.videoUrl, key2);
|
|
21062
|
-
outputPath =
|
|
21063
|
-
await writeFile3(outputPath, buffer);
|
|
21288
|
+
outputPath = await saveOutput(output3, buffer);
|
|
21064
21289
|
}
|
|
21065
21290
|
return {
|
|
21066
21291
|
success: true,
|
|
@@ -21082,8 +21307,7 @@ async function executeVideoStatus(options) {
|
|
|
21082
21307
|
let outputPath;
|
|
21083
21308
|
if (output3 && result.videoUrl) {
|
|
21084
21309
|
const buffer = await downloadVideo(result.videoUrl, key2);
|
|
21085
|
-
outputPath =
|
|
21086
|
-
await writeFile3(outputPath, buffer);
|
|
21310
|
+
outputPath = await saveOutput(output3, buffer);
|
|
21087
21311
|
}
|
|
21088
21312
|
return {
|
|
21089
21313
|
success: true,
|
|
@@ -21153,8 +21377,7 @@ async function executeVideoExtend(options) {
|
|
|
21153
21377
|
let outputPath;
|
|
21154
21378
|
if (output3 && finalResult.videoUrl) {
|
|
21155
21379
|
const buffer = await downloadVideo(finalResult.videoUrl, key2);
|
|
21156
|
-
outputPath =
|
|
21157
|
-
await writeFile3(outputPath, buffer);
|
|
21380
|
+
outputPath = await saveOutput(output3, buffer);
|
|
21158
21381
|
}
|
|
21159
21382
|
return {
|
|
21160
21383
|
success: true,
|
|
@@ -21169,12 +21392,7 @@ async function executeVideoExtend(options) {
|
|
|
21169
21392
|
if (!key2) return { success: false, error: "GOOGLE_API_KEY required" };
|
|
21170
21393
|
const gemini = new GeminiProvider();
|
|
21171
21394
|
await gemini.initialize({ apiKey: key2 });
|
|
21172
|
-
const
|
|
21173
|
-
"3.0": "veo-3.0-generate-preview",
|
|
21174
|
-
"3.1": "veo-3.1-generate-preview",
|
|
21175
|
-
"3.1-fast": "veo-3.1-fast-generate-preview"
|
|
21176
|
-
};
|
|
21177
|
-
const model = veoModelMap[veoModel] || "veo-3.1-generate-preview";
|
|
21395
|
+
const model = resolveVeoModel(veoModel);
|
|
21178
21396
|
const result = await gemini.extendVideo(videoId, prompt3, {
|
|
21179
21397
|
duration,
|
|
21180
21398
|
model
|
|
@@ -21189,8 +21407,7 @@ async function executeVideoExtend(options) {
|
|
|
21189
21407
|
let outputPath;
|
|
21190
21408
|
if (output3 && finalResult.videoUrl) {
|
|
21191
21409
|
const buffer = await downloadVideo(finalResult.videoUrl, key2);
|
|
21192
|
-
outputPath =
|
|
21193
|
-
await writeFile3(outputPath, buffer);
|
|
21410
|
+
outputPath = await saveOutput(output3, buffer);
|
|
21194
21411
|
}
|
|
21195
21412
|
return {
|
|
21196
21413
|
success: true,
|
|
@@ -21252,8 +21469,8 @@ var init_music_status = __esm({
|
|
|
21252
21469
|
|
|
21253
21470
|
// ../cli/src/commands/_shared/build-asset-metadata.ts
|
|
21254
21471
|
import { existsSync, readFileSync } from "node:fs";
|
|
21255
|
-
import { mkdir as
|
|
21256
|
-
import { dirname as
|
|
21472
|
+
import { mkdir as mkdir3, writeFile as writeFile4 } from "node:fs/promises";
|
|
21473
|
+
import { dirname as dirname3, join } from "node:path";
|
|
21257
21474
|
function assetMetadataPath(kind3, beatId) {
|
|
21258
21475
|
return `.vibeframe/assets/${kind3}-${beatId}.json`;
|
|
21259
21476
|
}
|
|
@@ -21301,7 +21518,7 @@ async function writeAssetMetadata(opts) {
|
|
|
21301
21518
|
cachePath: opts.cachePath,
|
|
21302
21519
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
21303
21520
|
};
|
|
21304
|
-
await
|
|
21521
|
+
await mkdir3(dirname3(abs), { recursive: true });
|
|
21305
21522
|
await writeFile4(abs, JSON.stringify(metadata, null, 2) + "\n", "utf-8");
|
|
21306
21523
|
}
|
|
21307
21524
|
var init_build_asset_metadata = __esm({
|
|
@@ -22260,7 +22477,7 @@ var init_storyboard_edit = __esm({
|
|
|
22260
22477
|
|
|
22261
22478
|
// ../cli/src/commands/_shared/storyboard-source.ts
|
|
22262
22479
|
import { existsSync as existsSync2 } from "node:fs";
|
|
22263
|
-
import { mkdir as
|
|
22480
|
+
import { mkdir as mkdir4, readdir, readFile as readFile4, rename, rm, writeFile as writeFile6 } from "node:fs/promises";
|
|
22264
22481
|
import { basename, join as join3 } from "node:path";
|
|
22265
22482
|
function sceneFileFrom(dir, filename) {
|
|
22266
22483
|
const stem = filename.replace(/\.mdx?$/i, "");
|
|
@@ -22373,7 +22590,7 @@ ${(0, import_yaml5.stringify)(data2, { lineWidth: 0 }).trimEnd()}
|
|
|
22373
22590
|
};
|
|
22374
22591
|
}
|
|
22375
22592
|
async function writeMigration(projectDir, plan2) {
|
|
22376
|
-
await
|
|
22593
|
+
await mkdir4(join3(projectDir, SCENES_DIRNAME), { recursive: true });
|
|
22377
22594
|
for (const file of plan2.scenes) {
|
|
22378
22595
|
await writeFile6(join3(projectDir, file.path), file.contents, "utf-8");
|
|
22379
22596
|
}
|
|
@@ -22395,7 +22612,7 @@ function strayBeatIssues(strayBeatIds) {
|
|
|
22395
22612
|
async function upsertScene(projectDir, opts) {
|
|
22396
22613
|
const beatId = deriveBeatId(opts.beatId);
|
|
22397
22614
|
const dir = join3(projectDir, SCENES_DIRNAME);
|
|
22398
|
-
await
|
|
22615
|
+
await mkdir4(dir, { recursive: true });
|
|
22399
22616
|
const cues = {};
|
|
22400
22617
|
if (opts.duration !== void 0) cues.duration = opts.duration;
|
|
22401
22618
|
if (opts.narration?.trim()) cues.narration = opts.narration.trim();
|
|
@@ -22467,22 +22684,22 @@ var init_storyboard_source = __esm({
|
|
|
22467
22684
|
// ../cli/src/commands/_shared/status-jobs.ts
|
|
22468
22685
|
import { createHash as createHash2, randomUUID as randomUUID2 } from "node:crypto";
|
|
22469
22686
|
import { existsSync as existsSync3, statSync } from "node:fs";
|
|
22470
|
-
import { copyFile, mkdir as
|
|
22471
|
-
import { dirname as
|
|
22687
|
+
import { copyFile, mkdir as mkdir5, readFile as readFile5, readdir as readdir2, rename as rename2, stat, writeFile as writeFile7 } from "node:fs/promises";
|
|
22688
|
+
import { dirname as dirname4, join as join4, parse as parse2, relative, resolve as resolve5 } from "node:path";
|
|
22472
22689
|
function isLocalJob(record) {
|
|
22473
22690
|
return record.jobType === "build" || record.jobType === "render";
|
|
22474
22691
|
}
|
|
22475
22692
|
function findProjectRoot(start = process.cwd()) {
|
|
22476
22693
|
let dir = resolve5(start);
|
|
22477
22694
|
try {
|
|
22478
|
-
if (existsSync3(dir) && statSync(dir).isFile()) dir =
|
|
22695
|
+
if (existsSync3(dir) && statSync(dir).isFile()) dir = dirname4(dir);
|
|
22479
22696
|
} catch {
|
|
22480
22697
|
}
|
|
22481
22698
|
for (; ; ) {
|
|
22482
22699
|
if (existsSync3(join4(dir, "vibe.config.json")) || existsSync3(join4(dir, "STORYBOARD.md"))) {
|
|
22483
22700
|
return dir;
|
|
22484
22701
|
}
|
|
22485
|
-
const parent =
|
|
22702
|
+
const parent = dirname4(dir);
|
|
22486
22703
|
if (parent === dir) return resolve5(start);
|
|
22487
22704
|
dir = parent;
|
|
22488
22705
|
}
|
|
@@ -22549,7 +22766,7 @@ async function createAndWriteJobRecord(opts) {
|
|
|
22549
22766
|
}
|
|
22550
22767
|
async function writeJobRecord(record) {
|
|
22551
22768
|
const dir = jobsDir(record.projectDir);
|
|
22552
|
-
await
|
|
22769
|
+
await mkdir5(dir, { recursive: true });
|
|
22553
22770
|
const path16 = jobRecordPath(record.id, record.projectDir);
|
|
22554
22771
|
const tmp = `${path16}.${randomUUID2()}.tmp`;
|
|
22555
22772
|
await writeFile7(tmp, JSON.stringify(stripUndefined2(record), null, 2) + "\n", "utf-8");
|
|
@@ -22597,7 +22814,7 @@ async function refreshJobRecord(record, opts = {}) {
|
|
|
22597
22814
|
try {
|
|
22598
22815
|
if (record.jobType === "generate-video") {
|
|
22599
22816
|
const output3 = resolveRefreshOutput(record, opts);
|
|
22600
|
-
if (output3) await
|
|
22817
|
+
if (output3) await mkdir5(dirname4(output3), { recursive: true });
|
|
22601
22818
|
const result = await executeVideoStatus({
|
|
22602
22819
|
taskId: record.providerTaskId,
|
|
22603
22820
|
provider: record.provider,
|
|
@@ -22880,14 +23097,14 @@ async function downloadUrl(url, outputPath) {
|
|
|
22880
23097
|
const response = await fetch(url);
|
|
22881
23098
|
if (!response.ok) throw new Error(`Download failed: HTTP ${response.status}`);
|
|
22882
23099
|
const buffer = Buffer.from(await response.arrayBuffer());
|
|
22883
|
-
await
|
|
23100
|
+
await mkdir5(dirname4(outputPath), { recursive: true });
|
|
22884
23101
|
await writeFile7(outputPath, buffer);
|
|
22885
23102
|
return outputPath;
|
|
22886
23103
|
}
|
|
22887
23104
|
async function maybeCacheOutput(record) {
|
|
22888
23105
|
if (record.status !== "completed" || !record.outputPath || !record.cachePath) return;
|
|
22889
23106
|
try {
|
|
22890
|
-
await
|
|
23107
|
+
await mkdir5(dirname4(record.cachePath), { recursive: true });
|
|
22891
23108
|
await copyFile(record.outputPath, record.cachePath);
|
|
22892
23109
|
} catch {
|
|
22893
23110
|
}
|
|
@@ -23471,7 +23688,7 @@ var init_project_config = __esm({
|
|
|
23471
23688
|
});
|
|
23472
23689
|
|
|
23473
23690
|
// ../cli/src/commands/_shared/scene-project.ts
|
|
23474
|
-
import { mkdir as
|
|
23691
|
+
import { mkdir as mkdir6, readFile as readFile7, writeFile as writeFile8, access as access3 } from "node:fs/promises";
|
|
23475
23692
|
import { resolve as resolve7, basename as basename2 } from "node:path";
|
|
23476
23693
|
function isSceneKind(value) {
|
|
23477
23694
|
return VALID_SCENE_KINDS.includes(value);
|
|
@@ -24083,11 +24300,11 @@ async function scaffoldSceneProject(opts) {
|
|
|
24083
24300
|
const now = opts.now ?? /* @__PURE__ */ new Date();
|
|
24084
24301
|
const profile = opts.profile ?? "full";
|
|
24085
24302
|
const kind3 = opts.kind ?? DEFAULT_SCENE_KIND;
|
|
24086
|
-
await
|
|
24303
|
+
await mkdir6(dir, { recursive: true });
|
|
24087
24304
|
if (profile === "full") {
|
|
24088
|
-
await
|
|
24089
|
-
await
|
|
24090
|
-
await
|
|
24305
|
+
await mkdir6(resolve7(dir, "compositions"), { recursive: true });
|
|
24306
|
+
await mkdir6(resolve7(dir, "assets"), { recursive: true });
|
|
24307
|
+
await mkdir6(resolve7(dir, "renders"), { recursive: true });
|
|
24091
24308
|
}
|
|
24092
24309
|
const created = [];
|
|
24093
24310
|
const skipped2 = [];
|
|
@@ -87788,7 +88005,7 @@ var require_yauzl = __commonJS({
|
|
|
87788
88005
|
// ../../node_modules/.pnpm/@puppeteer+browsers@3.0.6_yauzl@2.10.0/node_modules/@puppeteer/browsers/lib/fileUtil.js
|
|
87789
88006
|
import { spawnSync, spawn, execFile as execFile2 } from "node:child_process";
|
|
87790
88007
|
import { constants as constants2, createReadStream, createWriteStream as createWriteStream2 } from "node:fs";
|
|
87791
|
-
import { mkdir as
|
|
88008
|
+
import { mkdir as mkdir8, readdir as readdir4, symlink as symlink2 } from "node:fs/promises";
|
|
87792
88009
|
import * as path9 from "node:path";
|
|
87793
88010
|
import { Stream, Writable as Writable2 } from "node:stream";
|
|
87794
88011
|
import { pipeline } from "node:stream/promises";
|
|
@@ -87798,12 +88015,12 @@ async function unpackArchive(archivePath, folderPath) {
|
|
|
87798
88015
|
folderPath = path9.resolve(process.cwd(), folderPath);
|
|
87799
88016
|
}
|
|
87800
88017
|
if (archivePath.endsWith(".zip")) {
|
|
87801
|
-
await
|
|
88018
|
+
await mkdir8(folderPath, { recursive: true });
|
|
87802
88019
|
await extractZip(archivePath, folderPath);
|
|
87803
88020
|
} else if (archivePath.endsWith(".tar.bz2")) {
|
|
87804
88021
|
await extractTar(archivePath, folderPath, "bzip2");
|
|
87805
88022
|
} else if (archivePath.endsWith(".dmg")) {
|
|
87806
|
-
await
|
|
88023
|
+
await mkdir8(folderPath);
|
|
87807
88024
|
await installDMG(archivePath, folderPath);
|
|
87808
88025
|
} else if (archivePath.endsWith(".exe")) {
|
|
87809
88026
|
const result = spawnSync(archivePath, [`/ExtractDir=${folderPath}`], {
|
|
@@ -87991,10 +88208,10 @@ async function extractZipEntry(zipFile, entry, folderPath) {
|
|
|
87991
88208
|
const mode = unixMode === 0 ? isDirectory2 ? 493 : 420 : unixMode & 511;
|
|
87992
88209
|
const destination = path9.join(folderPath, entry.fileName);
|
|
87993
88210
|
if (isDirectory2) {
|
|
87994
|
-
await
|
|
88211
|
+
await mkdir8(destination, { recursive: true, mode });
|
|
87995
88212
|
return;
|
|
87996
88213
|
}
|
|
87997
|
-
await
|
|
88214
|
+
await mkdir8(path9.dirname(destination), { recursive: true });
|
|
87998
88215
|
const readStream = await promisify2(zipFile.openReadStream.bind(zipFile))(entry);
|
|
87999
88216
|
if (isSymlink) {
|
|
88000
88217
|
const chunks = [];
|
|
@@ -88162,7 +88379,7 @@ var init_ProgressBar = __esm({
|
|
|
88162
88379
|
import assert3 from "node:assert";
|
|
88163
88380
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
88164
88381
|
import { existsSync as existsSync5, readFileSync as readFileSync2 } from "node:fs";
|
|
88165
|
-
import { mkdir as
|
|
88382
|
+
import { mkdir as mkdir9, unlink } from "node:fs/promises";
|
|
88166
88383
|
import os6 from "node:os";
|
|
88167
88384
|
import path10 from "node:path";
|
|
88168
88385
|
function debugTime(label) {
|
|
@@ -88215,7 +88432,7 @@ async function installWithProviders(options) {
|
|
|
88215
88432
|
}
|
|
88216
88433
|
debugInstall?.(`Successfully got URL from ${provider.getName()}: ${url}`);
|
|
88217
88434
|
if (!existsSync5(browserRoot)) {
|
|
88218
|
-
await
|
|
88435
|
+
await mkdir9(browserRoot, { recursive: true });
|
|
88219
88436
|
}
|
|
88220
88437
|
return await installUrl(url, options, provider);
|
|
88221
88438
|
} catch (err) {
|
|
@@ -88288,7 +88505,7 @@ async function installUrl(url, options, provider) {
|
|
|
88288
88505
|
const browserRoot = cache.browserRoot(options.browser);
|
|
88289
88506
|
const archivePath = path10.join(browserRoot, `${options.buildId}-${fileName}`);
|
|
88290
88507
|
if (!existsSync5(browserRoot)) {
|
|
88291
|
-
await
|
|
88508
|
+
await mkdir9(browserRoot, { recursive: true });
|
|
88292
88509
|
}
|
|
88293
88510
|
if (options.expectedHash) {
|
|
88294
88511
|
debugInstall?.(`Using provided checksum for ${fileName}: ${options.expectedHash}`);
|
|
@@ -89079,18 +89296,18 @@ var init_cliui = __esm({
|
|
|
89079
89296
|
});
|
|
89080
89297
|
|
|
89081
89298
|
// ../../node_modules/.pnpm/escalade@3.2.0/node_modules/escalade/sync/index.mjs
|
|
89082
|
-
import { dirname as
|
|
89299
|
+
import { dirname as dirname7, resolve as resolve10 } from "path";
|
|
89083
89300
|
import { readdirSync, statSync as statSync2 } from "fs";
|
|
89084
89301
|
function sync_default(start, callback) {
|
|
89085
89302
|
let dir = resolve10(".", start);
|
|
89086
89303
|
let tmp, stats = statSync2(dir);
|
|
89087
89304
|
if (!stats.isDirectory()) {
|
|
89088
|
-
dir =
|
|
89305
|
+
dir = dirname7(dir);
|
|
89089
89306
|
}
|
|
89090
89307
|
while (true) {
|
|
89091
89308
|
tmp = callback(dir, readdirSync(dir));
|
|
89092
89309
|
if (tmp) return resolve10(dir, tmp);
|
|
89093
|
-
dir =
|
|
89310
|
+
dir = dirname7(tmp = dir);
|
|
89094
89311
|
if (tmp === dir) break;
|
|
89095
89312
|
}
|
|
89096
89313
|
}
|
|
@@ -90359,7 +90576,7 @@ var require_get_caller_file = __commonJS({
|
|
|
90359
90576
|
import { notStrictEqual, strictEqual } from "assert";
|
|
90360
90577
|
import { inspect } from "util";
|
|
90361
90578
|
import { fileURLToPath } from "url";
|
|
90362
|
-
import { basename as basename4, dirname as
|
|
90579
|
+
import { basename as basename4, dirname as dirname8, extname as extname2, relative as relative3, resolve as resolve13, join as join7 } from "path";
|
|
90363
90580
|
import { createRequire as createRequire2 } from "node:module";
|
|
90364
90581
|
import { readFileSync as readFileSync5, readdirSync as readdirSync2 } from "node:fs";
|
|
90365
90582
|
var import_get_caller_file, __dirname2, mainFilename, require3, esm_default;
|
|
@@ -90392,7 +90609,7 @@ var init_esm2 = __esm({
|
|
|
90392
90609
|
Parser: lib_default,
|
|
90393
90610
|
path: {
|
|
90394
90611
|
basename: basename4,
|
|
90395
|
-
dirname:
|
|
90612
|
+
dirname: dirname8,
|
|
90396
90613
|
extname: extname2,
|
|
90397
90614
|
relative: relative3,
|
|
90398
90615
|
resolve: resolve13,
|
|
@@ -95599,7 +95816,7 @@ var init_PuppeteerNode = __esm({
|
|
|
95599
95816
|
import { spawn as spawn3, spawnSync as spawnSync3 } from "node:child_process";
|
|
95600
95817
|
import fs8 from "node:fs";
|
|
95601
95818
|
import os10 from "node:os";
|
|
95602
|
-
import { dirname as
|
|
95819
|
+
import { dirname as dirname9 } from "node:path";
|
|
95603
95820
|
import { PassThrough } from "node:stream";
|
|
95604
95821
|
function countFrames(startTimestamp, previousTimestamp, timestamp, fps) {
|
|
95605
95822
|
const end = Math.round((timestamp - startTimestamp) * fps);
|
|
@@ -95723,7 +95940,7 @@ var init_ScreenRecorder = __esm({
|
|
|
95723
95940
|
filters2.push(formatArgs.splice(vf, 2).at(-1) ?? "");
|
|
95724
95941
|
}
|
|
95725
95942
|
if (path16) {
|
|
95726
|
-
fs8.mkdirSync(
|
|
95943
|
+
fs8.mkdirSync(dirname9(path16), { recursive: overwrite });
|
|
95727
95944
|
}
|
|
95728
95945
|
this.#process = spawn3(
|
|
95729
95946
|
ffmpegPath,
|
|
@@ -96910,7 +97127,7 @@ import {
|
|
|
96910
97127
|
symlinkSync,
|
|
96911
97128
|
writeFileSync as writeFileSync6
|
|
96912
97129
|
} from "node:fs";
|
|
96913
|
-
import { basename as basename42, dirname as
|
|
97130
|
+
import { basename as basename42, dirname as dirname112, isAbsolute as isAbsolute42, join as join21, relative as relative22, resolve as resolve122 } from "node:path";
|
|
96914
97131
|
import {
|
|
96915
97132
|
basename as basename32,
|
|
96916
97133
|
join as join20,
|
|
@@ -124195,7 +124412,7 @@ function writeCompiledArtifacts(compiled, workDir, includeSummary) {
|
|
|
124195
124412
|
writeFileSync6(join21(compileDir, "index.html"), compiled.html, "utf-8");
|
|
124196
124413
|
for (const [srcPath, html] of compiled.subCompositions) {
|
|
124197
124414
|
const outPath = join21(compileDir, srcPath);
|
|
124198
|
-
mkdirSync9(
|
|
124415
|
+
mkdirSync9(dirname112(outPath), { recursive: true });
|
|
124199
124416
|
writeFileSync6(outPath, html, "utf-8");
|
|
124200
124417
|
}
|
|
124201
124418
|
for (const [relativePath, absolutePath] of compiled.externalAssets) {
|
|
@@ -124204,7 +124421,7 @@ function writeCompiledArtifacts(compiled, workDir, includeSummary) {
|
|
|
124204
124421
|
console.warn(`[Render] Skipping external asset with unsafe path: ${relativePath}`);
|
|
124205
124422
|
continue;
|
|
124206
124423
|
}
|
|
124207
|
-
mkdirSync9(
|
|
124424
|
+
mkdirSync9(dirname112(outPath), { recursive: true });
|
|
124208
124425
|
copyFileSync3(absolutePath, outPath);
|
|
124209
124426
|
}
|
|
124210
124427
|
if (includeSummary) {
|
|
@@ -267045,7 +267262,7 @@ ${allInlineStyles}`.replace(/\/\*[\s\S]*?\*\//g, "");
|
|
|
267045
267262
|
materializePathModule = {
|
|
267046
267263
|
resolve: resolve122,
|
|
267047
267264
|
join: join21,
|
|
267048
|
-
dirname:
|
|
267265
|
+
dirname: dirname112,
|
|
267049
267266
|
basename: basename42,
|
|
267050
267267
|
relative: relative22,
|
|
267051
267268
|
isAbsolute: isAbsolute42
|
|
@@ -269905,7 +270122,7 @@ __export(scene_render_exports, {
|
|
|
269905
270122
|
});
|
|
269906
270123
|
import { execFile as execFile4 } from "node:child_process";
|
|
269907
270124
|
import { existsSync as existsSync49 } from "node:fs";
|
|
269908
|
-
import { mkdir as
|
|
270125
|
+
import { mkdir as mkdir13, readFile as readFile17, stat as stat5, writeFile as writeFile16 } from "node:fs/promises";
|
|
269909
270126
|
import { resolve as resolve33, relative as relative9, dirname as dirname26, basename as basename8, join as join61, isAbsolute as isAbsolute8 } from "node:path";
|
|
269910
270127
|
import { promisify as promisify4 } from "node:util";
|
|
269911
270128
|
function qualityToCrf(quality = "standard") {
|
|
@@ -270051,7 +270268,7 @@ async function executeSceneRender(opts = {}) {
|
|
|
270051
270268
|
}
|
|
270052
270269
|
const projectName = projectConfig.config.name;
|
|
270053
270270
|
const outputPath = opts.output ? resolve33(projectDir, opts.output) : defaultOutputPath({ projectDir, projectName, format: opts.format, beatId: opts.beatId });
|
|
270054
|
-
await
|
|
270271
|
+
await mkdir13(dirname26(outputPath), { recursive: true });
|
|
270055
270272
|
const config4 = buildRenderConfig({
|
|
270056
270273
|
fps: opts.fps,
|
|
270057
270274
|
quality: opts.quality,
|
|
@@ -270247,7 +270464,7 @@ async function prepareBeatRenderRoot(opts) {
|
|
|
270247
270464
|
durationSec,
|
|
270248
270465
|
narrationPath
|
|
270249
270466
|
});
|
|
270250
|
-
await
|
|
270467
|
+
await mkdir13(dirname26(join61(opts.projectDir, root2)), { recursive: true });
|
|
270251
270468
|
await writeFile16(join61(opts.projectDir, root2), html, "utf-8");
|
|
270252
270469
|
return {
|
|
270253
270470
|
success: true,
|
|
@@ -270532,7 +270749,7 @@ var init_design_parse = __esm({
|
|
|
270532
270749
|
|
|
270533
270750
|
// ../cli/src/commands/_shared/compose-aivideo.ts
|
|
270534
270751
|
import { existsSync as existsSync50 } from "node:fs";
|
|
270535
|
-
import { mkdir as
|
|
270752
|
+
import { mkdir as mkdir14, readFile as readFile18, writeFile as writeFile17 } from "node:fs/promises";
|
|
270536
270753
|
import { join as join63, resolve as resolve34 } from "node:path";
|
|
270537
270754
|
function headingDescriptor(heading) {
|
|
270538
270755
|
const stripped = heading.replace(/^\s*beat\s+/i, "");
|
|
@@ -270695,7 +270912,7 @@ async function composeAiVideo(opts) {
|
|
|
270695
270912
|
}
|
|
270696
270913
|
clipRels.push(rel);
|
|
270697
270914
|
}
|
|
270698
|
-
await
|
|
270915
|
+
await mkdir14(join63(projectDir, "assets"), { recursive: true });
|
|
270699
270916
|
const bgRel = "assets/bg-full.mp4";
|
|
270700
270917
|
const concatArgs = buildBgConcatArgs(
|
|
270701
270918
|
clipRels.map((r2) => join63(projectDir, r2)),
|
|
@@ -270703,7 +270920,7 @@ async function composeAiVideo(opts) {
|
|
|
270703
270920
|
);
|
|
270704
270921
|
await execSafe("ffmpeg", concatArgs, { timeout: 6e5 });
|
|
270705
270922
|
const totalDurationSec = await probeDurationSec(join63(projectDir, bgRel));
|
|
270706
|
-
await
|
|
270923
|
+
await mkdir14(join63(projectDir, "compositions"), { recursive: true });
|
|
270707
270924
|
const sceneFiles = [];
|
|
270708
270925
|
for (let i3 = 0; i3 < beats.length; i3++) {
|
|
270709
270926
|
const beat = beats[i3];
|
|
@@ -270852,7 +271069,7 @@ var init_compose_aivideo = __esm({
|
|
|
270852
271069
|
|
|
270853
271070
|
// ../cli/src/commands/_shared/footage-assemble.ts
|
|
270854
271071
|
import { existsSync as existsSync51 } from "node:fs";
|
|
270855
|
-
import { mkdir as
|
|
271072
|
+
import { mkdir as mkdir15, writeFile as writeFile18 } from "node:fs/promises";
|
|
270856
271073
|
import { dirname as dirname27, isAbsolute as isAbsolute9, join as join64, resolve as resolve35 } from "node:path";
|
|
270857
271074
|
function planFootageTimeline(inputs, opts = {}) {
|
|
270858
271075
|
if (inputs.length === 0) {
|
|
@@ -271182,7 +271399,7 @@ async function executeFootageAssemble(opts) {
|
|
|
271182
271399
|
if (opts.dryRun) {
|
|
271183
271400
|
return { success: true, dryRun: true, outputPath, report };
|
|
271184
271401
|
}
|
|
271185
|
-
await
|
|
271402
|
+
await mkdir15(dirname27(outputPath), { recursive: true });
|
|
271186
271403
|
const args = buildFootageAssembleArgs({
|
|
271187
271404
|
sources: sourceRels.map((s2) => ({ path: join64(projectDir, s2.rel), kind: s2.kind })),
|
|
271188
271405
|
plan: plan2,
|
|
@@ -271543,6 +271760,37 @@ var init_composer_resolve = __esm({
|
|
|
271543
271760
|
}
|
|
271544
271761
|
});
|
|
271545
271762
|
|
|
271763
|
+
// ../cli/src/commands/_shared/build-video-providers.ts
|
|
271764
|
+
function isBuildVideoProvider(value) {
|
|
271765
|
+
return BUILD_VIDEO_PROVIDERS.includes(value);
|
|
271766
|
+
}
|
|
271767
|
+
function resolveBuildVideoProvider(value) {
|
|
271768
|
+
const provider = String(value ?? "seedance").toLowerCase();
|
|
271769
|
+
if (provider === "fal") return "seedance";
|
|
271770
|
+
return isBuildVideoProvider(provider) ? provider : "seedance";
|
|
271771
|
+
}
|
|
271772
|
+
function videoProviderConfigKey(provider) {
|
|
271773
|
+
switch (provider) {
|
|
271774
|
+
case "seedance":
|
|
271775
|
+
case "fal":
|
|
271776
|
+
return "fal";
|
|
271777
|
+
case "grok":
|
|
271778
|
+
return "xai";
|
|
271779
|
+
case "veo":
|
|
271780
|
+
case "omni":
|
|
271781
|
+
return "google";
|
|
271782
|
+
default:
|
|
271783
|
+
return provider;
|
|
271784
|
+
}
|
|
271785
|
+
}
|
|
271786
|
+
var BUILD_VIDEO_PROVIDERS;
|
|
271787
|
+
var init_build_video_providers = __esm({
|
|
271788
|
+
"../cli/src/commands/_shared/build-video-providers.ts"() {
|
|
271789
|
+
"use strict";
|
|
271790
|
+
BUILD_VIDEO_PROVIDERS = ["seedance", "grok", "kling", "runway", "omni", "veo"];
|
|
271791
|
+
}
|
|
271792
|
+
});
|
|
271793
|
+
|
|
271546
271794
|
// ../cli/src/commands/_shared/build-plan.ts
|
|
271547
271795
|
import { existsSync as existsSync54 } from "node:fs";
|
|
271548
271796
|
import { dirname as dirname28, join as join65, resolve as resolve37 } from "node:path";
|
|
@@ -272217,12 +272465,7 @@ function normalizeImageProvider(value) {
|
|
|
272217
272465
|
return provider || "openai";
|
|
272218
272466
|
}
|
|
272219
272467
|
function normalizeVideoProvider(value) {
|
|
272220
|
-
|
|
272221
|
-
if (provider === "fal") return "seedance";
|
|
272222
|
-
if (provider === "seedance" || provider === "grok" || provider === "kling" || provider === "runway" || provider === "veo") {
|
|
272223
|
-
return provider;
|
|
272224
|
-
}
|
|
272225
|
-
return "seedance";
|
|
272468
|
+
return resolveBuildVideoProvider(value);
|
|
272226
272469
|
}
|
|
272227
272470
|
function normalizeMusicProvider(value) {
|
|
272228
272471
|
const provider = String(value ?? "elevenlabs").toLowerCase();
|
|
@@ -272234,7 +272477,7 @@ function imageConfigKey(provider) {
|
|
|
272234
272477
|
return "openai";
|
|
272235
272478
|
}
|
|
272236
272479
|
function videoConfigKey(provider) {
|
|
272237
|
-
return provider
|
|
272480
|
+
return videoProviderConfigKey(provider);
|
|
272238
272481
|
}
|
|
272239
272482
|
function composerConfigKey(provider) {
|
|
272240
272483
|
return provider === "claude" ? "anthropic" : provider === "gemini" ? "google" : "openai";
|
|
@@ -272278,6 +272521,7 @@ var init_build_plan = __esm({
|
|
|
272278
272521
|
init_project_config();
|
|
272279
272522
|
init_scene_project();
|
|
272280
272523
|
init_storyboard_edit();
|
|
272524
|
+
init_build_video_providers();
|
|
272281
272525
|
VIDEO_COST_USD = 5;
|
|
272282
272526
|
MUSIC_COST_USD = 0.5;
|
|
272283
272527
|
ELEVENLABS_NARRATION_COST_USD = 0.05;
|
|
@@ -272456,7 +272700,7 @@ function registerMusicCommand(parent) {
|
|
|
272456
272700
|
console.log();
|
|
272457
272701
|
console.log(`Saved to: ${source_default.bold(outputPath)}`);
|
|
272458
272702
|
console.log(`Duration: ${duration}s`);
|
|
272459
|
-
console.log(`Provider: ElevenLabs (
|
|
272703
|
+
console.log(`Provider: ElevenLabs (${ELEVENLABS_MUSIC_MODEL})`);
|
|
272460
272704
|
if (options.instrumental) console.log(`Mode: Instrumental`);
|
|
272461
272705
|
console.log();
|
|
272462
272706
|
} else {
|
|
@@ -272596,6 +272840,48 @@ var init_scene_build_mode = __esm({
|
|
|
272596
272840
|
}
|
|
272597
272841
|
});
|
|
272598
272842
|
|
|
272843
|
+
// ../cli/src/utils/image-file.ts
|
|
272844
|
+
import { rm as rm6, writeFile as writeFile20 } from "node:fs/promises";
|
|
272845
|
+
import { extname as extname12 } from "node:path";
|
|
272846
|
+
function detectImageFormat(buffer) {
|
|
272847
|
+
if (buffer.subarray(0, 8).equals(Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]))) {
|
|
272848
|
+
return "png";
|
|
272849
|
+
}
|
|
272850
|
+
if (buffer[0] === 255 && buffer[1] === 216 && buffer[2] === 255) return "jpeg";
|
|
272851
|
+
if (buffer.toString("ascii", 0, 4) === "RIFF" && buffer.toString("ascii", 8, 12) === "WEBP") {
|
|
272852
|
+
return "webp";
|
|
272853
|
+
}
|
|
272854
|
+
return void 0;
|
|
272855
|
+
}
|
|
272856
|
+
async function writeImageFile(path16, buffer) {
|
|
272857
|
+
const wanted = EXTENSION_FORMATS[extname12(path16).toLowerCase()];
|
|
272858
|
+
const actual = detectImageFormat(buffer);
|
|
272859
|
+
if (!wanted || !actual || wanted === actual) {
|
|
272860
|
+
await writeFile20(path16, buffer);
|
|
272861
|
+
return;
|
|
272862
|
+
}
|
|
272863
|
+
const source3 = `${path16}.source.${actual === "jpeg" ? "jpg" : actual}`;
|
|
272864
|
+
await writeFile20(source3, buffer);
|
|
272865
|
+
try {
|
|
272866
|
+
await execSafe("ffmpeg", ["-y", "-loglevel", "error", "-i", source3, "-frames:v", "1", path16]);
|
|
272867
|
+
} finally {
|
|
272868
|
+
await rm6(source3, { force: true });
|
|
272869
|
+
}
|
|
272870
|
+
}
|
|
272871
|
+
var EXTENSION_FORMATS;
|
|
272872
|
+
var init_image_file = __esm({
|
|
272873
|
+
"../cli/src/utils/image-file.ts"() {
|
|
272874
|
+
"use strict";
|
|
272875
|
+
init_exec_safe();
|
|
272876
|
+
EXTENSION_FORMATS = {
|
|
272877
|
+
".png": "png",
|
|
272878
|
+
".jpg": "jpeg",
|
|
272879
|
+
".jpeg": "jpeg",
|
|
272880
|
+
".webp": "webp"
|
|
272881
|
+
};
|
|
272882
|
+
}
|
|
272883
|
+
});
|
|
272884
|
+
|
|
272599
272885
|
// ../cli/src/commands/_shared/scene-build.ts
|
|
272600
272886
|
var scene_build_exports = {};
|
|
272601
272887
|
__export(scene_build_exports, {
|
|
@@ -272604,7 +272890,7 @@ __export(scene_build_exports, {
|
|
|
272604
272890
|
resolveSceneBuildMode: () => resolveSceneBuildMode
|
|
272605
272891
|
});
|
|
272606
272892
|
import { existsSync as existsSync56, readFileSync as readFileSync21 } from "node:fs";
|
|
272607
|
-
import { copyFile as copyFile4, mkdir as
|
|
272893
|
+
import { copyFile as copyFile4, mkdir as mkdir16, readFile as readFile19, rm as rm7, writeFile as writeFile21 } from "node:fs/promises";
|
|
272608
272894
|
import { dirname as dirname29, join as join66, resolve as resolve40 } from "node:path";
|
|
272609
272895
|
function readProjectKindSync(projectDir) {
|
|
272610
272896
|
try {
|
|
@@ -273458,7 +273744,7 @@ async function dispatchNarration(beat, ctx) {
|
|
|
273458
273744
|
};
|
|
273459
273745
|
}
|
|
273460
273746
|
if (existsSync56(cacheAbs) && !ctx.force) {
|
|
273461
|
-
await
|
|
273747
|
+
await mkdir16(dirname29(abs), { recursive: true });
|
|
273462
273748
|
await copyFile4(cacheAbs, abs);
|
|
273463
273749
|
await writeAssetMetadata({
|
|
273464
273750
|
projectDir: ctx.projectDir,
|
|
@@ -273489,14 +273775,14 @@ async function dispatchNarration(beat, ctx) {
|
|
|
273489
273775
|
ctx.onProgress({ type: "narration-failed", beatId: beat.id, error });
|
|
273490
273776
|
return { status: "failed", error };
|
|
273491
273777
|
}
|
|
273492
|
-
await
|
|
273493
|
-
await
|
|
273778
|
+
await mkdir16(dirname29(abs), { recursive: true });
|
|
273779
|
+
await writeFile21(abs, result.audioBuffer);
|
|
273494
273780
|
for (const otherExt of ["mp3", "wav"]) {
|
|
273495
273781
|
const sibling = join66(ctx.projectDir, `assets/narration-${beat.id}.${otherExt}`);
|
|
273496
|
-
if (sibling !== abs && existsSync56(sibling)) await
|
|
273782
|
+
if (sibling !== abs && existsSync56(sibling)) await rm7(sibling, { force: true });
|
|
273497
273783
|
}
|
|
273498
|
-
await
|
|
273499
|
-
await
|
|
273784
|
+
await mkdir16(dirname29(cacheAbs), { recursive: true });
|
|
273785
|
+
await writeFile21(cacheAbs, result.audioBuffer);
|
|
273500
273786
|
await writeAssetMetadata({
|
|
273501
273787
|
projectDir: ctx.projectDir,
|
|
273502
273788
|
kind: "narration",
|
|
@@ -273552,8 +273838,8 @@ async function dispatchTranscript(beat, narrationPath, narrationFresh, ctx) {
|
|
|
273552
273838
|
return "skipped";
|
|
273553
273839
|
}
|
|
273554
273840
|
try {
|
|
273555
|
-
await
|
|
273556
|
-
await
|
|
273841
|
+
await mkdir16(dirname29(abs), { recursive: true });
|
|
273842
|
+
await writeFile21(abs, JSON.stringify(words, null, 2), "utf-8");
|
|
273557
273843
|
} catch (err) {
|
|
273558
273844
|
ctx.onProgress({
|
|
273559
273845
|
type: "transcript-skipped",
|
|
@@ -273641,7 +273927,7 @@ async function buildCharacters(characters, ctx) {
|
|
|
273641
273927
|
}
|
|
273642
273928
|
const cacheAbs = join66(ctx.projectDir, cache.path);
|
|
273643
273929
|
if (existsSync56(cacheAbs) && !ctx.force) {
|
|
273644
|
-
await
|
|
273930
|
+
await mkdir16(dirname29(abs), { recursive: true });
|
|
273645
273931
|
await copyFile4(cacheAbs, abs);
|
|
273646
273932
|
await writeAssetMetadata({
|
|
273647
273933
|
projectDir: ctx.projectDir,
|
|
@@ -273674,10 +273960,10 @@ async function buildCharacters(characters, ctx) {
|
|
|
273674
273960
|
ctx.onProgress({ type: "character-failed", name: character.name, error: generated.error });
|
|
273675
273961
|
continue;
|
|
273676
273962
|
}
|
|
273677
|
-
await
|
|
273678
|
-
await
|
|
273679
|
-
await
|
|
273680
|
-
await
|
|
273963
|
+
await mkdir16(dirname29(abs), { recursive: true });
|
|
273964
|
+
await writeImageFile(abs, generated.buffer);
|
|
273965
|
+
await mkdir16(dirname29(cacheAbs), { recursive: true });
|
|
273966
|
+
await writeImageFile(cacheAbs, generated.buffer);
|
|
273681
273967
|
await writeAssetMetadata({
|
|
273682
273968
|
projectDir: ctx.projectDir,
|
|
273683
273969
|
kind: "character",
|
|
@@ -273746,7 +274032,7 @@ async function dispatchBackdrop(beat, ctx) {
|
|
|
273746
274032
|
}
|
|
273747
274033
|
const cacheAbs = join66(ctx.projectDir, cache.path);
|
|
273748
274034
|
if (existsSync56(cacheAbs) && !ctx.force) {
|
|
273749
|
-
await
|
|
274035
|
+
await mkdir16(dirname29(abs), { recursive: true });
|
|
273750
274036
|
await copyFile4(cacheAbs, abs);
|
|
273751
274037
|
await writeAssetMetadata({
|
|
273752
274038
|
projectDir: ctx.projectDir,
|
|
@@ -273776,11 +274062,11 @@ async function dispatchBackdrop(beat, ctx) {
|
|
|
273776
274062
|
ctx.onProgress({ type: "backdrop-failed", beatId: beat.id, error });
|
|
273777
274063
|
return { status: "failed", error };
|
|
273778
274064
|
}
|
|
273779
|
-
await
|
|
274065
|
+
await mkdir16(dirname29(abs), { recursive: true });
|
|
273780
274066
|
const buffer = generated.buffer;
|
|
273781
|
-
await
|
|
273782
|
-
await
|
|
273783
|
-
await
|
|
274067
|
+
await writeImageFile(abs, buffer);
|
|
274068
|
+
await mkdir16(dirname29(cacheAbs), { recursive: true });
|
|
274069
|
+
await writeImageFile(cacheAbs, buffer);
|
|
273784
274070
|
await writeAssetMetadata({
|
|
273785
274071
|
projectDir: ctx.projectDir,
|
|
273786
274072
|
kind: "backdrop",
|
|
@@ -273824,7 +274110,7 @@ async function generateBackdropImage(prompt3, ctx, ratio) {
|
|
|
273824
274110
|
const result2 = await provider2.generateImage(prompt3, {
|
|
273825
274111
|
// CLI input is free-form; an alias the provider doesn't know fails the
|
|
273826
274112
|
// API call and surfaces as a beat-scoped backdrop/keyframe error.
|
|
273827
|
-
model: ctx.imageModel ??
|
|
274113
|
+
model: ctx.imageModel ?? OPENAI_IMAGE_DEFAULT_MODEL,
|
|
273828
274114
|
size: ctx.imageSize,
|
|
273829
274115
|
quality: ctx.imageQuality
|
|
273830
274116
|
});
|
|
@@ -273909,7 +274195,7 @@ async function ensureKeyframe(beat, ctx, keyframeCue, characterRefsRel) {
|
|
|
273909
274195
|
}
|
|
273910
274196
|
const cacheAbs = join66(ctx.projectDir, cache.path);
|
|
273911
274197
|
if (existsSync56(cacheAbs) && !ctx.force) {
|
|
273912
|
-
await
|
|
274198
|
+
await mkdir16(dirname29(abs), { recursive: true });
|
|
273913
274199
|
await copyFile4(cacheAbs, abs);
|
|
273914
274200
|
await writeAssetMetadata({
|
|
273915
274201
|
projectDir: ctx.projectDir,
|
|
@@ -273939,10 +274225,10 @@ async function ensureKeyframe(beat, ctx, keyframeCue, characterRefsRel) {
|
|
|
273939
274225
|
const identityLock = "Keep the EXACT same person and face as the reference image(s): identical facial features (eyes, nose shape, jawline), skin tone and complexion, hairstyle, hair color, and wardrobe. Do not restyle or change the face. Change only the scene, pose, framing, and lighting. ";
|
|
273940
274226
|
const generated = sheetBuffers.length > 0 ? await editKeyframeImage(`${identityLock}${keyframeCue}`, sheetBuffers, imgCtx, ratio) : await generateBackdropImage(keyframeCue, imgCtx, ratio);
|
|
273941
274227
|
if (!generated.success) return { status: "failed", error: generated.error };
|
|
273942
|
-
await
|
|
273943
|
-
await
|
|
273944
|
-
await
|
|
273945
|
-
await
|
|
274228
|
+
await mkdir16(dirname29(abs), { recursive: true });
|
|
274229
|
+
await writeImageFile(abs, generated.buffer);
|
|
274230
|
+
await mkdir16(dirname29(cacheAbs), { recursive: true });
|
|
274231
|
+
await writeImageFile(cacheAbs, generated.buffer);
|
|
273946
274232
|
await writeAssetMetadata({
|
|
273947
274233
|
projectDir: ctx.projectDir,
|
|
273948
274234
|
kind: "keyframe",
|
|
@@ -274038,7 +274324,7 @@ async function dispatchVideo(beat, ctx, keyframe) {
|
|
|
274038
274324
|
}
|
|
274039
274325
|
const cacheAbs = join66(ctx.projectDir, cache.path);
|
|
274040
274326
|
if (existsSync56(cacheAbs) && !ctx.force) {
|
|
274041
|
-
await
|
|
274327
|
+
await mkdir16(dirname29(abs), { recursive: true });
|
|
274042
274328
|
await copyFile4(cacheAbs, abs);
|
|
274043
274329
|
await writeAssetMetadata({
|
|
274044
274330
|
projectDir: ctx.projectDir,
|
|
@@ -274115,7 +274401,7 @@ async function dispatchVideo(beat, ctx, keyframe) {
|
|
|
274115
274401
|
}
|
|
274116
274402
|
}
|
|
274117
274403
|
if (result.status === "completed" && existsSync56(abs)) {
|
|
274118
|
-
await
|
|
274404
|
+
await mkdir16(dirname29(cacheAbs), { recursive: true });
|
|
274119
274405
|
await copyFile4(abs, cacheAbs);
|
|
274120
274406
|
await writeAssetMetadata({
|
|
274121
274407
|
projectDir: ctx.projectDir,
|
|
@@ -274217,7 +274503,7 @@ async function dispatchMusic(beat, ctx) {
|
|
|
274217
274503
|
}
|
|
274218
274504
|
const cacheAbs = join66(ctx.projectDir, cache.path);
|
|
274219
274505
|
if (existsSync56(cacheAbs) && !ctx.force) {
|
|
274220
|
-
await
|
|
274506
|
+
await mkdir16(dirname29(abs), { recursive: true });
|
|
274221
274507
|
await copyFile4(cacheAbs, abs);
|
|
274222
274508
|
await writeAssetMetadata({
|
|
274223
274509
|
projectDir: ctx.projectDir,
|
|
@@ -274295,7 +274581,7 @@ async function dispatchMusic(beat, ctx) {
|
|
|
274295
274581
|
ctx.onProgress({ type: "music-failed", beatId: beat.id, error });
|
|
274296
274582
|
return { status: "failed", error };
|
|
274297
274583
|
}
|
|
274298
|
-
await
|
|
274584
|
+
await mkdir16(dirname29(cacheAbs), { recursive: true });
|
|
274299
274585
|
await copyFile4(abs, cacheAbs);
|
|
274300
274586
|
await writeAssetMetadata({
|
|
274301
274587
|
projectDir: ctx.projectDir,
|
|
@@ -274559,14 +274845,6 @@ async function safeAudioDuration(absPath) {
|
|
|
274559
274845
|
return void 0;
|
|
274560
274846
|
}
|
|
274561
274847
|
}
|
|
274562
|
-
function resolveBuildVideoProvider(value) {
|
|
274563
|
-
const provider = String(value ?? "seedance").toLowerCase();
|
|
274564
|
-
if (provider === "fal") return "seedance";
|
|
274565
|
-
if (provider === "seedance" || provider === "grok" || provider === "kling" || provider === "runway" || provider === "veo") {
|
|
274566
|
-
return provider;
|
|
274567
|
-
}
|
|
274568
|
-
return "seedance";
|
|
274569
|
-
}
|
|
274570
274848
|
function resolveBuildMusicProvider(value) {
|
|
274571
274849
|
const provider = String(value ?? "elevenlabs").toLowerCase();
|
|
274572
274850
|
return provider === "replicate" ? "replicate" : "elevenlabs";
|
|
@@ -274578,8 +274856,7 @@ function stringOrUndefined4(value) {
|
|
|
274578
274856
|
return typeof value === "string" && value.trim().length > 0 ? value : void 0;
|
|
274579
274857
|
}
|
|
274580
274858
|
async function apiKeyForVideoProvider(provider, projectDir) {
|
|
274581
|
-
|
|
274582
|
-
return getApiKeyFromConfig(providerKey, { cwd: projectDir });
|
|
274859
|
+
return getApiKeyFromConfig(videoProviderConfigKey(provider), { cwd: projectDir });
|
|
274583
274860
|
}
|
|
274584
274861
|
async function finalizeBuildResult(projectDir, startedAt, result, reportResult = result) {
|
|
274585
274862
|
const reportPath = join66(projectDir, "build-report.json");
|
|
@@ -274602,7 +274879,7 @@ async function finalizeBuildResult(projectDir, startedAt, result, reportResult =
|
|
|
274602
274879
|
const withMeta = decorate(result);
|
|
274603
274880
|
const reportMeta = reportResult === result ? withMeta : decorate(reportResult);
|
|
274604
274881
|
try {
|
|
274605
|
-
await
|
|
274882
|
+
await writeFile21(
|
|
274606
274883
|
reportPath,
|
|
274607
274884
|
JSON.stringify(toBuildReport(projectDir, reportMeta), null, 2) + "\n",
|
|
274608
274885
|
"utf-8"
|
|
@@ -274855,6 +275132,8 @@ var init_scene_build = __esm({
|
|
|
274855
275132
|
init_scene_repair();
|
|
274856
275133
|
init_tts_resolve();
|
|
274857
275134
|
init_scene_build_mode();
|
|
275135
|
+
init_image_file();
|
|
275136
|
+
init_build_video_providers();
|
|
274858
275137
|
init_scene_build_mode();
|
|
274859
275138
|
BEAT_PRIMITIVES_CONCURRENCY = 4;
|
|
274860
275139
|
}
|
|
@@ -274967,8 +275246,8 @@ __export(ai_audio_exports, {
|
|
|
274967
275246
|
executeTranscribe: () => executeTranscribe,
|
|
274968
275247
|
executeVoiceClone: () => executeVoiceClone
|
|
274969
275248
|
});
|
|
274970
|
-
import { resolve as resolve43, dirname as dirname30, basename as basename9, extname as
|
|
274971
|
-
import { readFile as readFile20, writeFile as
|
|
275249
|
+
import { resolve as resolve43, dirname as dirname30, basename as basename9, extname as extname13 } from "node:path";
|
|
275250
|
+
import { readFile as readFile20, writeFile as writeFile23 } from "node:fs/promises";
|
|
274972
275251
|
import { existsSync as existsSync57 } from "node:fs";
|
|
274973
275252
|
async function executeTranscribe(options) {
|
|
274974
275253
|
const { audioPath, language, output: output3, format: format4, apiKey } = options;
|
|
@@ -274990,7 +275269,7 @@ async function executeTranscribe(options) {
|
|
|
274990
275269
|
outputPath = resolve43(process.cwd(), output3);
|
|
274991
275270
|
const fmt = detectFormat(output3, format4);
|
|
274992
275271
|
const content = formatTranscript(result, fmt);
|
|
274993
|
-
await
|
|
275272
|
+
await writeFile23(outputPath, content, "utf-8");
|
|
274994
275273
|
}
|
|
274995
275274
|
return {
|
|
274996
275275
|
success: true,
|
|
@@ -275018,7 +275297,7 @@ async function executeIsolate(options) {
|
|
|
275018
275297
|
return { success: false, error: result.error || "Audio isolation failed" };
|
|
275019
275298
|
}
|
|
275020
275299
|
const outputPath = resolve43(process.cwd(), output3);
|
|
275021
|
-
await
|
|
275300
|
+
await writeFile23(outputPath, result.audioBuffer);
|
|
275022
275301
|
return { success: true, outputPath };
|
|
275023
275302
|
} catch (error) {
|
|
275024
275303
|
return { success: false, error: `Audio isolation failed: ${error instanceof Error ? error.message : String(error)}` };
|
|
@@ -275064,7 +275343,7 @@ async function executeDub(options) {
|
|
|
275064
275343
|
if (!openaiKey) return { success: false, error: "OPENAI_API_KEY required for Whisper transcription" };
|
|
275065
275344
|
if (!anthropicKey) return { success: false, error: "ANTHROPIC_API_KEY required for Claude translation" };
|
|
275066
275345
|
if (!analyzeOnly && !elevenlabsKey) return { success: false, error: "ELEVENLABS_API_KEY required for TTS" };
|
|
275067
|
-
const ext =
|
|
275346
|
+
const ext = extname13(absPath).toLowerCase();
|
|
275068
275347
|
const isVideo = [".mp4", ".mov", ".avi", ".mkv", ".webm"].includes(ext);
|
|
275069
275348
|
let audioPath = absPath;
|
|
275070
275349
|
if (isVideo) {
|
|
@@ -275129,7 +275408,7 @@ ${segmentTexts}`,
|
|
|
275129
275408
|
translated: translatedSegments[i3]?.text || s2.text
|
|
275130
275409
|
}))
|
|
275131
275410
|
};
|
|
275132
|
-
await
|
|
275411
|
+
await writeFile23(timingPath, JSON.stringify(timingData, null, 2));
|
|
275133
275412
|
}
|
|
275134
275413
|
return {
|
|
275135
275414
|
success: true,
|
|
@@ -275149,10 +275428,10 @@ ${segmentTexts}`,
|
|
|
275149
275428
|
}
|
|
275150
275429
|
}
|
|
275151
275430
|
const combinedBuffer = Buffer.concat(dubbedBuffers);
|
|
275152
|
-
const outputExt = isVideo ? ".mp3" :
|
|
275153
|
-
const defaultOutputPath2 = resolve43(dirname30(absPath), `${basename9(absPath,
|
|
275431
|
+
const outputExt = isVideo ? ".mp3" : extname13(absPath);
|
|
275432
|
+
const defaultOutputPath2 = resolve43(dirname30(absPath), `${basename9(absPath, extname13(absPath))}-${language}${outputExt}`);
|
|
275154
275433
|
const finalOutputPath = resolve43(process.cwd(), output3 || defaultOutputPath2);
|
|
275155
|
-
await
|
|
275434
|
+
await writeFile23(finalOutputPath, combinedBuffer);
|
|
275156
275435
|
if (isVideo && audioPath !== absPath) {
|
|
275157
275436
|
try {
|
|
275158
275437
|
const { unlink: unlink6 } = await import("node:fs/promises");
|
|
@@ -275187,7 +275466,7 @@ async function executeDuck(options) {
|
|
|
275187
275466
|
const absVoicePath = resolve43(process.cwd(), voicePath);
|
|
275188
275467
|
if (!existsSync57(absMusicPath)) return { success: false, error: `Music file not found: ${absMusicPath}` };
|
|
275189
275468
|
if (!existsSync57(absVoicePath)) return { success: false, error: `Voice file not found: ${absVoicePath}` };
|
|
275190
|
-
const defaultOutput = resolve43(dirname30(absMusicPath), `${basename9(absMusicPath,
|
|
275469
|
+
const defaultOutput = resolve43(dirname30(absMusicPath), `${basename9(absMusicPath, extname13(absMusicPath))}-ducked${extname13(absMusicPath)}`);
|
|
275191
275470
|
const outputPath = resolve43(process.cwd(), output3 || defaultOutput);
|
|
275192
275471
|
const filter3 = `[1:a]asplit=2[sc][mix];[0:a][sc]sidechaincompress=threshold=${threshold}dB:ratio=${ratio}:attack=${attack}:release=${release}[ducked];[ducked][mix]amix=inputs=2:duration=longest`;
|
|
275193
275472
|
await execSafe("ffmpeg", [
|
|
@@ -275452,7 +275731,7 @@ var init_silence_cut = __esm({
|
|
|
275452
275731
|
|
|
275453
275732
|
// ../cli/src/commands/_shared/edit/jump-cut.ts
|
|
275454
275733
|
import { existsSync as existsSync59 } from "node:fs";
|
|
275455
|
-
import { readFile as readFile23, writeFile as
|
|
275734
|
+
import { readFile as readFile23, writeFile as writeFile24, mkdir as mkdir17 } from "node:fs/promises";
|
|
275456
275735
|
import { join as join67 } from "node:path";
|
|
275457
275736
|
async function transcribeWithWords(audioPath, apiKey, language) {
|
|
275458
275737
|
const audioBuffer = await readFile23(audioPath);
|
|
@@ -275532,7 +275811,7 @@ async function executeJumpCut(options) {
|
|
|
275532
275811
|
}
|
|
275533
275812
|
try {
|
|
275534
275813
|
const tmpDir = `/tmp/vibe_jumpcut_${Date.now()}`;
|
|
275535
|
-
await
|
|
275814
|
+
await mkdir17(tmpDir, { recursive: true });
|
|
275536
275815
|
const audioPath = join67(tmpDir, "audio.wav");
|
|
275537
275816
|
try {
|
|
275538
275817
|
await execSafe(
|
|
@@ -275611,7 +275890,7 @@ async function executeJumpCut(options) {
|
|
|
275611
275890
|
}
|
|
275612
275891
|
const concatList = segmentPaths.map((p2) => `file '${p2}'`).join("\n");
|
|
275613
275892
|
const listPath = join67(tmpDir, "concat.txt");
|
|
275614
|
-
await
|
|
275893
|
+
await writeFile24(listPath, concatList);
|
|
275615
275894
|
await execSafe(
|
|
275616
275895
|
"ffmpeg",
|
|
275617
275896
|
[
|
|
@@ -275638,8 +275917,8 @@ async function executeJumpCut(options) {
|
|
|
275638
275917
|
};
|
|
275639
275918
|
} finally {
|
|
275640
275919
|
try {
|
|
275641
|
-
const { rm:
|
|
275642
|
-
await
|
|
275920
|
+
const { rm: rm11 } = await import("node:fs/promises");
|
|
275921
|
+
await rm11(tmpDir, { recursive: true, force: true });
|
|
275643
275922
|
} catch {
|
|
275644
275923
|
}
|
|
275645
275924
|
}
|
|
@@ -275716,29 +275995,27 @@ __export(remotion_exports, {
|
|
|
275716
275995
|
wrapComponentWithImage: () => wrapComponentWithImage,
|
|
275717
275996
|
wrapComponentWithVideo: () => wrapComponentWithVideo
|
|
275718
275997
|
});
|
|
275719
|
-
import { writeFile as
|
|
275998
|
+
import { writeFile as writeFile25, mkdir as mkdir18, rm as rm8, copyFile as copyFile5 } from "node:fs/promises";
|
|
275720
275999
|
import { existsSync as existsSync60 } from "node:fs";
|
|
275721
276000
|
import { join as join68 } from "node:path";
|
|
275722
276001
|
import { tmpdir as tmpdir9 } from "node:os";
|
|
275723
276002
|
import { createHash as createHash11 } from "node:crypto";
|
|
275724
276003
|
async function ensureRemotionInstalled() {
|
|
275725
276004
|
try {
|
|
275726
|
-
await execSafe("
|
|
276005
|
+
await execSafe("npm", ["--version"], { timeout: 3e4 });
|
|
275727
276006
|
return null;
|
|
275728
276007
|
} catch (error) {
|
|
275729
276008
|
const detail = error instanceof Error ? error.message : String(error);
|
|
275730
|
-
console.error(`[Remotion] ensureRemotionInstalled failed: ${detail.slice(0, 300)}`);
|
|
275731
276009
|
return [
|
|
275732
|
-
"Remotion
|
|
276010
|
+
"Remotion renders need npm to install the Remotion CLI into a temporary project.",
|
|
275733
276011
|
` Debug: ${detail.slice(0, 200)}`,
|
|
275734
|
-
" Fix: npm
|
|
275735
|
-
" Or ensure npx is available and can download @remotion/cli on demand."
|
|
276012
|
+
" Fix: install Node.js 20+ (which includes npm) and make sure `npm` is on PATH."
|
|
275736
276013
|
].join("\n");
|
|
275737
276014
|
}
|
|
275738
276015
|
}
|
|
275739
276016
|
async function scaffoldRemotionProject(componentCode, componentName, opts) {
|
|
275740
276017
|
const dir = join68(tmpdir9(), `vibe_motion_${Date.now()}`);
|
|
275741
|
-
await
|
|
276018
|
+
await mkdir18(dir, { recursive: true });
|
|
275742
276019
|
const deps = {
|
|
275743
276020
|
remotion: REMOTION_VERSION,
|
|
275744
276021
|
"@remotion/cli": REMOTION_VERSION,
|
|
@@ -275756,7 +276033,7 @@ async function scaffoldRemotionProject(componentCode, componentName, opts) {
|
|
|
275756
276033
|
dependencies: deps
|
|
275757
276034
|
};
|
|
275758
276035
|
const packageJsonStr = JSON.stringify(packageJson, null, 2);
|
|
275759
|
-
await
|
|
276036
|
+
await writeFile25(join68(dir, "package.json"), packageJsonStr);
|
|
275760
276037
|
const tsconfig = {
|
|
275761
276038
|
compilerOptions: {
|
|
275762
276039
|
target: "ES2020",
|
|
@@ -275768,8 +276045,8 @@ async function scaffoldRemotionProject(componentCode, componentName, opts) {
|
|
|
275768
276045
|
skipLibCheck: true
|
|
275769
276046
|
}
|
|
275770
276047
|
};
|
|
275771
|
-
await
|
|
275772
|
-
await
|
|
276048
|
+
await writeFile25(join68(dir, "tsconfig.json"), JSON.stringify(tsconfig, null, 2));
|
|
276049
|
+
await writeFile25(join68(dir, "Component.tsx"), componentCode);
|
|
275773
276050
|
const rootCode = `import { registerRoot, Composition } from "remotion";
|
|
275774
276051
|
import { ${componentName} } from "./Component";
|
|
275775
276052
|
|
|
@@ -275788,7 +276065,7 @@ const Root = () => {
|
|
|
275788
276065
|
|
|
275789
276066
|
registerRoot(Root);
|
|
275790
276067
|
`;
|
|
275791
|
-
await
|
|
276068
|
+
await writeFile25(join68(dir, "Root.tsx"), rootCode);
|
|
275792
276069
|
const depsHash = createHash11("md5").update(packageJsonStr).digest("hex").slice(0, 12);
|
|
275793
276070
|
const cacheMarker = join68(REMOTION_CACHE_DIR, `.deps-${depsHash}`);
|
|
275794
276071
|
const cachedModules = join68(REMOTION_CACHE_DIR, "node_modules");
|
|
@@ -275802,15 +276079,15 @@ registerRoot(Root);
|
|
|
275802
276079
|
} else {
|
|
275803
276080
|
await this_npmInstall(dir);
|
|
275804
276081
|
try {
|
|
275805
|
-
await
|
|
275806
|
-
await
|
|
276082
|
+
await mkdir18(REMOTION_CACHE_DIR, { recursive: true });
|
|
276083
|
+
await writeFile25(join68(REMOTION_CACHE_DIR, "package.json"), packageJsonStr);
|
|
275807
276084
|
if (existsSync60(join68(dir, "node_modules"))) {
|
|
275808
276085
|
const { rename: rename7, symlink: symlink4 } = await import("node:fs/promises");
|
|
275809
276086
|
await rename7(join68(dir, "node_modules"), cachedModules).catch(() => {
|
|
275810
276087
|
});
|
|
275811
276088
|
await symlink4(cachedModules, join68(dir, "node_modules"), "dir").catch(() => {
|
|
275812
276089
|
});
|
|
275813
|
-
await
|
|
276090
|
+
await writeFile25(cacheMarker, depsHash);
|
|
275814
276091
|
}
|
|
275815
276092
|
} catch {
|
|
275816
276093
|
}
|
|
@@ -275910,7 +276187,7 @@ async function renderMotion(options) {
|
|
|
275910
276187
|
stderr: ${stderr}` : ""}`);
|
|
275911
276188
|
return { success: false, error: `Remotion render failed: ${msg}` };
|
|
275912
276189
|
} finally {
|
|
275913
|
-
await
|
|
276190
|
+
await rm8(dir, { recursive: true, force: true }).catch(() => {
|
|
275914
276191
|
});
|
|
275915
276192
|
}
|
|
275916
276193
|
}
|
|
@@ -275979,7 +276256,7 @@ async function renderWithEmbeddedImage(options) {
|
|
|
275979
276256
|
);
|
|
275980
276257
|
try {
|
|
275981
276258
|
const publicDir = join68(dir, "public");
|
|
275982
|
-
await
|
|
276259
|
+
await mkdir18(publicDir, { recursive: true });
|
|
275983
276260
|
await copyFile5(options.imagePath, join68(publicDir, options.imageFileName));
|
|
275984
276261
|
const entryPoint = join68(dir, "Root.tsx");
|
|
275985
276262
|
const mp4Out = options.outputPath.replace(/\.\w+$/, ".mp4");
|
|
@@ -276002,7 +276279,7 @@ async function renderWithEmbeddedImage(options) {
|
|
|
276002
276279
|
const msg = error instanceof Error ? error.message : String(error);
|
|
276003
276280
|
return { success: false, error: `Remotion image embed render failed: ${msg}` };
|
|
276004
276281
|
} finally {
|
|
276005
|
-
await
|
|
276282
|
+
await rm8(dir, { recursive: true, force: true }).catch(() => {
|
|
276006
276283
|
});
|
|
276007
276284
|
}
|
|
276008
276285
|
}
|
|
@@ -276043,7 +276320,7 @@ async function renderWithEmbeddedVideo(options) {
|
|
|
276043
276320
|
);
|
|
276044
276321
|
try {
|
|
276045
276322
|
const publicDir = join68(dir, "public");
|
|
276046
|
-
await
|
|
276323
|
+
await mkdir18(publicDir, { recursive: true });
|
|
276047
276324
|
await copyFile5(options.videoPath, join68(publicDir, options.videoFileName));
|
|
276048
276325
|
const entryPoint = join68(dir, "Root.tsx");
|
|
276049
276326
|
const mp4VideoOnly = options.outputPath.replace(/\.\w+$/, "_video_only.mp4");
|
|
@@ -276079,14 +276356,14 @@ async function renderWithEmbeddedVideo(options) {
|
|
|
276079
276356
|
"-shortest",
|
|
276080
276357
|
mp4Out
|
|
276081
276358
|
], { timeout: 12e4 });
|
|
276082
|
-
await
|
|
276359
|
+
await rm8(mp4VideoOnly, { force: true }).catch(() => {
|
|
276083
276360
|
});
|
|
276084
276361
|
return { success: true, outputPath: mp4Out };
|
|
276085
276362
|
} catch (error) {
|
|
276086
276363
|
const msg = error instanceof Error ? error.message : String(error);
|
|
276087
276364
|
return { success: false, error: `Remotion video embed render failed: ${msg}` };
|
|
276088
276365
|
} finally {
|
|
276089
|
-
await
|
|
276366
|
+
await rm8(dir, { recursive: true, force: true }).catch(() => {
|
|
276090
276367
|
});
|
|
276091
276368
|
}
|
|
276092
276369
|
}
|
|
@@ -276467,8 +276744,8 @@ var init_remotion = __esm({
|
|
|
276467
276744
|
|
|
276468
276745
|
// ../cli/src/commands/_shared/edit/caption.ts
|
|
276469
276746
|
import { existsSync as existsSync61 } from "node:fs";
|
|
276470
|
-
import { readFile as readFile24, writeFile as
|
|
276471
|
-
import { dirname as dirname31, basename as basename10, extname as
|
|
276747
|
+
import { readFile as readFile24, writeFile as writeFile26, mkdir as mkdir19 } from "node:fs/promises";
|
|
276748
|
+
import { dirname as dirname31, basename as basename10, extname as extname14, join as join69 } from "node:path";
|
|
276472
276749
|
function getCaptionForceStyle(style, fontSize, fontColor, position) {
|
|
276473
276750
|
const alignment = position === "top" ? 8 : position === "center" ? 5 : 2;
|
|
276474
276751
|
const marginV = position === "center" ? 0 : 30;
|
|
@@ -276514,7 +276791,7 @@ async function executeCaption(options) {
|
|
|
276514
276791
|
}
|
|
276515
276792
|
try {
|
|
276516
276793
|
const tmpDir = `/tmp/vibe_caption_${Date.now()}`;
|
|
276517
|
-
await
|
|
276794
|
+
await mkdir19(tmpDir, { recursive: true });
|
|
276518
276795
|
const audioPath = join69(tmpDir, "audio.wav");
|
|
276519
276796
|
const srtPath = join69(tmpDir, "captions.srt");
|
|
276520
276797
|
try {
|
|
@@ -276547,7 +276824,7 @@ async function executeCaption(options) {
|
|
|
276547
276824
|
};
|
|
276548
276825
|
}
|
|
276549
276826
|
const srtContent = formatSRT(transcriptResult.segments);
|
|
276550
|
-
await
|
|
276827
|
+
await writeFile26(srtPath, srtContent);
|
|
276551
276828
|
const { width, height } = await getVideoResolution(videoPath);
|
|
276552
276829
|
const fontSize = customFontSize || Math.round(height / 18);
|
|
276553
276830
|
let hasSubtitles = false;
|
|
@@ -276587,9 +276864,9 @@ async function executeCaption(options) {
|
|
|
276587
276864
|
const outputDir2 = dirname31(outputPath);
|
|
276588
276865
|
const outputSrtPath2 = join69(
|
|
276589
276866
|
outputDir2,
|
|
276590
|
-
basename10(outputPath,
|
|
276867
|
+
basename10(outputPath, extname14(outputPath)) + ".srt"
|
|
276591
276868
|
);
|
|
276592
|
-
await
|
|
276869
|
+
await writeFile26(outputSrtPath2, srtContent);
|
|
276593
276870
|
return { success: false, error: `${remotionErr}
|
|
276594
276871
|
SRT saved to: ${outputSrtPath2}` };
|
|
276595
276872
|
}
|
|
@@ -276626,9 +276903,9 @@ SRT saved to: ${outputSrtPath2}` };
|
|
|
276626
276903
|
const outputDir2 = dirname31(outputPath);
|
|
276627
276904
|
const outputSrtPath2 = join69(
|
|
276628
276905
|
outputDir2,
|
|
276629
|
-
basename10(outputPath,
|
|
276906
|
+
basename10(outputPath, extname14(outputPath)) + ".srt"
|
|
276630
276907
|
);
|
|
276631
|
-
await
|
|
276908
|
+
await writeFile26(outputSrtPath2, srtContent);
|
|
276632
276909
|
return {
|
|
276633
276910
|
success: false,
|
|
276634
276911
|
error: `${renderResult.error}
|
|
@@ -276639,9 +276916,9 @@ SRT saved to: ${outputSrtPath2}`
|
|
|
276639
276916
|
const outputDir = dirname31(outputPath);
|
|
276640
276917
|
const outputSrtPath = join69(
|
|
276641
276918
|
outputDir,
|
|
276642
|
-
basename10(outputPath,
|
|
276919
|
+
basename10(outputPath, extname14(outputPath)) + ".srt"
|
|
276643
276920
|
);
|
|
276644
|
-
await
|
|
276921
|
+
await writeFile26(outputSrtPath, srtContent);
|
|
276645
276922
|
return {
|
|
276646
276923
|
success: true,
|
|
276647
276924
|
outputPath,
|
|
@@ -276650,8 +276927,8 @@ SRT saved to: ${outputSrtPath2}`
|
|
|
276650
276927
|
};
|
|
276651
276928
|
} finally {
|
|
276652
276929
|
try {
|
|
276653
|
-
const { rm:
|
|
276654
|
-
await
|
|
276930
|
+
const { rm: rm11 } = await import("node:fs/promises");
|
|
276931
|
+
await rm11(tmpDir, { recursive: true, force: true });
|
|
276655
276932
|
} catch {
|
|
276656
276933
|
}
|
|
276657
276934
|
}
|
|
@@ -276812,7 +277089,7 @@ var init_fade = __esm({
|
|
|
276812
277089
|
|
|
276813
277090
|
// ../cli/src/commands/_shared/edit/translate-srt.ts
|
|
276814
277091
|
import { existsSync as existsSync65 } from "node:fs";
|
|
276815
|
-
import { readFile as readFile25, writeFile as
|
|
277092
|
+
import { readFile as readFile25, writeFile as writeFile27 } from "node:fs/promises";
|
|
276816
277093
|
async function executeTranslateSrt(options) {
|
|
276817
277094
|
const {
|
|
276818
277095
|
srtPath,
|
|
@@ -276855,15 +277132,14 @@ ${textsToTranslate}`;
|
|
|
276855
277132
|
Authorization: `Bearer ${openaiKey}`
|
|
276856
277133
|
},
|
|
276857
277134
|
body: JSON.stringify({
|
|
276858
|
-
model: "
|
|
276859
|
-
messages: [{ role: "user", content: translatePrompt }]
|
|
276860
|
-
temperature: 0.3
|
|
277135
|
+
model: defaultModel("openai", "llm").id,
|
|
277136
|
+
messages: [{ role: "user", content: translatePrompt }]
|
|
276861
277137
|
})
|
|
276862
277138
|
});
|
|
276863
277139
|
if (!response.ok) {
|
|
276864
277140
|
return {
|
|
276865
277141
|
success: false,
|
|
276866
|
-
error: `OpenAI API error: ${response.status} ${response.statusText}`
|
|
277142
|
+
error: `OpenAI API error: ${response.status} ${response.statusText}: ${await response.text()}`
|
|
276867
277143
|
};
|
|
276868
277144
|
}
|
|
276869
277145
|
const data2 = await response.json();
|
|
@@ -276884,15 +277160,15 @@ ${textsToTranslate}`;
|
|
|
276884
277160
|
"anthropic-version": "2023-06-01"
|
|
276885
277161
|
},
|
|
276886
277162
|
body: JSON.stringify({
|
|
276887
|
-
model: "claude
|
|
276888
|
-
max_tokens:
|
|
277163
|
+
model: defaultModel("claude", "llm").id,
|
|
277164
|
+
max_tokens: 16e3,
|
|
276889
277165
|
messages: [{ role: "user", content: translatePrompt }]
|
|
276890
277166
|
})
|
|
276891
277167
|
});
|
|
276892
277168
|
if (!response.ok) {
|
|
276893
277169
|
return {
|
|
276894
277170
|
success: false,
|
|
276895
|
-
error: `Claude API error: ${response.status} ${response.statusText}`
|
|
277171
|
+
error: `Claude API error: ${response.status} ${response.statusText}: ${await response.text()}`
|
|
276896
277172
|
};
|
|
276897
277173
|
}
|
|
276898
277174
|
const data2 = await response.json();
|
|
@@ -276916,7 +277192,7 @@ ${textsToTranslate}`;
|
|
|
276916
277192
|
}
|
|
276917
277193
|
}
|
|
276918
277194
|
const translatedSrt = formatSRT(translatedSegments);
|
|
276919
|
-
await
|
|
277195
|
+
await writeFile27(outputPath, translatedSrt);
|
|
276920
277196
|
return {
|
|
276921
277197
|
success: true,
|
|
276922
277198
|
outputPath,
|
|
@@ -276935,6 +277211,7 @@ var init_translate_srt = __esm({
|
|
|
276935
277211
|
"../cli/src/commands/_shared/edit/translate-srt.ts"() {
|
|
276936
277212
|
"use strict";
|
|
276937
277213
|
init_subtitle();
|
|
277214
|
+
init_dist();
|
|
276938
277215
|
}
|
|
276939
277216
|
});
|
|
276940
277217
|
|
|
@@ -277168,7 +277445,7 @@ var init_ai_edit = __esm({
|
|
|
277168
277445
|
});
|
|
277169
277446
|
|
|
277170
277447
|
// ../cli/src/commands/ai-edit-cli.ts
|
|
277171
|
-
import { resolve as resolve45, extname as
|
|
277448
|
+
import { resolve as resolve45, extname as extname15, basename as basename11 } from "node:path";
|
|
277172
277449
|
import { existsSync as existsSync67 } from "node:fs";
|
|
277173
277450
|
function registerEditCommands(aiCommand) {
|
|
277174
277451
|
aiCommand.command("silence-cut").alias("sc").description("Remove silent segments from video (FFmpeg default, or Gemini for smart detection)").argument("<video>", "Video file path").option("-o, --output <path>", "Output file path (default: <name>-cut.<ext>)").option("--noise <dB>", "Silence threshold in dB (default: -30)", "-30").option("-d, --min-duration <seconds>", "Minimum silence duration to cut (default: 0.5)", "0.5").option("--padding <seconds>", "Padding around non-silent segments (default: 0.1)", "0.1").option("--analyze-only", "(deprecated - use `vibe detect silence`) Only detect silence, don't cut").option("--use-gemini", "Use Gemini Video Understanding for context-aware silence detection").option("-m, --model <model>", "Gemini model (default: flash)").option("--low-res", "Low resolution mode for longer videos (Gemini only)").option("-k, --api-key <key>", "Google API key override (or set GOOGLE_API_KEY env)").option("--dry-run", "Preview parameters without executing").addHelpText("after", `
|
|
@@ -277192,7 +277469,7 @@ No API key needed (FFmpeg only). Use --use-gemini for smart detection (requires
|
|
|
277192
277469
|
if (!commandExists("ffmpeg")) {
|
|
277193
277470
|
exitWithError(generalError("FFmpeg not found. Install with: brew install ffmpeg (macOS) or apt install ffmpeg (Linux). Run `vibe doctor` for details."));
|
|
277194
277471
|
}
|
|
277195
|
-
const ext =
|
|
277472
|
+
const ext = extname15(videoPath);
|
|
277196
277473
|
const name = basename11(videoPath, ext);
|
|
277197
277474
|
const outputPath = options.output || `${name}-cut${ext}`;
|
|
277198
277475
|
const useGemini = options.useGemini || false;
|
|
@@ -277322,7 +277599,7 @@ Requires: OPENAI_API_KEY (Whisper transcription) + FFmpeg`).action(async (videoP
|
|
|
277322
277599
|
if (!apiKey) {
|
|
277323
277600
|
exitWithError(authError("OPENAI_API_KEY", "OpenAI"));
|
|
277324
277601
|
}
|
|
277325
|
-
const ext =
|
|
277602
|
+
const ext = extname15(videoPath);
|
|
277326
277603
|
const name = basename11(videoPath, ext);
|
|
277327
277604
|
const outputPath = options.output || `${name}-captioned${ext}`;
|
|
277328
277605
|
const spinner2 = ora("Starting caption process...").start();
|
|
@@ -277396,7 +277673,7 @@ Requires: OPENAI_API_KEY (Whisper transcription) + FFmpeg`).action(async (videoP
|
|
|
277396
277673
|
});
|
|
277397
277674
|
return;
|
|
277398
277675
|
}
|
|
277399
|
-
const ext =
|
|
277676
|
+
const ext = extname15(inputPath);
|
|
277400
277677
|
const name = basename11(inputPath, ext);
|
|
277401
277678
|
const outputPath = options.output || `${name}-denoised${ext}`;
|
|
277402
277679
|
const spinner2 = ora("Applying noise reduction...").start();
|
|
@@ -277464,7 +277741,7 @@ Requires: OPENAI_API_KEY (Whisper transcription) + FFmpeg`).action(async (videoP
|
|
|
277464
277741
|
});
|
|
277465
277742
|
return;
|
|
277466
277743
|
}
|
|
277467
|
-
const ext =
|
|
277744
|
+
const ext = extname15(videoPath);
|
|
277468
277745
|
const name = basename11(videoPath, ext);
|
|
277469
277746
|
const outputPath = options.output || `${name}-faded${ext}`;
|
|
277470
277747
|
const spinner2 = ora("Applying fade effects...").start();
|
|
@@ -277542,7 +277819,7 @@ Requires: OPENAI_API_KEY (Whisper transcription) + FFmpeg`).action(async (videoP
|
|
|
277542
277819
|
if (!apiKey) {
|
|
277543
277820
|
exitWithError(authError(envKey, providerName));
|
|
277544
277821
|
}
|
|
277545
|
-
const ext =
|
|
277822
|
+
const ext = extname15(srtPath);
|
|
277546
277823
|
const name = basename11(srtPath, ext);
|
|
277547
277824
|
const outputPath = options.output || `${name}-${options.target}${ext}`;
|
|
277548
277825
|
const spinner2 = ora(`Translating to ${options.target}...`).start();
|
|
@@ -277620,7 +277897,7 @@ Requires: OPENAI_API_KEY (Whisper transcription) + FFmpeg`).action(async (videoP
|
|
|
277620
277897
|
if (!apiKey) {
|
|
277621
277898
|
exitWithError(authError("OPENAI_API_KEY", "OpenAI"));
|
|
277622
277899
|
}
|
|
277623
|
-
const ext =
|
|
277900
|
+
const ext = extname15(videoPath);
|
|
277624
277901
|
const name = basename11(videoPath, ext);
|
|
277625
277902
|
const outputPath = options.output || `${name}-jumpcut${ext}`;
|
|
277626
277903
|
const fillers = options.fillers ? options.fillers.split(",").map((f2) => f2.trim()) : void 0;
|
|
@@ -278080,7 +278357,7 @@ var init_project_resolver = __esm({
|
|
|
278080
278357
|
|
|
278081
278358
|
// ../cli/src/commands/_shared/execute-fill-gaps.ts
|
|
278082
278359
|
import { existsSync as existsSync68 } from "node:fs";
|
|
278083
|
-
import { readFile as readFile26, writeFile as
|
|
278360
|
+
import { readFile as readFile26, writeFile as writeFile28, mkdir as mkdir20, rename as renameFs } from "node:fs/promises";
|
|
278084
278361
|
import { resolve as resolve47, dirname as dirname32 } from "node:path";
|
|
278085
278362
|
function detectVideoGaps(videoClips, totalDuration) {
|
|
278086
278363
|
const gaps = [];
|
|
@@ -278135,22 +278412,13 @@ function analyzeGapFillability(gaps, videoClips, sources) {
|
|
|
278135
278412
|
return { gap, canExtendBefore, canExtendAfter, remainingGap, gapStart };
|
|
278136
278413
|
});
|
|
278137
278414
|
}
|
|
278138
|
-
async function
|
|
278415
|
+
async function uploadFrame(host, framePath) {
|
|
278139
278416
|
try {
|
|
278140
|
-
const
|
|
278141
|
-
|
|
278142
|
-
|
|
278143
|
-
formData.append("key", imgbbApiKey);
|
|
278144
|
-
formData.append("image", frameBase64);
|
|
278145
|
-
const response = await fetch("https://api.imgbb.com/1/upload", {
|
|
278146
|
-
method: "POST",
|
|
278147
|
-
body: formData
|
|
278417
|
+
const upload = await host.uploadImage(await readFile26(framePath), {
|
|
278418
|
+
filename: framePath,
|
|
278419
|
+
mimeType: "image/png"
|
|
278148
278420
|
});
|
|
278149
|
-
|
|
278150
|
-
if (!data2.success || !data2.data?.url) {
|
|
278151
|
-
return { error: data2.error?.message || "Upload failed" };
|
|
278152
|
-
}
|
|
278153
|
-
return { url: data2.data.url };
|
|
278421
|
+
return { url: upload.url };
|
|
278154
278422
|
} catch (err) {
|
|
278155
278423
|
return { error: err instanceof Error ? err.message : String(err) };
|
|
278156
278424
|
}
|
|
@@ -278291,21 +278559,23 @@ async function executeFillGaps(options) {
|
|
|
278291
278559
|
if (!kling.isConfigured()) {
|
|
278292
278560
|
return {
|
|
278293
278561
|
success: false,
|
|
278294
|
-
error: "Invalid KLING_API_KEY (
|
|
278562
|
+
error: "Invalid KLING_API_KEY (set your Kling API key, or the legacy ACCESS_KEY:SECRET_KEY pair)",
|
|
278295
278563
|
humanLines
|
|
278296
278564
|
};
|
|
278297
278565
|
}
|
|
278298
278566
|
const projectDir = dirname32(filePath);
|
|
278299
278567
|
const footageDir = options.dir ? resolve47(process.cwd(), options.dir) : resolve47(projectDir, "footage");
|
|
278300
278568
|
if (!existsSync68(footageDir)) {
|
|
278301
|
-
await
|
|
278569
|
+
await mkdir20(footageDir, { recursive: true });
|
|
278302
278570
|
}
|
|
278303
278571
|
humanLines.push("Generating AI Videos");
|
|
278304
|
-
|
|
278305
|
-
|
|
278572
|
+
let uploadHost;
|
|
278573
|
+
try {
|
|
278574
|
+
uploadHost = await resolveUploadHost();
|
|
278575
|
+
} catch (err) {
|
|
278306
278576
|
return {
|
|
278307
278577
|
success: false,
|
|
278308
|
-
error:
|
|
278578
|
+
error: err instanceof Error ? err.message : String(err),
|
|
278309
278579
|
humanLines
|
|
278310
278580
|
};
|
|
278311
278581
|
}
|
|
@@ -278349,12 +278619,12 @@ async function executeFillGaps(options) {
|
|
|
278349
278619
|
humanLines
|
|
278350
278620
|
};
|
|
278351
278621
|
}
|
|
278352
|
-
onProgress(
|
|
278353
|
-
const upload = await
|
|
278622
|
+
onProgress(`Uploading frame via ${uploadHost.provider}...`);
|
|
278623
|
+
const upload = await uploadFrame(uploadHost, framePath);
|
|
278354
278624
|
if (!upload.url) {
|
|
278355
278625
|
return {
|
|
278356
278626
|
success: false,
|
|
278357
|
-
error: `Failed to upload frame
|
|
278627
|
+
error: `Failed to upload frame via ${uploadHost.provider}: ${upload.error || "unknown"}`,
|
|
278358
278628
|
humanLines
|
|
278359
278629
|
};
|
|
278360
278630
|
}
|
|
@@ -278363,13 +278633,13 @@ async function executeFillGaps(options) {
|
|
|
278363
278633
|
let generatedDuration = 0;
|
|
278364
278634
|
const generatedVideos = [];
|
|
278365
278635
|
const initialDuration = Math.min(10, targetDuration);
|
|
278366
|
-
const
|
|
278367
|
-
onProgress(`Generating ${
|
|
278636
|
+
const klingDuration2 = initialDuration > 5 ? "10" : "5";
|
|
278637
|
+
onProgress(`Generating ${klingDuration2}s video with Kling...`);
|
|
278368
278638
|
const prompt3 = options.prompt || "Continue the scene naturally with subtle motion";
|
|
278369
278639
|
const result = await kling.generateVideo(prompt3, {
|
|
278370
278640
|
prompt: prompt3,
|
|
278371
278641
|
referenceImage: frameUrl,
|
|
278372
|
-
duration: parseInt(
|
|
278642
|
+
duration: parseInt(klingDuration2),
|
|
278373
278643
|
aspectRatio: options.ratio || "16:9",
|
|
278374
278644
|
mode: options.mode || "std"
|
|
278375
278645
|
});
|
|
@@ -278392,8 +278662,8 @@ async function executeFillGaps(options) {
|
|
|
278392
278662
|
const videoPath = resolve47(footageDir, videoFileName);
|
|
278393
278663
|
onProgress("Downloading generated video...");
|
|
278394
278664
|
const videoBuffer = await downloadVideo(finalResult.videoUrl);
|
|
278395
|
-
await
|
|
278396
|
-
generatedDuration = finalResult.duration || parseInt(
|
|
278665
|
+
await writeFile28(videoPath, videoBuffer);
|
|
278666
|
+
generatedDuration = finalResult.duration || parseInt(klingDuration2);
|
|
278397
278667
|
generatedVideos.push(videoPath);
|
|
278398
278668
|
humanLines.push(` Generated: ${videoFileName} (${generatedDuration}s)`);
|
|
278399
278669
|
let segmentIndex = 1;
|
|
@@ -278429,7 +278699,7 @@ async function executeFillGaps(options) {
|
|
|
278429
278699
|
humanLines.push(" Failed to extract frame for continuation");
|
|
278430
278700
|
break;
|
|
278431
278701
|
}
|
|
278432
|
-
const extUpload = await
|
|
278702
|
+
const extUpload = await uploadFrame(uploadHost, lastFramePath);
|
|
278433
278703
|
if (!extUpload.url) {
|
|
278434
278704
|
humanLines.push(" Failed to upload continuation frame");
|
|
278435
278705
|
break;
|
|
@@ -278462,11 +278732,11 @@ async function executeFillGaps(options) {
|
|
|
278462
278732
|
`gap-fill-${gap.start.toFixed(2)}-${gap.end.toFixed(2)}-seg${segmentIndex}.mp4`
|
|
278463
278733
|
);
|
|
278464
278734
|
const segVideoBuffer = await downloadVideo(segFinalResult.videoUrl);
|
|
278465
|
-
await
|
|
278735
|
+
await writeFile28(segVideoPath, segVideoBuffer);
|
|
278466
278736
|
const concatListPath = resolve47(footageDir, `concat-${gap.start.toFixed(2)}.txt`);
|
|
278467
278737
|
const concatList = generatedVideos.map((v4) => `file '${v4}'`).join("\n") + `
|
|
278468
278738
|
file '${segVideoPath}'`;
|
|
278469
|
-
await
|
|
278739
|
+
await writeFile28(concatListPath, concatList);
|
|
278470
278740
|
const concatOutputPath = resolve47(
|
|
278471
278741
|
footageDir,
|
|
278472
278742
|
`gap-fill-${gap.start.toFixed(2)}-${gap.end.toFixed(2)}-merged.mp4`
|
|
@@ -278524,7 +278794,7 @@ file '${segVideoPath}'`;
|
|
|
278524
278794
|
let outputPath = filePath;
|
|
278525
278795
|
if (generatedCount > 0) {
|
|
278526
278796
|
outputPath = options.output ? resolve47(process.cwd(), options.output) : filePath;
|
|
278527
|
-
await
|
|
278797
|
+
await writeFile28(outputPath, JSON.stringify(project.toJSON(), null, 2));
|
|
278528
278798
|
humanLines.push(`\u2714 Filled ${generatedCount} gap(s) with AI-generated video`);
|
|
278529
278799
|
humanLines.push(`Project saved: ${outputPath}`);
|
|
278530
278800
|
} else {
|
|
@@ -278552,6 +278822,7 @@ var init_execute_fill_gaps = __esm({
|
|
|
278552
278822
|
init_dist();
|
|
278553
278823
|
init_engine();
|
|
278554
278824
|
init_api_key();
|
|
278825
|
+
init_upload_host();
|
|
278555
278826
|
init_exec_safe();
|
|
278556
278827
|
init_project_resolver();
|
|
278557
278828
|
init_ai_helpers();
|
|
@@ -278618,7 +278889,14 @@ __export(ai_motion_exports, {
|
|
|
278618
278889
|
});
|
|
278619
278890
|
import { resolve as resolve48 } from "node:path";
|
|
278620
278891
|
import { existsSync as existsSync69 } from "node:fs";
|
|
278621
|
-
import { readFile as readFile27, writeFile as
|
|
278892
|
+
import { readFile as readFile27, writeFile as writeFile29 } from "node:fs/promises";
|
|
278893
|
+
function resolveMotionModel(alias) {
|
|
278894
|
+
const claude = findModel("claude", "llm", alias);
|
|
278895
|
+
if (claude) return { provider: "claude", modelId: claude.id };
|
|
278896
|
+
const gemini = findModel("gemini", "llm", alias);
|
|
278897
|
+
if (gemini) return { provider: "gemini", modelId: gemini.id };
|
|
278898
|
+
return { provider: "claude", modelId: defaultModel("claude", "llm").id };
|
|
278899
|
+
}
|
|
278622
278900
|
async function getOptionalGoogleApiKey() {
|
|
278623
278901
|
const configKey = await getApiKeyFromConfig("google");
|
|
278624
278902
|
if (configKey) return configKey;
|
|
@@ -278633,7 +278911,7 @@ function normalizeUnderstand(value) {
|
|
|
278633
278911
|
}
|
|
278634
278912
|
async function executeMotion(options) {
|
|
278635
278913
|
const modelAlias = options.model || "sonnet";
|
|
278636
|
-
const modelConfig =
|
|
278914
|
+
const modelConfig = resolveMotionModel(modelAlias);
|
|
278637
278915
|
const useGemini = modelConfig.provider === "gemini";
|
|
278638
278916
|
const width = options.width || 1920;
|
|
278639
278917
|
const height = options.height || 1080;
|
|
@@ -278788,7 +279066,7 @@ Use this video understanding to place motion graphics in safe zones, match the c
|
|
|
278788
279066
|
const defaultOutput = options.video || options.image ? "motion-output.mp4" : options.render ? "motion.webm" : "motion.tsx";
|
|
278789
279067
|
const outputPath = resolve48(process.cwd(), options.output || defaultOutput);
|
|
278790
279068
|
const codePath = outputPath.replace(/\.\w+$/, ".tsx");
|
|
278791
|
-
await
|
|
279069
|
+
await writeFile29(codePath, component.code, "utf-8");
|
|
278792
279070
|
const shouldRender = options.render || !!options.video || !!options.image;
|
|
278793
279071
|
if (!shouldRender) {
|
|
278794
279072
|
return { success: true, codePath, componentName: component.name };
|
|
@@ -279012,7 +279290,6 @@ function registerMotionCommand(aiCommand) {
|
|
|
279012
279290
|
}
|
|
279013
279291
|
});
|
|
279014
279292
|
}
|
|
279015
|
-
var MODEL_MAP2;
|
|
279016
279293
|
var init_ai_motion = __esm({
|
|
279017
279294
|
"../cli/src/commands/ai-motion.ts"() {
|
|
279018
279295
|
"use strict";
|
|
@@ -279023,14 +279300,6 @@ var init_ai_motion = __esm({
|
|
|
279023
279300
|
init_config();
|
|
279024
279301
|
init_output();
|
|
279025
279302
|
init_validate();
|
|
279026
|
-
MODEL_MAP2 = {
|
|
279027
|
-
sonnet: { provider: "claude", modelId: "claude-sonnet-4-6" },
|
|
279028
|
-
opus: { provider: "claude", modelId: "claude-opus-4-7" },
|
|
279029
|
-
"opus-4-6": { provider: "claude", modelId: "claude-opus-4-6" },
|
|
279030
|
-
gemini: { provider: "gemini", modelId: GEMINI_DEFAULT_TEXT_MODEL },
|
|
279031
|
-
"gemini-2.5-pro": { provider: "gemini", modelId: "gemini-2.5-pro" },
|
|
279032
|
-
"gemini-3.1-pro": { provider: "gemini", modelId: "gemini-3.1-pro-preview" }
|
|
279033
|
-
};
|
|
279034
279303
|
}
|
|
279035
279304
|
});
|
|
279036
279305
|
|
|
@@ -279267,7 +279536,7 @@ __export(project_builder_exports, {
|
|
|
279267
279536
|
buildTempProject: () => buildTempProject,
|
|
279268
279537
|
resolveSourceUrl: () => resolveSourceUrl
|
|
279269
279538
|
});
|
|
279270
|
-
import { mkdtemp as mkdtemp5, mkdir as
|
|
279539
|
+
import { mkdtemp as mkdtemp5, mkdir as mkdir21, copyFile as copyFile6, writeFile as writeFile30, rm as rm9, readdir as readdir7 } from "node:fs/promises";
|
|
279271
279540
|
import { existsSync as existsSync70 } from "node:fs";
|
|
279272
279541
|
import { tmpdir as tmpdir10 } from "node:os";
|
|
279273
279542
|
import { createRequire as createRequire4 } from "node:module";
|
|
@@ -279275,7 +279544,7 @@ import * as path15 from "node:path";
|
|
|
279275
279544
|
async function buildTempProject(state, projectFileDir) {
|
|
279276
279545
|
const dir = await mkdtemp5(path15.join(tmpdir10(), "vibeframe-hf-"));
|
|
279277
279546
|
const assetsDir = path15.join(dir, "assets");
|
|
279278
|
-
await
|
|
279547
|
+
await mkdir21(assetsDir, { recursive: true });
|
|
279279
279548
|
const copied = /* @__PURE__ */ new Map();
|
|
279280
279549
|
for (const source3 of state.sources) {
|
|
279281
279550
|
if (copied.has(source3.id)) continue;
|
|
@@ -279291,10 +279560,10 @@ async function buildTempProject(state, projectFileDir) {
|
|
|
279291
279560
|
await copyLottieRuntime(dir);
|
|
279292
279561
|
}
|
|
279293
279562
|
const html = generateCompositionHtml(state);
|
|
279294
|
-
await
|
|
279563
|
+
await writeFile30(path15.join(dir, "index.html"), html, "utf-8");
|
|
279295
279564
|
return {
|
|
279296
279565
|
dir,
|
|
279297
|
-
cleanup: () =>
|
|
279566
|
+
cleanup: () => rm9(dir, { recursive: true, force: true })
|
|
279298
279567
|
};
|
|
279299
279568
|
}
|
|
279300
279569
|
async function copyLottieRuntime(tempDir) {
|
|
@@ -279305,7 +279574,7 @@ async function copyLottieRuntime(tempDir) {
|
|
|
279305
279574
|
const wasmSrc = path15.join(path15.dirname(webEntry), "dotlottie-player.wasm");
|
|
279306
279575
|
const vendorDir = path15.join(tempDir, "vendor");
|
|
279307
279576
|
const wcDest = path15.join(vendorDir, "dotlottie-wc");
|
|
279308
|
-
await
|
|
279577
|
+
await mkdir21(wcDest, { recursive: true });
|
|
279309
279578
|
for (const file of await readdir7(wcDistDir)) {
|
|
279310
279579
|
if (file.endsWith(".map") || file.endsWith(".d.ts")) continue;
|
|
279311
279580
|
await copyFile6(path15.join(wcDistDir, file), path15.join(wcDest, file));
|
|
@@ -279413,9 +279682,9 @@ __export(motion_overlay_exports, {
|
|
|
279413
279682
|
executeMotionOverlay: () => executeMotionOverlay,
|
|
279414
279683
|
registerMotionOverlayCommand: () => registerMotionOverlayCommand
|
|
279415
279684
|
});
|
|
279416
|
-
import { mkdir as
|
|
279685
|
+
import { mkdir as mkdir23 } from "node:fs/promises";
|
|
279417
279686
|
import { existsSync as existsSync71 } from "node:fs";
|
|
279418
|
-
import { basename as basename13, dirname as dirname34, extname as
|
|
279687
|
+
import { basename as basename13, dirname as dirname34, extname as extname16, resolve as resolve50 } from "node:path";
|
|
279419
279688
|
function normalizeUnderstand2(value) {
|
|
279420
279689
|
return value === "off" || value === "required" || value === "auto" ? value : "auto";
|
|
279421
279690
|
}
|
|
@@ -279438,7 +279707,7 @@ function assertValidRequest(options) {
|
|
|
279438
279707
|
return "Provide a motion description, or pass --asset <logo.json|logo.lottie>.";
|
|
279439
279708
|
}
|
|
279440
279709
|
if (hasAsset) {
|
|
279441
|
-
const ext =
|
|
279710
|
+
const ext = extname16(options.asset).toLowerCase();
|
|
279442
279711
|
if (ext !== ".json" && ext !== ".lottie") {
|
|
279443
279712
|
return "Lottie overlay asset must be a .json or .lottie file.";
|
|
279444
279713
|
}
|
|
@@ -279561,7 +279830,7 @@ async function executeMotionOverlay(options) {
|
|
|
279561
279830
|
const scale = Math.max(0.01, Math.min(2, numberOption(options.scale, position === "full" ? 1 : 0.25)));
|
|
279562
279831
|
const opacity = Math.max(0, Math.min(1, numberOption(options.opacity, 1)));
|
|
279563
279832
|
const loop = options.loop ?? true;
|
|
279564
|
-
await
|
|
279833
|
+
await mkdir23(dirname34(outputPath), { recursive: true });
|
|
279565
279834
|
const backend = createHyperframesBackend();
|
|
279566
279835
|
const result2 = await backend.render({
|
|
279567
279836
|
projectState: buildLottieTimelineState({
|
|
@@ -279587,7 +279856,7 @@ async function executeMotionOverlay(options) {
|
|
|
279587
279856
|
return { success: true, outputPath, provider: "lottie" };
|
|
279588
279857
|
}
|
|
279589
279858
|
const duration = options.duration ?? await ffprobeDuration(absVideo).catch(() => void 0);
|
|
279590
|
-
await
|
|
279859
|
+
await mkdir23(dirname34(outputPath), { recursive: true });
|
|
279591
279860
|
const result = await executeMotion({
|
|
279592
279861
|
description: options.description.trim(),
|
|
279593
279862
|
video: absVideo,
|
|
@@ -279716,7 +279985,7 @@ __export(edit_cmd_exports, {
|
|
|
279716
279985
|
executeUpscale: () => executeUpscale
|
|
279717
279986
|
});
|
|
279718
279987
|
import { resolve as resolve51, dirname as dirname35 } from "node:path";
|
|
279719
|
-
import { readFile as readFile28, writeFile as
|
|
279988
|
+
import { readFile as readFile28, writeFile as writeFile31, mkdir as mkdir24 } from "node:fs/promises";
|
|
279720
279989
|
async function executeGrade(options) {
|
|
279721
279990
|
const { videoPath, style, preset: preset3, output: output3, analyzeOnly, apiKey } = options;
|
|
279722
279991
|
try {
|
|
@@ -279909,6 +280178,7 @@ var init_edit_cmd = __esm({
|
|
|
279909
280178
|
init_output();
|
|
279910
280179
|
init_validate();
|
|
279911
280180
|
init_cost_tier();
|
|
280181
|
+
init_image_file();
|
|
279912
280182
|
editCommand = new Command("edit").alias("ed").description(
|
|
279913
280183
|
"Edit and post-process media (silence-cut, caption, grade, reframe, upscale...)"
|
|
279914
280184
|
).addHelpText(
|
|
@@ -280344,7 +280614,7 @@ Run 'vibe schema edit.<command>' for structured parameter info.
|
|
|
280344
280614
|
console.log();
|
|
280345
280615
|
if (options.keyframes) {
|
|
280346
280616
|
const keyframesPath = resolve51(process.cwd(), options.keyframes);
|
|
280347
|
-
await
|
|
280617
|
+
await writeFile31(keyframesPath, JSON.stringify(cropKeyframes, null, 2));
|
|
280348
280618
|
console.log(source_default.green(`Keyframes saved to: ${keyframesPath}`));
|
|
280349
280619
|
}
|
|
280350
280620
|
if (options.analyzeOnly) {
|
|
@@ -280368,7 +280638,7 @@ Run 'vibe schema edit.<command>' for structured parameter info.
|
|
|
280368
280638
|
exitWithError(generalError(`Reframe failed: ${msg}`));
|
|
280369
280639
|
}
|
|
280370
280640
|
});
|
|
280371
|
-
editCommand.command("image").description("Edit image(s) using AI (Gemini, OpenAI, or Grok)").argument("<images...>", "Input image file(s) followed by edit prompt").option("-p, --provider <provider>", "Provider: gemini (default), openai, grok", "gemini").option("-k, --api-key <key>", "API key (or set env variable)").option("-o, --output <path>", "Output file path", "edited.png").option("-m, --model <model>", "Model: flash
|
|
280641
|
+
editCommand.command("image").description("Edit image(s) using AI (Gemini, OpenAI, or Grok)").argument("<images...>", "Input image file(s) followed by edit prompt").option("-p, --provider <provider>", "Provider: gemini (default), openai, grok", "gemini").option("-k, --api-key <key>", "API key (or set env variable)").option("-o, --output <path>", "Output file path", "edited.png").option("-m, --model <model>", "Model: flash, lite, pro (Gemini); pro (Grok)", "flash").option("-r, --ratio <ratio>", "Output aspect ratio").option("--size <resolution>", "Resolution: 1K, 2K, 4K (Gemini Pro only)").option("--dry-run", "Preview parameters without executing").action(async (args, options) => {
|
|
280372
280642
|
const startedAt = Date.now();
|
|
280373
280643
|
try {
|
|
280374
280644
|
if (args.length < 2) {
|
|
@@ -280427,14 +280697,16 @@ Run 'vibe schema edit.<command>' for structured parameter info.
|
|
|
280427
280697
|
const grok = new GrokProvider();
|
|
280428
280698
|
await grok.initialize({ apiKey });
|
|
280429
280699
|
result = await grok.editImage(imageBuffers[0], prompt3, {
|
|
280700
|
+
...resolveGrokImageModel(options.model),
|
|
280430
280701
|
aspectRatio: options.ratio
|
|
280431
280702
|
});
|
|
280432
280703
|
} else {
|
|
280433
280704
|
const editModelNames = {
|
|
280434
|
-
flash: "gemini-
|
|
280435
|
-
"3.1-flash": "gemini-3.1-flash-image
|
|
280436
|
-
latest: "gemini-3.1-flash-image
|
|
280437
|
-
|
|
280705
|
+
flash: "gemini-3.1-flash-image",
|
|
280706
|
+
"3.1-flash": "gemini-3.1-flash-image",
|
|
280707
|
+
latest: "gemini-3.1-flash-image",
|
|
280708
|
+
lite: "gemini-3.1-flash-lite-image",
|
|
280709
|
+
pro: "gemini-3-pro-image"
|
|
280438
280710
|
};
|
|
280439
280711
|
const editModelName = editModelNames[options.model] || editModelNames.flash;
|
|
280440
280712
|
spinner2.text = `Editing with ${editModelName}...`;
|
|
@@ -280445,15 +280717,6 @@ Run 'vibe schema edit.<command>' for structured parameter info.
|
|
|
280445
280717
|
aspectRatio: options.ratio,
|
|
280446
280718
|
resolution: options.size
|
|
280447
280719
|
});
|
|
280448
|
-
const fallbackModels = ["latest", "3.1-flash"];
|
|
280449
|
-
if (!result.success && fallbackModels.includes(options.model)) {
|
|
280450
|
-
spinner2.text = `${source_default.dim(result.error || `${editModelName} failed`)} \u2014 retrying with flash...`;
|
|
280451
|
-
result = await gemini.editImage(imageBuffers, prompt3, {
|
|
280452
|
-
model: "flash",
|
|
280453
|
-
aspectRatio: options.ratio,
|
|
280454
|
-
resolution: options.size
|
|
280455
|
-
});
|
|
280456
|
-
}
|
|
280457
280720
|
}
|
|
280458
280721
|
if (!result.success || !result.images || result.images.length === 0) {
|
|
280459
280722
|
spinner2.fail(result.error || "Image editing failed");
|
|
@@ -280463,14 +280726,14 @@ Run 'vibe schema edit.<command>' for structured parameter info.
|
|
|
280463
280726
|
const img = result.images[0];
|
|
280464
280727
|
const outputPath = resolve51(process.cwd(), options.output);
|
|
280465
280728
|
const saveImage = async () => {
|
|
280466
|
-
await
|
|
280729
|
+
await mkdir24(dirname35(outputPath), { recursive: true });
|
|
280467
280730
|
if (img.base64) {
|
|
280468
280731
|
const buffer = Buffer.from(img.base64, "base64");
|
|
280469
|
-
await
|
|
280732
|
+
await writeImageFile(outputPath, buffer);
|
|
280470
280733
|
} else if (img.url) {
|
|
280471
280734
|
const resp = await fetch(img.url);
|
|
280472
280735
|
const arrayBuf = await resp.arrayBuffer();
|
|
280473
|
-
await
|
|
280736
|
+
await writeImageFile(outputPath, Buffer.from(arrayBuf));
|
|
280474
280737
|
}
|
|
280475
280738
|
};
|
|
280476
280739
|
const resultModel = result.model;
|
|
@@ -280690,7 +280953,7 @@ __export(ai_image_exports, {
|
|
|
280690
280953
|
executeThumbnailBestFrame: () => executeThumbnailBestFrame
|
|
280691
280954
|
});
|
|
280692
280955
|
import { resolve as resolve54, dirname as dirname37 } from "node:path";
|
|
280693
|
-
import { readFile as readFile29,
|
|
280956
|
+
import { readFile as readFile29, mkdir as mkdir26 } from "node:fs/promises";
|
|
280694
280957
|
import { existsSync as existsSync74 } from "node:fs";
|
|
280695
280958
|
async function executeImageGenerate(options) {
|
|
280696
280959
|
const {
|
|
@@ -280733,8 +280996,8 @@ async function executeImageGenerate(options) {
|
|
|
280733
280996
|
return { success: false, error: "No image data available" };
|
|
280734
280997
|
}
|
|
280735
280998
|
outputPath = resolve54(process.cwd(), output3);
|
|
280736
|
-
await
|
|
280737
|
-
await
|
|
280999
|
+
await mkdir26(dirname37(outputPath), { recursive: true });
|
|
281000
|
+
await writeImageFile(outputPath, buffer);
|
|
280738
281001
|
}
|
|
280739
281002
|
return {
|
|
280740
281003
|
success: true,
|
|
@@ -280768,8 +281031,8 @@ async function executeImageGenerate(options) {
|
|
|
280768
281031
|
const img = result.images[0];
|
|
280769
281032
|
if (img.base64) {
|
|
280770
281033
|
outputPath = resolve54(process.cwd(), output3);
|
|
280771
|
-
await
|
|
280772
|
-
await
|
|
281034
|
+
await mkdir26(dirname37(outputPath), { recursive: true });
|
|
281035
|
+
await writeImageFile(outputPath, Buffer.from(img.base64, "base64"));
|
|
280773
281036
|
}
|
|
280774
281037
|
}
|
|
280775
281038
|
return {
|
|
@@ -280782,10 +281045,11 @@ async function executeImageGenerate(options) {
|
|
|
280782
281045
|
} else if (provider === "grok") {
|
|
280783
281046
|
const key2 = apiKey || process.env.XAI_API_KEY;
|
|
280784
281047
|
if (!key2) return { success: false, error: "XAI_API_KEY required" };
|
|
280785
|
-
const
|
|
280786
|
-
await
|
|
280787
|
-
const result = await
|
|
280788
|
-
|
|
281048
|
+
const grok = new GrokProvider();
|
|
281049
|
+
await grok.initialize({ apiKey: key2 });
|
|
281050
|
+
const result = await grok.generateImage(prompt3, {
|
|
281051
|
+
...resolveGrokImageModel(model),
|
|
281052
|
+
aspectRatio: ratio,
|
|
280789
281053
|
n: count
|
|
280790
281054
|
});
|
|
280791
281055
|
if (!result.success || !result.images) {
|
|
@@ -280804,8 +281068,8 @@ async function executeImageGenerate(options) {
|
|
|
280804
281068
|
return { success: false, error: "No image data available" };
|
|
280805
281069
|
}
|
|
280806
281070
|
outputPath = resolve54(process.cwd(), output3);
|
|
280807
|
-
await
|
|
280808
|
-
await
|
|
281071
|
+
await mkdir26(dirname37(outputPath), { recursive: true });
|
|
281072
|
+
await writeImageFile(outputPath, buffer);
|
|
280809
281073
|
}
|
|
280810
281074
|
return {
|
|
280811
281075
|
success: true,
|
|
@@ -280863,8 +281127,8 @@ async function executeGeminiEdit(options) {
|
|
|
280863
281127
|
let outputPath;
|
|
280864
281128
|
if (img.base64) {
|
|
280865
281129
|
outputPath = resolve54(process.cwd(), output3);
|
|
280866
|
-
await
|
|
280867
|
-
await
|
|
281130
|
+
await mkdir26(dirname37(outputPath), { recursive: true });
|
|
281131
|
+
await writeImageFile(outputPath, Buffer.from(img.base64, "base64"));
|
|
280868
281132
|
}
|
|
280869
281133
|
return {
|
|
280870
281134
|
success: true,
|
|
@@ -280938,6 +281202,7 @@ var init_ai_image = __esm({
|
|
|
280938
281202
|
"use strict";
|
|
280939
281203
|
init_dist();
|
|
280940
281204
|
init_exec_safe();
|
|
281205
|
+
init_image_file();
|
|
280941
281206
|
}
|
|
280942
281207
|
});
|
|
280943
281208
|
|
|
@@ -280949,7 +281214,7 @@ __export(ai_analyze_exports, {
|
|
|
280949
281214
|
registerAnalyzeCommands: () => registerAnalyzeCommands
|
|
280950
281215
|
});
|
|
280951
281216
|
import { readFile as readFile30 } from "node:fs/promises";
|
|
280952
|
-
import { extname as
|
|
281217
|
+
import { extname as extname17, resolve as resolve55 } from "node:path";
|
|
280953
281218
|
import { existsSync as existsSync75 } from "node:fs";
|
|
280954
281219
|
async function executeGeminiVideo(options) {
|
|
280955
281220
|
try {
|
|
@@ -281006,7 +281271,7 @@ async function executeAnalyze(options) {
|
|
|
281006
281271
|
const isYouTube = source3.includes("youtube.com") || source3.includes("youtu.be");
|
|
281007
281272
|
const isImageUrl = /^https?:\/\/.+\.(png|jpg|jpeg|webp|gif)(\?.*)?$/i.test(source3);
|
|
281008
281273
|
const isVideoUrl = /^https?:\/\/.+\.(mp4|mov|webm)(\?.*)?$/i.test(source3);
|
|
281009
|
-
const ext =
|
|
281274
|
+
const ext = extname17(source3).toLowerCase();
|
|
281010
281275
|
const imageExts = [".png", ".jpg", ".jpeg", ".webp", ".gif"];
|
|
281011
281276
|
const videoExts = [".mp4", ".mov", ".webm", ".avi", ".mkv"];
|
|
281012
281277
|
const isLocalImage = imageExts.includes(ext);
|
|
@@ -281414,7 +281679,7 @@ async function executeSoundEffect(options) {
|
|
|
281414
281679
|
}
|
|
281415
281680
|
}
|
|
281416
281681
|
function registerSoundEffectCommand(parent) {
|
|
281417
|
-
parent.command("sound-effect").description("Generate sound effect using ElevenLabs").argument("<prompt>", "Description of the sound effect").option("-k, --api-key <key>", "ElevenLabs API key (or set ELEVENLABS_API_KEY env)").option("-o, --output <path>", "Output audio file path", "sound-effect.mp3").option("-d, --duration <seconds>", "Duration in seconds (0.5-
|
|
281682
|
+
parent.command("sound-effect").description("Generate sound effect using ElevenLabs").argument("<prompt>", "Description of the sound effect").option("-k, --api-key <key>", "ElevenLabs API key (or set ELEVENLABS_API_KEY env)").option("-o, --output <path>", "Output audio file path", "sound-effect.mp3").option("-d, --duration <seconds>", "Duration in seconds (0.5-30, default: auto)").option("--prompt-influence <value>", "Prompt influence (0-1, default: 0.3)").option("--dry-run", "Preview parameters without executing").action(async (prompt3, options) => {
|
|
281418
281683
|
const startedAt = Date.now();
|
|
281419
281684
|
try {
|
|
281420
281685
|
rejectControlChars(prompt3);
|
|
@@ -281714,9 +281979,9 @@ var init_speech = __esm({
|
|
|
281714
281979
|
});
|
|
281715
281980
|
|
|
281716
281981
|
// ../cli/src/commands/generate/thumbnail.ts
|
|
281717
|
-
import { resolve as resolve64, dirname as dirname38, basename as basename17, extname as
|
|
281982
|
+
import { resolve as resolve64, dirname as dirname38, basename as basename17, extname as extname18 } from "node:path";
|
|
281718
281983
|
import { existsSync as existsSync79 } from "node:fs";
|
|
281719
|
-
import { writeFile as writeFile37, mkdir as
|
|
281984
|
+
import { writeFile as writeFile37, mkdir as mkdir27 } from "node:fs/promises";
|
|
281720
281985
|
function registerThumbnailCommand(parent) {
|
|
281721
281986
|
parent.command("thumbnail").description("Generate video thumbnail (DALL-E) or extract best frame from video (Gemini)").argument("[description]", "Thumbnail description (for DALL-E generation)").option("-k, --api-key <key>", "API key (OpenAI for generation, Google for best-frame)").option("-o, --output <path>", "Output file path").option("--style <style>", "Platform style: youtube, instagram, tiktok, twitter").option("--best-frame <video>", "Extract best thumbnail frame from video using Gemini AI").option("--prompt <prompt>", "Custom prompt for best-frame analysis").option("--model <model>", `Gemini model: ${GEMINI_TEXT_MODEL_HELP}`, "flash").action(async (description, options) => {
|
|
281722
281987
|
const startedAt = Date.now();
|
|
@@ -281739,7 +282004,7 @@ function registerThumbnailCommand(parent) {
|
|
|
281739
282004
|
);
|
|
281740
282005
|
}
|
|
281741
282006
|
const apiKey2 = await requireApiKey("GOOGLE_API_KEY", "Google", options.apiKey);
|
|
281742
|
-
const name = basename17(options.bestFrame,
|
|
282007
|
+
const name = basename17(options.bestFrame, extname18(options.bestFrame));
|
|
281743
282008
|
const outputPath = options.output || `${name}-thumbnail.png`;
|
|
281744
282009
|
const spinner3 = ora("Analyzing video for best frame...").start();
|
|
281745
282010
|
const result2 = await executeThumbnailBestFrame({
|
|
@@ -281807,7 +282072,7 @@ function registerThumbnailCommand(parent) {
|
|
|
281807
282072
|
throw new Error("No image data available");
|
|
281808
282073
|
}
|
|
281809
282074
|
outputPath = resolve64(process.cwd(), options.output);
|
|
281810
|
-
await
|
|
282075
|
+
await mkdir27(dirname38(outputPath), { recursive: true });
|
|
281811
282076
|
await writeFile37(outputPath, buffer);
|
|
281812
282077
|
}
|
|
281813
282078
|
outputSuccess({
|
|
@@ -281838,7 +282103,7 @@ function registerThumbnailCommand(parent) {
|
|
|
281838
282103
|
throw new Error("No image data available");
|
|
281839
282104
|
}
|
|
281840
282105
|
const outputPath = resolve64(process.cwd(), options.output);
|
|
281841
|
-
await
|
|
282106
|
+
await mkdir27(dirname38(outputPath), { recursive: true });
|
|
281842
282107
|
await writeFile37(outputPath, buffer);
|
|
281843
282108
|
saveSpinner.succeed(source_default.green(`Saved to: ${outputPath}`));
|
|
281844
282109
|
} catch {
|
|
@@ -281869,7 +282134,7 @@ var init_thumbnail = __esm({
|
|
|
281869
282134
|
import { resolve as resolve65 } from "node:path";
|
|
281870
282135
|
import { writeFile as writeFile38 } from "node:fs/promises";
|
|
281871
282136
|
function registerVideoExtendCommand(parent) {
|
|
281872
|
-
parent.command("video-extend", { hidden: true }).description("Extend video duration (Kling by video ID, Veo by operation name)").argument("<id>", "Kling video ID or Veo operation name").option("-p, --provider <provider>", "Provider: kling, veo", "kling").option("-k, --api-key <key>", "API key (KLING_API_KEY or GOOGLE_API_KEY)").option("-o, --output <path>", "Output file path").option("--prompt <text>", "Continuation prompt").option("-d, --duration <sec>", "Duration: 5 or 10 (Kling), 4/6/8 (Veo)", "5").option("--negative <prompt>", "Negative prompt (what to avoid, Kling only)").option("--veo-model <model>", "Veo model: 3.
|
|
282137
|
+
parent.command("video-extend", { hidden: true }).description("Extend video duration (Kling by video ID, Veo by operation name)").argument("<id>", "Kling video ID or Veo operation name").option("-p, --provider <provider>", "Provider: kling, veo", "kling").option("-k, --api-key <key>", "API key (KLING_API_KEY or GOOGLE_API_KEY)").option("-o, --output <path>", "Output file path").option("--prompt <text>", "Continuation prompt").option("-d, --duration <sec>", "Duration: 5 or 10 (Kling), 4/6/8 (Veo)", "5").option("--negative <prompt>", "Negative prompt (what to avoid, Kling only)").option("--veo-model <model>", "Veo model: 3.1, 3.1-fast", "3.1").option("--no-wait", "Start extension and return task ID without waiting").option("--dry-run", "Preview parameters without executing").action(async (id, options) => {
|
|
281873
282138
|
const startedAt = Date.now();
|
|
281874
282139
|
try {
|
|
281875
282140
|
const provider = (options.provider || "kling").toLowerCase();
|
|
@@ -281987,12 +282252,7 @@ function registerVideoExtendCommand(parent) {
|
|
|
281987
282252
|
const spinner2 = ora("Initializing Veo...").start();
|
|
281988
282253
|
const gemini = new GeminiProvider();
|
|
281989
282254
|
await gemini.initialize({ apiKey });
|
|
281990
|
-
const
|
|
281991
|
-
"3.0": "veo-3.0-generate-preview",
|
|
281992
|
-
"3.1": "veo-3.1-generate-preview",
|
|
281993
|
-
"3.1-fast": "veo-3.1-fast-generate-preview"
|
|
281994
|
-
};
|
|
281995
|
-
const veoModel = veoModelMap[options.veoModel] || "veo-3.1-generate-preview";
|
|
282255
|
+
const veoModel = resolveVeoModel(options.veoModel);
|
|
281996
282256
|
spinner2.text = "Starting video extension...";
|
|
281997
282257
|
const result = await gemini.extendVideo(id, options.prompt, {
|
|
281998
282258
|
duration: parseInt(options.duration),
|
|
@@ -282153,11 +282413,8 @@ var init_provider_resolver = __esm({
|
|
|
282153
282413
|
|
|
282154
282414
|
// ../cli/src/commands/_shared/openai-image.ts
|
|
282155
282415
|
function resolveOpenAIImageModel(modelAlias) {
|
|
282156
|
-
const
|
|
282157
|
-
return {
|
|
282158
|
-
openaiModel: isGptImage15 ? "gpt-image-1.5" : "gpt-image-2",
|
|
282159
|
-
modelLabel: isGptImage15 ? "GPT Image 1.5" : "GPT Image 2"
|
|
282160
|
-
};
|
|
282416
|
+
const model = findModel("openai", "image", modelAlias) ?? defaultModel("openai", "image");
|
|
282417
|
+
return { openaiModel: model.id, modelLabel: model.label };
|
|
282161
282418
|
}
|
|
282162
282419
|
async function executeOpenAIImageGenerate(prompt3, options, ctx) {
|
|
282163
282420
|
const provider = new OpenAIImageProvider();
|
|
@@ -282179,10 +282436,44 @@ var init_openai_image2 = __esm({
|
|
|
282179
282436
|
}
|
|
282180
282437
|
});
|
|
282181
282438
|
|
|
282439
|
+
// ../cli/src/commands/_shared/image-cost.ts
|
|
282440
|
+
function catalogPrice(provider, model) {
|
|
282441
|
+
if (provider === "openai") return findModel("openai", "image", resolveOpenAIImageModel(model).openaiModel)?.price?.usd;
|
|
282442
|
+
if (provider === "gemini") return findModel("gemini", "image", model ?? "flash")?.price?.usd ?? findModel("gemini", "image")?.price?.usd;
|
|
282443
|
+
if (provider === "grok") return findModel("grok", "image", resolveGrokImageModel(model).model)?.price?.usd;
|
|
282444
|
+
return void 0;
|
|
282445
|
+
}
|
|
282446
|
+
function estimateImageCostUsd(provider, model, count) {
|
|
282447
|
+
const images = Math.max(1, count);
|
|
282448
|
+
const perImage = catalogPrice(provider, model);
|
|
282449
|
+
if (perImage === void 0) {
|
|
282450
|
+
return {
|
|
282451
|
+
costUsd: lookupCostEstimateUpperBound("generate image") ?? 5,
|
|
282452
|
+
warnings: [
|
|
282453
|
+
`costUsd is the tier upper bound for ${provider} - actual provider billing is typically lower and is not metered here.`
|
|
282454
|
+
]
|
|
282455
|
+
};
|
|
282456
|
+
}
|
|
282457
|
+
return {
|
|
282458
|
+
costUsd: Number((perImage * images).toFixed(3)),
|
|
282459
|
+
warnings: [
|
|
282460
|
+
`costUsd is an upper-bound estimate from ${provider} list prices for ${images} image(s) - not metered billing.`
|
|
282461
|
+
]
|
|
282462
|
+
};
|
|
282463
|
+
}
|
|
282464
|
+
var init_image_cost = __esm({
|
|
282465
|
+
"../cli/src/commands/_shared/image-cost.ts"() {
|
|
282466
|
+
"use strict";
|
|
282467
|
+
init_dist();
|
|
282468
|
+
init_output();
|
|
282469
|
+
init_openai_image2();
|
|
282470
|
+
}
|
|
282471
|
+
});
|
|
282472
|
+
|
|
282182
282473
|
// ../cli/src/commands/generate/image.ts
|
|
282183
282474
|
import { resolve as resolve66, dirname as dirname39 } from "node:path";
|
|
282184
282475
|
import { fileURLToPath as fileURLToPath8 } from "node:url";
|
|
282185
|
-
import {
|
|
282476
|
+
import { mkdir as mkdir28 } from "node:fs/promises";
|
|
282186
282477
|
function registerImageCommand(parent) {
|
|
282187
282478
|
parent.command("image").alias("img").description("Generate image using AI (Gemini, OpenAI gpt-image, Grok, or Runway)").argument("[prompt]", "Image description prompt (interactive if omitted)").option(
|
|
282188
282479
|
"-p, --provider <provider>",
|
|
@@ -282193,7 +282484,7 @@ function registerImageCommand(parent) {
|
|
|
282193
282484
|
"1:1"
|
|
282194
282485
|
).option("--quality <quality>", "Quality: standard, hd (openai only)", "standard").option("--style <style>", "Style: vivid, natural (openai only)", "vivid").option("--count <n>", "Number of images to generate", "1").option(
|
|
282195
282486
|
"-m, --model <model>",
|
|
282196
|
-
"Model. Gemini: flash
|
|
282487
|
+
"Model. Gemini: flash (default), lite, pro. OpenAI: 2.5 (default), flare, 2, 1.5. Grok: pro"
|
|
282197
282488
|
).option("--dry-run", "Preview parameters without executing").addHelpText(
|
|
282198
282489
|
"after",
|
|
282199
282490
|
`
|
|
@@ -282276,6 +282567,7 @@ Examples:
|
|
|
282276
282567
|
command: "generate image",
|
|
282277
282568
|
startedAt,
|
|
282278
282569
|
dryRun: true,
|
|
282570
|
+
...estimateImageCostUsd(provider, options.model, parseInt(options.count) || 1),
|
|
282279
282571
|
data: {
|
|
282280
282572
|
params: {
|
|
282281
282573
|
prompt: prompt3,
|
|
@@ -282296,7 +282588,7 @@ Examples:
|
|
|
282296
282588
|
const apiKey = await requireApiKey(envKey, providerName, options.apiKey);
|
|
282297
282589
|
const spinner2 = ora(`Generating image with ${providerName}...`).start();
|
|
282298
282590
|
if (provider === "openai") {
|
|
282299
|
-
const { result, modelLabel } = await executeOpenAIImageGenerate(prompt3, options, {
|
|
282591
|
+
const { result, modelLabel, openaiModel } = await executeOpenAIImageGenerate(prompt3, options, {
|
|
282300
282592
|
apiKey
|
|
282301
282593
|
});
|
|
282302
282594
|
if (!result.success || !result.images) {
|
|
@@ -282319,14 +282611,17 @@ Examples:
|
|
|
282319
282611
|
} else {
|
|
282320
282612
|
throw new Error("No image data available");
|
|
282321
282613
|
}
|
|
282322
|
-
await
|
|
282323
|
-
await
|
|
282614
|
+
await mkdir28(dirname39(outputPath), { recursive: true });
|
|
282615
|
+
await writeImageFile(outputPath, buffer);
|
|
282324
282616
|
}
|
|
282325
282617
|
outputSuccess({
|
|
282326
282618
|
command: "generate image",
|
|
282327
282619
|
startedAt,
|
|
282620
|
+
...estimateImageCostUsd("openai", options.model, result.images.length),
|
|
282328
282621
|
data: {
|
|
282329
282622
|
provider: "openai",
|
|
282623
|
+
model: modelLabel,
|
|
282624
|
+
modelId: openaiModel,
|
|
282330
282625
|
images: result.images.map((img) => ({
|
|
282331
282626
|
url: img.url,
|
|
282332
282627
|
revisedPrompt: img.revisedPrompt
|
|
@@ -282366,8 +282661,8 @@ Examples:
|
|
|
282366
282661
|
throw new Error("No image data available");
|
|
282367
282662
|
}
|
|
282368
282663
|
const outputPath = resolve66(process.cwd(), options.output);
|
|
282369
|
-
await
|
|
282370
|
-
await
|
|
282664
|
+
await mkdir28(dirname39(outputPath), { recursive: true });
|
|
282665
|
+
await writeImageFile(outputPath, buffer);
|
|
282371
282666
|
saveSpinner.succeed(source_default.green(`Saved to: ${outputPath}`));
|
|
282372
282667
|
} catch (err) {
|
|
282373
282668
|
saveSpinner.fail(
|
|
@@ -282376,7 +282671,7 @@ Examples:
|
|
|
282376
282671
|
}
|
|
282377
282672
|
}
|
|
282378
282673
|
} else if (provider === "gemini") {
|
|
282379
|
-
const validGeminiModels = ["flash", "3.1-flash", "latest", "pro"];
|
|
282674
|
+
const validGeminiModels = ["flash", "3.1-flash", "latest", "lite", "pro"];
|
|
282380
282675
|
if (options.model && !validGeminiModels.includes(options.model)) {
|
|
282381
282676
|
console.warn(
|
|
282382
282677
|
source_default.yellow(
|
|
@@ -282409,26 +282704,17 @@ Examples:
|
|
|
282409
282704
|
const gemini = new GeminiProvider();
|
|
282410
282705
|
await gemini.initialize({ apiKey });
|
|
282411
282706
|
const geminiModelNames = {
|
|
282412
|
-
flash: "Nano Banana",
|
|
282707
|
+
flash: "Nano Banana 2",
|
|
282413
282708
|
"3.1-flash": "Nano Banana 2",
|
|
282414
282709
|
latest: "Nano Banana 2",
|
|
282710
|
+
lite: "Nano Banana 2 Lite",
|
|
282415
282711
|
pro: "Nano Banana Pro"
|
|
282416
282712
|
};
|
|
282417
|
-
const
|
|
282418
|
-
|
|
282713
|
+
const usedLabel = geminiModelNames[options.model] || "Nano Banana 2";
|
|
282714
|
+
const result = await gemini.generateImage(prompt3, {
|
|
282419
282715
|
model: options.model,
|
|
282420
282716
|
aspectRatio: options.ratio
|
|
282421
282717
|
});
|
|
282422
|
-
let usedLabel = modelLabel;
|
|
282423
|
-
const fallbackModels = ["latest", "3.1-flash"];
|
|
282424
|
-
if (!result.success && options.model && fallbackModels.includes(options.model)) {
|
|
282425
|
-
spinner2.text = `${source_default.dim(result.error || "Failed")} \u2014 retrying with Nano Banana (flash)...`;
|
|
282426
|
-
result = await gemini.generateImage(prompt3, {
|
|
282427
|
-
model: "flash",
|
|
282428
|
-
aspectRatio: options.ratio
|
|
282429
|
-
});
|
|
282430
|
-
usedLabel = "Nano Banana (fallback)";
|
|
282431
|
-
}
|
|
282432
282718
|
if (!result.success || !result.images) {
|
|
282433
282719
|
spinner2.fail(result.error || "Image generation failed");
|
|
282434
282720
|
exitWithError(apiError(result.error || "Image generation failed", true));
|
|
@@ -282441,16 +282727,17 @@ Examples:
|
|
|
282441
282727
|
if (outputPath && result.images.length > 0) {
|
|
282442
282728
|
const img = result.images[0];
|
|
282443
282729
|
const buffer = Buffer.from(img.base64, "base64");
|
|
282444
|
-
await
|
|
282445
|
-
await
|
|
282730
|
+
await mkdir28(dirname39(outputPath), { recursive: true });
|
|
282731
|
+
await writeImageFile(outputPath, buffer);
|
|
282446
282732
|
}
|
|
282447
282733
|
outputSuccess({
|
|
282448
282734
|
command: "generate image",
|
|
282449
282735
|
startedAt,
|
|
282450
|
-
|
|
282736
|
+
...estimateImageCostUsd("gemini", options.model, result.images.length),
|
|
282451
282737
|
data: {
|
|
282452
282738
|
provider: "gemini",
|
|
282453
282739
|
model: usedLabel,
|
|
282740
|
+
modelId: result.model,
|
|
282454
282741
|
images: result.images.map((img) => ({
|
|
282455
282742
|
mimeType: img.mimeType
|
|
282456
282743
|
})),
|
|
@@ -282474,8 +282761,8 @@ Examples:
|
|
|
282474
282761
|
const img = result.images[0];
|
|
282475
282762
|
const buffer = Buffer.from(img.base64, "base64");
|
|
282476
282763
|
const outputPath = resolve66(process.cwd(), options.output);
|
|
282477
|
-
await
|
|
282478
|
-
await
|
|
282764
|
+
await mkdir28(dirname39(outputPath), { recursive: true });
|
|
282765
|
+
await writeImageFile(outputPath, buffer);
|
|
282479
282766
|
saveSpinner.succeed(source_default.green(`Saved to: ${outputPath}`));
|
|
282480
282767
|
} catch (err) {
|
|
282481
282768
|
saveSpinner.fail(
|
|
@@ -282513,6 +282800,7 @@ Examples:
|
|
|
282513
282800
|
options.ratio = "1:1";
|
|
282514
282801
|
}
|
|
282515
282802
|
const result = await grok.generateImage(prompt3, {
|
|
282803
|
+
...resolveGrokImageModel(options.model),
|
|
282516
282804
|
aspectRatio: options.ratio || "1:1",
|
|
282517
282805
|
n: parseInt(options.count)
|
|
282518
282806
|
});
|
|
@@ -282534,14 +282822,16 @@ Examples:
|
|
|
282534
282822
|
} else {
|
|
282535
282823
|
throw new Error("No image data available");
|
|
282536
282824
|
}
|
|
282537
|
-
await
|
|
282538
|
-
await
|
|
282825
|
+
await mkdir28(dirname39(outputPath), { recursive: true });
|
|
282826
|
+
await writeImageFile(outputPath, buffer);
|
|
282539
282827
|
}
|
|
282540
282828
|
outputSuccess({
|
|
282541
282829
|
command: "generate image",
|
|
282542
282830
|
startedAt,
|
|
282831
|
+
...estimateImageCostUsd("grok", options.model, result.images.length),
|
|
282543
282832
|
data: {
|
|
282544
282833
|
provider: "grok",
|
|
282834
|
+
modelId: resolveGrokImageModel(options.model).model,
|
|
282545
282835
|
images: result.images.map((img) => ({ url: img.url })),
|
|
282546
282836
|
outputPath
|
|
282547
282837
|
}
|
|
@@ -282575,8 +282865,8 @@ Examples:
|
|
|
282575
282865
|
throw new Error("No image data available");
|
|
282576
282866
|
}
|
|
282577
282867
|
const outputPath = resolve66(process.cwd(), options.output);
|
|
282578
|
-
await
|
|
282579
|
-
await
|
|
282868
|
+
await mkdir28(dirname39(outputPath), { recursive: true });
|
|
282869
|
+
await writeImageFile(outputPath, buffer);
|
|
282580
282870
|
saveSpinner.succeed(source_default.green(`Saved to: ${outputPath}`));
|
|
282581
282871
|
} catch (err) {
|
|
282582
282872
|
saveSpinner.fail(
|
|
@@ -282658,6 +282948,8 @@ var init_image2 = __esm({
|
|
|
282658
282948
|
init_validate();
|
|
282659
282949
|
init_provider_resolver();
|
|
282660
282950
|
init_openai_image2();
|
|
282951
|
+
init_image_cost();
|
|
282952
|
+
init_image_file();
|
|
282661
282953
|
}
|
|
282662
282954
|
});
|
|
282663
282955
|
|
|
@@ -283606,11 +283898,11 @@ var init_dist5 = __esm({
|
|
|
283606
283898
|
|
|
283607
283899
|
// ../cli/src/commands/generate/video.ts
|
|
283608
283900
|
import { resolve as resolve67 } from "node:path";
|
|
283609
|
-
import { readFile as readFile36, writeFile as
|
|
283901
|
+
import { readFile as readFile36, writeFile as writeFile39 } from "node:fs/promises";
|
|
283610
283902
|
function registerVideoCommand(parent) {
|
|
283611
283903
|
parent.command("video").alias("vid").description("Generate video using AI (Seedance, Grok, Kling, Runway, Veo, or Gemini Omni)").argument("[prompt]", "Text prompt describing the video (interactive if omitted)").option(
|
|
283612
283904
|
"-p, --provider <provider>",
|
|
283613
|
-
"Provider: seedance (ByteDance Seedance 2.0 via fal.ai), grok, kling, runway,
|
|
283905
|
+
"Provider: seedance (ByteDance Seedance 2.0 via fal.ai), grok, kling, runway, omni (Gemini Omni 1.1 Flash; Google default), veo (Veo 3.1 preview, shuts down 2026-10-22). `fal` is a deprecated v0.x alias for seedance and will be removed in 1.0."
|
|
283614
283906
|
).option(
|
|
283615
283907
|
"-k, --api-key <key>",
|
|
283616
283908
|
"API key (or set FAL_API_KEY / XAI_API_KEY / RUNWAY_API_SECRET / KLING_API_KEY / GOOGLE_API_KEY env)"
|
|
@@ -283623,12 +283915,12 @@ function registerVideoCommand(parent) {
|
|
|
283623
283915
|
"Aspect ratio: 16:9, 9:16, or 1:1 (auto-detected from image if omitted)"
|
|
283624
283916
|
).option("--seed <number>", "Random seed for reproducibility (Runway only)").option("--mode <mode>", "Generation mode: std or pro (Kling only)", "std").option(
|
|
283625
283917
|
"--seedance-model <model>",
|
|
283626
|
-
"Seedance variant: quality
|
|
283918
|
+
"Seedance variant: quality (2.0), fast, or 2.5 (fal.ai only)",
|
|
283627
283919
|
"quality"
|
|
283628
|
-
).option("--negative <prompt>", "Negative prompt - what to avoid (Kling/Veo)").option("--resolution <res>", "Video resolution: 480p, 720p, 1080p, or 4k depending on provider").option("--last-frame <path>", "Last frame image for frame interpolation (Veo) or Seedance end frame").option("--end-image <path>", "Ending frame image for Seedance image-to-video").option(
|
|
283920
|
+
).option("--grok-model <model>", "Grok video model: 1.5 (default), lite, classic", "1.5").option("--kling-model <model>", "Kling model: v3 (default), v2.6, v2.5-turbo", "v3").option("--negative <prompt>", "Negative prompt - what to avoid (Kling/Veo)").option("--resolution <res>", "Video resolution: 480p, 720p, 1080p, or 4k depending on provider").option("--last-frame <path>", "Last frame image for frame interpolation (Veo) or Seedance end frame").option("--end-image <path>", "Ending frame image for Seedance image-to-video").option(
|
|
283629
283921
|
"--ref-images <paths...>",
|
|
283630
283922
|
"Reference images for Seedance reference-to-video or Veo character consistency"
|
|
283631
|
-
).option("--ref-videos <paths...>", "Reference videos for Seedance reference-to-video").option("--ref-audio <paths...>", "Reference audio for Seedance reference-to-video").option("--no-generate-audio", "Disable native audio when the provider supports it").option("--person <mode>", "Person generation: allow_all, allow_adult (Veo only)").option("--veo-model <model>", "Veo model: 3.
|
|
283923
|
+
).option("--ref-videos <paths...>", "Reference videos for Seedance reference-to-video").option("--ref-audio <paths...>", "Reference audio for Seedance reference-to-video").option("--no-generate-audio", "Disable native audio when the provider supports it").option("--person <mode>", "Person generation: allow_all, allow_adult (Veo only)").option("--veo-model <model>", "Veo model: 3.1, 3.1-fast (default: 3.1-fast)", "3.1-fast").option(
|
|
283632
283924
|
"--runway-model <model>",
|
|
283633
283925
|
"Runway model: gen4.5 (default, text+image-to-video), gen4_turbo (image-to-video only)",
|
|
283634
283926
|
"gen4.5"
|
|
@@ -283689,7 +283981,7 @@ Examples:
|
|
|
283689
283981
|
exitWithError(
|
|
283690
283982
|
usageError(
|
|
283691
283983
|
`Invalid provider: ${provider}`,
|
|
283692
|
-
"Available providers: seedance, grok, kling, runway,
|
|
283984
|
+
"Available providers: seedance, grok, kling, runway, omni, veo. `fal` is a deprecated alias for seedance."
|
|
283693
283985
|
)
|
|
283694
283986
|
);
|
|
283695
283987
|
}
|
|
@@ -283756,14 +284048,16 @@ Examples:
|
|
|
283756
284048
|
log(`${provider} does not support 1:1 \u2014 falling back to 16:9`);
|
|
283757
284049
|
options.ratio = "16:9";
|
|
283758
284050
|
}
|
|
284051
|
+
try {
|
|
284052
|
+
if (provider === "seedance" || provider === "fal") resolveSeedanceVariant(options.seedanceModel);
|
|
284053
|
+
if (provider === "grok") resolveGrokVideoModel(options.grokModel);
|
|
284054
|
+
if (provider === "kling") resolveKlingModel(options.klingModel);
|
|
284055
|
+
if (provider === "veo") resolveVeoModel(options.veoModel);
|
|
284056
|
+
} catch (err) {
|
|
284057
|
+
exitWithError(usageError(err instanceof Error ? err.message : String(err)));
|
|
284058
|
+
}
|
|
283759
284059
|
if (options.dryRun) {
|
|
283760
|
-
const costUsd = provider === "seedance" || provider === "fal" ?
|
|
283761
|
-
durationSec: Number(options.duration) || 5,
|
|
283762
|
-
resolution: options.resolution,
|
|
283763
|
-
aspectRatio: options.ratio,
|
|
283764
|
-
fast: options.seedanceModel === "fast",
|
|
283765
|
-
hasVideoReference: Boolean(options.refVideos)
|
|
283766
|
-
}) : void 0;
|
|
284060
|
+
const costUsd = provider === "seedance" || provider === "fal" ? realRunCost(provider, options).costUsd : void 0;
|
|
283767
284061
|
outputSuccess({
|
|
283768
284062
|
command: "generate video",
|
|
283769
284063
|
startedAt,
|
|
@@ -283781,6 +284075,8 @@ Examples:
|
|
|
283781
284075
|
resolution: options.resolution,
|
|
283782
284076
|
veoModel: options.veoModel,
|
|
283783
284077
|
seedanceModel: options.seedanceModel,
|
|
284078
|
+
grokModel: options.grokModel,
|
|
284079
|
+
klingModel: options.klingModel,
|
|
283784
284080
|
refImages: options.refImages,
|
|
283785
284081
|
refVideos: options.refVideos,
|
|
283786
284082
|
refAudio: options.refAudio,
|
|
@@ -283802,7 +284098,7 @@ Examples:
|
|
|
283802
284098
|
runway: "Runway",
|
|
283803
284099
|
kling: "Kling",
|
|
283804
284100
|
veo: "Veo",
|
|
283805
|
-
omni: "Gemini Omni
|
|
284101
|
+
omni: "Gemini Omni 1.1 Flash",
|
|
283806
284102
|
grok: "Grok",
|
|
283807
284103
|
seedance: "Seedance 2.0 via fal.ai"
|
|
283808
284104
|
};
|
|
@@ -283901,6 +284197,7 @@ Examples:
|
|
|
283901
284197
|
}
|
|
283902
284198
|
result = await kling.generateVideo(prompt3, {
|
|
283903
284199
|
prompt: prompt3,
|
|
284200
|
+
model: resolveKlingModel(options.klingModel),
|
|
283904
284201
|
referenceImage: klingImage,
|
|
283905
284202
|
duration: parseInt(options.duration),
|
|
283906
284203
|
aspectRatio: options.ratio,
|
|
@@ -283950,12 +284247,7 @@ Examples:
|
|
|
283950
284247
|
} else if (provider === "veo") {
|
|
283951
284248
|
const gemini = new GeminiProvider();
|
|
283952
284249
|
await gemini.initialize({ apiKey });
|
|
283953
|
-
const
|
|
283954
|
-
"3.0": "veo-3.0-generate-preview",
|
|
283955
|
-
"3.1": "veo-3.1-generate-preview",
|
|
283956
|
-
"3.1-fast": "veo-3.1-fast-generate-preview"
|
|
283957
|
-
};
|
|
283958
|
-
const veoModel = veoModelMap[options.veoModel] || "veo-3.1-fast-generate-preview";
|
|
284250
|
+
const veoModel = resolveVeoModel(options.veoModel);
|
|
283959
284251
|
const veoDuration = parseInt(options.duration) <= 6 ? 6 : 8;
|
|
283960
284252
|
let lastFrame;
|
|
283961
284253
|
if (options.lastFrame) {
|
|
@@ -284029,9 +284321,12 @@ Examples:
|
|
|
284029
284321
|
await grok.initialize({ apiKey });
|
|
284030
284322
|
result = await grok.generateVideo(prompt3, {
|
|
284031
284323
|
prompt: prompt3,
|
|
284324
|
+
model: resolveGrokVideoModel(options.grokModel),
|
|
284032
284325
|
referenceImage,
|
|
284033
284326
|
duration: parseInt(options.duration),
|
|
284034
|
-
aspectRatio: options.ratio
|
|
284327
|
+
aspectRatio: options.ratio,
|
|
284328
|
+
resolution: options.resolution,
|
|
284329
|
+
generateAudio: options.generateAudio
|
|
284035
284330
|
});
|
|
284036
284331
|
if (result.status === "failed") {
|
|
284037
284332
|
spinner2.fail(result.error || "Failed to start generation");
|
|
@@ -284121,9 +284416,8 @@ Examples:
|
|
|
284121
284416
|
exitWithError(apiError(message, true));
|
|
284122
284417
|
}
|
|
284123
284418
|
}
|
|
284124
|
-
|
|
284125
|
-
|
|
284126
|
-
const falModel = seedanceModel === "fast" || seedanceModel === "seedance-2.0-fast" ? "seedance-2.0-fast" : "seedance-2.0";
|
|
284419
|
+
const falModel = resolveSeedanceVariant(options.seedanceModel);
|
|
284420
|
+
spinner2.text = `Generating video with fal.ai ${falModel} (this may take 1-3 minutes)...`;
|
|
284127
284421
|
result = await fal.generateVideo(prompt3, {
|
|
284128
284422
|
prompt: prompt3,
|
|
284129
284423
|
referenceImage: seedanceReferences.length > 0 ? void 0 : falImage,
|
|
@@ -284140,11 +284434,20 @@ Examples:
|
|
|
284140
284434
|
} else if (provider === "omni") {
|
|
284141
284435
|
const omni = new OmniProvider();
|
|
284142
284436
|
await omni.initialize({ apiKey });
|
|
284143
|
-
spinner2.text = "Generating video with Gemini Omni
|
|
284437
|
+
spinner2.text = "Generating video with Gemini Omni 1.1 Flash...";
|
|
284438
|
+
let lastFrame;
|
|
284439
|
+
if (options.lastFrame) {
|
|
284440
|
+
const lastFramePath = resolve67(process.cwd(), options.lastFrame);
|
|
284441
|
+
const ext = options.lastFrame.toLowerCase().split(".").pop();
|
|
284442
|
+
const mimeType = ext === "jpg" || ext === "jpeg" ? "image/jpeg" : `image/${ext || "png"}`;
|
|
284443
|
+
lastFrame = `data:${mimeType};base64,${(await readFile36(lastFramePath)).toString("base64")}`;
|
|
284444
|
+
}
|
|
284144
284445
|
result = await omni.generateVideo(prompt3, {
|
|
284145
284446
|
prompt: prompt3,
|
|
284146
284447
|
referenceImage,
|
|
284147
|
-
|
|
284448
|
+
lastFrame,
|
|
284449
|
+
aspectRatio: options.ratio,
|
|
284450
|
+
resolution: options.resolution
|
|
284148
284451
|
});
|
|
284149
284452
|
finalResult = result;
|
|
284150
284453
|
}
|
|
@@ -284158,14 +284461,14 @@ Examples:
|
|
|
284158
284461
|
if (options.output && finalResult.videoUrl) {
|
|
284159
284462
|
const buffer = await downloadVideo(finalResult.videoUrl, apiKey);
|
|
284160
284463
|
outputPath = resolve67(process.cwd(), options.output);
|
|
284161
|
-
await
|
|
284464
|
+
await writeFile39(outputPath, buffer);
|
|
284162
284465
|
}
|
|
284163
284466
|
const cost = realRunCost(provider, options);
|
|
284164
284467
|
outputSuccess({
|
|
284165
284468
|
command: "generate video",
|
|
284166
284469
|
startedAt,
|
|
284167
284470
|
costUsd: cost.costUsd,
|
|
284168
|
-
warnings: cost.warnings,
|
|
284471
|
+
warnings: provider === "veo" ? [VEO_SHUTDOWN_WARNING, ...cost.warnings] : cost.warnings,
|
|
284169
284472
|
data: {
|
|
284170
284473
|
provider,
|
|
284171
284474
|
taskId: result?.id,
|
|
@@ -284177,6 +284480,9 @@ Examples:
|
|
|
284177
284480
|
return;
|
|
284178
284481
|
}
|
|
284179
284482
|
console.log();
|
|
284483
|
+
if (provider === "veo") {
|
|
284484
|
+
console.log(source_default.yellow(VEO_SHUTDOWN_WARNING));
|
|
284485
|
+
}
|
|
284180
284486
|
if (finalResult.videoUrl) {
|
|
284181
284487
|
console.log(`Video URL: ${finalResult.videoUrl}`);
|
|
284182
284488
|
}
|
|
@@ -284189,7 +284495,7 @@ Examples:
|
|
|
284189
284495
|
try {
|
|
284190
284496
|
const buffer = await downloadVideo(finalResult.videoUrl, apiKey);
|
|
284191
284497
|
const outputPath = resolve67(process.cwd(), options.output);
|
|
284192
|
-
await
|
|
284498
|
+
await writeFile39(outputPath, buffer);
|
|
284193
284499
|
downloadSpinner.succeed(source_default.green(`Saved to: ${outputPath}`));
|
|
284194
284500
|
} catch (err) {
|
|
284195
284501
|
downloadSpinner.fail(
|
|
@@ -284204,12 +284510,14 @@ Examples:
|
|
|
284204
284510
|
}
|
|
284205
284511
|
function realRunCost(provider, options) {
|
|
284206
284512
|
if (provider === "seedance" || provider === "fal") {
|
|
284513
|
+
const variant = resolveSeedanceVariant(options.seedanceModel);
|
|
284207
284514
|
return {
|
|
284208
284515
|
costUsd: estimateSeedanceVideoCostUsd({
|
|
284209
284516
|
durationSec: Number(options.duration) || 5,
|
|
284210
284517
|
resolution: options.resolution,
|
|
284211
284518
|
aspectRatio: options.ratio,
|
|
284212
|
-
fast:
|
|
284519
|
+
fast: variant === "seedance-2.0-fast",
|
|
284520
|
+
v25: variant === "seedance-2.5",
|
|
284213
284521
|
hasVideoReference: Boolean(options.refVideos)
|
|
284214
284522
|
}),
|
|
284215
284523
|
warnings: []
|
|
@@ -284299,6 +284607,7 @@ function printVideoStarted(providerLabel, taskId, taskType) {
|
|
|
284299
284607
|
console.log(`Task ID: ${source_default.bold(taskId)}`);
|
|
284300
284608
|
if (taskType) console.log(`Type: ${taskType}`);
|
|
284301
284609
|
}
|
|
284610
|
+
var VEO_SHUTDOWN_WARNING;
|
|
284302
284611
|
var init_video = __esm({
|
|
284303
284612
|
"../cli/src/commands/generate/video.ts"() {
|
|
284304
284613
|
"use strict";
|
|
@@ -284314,6 +284623,7 @@ var init_video = __esm({
|
|
|
284314
284623
|
init_upload_host();
|
|
284315
284624
|
init_ai_helpers();
|
|
284316
284625
|
init_status_jobs();
|
|
284626
|
+
VEO_SHUTDOWN_WARNING = "Veo 3.1 preview models shut down on 2026-10-22. Use `-p omni` (Gemini Omni 1.1 Flash) instead.";
|
|
284317
284627
|
}
|
|
284318
284628
|
});
|
|
284319
284629
|
|
|
@@ -284333,7 +284643,7 @@ var init_sanitize = __esm({
|
|
|
284333
284643
|
|
|
284334
284644
|
// ../cli/src/commands/generate/storyboard.ts
|
|
284335
284645
|
import { resolve as resolve68 } from "node:path";
|
|
284336
|
-
import { writeFile as
|
|
284646
|
+
import { writeFile as writeFile40 } from "node:fs/promises";
|
|
284337
284647
|
async function executeStoryboard(options) {
|
|
284338
284648
|
const { content, duration, creativity = "low", output: output3, apiKey } = options;
|
|
284339
284649
|
try {
|
|
@@ -284352,7 +284662,7 @@ async function executeStoryboard(options) {
|
|
|
284352
284662
|
let outputPath;
|
|
284353
284663
|
if (output3) {
|
|
284354
284664
|
outputPath = resolve68(process.cwd(), output3);
|
|
284355
|
-
await
|
|
284665
|
+
await writeFile40(outputPath, JSON.stringify(segments, null, 2), "utf-8");
|
|
284356
284666
|
}
|
|
284357
284667
|
return { success: true, segments, segmentCount: segments.length, outputPath };
|
|
284358
284668
|
} catch (error) {
|
|
@@ -298147,10 +298457,11 @@ var init_openai3 = __esm({
|
|
|
298147
298457
|
"../cli/src/agent/adapters/openai.ts"() {
|
|
298148
298458
|
"use strict";
|
|
298149
298459
|
init_openai2();
|
|
298460
|
+
init_dist();
|
|
298150
298461
|
OpenAIAdapter = class {
|
|
298151
298462
|
provider = "openai";
|
|
298152
298463
|
client = null;
|
|
298153
|
-
model = "
|
|
298464
|
+
model = defaultModel("openai", "llm").id;
|
|
298154
298465
|
async initialize(apiKey) {
|
|
298155
298466
|
this.client = new openai_default({ apiKey });
|
|
298156
298467
|
}
|
|
@@ -301696,10 +302007,11 @@ var init_claude2 = __esm({
|
|
|
301696
302007
|
"../cli/src/agent/adapters/claude.ts"() {
|
|
301697
302008
|
"use strict";
|
|
301698
302009
|
init_sdk();
|
|
302010
|
+
init_dist();
|
|
301699
302011
|
ClaudeAdapter = class {
|
|
301700
302012
|
provider = "claude";
|
|
301701
302013
|
client = null;
|
|
301702
|
-
model = "claude
|
|
302014
|
+
model = defaultModel("claude", "llm").id;
|
|
301703
302015
|
async initialize(apiKey) {
|
|
301704
302016
|
this.client = new sdk_default({ apiKey });
|
|
301705
302017
|
}
|
|
@@ -301724,6 +302036,13 @@ var init_claude2 = __esm({
|
|
|
301724
302036
|
content: msg.content
|
|
301725
302037
|
});
|
|
301726
302038
|
} else if (msg.role === "assistant") {
|
|
302039
|
+
if (msg.providerContent) {
|
|
302040
|
+
claudeMessages.push({
|
|
302041
|
+
role: "assistant",
|
|
302042
|
+
content: msg.providerContent
|
|
302043
|
+
});
|
|
302044
|
+
continue;
|
|
302045
|
+
}
|
|
301727
302046
|
const content = [];
|
|
301728
302047
|
if (msg.content) {
|
|
301729
302048
|
content.push({ type: "text", text: msg.content });
|
|
@@ -301745,16 +302064,17 @@ var init_claude2 = __esm({
|
|
|
301745
302064
|
});
|
|
301746
302065
|
}
|
|
301747
302066
|
} else if (msg.role === "tool") {
|
|
301748
|
-
|
|
301749
|
-
|
|
301750
|
-
|
|
301751
|
-
|
|
301752
|
-
|
|
301753
|
-
|
|
301754
|
-
|
|
301755
|
-
|
|
301756
|
-
|
|
301757
|
-
|
|
302067
|
+
const result = {
|
|
302068
|
+
type: "tool_result",
|
|
302069
|
+
tool_use_id: msg.toolCallId,
|
|
302070
|
+
content: msg.content
|
|
302071
|
+
};
|
|
302072
|
+
const last3 = claudeMessages.at(-1);
|
|
302073
|
+
if (last3?.role === "user" && Array.isArray(last3.content)) {
|
|
302074
|
+
last3.content.push(result);
|
|
302075
|
+
} else {
|
|
302076
|
+
claudeMessages.push({ role: "user", content: [result] });
|
|
302077
|
+
}
|
|
301758
302078
|
}
|
|
301759
302079
|
}
|
|
301760
302080
|
const claudeTools = tools2.map((tool) => ({
|
|
@@ -301768,7 +302088,8 @@ var init_claude2 = __esm({
|
|
|
301768
302088
|
}));
|
|
301769
302089
|
const response = await this.client.messages.create({
|
|
301770
302090
|
model: this.model,
|
|
301771
|
-
|
|
302091
|
+
// Thinking tokens count against this cap on Claude 5.x.
|
|
302092
|
+
max_tokens: 16e3,
|
|
301772
302093
|
system: systemPrompt,
|
|
301773
302094
|
messages: claudeMessages,
|
|
301774
302095
|
tools: claudeTools.length > 0 ? claudeTools : void 0
|
|
@@ -301795,7 +302116,8 @@ var init_claude2 = __esm({
|
|
|
301795
302116
|
return {
|
|
301796
302117
|
content: textContent2,
|
|
301797
302118
|
toolCalls: toolCalls.length > 0 ? toolCalls : void 0,
|
|
301798
|
-
finishReason
|
|
302119
|
+
finishReason,
|
|
302120
|
+
providerContent: response.content
|
|
301799
302121
|
};
|
|
301800
302122
|
}
|
|
301801
302123
|
};
|
|
@@ -302760,17 +303082,51 @@ var init_dist6 = __esm({
|
|
|
302760
303082
|
// ../cli/src/agent/adapters/gemini.ts
|
|
302761
303083
|
var gemini_exports = {};
|
|
302762
303084
|
__export(gemini_exports, {
|
|
302763
|
-
GeminiAdapter: () => GeminiAdapter
|
|
303085
|
+
GeminiAdapter: () => GeminiAdapter,
|
|
303086
|
+
toGeminiSchema: () => toGeminiSchema
|
|
302764
303087
|
});
|
|
302765
|
-
|
|
303088
|
+
function toGeminiSchema(schema) {
|
|
303089
|
+
if (Array.isArray(schema)) return schema.map(toGeminiSchema);
|
|
303090
|
+
if (!schema || typeof schema !== "object") return schema;
|
|
303091
|
+
const out = {};
|
|
303092
|
+
for (const [key2, value] of Object.entries(schema)) {
|
|
303093
|
+
if (!GEMINI_SCHEMA_KEYS.has(key2)) continue;
|
|
303094
|
+
if (key2 === "properties" && value && typeof value === "object") {
|
|
303095
|
+
out.properties = Object.fromEntries(
|
|
303096
|
+
Object.entries(value).map(([name, prop2]) => [name, toGeminiSchema(prop2)])
|
|
303097
|
+
);
|
|
303098
|
+
} else if (key2 === "items") {
|
|
303099
|
+
out.items = toGeminiSchema(value);
|
|
303100
|
+
} else {
|
|
303101
|
+
out[key2] = value;
|
|
303102
|
+
}
|
|
303103
|
+
}
|
|
303104
|
+
return out;
|
|
303105
|
+
}
|
|
303106
|
+
var GEMINI_SCHEMA_KEYS, GeminiAdapter;
|
|
302766
303107
|
var init_gemini2 = __esm({
|
|
302767
303108
|
"../cli/src/agent/adapters/gemini.ts"() {
|
|
302768
303109
|
"use strict";
|
|
302769
303110
|
init_dist6();
|
|
303111
|
+
init_dist();
|
|
303112
|
+
GEMINI_SCHEMA_KEYS = /* @__PURE__ */ new Set([
|
|
303113
|
+
"type",
|
|
303114
|
+
"format",
|
|
303115
|
+
"description",
|
|
303116
|
+
"nullable",
|
|
303117
|
+
"enum",
|
|
303118
|
+
"items",
|
|
303119
|
+
"properties",
|
|
303120
|
+
"required",
|
|
303121
|
+
"minItems",
|
|
303122
|
+
"maxItems",
|
|
303123
|
+
"minimum",
|
|
303124
|
+
"maximum"
|
|
303125
|
+
]);
|
|
302770
303126
|
GeminiAdapter = class {
|
|
302771
303127
|
provider = "gemini";
|
|
302772
303128
|
client = null;
|
|
302773
|
-
model =
|
|
303129
|
+
model = GEMINI_AGENT_DEFAULT_TEXT_MODEL;
|
|
302774
303130
|
async initialize(apiKey) {
|
|
302775
303131
|
this.client = new GoogleGenerativeAI(apiKey);
|
|
302776
303132
|
}
|
|
@@ -302792,7 +303148,12 @@ var init_gemini2 = __esm({
|
|
|
302792
303148
|
description: tool.description,
|
|
302793
303149
|
parameters: {
|
|
302794
303150
|
type: SchemaType.OBJECT,
|
|
302795
|
-
properties:
|
|
303151
|
+
properties: Object.fromEntries(
|
|
303152
|
+
Object.entries(tool.parameters.properties).map(([name, prop2]) => [
|
|
303153
|
+
name,
|
|
303154
|
+
toGeminiSchema(prop2)
|
|
303155
|
+
])
|
|
303156
|
+
),
|
|
302796
303157
|
required: tool.parameters.required
|
|
302797
303158
|
}
|
|
302798
303159
|
}))
|
|
@@ -302811,6 +303172,10 @@ var init_gemini2 = __esm({
|
|
|
302811
303172
|
parts: [{ text: msg.content }]
|
|
302812
303173
|
});
|
|
302813
303174
|
} else if (msg.role === "assistant") {
|
|
303175
|
+
if (msg.providerContent) {
|
|
303176
|
+
geminiContents.push({ role: "model", parts: msg.providerContent });
|
|
303177
|
+
continue;
|
|
303178
|
+
}
|
|
302814
303179
|
const parts = [];
|
|
302815
303180
|
if (msg.content) {
|
|
302816
303181
|
parts.push({ text: msg.content });
|
|
@@ -302832,16 +303197,19 @@ var init_gemini2 = __esm({
|
|
|
302832
303197
|
});
|
|
302833
303198
|
}
|
|
302834
303199
|
} else if (msg.role === "tool") {
|
|
302835
|
-
|
|
302836
|
-
|
|
302837
|
-
|
|
302838
|
-
|
|
302839
|
-
|
|
302840
|
-
|
|
302841
|
-
|
|
302842
|
-
|
|
302843
|
-
|
|
302844
|
-
|
|
303200
|
+
const part = {
|
|
303201
|
+
functionResponse: {
|
|
303202
|
+
name: msg.toolCallId.split(":::")[0] || "unknown",
|
|
303203
|
+
// Extract function name from id
|
|
303204
|
+
response: { result: msg.content }
|
|
303205
|
+
}
|
|
303206
|
+
};
|
|
303207
|
+
const last3 = geminiContents.at(-1);
|
|
303208
|
+
if (last3?.role === "user" && last3.parts.every((p2) => "functionResponse" in p2)) {
|
|
303209
|
+
last3.parts.push(part);
|
|
303210
|
+
} else {
|
|
303211
|
+
geminiContents.push({ role: "user", parts: [part] });
|
|
303212
|
+
}
|
|
302845
303213
|
}
|
|
302846
303214
|
}
|
|
302847
303215
|
const result = await model.generateContent({
|
|
@@ -302878,7 +303246,8 @@ var init_gemini2 = __esm({
|
|
|
302878
303246
|
return {
|
|
302879
303247
|
content: textContent2,
|
|
302880
303248
|
toolCalls: toolCalls.length > 0 ? toolCalls : void 0,
|
|
302881
|
-
finishReason
|
|
303249
|
+
finishReason,
|
|
303250
|
+
providerContent: candidate.content.parts
|
|
302882
303251
|
};
|
|
302883
303252
|
}
|
|
302884
303253
|
};
|
|
@@ -303078,10 +303447,11 @@ var init_xai = __esm({
|
|
|
303078
303447
|
"../cli/src/agent/adapters/xai.ts"() {
|
|
303079
303448
|
"use strict";
|
|
303080
303449
|
init_openai2();
|
|
303450
|
+
init_dist();
|
|
303081
303451
|
XAIAdapter = class {
|
|
303082
303452
|
provider = "xai";
|
|
303083
303453
|
client = null;
|
|
303084
|
-
model = "grok
|
|
303454
|
+
model = defaultModel("grok", "llm").id;
|
|
303085
303455
|
async initialize(apiKey) {
|
|
303086
303456
|
this.client = new openai_default({
|
|
303087
303457
|
apiKey,
|
|
@@ -303381,7 +303751,7 @@ __export(detect_exports, {
|
|
|
303381
303751
|
executeDetectScenes: () => executeDetectScenes,
|
|
303382
303752
|
executeDetectSilence: () => executeDetectSilence
|
|
303383
303753
|
});
|
|
303384
|
-
import { readFile as readFile41, writeFile as
|
|
303754
|
+
import { readFile as readFile41, writeFile as writeFile44 } from "node:fs/promises";
|
|
303385
303755
|
import { resolve as resolve74, basename as basename20 } from "node:path";
|
|
303386
303756
|
async function executeDetectScenes(options) {
|
|
303387
303757
|
try {
|
|
@@ -303420,7 +303790,7 @@ async function executeDetectScenes(options) {
|
|
|
303420
303790
|
}));
|
|
303421
303791
|
if (options.outputPath) {
|
|
303422
303792
|
const outputPath = resolve74(process.cwd(), options.outputPath);
|
|
303423
|
-
await
|
|
303793
|
+
await writeFile44(outputPath, JSON.stringify({ source: absPath, totalDuration, threshold, scenes: result }, null, 2), "utf-8");
|
|
303424
303794
|
}
|
|
303425
303795
|
return { success: true, scenes: result, totalDuration };
|
|
303426
303796
|
} catch (error) {
|
|
@@ -303467,7 +303837,7 @@ async function executeDetectSilence(options) {
|
|
|
303467
303837
|
}
|
|
303468
303838
|
if (options.outputPath) {
|
|
303469
303839
|
const outputPath = resolve74(process.cwd(), options.outputPath);
|
|
303470
|
-
await
|
|
303840
|
+
await writeFile44(outputPath, JSON.stringify({ source: absPath, silences }, null, 2), "utf-8");
|
|
303471
303841
|
}
|
|
303472
303842
|
return { success: true, silences };
|
|
303473
303843
|
} catch (error) {
|
|
@@ -303516,7 +303886,7 @@ async function executeDetectBeats(options) {
|
|
|
303516
303886
|
}
|
|
303517
303887
|
if (options.outputPath) {
|
|
303518
303888
|
const outputPath = resolve74(process.cwd(), options.outputPath);
|
|
303519
|
-
await
|
|
303889
|
+
await writeFile44(outputPath, JSON.stringify({ source: absPath, beatCount: beats.length, beats }, null, 2), "utf-8");
|
|
303520
303890
|
}
|
|
303521
303891
|
return { success: true, beats, beatCount: beats.length };
|
|
303522
303892
|
} catch (error) {
|
|
@@ -303620,7 +303990,7 @@ var init_detect = __esm({
|
|
|
303620
303990
|
duration: (i3 < scenes.length - 1 ? scenes[i3 + 1].timestamp : totalDuration) - s2.timestamp
|
|
303621
303991
|
}))
|
|
303622
303992
|
};
|
|
303623
|
-
await
|
|
303993
|
+
await writeFile44(outputPath, JSON.stringify(result, null, 2), "utf-8");
|
|
303624
303994
|
console.log(source_default.green(`Saved to: ${outputPath}`));
|
|
303625
303995
|
}
|
|
303626
303996
|
if (options.project) {
|
|
@@ -303650,7 +304020,7 @@ var init_detect = __esm({
|
|
|
303650
304020
|
sourceEndOffset: end
|
|
303651
304021
|
});
|
|
303652
304022
|
}
|
|
303653
|
-
await
|
|
304023
|
+
await writeFile44(projectPath, JSON.stringify(project.toJSON(), null, 2), "utf-8");
|
|
303654
304024
|
console.log(source_default.green(`Added ${scenes.length} clips to project`));
|
|
303655
304025
|
}
|
|
303656
304026
|
} catch (error) {
|
|
@@ -303732,7 +304102,7 @@ var init_detect = __esm({
|
|
|
303732
304102
|
console.log();
|
|
303733
304103
|
if (options.output) {
|
|
303734
304104
|
const outputPath = resolve74(process.cwd(), options.output);
|
|
303735
|
-
await
|
|
304105
|
+
await writeFile44(
|
|
303736
304106
|
outputPath,
|
|
303737
304107
|
JSON.stringify({ source: absPath, silences }, null, 2),
|
|
303738
304108
|
"utf-8"
|
|
@@ -303817,7 +304187,7 @@ var init_detect = __esm({
|
|
|
303817
304187
|
console.log();
|
|
303818
304188
|
if (options.output) {
|
|
303819
304189
|
const outputPath = resolve74(process.cwd(), options.output);
|
|
303820
|
-
await
|
|
304190
|
+
await writeFile44(
|
|
303821
304191
|
outputPath,
|
|
303822
304192
|
JSON.stringify({ source: absPath, beatCount: beats.length, beats }, null, 2),
|
|
303823
304193
|
"utf-8"
|
|
@@ -303872,8 +304242,9 @@ var EXPLICIT_COMMAND_METADATA = {
|
|
|
303872
304242
|
schema: { surface: "agent", note: "Machine-readable command discovery." },
|
|
303873
304243
|
completion: { surface: "advanced", note: "Shell ergonomics helper." },
|
|
303874
304244
|
agent: {
|
|
303875
|
-
surface: "
|
|
303876
|
-
|
|
304245
|
+
surface: "legacy",
|
|
304246
|
+
replacement: "a host agent (Claude Code, Codex, Cursor) or the MCP server via `vibe host setup`",
|
|
304247
|
+
note: "Deprecated built-in REPL, removed before 1.0."
|
|
303877
304248
|
},
|
|
303878
304249
|
"design.validate": { surface: "public", note: "Validate the DESIGN.md visual contract." },
|
|
303879
304250
|
"generate.image": { surface: "public" },
|
|
@@ -304411,7 +304782,7 @@ init_scene_project();
|
|
|
304411
304782
|
init_project_config();
|
|
304412
304783
|
init_cost_tier();
|
|
304413
304784
|
import { resolve as resolve29, relative as relative8, dirname as dirname24 } from "node:path";
|
|
304414
|
-
import { mkdir as
|
|
304785
|
+
import { mkdir as mkdir12, readFile as readFile14, writeFile as writeFile15, access as access4, copyFile as copyFile3 } from "node:fs/promises";
|
|
304415
304786
|
import { existsSync as existsSync46 } from "node:fs";
|
|
304416
304787
|
|
|
304417
304788
|
// ../cli/src/commands/_shared/scene-html-emit.ts
|
|
@@ -304891,7 +305262,7 @@ init_storyboard_parse();
|
|
|
304891
305262
|
init_storyboard_source();
|
|
304892
305263
|
init_root_sync();
|
|
304893
305264
|
import { existsSync as existsSync44 } from "node:fs";
|
|
304894
|
-
import { mkdir as
|
|
305265
|
+
import { mkdir as mkdir11, writeFile as writeFile13 } from "node:fs/promises";
|
|
304895
305266
|
import { join as join58, resolve as resolve26 } from "node:path";
|
|
304896
305267
|
async function executeSceneSubmit(opts) {
|
|
304897
305268
|
const projectDir = resolve26(opts.projectDir);
|
|
@@ -304985,7 +305356,7 @@ async function executeSceneSubmit(opts) {
|
|
|
304985
305356
|
return { ...base2, success: true };
|
|
304986
305357
|
}
|
|
304987
305358
|
const absPath = join58(projectDir, scenePath);
|
|
304988
|
-
await
|
|
305359
|
+
await mkdir11(join58(projectDir, "compositions"), { recursive: true });
|
|
304989
305360
|
await writeFile13(absPath, html.endsWith("\n") ? html : `${html}
|
|
304990
305361
|
`, "utf-8");
|
|
304991
305362
|
return {
|
|
@@ -305576,7 +305947,7 @@ async function executeSceneAdd(opts) {
|
|
|
305576
305947
|
}
|
|
305577
305948
|
audioRelPath = `assets/narration-${id}.${ext}`;
|
|
305578
305949
|
audioAbsPath = resolve29(projectDir, audioRelPath);
|
|
305579
|
-
await
|
|
305950
|
+
await mkdir12(dirname24(audioAbsPath), { recursive: true });
|
|
305580
305951
|
await copyFile3(sourceAbs, audioAbsPath);
|
|
305581
305952
|
try {
|
|
305582
305953
|
narrationDuration = await getAudioDuration(audioAbsPath);
|
|
@@ -305609,7 +305980,7 @@ async function executeSceneAdd(opts) {
|
|
|
305609
305980
|
}
|
|
305610
305981
|
audioRelPath = `assets/narration-${id}.${resolution.audioExtension}`;
|
|
305611
305982
|
audioAbsPath = resolve29(projectDir, audioRelPath);
|
|
305612
|
-
await
|
|
305983
|
+
await mkdir12(dirname24(audioAbsPath), { recursive: true });
|
|
305613
305984
|
await writeFile15(audioAbsPath, tts.audioBuffer);
|
|
305614
305985
|
try {
|
|
305615
305986
|
narrationDuration = await getAudioDuration(audioAbsPath);
|
|
@@ -305672,7 +306043,7 @@ async function executeSceneAdd(opts) {
|
|
|
305672
306043
|
const img = imageResult.images[0];
|
|
305673
306044
|
imageRelPath = `assets/scene-${id}.png`;
|
|
305674
306045
|
imageAbsPath = resolve29(projectDir, imageRelPath);
|
|
305675
|
-
await
|
|
306046
|
+
await mkdir12(dirname24(imageAbsPath), { recursive: true });
|
|
305676
306047
|
let buffer;
|
|
305677
306048
|
if (img.base64) {
|
|
305678
306049
|
buffer = Buffer.from(img.base64, "base64");
|
|
@@ -305699,7 +306070,7 @@ async function executeSceneAdd(opts) {
|
|
|
305699
306070
|
}
|
|
305700
306071
|
imageRelPath = `assets/scene-${id}.png`;
|
|
305701
306072
|
imageAbsPath = resolve29(projectDir, imageRelPath);
|
|
305702
|
-
await
|
|
306073
|
+
await mkdir12(dirname24(imageAbsPath), { recursive: true });
|
|
305703
306074
|
const buffer = Buffer.from(imageResult.images[0].base64, "base64");
|
|
305704
306075
|
await writeFile15(imageAbsPath, buffer);
|
|
305705
306076
|
}
|
|
@@ -305718,7 +306089,7 @@ async function executeSceneAdd(opts) {
|
|
|
305718
306089
|
}
|
|
305719
306090
|
lottieRelPath = `assets/lottie-${id}.${ext}`;
|
|
305720
306091
|
lottieAbsPath = resolve29(projectDir, lottieRelPath);
|
|
305721
|
-
await
|
|
306092
|
+
await mkdir12(dirname24(lottieAbsPath), { recursive: true });
|
|
305722
306093
|
await copyFile3(sourceAbs, lottieAbsPath);
|
|
305723
306094
|
lottieInput = {
|
|
305724
306095
|
src: lottieRelPath,
|
|
@@ -305788,7 +306159,7 @@ async function executeSceneAdd(opts) {
|
|
|
305788
306159
|
transcript: transcriptWords,
|
|
305789
306160
|
lottie: lottieInput
|
|
305790
306161
|
});
|
|
305791
|
-
await
|
|
306162
|
+
await mkdir12(dirname24(scenePath), { recursive: true });
|
|
305792
306163
|
await writeFile15(scenePath, sceneHtml, "utf-8");
|
|
305793
306164
|
opts.onProgress?.("Updating root composition...");
|
|
305794
306165
|
let start = 0;
|
|
@@ -306005,6 +306376,7 @@ init_scene_build();
|
|
|
306005
306376
|
init_install_skill();
|
|
306006
306377
|
init_compose_prompts();
|
|
306007
306378
|
init_scene_repair();
|
|
306379
|
+
init_build_video_providers();
|
|
306008
306380
|
var SCENE_PRESETS2 = [
|
|
306009
306381
|
"simple",
|
|
306010
306382
|
"announcement",
|
|
@@ -306404,12 +306776,12 @@ var sceneBuildSchema = z3.object({
|
|
|
306404
306776
|
"TTS provider override. Default 'auto' (elevenlabs key > openai key > local kokoro)."
|
|
306405
306777
|
),
|
|
306406
306778
|
voice: z3.string().optional().describe("TTS voice id (provider-specific)."),
|
|
306407
|
-
imageProvider: z3.enum(["openai"]).optional().describe("Image provider for backdrops. Default 'openai' (gpt-image-2)."),
|
|
306408
|
-
videoProvider: z3.enum(
|
|
306779
|
+
imageProvider: z3.enum(["openai"]).optional().describe("Image provider for backdrops. Default 'openai' (gpt-image-2.5-sunburst)."),
|
|
306780
|
+
videoProvider: z3.enum(BUILD_VIDEO_PROVIDERS).optional().describe("Video provider for per-beat video cues. Default seedance."),
|
|
306409
306781
|
musicProvider: z3.enum(["elevenlabs", "replicate"]).optional().describe("Music provider for per-beat music cues. Default elevenlabs."),
|
|
306410
306782
|
imageQuality: z3.enum(["standard", "hd"]).optional().describe("OpenAI image quality. Default 'standard'."),
|
|
306411
306783
|
imageModel: z3.string().optional().describe(
|
|
306412
|
-
"Image model for keyframes/backdrops/character sheets (gemini: flash|pro, openai: gpt-image-2). Provider default when omitted."
|
|
306784
|
+
"Image model for keyframes/backdrops/character sheets (gemini: flash|lite|pro, openai: gpt-image-2.5-sunburst|gpt-image-2.5-flare|gpt-image-2). Provider default when omitted."
|
|
306413
306785
|
),
|
|
306414
306786
|
imageSize: z3.enum(["1024x1024", "1536x1024", "1024x1536"]).optional().describe("OpenAI image size. Default '1536x1024' (cinematic 16:9-ish)."),
|
|
306415
306787
|
maxCostUsd: z3.number().optional().describe("Fail before provider spend when estimated cost exceeds this USD cap."),
|
|
@@ -306842,7 +307214,7 @@ init_api_key();
|
|
|
306842
307214
|
init_exec_safe();
|
|
306843
307215
|
init_remotion();
|
|
306844
307216
|
import { resolve as resolve53, dirname as dirname36, basename as basename14 } from "node:path";
|
|
306845
|
-
import { writeFile as
|
|
307217
|
+
import { writeFile as writeFile33, mkdir as mkdir25, rm as rm10 } from "node:fs/promises";
|
|
306846
307218
|
import { existsSync as existsSync73 } from "node:fs";
|
|
306847
307219
|
import { tmpdir as tmpdir11 } from "node:os";
|
|
306848
307220
|
var ASS_STYLES = ["karaoke-sweep", "typewriter"];
|
|
@@ -306994,7 +307366,7 @@ async function executeAnimatedCaption(options) {
|
|
|
306994
307366
|
}
|
|
306995
307367
|
const effectiveFontSize = fontSize ?? Math.round(height * 0.04);
|
|
306996
307368
|
const tmpAudioDir = resolve53(tmpdir11(), `vf-ac-${Date.now()}`);
|
|
306997
|
-
await
|
|
307369
|
+
await mkdir25(tmpAudioDir, { recursive: true });
|
|
306998
307370
|
const audioPath = resolve53(tmpAudioDir, "audio.wav");
|
|
306999
307371
|
await execSafe("ffmpeg", [
|
|
307000
307372
|
"-y",
|
|
@@ -307011,13 +307383,13 @@ async function executeAnimatedCaption(options) {
|
|
|
307011
307383
|
], { timeout: 12e4 });
|
|
307012
307384
|
const apiKey = await getApiKey("OPENAI_API_KEY", "OpenAI");
|
|
307013
307385
|
if (!apiKey) {
|
|
307014
|
-
await
|
|
307386
|
+
await rm10(tmpAudioDir, { recursive: true, force: true }).catch(() => {
|
|
307015
307387
|
});
|
|
307016
307388
|
return { success: false, error: "OPENAI_API_KEY required for Whisper transcription. Run 'vibe setup' or set OPENAI_API_KEY in .env" };
|
|
307017
307389
|
}
|
|
307018
307390
|
const transcript = await transcribeWithWords(audioPath, apiKey, language);
|
|
307019
307391
|
if (!transcript.words || transcript.words.length === 0) {
|
|
307020
|
-
await
|
|
307392
|
+
await rm10(tmpAudioDir, { recursive: true, force: true }).catch(() => {
|
|
307021
307393
|
});
|
|
307022
307394
|
return { success: false, error: "No words detected in transcription" };
|
|
307023
307395
|
}
|
|
@@ -307025,7 +307397,7 @@ async function executeAnimatedCaption(options) {
|
|
|
307025
307397
|
const absOutputPath = resolve53(process.cwd(), outputPath);
|
|
307026
307398
|
const outDir = dirname36(absOutputPath);
|
|
307027
307399
|
if (!existsSync73(outDir)) {
|
|
307028
|
-
await
|
|
307400
|
+
await mkdir25(outDir, { recursive: true });
|
|
307029
307401
|
}
|
|
307030
307402
|
if (tier === "ass") {
|
|
307031
307403
|
const assContent = generateASS(
|
|
@@ -307034,7 +307406,7 @@ async function executeAnimatedCaption(options) {
|
|
|
307034
307406
|
{ highlightColor, fontSize: effectiveFontSize, position, width, height }
|
|
307035
307407
|
);
|
|
307036
307408
|
const assPath = resolve53(tmpAudioDir, "captions.ass");
|
|
307037
|
-
await
|
|
307409
|
+
await writeFile33(assPath, assContent, "utf-8");
|
|
307038
307410
|
const escapedAssPath = assPath.replace(/\\/g, "\\\\").replace(/:/g, "\\:");
|
|
307039
307411
|
await execSafe("ffmpeg", [
|
|
307040
307412
|
"-y",
|
|
@@ -307071,12 +307443,12 @@ async function executeAnimatedCaption(options) {
|
|
|
307071
307443
|
outputPath: absOutputPath
|
|
307072
307444
|
});
|
|
307073
307445
|
if (!renderResult.success) {
|
|
307074
|
-
await
|
|
307446
|
+
await rm10(tmpAudioDir, { recursive: true, force: true }).catch(() => {
|
|
307075
307447
|
});
|
|
307076
307448
|
return { success: false, error: renderResult.error };
|
|
307077
307449
|
}
|
|
307078
307450
|
}
|
|
307079
|
-
await
|
|
307451
|
+
await rm10(tmpAudioDir, { recursive: true, force: true }).catch(() => {
|
|
307080
307452
|
});
|
|
307081
307453
|
return {
|
|
307082
307454
|
success: true,
|
|
@@ -307485,7 +307857,7 @@ var editImageTool = defineTool({
|
|
|
307485
307857
|
imagePaths: z5.array(z5.string()).describe("Input image file path(s)"),
|
|
307486
307858
|
prompt: z5.string().describe("Edit instruction"),
|
|
307487
307859
|
output: z5.string().optional().describe("Output file path (default: edited.png)"),
|
|
307488
|
-
model: z5.enum(["flash", "3.1-flash", "latest", "pro"]).optional().describe("Gemini model (default: flash)"),
|
|
307860
|
+
model: z5.enum(["flash", "3.1-flash", "latest", "lite", "pro"]).optional().describe("Gemini model (default: flash = Nano Banana 2)"),
|
|
307489
307861
|
ratio: z5.string().optional().describe("Output aspect ratio"),
|
|
307490
307862
|
resolution: z5.string().optional().describe("Resolution: 1K, 2K, 4K (Pro only)")
|
|
307491
307863
|
}),
|
|
@@ -309338,7 +309710,7 @@ var generateSoundEffectTool = defineTool({
|
|
|
309338
309710
|
schema: z7.object({
|
|
309339
309711
|
prompt: z7.string().describe("Description of the sound effect"),
|
|
309340
309712
|
output: z7.string().optional().describe("Output audio file path (default: sound-effect.mp3)"),
|
|
309341
|
-
duration: z7.number().optional().describe("Duration in seconds (0.5-
|
|
309713
|
+
duration: z7.number().optional().describe("Duration in seconds (0.5-30, default: auto)"),
|
|
309342
309714
|
promptInfluence: z7.number().optional().describe("Prompt influence 0-1 (default: 0.3)")
|
|
309343
309715
|
}),
|
|
309344
309716
|
async execute(args) {
|
|
@@ -309415,7 +309787,7 @@ var generateImageTool = defineTool({
|
|
|
309415
309787
|
ratio: z7.string().optional().describe("Aspect ratio for Gemini (1:1, 16:9, 9:16, 4:3, 3:4, etc.)"),
|
|
309416
309788
|
quality: z7.string().optional().describe("Quality for OpenAI: standard, hd"),
|
|
309417
309789
|
count: z7.number().optional().describe("Number of images (default: 1)"),
|
|
309418
|
-
model: z7.string().optional().describe("
|
|
309790
|
+
model: z7.string().optional().describe("Image model. Gemini: flash (default), lite, pro. OpenAI: 2.5 (default), flare, 2, 1.5. Grok: pro")
|
|
309419
309791
|
}),
|
|
309420
309792
|
async execute(args) {
|
|
309421
309793
|
const result = await executeImageGenerate(args);
|
|
@@ -309478,9 +309850,11 @@ var generateVideoTool = defineTool({
|
|
|
309478
309850
|
mode: z7.string().optional().describe("Kling mode: std or pro"),
|
|
309479
309851
|
negative: z7.string().optional().describe("Negative prompt (Seedance/Kling/Veo)"),
|
|
309480
309852
|
resolution: z7.string().optional().describe("Resolution: 480p, 720p, 1080p, or 4k depending on provider"),
|
|
309481
|
-
veoModel: z7.string().optional().describe("Veo model: 3.
|
|
309853
|
+
veoModel: z7.string().optional().describe("Veo model: 3.1, 3.1-fast"),
|
|
309482
309854
|
runwayModel: z7.string().optional().describe("Runway model: gen4.5, gen4_turbo"),
|
|
309483
|
-
seedanceModel: z7.string().optional().describe("Seedance variant: quality
|
|
309855
|
+
seedanceModel: z7.string().optional().describe("Seedance variant: quality (2.0), fast, or 2.5 (fal.ai only)"),
|
|
309856
|
+
grokModel: z7.string().optional().describe("Grok video model: 1.5 (default), lite, classic"),
|
|
309857
|
+
klingModel: z7.string().optional().describe("Kling model: v3 (default), v2.6, v2.5-turbo"),
|
|
309484
309858
|
generateAudio: z7.boolean().optional().describe("Generate native synchronized audio when supported"),
|
|
309485
309859
|
output: z7.string().optional().describe("Output file path (downloads video)"),
|
|
309486
309860
|
wait: z7.boolean().optional().describe("Wait for completion (default: true)")
|
|
@@ -309552,7 +309926,7 @@ var generateVideoExtendTool = defineTool({
|
|
|
309552
309926
|
prompt: z7.string().optional().describe("Continuation prompt"),
|
|
309553
309927
|
duration: z7.number().optional().describe("Duration in seconds"),
|
|
309554
309928
|
negative: z7.string().optional().describe("Negative prompt (Kling)"),
|
|
309555
|
-
veoModel: z7.string().optional().describe("Veo model: 3.
|
|
309929
|
+
veoModel: z7.string().optional().describe("Veo model: 3.1, 3.1-fast"),
|
|
309556
309930
|
output: z7.string().optional().describe("Output file path"),
|
|
309557
309931
|
wait: z7.boolean().optional().describe("Wait for completion (default: true)")
|
|
309558
309932
|
}),
|
|
@@ -309588,7 +309962,7 @@ var generateTools = [
|
|
|
309588
309962
|
|
|
309589
309963
|
// ../cli/src/tools/manifest/storyboard.ts
|
|
309590
309964
|
import { existsSync as existsSync81 } from "node:fs";
|
|
309591
|
-
import { readFile as readFile38, writeFile as
|
|
309965
|
+
import { readFile as readFile38, writeFile as writeFile42 } from "node:fs/promises";
|
|
309592
309966
|
import { resolve as resolve70 } from "node:path";
|
|
309593
309967
|
import { z as z9 } from "zod";
|
|
309594
309968
|
init_storyboard_parse();
|
|
@@ -309596,7 +309970,7 @@ init_storyboard_edit();
|
|
|
309596
309970
|
|
|
309597
309971
|
// ../cli/src/commands/_shared/storyboard-revise.ts
|
|
309598
309972
|
import { existsSync as existsSync80 } from "node:fs";
|
|
309599
|
-
import { readFile as readFile37, writeFile as
|
|
309973
|
+
import { readFile as readFile37, writeFile as writeFile41 } from "node:fs/promises";
|
|
309600
309974
|
import { join as join74, resolve as resolve69 } from "node:path";
|
|
309601
309975
|
|
|
309602
309976
|
// ../cli/src/agent/adapters/index.ts
|
|
@@ -309765,7 +310139,7 @@ async function executeStoryboardRevision(opts) {
|
|
|
309765
310139
|
if (loaded.layout === "bundle") {
|
|
309766
310140
|
await rewriteBundleFromMarkdown(projectDir, storyboardMd);
|
|
309767
310141
|
} else {
|
|
309768
|
-
await
|
|
310142
|
+
await writeFile41(storyboardPath, storyboardMd, "utf-8");
|
|
309769
310143
|
}
|
|
309770
310144
|
}
|
|
309771
310145
|
const changedBeats = unique5([...diffChangedBeats(currentStoryboard, storyboardMd), ...payload.changedBeats]);
|
|
@@ -309943,6 +310317,7 @@ function stripUndefined4(value) {
|
|
|
309943
310317
|
|
|
309944
310318
|
// ../cli/src/tools/manifest/storyboard.ts
|
|
309945
310319
|
init_build_plan();
|
|
310320
|
+
init_build_video_providers();
|
|
309946
310321
|
var PROJECT_DIR_DESCRIPTION3 = "Project directory. Defaults to the surface's cwd; in MCP hosts, relative paths resolve under the configured server workspace.";
|
|
309947
310322
|
var projectDirSchema = z9.object({
|
|
309948
310323
|
projectDir: z9.string().optional().describe(PROJECT_DIR_DESCRIPTION3)
|
|
@@ -310063,7 +310438,7 @@ var storyboardSetTool = defineTool({
|
|
|
310063
310438
|
value,
|
|
310064
310439
|
unset: args.unset
|
|
310065
310440
|
});
|
|
310066
|
-
await
|
|
310441
|
+
await writeFile42(file.path, next, "utf-8");
|
|
310067
310442
|
return {
|
|
310068
310443
|
success: true,
|
|
310069
310444
|
data: { beat: args.beat, key: args.key },
|
|
@@ -310095,7 +310470,7 @@ var storyboardMoveTool = defineTool({
|
|
|
310095
310470
|
beatId: args.beat,
|
|
310096
310471
|
afterBeatId: args.after
|
|
310097
310472
|
});
|
|
310098
|
-
await
|
|
310473
|
+
await writeFile42(file.path, next, "utf-8");
|
|
310099
310474
|
return {
|
|
310100
310475
|
success: true,
|
|
310101
310476
|
data: { beat: args.beat, after: args.after },
|
|
@@ -310160,7 +310535,7 @@ var planTool = defineTool({
|
|
|
310160
310535
|
imageProvider: z9.string().optional().describe("Image provider override."),
|
|
310161
310536
|
imageQuality: z9.enum(["standard", "hd"]).optional().describe("Image quality override."),
|
|
310162
310537
|
imageSize: z9.string().optional().describe("Image size override."),
|
|
310163
|
-
videoProvider: z9.enum(
|
|
310538
|
+
videoProvider: z9.enum(BUILD_VIDEO_PROVIDERS).optional().describe("Video provider override."),
|
|
310164
310539
|
musicProvider: z9.enum(["elevenlabs", "replicate"]).optional().describe("Music provider override."),
|
|
310165
310540
|
composer: z9.enum(["claude", "openai", "gemini"]).optional().describe("Composer provider override."),
|
|
310166
310541
|
force: z9.boolean().optional().describe("Plan regeneration even when outputs exist.")
|
|
@@ -310249,14 +310624,14 @@ var designValidateTool = defineTool({
|
|
|
310249
310624
|
var designTools = [designValidateTool];
|
|
310250
310625
|
|
|
310251
310626
|
// ../cli/src/tools/manifest/remix.ts
|
|
310252
|
-
import { writeFile as
|
|
310627
|
+
import { writeFile as writeFile46 } from "node:fs/promises";
|
|
310253
310628
|
import { tmpdir as tmpdir12 } from "node:os";
|
|
310254
310629
|
import { join as join76 } from "node:path";
|
|
310255
310630
|
import { z as z11 } from "zod";
|
|
310256
310631
|
|
|
310257
310632
|
// ../cli/src/commands/ai-highlights.ts
|
|
310258
|
-
import { readFile as readFile40, writeFile as
|
|
310259
|
-
import { resolve as resolve73, dirname as dirname40, basename as basename19, extname as
|
|
310633
|
+
import { readFile as readFile40, writeFile as writeFile43, mkdir as mkdir29 } from "node:fs/promises";
|
|
310634
|
+
import { resolve as resolve73, dirname as dirname40, basename as basename19, extname as extname19 } from "node:path";
|
|
310260
310635
|
import { existsSync as existsSync83 } from "node:fs";
|
|
310261
310636
|
init_dist();
|
|
310262
310637
|
init_engine();
|
|
@@ -310291,7 +310666,7 @@ async function executeHighlights(options) {
|
|
|
310291
310666
|
if (!existsSync83(absPath)) {
|
|
310292
310667
|
return { success: false, highlights: [], totalDuration: 0, totalHighlightDuration: 0, error: `File not found: ${absPath}` };
|
|
310293
310668
|
}
|
|
310294
|
-
const ext =
|
|
310669
|
+
const ext = extname19(absPath).toLowerCase();
|
|
310295
310670
|
const videoExtensions = [".mp4", ".mov", ".avi", ".mkv", ".webm", ".m4v"];
|
|
310296
310671
|
const isVideo = videoExtensions.includes(ext);
|
|
310297
310672
|
const targetDuration = options.duration;
|
|
@@ -310436,7 +310811,7 @@ Analyze both what is SHOWN (visual cues, actions, expressions) and what is SAID
|
|
|
310436
310811
|
};
|
|
310437
310812
|
if (options.output) {
|
|
310438
310813
|
const outputPath = resolve73(process.cwd(), options.output);
|
|
310439
|
-
await
|
|
310814
|
+
await writeFile43(outputPath, JSON.stringify({
|
|
310440
310815
|
sourceFile: absPath,
|
|
310441
310816
|
totalDuration: sourceDuration,
|
|
310442
310817
|
criteria: options.criteria || "all",
|
|
@@ -310471,7 +310846,7 @@ Analyze both what is SHOWN (visual cues, actions, expressions) and what is SAID
|
|
|
310471
310846
|
}
|
|
310472
310847
|
}
|
|
310473
310848
|
const projectPath = resolve73(process.cwd(), options.project);
|
|
310474
|
-
await
|
|
310849
|
+
await writeFile43(projectPath, JSON.stringify(project.toJSON(), null, 2), "utf-8");
|
|
310475
310850
|
extractResult.projectPath = projectPath;
|
|
310476
310851
|
}
|
|
310477
310852
|
return extractResult;
|
|
@@ -310620,7 +310995,7 @@ Analyze both VISUALS (expressions, actions, scene changes) and AUDIO (speech, re
|
|
|
310620
310995
|
}
|
|
310621
310996
|
const outputDir = options.outputDir ? resolve73(process.cwd(), options.outputDir) : dirname40(absPath);
|
|
310622
310997
|
if (options.outputDir && !existsSync83(outputDir)) {
|
|
310623
|
-
await
|
|
310998
|
+
await mkdir29(outputDir, { recursive: true });
|
|
310624
310999
|
}
|
|
310625
311000
|
const result = {
|
|
310626
311001
|
success: true,
|
|
@@ -310628,7 +311003,7 @@ Analyze both VISUALS (expressions, actions, scene changes) and AUDIO (speech, re
|
|
|
310628
311003
|
};
|
|
310629
311004
|
for (let i3 = 0; i3 < selectedHighlights.length; i3++) {
|
|
310630
311005
|
const h2 = selectedHighlights[i3];
|
|
310631
|
-
const baseName = basename19(absPath,
|
|
311006
|
+
const baseName = basename19(absPath, extname19(absPath));
|
|
310632
311007
|
const outputPath = resolve73(outputDir, `${baseName}-short-${i3 + 1}.mp4`);
|
|
310633
311008
|
const { stdout: probeOut } = await execSafe("ffprobe", [
|
|
310634
311009
|
"-v",
|
|
@@ -310698,7 +311073,7 @@ Analyze both VISUALS (expressions, actions, scene changes) and AUDIO (speech, re
|
|
|
310698
311073
|
// ../cli/src/pipeline/executor.ts
|
|
310699
311074
|
var import_yaml8 = __toESM(require_dist3(), 1);
|
|
310700
311075
|
import { resolve as resolve75 } from "node:path";
|
|
310701
|
-
import { readFile as readFile42, writeFile as
|
|
311076
|
+
import { readFile as readFile42, writeFile as writeFile45, mkdir as mkdir30 } from "node:fs/promises";
|
|
310702
311077
|
import { existsSync as existsSync84 } from "node:fs";
|
|
310703
311078
|
|
|
310704
311079
|
// ../cli/src/pipeline/resolver.ts
|
|
@@ -310760,6 +311135,7 @@ function findUnresolvedRefs(params, availableStepIds) {
|
|
|
310760
311135
|
init_output();
|
|
310761
311136
|
init_config();
|
|
310762
311137
|
init_provider_resolver();
|
|
311138
|
+
init_build_video_providers();
|
|
310763
311139
|
var ACTION_METADATA = {
|
|
310764
311140
|
"generate-image": { id: "generate-image", title: "Generate image", category: "generate", command: "generate image", outputs: ["image"] },
|
|
310765
311141
|
"generate-video": { id: "generate-video", title: "Generate video", category: "generate", command: "generate video", outputs: ["video"], requiredKeys: ["provider-dependent"] },
|
|
@@ -310833,7 +311209,7 @@ async function resolvePipelineVideoProvider(provider) {
|
|
|
310833
311209
|
if (explicit === "fal") return "seedance";
|
|
310834
311210
|
if (explicit) return explicit;
|
|
310835
311211
|
await loadProviderDefaults();
|
|
310836
|
-
return resolveProvider("video")?.name ?? "grok";
|
|
311212
|
+
return resolveBuildVideoProvider(resolveProvider("video")?.name ?? "grok");
|
|
310837
311213
|
}
|
|
310838
311214
|
function providerKeyForImage(provider) {
|
|
310839
311215
|
switch (provider) {
|
|
@@ -310859,6 +311235,7 @@ function providerKeyForVideo(provider) {
|
|
|
310859
311235
|
case "runway":
|
|
310860
311236
|
return "runway";
|
|
310861
311237
|
case "veo":
|
|
311238
|
+
case "omni":
|
|
310862
311239
|
return "google";
|
|
310863
311240
|
default:
|
|
310864
311241
|
return void 0;
|
|
@@ -311110,7 +311487,7 @@ var CHECKPOINT_FILE = ".pipeline-state.yaml";
|
|
|
311110
311487
|
async function executePipeline(manifest2, options = {}) {
|
|
311111
311488
|
await ensureActionsRegistered();
|
|
311112
311489
|
const outputDir = resolve75(process.cwd(), options.outputDir || `${manifest2.name}-output`);
|
|
311113
|
-
await
|
|
311490
|
+
await mkdir30(outputDir, { recursive: true });
|
|
311114
311491
|
const completedSteps = /* @__PURE__ */ new Map();
|
|
311115
311492
|
const results = [];
|
|
311116
311493
|
const startTime = Date.now();
|
|
@@ -311235,7 +311612,7 @@ async function executePipeline(manifest2, options = {}) {
|
|
|
311235
311612
|
data: s2.data
|
|
311236
311613
|
}))
|
|
311237
311614
|
};
|
|
311238
|
-
await
|
|
311615
|
+
await writeFile45(
|
|
311239
311616
|
resolve75(outputDir, CHECKPOINT_FILE),
|
|
311240
311617
|
(0, import_yaml8.stringify)(checkpoint, { indent: 2 }),
|
|
311241
311618
|
"utf-8"
|
|
@@ -311390,7 +311767,7 @@ var pipelineRunTool = defineTool({
|
|
|
311390
311767
|
let tempPath;
|
|
311391
311768
|
if (args.pipelineYaml) {
|
|
311392
311769
|
tempPath = join76(tmpdir12(), `vibe-mcp-pipeline-${Date.now()}.yaml`);
|
|
311393
|
-
await
|
|
311770
|
+
await writeFile46(tempPath, args.pipelineYaml, "utf-8");
|
|
311394
311771
|
resolvedPath = tempPath;
|
|
311395
311772
|
}
|
|
311396
311773
|
try {
|
|
@@ -311527,7 +311904,7 @@ var detectTools = [
|
|
|
311527
311904
|
|
|
311528
311905
|
// ../cli/src/tools/manifest/timeline.ts
|
|
311529
311906
|
import { z as z13 } from "zod";
|
|
311530
|
-
import { mkdir as
|
|
311907
|
+
import { mkdir as mkdir31, writeFile as writeFile48 } from "node:fs/promises";
|
|
311531
311908
|
import { basename as basename21, resolve as resolve76 } from "node:path";
|
|
311532
311909
|
init_engine();
|
|
311533
311910
|
init_project_resolver();
|
|
@@ -311535,7 +311912,7 @@ init_project_resolver();
|
|
|
311535
311912
|
// ../cli/src/tools/manifest/_project-io.ts
|
|
311536
311913
|
init_engine();
|
|
311537
311914
|
init_project_resolver();
|
|
311538
|
-
import { readFile as readFile43, writeFile as
|
|
311915
|
+
import { readFile as readFile43, writeFile as writeFile47 } from "node:fs/promises";
|
|
311539
311916
|
async function loadProject(projectPath, cwd) {
|
|
311540
311917
|
const absPath = await resolveTimelineFile(projectPath, cwd);
|
|
311541
311918
|
const content = await readFile43(absPath, "utf-8");
|
|
@@ -311543,7 +311920,7 @@ async function loadProject(projectPath, cwd) {
|
|
|
311543
311920
|
return { project: Project.fromJSON(data2), absPath };
|
|
311544
311921
|
}
|
|
311545
311922
|
async function saveProject(absPath, project) {
|
|
311546
|
-
await
|
|
311923
|
+
await writeFile47(absPath, JSON.stringify(project.toJSON(), null, 2), "utf-8");
|
|
311547
311924
|
}
|
|
311548
311925
|
|
|
311549
311926
|
// ../cli/src/tools/manifest/timeline.ts
|
|
@@ -311583,10 +311960,10 @@ var timelineCreateTool = defineTool({
|
|
|
311583
311960
|
outputPath = resolve76(ctx.workingDirectory, args.outputPath);
|
|
311584
311961
|
} else {
|
|
311585
311962
|
const dirPath = resolve76(ctx.workingDirectory, args.name);
|
|
311586
|
-
await
|
|
311963
|
+
await mkdir31(dirPath, { recursive: true });
|
|
311587
311964
|
outputPath = resolve76(dirPath, TIMELINE_FILENAME);
|
|
311588
311965
|
}
|
|
311589
|
-
await
|
|
311966
|
+
await writeFile48(outputPath, JSON.stringify(project.toJSON(), null, 2), "utf-8");
|
|
311590
311967
|
return {
|
|
311591
311968
|
success: true,
|
|
311592
311969
|
data: { name: projectName, outputPath },
|
|
@@ -311884,7 +312261,7 @@ var timelineTools = [
|
|
|
311884
312261
|
// ../cli/src/tools/manifest/project.ts
|
|
311885
312262
|
import { z as z14 } from "zod";
|
|
311886
312263
|
import { resolve as resolve78 } from "node:path";
|
|
311887
|
-
import { writeFile as
|
|
312264
|
+
import { writeFile as writeFile49 } from "node:fs/promises";
|
|
311888
312265
|
init_engine();
|
|
311889
312266
|
|
|
311890
312267
|
// ../cli/src/commands/_shared/project-list.ts
|
|
@@ -312042,7 +312419,7 @@ var projectCreateTool = defineTool({
|
|
|
312042
312419
|
const outputPath = resolve78(ctx.workingDirectory, args.outputPath ?? `${args.name}.vibe.json`);
|
|
312043
312420
|
const project = new Project(args.name);
|
|
312044
312421
|
if (args.fps) project.setFrameRate(args.fps);
|
|
312045
|
-
await
|
|
312422
|
+
await writeFile49(outputPath, JSON.stringify(project.toJSON(), null, 2), "utf-8");
|
|
312046
312423
|
return {
|
|
312047
312424
|
success: true,
|
|
312048
312425
|
data: { name: args.name, outputPath },
|
|
@@ -312763,8 +313140,8 @@ var exportVideoTool = defineTool({
|
|
|
312763
313140
|
var exportTools = [exportVideoTool];
|
|
312764
313141
|
|
|
312765
313142
|
// ../cli/src/tools/manifest/agent-only.ts
|
|
312766
|
-
import { readFile as readFile46, writeFile as
|
|
312767
|
-
import { resolve as resolve81, join as join78, basename as basename23, extname as
|
|
313143
|
+
import { readFile as readFile46, writeFile as writeFile50, readdir as readdir11, stat as stat10, access as access7, unlink as unlink5 } from "node:fs/promises";
|
|
313144
|
+
import { resolve as resolve81, join as join78, basename as basename23, extname as extname20 } from "node:path";
|
|
312768
313145
|
import { z as z16 } from "zod";
|
|
312769
313146
|
init_engine();
|
|
312770
313147
|
init_exec_safe();
|
|
@@ -312787,7 +313164,7 @@ function formatSize(bytes) {
|
|
|
312787
313164
|
return `${size.toFixed(1)}${units2[unit]}`;
|
|
312788
313165
|
}
|
|
312789
313166
|
function detectMediaType(filePath) {
|
|
312790
|
-
const ext =
|
|
313167
|
+
const ext = extname20(filePath).toLowerCase();
|
|
312791
313168
|
if ([".mp4", ".mov", ".avi", ".mkv", ".webm", ".m4v"].includes(ext)) return "video";
|
|
312792
313169
|
if ([".mp3", ".wav", ".aac", ".flac", ".ogg", ".m4a"].includes(ext)) return "audio";
|
|
312793
313170
|
if ([".jpg", ".jpeg", ".png", ".gif", ".webp", ".bmp"].includes(ext)) return "image";
|
|
@@ -312814,7 +313191,7 @@ function isMediaFile(filePath) {
|
|
|
312814
313191
|
".webp",
|
|
312815
313192
|
".bmp"
|
|
312816
313193
|
];
|
|
312817
|
-
return mediaExts.includes(
|
|
313194
|
+
return mediaExts.includes(extname20(filePath).toLowerCase());
|
|
312818
313195
|
}
|
|
312819
313196
|
async function getMediaDuration2(filePath) {
|
|
312820
313197
|
try {
|
|
@@ -312897,7 +313274,7 @@ var fsWriteTool = defineTool({
|
|
|
312897
313274
|
async execute(args, ctx) {
|
|
312898
313275
|
try {
|
|
312899
313276
|
const absPath = resolve81(ctx.workingDirectory, args.path);
|
|
312900
|
-
await
|
|
313277
|
+
await writeFile50(absPath, args.content, "utf-8");
|
|
312901
313278
|
return { success: true, data: { bytes: args.content.length }, humanLines: [`File written: ${args.path} (${formatSize(args.content.length)})`] };
|
|
312902
313279
|
} catch (error) {
|
|
312903
313280
|
return { success: false, error: `Failed to write file: ${error instanceof Error ? error.message : String(error)}` };
|
|
@@ -312960,7 +313337,7 @@ var batchImportTool = defineTool({
|
|
|
312960
313337
|
if (entry.isDirectory() && recursive) {
|
|
312961
313338
|
await scanDir(entryPath);
|
|
312962
313339
|
} else if (entry.isFile()) {
|
|
312963
|
-
const ext =
|
|
313340
|
+
const ext = extname20(entry.name).toLowerCase();
|
|
312964
313341
|
const matchesFilter = !filterExts || filterExts.includes(ext);
|
|
312965
313342
|
if (matchesFilter && isMediaFile(entryPath)) mediaFiles.push(entryPath);
|
|
312966
313343
|
}
|
|
@@ -312983,7 +313360,7 @@ var batchImportTool = defineTool({
|
|
|
312983
313360
|
const source3 = project.addSource({ name: mediaName, type: mediaType, url: mediaFile, duration });
|
|
312984
313361
|
addedSources.push({ id: source3.id, name: mediaName, type: mediaType });
|
|
312985
313362
|
}
|
|
312986
|
-
await
|
|
313363
|
+
await writeFile50(filePath, JSON.stringify(project.toJSON(), null, 2), "utf-8");
|
|
312987
313364
|
return {
|
|
312988
313365
|
success: true,
|
|
312989
313366
|
data: { count: addedSources.length, sources: addedSources },
|
|
@@ -313053,7 +313430,7 @@ var batchConcatTool = defineTool({
|
|
|
313053
313430
|
createdClips.push({ id: clip.id, sourceName: source3.name, startTime: currentTime, duration: source3.duration });
|
|
313054
313431
|
currentTime += source3.duration + gap;
|
|
313055
313432
|
}
|
|
313056
|
-
await
|
|
313433
|
+
await writeFile50(filePath, JSON.stringify(project.toJSON(), null, 2), "utf-8");
|
|
313057
313434
|
const totalDuration = currentTime - gap - startTime;
|
|
313058
313435
|
return {
|
|
313059
313436
|
success: true,
|
|
@@ -313116,7 +313493,7 @@ var batchApplyEffectTool = defineTool({
|
|
|
313116
313493
|
});
|
|
313117
313494
|
if (effect) appliedEffects.push({ clipId: clip.id, effectId: effect.id });
|
|
313118
313495
|
}
|
|
313119
|
-
await
|
|
313496
|
+
await writeFile50(filePath, JSON.stringify(project.toJSON(), null, 2), "utf-8");
|
|
313120
313497
|
return {
|
|
313121
313498
|
success: true,
|
|
313122
313499
|
data: { applied: appliedEffects.length, effectType: args.effectType },
|
|
@@ -313185,7 +313562,7 @@ var timelineClearTool = defineTool({
|
|
|
313185
313562
|
removed.sources++;
|
|
313186
313563
|
}
|
|
313187
313564
|
}
|
|
313188
|
-
await
|
|
313565
|
+
await writeFile50(filePath, JSON.stringify(project.toJSON(), null, 2), "utf-8");
|
|
313189
313566
|
const parts = [];
|
|
313190
313567
|
if (removed.clips > 0) parts.push(`${removed.clips} clips`);
|
|
313191
313568
|
if (removed.tracks > 0) parts.push(`${removed.tracks} tracks`);
|
|
@@ -313236,7 +313613,7 @@ var projectSetTool = defineTool({
|
|
|
313236
313613
|
project.setFrameRate(args.fps);
|
|
313237
313614
|
updates.push(`Frame Rate: ${args.fps} fps`);
|
|
313238
313615
|
}
|
|
313239
|
-
await
|
|
313616
|
+
await writeFile50(filePath, JSON.stringify(project.toJSON(), null, 2), "utf-8");
|
|
313240
313617
|
return {
|
|
313241
313618
|
success: true,
|
|
313242
313619
|
data: { updates },
|
|
@@ -313606,7 +313983,7 @@ var mediaConcatTool = defineTool({
|
|
|
313606
313983
|
} else {
|
|
313607
313984
|
const tempList = resolve81(ctx.workingDirectory, `concat-list-${Date.now()}.txt`);
|
|
313608
313985
|
const listContent = args.inputs.map((i3) => `file '${resolve81(ctx.workingDirectory, i3)}'`).join("\n");
|
|
313609
|
-
await
|
|
313986
|
+
await writeFile50(tempList, listContent, "utf-8");
|
|
313610
313987
|
try {
|
|
313611
313988
|
await execSafe(
|
|
313612
313989
|
"ffmpeg",
|
|
@@ -313900,8 +314277,9 @@ they want for a given task. This guide is the operator-facing summary.
|
|
|
313900
314277
|
|
|
313901
314278
|
If you already use Claude Code, Codex, Cursor, Aider, Gemini CLI, OpenCode,
|
|
313902
314279
|
or another coding agent, let that host drive \`vibe\` directly through shell
|
|
313903
|
-
commands plus \`AGENTS.md\` / \`CLAUDE.md\`.
|
|
313904
|
-
|
|
314280
|
+
commands plus \`AGENTS.md\` / \`CLAUDE.md\`. Without a coding agent, connect
|
|
314281
|
+
the MCP server to Claude Desktop or ChatGPT (\`vibe host setup\`).
|
|
314282
|
+
\`vibe agent\` is deprecated and will be removed before 1.0.
|
|
313905
314283
|
|
|
313906
314284
|
## TL;DR
|
|
313907
314285
|
|
|
@@ -313912,12 +314290,12 @@ built-in fallback when you do not already have an agent host.
|
|
|
313912
314290
|
| **Reproducibility** | none | high (idempotent) | highest (checkpointed) |
|
|
313913
314291
|
| **Budget caps** | per-session max-turns | none | \`--budget-usd\`, \`--budget-tokens\`, \`--max-errors\` |
|
|
313914
314292
|
| **Resume after crash** | no | re-invoke | \`--resume\` |
|
|
313915
|
-
| **Best for** |
|
|
314293
|
+
| **Best for** | deprecated; use a host agent | finished script | repeatable workflows |
|
|
313916
314294
|
|
|
313917
314295
|
## Decision tree
|
|
313918
314296
|
|
|
313919
314297
|
- "I am already in Claude Code/Codex/Cursor/etc." \u2192 regular \`vibe\` shell commands + \`vibe guide\` / \`vibe schema\`
|
|
313920
|
-
- "I
|
|
314298
|
+
- "I do not use a coding agent" \u2192 the MCP server in Claude Desktop or ChatGPT (\`vibe host setup\`)
|
|
313921
314299
|
- "I have a finished script + visual identity" \u2192 \`vibe build\`
|
|
313922
314300
|
- "I want this to run again next month" \u2192 \`vibe run\`
|
|
313923
314301
|
|
|
@@ -313943,9 +314321,6 @@ agent calls them through a tool manifest; \`build\` calls a curated subset
|
|
|
313943
314321
|
- \`vibe build\` is conceptually a 4-step pipeline; \`vibe run\` could express
|
|
313944
314322
|
the same flow but build's STORYBOARD.md input + opinionated defaults are
|
|
313945
314323
|
the value-add.
|
|
313946
|
-
- \`vibe agent\`'s tool registry currently exposes primitives, not
|
|
313947
|
-
orchestrators. Adding \`vibe.build\` / \`vibe.run\` as agent tools is on the
|
|
313948
|
-
table for a future major.
|
|
313949
314324
|
- \`vibe run --resume\` has no analog in build/agent; build's idempotent
|
|
313950
314325
|
re-invoke covers the common case.
|
|
313951
314326
|
`;
|
|
@@ -314052,17 +314427,17 @@ var META = {
|
|
|
314052
314427
|
},
|
|
314053
314428
|
architecture: {
|
|
314054
314429
|
title: "external agents / vibe agent / build / run",
|
|
314055
|
-
summary: "Choose between host-agent shell use,
|
|
314430
|
+
summary: "Choose between host-agent shell use, MCP hosts, storyboard builds, and YAML pipelines",
|
|
314056
314431
|
steps: [
|
|
314057
314432
|
"If you are already in Claude Code/Codex/Cursor/etc., let that host drive normal `vibe` shell commands using `AGENTS.md`, `vibe guide`, and `vibe schema`.",
|
|
314058
|
-
"
|
|
314433
|
+
"Without a coding agent, connect the MCP server to Claude Desktop or ChatGPT with `vibe host setup`; `vibe agent` is deprecated.",
|
|
314059
314434
|
"Pick build for STORYBOARD.md \u2192 MP4 with opinionated defaults.",
|
|
314060
314435
|
"Pick run for repeatable, budget-capped, checkpointed YAML pipelines.",
|
|
314061
314436
|
"Run `vibe doctor --test-keys` before any high-cost orchestrator to validate keys upfront.",
|
|
314062
314437
|
"Use `vibe schema --list` (cost field, v0.84) to plan the budget per step before kicking off `vibe run --budget-usd`."
|
|
314063
314438
|
],
|
|
314064
314439
|
relatedCommands: [
|
|
314065
|
-
"vibe
|
|
314440
|
+
"vibe host setup",
|
|
314066
314441
|
"vibe build",
|
|
314067
314442
|
"vibe run",
|
|
314068
314443
|
"vibe doctor",
|
|
@@ -315058,7 +315433,7 @@ function handleCliFlags(argv, version2) {
|
|
|
315058
315433
|
}
|
|
315059
315434
|
|
|
315060
315435
|
// src/index.ts
|
|
315061
|
-
if (handleCliFlags(process.argv.slice(2), "0.115.
|
|
315436
|
+
if (handleCliFlags(process.argv.slice(2), "0.115.4")) {
|
|
315062
315437
|
process.exit(0);
|
|
315063
315438
|
}
|
|
315064
315439
|
console.log = (...args) => console.error(...args);
|
|
@@ -315071,7 +315446,7 @@ var server = new Server(
|
|
|
315071
315446
|
{
|
|
315072
315447
|
name: "vibeframe",
|
|
315073
315448
|
// Stamped with the package version by build.js at bundle time.
|
|
315074
|
-
version: "0.115.
|
|
315449
|
+
version: "0.115.4"
|
|
315075
315450
|
},
|
|
315076
315451
|
{
|
|
315077
315452
|
capabilities: {
|