@vibeframe/cli 0.55.0 → 0.55.1

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 (497) hide show
  1. package/dist/index.js +63452 -233
  2. package/package.json +11 -6
  3. package/dist/agent/adapters/claude.d.ts +0 -15
  4. package/dist/agent/adapters/claude.d.ts.map +0 -1
  5. package/dist/agent/adapters/claude.js +0 -119
  6. package/dist/agent/adapters/claude.js.map +0 -1
  7. package/dist/agent/adapters/gemini.d.ts +0 -15
  8. package/dist/agent/adapters/gemini.d.ts.map +0 -1
  9. package/dist/agent/adapters/gemini.js +0 -132
  10. package/dist/agent/adapters/gemini.js.map +0 -1
  11. package/dist/agent/adapters/index.d.ts +0 -28
  12. package/dist/agent/adapters/index.d.ts.map +0 -1
  13. package/dist/agent/adapters/index.js +0 -43
  14. package/dist/agent/adapters/index.js.map +0 -1
  15. package/dist/agent/adapters/ollama.d.ts +0 -20
  16. package/dist/agent/adapters/ollama.d.ts.map +0 -1
  17. package/dist/agent/adapters/ollama.js +0 -186
  18. package/dist/agent/adapters/ollama.js.map +0 -1
  19. package/dist/agent/adapters/openai.d.ts +0 -15
  20. package/dist/agent/adapters/openai.d.ts.map +0 -1
  21. package/dist/agent/adapters/openai.js +0 -92
  22. package/dist/agent/adapters/openai.js.map +0 -1
  23. package/dist/agent/adapters/openrouter.d.ts +0 -16
  24. package/dist/agent/adapters/openrouter.d.ts.map +0 -1
  25. package/dist/agent/adapters/openrouter.js +0 -100
  26. package/dist/agent/adapters/openrouter.js.map +0 -1
  27. package/dist/agent/adapters/openrouter.test.d.ts +0 -5
  28. package/dist/agent/adapters/openrouter.test.d.ts.map +0 -1
  29. package/dist/agent/adapters/openrouter.test.js +0 -73
  30. package/dist/agent/adapters/openrouter.test.js.map +0 -1
  31. package/dist/agent/adapters/xai.d.ts +0 -15
  32. package/dist/agent/adapters/xai.d.ts.map +0 -1
  33. package/dist/agent/adapters/xai.js +0 -95
  34. package/dist/agent/adapters/xai.js.map +0 -1
  35. package/dist/agent/index.d.ts +0 -69
  36. package/dist/agent/index.d.ts.map +0 -1
  37. package/dist/agent/index.js +0 -180
  38. package/dist/agent/index.js.map +0 -1
  39. package/dist/agent/memory/index.d.ts +0 -70
  40. package/dist/agent/memory/index.d.ts.map +0 -1
  41. package/dist/agent/memory/index.js +0 -132
  42. package/dist/agent/memory/index.js.map +0 -1
  43. package/dist/agent/prompts/system.d.ts +0 -6
  44. package/dist/agent/prompts/system.d.ts.map +0 -1
  45. package/dist/agent/prompts/system.js +0 -103
  46. package/dist/agent/prompts/system.js.map +0 -1
  47. package/dist/agent/tools/ai-editing.d.ts +0 -15
  48. package/dist/agent/tools/ai-editing.d.ts.map +0 -1
  49. package/dist/agent/tools/ai-editing.js +0 -763
  50. package/dist/agent/tools/ai-editing.js.map +0 -1
  51. package/dist/agent/tools/ai-generation.d.ts +0 -13
  52. package/dist/agent/tools/ai-generation.d.ts.map +0 -1
  53. package/dist/agent/tools/ai-generation.js +0 -973
  54. package/dist/agent/tools/ai-generation.js.map +0 -1
  55. package/dist/agent/tools/ai-pipeline.d.ts +0 -14
  56. package/dist/agent/tools/ai-pipeline.d.ts.map +0 -1
  57. package/dist/agent/tools/ai-pipeline.js +0 -961
  58. package/dist/agent/tools/ai-pipeline.js.map +0 -1
  59. package/dist/agent/tools/ai.d.ts +0 -13
  60. package/dist/agent/tools/ai.d.ts.map +0 -1
  61. package/dist/agent/tools/ai.js +0 -19
  62. package/dist/agent/tools/ai.js.map +0 -1
  63. package/dist/agent/tools/batch.d.ts +0 -6
  64. package/dist/agent/tools/batch.d.ts.map +0 -1
  65. package/dist/agent/tools/batch.js +0 -383
  66. package/dist/agent/tools/batch.js.map +0 -1
  67. package/dist/agent/tools/e2e.test.d.ts +0 -26
  68. package/dist/agent/tools/e2e.test.d.ts.map +0 -1
  69. package/dist/agent/tools/e2e.test.js +0 -397
  70. package/dist/agent/tools/e2e.test.js.map +0 -1
  71. package/dist/agent/tools/export.d.ts +0 -6
  72. package/dist/agent/tools/export.d.ts.map +0 -1
  73. package/dist/agent/tools/export.js +0 -171
  74. package/dist/agent/tools/export.js.map +0 -1
  75. package/dist/agent/tools/filesystem.d.ts +0 -6
  76. package/dist/agent/tools/filesystem.d.ts.map +0 -1
  77. package/dist/agent/tools/filesystem.js +0 -212
  78. package/dist/agent/tools/filesystem.js.map +0 -1
  79. package/dist/agent/tools/index.d.ts +0 -66
  80. package/dist/agent/tools/index.d.ts.map +0 -1
  81. package/dist/agent/tools/index.js +0 -123
  82. package/dist/agent/tools/index.js.map +0 -1
  83. package/dist/agent/tools/integration.test.d.ts +0 -11
  84. package/dist/agent/tools/integration.test.d.ts.map +0 -1
  85. package/dist/agent/tools/integration.test.js +0 -659
  86. package/dist/agent/tools/integration.test.js.map +0 -1
  87. package/dist/agent/tools/media.d.ts +0 -6
  88. package/dist/agent/tools/media.d.ts.map +0 -1
  89. package/dist/agent/tools/media.js +0 -616
  90. package/dist/agent/tools/media.js.map +0 -1
  91. package/dist/agent/tools/project.d.ts +0 -6
  92. package/dist/agent/tools/project.d.ts.map +0 -1
  93. package/dist/agent/tools/project.js +0 -284
  94. package/dist/agent/tools/project.js.map +0 -1
  95. package/dist/agent/tools/scene.d.ts +0 -17
  96. package/dist/agent/tools/scene.d.ts.map +0 -1
  97. package/dist/agent/tools/scene.js +0 -263
  98. package/dist/agent/tools/scene.js.map +0 -1
  99. package/dist/agent/tools/scene.test.d.ts +0 -2
  100. package/dist/agent/tools/scene.test.d.ts.map +0 -1
  101. package/dist/agent/tools/scene.test.js +0 -139
  102. package/dist/agent/tools/scene.test.js.map +0 -1
  103. package/dist/agent/tools/timeline.d.ts +0 -6
  104. package/dist/agent/tools/timeline.d.ts.map +0 -1
  105. package/dist/agent/tools/timeline.js +0 -875
  106. package/dist/agent/tools/timeline.js.map +0 -1
  107. package/dist/agent/types.d.ts +0 -59
  108. package/dist/agent/types.d.ts.map +0 -1
  109. package/dist/agent/types.js +0 -5
  110. package/dist/agent/types.js.map +0 -1
  111. package/dist/commands/_shared/scene-audio-mux.d.ts +0 -75
  112. package/dist/commands/_shared/scene-audio-mux.d.ts.map +0 -1
  113. package/dist/commands/_shared/scene-audio-mux.js +0 -159
  114. package/dist/commands/_shared/scene-audio-mux.js.map +0 -1
  115. package/dist/commands/_shared/scene-audio-mux.test.d.ts +0 -7
  116. package/dist/commands/_shared/scene-audio-mux.test.d.ts.map +0 -1
  117. package/dist/commands/_shared/scene-audio-mux.test.js +0 -94
  118. package/dist/commands/_shared/scene-audio-mux.test.js.map +0 -1
  119. package/dist/commands/_shared/scene-audio-scan.d.ts +0 -94
  120. package/dist/commands/_shared/scene-audio-scan.d.ts.map +0 -1
  121. package/dist/commands/_shared/scene-audio-scan.js +0 -144
  122. package/dist/commands/_shared/scene-audio-scan.js.map +0 -1
  123. package/dist/commands/_shared/scene-audio-scan.test.d.ts +0 -6
  124. package/dist/commands/_shared/scene-audio-scan.test.d.ts.map +0 -1
  125. package/dist/commands/_shared/scene-audio-scan.test.js +0 -190
  126. package/dist/commands/_shared/scene-audio-scan.test.js.map +0 -1
  127. package/dist/commands/_shared/scene-html-emit.d.ts +0 -120
  128. package/dist/commands/_shared/scene-html-emit.d.ts.map +0 -1
  129. package/dist/commands/_shared/scene-html-emit.js +0 -422
  130. package/dist/commands/_shared/scene-html-emit.js.map +0 -1
  131. package/dist/commands/_shared/scene-html-emit.test.d.ts +0 -2
  132. package/dist/commands/_shared/scene-html-emit.test.d.ts.map +0 -1
  133. package/dist/commands/_shared/scene-html-emit.test.js +0 -396
  134. package/dist/commands/_shared/scene-html-emit.test.js.map +0 -1
  135. package/dist/commands/_shared/scene-lint.d.ts +0 -110
  136. package/dist/commands/_shared/scene-lint.d.ts.map +0 -1
  137. package/dist/commands/_shared/scene-lint.js +0 -207
  138. package/dist/commands/_shared/scene-lint.js.map +0 -1
  139. package/dist/commands/_shared/scene-lint.test.d.ts +0 -2
  140. package/dist/commands/_shared/scene-lint.test.d.ts.map +0 -1
  141. package/dist/commands/_shared/scene-lint.test.js +0 -208
  142. package/dist/commands/_shared/scene-lint.test.js.map +0 -1
  143. package/dist/commands/_shared/scene-project.d.ts +0 -101
  144. package/dist/commands/_shared/scene-project.d.ts.map +0 -1
  145. package/dist/commands/_shared/scene-project.js +0 -281
  146. package/dist/commands/_shared/scene-project.js.map +0 -1
  147. package/dist/commands/_shared/scene-project.test.d.ts +0 -2
  148. package/dist/commands/_shared/scene-project.test.d.ts.map +0 -1
  149. package/dist/commands/_shared/scene-project.test.js +0 -203
  150. package/dist/commands/_shared/scene-project.test.js.map +0 -1
  151. package/dist/commands/_shared/scene-render.d.ts +0 -85
  152. package/dist/commands/_shared/scene-render.d.ts.map +0 -1
  153. package/dist/commands/_shared/scene-render.js +0 -178
  154. package/dist/commands/_shared/scene-render.js.map +0 -1
  155. package/dist/commands/_shared/scene-render.test.d.ts +0 -2
  156. package/dist/commands/_shared/scene-render.test.d.ts.map +0 -1
  157. package/dist/commands/_shared/scene-render.test.js +0 -145
  158. package/dist/commands/_shared/scene-render.test.js.map +0 -1
  159. package/dist/commands/_shared/segments-to-scenes.d.ts +0 -85
  160. package/dist/commands/_shared/segments-to-scenes.d.ts.map +0 -1
  161. package/dist/commands/_shared/segments-to-scenes.js +0 -202
  162. package/dist/commands/_shared/segments-to-scenes.js.map +0 -1
  163. package/dist/commands/_shared/segments-to-scenes.test.d.ts +0 -2
  164. package/dist/commands/_shared/segments-to-scenes.test.d.ts.map +0 -1
  165. package/dist/commands/_shared/segments-to-scenes.test.js +0 -219
  166. package/dist/commands/_shared/segments-to-scenes.test.js.map +0 -1
  167. package/dist/commands/_shared/tts-resolve.d.ts +0 -75
  168. package/dist/commands/_shared/tts-resolve.d.ts.map +0 -1
  169. package/dist/commands/_shared/tts-resolve.js +0 -89
  170. package/dist/commands/_shared/tts-resolve.js.map +0 -1
  171. package/dist/commands/_shared/tts-resolve.test.d.ts +0 -6
  172. package/dist/commands/_shared/tts-resolve.test.d.ts.map +0 -1
  173. package/dist/commands/_shared/tts-resolve.test.js +0 -147
  174. package/dist/commands/_shared/tts-resolve.test.js.map +0 -1
  175. package/dist/commands/agent.d.ts +0 -21
  176. package/dist/commands/agent.d.ts.map +0 -1
  177. package/dist/commands/agent.js +0 -285
  178. package/dist/commands/agent.js.map +0 -1
  179. package/dist/commands/ai-analyze.d.ts +0 -106
  180. package/dist/commands/ai-analyze.d.ts.map +0 -1
  181. package/dist/commands/ai-analyze.js +0 -320
  182. package/dist/commands/ai-analyze.js.map +0 -1
  183. package/dist/commands/ai-animated-caption.d.ts +0 -64
  184. package/dist/commands/ai-animated-caption.d.ts.map +0 -1
  185. package/dist/commands/ai-animated-caption.js +0 -272
  186. package/dist/commands/ai-animated-caption.js.map +0 -1
  187. package/dist/commands/ai-audio.d.ts +0 -98
  188. package/dist/commands/ai-audio.d.ts.map +0 -1
  189. package/dist/commands/ai-audio.js +0 -1059
  190. package/dist/commands/ai-audio.js.map +0 -1
  191. package/dist/commands/ai-broll.d.ts +0 -15
  192. package/dist/commands/ai-broll.d.ts.map +0 -1
  193. package/dist/commands/ai-broll.js +0 -421
  194. package/dist/commands/ai-broll.js.map +0 -1
  195. package/dist/commands/ai-edit-cli.d.ts +0 -14
  196. package/dist/commands/ai-edit-cli.d.ts.map +0 -1
  197. package/dist/commands/ai-edit-cli.js +0 -585
  198. package/dist/commands/ai-edit-cli.js.map +0 -1
  199. package/dist/commands/ai-edit.d.ts +0 -398
  200. package/dist/commands/ai-edit.d.ts.map +0 -1
  201. package/dist/commands/ai-edit.js +0 -1060
  202. package/dist/commands/ai-edit.js.map +0 -1
  203. package/dist/commands/ai-fill-gaps.d.ts +0 -14
  204. package/dist/commands/ai-fill-gaps.d.ts.map +0 -1
  205. package/dist/commands/ai-fill-gaps.js +0 -447
  206. package/dist/commands/ai-fill-gaps.js.map +0 -1
  207. package/dist/commands/ai-helpers.d.ts +0 -20
  208. package/dist/commands/ai-helpers.d.ts.map +0 -1
  209. package/dist/commands/ai-helpers.js +0 -59
  210. package/dist/commands/ai-helpers.js.map +0 -1
  211. package/dist/commands/ai-highlights.d.ts +0 -127
  212. package/dist/commands/ai-highlights.d.ts.map +0 -1
  213. package/dist/commands/ai-highlights.js +0 -1053
  214. package/dist/commands/ai-highlights.js.map +0 -1
  215. package/dist/commands/ai-image.d.ts +0 -76
  216. package/dist/commands/ai-image.d.ts.map +0 -1
  217. package/dist/commands/ai-image.js +0 -858
  218. package/dist/commands/ai-image.js.map +0 -1
  219. package/dist/commands/ai-motion.d.ts +0 -50
  220. package/dist/commands/ai-motion.d.ts.map +0 -1
  221. package/dist/commands/ai-motion.js +0 -297
  222. package/dist/commands/ai-motion.js.map +0 -1
  223. package/dist/commands/ai-narrate.d.ts +0 -66
  224. package/dist/commands/ai-narrate.d.ts.map +0 -1
  225. package/dist/commands/ai-narrate.js +0 -332
  226. package/dist/commands/ai-narrate.js.map +0 -1
  227. package/dist/commands/ai-review.d.ts +0 -57
  228. package/dist/commands/ai-review.d.ts.map +0 -1
  229. package/dist/commands/ai-review.js +0 -270
  230. package/dist/commands/ai-review.js.map +0 -1
  231. package/dist/commands/ai-script-pipeline-cli.d.ts +0 -9
  232. package/dist/commands/ai-script-pipeline-cli.d.ts.map +0 -1
  233. package/dist/commands/ai-script-pipeline-cli.js +0 -502
  234. package/dist/commands/ai-script-pipeline-cli.js.map +0 -1
  235. package/dist/commands/ai-script-pipeline.d.ts +0 -305
  236. package/dist/commands/ai-script-pipeline.d.ts.map +0 -1
  237. package/dist/commands/ai-script-pipeline.js +0 -1546
  238. package/dist/commands/ai-script-pipeline.js.map +0 -1
  239. package/dist/commands/ai-suggest-edit.d.ts +0 -14
  240. package/dist/commands/ai-suggest-edit.d.ts.map +0 -1
  241. package/dist/commands/ai-suggest-edit.js +0 -215
  242. package/dist/commands/ai-suggest-edit.js.map +0 -1
  243. package/dist/commands/ai-video-fx.d.ts +0 -14
  244. package/dist/commands/ai-video-fx.d.ts.map +0 -1
  245. package/dist/commands/ai-video-fx.js +0 -396
  246. package/dist/commands/ai-video-fx.js.map +0 -1
  247. package/dist/commands/ai-video.d.ts +0 -91
  248. package/dist/commands/ai-video.d.ts.map +0 -1
  249. package/dist/commands/ai-video.js +0 -1055
  250. package/dist/commands/ai-video.js.map +0 -1
  251. package/dist/commands/ai-viral.d.ts +0 -15
  252. package/dist/commands/ai-viral.d.ts.map +0 -1
  253. package/dist/commands/ai-viral.js +0 -507
  254. package/dist/commands/ai-viral.js.map +0 -1
  255. package/dist/commands/ai-visual-fx.d.ts +0 -14
  256. package/dist/commands/ai-visual-fx.d.ts.map +0 -1
  257. package/dist/commands/ai-visual-fx.js +0 -521
  258. package/dist/commands/ai-visual-fx.js.map +0 -1
  259. package/dist/commands/ai.d.ts +0 -38
  260. package/dist/commands/ai.d.ts.map +0 -1
  261. package/dist/commands/ai.js +0 -225
  262. package/dist/commands/ai.js.map +0 -1
  263. package/dist/commands/ai.test.d.ts +0 -2
  264. package/dist/commands/ai.test.d.ts.map +0 -1
  265. package/dist/commands/ai.test.js +0 -557
  266. package/dist/commands/ai.test.js.map +0 -1
  267. package/dist/commands/analyze.d.ts +0 -16
  268. package/dist/commands/analyze.d.ts.map +0 -1
  269. package/dist/commands/analyze.js +0 -247
  270. package/dist/commands/analyze.js.map +0 -1
  271. package/dist/commands/audio.d.ts +0 -18
  272. package/dist/commands/audio.d.ts.map +0 -1
  273. package/dist/commands/audio.js +0 -539
  274. package/dist/commands/audio.js.map +0 -1
  275. package/dist/commands/batch.d.ts +0 -3
  276. package/dist/commands/batch.d.ts.map +0 -1
  277. package/dist/commands/batch.js +0 -419
  278. package/dist/commands/batch.js.map +0 -1
  279. package/dist/commands/batch.test.d.ts +0 -2
  280. package/dist/commands/batch.test.d.ts.map +0 -1
  281. package/dist/commands/batch.test.js +0 -203
  282. package/dist/commands/batch.test.js.map +0 -1
  283. package/dist/commands/context.d.ts +0 -7
  284. package/dist/commands/context.d.ts.map +0 -1
  285. package/dist/commands/context.js +0 -66
  286. package/dist/commands/context.js.map +0 -1
  287. package/dist/commands/demo.d.ts +0 -7
  288. package/dist/commands/demo.d.ts.map +0 -1
  289. package/dist/commands/demo.js +0 -192
  290. package/dist/commands/demo.js.map +0 -1
  291. package/dist/commands/detect.d.ts +0 -56
  292. package/dist/commands/detect.d.ts.map +0 -1
  293. package/dist/commands/detect.js +0 -464
  294. package/dist/commands/detect.js.map +0 -1
  295. package/dist/commands/doctor.d.ts +0 -6
  296. package/dist/commands/doctor.d.ts.map +0 -1
  297. package/dist/commands/doctor.js +0 -322
  298. package/dist/commands/doctor.js.map +0 -1
  299. package/dist/commands/edit-cmd.d.ts +0 -112
  300. package/dist/commands/edit-cmd.d.ts.map +0 -1
  301. package/dist/commands/edit-cmd.js +0 -1041
  302. package/dist/commands/edit-cmd.js.map +0 -1
  303. package/dist/commands/export.d.ts +0 -61
  304. package/dist/commands/export.d.ts.map +0 -1
  305. package/dist/commands/export.js +0 -980
  306. package/dist/commands/export.js.map +0 -1
  307. package/dist/commands/export.test.d.ts +0 -2
  308. package/dist/commands/export.test.d.ts.map +0 -1
  309. package/dist/commands/export.test.js +0 -107
  310. package/dist/commands/export.test.js.map +0 -1
  311. package/dist/commands/generate.d.ts +0 -84
  312. package/dist/commands/generate.d.ts.map +0 -1
  313. package/dist/commands/generate.js +0 -2030
  314. package/dist/commands/generate.js.map +0 -1
  315. package/dist/commands/media.d.ts +0 -3
  316. package/dist/commands/media.d.ts.map +0 -1
  317. package/dist/commands/media.js +0 -163
  318. package/dist/commands/media.js.map +0 -1
  319. package/dist/commands/output.d.ts +0 -51
  320. package/dist/commands/output.d.ts.map +0 -1
  321. package/dist/commands/output.js +0 -219
  322. package/dist/commands/output.js.map +0 -1
  323. package/dist/commands/output.test.d.ts +0 -2
  324. package/dist/commands/output.test.d.ts.map +0 -1
  325. package/dist/commands/output.test.js +0 -151
  326. package/dist/commands/output.test.js.map +0 -1
  327. package/dist/commands/pipeline.d.ts +0 -19
  328. package/dist/commands/pipeline.d.ts.map +0 -1
  329. package/dist/commands/pipeline.js +0 -345
  330. package/dist/commands/pipeline.js.map +0 -1
  331. package/dist/commands/project.d.ts +0 -3
  332. package/dist/commands/project.d.ts.map +0 -1
  333. package/dist/commands/project.js +0 -181
  334. package/dist/commands/project.js.map +0 -1
  335. package/dist/commands/project.test.d.ts +0 -2
  336. package/dist/commands/project.test.d.ts.map +0 -1
  337. package/dist/commands/project.test.js +0 -105
  338. package/dist/commands/project.test.js.map +0 -1
  339. package/dist/commands/run.d.ts +0 -15
  340. package/dist/commands/run.d.ts.map +0 -1
  341. package/dist/commands/run.js +0 -204
  342. package/dist/commands/run.js.map +0 -1
  343. package/dist/commands/sanitize.d.ts +0 -21
  344. package/dist/commands/sanitize.d.ts.map +0 -1
  345. package/dist/commands/sanitize.js +0 -56
  346. package/dist/commands/sanitize.js.map +0 -1
  347. package/dist/commands/scene.d.ts +0 -86
  348. package/dist/commands/scene.d.ts.map +0 -1
  349. package/dist/commands/scene.js +0 -728
  350. package/dist/commands/scene.js.map +0 -1
  351. package/dist/commands/scene.test.d.ts +0 -2
  352. package/dist/commands/scene.test.d.ts.map +0 -1
  353. package/dist/commands/scene.test.js +0 -219
  354. package/dist/commands/scene.test.js.map +0 -1
  355. package/dist/commands/schema.d.ts +0 -13
  356. package/dist/commands/schema.d.ts.map +0 -1
  357. package/dist/commands/schema.js +0 -218
  358. package/dist/commands/schema.js.map +0 -1
  359. package/dist/commands/setup.d.ts +0 -6
  360. package/dist/commands/setup.d.ts.map +0 -1
  361. package/dist/commands/setup.js +0 -461
  362. package/dist/commands/setup.js.map +0 -1
  363. package/dist/commands/timeline.d.ts +0 -3
  364. package/dist/commands/timeline.d.ts.map +0 -1
  365. package/dist/commands/timeline.js +0 -609
  366. package/dist/commands/timeline.js.map +0 -1
  367. package/dist/commands/timeline.test.d.ts +0 -2
  368. package/dist/commands/timeline.test.d.ts.map +0 -1
  369. package/dist/commands/timeline.test.js +0 -334
  370. package/dist/commands/timeline.test.js.map +0 -1
  371. package/dist/commands/validate.d.ts +0 -34
  372. package/dist/commands/validate.d.ts.map +0 -1
  373. package/dist/commands/validate.js +0 -70
  374. package/dist/commands/validate.js.map +0 -1
  375. package/dist/config/config.test.d.ts +0 -2
  376. package/dist/config/config.test.d.ts.map +0 -1
  377. package/dist/config/config.test.js +0 -164
  378. package/dist/config/config.test.js.map +0 -1
  379. package/dist/config/index.d.ts +0 -35
  380. package/dist/config/index.d.ts.map +0 -1
  381. package/dist/config/index.js +0 -101
  382. package/dist/config/index.js.map +0 -1
  383. package/dist/config/schema.d.ts +0 -52
  384. package/dist/config/schema.d.ts.map +0 -1
  385. package/dist/config/schema.js +0 -44
  386. package/dist/config/schema.js.map +0 -1
  387. package/dist/engine/index.d.ts +0 -3
  388. package/dist/engine/index.d.ts.map +0 -1
  389. package/dist/engine/index.js +0 -2
  390. package/dist/engine/index.js.map +0 -1
  391. package/dist/engine/project.d.ts +0 -84
  392. package/dist/engine/project.d.ts.map +0 -1
  393. package/dist/engine/project.js +0 -355
  394. package/dist/engine/project.js.map +0 -1
  395. package/dist/engine/project.test.d.ts +0 -2
  396. package/dist/engine/project.test.d.ts.map +0 -1
  397. package/dist/engine/project.test.js +0 -599
  398. package/dist/engine/project.test.js.map +0 -1
  399. package/dist/index.d.ts +0 -7
  400. package/dist/index.d.ts.map +0 -1
  401. package/dist/index.js.map +0 -1
  402. package/dist/pipeline/executor.d.ts +0 -19
  403. package/dist/pipeline/executor.d.ts.map +0 -1
  404. package/dist/pipeline/executor.js +0 -397
  405. package/dist/pipeline/executor.js.map +0 -1
  406. package/dist/pipeline/index.d.ts +0 -4
  407. package/dist/pipeline/index.d.ts.map +0 -1
  408. package/dist/pipeline/index.js +0 -2
  409. package/dist/pipeline/index.js.map +0 -1
  410. package/dist/pipeline/renderers/__tests__/html-template.test.d.ts +0 -2
  411. package/dist/pipeline/renderers/__tests__/html-template.test.d.ts.map +0 -1
  412. package/dist/pipeline/renderers/__tests__/html-template.test.js +0 -170
  413. package/dist/pipeline/renderers/__tests__/html-template.test.js.map +0 -1
  414. package/dist/pipeline/renderers/__tests__/integration.test.d.ts +0 -2
  415. package/dist/pipeline/renderers/__tests__/integration.test.d.ts.map +0 -1
  416. package/dist/pipeline/renderers/__tests__/integration.test.js +0 -175
  417. package/dist/pipeline/renderers/__tests__/integration.test.js.map +0 -1
  418. package/dist/pipeline/renderers/chrome.d.ts +0 -26
  419. package/dist/pipeline/renderers/chrome.d.ts.map +0 -1
  420. package/dist/pipeline/renderers/chrome.js +0 -48
  421. package/dist/pipeline/renderers/chrome.js.map +0 -1
  422. package/dist/pipeline/renderers/html-clips.d.ts +0 -20
  423. package/dist/pipeline/renderers/html-clips.d.ts.map +0 -1
  424. package/dist/pipeline/renderers/html-clips.js +0 -50
  425. package/dist/pipeline/renderers/html-clips.js.map +0 -1
  426. package/dist/pipeline/renderers/html-runtime.d.ts +0 -7
  427. package/dist/pipeline/renderers/html-runtime.d.ts.map +0 -1
  428. package/dist/pipeline/renderers/html-runtime.js +0 -80
  429. package/dist/pipeline/renderers/html-runtime.js.map +0 -1
  430. package/dist/pipeline/renderers/html-template.d.ts +0 -3
  431. package/dist/pipeline/renderers/html-template.d.ts.map +0 -1
  432. package/dist/pipeline/renderers/html-template.js +0 -36
  433. package/dist/pipeline/renderers/html-template.js.map +0 -1
  434. package/dist/pipeline/renderers/hyperframes.d.ts +0 -8
  435. package/dist/pipeline/renderers/hyperframes.d.ts.map +0 -1
  436. package/dist/pipeline/renderers/hyperframes.js +0 -63
  437. package/dist/pipeline/renderers/hyperframes.js.map +0 -1
  438. package/dist/pipeline/renderers/project-builder.d.ts +0 -8
  439. package/dist/pipeline/renderers/project-builder.d.ts.map +0 -1
  440. package/dist/pipeline/renderers/project-builder.js +0 -65
  441. package/dist/pipeline/renderers/project-builder.js.map +0 -1
  442. package/dist/pipeline/renderers/types.d.ts +0 -41
  443. package/dist/pipeline/renderers/types.d.ts.map +0 -1
  444. package/dist/pipeline/renderers/types.js +0 -11
  445. package/dist/pipeline/renderers/types.js.map +0 -1
  446. package/dist/pipeline/resolver.d.ts +0 -20
  447. package/dist/pipeline/resolver.d.ts.map +0 -1
  448. package/dist/pipeline/resolver.js +0 -74
  449. package/dist/pipeline/resolver.js.map +0 -1
  450. package/dist/pipeline/types.d.ts +0 -82
  451. package/dist/pipeline/types.d.ts.map +0 -1
  452. package/dist/pipeline/types.js +0 -8
  453. package/dist/pipeline/types.js.map +0 -1
  454. package/dist/utils/api-key.d.ts +0 -33
  455. package/dist/utils/api-key.d.ts.map +0 -1
  456. package/dist/utils/api-key.js +0 -228
  457. package/dist/utils/api-key.js.map +0 -1
  458. package/dist/utils/api-key.test.d.ts +0 -2
  459. package/dist/utils/api-key.test.d.ts.map +0 -1
  460. package/dist/utils/api-key.test.js +0 -35
  461. package/dist/utils/api-key.test.js.map +0 -1
  462. package/dist/utils/audio.d.ts +0 -23
  463. package/dist/utils/audio.d.ts.map +0 -1
  464. package/dist/utils/audio.js +0 -79
  465. package/dist/utils/audio.js.map +0 -1
  466. package/dist/utils/exec-safe.d.ts +0 -22
  467. package/dist/utils/exec-safe.d.ts.map +0 -1
  468. package/dist/utils/exec-safe.js +0 -62
  469. package/dist/utils/exec-safe.js.map +0 -1
  470. package/dist/utils/first-run.d.ts +0 -17
  471. package/dist/utils/first-run.d.ts.map +0 -1
  472. package/dist/utils/first-run.js +0 -73
  473. package/dist/utils/first-run.js.map +0 -1
  474. package/dist/utils/input-validation.d.ts +0 -27
  475. package/dist/utils/input-validation.d.ts.map +0 -1
  476. package/dist/utils/input-validation.js +0 -67
  477. package/dist/utils/input-validation.js.map +0 -1
  478. package/dist/utils/provider-resolver.d.ts +0 -19
  479. package/dist/utils/provider-resolver.d.ts.map +0 -1
  480. package/dist/utils/provider-resolver.js +0 -75
  481. package/dist/utils/provider-resolver.js.map +0 -1
  482. package/dist/utils/remotion.d.ts +0 -231
  483. package/dist/utils/remotion.d.ts.map +0 -1
  484. package/dist/utils/remotion.js +0 -879
  485. package/dist/utils/remotion.js.map +0 -1
  486. package/dist/utils/subtitle.d.ts +0 -65
  487. package/dist/utils/subtitle.d.ts.map +0 -1
  488. package/dist/utils/subtitle.js +0 -135
  489. package/dist/utils/subtitle.js.map +0 -1
  490. package/dist/utils/subtitle.test.d.ts +0 -2
  491. package/dist/utils/subtitle.test.d.ts.map +0 -1
  492. package/dist/utils/subtitle.test.js +0 -175
  493. package/dist/utils/subtitle.test.js.map +0 -1
  494. package/dist/utils/tty.d.ts +0 -45
  495. package/dist/utils/tty.d.ts.map +0 -1
  496. package/dist/utils/tty.js +0 -231
  497. package/dist/utils/tty.js.map +0 -1
