@vibeframe/cli 0.112.0 → 0.113.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/_shared/build-plan.d.ts +9 -0
- package/dist/commands/_shared/project-config.d.ts +1 -1
- package/dist/commands/_shared/scene-build.d.ts +1 -1
- package/dist/commands/_shared/scene-project.d.ts +1 -1
- package/dist/commands/_shared/tts-resolve.d.ts +11 -7
- package/dist/index.js +250 -54
- package/dist/tools/_shared/elicit.d.ts +1 -1
- package/dist/tools/manifest/index.js +246 -50
- package/dist/tools/manifest/scene.d.ts +3 -3
- package/dist/tools/manifest/storyboard.d.ts +3 -3
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -7066,8 +7066,8 @@ var init_api_keys = __esm({
|
|
|
7066
7066
|
envVar: "OPENAI_API_KEY",
|
|
7067
7067
|
label: "OpenAI",
|
|
7068
7068
|
showInSetup: true,
|
|
7069
|
-
setupDescription: "gpt-image-2 image gen ($, default since v0.56), Whisper transcribe, Agent",
|
|
7070
|
-
envExampleComment: "OpenAI API Key (Whisper transcription, gpt-image-2 \u2014 default text-to-image since v0.56)",
|
|
7069
|
+
setupDescription: "gpt-image-2 image gen ($, default since v0.56), gpt-4o-mini-tts narration, Whisper transcribe, Agent",
|
|
7070
|
+
envExampleComment: "OpenAI API Key (Whisper transcription, gpt-4o-mini-tts narration, gpt-image-2 \u2014 default text-to-image since v0.56)",
|
|
7071
7071
|
envExampleUrl: "https://platform.openai.com/api-keys",
|
|
7072
7072
|
keyFormat: { prefix: /^sk-/, example: "sk-..." }
|
|
7073
7073
|
});
|
|
@@ -9174,8 +9174,8 @@ var init_openai = __esm({
|
|
|
9174
9174
|
id: "openai",
|
|
9175
9175
|
label: "OpenAI",
|
|
9176
9176
|
apiKey: "openai",
|
|
9177
|
-
kinds: ["llm", "image", "transcription"],
|
|
9178
|
-
resolverPriority: { image: 1 },
|
|
9177
|
+
kinds: ["llm", "image", "transcription", "speech"],
|
|
9178
|
+
resolverPriority: { image: 1, speech: 2 },
|
|
9179
9179
|
commandsUnlocked: [
|
|
9180
9180
|
"agent -p openai",
|
|
9181
9181
|
"generate image -p openai",
|
|
@@ -11597,16 +11597,19 @@ var init_elevenlabs = __esm({
|
|
|
11597
11597
|
});
|
|
11598
11598
|
|
|
11599
11599
|
// ../ai-providers/dist/kokoro/KokoroProvider.js
|
|
11600
|
-
async function
|
|
11600
|
+
async function loadKokoroRuntime() {
|
|
11601
11601
|
if (factoryOverride)
|
|
11602
|
-
return factoryOverride;
|
|
11602
|
+
return { factory: factoryOverride, device: "cpu" };
|
|
11603
11603
|
try {
|
|
11604
11604
|
const mod = await import("kokoro-js");
|
|
11605
|
-
return mod.KokoroTTS;
|
|
11605
|
+
return { factory: mod.KokoroTTS, device: "cpu" };
|
|
11606
11606
|
} catch (err) {
|
|
11607
|
-
const
|
|
11608
|
-
if (
|
|
11609
|
-
return
|
|
11607
|
+
const workspace = await loadKokoroFromWorkspace();
|
|
11608
|
+
if (workspace)
|
|
11609
|
+
return { factory: workspace, device: "cpu" };
|
|
11610
|
+
const bundled = await loadBundledKokoroRuntime();
|
|
11611
|
+
if (bundled)
|
|
11612
|
+
return bundled;
|
|
11610
11613
|
throw mapKokoroImportError(err);
|
|
11611
11614
|
}
|
|
11612
11615
|
}
|
|
@@ -11626,10 +11629,51 @@ async function loadKokoroFromWorkspace(baseDir = process.cwd()) {
|
|
|
11626
11629
|
return null;
|
|
11627
11630
|
}
|
|
11628
11631
|
}
|
|
11632
|
+
async function loadBundledKokoroRuntime(runtimeDir = process.env.VIBE_KOKORO_RUNTIME) {
|
|
11633
|
+
const base = runtimeDir?.trim();
|
|
11634
|
+
if (!base)
|
|
11635
|
+
return null;
|
|
11636
|
+
try {
|
|
11637
|
+
const { readFile: readFile56, writeFile: writeFile61, mkdir: mkdir31 } = await import("node:fs/promises");
|
|
11638
|
+
const { join: join30, resolve: resolve86 } = await import("node:path");
|
|
11639
|
+
const { pathToFileURL } = await import("node:url");
|
|
11640
|
+
const { homedir: homedir8 } = await import("node:os");
|
|
11641
|
+
const transformersDir = resolve86(base, "node_modules", "@huggingface", "transformers");
|
|
11642
|
+
const ortDistDir = resolve86(base, "node_modules", "onnxruntime-web", "dist");
|
|
11643
|
+
const transformers = await import(pathToFileURL(join30(transformersDir, "dist", "transformers.web.js")).href);
|
|
11644
|
+
const cacheRoot = join30(homedir8(), ".cache", "vibeframe", "models");
|
|
11645
|
+
transformers.env.allowLocalModels = false;
|
|
11646
|
+
transformers.env.useCustomCache = true;
|
|
11647
|
+
transformers.env.customCache = {
|
|
11648
|
+
async match(key) {
|
|
11649
|
+
try {
|
|
11650
|
+
return new Response(await readFile56(join30(cacheRoot, encodeURIComponent(String(key)))));
|
|
11651
|
+
} catch {
|
|
11652
|
+
return void 0;
|
|
11653
|
+
}
|
|
11654
|
+
},
|
|
11655
|
+
async put(key, response) {
|
|
11656
|
+
try {
|
|
11657
|
+
const buf = Buffer.from(await response.arrayBuffer());
|
|
11658
|
+
await mkdir31(cacheRoot, { recursive: true });
|
|
11659
|
+
await writeFile61(join30(cacheRoot, encodeURIComponent(String(key))), buf);
|
|
11660
|
+
} catch {
|
|
11661
|
+
}
|
|
11662
|
+
}
|
|
11663
|
+
};
|
|
11664
|
+
transformers.env.backends.onnx.wasm.wasmPaths = pathToFileURL(ortDistDir + "/").href;
|
|
11665
|
+
const factory = await loadKokoroFromWorkspace(base);
|
|
11666
|
+
if (!factory)
|
|
11667
|
+
return null;
|
|
11668
|
+
return { factory, device: "cpu" };
|
|
11669
|
+
} catch {
|
|
11670
|
+
return null;
|
|
11671
|
+
}
|
|
11672
|
+
}
|
|
11629
11673
|
function mapKokoroImportError(err) {
|
|
11630
11674
|
const code = err instanceof Error && "code" in err ? err.code : void 0;
|
|
11631
11675
|
if (code === "ERR_MODULE_NOT_FOUND" || code === "MODULE_NOT_FOUND") {
|
|
11632
|
-
return new Error("Local Kokoro TTS is unavailable:
|
|
11676
|
+
return new Error("Local Kokoro TTS is unavailable: kokoro-js could not be loaded from the npm install, the workspace node_modules, or the bundled extension runtime. Set OPENAI_API_KEY or ELEVENLABS_API_KEY to use a cloud voice instead (ttsProvider: openai / elevenlabs), or install the engine locally with `npm i kokoro-js` in your workspace folder.");
|
|
11633
11677
|
}
|
|
11634
11678
|
return err instanceof Error ? err : new Error(String(err));
|
|
11635
11679
|
}
|
|
@@ -11637,10 +11681,12 @@ function loadModel(progress) {
|
|
|
11637
11681
|
if (modelPromise)
|
|
11638
11682
|
return modelPromise;
|
|
11639
11683
|
modelPromise = (async () => {
|
|
11640
|
-
const
|
|
11641
|
-
|
|
11684
|
+
const runtime = await loadKokoroRuntime();
|
|
11685
|
+
const override = process.env.VIBE_ONNX_DEVICE;
|
|
11686
|
+
const device = override === "cpu" || override === "wasm" ? override : runtime.device;
|
|
11687
|
+
return runtime.factory.from_pretrained(KOKORO_MODEL_ID, {
|
|
11642
11688
|
dtype: "q8",
|
|
11643
|
-
device
|
|
11689
|
+
device,
|
|
11644
11690
|
progress_callback: progress ? (raw) => progress(normaliseEvent(raw)) : void 0
|
|
11645
11691
|
});
|
|
11646
11692
|
})().catch((err) => {
|
|
@@ -11724,7 +11770,7 @@ var init_kokoro = __esm({
|
|
|
11724
11770
|
label: "Kokoro (local)",
|
|
11725
11771
|
apiKey: null,
|
|
11726
11772
|
kinds: ["speech"],
|
|
11727
|
-
resolverPriority: { speech:
|
|
11773
|
+
resolverPriority: { speech: 3 }
|
|
11728
11774
|
});
|
|
11729
11775
|
}
|
|
11730
11776
|
});
|
|
@@ -11996,12 +12042,119 @@ var init_openai_image = __esm({
|
|
|
11996
12042
|
}
|
|
11997
12043
|
});
|
|
11998
12044
|
|
|
12045
|
+
// ../ai-providers/dist/openai-tts/OpenAiTtsProvider.js
|
|
12046
|
+
var OPENAI_TTS_VOICES, DEFAULT_VOICE, DEFAULT_MODEL2, TTS_429_MAX_RETRIES2, TTS_429_RETRY_DELAY_MS2, OpenAiTtsProvider, openaiTtsProvider;
|
|
12047
|
+
var init_OpenAiTtsProvider = __esm({
|
|
12048
|
+
"../ai-providers/dist/openai-tts/OpenAiTtsProvider.js"() {
|
|
12049
|
+
"use strict";
|
|
12050
|
+
OPENAI_TTS_VOICES = [
|
|
12051
|
+
"alloy",
|
|
12052
|
+
"ash",
|
|
12053
|
+
"ballad",
|
|
12054
|
+
"cedar",
|
|
12055
|
+
"coral",
|
|
12056
|
+
"echo",
|
|
12057
|
+
"fable",
|
|
12058
|
+
"marin",
|
|
12059
|
+
"nova",
|
|
12060
|
+
"onyx",
|
|
12061
|
+
"sage",
|
|
12062
|
+
"shimmer",
|
|
12063
|
+
"verse"
|
|
12064
|
+
];
|
|
12065
|
+
DEFAULT_VOICE = "marin";
|
|
12066
|
+
DEFAULT_MODEL2 = "gpt-4o-mini-tts";
|
|
12067
|
+
TTS_429_MAX_RETRIES2 = 1;
|
|
12068
|
+
TTS_429_RETRY_DELAY_MS2 = 2e3;
|
|
12069
|
+
OpenAiTtsProvider = class {
|
|
12070
|
+
constructor() {
|
|
12071
|
+
this.id = "openai";
|
|
12072
|
+
this.name = "OpenAI TTS";
|
|
12073
|
+
this.description = "OpenAI cloud text-to-speech (gpt-4o-mini-tts)";
|
|
12074
|
+
this.capabilities = ["text-to-speech"];
|
|
12075
|
+
this.isAvailable = true;
|
|
12076
|
+
this.baseUrl = "https://api.openai.com/v1";
|
|
12077
|
+
}
|
|
12078
|
+
async initialize(config2) {
|
|
12079
|
+
this.apiKey = config2.apiKey;
|
|
12080
|
+
if (config2.baseUrl) {
|
|
12081
|
+
this.baseUrl = config2.baseUrl;
|
|
12082
|
+
}
|
|
12083
|
+
}
|
|
12084
|
+
isConfigured() {
|
|
12085
|
+
return !!this.apiKey;
|
|
12086
|
+
}
|
|
12087
|
+
async textToSpeech(text, options = {}) {
|
|
12088
|
+
if (!this.apiKey) {
|
|
12089
|
+
return { success: false, error: "OpenAI API key not configured" };
|
|
12090
|
+
}
|
|
12091
|
+
const voice = (options.voice ?? DEFAULT_VOICE).toLowerCase();
|
|
12092
|
+
if (!OPENAI_TTS_VOICES.includes(voice)) {
|
|
12093
|
+
return {
|
|
12094
|
+
success: false,
|
|
12095
|
+
error: `Unknown OpenAI voice "${options.voice}". Available voices: ${OPENAI_TTS_VOICES.join(", ")}.`
|
|
12096
|
+
};
|
|
12097
|
+
}
|
|
12098
|
+
try {
|
|
12099
|
+
let response;
|
|
12100
|
+
for (let attempt = 0; ; attempt++) {
|
|
12101
|
+
response = await fetch(`${this.baseUrl}/audio/speech`, {
|
|
12102
|
+
method: "POST",
|
|
12103
|
+
headers: {
|
|
12104
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
12105
|
+
"Content-Type": "application/json"
|
|
12106
|
+
},
|
|
12107
|
+
body: JSON.stringify({
|
|
12108
|
+
model: options.model ?? DEFAULT_MODEL2,
|
|
12109
|
+
input: text,
|
|
12110
|
+
voice,
|
|
12111
|
+
response_format: "mp3",
|
|
12112
|
+
...options.speed !== void 0 && { speed: options.speed },
|
|
12113
|
+
...options.instructions !== void 0 && { instructions: options.instructions }
|
|
12114
|
+
})
|
|
12115
|
+
});
|
|
12116
|
+
if (response.status === 429 && attempt < TTS_429_MAX_RETRIES2) {
|
|
12117
|
+
await new Promise((resolveDelay) => setTimeout(resolveDelay, TTS_429_RETRY_DELAY_MS2 * (attempt + 1)));
|
|
12118
|
+
continue;
|
|
12119
|
+
}
|
|
12120
|
+
break;
|
|
12121
|
+
}
|
|
12122
|
+
if (!response.ok) {
|
|
12123
|
+
const error = await response.text();
|
|
12124
|
+
return { success: false, error: `OpenAI TTS failed: ${error}` };
|
|
12125
|
+
}
|
|
12126
|
+
const arrayBuffer = await response.arrayBuffer();
|
|
12127
|
+
return {
|
|
12128
|
+
success: true,
|
|
12129
|
+
audioBuffer: Buffer.from(arrayBuffer),
|
|
12130
|
+
characterCount: text.length
|
|
12131
|
+
};
|
|
12132
|
+
} catch (error) {
|
|
12133
|
+
return {
|
|
12134
|
+
success: false,
|
|
12135
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
12136
|
+
};
|
|
12137
|
+
}
|
|
12138
|
+
}
|
|
12139
|
+
};
|
|
12140
|
+
openaiTtsProvider = new OpenAiTtsProvider();
|
|
12141
|
+
}
|
|
12142
|
+
});
|
|
12143
|
+
|
|
12144
|
+
// ../ai-providers/dist/openai-tts/index.js
|
|
12145
|
+
var init_openai_tts = __esm({
|
|
12146
|
+
"../ai-providers/dist/openai-tts/index.js"() {
|
|
12147
|
+
"use strict";
|
|
12148
|
+
init_OpenAiTtsProvider();
|
|
12149
|
+
}
|
|
12150
|
+
});
|
|
12151
|
+
|
|
11999
12152
|
// ../ai-providers/dist/runway/RunwayProvider.js
|
|
12000
|
-
var
|
|
12153
|
+
var DEFAULT_MODEL3, RunwayProvider, runwayProvider;
|
|
12001
12154
|
var init_RunwayProvider = __esm({
|
|
12002
12155
|
"../ai-providers/dist/runway/RunwayProvider.js"() {
|
|
12003
12156
|
"use strict";
|
|
12004
|
-
|
|
12157
|
+
DEFAULT_MODEL3 = "gen4.5";
|
|
12005
12158
|
RunwayProvider = class _RunwayProvider {
|
|
12006
12159
|
constructor() {
|
|
12007
12160
|
this.id = "runway";
|
|
@@ -12044,7 +12197,7 @@ var init_RunwayProvider = __esm({
|
|
|
12044
12197
|
"1:1": "960:960"
|
|
12045
12198
|
};
|
|
12046
12199
|
const apiRatio = ratioMap[options?.aspectRatio || "16:9"] || "1280:720";
|
|
12047
|
-
const model = options?.model ||
|
|
12200
|
+
const model = options?.model || DEFAULT_MODEL3;
|
|
12048
12201
|
if (!options?.referenceImage && model !== "gen4.5") {
|
|
12049
12202
|
return {
|
|
12050
12203
|
id: "",
|
|
@@ -12306,11 +12459,11 @@ var init_runway = __esm({
|
|
|
12306
12459
|
|
|
12307
12460
|
// ../ai-providers/dist/kling/KlingProvider.js
|
|
12308
12461
|
import { createHmac } from "node:crypto";
|
|
12309
|
-
var
|
|
12462
|
+
var DEFAULT_MODEL4, STD_MODE_MODELS, KlingProvider, klingProvider;
|
|
12310
12463
|
var init_KlingProvider = __esm({
|
|
12311
12464
|
"../ai-providers/dist/kling/KlingProvider.js"() {
|
|
12312
12465
|
"use strict";
|
|
12313
|
-
|
|
12466
|
+
DEFAULT_MODEL4 = "kling-v2-5-turbo";
|
|
12314
12467
|
STD_MODE_MODELS = ["kling-v2-5-turbo", "kling-v2-6", "kling-v3", "kling-v3-omni"];
|
|
12315
12468
|
KlingProvider = class {
|
|
12316
12469
|
constructor() {
|
|
@@ -12373,7 +12526,7 @@ var init_KlingProvider = __esm({
|
|
|
12373
12526
|
}
|
|
12374
12527
|
try {
|
|
12375
12528
|
const token = this.generateToken();
|
|
12376
|
-
const model = options?.model ||
|
|
12529
|
+
const model = options?.model || DEFAULT_MODEL4;
|
|
12377
12530
|
let mode = options?.mode || "std";
|
|
12378
12531
|
if (!STD_MODE_MODELS.includes(model) && mode === "std") {
|
|
12379
12532
|
mode = "pro";
|
|
@@ -12744,11 +12897,11 @@ var init_kling = __esm({
|
|
|
12744
12897
|
});
|
|
12745
12898
|
|
|
12746
12899
|
// ../ai-providers/dist/grok/GrokProvider.js
|
|
12747
|
-
var
|
|
12900
|
+
var DEFAULT_MODEL5, GrokProvider, grokProvider;
|
|
12748
12901
|
var init_GrokProvider = __esm({
|
|
12749
12902
|
"../ai-providers/dist/grok/GrokProvider.js"() {
|
|
12750
12903
|
"use strict";
|
|
12751
|
-
|
|
12904
|
+
DEFAULT_MODEL5 = "grok-imagine-video";
|
|
12752
12905
|
GrokProvider = class {
|
|
12753
12906
|
constructor() {
|
|
12754
12907
|
this.id = "grok";
|
|
@@ -12915,7 +13068,7 @@ var init_GrokProvider = __esm({
|
|
|
12915
13068
|
try {
|
|
12916
13069
|
const duration = Math.round(Math.min(15, Math.max(1, options?.duration || 5)));
|
|
12917
13070
|
const body = {
|
|
12918
|
-
model:
|
|
13071
|
+
model: DEFAULT_MODEL5,
|
|
12919
13072
|
prompt: prompt3,
|
|
12920
13073
|
duration,
|
|
12921
13074
|
aspect_ratio: options?.aspectRatio || "16:9"
|
|
@@ -18122,9 +18275,11 @@ __export(dist_exports2, {
|
|
|
18122
18275
|
KOKORO_MODEL_ID: () => KOKORO_MODEL_ID,
|
|
18123
18276
|
KlingProvider: () => KlingProvider,
|
|
18124
18277
|
KokoroProvider: () => KokoroProvider,
|
|
18278
|
+
OPENAI_TTS_VOICES: () => OPENAI_TTS_VOICES,
|
|
18125
18279
|
OllamaProvider: () => OllamaProvider,
|
|
18126
18280
|
OpenAIImageProvider: () => OpenAIImageProvider,
|
|
18127
18281
|
OpenAIProvider: () => OpenAIProvider,
|
|
18282
|
+
OpenAiTtsProvider: () => OpenAiTtsProvider,
|
|
18128
18283
|
ReplicateProvider: () => ReplicateProvider,
|
|
18129
18284
|
RunwayProvider: () => RunwayProvider,
|
|
18130
18285
|
WhisperProvider: () => WhisperProvider,
|
|
@@ -18148,9 +18303,12 @@ __export(dist_exports2, {
|
|
|
18148
18303
|
isGeminiTextModelAlias: () => isGeminiTextModelAlias,
|
|
18149
18304
|
klingProvider: () => klingProvider,
|
|
18150
18305
|
kokoroProvider: () => kokoroProvider,
|
|
18306
|
+
loadBundledKokoroRuntime: () => loadBundledKokoroRuntime,
|
|
18307
|
+
loadKokoroFromWorkspace: () => loadKokoroFromWorkspace,
|
|
18151
18308
|
ollamaProvider: () => ollamaProvider,
|
|
18152
18309
|
openaiImageProvider: () => openaiImageProvider,
|
|
18153
18310
|
openaiProvider: () => openaiProvider,
|
|
18311
|
+
openaiTtsProvider: () => openaiTtsProvider,
|
|
18154
18312
|
providerRegistry: () => providerRegistry,
|
|
18155
18313
|
replicateProvider: () => replicateProvider,
|
|
18156
18314
|
resolveGeminiTextModel: () => resolveGeminiTextModel,
|
|
@@ -18173,6 +18331,7 @@ var init_dist2 = __esm({
|
|
|
18173
18331
|
init_elevenlabs();
|
|
18174
18332
|
init_kokoro();
|
|
18175
18333
|
init_openai_image();
|
|
18334
|
+
init_openai_tts();
|
|
18176
18335
|
init_runway();
|
|
18177
18336
|
init_kling();
|
|
18178
18337
|
init_grok();
|
|
@@ -26347,10 +26506,22 @@ var init_api_key = __esm({
|
|
|
26347
26506
|
|
|
26348
26507
|
// src/commands/_shared/tts-resolve.ts
|
|
26349
26508
|
async function resolveTtsProvider(preferred = "auto") {
|
|
26350
|
-
|
|
26509
|
+
let choice = preferred;
|
|
26510
|
+
if (choice === "auto") {
|
|
26511
|
+
if (await getConfiguredApiKey("ELEVENLABS_API_KEY")) {
|
|
26512
|
+
choice = "elevenlabs";
|
|
26513
|
+
} else if (await getConfiguredApiKey("OPENAI_API_KEY")) {
|
|
26514
|
+
choice = "openai";
|
|
26515
|
+
} else {
|
|
26516
|
+
choice = "kokoro";
|
|
26517
|
+
}
|
|
26518
|
+
}
|
|
26351
26519
|
if (choice === "elevenlabs") {
|
|
26352
26520
|
return buildElevenLabs();
|
|
26353
26521
|
}
|
|
26522
|
+
if (choice === "openai") {
|
|
26523
|
+
return buildOpenAi();
|
|
26524
|
+
}
|
|
26354
26525
|
return buildKokoro();
|
|
26355
26526
|
}
|
|
26356
26527
|
async function buildElevenLabs() {
|
|
@@ -26366,6 +26537,19 @@ async function buildElevenLabs() {
|
|
|
26366
26537
|
});
|
|
26367
26538
|
return { provider: "elevenlabs", audioExtension: "mp3", call };
|
|
26368
26539
|
}
|
|
26540
|
+
async function buildOpenAi() {
|
|
26541
|
+
const key = await getApiKey("OPENAI_API_KEY", "OpenAI");
|
|
26542
|
+
if (!key) {
|
|
26543
|
+
throw new TtsKeyMissingError("openai");
|
|
26544
|
+
}
|
|
26545
|
+
const provider = new OpenAiTtsProvider();
|
|
26546
|
+
await provider.initialize({ apiKey: key });
|
|
26547
|
+
const call = async (text, opts) => provider.textToSpeech(text, {
|
|
26548
|
+
voice: opts?.voice,
|
|
26549
|
+
speed: opts?.speed
|
|
26550
|
+
});
|
|
26551
|
+
return { provider: "openai", audioExtension: "mp3", call };
|
|
26552
|
+
}
|
|
26369
26553
|
async function buildKokoro() {
|
|
26370
26554
|
const provider = new KokoroProvider();
|
|
26371
26555
|
await provider.initialize({});
|
|
@@ -26378,11 +26562,11 @@ async function buildKokoro() {
|
|
|
26378
26562
|
}
|
|
26379
26563
|
function parseTtsProviderName(value) {
|
|
26380
26564
|
if (!value) return "auto";
|
|
26381
|
-
if (value === "auto" || value === "elevenlabs" || value === "kokoro") {
|
|
26565
|
+
if (value === "auto" || value === "elevenlabs" || value === "openai" || value === "kokoro") {
|
|
26382
26566
|
return value;
|
|
26383
26567
|
}
|
|
26384
26568
|
throw new Error(
|
|
26385
|
-
`Invalid --tts: ${value}. Valid: auto, elevenlabs, kokoro.`
|
|
26569
|
+
`Invalid --tts: ${value}. Valid: auto, elevenlabs, openai, kokoro.`
|
|
26386
26570
|
);
|
|
26387
26571
|
}
|
|
26388
26572
|
var TtsKeyMissingError;
|
|
@@ -26394,7 +26578,7 @@ var init_tts_resolve = __esm({
|
|
|
26394
26578
|
TtsKeyMissingError = class extends Error {
|
|
26395
26579
|
constructor(provider) {
|
|
26396
26580
|
super(
|
|
26397
|
-
provider === "elevenlabs" ? "ElevenLabs API key required (ELEVENLABS_API_KEY). Run 'vibe setup', set ELEVENLABS_API_KEY in .env, or pass --tts kokoro for local synthesis." : `Provider ${provider} is unavailable.`
|
|
26581
|
+
provider === "elevenlabs" ? "ElevenLabs API key required (ELEVENLABS_API_KEY). Run 'vibe setup', set ELEVENLABS_API_KEY in .env, or pass --tts kokoro for local synthesis." : provider === "openai" ? "OpenAI API key required (OPENAI_API_KEY). Run 'vibe setup', set OPENAI_API_KEY in .env, or pass --tts kokoro for local synthesis." : `Provider ${provider} is unavailable.`
|
|
26398
26582
|
);
|
|
26399
26583
|
this.provider = provider;
|
|
26400
26584
|
this.name = "TtsKeyMissingError";
|
|
@@ -31013,7 +31197,7 @@ async function executeSceneAdd(opts) {
|
|
|
31013
31197
|
throw error;
|
|
31014
31198
|
}
|
|
31015
31199
|
opts.onProgress?.(
|
|
31016
|
-
resolution.provider === "kokoro" ? "Generating narration with Kokoro (local \u2014 first run downloads ~
|
|
31200
|
+
resolution.provider === "kokoro" ? "Generating narration with Kokoro (local \u2014 first run downloads a ~90MB model)..." : resolution.provider === "openai" ? "Generating narration with OpenAI (gpt-4o-mini-tts)..." : "Generating narration with ElevenLabs..."
|
|
31017
31201
|
);
|
|
31018
31202
|
const tts = await resolution.call(narrationText, {
|
|
31019
31203
|
voice: opts.voice,
|
|
@@ -31536,9 +31720,9 @@ Run 'vibe schema scene.<command>' for structured parameter info.`
|
|
|
31536
31720
|
"Image prompt \u2014 generates assets/scene-<id>.png via the configured image provider"
|
|
31537
31721
|
).option("--headline <text>", "Visible headline (defaults to the humanised scene name)").option("--kicker <text>", "Small label above the headline (explainer / product-shot)").option("--insert-into <path>", "Root composition file to update", "index.html").option("--project <dir>", "Project directory", ".").option("--image-provider <name>", "Image provider: gemini, openai", "gemini").option(
|
|
31538
31722
|
"--tts <provider>",
|
|
31539
|
-
"TTS provider: auto, elevenlabs, kokoro (default auto \u2014
|
|
31723
|
+
"TTS provider: auto, elevenlabs, openai, kokoro (default auto \u2014 ElevenLabs key > OpenAI key > Kokoro local)",
|
|
31540
31724
|
"auto"
|
|
31541
|
-
).option("--voice <id>", "Voice id (ElevenLabs name/id, or Kokoro id like af_heart
|
|
31725
|
+
).option("--voice <id>", "Voice id (ElevenLabs name/id, OpenAI voice like marin, or Kokoro id like af_heart)").option(
|
|
31542
31726
|
"--no-audio",
|
|
31543
31727
|
"Skip TTS even when --narration is provided (useful for tests/agent dry runs)"
|
|
31544
31728
|
).option("--no-image", "Skip image generation even when --visuals is provided").option(
|
|
@@ -59515,6 +59699,9 @@ var init_build_backdrop_prompt = __esm({
|
|
|
59515
59699
|
import { existsSync as existsSync47 } from "node:fs";
|
|
59516
59700
|
import { readFile as readFile43 } from "node:fs/promises";
|
|
59517
59701
|
import { dirname as dirname21, join as join23, resolve as resolve60 } from "node:path";
|
|
59702
|
+
function backdropCostUsd(quality) {
|
|
59703
|
+
return quality === "hd" ? 0.2 : 0.05;
|
|
59704
|
+
}
|
|
59518
59705
|
async function createBuildPlan(opts) {
|
|
59519
59706
|
const projectDir = resolve60(opts.projectDir);
|
|
59520
59707
|
loadPlanEnv(projectDir);
|
|
@@ -59616,13 +59803,13 @@ async function createBuildPlan(opts) {
|
|
|
59616
59803
|
const backdropCue = backdropPrompt ?? backdropReference?.raw;
|
|
59617
59804
|
const videoCue = videoPrompt ?? videoReference?.raw;
|
|
59618
59805
|
const musicCue = musicPrompt ?? musicReference?.raw;
|
|
59619
|
-
const narrationCost = resolved.narration.resolved === "elevenlabs" ? ELEVENLABS_NARRATION_COST_USD : 0;
|
|
59806
|
+
const narrationCost = resolved.narration.resolved === "elevenlabs" ? ELEVENLABS_NARRATION_COST_USD : resolved.narration.resolved === "openai" ? OPENAI_NARRATION_COST_USD : 0;
|
|
59620
59807
|
const narrationCache = narrationText && !narrationReference ? narrationCacheDescriptor({
|
|
59621
59808
|
beatId: beat.id,
|
|
59622
59809
|
cue: narrationText,
|
|
59623
59810
|
provider: resolved.narration.resolved,
|
|
59624
59811
|
voice,
|
|
59625
|
-
ext: resolved.narration.resolved === "
|
|
59812
|
+
ext: resolved.narration.resolved === "kokoro" ? "wav" : "mp3"
|
|
59626
59813
|
}) : null;
|
|
59627
59814
|
const backdropCache = augmentedBackdropPrompt && !backdropReference ? backdropCacheDescriptor({
|
|
59628
59815
|
beatId: beat.id,
|
|
@@ -59670,7 +59857,7 @@ async function createBuildPlan(opts) {
|
|
|
59670
59857
|
reference: backdropReference,
|
|
59671
59858
|
projectDir,
|
|
59672
59859
|
force: opts.force,
|
|
59673
|
-
cost:
|
|
59860
|
+
cost: backdropCostUsd(imageQuality),
|
|
59674
59861
|
active: includeAssets
|
|
59675
59862
|
}) : null;
|
|
59676
59863
|
const video = videoCue && !opts.skipVideo ? assetPlan({
|
|
@@ -60040,17 +60227,20 @@ function providerInput(opts) {
|
|
|
60040
60227
|
async function resolveNarrationProvider(input, projectDir) {
|
|
60041
60228
|
const requested = input.value.toLowerCase();
|
|
60042
60229
|
const hasElevenLabs = Boolean(await getApiKeyFromConfig("elevenlabs", { cwd: projectDir }));
|
|
60043
|
-
const
|
|
60230
|
+
const hasOpenAi = Boolean(await getApiKeyFromConfig("openai", { cwd: projectDir }));
|
|
60231
|
+
const resolved = requested === "elevenlabs" ? "elevenlabs" : requested === "openai" ? "openai" : requested === "kokoro" ? "kokoro" : hasElevenLabs ? "elevenlabs" : hasOpenAi ? "openai" : "kokoro";
|
|
60232
|
+
const requiresKey = resolved !== "kokoro";
|
|
60233
|
+
const hasKey = resolved === "elevenlabs" ? hasElevenLabs : resolved === "openai" ? hasOpenAi : true;
|
|
60044
60234
|
return {
|
|
60045
60235
|
kind: "narration",
|
|
60046
60236
|
requested: input.requested,
|
|
60047
60237
|
resolved,
|
|
60048
60238
|
source: input.source,
|
|
60049
|
-
requiresKey
|
|
60050
|
-
configured:
|
|
60051
|
-
...
|
|
60052
|
-
...
|
|
60053
|
-
retryWith:
|
|
60239
|
+
requiresKey,
|
|
60240
|
+
configured: hasKey,
|
|
60241
|
+
...requiresKey ? { configKey: resolved } : {},
|
|
60242
|
+
...requiresKey && !hasKey ? { missingKey: providerEnvVar(resolved) } : {},
|
|
60243
|
+
retryWith: requiresKey && !hasKey ? ["vibe setup --full"] : []
|
|
60054
60244
|
};
|
|
60055
60245
|
}
|
|
60056
60246
|
async function keyedProviderResolution(opts, projectDir) {
|
|
@@ -60146,7 +60336,7 @@ function loadPlanEnv(projectDir) {
|
|
|
60146
60336
|
dir = dirname21(dir);
|
|
60147
60337
|
}
|
|
60148
60338
|
}
|
|
60149
|
-
var import_dotenv3,
|
|
60339
|
+
var import_dotenv3, VIDEO_COST_USD, MUSIC_COST_USD, ELEVENLABS_NARRATION_COST_USD, OPENAI_NARRATION_COST_USD, COMPOSE_COST_USD, SUPPORTED_BUILD_IMAGE_PROVIDERS;
|
|
60150
60340
|
var init_build_plan = __esm({
|
|
60151
60341
|
"src/commands/_shared/build-plan.ts"() {
|
|
60152
60342
|
"use strict";
|
|
@@ -60161,10 +60351,10 @@ var init_build_plan = __esm({
|
|
|
60161
60351
|
init_storyboard_parse();
|
|
60162
60352
|
init_project_config();
|
|
60163
60353
|
init_storyboard_edit();
|
|
60164
|
-
BACKDROP_COST_USD = 3;
|
|
60165
60354
|
VIDEO_COST_USD = 5;
|
|
60166
60355
|
MUSIC_COST_USD = 0.5;
|
|
60167
60356
|
ELEVENLABS_NARRATION_COST_USD = 0.05;
|
|
60357
|
+
OPENAI_NARRATION_COST_USD = 0.01;
|
|
60168
60358
|
COMPOSE_COST_USD = 0.06;
|
|
60169
60359
|
SUPPORTED_BUILD_IMAGE_PROVIDERS = ["openai", "gemini", "grok"];
|
|
60170
60360
|
}
|
|
@@ -61177,7 +61367,10 @@ async function executeSceneBuild(opts) {
|
|
|
61177
61367
|
(beat) => beat.narrationStatus === "failed" || beat.backdropStatus === "failed" || beat.videoStatus === "failed" || beat.musicStatus === "failed"
|
|
61178
61368
|
);
|
|
61179
61369
|
stageReports.assets.status = assetFailed ? "failed" : pendingJobs.length > 0 ? "pending-jobs" : "done";
|
|
61180
|
-
stageReports.assets.costUsd = estimateActualAssetCost(
|
|
61370
|
+
stageReports.assets.costUsd = estimateActualAssetCost(
|
|
61371
|
+
beatOutcomes,
|
|
61372
|
+
opts.imageQuality ?? "hd"
|
|
61373
|
+
);
|
|
61181
61374
|
stageReports.assets.retryWith = pendingJobs.map(
|
|
61182
61375
|
(job) => `vibe status job ${job.id} --project ${projectDir} --json`
|
|
61183
61376
|
);
|
|
@@ -62360,11 +62553,11 @@ function shouldRunStage(selected, stage) {
|
|
|
62360
62553
|
if (selected === "all") return true;
|
|
62361
62554
|
return selected === stage;
|
|
62362
62555
|
}
|
|
62363
|
-
function estimateActualAssetCost(outcomes) {
|
|
62556
|
+
function estimateActualAssetCost(outcomes, imageQuality) {
|
|
62364
62557
|
let cost = 0;
|
|
62365
62558
|
for (const outcome of outcomes) {
|
|
62366
62559
|
if (outcome.narrationStatus === "generated") cost += 0.05;
|
|
62367
|
-
if (outcome.backdropStatus === "generated") cost +=
|
|
62560
|
+
if (outcome.backdropStatus === "generated") cost += backdropCostUsd(imageQuality);
|
|
62368
62561
|
if (outcome.videoStatus === "generated" || outcome.videoStatus === "pending") cost += 5;
|
|
62369
62562
|
if (outcome.musicStatus === "generated" || outcome.musicStatus === "pending") cost += 0.5;
|
|
62370
62563
|
}
|
|
@@ -67925,8 +68118,9 @@ function planBuildElicitation(args) {
|
|
|
67925
68118
|
description: "Which TTS engine narrates the video?",
|
|
67926
68119
|
enum: [...NARRATION_CHOICES],
|
|
67927
68120
|
enumNames: [
|
|
67928
|
-
"Kokoro \u2014 free, runs
|
|
67929
|
-
"
|
|
68121
|
+
"Kokoro \u2014 free, runs on this machine (first use downloads a ~90 MB voice model; slower)",
|
|
68122
|
+
"OpenAI \u2014 fast cloud voice, uses your OpenAI API key (~$0.02 per video)",
|
|
68123
|
+
"ElevenLabs \u2014 premium cloud voices, uses your ElevenLabs credits"
|
|
67930
68124
|
]
|
|
67931
68125
|
};
|
|
67932
68126
|
required.push("narration");
|
|
@@ -67982,7 +68176,7 @@ var NARRATION_CHOICES, BACKDROP_CHOICES;
|
|
|
67982
68176
|
var init_elicit = __esm({
|
|
67983
68177
|
"src/tools/_shared/elicit.ts"() {
|
|
67984
68178
|
"use strict";
|
|
67985
|
-
NARRATION_CHOICES = ["kokoro", "elevenlabs"];
|
|
68179
|
+
NARRATION_CHOICES = ["kokoro", "openai", "elevenlabs"];
|
|
67986
68180
|
BACKDROP_CHOICES = ["skip", "openai"];
|
|
67987
68181
|
}
|
|
67988
68182
|
});
|
|
@@ -68460,7 +68654,9 @@ var init_scene2 = __esm({
|
|
|
68460
68654
|
skipVideo: external_exports.boolean().optional().describe("Skip video generation for every beat (use existing MP4 assets if present)."),
|
|
68461
68655
|
skipMusic: external_exports.boolean().optional().describe("Skip music generation for every beat (use existing audio assets if present)."),
|
|
68462
68656
|
skipRender: external_exports.boolean().optional().describe("Stop after compose \u2014 produces compositions/*.html but no final MP4."),
|
|
68463
|
-
ttsProvider: external_exports.enum(["auto", "elevenlabs", "kokoro"]).optional().describe(
|
|
68657
|
+
ttsProvider: external_exports.enum(["auto", "elevenlabs", "openai", "kokoro"]).optional().describe(
|
|
68658
|
+
"TTS provider override. Default 'auto' (elevenlabs key > openai key > local kokoro)."
|
|
68659
|
+
),
|
|
68464
68660
|
voice: external_exports.string().optional().describe("TTS voice id (provider-specific)."),
|
|
68465
68661
|
imageProvider: external_exports.enum(["openai"]).optional().describe("Image provider for backdrops. Default 'openai' (gpt-image-2)."),
|
|
68466
68662
|
videoProvider: external_exports.enum(["seedance", "grok", "kling", "runway", "veo"]).optional().describe("Video provider for per-beat video cues. Default seedance."),
|
|
@@ -70315,7 +70511,7 @@ var init_storyboard2 = __esm({
|
|
|
70315
70511
|
skipBackdrop: external_exports.boolean().optional().describe("Don't include backdrop image generation in the plan."),
|
|
70316
70512
|
skipVideo: external_exports.boolean().optional().describe("Don't include video generation in the plan."),
|
|
70317
70513
|
skipMusic: external_exports.boolean().optional().describe("Don't include music generation in the plan."),
|
|
70318
|
-
ttsProvider: external_exports.enum(["auto", "elevenlabs", "kokoro"]).optional().describe("TTS provider override."),
|
|
70514
|
+
ttsProvider: external_exports.enum(["auto", "elevenlabs", "openai", "kokoro"]).optional().describe("TTS provider override."),
|
|
70319
70515
|
voice: external_exports.string().optional().describe("Voice id."),
|
|
70320
70516
|
imageProvider: external_exports.string().optional().describe("Image provider override."),
|
|
70321
70517
|
imageQuality: external_exports.enum(["standard", "hd"]).optional().describe("Image quality override."),
|
|
@@ -73431,7 +73627,7 @@ init_source();
|
|
|
73431
73627
|
// package.json
|
|
73432
73628
|
var package_default = {
|
|
73433
73629
|
name: "@vibeframe/cli",
|
|
73434
|
-
version: "0.
|
|
73630
|
+
version: "0.113.0",
|
|
73435
73631
|
description: "VibeFrame CLI - agentic video workflow runtime",
|
|
73436
73632
|
private: false,
|
|
73437
73633
|
license: "MIT",
|
|
@@ -83434,13 +83630,13 @@ init_output();
|
|
|
83434
83630
|
import { resolve as resolve61 } from "node:path";
|
|
83435
83631
|
var VALID_STAGES = ["assets", "compose", "sync", "render", "all"];
|
|
83436
83632
|
var VALID_MODES = ["agent", "batch", "auto"];
|
|
83437
|
-
var VALID_TTS_PROVIDERS = ["auto", "elevenlabs", "kokoro"];
|
|
83633
|
+
var VALID_TTS_PROVIDERS = ["auto", "elevenlabs", "openai", "kokoro"];
|
|
83438
83634
|
var VALID_IMAGE_PROVIDERS = ["openai", "gemini", "grok"];
|
|
83439
83635
|
var VALID_VIDEO_PROVIDERS = ["seedance", "grok", "kling", "runway", "veo"];
|
|
83440
83636
|
var VALID_MUSIC_PROVIDERS = ["elevenlabs", "replicate"];
|
|
83441
83637
|
var VALID_COMPOSERS = ["claude", "openai", "gemini"];
|
|
83442
83638
|
var VALID_IMAGE_QUALITIES = ["standard", "hd"];
|
|
83443
|
-
var planCommand = new Command("plan").description("Read STORYBOARD.md and show build plan, costs, missing cues, and provider needs").argument("[project-dir]", "Video project directory", ".").option("--stage <stage>", `Stage to plan: ${VALID_STAGES.join("|")}`, "all").option("--beat <id>", "Restrict the plan to one beat").option("--mode <mode>", "Build mode: agent|batch|auto", "auto").option("--skip-narration", "Don't include narration generation in the plan").option("--skip-backdrop", "Don't include backdrop image generation in the plan").option("--skip-video", "Don't include video generation in the plan").option("--skip-music", "Don't include music generation in the plan").option("--tts <provider>", "TTS provider: auto|elevenlabs|kokoro").option("--voice <id>", "Voice id").option("--image-provider <name>", `Image provider: ${VALID_IMAGE_PROVIDERS.join("|")}`).option("--video-provider <name>", `Video provider: ${VALID_VIDEO_PROVIDERS.join("|")}`).option("--music-provider <name>", `Music provider: ${VALID_MUSIC_PROVIDERS.join("|")}`).option("--quality <q>", "Image quality: standard|hd").option("--image-size <s>", "Image size: 1024x1024|1536x1024|1024x1536").option("--composer <provider>", "Batch composer: claude|openai|gemini").option("--force", "Plan regeneration even when outputs already exist").option("--max-cost <usd>", "Fail if estimated cost exceeds this USD cap").action(async (projectDirArg, options) => {
|
|
83639
|
+
var planCommand = new Command("plan").description("Read STORYBOARD.md and show build plan, costs, missing cues, and provider needs").argument("[project-dir]", "Video project directory", ".").option("--stage <stage>", `Stage to plan: ${VALID_STAGES.join("|")}`, "all").option("--beat <id>", "Restrict the plan to one beat").option("--mode <mode>", "Build mode: agent|batch|auto", "auto").option("--skip-narration", "Don't include narration generation in the plan").option("--skip-backdrop", "Don't include backdrop image generation in the plan").option("--skip-video", "Don't include video generation in the plan").option("--skip-music", "Don't include music generation in the plan").option("--tts <provider>", "TTS provider: auto|elevenlabs|openai|kokoro").option("--voice <id>", "Voice id").option("--image-provider <name>", `Image provider: ${VALID_IMAGE_PROVIDERS.join("|")}`).option("--video-provider <name>", `Video provider: ${VALID_VIDEO_PROVIDERS.join("|")}`).option("--music-provider <name>", `Music provider: ${VALID_MUSIC_PROVIDERS.join("|")}`).option("--quality <q>", "Image quality: standard|hd").option("--image-size <s>", "Image size: 1024x1024|1536x1024|1024x1536").option("--composer <provider>", "Batch composer: claude|openai|gemini").option("--force", "Plan regeneration even when outputs already exist").option("--max-cost <usd>", "Fail if estimated cost exceeds this USD cap").action(async (projectDirArg, options) => {
|
|
83444
83640
|
const startedAt = Date.now();
|
|
83445
83641
|
const stage = String(options.stage ?? "all");
|
|
83446
83642
|
if (!VALID_STAGES.includes(stage)) {
|
|
@@ -83631,7 +83827,7 @@ var VALID_STAGES2 = ["assets", "compose", "sync", "render", "all"];
|
|
|
83631
83827
|
var VALID_IMAGE_PROVIDERS2 = ["openai", "gemini", "grok"];
|
|
83632
83828
|
var VALID_VIDEO_PROVIDERS2 = ["seedance", "grok", "kling", "runway", "veo"];
|
|
83633
83829
|
var VALID_MUSIC_PROVIDERS2 = ["elevenlabs", "replicate"];
|
|
83634
|
-
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>", "Build mode: agent|batch|auto", "auto").option("--effort <level>", "Compose effort tier (batch mode only): low|medium|high", "medium").option("--composer <provider>", "Batch composer: claude|openai|gemini").option("--max-cost <usd>", "Fail before provider spend when estimated cost exceeds this USD cap").option("--skip-narration", "Don't dispatch TTS even when beats declare narration cues").option("--skip-backdrop", "Don't dispatch image-gen even when beats declare backdrop cues").option("--skip-video", "Don't dispatch video generation even when beats declare video cues").option("--skip-music", "Don't dispatch music generation even when beats declare music cues").option("--skip-render", "Compose only \u2014 don't render to MP4").option("--tts <provider>", "TTS provider: auto|elevenlabs|kokoro").option("--voice <id>", "Voice id").option("--image-provider <name>", `Image provider: ${VALID_IMAGE_PROVIDERS2.join("|")}`).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(
|
|
83830
|
+
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>", "Build mode: agent|batch|auto", "auto").option("--effort <level>", "Compose effort tier (batch mode only): low|medium|high", "medium").option("--composer <provider>", "Batch composer: claude|openai|gemini").option("--max-cost <usd>", "Fail before provider spend when estimated cost exceeds this USD cap").option("--skip-narration", "Don't dispatch TTS even when beats declare narration cues").option("--skip-backdrop", "Don't dispatch image-gen even when beats declare backdrop cues").option("--skip-video", "Don't dispatch video generation even when beats declare video cues").option("--skip-music", "Don't dispatch music generation even when beats declare music cues").option("--skip-render", "Compose only \u2014 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("--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(
|
|
83635
83831
|
"after",
|
|
83636
83832
|
`
|
|
83637
83833
|
Examples:
|
|
@@ -11,7 +11,7 @@ import type { ElicitForm } from "../adapters/mcp.js";
|
|
|
11
11
|
/** The subset of build args that drive the question set. */
|
|
12
12
|
export interface BuildChoiceArgs {
|
|
13
13
|
stage?: "assets" | "compose" | "sync" | "render" | "all";
|
|
14
|
-
ttsProvider?: "auto" | "elevenlabs" | "kokoro";
|
|
14
|
+
ttsProvider?: "auto" | "elevenlabs" | "openai" | "kokoro";
|
|
15
15
|
skipNarration?: boolean;
|
|
16
16
|
skipBackdrop?: boolean;
|
|
17
17
|
imageProvider?: string;
|