@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
package/dist/main.js CHANGED
@@ -7,9 +7,12 @@ import ffmpegStatic from "ffmpeg-static";
7
7
  import { buildRegistry } from "./adapter-registry.js";
8
8
  import { alignSubtitlesWith } from "./adapters/alignment/index.js";
9
9
  import { prefetchModel } from "./adapters/alignment/prefetch.js";
10
- import { prepareFfmpeg } from "./adapters/ffmpeg.js";
10
+ import { ffmpegOutput, prepareFfmpeg } from "./adapters/ffmpeg.js";
11
11
  import { createHostCliClient } from "./adapters/host-cli/index.js";
12
+ import { createSearchInterest } from "./adapters/interest/search-interest.js";
12
13
  import { nodeRunCli } from "./adapters/llm/run-cli.js";
14
+ import { assistantSelfUrl, wireAssistant } from "./assistant-wiring.js";
15
+ import { startAutopilot } from "./autopilot-timers.js";
13
16
  import { curateRegistry } from "./catalog/registry.js";
14
17
  import { createCatalogueStore } from "./catalog/store.js";
15
18
  import { createAutostart } from "./edge/autostart/index.js";
@@ -20,6 +23,8 @@ import { createApp } from "./edge/http/app.js";
20
23
  import { createMutationLifecycle, drainMutationsWithDeadline } from "./edge/http/mutations.js";
21
24
  import { limitRequestTimes } from "./edge/http/timeouts.js";
22
25
  import { openFolder } from "./edge/open-folder.js";
26
+ import { nodeTailscaleRun } from "./edge/remote-access/cli.js";
27
+ import { createRemoteAccessService } from "./edge/remote-access/service.js";
23
28
  import { readHostLogin } from "./host-cli/status.js";
24
29
  import { createAudioPreviewStore } from "./kernel/audio-preview.js";
25
30
  import { systemClock } from "./kernel/clock.js";
@@ -30,7 +35,7 @@ import { causedBy } from "./kernel/errors.js";
30
35
  import { ulidIds } from "./kernel/ids.js";
31
36
  import { acquireInstanceLock } from "./kernel/lock.js";
32
37
  import { openLog } from "./kernel/log.js";
33
- import { attachPlaces, ensureDataDirs, ensureDirs, layout, repoint, subtitleModelDir, } from "./kernel/paths.js";
38
+ import { attachPlaces, attachSamples, ensureDataDirs, ensureDirs, layout, repoint, subtitleModelDir, } from "./kernel/paths.js";
34
39
  import { stageKinds } from "./kernel/pipeline.js";
35
40
  import { sqliteAttempts } from "./kernel/runner/attempt-repo.js";
36
41
  import { auditionVoice } from "./kernel/runner/audition.js";
@@ -40,15 +45,25 @@ import { stageProviders } from "./kernel/runner/providers.js";
40
45
  import { createProviderQueue } from "./kernel/runner/queue.js";
41
46
  import { standaloneImage, standaloneLlm } from "./kernel/runner/standalone.js";
42
47
  import { readVersion } from "./kernel/version.js";
43
- import { modelSources } from "./model-catalog.js";
48
+ import { keptModels, modelSources } from "./model-catalog.js";
49
+ import { cliWatcher, lookAtModels, wireModelChecks } from "./model-checks.js";
44
50
  import { projectPaused, projectTrashed } from "./slices/admission/repo.js";
45
51
  import { createBackupService } from "./slices/backups/service.js";
46
52
  import { pumpQueue, queueWaiting } from "./slices/batch/index.js";
47
53
  import { settleInterruptedCastImages } from "./slices/channels/cast-images.js";
48
54
  import { approveCheckpoint } from "./slices/checkpoints/index.js";
49
55
  import { checkpointDecisionForWork, recoverCheckpointWork, settleReleasedCheckpoints, } from "./slices/checkpoints/recovery.js";
56
+ import { dailySampleBudget } from "./slices/designs/budget.js";
57
+ import { designCheckContext } from "./slices/designs/check-context.js";
58
+ import { contextChecks, sampleCheck } from "./slices/designs/gate.js";
59
+ import { runPdfWorker } from "./slices/designs/pdf-runner.js";
60
+ import { createDesignRenderer } from "./slices/designs/render.js";
61
+ import { createDesignRunner } from "./slices/designs/runner.js";
62
+ import { createDesignSamples } from "./slices/designs/sample.js";
50
63
  import { createEpisodeMemoryWatcher, } from "./slices/episodes/summarize.js";
51
64
  import { resolveFont } from "./slices/fonts/index.js";
65
+ import { accessRecorder } from "./slices/model-checks/record.js";
66
+ import { readChecks } from "./slices/model-checks/repo.js";
52
67
  import { decodePeaks } from "./slices/narration/peaks.js";
