@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,728 +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
- if (result.audioCount && result.audioCount > 0) {
719
- const muxStatus = result.audioMuxApplied
720
- ? chalk.green(`✓ ${result.audioCount} track${result.audioCount === 1 ? "" : "s"} muxed`)
721
- : chalk.yellow(`⚠ ${result.audioCount} track${result.audioCount === 1 ? "" : "s"} skipped`);
722
- console.log(` audio ${muxStatus}`);
723
- if (result.audioMuxWarning) {
724
- console.log(chalk.dim(` ${result.audioMuxWarning}`));
725
- }
726
- }
727
- });
728
- //# sourceMappingURL=scene.js.map