@gentbajko/slopify 3.25.9 → 4.1.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 (718) hide show
  1. package/dist/adapters/account-limits.js +30 -0
  2. package/dist/adapters/alignment/audio.js +1 -1
  3. package/dist/adapters/alignment/cache.js +4 -6
  4. package/dist/adapters/alignment/ctc.js +1 -2
  5. package/dist/adapters/alignment/lock.js +4 -3
  6. package/dist/adapters/alignment/multilingual.js +2 -4
  7. package/dist/adapters/alignment/prefetch.js +2 -1
  8. package/dist/adapters/alignment/runner.js +1 -1
  9. package/dist/adapters/alignment/worker.js +3 -2
  10. package/dist/adapters/explain.js +10 -12
  11. package/dist/adapters/ffmpeg.js +19 -1
  12. package/dist/adapters/host-cli/index.js +21 -4
  13. package/dist/adapters/host-cli/transport.js +2 -1
  14. package/dist/adapters/http-failure.js +53 -0
  15. package/dist/adapters/image/bytes.js +2 -1
  16. package/dist/adapters/image/codex.js +42 -9
  17. package/dist/adapters/image/fal.js +21 -53
  18. package/dist/adapters/image/google.js +33 -56
  19. package/dist/adapters/image/models.js +2 -2
  20. package/dist/adapters/image/openai.js +22 -48
  21. package/dist/adapters/image/reference.js +36 -0
  22. package/dist/adapters/image/replicate.js +21 -49
  23. package/dist/adapters/image/video.js +2 -1
  24. package/dist/adapters/interest/search-interest.js +113 -0
  25. package/dist/adapters/key-probes.js +54 -3
  26. package/dist/adapters/llm/antigravity-models.js +1 -1
  27. package/dist/adapters/llm/antigravity.js +11 -6
  28. package/dist/adapters/llm/assistant-cli.js +388 -0
  29. package/dist/adapters/llm/child-session.js +83 -0
  30. package/dist/adapters/llm/claude-code-models.js +52 -99
  31. package/dist/adapters/llm/claude-code.js +16 -4
  32. package/dist/adapters/llm/codex-limits.js +27 -68
  33. package/dist/adapters/llm/codex-models.js +1 -1
  34. package/dist/adapters/llm/codex-server-models.js +61 -109
  35. package/dist/adapters/llm/codex.js +12 -1
  36. package/dist/adapters/llm/document-workspace.js +3 -2
  37. package/dist/adapters/llm/image-workspace.js +3 -2
  38. package/dist/adapters/llm/openrouter.js +12 -48
  39. package/dist/adapters/llm/run-cli.js +9 -24
  40. package/dist/adapters/llm/sse-lines.js +5 -1
  41. package/dist/adapters/model-access.js +37 -0
  42. package/dist/adapters/tts/cartesia.js +15 -46
  43. package/dist/adapters/tts/elevenlabs.js +20 -52
  44. package/dist/adapters/tts/gemini.js +21 -41
  45. package/dist/adapters/tts/inworld-async.js +6 -2
  46. package/dist/adapters/tts/inworld.js +6 -2
  47. package/dist/adapters/tts/openai.js +20 -50
  48. package/dist/adapters/tts/system.js +2 -1
  49. package/dist/assets/models-lifecycle.yaml +6 -0
  50. package/dist/assistant-wiring.js +60 -0
  51. package/dist/autopilot-timers.js +59 -0
  52. package/dist/catalog/lifecycle.js +52 -0
  53. package/dist/catalog/propose.js +204 -0
  54. package/dist/catalog/registry.js +23 -14
  55. package/dist/catalog/schema.js +4 -1
  56. package/dist/catalog/store.js +39 -0
  57. package/dist/catalog/validate.js +5 -2
  58. package/dist/edge/autostart/native.js +3 -5
  59. package/dist/edge/autostart/prompt.js +2 -1
  60. package/dist/edge/autostart/service.js +3 -4
  61. package/dist/edge/cli-args.js +3 -4
  62. package/dist/edge/cli.js +2 -1
  63. package/dist/edge/docker-install/apply.js +11 -11
  64. package/dist/edge/docker-install/run.js +2 -1
  65. package/dist/edge/docker-install/state.js +4 -3
  66. package/dist/edge/docker-install/tree.js +2 -4
  67. package/dist/edge/docker-install/volume.js +3 -2
  68. package/dist/edge/docker.js +5 -4
  69. package/dist/edge/events/hub.js +5 -5
  70. package/dist/edge/http/actions.js +11 -32
  71. package/dist/edge/http/actor.js +5 -3
  72. package/dist/edge/http/app.js +86 -11
  73. package/dist/edge/http/assistant.js +129 -0
  74. package/dist/edge/http/audio-preview.js +4 -11
  75. package/dist/edge/http/auditions.js +1 -1
  76. package/dist/edge/http/autostart.js +5 -5
  77. package/dist/edge/http/backups.js +2 -4
  78. package/dist/edge/http/channel-memory.js +9 -22
  79. package/dist/edge/http/channels.js +14 -27
  80. package/dist/edge/http/checkpoints.js +39 -21
  81. package/dist/edge/http/design-templates.js +167 -0
  82. package/dist/edge/http/designs.js +178 -0
  83. package/dist/edge/http/diagnostics.js +5 -1
  84. package/dist/edge/http/document-themes.js +5 -14
  85. package/dist/edge/http/draft-files.js +1 -3
  86. package/dist/edge/http/draft-problem.js +5 -10
  87. package/dist/edge/http/drafts.js +3 -3
  88. package/dist/edge/http/entries.js +6 -9
  89. package/dist/edge/http/extension-auth.js +27 -0
  90. package/dist/edge/http/external-reviews.js +12 -11
  91. package/dist/edge/http/files.js +5 -11
  92. package/dist/edge/http/folder-location.js +1 -4
  93. package/dist/edge/http/fonts.js +0 -7
  94. package/dist/edge/http/home.js +47 -14
  95. package/dist/edge/http/host-cli.js +18 -8
  96. package/dist/edge/http/ids.js +8 -0
  97. package/dist/edge/http/keywords.js +35 -0
  98. package/dist/edge/http/model-checks.js +132 -0
  99. package/dist/edge/http/narration-peaks.js +5 -13
  100. package/dist/edge/http/onboarding.js +30 -26
  101. package/dist/edge/http/open-folder.js +5 -10
  102. package/dist/edge/http/outputs.js +7 -14
  103. package/dist/edge/http/patch-notes.js +6 -12
  104. package/dist/edge/http/planning.js +3 -7
  105. package/dist/edge/http/problem.js +2 -4
  106. package/dist/edge/http/project-create.js +2 -1
  107. package/dist/edge/http/project-templates.js +31 -19
  108. package/dist/edge/http/projects.js +24 -16
  109. package/dist/edge/http/prompts.js +9 -16
  110. package/dist/edge/http/pronunciations.js +1 -2
  111. package/dist/edge/http/providers.js +48 -34
  112. package/dist/edge/http/refusal.js +29 -0
  113. package/dist/edge/http/remote-access.js +40 -0
  114. package/dist/edge/http/remote-guard.js +71 -0
  115. package/dist/edge/http/request-guard.js +91 -0
  116. package/dist/edge/http/reviews.js +12 -25
  117. package/dist/edge/http/revision-files.js +6 -11
  118. package/dist/edge/http/revisions.js +14 -19
  119. package/dist/edge/http/run-cost.js +1 -2
  120. package/dist/edge/http/same-page.js +80 -0
  121. package/dist/edge/http/schedules.js +69 -40
  122. package/dist/edge/http/settings.js +27 -14
  123. package/dist/edge/http/social.js +283 -0
  124. package/dist/edge/http/staging.js +3 -5
  125. package/dist/edge/http/storage-files.js +5 -7
  126. package/dist/edge/http/storage.js +33 -25
  127. package/dist/edge/http/studio.js +94 -69
  128. package/dist/edge/http/style-preview.js +3 -6
  129. package/dist/edge/http/subtitles.js +3 -17
  130. package/dist/edge/http/template-studio.js +436 -0
  131. package/dist/edge/http/trash.js +11 -12
  132. package/dist/edge/http/tutorial.js +1 -2
  133. package/dist/edge/http/tutorials.js +5 -11
  134. package/dist/edge/http/update.js +7 -13
  135. package/dist/edge/http/waveform.js +3 -6
  136. package/dist/edge/http/youtube-edits.js +3 -4
  137. package/dist/edge/mcp/assistant.js +279 -0
  138. package/dist/edge/mcp/attribution.js +8 -2
  139. package/dist/edge/mcp/call-route.js +11 -2
  140. package/dist/edge/mcp/excluded-routes.js +29 -3
  141. package/dist/edge/mcp/http.js +11 -2
  142. package/dist/edge/mcp/instructions.js +6 -4
  143. package/dist/edge/mcp/library-tools.js +9 -5
  144. package/dist/edge/mcp/remake-tools.js +7 -4
  145. package/dist/edge/mcp/route-tool.js +35 -15
  146. package/dist/edge/mcp/server.js +13 -8
  147. package/dist/edge/mcp/tools-channels.js +11 -9
  148. package/dist/edge/mcp/tools-designs.js +165 -0
  149. package/dist/edge/mcp/tools-library.js +19 -7
  150. package/dist/edge/mcp/tools-planning.js +40 -21
  151. package/dist/edge/mcp/tools-projects.js +38 -11
  152. package/dist/edge/mcp/tools-publishing.js +9 -9
  153. package/dist/edge/mcp/tools-runs.js +23 -10
  154. package/dist/edge/mcp/tools-schedules.js +32 -8
  155. package/dist/edge/mcp/tools-setup.js +75 -11
  156. package/dist/edge/mcp/tools-social.js +47 -0
  157. package/dist/edge/mcp/tools-storage.js +11 -3
  158. package/dist/edge/mcp/tools-template-studio.js +166 -0
  159. package/dist/edge/mcp/tools.js +6 -0
  160. package/dist/edge/remote-access/cli.js +71 -0
  161. package/dist/edge/remote-access/model.js +32 -0
  162. package/dist/edge/remote-access/rules.js +207 -0
  163. package/dist/edge/remote-access/service.js +203 -0
  164. package/dist/edge/remote-access/store.js +44 -0
  165. package/dist/edge/remote-access/views.js +43 -0
  166. package/dist/extension/slopify-studio-chrome.zip +0 -0
  167. package/dist/extension/slopify-studio-firefox.zip +0 -0
  168. package/dist/host-cli/install.js +2 -2
  169. package/dist/host-cli/open-folder.js +2 -2
  170. package/dist/host-cli/paths.js +2 -4
  171. package/dist/host-cli/server.js +4 -4
  172. package/dist/host-cli/service.js +3 -3
  173. package/dist/host-cli/status.js +7 -7
  174. package/dist/kernel/db/migrations/0063-model-checks.sql +20 -0
  175. package/dist/kernel/db/migrations/0064-template-studio.sql +46 -0
  176. package/dist/kernel/db/migrations/0065-promise-and-assistant-reviews.sql +58 -0
  177. package/dist/kernel/db/migrations/0066-assistant.sql +44 -0
  178. package/dist/kernel/db/migrations/0067-autopilot.sql +6 -0
  179. package/dist/kernel/db/migrations/0068-topic-scores.sql +17 -0
  180. package/dist/kernel/db/migrations/0070-designs.sql +53 -0
  181. package/dist/kernel/db/migrations/0071-design-usage.sql +33 -0
  182. package/dist/kernel/db/migrations/0072-design-templates.sql +33 -0
  183. package/dist/kernel/db/migrations/0073-schedule-design-kind.sql +5 -0
  184. package/dist/kernel/db/migrations/0074-template-bakeoffs.sql +44 -0
  185. package/dist/kernel/db/migrations/0075-social-posts.sql +25 -0
  186. package/dist/kernel/db/migrations/0076-channel-social.sql +5 -0
  187. package/dist/kernel/db/migrations/0077-post-prompts.sql +17 -0
  188. package/dist/kernel/db/migrations/0078-uploaded-from-links.sql +7 -0
  189. package/dist/kernel/db/tx.js +2 -4
  190. package/dist/kernel/errors.js +27 -1
  191. package/dist/kernel/json-answer.js +15 -0
  192. package/dist/kernel/lock.js +4 -9
  193. package/dist/kernel/paths.js +8 -0
  194. package/dist/kernel/pipeline.js +12 -0
  195. package/dist/kernel/ports/assistant-cli.js +4 -0
  196. package/dist/kernel/ports/host-cli.js +3 -0
  197. package/dist/kernel/ports/interest.js +4 -0
  198. package/dist/kernel/ports/languages.js +0 -3
  199. package/dist/kernel/ports/model.js +2 -0
  200. package/dist/kernel/ports/settings-places.js +31 -0
  201. package/dist/kernel/ports/system-speech.js +31 -3
  202. package/dist/kernel/runner/attempt.js +14 -4
  203. package/dist/kernel/runner/audition.js +3 -1
  204. package/dist/kernel/runner/checkpoint-authority.js +2 -1
  205. package/dist/kernel/runner/index.js +8 -10
  206. package/dist/kernel/runner/model-access.js +40 -0
  207. package/dist/kernel/runner/model-check.js +153 -0
  208. package/dist/kernel/runner/providers.js +18 -12
  209. package/dist/kernel/runner/standalone.js +11 -7
  210. package/dist/main.js +338 -21
  211. package/dist/model-catalog.js +20 -0
  212. package/dist/model-checks.js +166 -0
  213. package/dist/patch-notes/4.0.0.md +51 -0
  214. package/dist/patch-notes/4.1.0.md +42 -0
  215. package/dist/patch-notes/index.json +12 -0
  216. package/dist/slices/admission/heads.js +2 -1
  217. package/dist/slices/admission/listing-facts.js +95 -0
  218. package/dist/slices/admission/repo.js +11 -7
  219. package/dist/slices/admission/rules.js +50 -15
  220. package/dist/slices/admission/schema.js +8 -0
  221. package/dist/slices/admission/stage-writes.js +0 -3
  222. package/dist/slices/admission/start.js +48 -31
  223. package/dist/slices/admission/state-words.js +34 -5
  224. package/dist/slices/admission/substitute.js +7 -4
  225. package/dist/slices/agents/attention-posts.js +31 -0
  226. package/dist/slices/agents/attention-templates.js +33 -0
  227. package/dist/slices/agents/attention.js +10 -1
  228. package/dist/slices/agents/connection.js +2 -6
  229. package/dist/slices/agents/model.js +6 -3
  230. package/dist/slices/agents/repo.js +15 -7
  231. package/dist/slices/article/continuation.js +0 -63
  232. package/dist/slices/article/plain.js +3 -2
  233. package/dist/slices/article/segments.js +2 -62
  234. package/dist/slices/assistant/access.js +1 -0
  235. package/dist/slices/assistant/asks.js +80 -0
  236. package/dist/slices/assistant/cost.js +54 -0
  237. package/dist/slices/assistant/gate.js +222 -0
  238. package/dist/slices/assistant/model.js +86 -0
  239. package/dist/slices/assistant/names.js +23 -0
  240. package/dist/slices/assistant/prompt.js +74 -0
  241. package/dist/slices/assistant/repo.js +74 -0
  242. package/dist/slices/assistant/tokens.js +18 -0
  243. package/dist/slices/assistant/turn.js +344 -0
  244. package/dist/slices/autopilot/buffer.js +76 -0
  245. package/dist/slices/autopilot/model.js +14 -0
  246. package/dist/slices/autopilot/notify.js +27 -0
  247. package/dist/slices/autopilot/repo.js +34 -0
  248. package/dist/slices/autopilot/signals.js +194 -0
  249. package/dist/slices/autopilot/warnings.js +85 -0
  250. package/dist/slices/autopilot/weekly.js +100 -0
  251. package/dist/slices/backups/files.js +2 -6
  252. package/dist/slices/backups/repo.js +3 -15
  253. package/dist/slices/backups/service.js +8 -7
  254. package/dist/slices/channels/cast-images.js +3 -2
  255. package/dist/slices/channels/model.js +0 -1
  256. package/dist/slices/channels/rebrand.js +0 -3
  257. package/dist/slices/channels/repo.js +4 -0
  258. package/dist/slices/channels/schema.js +7 -1
  259. package/dist/slices/channels/service.js +10 -0
  260. package/dist/slices/channels/videos.js +3 -15
  261. package/dist/slices/checkpoints/index.js +0 -1
  262. package/dist/slices/control/providers.js +2 -28
  263. package/dist/slices/designs/artwork.js +66 -0
  264. package/dist/slices/designs/budget.js +23 -0
  265. package/dist/slices/designs/calls.js +124 -0
  266. package/dist/slices/designs/check-context.js +38 -0
  267. package/dist/slices/designs/check-text.js +43 -0
  268. package/dist/slices/designs/fields.js +88 -0
  269. package/dist/slices/designs/frames.js +34 -0
  270. package/dist/slices/designs/gate.js +130 -0
  271. package/dist/slices/designs/layout.js +293 -0
  272. package/dist/slices/designs/model.js +35 -0
  273. package/dist/slices/designs/pdf-job.js +23 -0
  274. package/dist/slices/designs/pdf-pages.js +30 -0
  275. package/dist/slices/designs/pdf-runner.js +68 -0
  276. package/dist/slices/designs/pdf-worker.js +24 -0
  277. package/dist/slices/designs/picture-size.js +79 -0
  278. package/dist/slices/designs/pictures.js +55 -0
  279. package/dist/slices/designs/quote.js +24 -0
  280. package/dist/slices/designs/render-args.js +36 -0
  281. package/dist/slices/designs/render-input.js +59 -0
  282. package/dist/slices/designs/render.js +215 -0
  283. package/dist/slices/designs/repo.js +101 -0
  284. package/dist/slices/designs/requests.js +80 -0
  285. package/dist/slices/designs/runner.js +239 -0
  286. package/dist/slices/designs/sample-repo.js +91 -0
  287. package/dist/slices/designs/sample.js +223 -0
  288. package/dist/slices/designs/schema.js +87 -0
  289. package/dist/slices/designs/sections.js +44 -0
  290. package/dist/slices/designs/service.js +233 -0
  291. package/dist/slices/designs/steps-repo.js +102 -0
  292. package/dist/slices/designs/studio-kind.js +39 -0
  293. package/dist/slices/designs/template-checks.js +44 -0
  294. package/dist/slices/designs/template-make.js +118 -0
  295. package/dist/slices/designs/templates.js +218 -0
  296. package/dist/slices/document/fonts.js +2 -1
  297. package/dist/slices/document/model.js +7 -4
  298. package/dist/slices/document/render.js +2 -1
  299. package/dist/slices/document/theme-schema.js +1 -1
  300. package/dist/slices/document/theme.js +49 -3
  301. package/dist/slices/episodes/summarize.js +6 -2
  302. package/dist/slices/estimate/index.js +72 -28
  303. package/dist/slices/estimate/requests.js +4 -4
  304. package/dist/slices/fixes/rules.js +3 -1
  305. package/dist/slices/fonts/catalog.js +5 -3
  306. package/dist/slices/fonts/coverage.js +2 -1
  307. package/dist/slices/fonts/discovery.js +3 -2
  308. package/dist/slices/fonts/files.js +2 -6
  309. package/dist/slices/fonts/index.js +0 -1
  310. package/dist/slices/fonts/sfnt.js +45 -10
  311. package/dist/slices/images/appearance.js +8 -16
  312. package/dist/slices/images/scenes.js +102 -28
  313. package/dist/slices/keywords/digest.js +85 -0
  314. package/dist/slices/keywords/facts.js +92 -0
  315. package/dist/slices/keywords/fill.js +80 -0
  316. package/dist/slices/keywords/model.js +75 -0
  317. package/dist/slices/keywords/rules.js +187 -0
  318. package/dist/slices/keywords/schema.js +28 -0
  319. package/dist/slices/keywords/specs.js +260 -0
  320. package/dist/slices/keywords/values.js +74 -0
  321. package/dist/slices/library/lint.js +29 -12
  322. package/dist/slices/library/model.js +2 -0
  323. package/dist/slices/library/photorealistic.js +4 -12
  324. package/dist/slices/library/rename.js +9 -7
  325. package/dist/slices/library/save.js +14 -10
  326. package/dist/slices/library/slots.js +37 -11
  327. package/dist/slices/library/transfer.js +5 -4
  328. package/dist/slices/library/used-by.js +25 -10
  329. package/dist/slices/loudness/loudnorm.js +53 -12
  330. package/dist/slices/loudness/model.js +3 -2
  331. package/dist/slices/loudness/sentence-level.js +2 -1
  332. package/dist/slices/model-checks/cost.js +61 -0
  333. package/dist/slices/model-checks/listing.js +124 -0
  334. package/dist/slices/model-checks/model.js +20 -0
  335. package/dist/slices/model-checks/record.js +32 -0
  336. package/dist/slices/model-checks/repo.js +120 -0
  337. package/dist/slices/model-checks/rules.js +125 -0
  338. package/dist/slices/model-checks/run.js +143 -0
  339. package/dist/slices/model-checks/service.js +198 -0
  340. package/dist/slices/model-upkeep/model.js +1 -1
  341. package/dist/slices/model-upkeep/switch.js +72 -27
  342. package/dist/slices/model-upkeep/usage.js +39 -13
  343. package/dist/slices/narration/breaths.js +3 -1
  344. package/dist/slices/narration/clean-pieces.js +3 -1
  345. package/dist/slices/narration/concat.js +2 -1
  346. package/dist/slices/narration/pauses-model.js +3 -2
  347. package/dist/slices/narration/peaks.js +3 -4
  348. package/dist/slices/narration/pronunciation-chunks.js +4 -3
  349. package/dist/slices/narration/pronunciation.js +6 -4
  350. package/dist/slices/narration/steering.js +4 -3
  351. package/dist/slices/notifications/notifier.js +4 -3
  352. package/dist/slices/notifications/rules.js +5 -2
  353. package/dist/slices/notifications/settings.js +4 -12
  354. package/dist/slices/notifications/subject.js +4 -3
  355. package/dist/slices/onboarding/copy.js +21 -3
  356. package/dist/slices/onboarding/first-run.js +16 -40
  357. package/dist/slices/onboarding/full-video.js +3 -2
  358. package/dist/slices/onboarding/install.js +6 -4
  359. package/dist/slices/onboarding/model.js +26 -37
  360. package/dist/slices/onboarding/packs.js +22 -22
  361. package/dist/slices/onboarding/preferred-model.js +14 -0
  362. package/dist/slices/onboarding/quick-short.js +105 -65
  363. package/dist/slices/onboarding/sample.js +4 -2
  364. package/dist/slices/onboarding/state.js +9 -11
  365. package/dist/slices/onboarding/template.js +8 -6
  366. package/dist/slices/outputs/add.js +3 -2
  367. package/dist/slices/outputs/service.js +2 -2
  368. package/dist/slices/patch-notes/library.js +4 -3
  369. package/dist/slices/play-drafts/convert.js +4 -0
  370. package/dist/slices/play-drafts/readiness.js +3 -3
  371. package/dist/slices/play-drafts/review-inputs.js +9 -3
  372. package/dist/slices/play-drafts/review.js +5 -4
  373. package/dist/slices/play-drafts/schema.js +4 -0
  374. package/dist/slices/play-drafts/service.js +17 -7
  375. package/dist/slices/project-templates/from-project.js +9 -2
  376. package/dist/slices/project-templates/next-chapter.js +2 -1
  377. package/dist/slices/project-templates/provider-defaults.js +22 -0
  378. package/dist/slices/project-templates/repo.js +6 -1
  379. package/dist/slices/project-templates/setup-sections.js +26 -0
  380. package/dist/slices/project-templates/setup.js +14 -1
  381. package/dist/slices/project-templates/stand-ins.js +22 -0
  382. package/dist/slices/rebuild/activity.js +2 -0
  383. package/dist/slices/rebuild/admission-repo.js +3 -2
  384. package/dist/slices/rebuild/narration-history.js +4 -5
  385. package/dist/slices/rebuild/narration-retry.js +2 -1
  386. package/dist/slices/rebuild/preview-details.js +32 -14
  387. package/dist/slices/rebuild/preview-plan.js +3 -8
  388. package/dist/slices/rebuild/recipe-build.js +8 -3
  389. package/dist/slices/rebuild/recipe-describe.js +3 -3
  390. package/dist/slices/rebuild/recipe-digest.js +58 -0
  391. package/dist/slices/rebuild/recipe-input-schema.js +10 -0
  392. package/dist/slices/rebuild/recipe-keywords.js +71 -0
  393. package/dist/slices/rebuild/recipe-legacy.js +5 -1
  394. package/dist/slices/rebuild/recipe-model.js +4 -0
  395. package/dist/slices/rebuild/recipe-narration-text.js +2 -1
  396. package/dist/slices/rebuild/recipe-preparation.js +4 -4
  397. package/dist/slices/rebuild/recipe-reference.js +8 -4
  398. package/dist/slices/rebuild/recipe-reviews.js +27 -7
  399. package/dist/slices/rebuild/recipe-save.js +8 -5
  400. package/dist/slices/rebuild/recipe-scenes.js +40 -11
  401. package/dist/slices/rebuild/recipe-shorts.js +8 -8
  402. package/dist/slices/rebuild/recipe-social.js +46 -0
  403. package/dist/slices/rebuild/recipe-text.js +64 -20
  404. package/dist/slices/rebuild/recipe-validation.js +102 -31
  405. package/dist/slices/rebuild/recipe-visual.js +55 -16
  406. package/dist/slices/rebuild/recipe-voices.js +3 -2
  407. package/dist/slices/rebuild/recipe-work.js +19 -7
  408. package/dist/slices/rebuild/recipe-youtube.js +4 -3
  409. package/dist/slices/rebuild/recovery-selection.js +3 -1
  410. package/dist/slices/rebuild/recovery.js +9 -8
  411. package/dist/slices/rebuild/remake-outdated.js +5 -5
  412. package/dist/slices/rebuild/repo.js +4 -3
  413. package/dist/slices/rebuild/review-promise.js +25 -0
  414. package/dist/slices/rebuild/review-redo.js +3 -2
  415. package/dist/slices/rebuild/runtime-admission.js +4 -3
  416. package/dist/slices/rebuild/runtime-agent-review.js +11 -5
  417. package/dist/slices/rebuild/runtime-animate.js +10 -9
  418. package/dist/slices/rebuild/runtime-article.js +7 -5
  419. package/dist/slices/rebuild/runtime-checkpoints.js +5 -4
  420. package/dist/slices/rebuild/runtime-document.js +11 -13
  421. package/dist/slices/rebuild/runtime-export-bed.js +8 -12
  422. package/dist/slices/rebuild/runtime-export-edit.js +8 -16
  423. package/dist/slices/rebuild/runtime-export-inputs.js +12 -11
  424. package/dist/slices/rebuild/runtime-export-short.js +9 -5
  425. package/dist/slices/rebuild/runtime-export.js +38 -15
  426. package/dist/slices/rebuild/runtime-figure-card.js +2 -1
  427. package/dist/slices/rebuild/runtime-image.js +8 -12
  428. package/dist/slices/rebuild/runtime-instructions.js +2 -0
  429. package/dist/slices/rebuild/runtime-keywords.js +59 -0
  430. package/dist/slices/rebuild/runtime-lines.js +2 -11
  431. package/dist/slices/rebuild/runtime-local.js +17 -22
  432. package/dist/slices/rebuild/runtime-narration-publication.js +2 -5
  433. package/dist/slices/rebuild/runtime-narration-reuse.js +9 -13
  434. package/dist/slices/rebuild/runtime-narration-text.js +13 -17
  435. package/dist/slices/rebuild/runtime-pictures.js +2 -4
  436. package/dist/slices/rebuild/runtime-piece-label.js +10 -6
  437. package/dist/slices/rebuild/runtime-plan.js +31 -5
  438. package/dist/slices/rebuild/runtime-provider.js +67 -25
  439. package/dist/slices/rebuild/runtime-publication.js +10 -9
  440. package/dist/slices/rebuild/runtime-review.js +39 -33
  441. package/dist/slices/rebuild/runtime-run.js +4 -1
  442. package/dist/slices/rebuild/runtime-shorts.js +31 -50
  443. package/dist/slices/rebuild/runtime-store.js +20 -10
  444. package/dist/slices/rebuild/runtime-subtitles.js +28 -25
  445. package/dist/slices/rebuild/runtime-voices.js +10 -16
  446. package/dist/slices/rebuild/runtime-youtube.js +14 -31
  447. package/dist/slices/rebuild/service-readiness.js +11 -3
  448. package/dist/slices/rebuild/transition-repo.js +6 -5
  449. package/dist/slices/rebuild/work-records.js +6 -0
  450. package/dist/slices/reruns/cascade.js +1 -2
  451. package/dist/slices/reruns/index.js +6 -9
  452. package/dist/slices/research/synthesis.js +3 -2
  453. package/dist/slices/reviews/external-model.js +4 -1
  454. package/dist/slices/reviews/external-repo.js +2 -1
  455. package/dist/slices/reviews/external-rows.js +2 -3
  456. package/dist/slices/reviews/holds.js +5 -4
  457. package/dist/slices/reviews/model.js +32 -11
  458. package/dist/slices/reviews/repo.js +2 -1
  459. package/dist/slices/reviews/rules.js +4 -3
  460. package/dist/slices/reviews/verdict.js +2 -1
  461. package/dist/slices/reviews/view.js +5 -2
  462. package/dist/slices/revisions/downloads.js +4 -5
  463. package/dist/slices/revisions/image-plan.js +1 -1
  464. package/dist/slices/revisions/mutation-assets.js +9 -5
  465. package/dist/slices/revisions/mutation-cues.js +2 -5
  466. package/dist/slices/revisions/mutations.js +3 -3
  467. package/dist/slices/revisions/repo.js +3 -1
  468. package/dist/slices/revisions/schema.js +1 -0
  469. package/dist/slices/revisions/view.js +20 -0
  470. package/dist/slices/run-cost/limits.js +5 -2
  471. package/dist/slices/run-cost/meter.js +12 -5
  472. package/dist/slices/run-cost/panel.js +8 -74
  473. package/dist/slices/run-cost/plan-readings.js +127 -0
  474. package/dist/slices/run-cost/plan-use.js +169 -0
  475. package/dist/slices/run-cost/pricing.js +3 -3
  476. package/dist/slices/run-cost/week.js +32 -4
  477. package/dist/slices/schedules/agenda.js +18 -7
  478. package/dist/slices/schedules/by-date.js +42 -0
  479. package/dist/slices/schedules/calendar.js +5 -0
  480. package/dist/slices/schedules/design-agenda.js +36 -0
  481. package/dist/slices/schedules/design-check.js +41 -0
  482. package/dist/slices/schedules/design-run.js +126 -0
  483. package/dist/slices/schedules/next-run.js +62 -0
  484. package/dist/slices/schedules/prepare.js +18 -2
  485. package/dist/slices/schedules/repo.js +30 -21
  486. package/dist/slices/schedules/rescore.js +35 -0
  487. package/dist/slices/schedules/scheduler.js +13 -3
  488. package/dist/slices/schedules/schema.js +57 -3
  489. package/dist/slices/schedules/score.js +107 -0
  490. package/dist/slices/schedules/service.js +57 -24
  491. package/dist/slices/schedules/topic-list.js +15 -0
  492. package/dist/slices/schedules/topic-scores.js +104 -0
  493. package/dist/slices/schedules/topics.js +53 -41
  494. package/dist/slices/settings/cli-paths.js +4 -6
  495. package/dist/slices/settings/first-run.js +8 -43
  496. package/dist/slices/settings/health.js +30 -15
  497. package/dist/slices/settings/key-test.js +1 -1
  498. package/dist/slices/settings/model-reach.js +3 -17
  499. package/dist/slices/settings/model.js +14 -2
  500. package/dist/slices/settings/playback.js +34 -23
  501. package/dist/slices/settings/probe-read.js +16 -0
  502. package/dist/slices/settings/repo.js +33 -0
  503. package/dist/slices/settings/tutorial.js +2 -2
  504. package/dist/slices/settings/voices.js +4 -12
  505. package/dist/slices/shorts/keep.js +2 -1
  506. package/dist/slices/shorts/pick.js +6 -18
  507. package/dist/slices/shorts/prompts.js +4 -14
  508. package/dist/slices/shorts/render.js +6 -2
  509. package/dist/slices/social/channel.js +44 -0
  510. package/dist/slices/social/defaults.js +17 -0
  511. package/dist/slices/social/due.js +36 -0
  512. package/dist/slices/social/extension.js +18 -0
  513. package/dist/slices/social/fit.js +115 -0
  514. package/dist/slices/social/limits.js +186 -0
  515. package/dist/slices/social/links.js +21 -0
  516. package/dist/slices/social/media.js +132 -0
  517. package/dist/slices/social/model.js +75 -0
  518. package/dist/slices/social/notice.js +19 -0
  519. package/dist/slices/social/pack.js +176 -0
  520. package/dist/slices/social/post-prompt.js +56 -0
  521. package/dist/slices/social/queue.js +31 -0
  522. package/dist/slices/social/repo.js +133 -0
  523. package/dist/slices/social/reshape.js +97 -0
  524. package/dist/slices/social/rules.js +5 -0
  525. package/dist/slices/social/schema.js +70 -0
  526. package/dist/slices/social/serve.js +51 -0
  527. package/dist/slices/social/service.js +129 -0
  528. package/dist/slices/social/settings.js +21 -0
  529. package/dist/slices/social/sources.js +114 -0
  530. package/dist/slices/social/state.js +110 -0
  531. package/dist/slices/social/text.js +149 -0
  532. package/dist/slices/storage/arrange.js +3 -1
  533. package/dist/slices/storage/assets.js +8 -10
  534. package/dist/slices/storage/backup-designs.js +74 -0
  535. package/dist/slices/storage/backup-export.js +8 -3
  536. package/dist/slices/storage/backup-format.js +10 -0
  537. package/dist/slices/storage/backup-import.js +22 -4
  538. package/dist/slices/storage/delete-project.js +6 -5
  539. package/dist/slices/storage/files-location.js +6 -8
  540. package/dist/slices/storage/layout.js +13 -2
  541. package/dist/slices/storage/model.js +3 -0
  542. package/dist/slices/storage/portable.js +17 -12
  543. package/dist/slices/storage/schema.js +2 -0
  544. package/dist/slices/storage/staging-refs.js +2 -1
  545. package/dist/slices/storage/staging.js +6 -9
  546. package/dist/slices/storage/trim.js +26 -9
  547. package/dist/slices/studio/calendar.js +7 -2
  548. package/dist/slices/studio/disclosure.js +4 -4
  549. package/dist/slices/studio/model.js +1 -1
  550. package/dist/slices/studio/pack.js +9 -8
  551. package/dist/slices/studio/pick.js +2 -11
  552. package/dist/slices/studio/plan.js +7 -16
  553. package/dist/slices/studio/queue.js +3 -14
  554. package/dist/slices/studio/releases.js +26 -0
  555. package/dist/slices/studio/settings.js +20 -57
  556. package/dist/slices/studio/videos.js +35 -4
  557. package/dist/slices/style-preview/render.js +37 -16
  558. package/dist/slices/style-preview/schema.js +14 -1
  559. package/dist/slices/style-preview/service.js +2 -1
  560. package/dist/slices/style-preview/settings.js +33 -5
  561. package/dist/slices/subtitles/captions.js +1 -1
  562. package/dist/slices/telemetry/collector-client.js +2 -4
  563. package/dist/slices/telemetry/flush.js +2 -4
  564. package/dist/slices/telemetry/model.js +0 -7
  565. package/dist/slices/telemetry/record.js +10 -3
  566. package/dist/slices/template-studio/anatomy-view.js +161 -0
  567. package/dist/slices/template-studio/anatomy.js +73 -0
  568. package/dist/slices/template-studio/bakeoff-make.js +225 -0
  569. package/dist/slices/template-studio/bakeoff-repo.js +83 -0
  570. package/dist/slices/template-studio/bakeoff.js +333 -0
  571. package/dist/slices/template-studio/budget.js +106 -0
  572. package/dist/slices/template-studio/cards.js +78 -0
  573. package/dist/slices/template-studio/checks.js +322 -0
  574. package/dist/slices/template-studio/document-sample.js +56 -0
  575. package/dist/slices/template-studio/edit.js +15 -0
  576. package/dist/slices/template-studio/for-all.js +161 -0
  577. package/dist/slices/template-studio/free-video.js +31 -0
  578. package/dist/slices/template-studio/free.js +176 -0
  579. package/dist/slices/template-studio/gate.js +40 -0
  580. package/dist/slices/template-studio/hidden.js +20 -0
  581. package/dist/slices/template-studio/jobs.js +79 -0
  582. package/dist/slices/template-studio/loudness.js +111 -0
  583. package/dist/slices/template-studio/make.js +40 -0
  584. package/dist/slices/template-studio/model.js +58 -0
  585. package/dist/slices/template-studio/pack-import.js +253 -0
  586. package/dist/slices/template-studio/pack-samples.js +60 -0
  587. package/dist/slices/template-studio/pack.js +207 -0
  588. package/dist/slices/template-studio/paid-view.js +66 -0
  589. package/dist/slices/template-studio/paid.js +355 -0
  590. package/dist/slices/template-studio/quote.js +155 -0
  591. package/dist/slices/template-studio/ready.js +104 -0
  592. package/dist/slices/template-studio/repo.js +134 -0
  593. package/dist/slices/template-studio/reviews-path.js +58 -0
  594. package/dist/slices/template-studio/runner.js +84 -0
  595. package/dist/slices/template-studio/save.js +236 -0
  596. package/dist/slices/template-studio/say-it-as.js +248 -0
  597. package/dist/slices/template-studio/schedule-gate.js +34 -0
  598. package/dist/slices/template-studio/schedule-price.js +32 -0
  599. package/dist/slices/template-studio/schedule-sample.js +91 -0
  600. package/dist/slices/template-studio/schema.js +243 -0
  601. package/dist/slices/template-studio/scope.js +124 -0
  602. package/dist/slices/template-studio/sections.js +176 -0
  603. package/dist/slices/template-studio/service.js +175 -0
  604. package/dist/slices/template-studio/status.js +191 -0
  605. package/dist/slices/template-studio/topic.js +223 -0
  606. package/dist/slices/thumbnail/by-llm.js +1 -1
  607. package/dist/slices/trash/designs.js +76 -0
  608. package/dist/slices/trash/model.js +13 -4
  609. package/dist/slices/trash/service.js +52 -2
  610. package/dist/slices/tutorials/library.js +3 -2
  611. package/dist/slices/uploads/repo.js +37 -1
  612. package/dist/slices/uploads/rules.js +3 -2
  613. package/dist/slices/video/ass-text.js +17 -0
  614. package/dist/slices/video/audio-export.js +2 -64
  615. package/dist/slices/video/edit-list.js +2 -2
  616. package/dist/slices/video/edit-settings.js +1 -1
  617. package/dist/slices/video/encoding.js +169 -0
  618. package/dist/slices/video/ffmpeg.js +23 -21
  619. package/dist/slices/video/figure-card.js +1 -15
  620. package/dist/slices/video/plan.js +2 -1
  621. package/dist/slices/video/slideshow.js +43 -18
  622. package/dist/slices/voices/attribution.js +3 -2
  623. package/dist/slices/voices/model.js +9 -8
  624. package/dist/slices/voices/palette.js +0 -3
  625. package/dist/slices/voices/script.js +2 -1
  626. package/dist/slices/youtube/answer.js +4 -16
  627. package/dist/slices/youtube/edits-repo.js +3 -12
  628. package/dist/tutorials/AI-CLIs.md +25 -25
  629. package/dist/tutorials/Agents-MCP.md +34 -33
  630. package/dist/tutorials/Assistant.md +42 -0
  631. package/dist/tutorials/Backups.md +7 -7
  632. package/dist/tutorials/Calendar.md +17 -25
  633. package/dist/tutorials/Cast-Library.md +19 -19
  634. package/dist/tutorials/Channels.md +42 -35
  635. package/dist/tutorials/Costs-and-Run-Cost.md +38 -40
  636. package/dist/tutorials/Create-Article.md +114 -0
  637. package/dist/tutorials/Create-Extras.md +112 -0
  638. package/dist/tutorials/Create-Images.md +165 -0
  639. package/dist/tutorials/Create-Narration.md +178 -0
  640. package/dist/tutorials/Create-Overview.md +244 -0
  641. package/dist/tutorials/Create-Video-and-Style.md +144 -0
  642. package/dist/tutorials/Docker.md +3 -3
  643. package/dist/tutorials/Document-Themes.md +32 -32
  644. package/dist/tutorials/Editing-a-Project.md +94 -94
  645. package/dist/tutorials/FAQ.md +18 -18
  646. package/dist/tutorials/First-Launch-and-Welcome.md +50 -64
  647. package/dist/tutorials/Home-and-Projects.md +115 -71
  648. package/dist/tutorials/Home.md +33 -33
  649. package/dist/tutorials/Install.md +14 -13
  650. package/dist/tutorials/Intros-and-Outros.md +33 -34
  651. package/dist/tutorials/Keyboard-Shortcuts-and-Command-Palette.md +62 -58
  652. package/dist/tutorials/Keywords-Slopify-Fills.md +87 -0
  653. package/dist/tutorials/Models.md +53 -21
  654. package/dist/tutorials/Multiple-Voices.md +41 -40
  655. package/dist/tutorials/Narration-Aliases-and-Glossary.md +14 -14
  656. package/dist/tutorials/Notifications.md +27 -17
  657. package/dist/tutorials/Other-Languages.md +15 -15
  658. package/dist/tutorials/PDF-Documents.md +38 -29
  659. package/dist/tutorials/Posting-to-Social-Sites.md +121 -0
  660. package/dist/tutorials/Project-Page.md +118 -120
  661. package/dist/tutorials/Prompts-and-Templates.md +84 -0
  662. package/dist/tutorials/Prompts.md +48 -44
  663. package/dist/tutorials/Providers-and-Keys.md +105 -98
  664. package/dist/tutorials/Publishing-to-YouTube.md +31 -31
  665. package/dist/tutorials/Recovery-and-Retries.md +31 -31
  666. package/dist/tutorials/Remote-Access.md +63 -0
  667. package/dist/tutorials/Reviews-and-Checkpoints.md +98 -90
  668. package/dist/tutorials/Schedules.md +46 -27
  669. package/dist/tutorials/Settings-Reference.md +194 -174
  670. package/dist/tutorials/Shorts.md +34 -33
  671. package/dist/tutorials/Start-at-Login.md +3 -3
  672. package/dist/tutorials/Studio-Extension.md +22 -24
  673. package/dist/tutorials/Template-Studio.md +128 -0
  674. package/dist/tutorials/Templates.md +51 -77
  675. package/dist/tutorials/Trash.md +4 -4
  676. package/dist/tutorials/Troubleshooting.md +44 -44
  677. package/dist/tutorials/Uninstalling-and-Moving.md +5 -5
  678. package/dist/tutorials/Updating-and-Patch-Notes.md +18 -18
  679. package/dist/tutorials/Video-Editing.md +34 -34
  680. package/dist/tutorials/Where-Your-Files-Live.md +10 -10
  681. package/dist/tutorials/YouTube-Description.md +26 -26
  682. package/dist/tutorials/Your-First-Short.md +35 -35
  683. package/dist/tutorials/_Sidebar.md +19 -14
  684. package/dist/updater/work-in-progress.js +42 -12
  685. package/dist/web/assets/index-BNftKQrA.css +1 -0
  686. package/dist/web/assets/index-Cpa58woP.js +459 -0
  687. package/dist/web/assets/pdf-BKh8f7R6.js +56 -0
  688. package/dist/web/assets/pdf.worker.min-BmVo14Nb.mjs +28 -0
  689. package/dist/web/assets/pdf.worker.min-D7i8o3wR.js +1 -0
  690. package/dist/web/index.html +2 -2
  691. package/package.json +6 -2
  692. package/dist/slices/article/provided-entries.js +0 -66
  693. package/dist/slices/article/run.js +0 -145
  694. package/dist/slices/images/run.js +0 -234
  695. package/dist/slices/narration/legacy-plan.js +0 -58
  696. package/dist/slices/narration/run.js +0 -270
  697. package/dist/slices/rebuild/runtime-actions.js +0 -90
  698. package/dist/slices/research/run.js +0 -224
  699. package/dist/slices/subtitles/prepare.js +0 -194
  700. package/dist/slices/subtitles/transcript.js +0 -34
  701. package/dist/slices/thumbnail/run.js +0 -219
  702. package/dist/slices/video/audio-inputs.js +0 -33
  703. package/dist/slices/video/reuse-audio.js +0 -62
  704. package/dist/slices/video/run.js +0 -78
  705. package/dist/slices/video/write-export.js +0 -158
  706. package/dist/slices/video/write-subtitles.js +0 -59
  707. package/dist/tutorials/Library-Overview.md +0 -76
  708. package/dist/tutorials/Play-Images.md +0 -161
  709. package/dist/tutorials/Play-Narration.md +0 -167
  710. package/dist/tutorials/Play-Outputs.md +0 -109
  711. package/dist/tutorials/Play-Overview.md +0 -227
  712. package/dist/tutorials/Play-Title-and-Article.md +0 -136
  713. package/dist/tutorials/Play-Video-and-Style.md +0 -143
  714. package/dist/web/assets/index-BadsoORk.css +0 -1
  715. package/dist/web/assets/index-D8LqNsCl.js +0 -326
  716. package/dist/web/assets/pdf-T7MCwjIv.js +0 -54
  717. package/dist/web/assets/pdf.worker.min-Dswkl-cV.mjs +0 -29
  718. package/dist/web/assets/pdf.worker.min-zC6nfbxG.js +0 -1
