@vibeframe/cli 0.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (420) hide show
  1. package/.turbo/turbo-build.log +4 -0
  2. package/.turbo/turbo-lint.log +21 -0
  3. package/.turbo/turbo-test.log +689 -0
  4. package/dist/agent/adapters/claude.d.ts +15 -0
  5. package/dist/agent/adapters/claude.d.ts.map +1 -0
  6. package/dist/agent/adapters/claude.js +119 -0
  7. package/dist/agent/adapters/claude.js.map +1 -0
  8. package/dist/agent/adapters/gemini.d.ts +15 -0
  9. package/dist/agent/adapters/gemini.d.ts.map +1 -0
  10. package/dist/agent/adapters/gemini.js +132 -0
  11. package/dist/agent/adapters/gemini.js.map +1 -0
  12. package/dist/agent/adapters/index.d.ts +27 -0
  13. package/dist/agent/adapters/index.d.ts.map +1 -0
  14. package/dist/agent/adapters/index.js +38 -0
  15. package/dist/agent/adapters/index.js.map +1 -0
  16. package/dist/agent/adapters/ollama.d.ts +20 -0
  17. package/dist/agent/adapters/ollama.d.ts.map +1 -0
  18. package/dist/agent/adapters/ollama.js +186 -0
  19. package/dist/agent/adapters/ollama.js.map +1 -0
  20. package/dist/agent/adapters/openai.d.ts +15 -0
  21. package/dist/agent/adapters/openai.d.ts.map +1 -0
  22. package/dist/agent/adapters/openai.js +92 -0
  23. package/dist/agent/adapters/openai.js.map +1 -0
  24. package/dist/agent/adapters/xai.d.ts +15 -0
  25. package/dist/agent/adapters/xai.d.ts.map +1 -0
  26. package/dist/agent/adapters/xai.js +95 -0
  27. package/dist/agent/adapters/xai.js.map +1 -0
  28. package/dist/agent/index.d.ts +69 -0
  29. package/dist/agent/index.d.ts.map +1 -0
  30. package/dist/agent/index.js +180 -0
  31. package/dist/agent/index.js.map +1 -0
  32. package/dist/agent/memory/index.d.ts +70 -0
  33. package/dist/agent/memory/index.d.ts.map +1 -0
  34. package/dist/agent/memory/index.js +132 -0
  35. package/dist/agent/memory/index.js.map +1 -0
  36. package/dist/agent/prompts/system.d.ts +6 -0
  37. package/dist/agent/prompts/system.d.ts.map +1 -0
  38. package/dist/agent/prompts/system.js +103 -0
  39. package/dist/agent/prompts/system.js.map +1 -0
  40. package/dist/agent/tools/ai-editing.d.ts +15 -0
  41. package/dist/agent/tools/ai-editing.d.ts.map +1 -0
  42. package/dist/agent/tools/ai-editing.js +763 -0
  43. package/dist/agent/tools/ai-editing.js.map +1 -0
  44. package/dist/agent/tools/ai-generation.d.ts +13 -0
  45. package/dist/agent/tools/ai-generation.d.ts.map +1 -0
  46. package/dist/agent/tools/ai-generation.js +973 -0
  47. package/dist/agent/tools/ai-generation.js.map +1 -0
  48. package/dist/agent/tools/ai-pipeline.d.ts +14 -0
  49. package/dist/agent/tools/ai-pipeline.d.ts.map +1 -0
  50. package/dist/agent/tools/ai-pipeline.js +961 -0
  51. package/dist/agent/tools/ai-pipeline.js.map +1 -0
  52. package/dist/agent/tools/ai.d.ts +13 -0
  53. package/dist/agent/tools/ai.d.ts.map +1 -0
  54. package/dist/agent/tools/ai.js +19 -0
  55. package/dist/agent/tools/ai.js.map +1 -0
  56. package/dist/agent/tools/batch.d.ts +6 -0
  57. package/dist/agent/tools/batch.d.ts.map +1 -0
  58. package/dist/agent/tools/batch.js +383 -0
  59. package/dist/agent/tools/batch.js.map +1 -0
  60. package/dist/agent/tools/e2e.test.d.ts +26 -0
  61. package/dist/agent/tools/e2e.test.d.ts.map +1 -0
  62. package/dist/agent/tools/e2e.test.js +397 -0
  63. package/dist/agent/tools/e2e.test.js.map +1 -0
  64. package/dist/agent/tools/export.d.ts +6 -0
  65. package/dist/agent/tools/export.d.ts.map +1 -0
  66. package/dist/agent/tools/export.js +171 -0
  67. package/dist/agent/tools/export.js.map +1 -0
  68. package/dist/agent/tools/filesystem.d.ts +6 -0
  69. package/dist/agent/tools/filesystem.d.ts.map +1 -0
  70. package/dist/agent/tools/filesystem.js +212 -0
  71. package/dist/agent/tools/filesystem.js.map +1 -0
  72. package/dist/agent/tools/index.d.ts +65 -0
  73. package/dist/agent/tools/index.d.ts.map +1 -0
  74. package/dist/agent/tools/index.js +120 -0
  75. package/dist/agent/tools/index.js.map +1 -0
  76. package/dist/agent/tools/integration.test.d.ts +11 -0
  77. package/dist/agent/tools/integration.test.d.ts.map +1 -0
  78. package/dist/agent/tools/integration.test.js +659 -0
  79. package/dist/agent/tools/integration.test.js.map +1 -0
  80. package/dist/agent/tools/media.d.ts +6 -0
  81. package/dist/agent/tools/media.d.ts.map +1 -0
  82. package/dist/agent/tools/media.js +616 -0
  83. package/dist/agent/tools/media.js.map +1 -0
  84. package/dist/agent/tools/project.d.ts +6 -0
  85. package/dist/agent/tools/project.d.ts.map +1 -0
  86. package/dist/agent/tools/project.js +284 -0
  87. package/dist/agent/tools/project.js.map +1 -0
  88. package/dist/agent/tools/timeline.d.ts +6 -0
  89. package/dist/agent/tools/timeline.d.ts.map +1 -0
  90. package/dist/agent/tools/timeline.js +873 -0
  91. package/dist/agent/tools/timeline.js.map +1 -0
  92. package/dist/agent/types.d.ts +59 -0
  93. package/dist/agent/types.d.ts.map +1 -0
  94. package/dist/agent/types.js +5 -0
  95. package/dist/agent/types.js.map +1 -0
  96. package/dist/commands/agent.d.ts +21 -0
  97. package/dist/commands/agent.d.ts.map +1 -0
  98. package/dist/commands/agent.js +290 -0
  99. package/dist/commands/agent.js.map +1 -0
  100. package/dist/commands/ai-analyze.d.ts +106 -0
  101. package/dist/commands/ai-analyze.d.ts.map +1 -0
  102. package/dist/commands/ai-analyze.js +327 -0
  103. package/dist/commands/ai-analyze.js.map +1 -0
  104. package/dist/commands/ai-animated-caption.d.ts +64 -0
  105. package/dist/commands/ai-animated-caption.d.ts.map +1 -0
  106. package/dist/commands/ai-animated-caption.js +272 -0
  107. package/dist/commands/ai-animated-caption.js.map +1 -0
  108. package/dist/commands/ai-audio.d.ts +20 -0
  109. package/dist/commands/ai-audio.d.ts.map +1 -0
  110. package/dist/commands/ai-audio.js +808 -0
  111. package/dist/commands/ai-audio.js.map +1 -0
  112. package/dist/commands/ai-broll.d.ts +15 -0
  113. package/dist/commands/ai-broll.d.ts.map +1 -0
  114. package/dist/commands/ai-broll.js +406 -0
  115. package/dist/commands/ai-broll.js.map +1 -0
  116. package/dist/commands/ai-edit-cli.d.ts +14 -0
  117. package/dist/commands/ai-edit-cli.d.ts.map +1 -0
  118. package/dist/commands/ai-edit-cli.js +579 -0
  119. package/dist/commands/ai-edit-cli.js.map +1 -0
  120. package/dist/commands/ai-edit.d.ts +398 -0
  121. package/dist/commands/ai-edit.d.ts.map +1 -0
  122. package/dist/commands/ai-edit.js +1019 -0
  123. package/dist/commands/ai-edit.js.map +1 -0
  124. package/dist/commands/ai-fill-gaps.d.ts +14 -0
  125. package/dist/commands/ai-fill-gaps.d.ts.map +1 -0
  126. package/dist/commands/ai-fill-gaps.js +451 -0
  127. package/dist/commands/ai-fill-gaps.js.map +1 -0
  128. package/dist/commands/ai-helpers.d.ts +20 -0
  129. package/dist/commands/ai-helpers.d.ts.map +1 -0
  130. package/dist/commands/ai-helpers.js +59 -0
  131. package/dist/commands/ai-helpers.js.map +1 -0
  132. package/dist/commands/ai-highlights.d.ts +127 -0
  133. package/dist/commands/ai-highlights.d.ts.map +1 -0
  134. package/dist/commands/ai-highlights.js +1026 -0
  135. package/dist/commands/ai-highlights.js.map +1 -0
  136. package/dist/commands/ai-image.d.ts +34 -0
  137. package/dist/commands/ai-image.d.ts.map +1 -0
  138. package/dist/commands/ai-image.js +653 -0
  139. package/dist/commands/ai-image.js.map +1 -0
  140. package/dist/commands/ai-motion.d.ts +50 -0
  141. package/dist/commands/ai-motion.d.ts.map +1 -0
  142. package/dist/commands/ai-motion.js +271 -0
  143. package/dist/commands/ai-motion.js.map +1 -0
  144. package/dist/commands/ai-narrate.d.ts +66 -0
  145. package/dist/commands/ai-narrate.d.ts.map +1 -0
  146. package/dist/commands/ai-narrate.js +329 -0
  147. package/dist/commands/ai-narrate.js.map +1 -0
  148. package/dist/commands/ai-review.d.ts +57 -0
  149. package/dist/commands/ai-review.d.ts.map +1 -0
  150. package/dist/commands/ai-review.js +251 -0
  151. package/dist/commands/ai-review.js.map +1 -0
  152. package/dist/commands/ai-script-pipeline-cli.d.ts +9 -0
  153. package/dist/commands/ai-script-pipeline-cli.d.ts.map +1 -0
  154. package/dist/commands/ai-script-pipeline-cli.js +1494 -0
  155. package/dist/commands/ai-script-pipeline-cli.js.map +1 -0
  156. package/dist/commands/ai-script-pipeline.d.ts +259 -0
  157. package/dist/commands/ai-script-pipeline.d.ts.map +1 -0
  158. package/dist/commands/ai-script-pipeline.js +1027 -0
  159. package/dist/commands/ai-script-pipeline.js.map +1 -0
  160. package/dist/commands/ai-suggest-edit.d.ts +14 -0
  161. package/dist/commands/ai-suggest-edit.d.ts.map +1 -0
  162. package/dist/commands/ai-suggest-edit.js +220 -0
  163. package/dist/commands/ai-suggest-edit.js.map +1 -0
  164. package/dist/commands/ai-video-fx.d.ts +14 -0
  165. package/dist/commands/ai-video-fx.d.ts.map +1 -0
  166. package/dist/commands/ai-video-fx.js +395 -0
  167. package/dist/commands/ai-video-fx.js.map +1 -0
  168. package/dist/commands/ai-video.d.ts +15 -0
  169. package/dist/commands/ai-video.d.ts.map +1 -0
  170. package/dist/commands/ai-video.js +785 -0
  171. package/dist/commands/ai-video.js.map +1 -0
  172. package/dist/commands/ai-viral.d.ts +15 -0
  173. package/dist/commands/ai-viral.d.ts.map +1 -0
  174. package/dist/commands/ai-viral.js +519 -0
  175. package/dist/commands/ai-viral.js.map +1 -0
  176. package/dist/commands/ai-visual-fx.d.ts +14 -0
  177. package/dist/commands/ai-visual-fx.d.ts.map +1 -0
  178. package/dist/commands/ai-visual-fx.js +505 -0
  179. package/dist/commands/ai-visual-fx.js.map +1 -0
  180. package/dist/commands/ai.d.ts +38 -0
  181. package/dist/commands/ai.d.ts.map +1 -0
  182. package/dist/commands/ai.js +225 -0
  183. package/dist/commands/ai.js.map +1 -0
  184. package/dist/commands/ai.test.d.ts +2 -0
  185. package/dist/commands/ai.test.d.ts.map +1 -0
  186. package/dist/commands/ai.test.js +554 -0
  187. package/dist/commands/ai.test.js.map +1 -0
  188. package/dist/commands/analyze.d.ts +16 -0
  189. package/dist/commands/analyze.d.ts.map +1 -0
  190. package/dist/commands/analyze.js +247 -0
  191. package/dist/commands/analyze.js.map +1 -0
  192. package/dist/commands/audio.d.ts +18 -0
  193. package/dist/commands/audio.d.ts.map +1 -0
  194. package/dist/commands/audio.js +539 -0
  195. package/dist/commands/audio.js.map +1 -0
  196. package/dist/commands/batch.d.ts +3 -0
  197. package/dist/commands/batch.d.ts.map +1 -0
  198. package/dist/commands/batch.js +366 -0
  199. package/dist/commands/batch.js.map +1 -0
  200. package/dist/commands/batch.test.d.ts +2 -0
  201. package/dist/commands/batch.test.d.ts.map +1 -0
  202. package/dist/commands/batch.test.js +203 -0
  203. package/dist/commands/batch.test.js.map +1 -0
  204. package/dist/commands/detect.d.ts +3 -0
  205. package/dist/commands/detect.d.ts.map +1 -0
  206. package/dist/commands/detect.js +273 -0
  207. package/dist/commands/detect.js.map +1 -0
  208. package/dist/commands/doctor.d.ts +6 -0
  209. package/dist/commands/doctor.d.ts.map +1 -0
  210. package/dist/commands/doctor.js +191 -0
  211. package/dist/commands/doctor.js.map +1 -0
  212. package/dist/commands/edit-cmd.d.ts +26 -0
  213. package/dist/commands/edit-cmd.d.ts.map +1 -0
  214. package/dist/commands/edit-cmd.js +870 -0
  215. package/dist/commands/edit-cmd.js.map +1 -0
  216. package/dist/commands/export.d.ts +39 -0
  217. package/dist/commands/export.d.ts.map +1 -0
  218. package/dist/commands/export.js +730 -0
  219. package/dist/commands/export.js.map +1 -0
  220. package/dist/commands/generate.d.ts +25 -0
  221. package/dist/commands/generate.d.ts.map +1 -0
  222. package/dist/commands/generate.js +1885 -0
  223. package/dist/commands/generate.js.map +1 -0
  224. package/dist/commands/media.d.ts +3 -0
  225. package/dist/commands/media.d.ts.map +1 -0
  226. package/dist/commands/media.js +165 -0
  227. package/dist/commands/media.js.map +1 -0
  228. package/dist/commands/output.d.ts +45 -0
  229. package/dist/commands/output.d.ts.map +1 -0
  230. package/dist/commands/output.js +122 -0
  231. package/dist/commands/output.js.map +1 -0
  232. package/dist/commands/pipeline.d.ts +19 -0
  233. package/dist/commands/pipeline.d.ts.map +1 -0
  234. package/dist/commands/pipeline.js +345 -0
  235. package/dist/commands/pipeline.js.map +1 -0
  236. package/dist/commands/project.d.ts +3 -0
  237. package/dist/commands/project.d.ts.map +1 -0
  238. package/dist/commands/project.js +139 -0
  239. package/dist/commands/project.js.map +1 -0
  240. package/dist/commands/project.test.d.ts +2 -0
  241. package/dist/commands/project.test.d.ts.map +1 -0
  242. package/dist/commands/project.test.js +105 -0
  243. package/dist/commands/project.test.js.map +1 -0
  244. package/dist/commands/sanitize.d.ts +21 -0
  245. package/dist/commands/sanitize.d.ts.map +1 -0
  246. package/dist/commands/sanitize.js +56 -0
  247. package/dist/commands/sanitize.js.map +1 -0
  248. package/dist/commands/schema.d.ts +11 -0
  249. package/dist/commands/schema.d.ts.map +1 -0
  250. package/dist/commands/schema.js +101 -0
  251. package/dist/commands/schema.js.map +1 -0
  252. package/dist/commands/setup.d.ts +6 -0
  253. package/dist/commands/setup.d.ts.map +1 -0
  254. package/dist/commands/setup.js +440 -0
  255. package/dist/commands/setup.js.map +1 -0
  256. package/dist/commands/timeline.d.ts +3 -0
  257. package/dist/commands/timeline.d.ts.map +1 -0
  258. package/dist/commands/timeline.js +469 -0
  259. package/dist/commands/timeline.js.map +1 -0
  260. package/dist/commands/timeline.test.d.ts +2 -0
  261. package/dist/commands/timeline.test.d.ts.map +1 -0
  262. package/dist/commands/timeline.test.js +320 -0
  263. package/dist/commands/timeline.test.js.map +1 -0
  264. package/dist/commands/validate.d.ts +32 -0
  265. package/dist/commands/validate.d.ts.map +1 -0
  266. package/dist/commands/validate.js +63 -0
  267. package/dist/commands/validate.js.map +1 -0
  268. package/dist/config/config.test.d.ts +2 -0
  269. package/dist/config/config.test.d.ts.map +1 -0
  270. package/dist/config/config.test.js +164 -0
  271. package/dist/config/config.test.js.map +1 -0
  272. package/dist/config/index.d.ts +35 -0
  273. package/dist/config/index.d.ts.map +1 -0
  274. package/dist/config/index.js +101 -0
  275. package/dist/config/index.js.map +1 -0
  276. package/dist/config/schema.d.ts +43 -0
  277. package/dist/config/schema.d.ts.map +1 -0
  278. package/dist/config/schema.js +42 -0
  279. package/dist/config/schema.js.map +1 -0
  280. package/dist/engine/index.d.ts +3 -0
  281. package/dist/engine/index.d.ts.map +1 -0
  282. package/dist/engine/index.js +2 -0
  283. package/dist/engine/index.js.map +1 -0
  284. package/dist/engine/project.d.ts +84 -0
  285. package/dist/engine/project.d.ts.map +1 -0
  286. package/dist/engine/project.js +355 -0
  287. package/dist/engine/project.js.map +1 -0
  288. package/dist/engine/project.test.d.ts +2 -0
  289. package/dist/engine/project.test.d.ts.map +1 -0
  290. package/dist/engine/project.test.js +599 -0
  291. package/dist/engine/project.test.js.map +1 -0
  292. package/dist/index.d.ts +7 -0
  293. package/dist/index.d.ts.map +1 -0
  294. package/dist/index.js +131 -0
  295. package/dist/index.js.map +1 -0
  296. package/dist/utils/api-key.d.ts +36 -0
  297. package/dist/utils/api-key.d.ts.map +1 -0
  298. package/dist/utils/api-key.js +211 -0
  299. package/dist/utils/api-key.js.map +1 -0
  300. package/dist/utils/api-key.test.d.ts +2 -0
  301. package/dist/utils/api-key.test.d.ts.map +1 -0
  302. package/dist/utils/api-key.test.js +35 -0
  303. package/dist/utils/api-key.test.js.map +1 -0
  304. package/dist/utils/audio.d.ts +23 -0
  305. package/dist/utils/audio.d.ts.map +1 -0
  306. package/dist/utils/audio.js +79 -0
  307. package/dist/utils/audio.js.map +1 -0
  308. package/dist/utils/exec-safe.d.ts +22 -0
  309. package/dist/utils/exec-safe.d.ts.map +1 -0
  310. package/dist/utils/exec-safe.js +62 -0
  311. package/dist/utils/exec-safe.js.map +1 -0
  312. package/dist/utils/first-run.d.ts +13 -0
  313. package/dist/utils/first-run.d.ts.map +1 -0
  314. package/dist/utils/first-run.js +48 -0
  315. package/dist/utils/first-run.js.map +1 -0
  316. package/dist/utils/provider-resolver.d.ts +15 -0
  317. package/dist/utils/provider-resolver.d.ts.map +1 -0
  318. package/dist/utils/provider-resolver.js +42 -0
  319. package/dist/utils/provider-resolver.js.map +1 -0
  320. package/dist/utils/remotion.d.ts +210 -0
  321. package/dist/utils/remotion.d.ts.map +1 -0
  322. package/dist/utils/remotion.js +731 -0
  323. package/dist/utils/remotion.js.map +1 -0
  324. package/dist/utils/subtitle.d.ts +65 -0
  325. package/dist/utils/subtitle.d.ts.map +1 -0
  326. package/dist/utils/subtitle.js +135 -0
  327. package/dist/utils/subtitle.js.map +1 -0
  328. package/dist/utils/subtitle.test.d.ts +2 -0
  329. package/dist/utils/subtitle.test.d.ts.map +1 -0
  330. package/dist/utils/subtitle.test.js +175 -0
  331. package/dist/utils/subtitle.test.js.map +1 -0
  332. package/dist/utils/tty.d.ts +45 -0
  333. package/dist/utils/tty.d.ts.map +1 -0
  334. package/dist/utils/tty.js +172 -0
  335. package/dist/utils/tty.js.map +1 -0
  336. package/package.json +102 -0
  337. package/src/agent/adapters/claude.ts +143 -0
  338. package/src/agent/adapters/gemini.ts +159 -0
  339. package/src/agent/adapters/index.ts +61 -0
  340. package/src/agent/adapters/ollama.ts +231 -0
  341. package/src/agent/adapters/openai.ts +116 -0
  342. package/src/agent/adapters/xai.ts +119 -0
  343. package/src/agent/index.ts +251 -0
  344. package/src/agent/memory/index.ts +151 -0
  345. package/src/agent/prompts/system.ts +106 -0
  346. package/src/agent/tools/ai-editing.ts +845 -0
  347. package/src/agent/tools/ai-generation.ts +1073 -0
  348. package/src/agent/tools/ai-pipeline.ts +1055 -0
  349. package/src/agent/tools/ai.ts +21 -0
  350. package/src/agent/tools/batch.ts +429 -0
  351. package/src/agent/tools/e2e.test.ts +545 -0
  352. package/src/agent/tools/export.ts +184 -0
  353. package/src/agent/tools/filesystem.ts +237 -0
  354. package/src/agent/tools/index.ts +150 -0
  355. package/src/agent/tools/integration.test.ts +775 -0
  356. package/src/agent/tools/media.ts +697 -0
  357. package/src/agent/tools/project.ts +313 -0
  358. package/src/agent/tools/timeline.ts +951 -0
  359. package/src/agent/types.ts +68 -0
  360. package/src/commands/agent.ts +340 -0
  361. package/src/commands/ai-analyze.ts +429 -0
  362. package/src/commands/ai-animated-caption.ts +390 -0
  363. package/src/commands/ai-audio.ts +941 -0
  364. package/src/commands/ai-broll.ts +490 -0
  365. package/src/commands/ai-edit-cli.ts +658 -0
  366. package/src/commands/ai-edit.ts +1542 -0
  367. package/src/commands/ai-fill-gaps.ts +566 -0
  368. package/src/commands/ai-helpers.ts +65 -0
  369. package/src/commands/ai-highlights.ts +1303 -0
  370. package/src/commands/ai-image.ts +761 -0
  371. package/src/commands/ai-motion.ts +347 -0
  372. package/src/commands/ai-narrate.ts +451 -0
  373. package/src/commands/ai-review.ts +309 -0
  374. package/src/commands/ai-script-pipeline-cli.ts +1710 -0
  375. package/src/commands/ai-script-pipeline.ts +1365 -0
  376. package/src/commands/ai-suggest-edit.ts +264 -0
  377. package/src/commands/ai-video-fx.ts +445 -0
  378. package/src/commands/ai-video.ts +915 -0
  379. package/src/commands/ai-viral.ts +595 -0
  380. package/src/commands/ai-visual-fx.ts +601 -0
  381. package/src/commands/ai.test.ts +627 -0
  382. package/src/commands/ai.ts +307 -0
  383. package/src/commands/analyze.ts +282 -0
  384. package/src/commands/audio.ts +644 -0
  385. package/src/commands/batch.test.ts +279 -0
  386. package/src/commands/batch.ts +440 -0
  387. package/src/commands/detect.ts +329 -0
  388. package/src/commands/doctor.ts +237 -0
  389. package/src/commands/edit-cmd.ts +1014 -0
  390. package/src/commands/export.ts +918 -0
  391. package/src/commands/generate.ts +2146 -0
  392. package/src/commands/media.ts +177 -0
  393. package/src/commands/output.ts +142 -0
  394. package/src/commands/pipeline.ts +398 -0
  395. package/src/commands/project.test.ts +127 -0
  396. package/src/commands/project.ts +149 -0
  397. package/src/commands/sanitize.ts +60 -0
  398. package/src/commands/schema.ts +130 -0
  399. package/src/commands/setup.ts +509 -0
  400. package/src/commands/timeline.test.ts +499 -0
  401. package/src/commands/timeline.ts +529 -0
  402. package/src/commands/validate.ts +77 -0
  403. package/src/config/config.test.ts +197 -0
  404. package/src/config/index.ts +125 -0
  405. package/src/config/schema.ts +82 -0
  406. package/src/engine/index.ts +2 -0
  407. package/src/engine/project.test.ts +702 -0
  408. package/src/engine/project.ts +439 -0
  409. package/src/index.ts +146 -0
  410. package/src/utils/api-key.test.ts +41 -0
  411. package/src/utils/api-key.ts +247 -0
  412. package/src/utils/audio.ts +83 -0
  413. package/src/utils/exec-safe.ts +75 -0
  414. package/src/utils/first-run.ts +52 -0
  415. package/src/utils/provider-resolver.ts +56 -0
  416. package/src/utils/remotion.ts +951 -0
  417. package/src/utils/subtitle.test.ts +227 -0
  418. package/src/utils/subtitle.ts +169 -0
  419. package/src/utils/tty.ts +196 -0
  420. package/tsconfig.json +20 -0
