@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.
- package/dist/adapters/account-limits.js +30 -0
- package/dist/adapters/alignment/audio.js +1 -1
- package/dist/adapters/alignment/cache.js +4 -6
- package/dist/adapters/alignment/ctc.js +1 -2
- package/dist/adapters/alignment/lock.js +4 -3
- package/dist/adapters/alignment/multilingual.js +2 -4
- package/dist/adapters/alignment/prefetch.js +2 -1
- package/dist/adapters/alignment/runner.js +1 -1
- package/dist/adapters/alignment/worker.js +3 -2
- package/dist/adapters/explain.js +10 -12
- package/dist/adapters/ffmpeg.js +19 -1
- package/dist/adapters/host-cli/index.js +21 -4
- package/dist/adapters/host-cli/transport.js +2 -1
- package/dist/adapters/http-failure.js +53 -0
- package/dist/adapters/image/bytes.js +2 -1
- package/dist/adapters/image/codex.js +42 -9
- package/dist/adapters/image/fal.js +21 -53
- package/dist/adapters/image/google.js +33 -56
- package/dist/adapters/image/models.js +2 -2
- package/dist/adapters/image/openai.js +22 -48
- package/dist/adapters/image/reference.js +36 -0
- package/dist/adapters/image/replicate.js +21 -49
- package/dist/adapters/image/video.js +2 -1
- package/dist/adapters/interest/search-interest.js +113 -0
- package/dist/adapters/key-probes.js +54 -3
- package/dist/adapters/llm/antigravity-models.js +1 -1
- package/dist/adapters/llm/antigravity.js +11 -6
- package/dist/adapters/llm/assistant-cli.js +388 -0
- package/dist/adapters/llm/child-session.js +83 -0
- package/dist/adapters/llm/claude-code-models.js +52 -99
- package/dist/adapters/llm/claude-code.js +16 -4
- package/dist/adapters/llm/codex-limits.js +27 -68
- package/dist/adapters/llm/codex-models.js +1 -1
- package/dist/adapters/llm/codex-server-models.js +61 -109
- package/dist/adapters/llm/codex.js +12 -1
- package/dist/adapters/llm/document-workspace.js +3 -2
- package/dist/adapters/llm/image-workspace.js +3 -2
- package/dist/adapters/llm/openrouter.js +12 -48
- package/dist/adapters/llm/run-cli.js +9 -24
- package/dist/adapters/llm/sse-lines.js +5 -1
- package/dist/adapters/model-access.js +37 -0
- package/dist/adapters/tts/cartesia.js +15 -46
- package/dist/adapters/tts/elevenlabs.js +20 -52
- package/dist/adapters/tts/gemini.js +21 -41
- package/dist/adapters/tts/inworld-async.js +6 -2
- package/dist/adapters/tts/inworld.js +6 -2
- package/dist/adapters/tts/openai.js +20 -50
- package/dist/adapters/tts/system.js +2 -1
- package/dist/assets/models-lifecycle.yaml +6 -0
- package/dist/assistant-wiring.js +60 -0
- package/dist/autopilot-timers.js +59 -0
- package/dist/catalog/lifecycle.js +52 -0
- package/dist/catalog/propose.js +204 -0
- package/dist/catalog/registry.js +23 -14
- package/dist/catalog/schema.js +4 -1
- package/dist/catalog/store.js +39 -0
- package/dist/catalog/validate.js +5 -2
- package/dist/edge/autostart/native.js +3 -5
- package/dist/edge/autostart/prompt.js +2 -1
- package/dist/edge/autostart/service.js +3 -4
- package/dist/edge/cli-args.js +3 -4
- package/dist/edge/cli.js +2 -1
- package/dist/edge/docker-install/apply.js +11 -11
- package/dist/edge/docker-install/run.js +2 -1
- package/dist/edge/docker-install/state.js +4 -3
- package/dist/edge/docker-install/tree.js +2 -4
- package/dist/edge/docker-install/volume.js +3 -2
- package/dist/edge/docker.js +5 -4
- package/dist/edge/events/hub.js +5 -5
- package/dist/edge/http/actions.js +11 -32
- package/dist/edge/http/actor.js +5 -3
- package/dist/edge/http/app.js +86 -11
- package/dist/edge/http/assistant.js +129 -0
- package/dist/edge/http/audio-preview.js +4 -11
- package/dist/edge/http/auditions.js +1 -1
- package/dist/edge/http/autostart.js +5 -5
- package/dist/edge/http/backups.js +2 -4
- package/dist/edge/http/channel-memory.js +9 -22
- package/dist/edge/http/channels.js +14 -27
- package/dist/edge/http/checkpoints.js +39 -21
- package/dist/edge/http/design-templates.js +167 -0
- package/dist/edge/http/designs.js +178 -0
- package/dist/edge/http/diagnostics.js +5 -1
- package/dist/edge/http/document-themes.js +5 -14
- package/dist/edge/http/draft-files.js +1 -3
- package/dist/edge/http/draft-problem.js +5 -10
- package/dist/edge/http/drafts.js +3 -3
- package/dist/edge/http/entries.js +6 -9
- package/dist/edge/http/extension-auth.js +27 -0
- package/dist/edge/http/external-reviews.js +12 -11
- package/dist/edge/http/files.js +5 -11
- package/dist/edge/http/folder-location.js +1 -4
- package/dist/edge/http/fonts.js +0 -7
- package/dist/edge/http/home.js +47 -14
- package/dist/edge/http/host-cli.js +18 -8
- package/dist/edge/http/ids.js +8 -0
- package/dist/edge/http/keywords.js +35 -0
- package/dist/edge/http/model-checks.js +132 -0
- package/dist/edge/http/narration-peaks.js +5 -13
- package/dist/edge/http/onboarding.js +30 -26
- package/dist/edge/http/open-folder.js +5 -10
- package/dist/edge/http/outputs.js +7 -14
- package/dist/edge/http/patch-notes.js +6 -12
- package/dist/edge/http/planning.js +3 -7
- package/dist/edge/http/problem.js +2 -4
- package/dist/edge/http/project-create.js +2 -1
- package/dist/edge/http/project-templates.js +31 -19
- package/dist/edge/http/projects.js +24 -16
- package/dist/edge/http/prompts.js +9 -16
- package/dist/edge/http/pronunciations.js +1 -2
- package/dist/edge/http/providers.js +48 -34
- package/dist/edge/http/refusal.js +29 -0
- package/dist/edge/http/remote-access.js +40 -0
- package/dist/edge/http/remote-guard.js +71 -0
- package/dist/edge/http/request-guard.js +91 -0
- package/dist/edge/http/reviews.js +12 -25
- package/dist/edge/http/revision-files.js +6 -11
- package/dist/edge/http/revisions.js +14 -19
- package/dist/edge/http/run-cost.js +1 -2
- package/dist/edge/http/same-page.js +80 -0
- package/dist/edge/http/schedules.js +69 -40
- package/dist/edge/http/settings.js +27 -14
- package/dist/edge/http/social.js +283 -0
- package/dist/edge/http/staging.js +3 -5
- package/dist/edge/http/storage-files.js +5 -7
- package/dist/edge/http/storage.js +33 -25
- package/dist/edge/http/studio.js +94 -69
- package/dist/edge/http/style-preview.js +3 -6
- package/dist/edge/http/subtitles.js +3 -17
- package/dist/edge/http/template-studio.js +436 -0
- package/dist/edge/http/trash.js +11 -12
- package/dist/edge/http/tutorial.js +1 -2
- package/dist/edge/http/tutorials.js +5 -11
- package/dist/edge/http/update.js +7 -13
- package/dist/edge/http/waveform.js +3 -6
- package/dist/edge/http/youtube-edits.js +3 -4
- package/dist/edge/mcp/assistant.js +279 -0
- package/dist/edge/mcp/attribution.js +8 -2
- package/dist/edge/mcp/call-route.js +11 -2
- package/dist/edge/mcp/excluded-routes.js +29 -3
- package/dist/edge/mcp/http.js +11 -2
- package/dist/edge/mcp/instructions.js +6 -4
- package/dist/edge/mcp/library-tools.js +9 -5
- package/dist/edge/mcp/remake-tools.js +7 -4
- package/dist/edge/mcp/route-tool.js +35 -15
- package/dist/edge/mcp/server.js +13 -8
- package/dist/edge/mcp/tools-channels.js +11 -9
- package/dist/edge/mcp/tools-designs.js +165 -0
- package/dist/edge/mcp/tools-library.js +19 -7
- package/dist/edge/mcp/tools-planning.js +40 -21
- package/dist/edge/mcp/tools-projects.js +38 -11
- package/dist/edge/mcp/tools-publishing.js +9 -9
- package/dist/edge/mcp/tools-runs.js +23 -10
- package/dist/edge/mcp/tools-schedules.js +32 -8
- package/dist/edge/mcp/tools-setup.js +75 -11
- package/dist/edge/mcp/tools-social.js +47 -0
- package/dist/edge/mcp/tools-storage.js +11 -3
- package/dist/edge/mcp/tools-template-studio.js +166 -0
- package/dist/edge/mcp/tools.js +6 -0
- package/dist/edge/remote-access/cli.js +71 -0
- package/dist/edge/remote-access/model.js +32 -0
- package/dist/edge/remote-access/rules.js +207 -0
- package/dist/edge/remote-access/service.js +203 -0
- package/dist/edge/remote-access/store.js +44 -0
- package/dist/edge/remote-access/views.js +43 -0
- package/dist/extension/slopify-studio-chrome.zip +0 -0
- package/dist/extension/slopify-studio-firefox.zip +0 -0
- package/dist/host-cli/install.js +2 -2
- package/dist/host-cli/open-folder.js +2 -2
- package/dist/host-cli/paths.js +2 -4
- package/dist/host-cli/server.js +4 -4
- package/dist/host-cli/service.js +3 -3
- package/dist/host-cli/status.js +7 -7
- package/dist/kernel/db/migrations/0063-model-checks.sql +20 -0
- package/dist/kernel/db/migrations/0064-template-studio.sql +46 -0
- package/dist/kernel/db/migrations/0065-promise-and-assistant-reviews.sql +58 -0
- package/dist/kernel/db/migrations/0066-assistant.sql +44 -0
- package/dist/kernel/db/migrations/0067-autopilot.sql +6 -0
- package/dist/kernel/db/migrations/0068-topic-scores.sql +17 -0
- package/dist/kernel/db/migrations/0070-designs.sql +53 -0
- package/dist/kernel/db/migrations/0071-design-usage.sql +33 -0
- package/dist/kernel/db/migrations/0072-design-templates.sql +33 -0
- package/dist/kernel/db/migrations/0073-schedule-design-kind.sql +5 -0
- package/dist/kernel/db/migrations/0074-template-bakeoffs.sql +44 -0
- package/dist/kernel/db/migrations/0075-social-posts.sql +25 -0
- package/dist/kernel/db/migrations/0076-channel-social.sql +5 -0
- package/dist/kernel/db/migrations/0077-post-prompts.sql +17 -0
- package/dist/kernel/db/migrations/0078-uploaded-from-links.sql +7 -0
- package/dist/kernel/db/tx.js +2 -4
- package/dist/kernel/errors.js +27 -1
- package/dist/kernel/json-answer.js +15 -0
- package/dist/kernel/lock.js +4 -9
- package/dist/kernel/paths.js +8 -0
- package/dist/kernel/pipeline.js +12 -0
- package/dist/kernel/ports/assistant-cli.js +4 -0
- package/dist/kernel/ports/host-cli.js +3 -0
- package/dist/kernel/ports/interest.js +4 -0
- package/dist/kernel/ports/languages.js +0 -3
- package/dist/kernel/ports/model.js +2 -0
- package/dist/kernel/ports/settings-places.js +31 -0
- package/dist/kernel/ports/system-speech.js +31 -3
- package/dist/kernel/runner/attempt.js +14 -4
- package/dist/kernel/runner/audition.js +3 -1
- package/dist/kernel/runner/checkpoint-authority.js +2 -1
- package/dist/kernel/runner/index.js +8 -10
- package/dist/kernel/runner/model-access.js +40 -0
- package/dist/kernel/runner/model-check.js +153 -0
- package/dist/kernel/runner/providers.js +18 -12
- package/dist/kernel/runner/standalone.js +11 -7
- package/dist/main.js +338 -21
- package/dist/model-catalog.js +20 -0
- package/dist/model-checks.js +166 -0
- package/dist/patch-notes/4.0.0.md +51 -0
- package/dist/patch-notes/4.1.0.md +42 -0
- package/dist/patch-notes/index.json +12 -0
- package/dist/slices/admission/heads.js +2 -1
- package/dist/slices/admission/listing-facts.js +95 -0
- package/dist/slices/admission/repo.js +11 -7
- package/dist/slices/admission/rules.js +50 -15
- package/dist/slices/admission/schema.js +8 -0
- package/dist/slices/admission/stage-writes.js +0 -3
- package/dist/slices/admission/start.js +48 -31
- package/dist/slices/admission/state-words.js +34 -5
- package/dist/slices/admission/substitute.js +7 -4
- package/dist/slices/agents/attention-posts.js +31 -0
- package/dist/slices/agents/attention-templates.js +33 -0
- package/dist/slices/agents/attention.js +10 -1
- package/dist/slices/agents/connection.js +2 -6
- package/dist/slices/agents/model.js +6 -3
- package/dist/slices/agents/repo.js +15 -7
- package/dist/slices/article/continuation.js +0 -63
- package/dist/slices/article/plain.js +3 -2
- package/dist/slices/article/segments.js +2 -62
- package/dist/slices/assistant/access.js +1 -0
- package/dist/slices/assistant/asks.js +80 -0
- package/dist/slices/assistant/cost.js +54 -0
- package/dist/slices/assistant/gate.js +222 -0
- package/dist/slices/assistant/model.js +86 -0
- package/dist/slices/assistant/names.js +23 -0
- package/dist/slices/assistant/prompt.js +74 -0
- package/dist/slices/assistant/repo.js +74 -0
- package/dist/slices/assistant/tokens.js +18 -0
- package/dist/slices/assistant/turn.js +344 -0
- package/dist/slices/autopilot/buffer.js +76 -0
- package/dist/slices/autopilot/model.js +14 -0
- package/dist/slices/autopilot/notify.js +27 -0
- package/dist/slices/autopilot/repo.js +34 -0
- package/dist/slices/autopilot/signals.js +194 -0
- package/dist/slices/autopilot/warnings.js +85 -0
- package/dist/slices/autopilot/weekly.js +100 -0
- package/dist/slices/backups/files.js +2 -6
- package/dist/slices/backups/repo.js +3 -15
- package/dist/slices/backups/service.js +8 -7
- package/dist/slices/channels/cast-images.js +3 -2
- package/dist/slices/channels/model.js +0 -1
- package/dist/slices/channels/rebrand.js +0 -3
- package/dist/slices/channels/repo.js +4 -0
- package/dist/slices/channels/schema.js +7 -1
- package/dist/slices/channels/service.js +10 -0
- package/dist/slices/channels/videos.js +3 -15
- package/dist/slices/checkpoints/index.js +0 -1
- package/dist/slices/control/providers.js +2 -28
- package/dist/slices/designs/artwork.js +66 -0
- package/dist/slices/designs/budget.js +23 -0
- package/dist/slices/designs/calls.js +124 -0
- package/dist/slices/designs/check-context.js +38 -0
- package/dist/slices/designs/check-text.js +43 -0
- package/dist/slices/designs/fields.js +88 -0
- package/dist/slices/designs/frames.js +34 -0
- package/dist/slices/designs/gate.js +130 -0
- package/dist/slices/designs/layout.js +293 -0
- package/dist/slices/designs/model.js +35 -0
- package/dist/slices/designs/pdf-job.js +23 -0
- package/dist/slices/designs/pdf-pages.js +30 -0
- package/dist/slices/designs/pdf-runner.js +68 -0
- package/dist/slices/designs/pdf-worker.js +24 -0
- package/dist/slices/designs/picture-size.js +79 -0
- package/dist/slices/designs/pictures.js +55 -0
- package/dist/slices/designs/quote.js +24 -0
- package/dist/slices/designs/render-args.js +36 -0
- package/dist/slices/designs/render-input.js +59 -0
- package/dist/slices/designs/render.js +215 -0
- package/dist/slices/designs/repo.js +101 -0
- package/dist/slices/designs/requests.js +80 -0
- package/dist/slices/designs/runner.js +239 -0
- package/dist/slices/designs/sample-repo.js +91 -0
- package/dist/slices/designs/sample.js +223 -0
- package/dist/slices/designs/schema.js +87 -0
- package/dist/slices/designs/sections.js +44 -0
- package/dist/slices/designs/service.js +233 -0
- package/dist/slices/designs/steps-repo.js +102 -0
- package/dist/slices/designs/studio-kind.js +39 -0
- package/dist/slices/designs/template-checks.js +44 -0
- package/dist/slices/designs/template-make.js +118 -0
- package/dist/slices/designs/templates.js +218 -0
- package/dist/slices/document/fonts.js +2 -1
- package/dist/slices/document/model.js +7 -4
- package/dist/slices/document/render.js +2 -1
- package/dist/slices/document/theme-schema.js +1 -1
- package/dist/slices/document/theme.js +49 -3
- package/dist/slices/episodes/summarize.js +6 -2
- package/dist/slices/estimate/index.js +72 -28
- package/dist/slices/estimate/requests.js +4 -4
- package/dist/slices/fixes/rules.js +3 -1
- package/dist/slices/fonts/catalog.js +5 -3
- package/dist/slices/fonts/coverage.js +2 -1
- package/dist/slices/fonts/discovery.js +3 -2
- package/dist/slices/fonts/files.js +2 -6
- package/dist/slices/fonts/index.js +0 -1
- package/dist/slices/fonts/sfnt.js +45 -10
- package/dist/slices/images/appearance.js +8 -16
- package/dist/slices/images/scenes.js +102 -28
- package/dist/slices/keywords/digest.js +85 -0
- package/dist/slices/keywords/facts.js +92 -0
- package/dist/slices/keywords/fill.js +80 -0
- package/dist/slices/keywords/model.js +75 -0
- package/dist/slices/keywords/rules.js +187 -0
- package/dist/slices/keywords/schema.js +28 -0
- package/dist/slices/keywords/specs.js +260 -0
- package/dist/slices/keywords/values.js +74 -0
- package/dist/slices/library/lint.js +29 -12
- package/dist/slices/library/model.js +2 -0
- package/dist/slices/library/photorealistic.js +4 -12
- package/dist/slices/library/rename.js +9 -7
- package/dist/slices/library/save.js +14 -10
- package/dist/slices/library/slots.js +37 -11
- package/dist/slices/library/transfer.js +5 -4
- package/dist/slices/library/used-by.js +25 -10
- package/dist/slices/loudness/loudnorm.js +53 -12
- package/dist/slices/loudness/model.js +3 -2
- package/dist/slices/loudness/sentence-level.js +2 -1
- package/dist/slices/model-checks/cost.js +61 -0
- package/dist/slices/model-checks/listing.js +124 -0
- package/dist/slices/model-checks/model.js +20 -0
- package/dist/slices/model-checks/record.js +32 -0
- package/dist/slices/model-checks/repo.js +120 -0
- package/dist/slices/model-checks/rules.js +125 -0
- package/dist/slices/model-checks/run.js +143 -0
- package/dist/slices/model-checks/service.js +198 -0
- package/dist/slices/model-upkeep/model.js +1 -1
- package/dist/slices/model-upkeep/switch.js +72 -27
- package/dist/slices/model-upkeep/usage.js +39 -13
- package/dist/slices/narration/breaths.js +3 -1
- package/dist/slices/narration/clean-pieces.js +3 -1
- package/dist/slices/narration/concat.js +2 -1
- package/dist/slices/narration/pauses-model.js +3 -2
- package/dist/slices/narration/peaks.js +3 -4
- package/dist/slices/narration/pronunciation-chunks.js +4 -3
- package/dist/slices/narration/pronunciation.js +6 -4
- package/dist/slices/narration/steering.js +4 -3
- package/dist/slices/notifications/notifier.js +4 -3
- package/dist/slices/notifications/rules.js +5 -2
- package/dist/slices/notifications/settings.js +4 -12
- package/dist/slices/notifications/subject.js +4 -3
- package/dist/slices/onboarding/copy.js +21 -3
- package/dist/slices/onboarding/first-run.js +16 -40
- package/dist/slices/onboarding/full-video.js +3 -2
- package/dist/slices/onboarding/install.js +6 -4
- package/dist/slices/onboarding/model.js +26 -37
- package/dist/slices/onboarding/packs.js +22 -22
- package/dist/slices/onboarding/preferred-model.js +14 -0
- package/dist/slices/onboarding/quick-short.js +105 -65
- package/dist/slices/onboarding/sample.js +4 -2
- package/dist/slices/onboarding/state.js +9 -11
- package/dist/slices/onboarding/template.js +8 -6
- package/dist/slices/outputs/add.js +3 -2
- package/dist/slices/outputs/service.js +2 -2
- package/dist/slices/patch-notes/library.js +4 -3
- package/dist/slices/play-drafts/convert.js +4 -0
- package/dist/slices/play-drafts/readiness.js +3 -3
- package/dist/slices/play-drafts/review-inputs.js +9 -3
- package/dist/slices/play-drafts/review.js +5 -4
- package/dist/slices/play-drafts/schema.js +4 -0
- package/dist/slices/play-drafts/service.js +17 -7
- package/dist/slices/project-templates/from-project.js +9 -2
- package/dist/slices/project-templates/next-chapter.js +2 -1
- package/dist/slices/project-templates/provider-defaults.js +22 -0
- package/dist/slices/project-templates/repo.js +6 -1
- package/dist/slices/project-templates/setup-sections.js +26 -0
- package/dist/slices/project-templates/setup.js +14 -1
- package/dist/slices/project-templates/stand-ins.js +22 -0
- package/dist/slices/rebuild/activity.js +2 -0
- package/dist/slices/rebuild/admission-repo.js +3 -2
- package/dist/slices/rebuild/narration-history.js +4 -5
- package/dist/slices/rebuild/narration-retry.js +2 -1
- package/dist/slices/rebuild/preview-details.js +32 -14
- package/dist/slices/rebuild/preview-plan.js +3 -8
- package/dist/slices/rebuild/recipe-build.js +8 -3
- package/dist/slices/rebuild/recipe-describe.js +3 -3
- package/dist/slices/rebuild/recipe-digest.js +58 -0
- package/dist/slices/rebuild/recipe-input-schema.js +10 -0
- package/dist/slices/rebuild/recipe-keywords.js +71 -0
- package/dist/slices/rebuild/recipe-legacy.js +5 -1
- package/dist/slices/rebuild/recipe-model.js +4 -0
- package/dist/slices/rebuild/recipe-narration-text.js +2 -1
- package/dist/slices/rebuild/recipe-preparation.js +4 -4
- package/dist/slices/rebuild/recipe-reference.js +8 -4
- package/dist/slices/rebuild/recipe-reviews.js +27 -7
- package/dist/slices/rebuild/recipe-save.js +8 -5
- package/dist/slices/rebuild/recipe-scenes.js +40 -11
- package/dist/slices/rebuild/recipe-shorts.js +8 -8
- package/dist/slices/rebuild/recipe-social.js +46 -0
- package/dist/slices/rebuild/recipe-text.js +64 -20
- package/dist/slices/rebuild/recipe-validation.js +102 -31
- package/dist/slices/rebuild/recipe-visual.js +55 -16
- package/dist/slices/rebuild/recipe-voices.js +3 -2
- package/dist/slices/rebuild/recipe-work.js +19 -7
- package/dist/slices/rebuild/recipe-youtube.js +4 -3
- package/dist/slices/rebuild/recovery-selection.js +3 -1
- package/dist/slices/rebuild/recovery.js +9 -8
- package/dist/slices/rebuild/remake-outdated.js +5 -5
- package/dist/slices/rebuild/repo.js +4 -3
- package/dist/slices/rebuild/review-promise.js +25 -0
- package/dist/slices/rebuild/review-redo.js +3 -2
- package/dist/slices/rebuild/runtime-admission.js +4 -3
- package/dist/slices/rebuild/runtime-agent-review.js +11 -5
- package/dist/slices/rebuild/runtime-animate.js +10 -9
- package/dist/slices/rebuild/runtime-article.js +7 -5
- package/dist/slices/rebuild/runtime-checkpoints.js +5 -4
- package/dist/slices/rebuild/runtime-document.js +11 -13
- package/dist/slices/rebuild/runtime-export-bed.js +8 -12
- package/dist/slices/rebuild/runtime-export-edit.js +8 -16
- package/dist/slices/rebuild/runtime-export-inputs.js +12 -11
- package/dist/slices/rebuild/runtime-export-short.js +9 -5
- package/dist/slices/rebuild/runtime-export.js +38 -15
- package/dist/slices/rebuild/runtime-figure-card.js +2 -1
- package/dist/slices/rebuild/runtime-image.js +8 -12
- package/dist/slices/rebuild/runtime-instructions.js +2 -0
- package/dist/slices/rebuild/runtime-keywords.js +59 -0
- package/dist/slices/rebuild/runtime-lines.js +2 -11
- package/dist/slices/rebuild/runtime-local.js +17 -22
- package/dist/slices/rebuild/runtime-narration-publication.js +2 -5
- package/dist/slices/rebuild/runtime-narration-reuse.js +9 -13
- package/dist/slices/rebuild/runtime-narration-text.js +13 -17
- package/dist/slices/rebuild/runtime-pictures.js +2 -4
- package/dist/slices/rebuild/runtime-piece-label.js +10 -6
- package/dist/slices/rebuild/runtime-plan.js +31 -5
- package/dist/slices/rebuild/runtime-provider.js +67 -25
- package/dist/slices/rebuild/runtime-publication.js +10 -9
- package/dist/slices/rebuild/runtime-review.js +39 -33
- package/dist/slices/rebuild/runtime-run.js +4 -1
- package/dist/slices/rebuild/runtime-shorts.js +31 -50
- package/dist/slices/rebuild/runtime-store.js +20 -10
- package/dist/slices/rebuild/runtime-subtitles.js +28 -25
- package/dist/slices/rebuild/runtime-voices.js +10 -16
- package/dist/slices/rebuild/runtime-youtube.js +14 -31
- package/dist/slices/rebuild/service-readiness.js +11 -3
- package/dist/slices/rebuild/transition-repo.js +6 -5
- package/dist/slices/rebuild/work-records.js +6 -0
- package/dist/slices/reruns/cascade.js +1 -2
- package/dist/slices/reruns/index.js +6 -9
- package/dist/slices/research/synthesis.js +3 -2
- package/dist/slices/reviews/external-model.js +4 -1
- package/dist/slices/reviews/external-repo.js +2 -1
- package/dist/slices/reviews/external-rows.js +2 -3
- package/dist/slices/reviews/holds.js +5 -4
- package/dist/slices/reviews/model.js +32 -11
- package/dist/slices/reviews/repo.js +2 -1
- package/dist/slices/reviews/rules.js +4 -3
- package/dist/slices/reviews/verdict.js +2 -1
- package/dist/slices/reviews/view.js +5 -2
- package/dist/slices/revisions/downloads.js +4 -5
- package/dist/slices/revisions/image-plan.js +1 -1
- package/dist/slices/revisions/mutation-assets.js +9 -5
- package/dist/slices/revisions/mutation-cues.js +2 -5
- package/dist/slices/revisions/mutations.js +3 -3
- package/dist/slices/revisions/repo.js +3 -1
- package/dist/slices/revisions/schema.js +1 -0
- package/dist/slices/revisions/view.js +20 -0
- package/dist/slices/run-cost/limits.js +5 -2
- package/dist/slices/run-cost/meter.js +12 -5
- package/dist/slices/run-cost/panel.js +8 -74
- package/dist/slices/run-cost/plan-readings.js +127 -0
- package/dist/slices/run-cost/plan-use.js +169 -0
- package/dist/slices/run-cost/pricing.js +3 -3
- package/dist/slices/run-cost/week.js +32 -4
- package/dist/slices/schedules/agenda.js +18 -7
- package/dist/slices/schedules/by-date.js +42 -0
- package/dist/slices/schedules/calendar.js +5 -0
- package/dist/slices/schedules/design-agenda.js +36 -0
- package/dist/slices/schedules/design-check.js +41 -0
- package/dist/slices/schedules/design-run.js +126 -0
- package/dist/slices/schedules/next-run.js +62 -0
- package/dist/slices/schedules/prepare.js +18 -2
- package/dist/slices/schedules/repo.js +30 -21
- package/dist/slices/schedules/rescore.js +35 -0
- package/dist/slices/schedules/scheduler.js +13 -3
- package/dist/slices/schedules/schema.js +57 -3
- package/dist/slices/schedules/score.js +107 -0
- package/dist/slices/schedules/service.js +57 -24
- package/dist/slices/schedules/topic-list.js +15 -0
- package/dist/slices/schedules/topic-scores.js +104 -0
- package/dist/slices/schedules/topics.js +53 -41
- package/dist/slices/settings/cli-paths.js +4 -6
- package/dist/slices/settings/first-run.js +8 -43
- package/dist/slices/settings/health.js +30 -15
- package/dist/slices/settings/key-test.js +1 -1
- package/dist/slices/settings/model-reach.js +3 -17
- package/dist/slices/settings/model.js +14 -2
- package/dist/slices/settings/playback.js +34 -23
- package/dist/slices/settings/probe-read.js +16 -0
- package/dist/slices/settings/repo.js +33 -0
- package/dist/slices/settings/tutorial.js +2 -2
- package/dist/slices/settings/voices.js +4 -12
- package/dist/slices/shorts/keep.js +2 -1
- package/dist/slices/shorts/pick.js +6 -18
- package/dist/slices/shorts/prompts.js +4 -14
- package/dist/slices/shorts/render.js +6 -2
- package/dist/slices/social/channel.js +44 -0
- package/dist/slices/social/defaults.js +17 -0
- package/dist/slices/social/due.js +36 -0
- package/dist/slices/social/extension.js +18 -0
- package/dist/slices/social/fit.js +115 -0
- package/dist/slices/social/limits.js +186 -0
- package/dist/slices/social/links.js +21 -0
- package/dist/slices/social/media.js +132 -0
- package/dist/slices/social/model.js +75 -0
- package/dist/slices/social/notice.js +19 -0
- package/dist/slices/social/pack.js +176 -0
- package/dist/slices/social/post-prompt.js +56 -0
- package/dist/slices/social/queue.js +31 -0
- package/dist/slices/social/repo.js +133 -0
- package/dist/slices/social/reshape.js +97 -0
- package/dist/slices/social/rules.js +5 -0
- package/dist/slices/social/schema.js +70 -0
- package/dist/slices/social/serve.js +51 -0
- package/dist/slices/social/service.js +129 -0
- package/dist/slices/social/settings.js +21 -0
- package/dist/slices/social/sources.js +114 -0
- package/dist/slices/social/state.js +110 -0
- package/dist/slices/social/text.js +149 -0
- package/dist/slices/storage/arrange.js +3 -1
- package/dist/slices/storage/assets.js +8 -10
- package/dist/slices/storage/backup-designs.js +74 -0
- package/dist/slices/storage/backup-export.js +8 -3
- package/dist/slices/storage/backup-format.js +10 -0
- package/dist/slices/storage/backup-import.js +22 -4
- package/dist/slices/storage/delete-project.js +6 -5
- package/dist/slices/storage/files-location.js +6 -8
- package/dist/slices/storage/layout.js +13 -2
- package/dist/slices/storage/model.js +3 -0
- package/dist/slices/storage/portable.js +17 -12
- package/dist/slices/storage/schema.js +2 -0
- package/dist/slices/storage/staging-refs.js +2 -1
- package/dist/slices/storage/staging.js +6 -9
- package/dist/slices/storage/trim.js +26 -9
- package/dist/slices/studio/calendar.js +7 -2
- package/dist/slices/studio/disclosure.js +4 -4
- package/dist/slices/studio/model.js +1 -1
- package/dist/slices/studio/pack.js +9 -8
- package/dist/slices/studio/pick.js +2 -11
- package/dist/slices/studio/plan.js +7 -16
- package/dist/slices/studio/queue.js +3 -14
- package/dist/slices/studio/releases.js +26 -0
- package/dist/slices/studio/settings.js +20 -57
- package/dist/slices/studio/videos.js +35 -4
- package/dist/slices/style-preview/render.js +37 -16
- package/dist/slices/style-preview/schema.js +14 -1
- package/dist/slices/style-preview/service.js +2 -1
- package/dist/slices/style-preview/settings.js +33 -5
- package/dist/slices/subtitles/captions.js +1 -1
- package/dist/slices/telemetry/collector-client.js +2 -4
- package/dist/slices/telemetry/flush.js +2 -4
- package/dist/slices/telemetry/model.js +0 -7
- package/dist/slices/telemetry/record.js +10 -3
- package/dist/slices/template-studio/anatomy-view.js +161 -0
- package/dist/slices/template-studio/anatomy.js +73 -0
- package/dist/slices/template-studio/bakeoff-make.js +225 -0
- package/dist/slices/template-studio/bakeoff-repo.js +83 -0
- package/dist/slices/template-studio/bakeoff.js +333 -0
- package/dist/slices/template-studio/budget.js +106 -0
- package/dist/slices/template-studio/cards.js +78 -0
- package/dist/slices/template-studio/checks.js +322 -0
- package/dist/slices/template-studio/document-sample.js +56 -0
- package/dist/slices/template-studio/edit.js +15 -0
- package/dist/slices/template-studio/for-all.js +161 -0
- package/dist/slices/template-studio/free-video.js +31 -0
- package/dist/slices/template-studio/free.js +176 -0
- package/dist/slices/template-studio/gate.js +40 -0
- package/dist/slices/template-studio/hidden.js +20 -0
- package/dist/slices/template-studio/jobs.js +79 -0
- package/dist/slices/template-studio/loudness.js +111 -0
- package/dist/slices/template-studio/make.js +40 -0
- package/dist/slices/template-studio/model.js +58 -0
- package/dist/slices/template-studio/pack-import.js +253 -0
- package/dist/slices/template-studio/pack-samples.js +60 -0
- package/dist/slices/template-studio/pack.js +207 -0
- package/dist/slices/template-studio/paid-view.js +66 -0
- package/dist/slices/template-studio/paid.js +355 -0
- package/dist/slices/template-studio/quote.js +155 -0
- package/dist/slices/template-studio/ready.js +104 -0
- package/dist/slices/template-studio/repo.js +134 -0
- package/dist/slices/template-studio/reviews-path.js +58 -0
- package/dist/slices/template-studio/runner.js +84 -0
- package/dist/slices/template-studio/save.js +236 -0
- package/dist/slices/template-studio/say-it-as.js +248 -0
- package/dist/slices/template-studio/schedule-gate.js +34 -0
- package/dist/slices/template-studio/schedule-price.js +32 -0
- package/dist/slices/template-studio/schedule-sample.js +91 -0
- package/dist/slices/template-studio/schema.js +243 -0
- package/dist/slices/template-studio/scope.js +124 -0
- package/dist/slices/template-studio/sections.js +176 -0
- package/dist/slices/template-studio/service.js +175 -0
- package/dist/slices/template-studio/status.js +191 -0
- package/dist/slices/template-studio/topic.js +223 -0
- package/dist/slices/thumbnail/by-llm.js +1 -1
- package/dist/slices/trash/designs.js +76 -0
- package/dist/slices/trash/model.js +13 -4
- package/dist/slices/trash/service.js +52 -2
- package/dist/slices/tutorials/library.js +3 -2
- package/dist/slices/uploads/repo.js +37 -1
- package/dist/slices/uploads/rules.js +3 -2
- package/dist/slices/video/ass-text.js +17 -0
- package/dist/slices/video/audio-export.js +2 -64
- package/dist/slices/video/edit-list.js +2 -2
- package/dist/slices/video/edit-settings.js +1 -1
- package/dist/slices/video/encoding.js +169 -0
- package/dist/slices/video/ffmpeg.js +23 -21
- package/dist/slices/video/figure-card.js +1 -15
- package/dist/slices/video/plan.js +2 -1
- package/dist/slices/video/slideshow.js +43 -18
- package/dist/slices/voices/attribution.js +3 -2
- package/dist/slices/voices/model.js +9 -8
- package/dist/slices/voices/palette.js +0 -3
- package/dist/slices/voices/script.js +2 -1
- package/dist/slices/youtube/answer.js +4 -16
- package/dist/slices/youtube/edits-repo.js +3 -12
- package/dist/tutorials/AI-CLIs.md +25 -25
- package/dist/tutorials/Agents-MCP.md +34 -33
- package/dist/tutorials/Assistant.md +42 -0
- package/dist/tutorials/Backups.md +7 -7
- package/dist/tutorials/Calendar.md +17 -25
- package/dist/tutorials/Cast-Library.md +19 -19
- package/dist/tutorials/Channels.md +42 -35
- package/dist/tutorials/Costs-and-Run-Cost.md +38 -40
- package/dist/tutorials/Create-Article.md +114 -0
- package/dist/tutorials/Create-Extras.md +112 -0
- package/dist/tutorials/Create-Images.md +165 -0
- package/dist/tutorials/Create-Narration.md +178 -0
- package/dist/tutorials/Create-Overview.md +244 -0
- package/dist/tutorials/Create-Video-and-Style.md +144 -0
- package/dist/tutorials/Docker.md +3 -3
- package/dist/tutorials/Document-Themes.md +32 -32
- package/dist/tutorials/Editing-a-Project.md +94 -94
- package/dist/tutorials/FAQ.md +18 -18
- package/dist/tutorials/First-Launch-and-Welcome.md +50 -64
- package/dist/tutorials/Home-and-Projects.md +115 -71
- package/dist/tutorials/Home.md +33 -33
- package/dist/tutorials/Install.md +14 -13
- package/dist/tutorials/Intros-and-Outros.md +33 -34
- package/dist/tutorials/Keyboard-Shortcuts-and-Command-Palette.md +62 -58
- package/dist/tutorials/Keywords-Slopify-Fills.md +87 -0
- package/dist/tutorials/Models.md +53 -21
- package/dist/tutorials/Multiple-Voices.md +41 -40
- package/dist/tutorials/Narration-Aliases-and-Glossary.md +14 -14
- package/dist/tutorials/Notifications.md +27 -17
- package/dist/tutorials/Other-Languages.md +15 -15
- package/dist/tutorials/PDF-Documents.md +38 -29
- package/dist/tutorials/Posting-to-Social-Sites.md +121 -0
- package/dist/tutorials/Project-Page.md +118 -120
- package/dist/tutorials/Prompts-and-Templates.md +84 -0
- package/dist/tutorials/Prompts.md +48 -44
- package/dist/tutorials/Providers-and-Keys.md +105 -98
- package/dist/tutorials/Publishing-to-YouTube.md +31 -31
- package/dist/tutorials/Recovery-and-Retries.md +31 -31
- package/dist/tutorials/Remote-Access.md +63 -0
- package/dist/tutorials/Reviews-and-Checkpoints.md +98 -90
- package/dist/tutorials/Schedules.md +46 -27
- package/dist/tutorials/Settings-Reference.md +194 -174
- package/dist/tutorials/Shorts.md +34 -33
- package/dist/tutorials/Start-at-Login.md +3 -3
- package/dist/tutorials/Studio-Extension.md +22 -24
- package/dist/tutorials/Template-Studio.md +128 -0
- package/dist/tutorials/Templates.md +51 -77
- package/dist/tutorials/Trash.md +4 -4
- package/dist/tutorials/Troubleshooting.md +44 -44
- package/dist/tutorials/Uninstalling-and-Moving.md +5 -5
- package/dist/tutorials/Updating-and-Patch-Notes.md +18 -18
- package/dist/tutorials/Video-Editing.md +34 -34
- package/dist/tutorials/Where-Your-Files-Live.md +10 -10
- package/dist/tutorials/YouTube-Description.md +26 -26
- package/dist/tutorials/Your-First-Short.md +35 -35
- package/dist/tutorials/_Sidebar.md +19 -14
- package/dist/updater/work-in-progress.js +42 -12
- package/dist/web/assets/index-BNftKQrA.css +1 -0
- package/dist/web/assets/index-Cpa58woP.js +459 -0
- package/dist/web/assets/pdf-BKh8f7R6.js +56 -0
- package/dist/web/assets/pdf.worker.min-BmVo14Nb.mjs +28 -0
- package/dist/web/assets/pdf.worker.min-D7i8o3wR.js +1 -0
- package/dist/web/index.html +2 -2
- package/package.json +6 -2
- package/dist/slices/article/provided-entries.js +0 -66
- package/dist/slices/article/run.js +0 -145
- package/dist/slices/images/run.js +0 -234
- package/dist/slices/narration/legacy-plan.js +0 -58
- package/dist/slices/narration/run.js +0 -270
- package/dist/slices/rebuild/runtime-actions.js +0 -90
- package/dist/slices/research/run.js +0 -224
- package/dist/slices/subtitles/prepare.js +0 -194
- package/dist/slices/subtitles/transcript.js +0 -34
- package/dist/slices/thumbnail/run.js +0 -219
- package/dist/slices/video/audio-inputs.js +0 -33
- package/dist/slices/video/reuse-audio.js +0 -62
- package/dist/slices/video/run.js +0 -78
- package/dist/slices/video/write-export.js +0 -158
- package/dist/slices/video/write-subtitles.js +0 -59
- package/dist/tutorials/Library-Overview.md +0 -76
- package/dist/tutorials/Play-Images.md +0 -161
- package/dist/tutorials/Play-Narration.md +0 -167
- package/dist/tutorials/Play-Outputs.md +0 -109
- package/dist/tutorials/Play-Overview.md +0 -227
- package/dist/tutorials/Play-Title-and-Article.md +0 -136
- package/dist/tutorials/Play-Video-and-Style.md +0 -143
- package/dist/web/assets/index-BadsoORk.css +0 -1
- package/dist/web/assets/index-D8LqNsCl.js +0 -326
- package/dist/web/assets/pdf-T7MCwjIv.js +0 -54
- package/dist/web/assets/pdf.worker.min-Dswkl-cV.mjs +0 -29
- package/dist/web/assets/pdf.worker.min-zC6nfbxG.js +0 -1
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { errorText } from "../../kernel/errors.js";
|
|
2
|
+
import { choiceSites } from "../model-upkeep/usage.js";
|
|
3
|
+
import { isUncataloguedProvider, providerById, providerIds, providers, } from "../settings/model.js";
|
|
4
|
+
import { readSetting, writeSetting } from "../settings/repo.js";
|
|
5
|
+
import { keyOfModel, weeklyAtKey, } from "./model.js";
|
|
6
|
+
import { accountOf, readAuto, readChecks } from "./repo.js";
|
|
7
|
+
import { newForYou, standingOf } from "./rules.js";
|
|
8
|
+
import { needsConfirmation, planChecks, runChecks, } from "./run.js";
|
|
9
|
+
// ceiling: the weekly look runs once seven days have passed since the last one.
|
|
10
|
+
export const weeklyIntervalMs = 7 * 24 * 60 * 60_000;
|
|
11
|
+
function familyOfSlot(slot) {
|
|
12
|
+
return slot === "llm" ? "llm" : slot === "audio" ? "tts" : "image";
|
|
13
|
+
}
|
|
14
|
+
export function chosenModels(db) {
|
|
15
|
+
const chosen = new Set();
|
|
16
|
+
for (const site of choiceSites(db))
|
|
17
|
+
for (const [slot, choice] of Object.entries(site.choices)) {
|
|
18
|
+
if (choice === undefined || choice.provider === "" || choice.model.trim() === "")
|
|
19
|
+
continue;
|
|
20
|
+
chosen.add(keyOfModel({ provider: choice.provider, family: familyOfSlot(slot), model: choice.model }));
|
|
21
|
+
}
|
|
22
|
+
return chosen;
|
|
23
|
+
}
|
|
24
|
+
export function createModelChecks(deps) {
|
|
25
|
+
const running = new Set();
|
|
26
|
+
const stopping = new AbortController();
|
|
27
|
+
const offered = async (provider) => {
|
|
28
|
+
const { family } = providerById(provider);
|
|
29
|
+
if (isUncataloguedProvider(provider)) {
|
|
30
|
+
const models = await deps.providerModels(provider, family).catch(() => []);
|
|
31
|
+
return models.map((model) => ({ provider, family, model: model.id }));
|
|
32
|
+
}
|
|
33
|
+
return deps
|
|
34
|
+
.catalogue()[family].filter((row) => row.provider === provider && row.enabled && !row.deprecated)
|
|
35
|
+
.map((row) => ({ provider, family, model: row.id }));
|
|
36
|
+
};
|
|
37
|
+
const withAccount = () => providerIds.filter((id) => accountOf(deps.db, id) !== undefined);
|
|
38
|
+
// Named models of a CLI are taken as named: asking the CLI for its list would start it, and
|
|
39
|
+
// a picker asks this for its one chosen model whenever it opens.
|
|
40
|
+
const offeredFor = (provider, models) => {
|
|
41
|
+
if (models === undefined || !isUncataloguedProvider(provider))
|
|
42
|
+
return offered(provider);
|
|
43
|
+
const { family } = providerById(provider);
|
|
44
|
+
return Promise.resolve(models.map((model) => ({ provider, family, model })));
|
|
45
|
+
};
|
|
46
|
+
const plan = async (scope) => {
|
|
47
|
+
const scoped = scope.provider === undefined ? withAccount() : [scope.provider];
|
|
48
|
+
return planChecks({
|
|
49
|
+
catalogue: deps.catalogue(),
|
|
50
|
+
rows: readChecks(deps.db),
|
|
51
|
+
offered: (await Promise.all(scoped.map((id) => offeredFor(id, scope.models)))).flat(),
|
|
52
|
+
accounts: (id) => accountOf(deps.db, id),
|
|
53
|
+
chosen: chosenModels(deps.db),
|
|
54
|
+
}, scope);
|
|
55
|
+
};
|
|
56
|
+
// A provider is taken before the first await, so two starts that arrive together can't both
|
|
57
|
+
// pass the running check and pay for the same checks twice.
|
|
58
|
+
const reserve = (ids) => {
|
|
59
|
+
let held = [...ids];
|
|
60
|
+
for (const id of held)
|
|
61
|
+
running.add(id);
|
|
62
|
+
const release = () => {
|
|
63
|
+
for (const id of held)
|
|
64
|
+
running.delete(id);
|
|
65
|
+
held = [];
|
|
66
|
+
};
|
|
67
|
+
// Once planned, only the providers it checks stay taken.
|
|
68
|
+
const keepFor = (checks) => {
|
|
69
|
+
const owned = held.filter((id) => checks.targets.some((t) => t.provider === id));
|
|
70
|
+
for (const id of held)
|
|
71
|
+
if (!owned.includes(id))
|
|
72
|
+
running.delete(id);
|
|
73
|
+
held = owned;
|
|
74
|
+
};
|
|
75
|
+
return { release, keepFor };
|
|
76
|
+
};
|
|
77
|
+
const launch = (checks, release) => runChecks({ db: deps.db, clock: deps.clock, log: deps.log, check: deps.check }, checks,
|
|
78
|
+
// A manual plan's estimate was confirmed in `start`; an automatic one is free or cheap.
|
|
79
|
+
{ confirmedDollars: checks.totalDollars, signal: stopping.signal })
|
|
80
|
+
.then((answer) => answer.ok
|
|
81
|
+
? answer.summary
|
|
82
|
+
: { checked: 0, works: 0, noAccess: 0, failed: 0, skipped: 0, spent: 0 })
|
|
83
|
+
.finally(release);
|
|
84
|
+
const start = async (scope, confirmedDollars) => {
|
|
85
|
+
const scoped = scope.provider === undefined ? withAccount() : [scope.provider];
|
|
86
|
+
const busy = scoped.filter((id) => running.has(id));
|
|
87
|
+
if (busy.length > 0)
|
|
88
|
+
return { ok: false, reason: "running", providers: busy };
|
|
89
|
+
const { release, keepFor } = reserve(scoped);
|
|
90
|
+
let checks;
|
|
91
|
+
try {
|
|
92
|
+
checks = await plan(scope);
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
release();
|
|
96
|
+
throw error;
|
|
97
|
+
}
|
|
98
|
+
keepFor(checks);
|
|
99
|
+
if (scope.trigger === "manual" && needsConfirmation(checks, confirmedDollars)) {
|
|
100
|
+
release();
|
|
101
|
+
return { ok: false, reason: "estimate", plan: checks };
|
|
102
|
+
}
|
|
103
|
+
return { ok: true, plan: checks, done: launch(checks, release) };
|
|
104
|
+
};
|
|
105
|
+
const automatic = async (trigger, provider) => {
|
|
106
|
+
const scoped = provider === undefined ? withAccount() : [provider];
|
|
107
|
+
for (const id of scoped)
|
|
108
|
+
await deps.listing.refresh(id, true).catch((error) => {
|
|
109
|
+
deps.log.write("warn", "model-checks.listing", {
|
|
110
|
+
detail: `${id}: ${errorText(error)}`,
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
if (readAuto(deps.db) === "off")
|
|
114
|
+
return;
|
|
115
|
+
const free = scoped.filter((id) => !running.has(id));
|
|
116
|
+
if (free.length === 0)
|
|
117
|
+
return;
|
|
118
|
+
const { release, keepFor } = reserve(free);
|
|
119
|
+
let kept;
|
|
120
|
+
try {
|
|
121
|
+
const checks = await plan(provider === undefined ? { trigger } : { trigger, provider });
|
|
122
|
+
kept = {
|
|
123
|
+
...checks,
|
|
124
|
+
targets: checks.targets.filter((t) => free.some((id) => id === t.provider)),
|
|
125
|
+
};
|
|
126
|
+
keepFor(kept);
|
|
127
|
+
if (trigger === "weekly")
|
|
128
|
+
writeSetting(deps.db, weeklyAtKey, deps.clock.now().toISOString());
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
release();
|
|
132
|
+
throw error;
|
|
133
|
+
}
|
|
134
|
+
if (kept.targets.length > 0)
|
|
135
|
+
await launch(kept, release);
|
|
136
|
+
else
|
|
137
|
+
release();
|
|
138
|
+
};
|
|
139
|
+
return {
|
|
140
|
+
offered,
|
|
141
|
+
plan,
|
|
142
|
+
start,
|
|
143
|
+
automatic,
|
|
144
|
+
weeklyDue: () => {
|
|
145
|
+
if (readAuto(deps.db) === "off")
|
|
146
|
+
return false;
|
|
147
|
+
const last = readSetting(deps.db, weeklyAtKey);
|
|
148
|
+
return (last === undefined || deps.clock.now().getTime() - Date.parse(last) >= weeklyIntervalMs);
|
|
149
|
+
},
|
|
150
|
+
standings: (provider, models) => {
|
|
151
|
+
const { family } = providerById(provider);
|
|
152
|
+
const account = accountOf(deps.db, provider);
|
|
153
|
+
const rows = new Map(readChecks(deps.db, provider)
|
|
154
|
+
.filter((row) => row.family === family)
|
|
155
|
+
.map((row) => [row.model, row]));
|
|
156
|
+
return Object.fromEntries(models.map((model) => [
|
|
157
|
+
model.id,
|
|
158
|
+
standingOf(rows.get(model.id), account, deps.retiring?.({ provider, family, model: model.id })),
|
|
159
|
+
]));
|
|
160
|
+
},
|
|
161
|
+
overview: () => {
|
|
162
|
+
const rows = readChecks(deps.db);
|
|
163
|
+
const catalogue = deps.catalogue();
|
|
164
|
+
const nameOf = (key) => catalogue[key.family].find((m) => m.provider === key.provider && m.id === key.model)
|
|
165
|
+
?.name ?? key.model;
|
|
166
|
+
const states = providers.map((provider) => {
|
|
167
|
+
const account = accountOf(deps.db, provider.id);
|
|
168
|
+
const own = rows.filter((row) => row.provider === provider.id && row.account === account);
|
|
169
|
+
const times = own.flatMap((row) => (row.checkedAt === null ? [] : [row.checkedAt])).sort();
|
|
170
|
+
return {
|
|
171
|
+
provider: provider.id,
|
|
172
|
+
family: provider.family,
|
|
173
|
+
running: running.has(provider.id),
|
|
174
|
+
lastCheckedAt: times.at(-1) ?? null,
|
|
175
|
+
spent: own.reduce((sum, row) => sum + row.cost, 0),
|
|
176
|
+
works: own.filter((row) => row.verdict === "works").length,
|
|
177
|
+
noAccess: own.filter((row) => row.verdict === "no-access").length,
|
|
178
|
+
listed: own.filter((row) => row.listed === true).length,
|
|
179
|
+
};
|
|
180
|
+
});
|
|
181
|
+
const current = rows.filter((row) => providerIds.includes(row.provider) &&
|
|
182
|
+
row.account === accountOf(deps.db, row.provider));
|
|
183
|
+
return {
|
|
184
|
+
auto: readAuto(deps.db),
|
|
185
|
+
providers: states,
|
|
186
|
+
newForYou: newForYou(current).map((row) => ({
|
|
187
|
+
provider: row.provider,
|
|
188
|
+
family: row.family,
|
|
189
|
+
model: row.model,
|
|
190
|
+
name: nameOf(row),
|
|
191
|
+
firstWorksAt: row.firstWorksAt ?? "",
|
|
192
|
+
})),
|
|
193
|
+
};
|
|
194
|
+
},
|
|
195
|
+
running: () => [...running],
|
|
196
|
+
stop: () => stopping.abort(),
|
|
197
|
+
};
|
|
198
|
+
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
export const usageSlots = ["llm", "audio", "images", "animate"];
|
|
4
4
|
export const usageKinds = ["template", "schedule", "draft", "project"];
|
|
5
5
|
export const slotLabels = {
|
|
6
|
-
llm: "
|
|
6
|
+
llm: "Writing model",
|
|
7
7
|
audio: "Voice model",
|
|
8
8
|
images: "Image model",
|
|
9
9
|
animate: "Animation model",
|
|
@@ -6,8 +6,10 @@ import { templateById } from "../project-templates/repo.js";
|
|
|
6
6
|
import { updateTemplate } from "../project-templates/service.js";
|
|
7
7
|
import { ensureBaseline, saveRevision } from "../revisions/index.js";
|
|
8
8
|
import { currentRevisionId } from "../revisions/repo.js";
|
|
9
|
+
import { carryGateOnto } from "../template-studio/repo.js";
|
|
10
|
+
import { templateGate } from "../template-studio/schedule-gate.js";
|
|
9
11
|
import { configChoices, formChoices, retiredModelUsage, retiredStatus, } from "./usage.js";
|
|
10
|
-
function keepThinking(catalogue, provider, model, thinking) {
|
|
12
|
+
export function keepThinking(catalogue, provider, model, thinking) {
|
|
11
13
|
if (thinking === undefined)
|
|
12
14
|
return {};
|
|
13
15
|
const row = catalogue.llm.find((entry) => entry.provider === provider && entry.id === model);
|
|
@@ -92,7 +94,7 @@ export async function switchRetiredModel(deps, catalogue, request) {
|
|
|
92
94
|
if (row.version !== row.head)
|
|
93
95
|
return {
|
|
94
96
|
ok: false,
|
|
95
|
-
message: "This schedule runs an older version of its template. In
|
|
97
|
+
message: "This schedule runs an older version of its template. In Calendar → Schedules, choose Edit, pick the template again so it runs the latest version, then save.",
|
|
96
98
|
};
|
|
97
99
|
return switchTemplate(deps, catalogue, request, String(row.templateId));
|
|
98
100
|
}
|
|
@@ -103,32 +105,75 @@ export async function switchRetiredModel(deps, catalogue, request) {
|
|
|
103
105
|
}
|
|
104
106
|
}
|
|
105
107
|
function switchTemplate(deps, catalogue, request, templateId) {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
108
|
+
const template = templateById(deps.db, templateId);
|
|
109
|
+
if (template === undefined)
|
|
110
|
+
return { ok: false, message: changedMeanwhile };
|
|
111
|
+
try {
|
|
112
|
+
return transact(deps.db, () => switchTemplateIn(deps, catalogue, request, template));
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
if (!(error instanceof SwitchRefused))
|
|
116
|
+
throw error;
|
|
117
|
+
return {
|
|
118
|
+
ok: false,
|
|
119
|
+
message: error.reason === "missing-prompt"
|
|
120
|
+
? `The template "${template.name}" uses a prompt or intro/outro that was deleted, so it cannot be saved. Open it in Templates → Edit template, choose another, and save.`
|
|
121
|
+
: changedMeanwhile,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
// A refused save inside the switch's transaction: thrown so the carried version written before
|
|
126
|
+
// it is rolled back with it.
|
|
127
|
+
class SwitchRefused extends Error {
|
|
128
|
+
reason;
|
|
129
|
+
constructor(reason) {
|
|
130
|
+
super(reason);
|
|
131
|
+
this.reason = reason;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
function switchTemplateIn(deps, catalogue, request, template) {
|
|
135
|
+
const form = switchForm(template.document.form, catalogue, request);
|
|
136
|
+
// The version schedules run, when it isn't the head (an unchecked edit waits on Mark ready).
|
|
137
|
+
const runs = templateGate(deps.db, template.id)?.runs ?? null;
|
|
138
|
+
const running = runs === null || runs === template.version
|
|
139
|
+
? undefined
|
|
140
|
+
: templateById(deps.db, template.id, runs);
|
|
141
|
+
const runningForm = running === undefined ? undefined : switchForm(running.document.form, catalogue, request);
|
|
142
|
+
if (form === undefined && runningForm === undefined)
|
|
143
|
+
return { ok: true, changed: false };
|
|
144
|
+
let base = template.version;
|
|
145
|
+
if (running !== undefined && runningForm !== undefined) {
|
|
146
|
+
// The version that runs, switched, carried from it: schedules never keep running a
|
|
147
|
+
// retired model while the person's newer edit waits to be marked ready.
|
|
148
|
+
const carried = updateTemplate(deps, {
|
|
114
149
|
id: template.id,
|
|
115
|
-
name:
|
|
116
|
-
document: { ...
|
|
117
|
-
baseVersion:
|
|
150
|
+
name: running.name,
|
|
151
|
+
document: { ...running.document, form: runningForm },
|
|
152
|
+
baseVersion: base,
|
|
118
153
|
mutationId: deps.uuid(),
|
|
119
154
|
});
|
|
120
|
-
if (!
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
155
|
+
if (!carried.ok)
|
|
156
|
+
throw new SwitchRefused(carried.reason);
|
|
157
|
+
carryGateOnto(deps.db, template.id, running.version, carried.value.version);
|
|
158
|
+
base = carried.value.version;
|
|
159
|
+
}
|
|
160
|
+
// The head stays the person's newest work: switched too when it picks the model, and
|
|
161
|
+
// written again above the carried version so it is still the newest one.
|
|
162
|
+
const saved = updateTemplate(deps, {
|
|
163
|
+
id: template.id,
|
|
164
|
+
name: template.name,
|
|
165
|
+
document: { ...template.document, form: form ?? template.document.form },
|
|
166
|
+
baseVersion: base,
|
|
167
|
+
mutationId: deps.uuid(),
|
|
131
168
|
});
|
|
169
|
+
if (!saved.ok)
|
|
170
|
+
throw new SwitchRefused(saved.reason);
|
|
171
|
+
// Slopify's own change: a schedule running the version it came from keeps running.
|
|
172
|
+
carryGateOnto(deps.db, template.id, template.version, saved.value.version);
|
|
173
|
+
deps.db
|
|
174
|
+
.prepare("UPDATE schedules SET template_version=?,version=version+1,updated_at=? WHERE template_id=? AND template_version=? AND deleted_at IS NULL AND status IN ('active','paused')")
|
|
175
|
+
.run(saved.value.version, deps.clock.now().toISOString(), template.id, template.version);
|
|
176
|
+
return { ok: true, changed: true };
|
|
132
177
|
}
|
|
133
178
|
function switchDraft(deps, catalogue, request) {
|
|
134
179
|
const row = draftRow(deps.db, request.id);
|
|
@@ -185,16 +230,16 @@ async function switchProject(deps, catalogue, request) {
|
|
|
185
230
|
? " because the project changed meanwhile"
|
|
186
231
|
: "fields" in saved && saved.fields?.[0] !== undefined
|
|
187
232
|
? ` (${saved.fields[0].message})`
|
|
188
|
-
: ""}. Open the project
|
|
233
|
+
: ""}. Open the project and change it in Edit settings.`,
|
|
189
234
|
};
|
|
190
235
|
}
|
|
191
236
|
// "Switch all": every listed use that has a suggestion and no reason to hold back, one by one.
|
|
192
|
-
export async function switchAllRetired(deps, catalogue) {
|
|
237
|
+
export async function switchAllRetired(deps, catalogue, lifecycle) {
|
|
193
238
|
let switched = 0;
|
|
194
239
|
const failed = [];
|
|
195
240
|
// Templates first: switching one also moves the schedules that follow it.
|
|
196
241
|
const order = ["template", "schedule", "draft", "project"];
|
|
197
|
-
const usages = [...retiredModelUsage(deps.db, catalogue)].sort((a, b) => order.indexOf(a.kind) - order.indexOf(b.kind));
|
|
242
|
+
const usages = [...retiredModelUsage(deps.db, catalogue, lifecycle)].sort((a, b) => order.indexOf(a.kind) - order.indexOf(b.kind));
|
|
198
243
|
for (const usage of usages) {
|
|
199
244
|
if (usage.blocked !== null || usage.replacement === null)
|
|
200
245
|
continue;
|
|
@@ -1,16 +1,29 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
import { lifecycleReplacement } from "../../catalog/lifecycle.js";
|
|
2
3
|
import { isVideoModel } from "../../catalog/schema.js";
|
|
3
4
|
import { listProjects, stagesOf } from "../admission/repo.js";
|
|
4
5
|
import { draftRows } from "../play-drafts/repo.js";
|
|
5
6
|
import { documentOf } from "../play-drafts/service.js";
|
|
6
7
|
import { templateById } from "../project-templates/repo.js";
|
|
7
8
|
import { currentRevisionId, revisionById } from "../revisions/repo.js";
|
|
8
|
-
import { isUncataloguedProvider } from "../settings/model.js";
|
|
9
|
+
import { isSampleStandIn, isUncataloguedProvider } from "../settings/model.js";
|
|
10
|
+
import { runnableTemplate } from "../template-studio/schedule-gate.js";
|
|
9
11
|
import { usageSlots } from "./model.js";
|
|
10
12
|
export { slotLabels, usageKinds, usageSlots } from "./model.js";
|
|
11
13
|
function familyOf(slot) {
|
|
12
14
|
return slot === "llm" ? "llm" : slot === "audio" ? "tts" : "image";
|
|
13
15
|
}
|
|
16
|
+
// A Create draft's name as Create's header says it: its title once every keyword in it is
|
|
17
|
+
// filled, else "Untitled draft". Never a raw {{Topic}}.
|
|
18
|
+
function draftName(title, values) {
|
|
19
|
+
const filled = title
|
|
20
|
+
.replace(/\{\{\s*([^{}]+?)\s*\}\}/g, (keyword, name) => {
|
|
21
|
+
const value = values[name]?.trim() ?? "";
|
|
22
|
+
return value === "" ? keyword : value;
|
|
23
|
+
})
|
|
24
|
+
.trim();
|
|
25
|
+
return filled === "" || filled.includes("{{") ? "Untitled draft" : filled;
|
|
26
|
+
}
|
|
14
27
|
// The model choices a Play form (a draft or a template) makes.
|
|
15
28
|
export function formChoices(form) {
|
|
16
29
|
const edit = form.videoEdit;
|
|
@@ -36,11 +49,13 @@ export function configChoices(config) {
|
|
|
36
49
|
};
|
|
37
50
|
}
|
|
38
51
|
// Whether a choice names a catalogued model that is no longer offered. Command-line tools
|
|
39
|
-
// list their own models and are checked by the health check instead
|
|
52
|
+
// list their own models and are checked by the health check instead; the samples' stand-ins
|
|
53
|
+
// were never catalogued.
|
|
40
54
|
export function retiredStatus(catalogue, slot, choice) {
|
|
41
55
|
if (choice.provider === "" ||
|
|
42
56
|
choice.model.trim() === "" ||
|
|
43
|
-
isUncataloguedProvider(choice.provider)
|
|
57
|
+
isUncataloguedProvider(choice.provider) ||
|
|
58
|
+
isSampleStandIn(choice.provider))
|
|
44
59
|
return null;
|
|
45
60
|
const row = catalogue[familyOf(slot)].find((model) => model.provider === choice.provider &&
|
|
46
61
|
model.id === choice.model &&
|
|
@@ -51,9 +66,17 @@ export function retiredStatus(catalogue, slot, choice) {
|
|
|
51
66
|
return "retired";
|
|
52
67
|
return row.enabled ? null : "unlisted";
|
|
53
68
|
}
|
|
54
|
-
// The
|
|
55
|
-
//
|
|
56
|
-
|
|
69
|
+
// The replacement models-lifecycle.yaml names, when it is live; else the closest active model
|
|
70
|
+
// from the same provider and list: the one sharing the longest start of its ID (a newer
|
|
71
|
+
// version of the same line), the catalogue's order breaking ties.
|
|
72
|
+
export function suggestReplacement(catalogue, slot, choice, lifecycle) {
|
|
73
|
+
const named = lifecycleReplacement(lifecycle, catalogue, {
|
|
74
|
+
family: familyOf(slot),
|
|
75
|
+
provider: choice.provider,
|
|
76
|
+
model: choice.model,
|
|
77
|
+
});
|
|
78
|
+
if (named !== undefined && named.id !== choice.model)
|
|
79
|
+
return named;
|
|
57
80
|
let best = null;
|
|
58
81
|
for (const row of catalogue[familyOf(slot)]) {
|
|
59
82
|
if (row.provider !== choice.provider ||
|
|
@@ -74,7 +97,7 @@ function sharedStart(a, b) {
|
|
|
74
97
|
index++;
|
|
75
98
|
return index;
|
|
76
99
|
}
|
|
77
|
-
function usagesOf(catalogue, base, choices, blocked) {
|
|
100
|
+
function usagesOf(catalogue, base, choices, blocked, lifecycle) {
|
|
78
101
|
const found = [];
|
|
79
102
|
for (const slot of usageSlots) {
|
|
80
103
|
const choice = choices[slot];
|
|
@@ -83,7 +106,7 @@ function usagesOf(catalogue, base, choices, blocked) {
|
|
|
83
106
|
const why = retiredStatus(catalogue, slot, choice);
|
|
84
107
|
if (why === null)
|
|
85
108
|
continue;
|
|
86
|
-
const replacement = suggestReplacement(catalogue, slot, choice);
|
|
109
|
+
const replacement = suggestReplacement(catalogue, slot, choice, lifecycle);
|
|
87
110
|
found.push({
|
|
88
111
|
...base,
|
|
89
112
|
key: `${base.kind}:${base.id}:${slot}`,
|
|
@@ -128,7 +151,10 @@ export function choiceSites(db) {
|
|
|
128
151
|
.prepare("SELECT id,name,template_id,template_version FROM schedules WHERE deleted_at IS NULL AND status IN ('active','paused') ORDER BY lower(name),id")
|
|
129
152
|
.all()) {
|
|
130
153
|
const row = scheduleRow.parse(raw);
|
|
131
|
-
|
|
154
|
+
// What the schedule actually runs (`template-studio/schedule-gate.ts`): with an unchecked
|
|
155
|
+
// head that is an older ready version, whose models are the ones its runs use.
|
|
156
|
+
const template = runnableTemplate(db, row.template_id) ??
|
|
157
|
+
templateById(db, row.template_id, row.template_version);
|
|
132
158
|
if (template === undefined)
|
|
133
159
|
continue;
|
|
134
160
|
const head = heads.get(row.template_id) ??
|
|
@@ -140,7 +166,7 @@ export function choiceSites(db) {
|
|
|
140
166
|
choices: formChoices(template.document.form),
|
|
141
167
|
blocked: head === row.template_version
|
|
142
168
|
? null
|
|
143
|
-
: `This schedule runs an older version of the template "${template.name}". In
|
|
169
|
+
: `This schedule runs an older version of the template "${template.name}". In Calendar → Schedules, choose Edit, pick the template again so it runs the latest version, then save.`,
|
|
144
170
|
});
|
|
145
171
|
}
|
|
146
172
|
for (const row of draftRows(db)) {
|
|
@@ -152,7 +178,7 @@ export function choiceSites(db) {
|
|
|
152
178
|
sites.push({
|
|
153
179
|
kind: "draft",
|
|
154
180
|
id: row.id,
|
|
155
|
-
name: row.title.
|
|
181
|
+
name: draftName(row.title, document.form.values),
|
|
156
182
|
choices: formChoices(document.form),
|
|
157
183
|
blocked: null,
|
|
158
184
|
});
|
|
@@ -180,6 +206,6 @@ export function choiceSites(db) {
|
|
|
180
206
|
}
|
|
181
207
|
// Every template, schedule, draft and unfinished project that still picks a retired or
|
|
182
208
|
// unlisted model, with the suggested replacement. Nothing is changed here.
|
|
183
|
-
export function retiredModelUsage(db, catalogue) {
|
|
184
|
-
return choiceSites(db).flatMap((site) => usagesOf(catalogue, { kind: site.kind, id: site.id, name: site.name }, site.choices, site.blocked));
|
|
209
|
+
export function retiredModelUsage(db, catalogue, lifecycle) {
|
|
210
|
+
return choiceSites(db).flatMap((site) => usagesOf(catalogue, { kind: site.kind, id: site.id, name: site.name }, site.choices, site.blocked, lifecycle));
|
|
185
211
|
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { mkdirSync, rmSync } from "node:fs";
|
|
2
2
|
import { open, stat } from "node:fs/promises";
|
|
3
3
|
import { join } from "node:path";
|
|
4
|
+
import { errorText } from "../../kernel/errors.js";
|
|
5
|
+
import { editSettings } from "../../kernel/ports/settings-places.js";
|
|
4
6
|
import { runFfmpeg } from "../video/ffmpeg.js";
|
|
5
7
|
import { breathRate, scanBreaths, softenChunk } from "./breaths-detect.js";
|
|
6
8
|
// Soften breaths, made in the join (`breaths-model.ts` says why there). Each narration piece is
|
|
@@ -38,7 +40,7 @@ export async function softenBreaths(run, files, directory) {
|
|
|
38
40
|
catch (error) {
|
|
39
41
|
if (run.signal.aborted)
|
|
40
42
|
throw error;
|
|
41
|
-
throw new Error(`Soften breaths could not process narration piece ${String(index + 1)} (${
|
|
43
|
+
throw new Error(`Soften breaths could not process narration piece ${String(index + 1)} (${errorText(error)}), so the narration can't be joined together. Use Try again; if it fails again, turn off Soften breaths in ${editSettings.sound} and use Save changes, then use Download diagnostics in Settings and report it.`, { cause: error });
|
|
42
44
|
}
|
|
43
45
|
finally {
|
|
44
46
|
rmSync(raw, { force: true });
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { mkdirSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
|
+
import { errorText } from "../../kernel/errors.js";
|
|
4
|
+
import { editSettings } from "../../kernel/ports/settings-places.js";
|
|
3
5
|
import { runFfmpeg } from "../video/ffmpeg.js";
|
|
4
6
|
import { softenBreaths } from "./breaths.js";
|
|
5
7
|
import { deEsser } from "./breaths-model.js";
|
|
@@ -36,7 +38,7 @@ export async function deEssPieces(run, files, directory) {
|
|
|
36
38
|
catch (error) {
|
|
37
39
|
if (run.signal.aborted)
|
|
38
40
|
throw error;
|
|
39
|
-
throw new Error(`Soften S sounds could not process narration piece ${String(index + 1)} (${
|
|
41
|
+
throw new Error(`Soften S sounds could not process narration piece ${String(index + 1)} (${errorText(error)}), so the narration can't be joined together. Use Try again; if it fails again, turn off Soften S sounds in ${editSettings.sound} and use Save changes, then use Download diagnostics in Settings and report it.`, { cause: error });
|
|
40
42
|
}
|
|
41
43
|
written.push(output);
|
|
42
44
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { copyFileSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { dirname } from "node:path";
|
|
3
|
+
import { internalError } from "../../kernel/errors.js";
|
|
3
4
|
import { probeDurationMs, runFfmpeg } from "../video/ffmpeg.js";
|
|
4
5
|
// The concat demuxer's script format. A path is single-quoted, and the one character that
|
|
5
6
|
// can end the quoting is spelled out, so a folder with an apostrophe in it cannot become
|
|
@@ -46,7 +47,7 @@ export async function joinNarration(deps, input) {
|
|
|
46
47
|
const first = input.files[0];
|
|
47
48
|
if (first === undefined) {
|
|
48
49
|
// The stage refuses an empty narration before it gets here, so this is a bug.
|
|
49
|
-
throw new Error("
|
|
50
|
+
throw new Error(internalError("there is no narration audio to join"));
|
|
50
51
|
}
|
|
51
52
|
mkdirSync(dirname(input.output), { recursive: true, mode: 0o700 });
|
|
52
53
|
if (input.files.length === 1 && input.reencode !== true) {
|
|
@@ -9,9 +9,10 @@
|
|
|
9
9
|
// A paragraph's minimum is separate and 0 (the sentence minimum only) unless set: the pause
|
|
10
10
|
// between paragraphs is mostly the narration prompt's and the voice's to make.
|
|
11
11
|
//
|
|
12
|
-
// Browser-safe:
|
|
12
|
+
// Browser-safe: Create and Edit settings read these limits. A run without either has neither on
|
|
13
13
|
// its config, which is what every project saved before them was, and the joins keep their
|
|
14
14
|
// fingerprints then.
|
|
15
|
+
import { createRows, editSettings } from "../../kernel/ports/settings-places.js";
|
|
15
16
|
// ceiling: a quarter second reads brisk, 0.35 to 0.45 natural or documentary, 0.5 to 0.8 an
|
|
16
17
|
// audiobook's relaxed pace, and above 0.8 sleep content; beyond 2 s it stops sounding like a
|
|
17
18
|
// pause between sentences.
|
|
@@ -33,7 +34,7 @@ export function pauseProblem(value, name) {
|
|
|
33
34
|
value <= pauseSecondsMax &&
|
|
34
35
|
Math.abs(steps - Math.round(steps)) < 1e-6
|
|
35
36
|
? undefined
|
|
36
|
-
: `The pause between ${name} must be between 0 and ${String(pauseSecondsMax)} seconds, in steps of ${String(pauseSecondsStep)}. Change it under
|
|
37
|
+
: `The pause between ${name} must be between 0 and ${String(pauseSecondsMax)} seconds, in steps of ${String(pauseSecondsStep)}. Change it under ${createRows.video}, or ${editSettings.sound}.`;
|
|
37
38
|
}
|
|
38
39
|
export function pauseFields(config) {
|
|
39
40
|
const fields = [];
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { execFile } from "node:child_process";
|
|
2
|
+
import { isDonePiece, readyOutput } from "../revisions/view.js";
|
|
2
3
|
// The live view's narration waveform: each finished narration piece as a row of peaks, in the
|
|
3
4
|
// order it is spoken, growing as pieces land. Once the whole narration is joined (or was
|
|
4
5
|
// uploaded) that one file replaces the pieces.
|
|
@@ -12,7 +13,7 @@ const decodeMaxBytes = 3 * 3600 * decodeRate * 2;
|
|
|
12
13
|
// The saved narration audio of a revision, in spoken order: the joined narration when it is
|
|
13
14
|
// ready, else each finished request of the intro, the body and the outro.
|
|
14
15
|
export function narrationAudio(view) {
|
|
15
|
-
const joined = view
|
|
16
|
+
const joined = readyOutput(view, { role: "audio_body" });
|
|
16
17
|
if (joined !== undefined)
|
|
17
18
|
return {
|
|
18
19
|
complete: true,
|
|
@@ -22,10 +23,8 @@ export function narrationAudio(view) {
|
|
|
22
23
|
return {
|
|
23
24
|
complete: false,
|
|
24
25
|
pieces: view.pieces
|
|
25
|
-
.filter((row) => row
|
|
26
|
-
row.available &&
|
|
26
|
+
.filter((row) => isDonePiece(row) &&
|
|
27
27
|
row.stageKind === "audio" &&
|
|
28
|
-
row.piece.state === "done" &&
|
|
29
28
|
row.assetId !== null &&
|
|
30
29
|
row.piece.payload !== null &&
|
|
31
30
|
spoken(row.piece.payload))
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { internalError } from "../../kernel/errors.js";
|
|
1
2
|
import { fingerprint } from "../../kernel/runner/work.js";
|
|
2
3
|
import { anchoredChunks, defaultChunkCharacters, defaultChunkWords, } from "./chunk.js";
|
|
3
4
|
import { pronunciationMatches } from "./pronunciation.js";
|
|
@@ -32,7 +33,7 @@ export function pronunciationChunks(source, chunking, entries, overriddenKeys =
|
|
|
32
33
|
const chunks = narrationChunkTexts(source, chunking, anchors).map((text) => {
|
|
33
34
|
const start = source.indexOf(text, offset);
|
|
34
35
|
if (start < 0)
|
|
35
|
-
throw new Error("
|
|
36
|
+
throw new Error(internalError("a narration chunk isn't in the article text"));
|
|
36
37
|
offset = start + text.length;
|
|
37
38
|
return { key: nextKey(text), text, start, end: offset };
|
|
38
39
|
});
|
|
@@ -85,7 +86,7 @@ export function pronunciationChunks(source, chunking, entries, overriddenKeys =
|
|
|
85
86
|
}
|
|
86
87
|
const chunk = chunks[index];
|
|
87
88
|
if (chunk === undefined)
|
|
88
|
-
throw new Error("
|
|
89
|
+
throw new Error(internalError("a narration chunk went missing"));
|
|
89
90
|
while ((matches[matchIndex]?.end ?? Infinity) <= chunk.end)
|
|
90
91
|
matchIndex++;
|
|
91
92
|
const match = matches[matchIndex];
|
|
@@ -97,7 +98,7 @@ export function pronunciationChunks(source, chunking, entries, overriddenKeys =
|
|
|
97
98
|
continue;
|
|
98
99
|
const first = chunks[from];
|
|
99
100
|
if (first === undefined)
|
|
100
|
-
throw new Error("
|
|
101
|
+
throw new Error(internalError("a group of narration chunks is empty"));
|
|
101
102
|
const text = source.slice(first.start, chunk.end);
|
|
102
103
|
result.push(from === index
|
|
103
104
|
? { key: chunk.key, text }
|