@vibeframe/cli 0.115.3 → 0.115.5
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/CONTEXT.md +1 -1
- package/dist/commands/_shared/execute-fill-gaps.d.ts +0 -2
- package/dist/commands/_shared/image-cost.d.ts +15 -0
- package/dist/commands/_shared/image-cost.test.d.ts +1 -0
- package/dist/commands/_shared/init-templates.d.ts +1 -1
- package/dist/commands/_shared/openai-image.d.ts +4 -3
- package/dist/commands/_shared/scene-build.network.test.d.ts +1 -0
- package/dist/commands/_shared/video-utils.d.ts +3 -1
- package/dist/commands/agent.d.ts +6 -0
- package/dist/commands/generate/video.d.ts +9 -0
- package/dist/commands/generate.d.ts +1 -1
- package/dist/commands/output.d.ts +9 -1
- package/dist/index.js +455 -235
- package/dist/testing/fake-provider-network.d.ts +45 -0
- package/dist/tools/define-tool.js +3 -2
- package/dist/tools/manifest/edit.d.ts +2 -2
- package/dist/tools/manifest/generate.d.ts +4 -4
- package/dist/tools/manifest/index.js +421 -221
- package/dist/tools/manifest/storyboard.d.ts +2 -2
- package/dist/utils/model-lifecycle.d.ts +25 -0
- package/dist/utils/model-lifecycle.test.d.ts +1 -0
- package/dist/utils/remotion-precheck.test.d.ts +1 -0
- package/dist/utils/remotion.d.ts +7 -1
- package/package.json +4 -3
|
@@ -201,8 +201,8 @@ var init_api_keys = __esm({
|
|
|
201
201
|
envVar: "GOOGLE_API_KEY",
|
|
202
202
|
label: "Google",
|
|
203
203
|
showInSetup: true,
|
|
204
|
-
setupDescription: "Gemini \u2014 image gen (free tier), video analysis ($),
|
|
205
|
-
envExampleComment: "Google API Key (Gemini auto-edit suggestions, image gen,
|
|
204
|
+
setupDescription: "Gemini \u2014 image gen (free tier), video analysis ($), Omni video ($$)",
|
|
205
|
+
envExampleComment: "Google API Key (Gemini auto-edit suggestions, image gen, Omni video)",
|
|
206
206
|
envExampleUrl: "https://aistudio.google.com/apikey",
|
|
207
207
|
keyFormat: { prefix: /^AIza/, example: "AIza..." }
|
|
208
208
|
});
|
|
@@ -439,6 +439,114 @@ var init_whisper = __esm({
|
|
|
439
439
|
}
|
|
440
440
|
});
|
|
441
441
|
|
|
442
|
+
// ../ai-providers/dist/catalog/catalog.js
|
|
443
|
+
function listModels(filter = {}) {
|
|
444
|
+
return MODEL_CATALOG.filter((m) => (!filter.provider || m.provider === filter.provider) && (!filter.kind || m.kind === filter.kind));
|
|
445
|
+
}
|
|
446
|
+
function defaultModel(provider, kind) {
|
|
447
|
+
const found = MODEL_CATALOG.find((m) => m.provider === provider && m.kind === kind && m.default);
|
|
448
|
+
if (!found)
|
|
449
|
+
throw new Error(`Model catalog has no default ${kind} model for ${provider}`);
|
|
450
|
+
return found;
|
|
451
|
+
}
|
|
452
|
+
function findModel(provider, kind, aliasOrId) {
|
|
453
|
+
const key = aliasOrId?.trim();
|
|
454
|
+
if (!key)
|
|
455
|
+
return defaultModel(provider, kind);
|
|
456
|
+
const lower = key.toLowerCase();
|
|
457
|
+
return listModels({ provider, kind }).find((m) => m.id === key || m.aliases?.includes(lower));
|
|
458
|
+
}
|
|
459
|
+
function modelLifecycle(spec, now = /* @__PURE__ */ new Date()) {
|
|
460
|
+
if (!spec.shutdown)
|
|
461
|
+
return { state: "served" };
|
|
462
|
+
const remainingMs = Date.parse(`${spec.shutdown}T00:00:00Z`) - now.getTime();
|
|
463
|
+
const instead = spec.replacement ? ` Use ${spec.replacement} instead.` : "";
|
|
464
|
+
if (remainingMs <= 0) {
|
|
465
|
+
return {
|
|
466
|
+
state: "retired",
|
|
467
|
+
shutdown: spec.shutdown,
|
|
468
|
+
message: `${spec.label} (${spec.id}) was shut down by the provider on ${spec.shutdown}.${instead}`
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
const daysLeft = Math.ceil(remainingMs / 864e5);
|
|
472
|
+
return {
|
|
473
|
+
state: "retiring",
|
|
474
|
+
shutdown: spec.shutdown,
|
|
475
|
+
daysLeft,
|
|
476
|
+
message: `${spec.label} (${spec.id}) shuts down on ${spec.shutdown} (${daysLeft} day${daysLeft === 1 ? "" : "s"} left).${instead}`
|
|
477
|
+
};
|
|
478
|
+
}
|
|
479
|
+
function assertModelServed(spec, now = /* @__PURE__ */ new Date()) {
|
|
480
|
+
const lifecycle = modelLifecycle(spec, now);
|
|
481
|
+
if (lifecycle.state === "retired")
|
|
482
|
+
throw new ModelRetiredError(lifecycle.message, spec);
|
|
483
|
+
}
|
|
484
|
+
function modelAliases(provider, kind) {
|
|
485
|
+
return listModels({ provider, kind }).flatMap((m) => m.aliases ?? []);
|
|
486
|
+
}
|
|
487
|
+
var MODEL_CATALOG, ModelRetiredError;
|
|
488
|
+
var init_catalog = __esm({
|
|
489
|
+
"../ai-providers/dist/catalog/catalog.js"() {
|
|
490
|
+
"use strict";
|
|
491
|
+
MODEL_CATALOG = [
|
|
492
|
+
// ── LLMs ──────────────────────────────────────────────────────────────
|
|
493
|
+
{ id: "claude-sonnet-5-5", provider: "claude", kind: "llm", label: "Claude Sonnet 5.5", aliases: ["sonnet"], default: true, status: "ga", price: { usd: 2, per: "1M input tokens" }, note: "Agent, storyboard, translate-srt, motion default" },
|
|
494
|
+
{ id: "claude-opus-5-5", provider: "claude", kind: "llm", label: "Claude Opus 5.5", aliases: ["opus"], status: "ga", price: { usd: 4, per: "1M input tokens" } },
|
|
495
|
+
{ id: "claude-opus-4-6", provider: "claude", kind: "llm", label: "Claude Opus 4.6", aliases: ["opus-4-6"], status: "legacy", price: { usd: 5, per: "1M input tokens" } },
|
|
496
|
+
{ id: "gpt-5.4-mini", provider: "openai", kind: "llm", label: "GPT-5.4 mini", default: true, status: "ga", price: { usd: 0.75, per: "1M input tokens" }, note: "Agent and storyboard default (tools on Chat Completions)" },
|
|
497
|
+
{ id: "gemini-3.8-flash", provider: "gemini", kind: "llm", label: "Gemini 3.8 Flash", aliases: ["flash", "latest", "flash-3.8", "gemini"], default: true, status: "ga", price: { usd: 0.75, per: "1M input tokens", basis: "until 2026-12-31, then $1.50" } },
|
|
498
|
+
{ id: "gemini-3.5-flash", provider: "gemini", kind: "llm", label: "Gemini 3.5 Flash", aliases: ["flash-3.5"], status: "ga" },
|
|
499
|
+
{ id: "gemini-3-flash-preview", provider: "gemini", kind: "llm", label: "Gemini 3 Flash (preview)", aliases: ["flash-3"], status: "preview" },
|
|
500
|
+
{ id: "gemini-3.1-pro-preview", provider: "gemini", kind: "llm", label: "Gemini 3.1 Pro (preview)", aliases: ["pro", "pro-3.1", "3.1-pro", "gemini-3.1-pro"], status: "preview" },
|
|
501
|
+
{ id: "gemini-2.5-flash", provider: "gemini", kind: "llm", label: "Gemini 2.5 Flash", aliases: ["flash-2.5"], status: "legacy", note: "New projects cannot use 2.5 models since 2026-09-18" },
|
|
502
|
+
{ id: "gemini-2.5-pro", provider: "gemini", kind: "llm", label: "Gemini 2.5 Pro", aliases: ["pro-2.5", "2.5-pro"], status: "legacy" },
|
|
503
|
+
{ id: "grok-4.3", provider: "grok", kind: "llm", label: "Grok 4.3", default: true, status: "ga", price: { usd: 1.25, per: "1M input tokens" } },
|
|
504
|
+
{ id: "grok-4.7", provider: "grok", kind: "llm", label: "Grok 4.7", status: "ga", price: { usd: 2, per: "1M input tokens" } },
|
|
505
|
+
// ── Images ────────────────────────────────────────────────────────────
|
|
506
|
+
{ id: "gpt-image-2.5-sunburst", provider: "openai", kind: "image", label: "GPT Image 2.5 Sunburst", aliases: ["2.5", "sunburst"], default: true, status: "ga", price: { usd: 0.211, per: "image", basis: "high, 1024x1024" } },
|
|
507
|
+
{ id: "gpt-image-2.5-flare", provider: "openai", kind: "image", label: "GPT Image 2.5 Flare", aliases: ["flare", "2.5-flare"], status: "ga", price: { usd: 0.211, per: "image", basis: "high, 1024x1024" } },
|
|
508
|
+
{ id: "gpt-image-2", provider: "openai", kind: "image", label: "GPT Image 2", aliases: ["2"], status: "ga", price: { usd: 0.211, per: "image", basis: "high, 1024x1024" } },
|
|
509
|
+
{ id: "gpt-image-1.5", provider: "openai", kind: "image", label: "GPT Image 1.5", aliases: ["1.5"], status: "deprecated", shutdown: "2026-12-01", price: { usd: 0.133, per: "image", basis: "high, 1024x1024" } },
|
|
510
|
+
{ id: "gemini-3.1-flash-image", provider: "gemini", kind: "image", label: "Nano Banana 2", aliases: ["flash", "3.1-flash", "latest"], default: true, status: "ga", price: { usd: 0.067, per: "image", basis: "1K" } },
|
|
511
|
+
{ id: "gemini-3.1-flash-lite-image", provider: "gemini", kind: "image", label: "Nano Banana 2 Lite", aliases: ["lite"], status: "ga", price: { usd: 0.034, per: "image", basis: "1K" } },
|
|
512
|
+
{ id: "gemini-3-pro-image", provider: "gemini", kind: "image", label: "Nano Banana Pro", aliases: ["pro"], status: "ga", price: { usd: 0.134, per: "image", basis: "1K-2K" } },
|
|
513
|
+
{ id: "gemini-2.5-flash-image", provider: "gemini", kind: "image", label: "Nano Banana (2.5 Flash Image)", status: "deprecated", shutdown: "2026-10-02" },
|
|
514
|
+
{ id: "gemini-3.1-flash-image-preview", provider: "gemini", kind: "image", label: "Nano Banana 2 (preview)", status: "deprecated", shutdown: "2026-06-25" },
|
|
515
|
+
{ id: "gemini-3-pro-image-preview", provider: "gemini", kind: "image", label: "Nano Banana Pro (preview)", status: "deprecated", shutdown: "2026-06-25" },
|
|
516
|
+
{ id: "grok-imagine-image", provider: "grok", kind: "image", label: "Grok Imagine Image", default: true, status: "ga", price: { usd: 0.02, per: "image" } },
|
|
517
|
+
{ id: "grok-imagine-image-2.0", provider: "grok", kind: "image", label: "Grok Imagine Image 2.0", aliases: ["pro", "2.0", "quality"], status: "ga", price: { usd: 0.08, per: "image", basis: "medium, 2K" } },
|
|
518
|
+
// ── Video ─────────────────────────────────────────────────────────────
|
|
519
|
+
{ id: "seedance-2.0", provider: "seedance", kind: "video", label: "Seedance 2.0", aliases: ["quality", "2.0"], default: true, status: "ga", price: { usd: 0.3024, per: "second", basis: "720p 16:9" }, note: "4-15 s, native audio" },
|
|
520
|
+
{ id: "seedance-2.0-fast", provider: "seedance", kind: "video", label: "Seedance 2.0 Fast", aliases: ["fast"], status: "ga", price: { usd: 0.2419, per: "second", basis: "720p 16:9" }, note: "4-15 s, up to 720p, native audio" },
|
|
521
|
+
{ id: "seedance-2.5", provider: "seedance", kind: "video", label: "Seedance 2.5", aliases: ["2.5"], status: "ga", price: { usd: 0.473, per: "second", basis: "720p 16:9" }, note: "Opt-in; 4-30 s, native audio" },
|
|
522
|
+
{ id: "gemini-omni-1.1-flash", provider: "omni", kind: "video", label: "Gemini Omni 1.1 Flash", default: true, status: "ga", price: { usd: 0.1, per: "second", basis: "720p" }, note: "Google video default; the model picks 3-10 s; native audio" },
|
|
523
|
+
{ id: "veo-3.1-generate-preview", provider: "veo", kind: "video", label: "Veo 3.1", aliases: ["3.1"], status: "deprecated", shutdown: "2026-10-22", replacement: "`-p omni` (Gemini Omni 1.1 Flash)", price: { usd: 0.4, per: "second", basis: "720p/1080p" }, note: "4-8 s, native audio; explicit `-p veo` only" },
|
|
524
|
+
{ id: "veo-3.1-fast-generate-preview", provider: "veo", kind: "video", label: "Veo 3.1 Fast", aliases: ["3.1-fast"], default: true, status: "deprecated", shutdown: "2026-10-22", replacement: "`-p omni` (Gemini Omni 1.1 Flash)", price: { usd: 0.1, per: "second", basis: "720p" }, note: "4-8 s, native audio; explicit `-p veo` only" },
|
|
525
|
+
{ id: "grok-imagine-video-1.5", provider: "grok", kind: "video", label: "Grok Imagine Video 1.5", aliases: ["1.5"], default: true, status: "ga", price: { usd: 0.14, per: "second", basis: "720p" }, note: "1-15 s, native audio; 720p unless `--resolution` says otherwise" },
|
|
526
|
+
{ id: "grok-imagine-video-1.5-lite", provider: "grok", kind: "video", label: "Grok Imagine Video 1.5 Lite", aliases: ["lite", "1.5-lite"], status: "ga", price: { usd: 0.03, per: "second", basis: "720p" }, note: "1-15 s, native audio" },
|
|
527
|
+
{ id: "grok-imagine-video", provider: "grok", kind: "video", label: "Grok Imagine Video", aliases: ["classic"], status: "legacy", price: { usd: 0.05, per: "second", basis: "480p" }, note: "Previous generation" },
|
|
528
|
+
{ id: "kling-v3", provider: "kling", kind: "video", label: "Kling v3", aliases: ["v3"], default: true, status: "ga", price: { usd: 0.084, per: "second", basis: "std, silent" }, note: "3-15 s, multi-shot; `std` 720p, `pro` 1080p" },
|
|
529
|
+
{ id: "kling-v2-6", provider: "kling", kind: "video", label: "Kling v2.6", aliases: ["v2.6"], status: "ga", price: { usd: 0.042, per: "second", basis: "std 720p" }, note: "5 or 10 s" },
|
|
530
|
+
{ id: "kling-v2-5-turbo", provider: "kling", kind: "video", label: "Kling v2.5 Turbo", aliases: ["v2.5-turbo", "v2.5"], status: "ga", price: { usd: 0.042, per: "second", basis: "std" }, note: "5 or 10 s, no audio" },
|
|
531
|
+
{ id: "gen4.5", provider: "runway", kind: "video", label: "Runway Gen-4.5", default: true, status: "ga", price: { usd: 0.12, per: "second" }, note: "2-10 s, no audio" },
|
|
532
|
+
{ id: "gen4_turbo", provider: "runway", kind: "video", label: "Runway Gen-4 Turbo", status: "ga", price: { usd: 0.05, per: "second" }, note: "Image-to-video only, no audio" },
|
|
533
|
+
// ── Audio ─────────────────────────────────────────────────────────────
|
|
534
|
+
{ id: "eleven_v3", provider: "elevenlabs", kind: "speech", label: "ElevenLabs v3", default: true, status: "ga", price: { usd: 0.08, per: "1K characters" } },
|
|
535
|
+
{ id: "gpt-4o-mini-tts", provider: "openai", kind: "speech", label: "GPT-4o mini TTS", default: true, status: "deprecated", shutdown: "2027-01-06" },
|
|
536
|
+
{ id: "music_v2_5", provider: "elevenlabs", kind: "music", label: "ElevenLabs Music v2.5", default: true, status: "ga", price: { usd: 0.15, per: "minute" } },
|
|
537
|
+
{ id: "eleven_text_to_sound_v2", provider: "elevenlabs", kind: "sound-effect", label: "ElevenLabs Sound Effects v2", default: true, status: "ga", price: { usd: 0.12, per: "minute" }, note: "0.5-30 s" },
|
|
538
|
+
{ id: "whisper-1", provider: "openai", kind: "transcription", label: "Whisper", default: true, status: "deprecated", shutdown: "2027-02-26", note: "Only OpenAI model with word timestamps" }
|
|
539
|
+
];
|
|
540
|
+
ModelRetiredError = class extends Error {
|
|
541
|
+
constructor(message, model) {
|
|
542
|
+
super(message);
|
|
543
|
+
this.model = model;
|
|
544
|
+
this.name = "ModelRetiredError";
|
|
545
|
+
}
|
|
546
|
+
};
|
|
547
|
+
}
|
|
548
|
+
});
|
|
549
|
+
|
|
442
550
|
// ../ai-providers/dist/gemini/gemini-models.js
|
|
443
551
|
function isGeminiTextModelAlias(model) {
|
|
444
552
|
return Object.prototype.hasOwnProperty.call(GEMINI_TEXT_MODEL_ALIASES, model);
|
|
@@ -457,19 +565,10 @@ var GEMINI_DEFAULT_TEXT_MODEL, GEMINI_AGENT_DEFAULT_TEXT_MODEL, GEMINI_TEXT_MODE
|
|
|
457
565
|
var init_gemini_models = __esm({
|
|
458
566
|
"../ai-providers/dist/gemini/gemini-models.js"() {
|
|
459
567
|
"use strict";
|
|
460
|
-
|
|
568
|
+
init_catalog();
|
|
569
|
+
GEMINI_DEFAULT_TEXT_MODEL = defaultModel("gemini", "llm").id;
|
|
461
570
|
GEMINI_AGENT_DEFAULT_TEXT_MODEL = GEMINI_DEFAULT_TEXT_MODEL;
|
|
462
|
-
GEMINI_TEXT_MODEL_ALIASES = {
|
|
463
|
-
flash: GEMINI_DEFAULT_TEXT_MODEL,
|
|
464
|
-
latest: GEMINI_DEFAULT_TEXT_MODEL,
|
|
465
|
-
"flash-3.8": GEMINI_DEFAULT_TEXT_MODEL,
|
|
466
|
-
"flash-3.5": "gemini-3.5-flash",
|
|
467
|
-
"flash-3": "gemini-3-flash-preview",
|
|
468
|
-
"flash-2.5": "gemini-2.5-flash",
|
|
469
|
-
pro: "gemini-3.1-pro-preview",
|
|
470
|
-
"pro-3.1": "gemini-3.1-pro-preview",
|
|
471
|
-
"pro-2.5": "gemini-2.5-pro"
|
|
472
|
-
};
|
|
571
|
+
GEMINI_TEXT_MODEL_ALIASES = Object.fromEntries(listModels({ provider: "gemini", kind: "llm" }).flatMap((m) => (m.aliases ?? []).map((a) => [a, m.id])));
|
|
473
572
|
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";
|
|
474
573
|
}
|
|
475
574
|
});
|
|
@@ -803,19 +902,7 @@ var init_gemini_motion = __esm({
|
|
|
803
902
|
"../ai-providers/dist/gemini/gemini-motion.js"() {
|
|
804
903
|
"use strict";
|
|
805
904
|
init_gemini_models();
|
|
806
|
-
GEMINI_MOTION_MODELS =
|
|
807
|
-
gemini: GEMINI_DEFAULT_TEXT_MODEL,
|
|
808
|
-
flash: GEMINI_DEFAULT_TEXT_MODEL,
|
|
809
|
-
latest: GEMINI_DEFAULT_TEXT_MODEL,
|
|
810
|
-
"flash-3.8": GEMINI_DEFAULT_TEXT_MODEL,
|
|
811
|
-
"flash-3.5": "gemini-3.5-flash",
|
|
812
|
-
"flash-3": "gemini-3-flash-preview",
|
|
813
|
-
"flash-2.5": "gemini-2.5-flash",
|
|
814
|
-
pro: "gemini-3.1-pro-preview",
|
|
815
|
-
"2.5-pro": "gemini-2.5-pro",
|
|
816
|
-
"3.1-pro": "gemini-3.1-pro-preview",
|
|
817
|
-
"pro-3.1": "gemini-3.1-pro-preview"
|
|
818
|
-
};
|
|
905
|
+
GEMINI_MOTION_MODELS = GEMINI_TEXT_MODEL_ALIASES;
|
|
819
906
|
STYLE_USER_INSTRUCTIONS = {
|
|
820
907
|
minimal: "CENTER-ALIGNED pure typography. Thin lines + large title + subtitle. NO glass panels, NO bokeh, NO dark bars. Breathing pulse during hold.",
|
|
821
908
|
corporate: "Data-rich info bar at bottom + top-right badge. Animated number counter. Brand color stripe. Progress bar.",
|
|
@@ -1004,13 +1091,19 @@ var init_http = __esm({
|
|
|
1004
1091
|
// ../ai-providers/dist/gemini/GeminiProvider.js
|
|
1005
1092
|
function resolveVeoModel(alias) {
|
|
1006
1093
|
if (Object.hasOwn(VEO_MODEL_ALIASES, alias)) {
|
|
1007
|
-
return VEO_MODEL_ALIASES[alias];
|
|
1094
|
+
return servedVeoModel(VEO_MODEL_ALIASES[alias]);
|
|
1008
1095
|
}
|
|
1009
1096
|
const valid = Object.keys(VEO_MODEL_ALIASES).join(", ");
|
|
1010
1097
|
const hint = alias === "3.0" ? " Veo 3.0 was shut down by Google on 2025-11-12." : "";
|
|
1011
1098
|
throw new Error(`Unknown Veo model "${alias}". Valid: ${valid}.${hint}`);
|
|
1012
1099
|
}
|
|
1013
|
-
|
|
1100
|
+
function servedVeoModel(id) {
|
|
1101
|
+
const spec = id ? findModel("veo", "video", id) : defaultModel("veo", "video");
|
|
1102
|
+
if (spec)
|
|
1103
|
+
assertModelServed(spec);
|
|
1104
|
+
return spec?.id ?? id;
|
|
1105
|
+
}
|
|
1106
|
+
var VEO_MODEL_ALIASES, GeminiProvider, geminiProvider;
|
|
1014
1107
|
var init_GeminiProvider = __esm({
|
|
1015
1108
|
"../ai-providers/dist/gemini/GeminiProvider.js"() {
|
|
1016
1109
|
"use strict";
|
|
@@ -1018,23 +1111,8 @@ var init_GeminiProvider = __esm({
|
|
|
1018
1111
|
init_gemini_models();
|
|
1019
1112
|
init_gemini_storyboard();
|
|
1020
1113
|
init_http();
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
"3.1-fast": "veo-3.1-fast-generate-preview"
|
|
1024
|
-
};
|
|
1025
|
-
MODEL_MAP = {
|
|
1026
|
-
"flash": "gemini-3.1-flash-image",
|
|
1027
|
-
"3.1-flash": "gemini-3.1-flash-image",
|
|
1028
|
-
"latest": "gemini-3.1-flash-image",
|
|
1029
|
-
"lite": "gemini-3.1-flash-lite-image",
|
|
1030
|
-
"pro": "gemini-3-pro-image",
|
|
1031
|
-
"gemini-3.1-flash-image": "gemini-3.1-flash-image",
|
|
1032
|
-
"gemini-3.1-flash-lite-image": "gemini-3.1-flash-lite-image",
|
|
1033
|
-
"gemini-3-pro-image": "gemini-3-pro-image",
|
|
1034
|
-
"gemini-2.5-flash-image": "gemini-2.5-flash-image",
|
|
1035
|
-
"gemini-3.1-flash-image-preview": "gemini-3.1-flash-image-preview",
|
|
1036
|
-
"gemini-3-pro-image-preview": "gemini-3-pro-image-preview"
|
|
1037
|
-
};
|
|
1114
|
+
init_catalog();
|
|
1115
|
+
VEO_MODEL_ALIASES = Object.fromEntries(listModels({ provider: "veo", kind: "video" }).flatMap((m) => (m.aliases ?? []).map((a) => [a, m.id])));
|
|
1038
1116
|
GeminiProvider = class {
|
|
1039
1117
|
constructor() {
|
|
1040
1118
|
this.id = "gemini";
|
|
@@ -1068,7 +1146,7 @@ var init_GeminiProvider = __esm({
|
|
|
1068
1146
|
}
|
|
1069
1147
|
try {
|
|
1070
1148
|
const veoOpts = options ?? {};
|
|
1071
|
-
const model = veoOpts.model
|
|
1149
|
+
const model = servedVeoModel(veoOpts.model);
|
|
1072
1150
|
const aspectRatioMap = {
|
|
1073
1151
|
"16:9": "16:9",
|
|
1074
1152
|
"9:16": "9:16",
|
|
@@ -1245,7 +1323,7 @@ var init_GeminiProvider = __esm({
|
|
|
1245
1323
|
};
|
|
1246
1324
|
}
|
|
1247
1325
|
try {
|
|
1248
|
-
const model = options?.model
|
|
1326
|
+
const model = servedVeoModel(options?.model ?? findModel("veo", "video", "3.1")?.id);
|
|
1249
1327
|
const instance = {
|
|
1250
1328
|
video: { previousOperationName }
|
|
1251
1329
|
};
|
|
@@ -1293,9 +1371,7 @@ var init_GeminiProvider = __esm({
|
|
|
1293
1371
|
* Resolve model alias to full model ID
|
|
1294
1372
|
*/
|
|
1295
1373
|
resolveModel(model) {
|
|
1296
|
-
|
|
1297
|
-
return MODEL_MAP["flash"];
|
|
1298
|
-
return MODEL_MAP[model] || MODEL_MAP["flash"];
|
|
1374
|
+
return (findModel("gemini", "image", model) ?? defaultModel("gemini", "image")).id;
|
|
1299
1375
|
}
|
|
1300
1376
|
/**
|
|
1301
1377
|
* Check if model is Pro
|
|
@@ -1888,7 +1964,8 @@ var init_gemini_omni = __esm({
|
|
|
1888
1964
|
"../ai-providers/dist/gemini/gemini-omni.js"() {
|
|
1889
1965
|
"use strict";
|
|
1890
1966
|
init_http();
|
|
1891
|
-
|
|
1967
|
+
init_catalog();
|
|
1968
|
+
OMNI_MODEL = defaultModel("omni", "video").id;
|
|
1892
1969
|
API_ROOT = "https://generativelanguage.googleapis.com";
|
|
1893
1970
|
FILE_POLL_INTERVAL_MS = 3e3;
|
|
1894
1971
|
FILE_POLL_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
@@ -2028,6 +2105,14 @@ var init_gemini = __esm({
|
|
|
2028
2105
|
}
|
|
2029
2106
|
});
|
|
2030
2107
|
|
|
2108
|
+
// ../ai-providers/dist/catalog/index.js
|
|
2109
|
+
var init_catalog2 = __esm({
|
|
2110
|
+
"../ai-providers/dist/catalog/index.js"() {
|
|
2111
|
+
"use strict";
|
|
2112
|
+
init_catalog();
|
|
2113
|
+
}
|
|
2114
|
+
});
|
|
2115
|
+
|
|
2031
2116
|
// ../ai-providers/dist/openai/openai-storyboard.js
|
|
2032
2117
|
async function analyzeContent2(apiKey, content, targetDuration, options) {
|
|
2033
2118
|
const creativity = options?.creativity || "low";
|
|
@@ -2040,7 +2125,7 @@ async function analyzeContent2(apiKey, content, targetDuration, options) {
|
|
|
2040
2125
|
Authorization: `Bearer ${apiKey}`
|
|
2041
2126
|
},
|
|
2042
2127
|
body: JSON.stringify({
|
|
2043
|
-
model: "
|
|
2128
|
+
model: defaultModel("openai", "llm").id,
|
|
2044
2129
|
messages: [
|
|
2045
2130
|
{ role: "system", content: systemPrompt },
|
|
2046
2131
|
{ role: "user", content: buildStoryboardUserMessage(content) }
|
|
@@ -2085,6 +2170,7 @@ var init_openai_storyboard = __esm({
|
|
|
2085
2170
|
"../ai-providers/dist/openai/openai-storyboard.js"() {
|
|
2086
2171
|
"use strict";
|
|
2087
2172
|
init_storyboard_prompt();
|
|
2173
|
+
init_catalog();
|
|
2088
2174
|
}
|
|
2089
2175
|
});
|
|
2090
2176
|
|
|
@@ -2094,6 +2180,7 @@ var init_OpenAIProvider = __esm({
|
|
|
2094
2180
|
"../ai-providers/dist/openai/OpenAIProvider.js"() {
|
|
2095
2181
|
"use strict";
|
|
2096
2182
|
init_openai_storyboard();
|
|
2183
|
+
init_catalog();
|
|
2097
2184
|
OpenAIProvider = class {
|
|
2098
2185
|
constructor() {
|
|
2099
2186
|
this.id = "openai-gpt";
|
|
@@ -2103,7 +2190,7 @@ var init_OpenAIProvider = __esm({
|
|
|
2103
2190
|
this.iconUrl = "/icons/openai.svg";
|
|
2104
2191
|
this.isAvailable = true;
|
|
2105
2192
|
this.baseUrl = "https://api.openai.com/v1";
|
|
2106
|
-
this.model = "
|
|
2193
|
+
this.model = defaultModel("openai", "llm").id;
|
|
2107
2194
|
}
|
|
2108
2195
|
async initialize(config2) {
|
|
2109
2196
|
this.apiKey = config2.apiKey;
|
|
@@ -2409,7 +2496,7 @@ Each segment should be 3-10 seconds long.`;
|
|
|
2409
2496
|
Authorization: `Bearer ${this.apiKey}`
|
|
2410
2497
|
},
|
|
2411
2498
|
body: JSON.stringify({
|
|
2412
|
-
model: "
|
|
2499
|
+
model: defaultModel("openai", "llm").id,
|
|
2413
2500
|
// Reasoning tokens count against this cap.
|
|
2414
2501
|
max_completion_tokens: 16384,
|
|
2415
2502
|
response_format: { type: "json_object" },
|
|
@@ -3810,6 +3897,7 @@ var init_ClaudeProvider = __esm({
|
|
|
3810
3897
|
init_claude_analysis();
|
|
3811
3898
|
init_claude_viral();
|
|
3812
3899
|
init_claude_visual_fx();
|
|
3900
|
+
init_catalog();
|
|
3813
3901
|
ClaudeProvider = class {
|
|
3814
3902
|
constructor() {
|
|
3815
3903
|
this.id = "claude";
|
|
@@ -3819,7 +3907,7 @@ var init_ClaudeProvider = __esm({
|
|
|
3819
3907
|
this.iconUrl = "/icons/claude.svg";
|
|
3820
3908
|
this.isAvailable = true;
|
|
3821
3909
|
this.baseUrl = "https://api.anthropic.com/v1";
|
|
3822
|
-
this.model = "claude
|
|
3910
|
+
this.model = defaultModel("claude", "llm").id;
|
|
3823
3911
|
}
|
|
3824
3912
|
async initialize(config2) {
|
|
3825
3913
|
this.apiKey = config2.apiKey;
|
|
@@ -4121,11 +4209,7 @@ Instruction: ${instruction}`
|
|
|
4121
4209
|
return generateNarrationScript(this.api, videoAnalysis, duration, style, language);
|
|
4122
4210
|
}
|
|
4123
4211
|
};
|
|
4124
|
-
ClaudeProvider.MOTION_MODELS = {
|
|
4125
|
-
sonnet: "claude-sonnet-5-5",
|
|
4126
|
-
opus: "claude-opus-5-5",
|
|
4127
|
-
"opus-4-6": "claude-opus-4-6"
|
|
4128
|
-
};
|
|
4212
|
+
ClaudeProvider.MOTION_MODELS = Object.fromEntries(listModels({ provider: "claude", kind: "llm" }).flatMap((m) => (m.aliases ?? []).map((a) => [a, m.id])));
|
|
4129
4213
|
claudeProvider = new ClaudeProvider();
|
|
4130
4214
|
}
|
|
4131
4215
|
});
|
|
@@ -4465,6 +4549,7 @@ var KNOWN_VOICES, TTS_429_MAX_RETRIES, TTS_429_RETRY_DELAY_MS, ELEVENLABS_MUSIC_
|
|
|
4465
4549
|
var init_ElevenLabsProvider = __esm({
|
|
4466
4550
|
"../ai-providers/dist/elevenlabs/ElevenLabsProvider.js"() {
|
|
4467
4551
|
"use strict";
|
|
4552
|
+
init_catalog();
|
|
4468
4553
|
KNOWN_VOICES = {
|
|
4469
4554
|
// Default/popular voices
|
|
4470
4555
|
rachel: "21m00Tcm4TlvDq8ikWAM",
|
|
@@ -4498,7 +4583,7 @@ var init_ElevenLabsProvider = __esm({
|
|
|
4498
4583
|
};
|
|
4499
4584
|
TTS_429_MAX_RETRIES = 1;
|
|
4500
4585
|
TTS_429_RETRY_DELAY_MS = 2e3;
|
|
4501
|
-
ELEVENLABS_MUSIC_MODEL = "
|
|
4586
|
+
ELEVENLABS_MUSIC_MODEL = defaultModel("elevenlabs", "music").id;
|
|
4502
4587
|
ElevenLabsProvider = class {
|
|
4503
4588
|
constructor() {
|
|
4504
4589
|
this.id = "elevenlabs";
|
|
@@ -5162,7 +5247,8 @@ var OPENAI_IMAGE_DEFAULT_MODEL, DEFAULT_MODEL, OpenAIImageProvider, openaiImageP
|
|
|
5162
5247
|
var init_OpenAIImageProvider = __esm({
|
|
5163
5248
|
"../ai-providers/dist/openai-image/OpenAIImageProvider.js"() {
|
|
5164
5249
|
"use strict";
|
|
5165
|
-
|
|
5250
|
+
init_catalog();
|
|
5251
|
+
OPENAI_IMAGE_DEFAULT_MODEL = defaultModel("openai", "image").id;
|
|
5166
5252
|
DEFAULT_MODEL = OPENAI_IMAGE_DEFAULT_MODEL;
|
|
5167
5253
|
OpenAIImageProvider = class {
|
|
5168
5254
|
constructor() {
|
|
@@ -5486,7 +5572,8 @@ var DEFAULT_MODEL3, RunwayProvider, runwayProvider;
|
|
|
5486
5572
|
var init_RunwayProvider = __esm({
|
|
5487
5573
|
"../ai-providers/dist/runway/RunwayProvider.js"() {
|
|
5488
5574
|
"use strict";
|
|
5489
|
-
|
|
5575
|
+
init_catalog();
|
|
5576
|
+
DEFAULT_MODEL3 = defaultModel("runway", "video").id;
|
|
5490
5577
|
RunwayProvider = class _RunwayProvider {
|
|
5491
5578
|
constructor() {
|
|
5492
5579
|
this.id = "runway";
|
|
@@ -5539,6 +5626,13 @@ var init_RunwayProvider = __esm({
|
|
|
5539
5626
|
}
|
|
5540
5627
|
const hasImage = !!options?.referenceImage;
|
|
5541
5628
|
const endpoint = hasImage ? "image_to_video" : "text_to_video";
|
|
5629
|
+
if (!hasImage && apiRatio === "960:960") {
|
|
5630
|
+
return {
|
|
5631
|
+
id: "",
|
|
5632
|
+
status: "failed",
|
|
5633
|
+
error: "Runway text-to-video supports 16:9 and 9:16 only. Use 16:9 or 9:16, or pass an image (-i) for square output."
|
|
5634
|
+
};
|
|
5635
|
+
}
|
|
5542
5636
|
const body = {
|
|
5543
5637
|
model,
|
|
5544
5638
|
promptText: prompt3,
|
|
@@ -5639,7 +5733,9 @@ var init_RunwayProvider = __esm({
|
|
|
5639
5733
|
SUCCEEDED: "completed",
|
|
5640
5734
|
FAILED: "failed",
|
|
5641
5735
|
CANCELLED: "cancelled",
|
|
5642
|
-
THROTTLED
|
|
5736
|
+
// THROTTLED means queued behind the account's concurrency limit; the
|
|
5737
|
+
// task starts on its own, so keep polling.
|
|
5738
|
+
THROTTLED: "pending"
|
|
5643
5739
|
};
|
|
5644
5740
|
const result = {
|
|
5645
5741
|
id: data.id,
|
|
@@ -5649,8 +5745,9 @@ var init_RunwayProvider = __esm({
|
|
|
5649
5745
|
if (data.status === "SUCCEEDED" && data.output && data.output.length > 0) {
|
|
5650
5746
|
result.videoUrl = data.output[0];
|
|
5651
5747
|
}
|
|
5652
|
-
if (data.status === "FAILED"
|
|
5653
|
-
|
|
5748
|
+
if (data.status === "FAILED") {
|
|
5749
|
+
const reason = data.failure || "Generation failed";
|
|
5750
|
+
result.error = data.failureCode ? `${reason} (${data.failureCode})` : reason;
|
|
5654
5751
|
}
|
|
5655
5752
|
return result;
|
|
5656
5753
|
} catch (error) {
|
|
@@ -5662,27 +5759,14 @@ var init_RunwayProvider = __esm({
|
|
|
5662
5759
|
}
|
|
5663
5760
|
}
|
|
5664
5761
|
/**
|
|
5665
|
-
* Cancel
|
|
5762
|
+
* Cancel a pending or running task. Runway documents cancellation as
|
|
5763
|
+
* `DELETE /v1/tasks/{id}` (there is no `/cancel` route).
|
|
5666
5764
|
*/
|
|
5667
5765
|
async cancelGeneration(id) {
|
|
5668
|
-
|
|
5669
|
-
return false;
|
|
5670
|
-
}
|
|
5671
|
-
try {
|
|
5672
|
-
const response = await fetch(`${this.baseUrl}/tasks/${id}/cancel`, {
|
|
5673
|
-
method: "POST",
|
|
5674
|
-
headers: {
|
|
5675
|
-
Authorization: `Bearer ${this.apiKey}`,
|
|
5676
|
-
"X-Runway-Version": _RunwayProvider.API_VERSION
|
|
5677
|
-
}
|
|
5678
|
-
});
|
|
5679
|
-
return response.ok;
|
|
5680
|
-
} catch {
|
|
5681
|
-
return false;
|
|
5682
|
-
}
|
|
5766
|
+
return this.deleteTask(id);
|
|
5683
5767
|
}
|
|
5684
5768
|
/**
|
|
5685
|
-
*
|
|
5769
|
+
* Cancel a running task, or delete a finished one (`DELETE /v1/tasks/{id}`).
|
|
5686
5770
|
*/
|
|
5687
5771
|
async deleteTask(id) {
|
|
5688
5772
|
if (!this.apiKey) {
|
|
@@ -5792,19 +5876,10 @@ var init_runway = __esm({
|
|
|
5792
5876
|
// ../ai-providers/dist/kling/KlingProvider.js
|
|
5793
5877
|
import { createHmac } from "node:crypto";
|
|
5794
5878
|
function resolveKlingModel(alias) {
|
|
5795
|
-
const
|
|
5796
|
-
|
|
5797
|
-
|
|
5798
|
-
|
|
5799
|
-
"v2.6": "kling-v2-6",
|
|
5800
|
-
"kling-v2-6": "kling-v2-6",
|
|
5801
|
-
"v2.5-turbo": "kling-v2-5-turbo",
|
|
5802
|
-
"v2.5": "kling-v2-5-turbo",
|
|
5803
|
-
"kling-v2-5-turbo": "kling-v2-5-turbo"
|
|
5804
|
-
};
|
|
5805
|
-
if (Object.hasOwn(aliases, key))
|
|
5806
|
-
return aliases[key];
|
|
5807
|
-
throw new Error(`Unknown Kling model "${alias}". Valid: v3, v2.6, v2.5-turbo.`);
|
|
5879
|
+
const model = findModel("kling", "video", alias);
|
|
5880
|
+
if (model)
|
|
5881
|
+
return model.id;
|
|
5882
|
+
throw new Error(`Unknown Kling model "${alias}". Valid: ${modelAliases("kling", "video").join(", ")}.`);
|
|
5808
5883
|
}
|
|
5809
5884
|
function klingDuration(model, seconds) {
|
|
5810
5885
|
const requested = typeof seconds === "number" && Number.isFinite(seconds) ? Math.round(seconds) : 5;
|
|
@@ -5816,7 +5891,8 @@ var DEFAULT_MODEL4, STD_MODE_MODELS, KlingProvider, klingProvider;
|
|
|
5816
5891
|
var init_KlingProvider = __esm({
|
|
5817
5892
|
"../ai-providers/dist/kling/KlingProvider.js"() {
|
|
5818
5893
|
"use strict";
|
|
5819
|
-
|
|
5894
|
+
init_catalog();
|
|
5895
|
+
DEFAULT_MODEL4 = defaultModel("kling", "video").id;
|
|
5820
5896
|
STD_MODE_MODELS = ["kling-v2-5-turbo", "kling-v2-6", "kling-v3"];
|
|
5821
5897
|
KlingProvider = class {
|
|
5822
5898
|
constructor() {
|
|
@@ -6255,31 +6331,21 @@ var init_kling = __esm({
|
|
|
6255
6331
|
|
|
6256
6332
|
// ../ai-providers/dist/grok/GrokProvider.js
|
|
6257
6333
|
function resolveGrokVideoModel(alias) {
|
|
6258
|
-
const
|
|
6259
|
-
|
|
6260
|
-
|
|
6261
|
-
|
|
6262
|
-
lite: "grok-imagine-video-1.5-lite",
|
|
6263
|
-
"1.5-lite": "grok-imagine-video-1.5-lite",
|
|
6264
|
-
"grok-imagine-video-1.5-lite": "grok-imagine-video-1.5-lite",
|
|
6265
|
-
classic: "grok-imagine-video",
|
|
6266
|
-
"grok-imagine-video": "grok-imagine-video"
|
|
6267
|
-
};
|
|
6268
|
-
if (Object.hasOwn(aliases, key))
|
|
6269
|
-
return aliases[key];
|
|
6270
|
-
throw new Error(`Unknown Grok video model "${alias}". Valid: 1.5, lite, classic.`);
|
|
6334
|
+
const model = findModel("grok", "video", alias);
|
|
6335
|
+
if (model)
|
|
6336
|
+
return model.id;
|
|
6337
|
+
throw new Error(`Unknown Grok video model "${alias}". Valid: ${modelAliases("grok", "video").join(", ")}.`);
|
|
6271
6338
|
}
|
|
6272
6339
|
function resolveGrokImageModel(alias) {
|
|
6273
|
-
|
|
6274
|
-
|
|
6275
|
-
}
|
|
6276
|
-
return { model: "grok-imagine-image" };
|
|
6340
|
+
const model = (findModel("grok", "image", alias) ?? defaultModel("grok", "image")).id;
|
|
6341
|
+
return model === "grok-imagine-image-2.0" ? { model, quality: "medium" } : { model };
|
|
6277
6342
|
}
|
|
6278
6343
|
var DEFAULT_MODEL5, DEFAULT_VIDEO_RESOLUTION, GROK_VIDEO_RESOLUTIONS, GrokProvider, grokProvider;
|
|
6279
6344
|
var init_GrokProvider = __esm({
|
|
6280
6345
|
"../ai-providers/dist/grok/GrokProvider.js"() {
|
|
6281
6346
|
"use strict";
|
|
6282
|
-
|
|
6347
|
+
init_catalog();
|
|
6348
|
+
DEFAULT_MODEL5 = defaultModel("grok", "video").id;
|
|
6283
6349
|
DEFAULT_VIDEO_RESOLUTION = "720p";
|
|
6284
6350
|
GROK_VIDEO_RESOLUTIONS = ["480p", "720p", "1080p"];
|
|
6285
6351
|
GrokProvider = class {
|
|
@@ -10722,19 +10788,10 @@ var require_src = __commonJS({
|
|
|
10722
10788
|
|
|
10723
10789
|
// ../ai-providers/dist/fal/FalProvider.js
|
|
10724
10790
|
function resolveSeedanceVariant(alias) {
|
|
10725
|
-
const
|
|
10726
|
-
|
|
10727
|
-
|
|
10728
|
-
|
|
10729
|
-
"seedance-2.0": "seedance-2.0",
|
|
10730
|
-
fast: "seedance-2.0-fast",
|
|
10731
|
-
"seedance-2.0-fast": "seedance-2.0-fast",
|
|
10732
|
-
"2.5": "seedance-2.5",
|
|
10733
|
-
"seedance-2.5": "seedance-2.5"
|
|
10734
|
-
};
|
|
10735
|
-
if (Object.hasOwn(aliases, key))
|
|
10736
|
-
return aliases[key];
|
|
10737
|
-
throw new Error(`Unknown Seedance model "${alias}". Valid: quality, fast, 2.5.`);
|
|
10791
|
+
const model = findModel("seedance", "video", alias);
|
|
10792
|
+
if (model)
|
|
10793
|
+
return model.id;
|
|
10794
|
+
throw new Error(`Unknown Seedance model "${alias}". Valid: ${modelAliases("seedance", "video").join(", ")}.`);
|
|
10738
10795
|
}
|
|
10739
10796
|
function estimateSeedanceVideoCostUsd(opts) {
|
|
10740
10797
|
const shortSide = SEEDANCE_SHORT_SIDE[opts.resolution ?? "720p"] ?? 720;
|
|
@@ -10862,6 +10919,7 @@ var init_FalProvider = __esm({
|
|
|
10862
10919
|
"../ai-providers/dist/fal/FalProvider.js"() {
|
|
10863
10920
|
"use strict";
|
|
10864
10921
|
import_client = __toESM(require_src(), 1);
|
|
10922
|
+
init_catalog();
|
|
10865
10923
|
ENDPOINT_TEXT_TO_VIDEO = {
|
|
10866
10924
|
"seedance-2.0": "bytedance/seedance-2.0/text-to-video",
|
|
10867
10925
|
"seedance-2.0-fast": "bytedance/seedance-2.0/fast/text-to-video",
|
|
@@ -11706,6 +11764,8 @@ __export(dist_exports2, {
|
|
|
11706
11764
|
KOKORO_MODEL_ID: () => KOKORO_MODEL_ID,
|
|
11707
11765
|
KlingProvider: () => KlingProvider,
|
|
11708
11766
|
KokoroProvider: () => KokoroProvider,
|
|
11767
|
+
MODEL_CATALOG: () => MODEL_CATALOG,
|
|
11768
|
+
ModelRetiredError: () => ModelRetiredError,
|
|
11709
11769
|
OPENAI_IMAGE_DEFAULT_MODEL: () => OPENAI_IMAGE_DEFAULT_MODEL,
|
|
11710
11770
|
OPENAI_TTS_VOICES: () => OPENAI_TTS_VOICES,
|
|
11711
11771
|
OllamaProvider: () => OllamaProvider,
|
|
@@ -11717,12 +11777,15 @@ __export(dist_exports2, {
|
|
|
11717
11777
|
RunwayProvider: () => RunwayProvider,
|
|
11718
11778
|
VEO_MODEL_ALIASES: () => VEO_MODEL_ALIASES,
|
|
11719
11779
|
WhisperProvider: () => WhisperProvider,
|
|
11780
|
+
assertModelServed: () => assertModelServed,
|
|
11720
11781
|
claudeProvider: () => claudeProvider,
|
|
11782
|
+
defaultModel: () => defaultModel,
|
|
11721
11783
|
defineApiKey: () => defineApiKey,
|
|
11722
11784
|
defineProvider: () => defineProvider,
|
|
11723
11785
|
elevenLabsProvider: () => elevenLabsProvider,
|
|
11724
11786
|
estimateSeedanceVideoCostUsd: () => estimateSeedanceVideoCostUsd,
|
|
11725
11787
|
falProvider: () => falProvider,
|
|
11788
|
+
findModel: () => findModel,
|
|
11726
11789
|
geminiProvider: () => geminiProvider,
|
|
11727
11790
|
getAllApiKeys: () => getAllApiKeys,
|
|
11728
11791
|
getAllProviders: () => getAllProviders,
|
|
@@ -11739,8 +11802,11 @@ __export(dist_exports2, {
|
|
|
11739
11802
|
klingDuration: () => klingDuration,
|
|
11740
11803
|
klingProvider: () => klingProvider,
|
|
11741
11804
|
kokoroProvider: () => kokoroProvider,
|
|
11805
|
+
listModels: () => listModels,
|
|
11742
11806
|
loadBundledKokoroRuntime: () => loadBundledKokoroRuntime,
|
|
11743
11807
|
loadKokoroFromWorkspace: () => loadKokoroFromWorkspace,
|
|
11808
|
+
modelAliases: () => modelAliases,
|
|
11809
|
+
modelLifecycle: () => modelLifecycle,
|
|
11744
11810
|
ollamaProvider: () => ollamaProvider,
|
|
11745
11811
|
omniProvider: () => omniProvider,
|
|
11746
11812
|
openaiImageProvider: () => openaiImageProvider,
|
|
@@ -11767,6 +11833,7 @@ var init_dist2 = __esm({
|
|
|
11767
11833
|
init_define_provider();
|
|
11768
11834
|
init_whisper();
|
|
11769
11835
|
init_gemini();
|
|
11836
|
+
init_catalog2();
|
|
11770
11837
|
init_openai();
|
|
11771
11838
|
init_claude();
|
|
11772
11839
|
init_ollama();
|
|
@@ -20009,12 +20076,15 @@ var init_ai_helpers = __esm({
|
|
|
20009
20076
|
});
|
|
20010
20077
|
|
|
20011
20078
|
// src/commands/_shared/video-utils.ts
|
|
20012
|
-
async function uploadToImgbb(imageBuffer, apiKey) {
|
|
20079
|
+
async function uploadToImgbb(imageBuffer, apiKey, expirationSeconds) {
|
|
20013
20080
|
try {
|
|
20014
20081
|
const base64Image = imageBuffer.toString("base64");
|
|
20015
20082
|
const formData = new URLSearchParams();
|
|
20016
20083
|
formData.append("key", apiKey);
|
|
20017
20084
|
formData.append("image", base64Image);
|
|
20085
|
+
if (expirationSeconds !== void 0) {
|
|
20086
|
+
formData.append("expiration", String(expirationSeconds));
|
|
20087
|
+
}
|
|
20018
20088
|
const response = await fetch("https://api.imgbb.com/1/upload", {
|
|
20019
20089
|
method: "POST",
|
|
20020
20090
|
body: formData
|
|
@@ -20077,7 +20147,10 @@ function awsEncode(value) {
|
|
|
20077
20147
|
(c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`
|
|
20078
20148
|
);
|
|
20079
20149
|
}
|
|
20080
|
-
function
|
|
20150
|
+
function clamp(value, min, max) {
|
|
20151
|
+
return Math.min(max, Math.max(min, Math.round(value)));
|
|
20152
|
+
}
|
|
20153
|
+
function presignS3Url(params) {
|
|
20081
20154
|
const now = /* @__PURE__ */ new Date();
|
|
20082
20155
|
const amzDate = now.toISOString().replace(/[:-]|\.\d{3}/g, "");
|
|
20083
20156
|
const dateStamp = amzDate.slice(0, 8);
|
|
@@ -20088,7 +20161,7 @@ function presignS3PutUrl(params) {
|
|
|
20088
20161
|
"X-Amz-Algorithm": "AWS4-HMAC-SHA256",
|
|
20089
20162
|
"X-Amz-Credential": `${params.accessKeyId}/${credentialScope}`,
|
|
20090
20163
|
"X-Amz-Date": amzDate,
|
|
20091
|
-
"X-Amz-Expires": String(params.ttlSeconds),
|
|
20164
|
+
"X-Amz-Expires": String(clamp(params.ttlSeconds, 1, S3_MAX_PRESIGN_SECONDS)),
|
|
20092
20165
|
"X-Amz-SignedHeaders": "host"
|
|
20093
20166
|
};
|
|
20094
20167
|
if (params.sessionToken) {
|
|
@@ -20096,7 +20169,7 @@ function presignS3PutUrl(params) {
|
|
|
20096
20169
|
}
|
|
20097
20170
|
const canonicalQuery = Object.entries(query).sort(([a], [b]) => a.localeCompare(b)).map(([key, value]) => `${awsEncode(key)}=${awsEncode(value)}`).join("&");
|
|
20098
20171
|
const canonicalRequest = [
|
|
20099
|
-
|
|
20172
|
+
params.method,
|
|
20100
20173
|
canonicalUri,
|
|
20101
20174
|
canonicalQuery,
|
|
20102
20175
|
`host:${host}`,
|
|
@@ -20155,7 +20228,8 @@ async function resolveUploadHost() {
|
|
|
20155
20228
|
const ext = extensionFor(opts);
|
|
20156
20229
|
const prefix = safePrefix(settings.s3.prefix);
|
|
20157
20230
|
const key = `${prefix}/${Date.now()}-${randomUUID()}.${ext}`;
|
|
20158
|
-
const presignedUrl =
|
|
20231
|
+
const presignedUrl = presignS3Url({
|
|
20232
|
+
method: "PUT",
|
|
20159
20233
|
accessKeyId,
|
|
20160
20234
|
secretAccessKey,
|
|
20161
20235
|
sessionToken,
|
|
@@ -20174,10 +20248,26 @@ async function resolveUploadHost() {
|
|
|
20174
20248
|
if (!response.ok) {
|
|
20175
20249
|
throw new Error(`S3 upload failed (${response.status}): ${response.statusText}`);
|
|
20176
20250
|
}
|
|
20251
|
+
if (settings.s3.publicBaseUrl) {
|
|
20252
|
+
return {
|
|
20253
|
+
provider: "s3",
|
|
20254
|
+
url: publicS3Url({ region, bucket, key, publicBaseUrl: settings.s3.publicBaseUrl })
|
|
20255
|
+
};
|
|
20256
|
+
}
|
|
20257
|
+
const ttlSeconds = clamp(settings.ttlSeconds, 1, S3_MAX_PRESIGN_SECONDS);
|
|
20177
20258
|
return {
|
|
20178
20259
|
provider: "s3",
|
|
20179
|
-
url:
|
|
20180
|
-
|
|
20260
|
+
url: presignS3Url({
|
|
20261
|
+
method: "GET",
|
|
20262
|
+
accessKeyId,
|
|
20263
|
+
secretAccessKey,
|
|
20264
|
+
sessionToken,
|
|
20265
|
+
region,
|
|
20266
|
+
bucket,
|
|
20267
|
+
key,
|
|
20268
|
+
ttlSeconds
|
|
20269
|
+
}),
|
|
20270
|
+
expiresAt: new Date(Date.now() + ttlSeconds * 1e3).toISOString()
|
|
20181
20271
|
};
|
|
20182
20272
|
}
|
|
20183
20273
|
};
|
|
@@ -20189,19 +20279,28 @@ async function resolveUploadHost() {
|
|
|
20189
20279
|
if (!imgbbKey) {
|
|
20190
20280
|
throw new Error("IMGBB_API_KEY required for image-to-video uploads.");
|
|
20191
20281
|
}
|
|
20192
|
-
const
|
|
20282
|
+
const expiration = clamp(settings.ttlSeconds, IMGBB_MIN_EXPIRATION_SECONDS, IMGBB_MAX_EXPIRATION_SECONDS);
|
|
20283
|
+
const result = await uploadToImgbb(imageBuffer, imgbbKey, expiration);
|
|
20193
20284
|
if (!result.success || !result.url) {
|
|
20194
20285
|
throw new Error(`ImgBB upload failed: ${result.error ?? "unknown error"}`);
|
|
20195
20286
|
}
|
|
20196
|
-
return {
|
|
20287
|
+
return {
|
|
20288
|
+
provider: "imgbb",
|
|
20289
|
+
url: result.url,
|
|
20290
|
+
expiresAt: new Date(Date.now() + expiration * 1e3).toISOString()
|
|
20291
|
+
};
|
|
20197
20292
|
}
|
|
20198
20293
|
};
|
|
20199
20294
|
}
|
|
20295
|
+
var S3_MAX_PRESIGN_SECONDS, IMGBB_MIN_EXPIRATION_SECONDS, IMGBB_MAX_EXPIRATION_SECONDS;
|
|
20200
20296
|
var init_upload_host = __esm({
|
|
20201
20297
|
"src/utils/upload-host.ts"() {
|
|
20202
20298
|
"use strict";
|
|
20203
20299
|
init_config();
|
|
20204
20300
|
init_video_utils();
|
|
20301
|
+
S3_MAX_PRESIGN_SECONDS = 7 * 24 * 60 * 60;
|
|
20302
|
+
IMGBB_MIN_EXPIRATION_SECONDS = 60;
|
|
20303
|
+
IMGBB_MAX_EXPIRATION_SECONDS = 15552e3;
|
|
20205
20304
|
}
|
|
20206
20305
|
});
|
|
20207
20306
|
|
|
@@ -20842,6 +20941,7 @@ async function executeVideoGenerate(options) {
|
|
|
20842
20941
|
negative,
|
|
20843
20942
|
resolution,
|
|
20844
20943
|
veoModel = "3.1-fast",
|
|
20944
|
+
runwayModel,
|
|
20845
20945
|
seedanceModel = "quality",
|
|
20846
20946
|
grokModel,
|
|
20847
20947
|
klingModel,
|
|
@@ -20931,6 +21031,7 @@ async function executeVideoGenerate(options) {
|
|
|
20931
21031
|
await runway.initialize({ apiKey: key });
|
|
20932
21032
|
const result = await runway.generateVideo(prompt3, {
|
|
20933
21033
|
prompt: prompt3,
|
|
21034
|
+
model: runwayModel,
|
|
20934
21035
|
referenceImage,
|
|
20935
21036
|
duration,
|
|
20936
21037
|
aspectRatio: ratio,
|
|
@@ -30413,8 +30514,43 @@ function outputSuccess(opts) {
|
|
|
30413
30514
|
const data = opts.data;
|
|
30414
30515
|
const primary = data.outputPath ?? data.output ?? data.path ?? data.url ?? data.id;
|
|
30415
30516
|
if (primary !== void 0) console.log(String(primary));
|
|
30517
|
+
return;
|
|
30518
|
+
}
|
|
30519
|
+
if (opts.dryRun && !opts.humanRendered) {
|
|
30520
|
+
printDryRunSummary(opts.command, costUsd, opts.data, opts.warnings ?? []);
|
|
30416
30521
|
}
|
|
30417
30522
|
}
|
|
30523
|
+
function printWarnings(warnings) {
|
|
30524
|
+
if (isJsonMode()) return;
|
|
30525
|
+
for (const warning of warnings) {
|
|
30526
|
+
process.stderr.write(`${source_default.yellow(`Warning: ${warning}`)}
|
|
30527
|
+
`);
|
|
30528
|
+
}
|
|
30529
|
+
}
|
|
30530
|
+
function formatDryRunValue(value) {
|
|
30531
|
+
const text = Array.isArray(value) ? value.map((v) => formatDryRunValue(v)).join(", ") : typeof value === "object" ? JSON.stringify(value) : String(value);
|
|
30532
|
+
return text.length > 80 ? `${text.slice(0, 77)}...` : text;
|
|
30533
|
+
}
|
|
30534
|
+
function printDryRunSummary(command, costUsd, data, warnings) {
|
|
30535
|
+
const params = data.params && typeof data.params === "object" ? data.params : data;
|
|
30536
|
+
const rows = [
|
|
30537
|
+
["cost", costUsd > 0 ? `up to $${costUsd.toFixed(2)} (estimate)` : "free"]
|
|
30538
|
+
];
|
|
30539
|
+
for (const [key, value] of Object.entries(params)) {
|
|
30540
|
+
if (value === void 0 || value === null || value === "") continue;
|
|
30541
|
+
if (Array.isArray(value) && value.length === 0) continue;
|
|
30542
|
+
rows.push([key, formatDryRunValue(value)]);
|
|
30543
|
+
}
|
|
30544
|
+
const width = Math.max(...rows.map(([key]) => key.length));
|
|
30545
|
+
console.log();
|
|
30546
|
+
console.log(`${source_default.bold.cyan(`Dry run: vibe ${command}`)} ${source_default.dim("(nothing was sent)")}`);
|
|
30547
|
+
for (const [key, value] of rows) {
|
|
30548
|
+
console.log(` ${source_default.dim(key.padEnd(width))} ${value}`);
|
|
30549
|
+
}
|
|
30550
|
+
printWarnings(warnings);
|
|
30551
|
+
console.log(source_default.dim(" Run again without --dry-run to execute."));
|
|
30552
|
+
console.log();
|
|
30553
|
+
}
|
|
30418
30554
|
function log(...args) {
|
|
30419
30555
|
if (!isJsonMode() && !isQuietMode()) {
|
|
30420
30556
|
console.log(...args);
|
|
@@ -37890,16 +38026,14 @@ import { tmpdir } from "node:os";
|
|
|
37890
38026
|
import { createHash as createHash4 } from "node:crypto";
|
|
37891
38027
|
async function ensureRemotionInstalled() {
|
|
37892
38028
|
try {
|
|
37893
|
-
await execSafe("
|
|
38029
|
+
await execSafe("npm", ["--version"], { timeout: 3e4 });
|
|
37894
38030
|
return null;
|
|
37895
38031
|
} catch (error) {
|
|
37896
38032
|
const detail = error instanceof Error ? error.message : String(error);
|
|
37897
|
-
console.error(`[Remotion] ensureRemotionInstalled failed: ${detail.slice(0, 300)}`);
|
|
37898
38033
|
return [
|
|
37899
|
-
"Remotion
|
|
38034
|
+
"Remotion renders need npm to install the Remotion CLI into a temporary project.",
|
|
37900
38035
|
` Debug: ${detail.slice(0, 200)}`,
|
|
37901
|
-
" Fix: npm
|
|
37902
|
-
" Or ensure npx is available and can download @remotion/cli on demand."
|
|
38036
|
+
" Fix: install Node.js 20+ (which includes npm) and make sure `npm` is on PATH."
|
|
37903
38037
|
].join("\n");
|
|
37904
38038
|
}
|
|
37905
38039
|
}
|
|
@@ -39022,7 +39156,7 @@ ${textsToTranslate}`;
|
|
|
39022
39156
|
Authorization: `Bearer ${openaiKey}`
|
|
39023
39157
|
},
|
|
39024
39158
|
body: JSON.stringify({
|
|
39025
|
-
model: "
|
|
39159
|
+
model: defaultModel("openai", "llm").id,
|
|
39026
39160
|
messages: [{ role: "user", content: translatePrompt }]
|
|
39027
39161
|
})
|
|
39028
39162
|
});
|
|
@@ -39050,7 +39184,7 @@ ${textsToTranslate}`;
|
|
|
39050
39184
|
"anthropic-version": "2023-06-01"
|
|
39051
39185
|
},
|
|
39052
39186
|
body: JSON.stringify({
|
|
39053
|
-
model: "claude
|
|
39187
|
+
model: defaultModel("claude", "llm").id,
|
|
39054
39188
|
max_tokens: 16e3,
|
|
39055
39189
|
messages: [{ role: "user", content: translatePrompt }]
|
|
39056
39190
|
})
|
|
@@ -39101,6 +39235,7 @@ var init_translate_srt = __esm({
|
|
|
39101
39235
|
"src/commands/_shared/edit/translate-srt.ts"() {
|
|
39102
39236
|
"use strict";
|
|
39103
39237
|
init_subtitle();
|
|
39238
|
+
init_dist2();
|
|
39104
39239
|
}
|
|
39105
39240
|
});
|
|
39106
39241
|
|
|
@@ -40302,22 +40437,13 @@ function analyzeGapFillability(gaps, videoClips, sources) {
|
|
|
40302
40437
|
return { gap, canExtendBefore, canExtendAfter, remainingGap, gapStart };
|
|
40303
40438
|
});
|
|
40304
40439
|
}
|
|
40305
|
-
async function
|
|
40440
|
+
async function uploadFrame(host, framePath) {
|
|
40306
40441
|
try {
|
|
40307
|
-
const
|
|
40308
|
-
|
|
40309
|
-
|
|
40310
|
-
formData.append("key", imgbbApiKey);
|
|
40311
|
-
formData.append("image", frameBase64);
|
|
40312
|
-
const response = await fetch("https://api.imgbb.com/1/upload", {
|
|
40313
|
-
method: "POST",
|
|
40314
|
-
body: formData
|
|
40442
|
+
const upload = await host.uploadImage(await readFile24(framePath), {
|
|
40443
|
+
filename: framePath,
|
|
40444
|
+
mimeType: "image/png"
|
|
40315
40445
|
});
|
|
40316
|
-
|
|
40317
|
-
if (!data.success || !data.data?.url) {
|
|
40318
|
-
return { error: data.error?.message || "Upload failed" };
|
|
40319
|
-
}
|
|
40320
|
-
return { url: data.data.url };
|
|
40446
|
+
return { url: upload.url };
|
|
40321
40447
|
} catch (err) {
|
|
40322
40448
|
return { error: err instanceof Error ? err.message : String(err) };
|
|
40323
40449
|
}
|
|
@@ -40468,11 +40594,13 @@ async function executeFillGaps(options) {
|
|
|
40468
40594
|
await mkdir16(footageDir, { recursive: true });
|
|
40469
40595
|
}
|
|
40470
40596
|
humanLines.push("Generating AI Videos");
|
|
40471
|
-
|
|
40472
|
-
|
|
40597
|
+
let uploadHost;
|
|
40598
|
+
try {
|
|
40599
|
+
uploadHost = await resolveUploadHost();
|
|
40600
|
+
} catch (err) {
|
|
40473
40601
|
return {
|
|
40474
40602
|
success: false,
|
|
40475
|
-
error:
|
|
40603
|
+
error: err instanceof Error ? err.message : String(err),
|
|
40476
40604
|
humanLines
|
|
40477
40605
|
};
|
|
40478
40606
|
}
|
|
@@ -40516,12 +40644,12 @@ async function executeFillGaps(options) {
|
|
|
40516
40644
|
humanLines
|
|
40517
40645
|
};
|
|
40518
40646
|
}
|
|
40519
|
-
onProgress(
|
|
40520
|
-
const upload = await
|
|
40647
|
+
onProgress(`Uploading frame via ${uploadHost.provider}...`);
|
|
40648
|
+
const upload = await uploadFrame(uploadHost, framePath);
|
|
40521
40649
|
if (!upload.url) {
|
|
40522
40650
|
return {
|
|
40523
40651
|
success: false,
|
|
40524
|
-
error: `Failed to upload frame
|
|
40652
|
+
error: `Failed to upload frame via ${uploadHost.provider}: ${upload.error || "unknown"}`,
|
|
40525
40653
|
humanLines
|
|
40526
40654
|
};
|
|
40527
40655
|
}
|
|
@@ -40596,7 +40724,7 @@ async function executeFillGaps(options) {
|
|
|
40596
40724
|
humanLines.push(" Failed to extract frame for continuation");
|
|
40597
40725
|
break;
|
|
40598
40726
|
}
|
|
40599
|
-
const extUpload = await
|
|
40727
|
+
const extUpload = await uploadFrame(uploadHost, lastFramePath);
|
|
40600
40728
|
if (!extUpload.url) {
|
|
40601
40729
|
humanLines.push(" Failed to upload continuation frame");
|
|
40602
40730
|
break;
|
|
@@ -40719,6 +40847,7 @@ var init_execute_fill_gaps = __esm({
|
|
|
40719
40847
|
init_dist2();
|
|
40720
40848
|
init_engine();
|
|
40721
40849
|
init_api_key();
|
|
40850
|
+
init_upload_host();
|
|
40722
40851
|
init_exec_safe();
|
|
40723
40852
|
init_project_resolver();
|
|
40724
40853
|
init_ai_helpers();
|
|
@@ -40786,6 +40915,13 @@ __export(ai_motion_exports, {
|
|
|
40786
40915
|
import { resolve as resolve33 } from "node:path";
|
|
40787
40916
|
import { existsSync as existsSync33 } from "node:fs";
|
|
40788
40917
|
import { readFile as readFile25, writeFile as writeFile26 } from "node:fs/promises";
|
|
40918
|
+
function resolveMotionModel(alias) {
|
|
40919
|
+
const claude = findModel("claude", "llm", alias);
|
|
40920
|
+
if (claude) return { provider: "claude", modelId: claude.id };
|
|
40921
|
+
const gemini = findModel("gemini", "llm", alias);
|
|
40922
|
+
if (gemini) return { provider: "gemini", modelId: gemini.id };
|
|
40923
|
+
return { provider: "claude", modelId: defaultModel("claude", "llm").id };
|
|
40924
|
+
}
|
|
40789
40925
|
async function getOptionalGoogleApiKey() {
|
|
40790
40926
|
const configKey = await getApiKeyFromConfig("google");
|
|
40791
40927
|
if (configKey) return configKey;
|
|
@@ -40800,7 +40936,7 @@ function normalizeUnderstand(value) {
|
|
|
40800
40936
|
}
|
|
40801
40937
|
async function executeMotion(options) {
|
|
40802
40938
|
const modelAlias = options.model || "sonnet";
|
|
40803
|
-
const modelConfig =
|
|
40939
|
+
const modelConfig = resolveMotionModel(modelAlias);
|
|
40804
40940
|
const useGemini = modelConfig.provider === "gemini";
|
|
40805
40941
|
const width = options.width || 1920;
|
|
40806
40942
|
const height = options.height || 1080;
|
|
@@ -41179,7 +41315,6 @@ function registerMotionCommand(aiCommand) {
|
|
|
41179
41315
|
}
|
|
41180
41316
|
});
|
|
41181
41317
|
}
|
|
41182
|
-
var MODEL_MAP2;
|
|
41183
41318
|
var init_ai_motion = __esm({
|
|
41184
41319
|
"src/commands/ai-motion.ts"() {
|
|
41185
41320
|
"use strict";
|
|
@@ -41190,14 +41325,6 @@ var init_ai_motion = __esm({
|
|
|
41190
41325
|
init_config();
|
|
41191
41326
|
init_output();
|
|
41192
41327
|
init_validate();
|
|
41193
|
-
MODEL_MAP2 = {
|
|
41194
|
-
sonnet: { provider: "claude", modelId: "claude-sonnet-5-5" },
|
|
41195
|
-
opus: { provider: "claude", modelId: "claude-opus-5-5" },
|
|
41196
|
-
"opus-4-6": { provider: "claude", modelId: "claude-opus-4-6" },
|
|
41197
|
-
gemini: { provider: "gemini", modelId: GEMINI_DEFAULT_TEXT_MODEL },
|
|
41198
|
-
"gemini-2.5-pro": { provider: "gemini", modelId: "gemini-2.5-pro" },
|
|
41199
|
-
"gemini-3.1-pro": { provider: "gemini", modelId: "gemini-3.1-pro-preview" }
|
|
41200
|
-
};
|
|
41201
41328
|
}
|
|
41202
41329
|
});
|
|
41203
41330
|
|
|
@@ -44028,6 +44155,34 @@ var init_thumbnail = __esm({
|
|
|
44028
44155
|
}
|
|
44029
44156
|
});
|
|
44030
44157
|
|
|
44158
|
+
// src/utils/model-lifecycle.ts
|
|
44159
|
+
function videoModelSpec(provider, flags) {
|
|
44160
|
+
const catalogProvider = provider === "fal" ? "seedance" : provider;
|
|
44161
|
+
const flag = VIDEO_MODEL_FLAG[catalogProvider];
|
|
44162
|
+
return findModel(catalogProvider, "video", flag ? flags[flag] : void 0);
|
|
44163
|
+
}
|
|
44164
|
+
function checkModelLifecycle(spec, now = /* @__PURE__ */ new Date()) {
|
|
44165
|
+
if (!spec) return [];
|
|
44166
|
+
const lifecycle = modelLifecycle(spec, now);
|
|
44167
|
+
if (lifecycle.state === "retired") exitWithError(usageError(lifecycle.message));
|
|
44168
|
+
return lifecycle.state === "retiring" ? [lifecycle.message] : [];
|
|
44169
|
+
}
|
|
44170
|
+
var VIDEO_MODEL_FLAG;
|
|
44171
|
+
var init_model_lifecycle = __esm({
|
|
44172
|
+
"src/utils/model-lifecycle.ts"() {
|
|
44173
|
+
"use strict";
|
|
44174
|
+
init_dist2();
|
|
44175
|
+
init_output();
|
|
44176
|
+
VIDEO_MODEL_FLAG = {
|
|
44177
|
+
seedance: "seedanceModel",
|
|
44178
|
+
grok: "grokModel",
|
|
44179
|
+
kling: "klingModel",
|
|
44180
|
+
veo: "veoModel",
|
|
44181
|
+
runway: "runwayModel"
|
|
44182
|
+
};
|
|
44183
|
+
}
|
|
44184
|
+
});
|
|
44185
|
+
|
|
44031
44186
|
// src/commands/generate/video-extend.ts
|
|
44032
44187
|
import { resolve as resolve48 } from "node:path";
|
|
44033
44188
|
import { writeFile as writeFile34 } from "node:fs/promises";
|
|
@@ -44039,11 +44194,22 @@ function registerVideoExtendCommand(parent) {
|
|
|
44039
44194
|
if (options.output) {
|
|
44040
44195
|
validateOutputPath(options.output);
|
|
44041
44196
|
}
|
|
44197
|
+
let lifecycleWarnings = [];
|
|
44198
|
+
if (provider === "veo") {
|
|
44199
|
+
try {
|
|
44200
|
+
resolveVeoModel(options.veoModel);
|
|
44201
|
+
} catch (err) {
|
|
44202
|
+
exitWithError(usageError(err instanceof Error ? err.message : String(err)));
|
|
44203
|
+
}
|
|
44204
|
+
lifecycleWarnings = checkModelLifecycle(findModel("veo", "video", options.veoModel));
|
|
44205
|
+
if (!options.dryRun) printWarnings(lifecycleWarnings);
|
|
44206
|
+
}
|
|
44042
44207
|
if (options.dryRun) {
|
|
44043
44208
|
outputSuccess({
|
|
44044
44209
|
command: "generate video-extend",
|
|
44045
44210
|
startedAt,
|
|
44046
44211
|
dryRun: true,
|
|
44212
|
+
warnings: lifecycleWarnings,
|
|
44047
44213
|
data: {
|
|
44048
44214
|
params: {
|
|
44049
44215
|
id,
|
|
@@ -44196,6 +44362,7 @@ function registerVideoExtendCommand(parent) {
|
|
|
44196
44362
|
outputSuccess({
|
|
44197
44363
|
command: "generate video-extend",
|
|
44198
44364
|
startedAt,
|
|
44365
|
+
warnings: lifecycleWarnings,
|
|
44199
44366
|
data: {
|
|
44200
44367
|
provider: "veo",
|
|
44201
44368
|
taskId: result.id,
|
|
@@ -44244,6 +44411,7 @@ var init_video_extend = __esm({
|
|
|
44244
44411
|
init_ora();
|
|
44245
44412
|
init_dist2();
|
|
44246
44413
|
init_api_key();
|
|
44414
|
+
init_model_lifecycle();
|
|
44247
44415
|
init_output();
|
|
44248
44416
|
init_validate();
|
|
44249
44417
|
init_ai_helpers();
|
|
@@ -44311,16 +44479,8 @@ var init_provider_resolver = __esm({
|
|
|
44311
44479
|
|
|
44312
44480
|
// src/commands/_shared/openai-image.ts
|
|
44313
44481
|
function resolveOpenAIImageModel(modelAlias) {
|
|
44314
|
-
const
|
|
44315
|
-
|
|
44316
|
-
if (alias === id || model.aliases.includes(alias)) {
|
|
44317
|
-
return { openaiModel: id, modelLabel: model.label };
|
|
44318
|
-
}
|
|
44319
|
-
}
|
|
44320
|
-
return {
|
|
44321
|
-
openaiModel: OPENAI_IMAGE_DEFAULT_MODEL,
|
|
44322
|
-
modelLabel: OPENAI_IMAGE_MODELS[OPENAI_IMAGE_DEFAULT_MODEL].label
|
|
44323
|
-
};
|
|
44482
|
+
const model = findModel("openai", "image", modelAlias) ?? defaultModel("openai", "image");
|
|
44483
|
+
return { openaiModel: model.id, modelLabel: model.label };
|
|
44324
44484
|
}
|
|
44325
44485
|
async function executeOpenAIImageGenerate(prompt3, options, ctx) {
|
|
44326
44486
|
const provider = new OpenAIImageProvider();
|
|
@@ -44335,18 +44495,45 @@ async function executeOpenAIImageGenerate(prompt3, options, ctx) {
|
|
|
44335
44495
|
});
|
|
44336
44496
|
return { result, openaiModel, modelLabel };
|
|
44337
44497
|
}
|
|
44338
|
-
var OPENAI_IMAGE_MODELS;
|
|
44339
44498
|
var init_openai_image2 = __esm({
|
|
44340
44499
|
"src/commands/_shared/openai-image.ts"() {
|
|
44341
44500
|
"use strict";
|
|
44342
44501
|
init_dist2();
|
|
44343
|
-
|
|
44344
|
-
|
|
44345
|
-
|
|
44346
|
-
|
|
44347
|
-
|
|
44502
|
+
}
|
|
44503
|
+
});
|
|
44504
|
+
|
|
44505
|
+
// src/commands/_shared/image-cost.ts
|
|
44506
|
+
function catalogPrice(provider, model) {
|
|
44507
|
+
if (provider === "openai") return findModel("openai", "image", resolveOpenAIImageModel(model).openaiModel)?.price?.usd;
|
|
44508
|
+
if (provider === "gemini") return findModel("gemini", "image", model ?? "flash")?.price?.usd ?? findModel("gemini", "image")?.price?.usd;
|
|
44509
|
+
if (provider === "grok") return findModel("grok", "image", resolveGrokImageModel(model).model)?.price?.usd;
|
|
44510
|
+
return void 0;
|
|
44511
|
+
}
|
|
44512
|
+
function estimateImageCostUsd(provider, model, count) {
|
|
44513
|
+
const images = Math.max(1, count);
|
|
44514
|
+
const perImage = catalogPrice(provider, model);
|
|
44515
|
+
if (perImage === void 0) {
|
|
44516
|
+
return {
|
|
44517
|
+
costUsd: lookupCostEstimateUpperBound("generate image") ?? 5,
|
|
44518
|
+
warnings: [
|
|
44519
|
+
`costUsd is the tier upper bound for ${provider} - actual provider billing is typically lower and is not metered here.`
|
|
44520
|
+
]
|
|
44348
44521
|
};
|
|
44349
44522
|
}
|
|
44523
|
+
return {
|
|
44524
|
+
costUsd: Number((perImage * images).toFixed(3)),
|
|
44525
|
+
warnings: [
|
|
44526
|
+
`costUsd is an upper-bound estimate from ${provider} list prices for ${images} image(s) - not metered billing.`
|
|
44527
|
+
]
|
|
44528
|
+
};
|
|
44529
|
+
}
|
|
44530
|
+
var init_image_cost = __esm({
|
|
44531
|
+
"src/commands/_shared/image-cost.ts"() {
|
|
44532
|
+
"use strict";
|
|
44533
|
+
init_dist2();
|
|
44534
|
+
init_output();
|
|
44535
|
+
init_openai_image2();
|
|
44536
|
+
}
|
|
44350
44537
|
});
|
|
44351
44538
|
|
|
44352
44539
|
// src/commands/generate/image.ts
|
|
@@ -44446,6 +44633,7 @@ Examples:
|
|
|
44446
44633
|
command: "generate image",
|
|
44447
44634
|
startedAt,
|
|
44448
44635
|
dryRun: true,
|
|
44636
|
+
...estimateImageCostUsd(provider, options.model, parseInt(options.count) || 1),
|
|
44449
44637
|
data: {
|
|
44450
44638
|
params: {
|
|
44451
44639
|
prompt: prompt3,
|
|
@@ -44495,6 +44683,7 @@ Examples:
|
|
|
44495
44683
|
outputSuccess({
|
|
44496
44684
|
command: "generate image",
|
|
44497
44685
|
startedAt,
|
|
44686
|
+
...estimateImageCostUsd("openai", options.model, result.images.length),
|
|
44498
44687
|
data: {
|
|
44499
44688
|
provider: "openai",
|
|
44500
44689
|
model: modelLabel,
|
|
@@ -44610,7 +44799,7 @@ Examples:
|
|
|
44610
44799
|
outputSuccess({
|
|
44611
44800
|
command: "generate image",
|
|
44612
44801
|
startedAt,
|
|
44613
|
-
|
|
44802
|
+
...estimateImageCostUsd("gemini", options.model, result.images.length),
|
|
44614
44803
|
data: {
|
|
44615
44804
|
provider: "gemini",
|
|
44616
44805
|
model: usedLabel,
|
|
@@ -44705,6 +44894,7 @@ Examples:
|
|
|
44705
44894
|
outputSuccess({
|
|
44706
44895
|
command: "generate image",
|
|
44707
44896
|
startedAt,
|
|
44897
|
+
...estimateImageCostUsd("grok", options.model, result.images.length),
|
|
44708
44898
|
data: {
|
|
44709
44899
|
provider: "grok",
|
|
44710
44900
|
modelId: resolveGrokImageModel(options.model).model,
|
|
@@ -44824,6 +45014,7 @@ var init_image = __esm({
|
|
|
44824
45014
|
init_validate();
|
|
44825
45015
|
init_provider_resolver();
|
|
44826
45016
|
init_openai_image2();
|
|
45017
|
+
init_image_cost();
|
|
44827
45018
|
init_image_file();
|
|
44828
45019
|
}
|
|
44829
45020
|
});
|
|
@@ -45923,6 +46114,16 @@ Examples:
|
|
|
45923
46114
|
log(`${provider} does not support 1:1 \u2014 falling back to 16:9`);
|
|
45924
46115
|
options.ratio = "16:9";
|
|
45925
46116
|
}
|
|
46117
|
+
try {
|
|
46118
|
+
if (provider === "seedance" || provider === "fal") resolveSeedanceVariant(options.seedanceModel);
|
|
46119
|
+
if (provider === "grok") resolveGrokVideoModel(options.grokModel);
|
|
46120
|
+
if (provider === "kling") resolveKlingModel(options.klingModel);
|
|
46121
|
+
if (provider === "veo") resolveVeoModel(options.veoModel);
|
|
46122
|
+
} catch (err) {
|
|
46123
|
+
exitWithError(usageError(err instanceof Error ? err.message : String(err)));
|
|
46124
|
+
}
|
|
46125
|
+
const lifecycleWarnings = checkModelLifecycle(videoModelSpec(provider, options));
|
|
46126
|
+
if (!options.dryRun) printWarnings(lifecycleWarnings);
|
|
45926
46127
|
if (options.dryRun) {
|
|
45927
46128
|
const costUsd = provider === "seedance" || provider === "fal" ? realRunCost(provider, options).costUsd : void 0;
|
|
45928
46129
|
outputSuccess({
|
|
@@ -45930,6 +46131,7 @@ Examples:
|
|
|
45930
46131
|
startedAt,
|
|
45931
46132
|
dryRun: true,
|
|
45932
46133
|
costUsd,
|
|
46134
|
+
warnings: lifecycleWarnings,
|
|
45933
46135
|
data: {
|
|
45934
46136
|
params: {
|
|
45935
46137
|
prompt: prompt3,
|
|
@@ -45937,13 +46139,10 @@ Examples:
|
|
|
45937
46139
|
duration: options.duration,
|
|
45938
46140
|
ratio: options.ratio,
|
|
45939
46141
|
image: options.image,
|
|
45940
|
-
mode: options.mode,
|
|
46142
|
+
mode: provider === "kling" ? options.mode : void 0,
|
|
45941
46143
|
negative: options.negative,
|
|
45942
46144
|
resolution: options.resolution,
|
|
45943
|
-
|
|
45944
|
-
seedanceModel: options.seedanceModel,
|
|
45945
|
-
grokModel: options.grokModel,
|
|
45946
|
-
klingModel: options.klingModel,
|
|
46145
|
+
model: videoModelSpec(provider, options)?.id,
|
|
45947
46146
|
refImages: options.refImages,
|
|
45948
46147
|
refVideos: options.refVideos,
|
|
45949
46148
|
refAudio: options.refAudio,
|
|
@@ -46335,7 +46534,7 @@ Examples:
|
|
|
46335
46534
|
command: "generate video",
|
|
46336
46535
|
startedAt,
|
|
46337
46536
|
costUsd: cost.costUsd,
|
|
46338
|
-
warnings:
|
|
46537
|
+
warnings: [...lifecycleWarnings, ...cost.warnings],
|
|
46339
46538
|
data: {
|
|
46340
46539
|
provider,
|
|
46341
46540
|
taskId: result?.id,
|
|
@@ -46347,9 +46546,6 @@ Examples:
|
|
|
46347
46546
|
return;
|
|
46348
46547
|
}
|
|
46349
46548
|
console.log();
|
|
46350
|
-
if (provider === "veo") {
|
|
46351
|
-
console.log(source_default.yellow(VEO_SHUTDOWN_WARNING));
|
|
46352
|
-
}
|
|
46353
46549
|
if (finalResult.videoUrl) {
|
|
46354
46550
|
console.log(`Video URL: ${finalResult.videoUrl}`);
|
|
46355
46551
|
}
|
|
@@ -46474,7 +46670,6 @@ function printVideoStarted(providerLabel, taskId, taskType) {
|
|
|
46474
46670
|
console.log(`Task ID: ${source_default.bold(taskId)}`);
|
|
46475
46671
|
if (taskType) console.log(`Type: ${taskType}`);
|
|
46476
46672
|
}
|
|
46477
|
-
var VEO_SHUTDOWN_WARNING;
|
|
46478
46673
|
var init_video = __esm({
|
|
46479
46674
|
"src/commands/generate/video.ts"() {
|
|
46480
46675
|
"use strict";
|
|
@@ -46483,6 +46678,7 @@ var init_video = __esm({
|
|
|
46483
46678
|
init_dist3();
|
|
46484
46679
|
init_dist2();
|
|
46485
46680
|
init_api_key();
|
|
46681
|
+
init_model_lifecycle();
|
|
46486
46682
|
init_tty();
|
|
46487
46683
|
init_output();
|
|
46488
46684
|
init_validate();
|
|
@@ -46490,7 +46686,6 @@ var init_video = __esm({
|
|
|
46490
46686
|
init_upload_host();
|
|
46491
46687
|
init_ai_helpers();
|
|
46492
46688
|
init_status_jobs();
|
|
46493
|
-
VEO_SHUTDOWN_WARNING = "Veo 3.1 preview models shut down on 2026-10-22. Use `-p omni` (Gemini Omni 1.1 Flash) instead.";
|
|
46494
46689
|
}
|
|
46495
46690
|
});
|
|
46496
46691
|
|
|
@@ -46600,7 +46795,7 @@ Advanced:
|
|
|
46600
46795
|
generate video-cancel Provider lifecycle control; poll with 'vibe status job <job-id> --json'
|
|
46601
46796
|
|
|
46602
46797
|
API Keys (per provider):
|
|
46603
|
-
GOOGLE_API_KEY Image (default),
|
|
46798
|
+
GOOGLE_API_KEY Image (default), Omni video
|
|
46604
46799
|
OPENAI_API_KEY Image (-p openai)
|
|
46605
46800
|
FAL_API_KEY Seedance video (-p seedance, default video)
|
|
46606
46801
|
XAI_API_KEY Grok image/video
|
|
@@ -46645,10 +46840,11 @@ var OpenAIAdapter;
|
|
|
46645
46840
|
var init_openai2 = __esm({
|
|
46646
46841
|
"src/agent/adapters/openai.ts"() {
|
|
46647
46842
|
"use strict";
|
|
46843
|
+
init_dist2();
|
|
46648
46844
|
OpenAIAdapter = class {
|
|
46649
46845
|
provider = "openai";
|
|
46650
46846
|
client = null;
|
|
46651
|
-
model = "
|
|
46847
|
+
model = defaultModel("openai", "llm").id;
|
|
46652
46848
|
async initialize(apiKey) {
|
|
46653
46849
|
this.client = new OpenAI({ apiKey });
|
|
46654
46850
|
}
|
|
@@ -46741,10 +46937,11 @@ var ClaudeAdapter;
|
|
|
46741
46937
|
var init_claude2 = __esm({
|
|
46742
46938
|
"src/agent/adapters/claude.ts"() {
|
|
46743
46939
|
"use strict";
|
|
46940
|
+
init_dist2();
|
|
46744
46941
|
ClaudeAdapter = class {
|
|
46745
46942
|
provider = "claude";
|
|
46746
46943
|
client = null;
|
|
46747
|
-
model = "claude
|
|
46944
|
+
model = defaultModel("claude", "llm").id;
|
|
46748
46945
|
async initialize(apiKey) {
|
|
46749
46946
|
this.client = new Anthropic({ apiKey });
|
|
46750
46947
|
}
|
|
@@ -47225,10 +47422,11 @@ var XAIAdapter;
|
|
|
47225
47422
|
var init_xai = __esm({
|
|
47226
47423
|
"src/agent/adapters/xai.ts"() {
|
|
47227
47424
|
"use strict";
|
|
47425
|
+
init_dist2();
|
|
47228
47426
|
XAIAdapter = class {
|
|
47229
47427
|
provider = "xai";
|
|
47230
47428
|
client = null;
|
|
47231
|
-
model = "grok
|
|
47429
|
+
model = defaultModel("grok", "llm").id;
|
|
47232
47430
|
async initialize(apiKey) {
|
|
47233
47431
|
this.client = new OpenAI2({
|
|
47234
47432
|
apiKey,
|
|
@@ -47695,6 +47893,7 @@ var init_detect = __esm({
|
|
|
47695
47893
|
validateOutputPath(options.output);
|
|
47696
47894
|
}
|
|
47697
47895
|
if (options.dryRun) {
|
|
47896
|
+
spinner2.stop();
|
|
47698
47897
|
outputSuccess({
|
|
47699
47898
|
command: "detect scenes",
|
|
47700
47899
|
startedAt,
|
|
@@ -47814,6 +48013,7 @@ var init_detect = __esm({
|
|
|
47814
48013
|
validateOutputPath(options.output);
|
|
47815
48014
|
}
|
|
47816
48015
|
if (options.dryRun) {
|
|
48016
|
+
spinner2.stop();
|
|
47817
48017
|
outputSuccess({
|
|
47818
48018
|
command: "detect silence",
|
|
47819
48019
|
startedAt,
|
|
@@ -47900,6 +48100,7 @@ var init_detect = __esm({
|
|
|
47900
48100
|
validateOutputPath(options.output);
|
|
47901
48101
|
}
|
|
47902
48102
|
if (options.dryRun) {
|
|
48103
|
+
spinner2.stop();
|
|
47903
48104
|
outputSuccess({
|
|
47904
48105
|
command: "detect beats",
|
|
47905
48106
|
startedAt,
|
|
@@ -52047,8 +52248,9 @@ var EXPLICIT_COMMAND_METADATA = {
|
|
|
52047
52248
|
schema: { surface: "agent", note: "Machine-readable command discovery." },
|
|
52048
52249
|
completion: { surface: "advanced", note: "Shell ergonomics helper." },
|
|
52049
52250
|
agent: {
|
|
52050
|
-
surface: "
|
|
52051
|
-
|
|
52251
|
+
surface: "legacy",
|
|
52252
|
+
replacement: "a host agent (Claude Code, Codex, Cursor) or the MCP server via `vibe host setup`",
|
|
52253
|
+
note: "Deprecated built-in REPL, removed before 1.0."
|
|
52052
52254
|
},
|
|
52053
52255
|
"design.validate": { surface: "public", note: "Validate the DESIGN.md visual contract." },
|
|
52054
52256
|
"generate.image": { surface: "public" },
|
|
@@ -57634,7 +57836,7 @@ var generateVideoTool = defineTool({
|
|
|
57634
57836
|
cost: "high",
|
|
57635
57837
|
title: "Generate Video",
|
|
57636
57838
|
annotations: { readOnly: false, openWorld: true },
|
|
57637
|
-
description: "Generate video using AI. Supports Seedance 2.0 via fal.ai, Grok, Kling, Runway, and Veo. Requires FAL_API_KEY, XAI_API_KEY, KLING_API_KEY, RUNWAY_API_SECRET, or GOOGLE_API_KEY.",
|
|
57839
|
+
description: "Generate video using AI. Supports Seedance 2.0 via fal.ai, Grok, Kling, Runway, Gemini Omni, and Veo (shuts down 2026-10-22). Requires FAL_API_KEY, XAI_API_KEY, KLING_API_KEY, RUNWAY_API_SECRET, or GOOGLE_API_KEY.",
|
|
57638
57840
|
schema: external_exports.object({
|
|
57639
57841
|
prompt: external_exports.string().describe("Text prompt describing the video"),
|
|
57640
57842
|
provider: external_exports.enum(["seedance", "grok", "kling", "runway", "veo", "omni"]).optional().describe(
|
|
@@ -62066,8 +62268,9 @@ they want for a given task. This guide is the operator-facing summary.
|
|
|
62066
62268
|
|
|
62067
62269
|
If you already use Claude Code, Codex, Cursor, Aider, Gemini CLI, OpenCode,
|
|
62068
62270
|
or another coding agent, let that host drive \`vibe\` directly through shell
|
|
62069
|
-
commands plus \`AGENTS.md\` / \`CLAUDE.md\`.
|
|
62070
|
-
|
|
62271
|
+
commands plus \`AGENTS.md\` / \`CLAUDE.md\`. Without a coding agent, connect
|
|
62272
|
+
the MCP server to Claude Desktop or ChatGPT (\`vibe host setup\`).
|
|
62273
|
+
\`vibe agent\` is deprecated and will be removed before 1.0.
|
|
62071
62274
|
|
|
62072
62275
|
## TL;DR
|
|
62073
62276
|
|
|
@@ -62078,12 +62281,12 @@ built-in fallback when you do not already have an agent host.
|
|
|
62078
62281
|
| **Reproducibility** | none | high (idempotent) | highest (checkpointed) |
|
|
62079
62282
|
| **Budget caps** | per-session max-turns | none | \`--budget-usd\`, \`--budget-tokens\`, \`--max-errors\` |
|
|
62080
62283
|
| **Resume after crash** | no | re-invoke | \`--resume\` |
|
|
62081
|
-
| **Best for** |
|
|
62284
|
+
| **Best for** | deprecated; use a host agent | finished script | repeatable workflows |
|
|
62082
62285
|
|
|
62083
62286
|
## Decision tree
|
|
62084
62287
|
|
|
62085
62288
|
- "I am already in Claude Code/Codex/Cursor/etc." \u2192 regular \`vibe\` shell commands + \`vibe guide\` / \`vibe schema\`
|
|
62086
|
-
- "I
|
|
62289
|
+
- "I do not use a coding agent" \u2192 the MCP server in Claude Desktop or ChatGPT (\`vibe host setup\`)
|
|
62087
62290
|
- "I have a finished script + visual identity" \u2192 \`vibe build\`
|
|
62088
62291
|
- "I want this to run again next month" \u2192 \`vibe run\`
|
|
62089
62292
|
|
|
@@ -62109,9 +62312,6 @@ agent calls them through a tool manifest; \`build\` calls a curated subset
|
|
|
62109
62312
|
- \`vibe build\` is conceptually a 4-step pipeline; \`vibe run\` could express
|
|
62110
62313
|
the same flow but build's STORYBOARD.md input + opinionated defaults are
|
|
62111
62314
|
the value-add.
|
|
62112
|
-
- \`vibe agent\`'s tool registry currently exposes primitives, not
|
|
62113
|
-
orchestrators. Adding \`vibe.build\` / \`vibe.run\` as agent tools is on the
|
|
62114
|
-
table for a future major.
|
|
62115
62315
|
- \`vibe run --resume\` has no analog in build/agent; build's idempotent
|
|
62116
62316
|
re-invoke covers the common case.
|
|
62117
62317
|
`;
|
|
@@ -62218,17 +62418,17 @@ var META = {
|
|
|
62218
62418
|
},
|
|
62219
62419
|
architecture: {
|
|
62220
62420
|
title: "external agents / vibe agent / build / run",
|
|
62221
|
-
summary: "Choose between host-agent shell use,
|
|
62421
|
+
summary: "Choose between host-agent shell use, MCP hosts, storyboard builds, and YAML pipelines",
|
|
62222
62422
|
steps: [
|
|
62223
62423
|
"If you are already in Claude Code/Codex/Cursor/etc., let that host drive normal `vibe` shell commands using `AGENTS.md`, `vibe guide`, and `vibe schema`.",
|
|
62224
|
-
"
|
|
62424
|
+
"Without a coding agent, connect the MCP server to Claude Desktop or ChatGPT with `vibe host setup`; `vibe agent` is deprecated.",
|
|
62225
62425
|
"Pick build for STORYBOARD.md \u2192 MP4 with opinionated defaults.",
|
|
62226
62426
|
"Pick run for repeatable, budget-capped, checkpointed YAML pipelines.",
|
|
62227
62427
|
"Run `vibe doctor --test-keys` before any high-cost orchestrator to validate keys upfront.",
|
|
62228
62428
|
"Use `vibe schema --list` (cost field, v0.84) to plan the budget per step before kicking off `vibe run --budget-usd`."
|
|
62229
62429
|
],
|
|
62230
62430
|
relatedCommands: [
|
|
62231
|
-
"vibe
|
|
62431
|
+
"vibe host setup",
|
|
62232
62432
|
"vibe build",
|
|
62233
62433
|
"vibe run",
|
|
62234
62434
|
"vibe doctor",
|