@gentbajko/slopify 3.25.9 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (718) hide show
  1. package/dist/adapters/account-limits.js +30 -0
  2. package/dist/adapters/alignment/audio.js +1 -1
  3. package/dist/adapters/alignment/cache.js +4 -6
  4. package/dist/adapters/alignment/ctc.js +1 -2
  5. package/dist/adapters/alignment/lock.js +4 -3
  6. package/dist/adapters/alignment/multilingual.js +2 -4
  7. package/dist/adapters/alignment/prefetch.js +2 -1
  8. package/dist/adapters/alignment/runner.js +1 -1
  9. package/dist/adapters/alignment/worker.js +3 -2
  10. package/dist/adapters/explain.js +10 -12
  11. package/dist/adapters/ffmpeg.js +19 -1
  12. package/dist/adapters/host-cli/index.js +21 -4
  13. package/dist/adapters/host-cli/transport.js +2 -1
  14. package/dist/adapters/http-failure.js +53 -0
  15. package/dist/adapters/image/bytes.js +2 -1
  16. package/dist/adapters/image/codex.js +42 -9
  17. package/dist/adapters/image/fal.js +21 -53
  18. package/dist/adapters/image/google.js +33 -56
  19. package/dist/adapters/image/models.js +2 -2
  20. package/dist/adapters/image/openai.js +22 -48
  21. package/dist/adapters/image/reference.js +36 -0
  22. package/dist/adapters/image/replicate.js +21 -49
  23. package/dist/adapters/image/video.js +2 -1
  24. package/dist/adapters/interest/search-interest.js +113 -0
  25. package/dist/adapters/key-probes.js +54 -3
  26. package/dist/adapters/llm/antigravity-models.js +1 -1
  27. package/dist/adapters/llm/antigravity.js +11 -6
  28. package/dist/adapters/llm/assistant-cli.js +388 -0
  29. package/dist/adapters/llm/child-session.js +83 -0
  30. package/dist/adapters/llm/claude-code-models.js +52 -99
  31. package/dist/adapters/llm/claude-code.js +16 -4
  32. package/dist/adapters/llm/codex-limits.js +27 -68
  33. package/dist/adapters/llm/codex-models.js +1 -1
  34. package/dist/adapters/llm/codex-server-models.js +61 -109
  35. package/dist/adapters/llm/codex.js +12 -1
  36. package/dist/adapters/llm/document-workspace.js +3 -2
  37. package/dist/adapters/llm/image-workspace.js +3 -2
  38. package/dist/adapters/llm/openrouter.js +12 -48
  39. package/dist/adapters/llm/run-cli.js +9 -24
  40. package/dist/adapters/llm/sse-lines.js +5 -1
  41. package/dist/adapters/model-access.js +37 -0
  42. package/dist/adapters/tts/cartesia.js +15 -46
  43. package/dist/adapters/tts/elevenlabs.js +20 -52
  44. package/dist/adapters/tts/gemini.js +21 -41
  45. package/dist/adapters/tts/inworld-async.js +6 -2
  46. package/dist/adapters/tts/inworld.js +6 -2
  47. package/dist/adapters/tts/openai.js +20 -50
  48. package/dist/adapters/tts/system.js +2 -1
  49. package/dist/assets/models-lifecycle.yaml +6 -0
  50. package/dist/assistant-wiring.js +60 -0
  51. package/dist/autopilot-timers.js +59 -0
  52. package/dist/catalog/lifecycle.js +52 -0
  53. package/dist/catalog/propose.js +204 -0
  54. package/dist/catalog/registry.js +23 -14
  55. package/dist/catalog/schema.js +4 -1
  56. package/dist/catalog/store.js +39 -0
  57. package/dist/catalog/validate.js +5 -2
  58. package/dist/edge/autostart/native.js +3 -5
  59. package/dist/edge/autostart/prompt.js +2 -1
  60. package/dist/edge/autostart/service.js +3 -4
  61. package/dist/edge/cli-args.js +3 -4
  62. package/dist/edge/cli.js +2 -1
  63. package/dist/edge/docker-install/apply.js +11 -11
  64. package/dist/edge/docker-install/run.js +2 -1
  65. package/dist/edge/docker-install/state.js +4 -3
  66. package/dist/edge/docker-install/tree.js +2 -4
  67. package/dist/edge/docker-install/volume.js +3 -2
  68. package/dist/edge/docker.js +5 -4
  69. package/dist/edge/events/hub.js +5 -5
  70. package/dist/edge/http/actions.js +11 -32
  71. package/dist/edge/http/actor.js +5 -3
  72. package/dist/edge/http/app.js +86 -11
  73. package/dist/edge/http/assistant.js +129 -0
  74. package/dist/edge/http/audio-preview.js +4 -11
  75. package/dist/edge/http/auditions.js +1 -1
  76. package/dist/edge/http/autostart.js +5 -5
  77. package/dist/edge/http/backups.js +2 -4
  78. package/dist/edge/http/channel-memory.js +9 -22
  79. package/dist/edge/http/channels.js +14 -27
  80. package/dist/edge/http/checkpoints.js +39 -21
  81. package/dist/edge/http/design-templates.js +167 -0
  82. package/dist/edge/http/designs.js +178 -0
  83. package/dist/edge/http/diagnostics.js +5 -1
  84. package/dist/edge/http/document-themes.js +5 -14
  85. package/dist/edge/http/draft-files.js +1 -3
  86. package/dist/edge/http/draft-problem.js +5 -10
  87. package/dist/edge/http/drafts.js +3 -3
  88. package/dist/edge/http/entries.js +6 -9
  89. package/dist/edge/http/extension-auth.js +27 -0
  90. package/dist/edge/http/external-reviews.js +12 -11
  91. package/dist/edge/http/files.js +5 -11
  92. package/dist/edge/http/folder-location.js +1 -4
  93. package/dist/edge/http/fonts.js +0 -7
  94. package/dist/edge/http/home.js +47 -14
  95. package/dist/edge/http/host-cli.js +18 -8
  96. package/dist/edge/http/ids.js +8 -0
  97. package/dist/edge/http/keywords.js +35 -0
  98. package/dist/edge/http/model-checks.js +132 -0
  99. package/dist/edge/http/narration-peaks.js +5 -13
  100. package/dist/edge/http/onboarding.js +30 -26
  101. package/dist/edge/http/open-folder.js +5 -10
  102. package/dist/edge/http/outputs.js +7 -14
  103. package/dist/edge/http/patch-notes.js +6 -12
  104. package/dist/edge/http/planning.js +3 -7
  105. package/dist/edge/http/problem.js +2 -4
  106. package/dist/edge/http/project-create.js +2 -1
  107. package/dist/edge/http/project-templates.js +31 -19
  108. package/dist/edge/http/projects.js +24 -16
  109. package/dist/edge/http/prompts.js +9 -16
  110. package/dist/edge/http/pronunciations.js +1 -2
  111. package/dist/edge/http/providers.js +48 -34
  112. package/dist/edge/http/refusal.js +29 -0
  113. package/dist/edge/http/remote-access.js +40 -0
  114. package/dist/edge/http/remote-guard.js +71 -0
  115. package/dist/edge/http/request-guard.js +91 -0
  116. package/dist/edge/http/reviews.js +12 -25
  117. package/dist/edge/http/revision-files.js +6 -11
  118. package/dist/edge/http/revisions.js +14 -19
  119. package/dist/edge/http/run-cost.js +1 -2
  120. package/dist/edge/http/same-page.js +80 -0
  121. package/dist/edge/http/schedules.js +69 -40
  122. package/dist/edge/http/settings.js +27 -14
  123. package/dist/edge/http/social.js +283 -0
  124. package/dist/edge/http/staging.js +3 -5
  125. package/dist/edge/http/storage-files.js +5 -7
  126. package/dist/edge/http/storage.js +33 -25
  127. package/dist/edge/http/studio.js +94 -69
  128. package/dist/edge/http/style-preview.js +3 -6
  129. package/dist/edge/http/subtitles.js +3 -17
  130. package/dist/edge/http/template-studio.js +436 -0
  131. package/dist/edge/http/trash.js +11 -12
  132. package/dist/edge/http/tutorial.js +1 -2
  133. package/dist/edge/http/tutorials.js +5 -11
  134. package/dist/edge/http/update.js +7 -13
  135. package/dist/edge/http/waveform.js +3 -6
  136. package/dist/edge/http/youtube-edits.js +3 -4
  137. package/dist/edge/mcp/assistant.js +279 -0
  138. package/dist/edge/mcp/attribution.js +8 -2
  139. package/dist/edge/mcp/call-route.js +11 -2
  140. package/dist/edge/mcp/excluded-routes.js +29 -3
  141. package/dist/edge/mcp/http.js +11 -2
  142. package/dist/edge/mcp/instructions.js +6 -4
  143. package/dist/edge/mcp/library-tools.js +9 -5
  144. package/dist/edge/mcp/remake-tools.js +7 -4
  145. package/dist/edge/mcp/route-tool.js +35 -15
  146. package/dist/edge/mcp/server.js +13 -8
  147. package/dist/edge/mcp/tools-channels.js +11 -9
  148. package/dist/edge/mcp/tools-designs.js +165 -0
  149. package/dist/edge/mcp/tools-library.js +19 -7
  150. package/dist/edge/mcp/tools-planning.js +40 -21
  151. package/dist/edge/mcp/tools-projects.js +38 -11
  152. package/dist/edge/mcp/tools-publishing.js +9 -9
  153. package/dist/edge/mcp/tools-runs.js +23 -10
  154. package/dist/edge/mcp/tools-schedules.js +32 -8
  155. package/dist/edge/mcp/tools-setup.js +75 -11
  156. package/dist/edge/mcp/tools-social.js +47 -0
  157. package/dist/edge/mcp/tools-storage.js +11 -3
  158. package/dist/edge/mcp/tools-template-studio.js +166 -0
  159. package/dist/edge/mcp/tools.js +6 -0
  160. package/dist/edge/remote-access/cli.js +71 -0
  161. package/dist/edge/remote-access/model.js +32 -0
  162. package/dist/edge/remote-access/rules.js +207 -0
  163. package/dist/edge/remote-access/service.js +203 -0
  164. package/dist/edge/remote-access/store.js +44 -0
  165. package/dist/edge/remote-access/views.js +43 -0
  166. package/dist/extension/slopify-studio-chrome.zip +0 -0
  167. package/dist/extension/slopify-studio-firefox.zip +0 -0
  168. package/dist/host-cli/install.js +2 -2
  169. package/dist/host-cli/open-folder.js +2 -2
  170. package/dist/host-cli/paths.js +2 -4
  171. package/dist/host-cli/server.js +4 -4
  172. package/dist/host-cli/service.js +3 -3
  173. package/dist/host-cli/status.js +7 -7
  174. package/dist/kernel/db/migrations/0063-model-checks.sql +20 -0
  175. package/dist/kernel/db/migrations/0064-template-studio.sql +46 -0
  176. package/dist/kernel/db/migrations/0065-promise-and-assistant-reviews.sql +58 -0
  177. package/dist/kernel/db/migrations/0066-assistant.sql +44 -0
  178. package/dist/kernel/db/migrations/0067-autopilot.sql +6 -0
  179. package/dist/kernel/db/migrations/0068-topic-scores.sql +17 -0
  180. package/dist/kernel/db/migrations/0070-designs.sql +53 -0
  181. package/dist/kernel/db/migrations/0071-design-usage.sql +33 -0
  182. package/dist/kernel/db/migrations/0072-design-templates.sql +33 -0
  183. package/dist/kernel/db/migrations/0073-schedule-design-kind.sql +5 -0
  184. package/dist/kernel/db/migrations/0074-template-bakeoffs.sql +44 -0
  185. package/dist/kernel/db/migrations/0075-social-posts.sql +25 -0
  186. package/dist/kernel/db/migrations/0076-channel-social.sql +5 -0
  187. package/dist/kernel/db/migrations/0077-post-prompts.sql +17 -0
  188. package/dist/kernel/db/migrations/0078-uploaded-from-links.sql +7 -0
  189. package/dist/kernel/db/tx.js +2 -4
  190. package/dist/kernel/errors.js +27 -1
  191. package/dist/kernel/json-answer.js +15 -0
  192. package/dist/kernel/lock.js +4 -9
  193. package/dist/kernel/paths.js +8 -0
  194. package/dist/kernel/pipeline.js +12 -0
  195. package/dist/kernel/ports/assistant-cli.js +4 -0
  196. package/dist/kernel/ports/host-cli.js +3 -0
  197. package/dist/kernel/ports/interest.js +4 -0
  198. package/dist/kernel/ports/languages.js +0 -3
  199. package/dist/kernel/ports/model.js +2 -0
  200. package/dist/kernel/ports/settings-places.js +31 -0
  201. package/dist/kernel/ports/system-speech.js +31 -3
  202. package/dist/kernel/runner/attempt.js +14 -4
  203. package/dist/kernel/runner/audition.js +3 -1
  204. package/dist/kernel/runner/checkpoint-authority.js +2 -1
  205. package/dist/kernel/runner/index.js +8 -10
  206. package/dist/kernel/runner/model-access.js +40 -0
  207. package/dist/kernel/runner/model-check.js +153 -0
  208. package/dist/kernel/runner/providers.js +18 -12
  209. package/dist/kernel/runner/standalone.js +11 -7
  210. package/dist/main.js +338 -21
  211. package/dist/model-catalog.js +20 -0
  212. package/dist/model-checks.js +166 -0
  213. package/dist/patch-notes/4.0.0.md +51 -0
  214. package/dist/patch-notes/4.1.0.md +42 -0
  215. package/dist/patch-notes/index.json +12 -0
  216. package/dist/slices/admission/heads.js +2 -1
  217. package/dist/slices/admission/listing-facts.js +95 -0
  218. package/dist/slices/admission/repo.js +11 -7
  219. package/dist/slices/admission/rules.js +50 -15
  220. package/dist/slices/admission/schema.js +8 -0
  221. package/dist/slices/admission/stage-writes.js +0 -3
  222. package/dist/slices/admission/start.js +48 -31
  223. package/dist/slices/admission/state-words.js +34 -5
  224. package/dist/slices/admission/substitute.js +7 -4
  225. package/dist/slices/agents/attention-posts.js +31 -0
  226. package/dist/slices/agents/attention-templates.js +33 -0
  227. package/dist/slices/agents/attention.js +10 -1
  228. package/dist/slices/agents/connection.js +2 -6
  229. package/dist/slices/agents/model.js +6 -3
  230. package/dist/slices/agents/repo.js +15 -7
  231. package/dist/slices/article/continuation.js +0 -63
  232. package/dist/slices/article/plain.js +3 -2
  233. package/dist/slices/article/segments.js +2 -62
  234. package/dist/slices/assistant/access.js +1 -0
  235. package/dist/slices/assistant/asks.js +80 -0
  236. package/dist/slices/assistant/cost.js +54 -0
  237. package/dist/slices/assistant/gate.js +222 -0
  238. package/dist/slices/assistant/model.js +86 -0
  239. package/dist/slices/assistant/names.js +23 -0
  240. package/dist/slices/assistant/prompt.js +74 -0
  241. package/dist/slices/assistant/repo.js +74 -0
  242. package/dist/slices/assistant/tokens.js +18 -0
  243. package/dist/slices/assistant/turn.js +344 -0
  244. package/dist/slices/autopilot/buffer.js +76 -0
  245. package/dist/slices/autopilot/model.js +14 -0
  246. package/dist/slices/autopilot/notify.js +27 -0
  247. package/dist/slices/autopilot/repo.js +34 -0
  248. package/dist/slices/autopilot/signals.js +194 -0
  249. package/dist/slices/autopilot/warnings.js +85 -0
  250. package/dist/slices/autopilot/weekly.js +100 -0
  251. package/dist/slices/backups/files.js +2 -6
  252. package/dist/slices/backups/repo.js +3 -15
  253. package/dist/slices/backups/service.js +8 -7
  254. package/dist/slices/channels/cast-images.js +3 -2
  255. package/dist/slices/channels/model.js +0 -1
  256. package/dist/slices/channels/rebrand.js +0 -3
  257. package/dist/slices/channels/repo.js +4 -0
  258. package/dist/slices/channels/schema.js +7 -1
  259. package/dist/slices/channels/service.js +10 -0
  260. package/dist/slices/channels/videos.js +3 -15
  261. package/dist/slices/checkpoints/index.js +0 -1
  262. package/dist/slices/control/providers.js +2 -28
  263. package/dist/slices/designs/artwork.js +66 -0
  264. package/dist/slices/designs/budget.js +23 -0
  265. package/dist/slices/designs/calls.js +124 -0
  266. package/dist/slices/designs/check-context.js +38 -0
  267. package/dist/slices/designs/check-text.js +43 -0
  268. package/dist/slices/designs/fields.js +88 -0
  269. package/dist/slices/designs/frames.js +34 -0
  270. package/dist/slices/designs/gate.js +130 -0
  271. package/dist/slices/designs/layout.js +293 -0
  272. package/dist/slices/designs/model.js +35 -0
  273. package/dist/slices/designs/pdf-job.js +23 -0
  274. package/dist/slices/designs/pdf-pages.js +30 -0
  275. package/dist/slices/designs/pdf-runner.js +68 -0
  276. package/dist/slices/designs/pdf-worker.js +24 -0
  277. package/dist/slices/designs/picture-size.js +79 -0
  278. package/dist/slices/designs/pictures.js +55 -0
  279. package/dist/slices/designs/quote.js +24 -0
  280. package/dist/slices/designs/render-args.js +36 -0
  281. package/dist/slices/designs/render-input.js +59 -0
  282. package/dist/slices/designs/render.js +215 -0
  283. package/dist/slices/designs/repo.js +101 -0
  284. package/dist/slices/designs/requests.js +80 -0
  285. package/dist/slices/designs/runner.js +239 -0
  286. package/dist/slices/designs/sample-repo.js +91 -0
  287. package/dist/slices/designs/sample.js +223 -0
  288. package/dist/slices/designs/schema.js +87 -0
  289. package/dist/slices/designs/sections.js +44 -0
  290. package/dist/slices/designs/service.js +233 -0
  291. package/dist/slices/designs/steps-repo.js +102 -0
  292. package/dist/slices/designs/studio-kind.js +39 -0
  293. package/dist/slices/designs/template-checks.js +44 -0
  294. package/dist/slices/designs/template-make.js +118 -0
  295. package/dist/slices/designs/templates.js +218 -0
  296. package/dist/slices/document/fonts.js +2 -1
  297. package/dist/slices/document/model.js +7 -4
  298. package/dist/slices/document/render.js +2 -1
  299. package/dist/slices/document/theme-schema.js +1 -1
  300. package/dist/slices/document/theme.js +49 -3
  301. package/dist/slices/episodes/summarize.js +6 -2
  302. package/dist/slices/estimate/index.js +72 -28
  303. package/dist/slices/estimate/requests.js +4 -4
  304. package/dist/slices/fixes/rules.js +3 -1
  305. package/dist/slices/fonts/catalog.js +5 -3
  306. package/dist/slices/fonts/coverage.js +2 -1
  307. package/dist/slices/fonts/discovery.js +3 -2
  308. package/dist/slices/fonts/files.js +2 -6
  309. package/dist/slices/fonts/index.js +0 -1
  310. package/dist/slices/fonts/sfnt.js +45 -10
  311. package/dist/slices/images/appearance.js +8 -16
  312. package/dist/slices/images/scenes.js +102 -28
  313. package/dist/slices/keywords/digest.js +85 -0
  314. package/dist/slices/keywords/facts.js +92 -0
  315. package/dist/slices/keywords/fill.js +80 -0
  316. package/dist/slices/keywords/model.js +75 -0
  317. package/dist/slices/keywords/rules.js +187 -0
  318. package/dist/slices/keywords/schema.js +28 -0
  319. package/dist/slices/keywords/specs.js +260 -0
  320. package/dist/slices/keywords/values.js +74 -0
  321. package/dist/slices/library/lint.js +29 -12
  322. package/dist/slices/library/model.js +2 -0
  323. package/dist/slices/library/photorealistic.js +4 -12
  324. package/dist/slices/library/rename.js +9 -7
  325. package/dist/slices/library/save.js +14 -10
  326. package/dist/slices/library/slots.js +37 -11
  327. package/dist/slices/library/transfer.js +5 -4
  328. package/dist/slices/library/used-by.js +25 -10
  329. package/dist/slices/loudness/loudnorm.js +53 -12
  330. package/dist/slices/loudness/model.js +3 -2
  331. package/dist/slices/loudness/sentence-level.js +2 -1
  332. package/dist/slices/model-checks/cost.js +61 -0
  333. package/dist/slices/model-checks/listing.js +124 -0
  334. package/dist/slices/model-checks/model.js +20 -0
  335. package/dist/slices/model-checks/record.js +32 -0
  336. package/dist/slices/model-checks/repo.js +120 -0
  337. package/dist/slices/model-checks/rules.js +125 -0
  338. package/dist/slices/model-checks/run.js +143 -0
  339. package/dist/slices/model-checks/service.js +198 -0
  340. package/dist/slices/model-upkeep/model.js +1 -1
  341. package/dist/slices/model-upkeep/switch.js +72 -27
  342. package/dist/slices/model-upkeep/usage.js +39 -13
  343. package/dist/slices/narration/breaths.js +3 -1
  344. package/dist/slices/narration/clean-pieces.js +3 -1
  345. package/dist/slices/narration/concat.js +2 -1
  346. package/dist/slices/narration/pauses-model.js +3 -2
  347. package/dist/slices/narration/peaks.js +3 -4
  348. package/dist/slices/narration/pronunciation-chunks.js +4 -3
  349. package/dist/slices/narration/pronunciation.js +6 -4
  350. package/dist/slices/narration/steering.js +4 -3
  351. package/dist/slices/notifications/notifier.js +4 -3
  352. package/dist/slices/notifications/rules.js +5 -2
  353. package/dist/slices/notifications/settings.js +4 -12
  354. package/dist/slices/notifications/subject.js +4 -3
  355. package/dist/slices/onboarding/copy.js +21 -3
  356. package/dist/slices/onboarding/first-run.js +16 -40
  357. package/dist/slices/onboarding/full-video.js +3 -2
  358. package/dist/slices/onboarding/install.js +6 -4
  359. package/dist/slices/onboarding/model.js +26 -37
  360. package/dist/slices/onboarding/packs.js +22 -22
  361. package/dist/slices/onboarding/preferred-model.js +14 -0
  362. package/dist/slices/onboarding/quick-short.js +105 -65
  363. package/dist/slices/onboarding/sample.js +4 -2
  364. package/dist/slices/onboarding/state.js +9 -11
  365. package/dist/slices/onboarding/template.js +8 -6
  366. package/dist/slices/outputs/add.js +3 -2
  367. package/dist/slices/outputs/service.js +2 -2
  368. package/dist/slices/patch-notes/library.js +4 -3
  369. package/dist/slices/play-drafts/convert.js +4 -0
  370. package/dist/slices/play-drafts/readiness.js +3 -3
  371. package/dist/slices/play-drafts/review-inputs.js +9 -3
  372. package/dist/slices/play-drafts/review.js +5 -4
  373. package/dist/slices/play-drafts/schema.js +4 -0
  374. package/dist/slices/play-drafts/service.js +17 -7
  375. package/dist/slices/project-templates/from-project.js +9 -2
  376. package/dist/slices/project-templates/next-chapter.js +2 -1
  377. package/dist/slices/project-templates/provider-defaults.js +22 -0
  378. package/dist/slices/project-templates/repo.js +6 -1
  379. package/dist/slices/project-templates/setup-sections.js +26 -0
  380. package/dist/slices/project-templates/setup.js +14 -1
  381. package/dist/slices/project-templates/stand-ins.js +22 -0
  382. package/dist/slices/rebuild/activity.js +2 -0
  383. package/dist/slices/rebuild/admission-repo.js +3 -2
  384. package/dist/slices/rebuild/narration-history.js +4 -5
  385. package/dist/slices/rebuild/narration-retry.js +2 -1
  386. package/dist/slices/rebuild/preview-details.js +32 -14
  387. package/dist/slices/rebuild/preview-plan.js +3 -8
  388. package/dist/slices/rebuild/recipe-build.js +8 -3
  389. package/dist/slices/rebuild/recipe-describe.js +3 -3
  390. package/dist/slices/rebuild/recipe-digest.js +58 -0
  391. package/dist/slices/rebuild/recipe-input-schema.js +10 -0
  392. package/dist/slices/rebuild/recipe-keywords.js +71 -0
  393. package/dist/slices/rebuild/recipe-legacy.js +5 -1
  394. package/dist/slices/rebuild/recipe-model.js +4 -0
  395. package/dist/slices/rebuild/recipe-narration-text.js +2 -1
  396. package/dist/slices/rebuild/recipe-preparation.js +4 -4
  397. package/dist/slices/rebuild/recipe-reference.js +8 -4
  398. package/dist/slices/rebuild/recipe-reviews.js +27 -7
  399. package/dist/slices/rebuild/recipe-save.js +8 -5
  400. package/dist/slices/rebuild/recipe-scenes.js +40 -11
  401. package/dist/slices/rebuild/recipe-shorts.js +8 -8
  402. package/dist/slices/rebuild/recipe-social.js +46 -0
  403. package/dist/slices/rebuild/recipe-text.js +64 -20
  404. package/dist/slices/rebuild/recipe-validation.js +102 -31
  405. package/dist/slices/rebuild/recipe-visual.js +55 -16
  406. package/dist/slices/rebuild/recipe-voices.js +3 -2
  407. package/dist/slices/rebuild/recipe-work.js +19 -7
  408. package/dist/slices/rebuild/recipe-youtube.js +4 -3
  409. package/dist/slices/rebuild/recovery-selection.js +3 -1
  410. package/dist/slices/rebuild/recovery.js +9 -8
  411. package/dist/slices/rebuild/remake-outdated.js +5 -5
  412. package/dist/slices/rebuild/repo.js +4 -3
  413. package/dist/slices/rebuild/review-promise.js +25 -0
  414. package/dist/slices/rebuild/review-redo.js +3 -2
  415. package/dist/slices/rebuild/runtime-admission.js +4 -3
  416. package/dist/slices/rebuild/runtime-agent-review.js +11 -5
  417. package/dist/slices/rebuild/runtime-animate.js +10 -9
  418. package/dist/slices/rebuild/runtime-article.js +7 -5
  419. package/dist/slices/rebuild/runtime-checkpoints.js +5 -4
  420. package/dist/slices/rebuild/runtime-document.js +11 -13
  421. package/dist/slices/rebuild/runtime-export-bed.js +8 -12
  422. package/dist/slices/rebuild/runtime-export-edit.js +8 -16
  423. package/dist/slices/rebuild/runtime-export-inputs.js +12 -11
  424. package/dist/slices/rebuild/runtime-export-short.js +9 -5
  425. package/dist/slices/rebuild/runtime-export.js +38 -15
  426. package/dist/slices/rebuild/runtime-figure-card.js +2 -1
  427. package/dist/slices/rebuild/runtime-image.js +8 -12
  428. package/dist/slices/rebuild/runtime-instructions.js +2 -0
  429. package/dist/slices/rebuild/runtime-keywords.js +59 -0
  430. package/dist/slices/rebuild/runtime-lines.js +2 -11
  431. package/dist/slices/rebuild/runtime-local.js +17 -22
  432. package/dist/slices/rebuild/runtime-narration-publication.js +2 -5
  433. package/dist/slices/rebuild/runtime-narration-reuse.js +9 -13
  434. package/dist/slices/rebuild/runtime-narration-text.js +13 -17
  435. package/dist/slices/rebuild/runtime-pictures.js +2 -4
  436. package/dist/slices/rebuild/runtime-piece-label.js +10 -6
  437. package/dist/slices/rebuild/runtime-plan.js +31 -5
  438. package/dist/slices/rebuild/runtime-provider.js +67 -25
  439. package/dist/slices/rebuild/runtime-publication.js +10 -9
  440. package/dist/slices/rebuild/runtime-review.js +39 -33
  441. package/dist/slices/rebuild/runtime-run.js +4 -1
  442. package/dist/slices/rebuild/runtime-shorts.js +31 -50
  443. package/dist/slices/rebuild/runtime-store.js +20 -10
  444. package/dist/slices/rebuild/runtime-subtitles.js +28 -25
  445. package/dist/slices/rebuild/runtime-voices.js +10 -16
  446. package/dist/slices/rebuild/runtime-youtube.js +14 -31
  447. package/dist/slices/rebuild/service-readiness.js +11 -3
  448. package/dist/slices/rebuild/transition-repo.js +6 -5
  449. package/dist/slices/rebuild/work-records.js +6 -0
  450. package/dist/slices/reruns/cascade.js +1 -2
  451. package/dist/slices/reruns/index.js +6 -9
  452. package/dist/slices/research/synthesis.js +3 -2
  453. package/dist/slices/reviews/external-model.js +4 -1
  454. package/dist/slices/reviews/external-repo.js +2 -1
  455. package/dist/slices/reviews/external-rows.js +2 -3
  456. package/dist/slices/reviews/holds.js +5 -4
  457. package/dist/slices/reviews/model.js +32 -11
  458. package/dist/slices/reviews/repo.js +2 -1
  459. package/dist/slices/reviews/rules.js +4 -3
  460. package/dist/slices/reviews/verdict.js +2 -1
  461. package/dist/slices/reviews/view.js +5 -2
  462. package/dist/slices/revisions/downloads.js +4 -5
  463. package/dist/slices/revisions/image-plan.js +1 -1
  464. package/dist/slices/revisions/mutation-assets.js +9 -5
  465. package/dist/slices/revisions/mutation-cues.js +2 -5
  466. package/dist/slices/revisions/mutations.js +3 -3
  467. package/dist/slices/revisions/repo.js +3 -1
  468. package/dist/slices/revisions/schema.js +1 -0
  469. package/dist/slices/revisions/view.js +20 -0
  470. package/dist/slices/run-cost/limits.js +5 -2
  471. package/dist/slices/run-cost/meter.js +12 -5
  472. package/dist/slices/run-cost/panel.js +8 -74
  473. package/dist/slices/run-cost/plan-readings.js +127 -0
  474. package/dist/slices/run-cost/plan-use.js +169 -0
  475. package/dist/slices/run-cost/pricing.js +3 -3
  476. package/dist/slices/run-cost/week.js +32 -4
  477. package/dist/slices/schedules/agenda.js +18 -7
  478. package/dist/slices/schedules/by-date.js +42 -0
  479. package/dist/slices/schedules/calendar.js +5 -0
  480. package/dist/slices/schedules/design-agenda.js +36 -0
  481. package/dist/slices/schedules/design-check.js +41 -0
  482. package/dist/slices/schedules/design-run.js +126 -0
  483. package/dist/slices/schedules/next-run.js +62 -0
  484. package/dist/slices/schedules/prepare.js +18 -2
  485. package/dist/slices/schedules/repo.js +30 -21
  486. package/dist/slices/schedules/rescore.js +35 -0
  487. package/dist/slices/schedules/scheduler.js +13 -3
  488. package/dist/slices/schedules/schema.js +57 -3
  489. package/dist/slices/schedules/score.js +107 -0
  490. package/dist/slices/schedules/service.js +57 -24
  491. package/dist/slices/schedules/topic-list.js +15 -0
  492. package/dist/slices/schedules/topic-scores.js +104 -0
  493. package/dist/slices/schedules/topics.js +53 -41
  494. package/dist/slices/settings/cli-paths.js +4 -6
  495. package/dist/slices/settings/first-run.js +8 -43
  496. package/dist/slices/settings/health.js +30 -15
  497. package/dist/slices/settings/key-test.js +1 -1
  498. package/dist/slices/settings/model-reach.js +3 -17
  499. package/dist/slices/settings/model.js +14 -2
  500. package/dist/slices/settings/playback.js +34 -23
  501. package/dist/slices/settings/probe-read.js +16 -0
  502. package/dist/slices/settings/repo.js +33 -0
  503. package/dist/slices/settings/tutorial.js +2 -2
  504. package/dist/slices/settings/voices.js +4 -12
  505. package/dist/slices/shorts/keep.js +2 -1
  506. package/dist/slices/shorts/pick.js +6 -18
  507. package/dist/slices/shorts/prompts.js +4 -14
  508. package/dist/slices/shorts/render.js +6 -2
  509. package/dist/slices/social/channel.js +44 -0
  510. package/dist/slices/social/defaults.js +17 -0
  511. package/dist/slices/social/due.js +36 -0
  512. package/dist/slices/social/extension.js +18 -0
  513. package/dist/slices/social/fit.js +115 -0
  514. package/dist/slices/social/limits.js +186 -0
  515. package/dist/slices/social/links.js +21 -0
  516. package/dist/slices/social/media.js +132 -0
  517. package/dist/slices/social/model.js +75 -0
  518. package/dist/slices/social/notice.js +19 -0
  519. package/dist/slices/social/pack.js +176 -0
  520. package/dist/slices/social/post-prompt.js +56 -0
  521. package/dist/slices/social/queue.js +31 -0
  522. package/dist/slices/social/repo.js +133 -0
  523. package/dist/slices/social/reshape.js +97 -0
  524. package/dist/slices/social/rules.js +5 -0
  525. package/dist/slices/social/schema.js +70 -0
  526. package/dist/slices/social/serve.js +51 -0
  527. package/dist/slices/social/service.js +129 -0
  528. package/dist/slices/social/settings.js +21 -0
  529. package/dist/slices/social/sources.js +114 -0
  530. package/dist/slices/social/state.js +110 -0
  531. package/dist/slices/social/text.js +149 -0
  532. package/dist/slices/storage/arrange.js +3 -1
  533. package/dist/slices/storage/assets.js +8 -10
  534. package/dist/slices/storage/backup-designs.js +74 -0
  535. package/dist/slices/storage/backup-export.js +8 -3
  536. package/dist/slices/storage/backup-format.js +10 -0
  537. package/dist/slices/storage/backup-import.js +22 -4
  538. package/dist/slices/storage/delete-project.js +6 -5
  539. package/dist/slices/storage/files-location.js +6 -8
  540. package/dist/slices/storage/layout.js +13 -2
  541. package/dist/slices/storage/model.js +3 -0
  542. package/dist/slices/storage/portable.js +17 -12
  543. package/dist/slices/storage/schema.js +2 -0
  544. package/dist/slices/storage/staging-refs.js +2 -1
  545. package/dist/slices/storage/staging.js +6 -9
  546. package/dist/slices/storage/trim.js +26 -9
  547. package/dist/slices/studio/calendar.js +7 -2
  548. package/dist/slices/studio/disclosure.js +4 -4
  549. package/dist/slices/studio/model.js +1 -1
  550. package/dist/slices/studio/pack.js +9 -8
  551. package/dist/slices/studio/pick.js +2 -11
  552. package/dist/slices/studio/plan.js +7 -16
  553. package/dist/slices/studio/queue.js +3 -14
  554. package/dist/slices/studio/releases.js +26 -0
  555. package/dist/slices/studio/settings.js +20 -57
  556. package/dist/slices/studio/videos.js +35 -4
  557. package/dist/slices/style-preview/render.js +37 -16
  558. package/dist/slices/style-preview/schema.js +14 -1
  559. package/dist/slices/style-preview/service.js +2 -1
  560. package/dist/slices/style-preview/settings.js +33 -5
  561. package/dist/slices/subtitles/captions.js +1 -1
  562. package/dist/slices/telemetry/collector-client.js +2 -4
  563. package/dist/slices/telemetry/flush.js +2 -4
  564. package/dist/slices/telemetry/model.js +0 -7
  565. package/dist/slices/telemetry/record.js +10 -3
  566. package/dist/slices/template-studio/anatomy-view.js +161 -0
  567. package/dist/slices/template-studio/anatomy.js +73 -0
  568. package/dist/slices/template-studio/bakeoff-make.js +225 -0
  569. package/dist/slices/template-studio/bakeoff-repo.js +83 -0
  570. package/dist/slices/template-studio/bakeoff.js +333 -0
  571. package/dist/slices/template-studio/budget.js +106 -0
  572. package/dist/slices/template-studio/cards.js +78 -0
  573. package/dist/slices/template-studio/checks.js +322 -0
  574. package/dist/slices/template-studio/document-sample.js +56 -0
  575. package/dist/slices/template-studio/edit.js +15 -0
  576. package/dist/slices/template-studio/for-all.js +161 -0
  577. package/dist/slices/template-studio/free-video.js +31 -0
  578. package/dist/slices/template-studio/free.js +176 -0
  579. package/dist/slices/template-studio/gate.js +40 -0
  580. package/dist/slices/template-studio/hidden.js +20 -0
  581. package/dist/slices/template-studio/jobs.js +79 -0
  582. package/dist/slices/template-studio/loudness.js +111 -0
  583. package/dist/slices/template-studio/make.js +40 -0
  584. package/dist/slices/template-studio/model.js +58 -0
  585. package/dist/slices/template-studio/pack-import.js +253 -0
  586. package/dist/slices/template-studio/pack-samples.js +60 -0
  587. package/dist/slices/template-studio/pack.js +207 -0
  588. package/dist/slices/template-studio/paid-view.js +66 -0
  589. package/dist/slices/template-studio/paid.js +355 -0
  590. package/dist/slices/template-studio/quote.js +155 -0
  591. package/dist/slices/template-studio/ready.js +104 -0
  592. package/dist/slices/template-studio/repo.js +134 -0
  593. package/dist/slices/template-studio/reviews-path.js +58 -0
  594. package/dist/slices/template-studio/runner.js +84 -0
  595. package/dist/slices/template-studio/save.js +236 -0
  596. package/dist/slices/template-studio/say-it-as.js +248 -0
  597. package/dist/slices/template-studio/schedule-gate.js +34 -0
  598. package/dist/slices/template-studio/schedule-price.js +32 -0
  599. package/dist/slices/template-studio/schedule-sample.js +91 -0
  600. package/dist/slices/template-studio/schema.js +243 -0
  601. package/dist/slices/template-studio/scope.js +124 -0
  602. package/dist/slices/template-studio/sections.js +176 -0
  603. package/dist/slices/template-studio/service.js +175 -0
  604. package/dist/slices/template-studio/status.js +191 -0
  605. package/dist/slices/template-studio/topic.js +223 -0
  606. package/dist/slices/thumbnail/by-llm.js +1 -1
  607. package/dist/slices/trash/designs.js +76 -0
  608. package/dist/slices/trash/model.js +13 -4
  609. package/dist/slices/trash/service.js +52 -2
  610. package/dist/slices/tutorials/library.js +3 -2
  611. package/dist/slices/uploads/repo.js +37 -1
  612. package/dist/slices/uploads/rules.js +3 -2
  613. package/dist/slices/video/ass-text.js +17 -0
  614. package/dist/slices/video/audio-export.js +2 -64
  615. package/dist/slices/video/edit-list.js +2 -2
  616. package/dist/slices/video/edit-settings.js +1 -1
  617. package/dist/slices/video/encoding.js +169 -0
  618. package/dist/slices/video/ffmpeg.js +23 -21
  619. package/dist/slices/video/figure-card.js +1 -15
  620. package/dist/slices/video/plan.js +2 -1
  621. package/dist/slices/video/slideshow.js +43 -18
  622. package/dist/slices/voices/attribution.js +3 -2
  623. package/dist/slices/voices/model.js +9 -8
  624. package/dist/slices/voices/palette.js +0 -3
  625. package/dist/slices/voices/script.js +2 -1
  626. package/dist/slices/youtube/answer.js +4 -16
  627. package/dist/slices/youtube/edits-repo.js +3 -12
  628. package/dist/tutorials/AI-CLIs.md +25 -25
  629. package/dist/tutorials/Agents-MCP.md +34 -33
  630. package/dist/tutorials/Assistant.md +42 -0
  631. package/dist/tutorials/Backups.md +7 -7
  632. package/dist/tutorials/Calendar.md +17 -25
  633. package/dist/tutorials/Cast-Library.md +19 -19
  634. package/dist/tutorials/Channels.md +42 -35
  635. package/dist/tutorials/Costs-and-Run-Cost.md +38 -40
  636. package/dist/tutorials/Create-Article.md +114 -0
  637. package/dist/tutorials/Create-Extras.md +112 -0
  638. package/dist/tutorials/Create-Images.md +165 -0
  639. package/dist/tutorials/Create-Narration.md +178 -0
  640. package/dist/tutorials/Create-Overview.md +244 -0
  641. package/dist/tutorials/Create-Video-and-Style.md +144 -0
  642. package/dist/tutorials/Docker.md +3 -3
  643. package/dist/tutorials/Document-Themes.md +32 -32
  644. package/dist/tutorials/Editing-a-Project.md +94 -94
  645. package/dist/tutorials/FAQ.md +18 -18
  646. package/dist/tutorials/First-Launch-and-Welcome.md +50 -64
  647. package/dist/tutorials/Home-and-Projects.md +115 -71
  648. package/dist/tutorials/Home.md +33 -33
  649. package/dist/tutorials/Install.md +14 -13
  650. package/dist/tutorials/Intros-and-Outros.md +33 -34
  651. package/dist/tutorials/Keyboard-Shortcuts-and-Command-Palette.md +62 -58
  652. package/dist/tutorials/Keywords-Slopify-Fills.md +87 -0
  653. package/dist/tutorials/Models.md +53 -21
  654. package/dist/tutorials/Multiple-Voices.md +41 -40
  655. package/dist/tutorials/Narration-Aliases-and-Glossary.md +14 -14
  656. package/dist/tutorials/Notifications.md +27 -17
  657. package/dist/tutorials/Other-Languages.md +15 -15
  658. package/dist/tutorials/PDF-Documents.md +38 -29
  659. package/dist/tutorials/Posting-to-Social-Sites.md +121 -0
  660. package/dist/tutorials/Project-Page.md +118 -120
  661. package/dist/tutorials/Prompts-and-Templates.md +84 -0
  662. package/dist/tutorials/Prompts.md +48 -44
  663. package/dist/tutorials/Providers-and-Keys.md +105 -98
  664. package/dist/tutorials/Publishing-to-YouTube.md +31 -31
  665. package/dist/tutorials/Recovery-and-Retries.md +31 -31
  666. package/dist/tutorials/Remote-Access.md +63 -0
  667. package/dist/tutorials/Reviews-and-Checkpoints.md +98 -90
  668. package/dist/tutorials/Schedules.md +46 -27
  669. package/dist/tutorials/Settings-Reference.md +194 -174
  670. package/dist/tutorials/Shorts.md +34 -33
  671. package/dist/tutorials/Start-at-Login.md +3 -3
  672. package/dist/tutorials/Studio-Extension.md +22 -24
  673. package/dist/tutorials/Template-Studio.md +128 -0
  674. package/dist/tutorials/Templates.md +51 -77
  675. package/dist/tutorials/Trash.md +4 -4
  676. package/dist/tutorials/Troubleshooting.md +44 -44
  677. package/dist/tutorials/Uninstalling-and-Moving.md +5 -5
  678. package/dist/tutorials/Updating-and-Patch-Notes.md +18 -18
  679. package/dist/tutorials/Video-Editing.md +34 -34
  680. package/dist/tutorials/Where-Your-Files-Live.md +10 -10
  681. package/dist/tutorials/YouTube-Description.md +26 -26
  682. package/dist/tutorials/Your-First-Short.md +35 -35
  683. package/dist/tutorials/_Sidebar.md +19 -14
  684. package/dist/updater/work-in-progress.js +42 -12
  685. package/dist/web/assets/index-BNftKQrA.css +1 -0
  686. package/dist/web/assets/index-Cpa58woP.js +459 -0
  687. package/dist/web/assets/pdf-BKh8f7R6.js +56 -0
  688. package/dist/web/assets/pdf.worker.min-BmVo14Nb.mjs +28 -0
  689. package/dist/web/assets/pdf.worker.min-D7i8o3wR.js +1 -0
  690. package/dist/web/index.html +2 -2
  691. package/package.json +6 -2
  692. package/dist/slices/article/provided-entries.js +0 -66
  693. package/dist/slices/article/run.js +0 -145
  694. package/dist/slices/images/run.js +0 -234
  695. package/dist/slices/narration/legacy-plan.js +0 -58
  696. package/dist/slices/narration/run.js +0 -270
  697. package/dist/slices/rebuild/runtime-actions.js +0 -90
  698. package/dist/slices/research/run.js +0 -224
  699. package/dist/slices/subtitles/prepare.js +0 -194
  700. package/dist/slices/subtitles/transcript.js +0 -34
  701. package/dist/slices/thumbnail/run.js +0 -219
  702. package/dist/slices/video/audio-inputs.js +0 -33
  703. package/dist/slices/video/reuse-audio.js +0 -62
  704. package/dist/slices/video/run.js +0 -78
  705. package/dist/slices/video/write-export.js +0 -158
  706. package/dist/slices/video/write-subtitles.js +0 -59
  707. package/dist/tutorials/Library-Overview.md +0 -76
  708. package/dist/tutorials/Play-Images.md +0 -161
  709. package/dist/tutorials/Play-Narration.md +0 -167
  710. package/dist/tutorials/Play-Outputs.md +0 -109
  711. package/dist/tutorials/Play-Overview.md +0 -227
  712. package/dist/tutorials/Play-Title-and-Article.md +0 -136
  713. package/dist/tutorials/Play-Video-and-Style.md +0 -143
  714. package/dist/web/assets/index-BadsoORk.css +0 -1
  715. package/dist/web/assets/index-D8LqNsCl.js +0 -326
  716. package/dist/web/assets/pdf-T7MCwjIv.js +0 -54
  717. package/dist/web/assets/pdf.worker.min-Dswkl-cV.mjs +0 -29
  718. package/dist/web/assets/pdf.worker.min-zC6nfbxG.js +0 -1
