@vibeframe/cli 0.115.2 → 0.115.3
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/dist/agent/adapters/gemini.d.ts +2 -0
- package/dist/agent/adapters/provider-content.test.d.ts +6 -0
- package/dist/agent/memory/index.d.ts +1 -1
- package/dist/agent/types.d.ts +8 -0
- package/dist/commands/_shared/build-video-providers.d.ts +12 -0
- package/dist/commands/_shared/build-video-providers.test.d.ts +1 -0
- package/dist/commands/_shared/edit/translate-srt.test.d.ts +1 -0
- package/dist/commands/_shared/openai-image.d.ts +7 -7
- package/dist/commands/_shared/project-config.d.ts +2 -1
- package/dist/commands/_shared/scene-build.d.ts +3 -2
- package/dist/commands/ai-video.d.ts +2 -0
- package/dist/commands/generate/image.d.ts +1 -1
- package/dist/commands/generate/video.d.ts +1 -10
- package/dist/config/schema.d.ts +1 -1
- package/dist/index.js +1003 -709
- package/dist/tools/manifest/edit.d.ts +3 -3
- package/dist/tools/manifest/generate.d.ts +8 -2
- package/dist/tools/manifest/index.js +943 -652
- package/dist/tools/manifest/scene.d.ts +3 -3
- package/dist/tools/manifest/storyboard.d.ts +3 -3
- package/dist/utils/image-file.d.ts +19 -0
- package/dist/utils/image-file.test.d.ts +1 -0
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -6974,8 +6974,8 @@ var init_api_keys = __esm({
|
|
|
6974
6974
|
envVar: "OPENAI_API_KEY",
|
|
6975
6975
|
label: "OpenAI",
|
|
6976
6976
|
showInSetup: true,
|
|
6977
|
-
setupDescription: "gpt-image-2 image gen (
|
|
6978
|
-
envExampleComment: "OpenAI API Key (Whisper transcription, gpt-4o-mini-tts narration, gpt-image-2
|
|
6977
|
+
setupDescription: "gpt-image-2.5 image gen ($), gpt-4o-mini-tts narration, Whisper transcribe, Agent",
|
|
6978
|
+
envExampleComment: "OpenAI API Key (Whisper transcription, gpt-4o-mini-tts narration, gpt-image-2.5 text-to-image)",
|
|
6979
6979
|
envExampleUrl: "https://platform.openai.com/api-keys",
|
|
6980
6980
|
keyFormat: { prefix: /^sk-/, example: "sk-..." }
|
|
6981
6981
|
});
|
|
@@ -7050,8 +7050,7 @@ var init_api_keys = __esm({
|
|
|
7050
7050
|
setupDescription: "v2.5/v3 video \u2014 std ($$) and pro ($$$) modes",
|
|
7051
7051
|
envExampleComment: "Kling API Key (Kling video generation)",
|
|
7052
7052
|
envExampleUrl: "https://platform.klingai.com/",
|
|
7053
|
-
envExampleExtraLines: ["
|
|
7054
|
-
keyFormat: { prefix: /:/, example: "ACCESS_KEY:SECRET_KEY" }
|
|
7053
|
+
envExampleExtraLines: ["API key from the Kling console (legacy ACCESS_KEY:SECRET_KEY also works)"]
|
|
7055
7054
|
});
|
|
7056
7055
|
defineApiKey({
|
|
7057
7056
|
configKey: "replicate",
|
|
@@ -7241,18 +7240,20 @@ var GEMINI_DEFAULT_TEXT_MODEL, GEMINI_AGENT_DEFAULT_TEXT_MODEL, GEMINI_TEXT_MODE
|
|
|
7241
7240
|
var init_gemini_models = __esm({
|
|
7242
7241
|
"../ai-providers/dist/gemini/gemini-models.js"() {
|
|
7243
7242
|
"use strict";
|
|
7244
|
-
GEMINI_DEFAULT_TEXT_MODEL = "gemini-3.
|
|
7245
|
-
GEMINI_AGENT_DEFAULT_TEXT_MODEL =
|
|
7243
|
+
GEMINI_DEFAULT_TEXT_MODEL = "gemini-3.8-flash";
|
|
7244
|
+
GEMINI_AGENT_DEFAULT_TEXT_MODEL = GEMINI_DEFAULT_TEXT_MODEL;
|
|
7246
7245
|
GEMINI_TEXT_MODEL_ALIASES = {
|
|
7247
7246
|
flash: GEMINI_DEFAULT_TEXT_MODEL,
|
|
7248
7247
|
latest: GEMINI_DEFAULT_TEXT_MODEL,
|
|
7249
|
-
"flash-3.
|
|
7248
|
+
"flash-3.8": GEMINI_DEFAULT_TEXT_MODEL,
|
|
7249
|
+
"flash-3.5": "gemini-3.5-flash",
|
|
7250
7250
|
"flash-3": "gemini-3-flash-preview",
|
|
7251
7251
|
"flash-2.5": "gemini-2.5-flash",
|
|
7252
|
-
pro: "gemini-
|
|
7253
|
-
"pro-3.1": "gemini-3.1-pro-preview"
|
|
7252
|
+
pro: "gemini-3.1-pro-preview",
|
|
7253
|
+
"pro-3.1": "gemini-3.1-pro-preview",
|
|
7254
|
+
"pro-2.5": "gemini-2.5-pro"
|
|
7254
7255
|
};
|
|
7255
|
-
GEMINI_TEXT_MODEL_HELP = "flash/latest (Gemini 3.
|
|
7256
|
+
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";
|
|
7256
7257
|
}
|
|
7257
7258
|
});
|
|
7258
7259
|
|
|
@@ -7439,7 +7440,6 @@ UNIVERSAL RULES:
|
|
|
7439
7440
|
system_instruction: { parts: [{ text: systemPrompt }] },
|
|
7440
7441
|
contents: [{ role: "user", parts: [{ text: userPrompt }] }],
|
|
7441
7442
|
generationConfig: {
|
|
7442
|
-
temperature: 0.8,
|
|
7443
7443
|
maxOutputTokens: 16384
|
|
7444
7444
|
}
|
|
7445
7445
|
})
|
|
@@ -7540,7 +7540,7 @@ Return the complete modified component as JSON.`
|
|
|
7540
7540
|
]
|
|
7541
7541
|
}
|
|
7542
7542
|
],
|
|
7543
|
-
generationConfig: {
|
|
7543
|
+
generationConfig: { maxOutputTokens: 16384 }
|
|
7544
7544
|
})
|
|
7545
7545
|
});
|
|
7546
7546
|
if (!response.ok) {
|
|
@@ -7590,10 +7590,11 @@ var init_gemini_motion = __esm({
|
|
|
7590
7590
|
gemini: GEMINI_DEFAULT_TEXT_MODEL,
|
|
7591
7591
|
flash: GEMINI_DEFAULT_TEXT_MODEL,
|
|
7592
7592
|
latest: GEMINI_DEFAULT_TEXT_MODEL,
|
|
7593
|
-
"flash-3.
|
|
7593
|
+
"flash-3.8": GEMINI_DEFAULT_TEXT_MODEL,
|
|
7594
|
+
"flash-3.5": "gemini-3.5-flash",
|
|
7594
7595
|
"flash-3": "gemini-3-flash-preview",
|
|
7595
7596
|
"flash-2.5": "gemini-2.5-flash",
|
|
7596
|
-
pro: "gemini-
|
|
7597
|
+
pro: "gemini-3.1-pro-preview",
|
|
7597
7598
|
"2.5-pro": "gemini-2.5-pro",
|
|
7598
7599
|
"3.1-pro": "gemini-3.1-pro-preview",
|
|
7599
7600
|
"pro-3.1": "gemini-3.1-pro-preview"
|
|
@@ -7705,7 +7706,6 @@ var init_storyboard_prompt = __esm({
|
|
|
7705
7706
|
async function analyzeContent(api, content, targetDuration, options) {
|
|
7706
7707
|
const creativity = options?.creativity || "low";
|
|
7707
7708
|
const systemPrompt = buildStoryboardSystemPrompt(targetDuration, creativity);
|
|
7708
|
-
const temperature = creativity === "high" ? 1 : 0.7;
|
|
7709
7709
|
try {
|
|
7710
7710
|
const payload = {
|
|
7711
7711
|
system_instruction: {
|
|
@@ -7715,7 +7715,6 @@ async function analyzeContent(api, content, targetDuration, options) {
|
|
|
7715
7715
|
parts: [{ text: buildStoryboardUserMessage(content) }]
|
|
7716
7716
|
}],
|
|
7717
7717
|
generationConfig: {
|
|
7718
|
-
temperature,
|
|
7719
7718
|
maxOutputTokens: 4096
|
|
7720
7719
|
}
|
|
7721
7720
|
};
|
|
@@ -7786,7 +7785,15 @@ var init_http = __esm({
|
|
|
7786
7785
|
});
|
|
7787
7786
|
|
|
7788
7787
|
// ../ai-providers/dist/gemini/GeminiProvider.js
|
|
7789
|
-
|
|
7788
|
+
function resolveVeoModel(alias) {
|
|
7789
|
+
if (Object.hasOwn(VEO_MODEL_ALIASES, alias)) {
|
|
7790
|
+
return VEO_MODEL_ALIASES[alias];
|
|
7791
|
+
}
|
|
7792
|
+
const valid = Object.keys(VEO_MODEL_ALIASES).join(", ");
|
|
7793
|
+
const hint = alias === "3.0" ? " Veo 3.0 was shut down by Google on 2025-11-12." : "";
|
|
7794
|
+
throw new Error(`Unknown Veo model "${alias}". Valid: ${valid}.${hint}`);
|
|
7795
|
+
}
|
|
7796
|
+
var VEO_MODEL_ALIASES, MODEL_MAP, GeminiProvider, geminiProvider;
|
|
7790
7797
|
var init_GeminiProvider = __esm({
|
|
7791
7798
|
"../ai-providers/dist/gemini/GeminiProvider.js"() {
|
|
7792
7799
|
"use strict";
|
|
@@ -7794,11 +7801,19 @@ var init_GeminiProvider = __esm({
|
|
|
7794
7801
|
init_gemini_models();
|
|
7795
7802
|
init_gemini_storyboard();
|
|
7796
7803
|
init_http();
|
|
7804
|
+
VEO_MODEL_ALIASES = {
|
|
7805
|
+
"3.1": "veo-3.1-generate-preview",
|
|
7806
|
+
"3.1-fast": "veo-3.1-fast-generate-preview"
|
|
7807
|
+
};
|
|
7797
7808
|
MODEL_MAP = {
|
|
7798
|
-
"flash": "gemini-
|
|
7799
|
-
"3.1-flash": "gemini-3.1-flash-image
|
|
7800
|
-
"latest": "gemini-3.1-flash-image
|
|
7801
|
-
"
|
|
7809
|
+
"flash": "gemini-3.1-flash-image",
|
|
7810
|
+
"3.1-flash": "gemini-3.1-flash-image",
|
|
7811
|
+
"latest": "gemini-3.1-flash-image",
|
|
7812
|
+
"lite": "gemini-3.1-flash-lite-image",
|
|
7813
|
+
"pro": "gemini-3-pro-image",
|
|
7814
|
+
"gemini-3.1-flash-image": "gemini-3.1-flash-image",
|
|
7815
|
+
"gemini-3.1-flash-lite-image": "gemini-3.1-flash-lite-image",
|
|
7816
|
+
"gemini-3-pro-image": "gemini-3-pro-image",
|
|
7802
7817
|
"gemini-2.5-flash-image": "gemini-2.5-flash-image",
|
|
7803
7818
|
"gemini-3.1-flash-image-preview": "gemini-3.1-flash-image-preview",
|
|
7804
7819
|
"gemini-3-pro-image-preview": "gemini-3-pro-image-preview"
|
|
@@ -8107,7 +8122,7 @@ var init_GeminiProvider = __esm({
|
|
|
8107
8122
|
contents: [{ parts: [{ text: prompt3 }] }],
|
|
8108
8123
|
generationConfig
|
|
8109
8124
|
};
|
|
8110
|
-
const is31Flash = modelId
|
|
8125
|
+
const is31Flash = modelId.startsWith("gemini-3.1-flash-image");
|
|
8111
8126
|
if (options.imageSearchGrounding && is31Flash) {
|
|
8112
8127
|
payload.tools = [{ googleSearch: { searchTypes: { webSearch: {}, imageSearch: {} } } }];
|
|
8113
8128
|
} else if (options.grounding && isPro) {
|
|
@@ -8335,7 +8350,6 @@ var init_GeminiProvider = __esm({
|
|
|
8335
8350
|
videoPart.video_metadata = videoMetadata;
|
|
8336
8351
|
}
|
|
8337
8352
|
const generationConfig = {
|
|
8338
|
-
temperature: 0.4,
|
|
8339
8353
|
maxOutputTokens: 8192
|
|
8340
8354
|
};
|
|
8341
8355
|
if (options.lowResolution) {
|
|
@@ -8417,7 +8431,6 @@ var init_GeminiProvider = __esm({
|
|
|
8417
8431
|
}
|
|
8418
8432
|
}));
|
|
8419
8433
|
const generationConfig = {
|
|
8420
|
-
temperature: 0.4,
|
|
8421
8434
|
maxOutputTokens: 8192
|
|
8422
8435
|
};
|
|
8423
8436
|
if (options.lowResolution) {
|
|
@@ -8517,7 +8530,6 @@ Respond with ONLY the JSON array, no other text.`;
|
|
|
8517
8530
|
body: JSON.stringify({
|
|
8518
8531
|
contents: [{ parts: [{ text: prompt3 }] }],
|
|
8519
8532
|
generationConfig: {
|
|
8520
|
-
temperature: 0.3,
|
|
8521
8533
|
maxOutputTokens: 1024
|
|
8522
8534
|
}
|
|
8523
8535
|
})
|
|
@@ -8611,7 +8623,7 @@ Respond with ONLY the JSON array, no other text.`;
|
|
|
8611
8623
|
return refineMotion({ apiKey: this.apiKey, baseUrl: this.baseUrl }, existingCode, instructions, options);
|
|
8612
8624
|
}
|
|
8613
8625
|
/**
|
|
8614
|
-
* Generate a storyboard from script content using Gemini
|
|
8626
|
+
* Generate a storyboard from script content using the default Gemini Flash model.
|
|
8615
8627
|
* Alternative to ClaudeProvider.analyzeContent for when Claude is unavailable.
|
|
8616
8628
|
*/
|
|
8617
8629
|
async analyzeContent(content, targetDuration, options) {
|
|
@@ -8626,43 +8638,47 @@ Respond with ONLY the JSON array, no other text.`;
|
|
|
8626
8638
|
});
|
|
8627
8639
|
|
|
8628
8640
|
// ../ai-providers/dist/gemini/gemini-omni.js
|
|
8629
|
-
function
|
|
8630
|
-
const
|
|
8631
|
-
|
|
8632
|
-
return refs[0];
|
|
8633
|
-
const ref = options.referenceImage;
|
|
8634
|
-
if (typeof ref === "string" && ref) {
|
|
8641
|
+
function frameImages(options) {
|
|
8642
|
+
const frames = [];
|
|
8643
|
+
const toInline = (ref) => {
|
|
8635
8644
|
const m = ref.match(/^data:(.+?);base64,(.*)$/);
|
|
8636
|
-
|
|
8637
|
-
|
|
8638
|
-
|
|
8645
|
+
return m ? { mimeType: m[1], base64: m[2] } : { mimeType: "image/png", base64: ref };
|
|
8646
|
+
};
|
|
8647
|
+
if (options.referenceImages?.[0]?.base64)
|
|
8648
|
+
frames.push(options.referenceImages[0]);
|
|
8649
|
+
else if (typeof options.referenceImage === "string" && options.referenceImage) {
|
|
8650
|
+
frames.push(toInline(options.referenceImage));
|
|
8651
|
+
}
|
|
8652
|
+
if (frames.length > 0 && options.lastFrame)
|
|
8653
|
+
frames.push(toInline(options.lastFrame));
|
|
8654
|
+
return frames;
|
|
8655
|
+
}
|
|
8656
|
+
function findOmniVideo(response) {
|
|
8657
|
+
for (const step of response.steps ?? []) {
|
|
8658
|
+
if (step.type !== "model_output")
|
|
8659
|
+
continue;
|
|
8660
|
+
const video = step.content?.find((c) => c.type === "video");
|
|
8661
|
+
if (video)
|
|
8662
|
+
return video;
|
|
8639
8663
|
}
|
|
8640
|
-
return
|
|
8664
|
+
return response.output_video;
|
|
8641
8665
|
}
|
|
8642
|
-
function
|
|
8643
|
-
|
|
8644
|
-
return void 0;
|
|
8645
|
-
for (const [k, v] of Object.entries(obj)) {
|
|
8646
|
-
if (typeof v === "string" && /^https?:\/\//.test(v) && /(uri|url|video)/i.test(k))
|
|
8647
|
-
return v;
|
|
8648
|
-
if (typeof v === "object") {
|
|
8649
|
-
const nested = findVideoUrl(v);
|
|
8650
|
-
if (nested)
|
|
8651
|
-
return nested;
|
|
8652
|
-
}
|
|
8653
|
-
}
|
|
8654
|
-
return void 0;
|
|
8666
|
+
function fileIdFromUri(uri) {
|
|
8667
|
+
return uri.match(/files\/([^/?:]+)/)?.[1];
|
|
8655
8668
|
}
|
|
8656
|
-
var OMNI_MODEL,
|
|
8669
|
+
var OMNI_MODEL, API_ROOT, FILE_POLL_INTERVAL_MS, FILE_POLL_TIMEOUT_MS, OmniProvider, omniProvider;
|
|
8657
8670
|
var init_gemini_omni = __esm({
|
|
8658
8671
|
"../ai-providers/dist/gemini/gemini-omni.js"() {
|
|
8659
8672
|
"use strict";
|
|
8660
|
-
|
|
8661
|
-
|
|
8673
|
+
init_http();
|
|
8674
|
+
OMNI_MODEL = "gemini-omni-1.1-flash";
|
|
8675
|
+
API_ROOT = "https://generativelanguage.googleapis.com";
|
|
8676
|
+
FILE_POLL_INTERVAL_MS = 3e3;
|
|
8677
|
+
FILE_POLL_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
8662
8678
|
OmniProvider = class {
|
|
8663
8679
|
constructor() {
|
|
8664
8680
|
this.id = "omni";
|
|
8665
|
-
this.label = "Gemini Omni
|
|
8681
|
+
this.label = "Gemini Omni 1.1 Flash";
|
|
8666
8682
|
}
|
|
8667
8683
|
async initialize(config2) {
|
|
8668
8684
|
this.apiKey = config2.apiKey;
|
|
@@ -8675,22 +8691,23 @@ var init_gemini_omni = __esm({
|
|
|
8675
8691
|
return { id: "", status: "failed", error: "GOOGLE_API_KEY not configured for Gemini Omni" };
|
|
8676
8692
|
}
|
|
8677
8693
|
const opts = options ?? { prompt: prompt3 };
|
|
8678
|
-
const
|
|
8679
|
-
const
|
|
8680
|
-
|
|
8681
|
-
|
|
8682
|
-
|
|
8683
|
-
inputs.push({ inline_data: { mime_type: image.mimeType, data: image.base64 } });
|
|
8684
|
-
}
|
|
8694
|
+
const frames = frameImages(opts);
|
|
8695
|
+
const input = frames.length === 0 ? prompt3 : [
|
|
8696
|
+
...frames.map((f) => ({ type: "image", data: f.base64, mime_type: f.mimeType })),
|
|
8697
|
+
{ type: "text", text: prompt3 }
|
|
8698
|
+
];
|
|
8685
8699
|
const body = {
|
|
8686
8700
|
model: OMNI_MODEL,
|
|
8687
|
-
|
|
8688
|
-
|
|
8689
|
-
|
|
8701
|
+
input,
|
|
8702
|
+
response_format: {
|
|
8703
|
+
type: "video",
|
|
8704
|
+
aspect_ratio: opts.aspectRatio === "9:16" ? "9:16" : "16:9",
|
|
8705
|
+
resolution: opts.resolution ?? "720p",
|
|
8706
|
+
delivery: "uri"
|
|
8690
8707
|
}
|
|
8691
8708
|
};
|
|
8692
8709
|
try {
|
|
8693
|
-
const res = await fetch(
|
|
8710
|
+
const res = await fetch(`${API_ROOT}/v1beta/interactions`, {
|
|
8694
8711
|
method: "POST",
|
|
8695
8712
|
headers: { "Content-Type": "application/json", "x-goog-api-key": this.apiKey },
|
|
8696
8713
|
body: JSON.stringify(body)
|
|
@@ -8700,33 +8717,52 @@ var init_gemini_omni = __esm({
|
|
|
8700
8717
|
return {
|
|
8701
8718
|
id: "",
|
|
8702
8719
|
status: "failed",
|
|
8703
|
-
error: `Gemini Omni
|
|
8720
|
+
error: `Gemini Omni request failed: HTTP ${res.status} - ${text.slice(0, 300)}`
|
|
8704
8721
|
};
|
|
8705
8722
|
}
|
|
8706
|
-
|
|
8707
|
-
|
|
8708
|
-
|
|
8709
|
-
|
|
8710
|
-
|
|
8723
|
+
const parsed = JSON.parse(text);
|
|
8724
|
+
const id = parsed.id ?? "";
|
|
8725
|
+
const video = findOmniVideo(parsed);
|
|
8726
|
+
if (!video?.uri) {
|
|
8727
|
+
const reason = parsed.error?.message ?? `status ${parsed.status ?? "unknown"}`;
|
|
8728
|
+
return { id, status: "failed", error: `Gemini Omni returned no video (${reason})` };
|
|
8711
8729
|
}
|
|
8712
|
-
const
|
|
8713
|
-
|
|
8714
|
-
|
|
8715
|
-
return {
|
|
8716
|
-
id,
|
|
8717
|
-
status: "failed",
|
|
8718
|
-
error: "Gemini Omni response contained no video URL (the preview interactions schema may have changed)."
|
|
8719
|
-
};
|
|
8730
|
+
const fileId = fileIdFromUri(video.uri);
|
|
8731
|
+
if (!fileId) {
|
|
8732
|
+
return { id, status: "failed", error: `Gemini Omni returned an unexpected video URI: ${video.uri}` };
|
|
8720
8733
|
}
|
|
8721
|
-
|
|
8734
|
+
const ready = await this.waitForFile(fileId);
|
|
8735
|
+
if (ready !== "ACTIVE") {
|
|
8736
|
+
return { id, status: "failed", error: `Gemini Omni video file ended in state ${ready}` };
|
|
8737
|
+
}
|
|
8738
|
+
return {
|
|
8739
|
+
id,
|
|
8740
|
+
status: "completed",
|
|
8741
|
+
videoUrl: `${API_ROOT}/download/v1beta/files/${fileId}:download?alt=media`
|
|
8742
|
+
};
|
|
8722
8743
|
} catch (err) {
|
|
8723
8744
|
return {
|
|
8724
8745
|
id: "",
|
|
8725
8746
|
status: "failed",
|
|
8726
|
-
error: `Gemini Omni
|
|
8747
|
+
error: `Gemini Omni error: ${err instanceof Error ? err.message : String(err)}`
|
|
8727
8748
|
};
|
|
8728
8749
|
}
|
|
8729
8750
|
}
|
|
8751
|
+
/** Poll the Files API until the generated video is downloadable. */
|
|
8752
|
+
async waitForFile(fileId) {
|
|
8753
|
+
const deadline = Date.now() + FILE_POLL_TIMEOUT_MS;
|
|
8754
|
+
for (; ; ) {
|
|
8755
|
+
const res = await fetch(`${API_ROOT}/v1beta/files/${fileId}`, {
|
|
8756
|
+
headers: { "x-goog-api-key": this.apiKey }
|
|
8757
|
+
});
|
|
8758
|
+
const state = res.ok ? (await res.json()).state : `HTTP ${res.status}`;
|
|
8759
|
+
if (state !== "PROCESSING")
|
|
8760
|
+
return state ?? "UNKNOWN";
|
|
8761
|
+
if (Date.now() > deadline)
|
|
8762
|
+
return "TIMEOUT";
|
|
8763
|
+
await sleep(FILE_POLL_INTERVAL_MS);
|
|
8764
|
+
}
|
|
8765
|
+
}
|
|
8730
8766
|
};
|
|
8731
8767
|
omniProvider = new OmniProvider();
|
|
8732
8768
|
}
|
|
@@ -8760,14 +8796,16 @@ var init_gemini = __esm({
|
|
|
8760
8796
|
label: "Veo",
|
|
8761
8797
|
apiKey: "google",
|
|
8762
8798
|
kinds: ["video"],
|
|
8763
|
-
resolverPriority:
|
|
8799
|
+
// No resolverPriority: the Veo 3.1 previews shut down on 2026-10-22, so
|
|
8800
|
+
// Veo is explicit-only (`-p veo`) and Omni is the Google default.
|
|
8764
8801
|
commandsUnlocked: ["generate video -p veo"]
|
|
8765
8802
|
});
|
|
8766
8803
|
defineProvider({
|
|
8767
8804
|
id: "omni",
|
|
8768
|
-
label: "Gemini Omni
|
|
8805
|
+
label: "Gemini Omni",
|
|
8769
8806
|
apiKey: "google",
|
|
8770
8807
|
kinds: ["video"],
|
|
8808
|
+
resolverPriority: { video: 3 },
|
|
8771
8809
|
commandsUnlocked: ["generate video -p omni"]
|
|
8772
8810
|
});
|
|
8773
8811
|
}
|
|
@@ -8776,8 +8814,7 @@ var init_gemini = __esm({
|
|
|
8776
8814
|
// ../ai-providers/dist/openai/openai-storyboard.js
|
|
8777
8815
|
async function analyzeContent2(apiKey, content, targetDuration, options) {
|
|
8778
8816
|
const creativity = options?.creativity || "low";
|
|
8779
|
-
const systemPrompt = buildStoryboardSystemPrompt(targetDuration, creativity);
|
|
8780
|
-
const temperature = creativity === "high" ? 1 : 0.7;
|
|
8817
|
+
const systemPrompt = buildStoryboardSystemPrompt(targetDuration, creativity) + '\n\nWrap the array in a JSON object: {"segments": [ ...segment objects... ]}.';
|
|
8781
8818
|
try {
|
|
8782
8819
|
const response = await fetch("https://api.openai.com/v1/chat/completions", {
|
|
8783
8820
|
method: "POST",
|
|
@@ -8786,13 +8823,13 @@ async function analyzeContent2(apiKey, content, targetDuration, options) {
|
|
|
8786
8823
|
Authorization: `Bearer ${apiKey}`
|
|
8787
8824
|
},
|
|
8788
8825
|
body: JSON.stringify({
|
|
8789
|
-
model: "gpt-5-mini",
|
|
8826
|
+
model: "gpt-5.4-mini",
|
|
8790
8827
|
messages: [
|
|
8791
8828
|
{ role: "system", content: systemPrompt },
|
|
8792
8829
|
{ role: "user", content: buildStoryboardUserMessage(content) }
|
|
8793
8830
|
],
|
|
8794
|
-
|
|
8795
|
-
|
|
8831
|
+
// Reasoning tokens count against this cap.
|
|
8832
|
+
max_completion_tokens: 16384,
|
|
8796
8833
|
response_format: { type: "json_object" }
|
|
8797
8834
|
})
|
|
8798
8835
|
});
|
|
@@ -8849,7 +8886,7 @@ var init_OpenAIProvider = __esm({
|
|
|
8849
8886
|
this.iconUrl = "/icons/openai.svg";
|
|
8850
8887
|
this.isAvailable = true;
|
|
8851
8888
|
this.baseUrl = "https://api.openai.com/v1";
|
|
8852
|
-
this.model = "gpt-5-mini";
|
|
8889
|
+
this.model = "gpt-5.4-mini";
|
|
8853
8890
|
}
|
|
8854
8891
|
async initialize(config2) {
|
|
8855
8892
|
this.apiKey = config2.apiKey;
|
|
@@ -8945,7 +8982,6 @@ Or if clarification needed:
|
|
|
8945
8982
|
{ role: "system", content: systemPrompt },
|
|
8946
8983
|
{ role: "user", content: instruction }
|
|
8947
8984
|
],
|
|
8948
|
-
temperature: 0.2,
|
|
8949
8985
|
response_format: { type: "json_object" }
|
|
8950
8986
|
})
|
|
8951
8987
|
});
|
|
@@ -9156,8 +9192,9 @@ Each segment should be 3-10 seconds long.`;
|
|
|
9156
9192
|
Authorization: `Bearer ${this.apiKey}`
|
|
9157
9193
|
},
|
|
9158
9194
|
body: JSON.stringify({
|
|
9159
|
-
model: "gpt-5-mini",
|
|
9160
|
-
|
|
9195
|
+
model: "gpt-5.4-mini",
|
|
9196
|
+
// Reasoning tokens count against this cap.
|
|
9197
|
+
max_completion_tokens: 16384,
|
|
9161
9198
|
response_format: { type: "json_object" },
|
|
9162
9199
|
messages: [
|
|
9163
9200
|
{ role: "system", content: systemPrompt },
|
|
@@ -9190,7 +9227,7 @@ ${videoAnalysis}` }
|
|
|
9190
9227
|
}
|
|
9191
9228
|
}
|
|
9192
9229
|
/**
|
|
9193
|
-
* Generate a storyboard from script content using GPT-5
|
|
9230
|
+
* Generate a storyboard from script content using GPT-5.4 mini.
|
|
9194
9231
|
* Alternative to ClaudeProvider.analyzeContent for when Claude is unavailable.
|
|
9195
9232
|
*/
|
|
9196
9233
|
async analyzeContent(content, targetDuration, options) {
|
|
@@ -9238,10 +9275,12 @@ async function callClaude(params, opts) {
|
|
|
9238
9275
|
},
|
|
9239
9276
|
body: JSON.stringify({
|
|
9240
9277
|
model: params.model,
|
|
9241
|
-
|
|
9242
|
-
|
|
9278
|
+
// Claude 5.x thinks by default and thinking tokens count against
|
|
9279
|
+
// max_tokens, so a small cap can end before any text is written.
|
|
9280
|
+
max_tokens: Math.max(opts.maxTokens, CLAUDE_MIN_MAX_TOKENS),
|
|
9243
9281
|
messages: opts.messages,
|
|
9244
|
-
system: opts.system
|
|
9282
|
+
system: opts.system,
|
|
9283
|
+
...opts.jsonSchema ? { output_config: { format: { type: "json_schema", schema: opts.jsonSchema } } } : {}
|
|
9245
9284
|
})
|
|
9246
9285
|
});
|
|
9247
9286
|
if (!response.ok) {
|
|
@@ -9263,9 +9302,11 @@ function extractJsonArray(text) {
|
|
|
9263
9302
|
const match = text.match(/\[[\s\S]*\]/);
|
|
9264
9303
|
return match ? match[0] : null;
|
|
9265
9304
|
}
|
|
9305
|
+
var CLAUDE_MIN_MAX_TOKENS;
|
|
9266
9306
|
var init_claude_api = __esm({
|
|
9267
9307
|
"../ai-providers/dist/claude/claude-api.js"() {
|
|
9268
9308
|
"use strict";
|
|
9309
|
+
CLAUDE_MIN_MAX_TOKENS = 16e3;
|
|
9269
9310
|
}
|
|
9270
9311
|
});
|
|
9271
9312
|
|
|
@@ -9301,7 +9342,8 @@ MANDATORY ADAPTATION RULES:
|
|
|
9301
9342
|
const text = await callClaude(api, {
|
|
9302
9343
|
system: systemPrompt,
|
|
9303
9344
|
messages: [{ role: "user", content: userContent }],
|
|
9304
|
-
maxTokens: 16e3
|
|
9345
|
+
maxTokens: 16e3,
|
|
9346
|
+
jsonSchema: MOTION_COMPONENT_SCHEMA
|
|
9305
9347
|
});
|
|
9306
9348
|
const jsonStr = extractJsonObject(text);
|
|
9307
9349
|
if (!jsonStr) {
|
|
@@ -9376,7 +9418,8 @@ Modification instructions: ${instructions}
|
|
|
9376
9418
|
|
|
9377
9419
|
Return the complete modified component as JSON.`
|
|
9378
9420
|
}],
|
|
9379
|
-
maxTokens: 16e3
|
|
9421
|
+
maxTokens: 16e3,
|
|
9422
|
+
jsonSchema: MOTION_COMPONENT_SCHEMA
|
|
9380
9423
|
});
|
|
9381
9424
|
const jsonStr = extractJsonObject(text);
|
|
9382
9425
|
if (!jsonStr)
|
|
@@ -9405,15 +9448,13 @@ async function analyzeContent3(api, content, targetDuration, options) {
|
|
|
9405
9448
|
const creativity = options?.creativity || "low";
|
|
9406
9449
|
const systemPrompt = buildStoryboardSystemPrompt(targetDuration, creativity);
|
|
9407
9450
|
try {
|
|
9408
|
-
const temperature = creativity === "high" ? 1 : 0.7;
|
|
9409
9451
|
const text = await callClaude(api, {
|
|
9410
9452
|
system: systemPrompt,
|
|
9411
9453
|
messages: [{
|
|
9412
9454
|
role: "user",
|
|
9413
9455
|
content: buildStoryboardUserMessage(content)
|
|
9414
9456
|
}],
|
|
9415
|
-
maxTokens: 4096
|
|
9416
|
-
temperature
|
|
9457
|
+
maxTokens: 4096
|
|
9417
9458
|
});
|
|
9418
9459
|
const jsonStr = extractJsonArray(text);
|
|
9419
9460
|
if (!jsonStr) {
|
|
@@ -9770,11 +9811,22 @@ UNIVERSAL RULES:
|
|
|
9770
9811
|
- Both entrance AND exit animations
|
|
9771
9812
|
- whiteSpace: "nowrap" on all text`;
|
|
9772
9813
|
}
|
|
9814
|
+
var MOTION_COMPONENT_SCHEMA;
|
|
9773
9815
|
var init_claude_motion = __esm({
|
|
9774
9816
|
"../ai-providers/dist/claude/claude-motion.js"() {
|
|
9775
9817
|
"use strict";
|
|
9776
9818
|
init_claude_api();
|
|
9777
9819
|
init_storyboard_prompt();
|
|
9820
|
+
MOTION_COMPONENT_SCHEMA = {
|
|
9821
|
+
type: "object",
|
|
9822
|
+
properties: {
|
|
9823
|
+
name: { type: "string" },
|
|
9824
|
+
code: { type: "string" },
|
|
9825
|
+
description: { type: "string" }
|
|
9826
|
+
},
|
|
9827
|
+
required: ["name", "code", "description"],
|
|
9828
|
+
additionalProperties: false
|
|
9829
|
+
};
|
|
9778
9830
|
}
|
|
9779
9831
|
});
|
|
9780
9832
|
|
|
@@ -10536,6 +10588,7 @@ var ClaudeProvider, claudeProvider;
|
|
|
10536
10588
|
var init_ClaudeProvider = __esm({
|
|
10537
10589
|
"../ai-providers/dist/claude/ClaudeProvider.js"() {
|
|
10538
10590
|
"use strict";
|
|
10591
|
+
init_claude_api();
|
|
10539
10592
|
init_claude_motion();
|
|
10540
10593
|
init_claude_analysis();
|
|
10541
10594
|
init_claude_viral();
|
|
@@ -10549,7 +10602,7 @@ var init_ClaudeProvider = __esm({
|
|
|
10549
10602
|
this.iconUrl = "/icons/claude.svg";
|
|
10550
10603
|
this.isAvailable = true;
|
|
10551
10604
|
this.baseUrl = "https://api.anthropic.com/v1";
|
|
10552
|
-
this.model = "claude-sonnet-
|
|
10605
|
+
this.model = "claude-sonnet-5-5";
|
|
10553
10606
|
}
|
|
10554
10607
|
async initialize(config2) {
|
|
10555
10608
|
this.apiKey = config2.apiKey;
|
|
@@ -10653,7 +10706,7 @@ Or if clarification needed:
|
|
|
10653
10706
|
},
|
|
10654
10707
|
body: JSON.stringify({
|
|
10655
10708
|
model: this.model,
|
|
10656
|
-
max_tokens:
|
|
10709
|
+
max_tokens: CLAUDE_MIN_MAX_TOKENS,
|
|
10657
10710
|
messages: [{ role: "user", content: instruction }],
|
|
10658
10711
|
system: systemPrompt
|
|
10659
10712
|
})
|
|
@@ -10723,7 +10776,7 @@ Respond with JSON array:
|
|
|
10723
10776
|
},
|
|
10724
10777
|
body: JSON.stringify({
|
|
10725
10778
|
model: this.model,
|
|
10726
|
-
max_tokens:
|
|
10779
|
+
max_tokens: CLAUDE_MIN_MAX_TOKENS,
|
|
10727
10780
|
messages: [{
|
|
10728
10781
|
role: "user",
|
|
10729
10782
|
content: `Clips: ${JSON.stringify(clipsInfo)}
|
|
@@ -10852,8 +10905,8 @@ Instruction: ${instruction}`
|
|
|
10852
10905
|
}
|
|
10853
10906
|
};
|
|
10854
10907
|
ClaudeProvider.MOTION_MODELS = {
|
|
10855
|
-
sonnet: "claude-sonnet-
|
|
10856
|
-
opus: "claude-opus-
|
|
10908
|
+
sonnet: "claude-sonnet-5-5",
|
|
10909
|
+
opus: "claude-opus-5-5",
|
|
10857
10910
|
"opus-4-6": "claude-opus-4-6"
|
|
10858
10911
|
};
|
|
10859
10912
|
claudeProvider = new ClaudeProvider();
|
|
@@ -11191,7 +11244,7 @@ function resolveVoiceId(input) {
|
|
|
11191
11244
|
const availableVoices = Object.keys(KNOWN_VOICES).join(", ");
|
|
11192
11245
|
throw new Error(`Unknown voice "${input}". Available voices: ${availableVoices}. You can also use a custom voice ID from your ElevenLabs account.`);
|
|
11193
11246
|
}
|
|
11194
|
-
var KNOWN_VOICES, TTS_429_MAX_RETRIES, TTS_429_RETRY_DELAY_MS, ElevenLabsProvider, elevenLabsProvider;
|
|
11247
|
+
var KNOWN_VOICES, TTS_429_MAX_RETRIES, TTS_429_RETRY_DELAY_MS, ELEVENLABS_MUSIC_MODEL, ElevenLabsProvider, elevenLabsProvider;
|
|
11195
11248
|
var init_ElevenLabsProvider = __esm({
|
|
11196
11249
|
"../ai-providers/dist/elevenlabs/ElevenLabsProvider.js"() {
|
|
11197
11250
|
"use strict";
|
|
@@ -11228,6 +11281,7 @@ var init_ElevenLabsProvider = __esm({
|
|
|
11228
11281
|
};
|
|
11229
11282
|
TTS_429_MAX_RETRIES = 1;
|
|
11230
11283
|
TTS_429_RETRY_DELAY_MS = 2e3;
|
|
11284
|
+
ELEVENLABS_MUSIC_MODEL = "music_v2_5";
|
|
11231
11285
|
ElevenLabsProvider = class {
|
|
11232
11286
|
constructor() {
|
|
11233
11287
|
this.id = "elevenlabs";
|
|
@@ -11308,9 +11362,10 @@ var init_ElevenLabsProvider = __esm({
|
|
|
11308
11362
|
stability: options.stability ?? 0.5,
|
|
11309
11363
|
similarity_boost: options.similarityBoost ?? 0.75,
|
|
11310
11364
|
style: options.style ?? 0,
|
|
11311
|
-
use_speaker_boost: true
|
|
11312
|
-
|
|
11313
|
-
|
|
11365
|
+
use_speaker_boost: true,
|
|
11366
|
+
// The API reads speed only inside voice_settings.
|
|
11367
|
+
...options.speed !== void 0 && { speed: options.speed }
|
|
11368
|
+
}
|
|
11314
11369
|
})
|
|
11315
11370
|
});
|
|
11316
11371
|
if (response.status === 429 && attempt < TTS_429_MAX_RETRIES) {
|
|
@@ -11380,7 +11435,7 @@ var init_ElevenLabsProvider = __esm({
|
|
|
11380
11435
|
prompt_influence: options.promptInfluence ?? 0.3
|
|
11381
11436
|
};
|
|
11382
11437
|
if (options.duration !== void 0) {
|
|
11383
|
-
const duration = Math.max(0.5, Math.min(
|
|
11438
|
+
const duration = Math.max(0.5, Math.min(30, options.duration));
|
|
11384
11439
|
body.duration_seconds = duration;
|
|
11385
11440
|
}
|
|
11386
11441
|
const response = await fetch(`${this.baseUrl}/sound-generation`, {
|
|
@@ -11425,7 +11480,7 @@ var init_ElevenLabsProvider = __esm({
|
|
|
11425
11480
|
try {
|
|
11426
11481
|
const body = {
|
|
11427
11482
|
prompt: prompt3,
|
|
11428
|
-
model_id:
|
|
11483
|
+
model_id: ELEVENLABS_MUSIC_MODEL
|
|
11429
11484
|
};
|
|
11430
11485
|
if (options.duration !== void 0) {
|
|
11431
11486
|
const duration = Math.max(3, Math.min(600, options.duration));
|
|
@@ -11636,6 +11691,55 @@ var init_elevenlabs = __esm({
|
|
|
11636
11691
|
});
|
|
11637
11692
|
|
|
11638
11693
|
// ../ai-providers/dist/kokoro/KokoroProvider.js
|
|
11694
|
+
function splitForKokoro(text, maxChars = KOKORO_MAX_CHUNK_CHARS) {
|
|
11695
|
+
const pieces = (part, pattern) => part.length <= maxChars ? [part] : part.split(pattern).filter((p) => p.trim().length > 0);
|
|
11696
|
+
const units2 = text.trim().split(/(?<=[.!?…])\s+/).flatMap((sentence) => pieces(sentence, /(?<=[,;:])\s+/)).flatMap((clause) => {
|
|
11697
|
+
if (clause.length <= maxChars)
|
|
11698
|
+
return [clause];
|
|
11699
|
+
const words = [];
|
|
11700
|
+
let line = "";
|
|
11701
|
+
for (const word of clause.split(/\s+/)) {
|
|
11702
|
+
if (line && line.length + word.length + 1 > maxChars) {
|
|
11703
|
+
words.push(line);
|
|
11704
|
+
line = word;
|
|
11705
|
+
} else {
|
|
11706
|
+
line = line ? `${line} ${word}` : word;
|
|
11707
|
+
}
|
|
11708
|
+
}
|
|
11709
|
+
if (line)
|
|
11710
|
+
words.push(line);
|
|
11711
|
+
return words;
|
|
11712
|
+
});
|
|
11713
|
+
const chunks = [];
|
|
11714
|
+
for (const unit of units2) {
|
|
11715
|
+
const last = chunks.at(-1);
|
|
11716
|
+
if (last !== void 0 && last.length + unit.length + 1 <= maxChars) {
|
|
11717
|
+
chunks[chunks.length - 1] = `${last} ${unit}`;
|
|
11718
|
+
} else {
|
|
11719
|
+
chunks.push(unit);
|
|
11720
|
+
}
|
|
11721
|
+
}
|
|
11722
|
+
return chunks;
|
|
11723
|
+
}
|
|
11724
|
+
function encodeFloatWav(samples, sampleRate) {
|
|
11725
|
+
const dataBytes = samples.length * 4;
|
|
11726
|
+
const buffer = Buffer.alloc(44 + dataBytes);
|
|
11727
|
+
buffer.write("RIFF", 0, "ascii");
|
|
11728
|
+
buffer.writeUInt32LE(36 + dataBytes, 4);
|
|
11729
|
+
buffer.write("WAVE", 8, "ascii");
|
|
11730
|
+
buffer.write("fmt ", 12, "ascii");
|
|
11731
|
+
buffer.writeUInt32LE(16, 16);
|
|
11732
|
+
buffer.writeUInt16LE(3, 20);
|
|
11733
|
+
buffer.writeUInt16LE(1, 22);
|
|
11734
|
+
buffer.writeUInt32LE(sampleRate, 24);
|
|
11735
|
+
buffer.writeUInt32LE(sampleRate * 4, 28);
|
|
11736
|
+
buffer.writeUInt16LE(4, 32);
|
|
11737
|
+
buffer.writeUInt16LE(32, 34);
|
|
11738
|
+
buffer.write("data", 36, "ascii");
|
|
11739
|
+
buffer.writeUInt32LE(dataBytes, 40);
|
|
11740
|
+
Buffer.from(samples.buffer, samples.byteOffset, dataBytes).copy(buffer, 44);
|
|
11741
|
+
return buffer;
|
|
11742
|
+
}
|
|
11639
11743
|
async function loadKokoroRuntime() {
|
|
11640
11744
|
if (factoryOverride)
|
|
11641
11745
|
return { factory: factoryOverride, device: "cpu" };
|
|
@@ -11673,7 +11777,7 @@ async function loadBundledKokoroRuntime(runtimeDir = process.env.VIBE_KOKORO_RUN
|
|
|
11673
11777
|
if (!base)
|
|
11674
11778
|
return null;
|
|
11675
11779
|
try {
|
|
11676
|
-
const { readFile: readFile55, writeFile:
|
|
11780
|
+
const { readFile: readFile55, writeFile: writeFile56, mkdir: mkdir32 } = await import("node:fs/promises");
|
|
11677
11781
|
const { join: join34, resolve: resolve87 } = await import("node:path");
|
|
11678
11782
|
const { pathToFileURL } = await import("node:url");
|
|
11679
11783
|
const { homedir: homedir8 } = await import("node:os");
|
|
@@ -11694,8 +11798,8 @@ async function loadBundledKokoroRuntime(runtimeDir = process.env.VIBE_KOKORO_RUN
|
|
|
11694
11798
|
async put(key, response) {
|
|
11695
11799
|
try {
|
|
11696
11800
|
const buf = Buffer.from(await response.arrayBuffer());
|
|
11697
|
-
await
|
|
11698
|
-
await
|
|
11801
|
+
await mkdir32(cacheRoot, { recursive: true });
|
|
11802
|
+
await writeFile56(join34(cacheRoot, encodeURIComponent(String(key))), buf);
|
|
11699
11803
|
} catch {
|
|
11700
11804
|
}
|
|
11701
11805
|
}
|
|
@@ -11744,12 +11848,13 @@ function normaliseEvent(raw) {
|
|
|
11744
11848
|
total: typeof r.total === "number" ? r.total : void 0
|
|
11745
11849
|
};
|
|
11746
11850
|
}
|
|
11747
|
-
var KOKORO_DEFAULT_VOICE, KOKORO_MODEL_ID, modelPromise, factoryOverride, KokoroProvider, kokoroProvider;
|
|
11851
|
+
var KOKORO_DEFAULT_VOICE, KOKORO_MODEL_ID, KOKORO_MAX_CHUNK_CHARS, modelPromise, factoryOverride, KokoroProvider, kokoroProvider;
|
|
11748
11852
|
var init_KokoroProvider = __esm({
|
|
11749
11853
|
"../ai-providers/dist/kokoro/KokoroProvider.js"() {
|
|
11750
11854
|
"use strict";
|
|
11751
11855
|
KOKORO_DEFAULT_VOICE = "af_heart";
|
|
11752
11856
|
KOKORO_MODEL_ID = "onnx-community/Kokoro-82M-v1.0-ONNX";
|
|
11857
|
+
KOKORO_MAX_CHUNK_CHARS = 300;
|
|
11753
11858
|
modelPromise = null;
|
|
11754
11859
|
factoryOverride = null;
|
|
11755
11860
|
KokoroProvider = class {
|
|
@@ -11776,11 +11881,32 @@ var init_KokoroProvider = __esm({
|
|
|
11776
11881
|
}
|
|
11777
11882
|
try {
|
|
11778
11883
|
const model = await loadModel(options.onProgress);
|
|
11779
|
-
const
|
|
11884
|
+
const voiceOptions = {
|
|
11780
11885
|
voice: options.voice ?? KOKORO_DEFAULT_VOICE,
|
|
11781
11886
|
speed: options.speed ?? 1
|
|
11782
|
-
}
|
|
11783
|
-
const
|
|
11887
|
+
};
|
|
11888
|
+
const chunks = splitForKokoro(text);
|
|
11889
|
+
let buffer;
|
|
11890
|
+
if (chunks.length === 1) {
|
|
11891
|
+
buffer = Buffer.from((await model.generate(chunks[0], voiceOptions)).toWav());
|
|
11892
|
+
} else {
|
|
11893
|
+
const parts = [];
|
|
11894
|
+
let sampleRate = 24e3;
|
|
11895
|
+
for (const chunk of chunks) {
|
|
11896
|
+
const audio = await model.generate(chunk, voiceOptions);
|
|
11897
|
+
if (!audio.audio)
|
|
11898
|
+
throw new Error("Kokoro returned no raw samples to join");
|
|
11899
|
+
parts.push(audio.audio);
|
|
11900
|
+
sampleRate = audio.sampling_rate ?? sampleRate;
|
|
11901
|
+
}
|
|
11902
|
+
const samples = new Float32Array(parts.reduce((n, part) => n + part.length, 0));
|
|
11903
|
+
let offset = 0;
|
|
11904
|
+
for (const part of parts) {
|
|
11905
|
+
samples.set(part, offset);
|
|
11906
|
+
offset += part.length;
|
|
11907
|
+
}
|
|
11908
|
+
buffer = encodeFloatWav(samples, sampleRate);
|
|
11909
|
+
}
|
|
11784
11910
|
return {
|
|
11785
11911
|
success: true,
|
|
11786
11912
|
audioBuffer: buffer,
|
|
@@ -11815,11 +11941,12 @@ var init_kokoro = __esm({
|
|
|
11815
11941
|
});
|
|
11816
11942
|
|
|
11817
11943
|
// ../ai-providers/dist/openai-image/OpenAIImageProvider.js
|
|
11818
|
-
var DEFAULT_MODEL, OpenAIImageProvider, openaiImageProvider;
|
|
11944
|
+
var OPENAI_IMAGE_DEFAULT_MODEL, DEFAULT_MODEL, OpenAIImageProvider, openaiImageProvider;
|
|
11819
11945
|
var init_OpenAIImageProvider = __esm({
|
|
11820
11946
|
"../ai-providers/dist/openai-image/OpenAIImageProvider.js"() {
|
|
11821
11947
|
"use strict";
|
|
11822
|
-
|
|
11948
|
+
OPENAI_IMAGE_DEFAULT_MODEL = "gpt-image-2.5-sunburst";
|
|
11949
|
+
DEFAULT_MODEL = OPENAI_IMAGE_DEFAULT_MODEL;
|
|
11823
11950
|
OpenAIImageProvider = class {
|
|
11824
11951
|
constructor() {
|
|
11825
11952
|
this.id = "openai-image";
|
|
@@ -11841,7 +11968,7 @@ var init_OpenAIImageProvider = __esm({
|
|
|
11841
11968
|
}
|
|
11842
11969
|
/**
|
|
11843
11970
|
* Generate images from text prompt
|
|
11844
|
-
* Uses GPT Image
|
|
11971
|
+
* Uses GPT Image 2.5 Sunburst by default
|
|
11845
11972
|
*/
|
|
11846
11973
|
async generateImage(prompt3, options = {}) {
|
|
11847
11974
|
if (!this.apiKey) {
|
|
@@ -11851,28 +11978,20 @@ var init_OpenAIImageProvider = __esm({
|
|
|
11851
11978
|
};
|
|
11852
11979
|
}
|
|
11853
11980
|
const model = options.model || DEFAULT_MODEL;
|
|
11854
|
-
const isGPTImage = model === "gpt-image-1.5" || model === "gpt-image-2";
|
|
11855
11981
|
try {
|
|
11856
11982
|
const body = {
|
|
11857
11983
|
model,
|
|
11858
11984
|
prompt: prompt3,
|
|
11859
11985
|
n: options.n || 1
|
|
11860
11986
|
};
|
|
11861
|
-
|
|
11862
|
-
|
|
11863
|
-
|
|
11864
|
-
|
|
11865
|
-
|
|
11866
|
-
|
|
11867
|
-
|
|
11868
|
-
|
|
11869
|
-
body.size = options.size;
|
|
11870
|
-
}
|
|
11871
|
-
} else {
|
|
11872
|
-
body.response_format = "url";
|
|
11873
|
-
body.size = options.size || "1024x1024";
|
|
11874
|
-
body.quality = options.quality === "high" ? "hd" : options.quality || "standard";
|
|
11875
|
-
body.style = options.style || "vivid";
|
|
11987
|
+
const qualityMap = {
|
|
11988
|
+
standard: "medium",
|
|
11989
|
+
hd: "high"
|
|
11990
|
+
};
|
|
11991
|
+
const quality = options.quality || "medium";
|
|
11992
|
+
body.quality = qualityMap[quality] || quality;
|
|
11993
|
+
if (options.size && options.size !== "auto") {
|
|
11994
|
+
body.size = options.size;
|
|
11876
11995
|
}
|
|
11877
11996
|
const response = await fetch(`${this.baseUrl}/images/generations`, {
|
|
11878
11997
|
method: "POST",
|
|
@@ -12025,49 +12144,6 @@ var init_OpenAIImageProvider = __esm({
|
|
|
12025
12144
|
};
|
|
12026
12145
|
}
|
|
12027
12146
|
}
|
|
12028
|
-
/**
|
|
12029
|
-
* Create image variations (uses DALL-E 2)
|
|
12030
|
-
*/
|
|
12031
|
-
async createVariation(imageBuffer, options = {}) {
|
|
12032
|
-
if (!this.apiKey) {
|
|
12033
|
-
return {
|
|
12034
|
-
success: false,
|
|
12035
|
-
error: "OpenAI API key not configured"
|
|
12036
|
-
};
|
|
12037
|
-
}
|
|
12038
|
-
try {
|
|
12039
|
-
const formData = new FormData();
|
|
12040
|
-
const uint8Array = new Uint8Array(imageBuffer);
|
|
12041
|
-
formData.append("image", new Blob([uint8Array], { type: "image/png" }), "image.png");
|
|
12042
|
-
formData.append("model", "dall-e-2");
|
|
12043
|
-
formData.append("n", String(options.n || 1));
|
|
12044
|
-
formData.append("size", options.size || "1024x1024");
|
|
12045
|
-
const response = await fetch(`${this.baseUrl}/images/variations`, {
|
|
12046
|
-
method: "POST",
|
|
12047
|
-
headers: {
|
|
12048
|
-
Authorization: `Bearer ${this.apiKey}`
|
|
12049
|
-
},
|
|
12050
|
-
body: formData
|
|
12051
|
-
});
|
|
12052
|
-
if (!response.ok) {
|
|
12053
|
-
const error = await response.text();
|
|
12054
|
-
return {
|
|
12055
|
-
success: false,
|
|
12056
|
-
error: `API error: ${response.status} - ${error}`
|
|
12057
|
-
};
|
|
12058
|
-
}
|
|
12059
|
-
const data = await response.json();
|
|
12060
|
-
return {
|
|
12061
|
-
success: true,
|
|
12062
|
-
images: data.data.map((img) => ({ url: img.url }))
|
|
12063
|
-
};
|
|
12064
|
-
} catch (error) {
|
|
12065
|
-
return {
|
|
12066
|
-
success: false,
|
|
12067
|
-
error: error instanceof Error ? error.message : "Unknown error"
|
|
12068
|
-
};
|
|
12069
|
-
}
|
|
12070
|
-
}
|
|
12071
12147
|
};
|
|
12072
12148
|
openaiImageProvider = new OpenAIImageProvider();
|
|
12073
12149
|
}
|
|
@@ -12498,12 +12574,33 @@ var init_runway = __esm({
|
|
|
12498
12574
|
|
|
12499
12575
|
// ../ai-providers/dist/kling/KlingProvider.js
|
|
12500
12576
|
import { createHmac } from "node:crypto";
|
|
12577
|
+
function resolveKlingModel(alias) {
|
|
12578
|
+
const key = (alias ?? "v3").trim().toLowerCase();
|
|
12579
|
+
const aliases = {
|
|
12580
|
+
v3: "kling-v3",
|
|
12581
|
+
"kling-v3": "kling-v3",
|
|
12582
|
+
"v2.6": "kling-v2-6",
|
|
12583
|
+
"kling-v2-6": "kling-v2-6",
|
|
12584
|
+
"v2.5-turbo": "kling-v2-5-turbo",
|
|
12585
|
+
"v2.5": "kling-v2-5-turbo",
|
|
12586
|
+
"kling-v2-5-turbo": "kling-v2-5-turbo"
|
|
12587
|
+
};
|
|
12588
|
+
if (Object.hasOwn(aliases, key))
|
|
12589
|
+
return aliases[key];
|
|
12590
|
+
throw new Error(`Unknown Kling model "${alias}". Valid: v3, v2.6, v2.5-turbo.`);
|
|
12591
|
+
}
|
|
12592
|
+
function klingDuration(model, seconds) {
|
|
12593
|
+
const requested = typeof seconds === "number" && Number.isFinite(seconds) ? Math.round(seconds) : 5;
|
|
12594
|
+
if (model === "kling-v3")
|
|
12595
|
+
return String(Math.max(3, Math.min(15, requested)));
|
|
12596
|
+
return requested >= 10 ? "10" : "5";
|
|
12597
|
+
}
|
|
12501
12598
|
var DEFAULT_MODEL4, STD_MODE_MODELS, KlingProvider, klingProvider;
|
|
12502
12599
|
var init_KlingProvider = __esm({
|
|
12503
12600
|
"../ai-providers/dist/kling/KlingProvider.js"() {
|
|
12504
12601
|
"use strict";
|
|
12505
|
-
DEFAULT_MODEL4 = "kling-
|
|
12506
|
-
STD_MODE_MODELS = ["kling-v2-5-turbo", "kling-v2-6", "kling-v3"
|
|
12602
|
+
DEFAULT_MODEL4 = "kling-v3";
|
|
12603
|
+
STD_MODE_MODELS = ["kling-v2-5-turbo", "kling-v2-6", "kling-v3"];
|
|
12507
12604
|
KlingProvider = class {
|
|
12508
12605
|
constructor() {
|
|
12509
12606
|
this.id = "kling";
|
|
@@ -12518,11 +12615,11 @@ var init_KlingProvider = __esm({
|
|
|
12518
12615
|
async initialize(config2) {
|
|
12519
12616
|
if (config2.apiKey) {
|
|
12520
12617
|
const parts = config2.apiKey.split(":");
|
|
12521
|
-
if (parts.length === 2) {
|
|
12618
|
+
if (parts.length === 2 && parts[0] && parts[1]) {
|
|
12522
12619
|
this.accessKey = parts[0];
|
|
12523
12620
|
this.secretKey = parts[1];
|
|
12524
12621
|
} else {
|
|
12525
|
-
this.
|
|
12622
|
+
this.apiKey = config2.apiKey;
|
|
12526
12623
|
}
|
|
12527
12624
|
}
|
|
12528
12625
|
if (config2.baseUrl) {
|
|
@@ -12530,7 +12627,11 @@ var init_KlingProvider = __esm({
|
|
|
12530
12627
|
}
|
|
12531
12628
|
}
|
|
12532
12629
|
isConfigured() {
|
|
12533
|
-
return !!(this.accessKey && this.secretKey);
|
|
12630
|
+
return !!(this.apiKey || this.accessKey && this.secretKey);
|
|
12631
|
+
}
|
|
12632
|
+
/** Bearer value: the API key itself, or a JWT signed from the legacy pair. */
|
|
12633
|
+
bearerToken() {
|
|
12634
|
+
return this.apiKey ?? this.generateToken();
|
|
12534
12635
|
}
|
|
12535
12636
|
/**
|
|
12536
12637
|
* Generate JWT token for Kling API authentication
|
|
@@ -12560,11 +12661,11 @@ var init_KlingProvider = __esm({
|
|
|
12560
12661
|
return {
|
|
12561
12662
|
id: "",
|
|
12562
12663
|
status: "failed",
|
|
12563
|
-
error: "Kling API credentials not configured.
|
|
12664
|
+
error: "Kling API credentials not configured. Set KLING_API_KEY to your Kling API key (or the legacy ACCESS_KEY:SECRET_KEY pair)."
|
|
12564
12665
|
};
|
|
12565
12666
|
}
|
|
12566
12667
|
try {
|
|
12567
|
-
const token = this.
|
|
12668
|
+
const token = this.bearerToken();
|
|
12568
12669
|
const model = options?.model || DEFAULT_MODEL4;
|
|
12569
12670
|
let mode = options?.mode || "std";
|
|
12570
12671
|
if (!STD_MODE_MODELS.includes(model) && mode === "std") {
|
|
@@ -12582,7 +12683,7 @@ var init_KlingProvider = __esm({
|
|
|
12582
12683
|
model_name: model,
|
|
12583
12684
|
mode,
|
|
12584
12685
|
aspect_ratio: aspectRatioMap[options?.aspectRatio || "16:9"] || "16:9",
|
|
12585
|
-
duration: options?.duration
|
|
12686
|
+
duration: klingDuration(model, options?.duration)
|
|
12586
12687
|
};
|
|
12587
12688
|
if (options?.negativePrompt) {
|
|
12588
12689
|
body.negative_prompt = options.negativePrompt;
|
|
@@ -12694,7 +12795,7 @@ var init_KlingProvider = __esm({
|
|
|
12694
12795
|
};
|
|
12695
12796
|
}
|
|
12696
12797
|
try {
|
|
12697
|
-
const token = this.
|
|
12798
|
+
const token = this.bearerToken();
|
|
12698
12799
|
const response = await fetch(`${this.baseUrl}/videos/${type}/${id}`, {
|
|
12699
12800
|
headers: {
|
|
12700
12801
|
"Content-Type": "application/json",
|
|
@@ -12776,11 +12877,11 @@ var init_KlingProvider = __esm({
|
|
|
12776
12877
|
return {
|
|
12777
12878
|
id: "",
|
|
12778
12879
|
status: "failed",
|
|
12779
|
-
error: "Kling API credentials not configured.
|
|
12880
|
+
error: "Kling API credentials not configured. Set KLING_API_KEY to your Kling API key (or the legacy ACCESS_KEY:SECRET_KEY pair)."
|
|
12780
12881
|
};
|
|
12781
12882
|
}
|
|
12782
12883
|
try {
|
|
12783
|
-
const token = this.
|
|
12884
|
+
const token = this.bearerToken();
|
|
12784
12885
|
const body = {
|
|
12785
12886
|
video_id: videoId,
|
|
12786
12887
|
duration: options?.duration || "5"
|
|
@@ -12820,7 +12921,7 @@ var init_KlingProvider = __esm({
|
|
|
12820
12921
|
};
|
|
12821
12922
|
}
|
|
12822
12923
|
try {
|
|
12823
|
-
const token = this.
|
|
12924
|
+
const token = this.bearerToken();
|
|
12824
12925
|
const response = await fetch(`${this.baseUrl}/videos/video-extend/${id}`, {
|
|
12825
12926
|
headers: {
|
|
12826
12927
|
"Content-Type": "application/json",
|
|
@@ -12936,11 +13037,34 @@ var init_kling = __esm({
|
|
|
12936
13037
|
});
|
|
12937
13038
|
|
|
12938
13039
|
// ../ai-providers/dist/grok/GrokProvider.js
|
|
12939
|
-
|
|
13040
|
+
function resolveGrokVideoModel(alias) {
|
|
13041
|
+
const key = (alias ?? "1.5").trim().toLowerCase();
|
|
13042
|
+
const aliases = {
|
|
13043
|
+
"1.5": "grok-imagine-video-1.5",
|
|
13044
|
+
"grok-imagine-video-1.5": "grok-imagine-video-1.5",
|
|
13045
|
+
lite: "grok-imagine-video-1.5-lite",
|
|
13046
|
+
"1.5-lite": "grok-imagine-video-1.5-lite",
|
|
13047
|
+
"grok-imagine-video-1.5-lite": "grok-imagine-video-1.5-lite",
|
|
13048
|
+
classic: "grok-imagine-video",
|
|
13049
|
+
"grok-imagine-video": "grok-imagine-video"
|
|
13050
|
+
};
|
|
13051
|
+
if (Object.hasOwn(aliases, key))
|
|
13052
|
+
return aliases[key];
|
|
13053
|
+
throw new Error(`Unknown Grok video model "${alias}". Valid: 1.5, lite, classic.`);
|
|
13054
|
+
}
|
|
13055
|
+
function resolveGrokImageModel(alias) {
|
|
13056
|
+
if (alias === "pro" || alias === "2.0" || alias === "quality" || alias === "grok-imagine-image-2.0") {
|
|
13057
|
+
return { model: "grok-imagine-image-2.0", quality: "medium" };
|
|
13058
|
+
}
|
|
13059
|
+
return { model: "grok-imagine-image" };
|
|
13060
|
+
}
|
|
13061
|
+
var DEFAULT_MODEL5, DEFAULT_VIDEO_RESOLUTION, GROK_VIDEO_RESOLUTIONS, GrokProvider, grokProvider;
|
|
12940
13062
|
var init_GrokProvider = __esm({
|
|
12941
13063
|
"../ai-providers/dist/grok/GrokProvider.js"() {
|
|
12942
13064
|
"use strict";
|
|
12943
|
-
DEFAULT_MODEL5 = "grok-imagine-video";
|
|
13065
|
+
DEFAULT_MODEL5 = "grok-imagine-video-1.5";
|
|
13066
|
+
DEFAULT_VIDEO_RESOLUTION = "720p";
|
|
13067
|
+
GROK_VIDEO_RESOLUTIONS = ["480p", "720p", "1080p"];
|
|
12944
13068
|
GrokProvider = class {
|
|
12945
13069
|
constructor() {
|
|
12946
13070
|
this.id = "grok";
|
|
@@ -12974,6 +13098,7 @@ var init_GrokProvider = __esm({
|
|
|
12974
13098
|
try {
|
|
12975
13099
|
const body = {
|
|
12976
13100
|
model: options.model || "grok-imagine-image",
|
|
13101
|
+
...options.quality ? { quality: options.quality } : {},
|
|
12977
13102
|
prompt: prompt3,
|
|
12978
13103
|
n: options.n || 1,
|
|
12979
13104
|
response_format: options.responseFormat || "url"
|
|
@@ -13041,6 +13166,7 @@ var init_GrokProvider = __esm({
|
|
|
13041
13166
|
const dataUri = `data:image/png;base64,${base64}`;
|
|
13042
13167
|
const body = {
|
|
13043
13168
|
model: options.model || "grok-imagine-image",
|
|
13169
|
+
...options.quality ? { quality: options.quality } : {},
|
|
13044
13170
|
prompt: prompt3,
|
|
13045
13171
|
image: {
|
|
13046
13172
|
url: dataUri,
|
|
@@ -13107,11 +13233,15 @@ var init_GrokProvider = __esm({
|
|
|
13107
13233
|
try {
|
|
13108
13234
|
const duration = Math.round(Math.min(15, Math.max(1, options?.duration || 5)));
|
|
13109
13235
|
const body = {
|
|
13110
|
-
model: DEFAULT_MODEL5,
|
|
13236
|
+
model: options?.model || DEFAULT_MODEL5,
|
|
13111
13237
|
prompt: prompt3,
|
|
13112
13238
|
duration,
|
|
13113
|
-
aspect_ratio: options?.aspectRatio || "16:9"
|
|
13239
|
+
aspect_ratio: options?.aspectRatio || "16:9",
|
|
13240
|
+
resolution: GROK_VIDEO_RESOLUTIONS.includes(options?.resolution ?? "") ? options.resolution : DEFAULT_VIDEO_RESOLUTION
|
|
13114
13241
|
};
|
|
13242
|
+
if (typeof options?.generateAudio === "boolean") {
|
|
13243
|
+
body.generate_audio = options.generateAudio;
|
|
13244
|
+
}
|
|
13115
13245
|
if (options?.referenceImage) {
|
|
13116
13246
|
body.image = { url: options.referenceImage };
|
|
13117
13247
|
}
|
|
@@ -13173,13 +13303,14 @@ var init_GrokProvider = __esm({
|
|
|
13173
13303
|
const statusMap = {
|
|
13174
13304
|
pending: "pending",
|
|
13175
13305
|
done: "completed",
|
|
13176
|
-
expired: "failed"
|
|
13306
|
+
expired: "failed",
|
|
13307
|
+
failed: "failed"
|
|
13177
13308
|
};
|
|
13178
13309
|
return {
|
|
13179
13310
|
id,
|
|
13180
13311
|
status: statusMap[data.status] || "pending",
|
|
13181
13312
|
videoUrl: data.video?.url,
|
|
13182
|
-
error: data.status === "expired" ? "Generation expired" : void 0
|
|
13313
|
+
error: data.status === "expired" ? "Generation expired" : data.status === "failed" ? `Generation failed: ${data.error?.message ?? data.error?.code ?? "unknown error"}` : void 0
|
|
13183
13314
|
};
|
|
13184
13315
|
} catch (error) {
|
|
13185
13316
|
return {
|
|
@@ -17373,14 +17504,30 @@ var require_src = __commonJS({
|
|
|
17373
17504
|
});
|
|
17374
17505
|
|
|
17375
17506
|
// ../ai-providers/dist/fal/FalProvider.js
|
|
17507
|
+
function resolveSeedanceVariant(alias) {
|
|
17508
|
+
const key = (alias ?? "quality").trim().toLowerCase();
|
|
17509
|
+
const aliases = {
|
|
17510
|
+
quality: "seedance-2.0",
|
|
17511
|
+
"2.0": "seedance-2.0",
|
|
17512
|
+
"seedance-2.0": "seedance-2.0",
|
|
17513
|
+
fast: "seedance-2.0-fast",
|
|
17514
|
+
"seedance-2.0-fast": "seedance-2.0-fast",
|
|
17515
|
+
"2.5": "seedance-2.5",
|
|
17516
|
+
"seedance-2.5": "seedance-2.5"
|
|
17517
|
+
};
|
|
17518
|
+
if (Object.hasOwn(aliases, key))
|
|
17519
|
+
return aliases[key];
|
|
17520
|
+
throw new Error(`Unknown Seedance model "${alias}". Valid: quality, fast, 2.5.`);
|
|
17521
|
+
}
|
|
17376
17522
|
function estimateSeedanceVideoCostUsd(opts) {
|
|
17377
17523
|
const shortSide = SEEDANCE_SHORT_SIDE[opts.resolution ?? "720p"] ?? 720;
|
|
17378
17524
|
const [a, b] = (opts.aspectRatio ?? "16:9").split(":").map(Number);
|
|
17379
17525
|
const ratioFactor = a > 0 && b > 0 ? Math.max(a, b) / Math.min(a, b) : 16 / 9;
|
|
17380
17526
|
const longSide = Math.round(shortSide * ratioFactor);
|
|
17381
17527
|
const tokensPerSecond = shortSide * longSide * 24 / 1024;
|
|
17382
|
-
|
|
17383
|
-
|
|
17528
|
+
const rate = opts.v25 ? shortSide >= 1080 ? SEEDANCE_25_1080P_USD_PER_1K_TOKENS : SEEDANCE_25_USD_PER_1K_TOKENS : SEEDANCE_USD_PER_1K_TOKENS;
|
|
17529
|
+
let usdPerSecond = tokensPerSecond / 1e3 * rate;
|
|
17530
|
+
if (opts.fast && !opts.v25 && shortSide <= 720)
|
|
17384
17531
|
usdPerSecond *= SEEDANCE_FAST_FACTOR;
|
|
17385
17532
|
if (opts.hasVideoReference)
|
|
17386
17533
|
usdPerSecond *= SEEDANCE_VIDEO_REF_FACTOR;
|
|
@@ -17488,34 +17635,42 @@ function normaliseResolution(value) {
|
|
|
17488
17635
|
return "1080p";
|
|
17489
17636
|
return "720p";
|
|
17490
17637
|
}
|
|
17491
|
-
function normaliseDuration(value) {
|
|
17492
|
-
if (typeof value !== "number")
|
|
17493
|
-
return "auto";
|
|
17494
|
-
if (!Number.isFinite(value))
|
|
17638
|
+
function normaliseDuration(value, maxSec) {
|
|
17639
|
+
if (typeof value !== "number" || !Number.isFinite(value))
|
|
17495
17640
|
return "auto";
|
|
17496
|
-
return Math.max(4, Math.min(
|
|
17641
|
+
return String(Math.max(4, Math.min(maxSec, Math.round(value))));
|
|
17497
17642
|
}
|
|
17498
|
-
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;
|
|
17643
|
+
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;
|
|
17499
17644
|
var init_FalProvider = __esm({
|
|
17500
17645
|
"../ai-providers/dist/fal/FalProvider.js"() {
|
|
17501
17646
|
"use strict";
|
|
17502
17647
|
import_client = __toESM(require_src(), 1);
|
|
17503
17648
|
ENDPOINT_TEXT_TO_VIDEO = {
|
|
17504
17649
|
"seedance-2.0": "bytedance/seedance-2.0/text-to-video",
|
|
17505
|
-
"seedance-2.0-fast": "bytedance/seedance-2.0/fast/text-to-video"
|
|
17650
|
+
"seedance-2.0-fast": "bytedance/seedance-2.0/fast/text-to-video",
|
|
17651
|
+
"seedance-2.5": "bytedance/seedance-2.5/text-to-video"
|
|
17506
17652
|
};
|
|
17507
17653
|
ENDPOINT_IMAGE_TO_VIDEO = {
|
|
17508
17654
|
"seedance-2.0": "bytedance/seedance-2.0/image-to-video",
|
|
17509
|
-
"seedance-2.0-fast": "bytedance/seedance-2.0/fast/image-to-video"
|
|
17655
|
+
"seedance-2.0-fast": "bytedance/seedance-2.0/fast/image-to-video",
|
|
17656
|
+
"seedance-2.5": "bytedance/seedance-2.5/image-to-video"
|
|
17510
17657
|
};
|
|
17511
17658
|
ENDPOINT_REFERENCE_TO_VIDEO = {
|
|
17512
17659
|
"seedance-2.0": "bytedance/seedance-2.0/reference-to-video",
|
|
17513
|
-
"seedance-2.0-fast": "bytedance/seedance-2.0/fast/reference-to-video"
|
|
17660
|
+
"seedance-2.0-fast": "bytedance/seedance-2.0/fast/reference-to-video",
|
|
17661
|
+
"seedance-2.5": "bytedance/seedance-2.5/reference-to-video"
|
|
17514
17662
|
};
|
|
17515
17663
|
DEFAULT_VARIANT = "seedance-2.0";
|
|
17664
|
+
MAX_DURATION_SEC = {
|
|
17665
|
+
"seedance-2.0": 15,
|
|
17666
|
+
"seedance-2.0-fast": 15,
|
|
17667
|
+
"seedance-2.5": 30
|
|
17668
|
+
};
|
|
17516
17669
|
VALID_RESOLUTIONS = ["480p", "720p", "1080p"];
|
|
17517
17670
|
VALID_ASPECTS = ["21:9", "16:9", "4:3", "1:1", "3:4", "9:16", "auto"];
|
|
17518
17671
|
SEEDANCE_USD_PER_1K_TOKENS = 0.014;
|
|
17672
|
+
SEEDANCE_25_USD_PER_1K_TOKENS = 0.0214;
|
|
17673
|
+
SEEDANCE_25_1080P_USD_PER_1K_TOKENS = 0.0234;
|
|
17519
17674
|
SEEDANCE_FAST_FACTOR = 0.8;
|
|
17520
17675
|
SEEDANCE_VIDEO_REF_FACTOR = 0.6;
|
|
17521
17676
|
SEEDANCE_SHORT_SIDE = { "480p": 480, "720p": 720, "1080p": 1080 };
|
|
@@ -17570,7 +17725,7 @@ var init_FalProvider = __esm({
|
|
|
17570
17725
|
const endpointId = hasReferences ? ENDPOINT_REFERENCE_TO_VIDEO[variant] : isImageToVideo ? ENDPOINT_IMAGE_TO_VIDEO[variant] : ENDPOINT_TEXT_TO_VIDEO[variant];
|
|
17571
17726
|
const aspect = normaliseAspect(options?.aspectRatio);
|
|
17572
17727
|
const resolution = normaliseResolution(options?.resolution);
|
|
17573
|
-
const duration = normaliseDuration(options?.duration);
|
|
17728
|
+
const duration = normaliseDuration(options?.duration, MAX_DURATION_SEC[variant]);
|
|
17574
17729
|
const input = {
|
|
17575
17730
|
prompt: prompt3,
|
|
17576
17731
|
aspect_ratio: aspect,
|
|
@@ -17588,10 +17743,12 @@ var init_FalProvider = __esm({
|
|
|
17588
17743
|
} else if (referenceImage) {
|
|
17589
17744
|
input.image_url = referenceImage;
|
|
17590
17745
|
}
|
|
17591
|
-
if (
|
|
17592
|
-
|
|
17593
|
-
|
|
17594
|
-
|
|
17746
|
+
if (variant !== "seedance-2.5") {
|
|
17747
|
+
if (options?.negativePrompt)
|
|
17748
|
+
input.negative_prompt = options.negativePrompt;
|
|
17749
|
+
if (typeof options?.seed === "number")
|
|
17750
|
+
input.seed = options.seed;
|
|
17751
|
+
}
|
|
17595
17752
|
if (typeof options?.generateAudio === "boolean")
|
|
17596
17753
|
input.generate_audio = options.generateAudio;
|
|
17597
17754
|
if (options?.endUserId)
|
|
@@ -18318,6 +18475,7 @@ var init_replicate = __esm({
|
|
|
18318
18475
|
var dist_exports2 = {};
|
|
18319
18476
|
__export(dist_exports2, {
|
|
18320
18477
|
ClaudeProvider: () => ClaudeProvider,
|
|
18478
|
+
ELEVENLABS_MUSIC_MODEL: () => ELEVENLABS_MUSIC_MODEL,
|
|
18321
18479
|
ElevenLabsProvider: () => ElevenLabsProvider,
|
|
18322
18480
|
FalProvider: () => FalProvider,
|
|
18323
18481
|
GEMINI_AGENT_DEFAULT_TEXT_MODEL: () => GEMINI_AGENT_DEFAULT_TEXT_MODEL,
|
|
@@ -18331,6 +18489,7 @@ __export(dist_exports2, {
|
|
|
18331
18489
|
KOKORO_MODEL_ID: () => KOKORO_MODEL_ID,
|
|
18332
18490
|
KlingProvider: () => KlingProvider,
|
|
18333
18491
|
KokoroProvider: () => KokoroProvider,
|
|
18492
|
+
OPENAI_IMAGE_DEFAULT_MODEL: () => OPENAI_IMAGE_DEFAULT_MODEL,
|
|
18334
18493
|
OPENAI_TTS_VOICES: () => OPENAI_TTS_VOICES,
|
|
18335
18494
|
OllamaProvider: () => OllamaProvider,
|
|
18336
18495
|
OmniProvider: () => OmniProvider,
|
|
@@ -18339,6 +18498,7 @@ __export(dist_exports2, {
|
|
|
18339
18498
|
OpenAiTtsProvider: () => OpenAiTtsProvider,
|
|
18340
18499
|
ReplicateProvider: () => ReplicateProvider,
|
|
18341
18500
|
RunwayProvider: () => RunwayProvider,
|
|
18501
|
+
VEO_MODEL_ALIASES: () => VEO_MODEL_ALIASES,
|
|
18342
18502
|
WhisperProvider: () => WhisperProvider,
|
|
18343
18503
|
claudeProvider: () => claudeProvider,
|
|
18344
18504
|
defineApiKey: () => defineApiKey,
|
|
@@ -18359,6 +18519,7 @@ __export(dist_exports2, {
|
|
|
18359
18519
|
getSetupProviders: () => getSetupProviders,
|
|
18360
18520
|
grokProvider: () => grokProvider,
|
|
18361
18521
|
isGeminiTextModelAlias: () => isGeminiTextModelAlias,
|
|
18522
|
+
klingDuration: () => klingDuration,
|
|
18362
18523
|
klingProvider: () => klingProvider,
|
|
18363
18524
|
kokoroProvider: () => kokoroProvider,
|
|
18364
18525
|
loadBundledKokoroRuntime: () => loadBundledKokoroRuntime,
|
|
@@ -18371,6 +18532,11 @@ __export(dist_exports2, {
|
|
|
18371
18532
|
providerRegistry: () => providerRegistry,
|
|
18372
18533
|
replicateProvider: () => replicateProvider,
|
|
18373
18534
|
resolveGeminiTextModel: () => resolveGeminiTextModel,
|
|
18535
|
+
resolveGrokImageModel: () => resolveGrokImageModel,
|
|
18536
|
+
resolveGrokVideoModel: () => resolveGrokVideoModel,
|
|
18537
|
+
resolveKlingModel: () => resolveKlingModel,
|
|
18538
|
+
resolveSeedanceVariant: () => resolveSeedanceVariant,
|
|
18539
|
+
resolveVeoModel: () => resolveVeoModel,
|
|
18374
18540
|
resolveVoiceId: () => resolveVoiceId,
|
|
18375
18541
|
runwayProvider: () => runwayProvider,
|
|
18376
18542
|
whisperProvider: () => whisperProvider
|
|
@@ -33150,8 +33316,8 @@ var init_ai_motion = __esm({
|
|
|
33150
33316
|
init_output();
|
|
33151
33317
|
init_validate();
|
|
33152
33318
|
MODEL_MAP2 = {
|
|
33153
|
-
sonnet: { provider: "claude", modelId: "claude-sonnet-
|
|
33154
|
-
opus: { provider: "claude", modelId: "claude-opus-
|
|
33319
|
+
sonnet: { provider: "claude", modelId: "claude-sonnet-5-5" },
|
|
33320
|
+
opus: { provider: "claude", modelId: "claude-opus-5-5" },
|
|
33155
33321
|
"opus-4-6": { provider: "claude", modelId: "claude-opus-4-6" },
|
|
33156
33322
|
gemini: { provider: "gemini", modelId: GEMINI_DEFAULT_TEXT_MODEL },
|
|
33157
33323
|
"gemini-2.5-pro": { provider: "gemini", modelId: "gemini-2.5-pro" },
|
|
@@ -33197,7 +33363,7 @@ async function executeSoundEffect(options) {
|
|
|
33197
33363
|
}
|
|
33198
33364
|
}
|
|
33199
33365
|
function registerSoundEffectCommand(parent) {
|
|
33200
|
-
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-
|
|
33366
|
+
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) => {
|
|
33201
33367
|
const startedAt = Date.now();
|
|
33202
33368
|
try {
|
|
33203
33369
|
rejectControlChars(prompt3);
|
|
@@ -34126,8 +34292,14 @@ __export(ai_video_exports, {
|
|
|
34126
34292
|
executeVideoGenerate: () => executeVideoGenerate,
|
|
34127
34293
|
executeVideoStatus: () => executeVideoStatus
|
|
34128
34294
|
});
|
|
34129
|
-
import { readFile as readFile15, writeFile as writeFile17 } from "node:fs/promises";
|
|
34130
|
-
import { resolve as resolve21 } from "node:path";
|
|
34295
|
+
import { mkdir as mkdir8, readFile as readFile15, writeFile as writeFile17 } from "node:fs/promises";
|
|
34296
|
+
import { dirname as dirname3, resolve as resolve21 } from "node:path";
|
|
34297
|
+
async function saveOutput(output, buffer) {
|
|
34298
|
+
const outputPath = resolve21(process.cwd(), output);
|
|
34299
|
+
await mkdir8(dirname3(outputPath), { recursive: true });
|
|
34300
|
+
await writeFile17(outputPath, buffer);
|
|
34301
|
+
return outputPath;
|
|
34302
|
+
}
|
|
34131
34303
|
async function executeVideoGenerate(options) {
|
|
34132
34304
|
const {
|
|
34133
34305
|
prompt: prompt3,
|
|
@@ -34144,6 +34316,8 @@ async function executeVideoGenerate(options) {
|
|
|
34144
34316
|
resolution,
|
|
34145
34317
|
veoModel = "3.1-fast",
|
|
34146
34318
|
seedanceModel = "quality",
|
|
34319
|
+
grokModel,
|
|
34320
|
+
klingModel,
|
|
34147
34321
|
generateAudio,
|
|
34148
34322
|
output,
|
|
34149
34323
|
wait = true,
|
|
@@ -34198,7 +34372,7 @@ async function executeVideoGenerate(options) {
|
|
|
34198
34372
|
});
|
|
34199
34373
|
falImage = upload.url;
|
|
34200
34374
|
}
|
|
34201
|
-
const model = seedanceModel
|
|
34375
|
+
const model = resolveSeedanceVariant(seedanceModel);
|
|
34202
34376
|
const result = await fal.generateVideo(prompt3, {
|
|
34203
34377
|
prompt: prompt3,
|
|
34204
34378
|
referenceImage: references.length > 0 ? void 0 : falImage,
|
|
@@ -34215,8 +34389,7 @@ async function executeVideoGenerate(options) {
|
|
|
34215
34389
|
let outputPath;
|
|
34216
34390
|
if (output && result.videoUrl) {
|
|
34217
34391
|
const buffer = await downloadVideo(result.videoUrl, key);
|
|
34218
|
-
outputPath =
|
|
34219
|
-
await writeFile17(outputPath, buffer);
|
|
34392
|
+
outputPath = await saveOutput(output, buffer);
|
|
34220
34393
|
}
|
|
34221
34394
|
return {
|
|
34222
34395
|
success: true,
|
|
@@ -34247,8 +34420,7 @@ async function executeVideoGenerate(options) {
|
|
|
34247
34420
|
let outputPath;
|
|
34248
34421
|
if (output && finalResult.videoUrl) {
|
|
34249
34422
|
const buffer = await downloadVideo(finalResult.videoUrl, key);
|
|
34250
|
-
outputPath =
|
|
34251
|
-
await writeFile17(outputPath, buffer);
|
|
34423
|
+
outputPath = await saveOutput(output, buffer);
|
|
34252
34424
|
}
|
|
34253
34425
|
return {
|
|
34254
34426
|
success: true,
|
|
@@ -34274,6 +34446,7 @@ async function executeVideoGenerate(options) {
|
|
|
34274
34446
|
}
|
|
34275
34447
|
const result = await kling.generateVideo(prompt3, {
|
|
34276
34448
|
prompt: prompt3,
|
|
34449
|
+
model: resolveKlingModel(klingModel),
|
|
34277
34450
|
referenceImage: klingImage,
|
|
34278
34451
|
duration,
|
|
34279
34452
|
aspectRatio: ratio,
|
|
@@ -34292,8 +34465,7 @@ async function executeVideoGenerate(options) {
|
|
|
34292
34465
|
let outputPath;
|
|
34293
34466
|
if (output && finalResult.videoUrl) {
|
|
34294
34467
|
const buffer = await downloadVideo(finalResult.videoUrl, key);
|
|
34295
|
-
outputPath =
|
|
34296
|
-
await writeFile17(outputPath, buffer);
|
|
34468
|
+
outputPath = await saveOutput(output, buffer);
|
|
34297
34469
|
}
|
|
34298
34470
|
return {
|
|
34299
34471
|
success: true,
|
|
@@ -34307,12 +34479,7 @@ async function executeVideoGenerate(options) {
|
|
|
34307
34479
|
} else if (provider === "veo") {
|
|
34308
34480
|
const gemini = new GeminiProvider();
|
|
34309
34481
|
await gemini.initialize({ apiKey: key });
|
|
34310
|
-
const
|
|
34311
|
-
"3.0": "veo-3.0-generate-preview",
|
|
34312
|
-
"3.1": "veo-3.1-generate-preview",
|
|
34313
|
-
"3.1-fast": "veo-3.1-fast-generate-preview"
|
|
34314
|
-
};
|
|
34315
|
-
const model = veoModelMap[veoModel] || "veo-3.1-fast-generate-preview";
|
|
34482
|
+
const model = resolveVeoModel(veoModel);
|
|
34316
34483
|
const veoDuration = duration <= 6 ? 6 : 8;
|
|
34317
34484
|
const result = await gemini.generateVideo(prompt3, {
|
|
34318
34485
|
prompt: prompt3,
|
|
@@ -34333,8 +34500,7 @@ async function executeVideoGenerate(options) {
|
|
|
34333
34500
|
let outputPath;
|
|
34334
34501
|
if (output && finalResult.videoUrl) {
|
|
34335
34502
|
const buffer = await downloadVideo(finalResult.videoUrl, key);
|
|
34336
|
-
outputPath =
|
|
34337
|
-
await writeFile17(outputPath, buffer);
|
|
34503
|
+
outputPath = await saveOutput(output, buffer);
|
|
34338
34504
|
}
|
|
34339
34505
|
return {
|
|
34340
34506
|
success: true,
|
|
@@ -34349,9 +34515,12 @@ async function executeVideoGenerate(options) {
|
|
|
34349
34515
|
await grok.initialize({ apiKey: key });
|
|
34350
34516
|
const result = await grok.generateVideo(prompt3, {
|
|
34351
34517
|
prompt: prompt3,
|
|
34518
|
+
model: resolveGrokVideoModel(grokModel),
|
|
34352
34519
|
referenceImage,
|
|
34353
34520
|
duration,
|
|
34354
|
-
aspectRatio: ratio
|
|
34521
|
+
aspectRatio: ratio,
|
|
34522
|
+
resolution,
|
|
34523
|
+
generateAudio
|
|
34355
34524
|
});
|
|
34356
34525
|
if (result.status === "failed")
|
|
34357
34526
|
return { success: false, error: result.error || "Grok generation failed" };
|
|
@@ -34364,8 +34533,7 @@ async function executeVideoGenerate(options) {
|
|
|
34364
34533
|
let outputPath;
|
|
34365
34534
|
if (output && finalResult.videoUrl) {
|
|
34366
34535
|
const buffer = await downloadVideo(finalResult.videoUrl, key);
|
|
34367
|
-
outputPath =
|
|
34368
|
-
await writeFile17(outputPath, buffer);
|
|
34536
|
+
outputPath = await saveOutput(output, buffer);
|
|
34369
34537
|
}
|
|
34370
34538
|
return {
|
|
34371
34539
|
success: true,
|
|
@@ -34382,7 +34550,8 @@ async function executeVideoGenerate(options) {
|
|
|
34382
34550
|
const result = await omni.generateVideo(prompt3, {
|
|
34383
34551
|
prompt: prompt3,
|
|
34384
34552
|
referenceImage,
|
|
34385
|
-
aspectRatio: ratio
|
|
34553
|
+
aspectRatio: ratio,
|
|
34554
|
+
resolution
|
|
34386
34555
|
});
|
|
34387
34556
|
if (result.status !== "completed" || !result.videoUrl) {
|
|
34388
34557
|
return { success: false, error: result.error || "Gemini Omni generation failed" };
|
|
@@ -34390,8 +34559,7 @@ async function executeVideoGenerate(options) {
|
|
|
34390
34559
|
let outputPath;
|
|
34391
34560
|
if (output) {
|
|
34392
34561
|
const buffer = await downloadVideo(result.videoUrl, key);
|
|
34393
|
-
outputPath =
|
|
34394
|
-
await writeFile17(outputPath, buffer);
|
|
34562
|
+
outputPath = await saveOutput(output, buffer);
|
|
34395
34563
|
}
|
|
34396
34564
|
return {
|
|
34397
34565
|
success: true,
|
|
@@ -34487,8 +34655,7 @@ async function executeVideoStatus(options) {
|
|
|
34487
34655
|
let outputPath;
|
|
34488
34656
|
if (output && result.videoUrl) {
|
|
34489
34657
|
const buffer = await downloadVideo(result.videoUrl);
|
|
34490
|
-
outputPath =
|
|
34491
|
-
await writeFile17(outputPath, buffer);
|
|
34658
|
+
outputPath = await saveOutput(output, buffer);
|
|
34492
34659
|
}
|
|
34493
34660
|
return {
|
|
34494
34661
|
success: true,
|
|
@@ -34510,8 +34677,7 @@ async function executeVideoStatus(options) {
|
|
|
34510
34677
|
let outputPath;
|
|
34511
34678
|
if (output && result.videoUrl) {
|
|
34512
34679
|
const buffer = await downloadVideo(result.videoUrl, key);
|
|
34513
|
-
outputPath =
|
|
34514
|
-
await writeFile17(outputPath, buffer);
|
|
34680
|
+
outputPath = await saveOutput(output, buffer);
|
|
34515
34681
|
}
|
|
34516
34682
|
return {
|
|
34517
34683
|
success: true,
|
|
@@ -34532,8 +34698,7 @@ async function executeVideoStatus(options) {
|
|
|
34532
34698
|
let outputPath;
|
|
34533
34699
|
if (output && result.videoUrl) {
|
|
34534
34700
|
const buffer = await downloadVideo(result.videoUrl, key);
|
|
34535
|
-
outputPath =
|
|
34536
|
-
await writeFile17(outputPath, buffer);
|
|
34701
|
+
outputPath = await saveOutput(output, buffer);
|
|
34537
34702
|
}
|
|
34538
34703
|
return {
|
|
34539
34704
|
success: true,
|
|
@@ -34555,8 +34720,7 @@ async function executeVideoStatus(options) {
|
|
|
34555
34720
|
let outputPath;
|
|
34556
34721
|
if (output && result.videoUrl) {
|
|
34557
34722
|
const buffer = await downloadVideo(result.videoUrl, key);
|
|
34558
|
-
outputPath =
|
|
34559
|
-
await writeFile17(outputPath, buffer);
|
|
34723
|
+
outputPath = await saveOutput(output, buffer);
|
|
34560
34724
|
}
|
|
34561
34725
|
return {
|
|
34562
34726
|
success: true,
|
|
@@ -34626,8 +34790,7 @@ async function executeVideoExtend(options) {
|
|
|
34626
34790
|
let outputPath;
|
|
34627
34791
|
if (output && finalResult.videoUrl) {
|
|
34628
34792
|
const buffer = await downloadVideo(finalResult.videoUrl, key);
|
|
34629
|
-
outputPath =
|
|
34630
|
-
await writeFile17(outputPath, buffer);
|
|
34793
|
+
outputPath = await saveOutput(output, buffer);
|
|
34631
34794
|
}
|
|
34632
34795
|
return {
|
|
34633
34796
|
success: true,
|
|
@@ -34642,12 +34805,7 @@ async function executeVideoExtend(options) {
|
|
|
34642
34805
|
if (!key) return { success: false, error: "GOOGLE_API_KEY required" };
|
|
34643
34806
|
const gemini = new GeminiProvider();
|
|
34644
34807
|
await gemini.initialize({ apiKey: key });
|
|
34645
|
-
const
|
|
34646
|
-
"3.0": "veo-3.0-generate-preview",
|
|
34647
|
-
"3.1": "veo-3.1-generate-preview",
|
|
34648
|
-
"3.1-fast": "veo-3.1-fast-generate-preview"
|
|
34649
|
-
};
|
|
34650
|
-
const model = veoModelMap[veoModel] || "veo-3.1-generate-preview";
|
|
34808
|
+
const model = resolveVeoModel(veoModel);
|
|
34651
34809
|
const result = await gemini.extendVideo(videoId, prompt3, {
|
|
34652
34810
|
duration,
|
|
34653
34811
|
model
|
|
@@ -34662,8 +34820,7 @@ async function executeVideoExtend(options) {
|
|
|
34662
34820
|
let outputPath;
|
|
34663
34821
|
if (output && finalResult.videoUrl) {
|
|
34664
34822
|
const buffer = await downloadVideo(finalResult.videoUrl, key);
|
|
34665
|
-
outputPath =
|
|
34666
|
-
await writeFile17(outputPath, buffer);
|
|
34823
|
+
outputPath = await saveOutput(output, buffer);
|
|
34667
34824
|
}
|
|
34668
34825
|
return {
|
|
34669
34826
|
success: true,
|
|
@@ -34725,8 +34882,8 @@ var init_music_status = __esm({
|
|
|
34725
34882
|
|
|
34726
34883
|
// src/commands/_shared/build-asset-metadata.ts
|
|
34727
34884
|
import { existsSync as existsSync14, readFileSync } from "node:fs";
|
|
34728
|
-
import { mkdir as
|
|
34729
|
-
import { dirname as
|
|
34885
|
+
import { mkdir as mkdir9, writeFile as writeFile18 } from "node:fs/promises";
|
|
34886
|
+
import { dirname as dirname4, join as join11 } from "node:path";
|
|
34730
34887
|
function assetMetadataPath(kind, beatId) {
|
|
34731
34888
|
return `.vibeframe/assets/${kind}-${beatId}.json`;
|
|
34732
34889
|
}
|
|
@@ -34774,7 +34931,7 @@ async function writeAssetMetadata(opts) {
|
|
|
34774
34931
|
cachePath: opts.cachePath,
|
|
34775
34932
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
34776
34933
|
};
|
|
34777
|
-
await
|
|
34934
|
+
await mkdir9(dirname4(abs), { recursive: true });
|
|
34778
34935
|
await writeFile18(abs, JSON.stringify(metadata, null, 2) + "\n", "utf-8");
|
|
34779
34936
|
}
|
|
34780
34937
|
var init_build_asset_metadata = __esm({
|
|
@@ -34786,22 +34943,22 @@ var init_build_asset_metadata = __esm({
|
|
|
34786
34943
|
// src/commands/_shared/status-jobs.ts
|
|
34787
34944
|
import { createHash as createHash3, randomUUID as randomUUID2 } from "node:crypto";
|
|
34788
34945
|
import { existsSync as existsSync15, statSync } from "node:fs";
|
|
34789
|
-
import { copyFile as copyFile3, mkdir as
|
|
34790
|
-
import { dirname as
|
|
34946
|
+
import { copyFile as copyFile3, mkdir as mkdir10, readFile as readFile16, readdir as readdir3, rename as rename2, stat as stat4, writeFile as writeFile19 } from "node:fs/promises";
|
|
34947
|
+
import { dirname as dirname5, join as join12, parse as parse2, relative as relative6, resolve as resolve22 } from "node:path";
|
|
34791
34948
|
function isLocalJob(record) {
|
|
34792
34949
|
return record.jobType === "build" || record.jobType === "render";
|
|
34793
34950
|
}
|
|
34794
34951
|
function findProjectRoot(start = process.cwd()) {
|
|
34795
34952
|
let dir = resolve22(start);
|
|
34796
34953
|
try {
|
|
34797
|
-
if (existsSync15(dir) && statSync(dir).isFile()) dir =
|
|
34954
|
+
if (existsSync15(dir) && statSync(dir).isFile()) dir = dirname5(dir);
|
|
34798
34955
|
} catch {
|
|
34799
34956
|
}
|
|
34800
34957
|
for (; ; ) {
|
|
34801
34958
|
if (existsSync15(join12(dir, "vibe.config.json")) || existsSync15(join12(dir, "STORYBOARD.md"))) {
|
|
34802
34959
|
return dir;
|
|
34803
34960
|
}
|
|
34804
|
-
const parent =
|
|
34961
|
+
const parent = dirname5(dir);
|
|
34805
34962
|
if (parent === dir) return resolve22(start);
|
|
34806
34963
|
dir = parent;
|
|
34807
34964
|
}
|
|
@@ -34868,7 +35025,7 @@ async function createAndWriteJobRecord(opts) {
|
|
|
34868
35025
|
}
|
|
34869
35026
|
async function writeJobRecord(record) {
|
|
34870
35027
|
const dir = jobsDir(record.projectDir);
|
|
34871
|
-
await
|
|
35028
|
+
await mkdir10(dir, { recursive: true });
|
|
34872
35029
|
const path2 = jobRecordPath(record.id, record.projectDir);
|
|
34873
35030
|
const tmp = `${path2}.${randomUUID2()}.tmp`;
|
|
34874
35031
|
await writeFile19(tmp, JSON.stringify(stripUndefined2(record), null, 2) + "\n", "utf-8");
|
|
@@ -34916,7 +35073,7 @@ async function refreshJobRecord(record, opts = {}) {
|
|
|
34916
35073
|
try {
|
|
34917
35074
|
if (record.jobType === "generate-video") {
|
|
34918
35075
|
const output = resolveRefreshOutput(record, opts);
|
|
34919
|
-
if (output) await
|
|
35076
|
+
if (output) await mkdir10(dirname5(output), { recursive: true });
|
|
34920
35077
|
const result = await executeVideoStatus({
|
|
34921
35078
|
taskId: record.providerTaskId,
|
|
34922
35079
|
provider: record.provider,
|
|
@@ -35199,14 +35356,14 @@ async function downloadUrl(url, outputPath) {
|
|
|
35199
35356
|
const response = await fetch(url);
|
|
35200
35357
|
if (!response.ok) throw new Error(`Download failed: HTTP ${response.status}`);
|
|
35201
35358
|
const buffer = Buffer.from(await response.arrayBuffer());
|
|
35202
|
-
await
|
|
35359
|
+
await mkdir10(dirname5(outputPath), { recursive: true });
|
|
35203
35360
|
await writeFile19(outputPath, buffer);
|
|
35204
35361
|
return outputPath;
|
|
35205
35362
|
}
|
|
35206
35363
|
async function maybeCacheOutput(record) {
|
|
35207
35364
|
if (record.status !== "completed" || !record.outputPath || !record.cachePath) return;
|
|
35208
35365
|
try {
|
|
35209
|
-
await
|
|
35366
|
+
await mkdir10(dirname5(record.cachePath), { recursive: true });
|
|
35210
35367
|
await copyFile3(record.outputPath, record.cachePath);
|
|
35211
35368
|
} catch {
|
|
35212
35369
|
}
|
|
@@ -35805,7 +35962,7 @@ function registerMusicCommand(parent) {
|
|
|
35805
35962
|
console.log();
|
|
35806
35963
|
console.log(`Saved to: ${source_default.bold(outputPath)}`);
|
|
35807
35964
|
console.log(`Duration: ${duration}s`);
|
|
35808
|
-
console.log(`Provider: ElevenLabs (
|
|
35965
|
+
console.log(`Provider: ElevenLabs (${ELEVENLABS_MUSIC_MODEL})`);
|
|
35809
35966
|
if (options.instrumental) console.log(`Mode: Instrumental`);
|
|
35810
35967
|
console.log();
|
|
35811
35968
|
} else {
|
|
@@ -35934,6 +36091,48 @@ var init_music = __esm({
|
|
|
35934
36091
|
}
|
|
35935
36092
|
});
|
|
35936
36093
|
|
|
36094
|
+
// src/utils/image-file.ts
|
|
36095
|
+
import { rm as rm3, writeFile as writeFile21 } from "node:fs/promises";
|
|
36096
|
+
import { extname as extname3 } from "node:path";
|
|
36097
|
+
function detectImageFormat(buffer) {
|
|
36098
|
+
if (buffer.subarray(0, 8).equals(Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]))) {
|
|
36099
|
+
return "png";
|
|
36100
|
+
}
|
|
36101
|
+
if (buffer[0] === 255 && buffer[1] === 216 && buffer[2] === 255) return "jpeg";
|
|
36102
|
+
if (buffer.toString("ascii", 0, 4) === "RIFF" && buffer.toString("ascii", 8, 12) === "WEBP") {
|
|
36103
|
+
return "webp";
|
|
36104
|
+
}
|
|
36105
|
+
return void 0;
|
|
36106
|
+
}
|
|
36107
|
+
async function writeImageFile(path2, buffer) {
|
|
36108
|
+
const wanted = EXTENSION_FORMATS[extname3(path2).toLowerCase()];
|
|
36109
|
+
const actual = detectImageFormat(buffer);
|
|
36110
|
+
if (!wanted || !actual || wanted === actual) {
|
|
36111
|
+
await writeFile21(path2, buffer);
|
|
36112
|
+
return;
|
|
36113
|
+
}
|
|
36114
|
+
const source = `${path2}.source.${actual === "jpeg" ? "jpg" : actual}`;
|
|
36115
|
+
await writeFile21(source, buffer);
|
|
36116
|
+
try {
|
|
36117
|
+
await execSafe("ffmpeg", ["-y", "-loglevel", "error", "-i", source, "-frames:v", "1", path2]);
|
|
36118
|
+
} finally {
|
|
36119
|
+
await rm3(source, { force: true });
|
|
36120
|
+
}
|
|
36121
|
+
}
|
|
36122
|
+
var EXTENSION_FORMATS;
|
|
36123
|
+
var init_image_file = __esm({
|
|
36124
|
+
"src/utils/image-file.ts"() {
|
|
36125
|
+
"use strict";
|
|
36126
|
+
init_exec_safe();
|
|
36127
|
+
EXTENSION_FORMATS = {
|
|
36128
|
+
".png": "png",
|
|
36129
|
+
".jpg": "jpeg",
|
|
36130
|
+
".jpeg": "jpeg",
|
|
36131
|
+
".webp": "webp"
|
|
36132
|
+
};
|
|
36133
|
+
}
|
|
36134
|
+
});
|
|
36135
|
+
|
|
35937
36136
|
// src/commands/ai-image.ts
|
|
35938
36137
|
var ai_image_exports = {};
|
|
35939
36138
|
__export(ai_image_exports, {
|
|
@@ -35941,8 +36140,8 @@ __export(ai_image_exports, {
|
|
|
35941
36140
|
executeImageGenerate: () => executeImageGenerate,
|
|
35942
36141
|
executeThumbnailBestFrame: () => executeThumbnailBestFrame
|
|
35943
36142
|
});
|
|
35944
|
-
import { resolve as resolve24, dirname as
|
|
35945
|
-
import { readFile as readFile17,
|
|
36143
|
+
import { resolve as resolve24, dirname as dirname6 } from "node:path";
|
|
36144
|
+
import { readFile as readFile17, mkdir as mkdir11 } from "node:fs/promises";
|
|
35946
36145
|
import { existsSync as existsSync17 } from "node:fs";
|
|
35947
36146
|
async function executeImageGenerate(options) {
|
|
35948
36147
|
const {
|
|
@@ -35985,8 +36184,8 @@ async function executeImageGenerate(options) {
|
|
|
35985
36184
|
return { success: false, error: "No image data available" };
|
|
35986
36185
|
}
|
|
35987
36186
|
outputPath = resolve24(process.cwd(), output);
|
|
35988
|
-
await
|
|
35989
|
-
await
|
|
36187
|
+
await mkdir11(dirname6(outputPath), { recursive: true });
|
|
36188
|
+
await writeImageFile(outputPath, buffer);
|
|
35990
36189
|
}
|
|
35991
36190
|
return {
|
|
35992
36191
|
success: true,
|
|
@@ -36020,8 +36219,8 @@ async function executeImageGenerate(options) {
|
|
|
36020
36219
|
const img = result.images[0];
|
|
36021
36220
|
if (img.base64) {
|
|
36022
36221
|
outputPath = resolve24(process.cwd(), output);
|
|
36023
|
-
await
|
|
36024
|
-
await
|
|
36222
|
+
await mkdir11(dirname6(outputPath), { recursive: true });
|
|
36223
|
+
await writeImageFile(outputPath, Buffer.from(img.base64, "base64"));
|
|
36025
36224
|
}
|
|
36026
36225
|
}
|
|
36027
36226
|
return {
|
|
@@ -36034,10 +36233,11 @@ async function executeImageGenerate(options) {
|
|
|
36034
36233
|
} else if (provider === "grok") {
|
|
36035
36234
|
const key = apiKey || process.env.XAI_API_KEY;
|
|
36036
36235
|
if (!key) return { success: false, error: "XAI_API_KEY required" };
|
|
36037
|
-
const
|
|
36038
|
-
await
|
|
36039
|
-
const result = await
|
|
36040
|
-
|
|
36236
|
+
const grok = new GrokProvider();
|
|
36237
|
+
await grok.initialize({ apiKey: key });
|
|
36238
|
+
const result = await grok.generateImage(prompt3, {
|
|
36239
|
+
...resolveGrokImageModel(model),
|
|
36240
|
+
aspectRatio: ratio,
|
|
36041
36241
|
n: count
|
|
36042
36242
|
});
|
|
36043
36243
|
if (!result.success || !result.images) {
|
|
@@ -36056,8 +36256,8 @@ async function executeImageGenerate(options) {
|
|
|
36056
36256
|
return { success: false, error: "No image data available" };
|
|
36057
36257
|
}
|
|
36058
36258
|
outputPath = resolve24(process.cwd(), output);
|
|
36059
|
-
await
|
|
36060
|
-
await
|
|
36259
|
+
await mkdir11(dirname6(outputPath), { recursive: true });
|
|
36260
|
+
await writeImageFile(outputPath, buffer);
|
|
36061
36261
|
}
|
|
36062
36262
|
return {
|
|
36063
36263
|
success: true,
|
|
@@ -36115,8 +36315,8 @@ async function executeGeminiEdit(options) {
|
|
|
36115
36315
|
let outputPath;
|
|
36116
36316
|
if (img.base64) {
|
|
36117
36317
|
outputPath = resolve24(process.cwd(), output);
|
|
36118
|
-
await
|
|
36119
|
-
await
|
|
36318
|
+
await mkdir11(dirname6(outputPath), { recursive: true });
|
|
36319
|
+
await writeImageFile(outputPath, Buffer.from(img.base64, "base64"));
|
|
36120
36320
|
}
|
|
36121
36321
|
return {
|
|
36122
36322
|
success: true,
|
|
@@ -36190,13 +36390,14 @@ var init_ai_image = __esm({
|
|
|
36190
36390
|
"use strict";
|
|
36191
36391
|
init_dist2();
|
|
36192
36392
|
init_exec_safe();
|
|
36393
|
+
init_image_file();
|
|
36193
36394
|
}
|
|
36194
36395
|
});
|
|
36195
36396
|
|
|
36196
36397
|
// src/commands/generate/thumbnail.ts
|
|
36197
|
-
import { resolve as resolve25, dirname as
|
|
36398
|
+
import { resolve as resolve25, dirname as dirname7, basename as basename5, extname as extname4 } from "node:path";
|
|
36198
36399
|
import { existsSync as existsSync18 } from "node:fs";
|
|
36199
|
-
import { writeFile as writeFile22, mkdir as
|
|
36400
|
+
import { writeFile as writeFile22, mkdir as mkdir12 } from "node:fs/promises";
|
|
36200
36401
|
function registerThumbnailCommand(parent) {
|
|
36201
36402
|
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) => {
|
|
36202
36403
|
const startedAt = Date.now();
|
|
@@ -36219,7 +36420,7 @@ function registerThumbnailCommand(parent) {
|
|
|
36219
36420
|
);
|
|
36220
36421
|
}
|
|
36221
36422
|
const apiKey2 = await requireApiKey("GOOGLE_API_KEY", "Google", options.apiKey);
|
|
36222
|
-
const name = basename5(options.bestFrame,
|
|
36423
|
+
const name = basename5(options.bestFrame, extname4(options.bestFrame));
|
|
36223
36424
|
const outputPath = options.output || `${name}-thumbnail.png`;
|
|
36224
36425
|
const spinner3 = ora("Analyzing video for best frame...").start();
|
|
36225
36426
|
const result2 = await executeThumbnailBestFrame({
|
|
@@ -36287,7 +36488,7 @@ function registerThumbnailCommand(parent) {
|
|
|
36287
36488
|
throw new Error("No image data available");
|
|
36288
36489
|
}
|
|
36289
36490
|
outputPath = resolve25(process.cwd(), options.output);
|
|
36290
|
-
await
|
|
36491
|
+
await mkdir12(dirname7(outputPath), { recursive: true });
|
|
36291
36492
|
await writeFile22(outputPath, buffer);
|
|
36292
36493
|
}
|
|
36293
36494
|
outputSuccess({
|
|
@@ -36318,7 +36519,7 @@ function registerThumbnailCommand(parent) {
|
|
|
36318
36519
|
throw new Error("No image data available");
|
|
36319
36520
|
}
|
|
36320
36521
|
const outputPath = resolve25(process.cwd(), options.output);
|
|
36321
|
-
await
|
|
36522
|
+
await mkdir12(dirname7(outputPath), { recursive: true });
|
|
36322
36523
|
await writeFile22(outputPath, buffer);
|
|
36323
36524
|
saveSpinner.succeed(source_default.green(`Saved to: ${outputPath}`));
|
|
36324
36525
|
} catch {
|
|
@@ -36349,7 +36550,7 @@ var init_thumbnail = __esm({
|
|
|
36349
36550
|
import { resolve as resolve26 } from "node:path";
|
|
36350
36551
|
import { writeFile as writeFile23 } from "node:fs/promises";
|
|
36351
36552
|
function registerVideoExtendCommand(parent) {
|
|
36352
|
-
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.
|
|
36553
|
+
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) => {
|
|
36353
36554
|
const startedAt = Date.now();
|
|
36354
36555
|
try {
|
|
36355
36556
|
const provider = (options.provider || "kling").toLowerCase();
|
|
@@ -36467,12 +36668,7 @@ function registerVideoExtendCommand(parent) {
|
|
|
36467
36668
|
const spinner2 = ora("Initializing Veo...").start();
|
|
36468
36669
|
const gemini = new GeminiProvider();
|
|
36469
36670
|
await gemini.initialize({ apiKey });
|
|
36470
|
-
const
|
|
36471
|
-
"3.0": "veo-3.0-generate-preview",
|
|
36472
|
-
"3.1": "veo-3.1-generate-preview",
|
|
36473
|
-
"3.1-fast": "veo-3.1-fast-generate-preview"
|
|
36474
|
-
};
|
|
36475
|
-
const veoModel = veoModelMap[options.veoModel] || "veo-3.1-generate-preview";
|
|
36671
|
+
const veoModel = resolveVeoModel(options.veoModel);
|
|
36476
36672
|
spinner2.text = "Starting video extension...";
|
|
36477
36673
|
const result = await gemini.extendVideo(id, options.prompt, {
|
|
36478
36674
|
duration: parseInt(options.duration),
|
|
@@ -36633,10 +36829,15 @@ var init_provider_resolver = __esm({
|
|
|
36633
36829
|
|
|
36634
36830
|
// src/commands/_shared/openai-image.ts
|
|
36635
36831
|
function resolveOpenAIImageModel(modelAlias) {
|
|
36636
|
-
const
|
|
36832
|
+
const alias = modelAlias?.trim() ?? "";
|
|
36833
|
+
for (const [id, model] of Object.entries(OPENAI_IMAGE_MODELS)) {
|
|
36834
|
+
if (alias === id || model.aliases.includes(alias)) {
|
|
36835
|
+
return { openaiModel: id, modelLabel: model.label };
|
|
36836
|
+
}
|
|
36837
|
+
}
|
|
36637
36838
|
return {
|
|
36638
|
-
openaiModel:
|
|
36639
|
-
modelLabel:
|
|
36839
|
+
openaiModel: OPENAI_IMAGE_DEFAULT_MODEL,
|
|
36840
|
+
modelLabel: OPENAI_IMAGE_MODELS[OPENAI_IMAGE_DEFAULT_MODEL].label
|
|
36640
36841
|
};
|
|
36641
36842
|
}
|
|
36642
36843
|
async function executeOpenAIImageGenerate(prompt3, options, ctx) {
|
|
@@ -36652,17 +36853,24 @@ async function executeOpenAIImageGenerate(prompt3, options, ctx) {
|
|
|
36652
36853
|
});
|
|
36653
36854
|
return { result, openaiModel, modelLabel };
|
|
36654
36855
|
}
|
|
36856
|
+
var OPENAI_IMAGE_MODELS;
|
|
36655
36857
|
var init_openai_image2 = __esm({
|
|
36656
36858
|
"src/commands/_shared/openai-image.ts"() {
|
|
36657
36859
|
"use strict";
|
|
36658
36860
|
init_dist2();
|
|
36861
|
+
OPENAI_IMAGE_MODELS = {
|
|
36862
|
+
"gpt-image-2.5-sunburst": { label: "GPT Image 2.5 Sunburst", aliases: ["2.5", "sunburst"] },
|
|
36863
|
+
"gpt-image-2.5-flare": { label: "GPT Image 2.5 Flare", aliases: ["flare", "2.5-flare"] },
|
|
36864
|
+
"gpt-image-2": { label: "GPT Image 2", aliases: ["2"] },
|
|
36865
|
+
"gpt-image-1.5": { label: "GPT Image 1.5", aliases: ["1.5"] }
|
|
36866
|
+
};
|
|
36659
36867
|
}
|
|
36660
36868
|
});
|
|
36661
36869
|
|
|
36662
36870
|
// src/commands/generate/image.ts
|
|
36663
|
-
import { resolve as resolve27, dirname as
|
|
36871
|
+
import { resolve as resolve27, dirname as dirname8 } from "node:path";
|
|
36664
36872
|
import { fileURLToPath } from "node:url";
|
|
36665
|
-
import {
|
|
36873
|
+
import { mkdir as mkdir13 } from "node:fs/promises";
|
|
36666
36874
|
function registerImageCommand(parent) {
|
|
36667
36875
|
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(
|
|
36668
36876
|
"-p, --provider <provider>",
|
|
@@ -36673,7 +36881,7 @@ function registerImageCommand(parent) {
|
|
|
36673
36881
|
"1:1"
|
|
36674
36882
|
).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(
|
|
36675
36883
|
"-m, --model <model>",
|
|
36676
|
-
"Model. Gemini: flash
|
|
36884
|
+
"Model. Gemini: flash (default), lite, pro. OpenAI: 2.5 (default), flare, 2, 1.5. Grok: pro"
|
|
36677
36885
|
).option("--dry-run", "Preview parameters without executing").addHelpText(
|
|
36678
36886
|
"after",
|
|
36679
36887
|
`
|
|
@@ -36776,7 +36984,7 @@ Examples:
|
|
|
36776
36984
|
const apiKey = await requireApiKey(envKey, providerName, options.apiKey);
|
|
36777
36985
|
const spinner2 = ora(`Generating image with ${providerName}...`).start();
|
|
36778
36986
|
if (provider === "openai") {
|
|
36779
|
-
const { result, modelLabel } = await executeOpenAIImageGenerate(prompt3, options, {
|
|
36987
|
+
const { result, modelLabel, openaiModel } = await executeOpenAIImageGenerate(prompt3, options, {
|
|
36780
36988
|
apiKey
|
|
36781
36989
|
});
|
|
36782
36990
|
if (!result.success || !result.images) {
|
|
@@ -36799,14 +37007,16 @@ Examples:
|
|
|
36799
37007
|
} else {
|
|
36800
37008
|
throw new Error("No image data available");
|
|
36801
37009
|
}
|
|
36802
|
-
await
|
|
36803
|
-
await
|
|
37010
|
+
await mkdir13(dirname8(outputPath), { recursive: true });
|
|
37011
|
+
await writeImageFile(outputPath, buffer);
|
|
36804
37012
|
}
|
|
36805
37013
|
outputSuccess({
|
|
36806
37014
|
command: "generate image",
|
|
36807
37015
|
startedAt,
|
|
36808
37016
|
data: {
|
|
36809
37017
|
provider: "openai",
|
|
37018
|
+
model: modelLabel,
|
|
37019
|
+
modelId: openaiModel,
|
|
36810
37020
|
images: result.images.map((img) => ({
|
|
36811
37021
|
url: img.url,
|
|
36812
37022
|
revisedPrompt: img.revisedPrompt
|
|
@@ -36846,8 +37056,8 @@ Examples:
|
|
|
36846
37056
|
throw new Error("No image data available");
|
|
36847
37057
|
}
|
|
36848
37058
|
const outputPath = resolve27(process.cwd(), options.output);
|
|
36849
|
-
await
|
|
36850
|
-
await
|
|
37059
|
+
await mkdir13(dirname8(outputPath), { recursive: true });
|
|
37060
|
+
await writeImageFile(outputPath, buffer);
|
|
36851
37061
|
saveSpinner.succeed(source_default.green(`Saved to: ${outputPath}`));
|
|
36852
37062
|
} catch (err) {
|
|
36853
37063
|
saveSpinner.fail(
|
|
@@ -36856,7 +37066,7 @@ Examples:
|
|
|
36856
37066
|
}
|
|
36857
37067
|
}
|
|
36858
37068
|
} else if (provider === "gemini") {
|
|
36859
|
-
const validGeminiModels = ["flash", "3.1-flash", "latest", "pro"];
|
|
37069
|
+
const validGeminiModels = ["flash", "3.1-flash", "latest", "lite", "pro"];
|
|
36860
37070
|
if (options.model && !validGeminiModels.includes(options.model)) {
|
|
36861
37071
|
console.warn(
|
|
36862
37072
|
source_default.yellow(
|
|
@@ -36889,26 +37099,17 @@ Examples:
|
|
|
36889
37099
|
const gemini = new GeminiProvider();
|
|
36890
37100
|
await gemini.initialize({ apiKey });
|
|
36891
37101
|
const geminiModelNames = {
|
|
36892
|
-
flash: "Nano Banana",
|
|
37102
|
+
flash: "Nano Banana 2",
|
|
36893
37103
|
"3.1-flash": "Nano Banana 2",
|
|
36894
37104
|
latest: "Nano Banana 2",
|
|
37105
|
+
lite: "Nano Banana 2 Lite",
|
|
36895
37106
|
pro: "Nano Banana Pro"
|
|
36896
37107
|
};
|
|
36897
|
-
const
|
|
36898
|
-
|
|
37108
|
+
const usedLabel = geminiModelNames[options.model] || "Nano Banana 2";
|
|
37109
|
+
const result = await gemini.generateImage(prompt3, {
|
|
36899
37110
|
model: options.model,
|
|
36900
37111
|
aspectRatio: options.ratio
|
|
36901
37112
|
});
|
|
36902
|
-
let usedLabel = modelLabel;
|
|
36903
|
-
const fallbackModels = ["latest", "3.1-flash"];
|
|
36904
|
-
if (!result.success && options.model && fallbackModels.includes(options.model)) {
|
|
36905
|
-
spinner2.text = `${source_default.dim(result.error || "Failed")} \u2014 retrying with Nano Banana (flash)...`;
|
|
36906
|
-
result = await gemini.generateImage(prompt3, {
|
|
36907
|
-
model: "flash",
|
|
36908
|
-
aspectRatio: options.ratio
|
|
36909
|
-
});
|
|
36910
|
-
usedLabel = "Nano Banana (fallback)";
|
|
36911
|
-
}
|
|
36912
37113
|
if (!result.success || !result.images) {
|
|
36913
37114
|
spinner2.fail(result.error || "Image generation failed");
|
|
36914
37115
|
exitWithError(apiError(result.error || "Image generation failed", true));
|
|
@@ -36921,16 +37122,17 @@ Examples:
|
|
|
36921
37122
|
if (outputPath && result.images.length > 0) {
|
|
36922
37123
|
const img = result.images[0];
|
|
36923
37124
|
const buffer = Buffer.from(img.base64, "base64");
|
|
36924
|
-
await
|
|
36925
|
-
await
|
|
37125
|
+
await mkdir13(dirname8(outputPath), { recursive: true });
|
|
37126
|
+
await writeImageFile(outputPath, buffer);
|
|
36926
37127
|
}
|
|
36927
37128
|
outputSuccess({
|
|
36928
37129
|
command: "generate image",
|
|
36929
37130
|
startedAt,
|
|
36930
|
-
warnings:
|
|
37131
|
+
warnings: [],
|
|
36931
37132
|
data: {
|
|
36932
37133
|
provider: "gemini",
|
|
36933
37134
|
model: usedLabel,
|
|
37135
|
+
modelId: result.model,
|
|
36934
37136
|
images: result.images.map((img) => ({
|
|
36935
37137
|
mimeType: img.mimeType
|
|
36936
37138
|
})),
|
|
@@ -36954,8 +37156,8 @@ Examples:
|
|
|
36954
37156
|
const img = result.images[0];
|
|
36955
37157
|
const buffer = Buffer.from(img.base64, "base64");
|
|
36956
37158
|
const outputPath = resolve27(process.cwd(), options.output);
|
|
36957
|
-
await
|
|
36958
|
-
await
|
|
37159
|
+
await mkdir13(dirname8(outputPath), { recursive: true });
|
|
37160
|
+
await writeImageFile(outputPath, buffer);
|
|
36959
37161
|
saveSpinner.succeed(source_default.green(`Saved to: ${outputPath}`));
|
|
36960
37162
|
} catch (err) {
|
|
36961
37163
|
saveSpinner.fail(
|
|
@@ -36993,6 +37195,7 @@ Examples:
|
|
|
36993
37195
|
options.ratio = "1:1";
|
|
36994
37196
|
}
|
|
36995
37197
|
const result = await grok.generateImage(prompt3, {
|
|
37198
|
+
...resolveGrokImageModel(options.model),
|
|
36996
37199
|
aspectRatio: options.ratio || "1:1",
|
|
36997
37200
|
n: parseInt(options.count)
|
|
36998
37201
|
});
|
|
@@ -37014,14 +37217,15 @@ Examples:
|
|
|
37014
37217
|
} else {
|
|
37015
37218
|
throw new Error("No image data available");
|
|
37016
37219
|
}
|
|
37017
|
-
await
|
|
37018
|
-
await
|
|
37220
|
+
await mkdir13(dirname8(outputPath), { recursive: true });
|
|
37221
|
+
await writeImageFile(outputPath, buffer);
|
|
37019
37222
|
}
|
|
37020
37223
|
outputSuccess({
|
|
37021
37224
|
command: "generate image",
|
|
37022
37225
|
startedAt,
|
|
37023
37226
|
data: {
|
|
37024
37227
|
provider: "grok",
|
|
37228
|
+
modelId: resolveGrokImageModel(options.model).model,
|
|
37025
37229
|
images: result.images.map((img) => ({ url: img.url })),
|
|
37026
37230
|
outputPath
|
|
37027
37231
|
}
|
|
@@ -37055,8 +37259,8 @@ Examples:
|
|
|
37055
37259
|
throw new Error("No image data available");
|
|
37056
37260
|
}
|
|
37057
37261
|
const outputPath = resolve27(process.cwd(), options.output);
|
|
37058
|
-
await
|
|
37059
|
-
await
|
|
37262
|
+
await mkdir13(dirname8(outputPath), { recursive: true });
|
|
37263
|
+
await writeImageFile(outputPath, buffer);
|
|
37060
37264
|
saveSpinner.succeed(source_default.green(`Saved to: ${outputPath}`));
|
|
37061
37265
|
} catch (err) {
|
|
37062
37266
|
saveSpinner.fail(
|
|
@@ -37067,7 +37271,7 @@ Examples:
|
|
|
37067
37271
|
} else if (provider === "runway") {
|
|
37068
37272
|
const { spawn: spawn4 } = await import("child_process");
|
|
37069
37273
|
const __filename2 = fileURLToPath(import.meta.url);
|
|
37070
|
-
const __dirname2 =
|
|
37274
|
+
const __dirname2 = dirname8(__filename2);
|
|
37071
37275
|
const scriptPath = resolve27(
|
|
37072
37276
|
__dirname2,
|
|
37073
37277
|
"../../../../.claude/skills/runway-video/scripts/image.py"
|
|
@@ -37138,6 +37342,7 @@ var init_image = __esm({
|
|
|
37138
37342
|
init_validate();
|
|
37139
37343
|
init_provider_resolver();
|
|
37140
37344
|
init_openai_image2();
|
|
37345
|
+
init_image_file();
|
|
37141
37346
|
}
|
|
37142
37347
|
});
|
|
37143
37348
|
|
|
@@ -38086,11 +38291,11 @@ var init_dist3 = __esm({
|
|
|
38086
38291
|
|
|
38087
38292
|
// src/commands/generate/video.ts
|
|
38088
38293
|
import { resolve as resolve28 } from "node:path";
|
|
38089
|
-
import { readFile as readFile18, writeFile as
|
|
38294
|
+
import { readFile as readFile18, writeFile as writeFile24 } from "node:fs/promises";
|
|
38090
38295
|
function registerVideoCommand(parent) {
|
|
38091
38296
|
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(
|
|
38092
38297
|
"-p, --provider <provider>",
|
|
38093
|
-
"Provider: seedance (ByteDance Seedance 2.0 via fal.ai), grok, kling, runway,
|
|
38298
|
+
"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."
|
|
38094
38299
|
).option(
|
|
38095
38300
|
"-k, --api-key <key>",
|
|
38096
38301
|
"API key (or set FAL_API_KEY / XAI_API_KEY / RUNWAY_API_SECRET / KLING_API_KEY / GOOGLE_API_KEY env)"
|
|
@@ -38103,12 +38308,12 @@ function registerVideoCommand(parent) {
|
|
|
38103
38308
|
"Aspect ratio: 16:9, 9:16, or 1:1 (auto-detected from image if omitted)"
|
|
38104
38309
|
).option("--seed <number>", "Random seed for reproducibility (Runway only)").option("--mode <mode>", "Generation mode: std or pro (Kling only)", "std").option(
|
|
38105
38310
|
"--seedance-model <model>",
|
|
38106
|
-
"Seedance variant: quality
|
|
38311
|
+
"Seedance variant: quality (2.0), fast, or 2.5 (fal.ai only)",
|
|
38107
38312
|
"quality"
|
|
38108
|
-
).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(
|
|
38313
|
+
).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(
|
|
38109
38314
|
"--ref-images <paths...>",
|
|
38110
38315
|
"Reference images for Seedance reference-to-video or Veo character consistency"
|
|
38111
|
-
).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.
|
|
38316
|
+
).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(
|
|
38112
38317
|
"--runway-model <model>",
|
|
38113
38318
|
"Runway model: gen4.5 (default, text+image-to-video), gen4_turbo (image-to-video only)",
|
|
38114
38319
|
"gen4.5"
|
|
@@ -38169,7 +38374,7 @@ Examples:
|
|
|
38169
38374
|
exitWithError(
|
|
38170
38375
|
usageError(
|
|
38171
38376
|
`Invalid provider: ${provider}`,
|
|
38172
|
-
"Available providers: seedance, grok, kling, runway,
|
|
38377
|
+
"Available providers: seedance, grok, kling, runway, omni, veo. `fal` is a deprecated alias for seedance."
|
|
38173
38378
|
)
|
|
38174
38379
|
);
|
|
38175
38380
|
}
|
|
@@ -38237,13 +38442,7 @@ Examples:
|
|
|
38237
38442
|
options.ratio = "16:9";
|
|
38238
38443
|
}
|
|
38239
38444
|
if (options.dryRun) {
|
|
38240
|
-
const costUsd = provider === "seedance" || provider === "fal" ?
|
|
38241
|
-
durationSec: Number(options.duration) || 5,
|
|
38242
|
-
resolution: options.resolution,
|
|
38243
|
-
aspectRatio: options.ratio,
|
|
38244
|
-
fast: options.seedanceModel === "fast",
|
|
38245
|
-
hasVideoReference: Boolean(options.refVideos)
|
|
38246
|
-
}) : void 0;
|
|
38445
|
+
const costUsd = provider === "seedance" || provider === "fal" ? realRunCost(provider, options).costUsd : void 0;
|
|
38247
38446
|
outputSuccess({
|
|
38248
38447
|
command: "generate video",
|
|
38249
38448
|
startedAt,
|
|
@@ -38261,6 +38460,8 @@ Examples:
|
|
|
38261
38460
|
resolution: options.resolution,
|
|
38262
38461
|
veoModel: options.veoModel,
|
|
38263
38462
|
seedanceModel: options.seedanceModel,
|
|
38463
|
+
grokModel: options.grokModel,
|
|
38464
|
+
klingModel: options.klingModel,
|
|
38264
38465
|
refImages: options.refImages,
|
|
38265
38466
|
refVideos: options.refVideos,
|
|
38266
38467
|
refAudio: options.refAudio,
|
|
@@ -38282,7 +38483,7 @@ Examples:
|
|
|
38282
38483
|
runway: "Runway",
|
|
38283
38484
|
kling: "Kling",
|
|
38284
38485
|
veo: "Veo",
|
|
38285
|
-
omni: "Gemini Omni
|
|
38486
|
+
omni: "Gemini Omni 1.1 Flash",
|
|
38286
38487
|
grok: "Grok",
|
|
38287
38488
|
seedance: "Seedance 2.0 via fal.ai"
|
|
38288
38489
|
};
|
|
@@ -38381,6 +38582,7 @@ Examples:
|
|
|
38381
38582
|
}
|
|
38382
38583
|
result = await kling.generateVideo(prompt3, {
|
|
38383
38584
|
prompt: prompt3,
|
|
38585
|
+
model: resolveKlingModel(options.klingModel),
|
|
38384
38586
|
referenceImage: klingImage,
|
|
38385
38587
|
duration: parseInt(options.duration),
|
|
38386
38588
|
aspectRatio: options.ratio,
|
|
@@ -38430,12 +38632,7 @@ Examples:
|
|
|
38430
38632
|
} else if (provider === "veo") {
|
|
38431
38633
|
const gemini = new GeminiProvider();
|
|
38432
38634
|
await gemini.initialize({ apiKey });
|
|
38433
|
-
const
|
|
38434
|
-
"3.0": "veo-3.0-generate-preview",
|
|
38435
|
-
"3.1": "veo-3.1-generate-preview",
|
|
38436
|
-
"3.1-fast": "veo-3.1-fast-generate-preview"
|
|
38437
|
-
};
|
|
38438
|
-
const veoModel = veoModelMap[options.veoModel] || "veo-3.1-fast-generate-preview";
|
|
38635
|
+
const veoModel = resolveVeoModel(options.veoModel);
|
|
38439
38636
|
const veoDuration = parseInt(options.duration) <= 6 ? 6 : 8;
|
|
38440
38637
|
let lastFrame;
|
|
38441
38638
|
if (options.lastFrame) {
|
|
@@ -38509,9 +38706,12 @@ Examples:
|
|
|
38509
38706
|
await grok.initialize({ apiKey });
|
|
38510
38707
|
result = await grok.generateVideo(prompt3, {
|
|
38511
38708
|
prompt: prompt3,
|
|
38709
|
+
model: resolveGrokVideoModel(options.grokModel),
|
|
38512
38710
|
referenceImage,
|
|
38513
38711
|
duration: parseInt(options.duration),
|
|
38514
|
-
aspectRatio: options.ratio
|
|
38712
|
+
aspectRatio: options.ratio,
|
|
38713
|
+
resolution: options.resolution,
|
|
38714
|
+
generateAudio: options.generateAudio
|
|
38515
38715
|
});
|
|
38516
38716
|
if (result.status === "failed") {
|
|
38517
38717
|
spinner2.fail(result.error || "Failed to start generation");
|
|
@@ -38601,9 +38801,8 @@ Examples:
|
|
|
38601
38801
|
exitWithError(apiError(message, true));
|
|
38602
38802
|
}
|
|
38603
38803
|
}
|
|
38604
|
-
|
|
38605
|
-
|
|
38606
|
-
const falModel = seedanceModel === "fast" || seedanceModel === "seedance-2.0-fast" ? "seedance-2.0-fast" : "seedance-2.0";
|
|
38804
|
+
const falModel = resolveSeedanceVariant(options.seedanceModel);
|
|
38805
|
+
spinner2.text = `Generating video with fal.ai ${falModel} (this may take 1-3 minutes)...`;
|
|
38607
38806
|
result = await fal.generateVideo(prompt3, {
|
|
38608
38807
|
prompt: prompt3,
|
|
38609
38808
|
referenceImage: seedanceReferences.length > 0 ? void 0 : falImage,
|
|
@@ -38620,11 +38819,20 @@ Examples:
|
|
|
38620
38819
|
} else if (provider === "omni") {
|
|
38621
38820
|
const omni = new OmniProvider();
|
|
38622
38821
|
await omni.initialize({ apiKey });
|
|
38623
|
-
spinner2.text = "Generating video with Gemini Omni
|
|
38822
|
+
spinner2.text = "Generating video with Gemini Omni 1.1 Flash...";
|
|
38823
|
+
let lastFrame;
|
|
38824
|
+
if (options.lastFrame) {
|
|
38825
|
+
const lastFramePath = resolve28(process.cwd(), options.lastFrame);
|
|
38826
|
+
const ext = options.lastFrame.toLowerCase().split(".").pop();
|
|
38827
|
+
const mimeType = ext === "jpg" || ext === "jpeg" ? "image/jpeg" : `image/${ext || "png"}`;
|
|
38828
|
+
lastFrame = `data:${mimeType};base64,${(await readFile18(lastFramePath)).toString("base64")}`;
|
|
38829
|
+
}
|
|
38624
38830
|
result = await omni.generateVideo(prompt3, {
|
|
38625
38831
|
prompt: prompt3,
|
|
38626
38832
|
referenceImage,
|
|
38627
|
-
|
|
38833
|
+
lastFrame,
|
|
38834
|
+
aspectRatio: options.ratio,
|
|
38835
|
+
resolution: options.resolution
|
|
38628
38836
|
});
|
|
38629
38837
|
finalResult = result;
|
|
38630
38838
|
}
|
|
@@ -38638,14 +38846,14 @@ Examples:
|
|
|
38638
38846
|
if (options.output && finalResult.videoUrl) {
|
|
38639
38847
|
const buffer = await downloadVideo(finalResult.videoUrl, apiKey);
|
|
38640
38848
|
outputPath = resolve28(process.cwd(), options.output);
|
|
38641
|
-
await
|
|
38849
|
+
await writeFile24(outputPath, buffer);
|
|
38642
38850
|
}
|
|
38643
38851
|
const cost = realRunCost(provider, options);
|
|
38644
38852
|
outputSuccess({
|
|
38645
38853
|
command: "generate video",
|
|
38646
38854
|
startedAt,
|
|
38647
38855
|
costUsd: cost.costUsd,
|
|
38648
|
-
warnings: cost.warnings,
|
|
38856
|
+
warnings: provider === "veo" ? [VEO_SHUTDOWN_WARNING, ...cost.warnings] : cost.warnings,
|
|
38649
38857
|
data: {
|
|
38650
38858
|
provider,
|
|
38651
38859
|
taskId: result?.id,
|
|
@@ -38657,6 +38865,9 @@ Examples:
|
|
|
38657
38865
|
return;
|
|
38658
38866
|
}
|
|
38659
38867
|
console.log();
|
|
38868
|
+
if (provider === "veo") {
|
|
38869
|
+
console.log(source_default.yellow(VEO_SHUTDOWN_WARNING));
|
|
38870
|
+
}
|
|
38660
38871
|
if (finalResult.videoUrl) {
|
|
38661
38872
|
console.log(`Video URL: ${finalResult.videoUrl}`);
|
|
38662
38873
|
}
|
|
@@ -38669,7 +38880,7 @@ Examples:
|
|
|
38669
38880
|
try {
|
|
38670
38881
|
const buffer = await downloadVideo(finalResult.videoUrl, apiKey);
|
|
38671
38882
|
const outputPath = resolve28(process.cwd(), options.output);
|
|
38672
|
-
await
|
|
38883
|
+
await writeFile24(outputPath, buffer);
|
|
38673
38884
|
downloadSpinner.succeed(source_default.green(`Saved to: ${outputPath}`));
|
|
38674
38885
|
} catch (err) {
|
|
38675
38886
|
downloadSpinner.fail(
|
|
@@ -38684,12 +38895,14 @@ Examples:
|
|
|
38684
38895
|
}
|
|
38685
38896
|
function realRunCost(provider, options) {
|
|
38686
38897
|
if (provider === "seedance" || provider === "fal") {
|
|
38898
|
+
const variant = resolveSeedanceVariant(options.seedanceModel);
|
|
38687
38899
|
return {
|
|
38688
38900
|
costUsd: estimateSeedanceVideoCostUsd({
|
|
38689
38901
|
durationSec: Number(options.duration) || 5,
|
|
38690
38902
|
resolution: options.resolution,
|
|
38691
38903
|
aspectRatio: options.ratio,
|
|
38692
|
-
fast:
|
|
38904
|
+
fast: variant === "seedance-2.0-fast",
|
|
38905
|
+
v25: variant === "seedance-2.5",
|
|
38693
38906
|
hasVideoReference: Boolean(options.refVideos)
|
|
38694
38907
|
}),
|
|
38695
38908
|
warnings: []
|
|
@@ -38779,6 +38992,7 @@ function printVideoStarted(providerLabel, taskId, taskType) {
|
|
|
38779
38992
|
console.log(`Task ID: ${source_default.bold(taskId)}`);
|
|
38780
38993
|
if (taskType) console.log(`Type: ${taskType}`);
|
|
38781
38994
|
}
|
|
38995
|
+
var VEO_SHUTDOWN_WARNING;
|
|
38782
38996
|
var init_video = __esm({
|
|
38783
38997
|
"src/commands/generate/video.ts"() {
|
|
38784
38998
|
"use strict";
|
|
@@ -38794,6 +39008,7 @@ var init_video = __esm({
|
|
|
38794
39008
|
init_upload_host();
|
|
38795
39009
|
init_ai_helpers();
|
|
38796
39010
|
init_status_jobs();
|
|
39011
|
+
VEO_SHUTDOWN_WARNING = "Veo 3.1 preview models shut down on 2026-10-22. Use `-p omni` (Gemini Omni 1.1 Flash) instead.";
|
|
38797
39012
|
}
|
|
38798
39013
|
});
|
|
38799
39014
|
|
|
@@ -38813,7 +39028,7 @@ var init_sanitize = __esm({
|
|
|
38813
39028
|
|
|
38814
39029
|
// src/commands/generate/storyboard.ts
|
|
38815
39030
|
import { resolve as resolve29 } from "node:path";
|
|
38816
|
-
import { writeFile as
|
|
39031
|
+
import { writeFile as writeFile25 } from "node:fs/promises";
|
|
38817
39032
|
async function executeStoryboard(options) {
|
|
38818
39033
|
const { content, duration, creativity = "low", output, apiKey } = options;
|
|
38819
39034
|
try {
|
|
@@ -38832,7 +39047,7 @@ async function executeStoryboard(options) {
|
|
|
38832
39047
|
let outputPath;
|
|
38833
39048
|
if (output) {
|
|
38834
39049
|
outputPath = resolve29(process.cwd(), output);
|
|
38835
|
-
await
|
|
39050
|
+
await writeFile25(outputPath, JSON.stringify(segments, null, 2), "utf-8");
|
|
38836
39051
|
}
|
|
38837
39052
|
return { success: true, segments, segmentCount: segments.length, outputPath };
|
|
38838
39053
|
} catch (error) {
|
|
@@ -39175,7 +39390,7 @@ var init_silence_cut = __esm({
|
|
|
39175
39390
|
|
|
39176
39391
|
// src/commands/_shared/edit/jump-cut.ts
|
|
39177
39392
|
import { existsSync as existsSync20 } from "node:fs";
|
|
39178
|
-
import { readFile as readFile20, writeFile as
|
|
39393
|
+
import { readFile as readFile20, writeFile as writeFile26, mkdir as mkdir14 } from "node:fs/promises";
|
|
39179
39394
|
import { join as join13 } from "node:path";
|
|
39180
39395
|
async function transcribeWithWords(audioPath, apiKey, language) {
|
|
39181
39396
|
const audioBuffer = await readFile20(audioPath);
|
|
@@ -39255,7 +39470,7 @@ async function executeJumpCut(options) {
|
|
|
39255
39470
|
}
|
|
39256
39471
|
try {
|
|
39257
39472
|
const tmpDir = `/tmp/vibe_jumpcut_${Date.now()}`;
|
|
39258
|
-
await
|
|
39473
|
+
await mkdir14(tmpDir, { recursive: true });
|
|
39259
39474
|
const audioPath = join13(tmpDir, "audio.wav");
|
|
39260
39475
|
try {
|
|
39261
39476
|
await execSafe(
|
|
@@ -39334,7 +39549,7 @@ async function executeJumpCut(options) {
|
|
|
39334
39549
|
}
|
|
39335
39550
|
const concatList = segmentPaths.map((p) => `file '${p}'`).join("\n");
|
|
39336
39551
|
const listPath = join13(tmpDir, "concat.txt");
|
|
39337
|
-
await
|
|
39552
|
+
await writeFile26(listPath, concatList);
|
|
39338
39553
|
await execSafe(
|
|
39339
39554
|
"ffmpeg",
|
|
39340
39555
|
[
|
|
@@ -39361,8 +39576,8 @@ async function executeJumpCut(options) {
|
|
|
39361
39576
|
};
|
|
39362
39577
|
} finally {
|
|
39363
39578
|
try {
|
|
39364
|
-
const { rm:
|
|
39365
|
-
await
|
|
39579
|
+
const { rm: rm8 } = await import("node:fs/promises");
|
|
39580
|
+
await rm8(tmpDir, { recursive: true, force: true });
|
|
39366
39581
|
} catch {
|
|
39367
39582
|
}
|
|
39368
39583
|
}
|
|
@@ -39524,8 +39739,8 @@ var init_helpers = __esm({
|
|
|
39524
39739
|
|
|
39525
39740
|
// src/commands/_shared/edit/caption.ts
|
|
39526
39741
|
import { existsSync as existsSync21 } from "node:fs";
|
|
39527
|
-
import { readFile as readFile21, writeFile as
|
|
39528
|
-
import { dirname as
|
|
39742
|
+
import { readFile as readFile21, writeFile as writeFile27, mkdir as mkdir15 } from "node:fs/promises";
|
|
39743
|
+
import { dirname as dirname9, basename as basename6, extname as extname5, join as join14 } from "node:path";
|
|
39529
39744
|
function getCaptionForceStyle(style, fontSize, fontColor, position) {
|
|
39530
39745
|
const alignment = position === "top" ? 8 : position === "center" ? 5 : 2;
|
|
39531
39746
|
const marginV = position === "center" ? 0 : 30;
|
|
@@ -39571,7 +39786,7 @@ async function executeCaption(options) {
|
|
|
39571
39786
|
}
|
|
39572
39787
|
try {
|
|
39573
39788
|
const tmpDir = `/tmp/vibe_caption_${Date.now()}`;
|
|
39574
|
-
await
|
|
39789
|
+
await mkdir15(tmpDir, { recursive: true });
|
|
39575
39790
|
const audioPath = join14(tmpDir, "audio.wav");
|
|
39576
39791
|
const srtPath = join14(tmpDir, "captions.srt");
|
|
39577
39792
|
try {
|
|
@@ -39604,7 +39819,7 @@ async function executeCaption(options) {
|
|
|
39604
39819
|
};
|
|
39605
39820
|
}
|
|
39606
39821
|
const srtContent = formatSRT(transcriptResult.segments);
|
|
39607
|
-
await
|
|
39822
|
+
await writeFile27(srtPath, srtContent);
|
|
39608
39823
|
const { width, height } = await getVideoResolution(videoPath);
|
|
39609
39824
|
const fontSize = customFontSize || Math.round(height / 18);
|
|
39610
39825
|
let hasSubtitles = false;
|
|
@@ -39641,12 +39856,12 @@ async function executeCaption(options) {
|
|
|
39641
39856
|
} = await Promise.resolve().then(() => (init_remotion(), remotion_exports));
|
|
39642
39857
|
const remotionErr = await ensureRemotionInstalled2();
|
|
39643
39858
|
if (remotionErr) {
|
|
39644
|
-
const outputDir2 =
|
|
39859
|
+
const outputDir2 = dirname9(outputPath);
|
|
39645
39860
|
const outputSrtPath2 = join14(
|
|
39646
39861
|
outputDir2,
|
|
39647
|
-
basename6(outputPath,
|
|
39862
|
+
basename6(outputPath, extname5(outputPath)) + ".srt"
|
|
39648
39863
|
);
|
|
39649
|
-
await
|
|
39864
|
+
await writeFile27(outputSrtPath2, srtContent);
|
|
39650
39865
|
return { success: false, error: `${remotionErr}
|
|
39651
39866
|
SRT saved to: ${outputSrtPath2}` };
|
|
39652
39867
|
}
|
|
@@ -39680,12 +39895,12 @@ SRT saved to: ${outputSrtPath2}` };
|
|
|
39680
39895
|
outputPath
|
|
39681
39896
|
});
|
|
39682
39897
|
if (!renderResult.success) {
|
|
39683
|
-
const outputDir2 =
|
|
39898
|
+
const outputDir2 = dirname9(outputPath);
|
|
39684
39899
|
const outputSrtPath2 = join14(
|
|
39685
39900
|
outputDir2,
|
|
39686
|
-
basename6(outputPath,
|
|
39901
|
+
basename6(outputPath, extname5(outputPath)) + ".srt"
|
|
39687
39902
|
);
|
|
39688
|
-
await
|
|
39903
|
+
await writeFile27(outputSrtPath2, srtContent);
|
|
39689
39904
|
return {
|
|
39690
39905
|
success: false,
|
|
39691
39906
|
error: `${renderResult.error}
|
|
@@ -39693,12 +39908,12 @@ SRT saved to: ${outputSrtPath2}`
|
|
|
39693
39908
|
};
|
|
39694
39909
|
}
|
|
39695
39910
|
}
|
|
39696
|
-
const outputDir =
|
|
39911
|
+
const outputDir = dirname9(outputPath);
|
|
39697
39912
|
const outputSrtPath = join14(
|
|
39698
39913
|
outputDir,
|
|
39699
|
-
basename6(outputPath,
|
|
39914
|
+
basename6(outputPath, extname5(outputPath)) + ".srt"
|
|
39700
39915
|
);
|
|
39701
|
-
await
|
|
39916
|
+
await writeFile27(outputSrtPath, srtContent);
|
|
39702
39917
|
return {
|
|
39703
39918
|
success: true,
|
|
39704
39919
|
outputPath,
|
|
@@ -39707,8 +39922,8 @@ SRT saved to: ${outputSrtPath2}`
|
|
|
39707
39922
|
};
|
|
39708
39923
|
} finally {
|
|
39709
39924
|
try {
|
|
39710
|
-
const { rm:
|
|
39711
|
-
await
|
|
39925
|
+
const { rm: rm8 } = await import("node:fs/promises");
|
|
39926
|
+
await rm8(tmpDir, { recursive: true, force: true });
|
|
39712
39927
|
} catch {
|
|
39713
39928
|
}
|
|
39714
39929
|
}
|
|
@@ -39869,7 +40084,7 @@ var init_fade = __esm({
|
|
|
39869
40084
|
|
|
39870
40085
|
// src/commands/_shared/edit/translate-srt.ts
|
|
39871
40086
|
import { existsSync as existsSync24 } from "node:fs";
|
|
39872
|
-
import { readFile as readFile22, writeFile as
|
|
40087
|
+
import { readFile as readFile22, writeFile as writeFile28 } from "node:fs/promises";
|
|
39873
40088
|
async function executeTranslateSrt(options) {
|
|
39874
40089
|
const {
|
|
39875
40090
|
srtPath,
|
|
@@ -39912,15 +40127,14 @@ ${textsToTranslate}`;
|
|
|
39912
40127
|
Authorization: `Bearer ${openaiKey}`
|
|
39913
40128
|
},
|
|
39914
40129
|
body: JSON.stringify({
|
|
39915
|
-
model: "gpt-5-mini",
|
|
39916
|
-
messages: [{ role: "user", content: translatePrompt }]
|
|
39917
|
-
temperature: 0.3
|
|
40130
|
+
model: "gpt-5.4-mini",
|
|
40131
|
+
messages: [{ role: "user", content: translatePrompt }]
|
|
39918
40132
|
})
|
|
39919
40133
|
});
|
|
39920
40134
|
if (!response.ok) {
|
|
39921
40135
|
return {
|
|
39922
40136
|
success: false,
|
|
39923
|
-
error: `OpenAI API error: ${response.status} ${response.statusText}`
|
|
40137
|
+
error: `OpenAI API error: ${response.status} ${response.statusText}: ${await response.text()}`
|
|
39924
40138
|
};
|
|
39925
40139
|
}
|
|
39926
40140
|
const data = await response.json();
|
|
@@ -39941,15 +40155,15 @@ ${textsToTranslate}`;
|
|
|
39941
40155
|
"anthropic-version": "2023-06-01"
|
|
39942
40156
|
},
|
|
39943
40157
|
body: JSON.stringify({
|
|
39944
|
-
model: "claude-sonnet-
|
|
39945
|
-
max_tokens:
|
|
40158
|
+
model: "claude-sonnet-5-5",
|
|
40159
|
+
max_tokens: 16e3,
|
|
39946
40160
|
messages: [{ role: "user", content: translatePrompt }]
|
|
39947
40161
|
})
|
|
39948
40162
|
});
|
|
39949
40163
|
if (!response.ok) {
|
|
39950
40164
|
return {
|
|
39951
40165
|
success: false,
|
|
39952
|
-
error: `Claude API error: ${response.status} ${response.statusText}`
|
|
40166
|
+
error: `Claude API error: ${response.status} ${response.statusText}: ${await response.text()}`
|
|
39953
40167
|
};
|
|
39954
40168
|
}
|
|
39955
40169
|
const data = await response.json();
|
|
@@ -39973,7 +40187,7 @@ ${textsToTranslate}`;
|
|
|
39973
40187
|
}
|
|
39974
40188
|
}
|
|
39975
40189
|
const translatedSrt = formatSRT(translatedSegments);
|
|
39976
|
-
await
|
|
40190
|
+
await writeFile28(outputPath, translatedSrt);
|
|
39977
40191
|
return {
|
|
39978
40192
|
success: true,
|
|
39979
40193
|
outputPath,
|
|
@@ -40225,7 +40439,7 @@ var init_ai_edit = __esm({
|
|
|
40225
40439
|
});
|
|
40226
40440
|
|
|
40227
40441
|
// src/commands/ai-edit-cli.ts
|
|
40228
|
-
import { resolve as resolve31, extname as
|
|
40442
|
+
import { resolve as resolve31, extname as extname6, basename as basename7 } from "node:path";
|
|
40229
40443
|
import { existsSync as existsSync26 } from "node:fs";
|
|
40230
40444
|
function registerEditCommands(aiCommand) {
|
|
40231
40445
|
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", `
|
|
@@ -40249,7 +40463,7 @@ No API key needed (FFmpeg only). Use --use-gemini for smart detection (requires
|
|
|
40249
40463
|
if (!commandExists("ffmpeg")) {
|
|
40250
40464
|
exitWithError(generalError("FFmpeg not found. Install with: brew install ffmpeg (macOS) or apt install ffmpeg (Linux). Run `vibe doctor` for details."));
|
|
40251
40465
|
}
|
|
40252
|
-
const ext =
|
|
40466
|
+
const ext = extname6(videoPath);
|
|
40253
40467
|
const name = basename7(videoPath, ext);
|
|
40254
40468
|
const outputPath = options.output || `${name}-cut${ext}`;
|
|
40255
40469
|
const useGemini = options.useGemini || false;
|
|
@@ -40379,7 +40593,7 @@ Requires: OPENAI_API_KEY (Whisper transcription) + FFmpeg`).action(async (videoP
|
|
|
40379
40593
|
if (!apiKey) {
|
|
40380
40594
|
exitWithError(authError("OPENAI_API_KEY", "OpenAI"));
|
|
40381
40595
|
}
|
|
40382
|
-
const ext =
|
|
40596
|
+
const ext = extname6(videoPath);
|
|
40383
40597
|
const name = basename7(videoPath, ext);
|
|
40384
40598
|
const outputPath = options.output || `${name}-captioned${ext}`;
|
|
40385
40599
|
const spinner2 = ora("Starting caption process...").start();
|
|
@@ -40453,7 +40667,7 @@ Requires: OPENAI_API_KEY (Whisper transcription) + FFmpeg`).action(async (videoP
|
|
|
40453
40667
|
});
|
|
40454
40668
|
return;
|
|
40455
40669
|
}
|
|
40456
|
-
const ext =
|
|
40670
|
+
const ext = extname6(inputPath);
|
|
40457
40671
|
const name = basename7(inputPath, ext);
|
|
40458
40672
|
const outputPath = options.output || `${name}-denoised${ext}`;
|
|
40459
40673
|
const spinner2 = ora("Applying noise reduction...").start();
|
|
@@ -40521,7 +40735,7 @@ Requires: OPENAI_API_KEY (Whisper transcription) + FFmpeg`).action(async (videoP
|
|
|
40521
40735
|
});
|
|
40522
40736
|
return;
|
|
40523
40737
|
}
|
|
40524
|
-
const ext =
|
|
40738
|
+
const ext = extname6(videoPath);
|
|
40525
40739
|
const name = basename7(videoPath, ext);
|
|
40526
40740
|
const outputPath = options.output || `${name}-faded${ext}`;
|
|
40527
40741
|
const spinner2 = ora("Applying fade effects...").start();
|
|
@@ -40599,7 +40813,7 @@ Requires: OPENAI_API_KEY (Whisper transcription) + FFmpeg`).action(async (videoP
|
|
|
40599
40813
|
if (!apiKey) {
|
|
40600
40814
|
exitWithError(authError(envKey, providerName));
|
|
40601
40815
|
}
|
|
40602
|
-
const ext =
|
|
40816
|
+
const ext = extname6(srtPath);
|
|
40603
40817
|
const name = basename7(srtPath, ext);
|
|
40604
40818
|
const outputPath = options.output || `${name}-${options.target}${ext}`;
|
|
40605
40819
|
const spinner2 = ora(`Translating to ${options.target}...`).start();
|
|
@@ -40677,7 +40891,7 @@ Requires: OPENAI_API_KEY (Whisper transcription) + FFmpeg`).action(async (videoP
|
|
|
40677
40891
|
if (!apiKey) {
|
|
40678
40892
|
exitWithError(authError("OPENAI_API_KEY", "OpenAI"));
|
|
40679
40893
|
}
|
|
40680
|
-
const ext =
|
|
40894
|
+
const ext = extname6(videoPath);
|
|
40681
40895
|
const name = basename7(videoPath, ext);
|
|
40682
40896
|
const outputPath = options.output || `${name}-jumpcut${ext}`;
|
|
40683
40897
|
const fillers = options.fillers ? options.fillers.split(",").map((f) => f.trim()) : void 0;
|
|
@@ -40750,8 +40964,8 @@ var init_ai_edit_cli = __esm({
|
|
|
40750
40964
|
|
|
40751
40965
|
// src/commands/_shared/execute-fill-gaps.ts
|
|
40752
40966
|
import { existsSync as existsSync27 } from "node:fs";
|
|
40753
|
-
import { readFile as readFile23, writeFile as
|
|
40754
|
-
import { resolve as resolve32, dirname as
|
|
40967
|
+
import { readFile as readFile23, writeFile as writeFile29, mkdir as mkdir16, rename as renameFs } from "node:fs/promises";
|
|
40968
|
+
import { resolve as resolve32, dirname as dirname10 } from "node:path";
|
|
40755
40969
|
function detectVideoGaps(videoClips, totalDuration) {
|
|
40756
40970
|
const gaps = [];
|
|
40757
40971
|
const sortedClips = [...videoClips].sort((a, b) => a.startTime - b.startTime);
|
|
@@ -40961,14 +41175,14 @@ async function executeFillGaps(options) {
|
|
|
40961
41175
|
if (!kling.isConfigured()) {
|
|
40962
41176
|
return {
|
|
40963
41177
|
success: false,
|
|
40964
|
-
error: "Invalid KLING_API_KEY (
|
|
41178
|
+
error: "Invalid KLING_API_KEY (set your Kling API key, or the legacy ACCESS_KEY:SECRET_KEY pair)",
|
|
40965
41179
|
humanLines
|
|
40966
41180
|
};
|
|
40967
41181
|
}
|
|
40968
|
-
const projectDir =
|
|
41182
|
+
const projectDir = dirname10(filePath);
|
|
40969
41183
|
const footageDir = options.dir ? resolve32(process.cwd(), options.dir) : resolve32(projectDir, "footage");
|
|
40970
41184
|
if (!existsSync27(footageDir)) {
|
|
40971
|
-
await
|
|
41185
|
+
await mkdir16(footageDir, { recursive: true });
|
|
40972
41186
|
}
|
|
40973
41187
|
humanLines.push("Generating AI Videos");
|
|
40974
41188
|
const imgbbApiKey = options.imgbbApiKey || await getApiKey("IMGBB_API_KEY", "imgbb", void 0);
|
|
@@ -41033,13 +41247,13 @@ async function executeFillGaps(options) {
|
|
|
41033
41247
|
let generatedDuration = 0;
|
|
41034
41248
|
const generatedVideos = [];
|
|
41035
41249
|
const initialDuration = Math.min(10, targetDuration);
|
|
41036
|
-
const
|
|
41037
|
-
onProgress(`Generating ${
|
|
41250
|
+
const klingDuration2 = initialDuration > 5 ? "10" : "5";
|
|
41251
|
+
onProgress(`Generating ${klingDuration2}s video with Kling...`);
|
|
41038
41252
|
const prompt3 = options.prompt || "Continue the scene naturally with subtle motion";
|
|
41039
41253
|
const result = await kling.generateVideo(prompt3, {
|
|
41040
41254
|
prompt: prompt3,
|
|
41041
41255
|
referenceImage: frameUrl,
|
|
41042
|
-
duration: parseInt(
|
|
41256
|
+
duration: parseInt(klingDuration2),
|
|
41043
41257
|
aspectRatio: options.ratio || "16:9",
|
|
41044
41258
|
mode: options.mode || "std"
|
|
41045
41259
|
});
|
|
@@ -41062,8 +41276,8 @@ async function executeFillGaps(options) {
|
|
|
41062
41276
|
const videoPath = resolve32(footageDir, videoFileName);
|
|
41063
41277
|
onProgress("Downloading generated video...");
|
|
41064
41278
|
const videoBuffer = await downloadVideo(finalResult.videoUrl);
|
|
41065
|
-
await
|
|
41066
|
-
generatedDuration = finalResult.duration || parseInt(
|
|
41279
|
+
await writeFile29(videoPath, videoBuffer);
|
|
41280
|
+
generatedDuration = finalResult.duration || parseInt(klingDuration2);
|
|
41067
41281
|
generatedVideos.push(videoPath);
|
|
41068
41282
|
humanLines.push(` Generated: ${videoFileName} (${generatedDuration}s)`);
|
|
41069
41283
|
let segmentIndex = 1;
|
|
@@ -41132,11 +41346,11 @@ async function executeFillGaps(options) {
|
|
|
41132
41346
|
`gap-fill-${gap.start.toFixed(2)}-${gap.end.toFixed(2)}-seg${segmentIndex}.mp4`
|
|
41133
41347
|
);
|
|
41134
41348
|
const segVideoBuffer = await downloadVideo(segFinalResult.videoUrl);
|
|
41135
|
-
await
|
|
41349
|
+
await writeFile29(segVideoPath, segVideoBuffer);
|
|
41136
41350
|
const concatListPath = resolve32(footageDir, `concat-${gap.start.toFixed(2)}.txt`);
|
|
41137
41351
|
const concatList = generatedVideos.map((v) => `file '${v}'`).join("\n") + `
|
|
41138
41352
|
file '${segVideoPath}'`;
|
|
41139
|
-
await
|
|
41353
|
+
await writeFile29(concatListPath, concatList);
|
|
41140
41354
|
const concatOutputPath = resolve32(
|
|
41141
41355
|
footageDir,
|
|
41142
41356
|
`gap-fill-${gap.start.toFixed(2)}-${gap.end.toFixed(2)}-merged.mp4`
|
|
@@ -41194,7 +41408,7 @@ file '${segVideoPath}'`;
|
|
|
41194
41408
|
let outputPath = filePath;
|
|
41195
41409
|
if (generatedCount > 0) {
|
|
41196
41410
|
outputPath = options.output ? resolve32(process.cwd(), options.output) : filePath;
|
|
41197
|
-
await
|
|
41411
|
+
await writeFile29(outputPath, JSON.stringify(project.toJSON(), null, 2));
|
|
41198
41412
|
humanLines.push(`\u2714 Filled ${generatedCount} gap(s) with AI-generated video`);
|
|
41199
41413
|
humanLines.push(`Project saved: ${outputPath}`);
|
|
41200
41414
|
} else {
|
|
@@ -41571,7 +41785,7 @@ __export(project_builder_exports, {
|
|
|
41571
41785
|
buildTempProject: () => buildTempProject,
|
|
41572
41786
|
resolveSourceUrl: () => resolveSourceUrl
|
|
41573
41787
|
});
|
|
41574
|
-
import { mkdtemp, mkdir as
|
|
41788
|
+
import { mkdtemp, mkdir as mkdir17, copyFile as copyFile4, writeFile as writeFile30, rm as rm4, readdir as readdir4 } from "node:fs/promises";
|
|
41575
41789
|
import { existsSync as existsSync29 } from "node:fs";
|
|
41576
41790
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
41577
41791
|
import { createRequire } from "node:module";
|
|
@@ -41579,7 +41793,7 @@ import * as path from "node:path";
|
|
|
41579
41793
|
async function buildTempProject(state, projectFileDir) {
|
|
41580
41794
|
const dir = await mkdtemp(path.join(tmpdir2(), "vibeframe-hf-"));
|
|
41581
41795
|
const assetsDir = path.join(dir, "assets");
|
|
41582
|
-
await
|
|
41796
|
+
await mkdir17(assetsDir, { recursive: true });
|
|
41583
41797
|
const copied = /* @__PURE__ */ new Map();
|
|
41584
41798
|
for (const source of state.sources) {
|
|
41585
41799
|
if (copied.has(source.id)) continue;
|
|
@@ -41595,10 +41809,10 @@ async function buildTempProject(state, projectFileDir) {
|
|
|
41595
41809
|
await copyLottieRuntime(dir);
|
|
41596
41810
|
}
|
|
41597
41811
|
const html = generateCompositionHtml(state);
|
|
41598
|
-
await
|
|
41812
|
+
await writeFile30(path.join(dir, "index.html"), html, "utf-8");
|
|
41599
41813
|
return {
|
|
41600
41814
|
dir,
|
|
41601
|
-
cleanup: () =>
|
|
41815
|
+
cleanup: () => rm4(dir, { recursive: true, force: true })
|
|
41602
41816
|
};
|
|
41603
41817
|
}
|
|
41604
41818
|
async function copyLottieRuntime(tempDir) {
|
|
@@ -41609,7 +41823,7 @@ async function copyLottieRuntime(tempDir) {
|
|
|
41609
41823
|
const wasmSrc = path.join(path.dirname(webEntry), "dotlottie-player.wasm");
|
|
41610
41824
|
const vendorDir = path.join(tempDir, "vendor");
|
|
41611
41825
|
const wcDest = path.join(vendorDir, "dotlottie-wc");
|
|
41612
|
-
await
|
|
41826
|
+
await mkdir17(wcDest, { recursive: true });
|
|
41613
41827
|
for (const file of await readdir4(wcDistDir)) {
|
|
41614
41828
|
if (file.endsWith(".map") || file.endsWith(".d.ts")) continue;
|
|
41615
41829
|
await copyFile4(path.join(wcDistDir, file), path.join(wcDest, file));
|
|
@@ -41717,9 +41931,9 @@ __export(motion_overlay_exports, {
|
|
|
41717
41931
|
executeMotionOverlay: () => executeMotionOverlay,
|
|
41718
41932
|
registerMotionOverlayCommand: () => registerMotionOverlayCommand
|
|
41719
41933
|
});
|
|
41720
|
-
import { mkdir as
|
|
41934
|
+
import { mkdir as mkdir18 } from "node:fs/promises";
|
|
41721
41935
|
import { existsSync as existsSync30 } from "node:fs";
|
|
41722
|
-
import { basename as basename9, dirname as
|
|
41936
|
+
import { basename as basename9, dirname as dirname12, extname as extname7, resolve as resolve34 } from "node:path";
|
|
41723
41937
|
function normalizeUnderstand2(value) {
|
|
41724
41938
|
return value === "off" || value === "required" || value === "auto" ? value : "auto";
|
|
41725
41939
|
}
|
|
@@ -41742,7 +41956,7 @@ function assertValidRequest(options) {
|
|
|
41742
41956
|
return "Provide a motion description, or pass --asset <logo.json|logo.lottie>.";
|
|
41743
41957
|
}
|
|
41744
41958
|
if (hasAsset) {
|
|
41745
|
-
const ext =
|
|
41959
|
+
const ext = extname7(options.asset).toLowerCase();
|
|
41746
41960
|
if (ext !== ".json" && ext !== ".lottie") {
|
|
41747
41961
|
return "Lottie overlay asset must be a .json or .lottie file.";
|
|
41748
41962
|
}
|
|
@@ -41865,7 +42079,7 @@ async function executeMotionOverlay(options) {
|
|
|
41865
42079
|
const scale = Math.max(0.01, Math.min(2, numberOption(options.scale, position === "full" ? 1 : 0.25)));
|
|
41866
42080
|
const opacity = Math.max(0, Math.min(1, numberOption(options.opacity, 1)));
|
|
41867
42081
|
const loop = options.loop ?? true;
|
|
41868
|
-
await
|
|
42082
|
+
await mkdir18(dirname12(outputPath), { recursive: true });
|
|
41869
42083
|
const backend = createHyperframesBackend();
|
|
41870
42084
|
const result2 = await backend.render({
|
|
41871
42085
|
projectState: buildLottieTimelineState({
|
|
@@ -41891,7 +42105,7 @@ async function executeMotionOverlay(options) {
|
|
|
41891
42105
|
return { success: true, outputPath, provider: "lottie" };
|
|
41892
42106
|
}
|
|
41893
42107
|
const duration = options.duration ?? await ffprobeDuration(absVideo).catch(() => void 0);
|
|
41894
|
-
await
|
|
42108
|
+
await mkdir18(dirname12(outputPath), { recursive: true });
|
|
41895
42109
|
const result = await executeMotion({
|
|
41896
42110
|
description: options.description.trim(),
|
|
41897
42111
|
video: absVideo,
|
|
@@ -42019,8 +42233,8 @@ __export(edit_cmd_exports, {
|
|
|
42019
42233
|
executeSpeedRamp: () => executeSpeedRamp,
|
|
42020
42234
|
executeUpscale: () => executeUpscale
|
|
42021
42235
|
});
|
|
42022
|
-
import { resolve as resolve35, dirname as
|
|
42023
|
-
import { readFile as readFile24, writeFile as
|
|
42236
|
+
import { resolve as resolve35, dirname as dirname13 } from "node:path";
|
|
42237
|
+
import { readFile as readFile24, writeFile as writeFile31, mkdir as mkdir19 } from "node:fs/promises";
|
|
42024
42238
|
async function executeGrade(options) {
|
|
42025
42239
|
const { videoPath, style, preset, output, analyzeOnly, apiKey } = options;
|
|
42026
42240
|
try {
|
|
@@ -42213,6 +42427,7 @@ var init_edit_cmd = __esm({
|
|
|
42213
42427
|
init_output();
|
|
42214
42428
|
init_validate();
|
|
42215
42429
|
init_cost_tier();
|
|
42430
|
+
init_image_file();
|
|
42216
42431
|
editCommand = new Command("edit").alias("ed").description(
|
|
42217
42432
|
"Edit and post-process media (silence-cut, caption, grade, reframe, upscale...)"
|
|
42218
42433
|
).addHelpText(
|
|
@@ -42648,7 +42863,7 @@ Run 'vibe schema edit.<command>' for structured parameter info.
|
|
|
42648
42863
|
console.log();
|
|
42649
42864
|
if (options.keyframes) {
|
|
42650
42865
|
const keyframesPath = resolve35(process.cwd(), options.keyframes);
|
|
42651
|
-
await
|
|
42866
|
+
await writeFile31(keyframesPath, JSON.stringify(cropKeyframes, null, 2));
|
|
42652
42867
|
console.log(source_default.green(`Keyframes saved to: ${keyframesPath}`));
|
|
42653
42868
|
}
|
|
42654
42869
|
if (options.analyzeOnly) {
|
|
@@ -42672,7 +42887,7 @@ Run 'vibe schema edit.<command>' for structured parameter info.
|
|
|
42672
42887
|
exitWithError(generalError(`Reframe failed: ${msg}`));
|
|
42673
42888
|
}
|
|
42674
42889
|
});
|
|
42675
|
-
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
|
|
42890
|
+
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) => {
|
|
42676
42891
|
const startedAt = Date.now();
|
|
42677
42892
|
try {
|
|
42678
42893
|
if (args.length < 2) {
|
|
@@ -42731,14 +42946,16 @@ Run 'vibe schema edit.<command>' for structured parameter info.
|
|
|
42731
42946
|
const grok = new GrokProvider();
|
|
42732
42947
|
await grok.initialize({ apiKey });
|
|
42733
42948
|
result = await grok.editImage(imageBuffers[0], prompt3, {
|
|
42949
|
+
...resolveGrokImageModel(options.model),
|
|
42734
42950
|
aspectRatio: options.ratio
|
|
42735
42951
|
});
|
|
42736
42952
|
} else {
|
|
42737
42953
|
const editModelNames = {
|
|
42738
|
-
flash: "gemini-
|
|
42739
|
-
"3.1-flash": "gemini-3.1-flash-image
|
|
42740
|
-
latest: "gemini-3.1-flash-image
|
|
42741
|
-
|
|
42954
|
+
flash: "gemini-3.1-flash-image",
|
|
42955
|
+
"3.1-flash": "gemini-3.1-flash-image",
|
|
42956
|
+
latest: "gemini-3.1-flash-image",
|
|
42957
|
+
lite: "gemini-3.1-flash-lite-image",
|
|
42958
|
+
pro: "gemini-3-pro-image"
|
|
42742
42959
|
};
|
|
42743
42960
|
const editModelName = editModelNames[options.model] || editModelNames.flash;
|
|
42744
42961
|
spinner2.text = `Editing with ${editModelName}...`;
|
|
@@ -42749,15 +42966,6 @@ Run 'vibe schema edit.<command>' for structured parameter info.
|
|
|
42749
42966
|
aspectRatio: options.ratio,
|
|
42750
42967
|
resolution: options.size
|
|
42751
42968
|
});
|
|
42752
|
-
const fallbackModels = ["latest", "3.1-flash"];
|
|
42753
|
-
if (!result.success && fallbackModels.includes(options.model)) {
|
|
42754
|
-
spinner2.text = `${source_default.dim(result.error || `${editModelName} failed`)} \u2014 retrying with flash...`;
|
|
42755
|
-
result = await gemini.editImage(imageBuffers, prompt3, {
|
|
42756
|
-
model: "flash",
|
|
42757
|
-
aspectRatio: options.ratio,
|
|
42758
|
-
resolution: options.size
|
|
42759
|
-
});
|
|
42760
|
-
}
|
|
42761
42969
|
}
|
|
42762
42970
|
if (!result.success || !result.images || result.images.length === 0) {
|
|
42763
42971
|
spinner2.fail(result.error || "Image editing failed");
|
|
@@ -42767,14 +42975,14 @@ Run 'vibe schema edit.<command>' for structured parameter info.
|
|
|
42767
42975
|
const img = result.images[0];
|
|
42768
42976
|
const outputPath = resolve35(process.cwd(), options.output);
|
|
42769
42977
|
const saveImage = async () => {
|
|
42770
|
-
await
|
|
42978
|
+
await mkdir19(dirname13(outputPath), { recursive: true });
|
|
42771
42979
|
if (img.base64) {
|
|
42772
42980
|
const buffer = Buffer.from(img.base64, "base64");
|
|
42773
|
-
await
|
|
42981
|
+
await writeImageFile(outputPath, buffer);
|
|
42774
42982
|
} else if (img.url) {
|
|
42775
42983
|
const resp = await fetch(img.url);
|
|
42776
42984
|
const arrayBuf = await resp.arrayBuffer();
|
|
42777
|
-
await
|
|
42985
|
+
await writeImageFile(outputPath, Buffer.from(arrayBuf));
|
|
42778
42986
|
}
|
|
42779
42987
|
};
|
|
42780
42988
|
const resultModel = result.model;
|
|
@@ -42994,7 +43202,7 @@ __export(ai_analyze_exports, {
|
|
|
42994
43202
|
registerAnalyzeCommands: () => registerAnalyzeCommands
|
|
42995
43203
|
});
|
|
42996
43204
|
import { readFile as readFile25 } from "node:fs/promises";
|
|
42997
|
-
import { extname as
|
|
43205
|
+
import { extname as extname8, resolve as resolve36 } from "node:path";
|
|
42998
43206
|
import { existsSync as existsSync31 } from "node:fs";
|
|
42999
43207
|
async function executeGeminiVideo(options) {
|
|
43000
43208
|
try {
|
|
@@ -43051,7 +43259,7 @@ async function executeAnalyze(options) {
|
|
|
43051
43259
|
const isYouTube = source.includes("youtube.com") || source.includes("youtu.be");
|
|
43052
43260
|
const isImageUrl = /^https?:\/\/.+\.(png|jpg|jpeg|webp|gif)(\?.*)?$/i.test(source);
|
|
43053
43261
|
const isVideoUrl = /^https?:\/\/.+\.(mp4|mov|webm)(\?.*)?$/i.test(source);
|
|
43054
|
-
const ext =
|
|
43262
|
+
const ext = extname8(source).toLowerCase();
|
|
43055
43263
|
const imageExts = [".png", ".jpg", ".jpeg", ".webp", ".gif"];
|
|
43056
43264
|
const videoExts = [".mp4", ".mov", ".webm", ".avi", ".mkv"];
|
|
43057
43265
|
const isLocalImage = imageExts.includes(ext);
|
|
@@ -44904,8 +45112,8 @@ var init_render_inspect = __esm({
|
|
|
44904
45112
|
});
|
|
44905
45113
|
|
|
44906
45114
|
// src/commands/ai-highlights.ts
|
|
44907
|
-
import { readFile as readFile31, writeFile as
|
|
44908
|
-
import { resolve as resolve42, dirname as
|
|
45115
|
+
import { readFile as readFile31, writeFile as writeFile34, mkdir as mkdir20 } from "node:fs/promises";
|
|
45116
|
+
import { resolve as resolve42, dirname as dirname15, basename as basename13, extname as extname10 } from "node:path";
|
|
44909
45117
|
import { existsSync as existsSync36 } from "node:fs";
|
|
44910
45118
|
function filterHighlights(highlights, options) {
|
|
44911
45119
|
let filtered = highlights.filter((h) => h.confidence >= options.threshold);
|
|
@@ -44949,7 +45157,7 @@ async function executeHighlights(options) {
|
|
|
44949
45157
|
if (!existsSync36(absPath)) {
|
|
44950
45158
|
return { success: false, highlights: [], totalDuration: 0, totalHighlightDuration: 0, error: `File not found: ${absPath}` };
|
|
44951
45159
|
}
|
|
44952
|
-
const ext =
|
|
45160
|
+
const ext = extname10(absPath).toLowerCase();
|
|
44953
45161
|
const videoExtensions = [".mp4", ".mov", ".avi", ".mkv", ".webm", ".m4v"];
|
|
44954
45162
|
const isVideo = videoExtensions.includes(ext);
|
|
44955
45163
|
const targetDuration = options.duration;
|
|
@@ -45094,7 +45302,7 @@ Analyze both what is SHOWN (visual cues, actions, expressions) and what is SAID
|
|
|
45094
45302
|
};
|
|
45095
45303
|
if (options.output) {
|
|
45096
45304
|
const outputPath = resolve42(process.cwd(), options.output);
|
|
45097
|
-
await
|
|
45305
|
+
await writeFile34(outputPath, JSON.stringify({
|
|
45098
45306
|
sourceFile: absPath,
|
|
45099
45307
|
totalDuration: sourceDuration,
|
|
45100
45308
|
criteria: options.criteria || "all",
|
|
@@ -45129,7 +45337,7 @@ Analyze both what is SHOWN (visual cues, actions, expressions) and what is SAID
|
|
|
45129
45337
|
}
|
|
45130
45338
|
}
|
|
45131
45339
|
const projectPath = resolve42(process.cwd(), options.project);
|
|
45132
|
-
await
|
|
45340
|
+
await writeFile34(projectPath, JSON.stringify(project.toJSON(), null, 2), "utf-8");
|
|
45133
45341
|
extractResult.projectPath = projectPath;
|
|
45134
45342
|
}
|
|
45135
45343
|
return extractResult;
|
|
@@ -45276,9 +45484,9 @@ Analyze both VISUALS (expressions, actions, scene changes) and AUDIO (speech, re
|
|
|
45276
45484
|
}))
|
|
45277
45485
|
};
|
|
45278
45486
|
}
|
|
45279
|
-
const outputDir = options.outputDir ? resolve42(process.cwd(), options.outputDir) :
|
|
45487
|
+
const outputDir = options.outputDir ? resolve42(process.cwd(), options.outputDir) : dirname15(absPath);
|
|
45280
45488
|
if (options.outputDir && !existsSync36(outputDir)) {
|
|
45281
|
-
await
|
|
45489
|
+
await mkdir20(outputDir, { recursive: true });
|
|
45282
45490
|
}
|
|
45283
45491
|
const result = {
|
|
45284
45492
|
success: true,
|
|
@@ -45286,7 +45494,7 @@ Analyze both VISUALS (expressions, actions, scene changes) and AUDIO (speech, re
|
|
|
45286
45494
|
};
|
|
45287
45495
|
for (let i = 0; i < selectedHighlights.length; i++) {
|
|
45288
45496
|
const h = selectedHighlights[i];
|
|
45289
|
-
const baseName = basename13(absPath,
|
|
45497
|
+
const baseName = basename13(absPath, extname10(absPath));
|
|
45290
45498
|
const outputPath = resolve42(outputDir, `${baseName}-short-${i + 1}.mp4`);
|
|
45291
45499
|
const { stdout: probeOut } = await execSafe("ffprobe", [
|
|
45292
45500
|
"-v",
|
|
@@ -45385,7 +45593,7 @@ function registerHighlightsCommands(aiCommand) {
|
|
|
45385
45593
|
});
|
|
45386
45594
|
return;
|
|
45387
45595
|
}
|
|
45388
|
-
const ext =
|
|
45596
|
+
const ext = extname10(absPath).toLowerCase();
|
|
45389
45597
|
const videoExtensions = [".mp4", ".mov", ".avi", ".mkv", ".webm", ".m4v"];
|
|
45390
45598
|
const isVideo = videoExtensions.includes(ext);
|
|
45391
45599
|
console.log();
|
|
@@ -45614,7 +45822,7 @@ Analyze both what is SHOWN (visual cues, actions, expressions) and what is SAID
|
|
|
45614
45822
|
console.log();
|
|
45615
45823
|
if (options.output) {
|
|
45616
45824
|
const outputPath = resolve42(process.cwd(), options.output);
|
|
45617
|
-
await
|
|
45825
|
+
await writeFile34(outputPath, JSON.stringify(result, null, 2), "utf-8");
|
|
45618
45826
|
console.log(source_default.green(`\u{1F4BE} Saved highlights to: ${outputPath}`));
|
|
45619
45827
|
}
|
|
45620
45828
|
if (options.project) {
|
|
@@ -45644,7 +45852,7 @@ Analyze both what is SHOWN (visual cues, actions, expressions) and what is SAID
|
|
|
45644
45852
|
currentTime += highlight.duration;
|
|
45645
45853
|
}
|
|
45646
45854
|
const projectPath = resolve42(process.cwd(), options.project);
|
|
45647
|
-
await
|
|
45855
|
+
await writeFile34(projectPath, JSON.stringify(project.toJSON(), null, 2), "utf-8");
|
|
45648
45856
|
projectSpinner.succeed(source_default.green(`Created project: ${projectPath}`));
|
|
45649
45857
|
}
|
|
45650
45858
|
console.log();
|
|
@@ -45853,9 +46061,9 @@ Analyze both VISUALS (expressions, actions, scene changes) and AUDIO (speech, re
|
|
|
45853
46061
|
console.log(source_default.dim("Use without --analyze-only to generate shorts."));
|
|
45854
46062
|
return;
|
|
45855
46063
|
}
|
|
45856
|
-
const outputDir = options.outputDir ? resolve42(process.cwd(), options.outputDir) :
|
|
46064
|
+
const outputDir = options.outputDir ? resolve42(process.cwd(), options.outputDir) : dirname15(absPath);
|
|
45857
46065
|
if (options.outputDir && !existsSync36(outputDir)) {
|
|
45858
|
-
await
|
|
46066
|
+
await mkdir20(outputDir, { recursive: true });
|
|
45859
46067
|
}
|
|
45860
46068
|
for (let i = 0; i < selectedHighlights.length; i++) {
|
|
45861
46069
|
const h = selectedHighlights[i];
|
|
@@ -45863,16 +46071,16 @@ Analyze both VISUALS (expressions, actions, scene changes) and AUDIO (speech, re
|
|
|
45863
46071
|
let outputPath;
|
|
45864
46072
|
if (shortCount === 1 && options.output) {
|
|
45865
46073
|
outputPath = resolve42(process.cwd(), options.output);
|
|
45866
|
-
if (!
|
|
46074
|
+
if (!extname10(outputPath)) {
|
|
45867
46075
|
outputPath += ".mp4";
|
|
45868
46076
|
}
|
|
45869
46077
|
} else {
|
|
45870
|
-
const baseName = basename13(absPath,
|
|
46078
|
+
const baseName = basename13(absPath, extname10(absPath));
|
|
45871
46079
|
outputPath = resolve42(outputDir, `${baseName}-short-${i + 1}.mp4`);
|
|
45872
46080
|
}
|
|
45873
|
-
const parentDir =
|
|
46081
|
+
const parentDir = dirname15(outputPath);
|
|
45874
46082
|
if (!existsSync36(parentDir)) {
|
|
45875
|
-
await
|
|
46083
|
+
await mkdir20(parentDir, { recursive: true });
|
|
45876
46084
|
}
|
|
45877
46085
|
const { stdout: probeOut } = await execSafe("ffprobe", [
|
|
45878
46086
|
"-v",
|
|
@@ -45944,8 +46152,8 @@ var init_ai_highlights = __esm({
|
|
|
45944
46152
|
});
|
|
45945
46153
|
|
|
45946
46154
|
// src/commands/ai-animated-caption.ts
|
|
45947
|
-
import { resolve as resolve43, dirname as
|
|
45948
|
-
import { writeFile as
|
|
46155
|
+
import { resolve as resolve43, dirname as dirname16, basename as basename14 } from "node:path";
|
|
46156
|
+
import { writeFile as writeFile35, mkdir as mkdir21, rm as rm5 } from "node:fs/promises";
|
|
45949
46157
|
import { existsSync as existsSync37 } from "node:fs";
|
|
45950
46158
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
45951
46159
|
function groupWords(words, options = {}) {
|
|
@@ -46093,7 +46301,7 @@ async function executeAnimatedCaption(options) {
|
|
|
46093
46301
|
}
|
|
46094
46302
|
const effectiveFontSize = fontSize ?? Math.round(height * 0.04);
|
|
46095
46303
|
const tmpAudioDir = resolve43(tmpdir3(), `vf-ac-${Date.now()}`);
|
|
46096
|
-
await
|
|
46304
|
+
await mkdir21(tmpAudioDir, { recursive: true });
|
|
46097
46305
|
const audioPath = resolve43(tmpAudioDir, "audio.wav");
|
|
46098
46306
|
await execSafe("ffmpeg", [
|
|
46099
46307
|
"-y",
|
|
@@ -46110,21 +46318,21 @@ async function executeAnimatedCaption(options) {
|
|
|
46110
46318
|
], { timeout: 12e4 });
|
|
46111
46319
|
const apiKey = await getApiKey("OPENAI_API_KEY", "OpenAI");
|
|
46112
46320
|
if (!apiKey) {
|
|
46113
|
-
await
|
|
46321
|
+
await rm5(tmpAudioDir, { recursive: true, force: true }).catch(() => {
|
|
46114
46322
|
});
|
|
46115
46323
|
return { success: false, error: "OPENAI_API_KEY required for Whisper transcription. Run 'vibe setup' or set OPENAI_API_KEY in .env" };
|
|
46116
46324
|
}
|
|
46117
46325
|
const transcript = await transcribeWithWords(audioPath, apiKey, language);
|
|
46118
46326
|
if (!transcript.words || transcript.words.length === 0) {
|
|
46119
|
-
await
|
|
46327
|
+
await rm5(tmpAudioDir, { recursive: true, force: true }).catch(() => {
|
|
46120
46328
|
});
|
|
46121
46329
|
return { success: false, error: "No words detected in transcription" };
|
|
46122
46330
|
}
|
|
46123
46331
|
const groups = groupWords(transcript.words, { wordsPerGroup, maxChars });
|
|
46124
46332
|
const absOutputPath = resolve43(process.cwd(), outputPath);
|
|
46125
|
-
const outDir =
|
|
46333
|
+
const outDir = dirname16(absOutputPath);
|
|
46126
46334
|
if (!existsSync37(outDir)) {
|
|
46127
|
-
await
|
|
46335
|
+
await mkdir21(outDir, { recursive: true });
|
|
46128
46336
|
}
|
|
46129
46337
|
if (tier === "ass") {
|
|
46130
46338
|
const assContent = generateASS(
|
|
@@ -46133,7 +46341,7 @@ async function executeAnimatedCaption(options) {
|
|
|
46133
46341
|
{ highlightColor, fontSize: effectiveFontSize, position, width, height }
|
|
46134
46342
|
);
|
|
46135
46343
|
const assPath = resolve43(tmpAudioDir, "captions.ass");
|
|
46136
|
-
await
|
|
46344
|
+
await writeFile35(assPath, assContent, "utf-8");
|
|
46137
46345
|
const escapedAssPath = assPath.replace(/\\/g, "\\\\").replace(/:/g, "\\:");
|
|
46138
46346
|
await execSafe("ffmpeg", [
|
|
46139
46347
|
"-y",
|
|
@@ -46170,12 +46378,12 @@ async function executeAnimatedCaption(options) {
|
|
|
46170
46378
|
outputPath: absOutputPath
|
|
46171
46379
|
});
|
|
46172
46380
|
if (!renderResult.success) {
|
|
46173
|
-
await
|
|
46381
|
+
await rm5(tmpAudioDir, { recursive: true, force: true }).catch(() => {
|
|
46174
46382
|
});
|
|
46175
46383
|
return { success: false, error: renderResult.error };
|
|
46176
46384
|
}
|
|
46177
46385
|
}
|
|
46178
|
-
await
|
|
46386
|
+
await rm5(tmpAudioDir, { recursive: true, force: true }).catch(() => {
|
|
46179
46387
|
});
|
|
46180
46388
|
return {
|
|
46181
46389
|
success: true,
|
|
@@ -55769,7 +55977,7 @@ __export(detect_exports, {
|
|
|
55769
55977
|
executeDetectScenes: () => executeDetectScenes,
|
|
55770
55978
|
executeDetectSilence: () => executeDetectSilence
|
|
55771
55979
|
});
|
|
55772
|
-
import { readFile as readFile33, writeFile as
|
|
55980
|
+
import { readFile as readFile33, writeFile as writeFile37 } from "node:fs/promises";
|
|
55773
55981
|
import { resolve as resolve47, basename as basename18 } from "node:path";
|
|
55774
55982
|
async function executeDetectScenes(options) {
|
|
55775
55983
|
try {
|
|
@@ -55808,7 +56016,7 @@ async function executeDetectScenes(options) {
|
|
|
55808
56016
|
}));
|
|
55809
56017
|
if (options.outputPath) {
|
|
55810
56018
|
const outputPath = resolve47(process.cwd(), options.outputPath);
|
|
55811
|
-
await
|
|
56019
|
+
await writeFile37(outputPath, JSON.stringify({ source: absPath, totalDuration, threshold, scenes: result }, null, 2), "utf-8");
|
|
55812
56020
|
}
|
|
55813
56021
|
return { success: true, scenes: result, totalDuration };
|
|
55814
56022
|
} catch (error) {
|
|
@@ -55855,7 +56063,7 @@ async function executeDetectSilence(options) {
|
|
|
55855
56063
|
}
|
|
55856
56064
|
if (options.outputPath) {
|
|
55857
56065
|
const outputPath = resolve47(process.cwd(), options.outputPath);
|
|
55858
|
-
await
|
|
56066
|
+
await writeFile37(outputPath, JSON.stringify({ source: absPath, silences }, null, 2), "utf-8");
|
|
55859
56067
|
}
|
|
55860
56068
|
return { success: true, silences };
|
|
55861
56069
|
} catch (error) {
|
|
@@ -55904,7 +56112,7 @@ async function executeDetectBeats(options) {
|
|
|
55904
56112
|
}
|
|
55905
56113
|
if (options.outputPath) {
|
|
55906
56114
|
const outputPath = resolve47(process.cwd(), options.outputPath);
|
|
55907
|
-
await
|
|
56115
|
+
await writeFile37(outputPath, JSON.stringify({ source: absPath, beatCount: beats.length, beats }, null, 2), "utf-8");
|
|
55908
56116
|
}
|
|
55909
56117
|
return { success: true, beats, beatCount: beats.length };
|
|
55910
56118
|
} catch (error) {
|
|
@@ -56008,7 +56216,7 @@ var init_detect = __esm({
|
|
|
56008
56216
|
duration: (i < scenes.length - 1 ? scenes[i + 1].timestamp : totalDuration) - s.timestamp
|
|
56009
56217
|
}))
|
|
56010
56218
|
};
|
|
56011
|
-
await
|
|
56219
|
+
await writeFile37(outputPath, JSON.stringify(result, null, 2), "utf-8");
|
|
56012
56220
|
console.log(source_default.green(`Saved to: ${outputPath}`));
|
|
56013
56221
|
}
|
|
56014
56222
|
if (options.project) {
|
|
@@ -56038,7 +56246,7 @@ var init_detect = __esm({
|
|
|
56038
56246
|
sourceEndOffset: end
|
|
56039
56247
|
});
|
|
56040
56248
|
}
|
|
56041
|
-
await
|
|
56249
|
+
await writeFile37(projectPath, JSON.stringify(project.toJSON(), null, 2), "utf-8");
|
|
56042
56250
|
console.log(source_default.green(`Added ${scenes.length} clips to project`));
|
|
56043
56251
|
}
|
|
56044
56252
|
} catch (error) {
|
|
@@ -56120,7 +56328,7 @@ var init_detect = __esm({
|
|
|
56120
56328
|
console.log();
|
|
56121
56329
|
if (options.output) {
|
|
56122
56330
|
const outputPath = resolve47(process.cwd(), options.output);
|
|
56123
|
-
await
|
|
56331
|
+
await writeFile37(
|
|
56124
56332
|
outputPath,
|
|
56125
56333
|
JSON.stringify({ source: absPath, silences }, null, 2),
|
|
56126
56334
|
"utf-8"
|
|
@@ -56205,7 +56413,7 @@ var init_detect = __esm({
|
|
|
56205
56413
|
console.log();
|
|
56206
56414
|
if (options.output) {
|
|
56207
56415
|
const outputPath = resolve47(process.cwd(), options.output);
|
|
56208
|
-
await
|
|
56416
|
+
await writeFile37(
|
|
56209
56417
|
outputPath,
|
|
56210
56418
|
JSON.stringify({ source: absPath, beatCount: beats.length, beats }, null, 2),
|
|
56211
56419
|
"utf-8"
|
|
@@ -56841,7 +57049,7 @@ var init_openai2 = __esm({
|
|
|
56841
57049
|
OpenAIAdapter = class {
|
|
56842
57050
|
provider = "openai";
|
|
56843
57051
|
client = null;
|
|
56844
|
-
model = "gpt-5-mini";
|
|
57052
|
+
model = "gpt-5.4-mini";
|
|
56845
57053
|
async initialize(apiKey) {
|
|
56846
57054
|
this.client = new OpenAI({ apiKey });
|
|
56847
57055
|
}
|
|
@@ -56937,7 +57145,7 @@ var init_claude2 = __esm({
|
|
|
56937
57145
|
ClaudeAdapter = class {
|
|
56938
57146
|
provider = "claude";
|
|
56939
57147
|
client = null;
|
|
56940
|
-
model = "claude-sonnet-
|
|
57148
|
+
model = "claude-sonnet-5-5";
|
|
56941
57149
|
async initialize(apiKey) {
|
|
56942
57150
|
this.client = new Anthropic({ apiKey });
|
|
56943
57151
|
}
|
|
@@ -56962,6 +57170,13 @@ var init_claude2 = __esm({
|
|
|
56962
57170
|
content: msg.content
|
|
56963
57171
|
});
|
|
56964
57172
|
} else if (msg.role === "assistant") {
|
|
57173
|
+
if (msg.providerContent) {
|
|
57174
|
+
claudeMessages.push({
|
|
57175
|
+
role: "assistant",
|
|
57176
|
+
content: msg.providerContent
|
|
57177
|
+
});
|
|
57178
|
+
continue;
|
|
57179
|
+
}
|
|
56965
57180
|
const content = [];
|
|
56966
57181
|
if (msg.content) {
|
|
56967
57182
|
content.push({ type: "text", text: msg.content });
|
|
@@ -56983,16 +57198,17 @@ var init_claude2 = __esm({
|
|
|
56983
57198
|
});
|
|
56984
57199
|
}
|
|
56985
57200
|
} else if (msg.role === "tool") {
|
|
56986
|
-
|
|
56987
|
-
|
|
56988
|
-
|
|
56989
|
-
|
|
56990
|
-
|
|
56991
|
-
|
|
56992
|
-
|
|
56993
|
-
|
|
56994
|
-
|
|
56995
|
-
|
|
57201
|
+
const result = {
|
|
57202
|
+
type: "tool_result",
|
|
57203
|
+
tool_use_id: msg.toolCallId,
|
|
57204
|
+
content: msg.content
|
|
57205
|
+
};
|
|
57206
|
+
const last = claudeMessages.at(-1);
|
|
57207
|
+
if (last?.role === "user" && Array.isArray(last.content)) {
|
|
57208
|
+
last.content.push(result);
|
|
57209
|
+
} else {
|
|
57210
|
+
claudeMessages.push({ role: "user", content: [result] });
|
|
57211
|
+
}
|
|
56996
57212
|
}
|
|
56997
57213
|
}
|
|
56998
57214
|
const claudeTools = tools.map((tool) => ({
|
|
@@ -57006,7 +57222,8 @@ var init_claude2 = __esm({
|
|
|
57006
57222
|
}));
|
|
57007
57223
|
const response = await this.client.messages.create({
|
|
57008
57224
|
model: this.model,
|
|
57009
|
-
|
|
57225
|
+
// Thinking tokens count against this cap on Claude 5.x.
|
|
57226
|
+
max_tokens: 16e3,
|
|
57010
57227
|
system: systemPrompt,
|
|
57011
57228
|
messages: claudeMessages,
|
|
57012
57229
|
tools: claudeTools.length > 0 ? claudeTools : void 0
|
|
@@ -57033,7 +57250,8 @@ var init_claude2 = __esm({
|
|
|
57033
57250
|
return {
|
|
57034
57251
|
content: textContent,
|
|
57035
57252
|
toolCalls: toolCalls.length > 0 ? toolCalls : void 0,
|
|
57036
|
-
finishReason
|
|
57253
|
+
finishReason,
|
|
57254
|
+
providerContent: response.content
|
|
57037
57255
|
};
|
|
57038
57256
|
}
|
|
57039
57257
|
};
|
|
@@ -57043,17 +57261,51 @@ var init_claude2 = __esm({
|
|
|
57043
57261
|
// src/agent/adapters/gemini.ts
|
|
57044
57262
|
var gemini_exports = {};
|
|
57045
57263
|
__export(gemini_exports, {
|
|
57046
|
-
GeminiAdapter: () => GeminiAdapter
|
|
57264
|
+
GeminiAdapter: () => GeminiAdapter,
|
|
57265
|
+
toGeminiSchema: () => toGeminiSchema
|
|
57047
57266
|
});
|
|
57048
57267
|
import { GoogleGenerativeAI, SchemaType } from "@google/generative-ai";
|
|
57049
|
-
|
|
57268
|
+
function toGeminiSchema(schema) {
|
|
57269
|
+
if (Array.isArray(schema)) return schema.map(toGeminiSchema);
|
|
57270
|
+
if (!schema || typeof schema !== "object") return schema;
|
|
57271
|
+
const out = {};
|
|
57272
|
+
for (const [key, value] of Object.entries(schema)) {
|
|
57273
|
+
if (!GEMINI_SCHEMA_KEYS.has(key)) continue;
|
|
57274
|
+
if (key === "properties" && value && typeof value === "object") {
|
|
57275
|
+
out.properties = Object.fromEntries(
|
|
57276
|
+
Object.entries(value).map(([name, prop]) => [name, toGeminiSchema(prop)])
|
|
57277
|
+
);
|
|
57278
|
+
} else if (key === "items") {
|
|
57279
|
+
out.items = toGeminiSchema(value);
|
|
57280
|
+
} else {
|
|
57281
|
+
out[key] = value;
|
|
57282
|
+
}
|
|
57283
|
+
}
|
|
57284
|
+
return out;
|
|
57285
|
+
}
|
|
57286
|
+
var GEMINI_SCHEMA_KEYS, GeminiAdapter;
|
|
57050
57287
|
var init_gemini2 = __esm({
|
|
57051
57288
|
"src/agent/adapters/gemini.ts"() {
|
|
57052
57289
|
"use strict";
|
|
57290
|
+
init_dist2();
|
|
57291
|
+
GEMINI_SCHEMA_KEYS = /* @__PURE__ */ new Set([
|
|
57292
|
+
"type",
|
|
57293
|
+
"format",
|
|
57294
|
+
"description",
|
|
57295
|
+
"nullable",
|
|
57296
|
+
"enum",
|
|
57297
|
+
"items",
|
|
57298
|
+
"properties",
|
|
57299
|
+
"required",
|
|
57300
|
+
"minItems",
|
|
57301
|
+
"maxItems",
|
|
57302
|
+
"minimum",
|
|
57303
|
+
"maximum"
|
|
57304
|
+
]);
|
|
57053
57305
|
GeminiAdapter = class {
|
|
57054
57306
|
provider = "gemini";
|
|
57055
57307
|
client = null;
|
|
57056
|
-
model =
|
|
57308
|
+
model = GEMINI_AGENT_DEFAULT_TEXT_MODEL;
|
|
57057
57309
|
async initialize(apiKey) {
|
|
57058
57310
|
this.client = new GoogleGenerativeAI(apiKey);
|
|
57059
57311
|
}
|
|
@@ -57075,7 +57327,12 @@ var init_gemini2 = __esm({
|
|
|
57075
57327
|
description: tool.description,
|
|
57076
57328
|
parameters: {
|
|
57077
57329
|
type: SchemaType.OBJECT,
|
|
57078
|
-
properties:
|
|
57330
|
+
properties: Object.fromEntries(
|
|
57331
|
+
Object.entries(tool.parameters.properties).map(([name, prop]) => [
|
|
57332
|
+
name,
|
|
57333
|
+
toGeminiSchema(prop)
|
|
57334
|
+
])
|
|
57335
|
+
),
|
|
57079
57336
|
required: tool.parameters.required
|
|
57080
57337
|
}
|
|
57081
57338
|
}))
|
|
@@ -57094,6 +57351,10 @@ var init_gemini2 = __esm({
|
|
|
57094
57351
|
parts: [{ text: msg.content }]
|
|
57095
57352
|
});
|
|
57096
57353
|
} else if (msg.role === "assistant") {
|
|
57354
|
+
if (msg.providerContent) {
|
|
57355
|
+
geminiContents.push({ role: "model", parts: msg.providerContent });
|
|
57356
|
+
continue;
|
|
57357
|
+
}
|
|
57097
57358
|
const parts = [];
|
|
57098
57359
|
if (msg.content) {
|
|
57099
57360
|
parts.push({ text: msg.content });
|
|
@@ -57115,16 +57376,19 @@ var init_gemini2 = __esm({
|
|
|
57115
57376
|
});
|
|
57116
57377
|
}
|
|
57117
57378
|
} else if (msg.role === "tool") {
|
|
57118
|
-
|
|
57119
|
-
|
|
57120
|
-
|
|
57121
|
-
|
|
57122
|
-
|
|
57123
|
-
|
|
57124
|
-
|
|
57125
|
-
|
|
57126
|
-
|
|
57127
|
-
|
|
57379
|
+
const part = {
|
|
57380
|
+
functionResponse: {
|
|
57381
|
+
name: msg.toolCallId.split(":::")[0] || "unknown",
|
|
57382
|
+
// Extract function name from id
|
|
57383
|
+
response: { result: msg.content }
|
|
57384
|
+
}
|
|
57385
|
+
};
|
|
57386
|
+
const last = geminiContents.at(-1);
|
|
57387
|
+
if (last?.role === "user" && last.parts.every((p) => "functionResponse" in p)) {
|
|
57388
|
+
last.parts.push(part);
|
|
57389
|
+
} else {
|
|
57390
|
+
geminiContents.push({ role: "user", parts: [part] });
|
|
57391
|
+
}
|
|
57128
57392
|
}
|
|
57129
57393
|
}
|
|
57130
57394
|
const result = await model.generateContent({
|
|
@@ -57161,7 +57425,8 @@ var init_gemini2 = __esm({
|
|
|
57161
57425
|
return {
|
|
57162
57426
|
content: textContent,
|
|
57163
57427
|
toolCalls: toolCalls.length > 0 ? toolCalls : void 0,
|
|
57164
|
-
finishReason
|
|
57428
|
+
finishReason,
|
|
57429
|
+
providerContent: candidate.content.parts
|
|
57165
57430
|
};
|
|
57166
57431
|
}
|
|
57167
57432
|
};
|
|
@@ -57364,7 +57629,7 @@ var init_xai = __esm({
|
|
|
57364
57629
|
XAIAdapter = class {
|
|
57365
57630
|
provider = "xai";
|
|
57366
57631
|
client = null;
|
|
57367
|
-
model = "grok-4
|
|
57632
|
+
model = "grok-4.3";
|
|
57368
57633
|
async initialize(apiKey) {
|
|
57369
57634
|
this.client = new OpenAI2({
|
|
57370
57635
|
apiKey,
|
|
@@ -57768,7 +58033,7 @@ var init_composer_resolve = __esm({
|
|
|
57768
58033
|
|
|
57769
58034
|
// src/commands/_shared/storyboard-revise.ts
|
|
57770
58035
|
import { existsSync as existsSync42 } from "node:fs";
|
|
57771
|
-
import { readFile as readFile37, writeFile as
|
|
58036
|
+
import { readFile as readFile37, writeFile as writeFile40 } from "node:fs/promises";
|
|
57772
58037
|
import { join as join22, resolve as resolve51 } from "node:path";
|
|
57773
58038
|
async function executeStoryboardRevision(opts) {
|
|
57774
58039
|
const projectDir = resolve51(opts.projectDir);
|
|
@@ -57887,7 +58152,7 @@ async function executeStoryboardRevision(opts) {
|
|
|
57887
58152
|
if (loaded.layout === "bundle") {
|
|
57888
58153
|
await rewriteBundleFromMarkdown(projectDir, storyboardMd);
|
|
57889
58154
|
} else {
|
|
57890
|
-
await
|
|
58155
|
+
await writeFile40(storyboardPath2, storyboardMd, "utf-8");
|
|
57891
58156
|
}
|
|
57892
58157
|
}
|
|
57893
58158
|
const changedBeats = unique2([...diffChangedBeats(currentStoryboard, storyboardMd), ...payload.changedBeats]);
|
|
@@ -58179,7 +58444,7 @@ var init_design_parse = __esm({
|
|
|
58179
58444
|
|
|
58180
58445
|
// src/commands/_shared/build-asset-reference.ts
|
|
58181
58446
|
import { existsSync as existsSync45 } from "node:fs";
|
|
58182
|
-
import { extname as
|
|
58447
|
+
import { extname as extname13, isAbsolute as isAbsolute5, relative as relative9, resolve as resolve54, sep as sep2 } from "node:path";
|
|
58183
58448
|
function resolveTypedAssetReference(projectDir, kind, value) {
|
|
58184
58449
|
const raw = stringOrUndefined2(value);
|
|
58185
58450
|
if (!raw || !looksLikeAssetPath(raw)) return null;
|
|
@@ -58204,7 +58469,7 @@ function isReadyAssetReference(reference) {
|
|
|
58204
58469
|
return Boolean(reference && !reference.error && reference.relPath && reference.absPath);
|
|
58205
58470
|
}
|
|
58206
58471
|
function resolveReference(projectDir, kind, raw, source, forcedError) {
|
|
58207
|
-
const ext =
|
|
58472
|
+
const ext = extname13(raw).toLowerCase();
|
|
58208
58473
|
const inferred = inferAssetKind(raw);
|
|
58209
58474
|
const absPath = isAbsolute5(raw) ? resolve54(raw) : resolve54(projectDir, raw);
|
|
58210
58475
|
const rel = relative9(resolve54(projectDir), absPath);
|
|
@@ -58236,7 +58501,7 @@ function resolveReference(projectDir, kind, raw, source, forcedError) {
|
|
|
58236
58501
|
};
|
|
58237
58502
|
}
|
|
58238
58503
|
function inferAssetKind(value) {
|
|
58239
|
-
const ext =
|
|
58504
|
+
const ext = extname13(value).toLowerCase();
|
|
58240
58505
|
if (EXTENSIONS.backdrop.includes(ext)) return "backdrop";
|
|
58241
58506
|
if (EXTENSIONS.video.includes(ext)) return "video";
|
|
58242
58507
|
if (EXTENSIONS.narration.includes(ext)) return "music";
|
|
@@ -58398,9 +58663,40 @@ var init_build_backdrop_prompt = __esm({
|
|
|
58398
58663
|
}
|
|
58399
58664
|
});
|
|
58400
58665
|
|
|
58666
|
+
// src/commands/_shared/build-video-providers.ts
|
|
58667
|
+
function isBuildVideoProvider(value) {
|
|
58668
|
+
return BUILD_VIDEO_PROVIDERS.includes(value);
|
|
58669
|
+
}
|
|
58670
|
+
function resolveBuildVideoProvider(value) {
|
|
58671
|
+
const provider = String(value ?? "seedance").toLowerCase();
|
|
58672
|
+
if (provider === "fal") return "seedance";
|
|
58673
|
+
return isBuildVideoProvider(provider) ? provider : "seedance";
|
|
58674
|
+
}
|
|
58675
|
+
function videoProviderConfigKey(provider) {
|
|
58676
|
+
switch (provider) {
|
|
58677
|
+
case "seedance":
|
|
58678
|
+
case "fal":
|
|
58679
|
+
return "fal";
|
|
58680
|
+
case "grok":
|
|
58681
|
+
return "xai";
|
|
58682
|
+
case "veo":
|
|
58683
|
+
case "omni":
|
|
58684
|
+
return "google";
|
|
58685
|
+
default:
|
|
58686
|
+
return provider;
|
|
58687
|
+
}
|
|
58688
|
+
}
|
|
58689
|
+
var BUILD_VIDEO_PROVIDERS;
|
|
58690
|
+
var init_build_video_providers = __esm({
|
|
58691
|
+
"src/commands/_shared/build-video-providers.ts"() {
|
|
58692
|
+
"use strict";
|
|
58693
|
+
BUILD_VIDEO_PROVIDERS = ["seedance", "grok", "kling", "runway", "omni", "veo"];
|
|
58694
|
+
}
|
|
58695
|
+
});
|
|
58696
|
+
|
|
58401
58697
|
// src/commands/_shared/build-plan.ts
|
|
58402
58698
|
import { existsSync as existsSync46 } from "node:fs";
|
|
58403
|
-
import { dirname as
|
|
58699
|
+
import { dirname as dirname19, join as join24, resolve as resolve55 } from "node:path";
|
|
58404
58700
|
function backdropCostUsd(quality) {
|
|
58405
58701
|
return quality === "hd" ? 0.2 : 0.05;
|
|
58406
58702
|
}
|
|
@@ -59072,12 +59368,7 @@ function normalizeImageProvider(value) {
|
|
|
59072
59368
|
return provider || "openai";
|
|
59073
59369
|
}
|
|
59074
59370
|
function normalizeVideoProvider(value) {
|
|
59075
|
-
|
|
59076
|
-
if (provider === "fal") return "seedance";
|
|
59077
|
-
if (provider === "seedance" || provider === "grok" || provider === "kling" || provider === "runway" || provider === "veo") {
|
|
59078
|
-
return provider;
|
|
59079
|
-
}
|
|
59080
|
-
return "seedance";
|
|
59371
|
+
return resolveBuildVideoProvider(value);
|
|
59081
59372
|
}
|
|
59082
59373
|
function normalizeMusicProvider(value) {
|
|
59083
59374
|
const provider = String(value ?? "elevenlabs").toLowerCase();
|
|
@@ -59089,7 +59380,7 @@ function imageConfigKey(provider) {
|
|
|
59089
59380
|
return "openai";
|
|
59090
59381
|
}
|
|
59091
59382
|
function videoConfigKey(provider) {
|
|
59092
|
-
return provider
|
|
59383
|
+
return videoProviderConfigKey(provider);
|
|
59093
59384
|
}
|
|
59094
59385
|
function composerConfigKey(provider) {
|
|
59095
59386
|
return provider === "claude" ? "anthropic" : provider === "gemini" ? "google" : "openai";
|
|
@@ -59107,12 +59398,12 @@ function loadPlanEnv(projectDir) {
|
|
|
59107
59398
|
(0, import_dotenv3.config)({ path: join24(projectDir, ".env"), quiet: true });
|
|
59108
59399
|
(0, import_dotenv3.config)({ path: resolve55(process.cwd(), ".env"), quiet: true });
|
|
59109
59400
|
let dir = process.cwd();
|
|
59110
|
-
while (dir !==
|
|
59401
|
+
while (dir !== dirname19(dir)) {
|
|
59111
59402
|
if (existsSync46(join24(dir, "pnpm-workspace.yaml"))) {
|
|
59112
59403
|
(0, import_dotenv3.config)({ path: join24(dir, ".env"), quiet: true });
|
|
59113
59404
|
return;
|
|
59114
59405
|
}
|
|
59115
|
-
dir =
|
|
59406
|
+
dir = dirname19(dir);
|
|
59116
59407
|
}
|
|
59117
59408
|
}
|
|
59118
59409
|
var import_dotenv3, VIDEO_COST_USD, MUSIC_COST_USD, ELEVENLABS_NARRATION_COST_USD, OPENAI_NARRATION_COST_USD, TRANSCRIPT_COST_USD, COMPOSE_COST_USD, SUPPORTED_BUILD_IMAGE_PROVIDERS;
|
|
@@ -59133,6 +59424,7 @@ var init_build_plan = __esm({
|
|
|
59133
59424
|
init_project_config();
|
|
59134
59425
|
init_scene_project();
|
|
59135
59426
|
init_storyboard_edit();
|
|
59427
|
+
init_build_video_providers();
|
|
59136
59428
|
VIDEO_COST_USD = 5;
|
|
59137
59429
|
MUSIC_COST_USD = 0.5;
|
|
59138
59430
|
ELEVENLABS_NARRATION_COST_USD = 0.05;
|
|
@@ -59194,7 +59486,7 @@ var init_concurrency = __esm({
|
|
|
59194
59486
|
|
|
59195
59487
|
// src/commands/_shared/compose-aivideo.ts
|
|
59196
59488
|
import { existsSync as existsSync47 } from "node:fs";
|
|
59197
|
-
import { mkdir as
|
|
59489
|
+
import { mkdir as mkdir24, readFile as readFile40, writeFile as writeFile42 } from "node:fs/promises";
|
|
59198
59490
|
import { join as join25, resolve as resolve57 } from "node:path";
|
|
59199
59491
|
function headingDescriptor(heading) {
|
|
59200
59492
|
const stripped = heading.replace(/^\s*beat\s+/i, "");
|
|
@@ -59357,7 +59649,7 @@ async function composeAiVideo(opts) {
|
|
|
59357
59649
|
}
|
|
59358
59650
|
clipRels.push(rel);
|
|
59359
59651
|
}
|
|
59360
|
-
await
|
|
59652
|
+
await mkdir24(join25(projectDir, "assets"), { recursive: true });
|
|
59361
59653
|
const bgRel = "assets/bg-full.mp4";
|
|
59362
59654
|
const concatArgs = buildBgConcatArgs(
|
|
59363
59655
|
clipRels.map((r) => join25(projectDir, r)),
|
|
@@ -59365,7 +59657,7 @@ async function composeAiVideo(opts) {
|
|
|
59365
59657
|
);
|
|
59366
59658
|
await execSafe("ffmpeg", concatArgs, { timeout: 6e5 });
|
|
59367
59659
|
const totalDurationSec = await probeDurationSec(join25(projectDir, bgRel));
|
|
59368
|
-
await
|
|
59660
|
+
await mkdir24(join25(projectDir, "compositions"), { recursive: true });
|
|
59369
59661
|
const sceneFiles = [];
|
|
59370
59662
|
for (let i = 0; i < beats.length; i++) {
|
|
59371
59663
|
const beat = beats[i];
|
|
@@ -59382,12 +59674,12 @@ async function composeAiVideo(opts) {
|
|
|
59382
59674
|
isLast: i === beats.length - 1
|
|
59383
59675
|
});
|
|
59384
59676
|
const rel = `compositions/scene-${beat.id}.html`;
|
|
59385
|
-
await
|
|
59677
|
+
await writeFile42(join25(projectDir, rel), html, "utf-8");
|
|
59386
59678
|
sceneFiles.push(rel);
|
|
59387
59679
|
}
|
|
59388
59680
|
const indexPath = join25(projectDir, "index.html");
|
|
59389
59681
|
const next = existsSync47(indexPath) ? injectBgVideo(await readFile40(indexPath, "utf-8"), bgRel, totalDurationSec) : buildRootShell(tokens, bgRel, totalDurationSec);
|
|
59390
|
-
await
|
|
59682
|
+
await writeFile42(indexPath, next, "utf-8");
|
|
59391
59683
|
return { bgVideoRel: bgRel, sceneFiles, totalDurationSec, beats: beats.length };
|
|
59392
59684
|
}
|
|
59393
59685
|
function buildRootShell(tokens, bgRel, totalDuration) {
|
|
@@ -59514,8 +59806,8 @@ var init_compose_aivideo = __esm({
|
|
|
59514
59806
|
|
|
59515
59807
|
// src/commands/_shared/footage-assemble.ts
|
|
59516
59808
|
import { existsSync as existsSync48 } from "node:fs";
|
|
59517
|
-
import { mkdir as
|
|
59518
|
-
import { dirname as
|
|
59809
|
+
import { mkdir as mkdir25, writeFile as writeFile43 } from "node:fs/promises";
|
|
59810
|
+
import { dirname as dirname20, isAbsolute as isAbsolute6, join as join26, resolve as resolve58 } from "node:path";
|
|
59519
59811
|
function planFootageTimeline(inputs, opts = {}) {
|
|
59520
59812
|
if (inputs.length === 0) {
|
|
59521
59813
|
throw new Error("No clips to assemble.");
|
|
@@ -59844,7 +60136,7 @@ async function executeFootageAssemble(opts) {
|
|
|
59844
60136
|
if (opts.dryRun) {
|
|
59845
60137
|
return { success: true, dryRun: true, outputPath, report };
|
|
59846
60138
|
}
|
|
59847
|
-
await
|
|
60139
|
+
await mkdir25(dirname20(outputPath), { recursive: true });
|
|
59848
60140
|
const args = buildFootageAssembleArgs({
|
|
59849
60141
|
sources: sourceRels.map((s) => ({ path: join26(projectDir, s.rel), kind: s.kind })),
|
|
59850
60142
|
plan,
|
|
@@ -59869,7 +60161,7 @@ async function executeFootageAssemble(opts) {
|
|
|
59869
60161
|
};
|
|
59870
60162
|
}
|
|
59871
60163
|
const reportPath = join26(projectDir, "assemble-report.json");
|
|
59872
|
-
await
|
|
60164
|
+
await writeFile43(reportPath, `${JSON.stringify(report, null, 2)}
|
|
59873
60165
|
`, "utf-8");
|
|
59874
60166
|
return { success: true, dryRun: false, outputPath, reportPath, report };
|
|
59875
60167
|
}
|
|
@@ -60034,7 +60326,7 @@ var init_scene_audio_scan = __esm({
|
|
|
60034
60326
|
|
|
60035
60327
|
// src/commands/_shared/scene-audio-mux.ts
|
|
60036
60328
|
import { rename as rename4, unlink } from "node:fs/promises";
|
|
60037
|
-
import { resolve as resolve60, dirname as
|
|
60329
|
+
import { resolve as resolve60, dirname as dirname21, extname as extname14, basename as basename20 } from "node:path";
|
|
60038
60330
|
function buildAudioMuxFilter(audios) {
|
|
60039
60331
|
if (audios.length === 0) return null;
|
|
60040
60332
|
const labels = [];
|
|
@@ -60093,9 +60385,9 @@ async function muxAudioIntoVideo(opts) {
|
|
|
60093
60385
|
if (!filter) {
|
|
60094
60386
|
return { success: true, outputPath: opts.videoPath, audioCount: 0 };
|
|
60095
60387
|
}
|
|
60096
|
-
const ext =
|
|
60388
|
+
const ext = extname14(opts.videoPath) || `.${opts.format}`;
|
|
60097
60389
|
const tmpPath = resolve60(
|
|
60098
|
-
|
|
60390
|
+
dirname21(opts.videoPath),
|
|
60099
60391
|
`.${basename20(opts.videoPath, ext)}.muxing${ext}`
|
|
60100
60392
|
);
|
|
60101
60393
|
const args = ["-y", "-loglevel", "error", "-i", opts.videoPath];
|
|
@@ -60243,8 +60535,8 @@ __export(scene_render_exports, {
|
|
|
60243
60535
|
});
|
|
60244
60536
|
import { execFile as execFile2 } from "node:child_process";
|
|
60245
60537
|
import { existsSync as existsSync50 } from "node:fs";
|
|
60246
|
-
import { mkdir as
|
|
60247
|
-
import { resolve as resolve62, relative as relative10, dirname as
|
|
60538
|
+
import { mkdir as mkdir26, readFile as readFile43, stat as stat8, writeFile as writeFile44 } from "node:fs/promises";
|
|
60539
|
+
import { resolve as resolve62, relative as relative10, dirname as dirname22, basename as basename21, join as join27, isAbsolute as isAbsolute8 } from "node:path";
|
|
60248
60540
|
import { promisify as promisify2 } from "node:util";
|
|
60249
60541
|
import {
|
|
60250
60542
|
createRenderJob,
|
|
@@ -60297,7 +60589,7 @@ function buildMediaOpenCommand(action, filePath, platform3 = process.platform) {
|
|
|
60297
60589
|
display: ["cmd", ...args].map(quoteCliArg).join(" ")
|
|
60298
60590
|
};
|
|
60299
60591
|
}
|
|
60300
|
-
const target = action === "reveal" ?
|
|
60592
|
+
const target = action === "reveal" ? dirname22(filePath) : filePath;
|
|
60301
60593
|
return {
|
|
60302
60594
|
command: "xdg-open",
|
|
60303
60595
|
args: [target],
|
|
@@ -60393,7 +60685,7 @@ async function executeSceneRender(opts = {}) {
|
|
|
60393
60685
|
}
|
|
60394
60686
|
const projectName = projectConfig.config.name;
|
|
60395
60687
|
const outputPath = opts.output ? resolve62(projectDir, opts.output) : defaultOutputPath({ projectDir, projectName, format: opts.format, beatId: opts.beatId });
|
|
60396
|
-
await
|
|
60688
|
+
await mkdir26(dirname22(outputPath), { recursive: true });
|
|
60397
60689
|
const config2 = buildRenderConfig({
|
|
60398
60690
|
fps: opts.fps,
|
|
60399
60691
|
quality: opts.quality,
|
|
@@ -60589,8 +60881,8 @@ async function prepareBeatRenderRoot(opts) {
|
|
|
60589
60881
|
durationSec,
|
|
60590
60882
|
narrationPath
|
|
60591
60883
|
});
|
|
60592
|
-
await
|
|
60593
|
-
await
|
|
60884
|
+
await mkdir26(dirname22(join27(opts.projectDir, root)), { recursive: true });
|
|
60885
|
+
await writeFile44(join27(opts.projectDir, root), html, "utf-8");
|
|
60594
60886
|
return {
|
|
60595
60887
|
success: true,
|
|
60596
60888
|
root,
|
|
@@ -60656,7 +60948,7 @@ function reportedBeatAssetPaths(beat) {
|
|
|
60656
60948
|
async function writeRenderReport(projectDir, result) {
|
|
60657
60949
|
const reportPath = join27(projectDir, "render-report.json");
|
|
60658
60950
|
try {
|
|
60659
|
-
await
|
|
60951
|
+
await writeFile44(
|
|
60660
60952
|
reportPath,
|
|
60661
60953
|
JSON.stringify(
|
|
60662
60954
|
{
|
|
@@ -60753,8 +61045,8 @@ __export(scene_build_exports, {
|
|
|
60753
61045
|
resolveSceneBuildMode: () => resolveSceneBuildMode
|
|
60754
61046
|
});
|
|
60755
61047
|
import { existsSync as existsSync51, readFileSync as readFileSync2 } from "node:fs";
|
|
60756
|
-
import { copyFile as copyFile5, mkdir as
|
|
60757
|
-
import { dirname as
|
|
61048
|
+
import { copyFile as copyFile5, mkdir as mkdir27, readFile as readFile44, rm as rm6, writeFile as writeFile45 } from "node:fs/promises";
|
|
61049
|
+
import { dirname as dirname23, join as join28, resolve as resolve63 } from "node:path";
|
|
60758
61050
|
function readProjectKindSync(projectDir) {
|
|
60759
61051
|
try {
|
|
60760
61052
|
const raw = readFileSync2(join28(projectDir, "vibe.config.json"), "utf-8");
|
|
@@ -61607,7 +61899,7 @@ async function dispatchNarration(beat, ctx) {
|
|
|
61607
61899
|
};
|
|
61608
61900
|
}
|
|
61609
61901
|
if (existsSync51(cacheAbs) && !ctx.force) {
|
|
61610
|
-
await
|
|
61902
|
+
await mkdir27(dirname23(abs), { recursive: true });
|
|
61611
61903
|
await copyFile5(cacheAbs, abs);
|
|
61612
61904
|
await writeAssetMetadata({
|
|
61613
61905
|
projectDir: ctx.projectDir,
|
|
@@ -61638,14 +61930,14 @@ async function dispatchNarration(beat, ctx) {
|
|
|
61638
61930
|
ctx.onProgress({ type: "narration-failed", beatId: beat.id, error });
|
|
61639
61931
|
return { status: "failed", error };
|
|
61640
61932
|
}
|
|
61641
|
-
await
|
|
61642
|
-
await
|
|
61933
|
+
await mkdir27(dirname23(abs), { recursive: true });
|
|
61934
|
+
await writeFile45(abs, result.audioBuffer);
|
|
61643
61935
|
for (const otherExt of ["mp3", "wav"]) {
|
|
61644
61936
|
const sibling = join28(ctx.projectDir, `assets/narration-${beat.id}.${otherExt}`);
|
|
61645
|
-
if (sibling !== abs && existsSync51(sibling)) await
|
|
61937
|
+
if (sibling !== abs && existsSync51(sibling)) await rm6(sibling, { force: true });
|
|
61646
61938
|
}
|
|
61647
|
-
await
|
|
61648
|
-
await
|
|
61939
|
+
await mkdir27(dirname23(cacheAbs), { recursive: true });
|
|
61940
|
+
await writeFile45(cacheAbs, result.audioBuffer);
|
|
61649
61941
|
await writeAssetMetadata({
|
|
61650
61942
|
projectDir: ctx.projectDir,
|
|
61651
61943
|
kind: "narration",
|
|
@@ -61701,8 +61993,8 @@ async function dispatchTranscript(beat, narrationPath, narrationFresh, ctx) {
|
|
|
61701
61993
|
return "skipped";
|
|
61702
61994
|
}
|
|
61703
61995
|
try {
|
|
61704
|
-
await
|
|
61705
|
-
await
|
|
61996
|
+
await mkdir27(dirname23(abs), { recursive: true });
|
|
61997
|
+
await writeFile45(abs, JSON.stringify(words, null, 2), "utf-8");
|
|
61706
61998
|
} catch (err) {
|
|
61707
61999
|
ctx.onProgress({
|
|
61708
62000
|
type: "transcript-skipped",
|
|
@@ -61790,7 +62082,7 @@ async function buildCharacters(characters, ctx) {
|
|
|
61790
62082
|
}
|
|
61791
62083
|
const cacheAbs = join28(ctx.projectDir, cache.path);
|
|
61792
62084
|
if (existsSync51(cacheAbs) && !ctx.force) {
|
|
61793
|
-
await
|
|
62085
|
+
await mkdir27(dirname23(abs), { recursive: true });
|
|
61794
62086
|
await copyFile5(cacheAbs, abs);
|
|
61795
62087
|
await writeAssetMetadata({
|
|
61796
62088
|
projectDir: ctx.projectDir,
|
|
@@ -61823,10 +62115,10 @@ async function buildCharacters(characters, ctx) {
|
|
|
61823
62115
|
ctx.onProgress({ type: "character-failed", name: character.name, error: generated.error });
|
|
61824
62116
|
continue;
|
|
61825
62117
|
}
|
|
61826
|
-
await
|
|
61827
|
-
await
|
|
61828
|
-
await
|
|
61829
|
-
await
|
|
62118
|
+
await mkdir27(dirname23(abs), { recursive: true });
|
|
62119
|
+
await writeImageFile(abs, generated.buffer);
|
|
62120
|
+
await mkdir27(dirname23(cacheAbs), { recursive: true });
|
|
62121
|
+
await writeImageFile(cacheAbs, generated.buffer);
|
|
61830
62122
|
await writeAssetMetadata({
|
|
61831
62123
|
projectDir: ctx.projectDir,
|
|
61832
62124
|
kind: "character",
|
|
@@ -61895,7 +62187,7 @@ async function dispatchBackdrop(beat, ctx) {
|
|
|
61895
62187
|
}
|
|
61896
62188
|
const cacheAbs = join28(ctx.projectDir, cache.path);
|
|
61897
62189
|
if (existsSync51(cacheAbs) && !ctx.force) {
|
|
61898
|
-
await
|
|
62190
|
+
await mkdir27(dirname23(abs), { recursive: true });
|
|
61899
62191
|
await copyFile5(cacheAbs, abs);
|
|
61900
62192
|
await writeAssetMetadata({
|
|
61901
62193
|
projectDir: ctx.projectDir,
|
|
@@ -61925,11 +62217,11 @@ async function dispatchBackdrop(beat, ctx) {
|
|
|
61925
62217
|
ctx.onProgress({ type: "backdrop-failed", beatId: beat.id, error });
|
|
61926
62218
|
return { status: "failed", error };
|
|
61927
62219
|
}
|
|
61928
|
-
await
|
|
62220
|
+
await mkdir27(dirname23(abs), { recursive: true });
|
|
61929
62221
|
const buffer = generated.buffer;
|
|
61930
|
-
await
|
|
61931
|
-
await
|
|
61932
|
-
await
|
|
62222
|
+
await writeImageFile(abs, buffer);
|
|
62223
|
+
await mkdir27(dirname23(cacheAbs), { recursive: true });
|
|
62224
|
+
await writeImageFile(cacheAbs, buffer);
|
|
61933
62225
|
await writeAssetMetadata({
|
|
61934
62226
|
projectDir: ctx.projectDir,
|
|
61935
62227
|
kind: "backdrop",
|
|
@@ -61973,7 +62265,7 @@ async function generateBackdropImage(prompt3, ctx, ratio) {
|
|
|
61973
62265
|
const result2 = await provider2.generateImage(prompt3, {
|
|
61974
62266
|
// CLI input is free-form; an alias the provider doesn't know fails the
|
|
61975
62267
|
// API call and surfaces as a beat-scoped backdrop/keyframe error.
|
|
61976
|
-
model: ctx.imageModel ??
|
|
62268
|
+
model: ctx.imageModel ?? OPENAI_IMAGE_DEFAULT_MODEL,
|
|
61977
62269
|
size: ctx.imageSize,
|
|
61978
62270
|
quality: ctx.imageQuality
|
|
61979
62271
|
});
|
|
@@ -62058,7 +62350,7 @@ async function ensureKeyframe(beat, ctx, keyframeCue, characterRefsRel) {
|
|
|
62058
62350
|
}
|
|
62059
62351
|
const cacheAbs = join28(ctx.projectDir, cache.path);
|
|
62060
62352
|
if (existsSync51(cacheAbs) && !ctx.force) {
|
|
62061
|
-
await
|
|
62353
|
+
await mkdir27(dirname23(abs), { recursive: true });
|
|
62062
62354
|
await copyFile5(cacheAbs, abs);
|
|
62063
62355
|
await writeAssetMetadata({
|
|
62064
62356
|
projectDir: ctx.projectDir,
|
|
@@ -62088,10 +62380,10 @@ async function ensureKeyframe(beat, ctx, keyframeCue, characterRefsRel) {
|
|
|
62088
62380
|
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. ";
|
|
62089
62381
|
const generated = sheetBuffers.length > 0 ? await editKeyframeImage(`${identityLock}${keyframeCue}`, sheetBuffers, imgCtx, ratio) : await generateBackdropImage(keyframeCue, imgCtx, ratio);
|
|
62090
62382
|
if (!generated.success) return { status: "failed", error: generated.error };
|
|
62091
|
-
await
|
|
62092
|
-
await
|
|
62093
|
-
await
|
|
62094
|
-
await
|
|
62383
|
+
await mkdir27(dirname23(abs), { recursive: true });
|
|
62384
|
+
await writeImageFile(abs, generated.buffer);
|
|
62385
|
+
await mkdir27(dirname23(cacheAbs), { recursive: true });
|
|
62386
|
+
await writeImageFile(cacheAbs, generated.buffer);
|
|
62095
62387
|
await writeAssetMetadata({
|
|
62096
62388
|
projectDir: ctx.projectDir,
|
|
62097
62389
|
kind: "keyframe",
|
|
@@ -62187,7 +62479,7 @@ async function dispatchVideo(beat, ctx, keyframe) {
|
|
|
62187
62479
|
}
|
|
62188
62480
|
const cacheAbs = join28(ctx.projectDir, cache.path);
|
|
62189
62481
|
if (existsSync51(cacheAbs) && !ctx.force) {
|
|
62190
|
-
await
|
|
62482
|
+
await mkdir27(dirname23(abs), { recursive: true });
|
|
62191
62483
|
await copyFile5(cacheAbs, abs);
|
|
62192
62484
|
await writeAssetMetadata({
|
|
62193
62485
|
projectDir: ctx.projectDir,
|
|
@@ -62264,7 +62556,7 @@ async function dispatchVideo(beat, ctx, keyframe) {
|
|
|
62264
62556
|
}
|
|
62265
62557
|
}
|
|
62266
62558
|
if (result.status === "completed" && existsSync51(abs)) {
|
|
62267
|
-
await
|
|
62559
|
+
await mkdir27(dirname23(cacheAbs), { recursive: true });
|
|
62268
62560
|
await copyFile5(abs, cacheAbs);
|
|
62269
62561
|
await writeAssetMetadata({
|
|
62270
62562
|
projectDir: ctx.projectDir,
|
|
@@ -62366,7 +62658,7 @@ async function dispatchMusic(beat, ctx) {
|
|
|
62366
62658
|
}
|
|
62367
62659
|
const cacheAbs = join28(ctx.projectDir, cache.path);
|
|
62368
62660
|
if (existsSync51(cacheAbs) && !ctx.force) {
|
|
62369
|
-
await
|
|
62661
|
+
await mkdir27(dirname23(abs), { recursive: true });
|
|
62370
62662
|
await copyFile5(cacheAbs, abs);
|
|
62371
62663
|
await writeAssetMetadata({
|
|
62372
62664
|
projectDir: ctx.projectDir,
|
|
@@ -62444,7 +62736,7 @@ async function dispatchMusic(beat, ctx) {
|
|
|
62444
62736
|
ctx.onProgress({ type: "music-failed", beatId: beat.id, error });
|
|
62445
62737
|
return { status: "failed", error };
|
|
62446
62738
|
}
|
|
62447
|
-
await
|
|
62739
|
+
await mkdir27(dirname23(cacheAbs), { recursive: true });
|
|
62448
62740
|
await copyFile5(abs, cacheAbs);
|
|
62449
62741
|
await writeAssetMetadata({
|
|
62450
62742
|
projectDir: ctx.projectDir,
|
|
@@ -62478,12 +62770,12 @@ function loadSceneBuildEnv(projectDir) {
|
|
|
62478
62770
|
(0, import_dotenv4.config)({ path: join28(projectDir, ".env"), quiet: true });
|
|
62479
62771
|
(0, import_dotenv4.config)({ path: resolve63(process.cwd(), ".env"), quiet: true });
|
|
62480
62772
|
let dir = process.cwd();
|
|
62481
|
-
while (dir !==
|
|
62773
|
+
while (dir !== dirname23(dir)) {
|
|
62482
62774
|
if (existsSync51(join28(dir, "pnpm-workspace.yaml"))) {
|
|
62483
62775
|
(0, import_dotenv4.config)({ path: join28(dir, ".env"), quiet: true });
|
|
62484
62776
|
return;
|
|
62485
62777
|
}
|
|
62486
|
-
dir =
|
|
62778
|
+
dir = dirname23(dir);
|
|
62487
62779
|
}
|
|
62488
62780
|
}
|
|
62489
62781
|
async function skipped(kind, beatId, reason, ctx) {
|
|
@@ -62708,14 +63000,6 @@ async function safeAudioDuration(absPath) {
|
|
|
62708
63000
|
return void 0;
|
|
62709
63001
|
}
|
|
62710
63002
|
}
|
|
62711
|
-
function resolveBuildVideoProvider(value) {
|
|
62712
|
-
const provider = String(value ?? "seedance").toLowerCase();
|
|
62713
|
-
if (provider === "fal") return "seedance";
|
|
62714
|
-
if (provider === "seedance" || provider === "grok" || provider === "kling" || provider === "runway" || provider === "veo") {
|
|
62715
|
-
return provider;
|
|
62716
|
-
}
|
|
62717
|
-
return "seedance";
|
|
62718
|
-
}
|
|
62719
63003
|
function resolveBuildMusicProvider(value) {
|
|
62720
63004
|
const provider = String(value ?? "elevenlabs").toLowerCase();
|
|
62721
63005
|
return provider === "replicate" ? "replicate" : "elevenlabs";
|
|
@@ -62727,8 +63011,7 @@ function stringOrUndefined4(value) {
|
|
|
62727
63011
|
return typeof value === "string" && value.trim().length > 0 ? value : void 0;
|
|
62728
63012
|
}
|
|
62729
63013
|
async function apiKeyForVideoProvider(provider, projectDir) {
|
|
62730
|
-
|
|
62731
|
-
return getApiKeyFromConfig(providerKey, { cwd: projectDir });
|
|
63014
|
+
return getApiKeyFromConfig(videoProviderConfigKey(provider), { cwd: projectDir });
|
|
62732
63015
|
}
|
|
62733
63016
|
async function finalizeBuildResult(projectDir, startedAt, result, reportResult = result) {
|
|
62734
63017
|
const reportPath = join28(projectDir, "build-report.json");
|
|
@@ -62751,7 +63034,7 @@ async function finalizeBuildResult(projectDir, startedAt, result, reportResult =
|
|
|
62751
63034
|
const withMeta = decorate(result);
|
|
62752
63035
|
const reportMeta = reportResult === result ? withMeta : decorate(reportResult);
|
|
62753
63036
|
try {
|
|
62754
|
-
await
|
|
63037
|
+
await writeFile45(
|
|
62755
63038
|
reportPath,
|
|
62756
63039
|
JSON.stringify(toBuildReport(projectDir, reportMeta), null, 2) + "\n",
|
|
62757
63040
|
"utf-8"
|
|
@@ -63004,6 +63287,8 @@ var init_scene_build = __esm({
|
|
|
63004
63287
|
init_scene_repair();
|
|
63005
63288
|
init_tts_resolve();
|
|
63006
63289
|
init_scene_build_mode();
|
|
63290
|
+
init_image_file();
|
|
63291
|
+
init_build_video_providers();
|
|
63007
63292
|
init_scene_build_mode();
|
|
63008
63293
|
BEAT_PRIMITIVES_CONCURRENCY = 4;
|
|
63009
63294
|
}
|
|
@@ -63078,8 +63363,8 @@ __export(ai_audio_exports, {
|
|
|
63078
63363
|
executeTranscribe: () => executeTranscribe,
|
|
63079
63364
|
executeVoiceClone: () => executeVoiceClone
|
|
63080
63365
|
});
|
|
63081
|
-
import { resolve as resolve73, dirname as
|
|
63082
|
-
import { readFile as readFile46, writeFile as
|
|
63366
|
+
import { resolve as resolve73, dirname as dirname25, basename as basename22, extname as extname15 } from "node:path";
|
|
63367
|
+
import { readFile as readFile46, writeFile as writeFile46 } from "node:fs/promises";
|
|
63083
63368
|
import { existsSync as existsSync56 } from "node:fs";
|
|
63084
63369
|
async function executeTranscribe(options) {
|
|
63085
63370
|
const { audioPath, language, output, format, apiKey } = options;
|
|
@@ -63101,7 +63386,7 @@ async function executeTranscribe(options) {
|
|
|
63101
63386
|
outputPath = resolve73(process.cwd(), output);
|
|
63102
63387
|
const fmt = detectFormat(output, format);
|
|
63103
63388
|
const content = formatTranscript(result, fmt);
|
|
63104
|
-
await
|
|
63389
|
+
await writeFile46(outputPath, content, "utf-8");
|
|
63105
63390
|
}
|
|
63106
63391
|
return {
|
|
63107
63392
|
success: true,
|
|
@@ -63129,7 +63414,7 @@ async function executeIsolate(options) {
|
|
|
63129
63414
|
return { success: false, error: result.error || "Audio isolation failed" };
|
|
63130
63415
|
}
|
|
63131
63416
|
const outputPath = resolve73(process.cwd(), output);
|
|
63132
|
-
await
|
|
63417
|
+
await writeFile46(outputPath, result.audioBuffer);
|
|
63133
63418
|
return { success: true, outputPath };
|
|
63134
63419
|
} catch (error) {
|
|
63135
63420
|
return { success: false, error: `Audio isolation failed: ${error instanceof Error ? error.message : String(error)}` };
|
|
@@ -63175,11 +63460,11 @@ async function executeDub(options) {
|
|
|
63175
63460
|
if (!openaiKey) return { success: false, error: "OPENAI_API_KEY required for Whisper transcription" };
|
|
63176
63461
|
if (!anthropicKey) return { success: false, error: "ANTHROPIC_API_KEY required for Claude translation" };
|
|
63177
63462
|
if (!analyzeOnly && !elevenlabsKey) return { success: false, error: "ELEVENLABS_API_KEY required for TTS" };
|
|
63178
|
-
const ext =
|
|
63463
|
+
const ext = extname15(absPath).toLowerCase();
|
|
63179
63464
|
const isVideo = [".mp4", ".mov", ".avi", ".mkv", ".webm"].includes(ext);
|
|
63180
63465
|
let audioPath = absPath;
|
|
63181
63466
|
if (isVideo) {
|
|
63182
|
-
const tempAudioPath = resolve73(
|
|
63467
|
+
const tempAudioPath = resolve73(dirname25(absPath), `temp-audio-${Date.now()}.mp3`);
|
|
63183
63468
|
execSafeSync("ffmpeg", ["-i", absPath, "-vn", "-acodec", "mp3", "-y", tempAudioPath]);
|
|
63184
63469
|
audioPath = tempAudioPath;
|
|
63185
63470
|
}
|
|
@@ -63240,7 +63525,7 @@ ${segmentTexts}`,
|
|
|
63240
63525
|
translated: translatedSegments[i]?.text || s.text
|
|
63241
63526
|
}))
|
|
63242
63527
|
};
|
|
63243
|
-
await
|
|
63528
|
+
await writeFile46(timingPath, JSON.stringify(timingData, null, 2));
|
|
63244
63529
|
}
|
|
63245
63530
|
return {
|
|
63246
63531
|
success: true,
|
|
@@ -63260,10 +63545,10 @@ ${segmentTexts}`,
|
|
|
63260
63545
|
}
|
|
63261
63546
|
}
|
|
63262
63547
|
const combinedBuffer = Buffer.concat(dubbedBuffers);
|
|
63263
|
-
const outputExt = isVideo ? ".mp3" :
|
|
63264
|
-
const defaultOutputPath2 = resolve73(
|
|
63548
|
+
const outputExt = isVideo ? ".mp3" : extname15(absPath);
|
|
63549
|
+
const defaultOutputPath2 = resolve73(dirname25(absPath), `${basename22(absPath, extname15(absPath))}-${language}${outputExt}`);
|
|
63265
63550
|
const finalOutputPath = resolve73(process.cwd(), output || defaultOutputPath2);
|
|
63266
|
-
await
|
|
63551
|
+
await writeFile46(finalOutputPath, combinedBuffer);
|
|
63267
63552
|
if (isVideo && audioPath !== absPath) {
|
|
63268
63553
|
try {
|
|
63269
63554
|
const { unlink: unlink3 } = await import("node:fs/promises");
|
|
@@ -63298,7 +63583,7 @@ async function executeDuck(options) {
|
|
|
63298
63583
|
const absVoicePath = resolve73(process.cwd(), voicePath);
|
|
63299
63584
|
if (!existsSync56(absMusicPath)) return { success: false, error: `Music file not found: ${absMusicPath}` };
|
|
63300
63585
|
if (!existsSync56(absVoicePath)) return { success: false, error: `Voice file not found: ${absVoicePath}` };
|
|
63301
|
-
const defaultOutput = resolve73(
|
|
63586
|
+
const defaultOutput = resolve73(dirname25(absMusicPath), `${basename22(absMusicPath, extname15(absMusicPath))}-ducked${extname15(absMusicPath)}`);
|
|
63302
63587
|
const outputPath = resolve73(process.cwd(), output || defaultOutput);
|
|
63303
63588
|
const filter = `[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`;
|
|
63304
63589
|
await execSafe("ffmpeg", [
|
|
@@ -63328,7 +63613,7 @@ var init_ai_audio = __esm({
|
|
|
63328
63613
|
|
|
63329
63614
|
// src/pipeline/executor.ts
|
|
63330
63615
|
import { resolve as resolve74 } from "node:path";
|
|
63331
|
-
import { readFile as readFile47, writeFile as
|
|
63616
|
+
import { readFile as readFile47, writeFile as writeFile47, mkdir as mkdir29 } from "node:fs/promises";
|
|
63332
63617
|
import { existsSync as existsSync57 } from "node:fs";
|
|
63333
63618
|
function maxCostFor(action) {
|
|
63334
63619
|
const cmd = ACTION_METADATA[action]?.command;
|
|
@@ -63366,7 +63651,7 @@ async function resolvePipelineVideoProvider(provider) {
|
|
|
63366
63651
|
if (explicit === "fal") return "seedance";
|
|
63367
63652
|
if (explicit) return explicit;
|
|
63368
63653
|
await loadProviderDefaults();
|
|
63369
|
-
return resolveProvider("video")?.name ?? "grok";
|
|
63654
|
+
return resolveBuildVideoProvider(resolveProvider("video")?.name ?? "grok");
|
|
63370
63655
|
}
|
|
63371
63656
|
function providerKeyForImage(provider) {
|
|
63372
63657
|
switch (provider) {
|
|
@@ -63392,6 +63677,7 @@ function providerKeyForVideo(provider) {
|
|
|
63392
63677
|
case "runway":
|
|
63393
63678
|
return "runway";
|
|
63394
63679
|
case "veo":
|
|
63680
|
+
case "omni":
|
|
63395
63681
|
return "google";
|
|
63396
63682
|
default:
|
|
63397
63683
|
return void 0;
|
|
@@ -63642,7 +63928,7 @@ async function loadPipeline(filePath) {
|
|
|
63642
63928
|
async function executePipeline(manifest2, options = {}) {
|
|
63643
63929
|
await ensureActionsRegistered();
|
|
63644
63930
|
const outputDir = resolve74(process.cwd(), options.outputDir || `${manifest2.name}-output`);
|
|
63645
|
-
await
|
|
63931
|
+
await mkdir29(outputDir, { recursive: true });
|
|
63646
63932
|
const completedSteps = /* @__PURE__ */ new Map();
|
|
63647
63933
|
const results = [];
|
|
63648
63934
|
const startTime = Date.now();
|
|
@@ -63767,7 +64053,7 @@ async function executePipeline(manifest2, options = {}) {
|
|
|
63767
64053
|
data: s.data
|
|
63768
64054
|
}))
|
|
63769
64055
|
};
|
|
63770
|
-
await
|
|
64056
|
+
await writeFile47(
|
|
63771
64057
|
resolve74(outputDir, CHECKPOINT_FILE),
|
|
63772
64058
|
(0, import_yaml8.stringify)(checkpoint, { indent: 2 }),
|
|
63773
64059
|
"utf-8"
|
|
@@ -63824,6 +64110,7 @@ var init_executor = __esm({
|
|
|
63824
64110
|
init_output();
|
|
63825
64111
|
init_config();
|
|
63826
64112
|
init_provider_resolver();
|
|
64113
|
+
init_build_video_providers();
|
|
63827
64114
|
ACTION_METADATA = {
|
|
63828
64115
|
"generate-image": { id: "generate-image", title: "Generate image", category: "generate", command: "generate image", outputs: ["image"] },
|
|
63829
64116
|
"generate-video": { id: "generate-video", title: "Generate video", category: "generate", command: "generate video", outputs: ["video"], requiredKeys: ["provider-dependent"] },
|
|
@@ -68387,6 +68674,7 @@ var init_scene2 = __esm({
|
|
|
68387
68674
|
init_compose_prompts();
|
|
68388
68675
|
init_scene_repair();
|
|
68389
68676
|
init_scene_submit();
|
|
68677
|
+
init_build_video_providers();
|
|
68390
68678
|
SCENE_PRESETS2 = [
|
|
68391
68679
|
"simple",
|
|
68392
68680
|
"announcement",
|
|
@@ -68718,12 +69006,12 @@ var init_scene2 = __esm({
|
|
|
68718
69006
|
"TTS provider override. Default 'auto' (elevenlabs key > openai key > local kokoro)."
|
|
68719
69007
|
),
|
|
68720
69008
|
voice: external_exports.string().optional().describe("TTS voice id (provider-specific)."),
|
|
68721
|
-
imageProvider: external_exports.enum(["openai"]).optional().describe("Image provider for backdrops. Default 'openai' (gpt-image-2)."),
|
|
68722
|
-
videoProvider: external_exports.enum(
|
|
69009
|
+
imageProvider: external_exports.enum(["openai"]).optional().describe("Image provider for backdrops. Default 'openai' (gpt-image-2.5-sunburst)."),
|
|
69010
|
+
videoProvider: external_exports.enum(BUILD_VIDEO_PROVIDERS).optional().describe("Video provider for per-beat video cues. Default seedance."),
|
|
68723
69011
|
musicProvider: external_exports.enum(["elevenlabs", "replicate"]).optional().describe("Music provider for per-beat music cues. Default elevenlabs."),
|
|
68724
69012
|
imageQuality: external_exports.enum(["standard", "hd"]).optional().describe("OpenAI image quality. Default 'standard'."),
|
|
68725
69013
|
imageModel: external_exports.string().optional().describe(
|
|
68726
|
-
"Image model for keyframes/backdrops/character sheets (gemini: flash|pro, openai: gpt-image-2). Provider default when omitted."
|
|
69014
|
+
"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."
|
|
68727
69015
|
),
|
|
68728
69016
|
imageSize: external_exports.enum(["1024x1024", "1536x1024", "1024x1536"]).optional().describe("OpenAI image size. Default '1536x1024' (cinematic 16:9-ish)."),
|
|
68729
69017
|
maxCostUsd: external_exports.number().optional().describe("Fail before provider spend when estimated cost exceeds this USD cap."),
|
|
@@ -69490,7 +69778,7 @@ var init_edit = __esm({
|
|
|
69490
69778
|
imagePaths: external_exports.array(external_exports.string()).describe("Input image file path(s)"),
|
|
69491
69779
|
prompt: external_exports.string().describe("Edit instruction"),
|
|
69492
69780
|
output: external_exports.string().optional().describe("Output file path (default: edited.png)"),
|
|
69493
|
-
model: external_exports.enum(["flash", "3.1-flash", "latest", "pro"]).optional().describe("Gemini model (default: flash)"),
|
|
69781
|
+
model: external_exports.enum(["flash", "3.1-flash", "latest", "lite", "pro"]).optional().describe("Gemini model (default: flash = Nano Banana 2)"),
|
|
69494
69782
|
ratio: external_exports.string().optional().describe("Output aspect ratio"),
|
|
69495
69783
|
resolution: external_exports.string().optional().describe("Resolution: 1K, 2K, 4K (Pro only)")
|
|
69496
69784
|
}),
|
|
@@ -69570,7 +69858,7 @@ var init_edit = __esm({
|
|
|
69570
69858
|
});
|
|
69571
69859
|
|
|
69572
69860
|
// src/commands/ai-suggest-edit.ts
|
|
69573
|
-
import { readFile as readFile48, writeFile as
|
|
69861
|
+
import { readFile as readFile48, writeFile as writeFile48 } from "node:fs/promises";
|
|
69574
69862
|
import { resolve as resolve76 } from "node:path";
|
|
69575
69863
|
async function executeSuggestEdit(options) {
|
|
69576
69864
|
try {
|
|
@@ -69588,7 +69876,7 @@ async function executeSuggestEdit(options) {
|
|
|
69588
69876
|
const first = suggestions[0];
|
|
69589
69877
|
const applied = applySuggestion(project, first);
|
|
69590
69878
|
if (applied) {
|
|
69591
|
-
await
|
|
69879
|
+
await writeFile48(filePath, JSON.stringify(project.toJSON(), null, 2), "utf-8");
|
|
69592
69880
|
return {
|
|
69593
69881
|
success: true,
|
|
69594
69882
|
suggestions,
|
|
@@ -69893,7 +70181,7 @@ var init_generate2 = __esm({
|
|
|
69893
70181
|
schema: external_exports.object({
|
|
69894
70182
|
prompt: external_exports.string().describe("Description of the sound effect"),
|
|
69895
70183
|
output: external_exports.string().optional().describe("Output audio file path (default: sound-effect.mp3)"),
|
|
69896
|
-
duration: external_exports.number().optional().describe("Duration in seconds (0.5-
|
|
70184
|
+
duration: external_exports.number().optional().describe("Duration in seconds (0.5-30, default: auto)"),
|
|
69897
70185
|
promptInfluence: external_exports.number().optional().describe("Prompt influence 0-1 (default: 0.3)")
|
|
69898
70186
|
}),
|
|
69899
70187
|
async execute(args) {
|
|
@@ -69970,7 +70258,7 @@ var init_generate2 = __esm({
|
|
|
69970
70258
|
ratio: external_exports.string().optional().describe("Aspect ratio for Gemini (1:1, 16:9, 9:16, 4:3, 3:4, etc.)"),
|
|
69971
70259
|
quality: external_exports.string().optional().describe("Quality for OpenAI: standard, hd"),
|
|
69972
70260
|
count: external_exports.number().optional().describe("Number of images (default: 1)"),
|
|
69973
|
-
model: external_exports.string().optional().describe("
|
|
70261
|
+
model: external_exports.string().optional().describe("Image model. Gemini: flash (default), lite, pro. OpenAI: 2.5 (default), flare, 2, 1.5. Grok: pro")
|
|
69974
70262
|
}),
|
|
69975
70263
|
async execute(args) {
|
|
69976
70264
|
const result = await executeImageGenerate(args);
|
|
@@ -70033,9 +70321,11 @@ var init_generate2 = __esm({
|
|
|
70033
70321
|
mode: external_exports.string().optional().describe("Kling mode: std or pro"),
|
|
70034
70322
|
negative: external_exports.string().optional().describe("Negative prompt (Seedance/Kling/Veo)"),
|
|
70035
70323
|
resolution: external_exports.string().optional().describe("Resolution: 480p, 720p, 1080p, or 4k depending on provider"),
|
|
70036
|
-
veoModel: external_exports.string().optional().describe("Veo model: 3.
|
|
70324
|
+
veoModel: external_exports.string().optional().describe("Veo model: 3.1, 3.1-fast"),
|
|
70037
70325
|
runwayModel: external_exports.string().optional().describe("Runway model: gen4.5, gen4_turbo"),
|
|
70038
|
-
seedanceModel: external_exports.string().optional().describe("Seedance variant: quality
|
|
70326
|
+
seedanceModel: external_exports.string().optional().describe("Seedance variant: quality (2.0), fast, or 2.5 (fal.ai only)"),
|
|
70327
|
+
grokModel: external_exports.string().optional().describe("Grok video model: 1.5 (default), lite, classic"),
|
|
70328
|
+
klingModel: external_exports.string().optional().describe("Kling model: v3 (default), v2.6, v2.5-turbo"),
|
|
70039
70329
|
generateAudio: external_exports.boolean().optional().describe("Generate native synchronized audio when supported"),
|
|
70040
70330
|
output: external_exports.string().optional().describe("Output file path (downloads video)"),
|
|
70041
70331
|
wait: external_exports.boolean().optional().describe("Wait for completion (default: true)")
|
|
@@ -70107,7 +70397,7 @@ var init_generate2 = __esm({
|
|
|
70107
70397
|
prompt: external_exports.string().optional().describe("Continuation prompt"),
|
|
70108
70398
|
duration: external_exports.number().optional().describe("Duration in seconds"),
|
|
70109
70399
|
negative: external_exports.string().optional().describe("Negative prompt (Kling)"),
|
|
70110
|
-
veoModel: external_exports.string().optional().describe("Veo model: 3.
|
|
70400
|
+
veoModel: external_exports.string().optional().describe("Veo model: 3.1, 3.1-fast"),
|
|
70111
70401
|
output: external_exports.string().optional().describe("Output file path"),
|
|
70112
70402
|
wait: external_exports.boolean().optional().describe("Wait for completion (default: true)")
|
|
70113
70403
|
}),
|
|
@@ -70145,7 +70435,7 @@ var init_generate2 = __esm({
|
|
|
70145
70435
|
|
|
70146
70436
|
// src/tools/manifest/storyboard.ts
|
|
70147
70437
|
import { existsSync as existsSync58 } from "node:fs";
|
|
70148
|
-
import { readFile as readFile49, writeFile as
|
|
70438
|
+
import { readFile as readFile49, writeFile as writeFile49 } from "node:fs/promises";
|
|
70149
70439
|
import { resolve as resolve78 } from "node:path";
|
|
70150
70440
|
async function readStoryboard2(projectDir) {
|
|
70151
70441
|
const path2 = resolve78(projectDir, "STORYBOARD.md");
|
|
@@ -70162,6 +70452,7 @@ var init_storyboard2 = __esm({
|
|
|
70162
70452
|
init_storyboard_edit();
|
|
70163
70453
|
init_storyboard_revise();
|
|
70164
70454
|
init_build_plan();
|
|
70455
|
+
init_build_video_providers();
|
|
70165
70456
|
PROJECT_DIR_DESCRIPTION3 = "Project directory. Defaults to the surface's cwd; in MCP hosts, relative paths resolve under the configured server workspace.";
|
|
70166
70457
|
projectDirSchema = external_exports.object({
|
|
70167
70458
|
projectDir: external_exports.string().optional().describe(PROJECT_DIR_DESCRIPTION3)
|
|
@@ -70277,7 +70568,7 @@ var init_storyboard2 = __esm({
|
|
|
70277
70568
|
value,
|
|
70278
70569
|
unset: args.unset
|
|
70279
70570
|
});
|
|
70280
|
-
await
|
|
70571
|
+
await writeFile49(file.path, next, "utf-8");
|
|
70281
70572
|
return {
|
|
70282
70573
|
success: true,
|
|
70283
70574
|
data: { beat: args.beat, key: args.key },
|
|
@@ -70309,7 +70600,7 @@ var init_storyboard2 = __esm({
|
|
|
70309
70600
|
beatId: args.beat,
|
|
70310
70601
|
afterBeatId: args.after
|
|
70311
70602
|
});
|
|
70312
|
-
await
|
|
70603
|
+
await writeFile49(file.path, next, "utf-8");
|
|
70313
70604
|
return {
|
|
70314
70605
|
success: true,
|
|
70315
70606
|
data: { beat: args.beat, after: args.after },
|
|
@@ -70374,7 +70665,7 @@ var init_storyboard2 = __esm({
|
|
|
70374
70665
|
imageProvider: external_exports.string().optional().describe("Image provider override."),
|
|
70375
70666
|
imageQuality: external_exports.enum(["standard", "hd"]).optional().describe("Image quality override."),
|
|
70376
70667
|
imageSize: external_exports.string().optional().describe("Image size override."),
|
|
70377
|
-
videoProvider: external_exports.enum(
|
|
70668
|
+
videoProvider: external_exports.enum(BUILD_VIDEO_PROVIDERS).optional().describe("Video provider override."),
|
|
70378
70669
|
musicProvider: external_exports.enum(["elevenlabs", "replicate"]).optional().describe("Music provider override."),
|
|
70379
70670
|
composer: external_exports.enum(["claude", "openai", "gemini"]).optional().describe("Composer provider override."),
|
|
70380
70671
|
force: external_exports.boolean().optional().describe("Plan regeneration even when outputs exist.")
|
|
@@ -70472,7 +70763,7 @@ var init_design = __esm({
|
|
|
70472
70763
|
});
|
|
70473
70764
|
|
|
70474
70765
|
// src/tools/manifest/remix.ts
|
|
70475
|
-
import { writeFile as
|
|
70766
|
+
import { writeFile as writeFile50 } from "node:fs/promises";
|
|
70476
70767
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
70477
70768
|
import { join as join31 } from "node:path";
|
|
70478
70769
|
var pipelineHighlightsTool, pipelineAutoShortsTool, pipelineRunTool, remixTools;
|
|
@@ -70588,7 +70879,7 @@ var init_remix = __esm({
|
|
|
70588
70879
|
let tempPath;
|
|
70589
70880
|
if (args.pipelineYaml) {
|
|
70590
70881
|
tempPath = join31(tmpdir4(), `vibe-mcp-pipeline-${Date.now()}.yaml`);
|
|
70591
|
-
await
|
|
70882
|
+
await writeFile50(tempPath, args.pipelineYaml, "utf-8");
|
|
70592
70883
|
resolvedPath = tempPath;
|
|
70593
70884
|
}
|
|
70594
70885
|
try {
|
|
@@ -70733,7 +71024,7 @@ var init_detect2 = __esm({
|
|
|
70733
71024
|
});
|
|
70734
71025
|
|
|
70735
71026
|
// src/tools/manifest/_project-io.ts
|
|
70736
|
-
import { readFile as readFile51, writeFile as
|
|
71027
|
+
import { readFile as readFile51, writeFile as writeFile51 } from "node:fs/promises";
|
|
70737
71028
|
async function loadProject2(projectPath, cwd) {
|
|
70738
71029
|
const absPath = await resolveTimelineFile(projectPath, cwd);
|
|
70739
71030
|
const content = await readFile51(absPath, "utf-8");
|
|
@@ -70741,7 +71032,7 @@ async function loadProject2(projectPath, cwd) {
|
|
|
70741
71032
|
return { project: Project.fromJSON(data), absPath };
|
|
70742
71033
|
}
|
|
70743
71034
|
async function saveProject(absPath, project) {
|
|
70744
|
-
await
|
|
71035
|
+
await writeFile51(absPath, JSON.stringify(project.toJSON(), null, 2), "utf-8");
|
|
70745
71036
|
}
|
|
70746
71037
|
var init_project_io = __esm({
|
|
70747
71038
|
"src/tools/manifest/_project-io.ts"() {
|
|
@@ -70752,7 +71043,7 @@ var init_project_io = __esm({
|
|
|
70752
71043
|
});
|
|
70753
71044
|
|
|
70754
71045
|
// src/tools/manifest/timeline.ts
|
|
70755
|
-
import { mkdir as
|
|
71046
|
+
import { mkdir as mkdir30, writeFile as writeFile52 } from "node:fs/promises";
|
|
70756
71047
|
import { basename as basename23, resolve as resolve80 } from "node:path";
|
|
70757
71048
|
var MEDIA_TYPES, timelineCreateTool, timelineInfoTool, timelineAddSourceTool, timelineAddClipTool, timelineSplitClipTool, timelineTrimClipTool, timelineMoveClipTool, timelineDeleteClipTool, timelineDuplicateClipTool, timelineAddEffectTool, timelineAddTrackTool, timelineListTool, timelineTools;
|
|
70758
71049
|
var init_timeline = __esm({
|
|
@@ -70799,10 +71090,10 @@ var init_timeline = __esm({
|
|
|
70799
71090
|
outputPath = resolve80(ctx.workingDirectory, args.outputPath);
|
|
70800
71091
|
} else {
|
|
70801
71092
|
const dirPath = resolve80(ctx.workingDirectory, args.name);
|
|
70802
|
-
await
|
|
71093
|
+
await mkdir30(dirPath, { recursive: true });
|
|
70803
71094
|
outputPath = resolve80(dirPath, TIMELINE_FILENAME);
|
|
70804
71095
|
}
|
|
70805
|
-
await
|
|
71096
|
+
await writeFile52(outputPath, JSON.stringify(project.toJSON(), null, 2), "utf-8");
|
|
70806
71097
|
return {
|
|
70807
71098
|
success: true,
|
|
70808
71099
|
data: { name: projectName, outputPath },
|
|
@@ -71206,7 +71497,7 @@ var init_project_list = __esm({
|
|
|
71206
71497
|
|
|
71207
71498
|
// src/tools/manifest/project.ts
|
|
71208
71499
|
import { resolve as resolve82 } from "node:path";
|
|
71209
|
-
import { writeFile as
|
|
71500
|
+
import { writeFile as writeFile53 } from "node:fs/promises";
|
|
71210
71501
|
var projectListTool, projectCreateTool, projectInfoTool, projectTools;
|
|
71211
71502
|
var init_project2 = __esm({
|
|
71212
71503
|
"src/tools/manifest/project.ts"() {
|
|
@@ -71270,7 +71561,7 @@ var init_project2 = __esm({
|
|
|
71270
71561
|
const outputPath = resolve82(ctx.workingDirectory, args.outputPath ?? `${args.name}.vibe.json`);
|
|
71271
71562
|
const project = new Project(args.name);
|
|
71272
71563
|
if (args.fps) project.setFrameRate(args.fps);
|
|
71273
|
-
await
|
|
71564
|
+
await writeFile53(outputPath, JSON.stringify(project.toJSON(), null, 2), "utf-8");
|
|
71274
71565
|
return {
|
|
71275
71566
|
success: true,
|
|
71276
71567
|
data: { name: args.name, outputPath },
|
|
@@ -72005,8 +72296,8 @@ var init_export2 = __esm({
|
|
|
72005
72296
|
});
|
|
72006
72297
|
|
|
72007
72298
|
// src/tools/manifest/agent-only.ts
|
|
72008
|
-
import { readFile as readFile54, writeFile as
|
|
72009
|
-
import { resolve as resolve85, join as join33, basename as basename24, extname as
|
|
72299
|
+
import { readFile as readFile54, writeFile as writeFile54, readdir as readdir9, stat as stat10, access as access8, unlink as unlink2 } from "node:fs/promises";
|
|
72300
|
+
import { resolve as resolve85, join as join33, basename as basename24, extname as extname16 } from "node:path";
|
|
72010
72301
|
function matchPattern(filename, pattern) {
|
|
72011
72302
|
const regex2 = new RegExp(
|
|
72012
72303
|
"^" + pattern.replace(/\./g, "\\.").replace(/\*/g, ".*").replace(/\?/g, ".") + "$",
|
|
@@ -72025,7 +72316,7 @@ function formatSize(bytes) {
|
|
|
72025
72316
|
return `${size.toFixed(1)}${units2[unit]}`;
|
|
72026
72317
|
}
|
|
72027
72318
|
function detectMediaType4(filePath) {
|
|
72028
|
-
const ext =
|
|
72319
|
+
const ext = extname16(filePath).toLowerCase();
|
|
72029
72320
|
if ([".mp4", ".mov", ".avi", ".mkv", ".webm", ".m4v"].includes(ext)) return "video";
|
|
72030
72321
|
if ([".mp3", ".wav", ".aac", ".flac", ".ogg", ".m4a"].includes(ext)) return "audio";
|
|
72031
72322
|
if ([".jpg", ".jpeg", ".png", ".gif", ".webp", ".bmp"].includes(ext)) return "image";
|
|
@@ -72052,7 +72343,7 @@ function isMediaFile2(filePath) {
|
|
|
72052
72343
|
".webp",
|
|
72053
72344
|
".bmp"
|
|
72054
72345
|
];
|
|
72055
|
-
return mediaExts.includes(
|
|
72346
|
+
return mediaExts.includes(extname16(filePath).toLowerCase());
|
|
72056
72347
|
}
|
|
72057
72348
|
async function getMediaDuration2(filePath) {
|
|
72058
72349
|
try {
|
|
@@ -72145,7 +72436,7 @@ var init_agent_only = __esm({
|
|
|
72145
72436
|
async execute(args, ctx) {
|
|
72146
72437
|
try {
|
|
72147
72438
|
const absPath = resolve85(ctx.workingDirectory, args.path);
|
|
72148
|
-
await
|
|
72439
|
+
await writeFile54(absPath, args.content, "utf-8");
|
|
72149
72440
|
return { success: true, data: { bytes: args.content.length }, humanLines: [`File written: ${args.path} (${formatSize(args.content.length)})`] };
|
|
72150
72441
|
} catch (error) {
|
|
72151
72442
|
return { success: false, error: `Failed to write file: ${error instanceof Error ? error.message : String(error)}` };
|
|
@@ -72208,7 +72499,7 @@ var init_agent_only = __esm({
|
|
|
72208
72499
|
if (entry.isDirectory() && recursive) {
|
|
72209
72500
|
await scanDir(entryPath);
|
|
72210
72501
|
} else if (entry.isFile()) {
|
|
72211
|
-
const ext =
|
|
72502
|
+
const ext = extname16(entry.name).toLowerCase();
|
|
72212
72503
|
const matchesFilter = !filterExts || filterExts.includes(ext);
|
|
72213
72504
|
if (matchesFilter && isMediaFile2(entryPath)) mediaFiles.push(entryPath);
|
|
72214
72505
|
}
|
|
@@ -72231,7 +72522,7 @@ var init_agent_only = __esm({
|
|
|
72231
72522
|
const source = project.addSource({ name: mediaName, type: mediaType, url: mediaFile, duration });
|
|
72232
72523
|
addedSources.push({ id: source.id, name: mediaName, type: mediaType });
|
|
72233
72524
|
}
|
|
72234
|
-
await
|
|
72525
|
+
await writeFile54(filePath, JSON.stringify(project.toJSON(), null, 2), "utf-8");
|
|
72235
72526
|
return {
|
|
72236
72527
|
success: true,
|
|
72237
72528
|
data: { count: addedSources.length, sources: addedSources },
|
|
@@ -72301,7 +72592,7 @@ var init_agent_only = __esm({
|
|
|
72301
72592
|
createdClips.push({ id: clip.id, sourceName: source.name, startTime: currentTime, duration: source.duration });
|
|
72302
72593
|
currentTime += source.duration + gap;
|
|
72303
72594
|
}
|
|
72304
|
-
await
|
|
72595
|
+
await writeFile54(filePath, JSON.stringify(project.toJSON(), null, 2), "utf-8");
|
|
72305
72596
|
const totalDuration = currentTime - gap - startTime;
|
|
72306
72597
|
return {
|
|
72307
72598
|
success: true,
|
|
@@ -72364,7 +72655,7 @@ var init_agent_only = __esm({
|
|
|
72364
72655
|
});
|
|
72365
72656
|
if (effect) appliedEffects.push({ clipId: clip.id, effectId: effect.id });
|
|
72366
72657
|
}
|
|
72367
|
-
await
|
|
72658
|
+
await writeFile54(filePath, JSON.stringify(project.toJSON(), null, 2), "utf-8");
|
|
72368
72659
|
return {
|
|
72369
72660
|
success: true,
|
|
72370
72661
|
data: { applied: appliedEffects.length, effectType: args.effectType },
|
|
@@ -72433,7 +72724,7 @@ var init_agent_only = __esm({
|
|
|
72433
72724
|
removed.sources++;
|
|
72434
72725
|
}
|
|
72435
72726
|
}
|
|
72436
|
-
await
|
|
72727
|
+
await writeFile54(filePath, JSON.stringify(project.toJSON(), null, 2), "utf-8");
|
|
72437
72728
|
const parts = [];
|
|
72438
72729
|
if (removed.clips > 0) parts.push(`${removed.clips} clips`);
|
|
72439
72730
|
if (removed.tracks > 0) parts.push(`${removed.tracks} tracks`);
|
|
@@ -72484,7 +72775,7 @@ var init_agent_only = __esm({
|
|
|
72484
72775
|
project.setFrameRate(args.fps);
|
|
72485
72776
|
updates.push(`Frame Rate: ${args.fps} fps`);
|
|
72486
72777
|
}
|
|
72487
|
-
await
|
|
72778
|
+
await writeFile54(filePath, JSON.stringify(project.toJSON(), null, 2), "utf-8");
|
|
72488
72779
|
return {
|
|
72489
72780
|
success: true,
|
|
72490
72781
|
data: { updates },
|
|
@@ -72854,7 +73145,7 @@ Audio:`);
|
|
|
72854
73145
|
} else {
|
|
72855
73146
|
const tempList = resolve85(ctx.workingDirectory, `concat-list-${Date.now()}.txt`);
|
|
72856
73147
|
const listContent = args.inputs.map((i) => `file '${resolve85(ctx.workingDirectory, i)}'`).join("\n");
|
|
72857
|
-
await
|
|
73148
|
+
await writeFile54(tempList, listContent, "utf-8");
|
|
72858
73149
|
try {
|
|
72859
73150
|
await execSafe(
|
|
72860
73151
|
"ffmpeg",
|
|
@@ -73297,7 +73588,7 @@ init_source();
|
|
|
73297
73588
|
// package.json
|
|
73298
73589
|
var package_default = {
|
|
73299
73590
|
name: "@vibeframe/cli",
|
|
73300
|
-
version: "0.115.
|
|
73591
|
+
version: "0.115.3",
|
|
73301
73592
|
description: "Frontier AI video generation for coding agents - Seedance, Runway, Veo, and Kling on your own keys, behind a hard cost cap",
|
|
73302
73593
|
private: false,
|
|
73303
73594
|
license: "MIT",
|
|
@@ -74401,7 +74692,7 @@ init_validate();
|
|
|
74401
74692
|
init_cost_tier();
|
|
74402
74693
|
init_scene_inspect();
|
|
74403
74694
|
init_render_inspect();
|
|
74404
|
-
import { readFile as readFile29, writeFile as
|
|
74695
|
+
import { readFile as readFile29, writeFile as writeFile32 } from "node:fs/promises";
|
|
74405
74696
|
import { resolve as resolve40 } from "node:path";
|
|
74406
74697
|
var VALID_RENDER_AI_MODELS = [
|
|
74407
74698
|
"flash",
|
|
@@ -74716,7 +75007,7 @@ inspectCommand.command("suggest").description("Get AI edit suggestions using Gem
|
|
|
74716
75007
|
const sug = suggestions[0];
|
|
74717
75008
|
const applied = applySuggestion(project, sug);
|
|
74718
75009
|
if (applied) {
|
|
74719
|
-
await
|
|
75010
|
+
await writeFile32(filePath, JSON.stringify(project.toJSON(), null, 2), "utf-8");
|
|
74720
75011
|
spinner2.succeed(source_default.green("Suggestion applied"));
|
|
74721
75012
|
} else {
|
|
74722
75013
|
spinner2.warn(source_default.yellow("Could not apply suggestion automatically"));
|
|
@@ -74741,8 +75032,8 @@ init_cost_tier();
|
|
|
74741
75032
|
init_ai_helpers();
|
|
74742
75033
|
init_output();
|
|
74743
75034
|
init_validate();
|
|
74744
|
-
import { resolve as resolve41, dirname as
|
|
74745
|
-
import { readFile as readFile30, writeFile as
|
|
75035
|
+
import { resolve as resolve41, dirname as dirname14, basename as basename12, extname as extname9 } from "node:path";
|
|
75036
|
+
import { readFile as readFile30, writeFile as writeFile33 } from "node:fs/promises";
|
|
74746
75037
|
import { existsSync as existsSync35 } from "node:fs";
|
|
74747
75038
|
var audioCommand = new Command("audio").alias("au").description("Audio operations (transcribe, dub, duck, isolate, voice clone)").addHelpText(
|
|
74748
75039
|
"after",
|
|
@@ -74820,7 +75111,7 @@ audioCommand.command("transcribe").description("Transcribe audio using Whisper")
|
|
|
74820
75111
|
const outputPath = resolve41(process.cwd(), options.output);
|
|
74821
75112
|
const format = detectFormat(options.output, options.format);
|
|
74822
75113
|
const content = formatTranscript(result, format);
|
|
74823
|
-
await
|
|
75114
|
+
await writeFile33(outputPath, content, "utf-8");
|
|
74824
75115
|
console.log(source_default.green(`Saved ${format.toUpperCase()} to: ${outputPath}`));
|
|
74825
75116
|
}
|
|
74826
75117
|
} catch (error) {
|
|
@@ -74894,7 +75185,7 @@ audioCommand.command("isolate").description("Isolate vocals from audio using Ele
|
|
|
74894
75185
|
exitWithError(apiError(result.error || "Audio isolation failed", true));
|
|
74895
75186
|
}
|
|
74896
75187
|
const outputPath = resolve41(process.cwd(), options.output);
|
|
74897
|
-
await
|
|
75188
|
+
await writeFile33(outputPath, result.audioBuffer);
|
|
74898
75189
|
spinner2.succeed(source_default.green("Vocals isolated"));
|
|
74899
75190
|
if (isJsonMode()) {
|
|
74900
75191
|
outputSuccess({
|
|
@@ -75030,11 +75321,11 @@ audioCommand.command("dub").description("Dub audio/video to another language (tr
|
|
|
75030
75321
|
const anthropicKey = await requireApiKey("ANTHROPIC_API_KEY", "Anthropic");
|
|
75031
75322
|
const elevenlabsKey = options.analyzeOnly ? await getApiKey("ELEVENLABS_API_KEY", "ElevenLabs", void 0) : await requireApiKey("ELEVENLABS_API_KEY", "ElevenLabs");
|
|
75032
75323
|
const spinner2 = ora("Extracting audio...").start();
|
|
75033
|
-
const ext =
|
|
75324
|
+
const ext = extname9(absPath).toLowerCase();
|
|
75034
75325
|
const isVideo = [".mp4", ".mov", ".avi", ".mkv", ".webm"].includes(ext);
|
|
75035
75326
|
let audioPath = absPath;
|
|
75036
75327
|
if (isVideo) {
|
|
75037
|
-
const tempAudioPath = resolve41(
|
|
75328
|
+
const tempAudioPath = resolve41(dirname14(absPath), `temp-audio-${Date.now()}.mp3`);
|
|
75038
75329
|
try {
|
|
75039
75330
|
execSafeSync("ffmpeg", ["-i", absPath, "-vn", "-acodec", "mp3", "-y", tempAudioPath]);
|
|
75040
75331
|
audioPath = tempAudioPath;
|
|
@@ -75146,7 +75437,7 @@ ${segmentTexts}`,
|
|
|
75146
75437
|
translated: translatedSegments[i]?.text || s.text
|
|
75147
75438
|
}))
|
|
75148
75439
|
};
|
|
75149
|
-
await
|
|
75440
|
+
await writeFile33(timingPath, JSON.stringify(timingData, null, 2));
|
|
75150
75441
|
console.log(`Timing saved to: ${source_default.bold(timingPath)}`);
|
|
75151
75442
|
}
|
|
75152
75443
|
return;
|
|
@@ -75170,13 +75461,13 @@ ${segmentTexts}`,
|
|
|
75170
75461
|
}
|
|
75171
75462
|
spinner2.text = "Combining audio...";
|
|
75172
75463
|
const combinedBuffer = Buffer.concat(dubbedAudioBuffers.map((a) => a.buffer));
|
|
75173
|
-
const outputExt = isVideo ? ".mp3" :
|
|
75464
|
+
const outputExt = isVideo ? ".mp3" : extname9(absPath);
|
|
75174
75465
|
const defaultOutputPath2 = resolve41(
|
|
75175
|
-
|
|
75176
|
-
`${basename12(absPath,
|
|
75466
|
+
dirname14(absPath),
|
|
75467
|
+
`${basename12(absPath, extname9(absPath))}-${options.language}${outputExt}`
|
|
75177
75468
|
);
|
|
75178
75469
|
const finalOutputPath = resolve41(process.cwd(), options.output || defaultOutputPath2);
|
|
75179
|
-
await
|
|
75470
|
+
await writeFile33(finalOutputPath, combinedBuffer);
|
|
75180
75471
|
spinner2.succeed(source_default.green("Dubbing complete"));
|
|
75181
75472
|
if (isJsonMode()) {
|
|
75182
75473
|
outputSuccess({
|
|
@@ -75735,7 +76026,7 @@ init_esm();
|
|
|
75735
76026
|
init_source();
|
|
75736
76027
|
init_ora();
|
|
75737
76028
|
import { stat as stat7 } from "node:fs/promises";
|
|
75738
|
-
import { resolve as resolve45, extname as
|
|
76029
|
+
import { resolve as resolve45, extname as extname11, basename as basename16 } from "node:path";
|
|
75739
76030
|
|
|
75740
76031
|
// ../../node_modules/.pnpm/music-metadata@11.11.1/node_modules/music-metadata/lib/index.js
|
|
75741
76032
|
init_lib();
|
|
@@ -79612,7 +79903,7 @@ mediaCommand.command("info").description("Get media file information").argument(
|
|
|
79612
79903
|
const spinner2 = ora("Analyzing media...").start();
|
|
79613
79904
|
try {
|
|
79614
79905
|
const filePath = resolve45(process.cwd(), file);
|
|
79615
|
-
const ext =
|
|
79906
|
+
const ext = extname11(filePath).toLowerCase();
|
|
79616
79907
|
const fileName = basename16(filePath);
|
|
79617
79908
|
const fileStat = await stat7(filePath);
|
|
79618
79909
|
const mediaType = detectMediaType2(ext);
|
|
@@ -79753,11 +80044,11 @@ init_ora();
|
|
|
79753
80044
|
init_engine();
|
|
79754
80045
|
init_output();
|
|
79755
80046
|
init_cost_tier();
|
|
79756
|
-
import { readFile as readFile32, writeFile as
|
|
79757
|
-
import { resolve as resolve46, basename as basename17, extname as
|
|
80047
|
+
import { readFile as readFile32, writeFile as writeFile36, readdir as readdir7 } from "node:fs/promises";
|
|
80048
|
+
import { resolve as resolve46, basename as basename17, extname as extname12, join as join19 } from "node:path";
|
|
79758
80049
|
var batchCommand = new Command("batch").description("Batch operations for processing multiple items");
|
|
79759
80050
|
function detectMediaType3(filePath) {
|
|
79760
|
-
const ext =
|
|
80051
|
+
const ext = extname12(filePath).toLowerCase();
|
|
79761
80052
|
const videoExts = [".mp4", ".mov", ".avi", ".mkv", ".webm", ".m4v"];
|
|
79762
80053
|
const audioExts = [".mp3", ".wav", ".aac", ".flac", ".ogg", ".m4a"];
|
|
79763
80054
|
const imageExts = [".jpg", ".jpeg", ".png", ".gif", ".webp", ".bmp"];
|
|
@@ -79767,7 +80058,7 @@ function detectMediaType3(filePath) {
|
|
|
79767
80058
|
return "video";
|
|
79768
80059
|
}
|
|
79769
80060
|
function isMediaFile(filePath) {
|
|
79770
|
-
const ext =
|
|
80061
|
+
const ext = extname12(filePath).toLowerCase();
|
|
79771
80062
|
const mediaExts = [
|
|
79772
80063
|
".mp4",
|
|
79773
80064
|
".mov",
|
|
@@ -79825,7 +80116,7 @@ batchCommand.command("import").description("Import multiple media files from a d
|
|
|
79825
80116
|
if (entry.isDirectory() && options.recursive) {
|
|
79826
80117
|
await scanDir(entryPath);
|
|
79827
80118
|
} else if (entry.isFile()) {
|
|
79828
|
-
const ext =
|
|
80119
|
+
const ext = extname12(entry.name).toLowerCase();
|
|
79829
80120
|
const matchesFilter = !filterExts || filterExts.includes(ext);
|
|
79830
80121
|
if (matchesFilter && isMediaFile(entryPath)) {
|
|
79831
80122
|
mediaFiles.push(entryPath);
|
|
@@ -79854,7 +80145,7 @@ batchCommand.command("import").description("Import multiple media files from a d
|
|
|
79854
80145
|
});
|
|
79855
80146
|
addedSources.push(source.id);
|
|
79856
80147
|
}
|
|
79857
|
-
await
|
|
80148
|
+
await writeFile36(filePath, JSON.stringify(project.toJSON(), null, 2), "utf-8");
|
|
79858
80149
|
spinner2.succeed(source_default.green(`Imported ${addedSources.length} media files`));
|
|
79859
80150
|
console.log();
|
|
79860
80151
|
for (const file of mediaFiles) {
|
|
@@ -79929,7 +80220,7 @@ batchCommand.command("concat").description("Concatenate multiple sources into se
|
|
|
79929
80220
|
addedClips.push(clip.id);
|
|
79930
80221
|
currentTime += source.duration + gap;
|
|
79931
80222
|
}
|
|
79932
|
-
await
|
|
80223
|
+
await writeFile36(filePath, JSON.stringify(project.toJSON(), null, 2), "utf-8");
|
|
79933
80224
|
spinner2.succeed(source_default.green(`Created ${addedClips.length} clips`));
|
|
79934
80225
|
console.log();
|
|
79935
80226
|
console.log(source_default.dim(" Total duration:"), `${currentTime - gap}s`);
|
|
@@ -80000,7 +80291,7 @@ batchCommand.command("apply-effect").description("Apply an effect to multiple cl
|
|
|
80000
80291
|
appliedCount++;
|
|
80001
80292
|
}
|
|
80002
80293
|
}
|
|
80003
|
-
await
|
|
80294
|
+
await writeFile36(filePath, JSON.stringify(project.toJSON(), null, 2), "utf-8");
|
|
80004
80295
|
spinner2.succeed(
|
|
80005
80296
|
source_default.green(`Applied ${effectType} to ${appliedCount} clips`)
|
|
80006
80297
|
);
|
|
@@ -80062,7 +80353,7 @@ batchCommand.command("remove-clips").description("Remove multiple clips from the
|
|
|
80062
80353
|
removedCount++;
|
|
80063
80354
|
}
|
|
80064
80355
|
}
|
|
80065
|
-
await
|
|
80356
|
+
await writeFile36(filePath, JSON.stringify(project.toJSON(), null, 2), "utf-8");
|
|
80066
80357
|
spinner2.succeed(source_default.green(`Removed ${removedCount} clips`));
|
|
80067
80358
|
console.log();
|
|
80068
80359
|
} catch (error) {
|
|
@@ -80421,7 +80712,7 @@ var AI_FEATURES = [
|
|
|
80421
80712
|
{
|
|
80422
80713
|
label: "Images",
|
|
80423
80714
|
desc: "generate + edit",
|
|
80424
|
-
defaultProvider: "OpenAI gpt-image-2
|
|
80715
|
+
defaultProvider: "OpenAI gpt-image-2.5-sunburst",
|
|
80425
80716
|
alsoAvailable: "Gemini Nano Banana, Grok Imagine",
|
|
80426
80717
|
keyHint: "1 key",
|
|
80427
80718
|
keys: [
|
|
@@ -80430,19 +80721,19 @@ var AI_FEATURES = [
|
|
|
80430
80721
|
envVar: "OPENAI_API_KEY",
|
|
80431
80722
|
name: "OpenAI",
|
|
80432
80723
|
url: "https://platform.openai.com/api-keys",
|
|
80433
|
-
what: "gpt-image-2 image generation + editing (also Whisper, Agent)"
|
|
80724
|
+
what: "gpt-image-2.5 image generation + editing (also Whisper, Agent)"
|
|
80434
80725
|
}
|
|
80435
80726
|
],
|
|
80436
80727
|
providerChoices: [
|
|
80437
80728
|
{
|
|
80438
|
-
label: "OpenAI gpt-image-2",
|
|
80729
|
+
label: "OpenAI gpt-image-2.5",
|
|
80439
80730
|
desc: "recommended default, image generation + editing",
|
|
80440
80731
|
key: {
|
|
80441
80732
|
configKey: "openai",
|
|
80442
80733
|
envVar: "OPENAI_API_KEY",
|
|
80443
80734
|
name: "OpenAI",
|
|
80444
80735
|
url: "https://platform.openai.com/api-keys",
|
|
80445
|
-
what: "gpt-image-2 image generation + editing (also Whisper, Agent)"
|
|
80736
|
+
what: "gpt-image-2.5 image generation + editing (also Whisper, Agent)"
|
|
80446
80737
|
},
|
|
80447
80738
|
defaultFor: { kind: "image", value: "openai" }
|
|
80448
80739
|
},
|
|
@@ -80943,7 +81234,7 @@ async function runSetupWizard(fullSetup = false, scope = "user") {
|
|
|
80943
81234
|
envVar: "OPENAI_API_KEY",
|
|
80944
81235
|
name: "OpenAI",
|
|
80945
81236
|
url: "https://platform.openai.com/api-keys",
|
|
80946
|
-
what: "gpt-image-2 image generation
|
|
81237
|
+
what: "gpt-image-2.5 image generation + Whisper word-level transcribe"
|
|
80947
81238
|
},
|
|
80948
81239
|
{
|
|
80949
81240
|
configKey: "fal",
|
|
@@ -81257,9 +81548,9 @@ async function runCustomSetup(config2, scope = "user", opts = {}) {
|
|
|
81257
81548
|
const providers = ["claude", "openai", "gemini", "xai", "openrouter", "evolink", "ollama"];
|
|
81258
81549
|
const providerDescriptions = {
|
|
81259
81550
|
claude: "Best reasoning, most capable for complex tasks",
|
|
81260
|
-
openai: "GPT-5
|
|
81551
|
+
openai: "GPT-5.4 mini, reliable and fast, good default",
|
|
81261
81552
|
gemini: "Google AI, strong multimodal understanding",
|
|
81262
|
-
xai: "Grok 4.
|
|
81553
|
+
xai: "Grok 4.3, 1M context, inexpensive tool calling",
|
|
81263
81554
|
openrouter: "300+ models via one API key (Claude, GPT, Gemini, Llama, etc.)",
|
|
81264
81555
|
evolink: "GPT-5, Claude, Gemini, DeepSeek & more via one key",
|
|
81265
81556
|
ollama: "Free, local, no API key - offline capable (default: llama3.2)"
|
|
@@ -81554,8 +81845,8 @@ function pickCompletionHint(shellPath) {
|
|
|
81554
81845
|
init_esm();
|
|
81555
81846
|
init_source();
|
|
81556
81847
|
import { existsSync as existsSync41 } from "node:fs";
|
|
81557
|
-
import { mkdir as
|
|
81558
|
-
import { basename as basename19, dirname as
|
|
81848
|
+
import { mkdir as mkdir23, readFile as readFile36, writeFile as writeFile39 } from "node:fs/promises";
|
|
81849
|
+
import { basename as basename19, dirname as dirname18, resolve as resolve50, sep } from "node:path";
|
|
81559
81850
|
init_scene_project();
|
|
81560
81851
|
init_visual_styles();
|
|
81561
81852
|
|
|
@@ -81722,9 +82013,9 @@ init_install_skill();
|
|
|
81722
82013
|
|
|
81723
82014
|
// src/commands/_shared/host-integration.ts
|
|
81724
82015
|
import { existsSync as existsSync40 } from "node:fs";
|
|
81725
|
-
import { mkdir as
|
|
82016
|
+
import { mkdir as mkdir22, readFile as readFile35, writeFile as writeFile38 } from "node:fs/promises";
|
|
81726
82017
|
import { homedir as homedir7 } from "node:os";
|
|
81727
|
-
import { dirname as
|
|
82018
|
+
import { dirname as dirname17, join as join21, resolve as resolve49 } from "node:path";
|
|
81728
82019
|
var HOST_SELECTIONS = [
|
|
81729
82020
|
"codex",
|
|
81730
82021
|
"claude",
|
|
@@ -81928,15 +82219,15 @@ async function mergeMcpJson(configPath, opts) {
|
|
|
81928
82219
|
...mcpServers,
|
|
81929
82220
|
vibeframe: opts.server
|
|
81930
82221
|
};
|
|
81931
|
-
await
|
|
82222
|
+
await mkdir22(dirname17(configPath), { recursive: true });
|
|
81932
82223
|
if (exists && opts.backup) {
|
|
81933
|
-
await
|
|
82224
|
+
await writeFile38(
|
|
81934
82225
|
`${configPath}.bak-${timestamp()}`,
|
|
81935
82226
|
await readFile35(configPath, "utf-8"),
|
|
81936
82227
|
"utf-8"
|
|
81937
82228
|
);
|
|
81938
82229
|
}
|
|
81939
|
-
await
|
|
82230
|
+
await writeFile38(configPath, JSON.stringify(root, null, 2) + "\n", "utf-8");
|
|
81940
82231
|
return {
|
|
81941
82232
|
path: configPath,
|
|
81942
82233
|
status: "merged",
|
|
@@ -81950,15 +82241,15 @@ async function mergeMcpJson(configPath, opts) {
|
|
|
81950
82241
|
};
|
|
81951
82242
|
}
|
|
81952
82243
|
root.mcpServers = { ...mcpServers, vibeframe: opts.server };
|
|
81953
|
-
await
|
|
82244
|
+
await mkdir22(dirname17(configPath), { recursive: true });
|
|
81954
82245
|
if (exists && opts.backup) {
|
|
81955
|
-
await
|
|
82246
|
+
await writeFile38(
|
|
81956
82247
|
`${configPath}.bak-${timestamp()}`,
|
|
81957
82248
|
await readFile35(configPath, "utf-8"),
|
|
81958
82249
|
"utf-8"
|
|
81959
82250
|
);
|
|
81960
82251
|
}
|
|
81961
|
-
await
|
|
82252
|
+
await writeFile38(configPath, JSON.stringify(root, null, 2) + "\n", "utf-8");
|
|
81962
82253
|
return { path: configPath, status: exists ? "merged" : "wrote" };
|
|
81963
82254
|
}
|
|
81964
82255
|
async function mergeCodexToml(configPath, opts) {
|
|
@@ -81966,8 +82257,8 @@ async function mergeCodexToml(configPath, opts) {
|
|
|
81966
82257
|
const block = `${CODEX_MANAGED_START}
|
|
81967
82258
|
${CODEX_MCP_BLOCK}${CODEX_MANAGED_END}`;
|
|
81968
82259
|
if (!exists) {
|
|
81969
|
-
await
|
|
81970
|
-
await
|
|
82260
|
+
await mkdir22(dirname17(configPath), { recursive: true });
|
|
82261
|
+
await writeFile38(
|
|
81971
82262
|
configPath,
|
|
81972
82263
|
`#:schema https://developers.openai.com/codex/config-schema.json
|
|
81973
82264
|
|
|
@@ -81985,7 +82276,7 @@ ${block}
|
|
|
81985
82276
|
),
|
|
81986
82277
|
block
|
|
81987
82278
|
);
|
|
81988
|
-
await
|
|
82279
|
+
await writeFile38(configPath, ensureTrailingNewline(updated), "utf-8");
|
|
81989
82280
|
return { path: configPath, status: "merged", reason: "updated managed VibeFrame block" };
|
|
81990
82281
|
}
|
|
81991
82282
|
if (/\[mcp_servers\.vibeframe\]/.test(raw)) {
|
|
@@ -81999,10 +82290,10 @@ ${block}
|
|
|
81999
82290
|
const updated = raw.replace(/\n?\[mcp_servers\.vibeframe\][\s\S]*?(?=\n\[|$)/, `
|
|
82000
82291
|
${block}
|
|
82001
82292
|
`);
|
|
82002
|
-
await
|
|
82293
|
+
await writeFile38(configPath, ensureTrailingNewline(updated), "utf-8");
|
|
82003
82294
|
return { path: configPath, status: "merged", reason: "replaced existing VibeFrame MCP table" };
|
|
82004
82295
|
}
|
|
82005
|
-
await
|
|
82296
|
+
await writeFile38(configPath, `${ensureTrailingNewline(raw)}
|
|
82006
82297
|
${block}
|
|
82007
82298
|
`, "utf-8");
|
|
82008
82299
|
return { path: configPath, status: "merged" };
|
|
@@ -82423,7 +82714,7 @@ function renderEnvExample(opts = {}) {
|
|
|
82423
82714
|
|
|
82424
82715
|
${fallback2}# \u2500\u2500 LLM provider / optional \`vibe agent\` fallback (pick one) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
82425
82716
|
ANTHROPIC_API_KEY= # Claude - recommended default
|
|
82426
|
-
OPENAI_API_KEY= # GPT-5
|
|
82717
|
+
OPENAI_API_KEY= # GPT-5.4 mini \xB7 Whisper \xB7 gpt-image-2.5
|
|
82427
82718
|
GOOGLE_API_KEY= # Gemini \xB7 Veo
|
|
82428
82719
|
XAI_API_KEY= # Grok image+video
|
|
82429
82720
|
OPENROUTER_API_KEY= # multiplexes any provider above
|
|
@@ -82526,7 +82817,7 @@ var initCommand = new Command("init").description("Scaffold a VibeFrame project
|
|
|
82526
82817
|
reason: "(would create directory)"
|
|
82527
82818
|
});
|
|
82528
82819
|
} else {
|
|
82529
|
-
await
|
|
82820
|
+
await mkdir23(projectDir, { recursive: true });
|
|
82530
82821
|
}
|
|
82531
82822
|
}
|
|
82532
82823
|
if (wantsCrossTool || !wantsClaude) {
|
|
@@ -82747,7 +83038,7 @@ async function runSceneInit(projectDirArg, options, startedAt) {
|
|
|
82747
83038
|
}
|
|
82748
83039
|
}
|
|
82749
83040
|
if (options.force || result.created.includes(designPath) || !existsSync41(designPath)) {
|
|
82750
|
-
await
|
|
83041
|
+
await writeFile39(designPath, draft.designMd, "utf-8");
|
|
82751
83042
|
if (!result.created.includes(designPath)) result.created.push(designPath);
|
|
82752
83043
|
}
|
|
82753
83044
|
draftWarnings.push(...draft.warnings);
|
|
@@ -82930,15 +83221,15 @@ async function writeIfMissing(absPath, content, force, dryRun) {
|
|
|
82930
83221
|
if (dryRun) {
|
|
82931
83222
|
return { path: absPath, status: "would-write" };
|
|
82932
83223
|
}
|
|
82933
|
-
await
|
|
82934
|
-
await
|
|
83224
|
+
await mkdir23(dirname18(absPath), { recursive: true });
|
|
83225
|
+
await writeFile39(absPath, content, "utf-8");
|
|
82935
83226
|
return { path: absPath, status: "wrote" };
|
|
82936
83227
|
}
|
|
82937
83228
|
async function mergeGitignore(absPath, additions, dryRun) {
|
|
82938
83229
|
const marker = "# VibeFrame";
|
|
82939
83230
|
if (!existsSync41(absPath)) {
|
|
82940
83231
|
if (dryRun) return { path: absPath, status: "would-write" };
|
|
82941
|
-
await
|
|
83232
|
+
await writeFile39(absPath, additions.trimStart(), "utf-8");
|
|
82942
83233
|
return { path: absPath, status: "wrote" };
|
|
82943
83234
|
}
|
|
82944
83235
|
const existing = await readFile36(absPath, "utf-8");
|
|
@@ -82947,7 +83238,7 @@ async function mergeGitignore(absPath, additions, dryRun) {
|
|
|
82947
83238
|
}
|
|
82948
83239
|
if (dryRun) return { path: absPath, status: "merged" };
|
|
82949
83240
|
const trailing = existing.endsWith("\n") ? "" : "\n";
|
|
82950
|
-
await
|
|
83241
|
+
await writeFile39(absPath, existing + trailing + additions, "utf-8");
|
|
82951
83242
|
return { path: absPath, status: "merged" };
|
|
82952
83243
|
}
|
|
82953
83244
|
function formatStatusIcon(status) {
|
|
@@ -82975,7 +83266,7 @@ init_storyboard_revise();
|
|
|
82975
83266
|
init_composer_resolve();
|
|
82976
83267
|
init_cost_tier();
|
|
82977
83268
|
init_output();
|
|
82978
|
-
import { readFile as readFile38, writeFile as
|
|
83269
|
+
import { readFile as readFile38, writeFile as writeFile41 } from "node:fs/promises";
|
|
82979
83270
|
import { existsSync as existsSync43 } from "node:fs";
|
|
82980
83271
|
import { resolve as resolve52 } from "node:path";
|
|
82981
83272
|
var storyboardCommand = new Command("storyboard").description("Read, validate, and safely mutate STORYBOARD.md cue blocks").addHelpText("after", `
|
|
@@ -83053,7 +83344,7 @@ storyboardCommand.command("set").description("Update one cue in one beat without
|
|
|
83053
83344
|
cues = (await setSceneCue(projectDir, { beatId, key, value, unset: options.unset })).cues;
|
|
83054
83345
|
} else {
|
|
83055
83346
|
const next = setStoryboardCue(md, { beatId, key, value, unset: options.unset });
|
|
83056
|
-
await
|
|
83347
|
+
await writeFile41(storyboardPath(projectDir), next, "utf-8");
|
|
83057
83348
|
cues = getStoryboardBeat(next, beatId)?.cues ?? {};
|
|
83058
83349
|
}
|
|
83059
83350
|
} catch (error) {
|
|
@@ -83081,7 +83372,7 @@ storyboardCommand.command("move").description("Reorder beats safely").argument("
|
|
|
83081
83372
|
order = await moveScene(projectDir, { beatId, afterBeatId: options.after });
|
|
83082
83373
|
} else {
|
|
83083
83374
|
const next = moveStoryboardBeat(md, { beatId, afterBeatId: options.after });
|
|
83084
|
-
await
|
|
83375
|
+
await writeFile41(storyboardPath(projectDir), next, "utf-8");
|
|
83085
83376
|
order = parseStoryboard(next).beats.map((beat) => beat.id);
|
|
83086
83377
|
}
|
|
83087
83378
|
} catch (error) {
|
|
@@ -83339,12 +83630,13 @@ init_esm();
|
|
|
83339
83630
|
init_source();
|
|
83340
83631
|
init_build_plan();
|
|
83341
83632
|
init_output();
|
|
83633
|
+
init_build_video_providers();
|
|
83342
83634
|
import { resolve as resolve56 } from "node:path";
|
|
83343
83635
|
var VALID_STAGES = ["assets", "transcript", "compose", "sync", "render", "all"];
|
|
83344
83636
|
var VALID_MODES = ["agent", "batch", "auto"];
|
|
83345
83637
|
var VALID_TTS_PROVIDERS = ["auto", "elevenlabs", "openai", "kokoro"];
|
|
83346
83638
|
var VALID_IMAGE_PROVIDERS = ["openai", "gemini", "grok"];
|
|
83347
|
-
var VALID_VIDEO_PROVIDERS =
|
|
83639
|
+
var VALID_VIDEO_PROVIDERS = BUILD_VIDEO_PROVIDERS;
|
|
83348
83640
|
var VALID_MUSIC_PROVIDERS = ["elevenlabs", "replicate"];
|
|
83349
83641
|
var VALID_COMPOSERS = ["claude", "openai", "gemini"];
|
|
83350
83642
|
var VALID_IMAGE_QUALITIES = ["standard", "hd"];
|
|
@@ -83514,12 +83806,13 @@ init_scene_build();
|
|
|
83514
83806
|
init_build_plan();
|
|
83515
83807
|
init_storyboard_parse();
|
|
83516
83808
|
init_output();
|
|
83809
|
+
init_build_video_providers();
|
|
83517
83810
|
import { resolve as resolve64, join as join29 } from "node:path";
|
|
83518
83811
|
import { readFileSync as readFileSync3, existsSync as existsSync52 } from "node:fs";
|
|
83519
83812
|
var VALID_MODES2 = ["agent", "batch", "auto"];
|
|
83520
83813
|
var VALID_STAGES2 = ["assets", "transcript", "compose", "sync", "render", "all"];
|
|
83521
83814
|
var VALID_IMAGE_PROVIDERS2 = ["openai", "gemini", "grok"];
|
|
83522
|
-
var VALID_VIDEO_PROVIDERS2 =
|
|
83815
|
+
var VALID_VIDEO_PROVIDERS2 = BUILD_VIDEO_PROVIDERS;
|
|
83523
83816
|
var VALID_MUSIC_PROVIDERS2 = ["elevenlabs", "replicate"];
|
|
83524
83817
|
var buildCommand = new Command("build").description("Build a VibeFrame video project from STORYBOARD.md").argument("[project-dir]", "Video project directory", ".").option("--stage <stage>", `Build stage: ${VALID_STAGES2.join("|")}`, "all").option("--beat <id>", "Restrict asset/compose work to one beat id").option("--mode <mode>", "Retained for compatibility; scene HTML is always authored by your host agent unless --composer template is set", "auto").option(
|
|
83525
83818
|
"--composer <provider>",
|
|
@@ -83532,7 +83825,7 @@ var buildCommand = new Command("build").description("Build a VibeFrame video pro
|
|
|
83532
83825
|
"Don't transcribe narration for word-sync (default: transcribe when narration + OpenAI key exist)"
|
|
83533
83826
|
).option("--skip-render", "Compose only - don't render to MP4").option("--tts <provider>", "TTS provider: auto|elevenlabs|openai|kokoro").option("--voice <id>", "Voice id").option("--image-provider <name>", `Image provider: ${VALID_IMAGE_PROVIDERS2.join("|")}`).option(
|
|
83534
83827
|
"--image-model <model>",
|
|
83535
|
-
"Image model for keyframes/backdrops/character sheets (gemini: flash|pro, openai: gpt-image-2). Provider default when omitted."
|
|
83828
|
+
"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."
|
|
83536
83829
|
).option("--video-provider <name>", `Video provider: ${VALID_VIDEO_PROVIDERS2.join("|")}`).option("--music-provider <name>", `Music provider: ${VALID_MUSIC_PROVIDERS2.join("|")}`).option("--quality <q>", "Image quality: standard|hd", "hd").option("--image-size <s>", "Image size: 1024x1024|1536x1024|1024x1536", "1536x1024").option("--force", "Re-dispatch primitives even when assets already exist").option("--dry-run", "Preview parameters without dispatching").addHelpText(
|
|
83537
83830
|
"after",
|
|
83538
83831
|
`
|
|
@@ -85396,7 +85689,7 @@ init_ai_edit();
|
|
|
85396
85689
|
init_output();
|
|
85397
85690
|
import { resolve as resolve71 } from "node:path";
|
|
85398
85691
|
import { existsSync as existsSync54 } from "node:fs";
|
|
85399
|
-
import { mkdir as
|
|
85692
|
+
import { mkdir as mkdir28, rm as rm7 } from "node:fs/promises";
|
|
85400
85693
|
var DEMO_DIR = resolve71(process.cwd(), ".vibeframe-demo");
|
|
85401
85694
|
async function generateTestVideo(outputPath) {
|
|
85402
85695
|
const filter = [
|
|
@@ -85476,7 +85769,7 @@ var demoCommand = new Command("demo").description("Run sample edits on a test vi
|
|
|
85476
85769
|
console.log(source_default.dim(" " + "\u2500".repeat(50)));
|
|
85477
85770
|
console.log();
|
|
85478
85771
|
}
|
|
85479
|
-
await
|
|
85772
|
+
await mkdir28(DEMO_DIR, { recursive: true });
|
|
85480
85773
|
const testVideo = resolve71(DEMO_DIR, "test-input.mp4");
|
|
85481
85774
|
const genSpinner = !isJson ? ora("Generating test video...").start() : null;
|
|
85482
85775
|
const generated = await generateTestVideo(testVideo);
|
|
@@ -85586,7 +85879,7 @@ var demoCommand = new Command("demo").description("Run sample edits on a test vi
|
|
|
85586
85879
|
}
|
|
85587
85880
|
if (!options.keep) {
|
|
85588
85881
|
try {
|
|
85589
|
-
await
|
|
85882
|
+
await rm7(DEMO_DIR, { recursive: true, force: true });
|
|
85590
85883
|
} catch {
|
|
85591
85884
|
}
|
|
85592
85885
|
}
|
|
@@ -85596,10 +85889,10 @@ var demoCommand = new Command("demo").description("Run sample edits on a test vi
|
|
|
85596
85889
|
init_esm();
|
|
85597
85890
|
import { existsSync as existsSync55 } from "node:fs";
|
|
85598
85891
|
import { readFile as readFile45 } from "node:fs/promises";
|
|
85599
|
-
import { resolve as resolve72, dirname as
|
|
85892
|
+
import { resolve as resolve72, dirname as dirname24 } from "node:path";
|
|
85600
85893
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
85601
85894
|
var __filename = fileURLToPath2(import.meta.url);
|
|
85602
|
-
var __dirname =
|
|
85895
|
+
var __dirname = dirname24(__filename);
|
|
85603
85896
|
function resolveContextPath(baseDir = __dirname) {
|
|
85604
85897
|
const candidates = [
|
|
85605
85898
|
// Bundled package layout: packages/cli/dist/index.js -> packages/cli/CONTEXT.md
|
|
@@ -86228,11 +86521,12 @@ var ConversationMemory = class {
|
|
|
86228
86521
|
/**
|
|
86229
86522
|
* Add an assistant message
|
|
86230
86523
|
*/
|
|
86231
|
-
addAssistant(content, toolCalls) {
|
|
86524
|
+
addAssistant(content, toolCalls, providerContent) {
|
|
86232
86525
|
this.messages.push({
|
|
86233
86526
|
role: "assistant",
|
|
86234
86527
|
content,
|
|
86235
|
-
toolCalls
|
|
86528
|
+
toolCalls,
|
|
86529
|
+
providerContent
|
|
86236
86530
|
});
|
|
86237
86531
|
this.trim();
|
|
86238
86532
|
}
|
|
@@ -86406,7 +86700,7 @@ var AgentExecutor = class {
|
|
|
86406
86700
|
this.registry.getDefinitions()
|
|
86407
86701
|
);
|
|
86408
86702
|
if (response.finishReason === "tool_calls" && response.toolCalls) {
|
|
86409
|
-
this.memory.addAssistant(response.content, response.toolCalls);
|
|
86703
|
+
this.memory.addAssistant(response.content, response.toolCalls, response.providerContent);
|
|
86410
86704
|
for (const toolCall of response.toolCalls) {
|
|
86411
86705
|
if (this.config.verbose) {
|
|
86412
86706
|
console.log(`[Agent] Calling tool: ${toolCall.name}`);
|
|
@@ -87043,8 +87337,8 @@ init_source();
|
|
|
87043
87337
|
init_config();
|
|
87044
87338
|
init_schema();
|
|
87045
87339
|
init_api_key();
|
|
87046
|
-
import { access as access9, writeFile as
|
|
87047
|
-
import { dirname as
|
|
87340
|
+
import { access as access9, writeFile as writeFile55, mkdir as mkdir31 } from "node:fs/promises";
|
|
87341
|
+
import { dirname as dirname26 } from "node:path";
|
|
87048
87342
|
var BANNER_SHOWN_PATH = `${USER_CONFIG_DIR}/.banner-shown`;
|
|
87049
87343
|
async function isFirstRun() {
|
|
87050
87344
|
try {
|
|
@@ -87063,8 +87357,8 @@ async function isFirstRun() {
|
|
|
87063
87357
|
}
|
|
87064
87358
|
async function markBannerShown() {
|
|
87065
87359
|
try {
|
|
87066
|
-
await
|
|
87067
|
-
await
|
|
87360
|
+
await mkdir31(dirname26(BANNER_SHOWN_PATH), { recursive: true });
|
|
87361
|
+
await writeFile55(BANNER_SHOWN_PATH, (/* @__PURE__ */ new Date()).toISOString());
|
|
87068
87362
|
} catch {
|
|
87069
87363
|
}
|
|
87070
87364
|
}
|