@gentbajko/slopify 3.25.9 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (718) hide show
  1. package/dist/adapters/account-limits.js +30 -0
  2. package/dist/adapters/alignment/audio.js +1 -1
  3. package/dist/adapters/alignment/cache.js +4 -6
  4. package/dist/adapters/alignment/ctc.js +1 -2
  5. package/dist/adapters/alignment/lock.js +4 -3
  6. package/dist/adapters/alignment/multilingual.js +2 -4
  7. package/dist/adapters/alignment/prefetch.js +2 -1
  8. package/dist/adapters/alignment/runner.js +1 -1
  9. package/dist/adapters/alignment/worker.js +3 -2
  10. package/dist/adapters/explain.js +10 -12
  11. package/dist/adapters/ffmpeg.js +19 -1
  12. package/dist/adapters/host-cli/index.js +21 -4
  13. package/dist/adapters/host-cli/transport.js +2 -1
  14. package/dist/adapters/http-failure.js +53 -0
  15. package/dist/adapters/image/bytes.js +2 -1
  16. package/dist/adapters/image/codex.js +42 -9
  17. package/dist/adapters/image/fal.js +21 -53
  18. package/dist/adapters/image/google.js +33 -56
  19. package/dist/adapters/image/models.js +2 -2
  20. package/dist/adapters/image/openai.js +22 -48
  21. package/dist/adapters/image/reference.js +36 -0
  22. package/dist/adapters/image/replicate.js +21 -49
  23. package/dist/adapters/image/video.js +2 -1
  24. package/dist/adapters/interest/search-interest.js +113 -0
  25. package/dist/adapters/key-probes.js +54 -3
  26. package/dist/adapters/llm/antigravity-models.js +1 -1
  27. package/dist/adapters/llm/antigravity.js +11 -6
  28. package/dist/adapters/llm/assistant-cli.js +388 -0
  29. package/dist/adapters/llm/child-session.js +83 -0
  30. package/dist/adapters/llm/claude-code-models.js +52 -99
  31. package/dist/adapters/llm/claude-code.js +16 -4
  32. package/dist/adapters/llm/codex-limits.js +27 -68
  33. package/dist/adapters/llm/codex-models.js +1 -1
  34. package/dist/adapters/llm/codex-server-models.js +61 -109
  35. package/dist/adapters/llm/codex.js +12 -1
  36. package/dist/adapters/llm/document-workspace.js +3 -2
  37. package/dist/adapters/llm/image-workspace.js +3 -2
  38. package/dist/adapters/llm/openrouter.js +12 -48
  39. package/dist/adapters/llm/run-cli.js +9 -24
  40. package/dist/adapters/llm/sse-lines.js +5 -1
  41. package/dist/adapters/model-access.js +37 -0
  42. package/dist/adapters/tts/cartesia.js +15 -46
  43. package/dist/adapters/tts/elevenlabs.js +20 -52
  44. package/dist/adapters/tts/gemini.js +21 -41
  45. package/dist/adapters/tts/inworld-async.js +6 -2
  46. package/dist/adapters/tts/inworld.js +6 -2
  47. package/dist/adapters/tts/openai.js +20 -50
  48. package/dist/adapters/tts/system.js +2 -1
  49. package/dist/assets/models-lifecycle.yaml +6 -0
  50. package/dist/assistant-wiring.js +60 -0
  51. package/dist/autopilot-timers.js +59 -0
  52. package/dist/catalog/lifecycle.js +52 -0
  53. package/dist/catalog/propose.js +204 -0
  54. package/dist/catalog/registry.js +23 -14
  55. package/dist/catalog/schema.js +4 -1
  56. package/dist/catalog/store.js +39 -0
  57. package/dist/catalog/validate.js +5 -2
  58. package/dist/edge/autostart/native.js +3 -5
  59. package/dist/edge/autostart/prompt.js +2 -1
  60. package/dist/edge/autostart/service.js +3 -4
  61. package/dist/edge/cli-args.js +3 -4
  62. package/dist/edge/cli.js +2 -1
  63. package/dist/edge/docker-install/apply.js +11 -11
  64. package/dist/edge/docker-install/run.js +2 -1
  65. package/dist/edge/docker-install/state.js +4 -3
  66. package/dist/edge/docker-install/tree.js +2 -4
  67. package/dist/edge/docker-install/volume.js +3 -2
  68. package/dist/edge/docker.js +5 -4
  69. package/dist/edge/events/hub.js +5 -5
  70. package/dist/edge/http/actions.js +11 -32
  71. package/dist/edge/http/actor.js +5 -3
  72. package/dist/edge/http/app.js +86 -11
  73. package/dist/edge/http/assistant.js +129 -0
  74. package/dist/edge/http/audio-preview.js +4 -11
  75. package/dist/edge/http/auditions.js +1 -1
  76. package/dist/edge/http/autostart.js +5 -5
  77. package/dist/edge/http/backups.js +2 -4
  78. package/dist/edge/http/channel-memory.js +9 -22
  79. package/dist/edge/http/channels.js +14 -27
  80. package/dist/edge/http/checkpoints.js +39 -21
  81. package/dist/edge/http/design-templates.js +167 -0
  82. package/dist/edge/http/designs.js +178 -0
  83. package/dist/edge/http/diagnostics.js +5 -1
  84. package/dist/edge/http/document-themes.js +5 -14
  85. package/dist/edge/http/draft-files.js +1 -3
  86. package/dist/edge/http/draft-problem.js +5 -10
  87. package/dist/edge/http/drafts.js +3 -3
  88. package/dist/edge/http/entries.js +6 -9
  89. package/dist/edge/http/extension-auth.js +27 -0
  90. package/dist/edge/http/external-reviews.js +12 -11
  91. package/dist/edge/http/files.js +5 -11
  92. package/dist/edge/http/folder-location.js +1 -4
  93. package/dist/edge/http/fonts.js +0 -7
  94. package/dist/edge/http/home.js +47 -14
  95. package/dist/edge/http/host-cli.js +18 -8
  96. package/dist/edge/http/ids.js +8 -0
  97. package/dist/edge/http/keywords.js +35 -0
  98. package/dist/edge/http/model-checks.js +132 -0
  99. package/dist/edge/http/narration-peaks.js +5 -13
  100. package/dist/edge/http/onboarding.js +30 -26
  101. package/dist/edge/http/open-folder.js +5 -10
  102. package/dist/edge/http/outputs.js +7 -14
  103. package/dist/edge/http/patch-notes.js +6 -12
  104. package/dist/edge/http/planning.js +3 -7
  105. package/dist/edge/http/problem.js +2 -4
  106. package/dist/edge/http/project-create.js +2 -1
  107. package/dist/edge/http/project-templates.js +31 -19
  108. package/dist/edge/http/projects.js +24 -16
  109. package/dist/edge/http/prompts.js +9 -16
  110. package/dist/edge/http/pronunciations.js +1 -2
  111. package/dist/edge/http/providers.js +48 -34
  112. package/dist/edge/http/refusal.js +29 -0
  113. package/dist/edge/http/remote-access.js +40 -0
  114. package/dist/edge/http/remote-guard.js +71 -0
  115. package/dist/edge/http/request-guard.js +91 -0
  116. package/dist/edge/http/reviews.js +12 -25
  117. package/dist/edge/http/revision-files.js +6 -11
  118. package/dist/edge/http/revisions.js +14 -19
  119. package/dist/edge/http/run-cost.js +1 -2
  120. package/dist/edge/http/same-page.js +80 -0
  121. package/dist/edge/http/schedules.js +69 -40
  122. package/dist/edge/http/settings.js +27 -14
  123. package/dist/edge/http/social.js +283 -0
  124. package/dist/edge/http/staging.js +3 -5
  125. package/dist/edge/http/storage-files.js +5 -7
  126. package/dist/edge/http/storage.js +33 -25
  127. package/dist/edge/http/studio.js +94 -69
  128. package/dist/edge/http/style-preview.js +3 -6
  129. package/dist/edge/http/subtitles.js +3 -17
  130. package/dist/edge/http/template-studio.js +436 -0
  131. package/dist/edge/http/trash.js +11 -12
  132. package/dist/edge/http/tutorial.js +1 -2
  133. package/dist/edge/http/tutorials.js +5 -11
  134. package/dist/edge/http/update.js +7 -13
  135. package/dist/edge/http/waveform.js +3 -6
  136. package/dist/edge/http/youtube-edits.js +3 -4
  137. package/dist/edge/mcp/assistant.js +279 -0
  138. package/dist/edge/mcp/attribution.js +8 -2
  139. package/dist/edge/mcp/call-route.js +11 -2
  140. package/dist/edge/mcp/excluded-routes.js +29 -3
  141. package/dist/edge/mcp/http.js +11 -2
  142. package/dist/edge/mcp/instructions.js +6 -4
  143. package/dist/edge/mcp/library-tools.js +9 -5
  144. package/dist/edge/mcp/remake-tools.js +7 -4
  145. package/dist/edge/mcp/route-tool.js +35 -15
  146. package/dist/edge/mcp/server.js +13 -8
  147. package/dist/edge/mcp/tools-channels.js +11 -9
  148. package/dist/edge/mcp/tools-designs.js +165 -0
  149. package/dist/edge/mcp/tools-library.js +19 -7
  150. package/dist/edge/mcp/tools-planning.js +40 -21
  151. package/dist/edge/mcp/tools-projects.js +38 -11
  152. package/dist/edge/mcp/tools-publishing.js +9 -9
  153. package/dist/edge/mcp/tools-runs.js +23 -10
  154. package/dist/edge/mcp/tools-schedules.js +32 -8
  155. package/dist/edge/mcp/tools-setup.js +75 -11
  156. package/dist/edge/mcp/tools-social.js +47 -0
  157. package/dist/edge/mcp/tools-storage.js +11 -3
  158. package/dist/edge/mcp/tools-template-studio.js +166 -0
  159. package/dist/edge/mcp/tools.js +6 -0
  160. package/dist/edge/remote-access/cli.js +71 -0
  161. package/dist/edge/remote-access/model.js +32 -0
  162. package/dist/edge/remote-access/rules.js +207 -0
  163. package/dist/edge/remote-access/service.js +203 -0
  164. package/dist/edge/remote-access/store.js +44 -0
  165. package/dist/edge/remote-access/views.js +43 -0
  166. package/dist/extension/slopify-studio-chrome.zip +0 -0
  167. package/dist/extension/slopify-studio-firefox.zip +0 -0
  168. package/dist/host-cli/install.js +2 -2
  169. package/dist/host-cli/open-folder.js +2 -2
  170. package/dist/host-cli/paths.js +2 -4
  171. package/dist/host-cli/server.js +4 -4
  172. package/dist/host-cli/service.js +3 -3
  173. package/dist/host-cli/status.js +7 -7
  174. package/dist/kernel/db/migrations/0063-model-checks.sql +20 -0
  175. package/dist/kernel/db/migrations/0064-template-studio.sql +46 -0
  176. package/dist/kernel/db/migrations/0065-promise-and-assistant-reviews.sql +58 -0
  177. package/dist/kernel/db/migrations/0066-assistant.sql +44 -0
  178. package/dist/kernel/db/migrations/0067-autopilot.sql +6 -0
  179. package/dist/kernel/db/migrations/0068-topic-scores.sql +17 -0
  180. package/dist/kernel/db/migrations/0070-designs.sql +53 -0
  181. package/dist/kernel/db/migrations/0071-design-usage.sql +33 -0
  182. package/dist/kernel/db/migrations/0072-design-templates.sql +33 -0
  183. package/dist/kernel/db/migrations/0073-schedule-design-kind.sql +5 -0
  184. package/dist/kernel/db/migrations/0074-template-bakeoffs.sql +44 -0
  185. package/dist/kernel/db/migrations/0075-social-posts.sql +25 -0
  186. package/dist/kernel/db/migrations/0076-channel-social.sql +5 -0
  187. package/dist/kernel/db/migrations/0077-post-prompts.sql +17 -0
  188. package/dist/kernel/db/migrations/0078-uploaded-from-links.sql +7 -0
  189. package/dist/kernel/db/tx.js +2 -4
  190. package/dist/kernel/errors.js +27 -1
  191. package/dist/kernel/json-answer.js +15 -0
  192. package/dist/kernel/lock.js +4 -9
  193. package/dist/kernel/paths.js +8 -0
  194. package/dist/kernel/pipeline.js +12 -0
  195. package/dist/kernel/ports/assistant-cli.js +4 -0
  196. package/dist/kernel/ports/host-cli.js +3 -0
  197. package/dist/kernel/ports/interest.js +4 -0
  198. package/dist/kernel/ports/languages.js +0 -3
  199. package/dist/kernel/ports/model.js +2 -0
  200. package/dist/kernel/ports/settings-places.js +31 -0
  201. package/dist/kernel/ports/system-speech.js +31 -3
  202. package/dist/kernel/runner/attempt.js +14 -4
  203. package/dist/kernel/runner/audition.js +3 -1
  204. package/dist/kernel/runner/checkpoint-authority.js +2 -1
  205. package/dist/kernel/runner/index.js +8 -10
  206. package/dist/kernel/runner/model-access.js +40 -0
  207. package/dist/kernel/runner/model-check.js +153 -0
  208. package/dist/kernel/runner/providers.js +18 -12
  209. package/dist/kernel/runner/standalone.js +11 -7
  210. package/dist/main.js +338 -21
  211. package/dist/model-catalog.js +20 -0
  212. package/dist/model-checks.js +166 -0
  213. package/dist/patch-notes/4.0.0.md +51 -0
  214. package/dist/patch-notes/4.1.0.md +42 -0
  215. package/dist/patch-notes/index.json +12 -0
  216. package/dist/slices/admission/heads.js +2 -1
  217. package/dist/slices/admission/listing-facts.js +95 -0
  218. package/dist/slices/admission/repo.js +11 -7
  219. package/dist/slices/admission/rules.js +50 -15
  220. package/dist/slices/admission/schema.js +8 -0
  221. package/dist/slices/admission/stage-writes.js +0 -3
  222. package/dist/slices/admission/start.js +48 -31
  223. package/dist/slices/admission/state-words.js +34 -5
  224. package/dist/slices/admission/substitute.js +7 -4
  225. package/dist/slices/agents/attention-posts.js +31 -0
  226. package/dist/slices/agents/attention-templates.js +33 -0
  227. package/dist/slices/agents/attention.js +10 -1
  228. package/dist/slices/agents/connection.js +2 -6
  229. package/dist/slices/agents/model.js +6 -3
  230. package/dist/slices/agents/repo.js +15 -7
  231. package/dist/slices/article/continuation.js +0 -63
  232. package/dist/slices/article/plain.js +3 -2
  233. package/dist/slices/article/segments.js +2 -62
  234. package/dist/slices/assistant/access.js +1 -0
  235. package/dist/slices/assistant/asks.js +80 -0
  236. package/dist/slices/assistant/cost.js +54 -0
  237. package/dist/slices/assistant/gate.js +222 -0
  238. package/dist/slices/assistant/model.js +86 -0
  239. package/dist/slices/assistant/names.js +23 -0
  240. package/dist/slices/assistant/prompt.js +74 -0
  241. package/dist/slices/assistant/repo.js +74 -0
  242. package/dist/slices/assistant/tokens.js +18 -0
  243. package/dist/slices/assistant/turn.js +344 -0
  244. package/dist/slices/autopilot/buffer.js +76 -0
  245. package/dist/slices/autopilot/model.js +14 -0
  246. package/dist/slices/autopilot/notify.js +27 -0
  247. package/dist/slices/autopilot/repo.js +34 -0
  248. package/dist/slices/autopilot/signals.js +194 -0
  249. package/dist/slices/autopilot/warnings.js +85 -0
  250. package/dist/slices/autopilot/weekly.js +100 -0
  251. package/dist/slices/backups/files.js +2 -6
  252. package/dist/slices/backups/repo.js +3 -15
  253. package/dist/slices/backups/service.js +8 -7
  254. package/dist/slices/channels/cast-images.js +3 -2
  255. package/dist/slices/channels/model.js +0 -1
  256. package/dist/slices/channels/rebrand.js +0 -3
  257. package/dist/slices/channels/repo.js +4 -0
  258. package/dist/slices/channels/schema.js +7 -1
  259. package/dist/slices/channels/service.js +10 -0
  260. package/dist/slices/channels/videos.js +3 -15
  261. package/dist/slices/checkpoints/index.js +0 -1
  262. package/dist/slices/control/providers.js +2 -28
  263. package/dist/slices/designs/artwork.js +66 -0
  264. package/dist/slices/designs/budget.js +23 -0
  265. package/dist/slices/designs/calls.js +124 -0
  266. package/dist/slices/designs/check-context.js +38 -0
  267. package/dist/slices/designs/check-text.js +43 -0
  268. package/dist/slices/designs/fields.js +88 -0
  269. package/dist/slices/designs/frames.js +34 -0
  270. package/dist/slices/designs/gate.js +130 -0
  271. package/dist/slices/designs/layout.js +293 -0
  272. package/dist/slices/designs/model.js +35 -0
  273. package/dist/slices/designs/pdf-job.js +23 -0
  274. package/dist/slices/designs/pdf-pages.js +30 -0
  275. package/dist/slices/designs/pdf-runner.js +68 -0
  276. package/dist/slices/designs/pdf-worker.js +24 -0
  277. package/dist/slices/designs/picture-size.js +79 -0
  278. package/dist/slices/designs/pictures.js +55 -0
  279. package/dist/slices/designs/quote.js +24 -0
  280. package/dist/slices/designs/render-args.js +36 -0
  281. package/dist/slices/designs/render-input.js +59 -0
  282. package/dist/slices/designs/render.js +215 -0
  283. package/dist/slices/designs/repo.js +101 -0
  284. package/dist/slices/designs/requests.js +80 -0
  285. package/dist/slices/designs/runner.js +239 -0
  286. package/dist/slices/designs/sample-repo.js +91 -0
  287. package/dist/slices/designs/sample.js +223 -0
  288. package/dist/slices/designs/schema.js +87 -0
  289. package/dist/slices/designs/sections.js +44 -0
  290. package/dist/slices/designs/service.js +233 -0
  291. package/dist/slices/designs/steps-repo.js +102 -0
  292. package/dist/slices/designs/studio-kind.js +39 -0
  293. package/dist/slices/designs/template-checks.js +44 -0
  294. package/dist/slices/designs/template-make.js +118 -0
  295. package/dist/slices/designs/templates.js +218 -0
  296. package/dist/slices/document/fonts.js +2 -1
  297. package/dist/slices/document/model.js +7 -4
  298. package/dist/slices/document/render.js +2 -1
  299. package/dist/slices/document/theme-schema.js +1 -1
  300. package/dist/slices/document/theme.js +49 -3
  301. package/dist/slices/episodes/summarize.js +6 -2
  302. package/dist/slices/estimate/index.js +72 -28
  303. package/dist/slices/estimate/requests.js +4 -4
  304. package/dist/slices/fixes/rules.js +3 -1
  305. package/dist/slices/fonts/catalog.js +5 -3
  306. package/dist/slices/fonts/coverage.js +2 -1
  307. package/dist/slices/fonts/discovery.js +3 -2
  308. package/dist/slices/fonts/files.js +2 -6
  309. package/dist/slices/fonts/index.js +0 -1
  310. package/dist/slices/fonts/sfnt.js +45 -10
  311. package/dist/slices/images/appearance.js +8 -16
  312. package/dist/slices/images/scenes.js +102 -28
  313. package/dist/slices/keywords/digest.js +85 -0
  314. package/dist/slices/keywords/facts.js +92 -0
  315. package/dist/slices/keywords/fill.js +80 -0
  316. package/dist/slices/keywords/model.js +75 -0
  317. package/dist/slices/keywords/rules.js +187 -0
  318. package/dist/slices/keywords/schema.js +28 -0
  319. package/dist/slices/keywords/specs.js +260 -0
  320. package/dist/slices/keywords/values.js +74 -0
  321. package/dist/slices/library/lint.js +29 -12
  322. package/dist/slices/library/model.js +2 -0
  323. package/dist/slices/library/photorealistic.js +4 -12
  324. package/dist/slices/library/rename.js +9 -7
  325. package/dist/slices/library/save.js +14 -10
  326. package/dist/slices/library/slots.js +37 -11
  327. package/dist/slices/library/transfer.js +5 -4
  328. package/dist/slices/library/used-by.js +25 -10
  329. package/dist/slices/loudness/loudnorm.js +53 -12
  330. package/dist/slices/loudness/model.js +3 -2
  331. package/dist/slices/loudness/sentence-level.js +2 -1
  332. package/dist/slices/model-checks/cost.js +61 -0
  333. package/dist/slices/model-checks/listing.js +124 -0
  334. package/dist/slices/model-checks/model.js +20 -0
  335. package/dist/slices/model-checks/record.js +32 -0
  336. package/dist/slices/model-checks/repo.js +120 -0
  337. package/dist/slices/model-checks/rules.js +125 -0
  338. package/dist/slices/model-checks/run.js +143 -0
  339. package/dist/slices/model-checks/service.js +198 -0
  340. package/dist/slices/model-upkeep/model.js +1 -1
  341. package/dist/slices/model-upkeep/switch.js +72 -27
  342. package/dist/slices/model-upkeep/usage.js +39 -13
  343. package/dist/slices/narration/breaths.js +3 -1
  344. package/dist/slices/narration/clean-pieces.js +3 -1
  345. package/dist/slices/narration/concat.js +2 -1
  346. package/dist/slices/narration/pauses-model.js +3 -2
  347. package/dist/slices/narration/peaks.js +3 -4
  348. package/dist/slices/narration/pronunciation-chunks.js +4 -3
  349. package/dist/slices/narration/pronunciation.js +6 -4
  350. package/dist/slices/narration/steering.js +4 -3
  351. package/dist/slices/notifications/notifier.js +4 -3
  352. package/dist/slices/notifications/rules.js +5 -2
  353. package/dist/slices/notifications/settings.js +4 -12
  354. package/dist/slices/notifications/subject.js +4 -3
  355. package/dist/slices/onboarding/copy.js +21 -3
  356. package/dist/slices/onboarding/first-run.js +16 -40
  357. package/dist/slices/onboarding/full-video.js +3 -2
  358. package/dist/slices/onboarding/install.js +6 -4
  359. package/dist/slices/onboarding/model.js +26 -37
  360. package/dist/slices/onboarding/packs.js +22 -22
  361. package/dist/slices/onboarding/preferred-model.js +14 -0
  362. package/dist/slices/onboarding/quick-short.js +105 -65
  363. package/dist/slices/onboarding/sample.js +4 -2
  364. package/dist/slices/onboarding/state.js +9 -11
  365. package/dist/slices/onboarding/template.js +8 -6
  366. package/dist/slices/outputs/add.js +3 -2
  367. package/dist/slices/outputs/service.js +2 -2
  368. package/dist/slices/patch-notes/library.js +4 -3
  369. package/dist/slices/play-drafts/convert.js +4 -0
  370. package/dist/slices/play-drafts/readiness.js +3 -3
  371. package/dist/slices/play-drafts/review-inputs.js +9 -3
  372. package/dist/slices/play-drafts/review.js +5 -4
  373. package/dist/slices/play-drafts/schema.js +4 -0
  374. package/dist/slices/play-drafts/service.js +17 -7
  375. package/dist/slices/project-templates/from-project.js +9 -2
  376. package/dist/slices/project-templates/next-chapter.js +2 -1
  377. package/dist/slices/project-templates/provider-defaults.js +22 -0
  378. package/dist/slices/project-templates/repo.js +6 -1
  379. package/dist/slices/project-templates/setup-sections.js +26 -0
  380. package/dist/slices/project-templates/setup.js +14 -1
  381. package/dist/slices/project-templates/stand-ins.js +22 -0
  382. package/dist/slices/rebuild/activity.js +2 -0
  383. package/dist/slices/rebuild/admission-repo.js +3 -2
  384. package/dist/slices/rebuild/narration-history.js +4 -5
  385. package/dist/slices/rebuild/narration-retry.js +2 -1
  386. package/dist/slices/rebuild/preview-details.js +32 -14
  387. package/dist/slices/rebuild/preview-plan.js +3 -8
  388. package/dist/slices/rebuild/recipe-build.js +8 -3
  389. package/dist/slices/rebuild/recipe-describe.js +3 -3
  390. package/dist/slices/rebuild/recipe-digest.js +58 -0
  391. package/dist/slices/rebuild/recipe-input-schema.js +10 -0
  392. package/dist/slices/rebuild/recipe-keywords.js +71 -0
  393. package/dist/slices/rebuild/recipe-legacy.js +5 -1
  394. package/dist/slices/rebuild/recipe-model.js +4 -0
  395. package/dist/slices/rebuild/recipe-narration-text.js +2 -1
  396. package/dist/slices/rebuild/recipe-preparation.js +4 -4
  397. package/dist/slices/rebuild/recipe-reference.js +8 -4
  398. package/dist/slices/rebuild/recipe-reviews.js +27 -7
  399. package/dist/slices/rebuild/recipe-save.js +8 -5
  400. package/dist/slices/rebuild/recipe-scenes.js +40 -11
  401. package/dist/slices/rebuild/recipe-shorts.js +8 -8
  402. package/dist/slices/rebuild/recipe-social.js +46 -0
  403. package/dist/slices/rebuild/recipe-text.js +64 -20
  404. package/dist/slices/rebuild/recipe-validation.js +102 -31
  405. package/dist/slices/rebuild/recipe-visual.js +55 -16
  406. package/dist/slices/rebuild/recipe-voices.js +3 -2
  407. package/dist/slices/rebuild/recipe-work.js +19 -7
  408. package/dist/slices/rebuild/recipe-youtube.js +4 -3
  409. package/dist/slices/rebuild/recovery-selection.js +3 -1
  410. package/dist/slices/rebuild/recovery.js +9 -8
  411. package/dist/slices/rebuild/remake-outdated.js +5 -5
  412. package/dist/slices/rebuild/repo.js +4 -3
  413. package/dist/slices/rebuild/review-promise.js +25 -0
  414. package/dist/slices/rebuild/review-redo.js +3 -2
  415. package/dist/slices/rebuild/runtime-admission.js +4 -3
  416. package/dist/slices/rebuild/runtime-agent-review.js +11 -5
  417. package/dist/slices/rebuild/runtime-animate.js +10 -9
  418. package/dist/slices/rebuild/runtime-article.js +7 -5
  419. package/dist/slices/rebuild/runtime-checkpoints.js +5 -4
  420. package/dist/slices/rebuild/runtime-document.js +11 -13
  421. package/dist/slices/rebuild/runtime-export-bed.js +8 -12
  422. package/dist/slices/rebuild/runtime-export-edit.js +8 -16
  423. package/dist/slices/rebuild/runtime-export-inputs.js +12 -11
  424. package/dist/slices/rebuild/runtime-export-short.js +9 -5
  425. package/dist/slices/rebuild/runtime-export.js +38 -15
  426. package/dist/slices/rebuild/runtime-figure-card.js +2 -1
  427. package/dist/slices/rebuild/runtime-image.js +8 -12
  428. package/dist/slices/rebuild/runtime-instructions.js +2 -0
  429. package/dist/slices/rebuild/runtime-keywords.js +59 -0
  430. package/dist/slices/rebuild/runtime-lines.js +2 -11
  431. package/dist/slices/rebuild/runtime-local.js +17 -22
  432. package/dist/slices/rebuild/runtime-narration-publication.js +2 -5
  433. package/dist/slices/rebuild/runtime-narration-reuse.js +9 -13
  434. package/dist/slices/rebuild/runtime-narration-text.js +13 -17
  435. package/dist/slices/rebuild/runtime-pictures.js +2 -4
  436. package/dist/slices/rebuild/runtime-piece-label.js +10 -6
  437. package/dist/slices/rebuild/runtime-plan.js +31 -5
  438. package/dist/slices/rebuild/runtime-provider.js +67 -25
  439. package/dist/slices/rebuild/runtime-publication.js +10 -9
  440. package/dist/slices/rebuild/runtime-review.js +39 -33
  441. package/dist/slices/rebuild/runtime-run.js +4 -1
  442. package/dist/slices/rebuild/runtime-shorts.js +31 -50
  443. package/dist/slices/rebuild/runtime-store.js +20 -10
  444. package/dist/slices/rebuild/runtime-subtitles.js +28 -25
  445. package/dist/slices/rebuild/runtime-voices.js +10 -16
  446. package/dist/slices/rebuild/runtime-youtube.js +14 -31
  447. package/dist/slices/rebuild/service-readiness.js +11 -3
  448. package/dist/slices/rebuild/transition-repo.js +6 -5
  449. package/dist/slices/rebuild/work-records.js +6 -0
  450. package/dist/slices/reruns/cascade.js +1 -2
  451. package/dist/slices/reruns/index.js +6 -9
  452. package/dist/slices/research/synthesis.js +3 -2
  453. package/dist/slices/reviews/external-model.js +4 -1
  454. package/dist/slices/reviews/external-repo.js +2 -1
  455. package/dist/slices/reviews/external-rows.js +2 -3
  456. package/dist/slices/reviews/holds.js +5 -4
  457. package/dist/slices/reviews/model.js +32 -11
  458. package/dist/slices/reviews/repo.js +2 -1
  459. package/dist/slices/reviews/rules.js +4 -3
  460. package/dist/slices/reviews/verdict.js +2 -1
  461. package/dist/slices/reviews/view.js +5 -2
  462. package/dist/slices/revisions/downloads.js +4 -5
  463. package/dist/slices/revisions/image-plan.js +1 -1
  464. package/dist/slices/revisions/mutation-assets.js +9 -5
  465. package/dist/slices/revisions/mutation-cues.js +2 -5
  466. package/dist/slices/revisions/mutations.js +3 -3
  467. package/dist/slices/revisions/repo.js +3 -1
  468. package/dist/slices/revisions/schema.js +1 -0
  469. package/dist/slices/revisions/view.js +20 -0
  470. package/dist/slices/run-cost/limits.js +5 -2
  471. package/dist/slices/run-cost/meter.js +12 -5
  472. package/dist/slices/run-cost/panel.js +8 -74
  473. package/dist/slices/run-cost/plan-readings.js +127 -0
  474. package/dist/slices/run-cost/plan-use.js +169 -0
  475. package/dist/slices/run-cost/pricing.js +3 -3
  476. package/dist/slices/run-cost/week.js +32 -4
  477. package/dist/slices/schedules/agenda.js +18 -7
  478. package/dist/slices/schedules/by-date.js +42 -0
  479. package/dist/slices/schedules/calendar.js +5 -0
  480. package/dist/slices/schedules/design-agenda.js +36 -0
  481. package/dist/slices/schedules/design-check.js +41 -0
  482. package/dist/slices/schedules/design-run.js +126 -0
  483. package/dist/slices/schedules/next-run.js +62 -0
  484. package/dist/slices/schedules/prepare.js +18 -2
  485. package/dist/slices/schedules/repo.js +30 -21
  486. package/dist/slices/schedules/rescore.js +35 -0
  487. package/dist/slices/schedules/scheduler.js +13 -3
  488. package/dist/slices/schedules/schema.js +57 -3
  489. package/dist/slices/schedules/score.js +107 -0
  490. package/dist/slices/schedules/service.js +57 -24
  491. package/dist/slices/schedules/topic-list.js +15 -0
  492. package/dist/slices/schedules/topic-scores.js +104 -0
  493. package/dist/slices/schedules/topics.js +53 -41
  494. package/dist/slices/settings/cli-paths.js +4 -6
  495. package/dist/slices/settings/first-run.js +8 -43
  496. package/dist/slices/settings/health.js +30 -15
  497. package/dist/slices/settings/key-test.js +1 -1
  498. package/dist/slices/settings/model-reach.js +3 -17
  499. package/dist/slices/settings/model.js +14 -2
  500. package/dist/slices/settings/playback.js +34 -23
  501. package/dist/slices/settings/probe-read.js +16 -0
  502. package/dist/slices/settings/repo.js +33 -0
  503. package/dist/slices/settings/tutorial.js +2 -2
  504. package/dist/slices/settings/voices.js +4 -12
  505. package/dist/slices/shorts/keep.js +2 -1
  506. package/dist/slices/shorts/pick.js +6 -18
  507. package/dist/slices/shorts/prompts.js +4 -14
  508. package/dist/slices/shorts/render.js +6 -2
  509. package/dist/slices/social/channel.js +44 -0
  510. package/dist/slices/social/defaults.js +17 -0
  511. package/dist/slices/social/due.js +36 -0
  512. package/dist/slices/social/extension.js +18 -0
  513. package/dist/slices/social/fit.js +115 -0
  514. package/dist/slices/social/limits.js +186 -0
  515. package/dist/slices/social/links.js +21 -0
  516. package/dist/slices/social/media.js +132 -0
  517. package/dist/slices/social/model.js +75 -0
  518. package/dist/slices/social/notice.js +19 -0
  519. package/dist/slices/social/pack.js +176 -0
  520. package/dist/slices/social/post-prompt.js +56 -0
  521. package/dist/slices/social/queue.js +31 -0
  522. package/dist/slices/social/repo.js +133 -0
  523. package/dist/slices/social/reshape.js +97 -0
  524. package/dist/slices/social/rules.js +5 -0
  525. package/dist/slices/social/schema.js +70 -0
  526. package/dist/slices/social/serve.js +51 -0
  527. package/dist/slices/social/service.js +129 -0
  528. package/dist/slices/social/settings.js +21 -0
  529. package/dist/slices/social/sources.js +114 -0
  530. package/dist/slices/social/state.js +110 -0
  531. package/dist/slices/social/text.js +149 -0
  532. package/dist/slices/storage/arrange.js +3 -1
  533. package/dist/slices/storage/assets.js +8 -10
  534. package/dist/slices/storage/backup-designs.js +74 -0
  535. package/dist/slices/storage/backup-export.js +8 -3
  536. package/dist/slices/storage/backup-format.js +10 -0
  537. package/dist/slices/storage/backup-import.js +22 -4
  538. package/dist/slices/storage/delete-project.js +6 -5
  539. package/dist/slices/storage/files-location.js +6 -8
  540. package/dist/slices/storage/layout.js +13 -2
  541. package/dist/slices/storage/model.js +3 -0
  542. package/dist/slices/storage/portable.js +17 -12
  543. package/dist/slices/storage/schema.js +2 -0
  544. package/dist/slices/storage/staging-refs.js +2 -1
  545. package/dist/slices/storage/staging.js +6 -9
  546. package/dist/slices/storage/trim.js +26 -9
  547. package/dist/slices/studio/calendar.js +7 -2
  548. package/dist/slices/studio/disclosure.js +4 -4
  549. package/dist/slices/studio/model.js +1 -1
  550. package/dist/slices/studio/pack.js +9 -8
  551. package/dist/slices/studio/pick.js +2 -11
  552. package/dist/slices/studio/plan.js +7 -16
  553. package/dist/slices/studio/queue.js +3 -14
  554. package/dist/slices/studio/releases.js +26 -0
  555. package/dist/slices/studio/settings.js +20 -57
  556. package/dist/slices/studio/videos.js +35 -4
  557. package/dist/slices/style-preview/render.js +37 -16
  558. package/dist/slices/style-preview/schema.js +14 -1
  559. package/dist/slices/style-preview/service.js +2 -1
  560. package/dist/slices/style-preview/settings.js +33 -5
  561. package/dist/slices/subtitles/captions.js +1 -1
  562. package/dist/slices/telemetry/collector-client.js +2 -4
  563. package/dist/slices/telemetry/flush.js +2 -4
  564. package/dist/slices/telemetry/model.js +0 -7
  565. package/dist/slices/telemetry/record.js +10 -3
  566. package/dist/slices/template-studio/anatomy-view.js +161 -0
  567. package/dist/slices/template-studio/anatomy.js +73 -0
  568. package/dist/slices/template-studio/bakeoff-make.js +225 -0
  569. package/dist/slices/template-studio/bakeoff-repo.js +83 -0
  570. package/dist/slices/template-studio/bakeoff.js +333 -0
  571. package/dist/slices/template-studio/budget.js +106 -0
  572. package/dist/slices/template-studio/cards.js +78 -0
  573. package/dist/slices/template-studio/checks.js +322 -0
  574. package/dist/slices/template-studio/document-sample.js +56 -0
  575. package/dist/slices/template-studio/edit.js +15 -0
  576. package/dist/slices/template-studio/for-all.js +161 -0
  577. package/dist/slices/template-studio/free-video.js +31 -0
  578. package/dist/slices/template-studio/free.js +176 -0
  579. package/dist/slices/template-studio/gate.js +40 -0
  580. package/dist/slices/template-studio/hidden.js +20 -0
  581. package/dist/slices/template-studio/jobs.js +79 -0
  582. package/dist/slices/template-studio/loudness.js +111 -0
  583. package/dist/slices/template-studio/make.js +40 -0
  584. package/dist/slices/template-studio/model.js +58 -0
  585. package/dist/slices/template-studio/pack-import.js +253 -0
  586. package/dist/slices/template-studio/pack-samples.js +60 -0
  587. package/dist/slices/template-studio/pack.js +207 -0
  588. package/dist/slices/template-studio/paid-view.js +66 -0
  589. package/dist/slices/template-studio/paid.js +355 -0
  590. package/dist/slices/template-studio/quote.js +155 -0
  591. package/dist/slices/template-studio/ready.js +104 -0
  592. package/dist/slices/template-studio/repo.js +134 -0
  593. package/dist/slices/template-studio/reviews-path.js +58 -0
  594. package/dist/slices/template-studio/runner.js +84 -0
  595. package/dist/slices/template-studio/save.js +236 -0
  596. package/dist/slices/template-studio/say-it-as.js +248 -0
  597. package/dist/slices/template-studio/schedule-gate.js +34 -0
  598. package/dist/slices/template-studio/schedule-price.js +32 -0
  599. package/dist/slices/template-studio/schedule-sample.js +91 -0
  600. package/dist/slices/template-studio/schema.js +243 -0
  601. package/dist/slices/template-studio/scope.js +124 -0
  602. package/dist/slices/template-studio/sections.js +176 -0
  603. package/dist/slices/template-studio/service.js +175 -0
  604. package/dist/slices/template-studio/status.js +191 -0
  605. package/dist/slices/template-studio/topic.js +223 -0
  606. package/dist/slices/thumbnail/by-llm.js +1 -1
  607. package/dist/slices/trash/designs.js +76 -0
  608. package/dist/slices/trash/model.js +13 -4
  609. package/dist/slices/trash/service.js +52 -2
  610. package/dist/slices/tutorials/library.js +3 -2
  611. package/dist/slices/uploads/repo.js +37 -1
  612. package/dist/slices/uploads/rules.js +3 -2
  613. package/dist/slices/video/ass-text.js +17 -0
  614. package/dist/slices/video/audio-export.js +2 -64
  615. package/dist/slices/video/edit-list.js +2 -2
  616. package/dist/slices/video/edit-settings.js +1 -1
  617. package/dist/slices/video/encoding.js +169 -0
  618. package/dist/slices/video/ffmpeg.js +23 -21
  619. package/dist/slices/video/figure-card.js +1 -15
  620. package/dist/slices/video/plan.js +2 -1
  621. package/dist/slices/video/slideshow.js +43 -18
  622. package/dist/slices/voices/attribution.js +3 -2
  623. package/dist/slices/voices/model.js +9 -8
  624. package/dist/slices/voices/palette.js +0 -3
  625. package/dist/slices/voices/script.js +2 -1
  626. package/dist/slices/youtube/answer.js +4 -16
  627. package/dist/slices/youtube/edits-repo.js +3 -12
  628. package/dist/tutorials/AI-CLIs.md +25 -25
  629. package/dist/tutorials/Agents-MCP.md +34 -33
  630. package/dist/tutorials/Assistant.md +42 -0
  631. package/dist/tutorials/Backups.md +7 -7
  632. package/dist/tutorials/Calendar.md +17 -25
  633. package/dist/tutorials/Cast-Library.md +19 -19
  634. package/dist/tutorials/Channels.md +42 -35
  635. package/dist/tutorials/Costs-and-Run-Cost.md +38 -40
  636. package/dist/tutorials/Create-Article.md +114 -0
  637. package/dist/tutorials/Create-Extras.md +112 -0
  638. package/dist/tutorials/Create-Images.md +165 -0
  639. package/dist/tutorials/Create-Narration.md +178 -0
  640. package/dist/tutorials/Create-Overview.md +244 -0
  641. package/dist/tutorials/Create-Video-and-Style.md +144 -0
  642. package/dist/tutorials/Docker.md +3 -3
  643. package/dist/tutorials/Document-Themes.md +32 -32
  644. package/dist/tutorials/Editing-a-Project.md +94 -94
  645. package/dist/tutorials/FAQ.md +18 -18
  646. package/dist/tutorials/First-Launch-and-Welcome.md +50 -64
  647. package/dist/tutorials/Home-and-Projects.md +115 -71
  648. package/dist/tutorials/Home.md +33 -33
  649. package/dist/tutorials/Install.md +14 -13
  650. package/dist/tutorials/Intros-and-Outros.md +33 -34
  651. package/dist/tutorials/Keyboard-Shortcuts-and-Command-Palette.md +62 -58
  652. package/dist/tutorials/Keywords-Slopify-Fills.md +87 -0
  653. package/dist/tutorials/Models.md +53 -21
  654. package/dist/tutorials/Multiple-Voices.md +41 -40
  655. package/dist/tutorials/Narration-Aliases-and-Glossary.md +14 -14
  656. package/dist/tutorials/Notifications.md +27 -17
  657. package/dist/tutorials/Other-Languages.md +15 -15
  658. package/dist/tutorials/PDF-Documents.md +38 -29
  659. package/dist/tutorials/Posting-to-Social-Sites.md +121 -0
  660. package/dist/tutorials/Project-Page.md +118 -120
  661. package/dist/tutorials/Prompts-and-Templates.md +84 -0
  662. package/dist/tutorials/Prompts.md +48 -44
  663. package/dist/tutorials/Providers-and-Keys.md +105 -98
  664. package/dist/tutorials/Publishing-to-YouTube.md +31 -31
  665. package/dist/tutorials/Recovery-and-Retries.md +31 -31
  666. package/dist/tutorials/Remote-Access.md +63 -0
  667. package/dist/tutorials/Reviews-and-Checkpoints.md +98 -90
  668. package/dist/tutorials/Schedules.md +46 -27
  669. package/dist/tutorials/Settings-Reference.md +194 -174
  670. package/dist/tutorials/Shorts.md +34 -33
  671. package/dist/tutorials/Start-at-Login.md +3 -3
  672. package/dist/tutorials/Studio-Extension.md +22 -24
  673. package/dist/tutorials/Template-Studio.md +128 -0
  674. package/dist/tutorials/Templates.md +51 -77
  675. package/dist/tutorials/Trash.md +4 -4
  676. package/dist/tutorials/Troubleshooting.md +44 -44
  677. package/dist/tutorials/Uninstalling-and-Moving.md +5 -5
  678. package/dist/tutorials/Updating-and-Patch-Notes.md +18 -18
  679. package/dist/tutorials/Video-Editing.md +34 -34
  680. package/dist/tutorials/Where-Your-Files-Live.md +10 -10
  681. package/dist/tutorials/YouTube-Description.md +26 -26
  682. package/dist/tutorials/Your-First-Short.md +35 -35
  683. package/dist/tutorials/_Sidebar.md +19 -14
  684. package/dist/updater/work-in-progress.js +42 -12
  685. package/dist/web/assets/index-BNftKQrA.css +1 -0
  686. package/dist/web/assets/index-Cpa58woP.js +459 -0
  687. package/dist/web/assets/pdf-BKh8f7R6.js +56 -0
  688. package/dist/web/assets/pdf.worker.min-BmVo14Nb.mjs +28 -0
  689. package/dist/web/assets/pdf.worker.min-D7i8o3wR.js +1 -0
  690. package/dist/web/index.html +2 -2
  691. package/package.json +6 -2
  692. package/dist/slices/article/provided-entries.js +0 -66
  693. package/dist/slices/article/run.js +0 -145
  694. package/dist/slices/images/run.js +0 -234
  695. package/dist/slices/narration/legacy-plan.js +0 -58
  696. package/dist/slices/narration/run.js +0 -270
  697. package/dist/slices/rebuild/runtime-actions.js +0 -90
  698. package/dist/slices/research/run.js +0 -224
  699. package/dist/slices/subtitles/prepare.js +0 -194
  700. package/dist/slices/subtitles/transcript.js +0 -34
  701. package/dist/slices/thumbnail/run.js +0 -219
  702. package/dist/slices/video/audio-inputs.js +0 -33
  703. package/dist/slices/video/reuse-audio.js +0 -62
  704. package/dist/slices/video/run.js +0 -78
  705. package/dist/slices/video/write-export.js +0 -158
  706. package/dist/slices/video/write-subtitles.js +0 -59
  707. package/dist/tutorials/Library-Overview.md +0 -76
  708. package/dist/tutorials/Play-Images.md +0 -161
  709. package/dist/tutorials/Play-Narration.md +0 -167
  710. package/dist/tutorials/Play-Outputs.md +0 -109
  711. package/dist/tutorials/Play-Overview.md +0 -227
  712. package/dist/tutorials/Play-Title-and-Article.md +0 -136
  713. package/dist/tutorials/Play-Video-and-Style.md +0 -143
  714. package/dist/web/assets/index-BadsoORk.css +0 -1
  715. package/dist/web/assets/index-D8LqNsCl.js +0 -326
  716. package/dist/web/assets/pdf-T7MCwjIv.js +0 -54
  717. package/dist/web/assets/pdf.worker.min-Dswkl-cV.mjs +0 -29
  718. package/dist/web/assets/pdf.worker.min-zC6nfbxG.js +0 -1
