@vibeframe/cli 0.105.1 → 0.106.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (245) hide show
  1. package/dist/agent/adapters/claude.d.ts +14 -0
  2. package/dist/agent/adapters/gemini.d.ts +14 -0
  3. package/dist/agent/adapters/index.d.ts +27 -0
  4. package/dist/agent/adapters/ollama.d.ts +19 -0
  5. package/dist/agent/adapters/openai.d.ts +14 -0
  6. package/dist/agent/adapters/openrouter.d.ts +15 -0
  7. package/dist/agent/adapters/openrouter.test.d.ts +4 -0
  8. package/dist/agent/adapters/xai.d.ts +14 -0
  9. package/dist/agent/index.d.ts +109 -0
  10. package/dist/agent/memory/index.d.ts +69 -0
  11. package/dist/agent/prompts/system.d.ts +5 -0
  12. package/dist/agent/tools/e2e.test.d.ts +25 -0
  13. package/dist/agent/tools/index.d.ts +59 -0
  14. package/dist/agent/tools/integration.test.d.ts +10 -0
  15. package/dist/agent/tools/scene.test.d.ts +1 -0
  16. package/dist/agent/types.d.ts +72 -0
  17. package/dist/commands/_shared/build-asset-metadata.d.ts +43 -0
  18. package/dist/commands/_shared/build-asset-reference.d.ts +18 -0
  19. package/dist/commands/_shared/build-backdrop-prompt.d.ts +8 -0
  20. package/dist/commands/_shared/build-backdrop-prompt.test.d.ts +1 -0
  21. package/dist/commands/_shared/build-cache.d.ts +37 -0
  22. package/dist/commands/_shared/build-plan.d.ts +107 -0
  23. package/dist/commands/_shared/build-plan.test.d.ts +1 -0
  24. package/dist/commands/_shared/compose-prompts.d.ts +97 -0
  25. package/dist/commands/_shared/compose-prompts.test.d.ts +1 -0
  26. package/dist/commands/_shared/compose-scenes-skills.d.ts +282 -0
  27. package/dist/commands/_shared/compose-scenes-skills.test.d.ts +1 -0
  28. package/dist/commands/_shared/composer-resolve.d.ts +47 -0
  29. package/dist/commands/_shared/composer-resolve.test.d.ts +1 -0
  30. package/dist/commands/_shared/cost-tier.d.ts +58 -0
  31. package/dist/commands/_shared/edit/_helpers.d.ts +12 -0
  32. package/dist/commands/_shared/edit/caption.d.ts +47 -0
  33. package/dist/commands/_shared/edit/fade.d.ts +38 -0
  34. package/dist/commands/_shared/edit/jump-cut.d.ts +80 -0
  35. package/dist/commands/_shared/edit/noise-reduce.d.ts +33 -0
  36. package/dist/commands/_shared/edit/silence-cut.d.ts +63 -0
  37. package/dist/commands/_shared/edit/text-overlay.d.ts +50 -0
  38. package/dist/commands/_shared/edit/translate-srt.d.ts +40 -0
  39. package/dist/commands/_shared/edit/video-review.d.ts +62 -0
  40. package/dist/commands/_shared/execute-fill-gaps.d.ts +97 -0
  41. package/dist/commands/_shared/hf-skill-bundle/bundle-content.d.ts +16 -0
  42. package/dist/commands/_shared/hf-skill-bundle/bundle.d.ts +57 -0
  43. package/dist/commands/_shared/hf-skill-bundle/bundle.test.d.ts +1 -0
  44. package/dist/commands/_shared/init-templates.d.ts +58 -0
  45. package/dist/commands/_shared/init-templates.test.d.ts +1 -0
  46. package/dist/commands/_shared/install-skill.d.ts +76 -0
  47. package/dist/commands/_shared/install-skill.test.d.ts +1 -0
  48. package/dist/commands/_shared/openai-image.d.ts +49 -0
  49. package/dist/commands/_shared/openai-image.test.d.ts +1 -0
  50. package/dist/commands/_shared/product-surface.d.ts +11 -0
  51. package/dist/commands/_shared/product-surface.test.d.ts +1 -0
  52. package/dist/commands/_shared/project-config.d.ts +60 -0
  53. package/dist/commands/_shared/render-inspect.d.ts +104 -0
  54. package/dist/commands/_shared/render-inspect.test.d.ts +1 -0
  55. package/dist/commands/_shared/review-report.d.ts +65 -0
  56. package/dist/commands/_shared/root-sync.d.ts +39 -0
  57. package/dist/commands/_shared/scene-audio-mux.d.ts +74 -0
  58. package/dist/commands/_shared/scene-audio-mux.test.d.ts +6 -0
  59. package/dist/commands/_shared/scene-audio-scan.d.ts +93 -0
  60. package/dist/commands/_shared/scene-audio-scan.test.d.ts +5 -0
  61. package/dist/commands/_shared/scene-build-mode.d.ts +4 -0
  62. package/dist/commands/_shared/scene-build-mode.test.d.ts +1 -0
  63. package/dist/commands/_shared/scene-build.d.ts +452 -0
  64. package/dist/commands/_shared/scene-build.test.d.ts +1 -0
  65. package/dist/commands/_shared/scene-html-emit.d.ts +163 -0
  66. package/dist/commands/_shared/scene-html-emit.test.d.ts +1 -0
  67. package/dist/commands/_shared/scene-inspect.d.ts +56 -0
  68. package/dist/commands/_shared/scene-inspect.test.d.ts +1 -0
  69. package/dist/commands/_shared/scene-lint.d.ts +109 -0
  70. package/dist/commands/_shared/scene-lint.test.d.ts +1 -0
  71. package/dist/commands/_shared/scene-project.d.ts +147 -0
  72. package/dist/commands/_shared/scene-project.test.d.ts +1 -0
  73. package/dist/commands/_shared/scene-render.d.ts +109 -0
  74. package/dist/commands/_shared/scene-render.test.d.ts +1 -0
  75. package/dist/commands/_shared/scene-repair.d.ts +22 -0
  76. package/dist/commands/_shared/scene-repair.test.d.ts +1 -0
  77. package/dist/commands/_shared/status-jobs.d.ts +197 -0
  78. package/dist/commands/_shared/status-jobs.test.d.ts +1 -0
  79. package/dist/commands/_shared/storyboard-draft.d.ts +13 -0
  80. package/dist/commands/_shared/storyboard-draft.test.d.ts +1 -0
  81. package/dist/commands/_shared/storyboard-edit.d.ts +26 -0
  82. package/dist/commands/_shared/storyboard-edit.test.d.ts +1 -0
  83. package/dist/commands/_shared/storyboard-parse.d.ts +159 -0
  84. package/dist/commands/_shared/storyboard-parse.test.d.ts +1 -0
  85. package/dist/commands/_shared/storyboard-revise.d.ts +32 -0
  86. package/dist/commands/_shared/storyboard-revise.test.d.ts +1 -0
  87. package/dist/commands/_shared/timeline-project.d.ts +32 -0
  88. package/dist/commands/_shared/tts-resolve.d.ts +75 -0
  89. package/dist/commands/_shared/tts-resolve.test.d.ts +5 -0
  90. package/dist/commands/_shared/video-providers.d.ts +44 -0
  91. package/dist/commands/_shared/video-utils.d.ts +71 -0
  92. package/dist/commands/_shared/visual-styles.d.ts +55 -0
  93. package/dist/commands/_shared/visual-styles.test.d.ts +1 -0
  94. package/dist/commands/_shared/walkthroughs/walkthroughs.d.ts +47 -0
  95. package/dist/commands/_shared/walkthroughs/walkthroughs.test.d.ts +1 -0
  96. package/dist/commands/agent.d.ts +24 -0
  97. package/dist/commands/ai-analyze.d.ts +105 -0
  98. package/dist/commands/ai-animated-caption.d.ts +63 -0
  99. package/dist/commands/ai-audio.d.ts +92 -0
  100. package/dist/commands/ai-edit-cli.d.ts +13 -0
  101. package/dist/commands/ai-edit.d.ts +29 -0
  102. package/dist/commands/ai-fill-gaps.d.ts +15 -0
  103. package/dist/commands/ai-helpers.d.ts +26 -0
  104. package/dist/commands/ai-highlights.d.ts +126 -0
  105. package/dist/commands/ai-image.d.ts +71 -0
  106. package/dist/commands/ai-motion.d.ts +53 -0
  107. package/dist/commands/ai-review.d.ts +58 -0
  108. package/dist/commands/ai-script-pipeline-cli.d.ts +10 -0
  109. package/dist/commands/ai-script-pipeline.d.ts +74 -0
  110. package/dist/commands/ai-suggest-edit.d.ts +32 -0
  111. package/dist/commands/ai-video.d.ts +95 -0
  112. package/dist/commands/ai.test.d.ts +1 -0
  113. package/dist/commands/audio.d.ts +17 -0
  114. package/dist/commands/batch.d.ts +2 -0
  115. package/dist/commands/batch.test.d.ts +1 -0
  116. package/dist/commands/build.d.ts +2 -0
  117. package/dist/commands/completion.d.ts +20 -0
  118. package/dist/commands/completion.test.d.ts +1 -0
  119. package/dist/commands/context.d.ts +7 -0
  120. package/dist/commands/context.test.d.ts +1 -0
  121. package/dist/commands/demo.d.ts +6 -0
  122. package/dist/commands/detect.d.ts +55 -0
  123. package/dist/commands/doctor.d.ts +5 -0
  124. package/dist/commands/doctor.test.d.ts +1 -0
  125. package/dist/commands/edit/motion-overlay.d.ts +30 -0
  126. package/dist/commands/edit-cmd.d.ts +112 -0
  127. package/dist/commands/envelope-snapshots.test.d.ts +32 -0
  128. package/dist/commands/export.d.ts +60 -0
  129. package/dist/commands/export.test.d.ts +1 -0
  130. package/dist/commands/generate/background.d.ts +22 -0
  131. package/dist/commands/generate/image.d.ts +8 -0
  132. package/dist/commands/generate/music-status.d.ts +20 -0
  133. package/dist/commands/generate/music.d.ts +27 -0
  134. package/dist/commands/generate/sound-effect.d.ts +19 -0
  135. package/dist/commands/generate/speech.d.ts +21 -0
  136. package/dist/commands/generate/storyboard.d.ts +27 -0
  137. package/dist/commands/generate/thumbnail.d.ts +8 -0
  138. package/dist/commands/generate/video-cancel.d.ts +8 -0
  139. package/dist/commands/generate/video-extend.d.ts +8 -0
  140. package/dist/commands/generate/video-status.d.ts +8 -0
  141. package/dist/commands/generate/video.d.ts +8 -0
  142. package/dist/commands/generate.d.ts +36 -0
  143. package/dist/commands/init.d.ts +24 -0
  144. package/dist/commands/init.test.d.ts +1 -0
  145. package/dist/commands/inspect.d.ts +20 -0
  146. package/dist/commands/media.d.ts +2 -0
  147. package/dist/commands/output.d.ts +80 -0
  148. package/dist/commands/output.test.d.ts +1 -0
  149. package/dist/commands/plan.d.ts +2 -0
  150. package/dist/commands/project.d.ts +2 -0
  151. package/dist/commands/project.test.d.ts +1 -0
  152. package/dist/commands/provider-config-cli.test.d.ts +1 -0
  153. package/dist/commands/q-flag-collision.test.d.ts +1 -0
  154. package/dist/commands/remix.d.ts +20 -0
  155. package/dist/commands/render.d.ts +2 -0
  156. package/dist/commands/run.d.ts +14 -0
  157. package/dist/commands/sanitize.d.ts +20 -0
  158. package/dist/commands/scene.d.ts +95 -0
  159. package/dist/commands/scene.test.d.ts +1 -0
  160. package/dist/commands/schema.d.ts +12 -0
  161. package/dist/commands/setup.d.ts +5 -0
  162. package/dist/commands/setup.test.d.ts +1 -0
  163. package/dist/commands/status.d.ts +2 -0
  164. package/dist/commands/storyboard.d.ts +2 -0
  165. package/dist/commands/timeline.d.ts +2 -0
  166. package/dist/commands/timeline.test.d.ts +1 -0
  167. package/dist/commands/validate.d.ts +33 -0
  168. package/dist/commands/walkthrough.d.ts +21 -0
  169. package/dist/config/config.test.d.ts +1 -0
  170. package/dist/config/index.d.ts +110 -0
  171. package/dist/config/schema.d.ts +64 -0
  172. package/dist/config/scope.test.d.ts +1 -0
  173. package/dist/engine/index.d.ts +2 -0
  174. package/dist/engine/index.js +345 -0
  175. package/dist/engine/project.d.ts +93 -0
  176. package/dist/engine/project.test.d.ts +1 -0
  177. package/dist/index.d.ts +6 -0
  178. package/dist/index.js +500 -330
  179. package/dist/pipeline/executor.d.ts +27 -0
  180. package/dist/pipeline/generate-actions.test.d.ts +1 -0
  181. package/dist/pipeline/index.d.ts +3 -0
  182. package/dist/pipeline/renderers/__tests__/html-template.test.d.ts +1 -0
  183. package/dist/pipeline/renderers/__tests__/integration.test.d.ts +1 -0
  184. package/dist/pipeline/renderers/chrome.d.ts +25 -0
  185. package/dist/pipeline/renderers/html-clips.d.ts +19 -0
  186. package/dist/pipeline/renderers/html-runtime.d.ts +6 -0
  187. package/dist/pipeline/renderers/html-template.d.ts +2 -0
  188. package/dist/pipeline/renderers/hyperframes.d.ts +7 -0
  189. package/dist/pipeline/renderers/project-builder.d.ts +7 -0
  190. package/dist/pipeline/renderers/types.d.ts +39 -0
  191. package/dist/pipeline/resolver.d.ts +19 -0
  192. package/dist/pipeline/scene-actions.test.d.ts +1 -0
  193. package/dist/pipeline/types.d.ts +81 -0
  194. package/dist/tools/adapters/agent.d.ts +9 -0
  195. package/dist/tools/adapters/agent.js +188 -0
  196. package/dist/tools/adapters/mcp.d.ts +34 -0
  197. package/dist/tools/adapters/mcp.js +173 -0
  198. package/dist/tools/define-tool.d.ts +82 -0
  199. package/dist/tools/define-tool.js +214 -0
  200. package/dist/tools/manifest/_project-io.d.ts +13 -0
  201. package/dist/tools/manifest/agent-only.d.ts +236 -0
  202. package/dist/tools/manifest/audio.d.ts +93 -0
  203. package/dist/tools/manifest/detect.d.ts +47 -0
  204. package/dist/tools/manifest/edit.d.ts +398 -0
  205. package/dist/tools/manifest/export.d.ts +27 -0
  206. package/dist/tools/manifest/generate.d.ts +310 -0
  207. package/dist/tools/manifest/index.d.ts +22 -0
  208. package/dist/tools/manifest/index.js +60812 -0
  209. package/dist/tools/manifest/inspect.d.ts +139 -0
  210. package/dist/tools/manifest/project.d.ts +33 -0
  211. package/dist/tools/manifest/remix.d.ts +154 -0
  212. package/dist/tools/manifest/scene.d.ts +221 -0
  213. package/dist/tools/manifest/status.d.ts +36 -0
  214. package/dist/tools/manifest/storyboard.d.ts +136 -0
  215. package/dist/tools/manifest/timeline.d.ts +173 -0
  216. package/dist/tools/manifest/walkthrough.d.ts +22 -0
  217. package/dist/tools/manifest.test.d.ts +13 -0
  218. package/dist/tools/zod-to-json-schema.d.ts +47 -0
  219. package/dist/utils/agent-host-detect.d.ts +61 -0
  220. package/dist/utils/agent-host-detect.test.d.ts +1 -0
  221. package/dist/utils/api-key.d.ts +58 -0
  222. package/dist/utils/api-key.test.d.ts +1 -0
  223. package/dist/utils/audio.d.ts +22 -0
  224. package/dist/utils/clipboard.d.ts +27 -0
  225. package/dist/utils/clipboard.test.d.ts +1 -0
  226. package/dist/utils/exec-safe.d.ts +21 -0
  227. package/dist/utils/first-run.d.ts +16 -0
  228. package/dist/utils/input-validation.d.ts +26 -0
  229. package/dist/utils/key-format.d.ts +15 -0
  230. package/dist/utils/key-live-test.d.ts +29 -0
  231. package/dist/utils/key-live-test.test.d.ts +1 -0
  232. package/dist/utils/open-url.d.ts +26 -0
  233. package/dist/utils/open-url.test.d.ts +1 -0
  234. package/dist/utils/project-resolver.d.ts +30 -0
  235. package/dist/utils/project-resolver.test.d.ts +8 -0
  236. package/dist/utils/provider-resolver.d.ts +32 -0
  237. package/dist/utils/provider-resolver.test.d.ts +13 -0
  238. package/dist/utils/remotion.d.ts +201 -0
  239. package/dist/utils/subtitle.d.ts +64 -0
  240. package/dist/utils/subtitle.test.d.ts +1 -0
  241. package/dist/utils/tty.d.ts +86 -0
  242. package/dist/utils/tty.test.d.ts +1 -0
  243. package/dist/utils/upload-host.d.ts +15 -0
  244. package/dist/utils/upload-host.test.d.ts +1 -0
  245. package/package.json +15 -115
