@vibeframe/mcp-server 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.
Files changed (3) hide show
  1. package/README.md +2 -2
  2. package/dist/index.js +423 -223
  3. package/package.json +4 -4
package/dist/index.js CHANGED
@@ -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 ($), Veo ($$)",
205
- envExampleComment: "Google API Key (Gemini auto-edit suggestions, image gen, Veo video)",
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(filter3 = {}) {
444
+ return MODEL_CATALOG.filter((m2) => (!filter3.provider || m2.provider === filter3.provider) && (!filter3.kind || m2.kind === filter3.kind));
445
+ }
446
+ function defaultModel(provider, kind3) {
447
+ const found = MODEL_CATALOG.find((m2) => m2.provider === provider && m2.kind === kind3 && m2.default);
448
+ if (!found)
449
+ throw new Error(`Model catalog has no default ${kind3} model for ${provider}`);
450
+ return found;
451
+ }
452
+ function findModel(provider, kind3, aliasOrId) {
453
+ const key2 = aliasOrId?.trim();
454
+ if (!key2)
455
+ return defaultModel(provider, kind3);
456
+ const lower = key2.toLowerCase();
457
+ return listModels({ provider, kind: kind3 }).find((m2) => m2.id === key2 || m2.aliases?.includes(lower));
458
+ }
459
+ function 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, kind3) {
485
+ return listModels({ provider, kind: kind3 }).flatMap((m2) => m2.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
- GEMINI_DEFAULT_TEXT_MODEL = "gemini-3.8-flash";
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((m2) => (m2.aliases ?? []).map((a4) => [a4, m2.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
- var VEO_MODEL_ALIASES, MODEL_MAP, GeminiProvider, geminiProvider;
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
- VEO_MODEL_ALIASES = {
1022
- "3.1": "veo-3.1-generate-preview",
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((m2) => (m2.aliases ?? []).map((a4) => [a4, m2.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 || "veo-3.1-fast-generate-preview";
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 || "veo-3.1-generate-preview";
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
- if (!model)
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
- OMNI_MODEL = "gemini-omni-1.1-flash";
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: "gpt-5.4-mini",
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 = "gpt-5.4-mini";
2193
+ this.model = defaultModel("openai", "llm").id;
2107
2194
  }
2108
2195
  async initialize(config4) {
2109
2196
  this.apiKey = config4.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: "gpt-5.4-mini",
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-sonnet-5-5";
3910
+ this.model = defaultModel("claude", "llm").id;
3823
3911
  }
3824
3912
  async initialize(config4) {
3825
3913
  this.apiKey = config4.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((m2) => (m2.aliases ?? []).map((a4) => [a4, m2.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 = "music_v2_5";
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
- OPENAI_IMAGE_DEFAULT_MODEL = "gpt-image-2.5-sunburst";
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
- DEFAULT_MODEL3 = "gen4.5";
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: "failed"
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: data2.id,
@@ -5649,8 +5745,9 @@ var init_RunwayProvider = __esm({
5649
5745
  if (data2.status === "SUCCEEDED" && data2.output && data2.output.length > 0) {
5650
5746
  result.videoUrl = data2.output[0];
5651
5747
  }
5652
- if (data2.status === "FAILED" || data2.status === "THROTTLED") {
5653
- result.error = data2.failure || data2.failureCode || "Generation failed";
5748
+ if (data2.status === "FAILED") {
5749
+ const reason = data2.failure || "Generation failed";
5750
+ result.error = data2.failureCode ? `${reason} (${data2.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 ongoing generation
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
- if (!this.apiKey) {
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
- * Delete a completed task
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 key2 = (alias ?? "v3").trim().toLowerCase();
5796
- const aliases2 = {
5797
- v3: "kling-v3",
5798
- "kling-v3": "kling-v3",
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(aliases2, key2))
5806
- return aliases2[key2];
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
- DEFAULT_MODEL4 = "kling-v3";
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 key2 = (alias ?? "1.5").trim().toLowerCase();
6259
- const aliases2 = {
6260
- "1.5": "grok-imagine-video-1.5",
6261
- "grok-imagine-video-1.5": "grok-imagine-video-1.5",
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(aliases2, key2))
6269
- return aliases2[key2];
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
- if (alias === "pro" || alias === "2.0" || alias === "quality" || alias === "grok-imagine-image-2.0") {
6274
- return { model: "grok-imagine-image-2.0", quality: "medium" };
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
- DEFAULT_MODEL5 = "grok-imagine-video-1.5";
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 key2 = (alias ?? "quality").trim().toLowerCase();
10726
- const aliases2 = {
10727
- quality: "seedance-2.0",
10728
- "2.0": "seedance-2.0",
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(aliases2, key2))
10736
- return aliases2[key2];
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_exports, {
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_exports, {
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_exports, {
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_dist = __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
  // ../cli/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
  (c2) => `%${c2.charCodeAt(0).toString(16).toUpperCase()}`
20078
20148
  );
20079
20149
  }
20080
- function presignS3PutUrl(params) {
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(query2).sort(([a4], [b4]) => a4.localeCompare(b4)).map(([key2, value]) => `${awsEncode(key2)}=${awsEncode(value)}`).join("&");
20098
20171
  const canonicalRequest = [
20099
- "PUT",
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 key2 = `${prefix}/${Date.now()}-${randomUUID()}.${ext}`;
20158
- const presignedUrl = presignS3PutUrl({
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: key2, 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: publicS3Url({ region, bucket, key: key2, publicBaseUrl: settings.s3.publicBaseUrl }),
20180
- expiresAt: new Date(Date.now() + settings.ttlSeconds * 1e3).toISOString()
20260
+ url: presignS3Url({
20261
+ method: "GET",
20262
+ accessKeyId,
20263
+ secretAccessKey,
20264
+ sessionToken,
20265
+ region,
20266
+ bucket,
20267
+ key: key2,
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 result = await uploadToImgbb(imageBuffer, imgbbKey);
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 { provider: "imgbb", url: result.url };
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
  "../cli/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: key2 });
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,
@@ -268467,8 +268568,43 @@ function outputSuccess(opts) {
268467
268568
  const data2 = opts.data;
268468
268569
  const primary = data2.outputPath ?? data2.output ?? data2.path ?? data2.url ?? data2.id;
268469
268570
  if (primary !== void 0) console.log(String(primary));
268571
+ return;
268572
+ }
268573
+ if (opts.dryRun && !opts.humanRendered) {
268574
+ printDryRunSummary(opts.command, costUsd, opts.data, opts.warnings ?? []);
268575
+ }
268576
+ }
268577
+ function printWarnings(warnings) {
268578
+ if (isJsonMode()) return;
268579
+ for (const warning of warnings) {
268580
+ process.stderr.write(`${source_default.yellow(`Warning: ${warning}`)}
268581
+ `);
268470
268582
  }
268471
268583
  }
268584
+ function formatDryRunValue(value) {
268585
+ const text = Array.isArray(value) ? value.map((v4) => formatDryRunValue(v4)).join(", ") : typeof value === "object" ? JSON.stringify(value) : String(value);
268586
+ return text.length > 80 ? `${text.slice(0, 77)}...` : text;
268587
+ }
268588
+ function printDryRunSummary(command3, costUsd, data2, warnings) {
268589
+ const params = data2.params && typeof data2.params === "object" ? data2.params : data2;
268590
+ const rows = [
268591
+ ["cost", costUsd > 0 ? `up to $${costUsd.toFixed(2)} (estimate)` : "free"]
268592
+ ];
268593
+ for (const [key2, value] of Object.entries(params)) {
268594
+ if (value === void 0 || value === null || value === "") continue;
268595
+ if (Array.isArray(value) && value.length === 0) continue;
268596
+ rows.push([key2, formatDryRunValue(value)]);
268597
+ }
268598
+ const width = Math.max(...rows.map(([key2]) => key2.length));
268599
+ console.log();
268600
+ console.log(`${source_default.bold.cyan(`Dry run: vibe ${command3}`)} ${source_default.dim("(nothing was sent)")}`);
268601
+ for (const [key2, value] of rows) {
268602
+ console.log(` ${source_default.dim(key2.padEnd(width))} ${value}`);
268603
+ }
268604
+ printWarnings(warnings);
268605
+ console.log(source_default.dim(" Run again without --dry-run to execute."));
268606
+ console.log();
268607
+ }
268472
268608
  function log(...args) {
268473
268609
  if (!isJsonMode() && !isQuietMode()) {
268474
268610
  console.log(...args);
@@ -275942,16 +276078,14 @@ import { tmpdir as tmpdir9 } from "node:os";
275942
276078
  import { createHash as createHash11 } from "node:crypto";
275943
276079
  async function ensureRemotionInstalled() {
275944
276080
  try {
275945
- await execSafe("npx", ["--yes", "remotion", "--help"], { timeout: 6e4 });
276081
+ await execSafe("npm", ["--version"], { timeout: 3e4 });
275946
276082
  return null;
275947
276083
  } catch (error) {
275948
276084
  const detail = error instanceof Error ? error.message : String(error);
275949
- console.error(`[Remotion] ensureRemotionInstalled failed: ${detail.slice(0, 300)}`);
275950
276085
  return [
275951
- "Remotion CLI not found or failed to initialize.",
276086
+ "Remotion renders need npm to install the Remotion CLI into a temporary project.",
275952
276087
  ` Debug: ${detail.slice(0, 200)}`,
275953
- " Fix: npm install -g @remotion/cli",
275954
- " Or ensure npx is available and can download @remotion/cli on demand."
276088
+ " Fix: install Node.js 20+ (which includes npm) and make sure `npm` is on PATH."
275955
276089
  ].join("\n");
275956
276090
  }
275957
276091
  }
@@ -277074,7 +277208,7 @@ ${textsToTranslate}`;
277074
277208
  Authorization: `Bearer ${openaiKey}`
277075
277209
  },
277076
277210
  body: JSON.stringify({
277077
- model: "gpt-5.4-mini",
277211
+ model: defaultModel("openai", "llm").id,
277078
277212
  messages: [{ role: "user", content: translatePrompt }]
277079
277213
  })
277080
277214
  });
@@ -277102,7 +277236,7 @@ ${textsToTranslate}`;
277102
277236
  "anthropic-version": "2023-06-01"
277103
277237
  },
277104
277238
  body: JSON.stringify({
277105
- model: "claude-sonnet-5-5",
277239
+ model: defaultModel("claude", "llm").id,
277106
277240
  max_tokens: 16e3,
277107
277241
  messages: [{ role: "user", content: translatePrompt }]
277108
277242
  })
@@ -277153,6 +277287,7 @@ var init_translate_srt = __esm({
277153
277287
  "../cli/src/commands/_shared/edit/translate-srt.ts"() {
277154
277288
  "use strict";
277155
277289
  init_subtitle();
277290
+ init_dist();
277156
277291
  }
277157
277292
  });
277158
277293
 
@@ -278353,22 +278488,13 @@ function analyzeGapFillability(gaps, videoClips, sources) {
278353
278488
  return { gap, canExtendBefore, canExtendAfter, remainingGap, gapStart };
278354
278489
  });
278355
278490
  }
278356
- async function uploadFrameToImgbb(framePath, imgbbApiKey) {
278491
+ async function uploadFrame(host, framePath) {
278357
278492
  try {
278358
- const frameBuffer = await readFile26(framePath);
278359
- const frameBase64 = frameBuffer.toString("base64");
278360
- const formData = new FormData();
278361
- formData.append("key", imgbbApiKey);
278362
- formData.append("image", frameBase64);
278363
- const response = await fetch("https://api.imgbb.com/1/upload", {
278364
- method: "POST",
278365
- body: formData
278493
+ const upload = await host.uploadImage(await readFile26(framePath), {
278494
+ filename: framePath,
278495
+ mimeType: "image/png"
278366
278496
  });
278367
- const data2 = await response.json();
278368
- if (!data2.success || !data2.data?.url) {
278369
- return { error: data2.error?.message || "Upload failed" };
278370
- }
278371
- return { url: data2.data.url };
278497
+ return { url: upload.url };
278372
278498
  } catch (err) {
278373
278499
  return { error: err instanceof Error ? err.message : String(err) };
278374
278500
  }
@@ -278519,11 +278645,13 @@ async function executeFillGaps(options) {
278519
278645
  await mkdir20(footageDir, { recursive: true });
278520
278646
  }
278521
278647
  humanLines.push("Generating AI Videos");
278522
- const imgbbApiKey = options.imgbbApiKey || await getApiKey("IMGBB_API_KEY", "imgbb", void 0);
278523
- if (!imgbbApiKey) {
278648
+ let uploadHost;
278649
+ try {
278650
+ uploadHost = await resolveUploadHost();
278651
+ } catch (err) {
278524
278652
  return {
278525
278653
  success: false,
278526
- error: "IMGBB_API_KEY required for image hosting. Get a free API key at https://api.imgbb.com/",
278654
+ error: err instanceof Error ? err.message : String(err),
278527
278655
  humanLines
278528
278656
  };
278529
278657
  }
@@ -278567,12 +278695,12 @@ async function executeFillGaps(options) {
278567
278695
  humanLines
278568
278696
  };
278569
278697
  }
278570
- onProgress("Uploading frame to imgbb...");
278571
- const upload = await uploadFrameToImgbb(framePath, imgbbApiKey);
278698
+ onProgress(`Uploading frame via ${uploadHost.provider}...`);
278699
+ const upload = await uploadFrame(uploadHost, framePath);
278572
278700
  if (!upload.url) {
278573
278701
  return {
278574
278702
  success: false,
278575
- error: `Failed to upload frame to imgbb: ${upload.error || "unknown"}`,
278703
+ error: `Failed to upload frame via ${uploadHost.provider}: ${upload.error || "unknown"}`,
278576
278704
  humanLines
278577
278705
  };
278578
278706
  }
@@ -278647,7 +278775,7 @@ async function executeFillGaps(options) {
278647
278775
  humanLines.push(" Failed to extract frame for continuation");
278648
278776
  break;
278649
278777
  }
278650
- const extUpload = await uploadFrameToImgbb(lastFramePath, imgbbApiKey);
278778
+ const extUpload = await uploadFrame(uploadHost, lastFramePath);
278651
278779
  if (!extUpload.url) {
278652
278780
  humanLines.push(" Failed to upload continuation frame");
278653
278781
  break;
@@ -278770,6 +278898,7 @@ var init_execute_fill_gaps = __esm({
278770
278898
  init_dist();
278771
278899
  init_engine();
278772
278900
  init_api_key();
278901
+ init_upload_host();
278773
278902
  init_exec_safe();
278774
278903
  init_project_resolver();
278775
278904
  init_ai_helpers();
@@ -278837,6 +278966,13 @@ __export(ai_motion_exports, {
278837
278966
  import { resolve as resolve48 } from "node:path";
278838
278967
  import { existsSync as existsSync69 } from "node:fs";
278839
278968
  import { readFile as readFile27, writeFile as writeFile29 } from "node:fs/promises";
278969
+ function resolveMotionModel(alias) {
278970
+ const claude = findModel("claude", "llm", alias);
278971
+ if (claude) return { provider: "claude", modelId: claude.id };
278972
+ const gemini = findModel("gemini", "llm", alias);
278973
+ if (gemini) return { provider: "gemini", modelId: gemini.id };
278974
+ return { provider: "claude", modelId: defaultModel("claude", "llm").id };
278975
+ }
278840
278976
  async function getOptionalGoogleApiKey() {
278841
278977
  const configKey = await getApiKeyFromConfig("google");
278842
278978
  if (configKey) return configKey;
@@ -278851,7 +278987,7 @@ function normalizeUnderstand(value) {
278851
278987
  }
278852
278988
  async function executeMotion(options) {
278853
278989
  const modelAlias = options.model || "sonnet";
278854
- const modelConfig = MODEL_MAP2[modelAlias] ?? MODEL_MAP2["sonnet"];
278990
+ const modelConfig = resolveMotionModel(modelAlias);
278855
278991
  const useGemini = modelConfig.provider === "gemini";
278856
278992
  const width = options.width || 1920;
278857
278993
  const height = options.height || 1080;
@@ -279230,7 +279366,6 @@ function registerMotionCommand(aiCommand) {
279230
279366
  }
279231
279367
  });
279232
279368
  }
279233
- var MODEL_MAP2;
279234
279369
  var init_ai_motion = __esm({
279235
279370
  "../cli/src/commands/ai-motion.ts"() {
279236
279371
  "use strict";
@@ -279241,14 +279376,6 @@ var init_ai_motion = __esm({
279241
279376
  init_config();
279242
279377
  init_output();
279243
279378
  init_validate();
279244
- MODEL_MAP2 = {
279245
- sonnet: { provider: "claude", modelId: "claude-sonnet-5-5" },
279246
- opus: { provider: "claude", modelId: "claude-opus-5-5" },
279247
- "opus-4-6": { provider: "claude", modelId: "claude-opus-4-6" },
279248
- gemini: { provider: "gemini", modelId: GEMINI_DEFAULT_TEXT_MODEL },
279249
- "gemini-2.5-pro": { provider: "gemini", modelId: "gemini-2.5-pro" },
279250
- "gemini-3.1-pro": { provider: "gemini", modelId: "gemini-3.1-pro-preview" }
279251
- };
279252
279379
  }
279253
279380
  });
279254
279381
 
@@ -282079,6 +282206,34 @@ var init_thumbnail = __esm({
282079
282206
  }
282080
282207
  });
282081
282208
 
282209
+ // ../cli/src/utils/model-lifecycle.ts
282210
+ function videoModelSpec(provider, flags) {
282211
+ const catalogProvider = provider === "fal" ? "seedance" : provider;
282212
+ const flag = VIDEO_MODEL_FLAG[catalogProvider];
282213
+ return findModel(catalogProvider, "video", flag ? flags[flag] : void 0);
282214
+ }
282215
+ function checkModelLifecycle(spec, now = /* @__PURE__ */ new Date()) {
282216
+ if (!spec) return [];
282217
+ const lifecycle = modelLifecycle(spec, now);
282218
+ if (lifecycle.state === "retired") exitWithError(usageError(lifecycle.message));
282219
+ return lifecycle.state === "retiring" ? [lifecycle.message] : [];
282220
+ }
282221
+ var VIDEO_MODEL_FLAG;
282222
+ var init_model_lifecycle = __esm({
282223
+ "../cli/src/utils/model-lifecycle.ts"() {
282224
+ "use strict";
282225
+ init_dist();
282226
+ init_output();
282227
+ VIDEO_MODEL_FLAG = {
282228
+ seedance: "seedanceModel",
282229
+ grok: "grokModel",
282230
+ kling: "klingModel",
282231
+ veo: "veoModel",
282232
+ runway: "runwayModel"
282233
+ };
282234
+ }
282235
+ });
282236
+
282082
282237
  // ../cli/src/commands/generate/video-extend.ts
282083
282238
  import { resolve as resolve65 } from "node:path";
282084
282239
  import { writeFile as writeFile38 } from "node:fs/promises";
@@ -282090,11 +282245,22 @@ function registerVideoExtendCommand(parent) {
282090
282245
  if (options.output) {
282091
282246
  validateOutputPath(options.output);
282092
282247
  }
282248
+ let lifecycleWarnings = [];
282249
+ if (provider === "veo") {
282250
+ try {
282251
+ resolveVeoModel(options.veoModel);
282252
+ } catch (err) {
282253
+ exitWithError(usageError(err instanceof Error ? err.message : String(err)));
282254
+ }
282255
+ lifecycleWarnings = checkModelLifecycle(findModel("veo", "video", options.veoModel));
282256
+ if (!options.dryRun) printWarnings(lifecycleWarnings);
282257
+ }
282093
282258
  if (options.dryRun) {
282094
282259
  outputSuccess({
282095
282260
  command: "generate video-extend",
282096
282261
  startedAt,
282097
282262
  dryRun: true,
282263
+ warnings: lifecycleWarnings,
282098
282264
  data: {
282099
282265
  params: {
282100
282266
  id,
@@ -282247,6 +282413,7 @@ function registerVideoExtendCommand(parent) {
282247
282413
  outputSuccess({
282248
282414
  command: "generate video-extend",
282249
282415
  startedAt,
282416
+ warnings: lifecycleWarnings,
282250
282417
  data: {
282251
282418
  provider: "veo",
282252
282419
  taskId: result.id,
@@ -282295,6 +282462,7 @@ var init_video_extend = __esm({
282295
282462
  init_ora();
282296
282463
  init_dist();
282297
282464
  init_api_key();
282465
+ init_model_lifecycle();
282298
282466
  init_output();
282299
282467
  init_validate();
282300
282468
  init_ai_helpers();
@@ -282362,16 +282530,8 @@ var init_provider_resolver = __esm({
282362
282530
 
282363
282531
  // ../cli/src/commands/_shared/openai-image.ts
282364
282532
  function resolveOpenAIImageModel(modelAlias) {
282365
- const alias = modelAlias?.trim() ?? "";
282366
- for (const [id, model] of Object.entries(OPENAI_IMAGE_MODELS)) {
282367
- if (alias === id || model.aliases.includes(alias)) {
282368
- return { openaiModel: id, modelLabel: model.label };
282369
- }
282370
- }
282371
- return {
282372
- openaiModel: OPENAI_IMAGE_DEFAULT_MODEL,
282373
- modelLabel: OPENAI_IMAGE_MODELS[OPENAI_IMAGE_DEFAULT_MODEL].label
282374
- };
282533
+ const model = findModel("openai", "image", modelAlias) ?? defaultModel("openai", "image");
282534
+ return { openaiModel: model.id, modelLabel: model.label };
282375
282535
  }
282376
282536
  async function executeOpenAIImageGenerate(prompt3, options, ctx) {
282377
282537
  const provider = new OpenAIImageProvider();
@@ -282386,18 +282546,45 @@ async function executeOpenAIImageGenerate(prompt3, options, ctx) {
282386
282546
  });
282387
282547
  return { result, openaiModel, modelLabel };
282388
282548
  }
282389
- var OPENAI_IMAGE_MODELS;
282390
282549
  var init_openai_image2 = __esm({
282391
282550
  "../cli/src/commands/_shared/openai-image.ts"() {
282392
282551
  "use strict";
282393
282552
  init_dist();
282394
- OPENAI_IMAGE_MODELS = {
282395
- "gpt-image-2.5-sunburst": { label: "GPT Image 2.5 Sunburst", aliases: ["2.5", "sunburst"] },
282396
- "gpt-image-2.5-flare": { label: "GPT Image 2.5 Flare", aliases: ["flare", "2.5-flare"] },
282397
- "gpt-image-2": { label: "GPT Image 2", aliases: ["2"] },
282398
- "gpt-image-1.5": { label: "GPT Image 1.5", aliases: ["1.5"] }
282553
+ }
282554
+ });
282555
+
282556
+ // ../cli/src/commands/_shared/image-cost.ts
282557
+ function catalogPrice(provider, model) {
282558
+ if (provider === "openai") return findModel("openai", "image", resolveOpenAIImageModel(model).openaiModel)?.price?.usd;
282559
+ if (provider === "gemini") return findModel("gemini", "image", model ?? "flash")?.price?.usd ?? findModel("gemini", "image")?.price?.usd;
282560
+ if (provider === "grok") return findModel("grok", "image", resolveGrokImageModel(model).model)?.price?.usd;
282561
+ return void 0;
282562
+ }
282563
+ function estimateImageCostUsd(provider, model, count) {
282564
+ const images = Math.max(1, count);
282565
+ const perImage = catalogPrice(provider, model);
282566
+ if (perImage === void 0) {
282567
+ return {
282568
+ costUsd: lookupCostEstimateUpperBound("generate image") ?? 5,
282569
+ warnings: [
282570
+ `costUsd is the tier upper bound for ${provider} - actual provider billing is typically lower and is not metered here.`
282571
+ ]
282399
282572
  };
282400
282573
  }
282574
+ return {
282575
+ costUsd: Number((perImage * images).toFixed(3)),
282576
+ warnings: [
282577
+ `costUsd is an upper-bound estimate from ${provider} list prices for ${images} image(s) - not metered billing.`
282578
+ ]
282579
+ };
282580
+ }
282581
+ var init_image_cost = __esm({
282582
+ "../cli/src/commands/_shared/image-cost.ts"() {
282583
+ "use strict";
282584
+ init_dist();
282585
+ init_output();
282586
+ init_openai_image2();
282587
+ }
282401
282588
  });
282402
282589
 
282403
282590
  // ../cli/src/commands/generate/image.ts
@@ -282497,6 +282684,7 @@ Examples:
282497
282684
  command: "generate image",
282498
282685
  startedAt,
282499
282686
  dryRun: true,
282687
+ ...estimateImageCostUsd(provider, options.model, parseInt(options.count) || 1),
282500
282688
  data: {
282501
282689
  params: {
282502
282690
  prompt: prompt3,
@@ -282546,6 +282734,7 @@ Examples:
282546
282734
  outputSuccess({
282547
282735
  command: "generate image",
282548
282736
  startedAt,
282737
+ ...estimateImageCostUsd("openai", options.model, result.images.length),
282549
282738
  data: {
282550
282739
  provider: "openai",
282551
282740
  model: modelLabel,
@@ -282661,7 +282850,7 @@ Examples:
282661
282850
  outputSuccess({
282662
282851
  command: "generate image",
282663
282852
  startedAt,
282664
- warnings: [],
282853
+ ...estimateImageCostUsd("gemini", options.model, result.images.length),
282665
282854
  data: {
282666
282855
  provider: "gemini",
282667
282856
  model: usedLabel,
@@ -282756,6 +282945,7 @@ Examples:
282756
282945
  outputSuccess({
282757
282946
  command: "generate image",
282758
282947
  startedAt,
282948
+ ...estimateImageCostUsd("grok", options.model, result.images.length),
282759
282949
  data: {
282760
282950
  provider: "grok",
282761
282951
  modelId: resolveGrokImageModel(options.model).model,
@@ -282875,6 +283065,7 @@ var init_image2 = __esm({
282875
283065
  init_validate();
282876
283066
  init_provider_resolver();
282877
283067
  init_openai_image2();
283068
+ init_image_cost();
282878
283069
  init_image_file();
282879
283070
  }
282880
283071
  });
@@ -283974,6 +284165,16 @@ Examples:
283974
284165
  log(`${provider} does not support 1:1 \u2014 falling back to 16:9`);
283975
284166
  options.ratio = "16:9";
283976
284167
  }
284168
+ try {
284169
+ if (provider === "seedance" || provider === "fal") resolveSeedanceVariant(options.seedanceModel);
284170
+ if (provider === "grok") resolveGrokVideoModel(options.grokModel);
284171
+ if (provider === "kling") resolveKlingModel(options.klingModel);
284172
+ if (provider === "veo") resolveVeoModel(options.veoModel);
284173
+ } catch (err) {
284174
+ exitWithError(usageError(err instanceof Error ? err.message : String(err)));
284175
+ }
284176
+ const lifecycleWarnings = checkModelLifecycle(videoModelSpec(provider, options));
284177
+ if (!options.dryRun) printWarnings(lifecycleWarnings);
283977
284178
  if (options.dryRun) {
283978
284179
  const costUsd = provider === "seedance" || provider === "fal" ? realRunCost(provider, options).costUsd : void 0;
283979
284180
  outputSuccess({
@@ -283981,6 +284182,7 @@ Examples:
283981
284182
  startedAt,
283982
284183
  dryRun: true,
283983
284184
  costUsd,
284185
+ warnings: lifecycleWarnings,
283984
284186
  data: {
283985
284187
  params: {
283986
284188
  prompt: prompt3,
@@ -283988,13 +284190,10 @@ Examples:
283988
284190
  duration: options.duration,
283989
284191
  ratio: options.ratio,
283990
284192
  image: options.image,
283991
- mode: options.mode,
284193
+ mode: provider === "kling" ? options.mode : void 0,
283992
284194
  negative: options.negative,
283993
284195
  resolution: options.resolution,
283994
- veoModel: options.veoModel,
283995
- seedanceModel: options.seedanceModel,
283996
- grokModel: options.grokModel,
283997
- klingModel: options.klingModel,
284196
+ model: videoModelSpec(provider, options)?.id,
283998
284197
  refImages: options.refImages,
283999
284198
  refVideos: options.refVideos,
284000
284199
  refAudio: options.refAudio,
@@ -284386,7 +284585,7 @@ Examples:
284386
284585
  command: "generate video",
284387
284586
  startedAt,
284388
284587
  costUsd: cost.costUsd,
284389
- warnings: provider === "veo" ? [VEO_SHUTDOWN_WARNING, ...cost.warnings] : cost.warnings,
284588
+ warnings: [...lifecycleWarnings, ...cost.warnings],
284390
284589
  data: {
284391
284590
  provider,
284392
284591
  taskId: result?.id,
@@ -284398,9 +284597,6 @@ Examples:
284398
284597
  return;
284399
284598
  }
284400
284599
  console.log();
284401
- if (provider === "veo") {
284402
- console.log(source_default.yellow(VEO_SHUTDOWN_WARNING));
284403
- }
284404
284600
  if (finalResult.videoUrl) {
284405
284601
  console.log(`Video URL: ${finalResult.videoUrl}`);
284406
284602
  }
@@ -284525,7 +284721,6 @@ function printVideoStarted(providerLabel, taskId, taskType) {
284525
284721
  console.log(`Task ID: ${source_default.bold(taskId)}`);
284526
284722
  if (taskType) console.log(`Type: ${taskType}`);
284527
284723
  }
284528
- var VEO_SHUTDOWN_WARNING;
284529
284724
  var init_video = __esm({
284530
284725
  "../cli/src/commands/generate/video.ts"() {
284531
284726
  "use strict";
@@ -284534,6 +284729,7 @@ var init_video = __esm({
284534
284729
  init_dist5();
284535
284730
  init_dist();
284536
284731
  init_api_key();
284732
+ init_model_lifecycle();
284537
284733
  init_tty();
284538
284734
  init_output();
284539
284735
  init_validate();
@@ -284541,7 +284737,6 @@ var init_video = __esm({
284541
284737
  init_upload_host();
284542
284738
  init_ai_helpers();
284543
284739
  init_status_jobs();
284544
- VEO_SHUTDOWN_WARNING = "Veo 3.1 preview models shut down on 2026-10-22. Use `-p omni` (Gemini Omni 1.1 Flash) instead.";
284545
284740
  }
284546
284741
  });
284547
284742
 
@@ -284651,7 +284846,7 @@ Advanced:
284651
284846
  generate video-cancel Provider lifecycle control; poll with 'vibe status job <job-id> --json'
284652
284847
 
284653
284848
  API Keys (per provider):
284654
- GOOGLE_API_KEY Image (default), Veo video
284849
+ GOOGLE_API_KEY Image (default), Omni video
284655
284850
  OPENAI_API_KEY Image (-p openai)
284656
284851
  FAL_API_KEY Seedance video (-p seedance, default video)
284657
284852
  XAI_API_KEY Grok image/video
@@ -298375,10 +298570,11 @@ var init_openai3 = __esm({
298375
298570
  "../cli/src/agent/adapters/openai.ts"() {
298376
298571
  "use strict";
298377
298572
  init_openai2();
298573
+ init_dist();
298378
298574
  OpenAIAdapter = class {
298379
298575
  provider = "openai";
298380
298576
  client = null;
298381
- model = "gpt-5.4-mini";
298577
+ model = defaultModel("openai", "llm").id;
298382
298578
  async initialize(apiKey) {
298383
298579
  this.client = new openai_default({ apiKey });
298384
298580
  }
@@ -301924,10 +302120,11 @@ var init_claude2 = __esm({
301924
302120
  "../cli/src/agent/adapters/claude.ts"() {
301925
302121
  "use strict";
301926
302122
  init_sdk();
302123
+ init_dist();
301927
302124
  ClaudeAdapter = class {
301928
302125
  provider = "claude";
301929
302126
  client = null;
301930
- model = "claude-sonnet-5-5";
302127
+ model = defaultModel("claude", "llm").id;
301931
302128
  async initialize(apiKey) {
301932
302129
  this.client = new sdk_default({ apiKey });
301933
302130
  }
@@ -303363,10 +303560,11 @@ var init_xai = __esm({
303363
303560
  "../cli/src/agent/adapters/xai.ts"() {
303364
303561
  "use strict";
303365
303562
  init_openai2();
303563
+ init_dist();
303366
303564
  XAIAdapter = class {
303367
303565
  provider = "xai";
303368
303566
  client = null;
303369
- model = "grok-4.3";
303567
+ model = defaultModel("grok", "llm").id;
303370
303568
  async initialize(apiKey) {
303371
303569
  this.client = new openai_default({
303372
303570
  apiKey,
@@ -303833,6 +304031,7 @@ var init_detect = __esm({
303833
304031
  validateOutputPath(options.output);
303834
304032
  }
303835
304033
  if (options.dryRun) {
304034
+ spinner2.stop();
303836
304035
  outputSuccess({
303837
304036
  command: "detect scenes",
303838
304037
  startedAt,
@@ -303952,6 +304151,7 @@ var init_detect = __esm({
303952
304151
  validateOutputPath(options.output);
303953
304152
  }
303954
304153
  if (options.dryRun) {
304154
+ spinner2.stop();
303955
304155
  outputSuccess({
303956
304156
  command: "detect silence",
303957
304157
  startedAt,
@@ -304038,6 +304238,7 @@ var init_detect = __esm({
304038
304238
  validateOutputPath(options.output);
304039
304239
  }
304040
304240
  if (options.dryRun) {
304241
+ spinner2.stop();
304041
304242
  outputSuccess({
304042
304243
  command: "detect beats",
304043
304244
  startedAt,
@@ -304157,8 +304358,9 @@ var EXPLICIT_COMMAND_METADATA = {
304157
304358
  schema: { surface: "agent", note: "Machine-readable command discovery." },
304158
304359
  completion: { surface: "advanced", note: "Shell ergonomics helper." },
304159
304360
  agent: {
304160
- surface: "advanced",
304161
- note: "Optional fallback REPL; external coding agents are the primary workflow."
304361
+ surface: "legacy",
304362
+ replacement: "a host agent (Claude Code, Codex, Cursor) or the MCP server via `vibe host setup`",
304363
+ note: "Deprecated built-in REPL, removed before 1.0."
304162
304364
  },
304163
304365
  "design.validate": { surface: "public", note: "Validate the DESIGN.md visual contract." },
304164
304366
  "generate.image": { surface: "public" },
@@ -309748,7 +309950,7 @@ var generateVideoTool = defineTool({
309748
309950
  cost: "high",
309749
309951
  title: "Generate Video",
309750
309952
  annotations: { readOnly: false, openWorld: true },
309751
- 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.",
309953
+ 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.",
309752
309954
  schema: z7.object({
309753
309955
  prompt: z7.string().describe("Text prompt describing the video"),
309754
309956
  provider: z7.enum(["seedance", "grok", "kling", "runway", "veo", "omni"]).optional().describe(
@@ -314191,8 +314393,9 @@ they want for a given task. This guide is the operator-facing summary.
314191
314393
 
314192
314394
  If you already use Claude Code, Codex, Cursor, Aider, Gemini CLI, OpenCode,
314193
314395
  or another coding agent, let that host drive \`vibe\` directly through shell
314194
- commands plus \`AGENTS.md\` / \`CLAUDE.md\`. \`vibe agent\` is the optional
314195
- built-in fallback when you do not already have an agent host.
314396
+ commands plus \`AGENTS.md\` / \`CLAUDE.md\`. Without a coding agent, connect
314397
+ the MCP server to Claude Desktop or ChatGPT (\`vibe host setup\`).
314398
+ \`vibe agent\` is deprecated and will be removed before 1.0.
314196
314399
 
314197
314400
  ## TL;DR
314198
314401
 
@@ -314203,12 +314406,12 @@ built-in fallback when you do not already have an agent host.
314203
314406
  | **Reproducibility** | none | high (idempotent) | highest (checkpointed) |
314204
314407
  | **Budget caps** | per-session max-turns | none | \`--budget-usd\`, \`--budget-tokens\`, \`--max-errors\` |
314205
314408
  | **Resume after crash** | no | re-invoke | \`--resume\` |
314206
- | **Best for** | optional built-in exploration | finished script | repeatable workflows |
314409
+ | **Best for** | deprecated; use a host agent | finished script | repeatable workflows |
314207
314410
 
314208
314411
  ## Decision tree
314209
314412
 
314210
314413
  - "I am already in Claude Code/Codex/Cursor/etc." \u2192 regular \`vibe\` shell commands + \`vibe guide\` / \`vibe schema\`
314211
- - "I want to play and do not have an external coding agent" \u2192 \`vibe agent\`
314414
+ - "I do not use a coding agent" \u2192 the MCP server in Claude Desktop or ChatGPT (\`vibe host setup\`)
314212
314415
  - "I have a finished script + visual identity" \u2192 \`vibe build\`
314213
314416
  - "I want this to run again next month" \u2192 \`vibe run\`
314214
314417
 
@@ -314234,9 +314437,6 @@ agent calls them through a tool manifest; \`build\` calls a curated subset
314234
314437
  - \`vibe build\` is conceptually a 4-step pipeline; \`vibe run\` could express
314235
314438
  the same flow but build's STORYBOARD.md input + opinionated defaults are
314236
314439
  the value-add.
314237
- - \`vibe agent\`'s tool registry currently exposes primitives, not
314238
- orchestrators. Adding \`vibe.build\` / \`vibe.run\` as agent tools is on the
314239
- table for a future major.
314240
314440
  - \`vibe run --resume\` has no analog in build/agent; build's idempotent
314241
314441
  re-invoke covers the common case.
314242
314442
  `;
@@ -314343,17 +314543,17 @@ var META = {
314343
314543
  },
314344
314544
  architecture: {
314345
314545
  title: "external agents / vibe agent / build / run",
314346
- summary: "Choose between host-agent shell use, optional built-in agent mode, storyboard builds, and YAML pipelines",
314546
+ summary: "Choose between host-agent shell use, MCP hosts, storyboard builds, and YAML pipelines",
314347
314547
  steps: [
314348
314548
  "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`.",
314349
- "Pick `vibe agent` only for optional built-in exploration when no external agent host is driving the CLI.",
314549
+ "Without a coding agent, connect the MCP server to Claude Desktop or ChatGPT with `vibe host setup`; `vibe agent` is deprecated.",
314350
314550
  "Pick build for STORYBOARD.md \u2192 MP4 with opinionated defaults.",
314351
314551
  "Pick run for repeatable, budget-capped, checkpointed YAML pipelines.",
314352
314552
  "Run `vibe doctor --test-keys` before any high-cost orchestrator to validate keys upfront.",
314353
314553
  "Use `vibe schema --list` (cost field, v0.84) to plan the budget per step before kicking off `vibe run --budget-usd`."
314354
314554
  ],
314355
314555
  relatedCommands: [
314356
- "vibe agent",
314556
+ "vibe host setup",
314357
314557
  "vibe build",
314358
314558
  "vibe run",
314359
314559
  "vibe doctor",
@@ -315349,7 +315549,7 @@ function handleCliFlags(argv, version2) {
315349
315549
  }
315350
315550
 
315351
315551
  // src/index.ts
315352
- if (handleCliFlags(process.argv.slice(2), "0.115.3")) {
315552
+ if (handleCliFlags(process.argv.slice(2), "0.115.5")) {
315353
315553
  process.exit(0);
315354
315554
  }
315355
315555
  console.log = (...args) => console.error(...args);
@@ -315362,7 +315562,7 @@ var server = new Server(
315362
315562
  {
315363
315563
  name: "vibeframe",
315364
315564
  // Stamped with the package version by build.js at bundle time.
315365
- version: "0.115.3"
315565
+ version: "0.115.5"
315366
315566
  },
315367
315567
  {
315368
315568
  capabilities: {