@@ -0,0 +1,83 @@
1
+ import { spawn } from "node:child_process";
2
+ import { mkdtemp, rm } from "node:fs/promises";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ export async function withChildSession(spec, work) {
6
+ const directory = await mkdtemp(join(tmpdir(), spec.directoryPrefix));
7
+ const child = spawn(spec.file, [...spec.args], {
8
+ cwd: directory,
9
+ env: spec.env(directory),
10
+ stdio: ["pipe", "pipe", "pipe"],
11
+ windowsHide: true,
12
+ detached: process.platform !== "win32",
13
+ });
14
+ child.on("error", () => { });
15
+ child.stdin.on("error", () => { });
16
+ child.stderr.resume();
17
+ const closed = new Promise((resolve) => child.once("close", () => resolve()));
18
+ const terminate = (signal) => {
19
+ if (process.platform !== "win32" && child.pid !== undefined) {
20
+ try {
21
+ process.kill(-child.pid, signal);
22
+ return;
23
+ }
24
+ catch {
25
+ // A child that already exited has no process group to signal.
26
+ }
27
+ }
28
+ child.kill(signal);
29
+ };
30
+ let forceTimer;
31
+ const timer = setTimeout(() => {
32
+ if (spec.killAfterTermMs === undefined) {
33
+ terminate("SIGKILL");
34
+ return;
35
+ }
36
+ terminate("SIGTERM");
37
+ forceTimer = setTimeout(() => terminate("SIGKILL"), spec.killAfterTermMs);
38
+ }, spec.timeoutMs);
39
+ try {
40
+ return await work({
41
+ child,
42
+ send: (message) => {
43
+ child.stdin.write(`${JSON.stringify(message)}\n`);
44
+ },
45
+ });
46
+ }
47
+ finally {
48
+ clearTimeout(timer);
49
+ if (forceTimer !== undefined)
50
+ clearTimeout(forceTimer);
51
+ terminate("SIGTERM");
52
+ if (!(await closesWithin(closed, spec.graceMs))) {
53
+ terminate("SIGKILL");
54
+ if (spec.settleMs !== undefined)
55
+ await closesWithin(closed, spec.settleMs);
56
+ }
57
+ await rm(directory, { recursive: true, force: true, maxRetries: 3, retryDelay: 50 });
58
+ }
59
+ }
60
+ async function closesWithin(closed, ms) {
61
+ let timer;
62
+ try {
63
+ return await Promise.race([
64
+ closed.then(() => true),
65
+ new Promise((resolve) => {
66
+ timer = setTimeout(() => resolve(false), ms);
67
+ }),
68
+ ]);
69
+ }
70
+ finally {
71
+ clearTimeout(timer);
72
+ }
73
+ }
74
+ // The child's output, ended with an error once more than `maxBytes` has arrived.
75
+ export async function* cappedOutput(chunks, maxBytes, oversize) {
76
+ let bytes = 0;
77
+ for await (const chunk of chunks) {
78
+ bytes += chunk.byteLength;
79
+ if (bytes > maxBytes)
80
+ throw oversize();
81
+ yield chunk;
82
+ }
83
+ }
@@ -1,10 +1,8 @@
1
- import { spawn } from "node:child_process";
2
1
  import { randomUUID } from "node:crypto";
