@kenkaiiii/gg-editor 0.7.0 → 0.7.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 (446) hide show
  1. package/dist/cli.js +64 -1
  2. package/dist/cli.js.map +1 -1
  3. package/dist/core/audio-mix.d.ts.map +1 -1
  4. package/dist/core/audio-mix.js +8 -1
  5. package/dist/core/audio-mix.js.map +1 -1
  6. package/dist/core/audio-mix.test.js +1 -1
  7. package/dist/core/audio-mix.test.js.map +1 -1
  8. package/dist/core/auth/api-keys.d.ts +1 -1
  9. package/dist/core/auth/api-keys.d.ts.map +1 -1
  10. package/dist/core/auth/api-keys.js +2 -1
  11. package/dist/core/auth/api-keys.js.map +1 -1
  12. package/dist/core/auth/login.d.ts.map +1 -1
  13. package/dist/core/auth/login.js.map +1 -1
  14. package/dist/core/beats.d.ts +59 -0
  15. package/dist/core/beats.d.ts.map +1 -0
  16. package/dist/core/beats.js +122 -0
  17. package/dist/core/beats.js.map +1 -0
  18. package/dist/core/beats.test.d.ts +2 -0
  19. package/dist/core/beats.test.d.ts.map +1 -0
  20. package/dist/core/beats.test.js +86 -0
  21. package/dist/core/beats.test.js.map +1 -0
  22. package/dist/core/brand-kit.d.ts +80 -0
  23. package/dist/core/brand-kit.d.ts.map +1 -0
  24. package/dist/core/brand-kit.js +96 -0
  25. package/dist/core/brand-kit.js.map +1 -0
  26. package/dist/core/brand-kit.test.d.ts +2 -0
  27. package/dist/core/brand-kit.test.d.ts.map +1 -0
  28. package/dist/core/brand-kit.test.js +76 -0
  29. package/dist/core/brand-kit.test.js.map +1 -0
  30. package/dist/core/bundled-sfx.d.ts +64 -0
  31. package/dist/core/bundled-sfx.d.ts.map +1 -0
  32. package/dist/core/bundled-sfx.js +218 -0
  33. package/dist/core/bundled-sfx.js.map +1 -0
  34. package/dist/core/bundled-sfx.test.d.ts +2 -0
  35. package/dist/core/bundled-sfx.test.d.ts.map +1 -0
  36. package/dist/core/bundled-sfx.test.js +81 -0
  37. package/dist/core/bundled-sfx.test.js.map +1 -0
  38. package/dist/core/child-abort.d.ts +57 -0
  39. package/dist/core/child-abort.d.ts.map +1 -0
  40. package/dist/core/child-abort.js +95 -0
  41. package/dist/core/child-abort.js.map +1 -0
  42. package/dist/core/child-abort.test.d.ts +2 -0
  43. package/dist/core/child-abort.test.d.ts.map +1 -0
  44. package/dist/core/child-abort.test.js +88 -0
  45. package/dist/core/child-abort.test.js.map +1 -0
  46. package/dist/core/clip-scoring.d.ts +44 -0
  47. package/dist/core/clip-scoring.d.ts.map +1 -0
  48. package/dist/core/clip-scoring.js +165 -0
  49. package/dist/core/clip-scoring.js.map +1 -0
  50. package/dist/core/clip-scoring.test.d.ts +2 -0
  51. package/dist/core/clip-scoring.test.d.ts.map +1 -0
  52. package/dist/core/clip-scoring.test.js +113 -0
  53. package/dist/core/clip-scoring.test.js.map +1 -0
  54. package/dist/core/emoji-captions.d.ts +45 -0
  55. package/dist/core/emoji-captions.d.ts.map +1 -0
  56. package/dist/core/emoji-captions.js +121 -0
  57. package/dist/core/emoji-captions.js.map +1 -0
  58. package/dist/core/face-reframe.d.ts +91 -0
  59. package/dist/core/face-reframe.d.ts.map +1 -0
  60. package/dist/core/face-reframe.js +141 -0
  61. package/dist/core/face-reframe.js.map +1 -0
  62. package/dist/core/face-reframe.test.d.ts +2 -0
  63. package/dist/core/face-reframe.test.d.ts.map +1 -0
  64. package/dist/core/face-reframe.test.js +171 -0
  65. package/dist/core/face-reframe.test.js.map +1 -0
  66. package/dist/core/filler-words.d.ts +57 -9
  67. package/dist/core/filler-words.d.ts.map +1 -1
  68. package/dist/core/filler-words.js +61 -9
  69. package/dist/core/filler-words.js.map +1 -1
  70. package/dist/core/filler-words.test.js +91 -17
  71. package/dist/core/filler-words.test.js.map +1 -1
  72. package/dist/core/hook-rewrite.d.ts +48 -0
  73. package/dist/core/hook-rewrite.d.ts.map +1 -0
  74. package/dist/core/hook-rewrite.js +151 -0
  75. package/dist/core/hook-rewrite.js.map +1 -0
  76. package/dist/core/hook-rewrite.test.d.ts +2 -0
  77. package/dist/core/hook-rewrite.test.d.ts.map +1 -0
  78. package/dist/core/hook-rewrite.test.js +58 -0
  79. package/dist/core/hook-rewrite.test.js.map +1 -0
  80. package/dist/core/hosts/lazy.d.ts.map +1 -1
  81. package/dist/core/hosts/lazy.js +2 -0
  82. package/dist/core/hosts/lazy.js.map +1 -1
  83. package/dist/core/hosts/premiere/adapter.d.ts +1 -0
  84. package/dist/core/hosts/premiere/adapter.d.ts.map +1 -1
  85. package/dist/core/hosts/premiere/adapter.js.map +1 -1
  86. package/dist/core/hosts/premiere/bridge-source.d.ts.map +1 -1
  87. package/dist/core/hosts/premiere/bridge-source.js +6 -3
  88. package/dist/core/hosts/premiere/bridge-source.js.map +1 -1
  89. package/dist/core/hosts/resolve/adapter.d.ts +1 -0
  90. package/dist/core/hosts/resolve/adapter.d.ts.map +1 -1
  91. package/dist/core/hosts/resolve/adapter.js.map +1 -1
  92. package/dist/core/hosts/resolve/bridge-source.d.ts.map +1 -1
  93. package/dist/core/hosts/resolve/bridge-source.js +31 -4
  94. package/dist/core/hosts/resolve/bridge-source.js.map +1 -1
  95. package/dist/core/hosts/resolve/bridge.d.ts +2 -19
  96. package/dist/core/hosts/resolve/bridge.d.ts.map +1 -1
  97. package/dist/core/hosts/resolve/bridge.js +70 -41
  98. package/dist/core/hosts/resolve/bridge.js.map +1 -1
  99. package/dist/core/hosts/resolve/bridge.test.js +130 -0
  100. package/dist/core/hosts/resolve/bridge.test.js.map +1 -1
  101. package/dist/core/hosts/types.d.ts +6 -0
  102. package/dist/core/hosts/types.d.ts.map +1 -1
  103. package/dist/core/hosts/types.js.map +1 -1
  104. package/dist/core/logger.d.ts +32 -0
  105. package/dist/core/logger.d.ts.map +1 -0
  106. package/dist/core/logger.js +188 -0
  107. package/dist/core/logger.js.map +1 -0
  108. package/dist/core/loop-match.d.ts +57 -0
  109. package/dist/core/loop-match.d.ts.map +1 -0
  110. package/dist/core/loop-match.js +91 -0
  111. package/dist/core/loop-match.js.map +1 -0
  112. package/dist/core/media/ffmpeg.d.ts.map +1 -1
  113. package/dist/core/media/ffmpeg.js +14 -3
  114. package/dist/core/media/ffmpeg.js.map +1 -1
  115. package/dist/core/multi-format.d.ts +67 -0
  116. package/dist/core/multi-format.d.ts.map +1 -0
  117. package/dist/core/multi-format.js +127 -0
  118. package/dist/core/multi-format.js.map +1 -0
  119. package/dist/core/multi-format.test.d.ts +2 -0
  120. package/dist/core/multi-format.test.d.ts.map +1 -0
  121. package/dist/core/multi-format.test.js +151 -0
  122. package/dist/core/multi-format.test.js.map +1 -0
  123. package/dist/core/python/beats.py +61 -0
  124. package/dist/core/python/face_reframe.py +163 -0
  125. package/dist/core/python/sidecar-path.d.ts +13 -0
  126. package/dist/core/python/sidecar-path.d.ts.map +1 -0
  127. package/dist/core/python/sidecar-path.js +24 -0
  128. package/dist/core/python/sidecar-path.js.map +1 -0
  129. package/dist/core/python.d.ts +57 -0
  130. package/dist/core/python.d.ts.map +1 -0
  131. package/dist/core/python.js +107 -0
  132. package/dist/core/python.js.map +1 -0
  133. package/dist/core/python.test.d.ts +2 -0
  134. package/dist/core/python.test.d.ts.map +1 -0
  135. package/dist/core/python.test.js +129 -0
  136. package/dist/core/python.test.js.map +1 -0
  137. package/dist/core/retention-structure.d.ts +81 -0
  138. package/dist/core/retention-structure.d.ts.map +1 -0
  139. package/dist/core/retention-structure.js +206 -0
  140. package/dist/core/retention-structure.js.map +1 -0
  141. package/dist/core/retention-structure.test.d.ts +2 -0
  142. package/dist/core/retention-structure.test.d.ts.map +1 -0
  143. package/dist/core/retention-structure.test.js +88 -0
  144. package/dist/core/retention-structure.test.js.map +1 -0
  145. package/dist/core/review.d.ts +17 -0
  146. package/dist/core/review.d.ts.map +1 -1
  147. package/dist/core/review.js +20 -24
  148. package/dist/core/review.js.map +1 -1
  149. package/dist/core/safe-paths.d.ts +11 -0
  150. package/dist/core/safe-paths.d.ts.map +1 -1
  151. package/dist/core/safe-paths.js +26 -10
  152. package/dist/core/safe-paths.js.map +1 -1
  153. package/dist/core/safe-paths.test.js +16 -0
  154. package/dist/core/safe-paths.test.js.map +1 -1
  155. package/dist/core/skills-loader.d.ts +48 -2
  156. package/dist/core/skills-loader.d.ts.map +1 -1
  157. package/dist/core/skills-loader.js +97 -19
  158. package/dist/core/skills-loader.js.map +1 -1
  159. package/dist/core/skills-loader.test.js +63 -1
  160. package/dist/core/skills-loader.test.js.map +1 -1
  161. package/dist/core/srt.d.ts +42 -7
  162. package/dist/core/srt.d.ts.map +1 -1
  163. package/dist/core/srt.js +101 -32
  164. package/dist/core/srt.js.map +1 -1
  165. package/dist/core/srt.test.js +54 -1
  166. package/dist/core/srt.test.js.map +1 -1
  167. package/dist/core/thumbnail-compose.d.ts +58 -0
  168. package/dist/core/thumbnail-compose.d.ts.map +1 -0
  169. package/dist/core/thumbnail-compose.js +101 -0
  170. package/dist/core/thumbnail-compose.js.map +1 -0
  171. package/dist/core/thumbnail-promise.d.ts +46 -0
  172. package/dist/core/thumbnail-promise.d.ts.map +1 -0
  173. package/dist/core/thumbnail-promise.js +133 -0
  174. package/dist/core/thumbnail-promise.js.map +1 -0
  175. package/dist/core/thumbnail-promise.test.d.ts +2 -0
  176. package/dist/core/thumbnail-promise.test.d.ts.map +1 -0
  177. package/dist/core/thumbnail-promise.test.js +52 -0
  178. package/dist/core/thumbnail-promise.test.js.map +1 -0
  179. package/dist/core/viral-moments.d.ts +70 -0
  180. package/dist/core/viral-moments.d.ts.map +1 -0
  181. package/dist/core/viral-moments.js +192 -0
  182. package/dist/core/viral-moments.js.map +1 -0
  183. package/dist/core/viral-moments.test.d.ts +2 -0
  184. package/dist/core/viral-moments.test.d.ts.map +1 -0
  185. package/dist/core/viral-moments.test.js +153 -0
  186. package/dist/core/viral-moments.test.js.map +1 -0
  187. package/dist/core/whisper.d.ts +16 -0
  188. package/dist/core/whisper.d.ts.map +1 -1
  189. package/dist/core/whisper.js +72 -5
  190. package/dist/core/whisper.js.map +1 -1
  191. package/dist/core/whisper.test.js +111 -1
  192. package/dist/core/whisper.test.js.map +1 -1
  193. package/dist/core/youtube-metadata.d.ts +44 -0
  194. package/dist/core/youtube-metadata.d.ts.map +1 -0
  195. package/dist/core/youtube-metadata.js +168 -0
  196. package/dist/core/youtube-metadata.js.map +1 -0
  197. package/dist/core/youtube-metadata.test.d.ts +2 -0
  198. package/dist/core/youtube-metadata.test.d.ts.map +1 -0
  199. package/dist/core/youtube-metadata.test.js +132 -0
  200. package/dist/core/youtube-metadata.test.js.map +1 -0
  201. package/dist/prompt-commands.d.ts +24 -0
  202. package/dist/prompt-commands.d.ts.map +1 -0
  203. package/dist/prompt-commands.js +243 -0
  204. package/dist/prompt-commands.js.map +1 -0
  205. package/dist/prompt-commands.test.d.ts +2 -0
  206. package/dist/prompt-commands.test.d.ts.map +1 -0
  207. package/dist/prompt-commands.test.js +46 -0
  208. package/dist/prompt-commands.test.js.map +1 -0
  209. package/dist/skills.d.ts +6 -6
  210. package/dist/skills.d.ts.map +1 -1
  211. package/dist/skills.js +1426 -445
  212. package/dist/skills.js.map +1 -1
  213. package/dist/system-prompt.d.ts.map +1 -1
  214. package/dist/system-prompt.js +108 -0
  215. package/dist/system-prompt.js.map +1 -1
  216. package/dist/tools/add-fades.d.ts.map +1 -1
  217. package/dist/tools/add-fades.js +2 -1
  218. package/dist/tools/add-fades.js.map +1 -1
  219. package/dist/tools/add-sfx-at-cuts.d.ts.map +1 -1
  220. package/dist/tools/add-sfx-at-cuts.js +36 -11
  221. package/dist/tools/add-sfx-at-cuts.js.map +1 -1
  222. package/dist/tools/add-sfx-to-timeline.d.ts +34 -0
  223. package/dist/tools/add-sfx-to-timeline.d.ts.map +1 -0
  224. package/dist/tools/add-sfx-to-timeline.js +169 -0
  225. package/dist/tools/add-sfx-to-timeline.js.map +1 -0
  226. package/dist/tools/add-sfx-to-timeline.test.d.ts +2 -0
  227. package/dist/tools/add-sfx-to-timeline.test.d.ts.map +1 -0
  228. package/dist/tools/add-sfx-to-timeline.test.js +181 -0
  229. package/dist/tools/add-sfx-to-timeline.test.js.map +1 -0
  230. package/dist/tools/audit-first-frame.d.ts +36 -0
  231. package/dist/tools/audit-first-frame.d.ts.map +1 -0
  232. package/dist/tools/audit-first-frame.js +181 -0
  233. package/dist/tools/audit-first-frame.js.map +1 -0
  234. package/dist/tools/audit-retention-structure.d.ts +20 -0
  235. package/dist/tools/audit-retention-structure.d.ts.map +1 -0
  236. package/dist/tools/audit-retention-structure.js +95 -0
  237. package/dist/tools/audit-retention-structure.js.map +1 -0
  238. package/dist/tools/audit-retention-structure.test.d.ts +2 -0
  239. package/dist/tools/audit-retention-structure.test.d.ts.map +1 -0
  240. package/dist/tools/audit-retention-structure.test.js +93 -0
  241. package/dist/tools/audit-retention-structure.test.js.map +1 -0
  242. package/dist/tools/bleep-words.d.ts +59 -0
  243. package/dist/tools/bleep-words.d.ts.map +1 -0
  244. package/dist/tools/bleep-words.js +211 -0
  245. package/dist/tools/bleep-words.js.map +1 -0
  246. package/dist/tools/bleep-words.test.d.ts +2 -0
  247. package/dist/tools/bleep-words.test.d.ts.map +1 -0
  248. package/dist/tools/bleep-words.test.js +96 -0
  249. package/dist/tools/bleep-words.test.js.map +1 -0
  250. package/dist/tools/burn-subtitles.d.ts.map +1 -1
  251. package/dist/tools/burn-subtitles.js +10 -5
  252. package/dist/tools/burn-subtitles.js.map +1 -1
  253. package/dist/tools/clean-audio.d.ts.map +1 -1
  254. package/dist/tools/clean-audio.js +2 -1
  255. package/dist/tools/clean-audio.js.map +1 -1
  256. package/dist/tools/cluster-takes.js +2 -1
  257. package/dist/tools/cluster-takes.js.map +1 -1
  258. package/dist/tools/compose-thumbnail-variants.d.ts +70 -0
  259. package/dist/tools/compose-thumbnail-variants.d.ts.map +1 -0
  260. package/dist/tools/compose-thumbnail-variants.js +274 -0
  261. package/dist/tools/compose-thumbnail-variants.js.map +1 -0
  262. package/dist/tools/compose-thumbnail.d.ts +6 -13
  263. package/dist/tools/compose-thumbnail.d.ts.map +1 -1
  264. package/dist/tools/compose-thumbnail.js +44 -81
  265. package/dist/tools/compose-thumbnail.js.map +1 -1
  266. package/dist/tools/concat-videos.d.ts.map +1 -1
  267. package/dist/tools/concat-videos.js +12 -5
  268. package/dist/tools/concat-videos.js.map +1 -1
  269. package/dist/tools/concat-videos.test.d.ts +2 -0
  270. package/dist/tools/concat-videos.test.d.ts.map +1 -0
  271. package/dist/tools/concat-videos.test.js +103 -0
  272. package/dist/tools/concat-videos.test.js.map +1 -0
  273. package/dist/tools/crossfade-videos.d.ts.map +1 -1
  274. package/dist/tools/crossfade-videos.js +2 -1
  275. package/dist/tools/crossfade-videos.js.map +1 -1
  276. package/dist/tools/cut-filler-words.d.ts.map +1 -1
  277. package/dist/tools/cut-filler-words.js +24 -8
  278. package/dist/tools/cut-filler-words.js.map +1 -1
  279. package/dist/tools/detect-speaker-changes.js +2 -1
  280. package/dist/tools/detect-speaker-changes.js.map +1 -1
  281. package/dist/tools/extract-audio.d.ts.map +1 -1
  282. package/dist/tools/extract-audio.js +13 -7
  283. package/dist/tools/extract-audio.js.map +1 -1
  284. package/dist/tools/face-reframe.d.ts +30 -0
  285. package/dist/tools/face-reframe.d.ts.map +1 -0
  286. package/dist/tools/face-reframe.js +143 -0
  287. package/dist/tools/face-reframe.js.map +1 -0
  288. package/dist/tools/face-reframe.test.d.ts +2 -0
  289. package/dist/tools/face-reframe.test.d.ts.map +1 -0
  290. package/dist/tools/face-reframe.test.js +139 -0
  291. package/dist/tools/face-reframe.test.js.map +1 -0
  292. package/dist/tools/find-viral-moments.d.ts +23 -0
  293. package/dist/tools/find-viral-moments.d.ts.map +1 -0
  294. package/dist/tools/find-viral-moments.js +176 -0
  295. package/dist/tools/find-viral-moments.js.map +1 -0
  296. package/dist/tools/find-viral-moments.test.d.ts +2 -0
  297. package/dist/tools/find-viral-moments.test.d.ts.map +1 -0
  298. package/dist/tools/find-viral-moments.test.js +144 -0
  299. package/dist/tools/find-viral-moments.test.js.map +1 -0
  300. package/dist/tools/generate-gif.d.ts.map +1 -1
  301. package/dist/tools/generate-gif.js +47 -40
  302. package/dist/tools/generate-gif.js.map +1 -1
  303. package/dist/tools/generate-gif.test.d.ts +2 -0
  304. package/dist/tools/generate-gif.test.d.ts.map +1 -0
  305. package/dist/tools/generate-gif.test.js +115 -0
  306. package/dist/tools/generate-gif.test.js.map +1 -0
  307. package/dist/tools/generate-outro.d.ts +18 -0
  308. package/dist/tools/generate-outro.d.ts.map +1 -0
  309. package/dist/tools/generate-outro.js +175 -0
  310. package/dist/tools/generate-outro.js.map +1 -0
  311. package/dist/tools/generate-youtube-metadata.d.ts +23 -0
  312. package/dist/tools/generate-youtube-metadata.d.ts.map +1 -0
  313. package/dist/tools/generate-youtube-metadata.js +103 -0
  314. package/dist/tools/generate-youtube-metadata.js.map +1 -0
  315. package/dist/tools/generate-youtube-metadata.test.d.ts +2 -0
  316. package/dist/tools/generate-youtube-metadata.test.d.ts.map +1 -0
  317. package/dist/tools/generate-youtube-metadata.test.js +118 -0
  318. package/dist/tools/generate-youtube-metadata.test.js.map +1 -0
  319. package/dist/tools/index.d.ts +14 -0
  320. package/dist/tools/index.d.ts.map +1 -1
  321. package/dist/tools/index.js +130 -1
  322. package/dist/tools/index.js.map +1 -1
  323. package/dist/tools/index.test.js +27 -1
  324. package/dist/tools/index.test.js.map +1 -1
  325. package/dist/tools/ken-burns.d.ts.map +1 -1
  326. package/dist/tools/ken-burns.js +2 -1
  327. package/dist/tools/ken-burns.js.map +1 -1
  328. package/dist/tools/loop-match-short.d.ts +22 -0
  329. package/dist/tools/loop-match-short.d.ts.map +1 -0
  330. package/dist/tools/loop-match-short.js +107 -0
  331. package/dist/tools/loop-match-short.js.map +1 -0
  332. package/dist/tools/mix-audio.d.ts.map +1 -1
  333. package/dist/tools/mix-audio.js +2 -1
  334. package/dist/tools/mix-audio.js.map +1 -1
  335. package/dist/tools/normalize-loudness.d.ts.map +1 -1
  336. package/dist/tools/normalize-loudness.js +2 -1
  337. package/dist/tools/normalize-loudness.js.map +1 -1
  338. package/dist/tools/path-traversal.test.d.ts +15 -0
  339. package/dist/tools/path-traversal.test.d.ts.map +1 -0
  340. package/dist/tools/path-traversal.test.js +223 -0
  341. package/dist/tools/path-traversal.test.js.map +1 -0
  342. package/dist/tools/pick-best-takes.js +2 -1
  343. package/dist/tools/pick-best-takes.js.map +1 -1
  344. package/dist/tools/punch-in.d.ts.map +1 -1
  345. package/dist/tools/punch-in.js +2 -1
  346. package/dist/tools/punch-in.js.map +1 -1
  347. package/dist/tools/read-transcript.js +2 -1
  348. package/dist/tools/read-transcript.js.map +1 -1
  349. package/dist/tools/render-multi-format.d.ts +35 -0
  350. package/dist/tools/render-multi-format.d.ts.map +1 -0
  351. package/dist/tools/render-multi-format.js +206 -0
  352. package/dist/tools/render-multi-format.js.map +1 -0
  353. package/dist/tools/render-multi-format.test.d.ts +2 -0
  354. package/dist/tools/render-multi-format.test.d.ts.map +1 -0
  355. package/dist/tools/render-multi-format.test.js +312 -0
  356. package/dist/tools/render-multi-format.test.js.map +1 -0
  357. package/dist/tools/render.d.ts.map +1 -1
  358. package/dist/tools/render.js +2 -2
  359. package/dist/tools/render.js.map +1 -1
  360. package/dist/tools/rewrite-hook.d.ts +32 -0
  361. package/dist/tools/rewrite-hook.d.ts.map +1 -0
  362. package/dist/tools/rewrite-hook.js +65 -0
  363. package/dist/tools/rewrite-hook.js.map +1 -0
  364. package/dist/tools/score-clip.d.ts +30 -0
  365. package/dist/tools/score-clip.d.ts.map +1 -0
  366. package/dist/tools/score-clip.js +109 -0
  367. package/dist/tools/score-clip.js.map +1 -0
  368. package/dist/tools/score-clip.test.d.ts +2 -0
  369. package/dist/tools/score-clip.test.d.ts.map +1 -0
  370. package/dist/tools/score-clip.test.js +110 -0
  371. package/dist/tools/score-clip.test.js.map +1 -0
  372. package/dist/tools/search-tools.d.ts +34 -0
  373. package/dist/tools/search-tools.d.ts.map +1 -0
  374. package/dist/tools/search-tools.js +86 -0
  375. package/dist/tools/search-tools.js.map +1 -0
  376. package/dist/tools/search-tools.test.d.ts +2 -0
  377. package/dist/tools/search-tools.test.d.ts.map +1 -0
  378. package/dist/tools/search-tools.test.js +60 -0
  379. package/dist/tools/search-tools.test.js.map +1 -0
  380. package/dist/tools/snap-cuts-to-beats.d.ts +18 -0
  381. package/dist/tools/snap-cuts-to-beats.d.ts.map +1 -0
  382. package/dist/tools/snap-cuts-to-beats.js +110 -0
  383. package/dist/tools/snap-cuts-to-beats.js.map +1 -0
  384. package/dist/tools/snap-cuts-to-beats.test.d.ts +2 -0
  385. package/dist/tools/snap-cuts-to-beats.test.d.ts.map +1 -0
  386. package/dist/tools/snap-cuts-to-beats.test.js +99 -0
  387. package/dist/tools/snap-cuts-to-beats.test.js.map +1 -0
  388. package/dist/tools/speed-ramp.d.ts.map +1 -1
  389. package/dist/tools/speed-ramp.js +2 -1
  390. package/dist/tools/speed-ramp.js.map +1 -1
  391. package/dist/tools/stabilize-video.d.ts.map +1 -1
  392. package/dist/tools/stabilize-video.js +2 -1
  393. package/dist/tools/stabilize-video.js.map +1 -1
  394. package/dist/tools/suggest-broll.d.ts +34 -0
  395. package/dist/tools/suggest-broll.d.ts.map +1 -0
  396. package/dist/tools/suggest-broll.js +367 -0
  397. package/dist/tools/suggest-broll.js.map +1 -0
  398. package/dist/tools/suggest-broll.test.d.ts +2 -0
  399. package/dist/tools/suggest-broll.test.d.ts.map +1 -0
  400. package/dist/tools/suggest-broll.test.js +217 -0
  401. package/dist/tools/suggest-broll.test.js.map +1 -0
  402. package/dist/tools/text-based-cut.d.ts +33 -0
  403. package/dist/tools/text-based-cut.d.ts.map +1 -0
  404. package/dist/tools/text-based-cut.js +172 -0
  405. package/dist/tools/text-based-cut.js.map +1 -0
  406. package/dist/tools/text-based-cut.test.d.ts +2 -0
  407. package/dist/tools/text-based-cut.test.d.ts.map +1 -0
  408. package/dist/tools/text-based-cut.test.js +32 -0
  409. package/dist/tools/text-based-cut.test.js.map +1 -0
  410. package/dist/tools/transcribe.d.ts +1 -1
  411. package/dist/tools/transition-videos.d.ts +1 -1
  412. package/dist/tools/transition-videos.d.ts.map +1 -1
  413. package/dist/tools/transition-videos.js +2 -1
  414. package/dist/tools/transition-videos.js.map +1 -1
  415. package/dist/tools/trim-dead-air.d.ts +59 -0
  416. package/dist/tools/trim-dead-air.d.ts.map +1 -0
  417. package/dist/tools/trim-dead-air.js +215 -0
  418. package/dist/tools/trim-dead-air.js.map +1 -0
  419. package/dist/tools/trim-dead-air.test.d.ts +2 -0
  420. package/dist/tools/trim-dead-air.test.d.ts.map +1 -0
  421. package/dist/tools/trim-dead-air.test.js +75 -0
  422. package/dist/tools/trim-dead-air.test.js.map +1 -0
  423. package/dist/tools/verify-thumbnail-promise.d.ts +33 -0
  424. package/dist/tools/verify-thumbnail-promise.d.ts.map +1 -0
  425. package/dist/tools/verify-thumbnail-promise.js +112 -0
  426. package/dist/tools/verify-thumbnail-promise.js.map +1 -0
  427. package/dist/tools/verify-thumbnail-promise.test.d.ts +2 -0
  428. package/dist/tools/verify-thumbnail-promise.test.d.ts.map +1 -0
  429. package/dist/tools/verify-thumbnail-promise.test.js +38 -0
  430. package/dist/tools/verify-thumbnail-promise.test.js.map +1 -0
  431. package/dist/tools/write-keyword-captions.d.ts +7 -0
  432. package/dist/tools/write-keyword-captions.d.ts.map +1 -1
  433. package/dist/tools/write-keyword-captions.js +35 -4
  434. package/dist/tools/write-keyword-captions.js.map +1 -1
  435. package/dist/ui/App.d.ts.map +1 -1
  436. package/dist/ui/App.js +75 -11
  437. package/dist/ui/App.js.map +1 -1
  438. package/dist/ui/tool-formatters.d.ts +30 -0
  439. package/dist/ui/tool-formatters.d.ts.map +1 -0
  440. package/dist/ui/tool-formatters.js +461 -0
  441. package/dist/ui/tool-formatters.js.map +1 -0
  442. package/dist/ui/tool-formatters.test.d.ts +2 -0
  443. package/dist/ui/tool-formatters.test.d.ts.map +1 -0
  444. package/dist/ui/tool-formatters.test.js +143 -0
  445. package/dist/ui/tool-formatters.test.js.map +1 -0
  446. package/package.json +10 -9
