@vibeframe/cli 0.54.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 (481) 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-html-emit.d.ts +0 -120
  112. package/dist/commands/_shared/scene-html-emit.d.ts.map +0 -1
  113. package/dist/commands/_shared/scene-html-emit.js +0 -422
  114. package/dist/commands/_shared/scene-html-emit.js.map +0 -1
  115. package/dist/commands/_shared/scene-html-emit.test.d.ts +0 -2
  116. package/dist/commands/_shared/scene-html-emit.test.d.ts.map +0 -1
  117. package/dist/commands/_shared/scene-html-emit.test.js +0 -396
  118. package/dist/commands/_shared/scene-html-emit.test.js.map +0 -1
  119. package/dist/commands/_shared/scene-lint.d.ts +0 -110
  120. package/dist/commands/_shared/scene-lint.d.ts.map +0 -1
  121. package/dist/commands/_shared/scene-lint.js +0 -207
  122. package/dist/commands/_shared/scene-lint.js.map +0 -1
  123. package/dist/commands/_shared/scene-lint.test.d.ts +0 -2
  124. package/dist/commands/_shared/scene-lint.test.d.ts.map +0 -1
  125. package/dist/commands/_shared/scene-lint.test.js +0 -208
  126. package/dist/commands/_shared/scene-lint.test.js.map +0 -1
  127. package/dist/commands/_shared/scene-project.d.ts +0 -101
  128. package/dist/commands/_shared/scene-project.d.ts.map +0 -1
  129. package/dist/commands/_shared/scene-project.js +0 -281
  130. package/dist/commands/_shared/scene-project.js.map +0 -1
  131. package/dist/commands/_shared/scene-project.test.d.ts +0 -2
  132. package/dist/commands/_shared/scene-project.test.d.ts.map +0 -1
  133. package/dist/commands/_shared/scene-project.test.js +0 -203
  134. package/dist/commands/_shared/scene-project.test.js.map +0 -1
  135. package/dist/commands/_shared/scene-render.d.ts +0 -79
  136. package/dist/commands/_shared/scene-render.d.ts.map +0 -1
  137. package/dist/commands/_shared/scene-render.js +0 -138
  138. package/dist/commands/_shared/scene-render.js.map +0 -1
  139. package/dist/commands/_shared/scene-render.test.d.ts +0 -2
  140. package/dist/commands/_shared/scene-render.test.d.ts.map +0 -1
  141. package/dist/commands/_shared/scene-render.test.js +0 -145
  142. package/dist/commands/_shared/scene-render.test.js.map +0 -1
  143. package/dist/commands/_shared/segments-to-scenes.d.ts +0 -85
  144. package/dist/commands/_shared/segments-to-scenes.d.ts.map +0 -1
  145. package/dist/commands/_shared/segments-to-scenes.js +0 -202
  146. package/dist/commands/_shared/segments-to-scenes.js.map +0 -1
  147. package/dist/commands/_shared/segments-to-scenes.test.d.ts +0 -2
  148. package/dist/commands/_shared/segments-to-scenes.test.d.ts.map +0 -1
  149. package/dist/commands/_shared/segments-to-scenes.test.js +0 -219
  150. package/dist/commands/_shared/segments-to-scenes.test.js.map +0 -1
  151. package/dist/commands/_shared/tts-resolve.d.ts +0 -75
  152. package/dist/commands/_shared/tts-resolve.d.ts.map +0 -1
  153. package/dist/commands/_shared/tts-resolve.js +0 -89
  154. package/dist/commands/_shared/tts-resolve.js.map +0 -1
  155. package/dist/commands/_shared/tts-resolve.test.d.ts +0 -6
  156. package/dist/commands/_shared/tts-resolve.test.d.ts.map +0 -1
  157. package/dist/commands/_shared/tts-resolve.test.js +0 -147
  158. package/dist/commands/_shared/tts-resolve.test.js.map +0 -1
  159. package/dist/commands/agent.d.ts +0 -21
  160. package/dist/commands/agent.d.ts.map +0 -1
  161. package/dist/commands/agent.js +0 -285
  162. package/dist/commands/agent.js.map +0 -1
  163. package/dist/commands/ai-analyze.d.ts +0 -106
  164. package/dist/commands/ai-analyze.d.ts.map +0 -1
  165. package/dist/commands/ai-analyze.js +0 -320
  166. package/dist/commands/ai-analyze.js.map +0 -1
  167. package/dist/commands/ai-animated-caption.d.ts +0 -64
  168. package/dist/commands/ai-animated-caption.d.ts.map +0 -1
  169. package/dist/commands/ai-animated-caption.js +0 -272
  170. package/dist/commands/ai-animated-caption.js.map +0 -1
  171. package/dist/commands/ai-audio.d.ts +0 -98
  172. package/dist/commands/ai-audio.d.ts.map +0 -1
  173. package/dist/commands/ai-audio.js +0 -1059
  174. package/dist/commands/ai-audio.js.map +0 -1
  175. package/dist/commands/ai-broll.d.ts +0 -15
  176. package/dist/commands/ai-broll.d.ts.map +0 -1
  177. package/dist/commands/ai-broll.js +0 -421
  178. package/dist/commands/ai-broll.js.map +0 -1
  179. package/dist/commands/ai-edit-cli.d.ts +0 -14
  180. package/dist/commands/ai-edit-cli.d.ts.map +0 -1
  181. package/dist/commands/ai-edit-cli.js +0 -585
  182. package/dist/commands/ai-edit-cli.js.map +0 -1
  183. package/dist/commands/ai-edit.d.ts +0 -398
  184. package/dist/commands/ai-edit.d.ts.map +0 -1
  185. package/dist/commands/ai-edit.js +0 -1060
  186. package/dist/commands/ai-edit.js.map +0 -1
  187. package/dist/commands/ai-fill-gaps.d.ts +0 -14
  188. package/dist/commands/ai-fill-gaps.d.ts.map +0 -1
  189. package/dist/commands/ai-fill-gaps.js +0 -447
  190. package/dist/commands/ai-fill-gaps.js.map +0 -1
  191. package/dist/commands/ai-helpers.d.ts +0 -20
  192. package/dist/commands/ai-helpers.d.ts.map +0 -1
  193. package/dist/commands/ai-helpers.js +0 -59
  194. package/dist/commands/ai-helpers.js.map +0 -1
  195. package/dist/commands/ai-highlights.d.ts +0 -127
  196. package/dist/commands/ai-highlights.d.ts.map +0 -1
  197. package/dist/commands/ai-highlights.js +0 -1053
  198. package/dist/commands/ai-highlights.js.map +0 -1
  199. package/dist/commands/ai-image.d.ts +0 -76
  200. package/dist/commands/ai-image.d.ts.map +0 -1
  201. package/dist/commands/ai-image.js +0 -858
  202. package/dist/commands/ai-image.js.map +0 -1
  203. package/dist/commands/ai-motion.d.ts +0 -50
  204. package/dist/commands/ai-motion.d.ts.map +0 -1
  205. package/dist/commands/ai-motion.js +0 -297
  206. package/dist/commands/ai-motion.js.map +0 -1
  207. package/dist/commands/ai-narrate.d.ts +0 -66
  208. package/dist/commands/ai-narrate.d.ts.map +0 -1
  209. package/dist/commands/ai-narrate.js +0 -332
  210. package/dist/commands/ai-narrate.js.map +0 -1
  211. package/dist/commands/ai-review.d.ts +0 -57
  212. package/dist/commands/ai-review.d.ts.map +0 -1
  213. package/dist/commands/ai-review.js +0 -270
  214. package/dist/commands/ai-review.js.map +0 -1
  215. package/dist/commands/ai-script-pipeline-cli.d.ts +0 -9
  216. package/dist/commands/ai-script-pipeline-cli.d.ts.map +0 -1
  217. package/dist/commands/ai-script-pipeline-cli.js +0 -502
  218. package/dist/commands/ai-script-pipeline-cli.js.map +0 -1
  219. package/dist/commands/ai-script-pipeline.d.ts +0 -305
  220. package/dist/commands/ai-script-pipeline.d.ts.map +0 -1
  221. package/dist/commands/ai-script-pipeline.js +0 -1546
  222. package/dist/commands/ai-script-pipeline.js.map +0 -1
  223. package/dist/commands/ai-suggest-edit.d.ts +0 -14
  224. package/dist/commands/ai-suggest-edit.d.ts.map +0 -1
  225. package/dist/commands/ai-suggest-edit.js +0 -215
  226. package/dist/commands/ai-suggest-edit.js.map +0 -1
  227. package/dist/commands/ai-video-fx.d.ts +0 -14
  228. package/dist/commands/ai-video-fx.d.ts.map +0 -1
  229. package/dist/commands/ai-video-fx.js +0 -396
  230. package/dist/commands/ai-video-fx.js.map +0 -1
  231. package/dist/commands/ai-video.d.ts +0 -91
  232. package/dist/commands/ai-video.d.ts.map +0 -1
  233. package/dist/commands/ai-video.js +0 -1055
  234. package/dist/commands/ai-video.js.map +0 -1
  235. package/dist/commands/ai-viral.d.ts +0 -15
  236. package/dist/commands/ai-viral.d.ts.map +0 -1
  237. package/dist/commands/ai-viral.js +0 -507
  238. package/dist/commands/ai-viral.js.map +0 -1
  239. package/dist/commands/ai-visual-fx.d.ts +0 -14
  240. package/dist/commands/ai-visual-fx.d.ts.map +0 -1
  241. package/dist/commands/ai-visual-fx.js +0 -521
  242. package/dist/commands/ai-visual-fx.js.map +0 -1
  243. package/dist/commands/ai.d.ts +0 -38
  244. package/dist/commands/ai.d.ts.map +0 -1
  245. package/dist/commands/ai.js +0 -225
  246. package/dist/commands/ai.js.map +0 -1
  247. package/dist/commands/ai.test.d.ts +0 -2
  248. package/dist/commands/ai.test.d.ts.map +0 -1
  249. package/dist/commands/ai.test.js +0 -557
  250. package/dist/commands/ai.test.js.map +0 -1
  251. package/dist/commands/analyze.d.ts +0 -16
  252. package/dist/commands/analyze.d.ts.map +0 -1
  253. package/dist/commands/analyze.js +0 -247
  254. package/dist/commands/analyze.js.map +0 -1
  255. package/dist/commands/audio.d.ts +0 -18
  256. package/dist/commands/audio.d.ts.map +0 -1
  257. package/dist/commands/audio.js +0 -539
  258. package/dist/commands/audio.js.map +0 -1
  259. package/dist/commands/batch.d.ts +0 -3
  260. package/dist/commands/batch.d.ts.map +0 -1
  261. package/dist/commands/batch.js +0 -419
  262. package/dist/commands/batch.js.map +0 -1
  263. package/dist/commands/batch.test.d.ts +0 -2
  264. package/dist/commands/batch.test.d.ts.map +0 -1
  265. package/dist/commands/batch.test.js +0 -203
  266. package/dist/commands/batch.test.js.map +0 -1
  267. package/dist/commands/context.d.ts +0 -7
  268. package/dist/commands/context.d.ts.map +0 -1
  269. package/dist/commands/context.js +0 -66
  270. package/dist/commands/context.js.map +0 -1
  271. package/dist/commands/demo.d.ts +0 -7
  272. package/dist/commands/demo.d.ts.map +0 -1
  273. package/dist/commands/demo.js +0 -192
  274. package/dist/commands/demo.js.map +0 -1
  275. package/dist/commands/detect.d.ts +0 -56
  276. package/dist/commands/detect.d.ts.map +0 -1
  277. package/dist/commands/detect.js +0 -464
  278. package/dist/commands/detect.js.map +0 -1
  279. package/dist/commands/doctor.d.ts +0 -6
  280. package/dist/commands/doctor.d.ts.map +0 -1
  281. package/dist/commands/doctor.js +0 -322
  282. package/dist/commands/doctor.js.map +0 -1
  283. package/dist/commands/edit-cmd.d.ts +0 -112
  284. package/dist/commands/edit-cmd.d.ts.map +0 -1
  285. package/dist/commands/edit-cmd.js +0 -1041
  286. package/dist/commands/edit-cmd.js.map +0 -1
  287. package/dist/commands/export.d.ts +0 -61
  288. package/dist/commands/export.d.ts.map +0 -1
  289. package/dist/commands/export.js +0 -980
  290. package/dist/commands/export.js.map +0 -1
  291. package/dist/commands/export.test.d.ts +0 -2
  292. package/dist/commands/export.test.d.ts.map +0 -1
  293. package/dist/commands/export.test.js +0 -107
  294. package/dist/commands/export.test.js.map +0 -1
  295. package/dist/commands/generate.d.ts +0 -84
  296. package/dist/commands/generate.d.ts.map +0 -1
  297. package/dist/commands/generate.js +0 -2030
  298. package/dist/commands/generate.js.map +0 -1
  299. package/dist/commands/media.d.ts +0 -3
  300. package/dist/commands/media.d.ts.map +0 -1
  301. package/dist/commands/media.js +0 -163
  302. package/dist/commands/media.js.map +0 -1
  303. package/dist/commands/output.d.ts +0 -51
  304. package/dist/commands/output.d.ts.map +0 -1
  305. package/dist/commands/output.js +0 -219
  306. package/dist/commands/output.js.map +0 -1
  307. package/dist/commands/output.test.d.ts +0 -2
  308. package/dist/commands/output.test.d.ts.map +0 -1
  309. package/dist/commands/output.test.js +0 -151
  310. package/dist/commands/output.test.js.map +0 -1
  311. package/dist/commands/pipeline.d.ts +0 -19
  312. package/dist/commands/pipeline.d.ts.map +0 -1
  313. package/dist/commands/pipeline.js +0 -345
  314. package/dist/commands/pipeline.js.map +0 -1
  315. package/dist/commands/project.d.ts +0 -3
  316. package/dist/commands/project.d.ts.map +0 -1
  317. package/dist/commands/project.js +0 -181
  318. package/dist/commands/project.js.map +0 -1
  319. package/dist/commands/project.test.d.ts +0 -2
  320. package/dist/commands/project.test.d.ts.map +0 -1
  321. package/dist/commands/project.test.js +0 -105
  322. package/dist/commands/project.test.js.map +0 -1
  323. package/dist/commands/run.d.ts +0 -15
  324. package/dist/commands/run.d.ts.map +0 -1
  325. package/dist/commands/run.js +0 -204
  326. package/dist/commands/run.js.map +0 -1
  327. package/dist/commands/sanitize.d.ts +0 -21
  328. package/dist/commands/sanitize.d.ts.map +0 -1
  329. package/dist/commands/sanitize.js +0 -56
  330. package/dist/commands/sanitize.js.map +0 -1
  331. package/dist/commands/scene.d.ts +0 -86
  332. package/dist/commands/scene.d.ts.map +0 -1
  333. package/dist/commands/scene.js +0 -719
  334. package/dist/commands/scene.js.map +0 -1
  335. package/dist/commands/scene.test.d.ts +0 -2
  336. package/dist/commands/scene.test.d.ts.map +0 -1
  337. package/dist/commands/scene.test.js +0 -219
  338. package/dist/commands/scene.test.js.map +0 -1
  339. package/dist/commands/schema.d.ts +0 -13
  340. package/dist/commands/schema.d.ts.map +0 -1
  341. package/dist/commands/schema.js +0 -218
  342. package/dist/commands/schema.js.map +0 -1
  343. package/dist/commands/setup.d.ts +0 -6
  344. package/dist/commands/setup.d.ts.map +0 -1
  345. package/dist/commands/setup.js +0 -461
  346. package/dist/commands/setup.js.map +0 -1
  347. package/dist/commands/timeline.d.ts +0 -3
  348. package/dist/commands/timeline.d.ts.map +0 -1
  349. package/dist/commands/timeline.js +0 -609
  350. package/dist/commands/timeline.js.map +0 -1
  351. package/dist/commands/timeline.test.d.ts +0 -2
  352. package/dist/commands/timeline.test.d.ts.map +0 -1
  353. package/dist/commands/timeline.test.js +0 -334
  354. package/dist/commands/timeline.test.js.map +0 -1
  355. package/dist/commands/validate.d.ts +0 -34
  356. package/dist/commands/validate.d.ts.map +0 -1
  357. package/dist/commands/validate.js +0 -70
  358. package/dist/commands/validate.js.map +0 -1
  359. package/dist/config/config.test.d.ts +0 -2
  360. package/dist/config/config.test.d.ts.map +0 -1
  361. package/dist/config/config.test.js +0 -164
  362. package/dist/config/config.test.js.map +0 -1
  363. package/dist/config/index.d.ts +0 -35
  364. package/dist/config/index.d.ts.map +0 -1
  365. package/dist/config/index.js +0 -101
  366. package/dist/config/index.js.map +0 -1
  367. package/dist/config/schema.d.ts +0 -52
  368. package/dist/config/schema.d.ts.map +0 -1
  369. package/dist/config/schema.js +0 -44
  370. package/dist/config/schema.js.map +0 -1
  371. package/dist/engine/index.d.ts +0 -3
  372. package/dist/engine/index.d.ts.map +0 -1
  373. package/dist/engine/index.js +0 -2
  374. package/dist/engine/index.js.map +0 -1
  375. package/dist/engine/project.d.ts +0 -84
  376. package/dist/engine/project.d.ts.map +0 -1
  377. package/dist/engine/project.js +0 -355
  378. package/dist/engine/project.js.map +0 -1
  379. package/dist/engine/project.test.d.ts +0 -2
  380. package/dist/engine/project.test.d.ts.map +0 -1
  381. package/dist/engine/project.test.js +0 -599
  382. package/dist/engine/project.test.js.map +0 -1
  383. package/dist/index.d.ts +0 -7
  384. package/dist/index.d.ts.map +0 -1
  385. package/dist/index.js.map +0 -1
  386. package/dist/pipeline/executor.d.ts +0 -19
  387. package/dist/pipeline/executor.d.ts.map +0 -1
  388. package/dist/pipeline/executor.js +0 -397
  389. package/dist/pipeline/executor.js.map +0 -1
  390. package/dist/pipeline/index.d.ts +0 -4
  391. package/dist/pipeline/index.d.ts.map +0 -1
  392. package/dist/pipeline/index.js +0 -2
  393. package/dist/pipeline/index.js.map +0 -1
  394. package/dist/pipeline/renderers/__tests__/html-template.test.d.ts +0 -2
  395. package/dist/pipeline/renderers/__tests__/html-template.test.d.ts.map +0 -1
  396. package/dist/pipeline/renderers/__tests__/html-template.test.js +0 -170
  397. package/dist/pipeline/renderers/__tests__/html-template.test.js.map +0 -1
  398. package/dist/pipeline/renderers/__tests__/integration.test.d.ts +0 -2
  399. package/dist/pipeline/renderers/__tests__/integration.test.d.ts.map +0 -1
  400. package/dist/pipeline/renderers/__tests__/integration.test.js +0 -175
  401. package/dist/pipeline/renderers/__tests__/integration.test.js.map +0 -1
  402. package/dist/pipeline/renderers/chrome.d.ts +0 -26
  403. package/dist/pipeline/renderers/chrome.d.ts.map +0 -1
  404. package/dist/pipeline/renderers/chrome.js +0 -48
  405. package/dist/pipeline/renderers/chrome.js.map +0 -1
  406. package/dist/pipeline/renderers/html-clips.d.ts +0 -20
  407. package/dist/pipeline/renderers/html-clips.d.ts.map +0 -1
  408. package/dist/pipeline/renderers/html-clips.js +0 -50
  409. package/dist/pipeline/renderers/html-clips.js.map +0 -1
  410. package/dist/pipeline/renderers/html-runtime.d.ts +0 -7
  411. package/dist/pipeline/renderers/html-runtime.d.ts.map +0 -1
  412. package/dist/pipeline/renderers/html-runtime.js +0 -80
  413. package/dist/pipeline/renderers/html-runtime.js.map +0 -1
  414. package/dist/pipeline/renderers/html-template.d.ts +0 -3
  415. package/dist/pipeline/renderers/html-template.d.ts.map +0 -1
  416. package/dist/pipeline/renderers/html-template.js +0 -36
  417. package/dist/pipeline/renderers/html-template.js.map +0 -1
  418. package/dist/pipeline/renderers/hyperframes.d.ts +0 -8
  419. package/dist/pipeline/renderers/hyperframes.d.ts.map +0 -1
  420. package/dist/pipeline/renderers/hyperframes.js +0 -63
  421. package/dist/pipeline/renderers/hyperframes.js.map +0 -1
  422. package/dist/pipeline/renderers/project-builder.d.ts +0 -8
  423. package/dist/pipeline/renderers/project-builder.d.ts.map +0 -1
  424. package/dist/pipeline/renderers/project-builder.js +0 -65
  425. package/dist/pipeline/renderers/project-builder.js.map +0 -1
  426. package/dist/pipeline/renderers/types.d.ts +0 -41
  427. package/dist/pipeline/renderers/types.d.ts.map +0 -1
  428. package/dist/pipeline/renderers/types.js +0 -11
  429. package/dist/pipeline/renderers/types.js.map +0 -1
  430. package/dist/pipeline/resolver.d.ts +0 -20
  431. package/dist/pipeline/resolver.d.ts.map +0 -1
  432. package/dist/pipeline/resolver.js +0 -74
  433. package/dist/pipeline/resolver.js.map +0 -1
  434. package/dist/pipeline/types.d.ts +0 -82
  435. package/dist/pipeline/types.d.ts.map +0 -1
  436. package/dist/pipeline/types.js +0 -8
  437. package/dist/pipeline/types.js.map +0 -1
  438. package/dist/utils/api-key.d.ts +0 -33
  439. package/dist/utils/api-key.d.ts.map +0 -1
  440. package/dist/utils/api-key.js +0 -228
  441. package/dist/utils/api-key.js.map +0 -1
  442. package/dist/utils/api-key.test.d.ts +0 -2
  443. package/dist/utils/api-key.test.d.ts.map +0 -1
  444. package/dist/utils/api-key.test.js +0 -35
  445. package/dist/utils/api-key.test.js.map +0 -1
  446. package/dist/utils/audio.d.ts +0 -23
  447. package/dist/utils/audio.d.ts.map +0 -1
  448. package/dist/utils/audio.js +0 -79
  449. package/dist/utils/audio.js.map +0 -1
  450. package/dist/utils/exec-safe.d.ts +0 -22
  451. package/dist/utils/exec-safe.d.ts.map +0 -1
  452. package/dist/utils/exec-safe.js +0 -62
  453. package/dist/utils/exec-safe.js.map +0 -1
  454. package/dist/utils/first-run.d.ts +0 -17
  455. package/dist/utils/first-run.d.ts.map +0 -1
  456. package/dist/utils/first-run.js +0 -73
  457. package/dist/utils/first-run.js.map +0 -1
  458. package/dist/utils/input-validation.d.ts +0 -27
  459. package/dist/utils/input-validation.d.ts.map +0 -1
  460. package/dist/utils/input-validation.js +0 -67
  461. package/dist/utils/input-validation.js.map +0 -1
  462. package/dist/utils/provider-resolver.d.ts +0 -19
  463. package/dist/utils/provider-resolver.d.ts.map +0 -1
  464. package/dist/utils/provider-resolver.js +0 -75
  465. package/dist/utils/provider-resolver.js.map +0 -1
  466. package/dist/utils/remotion.d.ts +0 -231
  467. package/dist/utils/remotion.d.ts.map +0 -1
  468. package/dist/utils/remotion.js +0 -879
  469. package/dist/utils/remotion.js.map +0 -1
  470. package/dist/utils/subtitle.d.ts +0 -65
  471. package/dist/utils/subtitle.d.ts.map +0 -1
  472. package/dist/utils/subtitle.js +0 -135
  473. package/dist/utils/subtitle.js.map +0 -1
  474. package/dist/utils/subtitle.test.d.ts +0 -2
  475. package/dist/utils/subtitle.test.d.ts.map +0 -1
  476. package/dist/utils/subtitle.test.js +0 -175
  477. package/dist/utils/subtitle.test.js.map +0 -1
  478. package/dist/utils/tty.d.ts +0 -45
  479. package/dist/utils/tty.d.ts.map +0 -1
  480. package/dist/utils/tty.js +0 -231
  481. package/dist/utils/tty.js.map +0 -1
