videobook 0.0.0-stage → 0.2.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 (565) hide show
  1. package/CHANGELOG.md +54 -0
  2. package/LICENSE +21 -0
  3. package/README.md +195 -2
  4. package/bin/videobook.js +7 -0
  5. package/dist/acestep/client.js +203 -0
  6. package/dist/acestep/config.js +62 -0
  7. package/dist/acestep/errors.js +8 -0
  8. package/dist/acestep/process.js +175 -0
  9. package/dist/alive-captions/analyze.js +117 -0
  10. package/dist/alive-captions/audio.js +179 -0
  11. package/dist/alive-captions/frames.js +59 -0
  12. package/dist/alive-captions/model.js +37 -0
  13. package/dist/alive-captions/schema.js +49 -0
  14. package/dist/alive-captions/track.js +9 -0
  15. package/dist/api-key.js +33 -0
  16. package/dist/app-state.js +56 -0
  17. package/dist/app.js +257 -0
  18. package/dist/archive-b2.js +332 -0
  19. package/dist/archive-store.js +169 -0
  20. package/dist/artifact-label.js +36 -0
  21. package/dist/artifact-refs.js +49 -0
  22. package/dist/asset-tag-extraction.js +169 -0
  23. package/dist/asset-tags.js +228 -0
  24. package/dist/asset-usage.js +23 -0
  25. package/dist/audio-cue.js +71 -0
  26. package/dist/audio-encoding.js +32 -0
  27. package/dist/audio-sync-request.js +1 -0
  28. package/dist/audio-sync.js +223 -0
  29. package/dist/audio-trim-range.js +31 -0
  30. package/dist/book-context.js +31 -0
  31. package/dist/book-manager.js +374 -0
  32. package/dist/catalog-gc.js +26 -0
  33. package/dist/chain-executor.js +815 -0
  34. package/dist/chain-generation.js +115 -0
  35. package/dist/chain-plan.js +746 -0
  36. package/dist/chain-step-review.js +60 -0
  37. package/dist/character-name.js +25 -0
  38. package/dist/chat-generation-routing.js +73 -0
  39. package/dist/chat-generation-settings.js +78 -0
  40. package/dist/chat-models.js +44 -0
  41. package/dist/chat-prompt-rewrite.js +67 -0
  42. package/dist/chat-router.js +628 -0
  43. package/dist/chat-view-actions.js +49 -0
  44. package/dist/cli/args.js +242 -0
  45. package/dist/cli/config-command.js +103 -0
  46. package/dist/cli/doctor-command.js +289 -0
  47. package/dist/cli/entry.js +2 -0
  48. package/dist/cli/key-report.js +16 -0
  49. package/dist/cli/main.js +104 -0
  50. package/dist/cli/mcp-command.js +88 -0
  51. package/dist/cli/mcp-relay.js +51 -0
  52. package/dist/cli/open-browser.js +14 -0
  53. package/dist/cli/run-command.js +231 -0
  54. package/dist/cli/serve-command.js +62 -0
  55. package/dist/cli/setup-command.js +60 -0
  56. package/dist/cli/stdio-guard.js +8 -0
  57. package/dist/cold-open-model.js +7 -0
  58. package/dist/cold-open.js +79 -0
  59. package/dist/command-reference.js +95 -0
  60. package/dist/content-store.js +74 -0
  61. package/dist/cost.js +8 -0
  62. package/dist/crop-geometry.js +23 -0
  63. package/dist/dancing-workflow.js +447 -0
  64. package/dist/data-home.js +44 -0
  65. package/dist/diagnostics.js +109 -0
  66. package/dist/dialog-quality.js +34 -0
  67. package/dist/downloads-dest.js +56 -0
  68. package/dist/editing-moments.js +194 -0
  69. package/dist/elevenlabs-audio-extension.js +66 -0
  70. package/dist/engine.js +54 -0
  71. package/dist/env-file.js +91 -0
  72. package/dist/env-secrets.js +148 -0
  73. package/dist/ffmpeg-binary.js +12 -0
  74. package/dist/ffmpeg.js +425 -0
  75. package/dist/ffprobe-binary.js +77 -0
  76. package/dist/forget-asset.js +216 -0
  77. package/dist/frame-utils.js +27 -0
  78. package/dist/generation-credit-error.js +11 -0
  79. package/dist/generation-input-mentions.js +117 -0
  80. package/dist/generation-input-policy.js +68 -0
  81. package/dist/generation-reference-mentions.js +97 -0
  82. package/dist/goal-characters.js +49 -0
  83. package/dist/goal-plan-v3.js +273 -0
  84. package/dist/goal-plan.js +220 -0
  85. package/dist/goal-planner-prompt.js +28 -0
  86. package/dist/goal-prompt-budget.js +4 -0
  87. package/dist/goal-reference-images.js +25 -0
  88. package/dist/goal-state.js +261 -0
  89. package/dist/goal-stills.js +153 -0
  90. package/dist/goal-store.js +144 -0
  91. package/dist/goal-styles.js +144 -0
  92. package/dist/goal-v3-runtime.js +157 -0
  93. package/dist/guides/character_schema_guide.md +70 -0
  94. package/dist/guides/gpt_image_2_5_prompting_guide.md +21 -0
  95. package/dist/guides/grok_imagine_prompting_guide.md +72 -0
  96. package/dist/guides/image_reproduction_guide.md +84 -0
  97. package/dist/guides/kling_3_0_prompting_guide.md +136 -0
  98. package/dist/guides/nano_banana_pro_prompting_guide.md +28 -0
  99. package/dist/guides/seedance_2_prompting_guide.md +172 -0
  100. package/dist/http-access.js +49 -0
  101. package/dist/http-byte-range.js +31 -0
  102. package/dist/hydration.js +56 -0
  103. package/dist/image-compress.js +77 -0
  104. package/dist/image-edit-default.js +1 -0
  105. package/dist/image-edit-models.js +41 -0
  106. package/dist/image-edit-settings.js +11 -0
  107. package/dist/image-region-edit.js +32 -0
  108. package/dist/image-subject-map.js +523 -0
  109. package/dist/image.js +46 -0
  110. package/dist/index.js +12 -0
  111. package/dist/job-deadline.js +60 -0
  112. package/dist/jobs/_alibaba-upload.js +30 -0
  113. package/dist/jobs/_audio-chunks.js +31 -0
  114. package/dist/jobs/_download-into-asset.js +15 -0
  115. package/dist/jobs/_fal-shared.js +22 -0
  116. package/dist/jobs/_fal-upload.js +35 -0
  117. package/dist/jobs/_image-edit-adapter.js +213 -0
  118. package/dist/jobs/_kie-poll.js +119 -0
  119. package/dist/jobs/_kie-upload.js +32 -0
  120. package/dist/jobs/_lease.js +163 -0
  121. package/dist/jobs/_persist-output.js +19 -0
  122. package/dist/jobs/_storage-retry.js +21 -0
  123. package/dist/jobs/_transcribe.js +245 -0
  124. package/dist/jobs/_translate-transcript.js +270 -0
  125. package/dist/jobs/analyze-alive-captions.js +10 -0
  126. package/dist/jobs/analyze-editing-moments.js +104 -0
  127. package/dist/jobs/analyze-jokes.js +143 -0
  128. package/dist/jobs/analyze-keyword-placement.js +155 -0
  129. package/dist/jobs/analyze-music.js +14 -0
  130. package/dist/jobs/analyze-video.js +282 -0
  131. package/dist/jobs/apply-cuts.js +83 -0
  132. package/dist/jobs/apply-sfx.js +107 -0
  133. package/dist/jobs/archive-clip.js +458 -0
  134. package/dist/jobs/assemble-goal.js +98 -0
  135. package/dist/jobs/audio-boost.js +71 -0
  136. package/dist/jobs/audio-mix.js +161 -0
  137. package/dist/jobs/backfill-asset-tags.js +144 -0
  138. package/dist/jobs/burn-watermark.js +316 -0
  139. package/dist/jobs/change-video-speed.js +176 -0
  140. package/dist/jobs/clean-video-audio.js +207 -0
  141. package/dist/jobs/cold-open.js +166 -0
  142. package/dist/jobs/combine-goal.js +108 -0
  143. package/dist/jobs/complete-provider-task.js +185 -0
  144. package/dist/jobs/copy-library-asset.js +33 -0
  145. package/dist/jobs/cost-estimate-assessment.js +113 -0
  146. package/dist/jobs/crop-image.js +47 -0
  147. package/dist/jobs/crop-video.js +71 -0
  148. package/dist/jobs/describe-image.js +181 -0
  149. package/dist/jobs/detect-scenes.js +33 -0
  150. package/dist/jobs/doctor-fix.js +100 -0
  151. package/dist/jobs/download-video.js +427 -0
  152. package/dist/jobs/enqueue-search-index.js +24 -0
  153. package/dist/jobs/even-split.js +122 -0
  154. package/dist/jobs/export-sequence.js +365 -0
  155. package/dist/jobs/extend-audio.js +229 -0
  156. package/dist/jobs/extract-audio.js +72 -0
  157. package/dist/jobs/extract-frame.js +58 -0
  158. package/dist/jobs/extract-notebook-audio.js +82 -0
  159. package/dist/jobs/extract-notebook-frame.js +93 -0
  160. package/dist/jobs/extract-video-clip.js +8 -0
  161. package/dist/jobs/extract-video-poster.js +55 -0
  162. package/dist/jobs/extract-waveform.js +25 -0
  163. package/dist/jobs/finish-goal.js +255 -0
  164. package/dist/jobs/forget-asset.js +11 -0
  165. package/dist/jobs/generate-acestep-cover.js +219 -0
  166. package/dist/jobs/generate-media.js +70 -0
  167. package/dist/jobs/image-subjects.js +1059 -0
  168. package/dist/jobs/index.js +18 -0
  169. package/dist/jobs/inject-first-frame.js +175 -0
  170. package/dist/jobs/isolate-vocals.js +69 -0
  171. package/dist/jobs/kie-paygate.js +177 -0
  172. package/dist/jobs/label-music-sections.js +5 -0
  173. package/dist/jobs/osg-placement.js +135 -0
  174. package/dist/jobs/pad-video.js +72 -0
  175. package/dist/jobs/plan-goal.js +97 -0
  176. package/dist/jobs/post-record.js +21 -0
  177. package/dist/jobs/post-to-x.js +21 -0
  178. package/dist/jobs/prepare-search-reference.js +190 -0
  179. package/dist/jobs/prepare-temporal-search.js +16 -0
  180. package/dist/jobs/process-audio.js +67 -0
  181. package/dist/jobs/process-image.js +58 -0
  182. package/dist/jobs/process-upload.js +166 -0
  183. package/dist/jobs/process-video.js +438 -0
  184. package/dist/jobs/register-all.js +161 -0
  185. package/dist/jobs/relayout-notebook.js +78 -0
  186. package/dist/jobs/remove-sound.js +299 -0
  187. package/dist/jobs/render-project.js +380 -0
  188. package/dist/jobs/render-qr-outro.js +138 -0
  189. package/dist/jobs/render-timeline.js +283 -0
  190. package/dist/jobs/repair-search-indexes.js +42 -0
  191. package/dist/jobs/replace-video-audio.js +64 -0
  192. package/dist/jobs/restore-archive-clip.js +53 -0
  193. package/dist/jobs/reverse-video.js +53 -0
  194. package/dist/jobs/rewrite-script.js +173 -0
  195. package/dist/jobs/run-notebook.js +3335 -0
  196. package/dist/jobs/semantic-index.js +797 -0
  197. package/dist/jobs/smooth-scene-concat.js +257 -0
  198. package/dist/jobs/splice-video.js +280 -0
  199. package/dist/jobs/split-video.js +127 -0
  200. package/dist/jobs/suggest-cuts.js +149 -0
  201. package/dist/jobs/suggest-sfx.js +135 -0
  202. package/dist/jobs/sync-video-to-audio.js +329 -0
  203. package/dist/jobs/tag-asset.js +266 -0
  204. package/dist/jobs/task-failure.js +16 -0
  205. package/dist/jobs/timewarp-video.js +152 -0
  206. package/dist/jobs/transcribe-video-audio.js +117 -0
  207. package/dist/jobs/transcribe.js +35 -0
  208. package/dist/jobs/translate-transcript.js +55 -0
  209. package/dist/jobs/trim-audio.js +133 -0
  210. package/dist/jobs/trim-video.js +291 -0
  211. package/dist/jobs/xai-paygate.js +26 -0
  212. package/dist/keyword-placement-cache.js +74 -0
  213. package/dist/lazy-render.js +142 -0
  214. package/dist/library-browse.js +78 -0
  215. package/dist/lightning-defaults.js +206 -0
  216. package/dist/load-env.js +12 -0
  217. package/dist/local-search-models.js +206 -0
  218. package/dist/local-upload.js +318 -0
  219. package/dist/logger.js +69 -0
  220. package/dist/media/adapters/alibaba.js +20 -0
  221. package/dist/media/adapters/elevenlabs.js +58 -0
  222. package/dist/media/adapters/fal.js +45 -0
  223. package/dist/media/adapters/index.js +26 -0
  224. package/dist/media/adapters/kie.js +120 -0
  225. package/dist/media/adapters/pending.js +21 -0
  226. package/dist/media/adapters/types.js +5 -0
  227. package/dist/media/adapters/xai.js +18 -0
  228. package/dist/media/catalog.js +236 -0
  229. package/dist/media/complete.js +191 -0
  230. package/dist/media/cost.js +45 -0
  231. package/dist/media/descriptor.js +157 -0
  232. package/dist/media/endpoints.js +11 -0
  233. package/dist/media/frame-options.js +18 -0
  234. package/dist/media/insert-video-timing.js +17 -0
  235. package/dist/media/json-schema.js +75 -0
  236. package/dist/media/legacy-task-types.js +129 -0
  237. package/dist/media/listing.js +24 -0
  238. package/dist/media/model-id.js +14 -0
  239. package/dist/media/preview.js +86 -0
  240. package/dist/media/prompt-dialects.js +65 -0
  241. package/dist/media/ref-fields.js +106 -0
  242. package/dist/media/refs.js +131 -0
  243. package/dist/media/request.js +188 -0
  244. package/dist/media/types.js +6 -0
  245. package/dist/media/wire.js +161 -0
  246. package/dist/media-library.js +535 -0
  247. package/dist/media-output-path.js +33 -0
  248. package/dist/multyculty-workflow.js +757 -0
  249. package/dist/notebook-action-catalog.js +608 -0
  250. package/dist/notebook-cell-outputs.js +726 -0
  251. package/dist/notebook-credit-retry.js +45 -0
  252. package/dist/notebook-fixtures.js +8 -0
  253. package/dist/notebook-generation-contract.js +77 -0
  254. package/dist/notebook-generation-controls.js +145 -0
  255. package/dist/notebook-goal-layout.js +40 -0
  256. package/dist/notebook-graph.js +37 -0
  257. package/dist/notebook-image-edit.js +84 -0
  258. package/dist/notebook-initial-generation-prompt.js +222 -0
  259. package/dist/notebook-live-analysis.js +941 -0
  260. package/dist/notebook-media-ops.js +579 -0
  261. package/dist/notebook-mutations.js +20 -0
  262. package/dist/notebook-placement.js +41 -0
  263. package/dist/notebook-provider-failure.js +87 -0
  264. package/dist/notebook-published-post.js +26 -0
  265. package/dist/notebook-reference-resolver.js +227 -0
  266. package/dist/notebook-relayout.js +270 -0
  267. package/dist/notebook-run-plan.js +519 -0
  268. package/dist/notebook-shots.js +162 -0
  269. package/dist/notebook-workflow.js +856 -0
  270. package/dist/one-password.js +200 -0
  271. package/dist/openai-intelligence.js +99 -0
  272. package/dist/original-media-file.js +12 -0
  273. package/dist/osg-assets.js +36 -0
  274. package/dist/osg-placement-cache.js +64 -0
  275. package/dist/osg-settings.js +27 -0
  276. package/dist/paid-tools.js +22 -0
  277. package/dist/platform-guidance.js +26 -0
  278. package/dist/posts/dropbox-auth.js +91 -0
  279. package/dist/posts/dropbox-upload.js +132 -0
  280. package/dist/posts/icloud-drive.js +134 -0
  281. package/dist/posts/icloud-status.js +64 -0
  282. package/dist/posts/post-contract.js +2 -0
  283. package/dist/posts/post-copy-format.js +43 -0
  284. package/dist/posts/post-copy.js +193 -0
  285. package/dist/posts/post-folder.js +18 -0
  286. package/dist/posts/post-metrics.js +119 -0
  287. package/dist/posts/post-store.js +340 -0
  288. package/dist/posts/x-post-target.js +43 -0
  289. package/dist/preview-payload.js +90 -0
  290. package/dist/prompt-surfaces.js +22 -0
  291. package/dist/provider-prompt-transform.js +77 -0
  292. package/dist/provider-status-link.js +21 -0
  293. package/dist/provider-task-record.js +78 -0
  294. package/dist/provider-task-status.js +47 -0
  295. package/dist/provider-usage.js +294 -0
  296. package/dist/queue.js +810 -0
  297. package/dist/reference-video-duration.js +17 -0
  298. package/dist/remotion/BlurFillVideo.js +51 -0
  299. package/dist/remotion/KeywordGraphicsOverlay.js +68 -0
  300. package/dist/remotion/OsgOverlay.js +30 -0
  301. package/dist/remotion/QrOutroComposition.js +47 -0
  302. package/dist/remotion/RenderComposition.js +11 -0
  303. package/dist/remotion/browser.js +59 -0
  304. package/dist/remotion/constants.js +35 -0
  305. package/dist/remotion/index.js +66 -0
  306. package/dist/remotion/keyword-graphics.js +151 -0
  307. package/dist/remotion/keyword-placement.js +182 -0
  308. package/dist/remotion/osg-spec.js +198 -0
  309. package/dist/remotion/public/qr-outro-impact.wav +0 -0
  310. package/dist/remotion/qr-outro-audio.js +1 -0
  311. package/dist/remotion/qr-outro-spec.js +211 -0
  312. package/dist/remotion/shared-bundle.js +37 -0
  313. package/dist/remotion/subtitles/AliveCaptions.js +83 -0
  314. package/dist/remotion/subtitles/Highlight.js +58 -0
  315. package/dist/remotion/subtitles/Impact.js +67 -0
  316. package/dist/remotion/subtitles/SubtitleOverlay.js +9 -0
  317. package/dist/remotion/subtitles/alive-layout.js +321 -0
  318. package/dist/remotion/subtitles/alive-types.js +17 -0
  319. package/dist/remotion/subtitles/chunker.js +68 -0
  320. package/dist/remotion/subtitles/segments.js +42 -0
  321. package/dist/remotion/subtitles/styles.js +4 -0
  322. package/dist/remotion/subtitles/types.js +1 -0
  323. package/dist/remotion/util.js +18 -0
  324. package/dist/remotion-cancellation.js +15 -0
  325. package/dist/rename-helpers.js +204 -0
  326. package/dist/rhythm/analyze.js +128 -0
  327. package/dist/rhythm/contract.js +14 -0
  328. package/dist/rhythm/draft-model.js +19 -0
  329. package/dist/rhythm/energy.js +133 -0
  330. package/dist/rhythm/fft.js +44 -0
  331. package/dist/rhythm/model.js +71 -0
  332. package/dist/rhythm/music-analysis.js +124 -0
  333. package/dist/rhythm/music-draft.js +261 -0
  334. package/dist/rhythm/onset.js +101 -0
  335. package/dist/rhythm/run-worker.js +51 -0
  336. package/dist/rhythm/score.js +47 -0
  337. package/dist/rhythm/section-labels.js +168 -0
  338. package/dist/rhythm/sequence-rhythm.js +67 -0
  339. package/dist/rhythm/synthesize.js +103 -0
  340. package/dist/rhythm/timing.js +98 -0
  341. package/dist/rhythm/track.js +320 -0
  342. package/dist/rhythm/visual-fit.js +4 -0
  343. package/dist/rhythm/worker.js +25 -0
  344. package/dist/scene-detect.js +200 -0
  345. package/dist/scene-transition.js +12 -0
  346. package/dist/scheduled-posts.js +200 -0
  347. package/dist/search-index-coverage.js +13 -0
  348. package/dist/search-index-media.js +71 -0
  349. package/dist/search-reference-store.js +60 -0
  350. package/dist/search-scoring.js +17 -0
  351. package/dist/serve.js +125 -0
  352. package/dist/server-lock.js +143 -0
  353. package/dist/server.js +42 -0
  354. package/dist/srt.js +16 -0
  355. package/dist/tag-backfill-state.js +121 -0
  356. package/dist/tag-settings.js +30 -0
  357. package/dist/tag-vocabulary.js +237 -0
  358. package/dist/test-queue-cleanup.js +1 -0
  359. package/dist/time-parse.js +50 -0
  360. package/dist/timeline-helpers.js +554 -0
  361. package/dist/timewarp.js +87 -0
  362. package/dist/tools/_image-inputs.js +9 -0
  363. package/dist/tools/_media-refs.js +84 -0
  364. package/dist/tools/_shared.js +59 -0
  365. package/dist/tools/_suggest-shared.js +279 -0
  366. package/dist/tools/add-timeline-audio.js +73 -0
  367. package/dist/tools/alive-captions.js +157 -0
  368. package/dist/tools/analyze-jokes.js +56 -0
  369. package/dist/tools/analyze-video.js +66 -0
  370. package/dist/tools/animate-keywords.js +217 -0
  371. package/dist/tools/api-status.js +42 -0
  372. package/dist/tools/application-commands.js +34 -0
  373. package/dist/tools/apply-cuts.js +112 -0
  374. package/dist/tools/apply-sfx.js +152 -0
  375. package/dist/tools/apply-watermark.js +670 -0
  376. package/dist/tools/archive-clip.js +74 -0
  377. package/dist/tools/asset-history.js +61 -0
  378. package/dist/tools/asset-manifest.js +24 -0
  379. package/dist/tools/asset-tags.js +151 -0
  380. package/dist/tools/assign-slot.js +97 -0
  381. package/dist/tools/audio-boost.js +107 -0
  382. package/dist/tools/audio-mix.js +121 -0
  383. package/dist/tools/book-usage.js +16 -0
  384. package/dist/tools/chain.js +136 -0
  385. package/dist/tools/change-video-speed.js +105 -0
  386. package/dist/tools/chat-history.js +5 -0
  387. package/dist/tools/chat.js +848 -0
  388. package/dist/tools/clean-video-audio.js +97 -0
  389. package/dist/tools/clear-failed-tasks.js +66 -0
  390. package/dist/tools/cold-open.js +114 -0
  391. package/dist/tools/command-plan.js +1680 -0
  392. package/dist/tools/commands.js +1666 -0
  393. package/dist/tools/concat-images.js +236 -0
  394. package/dist/tools/connect-service.js +55 -0
  395. package/dist/tools/copy-file-to-clipboard.js +58 -0
  396. package/dist/tools/create-character.js +114 -0
  397. package/dist/tools/create-qart.js +253 -0
  398. package/dist/tools/create-qr-outro.js +149 -0
  399. package/dist/tools/create-qrbtf.js +215 -0
  400. package/dist/tools/create-watermark.js +97 -0
  401. package/dist/tools/crop-asset.js +18 -0
  402. package/dist/tools/crop-image.js +120 -0
  403. package/dist/tools/crop-video.js +97 -0
  404. package/dist/tools/delete-asset.js +104 -0
  405. package/dist/tools/describe-image.js +69 -0
  406. package/dist/tools/detect-scenes.js +44 -0
  407. package/dist/tools/doctor.js +126 -0
  408. package/dist/tools/download-video.js +114 -0
  409. package/dist/tools/duplicate-asset.js +184 -0
  410. package/dist/tools/edit-timeline.js +59 -0
  411. package/dist/tools/editing-moments.js +105 -0
  412. package/dist/tools/estimate-cost.js +171 -0
  413. package/dist/tools/even-split.js +295 -0
  414. package/dist/tools/export-asset-file.js +22 -0
  415. package/dist/tools/export-asset.js +140 -0
  416. package/dist/tools/export-sequence.js +250 -0
  417. package/dist/tools/export-to-downloads.js +54 -0
  418. package/dist/tools/export-transcript-srt.js +79 -0
  419. package/dist/tools/extend-audio.js +100 -0
  420. package/dist/tools/extract-audio.js +174 -0
  421. package/dist/tools/extract-frame.js +108 -0
  422. package/dist/tools/extract-notebook-audio.js +173 -0
  423. package/dist/tools/extract-notebook-frame.js +160 -0
  424. package/dist/tools/extract-video-clip.js +101 -0
  425. package/dist/tools/generate-media.js +157 -0
  426. package/dist/tools/generation-payload.js +48 -0
  427. package/dist/tools/get-timeline.js +12 -0
  428. package/dist/tools/get-watermark-config.js +38 -0
  429. package/dist/tools/goal.js +644 -0
  430. package/dist/tools/image-subjects.js +711 -0
  431. package/dist/tools/index.js +323 -0
  432. package/dist/tools/inject-first-frame.js +154 -0
  433. package/dist/tools/invert-image.js +70 -0
  434. package/dist/tools/isolate-vocals.js +66 -0
  435. package/dist/tools/list-assets.js +98 -0
  436. package/dist/tools/list-cell-generations.js +225 -0
  437. package/dist/tools/list-elevenlabs-voices.js +163 -0
  438. package/dist/tools/log-wrapper.js +29 -0
  439. package/dist/tools/make-cover-song.js +95 -0
  440. package/dist/tools/mark-asset-seen.js +23 -0
  441. package/dist/tools/media-library.js +245 -0
  442. package/dist/tools/move-timeline-audio.js +35 -0
  443. package/dist/tools/music-analysis.js +60 -0
  444. package/dist/tools/music-draft.js +29 -0
  445. package/dist/tools/pad-video.js +87 -0
  446. package/dist/tools/post-record.js +83 -0
  447. package/dist/tools/post.js +168 -0
  448. package/dist/tools/prompt-history.js +164 -0
  449. package/dist/tools/provider-key-status.js +248 -0
  450. package/dist/tools/qrbtf-render.js +849 -0
  451. package/dist/tools/read-asset-metadata.js +26 -0
  452. package/dist/tools/read-file-at-commit.js +29 -0
  453. package/dist/tools/read-transcript.js +41 -0
  454. package/dist/tools/reconcile-project-work.js +1452 -0
  455. package/dist/tools/recover-asset.js +28 -0
  456. package/dist/tools/remove-sound.js +72 -0
  457. package/dist/tools/remove-timeline-audio.js +34 -0
  458. package/dist/tools/remove-timeline-slot.js +40 -0
  459. package/dist/tools/rename-all.js +434 -0
  460. package/dist/tools/rename-asset.js +34 -0
  461. package/dist/tools/render-settings.js +47 -0
  462. package/dist/tools/render-timeline.js +120 -0
  463. package/dist/tools/render.js +384 -0
  464. package/dist/tools/reorder-character-images.js +45 -0
  465. package/dist/tools/replace-video-audio.js +133 -0
  466. package/dist/tools/restore-archive-clips.js +209 -0
  467. package/dist/tools/restore-asset-version.js +37 -0
  468. package/dist/tools/retry-generation.js +54 -0
  469. package/dist/tools/reverse-video.js +74 -0
  470. package/dist/tools/rewrite-prompt.js +388 -0
  471. package/dist/tools/rewrite-script.js +67 -0
  472. package/dist/tools/schema-from-apicity.js +66 -0
  473. package/dist/tools/search-archive.js +150 -0
  474. package/dist/tools/semantic-search.js +1214 -0
  475. package/dist/tools/sequence-rhythm.js +43 -0
  476. package/dist/tools/set-character-metadata.js +84 -0
  477. package/dist/tools/set-env-secret.js +40 -0
  478. package/dist/tools/set-osg.js +143 -0
  479. package/dist/tools/show-folder.js +37 -0
  480. package/dist/tools/smooth-scene-concat.js +122 -0
  481. package/dist/tools/splice-video.js +149 -0
  482. package/dist/tools/split-video.js +202 -0
  483. package/dist/tools/suggest-cuts.js +45 -0
  484. package/dist/tools/suggest-sfx.js +43 -0
  485. package/dist/tools/sync-video-to-audio.js +115 -0
  486. package/dist/tools/tag-backfill.js +177 -0
  487. package/dist/tools/timewarp-video.js +85 -0
  488. package/dist/tools/tool-def.js +1 -0
  489. package/dist/tools/tool-json-schema.js +116 -0
  490. package/dist/tools/transcribe.js +90 -0
  491. package/dist/tools/translate-subtitles.js +59 -0
  492. package/dist/tools/trim-audio.js +139 -0
  493. package/dist/tools/trim-video.js +168 -0
  494. package/dist/tools/update-script.js +25 -0
  495. package/dist/tools/update-timeline-audio.js +40 -0
  496. package/dist/tools/upload-file.js +41 -0
  497. package/dist/tools/verify-x-mentions.js +141 -0
  498. package/dist/tools/video-editing-command-contract.js +291 -0
  499. package/dist/tools/video-source-reference.js +30 -0
  500. package/dist/tools/video-time-input.js +18 -0
  501. package/dist/tools/videobook-domain.js +2021 -0
  502. package/dist/tools/wait-for-asset-ready.js +143 -0
  503. package/dist/tools/workspace-actions.js +54 -0
  504. package/dist/transcript-projection.js +202 -0
  505. package/dist/transcript-srt.js +33 -0
  506. package/dist/upload.js +76 -0
  507. package/dist/usage-providers.js +25 -0
  508. package/dist/video-analysis-projection.js +46 -0
  509. package/dist/video-poster.js +33 -0
  510. package/dist/video-proxy.js +99 -0
  511. package/dist/vision-regions.js +111 -0
  512. package/dist/voice-actions.js +90 -0
  513. package/dist/voice-audio.js +55 -0
  514. package/dist/voice-config.js +122 -0
  515. package/dist/voice-continuation.js +54 -0
  516. package/dist/voice-contract.js +1 -0
  517. package/dist/voice-http.js +145 -0
  518. package/dist/voice-reply-progress.js +55 -0
  519. package/dist/voice-session.js +992 -0
  520. package/dist/watermark-badge.js +259 -0
  521. package/dist/watermark-config.js +111 -0
  522. package/dist/watermark-handle-position.js +55 -0
  523. package/dist/watermark-platform.js +15 -0
  524. package/dist/watermark-timing.js +16 -0
  525. package/dist/workspace-action-catalog.js +315 -0
  526. package/dist/workspace-action-contract.js +21 -0
  527. package/dist/workspace-action-groups.js +98 -0
  528. package/dist/workspace-action-surfaces.js +7 -0
  529. package/dist/x/account.js +88 -0
  530. package/dist/x/authenticated-handle.js +30 -0
  531. package/dist/x/oauth-flow.js +191 -0
  532. package/dist/x/post-contract.js +1 -0
  533. package/dist/x/post-metadata.js +44 -0
  534. package/dist/x/post-to-x.js +456 -0
  535. package/dist/x/published-post-cell.js +90 -0
  536. package/dist/x/x-tokens.js +69 -0
  537. package/dist/ytdlp-binary.js +65 -0
  538. package/dist/zod-slots.js +334 -0
  539. package/package.json +84 -4
  540. package/ui/assets/alive-captions-BWb5nLKj.css +1 -0
  541. package/ui/assets/alive-captions-DPEr1nKM.js +1 -0
  542. package/ui/assets/confirm-bodies-D8ouHXKy.js +1 -0
  543. package/ui/assets/confirm-bodies-DrMhaXC6.css +1 -0
  544. package/ui/assets/fullscreen-B7nw4YbE.js +1 -0
  545. package/ui/assets/goal-ui-DK-xTCK0.js +2 -0
  546. package/ui/assets/goal-ui-DXdUM2KF.css +1 -0
  547. package/ui/assets/index-DzPAnCUj.css +1 -0
  548. package/ui/assets/index-kS1905s5.js +37 -0
  549. package/ui/assets/inspector-MlzQbTVo.js +1 -0
  550. package/ui/assets/jobs-ui-CoinOWx0.js +1 -0
  551. package/ui/assets/music-video-Cbe80kmQ.js +1 -0
  552. package/ui/assets/music-video-DPaiKKEq.css +1 -0
  553. package/ui/assets/ui-Oirr9VOf.css +1 -0
  554. package/ui/assets/ui-xo_Y1yQg.js +2 -0
  555. package/ui/assets/vendor-D2rfiZ5j.css +1 -0
  556. package/ui/assets/vendor-DfTCWgKm.js +19 -0
  557. package/ui/assets/vendor-flow-BXbeWxW7.js +7 -0
  558. package/ui/assets/vendor-flow-BnuhLJ6X.css +1 -0
  559. package/ui/assets/vendor-icons-CGqhCIXV.js +1 -0
  560. package/ui/assets/vendor-mcp-BTlEJcHV.js +67 -0
  561. package/ui/assets/vendor-react-Dj7D1fD4.js +9 -0
  562. package/ui/assets/vendor-remotion-CH1HXrlc.js +95 -0
  563. package/ui/assets/videobook-Qlp9HQFu.js +20 -0
  564. package/ui/favicon.svg +8 -0
  565. package/ui/index.html +126 -0
