@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
@@ -1,7 +1,14 @@
1
1
  import { thinkingModes } from "../kernel/ports/llm.js";
2
2
  import { providerError } from "../kernel/ports/model.js";
3
+ import { editSettings } from "../kernel/ports/settings-places.js";
3
4
  import { isLocalCliProvider, systemVoiceProvider } from "../slices/settings/model.js";
4
- import { referenceRefusal, takesReferenceImage } from "./schema.js";
5
+ import { editRefusal, referenceRefusal, takesReferenceImage } from "./schema.js";
6
+ // Where a project's settings choose the model of each family.
7
+ const modelPlace = {
8
+ llm: editSettings.writer,
9
+ tts: editSettings.narration,
10
+ image: editSettings.images,
11
+ };
5
12
  export function curateRegistry(registry, catalogue) {
6
13
  const requireModel = (provider, family, id) => {
7
14
  const models = catalogue.models(provider, family);
@@ -9,7 +16,7 @@ export function curateRegistry(registry, catalogue) {
9
16
  if (!model)
10
17
  throw providerError({
11
18
  kind: "unsupported",
12
- message: `The chosen ${provider} model is no longer in Slopify's model list. In the Edit tab, choose Edit project and change it under Providers, then use Continue the run.`,
19
+ message: `The chosen ${provider} model is no longer in Slopify's model list. Pick another in ${modelPlace[family]}, then use Continue the run.`,
13
20
  });
14
21
  return model;
15
22
  };
@@ -25,7 +32,7 @@ export function curateRegistry(registry, catalogue) {
25
32
  if (request.model.trim() === "")
26
33
  throw providerError({
27
34
  kind: "unsupported",
28
- message: "No model is chosen for this step. In the Edit tab, choose Edit project and change it under Providers, then use Continue the run.",
35
+ message: `No model is chosen for this step. Pick one in ${editSettings.writer}, then use Continue the run.`,
29
36
  });
30
37
  let models;
31
38
  try {
@@ -39,19 +46,19 @@ export function curateRegistry(registry, catalogue) {
39
46
  if (models !== undefined && selected === undefined)
40
47
  throw providerError({
41
48
  kind: "unsupported",
42
- message: "The chosen model is not available in the AI command-line tool on your computer. Update the tool, or pick another model: in the Edit tab, choose Edit project and change it under Providers, then use Continue the run.",
49
+ message: `The chosen model is not available in the AI command-line tool on your computer. Update the tool, or pick another model in ${editSettings.writer}, then use Continue the run.`,
43
50
  });
44
51
  if (request.thinking !== undefined &&
45
52
  selected !== undefined &&
46
53
  !selected.thinkingModes?.includes(request.thinking))
47
54
  throw providerError({
48
55
  kind: "unsupported",
49
- message: "The chosen model does not support this thinking setting. In the Edit tab, choose Edit project and change it under Providers, then use Continue the run.",
56
+ message: `The chosen model does not support this Thinking level. Change it in ${editSettings.writer}, then use Continue the run.`,
50
57
  });
51
58
  if (request.webSearch && !port.capabilities.webSearch)
52
59
  throw providerError({
53
60
  kind: "unsupported",
54
- message: "This command-line tool cannot search the web for research. Choose another text provider or turn Research off in the Edit tab under Edit project, then use Continue the run.",
61
+ message: `This command-line tool cannot search the web for research. Choose another service in ${editSettings.writer}, or set Research source to Off in ${editSettings.article}, then use Continue the run.`,
55
62
  });
56
63
  const thinkingConfig = id === "codex" && request.thinking !== undefined
57
64
  ? { effort: request.thinking === "off" ? "none" : request.thinking }
@@ -80,13 +87,13 @@ export function curateRegistry(registry, catalogue) {
80
87
  if (request.webSearch && !model.llm.webSearch)
81
88
  throw providerError({
82
89
  kind: "unsupported",
83
- message: "The chosen model cannot search the web for research. Choose another model or turn Research off in the Edit tab under Edit project, then use Continue the run.",
90
+ message: `The chosen model cannot search the web for research. Choose another model in ${editSettings.writer}, or set Research source to Off in ${editSettings.article}, then use Continue the run.`,
84
91
  });
85
92
  const thinkingConfig = request.thinking === undefined ? undefined : model.llm.thinking?.[request.thinking];
86
93
  if (request.thinking !== undefined && !thinkingConfig)
87
94
  throw providerError({
88
95
  kind: "unsupported",
89
- message: "The chosen model does not support this thinking setting. In the Edit tab, choose Edit project and change it under Providers, then use Continue the run.",
96
+ message: `The chosen model does not support this Thinking level. Change it in ${editSettings.writer}, then use Continue the run.`,
90
97
  });
91
98
  yield* port.complete({
92
99
  ...request,
@@ -107,14 +114,14 @@ export function curateRegistry(registry, catalogue) {
107
114
  throw providerError({
108
115
  kind: "unsupported",
109
116
  message: request.model === "codex-imagegen"
110
- ? "Image generation is not available in the Codex CLI on your computer. Update Codex CLI, or choose another image provider in the Edit tab under Edit project, then use Continue the run."
111
- : "The chosen Codex model for images is not in the Codex CLI's model list on your computer. Update Codex CLI, or pick another model for images: in the Edit tab, choose Edit project and change it under Providers, then use Continue the run.",
117
+ ? `Image generation is not available in the Codex CLI on your computer. Update Codex CLI, or choose another image service in ${editSettings.images}, then use Continue the run.`
118
+ : `The chosen Codex model for images is not in the Codex CLI's model list on your computer. Update Codex CLI, or pick another image model in ${editSettings.images}, then use Continue the run.`,
112
119
  });
113
120
  if (request.thinking !== undefined &&
114
121
  !selected.thinkingModes?.includes(request.thinking))
115
122
  throw providerError({
116
123
  kind: "unsupported",
117
- message: "The chosen Codex model does not support this effort for images. In the Edit tab, choose Edit project and change the images' Effort under Providers, then use Continue the run.",
124
+ message: `The chosen Codex model does not support this effort for images. Change Effort in ${editSettings.images}, then use Continue the run.`,
118
125
  });
119
126
  return port.generate(request);
120
127
  },
@@ -128,13 +135,15 @@ export function curateRegistry(registry, catalogue) {
128
135
  if (!("image" in model) || !model.image.aspectRatios.includes(request.aspect))
129
136
  throw providerError({
130
137
  kind: "unsupported",
131
- message: "The chosen image model cannot make images in this video's shape. In the Edit tab, choose Edit project and change it under Providers, then use Continue the run.",
138
+ message: `The chosen image model cannot make images in this video's shape. Pick another in ${editSettings.images}, then use Continue the run.`,
132
139
  });
133
140
  if (request.thinking !== undefined)
134
141
  throw providerError({
135
142
  kind: "unsupported",
136
- message: "The chosen image model has no effort setting. In the Edit tab, choose Edit project and set the images' Effort back to Model default under Providers, then use Continue the run.",
143
+ message: `The chosen image model has no effort setting. Set Effort back to Model default in ${editSettings.images}, then use Continue the run.`,
137
144
  });
145
+ if (request.edit !== undefined && !takesReferenceImage(model))
146
+ throw providerError({ kind: "unsupported", message: editRefusal });
138
147
  if (request.reference !== undefined && !takesReferenceImage(model))
139
148
  throw providerError({
140
149
  kind: "unsupported",
@@ -162,7 +171,7 @@ export function curateRegistry(registry, catalogue) {
162
171
  if (request.text.length > model.tts.maxCharacters)
163
172
  throw providerError({
164
173
  kind: "unsupported",
165
- message: `A piece of narration is longer than this voice model's ${model.tts.maxCharacters}-character limit. Use More → make it again in its section on Audio so Slopify splits it into shorter pieces.`,
174
+ message: `A piece of narration is longer than this voice model's ${model.tts.maxCharacters}-character limit. Press Make the narration again in the project's Narration section, so Slopify splits it into shorter pieces.`,
166
175
  });
167
176
  return port.synthesize({ ...request, model: model.id });
168
177
  },
@@ -1,5 +1,6 @@
1
1
  import { z } from "zod";
2
2
  import { thinkingModes } from "../kernel/ports/llm.js";
3
+ import { createRows, editSettings } from "../kernel/ports/settings-places.js";
3
4
  import { providers } from "../slices/settings/model.js";
4
5
  const money = z.number().finite().nonnegative();
5
6
  const base = z.object({
@@ -105,7 +106,9 @@ export function takesReferenceImage(model) {
105
106
  return model.keywords.includes("reference");
106
107
  }
107
108
  // What the run says when the chosen image model cannot take the establishing image.
108
- export const referenceRefusal = "The chosen image model can't use an establishing image as a reference, so the images can't be drawn to match it. Choose an image model that can (Codex CLI, OpenAI, Google, or a fal.ai model listed with reference) under Images → Model on Play or in Edit project → Providers, or set Establishing image to Off in the Images section.";
109
+ export const referenceRefusal = `The chosen image model can't use an establishing image as a reference, so the images can't be drawn to match it. Choose an image model that can (Codex CLI, OpenAI, Google, or a fal.ai model listed with reference) in ${createRows.images} or ${editSettings.images}, or set Establishing image to Off there.`;
110
+ // What a design's edit says when the chosen image model takes no input picture.
111
+ export const editRefusal = "This image model can't edit a picture. Choose Codex CLI, OpenAI, Google, or FLUX.2 or Nano Banana 2 on fal.ai under Made with … · change.";
109
112
  // The image-to-video models a provider offers, as Animate images lists them.
110
113
  export function videoModelsOf(catalogue, provider) {
111
114
  return catalogue.image.filter((m) => m.provider === provider && m.enabled && !m.deprecated && isVideoModel(m));
@@ -2,6 +2,7 @@ import { existsSync, mkdirSync, readFileSync, renameSync, statSync, writeFileSyn
2
2
  import { join } from "node:path";
3
3
  import { parse, stringify } from "yaml";
4
4
  import { isLocalCliProvider } from "../slices/settings/model.js";
5
+ import { emptyLifecycle, lifecycleSource, parseLifecycle } from "./lifecycle.js";
5
6
  import { applyOpenRouterListing, catalogueFamilies, combineChanges, mergeCatalogue, modelKey, noChanges, } from "./merge.js";
6
7
  import { catalogueSchema, isVideoModel } from "./schema.js";
7
8
  export const catalogueSource = "https://raw.githubusercontent.com/GentBajko/slopify/main/packages/app/src/assets/models.yaml";
@@ -33,6 +34,42 @@ export function createCatalogueStore(deps) {
33
34
  let refreshing;
34
35
  let syncing;
35
36
  const syncPath = join(deps.dataDir, "models-sync.json");
37
+ const lifecyclePath = join(deps.dataDir, "models-lifecycle.yaml");
38
+ const shippedLifecycle = () => {
39
+ try {
40
+ return parseLifecycle(deps.bundledLifecycle ??
41
+ readFileSync(new URL("../assets/models-lifecycle.yaml", import.meta.url), "utf8"));
42
+ }
43
+ catch {
44
+ return emptyLifecycle;
45
+ }
46
+ };
47
+ let lifecycle;
48
+ const readLifecycle = () => {
49
+ if (lifecycle !== undefined)
50
+ return lifecycle;
51
+ try {
52
+ lifecycle = parseLifecycle(readFileSync(lifecyclePath, "utf8"));
53
+ }
54
+ catch {
55
+ // No downloaded copy yet, or a damaged one: the shipped list stands in.
56
+ lifecycle = shippedLifecycle();
57
+ }
58
+ return lifecycle;
59
+ };
60
+ // Optional: a failed download keeps the last copy, and nothing else of the check depends on it.
61
+ async function syncLifecycle() {
62
+ try {
63
+ const text = await download(lifecycleSource, 256 * 1024);
64
+ const next = parseLifecycle(text);
65
+ writeFileSync(`${lifecyclePath}.next`, text, { mode: 0o600 });
66
+ renameSync(`${lifecyclePath}.next`, lifecyclePath);
67
+ lifecycle = next;
68
+ }
69
+ catch {
70
+ // Kept as it was.
71
+ }
72
+ }
36
73
  const now = deps.now ?? (() => new Date());
37
74
  function read() {
38
75
  try {
@@ -141,6 +178,7 @@ export function createCatalogueStore(deps) {
141
178
  const known = new Set(saved.known ?? keysOf(parseCatalogue(bundled)));
142
179
  const merged = mergeCatalogue(local, published, known);
143
180
  const live = applyOpenRouterListing(merged.catalogue, await openRouterListing());
181
+ await syncLifecycle();
144
182
  const changes = combineChanges(merged.changes, live.changes);
145
183
  const text = `${syncedHeader}${stringify(live.catalogue, { aliasDuplicateObjects: false })}`;
146
184
  const next = parseCatalogue(text);
@@ -169,6 +207,7 @@ export function createCatalogueStore(deps) {
169
207
  return last === null || at - Date.parse(last) >= catalogueCheckIntervalMs;
170
208
  },
171
209
  read,
210
+ lifecycle: readLifecycle,
172
211
  models: (provider, family) => read()[family].filter((m) => m.provider === provider && m.enabled && !m.deprecated && !isVideoModel(m)),
173
212
  status: () => {
174
213
  const saved = readSync();
@@ -1,3 +1,4 @@
1
+ import { createRows, editSettings } from "../kernel/ports/settings-places.js";
1
2
  import { usesNarrationPreparation, usesReference, usesShorts, usesYoutubeDescription, } from "../slices/admission/rules.js";
2
3
  import { isLocalCliProvider, isUncataloguedProvider } from "../slices/settings/model.js";
3
4
  import { usesAnimation } from "../slices/video/edit-settings.js";
@@ -32,7 +33,9 @@ export function modelFields(draft, catalogue) {
32
33
  },
33
34
  ];
34
35
  for (const { field, family, choice, needed } of checks) {
35
- if (!needed || !choice || isUncataloguedProvider(choice.provider))
36
+ // No model at all is admission's to say ("Choose a Service and a Model under …"): none was
37
+ // chosen, so none is "no longer" in the list.
38
+ if (!needed || !choice || choice.model === "" || isUncataloguedProvider(choice.provider))
36
39
  continue;
37
40
  const model = catalogue.models(choice.provider, family).find((m) => m.id === choice.model);
38
41
  if (!model)
@@ -87,7 +90,7 @@ export function modelFields(draft, catalogue) {
87
90
  if (offered.length === 0)
88
91
  fields.push({
89
92
  field: "videoEdit.animateModel",
90
- message: "This image provider can't animate images. Choose fal.ai or Replicate as the image provider (on Play's Images rail, or in Edit project → Providers), or turn Animate images off.",
93
+ message: `This image service can't animate images. Choose fal.ai or Replicate as the image service (in ${createRows.images}, or ${editSettings.images}), or turn Animate images off.`,
91
94
  });
92
95
  else if (model.trim() !== "" && !offered.some((one) => one.id === model))
93
96
  fields.push({
@@ -1,6 +1,7 @@
1
1
  import { execFile } from "node:child_process";
2
2
  import { mkdir, readFile, rename, rmdir, unlink, writeFile } from "node:fs/promises";
3
3
  import { posix, win32 } from "node:path";
4
+ import { hasErrnoCode } from "../../kernel/errors.js";
4
5
  import { agentLabel, cmdLauncher, desktopEntry, desktopExecArg, desktopMarker, launchAgent, launcherMarker, runKey, runValue, shellLauncher, windowsPathProblem, windowsRunCommand, xmlText, } from "./launcher.js";
5
6
  const launcherDir = "autostart";
6
7
  // How each entry spells the launcher's path.
@@ -173,7 +174,7 @@ export const nodeAutostartFs = {
173
174
  return await readFile(path, "utf8");
174
175
  }
175
176
  catch (error) {
176
- if (isMissing(error))
177
+ if (hasErrnoCode(error, "ENOENT"))
177
178
  return undefined;
178
179
  throw error;
179
180
  }
@@ -190,7 +191,7 @@ export const nodeAutostartFs = {
190
191
  await unlink(path);
191
192
  }
192
193
  catch (error) {
193
- if (!isMissing(error))
194
+ if (!hasErrnoCode(error, "ENOENT"))
194
195
  throw error;
195
196
  }
196
197
  },
@@ -214,6 +215,3 @@ export const nodeAutostartExec = (file, args) => new Promise((resolve) => {
214
215
  resolve({ code, stdout, stderr: stderr || (error?.message ?? "") });
215
216
  });
216
217
  });
217
- function isMissing(error) {
218
- return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
219
- }
@@ -1,4 +1,5 @@
1
1
  import { createInterface } from "node:readline/promises";
2
+ import { errorText } from "../../kernel/errors.js";
2
3
  export const autostartQuestion = "Start Slopify when you log in? (Y/n) ";
3
4
  // The two flags as one answer: undefined when neither was given.
4
5
  export function autostartFlag(values) {
@@ -67,6 +68,6 @@ export async function settleAutostart(options) {
67
68
  : `${view.summary} Turn it on any time in Settings → General.`);
68
69
  }
69
70
  catch (error) {
70
- options.warn(error instanceof Error ? error.message : String(error));
71
+ options.warn(errorText(error));
71
72
  }
72
73
  }
@@ -1,3 +1,4 @@
1
+ import { errnoCode, errorText } from "../../kernel/errors.js";
1
2
  import { readSetting, writeSetting } from "../../slices/settings/repo.js";
2
3
  import { desktopHowTo, howToFor } from "./docker.js";
3
4
  import { autostartAnsweredKey } from "./model.js";
@@ -77,10 +78,8 @@ function desktopSummary(docker) {
77
78
  }
78
79
  // The native steps already speak in sentences; a file error from the disk doesn't.
79
80
  function plain(error, enabled) {
80
- const message = error instanceof Error ? error.message : String(error);
81
- const code = error instanceof Error && "code" in error && typeof error.code === "string"
82
- ? error.code
83
- : undefined;
81
+ const message = errorText(error);
82
+ const code = errnoCode(error);
84
83
  if (code === undefined)
85
84
  return message;
86
85
  const path = error instanceof Error && "path" in error && typeof error.path === "string"
@@ -1,4 +1,5 @@
1
1
  import { parseArgs } from "node:util";
2
+ import { errnoCode, errorText } from "../kernel/errors.js";
2
3
  const options = {
3
4
  port: { type: "string" },
4
5
  host: { type: "string" },
@@ -24,15 +25,13 @@ export function parseCli(args) {
24
25
  parsed = parse(args);
25
26
  }
26
27
  catch (error) {
27
- const code = error instanceof Error && "code" in error && typeof error.code === "string"
28
- ? error.code
29
- : undefined;
28
+ const code = errnoCode(error);
30
29
  if (code === "ERR_PARSE_ARGS_UNKNOWN_OPTION") {
31
30
  const flag = /'([^']+)'/.exec(error instanceof Error ? error.message : "")?.[1];
32
31
  throw new Error(`Slopify doesn't know the option ${flag ?? "you gave"}. Run npx @gentbajko/slopify --help to see every option.`);
33
32
  }
34
33
  if (code === "ERR_PARSE_ARGS_INVALID_OPTION_VALUE")
35
- throw new Error(`${error instanceof Error ? error.message : String(error)}. Run npx @gentbajko/slopify --help to see how each option is written.`);
34
+ throw new Error(`${errorText(error)}. Run npx @gentbajko/slopify --help to see how each option is written.`);
36
35
  throw error;
37
36
  }
38
37
  if (parsed.values.help === true || parsed.positionals[0] === "help")
package/dist/edge/cli.js CHANGED
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { configFrom } from "../kernel/config/index.js";
3
+ import { errnoCode } from "../kernel/errors.js";
3
4
  import { readVersion } from "../kernel/version.js";
4
5
  import { boot } from "../main.js";
5
6
  import { forwardManagedUpdate } from "../updater/forward.js";
@@ -113,7 +114,7 @@ catch (error) {
113
114
  function explainStartupError(error, config) {
114
115
  if (!(error instanceof Error))
115
116
  return String(error);
116
- const code = "code" in error && typeof error.code === "string" ? error.code : undefined;
117
+ const code = errnoCode(error);
117
118
  const syscall = "syscall" in error && typeof error.syscall === "string" ? error.syscall : "";
118
119
  if (config !== undefined && syscall === "listen") {
119
120
  const other = config.port === 7070 ? 7071 : 7070;
@@ -3,11 +3,11 @@ import { constants } from "node:fs";
3
3
  import { cp, lstat, mkdir, open, readdir, readFile, rename, rm, rmdir, unlink, } from "node:fs/promises";
4
4
  import { dirname, join } from "node:path";
5
5
  import { setTimeout as delay } from "node:timers/promises";
6
- import { hasCode } from "../../host-cli/paths.js";
7
6
  import { privateRead } from "../../host-cli/service.js";
7
+ import { errorText, hasErrnoCode } from "../../kernel/errors.js";
8
8
  import { recoveryId } from "./engine.js";
9
9
  import { installSchema, legacyJournalSchema, legacyReceiptSchema, privateDirectory, readState, settledLegacyPhases, updateSchema, writeState, writeText, } from "./state.js";
10
- import { contains, identity, isMissing, privateTree, safePath, treeDigest } from "./tree.js";
10
+ import { contains, identity, privateTree, safePath, treeDigest } from "./tree.js";
11
11
  const upArgs = ["up", "--detach", "--force-recreate", "--no-build", "--pull", "never"];
12
12
  /**
13
13
  * Installs or updates the Docker installation `<name>`: one transaction that waits for running
@@ -247,13 +247,13 @@ async function locked(o, e, directory) {
247
247
  };
248
248
  }
249
249
  catch (cause) {
250
- const reason = cause instanceof Error ? cause.message : String(cause);
250
+ const reason = errorText(cause);
251
251
  try {
252
252
  await rollback(o, e, directory, u);
253
253
  await unlink(paths.update);
254
254
  }
255
255
  catch (failure) {
256
- throw new Error(`Slopify could not finish, and could not fully put the previous version back either. Don't delete anything: ${u.backup ? `your data's recovery copy is the Docker volume ${u.backup}, ` : ""}progress is recorded in ${paths.update}. Fix the problem below and run the same command again; it finishes the undo first. What failed: ${reason} Undo problem: ${failure instanceof Error ? failure.message : String(failure)}`, { cause });
256
+ throw new Error(`Slopify could not finish, and could not fully put the previous version back either. Don't delete anything: ${u.backup ? `your data's recovery copy is the Docker volume ${u.backup}, ` : ""}progress is recorded in ${paths.update}. Fix the problem below and run the same command again; it finishes the undo first. What failed: ${reason} Undo problem: ${errorText(failure)}`, { cause });
257
257
  }
258
258
  throw new Error(`${o.mode === "update" ? "The update" : "The install"} failed, so Slopify put the previous version back${u.previous.kind === "none" ? "" : " and nothing was lost"}. What failed: ${reason}${u.backup ? ` The recovery copy of your data is kept in the Docker volume ${u.backup}.` : ""}`, { cause });
259
259
  }
@@ -312,7 +312,7 @@ async function tidyUp(o, e, u) {
312
312
  removed.push(what);
313
313
  }
314
314
  catch (error) {
315
- problems.push(`Couldn't remove ${what}, so it is kept. ${fix} Why: ${error instanceof Error ? error.message : String(error)}`);
315
+ problems.push(`Couldn't remove ${what}, so it is kept. ${fix} Why: ${errorText(error)}`);
316
316
  }
317
317
  };
318
318
  try {
@@ -332,7 +332,7 @@ async function tidyUp(o, e, u) {
332
332
  }
333
333
  }
334
334
  catch (error) {
335
- problems.push(`Couldn't list older recovery volumes and containers to tidy up, so all of them are kept. See them with docker volume ls --filter label=io.slopify.transaction. Why: ${error instanceof Error ? error.message : String(error)}`);
335
+ problems.push(`Couldn't list older recovery volumes and containers to tidy up, so all of them are kept. See them with docker volume ls --filter label=io.slopify.transaction. Why: ${errorText(error)}`);
336
336
  }
337
337
  return { removed, problems };
338
338
  }
@@ -395,14 +395,14 @@ async function publishProjects(o, e, source, projects, id, current) {
395
395
  }
396
396
  // assertEmpty checked it before anything changed; rmdir still refuses if files appeared since.
397
397
  await rmdir(projects).catch((error) => {
398
- if (!isMissing(error))
398
+ if (!hasErrnoCode(error, "ENOENT"))
399
399
  throw error;
400
400
  });
401
401
  await rename(staging, projects);
402
402
  }
403
403
  async function assertFolder(path) {
404
404
  const s = await lstat(path).catch((error) => {
405
- if (isMissing(error))
405
+ if (hasErrnoCode(error, "ENOENT"))
406
406
  return null;
407
407
  throw error;
408
408
  });
@@ -411,7 +411,7 @@ async function assertFolder(path) {
411
411
  }
412
412
  async function assertEmpty(path) {
413
413
  const entries = await readdir(path).catch((error) => {
414
- if (isMissing(error))
414
+ if (hasErrnoCode(error, "ENOENT"))
415
415
  return [];
416
416
  throw error;
417
417
  });
@@ -437,7 +437,7 @@ async function lock(path) {
437
437
  return () => unlink(path);
438
438
  }
439
439
  catch (error) {
440
- if (!hasCode(error, "EEXIST"))
440
+ if (!hasErrnoCode(error, "EEXIST"))
441
441
  throw error;
442
442
  const pid = Number((await readFile(path, "utf8").catch(() => "")).trim());
443
443
  if (Number.isInteger(pid) && pid > 0 && alive(pid))
@@ -453,6 +453,6 @@ function alive(pid) {
453
453
  return true;
454
454
  }
455
455
  catch (error) {
456
- return hasCode(error, "EPERM");
456
+ return hasErrnoCode(error, "EPERM");
457
457
  }
458
458
  }
@@ -4,6 +4,7 @@ import { join, resolve } from "node:path";
4
4
  import { createInterface } from "node:readline/promises";
5
5
  import { fileURLToPath } from "node:url";
6
6
  import { nodeHostSetupRunner } from "../../host-cli/install.js";
7
+ import { errorText } from "../../kernel/errors.js";
7
8
  import { readVersion } from "../../kernel/version.js";
8
9
  import { documentsDir, nodeDocumentsHost } from "../../slices/storage/documents.js";
9
10
  import { recordLoginStart } from "../autostart/docker-record.js";
@@ -116,7 +117,7 @@ export async function runDockerCommand(command) {
116
117
  now: () => new Date(),
117
118
  report: (line) => console.log(line),
118
119
  }).catch((error) => {
119
- console.warn(`Slopify couldn't check whether Docker starts when you log in (${error instanceof Error ? error.message : String(error)}). Settings → General will say it doesn't know; run the command again to check again.`);
120
+ console.warn(`Slopify couldn't check whether Docker starts when you log in (${errorText(error)}). Settings → General will say it doesn't know; run the command again to check again.`);
120
121
  });
121
122
  }
122
123
  finally {
@@ -2,7 +2,8 @@ import { lstat, mkdir } from "node:fs/promises";
2
2
  import { dirname, isAbsolute, join, resolve, sep } from "node:path";
3
3
  import { z } from "zod";
4
4
  import { privateRead, privateWrite } from "../../host-cli/service.js";
5
- import { isMissing, syncDirectory } from "./tree.js";
5
+ import { hasErrnoCode } from "../../kernel/errors.js";
6
+ import { syncDirectory } from "./tree.js";
6
7
  export const identifier = z
7
8
  .string()
8
9
  .min(1)
@@ -102,7 +103,7 @@ export async function privateDirectory(path, uid) {
102
103
  for (const name of path.split(sep).filter(Boolean)) {
103
104
  current = join(current, name);
104
105
  await mkdir(current, { mode: 0o700 }).catch((error) => {
105
- if (!(typeof error === "object" && error !== null && "code" in error && error.code === "EEXIST"))
106
+ if (!hasErrnoCode(error, "EEXIST"))
106
107
  throw error;
107
108
  });
108
109
  const s = await lstat(current);
@@ -117,7 +118,7 @@ export async function privateDirectory(path, uid) {
117
118
  }
118
119
  export async function readState(path, schema, uid) {
119
120
  const s = await lstat(path).catch((error) => {
120
- if (isMissing(error))
121
+ if (hasErrnoCode(error, "ENOENT"))
121
122
  return undefined;
122
123
  throw error;
123
124
  });
@@ -2,6 +2,7 @@ import { createHash } from "node:crypto";
2
2
  import { constants } from "node:fs";
3
3
  import { chmod, lchown, lstat, mkdir, open, readdir, readlink } from "node:fs/promises";
4
4
  import { dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
5
+ import { hasErrnoCode } from "../../kernel/errors.js";
5
6
  export async function identity(path) {
6
7
  const s = await lstat(path, { bigint: true });
7
8
  if (!s.isDirectory() || s.isSymbolicLink())
@@ -42,7 +43,7 @@ export async function safePath(path, home, stateRoot, createParents) {
42
43
  for (const [i, part] of parts.entries()) {
43
44
  current = join(current, part);
44
45
  let s = await lstat(current).catch((error) => {
45
- if (isMissing(error))
46
+ if (hasErrnoCode(error, "ENOENT"))
46
47
  return undefined;
47
48
  throw error;
48
49
  });
@@ -60,9 +61,6 @@ export async function safePath(path, home, stateRoot, createParents) {
60
61
  throw new Error(`Other users can write to ${current}, which contains the project folder. Choose a project folder inside your home folder with --projects-dir <folder>, or fix it with chmod go-w ${current}.`);
61
62
  }
62
63
  }
63
- export function isMissing(error) {
64
- return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
65
- }
66
64
  export async function syncDirectory(path) {
67
65
  const fd = await open(path, constants.O_RDONLY | constants.O_DIRECTORY | constants.O_NOFOLLOW);
68
66
  try {
@@ -2,12 +2,13 @@ import { execFileSync } from "node:child_process";
2
2
  import { chmod, lchown, lstat, mkdir, readdir, rm } from "node:fs/promises";
3
3
  import { join } from "node:path";
4
4
  import { fileURLToPath } from "node:url";
5
- import { isMissing, syncDirectory, treeDigest } from "./tree.js";
5
+ import { hasErrnoCode } from "../../kernel/errors.js";
6
+ import { syncDirectory, treeDigest } from "./tree.js";
6
7
  export async function volumeOperation(args) {
7
8
  const [operation, user = "0:0"] = args;
8
9
  if (operation === "projects") {
9
10
  const present = await lstat("/source/projects").catch((e) => {
10
- if (isMissing(e))
11
+ if (hasErrnoCode(e, "ENOENT"))
11
12
  return null;
12
13
  throw e;
13
14
  });
@@ -3,9 +3,10 @@ import { join } from "node:path";
3
3
  import { setTimeout as delay } from "node:timers/promises";
4
4
  import { z } from "zod";
5
5
  import { installHostPackage } from "../host-cli/install.js";
6
- import { ensureBridgeToken, hasCode, prepareHostPaths } from "../host-cli/paths.js";
6
+ import { ensureBridgeToken, prepareHostPaths } from "../host-cli/paths.js";
7
7
  import { ensureHostService, privateRead, privateWrite } from "../host-cli/service.js";
8
8
  import { hostCommandName, resolveHostCommand } from "../host-cli/status.js";
9
+ import { errorText, hasErrnoCode } from "../kernel/errors.js";
9
10
  import { hostLlmIds } from "../kernel/ports/host-cli.js";
10
11
  export function assertManagedDockerHost(platform, uid, gid) {
11
12
  if (platform !== "linux")
@@ -28,8 +29,8 @@ export async function planDockerHostCli(options) {
28
29
  installed = true;
29
30
  }
30
31
  catch (error) {
31
- if (!hasCode(error, "ENOENT"))
32
- throw new Error(`Could not check whether ${hostCommandName(id)} is installed on this machine (${error instanceof Error ? error.message : String(error)}). Nothing was changed. Fix the problem, or start with --host-cli=off to use API keys only.`);
32
+ if (!hasErrnoCode(error, "ENOENT"))
33
+ throw new Error(`Could not check whether ${hostCommandName(id)} is installed on this machine (${errorText(error)}). Nothing was changed. Fix the problem, or start with --host-cli=off to use API keys only.`);
33
34
  }
34
35
  }
35
36
  if (!installed)
@@ -73,7 +74,7 @@ async function ensureDockerHostCli(options, uid, receiptPath) {
73
74
  break;
74
75
  }
75
76
  catch (error) {
76
- if (!hasCode(error, "EEXIST"))
77
+ if (!hasErrnoCode(error, "EEXIST"))
77
78
  throw error;
78
79
  if (Date.now() >= deadline)
79
80
  throw new Error(`Another Slopify launcher is setting up the host CLI helper right now. Wait for it to finish and try again. If no other launcher is running, delete the folder ${lock} and retry.`);
@@ -1,3 +1,4 @@
1
+ import { errorText } from "../../kernel/errors.js";
1
2
  import { createPreviewCache } from "./preview-cache.js";
2
3
  export function createHub(deps) {
3
4
  const previews = createPreviewCache();
@@ -20,7 +21,7 @@ export function createHub(deps) {
20
21
  .writeSSE({ event: event.type, data: JSON.stringify(event), id: deps.ids.next() })
21
22
  .catch((error) => {
22
23
  subscriber.drop();
23
- deps.log.write("warn", "sse.write", { detail: `${event.type}: ${messageOf(error)}` });
24
+ deps.log.write("warn", "sse.write", { detail: `${event.type}: ${errorText(error)}` });
24
25
  });
25
26
  };
26
27
  const join = (set, stream, signal, prune) => {
@@ -80,7 +81,7 @@ export function createHub(deps) {
80
81
  // What the AI models are writing right now, so a page opened mid-call shows it.
81
82
  for (const event of previews.snapshotAll()) {
82
83
  const shown = present(event);
83
- if (shown !== undefined)
84
+ if (shown !== undefined && deps.quiet?.(shown.projectId) !== true)
84
85
  send(subscriber, shown);
85
86
  }
86
87
  }
@@ -96,6 +97,8 @@ export function createHub(deps) {
96
97
  return;
97
98
  for (const subscriber of projects.get(projectId) ?? [])
98
99
  send(subscriber, shown);
100
+ if (deps.quiet?.(projectId) === true)
101
+ return;
99
102
  for (const subscriber of globals)
100
103
  send(subscriber, shown);
101
104
  },
@@ -120,6 +123,3 @@ export function observedHub(hub, observe) {
120
123
  },
121
124
  };
122
125
  }
123
- function messageOf(error) {
124
- return error instanceof Error ? error.message : String(error);
125
- }