@@ -1,719 +0,0 @@
1
- /**
2
- * @module scene
3
- *
4
- * `vibe scene <sub>` — author, lint, and render per-scene HTML projects that
5
- * target the Hyperframes render backend. A scene project is bilingual: it's
6
- * also a valid Hyperframes project (hyperframes.json + meta.json +
7
- * index.html + compositions/). Users and AI agents can hand-author rich per-
8
- * scene animation instead of relying on flat YAML steps or opaque MP4s.
9
- *
10
- * Subcommands land incrementally across MVP 1:
11
- * - init [C1] — scaffold project directory
12
- * - add [C2] — author one scene (template + assets)
13
- * - lint [C3] — in-process Hyperframes lint + --fix
14
- * - render [C4, this commit] — render scene project to MP4/WebM/MOV
15
- */
16
- import { Command } from "commander";
17
- import { basename, resolve, relative, dirname } from "node:path";
18
- import { mkdir, readFile, writeFile, access, copyFile } from "node:fs/promises";
19
- import { existsSync } from "node:fs";
20
- import chalk from "chalk";
21
- import ora from "ora";
22
- import { parse as yamlParse } from "yaml";
23
- import { GeminiProvider, OpenAIImageProvider, WhisperProvider, } from "@vibeframe/ai-providers";
24
- import { resolveTtsProvider, TtsKeyMissingError, parseTtsProviderName, } from "./_shared/tts-resolve.js";
25
- import { scaffoldSceneProject, aspectToDims, } from "./_shared/scene-project.js";
26
- import { emitSceneHtml, insertClipIntoRoot, nextSceneStart, readRootDims, slugifySceneName, SCENE_PRESETS, } from "./_shared/scene-html-emit.js";
27
- import { runProjectLint, rootExists, } from "./_shared/scene-lint.js";
28
- import { executeSceneRender, } from "./_shared/scene-render.js";
29
- import { exitWithError, generalError, usageError, outputResult, isJsonMode, } from "./output.js";
30
- import { getApiKey } from "../utils/api-key.js";
31
- import { getAudioDuration } from "../utils/audio.js";
32
- const VALID_ASPECTS = ["16:9", "9:16", "1:1", "4:5"];
33
- function validateAspect(value) {
34
- if (!VALID_ASPECTS.includes(value)) {
35
- exitWithError(usageError(`Invalid aspect ratio: ${value}`, `Valid: ${VALID_ASPECTS.join(", ")}`));
36
- }
37
- return value;
38
- }
39
- function validateDuration(value) {
40
- const n = parseFloat(value);
41
- if (!Number.isFinite(n) || n <= 0 || n > 3600) {
42
- exitWithError(usageError(`Invalid duration: ${value}`, "Duration must be a positive number of seconds (≤3600)"));
43
- }
44
- return n;
45
- }
46
- function validatePreset(value) {
47
- if (!SCENE_PRESETS.includes(value)) {
48
- exitWithError(usageError(`Invalid style: ${value}`, `Valid: ${SCENE_PRESETS.join(", ")}`));
49
- }
50
- return value;
51
- }
52
- export const sceneCommand = new Command("scene")
53
- .description("Author and render per-scene HTML compositions (Hyperframes backend)")
54
- .addHelpText("after", `
55
- Examples:
56
- $ vibe scene init my-video # Scaffold a new project
57
- $ vibe scene init my-video -r 9:16 -d 30 # Vertical 30s project
58
- $ vibe scene add intro --style announcement \\
59
- --headline "Welcome to VibeFrame" # Headline-only scene
60
- $ vibe scene add overview --narration "VibeFrame turns scripts into video." \\
61
- --visuals "studio desk, soft lighting" # AI narration + image
62
- $ vibe scene lint # Validate every scene against Hyperframes rules
63
- $ vibe scene lint --fix # Auto-fix mechanical issues (e.g. missing class="clip")
64
- $ vibe scene lint --json # Structured output for agent loops
65
- $ vibe scene render # Render to renders/<name>-<timestamp>.mp4
66
- $ vibe scene render -o demo.mp4 --quality high # Custom output path + quality
67
- $ vibe scene render --fps 60 --format webm # 60fps WebM render
68
-
69
- A scene project is bilingual: it works with both \`vibe\` and \`npx hyperframes\`.
70
- Run 'vibe schema scene.<command>' for structured parameter info.`);
71
- sceneCommand
72
- .command("init")
73
- .description("Scaffold a new scene project (or safely augment an existing Hyperframes project)")
74
- .argument("<dir>", "Project directory (created if it doesn't exist)")
75
- .option("-n, --name <name>", "Project name (defaults to directory basename)")
76
- .option("-r, --ratio <ratio>", "Aspect ratio: 16:9, 9:16, 1:1, 4:5", "16:9")
77
- .option("-d, --duration <sec>", "Default root composition duration (seconds)", "10")
78
- .option("--dry-run", "Preview parameters without writing files")
79
- .action(async (dir, options) => {
80
- const aspect = validateAspect(options.ratio);
81
- const duration = validateDuration(options.duration);
82
- const name = options.name ?? basename(dir.replace(/\/+$/, ""));
83
- if (options.dryRun) {
84
- outputResult({
85
- dryRun: true,
86
- command: "scene init",
87
- params: { dir, name, aspect, duration },
88
- });
89
- return;
90
- }
91
- const spinner = isJsonMode() ? null : ora(`Scaffolding scene project at ${dir}...`).start();
92
- try {
93
- const result = await scaffoldSceneProject({ dir, name, aspect, duration });
94
- if (isJsonMode()) {
95
- outputResult({
96
- success: true,
97
- command: "scene init",
98
- dir,
99
- name,
100
- aspect,
101
- duration,
102
- created: result.created,
103
- merged: result.merged,
104
- skipped: result.skipped,
105
- });
106
- return;
107
- }
108
- spinner?.succeed(chalk.green(`Scene project ready: ${dir}`));
109
- console.log();
110
- console.log(chalk.bold.cyan("Files"));
111
- console.log(chalk.dim("─".repeat(60)));
112
- for (const f of result.created)
113
- console.log(chalk.green(" +"), f);
114
- for (const f of result.merged)
115
- console.log(chalk.yellow(" ~"), f, chalk.dim("(merged)"));
116
- for (const f of result.skipped)
117
- console.log(chalk.dim(" ·"), f, chalk.dim("(kept existing)"));
118
- console.log();
119
- console.log(chalk.bold.cyan("Next steps"));
120
- console.log(chalk.dim("─".repeat(60)));
121
- console.log(` ${chalk.cyan("vibe scene add")} <name> ${chalk.dim("# author a scene via AI")}`);
122
- console.log(` ${chalk.cyan("vibe scene lint")} ${chalk.dim("# validate HTML")}`);
123
- console.log(` ${chalk.cyan("vibe scene render")} ${chalk.dim("# render to MP4")}`);
124
- }
125
- catch (error) {
126
- spinner?.fail("Failed to scaffold scene project");
127
- const msg = error instanceof Error ? error.message : String(error);
128
- exitWithError(generalError(`Failed to scaffold: ${msg}`));
129
- }
130
- });
131
- // ---------------------------------------------------------------------------
132
- // `vibe scene add`
133
- // ---------------------------------------------------------------------------
134
- sceneCommand
135
- .command("add")
136
- .description("Add a new scene to a project: AI narration + image + per-scene HTML")
137
- .argument("<name>", "Scene name (slugified into the composition id)")
138
- .option("--style <preset>", `Style preset: ${SCENE_PRESETS.join(", ")}`, "simple")
139
- .option("--narration <text>", "Narration text (or path to a .txt file). Drives TTS + scene duration.")
140
- .option("--narration-file <path>", "Existing narration audio file (.wav/.mp3). Skips TTS — useful with hyperframes tts, Mac say, or other external tools.")
141
- .option("-d, --duration <sec>", "Explicit scene duration in seconds (overrides narration audio)")
142
- .option("--visuals <prompt>", "Image prompt — generates assets/scene-<id>.png via the configured image provider")
143
- .option("--headline <text>", "Visible headline (defaults to the humanised scene name)")
144
- .option("--kicker <text>", "Small label above the headline (explainer / product-shot)")
145
- .option("--insert-into <path>", "Root composition file to update", "index.html")
146
- .option("--project <dir>", "Project directory", ".")
147
- .option("--image-provider <name>", "Image provider: gemini, openai", "gemini")
148
- .option("--tts <provider>", "TTS provider: auto, elevenlabs, kokoro (default auto — picks ElevenLabs when key set, else Kokoro local)", "auto")
149
- .option("--voice <id>", "Voice id (ElevenLabs name/id, or Kokoro id like af_heart, am_michael)")
150
- .option("--no-audio", "Skip TTS even when --narration is provided (useful for tests/agent dry runs)")
151
- .option("--no-image", "Skip image generation even when --visuals is provided")
152
- .option("--no-transcribe", "Skip Whisper word-level transcribe step (no transcript-<id>.json emitted)")
153
- .option("--transcribe-language <code>", "BCP-47 language code passed to Whisper (e.g. en, ko)")
154
- .option("--force", "Overwrite an existing compositions/scene-<id>.html")
155
- .option("--dry-run", "Preview parameters without writing files or calling APIs")
156
- .action(async (name, options) => {
157
- if (options.style)
158
- options.style = validatePreset(options.style);
159
- if (options.duration !== undefined)
160
- options.duration = validateDuration(options.duration);
161
- let tts;
162
- try {
163
- tts = parseTtsProviderName(options.tts);
164
- }
165
- catch (error) {
166
- exitWithError(usageError(error instanceof Error ? error.message : String(error)));
167
- }
168
- if (options.dryRun) {
169
- const id = slugifySceneName(name);
170
- outputResult({
171
- dryRun: true,
172
- command: "scene add",
173
- params: {
174
- name,
175
- id,
176
- preset: options.style,
177
- narration: !!options.narration,
178
- visuals: !!options.visuals,
179
- duration: options.duration,
180
- headline: options.headline,
181
- kicker: options.kicker,
182
- project: options.project,
183
- insertInto: options.insertInto,
184
- imageProvider: options.imageProvider,
185
- tts,
186
- audio: options.audio, // commander sets `audio: false` when --no-audio is passed
187
- image: options.image,
188
- },
189
- });
190
- return;
191
- }
192
- const spinner = isJsonMode() ? null : ora(`Adding scene "${name}"...`).start();
193
- try {
194
- const result = await executeSceneAdd({
195
- name,
196
- preset: options.style,
197
- narration: options.narration,
198
- narrationFile: options.narrationFile,
199
- duration: options.duration,
200
- visuals: options.visuals,
201
- headline: options.headline,
202
- kicker: options.kicker,
203
- projectDir: options.project,
204
- insertInto: options.insertInto,
205
- imageProvider: options.imageProvider,
206
- tts,
207
- voice: options.voice,
208
- skipAudio: options.audio === false,
209
- skipImage: options.image === false,
210
- skipTranscribe: options.transcribe === false,
211
- transcribeLanguage: options.transcribeLanguage,
212
- force: !!options.force,
213
- onProgress: (msg) => {
214
- if (spinner)
215
- spinner.text = msg;
216
- },
217
- });
218
- if (!result.success) {
219
- spinner?.fail(`Failed to add scene "${name}"`);
220
- exitWithError(generalError(result.error ?? "Scene add failed"));
221
- }
222
- if (isJsonMode()) {
223
- outputResult({
224
- command: "scene add",
225
- ...result,
226
- });
227
- return;
228
- }
229
- spinner?.succeed(chalk.green(`Scene added: ${result.id}`));
230
- console.log();
231
- console.log(chalk.bold.cyan("Files"));
232
- console.log(chalk.dim("─".repeat(60)));
233
- console.log(chalk.green(" +"), result.scenePath);
234
- if (result.audioPath)
235
- console.log(chalk.green(" +"), result.audioPath);
236
- if (result.imagePath)
237
- console.log(chalk.green(" +"), result.imagePath);
238
- if (result.transcriptPath)
239
- console.log(chalk.green(" +"), result.transcriptPath);
240
- console.log(chalk.yellow(" ~"), result.rootPath, chalk.dim("(updated)"));
241
- console.log();
242
- console.log(chalk.bold.cyan("Composition"));
243
- console.log(chalk.dim("─".repeat(60)));
244
- console.log(` id ${chalk.bold(result.id)}`);
245
- console.log(` preset ${result.preset}`);
246
- console.log(` start ${result.start.toFixed(2)}s`);
247
- console.log(` duration ${result.duration.toFixed(2)}s`);
248
- console.log();
249
- console.log(chalk.bold.cyan("Next steps"));
250
- console.log(chalk.dim("─".repeat(60)));
251
- console.log(` ${chalk.cyan("vibe scene lint")} ${chalk.dim("# validate HTML")}`);
252
- console.log(` ${chalk.cyan("vibe scene render")} ${chalk.dim("# render to MP4")}`);
253
- }
254
- catch (error) {
255
- spinner?.fail(`Failed to add scene "${name}"`);
256
- const msg = error instanceof Error ? error.message : String(error);
257
- exitWithError(generalError(msg));
258
- }
259
- });
260
- async function pathExists(p) {
261
- try {
262
- await access(p);
263
- return true;
264
- }
265
- catch {
266
- return false;
267
- }
268
- }
269
- async function loadVibeProjectConfig(projectDir) {
270
- const cfgPath = resolve(projectDir, "vibe.project.yaml");
271
- if (!(await pathExists(cfgPath)))
272
- return null;
273
- const raw = await readFile(cfgPath, "utf-8");
274
- return yamlParse(raw);
275
- }
276
- /** Resolve narration text — value may be inline text or a path to a `.txt`/`.md` file. */
277
- async function resolveNarrationText(value) {
278
- if (!value)
279
- return undefined;
280
- // Treat as a file path only when it actually exists AND looks like one. This
281
- // avoids accidentally interpreting a sentence with a slash as a path.
282
- const looksLikePath = /\.[a-z]{2,4}$/i.test(value) || value.includes("/") || value.includes("\\");
283
- if (looksLikePath && existsSync(value)) {
284
- return (await readFile(value, "utf-8")).trim();
285
- }
286
- return value.trim();
287
- }
288
- /** Map a project aspect to the OpenAI image API size string. */
289
- function openAiSizeForAspect(width, height) {
290
- if (width === height)
291
- return "1024x1024";
292
- return width > height ? "1536x1024" : "1024x1536";
293
- }
294
- /** Best-effort aspect-ratio string for the image provider. */
295
- function aspectStringFromDims(width, height) {
296
- if (width === height)
297
- return "1:1";
298
- if (width === 1920 && height === 1080)
299
- return "16:9";
300
- if (width === 1080 && height === 1920)
301
- return "9:16";
302
- if (width === 1080 && height === 1350)
303
- return "4:5";
304
- return width > height ? "16:9" : "9:16";
305
- }
306
- export async function executeSceneAdd(opts) {
307
- const projectDir = resolve(opts.projectDir ?? ".");
308
- const rootRel = opts.insertInto ?? "index.html";
309
- const rootPath = resolve(projectDir, rootRel);
310
- const id = slugifySceneName(opts.name);
311
- const sceneRel = `compositions/scene-${id}.html`;
312
- const scenePath = resolve(projectDir, sceneRel);
313
- // -- Validate project ----------------------------------------------------
314
- const errResult = (error) => ({
315
- success: false,
316
- id,
317
- preset: opts.preset,
318
- start: 0,
319
- duration: 0,
320
- scenePath,
321
- rootPath,
322
- error,
323
- });
324
- if (!(await pathExists(rootPath))) {
325
- return errResult(`Root composition not found: ${rootPath}. Run \`vibe scene init\` first.`);
326
- }
327
- if (!opts.force && (await pathExists(scenePath))) {
328
- return errResult(`Scene already exists: ${sceneRel}. Re-run with --force to overwrite.`);
329
- }
330
- // -- Resolve canvas dims (root takes precedence over project config) -----
331
- const rootHtmlBefore = await readFile(rootPath, "utf-8");
332
- let dims = readRootDims(rootHtmlBefore);
333
- if (!dims) {
334
- const cfg = await loadVibeProjectConfig(projectDir);
335
- if (cfg?.aspect)
336
- dims = aspectToDims(cfg.aspect);
337
- }
338
- if (!dims) {
339
- return errResult("Could not determine canvas dimensions from index.html or vibe.project.yaml.");
340
- }
341
- // -- Resolve narration text ---------------------------------------------
342
- const narrationText = await resolveNarrationText(opts.narration);
343
- // -- Asset generation: narration audio -----------------------------------
344
- let audioRelPath;
345
- let audioAbsPath;
346
- let narrationDuration;
347
- if (opts.narrationFile && !opts.skipAudio) {
348
- // External wav/mp3: skip TTS, copy file into the project's assets/ dir.
349
- const sourceAbs = resolve(opts.narrationFile);
350
- if (!(await pathExists(sourceAbs))) {
351
- return errResult(`Narration file not found: ${sourceAbs}`);
352
- }
353
- const ext = (sourceAbs.match(/\.([a-z0-9]+)$/i)?.[1] ?? "wav").toLowerCase();
354
- if (ext !== "wav" && ext !== "mp3") {
355
- return errResult(`Unsupported narration file extension: .${ext}. Use .wav or .mp3.`);
356
- }
357
- audioRelPath = `assets/narration-${id}.${ext}`;
358
- audioAbsPath = resolve(projectDir, audioRelPath);
359
- await mkdir(dirname(audioAbsPath), { recursive: true });
360
- await copyFile(sourceAbs, audioAbsPath);
361
- try {
362
- narrationDuration = await getAudioDuration(audioAbsPath);
363
- }
364
- catch {
365
- narrationDuration = undefined;
366
- }
367
- }
368
- else if (narrationText && !opts.skipAudio) {
369
- let resolution;
370
- try {
371
- resolution = await resolveTtsProvider(opts.tts ?? "auto");
372
- }
373
- catch (error) {
374
- if (error instanceof TtsKeyMissingError) {
375
- return errResult(error.message);
376
- }
377
- throw error;
378
- }
379
- opts.onProgress?.(resolution.provider === "kokoro"
380
- ? "Generating narration with Kokoro (local — first run downloads ~330MB)..."
381
- : "Generating narration with ElevenLabs...");
382
- const tts = await resolution.call(narrationText, {
383
- voice: opts.voice,
384
- onProgress: (event) => {
385
- if (event.status === "progress" && typeof event.progress === "number") {
386
- opts.onProgress?.(`Kokoro model: ${event.file ?? ""} ${Math.round(event.progress)}%`);
387
- }
388
- },
389
- });
390
- if (!tts.success || !tts.audioBuffer) {
391
- return errResult(`${resolution.provider} TTS failed: ${tts.error ?? "unknown error"}`);
392
- }
393
- audioRelPath = `assets/narration-${id}.${resolution.audioExtension}`;
394
- audioAbsPath = resolve(projectDir, audioRelPath);
395
- await mkdir(dirname(audioAbsPath), { recursive: true });
396
- await writeFile(audioAbsPath, tts.audioBuffer);
397
- try {
398
- narrationDuration = await getAudioDuration(audioAbsPath);
399
- }
400
- catch {
401
- narrationDuration = undefined;
402
- }
403
- }
404
- // -- Whisper word-level transcribe --------------------------------------
405
- // Auto-runs whenever we have audio + an OpenAI key. The transcript JSON
406
- // mirrors the Hyperframes shape so a future emitSceneHtml (C5) can drive
407
- // GSAP word-sync from it. Failure is non-fatal — narration still plays,
408
- // we just lose word-level animation timing.
409
- let transcriptRelPath;
410
- let transcriptWordCount;
411
- let transcriptWords;
412
- if (audioAbsPath && !opts.skipTranscribe) {
413
- const whisperKey = await getApiKey("OPENAI_API_KEY", "OpenAI");
414
- if (!whisperKey) {
415
- opts.onProgress?.("Skipping transcribe (OPENAI_API_KEY not set — narration plays but word-sync unavailable)");
416
- }
417
- else {
418
- opts.onProgress?.("Transcribing narration (Whisper word-level)...");
419
- try {
420
- const whisper = new WhisperProvider();
421
- await whisper.initialize({ apiKey: whisperKey });
422
- const audioBytes = await readFile(audioAbsPath);
423
- const audioBlob = new Blob([new Uint8Array(audioBytes)]);
424
- const transcript = await whisper.transcribe(audioBlob, undefined, {
425
- granularity: "word",
426
- language: opts.transcribeLanguage,
427
- });
428
- if (transcript.status === "completed" && transcript.words?.length) {
429
- transcriptRelPath = `assets/transcript-${id}.json`;
430
- const transcriptAbs = resolve(projectDir, transcriptRelPath);
431
- await writeFile(transcriptAbs, JSON.stringify(transcript.words, null, 2), "utf-8");
432
- transcriptWordCount = transcript.words.length;
433
- transcriptWords = transcript.words.map((w) => ({ text: w.text, start: w.start, end: w.end }));
434
- }
435
- else if (transcript.status === "failed") {
436
- opts.onProgress?.(`Transcribe failed: ${transcript.error ?? "unknown error"}`);
437
- }
438
- }
439
- catch (error) {
440
- const msg = error instanceof Error ? error.message : String(error);
441
- opts.onProgress?.(`Transcribe failed: ${msg}`);
442
- }
443
- }
444
- }
445
- // -- Asset generation: backdrop image -----------------------------------
446
- let imageRelPath;
447
- let imageAbsPath;
448
- if (opts.visuals && !opts.skipImage) {
449
- const provider = (opts.imageProvider ?? "gemini").toLowerCase();
450
- if (provider !== "gemini" && provider !== "openai") {
451
- return errResult(`Unsupported --image-provider: ${provider}. Valid: gemini, openai.`);
452
- }
453
- opts.onProgress?.(`Generating image with ${provider}...`);
454
- if (provider === "openai") {
455
- const openaiKey = await getApiKey("OPENAI_API_KEY", "OpenAI");
456
- if (!openaiKey) {
457
- return errResult("OpenAI API key required for --visuals --image-provider openai. Set OPENAI_API_KEY or pass --no-image.");
458
- }
459
- const openai = new OpenAIImageProvider();
460
- await openai.initialize({ apiKey: openaiKey });
461
- const imageResult = await openai.generateImage(opts.visuals, {
462
- size: openAiSizeForAspect(dims.width, dims.height),
463
- quality: "standard",
464
- });
465
- if (!imageResult.success || !imageResult.images?.[0]) {
466
- return errResult(`OpenAI image generation failed: ${imageResult.error ?? "unknown error"}`);
467
- }
468
- const img = imageResult.images[0];
469
- imageRelPath = `assets/scene-${id}.png`;
470
- imageAbsPath = resolve(projectDir, imageRelPath);
471
- await mkdir(dirname(imageAbsPath), { recursive: true });
472
- let buffer;
473
- if (img.base64) {
474
- buffer = Buffer.from(img.base64, "base64");
475
- }
476
- else if (img.url) {
477
- const response = await fetch(img.url);
478
- buffer = Buffer.from(await response.arrayBuffer());
479
- }
480
- else {
481
- return errResult("OpenAI returned no image data");
482
- }
483
- await writeFile(imageAbsPath, buffer);
484
- }
485
- else {
486
- const googleKey = await getApiKey("GOOGLE_API_KEY", "Google");
487
- if (!googleKey) {
488
- return errResult("Google API key required for Gemini image generation. Set GOOGLE_API_KEY or pass --no-image.");
489
- }
490
- const gemini = new GeminiProvider();
491
- await gemini.initialize({ apiKey: googleKey });
492
- const aspectRatio = aspectStringFromDims(dims.width, dims.height);
493
- const imageResult = await gemini.generateImage(opts.visuals, { aspectRatio });
494
- if (!imageResult.success || !imageResult.images?.[0]?.base64) {
495
- return errResult(`Gemini image generation failed: ${imageResult.error ?? "unknown error"}`);
496
- }
497
- imageRelPath = `assets/scene-${id}.png`;
498
- imageAbsPath = resolve(projectDir, imageRelPath);
499
- await mkdir(dirname(imageAbsPath), { recursive: true });
500
- const buffer = Buffer.from(imageResult.images[0].base64, "base64");
501
- await writeFile(imageAbsPath, buffer);
502
- }
503
- }
504
- // -- Decide scene duration -----------------------------------------------
505
- const cfg = await loadVibeProjectConfig(projectDir);
506
- const fallback = cfg?.defaultSceneDuration ?? 5;
507
- const duration = opts.duration ?? narrationDuration ?? fallback;
508
- // -- Emit scene HTML -----------------------------------------------------
509
- opts.onProgress?.("Emitting scene HTML...");
510
- const sceneHtml = emitSceneHtml({
511
- id,
512
- preset: opts.preset,
513
- width: dims.width,
514
- height: dims.height,
515
- duration,
516
- headline: opts.headline,
517
- subhead: narrationText,
518
- kicker: opts.kicker,
519
- imagePath: imageRelPath,
520
- audioPath: audioRelPath,
521
- transcript: transcriptWords,
522
- });
523
- await mkdir(dirname(scenePath), { recursive: true });
524
- await writeFile(scenePath, sceneHtml, "utf-8");
525
- // -- Update root index.html ---------------------------------------------
526
- opts.onProgress?.("Updating root composition...");
527
- const start = nextSceneStart(rootHtmlBefore);
528
- const updated = insertClipIntoRoot(rootHtmlBefore, { id, start, duration });
529
- await writeFile(rootPath, updated, "utf-8");
530
- const transcriptAbsPath = transcriptRelPath ? resolve(projectDir, transcriptRelPath) : undefined;
531
- return {
532
- success: true,
533
- id,
534
- preset: opts.preset,
535
- start,
536
- duration,
537
- scenePath: relative(process.cwd(), scenePath) || scenePath,
538
- rootPath: relative(process.cwd(), rootPath) || rootPath,
539
- audioPath: audioAbsPath ? (relative(process.cwd(), audioAbsPath) || audioAbsPath) : undefined,
540
- imagePath: imageAbsPath ? (relative(process.cwd(), imageAbsPath) || imageAbsPath) : undefined,
541
- transcriptPath: transcriptAbsPath ? (relative(process.cwd(), transcriptAbsPath) || transcriptAbsPath) : undefined,
542
- transcriptWordCount,
543
- };
544
- }
545
- // ---------------------------------------------------------------------------
546
- // `vibe scene lint`
547
- // ---------------------------------------------------------------------------
548
- sceneCommand
549
- .command("lint")
550
- .description("Validate scene HTML against Hyperframes rules (in-process, no Chrome required)")
551
- .argument("[root]", "Root composition file relative to --project", "index.html")
552
- .option("--project <dir>", "Project directory", ".")
553
- .option("--fix", "Apply mechanical auto-fixes (currently: missing class=\"clip\")")
554
- .action(async (root, options) => {
555
- const projectDir = resolve(options.project);
556
- if (!(await rootExists(projectDir, root))) {
557
- exitWithError(generalError(`Root composition not found: ${resolve(projectDir, root)}`, "Run `vibe scene init` first, or pass --project <dir>."));
558
- }
559
- const spinner = isJsonMode() ? null : ora("Linting scenes...").start();
560
- let result;
561
- try {
562
- result = await runProjectLint({ projectDir, rootRel: root, fix: !!options.fix });
563
- }
564
- catch (error) {
565
- spinner?.fail("Lint failed");
566
- const msg = error instanceof Error ? error.message : String(error);
567
- exitWithError(generalError(`Lint failed: ${msg}`));
568
- }
569
- if (isJsonMode()) {
570
- outputResult({
571
- command: "scene lint",
572
- ...result,
573
- });
574
- if (!result.ok)
575
- process.exit(1);
576
- return;
577
- }
578
- if (result.ok && result.warningCount === 0 && result.infoCount === 0) {
579
- spinner?.succeed(chalk.green(`Lint clean — ${result.files.length} file(s) checked`));
580
- }
581
- else if (result.ok) {
582
- spinner?.warn(chalk.yellow(`${result.warningCount} warning(s), ${result.infoCount} info — ${result.errorCount} error(s)`));
583
- }
584
- else {
585
- spinner?.fail(chalk.red(`${result.errorCount} error(s), ${result.warningCount} warning(s), ${result.infoCount} info`));
586
- }
587
- for (const file of result.files) {
588
- if (file.findings.length === 0)
589
- continue;
590
- console.log();
591
- console.log(chalk.bold.cyan(file.file));
592
- console.log(chalk.dim("─".repeat(60)));
593
- for (const f of file.findings) {
594
- const tag = severityTag(f.severity);
595
- const loc = f.elementId ? chalk.dim(` #${f.elementId}`) : f.selector ? chalk.dim(` ${f.selector}`) : "";
596
- console.log(` ${tag} ${chalk.dim(`[${f.code}]`)}${loc} ${f.message}`);
597
- if (f.fixHint)
598
- console.log(` ${chalk.dim("→ " + f.fixHint)}`);
599
- }
600
- }
601
- if (result.fixed.length > 0) {
602
- console.log();
603
- console.log(chalk.bold.cyan("Auto-fixed"));
604
- console.log(chalk.dim("─".repeat(60)));
605
- for (const fx of result.fixed) {
606
- console.log(` ${chalk.green("✔")} ${fx.file} ${chalk.dim(fx.codes.join(", "))}`);
607
- }
608
- }
609
- if (!result.ok)
610
- process.exit(1);
611
- });
612
- function severityTag(severity) {
613
- if (severity === "error")
614
- return chalk.red("✘ error ");
615
- if (severity === "warning")
616
- return chalk.yellow("⚠ warn ");
617
- return chalk.blue("ℹ info ");
618
- }
619
- // ---------------------------------------------------------------------------
620
- // `vibe scene render`
621
- // ---------------------------------------------------------------------------
622
- const VALID_FPS = [24, 30, 60];
623
- const VALID_QUALITIES = ["draft", "standard", "high"];
624
- const VALID_FORMATS = ["mp4", "webm", "mov"];
625
- function validateFps(value) {
626
- const n = parseInt(value, 10);
627
- if (!VALID_FPS.includes(n)) {
628
- exitWithError(usageError(`Invalid --fps: ${value}`, `Valid: ${VALID_FPS.join(", ")}`));
629
- }
630
- return n;
631
- }
632
- function validateQuality(value) {
633
- if (!VALID_QUALITIES.includes(value)) {
634
- exitWithError(usageError(`Invalid --quality: ${value}`, `Valid: ${VALID_QUALITIES.join(", ")}`));
635
- }
636
- return value;
637
- }
638
- function validateFormat(value) {
639
- if (!VALID_FORMATS.includes(value)) {
640
- exitWithError(usageError(`Invalid --format: ${value}`, `Valid: ${VALID_FORMATS.join(", ")}`));
641
- }
642
- return value;
643
- }
644
- function validateWorkers(value) {
645
- const n = parseInt(value, 10);
646
- if (!Number.isFinite(n) || n < 1 || n > 16) {
647
- exitWithError(usageError(`Invalid --workers: ${value}`, "Must be an integer between 1 and 16"));
648
- }
649
- return n;
650
- }
651
- sceneCommand
652
- .command("render")
653
- .description("Render a scene project to MP4/WebM/MOV via the Hyperframes producer (requires Chrome)")
654
- .argument("[root]", "Root composition file relative to --project", "index.html")
655
- .option("--project <dir>", "Project directory", ".")
656
- .option("-o, --out <path>", "Output file (default: renders/<name>-<timestamp>.<format>)")
657
- .option("--fps <n>", `Frames per second: ${VALID_FPS.join("|")}`, "30")
658
- .option("--quality <q>", `Quality preset: ${VALID_QUALITIES.join("|")}`, "standard")
659
- .option("--format <f>", `Output container: ${VALID_FORMATS.join("|")}`, "mp4")
660
- .option("--workers <n>", "Capture workers (1-16, default 1)", "1")
661
- .option("--dry-run", "Preview parameters without rendering")
662
- .action(async (root, options) => {
663
- const fps = validateFps(options.fps);
664
- const quality = validateQuality(options.quality);
665
- const format = validateFormat(options.format);
666
- const workers = validateWorkers(options.workers);
667
- const projectDir = resolve(options.project);
668
- if (options.dryRun) {
669
- outputResult({
670
- dryRun: true,
671
- command: "scene render",
672
- params: {
673
- projectDir,
674
- root,
675
- output: options.out,
676
- fps,
677
- quality,
678
- format,
679
- workers,
680
- },
681
- });
682
- return;
683
- }
684
- const spinner = isJsonMode() ? null : ora("Rendering scene project...").start();
685
- const result = await executeSceneRender({
686
- projectDir,
687
- root,
688
- output: options.out,
689
- fps,
690
- quality,
691
- format,
692
- workers,
693
- onProgress: (pct, stage) => {
694
- if (spinner)
695
- spinner.text = `Rendering [${Math.round(pct * 100)}%] ${stage}`;
696
- },
697
- });
698
- if (!result.success) {
699
- spinner?.fail("Render failed");
700
- if (isJsonMode()) {
701
- outputResult({ command: "scene render", ...result });
702
- process.exit(1);
703
- }
704
- exitWithError(generalError(result.error ?? "Render failed"));
705
- }
706
- if (isJsonMode()) {
707
- outputResult({ command: "scene render", ...result });
708
- return;
709
- }
710
- spinner?.succeed(chalk.green(`Render complete: ${result.outputPath}`));
711
- console.log();
712
- console.log(chalk.bold.cyan("Render"));
713
- console.log(chalk.dim("─".repeat(60)));
714
- console.log(` output ${chalk.bold(result.outputPath)}`);
715
- console.log(` duration ${(((result.durationMs ?? 0) / 1000)).toFixed(1)}s`);
716
- console.log(` frames ${result.framesRendered ?? "?"}${result.totalFrames ? ` / ${result.totalFrames}` : ""}`);
717
- console.log(` config ${result.fps}fps · ${result.quality} · ${result.format}`);
718
- });
719
- //# sourceMappingURL=scene.js.map