@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
@@ -58,7 +58,7 @@ export const starterPacks = [
58
58
  kind: "article",
59
59
  name: "Sleep lore · Story",
60
60
  body: [
61
- "Write a long, calm bedtime telling of {{topic}} for listeners who want to drift off to sleep.",
61
+ "Write a long, calm bedtime telling of {{Topic}} for listeners who want to drift off to sleep.",
62
62
  "",
63
63
  "Length: 2800-3200 words.",
64
64
  "",
@@ -83,7 +83,7 @@ export const starterPacks = [
83
83
  kind: "article",
84
84
  name: "Sleep lore · 60-second short",
85
85
  body: [
86
- `Subject: {{topic}}, as a quiet moment from myth or legend.`,
86
+ `Subject: {{Topic}}, as a quiet moment from myth or legend.`,
87
87
  "",
88
88
  scriptRules,
89
89
  "- Keep the calm, hushed tone of a bedtime story even in the hook.",
@@ -94,7 +94,7 @@ export const starterPacks = [
94
94
  kind: "image",
95
95
  name: "Sleep lore · Scene",
96
96
  body: [
97
- "A dreamlike painted scene from the legend of {{topic}}.",
97
+ "A dreamlike painted scene from the legend of {{Topic}}.",
98
98
  "Soft oil-painting style with visible brushwork, muted twilight palette of deep blues, dusky violets and warm lantern gold.",
99
99
  "Gentle haze, low contrast, wide calm composition with plenty of quiet space; distant figures rather than close faces.",
100
100
  "Peaceful and still, nothing threatening in the frame.",
@@ -106,7 +106,7 @@ export const starterPacks = [
106
106
  kind: "thumbnail",
107
107
  name: "Sleep lore · Thumbnail",
108
108
  body: [
109
- "A serene, luminous painting that sums up the legend of {{topic}} in one image.",
109
+ "A serene, luminous painting that sums up the legend of {{Topic}} in one image.",
110
110
  "One clear subject in the centre, soft moonlight or candlelight, deep blue and gold palette, gentle mist.",
111
111
  "Readable at a small size: simple shapes, strong silhouette, calm mood.",
112
112
  noText,
@@ -117,7 +117,7 @@ export const starterPacks = [
117
117
  kind: "description",
118
118
  name: "Sleep lore · Description",
119
119
  body: [
120
- "Write a YouTube description for a sleep story about {{topic}}.",
120
+ "Write a YouTube description for a sleep story about {{Topic}}.",
121
121
  "",
122
122
  "- Summary: 2-3 soothing sentences that invite the viewer to settle in. Mention that the story is calm and has no sudden sounds.",
123
123
  "- Chapters: one per part of the story, 3-6 gentle words each.",
@@ -164,7 +164,7 @@ export const starterPacks = [
164
164
  kind: "article",
165
165
  name: "True crime · Case",
166
166
  body: [
167
- "Write a documentary narration about the case of {{topic}}.",
167
+ "Write a documentary narration about the case of {{Topic}}.",
168
168
  "",
169
169
  "Length: 2200-2600 words.",
170
170
  "",
@@ -190,7 +190,7 @@ export const starterPacks = [
190
190
  kind: "article",
191
191
  name: "True crime · 60-second short",
192
192
  body: [
193
- "Subject: one striking, well-documented moment from the case of {{topic}}.",
193
+ "Subject: one striking, well-documented moment from the case of {{Topic}}.",
194
194
  "",
195
195
  scriptRules,
196
196
  "- Respectful and factual: no gore, no speculation about guilt, no invented detail.",
@@ -201,7 +201,7 @@ export const starterPacks = [
201
201
  kind: "image",
202
202
  name: "True crime · Scene",
203
203
  body: [
204
- "A moody documentary-style photograph evoking the setting of {{topic}}: the place, the era, the objects, the weather.",
204
+ "A moody documentary-style photograph evoking the setting of {{Topic}}: the place, the era, the objects, the weather.",
205
205
  "Cinematic 35mm look, overcast or night light, desaturated cool palette with deep shadows and a single practical light source.",
206
206
  "Empty streets, closed doors, rain on glass, paperwork on a desk; no recognisable real people, no bodies, no blood, no weapons pointed at anyone.",
207
207
  noText,
@@ -212,7 +212,7 @@ export const starterPacks = [
212
212
  kind: "thumbnail",
213
213
  name: "True crime · Thumbnail",
214
214
  body: [
215
- "A tense cinematic image that sums up the case of {{topic}}: one strong object or place in sharp focus against a dark, blurred background.",
215
+ "A tense cinematic image that sums up the case of {{Topic}}: one strong object or place in sharp focus against a dark, blurred background.",
216
216
  "High contrast, cold blue and amber light, heavy vignette, readable at phone size.",
217
217
  "No real people's faces, no gore.",
218
218
  noText,
@@ -223,7 +223,7 @@ export const starterPacks = [
223
223
  kind: "description",
224
224
  name: "True crime · Description",
225
225
  body: [
226
- "Write a YouTube description for a documentary about the case of {{topic}}.",
226
+ "Write a YouTube description for a documentary about the case of {{Topic}}.",
227
227
  "",
228
228
  "- Summary: 2-3 factual sentences on what happened and what the video covers. No sensational words.",
229
229
  "- Chapters: split where the story moves from events to investigation to outcome; 3-6 plain words each.",
@@ -273,7 +273,7 @@ export const starterPacks = [
273
273
  kind: "article",
274
274
  name: "History · Documentary",
275
275
  body: [
276
- "Write a documentary narration about {{topic}}.",
276
+ "Write a documentary narration about {{Topic}}.",
277
277
  "",
278
278
  "Length: 2000-2400 words.",
279
279
  "",
@@ -297,7 +297,7 @@ export const starterPacks = [
297
297
  kind: "article",
298
298
  name: "History · 60-second short",
299
299
  body: [
300
- "Subject: one surprising, true story or detail about {{topic}}.",
300
+ "Subject: one surprising, true story or detail about {{Topic}}.",
301
301
  "",
302
302
  scriptRules,
303
303
  "- Put the year and the place in the first two sentences.",
@@ -308,7 +308,7 @@ export const starterPacks = [
308
308
  kind: "image",
309
309
  name: "History · Scene",
310
310
  body: [
311
- "A historically grounded illustration of {{topic}}: period-accurate clothing, architecture, tools and landscape.",
311
+ "A historically grounded illustration of {{Topic}}: period-accurate clothing, architecture, tools and landscape.",
312
312
  "Rich painterly realism in the manner of a museum reconstruction, warm golden light, earthy ochre, umber and faded blue palette.",
313
313
  "Wide establishing views and mid shots of daily life; figures shown at a distance or from behind rather than as portraits of real people.",
314
314
  noText,
@@ -319,7 +319,7 @@ export const starterPacks = [
319
319
  kind: "thumbnail",
320
320
  name: "History · Thumbnail",
321
321
  body: [
322
- "A dramatic, detailed painting that sums up {{topic}} in one moment: one clear focal subject, strong light from one side, dust or smoke in the air.",
322
+ "A dramatic, detailed painting that sums up {{Topic}} in one moment: one clear focal subject, strong light from one side, dust or smoke in the air.",
323
323
  "Warm ochre and deep blue palette, high contrast, simple composition that reads at phone size.",
324
324
  noText,
325
325
  ].join(" "),
@@ -329,7 +329,7 @@ export const starterPacks = [
329
329
  kind: "description",
330
330
  name: "History · Description",
331
331
  body: [
332
- "Write a YouTube description for a history documentary about {{topic}}.",
332
+ "Write a YouTube description for a history documentary about {{Topic}}.",
333
333
  "",
334
334
  "- Summary: 2-3 sentences that name the period and place and say what the viewer will understand by the end.",
335
335
  "- Chapters: one per section of the narration, 2-6 words each, in title case.",
@@ -371,7 +371,7 @@ export const starterPacks = [
371
371
  kind: "article",
372
372
  name: "Science · Explainer",
373
373
  body: [
374
- "Write an explainer video narration about {{topic}} for curious viewers with no science background.",
374
+ "Write an explainer video narration about {{Topic}} for curious viewers with no science background.",
375
375
  "",
376
376
  "Length: 1400-1800 words.",
377
377
  "",
@@ -396,7 +396,7 @@ export const starterPacks = [
396
396
  kind: "article",
397
397
  name: "Science · 60-second short",
398
398
  body: [
399
- "Subject: one mind-bending but true fact about {{topic}}, and why it is so.",
399
+ "Subject: one mind-bending but true fact about {{Topic}}, and why it is so.",
400
400
  "",
401
401
  scriptRules,
402
402
  "- Give one real number with its unit and a comparison that makes it graspable.",
@@ -407,7 +407,7 @@ export const starterPacks = [
407
407
  kind: "image",
408
408
  name: "Science · Visual",
409
409
  body: [
410
- "A clean, striking visual that explains an aspect of {{topic}}.",
410
+ "A clean, striking visual that explains an aspect of {{Topic}}.",
411
411
  "Modern 3D-rendered or macro-photography look, crisp detail, dark background with vivid cyan, magenta and amber accents, soft rim light.",
412
412
  "One clear subject, scientifically plausible shapes and scales, generous negative space.",
413
413
  noText,
@@ -418,7 +418,7 @@ export const starterPacks = [
418
418
  kind: "thumbnail",
419
419
  name: "Science · Thumbnail",
420
420
  body: [
421
- "A bold, eye-catching image about {{topic}}: one surprising subject, glowing against a deep dark background.",
421
+ "A bold, eye-catching image about {{Topic}}: one surprising subject, glowing against a deep dark background.",
422
422
  "Saturated cyan and amber, strong contrast, simple composition that reads at phone size.",
423
423
  noText,
424
424
  ].join(" "),
@@ -428,7 +428,7 @@ export const starterPacks = [
428
428
  kind: "description",
429
429
  name: "Science · Description",
430
430
  body: [
431
- "Write a YouTube description for a science explainer about {{topic}}.",
431
+ "Write a YouTube description for a science explainer about {{Topic}}.",
432
432
  "",
433
433
  "- Summary: 2-3 sentences that pose the question and promise a clear answer, without exaggeration.",
434
434
  "- Chapters: one per step of the explanation, 2-6 words each.",
@@ -471,14 +471,14 @@ export const starterSet = {
471
471
  key: "shortScript",
472
472
  kind: "article",
473
473
  name: "Starter · 60-second short",
474
- body: ["Subject: {{topic}}.", "", scriptRules].join("\n"),
474
+ body: ["Subject: {{Topic}}.", "", scriptRules].join("\n"),
475
475
  },
476
476
  {
477
477
  key: "image",
478
478
  kind: "image",
479
479
  name: "Starter · Vertical scene",
480
480
  body: [
481
- "A cinematic vertical image about {{topic}}.",
481
+ "A cinematic vertical image about {{Topic}}.",
482
482
  "Rich colour, dramatic light, one clear subject large in the frame so it reads on a phone.",
483
483
  "Keep the lower half calm: captions are drawn over it.",
484
484
  noText,
@@ -0,0 +1,14 @@
1
+ // The model a service starts with when Slopify picks it for the person (a first short, the
2
+ // writer and voice Create fills in): a fast, capable default rather than the first listed,
3
+ // which can be the slowest or the smallest. One rule, so a service names the same model
4
+ // wherever it was picked for the person.
5
+ const preferred = {
6
+ "claude-code": /sonnet/i,
7
+ "openai-tts": /^gpt-4o-mini-tts$/,
8
+ };
9
+ export function isPreferredModel(provider, model) {
10
+ return preferred[provider]?.test(model) === true;
11
+ }
12
+ export function preferredModel(provider, models) {
13
+ return models.find((model) => isPreferredModel(provider, model.id)) ?? models[0];
14
+ }
@@ -2,18 +2,82 @@ import { readinessIsUsable } from "../../kernel/ports/model.js";
2
2
  import { titleMax } from "../admission/rules.js";
3
3
  import { defaultSentencePauseSeconds } from "../narration/pauses-model.js";
4
4
  import { systemVoiceProvider } from "../settings/model.js";
5
- const textClis = ["claude-code", "codex", "gemini"];
6
- const keyedImages = ["openai-image", "google-image", "fal", "replicate"];
5
+ import { preferredModel } from "./preferred-model.js";
6
+ // Who is asked first for each part: the CLIs before a key for the text, Codex before a key for
7
+ // the images.
8
+ const textOrder = ["claude-code", "codex", "gemini", "openrouter"];
9
+ const imageOrder = ["codex-image", "openai-image", "google-image", "fal", "replicate"];
7
10
  const keyedVoices = ["openai-tts", "elevenlabs", "cartesia", "inworld"];
8
- // The first model of these providers is the one a first short uses, unless one of these is
9
- // listed: a fast, capable default rather than the slowest or the smallest.
10
- const preferred = {
11
- "claude-code": /sonnet/i,
12
- "openai-tts": /^gpt-4o-mini-tts$/,
13
- };
14
11
  function ready(status) {
15
12
  return status !== undefined && readinessIsUsable(status.readiness);
16
13
  }
14
+ const statusOf = (statuses) => (id) => statuses.find((row) => row.id === id);
15
+ // The keyed voice a first short narrates with: a saved voice of a voice service with a key,
16
+ // else the voice the pack suggests when its service has a key.
17
+ function keyedVoice(statuses, voices, suggested) {
18
+ const status = statusOf(statuses);
19
+ const saved = voices.find((voice) => voice.provider !== systemVoiceProvider && ready(status(voice.provider)));
20
+ if (saved !== undefined)
21
+ return { provider: saved.provider, voiceId: saved.voiceId };
22
+ return ready(status(suggested.provider))
23
+ ? { provider: suggested.provider, voiceId: suggested.voiceId }
24
+ : undefined;
25
+ }
26
+ // One gap per part nothing can do, in plain words with what fixes it. The voice names a voice
27
+ // service that has a key but no saved voice, since a key alone is not the fix then.
28
+ function gapOf(need, statuses, install) {
29
+ if (need === "text")
30
+ return {
31
+ need,
32
+ fix: "key",
33
+ message: "Nothing can write the article yet. Sign in to Claude Code, Codex or Antigravity on this computer, or add an OpenRouter key.",
34
+ };
35
+ if (need === "images")
36
+ return {
37
+ need,
38
+ fix: "key",
39
+ message: "Nothing can make the images yet. Add an image key (OpenAI, Google, fal.ai or Replicate), or sign in to Codex on this computer.",
40
+ };
41
+ const status = statusOf(statuses);
42
+ const unsaved = keyedVoices.map(status).find((row) => ready(row));
43
+ if (unsaved !== undefined)
44
+ return {
45
+ need,
46
+ fix: "saved-voice",
47
+ message: `${unsaved.displayName} has a key but no voice saved yet. Save one in Settings → Voices, or add an OpenAI key, which works at once.`,
48
+ };
49
+ return {
50
+ need,
51
+ fix: "key",
52
+ message: "Nothing can read the article aloud yet. Add a voice key: an OpenAI key works at once with the voices Slopify sets up.",
53
+ ...(install === undefined ? {} : { install: { ...install, commands: [...install.commands] } }),
54
+ };
55
+ }
56
+ // What a first short would use on this computer and what it lacks, without asking any provider
57
+ // for its models: the first-run checklist, which must agree with the refusal below.
58
+ export function shortReadiness(input) {
59
+ const status = statusOf(input.statuses);
60
+ const part = (row) => row === undefined
61
+ ? { by: null, how: null }
62
+ : { by: row.displayName, how: row.readiness.kind === "cli" ? "sign-in" : "key" };
63
+ const text = part(textOrder.map(status).find((row) => ready(row)));
64
+ const images = part(imageOrder.map(status).find((row) => ready(row)));
65
+ const keyed = keyedVoice(input.statuses, input.voices, input.suggested);
66
+ const system = status(systemVoiceProvider)?.readiness;
67
+ const voice = keyed !== undefined
68
+ ? part(status(keyed.provider))
69
+ : system?.kind === "local" && system.available
70
+ ? { by: system.engine ?? "System voice", how: "computer" }
71
+ : { by: null, how: null };
72
+ const gaps = [
73
+ ["text", text],
74
+ ["images", images],
75
+ ["voice", voice],
76
+ ]
77
+ .filter(([, done]) => done.by === null)
78
+ .map(([need]) => gapOf(need, input.statuses, input.install));
79
+ return { text, voice, images, gaps };
80
+ }
17
81
  async function firstModel(modelsFor, provider, family) {
18
82
  let models;
19
83
  try {
@@ -22,58 +86,37 @@ async function firstModel(modelsFor, provider, family) {
22
86
  catch {
23
87
  return undefined;
24
88
  }
25
- const liked = preferred[provider];
26
- return ((liked === undefined ? undefined : models.find((model) => liked.test(model.id)))?.id ??
27
- models[0]?.id);
89
+ return preferredModel(provider, models)?.id;
28
90
  }
29
- export async function planShortProviders(input) {
30
- const status = (id) => input.statuses.find((row) => row.id === id);
31
- const gaps = [];
32
- let llm;
33
- for (const id of [...textClis, "openrouter"]) {
91
+ // The first ready provider in `order` that lists a model.
92
+ async function firstReady(input, order, family) {
93
+ const status = statusOf(input.statuses);
94
+ for (const id of order) {
34
95
  if (!ready(status(id)))
35
96
  continue;
36
- const model = await firstModel(input.modelsFor, id, "llm");
37
- if (model !== undefined) {
38
- llm = { provider: id, model };
39
- break;
40
- }
41
- }
42
- if (llm === undefined)
43
- gaps.push({
44
- need: "text",
45
- message: "No text model is ready. Install Claude Code, Codex or Antigravity CLI and sign in to it (Settings → Providers shows what Slopify found), or add an OpenRouter key in Settings → Providers.",
46
- });
47
- let images;
48
- for (const id of ["codex-image", ...keyedImages]) {
49
- if (!ready(status(id)))
50
- continue;
51
- const model = await firstModel(input.modelsFor, id, "image");
52
- if (model !== undefined) {
53
- images = { provider: id, model };
54
- break;
55
- }
97
+ const model = await firstModel(input.modelsFor, id, family);
98
+ if (model !== undefined)
99
+ return { provider: id, model };
56
100
  }
57
- if (images === undefined)
58
- gaps.push({
59
- need: "images",
60
- message: "No image model is ready. Install Codex CLI and sign in to it, or add an OpenAI, Google, fal.ai or Replicate key in Settings → Providers.",
61
- });
101
+ return undefined;
102
+ }
103
+ export async function planShortProviders(input) {
104
+ const status = statusOf(input.statuses);
105
+ const llm = await firstReady(input, textOrder, "llm");
106
+ const images = await firstReady(input, imageOrder, "image");
62
107
  // A keyed voice first (a saved one, else the pack's suggestion), then the computer's own: a
63
108
  // saved system voice, else the one found. Keys are the better voice, never a requirement.
64
109
  let audio;
65
- const keyed = (provider) => provider !== systemVoiceProvider;
66
- const saved = input.voices.find((voice) => keyed(voice.provider) && ready(status(voice.provider)));
67
- const provider = saved?.provider ??
68
- (ready(status(input.suggested.provider)) ? input.suggested.provider : undefined);
69
- if (provider !== undefined) {
70
- const model = await firstModel(input.modelsFor, provider, "tts");
110
+ const keyed = keyedVoice(input.statuses, input.voices, input.suggested);
111
+ if (keyed !== undefined) {
112
+ const model = await firstModel(input.modelsFor, keyed.provider, "tts");
71
113
  if (model !== undefined)
72
- audio = { provider, model, voice: saved?.voiceId ?? input.suggested.voiceId };
114
+ audio = { provider: keyed.provider, model, voice: keyed.voiceId };
73
115
  }
74
116
  let systemVoice = false;
75
- const system = status(systemVoiceProvider);
76
- if (audio === undefined && ready(system) && input.systemVoice !== undefined) {
117
+ if (audio === undefined &&
118
+ ready(status(systemVoiceProvider)) &&
119
+ input.systemVoice !== undefined) {
77
120
  const savedSystem = input.voices.find((voice) => voice.provider === systemVoiceProvider);
78
121
  audio = {
79
122
  provider: systemVoiceProvider,
@@ -82,20 +125,16 @@ export async function planShortProviders(input) {
82
125
  };
83
126
  systemVoice = true;
84
127
  }
85
- if (audio === undefined) {
86
- const systemIssue = system?.readiness.kind === "local" && system.readiness.issue !== undefined
87
- ? ` ${system.readiness.issue}`
88
- : "";
89
- gaps.push({
90
- need: "voice",
91
- message: keyedVoices.some((id) => ready(status(id)))
92
- ? "Your voice provider has no saved voice yet. Add one in Settings → Voices, then try again."
93
- : `No voice is ready to narrate the short: no voice key is saved and this computer's built-in voice can't be used.${systemIssue || " Install espeak-ng, or add an OpenAI, ElevenLabs, Cartesia or Inworld key in Settings → Providers (with ElevenLabs, Cartesia or Inworld, also save a voice in Settings → Voices)."}`,
94
- });
95
- }
96
- return llm === undefined || images === undefined || audio === undefined
97
- ? { ok: false, gaps }
98
- : { ok: true, providers: { llm, audio, images }, systemVoice };
128
+ if (llm === undefined || images === undefined || audio === undefined)
129
+ return {
130
+ ok: false,
131
+ gaps: [
132
+ ...(llm === undefined ? [gapOf("text", input.statuses, input.install)] : []),
133
+ ...(images === undefined ? [gapOf("images", input.statuses, input.install)] : []),
134
+ ...(audio === undefined ? [gapOf("voice", input.statuses, input.install)] : []),
135
+ ],
136
+ };
137
+ return { ok: true, providers: { llm, audio, images }, systemVoice };
99
138
  }
100
139
  // The short-mode draft for a topic, using the pack's (or starter set's) script and scene
101
140
  // prompts under the names they have in the library.
@@ -121,7 +160,8 @@ export function shortDraft(input) {
121
160
  images: input.providers.images,
122
161
  articlePrompt: input.names.shortScript ?? "",
123
162
  imagePrompts: [{ name: input.names.image ?? "", number: shortImages }],
124
- values: { topic },
163
+ // {{Topic}} since 4.0; a pack installed before asks for {{topic}}, so both are filled.
164
+ values: { Topic: topic, topic },
125
165
  provided: {},
126
166
  silenceGapSeconds: 0.5,
127
167
  imageSeconds: shortImageSeconds,
@@ -19,7 +19,6 @@ export const sampleArchives = {
19
19
  audiobook: bundled("sample-audiobook.tar"),
20
20
  podcast: bundled("sample-podcast.tar"),
21
21
  };
22
- export const sampleArchive = sampleArchives.library;
23
22
  const archiveOf = (deps, id) => deps.archives?.[id] ?? sampleArchives[id];
24
23
  function recordedProject(db, id) {
25
24
  const record = readSampleRecord(db, id);
@@ -128,5 +127,8 @@ export function copySample(deps, projectId) {
128
127
  status: 404,
129
128
  detail: "That sample project is no longer here. Bring it back with Settings → Backup & storage → Restore samples, then press Make my own copy.",
130
129
  };
131
- return { ok: true, ...copyProject(deps, projectId, `${title} (my copy)`) };
130
+ return {
131
+ ok: true,
132
+ ...copyProject(deps, projectId, `${title} (my copy)`, { renamed: true }),
133
+ };
132
134
  }
@@ -1,5 +1,6 @@
1
1
  import { z } from "zod";
2
- import { readSetting, writeSetting } from "../settings/repo.js";
2
+ import { readJsonSetting, readSetting, writeSetting } from "../settings/repo.js";
3
+ import { sampleIds } from "./model.js";
3
4
  // What the first five minutes remember, in the settings table: whether the first-run screen
4
5
  // was dismissed, which project is the bundled sample, and which library rows each installed
5
6
  // starter pack became. None of these keys is in a portable backup's settings, so another
@@ -25,16 +26,7 @@ const shortRequests = z.record(z.string(), z.string());
25
26
  // ceiling: only a retry of a recent click needs its answer.
26
27
  const shortRequestsKept = 20;
27
28
  function readJson(db, key, schema) {
28
- const raw = readSetting(db, key);
29
- if (raw === undefined)
30
- return undefined;
31
- try {
32
- const parsed = schema.safeParse(JSON.parse(raw));
33
- return parsed.success ? parsed.data : undefined;
34
- }
35
- catch {
36
- return undefined;
37
- }
29
+ return readJsonSetting(db, key, schema, undefined);
38
30
  }
39
31
  export function firstRunDismissed(db) {
40
32
  return readSetting(db, dismissedKey) !== undefined;
@@ -50,6 +42,12 @@ const sampleKeyOf = (id) => (id === "library" ? sampleKey : `${sampleKey}.${id}`
50
42
  export function readSampleRecord(db, id = "library") {
51
43
  return readJson(db, sampleKeyOf(id), sampleRecord);
52
44
  }
45
+ // The bundled samples' projects, by id, for a slice that must leave them as they are (Disk
46
+ // space's clean-ups). A deleted sample's record stays until Restore samples, so an id may name
47
+ // no project any more.
48
+ export function bundledSampleProjects(db) {
49
+ return new Set(sampleIds.flatMap((id) => readSampleRecord(db, id)?.projectId ?? []));
50
+ }
53
51
  export function writeSampleRecord(db, record, id = "library") {
54
52
  writeSetting(db, sampleKeyOf(id), JSON.stringify(record));
55
53
  }
@@ -1,15 +1,17 @@
1
1
  import { defaultEdgeSilenceSeconds } from "../admission/rules.js";
2
2
  import { playDraftDocumentSchema } from "../play-drafts/schema.js";
3
3
  // A pack's Play template: its prompts ticked, its voice picked, its style set, and the text and
4
- // image providers left for the user to choose, since which of them is installed or keyed
5
- // differs per machine.
6
- export function packTemplate(pack, names, voiceId) {
4
+ // image providers this machine's first launch found (Claude Code, Codex), since which of them
5
+ // is installed or keyed differs per machine. One it did not find is left for the user to pick.
6
+ export function packTemplate(pack, names, voiceId, providers = {}) {
7
7
  const { style } = pack;
8
8
  const name = (key) => names[key] ?? "";
9
+ const chosen = (choice) => choice === undefined ? { provider: "", model: "" } : { ...choice };
9
10
  return playDraftDocumentSchema.parse({
10
11
  schemaVersion: 1,
11
12
  form: {
12
- title: "",
13
+ // The topic typed in Play, or the one a schedule fills each run, names the video.
14
+ title: "{{Topic}}",
13
15
  format: "16:9",
14
16
  sources: {
15
17
  research: style.research ? "generate" : "off",
@@ -20,7 +22,7 @@ export function packTemplate(pack, names, voiceId) {
20
22
  video: "generate",
21
23
  document: "off",
22
24
  },
23
- llm: { provider: "", model: "" },
25
+ llm: chosen(providers.llm),
24
26
  audio: {
25
27
  provider: pack.voice.provider,
26
28
  model: pack.voice.model,
@@ -29,7 +31,7 @@ export function packTemplate(pack, names, voiceId) {
29
31
  shareGlossary: true,
30
32
  describeFigures: true,
31
33
  },
32
- images: { provider: "", model: "" },
34
+ images: chosen(providers.images),
33
35
  articlePrompt: name("article"),
34
36
  narrationPrompt: "",
35
37
  youtubeDescription: name("description") !== "",
@@ -1,4 +1,5 @@
1
1
  import { stageKinds } from "../../kernel/pipeline.js";
2
+ import { editSettings } from "../../kernel/ports/settings-places.js";
2
3
  import { sourceOf } from "../admission/model.js";
3
4
  import { defaultVoicesSettings } from "../voices/model.js";
4
5
  // Another output made from a project that already exists: the same brief, sources and
@@ -53,7 +54,7 @@ export function planAddedOutput(config, kind) {
53
54
  return {
54
55
  ok: false,
55
56
  reason: "narration-taken",
56
- message: `This project already has narration, and a project has one: ${kind === "podcast" ? "a podcast" : "an audiobook"} would replace it. Keep it, or change its format under Speakers in this project's Settings → Providers.`,
57
+ message: `This project already has narration, and a project has one: ${kind === "podcast" ? "a podcast" : "an audiobook"} would replace it. Keep it, or change its format under Speakers in ${editSettings.narration}.`,
57
58
  };
58
59
  const sources = switchedOn(config, kind);
59
60
  const next = {
@@ -78,7 +79,7 @@ export function planAddedOutput(config, kind) {
78
79
  reused: ["Brief: title, prompts and keywords", ...kept.map((stage) => stageResults[stage])],
79
80
  created: createdWords(kind, stages),
80
81
  textUse: kind === "podcast"
81
- ? "Adapted: the text model rewrites your article as a conversation between two hosts for the narration. The article stays as written; the conversation is kept beside it as the script."
82
+ ? "Adapted: the AI model rewrites your article as a conversation between two hosts for the narration. The article stays as written; the conversation is kept beside it as the script."
82
83
  : kind === "images"
83
84
  ? "Your text is not changed."
84
85
  : "Your text is used as written: nothing is rewritten.",
@@ -117,9 +117,9 @@ function newProblems(before, after) {
117
117
  .map((one) => ({ field: one.field, message: settingsHint(one) }));
118
118
  }
119
119
  function settingsHint(problem) {
120
- return /Settings|Edit project/.test(problem.message)
120
+ return /Settings|Edit settings/.test(problem.message)
121
121
  ? problem.message
122
- : `${problem.message} Set it in this project's Settings, save, then add the output again.`;
122
+ : `${problem.message} Set it in Edit settings, save, then add the output again.`;
123
123
  }
124
124
  function catalogueOf(deps) {
125
125
  return (deps.catalogue?.read() ?? {
@@ -3,7 +3,8 @@ import { readFile } from "node:fs/promises";
3
3
  import { join } from "node:path";
4
4
  import { fileURLToPath } from "node:url";
5
5
  import { z } from "zod";
6
- // The patch notes the app shows in Settings → Patch notes: Markdown files kept in the
6
+ import { hasErrnoCode } from "../../kernel/errors.js";
7
+ // The patch notes the app shows in Settings → What's new: Markdown files kept in the
7
8
  // repository's docs/patch-notes/ and copied into the build beside the compiled code
8
9
  // (scripts/copy-assets.mjs). index.json lists them with a title and a date; each note is
9
10
  // `<id>.md` beside it. Nothing here writes: the notes are part of the release.
@@ -34,7 +35,7 @@ export async function listPatchNotes(dir) {
34
35
  raw = await readFile(join(dir, "index.json"), "utf8");
35
36
  }
36
37
  catch (error) {
37
- if (error.code === "ENOENT")
38
+ if (hasErrnoCode(error, "ENOENT"))
38
39
  throw new PatchNotesMissing("This copy of Slopify has no patch notes: its docs/patch-notes/index.json is missing. Reinstall Slopify (or run npm run build) and reload the page.");
39
40
  throw error;
40
41
  }
@@ -66,7 +67,7 @@ export async function readPatchNote(dir, id) {
66
67
  return await readFile(join(dir, `${id}.md`), "utf8");
67
68
  }
68
69
  catch (error) {
69
- if (error.code === "ENOENT")
70
+ if (hasErrnoCode(error, "ENOENT"))
70
71
  return undefined;
71
72
  throw error;
72
73
  }
@@ -9,6 +9,7 @@ import { pausesOfForm } from "../narration/pauses-model.js";
9
9
  import { reviewSettingsFromForm } from "../reviews/model.js";
10
10
  import { stageMakesItems } from "../reviews/rules.js";
11
11
  import { defaultShorts, shortsExtrasOf, shortsSettingsProblems, } from "../shorts/model.js";
12
+ import { socialOfForm } from "../social/settings.js";
12
13
  import { defaultSubtitles } from "../subtitles/model.js";
13
14
  import { ambientBedOfForm, ambientBedProblems } from "../video/ambient-bed.js";
14
15
  // Said where the control is, since the music sits in a closed disclosure on the Export rail.
@@ -206,6 +207,9 @@ export function toAdmissionDraft(input) {
206
207
  ...(form.descriptionPrompt?.trim() ? { descriptionPrompt: form.descriptionPrompt } : {}),
207
208
  }
208
209
  : {}),
210
+ // Posting is free unless a site's words come from a post prompt; none turned on is left out,
211
+ // which is what every draft saved before posting was.
212
+ ...((social) => (social === undefined ? {} : { social }))(socialOfForm(form.social)),
209
213
  // Cut from the narration too, so the same rule: a switch left on with narration Off asks
210
214
  // for nothing.
211
215
  ...(shortsOn && form.shorts !== undefined ? { shorts: shortsOf(form.shorts) } : {}),
@@ -63,7 +63,7 @@ export async function checkDraftReadiness(deps, runs) {
63
63
  field: c.field,
64
64
  message: provider !== undefined && provider.readiness.kind !== "keyed" && provider.readiness.issue
65
65
  ? provider.readiness.issue
66
- : "Set up this provider in Settings → Providers before starting.",
66
+ : "Set up this provider in Settings → Keys & services before starting.",
67
67
  });
68
68
  continue;
69
69
  }
@@ -88,12 +88,12 @@ export function localDraftReadiness(deps, runs, providers) {
88
88
  if (cliPathChanged(deps.db, provider))
89
89
  fields.push({
90
90
  field: `${c.field}.cliPath`,
91
- message: "This provider's command-line tool changed in Settings → Providers. Choose Review and start again.",
91
+ message: "This provider's command-line tool changed in Settings → Keys & services. Choose Review and start again.",
92
92
  });
93
93
  if (provider?.readiness.kind === "keyed" && !hasKey(deps.db, provider.id))
94
94
  fields.push({
95
95
  field: c.field,
96
- message: "Add this provider's API key in Settings → Providers before starting.",
96
+ message: "Add this provider's API key in Settings → Keys & services before starting.",
97
97
  });
98
98
  }
99
99
  for (const { draft } of runs)