@@ -0,0 +1,75 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { buildTrimConcatFilter, computeKeeps } from "./trim-dead-air.js";
3
+ describe("computeKeeps", () => {
4
+ it("head-tail trims leading and trailing silence", () => {
5
+ const sil = [
6
+ { startSec: 0, endSec: 1.5 },
7
+ { startSec: 28, endSec: 30 },
8
+ ];
9
+ const keeps = computeKeeps(sil, 30, "head-tail", 0);
10
+ expect(keeps).toEqual([{ startSec: 1.5, endSec: 28 }]);
11
+ });
12
+ it("head-tail keeps mid-recording silence intact", () => {
13
+ const sil = [
14
+ { startSec: 0, endSec: 1 },
15
+ { startSec: 10, endSec: 12 },
16
+ { startSec: 29, endSec: 30 },
17
+ ];
18
+ const keeps = computeKeeps(sil, 30, "head-tail", 0);
19
+ expect(keeps).toEqual([{ startSec: 1, endSec: 29 }]);
20
+ });
21
+ it("head-tail returns full duration when no silences detected", () => {
22
+ const keeps = computeKeeps([], 30, "head-tail", 0);
23
+ expect(keeps).toEqual([{ startSec: 0, endSec: 30 }]);
24
+ });
25
+ it("all mode emits keeps between every silence", () => {
26
+ const sil = [
27
+ { startSec: 5, endSec: 6 },
28
+ { startSec: 12, endSec: 13 },
29
+ ];
30
+ const keeps = computeKeeps(sil, 20, "all", 0);
31
+ expect(keeps).toEqual([
32
+ { startSec: 0, endSec: 5 },
33
+ { startSec: 6, endSec: 12 },
34
+ { startSec: 13, endSec: 20 },
35
+ ]);
36
+ });
37
+ it("padding extends keeps and merges overlaps", () => {
38
+ const sil = [
39
+ { startSec: 5, endSec: 5.1 },
40
+ { startSec: 5.3, endSec: 5.4 },
41
+ ];
42
+ // Padding of 0.2 makes the two surrounding keeps overlap, merging to one.
43
+ const keeps = computeKeeps(sil, 10, "all", 0.2);
44
+ expect(keeps.length).toBe(1);
45
+ expect(keeps[0].startSec).toBeCloseTo(0, 5);
46
+ expect(keeps[0].endSec).toBeCloseTo(10, 5);
47
+ });
48
+ it("returns empty when totalSec is 0", () => {
49
+ expect(computeKeeps([], 0, "head-tail", 0)).toEqual([]);
50
+ });
51
+ });
52
+ describe("buildTrimConcatFilter", () => {
53
+ it("single keep emits one trim + atrim labelled [v][a]", () => {
54
+ const f = buildTrimConcatFilter([{ startSec: 1, endSec: 5 }]);
55
+ expect(f).toContain("trim=start=1:end=5");
56
+ expect(f).toContain("atrim=start=1:end=5");
57
+ expect(f).toContain("[v]");
58
+ expect(f).toContain("[a]");
59
+ });
60
+ it("multiple keeps emit per-segment trims and a concat", () => {
61
+ const f = buildTrimConcatFilter([
62
+ { startSec: 0, endSec: 2 },
63
+ { startSec: 5, endSec: 8 },
64
+ ]);
65
+ expect(f).toContain("[v0]");
66
+ expect(f).toContain("[v1]");
67
+ expect(f).toContain("[a0]");
68
+ expect(f).toContain("[a1]");
69
+ expect(f).toContain("concat=n=2:v=1:a=1[v][a]");
70
+ });
71
+ it("throws on empty keep list", () => {
72
+ expect(() => buildTrimConcatFilter([])).toThrow();
73
+ });
74
+ });
75
+ //# sourceMappingURL=trim-dead-air.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trim-dead-air.test.js","sourceRoot":"","sources":["../../src/tools/trim-dead-air.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import { z } from "zod";
2
+ import type { AgentTool } from "@kenkaiiii/gg-agent";
3
+ declare const VerifyThumbnailPromiseParams: z.ZodObject<{
4
+ thumbnail: z.ZodString;
5
+ video: z.ZodString;
6
+ windowSec: z.ZodOptional<z.ZodNumber>;
7
+ sampleCount: z.ZodOptional<z.ZodNumber>;
8
+ detail: z.ZodOptional<z.ZodEnum<{
9
+ low: "low";
10
+ high: "high";
11
+ }>>;
12
+ model: z.ZodOptional<z.ZodString>;
13
+ }, z.core.$strip>;
14
+ /**
15
+ * verify_thumbnail_promise — does the opening deliver on the thumbnail?
16
+ *
17
+ * Per MrBeast's manual: "match the clickbait expectations and
18
+ * front-load." Thumbnails that promise X but show X at minute 8 tank
19
+ * retention. ONE vision LLM call against thumbnail + N sampled frames.
20
+ */
21
+ export declare function createVerifyThumbnailPromiseTool(cwd: string): AgentTool<typeof VerifyThumbnailPromiseParams>;
22
+ /**
23
+ * Compute N sample timestamps evenly distributed across [0, windowSec].
24
+ * - 1 sample → [0]
25
+ * - 2 samples → [0, windowSec]
26
+ * - 3 samples → [0, windowSec/2, windowSec]
27
+ * - 4+ → endpoints + interior at equal stride
28
+ *
29
+ * Pure — exported for testing.
30
+ */
31
+ export declare function sampleTimes(windowSec: number, n: number): number[];
32
+ export {};
33
+ //# sourceMappingURL=verify-thumbnail-promise.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify-thumbnail-promise.d.ts","sourceRoot":"","sources":["../../src/tools/verify-thumbnail-promise.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAMrD,QAAA,MAAM,4BAA4B;;;;;;;;;;iBAqBhC,CAAC;AAEH;;;;;;GAMG;AACH,wBAAgB,gCAAgC,CAC9C,GAAG,EAAE,MAAM,GACV,SAAS,CAAC,OAAO,4BAA4B,CAAC,CAiEhD;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAMlE"}
@@ -0,0 +1,112 @@
1
+ import { resolve as resolvePath } from "node:path";
2
+ import { z } from "zod";
3
+ import { compact, err } from "../core/format.js";
4
+ import { extractAtTimes } from "../core/frames.js";
5
+ import { checkFfmpeg, probeMedia } from "../core/media/ffmpeg.js";
6
+ import { runThumbnailPromise } from "../core/thumbnail-promise.js";
7
+ const VerifyThumbnailPromiseParams = z.object({
8
+ thumbnail: z.string().describe("Path to the thumbnail .jpg/.png (relative resolves to cwd)."),
9
+ video: z.string().describe("Path to the source video the thumbnail accompanies."),
10
+ windowSec: z
11
+ .number()
12
+ .positive()
13
+ .max(120)
14
+ .optional()
15
+ .describe("How much of the opening to sample. Default 60s — short-form delivery's danger zone is " +
16
+ "the first minute."),
17
+ sampleCount: z
18
+ .number()
19
+ .int()
20
+ .min(1)
21
+ .max(8)
22
+ .optional()
23
+ .describe("Frames sampled within the window. Default 3 (taken at 0%, 50%, 100% of windowSec)."),
24
+ detail: z.enum(["low", "high"]).optional().describe("Vision detail. Default low."),
25
+ model: z.string().optional().describe("OpenAI model. Default gpt-4o-mini."),
26
+ });
27
+ /**
28
+ * verify_thumbnail_promise — does the opening deliver on the thumbnail?
29
+ *
30
+ * Per MrBeast's manual: "match the clickbait expectations and
31
+ * front-load." Thumbnails that promise X but show X at minute 8 tank
32
+ * retention. ONE vision LLM call against thumbnail + N sampled frames.
33
+ */
34
+ export function createVerifyThumbnailPromiseTool(cwd) {
35
+ return {
36
+ name: "verify_thumbnail_promise",
37
+ description: "Verify a thumbnail's visual promise is delivered in the first N seconds of the video " +
38
+ "(default 60s). Per MrBeast's manual: 'match clickbait expectations, front-load' — " +
39
+ "thumbnails that promise X but show X at minute 8 tank retention. ONE vision LLM " +
40
+ "call. Returns matches (0-1), what the thumbnail promises, what the opening actually " +
41
+ "shows, missing elements, and a one-line suggestion. ALWAYS run before declaring done " +
42
+ "on any short-form delivery. Pair with `audit_first_frame` and `analyze_hook` as the " +
43
+ "three short-form pre-render checks.",
44
+ parameters: VerifyThumbnailPromiseParams,
45
+ async execute(args, ctx) {
46
+ if (!checkFfmpeg())
47
+ return err("ffmpeg not on PATH", "install ffmpeg");
48
+ if (!process.env.OPENAI_API_KEY) {
49
+ return err("OPENAI_API_KEY not set", "export OPENAI_API_KEY=...");
50
+ }
51
+ try {
52
+ const thumbAbs = resolvePath(cwd, args.thumbnail);
53
+ const videoAbs = resolvePath(cwd, args.video);
54
+ const probe = probeMedia(videoAbs);
55
+ if (!probe) {
56
+ return err(`probe failed for ${videoAbs}`, "verify file exists and is media");
57
+ }
58
+ const windowSec = Math.min(args.windowSec ?? 60, probe.durationSec);
59
+ if (windowSec < 1) {
60
+ return err("video shorter than 1s — nothing to verify against");
61
+ }
62
+ const sampleCount = Math.min(8, Math.max(1, args.sampleCount ?? 3));
63
+ const times = sampleTimes(windowSec, sampleCount);
64
+ const frames = await extractAtTimes(videoAbs, times, {
65
+ maxWidth: 768,
66
+ signal: ctx.signal,
67
+ });
68
+ if (frames.length === 0) {
69
+ return err("could not extract opening frames");
70
+ }
71
+ const result = await runThumbnailPromise(thumbAbs, frames.map((f) => f.path), {
72
+ model: args.model,
73
+ detail: args.detail,
74
+ windowSec,
75
+ signal: ctx.signal,
76
+ });
77
+ return compact({
78
+ matches: +result.matches.toFixed(2),
79
+ thumbnailPromise: result.thumbnailPromise,
80
+ openingShows: result.openingShows,
81
+ missing: result.missing,
82
+ suggestion: result.suggestion,
83
+ windowSec: +windowSec.toFixed(2),
84
+ sampleCount: frames.length,
85
+ sampledAt: times.map((t) => +t.toFixed(2)),
86
+ });
87
+ }
88
+ catch (e) {
89
+ return err(e.message);
90
+ }
91
+ },
92
+ };
93
+ }
94
+ /**
95
+ * Compute N sample timestamps evenly distributed across [0, windowSec].
96
+ * - 1 sample → [0]
97
+ * - 2 samples → [0, windowSec]
98
+ * - 3 samples → [0, windowSec/2, windowSec]
99
+ * - 4+ → endpoints + interior at equal stride
100
+ *
101
+ * Pure — exported for testing.
102
+ */
103
+ export function sampleTimes(windowSec, n) {
104
+ if (n <= 1 || windowSec <= 0)
105
+ return [0];
106
+ const out = [];
107
+ const step = windowSec / (n - 1);
108
+ for (let i = 0; i < n; i++)
109
+ out.push(+(i * step).toFixed(3));
110
+ return out;
111
+ }
112
+ //# sourceMappingURL=verify-thumbnail-promise.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify-thumbnail-promise.js","sourceRoot":"","sources":["../../src/tools/verify-thumbnail-promise.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAEnE,MAAM,4BAA4B,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5C,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,6DAA6D,CAAC;IAC7F,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,qDAAqD,CAAC;IACjF,SAAS,EAAE,CAAC;SACT,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,GAAG,CAAC,GAAG,CAAC;SACR,QAAQ,EAAE;SACV,QAAQ,CACP,wFAAwF;QACtF,mBAAmB,CACtB;IACH,WAAW,EAAE,CAAC;SACX,MAAM,EAAE;SACR,GAAG,EAAE;SACL,GAAG,CAAC,CAAC,CAAC;SACN,GAAG,CAAC,CAAC,CAAC;SACN,QAAQ,EAAE;SACV,QAAQ,CAAC,oFAAoF,CAAC;IACjG,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,6BAA6B,CAAC;IAClF,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,oCAAoC,CAAC;CAC5E,CAAC,CAAC;AAEH;;;;;;GAMG;AACH,MAAM,UAAU,gCAAgC,CAC9C,GAAW;IAEX,OAAO;QACL,IAAI,EAAE,0BAA0B;QAChC,WAAW,EACT,uFAAuF;YACvF,oFAAoF;YACpF,kFAAkF;YAClF,sFAAsF;YACtF,uFAAuF;YACvF,sFAAsF;YACtF,qCAAqC;QACvC,UAAU,EAAE,4BAA4B;QACxC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG;YACrB,IAAI,CAAC,WAAW,EAAE;gBAAE,OAAO,GAAG,CAAC,oBAAoB,EAAE,gBAAgB,CAAC,CAAC;YACvE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,CAAC;gBAChC,OAAO,GAAG,CAAC,wBAAwB,EAAE,2BAA2B,CAAC,CAAC;YACpE,CAAC;YACD,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;gBAClD,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;gBAC9C,MAAM,KAAK,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;gBACnC,IAAI,CAAC,KAAK,EAAE,CAAC;oBACX,OAAO,GAAG,CAAC,oBAAoB,QAAQ,EAAE,EAAE,iCAAiC,CAAC,CAAC;gBAChF,CAAC;gBACD,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,IAAI,EAAE,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;gBACpE,IAAI,SAAS,GAAG,CAAC,EAAE,CAAC;oBAClB,OAAO,GAAG,CAAC,mDAAmD,CAAC,CAAC;gBAClE,CAAC;gBAED,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,WAAW,IAAI,CAAC,CAAC,CAAC,CAAC;gBACpE,MAAM,KAAK,GAAG,WAAW,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;gBAClD,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,QAAQ,EAAE,KAAK,EAAE;oBACnD,QAAQ,EAAE,GAAG;oBACb,MAAM,EAAE,GAAG,CAAC,MAAM;iBACnB,CAAC,CAAC;gBACH,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBACxB,OAAO,GAAG,CAAC,kCAAkC,CAAC,CAAC;gBACjD,CAAC;gBAED,MAAM,MAAM,GAAG,MAAM,mBAAmB,CACtC,QAAQ,EACR,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EACzB;oBACE,KAAK,EAAE,IAAI,CAAC,KAAK;oBACjB,MAAM,EAAE,IAAI,CAAC,MAAM;oBACnB,SAAS;oBACT,MAAM,EAAE,GAAG,CAAC,MAAM;iBACnB,CACF,CAAC;gBAEF,OAAO,OAAO,CAAC;oBACb,OAAO,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;oBACnC,gBAAgB,EAAE,MAAM,CAAC,gBAAgB;oBACzC,YAAY,EAAE,MAAM,CAAC,YAAY;oBACjC,OAAO,EAAE,MAAM,CAAC,OAAO;oBACvB,UAAU,EAAE,MAAM,CAAC,UAAU;oBAC7B,SAAS,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;oBAChC,WAAW,EAAE,MAAM,CAAC,MAAM;oBAC1B,SAAS,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;iBAC3C,CAAC,CAAC;YACL,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,OAAO,GAAG,CAAE,CAAW,CAAC,OAAO,CAAC,CAAC;YACnC,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,WAAW,CAAC,SAAiB,EAAE,CAAS;IACtD,IAAI,CAAC,IAAI,CAAC,IAAI,SAAS,IAAI,CAAC;QAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IACzC,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,MAAM,IAAI,GAAG,SAAS,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACjC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;QAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7D,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=verify-thumbnail-promise.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify-thumbnail-promise.test.d.ts","sourceRoot":"","sources":["../../src/tools/verify-thumbnail-promise.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,38 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { createVerifyThumbnailPromiseTool, sampleTimes } from "./verify-thumbnail-promise.js";
3
+ const ctx = {
4
+ signal: new AbortController().signal,
5
+ toolCallId: "t1",
6
+ };
7
+ describe("sampleTimes", () => {
8
+ it("returns single sample at 0 when n=1", () => {
9
+ expect(sampleTimes(60, 1)).toEqual([0]);
10
+ });
11
+ it("returns endpoints when n=2", () => {
12
+ expect(sampleTimes(60, 2)).toEqual([0, 60]);
13
+ });
14
+ it("returns 0/mid/end when n=3", () => {
15
+ expect(sampleTimes(60, 3)).toEqual([0, 30, 60]);
16
+ });
17
+ it("evenly distributes for n=5", () => {
18
+ const t = sampleTimes(40, 5);
19
+ expect(t).toHaveLength(5);
20
+ expect(t[0]).toBe(0);
21
+ expect(t[t.length - 1]).toBe(40);
22
+ });
23
+ });
24
+ describe("verify_thumbnail_promise tool", () => {
25
+ it("description names front-load + matches + always-run + algorithm pairing", () => {
26
+ const tool = createVerifyThumbnailPromiseTool("/tmp");
27
+ expect(tool.description).toMatch(/front-load|MrBeast/);
28
+ expect(tool.description).toMatch(/ALWAYS|matches/);
29
+ expect(tool.description).toMatch(/audit_first_frame|analyze_hook/);
30
+ });
31
+ it("errors when OPENAI_API_KEY is missing", async () => {
32
+ delete process.env.OPENAI_API_KEY;
33
+ const tool = createVerifyThumbnailPromiseTool("/tmp");
34
+ const r = await tool.execute({ thumbnail: "t.jpg", video: "v.mp4" }, ctx);
35
+ expect(r).toMatch(/error/);
36
+ });
37
+ });
38
+ //# sourceMappingURL=verify-thumbnail-promise.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify-thumbnail-promise.test.js","sourceRoot":"","sources":["../../src/tools/verify-thumbnail-promise.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,gCAAgC,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAE9F,MAAM,GAAG,GAAG;IACV,MAAM,EAAE,IAAI,eAAe,EAAE,CAAC,MAAM;IACpC,UAAU,EAAE,IAAI;CAC2E,CAAC;AAE9F,QAAQ,CAAC,aAAa,EAAE,GAAG,EAAE;IAC3B,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;QAC7C,MAAM,CAAC,WAAW,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4BAA4B,EAAE,GAAG,EAAE;QACpC,MAAM,CAAC,WAAW,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4BAA4B,EAAE,GAAG,EAAE;QACpC,MAAM,CAAC,WAAW,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4BAA4B,EAAE,GAAG,EAAE;QACpC,MAAM,CAAC,GAAG,WAAW,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QAC7B,MAAM,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC1B,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACrB,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,+BAA+B,EAAE,GAAG,EAAE;IAC7C,EAAE,CAAC,yEAAyE,EAAE,GAAG,EAAE;QACjF,MAAM,IAAI,GAAG,gCAAgC,CAAC,MAAM,CAAC,CAAC;QACtD,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC;QACvD,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;QACnD,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,gCAAgC,CAAC,CAAC;IACrE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uCAAuC,EAAE,KAAK,IAAI,EAAE;QACrD,OAAO,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;QAClC,MAAM,IAAI,GAAG,gCAAgC,CAAC,MAAM,CAAC,CAAC;QACtD,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,GAAG,CAAC,CAAC;QAC1E,MAAM,CAAC,CAAW,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -18,6 +18,13 @@ declare const WriteKeywordCaptionsParams: z.ZodObject<{
18
18
  marginV: z.ZodOptional<z.ZodNumber>;