@@ -0,0 +1,176 @@
1
+ import { errorText } from "../../kernel/errors.js";
2
+ import { StylePreviewError } from "../style-preview/render.js";
3
+ import { normalizeStylePreview, stylePreviewHash } from "../style-preview/settings.js";
4
+ import { documentHash, documentThemeOfTemplate } from "./document-sample.js";
5
+ import { videoSampleRequest } from "./free-video.js";
6
+ import { loudnessGoalOf, loudnessHash } from "./loudness.js";
7
+ // The samples the studio makes on this computer, free: the 30-second video, the loudness before
8
+ // and after, and the PDF. Each is kept by the hash of what it is made from, so a setting changed
9
+ // back, or the same setup in another template, shows at once.
10
+ export const freeKinds = ["video", "loudness", "document"];
11
+ const press = "press Make sample";
12
+ export function createFreeSamples(deps) {
13
+ const failures = new Map();
14
+ const making = new Set();
15
+ const keyOf = (kind, hash) => `${kind}:${hash}`;
16
+ const videoHash = (document) => stylePreviewHash(normalizeStylePreview(videoSampleRequest(document)));
17
+ const loudnessHashOf = (document) => {
18
+ const goal = loudnessGoalOf(document, deps.loudnessDefault());
19
+ return goal === undefined ? undefined : loudnessHash(goal);
20
+ };
21
+ const documentHashOf = (document) => documentHash(documentThemeOfTemplate(document));
22
+ const attempt = async (kind, hash, work, failure) => {
23
+ const key = keyOf(kind, hash);
24
+ making.add(key);
25
+ failures.delete(key);
26
+ try {
27
+ await work();
28
+ }
29
+ catch (error) {
30
+ failures.set(key, failure(error));
31
+ }
32
+ finally {
33
+ making.delete(key);
34
+ }
35
+ };
36
+ const pending = (job, kind, hash, what) => {
37
+ const key = keyOf(kind, hash);
38
+ const failed = failures.get(key);
39
+ if (failed !== undefined)
40
+ return { state: "needs-fix", sentence: failed, url: null };
41
+ if (making.has(key) || job.running)
42
+ return { state: "making", sentence: `Making the ${what} on this computer.`, url: null };
43
+ if (job.queued)
44
+ return {
45
+ state: "waiting",
46
+ sentence: `The ${what} waits for another template's samples to finish.`,
47
+ url: null,
48
+ };
49
+ return { state: "stale", sentence: `No ${what} for this version yet: ${press}.`, url: null };
50
+ };
51
+ return {
52
+ loudnessHashOf,
53
+ documentHashOf,
54
+ make: async (document, signal) => {
55
+ const { form } = document;
56
+ if (form.sources.video !== "off" && deps.stylePreviews !== undefined) {
57
+ const previews = deps.stylePreviews;
58
+ await attempt("video", videoHash(document), async () => {
59
+ await previews.render(videoSampleRequest(document));
60
+ }, videoFailure);
61
+ }
62
+ if (signal.aborted)
63
+ return;
64
+ const goal = loudnessGoalOf(document, deps.loudnessDefault());
65
+ if (goal !== undefined && deps.loudness !== undefined) {
66
+ const samples = deps.loudness;
67
+ await attempt("loudness", loudnessHash(goal), () => samples.make(goal, signal), (error) => ffmpegFailure("loudness before and after", error));
68
+ }
69
+ if (signal.aborted)
70
+ return;
71
+ if (form.sources.document === "generate" && deps.documents !== undefined) {
72
+ const documents = deps.documents;
73
+ const theme = documentThemeOfTemplate(document);
74
+ await attempt("document", documentHash(theme), () => documents.make(theme), (error) => `The PDF sample couldn't be made: ${errorText(error)} Change the theme under All PDF settings, then ${press}.`);
75
+ }
76
+ },
77
+ view: (templateId, document, job) => {
78
+ const { form } = document;
79
+ const base = `/api/template-studio/${encodeURIComponent(templateId)}`;
80
+ const unavailable = (what) => ({
81
+ state: "needs-fix",
82
+ sentence: `The ${what} can't be made because this Slopify started without ffmpeg. Install ffmpeg, or use the Docker image, then restart Slopify and ${press}.`,
83
+ url: null,
84
+ });
85
+ let video;
86
+ if (form.sources.video === "off")
87
+ video = { state: "off", sentence: "The video is off.", url: null };
88
+ else if (deps.stylePreviews === undefined)
89
+ video = unavailable("video sample");
90
+ else {
91
+ const hash = videoHash(document);
92
+ const saved = deps.stylePreviews.file(hash);
93
+ video =
94
+ saved === undefined
95
+ ? pending(job, "video", hash, "30-second video")
96
+ : {
97
+ state: "current",
98
+ sentence: "30 seconds in your frame, captions, Look and picture timing, on Slopify's sample pictures and narration.",
99
+ url: `/api/style-preview/${hash}.mp4?v=${String(saved.version)}`,
100
+ };
101
+ }
102
+ const lHash = loudnessHashOf(document);
103
+ let loudness;
104
+ if (lHash === undefined)
105
+ loudness = {
106
+ state: "off",
107
+ sentence: "Level the volume is off: the narration plays as the voice gives it.",
108
+ url: null,
109
+ beforeUrl: null,
110
+ beforeLufs: null,
111
+ afterLufs: null,
112
+ targetLufs: null,
113
+ ceiling: null,
114
+ };
115
+ else if (deps.loudness === undefined)
116
+ loudness = {
117
+ ...unavailable("loudness before and after"),
118
+ beforeUrl: null,
119
+ beforeLufs: null,
120
+ afterLufs: null,
121
+ targetLufs: null,
122
+ ceiling: null,
123
+ };
124
+ else {
125
+ const reading = deps.loudness.reading(lHash);
126
+ const shown = reading === undefined
127
+ ? pending(job, "loudness", lHash, "loudness before and after")
128
+ : undefined;
129
+ loudness = {
130
+ ...(shown ?? {
131
+ state: "current",
132
+ sentence: "How your narration will be levelled, shown on Slopify's sample narration until your voice's own sample is made.",
133
+ url: `${base}/loudness/after.mp3?v=${lHash.slice(0, 12)}`,
134
+ }),
135
+ beforeUrl: `${base}/loudness/before.mp3`,
136
+ beforeLufs: reading?.before ?? null,
137
+ afterLufs: reading?.after ?? null,
138
+ targetLufs: reading?.target ?? null,
139
+ ceiling: reading?.ceiling ?? null,
140
+ };
141
+ }
142
+ let pdf;
143
+ if (form.sources.document !== "generate")
144
+ pdf = { state: "off", sentence: "The PDF is off.", url: null };
145
+ else if (deps.documents === undefined)
146
+ pdf = unavailable("PDF sample");
147
+ else {
148
+ const hash = documentHashOf(document);
149
+ pdf =
150
+ deps.documents.file(hash) === undefined
151
+ ? pending(job, "document", hash, "PDF sample")
152
+ : {
153
+ state: "current",
154
+ sentence: "Slopify's sample article laid out in your theme.",
155
+ url: `${base}/document.pdf?v=${hash.slice(0, 12)}`,
156
+ };
157
+ }
158
+ return { video, loudness, document: pdf };
159
+ },
160
+ };
161
+ }
162
+ function videoFailure(error) {
163
+ if (error instanceof StylePreviewError) {
164
+ if (error.reason === "font-missing")
165
+ return `The video sample couldn't be made because the caption font is no longer on this computer. Choose another Caption font in Video and style, then ${press}.`;
166
+ if (error.reason === "ffmpeg-missing")
167
+ return `The video sample couldn't be made because ffmpeg wasn't found. Install ffmpeg, or use the Docker image, then ${press}.`;
168
+ }
169
+ return ffmpegFailure("video sample", error);
170
+ }
171
+ function ffmpegFailure(what, error) {
172
+ const message = errorText(error);
173
+ if (/\bENOENT\b/.test(message) || message.startsWith("Slopify could not start ffmpeg"))
174
+ return `The ${what} couldn't be made because ffmpeg wasn't found. Install ffmpeg, or use the Docker image, then ${press}.`;
175
+ return `The ${what} couldn't be made because ffmpeg stopped with an error. ${press[0]?.toUpperCase()}${press.slice(1)} again; if it fails again, use Download diagnostics in Settings and report it.`;
176
+ }
@@ -0,0 +1,40 @@
1
+ function runnable(byVersion, version, seen = new Set()) {
2
+ const gate = byVersion.get(version);
3
+ if (gate === undefined || seen.has(version))
4
+ return false;
5
+ if (gate.state !== "carried")
6
+ return true;
7
+ const from = gate.carriedFrom;
8
+ return from !== null && from < version && runnable(byVersion, from, new Set([...seen, version]));
9
+ }
10
+ // The newest version at or below the head that was legacy, marked ready, or carried from a
11
+ // runnable one. Undefined when none was ever checked. What a pack carries.
12
+ export function checkedVersion(gates, head) {
13
+ const byVersion = new Map(gates.map((gate) => [gate.version, gate]));
14
+ return [...byVersion.keys()]
15
+ .filter((version) => version <= head && runnable(byVersion, version))
16
+ .sort((a, b) => b - a)[0];
17
+ }
18
+ // A template is gated from the first time any of its versions is marked ready in the studio.
19
+ // Before that it follows its newest version as 3.x did, so an edit applies to the next run.
20
+ export function isGated(gates) {
21
+ return gates.some((gate) => gate.state === "ready");
22
+ }
23
+ // The version a schedule runs: the newest one while the template isn't gated, else the newest
24
+ // checked one (a newer unchecked version waits for Mark ready).
25
+ export function runnableVersion(gates, head) {
26
+ return isGated(gates) ? checkedVersion(gates, head) : head;
27
+ }
28
+ export function gateOf(gates, version) {
29
+ return gates.find((gate) => gate.version === version)?.state ?? "unchecked";
30
+ }
31
+ // A version Slopify itself wrote (a model switch, a restore under a new name) keeps the gate of
32
+ // the version it came from, so a schedule is never stopped by a change its user did not make.
33
+ export function carryGate(gates, parent, next) {
34
+ if (next <= parent)
35
+ return undefined;
36
+ const byVersion = new Map(gates.map((gate) => [gate.version, gate]));
37
+ return runnable(byVersion, parent)
38
+ ? { version: next, state: "carried", carriedFrom: parent }
39
+ : undefined;
40
+ }
@@ -0,0 +1,20 @@
1
+ import { transact } from "../../kernel/db/tx.js";
2
+ import { deleteProject } from "../storage/delete-project.js";
3
+ // Removes one of the studio's hidden projects (a sample made again on its own project, a
4
+ // bake-off copy) for good. What it was charged today stays counted against the sample budget:
5
+ // its priced calls are kept in `template_studio_spend` first, so removing a project never
6
+ // frees budget it already spent.
7
+ export function removeHiddenProject(deps, projectId) {
8
+ return transact(deps.db, () => {
9
+ deps.db
10
+ .prepare(`INSERT INTO template_studio_spend (project_id,cost,created_at)
11
+ SELECT project_id,cost,created_at FROM provider_usage
12
+ WHERE project_id=? AND on_plan=0 AND cost > 0`)
13
+ .run(projectId);
14
+ const removed = deleteProject(deps, projectId);
15
+ // A project that stays (running, a file the OS keeps) keeps its own rows: not counted twice.
16
+ if (!removed.ok)
17
+ deps.db.prepare("DELETE FROM template_studio_spend WHERE project_id=?").run(projectId);
18
+ return removed;
19
+ });
20
+ }
@@ -0,0 +1,79 @@
1
+ import { z } from "zod";
2
+ import { transact } from "../../kernel/db/tx.js";
3
+ import { supersedeQueuedBakeoff } from "./bakeoff-repo.js";
4
+ import { sampleJobKinds } from "./model.js";
5
+ const jobRow = z.object({
6
+ templateId: z.string(),
7
+ templateVersion: z.number().int().positive(),
8
+ ackHigh: z.number(),
9
+ kind: z.enum(sampleJobKinds),
10
+ requestedAt: z.string(),
11
+ });
12
+ const columns = "template_id AS templateId,template_version AS templateVersion,ack_high AS ackHigh,kind,requested_at AS requestedAt";
13
+ // Queues a template's sample job. A newer request takes the place of the one still queued; the
14
+ // running one is left to finish and this one waits behind it. A free-only request never takes
15
+ // the place of a queued paid one for the same version, which already makes the free samples,
16
+ // nor of a queued bake-off.
17
+ export function enqueueJob(db, job) {
18
+ transact(db, () => {
19
+ const queued = queuedJob(db, job.templateId);
20
+ if (queued !== undefined &&
21
+ job.kind === "free" &&
22
+ queued.kind !== "free" &&
23
+ (queued.templateVersion === job.templateVersion || queued.kind === "bakeoff"))
24
+ return;
25
+ // A bake-off still waiting was priced on the version a paid change replaces: it is
26
+ // dropped, saying so, and nothing was spent on it.
27
+ if (queued?.kind === "bakeoff" && job.kind !== "bakeoff")
28
+ supersedeQueuedBakeoff(db, job.templateId, job.requestedAt);
29
+ db.prepare(`INSERT INTO template_sample_jobs (template_id,template_version,ack_high,kind,requested_at,state)
30
+ VALUES (?,?,?,?,?,'queued')
31
+ ON CONFLICT(template_id,state) DO UPDATE SET template_version=excluded.template_version,
32
+ ack_high=excluded.ack_high,kind=excluded.kind,requested_at=excluded.requested_at`).run(job.templateId, job.templateVersion, job.ackHigh, job.kind, job.requestedAt);
33
+ });
34
+ }
35
+ export function queuedJob(db, templateId) {
36
+ const row = db
37
+ .prepare(`SELECT ${columns} FROM template_sample_jobs WHERE template_id=? AND state='queued'`)
38
+ .get(templateId);
39
+ return row === undefined ? undefined : jobRow.parse(row);
40
+ }
41
+ export function runningJob(db) {
42
+ const row = db
43
+ .prepare(`SELECT ${columns} FROM template_sample_jobs WHERE state='running' LIMIT 1`)
44
+ .get();
45
+ return row === undefined ? undefined : jobRow.parse(row);
46
+ }
47
+ // The next job to make: the oldest queued one, only while no other is running anywhere, so one
48
+ // sample is made at a time across every template.
49
+ export function claimNextJob(db) {
50
+ return transact(db, () => {
51
+ if (runningJob(db) !== undefined)
52
+ return undefined;
53
+ const row = db
54
+ .prepare(`SELECT ${columns} FROM template_sample_jobs WHERE state='queued' ORDER BY requested_at,template_id LIMIT 1`)
55
+ .get();
56
+ if (row === undefined)
57
+ return undefined;
58
+ const job = jobRow.parse(row);
59
+ db.prepare("UPDATE template_sample_jobs SET state='running' WHERE template_id=? AND state='queued'").run(job.templateId);
60
+ return job;
61
+ });
62
+ }
63
+ // The running job of a template now continues the project its paid work started on: queued
64
+ // again by a restart, it is a Save of the same version, never a new topic's fresh project.
65
+ export function continueJobAsSave(db, templateId) {
66
+ db.prepare("UPDATE template_sample_jobs SET kind='save' WHERE template_id=? AND state='running' AND kind IN ('topic','full-script')").run(templateId);
67
+ }
68
+ export function finishJob(db, templateId) {
69
+ db.prepare("DELETE FROM template_sample_jobs WHERE template_id=? AND state='running'").run(templateId);
70
+ }
71
+ // At start: a job that was running when Slopify stopped is queued again, unless a newer one
72
+ // already waits for its template, which then takes its place.
73
+ export function recoverJobs(db) {
74
+ transact(db, () => {
75
+ db.prepare(`DELETE FROM template_sample_jobs WHERE state='running' AND template_id IN
76
+ (SELECT template_id FROM template_sample_jobs WHERE state='queued')`).run();
77
+ db.prepare("UPDATE template_sample_jobs SET state='queued' WHERE state='running'").run();
78
+ });
79
+ }
@@ -0,0 +1,111 @@
1
+ import { createHash, randomUUID } from "node:crypto";
2
+ import { mkdirSync, readFileSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
3
+ import { join } from "node:path";
4
+ import { z } from "zod";
5
+ import { levelFile } from "../loudness/loudnorm.js";
6
+ import { encodeHeadroom, videoTruePeak, } from "../loudness/model.js";
7
+ import { runFfmpeg } from "../video/ffmpeg.js";
8
+ // Voice's loudness before and after: Slopify's sample narration as it came, and the same
9
+ // levelled to the template's video target, as the run's master would. Phase 3's own voice sample
10
+ // takes the bundled narration's place.
11
+ // The target a template's video is levelled to, or undefined while Level the volume is off.
12
+ export function loudnessGoalOf(document, fallback) {
13
+ const chosen = document.form.loudness;
14
+ if (!(chosen?.enabled ?? fallback.enabled))
15
+ return undefined;
16
+ return {
17
+ lufs: chosen?.videoLufs ?? fallback.videoLufs,
18
+ truePeak: videoTruePeak - encodeHeadroom,
19
+ };
20
+ }
21
+ export function loudnessHash(goal) {
22
+ return createHash("sha256")
23
+ .update(JSON.stringify({ version: 2, lufs: goal.lufs, truePeak: goal.truePeak }))
24
+ .digest("hex");
25
+ }
26
+ const readingSchema = z.object({
27
+ before: z.number(),
28
+ after: z.number(),
29
+ target: z.number(),
30
+ ceiling: z.number(),
31
+ });
32
+ const hashPattern = /^[a-f0-9]{64}$/;
33
+ export function createLoudnessSamples(deps) {
34
+ const pathOf = (hash, extension) => join(deps.dir, `${hash}.${extension}`);
35
+ const file = (hash) => {
36
+ if (!hashPattern.test(hash))
37
+ return undefined;
38
+ try {
39
+ const stats = statSync(pathOf(hash, "mp3"));
40
+ return stats.isFile() && stats.size > 0
41
+ ? { path: pathOf(hash, "mp3"), bytes: stats.size }
42
+ : undefined;
43
+ }
44
+ catch {
45
+ return undefined;
46
+ }
47
+ };
48
+ return {
49
+ source: deps.source,
50
+ file,
51
+ reading: (hash) => {
52
+ if (file(hash) === undefined)
53
+ return undefined;
54
+ try {
55
+ return readingSchema.parse(JSON.parse(readFileSync(pathOf(hash, "json"), "utf8")));
56
+ }
57
+ catch {
58
+ return undefined;
59
+ }
60
+ },
61
+ make: async (goal, signal) => {
62
+ const hash = loudnessHash(goal);
63
+ if (file(hash) !== undefined)
64
+ return;
65
+ mkdirSync(deps.dir, { recursive: true, mode: 0o700 });
66
+ const work = join(deps.dir, `${hash}.${randomUUID()}`);
67
+ const priority = deps.priority?.();
68
+ const run = { bin: deps.ffmpeg, log: deps.log, signal, priority };
69
+ try {
70
+ const levelled = await levelFile(run, deps.source, `${work}.wav`, goal, {
71
+ sampleRate: 48_000,
72
+ channels: 1,
73
+ });
74
+ await runFfmpeg({
75
+ bin: deps.ffmpeg,
76
+ args: [
77
+ "-hide_banner",
78
+ "-nostdin",
79
+ "-loglevel",
80
+ "error",
81
+ "-y",
82
+ "-i",
83
+ `${work}.wav`,
84
+ "-c:a",
85
+ "libmp3lame",
86
+ "-b:a",
87
+ "128k",
88
+ "-f",
89
+ "mp3",
90
+ `${work}.mp3`,
91
+ ],
92
+ signal,
93
+ log: deps.log,
94
+ priority,
95
+ onProgress: () => undefined,
96
+ });
97
+ writeFileSync(pathOf(hash, "json"), JSON.stringify({
98
+ before: Math.round(levelled.before.integrated * 10) / 10,
99
+ after: Math.round(levelled.after.integrated * 10) / 10,
100
+ target: goal.lufs,
101
+ ceiling: goal.truePeak,
102
+ }), { mode: 0o600 });
103
+ renameSync(`${work}.mp3`, pathOf(hash, "mp3"));
104
+ }
105
+ finally {
106
+ rmSync(`${work}.wav`, { force: true });
107
+ rmSync(`${work}.mp3`, { force: true });
108
+ }
109
+ },
110
+ };
111
+ }
@@ -0,0 +1,40 @@
1
+ import { templateById } from "../project-templates/repo.js";
2
+ import { finishJob } from "./jobs.js";
3
+ import { priceScheduledRun } from "./schedule-price.js";
4
+ import { priceKey, templateSchedules } from "./service.js";
5
+ // What one sample job makes: the free samples of its version, its paid sample unless it asked
6
+ // for the free ones only, then the price of each schedule's run, the studio told after each so its page fills in as they land. A template deleted since
7
+ // the job was queued makes nothing.
8
+ export function sampleMaker(deps) {
9
+ return async (job, signal) => {
10
+ const template = templateById(deps.db, job.templateId, job.templateVersion);
11
+ if (template === undefined)
12
+ return;
13
+ // A bake-off makes only its copies: the template's own samples are current already.
14
+ if (job.kind === "bakeoff") {
15
+ await deps.bakeoff?.(job, signal);
16
+ deps.changed(template.id);
17
+ return;
18
+ }
19
+ await deps.free.make(template.document, signal);
20
+ deps.changed(template.id);
21
+ if (job.kind !== "free" && deps.paid !== undefined && !signal.aborted) {
22
+ await deps.paid(job, signal);
23
+ // Made: a quit while the schedules are priced below never queues it again.
24
+ finishJob(deps.db, job.templateId);
25
+ deps.changed(template.id);
26
+ }
27
+ const head = templateById(deps.db, job.templateId);
28
+ if (head === undefined)
29
+ return;
30
+ for (const schedule of templateSchedules(deps.db, head.id)) {
31
+ if (signal.aborted)
32
+ return;
33
+ const key = priceKey(schedule, head);
34
+ if (deps.prices.get(key) !== undefined)
35
+ continue;
36
+ deps.prices.set(key, await priceScheduledRun(deps.review, head, schedule));
37
+ deps.changed(head.id);
38
+ }
39
+ };
40
+ }
@@ -0,0 +1,58 @@
1
+ import { setupSectionNames } from "../project-templates/setup-sections.js";
2
+ // Template studio (4.0, "Edit template" on screen): a template is set up once, section by
3
+ // section, with live samples on a hidden project, then approved for its schedules. Not to be
4
+ // confused with `slices/studio`, which is the YouTube Studio pack and its extension.
5
+ // In pipeline order: the studio's rail shows them so.
6
+ export const templateSections = [
7
+ "subject",
8
+ "script",
9
+ "voice",
10
+ "pictures",
11
+ "video",
12
+ "thumbnail",
13
+ "shorts",
14
+ "document",
15
+ "reviews",
16
+ "upload",
17
+ "schedule",
18
+ ];
19
+ // Each section's place in the one list of setup sections Create, Edit template and a project's
20
+ // settings share. The ids stay as they were, so every saved address still opens its section.
21
+ export const setupSectionOf = {
22
+ subject: "topic",
23
+ script: "article",
24
+ voice: "narration",
25
+ pictures: "images",
26
+ video: "video",
27
+ thumbnail: "thumbnail",
28
+ shorts: "shorts",
29
+ document: "pdf",
30
+ reviews: "checks",
31
+ upload: "youtube",
32
+ schedule: "schedule",
33
+ };
34
+ export const sectionLabel = Object.fromEntries(templateSections.map((id) => [id, setupSectionNames[setupSectionOf[id]]]));
35
+ // What a section's sample is: made for the current version, being made, queued behind another,
36
+ // failed with a fix, made for an older version, switched off, or provided by the user at run time.
37
+ export const sectionStates = [
38
+ "current",
39
+ "making",
40
+ "waiting",
41
+ "needs-fix",
42
+ "stale",
43
+ "off",
44
+ "provided",
45
+ ];
46
+ // A version's gate. A version without one was never checked in the studio.
47
+ export const gateStates = ["legacy", "ready", "carried"];
48
+ export const sampleVersionStates = [
49
+ "queued",
50
+ "making",
51
+ "done",
52
+ "failed",
53
+ "skipped",
54
+ "held",
55
+ ];
56
+ export const sampleJobKinds = ["save", "topic", "full-script", "bakeoff", "free"];
57
+ // The topic every template's sample is made about until the user picks another.
58
+ export const fallbackSampleTopic = "The history of the lighthouse";