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,447 @@
1
+ import { mkdtemp, rm } from "node:fs/promises";
2
+ import { dirname, join, resolve } from "node:path";
3
+ import { tmpdir } from "node:os";
4
+ import { fileURLToPath } from "node:url";
5
+ import { YtDlp } from "ytdlp-nodejs";
6
+ import { ytdlpRunOptions } from "./ytdlp-binary.js";
7
+ import { findVideoFile, resolveNotebookCellArtifactId, } from "videobook-engine";
8
+ import { probeImage } from "./image.js";
9
+ import { notebookCellFingerprint } from "./jobs/run-notebook.js";
10
+ import { probeVideo, runFfmpeg } from "./ffmpeg.js";
11
+ export const DANCING_FIXTURE_OWNER = "dancing-default";
12
+ export const DANCING_FIXTURE_VERSION = 7;
13
+ const DANCING_SOURCE_URL = "https://www.youtube.com/watch?v=8GwZveBYRJI";
14
+ export const DANCING_MOTION_DURATION_SECONDS = 10;
15
+ const __dirname = dirname(fileURLToPath(import.meta.url));
16
+ const DEFAULT_KITTEN_IMAGE_PATH = resolve(__dirname, "../../tests/fixtures/images/dancing-kittens-first-frame.png");
17
+ const SOURCE_LABEL = "Dancing motion reference";
18
+ const FIRST_FRAME_LABEL = "Dancing first frame";
19
+ const KITTEN_IMAGE_LABEL = "Kittens freeway first frame";
20
+ const IMAGE_PROMPT = "Replace the two dancers with two kittens standing in the same pose on the shoulder at the side of a freeway.";
21
+ const MOTION_PROMPT = "Two kittens perform the same synchronized dance as the reference video while standing on the freeway shoulder.";
22
+ const FIXTURE_ROLES = [
23
+ "download-video",
24
+ "extract-first-frame",
25
+ "kittens-freeway",
26
+ "kittens-freeway-output",
27
+ "kling-omni-transformation",
28
+ "kling-omni-transformation-output",
29
+ ];
30
+ function roleOf(cell) {
31
+ return typeof cell.inputs?.workflowRole === "string"
32
+ ? cell.inputs.workflowRole
33
+ : null;
34
+ }
35
+ function fixtureRecord(document) {
36
+ const fixture = document.fixture;
37
+ return fixture && typeof fixture === "object" && !Array.isArray(fixture)
38
+ ? fixture
39
+ : null;
40
+ }
41
+ function fixtureCells(document) {
42
+ return document.cells.filter((cell) => cell.inputs?.fixtureOwner === DANCING_FIXTURE_OWNER);
43
+ }
44
+ function isCurrentFixture(document) {
45
+ const cells = fixtureCells(document);
46
+ const cellIds = new Set(cells.map((cell) => cell.id));
47
+ const roles = new Set(cells.map(roleOf));
48
+ const edges = document.edges.filter((edge) => cellIds.has(edge.source) && cellIds.has(edge.target));
49
+ return fixtureRecord(document)?.version === DANCING_FIXTURE_VERSION
50
+ && cells.length === FIXTURE_ROLES.length
51
+ && FIXTURE_ROLES.every((role) => roles.has(role))
52
+ && edges.length === 6
53
+ && cells.filter((cell) => cell.outputArtifactId).every((cell) => document.execution?.[cell.id]?.fingerprint
54
+ === notebookCellFingerprint(document, cell));
55
+ }
56
+ function requiredArtifact(artifacts, label) {
57
+ const artifact = artifacts.find((candidate) => candidate.label === label);
58
+ if (!artifact)
59
+ throw new Error(`Dancing fixture artifact is missing: ${label}`);
60
+ return artifact;
61
+ }
62
+ async function ensureArtifact(engine, kind, label) {
63
+ const existing = engine.artifacts.list().find((artifact) => artifact.label === label);
64
+ if (existing)
65
+ return existing;
66
+ const created = await engine.artifacts.create({ kind, label });
67
+ if (!created.ok)
68
+ throw new Error(created.error.message);
69
+ return created.value;
70
+ }
71
+ async function hasFile(engine, artifactId, filename) {
72
+ const manifest = await engine.files.manifest(artifactId);
73
+ return manifest.ok
74
+ && manifest.value.files.some((file) => file.name === filename);
75
+ }
76
+ async function downloadDancingVideo(destination) {
77
+ const ytdlp = new YtDlp(ytdlpRunOptions());
78
+ await ytdlp
79
+ .download(DANCING_SOURCE_URL)
80
+ .setOutputTemplate(destination)
81
+ .addArgs("--merge-output-format", "mp4")
82
+ .addArgs("--no-playlist")
83
+ .run();
84
+ }
85
+ async function ensureSourceVideo(engine, artifact, options) {
86
+ if (await hasFile(engine, artifact.artifactId, "original.mp4"))
87
+ return;
88
+ const workspace = await mkdtemp(join(tmpdir(), "videobook-dancing-source-"));
89
+ try {
90
+ const downloadedPath = join(workspace, "downloaded.mp4");
91
+ const sourcePath = options.sourceVideoPath ?? downloadedPath;
92
+ if (!options.sourceVideoPath)
93
+ await downloadDancingVideo(downloadedPath);
94
+ const clippedPath = join(workspace, "motion-reference.mp4");
95
+ await runFfmpeg([
96
+ "-y",
97
+ "-i", sourcePath,
98
+ "-t", String(DANCING_MOTION_DURATION_SECONDS),
99
+ "-map", "0:v:0",
100
+ "-map", "0:a:0?",
101
+ "-c:v", "libx264",
102
+ "-preset", "veryfast",
103
+ "-crf", "23",
104
+ "-pix_fmt", "yuv420p",
105
+ "-c:a", "aac",
106
+ "-b:a", "192k",
107
+ "-ac", "2",
108
+ "-movflags", "+faststart",
109
+ clippedPath,
110
+ ]);
111
+ const probe = await probeVideo(clippedPath);
112
+ if (probe.duration < 3 || probe.duration > 30) {
113
+ throw new Error(`Dancing motion reference must be 3-30 seconds, got ${probe.duration}`);
114
+ }
115
+ const written = await engine.files.writeFromPath(artifact.artifactId, "original.mp4", clippedPath);
116
+ if (!written.ok)
117
+ throw new Error(written.error.message);
118
+ const metadata = await engine.metadata.artifacts.write(artifact.artifactId, "original", {
119
+ origin: "download",
120
+ source_url: DANCING_SOURCE_URL,
121
+ title: "Dancing motion reference",
122
+ selected_range_seconds: [0, DANCING_MOTION_DURATION_SECONDS],
123
+ width: probe.width,
124
+ height: probe.height,
125
+ duration: probe.duration,
126
+ hasAudio: probe.hasAudio,
127
+ fixture: true,
128
+ });
129
+ if (!metadata.ok)
130
+ throw new Error(metadata.error.message);
131
+ }
132
+ finally {
133
+ await rm(workspace, { recursive: true, force: true });
134
+ }
135
+ }
136
+ async function ensureFirstFrame(engine, source, frame) {
137
+ if (await hasFile(engine, frame.artifactId, "original.jpg"))
138
+ return;
139
+ const sourceManifest = await engine.files.manifest(source.artifactId);
140
+ if (!sourceManifest.ok)
141
+ throw new Error(sourceManifest.error.message);
142
+ const video = findVideoFile(sourceManifest.value.files);
143
+ if (!video)
144
+ throw new Error("Dancing fixture source has no video file");
145
+ const workspace = await mkdtemp(join(tmpdir(), "videobook-dancing-frame-"));
146
+ try {
147
+ const framePath = join(workspace, "first-frame.jpg");
148
+ await runFfmpeg([
149
+ "-y",
150
+ "-ss", "0.1",
151
+ "-i", join(sourceManifest.value.path, video.name),
152
+ "-frames:v", "1",
153
+ "-q:v", "2",
154
+ framePath,
155
+ ]);
156
+ const written = await engine.files.writeFromPath(frame.artifactId, "original.jpg", framePath);
157
+ if (!written.ok)
158
+ throw new Error(written.error.message);
159
+ const image = await engine.files.read(frame.artifactId, "original.jpg");
160
+ if (!image.ok)
161
+ throw new Error(image.error.message);
162
+ const dimensions = await probeImage(image.value);
163
+ const metadata = await engine.metadata.artifacts.write(frame.artifactId, "original", {
164
+ origin: "first_frame",
165
+ source_asset: source.artifactId,
166
+ timestamp: 0.1,
167
+ ...dimensions,
168
+ fixture: true,
169
+ });
170
+ if (!metadata.ok)
171
+ throw new Error(metadata.error.message);
172
+ }
173
+ finally {
174
+ await rm(workspace, { recursive: true, force: true });
175
+ }
176
+ }
177
+ async function ensureKittenImage(engine, frame, kitten, options) {
178
+ if (await hasFile(engine, kitten.artifactId, "original.png"))
179
+ return;
180
+ const imagePath = options.kittenImagePath ?? DEFAULT_KITTEN_IMAGE_PATH;
181
+ const written = await engine.files.writeFromPath(kitten.artifactId, "original.png", imagePath);
182
+ if (!written.ok)
183
+ throw new Error(written.error.message);
184
+ const image = await engine.files.read(kitten.artifactId, "original.png");
185
+ if (!image.ok)
186
+ throw new Error(image.error.message);
187
+ const dimensions = await probeImage(image.value);
188
+ const metadata = await engine.metadata.artifacts.write(kitten.artifactId, "original", {
189
+ origin: "fixture_baseline",
190
+ source_asset: frame.artifactId,
191
+ prompt: IMAGE_PROMPT,
192
+ provider: "codex-imagegen",
193
+ ...dimensions,
194
+ fixture: true,
195
+ });
196
+ if (!metadata.ok)
197
+ throw new Error(metadata.error.message);
198
+ }
199
+ async function bootstrapDancingAssets(engine, options = {}) {
200
+ if (engine.book.get().name !== "dancing") {
201
+ throw new Error("The Dancing workflow can only seed the dancing book");
202
+ }
203
+ if (engine.notebooks.list().length === 0) {
204
+ const notebook = await engine.notebooks.create("Main");
205
+ if (!notebook.ok)
206
+ throw new Error(notebook.error.message);
207
+ }
208
+ const source = await ensureArtifact(engine, "video", SOURCE_LABEL);
209
+ const frame = await ensureArtifact(engine, "image", FIRST_FRAME_LABEL);
210
+ const kitten = await ensureArtifact(engine, "image", KITTEN_IMAGE_LABEL);
211
+ await ensureSourceVideo(engine, source, options);
212
+ await ensureFirstFrame(engine, source, frame);
213
+ await ensureKittenImage(engine, frame, kitten, options);
214
+ }
215
+ function completedExecution(document, preserved) {
216
+ const execution = { ...preserved };
217
+ const completedAt = new Date().toISOString();
218
+ for (const cell of fixtureCells(document)) {
219
+ const artifactId = resolveNotebookCellArtifactId(document, cell);
220
+ if (!artifactId)
221
+ continue;
222
+ execution[cell.id] = {
223
+ status: "completed",
224
+ fingerprint: notebookCellFingerprint(document, cell),
225
+ outputArtifactId: artifactId,
226
+ completedAt,
227
+ updatedAt: completedAt,
228
+ ...(cell.tool ? { tool: cell.tool } : {}),
229
+ fixtureBaseline: true,
230
+ };
231
+ }
232
+ return execution;
233
+ }
234
+ async function writeNotebook(engine, document) {
235
+ const written = await engine.notebooks.write(document);
236
+ if (!written.ok)
237
+ throw new Error(written.error.message);
238
+ const read = engine.notebooks.read(document.id);
239
+ if (!read.ok)
240
+ throw new Error(read.error.message);
241
+ return read.value;
242
+ }
243
+ export async function seedDancingWorkflow(engine, options = {}) {
244
+ if (engine.book.get().name !== "dancing") {
245
+ throw new Error("The Dancing workflow can only seed the dancing book");
246
+ }
247
+ await bootstrapDancingAssets(engine, options);
248
+ const notebook = engine.notebooks.list().find((candidate) => candidate.name.toLowerCase() === "dancing kittens")
249
+ ?? engine.notebooks.list()[0];
250
+ if (!notebook)
251
+ throw new Error("The Dancing book has no notebook");
252
+ if (isCurrentFixture(notebook))
253
+ return notebook;
254
+ const artifacts = engine.artifacts.list();
255
+ const sourceArtifact = requiredArtifact(artifacts, SOURCE_LABEL);
256
+ const frameArtifact = requiredArtifact(artifacts, FIRST_FRAME_LABEL);
257
+ const kittenArtifact = requiredArtifact(artifacts, KITTEN_IMAGE_LABEL);
258
+ const previousFixtureCells = fixtureCells(notebook);
259
+ const previousFixtureIds = new Set(previousFixtureCells.map((cell) => cell.id));
260
+ const preservedCells = notebook.cells.filter((cell) => !previousFixtureIds.has(cell.id));
261
+ const preservedEdges = notebook.edges.filter((edge) => !previousFixtureIds.has(edge.source) && !previousFixtureIds.has(edge.target));
262
+ const preservedExecution = Object.fromEntries(Object.entries(notebook.execution ?? {}).filter(([cellId]) => !previousFixtureIds.has(cellId)));
263
+ const ownedInputs = (workflowRole) => ({
264
+ fixtureOwner: DANCING_FIXTURE_OWNER,
265
+ workflowRole,
266
+ });
267
+ const source = engine.notebooks.createCell({
268
+ type: "video",
269
+ label: "Dancing reference video",
270
+ slot: { row: 0, column: 0 },
271
+ outputArtifactId: sourceArtifact.artifactId,
272
+ inputs: {
273
+ ...ownedInputs("download-video"),
274
+ sourceOperation: "download_video",
275
+ sourceUrl: DANCING_SOURCE_URL,
276
+ selectedRangeSeconds: [0, DANCING_MOTION_DURATION_SECONDS],
277
+ durationSeconds: DANCING_MOTION_DURATION_SECONDS,
278
+ state: "completed",
279
+ },
280
+ });
281
+ const extract = engine.notebooks.createCell({
282
+ type: "image",
283
+ label: "First frame",
284
+ slot: { row: 1, column: 0 },
285
+ outputArtifactId: frameArtifact.artifactId,
286
+ inputs: {
287
+ ...ownedInputs("extract-first-frame"),
288
+ mediaRole: "extract-frame-output",
289
+ sourceCellId: source.id,
290
+ atSeconds: 0.1,
291
+ frameMode: "first",
292
+ state: "completed",
293
+ },
294
+ });
295
+ const kittens = engine.notebooks.createCell({
296
+ type: "generate_image",
297
+ label: "Generate kittens freeway image",
298
+ slot: { row: 2, column: 1 },
299
+ prompt: IMAGE_PROMPT,
300
+ provider: "kie",
301
+ model: "kie:nano-banana-pro",
302
+ operation: "text_to_image",
303
+ tool: "generate_image",
304
+ inputs: {
305
+ ...ownedInputs("kittens-freeway"),
306
+ generationMode: "default",
307
+ generationSettings: { aspect_ratio: "9:16" },
308
+ fixtureBaseline: true,
309
+ requiresConfirmation: true,
310
+ state: "completed",
311
+ },
312
+ });
313
+ const kittenOutput = engine.notebooks.createCell({
314
+ type: "image",
315
+ label: "Kittens freeway image",
316
+ slot: { row: 3, column: 1 },
317
+ outputArtifactId: kittenArtifact.artifactId,
318
+ inputs: {
319
+ ...ownedInputs("kittens-freeway-output"),
320
+ mediaRole: "generate-image-output",
321
+ producerCellId: kittens.id,
322
+ fixtureBaseline: true,
323
+ state: "completed",
324
+ },
325
+ });
326
+ const motion = engine.notebooks.createCell({
327
+ type: "generate_video",
328
+ label: "Kittens dancing motion",
329
+ slot: { row: 3, column: 2 },
330
+ prompt: MOTION_PROMPT,
331
+ provider: "kie",
332
+ model: "kie:kling-3.0-omni/transformation",
333
+ operation: "edit_video",
334
+ tool: "generate_video",
335
+ inputs: {
336
+ ...ownedInputs("kling-omni-transformation"),
337
+ generationSettings: {
338
+ resolution: "720p",
339
+ aspect_ratio: "9:16",
340
+ duration: "10",
341
+ },
342
+ requiresConfirmation: true,
343
+ state: "pending",
344
+ },
345
+ });
346
+ const motionOutput = engine.notebooks.createCell({
347
+ type: "video",
348
+ label: "Kittens dancing video",
349
+ slot: { row: 4, column: 2 },
350
+ inputs: {
351
+ ...ownedInputs("kling-omni-transformation-output"),
352
+ mediaRole: "generate-video-output",
353
+ producerCellId: motion.id,
354
+ state: "pending",
355
+ },
356
+ });
357
+ const fixtureEdges = [
358
+ engine.notebooks.createEdge({
359
+ source: source.id,
360
+ target: extract.id,
361
+ targetInput: "segment",
362
+ }),
363
+ engine.notebooks.createEdge({
364
+ source: extract.id,
365
+ target: kittens.id,
366
+ targetInput: "input",
367
+ }),
368
+ engine.notebooks.createEdge({
369
+ source: kittens.id,
370
+ target: kittenOutput.id,
371
+ targetInput: "media",
372
+ }),
373
+ engine.notebooks.createEdge({
374
+ source: kittenOutput.id,
375
+ target: motion.id,
376
+ targetInput: "image",
377
+ }),
378
+ engine.notebooks.createEdge({
379
+ source: source.id,
380
+ target: motion.id,
381
+ targetInput: "video",
382
+ }),
383
+ engine.notebooks.createEdge({
384
+ source: motion.id,
385
+ target: motionOutput.id,
386
+ targetInput: "media",
387
+ }),
388
+ ];
389
+ const ensuredAt = new Date().toISOString();
390
+ const document = {
391
+ ...notebook,
392
+ name: "Dancing Kittens",
393
+ description: "Download a dance reference, extract its first frame, replace the dancers with kittens beside a freeway, then transfer the dance with Kling 3.0 Omni transformation.",
394
+ lifecycleState: "in-progress",
395
+ cells: [
396
+ ...preservedCells,
397
+ source,
398
+ extract,
399
+ kittens,
400
+ kittenOutput,
401
+ motion,
402
+ motionOutput,
403
+ ],
404
+ edges: [...preservedEdges, ...fixtureEdges],
405
+ generationPlans: [],
406
+ notebookRunPlans: [],
407
+ execution: preservedExecution,
408
+ fixture: {
409
+ version: DANCING_FIXTURE_VERSION,
410
+ owner: DANCING_FIXTURE_OWNER,
411
+ ensuredAt,
412
+ materializedAt: ensuredAt,
413
+ noPaidCalls: true,
414
+ sourceUrl: DANCING_SOURCE_URL,
415
+ motionDurationSeconds: DANCING_MOTION_DURATION_SECONDS,
416
+ },
417
+ };
418
+ document.execution = completedExecution(document, preservedExecution);
419
+ const persisted = await writeNotebook(engine, document);
420
+ persisted.execution = completedExecution(persisted, persisted.execution ?? preservedExecution);
421
+ return writeNotebook(engine, persisted);
422
+ }
423
+ export async function ensureDancingWorkflow(books, options = {}) {
424
+ await books.ready();
425
+ let selected = books.getByName("dancing");
426
+ let created = false;
427
+ if (!selected.ok) {
428
+ const createdBook = await books.create("dancing");
429
+ if (!createdBook.ok)
430
+ throw new Error(createdBook.error.message);
431
+ selected = books.getByName("dancing");
432
+ if (!selected.ok)
433
+ throw new Error(selected.error.message);
434
+ created = true;
435
+ }
436
+ const previousHead = selected.value.engine.head;
437
+ const notebook = await seedDancingWorkflow(selected.value.engine, options);
438
+ return {
439
+ status: created
440
+ ? "created"
441
+ : selected.value.engine.head === previousHead
442
+ ? "unchanged"
443
+ : "migrated",
444
+ notebookId: notebook.id,
445
+ revision: selected.value.engine.head,
446
+ };
447
+ }
@@ -0,0 +1,44 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { homedir } from "node:os";
3
+ import { dirname, join, resolve } from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ const WORKSPACE_PACKAGE_NAME = "videobook-workspace";
6
+ function packageName(path) {
7
+ try {
8
+ const parsed = JSON.parse(readFileSync(path, "utf8"));
9
+ return typeof parsed.name === "string" ? parsed.name : null;
10
+ }
11
+ catch {
12
+ return null;
13
+ }
14
+ }
15
+ export function sourceCheckoutRoot(moduleUrl = import.meta.url) {
16
+ const root = resolve(dirname(fileURLToPath(moduleUrl)), "../..");
17
+ return packageName(join(root, "package.json")) === WORKSPACE_PACKAGE_NAME ? root : null;
18
+ }
19
+ function homeLayout(root) {
20
+ return {
21
+ kind: "home",
22
+ root,
23
+ libraryDir: join(root, "books"),
24
+ appStatePath: join(root, "app-state.json"),
25
+ envPath: join(root, ".env"),
26
+ };
27
+ }
28
+ function checkoutLayout(root) {
29
+ return {
30
+ kind: "checkout",
31
+ root,
32
+ libraryDir: join(root, "books"),
33
+ appStatePath: join(root, "runtime", "app-state.json"),
34
+ envPath: join(root, ".env"),
35
+ };
36
+ }
37
+ export function dataLayout(env = process.env, cwd = process.cwd(), checkoutRoot = sourceCheckoutRoot()) {
38
+ const home = env.VIDEOBOOK_HOME?.trim();
39
+ if (home)
40
+ return homeLayout(resolve(cwd, home));
41
+ if (checkoutRoot)
42
+ return checkoutLayout(checkoutRoot);
43
+ return homeLayout(join(homedir(), ".videobook"));
44
+ }
@@ -0,0 +1,109 @@
1
+ import { ENGINE_ERROR_CODES } from "videobook-engine";
2
+ const EVENTS = [
3
+ "mcp", "server-listening", "shutdown-complete", "shutdown-failed", "startup-failed",
4
+ "book-open", "book-open-slow", "book-catalog-gc", "provider-poll-failed",
5
+ "ace-server-exited", "scheduled-post-failed", "scheduled-post-rearm-failed",
6
+ "generation-record-failed", "generation-update-failed", "generation-list-failed",
7
+ "provider-task-record-failed",
8
+ "prompt-record-failed",
9
+ "waveform-empty", "waveform-failed", "heartbeat-failed", "subtitle-cache-failed",
10
+ "subtitle-translation-failed", "overlay-skipped", "kie-upload-fallback",
11
+ "kie-upload-unconfigured", "fal-upload-fallback", "fal-upload-unconfigured",
12
+ "alibaba-upload-fallback", "alibaba-upload-unconfigured", "suggest-cuts-dropped",
13
+ "suggest-sfx-dropped", "transcribe-soft-fail", "post-record-failed", "post-cell-failed",
14
+ "process-video-enqueue-failed", "waveform-write-failed", "timeline-reencode",
15
+ "pad-video-started", "video-analysis-failed", "description-truncated",
16
+ "description-cache-failed", "watermark-placement-fallback", "waveform-enqueue-failed",
17
+ "poster-enqueue-failed",
18
+ "watermark-probe-fallback", "generation-error-clear-failed", "timeline-orientation-failed",
19
+ "generation-cost-estimate", "job-error", "semantic-index-deferred",
20
+ "tag-asset-failed", "voice-session-closed", "alive-captions-regions-failed",
21
+ ];
22
+ const events = new Set(EVENTS);
23
+ const errorCodes = new Set([
24
+ ...ENGINE_ERROR_CODES, "UNKNOWN", "ENOENT", "EACCES", "EPERM", "ENOSPC",
25
+ "EIO", "EMFILE", "ENFILE", "ENOMEM", "ECONNREFUSED", "ECONNRESET",
26
+ "ETIMEDOUT", "EPIPE", "ENOTFOUND", "EADDRINUSE", "EADDRNOTAVAIL", "ABORT_ERR",
27
+ ]);
28
+ const names = { tool: new Set(), jobType: new Set() };
29
+ export function registerDiagnosticName(kind, name) {
30
+ if (typeof name === "string" && name.trim() === name && /^[a-z][a-z0-9_]{0,95}$/.test(name))
31
+ names[kind].add(name);
32
+ }
33
+ function ownValue(value, key) {
34
+ if (typeof value !== "object" || value === null)
35
+ return undefined;
36
+ try {
37
+ return Object.getOwnPropertyDescriptor(value, key)?.value;
38
+ }
39
+ catch {
40
+ return undefined;
41
+ }
42
+ }
43
+ export function diagnosticErrorCode(error) {
44
+ for (const value of [ownValue(error, "code"), ownValue(ownValue(error, "error"), "code")]) {
45
+ if (typeof value === "string" && errorCodes.has(value))
46
+ return value;
47
+ }
48
+ return "UNKNOWN";
49
+ }
50
+ const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
51
+ const UUID_FIELDS = ["bookId", "assetId", "artifactId", "notebookId", "cellId", "outputCellId",
52
+ "generationId", "scheduleId", "operationId", "runId"];
53
+ const NUMBER_FIELDS = ["durationMs", "bytesBefore", "bytesAfter", "count", "limit", "warningCount", "targetFps", "inputTokens", "outputTokens"];
54
+ const ENUM_FIELDS = {
55
+ voiceModel: ["gpt-realtime-2.1-mini", "gpt-realtime-2.1", "gpt-realtime-mini", "gpt-realtime", "grok-voice-think-fast-2.0", "grok-voice-latest"],
56
+ status: ["ok", "error"],
57
+ modality: ["visual", "audio", "metadata"],
58
+ reason: ["unbounded", "zero", "missing-adapter", "missing-rates", "missing-selector", "estimator-threw", "estimate-error"],
59
+ provider: ["kie", "fal", "alibaba", "elevenlabs", "openai", "kimicoding", "xai", "acestep"],
60
+ stage: ["submit-kie", "submit-queued-kie", "submit-veo", "index-progressive"],
61
+ signal: ["SIGTERM", "SIGKILL", "SIGINT", "SIGABRT", "SIGSEGV", "SIGBUS", "SIGILL", "SIGFPE", "SIGHUP"],
62
+ };
63
+ export function diagnosticRecord(event, fields = {}) {
64
+ const result = { event: events.has(event) ? event : "unknown-event" };
65
+ for (const key of UUID_FIELDS) {
66
+ const value = ownValue(fields, key);
67
+ if (typeof value === "string" && value.length === 36 && UUID.test(value))
68
+ result[key] = value;
69
+ }
70
+ for (const key of NUMBER_FIELDS) {
71
+ const value = ownValue(fields, key);
72
+ if (typeof value === "number" && Number.isFinite(value) && value >= 0)
73
+ result[key] = value;
74
+ }
75
+ for (const key of ["available", "detached", "rolledBack"]) {
76
+ const value = ownValue(fields, key);
77
+ if (typeof value === "boolean")
78
+ result[key] = value;
79
+ }
80
+ for (const key of Object.keys(ENUM_FIELDS)) {
81
+ const value = ownValue(fields, key);
82
+ if (typeof value === "string" && ENUM_FIELDS[key].includes(value))
83
+ result[key] = value;
84
+ }
85
+ for (const key of ["tool", "jobType"]) {
86
+ const value = ownValue(fields, key);
87
+ if (typeof value === "string" && names[key].has(value))
88
+ result[key] = value;
89
+ }
90
+ const jobId = ownValue(fields, "jobId");
91
+ if ((typeof jobId === "number" && Number.isSafeInteger(jobId) && jobId >= 0)
92
+ || (typeof jobId === "string" && jobId.length === 36 && UUID.test(jobId)))
93
+ result.jobId = jobId;
94
+ for (const [key, min, max] of [["exitCode", -255, 255], ["port", 1, 65535]]) {
95
+ const value = ownValue(fields, key);
96
+ if (typeof value === "number" && Number.isInteger(value) && value >= min && value <= max)
97
+ result[key] = value;
98
+ }
99
+ const error = ownValue(fields, "error");
100
+ const code = ownValue(fields, "errorCode");
101
+ if (error !== undefined || code !== undefined) {
102
+ result.errorCode = typeof code === "string" && errorCodes.has(code) ? code : diagnosticErrorCode(error);
103
+ }
104
+ return result;
105
+ }
106
+ export async function appendDiagnostic(engine, event, fields) {
107
+ const record = diagnosticRecord(event, fields);
108
+ await engine.logs.append(String(record.event), record);
109
+ }
@@ -0,0 +1,34 @@
1
+ export function assessDialogQuality(data) {
2
+ const raw = data.text ?? "";
3
+ const trimmed = raw.trim();
4
+ if (trimmed.length === 0) {
5
+ return { hasDialog: false, reason: "empty", text: trimmed, wordCount: 0 };
6
+ }
7
+ const stripped = trimmed.replace(/\[[^\]]*\]/g, "").trim();
8
+ if (stripped.length === 0) {
9
+ return { hasDialog: false, reason: "noise_only", text: trimmed, wordCount: 0 };
10
+ }
11
+ const words = stripped.split(/\s+/);
12
+ const wordCount = words.length;
13
+ if (wordCount < 3) {
14
+ return { hasDialog: false, reason: "too_short", text: trimmed, wordCount };
15
+ }
16
+ const uniqueWords = new Set(words.map((w) => w.toLowerCase()));
17
+ if (uniqueWords.size / wordCount < 0.3) {
18
+ return { hasDialog: false, reason: "nonsensical", text: trimmed, wordCount };
19
+ }
20
+ return { hasDialog: true, reason: "real_dialog", text: trimmed, wordCount };
21
+ }
22
+ export async function readAndAssessDialog(engine, assetId) {
23
+ const result = await engine.files.read(assetId, ".analysis.gpt4otrans.json");
24
+ if (!result.ok) {
25
+ return { hasDialog: false, reason: "no_transcription", text: "", wordCount: 0 };
26
+ }
27
+ try {
28
+ const data = JSON.parse(result.value.toString());
29
+ return assessDialogQuality(data);
30
+ }
31
+ catch {
32
+ return { hasDialog: false, reason: "no_transcription", text: "", wordCount: 0 };
33
+ }
34
+ }