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,628 @@
1
+ import { LIGHTNING_VIDEO_MODEL } from "./lightning-defaults.js";
2
+ import { CHAIN_TOOL_CATALOG, planStackedChainFromQuery } from "./chain-plan.js";
3
+ import { CHAT_VIEW_ACTIONS } from "./chat-view-actions.js";
4
+ import { zodEnumOptionsOrNull, zodIsRequired, zodUnionEnumOptions, } from "./zod-slots.js";
5
+ const AUTO_APPLY_TOOL_NAMES = new Set([
6
+ "duplicate_asset",
7
+ "extract_audio",
8
+ "extract_frame",
9
+ ]);
10
+ const TIMESTAMP_PARAMS = {
11
+ trim_video: ["trim_start", "trim_end", "cut_start", "cut_end"],
12
+ download_video: ["start_time", "end_time"],
13
+ split_video: ["chunk_a_end", "chunk_b_start"],
14
+ extract_video_clip: ["start_time", "end_time"],
15
+ extract_frame: ["timestamp"],
16
+ timewarp_video: ["start_seconds", "end_seconds"],
17
+ };
18
+ const NESTED_TIMESTAMP_PARAMS = {
19
+ sync_video_to_audio: {
20
+ anchors: ["video_seconds", "audio_seconds"],
21
+ },
22
+ };
23
+ const READ_ONLY_TOOL_NAMES = new Set([
24
+ "asset_history",
25
+ "asset_manifest",
26
+ "slash_commands",
27
+ "storage_status",
28
+ "service_status",
29
+ ]);
30
+ const READ_ONLY_TOOL_PREFIXES = [
31
+ "check_",
32
+ "estimate_",
33
+ "get_",
34
+ "inspect_",
35
+ "list_",
36
+ "plan_",
37
+ "prepare_",
38
+ "preview_",
39
+ "read_",
40
+ "search_",
41
+ "wait_",
42
+ ];
43
+ function categoryForTool(name) {
44
+ return /^(?:generate|extend|upscale)_/u.test(name)
45
+ || name === "concat_images"
46
+ ? "generation"
47
+ : "action";
48
+ }
49
+ function effectForTool(name, category) {
50
+ if (category === "generation")
51
+ return "generation";
52
+ if (name === "prepare_cold_open")
53
+ return "mutation";
54
+ if (READ_ONLY_TOOL_NAMES.has(name)
55
+ || READ_ONLY_TOOL_PREFIXES.some((prefix) => name.startsWith(prefix)))
56
+ return "read";
57
+ return "mutation";
58
+ }
59
+ function paramsForTool(definition) {
60
+ return Object.keys(definition.schema).filter((name) => name !== "book_id");
61
+ }
62
+ function requiredParamsForTool(definition) {
63
+ return Object.entries(definition.schema)
64
+ .filter(([name, schema]) => name !== "book_id"
65
+ && zodIsRequired(schema))
66
+ .map(([name]) => name);
67
+ }
68
+ function constraintsForTool(definition) {
69
+ return Object.entries(definition.schema).flatMap(([name, schema]) => {
70
+ if (name === "book_id")
71
+ return [];
72
+ const constraintSchema = schema;
73
+ const values = zodEnumOptionsOrNull(constraintSchema)
74
+ ?? zodUnionEnumOptions(constraintSchema);
75
+ return values
76
+ ? [`${name}=${values.map((value) => JSON.stringify(value)).join("|")}`]
77
+ : [];
78
+ });
79
+ }
80
+ function buildRoutableTools(definitions) {
81
+ const tools = definitions
82
+ .filter((definition) => definition.name !== "chat")
83
+ .map((definition) => {
84
+ const category = categoryForTool(definition.name);
85
+ return {
86
+ name: definition.name,
87
+ actualTool: definition.name,
88
+ description: definition.description,
89
+ params: paramsForTool(definition),
90
+ requiredParams: requiredParamsForTool(definition),
91
+ constraints: constraintsForTool(definition),
92
+ category,
93
+ effect: effectForTool(definition.name, category),
94
+ autoApply: AUTO_APPLY_TOOL_NAMES.has(definition.name),
95
+ };
96
+ });
97
+ // Views run in the app, never on the server, so they need no review.
98
+ const views = CHAT_VIEW_ACTIONS.map((action) => ({
99
+ name: action.name,
100
+ actualTool: action.name,
101
+ description: action.description,
102
+ params: paramsForTool(action),
103
+ requiredParams: requiredParamsForTool(action),
104
+ constraints: constraintsForTool(action),
105
+ category: "action",
106
+ effect: "view",
107
+ autoApply: true,
108
+ }));
109
+ return [...views, ...tools];
110
+ }
111
+ const SEEDREAM_IMAGE_EDIT_MODEL = "kie:seedream/5-lite-image-to-image";
112
+ const SEEDANCE_SUBSTITUTION_NOTE = "Using Seedream for this image edit (Seedance is video).";
113
+ const MENTION_PATTERN = /@([a-z]{1,2}\d{1,2}|[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12})/gi;
114
+ function mentionsBytedanceFamily(query) {
115
+ return /seedance|seedream|bytedance/i.test(query);
116
+ }
117
+ function mentionsSeedanceFiveAlias(query) {
118
+ return /seedance\s*5(?:\.0)?(?:\s*edit)?/i.test(query)
119
+ || /seedream\s*5/i.test(query);
120
+ }
121
+ function normalizeMention(value) {
122
+ return value.trim().replace(/^@/, "").toLowerCase();
123
+ }
124
+ function stringList(value) {
125
+ if (!Array.isArray(value))
126
+ return [];
127
+ return value.flatMap((entry) => typeof entry === "string" && entry.trim()
128
+ ? [entry.trim()]
129
+ : []);
130
+ }
131
+ function queryMentions(query) {
132
+ return [...query.matchAll(MENTION_PATTERN)].map((match) => `@${match[1]}`);
133
+ }
134
+ function assetMediaType(asset) {
135
+ const type = typeof asset.type === "string"
136
+ ? asset.type
137
+ : typeof asset.artifact_type === "string"
138
+ ? asset.artifact_type
139
+ : null;
140
+ return type === "image" || type === "video" || type === "audio" || type === "script"
141
+ ? type
142
+ : null;
143
+ }
144
+ function assetMentionKeys(asset) {
145
+ const keys = [
146
+ typeof asset.tag === "string" ? asset.tag : "",
147
+ typeof asset.asset_id === "string" ? asset.asset_id : "",
148
+ ];
149
+ if (Array.isArray(asset.notebook_references)) {
150
+ for (const reference of asset.notebook_references) {
151
+ if (typeof reference === "string")
152
+ keys.push(reference);
153
+ }
154
+ }
155
+ return keys.filter(Boolean).map(normalizeMention);
156
+ }
157
+ function mediaTypeForMention(mention, assetContext) {
158
+ const needle = normalizeMention(mention);
159
+ const match = assetContext.find((asset) => assetMentionKeys(asset).includes(needle));
160
+ return match ? assetMediaType(match) : null;
161
+ }
162
+ function mentionWithAt(mention) {
163
+ return mention.startsWith("@") ? mention : `@${mention}`;
164
+ }
165
+ function sceneTargetMention(query) {
166
+ const match = query.match(/\b(?:in|on|across|from|of)\s+(@[a-z]{1,2}\d{1,2}|@[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12})\b/i);
167
+ return match?.[1] ? mentionWithAt(match[1]) : null;
168
+ }
169
+ function withClauseMentions(query) {
170
+ const match = query.match(/\bwith\s+((?:@[a-z]{1,2}\d{1,2}|@[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12})(?:\s+(?:and|,)?\s*(?:@[a-z]{1,2}\d{1,2}|@[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}))*)/i);
171
+ return match?.[1] ? queryMentions(match[1]) : [];
172
+ }
173
+ function uniqueMentions(values) {
174
+ const seen = new Set();
175
+ const unique = [];
176
+ for (const value of values) {
177
+ const key = normalizeMention(value);
178
+ if (!key || seen.has(key))
179
+ continue;
180
+ seen.add(key);
181
+ unique.push(mentionWithAt(value));
182
+ }
183
+ return unique;
184
+ }
185
+ function applyBytedanceNamedModelRoute(input) {
186
+ if (!mentionsBytedanceFamily(input.query)) {
187
+ return {
188
+ tool: input.tool,
189
+ params: input.params,
190
+ message: input.message,
191
+ substituted: false,
192
+ };
193
+ }
194
+ const mentions = queryMentions(input.query);
195
+ const target = sceneTargetMention(input.query) ?? mentions[0] ?? null;
196
+ const targetType = target ? mediaTypeForMention(target, input.assetContext) : null;
197
+ const mentionedTypes = mentions.map((mention) => mediaTypeForMention(mention, input.assetContext));
198
+ const hasImage = mentionedTypes.includes("image") || targetType === "image";
199
+ const hasVideo = mentionedTypes.includes("video") || targetType === "video";
200
+ const imageTarget = targetType === "image"
201
+ || (hasImage && targetType !== "video" && !hasVideo)
202
+ || (mentionsSeedanceFiveAlias(input.query) && hasImage && targetType !== "video");
203
+ const replacements = uniqueMentions(withClauseMentions(input.query))
204
+ .filter((mention) => mentionWithAt(mention).toLowerCase() !== target?.toLowerCase());
205
+ const imageMentions = uniqueMentions(mentions.filter((mention) => mediaTypeForMention(mention, input.assetContext) === "image"));
206
+ const videoMentions = uniqueMentions(mentions.filter((mention) => mediaTypeForMention(mention, input.assetContext) === "video"));
207
+ const prompt = typeof input.params.prompt === "string" && input.params.prompt.trim()
208
+ ? input.params.prompt
209
+ : input.query;
210
+ if (imageTarget && (target || imageMentions.length > 0)) {
211
+ const editTarget = target && targetType === "image" ? target : imageMentions[0];
212
+ const rest = uniqueMentions([
213
+ ...replacements.filter((mention) => mediaTypeForMention(mention, input.assetContext) !== "video"),
214
+ ...imageMentions,
215
+ ]).filter((mention) => normalizeMention(mention) !== normalizeMention(editTarget));
216
+ const imageRefs = uniqueMentions([editTarget, ...rest]);
217
+ const saidSeedance = /seedance|bytedance/i.test(input.query);
218
+ const message = saidSeedance
219
+ ? (input.message.trim()
220
+ ? `${input.message.trim().replace(/[.!]?$/, "")}. ${SEEDANCE_SUBSTITUTION_NOTE}`
221
+ : SEEDANCE_SUBSTITUTION_NOTE)
222
+ : input.message;
223
+ const { video_refs: _videoRefs, image_refs: _imageRefs, refs: _refs, ...imageParams } = input.params;
224
+ return {
225
+ tool: "generate_image",
226
+ params: {
227
+ ...imageParams,
228
+ model: SEEDREAM_IMAGE_EDIT_MODEL,
229
+ prompt,
230
+ refs: { image: imageRefs },
231
+ },
232
+ message,
233
+ substituted: saidSeedance,
234
+ };
235
+ }
236
+ if (hasVideo) {
237
+ const routedRefs = input.params.refs !== null && typeof input.params.refs === "object" && !Array.isArray(input.params.refs)
238
+ ? input.params.refs
239
+ : {};
240
+ const videoRefs = uniqueMentions([
241
+ ...(target && targetType === "video" ? [target] : []),
242
+ ...videoMentions,
243
+ ...stringList(input.params.video_refs),
244
+ ...stringList(routedRefs.video),
245
+ ]).filter((mention) => mediaTypeForMention(mention, input.assetContext) !== "image");
246
+ const imageRefs = uniqueMentions([
247
+ ...replacements.filter((mention) => mediaTypeForMention(mention, input.assetContext) === "image"),
248
+ ...imageMentions,
249
+ ...stringList(input.params.image_refs),
250
+ ...stringList(routedRefs.image),
251
+ ]).filter((mention) => mediaTypeForMention(mention, input.assetContext) !== "video");
252
+ const { video_refs: _videoRefs, image_refs: _imageRefs, refs: _refs, ...videoParams } = input.params;
253
+ return {
254
+ tool: "generate_video",
255
+ params: {
256
+ ...videoParams,
257
+ model: LIGHTNING_VIDEO_MODEL,
258
+ prompt,
259
+ refs: {
260
+ ...(videoRefs.length > 0 ? { video: videoRefs } : {}),
261
+ ...(imageRefs.length > 0 ? { image: imageRefs } : {}),
262
+ },
263
+ mode: "r2v",
264
+ },
265
+ message: input.message,
266
+ substituted: false,
267
+ };
268
+ }
269
+ return {
270
+ tool: input.tool,
271
+ params: input.params,
272
+ message: input.message,
273
+ substituted: false,
274
+ };
275
+ }
276
+ const NOTEBOOK_VIDEO_CELL_TYPES = new Set([
277
+ "video",
278
+ "generate_video",
279
+ "splice",
280
+ "concat",
281
+ "split_video",
282
+ ]);
283
+ const UUID_PATTERN = /^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$/i;
284
+ function isVideoJoinQuery(query) {
285
+ if (/\b(?:splice\s+out|apply[\s-]?cuts|cut\s+out)\b/iu.test(query))
286
+ return false;
287
+ return /\b(?:splice(?:\s+together)?|concat(?:enate)?|stitch(?:\s+together)?)\b/iu.test(query)
288
+ || /\bjoin(?:ing)?\s+(?:(?:these|the|all)\s+)?(?:\d+\s+)?(?:video|clip|scene)s?\b/iu.test(query);
289
+ }
290
+ function overlapFromParams(params) {
291
+ const raw = params.overlap;
292
+ if (typeof raw === "number" && Number.isFinite(raw) && raw >= 0)
293
+ return raw;
294
+ if (typeof raw === "string" && raw.trim()) {
295
+ const parsed = Number(raw);
296
+ if (Number.isFinite(parsed) && parsed >= 0)
297
+ return parsed;
298
+ }
299
+ return 0;
300
+ }
301
+ function rawMediaContextEntries(value) {
302
+ return Array.isArray(value) ? value : [];
303
+ }
304
+ function artifactTokenFromUnknown(value) {
305
+ if (typeof value === "string") {
306
+ const trimmed = value.trim();
307
+ return trimmed ? trimmed : null;
308
+ }
309
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
310
+ return null;
311
+ }
312
+ const record = value;
313
+ for (const key of [
314
+ "artifact_id",
315
+ "asset_id",
316
+ "outputAsset",
317
+ "output_artifact_id",
318
+ "address",
319
+ "tag",
320
+ ]) {
321
+ if (typeof record[key] === "string" && record[key].trim()) {
322
+ return record[key].trim();
323
+ }
324
+ }
325
+ return null;
326
+ }
327
+ function uniqueAssetIds(values) {
328
+ const seen = new Set();
329
+ const unique = [];
330
+ for (const value of values) {
331
+ const stripped = value.replace(/^@/u, "").trim();
332
+ const key = stripped.toLowerCase();
333
+ if (!key || seen.has(key))
334
+ continue;
335
+ seen.add(key);
336
+ unique.push(stripped);
337
+ }
338
+ return unique;
339
+ }
340
+ function notebookVideoAssetId(token, notebookContext) {
341
+ if (!notebookContext)
342
+ return null;
343
+ const needle = normalizeMention(token);
344
+ const cell = notebookContext.cells.find((candidate) => normalizeMention(candidate.address) === needle
345
+ || normalizeMention(candidate.cellId) === needle
346
+ || (candidate.outputAsset !== null
347
+ && normalizeMention(candidate.outputAsset) === needle));
348
+ if (!cell || !cell.outputAsset)
349
+ return null;
350
+ if (cell.type && !NOTEBOOK_VIDEO_CELL_TYPES.has(cell.type))
351
+ return null;
352
+ return cell.outputAsset.replace(/^@/u, "");
353
+ }
354
+ function resolveVideoAssetId(token, input) {
355
+ const mention = mentionWithAt(token);
356
+ const mentionedType = mediaTypeForMention(mention, input.assetContext);
357
+ if (mentionedType && mentionedType !== "video")
358
+ return null;
359
+ if (mentionedType === "video") {
360
+ const needle = normalizeMention(token);
361
+ const asset = input.assetContext.find((candidate) => assetMentionKeys(candidate).includes(needle));
362
+ const assetId = typeof asset?.asset_id === "string" ? asset.asset_id.trim() : "";
363
+ return assetId || null;
364
+ }
365
+ const fromNotebook = notebookVideoAssetId(token, input.notebookContext);
366
+ if (fromNotebook)
367
+ return fromNotebook;
368
+ const stripped = token.replace(/^@/u, "").trim();
369
+ return UUID_PATTERN.test(stripped) ? stripped : null;
370
+ }
371
+ function collectJoinAssetIds(input) {
372
+ const fromMentions = uniqueAssetIds(queryMentions(input.query).flatMap((mention) => {
373
+ const resolved = resolveVideoAssetId(mention, input);
374
+ return resolved ? [resolved] : [];
375
+ }));
376
+ const fromMediaContext = uniqueAssetIds(rawMediaContextEntries(input.params.media_context).flatMap((entry) => {
377
+ const token = artifactTokenFromUnknown(entry);
378
+ if (!token)
379
+ return [];
380
+ const resolved = resolveVideoAssetId(token, input);
381
+ return resolved ? [resolved] : [];
382
+ }));
383
+ const fromAssetIds = uniqueAssetIds(stringList(input.params.asset_ids).flatMap((token) => {
384
+ const resolved = resolveVideoAssetId(token, input);
385
+ return resolved ? [resolved] : [];
386
+ }));
387
+ const fromPair = uniqueAssetIds([
388
+ ...(typeof input.params.first_asset_id === "string"
389
+ ? [input.params.first_asset_id]
390
+ : []),
391
+ ...(typeof input.params.second_asset_id === "string"
392
+ ? [input.params.second_asset_id]
393
+ : []),
394
+ ...stringList(input.params.additional_asset_ids),
395
+ ].flatMap((token) => {
396
+ const resolved = resolveVideoAssetId(token, input);
397
+ return resolved ? [resolved] : [];
398
+ }));
399
+ if (fromMentions.length >= 2)
400
+ return fromMentions;
401
+ if (fromMediaContext.length >= 2)
402
+ return fromMediaContext;
403
+ if (fromAssetIds.length >= 2)
404
+ return fromAssetIds;
405
+ if (fromPair.length >= 2)
406
+ return fromPair;
407
+ return [];
408
+ }
409
+ function planBackgroundAudioFromQuery(input) {
410
+ if (!/^(?:(?:please|can you|could you|would you)\s+)*(?:add|mix|layer|overlay|put)\b/iu.test(input.query.trim()))
411
+ return null;
412
+ if (!/\b(?:ambience|ambient|foley|sfx|sound effects?|asmr)\b/iu.test(input.query))
413
+ return null;
414
+ if (/\b(?:replace|remove|delete|trim|crop|speed|reverse|narration|voiceover|using|model)\b|\b(?:at|after|from|until)\s+\d/iu.test(input.query))
415
+ return null;
416
+ const soundRequest = input.query.replace(/\b(?:no|without)\s+(?:any\s+)?(?:music|speech)\b/giu, "");
417
+ if (/\b(?:music|speech|score|fal|kie|acestep)\b/iu.test(soundRequest))
418
+ return null;
419
+ const mentions = uniqueMentions(queryMentions(input.query));
420
+ if (mentions.length === 0 || mentions.some((mention) => mediaTypeForMention(mention, input.assetContext) !== "video"))
421
+ return null;
422
+ const targets = uniqueAssetIds(mentions.flatMap((mention) => {
423
+ const asset = resolveVideoAssetId(mention, input);
424
+ return asset ? [asset] : [];
425
+ }));
426
+ if (targets.length !== 1)
427
+ return null;
428
+ const prompt = input.query.replace(/\b(?:to|on|onto|for)\s+(?=@)/giu, "")
429
+ .replace(MENTION_PATTERN, "").replace(/\s+/gu, " ").replace(/\s+([,.;:])/gu, "$1").trim();
430
+ const durationMatch = input.query.match(/\b(?:for|lasting|duration(?: of)?)\s+(\d+(?:\.\d+)?)\s*(seconds?|secs?|s|minutes?|mins?)\b/iu)
431
+ ?? input.query.match(/\b(\d+(?:\.\d+)?)[\s-]*(seconds?|secs?|s|minutes?|mins?)[\s-]+(?:of\s+)?(?:background|ambience|ambient|foley|sfx|sound|asmr)\b/iu);
432
+ const duration = durationMatch ? Number(durationMatch[1]) * (/^m/iu.test(durationMatch[2]) ? 60 : 1) : undefined;
433
+ const volumeMatch = input.query.match(/\b(?:volume|at)\s+(\d+(?:\.\d+)?)\s*%/iu)
434
+ ?? input.query.match(/\b(\d+(?:\.\d+)?)\s*%\s*(?:volume|level)\b/iu);
435
+ return {
436
+ tool: "chain",
437
+ params: {
438
+ action: "run",
439
+ version: 1,
440
+ steps: [
441
+ {
442
+ id: "ambience", tool: "generate_audio",
443
+ params: {
444
+ model: "elevenlabs:sound-generation", prompt,
445
+ ...(duration !== undefined ? { options: { duration_seconds: duration } } : {}),
446
+ },
447
+ },
448
+ {
449
+ id: "mix", tool: "audio_mix",
450
+ params: { target_asset_id: targets[0], layer_asset_id: { $ref: { step_id: "ambience", output: "asset_id" } }, volume: volumeMatch ? Number(volumeMatch[1]) : 50 },
451
+ },
452
+ ],
453
+ },
454
+ message: "Adding ambience and sound effects.",
455
+ substituted: true,
456
+ };
457
+ }
458
+ function applyBackgroundAudioRoute(input) {
459
+ const unchanged = { tool: input.tool, params: input.params, message: input.message, substituted: false };
460
+ if (input.tool !== "analyze_video" && effectForTool(input.tool, categoryForTool(input.tool)) !== "read")
461
+ return unchanged;
462
+ return planBackgroundAudioFromQuery(input) ?? unchanged;
463
+ }
464
+ function applyStackedChainRoute(input) {
465
+ const planned = planStackedChainFromQuery(input.query);
466
+ if (!planned) {
467
+ return {
468
+ tool: input.tool,
469
+ params: input.params,
470
+ message: input.message,
471
+ substituted: false,
472
+ };
473
+ }
474
+ return {
475
+ tool: "chain",
476
+ params: {
477
+ action: "run",
478
+ version: 1,
479
+ steps: planned.steps,
480
+ ...(input.notebookContext?.id
481
+ ? { notebook_id: input.notebookContext.id }
482
+ : {}),
483
+ },
484
+ message: planned.message,
485
+ substituted: true,
486
+ };
487
+ }
488
+ function applyVideoJoinRoute(input) {
489
+ if (input.tool === "apply_cuts" || input.tool === "smooth_scene_concat") {
490
+ return {
491
+ tool: input.tool,
492
+ params: input.params,
493
+ message: input.message,
494
+ substituted: false,
495
+ };
496
+ }
497
+ const joinQuery = isVideoJoinQuery(input.query);
498
+ if (!joinQuery && input.tool !== "splice_video") {
499
+ return {
500
+ tool: input.tool,
501
+ params: input.params,
502
+ message: input.message,
503
+ substituted: false,
504
+ };
505
+ }
506
+ const assetIds = collectJoinAssetIds(input);
507
+ if (assetIds.length < 2) {
508
+ return {
509
+ tool: input.tool,
510
+ params: input.params,
511
+ message: input.message,
512
+ substituted: false,
513
+ };
514
+ }
515
+ const additional = assetIds.slice(2);
516
+ return {
517
+ tool: "splice_video",
518
+ params: {
519
+ first_asset_id: assetIds[0],
520
+ second_asset_id: assetIds[1],
521
+ ...(additional.length > 0 ? { additional_asset_ids: additional } : {}),
522
+ overlap: overlapFromParams(input.params),
523
+ },
524
+ message: input.message.trim() || "Splicing videos.",
525
+ substituted: input.tool !== "splice_video",
526
+ };
527
+ }
528
+ function routingArgument(tool, param) {
529
+ const required = tool.requiredParams.includes(param) ? "*" : "";
530
+ const allowed = tool.constraints.find((constraint) => constraint.startsWith(`${param}=`));
531
+ return allowed ? `${allowed.replace("=", `${required}=`)}` : `${param}${required}`;
532
+ }
533
+ function routingToolLine(tool) {
534
+ const args = tool.params.map((param) => routingArgument(tool, param)).join(", ");
535
+ return `- ${tool.name}: ${tool.description}${args ? ` (${args})` : ""}`;
536
+ }
537
+ function buildChatRoutingPrompt(bookName, tools, historyContext) {
538
+ const toolLines = tools.map(routingToolLine).join("\n");
539
+ const chainTools = tools.filter((tool) => CHAIN_TOOL_CATALOG[tool.name])
540
+ .map((tool) => `${tool.name} -> ${Object.keys(CHAIN_TOOL_CATALOG[tool.name].outputs).join(", ")}`)
541
+ .join("; ");
542
+ const historyBlock = historyContext
543
+ ? `\n${historyContext}\n\nUse conversation history to resolve pronouns and follow-up references (e.g. "reverse it" refers to the asset from the previous turn).\n`
544
+ : "";
545
+ return `You are a routing assistant for the Videobook media system.
546
+
547
+ Available tools (arguments in parentheses; * marks a required argument and name="a"|"b" lists its allowed values):
548
+ ${toolLines}
549
+
550
+ Current book: ${bookName}
551
+ ${historyBlock}
552
+ Given a user query (possibly with @asset references), determine:
553
+ 1. tool: Which tool to use
554
+ 2. params: Parameters to pass
555
+ 3. message: A brief present-progressive status message (2-5 words, e.g. "Trimming video.")
556
+
557
+ Parameter guidelines:
558
+ - Route the current request to the action or chain that delivers its requested result. This is a single routing decision, not an agent loop: an exploratory read will end the turn. Use list_jobs only when the user asks about jobs or progress, and analyze_video only when analysis itself is requested. Repeating an edit request asks for that edit again, not a status check on an earlier attempt
559
+ - Generate images, video and audio with generate_image, generate_video and generate_audio. Omit model unless the user names a model or provider; the default model is applied automatically. When the user names one, pick its id from list_generation_models (for example kie:bytedance/seedance-2-5, kie:nano-banana-2-1, fal:fal-ai/nano-banana-pro). Put media inputs in refs by role (image, first_frame, last_frame, video, audio) and model settings in options
560
+ - Include every required parameter. Omit optional parameters unless the user explicitly requests them so the tool can apply its defaults
561
+ - For parameters with listed allowed values, use exactly one listed value and never borrow an option from another tool
562
+ - For asset_id: use the resolved asset ID from the referenced @tag (e.g., @vid-foo → asset_id: "vid-foo")
563
+ - Use the current notebook ID for notebook_id. Resolve notebook addresses through the supplied notebook context and use cell UUIDs for cell ID parameters
564
+ - For duplicate_asset, use asset_id for the source, pass an explicit empty grid address as destination without @, and omit destination when the copy should go directly below the source
565
+ - When the user wants a first clip of a stated length plus the remaining/rest/remainder, use split_video with chunk_a_end set to that length and omit chunk_b_start
566
+ - When the user asks for a cold open or an exciting highlight before the full clip, use prepare_cold_open. The user reviews its range before edit_cold_open creates the copy. Never invent source hashes or request IDs.
567
+ - When the user wants to send, deliver, or save a Post to the phone or iPhone, or deliver a Post without naming a service, use save_post_to_icloud. Use upload_post_to_dropbox only when the user says Dropbox
568
+ - When the user asks to cut, extract, or create a new clip from a start time to an end time, use extract_video_clip; use trim_video only when the existing source should be changed in place
569
+ - When the user asks to trim or tighten a video for better pacing, timing or transitions without specifying cut ranges, use suggest_cuts and preserve the editing goal in instructions. It can assess visual pacing without a transcript. Never invent trim timestamps
570
+ - For timestamps (trim_start, trim_end, cut_start, cut_end, chunk_a_end, chunk_b_start, start_time, end_time, start_seconds, end_seconds, timestamp): parse to seconds as a number (e.g., "1:30" → 90, "2m20s" → 140)
571
+ - For timewarp_video: stretch_factor is a duration multiplier; values above 1 slow and lengthen the selected picture, while values below 1 accelerate and shorten it
572
+ - For sync_video_to_audio: anchors is an ordered array. Each anchor has video_seconds plus exactly one target: audio_seconds for an explicit audio time or audio_cue for transcript words. Convert nested timestamp values to seconds and preserve audio_cue text exactly. The original audio stays fixed; only the picture is retimed
573
+ - For every image or video generation tool, build the initial prompt from the user's requested result plus every consumed notebook cell and referenced media input
574
+ - Write generation prompts in smart Caveman style: short, concrete, role-based fragments; drop filler, hedging, pleasantries, articles, and preambles such as "Create an image of"; preserve the user's language plus exact names, technical terms, negation, numbers, units, and @addresses
575
+ - Prefer the pattern "thing, role, action. Next visual fact." and compact clauses such as "scene @a5, character @a1, fluffy kitten standing"
576
+ - Preserve every consumed notebook @address in the generation prompt at the semantic position where it belongs. Do not strip, rename, or expand notebook references into prose
577
+ - For generate_video: put the compact generation description in "prompt" and preserve every consumed @ reference
578
+ - For generate_image: put the compact image description in "prompt" and preserve every consumed image @address there; use refs.image ONLY for the corresponding resolved asset tags whose asset context type is "image", in the same order (include @ prefix). Never put a video or audio asset tag in refs.image — if the user wants an image inspired by a video, describe that source without connecting it as an image
579
+ - ByteDance naming: Seedance is video, Seedream is image. Users often say Seedance for both. When the query names seedance, bytedance, or seedream: if the edit/replace target is an image, use generate_image with model kie:seedream/5-lite-image-to-image and put the edit-target image first in refs.image, followed by replacement image refs. If the target is a video, use generate_video with model kie:bytedance/seedance-2-5, that clip in refs.video and replacement stills in refs.image. Never route an image-target Seedance ask to a video model or to Nano Banana Pro
580
+ - Treat "Seedance 5.0 edit", "Seedance 5", and "Seedream 5" as Seedream 5. Generic chat uses Seedream 5 Lite image-to-image; Seedream 5 Pro edit lives in the subject/region pipeline. When Seedream is used for an image ask that said Seedance, the status message must note that substitution
581
+ - For create_watermark_card (QR code / watermark card): use this tool for real scannable QR codes — never generate_image. Pass url from the referenced asset's source_url/webpage_url when the user says "from the url in @vid-…" or similar; optional handle is an X or TikTok alias without @; set platform to "tiktok" for TikTok or "x" for X. apply_watermark uses the same platform field for its alias, icon, and default QR destination
582
+ - For create_qart (artistic / picture QR): use when turning an image asset into scan-safe color and monochrome QR mosaics; pass image_ref and value (URL/text). Prefer over create_watermark_card when the user wants a photo integrated into the QR modules
583
+ - For create_qrbtf (parametric / styled QR): use when the user wants a stylized QR code (normal, line, dsj, bubble, or func styles) from the qrbtf library; pass value (URL/text) and optional style. No source image needed — the QR is generated parametrically with a black background by default
584
+ - For create_qr_outro: use when the user asks for an animated QR outro video from one to four QR images. Pass every referenced QR image in order through qr_image_refs (array of image asset ids), plus sound_effect_ref only for an explicit audio asset override and aspect_ratio ("16:9", "9:16", or "1:1"). Without an audio override, the bundled impact sound is used. This creates a video asset, it is NOT generate_video or create_watermark_card.
585
+ - For speech, voiceover, narration, or text-to-speech requests use generate_audio and put the exact words to speak in "prompt" (write out the words even when the user paraphrases them); omit options.voice_id unless the user supplies a specific ElevenLabs voice id
586
+ - For sound effects, foley, or background ambience (rain, crowd, whoosh, door slam) use generate_audio with model elevenlabs:sound-generation and the sound described in "prompt". For background music, a score, or a music bed use generate_audio with model elevenlabs:music and the music described in "prompt"; set options.generation_mode "ambience" for atmospheric beds and "loop" for seamless loops. To score an existing video use generate_audio with model elevenlabs:video-to-music and that clip's asset tag in refs.video
587
+ - For concat_images: use image_refs for the referenced image assets; a single ref leaves the second two-slot cell empty, and null explicitly leaves a slot empty. Use aspect_ratio 16:9 or 9:16; layout is automatic unless overridden
588
+ - For splice_video: join two or more videos into one new asset. Use this for splice, concat, or stitch requests, not plan_chat_command. Pass first_asset_id and second_asset_id in playback order, additional_asset_ids for any further clips in that same order, and overlap 0 to concatenate complete clips
589
+ - For chain: use when one request stacks two or more supported actions in order, including extract audio then replace another clip's soundtrack. Pass action "run", version 1, and ordered steps. Each step is {"id","tool","params"}. id is required and unique, starts with a letter (extract, replace, step1). Point a later step at an earlier output with {"$ref":{"step_id":"<that id>","output":"<field>"}} and never interpolate a ref inside a string. Do not nest chain or chat. Leave book_id out of step params
590
+ - Use only these chain step tools and their listed output fields: ${chainTools}
591
+ - To add background ambience or generated sound to an existing video, chain generate_audio with audio_mix; pass the generated asset_id as layer_asset_id and preserve the target's existing sound. Use replace_video_audio only when replacing the soundtrack is requested. Use apply_sfx for additional timed cues, taking asset_id from the preceding edit's output (audio_mix returns target_asset_id). After editing an asset, reference that step's output for further edits instead of the original grid address
592
+ - Background ambience should cover the target clip. A generate_audio step consumed by audio_mix or replace_video_audio automatically inherits the target duration when omitted; do not add a metadata lookup or invent duration references. Use options.duration_seconds or options.music_length_ms only for an explicitly requested length, preserving shorter cues
593
+ - For show_media_fullscreen: use when the user asks to show, open, view, or enlarge one cell's image or video (full screen, fullscreen, bigger). Pass that cell's resolved asset ID as asset_id
594
+ - plan_chat_command is only for timeline sequence edits such as trim, move, split, insert at a frame, or captions. media_context is an optional single object {notebook_id, cell_id, artifact_id} for one fullscreen clip — never an array of clips
595
+ - Timeline audio positions (start_frame, duration_frames) are in frames at 30 fps — convert seconds to frames (e.g., "at 5 seconds" → start_frame: 150)
596
+ - Do NOT include book_id in params — it is injected automatically
597
+ - Asset @tags are opaque artifact ids; the asset context lists each tag's media type ("image", "video", "audio", "script"). Use that type — never the tag text — to decide which parameter an asset belongs in
598
+ - When a referenced asset has type "script", use its script content as the prompt for generation tools
599
+
600
+ Respond with JSON only (strict JSON: double-quoted keys/strings, no trailing commas, no comments):
601
+ {"tool": "tool_name", "params": {"param1": "value1"}, "message": "Status message."}`;
602
+ }
603
+ function buildChatRoutingUserMessage(context) {
604
+ return `User query: ${context.query}
605
+
606
+ Referenced assets:
607
+ ${JSON.stringify(context.assetContext, null, 2)}
608
+
609
+ Available file paths:
610
+ - Image files: ${JSON.stringify(context.imageFiles)}
611
+ - Video files: ${JSON.stringify(context.videoFiles)}
612
+
613
+ Script contents:
614
+ ${context.scriptContents.length > 0
615
+ ? JSON.stringify(context.scriptContents, null, 2)
616
+ : "None"}
617
+
618
+ Current notebook:
619
+ ${context.notebookContext
620
+ ? JSON.stringify(context.notebookContext, null, 2)
621
+ : "None"}
622
+
623
+ Determine which tool to use and what parameters to pass. Return the routing decision as a JSON object.`;
624
+ }
625
+ function getRoutableTool(tools, name) {
626
+ return tools.find((tool) => tool.name === name);
627
+ }
628
+ export { AUTO_APPLY_TOOL_NAMES, READ_ONLY_TOOL_NAMES, TIMESTAMP_PARAMS, NESTED_TIMESTAMP_PARAMS, applyBackgroundAudioRoute, planBackgroundAudioFromQuery, applyBytedanceNamedModelRoute, applyStackedChainRoute, applyVideoJoinRoute, buildRoutableTools, buildChatRoutingPrompt, buildChatRoutingUserMessage, effectForTool, getRoutableTool, };