@@ -1,858 +0,0 @@
1
- /**
2
- * @module ai-image
3
- * @description Image generation and editing commands for the VibeFrame CLI.
4
- *
5
- * ## Commands: vibe ai image, vibe ai thumbnail, vibe ai background,
6
- * vibe ai gemini, vibe ai gemini-edit
7
- * ## Dependencies: OpenAI, Gemini, FFmpeg
8
- *
9
- * Extracted from ai.ts as part of modularisation.
10
- * ai.ts calls registerImageCommands(aiCommand).
11
- * @see MODELS.md for AI model configuration
12
- */
13
- import { resolve, dirname, basename, extname } from 'node:path';
14
- import { fileURLToPath } from 'node:url';
15
- import { readFile, writeFile, mkdir } from 'node:fs/promises';
16
- import { existsSync } from 'node:fs';
17
- import chalk from 'chalk';
18
- import ora from 'ora';
19
- import { GeminiProvider, OpenAIImageProvider, } from '@vibeframe/ai-providers';
20
- import { getApiKey } from '../utils/api-key.js';
21
- import { execSafe, commandExists } from '../utils/exec-safe.js';
22
- import { exitWithError, authError, notFoundError, apiError, usageError, generalError, outputResult } from './output.js';
23
- import { validateOutputPath } from "./validate.js";
24
- function _registerImageCommands(aiCommand) {
25
- aiCommand
26
- .command("image")
27
- .description("Generate image using AI (Gemini or DALL-E)")
28
- .argument("<prompt>", "Image description prompt")
29
- .option("-p, --provider <provider>", "Provider: gemini, openai, runway (dalle is deprecated)", "gemini")
30
- .option("-k, --api-key <key>", "API key (or set env: OPENAI_API_KEY, GOOGLE_API_KEY)")
31
- .option("-o, --output <path>", "Output file path (downloads image)")
32
- .option("-s, --size <size>", "Image size (openai: 1024x1024, 1536x1024, 1024x1536)", "1024x1024")
33
- .option("-r, --ratio <ratio>", "Aspect ratio (gemini: 1:1, 1:4, 1:8, 4:1, 8:1, 16:9, 9:16, 3:4, 4:3, etc.)", "1:1")
34
- .option("-q, --quality <quality>", "Quality: standard, hd (openai only)", "standard")
35
- .option("--style <style>", "Style: vivid, natural (openai only)", "vivid")
36
- .option("-n, --count <n>", "Number of images to generate", "1")
37
- .option("-m, --model <model>", "Model. Gemini: flash, 3.1-flash, latest, pro. OpenAI: 1.5 (default), 2 (gpt-image-2)")
38
- .option("--dry-run", "Preview parameters without executing")
39
- .action(async (prompt, options) => {
40
- try {
41
- if (options.output) {
42
- validateOutputPath(options.output);
43
- }
44
- const provider = options.provider.toLowerCase();
45
- const validProviders = ["openai", "dalle", "gemini", "runway"];
46
- if (!validProviders.includes(provider)) {
47
- exitWithError(usageError(`Invalid provider: ${provider}`, "Available providers: openai, gemini, runway"));
48
- }
49
- if (options.dryRun) {
50
- outputResult({ dryRun: true, command: "ai image", params: { prompt, provider, output: options.output, size: options.size, ratio: options.ratio, quality: options.quality, style: options.style, count: options.count, model: options.model } });
51
- return;
52
- }
53
- // Show deprecation warning for "dalle"
54
- if (provider === "dalle") {
55
- console.log(chalk.yellow('Warning: "dalle" is deprecated. Use "openai" instead.'));
56
- }
57
- // Get API key based on provider
58
- const envKeyMap = {
59
- openai: "OPENAI_API_KEY",
60
- dalle: "OPENAI_API_KEY", // backward compatibility
61
- gemini: "GOOGLE_API_KEY",
62
- runway: "RUNWAY_API_SECRET",
63
- };
64
- const providerNameMap = {
65
- openai: "OpenAI",
66
- dalle: "OpenAI", // backward compatibility
67
- gemini: "Google",
68
- runway: "Runway",
69
- };
70
- const envKey = envKeyMap[provider];
71
- const providerName = providerNameMap[provider];
72
- const apiKey = await getApiKey(envKey, providerName, options.apiKey);
73
- if (!apiKey) {
74
- exitWithError(authError(envKey, providerName));
75
- }
76
- const spinner = ora(`Generating image with ${providerName}...`).start();
77
- if (provider === "dalle" || provider === "openai") {
78
- const openaiImage = new OpenAIImageProvider();
79
- await openaiImage.initialize({ apiKey });
80
- const modelAlias = options.model;
81
- const openaiModel = modelAlias === "2" || modelAlias === "gpt-image-2"
82
- ? "gpt-image-2"
83
- : undefined;
84
- const result = await openaiImage.generateImage(prompt, {
85
- model: openaiModel,
86
- size: options.size,
87
- quality: options.quality,
88
- style: options.style,
89
- n: parseInt(options.count),
90
- });
91
- if (!result.success || !result.images) {
92
- spinner.fail("Image generation failed");
93
- exitWithError(apiError(result.error || "Image generation failed", true));
94
- }
95
- const modelLabel = openaiModel === "gpt-image-2" ? "GPT Image 2" : "GPT Image 1.5";
96
- spinner.succeed(chalk.green(`Generated ${result.images.length} image(s) with OpenAI ${modelLabel}`));
97
- console.log();
98
- console.log(chalk.bold.cyan("Generated Images"));
99
- console.log(chalk.dim("─".repeat(60)));
100
- for (let i = 0; i < result.images.length; i++) {
101
- const img = result.images[i];
102
- console.log();
103
- if (img.url) {
104
- console.log(`${chalk.yellow(`[${i + 1}]`)} ${img.url}`);
105
- }
106
- else if (img.base64) {
107
- console.log(`${chalk.yellow(`[${i + 1}]`)} (base64 image data)`);
108
- }
109
- if (img.revisedPrompt) {
110
- console.log(chalk.dim(` Revised: ${img.revisedPrompt.slice(0, 100)}...`));
111
- }
112
- }
113
- console.log();
114
- // Save if output specified
115
- if (options.output && result.images.length > 0) {
116
- const img = result.images[0];
117
- const saveSpinner = ora("Saving image...").start();
118
- try {
119
- let buffer;
120
- if (img.url) {
121
- // Download from URL
122
- const response = await fetch(img.url);
123
- buffer = Buffer.from(await response.arrayBuffer());
124
- }
125
- else if (img.base64) {
126
- // Decode base64
127
- buffer = Buffer.from(img.base64, "base64");
128
- }
129
- else {
130
- throw new Error("No image data available");
131
- }
132
- const outputPath = resolve(process.cwd(), options.output);
133
- await mkdir(dirname(outputPath), { recursive: true });
134
- await writeFile(outputPath, buffer);
135
- saveSpinner.succeed(chalk.green(`Saved to: ${outputPath}`));
136
- }
137
- catch (err) {
138
- saveSpinner.fail(chalk.red(`Failed to save image: ${err instanceof Error ? err.message : err}`));
139
- }
140
- }
141
- }
142
- else if (provider === "gemini") {
143
- // Validate model name
144
- const validGeminiModels = ["flash", "3.1-flash", "latest", "pro"];
145
- if (options.model && !validGeminiModels.includes(options.model)) {
146
- console.warn(chalk.yellow(`Unknown model "${options.model}", using flash. Valid: ${validGeminiModels.join(", ")}`));
147
- options.model = "flash";
148
- }
149
- // Validate aspect ratio
150
- const validRatios = ["1:1", "1:4", "1:8", "2:3", "3:2", "3:4", "4:1", "4:3", "4:5", "5:4", "8:1", "9:16", "16:9", "21:9"];
151
- if (options.ratio && !validRatios.includes(options.ratio)) {
152
- exitWithError(usageError(`Invalid ratio "${options.ratio}". Valid: ${validRatios.join(", ")}`));
153
- }
154
- const gemini = new GeminiProvider();
155
- await gemini.initialize({ apiKey });
156
- const geminiModelNames = {
157
- flash: "Nano Banana",
158
- "3.1-flash": "Nano Banana 2",
159
- latest: "Nano Banana 2",
160
- pro: "Nano Banana Pro",
161
- };
162
- const modelLabel = geminiModelNames[options.model] || "Nano Banana";
163
- let result = await gemini.generateImage(prompt, {
164
- model: options.model,
165
- aspectRatio: options.ratio,
166
- });
167
- // Auto-fallback: if latest/3.1-flash fails, retry with flash
168
- let usedLabel = modelLabel;
169
- const fallbackModels = ["latest", "3.1-flash"];
170
- if (!result.success && options.model && fallbackModels.includes(options.model)) {
171
- spinner.text = `${chalk.dim(result.error || "Failed")} — retrying with Nano Banana (flash)...`;
172
- result = await gemini.generateImage(prompt, {
173
- model: "flash",
174
- aspectRatio: options.ratio,
175
- });
176
- usedLabel = "Nano Banana (fallback)";
177
- }
178
- if (!result.success || !result.images) {
179
- spinner.fail("Image generation failed");
180
- exitWithError(apiError(result.error || "Image generation failed", true));
181
- }
182
- spinner.succeed(chalk.green(`Generated ${result.images.length} image(s) with Gemini (${usedLabel})`));
183
- console.log();
184
- console.log(chalk.bold.cyan("Generated Images"));
185
- console.log(chalk.dim("─".repeat(60)));
186
- // Gemini returns base64, we need to save or display
187
- for (let i = 0; i < result.images.length; i++) {
188
- const img = result.images[i];
189
- console.log();
190
- console.log(`${chalk.yellow(`[${i + 1}]`)} (base64 image, ${img.mimeType})`);
191
- }
192
- console.log();
193
- // Save if output specified
194
- if (options.output && result.images.length > 0) {
195
- const saveSpinner = ora("Saving image...").start();
196
- try {
197
- const img = result.images[0];
198
- const buffer = Buffer.from(img.base64, "base64");
199
- const outputPath = resolve(process.cwd(), options.output);
200
- await mkdir(dirname(outputPath), { recursive: true });
201
- await writeFile(outputPath, buffer);
202
- saveSpinner.succeed(chalk.green(`Saved to: ${outputPath}`));
203
- }
204
- catch (err) {
205
- saveSpinner.fail(chalk.red(`Failed to save image: ${err instanceof Error ? err.message : err}`));
206
- }
207
- }
208
- else {
209
- console.log(chalk.yellow("Use -o to save the generated image to a file"));
210
- }
211
- }
212
- else if (provider === "runway") {
213
- // Use Runway's Gemini model for text-to-image (no reference needed)
214
- const { spawn } = await import("child_process");
215
- const __filename = fileURLToPath(import.meta.url);
216
- const __dirname = dirname(__filename);
217
- const scriptPath = resolve(__dirname, "../../../../.claude/skills/runway-video/scripts/image.py");
218
- if (!options.output) {
219
- spinner.fail("Output path required");
220
- exitWithError(usageError("Output path required for Runway. Use -o option."));
221
- }
222
- const outputPath = resolve(process.cwd(), options.output);
223
- const args = [scriptPath, prompt, "-o", outputPath, "-r", options.ratio || "16:9"];
224
- spinner.text = "Generating image with Runway (gemini_2.5_flash)...";
225
- await new Promise((resolvePromise, reject) => {
226
- const proc = spawn("python3", args, {
227
- env: { ...process.env, RUNWAY_API_SECRET: apiKey },
228
- stdio: ["ignore", "pipe", "pipe"],
229
- });
230
- let stdout = "";
231
- let stderr = "";
232
- proc.stdout.on("data", (data) => {
233
- stdout += data.toString();
234
- });
235
- proc.stderr.on("data", (data) => {
236
- stderr += data.toString();
237
- });
238
- proc.on("close", (code) => {
239
- if (code === 0) {
240
- spinner.succeed(chalk.green("Generated image with Runway"));
241
- console.log(chalk.dim(stdout.trim()));
242
- resolvePromise();
243
- }
244
- else {
245
- spinner.fail(chalk.red("Runway image generation failed"));
246
- console.error(chalk.red(stderr || stdout));
247
- reject(new Error("Runway generation failed"));
248
- }
249
- });
250
- proc.on("error", (err) => {
251
- spinner.fail(chalk.red("Failed to run Runway script"));
252
- reject(err);
253
- });
254
- });
255
- }
256
- }
257
- catch (error) {
258
- exitWithError(apiError(`Image generation failed: ${error instanceof Error ? error.message : String(error)}`, true));
259
- }
260
- });
261
- aiCommand
262
- .command("thumbnail")
263
- .description("Generate video thumbnail (DALL-E) or extract best frame from video (Gemini)")
264
- .argument("[description]", "Thumbnail description (for DALL-E generation)")
265
- .option("-k, --api-key <key>", "API key (OpenAI for generation, Google for best-frame)")
266
- .option("-o, --output <path>", "Output file path")
267
- .option("-s, --style <style>", "Platform style: youtube, instagram, tiktok, twitter")
268
- .option("--best-frame <video>", "Extract best thumbnail frame from video using Gemini AI")
269
- .option("--prompt <prompt>", "Custom prompt for best-frame analysis")
270
- .option("--model <model>", "Gemini model: flash, latest, pro (default: flash)", "flash")
271
- .option("--dry-run", "Preview parameters without executing")
272
- .action(async (description, options) => {
273
- try {
274
- if (options.output) {
275
- validateOutputPath(options.output);
276
- }
277
- if (options.dryRun) {
278
- outputResult({ dryRun: true, command: "ai thumbnail", params: { description, output: options.output, style: options.style, bestFrame: options.bestFrame, prompt: options.prompt, model: options.model } });
279
- return;
280
- }
281
- // Best-frame mode: analyze video with Gemini and extract frame
282
- if (options.bestFrame) {
283
- const absVideoPath = resolve(process.cwd(), options.bestFrame);
284
- if (!existsSync(absVideoPath)) {
285
- exitWithError(notFoundError(absVideoPath));
286
- }
287
- if (!commandExists("ffmpeg")) {
288
- exitWithError(generalError("FFmpeg not found. Please install FFmpeg."));
289
- }
290
- const apiKey = await getApiKey("GOOGLE_API_KEY", "Google", options.apiKey);
291
- if (!apiKey) {
292
- exitWithError(authError("GOOGLE_API_KEY", "Google"));
293
- }
294
- const name = basename(options.bestFrame, extname(options.bestFrame));
295
- const outputPath = options.output || `${name}-thumbnail.png`;
296
- const spinner = ora("Analyzing video for best frame...").start();
297
- const result = await executeThumbnailBestFrame({
298
- videoPath: absVideoPath,
299
- outputPath: resolve(process.cwd(), outputPath),
300
- prompt: options.prompt,
301
- model: options.model,
302
- apiKey,
303
- });
304
- if (!result.success) {
305
- spinner.fail("Best frame extraction failed");
306
- exitWithError(apiError(result.error || "Best frame extraction failed", true));
307
- }
308
- spinner.succeed(chalk.green("Best frame extracted"));
309
- console.log();
310
- console.log(chalk.bold.cyan("Best Frame Result"));
311
- console.log(chalk.dim("─".repeat(60)));
312
- console.log(`Timestamp: ${chalk.bold(result.timestamp.toFixed(2))}s`);
313
- if (result.reason)
314
- console.log(`Reason: ${chalk.dim(result.reason)}`);
315
- console.log(`Output: ${chalk.green(result.outputPath)}`);
316
- console.log();
317
- return;
318
- }
319
- // Generation mode: create thumbnail with DALL-E
320
- if (!description) {
321
- exitWithError(usageError("Description required for thumbnail generation.", "Usage: vibe ai thumbnail <description> or vibe ai thumbnail --best-frame <video>"));
322
- }
323
- const apiKey = await getApiKey("OPENAI_API_KEY", "OpenAI", options.apiKey);
324
- if (!apiKey) {
325
- exitWithError(authError("OPENAI_API_KEY", "OpenAI"));
326
- }
327
- const spinner = ora("Generating thumbnail...").start();
328
- const openaiImage = new OpenAIImageProvider();
329
- await openaiImage.initialize({ apiKey });
330
- const result = await openaiImage.generateThumbnail(description, options.style);
331
- if (!result.success || !result.images) {
332
- spinner.fail("Thumbnail generation failed");
333
- exitWithError(apiError(result.error || "Thumbnail generation failed", true));
334
- }
335
- spinner.succeed(chalk.green("Thumbnail generated"));
336
- const img = result.images[0];
337
- console.log();
338
- console.log(chalk.bold.cyan("Generated Thumbnail"));
339
- console.log(chalk.dim("─".repeat(60)));
340
- console.log(`URL: ${img.url}`);
341
- if (img.revisedPrompt) {
342
- console.log(chalk.dim(`Prompt: ${img.revisedPrompt.slice(0, 100)}...`));
343
- }
344
- console.log();
345
- // Save if output specified
346
- if (options.output) {
347
- const saveSpinner = ora("Saving thumbnail...").start();
348
- try {
349
- let buffer;
350
- if (img.url) {
351
- const response = await fetch(img.url);
352
- buffer = Buffer.from(await response.arrayBuffer());
353
- }
354
- else if (img.base64) {
355
- buffer = Buffer.from(img.base64, "base64");
356
- }
357
- else {
358
- throw new Error("No image data available");
359
- }
360
- const outputPath = resolve(process.cwd(), options.output);
361
- await mkdir(dirname(outputPath), { recursive: true });
362
- await writeFile(outputPath, buffer);
363
- saveSpinner.succeed(chalk.green(`Saved to: ${outputPath}`));
364
- }
365
- catch (err) {
366
- saveSpinner.fail(chalk.red("Failed to save thumbnail"));
367
- }
368
- }
369
- }
370
- catch (error) {
371
- exitWithError(apiError(`Thumbnail generation failed: ${error instanceof Error ? error.message : String(error)}`, true));
372
- }
373
- });
374
- aiCommand
375
- .command("background")
376
- .description("Generate video background using DALL-E")
377
- .argument("<description>", "Background description")
378
- .option("-k, --api-key <key>", "OpenAI API key (or set OPENAI_API_KEY env)")
379
- .option("-o, --output <path>", "Output file path (downloads image)")
380
- .option("-a, --aspect <ratio>", "Aspect ratio: 16:9, 9:16, 1:1", "16:9")
381
- .option("--dry-run", "Preview parameters without executing")
382
- .action(async (description, options) => {
383
- try {
384
- if (options.output) {
385
- validateOutputPath(options.output);
386
- }
387
- if (options.dryRun) {
388
- outputResult({ dryRun: true, command: "ai background", params: { description, output: options.output, aspect: options.aspect } });
389
- return;
390
- }
391
- const apiKey = await getApiKey("OPENAI_API_KEY", "OpenAI", options.apiKey);
392
- if (!apiKey) {
393
- exitWithError(authError("OPENAI_API_KEY", "OpenAI"));
394
- }
395
- const spinner = ora("Generating background...").start();
396
- const openaiImage = new OpenAIImageProvider();
397
- await openaiImage.initialize({ apiKey });
398
- const result = await openaiImage.generateBackground(description, options.aspect);
399
- if (!result.success || !result.images) {
400
- spinner.fail("Background generation failed");
401
- exitWithError(apiError(result.error || "Background generation failed", true));
402
- }
403
- spinner.succeed(chalk.green("Background generated"));
404
- const img = result.images[0];
405
- console.log();
406
- console.log(chalk.bold.cyan("Generated Background"));
407
- console.log(chalk.dim("─".repeat(60)));
408
- console.log(`Image: ${img.url || "(base64 data)"}`);
409
- if (img.revisedPrompt) {
410
- console.log(chalk.dim(`Prompt: ${img.revisedPrompt.slice(0, 100)}...`));
411
- }
412
- console.log();
413
- // Save if output specified
414
- if (options.output) {
415
- const saveSpinner = ora("Saving background...").start();
416
- try {
417
- let buffer;
418
- if (img.url) {
419
- const response = await fetch(img.url);
420
- buffer = Buffer.from(await response.arrayBuffer());
421
- }
422
- else if (img.base64) {
423
- buffer = Buffer.from(img.base64, "base64");
424
- }
425
- else {
426
- throw new Error("No image data available");
427
- }
428
- const outputPath = resolve(process.cwd(), options.output);
429
- await mkdir(dirname(outputPath), { recursive: true });
430
- await writeFile(outputPath, buffer);
431
- saveSpinner.succeed(chalk.green(`Saved to: ${outputPath}`));
432
- }
433
- catch (err) {
434
- saveSpinner.fail(chalk.red("Failed to save background"));
435
- }
436
- }
437
- }
438
- catch (error) {
439
- exitWithError(apiError(`Background generation failed: ${error instanceof Error ? error.message : String(error)}`, true));
440
- }
441
- });
442
- // Gemini (Nano Banana) commands
443
- aiCommand
444
- .command("gemini")
445
- .description("Generate image using Gemini (Nano Banana)")
446
- .argument("<prompt>", "Text prompt describing the image")
447
- .option("-k, --api-key <key>", "Google API key (or set GOOGLE_API_KEY env)")
448
- .option("-o, --output <path>", "Output file path", "output.png")
449
- .option("-m, --model <model>", "Model: flash (fast), 3.1-flash / latest (Nano Banana 2), pro (professional, 4K)", "flash")
450
- .option("-r, --ratio <ratio>", "Aspect ratio: 1:1, 1:4, 1:8, 4:1, 8:1, 16:9, 9:16, 4:3, 3:4, 21:9, etc.", "1:1")
451
- .option("-s, --size <resolution>", "Resolution: 512px, 1K, 2K, 4K")
452
- .option("--grounding", "Enable Google Search grounding (Pro only)")
453
- .option("--thinking <level>", "Enable thinking mode: minimal or high")
454
- .option("--image-search", "Enable Image Search grounding (3.1 Flash only)")
455
- .option("--dry-run", "Preview parameters without executing")
456
- .action(async (prompt, options) => {
457
- try {
458
- if (options.output) {
459
- validateOutputPath(options.output);
460
- }
461
- if (options.dryRun) {
462
- outputResult({ dryRun: true, command: "ai gemini", params: { prompt, output: options.output, model: options.model, ratio: options.ratio, size: options.size, grounding: options.grounding, thinking: options.thinking, imageSearch: options.imageSearch } });
463
- return;
464
- }
465
- const apiKey = await getApiKey("GOOGLE_API_KEY", "Google", options.apiKey);
466
- if (!apiKey) {
467
- exitWithError(authError("GOOGLE_API_KEY", "Google"));
468
- }
469
- const modelNames = {
470
- flash: "gemini-2.5-flash-image",
471
- "3.1-flash": "gemini-3.1-flash-image-preview",
472
- latest: "gemini-3.1-flash-image-preview",
473
- pro: "gemini-3-pro-image-preview",
474
- };
475
- const modelName = modelNames[options.model] || modelNames.flash;
476
- const spinner = ora(`Generating image with ${modelName}...`).start();
477
- const gemini = new GeminiProvider();
478
- await gemini.initialize({ apiKey });
479
- let result = await gemini.generateImage(prompt, {
480
- model: options.model,
481
- aspectRatio: options.ratio,
482
- resolution: options.size,
483
- grounding: options.grounding,
484
- thinkingConfig: options.thinking ? { thinkingLevel: options.thinking } : undefined,
485
- imageSearchGrounding: options.imageSearch,
486
- });
487
- // Auto-fallback: if latest/3.1-flash fails, retry with flash
488
- const fallbackModels = ["latest", "3.1-flash"];
489
- if (!result.success && fallbackModels.includes(options.model)) {
490
- spinner.text = `${chalk.dim(result.error || `${modelName} failed`)} — retrying with flash...`;
491
- result = await gemini.generateImage(prompt, {
492
- model: "flash",
493
- aspectRatio: options.ratio,
494
- resolution: options.size,
495
- });
496
- }
497
- if (!result.success || !result.images || result.images.length === 0) {
498
- spinner.fail("Image generation failed");
499
- exitWithError(apiError(result.error || "Image generation failed", true));
500
- }
501
- spinner.succeed(chalk.green("Image generated"));
502
- if (result.model) {
503
- console.log(chalk.dim(`Model: ${result.model}`));
504
- }
505
- const img = result.images[0];
506
- if (img.base64) {
507
- const outputPath = resolve(process.cwd(), options.output);
508
- await mkdir(dirname(outputPath), { recursive: true });
509
- const buffer = Buffer.from(img.base64, "base64");
510
- await writeFile(outputPath, buffer);
511
- console.log(chalk.green(`Saved to: ${outputPath}`));
512
- }
513
- }
514
- catch (error) {
515
- exitWithError(apiError(`Image generation failed: ${error instanceof Error ? error.message : String(error)}`, true));
516
- }
517
- });
518
- aiCommand
519
- .command("gemini-edit")
520
- .description("Edit image(s) using Gemini (Nano Banana)")
521
- .argument("<images...>", "Input image file(s) followed by edit prompt")
522
- .option("-k, --api-key <key>", "Google API key (or set GOOGLE_API_KEY env)")
523
- .option("-o, --output <path>", "Output file path", "edited.png")
524
- .option("-m, --model <model>", "Model: flash (max 3 images), 3.1-flash / latest (max 3 images), pro (max 14 images)", "flash")
525
- .option("-r, --ratio <ratio>", "Output aspect ratio")
526
- .option("-s, --size <resolution>", "Resolution: 1K, 2K, 4K (Pro model only)")
527
- .option("--dry-run", "Preview parameters without executing")
528
- .action(async (args, options) => {
529
- try {
530
- if (options.output) {
531
- validateOutputPath(options.output);
532
- }
533
- // Last argument is the prompt, rest are image paths
534
- if (args.length < 2) {
535
- exitWithError(usageError("Need at least one image and a prompt"));
536
- }
537
- const prompt = args[args.length - 1];
538
- const imagePaths = args.slice(0, -1);
539
- if (options.dryRun) {
540
- outputResult({ dryRun: true, command: "ai gemini-edit", params: { images: imagePaths, prompt, output: options.output, model: options.model, ratio: options.ratio, size: options.size } });
541
- return;
542
- }
543
- const apiKey = await getApiKey("GOOGLE_API_KEY", "Google", options.apiKey);
544
- if (!apiKey) {
545
- exitWithError(authError("GOOGLE_API_KEY", "Google"));
546
- }
547
- const spinner = ora(`Reading ${imagePaths.length} image(s)...`).start();
548
- // Load all images
549
- const imageBuffers = [];
550
- for (const imagePath of imagePaths) {
551
- const absPath = resolve(process.cwd(), imagePath);
552
- const buffer = await readFile(absPath);
553
- imageBuffers.push(buffer);
554
- }
555
- const editModelNames = {
556
- flash: "gemini-2.5-flash-image",
557
- "3.1-flash": "gemini-3.1-flash-image-preview",
558
- latest: "gemini-3.1-flash-image-preview",
559
- pro: "gemini-3-pro-image-preview",
560
- };
561
- const editModelName = editModelNames[options.model] || editModelNames.flash;
562
- spinner.text = `Editing with ${editModelName}...`;
563
- const gemini = new GeminiProvider();
564
- await gemini.initialize({ apiKey });
565
- let result = await gemini.editImage(imageBuffers, prompt, {
566
- model: options.model,
567
- aspectRatio: options.ratio,
568
- resolution: options.size,
569
- });
570
- // Auto-fallback: if latest/3.1-flash fails, retry with flash
571
- const fallbackModels = ["latest", "3.1-flash"];
572
- if (!result.success && fallbackModels.includes(options.model)) {
573
- spinner.text = `${chalk.dim(result.error || `${editModelName} failed`)} — retrying with flash...`;
574
- result = await gemini.editImage(imageBuffers, prompt, {
575
- model: "flash",
576
- aspectRatio: options.ratio,
577
- resolution: options.size,
578
- });
579
- }
580
- if (!result.success || !result.images || result.images.length === 0) {
581
- spinner.fail("Image editing failed");
582
- exitWithError(apiError(result.error || "Image editing failed", true));
583
- }
584
- spinner.succeed(chalk.green("Image edited"));
585
- if (result.model) {
586
- console.log(chalk.dim(`Model: ${result.model}`));
587
- }
588
- const img = result.images[0];
589
- if (img.base64) {
590
- const outputPath = resolve(process.cwd(), options.output);
591
- await mkdir(dirname(outputPath), { recursive: true });
592
- const buffer = Buffer.from(img.base64, "base64");
593
- await writeFile(outputPath, buffer);
594
- console.log(chalk.green(`Saved to: ${outputPath}`));
595
- }
596
- }
597
- catch (error) {
598
- exitWithError(apiError(`Image editing failed: ${error instanceof Error ? error.message : String(error)}`, true));
599
- }
600
- });
601
- }
602
- export async function executeImageGenerate(options) {
603
- const { prompt, provider = "gemini", output, size = "1024x1024", ratio = "1:1", quality = "standard", style = "vivid", count = 1, model, apiKey, } = options;
604
- try {
605
- if (provider === "openai") {
606
- const key = apiKey || process.env.OPENAI_API_KEY;
607
- if (!key)
608
- return { success: false, error: "OPENAI_API_KEY required" };
609
- const openaiImage = new OpenAIImageProvider();
610
- await openaiImage.initialize({ apiKey: key });
611
- const result = await openaiImage.generateImage(prompt, {
612
- size: size,
613
- quality: quality,
614
- style: style,
615
- n: count,
616
- });
617
- if (!result.success || !result.images) {
618
- return { success: false, error: result.error || "Image generation failed" };
619
- }
620
- // Save first image if output specified
621
- let outputPath;
622
- if (output && result.images.length > 0) {
623
- const img = result.images[0];
624
- let buffer;
625
- if (img.url) {
626
- const response = await fetch(img.url);
627
- buffer = Buffer.from(await response.arrayBuffer());
628
- }
629
- else if (img.base64) {
630
- buffer = Buffer.from(img.base64, "base64");
631
- }
632
- else {
633
- return { success: false, error: "No image data available" };
634
- }
635
- outputPath = resolve(process.cwd(), output);
636
- await mkdir(dirname(outputPath), { recursive: true });
637
- await writeFile(outputPath, buffer);
638
- }
639
- return {
640
- success: true,
641
- outputPath,
642
- images: result.images.map(img => ({ url: img.url, base64: img.base64, revisedPrompt: img.revisedPrompt })),
643
- provider: "openai",
644
- };
645
- }
646
- else if (provider === "gemini") {
647
- const key = apiKey || process.env.GOOGLE_API_KEY;
648
- if (!key)
649
- return { success: false, error: "GOOGLE_API_KEY required" };
650
- const gemini = new GeminiProvider();
651
- await gemini.initialize({ apiKey: key });
652
- // Map "latest" to "3.1-flash" for type safety
653
- const modelMap = { latest: "3.1-flash" };
654
- const mappedModel = model ? (modelMap[model] || model) : undefined;
655
- let result = await gemini.generateImage(prompt, {
656
- model: mappedModel,
657
- aspectRatio: ratio,
658
- });
659
- // Auto-fallback
660
- const fallbackModels = ["3.1-flash"];
661
- if (!result.success && mappedModel && fallbackModels.includes(mappedModel)) {
662
- result = await gemini.generateImage(prompt, {
663
- model: "flash",
664
- aspectRatio: ratio,
665
- });
666
- }
667
- if (!result.success || !result.images) {
668
- return { success: false, error: result.error || "Image generation failed" };
669
- }
670
- // Save first image if output specified
671
- let outputPath;
672
- if (output && result.images.length > 0) {
673
- const img = result.images[0];
674
- if (img.base64) {
675
- outputPath = resolve(process.cwd(), output);
676
- await mkdir(dirname(outputPath), { recursive: true });
677
- await writeFile(outputPath, Buffer.from(img.base64, "base64"));
678
- }
679
- }
680
- return {
681
- success: true,
682
- outputPath,
683
- images: result.images.map(img => ({ base64: img.base64, mimeType: img.mimeType })),
684
- provider: "gemini",
685
- model: result.model,
686
- };
687
- }
688
- else if (provider === "grok") {
689
- const key = apiKey || process.env.XAI_API_KEY;
690
- if (!key)
691
- return { success: false, error: "XAI_API_KEY required" };
692
- // Grok image generation uses OpenAI-compatible API
693
- const openaiImage = new OpenAIImageProvider();
694
- await openaiImage.initialize({ apiKey: key, baseUrl: "https://api.x.ai/v1" });
695
- const result = await openaiImage.generateImage(prompt, {
696
- size: size,
697
- n: count,
698
- });
699
- if (!result.success || !result.images) {
700
- return { success: false, error: result.error || "Image generation failed" };
701
- }
702
- let outputPath;
703
- if (output && result.images.length > 0) {
704
- const img = result.images[0];
705
- let buffer;
706
- if (img.url) {
707
- const response = await fetch(img.url);
708
- buffer = Buffer.from(await response.arrayBuffer());
709
- }
710
- else if (img.base64) {
711
- buffer = Buffer.from(img.base64, "base64");
712
- }
713
- else {
714
- return { success: false, error: "No image data available" };
715
- }
716
- outputPath = resolve(process.cwd(), output);
717
- await mkdir(dirname(outputPath), { recursive: true });
718
- await writeFile(outputPath, buffer);
719
- }
720
- return {
721
- success: true,
722
- outputPath,
723
- images: result.images.map(img => ({ url: img.url, base64: img.base64, revisedPrompt: img.revisedPrompt })),
724
- provider: "grok",
725
- };
726
- }
727
- return { success: false, error: `Unsupported provider: ${provider}` };
728
- }
729
- catch (error) {
730
- return { success: false, error: `Image generation failed: ${error instanceof Error ? error.message : String(error)}` };
731
- }
732
- }
733
- export async function executeGeminiEdit(options) {
734
- const { imagePaths, prompt, output = "edited.png", model = "flash", ratio, resolution, apiKey, } = options;
735
- try {
736
- const key = apiKey || process.env.GOOGLE_API_KEY;
737
- if (!key)
738
- return { success: false, error: "GOOGLE_API_KEY required" };
739
- // Load all images
740
- const imageBuffers = [];
741
- for (const imagePath of imagePaths) {
742
- const absPath = resolve(process.cwd(), imagePath);
743
- if (!existsSync(absPath)) {
744
- return { success: false, error: `Image not found: ${absPath}` };
745
- }
746
- const buffer = await readFile(absPath);
747
- imageBuffers.push(buffer);
748
- }
749
- const gemini = new GeminiProvider();
750
- await gemini.initialize({ apiKey: key });
751
- let result = await gemini.editImage(imageBuffers, prompt, {
752
- model: model,
753
- aspectRatio: ratio,
754
- resolution: resolution,
755
- });
756
- // Auto-fallback
757
- const fallbackModels = ["latest", "3.1-flash"];
758
- if (!result.success && fallbackModels.includes(model)) {
759
- result = await gemini.editImage(imageBuffers, prompt, {
760
- model: "flash",
761
- aspectRatio: ratio,
762
- resolution: resolution,
763
- });
764
- }
765
- if (!result.success || !result.images || result.images.length === 0) {
766
- return { success: false, error: result.error || "Image editing failed" };
767
- }
768
- // Save output
769
- const img = result.images[0];
770
- let outputPath;
771
- if (img.base64) {
772
- outputPath = resolve(process.cwd(), output);
773
- await mkdir(dirname(outputPath), { recursive: true });
774
- await writeFile(outputPath, Buffer.from(img.base64, "base64"));
775
- }
776
- return {
777
- success: true,
778
- outputPath,
779
- model: result.model,
780
- };
781
- }
782
- catch (error) {
783
- return { success: false, error: `Image editing failed: ${error instanceof Error ? error.message : String(error)}` };
784
- }
785
- }
786
- export async function executeThumbnailBestFrame(options) {
787
- const { videoPath, outputPath, prompt, model = "flash", apiKey, } = options;
788
- if (!existsSync(videoPath)) {
789
- return { success: false, error: `Video not found: ${videoPath}` };
790
- }
791
- if (!commandExists("ffmpeg")) {
792
- return { success: false, error: "FFmpeg not found. Please install FFmpeg." };
793
- }
794
- const googleKey = apiKey || process.env.GOOGLE_API_KEY;
795
- if (!googleKey) {
796
- return { success: false, error: "Google API key required for Gemini video analysis. Run 'vibe setup' or set GOOGLE_API_KEY in .env" };
797
- }
798
- try {
799
- const gemini = new GeminiProvider();
800
- await gemini.initialize({ apiKey: googleKey });
801
- const videoData = await readFile(videoPath);
802
- const analysisPrompt = prompt ||
803
- "Analyze this video and find the single best frame for a thumbnail. " +
804
- "Look for frames that are visually striking, well-composed, emotionally engaging, " +
805
- "and representative of the video content. Avoid blurry frames, transitions, or dark scenes. " +
806
- "Return ONLY a JSON object: {\"timestamp\": <seconds as number>, \"reason\": \"<brief explanation>\"}";
807
- const modelMap = {
808
- flash: "gemini-3-flash-preview",
809
- latest: "gemini-2.5-flash",
810
- "flash-2.5": "gemini-2.5-flash", // backward compat
811
- pro: "gemini-2.5-pro",
812
- };
813
- const modelId = modelMap[model] || "gemini-3-flash-preview";
814
- const result = await gemini.analyzeVideo(videoData, analysisPrompt, {
815
- model: modelId,
816
- fps: 1,
817
- });
818
- if (!result.success || !result.response) {
819
- return { success: false, error: result.error || "Gemini analysis failed" };
820
- }
821
- // Parse timestamp from response
822
- const jsonMatch = result.response.match(/\{[\s\S]*?"timestamp"\s*:\s*([\d.]+)[\s\S]*?\}/);
823
- if (!jsonMatch) {
824
- return { success: false, error: `Could not parse timestamp from Gemini response: ${result.response.slice(0, 200)}` };
825
- }
826
- const timestamp = parseFloat(jsonMatch[1]);
827
- let reason;
828
- const reasonMatch = result.response.match(/"reason"\s*:\s*"([^"]+)"/);
829
- if (reasonMatch) {
830
- reason = reasonMatch[1];
831
- }
832
- // Extract frame with FFmpeg
833
- await execSafe("ffmpeg", ["-ss", String(timestamp), "-i", videoPath, "-frames:v", "1", "-q:v", "2", outputPath, "-y"], { timeout: 60000, maxBuffer: 50 * 1024 * 1024 });
834
- if (!existsSync(outputPath)) {
835
- return { success: false, error: "FFmpeg failed to extract frame" };
836
- }
837
- return {
838
- success: true,
839
- outputPath,
840
- timestamp,
841
- reason,
842
- };
843
- }
844
- catch (error) {
845
- return {
846
- success: false,
847
- error: `Best frame extraction failed: ${error instanceof Error ? error.message : String(error)}`,
848
- };
849
- }
850
- }
851
- /**
852
- * Register all image sub-commands on the given parent command.
853
- * Called from ai.ts: registerImageCommands(aiCommand)
854
- */
855
- export function registerImageCommands(aiCommand) {
856
- _registerImageCommands(aiCommand);
857
- }
858
- //# sourceMappingURL=ai-image.js.map