19
19
  playResX: z.ZodOptional<z.ZodNumber>;
20
20
  playResY: z.ZodOptional<z.ZodNumber>;
21
+ autoEmoji: z.ZodOptional<z.ZodBoolean>;
22
+ emojiDensity: z.ZodOptional<z.ZodEnum<{
23
+ low: "low";
24
+ high: "high";
25
+ med: "med";
26
+ }>>;
27
+ emojiModel: z.ZodOptional<z.ZodString>;
21
28
  }, z.core.$strip>;
22
29
  /**
23
30
  * write_keyword_captions — CapCut-style "active word" caption track.
@@ -1 +1 @@
1
- {"version":3,"file":"write-keyword-captions.d.ts","sourceRoot":"","sources":["../../src/tools/write-keyword-captions.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAOrD,QAAA,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;iBAoE9B,CAAC;AAEH;;;;;;;;;;;GAWG;AACH,wBAAgB,8BAA8B,CAC5C,GAAG,EAAE,MAAM,GACV,SAAS,CAAC,OAAO,0BAA0B,CAAC,CA+F9C"}
1
+ {"version":3,"file":"write-keyword-captions.d.ts","sourceRoot":"","sources":["../../src/tools/write-keyword-captions.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AASrD,QAAA,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;iBAgF9B,CAAC;AAEH;;;;;;;;;;;GAWG;AACH,wBAAgB,8BAA8B,CAC5C,GAAG,EAAE,MAAM,GACV,SAAS,CAAC,OAAO,0BAA0B,CAAC,CAmH9C"}
@@ -2,9 +2,11 @@ import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
2
  import { dirname, resolve as resolvePath } from "node:path";
3
3
  import { z } from "zod";
4
4
  import { buildAss } from "../core/ass.js";
5
+ import { injectEmojis } from "../core/emoji-captions.js";
5
6
  import { compact, err } from "../core/format.js";
6
7
  import { buildKeywordCaptions } from "../core/keyword-captions.js";
7
8
  import { safeOutputPath } from "../core/safe-paths.js";
9
+ import { parseTranscript } from "../core/whisper.js";
8
10
  const WriteKeywordCaptionsParams = z.object({
9
11
  transcript: z
10
12
  .string()
@@ -69,6 +71,16 @@ const WriteKeywordCaptionsParams = z.object({
69
71
  "puts captions in the lower-third sweet spot."),
70
72
  playResX: z.number().int().positive().optional().describe("Canvas width. Default 1080."),
71
73
  playResY: z.number().int().positive().optional().describe("Canvas height. Default 1920."),
74
+ autoEmoji: z
75
+ .boolean()
76
+ .optional()
77
+ .describe("If true, the tool calls the LLM ONCE over all cues to suggest a fitting emoji per cue " +
78
+ "(or empty string). Submagic / CapCut signature look. Default false."),
79
+ emojiDensity: z
80
+ .enum(["low", "med", "high"])
81
+ .optional()
82
+ .describe("low ≈ 1 in 4 cues, med ≈ 1 in 2, high = every cue. Default 'med'."),
83
+ emojiModel: z.string().optional().describe("LLM model. Default gpt-4o-mini."),
72
84
  });
73
85
  /**
74
86
  * write_keyword_captions — CapCut-style "active word" caption track.
@@ -102,10 +114,10 @@ export function createWriteKeywordCaptionsTool(cwd) {
102
114
  }
103
115
  let t;
104
116
  try {
105
- t = JSON.parse(raw);
117
+ t = parseTranscript(raw);
106
118
  }
107
119
  catch (e) {
108
- return err(`transcript is not valid JSON: ${e.message}`);
120
+ return err(e.message);
109
121
  }
110
122
  const lo = args.startSec ?? 0;
111
123
  const hi = args.endSec ?? t.durationSec;
@@ -130,12 +142,14 @@ export function createWriteKeywordCaptionsTool(cwd) {
130
142
  if (allWords.length === 0) {
131
143
  return err("no word timings in window", "rerun transcribe(wordTimestamps=true) or widen startSec/endSec");
132
144
  }
133
- const { cues, styles } = buildKeywordCaptions(allWords, {
145
+ const built = buildKeywordCaptions(allWords, {
134
146
  groupSize: args.groupSize,
135
147
  gapSec: args.gapSec,
136
148
  maxKeywordsPerCue: args.maxKeywordsPerCue,
137
149
  minKeywordLen: args.minKeywordLen,
138
150
  });
151
+ let cues = built.cues;
152
+ const styles = built.styles;
139
153
  // Apply aesthetic overrides onto the returned styles.
140
154
  for (const s of styles) {
141
155
  if (s.name === "Default") {
@@ -163,6 +177,18 @@ export function createWriteKeywordCaptionsTool(cwd) {
163
177
  s.marginV = args.marginV;
164
178
  }
165
179
  }
180
+ // Optional emoji-injection pass (Submagic / CapCut look).
181
+ let emojiInjected = 0;
182
+ let emojiError;
183
+ if (args.autoEmoji) {
184
+ const r = await injectEmojis(cues, {
185
+ density: args.emojiDensity,
186
+ model: args.emojiModel,
187
+ });
188
+ cues = r.cues;
189
+ emojiInjected = r.injected;
190
+ emojiError = r.error;
191
+ }
166
192
  const ass = buildAss({
167
193
  styles,
168
194
  cues,
@@ -173,7 +199,12 @@ export function createWriteKeywordCaptionsTool(cwd) {
173
199
  const outAbs = safeOutputPath(cwd, args.output);
174
200
  mkdirSync(dirname(outAbs), { recursive: true });
175
201
  writeFileSync(outAbs, ass, "utf8");
176
- return compact({ path: outAbs, cues: cues.length });
202
+ return compact({
203
+ path: outAbs,
204
+ cues: cues.length,
205
+ ...(args.autoEmoji ? { emojiInjected } : {}),
206
+ ...(emojiError ? { emojiError } : {}),
207
+ });
177
208
  }
178
209
  catch (e) {
179
210
  return err(e.message);
@@ -1 +1 @@
1
- {"version":3,"file":"write-keyword-captions.js","sourceRoot":"","sources":["../../src/tools/write-keyword-captions.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"write-keyword-captions.js","sourceRoot":"","sources":["../../src/tools/write-keyword-captions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACjE,OAAO,EAAE,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,WAAW,CAAC;AAC5D,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAGrD,MAAM,0BAA0B,GAAG,CAAC,CAAC,MAAM,CAAC;IAC1C,UAAU,EAAE,CAAC;SACV,MAAM,EAAE;SACR,QAAQ,CACP,qFAAqF,CACtF;IACH,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,8CAA8C,CAAC;IAC3E,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,0CAA0C,CAAC;IAC3F,MAAM,EAAE,CAAC;SACN,MAAM,EAAE;SACR,GAAG,CAAC,CAAC,CAAC;SACN,QAAQ,EAAE;SACV,QAAQ,CAAC,uDAAuD,CAAC;IACpE,SAAS,EAAE,CAAC;SACT,MAAM,EAAE;SACR,GAAG,EAAE;SACL,GAAG,CAAC,CAAC,CAAC;SACN,GAAG,CAAC,CAAC,CAAC;SACN,QAAQ,EAAE;SACV,QAAQ,CAAC,2DAA2D,CAAC;IACxE,iBAAiB,EAAE,CAAC;SACjB,MAAM,EAAE;SACR,GAAG,EAAE;SACL,GAAG,CAAC,CAAC,CAAC;SACN,GAAG,CAAC,CAAC,CAAC;SACN,QAAQ,EAAE;SACV,QAAQ,CAAC,oEAAoE,CAAC;IACjF,aAAa,EAAE,CAAC;SACb,MAAM,EAAE;SACR,GAAG,EAAE;SACL,GAAG,CAAC,CAAC,CAAC;SACN,GAAG,CAAC,EAAE,CAAC;SACP,QAAQ,EAAE;SACV,QAAQ,CAAC,iEAAiE,CAAC;IAC9E,MAAM,EAAE,CAAC;SACN,MAAM,EAAE;SACR,GAAG,CAAC,CAAC,CAAC;SACN,QAAQ,EAAE;SACV,QAAQ,CAAC,mDAAmD,CAAC;IAChE,qEAAqE;IACrE,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,6BAA6B,CAAC;IACvE,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,sCAAsC,CAAC;IACjG,YAAY,EAAE,CAAC;SACZ,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CAAC,sDAAsD,CAAC;IACnE,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,4CAA4C,CAAC;IAC1F,YAAY,EAAE,CAAC;SACZ,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CAAC,iEAAiE,CAAC;IAC9E,eAAe,EAAE,CAAC;SACf,MAAM,EAAE;SACR,GAAG,EAAE;SACL,QAAQ,EAAE;SACV,QAAQ,EAAE;SACV,QAAQ,CAAC,0DAA0D,CAAC;IACvE,OAAO,EAAE,CAAC;SACP,MAAM,EAAE;SACR,GAAG,EAAE;SACL,GAAG,CAAC,CAAC,CAAC;SACN,QAAQ,EAAE;SACV,QAAQ,CACP,sFAAsF;QACpF,8CAA8C,CACjD;IACH,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,6BAA6B,CAAC;IACxF,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,8BAA8B,CAAC;IACzF,SAAS,EAAE,CAAC;SACT,OAAO,EAAE;SACT,QAAQ,EAAE;SACV,QAAQ,CACP,wFAAwF;QACtF,qEAAqE,CACxE;IACH,YAAY,EAAE,CAAC;SACZ,IAAI,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;SAC5B,QAAQ,EAAE;SACV,QAAQ,CAAC,mEAAmE,CAAC;IAChF,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,iCAAiC,CAAC;CAC9E,CAAC,CAAC;AAEH;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,8BAA8B,CAC5C,GAAW;IAEX,OAAO;QACL,IAAI,EAAE,wBAAwB;QAC9B,WAAW,EACT,qFAAqF;YACrF,0FAA0F;YAC1F,0FAA0F;YAC1F,+EAA+E;QACjF,UAAU,EAAE,0BAA0B;QACtC,KAAK,CAAC,OAAO,CAAC,IAAI;YAChB,IAAI,CAAC;gBACH,MAAM,aAAa,GAAG,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;gBACxD,IAAI,GAAW,CAAC;gBAChB,IAAI,CAAC;oBACH,GAAG,GAAG,YAAY,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;gBAC5C,CAAC;gBAAC,OAAO,CAAC,EAAE,CAAC;oBACX,OAAO,GAAG,CACR,0BAA0B,aAAa,KAAM,CAAW,CAAC,OAAO,EAAE,EAClE,mCAAmC,CACpC,CAAC;gBACJ,CAAC;gBACD,IAAI,CAAa,CAAC;gBAClB,IAAI,CAAC;oBACH,CAAC,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;gBAC3B,CAAC;gBAAC,OAAO,CAAC,EAAE,CAAC;oBACX,OAAO,GAAG,CAAE,CAAW,CAAC,OAAO,CAAC,CAAC;gBACnC,CAAC;gBAED,MAAM,EAAE,GAAG,IAAI,CAAC,QAAQ,IAAI,CAAC,CAAC;gBAC9B,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC,WAAW,CAAC;gBACxC,IAAI,EAAE,IAAI,EAAE;oBAAE,OAAO,GAAG,CAAC,2BAA2B,CAAC,CAAC;gBAEtD,6DAA6D;gBAC7D,uCAAuC;gBACvC,MAAM,QAAQ,GAAwD,EAAE,CAAC;gBACzE,KAAK,MAAM,GAAG,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC;oBAC7B,IAAI,CAAC,GAAG,CAAC,KAAK;wBAAE,SAAS;oBACzB,KAAK,MAAM,CAAC,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;wBAC1B,IAAI,CAAC,CAAC,GAAG,IAAI,EAAE,IAAI,CAAC,CAAC,KAAK,IAAI,EAAE;4BAAE,SAAS;wBAC3C,QAAQ,CAAC,IAAI,CAAC;4BACZ,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE;4BACjC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE;4BAC7B,IAAI,EAAE,CAAC,CAAC,IAAI;yBACb,CAAC,CAAC;oBACL,CAAC;gBACH,CAAC;gBACD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBAC1B,OAAO,GAAG,CACR,2BAA2B,EAC3B,gEAAgE,CACjE,CAAC;gBACJ,CAAC;gBAED,MAAM,KAAK,GAAG,oBAAoB,CAAC,QAAQ,EAAE;oBAC3C,SAAS,EAAE,IAAI,CAAC,SAAS;oBACzB,MAAM,EAAE,IAAI,CAAC,MAAM;oBACnB,iBAAiB,EAAE,IAAI,CAAC,iBAAiB;oBACzC,aAAa,EAAE,IAAI,CAAC,aAAa;iBAClC,CAAC,CAAC;gBACH,IAAI,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;gBACtB,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;gBAE5B,sDAAsD;gBACtD,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;oBACvB,IAAI,CAAC,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;wBACzB,IAAI,IAAI,CAAC,QAAQ;4BAAE,CAAC,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;wBAC9C,IAAI,IAAI,CAAC,QAAQ;4BAAE,CAAC,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;wBAC9C,IAAI,IAAI,CAAC,YAAY;4BAAE,CAAC,CAAC,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC;wBAC1D,IAAI,IAAI,CAAC,YAAY;4BAAE,CAAC,CAAC,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC;wBAC1D,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS;4BAAE,CAAC,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;oBAC3D,CAAC;yBAAM,IAAI,CAAC,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;wBAChC,IAAI,IAAI,CAAC,QAAQ;4BAAE,CAAC,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;wBAC9C,IAAI,IAAI,CAAC,eAAe;4BAAE,CAAC,CAAC,QAAQ,GAAG,IAAI,CAAC,eAAe,CAAC;wBAC5D,IAAI,IAAI,CAAC,YAAY;4BAAE,CAAC,CAAC,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC;wBAC1D,IAAI,IAAI,CAAC,YAAY;4BAAE,CAAC,CAAC,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC;wBAC1D,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS;4BAAE,CAAC,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;oBAC3D,CAAC;gBACH,CAAC;gBAED,0DAA0D;gBAC1D,IAAI,aAAa,GAAG,CAAC,CAAC;gBACtB,IAAI,UAA8B,CAAC;gBACnC,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;oBACnB,MAAM,CAAC,GAAG,MAAM,YAAY,CAAC,IAAI,EAAE;wBACjC,OAAO,EAAE,IAAI,CAAC,YAAY;wBAC1B,KAAK,EAAE,IAAI,CAAC,UAAU;qBACvB,CAAC,CAAC;oBACH,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC;oBACd,aAAa,GAAG,CAAC,CAAC,QAAQ,CAAC;oBAC3B,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC;gBACvB,CAAC;gBAED,MAAM,GAAG,GAAG,QAAQ,CAAC;oBACnB,MAAM;oBACN,IAAI;oBACJ,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,IAAI;oBAC/B,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,IAAI;oBAC/B,KAAK,EAAE,8BAA8B;iBACtC,CAAC,CAAC;gBAEH,MAAM,MAAM,GAAG,cAAc,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;gBAChD,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;gBAChD,aAAa,CAAC,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;gBAEnC,OAAO,OAAO,CAAC;oBACb,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,IAAI,CAAC,MAAM;oBACjB,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBAC5C,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBACtC,CAAC,CAAC;YACL,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,OAAO,GAAG,CAAE,CAAW,CAAC,OAAO,CAAC,CAAC;YACnC,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../../src/ui/App.tsx"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAErD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAOtD,MAAM,WAAW,QAAQ;IACvB;;;OAGG;IACH,QAAQ,EAAE,QAAQ,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,CACnB,QAAQ,EAAE,QAAQ,EAClB,IAAI,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE,OAAO,CAAA;KAAE,KAC9B,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACrD,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB;;;;;OAKG;IACH,gBAAgB,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,IAAI,EAAE,QAAQ,CAAC;IACf,gEAAgE;IAChE,aAAa,EAAE,OAAO,EAAE,CAAC;IAEzB,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,OAAO,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,sCAAsC;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,wEAAwE;IACxE,iBAAiB,EAAE,QAAQ,EAAE,CAAC;IAE9B,yEAAyE;IACzE,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,UAAU,EAAE,MAAM,IAAI,CAAC;CACxB;AAqCD,wBAAgB,GAAG,CAAC,KAAK,EAAE,QAAQ,2CA8clC"}
1
+ {"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../../src/ui/App.tsx"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAErD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAStD,MAAM,WAAW,QAAQ;IACvB;;;OAGG;IACH,QAAQ,EAAE,QAAQ,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,CACnB,QAAQ,EAAE,QAAQ,EAClB,IAAI,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE,OAAO,CAAA;KAAE,KAC9B,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACrD,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB;;;;;OAKG;IACH,gBAAgB,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,IAAI,EAAE,QAAQ,CAAC;IACf,gEAAgE;IAChE,aAAa,EAAE,OAAO,EAAE,CAAC;IAEzB,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,OAAO,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,sCAAsC;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,wEAAwE;IACxE,iBAAiB,EAAE,QAAQ,EAAE,CAAC;IAE9B,yEAAyE;IACzE,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,UAAU,EAAE,MAAM,IAAI,CAAC;CACxB;AA+DD,wBAAgB,GAAG,CAAC,KAAK,EAAE,QAAQ,2CA4flC"}
package/dist/ui/App.js CHANGED
@@ -6,17 +6,46 @@ import { useTerminalSize } from "@kenkaiiii/ggcoder/ui/hooks/terminal-size";
6
6
  import { useAgentLoop } from "@kenkaiiii/ggcoder/ui/hooks/agent-loop";
7
7
  import { useDoublePress } from "@kenkaiiii/ggcoder/ui/hooks/double-press";
8
8
  import { useTheme } from "@kenkaiiii/ggcoder/ui/theme";
9
+ import { getMaxThinkingLevel } from "@kenkaiiii/ggcoder/models";
9
10
  import { Banner } from "./components/Banner.js";
10
11
  import { saveSession } from "../core/sessions.js";
11
12
  import { buildEditorHostBlock, spliceHostBlock } from "../system-prompt.js";
13
+ import { EDITOR_PROMPT_COMMANDS, getEditorPromptCommand } from "../prompt-commands.js";
14
+ import { ggEditorFormatters } from "./tool-formatters.js";
12
15
  // Editor brand pulse — amber → orange → rose. Distinct from ggcoder's blue/purple.
13
16
  const THINKING_BORDER_COLORS = ["#fbbf24", "#f97316", "#ec4899", "#f97316", "#fbbf24"];
14
17
  // Names are bare (no `/` prefix) — ggcoder's slash menu prepends `/` for
15
18
  // display. Including a `/` here would render as `//`.
19
+ //
20
+ // Order is intentional, follows the typical creator session arc:
21
+ // 1. Setup — one-time per channel
22
+ // 2. Workflow — the main verb ("make me a YouTube video")
23
+ // 3. QA — audit before ship; diagnose after under-performance
24
+ // 4. Session UI — model swap, clear scrollback
25
+ // 5. Meta — help, then quit (always last)
26
+ //
27
+ // Prompt commands (group 1–3) come from `prompt-commands.ts` — looked up by
28
+ // name in the same handleSubmit dispatcher. Local UI commands (group 4–5)
29
+ // are handled inline because they manipulate React state directly.
30
+ function promptCmd(name) {
31
+ const c = EDITOR_PROMPT_COMMANDS.find((x) => x.name === name);
32
+ if (!c)
33
+ throw new Error(`gg-editor: missing prompt command '${name}' — check prompt-commands.ts`);
34
+ return { name: c.name, aliases: c.aliases, description: c.description };
35
+ }
16
36
  const EDITOR_COMMANDS = [
37
+ // 1. Setup (one-time per channel)
38
+ promptCmd("setup-channel"),
39
+ // 2. Workflow (the main verb)
40
+ promptCmd("youtube"),
41
+ // 3. QA — pre-render audit, post-render diagnosis
42
+ promptCmd("audit"),
43
+ promptCmd("diagnose"),
44
+ // 4. Session UI
17
45
  { name: "model", aliases: ["m"], description: "switch model" },
18
- { name: "help", aliases: ["?"], description: "show available commands" },
19
46
  { name: "clear", aliases: [], description: "clear visible history (doesn't reset agent)" },
47
+ // 5. Meta — help next-to-last, quit always last
48
+ { name: "help", aliases: ["?"], description: "show available commands" },
20
49
  { name: "quit", aliases: ["exit", "q"], description: "exit cleanly" },
21
50
  ];
22
51
  export function App(props) {
@@ -170,7 +199,7 @@ export function App(props) {
170
199
  maxTokens: 16384,
171
200
  apiKey: props.apiKey,
172
201
  accountId: props.accountId,
173
- thinking: thinkingEnabled ? "medium" : undefined,
202
+ thinking: thinkingEnabled ? getMaxThinkingLevel(currentModel) : undefined,
174
203
  // Pull fresh creds before each turn so OAuth refresh + provider swaps
175
204
  // via /model both flow through. Without this, an 8h Anthropic token
176
205
  // that expires mid-session takes the whole CLI down.
@@ -194,14 +223,17 @@ export function App(props) {
194
223
  },
195
224
  // Running tool calls are rendered live from agentLoop.activeToolCalls
196
225
  // OUTSIDE of <Static>; only the completed result enters scrollback here.
197
- onToolEnd: (toolCallId, name, result, isError, _durationMs, details) => {
198
- const active = agentLoop.activeToolCalls.find((tc) => tc.toolCallId === toolCallId);
226
+ onToolEnd: (toolCallId, name, result, isError, _durationMs, details, args) => {
227
+ // Use the args passed through from onToolEnd directly. Looking them up
228
+ // via `agentLoop.activeToolCalls` here is racey — by the time onToolEnd
229
+ // fires the call has been pulled from the active list, so most tools
230
+ // would land on `{}` and lose every detail/inline summary.
199
231
  queueFlush({
200
232
  id: nextId(),
201
233
  kind: "tool_done",
202
234
  toolCallId,
203
235
  name,
204
- args: active?.args ?? {},
236
+ args: args ?? {},
205
237
  result,
206
238
  isError,
207
239
  details,
@@ -248,16 +280,26 @@ export function App(props) {
248
280
  return;
249
281
  }
250
282
  if (value === "/help" || value === "/?") {
283
+ const fmt = (c) => `- \`/${c.name}\`${c.aliases.length ? " " + c.aliases.map((a) => `\`/${a}\``).join(" ") : ""} — ${c.description}`;
284
+ const setup = EDITOR_PROMPT_COMMANDS.filter((c) => c.name === "setup-channel").map(fmt);
285
+ const workflow = EDITOR_PROMPT_COMMANDS.filter((c) => c.name === "youtube").map(fmt);
286
+ const qa = EDITOR_PROMPT_COMMANDS.filter((c) => ["audit", "diagnose"].includes(c.name)).map(fmt);
251
287
  setHistoryItems((items) => [
252
288
  ...items,
253
289
  {
254
290
  id: nextId(),
255
291
  kind: "assistant",
256
- text: "**Slash commands**\n\n" +
292
+ text: "**Setup** (one-time per channel)\n\n" +
293
+ setup.join("\n") +
294
+ "\n\n**Workflow**\n\n" +
295
+ workflow.join("\n") +
296
+ "\n\n**Quality checks**\n\n" +
297
+ qa.join("\n") +
298
+ "\n\n**Session**\n\n" +
257
299
  "- `/model` `/m` — switch model\n" +
258
- "- `/quit` `/exit` `/q` — exit\n" +
259
300
  "- `/clear` — clear visible history (doesn't reset agent)\n" +
260
- "- `/help` `/?` — this help\n\n" +
301
+ "- `/help` `/?` — this help\n" +
302
+ "- `/quit` `/exit` `/q` — exit\n\n" +
261
303
  "**Keys**\n\n" +
262
304
  "- `Shift-Tab` toggle thinking\n" +
263
305
  "- `ESC` interrupt the agent\n" +
@@ -272,6 +314,28 @@ export function App(props) {
272
314
  setOverlay("model");
273
315
  return;
274
316
  }
317
+ // Bundled prompt commands — dispatch to the agent loop with the
318
+ // command's prompt as the user message. Mirrors ggcoder's pattern.
319
+ // Args after the command name are appended as "## User Instructions".
320
+ if (value.startsWith("/")) {
321
+ const parts = value.slice(1).split(" ");
322
+ const cmdName = parts[0];
323
+ const cmdArgs = parts.slice(1).join(" ").trim();
324
+ const cmd = getEditorPromptCommand(cmdName);
325
+ if (cmd) {
326
+ const fullPrompt = cmdArgs
327
+ ? `${cmd.prompt}\n\n## User Instructions\n\n${cmdArgs}`
328
+ : cmd.prompt;
329
+ // Show the user's literal /command invocation in scrollback so the
330
+ // history stays a faithful transcript; the expanded prompt itself
331
+ // goes to the agent loop only.
332
+ lastUserMessageRef.current = value;
333
+ setLastUserMessage(value);
334
+ setHistoryItems((items) => [...items, { id: nextId(), kind: "user", text: value }]);
335
+ void agentLoop.run(fullPrompt);
336
+ return;
337
+ }
338
+ }
275
339
  lastUserMessageRef.current = value;
276
340
  setLastUserMessage(value);
277
341
  setHistoryItems((items) => [...items, { id: nextId(), kind: "user", text: value }]);
@@ -355,9 +419,9 @@ export function App(props) {
355
419
  // Banner is static — host connection state lives in the Footer (which
356
420
  // polls every few seconds and updates live).
357
421
  [historyItems, props.version, currentModel, currentProvider]);
358
- return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Static, { items: staticItems, children: (item) => _jsx(Box, { children: item.el }, item.id) }), _jsx(StreamingArea, { isRunning: agentLoop.isRunning, streamingText: agentLoop.streamingText, streamingThinking: agentLoop.streamingThinking, showThinking: true, thinkingMs: agentLoop.thinkingMs }), agentLoop.activeToolCalls.map((tc) => (_jsx(ToolExecution, { status: "running", name: tc.name, args: tc.args }, tc.toolCallId))), agentLoop.isRunning && agentLoop.activityPhase !== "idle" ? (_jsx(Box, { marginTop: 1, borderStyle: "round", borderColor: agentLoop.activityPhase === "thinking"
422
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Static, { items: staticItems, children: (item) => _jsx(Box, { children: item.el }, item.id) }), _jsx(StreamingArea, { isRunning: agentLoop.isRunning, streamingText: agentLoop.streamingText, streamingThinking: agentLoop.streamingThinking, showThinking: true, thinkingMs: agentLoop.thinkingMs }), agentLoop.activeToolCalls.map((tc) => (_jsx(ToolExecution, { status: "running", name: tc.name, args: tc.args, formatters: ggEditorFormatters }, tc.toolCallId))), agentLoop.isRunning && agentLoop.activityPhase !== "idle" ? (_jsx(Box, { marginTop: 1, borderStyle: "round", borderColor: agentLoop.activityPhase === "thinking"
359
423
  ? THINKING_BORDER_COLORS[thinkingBorderFrame]
360
- : "transparent", paddingLeft: 1, paddingRight: 1, width: columns, children: _jsx(ActivityIndicator, { phase: agentLoop.activityPhase, elapsedMs: agentLoop.elapsedMs, runStartRef: agentLoop.runStartRef, thinkingMs: agentLoop.thinkingMs, isThinking: agentLoop.isThinking, tokenEstimate: agentLoop.streamedTokenEstimate, charCountRef: agentLoop.charCountRef, realTokensAccumRef: agentLoop.realTokensAccumRef, userMessage: lastUserMessage, activeToolNames: agentLoop.activeToolCalls.map((tc) => tc.name), retryInfo: agentLoop.retryInfo }) })) : agentLoop.stallError ? (_jsx(Box, { marginTop: 1, flexDirection: "column", children: _jsx(Text, { color: theme.warning, children: "⚠ Stream interrupted — retries exhausted. Your conversation is preserved." }) })) : null, _jsx(InputArea, { onSubmit: (value) => handleSubmit(value), onAbort: handleAbort, disabled: agentLoop.isRunning, isActive: overlay === null, onShiftTab: handleToggleThinking, cwd: props.cwd, commands: EDITOR_COMMANDS }), overlay === "model" ? (_jsx(ModelSelector, { onSelect: handleModelSelect, onCancel: () => setOverlay(null), loggedInProviders: props.loggedInProviders, currentModel: currentModel, currentProvider: currentProvider })) : (_jsx(Footer, { model: currentModel, tokensIn: agentLoop.contextUsed, cwd: props.cwd, thinkingEnabled: thinkingEnabled, hidePlan: true, hideCwd: true, hideGitBranch: true, exitPending: exitPending, statusLabel: composeStatusLabel(hostStatus, timelineGlance), statusColor: composeStatusColor(hostStatus, theme) }))] }));
424
+ : "transparent", paddingLeft: 1, paddingRight: 1, width: columns, children: _jsx(ActivityIndicator, { phase: agentLoop.activityPhase, elapsedMs: agentLoop.elapsedMs, runStartRef: agentLoop.runStartRef, thinkingMs: agentLoop.thinkingMs, isThinking: agentLoop.isThinking, tokenEstimate: agentLoop.streamedTokenEstimate, charCountRef: agentLoop.charCountRef, realTokensAccumRef: agentLoop.realTokensAccumRef, userMessage: lastUserMessage, activeToolNames: agentLoop.activeToolCalls.map((tc) => tc.name), retryInfo: agentLoop.retryInfo }) })) : agentLoop.stallError ? (_jsx(Box, { marginTop: 1, flexDirection: "column", children: _jsx(Text, { color: theme.warning, children: "⚠ Stream interrupted — retries exhausted. Your conversation is preserved." }) })) : null, _jsx(InputArea, { onSubmit: (value) => handleSubmit(value), onAbort: handleAbort, disabled: agentLoop.isRunning, isActive: overlay === null, onShiftTab: handleToggleThinking, cwd: props.cwd, commands: EDITOR_COMMANDS }), overlay === "model" ? (_jsx(ModelSelector, { onSelect: handleModelSelect, onCancel: () => setOverlay(null), loggedInProviders: props.loggedInProviders, currentModel: currentModel, currentProvider: currentProvider })) : (_jsx(Footer, { model: currentModel, tokensIn: agentLoop.contextUsed, cwd: props.cwd, thinkingLevel: thinkingEnabled ? getMaxThinkingLevel(currentModel) : undefined, hidePlan: true, hideCwd: true, hideGitBranch: true, exitPending: exitPending, statusLabel: composeStatusLabel(hostStatus, timelineGlance), statusColor: composeStatusColor(hostStatus, theme), statusBelow: true }))] }));
361
425
  }
362
426
  function composeStatusLabel(status, timeline) {
363
427
  if (status.name === "none")
@@ -409,7 +473,7 @@ function renderItem(item) {
409
473
  return (_jsx(AssistantMessage, { text: item.text, thinking: item.thinking, thinkingMs: item.thinkingMs, showThinking: true }, item.id));
410
474
  }
411
475
  // tool_done
412
- return (_jsx(ToolExecution, { status: "done", name: item.name, args: item.args, result: item.result, isError: item.isError, details: item.details }, item.id));
476
+ return (_jsx(ToolExecution, { status: "done", name: item.name, args: item.args, result: item.result, isError: item.isError, details: item.details, formatters: ggEditorFormatters }, item.id));
413
477
  }
414
478
  /** Convert a persisted Message into HistoryItems for resume display. */
415
479
  function messageToHistoryItems(msg, baseId) {