@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
@@ -25,8 +25,13 @@ export function reviewBinding(value) {
25
25
  attachmentIdentity: value.attachmentIdentity,
26
26
  });
27
27
  }
28
- export function resolveReviewInputs(deps, view, font) {
29
- const fresh = readDraft(deps, view.draft.id);
28
+ export function resolveReviewInputs(deps, view, font,
29
+ // A view no draft row holds (the template studio prices a schedule's run on one): it is its
30
+ // own latest version and has no uploads.
31
+ unsaved = false) {
32
+ const fresh = unsaved
33
+ ? { ok: true, value: view }
34
+ : readDraft(deps, view.draft.id);
30
35
  if (!fresh.ok)
31
36
  return fresh;
32
37
  if (fresh.value.draft.version !== view.draft.version ||
@@ -103,6 +108,7 @@ export function resolveReviewInputs(deps, view, font) {
103
108
  draft: { ...draft, values },
104
109
  staged,
105
110
  requiredSlots: basePicked.requiredSlots,
111
+ keywordUses: basePicked.keywordUses,
106
112
  });
107
113
  const accepted = admitted.ok ? admitted.draft : draft;
108
114
  const issues = [
@@ -155,7 +161,7 @@ export function resolveReviewInputs(deps, view, font) {
155
161
  : run.draft.sources[stage] !== "generate")
156
162
  fields.push({
157
163
  field: `checkpoints.${stage}`,
158
- message: "Checkpoints can only go before a step Slopify generates, or before export. Remove this checkpoint or turn that step on.",
164
+ message: "A pause can only go before a step Slopify makes, or before the video. Untick this pause or turn that step on.",
159
165
  });
160
166
  if (fields.length)
161
167
  return reviewRefusal(view, fields);
@@ -8,11 +8,12 @@ import { resolveReviewInputs, reviewBinding, reviewRefusal } from "./review-inpu
8
8
  import { draftViewSchema, playReviewSchema } from "./schema.js";
9
9
  import { readDraft } from "./service.js";
10
10
  export { resolveReviewInputs } from "./review-inputs.js";
11
- export async function resolvePlayReview(deps, view) {
11
+ export async function resolvePlayReview(deps, view, options = {}) {
12
+ const unsaved = options.unsaved === true;
12
13
  const parsed = draftViewSchema.safeParse(view);
13
14
  if (!parsed.success)
14
15
  return { ok: false, reason: "invalid-edit", currentVersion: null, fields: [] };
15
- const before = resolveReviewInputs(deps, parsed.data, null);
16
+ const before = resolveReviewInputs(deps, parsed.data, null, unsaved);
16
17
  if (!before.ok)
17
18
  return before;
18
19
  let font = null;
@@ -32,7 +33,7 @@ export async function resolvePlayReview(deps, view) {
32
33
  ]);
33
34
  }
34
35
  }
35
- const after = resolveReviewInputs(deps, parsed.data, font);
36
+ const after = resolveReviewInputs(deps, parsed.data, font, unsaved);
36
37
  if (!after.ok)
37
38
  return after;
38
39
  const fields = [];
@@ -55,7 +56,7 @@ export async function resolvePlayReview(deps, view) {
55
56
  // without the font: `before` had none yet, and a Before Video checkpoint covers the render
56
57
  // that burns the captions in, so comparing it with `after` always differed and refused every
57
58
  // such review.
58
- const unchanged = resolveReviewInputs(deps, parsed.data, null);
59
+ const unchanged = resolveReviewInputs(deps, parsed.data, null, unsaved);
59
60
  if (!unchanged.ok)
60
61
  return unchanged;
61
62
  return reviewBinding(before.value) === reviewBinding(unchanged.value)
@@ -10,6 +10,7 @@ import { documentSettingsSchema } from "../document/theme-schema.js";
10
10
  import { librarySnapshotSchema } from "../library/snapshot.js";
11
11
  import { chunkModes } from "../narration/chunk.js";
12
12
  import { reviewers, reviewModes, reviewStages } from "../reviews/model.js";
13
+ import { socialSettingsSchema } from "../social/schema.js";
13
14
  import { subtitleModes, subtitlePositions } from "../subtitles/model.js";
14
15
  import { ambientBedSources } from "../video/ambient-bed.js";
15
16
  import { voicesSettingsSchema } from "../voices/model.js";
@@ -94,6 +95,9 @@ export const playDraftFormSchema = z
94
95
  levelSentences: z.boolean().optional(),
95
96
  // Absent on drafts and templates saved before the YouTube description: off, built-in prompt.
96
97
  youtubeDescription: z.boolean().optional(),
98
+ // Which other sites the project posts to and what each gets (`slices/social`), as the run
99
+ // stores it. Absent on drafts and templates saved before posting: nowhere.
100
+ social: socialSettingsSchema.optional(),
97
101
  showFigures: z.boolean().optional(),
98
102
  descriptionPrompt: text.optional(),
99
103
  // The project language (`kernel/ports/languages.ts`). Absent on drafts and templates saved
@@ -1,6 +1,7 @@
1
1
  import { statSync } from "node:fs";
2
2
  import { z } from "zod";
3
3
  import { transact } from "../../kernel/db/tx.js";
4
+ import { render } from "../admission/substitute.js";
4
5
  import { stagingPath } from "../storage/layout.js";
5
6
  import { stagedFileById } from "../storage/repo.js";
6
7
  import { releaseStagedFile } from "../storage/staging-refs.js";
@@ -114,14 +115,23 @@ export function readDraft(deps, id) {
114
115
  }),
115
116
  };
116
117
  }