53
68
  import { projectLink } from "./slices/notifications/address.js";
54
69
  import { createNotificationSender } from "./slices/notifications/send.js";
@@ -68,13 +83,15 @@ import { releaseDueReviews } from "./slices/reviews/external-release.js";
68
83
  import { currentRevisionId } from "./slices/revisions/repo.js";
69
84
  import { createLimitGate, resumeAfterRestart } from "./slices/run-cost/limits.js";
70
85
  import { createStandaloneMeter, createUsageMeter } from "./slices/run-cost/meter.js";
86
+ import { refreshDesignSchedules } from "./slices/schedules/next-run.js";
71
87
  import { settleTerminalScheduleRuns } from "./slices/schedules/repo.js";
72
88
  import { createScheduleRunner } from "./slices/schedules/scheduler.js";
73
89
  import { nodeCliProbe } from "./slices/settings/cli-status.js";
74
- import { isLocalCliProvider, localCliConcurrency } from "./slices/settings/model.js";
90
+ import { isLocalCliProvider, localCliConcurrency, providerIds } from "./slices/settings/model.js";
75
91
  import { readSettings } from "./slices/settings/playback.js";
76
92
  import { providerStatuses } from "./slices/settings/readiness.js";
77
93
  import { readSetting } from "./slices/settings/repo.js";
94
+ import { createReshaper } from "./slices/social/reshape.js";
78
95
  import { arrangeChanged } from "./slices/storage/arrange.js";
79
96
  import { busyProjects } from "./slices/storage/backup-export.js";
80
97
  import { documentsDir, nodeDocumentsHost } from "./slices/storage/documents.js";
@@ -83,13 +100,27 @@ import { createPlaces, recoverPlaces } from "./slices/storage/places.js";
83
100
  import { reconcileStorage } from "./slices/storage/reconcile.js";
84
101
  import { installUnpackedExtension, unpackedExtensionDir, } from "./slices/studio/unpacked.js";
85
102
  import { previewPictures } from "./slices/style-preview/images.js";
103
+ import { bundledSampleAssets } from "./slices/style-preview/narration.js";
86
104
  import { ffmpegStylePreview } from "./slices/style-preview/render.js";
87
105
  import { createStylePreviews, stylePreviewDir } from "./slices/style-preview/service.js";
88
106
  import { collectorEndpoint, httpPostEvents } from "./slices/telemetry/collector-client.js";
89
107
  import { createFlusher } from "./slices/telemetry/flush.js";
90
- import { record } from "./slices/telemetry/record.js";
108
+ import { record, skippingProjects } from "./slices/telemetry/record.js";
109
+ import { makeBakeoff } from "./slices/template-studio/bakeoff-make.js";
110
+ import { readStudioSettings } from "./slices/template-studio/budget.js";
111
+ import { createDocumentSamples } from "./slices/template-studio/document-sample.js";
112
+ import { createFreeSamples } from "./slices/template-studio/free.js";
113
+ import { createLoudnessSamples } from "./slices/template-studio/loudness.js";
114
+ import { sampleMaker } from "./slices/template-studio/make.js";
115
+ import { makePaidSample } from "./slices/template-studio/paid.js";
116
+ import { sampleProjects, templateSampleCheck } from "./slices/template-studio/repo.js";
117
+ import { createSampleRunner } from "./slices/template-studio/runner.js";
118
+ import { storedUnknownAcks } from "./slices/template-studio/save.js";
119
+ import { notReadySentence, runnableTemplate, templateGate, } from "./slices/template-studio/schedule-gate.js";
120
+ import { createPriceCache } from "./slices/template-studio/service.js";
91
121
  import { createTrashPurge } from "./slices/trash/service.js";
92
- import { probeDurationMs } from "./slices/video/ffmpeg.js";
122
+ import { createNvencProbe, noNvenc, renderMachine, } from "./slices/video/encoding.js";
123
+ import { probeDurationMs, runFfmpegAt } from "./slices/video/ffmpeg.js";
93
124
  import { watchActivation } from "./updater/candidate.js";
94
125
  import { launchUpdate } from "./updater/install.js";
95
126
  import { isUpdateToken } from "./updater/model.js";
@@ -103,6 +134,21 @@ import { workInProgress } from "./updater/work-in-progress.js";
103
134
  const flushDelayMs = 1000;
104
135
  const collectorTimeoutMs = 10_000;
105
136
  const mutationDrainTimeoutMs = 5_000;