@@ -0,0 +1,80 @@
1
+ // Filling the keywords Slopify fills into a prompt that `render` has already filled with the
2
+ // person's own values, so a value they gave a `Slopify_` name still wins. A body with no
3
+ // keyword comes back as the very same string. Browser-safe.
4
+ import { keywordOf } from "./specs.js";
5
+ const slot = /\{\{([^{}\n]*)\}\}/g;
6
+ // Filled elsewhere: each picture's own keywords by the pictures, the release date and the length
7
+ // when the step runs.
8
+ const elsewhere = ["scenes", "appearance", "release", "duration"];
9
+ export function mentionsKeyword(body) {
10
+ for (const match of body.matchAll(slot))
11
+ if (keywordOf((match[1] ?? "").trim())?.name === (match[1] ?? "").trim())
12
+ return true;
13
+ return false;
14
+ }
15
+ export function fillKeywords(body, place, values) {
16
+ return fillWith(body, (name) => {
17
+ const spec = keywordOf(name);
18
+ if (spec === undefined || spec.name !== name || !spec.places.includes(place))
19
+ return undefined;
20
+ if (elsewhere.includes(spec.filler))
21
+ return undefined;
22
+ return Object.hasOwn(values, name) ? (values[name] ?? "") : null;
23
+ });
24
+ }
25
+ // The release date and the length, filled when the step runs: they are left in the planned
26
+ // request, so a later change to either never makes anything outdated.
27
+ export function fillLateKeywords(text, late) {
28
+ const filled = fillWith(text, (name) => name === "Slopify_Release_Date"
29
+ ? (late.releaseDate ?? "")
30
+ : name === "Slopify_Duration"
31
+ ? (late.duration ?? "")
32
+ : undefined);
33
+ return filled.ok ? filled.text : text;
34
+ }
35
+ export function mentionsLateKeyword(text) {
36
+ return text.includes("Slopify_Release_Date") || text.includes("Slopify_Duration");
37
+ }
38
+ // `valueFor` answers a string to fill (an empty one leaves its line out), null for a keyword
39
+ // still waiting, and undefined for a name to leave as written.
40
+ export function fillWith(body, valueFor) {
41
+ const waiting = [];
42
+ const blank = [];
43
+ let touched = false;
44
+ for (const match of body.matchAll(slot)) {
45
+ const name = (match[1] ?? "").trim();
46
+ const value = valueFor(name);
47
+ if (value === undefined)
48
+ continue;
49
+ touched = true;
50
+ if (value === null && !waiting.includes(name))
51
+ waiting.push(name);
52
+ if (value === "" && !blank.includes(name))
53
+ blank.push(name);
54
+ }
55
+ if (!touched)
56
+ return { ok: true, text: body };
57
+ if (waiting.length > 0)
58
+ return { ok: false, waiting };
59
+ const kept = blank.length === 0
60
+ ? body
61
+ : body
62
+ .split("\n")
63
+ .filter((line) => !blank.some((name) => holds(line, name)))
64
+ .join("\n")
65
+ .replace(/\n{3,}/g, "\n\n")
66
+ .trim();
67
+ return {
68
+ ok: true,
69
+ text: kept.replace(slot, (whole, inside) => {
70
+ const value = valueFor(inside.trim());
71
+ return value === undefined || value === null ? whole : value;
72
+ }),
73
+ };
74
+ }
75
+ function holds(line, name) {
76
+ for (const match of line.matchAll(slot))
77
+ if ((match[1] ?? "").trim() === name)
78
+ return true;
79
+ return false;
80
+ }
@@ -0,0 +1,75 @@
1
+ // The keywords Slopify fills itself: never fields for the person, always written with the
2
+ // reserved `Slopify_` prefix so they never take a name a template already uses. One table
3
+ // says, for each, what fills it, where it works and what it costs; the editor's Insert bar,
4
+ // its hover cards, the help tips, the lint and the fillers all read it. Browser-safe: the
5
+ // editor imports it.
6
+ // Where a keyword can appear: the prompt kinds, the intro and outro entries, and the title.
7
+ export const keywordPlaces = [
8
+ "title",
9
+ "article",
10
+ "script",
11
+ "narration",
12
+ "intro",
13
+ "outro",
14
+ "image",
15
+ "thumbnail",
16
+ "description",
17
+ "shorts",
18
+ "review",
19
+ // A Library prompt that writes a post for another site (`slices/social`).
20
+ "post",
21
+ ];
22
+ // What fills a keyword: facts copied when the run starts, the release date read when the step
23
+ // runs, the article's chapter titles, the finished length, the shared digest call, the scenes
24
+ // call and the appearance lookup.
25
+ export const fillerKinds = [
26
+ "facts",
27
+ "release",
28
+ "chapters",
29
+ "duration",
30
+ "digest",
31
+ "scenes",
32
+ "appearance",
33
+ ];
34
+ // Free, or part of one AI call per run (shared by every keyword with the same cost).
35
+ export const keywordCosts = ["free", "digest", "scenes", "appearance"];
36
+ export const reservedPrefix = "Slopify_";
37
+ // The whole prefix is Slopify's, whatever its case, so a near miss never turns into a field
38
+ // that a later keyword would take over.
39
+ export function isReserved(name) {
40
+ return name.toLowerCase().startsWith(reservedPrefix.toLowerCase());
41
+ }
42
+ // What a keyword's cost says in the Insert bar.
43
+ export function costLabel(cost) {
44
+ switch (cost) {
45
+ case "free":
46
+ return "Free: no AI call.";
47
+ case "digest":
48
+ return "Part of one AI call per run: the keyword digest, shared by every digest keyword.";
49
+ case "scenes":
50
+ return "Part of one AI call per run: the scenes call, shared by every picture.";
51
+ case "appearance":
52
+ return "Part of one AI call per run: the appearance lookup, with web search.";
53
+ }
54
+ }
55
+ // How the editor names a place: the prompt kinds and the two entry categories.
56
+ export const placeLabels = {
57
+ title: "Title",
58
+ article: "Article",
59
+ script: "Script",
60
+ narration: "Narration",
61
+ intro: "Intro",
62
+ outro: "Outro",
63
+ image: "Image",
64
+ thumbnail: "Thumbnail",
65
+ description: "Description",
66
+ shorts: "Shorts",
67
+ review: "Review",
68
+ post: "Post",
69
+ };
70
+ // "A, B and C".
71
+ export function listOf(words) {
72
+ if (words.length <= 1)
73
+ return words.join("");
74
+ return `${words.slice(0, -1).join(", ")} and ${words.at(-1) ?? ""}`;
75
+ }
@@ -0,0 +1,187 @@
1
+ // What the editor and Play say about the keywords in one body: a `Slopify_` name that is no
2
+ // keyword, a keyword where it can't be filled, and an old name that still works. Browser-safe.
3
+ import { detectSlots } from "../admission/substitute.js";
4
+ import { isReserved, listOf, placeLabels, reservedPrefix, } from "./model.js";
5
+ import { keywordOf, keywordSpecs, legacyNames } from "./specs.js";
6
+ export const keywordProblemKinds = ["unknown", "wrong-place", "legacy"];
7
+ // The same well-formed slot the parser reads (`admission/substitute.ts`).
8
+ const slot = /\{\{([^{}\n]*)\}\}/g;
9
+ // Unknown names already in the stored prompt are let through, so a prompt saved before the
10
+ // prefix was reserved still saves.
11
+ export function keywordProblems(body, place, grandfathered = []) {
12
+ const problems = [];
13
+ for (const match of body.matchAll(slot)) {
14
+ const name = (match[1] ?? "").trim();
15
+ if (name === "")
16
+ continue;
17
+ const at = match.index;
18
+ const where = `{{${name}}} at ${positionOf(body, at)}`;
19
+ const spec = keywordOf(name);
20
+ if (spec === undefined) {
21
+ if (isReserved(name) && !grandfathered.includes(name))
22
+ problems.push({
23
+ kind: "unknown",
24
+ name,
25
+ at,
26
+ message: `${where} isn't a keyword Slopify fills: names starting with ${reservedPrefix} are Slopify's own. Rename it, e.g. {{${name.slice(reservedPrefix.length) || "Topic"}}}, or insert a keyword from the Insert bar above the text.`,
27
+ });
28
+ continue;
29
+ }
30
+ const legacy = spec.legacy === name;
31
+ if (!spec.places.includes(place)) {
32
+ // An old name outside the picture prompts was plain text before the keywords, and still is.
33
+ if (legacy)
34
+ continue;
35
+ problems.push({ kind: "wrong-place", name, at, message: wrongPlace(where, spec, place) });
36
+ continue;
37
+ }
38
+ if (legacy)
39
+ problems.push({
40
+ kind: "legacy",
41
+ name,
42
+ at,
43
+ message: `${where} is the old name of {{${spec.name}}}. It keeps working; use Update to new names in the editor to rename it.`,
44
+ });
45
+ }
46
+ return problems;
47
+ }
48
+ function wrongPlace(where, spec, place) {
49
+ if (place === "title")
50
+ return `${where} can't be used in the title: Slopify fills its keywords from the title, so the title can't use them. Remove it, or use a keyword of your own such as {{${spec.name.slice(reservedPrefix.length)}}}.`;
51
+ const works = listOf(spec.places.map((one) => placeLabels[one]));
52
+ return `${where} can't be used in ${placeName(place)}: ${why(spec, place)}. Remove it; it works in ${works}.`;
53
+ }
54
+ function why(spec, place) {
55
+ if ((place === "article" || place === "script") && spec.places.includes("narration"))
56
+ return "it exists once the article is written, so never in the Article or Script prompt";
57
+ switch (spec.filler) {
58
+ case "digest":
59
+ return place === "article" || place === "script"
60
+ ? "it is written from the article, which doesn't exist yet when this prompt runs"
61
+ : "Slopify writes it for pictures, descriptions, shorts and reviews only";
62
+ case "duration":
63
+ return "the video's length is known only once the narration is finished";
64
+ case "scenes":
65
+ case "appearance":
66
+ return "it describes one picture, so it works only in picture prompts";
67
+ default:
68
+ return "it describes how pictures look, so it works only in picture prompts";
69
+ }
70
+ }
71
+ function placeName(place) {
72
+ const label = placeLabels[place];
73
+ const article = /^[AEIOU]/.test(label) ? "an" : "a";
74
+ return place === "intro" || place === "outro"
75
+ ? `${article} ${label} entry`
76
+ : `${article} ${label} prompt`;
77
+ }
78
+ // The old names a body uses, in first-appearance order.
79
+ export function usesLegacy(body) {
80
+ const found = [];
81
+ for (const match of body.matchAll(slot)) {
82
+ const name = (match[1] ?? "").trim();
83
+ if (legacyNames.includes(name) && !found.includes(name))
84
+ found.push(name);
85
+ }
86
+ return found;
87
+ }
88
+ // The body with one old name written as its new one. Appearance means the same under both
89
+ // names; Scene's new name turns scenes on for that picture, which is why each is its own choice.
90
+ export function upgradeLegacy(body, which) {
91
+ const spec = keywordOf(which);
92
+ if (spec === undefined || spec.legacy !== which)
93
+ return body;
94
+ return body.replace(slot, (whole, inside) => inside.trim() === which ? `{{${spec.name}}}` : whole);
95
+ }
96
+ // The place a rendered prompt key fills (`library/slots.ts` names them).
97
+ export function placeOfKey(key, options = {}) {
98
+ if (key === "article")
99
+ return options.script === true ? "script" : "article";
100
+ if (key === "narration" || key === "intro" || key === "outro")
101
+ return key;
102
+ if (key === "description" || key === "shorts")
103
+ return key;
104
+ if (key === "shortsImage" || key === "referencePrompt" || /^imagePrompts\.\d+$/.test(key))
105
+ return "image";
106
+ if (key === "thumbnailPrompt")
107
+ return "thumbnail";
108
+ if (key.startsWith("review."))
109
+ return "review";
110
+ if (key.startsWith("social."))
111
+ return "post";
112
+ return undefined;
113
+ }
114
+ // The parser reports a character offset; a person editing a textarea counts lines and columns.
115
+ export function positionOf(body, at) {
116
+ const before = body.slice(0, at);
117
+ const lastBreak = before.lastIndexOf("\n");
118
+ const line = before.split("\n").length;
119
+ const column = at - lastBreak;
120
+ return `line ${String(line)}, column ${String(column)}`;
121
+ }
122
+ // The keywords filled from the facts a run copies when it starts (`facts.ts`).
123
+ const factNames = keywordSpecs
124
+ .filter((spec) => spec.filler === "facts" && spec.name !== "Slopify_Title")
125
+ .map((spec) => spec.name);
126
+ // Whether any of the bodies asks for a fact Slopify copies (the title is the project's own).
127
+ export function usesFacts(bodies) {
128
+ return bodies.some((body) => detectSlots(body).names.some((name) => factNames.includes(name)));
129
+ }
130
+ export function keywordUsesOf(bodies) {
131
+ let digest;
132
+ let chapters;
133
+ let scenes;
134
+ for (const { field, place, body } of bodies)
135
+ for (const name of detectSlots(body).names) {
136
+ const spec = keywordOf(name);
137
+ if (spec === undefined || spec.name !== name || !spec.places.includes(place))
138
+ continue;
139
+ if (spec.filler === "digest")
140
+ digest ??= field;
141
+ if (spec.filler === "chapters")
142
+ chapters ??= field;
143
+ if (spec.filler === "scenes")
144
+ scenes ??= field;
145
+ }
146
+ return {
147
+ ...(digest === undefined ? {} : { digest }),
148
+ ...(chapters === undefined ? {} : { chapters }),
149
+ ...(scenes === undefined ? {} : { scenes }),
150
+ };
151
+ }
152
+ // What stops a run: a keyword in a prompt that runs where it can't be filled. A name the person
153
+ // gave a value of their own is theirs (a prompt saved before the prefix was reserved), and an
154
+ // unknown `Slopify_` name stays an ordinary keyword to fill in.
155
+ export function placedProblems(bodies, values) {
156
+ const problems = [];
157
+ const seen = new Set();
158
+ for (const { field, place, body } of bodies)
159
+ for (const problem of keywordProblems(body, place)) {
160
+ if (problem.kind !== "wrong-place" || Object.hasOwn(values, problem.name))
161
+ continue;
162
+ const key = `${field}\0${problem.name}`;
163
+ if (seen.has(key))
164
+ continue;
165
+ seen.add(key);
166
+ problems.push({
167
+ field,
168
+ message: place === "title"
169
+ ? problem.message
170
+ : `${problem.message} Change the prompt in Prompts, or pick another one.`,
171
+ });
172
+ }
173
+ return problems;
174
+ }
175
+ // A Text-mode intro or outro is narrated as written, and the release date is only filled into a
176
+ // request as it is sent to the AI model (`rebuild/runtime-keywords.ts`), so a Text entry can't
177
+ // say it.
178
+ export function textEntryProblems(body, category) {
179
+ return detectSlots(body).names.includes("Slopify_Release_Date")
180
+ ? [
181
+ {
182
+ field: category,
183
+ message: `{{Slopify_Release_Date}} can't be used in an ${category} that says these exact words: those are narrated as written, and the release date is only filled in when a step asks the AI model. In Prompts → Intros and outros, set this ${category}'s What the narrator reads to Let the AI write it from these instructions, or remove the keyword.`,
184
+ },
185
+ ]
186
+ : [];
187
+ }
@@ -0,0 +1,28 @@
1
+ import { z } from "zod";
2
+ // `values.ts`'s KeywordFacts, as a saved config holds it. Edit project sends it back with the
3
+ // rest of the config, so it is bounded like any other part of a draft.
4
+ const text = z.string().max(10_000);
5
+ export const keywordFactsSchema = z.object({
6
+ channel: text.optional(),
7
+ series: text.optional(),
8
+ links: z
9
+ .array(z.object({ name: text, url: text }))
10
+ .max(200)
11
+ .readonly()
12
+ .optional(),
13
+ previousVideo: z.object({ title: text, url: text.optional() }).optional(),
14
+ nextVideo: z.object({ title: text }).optional(),
15
+ cast: z
16
+ .array(z.object({ name: text, description: text }))
17
+ .max(500)
18
+ .readonly()
19
+ .optional(),
20
+ coveredBefore: z.array(text).max(500).readonly().optional(),
21
+ episode: z.number().int().min(1).optional(),
22
+ brand: z
23
+ .object({
24
+ colours: z.array(text).max(10).readonly(),
25
+ fonts: z.array(text).max(10).readonly(),
26
+ })
27
+ .optional(),
28
+ });
@@ -0,0 +1,260 @@
1
+ // The keywords themselves, in the order the Insert bar and the wiki list them.
2
+ import { keywordPlaces } from "./model.js";
3
+ const everywhere = keywordPlaces.filter((place) => place !== "title");
4
+ const afterArticle = everywhere.filter((place) => place !== "article" && place !== "script");
5
+ const pictures = ["image", "thumbnail"];
6
+ const fromDigest = [
7
+ "image",
8
+ "thumbnail",
9
+ "description",
10
+ "shorts",
11
+ "review",
12
+ "post",
13
+ ];
14
+ const atStart = "When the run starts; later changes don't change this project.";
15
+ const digestAvailable = "Once the article is written: one shared AI call writes every digest keyword the run uses.";
16
+ const sceneAvailable = "Once the article is written: the scenes call writes one for each picture, even with Scenes from the article off.";
17
+ export const keywordSpecs = [
18
+ {
19
+ name: "Slopify_Title",
20
+ filler: "facts",
21
+ fills: "The video's title, with its keywords filled in.",
22
+ example: "How Lighthouses Were Built on Bare Rock",
23
+ available: atStart,
24
+ places: everywhere,
25
+ cost: "free",
26
+ batch: 1,
27
+ },
28
+ {
29
+ name: "Slopify_Channel",
30
+ filler: "facts",
31
+ fills: "The name of the project's channel.",
32
+ example: "Quiet Histories",
33
+ available: atStart,
34
+ places: everywhere,
35
+ cost: "free",
36
+ batch: 1,
37
+ },
38
+ {
39
+ name: "Slopify_Series",
40
+ filler: "facts",
41
+ fills: "The channel's series brief, from the channel's page under Name and look. A line with an empty brief is left out.",
42
+ example: "Calm histories of how things were made, one invention at a time.",
43
+ available: atStart,
44
+ places: everywhere,
45
+ cost: "free",
46
+ batch: 2,
47
+ },
48
+ {
49
+ name: "Slopify_Chapters",
50
+ filler: "chapters",
51
+ fills: "The article's chapter titles, one per line.",
52
+ example: "The first lamps\nBuilding on bare rock\nThe last keepers",
53
+ available: "Once the article is written, so never in the Article or Script prompt.",
54
+ places: afterArticle,
55
+ cost: "free",
56
+ batch: 1,
57
+ },
58
+ {
59
+ name: "Slopify_Links",
60
+ filler: "facts",
61
+ fills: "The channel's links, one per line as name and address. In a Description prompt they stay links the page fills when it shows the description.",
62
+ example: "Website: https://example.com\nPatreon: https://patreon.com/example",
63
+ available: atStart,
64
+ places: everywhere,
65
+ cost: "free",
66
+ batch: 1,
67
+ },
68
+ {
69
+ name: "Slopify_Previous_Video",
70
+ filler: "facts",
71
+ fills: "The title and link of the channel's previous video in the same series. A line with none is left out; in a Description prompt it stays the Previous video link.",
72
+ example: "The Canal Age – https://youtu.be/abc123",
73
+ available: atStart,
74
+ places: everywhere,
75
+ cost: "free",
76
+ batch: 1,
77
+ },
78
+ {
79
+ name: "Slopify_Next_Video",
80
+ filler: "facts",
81
+ fills: "The title of the next planned video in the same series and posting plan line. A line with none is left out; in a Description prompt it stays the Next video link.",
82
+ example: "Tea Clippers and the Race Home",
83
+ available: atStart,
84
+ places: everywhere,
85
+ cost: "free",
86
+ batch: 1,
87
+ },
88
+ {
89
+ name: "Slopify_Release_Date",
90
+ filler: "release",
91
+ fills: "The release date from the posting plan. A line with no date is left out; moving the date later makes nothing again.",
92
+ example: "Thursday 22 October 2026",
93
+ available: "When the step runs.",
94
+ places: everywhere,
95
+ cost: "free",
96
+ batch: 2,
97
+ },
98
+ {
99
+ name: "Slopify_Episode",
100
+ filler: "facts",
101
+ fills: "This video's number in its series on the channel.",
102
+ example: "7",
103
+ available: atStart,
104
+ places: everywhere,
105
+ cost: "free",
106
+ batch: 2,
107
+ },
108
+ {
109
+ name: "Slopify_Duration",
110
+ filler: "duration",
111
+ fills: "The finished video's length.",
112
+ example: "42 min 10 s",
113
+ available: "Once the narration is finished.",
114
+ places: ["description", "shorts", "review", "post"],
115
+ cost: "free",
116
+ batch: 2,
117
+ },
118
+ {
119
+ name: "Slopify_Cast",
120
+ filler: "facts",
121
+ fills: "The channel's cast members, each with their description. A line with no cast is left out.",
122
+ example: "Mira: a keeper's daughter who kept the lighthouse logbook",
123
+ available: atStart,
124
+ places: everywhere,
125
+ cost: "free",
126
+ batch: 2,
127
+ },
128
+ {
129
+ name: "Slopify_Covered_Before",
130
+ filler: "facts",
131
+ fills: "The titles of the videos the channel already made, so the article avoids repeating them. A line with none is left out.",
132
+ example: "The Canal Age\nHow Bread Was Baked in Rome",
133
+ available: atStart,
134
+ places: everywhere,
135
+ cost: "free",
136
+ batch: 2,
137
+ },
138
+ {
139
+ name: "Slopify_Brand",
140
+ filler: "facts",
141
+ fills: "The brand kit's caption and title colors and font names. A line with an empty kit is left out.",
142
+ example: "Colors: #f5c542, #101010. Fonts: Barlow Condensed",
143
+ available: atStart,
144
+ places: pictures,
145
+ cost: "free",
146
+ batch: 2,
147
+ },
148
+ {
149
+ name: "Slopify_Summary",
150
+ filler: "digest",
151
+ fills: "Two or three sentences on what the video covers.",
152
+ example: "How engineers raised towers on rocks the sea covered twice a day, and how their keepers lived.",
153
+ available: digestAvailable,
154
+ places: fromDigest,
155
+ cost: "digest",
156
+ batch: 1,
157
+ },
158
+ {
159
+ name: "Slopify_Hook",
160
+ filler: "digest",
161
+ fills: "The video's most click-worthy idea.",
162
+ example: "The rock was under water half of every day. They built on it anyway.",
163
+ available: digestAvailable,
164
+ places: fromDigest,
165
+ cost: "digest",
166
+ batch: 1,
167
+ },
168
+ {
169
+ name: "Slopify_Thumbnail_Text",
170
+ filler: "digest",
171
+ fills: "Two to four words to put on the thumbnail.",
172
+ example: "BUILT UNDER WATER",
173
+ available: digestAvailable,
174
+ places: fromDigest,
175
+ cost: "digest",
176
+ batch: 1,
177
+ },
178
+ {
179
+ name: "Slopify_Key_Facts",
180
+ filler: "digest",
181
+ fills: "Three to five striking facts from the article, one per line.",
182
+ example: "The tower stands 35 metres high.\nIts lamp was first lit in 1811.",
183
+ available: digestAvailable,
184
+ places: fromDigest,
185
+ cost: "digest",
186
+ batch: 2,
187
+ },
188
+ {
189
+ name: "Slopify_Quote",
190
+ filler: "digest",
191
+ fills: "One quotable line from the article.",
192
+ example: "A light is only as good as the person who keeps it.",
193
+ available: digestAvailable,
194
+ places: fromDigest,
195
+ cost: "digest",
196
+ batch: 2,
197
+ },
198
+ {
199
+ name: "Slopify_Tags",
200
+ filler: "digest",
201
+ fills: "Search terms for the video, separated by commas.",
202
+ example: "lighthouses, engineering history, maritime history, history for sleep",
203
+ available: digestAvailable,
204
+ places: fromDigest,
205
+ cost: "digest",
206
+ batch: 2,
207
+ },
208
+ {
209
+ name: "Slopify_Scene",
210
+ filler: "scenes",
211
+ fills: "What this picture shows: a moment of the article, written for each picture.",
212
+ example: "A keeper climbs the spiral stair at dusk, a lamp held high.",
213
+ available: sceneAvailable,
214
+ places: pictures,
215
+ cost: "scenes",
216
+ legacy: "Scene",
217
+ batch: 1,
218
+ },
219
+ {
220
+ name: "Slopify_Setting",
221
+ filler: "scenes",
222
+ fills: "The era and place of this picture's moment, so it stays period-correct.",
223
+ example: "A rocky Scottish coast, early 19th century, late autumn",
224
+ available: sceneAvailable,
225
+ places: pictures,
226
+ cost: "scenes",
227
+ batch: 1,
228
+ },
229
+ {
230
+ name: "Slopify_Mood",
231
+ filler: "scenes",
232
+ fills: "The feeling of this picture's moment, for its light and color.",
233
+ example: "tense",
234
+ available: sceneAvailable,
235
+ places: pictures,
236
+ cost: "scenes",
237
+ batch: 2,
238
+ },
239
+ {
240
+ name: "Slopify_Appearance",
241
+ filler: "appearance",
242
+ fills: "How the video's subject and the characters in this picture look, looked up on the web.",
243
+ example: "Mira: a tall woman in a wool coat and oilskin hat, a brass lamp at her belt.",
244
+ available: "Once the article is written: one AI call with web search looks them up.",
245
+ places: pictures,
246
+ cost: "appearance",
247
+ legacy: "Appearance",
248
+ batch: 1,
249
+ },
250
+ ];
251
+ export const keywordNames = keywordSpecs.map((spec) => spec.name);
252
+ export const legacyNames = keywordSpecs.flatMap((spec) => spec.legacy === undefined ? [] : [spec.legacy]);
253
+ // The keyword a slot name stands for: its own name, or Scene's and Appearance's old ones. Names
254
+ // are case-sensitive, like every slot name.
255
+ export function keywordOf(name) {
256
+ return keywordSpecs.find((spec) => spec.name === name || spec.legacy === name);
257
+ }
258
+ export function keywordsFor(place) {
259
+ return keywordSpecs.filter((spec) => spec.places.includes(place));
260
+ }