@@ -0,0 +1,227 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import {
3
+ detectFormat,
4
+ formatTranscript,
5
+ formatSRT,
6
+ formatVTT,
7
+ formatSRTTime,
8
+ formatVTTTime,
9
+ parseSRT,
10
+ } from "./subtitle.js";
11
+
12
+ describe("subtitle utilities", () => {
13
+ describe("detectFormat", () => {
14
+ it("detects SRT from file extension", () => {
15
+ expect(detectFormat("output.srt")).toBe("srt");
16
+ expect(detectFormat("video.SRT")).toBe("srt");
17
+ });
18
+
19
+ it("detects VTT from file extension", () => {
20
+ expect(detectFormat("output.vtt")).toBe("vtt");
21
+ expect(detectFormat("video.VTT")).toBe("vtt");
22
+ });
23
+
24
+ it("defaults to JSON for unknown extensions", () => {
25
+ expect(detectFormat("output.json")).toBe("json");
26
+ expect(detectFormat("output.txt")).toBe("json");
27
+ expect(detectFormat("output")).toBe("json");
28
+ });
29
+
30
+ it("uses explicit format over extension", () => {
31
+ expect(detectFormat("output.json", "srt")).toBe("srt");
32
+ expect(detectFormat("output.srt", "vtt")).toBe("vtt");
33
+ expect(detectFormat("output.vtt", "json")).toBe("json");
34
+ });
35
+ });
36
+
37
+ describe("formatSRTTime", () => {
38
+ it("formats zero", () => {
39
+ expect(formatSRTTime(0)).toBe("00:00:00,000");
40
+ });
41
+
42
+ it("formats seconds", () => {
43
+ expect(formatSRTTime(5.5)).toBe("00:00:05,500");
44
+ });
45
+
46
+ it("formats minutes", () => {
47
+ expect(formatSRTTime(65.25)).toBe("00:01:05,250");
48
+ });
49
+
50
+ it("formats hours", () => {
51
+ expect(formatSRTTime(3661.123)).toBe("01:01:01,123");
52
+ });
53
+ });
54
+
55
+ describe("formatVTTTime", () => {
56
+ it("formats zero", () => {
57
+ expect(formatVTTTime(0)).toBe("00:00:00.000");
58
+ });
59
+
60
+ it("formats seconds with period separator", () => {
61
+ expect(formatVTTTime(5.5)).toBe("00:00:05.500");
62
+ });
63
+
64
+ it("formats hours", () => {
65
+ expect(formatVTTTime(3661.123)).toBe("01:01:01.123");
66
+ });
67
+ });
68
+
69
+ describe("formatSRT", () => {
70
+ it("formats empty segments", () => {
71
+ expect(formatSRT([])).toBe("");
72
+ });
73
+
74
+ it("formats single segment", () => {
75
+ const segments = [
76
+ { startTime: 0, endTime: 2.5, text: "Hello world" },
77
+ ];
78
+
79
+ const result = formatSRT(segments);
80
+
81
+ expect(result).toBe(
82
+ "1\n00:00:00,000 --> 00:00:02,500\nHello world\n"
83
+ );
84
+ });
85
+
86
+ it("formats multiple segments", () => {
87
+ const segments = [
88
+ { startTime: 0, endTime: 2.5, text: "First line" },
89
+ { startTime: 2.5, endTime: 5.0, text: "Second line" },
90
+ ];
91
+
92
+ const result = formatSRT(segments);
93
+
94
+ expect(result).toContain("1\n00:00:00,000 --> 00:00:02,500\nFirst line\n");
95
+ expect(result).toContain("2\n00:00:02,500 --> 00:00:05,000\nSecond line\n");
96
+ });
97
+ });
98
+
99
+ describe("formatVTT", () => {
100
+ it("includes WEBVTT header", () => {
101
+ const result = formatVTT([]);
102
+ expect(result).toBe("WEBVTT\n\n");
103
+ });
104
+
105
+ it("formats segments with period separator", () => {
106
+ const segments = [
107
+ { startTime: 0, endTime: 2.5, text: "Hello world" },
108
+ ];
109
+
110
+ const result = formatVTT(segments);
111
+
112
+ expect(result).toBe(
113
+ "WEBVTT\n\n1\n00:00:00.000 --> 00:00:02.500\nHello world\n"
114
+ );
115
+ });
116
+ });
117
+
118
+ describe("formatTranscript", () => {
119
+ const mockResult = {
120
+ id: "test-id",
121
+ status: "completed",
122
+ fullText: "Hello world. This is a test.",
123
+ segments: [
124
+ { startTime: 0, endTime: 2.5, text: "Hello world." },
125
+ { startTime: 2.5, endTime: 5.0, text: "This is a test." },
126
+ ],
127
+ };
128
+
129
+ it("formats as JSON", () => {
130
+ const result = formatTranscript(mockResult, "json");
131
+ const parsed = JSON.parse(result);
132
+
133
+ expect(parsed.id).toBe("test-id");
134
+ expect(parsed.segments).toHaveLength(2);
135
+ });
136
+
137
+ it("formats as SRT", () => {
138
+ const result = formatTranscript(mockResult, "srt");
139
+
140
+ expect(result).toContain("00:00:00,000 --> 00:00:02,500");
141
+ expect(result).toContain("Hello world.");
142
+ expect(result).not.toContain("WEBVTT");
143
+ });
144
+
145
+ it("formats as VTT", () => {
146
+ const result = formatTranscript(mockResult, "vtt");
147
+
148
+ expect(result).toContain("WEBVTT");
149
+ expect(result).toContain("00:00:00.000 --> 00:00:02.500");
150
+ expect(result).toContain("Hello world.");
151
+ });
152
+
153
+ it("handles empty segments", () => {
154
+ const emptyResult = { id: "test", status: "completed" };
155
+
156
+ expect(formatTranscript(emptyResult, "srt")).toBe("");
157
+ expect(formatTranscript(emptyResult, "vtt")).toBe("WEBVTT\n\n");
158
+ });
159
+ });
160
+
161
+ describe("parseSRT", () => {
162
+ it("parses valid SRT content", () => {
163
+ const srt = `1
164
+ 00:00:00,000 --> 00:00:02,500
165
+ Hello world
166
+
167
+ 2
168
+ 00:00:02,500 --> 00:00:05,000
169
+ This is a test
170
+ `;
171
+ const segments = parseSRT(srt);
172
+
173
+ expect(segments).toHaveLength(2);
174
+ expect(segments[0].startTime).toBe(0);
175
+ expect(segments[0].endTime).toBe(2.5);
176
+ expect(segments[0].text).toBe("Hello world");
177
+ expect(segments[1].startTime).toBe(2.5);
178
+ expect(segments[1].endTime).toBe(5);
179
+ expect(segments[1].text).toBe("This is a test");
180
+ });
181
+
182
+ it("parses multi-line subtitle text", () => {
183
+ const srt = `1
184
+ 00:00:00,000 --> 00:00:03,000
185
+ First line
186
+ Second line
187
+ `;
188
+ const segments = parseSRT(srt);
189
+
190
+ expect(segments).toHaveLength(1);
191
+ expect(segments[0].text).toBe("First line\nSecond line");
192
+ });
193
+
194
+ it("returns empty array for empty content", () => {
195
+ expect(parseSRT("")).toHaveLength(0);
196
+ expect(parseSRT(" \n \n ")).toHaveLength(0);
197
+ });
198
+
199
+ it("handles timestamps with hours", () => {
200
+ const srt = `1
201
+ 01:30:15,500 --> 02:00:00,000
202
+ Long video subtitle
203
+ `;
204
+ const segments = parseSRT(srt);
205
+
206
+ expect(segments).toHaveLength(1);
207
+ expect(segments[0].startTime).toBe(5415.5); // 1*3600 + 30*60 + 15 + 0.5
208
+ expect(segments[0].endTime).toBe(7200); // 2*3600
209
+ });
210
+
211
+ it("roundtrips with formatSRT", () => {
212
+ const original = [
213
+ { startTime: 0, endTime: 2.5, text: "Hello world" },
214
+ { startTime: 2.5, endTime: 5, text: "Second line" },
215
+ ];
216
+
217
+ const srtString = formatSRT(original);
218
+ const parsed = parseSRT(srtString);
219
+
220
+ expect(parsed).toHaveLength(2);
221
+ expect(parsed[0].text).toBe("Hello world");
222
+ expect(parsed[1].text).toBe("Second line");
223
+ expect(parsed[0].startTime).toBe(0);
224
+ expect(parsed[0].endTime).toBe(2.5);
225
+ });
226
+ });
227
+ });
@@ -0,0 +1,169 @@
1
+ /**
2
+ * Subtitle format utilities for SRT/VTT generation
3
+ */
4
+
5
+ export type SubtitleFormat = "json" | "srt" | "vtt";
6
+
7
+ export interface SubtitleSegment {
8
+ startTime: number;
9
+ endTime: number;
10
+ text: string;
11
+ }
12
+
13
+ export interface TranscriptResult {
14
+ id: string;
15
+ status: string;
16
+ fullText?: string;
17
+ segments?: SubtitleSegment[];
18
+ detectedLanguage?: string;
19
+ error?: string;
20
+ }
21
+
22
+ /**
23
+ * Detect subtitle format from file extension or explicit format option
24
+ */
25
+ export function detectFormat(outputPath: string, explicitFormat?: string): SubtitleFormat {
26
+ if (explicitFormat) {
27
+ const fmt = explicitFormat.toLowerCase();
28
+ if (fmt === "srt" || fmt === "vtt" || fmt === "json") {
29
+ return fmt;
30
+ }
31
+ }
32
+
33
+ const ext = outputPath.toLowerCase().split(".").pop();
34
+ if (ext === "srt") return "srt";
35
+ if (ext === "vtt") return "vtt";
36
+ return "json";
37
+ }
38
+
39
+ /**
40
+ * Format transcript result to the specified format
41
+ */
42
+ export function formatTranscript(result: TranscriptResult, format: SubtitleFormat): string {
43
+ if (format === "json") {
44
+ return JSON.stringify(result, null, 2);
45
+ }
46
+
47
+ const segments = result.segments || [];
48
+
49
+ if (format === "srt") {
50
+ return formatSRT(segments);
51
+ }
52
+
53
+ return formatVTT(segments);
54
+ }
55
+
56
+ /**
57
+ * Format segments as SRT (SubRip Subtitle)
58
+ *
59
+ * SRT Format:
60
+ * 1
61
+ * 00:00:00,000 --> 00:00:02,500
62
+ * Hello world
63
+ */
64
+ export function formatSRT(segments: SubtitleSegment[]): string {
65
+ return segments.map((seg, index) => {
66
+ const start = formatSRTTime(seg.startTime);
67
+ const end = formatSRTTime(seg.endTime);
68
+ return `${index + 1}\n${start} --> ${end}\n${seg.text}\n`;
69
+ }).join("\n");
70
+ }
71
+
72
+ /**
73
+ * Format segments as WebVTT (Web Video Text Tracks)
74
+ *
75
+ * VTT Format:
76
+ * WEBVTT
77
+ *
78
+ * 1
79
+ * 00:00:00.000 --> 00:00:02.500
80
+ * Hello world
81
+ */
82
+ export function formatVTT(segments: SubtitleSegment[]): string {
83
+ const header = "WEBVTT\n\n";
84
+ const cues = segments.map((seg, index) => {
85
+ const start = formatVTTTime(seg.startTime);
86
+ const end = formatVTTTime(seg.endTime);
87
+ return `${index + 1}\n${start} --> ${end}\n${seg.text}\n`;
88
+ }).join("\n");
89
+ return header + cues;
90
+ }
91
+
92
+ /**
93
+ * Format time for SRT (uses comma for milliseconds)
94
+ * Format: HH:MM:SS,mmm
95
+ */
96
+ export function formatSRTTime(seconds: number): string {
97
+ const hours = Math.floor(seconds / 3600);
98
+ const mins = Math.floor((seconds % 3600) / 60);
99
+ const secs = Math.floor(seconds % 60);
100
+ const ms = Math.round((seconds % 1) * 1000);
101
+
102
+ return `${pad(hours, 2)}:${pad(mins, 2)}:${pad(secs, 2)},${pad(ms, 3)}`;
103
+ }
104
+
105
+ /**
106
+ * Format time for VTT (uses period for milliseconds)
107
+ * Format: HH:MM:SS.mmm
108
+ */
109
+ export function formatVTTTime(seconds: number): string {
110
+ const hours = Math.floor(seconds / 3600);
111
+ const mins = Math.floor((seconds % 3600) / 60);
112
+ const secs = Math.floor(seconds % 60);
113
+ const ms = Math.round((seconds % 1) * 1000);
114
+
115
+ return `${pad(hours, 2)}:${pad(mins, 2)}:${pad(secs, 2)}.${pad(ms, 3)}`;
116
+ }
117
+
118
+ /**
119
+ * Parse SRT content into SubtitleSegment array
120
+ *
121
+ * Handles standard SRT format:
122
+ * 1
123
+ * 00:00:00,000 --> 00:00:02,500
124
+ * Hello world
125
+ */
126
+ export function parseSRT(content: string): SubtitleSegment[] {
127
+ const segments: SubtitleSegment[] = [];
128
+ const blocks = content.trim().split(/\n\s*\n/);
129
+
130
+ for (const block of blocks) {
131
+ const lines = block.trim().split("\n");
132
+ if (lines.length < 3) continue;
133
+
134
+ // Line 0: sequence number (skip)
135
+ // Line 1: timestamp line
136
+ const timeLine = lines[1].trim();
137
+ const timeMatch = timeLine.match(
138
+ /(\d{2}:\d{2}:\d{2}[,.]\d{3})\s*-->\s*(\d{2}:\d{2}:\d{2}[,.]\d{3})/,
139
+ );
140
+ if (!timeMatch) continue;
141
+
142
+ const startTime = parseSRTTimestamp(timeMatch[1]);
143
+ const endTime = parseSRTTimestamp(timeMatch[2]);
144
+ // Lines 2+: subtitle text (may be multi-line)
145
+ const text = lines.slice(2).join("\n").trim();
146
+
147
+ if (text) {
148
+ segments.push({ startTime, endTime, text });
149
+ }
150
+ }
151
+
152
+ return segments;
153
+ }
154
+
155
+ function parseSRTTimestamp(timestamp: string): number {
156
+ // Accept both comma (SRT) and period (VTT) as ms separator
157
+ const normalized = timestamp.replace(",", ".");
158
+ const parts = normalized.split(":");
159
+ const hours = parseInt(parts[0], 10);
160
+ const mins = parseInt(parts[1], 10);
161
+ const secParts = parts[2].split(".");
162
+ const secs = parseInt(secParts[0], 10);
163
+ const ms = parseInt(secParts[1], 10);
164
+ return hours * 3600 + mins * 60 + secs + ms / 1000;
165
+ }
166
+
167
+ function pad(num: number, size: number): string {
168
+ return num.toString().padStart(size, "0");
169
+ }
@@ -0,0 +1,196 @@
1
+ /**
2
+ * TTY Input Utilities
3
+ * Handles stdin fallback to /dev/tty for piped environments
4
+ */
5
+
6
+ import { createInterface, Interface } from "node:readline";
7
+ import { ReadStream } from "node:tty";
8
+
9
+ let ttyStream: ReadStream | null = null;
10
+
11
+ /**
12
+ * Get a TTY-capable input stream
13
+ * Falls back to /dev/tty when stdin is piped (e.g., from curl)
14
+ */
15
+ export function getTTYInputStream(): typeof process.stdin | ReadStream {
16
+ if (process.stdin.isTTY) {
17
+ return process.stdin;
18
+ }
19
+
20
+ // stdin is not a TTY (piped), open /dev/tty directly
21
+ if (!ttyStream) {
22
+ try {
23
+ // Open /dev/tty as a TTY stream
24
+ const fd = require("fs").openSync("/dev/tty", "r");
25
+ ttyStream = new ReadStream(fd);
26
+ } catch {
27
+ // Fallback to stdin if /dev/tty is not available
28
+ console.warn("Warning: Cannot open /dev/tty, interactive input may not work");
29
+ return process.stdin;
30
+ }
31
+ }
32
+ return ttyStream;
33
+ }
34
+
35
+ /**
36
+ * Check if we have TTY input available
37
+ */
38
+ export function hasTTY(): boolean {
39
+ if (process.stdin.isTTY) return true;
40
+
41
+ // Try to actually open /dev/tty to verify it's accessible
42
+ try {
43
+ const fs = require("fs");
44
+ const fd = fs.openSync("/dev/tty", "r");
45
+ fs.closeSync(fd);
46
+ return true;
47
+ } catch {
48
+ return false;
49
+ }
50
+ }
51
+
52
+ /**
53
+ * Close the TTY stream if we opened one
54
+ */
55
+ export function closeTTYStream(): void {
56
+ if (ttyStream) {
57
+ ttyStream.destroy();
58
+ ttyStream = null;
59
+ }
60
+ }
61
+
62
+ /**
63
+ * Create a readline interface with TTY support
64
+ */
65
+ export function createTTYInterface(options?: {
66
+ prompt?: string;
67
+ historySize?: number;
68
+ }): Interface {
69
+ const input = getTTYInputStream();
70
+ return createInterface({
71
+ input,
72
+ output: process.stdout,
73
+ terminal: true,
74
+ historySize: options?.historySize ?? 100,
75
+ prompt: options?.prompt ?? "> ",
76
+ });
77
+ }
78
+
79
+ /**
80
+ * Prompt for input (single line)
81
+ * Throws in non-TTY environments to prevent hanging.
82
+ */
83
+ export async function prompt(question: string): Promise<string> {
84
+ if (!hasTTY()) {
85
+ throw new Error(
86
+ "Interactive input required but no TTY available. " +
87
+ "Use command flags to provide values non-interactively."
88
+ );
89
+ }
90
+ const input = getTTYInputStream();
91
+ const rl = createInterface({
92
+ input,
93
+ output: process.stdout,
94
+ });
95
+
96
+ return new Promise((resolve) => {
97
+ rl.question(question, (answer) => {
98
+ rl.close();
99
+ resolve(answer);
100
+ });
101
+ });
102
+ }
103
+
104
+ /**
105
+ * Prompt for hidden input (password/API key)
106
+ * Characters are not echoed to terminal
107
+ */
108
+ export async function promptHidden(question: string): Promise<string> {
109
+ const input = getTTYInputStream() as ReadStream;
110
+
111
+ return new Promise((resolve) => {
112
+ process.stdout.write(question);
113
+
114
+ let value = "";
115
+
116
+ // Check if we can use raw mode
117
+ if (typeof input.setRawMode === "function") {
118
+ input.setRawMode(true);
119
+ input.resume();
120
+ input.setEncoding("utf8");
121
+
122
+ const onData = (char: string) => {
123
+ if (char === "\n" || char === "\r" || char === "\u0004") {
124
+ // Enter or EOF
125
+ input.setRawMode(false);
126
+ input.removeListener("data", onData);
127
+ process.stdout.write("\n");
128
+ resolve(value);
129
+ } else if (char === "\u0003") {
130
+ // Ctrl+C
131
+ input.setRawMode(false);
132
+ process.stdout.write("\n");
133
+ process.exit(1);
134
+ } else if (char === "\u007F" || char === "\b") {
135
+ // Backspace
136
+ if (value.length > 0) {
137
+ value = value.slice(0, -1);
138
+ // Clear character from display
139
+ process.stdout.write("\b \b");
140
+ }
141
+ } else if (char >= " ") {
142
+ // Printable character (may be multiple chars when pasting)
143
+ value += char;
144
+ process.stdout.write("*".repeat(char.length)); // Show asterisk for each char
145
+ }
146
+ };
147
+
148
+ input.on("data", onData);
149
+ } else {
150
+ // Fallback: no raw mode available, input will be visible
151
+ const rl = createInterface({ input, output: process.stdout });
152
+ rl.question("", (answer) => {
153
+ rl.close();
154
+ resolve(answer);
155
+ });
156
+ }
157
+ });
158
+ }
159
+
160
+ /**
161
+ * Prompt for selection from a list (1-based index)
162
+ */
163
+ export async function promptSelect(
164
+ question: string,
165
+ options: string[],
166
+ defaultIndex = 0
167
+ ): Promise<number> {
168
+ // Display options
169
+ for (let i = 0; i < options.length; i++) {
170
+ const marker = i === defaultIndex ? "→" : " ";
171
+ console.log(` ${marker} ${i + 1}. ${options[i]}`);
172
+ }
173
+ console.log();
174
+
175
+ const answer = await prompt(question);
176
+ const index = parseInt(answer, 10) - 1;
177
+
178
+ if (isNaN(index) || index < 0 || index >= options.length) {
179
+ return defaultIndex;
180
+ }
181
+ return index;
182
+ }
183
+
184
+ /**
185
+ * Prompt for yes/no confirmation
186
+ */
187
+ export async function promptConfirm(
188
+ question: string,
189
+ defaultYes = true
190
+ ): Promise<boolean> {
191
+ const hint = defaultYes ? "(Y/n)" : "(y/N)";
192
+ const answer = await prompt(`${question} ${hint}: `);
193
+
194
+ if (answer === "") return defaultYes;
195
+ return answer.toLowerCase().startsWith("y");
196
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,20 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "Bundler",
6
+ "lib": ["ES2022"],
7
+ "outDir": "./dist",
8
+ "rootDir": "./src",
9
+ "strict": true,
10
+ "esModuleInterop": true,
11
+ "skipLibCheck": true,
12
+ "forceConsistentCasingInFileNames": true,
13
+ "declaration": true,
14
+ "declarationMap": true,
15
+ "sourceMap": true,
16
+ "resolveJsonModule": true
17
+ },
18
+ "include": ["src/**/*"],
19
+ "exclude": ["node_modules", "dist"]
20
+ }