137
+ // ceiling: removing the serve handler is two quick tailscale calls; a hung Tailscale must not
138
+ // hold the shutdown, and the next start removes or replaces what is left.
139
+ const remoteAccessStopMs = 5_000;
140
+ // ceiling: an image call usually answers within a minute; shutdown waits no longer than this
141
+ // for one already sent, and the next start marks a step still making as stopped.
142
+ const designIdleMs = 60_000;
143
+ function withDeadline(work, ms) {
144
+ return new Promise((resolve) => {
145
+ const timer = setTimeout(resolve, ms);
146
+ void work.finally(() => {
147
+ clearTimeout(timer);
148
+ resolve();
149
+ });
150
+ });
151
+ }
106
152
  export function createScheduleTickLifecycle(deps) {
107
153
  let stopping = false;
108
154
  let inflight;
@@ -195,6 +241,9 @@ export async function boot(config, options = {}) {
195
241
  recoverPlaces(db, paths);
196
242
  const places = createPlaces(db);
197
243
  attachPlaces(paths, places);
244
+ // A template's studio sample keeps its folder in the data dir, never in Projects
245
+ // (`slices/template-studio`): set before anything reads or reconciles a project's files.
246
+ attachSamples(paths, sampleProjects(db, paths.dataDir));
198
247
  const runtimeDb = db;
199
248
  const interrupted = markInterruptedStages(db, clock);
200
249
  recoverCheckpointWork(db);
@@ -205,6 +254,17 @@ export async function boot(config, options = {}) {
205
254
  // candidate's committed activation pointer has been verified.
206
255
  const reconciled = pendingActivation ? undefined : reconcileStorage(db, paths);
207
256
  const log = openLog(paths.logs, clock);
257
+ // Settings → Production defaults → Video encoder: the bundled ffmpeg first, then the
258
+ // computer's own. Asked once, when the settings page or a render first needs it.
259
+ const nvenc = createNvencProbe({
260
+ candidates: [ffmpeg, "ffmpeg", "/usr/bin/ffmpeg"],
261
+ exec: ffmpegOutput,
262
+ log,
263
+ });
264
+ // Settings → Production defaults → Render priority for the ffmpeg work outside a project's
265
+ // render (Template Studio's samples, designs' drawing, posts' pictures), read as each starts.
266
+ const renderPriority = () => readSettings({ db: runtimeDb, log }).renderPriority;
267
+ const runFfmpeg = runFfmpegAt(renderPriority);
208
268
  log.write("info", "boot", {
209
269
  detail: reconciled === undefined
210
270
  ? `interrupted stages ${interrupted}, settled schedules ${settledSchedules}, storage reconciliation deferred during update activation`
@@ -225,6 +285,8 @@ export async function boot(config, options = {}) {
225
285
  ids,
226
286
  log,
227
287
  presentEvent: eventPresenter(eventDb),
288
+ // A template's hidden sample is told to its studio, never to the shell or Home.
289
+ quiet: templateSampleCheck(eventDb),
228
290
  }), (event) => {
229
291
  notifier.observe(event);
230
292
  episodes?.observe(event);
@@ -252,11 +314,15 @@ export async function boot(config, options = {}) {
252
314
  }), catalogue);
253
315
  // Calls that belong to no project (topic generation, episode summaries, cast pictures)
254
316
  // still go through the attempt wrapper, and are metered against their schedule or channel.
317
+ // What real calls teach about each model for the person's keys and logins (Settings →
318
+ // Models, the pickers); no run reads it back.
319
+ const access = accessRecorder({ db, clock });
255
320
  const standalone = {
256
321
  registry,
257
322
  clock,
258
323
  log,
259
324
  meter: createStandaloneMeter({ db, ids, clock, catalogue: () => catalogue.read() }),
325
+ access,
260
326
  };
261
327
  episodes = createEpisodeMemoryWatcher({
262
328
  db,
@@ -285,6 +351,7 @@ export async function boot(config, options = {}) {
285
351
  registry,
286
352
  catalogue,
287
353
  ffmpeg,
354
+ nvenc,
288
355
  audioPreviews,
289
356
  });
290
357
  const updateDb = db;
@@ -306,6 +373,8 @@ export async function boot(config, options = {}) {
306
373
  // Folders are renamed only by a version that is committed: an update on trial can still be
307
374
  // rolled back to a version that knows only id-named folders.
308
375
  let arrangeAllowed = !pendingActivation;
376
+ // What an update waits for that only lives in memory; set once those parts are wired.
377
+ let liveWork = () => undefined;
309
378
  const updater = createUpdater({
310
379
  ...(isUpdateToken(candidateToken)
311
380
  ? {
@@ -348,9 +417,8 @@ export async function boot(config, options = {}) {
348
417
  ? "npm was not found, so in-app updates are off. Install Node.js with npm (https://nodejs.org), or update from the terminal: npx @gentbajko/slopify@latest"
349
418
  : undefined,
350
419
  // An update never installs while a job is going (`updater/work-in-progress.ts`).
351
- busy: () => workInProgress(updateDb, (id) => runner.hasInflight?.(id) === true, Date.now()) !==
352
- undefined,
353
- busyWith: () => workInProgress(updateDb, (id) => runner.hasInflight?.(id) === true, Date.now()),
420
+ busy: () => workInProgress(updateDb, (id) => runner.hasInflight?.(id) === true, Date.now(), liveWork) !== undefined,
421
+ busyWith: () => workInProgress(updateDb, (id) => runner.hasInflight?.(id) === true, Date.now(), liveWork),
354
422
  report: (message) => log.write("warn", "update", { detail: message }),
355
423
  install: async (next, restarting) => {
356
424
  if (npm === undefined)
@@ -384,6 +452,18 @@ export async function boot(config, options = {}) {
384
452
  modelsFor: modelSources(registry).modelsFor,
385
453
  emit: (projectId, event) => hub.emit(projectId, event),
386
454
  };
455
+ // Which models work for the person's keys and logins (Settings → Models, the pickers).
456
+ const { checks: modelChecks, listing: modelListing } = wireModelChecks({
457
+ db,
458
+ clock,
459
+ log,
460
+ registry,
461
+ catalogue: () => catalogue.read(),
462
+ lifecycle: catalogue.lifecycle,
463
+ fetch: globalThis.fetch,
464
+ statuses: rebuild.providers,
465
+ });
466
+ const autoModelChecks = options.refreshModels === true;
387
467
  // Redos a review asked for before the last shutdown start now.
388
468
  reviewRedos.bind(rebuild);
389
469
  reviewRedos.kick();
@@ -413,7 +493,9 @@ export async function boot(config, options = {}) {
413
493
  uuid: randomUUID,
414
494
  resolveFont: (fontId) => resolveFont(paths, fontId),
415
495
  providers: rebuild.providers,
416
- modelsFor: rebuild.modelsFor,
496
+ // Create checks the draft after every pause in typing; the model lists it checks against
497
+ // are read once a minute at most, not each time (`keptModels`).
498
+ modelsFor: keptModels(rebuild.modelsFor, 60_000),
417
499
  emit: (event) => hub.emitGlobal(event),
418
500
  recordStarted: (projectIds) => {
419
501
  for (const _projectId of projectIds)
@@ -421,10 +503,20 @@ export async function boot(config, options = {}) {
421
503
  flusher.soon();
422
504
  },
423
505
  };
506
+ // Built with the designs further down; design schedules make their pieces with it.
507
+ let designMake;
424
508
  const scheduleRunnerDeps = {
425
509
  ...draftDeps,
426
- template: (id) => templateById(runtimeDb, id),
510
+ designs: () => designMake,
511
+ // The newest version that may run: legacy, marked ready, or carried by Slopify. Only a
512
+ // project template's: a design schedule asks the designs (runnableDesignVersion).
513
+ template: (id) => runnableTemplate(runtimeDb, id),
514
+ notReady: (id) => notReadySentence(runtimeDb, id),
515
+ templateHead: (id) => templateById(runtimeDb, id),
516
+ templateGate: (id) => templateGate(runtimeDb, id),
427
517
  topicLlm: (call) => standaloneLlm(standalone, call),
518
+ // Asked only for schedules set to rank topics by public search interest.
519
+ interest: createSearchInterest({ fetch: globalThis.fetch, version, now: () => clock.now() }),
428
520
  topicsWaiting: (event) => {
429
521
  hub.emitGlobal(event);
430
522
  notifier.observeTopics(event);
@@ -443,6 +535,59 @@ export async function boot(config, options = {}) {
443
535
  detail: "Scheduled jobs could not be advanced.",
444
536
  }),
445
537
  });
538
+ // Library → Templates → Open studio: its free samples, made one job at a time in the
539
+ // background (`slices/template-studio/runner.ts`).
540
+ const stylePreviews = createStylePreviews({
541
+ dir: stylePreviewDir(paths.dataDir),
542
+ render: ffmpegStylePreview({
543
+ ffmpeg,
544
+ paths,
545
+ log,
546
+ dir: stylePreviewDir(paths.dataDir),
547
+ // Encoded and prioritised as this computer's videos are (`slices/video/encoding.ts`).
548
+ machine: async () => (await renderMachine({ settings: readSettings({ db: runtimeDb, log }), nvenc, log }))
549
+ .machine,
550
+ }),
551
+ pictures: previewPictures({ db, paths }),
552
+ log,
553
+ });
554
+ const studioCache = join(paths.dataDir, "cache", "template-studio");
555
+ const loudnessSamples = createLoudnessSamples({
556
+ ffmpeg,
557
+ dir: join(studioCache, "loudness"),
558
+ source: bundledSampleAssets().narration,
559
+ log,
560
+ priority: renderPriority,
561
+ });
562
+ const documentSamples = createDocumentSamples({ dir: join(studioCache, "document") });
563
+ const freeSamples = createFreeSamples({
564
+ stylePreviews,
565
+ loudness: loudnessSamples,
566
+ documents: documentSamples,
567
+ loudnessDefault: () => readSettings({ db: runtimeDb, log }).loudness,
568
+ });
569
+ const studioPrices = createPriceCache();
570
+ // The unknown prices accepted on Save, shared by the studio's routes and its sample loop,
571
+ // and kept across restarts.
572
+ const studioAcks = storedUnknownAcks(db);
573
+ const sampleChanged = (templateId) => hub.emitGlobal({ type: "template.sample", templateId });
574
+ const sampleRunner = createSampleRunner({
575
+ db,
576
+ log,
577
+ changed: sampleChanged,
578
+ make: sampleMaker({
579
+ db,
580
+ free: freeSamples,
581
+ prices: studioPrices,
582
+ review: draftDeps,
583
+ changed: sampleChanged,
584
+ // Paid samples run on their hidden project through the same engine as every project.
585
+ paid: (job, signal) => makePaidSample({ start: draftDeps, rebuild, acks: studioAcks }, job, signal),
586
+ // Compare models: copies of the sample, made one bake-off at a time on the same loop.
587
+ bakeoff: (job, signal) => makeBakeoff({ start: draftDeps, rebuild }, job, signal),
588
+ }),
589
+ });
590
+ sampleRunner.start();
446
591
  const mutations = createMutationLifecycle();
447
592
  const folderConfiguration = await dockerFolderConfiguration(process.env, paths.projects);
448
593
  const filesService = createFilesService({
@@ -489,6 +634,18 @@ export async function boot(config, options = {}) {
489
634
  version,
490
635
  env: process.env,
491
636
  });
637
+ // Settings → Remote access. It proxies to the port the server really got, read
638
+ // when it applies; nothing applies before the server listens.
639
+ const remoteAccess = createRemoteAccessService({
640
+ db,
641
+ run: nodeTailscaleRun(process.platform),
642
+ platform: process.platform,
643
+ container: process.env.SLOPIFY_CONTAINER === "1",
644
+ listenHost: config.host,
645
+ port: () => listeningPort,
646
+ log,
647
+ now: () => Date.now(),
648
+ });
492
649
  if (options.refreshAutostart === true)
493
650
  void autostart.refresh().catch((error) => {
494
651
  log.write("warn", "autostart.refresh", { detail: causedBy(error) });
@@ -505,8 +662,109 @@ export async function boot(config, options = {}) {
505
662
  catch (error) {
506
663
  log.write("warn", "studio.extension", { detail: causedBy(error) });
507
664
  }
665
+ const autopilot = startAutopilot({
666
+ db: updateDb,
667
+ clock,
668
+ log,
669
+ dataDir: paths.dataDir,
670
+ template: (id) => templateById(updateDb, id),
671
+ catalogue: () => catalogue.read(),
672
+ fetch: globalThis.fetch,
673
+ send: sendNotification,
674
+ hostCli,
675
+ readLogin: readHostLogin,
676
+ });
677
+ // The assistant panel's chat: turns on this computer's Claude Code or Codex, reaching this
678
+ // server's own `/mcp/assistant`. In the Docker copy it says why it isn't there.
679
+ const assistant = wireAssistant({
680
+ db: updateDb,
681
+ ids,
682
+ clock,
683
+ log,
684
+ emit: hub.emitGlobal,
685
+ spawn: nodeRunCli,
686
+ probe: nodeCliProbe,
687
+ readLogin: readHostLogin,
688
+ selfUrl: () => assistantSelfUrl(config.host, listeningPort),
689
+ container: hostCli !== undefined,
690
+ });
691
+ // Library → Designs: paid pictures through the attempt wrapper, metered on the design;
692
+ // drawing in a child ffmpeg and PDFs in a forked worker, never on this thread.
693
+ // The template editor's samples hear when a sample's picture lands, to start the next.
694
+ let designSamples;
695
+ const designService = {
696
+ db,
697
+ clock,
698
+ ids,
699
+ paths,
700
+ log,
701
+ emit: (event) => {
702
+ hub.emitGlobal(event);
703
+ if (event.type === "design.changed")
704
+ designSamples?.designChanged(event.designId);
705
+ },
706
+ };
707
+ const designRenderer = createDesignRenderer({
708
+ db,
709
+ paths,
710
+ log,
711
+ clock,
712
+ ffmpeg,
713
+ runFfmpeg,
714
+ font: (fontId) => resolveFont(paths, fontId),
715
+ pdf: (job, signal) => runPdfWorker(job, signal),
716
+ });
717
+ const designRunner = createDesignRunner({
718
+ ...designService,
719
+ catalogue: () => catalogue.read(),
720
+ generate: ({ designId, ...call }) => standaloneImage(standalone, { ...call, owner: { kind: "design", id: designId } }),
721
+ shrink: (bytes) => designRenderer.shrink(bytes, AbortSignal.timeout(120_000)),
722
+ });
723
+ designRunner.recover();
724
+ liveWork = () => modelChecks.running().length > 0
725
+ ? "the model checks"
726
+ : assistant.turnsRunning() > 0
727
+ ? "the assistant's answer"
728
+ : undefined;
729
+ designMake = {
730
+ service: designService,
731
+ runner: designRunner,
732
+ catalogue: () => catalogue.read(),
733
+ };
734
+ designSamples = createDesignSamples({
735
+ service: designService,
736
+ runner: designRunner,
737
+ catalogue: () => catalogue.read(),
738
+ budget: () => dailySampleBudget(runtimeDb, log),
739
+ plans: () => readStudioSettings(runtimeDb).samplesUsePlans,
740
+ timeZone: () => Intl.DateTimeFormat().resolvedOptions().timeZone || "UTC",
741
+ });
742
+ designSamples.recover();
743
+ const designChecks = designCheckContext({
744
+ resolveFont: (fontId) => resolveFont(paths, fontId),
745
+ providers: rebuild.providers,
746
+ });
508
747
  const app = createApp({
748
+ assistant,
749
+ autopilot,
750
+ designs: { service: designService, runner: designRunner, renderer: designRenderer },
751
+ // Pictures cut to a post's shape, in a child ffmpeg like the designs' drawing.
752
+ social: { reshaper: createReshaper({ paths, ffmpeg, runFfmpeg, log }) },
753
+ designTemplates: {
754
+ service: designService,
755
+ runner: designRunner,
756
+ catalogue: () => catalogue.read(),
757
+ checks: async (templateId, doc, version) => [
758
+ ...(await contextChecks(doc, templateId, designChecks)),
759
+ sampleCheck(runtimeDb, templateId, version),
760
+ ],
761
+ samples: designSamples,
762
+ templateChanged: (templateId) => {
763
+ refreshDesignSchedules(runtimeDb, templateId, clock.now());
764
+ },
765
+ },
509
766
  autostart,
767
+ remoteAccess,
510
768
  rebuild,
511
769
  drafts: draftDeps,
512
770
  schedules: scheduleDeps,
@@ -523,20 +781,29 @@ export async function boot(config, options = {}) {
523
781
  db,
524
782
  paths,
525
783
  host: config.host,
784
+ allowedHosts: (process.env.SLOPIFY_ALLOWED_HOSTS ?? "")
785
+ .split(",")
786
+ .map((name) => name.trim())
787
+ .filter((name) => name !== ""),
526
788
  hub,
527
789
  runner,
528
790
  updater,
529
791
  mutations,
530
792
  sendNotification,
793
+ nvenc,
531
794
  audioPreviews,
532
- stylePreviews: createStylePreviews({
533
- dir: stylePreviewDir(paths.dataDir),
534
- render: ffmpegStylePreview({ ffmpeg, paths, log, dir: stylePreviewDir(paths.dataDir) }),
535
- pictures: previewPictures({ db, paths }),
536
- log,
537
- }),
795
+ stylePreviews,
796
+ templateStudio: {
797
+ free: freeSamples,
798
+ prices: studioPrices,
799
+ wake: sampleRunner.wake,
800
+ acks: studioAcks,
801
+ loudnessSource: loudnessSamples.source,
802
+ loudnessFile: loudnessSamples.file,
803
+ documentFile: documentSamples.file,
804
+ },
538
805
  ...modelSources(registry),
539
- audition: (call, signal) => auditionVoice({ registry, clock, log }, call, signal),
806
+ audition: (call, signal) => auditionVoice({ registry, clock, log, access }, call, signal),
540
807
  voiceLanguages: async (provider, voiceId, signal) => {
541
808
  try {
542
809
  return await registry.tts(provider).voiceLanguages?.(voiceId, signal);
@@ -546,6 +813,9 @@ export async function boot(config, options = {}) {
546
813
  }
547
814
  },
548
815
  catalogue,
816
+ modelChecks,
817
+ modelListing,
818
+ autoModelChecks,
549
819
  clock,
550
820
  ids,
551
821
  log,
@@ -627,12 +897,28 @@ export async function boot(config, options = {}) {
627
897
  catalogue.sync().then((status) => {
628
898
  if (status.warning !== null)
629
899
  log.write("warn", "model-catalog.sync", { detail: status.warning });
900
+ // A model new to the list may already be on the person's key's own list.
901
+ for (const provider of new Set(status.changes.added.map((added) => added.provider)))
902
+ if (isProviderId(provider))
903
+ void modelListing.refresh(provider, true).catch((error) => {
904
+ log.write("warn", "model-checks.listing", { detail: causedBy(error) });
905
+ });
630
906
  }, (error) => log.write("warn", "model-catalog.sync", { detail: causedBy(error) }));
631
907
  };
632
908
  syncModels();
909
+ // Model checks look hourly too: the weekly look, and a CLI that became usable. Both run in
910
+ // the background and never hold a request or a run.
911
+ const lookForClis = cliWatcher(modelChecks, rebuild.providers, (provider) => readChecks(updateDb, provider).length > 0);
912
+ const lookForModels = () => {
913
+ if (!autoModelChecks)
914
+ return;
915
+ lookAtModels(modelChecks, lookForClis).catch((error) => log.write("warn", "model-checks", { detail: causedBy(error) }));
916
+ };
917
+ lookForModels();
633
918
  const modelTimer = setInterval(() => {
634
919
  if (catalogue.syncDue?.(Date.now()) === true)
635
920
  syncModels();
921
+ lookForModels();
636
922
  }, 60 * 60_000);
637
923
  const backupTimer = setInterval(() => {
638
924
  backups.tick().catch((error) => {
@@ -685,6 +971,11 @@ export async function boot(config, options = {}) {
685
971
  };
686
972
  const arrangeTimer = setInterval(arrange, 5_000);
687
973
  listeningPort = portOf(server) ?? config.port;
974
+ // Never awaited: Tailscale's answer must not hold the start-up. A problem is logged with
975
+ // its fix and shown in Settings.
976
+ void remoteAccess.start().catch((error) => {
977
+ log.write("warn", "remote-access.start", { detail: causedBy(error) });
978
+ });
688
979
  // Whatever last run left queued goes out at start. Nothing waits for
689
980
  // it, and an unreachable collector costs one refused socket.
690
981
  flusher.soon();
@@ -715,13 +1006,22 @@ export async function boot(config, options = {}) {
715
1006
  clearInterval(trashTimer);
716
1007
  clearInterval(arrangeTimer);
717
1008
  clearInterval(modelTimer);
1009
+ modelChecks.stop();
1010
+ autopilot.stop();
718
1011
  const mutationDrain = mutations.stop();
719
1012
  const scheduleDrain = scheduleTicks.stop();
720
1013
  const topicDrain = scheduleRunner.stop();
1014
+ // A local sample render is stopped and its job queued again at the next start.
1015
+ const sampleDrain = sampleRunner.stop();
721
1016
  // A backup being written is stopped and its partial file removed, not waited for.
722
1017
  const backupDrain = backups.stop();
723
1018
  const serverClose = beginServerClose(server);
724
1019
  stopActivation();
1020
+ // Slopify's serve handler goes with it, so no proxy points at a port another program
1021
+ // could take while Slopify is stopped; the next start puts it back.
1022
+ const remoteDrain = withDeadline(remoteAccess.stop().catch((error) => {
1023
+ log.write("warn", "remote-access.stop", { detail: causedBy(error) });
1024
+ }), remoteAccessStopMs);
725
1025
  audioPreviews.close();
726
1026
  modelPrefetch.abort();
727
1027
  try {
@@ -730,7 +1030,13 @@ export async function boot(config, options = {}) {
730
1030
  await drainMutationsWithDeadline(mutationDrain, serverClose.terminate, mutationDrainTimeoutMs);
731
1031
  await scheduleDrain;
732
1032
  await topicDrain;
1033
+ await sampleDrain;
733
1034
  await backupDrain;
1035
+ await remoteDrain;
1036
+ // An assistant turn left running would keep spending the person's plan.
1037
+ await assistant.stopAll();
1038
+ // A picture call already sent is paid for: let it land rather than lose it.
1039
+ await withDeadline(designRunner.idle(), designIdleMs);
734
1040
  await runner.abortAll();
735
1041
  await episodes?.settled();
736
1042
  }
@@ -764,16 +1070,16 @@ export async function boot(config, options = {}) {
764
1070
  throw error;
765
1071
  }
766
1072
  }
767
- export function wireRunner({ onFinished, audioPreviews, db, paths, clock, ids, log, hub, telemetry, flusher, registry, catalogue, ffmpeg,
1073
+ export function wireRunner({ onFinished, audioPreviews, db, paths, clock, ids, log, hub, telemetry, flusher, registry, catalogue, ffmpeg, nvenc = async () => ({ available: false, reason: noNvenc }),
768
1074
  // Settings → Production defaults → Subtitle timing model, read as each alignment starts.
769
1075
  alignSubtitles: aligner = alignSubtitlesWith(() => readSettings({ db, log }).subtitleModel), }) {
770
1076
  // A stage counts what it did and the queue is flushed after each new event. `record`
771
1077
  // swallows its own failures, so this can neither fail a stage nor widen what leaves the
772
1078
  // machine - the payload allow-list is checked inside it.
773
- const count = (type, counters) => {
1079
+ const count = skippingProjects((type, counters) => {
774
1080
  record(telemetry, type, counters);
775
1081
  flusher.soon();
776
- };
1082
+ }, templateSampleCheck(db));
777
1083
  const execution = {
778
1084
  db,
779
1085
  paths,
@@ -782,6 +1088,8 @@ alignSubtitles: aligner = alignSubtitlesWith(() => readSettings({ db, log }).sub
782
1088
  log,
783
1089
  ffmpeg,
784
1090
  alignSubtitles: aligner,
1091
+ // Settings → Production defaults → Rendering, read as each render starts.
1092
+ renderMachine: (projectId) => renderMachine({ settings: readSettings({ db, log }), nvenc, log, projectId }),
785
1093
  audioPreviews,
786
1094
  count,
787
1095
  };
@@ -793,6 +1101,7 @@ alignSubtitles: aligner = alignSubtitlesWith(() => readSettings({ db, log }).sub
793
1101
  clock,
794
1102
  log,
795
1103
  meter: createUsageMeter({ db, ids, clock, catalogue: () => catalogue.read() }),
1104
+ access: accessRecorder({ db, clock }),
796
1105
  limits: createLimitGate({
797
1106
  db,
798
1107
  clock,
@@ -873,6 +1182,11 @@ alignSubtitles: aligner = alignSubtitlesWith(() => readSettings({ db, log }).sub
873
1182
  emitRunningCount: (running) => {
874
1183
  hub.emitGlobal({ type: "running.count", count: running });
875
1184
  },
1185
+ // The shell's "N running" leaves out the template studio's hidden samples.
1186
+ counted: (() => {
1187
+ const sample = templateSampleCheck(db);
1188
+ return (projectId) => !sample(projectId);
1189
+ })(),
876
1190
  log,
877
1191
  });
878
1192
  return { ...runner, checkpoints };
@@ -921,6 +1235,9 @@ export function urlOf(host, port) {
921
1235
  }
922
1236
  // A stage can only be `running` at boot if the previous process died mid-run;
923
1237
  // nothing auto-resumes, the user retries by hand.
1238
+ function isProviderId(id) {
1239
+ return providerIds.includes(id);
1240
+ }
924
1241
  export function markInterruptedStages(db, clock) {
925
1242
  const result = db
926
1243
  .prepare("UPDATE stages SET state = CASE WHEN EXISTS (SELECT 1 FROM project_controls WHERE project_id = stages.project_id AND paused = 1) THEN 'pending' ELSE 'failed' END, failure_reason = CASE WHEN EXISTS (SELECT 1 FROM project_controls WHERE project_id = stages.project_id AND paused = 1) THEN NULL ELSE 'interrupted' END, finished_at = CASE WHEN EXISTS (SELECT 1 FROM project_controls WHERE project_id = stages.project_id AND paused = 1) THEN NULL ELSE ? END WHERE state = 'running'")
@@ -31,3 +31,23 @@ export function modelSources(registry) {
31
31
  fallbackModelsFor: (provider) => Object.hasOwn(fallbacks, provider) ? (fallbacks[provider] ?? []) : [],
32
32
  };
33
33
  }
34
+ // A model list kept for a short while. Create checks a draft again after every pause in typing,
35
+ // and Claude Code lists its models by running its CLI (about a second each time), so the check
36
+ // and the start that follows read one list. A list that failed is asked for again.
37
+ export function keptModels(modelsFor, keepMs, now = Date.now) {
38
+ const kept = new Map();
39
+ return (provider, family) => {
40
+ const key = `${family}:${provider}`;
41
+ const at = now();
42
+ const held = kept.get(key);
43
+ if (held !== undefined && at - held.at < keepMs)
44
+ return held.models;
45
+ const models = modelsFor(provider, family);
46
+ kept.set(key, { at, models });
47
+ models.catch(() => {
48
+ if (kept.get(key)?.models === models)
49
+ kept.delete(key);
50
+ });
51
+ return models;
52
+ };
53
+ }