@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,35 @@
|
|
|
1
|
+
-- What every successful provider call made outside a project used and cost: a schedule's
|
|
2
|
+
-- topic generation, a channel's episode summary and its cast pictures. provider_usage cannot
|
|
3
|
+
-- hold them, since each of its rows belongs to a project. Priced the same way when the call
|
|
4
|
+
-- lands. There is no link to the schedule or channel: deleting one keeps what it cost this
|
|
5
|
+
-- week. `channel_id` is the channel the call was made for, resolved when it landed, for Home's
|
|
6
|
+
-- channel filter. A CLI's plan windows reported around the call ride along (`account`,
|
|
7
|
+
-- `reading_json`), so Home's plan standings read them beside a project's.
|
|
8
|
+
CREATE TABLE standalone_usage (
|
|
9
|
+
id TEXT PRIMARY KEY,
|
|
10
|
+
owner_kind TEXT NOT NULL CHECK(owner_kind IN ('schedule','channel')),
|
|
11
|
+
owner_id TEXT NOT NULL,
|
|
12
|
+
channel_id TEXT NOT NULL,
|
|
13
|
+
purpose TEXT NOT NULL,
|
|
14
|
+
kind TEXT NOT NULL CHECK(kind IN ('llm','tts','image','video')),
|
|
15
|
+
provider TEXT NOT NULL,
|
|
16
|
+
model TEXT NOT NULL,
|
|
17
|
+
tokens_in INTEGER,
|
|
18
|
+
tokens_out INTEGER,
|
|
19
|
+
tokens_cached INTEGER,
|
|
20
|
+
characters INTEGER,
|
|
21
|
+
images INTEGER,
|
|
22
|
+
seconds REAL,
|
|
23
|
+
size TEXT,
|
|
24
|
+
quality TEXT,
|
|
25
|
+
wall_ms INTEGER NOT NULL,
|
|
26
|
+
on_plan INTEGER NOT NULL DEFAULT 0 CHECK(on_plan IN (0,1)),
|
|
27
|
+
cost REAL,
|
|
28
|
+
api_model TEXT,
|
|
29
|
+
api_cost REAL,
|
|
30
|
+
price_json TEXT CHECK(price_json IS NULL OR json_valid(price_json)),
|
|
31
|
+
account TEXT,
|
|
32
|
+
reading_json TEXT CHECK(reading_json IS NULL OR json_valid(reading_json)),
|
|
33
|
+
created_at TEXT NOT NULL
|
|
34
|
+
);
|
|
35
|
+
CREATE INDEX standalone_usage_created ON standalone_usage(created_at);
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
-- A channel's hosts: cast members marked as the channel's recurring voices. A new podcast or
|
|
2
|
+
-- interview draft starts with them as its speakers. Every member made before this is not a host.
|
|
3
|
+
ALTER TABLE cast_members ADD COLUMN host INTEGER NOT NULL DEFAULT 0 CHECK (host IN (0, 1));
|
package/dist/kernel/paths.js
CHANGED
|
@@ -1,18 +1,38 @@
|
|
|
1
1
|
import { chmodSync, mkdirSync } from "node:fs";
|
|
2
2
|
import { join, resolve } from "node:path";
|
|
3
|
-
export function layout(dataDir) {
|
|
3
|
+
export function layout(dataDir, files) {
|
|
4
4
|
const root = resolve(dataDir);
|
|
5
|
+
const projects = join(root, "projects");
|
|
5
6
|
return {
|
|
6
7
|
dataDir: root,
|
|
7
8
|
db: join(root, "slopify.db"),
|
|
8
|
-
projects:
|
|
9
|
+
projects: files?.projects ?? projects,
|
|
10
|
+
backups: files?.backups ?? join(projects, "Backups"),
|
|
11
|
+
exports: files === undefined ? null : files.exports,
|
|
9
12
|
staging: join(root, "staging"),
|
|
10
13
|
logs: join(root, "logs"),
|
|
11
14
|
lock: join(root, ".lock"),
|
|
12
15
|
};
|
|
13
16
|
}
|
|
17
|
+
// Points a running install's Paths at moved files. The one object every slice was handed is
|
|
18
|
+
// changed in place, so the next file each one reads or writes is in the new place.
|
|
19
|
+
export function repoint(paths, files) {
|
|
20
|
+
Object.assign(paths, {
|
|
21
|
+
projects: files.projects,
|
|
22
|
+
backups: files.backups,
|
|
23
|
+
exports: files.exports,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
14
26
|
export function ensureDirs(paths, options) {
|
|
15
|
-
|
|
27
|
+
ensureDataDirs(paths, options);
|
|
28
|
+
ensureOwnerOnly([paths.projects], options);
|
|
29
|
+
}
|
|
30
|
+
// The data dir's own folders, before it is known where the user-visible files go.
|
|
31
|
+
export function ensureDataDirs(paths, options) {
|
|
32
|
+
ensureOwnerOnly([paths.dataDir, paths.staging, paths.logs], options);
|
|
33
|
+
}
|
|
34
|
+
function ensureOwnerOnly(dirs, options) {
|
|
35
|
+
for (const dir of dirs) {
|
|
16
36
|
mkdirSync(dir, { recursive: true, mode: options.mode });
|
|
17
37
|
// mkdir's mode is masked by the umask and ignored for a directory that already
|
|
18
38
|
// exists; provider keys sit in this tree, so the mode has to be forced.
|
|
@@ -20,7 +40,8 @@ export function ensureDirs(paths, options) {
|
|
|
20
40
|
}
|
|
21
41
|
}
|
|
22
42
|
// The subtitle-timing model's cache. The app readies it at start and every captioned render
|
|
23
|
-
// reads it, so both name it through here.
|
|
24
|
-
|
|
25
|
-
|
|
43
|
+
// reads it, so both name it through here. Other languages use the multilingual model, kept
|
|
44
|
+
// in a folder of its own and downloaded on first use, never at start.
|
|
45
|
+
export function subtitleModelDir(dataDir, language = "en") {
|
|
46
|
+
return join(dataDir, "models", language === "en" ? "english-subtitles" : "multilingual-subtitles");
|
|
26
47
|
}
|
package/dist/kernel/pipeline.js
CHANGED
|
@@ -24,12 +24,15 @@ export const stageStates = [
|
|
|
24
24
|
"skipped",
|
|
25
25
|
];
|
|
26
26
|
// A persisted pause overrides the stage-derived status. A completed run need not
|
|
27
|
-
// include a video: all selected stages being satisfied is enough.
|
|
27
|
+
// include a video: all selected stages being satisfied is enough. `partial` is a run whose
|
|
28
|
+
// main output was made while another step failed (the video is there, its thumbnail is
|
|
29
|
+
// not): done with problems, not failed.
|
|
28
30
|
export const projectStates = [
|
|
29
31
|
"running",
|
|
30
32
|
"paused",
|
|
31
33
|
"canceled",
|
|
32
34
|
"failed",
|
|
35
|
+
"partial",
|
|
33
36
|
"done",
|
|
34
37
|
"pending",
|
|
35
38
|
];
|
|
@@ -5,7 +5,20 @@ import { llmDocumentsSchema } from "./llm-documents.js";
|
|
|
5
5
|
import { providerErrorKinds } from "./model.js";
|
|
6
6
|
export const hostLlmIds = ["claude-code", "codex", "gemini"];
|
|
7
7
|
export const hostCliIds = [...hostLlmIds, "codex-image"];
|
|
8
|
+
// The health answer's protocol stays 1: both sides read it as an exact value, so bumping it
|
|
9
|
+
// would lock an older app out of a newer helper and the other way round. Richer stream frames
|
|
10
|
+
// are negotiated per request instead, with `hostFramesHeader`.
|
|
8
11
|
export const hostCliProtocol = 1;
|
|
12
|
+
// Sent by the app on every LLM request: the frame version it can read. A helper puts the
|
|
13
|
+
// cached-token count, the answering model and the plan windows on the `done` frame only when
|
|
14
|
+
// this says 2 or more, because an app from before them rejects any field it does not know.
|
|
15
|
+
// An older helper ignores the header and sends the plain frame, which reads as "not reported".
|
|
16
|
+
export const hostFramesHeader = "x-slopify-frames";
|
|
17
|
+
export const hostFramesVersion = 2;
|
|
18
|
+
// What the Codex CLI reported spending on a bridged image (its tokens and plan windows), as
|
|
19
|
+
// base64url JSON. A header rather than a body change, so an older app just ignores it and a
|
|
20
|
+
// newer app reads a missing one as "not reported".
|
|
21
|
+
export const hostImageReportHeader = "x-slopify-image-report";
|
|
9
22
|
export const bridgeLimits = {
|
|
10
23
|
request: 16 * 1024 * 1024,
|
|
11
24
|
status: 64 * 1024,
|
|
@@ -39,6 +52,15 @@ export const hostLlmSchema = z
|
|
|
39
52
|
webSearch: z.boolean().optional(),
|
|
40
53
|
})
|
|
41
54
|
.strict();
|
|
55
|
+
const bridgedImage = z
|
|
56
|
+
.object({
|
|
57
|
+
mime: z.enum(["image/png", "image/jpeg"]),
|
|
58
|
+
base64: z
|
|
59
|
+
.string()
|
|
60
|
+
.max(Math.ceil(bridgeLimits.reference / 3) * 4)
|
|
61
|
+
.regex(/^[A-Za-z0-9+/]*={0,2}$/),
|
|
62
|
+
})
|
|
63
|
+
.strict();
|
|
42
64
|
export const hostImageSchema = z
|
|
43
65
|
.object({
|
|
44
66
|
// "codex-imagegen" is the Codex default; any other is one of the Codex CLI's models.
|
|
@@ -57,6 +79,18 @@ export const hostImageSchema = z
|
|
|
57
79
|
})
|
|
58
80
|
.strict()
|
|
59
81
|
.optional(),
|
|
82
|
+
// The cast members the brief mentions, with their pictures (`ImageRequest.cast`); the
|
|
83
|
+
// whole request still has to fit `bridgeLimits.request`.
|
|
84
|
+
cast: z
|
|
85
|
+
.array(z
|
|
86
|
+
.object({
|
|
87
|
+
name: z.string().min(1).max(200),
|
|
88
|
+
description: z.string().max(2000),
|
|
89
|
+
images: z.array(bridgedImage).min(1).max(4),
|
|
90
|
+
})
|
|
91
|
+
.strict())
|
|
92
|
+
.max(4)
|
|
93
|
+
.optional(),
|
|
60
94
|
})
|
|
61
95
|
.strict();
|
|
62
96
|
export const hostOpenFolderSchema = z
|
|
@@ -102,25 +136,99 @@ export const hostHealthSchema = z
|
|
|
102
136
|
accepting: z.boolean(),
|
|
103
137
|
})
|
|
104
138
|
.strict();
|
|
105
|
-
|
|
106
|
-
|
|
139
|
+
// Faults and frames are read leniently: a field this side does not know is dropped, never an
|
|
140
|
+
// error, so a newer helper can add optional fields without breaking this app. (Apps before
|
|
141
|
+
// frame version 2 read them strictly, which is why the helper asks before adding any.)
|
|
142
|
+
export const hostFaultSchema = z.object({
|
|
107
143
|
type: z.literal("error"),
|
|
108
144
|
kind: z.enum(providerErrorKinds),
|
|
109
145
|
message: z.string().max(4096),
|
|
110
|
-
})
|
|
111
|
-
|
|
146
|
+
});
|
|
147
|
+
const limitWindowSchema = z.object({
|
|
148
|
+
kind: z.enum(["five_hour", "weekly", "other"]),
|
|
149
|
+
usedPercent: z.number().min(0).max(1_000_000),
|
|
150
|
+
resetsAt: z.string().max(64).nullable(),
|
|
151
|
+
});
|
|
152
|
+
const limitWindowsSchema = z.array(limitWindowSchema).max(16);
|
|
153
|
+
const planLimitReadingSchema = z.object({
|
|
154
|
+
before: limitWindowsSchema.optional(),
|
|
155
|
+
after: limitWindowsSchema.optional(),
|
|
156
|
+
});
|
|
157
|
+
const usageSchema = z.object({
|
|
158
|
+
inputTokens: z.number().nonnegative(),
|
|
159
|
+
outputTokens: z.number().nonnegative(),
|
|
160
|
+
// Frame version 2 on; an older helper never sends them.
|
|
161
|
+
cachedInputTokens: z.number().nonnegative().optional(),
|
|
162
|
+
model: short.optional(),
|
|
163
|
+
});
|
|
112
164
|
export const hostFrameSchema = z.discriminatedUnion("type", [
|
|
113
|
-
z.object({ type: z.literal("delta"), text: z.string().max(bridgeLimits.frame) })
|
|
114
|
-
z.object({ type: z.literal("activity") })
|
|
115
|
-
z
|
|
116
|
-
.object({
|
|
165
|
+
z.object({ type: z.literal("delta"), text: z.string().max(bridgeLimits.frame) }),
|
|
166
|
+
z.object({ type: z.literal("activity") }),
|
|
167
|
+
z.object({
|
|
117
168
|
type: z.literal("done"),
|
|
118
|
-
usage:
|
|
119
|
-
.object({ inputTokens: z.number().nonnegative(), outputTokens: z.number().nonnegative() })
|
|
120
|
-
.strict()
|
|
121
|
-
.nullable(),
|
|
169
|
+
usage: usageSchema.nullable(),
|
|
122
170
|
finishReason: z.string().max(256).nullable(),
|
|
123
|
-
|
|
124
|
-
.
|
|
171
|
+
// Frame version 2 on.
|
|
172
|
+
limits: planLimitReadingSchema.optional(),
|
|
173
|
+
}),
|
|
125
174
|
hostFaultSchema,
|
|
126
175
|
]);
|
|
176
|
+
// The `done` frame the helper sends to an app that reads frame `version`. Version 1 is the
|
|
177
|
+
// original shape exactly; version 2 adds what the CLI reported, each part kept only when it is
|
|
178
|
+
// well formed so one odd value never costs the answer.
|
|
179
|
+
export function hostDoneFrame(event, version) {
|
|
180
|
+
const plain = event.usage === null
|
|
181
|
+
? null
|
|
182
|
+
: { inputTokens: event.usage.inputTokens, outputTokens: event.usage.outputTokens };
|
|
183
|
+
if (!(version >= 2))
|
|
184
|
+
return { type: "done", usage: plain, finishReason: event.finishReason };
|
|
185
|
+
const cached = z.number().nonnegative().safeParse(event.usage?.cachedInputTokens);
|
|
186
|
+
const model = short.safeParse(event.usage?.model);
|
|
187
|
+
const limits = planLimitReadingSchema.safeParse(event.limits);
|
|
188
|
+
return {
|
|
189
|
+
type: "done",
|
|
190
|
+
usage: plain === null
|
|
191
|
+
? null
|
|
192
|
+
: {
|
|
193
|
+
...plain,
|
|
194
|
+
...(cached.success ? { cachedInputTokens: cached.data } : {}),
|
|
195
|
+
...(model.success ? { model: model.data } : {}),
|
|
196
|
+
},
|
|
197
|
+
finishReason: event.finishReason,
|
|
198
|
+
...(event.limits !== undefined && limits.success ? { limits: limits.data } : {}),
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
const imageReportSchema = z.object({
|
|
202
|
+
usage: usageSchema.optional(),
|
|
203
|
+
limits: planLimitReadingSchema.optional(),
|
|
204
|
+
});
|
|
205
|
+
// The image report header's value, or undefined when there is nothing well formed to report.
|
|
206
|
+
export function encodeHostImageReport(image) {
|
|
207
|
+
const report = imageReportSchema.safeParse({
|
|
208
|
+
...(image.usage === undefined ? {} : { usage: image.usage }),
|
|
209
|
+
...(image.limits === undefined ? {} : { limits: image.limits }),
|
|
210
|
+
});
|
|
211
|
+
if (!report.success || (report.data.usage === undefined && report.data.limits === undefined))
|
|
212
|
+
return undefined;
|
|
213
|
+
const value = Buffer.from(JSON.stringify(report.data)).toString("base64url");
|
|
214
|
+
// Well inside Node's 16 KB header allowance; a larger report is dropped, never the image.
|
|
215
|
+
return value.length > 8192 ? undefined : value;
|
|
216
|
+
}
|
|
217
|
+
// The usage and plan windows a helper sent beside an image: empty when it sent none (an older
|
|
218
|
+
// helper) or something unreadable, which only costs the report.
|
|
219
|
+
export function decodeHostImageReport(value) {
|
|
220
|
+
if (typeof value !== "string" || value.length > 8192)
|
|
221
|
+
return {};
|
|
222
|
+
try {
|
|
223
|
+
const report = imageReportSchema.safeParse(JSON.parse(Buffer.from(value, "base64url").toString("utf8")));
|
|
224
|
+
if (!report.success)
|
|
225
|
+
return {};
|
|
226
|
+
return {
|
|
227
|
+
...(report.data.usage === undefined ? {} : { usage: report.data.usage }),
|
|
228
|
+
...(report.data.limits === undefined ? {} : { limits: report.data.limits }),
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
catch {
|
|
232
|
+
return {};
|
|
233
|
+
}
|
|
234
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
// The language a project is made in: what the LLM writes, what the voice speaks, how the
|
|
3
|
+
// narration is split into sentences and how the captions are timed. Absent on every run
|
|
4
|
+
// config, draft, template and channel saved before it existed, and absent is English, so
|
|
5
|
+
// nothing about those changes. Only a language other than English is ever stored.
|
|
6
|
+
export const writingSystems = [
|
|
7
|
+
"latin",
|
|
8
|
+
"cyrillic",
|
|
9
|
+
"greek",
|
|
10
|
+
"arabic",
|
|
11
|
+
"hebrew",
|
|
12
|
+
"devanagari",
|
|
13
|
+
"thai",
|
|
14
|
+
"cjk",
|
|
15
|
+
"hangul",
|
|
16
|
+
];
|
|
17
|
+
export const languageList = [
|
|
18
|
+
{ code: "en", name: "English", native: "English", script: "latin", timing: "english" },
|
|
19
|
+
{ code: "es", name: "Spanish", native: "Español", script: "latin", timing: "multilingual" },
|
|
20
|
+
{ code: "de", name: "German", native: "Deutsch", script: "latin", timing: "multilingual" },
|
|
21
|
+
{ code: "fr", name: "French", native: "Français", script: "latin", timing: "multilingual" },
|
|
22
|
+
{ code: "it", name: "Italian", native: "Italiano", script: "latin", timing: "multilingual" },
|
|
23
|
+
{ code: "pt", name: "Portuguese", native: "Português", script: "latin", timing: "multilingual" },
|
|
24
|
+
{ code: "nl", name: "Dutch", native: "Nederlands", script: "latin", timing: "multilingual" },
|
|
25
|
+
{ code: "ca", name: "Catalan", native: "Català", script: "latin", timing: "multilingual" },
|
|
26
|
+
{ code: "pl", name: "Polish", native: "Polski", script: "latin", timing: "multilingual" },
|
|
27
|
+
{ code: "cs", name: "Czech", native: "Čeština", script: "latin", timing: "multilingual" },
|
|
28
|
+
{ code: "ro", name: "Romanian", native: "Română", script: "latin", timing: "sentences" },
|
|
29
|
+
{ code: "sv", name: "Swedish", native: "Svenska", script: "latin", timing: "sentences" },
|
|
30
|
+
{ code: "da", name: "Danish", native: "Dansk", script: "latin", timing: "sentences" },
|
|
31
|
+
{ code: "nb", name: "Norwegian", native: "Norsk bokmål", script: "latin", timing: "sentences" },
|
|
32
|
+
{ code: "fi", name: "Finnish", native: "Suomi", script: "latin", timing: "sentences" },
|
|
33
|
+
{ code: "hu", name: "Hungarian", native: "Magyar", script: "latin", timing: "sentences" },
|
|
34
|
+
{ code: "tr", name: "Turkish", native: "Türkçe", script: "latin", timing: "sentences" },
|
|
35
|
+
{
|
|
36
|
+
code: "id",
|
|
37
|
+
name: "Indonesian",
|
|
38
|
+
native: "Bahasa Indonesia",
|
|
39
|
+
script: "latin",
|
|
40
|
+
timing: "sentences",
|
|
41
|
+
},
|
|
42
|
+
{ code: "vi", name: "Vietnamese", native: "Tiếng Việt", script: "latin", timing: "sentences" },
|
|
43
|
+
{ code: "el", name: "Greek", native: "Ελληνικά", script: "greek", timing: "sentences" },
|
|
44
|
+
{ code: "ru", name: "Russian", native: "Русский", script: "cyrillic", timing: "sentences" },
|
|
45
|
+
{ code: "uk", name: "Ukrainian", native: "Українська", script: "cyrillic", timing: "sentences" },
|
|
46
|
+
{ code: "ar", name: "Arabic", native: "العربية", script: "arabic", timing: "sentences" },
|
|
47
|
+
{ code: "he", name: "Hebrew", native: "עברית", script: "hebrew", timing: "sentences" },
|
|
48
|
+
{ code: "hi", name: "Hindi", native: "हिन्दी", script: "devanagari", timing: "sentences" },
|
|
49
|
+
{ code: "th", name: "Thai", native: "ไทย", script: "thai", timing: "sentences" },
|
|
50
|
+
{ code: "ja", name: "Japanese", native: "日本語", script: "cjk", timing: "sentences" },
|
|
51
|
+
{ code: "zh", name: "Chinese", native: "中文", script: "cjk", timing: "sentences" },
|
|
52
|
+
{ code: "ko", name: "Korean", native: "한국어", script: "hangul", timing: "sentences" },
|
|
53
|
+
];
|
|
54
|
+
export const languageCodes = languageList.map((language) => language.code);
|
|
55
|
+
export const defaultLanguage = "en";
|
|
56
|
+
export const languageSchema = z.enum(languageCodes);
|
|
57
|
+
export function languageInfo(code) {
|
|
58
|
+
return (languageList.find((language) => language.code === (code ?? defaultLanguage)) ?? languageList[0]);
|
|
59
|
+
}
|
|
60
|
+
// The project's language; absent is English.
|
|
61
|
+
export function projectLanguage(config) {
|
|
62
|
+
return config.language ?? defaultLanguage;
|
|
63
|
+
}
|
|
64
|
+
export function isEnglish(config) {
|
|
65
|
+
return projectLanguage(config) === defaultLanguage;
|
|
66
|
+
}
|
|
67
|
+
// The line added to every prompt that writes for the audience, when the project is not in
|
|
68
|
+
// English. It is the app's own sentence, added after the user's prompt rather than written
|
|
69
|
+
// into it, so the prompt library stays as the user wrote it; an English project gets nothing,
|
|
70
|
+
// and its requests (and their fingerprints) stay exactly as they were.
|
|
71
|
+
export function languageInstruction(language) {
|
|
72
|
+
if (language === undefined || language === defaultLanguage)
|
|
73
|
+
return undefined;
|
|
74
|
+
const { name, native } = languageInfo(language);
|
|
75
|
+
return `Language: write everything meant for the audience (article, narration, titles, descriptions, chapter names, hashtags and tags) in ${name} (${native}), even where the instructions above are written in English. Keep JSON keys, markup and any heading or label the instructions say to use exactly as given.`;
|
|
76
|
+
}
|
|
77
|
+
// The messages with the language line added: to the system message when there is one, since
|
|
78
|
+
// the last user message is sometimes the source text itself; otherwise to the end of the last
|
|
79
|
+
// user message. English returns the very same messages.
|
|
80
|
+
export function withLanguage(messages, language) {
|
|
81
|
+
const instruction = languageInstruction(language);
|
|
82
|
+
if (instruction === undefined)
|
|
83
|
+
return messages;
|
|
84
|
+
const system = messages.findIndex((message) => message.role === "system");
|
|
85
|
+
const target = system !== -1 ? system : messages.findLastIndex((message) => message.role === "user");
|
|
86
|
+
if (target === -1)
|
|
87
|
+
return messages;
|
|
88
|
+
return messages.map((message, index) => index === target ? { ...message, content: `${message.content}\n\n${instruction}` } : message);
|
|
89
|
+
}
|
|
90
|
+
// Why word-by-word features are off in a language timed by sentences, or undefined when they
|
|
91
|
+
// are available. The same sentence is shown beside every control it turns off.
|
|
92
|
+
export function wordTimingUnavailable(code) {
|
|
93
|
+
const language = languageInfo(code);
|
|
94
|
+
if (language.timing !== "sentences")
|
|
95
|
+
return undefined;
|
|
96
|
+
return `Word timing isn't available for ${language.name} yet, so captions are timed sentence by sentence: each sentence is shown for the part of the narration that reads it. Word-by-word captions and cuts that follow the narration need word timing and are off.`;
|
|
97
|
+
}
|
|
98
|
+
// The letters a caption font needs for a language: its alphabet beyond a–z, or a sample of
|
|
99
|
+
// its script. A font missing any of them draws empty boxes in that language's captions.
|
|
100
|
+
const extraLetters = {
|
|
101
|
+
es: "áéíóúüñ¿¡",
|
|
102
|
+
de: "äöüß",
|
|
103
|
+
fr: "àâæçèéêëîïôœùûüÿ",
|
|
104
|
+
it: "àèéìíîòóù",
|
|
105
|
+
pt: "áâãàçéêíóôõú",
|
|
106
|
+
ca: "àèéíïòóúüç·",
|
|
107
|
+
nl: "éëïóöü",
|
|
108
|
+
pl: "ąćęłńóśźż",
|
|
109
|
+
cs: "áčďéěíňóřšťúůýž",
|
|
110
|
+
ro: "ăâîșț",
|
|
111
|
+
sv: "åäö",
|
|
112
|
+
da: "æøå",
|
|
113
|
+
nb: "æøå",
|
|
114
|
+
fi: "äö",
|
|
115
|
+
hu: "áéíóöőúüű",
|
|
116
|
+
tr: "çğıöşü",
|
|
117
|
+
vi: "ăâđêôơưạảấầẩẫậắằẳẵặẹẻẽếềểễệỉịọỏốồổỗộớờởỡợụủứừửữựỳỵỷỹ",
|
|
118
|
+
el: "αβγδεζηθικλμνξοπρστυφχψωάέήίόύώΑΩ",
|
|
119
|
+
ru: "абвгдеёжзийклмнопрстуфхцчшщъыьэюяАЯ",
|
|
120
|
+
uk: "абвгґдеєжзиіїйклмнопрстуфхцчшщьюяАЯ",
|
|
121
|
+
ar: "ابتثجحخدذرزسشصضطظعغفقكلمنهوي",
|
|
122
|
+
he: "אבגדהוזחטיכלמנסעפצקרשת",
|
|
123
|
+
hi: "अआइईउऊएऐओऔकखगघचछजझटठडढणतथदधनपफबभमयरलवशषसह",
|
|
124
|
+
th: "กขคงจฉชซญดตถทนบปผพฟภมยรลวสหอฮ",
|
|
125
|
+
ja: "あいうえおかきくけこアイウエオ日本語",
|
|
126
|
+
zh: "的一是不了人我在有他这中大来上国个到说们为子和你地出道也时年",
|
|
127
|
+
ko: "가나다라마바사아자차카타파하한국어",
|
|
128
|
+
};
|
|
129
|
+
export function languageLetters(code) {
|
|
130
|
+
const info = languageInfo(code);
|
|
131
|
+
const letters = `${info.script === "latin" ? "abcdefghijklmnopqrstuvwxyz" : ""}${extraLetters[info.code] ?? ""}`;
|
|
132
|
+
return [...new Set(Array.from(letters, (letter) => letter.codePointAt(0) ?? 0))];
|
|
133
|
+
}
|
|
134
|
+
// Whether a codepoint belongs to a writing system; used to decide whether a caption font
|
|
135
|
+
// covers the project's letters without reading the font for every character.
|
|
136
|
+
export function writingSystemOf(codepoint) {
|
|
137
|
+
const inRange = (from, to) => codepoint >= from && codepoint <= to;
|
|
138
|
+
if (inRange(0x41, 0x5a) || inRange(0x61, 0x7a) || inRange(0xc0, 0x24f) || inRange(0x1e00, 0x1eff))
|
|
139
|
+
return "latin";
|
|
140
|
+
if (inRange(0x370, 0x3ff) || inRange(0x1f00, 0x1fff))
|
|
141
|
+
return "greek";
|
|
142
|
+
if (inRange(0x400, 0x52f))
|
|
143
|
+
return "cyrillic";
|
|
144
|
+
if (inRange(0x590, 0x5ff))
|
|
145
|
+
return "hebrew";
|
|
146
|
+
if (inRange(0x600, 0x6ff) || inRange(0x750, 0x77f) || inRange(0xfb50, 0xfdff))
|
|
147
|
+
return "arabic";
|
|
148
|
+
if (inRange(0x900, 0x97f))
|
|
149
|
+
return "devanagari";
|
|
150
|
+
if (inRange(0xe00, 0xe7f))
|
|
151
|
+
return "thai";
|
|
152
|
+
if (inRange(0x1100, 0x11ff) || inRange(0xac00, 0xd7af))
|
|
153
|
+
return "hangul";
|
|
154
|
+
if (inRange(0x3040, 0x30ff) || inRange(0x3400, 0x4dbf) || inRange(0x4e00, 0x9fff))
|
|
155
|
+
return "cjk";
|
|
156
|
+
return undefined;
|
|
157
|
+
}
|
|
@@ -2,20 +2,24 @@
|
|
|
2
2
|
// shape never leaves its adapter.
|
|
3
3
|
export const providerFamilies = ["llm", "tts", "image"];
|
|
4
4
|
export function readinessIsUsable(readiness) {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
if (readiness.kind === "keyed")
|
|
6
|
+
return readiness.hasKey;
|
|
7
|
+
if (readiness.kind === "local")
|
|
8
|
+
return readiness.available;
|
|
9
|
+
return readiness.installed && readiness.issue === undefined;
|
|
8
10
|
}
|
|
9
11
|
export const providerErrorKinds = [
|
|
12
|
+
// A key the provider rejected. Like an absent one it fails at once: no wait fixes it.
|
|
10
13
|
"auth",
|
|
11
|
-
// Distinct from `auth`, a key the provider rejected: a bad key runs the whole retry
|
|
12
|
-
// policy, an absent one fails immediately.
|
|
13
14
|
"missing_key",
|
|
14
15
|
"unavailable",
|
|
15
16
|
"rate_limit",
|
|
16
17
|
"refusal",
|
|
17
18
|
"unsupported",
|
|
18
19
|
"timeout",
|
|
20
|
+
// The connection, the provider's server or the CLI process went away before an answer:
|
|
21
|
+
// nothing says the request itself was wrong, so it is worth sending again later.
|
|
22
|
+
"dropped",
|
|
19
23
|
"other",
|
|
20
24
|
];
|
|
21
25
|
export function providerError(init) {
|
|
@@ -23,6 +27,7 @@ export function providerError(init) {
|
|
|
23
27
|
fault: {
|
|
24
28
|
kind: init.kind,
|
|
25
29
|
...(init.retryAfterMs === undefined ? {} : { retryAfterMs: init.retryAfterMs }),
|
|
30
|
+
...(init.planLimit === undefined ? {} : { planLimit: init.planLimit }),
|
|
26
31
|
},
|
|
27
32
|
});
|
|
28
33
|
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// Narration aliases: a written word or phrase and how the narrator should say it ("Dr." as
|
|
2
|
+
// "Doctor"). They change only what is sent to the voice (and to Narration Preparation);
|
|
3
|
+
// the article, the transcript and the captions keep the written form. The same matcher runs
|
|
4
|
+
// where the text is narrated and where captions are timed against that narration, so both
|
|
5
|
+
// agree on which words were said differently. It lives with the ports because the caption
|
|
6
|
+
// aligner (an adapter, which may import only ports) needs it as much as the recipes do.
|
|
7
|
+
export const aliasWrittenMax = 200;
|
|
8
|
+
export const aliasSpokenMax = 500;
|
|
9
|
+
export const aliasCountMax = 1000;
|
|
10
|
+
const wordCharacter = /[\p{L}\p{M}\p{N}_]/u;
|
|
11
|
+
// Every place an alias applies: leftmost first, the longest written form where two start at
|
|
12
|
+
// the same place, never overlapping.
|
|
13
|
+
export function aliasMatches(text, aliases) {
|
|
14
|
+
const found = [];
|
|
15
|
+
for (const alias of aliases) {
|
|
16
|
+
const written = alias.written.trim();
|
|
17
|
+
if (written === "")
|
|
18
|
+
continue;
|
|
19
|
+
const pattern = written
|
|
20
|
+
.split(/\s+/u)
|
|
21
|
+
.map((word) => word.replace(/[|\\{}()[\]^$+*?.]/gu, "\\$&"))
|
|
22
|
+
.join("\\s+");
|
|
23
|
+
const expression = new RegExp(pattern, alias.caseSensitive ? "gu" : "giu");
|
|
24
|
+
const first = Array.from(written)[0] ?? "";
|
|
25
|
+
const last = Array.from(written).at(-1) ?? "";
|
|
26
|
+
for (const match of text.matchAll(expression)) {
|
|
27
|
+
const start = match.index;
|
|
28
|
+
const end = start + match[0].length;
|
|
29
|
+
if (alias.wholeWord) {
|
|
30
|
+
const before = Array.from(text.slice(Math.max(0, start - 2), start)).at(-1) ?? "";
|
|
31
|
+
const after = Array.from(text.slice(end, end + 2))[0] ?? "";
|
|
32
|
+
if (wordCharacter.test(first) && wordCharacter.test(before))
|
|
33
|
+
continue;
|
|
34
|
+
if (wordCharacter.test(last) && wordCharacter.test(after))
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
found.push({ start, end, spoken: alias.spoken });
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
found.sort((a, b) => a.start - b.start || b.end - a.end);
|
|
41
|
+
const chosen = [];
|
|
42
|
+
let reached = 0;
|
|
43
|
+
for (const match of found) {
|
|
44
|
+
if (match.start < reached)
|
|
45
|
+
continue;
|
|
46
|
+
chosen.push(match);
|
|
47
|
+
reached = match.end;
|
|
48
|
+
}
|
|
49
|
+
return chosen;
|
|
50
|
+
}
|
|
51
|
+
// The same text as the narrator should read it.
|
|
52
|
+
export function applyAliases(text, aliases) {
|
|
53
|
+
let out = "";
|
|
54
|
+
let at = 0;
|
|
55
|
+
for (const match of aliasMatches(text, aliases)) {
|
|
56
|
+
out += text.slice(at, match.start) + match.spoken;
|
|
57
|
+
at = match.end;
|
|
58
|
+
}
|
|
59
|
+
return out + text.slice(at);
|
|
60
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// The plan limits of the command-line agents: Claude Code, Codex and Gemini are billed to
|
|
2
|
+
// the user's subscription, which gives them a share of a 5-hour and a weekly allowance rather
|
|
3
|
+
// than a bill. Only what a CLI reports is ever recorded here; nothing is estimated.
|
|
4
|
+
// The subscription a CLI provider draws on. Codex text and Codex images share one login and
|
|
5
|
+
// so one allowance.
|
|
6
|
+
export const planAccounts = ["claude-code", "codex", "gemini"];
|
|
7
|
+
export function planAccountOf(provider) {
|
|
8
|
+
if (provider === "claude-code")
|
|
9
|
+
return "claude-code";
|
|
10
|
+
if (provider === "codex" || provider === "codex-image")
|
|
11
|
+
return "codex";
|
|
12
|
+
if (provider === "gemini")
|
|
13
|
+
return "gemini";
|
|
14
|
+
return undefined;
|
|
15
|
+
}
|
|
16
|
+
export const planAccountNames = {
|
|
17
|
+
"claude-code": "Claude",
|
|
18
|
+
codex: "Codex",
|
|
19
|
+
gemini: "Gemini",
|
|
20
|
+
};
|
|
21
|
+
// A window of `minutes` length, named the way the screens name it.
|
|
22
|
+
export function windowKindOf(minutes) {
|
|
23
|
+
if (minutes === 300)
|
|
24
|
+
return "five_hour";
|
|
25
|
+
if (minutes === 10_080)
|
|
26
|
+
return "weekly";
|
|
27
|
+
return "other";
|
|
28
|
+
}
|
|
29
|
+
// Epoch seconds or milliseconds to ISO, null for anything that is not a plausible time.
|
|
30
|
+
export function isoOfEpoch(value) {
|
|
31
|
+
if (value === null || value === undefined || !Number.isFinite(value) || value <= 0)
|
|
32
|
+
return null;
|
|
33
|
+
const ms = value < 1e12 ? value * 1000 : value;
|
|
34
|
+
const date = new Date(ms);
|
|
35
|
+
return Number.isNaN(date.getTime()) ? null : date.toISOString();
|
|
36
|
+
}
|