@@ -0,0 +1,1666 @@
1
+ import { z } from "zod";
2
+ import { bookManager } from "../engine.js";
3
+ import { APPLICATION_COMMANDS } from "./application-commands.js";
4
+ import { VIDEO_EDITING_COMMANDS, canonicalizeCommands, } from "./video-editing-command-contract.js";
5
+ const CANONICAL_COMMANDS = [
6
+ ...VIDEO_EDITING_COMMANDS,
7
+ {
8
+ command: "/post",
9
+ description: "Post a video or image asset to X (Twitter), now or scheduled",
10
+ example: "/post @hero-clip Check this out!",
11
+ category: "action",
12
+ icon: "Share2",
13
+ size: "default",
14
+ variant: "blue",
15
+ chevron: "right",
16
+ params: [
17
+ { name: "asset_ref", type: "string", required: false, description: "Asset to post (video or image artifact id)" },
18
+ { name: "text", type: "string", required: false, description: "Post title (max 280 chars, or 25,000 with X Premium; the confirm sheet asks for it when omitted)" },
19
+ ],
20
+ uiAction: "open_post_composer",
21
+ },
22
+ {
23
+ command: "/character",
24
+ description: "Create a character folder",
25
+ example: "/character bob",
26
+ category: "action",
27
+ icon: "User",
28
+ size: "default",
29
+ variant: "pink",
30
+ chevron: "right",
31
+ params: [
32
+ { name: "args", type: "string[]", required: true, description: "Name of the character OR one or more image artifact ids" },
33
+ ],
34
+ mcpTool: { tool: "create_character", autoInject: ["book_id"] },
35
+ },
36
+ {
37
+ command: "/crop",
38
+ description: "Crop video or image to a 16:9, 9:16, or 1:1 region (visually place the box, then re-render)",
39
+ example: "/crop @a1 9:16",
40
+ category: "context_menu",
41
+ icon: "Crop",
42
+ size: "default",
43
+ variant: "default",
44
+ chevron: "right",
45
+ params: [
46
+ { name: "asset_id", type: "string", required: true, description: "Video or image asset to crop" },
47
+ { name: "ratio", type: "string", required: false, description: "Initial ratio: 16:9 | 9:16 | 1:1" },
48
+ ],
49
+ uiAction: "open_crop",
50
+ },
51
+ {
52
+ command: "/invert",
53
+ description: "In-place inverts an image asset (negates colors)",
54
+ example: "/invert @a1",
55
+ category: "context_menu",
56
+ icon: "ImageOff",
57
+ size: "default",
58
+ variant: "default",
59
+ chevron: "right",
60
+ params: [
61
+ { name: "asset_id", type: "string", required: true, description: "Image asset to invert" },
62
+ ],
63
+ mcpTool: { tool: "invert_image", autoInject: ["book_id"] },
64
+ },
65
+ {
66
+ command: "/pad",
67
+ description: "Add a whole-second video tail with black frames and silence",
68
+ example: "/pad @a1 2s",
69
+ category: "context_menu",
70
+ icon: "SquareSquare",
71
+ size: "default",
72
+ variant: "default",
73
+ chevron: "right",
74
+ params: [
75
+ { name: "asset_id", type: "string", required: true, description: "Video asset to pad" },
76
+ { name: "padding", type: "string", required: true, description: "Padding duration (e.g. 2s)" },
77
+ ],
78
+ mcpTool: { tool: "pad_video", autoInject: ["book_id"] },
79
+ },
80
+ {
81
+ command: "/keywords",
82
+ description: "Animate transcript keywords in face-safe open space, or omit words for automatic selection",
83
+ example: "/keywords @a1 Multicultural Revolution Success",
84
+ category: "action",
85
+ icon: "Sparkles",
86
+ size: "default",
87
+ variant: "violet",
88
+ chevron: "right",
89
+ params: [
90
+ { name: "asset_id", type: "string", required: true, description: "Video asset with a timed transcript" },
91
+ { name: "inputs", type: "string[]", required: false, description: "Exact transcript words, or: on [max] [linger] | off" },
92
+ ],
93
+ mcpTool: { tool: "animate_keywords", adapter: "keywords", autoInject: ["book_id"] },
94
+ },
95
+ {
96
+ command: "/download",
97
+ description: "Download video from URL",
98
+ example: "/download https://youtube.com/watch?v=abc123",
99
+ category: "action",
100
+ icon: "Download",
101
+ size: "lg",
102
+ variant: "default",
103
+ chevron: "right",
104
+ params: [
105
+ { name: "url", type: "string", required: true, description: "Video URL (YouTube, Twitter/X, Instagram, TikTok, etc.)" },
106
+ { name: "start_time", type: "string", required: false, description: "Requested start time metadata (e.g. '30', '1:30', '2m20s')" },
107
+ { name: "end_time", type: "string", required: false, description: "Requested end time metadata (e.g. '60', '2:00', '3m')" },
108
+ { name: "full", type: "boolean", required: false, description: "Deprecated; downloads are always full" },
109
+ ],
110
+ mcpTool: { tool: "download_video", autoInject: ["book_id"] },
111
+ },
112
+ {
113
+ command: "/upload",
114
+ description: "Upload a file",
115
+ example: "/upload",
116
+ category: "action",
117
+ icon: "Upload",
118
+ size: "default",
119
+ variant: "default",
120
+ chevron: "right",
121
+ params: [],
122
+ uiAction: "open_upload",
123
+ },
124
+ {
125
+ command: "/inbox",
126
+ description: "View generations inbox",
127
+ example: "/inbox",
128
+ category: "action",
129
+ icon: "Mailbox",
130
+ size: "default",
131
+ variant: "default",
132
+ chevron: "down",
133
+ params: [],
134
+ uiAction: "open_inbox",
135
+ },
136
+ {
137
+ command: "/activity",
138
+ description: "View project activity log",
139
+ example: "/activity",
140
+ category: "action",
141
+ icon: "History",
142
+ size: "default",
143
+ variant: "zinc",
144
+ chevron: "down",
145
+ params: [],
146
+ uiAction: "open_status",
147
+ aliases: ["/status"],
148
+ },
149
+ {
150
+ command: "/copy",
151
+ description: "Copy asset name",
152
+ example: "/copy @hero-intro",
153
+ category: "context_menu",
154
+ icon: "ClipboardCopy",
155
+ size: "default",
156
+ variant: "default",
157
+ chevron: "right",
158
+ params: [
159
+ { name: "asset_id", type: "string", required: true, description: "Asset whose name to copy" },
160
+ ],
161
+ uiAction: "copy_clipboard",
162
+ },
163
+ {
164
+ command: "/folder",
165
+ description: "Show asset folder",
166
+ example: "/folder @a1",
167
+ category: "context_menu",
168
+ icon: "FolderOpen",
169
+ size: "default",
170
+ variant: "default",
171
+ chevron: "right",
172
+ params: [
173
+ { name: "asset_id", type: "string", required: true, description: "Asset to open folder for" },
174
+ ],
175
+ mcpTool: { tool: "export_asset_file", autoInject: ["book_id"], injectParams: { to: "finder" } },
176
+ },
177
+ {
178
+ command: "/describe",
179
+ description: "Describe image into a reproduction-ready prompt",
180
+ example: "/describe @a1",
181
+ category: "context_menu",
182
+ icon: "ScanEye",
183
+ size: "default",
184
+ variant: "default",
185
+ chevron: "right",
186
+ params: [
187
+ { name: "asset_id", type: "string", required: true, description: "Image asset to describe" },
188
+ ],
189
+ mcpTool: { tool: "describe_image", autoInject: ["book_id"] },
190
+ },
191
+ {
192
+ command: "/suggest-cuts",
193
+ description: "Suggest video trims for pacing and transitions, using dialogue when available",
194
+ example: "/suggest-cuts @a1",
195
+ category: "context_menu",
196
+ icon: "Scissors",
197
+ size: "default",
198
+ variant: "default",
199
+ chevron: "right",
200
+ params: [
201
+ { name: "asset_id", type: "string", required: true, description: "Video asset to analyze" },
202
+ ],
203
+ mcpTool: { tool: "suggest_cuts", autoInject: ["book_id"] },
204
+ },
205
+ {
206
+ command: "/recover",
207
+ description: "Recover an asset stuck in the failed state (clears the error, keeps the media)",
208
+ example: "/recover @a1",
209
+ category: "context_menu",
210
+ icon: "RotateCcw",
211
+ size: "default",
212
+ variant: "default",
213
+ chevron: "right",
214
+ params: [
215
+ { name: "asset_id", type: "string", required: true, description: "Failed asset to recover" },
216
+ ],
217
+ mcpTool: { tool: "recover_asset", autoInject: ["book_id"] },
218
+ },
219
+ {
220
+ command: "/doctor",
221
+ description: "Diagnose project health across all asset types (broken + stuck assets). Add an asset and 'fix' to restore that asset to its last usable state.",
222
+ example: "/doctor · /doctor @a1 fix",
223
+ category: "action",
224
+ icon: "Stethoscope",
225
+ size: "default",
226
+ variant: "emerald",
227
+ chevron: "right",
228
+ params: [
229
+ { name: "asset_id", type: "string", required: false, description: "Asset to diagnose; required to fix (artifact id or grid address such as @a1). Omit for a full project scan." },
230
+ { name: "fix", type: "boolean", required: false, description: "Restore the asset to its last usable state before the current error. Requires asset_id." },
231
+ ],
232
+ mcpTool: { tool: "doctor", autoInject: ["book_id"] },
233
+ },
234
+ {
235
+ command: "/analyze-jokes",
236
+ description: "Identify the jokes in a clip's transcript, classified by type",
237
+ example: "/analyze-jokes @a1",
238
+ category: "context_menu",
239
+ icon: "Laugh",
240
+ size: "default",
241
+ variant: "default",
242
+ chevron: "right",
243
+ params: [
244
+ { name: "asset_id", type: "string", required: true, description: "Video asset with an ElevenLabs transcript to analyze" },
245
+ ],
246
+ mcpTool: { tool: "analyze_jokes", autoInject: ["book_id"] },
247
+ },
248
+ {
249
+ command: "/suggest-sfx",
250
+ description: "Suggest sound-effect placements for a video",
251
+ example: "/suggest-sfx @a1",
252
+ category: "context_menu",
253
+ icon: "Volume2",
254
+ size: "default",
255
+ variant: "default",
256
+ chevron: "right",
257
+ params: [
258
+ { name: "asset_id", type: "string", required: true, description: "Video asset to analyze" },
259
+ ],
260
+ mcpTool: { tool: "suggest_sfx", autoInject: ["book_id"] },
261
+ },
262
+ {
263
+ command: "/apply-sfx",
264
+ description: "Generate an ElevenLabs sound effect and mix it into a video in place",
265
+ example: "/apply-sfx @a1 2.5 whoosh fast cinematic transition whoosh",
266
+ category: "action",
267
+ icon: "Volume2",
268
+ size: "default",
269
+ variant: "emerald",
270
+ chevron: "right",
271
+ params: [
272
+ { name: "asset_id", type: "string", required: true, description: "Video artifact to modify in place" },
273
+ { name: "timestamp", type: "number", required: true, description: "Seconds into the video where the effect starts" },
274
+ { name: "type", type: "string", required: true, description: "Short effect type such as whoosh, impact, or ding" },
275
+ { name: "description", type: "string", required: true, description: "Description of the sound effect to generate" },
276
+ ],
277
+ mcpTool: { tool: "apply_sfx", adapter: "apply_sfx", autoInject: ["book_id"] },
278
+ },
279
+ {
280
+ command: "/notebook",
281
+ description: "Open a project Notebook — a workflow of prompt, image, and video steps. Opens the existing notebook when present; creates 'scratch' by default.",
282
+ example: "/notebook scratch",
283
+ category: "action",
284
+ icon: "NotebookPen",
285
+ size: "default",
286
+ variant: "emerald",
287
+ chevron: "right",
288
+ params: [
289
+ { name: "name", type: "string", required: false, description: "Notebook name. Omit to open the current/default notebook, or create 'scratch' if none exist." },
290
+ ],
291
+ uiAction: "open_notebook",
292
+ },
293
+ {
294
+ command: "/goal",
295
+ description: "Build a portrait video in Cinematic or IG Influencer style; choose format, delivery, camera and light before the frame, then review each stage",
296
+ example: "/goal @a1 as an IG influencer, GRWM morning routine",
297
+ category: "action",
298
+ icon: "Wand2",
299
+ size: "lg",
300
+ variant: "violet",
301
+ chevron: "right",
302
+ params: [{ name: "brief", type: "string", required: false, description: "Mention the character image cells, then describe the video, clip count and duration. Omit to show the current goal." }],
303
+ uiAction: "start_goal",
304
+ exposure: "ui",
305
+ },
306
+ {
307
+ command: "/music-video",
308
+ description: "Open the full-screen music-video editor with a required master soundtrack",
309
+ example: "/music-video @a1",
310
+ category: "action",
311
+ icon: "AudioWaveform",
312
+ size: "lg",
313
+ variant: "violet",
314
+ chevron: "right",
315
+ params: [
316
+ { name: "audio_ref", type: "string", required: true, description: "Ready audio artifact or notebook address used as the master soundtrack" },
317
+ ],
318
+ uiAction: "open_music_video",
319
+ exposure: "ui",
320
+ },
321
+ {
322
+ command: "/alive",
323
+ description: "Open the full-screen alive captions studio: stacked, frame-aware subtitles timed to the vocals",
324
+ example: "/alive @c4",
325
+ category: "action",
326
+ icon: "captions",
327
+ size: "lg",
328
+ variant: "emerald",
329
+ chevron: "right",
330
+ params: [
331
+ { name: "asset_ref", type: "string", required: true, description: "Video artifact or notebook address with a timed transcript" },
332
+ ],
333
+ uiAction: "open_alive_captions",
334
+ exposure: "ui",
335
+ },
336
+ {
337
+ command: "/notebooks",
338
+ description: "List first-class notebooks in the current project",
339
+ example: "/notebooks",
340
+ category: "action",
341
+ icon: "BookOpen",
342
+ size: "default",
343
+ variant: "emerald",
344
+ chevron: "down",
345
+ params: [],
346
+ mcpTool: { tool: "list_notebooks", autoInject: ["book_id"] },
347
+ },
348
+ {
349
+ command: "/save",
350
+ description: "Save the active notebook as a new revision",
351
+ example: "/save",
352
+ category: "action",
353
+ icon: "Save",
354
+ size: "default",
355
+ variant: "emerald",
356
+ chevron: "right",
357
+ params: [],
358
+ uiAction: "save_notebook",
359
+ },
360
+ {
361
+ command: "/run",
362
+ description: "Save and run the active notebook",
363
+ example: "/run",
364
+ category: "action",
365
+ icon: "Play",
366
+ size: "lg",
367
+ variant: "emerald",
368
+ chevron: "right",
369
+ params: [],
370
+ uiAction: "run_notebook",
371
+ },
372
+ {
373
+ command: "/prompt-new",
374
+ description: "Create a reusable prompt entity",
375
+ example: "/prompt-new hero-portrait cinematic astronaut portrait",
376
+ category: "action",
377
+ icon: "MessageSquareText",
378
+ size: "default",
379
+ variant: "emerald",
380
+ chevron: "right",
381
+ params: [
382
+ { name: "name", type: "string", required: true, description: "Prompt entity name" },
383
+ { name: "prompt", type: "string", required: false, description: "Reusable prompt text" },
384
+ ],
385
+ mcpTool: { tool: "create_entity", autoInject: ["book_id"], injectParams: { kind: "prompt" } },
386
+ },
387
+ {
388
+ command: "/character-new",
389
+ description: "Create a reusable Videobook character entity",
390
+ example: "/character-new luna calm lunar gardener",
391
+ category: "action",
392
+ icon: "UserRound",
393
+ size: "default",
394
+ variant: "pink",
395
+ chevron: "right",
396
+ params: [
397
+ { name: "name", type: "string", required: true, description: "Character entity name" },
398
+ { name: "prompt", type: "string", required: false, description: "Reusable character prompt" },
399
+ ],
400
+ mcpTool: { tool: "create_entity", autoInject: ["book_id"], injectParams: { kind: "character" } },
401
+ },
402
+ {
403
+ command: "/scene-new",
404
+ description: "Create a reusable scene entity",
405
+ example: "/scene-new moon-garden silver greenhouse at night",
406
+ category: "action",
407
+ icon: "Film",
408
+ size: "default",
409
+ variant: "violet",
410
+ chevron: "right",
411
+ params: [
412
+ { name: "name", type: "string", required: true, description: "Scene entity name" },
413
+ { name: "prompt", type: "string", required: false, description: "Reusable scene prompt" },
414
+ ],
415
+ mcpTool: { tool: "create_entity", autoInject: ["book_id"], injectParams: { kind: "scene" } },
416
+ },
417
+ {
418
+ command: "/entities",
419
+ description: "Open the reusable entity library",
420
+ example: "/entities",
421
+ category: "action",
422
+ icon: "Library",
423
+ size: "default",
424
+ variant: "emerald",
425
+ chevron: "down",
426
+ params: [],
427
+ uiAction: "open_entities",
428
+ },
429
+ {
430
+ command: "/jobs",
431
+ description: "Open persistent jobs for the current project",
432
+ example: "/jobs",
433
+ category: "action",
434
+ icon: "Activity",
435
+ size: "default",
436
+ variant: "zinc",
437
+ chevron: "down",
438
+ params: [],
439
+ uiAction: "open_jobs",
440
+ },
441
+ {
442
+ command: "/revisions",
443
+ description: "Open forward-only project revision history",
444
+ example: "/revisions",
445
+ category: "action",
446
+ icon: "History",
447
+ size: "default",
448
+ variant: "zinc",
449
+ chevron: "down",
450
+ params: [],
451
+ uiAction: "open_revisions",
452
+ },
453
+ {
454
+ command: "/storage",
455
+ description: "Open DoltLite and content-store diagnostics",
456
+ example: "/storage",
457
+ category: "action",
458
+ icon: "Database",
459
+ size: "default",
460
+ variant: "zinc",
461
+ chevron: "down",
462
+ params: [],
463
+ uiAction: "open_diagnostics",
464
+ },
465
+ {
466
+ command: "/sync",
467
+ description: "Publish pending content-addressed objects",
468
+ example: "/sync",
469
+ category: "action",
470
+ icon: "RefreshCw",
471
+ size: "default",
472
+ variant: "zinc",
473
+ chevron: "right",
474
+ params: [],
475
+ mcpTool: { tool: "storage_sync" },
476
+ },
477
+ {
478
+ command: "/providers",
479
+ description: "Open provider credentials and routing settings",
480
+ example: "/providers",
481
+ category: "action",
482
+ icon: "Settings",
483
+ size: "default",
484
+ variant: "zinc",
485
+ chevron: "down",
486
+ params: [],
487
+ uiAction: "open_provider_keys",
488
+ },
489
+ {
490
+ command: "/diagnostics",
491
+ description: "Open MCP, catalog, CAS, and publication diagnostics",
492
+ example: "/diagnostics",
493
+ category: "action",
494
+ icon: "CircleDot",
495
+ size: "default",
496
+ variant: "zinc",
497
+ chevron: "down",
498
+ params: [],
499
+ uiAction: "open_diagnostics",
500
+ },
501
+ {
502
+ command: "/detect-scenes",
503
+ description: "Run ffmpeg scdet over a video asset and report natural visual break candidates (camera cuts + motion-settle points).",
504
+ example: "/detect-scenes @a1",
505
+ category: "context_menu",
506
+ icon: "Scissors",
507
+ size: "default",
508
+ variant: "default",
509
+ chevron: "right",
510
+ params: [
511
+ { name: "source_asset_id", type: "string", required: true, description: "Video artifact id inside the project" },
512
+ ],
513
+ mcpTool: { tool: "detect_scenes", autoInject: ["book_id"] },
514
+ },
515
+ {
516
+ command: "/rename-all",
517
+ description: "Bulk-rename video/image assets with an explicit dry run: GPT-5.5 proposes descriptive names from each asset's stored context, you edit them in a side-by-side preview, then confirm to apply (updates timeline slots, OSG metadata, and plan/.plan.json references).",
518
+ example: "/rename-all",
519
+ category: "action",
520
+ icon: "Tags",
521
+ size: "default",
522
+ variant: "blue",
523
+ chevron: "right",
524
+ params: [],
525
+ uiAction: "open_rename_all",
526
+ },
527
+ {
528
+ command: "/edit-cold-open",
529
+ description: "Review an AI-selected highlight, then create a copy with the highlight followed by the full original clip",
530
+ example: "/edit-cold-open @a1",
531
+ category: "viewer",
532
+ icon: "Scissors",
533
+ size: "default",
534
+ variant: "default",
535
+ chevron: "right",
536
+ params: [{ name: "asset_ref", type: "string", required: false, description: "Source video; defaults to the selected video" }],
537
+ uiAction: "open_cold_open",
538
+ exposure: "composite",
539
+ },
540
+ {
541
+ command: "/upload-post-to-dropbox",
542
+ description: "Review a Post's clip, caption and destination folder, then upload them to a private Dropbox folder",
543
+ example: "/upload-post-to-dropbox @b1",
544
+ category: "action",
545
+ icon: "Upload",
546
+ size: "default",
547
+ variant: "default",
548
+ chevron: "right",
549
+ params: [{ name: "post_ref", type: "string", required: false, description: "Post cell; defaults to the selected Post" }],
550
+ uiAction: "open_post_dropbox",
551
+ exposure: "composite",
552
+ },
553
+ {
554
+ command: "/save-post-to-icloud",
555
+ description: "Review a Post's clip and caption, then save them to the shared iCloud Drive Videobook folder so they appear on iPhone",
556
+ example: "/save-post-to-icloud @b1",
557
+ category: "action",
558
+ icon: "Upload",
559
+ size: "default",
560
+ variant: "default",
561
+ chevron: "right",
562
+ params: [{ name: "post_ref", type: "string", required: false, description: "Post cell; defaults to the selected Post" }],
563
+ uiAction: "open_post_icloud",
564
+ exposure: "composite",
565
+ },
566
+ {
567
+ command: "/watermark",
568
+ description: "Open the chat watermark review with a positioned QR plus a centered floating handle, live preview, and timing controls",
569
+ example: "/watermark @a1",
570
+ category: "viewer",
571
+ icon: "QrCode",
572
+ size: "default",
573
+ variant: "default",
574
+ chevron: "right",
575
+ params: [
576
+ { name: "asset_ref", type: "string", required: false, description: "Video to watermark (video artifact id); defaults to the open clip" },
577
+ ],
578
+ uiAction: "open_watermark",
579
+ exposure: "composite",
580
+ },
581
+ {
582
+ command: "/qart",
583
+ description: "Create scan-safe color and monochrome QR mosaics from an image source",
584
+ example: "/qart @a1 https://example.com",
585
+ category: "action",
586
+ icon: "QrCode",
587
+ size: "default",
588
+ variant: "amber",
589
+ chevron: "right",
590
+ params: [
591
+ { name: "image_ref", type: "string", required: true, description: "Cover image artifact id" },
592
+ { name: "value", type: "string", required: true, description: "URL or text to encode in the QR" },
593
+ ],
594
+ mcpTool: { tool: "create_qart", autoInject: ["book_id"] },
595
+ },
596
+ {
597
+ command: "/qrbtf",
598
+ description: "Generate a parametric QR code in an artistic style (normal, line, dsj, bubble, func)",
599
+ example: "/qrbtf https://example.com normal",
600
+ category: "action",
601
+ icon: "QrCode",
602
+ size: "default",
603
+ variant: "default",
604
+ chevron: "right",
605
+ params: [
606
+ { name: "value", type: "string", required: true, description: "URL or text to encode in the QR" },
607
+ { name: "style", type: "string", required: false, description: "QR style: normal, line, dsj, bubble, or func (default: normal)" },
608
+ ],
609
+ mcpTool: { tool: "create_qrbtf", adapter: "qrbtf", autoInject: ["book_id"] },
610
+ },
611
+ {
612
+ command: "/outroqr",
613
+ description: "Generate a 10-second animated QR outro with bundled impact sound",
614
+ example: "/outroqr @a1 @a2 16:9",
615
+ category: "action",
616
+ icon: "QrCode",
617
+ size: "default",
618
+ variant: "amber",
619
+ chevron: "right",
620
+ params: [
621
+ { name: "inputs", type: "string[]", required: true, description: "1-4 QR images and an optional aspect ratio" },
622
+ ],
623
+ mcpTool: {
624
+ tool: "create_qr_outro",
625
+ adapter: "qr_outro",
626
+ autoInject: ["book_id"],
627
+ injectParams: { duration_seconds: 10, include_audio: true },
628
+ },
629
+ },
630
+ {
631
+ command: "/concat",
632
+ description: "Compose one or two image assets into a 16:9 two-slot sheet; omit the second image to leave an empty cell",
633
+ example: "/concat @a1 @a2",
634
+ category: "action",
635
+ icon: "Images",
636
+ size: "default",
637
+ variant: "default",
638
+ chevron: "right",
639
+ params: [
640
+ { name: "image_refs", type: "string[]", required: true, description: "One or two image artifact ids; one leaves the second slot empty" },
641
+ ],
642
+ mcpTool: { tool: "concat_images", autoInject: ["book_id"] },
643
+ },
644
+ {
645
+ command: "/rewrite-script",
646
+ description: "Rewrite a script asset in place with the full describe model",
647
+ example: "/rewrite-script @a1",
648
+ category: "context_menu",
649
+ icon: "RefreshCw",
650
+ size: "default",
651
+ variant: "default",
652
+ chevron: "right",
653
+ params: [
654
+ { name: "asset_id", type: "string", required: true, description: "Script asset to rewrite" },
655
+ { name: "platform", type: "string", required: false, description: "Platform preset: ig | tiktok | youtube" },
656
+ { name: "custom_prompt", type: "string", required: false, description: "Optional transformation instruction" },
657
+ ],
658
+ mcpTool: { tool: "rewrite_script", adapter: "rewrite_script", autoInject: ["book_id"], injectParams: { variant: "full" } },
659
+ },
660
+ {
661
+ command: "/tldr",
662
+ description: "Rewrite a script asset in place as a 1–2 sentence TLDR",
663
+ example: "/tldr @a1",
664
+ category: "context_menu",
665
+ icon: "Zap",
666
+ size: "default",
667
+ variant: "default",
668
+ chevron: "right",
669
+ params: [
670
+ { name: "asset_id", type: "string", required: true, description: "Script asset to rewrite" },
671
+ { name: "platform", type: "string", required: false, description: "Platform preset: ig | tiktok | youtube" },
672
+ { name: "custom_prompt", type: "string", required: false, description: "Optional transformation instruction" },
673
+ ],
674
+ mcpTool: { tool: "rewrite_script", adapter: "rewrite_script", autoInject: ["book_id"], injectParams: { variant: "tldr" } },
675
+ },
676
+ {
677
+ command: "/copy-media",
678
+ description: "Copy an asset's primary media file to the clipboard",
679
+ example: "/copy-media @hero-intro",
680
+ category: "context_menu",
681
+ icon: "ClipboardCopy",
682
+ size: "default",
683
+ variant: "default",
684
+ chevron: "right",
685
+ params: [
686
+ { name: "asset_id", type: "string", required: true, description: "Asset to copy to clipboard" },
687
+ ],
688
+ mcpTool: { tool: "export_asset_file", autoInject: ["book_id"], injectParams: { to: "clipboard" } },
689
+ aliases: ["/copy-video"],
690
+ },
691
+ {
692
+ command: "/export",
693
+ description: "Export asset to Downloads folder",
694
+ example: "/export @hero-intro",
695
+ category: "context_menu",
696
+ icon: "Download",
697
+ size: "default",
698
+ variant: "default",
699
+ chevron: "right",
700
+ params: [
701
+ { name: "asset_id", type: "string", required: true, description: "Asset to export" },
702
+ ],
703
+ mcpTool: { tool: "export_asset_file", autoInject: ["book_id"], injectParams: { to: "downloads" } },
704
+ },
705
+ {
706
+ command: "/duplicate",
707
+ description: "Duplicate an asset into an optional notebook destination",
708
+ example: "/duplicate @a1 @b1",
709
+ category: "context_menu",
710
+ icon: "Copy",
711
+ size: "default",
712
+ variant: "default",
713
+ chevron: "right",
714
+ params: [
715
+ { name: "asset_id", type: "string", required: true, description: "Asset to duplicate" },
716
+ { name: "new_name", type: "string", required: false, description: "Optional name for the copy", consumeRest: true },
717
+ { name: "destination", type: "string", required: false, description: "Optional empty destination cell from a1 through bl8" },
718
+ ],
719
+ mcpTool: {
720
+ tool: "duplicate_asset",
721
+ adapter: "duplicate",
722
+ autoInject: ["book_id", "notebook_id"],
723
+ },
724
+ },
725
+ {
726
+ command: "/arrange-videos-column",
727
+ description: "Stack all video cells into the current column starting at the selected cell; cells in the way move to free slots",
728
+ example: "/arrange-videos-column",
729
+ category: "action",
730
+ icon: "Columns3",
731
+ size: "default",
732
+ variant: "blue",
733
+ chevron: "right",
734
+ params: [],
735
+ exposure: "composite",
736
+ },
737
+ {
738
+ command: "/arrange-videos-row",
739
+ description: "Line up all video cells across the current row starting at the selected cell; cells in the way move to free slots",
740
+ example: "/arrange-videos-row",
741
+ category: "action",
742
+ icon: "Rows3",
743
+ size: "default",
744
+ variant: "emerald",
745
+ chevron: "right",
746
+ params: [],
747
+ exposure: "composite",
748
+ },
749
+ {
750
+ command: "/group-images",
751
+ description: "Gather all image cells into horizontal lines starting at the selected cell, wrapping onto the next row at the grid edge; cells in the way move to free slots",
752
+ example: "/group-images",
753
+ category: "action",
754
+ icon: "Images",
755
+ size: "default",
756
+ variant: "violet",
757
+ chevron: "right",
758
+ params: [],
759
+ exposure: "composite",
760
+ },
761
+ {
762
+ command: "/history",
763
+ description: "View asset version history",
764
+ example: "/history @hero-intro",
765
+ category: "context_menu",
766
+ icon: "History",
767
+ size: "default",
768
+ variant: "default",
769
+ chevron: "right",
770
+ params: [
771
+ { name: "asset_id", type: "string", required: true, description: "Asset to view history for" },
772
+ ],
773
+ uiAction: "show_history",
774
+ },
775
+ {
776
+ command: "/open",
777
+ description: "Open asset in viewer",
778
+ example: "/open @hero-intro",
779
+ category: "context_menu",
780
+ icon: "Eye",
781
+ size: "default",
782
+ variant: "default",
783
+ chevron: "right",
784
+ params: [
785
+ { name: "asset_id", type: "string", required: true, description: "Asset to open" },
786
+ ],
787
+ uiAction: "open_asset",
788
+ },
789
+ {
790
+ command: "/delete",
791
+ description: "Delete an asset",
792
+ example: "/delete @outro-clip",
793
+ category: "context_menu",
794
+ icon: "Trash2",
795
+ size: "default",
796
+ variant: "default",
797
+ chevron: "right",
798
+ params: [
799
+ { name: "asset_id", type: "string", required: true, description: "Asset to delete" },
800
+ ],
801
+ mcpTool: { tool: "delete_asset", autoInject: ["book_id"] },
802
+ },
803
+ {
804
+ command: "/rename",
805
+ description: "Rename an asset",
806
+ example: "/rename @a1 product-hero",
807
+ category: "context_menu",
808
+ icon: "Pencil",
809
+ size: "default",
810
+ variant: "default",
811
+ chevron: "right",
812
+ params: [
813
+ { name: "asset_id", type: "string", required: true, description: "Asset to rename" },
814
+ { name: "new_name", type: "string", required: true, description: "New display name" },
815
+ ],
816
+ mcpTool: { tool: "rename_asset", autoInject: ["book_id"] },
817
+ },
818
+ {
819
+ command: "/inject-first-frame",
820
+ description: "Replace frame zero of a video or final output with an image while preserving audio and timing",
821
+ example: "/inject-first-frame @a1 @a2",
822
+ category: "context_menu",
823
+ icon: "ImagePlus",
824
+ size: "default",
825
+ variant: "default",
826
+ chevron: "right",
827
+ params: [
828
+ { name: "target_asset_id", type: "string", required: true, description: "Target video artifact id or final" },
829
+ { name: "image_asset_id", type: "string", required: true, description: "Source image artifact id" },
830
+ { name: "orientation", type: "string", required: false, description: "For final: landscape, portrait, or square" },
831
+ ],
832
+ mcpTool: { tool: "inject_first_frame", autoInject: ["book_id"] },
833
+ },
834
+ {
835
+ command: "/extract-first-frame",
836
+ description: "Extract first frame from video as image asset",
837
+ example: "/extract-first-frame @a1",
838
+ category: "context_menu",
839
+ icon: "Image",
840
+ size: "default",
841
+ variant: "default",
842
+ chevron: "right",
843
+ params: [
844
+ { name: "asset_id", type: "string", required: true, description: "Video asset to extract from" },
845
+ ],
846
+ mcpTool: { tool: "extract_frame", autoInject: ["book_id"], injectParams: { frame: "first" } },
847
+ },
848
+ {
849
+ command: "/extract-last-frame",
850
+ description: "Extract last frame from video as image asset",
851
+ example: "/extract-last-frame @a1",
852
+ category: "context_menu",
853
+ icon: "Image",
854
+ size: "default",
855
+ variant: "default",
856
+ chevron: "right",
857
+ params: [
858
+ { name: "asset_id", type: "string", required: true, description: "Video asset to extract from" },
859
+ ],
860
+ mcpTool: { tool: "extract_frame", autoInject: ["book_id"], injectParams: { frame: "last" } },
861
+ },
862
+ {
863
+ command: "/extract-audio",
864
+ description: "Extract audio track from video as audio asset (MP3)",
865
+ example: "/extract-audio @a1",
866
+ category: "context_menu",
867
+ icon: "Music",
868
+ size: "default",
869
+ variant: "emerald",
870
+ chevron: "right",
871
+ params: [
872
+ { name: "asset_id", type: "string", required: true, description: "Video asset to extract from" },
873
+ ],
874
+ mcpTool: { tool: "extract_audio", autoInject: ["book_id"] },
875
+ },
876
+ {
877
+ command: "/make-cover-song",
878
+ description: "Generate a rhythm-and-style-guided drums-and-strings cover with the source media's exact duration",
879
+ example: "/make-cover-song @a1 punchier drums and sweeping strings",
880
+ category: "context_menu",
881
+ icon: "AudioLines",
882
+ size: "default",
883
+ variant: "emerald",
884
+ chevron: "right",
885
+ params: [
886
+ { name: "asset_id", type: "string", required: true, description: "Video or audio asset whose song rhythm and duration to follow" },
887
+ { name: "direction", type: "string", required: false, description: "Optional musical direction; defaults to instrumental drums and strings" },
888
+ ],
889
+ mcpTool: { tool: "make_cover_song", autoInject: ["book_id"] },
890
+ aliases: ["/replicate-song"],
891
+ },
892
+ {
893
+ command: "/archive",
894
+ description: "Archive a full video or audio asset to the global clip archive and transcribe it",
895
+ example: "/archive @a1 ai interview",
896
+ category: "context_menu",
897
+ icon: "Archive",
898
+ size: "default",
899
+ variant: "amber",
900
+ chevron: "right",
901
+ params: [
902
+ { name: "asset_id", type: "string", required: true, description: "Video or audio asset to archive" },
903
+ { name: "topics", type: "string[]", required: false, description: "Optional search topic tokens to attach" },
904
+ ],
905
+ mcpTool: { tool: "archive_clip", autoInject: ["book_id"] },
906
+ },
907
+ {
908
+ command: "/extend-audio",
909
+ description: "Extend an audio asset to a longer total duration with a matching ElevenLabs continuation, creating a new audio asset",
910
+ example: "/extend-audio @a1 15 add outro music",
911
+ category: "context_menu",
912
+ icon: "AudioLines",
913
+ size: "default",
914
+ variant: "emerald",
915
+ chevron: "right",
916
+ params: [
917
+ { name: "asset_id", type: "string", required: true, description: "Source audio artifact id" },
918
+ { name: "target_duration_seconds", type: "number", required: true, description: "Requested total duration in seconds" },
919
+ { name: "continuation_prompt", type: "string", required: false, description: "Optional free-text direction for the continuation, e.g. add outro music" },
920
+ ],
921
+ mcpTool: { tool: "extend_audio_asset", autoInject: ["book_id"] },
922
+ },
923
+ {
924
+ command: "/remove-sound",
925
+ description: "Remove a described sound from a video or audio asset in place by silencing its Scribe-tagged audio events",
926
+ example: "/remove-sound @a1 horse neighing",
927
+ category: "context_menu",
928
+ icon: "VolumeX",
929
+ size: "default",
930
+ variant: "emerald",
931
+ chevron: "right",
932
+ params: [
933
+ { name: "asset_id", type: "string", required: true, description: "Asset to edit in-place (video or audio artifact id)" },
934
+ { name: "sound", type: "string", required: true, description: "Sound to remove, e.g. horse neighing" },
935
+ ],
936
+ mcpTool: { tool: "remove_sound", autoInject: ["book_id"] },
937
+ },
938
+ {
939
+ command: "/audio-boost",
940
+ description: "Boost audio volume of a video or audio asset (linear multiplier, 1.0–4.0). In-place with git versioning.",
941
+ example: "/audio-boost @a1 2",
942
+ category: "context_menu",
943
+ icon: "Volume2",
944
+ size: "default",
945
+ variant: "emerald",
946
+ chevron: "right",
947
+ params: [
948
+ { name: "asset_id", type: "string", required: true, description: "Asset to boost (video or audio artifact id)" },
949
+ { name: "boost", type: "number", required: true, description: "Volume multiplier (1.0–4.0). >1 = louder." },
950
+ ],
951
+ mcpTool: { tool: "audio_boost", autoInject: ["book_id"] },
952
+ },
953
+ {
954
+ command: "/audio-mix",
955
+ description: "Mix a video or audio asset onto another at a lower volume, editing the target in-place.",
956
+ example: "/audio-mix @a1 @a2 30",
957
+ category: "context_menu",
958
+ icon: "AudioLines",
959
+ size: "default",
960
+ variant: "emerald",
961
+ chevron: "right",
962
+ params: [
963
+ { name: "target_asset_id", type: "string", required: true, description: "Asset to edit in-place (video or audio artifact id)" },
964
+ { name: "layer_asset_id", type: "string", required: true, description: "Asset whose audio is layered on (video or audio artifact id)" },
965
+ { name: "volume", type: "number", required: true, description: "Layer volume percentage (0-100)" },
966
+ ],
967
+ mcpTool: { tool: "audio_mix", autoInject: ["book_id"] },
968
+ },
969
+ {
970
+ command: "/replace-audio",
971
+ description: "Replace the audio track of a video asset with an audio asset's audio",
972
+ example: "/replace-audio @a1 @a2",
973
+ category: "context_menu",
974
+ icon: "Music",
975
+ size: "default",
976
+ variant: "default",
977
+ chevron: "right",
978
+ params: [
979
+ { name: "asset_id", type: "string", required: true, description: "Video asset whose audio is being replaced" },
980
+ { name: "audio_asset_id", type: "string", required: true, description: "Audio asset providing the new audio track" },
981
+ ],
982
+ mcpTool: { tool: "replace_video_audio", autoInject: ["book_id"] },
983
+ },
984
+ {
985
+ command: "/splice",
986
+ description: "Splice videos with an overlap window; use 0 to concatenate complete clips",
987
+ example: "/splice @a1 @a2 0",
988
+ category: "context_menu",
989
+ icon: "GitMerge",
990
+ size: "default",
991
+ variant: "default",
992
+ chevron: "right",
993
+ params: [
994
+ { name: "first_asset_id", type: "string", required: true, description: "Base video — search for the match point inside this one" },
995
+ { name: "second_asset_id", type: "string", required: true, description: "Continuation video — its first frame is the search target" },
996
+ { name: "overlap", type: "number", required: true, description: "Possible overlap in seconds; 0 means plain concatenation" },
997
+ ],
998
+ mcpTool: { tool: "splice_video", autoInject: ["book_id"] },
999
+ },
1000
+ {
1001
+ command: "/scene-concat",
1002
+ description: "Smoothly join two video scenes, automatically aligning shared boundary audio",
1003
+ example: "/scene-concat @a1 @a2",
1004
+ category: "context_menu",
1005
+ icon: "GitMerge",
1006
+ size: "default",
1007
+ variant: "violet",
1008
+ chevron: "right",
1009
+ params: [
1010
+ { name: "first_asset_id", type: "string", required: true, description: "First video in playback order" },
1011
+ { name: "second_asset_id", type: "string", required: true, description: "Second video in playback order" },
1012
+ { name: "transition_seconds", type: "number", required: false, description: "Optional fixed crossfade duration; omit for automatic audio alignment" },
1013
+ ],
1014
+ mcpTool: { tool: "smooth_scene_concat", autoInject: ["book_id"] },
1015
+ },
1016
+ {
1017
+ command: "/assign",
1018
+ description: "Assign asset to timeline slot",
1019
+ example: "/assign @a1 @s02",
1020
+ category: "action",
1021
+ icon: "LayoutGrid",
1022
+ size: "default",
1023
+ variant: "default",
1024
+ chevron: "right",
1025
+ params: [
1026
+ { name: "asset_id", type: "string", required: true, description: "Asset to assign" },
1027
+ { name: "slot", type: "string", required: true, description: "Timeline slot (e.g. @s01)" },
1028
+ ],
1029
+ mcpTool: { tool: "assign_slot", autoInject: ["book_id"] },
1030
+ },
1031
+ {
1032
+ command: "/remove-slot",
1033
+ description: "Remove a timeline slot and shift later slots left",
1034
+ example: "/remove-slot @s02",
1035
+ category: "action",
1036
+ icon: "Scissors",
1037
+ size: "default",
1038
+ variant: "default",
1039
+ chevron: "right",
1040
+ params: [
1041
+ { name: "slot", type: "string", required: true, description: "Stored timeline slot (e.g. @s01)" },
1042
+ ],
1043
+ mcpTool: { tool: "remove_timeline_slot", autoInject: ["book_id"] },
1044
+ aliases: ["/unassign"],
1045
+ },
1046
+ {
1047
+ command: "/rewrite",
1048
+ description: "Optimize a prompt",
1049
+ example: '/rewrite "make it more cinematic"',
1050
+ category: "action",
1051
+ icon: "Sparkles",
1052
+ size: "sm",
1053
+ variant: "default",
1054
+ chevron: "right",
1055
+ params: [
1056
+ { name: "prompt", type: "string", required: true, description: "The prompt to rewrite" },
1057
+ ],
1058
+ mcpTool: { tool: "rewrite_prompt", autoInject: ["book_id"] },
1059
+ },
1060
+ {
1061
+ command: "/clean-audio",
1062
+ description: "Clean a video's audio in place with ElevenLabs while preserving vocals and key sound effects",
1063
+ example: "/clean-audio @a1 true",
1064
+ category: "action",
1065
+ icon: "AudioLines",
1066
+ size: "default",
1067
+ variant: "emerald",
1068
+ chevron: "right",
1069
+ params: [
1070
+ { name: "asset_id", type: "string", required: true, description: "Video artifact to clean in place" },
1071
+ { name: "add_light_music", type: "boolean", required: false, description: "Set true to add a light instrumental music bed" },
1072
+ ],
1073
+ mcpTool: { tool: "clean_video_audio", autoInject: ["book_id"] },
1074
+ },
1075
+ {
1076
+ command: "/vocals",
1077
+ description: "Isolate vocals from audio",
1078
+ example: "/vocals @voiceover-main",
1079
+ category: "action",
1080
+ icon: "Mic",
1081
+ size: "default",
1082
+ variant: "emerald",
1083
+ chevron: "right",
1084
+ params: [
1085
+ { name: "asset_id", type: "string", required: true, description: "Asset to isolate vocals from" },
1086
+ ],
1087
+ mcpTool: { tool: "isolate_vocals", autoInject: ["book_id"] },
1088
+ },
1089
+ {
1090
+ command: "/transcribe",
1091
+ description: "Transcribe audio using ElevenLabs",
1092
+ example: "/transcribe @a1",
1093
+ category: "action",
1094
+ icon: "Mic",
1095
+ size: "default",
1096
+ variant: "violet",
1097
+ chevron: "right",
1098
+ params: [
1099
+ { name: "asset_id", type: "string", required: true, description: "Video or audio asset to transcribe" },
1100
+ ],
1101
+ mcpTool: { tool: "transcribe", autoInject: ["book_id"] },
1102
+ },
1103
+ {
1104
+ command: "/subs",
1105
+ description: "Subtitle settings",
1106
+ example: "/subs position top",
1107
+ category: "viewer",
1108
+ icon: "captions",
1109
+ size: "sm",
1110
+ variant: "default",
1111
+ chevron: "right",
1112
+ params: [
1113
+ { name: "field", type: "string", required: true, description: "on|off|enabled|style|position|size|fontSize|color|textColor|highlight|highlightColor|stroke|strokeWidth|strokeColor|shadow|shadowBlur|shadowOpacity|language" },
1114
+ { name: "value", type: "string", required: false, description: "Value for the field" },
1115
+ ],
1116
+ uiAction: "settings_subs",
1117
+ },
1118
+ {
1119
+ command: "/bg",
1120
+ description: "Background mode",
1121
+ example: "/bg blur",
1122
+ category: "viewer",
1123
+ icon: "image",
1124
+ size: "sm",
1125
+ variant: "default",
1126
+ chevron: "right",
1127
+ params: [
1128
+ { name: "mode", type: "string", required: true, description: "blur|black" },
1129
+ ],
1130
+ uiAction: "settings_bg",
1131
+ },
1132
+ {
1133
+ command: "/original",
1134
+ description: "Show original uncropped image",
1135
+ category: "viewer",
1136
+ icon: "image",
1137
+ size: "sm",
1138
+ variant: "default",
1139
+ chevron: "right",
1140
+ params: [],
1141
+ uiAction: "viewer_set_original",
1142
+ },
1143
+ {
1144
+ command: "/landscape",
1145
+ description: "Show landscape crop (1920x1080)",
1146
+ category: "viewer",
1147
+ icon: "monitor",
1148
+ size: "sm",
1149
+ variant: "default",
1150
+ chevron: "right",
1151
+ params: [],
1152
+ uiAction: "viewer_set_landscape",
1153
+ },
1154
+ {
1155
+ command: "/portrait",
1156
+ description: "Show portrait crop (1080x1920)",
1157
+ category: "viewer",
1158
+ icon: "smartphone",
1159
+ size: "sm",
1160
+ variant: "default",
1161
+ chevron: "right",
1162
+ params: [],
1163
+ uiAction: "viewer_set_portrait",
1164
+ },
1165
+ {
1166
+ command: "/info",
1167
+ description: "Show asset metadata",
1168
+ category: "viewer",
1169
+ icon: "info",
1170
+ size: "sm",
1171
+ variant: "default",
1172
+ chevron: "right",
1173
+ params: [],
1174
+ uiAction: "viewer_toggle_info",
1175
+ },
1176
+ {
1177
+ command: "/settings",
1178
+ description: "Show render settings",
1179
+ category: "viewer",
1180
+ icon: "settings",
1181
+ size: "sm",
1182
+ variant: "default",
1183
+ chevron: "right",
1184
+ params: [],
1185
+ uiAction: "viewer_show_settings",
1186
+ },
1187
+ {
1188
+ command: "/settings-landscape",
1189
+ description: "Settings for landscape orientation",
1190
+ category: "viewer",
1191
+ icon: "monitor",
1192
+ size: "sm",
1193
+ variant: "default",
1194
+ chevron: "right",
1195
+ params: [],
1196
+ uiAction: "settings_landscape",
1197
+ },
1198
+ {
1199
+ command: "/settings-portrait",
1200
+ description: "Settings for portrait orientation",
1201
+ category: "viewer",
1202
+ icon: "smartphone",
1203
+ size: "sm",
1204
+ variant: "default",
1205
+ chevron: "right",
1206
+ params: [],
1207
+ uiAction: "settings_portrait",
1208
+ },
1209
+ {
1210
+ command: "/settings-square",
1211
+ description: "Settings for square orientation",
1212
+ category: "viewer",
1213
+ icon: "square",
1214
+ size: "sm",
1215
+ variant: "default",
1216
+ chevron: "right",
1217
+ params: [],
1218
+ uiAction: "settings_square",
1219
+ },
1220
+ {
1221
+ command: "/files",
1222
+ description: "Focus file by position",
1223
+ example: "/files 3",
1224
+ category: "viewer",
1225
+ icon: "file",
1226
+ size: "sm",
1227
+ variant: "default",
1228
+ chevron: "right",
1229
+ params: [
1230
+ { name: "position", type: "number", required: true, description: "1-based file position" },
1231
+ ],
1232
+ uiAction: "viewer_focus_file",
1233
+ },
1234
+ // ── Book management commands ──
1235
+ {
1236
+ command: "/books",
1237
+ description: "Open the book selector dropdown",
1238
+ example: "/books",
1239
+ category: "project",
1240
+ icon: "FolderOpen",
1241
+ size: "default",
1242
+ variant: "zinc",
1243
+ chevron: "down",
1244
+ params: [],
1245
+ uiAction: "open_projects",
1246
+ },
1247
+ // ── Layout / navigation commands ──
1248
+ {
1249
+ command: "/close",
1250
+ description: "Close the active viewer, panel, or browser and return to the idle screen",
1251
+ example: "/close",
1252
+ category: "action",
1253
+ icon: "X",
1254
+ size: "sm",
1255
+ variant: "zinc",
1256
+ chevron: "right",
1257
+ params: [],
1258
+ uiAction: "close_viewer",
1259
+ },
1260
+ {
1261
+ command: "/collapse",
1262
+ description: "Close the project selector (left), chat controls (right), or both",
1263
+ example: "/collapse left",
1264
+ category: "action",
1265
+ icon: "PanelLeftClose",
1266
+ size: "sm",
1267
+ variant: "zinc",
1268
+ chevron: "right",
1269
+ params: [
1270
+ { name: "side", type: "string", required: false, description: "left | right | both (default both)" },
1271
+ ],
1272
+ uiAction: "sidebar_collapse",
1273
+ },
1274
+ {
1275
+ command: "/expand",
1276
+ description: "Open the project selector (left), chat controls (right), or both",
1277
+ example: "/expand right",
1278
+ category: "action",
1279
+ icon: "PanelLeftOpen",
1280
+ size: "sm",
1281
+ variant: "zinc",
1282
+ chevron: "right",
1283
+ params: [
1284
+ { name: "side", type: "string", required: false, description: "left | right | both (default both)" },
1285
+ ],
1286
+ uiAction: "sidebar_expand",
1287
+ },
1288
+ {
1289
+ command: "/sort",
1290
+ description: "Browse project media by creation date",
1291
+ example: "/sort oldest",
1292
+ category: "action",
1293
+ icon: "ArrowUpDown",
1294
+ size: "sm",
1295
+ variant: "zinc",
1296
+ chevron: "right",
1297
+ params: [
1298
+ { name: "order", type: "string", required: false, description: "newest | oldest (default newest)" },
1299
+ ],
1300
+ uiAction: "sidebar_sort",
1301
+ },
1302
+ {
1303
+ command: "/keys",
1304
+ description: "Open the provider API keys / settings screen",
1305
+ example: "/keys",
1306
+ category: "action",
1307
+ icon: "KeyRound",
1308
+ size: "default",
1309
+ variant: "zinc",
1310
+ chevron: "down",
1311
+ params: [],
1312
+ uiAction: "open_provider_keys",
1313
+ },
1314
+ {
1315
+ command: "/archive-browse",
1316
+ description: "Open the clip archive browser, optionally with an initial search",
1317
+ example: "/archive-browse interview",
1318
+ category: "action",
1319
+ icon: "ArchiveRestore",
1320
+ size: "default",
1321
+ variant: "amber",
1322
+ chevron: "down",
1323
+ params: [
1324
+ { name: "query", type: "string", required: false, description: "Initial search query" },
1325
+ ],
1326
+ uiAction: "open_archive",
1327
+ },
1328
+ // ── Timeline audio lane commands ──
1329
+ {
1330
+ command: "/audio-add",
1331
+ description: "Add an audio asset to the timeline audio lane (times in seconds)",
1332
+ example: "/audio-add @a1 2 10",
1333
+ category: "action",
1334
+ icon: "AudioLines",
1335
+ size: "default",
1336
+ variant: "emerald",
1337
+ chevron: "right",
1338
+ params: [
1339
+ { name: "asset_id", type: "string", required: true, description: "Audio artifact id" },
1340
+ { name: "start", type: "number", required: false, description: "Start position in seconds (default 0)" },
1341
+ { name: "duration", type: "number", required: false, description: "Duration in seconds (default full clip)" },
1342
+ ],
1343
+ uiAction: "timeline_audio_add",
1344
+ },
1345
+ {
1346
+ command: "/audio-move",
1347
+ description: "Move a timeline audio clip to a new start position (seconds)",
1348
+ example: "/audio-move @a1 5",
1349
+ category: "action",
1350
+ icon: "AudioLines",
1351
+ size: "default",
1352
+ variant: "emerald",
1353
+ chevron: "right",
1354
+ params: [
1355
+ { name: "audio_ref", type: "string", required: true, description: "Timeline audio clip (audio artifact id or clip id)" },
1356
+ { name: "start", type: "number", required: true, description: "New start position in seconds" },
1357
+ ],
1358
+ uiAction: "timeline_audio_move",
1359
+ },
1360
+ {
1361
+ command: "/audio-remove",
1362
+ description: "Remove an audio clip from the timeline audio lane",
1363
+ example: "/audio-remove @a1",
1364
+ category: "action",
1365
+ icon: "AudioLines",
1366
+ size: "default",
1367
+ variant: "emerald",
1368
+ chevron: "right",
1369
+ params: [
1370
+ { name: "audio_ref", type: "string", required: true, description: "Timeline audio clip (audio artifact id or clip id)" },
1371
+ ],
1372
+ uiAction: "timeline_audio_remove",
1373
+ },
1374
+ {
1375
+ command: "/audio-set",
1376
+ description: "Update a timeline audio clip: volume (0-100), fade-in or fade-out (ms)",
1377
+ example: "/audio-set @a1 volume 80",
1378
+ category: "action",
1379
+ icon: "AudioLines",
1380
+ size: "default",
1381
+ variant: "emerald",
1382
+ chevron: "right",
1383
+ params: [
1384
+ { name: "audio_ref", type: "string", required: true, description: "Timeline audio clip (audio artifact id or clip id)" },
1385
+ { name: "field", type: "string", required: true, description: "volume | fade-in | fade-out" },
1386
+ { name: "value", type: "number", required: true, description: "volume 0-100, fades in ms" },
1387
+ ],
1388
+ uiAction: "timeline_audio_update",
1389
+ },
1390
+ // ── Video op commands ──
1391
+ {
1392
+ command: "/reverse",
1393
+ description: "Reverse video playback (play backwards)",
1394
+ example: "/reverse @a1",
1395
+ category: "context_menu",
1396
+ icon: "Rewind",
1397
+ size: "default",
1398
+ variant: "default",
1399
+ chevron: "right",
1400
+ params: [
1401
+ { name: "asset_id", type: "string", required: true, description: "Video asset to reverse" },
1402
+ ],
1403
+ mcpTool: { tool: "reverse_video", autoInject: ["book_id"] },
1404
+ },
1405
+ {
1406
+ command: "/speed",
1407
+ description: "Change video playback speed (0.25-4.0x) or exact duration (e.g. 8.32s)",
1408
+ example: "/speed @a1 8.32s",
1409
+ category: "context_menu",
1410
+ icon: "Gauge",
1411
+ size: "default",
1412
+ variant: "default",
1413
+ chevron: "right",
1414
+ params: [
1415
+ { name: "asset_id", type: "string", required: true, description: "Video asset to retime" },
1416
+ { name: "speed", type: "string", required: true, description: "Speed multiplier (2) or target duration (8.32s)" },
1417
+ ],
1418
+ mcpTool: { tool: "change_video_speed", adapter: "change_speed", autoInject: ["book_id"] },
1419
+ },
1420
+ {
1421
+ command: "/timewarp",
1422
+ description: "Retime one scene while compensating the rest of the picture and preserving the original audio and duration",
1423
+ example: "/timewarp @a1 0-4.2s 1.5x",
1424
+ category: "context_menu",
1425
+ icon: "Gauge",
1426
+ size: "default",
1427
+ variant: "violet",
1428
+ chevron: "right",
1429
+ params: [
1430
+ { name: "asset_id", type: "string", required: true, description: "Video asset to timewarp" },
1431
+ { name: "range", type: "string", required: true, description: "Selected range as start-end" },
1432
+ { name: "factor", type: "string", required: true, description: "Duration multiplier from 0.25x to 4x" },
1433
+ ],
1434
+ mcpTool: { tool: "timewarp_video", adapter: "timewarp", autoInject: ["book_id"] },
1435
+ },
1436
+ {
1437
+ command: "/sync-audio",
1438
+ description: "Smoothly retime video action to match fixed original-audio cues at multiple anchors",
1439
+ example: "/sync-audio @a1 3s=England; 6s=America",
1440
+ category: "context_menu",
1441
+ icon: "Gauge",
1442
+ size: "default",
1443
+ variant: "violet",
1444
+ chevron: "right",
1445
+ params: [
1446
+ { name: "asset_id", type: "string", required: true, description: "Video asset to synchronize" },
1447
+ { name: "mappings", type: "string", required: true, description: "Semicolon-separated video-time=audio-cue-or-time anchors" },
1448
+ ],
1449
+ mcpTool: { tool: "sync_video_to_audio", adapter: "sync_audio", autoInject: ["book_id"] },
1450
+ },
1451
+ {
1452
+ command: "/split",
1453
+ description: "Open the interactive splitter for a notebook video, optionally seeded with cut times",
1454
+ example: "/split @a1 at 15s, 28.5s",
1455
+ category: "action",
1456
+ icon: "Scissors",
1457
+ size: "default",
1458
+ variant: "violet",
1459
+ chevron: "right",
1460
+ params: [
1461
+ { name: "cell", type: "string", required: true, description: "Notebook video cell to split (grid address such as @a1)" },
1462
+ { name: "split_spec", type: "string", required: false, description: "Optional comma-separated cut times; defaults to the midpoint" },
1463
+ ],
1464
+ exposure: "composite",
1465
+ },
1466
+ {
1467
+ command: "/split-clip",
1468
+ description: "Split a canonical-sequence clip at an exact sequence frame",
1469
+ example: "/split-clip @clip-id 45",
1470
+ category: "action",
1471
+ icon: "Scissors",
1472
+ size: "default",
1473
+ variant: "violet",
1474
+ chevron: "right",
1475
+ params: [
1476
+ { name: "clip_id", type: "string", required: true, description: "Canonical-sequence clip ID" },
1477
+ { name: "sequence_frame", type: "number", required: true, description: "Frame where the clip should split" },
1478
+ ],
1479
+ exposure: "composite",
1480
+ },
1481
+ {
1482
+ command: "/export-to",
1483
+ description: "Export an asset into a different project",
1484
+ example: "/export-to @a1 other-project",
1485
+ category: "context_menu",
1486
+ icon: "FolderOutput",
1487
+ size: "default",
1488
+ variant: "default",
1489
+ chevron: "right",
1490
+ params: [
1491
+ { name: "asset_id", type: "string", required: true, description: "Asset to export" },
1492
+ { name: "target_project", type: "string", required: true, description: "Target book name" },
1493
+ { name: "new_name", type: "string", required: false, description: "Optional name for the exported asset" },
1494
+ ],
1495
+ mcpTool: { tool: "export_asset_to_project", autoInject: ["book_id"] },
1496
+ },
1497
+ {
1498
+ command: "/skeleton",
1499
+ description: "Review an AI pose skeleton guide generated from a reference image",
1500
+ example: "/skeleton @a1",
1501
+ category: "context_menu",
1502
+ icon: "PersonStanding",
1503
+ size: "default",
1504
+ variant: "default",
1505
+ chevron: "right",
1506
+ params: [
1507
+ { name: "asset_id", type: "string", required: true, description: "Image artifact id" },
1508
+ ],
1509
+ uiAction: "extract_skeleton",
1510
+ },
1511
+ {
1512
+ command: "/archive-restore",
1513
+ description: "Restore archived clips into the current project by archive ID",
1514
+ example: "/archive-restore arc-abc123 arc-def456",
1515
+ category: "action",
1516
+ icon: "ArchiveRestore",
1517
+ size: "default",
1518
+ variant: "amber",
1519
+ chevron: "right",
1520
+ params: [
1521
+ { name: "archive_ids", type: "string[]", required: true, description: "One or more archive IDs to restore" },
1522
+ ],
1523
+ mcpTool: { tool: "restore_archive_clips", autoInject: ["book_id"] },
1524
+ },
1525
+ // ── Activity commands ──
1526
+ {
1527
+ command: "/rewind",
1528
+ description: "Rewind the project to a previous commit (no hash opens the activity log to pick one)",
1529
+ example: "/rewind 4f3a2b1",
1530
+ category: "action",
1531
+ icon: "History",
1532
+ size: "default",
1533
+ variant: "zinc",
1534
+ chevron: "right",
1535
+ params: [
1536
+ { name: "commit_hash", type: "string", required: false, description: "Git commit hash or unique prefix (min 7 chars) from /activity (omit to browse)" },
1537
+ ],
1538
+ uiAction: "rewind_activity",
1539
+ },
1540
+ {
1541
+ command: "/clear-failed",
1542
+ description: "Clean up failed work: delete failed-generation husks and clear error badges from assets that already have media",
1543
+ example: "/clear-failed",
1544
+ category: "action",
1545
+ icon: "Trash2",
1546
+ size: "default",
1547
+ variant: "zinc",
1548
+ chevron: "right",
1549
+ params: [],
1550
+ mcpTool: { tool: "clean_failed_assets", autoInject: ["book_id"] },
1551
+ },
1552
+ // ── Character / voice commands ──
1553
+ {
1554
+ command: "/voices",
1555
+ description: "Browse ElevenLabs voices in the speak preview",
1556
+ example: "/voices",
1557
+ category: "action",
1558
+ icon: "Mic",
1559
+ size: "default",
1560
+ variant: "pink",
1561
+ chevron: "down",
1562
+ params: [],
1563
+ uiAction: "speak_preview",
1564
+ },
1565
+ {
1566
+ command: "/say",
1567
+ description: "Generate speech audio from text with ElevenLabs",
1568
+ example: "/say welcome back everyone",
1569
+ category: "context_menu",
1570
+ icon: "Mic",
1571
+ size: "default",
1572
+ variant: "pink",
1573
+ chevron: "right",
1574
+ params: [
1575
+ { name: "prompt", type: "string", required: true, description: "Text to speak" },
1576
+ ],
1577
+ mcpTool: { tool: "generate_audio", autoInject: ["book_id"], injectParams: { model: "kie:elevenlabs/text-to-speech-turbo-2-5" } },
1578
+ },
1579
+ {
1580
+ command: "/speak",
1581
+ description: "Generate ElevenLabs speech into the notebook from the inline voice preview",
1582
+ example: "/speak welcome back everyone",
1583
+ category: "action",
1584
+ icon: "Mic",
1585
+ size: "default",
1586
+ variant: "pink",
1587
+ chevron: "right",
1588
+ params: [{ name: "text", type: "string", required: false, description: "Text to synthesize" }],
1589
+ uiAction: "speak_preview",
1590
+ },
1591
+ // ── X connect command ──
1592
+ {
1593
+ command: "/connect-x",
1594
+ description: "Connect your X (Twitter) account via browser OAuth",
1595
+ example: "/connect-x",
1596
+ category: "action",
1597
+ icon: "Share2",
1598
+ size: "default",
1599
+ variant: "blue",
1600
+ chevron: "right",
1601
+ params: [],
1602
+ uiAction: "x_connect",
1603
+ },
1604
+ // ── Timeline player command ──
1605
+ {
1606
+ command: "/play",
1607
+ description: "Open the timeline player at a slot (default: first filled slot)",
1608
+ example: "/play @s02",
1609
+ category: "action",
1610
+ icon: "Play",
1611
+ size: "default",
1612
+ variant: "default",
1613
+ chevron: "right",
1614
+ params: [
1615
+ { name: "slot", type: "string", required: false, description: "Timeline slot (e.g. @s01)" },
1616
+ ],
1617
+ uiAction: "open_slot_player",
1618
+ },
1619
+ ];
1620
+ export function getCanonicalCommands() {
1621
+ return canonicalizeCommands([...CANONICAL_COMMANDS, ...APPLICATION_COMMANDS]);
1622
+ }
1623
+ function commandSummary(command) {
1624
+ return {
1625
+ command: command.command,
1626
+ description: command.description,
1627
+ ...(command.aliases?.length ? { aliases: command.aliases } : {}),
1628
+ ...(command.mcpTool ? { runs: `tool:${command.mcpTool.tool}` } : command.uiAction ? { runs: `ui:${command.uiAction}` } : {}),
1629
+ };
1630
+ }
1631
+ export function commandsDef(books = bookManager, reservedActionNames = () => []) {
1632
+ return {
1633
+ name: "slash_commands",
1634
+ description: "List the UI slash commands as command, description, aliases and the tool or UI action each runs; detail full returns the complete records the app renders (params, examples, icons).",
1635
+ scope: "global",
1636
+ schema: {
1637
+ detail: z.enum(["summary", "full"]).optional(),
1638
+ },
1639
+ handler: async (args) => {
1640
+ const commands = [...CANONICAL_COMMANDS, ...APPLICATION_COMMANDS];
1641
+ const reserved = new Set([...commands.flatMap((command) => [command.command, ...(command.aliases ?? [])]), ...reservedActionNames()]
1642
+ .map((name) => name.toLowerCase()));
1643
+ await books.ready();
1644
+ for (const book of books.list()) {
1645
+ if (reserved.has(`/${book.name}`.toLowerCase()))
1646
+ continue;
1647
+ commands.push({
1648
+ command: `/${book.name}`,
1649
+ description: `Switch to book ${book.name}`,
1650
+ category: "project",
1651
+ icon: "FolderOpen",
1652
+ size: "default",
1653
+ variant: "default",
1654
+ chevron: "down",
1655
+ params: [],
1656
+ uiAction: "switch_book",
1657
+ });
1658
+ }
1659
+ const canonical = canonicalizeCommands(commands);
1660
+ const payload = args.detail === "full" ? canonical : canonical.map(commandSummary);
1661
+ return {
1662
+ content: [{ type: "text", text: JSON.stringify(payload) }],
1663
+ };
1664
+ },
1665
+ };
1666
+ }