package/dist/index.js CHANGED
@@ -7299,6 +7299,39 @@ var init_whisper = __esm({
7299
7299
  }
7300
7300
  });
7301
7301
 
7302
+ // ../ai-providers/dist/gemini/gemini-models.js
7303
+ function isGeminiTextModelAlias(model) {
7304
+ return Object.prototype.hasOwnProperty.call(GEMINI_TEXT_MODEL_ALIASES, model);
7305
+ }
7306
+ function resolveGeminiTextModel(model) {
7307
+ const trimmed = model?.trim();
7308
+ if (!trimmed)
7309
+ return GEMINI_DEFAULT_TEXT_MODEL;
7310
+ if (isGeminiTextModelAlias(trimmed))
7311
+ return GEMINI_TEXT_MODEL_ALIASES[trimmed];
7312
+ if (trimmed.startsWith("gemini-"))
7313
+ return trimmed;
7314
+ return GEMINI_DEFAULT_TEXT_MODEL;
7315
+ }
7316
+ var GEMINI_DEFAULT_TEXT_MODEL, GEMINI_AGENT_DEFAULT_TEXT_MODEL, GEMINI_TEXT_MODEL_ALIASES, GEMINI_TEXT_MODEL_HELP;
7317
+ var init_gemini_models = __esm({
7318
+ "../ai-providers/dist/gemini/gemini-models.js"() {
7319
+ "use strict";
7320
+ GEMINI_DEFAULT_TEXT_MODEL = "gemini-3.5-flash";
7321
+ GEMINI_AGENT_DEFAULT_TEXT_MODEL = "gemini-2.5-flash";
7322
+ GEMINI_TEXT_MODEL_ALIASES = {
7323
+ flash: GEMINI_DEFAULT_TEXT_MODEL,
7324
+ latest: GEMINI_DEFAULT_TEXT_MODEL,
7325
+ "flash-3.5": GEMINI_DEFAULT_TEXT_MODEL,
7326
+ "flash-3": "gemini-3-flash-preview",
7327
+ "flash-2.5": "gemini-2.5-flash",
7328
+ pro: "gemini-2.5-pro",
7329
+ "pro-3.1": "gemini-3.1-pro-preview"
7330
+ };
7331
+ GEMINI_TEXT_MODEL_HELP = "flash/latest (Gemini 3.5 Flash), flash-3.5, flash-3, flash-2.5, pro, pro-3.1, or a full gemini-* model ID";
7332
+ }
7333
+ });
7334
+
7302
7335
  // ../ai-providers/dist/gemini/gemini-motion.js