3
- import { mkdtemp, rm } from "node:fs/promises";
4
- import { tmpdir } from "node:os";
5
- import { join } from "node:path";
6
2
  import { z } from "zod";
7
3
  import { cliCommand } from "../../kernel/cli-command.js";
4
+ import { cappedOutput, withChildSession } from "./child-session.js";
5
+ import { lines } from "./sse-lines.js";
8
6
  const maxOutputBytes = 1024 * 1024;
9
7
  const modelId = z
10
8
  .string()
@@ -38,7 +36,7 @@ const responseSchema = z.object({
38
36
  });
39
37
  const supportedEfforts = ["low", "medium", "high", "xhigh"];
40
38
  function unavailable() {
41
- return new Error("Slopify could not get the model list from the Claude Code CLI. Check the CLI is installed and signed in (Settings → Providers), then refresh the list, or type an exact model ID.");
39
+ return new Error("Slopify could not get the model list from the Claude Code CLI. Check the CLI is installed and signed in (Settings → Keys & services), then refresh the list, or type an exact model ID.");
42
40
  }
43
41
  function discoveryEnv() {
44
42
  const names = [
@@ -109,104 +107,59 @@ function claudeModelName(target, description, fallback) {
109
107
  // The installed CLI has no model-list command; initialize is a no-prompt
110
108
  // stream-JSON control exchange. Treat protocol drift as unavailable metadata.
111
109
  export async function nodeClaudeCodeModels(binary, timeoutMs = 15_000) {
112
- const directory = await mkdtemp(join(tmpdir(), "slopify-claude-models-"));
113
110
  const requestId = randomUUID();
114
111
  const command = cliCommand(binary);
115
- const child = spawn(command.file, [
116
- ...command.args,
117
- "-p",
118
- "--input-format",
119
- "stream-json",
120
- "--output-format",
121
- "stream-json",
122
- "--verbose",
123
- "--safe-mode",
124
- "--tools",
125
- "",
126
- "--strict-mcp-config",
127
- "--no-session-persistence",
128
- ], {
129
- cwd: directory,
130
- env: discoveryEnv(),
131
- stdio: ["pipe", "pipe", "pipe"],
132
- windowsHide: true,
133
- detached: process.platform !== "win32",
134
- });
135
- child.on("error", () => { });
136
- child.stdin.on("error", () => { });
137
- child.stderr.resume();
138
- const closed = new Promise((resolve) => child.once("close", () => resolve()));
139
- const terminate = (force) => {
140
- const signal = force ? "SIGKILL" : "SIGTERM";
141
- if (process.platform !== "win32" && child.pid !== undefined) {
142
- try {
143
- process.kill(-child.pid, signal);
144
- return;
145
- }
146
- catch {
147
- // A child that already exited has no process group to signal.
148
- }
149
- }
150
- child.kill(signal);
151
- };
152
- let forceTimer;
153
- const timer = setTimeout(() => {
154
- terminate(false);
155
- forceTimer = setTimeout(() => terminate(true), 500);
156
- }, timeoutMs);
157
- try {
158
- child.stdin.write(`${JSON.stringify({
159
- request_id: requestId,
160
- type: "control_request",
161
- request: { subtype: "initialize" },
162
- })}\n`);
163
- let output = "";
164
- let bytes = 0;
165
- for await (const piece of child.stdout) {
166
- bytes += piece.length;
167
- if (bytes > maxOutputBytes)
168
- throw unavailable();
169
- output += piece.toString();
170
- let newline = output.indexOf("\n");
171
- while (newline >= 0) {
172
- const line = output.slice(0, newline).trim();
173
- output = output.slice(newline + 1);
174
- if (line !== "") {
175
- let event;
176
- try {
177
- event = JSON.parse(line);
178
- }
179
- catch {
180
- throw unavailable();
181
- }
182
- if (typeof event === "object" &&
183
- event !== null &&
184
- "type" in event &&
185
- event.type === "control_response") {
186
- return choices(event, requestId);
187
- }
112
+ return withChildSession({
113
+ file: command.file,
114
+ args: [
115
+ ...command.args,
116
+ "-p",
117
+ "--input-format",
118
+ "stream-json",
119
+ "--output-format",
120
+ "stream-json",
121
+ "--verbose",
122
+ "--safe-mode",
123
+ "--tools",
124
+ "",
125
+ "--strict-mcp-config",
126
+ "--no-session-persistence",
127
+ ],
128
+ env: () => discoveryEnv(),
129
+ directoryPrefix: "slopify-claude-models-",
130
+ timeoutMs,
131
+ killAfterTermMs: 500,
132
+ graceMs: 500,
133
+ settleMs: 500,
134
+ }, async ({ child, send }) => {
135
+ try {
136
+ send({
137
+ request_id: requestId,
138
+ type: "control_request",
139
+ request: { subtype: "initialize" },
140
+ });
141
+ for await (const text of lines(cappedOutput(child.stdout, maxOutputBytes, unavailable))) {
142
+ const line = text.trim();
143
+ if (line === "")
144
+ continue;
145
+ let event;
146
+ try {
147
+ event = JSON.parse(line);
148
+ }
149
+ catch {
150
+ throw unavailable();
151
+ }
152
+ if (typeof event === "object" &&
153
+ event !== null &&
154
+ "type" in event &&
155
+ event.type === "control_response") {
156
+ return choices(event, requestId);
188
157
  }
189
- newline = output.indexOf("\n");
190
158
  }
159
+ throw unavailable();
191
160
  }
192
- throw unavailable();
193
- }
194
- catch {
195
- throw unavailable();
196
- }
197
- finally {
198
- clearTimeout(timer);
199
- if (forceTimer !== undefined)
200
- clearTimeout(forceTimer);
201
- terminate(false);
202
- const grace = await Promise.race([
203
- closed.then(() => true),
204
- new Promise((resolve) => setTimeout(() => resolve(false), 500)),
205
- ]);
206
- if (!grace) {
207
- terminate(true);
208
- await Promise.race([closed, new Promise((resolve) => setTimeout(resolve, 500))]);
161
+ catch {
162
+ throw unavailable();
209
163
  }
210
- await rm(directory, { recursive: true, force: true, maxRetries: 3, retryDelay: 50 });
211
- }
164
+ });
212
165
  }
@@ -2,6 +2,7 @@ import { z } from "zod";
2
2
  import { redact } from "../../kernel/log.js";
3
3
  import { providerError } from "../../kernel/ports/model.js";
4
4
  import { isoOfEpoch } from "../../kernel/ports/plan-limits.js";
5
+ import { editSettings } from "../../kernel/ports/settings-places.js";
5
6
  import { cliCheck, cliReported, commandOf } from "../explain.js";
6
7
  import { nodeClaudeCodeModels } from "./claude-code-models.js";
7
8
  import { cliLoginError } from "./cli-login-error.js";
@@ -142,7 +143,11 @@ export function claudeCodeLlm(deps) {
142
143
  const read = new Set();
143
144
  let run;
144
145
  let ended;
146
+ // A call of several model turns reports its windows once per turn: the first is kept as
147
+ // the call's "before", the last as its "after".
148
+ let firstLimits;
145
149
  let limits;
150
+ let limitEvents = 0;
146
151
  try {
147
152
  images = imageWorkspace(req.images);
148
153
  const folder = images?.directory ?? documents?.directory;
@@ -191,8 +196,11 @@ export function claudeCodeLlm(deps) {
191
196
  // A shape this version does not know is not a failure: the plan windows are
192
197
  // reported beside the answer, never needed for it.
193
198
  const parsed = rateLimitEvent.safeParse(event.value);
194
- if (parsed.success)
199
+ if (parsed.success) {
200
+ firstLimits ??= parsed.data.rate_limit_info;
195
201
  limits = parsed.data.rate_limit_info;
202
+ limitEvents += 1;
203
+ }
196
204
  continue;
197
205
  }
198
206
  if (event.type === "assistant" && !documents) {
@@ -231,6 +239,7 @@ export function claudeCodeLlm(deps) {
231
239
  });
232
240
  throw providerError({
233
241
  kind: kindOf(result.api_error_status ?? null),
242
+ ...(result.api_error_status === 404 ? { access: "not-found" } : {}),
234
243
  message: cliReported(binary, redact(result.result ?? result.subtype), nextStep(binary, result.api_error_status ?? null)),
235
244
  });
236
245
  }
@@ -240,11 +249,14 @@ export function claudeCodeLlm(deps) {
240
249
  if ((documents || images) && result.result)
241
250
  yield { type: "delta", text: result.result };
242
251
  const windows = limits === undefined ? [] : claudeWindows(limits);
252
+ const start = limitEvents > 1 && firstLimits !== undefined ? claudeWindows(firstLimits) : [];
243
253
  yield {
244
254
  type: "done",
245
255
  usage: usageOf(result.modelUsage),
246
256
  finishReason: result.stop_reason ?? null,
247
- ...(windows.length === 0 ? {} : { limits: { after: windows } }),
257
+ ...(windows.length === 0
258
+ ? {}
259
+ : { limits: { ...(start.length === 0 ? {} : { before: start }), after: windows } }),
248
260
  };
249
261
  return;
250
262
  }
@@ -273,7 +285,7 @@ export function claudeCodeLlm(deps) {
273
285
  req.signal.throwIfAborted();
274
286
  // The stream ended with no result event at all.
275
287
  if (!run)
276
- throw new Error("The Claude Code CLI could not be started. Check it is installed and set up in Settings → Providers, then use Try again.");
288
+ throw new Error("The Claude Code CLI could not be started. Check it is installed and set up in Settings → Keys & services, then use Try again.");
277
289
  const login = cliLoginError("claude-code", run.stderr());
278
290
  if (login)
279
291
  throw login;
@@ -311,7 +323,7 @@ function nextStep(binary, status) {
311
323
  if (status === 429)
312
324
  return "Your Claude usage limit may be used up: wait until it resets, then use Try again.";
313
325
  if (status === 404)
314
- return "The chosen model may not exist or not be available to your account: choose another in the Providers section of Edit project, then use Try again.";
326
+ return `The chosen model may not exist or not be available to your account: choose another in ${editSettings.writer}, then use Try again.`;
315
327
  return cliCheck(binary);
316
328
  }
317
329
  // `modelUsage` is keyed by model id and a run may touch more than one - a fallback model,
@@ -1,10 +1,8 @@
1
- import { spawn } from "node:child_process";
2
- import { mkdtemp, rm } from "node:fs/promises";
3
- import { tmpdir } from "node:os";
4
- import { join } from "node:path";
5
1
  import { z } from "zod";
6
2
  import { cliCommand } from "../../kernel/cli-command.js";
7
3
  import { isoOfEpoch, windowKindOf, } from "../../kernel/ports/plan-limits.js";
4
+ import { withChildSession } from "./child-session.js";
5
+ import { lines } from "./sse-lines.js";
8
6
  // The Codex plan windows. `codex exec --json` reports none, so they are asked of the CLI's
9
7
  // app server with `account/rateLimits/read` - a metadata-only exchange that starts no thread
10
8
  // and spends nothing. Measured on 0.155.1: the reply carries `rateLimits.primary` and
@@ -40,49 +38,26 @@ export function codexWindows(result) {
40
38
  // method, a slow start: the windows are reported beside a run, never needed for it.
41
39
  export async function nodeCodexLimits(binary, env, timeoutMs = 10_000) {
42
40
  const command = cliCommand(binary);
43
- const directory = await mkdtemp(join(tmpdir(), "slopify-codex-limits-"));
44
- const child = spawn(command.file, [...command.args, "app-server", "--listen", "stdio://"], {
45
- cwd: directory,
46
- env: { ...env, PWD: directory },
47
- stdio: ["pipe", "pipe", "pipe"],
48
- windowsHide: true,
49
- detached: process.platform !== "win32",
50
- });
51
- child.on("error", () => { });
52
- child.stdin.on("error", () => { });
53
- child.stderr.resume();
54
- const closed = new Promise((resolve) => child.once("close", () => resolve()));
55
- const terminate = (signal) => {
56
- if (process.platform !== "win32" && child.pid !== undefined) {
57
- try {
58
- process.kill(-child.pid, signal);
59
- return;
60
- }
61
- catch {
62
- /* The process may already have exited. */
63
- }
64
- }
65
- child.kill(signal);
66
- };
67
- const timer = setTimeout(() => terminate("SIGKILL"), timeoutMs);
68
- const send = (message) => child.stdin.write(`${JSON.stringify(message)}\n`);
69
- let buffer = "";
70
- try {
71
- send({
72
- id: 1,
73
- method: "initialize",
74
- params: { clientInfo: { name: "slopify_limits", version: "1.0" } },
75
- });
76
- child.stdout.setEncoding("utf8");
77
- for await (const piece of child.stdout) {
78
- buffer += piece;
79
- if (buffer.length > 1024 * 1024)
80
- return null;
81
- let newline = buffer.indexOf("\n");
82
- while (newline >= 0) {
83
- const line = buffer.slice(0, newline).trim();
84
- buffer = buffer.slice(newline + 1);
85
- newline = buffer.indexOf("\n");
41
+ const oversize = () => new Error("Oversized reply");
42
+ return withChildSession({
43
+ file: command.file,
44
+ args: [...command.args, "app-server", "--listen", "stdio://"],
45
+ env: (directory) => ({ ...env, PWD: directory }),
46
+ directoryPrefix: "slopify-codex-limits-",
47
+ timeoutMs,
48
+ graceMs: 1000,
49
+ }, async ({ child, send }) => {
50
+ try {
51
+ send({
52
+ id: 1,
53
+ method: "initialize",
54
+ params: { clientInfo: { name: "slopify_limits", version: "1.0" } },
55
+ });
56
+ for await (const raw of lines(child.stdout, undefined, {
57
+ chars: 1024 * 1024,
58
+ error: oversize,
59
+ })) {
60
+ const line = raw.trim();
86
61
  if (line === "")
87
62
  continue;
88
63
  const reply = z
@@ -99,28 +74,12 @@ export async function nodeCodexLimits(binary, env, timeoutMs = 10_000) {
99
74
  return windows.length === 0 ? null : windows;
100
75
  }
101
76
  }
77
+ return null;
102
78
  }
103
- return null;
104
- }
105
- catch {
106
- return null;
107
- }
108
- finally {
109
- clearTimeout(timer);
110
- terminate("SIGTERM");
111
- let grace;
112
- await Promise.race([
113
- closed,
114
- new Promise((resolve) => {
115
- grace = setTimeout(() => {
116
- terminate("SIGKILL");
117
- resolve();
118
- }, 1000);
119
- }),
120
- ]);
121
- clearTimeout(grace);
122
- await rm(directory, { recursive: true, force: true });
123
- }
79
+ catch {
80
+ return null;
81
+ }
82
+ });
124
83
  }
125
84
  const months = ["jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec"];
126
85
  // Codex refuses a turn over the plan's allowance with "You've hit your usage limit. … Try
@@ -59,7 +59,7 @@ export async function nodeCodexModels(env = process.env, binary = "codex", timeo
59
59
  }
60
60
  catch {
61
61
  // Do not expose cache contents, home paths or raw JSON errors to the browser.
62
- throw new Error("Slopify could not get the model list from the Codex CLI. Check the CLI is installed and signed in (Settings → Providers), then refresh the list, or type an exact model ID.");
62
+ throw new Error("Slopify could not get the model list from the Codex CLI. Check the CLI is installed and signed in (Settings → Keys & services), then refresh the list, or type an exact model ID.");
63
63
  }
64
64
  }
65
65
  }
@@ -1,10 +1,8 @@
1
- import { spawn } from "node:child_process";
2
- import { mkdtemp, rm } from "node:fs/promises";
3
- import { tmpdir } from "node:os";
4
- import { join } from "node:path";
5
1
  import { z } from "zod";
6
2
  import { cliCommand } from "../../kernel/cli-command.js";
7
3
  import { thinkingModes as knownEfforts } from "../../kernel/ports/llm.js";
4
+ import { cappedOutput, withChildSession } from "./child-session.js";
5
+ import { lines } from "./sse-lines.js";
8
6
  const text = z
9
7
  .string()
10
8
  .trim()
@@ -28,39 +26,18 @@ const pageSchema = z.object({
28
26
  // model/list is a metadata-only app-server exchange: no thread, turn or tool is started.
29
27
  export async function nodeCodexServerModels(binary, env, timeoutMs = 15_000) {
30
28
  const command = cliCommand(binary);
31
- const directory = await mkdtemp(join(tmpdir(), "slopify-codex-models-"));
32
- const child = spawn(command.file, [...command.args, "app-server", "--listen", "stdio://"], {
33
- cwd: directory,
34
- env: { ...env, PWD: directory },
35
- stdio: ["pipe", "pipe", "pipe"],
36
- windowsHide: true,
37
- detached: process.platform !== "win32",
38
- });
39
- child.on("error", () => { });
40
- child.stdin.on("error", () => { });
41
- child.stderr.resume();
42
- const closed = new Promise((resolve) => child.once("close", () => resolve()));
43
- function terminate(signal) {
44
- if (process.platform !== "win32" && child.pid !== undefined) {
45
- try {
46
- process.kill(-child.pid, signal);
47
- return;
48
- }
49
- catch {
50
- /* The process may already have exited. */
51
- }
52
- }
53
- child.kill(signal);
54
- }
55
- const timer = setTimeout(() => terminate("SIGKILL"), timeoutMs);
56
- const send = (message) => child.stdin.write(`${JSON.stringify(message)}\n`);
57
- let expectedId = 1;
58
- let pages = 0;
59
- let bytes = 0;
60
- let buffer = "";
61
- const models = new Map();
62
- const cursors = new Set();
63
- try {
29
+ return withChildSession({
30
+ file: command.file,
31
+ args: [...command.args, "app-server", "--listen", "stdio://"],
32
+ env: (directory) => ({ ...env, PWD: directory }),
33
+ directoryPrefix: "slopify-codex-models-",
34
+ timeoutMs,
35
+ graceMs: 500,
36
+ }, async ({ child, send }) => {
37
+ let expectedId = 1;
38
+ let pages = 0;
39
+ const models = new Map();
40
+ const cursors = new Set();
64
41
  send({
65
42
  id: expectedId,
66
43
  method: "initialize",
@@ -68,83 +45,58 @@ export async function nodeCodexServerModels(binary, env, timeoutMs = 15_000) {
68
45
  clientInfo: { name: "slopify_model_discovery", version: "1.0" },
69
46
  },
70
47
  });
71
- child.stdout.setEncoding("utf8");
72
- for await (const piece of child.stdout) {
73
- bytes += Buffer.byteLength(piece);
74
- if (bytes > 4 * 1024 * 1024)
75
- throw new Error("Oversized metadata");
76
- buffer += piece;
77
- let newline = buffer.indexOf("\n");
78
- while (newline >= 0) {
79
- const line = buffer.slice(0, newline).trim();
80
- buffer = buffer.slice(newline + 1);
81
- newline = buffer.indexOf("\n");
82
- if (line === "")
83
- continue;
84
- const event = z
85
- .object({
86
- id: z.unknown().optional(),
87
- result: z.unknown().optional(),
88
- error: z.unknown().optional(),
89
- })
90
- .parse(JSON.parse(line));
91
- if (event.id !== expectedId)
92
- continue;
93
- if (event.error !== undefined)
94
- throw new Error("Discovery refused");
95
- let cursor;
96
- if (expectedId === 1) {
97
- send({ method: "initialized" });
48
+ const oversize = () => new Error("Oversized metadata");
49
+ for await (const raw of lines(cappedOutput(child.stdout, 4 * 1024 * 1024, oversize))) {
50
+ const line = raw.trim();
51
+ if (line === "")
52
+ continue;
53
+ const event = z
54
+ .object({
55
+ id: z.unknown().optional(),
56
+ result: z.unknown().optional(),
57
+ error: z.unknown().optional(),
58
+ })
59
+ .parse(JSON.parse(line));
60
+ if (event.id !== expectedId)
61
+ continue;
62
+ if (event.error !== undefined)
63
+ throw new Error("Discovery refused");
64
+ let cursor;
65
+ if (expectedId === 1) {
66
+ send({ method: "initialized" });
67
+ }
68
+ else {
69
+ const page = pageSchema.parse(event.result);
70
+ for (const row of page.data) {
71
+ if (row.hidden === true || models.has(row.model))
72
+ continue;
73
+ const thinkingModes = row.supportedReasoningEfforts
74
+ ?.map((item) => item.reasoningEffort)
75
+ .filter((effort) => knownEfforts.includes(effort));
76
+ models.set(row.model, {
77
+ id: row.model,
78
+ name: codexModelName(row.displayName),
79
+ ...(thinkingModes?.length ? { thinkingModes } : {}),
80
+ });
98
81
  }
99
- else {
100
- const page = pageSchema.parse(event.result);
101
- for (const row of page.data) {
102
- if (row.hidden === true || models.has(row.model))
103
- continue;
104
- const thinkingModes = row.supportedReasoningEfforts
105
- ?.map((item) => item.reasoningEffort)
106
- .filter((effort) => knownEfforts.includes(effort));
107
- models.set(row.model, {
108
- id: row.model,
109
- name: codexModelName(row.displayName),
110
- ...(thinkingModes?.length ? { thinkingModes } : {}),
111
- });
112
- }
113
- cursor = page.nextCursor;
114
- if (!cursor) {
115
- if (models.size === 0)
116
- throw new Error("No visible models");
117
- return [...models.values()];
118
- }
119
- if (cursors.has(cursor) || ++pages >= 20)
120
- throw new Error("Invalid pagination");
121
- cursors.add(cursor);
82
+ cursor = page.nextCursor;
83
+ if (!cursor) {
84
+ if (models.size === 0)
85
+ throw new Error("No visible models");
86
+ return [...models.values()];
122
87
  }
123
- send({
124
- id: ++expectedId,
125
- method: "model/list",
126
- params: { limit: 100, includeHidden: false, ...(cursor ? { cursor } : {}) },
127
- });
88
+ if (cursors.has(cursor) || ++pages >= 20)
89
+ throw new Error("Invalid pagination");
90
+ cursors.add(cursor);
128
91
  }
92
+ send({
93
+ id: ++expectedId,
94
+ method: "model/list",
95
+ params: { limit: 100, includeHidden: false, ...(cursor ? { cursor } : {}) },
96
+ });
129
97
  }
130
98
  throw new Error("Discovery ended before its reply");
131
- }
132
- finally {
133
- clearTimeout(timer);
134
- terminate("SIGTERM");
135
- let grace;
136
- await Promise.race([
137
- closed,
138
- new Promise((resolve) => {
139
- grace = setTimeout(() => {
140
- terminate("SIGKILL");
141
- resolve();
142
- }, 500);
143
- }),
144
- ]);
145
- clearTimeout(grace);
146
- await rm(directory, { recursive: true, force: true, maxRetries: 3, retryDelay: 50 });
147
- }
99
+ });
148
100
  }
149
101
  export function codexModelName(name) {
150
102
  return name.replace(/^(GPT-\d+(?:\.\d+)?)-/i, "$1 ");