@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
|
@@ -191,8 +191,8 @@ var init_api_keys = __esm({
|
|
|
191
191
|
envVar: "OPENAI_API_KEY",
|
|
192
192
|
label: "OpenAI",
|
|
193
193
|
showInSetup: true,
|
|
194
|
-
setupDescription: "gpt-image-2 image gen ($, default since v0.56), Whisper transcribe, Agent",
|
|
195
|
-
envExampleComment: "OpenAI API Key (Whisper transcription, gpt-image-2 \u2014 default text-to-image since v0.56)",
|
|
194
|
+
setupDescription: "gpt-image-2 image gen ($, default since v0.56), gpt-4o-mini-tts narration, Whisper transcribe, Agent",
|
|
195
|
+
envExampleComment: "OpenAI API Key (Whisper transcription, gpt-4o-mini-tts narration, gpt-image-2 \u2014 default text-to-image since v0.56)",
|
|
196
196
|
envExampleUrl: "https://platform.openai.com/api-keys",
|
|
197
197
|
keyFormat: { prefix: /^sk-/, example: "sk-..." }
|
|
198
198
|
});
|
|
@@ -2299,8 +2299,8 @@ var init_openai = __esm({
|
|
|
2299
2299
|
id: "openai",
|
|
2300
2300
|
label: "OpenAI",
|
|
2301
2301
|
apiKey: "openai",
|
|
2302
|
-
kinds: ["llm", "image", "transcription"],
|
|
2303
|
-
resolverPriority: { image: 1 },
|
|
2302
|
+
kinds: ["llm", "image", "transcription", "speech"],
|
|
2303
|
+
resolverPriority: { image: 1, speech: 2 },
|
|
2304
2304
|
commandsUnlocked: [
|
|
2305
2305
|
"agent -p openai",
|
|
2306
2306
|
"generate image -p openai",
|
|
@@ -4722,16 +4722,19 @@ var init_elevenlabs = __esm({
|
|
|
4722
4722
|
});
|
|
4723
4723
|
|
|
4724
4724
|
// ../ai-providers/dist/kokoro/KokoroProvider.js
|
|
4725
|
-
async function
|
|
4725
|
+
async function loadKokoroRuntime() {
|
|
4726
4726
|
if (factoryOverride)
|
|
4727
|
-
return factoryOverride;
|
|
4727
|
+
return { factory: factoryOverride, device: "cpu" };
|
|
4728
4728
|
try {
|
|
4729
4729
|
const mod = await import("kokoro-js");
|
|
4730
|
-
return mod.KokoroTTS;
|
|
4730
|
+
return { factory: mod.KokoroTTS, device: "cpu" };
|
|
4731
4731
|
} catch (err) {
|
|
4732
|
-
const
|
|
4733
|
-
if (
|
|
4734
|
-
return
|
|
4732
|
+
const workspace = await loadKokoroFromWorkspace();
|
|
4733
|
+
if (workspace)
|
|
4734
|
+
return { factory: workspace, device: "cpu" };
|
|
4735
|
+
const bundled = await loadBundledKokoroRuntime();
|
|
4736
|
+
if (bundled)
|
|
4737
|
+
return bundled;
|
|
4735
4738
|
throw mapKokoroImportError(err);
|
|
4736
4739
|
}
|
|
4737
4740
|
}
|
|
@@ -4751,10 +4754,51 @@ async function loadKokoroFromWorkspace(baseDir = process.cwd()) {
|
|
|
4751
4754
|
return null;
|
|
4752
4755
|
}
|
|
4753
4756
|
}
|
|
4757
|
+
async function loadBundledKokoroRuntime(runtimeDir = process.env.VIBE_KOKORO_RUNTIME) {
|
|
4758
|
+
const base = runtimeDir?.trim();
|
|
4759
|
+
if (!base)
|
|
4760
|
+
return null;
|
|
4761
|
+
try {
|
|
4762
|
+
const { readFile: readFile45, writeFile: writeFile51, mkdir: mkdir26 } = await import("node:fs/promises");
|
|
4763
|
+
const { join: join27, resolve: resolve66 } = await import("node:path");
|
|
4764
|
+
const { pathToFileURL } = await import("node:url");
|
|
4765
|
+
const { homedir: homedir6 } = await import("node:os");
|
|
4766
|
+
const transformersDir = resolve66(base, "node_modules", "@huggingface", "transformers");
|
|
4767
|
+
const ortDistDir = resolve66(base, "node_modules", "onnxruntime-web", "dist");
|
|
4768
|
+
const transformers = await import(pathToFileURL(join27(transformersDir, "dist", "transformers.web.js")).href);
|
|
4769
|
+
const cacheRoot = join27(homedir6(), ".cache", "vibeframe", "models");
|
|
4770
|
+
transformers.env.allowLocalModels = false;
|
|
4771
|
+
transformers.env.useCustomCache = true;
|
|
4772
|
+
transformers.env.customCache = {
|
|
4773
|
+
async match(key) {
|
|
4774
|
+
try {
|
|
4775
|
+
return new Response(await readFile45(join27(cacheRoot, encodeURIComponent(String(key)))));
|
|
4776
|
+
} catch {
|
|
4777
|
+
return void 0;
|
|
4778
|
+
}
|
|
4779
|
+
},
|
|
4780
|
+
async put(key, response) {
|
|
4781
|
+
try {
|
|
4782
|
+
const buf = Buffer.from(await response.arrayBuffer());
|
|
4783
|
+
await mkdir26(cacheRoot, { recursive: true });
|
|
4784
|
+
await writeFile51(join27(cacheRoot, encodeURIComponent(String(key))), buf);
|
|
4785
|
+
} catch {
|
|
4786
|
+
}
|
|
4787
|
+
}
|
|
4788
|
+
};
|
|
4789
|
+
transformers.env.backends.onnx.wasm.wasmPaths = pathToFileURL(ortDistDir + "/").href;
|
|
4790
|
+
const factory = await loadKokoroFromWorkspace(base);
|
|
4791
|
+
if (!factory)
|
|
4792
|
+
return null;
|
|
4793
|
+
return { factory, device: "cpu" };
|
|
4794
|
+
} catch {
|
|
4795
|
+
return null;
|
|
4796
|
+
}
|
|
4797
|
+
}
|
|
4754
4798
|
function mapKokoroImportError(err) {
|
|
4755
4799
|
const code = err instanceof Error && "code" in err ? err.code : void 0;
|
|
4756
4800
|
if (code === "ERR_MODULE_NOT_FOUND" || code === "MODULE_NOT_FOUND") {
|
|
4757
|
-
return new Error("Local Kokoro TTS is unavailable:
|
|
4801
|
+
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.");
|
|
4758
4802
|
}
|
|
4759
4803
|
return err instanceof Error ? err : new Error(String(err));
|
|
4760
4804
|
}
|
|
@@ -4762,10 +4806,12 @@ function loadModel(progress) {
|
|
|
4762
4806
|
if (modelPromise)
|
|
4763
4807
|
return modelPromise;
|
|
4764
4808
|
modelPromise = (async () => {
|
|
4765
|
-
const
|
|
4766
|
-
|
|
4809
|
+
const runtime = await loadKokoroRuntime();
|
|
4810
|
+
const override = process.env.VIBE_ONNX_DEVICE;
|
|
4811
|
+
const device = override === "cpu" || override === "wasm" ? override : runtime.device;
|
|
4812
|
+
return runtime.factory.from_pretrained(KOKORO_MODEL_ID, {
|
|
4767
4813
|
dtype: "q8",
|
|
4768
|
-
device
|
|
4814
|
+
device,
|
|
4769
4815
|
progress_callback: progress ? (raw) => progress(normaliseEvent(raw)) : void 0
|
|
4770
4816
|
});
|
|
4771
4817
|
})().catch((err) => {
|
|
@@ -4849,7 +4895,7 @@ var init_kokoro = __esm({
|
|
|
4849
4895
|
label: "Kokoro (local)",
|
|
4850
4896
|
apiKey: null,
|
|
4851
4897
|
kinds: ["speech"],
|
|
4852
|
-
resolverPriority: { speech:
|
|
4898
|
+
resolverPriority: { speech: 3 }
|
|
4853
4899
|
});
|
|
4854
4900
|
}
|
|
4855
4901
|
});
|
|
@@ -5121,12 +5167,119 @@ var init_openai_image = __esm({
|
|
|
5121
5167
|
}
|
|
5122
5168
|
});
|
|
5123
5169
|
|
|
5170
|
+
// ../ai-providers/dist/openai-tts/OpenAiTtsProvider.js
|
|
5171
|
+
var OPENAI_TTS_VOICES, DEFAULT_VOICE, DEFAULT_MODEL2, TTS_429_MAX_RETRIES2, TTS_429_RETRY_DELAY_MS2, OpenAiTtsProvider, openaiTtsProvider;
|
|
5172
|
+
var init_OpenAiTtsProvider = __esm({
|
|
5173
|
+
"../ai-providers/dist/openai-tts/OpenAiTtsProvider.js"() {
|
|
5174
|
+
"use strict";
|
|
5175
|
+
OPENAI_TTS_VOICES = [
|
|
5176
|
+
"alloy",
|
|
5177
|
+
"ash",
|
|
5178
|
+
"ballad",
|
|
5179
|
+
"cedar",
|
|
5180
|
+
"coral",
|
|
5181
|
+
"echo",
|
|
5182
|
+
"fable",
|
|
5183
|
+
"marin",
|
|
5184
|
+
"nova",
|
|
5185
|
+
"onyx",
|
|
5186
|
+
"sage",
|
|
5187
|
+
"shimmer",
|
|
5188
|
+
"verse"
|
|
5189
|
+
];
|
|
5190
|
+
DEFAULT_VOICE = "marin";
|
|
5191
|
+
DEFAULT_MODEL2 = "gpt-4o-mini-tts";
|
|
5192
|
+
TTS_429_MAX_RETRIES2 = 1;
|
|
5193
|
+
TTS_429_RETRY_DELAY_MS2 = 2e3;
|
|
5194
|
+
OpenAiTtsProvider = class {
|
|
5195
|
+
constructor() {
|
|
5196
|
+
this.id = "openai";
|
|
5197
|
+
this.name = "OpenAI TTS";
|
|
5198
|
+
this.description = "OpenAI cloud text-to-speech (gpt-4o-mini-tts)";
|
|
5199
|
+
this.capabilities = ["text-to-speech"];
|
|
5200
|
+
this.isAvailable = true;
|
|
5201
|
+
this.baseUrl = "https://api.openai.com/v1";
|
|
5202
|
+
}
|
|
5203
|
+
async initialize(config2) {
|
|
5204
|
+
this.apiKey = config2.apiKey;
|
|
5205
|
+
if (config2.baseUrl) {
|
|
5206
|
+
this.baseUrl = config2.baseUrl;
|
|
5207
|
+
}
|
|
5208
|
+
}
|
|
5209
|
+
isConfigured() {
|
|
5210
|
+
return !!this.apiKey;
|
|
5211
|
+
}
|
|
5212
|
+
async textToSpeech(text, options = {}) {
|
|
5213
|
+
if (!this.apiKey) {
|
|
5214
|
+
return { success: false, error: "OpenAI API key not configured" };
|
|
5215
|
+
}
|
|
5216
|
+
const voice = (options.voice ?? DEFAULT_VOICE).toLowerCase();
|
|
5217
|
+
if (!OPENAI_TTS_VOICES.includes(voice)) {
|
|
5218
|
+
return {
|
|
5219
|
+
success: false,
|
|
5220
|
+
error: `Unknown OpenAI voice "${options.voice}". Available voices: ${OPENAI_TTS_VOICES.join(", ")}.`
|
|
5221
|
+
};
|
|
5222
|
+
}
|
|
5223
|
+
try {
|
|
5224
|
+
let response;
|
|
5225
|
+
for (let attempt = 0; ; attempt++) {
|
|
5226
|
+
response = await fetch(`${this.baseUrl}/audio/speech`, {
|
|
5227
|
+
method: "POST",
|
|
5228
|
+
headers: {
|
|
5229
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
5230
|
+
"Content-Type": "application/json"
|
|
5231
|
+
},
|
|
5232
|
+
body: JSON.stringify({
|
|
5233
|
+
model: options.model ?? DEFAULT_MODEL2,
|
|
5234
|
+
input: text,
|
|
5235
|
+
voice,
|
|
5236
|
+
response_format: "mp3",
|
|
5237
|
+
...options.speed !== void 0 && { speed: options.speed },
|
|
5238
|
+
...options.instructions !== void 0 && { instructions: options.instructions }
|
|
5239
|
+
})
|
|
5240
|
+
});
|
|
5241
|
+
if (response.status === 429 && attempt < TTS_429_MAX_RETRIES2) {
|
|
5242
|
+
await new Promise((resolveDelay) => setTimeout(resolveDelay, TTS_429_RETRY_DELAY_MS2 * (attempt + 1)));
|
|
5243
|
+
continue;
|
|
5244
|
+
}
|
|
5245
|
+
break;
|
|
5246
|
+
}
|
|
5247
|
+
if (!response.ok) {
|
|
5248
|
+
const error = await response.text();
|
|
5249
|
+
return { success: false, error: `OpenAI TTS failed: ${error}` };
|
|
5250
|
+
}
|
|
5251
|
+
const arrayBuffer = await response.arrayBuffer();
|
|
5252
|
+
return {
|
|
5253
|
+
success: true,
|
|
5254
|
+
audioBuffer: Buffer.from(arrayBuffer),
|
|
5255
|
+
characterCount: text.length
|
|
5256
|
+
};
|
|
5257
|
+
} catch (error) {
|
|
5258
|
+
return {
|
|
5259
|
+
success: false,
|
|
5260
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
5261
|
+
};
|
|
5262
|
+
}
|
|
5263
|
+
}
|
|
5264
|
+
};
|
|
5265
|
+
openaiTtsProvider = new OpenAiTtsProvider();
|
|
5266
|
+
}
|
|
5267
|
+
});
|
|
5268
|
+
|
|
5269
|
+
// ../ai-providers/dist/openai-tts/index.js
|
|
5270
|
+
var init_openai_tts = __esm({
|
|
5271
|
+
"../ai-providers/dist/openai-tts/index.js"() {
|
|
5272
|
+
"use strict";
|
|
5273
|
+
init_OpenAiTtsProvider();
|
|
5274
|
+
}
|
|
5275
|
+
});
|
|
5276
|
+
|
|
5124
5277
|
// ../ai-providers/dist/runway/RunwayProvider.js
|
|
5125
|
-
var
|
|
5278
|
+
var DEFAULT_MODEL3, RunwayProvider, runwayProvider;
|
|
5126
5279
|
var init_RunwayProvider = __esm({
|
|
5127
5280
|
"../ai-providers/dist/runway/RunwayProvider.js"() {
|
|
5128
5281
|
"use strict";
|
|
5129
|
-
|
|
5282
|
+
DEFAULT_MODEL3 = "gen4.5";
|
|
5130
5283
|
RunwayProvider = class _RunwayProvider {
|
|
5131
5284
|
constructor() {
|
|
5132
5285
|
this.id = "runway";
|
|
@@ -5169,7 +5322,7 @@ var init_RunwayProvider = __esm({
|
|
|
5169
5322
|
"1:1": "960:960"
|
|
5170
5323
|
};
|
|
5171
5324
|
const apiRatio = ratioMap[options?.aspectRatio || "16:9"] || "1280:720";
|
|
5172
|
-
const model = options?.model ||
|
|
5325
|
+
const model = options?.model || DEFAULT_MODEL3;
|
|
5173
5326
|
if (!options?.referenceImage && model !== "gen4.5") {
|
|
5174
5327
|
return {
|
|
5175
5328
|
id: "",
|
|
@@ -5431,11 +5584,11 @@ var init_runway = __esm({
|
|
|
5431
5584
|
|
|
5432
5585
|
// ../ai-providers/dist/kling/KlingProvider.js
|
|
5433
5586
|
import { createHmac } from "node:crypto";
|
|
5434
|
-
var
|
|
5587
|
+
var DEFAULT_MODEL4, STD_MODE_MODELS, KlingProvider, klingProvider;
|
|
5435
5588
|
var init_KlingProvider = __esm({
|
|
5436
5589
|
"../ai-providers/dist/kling/KlingProvider.js"() {
|
|
5437
5590
|
"use strict";
|
|
5438
|
-
|
|
5591
|
+
DEFAULT_MODEL4 = "kling-v2-5-turbo";
|
|
5439
5592
|
STD_MODE_MODELS = ["kling-v2-5-turbo", "kling-v2-6", "kling-v3", "kling-v3-omni"];
|
|
5440
5593
|
KlingProvider = class {
|
|
5441
5594
|
constructor() {
|
|
@@ -5498,7 +5651,7 @@ var init_KlingProvider = __esm({
|
|
|
5498
5651
|
}
|
|
5499
5652
|
try {
|
|
5500
5653
|
const token = this.generateToken();
|
|
5501
|
-
const model = options?.model ||
|
|
5654
|
+
const model = options?.model || DEFAULT_MODEL4;
|
|
5502
5655
|
let mode = options?.mode || "std";
|
|
5503
5656
|
if (!STD_MODE_MODELS.includes(model) && mode === "std") {
|
|
5504
5657
|
mode = "pro";
|
|
@@ -5869,11 +6022,11 @@ var init_kling = __esm({
|
|
|
5869
6022
|
});
|
|
5870
6023
|
|
|
5871
6024
|
// ../ai-providers/dist/grok/GrokProvider.js
|
|
5872
|
-
var
|
|
6025
|
+
var DEFAULT_MODEL5, GrokProvider, grokProvider;
|
|
5873
6026
|
var init_GrokProvider = __esm({
|
|
5874
6027
|
"../ai-providers/dist/grok/GrokProvider.js"() {
|
|
5875
6028
|
"use strict";
|
|
5876
|
-
|
|
6029
|
+
DEFAULT_MODEL5 = "grok-imagine-video";
|
|
5877
6030
|
GrokProvider = class {
|
|
5878
6031
|
constructor() {
|
|
5879
6032
|
this.id = "grok";
|
|
@@ -6040,7 +6193,7 @@ var init_GrokProvider = __esm({
|
|
|
6040
6193
|
try {
|
|
6041
6194
|
const duration = Math.round(Math.min(15, Math.max(1, options?.duration || 5)));
|
|
6042
6195
|
const body = {
|
|
6043
|
-
model:
|
|
6196
|
+
model: DEFAULT_MODEL5,
|
|
6044
6197
|
prompt: prompt3,
|
|
6045
6198
|
duration,
|
|
6046
6199
|
aspect_ratio: options?.aspectRatio || "16:9"
|
|
@@ -11247,9 +11400,11 @@ __export(dist_exports2, {
|
|
|
11247
11400
|
KOKORO_MODEL_ID: () => KOKORO_MODEL_ID,
|
|
11248
11401
|
KlingProvider: () => KlingProvider,
|
|
11249
11402
|
KokoroProvider: () => KokoroProvider,
|
|
11403
|
+
OPENAI_TTS_VOICES: () => OPENAI_TTS_VOICES,
|
|
11250
11404
|
OllamaProvider: () => OllamaProvider,
|
|
11251
11405
|
OpenAIImageProvider: () => OpenAIImageProvider,
|
|
11252
11406
|
OpenAIProvider: () => OpenAIProvider,
|
|
11407
|
+
OpenAiTtsProvider: () => OpenAiTtsProvider,
|
|
11253
11408
|
ReplicateProvider: () => ReplicateProvider,
|
|
11254
11409
|
RunwayProvider: () => RunwayProvider,
|
|
11255
11410
|
WhisperProvider: () => WhisperProvider,
|
|
@@ -11273,9 +11428,12 @@ __export(dist_exports2, {
|
|
|
11273
11428
|
isGeminiTextModelAlias: () => isGeminiTextModelAlias,
|
|
11274
11429
|
klingProvider: () => klingProvider,
|
|
11275
11430
|
kokoroProvider: () => kokoroProvider,
|
|
11431
|
+
loadBundledKokoroRuntime: () => loadBundledKokoroRuntime,
|
|
11432
|
+
loadKokoroFromWorkspace: () => loadKokoroFromWorkspace,
|
|
11276
11433
|
ollamaProvider: () => ollamaProvider,
|
|
11277
11434
|
openaiImageProvider: () => openaiImageProvider,
|
|
11278
11435
|
openaiProvider: () => openaiProvider,
|
|
11436
|
+
openaiTtsProvider: () => openaiTtsProvider,
|
|
11279
11437
|
providerRegistry: () => providerRegistry,
|
|
11280
11438
|
replicateProvider: () => replicateProvider,
|
|
11281
11439
|
resolveGeminiTextModel: () => resolveGeminiTextModel,
|
|
@@ -11298,6 +11456,7 @@ var init_dist2 = __esm({
|
|
|
11298
11456
|
init_elevenlabs();
|
|
11299
11457
|
init_kokoro();
|
|
11300
11458
|
init_openai_image();
|
|
11459
|
+
init_openai_tts();
|
|
11301
11460
|
init_runway();
|
|
11302
11461
|
init_kling();
|
|
11303
11462
|
init_grok();
|
|
@@ -28713,10 +28872,22 @@ var init_esm = __esm({
|
|
|
28713
28872
|
|
|
28714
28873
|
// src/commands/_shared/tts-resolve.ts
|
|
28715
28874
|
async function resolveTtsProvider(preferred = "auto") {
|
|
28716
|
-
|
|
28875
|
+
let choice = preferred;
|
|
28876
|
+
if (choice === "auto") {
|
|
28877
|
+
if (await getConfiguredApiKey("ELEVENLABS_API_KEY")) {
|
|
28878
|
+
choice = "elevenlabs";
|
|
28879
|
+
} else if (await getConfiguredApiKey("OPENAI_API_KEY")) {
|
|
28880
|
+
choice = "openai";
|
|
28881
|
+
} else {
|
|
28882
|
+
choice = "kokoro";
|
|
28883
|
+
}
|
|
28884
|
+
}
|
|
28717
28885
|
if (choice === "elevenlabs") {
|
|
28718
28886
|
return buildElevenLabs();
|
|
28719
28887
|
}
|
|
28888
|
+
if (choice === "openai") {
|
|
28889
|
+
return buildOpenAi();
|
|
28890
|
+
}
|
|
28720
28891
|
return buildKokoro();
|
|
28721
28892
|
}
|
|
28722
28893
|
async function buildElevenLabs() {
|
|
@@ -28732,6 +28903,19 @@ async function buildElevenLabs() {
|
|
|
28732
28903
|
});
|
|
28733
28904
|
return { provider: "elevenlabs", audioExtension: "mp3", call };
|
|
28734
28905
|
}
|
|
28906
|
+
async function buildOpenAi() {
|
|
28907
|
+
const key = await getApiKey("OPENAI_API_KEY", "OpenAI");
|
|
28908
|
+
if (!key) {
|
|
28909
|
+
throw new TtsKeyMissingError("openai");
|
|
28910
|
+
}
|
|
28911
|
+
const provider = new OpenAiTtsProvider();
|
|
28912
|
+
await provider.initialize({ apiKey: key });
|
|
28913
|
+
const call = async (text, opts) => provider.textToSpeech(text, {
|
|
28914
|
+
voice: opts?.voice,
|
|
28915
|
+
speed: opts?.speed
|
|
28916
|
+
});
|
|
28917
|
+
return { provider: "openai", audioExtension: "mp3", call };
|
|
28918
|
+
}
|
|
28735
28919
|
async function buildKokoro() {
|
|
28736
28920
|
const provider = new KokoroProvider();
|
|
28737
28921
|
await provider.initialize({});
|
|
@@ -28744,11 +28928,11 @@ async function buildKokoro() {
|
|
|
28744
28928
|
}
|
|
28745
28929
|
function parseTtsProviderName(value) {
|
|
28746
28930
|
if (!value) return "auto";
|
|
28747
|
-
if (value === "auto" || value === "elevenlabs" || value === "kokoro") {
|
|
28931
|
+
if (value === "auto" || value === "elevenlabs" || value === "openai" || value === "kokoro") {
|
|
28748
28932
|
return value;
|
|
28749
28933
|
}
|
|
28750
28934
|
throw new Error(
|
|
28751
|
-
`Invalid --tts: ${value}. Valid: auto, elevenlabs, kokoro.`
|
|
28935
|
+
`Invalid --tts: ${value}. Valid: auto, elevenlabs, openai, kokoro.`
|
|
28752
28936
|
);
|
|
28753
28937
|
}
|
|
28754
28938
|
var TtsKeyMissingError;
|
|
@@ -28760,7 +28944,7 @@ var init_tts_resolve = __esm({
|
|
|
28760
28944
|
TtsKeyMissingError = class extends Error {
|
|
28761
28945
|
constructor(provider) {
|
|
28762
28946
|
super(
|
|
28763
|
-
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.`
|
|
28947
|
+
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.`
|
|
28764
28948
|
);
|
|
28765
28949
|
this.provider = provider;
|
|
28766
28950
|
this.name = "TtsKeyMissingError";
|
|
@@ -32697,6 +32881,9 @@ var init_storyboard_edit = __esm({
|
|
|
32697
32881
|
import { existsSync as existsSync17 } from "node:fs";
|
|
32698
32882
|
import { readFile as readFile17 } from "node:fs/promises";
|
|
32699
32883
|
import { dirname as dirname9, join as join15, resolve as resolve22 } from "node:path";
|
|
32884
|
+
function backdropCostUsd(quality) {
|
|
32885
|
+
return quality === "hd" ? 0.2 : 0.05;
|
|
32886
|
+
}
|
|
32700
32887
|
async function createBuildPlan(opts) {
|
|
32701
32888
|
const projectDir = resolve22(opts.projectDir);
|
|
32702
32889
|
loadPlanEnv(projectDir);
|
|
@@ -32798,13 +32985,13 @@ async function createBuildPlan(opts) {
|
|
|
32798
32985
|
const backdropCue = backdropPrompt ?? backdropReference?.raw;
|
|
32799
32986
|
const videoCue = videoPrompt ?? videoReference?.raw;
|
|
32800
32987
|
const musicCue = musicPrompt ?? musicReference?.raw;
|
|
32801
|
-
const narrationCost = resolved.narration.resolved === "elevenlabs" ? ELEVENLABS_NARRATION_COST_USD : 0;
|
|
32988
|
+
const narrationCost = resolved.narration.resolved === "elevenlabs" ? ELEVENLABS_NARRATION_COST_USD : resolved.narration.resolved === "openai" ? OPENAI_NARRATION_COST_USD : 0;
|
|
32802
32989
|
const narrationCache = narrationText && !narrationReference ? narrationCacheDescriptor({
|
|
32803
32990
|
beatId: beat.id,
|
|
32804
32991
|
cue: narrationText,
|
|
32805
32992
|
provider: resolved.narration.resolved,
|
|
32806
32993
|
voice,
|
|
32807
|
-
ext: resolved.narration.resolved === "
|
|
32994
|
+
ext: resolved.narration.resolved === "kokoro" ? "wav" : "mp3"
|
|
32808
32995
|
}) : null;
|
|
32809
32996
|
const backdropCache = augmentedBackdropPrompt && !backdropReference ? backdropCacheDescriptor({
|
|
32810
32997
|
beatId: beat.id,
|
|
@@ -32852,7 +33039,7 @@ async function createBuildPlan(opts) {
|
|
|
32852
33039
|
reference: backdropReference,
|
|
32853
33040
|
projectDir,
|
|
32854
33041
|
force: opts.force,
|
|
32855
|
-
cost:
|
|
33042
|
+
cost: backdropCostUsd(imageQuality),
|
|
32856
33043
|
active: includeAssets
|
|
32857
33044
|
}) : null;
|
|
32858
33045
|
const video = videoCue && !opts.skipVideo ? assetPlan({
|
|
@@ -33222,17 +33409,20 @@ function providerInput(opts) {
|
|
|
33222
33409
|
async function resolveNarrationProvider(input, projectDir) {
|
|
33223
33410
|
const requested = input.value.toLowerCase();
|
|
33224
33411
|
const hasElevenLabs = Boolean(await getApiKeyFromConfig("elevenlabs", { cwd: projectDir }));
|
|
33225
|
-
const
|
|
33412
|
+
const hasOpenAi = Boolean(await getApiKeyFromConfig("openai", { cwd: projectDir }));
|
|
33413
|
+
const resolved = requested === "elevenlabs" ? "elevenlabs" : requested === "openai" ? "openai" : requested === "kokoro" ? "kokoro" : hasElevenLabs ? "elevenlabs" : hasOpenAi ? "openai" : "kokoro";
|
|
33414
|
+
const requiresKey = resolved !== "kokoro";
|
|
33415
|
+
const hasKey = resolved === "elevenlabs" ? hasElevenLabs : resolved === "openai" ? hasOpenAi : true;
|
|
33226
33416
|
return {
|
|
33227
33417
|
kind: "narration",
|
|
33228
33418
|
requested: input.requested,
|
|
33229
33419
|
resolved,
|
|
33230
33420
|
source: input.source,
|
|
33231
|
-
requiresKey
|
|
33232
|
-
configured:
|
|
33233
|
-
...
|
|
33234
|
-
...
|
|
33235
|
-
retryWith:
|
|
33421
|
+
requiresKey,
|
|
33422
|
+
configured: hasKey,
|
|
33423
|
+
...requiresKey ? { configKey: resolved } : {},
|
|
33424
|
+
...requiresKey && !hasKey ? { missingKey: providerEnvVar(resolved) } : {},
|
|
33425
|
+
retryWith: requiresKey && !hasKey ? ["vibe setup --full"] : []
|
|
33236
33426
|
};
|
|
33237
33427
|
}
|
|
33238
33428
|
async function keyedProviderResolution(opts, projectDir) {
|
|
@@ -33328,7 +33518,7 @@ function loadPlanEnv(projectDir) {
|
|
|
33328
33518
|
dir = dirname9(dir);
|
|
33329
33519
|
}
|
|
33330
33520
|
}
|
|
33331
|
-
var import_dotenv2,
|
|
33521
|
+
var import_dotenv2, VIDEO_COST_USD, MUSIC_COST_USD, ELEVENLABS_NARRATION_COST_USD, OPENAI_NARRATION_COST_USD, COMPOSE_COST_USD, SUPPORTED_BUILD_IMAGE_PROVIDERS;
|
|
33332
33522
|
var init_build_plan = __esm({
|
|
33333
33523
|
"src/commands/_shared/build-plan.ts"() {
|
|
33334
33524
|
"use strict";
|
|
@@ -33343,10 +33533,10 @@ var init_build_plan = __esm({
|
|
|
33343
33533
|
init_storyboard_parse();
|
|
33344
33534
|
init_project_config();
|
|
33345
33535
|
init_storyboard_edit();
|
|
33346
|
-
BACKDROP_COST_USD = 3;
|
|
33347
33536
|
VIDEO_COST_USD = 5;
|
|
33348
33537
|
MUSIC_COST_USD = 0.5;
|
|
33349
33538
|
ELEVENLABS_NARRATION_COST_USD = 0.05;
|
|
33539
|
+
OPENAI_NARRATION_COST_USD = 0.01;
|
|
33350
33540
|
COMPOSE_COST_USD = 0.06;
|
|
33351
33541
|
SUPPORTED_BUILD_IMAGE_PROVIDERS = ["openai", "gemini", "grok"];
|
|
33352
33542
|
}
|
|
@@ -33864,7 +34054,10 @@ async function executeSceneBuild(opts) {
|
|
|
33864
34054
|
(beat) => beat.narrationStatus === "failed" || beat.backdropStatus === "failed" || beat.videoStatus === "failed" || beat.musicStatus === "failed"
|
|
33865
34055
|
);
|
|
33866
34056
|
stageReports.assets.status = assetFailed ? "failed" : pendingJobs.length > 0 ? "pending-jobs" : "done";
|
|
33867
|
-
stageReports.assets.costUsd = estimateActualAssetCost(
|
|
34057
|
+
stageReports.assets.costUsd = estimateActualAssetCost(
|
|
34058
|
+
beatOutcomes,
|
|
34059
|
+
opts.imageQuality ?? "hd"
|
|
34060
|
+
);
|
|
33868
34061
|
stageReports.assets.retryWith = pendingJobs.map(
|
|
33869
34062
|
(job) => `vibe status job ${job.id} --project ${projectDir} --json`
|
|
33870
34063
|
);
|
|
@@ -35047,11 +35240,11 @@ function shouldRunStage(selected, stage) {
|
|
|
35047
35240
|
if (selected === "all") return true;
|
|
35048
35241
|
return selected === stage;
|
|
35049
35242
|
}
|
|
35050
|
-
function estimateActualAssetCost(outcomes) {
|
|
35243
|
+
function estimateActualAssetCost(outcomes, imageQuality) {
|
|
35051
35244
|
let cost = 0;
|
|
35052
35245
|
for (const outcome of outcomes) {
|
|
35053
35246
|
if (outcome.narrationStatus === "generated") cost += 0.05;
|
|
35054
|
-
if (outcome.backdropStatus === "generated") cost +=
|
|
35247
|
+
if (outcome.backdropStatus === "generated") cost += backdropCostUsd(imageQuality);
|
|
35055
35248
|
if (outcome.videoStatus === "generated" || outcome.videoStatus === "pending") cost += 5;
|
|
35056
35249
|
if (outcome.musicStatus === "generated" || outcome.musicStatus === "pending") cost += 0.5;
|
|
35057
35250
|
}
|
|
@@ -51374,7 +51567,7 @@ function pickOutputPath(data) {
|
|
|
51374
51567
|
}
|
|
51375
51568
|
|
|
51376
51569
|
// src/tools/_shared/elicit.ts
|
|
51377
|
-
var NARRATION_CHOICES = ["kokoro", "elevenlabs"];
|
|
51570
|
+
var NARRATION_CHOICES = ["kokoro", "openai", "elevenlabs"];
|
|
51378
51571
|
var BACKDROP_CHOICES = ["skip", "openai"];
|
|
51379
51572
|
function planBuildElicitation(args) {
|
|
51380
51573
|
const assetsWillRun = args.stage === void 0 || args.stage === "all" || args.stage === "assets";
|
|
@@ -51389,8 +51582,9 @@ function planBuildElicitation(args) {
|
|
|
51389
51582
|
description: "Which TTS engine narrates the video?",
|
|
51390
51583
|
enum: [...NARRATION_CHOICES],
|
|
51391
51584
|
enumNames: [
|
|
51392
|
-
"Kokoro \u2014 free, runs
|
|
51393
|
-
"
|
|
51585
|
+
"Kokoro \u2014 free, runs on this machine (first use downloads a ~90 MB voice model; slower)",
|
|
51586
|
+
"OpenAI \u2014 fast cloud voice, uses your OpenAI API key (~$0.02 per video)",
|
|
51587
|
+
"ElevenLabs \u2014 premium cloud voices, uses your ElevenLabs credits"
|
|
51394
51588
|
]
|
|
51395
51589
|
};
|
|
51396
51590
|
required.push("narration");
|
|
@@ -52595,9 +52789,9 @@ sceneCommand.command("add").description("Add a new scene to a project: AI narrat
|
|
|
52595
52789
|
"Image prompt \u2014 generates assets/scene-<id>.png via the configured image provider"
|
|
52596
52790
|
).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(
|
|
52597
52791
|
"--tts <provider>",
|
|
52598
|
-
"TTS provider: auto, elevenlabs, kokoro (default auto \u2014
|
|
52792
|
+
"TTS provider: auto, elevenlabs, openai, kokoro (default auto \u2014 ElevenLabs key > OpenAI key > Kokoro local)",
|
|
52599
52793
|
"auto"
|
|
52600
|
-
).option("--voice <id>", "Voice id (ElevenLabs name/id, or Kokoro id like af_heart
|
|
52794
|
+
).option("--voice <id>", "Voice id (ElevenLabs name/id, OpenAI voice like marin, or Kokoro id like af_heart)").option(
|
|
52601
52795
|
"--no-audio",
|
|
52602
52796
|
"Skip TTS even when --narration is provided (useful for tests/agent dry runs)"
|
|
52603
52797
|
).option("--no-image", "Skip image generation even when --visuals is provided").option(
|
|
@@ -52858,7 +53052,7 @@ async function executeSceneAdd(opts) {
|
|
|
52858
53052
|
throw error;
|
|
52859
53053
|
}
|
|
52860
53054
|
opts.onProgress?.(
|
|
52861
|
-
resolution.provider === "kokoro" ? "Generating narration with Kokoro (local \u2014 first run downloads ~
|
|
53055
|
+
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..."
|
|
52862
53056
|
);
|
|
52863
53057
|
const tts = await resolution.call(narrationText, {
|
|
52864
53058
|
voice: opts.voice,
|
|
@@ -53618,7 +53812,9 @@ var sceneBuildSchema = external_exports.object({
|
|
|
53618
53812
|
skipVideo: external_exports.boolean().optional().describe("Skip video generation for every beat (use existing MP4 assets if present)."),
|
|
53619
53813
|
skipMusic: external_exports.boolean().optional().describe("Skip music generation for every beat (use existing audio assets if present)."),
|
|
53620
53814
|
skipRender: external_exports.boolean().optional().describe("Stop after compose \u2014 produces compositions/*.html but no final MP4."),
|
|
53621
|
-
ttsProvider: external_exports.enum(["auto", "elevenlabs", "kokoro"]).optional().describe(
|
|
53815
|
+
ttsProvider: external_exports.enum(["auto", "elevenlabs", "openai", "kokoro"]).optional().describe(
|
|
53816
|
+
"TTS provider override. Default 'auto' (elevenlabs key > openai key > local kokoro)."
|
|
53817
|
+
),
|
|
53622
53818
|
voice: external_exports.string().optional().describe("TTS voice id (provider-specific)."),
|
|
53623
53819
|
imageProvider: external_exports.enum(["openai"]).optional().describe("Image provider for backdrops. Default 'openai' (gpt-image-2)."),
|
|
53624
53820
|
videoProvider: external_exports.enum(["seedance", "grok", "kling", "runway", "veo"]).optional().describe("Video provider for per-beat video cues. Default seedance."),
|
|
@@ -57456,7 +57652,7 @@ var planTool = defineTool({
|
|
|
57456
57652
|
skipBackdrop: external_exports.boolean().optional().describe("Don't include backdrop image generation in the plan."),
|
|
57457
57653
|
skipVideo: external_exports.boolean().optional().describe("Don't include video generation in the plan."),
|
|
57458
57654
|
skipMusic: external_exports.boolean().optional().describe("Don't include music generation in the plan."),
|
|
57459
|
-
ttsProvider: external_exports.enum(["auto", "elevenlabs", "kokoro"]).optional().describe("TTS provider override."),
|
|
57655
|
+
ttsProvider: external_exports.enum(["auto", "elevenlabs", "openai", "kokoro"]).optional().describe("TTS provider override."),
|
|
57460
57656
|
voice: external_exports.string().optional().describe("Voice id."),
|
|
57461
57657
|
imageProvider: external_exports.string().optional().describe("Image provider override."),
|
|
57462
57658
|
imageQuality: external_exports.enum(["standard", "hd"]).optional().describe("Image quality override."),
|
|
@@ -145,7 +145,7 @@ export declare const sceneBuildTool: import("../define-tool.js").ToolDefinition<
|
|
|
145
145
|
skipVideo: z.ZodOptional<z.ZodBoolean>;
|
|
146
146
|
skipMusic: z.ZodOptional<z.ZodBoolean>;
|
|
147
147
|
skipRender: z.ZodOptional<z.ZodBoolean>;
|
|
148
|
-
ttsProvider: z.ZodOptional<z.ZodEnum<["auto", "elevenlabs", "kokoro"]>>;
|
|
148
|
+
ttsProvider: z.ZodOptional<z.ZodEnum<["auto", "elevenlabs", "openai", "kokoro"]>>;
|
|
149
149
|
voice: z.ZodOptional<z.ZodString>;
|
|
150
150
|
imageProvider: z.ZodOptional<z.ZodEnum<["openai"]>>;
|
|
151
151
|
videoProvider: z.ZodOptional<z.ZodEnum<["seedance", "grok", "kling", "runway", "veo"]>>;
|
|
@@ -167,7 +167,7 @@ export declare const sceneBuildTool: import("../define-tool.js").ToolDefinition<
|
|
|
167
167
|
skipBackdrop?: boolean | undefined;
|
|
168
168
|
skipRender?: boolean | undefined;
|
|
169
169
|
imageProvider?: "openai" | undefined;
|
|
170
|
-
ttsProvider?: "elevenlabs" | "auto" | "kokoro" | undefined;
|
|
170
|
+
ttsProvider?: "openai" | "elevenlabs" | "auto" | "kokoro" | undefined;
|
|
171
171
|
skipVideo?: boolean | undefined;
|
|
172
172
|
skipMusic?: boolean | undefined;
|
|
173
173
|
videoProvider?: "grok" | "seedance" | "kling" | "runway" | "veo" | undefined;
|
|
@@ -188,7 +188,7 @@ export declare const sceneBuildTool: import("../define-tool.js").ToolDefinition<
|
|
|
188
188
|
skipBackdrop?: boolean | undefined;
|
|
189
189
|
skipRender?: boolean | undefined;
|
|
190
190
|
imageProvider?: "openai" | undefined;
|
|
191
|
-
ttsProvider?: "elevenlabs" | "auto" | "kokoro" | undefined;
|
|
191
|
+
ttsProvider?: "openai" | "elevenlabs" | "auto" | "kokoro" | undefined;
|
|
192
192
|
skipVideo?: boolean | undefined;
|
|
193
193
|
skipMusic?: boolean | undefined;
|
|
194
194
|
videoProvider?: "grok" | "seedance" | "kling" | "runway" | "veo" | undefined;
|
|
@@ -87,7 +87,7 @@ export declare const planTool: import("../define-tool.js").ToolDefinition<z.ZodO
|
|
|
87
87
|
skipBackdrop: z.ZodOptional<z.ZodBoolean>;
|
|
88
88
|
skipVideo: z.ZodOptional<z.ZodBoolean>;
|
|
89
89
|
skipMusic: z.ZodOptional<z.ZodBoolean>;
|
|
90
|
-
ttsProvider: z.ZodOptional<z.ZodEnum<["auto", "elevenlabs", "kokoro"]>>;
|
|
90
|
+
ttsProvider: z.ZodOptional<z.ZodEnum<["auto", "elevenlabs", "openai", "kokoro"]>>;
|
|
91
91
|
voice: z.ZodOptional<z.ZodString>;
|
|
92
92
|
imageProvider: z.ZodOptional<z.ZodString>;
|
|
93
93
|
imageQuality: z.ZodOptional<z.ZodEnum<["standard", "hd"]>>;
|
|
@@ -107,7 +107,7 @@ export declare const planTool: import("../define-tool.js").ToolDefinition<z.ZodO
|
|
|
107
107
|
skipNarration?: boolean | undefined;
|
|
108
108
|
skipBackdrop?: boolean | undefined;
|
|
109
109
|
imageProvider?: string | undefined;
|
|
110
|
-
ttsProvider?: "elevenlabs" | "auto" | "kokoro" | undefined;
|
|
110
|
+
ttsProvider?: "openai" | "elevenlabs" | "auto" | "kokoro" | undefined;
|
|
111
111
|
skipVideo?: boolean | undefined;
|
|
112
112
|
skipMusic?: boolean | undefined;
|
|
113
113
|
videoProvider?: "grok" | "seedance" | "kling" | "runway" | "veo" | undefined;
|
|
@@ -125,7 +125,7 @@ export declare const planTool: import("../define-tool.js").ToolDefinition<z.ZodO
|
|
|
125
125
|
skipNarration?: boolean | undefined;
|
|
126
126
|
skipBackdrop?: boolean | undefined;
|
|
127
127
|
imageProvider?: string | undefined;
|
|
128
|
-
ttsProvider?: "elevenlabs" | "auto" | "kokoro" | undefined;
|
|
128
|
+
ttsProvider?: "openai" | "elevenlabs" | "auto" | "kokoro" | undefined;
|
|
129
129
|
skipVideo?: boolean | undefined;
|
|
130
130
|
skipMusic?: boolean | undefined;
|
|
131
131
|
videoProvider?: "grok" | "seedance" | "kling" | "runway" | "veo" | undefined;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vibeframe/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.113.0",
|
|
4
4
|
"description": "VibeFrame CLI - agentic video workflow runtime",
|
|
5
5
|
"private": false,
|
|
6
6
|
"license": "MIT",
|
|
@@ -83,8 +83,8 @@
|
|
|
83
83
|
"tsx": "^4.21.0",
|
|
84
84
|
"typescript": "^5.3.3",
|
|
85
85
|
"vitest": "^1.2.2",
|
|
86
|
-
"@vibeframe/ai-providers": "0.
|
|
87
|
-
"@vibeframe/core": "0.
|
|
86
|
+
"@vibeframe/ai-providers": "0.113.0",
|
|
87
|
+
"@vibeframe/core": "0.113.0"
|
|
88
88
|
},
|
|
89
89
|
"engines": {
|
|
90
90
|
"node": ">=20"
|