7303
7336
  function buildMotionSystemPrompt(width, height, fps, duration, durationInFrames, stylePreset) {
7304
7337
  return `You are a world-class broadcast motion graphics designer (like Apple Keynote, Netflix intros, ESPN graphics). Create STUNNING, jaw-dropping overlays that make viewers go "wow".
@@ -7452,7 +7485,7 @@ async function generateMotion(api, description, options = {}) {
7452
7485
  const duration = options.duration || 5;
7453
7486
  const durationInFrames = Math.round(duration * fps);
7454
7487
  const stylePreset = options.style || "modern and clean";
7455
- const modelId = options.model || "gemini-2.5-pro";
7488
+ const modelId = resolveGeminiTextModel(options.model);
7456
7489
  let systemPrompt = buildMotionSystemPrompt(width, height, fps, duration, durationInFrames, stylePreset);
7457
7490
  if (options.videoContext) {
7458
7491
  const sourceLabel = options.sourceType === "image" ? "IMAGE" : "VIDEO";
@@ -7533,7 +7566,7 @@ async function refineMotion(api, existingCode, instructions, options = {}) {
7533
7566
  const fps = options.fps || 30;
7534
7567
  const duration = options.duration || 5;
7535
7568
  const durationInFrames = Math.round(duration * fps);
7536
- const modelId = options.model || "gemini-2.5-pro";
7569
+ const modelId = resolveGeminiTextModel(options.model);
7537
7570
  const systemPrompt = `You are a world-class broadcast motion graphics designer. Modify the provided Remotion component based on instructions.
7538
7571
 
7539
7572
  CANVAS: ${width}\xD7${height}px | ${fps}fps | ${durationInFrames} frames (${duration}s)
@@ -7628,9 +7661,18 @@ var GEMINI_MOTION_MODELS, STYLE_USER_INSTRUCTIONS;
7628
7661
  var init_gemini_motion = __esm({
7629
7662
  "../ai-providers/dist/gemini/gemini-motion.js"() {
7630
7663
  "use strict";
7664
+ init_gemini_models();
7631
7665
  GEMINI_MOTION_MODELS = {
7666
+ gemini: GEMINI_DEFAULT_TEXT_MODEL,
7667
+ flash: GEMINI_DEFAULT_TEXT_MODEL,
7668
+ latest: GEMINI_DEFAULT_TEXT_MODEL,
7669
+ "flash-3.5": GEMINI_DEFAULT_TEXT_MODEL,
7670
+ "flash-3": "gemini-3-flash-preview",
7671
+ "flash-2.5": "gemini-2.5-flash",
7632
7672
  pro: "gemini-2.5-pro",
7633
- "3.1-pro": "gemini-3.1-pro-preview"
7673
+ "2.5-pro": "gemini-2.5-pro",
7674
+ "3.1-pro": "gemini-3.1-pro-preview",
7675
+ "pro-3.1": "gemini-3.1-pro-preview"
7634
7676
  };
7635
7677
  STYLE_USER_INSTRUCTIONS = {
7636
7678
  minimal: "CENTER-ALIGNED pure typography. Thin lines + large title + subtitle. NO glass panels, NO bokeh, NO dark bars. Breathing pulse during hold.",
@@ -7753,7 +7795,7 @@ async function analyzeContent(api, content, targetDuration, options) {
7753
7795
  maxOutputTokens: 4096
7754
7796
  }
7755
7797
  };
7756
- const response = await fetch(`${api.baseUrl}/models/gemini-2.5-flash:generateContent?key=${api.apiKey}`, {
7798
+ const response = await fetch(`${api.baseUrl}/models/${GEMINI_DEFAULT_TEXT_MODEL}:generateContent?key=${api.apiKey}`, {
7757
7799
  method: "POST",
7758
7800
  headers: { "Content-Type": "application/json" },
7759
7801
  body: JSON.stringify(payload)
@@ -7786,6 +7828,36 @@ var init_gemini_storyboard = __esm({
7786
7828
  "../ai-providers/dist/gemini/gemini-storyboard.js"() {
7787
7829
  "use strict";
7788
7830
  init_storyboard_prompt();
7831
+ init_gemini_models();
7832
+ }
7833
+ });
7834
+
7835
+ // ../ai-providers/dist/shared/http.js
7836
+ async function fetchJson(label, url, init) {
7837
+ const response = await fetch(url, init);
7838
+ if (!response.ok) {
7839
+ throw new ProviderHttpError(label, response.status, await response.text());
7840
+ }
7841
+ return await response.json();
7842
+ }
7843
+ function errorMessage(error) {
7844
+ return error instanceof Error ? error.message : "Unknown error";
7845
+ }
7846
+ function sleep(ms) {
7847
+ return new Promise((resolve81) => setTimeout(resolve81, ms));
7848
+ }
7849
+ var ProviderHttpError;
7850
+ var init_http = __esm({
7851
+ "../ai-providers/dist/shared/http.js"() {
7852
+ "use strict";
7853
+ ProviderHttpError = class extends Error {
7854
+ constructor(label, status, body) {
7855
+ super(`${label} (${status}): ${body}`);
7856
+ this.name = "ProviderHttpError";
7857
+ this.status = status;
7858
+ this.body = body;
7859
+ }
7860
+ };
7789
7861
  }
7790
7862
  });
7791
7863
 
@@ -7795,7 +7867,9 @@ var init_GeminiProvider = __esm({
7795
7867
  "../ai-providers/dist/gemini/GeminiProvider.js"() {
7796
7868
  "use strict";
7797
7869
  init_gemini_motion();
7870
+ init_gemini_models();
7798
7871
  init_gemini_storyboard();
7872
+ init_http();
7799
7873
  MODEL_MAP = {
7800
7874
  "flash": "gemini-2.5-flash-image",
7801
7875
  "3.1-flash": "gemini-3.1-flash-image-preview",
@@ -7890,7 +7964,7 @@ var init_GeminiProvider = __esm({
7890
7964
  instances: [instance],
7891
7965
  parameters
7892
7966
  };
7893
- const response = await fetch(`${this.baseUrl}/models/${model}:predictLongRunning`, {
7967
+ const data = await fetchJson("Veo API error", `${this.baseUrl}/models/${model}:predictLongRunning`, {
7894
7968
  method: "POST",
7895
7969
  headers: {
7896
7970
  "Content-Type": "application/json",
@@ -7898,15 +7972,6 @@ var init_GeminiProvider = __esm({
7898
7972
  },
7899
7973
  body: JSON.stringify(requestBody)
7900
7974
  });
7901
- if (!response.ok) {
7902
- const errorText = await response.text();
7903
- return {
7904
- id: "",
7905
- status: "failed",
7906
- error: `Veo API error (${response.status}): ${errorText}`
7907
- };
7908
- }
7909
- const data = await response.json();
7910
7975
  if (data.name) {
7911
7976
  return {
7912
7977
  id: data.name,
@@ -7931,7 +7996,7 @@ var init_GeminiProvider = __esm({
7931
7996
  return {
7932
7997
  id: "",
7933
7998
  status: "failed",
7934
- error: error instanceof Error ? error.message : "Unknown error"
7999
+ error: errorMessage(error)
7935
8000
  };
7936
8001
  }
7937
8002
  }
@@ -7947,21 +8012,12 @@ var init_GeminiProvider = __esm({
7947
8012
  };
7948
8013
  }
7949
8014
  try {
7950
- const response = await fetch(`https://generativelanguage.googleapis.com/v1beta/${operationName}?key=${this.apiKey}`, {
8015
+ const data = await fetchJson("Status check failed", `https://generativelanguage.googleapis.com/v1beta/${operationName}?key=${this.apiKey}`, {
7951
8016
  method: "GET",
7952
8017
  headers: {
7953
8018
  "Content-Type": "application/json"
7954
8019
  }
7955
8020
  });
7956
- if (!response.ok) {
7957
- const errorText = await response.text();
7958
- return {
7959
- id: operationName,
7960
- status: "failed",
7961
- error: `Status check failed (${response.status}): ${errorText}`
7962
- };
7963
- }
7964
- const data = await response.json();
7965
8021
  if (data.error) {
7966
8022
  return {
7967
8023
  id: operationName,
@@ -7994,7 +8050,7 @@ var init_GeminiProvider = __esm({
7994
8050
  return {
7995
8051
  id: operationName,
7996
8052
  status: "failed",
7997
- error: error instanceof Error ? error.message : "Unknown error"
8053
+ error: errorMessage(error)
7998
8054
  };
7999
8055
  }
8000
8056
  }
@@ -8012,7 +8068,7 @@ var init_GeminiProvider = __esm({
8012
8068
  if (result.status === "completed" || result.status === "failed" || result.status === "cancelled") {
8013
8069
  return result;
8014
8070
  }
8015
- await this.sleep(pollingInterval);
8071
+ await sleep(pollingInterval);
8016
8072
  }
8017
8073
  return {
8018
8074
  id: operationName,
@@ -8020,12 +8076,6 @@ var init_GeminiProvider = __esm({
8020
8076
  error: "Generation timed out"
8021
8077
  };
8022
8078
  }
8023
- /**
8024
- * Sleep helper
8025
- */
8026
- sleep(ms) {
8027
- return new Promise((resolve81) => setTimeout(resolve81, ms));
8028
- }
8029
8079
  /**
8030
8080
  * Extend a previously generated Veo video
8031
8081
  * Uses the operation name from a completed generation to create a continuation
@@ -8052,7 +8102,7 @@ var init_GeminiProvider = __esm({
8052
8102
  durationSeconds: Math.max(4, Math.min(8, options?.duration || 6))
8053
8103
  }
8054
8104
  };
8055
- const response = await fetch(`${this.baseUrl}/models/${model}:predictLongRunning`, {
8105
+ const data = await fetchJson("Veo extend API error", `${this.baseUrl}/models/${model}:predictLongRunning`, {
8056
8106
  method: "POST",
8057
8107
  headers: {
8058
8108
  "Content-Type": "application/json",
@@ -8060,15 +8110,6 @@ var init_GeminiProvider = __esm({
8060
8110
  },
8061
8111
  body: JSON.stringify(requestBody)
8062
8112
  });
8063
- if (!response.ok) {
8064
- const errorText = await response.text();
8065
- return {
8066
- id: "",
8067
- status: "failed",
8068
- error: `Veo extend API error (${response.status}): ${errorText}`
8069
- };
8070
- }
8071
- const data = await response.json();
8072
8113
  if (data.name) {
8073
8114
  return {
8074
8115
  id: data.name,
@@ -8085,7 +8126,7 @@ var init_GeminiProvider = __esm({
8085
8126
  return {
8086
8127
  id: "",
8087
8128
  status: "failed",
8088
- error: error instanceof Error ? error.message : "Unknown error"
8129
+ error: errorMessage(error)
8089
8130
  };
8090
8131
  }
8091
8132
  }
@@ -8157,16 +8198,16 @@ var init_GeminiProvider = __esm({
8157
8198
  });
8158
8199
  if (!response.ok) {
8159
8200
  const errorText = await response.text();
8160
- let errorMessage;
8201
+ let errorMessage2;
8161
8202
  try {
8162
8203
  const errorData = JSON.parse(errorText);
8163
- errorMessage = errorData.error?.message || errorText;
8204
+ errorMessage2 = errorData.error?.message || errorText;
8164
8205
  } catch {
8165
- errorMessage = errorText;
8206
+ errorMessage2 = errorText;
8166
8207
  }
8167
8208
  return {
8168
8209
  success: false,
8169
- error: `API error (${response.status}): ${errorMessage}`
8210
+ error: `API error (${response.status}): ${errorMessage2}`
8170
8211
  };
8171
8212
  }
8172
8213
  const data = await response.json();
@@ -8269,16 +8310,16 @@ var init_GeminiProvider = __esm({
8269
8310
  });
8270
8311
  if (!response.ok) {
8271
8312
  const errorText = await response.text();
8272
- let errorMessage;
8313
+ let errorMessage2;
8273
8314
  try {
8274
8315
  const errorData = JSON.parse(errorText);
8275
- errorMessage = errorData.error?.message || errorText;
8316
+ errorMessage2 = errorData.error?.message || errorText;
8276
8317
  } catch {
8277
- errorMessage = errorText;
8318
+ errorMessage2 = errorText;
8278
8319
  }
8279
8320
  return {
8280
8321
  success: false,
8281
- error: `API error (${response.status}): ${errorMessage}`
8322
+ error: `API error (${response.status}): ${errorMessage2}`
8282
8323
  };
8283
8324
  }
8284
8325
  const data = await response.json();
@@ -8335,7 +8376,7 @@ var init_GeminiProvider = __esm({
8335
8376
  error: "Google API key not configured"
8336
8377
  };
8337
8378
  }
8338
- const modelId = options.model || "gemini-3-flash-preview";
8379
+ const modelId = resolveGeminiTextModel(options.model);
8339
8380
  try {
8340
8381
  let videoPart;
8341
8382
  if (typeof videoData === "string") {
@@ -8394,16 +8435,16 @@ var init_GeminiProvider = __esm({
8394
8435
  });
8395
8436
  if (!response.ok) {
8396
8437
  const errorText = await response.text();
8397
- let errorMessage;
8438
+ let errorMessage2;
8398
8439
  try {
8399
8440
  const errorData = JSON.parse(errorText);
8400
- errorMessage = errorData.error?.message || errorText;
8441
+ errorMessage2 = errorData.error?.message || errorText;
8401
8442
  } catch {
8402
- errorMessage = errorText;
8443
+ errorMessage2 = errorText;
8403
8444
  }
8404
8445
  return {
8405
8446
  success: false,
8406
- error: `API error (${response.status}): ${errorMessage}`
8447
+ error: `API error (${response.status}): ${errorMessage2}`
8407
8448
  };
8408
8449
  }
8409
8450
  const data = await response.json();
@@ -8442,7 +8483,7 @@ var init_GeminiProvider = __esm({
8442
8483
  error: "Google API key not configured"
8443
8484
  };
8444
8485
  }
8445
- const modelId = options.model || "gemini-3-flash-preview";
8486
+ const modelId = resolveGeminiTextModel(options.model);
8446
8487
  try {
8447
8488
  const buffers = Array.isArray(imageData) ? imageData : [imageData];
8448
8489
  const imageParts = buffers.map((buf) => ({
@@ -8476,16 +8517,16 @@ var init_GeminiProvider = __esm({
8476
8517
  });
8477
8518
  if (!response.ok) {
8478
8519
  const errorText = await response.text();
8479
- let errorMessage;
8520
+ let errorMessage2;
8480
8521
  try {
8481
8522
  const errorData = JSON.parse(errorText);
8482
- errorMessage = errorData.error?.message || errorText;
8523
+ errorMessage2 = errorData.error?.message || errorText;
8483
8524
  } catch {
8484
- errorMessage = errorText;
8525
+ errorMessage2 = errorText;
8485
8526
  }
8486
8527
  return {
8487
8528
  success: false,
8488
- error: `API error (${response.status}): ${errorMessage}`
8529
+ error: `API error (${response.status}): ${errorMessage2}`
8489
8530
  };
8490
8531
  }
8491
8532
  const data = await response.json();
@@ -8544,7 +8585,7 @@ Example response:
8544
8585
  [{"type":"trim","description":"Trim intro to 3 seconds","clipIds":["clip-1"],"params":{"newDuration":3},"confidence":0.9}]
8545
8586
 
8546
8587
  Respond with ONLY the JSON array, no other text.`;
8547
- const response = await fetch(`${this.baseUrl}/models/gemini-2.5-flash:generateContent?key=${this.apiKey}`, {
8588
+ const response = await fetch(`${this.baseUrl}/models/${GEMINI_DEFAULT_TEXT_MODEL}:generateContent?key=${this.apiKey}`, {
8548
8589
  method: "POST",
8549
8590
  headers: {
8550
8591
  "Content-Type": "application/json"
@@ -8666,6 +8707,7 @@ var init_gemini = __esm({
8666
8707
  "use strict";
8667
8708
  init_GeminiProvider();
8668
8709
  init_gemini_motion();
8710
+ init_gemini_models();
8669
8711
  init_define_provider();
8670
8712
  defineProvider({
8671
8713
  id: "gemini",
@@ -11718,20 +11760,20 @@ var init_OpenAIImageProvider = __esm({
11718
11760
  if (!response.ok) {
11719
11761
  const errorText = await response.text();
11720
11762
  console.error("OpenAI Image API error:", errorText);
11721
- let errorMessage = `API error: ${response.status}`;
11763
+ let errorMessage2 = `API error: ${response.status}`;
11722
11764
  try {
11723
11765
  const errorJson = JSON.parse(errorText);
11724
11766
  if (errorJson.error?.message) {
11725
- errorMessage = errorJson.error.message;
11767
+ errorMessage2 = errorJson.error.message;
11726
11768
  }
11727
11769
  } catch {
11728
11770
  if (errorText) {
11729
- errorMessage = errorText.substring(0, 200);
11771
+ errorMessage2 = errorText.substring(0, 200);
11730
11772
  }
11731
11773
  }
11732
11774
  return {
11733
11775
  success: false,
11734
- error: errorMessage
11776
+ error: errorMessage2
11735
11777
  };
11736
11778
  }
11737
11779
  const data = await response.json();
@@ -11826,20 +11868,20 @@ var init_OpenAIImageProvider = __esm({
11826
11868
  });
11827
11869
  if (!response.ok) {
11828
11870
  const errorText = await response.text();
11829
- let errorMessage = `API error: ${response.status}`;
11871
+ let errorMessage2 = `API error: ${response.status}`;
11830
11872
  try {
11831
11873
  const errorJson = JSON.parse(errorText);
11832
11874
  if (errorJson.error?.message) {
11833
- errorMessage = errorJson.error.message;
11875
+ errorMessage2 = errorJson.error.message;
11834
11876
  }
11835
11877
  } catch {
11836
11878
  if (errorText) {
11837
- errorMessage = errorText.substring(0, 200);
11879
+ errorMessage2 = errorText.substring(0, 200);
11838
11880
  }
11839
11881
  }
11840
11882
  return {
11841
11883
  success: false,
11842
- error: errorMessage
11884
+ error: errorMessage2
11843
11885
  };
11844
11886
  }
11845
11887
  const data = await response.json();
@@ -11996,12 +12038,12 @@ var init_RunwayProvider = __esm({
11996
12038
  });
11997
12039
  if (!response.ok) {
11998
12040
  const errorText = await response.text();
11999
- let errorMessage;
12041
+ let errorMessage2;
12000
12042
  try {
12001
12043
  const errorData = JSON.parse(errorText);
12002
- errorMessage = errorData.error || errorData.message || errorText;
12044
+ errorMessage2 = errorData.error || errorData.message || errorText;
12003
12045
  } catch {
12004
- errorMessage = errorText;
12046
+ errorMessage2 = errorText;
12005
12047
  }
12006
12048
  console.error(`[Runway] POST /${endpoint} -> ${response.status} ${response.statusText}
12007
12049
  Model: ${model}, Ratio: ${apiRatio}, Duration: ${body.duration}
@@ -12009,7 +12051,7 @@ var init_RunwayProvider = __esm({
12009
12051
  return {
12010
12052
  id: "",
12011
12053
  status: "failed",
12012
- error: `API error (${response.status}): ${errorMessage}`
12054
+ error: `API error (${response.status}): ${errorMessage2}`
12013
12055
  };
12014
12056
  }
12015
12057
  const data = await response.json();
@@ -12381,17 +12423,17 @@ var init_KlingProvider = __esm({
12381
12423
  async handleResponse(response) {
12382
12424
  if (!response.ok) {
12383
12425
  const errorText = await response.text();
12384
- let errorMessage;
12426
+ let errorMessage2;
12385
12427
  try {
12386
12428
  const errorData = JSON.parse(errorText);
12387
- errorMessage = errorData.message || errorData.error || errorText;
12429
+ errorMessage2 = errorData.message || errorData.error || errorText;
12388
12430
  } catch {
12389
- errorMessage = errorText;
12431
+ errorMessage2 = errorText;
12390
12432
  }
12391
12433
  return {
12392
12434
  id: "",
12393
12435
  status: "failed",
12394
- error: `API error (${response.status}): ${errorMessage}`
12436
+ error: `API error (${response.status}): ${errorMessage2}`
12395
12437
  };
12396
12438
  }
12397
12439
  const data = await response.json();
@@ -12720,20 +12762,20 @@ var init_GrokProvider = __esm({
12720
12762
  });
12721
12763
  if (!response.ok) {
12722
12764
  const errorText = await response.text();
12723
- let errorMessage = `API error: ${response.status}`;
12765
+ let errorMessage2 = `API error: ${response.status}`;
12724
12766
  try {
12725
12767
  const errorJson = JSON.parse(errorText);
12726
12768
  if (errorJson.error?.message) {
12727
- errorMessage = errorJson.error.message;
12769
+ errorMessage2 = errorJson.error.message;
12728
12770
  }
12729
12771
  } catch {
12730
12772
  if (errorText) {
12731
- errorMessage = errorText.substring(0, 200);
12773
+ errorMessage2 = errorText.substring(0, 200);
12732
12774
  }
12733
12775
  }
12734
12776
  return {
12735
12777
  success: false,
12736
- error: errorMessage
12778
+ error: errorMessage2
12737
12779
  };
12738
12780
  }
12739
12781
  const data = await response.json();
@@ -12788,20 +12830,20 @@ var init_GrokProvider = __esm({
12788
12830
  });
12789
12831
  if (!response.ok) {
12790
12832
  const errorText = await response.text();
12791
- let errorMessage = `API error: ${response.status}`;
12833
+ let errorMessage2 = `API error: ${response.status}`;
12792
12834
  try {
12793
12835
  const errorJson = JSON.parse(errorText);
12794
12836
  if (errorJson.error?.message) {
12795
- errorMessage = errorJson.error.message;
12837
+ errorMessage2 = errorJson.error.message;
12796
12838
  }
12797
12839
  } catch {
12798
12840
  if (errorText) {
12799
- errorMessage = errorText.substring(0, 200);
12841
+ errorMessage2 = errorText.substring(0, 200);
12800
12842
  }
12801
12843
  }
12802
12844
  return {
12803
12845
  success: false,
12804
- error: errorMessage
12846
+ error: errorMessage2
12805
12847
  };
12806
12848
  }
12807
12849
  const data = await response.json();
@@ -13255,7 +13297,7 @@ var require_utils = __commonJS({
13255
13297
  exports.throttle = throttle;
13256
13298
  exports.isReact = isReact;
13257
13299
  exports.isPlainObject = isPlainObject;
13258
- exports.sleep = sleep3;
13300
+ exports.sleep = sleep4;
13259
13301
  function ensureEndpointIdFormat(id) {
13260
13302
  const parts = id.split("/");
13261
13303
  if (parts.length > 1) {
@@ -13333,7 +13375,7 @@ var require_utils = __commonJS({
13333
13375
  function isPlainObject(value) {
13334
13376
  return !!value && Object.getPrototypeOf(value) === Object.prototype;
13335
13377
  }
13336
- function sleep3(ms) {
13378
+ function sleep4(ms) {
13337
13379
  return __awaiter(this, void 0, void 0, function* () {
13338
13380
  return new Promise((resolve81) => setTimeout(resolve81, ms));
13339
13381
  });
@@ -17099,6 +17141,39 @@ var require_src = __commonJS({
17099
17141
  });
17100
17142
 
17101
17143
  // ../ai-providers/dist/fal/FalProvider.js
17144
+ function formatFalError(error) {
17145
+ if (!(error instanceof Error))
17146
+ return String(error);
17147
+ const parts = [error.message];
17148
+ const details = falErrorDetails(error);
17149
+ if (details)
17150
+ parts.push(details);
17151
+ return parts.join(" - ");
17152
+ }
17153
+ function falErrorDetails(error) {
17154
+ const withBody = error;
17155
+ const items = [];
17156
+ if (typeof withBody.status === "number")
17157
+ items.push(`HTTP ${withBody.status}`);
17158
+ if (withBody.requestId)
17159
+ items.push(`request ${withBody.requestId}`);
17160
+ if (Array.isArray(withBody.fieldErrors) && withBody.fieldErrors.length > 0) {
17161
+ items.push(withBody.fieldErrors.map((fieldError) => {
17162
+ const path2 = Array.isArray(fieldError.loc) ? fieldError.loc.join(".") : "body";
17163
+ return `${path2}: ${fieldError.msg ?? fieldError.type ?? "invalid"}`;
17164
+ }).join("; "));
17165
+ } else if (withBody.body !== void 0) {
17166
+ items.push(safeJson(withBody.body));
17167
+ }
17168
+ return items.filter(Boolean).join(" - ") || void 0;
17169
+ }
17170
+ function safeJson(value) {
17171
+ try {
17172
+ return JSON.stringify(value);
17173
+ } catch {
17174
+ return String(value);
17175
+ }
17176
+ }
17102
17177
  function pickReferenceImageUrl(input) {
17103
17178
  if (typeof input !== "string")
17104
17179
  return void 0;
@@ -17295,7 +17370,7 @@ var init_FalProvider = __esm({
17295
17370
  return {
17296
17371
  id: "",
17297
17372
  status: "failed",
17298
- error: err instanceof Error ? err.message : String(err)
17373
+ error: formatFalError(err)
17299
17374
  };
17300
17375
  }
17301
17376
  }
@@ -17394,17 +17469,17 @@ var init_ReplicateProvider = __esm({
17394
17469
  });
17395
17470
  if (!response.ok) {
17396
17471
  const errorText = await response.text();
17397
- let errorMessage;
17472
+ let errorMessage2;
17398
17473
  try {
17399
17474
  const errorData = JSON.parse(errorText);
17400
- errorMessage = errorData.detail || errorData.error || errorText;
17475
+ errorMessage2 = errorData.detail || errorData.error || errorText;
17401
17476
  } catch {
17402
- errorMessage = errorText;
17477
+ errorMessage2 = errorText;
17403
17478
  }
17404
17479
  return {
17405
17480
  id: "",
17406
17481
  status: "failed",
17407
- error: `API error (${response.status}): ${errorMessage}`
17482
+ error: `API error (${response.status}): ${errorMessage2}`
17408
17483
  };
17409
17484
  }
17410
17485
  const prediction = await response.json();
@@ -17467,17 +17542,17 @@ var init_ReplicateProvider = __esm({
17467
17542
  });
17468
17543
  if (!response.ok) {
17469
17544
  const errorText = await response.text();
17470
- let errorMessage;
17545
+ let errorMessage2;
17471
17546
  try {
17472
17547
  const errorData = JSON.parse(errorText);
17473
- errorMessage = errorData.detail || errorData.error || errorText;
17548
+ errorMessage2 = errorData.detail || errorData.error || errorText;
17474
17549
  } catch {
17475
- errorMessage = errorText;
17550
+ errorMessage2 = errorText;
17476
17551
  }
17477
17552
  return {
17478
17553
  id: "",
17479
17554
  status: "failed",
17480
- error: `API error (${response.status}): ${errorMessage}`
17555
+ error: `API error (${response.status}): ${errorMessage2}`
17481
17556
  };
17482
17557
  }
17483
17558
  const prediction = await response.json();
@@ -17635,16 +17710,16 @@ var init_ReplicateProvider = __esm({
17635
17710
  });
17636
17711
  if (!response.ok) {
17637
17712
  const errorText = await response.text();
17638
- let errorMessage;
17713
+ let errorMessage2;
17639
17714
  try {
17640
17715
  const errorData = JSON.parse(errorText);
17641
- errorMessage = errorData.detail || errorData.error || errorText;
17716
+ errorMessage2 = errorData.detail || errorData.error || errorText;
17642
17717
  } catch {
17643
- errorMessage = errorText;
17718
+ errorMessage2 = errorText;
17644
17719
  }
17645
17720
  return {
17646
17721
  success: false,
17647
- error: `API error (${response.status}): ${errorMessage}`
17722
+ error: `API error (${response.status}): ${errorMessage2}`
17648
17723
  };
17649
17724
  }
17650
17725
  const prediction = await response.json();
@@ -17738,16 +17813,16 @@ var init_ReplicateProvider = __esm({
17738
17813
  });
17739
17814
  if (!response.ok) {
17740
17815
  const errorText = await response.text();
17741
- let errorMessage;
17816
+ let errorMessage2;
17742
17817
  try {
17743
17818
  const errorData = JSON.parse(errorText);
17744
- errorMessage = errorData.detail || errorData.error || errorText;
17819
+ errorMessage2 = errorData.detail || errorData.error || errorText;
17745
17820
  } catch {
17746
- errorMessage = errorText;
17821
+ errorMessage2 = errorText;
17747
17822
  }
17748
17823
  return {
17749
17824
  success: false,
17750
- error: `API error (${response.status}): ${errorMessage}`
17825
+ error: `API error (${response.status}): ${errorMessage2}`
17751
17826
  };
17752
17827
  }
17753
17828
  const prediction = await response.json();
@@ -17849,17 +17924,17 @@ var init_ReplicateProvider = __esm({
17849
17924
  });
17850
17925
  if (!response.ok) {
17851
17926
  const errorText = await response.text();
17852
- let errorMessage;
17927
+ let errorMessage2;
17853
17928
  try {
17854
17929
  const errorData = JSON.parse(errorText);
17855
- errorMessage = errorData.detail || errorData.error || errorText;
17930
+ errorMessage2 = errorData.detail || errorData.error || errorText;
17856
17931
  } catch {
17857
- errorMessage = errorText;
17932
+ errorMessage2 = errorText;
17858
17933
  }
17859
17934
  return {
17860
17935
  id: "",
17861
17936
  status: "failed",
17862
- error: `API error (${response.status}): ${errorMessage}`
17937
+ error: `API error (${response.status}): ${errorMessage2}`
17863
17938
  };
17864
17939
  }
17865
17940
  const prediction = await response.json();
@@ -17922,17 +17997,17 @@ var init_ReplicateProvider = __esm({
17922
17997
  });
17923
17998
  if (!response.ok) {
17924
17999
  const errorText = await response.text();
17925
- let errorMessage;
18000
+ let errorMessage2;
17926
18001
  try {
17927
18002
  const errorData = JSON.parse(errorText);
17928
- errorMessage = errorData.detail || errorData.error || errorText;
18003
+ errorMessage2 = errorData.detail || errorData.error || errorText;
17929
18004
  } catch {
17930
- errorMessage = errorText;
18005
+ errorMessage2 = errorText;
17931
18006
  }
17932
18007
  return {
17933
18008
  id: "",
17934
18009
  status: "failed",
17935
- error: `API error (${response.status}): ${errorMessage}`
18010
+ error: `API error (${response.status}): ${errorMessage2}`
17936
18011
  };
17937
18012
  }
17938
18013
  const prediction = await response.json();
@@ -17996,6 +18071,10 @@ __export(dist_exports2, {
17996
18071
  ClaudeProvider: () => ClaudeProvider,
17997
18072
  ElevenLabsProvider: () => ElevenLabsProvider,
17998
18073
  FalProvider: () => FalProvider,
18074
+ GEMINI_AGENT_DEFAULT_TEXT_MODEL: () => GEMINI_AGENT_DEFAULT_TEXT_MODEL,
18075
+ GEMINI_DEFAULT_TEXT_MODEL: () => GEMINI_DEFAULT_TEXT_MODEL,
18076
+ GEMINI_TEXT_MODEL_ALIASES: () => GEMINI_TEXT_MODEL_ALIASES,
18077
+ GEMINI_TEXT_MODEL_HELP: () => GEMINI_TEXT_MODEL_HELP,
17999
18078
  GeminiProvider: () => GeminiProvider,
18000
18079
  GrokProvider: () => GrokProvider,
18001
18080
  KNOWN_VOICES: () => KNOWN_VOICES,
@@ -18026,6 +18105,7 @@ __export(dist_exports2, {
18026
18105
  getProvidersFor: () => getProvidersFor,
18027
18106
  getSetupProviders: () => getSetupProviders,
18028
18107
  grokProvider: () => grokProvider,
18108
+ isGeminiTextModelAlias: () => isGeminiTextModelAlias,
18029
18109
  klingProvider: () => klingProvider,
18030
18110
  kokoroProvider: () => kokoroProvider,
18031
18111
  ollamaProvider: () => ollamaProvider,
@@ -18033,6 +18113,7 @@ __export(dist_exports2, {
18033
18113
  openaiProvider: () => openaiProvider,
18034
18114
  providerRegistry: () => providerRegistry,
18035
18115
  replicateProvider: () => replicateProvider,
18116
+ resolveGeminiTextModel: () => resolveGeminiTextModel,
18036
18117
  resolveVoiceId: () => resolveVoiceId,
18037
18118
  runwayProvider: () => runwayProvider,
18038
18119
  whisperProvider: () => whisperProvider
@@ -25793,6 +25874,7 @@ var config_exports = {};
25793
25874
  __export(config_exports, {
25794
25875
  CONFIG_DIR: () => CONFIG_DIR,
25795
25876
  CONFIG_PATH: () => CONFIG_PATH,
25877
+ ConfigFileError: () => ConfigFileError,
25796
25878
  LEGACY_USER_CONFIG_DIR: () => LEGACY_USER_CONFIG_DIR,
25797
25879
  LEGACY_USER_CONFIG_PATH: () => LEGACY_USER_CONFIG_PATH,
25798
25880
  PROVIDER_ENV_ALIASES: () => PROVIDER_ENV_ALIASES,
@@ -25903,8 +25985,8 @@ async function readConfigFile(path2) {
25903
25985
  const content = await readFile2(path2, "utf-8");
25904
25986
  const parsed = (0, import_yaml.parse)(content);
25905
25987
  return applyDefaults(parsed);
25906
- } catch {
25907
- return null;
25988
+ } catch (error) {
25989
+ throw new ConfigFileError(path2, error);
25908
25990
  }
25909
25991
  }
25910
25992
  async function readUserConfigFile() {
@@ -25984,7 +26066,7 @@ async function updateProviderKey(providerKey, apiKey, options = {}) {
25984
26066
  config2.providers[providerKey] = apiKey;
25985
26067
  await saveConfig(config2, { scope, cwd: options.cwd });
25986
26068
  }
25987
- var import_yaml, USER_CONFIG_DIR, USER_CONFIG_PATH, USER_DATA_DIR, USER_CACHE_DIR, LEGACY_USER_CONFIG_DIR, LEGACY_USER_CONFIG_PATH, CONFIG_DIR, CONFIG_PATH;
26069
+ var import_yaml, USER_CONFIG_DIR, USER_CONFIG_PATH, USER_DATA_DIR, USER_CACHE_DIR, LEGACY_USER_CONFIG_DIR, LEGACY_USER_CONFIG_PATH, CONFIG_DIR, CONFIG_PATH, ConfigFileError;
25988
26070
  var init_config = __esm({
25989
26071
  "src/config/index.ts"() {
25990
26072
  "use strict";
@@ -26003,6 +26085,16 @@ var init_config = __esm({
26003
26085
  LEGACY_USER_CONFIG_PATH = resolve4(LEGACY_USER_CONFIG_DIR, "config.yaml");
26004
26086
  CONFIG_DIR = USER_CONFIG_DIR;
26005
26087
  CONFIG_PATH = USER_CONFIG_PATH;
26088
+ ConfigFileError = class extends Error {
26089
+ path;
26090
+ constructor(path2, cause) {
26091
+ const detail = cause instanceof Error ? cause.message : String(cause);
26092
+ super(`Failed to read VibeFrame config at ${path2}: ${detail}`);
26093
+ this.name = "ConfigFileError";
26094
+ this.path = path2;
26095
+ this.cause = cause;
26096
+ }
26097
+ };
26006
26098
  }
26007
26099
  });
26008
26100
 
@@ -27430,6 +27522,52 @@ function buildPreset(input) {
27430
27522
  }
27431
27523
  }
27432
27524
  }
27525
+ function lottieOverlayStyle(input) {
27526
+ const pos = input.position ?? "full";
27527
+ const rawScale = input.scale ?? (pos === "full" ? 1 : 0.25);
27528
+ const scale = Math.max(0.01, Math.min(2, rawScale));
27529
+ const opacity = Math.max(0, Math.min(1, input.opacity ?? 1));
27530
+ const base = [
27531
+ "position:absolute",
27532
+ "pointer-events:none",
27533
+ `opacity:${opacity}`
27534
+ ];
27535
+ if (pos === "full") {
27536
+ base.push("inset:0", "width:100%", "height:100%");
27537
+ } else {
27538
+ const pct = scale * 100;
27539
+ base.push(`width:${pct}%`, `height:${pct}%`);
27540
+ switch (pos) {
27541
+ case "center":
27542
+ base.push("top:50%", "left:50%", "transform:translate(-50%,-50%)");
27543
+ break;
27544
+ case "top-left":
27545
+ base.push("top:4%", "left:4%");
27546
+ break;
27547
+ case "top-right":
27548
+ base.push("top:4%", "right:4%");
27549
+ break;
27550
+ case "bottom-left":
27551
+ base.push("bottom:4%", "left:4%");
27552
+ break;
27553
+ case "bottom-right":
27554
+ base.push("bottom:4%", "right:4%");
27555
+ break;
27556
+ }
27557
+ }
27558
+ return base.join(";");
27559
+ }
27560
+ function buildLottieOverlay(input, sceneId) {
27561
+ const loop = input.loop ?? true ? " loop" : "";
27562
+ const style = lottieOverlayStyle(input);
27563
+ const overlayId = `lottie-overlay-${sceneId}`;
27564
+ const markup = `<dotlottie-wc id="${overlayId}" src="${esc(input.src)}" autoplay${loop} style="${style}"></dotlottie-wc>`;
27565
+ const script = `<script type="module">
27566
+ import { setWasmUrl } from "${DOTLOTTIE_WC_CDN}";
27567
+ setWasmUrl("${DOTLOTTIE_WASM_CDN}");
27568
+ </script>`;
27569
+ return { markup, script };
27570
+ }
27433
27571
  function emitSceneHtml(input) {
27434
27572
  if (input.duration <= 0) {
27435
27573
  throw new Error(`Scene duration must be > 0, got ${input.duration}`);
@@ -27450,15 +27588,20 @@ function emitSceneHtml(input) {
27450
27588
  data-volume="1"
27451
27589
  ></audio>
27452
27590
  ` : "";
27591
+ const lottieLayer = input.lottie ? buildLottieOverlay(input.lottie, id) : null;
27592
+ const lottieMarkup = lottieLayer ? `
27593
+ ${lottieLayer.markup}` : "";
27594
+ const lottieScript = lottieLayer ? `
27595
+ ${lottieLayer.script}` : "";
27453
27596
  return `<template id="scene-${id}-template">
27454
27597
  <div data-composition-id="${id}" data-start="0" data-duration="${dur}" data-width="${input.width}" data-height="${input.height}">
27455
27598
  <style>
27456
27599
  ${parts.css}
27457
27600
  </style>
27458
27601
 
27459
- ${parts.body}
27602
+ ${parts.body}${lottieMarkup}
27460
27603
  ${audioBlock}
27461
- <script src="${GSAP_CDN}"></script>
27604
+ <script src="${GSAP_CDN}"></script>${lottieScript}
27462
27605
  <script>
27463
27606
  window.__timelines = window.__timelines || {};
27464
27607
  const tl = gsap.timeline({ paused: true });
@@ -27520,7 +27663,7 @@ function readRootDims(rootHtml) {
27520
27663
  if (!widthMatch || !heightMatch) return null;
27521
27664
  return { width: parseInt(widthMatch[1], 10), height: parseInt(heightMatch[1], 10) };
27522
27665
  }
27523
- var SCENE_PRESETS, GSAP_CDN, SCENE_OVERLAP_SECONDS;
27666
+ var SCENE_PRESETS, LOTTIE_POSITIONS, GSAP_CDN, SCENE_OVERLAP_SECONDS, DOTLOTTIE_WC_VERSION, DOTLOTTIE_WEB_VERSION, DOTLOTTIE_WC_CDN, DOTLOTTIE_WASM_CDN;
27524
27667
  var init_scene_html_emit = __esm({
27525
27668
  "src/commands/_shared/scene-html-emit.ts"() {
27526
27669
  "use strict";
@@ -27531,8 +27674,20 @@ var init_scene_html_emit = __esm({
27531
27674
  "kinetic-type",
27532
27675
  "product-shot"
27533
27676
  ];
27677
+ LOTTIE_POSITIONS = [
27678
+ "full",
27679
+ "center",
27680
+ "top-left",
27681
+ "top-right",
27682
+ "bottom-left",
27683
+ "bottom-right"
27684
+ ];
27534
27685
  GSAP_CDN = "https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js";
27535
27686
  SCENE_OVERLAP_SECONDS = 0.4;
27687
+ DOTLOTTIE_WC_VERSION = "0.9.12";
27688
+ DOTLOTTIE_WEB_VERSION = "0.71.0";
27689
+ DOTLOTTIE_WC_CDN = `https://cdn.jsdelivr.net/npm/@lottiefiles/dotlottie-wc@${DOTLOTTIE_WC_VERSION}/dist/index.js`;
27690
+ DOTLOTTIE_WASM_CDN = `https://cdn.jsdelivr.net/npm/@lottiefiles/dotlottie-web@${DOTLOTTIE_WEB_VERSION}/dist/dotlottie-player.wasm`;
27536
27691
  }
27537
27692
  });
27538
27693
 
@@ -29566,6 +29721,7 @@ var MODEL_SETTINGS_BY_PROVIDER, ComposeBeatError, defaultCallLLM, CONFIG_PROVIDE
29566
29721
  var init_compose_scenes_skills = __esm({
29567
29722
  "src/commands/_shared/compose-scenes-skills.ts"() {
29568
29723
  "use strict";
29724
+ init_dist2();
29569
29725
  init_config();
29570
29726
  init_bundle();
29571
29727
  init_scene_lint();
@@ -29587,12 +29743,12 @@ var init_compose_scenes_skills = __esm({
29587
29743
  medium: { model: "gpt-5", maxTokens: 6e3, costPerMTokIn: 1.25, costPerMTokOut: 10 },
29588
29744
  high: { model: "gpt-5", maxTokens: 8e3, costPerMTokIn: 1.25, costPerMTokOut: 10 }
29589
29745
  },
29590
- // Google Gemini 2.5 Pro — ~2.6× cheaper than Claude per spike, ~20 s/beat.
29591
- // Strong instruction-following on the Hyperframes skill bundle.
29746
+ // Google Gemini 3.5 Flash — current one-shot Gemini default for
29747
+ // analysis/composition. Keep agent loops on their explicit 2.5 Flash default.
29592
29748
  gemini: {
29593
- low: { model: "gemini-2.5-pro", maxTokens: 4e3, costPerMTokIn: 1.25, costPerMTokOut: 5 },
29594
- medium: { model: "gemini-2.5-pro", maxTokens: 6e3, costPerMTokIn: 1.25, costPerMTokOut: 5 },
29595
- high: { model: "gemini-2.5-pro", maxTokens: 8e3, costPerMTokIn: 1.25, costPerMTokOut: 5 }
29749
+ low: { model: GEMINI_DEFAULT_TEXT_MODEL, maxTokens: 4e3, costPerMTokIn: 1.5, costPerMTokOut: 9 },
29750
+ medium: { model: GEMINI_DEFAULT_TEXT_MODEL, maxTokens: 6e3, costPerMTokIn: 1.5, costPerMTokOut: 9 },
29751
+ high: { model: GEMINI_DEFAULT_TEXT_MODEL, maxTokens: 8e3, costPerMTokIn: 1.5, costPerMTokOut: 9 }
29596
29752
  }
29597
29753
  };
29598
29754
  ComposeBeatError = class extends Error {
@@ -30538,6 +30694,30 @@ async function executeSceneAdd(opts) {
30538
30694
  await writeFile11(imageAbsPath, buffer);
30539
30695
  }
30540
30696
  }
30697
+ let lottieRelPath;
30698
+ let lottieAbsPath;
30699
+ let lottieInput;
30700
+ if (opts.lottie) {
30701
+ const sourceAbs = resolve15(opts.lottie.src);
30702
+ if (!await pathExists2(sourceAbs)) {
30703
+ return errResult(`Lottie file not found: ${sourceAbs}`);
30704
+ }
30705
+ const ext = (sourceAbs.match(/\.([a-z0-9]+)$/i)?.[1] ?? "json").toLowerCase();
30706
+ if (ext !== "json" && ext !== "lottie") {
30707
+ return errResult(`Unsupported Lottie file extension: .${ext}. Use .json or .lottie.`);
30708
+ }
30709
+ lottieRelPath = `assets/lottie-${id}.${ext}`;
30710
+ lottieAbsPath = resolve15(projectDir, lottieRelPath);
30711
+ await mkdir6(dirname3(lottieAbsPath), { recursive: true });
30712
+ await copyFile(sourceAbs, lottieAbsPath);
30713
+ lottieInput = {
30714
+ src: lottieRelPath,
30715
+ position: opts.lottie.position,
30716
+ scale: opts.lottie.scale,
30717
+ opacity: opts.lottie.opacity,
30718
+ loop: opts.lottie.loop
30719
+ };
30720
+ }
30541
30721
  const cfg = await loadVibeProjectConfig(projectDir);
30542
30722
  const fallback2 = cfg?.defaultSceneDuration ?? 5;
30543
30723
  const NARRATION_TAIL_BUFFER = 0.5;
@@ -30566,7 +30746,8 @@ async function executeSceneAdd(opts) {
30566
30746
  kicker: opts.kicker,
30567
30747
  imagePath: imageRelPath,
30568
30748
  audioPath: audioRelPath,
30569
- transcript: transcriptWords
30749
+ transcript: transcriptWords,
30750
+ lottie: lottieInput
30570
30751
  });
30571
30752
  await mkdir6(dirname3(scenePath), { recursive: true });
30572
30753
  await writeFile11(scenePath, sceneHtml, "utf-8");
@@ -30587,6 +30768,7 @@ async function executeSceneAdd(opts) {
30587
30768
  rootPath: relative6(process.cwd(), rootPath) || rootPath,
30588
30769
  audioPath: audioAbsPath ? relative6(process.cwd(), audioAbsPath) || audioAbsPath : void 0,
30589
30770
  imagePath: imageAbsPath ? relative6(process.cwd(), imageAbsPath) || imageAbsPath : void 0,
30771
+ lottiePath: lottieAbsPath ? relative6(process.cwd(), lottieAbsPath) || lottieAbsPath : void 0,
30590
30772
  transcriptPath: transcriptAbsPath ? relative6(process.cwd(), transcriptAbsPath) || transcriptAbsPath : void 0,
30591
30773
  transcriptWordCount
30592
30774
  };
@@ -30864,9 +31046,40 @@ Run 'vibe schema scene.<command>' for structured parameter info.`
30864
31046
  ).option("--no-image", "Skip image generation even when --visuals is provided").option(
30865
31047
  "--no-transcribe",
30866
31048
  "Skip Whisper word-level transcribe step (no transcript-<id>.json emitted)"
30867
- ).option("--transcribe-language <code>", "BCP-47 language code passed to Whisper (e.g. en, ko)").option("--force", "Overwrite an existing compositions/scene-<id>.html").option("--dry-run", "Preview parameters without writing files or calling APIs").action(async (name, options) => {
31049
+ ).option("--transcribe-language <code>", "BCP-47 language code passed to Whisper (e.g. en, ko)").option("--force", "Overwrite an existing compositions/scene-<id>.html").option("--lottie <path>", "Lottie animation file (.json/.lottie) to overlay on the scene").option(
31050
+ "--lottie-position <position>",
31051
+ `Lottie position: ${LOTTIE_POSITIONS.join(", ")}`,
31052
+ "full"
31053
+ ).option("--lottie-scale <number>", "Lottie overlay scale (0.01-2)").option("--lottie-opacity <number>", "Lottie overlay opacity (0-1)", "1").option("--lottie-no-loop", "Do not loop the Lottie animation").option("--dry-run", "Preview parameters without writing files or calling APIs").action(async (name, options) => {
30868
31054
  const startedAt = Date.now();
30869
31055
  if (options.style) options.style = validatePreset(options.style);
31056
+ if (options.lottiePosition) {
31057
+ if (!LOTTIE_POSITIONS.includes(options.lottiePosition)) {
31058
+ exitWithError(
31059
+ usageError(
31060
+ `Invalid --lottie-position "${options.lottiePosition}". Valid: ${LOTTIE_POSITIONS.join(", ")}`
31061
+ )
31062
+ );
31063
+ }
31064
+ }
31065
+ let lottieScale;
31066
+ if (options.lottieScale !== void 0) {
31067
+ lottieScale = Number(options.lottieScale);
31068
+ if (!Number.isFinite(lottieScale) || lottieScale < 0.01 || lottieScale > 2) {
31069
+ exitWithError(
31070
+ usageError(`Invalid --lottie-scale "${options.lottieScale}". Must be between 0.01 and 2.`)
31071
+ );
31072
+ }
31073
+ }
31074
+ let lottieOpacity = 1;
31075
+ if (options.lottieOpacity !== void 0) {
31076
+ lottieOpacity = Number(options.lottieOpacity);
31077
+ if (!Number.isFinite(lottieOpacity) || lottieOpacity < 0 || lottieOpacity > 1) {
31078
+ exitWithError(
31079
+ usageError(`Invalid --lottie-opacity "${options.lottieOpacity}". Must be between 0 and 1.`)
31080
+ );
31081
+ }
31082
+ }
30870
31083
  if (options.duration !== void 0) options.duration = validateDuration(options.duration);
30871
31084
  let tts;
30872
31085
  try {
@@ -30895,7 +31108,11 @@ Run 'vibe schema scene.<command>' for structured parameter info.`
30895
31108
  imageProvider: options.imageProvider,
30896
31109
  tts,
30897
31110
  audio: options.audio,
30898
- // commander sets `audio: false` when --no-audio is passed
31111
+ lottie: options.lottie ?? null,
31112
+ lottiePosition: options.lottiePosition,
31113
+ lottieScale: lottieScale ?? null,
31114
+ lottieOpacity: options.lottieOpacity !== void 0 ? lottieOpacity : null,
31115
+ lottieLoop: !options.lottieNoLoop,
30899
31116
  image: options.image
30900
31117
  }
30901
31118
  }
@@ -30923,6 +31140,13 @@ Run 'vibe schema scene.<command>' for structured parameter info.`
30923
31140
  skipTranscribe: options.transcribe === false,
30924
31141
  transcribeLanguage: options.transcribeLanguage,
30925
31142
  force: !!options.force,
31143
+ lottie: options.lottie ? {
31144
+ src: options.lottie,
31145
+ position: options.lottiePosition ?? "full",
31146
+ scale: lottieScale,
31147
+ opacity: options.lottieOpacity !== void 0 ? lottieOpacity : 1,
31148
+ loop: !options.lottieNoLoop
31149
+ } : void 0,
30926
31150
  onProgress: (msg) => {
30927
31151
  if (spinner2) spinner2.text = msg;
30928
31152
  }
@@ -31987,7 +32211,7 @@ Use this image analysis to inform the color palette, typography placement, and o
31987
32211
  6. Recommended animation timing and entrance/exit style
31988
32212
  7. Any moments where overlays should pause, fade, or stay minimal`;
31989
32213
  const analysisResult = await gemini.analyzeVideo(videoBuffer, analysisPrompt, {
31990
- model: "gemini-2.5-flash",
32214
+ model: GEMINI_DEFAULT_TEXT_MODEL,
31991
32215
  fps: 1,
31992
32216
  lowResolution: true
31993
32217
  });
@@ -32156,7 +32380,7 @@ function registerMotionCommand(aiCommand) {
32156
32380
  "auto"
32157
32381
  ).option("--understanding-prompt <text>", "Custom prompt for --video understanding").option("--from-tsx <path>", "Refine an existing TSX file instead of generating from scratch").option(
32158
32382
  "-m, --model <alias>",
32159
- "LLM model: sonnet (default), opus, gemini, gemini-3.1-pro",
32383
+ "LLM model: sonnet (default), opus, gemini, gemini-2.5-pro, gemini-3.1-pro",
32160
32384
  "sonnet"
32161
32385
  ).option("--dry-run", "Preview parameters without executing").action(async (description, options) => {
32162
32386
  const startedAt = Date.now();
@@ -32300,7 +32524,8 @@ var init_ai_motion = __esm({
32300
32524
  sonnet: { provider: "claude", modelId: "claude-sonnet-4-6" },
32301
32525
  opus: { provider: "claude", modelId: "claude-opus-4-7" },
32302
32526
  "opus-4-6": { provider: "claude", modelId: "claude-opus-4-6" },
32303
- gemini: { provider: "gemini", modelId: "gemini-2.5-pro" },
32527
+ gemini: { provider: "gemini", modelId: GEMINI_DEFAULT_TEXT_MODEL },
32528
+ "gemini-2.5-pro": { provider: "gemini", modelId: "gemini-2.5-pro" },
32304
32529
  "gemini-3.1-pro": { provider: "gemini", modelId: "gemini-3.1-pro-preview" }
32305
32530
  };
32306
32531
  }
@@ -33590,7 +33815,7 @@ var init_speech = __esm({
33590
33815
  // src/commands/_shared/video-utils.ts
33591
33816
  import { writeFile as writeFile19, unlink, rename } from "node:fs/promises";
33592
33817
  import { resolve as resolve22, basename as basename4 } from "node:path";
33593
- function sleep(ms) {
33818
+ function sleep2(ms) {
33594
33819
  return new Promise((resolve81) => setTimeout(resolve81, ms));
33595
33820
  }
33596
33821
  async function uploadToImgbb(imageBuffer, apiKey) {
@@ -34811,7 +35036,7 @@ async function refreshMusicStatus(taskId, wait) {
34811
35036
  let result = await executeMusicStatus({ taskId });
34812
35037
  if (!wait) return result;
34813
35038
  for (let i = 0; i < 120 && result.success && result.status === "processing"; i++) {
34814
- await sleep2(5e3);
35039
+ await sleep3(5e3);
34815
35040
  result = await executeMusicStatus({ taskId });
34816
35041
  }
34817
35042
  return result;
@@ -35229,7 +35454,7 @@ function unique(items) {
35229
35454
  ...new Set(items.filter((item) => typeof item === "string" && item.length > 0))
35230
35455
  ];
35231
35456
  }
35232
- function sleep2(ms) {
35457
+ function sleep3(ms) {
35233
35458
  return new Promise((resolve81) => setTimeout(resolve81, ms));
35234
35459
  }
35235
35460
  var init_status_jobs = __esm({
@@ -35727,13 +35952,7 @@ async function executeThumbnailBestFrame(options) {
35727
35952
  await gemini.initialize({ apiKey: googleKey });
35728
35953
  const videoData = await readFile17(videoPath);
35729
35954
  const analysisPrompt = prompt3 || 'Analyze this video and find the single best frame for a thumbnail. Look for frames that are visually striking, well-composed, emotionally engaging, and representative of the video content. Avoid blurry frames, transitions, or dark scenes. Return ONLY a JSON object: {"timestamp": <seconds as number>, "reason": "<brief explanation>"}';
35730
- const modelMap = {
35731
- flash: "gemini-3-flash-preview",
35732
- latest: "gemini-2.5-flash",
35733
- "flash-2.5": "gemini-2.5-flash",
35734
- pro: "gemini-2.5-pro"
35735
- };
35736
- const modelId = modelMap[model] || "gemini-3-flash-preview";
35955
+ const modelId = resolveGeminiTextModel(model);
35737
35956
  const result = await gemini.analyzeVideo(videoData, analysisPrompt, {
35738
35957
  model: modelId,
35739
35958
  fps: 1
@@ -35781,7 +36000,7 @@ import { resolve as resolve27, dirname as dirname8, basename as basename5, extna
35781
36000
  import { existsSync as existsSync17 } from "node:fs";
35782
36001
  import { writeFile as writeFile25, mkdir as mkdir12 } from "node:fs/promises";
35783
36002
  function registerThumbnailCommand(parent) {
35784
- parent.command("thumbnail").description("Generate video thumbnail (DALL-E) or extract best frame from video (Gemini)").argument("[description]", "Thumbnail description (for DALL-E generation)").option("-k, --api-key <key>", "API key (OpenAI for generation, Google for best-frame)").option("-o, --output <path>", "Output file path").option("--style <style>", "Platform style: youtube, instagram, tiktok, twitter").option("--best-frame <video>", "Extract best thumbnail frame from video using Gemini AI").option("--prompt <prompt>", "Custom prompt for best-frame analysis").option("--model <model>", "Gemini model: flash, latest, pro (default: flash)", "flash").action(async (description, options) => {
36003
+ parent.command("thumbnail").description("Generate video thumbnail (DALL-E) or extract best frame from video (Gemini)").argument("[description]", "Thumbnail description (for DALL-E generation)").option("-k, --api-key <key>", "API key (OpenAI for generation, Google for best-frame)").option("-o, --output <path>", "Output file path").option("--style <style>", "Platform style: youtube, instagram, tiktok, twitter").option("--best-frame <video>", "Extract best thumbnail frame from video using Gemini AI").option("--prompt <prompt>", "Custom prompt for best-frame analysis").option("--model <model>", `Gemini model: ${GEMINI_TEXT_MODEL_HELP}`, "flash").action(async (description, options) => {
35785
36004
  const startedAt = Date.now();
35786
36005
  try {
35787
36006
  if (description) rejectControlChars(description);
@@ -37936,7 +38155,7 @@ function registerVideoCommand(parent) {
37936
38155
  "--seedance-model <model>",
37937
38156
  "Seedance variant: quality or fast (fal.ai only)",
37938
38157
  "quality"
37939
- ).option("--negative <prompt>", "Negative prompt - what to avoid (Kling/Veo)").option("--resolution <res>", "Video resolution: 720p, 1080p, 4k (Veo only)").option("--last-frame <path>", "Last frame image for frame interpolation (Veo only)").option(
38158
+ ).option("--negative <prompt>", "Negative prompt - what to avoid (Kling/Veo)").option("--resolution <res>", "Video resolution: 480p, 720p, 1080p, or 4k depending on provider").option("--last-frame <path>", "Last frame image for frame interpolation (Veo) or Seedance end frame").option("--end-image <path>", "Ending frame image for Seedance image-to-video").option(
37940
38159
  "--ref-images <paths...>",
37941
38160
  "Reference images for Seedance reference-to-video or Veo character consistency"
37942
38161
  ).option("--ref-videos <paths...>", "Reference videos for Seedance reference-to-video").option("--ref-audio <paths...>", "Reference audio for Seedance reference-to-video").option("--no-generate-audio", "Disable native audio when the provider supports it").option("--person <mode>", "Person generation: allow_all, allow_adult (Veo only)").option("--veo-model <model>", "Veo model: 3.0, 3.1, 3.1-fast (default: 3.1-fast)", "3.1-fast").option(
@@ -38397,6 +38616,30 @@ Examples:
38397
38616
  exitWithError(apiError(message, true));
38398
38617
  }
38399
38618
  }
38619
+ let seedanceEndImage;
38620
+ const seedanceEndImagePath = options.endImage ?? options.lastFrame;
38621
+ if (seedanceEndImagePath && seedanceReferences.length === 0) {
38622
+ try {
38623
+ const absEndImagePath = resolve31(process.cwd(), seedanceEndImagePath);
38624
+ const endImageBuffer = await readFile18(absEndImagePath);
38625
+ const ext = seedanceEndImagePath.toLowerCase().split(".").pop();
38626
+ const mimeType = ext === "jpg" || ext === "jpeg" ? "image/jpeg" : `image/${ext || "png"}`;
38627
+ const uploadHost = await resolveUploadHost();
38628
+ spinner2.text = `Uploading end image via ${uploadHost.provider} for Seedance...`;
38629
+ const upload = await uploadHost.uploadImage(endImageBuffer, {
38630
+ filename: seedanceEndImagePath,
38631
+ mimeType
38632
+ });
38633
+ seedanceEndImage = upload.url;
38634
+ } catch (err) {
38635
+ spinner2.fail("End image upload failed");
38636
+ const message = err instanceof Error ? err.message : String(err);
38637
+ if (message.includes("IMGBB_API_KEY")) {
38638
+ exitWithError(authError("IMGBB_API_KEY", "ImgBB"));
38639
+ }
38640
+ exitWithError(apiError(message, true));
38641
+ }
38642
+ }
38400
38643
  spinner2.text = "Generating video with fal.ai Seedance 2.0 (this may take 1-3 minutes)...";
38401
38644
  const seedanceModel = String(options.seedanceModel ?? "quality").toLowerCase();
38402
38645
  const falModel = seedanceModel === "fast" || seedanceModel === "seedance-2.0-fast" ? "seedance-2.0-fast" : "seedance-2.0";
@@ -38409,7 +38652,8 @@ Examples:
38409
38652
  negativePrompt: options.negative,
38410
38653
  model: falModel,
38411
38654
  resolution: options.resolution,
38412
- generateAudio: options.generateAudio
38655
+ generateAudio: options.generateAudio,
38656
+ lastFrame: seedanceEndImage
38413
38657
  });
38414
38658
  finalResult = result;
38415
38659
  }
@@ -38719,12 +38963,7 @@ async function detectSilencePeriodsWithGemini(videoPath, minDuration, options) {
38719
38963
  const gemini = new GeminiProvider();
38720
38964
  await gemini.initialize({ apiKey: geminiApiKey });
38721
38965
  const videoBuffer = await readFile19(videoPath);
38722
- const modelMap = {
38723
- flash: "gemini-3-flash-preview",
38724
- "flash-2.5": "gemini-2.5-flash",
38725
- pro: "gemini-2.5-pro"
38726
- };
38727
- const modelId = options.model ? modelMap[options.model] || modelMap.flash : void 0;
38966
+ const modelId = options.model ? resolveGeminiTextModel(options.model) : void 0;
38728
38967
  const prompt3 = `Analyze this video and identify all silent or dead segments where there is NO meaningful content.
38729
38968
 
38730
38969
  Detect these as silent/dead segments:
@@ -41630,7 +41869,7 @@ async function executeMotionOverlay(options) {
41630
41869
  };
41631
41870
  }
41632
41871
  function registerMotionOverlayCommand(parent) {
41633
- parent.command("motion-overlay").description("Apply designed motion graphics overlays to an existing video").argument("<video>", "Video file path").argument("[description]", "Motion overlay description (omit when using --asset)").option("--asset <path>", "User-provided .json/.lottie animation to overlay").option("-o, --output <path>", "Output video file path").option("-d, --duration <sec>", "Overlay/render duration in seconds").option("--start <sec>", "Overlay start time in seconds", "0").option("--style <style>", "Style preset for generated overlays: minimal, corporate, playful, cinematic").option("-m, --model <alias>", "LLM model for generated overlays: sonnet, opus, gemini, gemini-3.1-pro", "sonnet").option("--understand <mode>", "Analyze video before generated overlay: auto, off, required", "auto").option("--understanding-prompt <text>", "Custom prompt for video understanding").option("--position <position>", "Lottie position: full, center, top-left, top-right, bottom-left, bottom-right", "full").option("--scale <number>", "Lottie overlay scale (0.01-2)").option("--opacity <number>", "Lottie overlay opacity (0-1)", "1").option("--loop", "Loop Lottie overlay", true).option("--no-loop", "Do not loop Lottie overlay").option("--dry-run", "Preview parameters without executing").action(async (videoPath, description, options) => {
41872
+ parent.command("motion-overlay").description("Apply designed motion graphics overlays to an existing video").argument("<video>", "Video file path").argument("[description]", "Motion overlay description (omit when using --asset)").option("--asset <path>", "User-provided .json/.lottie animation to overlay").option("-o, --output <path>", "Output video file path").option("-d, --duration <sec>", "Overlay/render duration in seconds").option("--start <sec>", "Overlay start time in seconds", "0").option("--style <style>", "Style preset for generated overlays: minimal, corporate, playful, cinematic").option("-m, --model <alias>", "LLM model for generated overlays: sonnet, opus, gemini, gemini-2.5-pro, gemini-3.1-pro", "sonnet").option("--understand <mode>", "Analyze video before generated overlay: auto, off, required", "auto").option("--understanding-prompt <text>", "Custom prompt for video understanding").option("--position <position>", "Lottie position: full, center, top-left, top-right, bottom-left, bottom-right", "full").option("--scale <number>", "Lottie overlay scale (0.01-2)").option("--opacity <number>", "Lottie overlay opacity (0-1)", "1").option("--loop", "Loop Lottie overlay", true).option("--no-loop", "Do not loop Lottie overlay").option("--dry-run", "Preview parameters without executing").action(async (videoPath, description, options) => {
41634
41873
  const startedAt = Date.now();
41635
41874
  try {
41636
41875
  if (options.output) validateOutputPath(options.output);
@@ -42720,12 +42959,7 @@ async function executeGeminiVideo(options) {
42720
42959
  return { success: false, error: "Google API key required. Run 'vibe setup' or set GOOGLE_API_KEY in .env" };
42721
42960
  }
42722
42961
  const isYouTube = options.source.includes("youtube.com") || options.source.includes("youtu.be");
42723
- const modelMap = {
42724
- flash: "gemini-3-flash-preview",
42725
- "flash-2.5": "gemini-2.5-flash",
42726
- pro: "gemini-2.5-pro"
42727
- };
42728
- const modelId = modelMap[options.model || "flash"] || modelMap.flash;
42962
+ const modelId = resolveGeminiTextModel(options.model);
42729
42963
  let videoData;
42730
42964
  if (isYouTube) {
42731
42965
  videoData = options.source;
@@ -42786,12 +43020,7 @@ async function executeAnalyze(options) {
42786
43020
  error: "Cannot detect source type. Supported: images (.png/.jpg/.webp/.gif), videos (.mp4/.mov/.webm), YouTube URLs, image URLs."
42787
43021
  };
42788
43022
  }
42789
- const modelMap = {
42790
- flash: "gemini-3-flash-preview",
42791
- "flash-2.5": "gemini-2.5-flash",
42792
- pro: "gemini-2.5-pro"
42793
- };
42794
- const modelId = modelMap[options.model || "flash"] || modelMap.flash;
43023
+ const modelId = resolveGeminiTextModel(options.model);
42795
43024
  const gemini = new GeminiProvider();
42796
43025
  await gemini.initialize({ apiKey });
42797
43026
  if (isImage) {
@@ -42871,7 +43100,7 @@ async function executeAnalyze(options) {
42871
43100
  }
42872
43101
  }
42873
43102
  function registerAnalyzeCommands(aiCommand) {
42874
- aiCommand.command("gemini-video").description("Analyze video using Gemini (summarize, Q&A, extract info)").argument("<source>", "Video file path or YouTube URL").argument("<prompt>", "Analysis prompt (e.g., 'Summarize this video')").option("-k, --api-key <key>", "Google API key (or set GOOGLE_API_KEY env)").option("-m, --model <model>", "Model: flash (default), flash-2.5, pro", "flash").option("--fps <number>", "Frames per second (default: 1, higher for action)").option("--start <seconds>", "Start offset in seconds (for clipping)").option("--end <seconds>", "End offset in seconds (for clipping)").option("--low-res", "Use low resolution mode (fewer tokens, longer videos)").option("-v, --verbose", "Show token usage").action(async (source, prompt3, options) => {
43103
+ aiCommand.command("gemini-video").description("Analyze video using Gemini (summarize, Q&A, extract info)").argument("<source>", "Video file path or YouTube URL").argument("<prompt>", "Analysis prompt (e.g., 'Summarize this video')").option("-k, --api-key <key>", "Google API key (or set GOOGLE_API_KEY env)").option("-m, --model <model>", `Model: ${GEMINI_TEXT_MODEL_HELP}`, "flash").option("--fps <number>", "Frames per second (default: 1, higher for action)").option("--start <seconds>", "Start offset in seconds (for clipping)").option("--end <seconds>", "End offset in seconds (for clipping)").option("--low-res", "Use low resolution mode (fewer tokens, longer videos)").option("-v, --verbose", "Show token usage").action(async (source, prompt3, options) => {
42875
43104
  try {
42876
43105
  if (options.apiKey) {
42877
43106
  process.env.GOOGLE_API_KEY = options.apiKey;
@@ -42914,7 +43143,7 @@ function registerAnalyzeCommands(aiCommand) {
42914
43143
  exitWithError(apiError(`Video analysis failed: ${error instanceof Error ? error.message : String(error)}`, true));
42915
43144
  }
42916
43145
  });
42917
- aiCommand.command("analyze").description("Analyze any media: images, videos, or YouTube URLs using Gemini").argument("<source>", "Image/video file path, image URL, or YouTube URL").argument("<prompt>", "Analysis prompt (e.g., 'Describe this image', 'Summarize this video')").option("-k, --api-key <key>", "Google API key (or set GOOGLE_API_KEY env)").option("-m, --model <model>", "Model: flash (default), flash-2.5, pro", "flash").option("--fps <number>", "Frames per second for video (default: 1)").option("--start <seconds>", "Start offset in seconds (video only)").option("--end <seconds>", "End offset in seconds (video only)").option("--low-res", "Use low resolution mode (fewer tokens)").option("-v, --verbose", "Show token usage").action(async (source, prompt3, options) => {
43146
+ aiCommand.command("analyze").description("Analyze any media: images, videos, or YouTube URLs using Gemini").argument("<source>", "Image/video file path, image URL, or YouTube URL").argument("<prompt>", "Analysis prompt (e.g., 'Describe this image', 'Summarize this video')").option("-k, --api-key <key>", "Google API key (or set GOOGLE_API_KEY env)").option("-m, --model <model>", `Model: ${GEMINI_TEXT_MODEL_HELP}`, "flash").option("--fps <number>", "Frames per second for video (default: 1)").option("--start <seconds>", "Start offset in seconds (video only)").option("--end <seconds>", "End offset in seconds (video only)").option("--low-res", "Use low resolution mode (fewer tokens)").option("-v, --verbose", "Show token usage").action(async (source, prompt3, options) => {
42918
43147
  try {
42919
43148
  if (options.apiKey) {
42920
43149
  process.env.GOOGLE_API_KEY = options.apiKey;
@@ -43035,12 +43264,7 @@ ${content}`;
43035
43264
 
43036
43265
  Project context for beat-aware review:
43037
43266
  ${projectContext}` : "";
43038
- const modelMap = {
43039
- flash: "gemini-3-flash-preview",
43040
- "flash-2.5": "gemini-2.5-flash",
43041
- pro: "gemini-2.5-pro"
43042
- };
43043
- const modelId = modelMap[model] || modelMap.flash;
43267
+ const modelId = resolveGeminiTextModel(model);
43044
43268
  const reviewPrompt = `You are a professional video editor reviewing this video for quality. Analyze the video and return a JSON review with the following structure. Return ONLY valid JSON, no extra text.
43045
43269
 
43046
43270
  {
@@ -43147,7 +43371,7 @@ Score each category 1-10. Prefer beatIssues when you can map a problem to a stor
43147
43371
  return result;
43148
43372
  }
43149
43373
  function registerReviewCommand(aiCommand) {
43150
- aiCommand.command("review", { hidden: true }).description("Review video quality using Gemini AI and optionally auto-fix issues").argument("<source>", "Video file path").option("--storyboard <path>", "Storyboard JSON file for context").option("--auto-apply", "Automatically apply fixable corrections").option("--verify", "Run verification pass after applying fixes").option("-m, --model <model>", "Gemini model: flash (default), flash-2.5, pro", "flash").option("-o, --output <path>", "Output video file path (for auto-apply)").option("--dry-run", "Preview parameters without executing").action(async (videoPath, options) => {
43374
+ aiCommand.command("review", { hidden: true }).description("Review video quality using Gemini AI and optionally auto-fix issues").argument("<source>", "Video file path").option("--storyboard <path>", "Storyboard JSON file for context").option("--auto-apply", "Automatically apply fixable corrections").option("--verify", "Run verification pass after applying fixes").option("-m, --model <model>", `Gemini model: ${GEMINI_TEXT_MODEL_HELP}`, "flash").option("-o, --output <path>", "Output video file path (for auto-apply)").option("--dry-run", "Preview parameters without executing").action(async (videoPath, options) => {
43151
43375
  const startedAt = Date.now();
43152
43376
  try {
43153
43377
  if (options.output) {
@@ -44846,7 +45070,7 @@ async function generateVideoWithRetryGrok(grok, segment, options, maxRetries, on
44846
45070
  onProgress?.(
44847
45071
  `\u26A0 ${providerErr.slice(0, 50)}... retry ${attempt + 1}/${maxRetries}`
44848
45072
  );
44849
- await sleep(RETRY_DELAY_MS);
45073
+ await sleep2(RETRY_DELAY_MS);
44850
45074
  } else {
44851
45075
  console.error(source_default.dim(`
44852
45076
  [Grok error: ${providerErr}]`));
@@ -44855,7 +45079,7 @@ async function generateVideoWithRetryGrok(grok, segment, options, maxRetries, on
44855
45079
  const errMsg = err instanceof Error ? err.message : String(err);
44856
45080
  if (attempt < maxRetries) {
44857
45081
  onProgress?.(`\u26A0 Error: ${errMsg.slice(0, 50)}... retry ${attempt + 1}/${maxRetries}`);
44858
- await sleep(RETRY_DELAY_MS);
45082
+ await sleep2(RETRY_DELAY_MS);
44859
45083
  } else {
44860
45084
  console.error(source_default.dim(`
44861
45085
  [Grok error: ${errMsg}]`));
@@ -44886,7 +45110,7 @@ async function generateVideoWithRetryKling(kling, segment, options, maxRetries,
44886
45110
  const providerErr = result.error || "Kling returned failed status";
44887
45111
  if (attempt < maxRetries) {
44888
45112
  onProgress?.(`\u26A0 ${providerErr.slice(0, 50)}... retry ${attempt + 1}/${maxRetries}`);
44889
- await sleep(RETRY_DELAY_MS);
45113
+ await sleep2(RETRY_DELAY_MS);
44890
45114
  } else {
44891
45115
  console.error(source_default.dim(`
44892
45116
  [Kling error: ${providerErr}]`));
@@ -44895,7 +45119,7 @@ async function generateVideoWithRetryKling(kling, segment, options, maxRetries,
44895
45119
  const errMsg = err instanceof Error ? err.message : String(err);
44896
45120
  if (attempt < maxRetries) {
44897
45121
  onProgress?.(`\u26A0 Error: ${errMsg.slice(0, 50)}... retry ${attempt + 1}/${maxRetries}`);
44898
- await sleep(RETRY_DELAY_MS);
45122
+ await sleep2(RETRY_DELAY_MS);
44899
45123
  } else {
44900
45124
  console.error(source_default.dim(`
44901
45125
  [Kling error: ${errMsg}]`));
@@ -44919,7 +45143,7 @@ async function generateVideoWithRetryRunway(runway, segment, referenceImage, opt
44919
45143
  const providerErr = result.error || "Runway returned failed status";
44920
45144
  if (attempt < maxRetries) {
44921
45145
  onProgress?.(`\u26A0 ${providerErr.slice(0, 50)}... retry ${attempt + 1}/${maxRetries}`);
44922
- await sleep(RETRY_DELAY_MS);
45146
+ await sleep2(RETRY_DELAY_MS);
44923
45147
  } else {
44924
45148
  console.error(source_default.dim(`
44925
45149
  [Runway error: ${providerErr}]`));
@@ -44928,7 +45152,7 @@ async function generateVideoWithRetryRunway(runway, segment, referenceImage, opt
44928
45152
  const errMsg = err instanceof Error ? err.message : String(err);
44929
45153
  if (attempt < maxRetries) {
44930
45154
  onProgress?.(`\u26A0 Error: ${errMsg.slice(0, 50)}... retry ${attempt + 1}/${maxRetries}`);
44931
- await sleep(RETRY_DELAY_MS);
45155
+ await sleep2(RETRY_DELAY_MS);
44932
45156
  } else {
44933
45157
  console.error(source_default.dim(`
44934
45158
  [Runway error: ${errMsg}]`));
@@ -44954,7 +45178,7 @@ async function generateVideoWithRetryVeo(gemini, segment, options, maxRetries, o
44954
45178
  const providerErr = result.error || "Veo returned failed status";
44955
45179
  if (attempt < maxRetries) {
44956
45180
  onProgress?.(`\u26A0 ${providerErr.slice(0, 50)}... retry ${attempt + 1}/${maxRetries}`);
44957
- await sleep(RETRY_DELAY_MS);
45181
+ await sleep2(RETRY_DELAY_MS);
44958
45182
  } else {
44959
45183
  console.error(source_default.dim(`
44960
45184
  [Veo error: ${providerErr}]`));
@@ -44963,7 +45187,7 @@ async function generateVideoWithRetryVeo(gemini, segment, options, maxRetries, o
44963
45187
  const errMsg = err instanceof Error ? err.message : String(err);
44964
45188
  if (attempt < maxRetries) {
44965
45189
  onProgress?.(`\u26A0 Error: ${errMsg.slice(0, 50)}... retry ${attempt + 1}/${maxRetries}`);
44966
- await sleep(RETRY_DELAY_MS);
45190
+ await sleep2(RETRY_DELAY_MS);
44967
45191
  } else {
44968
45192
  console.error(source_default.dim(`
44969
45193
  [Veo error: ${errMsg}]`));
@@ -59912,6 +60136,20 @@ var init_scene_render = __esm({
59912
60136
  }
59913
60137
  });
59914
60138
 
60139
+ // src/commands/_shared/scene-build-mode.ts
60140
+ function resolveSceneBuildMode(opts) {
60141
+ const env2 = process.env.VIBE_BUILD_MODE?.trim().toLowerCase();
60142
+ if (env2 === "agent" || env2 === "batch") return env2;
60143
+ if (opts.mode === "agent" || opts.mode === "batch") return opts.mode;
60144
+ return detectedAgentHosts().length > 0 ? "agent" : "batch";
60145
+ }
60146
+ var init_scene_build_mode = __esm({
60147
+ "src/commands/_shared/scene-build-mode.ts"() {
60148
+ "use strict";
60149
+ init_agent_host_detect();
60150
+ }
60151
+ });
60152
+
59915
60153
  // src/commands/_shared/scene-build.ts
59916
60154
  var scene_build_exports = {};
59917
60155
  __export(scene_build_exports, {
@@ -61622,14 +61860,6 @@ function rootSyncBeatsFromOutcomes(beats, outcomes) {
61622
61860
  };
61623
61861
  });
61624
61862
  }
61625
- function resolveSceneBuildMode(opts) {
61626
- const envOverride = process.env.VIBE_BUILD_MODE?.toLowerCase();
61627
- if (envOverride === "agent" || envOverride === "batch") return envOverride;
61628
- const requested = opts.mode ?? "auto";
61629
- if (requested === "agent") return "agent";
61630
- if (requested === "batch") return "batch";
61631
- return detectedAgentHosts().length > 0 ? "agent" : "batch";
61632
- }
61633
61863
  async function resolveBeatDuration(opts) {
61634
61864
  const storyboardMin = opts.beatDuration ?? 3;
61635
61865
  if (!opts.narrationPath) return Number(storyboardMin.toFixed(2));
@@ -61649,7 +61879,6 @@ var init_scene_build = __esm({
61649
61879
  init_audio();
61650
61880
  init_compose_scenes_skills();
61651
61881
  init_compose_prompts();
61652
- init_agent_host_detect();
61653
61882
  init_config();
61654
61883
  init_scene_render();
61655
61884
  init_storyboard_parse();
@@ -61665,6 +61894,8 @@ var init_scene_build = __esm({
61665
61894
  init_status_jobs();
61666
61895
  init_scene_repair();
61667
61896
  init_tts_resolve();
61897
+ init_scene_build_mode();
61898
+ init_scene_build_mode();
61668
61899
  }
61669
61900
  });
61670
61901
 
@@ -62979,15 +63210,15 @@ var init_parseUtil = __esm({
62979
63210
  message: issueData.message
62980
63211
  };
62981
63212
  }
62982
- let errorMessage = "";
63213
+ let errorMessage2 = "";
62983
63214
  const maps = errorMaps.filter((m) => !!m).slice().reverse();
62984
63215
  for (const map of maps) {
62985
- errorMessage = map(fullIssue, { data, defaultError: errorMessage }).message;
63216
+ errorMessage2 = map(fullIssue, { data, defaultError: errorMessage2 }).message;
62986
63217
  }
62987
63218
  return {
62988
63219
  ...issueData,
62989
63220
  path: fullPath,
62990
- message: errorMessage
63221
+ message: errorMessage2
62991
63222
  };
62992
63223
  };
62993
63224
  EMPTY_PATH = [];
@@ -67566,7 +67797,7 @@ var init_edit = __esm({
67566
67797
  duration: external_exports.number().optional().describe("Overlay/render duration in seconds"),
67567
67798
  start: external_exports.number().optional().describe("Overlay start time in seconds"),
67568
67799
  style: external_exports.string().optional().describe("Style preset for generated overlays"),
67569
- model: external_exports.enum(["sonnet", "opus", "gemini", "gemini-3.1-pro"]).optional().describe("LLM model for generated overlays"),
67800
+ model: external_exports.enum(["sonnet", "opus", "gemini", "gemini-2.5-pro", "gemini-3.1-pro"]).optional().describe("LLM model for generated overlays"),
67570
67801
  understand: external_exports.enum(["auto", "off", "required"]).optional().describe("Analyze video before generated overlay (default: auto)"),
67571
67802
  understandingPrompt: external_exports.string().optional().describe("Custom prompt for video understanding"),
67572
67803
  position: external_exports.enum(["full", "center", "top-left", "top-right", "bottom-left", "bottom-right"]).optional().describe("Lottie overlay position"),
@@ -67942,7 +68173,7 @@ var init_inspect = __esm({
67942
68173
  outputPath: external_exports.string().optional().describe("Optional review report path. Defaults to <project>/review-report.json."),
67943
68174
  report: external_exports.boolean().optional().describe("Write review-report.json. Default true."),
67944
68175
  ai: external_exports.boolean().optional().describe("Also run Gemini video review and merge findings into review-report.json. Default false."),
67945
- model: external_exports.enum(["flash", "flash-2.5", "pro"]).optional().describe("Gemini model variant for ai review. Default flash."),
68176
+ model: external_exports.enum(["flash", "latest", "flash-3", "flash-2.5", "pro", "pro-3.1"]).optional().describe("Gemini model variant for ai review. Default flash."),
67946
68177
  dryRun: external_exports.boolean().optional().describe("Preview resolved inputs without probing video or calling Gemini.")
67947
68178
  }),
67948
68179
  async execute(args, ctx) {
@@ -67994,7 +68225,7 @@ var init_inspect = __esm({
67994
68225
  schema: external_exports.object({
67995
68226
  source: external_exports.string().describe("Path to image/video or YouTube URL"),
67996
68227
  prompt: external_exports.string().describe("Analysis prompt (e.g., 'Describe the scene', 'Count people')"),
67997
- model: external_exports.enum(["flash", "flash-2.5", "pro"]).optional().describe("Gemini model variant (default: flash)"),
68228
+ model: external_exports.enum(["flash", "latest", "flash-3", "flash-2.5", "pro", "pro-3.1"]).optional().describe("Gemini model variant (default: flash)"),
67998
68229
  fps: external_exports.number().optional().describe("Frames per second for video sampling (default: 1)"),
67999
68230
  start: external_exports.number().optional().describe("Start time in seconds for video analysis"),
68000
68231
  end: external_exports.number().optional().describe("End time in seconds for video analysis"),
@@ -68022,7 +68253,7 @@ var init_inspect = __esm({
68022
68253
  schema: external_exports.object({
68023
68254
  source: external_exports.string().describe("Path to video file"),
68024
68255
  prompt: external_exports.string().describe("Analysis prompt"),
68025
- model: external_exports.enum(["flash", "flash-2.5", "pro"]).optional().describe("Gemini model variant (default: flash)"),
68256
+ model: external_exports.enum(["flash", "latest", "flash-3", "flash-2.5", "pro", "pro-3.1"]).optional().describe("Gemini model variant (default: flash)"),
68026
68257
  fps: external_exports.number().optional().describe("Frames per second for sampling"),
68027
68258
  start: external_exports.number().optional().describe("Start time in seconds"),
68028
68259
  end: external_exports.number().optional().describe("End time in seconds"),
@@ -68052,7 +68283,7 @@ var init_inspect = __esm({
68052
68283
  storyboardPath: external_exports.string().optional().describe("Path to storyboard.json for intent comparison"),
68053
68284
  autoApply: external_exports.boolean().optional().describe("Automatically apply suggested fixes (default: false)"),
68054
68285
  verify: external_exports.boolean().optional().describe("Re-review after applying fixes (default: false)"),
68055
- model: external_exports.enum(["flash", "flash-2.5", "pro"]).optional().describe("Gemini model variant (default: flash)"),
68286
+ model: external_exports.enum(["flash", "latest", "flash-3", "flash-2.5", "pro", "pro-3.1"]).optional().describe("Gemini model variant (default: flash)"),
68056
68287
  outputPath: external_exports.string().optional().describe("Output path for fixed video")
68057
68288
  }),
68058
68289
  async execute(args) {
@@ -68144,7 +68375,7 @@ var init_generate2 = __esm({
68144
68375
  "Analyze the base video with Gemini before generating motion graphics: auto, off, or required (default: auto)"
68145
68376
  ),
68146
68377
  understandingPrompt: external_exports.string().optional().describe("Custom prompt for video understanding when --video is provided"),
68147
- model: external_exports.enum(["sonnet", "opus", "gemini", "gemini-3.1-pro"]).optional().describe("LLM model for code generation (default: sonnet)"),
68378
+ model: external_exports.enum(["sonnet", "opus", "gemini", "gemini-2.5-pro", "gemini-3.1-pro"]).optional().describe("LLM model for code generation (default: sonnet)"),
68148
68379
  output: external_exports.string().optional().describe("Output path (TSX if code-only, MP4 if rendered)")
68149
68380
  }),
68150
68381
  async execute(args) {
@@ -68409,6 +68640,7 @@ var init_generate2 = __esm({
68409
68640
  "Video provider (default: seedance when FAL_API_KEY is configured, otherwise first configured provider)"
68410
68641
  ),
68411
68642
  image: external_exports.string().optional().describe("Reference image path for image-to-video"),
68643
+ endImage: external_exports.string().optional().describe("Ending frame image path for Seedance image-to-video"),
68412
68644
  refImages: external_exports.array(external_exports.string()).optional().describe("Reference images for Seedance reference-to-video"),
68413
68645
  refVideos: external_exports.array(external_exports.string()).optional().describe("Reference videos for Seedance reference-to-video"),
68414
68646
  refAudio: external_exports.array(external_exports.string()).optional().describe("Reference audio files for Seedance reference-to-video"),
@@ -68416,7 +68648,7 @@ var init_generate2 = __esm({
68416
68648
  ratio: external_exports.string().optional().describe("Aspect ratio: 16:9, 9:16, 1:1 (default: 16:9)"),
68417
68649
  mode: external_exports.string().optional().describe("Kling mode: std or pro"),
68418
68650
  negative: external_exports.string().optional().describe("Negative prompt (Seedance/Kling/Veo)"),
68419
- resolution: external_exports.string().optional().describe("Resolution: 720p, 1080p, 4k (Veo only)"),
68651
+ resolution: external_exports.string().optional().describe("Resolution: 480p, 720p, 1080p, or 4k depending on provider"),
68420
68652
  veoModel: external_exports.string().optional().describe("Veo model: 3.0, 3.1, 3.1-fast"),
68421
68653
  runwayModel: external_exports.string().optional().describe("Runway model: gen4.5, gen4_turbo"),
68422
68654
  seedanceModel: external_exports.string().optional().describe("Seedance variant: quality or fast (fal.ai only)"),
@@ -69631,10 +69863,10 @@ async function runExport(projectPath, outputPath, options = {}) {
69631
69863
  outputPath: finalOutputPath
69632
69864
  };
69633
69865
  } catch (error) {
69634
- const errorMessage = error instanceof Error ? error.message : String(error);
69866
+ const errorMessage2 = error instanceof Error ? error.message : String(error);
69635
69867
  return {
69636
69868
  success: false,
69637
- message: `Export failed: ${errorMessage}`
69869
+ message: `Export failed: ${errorMessage2}`
69638
69870
  };
69639
69871
  }
69640
69872
  }
@@ -71654,7 +71886,7 @@ init_source();
71654
71886
  // package.json
71655
71887
  var package_default = {
71656
71888
  name: "@vibeframe/cli",
71657
- version: "0.105.1",
71889
+ version: "0.106.0",
71658
71890
  description: "VibeFrame CLI - natural language video editing from the terminal",
71659
71891
  private: false,
71660
71892
  license: "MIT",
@@ -71687,128 +71919,28 @@ var package_default = {
71687
71919
  ],
71688
71920
  exports: {
71689
71921
  ".": {
71690
- import: "./src/index.ts",
71691
- types: "./src/index.ts"
71922
+ types: "./dist/index.d.ts",
71923
+ import: "./dist/index.js"
71692
71924
  },
71693
71925
  "./engine": {
71694
- import: "./src/engine/index.ts",
71695
- types: "./src/engine/index.ts"
71696
- },
71697
- "./agent": {
71698
- import: "./src/agent/index.ts",
71699
- types: "./src/agent/index.ts"
71926
+ types: "./dist/engine/index.d.ts",
71927
+ import: "./dist/engine/index.js"
71700
71928
  },
71701
71929
  "./tools/manifest": {
71702
- import: "./src/tools/manifest/index.ts",
71703
- types: "./src/tools/manifest/index.ts"
71930
+ types: "./dist/tools/manifest/index.d.ts",
71931
+ import: "./dist/tools/manifest/index.js"
71704
71932
  },
71705
71933
  "./tools/define-tool": {
71706
- import: "./src/tools/define-tool.ts",
71707
- types: "./src/tools/define-tool.ts"
71934
+ types: "./dist/tools/define-tool.d.ts",
71935
+ import: "./dist/tools/define-tool.js"
71708
71936
  },
71709
71937
  "./tools/adapters/mcp": {
71710
- import: "./src/tools/adapters/mcp.ts",
71711
- types: "./src/tools/adapters/mcp.ts"
71938
+ types: "./dist/tools/adapters/mcp.d.ts",
71939
+ import: "./dist/tools/adapters/mcp.js"
71712
71940
  },
71713
71941
  "./tools/adapters/agent": {
71714
- import: "./src/tools/adapters/agent.ts",
71715
- types: "./src/tools/adapters/agent.ts"
71716
- },
71717
- "./commands/export": {
71718
- import: "./src/commands/export.ts",
71719
- types: "./src/commands/export.ts"
71720
- },
71721
- "./commands/ai-edit": {
71722
- import: "./src/commands/ai-edit.ts",
71723
- types: "./src/commands/ai-edit.ts"
71724
- },
71725
- "./commands/ai-analyze": {
71726
- import: "./src/commands/ai-analyze.ts",
71727
- types: "./src/commands/ai-analyze.ts"
71728
- },
71729
- "./commands/ai-review": {
71730
- import: "./src/commands/ai-review.ts",
71731
- types: "./src/commands/ai-review.ts"
71732
- },
71733
- "./commands/ai-image": {
71734
- import: "./src/commands/ai-image.ts",
71735
- types: "./src/commands/ai-image.ts"
71736
- },
71737
- "./commands/ai-script-pipeline": {
71738
- import: "./src/commands/ai-script-pipeline.ts",
71739
- types: "./src/commands/ai-script-pipeline.ts"
71740
- },
71741
- "./commands/ai-highlights": {
71742
- import: "./src/commands/ai-highlights.ts",
71743
- types: "./src/commands/ai-highlights.ts"
71744
- },
71745
- "./commands/ai-narrate": {
71746
- import: "./src/commands/ai-narrate.ts",
71747
- types: "./src/commands/ai-narrate.ts"
71748
- },
71749
- "./commands/ai-motion": {
71750
- import: "./src/commands/ai-motion.ts",
71751
- types: "./src/commands/ai-motion.ts"
71752
- },
71753
- "./commands/ai-animated-caption": {
71754
- import: "./src/commands/ai-animated-caption.ts",
71755
- types: "./src/commands/ai-animated-caption.ts"
71756
- },
71757
- "./commands/detect": {
71758
- import: "./src/commands/detect.ts",
71759
- types: "./src/commands/detect.ts"
71760
- },
71761
- "./commands/generate": {
71762
- import: "./src/commands/generate.ts",
71763
- types: "./src/commands/generate.ts"
71764
- },
71765
- "./commands/ai-video": {
71766
- import: "./src/commands/ai-video.ts",
71767
- types: "./src/commands/ai-video.ts"
71768
- },
71769
- "./commands/ai-audio": {
71770
- import: "./src/commands/ai-audio.ts",
71771
- types: "./src/commands/ai-audio.ts"
71772
- },
71773
- "./commands/edit-cmd": {
71774
- import: "./src/commands/edit-cmd.ts",
71775
- types: "./src/commands/edit-cmd.ts"
71776
- },
71777
- "./commands/scene": {
71778
- import: "./src/commands/scene.ts",
71779
- types: "./src/commands/scene.ts"
71780
- },
71781
- "./commands/_shared/scene-project": {
71782
- import: "./src/commands/_shared/scene-project.ts",
71783
- types: "./src/commands/_shared/scene-project.ts"
71784
- },
71785
- "./commands/_shared/scene-lint": {
71786
- import: "./src/commands/_shared/scene-lint.ts",
71787
- types: "./src/commands/_shared/scene-lint.ts"
71788
- },
71789
- "./commands/_shared/scene-render": {
71790
- import: "./src/commands/_shared/scene-render.ts",
71791
- types: "./src/commands/_shared/scene-render.ts"
71792
- },
71793
- "./commands/_shared/scene-html-emit": {
71794
- import: "./src/commands/_shared/scene-html-emit.ts",
71795
- types: "./src/commands/_shared/scene-html-emit.ts"
71796
- },
71797
- "./commands/_shared/scene-build": {
71798
- import: "./src/commands/_shared/scene-build.ts",
71799
- types: "./src/commands/_shared/scene-build.ts"
71800
- },
71801
- "./commands/_shared/visual-styles": {
71802
- import: "./src/commands/_shared/visual-styles.ts",
71803
- types: "./src/commands/_shared/visual-styles.ts"
71804
- },
71805
- "./commands/ai-suggest-edit": {
71806
- import: "./src/commands/ai-suggest-edit.ts",
71807
- types: "./src/commands/ai-suggest-edit.ts"
71808
- },
71809
- "./pipeline": {
71810
- import: "./src/pipeline/index.ts",
71811
- types: "./src/pipeline/index.ts"
71942
+ types: "./dist/tools/adapters/agent.d.ts",
71943
+ import: "./dist/tools/adapters/agent.js"
71812
71944
  }
71813
71945
  },
71814
71946
  scripts: {
@@ -72853,7 +72985,14 @@ init_scene_inspect();
72853
72985
  init_render_inspect();
72854
72986
  import { readFile as readFile29, writeFile as writeFile36 } from "node:fs/promises";
72855
72987
  import { resolve as resolve42 } from "node:path";
72856
- var VALID_RENDER_AI_MODELS = ["flash", "flash-2.5", "pro"];
72988
+ var VALID_RENDER_AI_MODELS = [
72989
+ "flash",
72990
+ "latest",
72991
+ "flash-3",
72992
+ "flash-2.5",
72993
+ "pro",
72994
+ "pro-3.1"
72995
+ ];
72857
72996
  var inspectCommand = new Command("inspect").description("Inspect projects, renders, and media").addHelpText(
72858
72997
  "after",
72859
72998
  `
@@ -72918,7 +73057,7 @@ inspectCommand.command("project").description(
72918
73057
  }
72919
73058
  });
72920
73059
  applyTier(inspectCommand.commands[inspectCommand.commands.length - 1], "free");
72921
- inspectCommand.command("render").description("Inspect a rendered project video with local checks and optional Gemini review").argument("[project-dir]", "VibeFrame project directory", ".").option("--cheap", "Run local checks only (default; no AI/API calls)").option("--ai", "Also run Gemini video review and merge findings into review-report.json").option("-m, --model <model>", "Gemini model for --ai: flash (default), flash-2.5, pro", "flash").option("--beat <id>", "Inspect a render for one storyboard beat").option(
73060
+ inspectCommand.command("render").description("Inspect a rendered project video with local checks and optional Gemini review").argument("[project-dir]", "VibeFrame project directory", ".").option("--cheap", "Run local checks only (default; no AI/API calls)").option("--ai", "Also run Gemini video review and merge findings into review-report.json").option("-m, --model <model>", `Gemini model for --ai: ${GEMINI_TEXT_MODEL_HELP}`, "flash").option("--beat <id>", "Inspect a render for one storyboard beat").option(
72922
73061
  "--video <path>",
72923
73062
  "Rendered video path. Defaults to build-report outputPath or latest renders/* video."
72924
73063
  ).option(
@@ -72983,7 +73122,7 @@ inspectCommand.command("render").description("Inspect a rendered project video w
72983
73122
  }
72984
73123
  });
72985
73124
  applyTier(inspectCommand.commands[inspectCommand.commands.length - 1], "low");
72986
- inspectCommand.command("media").description("Analyze any media: images, videos, or YouTube URLs using Gemini").argument("<source>", "Image/video file path, image URL, or YouTube URL").argument("<prompt>", "Analysis prompt (e.g., 'Describe this image', 'Summarize this video')").option("-k, --api-key <key>", "Google API key (or set GOOGLE_API_KEY env)").option("-m, --model <model>", "Model: flash (default), flash-2.5, pro", "flash").option("--fps <number>", "Frames per second for video (default: 1)").option("--start <seconds>", "Start offset in seconds (video only)").option("--end <seconds>", "End offset in seconds (video only)").option("--low-res", "Use low resolution mode (fewer tokens)").option("--verbose", "Show token usage").option("--fields <fields>", "Comma-separated fields to include in output (e.g., response,model)").option("--dry-run", "Preview parameters without executing").action(async (source, prompt3, options) => {
73125
+ inspectCommand.command("media").description("Analyze any media: images, videos, or YouTube URLs using Gemini").argument("<source>", "Image/video file path, image URL, or YouTube URL").argument("<prompt>", "Analysis prompt (e.g., 'Describe this image', 'Summarize this video')").option("-k, --api-key <key>", "Google API key (or set GOOGLE_API_KEY env)").option("-m, --model <model>", `Model: ${GEMINI_TEXT_MODEL_HELP}`, "flash").option("--fps <number>", "Frames per second for video (default: 1)").option("--start <seconds>", "Start offset in seconds (video only)").option("--end <seconds>", "End offset in seconds (video only)").option("--low-res", "Use low resolution mode (fewer tokens)").option("--verbose", "Show token usage").option("--fields <fields>", "Comma-separated fields to include in output (e.g., response,model)").option("--dry-run", "Preview parameters without executing").action(async (source, prompt3, options) => {
72987
73126
  const startedAt = Date.now();
72988
73127
  try {
72989
73128
  rejectControlChars(prompt3);
@@ -73086,14 +73225,17 @@ function printInspectSummary(title, status, score, issues, reportPath) {
73086
73225
  }
73087
73226
  }
73088
73227
  function parseRenderAiModel(value) {
73089
- if (VALID_RENDER_AI_MODELS.includes(value)) {
73228
+ if (isGeminiTextModelAlias(value) || value.startsWith("gemini-")) {
73090
73229
  return value;
73091
73230
  }
73092
73231
  exitWithError(
73093
- usageError(`Invalid --model: ${value}`, `Must be one of: ${VALID_RENDER_AI_MODELS.join(", ")}`)
73232
+ usageError(
73233
+ `Invalid --model: ${value}`,
73234
+ `Must be one of: ${VALID_RENDER_AI_MODELS.join(", ")}, or a full gemini-* model ID`
73235
+ )
73094
73236
  );
73095
73237
  }
73096
- inspectCommand.command("video", { hidden: true }).description("Analyze video using Gemini (summarize, Q&A, extract info)").argument("<source>", "Video file path or YouTube URL").argument("<prompt>", "Analysis prompt (e.g., 'Summarize this video')").option("-k, --api-key <key>", "Google API key (or set GOOGLE_API_KEY env)").option("-m, --model <model>", "Model: flash (default), flash-2.5, pro", "flash").option("--fps <number>", "Frames per second (default: 1, higher for action)").option("--start <seconds>", "Start offset in seconds (for clipping)").option("--end <seconds>", "End offset in seconds (for clipping)").option("--low-res", "Use low resolution mode (fewer tokens, longer videos)").option("--verbose", "Show token usage").option("--fields <fields>", "Comma-separated fields to include in output (e.g., response,model)").option("--dry-run", "Preview parameters without executing").action(async (source, prompt3, options) => {
73238
+ inspectCommand.command("video", { hidden: true }).description("Analyze video using Gemini (summarize, Q&A, extract info)").argument("<source>", "Video file path or YouTube URL").argument("<prompt>", "Analysis prompt (e.g., 'Summarize this video')").option("-k, --api-key <key>", "Google API key (or set GOOGLE_API_KEY env)").option("-m, --model <model>", `Model: ${GEMINI_TEXT_MODEL_HELP}`, "flash").option("--fps <number>", "Frames per second (default: 1, higher for action)").option("--start <seconds>", "Start offset in seconds (for clipping)").option("--end <seconds>", "End offset in seconds (for clipping)").option("--low-res", "Use low resolution mode (fewer tokens, longer videos)").option("--verbose", "Show token usage").option("--fields <fields>", "Comma-separated fields to include in output (e.g., response,model)").option("--dry-run", "Preview parameters without executing").action(async (source, prompt3, options) => {
73097
73239
  const startedAt = Date.now();
73098
73240
  try {
73099
73241
  rejectControlChars(prompt3);
@@ -79502,7 +79644,7 @@ async function runSetupWizard(fullSetup = false, scope = "user") {
79502
79644
  const userStatus = scope === "user" ? await getUserConfigStatus() : null;
79503
79645
  const displayPath2 = scope === "user" ? userStatus?.source === "legacy" ? userStatus.configPath : USER_CONFIG_PATH : getConfigPath(scope);
79504
79646
  const cfgPath = displayPath2.replace(homedir5(), "~");
79505
- const scopeNote = scope === "project" ? "applies to this project only \xB7 add .vibeframe/ to .gitignore" : "applies to every project for this user";
79647
+ const scopeNote = scope === "project" ? "applies to this project only \xB7 user config is ignored while this file exists \xB7 add .vibeframe/ to .gitignore" : "applies to every project for this user";
79506
79648
  console.log(source_default.bold.magenta("VibeFrame Setup") + source_default.bold(` \u2014 ${scope} scope`));
79507
79649
  console.log(source_default.dim(`${cfgPath} \xB7 ${scopeNote}`));
79508
79650
  if (userStatus?.source === "legacy") {
@@ -82315,7 +82457,7 @@ init_api_key();
82315
82457
  init_agent_host_detect();
82316
82458
  init_composer_resolve();
82317
82459
  init_cost_tier();
82318
- init_scene_build();
82460
+ init_scene_build_mode();
82319
82461
  init_output();
82320
82462
  import { existsSync as existsSync48 } from "node:fs";
82321
82463
  import { resolve as resolve66 } from "node:path";
@@ -82479,7 +82621,14 @@ async function runDiagnostics() {
82479
82621
  const userConfig = await getUserConfigStatus();
82480
82622
  const configExists = userConfig.configured;
82481
82623
  const cwd = process.cwd();
82482
- const activeConfig = await loadConfig({ cwd });
82624
+ let activeConfig = null;
82625
+ let configError;
82626
+ try {
82627
+ activeConfig = await loadConfig({ cwd });
82628
+ } catch (err) {
82629
+ if (!(err instanceof ConfigFileError)) throw err;
82630
+ configError = { path: err.path, message: err.message };
82631
+ }
82483
82632
  const providers = {};
82484
82633
  let readyCount = FREE_COMMANDS.length;
82485
82634
  let totalCount = FREE_COMMANDS.length;
@@ -82528,7 +82677,11 @@ async function runDiagnostics() {
82528
82677
  ok: ffmpegExists,
82529
82678
  ...ffmpegFilters ? { filters: ffmpegFilters } : {}
82530
82679
  },
82531
- config: { path: userConfig.configPath, ok: configExists },
82680
+ config: {
82681
+ path: userConfig.configPath,
82682
+ ok: (configExists || projectConfigExists) && !configError,
82683
+ ...configError ? { error: configError } : {}
82684
+ },
82532
82685
  ...Object.keys(optionalTools).length > 0 ? { optionalTools } : {}
82533
82686
  },
82534
82687
  scope: {
@@ -82554,7 +82707,8 @@ async function runDiagnostics() {
82554
82707
  composerEnvVar: composerEnv,
82555
82708
  sceneProjectInCwd,
82556
82709
  skillInstalled
82557
- }
82710
+ },
82711
+ ...configError ? { configError } : {}
82558
82712
  },
82559
82713
  providers,
82560
82714
  readyCount,
@@ -82626,10 +82780,12 @@ function printReport(results, opts = { verbose: false }) {
82626
82780
  const userActive = results.scope.activeScope === "user" && results.scope.user.configured;
82627
82781
  const projectActive = results.scope.activeScope === "project";
82628
82782
  const activeMark = source_default.cyan(" \u2190 active");
82783
+ const configErrorPath = results.scope.configError?.path;
82629
82784
  if (results.scope.user.configured) {
82630
82785
  const userPath = results.scope.user.source === "legacy" ? `${results.scope.user.configPath} ${source_default.dim(`(legacy; writes ${results.scope.user.writePath})`)}` : results.scope.user.configPath;
82786
+ const invalid = configErrorPath === results.scope.user.configPath;
82631
82787
  console.log(
82632
- ` Cfg(user) ${source_default.green("OK")} ${source_default.dim(userPath)}${userActive ? activeMark : ""}`
82788
+ ` Cfg(user) ${invalid ? source_default.red("INVALID") : source_default.green("OK")} ${source_default.dim(userPath)}${userActive ? activeMark : ""}`
82633
82789
  );
82634
82790
  } else {
82635
82791
  console.log(
@@ -82637,14 +82793,23 @@ function printReport(results, opts = { verbose: false }) {
82637
82793
  );
82638
82794
  }
82639
82795
  if (results.scope.project.configFileExists) {
82796
+ const invalid = configErrorPath === results.scope.project.configPath;
82640
82797
  console.log(
82641
- ` Cfg(proj) ${source_default.green("OK")} ${source_default.dim(results.scope.project.configPath)}${projectActive ? activeMark : ""}`
82798
+ ` Cfg(proj) ${invalid ? source_default.red("INVALID") : source_default.green("OK")} ${source_default.dim(results.scope.project.configPath)}${projectActive ? activeMark : ""}`
82642
82799
  );
82800
+ if (projectActive) {
82801
+ console.log(
82802
+ ` ${source_default.dim("project scope is isolated; user config is ignored while this file exists")}`
82803
+ );
82804
+ }
82643
82805
  } else {
82644
82806
  console.log(
82645
82807
  ` Cfg(proj) ${source_default.dim("none")} ${source_default.dim(`Run: vibe setup --scope project (cwd: ${results.scope.project.cwd})`)}`
82646
82808
  );
82647
82809
  }
82810
+ if (results.scope.configError) {
82811
+ console.log(` Cfg error ${source_default.red(results.scope.configError.message)}`);
82812
+ }
82648
82813
  if (results.scope.project.initialized) {
82649
82814
  const present = results.scope.project.files.filter((f) => f.exists).map((f) => f.path);
82650
82815
  console.log(` Init ${source_default.green("OK")} ${source_default.dim(present.join(", "))}`);
@@ -82810,7 +82975,12 @@ async function runLiveKeyTests(results) {
82810
82975
  return;
82811
82976
  }
82812
82977
  const { testKey: testKey2 } = await Promise.resolve().then(() => (init_key_live_test(), key_live_test_exports));
82813
- const activeConfig = await loadConfig({ cwd: process.cwd() });
82978
+ let activeConfig = null;
82979
+ try {
82980
+ activeConfig = await loadConfig({ cwd: process.cwd() });
82981
+ } catch (err) {
82982
+ if (!(err instanceof ConfigFileError)) throw err;
82983
+ }
82814
82984
  for (const [name, info] of configured) {
82815
82985
  const value = process.env[info.envVar] || PROVIDER_ENV_ALIASES[info.envVar]?.map((alias) => process.env[alias]).find(Boolean) || activeConfig?.providers[name];
82816
82986
  if (!value) continue;
@@ -83506,12 +83676,12 @@ var ToolRegistry = class {
83506
83676
  try {
83507
83677
  return await tool.handler(args, context);
83508
83678
  } catch (error) {
83509
- const errorMessage = error instanceof Error ? error.message : String(error);
83679
+ const errorMessage2 = error instanceof Error ? error.message : String(error);
83510
83680
  return {
83511
83681
  toolCallId: "",
83512
83682
  success: false,
83513
83683
  output: "",
83514
- error: errorMessage
83684
+ error: errorMessage2
83515
83685
  };
83516
83686
  }
83517
83687
  }