@gentbajko/slopify 2.5.0 → 3.0.1
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/LICENSE +201 -21
- package/NOTICE +12 -0
- package/README.md +24 -41
- package/SUBTITLES.md +1 -1
- package/dist/adapter-registry.js +31 -0
- package/dist/adapters/alignment/cache.js +4 -1
- package/dist/adapters/alignment/ctc.js +25 -23
- package/dist/adapters/alignment/index.js +37 -6
- package/dist/adapters/alignment/multilingual.js +267 -0
- package/dist/adapters/alignment/protocol.js +11 -0
- package/dist/adapters/alignment/quality.js +4 -3
- package/dist/adapters/alignment/sentences.js +95 -0
- package/dist/adapters/alignment/spec.js +24 -0
- package/dist/adapters/alignment/spell.js +769 -0
- package/dist/adapters/alignment/text.js +56 -9
- package/dist/adapters/alignment/window.js +34 -30
- package/dist/adapters/alignment/worker.js +23 -21
- package/dist/adapters/explain.js +11 -11
- package/dist/adapters/host-cli/index.js +44 -5
- package/dist/adapters/host-cli/transport.js +7 -5
- package/dist/adapters/image/bytes.js +2 -2
- package/dist/adapters/image/codex-output.js +1 -1
- package/dist/adapters/image/codex.js +87 -22
- package/dist/adapters/image/fal.js +13 -5
- package/dist/adapters/image/google.js +11 -8
- package/dist/adapters/image/openai.js +14 -7
- package/dist/adapters/image/reference.js +34 -0
- package/dist/adapters/image/replicate.js +7 -2
- package/dist/adapters/image/video.js +2 -2
- package/dist/adapters/key-probes.js +85 -0
- package/dist/adapters/llm/claude-code.js +168 -32
- package/dist/adapters/llm/cli-login-error.js +1 -1
- package/dist/adapters/llm/codex-limits.js +157 -0
- package/dist/adapters/llm/codex.js +99 -12
- package/dist/adapters/llm/document-workspace.js +2 -2
- package/dist/adapters/llm/gemini-workspace.js +1 -1
- package/dist/adapters/llm/gemini.js +16 -3
- package/dist/adapters/llm/image-workspace.js +58 -0
- package/dist/adapters/llm/openrouter.js +11 -3
- package/dist/adapters/llm/run-cli.js +12 -7
- package/dist/adapters/tts/cartesia.js +10 -0
- package/dist/adapters/tts/elevenlabs.js +31 -9
- package/dist/adapters/tts/gemini.js +206 -0
- package/dist/adapters/tts/inworld-async.js +9 -5
- package/dist/adapters/tts/inworld.js +17 -3
- package/dist/adapters/tts/openai.js +3 -0
- package/dist/adapters/tts/pcm-mp3.js +62 -0
- package/dist/adapters/tts/system.js +147 -0
- package/dist/adapters/tts/voice-languages.js +80 -0
- package/dist/assets/fonts/noto/NotoSans-Regular.ttf +0 -0
- package/dist/assets/fonts/noto/NotoSansArabic-Regular.ttf +0 -0
- package/dist/assets/fonts/noto/NotoSansDevanagari-Regular.ttf +0 -0
- package/dist/assets/fonts/noto/NotoSansHebrew-Regular.ttf +0 -0
- package/dist/assets/fonts/noto/NotoSansThai-Regular.ttf +0 -0
- package/dist/assets/fonts/noto/OFL.txt +93 -0
- package/dist/assets/fonts/noto/SOURCE.txt +18 -0
- package/dist/assets/models.yaml +38 -0
- package/dist/assets/sample/sample-audiobook.tar +0 -0
- package/dist/assets/sample/sample-podcast.tar +0 -0
- package/dist/assets/sample/sample-project.tar +0 -0
- package/dist/assets/style-preview/narration.mp3 +0 -0
- package/dist/assets/style-preview/tall-1.jpg +0 -0
- package/dist/assets/style-preview/tall-2.jpg +0 -0
- package/dist/assets/style-preview/tall-3.jpg +0 -0
- package/dist/assets/style-preview/wide-1.jpg +0 -0
- package/dist/assets/style-preview/wide-2.jpg +0 -0
- package/dist/assets/style-preview/wide-3.jpg +0 -0
- package/dist/catalog/merge.js +132 -0
- package/dist/catalog/registry.js +17 -14
- package/dist/catalog/schema.js +2 -0
- package/dist/catalog/store.js +147 -8
- package/dist/catalog/validate.js +2 -2
- package/dist/compose.yaml +71 -0
- package/dist/edge/autostart/docker-record.js +32 -0
- package/dist/edge/autostart/docker.js +118 -0
- package/dist/edge/autostart/index.js +78 -0
- package/dist/edge/autostart/launcher.js +176 -0
- package/dist/edge/autostart/model.js +3 -0
- package/dist/edge/autostart/native.js +210 -0
- package/dist/edge/autostart/prompt.js +72 -0
- package/dist/edge/autostart/service.js +90 -0
- package/dist/edge/cli-args.js +71 -0
- package/dist/edge/cli.js +64 -63
- package/dist/edge/docker-install/activation.js +56 -0
- package/dist/edge/docker-install/apply.js +458 -0
- package/dist/edge/docker-install/engine.js +362 -0
- package/dist/edge/docker-install/run.js +160 -0
- package/dist/edge/docker-install/state.js +146 -0
- package/dist/edge/{docker-projects → docker-install}/volume.js +1 -5
- package/dist/edge/docker.js +14 -22
- package/dist/edge/events/hub.js +3 -1
- package/dist/edge/host-cli.js +1 -1
- package/dist/edge/http/actions.js +38 -11
- package/dist/edge/http/app.js +60 -2
- package/dist/edge/http/auditions.js +70 -0
- package/dist/edge/http/autostart.js +37 -0
- package/dist/edge/http/byte-range.js +42 -0
- package/dist/edge/http/channel-memory.js +92 -0
- package/dist/edge/http/channels.js +128 -0
- package/dist/edge/http/diagnostics.js +1 -0
- package/dist/edge/http/draft-files.js +2 -4
- package/dist/edge/http/entries.js +22 -3
- package/dist/edge/http/files.js +11 -7
- package/dist/edge/http/folder-location.js +1 -1
- package/dist/edge/http/home.js +39 -0
- package/dist/edge/http/host-cli.js +29 -5
- package/dist/edge/http/narration-peaks.js +76 -0
- package/dist/edge/http/onboarding.js +212 -0
- package/dist/edge/http/open-folder.js +1 -1
- package/dist/edge/http/patch-notes.js +45 -0
- package/dist/edge/http/planning.js +4 -2
- package/dist/edge/http/project-create.js +87 -0
- package/dist/edge/http/project-templates.js +19 -2
- package/dist/edge/http/projects.js +37 -100
- package/dist/edge/http/prompts.js +40 -3
- package/dist/edge/http/pronunciations.js +23 -4
- package/dist/edge/http/providers.js +119 -3
- package/dist/edge/http/reviews.js +131 -0
- package/dist/edge/http/revision-files.js +3 -5
- package/dist/edge/http/revisions.js +1 -1
- package/dist/edge/http/run-cost.js +25 -0
- package/dist/edge/http/schedules.js +115 -6
- package/dist/edge/http/settings.js +84 -6
- package/dist/edge/http/storage-files.js +50 -0
- package/dist/edge/http/storage.js +43 -2
- package/dist/edge/http/studio.js +287 -0
- package/dist/edge/http/style-preview.js +61 -0
- package/dist/edge/http/subtitles.js +1 -1
- package/dist/edge/http/trash.js +69 -0
- package/dist/edge/http/tutorials.js +59 -0
- package/dist/edge/http/update.js +24 -3
- package/dist/edge/http/whats-new.js +15 -0
- package/dist/edge/http/youtube-edits.js +92 -0
- package/dist/edge/native-update.js +62 -0
- package/dist/extension/slopify-studio-chrome.zip +0 -0
- package/dist/extension/slopify-studio-firefox.zip +0 -0
- package/dist/host-cli/gemini-login.js +83 -0
- package/dist/host-cli/open-folder.js +10 -10
- package/dist/host-cli/runtime.js +9 -1
- package/dist/host-cli/status.js +4 -2
- package/dist/kernel/db/migrations/0025-automatic-reviews.sql +40 -0
- package/dist/kernel/db/migrations/0026-schedule-topic-generation.sql +23 -0
- package/dist/kernel/db/migrations/0027-run-cost.sql +58 -0
- package/dist/kernel/db/migrations/0030-automatic-retries.sql +18 -0
- package/dist/kernel/db/migrations/0031-prompt-history-and-description-edits.sql +33 -0
- package/dist/kernel/db/migrations/0032-channels.sql +65 -0
- package/dist/kernel/db/migrations/0034-script-prompts.sql +23 -0
- package/dist/kernel/db/migrations/0035-narration-aliases.sql +13 -0
- package/dist/kernel/db/migrations/0037-project-uploads.sql +8 -0
- package/dist/kernel/db/migrations/0038-voice-languages.sql +7 -0
- package/dist/kernel/db/migrations/0039-channel-essentials.sql +64 -0
- package/dist/kernel/db/migrations/0040-standalone-usage.sql +35 -0
- package/dist/kernel/db/migrations/0041-cast-hosts.sql +3 -0
- package/dist/kernel/paths.js +27 -6
- package/dist/kernel/pipeline.js +4 -1
- package/dist/kernel/ports/host-cli.js +122 -14
- package/dist/kernel/ports/key-probe.js +1 -0
- package/dist/kernel/ports/languages.js +157 -0
- package/dist/kernel/ports/model.js +10 -5
- package/dist/kernel/ports/narration-aliases.js +60 -0
- package/dist/kernel/ports/plan-limits.js +36 -0
- package/dist/kernel/ports/system-speech.js +203 -0
- package/dist/kernel/runner/attempt.js +17 -8
- package/dist/kernel/runner/audition.js +36 -0
- package/dist/kernel/runner/graph.js +40 -5
- package/dist/kernel/runner/index.js +39 -9
- package/dist/kernel/runner/meter.js +1 -0
- package/dist/kernel/runner/providers.js +142 -7
- package/dist/kernel/runner/retry-policy.js +43 -0
- package/dist/kernel/runner/standalone.js +134 -0
- package/dist/kernel/runner/work-authority.js +28 -2
- package/dist/main.js +277 -16
- package/dist/model-catalog.js +2 -0
- package/dist/patch-notes/0.4.2-to-1.0.md +93 -0
- package/dist/patch-notes/1.0-to-2.0.md +74 -0
- package/dist/patch-notes/2.0-to-3.0.md +257 -0
- package/dist/patch-notes/3.0.0.md +70 -0
- package/dist/patch-notes/3.0.1.md +105 -0
- package/dist/patch-notes/index.json +32 -0
- package/dist/slices/admission/model.js +27 -0
- package/dist/slices/admission/repo.js +24 -4
- package/dist/slices/admission/rules.js +80 -2
- package/dist/slices/admission/schema.js +58 -1
- package/dist/slices/admission/short-mode.js +47 -0
- package/dist/slices/admission/start.js +42 -6
- package/dist/slices/article/continuation.js +2 -2
- package/dist/slices/article/provided-entries.js +2 -2
- package/dist/slices/article/run.js +6 -2
- package/dist/slices/article/segments.js +3 -3
- package/dist/slices/backups/folder.js +14 -6
- package/dist/slices/batch/index.js +7 -2
- package/dist/slices/cancel/index.js +1 -1
- package/dist/slices/channels/cast-images.js +110 -0
- package/dist/slices/channels/cast-match.js +32 -0
- package/dist/slices/channels/images.js +19 -0
- package/dist/slices/channels/model.js +5 -0
- package/dist/slices/channels/rebrand.js +100 -0
- package/dist/slices/channels/repo.js +221 -0
- package/dist/slices/channels/runs.js +129 -0
- package/dist/slices/channels/schema.js +152 -0
- package/dist/slices/channels/service.js +180 -0
- package/dist/slices/channels/studio-csv.js +110 -0
- package/dist/slices/channels/videos.js +120 -0
- package/dist/slices/checkpoints/recovery.js +10 -0
- package/dist/slices/control/index.js +5 -2
- package/dist/slices/control/providers.js +4 -1
- package/dist/slices/document/fonts.js +1 -1
- package/dist/slices/document/render.js +1 -1
- package/dist/slices/episodes/related.js +90 -0
- package/dist/slices/episodes/repo.js +60 -0
- package/dist/slices/episodes/service.js +58 -0
- package/dist/slices/episodes/summarize.js +170 -0
- package/dist/slices/estimate/index.js +109 -28
- package/dist/slices/estimate/requests.js +68 -2
- package/dist/slices/eta/history.js +56 -0
- package/dist/slices/eta/model.js +63 -0
- package/dist/slices/eta/view.js +25 -0
- package/dist/slices/fixes/rules.js +73 -0
- package/dist/slices/fonts/coverage.js +82 -0
- package/dist/slices/fonts/sfnt.js +74 -0
- package/dist/slices/images/run.js +8 -5
- package/dist/slices/images/scale.js +84 -0
- package/dist/slices/library/diff.js +122 -0
- package/dist/slices/library/history.js +100 -0
- package/dist/slices/library/model.js +3 -0
- package/dist/slices/library/photorealistic.js +49 -0
- package/dist/slices/library/repo.js +19 -14
- package/dist/slices/library/save.js +62 -12
- package/dist/slices/library/slots.js +7 -1
- package/dist/slices/library/used-by.js +153 -0
- package/dist/slices/loudness/level-pieces.js +41 -0
- package/dist/slices/loudness/loudnorm.js +164 -0
- package/dist/slices/loudness/model.js +153 -0
- package/dist/slices/model-upkeep/model.js +10 -0
- package/dist/slices/model-upkeep/switch.js +217 -0
- package/dist/slices/model-upkeep/usage.js +185 -0
- package/dist/slices/narration/aliases-library.js +31 -0
- package/dist/slices/narration/aliases-schema.js +53 -0
- package/dist/slices/narration/aliases.js +49 -0
- package/dist/slices/narration/blocks.js +352 -0
- package/dist/slices/narration/chunk.js +19 -7
- package/dist/slices/narration/concat.js +2 -2
- package/dist/slices/narration/describe.js +45 -0
- package/dist/slices/narration/pauses-model.js +63 -0
- package/dist/slices/narration/pauses.js +269 -0
- package/dist/slices/narration/peaks-model.js +1 -0
- package/dist/slices/narration/peaks.js +94 -0
- package/dist/slices/narration/preparation.js +21 -3
- package/dist/slices/narration/pronunciation-chunks.js +3 -3
- package/dist/slices/narration/pronunciation.js +72 -25
- package/dist/slices/narration/run.js +6 -6
- package/dist/slices/narration/shared-glossary.js +1 -1
- package/dist/slices/narration/steering.js +15 -4
- package/dist/slices/notifications/notifier.js +47 -3
- package/dist/slices/notifications/rules.js +48 -3
- package/dist/slices/onboarding/copy.js +143 -0
- package/dist/slices/onboarding/first-run.js +72 -0
- package/dist/slices/onboarding/full-video.js +81 -0
- package/dist/slices/onboarding/install.js +119 -0
- package/dist/slices/onboarding/model.js +85 -0
- package/dist/slices/onboarding/packs.js +491 -0
- package/dist/slices/onboarding/quick-short.js +144 -0
- package/dist/slices/onboarding/sample.js +132 -0
- package/dist/slices/onboarding/state.js +68 -0
- package/dist/slices/onboarding/template.js +73 -0
- package/dist/slices/patch-notes/library.js +73 -0
- package/dist/slices/patch-notes/seen.js +77 -0
- package/dist/slices/play-drafts/convert.js +127 -8
- package/dist/slices/play-drafts/readiness.js +4 -1
- package/dist/slices/play-drafts/repo.js +2 -0
- package/dist/slices/play-drafts/review-inputs.js +20 -3
- package/dist/slices/play-drafts/schema.js +89 -0
- package/dist/slices/play-drafts/service.js +4 -1
- package/dist/slices/play-drafts/start.js +43 -18
- package/dist/slices/project-templates/from-project.js +59 -6
- package/dist/slices/project-templates/next-chapter.js +94 -0
- package/dist/slices/project-templates/one-off.js +26 -0
- package/dist/slices/project-templates/repo.js +2 -1
- package/dist/slices/project-templates/schema.js +7 -1
- package/dist/slices/project-templates/service.js +15 -4
- package/dist/slices/project-templates/setup.js +18 -2
- package/dist/slices/rebuild/admission-repo.js +1 -1
- package/dist/slices/rebuild/model.js +6 -0
- package/dist/slices/rebuild/preview-details.js +46 -3
- package/dist/slices/rebuild/preview-plan.js +13 -6
- package/dist/slices/rebuild/recipe-audio-parts.js +40 -7
- package/dist/slices/rebuild/recipe-audio.js +66 -12
- package/dist/slices/rebuild/recipe-build.js +8 -4
- package/dist/slices/rebuild/recipe-cast.js +18 -0
- package/dist/slices/rebuild/recipe-checkpoints.js +11 -9
- package/dist/slices/rebuild/recipe-describe.js +93 -0
- package/dist/slices/rebuild/recipe-edit.js +13 -1
- package/dist/slices/rebuild/recipe-exports.js +67 -8
- package/dist/slices/rebuild/recipe-input-schema.js +35 -0
- package/dist/slices/rebuild/recipe-legacy.js +9 -0
- package/dist/slices/rebuild/recipe-loudness.js +45 -0
- package/dist/slices/rebuild/recipe-model.js +25 -6
- package/dist/slices/rebuild/recipe-pauses.js +7 -0
- package/dist/slices/rebuild/recipe-preparation.js +3 -3
- package/dist/slices/rebuild/recipe-provider-choice.js +11 -1
- package/dist/slices/rebuild/recipe-reference.js +15 -1
- package/dist/slices/rebuild/recipe-reviews.js +117 -0
- package/dist/slices/rebuild/recipe-save.js +4 -1
- package/dist/slices/rebuild/recipe-shorts.js +23 -3
- package/dist/slices/rebuild/recipe-text.js +114 -19
- package/dist/slices/rebuild/recipe-validation.js +14 -2
- package/dist/slices/rebuild/recipe-visual.js +96 -33
- package/dist/slices/rebuild/recipe-voices.js +286 -0
- package/dist/slices/rebuild/recipe-work.js +77 -6
- package/dist/slices/rebuild/recipe-youtube.js +2 -0
- package/dist/slices/rebuild/recovery-conflict.js +7 -3
- package/dist/slices/rebuild/recovery-model.js +3 -0
- package/dist/slices/rebuild/recovery-selection.js +28 -2
- package/dist/slices/rebuild/recovery.js +35 -17
- package/dist/slices/rebuild/repo.js +3 -3
- package/dist/slices/rebuild/retry.js +18 -0
- package/dist/slices/rebuild/review-redo.js +125 -0
- package/dist/slices/rebuild/runtime-actions.js +5 -0
- package/dist/slices/rebuild/runtime-admission.js +4 -1
- package/dist/slices/rebuild/runtime-animate.js +4 -4
- package/dist/slices/rebuild/runtime-article.js +5 -5
- package/dist/slices/rebuild/runtime-document.js +4 -4
- package/dist/slices/rebuild/runtime-export-bed.js +43 -0
- package/dist/slices/rebuild/runtime-export-edit.js +70 -11
- package/dist/slices/rebuild/runtime-export-inputs.js +52 -10
- package/dist/slices/rebuild/runtime-export-short.js +85 -0
- package/dist/slices/rebuild/runtime-export.js +84 -19
- package/dist/slices/rebuild/runtime-figure-card.js +87 -0
- package/dist/slices/rebuild/runtime-image.js +21 -2
- package/dist/slices/rebuild/runtime-local.js +148 -24
- package/dist/slices/rebuild/runtime-materialize.js +8 -0
- package/dist/slices/rebuild/runtime-narration-reuse.js +2 -1
- package/dist/slices/rebuild/runtime-narration-text.js +7 -7
- package/dist/slices/rebuild/runtime-pictures.js +28 -0
- package/dist/slices/rebuild/runtime-piece-label.js +27 -0
- package/dist/slices/rebuild/runtime-provider.js +126 -18
- package/dist/slices/rebuild/runtime-publication.js +21 -5
- package/dist/slices/rebuild/runtime-review.js +267 -0
- package/dist/slices/rebuild/runtime-run.js +17 -11
- package/dist/slices/rebuild/runtime-shorts.js +44 -17
- package/dist/slices/rebuild/runtime-store.js +62 -11
- package/dist/slices/rebuild/runtime-subtitles.js +72 -19
- package/dist/slices/rebuild/runtime-voices.js +103 -0
- package/dist/slices/rebuild/runtime-youtube.js +7 -6
- package/dist/slices/rebuild/service-readiness.js +3 -3
- package/dist/slices/rebuild/soften.js +49 -0
- package/dist/slices/rebuild/transition-repo.js +9 -2
- package/dist/slices/research/run.js +4 -4
- package/dist/slices/research/synthesis.js +2 -2
- package/dist/slices/reviews/model.js +105 -0
- package/dist/slices/reviews/outcome.js +22 -0
- package/dist/slices/reviews/repo.js +118 -0
- package/dist/slices/reviews/rules.js +63 -0
- package/dist/slices/reviews/verdict.js +71 -0
- package/dist/slices/reviews/view.js +30 -0
- package/dist/slices/revisions/adopt-content.js +5 -2
- package/dist/slices/revisions/adopt.js +3 -1
- package/dist/slices/revisions/downloads.js +7 -1
- package/dist/slices/revisions/image-plan.js +183 -0
- package/dist/slices/revisions/mutation-assets.js +10 -0
- package/dist/slices/revisions/mutation-cues.js +71 -0
- package/dist/slices/revisions/mutation-request.js +2 -1
- package/dist/slices/revisions/mutations.js +97 -3
- package/dist/slices/revisions/schema.js +11 -1
- package/dist/slices/run-cost/limits.js +128 -0
- package/dist/slices/run-cost/meter.js +47 -0
- package/dist/slices/run-cost/panel.js +256 -0
- package/dist/slices/run-cost/pricing.js +95 -0
- package/dist/slices/run-cost/week.js +108 -0
- package/dist/slices/schedules/agenda.js +222 -0
- package/dist/slices/schedules/repo.js +58 -18
- package/dist/slices/schedules/scheduler.js +68 -17
- package/dist/slices/schedules/schema.js +179 -1
- package/dist/slices/schedules/service.js +43 -4
- package/dist/slices/schedules/similar.js +128 -0
- package/dist/slices/schedules/topic-list.js +163 -0
- package/dist/slices/schedules/topics.js +523 -0
- package/dist/slices/settings/first-run.js +106 -0
- package/dist/slices/settings/health.js +247 -0
- package/dist/slices/settings/key-guides.js +138 -0
- package/dist/slices/settings/key-test.js +93 -0
- package/dist/slices/settings/keys.js +10 -5
- package/dist/slices/settings/model-reach.js +52 -0
- package/dist/slices/settings/model.js +55 -1
- package/dist/slices/settings/models.js +5 -1
- package/dist/slices/settings/playback.js +15 -0
- package/dist/slices/settings/readiness.js +14 -2
- package/dist/slices/settings/repo.js +17 -3
- package/dist/slices/settings/tutorial-schema.js +5 -0
- package/dist/slices/settings/voices.js +64 -4
- package/dist/slices/settings/whats-new.js +64 -0
- package/dist/slices/shorts/captions.js +9 -0
- package/dist/slices/shorts/pick.js +3 -3
- package/dist/slices/shorts/prompts.js +1 -1
- package/dist/slices/shorts/render.js +63 -13
- package/dist/slices/storage/asset-name.js +3 -0
- package/dist/slices/storage/backup-export.js +48 -9
- package/dist/slices/storage/backup-format.js +38 -1
- package/dist/slices/storage/backup-import.js +191 -19
- package/dist/slices/storage/delete-project.js +7 -4
- package/dist/slices/storage/documents.js +87 -0
- package/dist/slices/storage/downloads.js +33 -1
- package/dist/slices/storage/files-location.js +531 -0
- package/dist/slices/storage/layout.js +14 -4
- package/dist/slices/storage/model.js +11 -0
- package/dist/slices/storage/portable.js +94 -12
- package/dist/slices/storage/reconcile.js +14 -1
- package/dist/slices/storage/repo.js +4 -1
- package/dist/slices/storage/schema.js +11 -0
- package/dist/slices/storage/trim.js +146 -0
- package/dist/slices/studio/disclosure.js +74 -0
- package/dist/slices/studio/model.js +30 -0
- package/dist/slices/studio/pack.js +211 -0
- package/dist/slices/studio/queue.js +69 -0
- package/dist/slices/studio/settings.js +170 -0
- package/dist/slices/style-preview/images.js +61 -0
- package/dist/slices/style-preview/narration.js +33 -0
- package/dist/slices/style-preview/render.js +148 -0
- package/dist/slices/style-preview/schema.js +59 -0
- package/dist/slices/style-preview/service.js +92 -0
- package/dist/slices/style-preview/settings.js +139 -0
- package/dist/slices/subtitles/captions.js +42 -9
- package/dist/slices/subtitles/model.js +22 -0
- package/dist/slices/subtitles/prepare.js +27 -16
- package/dist/slices/subtitles/transcript.js +1 -1
- package/dist/slices/thumbnail/run.js +7 -7
- package/dist/slices/trash/model.js +25 -0
- package/dist/slices/trash/service.js +273 -0
- package/dist/slices/tutorials/anchors.js +57 -0
- package/dist/slices/tutorials/library.js +185 -0
- package/dist/slices/uploads/repo.js +20 -0
- package/dist/slices/video/ambient-bed-schema.js +15 -0
- package/dist/slices/video/ambient-bed.js +95 -0
- package/dist/slices/video/ambient-mix.js +72 -0
- package/dist/slices/video/audio-inputs.js +2 -2
- package/dist/slices/video/cards.js +5 -2
- package/dist/slices/video/edit-list.js +23 -2
- package/dist/slices/video/edit-settings.js +13 -3
- package/dist/slices/video/ffmpeg.js +63 -9
- package/dist/slices/video/figure-card.js +492 -0
- package/dist/slices/video/figure-spans.js +51 -0
- package/dist/slices/video/plan.js +125 -13
- package/dist/slices/video/run.js +14 -12
- package/dist/slices/video/slideshow.js +39 -4
- package/dist/slices/voices/attribution.js +69 -0
- package/dist/slices/voices/audio-files.js +87 -0
- package/dist/slices/voices/audition.js +25 -0
- package/dist/slices/voices/cast.js +74 -0
- package/dist/slices/voices/grouping.js +59 -0
- package/dist/slices/voices/join.js +35 -0
- package/dist/slices/voices/languages.js +25 -0
- package/dist/slices/voices/model.js +218 -0
- package/dist/slices/voices/palette.js +26 -0
- package/dist/slices/voices/panel.js +91 -0
- package/dist/slices/voices/portraits.js +55 -0
- package/dist/slices/voices/script.js +136 -0
- package/dist/slices/voices/timing.js +58 -0
- package/dist/slices/youtube/answer.js +1 -1
- package/dist/slices/youtube/chapters.js +126 -0
- package/dist/slices/youtube/edits-repo.js +84 -0
- package/dist/slices/youtube/edits.js +89 -0
- package/dist/slices/youtube/placeholders.js +98 -0
- package/dist/slices/youtube/transcript.js +11 -4
- package/dist/tutorials/AI-CLIs.md +146 -0
- package/dist/tutorials/Backups.md +121 -0
- package/dist/tutorials/Calendar.md +103 -0
- package/dist/tutorials/Cast-Library.md +112 -0
- package/dist/tutorials/Channels.md +148 -0
- package/dist/tutorials/Costs-and-Run-Cost.md +136 -0
- package/dist/tutorials/Docker.md +171 -0
- package/dist/tutorials/Document-Themes.md +207 -0
- package/dist/tutorials/Editing-a-Project.md +204 -0
- package/dist/tutorials/FAQ.md +134 -0
- package/dist/tutorials/First-Launch-and-Welcome.md +153 -0
- package/dist/tutorials/Home-and-Projects.md +174 -0
- package/dist/tutorials/Home.md +119 -0
- package/dist/tutorials/Install.md +154 -0
- package/dist/tutorials/Intros-and-Outros.md +86 -0
- package/dist/tutorials/Keyboard-Shortcuts-and-Command-Palette.md +215 -0
- package/dist/tutorials/Library-Overview.md +75 -0
- package/dist/tutorials/Models.md +133 -0
- package/dist/tutorials/Multiple-Voices.md +161 -0
- package/dist/tutorials/Narration-Aliases-and-Glossary.md +129 -0
- package/dist/tutorials/Notifications.md +86 -0
- package/dist/tutorials/Other-Languages.md +110 -0
- package/dist/tutorials/PDF-Documents.md +100 -0
- package/dist/tutorials/Play-Images.md +135 -0
- package/dist/tutorials/Play-Narration.md +167 -0
- package/dist/tutorials/Play-Outputs.md +109 -0
- package/dist/tutorials/Play-Overview.md +216 -0
- package/dist/tutorials/Play-Title-and-Article.md +135 -0
- package/dist/tutorials/Play-Video-and-Style.md +143 -0
- package/dist/tutorials/Project-Page.md +228 -0
- package/dist/tutorials/Prompts.md +136 -0
- package/dist/tutorials/Providers-and-Keys.md +290 -0
- package/dist/tutorials/Publishing-to-YouTube.md +135 -0
- package/dist/tutorials/Recovery-and-Retries.md +141 -0
- package/dist/tutorials/Reviews-and-Checkpoints.md +143 -0
- package/dist/tutorials/Schedules.md +154 -0
- package/dist/tutorials/Settings-Reference.md +258 -0
- package/dist/tutorials/Shorts.md +116 -0
- package/dist/tutorials/Start-at-Login.md +126 -0
- package/dist/tutorials/Studio-Extension.md +146 -0
- package/dist/tutorials/Templates.md +146 -0
- package/dist/tutorials/Trash.md +87 -0
- package/dist/tutorials/Troubleshooting.md +149 -0
- package/dist/tutorials/Uninstalling-and-Moving.md +113 -0
- package/dist/tutorials/Updating-and-Patch-Notes.md +120 -0
- package/dist/tutorials/Video-Editing.md +135 -0
- package/dist/tutorials/Where-Your-Files-Live.md +149 -0
- package/dist/tutorials/YouTube-Description.md +132 -0
- package/dist/tutorials/Your-First-Short.md +125 -0
- package/dist/tutorials/_Footer.md +1 -0
- package/dist/tutorials/_Sidebar.md +69 -0
- package/dist/updater/service.js +66 -21
- package/dist/web/assets/index-DBLSfqA-.css +1 -0
- package/dist/web/assets/index-DFdIhmm0.js +307 -0
- package/dist/web/assets/jetbrains-mono-cyrillic-400-normal-BEIGL1Tu.woff2 +0 -0
- package/dist/web/assets/jetbrains-mono-cyrillic-400-normal-ugxPyKxw.woff +0 -0
- package/dist/web/assets/jetbrains-mono-greek-400-normal-B9oWc5Lo.woff +0 -0
- package/dist/web/assets/jetbrains-mono-greek-400-normal-C190GLew.woff2 +0 -0
- package/dist/web/assets/jetbrains-mono-latin-400-normal-6-qcROiO.woff +0 -0
- package/dist/web/assets/jetbrains-mono-latin-400-normal-V6pRDFza.woff2 +0 -0
- package/dist/web/assets/jetbrains-mono-latin-ext-400-normal-Bc8Ftmh3.woff2 +0 -0
- package/dist/web/assets/jetbrains-mono-latin-ext-400-normal-fXTG6kC5.woff +0 -0
- package/dist/web/assets/jetbrains-mono-vietnamese-400-normal-CqNFfHCs.woff +0 -0
- package/dist/web/assets/{pdf-BLF2i8c2.js → pdf-B9OY1ioX.js} +1 -1
- package/dist/web/index.html +2 -2
- package/package.json +5 -5
- package/dist/edge/docker-launch.js +0 -81
- package/dist/edge/docker-projects/activation.js +0 -35
- package/dist/edge/docker-projects/claims.js +0 -85
- package/dist/edge/docker-projects/committed.js +0 -40
- package/dist/edge/docker-projects/engine.js +0 -461
- package/dist/edge/docker-projects/install.js +0 -254
- package/dist/edge/docker-projects/prune.js +0 -66
- package/dist/edge/docker-projects/recover.js +0 -100
- package/dist/edge/docker-projects/state.js +0 -225
- package/dist/web/assets/index-CktpxlJd.js +0 -171
- package/dist/web/assets/index-DB-vOnGU.css +0 -1
- package/scripts/docker-run.sh +0 -3
- /package/dist/edge/{docker-projects → docker-install}/tree.js +0 -0
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
// The speech a computer already has, found when asked: macOS's `say`, Windows' built-in
|
|
2
|
+
// System.Speech through PowerShell, and on Linux Piper, SVOX Pico, eSpeak NG or eSpeak, best
|
|
3
|
+
// first. No key and no charge. It lives in the kernel because the settings slice (readiness)
|
|
4
|
+
// and the TTS adapter both read it, and neither may import the other.
|
|
5
|
+
export const speechEngineIds = [
|
|
6
|
+
"say",
|
|
7
|
+
"sapi",
|
|
8
|
+
"piper",
|
|
9
|
+
"pico2wave",
|
|
10
|
+
"espeak-ng",
|
|
11
|
+
"espeak",
|
|
12
|
+
];
|
|
13
|
+
export const speechEngineNames = {
|
|
14
|
+
say: "macOS voices",
|
|
15
|
+
sapi: "Windows voices",
|
|
16
|
+
piper: "Piper",
|
|
17
|
+
pico2wave: "SVOX Pico",
|
|
18
|
+
"espeak-ng": "eSpeak NG",
|
|
19
|
+
espeak: "eSpeak",
|
|
20
|
+
};
|
|
21
|
+
const probeTimeoutMs = 15_000;
|
|
22
|
+
// Windows lists the enabled voices as "name<TAB>culture" lines.
|
|
23
|
+
export const windowsVoiceListScript = "Add-Type -AssemblyName System.Speech; $s = New-Object System.Speech.Synthesis.SpeechSynthesizer; foreach ($v in $s.GetInstalledVoices()) { if ($v.Enabled) { Write-Output ($v.VoiceInfo.Name + [char]9 + $v.VoiceInfo.Culture.Name) } }; $s.Dispose()";
|
|
24
|
+
// SVOX Pico ships exactly these six.
|
|
25
|
+
const picoVoices = [
|
|
26
|
+
{ id: "en-US", name: "English (US)", language: "en-US" },
|
|
27
|
+
{ id: "en-GB", name: "English (UK)", language: "en-GB" },
|
|
28
|
+
{ id: "de-DE", name: "German", language: "de-DE" },
|
|
29
|
+
{ id: "es-ES", name: "Spanish", language: "es-ES" },
|
|
30
|
+
{ id: "fr-FR", name: "French", language: "fr-FR" },
|
|
31
|
+
{ id: "it-IT", name: "Italian", language: "it-IT" },
|
|
32
|
+
];
|
|
33
|
+
export const noSpeechFix = "or add an ElevenLabs or OpenAI key in Settings → Providers for a better voice.";
|
|
34
|
+
export async function detectSpeech(given, host) {
|
|
35
|
+
// A probe that throws (a host bridge that cannot run local programs) found nothing.
|
|
36
|
+
const probe = (binary, args, timeoutMs) => Promise.resolve()
|
|
37
|
+
.then(() => given(binary, args, timeoutMs))
|
|
38
|
+
.catch(() => ({ ran: false, stdout: "" }));
|
|
39
|
+
const engines = [];
|
|
40
|
+
const add = (id, voices) => {
|
|
41
|
+
if (voices.length > 0)
|
|
42
|
+
engines.push({ id, name: speechEngineNames[id], voices });
|
|
43
|
+
};
|
|
44
|
+
if (host.platform === "darwin") {
|
|
45
|
+
const listed = await probe("say", ["-v", "?"], probeTimeoutMs);
|
|
46
|
+
if (listed.ran)
|
|
47
|
+
add("say", parseSayVoices(listed.stdout));
|
|
48
|
+
return engines.length > 0
|
|
49
|
+
? { engines }
|
|
50
|
+
: {
|
|
51
|
+
engines,
|
|
52
|
+
issue: `macOS's speech command (say) didn't answer, so the system voice can't narrate. Check that /usr/bin/say runs in Terminal, ${noSpeechFix}`,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
if (host.platform === "win32") {
|
|
56
|
+
const listed = await probe("powershell", ["-NoProfile", "-NonInteractive", "-Command", windowsVoiceListScript], probeTimeoutMs);
|
|
57
|
+
if (listed.ran)
|
|
58
|
+
add("sapi", parseWindowsVoices(listed.stdout));
|
|
59
|
+
return engines.length > 0
|
|
60
|
+
? { engines }
|
|
61
|
+
: {
|
|
62
|
+
engines,
|
|
63
|
+
issue: `Windows' built-in speech didn't answer through PowerShell, or no voice is installed. Add a voice in Windows Settings → Time & language → Speech, ${noSpeechFix}`,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
const piperModels = piperVoices(host.env);
|
|
67
|
+
const [piper, pico, espeakNg, espeak] = await Promise.all([
|
|
68
|
+
// Without a voice model Piper can't speak, so it isn't even asked.
|
|
69
|
+
piperModels.length > 0 ? isPiperTts(probe) : Promise.resolve(false),
|
|
70
|
+
onPath(probe, "pico2wave"),
|
|
71
|
+
probe("espeak-ng", ["--voices"], probeTimeoutMs),
|
|
72
|
+
probe("espeak", ["--voices"], probeTimeoutMs),
|
|
73
|
+
]);
|
|
74
|
+
if (piper)
|
|
75
|
+
add("piper", piperModels);
|
|
76
|
+
if (pico)
|
|
77
|
+
add("pico2wave", picoVoices);
|
|
78
|
+
if (espeakNg.ran)
|
|
79
|
+
add("espeak-ng", parseEspeakVoices(espeakNg.stdout));
|
|
80
|
+
if (espeak.ran)
|
|
81
|
+
add("espeak", parseEspeakVoices(espeak.stdout));
|
|
82
|
+
if (engines.length > 0)
|
|
83
|
+
return { engines };
|
|
84
|
+
return {
|
|
85
|
+
engines,
|
|
86
|
+
issue: host.env.SLOPIFY_CONTAINER === "1"
|
|
87
|
+
? `Slopify runs in Docker and this image has no speech program, so the system voice can't narrate. Update the image (docker compose pull, then docker compose up -d), ${noSpeechFix}`
|
|
88
|
+
: `No speech program was found on this computer, so the system voice can't narrate. Install espeak-ng (for example sudo apt install espeak-ng, sudo pacman -S espeak-ng or sudo dnf install espeak-ng) and reload Settings → Providers, ${noSpeechFix}`,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
async function onPath(probe, binary) {
|
|
92
|
+
// `command -v` answers for a program on PATH without running it: Pico and Piper have no
|
|
93
|
+
// harmless flag that exits cleanly.
|
|
94
|
+
return (await probe("sh", ["-c", 'command -v "$1"', "sh", binary], probeTimeoutMs)).ran;
|
|
95
|
+
}
|
|
96
|
+
// `piper` on PATH is not always Piper the voice engine: libratbag's mouse settings app has the
|
|
97
|
+
// same name (/usr/bin/piper on many desktops). The engine is told apart by its help, which names
|
|
98
|
+
// --model and an output option (the C++ build prints it on stderr, hence 2>&1), or failing that
|
|
99
|
+
// by a version line that names piper-tts. Anything else, or no answer, is not Piper.
|
|
100
|
+
async function isPiperTts(probe) {
|
|
101
|
+
const ask = (flag) => probe("sh", ["-c", '"$1" "$2" 2>&1; exit 0', "sh", "piper", flag], probeTimeoutMs);
|
|
102
|
+
const help = await ask("--help");
|
|
103
|
+
if (help.ran && isPiperTtsHelp(help.stdout))
|
|
104
|
+
return true;
|
|
105
|
+
const version = await ask("--version");
|
|
106
|
+
return version.ran && isPiperTtsVersion(version.stdout);
|
|
107
|
+
}
|
|
108
|
+
export function isPiperTtsHelp(text) {
|
|
109
|
+
return /--model\b/.test(text) && /--output[-_](?:file|dir|raw)\b/.test(text);
|
|
110
|
+
}
|
|
111
|
+
export function isPiperTtsVersion(text) {
|
|
112
|
+
return /\bpiper[-_ ]tts\b/i.test(text);
|
|
113
|
+
}
|
|
114
|
+
// Piper needs a voice model file; SLOPIFY_PIPER_VOICES lists them (.onnx paths, separated like
|
|
115
|
+
// PATH). Without one, Piper can't speak and is left out.
|
|
116
|
+
export function piperVoices(env) {
|
|
117
|
+
return (env.SLOPIFY_PIPER_VOICES ?? "")
|
|
118
|
+
.split(":")
|
|
119
|
+
.map((path) => path.trim())
|
|
120
|
+
.filter((path) => path.endsWith(".onnx"))
|
|
121
|
+
.map((path) => {
|
|
122
|
+
const name = (path.split("/").pop() ?? path).replace(/\.onnx$/, "");
|
|
123
|
+
const language = /^([a-z]{2,3}_[A-Z]{2})/.exec(name)?.[1];
|
|
124
|
+
return { id: path, name, ...(language === undefined ? {} : { language }) };
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
// `say -v ?`: "Samantha en_US # Hello! My name is Samantha." A name may carry
|
|
128
|
+
// single spaces and brackets ("Eddy (English (US))"), so the language is the anchor.
|
|
129
|
+
export function parseSayVoices(stdout) {
|
|
130
|
+
const voices = [];
|
|
131
|
+
for (const line of stdout.split(/\r?\n/)) {
|
|
132
|
+
const match = /^(.+?)\s+([a-z]{2,3}[_-][A-Za-z0-9_-]+)\s+#/.exec(line);
|
|
133
|
+
if (match?.[1] === undefined || match[2] === undefined)
|
|
134
|
+
continue;
|
|
135
|
+
const name = match[1].trim();
|
|
136
|
+
if (!voices.some((voice) => voice.id === name))
|
|
137
|
+
voices.push({ id: name, name, language: match[2] });
|
|
138
|
+
}
|
|
139
|
+
return voices;
|
|
140
|
+
}
|
|
141
|
+
export function parseWindowsVoices(stdout) {
|
|
142
|
+
const voices = [];
|
|
143
|
+
for (const line of stdout.split(/\r?\n/)) {
|
|
144
|
+
const [name, culture] = line.split("\t").map((part) => part.trim());
|
|
145
|
+
if (name === undefined || name === "" || voices.some((voice) => voice.id === name))
|
|
146
|
+
continue;
|
|
147
|
+
voices.push({
|
|
148
|
+
id: name,
|
|
149
|
+
name: name.replace(/^Microsoft\s+/, "").replace(/\s+Desktop$/, ""),
|
|
150
|
+
...(culture === undefined || culture === "" ? {} : { language: culture }),
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
return voices;
|
|
154
|
+
}
|
|
155
|
+
// `espeak-ng --voices`: a header, then " 5 en-us --/M English_(America) gmw/en-US ...".
|
|
156
|
+
export function parseEspeakVoices(stdout) {
|
|
157
|
+
const voices = [];
|
|
158
|
+
for (const line of stdout.split(/\r?\n/)) {
|
|
159
|
+
const parts = line.trim().split(/\s+/);
|
|
160
|
+
if (parts.length < 4 || !/^\d+$/.test(parts[0] ?? ""))
|
|
161
|
+
continue;
|
|
162
|
+
const [, language, , name] = parts;
|
|
163
|
+
if (language === undefined || name === undefined)
|
|
164
|
+
continue;
|
|
165
|
+
if (voices.some((voice) => voice.id === language))
|
|
166
|
+
continue;
|
|
167
|
+
voices.push({ id: language, name: name.replace(/_/g, " "), language });
|
|
168
|
+
}
|
|
169
|
+
return voices;
|
|
170
|
+
}
|
|
171
|
+
// The voice a first short uses when none is saved: an English one, American first.
|
|
172
|
+
export function defaultSpeechVoice(engine) {
|
|
173
|
+
const english = (voice, tag) => tag.test(voice.language ?? voice.id);
|
|
174
|
+
return (engine.voices.find((voice) => voice.name === "Samantha") ??
|
|
175
|
+
engine.voices.find((voice) => english(voice, /^en[-_]us$/i)) ??
|
|
176
|
+
engine.voices.find((voice) => english(voice, /^en\b|^en[-_]/i)) ??
|
|
177
|
+
engine.voices[0]);
|
|
178
|
+
}
|
|
179
|
+
// The primary language subtag ("en" from "en_US"), as Settings → Voices records it.
|
|
180
|
+
export function primaryLanguage(voice) {
|
|
181
|
+
const tag = /^([a-z]{2,3})(?:[-_]|$)/i.exec(voice.language ?? "")?.[1];
|
|
182
|
+
return tag?.toLowerCase();
|
|
183
|
+
}
|
|
184
|
+
// One look per minute: readiness is asked on every Settings and Play load, and starting four
|
|
185
|
+
// processes each time is wasted work for something that changes when a program is installed.
|
|
186
|
+
const cacheMs = 60_000;
|
|
187
|
+
const cached = new WeakMap();
|
|
188
|
+
export function detectSpeechCached(probe, host) {
|
|
189
|
+
const now = performance.now();
|
|
190
|
+
const key = [
|
|
191
|
+
host.platform,
|
|
192
|
+
host.env.SLOPIFY_CONTAINER ?? "",
|
|
193
|
+
host.env.SLOPIFY_PIPER_VOICES ?? "",
|
|
194
|
+
].join("\n");
|
|
195
|
+
const byHost = cached.get(probe) ?? new Map();
|
|
196
|
+
cached.set(probe, byHost);
|
|
197
|
+
const hit = byHost.get(key);
|
|
198
|
+
if (hit !== undefined && now - hit.at < cacheMs)
|
|
199
|
+
return hit.found;
|
|
200
|
+
const found = detectSpeech(probe, host);
|
|
201
|
+
byHost.set(key, { at: now, found });
|
|
202
|
+
return found;
|
|
203
|
+
}
|
|
@@ -14,15 +14,18 @@ export const timeoutMs = {
|
|
|
14
14
|
video: 900_000,
|
|
15
15
|
};
|
|
16
16
|
// A refusal and an unsupported capability are the provider's final answer; retrying only
|
|
17
|
-
// spends the user's money again.
|
|
18
|
-
//
|
|
19
|
-
// retried like any other.
|
|
17
|
+
// spends the user's money again. A key the provider rejected, or one removed mid-run, needs
|
|
18
|
+
// the user in Settings before any call can succeed.
|
|
20
19
|
const terminalKinds = [
|
|
21
20
|
"refusal",
|
|
22
21
|
"unsupported",
|
|
22
|
+
"auth",
|
|
23
23
|
"missing_key",
|
|
24
24
|
"unavailable",
|
|
25
25
|
];
|
|
26
|
+
// A Retry-After longer than this is not slept through with the stage holding its provider
|
|
27
|
+
// slot: the call fails here and the runner's persisted wait (`retry-policy.ts`) takes over.
|
|
28
|
+
export const inCallRetryAfterCeilingMs = 60_000;
|
|
26
29
|
export async function attempt(ctx, call, opts) {
|
|
27
30
|
ctx.signal.throwIfAborted();
|
|
28
31
|
const limit = opts.timeoutMs ?? timeoutMs[opts.kind];
|
|
@@ -84,7 +87,12 @@ export async function attempt(ctx, call, opts) {
|
|
|
84
87
|
stage: ctx.stage,
|
|
85
88
|
detail: `${opts.kind} attempt ${n} of ${attemptLimit} failed (${failure.fault.kind}): ${failure.message}`,
|
|
86
89
|
});
|
|
87
|
-
|
|
90
|
+
// A used-up plan allowance is not retried here: the call waits for the reset outside the
|
|
91
|
+
// provider queue (providers.ts), so a waiting stage holds no slot other work needs.
|
|
92
|
+
if (terminalKinds.includes(failure.fault.kind) ||
|
|
93
|
+
failure.fault.planLimit !== undefined ||
|
|
94
|
+
n >= attemptLimit ||
|
|
95
|
+
(failure.fault.retryAfterMs ?? 0) > inCallRetryAfterCeilingMs) {
|
|
88
96
|
throw failure;
|
|
89
97
|
}
|
|
90
98
|
// A 429 that names a Retry-After replaces the fixed wait with the provider's.
|
|
@@ -102,8 +110,8 @@ function classify(error, expired, opts, limit) {
|
|
|
102
110
|
return providerError({
|
|
103
111
|
kind: "timeout",
|
|
104
112
|
message: opts.streaming === true
|
|
105
|
-
? `The ${callee[opts.kind]} sent nothing for ${seconds} seconds, so Slopify stopped waiting. It may be overloaded: wait a few minutes, then use
|
|
106
|
-
: `The ${callee[opts.kind]} did not answer within ${seconds} seconds. It may be overloaded: wait a few minutes, then use
|
|
113
|
+
? `The ${callee[opts.kind]} sent nothing for ${seconds} seconds, so Slopify stopped waiting. It may be overloaded: wait a few minutes, then use Try again.`
|
|
114
|
+
: `The ${callee[opts.kind]} did not answer within ${seconds} seconds. It may be overloaded: wait a few minutes, then use Try again, or choose another model in the Providers section of Edit project.`,
|
|
107
115
|
});
|
|
108
116
|
}
|
|
109
117
|
if (isProviderError(error)) {
|
|
@@ -113,14 +121,15 @@ function classify(error, expired, opts, limit) {
|
|
|
113
121
|
kind: error.fault.kind,
|
|
114
122
|
message: redact(error.message),
|
|
115
123
|
...(error.fault.retryAfterMs === undefined ? {} : { retryAfterMs: error.fault.retryAfterMs }),
|
|
124
|
+
...(error.fault.planLimit === undefined ? {} : { planLimit: error.fault.planLimit }),
|
|
116
125
|
});
|
|
117
126
|
}
|
|
118
127
|
if (unreachable(error)) {
|
|
119
128
|
// `fetch` names only itself; the cause's code (ENOTFOUND, ECONNREFUSED) is the clue.
|
|
120
129
|
const code = causeCode(error);
|
|
121
130
|
return providerError({
|
|
122
|
-
kind: "
|
|
123
|
-
message: `Slopify could not reach the ${callee[opts.kind]} over the internet${code === undefined ? "" : ` (${code})`}. Check your internet connection, firewall or VPN, then use
|
|
131
|
+
kind: "dropped",
|
|
132
|
+
message: `Slopify could not reach the ${callee[opts.kind]} over the internet${code === undefined ? "" : ` (${code})`}. Check your internet connection, firewall or VPN, then use Try again.`,
|
|
124
133
|
});
|
|
125
134
|
}
|
|
126
135
|
return providerError({
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { attempt } from "./attempt.js";
|
|
2
|
+
const unrecorded = {
|
|
3
|
+
start: () => "audition",
|
|
4
|
+
end: () => { },
|
|
5
|
+
};
|
|
6
|
+
export function auditionVoice(deps, call, signal) {
|
|
7
|
+
const port = deps.registry.tts(call.provider);
|
|
8
|
+
return attempt({
|
|
9
|
+
work: {
|
|
10
|
+
projectId: "audition",
|
|
11
|
+
revisionId: "audition",
|
|
12
|
+
workId: "audition",
|
|
13
|
+
stageId: "audition",
|
|
14
|
+
kind: "audio",
|
|
15
|
+
fingerprint: "audition",
|
|
16
|
+
},
|
|
17
|
+
maySubmit: () => true,
|
|
18
|
+
clock: deps.clock,
|
|
19
|
+
log: deps.log,
|
|
20
|
+
attempts: unrecorded,
|
|
21
|
+
projectId: "audition",
|
|
22
|
+
stage: "audio",
|
|
23
|
+
stageId: "audition",
|
|
24
|
+
signal,
|
|
25
|
+
}, async (inner, progress) => {
|
|
26
|
+
const spoken = await port.synthesize({
|
|
27
|
+
model: call.model,
|
|
28
|
+
voiceId: call.voiceId,
|
|
29
|
+
text: call.text,
|
|
30
|
+
signal: inner,
|
|
31
|
+
onActivity: progress,
|
|
32
|
+
});
|
|
33
|
+
const bytes = new Uint8Array(await new Response(spoken.audio).arrayBuffer());
|
|
34
|
+
return { bytes, container: spoken.container };
|
|
35
|
+
}, { kind: "tts", streaming: port.capabilities.streams });
|
|
36
|
+
}
|
|
@@ -1,33 +1,55 @@
|
|
|
1
1
|
// Images use saved prompts and can run immediately. A thumbnail's source and an
|
|
2
2
|
// audio-only export narrow these dependencies through dependenciesOf(). The document is
|
|
3
3
|
// laid out from the article alone, with the thumbnail as its cover when there is one, so it
|
|
4
|
-
// runs beside narration and images rather than after them.
|
|
4
|
+
// runs beside narration and images rather than after them. The video never reads the
|
|
5
|
+
// thumbnail, so a thumbnail that fails does not hold the video back; neither does it hold
|
|
6
|
+
// the document back (see `optionalDeps`).
|
|
5
7
|
export const deps = {
|
|
6
8
|
research: [],
|
|
7
9
|
article: ["research"],
|
|
8
10
|
audio: ["article"],
|
|
9
11
|
images: [],
|
|
10
12
|
thumbnail: ["article"],
|
|
11
|
-
video: ["article", "audio", "images"
|
|
13
|
+
video: ["article", "audio", "images"],
|
|
12
14
|
document: ["article", "thumbnail"],
|
|
13
15
|
};
|
|
16
|
+
// Dependencies a stage waits for but can do without: the document takes the thumbnail as its
|
|
17
|
+
// cover when there is one. A thumbnail that failed or was canceled releases the document,
|
|
18
|
+
// which is then laid out with no cover, instead of holding it back with it. Making the
|
|
19
|
+
// thumbnail again still redoes the document (reruns/cascade.ts follows `deps`), so it gets
|
|
20
|
+
// its cover then.
|
|
21
|
+
export const optionalDeps = {
|
|
22
|
+
document: ["thumbnail"],
|
|
23
|
+
};
|
|
14
24
|
// `provided` and `skipped` release a dependency exactly as `done` does.
|
|
15
25
|
export function satisfied(state) {
|
|
16
26
|
return state === "done" || state === "provided" || state === "skipped";
|
|
17
27
|
}
|
|
28
|
+
// Whether `dependency`, in `state`, lets `kind` start.
|
|
29
|
+
export function releases(kind, dependency, state) {
|
|
30
|
+
if (satisfied(state))
|
|
31
|
+
return true;
|
|
32
|
+
return ((state === "failed" || state === "canceled") &&
|
|
33
|
+
(optionalDeps[kind]?.includes(dependency) ?? false));
|
|
34
|
+
}
|
|
35
|
+
// What a run is for, in order: the first of these the run asks for is the one that has to be
|
|
36
|
+
// there for the run to count as finished. Anything else failing leaves it done with
|
|
37
|
+
// problems rather than failed.
|
|
38
|
+
const headline = ["video", "audio", "article"];
|
|
18
39
|
// Stage state is derived; an explicit persisted pause takes precedence while calls
|
|
19
|
-
// drain. Completed independent images do not imply that a run was canceled.
|
|
40
|
+
// drain. Completed independent images do not imply that a run was canceled. A stage
|
|
41
|
+
// waiting out a rate limit is still part of a run in progress.
|
|
20
42
|
export function derive(stages, paused = false) {
|
|
21
43
|
if (paused)
|
|
22
44
|
return "paused";
|
|
23
|
-
if (stages.some((stage) => stage.state === "running")) {
|
|
45
|
+
if (stages.some((stage) => stage.state === "running" || waiting(stage))) {
|
|
24
46
|
return "running";
|
|
25
47
|
}
|
|
26
48
|
if (stages.some((stage) => stage.state === "canceled")) {
|
|
27
49
|
return "canceled";
|
|
28
50
|
}
|
|
29
51
|
if (stages.some((stage) => stage.state === "failed")) {
|
|
30
|
-
return "failed";
|
|
52
|
+
return headlineMade(stages) ? "partial" : "failed";
|
|
31
53
|
}
|
|
32
54
|
if (stages.length > 0 && stages.every((stage) => satisfied(stage.state))) {
|
|
33
55
|
return "done";
|
|
@@ -35,6 +57,19 @@ export function derive(stages, paused = false) {
|
|
|
35
57
|
// Includes a run created but not yet claimed and unfinished work after restart.
|
|
36
58
|
return "pending";
|
|
37
59
|
}
|
|
60
|
+
function waiting(stage) {
|
|
61
|
+
return stage.state === "pending" && stage.retryAt !== undefined && stage.retryAt !== null;
|
|
62
|
+
}
|
|
63
|
+
function headlineMade(stages) {
|
|
64
|
+
for (const kind of headline) {
|
|
65
|
+
const stage = stages.find((one) => one.kind === kind);
|
|
66
|
+
if (stage === undefined || stage.state === "skipped")
|
|
67
|
+
continue;
|
|
68
|
+
// A file the user supplied is not something this run made.
|
|
69
|
+
return stage.state === "done";
|
|
70
|
+
}
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
38
73
|
export function dependenciesOf(kind, sources) {
|
|
39
74
|
if (kind === "thumbnail" && sources.thumbnail === "from_prompt")
|
|
40
75
|
return [];
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { causedBy } from "../errors.js";
|
|
2
|
-
import { derive, deps as graph,
|
|
2
|
+
import { derive, deps as graph, releases } from "./graph.js";
|
|
3
3
|
import { progressGate } from "./progress.js";
|
|
4
|
+
import { faultOf } from "./retry-policy.js";
|
|
4
5
|
const pauseReason = new Error("paused by user");
|
|
5
6
|
export function createRunner(deps) {
|
|
6
7
|
const inflight = new Map();
|
|
@@ -15,7 +16,7 @@ export function createRunner(deps) {
|
|
|
15
16
|
const stopped = new Set();
|
|
16
17
|
let count = 0;
|
|
17
18
|
let shuttingDown = false;
|
|
18
|
-
const emitStage = (stage, state, reason) => {
|
|
19
|
+
const emitStage = (stage, state, reason, detail = {}) => {
|
|
19
20
|
deps.emit(stage.projectId, {
|
|
20
21
|
type: "stage.state",
|
|
21
22
|
revisionId: stage.work.revisionId,
|
|
@@ -24,6 +25,8 @@ export function createRunner(deps) {
|
|
|
24
25
|
stage: stage.kind,
|
|
25
26
|
state,
|
|
26
27
|
...(reason === null ? {} : { failureReason: reason }),
|
|
28
|
+
...(detail.retryAt === undefined ? {} : { retryAt: detail.retryAt }),
|
|
29
|
+
...(detail.failureKind === undefined ? {} : { failureKind: detail.failureKind }),
|
|
27
30
|
});
|
|
28
31
|
};
|
|
29
32
|
// The global tally counts projects with a stage in flight, read off the in-flight set
|
|
@@ -46,9 +49,9 @@ export function createRunner(deps) {
|
|
|
46
49
|
announced.set(projectId, state);
|
|
47
50
|
deps.emit(projectId, { type: "project.state", projectId, state });
|
|
48
51
|
};
|
|
49
|
-
const conclude = (stage, state, reason) => {
|
|
52
|
+
const conclude = (stage, state, reason, kind) => {
|
|
50
53
|
try {
|
|
51
|
-
deps.stages.finish(stage.work, state, reason);
|
|
54
|
+
deps.stages.finish(stage.work, state, reason, kind ?? null);
|
|
52
55
|
}
|
|
53
56
|
catch (error) {
|
|
54
57
|
// The row stays `running` when the write fails. The event still goes out, and the
|
|
@@ -59,7 +62,31 @@ export function createRunner(deps) {
|
|
|
59
62
|
detail: reasonOf(error),
|
|
60
63
|
});
|
|
61
64
|
}
|
|
62
|
-
emitStage(stage, state, reason);
|
|
65
|
+
emitStage(stage, state, reason, { failureKind: kind });
|
|
66
|
+
};
|
|
67
|
+
// False when the failure is to be shown now.
|
|
68
|
+
const deferred = (stage, fault, reason) => {
|
|
69
|
+
let at;
|
|
70
|
+
try {
|
|
71
|
+
at = deps.stages.waitToRetry?.(stage.work, fault, reason);
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
deps.log.write("error", "stage.retry", {
|
|
75
|
+
projectId: stage.projectId,
|
|
76
|
+
stage: stage.kind,
|
|
77
|
+
detail: reasonOf(error),
|
|
78
|
+
});
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
if (at === undefined)
|
|
82
|
+
return false;
|
|
83
|
+
deps.log.write("warn", "stage.retry", {
|
|
84
|
+
projectId: stage.projectId,
|
|
85
|
+
stage: stage.kind,
|
|
86
|
+
detail: `waiting until ${at} to run again after ${fault?.kind ?? "a failure"}: ${reason}`,
|
|
87
|
+
});
|
|
88
|
+
emitStage(stage, "pending", reason, { retryAt: at, failureKind: fault?.kind });
|
|
89
|
+
return true;
|
|
63
90
|
};
|
|
64
91
|
async function execute(stage, controller) {
|
|
65
92
|
const tag = (event) => ({
|
|
@@ -103,12 +130,15 @@ export function createRunner(deps) {
|
|
|
103
130
|
conclude(stage, paused ? "pending" : "canceled", paused ? null : "canceled by user");
|
|
104
131
|
return;
|
|
105
132
|
}
|
|
133
|
+
const fault = faultOf(error);
|
|
134
|
+
if (deferred(stage, fault, reasonOf(error)))
|
|
135
|
+
return;
|
|
106
136
|
deps.log.write("error", "stage.failed", {
|
|
107
137
|
projectId: stage.projectId,
|
|
108
138
|
stage: stage.kind,
|
|
109
139
|
detail: causedBy(error),
|
|
110
140
|
});
|
|
111
|
-
conclude(stage, "failed", reasonOf(error));
|
|
141
|
+
conclude(stage, "failed", reasonOf(error), fault?.kind);
|
|
112
142
|
}
|
|
113
143
|
}
|
|
114
144
|
function start(stage) {
|
|
@@ -160,9 +190,9 @@ export function createRunner(deps) {
|
|
|
160
190
|
}
|
|
161
191
|
function startEligible(projectId) {
|
|
162
192
|
const stages = deps.stages.stagesOf(projectId);
|
|
163
|
-
const
|
|
193
|
+
const releasesKind = (dependent) => (kind) => {
|
|
164
194
|
const matches = stages.filter((stage) => stage.kind === kind);
|
|
165
|
-
return matches.length > 0 && matches.every((stage) =>
|
|
195
|
+
return (matches.length > 0 && matches.every((stage) => releases(dependent, kind, stage.state)));
|
|
166
196
|
};
|
|
167
197
|
for (const stage of stages) {
|
|
168
198
|
if (stage.state !== "pending" || inflight.has(stage.work.workId)) {
|
|
@@ -170,7 +200,7 @@ export function createRunner(deps) {
|
|
|
170
200
|
}
|
|
171
201
|
const dependencies = deps.stages.dependenciesOf?.(projectId, stage.kind) ?? graph[stage.kind];
|
|
172
202
|
if (deps.stages.ready === undefined
|
|
173
|
-
? !dependencies.every(
|
|
203
|
+
? !dependencies.every(releasesKind(stage.kind))
|
|
174
204
|
: !deps.stages.ready(stage.work)) {
|
|
175
205
|
continue;
|
|
176
206
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|