118
+ // A draft is listed by its title as the run would have it, with the topic typed in ("Lore:
119
+ // Cleopatra", not "Lore: {{Topic}}"); a keyword still empty stays in braces.
117
120
  export function listDrafts(deps) {
118
- return draftRows(deps.db).map((row) => ({
119
- id: row.id,
120
- title: row.title,
121
- version: row.version,
122
- updatedAt: row.updated_at,
123
- readable: documentOf(row) !== null,
124
- }));
121
+ return draftRows(deps.db).map((row) => {
122
+ const document = documentOf(row);
123
+ return {
124
+ id: row.id,
125
+ title: document === null ? row.title : filledTitle(document),
126
+ version: row.version,
127
+ updatedAt: row.updated_at,
128
+ readable: document !== null,
129
+ };
130
+ });
131
+ }
132
+ function filledTitle(document) {
133
+ const { title, values } = document.form;
134
+ return render(title, Object.fromEntries(Object.entries(values).filter(([, value]) => value.trim() !== "")));
125
135
  }
126
136
  export function createDraft(deps, input) {
127
137
  const parsed = createDraftInputSchema.safeParse(input);
@@ -11,10 +11,13 @@ import { requestHash } from "../play-drafts/repo.js";
11
11
  import { reviewSettingsForm } from "../reviews/model.js";
12
12
  import { currentRevisionId, revisionById } from "../revisions/repo.js";
13
13
  import { shortsExtrasForm } from "../shorts/model.js";
14
+ import { socialPlatforms } from "../social/model.js";
15
+ import { socialSettingsSchema } from "../social/schema.js";
14
16
  import { ambientBedFormOf } from "../video/ambient-bed.js";
15
17
  import { usesScriptPrompt } from "../voices/model.js";
16
18
  import { templateNameMax } from "./schema.js";
17
19
  import { createTemplate, readTemplate } from "./service.js";
20
+ import { withoutSampleStandIns } from "./stand-ins.js";
18
21
  export const projectTemplateCreateSchema = z
19
22
  .object({
20
23
  id: z.uuid(),
@@ -88,6 +91,9 @@ export function documentFromProject(deps, revision) {
88
91
  addPrompt(usesScriptPrompt(config) ? "script" : "article", config.articlePrompt, "article");
89
92
  addPrompt("narration", config.narrationPrompt, "narration");
90
93
  addPrompt("description", config.descriptionPrompt, "description");
94
+ for (const platform of socialPlatforms)
95
+ if (config.social?.[platform]?.text === "prompt")
96
+ addPrompt("post", config.social[platform]?.prompt, `social.${platform}`);
91
97
  for (const [stage, picked] of Object.entries(config.reviews?.stages ?? {}))
92
98
  addPrompt("review", picked.prompt, `review.${stage}`);
93
99
  const definitions = revision.content.imageOrder.flatMap((key) => {
@@ -163,7 +169,7 @@ export function documentFromProject(deps, revision) {
163
169
  return {
164
170
  schemaVersion: 1,
165
171
  librarySnapshot: { prompts, entries },
166
- form: {
172
+ form: withoutSampleStandIns({
167
173
  title: config.title,
168
174
  format: config.format,
169
175
  sources: config.sources,
@@ -191,6 +197,7 @@ export function documentFromProject(deps, revision) {
191
197
  ...(config.thumbnailCount === 3 ? { thumbnailCount: 3 } : {}),
192
198
  ...(config.narrationPrompt === undefined ? {} : { narrationPrompt: config.narrationPrompt }),
193
199
  ...(config.youtubeDescription === true ? { youtubeDescription: true } : {}),
200
+ ...(config.social === undefined ? {} : { social: socialSettingsSchema.parse(config.social) }),
194
201
  ...(config.language === undefined ? {} : { language: config.language }),
195
202
  ...(config.descriptionPrompt === undefined
196
203
  ? {}
@@ -263,7 +270,7 @@ export function documentFromProject(deps, revision) {
263
270
  motionStyle: config.motionStyle,
264
271
  values: config.values,
265
272
  provided,
266
- },
273
+ }),
267
274
  section: "content",
268
275
  variants: [],
269
276
  // The length a project that scales its images planned for, so the template plans the same.
@@ -1,5 +1,6 @@
1
1
  import { z } from "zod";
2
2
  import { transact } from "../../kernel/db/tx.js";
3
+ import { createRows } from "../../kernel/ports/settings-places.js";
3
4
  import { projectById } from "../admission/repo.js";
4
5
  import { projectChannelId } from "../channels/repo.js";
5
6
  import { draftRow } from "../play-drafts/repo.js";
@@ -55,7 +56,7 @@ export function makeNextChapter(deps, input) {
55
56
  return {
56
57
  ok: false,
57
58
  reason: "not-an-audiobook",
58
- message: "Only an audiobook has chapters. Pick Audiobook under Speakers (Play → Narration) to start a book.",
59
+ message: `Only an audiobook has chapters. Pick Audiobook as the Format under Speakers (${createRows.narration}) to start a book.`,
59
60
  };
60
61
  const book = nextBook(revision.config.title, voices.book);
61
62
  const document = documentFromProject(deps, revision);
@@ -0,0 +1,22 @@
1
+ // A template nobody picked a writer or an image service in runs on this computer's defaults,
2
+ // kind by kind, by the same rule Create applies to a draft (web `play/draft-state.ts`
3
+ // withProviderDefaults): a writer nobody picked takes the default writer even where the images
4
+ // were picked, and the other way round; a choice someone made is never changed. Every place a
5
+ // template runs or is checked reads it through here (a draft made from it, a schedule's run, a
6
+ // sample, Edit template's checks and editors), so none of them can disagree about whether it
7
+ // can start.
8
+ export function withProviderDefaults(document, defaults) {
9
+ const { form } = document;
10
+ const llm = form.llm.provider === "" ? defaults.llm : undefined;
11
+ const images = form.images.provider === "" ? defaults.images : undefined;
12
+ if (llm === undefined && images === undefined)
13
+ return document;
14
+ return {
15
+ ...document,
16
+ form: {
17
+ ...form,
18
+ ...(llm === undefined ? {} : { llm: { ...llm } }),
19
+ ...(images === undefined ? {} : { images: { ...images } }),
20
+ },
21
+ };
22
+ }
@@ -1,5 +1,6 @@
1
1
  import { z } from "zod";
2
2
  import { projectTemplateSchema } from "./schema.js";
3
+ import { withoutSampleStandIns } from "./stand-ins.js";
3
4
  // A template in the trash (`deleted_at` set, Settings → Trash) is invisible to every read here.
4
5
  const select = `SELECT t.id,r.version,r.name,t.created_at AS createdAt,r.created_at AS updatedAt,r.document_json AS document FROM project_templates t JOIN project_template_revisions r ON r.template_id=t.id AND t.deleted_at IS NULL`;
5
6
  const templateSummarySchema = z
@@ -20,7 +21,11 @@ export function templateById(db, id, version) {
20
21
  return undefined;
21
22
  if (typeof row.document !== "string")
22
23
  throw new Error("Template document is missing");
23
- return projectTemplateSchema.parse({ ...row, document: JSON.parse(row.document) });
24
+ const template = projectTemplateSchema.parse({ ...row, document: JSON.parse(row.document) });
25
+ // A template made from a sample before stand-ins were cleared reads as one that asks for the
26
+ // person's own providers.
27
+ const form = withoutSampleStandIns(template.document.form);
28
+ return { ...template, document: { ...template.document, form } };
24
29
  }
25
30
  export function templateSummaries(db) {
26
31
  return db
@@ -0,0 +1,26 @@
1
+ // One setup, three editors: Create, Edit template and a project's Edit settings show the same
2
+ // setup, so they name its sections alike and list them in this order, the order a run makes
3
+ // them. Each editor keeps its own data model and its own ids; only the names and the order
4
+ // come from here. Browser-safe: the web app imports it too.
5
+ export const setupSectionNames = {
6
+ topic: "Title and keywords",
7
+ article: "Article",
8
+ narration: "Narration",
9
+ images: "Images",
10
+ video: "Video and style",
11
+ thumbnail: "Thumbnail",
12
+ shorts: "Shorts",
13
+ pdf: "PDF",
14
+ checks: "Pauses and checks",
15
+ youtube: "YouTube description and posts",
16
+ schedule: "Schedule",
17
+ };
18
+ // In run order.
19
+ export const setupSections = Object.keys(setupSectionNames);
20
+ // Create and a project's Edit settings keep the optional outputs together in one section, where
21
+ // Edit template gives each its own: the thumbnail, the shorts, the PDF and the YouTube
22
+ // description and posts.
23
+ export const extrasName = "Extras";
24
+ // Last in Create and a project's Edit settings: the channel the video is for. A template has no
25
+ // section for it; its schedules and Create pick the channel.
26
+ export const channelName = "Channel";
@@ -1,6 +1,9 @@
1
1
  import { templateChannelId } from "../channels/repo.js";
2
2
  import { snapshotEntry, snapshotPrompt } from "../library/snapshot.js";
3
+ import { readProviderDefaults } from "../settings/first-run.js";
4
+ import { socialPlatforms } from "../social/model.js";
3
5
  import { templateDocument } from "./one-off.js";
6
+ import { withProviderDefaults } from "./provider-defaults.js";
4
7
  export function templateSetup(deps, input) {
5
8
  const prompts = [];
6
9
  const entries = [];
@@ -25,6 +28,13 @@ export function templateSetup(deps, input) {
25
28
  kind: "image",
26
29
  name: input.form.reference?.source === "prompt" ? input.form.reference.prompt : "",
27
30
  },
31
+ ...socialPlatforms.map((platform) => {
32
+ const choice = input.form.social?.[platform];
33
+ return {
34
+ kind: "post",
35
+ name: choice?.text === "prompt" ? (choice.prompt ?? "") : "",
36
+ };
37
+ }),
28
38
  ];
29
39
  for (const choice of choices) {
30
40
  if (choice.name === "")
@@ -50,7 +60,10 @@ export function templateSetup(deps, input) {
50
60
  value: { ...document, fontUpload: null, librarySnapshot: { prompts, entries } },
51
61
  };
52
62
  }
53
- export function freshTemplateDraft(deps, document, source) {
63
+ // A draft made from a template, for Create or a schedule's run. A template nobody picked a writer
64
+ // or image service in gets this computer's defaults, as Edit template's checks expect.
65
+ export function freshTemplateDraft(deps, saved, source) {
66
+ const document = withProviderDefaults(saved, readProviderDefaults(deps.db));
54
67
  const provided = document.form.provided;
55
68
  const fresh = (file) => ({
56
69
  attachmentId: deps.uuid(),
@@ -0,0 +1,22 @@
1
+ import { isSampleStandIn } from "../settings/model.js";
2
+ // A template made from a bundled sample asks for the person's own providers: the samples'
3
+ // stand-ins can't run anything new, so their choices are left blank, the same as a template
4
+ // nobody has picked a provider in (Play then offers the providers this computer has).
5
+ export function withoutSampleStandIns(form) {
6
+ const blankVoice = { provider: "", model: "", voice: "" };
7
+ const voices = form.voices;
8
+ return {
9
+ ...form,
10
+ llm: isSampleStandIn(form.llm.provider) ? { provider: "", model: "" } : form.llm,
11
+ audio: isSampleStandIn(form.audio.provider) ? { ...form.audio, ...blankVoice } : form.audio,
12
+ images: isSampleStandIn(form.images.provider) ? { provider: "", model: "" } : form.images,
13
+ ...(voices === undefined
14
+ ? {}
15
+ : {
16
+ voices: {
17
+ ...voices,
18
+ speakers: voices.speakers.map((speaker) => isSampleStandIn(speaker.voice.provider) ? { ...speaker, voice: blankVoice } : speaker),
19
+ },
20
+ }),
21
+ };
22
+ }
@@ -50,6 +50,8 @@ export function videoActivity(db, projectId) {
50
50
  return { label: "picking the shorts" };
51
51
  if (running("youtube:description"))
52
52
  return { label: "writing the YouTube description" };
53
+ if (rows.some((row) => row.key.startsWith("social:post:") && row.state === "running"))
54
+ return { label: "writing the posts for other sites" };
53
55
  if (running("subtitles:timing"))
54
56
  return percent("timing the captions", running("subtitles:timing"));
55
57
  if (running("subtitles:cues") || running("subtitles:files"))
@@ -1,4 +1,5 @@
1
1
  import { transact } from "../../kernel/db/tx.js";
2
+ import { internalError } from "../../kernel/errors.js";
2
3
  import { setProjectPaused } from "../admission/repo.js";
3
4
  import { requestHash as hash } from "../revisions/mutation-request.js";
4
5
  import { currentRevisionId } from "../revisions/repo.js";
@@ -92,14 +93,14 @@ export function admitPreview(deps, input) {
92
93
  continue;
93
94
  }
94
95
  if (existing?.state === "running")
95
- throw new Error("Slopify hit an internal error (a step is already running for a different version of the project). Try again; if it happens again, use Download diagnostics in Settings and report it.");
96
+ throw new Error(internalError("a step is already running for a different version of the project"));
96
97
  deps.db
97
98
  .prepare("DELETE FROM revision_work_reservations WHERE revision_id=? AND work_key=?")
98
99
  .run(view.revision.id, recipe.key);
99
100
  const key = reservationKey(recipe, view);
100
101
  const fingerprint = snapshot.anchors[key];
101
102
  if (fingerprint === undefined)
102
- throw new Error("Slopify hit an internal error (a step has no saved starting point). Try again; if it happens again, use Download diagnostics in Settings and report it.");
103
+ throw new Error(internalError("a step has no saved starting point"));
103
104
  const work = insertInvocation(deps, view, recipe, catalogue, { key, fingerprint }, false, view.revision.id, admissionId);
104
105
  workIds.push(work.workId);
105
106
  }
@@ -1,5 +1,6 @@
1
1
  import { statSync } from "node:fs";
2
2
  import { z } from "zod";
3
+ import { assetPathOrUndefined } from "../revisions/mutation-assets.js";
3
4
  import { stagePieceSchema } from "../revisions/schema.js";
4
5
  import { outputPath } from "../storage/layout.js";
5
6
  export function retainedNarrationPieces(deps, projectId) {
@@ -32,11 +33,9 @@ export function retainedNarrationPieces(deps, projectId) {
32
33
  }
33
34
  export function referencedAssetsAvailable(deps, projectId, ids) {
34
35
  return ids.filter((id) => {
35
- const row = deps.db
36
- .prepare("SELECT path FROM project_assets WHERE project_id=? AND id=?")
37
- .get(projectId, id);
38
- return (row !== undefined &&
39
- statSync(outputPath(deps.paths, projectId, z.string().parse(row.path)), {
36
+ const path = assetPathOrUndefined(deps, projectId, id);
37
+ return (path !== undefined &&
38
+ statSync(outputPath(deps.paths, projectId, path), {
40
39
  throwIfNoEntry: false,
41
40
  })?.isFile() === true);
42
41
  });
@@ -1,6 +1,7 @@
1
1
  import { createHash } from "node:crypto";
2
2
  import { z } from "zod";
3
3
  import { transact } from "../../kernel/db/tx.js";
4
+ import { errorText } from "../../kernel/errors.js";
4
5
  import { currentRevisionId } from "../revisions/repo.js";
5
6
  import { recoverProject } from "./recovery.js";
6
7
  // How many times one narration chunk is recorded again by itself. A voice that garbles a
@@ -71,7 +72,7 @@ export function createNarrationRetries() {
71
72
  .catch((error) => {
72
73
  deps.log.write("error", "narration.retry", {
73
74
  projectId: retry.projectId,
74
- detail: error instanceof Error ? error.message : String(error),
75
+ detail: errorText(error),
75
76
  });
76
77
  settle(deps.db, retry, "failed", "internal error", deps.clock.now().toISOString());
77
78
  })
@@ -7,6 +7,7 @@ import { loudnessLabel } from "../loudness/model.js";
7
7
  import { reviewModeLabels, reviewModeOf, reviewStageLabels, reviewStages, } from "../reviews/model.js";
8
8
  import { getRevisionView } from "../revisions/view.js";
9
9
  import { musicVolumeOf, shortsSpeedOf } from "../shorts/model.js";
10
+ import { platformLabels, socialPlatforms } from "../social/model.js";
10
11
  import { ambientBedLabels } from "../video/ambient-bed.js";
11
12
  import { videoEditOf, videoEditRows } from "../video/edit-settings.js";
12
13
  export function previewDetails(deps, view, allRecipes, selected) {
@@ -71,20 +72,22 @@ export function previewDetails(deps, view, allRecipes, selected) {
71
72
  if (input.kind === "llm") {
72
73
  const peers = allRecipes.filter((one) => one.stage === row.stage && one.input.kind === "llm");
73
74
  const category = input.preparation !== undefined
74
- ? "Narration Preparation"
75
+ ? "Narration preparation"
75
76
  : row.key.startsWith("entry:intro")
76
77
  ? "Intro text"
77
78
  : row.key.startsWith("entry:outro")
78
79
  ? "Outro text"
79
- : row.stage === "article"
80
- ? "Article"
81
- : row.stage === "research"
82
- ? "Research"
83
- : row.key.startsWith("shorts:")
84
- ? "Short image prompts"
85
- : row.key === "images:scenes"
86
- ? "Image scenes"
87
- : "Thumbnail prompt";
80
+ : row.key === "article:digest"
81
+ ? "Keyword digest"
82
+ : row.stage === "article"
83
+ ? "Article"
84
+ : row.stage === "research"
85
+ ? "Research"
86
+ : row.key.startsWith("shorts:")
87
+ ? "Short image prompts"
88
+ : row.key === "images:scenes"
89
+ ? "Image scenes"
90
+ : "Thumbnail prompt";
88
91
  return [
89
92
  {
90
93
  key: row.key,
@@ -151,9 +154,9 @@ function inputChanges(parent, view) {
151
154
  }
152
155
  add("Language", languageInfo(before.language).name, languageInfo(after.language).name);
153
156
  add("Narration voice", before.audio?.voice, after.audio?.voice);
154
- add("Narration Preparation", before.narrationPrompt, after.narrationPrompt);
157
+ add("Narration preparation", before.narrationPrompt, after.narrationPrompt);
155
158
  add("Narration chunking", before.chunking, after.chunking);
156
- add("Narration aliases", before.audio?.useNarrationAliases === true ? aliasLines(before.narrationAliases) : "Off", after.audio?.useNarrationAliases === true ? aliasLines(after.narrationAliases) : "Off");
159
+ add("Pronunciation list", before.audio?.useNarrationAliases === true ? aliasLines(before.narrationAliases) : "Off", after.audio?.useNarrationAliases === true ? aliasLines(after.narrationAliases) : "Off");
157
160
  const described = (audio) => audio?.describeFigures !== true ? "Off" : audio.skipCode === true ? "On, code left out" : "On";
158
161
  add("Describe tables and figures", described(before.audio), described(after.audio));
159
162
  add("Show tables and figures on screen", before.showFigures === true ? "On" : "Off", after.showFigures === true ? "On" : "Off");
@@ -165,6 +168,7 @@ function inputChanges(parent, view) {
165
168
  add("Level the volume", before.loudness === undefined ? "Off" : loudnessSummary(before.loudness), after.loudness === undefined ? "Off" : loudnessSummary(after.loudness));
166
169
  add("YouTube description", before.youtubeDescription === true ? "On" : "Off", after.youtubeDescription === true ? "On" : "Off");
167
170
  add("Description prompt", before.descriptionPrompt, after.descriptionPrompt);
171
+ add("Posts", postsSummary(before.social), postsSummary(after.social));
168
172
  add("Shorts", before.shorts?.enabled === true ? "On" : "Off", after.shorts?.enabled === true ? "On" : "Off");
169
173
  add("Number of shorts", before.shorts?.count, after.shorts?.count);
170
174
  add("Short length (seconds)", before.shorts === undefined
@@ -211,11 +215,11 @@ function inputChanges(parent, view) {
211
215
  add(label, value, editAfter.get(label));
212
216
  add("Intro", before.intro, after.intro);
213
217
  add("Outro", before.outro, after.outro);
214
- add("Subtitle settings", before.subtitles, after.subtitles);
218
+ add("Caption settings", before.subtitles, after.subtitles);
215
219
  const themeBefore = documentThemeLabel(before.document);
216
220
  const themeAfter = documentThemeLabel(after.document);
217
221
  // A Library theme saved again under the same name still changes the document.
218
- add("Document theme", themeBefore, themeBefore === themeAfter &&
222
+ add("PDF look", themeBefore, themeBefore === themeAfter &&
219
223
  JSON.stringify(before.document?.custom?.values) !==
220
224
  JSON.stringify(after.document?.custom?.values)
221
225
  ? `${themeAfter} (updated settings)`
@@ -261,3 +265,17 @@ function aliasLines(aliases) {
261
265
  .map((alias) => `${alias.written} → ${alias.spoken}${alias.wholeWord ? "" : " (inside words too)"}${alias.caseSensitive ? " (match case)" : ""}`)
262
266
  .join("\n");
263
267
  }
268
+ // The sites a version posts to, each with where its words come from: "X (post prompt), Bluesky
269
+ // (summary)"; "Off" for none.
270
+ function postsSummary(social) {
271
+ const sites = socialPlatforms.flatMap((platform) => {
272
+ const choice = social?.[platform];
273
+ if (choice === undefined)
274
+ return [];
275
+ const source = choice.text === "prompt"
276
+ ? `post prompt${choice.prompt?.trim() ? ` ${choice.prompt.trim()}` : ""}`
277
+ : choice.text;
278
+ return [`${platformLabels[platform]} (${source})`];
279
+ });
280
+ return sites.length === 0 ? "Off" : sites.join(", ");
281
+ }
@@ -2,6 +2,7 @@ import { z } from "zod";
2
2
  import { catalogueSchema } from "../../catalog/schema.js";
3
3
  import { stageKinds } from "../../kernel/pipeline.js";
4
4
  import { estimateRequests } from "../estimate/index.js";
5
+ import { assetPathOrUndefined } from "../revisions/mutation-assets.js";
5
6
  import { requestHash } from "../revisions/mutation-request.js";
6
7
  import { previewDetails } from "./preview-details.js";
7
8
  import { hasSubmittedRequest, requiresNewSubmission, retainedPreviewPlan, } from "./preview-retained.js";
@@ -99,23 +100,17 @@ export function planPreview(deps, view, catalogue, selection, id) {
99
100
  });
100
101
  for (const row of view.pieces)
101
102
  if (row.selected && selected.has(row.key) && row.assetId !== null) {
102
- const asset = deps.db
103
- .prepare("SELECT path FROM project_assets WHERE id=? AND project_id=?")
104
- .get(row.assetId, view.revision.projectId);
105
103
  relevantAssets.set(row.assetId, {
106
104
  id: row.assetId,
107
- path: String(asset?.path ?? ""),
105
+ path: assetPathOrUndefined(deps, view.revision.projectId, row.assetId) ?? "",
108
106
  available: row.available,
109
107
  });
110
108
  }
111
109
  for (const recipe of recipes)
112
110
  if (recipe.input.kind === "provided" && recipe.input.assetId !== null) {
113
- const asset = deps.db
114
- .prepare("SELECT path FROM project_assets WHERE id=? AND project_id=?")
115
- .get(recipe.input.assetId, view.revision.projectId);
116
111
  relevantAssets.set(recipe.input.assetId, {
117
112
  id: recipe.input.assetId,
118
- path: String(asset?.path ?? ""),
113
+ path: assetPathOrUndefined(deps, view.revision.projectId, recipe.input.assetId) ?? "",
119
114
  available: !recipe.unresolved,
120
115
  });
121
116
  }
@@ -4,6 +4,7 @@ import { audioRecipes } from "./recipe-audio.js";
4
4
  import { documentRecipes } from "./recipe-document.js";
5
5
  import { editPlan } from "./recipe-edit.js";
6
6
  import { exportRecipes } from "./recipe-exports.js";
7
+ import { fillPrompt } from "./recipe-keywords.js";
7
8
  import { linePlan } from "./recipe-lines.js";
8
9
  import { masterPlan } from "./recipe-loudness.js";
9
10
  import { resourceIdentity } from "./recipe-model.js";
@@ -11,6 +12,7 @@ import { imageReference, referenceRecipe } from "./recipe-reference.js";
11
12
  import { withReviews } from "./recipe-reviews.js";
12
13
  import { imageScenes, thumbnailScenes } from "./recipe-scenes.js";
13
14
  import { shortsRecipes } from "./recipe-shorts.js";
15
+ import { socialRecipes } from "./recipe-social.js";
14
16
  import { unsoftenedTimelines } from "./recipe-softening.js";
15
17
  import { textRecipes } from "./recipe-text.js";
16
18
  import { thumbnailRecipes, visualAssets, visualRecipes } from "./recipe-visual.js";
@@ -50,8 +52,10 @@ export function buildRecipes(context) {
50
52
  return built;
51
53
  }
52
54
  const descriptionKey = "youtube:description";
53
- function buildEach(context) {
54
- const text = textRecipes(context);
55
+ function buildEach(plain) {
56
+ const text = textRecipes(plain);
57
+ // Every later step fills its prompts' keywords from what the text steps write.
58
+ const context = { ...plain, keywords: text.keywords };
55
59
  const audio = audioRecipes(context, text);
56
60
  const exports = exportRecipes(context, audio, () => unsoftenedTimelines(context, text));
57
61
  const captions = exports.find((value) => value.key === "subtitles:files");
@@ -72,11 +76,12 @@ function buildEach(context) {
72
76
  ...audio.recipes,
73
77
  ...exports,
74
78
  ...youtube,
79
+ ...socialRecipes(context, text),
75
80
  ...(reference === undefined ? [] : [reference]),
76
81
  ...shortsRecipes(context, exports, drawnFrom, audio.cards ?? [], masterPlan(context, audio.levels, "video"), appearance),
77
82
  ...thumbnail,
78
83
  ...documentRecipes(context, text, thumbnail),
79
- ...visualAssets(context, visualRecipes(context.config, context.content, audio.mediaFingerprint, captions?.fingerprint ?? null, (images) => editPlan(context, exports, youtube, images, audio.cards ?? []), drawnFrom, timing === undefined ? null : resourceIdentity(context, timing), withLines(masterPlan(context, audio.levels, "video"), linePlan(context, timing)), scenes, appearance)),
84
+ ...visualAssets(context, visualRecipes(context.config, context.content, audio.mediaFingerprint, captions?.fingerprint ?? null, (images) => editPlan(context, exports, youtube, images, audio.cards ?? []), drawnFrom, timing === undefined ? null : resourceIdentity(context, timing), withLines(masterPlan(context, audio.levels, "video"), linePlan(context, timing)), scenes, appearance, (text) => fillPrompt(context, text, "image"))),
80
85
  ...(scenes === undefined ? [] : [scenes.recipe]),
81
86
  ...(thumbnailScened === undefined ? [] : [thumbnailScened.recipe]),
82
87
  ...(appearance === undefined ? [] : [appearance.recipe]),
@@ -2,7 +2,7 @@ import { usesDescribedNarration, usesFigureCards, usesShorts } from "../admissio
2
2
  import { describedBlocks, narrationBlocks, spokenNarration, } from "../narration/blocks.js";
3
3
  import { describeMessages, spokenPassage } from "../narration/describe.js";
4
4
  import { recipe } from "./recipe-model.js";
5
- import { llmInput, matchingText, renderedPrompt } from "./recipe-text.js";
5
+ import { llmInput, matchingText, promptOf } from "./recipe-text.js";
6
6
  // "Describe tables and figures in the narration": one text-model step per table, figure,
7
7
  // diagram, equation or code block (`narration:describe:<n>`, in reading order), whose answer
8
8
  // is said in the block's place. The narration is chunked, prepared and spoken from that
@@ -19,7 +19,7 @@ export function describing(context) {
19
19
  // the model and the style guidance. The future step's template, so a change to any of them
20
20
  // reaches the narration still to be written.
21
21
  export function describeTemplate(context) {
22
- const input = llmInput(context, describeMessages({ kind: "table", index: 1, source: "", section: null }, renderedPrompt(context, "narration"), context.config.language));
22
+ const input = llmInput(context, describeMessages({ kind: "table", index: 1, source: "", section: null }, promptOf(context, "narration").text, context.config.language));
23
23
  return [
24
24
  "narration-description-v1",
25
25
  JSON.parse(JSON.stringify({ ...input, thinkingConfig: null })),
@@ -43,7 +43,7 @@ export function describedText(context, markdown, dependsOn, offset = 0) {
43
43
  code: config.audio?.skipCode === true ? "skip" : "describe",
44
44
  language: config.language,
45
45
  });
46
- const style = renderedPrompt(context, "narration");
46
+ const style = promptOf(context, "narration").text;
47
47
  const passages = new Map();
48
48
  const cards = [];
49
49
  const recipes = describedBlocks(blocks).map((block) => {