@gentbajko/slopify 2.5.0 → 3.0.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 (446) hide show
  1. package/LICENSE +201 -21
  2. package/NOTICE +12 -0
  3. package/README.md +21 -40
  4. package/SUBTITLES.md +1 -1
  5. package/dist/adapter-registry.js +3 -0
  6. package/dist/adapters/alignment/cache.js +4 -1
  7. package/dist/adapters/alignment/ctc.js +25 -23
  8. package/dist/adapters/alignment/index.js +37 -6
  9. package/dist/adapters/alignment/multilingual.js +267 -0
  10. package/dist/adapters/alignment/protocol.js +11 -0
  11. package/dist/adapters/alignment/quality.js +4 -3
  12. package/dist/adapters/alignment/sentences.js +95 -0
  13. package/dist/adapters/alignment/spec.js +24 -0
  14. package/dist/adapters/alignment/spell.js +769 -0
  15. package/dist/adapters/alignment/text.js +56 -9
  16. package/dist/adapters/alignment/window.js +34 -30
  17. package/dist/adapters/alignment/worker.js +23 -21
  18. package/dist/adapters/explain.js +11 -11
  19. package/dist/adapters/host-cli/index.js +44 -5
  20. package/dist/adapters/host-cli/transport.js +7 -5
  21. package/dist/adapters/image/bytes.js +2 -2
  22. package/dist/adapters/image/codex-output.js +1 -1
  23. package/dist/adapters/image/codex.js +87 -22
  24. package/dist/adapters/image/fal.js +13 -5
  25. package/dist/adapters/image/google.js +11 -8
  26. package/dist/adapters/image/openai.js +14 -7
  27. package/dist/adapters/image/reference.js +34 -0
  28. package/dist/adapters/image/replicate.js +7 -2
  29. package/dist/adapters/image/video.js +2 -2
  30. package/dist/adapters/key-probes.js +36 -0
  31. package/dist/adapters/llm/claude-code.js +168 -32
  32. package/dist/adapters/llm/cli-login-error.js +1 -1
  33. package/dist/adapters/llm/codex-limits.js +157 -0
  34. package/dist/adapters/llm/codex.js +99 -12
  35. package/dist/adapters/llm/document-workspace.js +2 -2
  36. package/dist/adapters/llm/gemini-workspace.js +1 -1
  37. package/dist/adapters/llm/gemini.js +16 -3
  38. package/dist/adapters/llm/image-workspace.js +58 -0
  39. package/dist/adapters/llm/openrouter.js +11 -3
  40. package/dist/adapters/llm/run-cli.js +12 -7
  41. package/dist/adapters/tts/cartesia.js +10 -0
  42. package/dist/adapters/tts/elevenlabs.js +31 -9
  43. package/dist/adapters/tts/inworld-async.js +9 -5
  44. package/dist/adapters/tts/inworld.js +17 -3
  45. package/dist/adapters/tts/openai.js +3 -0
  46. package/dist/adapters/tts/voice-languages.js +80 -0
  47. package/dist/assets/fonts/noto/NotoSans-Regular.ttf +0 -0
  48. package/dist/assets/fonts/noto/NotoSansArabic-Regular.ttf +0 -0
  49. package/dist/assets/fonts/noto/NotoSansDevanagari-Regular.ttf +0 -0
  50. package/dist/assets/fonts/noto/NotoSansHebrew-Regular.ttf +0 -0
  51. package/dist/assets/fonts/noto/NotoSansThai-Regular.ttf +0 -0
  52. package/dist/assets/fonts/noto/OFL.txt +93 -0
  53. package/dist/assets/fonts/noto/SOURCE.txt +18 -0
  54. package/dist/assets/sample/sample-audiobook.tar +0 -0
  55. package/dist/assets/sample/sample-podcast.tar +0 -0
  56. package/dist/assets/sample/sample-project.tar +0 -0
  57. package/dist/catalog/merge.js +132 -0
  58. package/dist/catalog/registry.js +13 -13
  59. package/dist/catalog/schema.js +2 -0
  60. package/dist/catalog/store.js +147 -8
  61. package/dist/compose.yaml +71 -0
  62. package/dist/edge/autostart/docker-record.js +32 -0
  63. package/dist/edge/autostart/docker.js +50 -0
  64. package/dist/edge/autostart/index.js +78 -0
  65. package/dist/edge/autostart/launcher.js +176 -0
  66. package/dist/edge/autostart/model.js +3 -0
  67. package/dist/edge/autostart/native.js +210 -0
  68. package/dist/edge/autostart/prompt.js +66 -0
  69. package/dist/edge/autostart/service.js +81 -0
  70. package/dist/edge/cli.js +57 -51
  71. package/dist/edge/docker-install/activation.js +56 -0
  72. package/dist/edge/docker-install/apply.js +458 -0
  73. package/dist/edge/docker-install/engine.js +362 -0
  74. package/dist/edge/docker-install/run.js +154 -0
  75. package/dist/edge/docker-install/state.js +146 -0
  76. package/dist/edge/{docker-projects → docker-install}/volume.js +1 -5
  77. package/dist/edge/docker.js +14 -22
  78. package/dist/edge/host-cli.js +1 -1
  79. package/dist/edge/http/actions.js +32 -10
  80. package/dist/edge/http/app.js +58 -2
  81. package/dist/edge/http/auditions.js +70 -0
  82. package/dist/edge/http/autostart.js +37 -0
  83. package/dist/edge/http/channel-memory.js +92 -0
  84. package/dist/edge/http/channels.js +128 -0
  85. package/dist/edge/http/entries.js +22 -3
  86. package/dist/edge/http/files.js +1 -1
  87. package/dist/edge/http/folder-location.js +1 -1
  88. package/dist/edge/http/home.js +39 -0
  89. package/dist/edge/http/host-cli.js +29 -5
  90. package/dist/edge/http/narration-peaks.js +76 -0
  91. package/dist/edge/http/onboarding.js +152 -0
  92. package/dist/edge/http/open-folder.js +1 -1
  93. package/dist/edge/http/patch-notes.js +45 -0
  94. package/dist/edge/http/planning.js +4 -2
  95. package/dist/edge/http/project-create.js +87 -0
  96. package/dist/edge/http/projects.js +31 -99
  97. package/dist/edge/http/prompts.js +40 -3
  98. package/dist/edge/http/pronunciations.js +23 -4
  99. package/dist/edge/http/providers.js +86 -0
  100. package/dist/edge/http/reviews.js +121 -0
  101. package/dist/edge/http/revision-files.js +1 -1
  102. package/dist/edge/http/revisions.js +1 -1
  103. package/dist/edge/http/run-cost.js +25 -0
  104. package/dist/edge/http/schedules.js +111 -6
  105. package/dist/edge/http/settings.js +84 -6
  106. package/dist/edge/http/storage-files.js +50 -0
  107. package/dist/edge/http/storage.js +29 -2
  108. package/dist/edge/http/studio.js +207 -0
  109. package/dist/edge/http/style-preview.js +100 -0
  110. package/dist/edge/http/subtitles.js +1 -1
  111. package/dist/edge/http/trash.js +69 -0
  112. package/dist/edge/http/update.js +24 -3
  113. package/dist/edge/http/whats-new.js +15 -0
  114. package/dist/edge/http/youtube-edits.js +83 -0
  115. package/dist/edge/native-update.js +62 -0
  116. package/dist/host-cli/open-folder.js +10 -10
  117. package/dist/host-cli/runtime.js +9 -1
  118. package/dist/kernel/db/migrations/0025-automatic-reviews.sql +40 -0
  119. package/dist/kernel/db/migrations/0026-schedule-topic-generation.sql +23 -0
  120. package/dist/kernel/db/migrations/0027-run-cost.sql +58 -0
  121. package/dist/kernel/db/migrations/0030-automatic-retries.sql +18 -0
  122. package/dist/kernel/db/migrations/0031-prompt-history-and-description-edits.sql +33 -0
  123. package/dist/kernel/db/migrations/0032-channels.sql +65 -0
  124. package/dist/kernel/db/migrations/0034-script-prompts.sql +23 -0
  125. package/dist/kernel/db/migrations/0035-narration-aliases.sql +13 -0
  126. package/dist/kernel/db/migrations/0037-project-uploads.sql +8 -0
  127. package/dist/kernel/db/migrations/0038-voice-languages.sql +7 -0
  128. package/dist/kernel/db/migrations/0039-channel-essentials.sql +64 -0
  129. package/dist/kernel/db/migrations/0040-standalone-usage.sql +35 -0
  130. package/dist/kernel/paths.js +27 -6
  131. package/dist/kernel/pipeline.js +4 -1
  132. package/dist/kernel/ports/host-cli.js +122 -14
  133. package/dist/kernel/ports/key-probe.js +1 -0
  134. package/dist/kernel/ports/languages.js +157 -0
  135. package/dist/kernel/ports/model.js +5 -2
  136. package/dist/kernel/ports/narration-aliases.js +60 -0
  137. package/dist/kernel/ports/plan-limits.js +36 -0
  138. package/dist/kernel/runner/attempt.js +17 -8
  139. package/dist/kernel/runner/audition.js +36 -0
  140. package/dist/kernel/runner/graph.js +24 -5
  141. package/dist/kernel/runner/index.js +35 -5
  142. package/dist/kernel/runner/meter.js +1 -0
  143. package/dist/kernel/runner/providers.js +142 -7
  144. package/dist/kernel/runner/retry-policy.js +43 -0
  145. package/dist/kernel/runner/standalone.js +134 -0
  146. package/dist/kernel/runner/work-authority.js +28 -2
  147. package/dist/main.js +272 -16
  148. package/dist/patch-notes/0.4.2-to-1.0.md +93 -0
  149. package/dist/patch-notes/1.0-to-2.0.md +74 -0
  150. package/dist/patch-notes/2.0-to-3.0.md +257 -0
  151. package/dist/patch-notes/3.0.0.md +70 -0
  152. package/dist/patch-notes/index.json +26 -0
  153. package/dist/slices/admission/model.js +27 -0
  154. package/dist/slices/admission/repo.js +24 -4
  155. package/dist/slices/admission/rules.js +79 -1
  156. package/dist/slices/admission/schema.js +58 -1
  157. package/dist/slices/admission/short-mode.js +47 -0
  158. package/dist/slices/admission/start.js +41 -5
  159. package/dist/slices/article/continuation.js +2 -2
  160. package/dist/slices/article/provided-entries.js +2 -2
  161. package/dist/slices/article/run.js +6 -2
  162. package/dist/slices/article/segments.js +3 -3
  163. package/dist/slices/backups/folder.js +14 -6
  164. package/dist/slices/batch/index.js +7 -2
  165. package/dist/slices/cancel/index.js +1 -1
  166. package/dist/slices/channels/cast-images.js +110 -0
  167. package/dist/slices/channels/cast-match.js +32 -0
  168. package/dist/slices/channels/images.js +19 -0
  169. package/dist/slices/channels/model.js +5 -0
  170. package/dist/slices/channels/rebrand.js +100 -0
  171. package/dist/slices/channels/repo.js +218 -0
  172. package/dist/slices/channels/runs.js +129 -0
  173. package/dist/slices/channels/schema.js +129 -0
  174. package/dist/slices/channels/service.js +180 -0
  175. package/dist/slices/channels/studio-csv.js +110 -0
  176. package/dist/slices/channels/videos.js +120 -0
  177. package/dist/slices/checkpoints/recovery.js +10 -0
  178. package/dist/slices/control/index.js +2 -1
  179. package/dist/slices/document/fonts.js +1 -1
  180. package/dist/slices/document/render.js +1 -1
  181. package/dist/slices/episodes/related.js +90 -0
  182. package/dist/slices/episodes/repo.js +60 -0
  183. package/dist/slices/episodes/service.js +58 -0
  184. package/dist/slices/episodes/summarize.js +170 -0
  185. package/dist/slices/estimate/index.js +109 -28
  186. package/dist/slices/estimate/requests.js +60 -2
  187. package/dist/slices/fixes/rules.js +73 -0
  188. package/dist/slices/fonts/coverage.js +82 -0
  189. package/dist/slices/fonts/sfnt.js +74 -0
  190. package/dist/slices/images/run.js +8 -5
  191. package/dist/slices/images/scale.js +84 -0
  192. package/dist/slices/library/diff.js +122 -0
  193. package/dist/slices/library/history.js +100 -0
  194. package/dist/slices/library/model.js +3 -0
  195. package/dist/slices/library/photorealistic.js +49 -0
  196. package/dist/slices/library/repo.js +19 -14
  197. package/dist/slices/library/save.js +62 -12
  198. package/dist/slices/library/slots.js +7 -1
  199. package/dist/slices/library/used-by.js +153 -0
  200. package/dist/slices/loudness/level-pieces.js +41 -0
  201. package/dist/slices/loudness/loudnorm.js +164 -0
  202. package/dist/slices/loudness/model.js +153 -0
  203. package/dist/slices/model-upkeep/model.js +10 -0
  204. package/dist/slices/model-upkeep/switch.js +217 -0
  205. package/dist/slices/model-upkeep/usage.js +183 -0
  206. package/dist/slices/narration/aliases-library.js +31 -0
  207. package/dist/slices/narration/aliases-schema.js +53 -0
  208. package/dist/slices/narration/aliases.js +49 -0
  209. package/dist/slices/narration/blocks.js +352 -0
  210. package/dist/slices/narration/chunk.js +19 -7
  211. package/dist/slices/narration/concat.js +2 -2
  212. package/dist/slices/narration/describe.js +45 -0
  213. package/dist/slices/narration/pauses-model.js +63 -0
  214. package/dist/slices/narration/pauses.js +269 -0
  215. package/dist/slices/narration/peaks-model.js +1 -0
  216. package/dist/slices/narration/peaks.js +94 -0
  217. package/dist/slices/narration/preparation.js +21 -3
  218. package/dist/slices/narration/pronunciation-chunks.js +3 -3
  219. package/dist/slices/narration/pronunciation.js +72 -25
  220. package/dist/slices/narration/run.js +6 -6
  221. package/dist/slices/narration/shared-glossary.js +1 -1
  222. package/dist/slices/narration/steering.js +15 -4
  223. package/dist/slices/notifications/notifier.js +21 -3
  224. package/dist/slices/notifications/rules.js +22 -1
  225. package/dist/slices/onboarding/copy.js +143 -0
  226. package/dist/slices/onboarding/first-run.js +46 -0
  227. package/dist/slices/onboarding/install.js +119 -0
  228. package/dist/slices/onboarding/model.js +64 -0
  229. package/dist/slices/onboarding/packs.js +491 -0
  230. package/dist/slices/onboarding/quick-short.js +129 -0
  231. package/dist/slices/onboarding/sample.js +132 -0
  232. package/dist/slices/onboarding/state.js +68 -0
  233. package/dist/slices/onboarding/template.js +73 -0
  234. package/dist/slices/patch-notes/library.js +73 -0
  235. package/dist/slices/patch-notes/seen.js +77 -0
  236. package/dist/slices/play-drafts/convert.js +125 -6
  237. package/dist/slices/play-drafts/readiness.js +3 -0
  238. package/dist/slices/play-drafts/repo.js +2 -0
  239. package/dist/slices/play-drafts/review-inputs.js +20 -3
  240. package/dist/slices/play-drafts/schema.js +89 -0
  241. package/dist/slices/play-drafts/service.js +4 -1
  242. package/dist/slices/play-drafts/start.js +43 -18
  243. package/dist/slices/project-templates/from-project.js +50 -4
  244. package/dist/slices/project-templates/one-off.js +26 -0
  245. package/dist/slices/project-templates/repo.js +2 -1
  246. package/dist/slices/project-templates/service.js +15 -4
  247. package/dist/slices/project-templates/setup.js +18 -2
  248. package/dist/slices/rebuild/admission-repo.js +1 -1
  249. package/dist/slices/rebuild/model.js +6 -0
  250. package/dist/slices/rebuild/preview-details.js +46 -3
  251. package/dist/slices/rebuild/preview-plan.js +13 -6
  252. package/dist/slices/rebuild/recipe-audio-parts.js +40 -7
  253. package/dist/slices/rebuild/recipe-audio.js +66 -12
  254. package/dist/slices/rebuild/recipe-build.js +8 -4
  255. package/dist/slices/rebuild/recipe-cast.js +18 -0
  256. package/dist/slices/rebuild/recipe-checkpoints.js +11 -9
  257. package/dist/slices/rebuild/recipe-describe.js +93 -0
  258. package/dist/slices/rebuild/recipe-edit.js +13 -1
  259. package/dist/slices/rebuild/recipe-exports.js +62 -8
  260. package/dist/slices/rebuild/recipe-input-schema.js +35 -0
  261. package/dist/slices/rebuild/recipe-legacy.js +9 -0
  262. package/dist/slices/rebuild/recipe-loudness.js +45 -0
  263. package/dist/slices/rebuild/recipe-model.js +25 -6
  264. package/dist/slices/rebuild/recipe-pauses.js +7 -0
  265. package/dist/slices/rebuild/recipe-preparation.js +3 -3
  266. package/dist/slices/rebuild/recipe-provider-choice.js +11 -1
  267. package/dist/slices/rebuild/recipe-reference.js +15 -1
  268. package/dist/slices/rebuild/recipe-reviews.js +117 -0
  269. package/dist/slices/rebuild/recipe-save.js +4 -1
  270. package/dist/slices/rebuild/recipe-shorts.js +23 -3
  271. package/dist/slices/rebuild/recipe-text.js +114 -19
  272. package/dist/slices/rebuild/recipe-validation.js +14 -2
  273. package/dist/slices/rebuild/recipe-visual.js +96 -33
  274. package/dist/slices/rebuild/recipe-voices.js +286 -0
  275. package/dist/slices/rebuild/recipe-work.js +77 -6
  276. package/dist/slices/rebuild/recipe-youtube.js +2 -0
  277. package/dist/slices/rebuild/recovery-conflict.js +7 -3
  278. package/dist/slices/rebuild/recovery-model.js +3 -0
  279. package/dist/slices/rebuild/recovery-selection.js +28 -2
  280. package/dist/slices/rebuild/recovery.js +35 -17
  281. package/dist/slices/rebuild/repo.js +3 -3
  282. package/dist/slices/rebuild/retry.js +18 -0
  283. package/dist/slices/rebuild/review-redo.js +110 -0
  284. package/dist/slices/rebuild/runtime-actions.js +5 -0
  285. package/dist/slices/rebuild/runtime-admission.js +4 -1
  286. package/dist/slices/rebuild/runtime-animate.js +4 -4
  287. package/dist/slices/rebuild/runtime-article.js +5 -5
  288. package/dist/slices/rebuild/runtime-document.js +4 -4
  289. package/dist/slices/rebuild/runtime-export-bed.js +43 -0
  290. package/dist/slices/rebuild/runtime-export-edit.js +70 -11
  291. package/dist/slices/rebuild/runtime-export-inputs.js +52 -10
  292. package/dist/slices/rebuild/runtime-export-short.js +85 -0
  293. package/dist/slices/rebuild/runtime-export.js +84 -19
  294. package/dist/slices/rebuild/runtime-figure-card.js +87 -0
  295. package/dist/slices/rebuild/runtime-image.js +21 -2
  296. package/dist/slices/rebuild/runtime-local.js +148 -24
  297. package/dist/slices/rebuild/runtime-materialize.js +8 -0
  298. package/dist/slices/rebuild/runtime-narration-reuse.js +2 -1
  299. package/dist/slices/rebuild/runtime-narration-text.js +7 -7
  300. package/dist/slices/rebuild/runtime-pictures.js +28 -0
  301. package/dist/slices/rebuild/runtime-piece-label.js +27 -0
  302. package/dist/slices/rebuild/runtime-provider.js +126 -18
  303. package/dist/slices/rebuild/runtime-publication.js +21 -5
  304. package/dist/slices/rebuild/runtime-review.js +237 -0
  305. package/dist/slices/rebuild/runtime-run.js +17 -11
  306. package/dist/slices/rebuild/runtime-shorts.js +44 -17
  307. package/dist/slices/rebuild/runtime-store.js +39 -10
  308. package/dist/slices/rebuild/runtime-subtitles.js +72 -19
  309. package/dist/slices/rebuild/runtime-voices.js +103 -0
  310. package/dist/slices/rebuild/runtime-youtube.js +7 -6
  311. package/dist/slices/rebuild/soften.js +49 -0
  312. package/dist/slices/rebuild/transition-repo.js +9 -2
  313. package/dist/slices/research/run.js +4 -4
  314. package/dist/slices/research/synthesis.js +2 -2
  315. package/dist/slices/reviews/model.js +105 -0
  316. package/dist/slices/reviews/outcome.js +22 -0
  317. package/dist/slices/reviews/repo.js +106 -0
  318. package/dist/slices/reviews/rules.js +63 -0
  319. package/dist/slices/reviews/verdict.js +71 -0
  320. package/dist/slices/reviews/view.js +30 -0
  321. package/dist/slices/revisions/adopt-content.js +5 -2
  322. package/dist/slices/revisions/adopt.js +3 -1
  323. package/dist/slices/revisions/downloads.js +7 -1
  324. package/dist/slices/revisions/image-plan.js +183 -0
  325. package/dist/slices/revisions/mutation-assets.js +10 -0
  326. package/dist/slices/revisions/mutation-cues.js +71 -0
  327. package/dist/slices/revisions/mutation-request.js +2 -1
  328. package/dist/slices/revisions/mutations.js +97 -3
  329. package/dist/slices/revisions/schema.js +11 -1
  330. package/dist/slices/run-cost/limits.js +128 -0
  331. package/dist/slices/run-cost/meter.js +47 -0
  332. package/dist/slices/run-cost/panel.js +234 -0
  333. package/dist/slices/run-cost/pricing.js +92 -0
  334. package/dist/slices/run-cost/week.js +108 -0
  335. package/dist/slices/schedules/agenda.js +158 -0
  336. package/dist/slices/schedules/repo.js +58 -18
  337. package/dist/slices/schedules/scheduler.js +67 -16
  338. package/dist/slices/schedules/schema.js +138 -1
  339. package/dist/slices/schedules/service.js +43 -4
  340. package/dist/slices/schedules/similar.js +90 -0
  341. package/dist/slices/schedules/topic-list.js +163 -0
  342. package/dist/slices/schedules/topics.js +422 -0
  343. package/dist/slices/settings/first-run.js +102 -0
  344. package/dist/slices/settings/health.js +190 -0
  345. package/dist/slices/settings/key-guides.js +128 -0
  346. package/dist/slices/settings/key-test.js +85 -0
  347. package/dist/slices/settings/model.js +6 -1
  348. package/dist/slices/settings/playback.js +15 -0
  349. package/dist/slices/settings/repo.js +17 -3
  350. package/dist/slices/settings/voices.js +64 -4
  351. package/dist/slices/settings/whats-new.js +64 -0
  352. package/dist/slices/shorts/captions.js +9 -0
  353. package/dist/slices/shorts/pick.js +3 -3
  354. package/dist/slices/shorts/prompts.js +1 -1
  355. package/dist/slices/shorts/render.js +54 -5
  356. package/dist/slices/storage/asset-name.js +3 -0
  357. package/dist/slices/storage/backup-export.js +48 -9
  358. package/dist/slices/storage/backup-format.js +38 -1
  359. package/dist/slices/storage/backup-import.js +191 -19
  360. package/dist/slices/storage/delete-project.js +7 -4
  361. package/dist/slices/storage/documents.js +79 -0
  362. package/dist/slices/storage/files-location.js +531 -0
  363. package/dist/slices/storage/layout.js +14 -4
  364. package/dist/slices/storage/model.js +11 -0
  365. package/dist/slices/storage/portable.js +92 -12
  366. package/dist/slices/storage/reconcile.js +14 -1
  367. package/dist/slices/storage/repo.js +4 -1
  368. package/dist/slices/storage/schema.js +11 -0
  369. package/dist/slices/storage/trim.js +146 -0
  370. package/dist/slices/studio/disclosure.js +74 -0
  371. package/dist/slices/studio/model.js +28 -0
  372. package/dist/slices/studio/pack.js +209 -0
  373. package/dist/slices/studio/settings.js +133 -0
  374. package/dist/slices/style-preview/images.js +61 -0
  375. package/dist/slices/style-preview/render.js +161 -0
  376. package/dist/slices/style-preview/schema.js +45 -0
  377. package/dist/slices/style-preview/service.js +93 -0
  378. package/dist/slices/style-preview/settings.js +89 -0
  379. package/dist/slices/subtitles/captions.js +42 -9
  380. package/dist/slices/subtitles/model.js +22 -0
  381. package/dist/slices/subtitles/prepare.js +27 -16
  382. package/dist/slices/subtitles/transcript.js +1 -1
  383. package/dist/slices/thumbnail/run.js +7 -7
  384. package/dist/slices/trash/model.js +25 -0
  385. package/dist/slices/trash/service.js +273 -0
  386. package/dist/slices/uploads/repo.js +20 -0
  387. package/dist/slices/video/ambient-bed-schema.js +15 -0
  388. package/dist/slices/video/ambient-bed.js +95 -0
  389. package/dist/slices/video/ambient-mix.js +72 -0
  390. package/dist/slices/video/audio-inputs.js +2 -2
  391. package/dist/slices/video/cards.js +5 -2
  392. package/dist/slices/video/edit-list.js +23 -2
  393. package/dist/slices/video/edit-settings.js +13 -3
  394. package/dist/slices/video/ffmpeg.js +63 -9
  395. package/dist/slices/video/figure-card.js +492 -0
  396. package/dist/slices/video/figure-spans.js +51 -0
  397. package/dist/slices/video/plan.js +125 -13
  398. package/dist/slices/video/run.js +14 -12
  399. package/dist/slices/video/slideshow.js +39 -4
  400. package/dist/slices/voices/attribution.js +69 -0
  401. package/dist/slices/voices/audio-files.js +82 -0
  402. package/dist/slices/voices/audition.js +25 -0
  403. package/dist/slices/voices/cast.js +56 -0
  404. package/dist/slices/voices/grouping.js +49 -0
  405. package/dist/slices/voices/join.js +35 -0
  406. package/dist/slices/voices/languages.js +25 -0
  407. package/dist/slices/voices/model.js +179 -0
  408. package/dist/slices/voices/palette.js +26 -0
  409. package/dist/slices/voices/panel.js +91 -0
  410. package/dist/slices/voices/portraits.js +55 -0
  411. package/dist/slices/voices/script.js +136 -0
  412. package/dist/slices/voices/timing.js +58 -0
  413. package/dist/slices/youtube/answer.js +1 -1
  414. package/dist/slices/youtube/chapters.js +126 -0
  415. package/dist/slices/youtube/edits-repo.js +69 -0
  416. package/dist/slices/youtube/edits.js +89 -0
  417. package/dist/slices/youtube/placeholders.js +98 -0
  418. package/dist/slices/youtube/transcript.js +11 -4
  419. package/dist/updater/service.js +66 -21
  420. package/dist/web/assets/index-CUA2sUxU.css +1 -0
  421. package/dist/web/assets/index-CX590kE-.js +303 -0
  422. package/dist/web/assets/jetbrains-mono-cyrillic-400-normal-BEIGL1Tu.woff2 +0 -0
  423. package/dist/web/assets/jetbrains-mono-cyrillic-400-normal-ugxPyKxw.woff +0 -0
  424. package/dist/web/assets/jetbrains-mono-greek-400-normal-B9oWc5Lo.woff +0 -0
  425. package/dist/web/assets/jetbrains-mono-greek-400-normal-C190GLew.woff2 +0 -0
  426. package/dist/web/assets/jetbrains-mono-latin-400-normal-6-qcROiO.woff +0 -0
  427. package/dist/web/assets/jetbrains-mono-latin-400-normal-V6pRDFza.woff2 +0 -0
  428. package/dist/web/assets/jetbrains-mono-latin-ext-400-normal-Bc8Ftmh3.woff2 +0 -0
  429. package/dist/web/assets/jetbrains-mono-latin-ext-400-normal-fXTG6kC5.woff +0 -0
  430. package/dist/web/assets/jetbrains-mono-vietnamese-400-normal-CqNFfHCs.woff +0 -0
  431. package/dist/web/assets/{pdf-BLF2i8c2.js → pdf-BG8n_uc5.js} +1 -1
  432. package/dist/web/index.html +2 -2
  433. package/package.json +4 -4
  434. package/dist/edge/docker-launch.js +0 -81
  435. package/dist/edge/docker-projects/activation.js +0 -35
  436. package/dist/edge/docker-projects/claims.js +0 -85
  437. package/dist/edge/docker-projects/committed.js +0 -40
  438. package/dist/edge/docker-projects/engine.js +0 -461
  439. package/dist/edge/docker-projects/install.js +0 -254
  440. package/dist/edge/docker-projects/prune.js +0 -66
  441. package/dist/edge/docker-projects/recover.js +0 -100
  442. package/dist/edge/docker-projects/state.js +0 -225
  443. package/dist/web/assets/index-CktpxlJd.js +0 -171
  444. package/dist/web/assets/index-DB-vOnGU.css +0 -1
  445. package/scripts/docker-run.sh +0 -3
  446. /package/dist/edge/{docker-projects → docker-install}/tree.js +0 -0
