@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.
@@ -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(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
- 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((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
- 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((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 || "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(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: "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(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 = "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: 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" || data.status === "THROTTLED") {
5653
- result.error = data.failure || data.failureCode || "Generation failed";
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 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 key = (alias ?? "v3").trim().toLowerCase();
5796
- const aliases = {
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(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
- 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 key = (alias ?? "1.5").trim().toLowerCase();
6259
- const aliases = {
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(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
- 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 key = (alias ?? "quality").trim().toLowerCase();
10726
- const aliases = {
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(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 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(query).sort(([a], [b]) => a.localeCompare(b)).map(([key, value]) => `${awsEncode(key)}=${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 key = `${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, 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, 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,
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
  "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("npx", ["--yes", "remotion", "--help"], { timeout: 6e4 });
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 CLI not found or failed to initialize.",
38034
+ "Remotion renders need npm to install the Remotion CLI into a temporary project.",
37900
38035
  ` Debug: ${detail.slice(0, 200)}`,
37901
- " Fix: npm install -g @remotion/cli",
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: "gpt-5.4-mini",
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-sonnet-5-5",
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 uploadFrameToImgbb(framePath, imgbbApiKey) {
40440
+ async function uploadFrame(host, framePath) {
40306
40441
  try {
40307
- const frameBuffer = await readFile24(framePath);
40308
- const frameBase64 = frameBuffer.toString("base64");
40309
- const formData = new FormData();
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
- const data = await response.json();
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
- const imgbbApiKey = options.imgbbApiKey || await getApiKey("IMGBB_API_KEY", "imgbb", void 0);
40472
- if (!imgbbApiKey) {
40597
+ let uploadHost;
40598
+ try {
40599
+ uploadHost = await resolveUploadHost();
40600
+ } catch (err) {
40473
40601
  return {
40474
40602
  success: false,
40475
- error: "IMGBB_API_KEY required for image hosting. Get a free API key at https://api.imgbb.com/",
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("Uploading frame to imgbb...");
40520
- const upload = await uploadFrameToImgbb(framePath, imgbbApiKey);
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 to imgbb: ${upload.error || "unknown"}`,
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 uploadFrameToImgbb(lastFramePath, imgbbApiKey);
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 = MODEL_MAP2[modelAlias] ?? MODEL_MAP2["sonnet"];
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 alias = modelAlias?.trim() ?? "";
44315
- for (const [id, model] of Object.entries(OPENAI_IMAGE_MODELS)) {
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
- OPENAI_IMAGE_MODELS = {
44344
- "gpt-image-2.5-sunburst": { label: "GPT Image 2.5 Sunburst", aliases: ["2.5", "sunburst"] },
44345
- "gpt-image-2.5-flare": { label: "GPT Image 2.5 Flare", aliases: ["flare", "2.5-flare"] },
44346
- "gpt-image-2": { label: "GPT Image 2", aliases: ["2"] },
44347
- "gpt-image-1.5": { label: "GPT Image 1.5", aliases: ["1.5"] }
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
- warnings: [],
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
- veoModel: options.veoModel,
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: provider === "veo" ? [VEO_SHUTDOWN_WARNING, ...cost.warnings] : cost.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), Veo video
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 = "gpt-5.4-mini";
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-sonnet-5-5";
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-4.3";
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: "advanced",
52051
- note: "Optional fallback REPL; external coding agents are the primary workflow."
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\`. \`vibe agent\` is the optional
62070
- built-in fallback when you do not already have an agent host.
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** | optional built-in exploration | finished script | repeatable workflows |
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 want to play and do not have an external coding agent" \u2192 \`vibe agent\`
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, optional built-in agent mode, storyboard builds, and YAML pipelines",
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
- "Pick `vibe agent` only for optional built-in exploration when no external agent host is driving the CLI.",
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 agent",
62431
+ "vibe host setup",
62232
62432
  "vibe build",
62233
62433
  "vibe run",
62234
62434
  "vibe doctor",