@@ -4,6 +4,7 @@ import { providerError } from "../../kernel/ports/model.js";
4
4
  import { httpFailure, missingKey, noAudio, unreadable, voiceFix } from "../explain.js";
5
5
  import { retryAfter } from "../retry-after.js";
6
6
  import { inworldAsync, streamFailure } from "./inworld-async.js";
7
+ import { inworldLanguages, lookUp } from "./voice-languages.js";
7
8
  export const inworldModels = [
8
9
  { id: "inworld-tts-2", name: "Realtime TTS-2" },
9
10
  { id: "inworld-tts-2-flash", name: "Realtime TTS-2 Flash" },
@@ -16,6 +17,15 @@ export function inworldTts(deps) {
16
17
  return {
17
18
  id: "inworld",
18
19
  capabilities: { streams: true },
20
+ voiceLanguages: async (voiceId, signal) => {
21
+ const key = deps
22
+ .key()
23
+ ?.trim()
24
+ .replace(/^Basic\s+/i, "");
25
+ if (!key)
26
+ return undefined;
27
+ return inworldLanguages(await lookUp(deps.fetch, `https://api.inworld.ai/voices/v1/voices/${encodeURIComponent(voiceId)}`, { Authorization: `Basic ${key}` }, signal));
28
+ },
19
29
  models: async () => inworldModels,
20
30
  synthesize: async (request) => {
21
31
  const key = deps
@@ -59,7 +69,7 @@ async function* synthesizeRequest(deps, request, key) {
59
69
  if (request.text.trim().length === 0)
60
70
  throw providerError({
61
71
  kind: "unsupported",
62
- message: "Inworld was sent an empty piece of narration. Check the article has text in the Article section of Edit project, then use Retry stage.",
72
+ message: "Inworld was sent an empty piece of narration. Check the article has text in the Article section of Edit project, then use Try again.",
63
73
  });
64
74
  if ((request.model ?? "inworld-tts-2") === "inworld-tts-2" && request.text.length > 4000) {
65
75
  yield* inworldAsync(deps, request, key);
@@ -93,7 +103,9 @@ async function* synthesizeRequest(deps, request, key) {
93
103
  ? "rate_limit"
94
104
  : response.status === 400 || response.status === 404
95
105
  ? "unsupported"
96
- : "other",
106
+ : response.status >= 500
107
+ ? "dropped"
108
+ : "other",
97
109
  message: clean(httpFailure({
98
110
  provider: "Inworld",
99
111
  status: response.status,
@@ -128,7 +140,9 @@ async function* synthesizeRequest(deps, request, key) {
128
140
  ? "rate_limit"
129
141
  : code === 3 || code === 5
130
142
  ? "unsupported"
131
- : "other",
143
+ : code === 14
144
+ ? "dropped"
145
+ : "other",
132
146
  message: streamFailure(code, clean(message ?? "", key), request.voiceId),
133
147
  });
134
148
  }
@@ -95,6 +95,9 @@ function kindOf(status) {
95
95
  }
96
96
  // ceiling: as in the OpenRouter adapter, a 400 is retried three more times because the
97
97
  // port's error contract has no terminal kind for a request that cannot be repaired.
98
+ // The provider's own server failed; the same request may well succeed later.
99
+ if (status >= 500)
100
+ return "dropped";
98
101
  return "other";
99
102
  }
100
103
  async function failure(response, voiceId, next) {
@@ -0,0 +1,80 @@
1
+ import { z } from "zod";
2
+ // What each provider's voice API says a voice speaks, reduced to lower-case primary language
3
+ // subtags ("es-MX" and "ES_MX" are both "es"). Undefined when the provider said nothing
4
+ // usable: an unknown voice speaks every language as far as the app is concerned.
5
+ export function primaryLanguages(values) {
6
+ const codes = values.flatMap((value) => {
7
+ const code = value?.trim().split(/[-_]/)[0]?.toLowerCase();
8
+ return code !== undefined && /^[a-z]{2,3}$/.test(code) ? [code] : [];
9
+ });
10
+ return codes.length === 0 ? undefined : [...new Set(codes)];
11
+ }
12
+ // Asks once, briefly: the answer only fills a hint in Settings → Voices, so a slow or failed
13
+ // lookup is simply no answer.
14
+ export async function lookUp(fetcher, url, headers, signal) {
15
+ try {
16
+ const response = await fetcher(url, {
17
+ headers,
18
+ signal: AbortSignal.any([signal, AbortSignal.timeout(8000)]),
19
+ });
20
+ if (!response.ok) {
21
+ await response.body?.cancel();
22
+ return undefined;
23
+ }
24
+ return await response.json();
25
+ }
26
+ catch {
27
+ signal.throwIfAborted();
28
+ return undefined;
29
+ }
30
+ }
31
+ // GET /v1/voices/{id}: `verified_languages[].language` (or `.locale`), and the older
32
+ // `labels.language` and `fine_tuning.language`.
33
+ const elevenLabsVoice = z.object({
34
+ verified_languages: z
35
+ .array(z.object({ language: z.string().nullish(), locale: z.string().nullish() }))
36
+ .nullish(),
37
+ labels: z.object({ language: z.string().nullish() }).partial().nullish(),
38
+ fine_tuning: z.object({ language: z.string().nullish() }).partial().nullish(),
39
+ });
40
+ export function elevenLabsLanguages(body) {
41
+ const parsed = elevenLabsVoice.safeParse(body);
42
+ if (!parsed.success)
43
+ return undefined;
44
+ return primaryLanguages([
45
+ ...(parsed.data.verified_languages ?? []).flatMap((one) => [one.language, one.locale]),
46
+ parsed.data.labels?.language,
47
+ parsed.data.fine_tuning?.language,
48
+ ]);
49
+ }
50
+ // GET /voices/{id}: `language` (ISO 639-1) and `accents[].locale`.
51
+ const cartesiaVoice = z.object({
52
+ language: z.string().nullish(),
53
+ accents: z.array(z.object({ locale: z.string().nullish() })).nullish(),
54
+ });
55
+ export function cartesiaLanguages(body) {
56
+ const parsed = cartesiaVoice.safeParse(body);
57
+ if (!parsed.success)
58
+ return undefined;
59
+ return primaryLanguages([
60
+ parsed.data.language,
61
+ ...(parsed.data.accents ?? []).map((one) => one.locale),
62
+ ]);
63
+ }
64
+ // GET /voices/v1/voices/{id}: `languageCode` ("en-US"), `langCode` ("EN_US") and, for a
65
+ // multilingual voice, `promptLanguages`.
66
+ const inworldVoice = z.object({
67
+ languageCode: z.string().nullish(),
68
+ langCode: z.string().nullish(),
69
+ promptLanguages: z.array(z.string()).nullish(),
70
+ });
71
+ export function inworldLanguages(body) {
72
+ const parsed = inworldVoice.safeParse(typeof body === "object" && body !== null && "voice" in body ? body.voice : body);
73
+ if (!parsed.success)
74
+ return undefined;
75
+ return primaryLanguages([
76
+ parsed.data.languageCode,
77
+ parsed.data.langCode,
78
+ ...(parsed.data.promptLanguages ?? []),
79
+ ]);
80
+ }
@@ -0,0 +1,93 @@
1
+ Copyright 2022 The Noto Project Authors (https://github.com/notofonts/latin-greek-cyrillic)
2
+
3
+ This Font Software is licensed under the SIL Open Font License, Version 1.1.
4
+ This license is copied below, and is also available with a FAQ at:
5
+ https://scripts.sil.org/OFL
6
+
7
+
8
+ -----------------------------------------------------------
9
+ SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
10
+ -----------------------------------------------------------
11
+
12
+ PREAMBLE
13
+ The goals of the Open Font License (OFL) are to stimulate worldwide
14
+ development of collaborative font projects, to support the font creation
15
+ efforts of academic and linguistic communities, and to provide a free and
16
+ open framework in which fonts may be shared and improved in partnership
17
+ with others.
18
+
19
+ The OFL allows the licensed fonts to be used, studied, modified and
20
+ redistributed freely as long as they are not sold by themselves. The
21
+ fonts, including any derivative works, can be bundled, embedded,
22
+ redistributed and/or sold with any software provided that any reserved
23
+ names are not used by derivative works. The fonts and derivatives,
24
+ however, cannot be released under any other type of license. The
25
+ requirement for fonts to remain under this license does not apply
26
+ to any document created using the fonts or their derivatives.
27
+
28
+ DEFINITIONS
29
+ "Font Software" refers to the set of files released by the Copyright
30
+ Holder(s) under this license and clearly marked as such. This may
31
+ include source files, build scripts and documentation.
32
+
33
+ "Reserved Font Name" refers to any names specified as such after the
34
+ copyright statement(s).
35
+
36
+ "Original Version" refers to the collection of Font Software components as
37
+ distributed by the Copyright Holder(s).
38
+
39
+ "Modified Version" refers to any derivative made by adding to, deleting,
40
+ or substituting -- in part or in whole -- any of the components of the
41
+ Original Version, by changing formats or by porting the Font Software to a
42
+ new environment.
43
+
44
+ "Author" refers to any designer, engineer, programmer, technical
45
+ writer or other person who contributed to the Font Software.
46
+
47
+ PERMISSION & CONDITIONS
48
+ Permission is hereby granted, free of charge, to any person obtaining
49
+ a copy of the Font Software, to use, study, copy, merge, embed, modify,
50
+ redistribute, and sell modified and unmodified copies of the Font
51
+ Software, subject to the following conditions:
52
+
53
+ 1) Neither the Font Software nor any of its individual components,
54
+ in Original or Modified Versions, may be sold by itself.
55
+
56
+ 2) Original or Modified Versions of the Font Software may be bundled,
57
+ redistributed and/or sold with any software, provided that each copy
58
+ contains the above copyright notice and this license. These can be
59
+ included either as stand-alone text files, human-readable headers or
60
+ in the appropriate machine-readable metadata fields within text or
61
+ binary files as long as those fields can be easily viewed by the user.
62
+
63
+ 3) No Modified Version of the Font Software may use the Reserved Font
64
+ Name(s) unless explicit written permission is granted by the corresponding
65
+ Copyright Holder. This restriction only applies to the primary font name as
66
+ presented to the users.
67
+
68
+ 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
69
+ Software shall not be used to promote, endorse or advertise any
70
+ Modified Version, except to acknowledge the contribution(s) of the
71
+ Copyright Holder(s) and the Author(s) or with their explicit written
72
+ permission.
73
+
74
+ 5) The Font Software, modified or unmodified, in part or in whole,
75
+ must be distributed entirely under this license, and must not be
76
+ distributed under any other license. The requirement for fonts to
77
+ remain under this license does not apply to any document created
78
+ using the Font Software.
79
+
80
+ TERMINATION
81
+ This license becomes null and void if any of the above conditions are
82
+ not met.
83
+
84
+ DISCLAIMER
85
+ THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
86
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
87
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
88
+ OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
89
+ COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
90
+ INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
91
+ DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
92
+ FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
93
+ OTHER DEALINGS IN THE FONT SOFTWARE.
@@ -0,0 +1,18 @@
1
+ Noto Sans (Latin, Greek, Cyrillic), Noto Sans Arabic, Noto Sans Hebrew, Noto Sans Devanagari
2
+ and Noto Sans Thai, Regular. Caption fallbacks for project languages the chosen caption font
3
+ cannot draw (src/slices/fonts/coverage.ts).
4
+
5
+ Source: the Noto Project (https://github.com/notofonts), static Regular instances as packaged
6
+ by Arch Linux noto-fonts 1:2026.09.01-1 (/usr/share/fonts/noto/). Noto Sans reports
7
+ "Version 2.015".
8
+ Licence: SIL Open Font License 1.1, OFL.txt beside this file, from
9
+ https://raw.githubusercontent.com/notofonts/latin-greek-cyrillic/main/OFL.txt
10
+ (SHA-256 cee9892f9f0cc8fe882c9e9537ee6a89621d86ee7ceaf70b02e2b2b1c25c061a). Each family is
11
+ "Copyright 2022 The Noto Project Authors" under the same licence.
12
+
13
+ SHA-256:
14
+ 478c558ea716033cd60c03438f628dfa75694dcf6b5f6d505a2f05fd2b4f3823 NotoSans-Regular.ttf
15
+ bdff3e5659d67e67def05b33f749683b9376ae819d65d3dd62ac4640b3aaef48 NotoSansArabic-Regular.ttf
16
+ cdefaf8efd47045f6820928eba84db5bed7557539328952b5f828315485e02ee NotoSansHebrew-Regular.ttf
17
+ 306b53ecfb182a504dd8a7446093c316387d2fd8dc350d0792ed1753fe0996cd NotoSansDevanagari-Regular.ttf
18
+ 61cf814eec46b294d6ea4401ac295d0cecd5207bd2331dcc5a15e7301d30ee44 NotoSansThai-Regular.ttf
@@ -0,0 +1,132 @@
1
+ // What an automatic catalogue check found. Every change is reported, none is applied to a
2
+ // template, schedule, draft or project: a retired model is only flagged.
3
+ export const catalogueFamilies = ["llm", "image", "tts"];
4
+ export const noChanges = { added: [], retired: [], priced: [] };
5
+ export function modelKey(family, provider, id) {
6
+ return `${family}:${provider}:${id}`;
7
+ }
8
+ function ref(family, model) {
9
+ return { family, provider: model.provider, id: model.id, name: model.name };
10
+ }
11
+ function samePricing(a, b) {
12
+ const keys = new Set([...Object.keys(a), ...Object.keys(b)]);
13
+ for (const key of keys) {
14
+ if (key === "note")
15
+ continue;
16
+ const x = a[key];
17
+ const y = b[key];
18
+ // A price read back from per-token figures differs from the curated one only in rounding.
19
+ if (typeof x === "number" && typeof y === "number") {
20
+ if (Math.abs(x - y) > 1e-9 * Math.max(1, Math.abs(x), Math.abs(y)))
21
+ return false;
22
+ }
23
+ else if (x !== y)
24
+ return false;
25
+ }
26
+ return true;
27
+ }
28
+ // Folds the published catalogue into the local one instead of replacing it:
29
+ // - a published model replaces the local row (prices, names, capabilities), except that a model
30
+ // the user switched off stays off and a speech model keeps its local character limit, which
31
+ // decides how narration is split and so what existing projects count as up to date;
32
+ // - a published model the local file lacks is added;
33
+ // - a local model that was published before and no longer is, or that the published file marks
34
+ // deprecated, is kept and marked deprecated, so pickers hide it and the places that use it can
35
+ // be listed; a model the user added themselves (never published) is left alone.
36
+ export function mergeCatalogue(local, published, knownPublished) {
37
+ const added = [];
38
+ const retired = [];
39
+ const priced = [];
40
+ const known = new Set(knownPublished);
41
+ const merge = (family, localRows, publishedRows) => {
42
+ const localByKey = new Map(localRows.map((row) => [modelKey(family, row.provider, row.id), row]));
43
+ const publishedKeys = new Set();
44
+ const rows = [];
45
+ for (const row of publishedRows) {
46
+ const key = modelKey(family, row.provider, row.id);
47
+ publishedKeys.add(key);
48
+ known.add(key);
49
+ const before = localByKey.get(key);
50
+ if (before === undefined) {
51
+ added.push(ref(family, row));
52
+ rows.push(row);
53
+ continue;
54
+ }
55
+ let next = before.enabled ? row : { ...row, enabled: false };
56
+ if ("tts" in before && "tts" in next)
57
+ next = { ...next, tts: { ...next.tts, maxCharacters: before.tts.maxCharacters } };
58
+ if (!before.deprecated && next.deprecated)
59
+ retired.push(ref(family, next));
60
+ if (!samePricing(before.pricing, next.pricing))
61
+ priced.push({ ...ref(family, next), before: before.pricing, after: next.pricing });
62
+ rows.push(next);
63
+ }
64
+ for (const row of localRows) {
65
+ const key = modelKey(family, row.provider, row.id);
66
+ if (publishedKeys.has(key))
67
+ continue;
68
+ if (knownPublished.has(key) && !row.deprecated) {
69
+ retired.push(ref(family, row));
70
+ rows.push({ ...row, deprecated: true });
71
+ }
72
+ else
73
+ rows.push(row);
74
+ }
75
+ return rows;
76
+ };
77
+ const catalogue = {
78
+ schemaVersion: 1,
79
+ updatedAt: published.updatedAt > local.updatedAt ? published.updatedAt : local.updatedAt,
80
+ providers: { ...local.providers, ...published.providers },
81
+ llm: merge("llm", local.llm, published.llm),
82
+ image: merge("image", local.image, published.image),
83
+ tts: merge("tts", local.tts, published.tts),
84
+ };
85
+ return { catalogue, changes: { added, retired, priced }, known };
86
+ }
87
+ export function applyOpenRouterListing(catalogue, listing) {
88
+ if (listing.length === 0)
89
+ return { catalogue, changes: noChanges };
90
+ const byId = new Map(listing.map((row) => [row.id, row]));
91
+ const retired = [];
92
+ const priced = [];
93
+ const llm = catalogue.llm.map((row) => {
94
+ if (row.provider !== "openrouter" || row.deprecated)
95
+ return row;
96
+ const live = byId.get(row.id);
97
+ if (live === undefined) {
98
+ retired.push(ref("llm", row));
99
+ return { ...row, deprecated: true };
100
+ }
101
+ const pricing = {
102
+ ...row.pricing,
103
+ ...(live.promptPerToken === undefined
104
+ ? {}
105
+ : { inputPerMillionTokens: perMillion(live.promptPerToken) }),
106
+ ...(live.completionPerToken === undefined
107
+ ? {}
108
+ : { outputPerMillionTokens: perMillion(live.completionPerToken) }),
109
+ };
110
+ if (samePricing(row.pricing, pricing))
111
+ return row;
112
+ priced.push({ ...ref("llm", row), before: row.pricing, after: pricing });
113
+ return { ...row, pricing };
114
+ });
115
+ return { catalogue: { ...catalogue, llm }, changes: { added: [], retired, priced } };
116
+ }
117
+ function perMillion(perToken) {
118
+ return Math.round(perToken * 1_000_000 * 1_000_000) / 1_000_000;
119
+ }
120
+ export function combineChanges(a, b) {
121
+ const priced = new Map();
122
+ for (const row of [...a.priced, ...b.priced]) {
123
+ const key = modelKey(row.family, row.provider, row.id);
124
+ const earlier = priced.get(key);
125
+ priced.set(key, earlier === undefined ? row : { ...row, before: earlier.before });
126
+ }
127
+ return {
128
+ added: [...a.added, ...b.added],
129
+ retired: [...a.retired, ...b.retired],
130
+ priced: [...priced.values()],
131
+ };
132
+ }
@@ -9,7 +9,7 @@ export function curateRegistry(registry, catalogue) {
9
9
  if (!model)
10
10
  throw providerError({
11
11
  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 Resume.`,
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.`,
13
13
  });
14
14
  return model;
15
15
  };
@@ -25,7 +25,7 @@ export function curateRegistry(registry, catalogue) {
25
25
  if (request.model.trim() === "")
26
26
  throw providerError({
27
27
  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 Resume.",
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.",
29
29
  });
30
30
  let models;
31
31
  try {
@@ -39,19 +39,19 @@ export function curateRegistry(registry, catalogue) {
39
39
  if (models !== undefined && selected === undefined)
40
40
  throw providerError({
41
41
  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 Resume.",
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.",
43
43
  });
44
44
  if (request.thinking !== undefined &&
45
45
  selected !== undefined &&
46
46
  !selected.thinkingModes?.includes(request.thinking))
47
47
  throw providerError({
48
48
  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 Resume.",
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.",
50
50
  });
51
51
  if (request.webSearch && !port.capabilities.webSearch)
52
52
  throw providerError({
53
53
  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 Resume.",
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.",
55
55
  });
56
56
  const thinkingConfig = id === "codex" && request.thinking !== undefined
57
57
  ? { effort: request.thinking === "off" ? "none" : request.thinking }
@@ -80,13 +80,13 @@ export function curateRegistry(registry, catalogue) {
80
80
  if (request.webSearch && !model.llm.webSearch)
81
81
  throw providerError({
82
82
  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 Resume.",
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.",
84
84
  });
85
85
  const thinkingConfig = request.thinking === undefined ? undefined : model.llm.thinking?.[request.thinking];
86
86
  if (request.thinking !== undefined && !thinkingConfig)
87
87
  throw providerError({
88
88
  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 Resume.",
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.",
90
90
  });
91
91
  yield* port.complete({
92
92
  ...request,
@@ -107,14 +107,14 @@ export function curateRegistry(registry, catalogue) {
107
107
  throw providerError({
108
108
  kind: "unsupported",
109
109
  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 Resume."
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 Resume.",
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.",
112
112
  });
113
113
  if (request.thinking !== undefined &&
114
114
  !selected.thinkingModes?.includes(request.thinking))
115
115
  throw providerError({
116
116
  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 Resume.",
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.",
118
118
  });
119
119
  return port.generate(request);
120
120
  },
@@ -128,12 +128,12 @@ export function curateRegistry(registry, catalogue) {
128
128
  if (!("image" in model) || !model.image.aspectRatios.includes(request.aspect))
129
129
  throw providerError({
130
130
  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 Resume.",
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.",
132
132
  });
133
133
  if (request.thinking !== undefined)
134
134
  throw providerError({
135
135
  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 Resume.",
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.",
137
137
  });
138
138
  if (request.reference !== undefined && !takesReferenceImage(model))
139
139
  throw providerError({
@@ -159,7 +159,7 @@ export function curateRegistry(registry, catalogue) {
159
159
  if (request.text.length > model.tts.maxCharacters)
160
160
  throw providerError({
161
161
  kind: "unsupported",
162
- message: `A piece of narration is longer than this voice model's ${model.tts.maxCharacters}-character limit. Use Re-run section on Audio so Slopify splits it into shorter pieces.`,
162
+ 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.`,
163
163
  });
164
164
  return port.synthesize({ ...request, model: model.id });
165
165
  },
@@ -14,6 +14,8 @@ const base = z.object({
14
14
  .object({
15
15
  inputPerMillionTokens: money.optional(),
16
16
  outputPerMillionTokens: money.optional(),
17
+ // Input read from the provider's prompt cache. Absent, cached input is priced as input.
18
+ cachedInputPerMillionTokens: money.optional(),
17
19
  perMillionCharacters: money.optional(),
18
20
  perImage: money.optional(),
19
21
  perMinute: money.optional(),