@gentbajko/slopify 3.25.9 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/account-limits.js +30 -0
- package/dist/adapters/alignment/audio.js +1 -1
- package/dist/adapters/alignment/cache.js +4 -6
- package/dist/adapters/alignment/ctc.js +1 -2
- package/dist/adapters/alignment/lock.js +4 -3
- package/dist/adapters/alignment/multilingual.js +2 -4
- package/dist/adapters/alignment/prefetch.js +2 -1
- package/dist/adapters/alignment/runner.js +1 -1
- package/dist/adapters/alignment/worker.js +3 -2
- package/dist/adapters/explain.js +10 -12
- package/dist/adapters/ffmpeg.js +19 -1
- package/dist/adapters/host-cli/index.js +21 -4
- package/dist/adapters/host-cli/transport.js +2 -1
- package/dist/adapters/http-failure.js +53 -0
- package/dist/adapters/image/bytes.js +2 -1
- package/dist/adapters/image/codex.js +42 -9
- package/dist/adapters/image/fal.js +21 -53
- package/dist/adapters/image/google.js +33 -56
- package/dist/adapters/image/models.js +2 -2
- package/dist/adapters/image/openai.js +22 -48
- package/dist/adapters/image/reference.js +36 -0
- package/dist/adapters/image/replicate.js +21 -49
- package/dist/adapters/image/video.js +2 -1
- package/dist/adapters/interest/search-interest.js +113 -0
- package/dist/adapters/key-probes.js +54 -3
- package/dist/adapters/llm/antigravity-models.js +1 -1
- package/dist/adapters/llm/antigravity.js +11 -6
- package/dist/adapters/llm/assistant-cli.js +388 -0
- package/dist/adapters/llm/child-session.js +83 -0
- package/dist/adapters/llm/claude-code-models.js +52 -99
- package/dist/adapters/llm/claude-code.js +16 -4
- package/dist/adapters/llm/codex-limits.js +27 -68
- package/dist/adapters/llm/codex-models.js +1 -1
- package/dist/adapters/llm/codex-server-models.js +61 -109
- package/dist/adapters/llm/codex.js +12 -1
- package/dist/adapters/llm/document-workspace.js +3 -2
- package/dist/adapters/llm/image-workspace.js +3 -2
- package/dist/adapters/llm/openrouter.js +12 -48
- package/dist/adapters/llm/run-cli.js +9 -24
- package/dist/adapters/llm/sse-lines.js +5 -1
- package/dist/adapters/model-access.js +37 -0
- package/dist/adapters/tts/cartesia.js +15 -46
- package/dist/adapters/tts/elevenlabs.js +20 -52
- package/dist/adapters/tts/gemini.js +21 -41
- package/dist/adapters/tts/inworld-async.js +6 -2
- package/dist/adapters/tts/inworld.js +6 -2
- package/dist/adapters/tts/openai.js +20 -50
- package/dist/adapters/tts/system.js +2 -1
- package/dist/assets/models-lifecycle.yaml +6 -0
- package/dist/assistant-wiring.js +60 -0
- package/dist/autopilot-timers.js +59 -0
- package/dist/catalog/lifecycle.js +52 -0
- package/dist/catalog/propose.js +204 -0
- package/dist/catalog/registry.js +23 -14
- package/dist/catalog/schema.js +4 -1
- package/dist/catalog/store.js +39 -0
- package/dist/catalog/validate.js +5 -2
- package/dist/edge/autostart/native.js +3 -5
- package/dist/edge/autostart/prompt.js +2 -1
- package/dist/edge/autostart/service.js +3 -4
- package/dist/edge/cli-args.js +3 -4
- package/dist/edge/cli.js +2 -1
- package/dist/edge/docker-install/apply.js +11 -11
- package/dist/edge/docker-install/run.js +2 -1
- package/dist/edge/docker-install/state.js +4 -3
- package/dist/edge/docker-install/tree.js +2 -4
- package/dist/edge/docker-install/volume.js +3 -2
- package/dist/edge/docker.js +5 -4
- package/dist/edge/events/hub.js +5 -5
- package/dist/edge/http/actions.js +11 -32
- package/dist/edge/http/actor.js +5 -3
- package/dist/edge/http/app.js +86 -11
- package/dist/edge/http/assistant.js +129 -0
- package/dist/edge/http/audio-preview.js +4 -11
- package/dist/edge/http/auditions.js +1 -1
- package/dist/edge/http/autostart.js +5 -5
- package/dist/edge/http/backups.js +2 -4
- package/dist/edge/http/channel-memory.js +9 -22
- package/dist/edge/http/channels.js +14 -27
- package/dist/edge/http/checkpoints.js +39 -21
- package/dist/edge/http/design-templates.js +167 -0
- package/dist/edge/http/designs.js +178 -0
- package/dist/edge/http/diagnostics.js +5 -1
- package/dist/edge/http/document-themes.js +5 -14
- package/dist/edge/http/draft-files.js +1 -3
- package/dist/edge/http/draft-problem.js +5 -10
- package/dist/edge/http/drafts.js +3 -3
- package/dist/edge/http/entries.js +6 -9
- package/dist/edge/http/extension-auth.js +27 -0
- package/dist/edge/http/external-reviews.js +12 -11
- package/dist/edge/http/files.js +5 -11
- package/dist/edge/http/folder-location.js +1 -4
- package/dist/edge/http/fonts.js +0 -7
- package/dist/edge/http/home.js +47 -14
- package/dist/edge/http/host-cli.js +18 -8
- package/dist/edge/http/ids.js +8 -0
- package/dist/edge/http/keywords.js +35 -0
- package/dist/edge/http/model-checks.js +132 -0
- package/dist/edge/http/narration-peaks.js +5 -13
- package/dist/edge/http/onboarding.js +30 -26
- package/dist/edge/http/open-folder.js +5 -10
- package/dist/edge/http/outputs.js +7 -14
- package/dist/edge/http/patch-notes.js +6 -12
- package/dist/edge/http/planning.js +3 -7
- package/dist/edge/http/problem.js +2 -4
- package/dist/edge/http/project-create.js +2 -1
- package/dist/edge/http/project-templates.js +31 -19
- package/dist/edge/http/projects.js +24 -16
- package/dist/edge/http/prompts.js +9 -16
- package/dist/edge/http/pronunciations.js +1 -2
- package/dist/edge/http/providers.js +48 -34
- package/dist/edge/http/refusal.js +29 -0
- package/dist/edge/http/remote-access.js +40 -0
- package/dist/edge/http/remote-guard.js +71 -0
- package/dist/edge/http/request-guard.js +91 -0
- package/dist/edge/http/reviews.js +12 -25
- package/dist/edge/http/revision-files.js +6 -11
- package/dist/edge/http/revisions.js +14 -19
- package/dist/edge/http/run-cost.js +1 -2
- package/dist/edge/http/same-page.js +80 -0
- package/dist/edge/http/schedules.js +69 -40
- package/dist/edge/http/settings.js +27 -14
- package/dist/edge/http/social.js +283 -0
- package/dist/edge/http/staging.js +3 -5
- package/dist/edge/http/storage-files.js +5 -7
- package/dist/edge/http/storage.js +33 -25
- package/dist/edge/http/studio.js +94 -69
- package/dist/edge/http/style-preview.js +3 -6
- package/dist/edge/http/subtitles.js +3 -17
- package/dist/edge/http/template-studio.js +436 -0
- package/dist/edge/http/trash.js +11 -12
- package/dist/edge/http/tutorial.js +1 -2
- package/dist/edge/http/tutorials.js +5 -11
- package/dist/edge/http/update.js +7 -13
- package/dist/edge/http/waveform.js +3 -6
- package/dist/edge/http/youtube-edits.js +3 -4
- package/dist/edge/mcp/assistant.js +279 -0
- package/dist/edge/mcp/attribution.js +8 -2
- package/dist/edge/mcp/call-route.js +11 -2
- package/dist/edge/mcp/excluded-routes.js +29 -3
- package/dist/edge/mcp/http.js +11 -2
- package/dist/edge/mcp/instructions.js +6 -4
- package/dist/edge/mcp/library-tools.js +9 -5
- package/dist/edge/mcp/remake-tools.js +7 -4
- package/dist/edge/mcp/route-tool.js +35 -15
- package/dist/edge/mcp/server.js +13 -8
- package/dist/edge/mcp/tools-channels.js +11 -9
- package/dist/edge/mcp/tools-designs.js +165 -0
- package/dist/edge/mcp/tools-library.js +19 -7
- package/dist/edge/mcp/tools-planning.js +40 -21
- package/dist/edge/mcp/tools-projects.js +38 -11
- package/dist/edge/mcp/tools-publishing.js +9 -9
- package/dist/edge/mcp/tools-runs.js +23 -10
- package/dist/edge/mcp/tools-schedules.js +32 -8
- package/dist/edge/mcp/tools-setup.js +75 -11
- package/dist/edge/mcp/tools-social.js +47 -0
- package/dist/edge/mcp/tools-storage.js +11 -3
- package/dist/edge/mcp/tools-template-studio.js +166 -0
- package/dist/edge/mcp/tools.js +6 -0
- package/dist/edge/remote-access/cli.js +71 -0
- package/dist/edge/remote-access/model.js +32 -0
- package/dist/edge/remote-access/rules.js +207 -0
- package/dist/edge/remote-access/service.js +203 -0
- package/dist/edge/remote-access/store.js +44 -0
- package/dist/edge/remote-access/views.js +43 -0
- package/dist/extension/slopify-studio-chrome.zip +0 -0
- package/dist/extension/slopify-studio-firefox.zip +0 -0
- package/dist/host-cli/install.js +2 -2
- package/dist/host-cli/open-folder.js +2 -2
- package/dist/host-cli/paths.js +2 -4
- package/dist/host-cli/server.js +4 -4
- package/dist/host-cli/service.js +3 -3
- package/dist/host-cli/status.js +7 -7
- package/dist/kernel/db/migrations/0063-model-checks.sql +20 -0
- package/dist/kernel/db/migrations/0064-template-studio.sql +46 -0
- package/dist/kernel/db/migrations/0065-promise-and-assistant-reviews.sql +58 -0
- package/dist/kernel/db/migrations/0066-assistant.sql +44 -0
- package/dist/kernel/db/migrations/0067-autopilot.sql +6 -0
- package/dist/kernel/db/migrations/0068-topic-scores.sql +17 -0
- package/dist/kernel/db/migrations/0070-designs.sql +53 -0
- package/dist/kernel/db/migrations/0071-design-usage.sql +33 -0
- package/dist/kernel/db/migrations/0072-design-templates.sql +33 -0
- package/dist/kernel/db/migrations/0073-schedule-design-kind.sql +5 -0
- package/dist/kernel/db/migrations/0074-template-bakeoffs.sql +44 -0
- package/dist/kernel/db/migrations/0075-social-posts.sql +25 -0
- package/dist/kernel/db/migrations/0076-channel-social.sql +5 -0
- package/dist/kernel/db/migrations/0077-post-prompts.sql +17 -0
- package/dist/kernel/db/migrations/0078-uploaded-from-links.sql +7 -0
- package/dist/kernel/db/tx.js +2 -4
- package/dist/kernel/errors.js +27 -1
- package/dist/kernel/json-answer.js +15 -0
- package/dist/kernel/lock.js +4 -9
- package/dist/kernel/paths.js +8 -0
- package/dist/kernel/pipeline.js +12 -0
- package/dist/kernel/ports/assistant-cli.js +4 -0
- package/dist/kernel/ports/host-cli.js +3 -0
- package/dist/kernel/ports/interest.js +4 -0
- package/dist/kernel/ports/languages.js +0 -3
- package/dist/kernel/ports/model.js +2 -0
- package/dist/kernel/ports/settings-places.js +31 -0
- package/dist/kernel/ports/system-speech.js +31 -3
- package/dist/kernel/runner/attempt.js +14 -4
- package/dist/kernel/runner/audition.js +3 -1
- package/dist/kernel/runner/checkpoint-authority.js +2 -1
- package/dist/kernel/runner/index.js +8 -10
- package/dist/kernel/runner/model-access.js +40 -0
- package/dist/kernel/runner/model-check.js +153 -0
- package/dist/kernel/runner/providers.js +18 -12
- package/dist/kernel/runner/standalone.js +11 -7
- package/dist/main.js +338 -21
- package/dist/model-catalog.js +20 -0
- package/dist/model-checks.js +166 -0
- package/dist/patch-notes/4.0.0.md +51 -0
- package/dist/patch-notes/4.1.0.md +42 -0
- package/dist/patch-notes/index.json +12 -0
- package/dist/slices/admission/heads.js +2 -1
- package/dist/slices/admission/listing-facts.js +95 -0
- package/dist/slices/admission/repo.js +11 -7
- package/dist/slices/admission/rules.js +50 -15
- package/dist/slices/admission/schema.js +8 -0
- package/dist/slices/admission/stage-writes.js +0 -3
- package/dist/slices/admission/start.js +48 -31
- package/dist/slices/admission/state-words.js +34 -5
- package/dist/slices/admission/substitute.js +7 -4
- package/dist/slices/agents/attention-posts.js +31 -0
- package/dist/slices/agents/attention-templates.js +33 -0
- package/dist/slices/agents/attention.js +10 -1
- package/dist/slices/agents/connection.js +2 -6
- package/dist/slices/agents/model.js +6 -3
- package/dist/slices/agents/repo.js +15 -7
- package/dist/slices/article/continuation.js +0 -63
- package/dist/slices/article/plain.js +3 -2
- package/dist/slices/article/segments.js +2 -62
- package/dist/slices/assistant/access.js +1 -0
- package/dist/slices/assistant/asks.js +80 -0
- package/dist/slices/assistant/cost.js +54 -0
- package/dist/slices/assistant/gate.js +222 -0
- package/dist/slices/assistant/model.js +86 -0
- package/dist/slices/assistant/names.js +23 -0
- package/dist/slices/assistant/prompt.js +74 -0
- package/dist/slices/assistant/repo.js +74 -0
- package/dist/slices/assistant/tokens.js +18 -0
- package/dist/slices/assistant/turn.js +344 -0
- package/dist/slices/autopilot/buffer.js +76 -0
- package/dist/slices/autopilot/model.js +14 -0
- package/dist/slices/autopilot/notify.js +27 -0
- package/dist/slices/autopilot/repo.js +34 -0
- package/dist/slices/autopilot/signals.js +194 -0
- package/dist/slices/autopilot/warnings.js +85 -0
- package/dist/slices/autopilot/weekly.js +100 -0
- package/dist/slices/backups/files.js +2 -6
- package/dist/slices/backups/repo.js +3 -15
- package/dist/slices/backups/service.js +8 -7
- package/dist/slices/channels/cast-images.js +3 -2
- package/dist/slices/channels/model.js +0 -1
- package/dist/slices/channels/rebrand.js +0 -3
- package/dist/slices/channels/repo.js +4 -0
- package/dist/slices/channels/schema.js +7 -1
- package/dist/slices/channels/service.js +10 -0
- package/dist/slices/channels/videos.js +3 -15
- package/dist/slices/checkpoints/index.js +0 -1
- package/dist/slices/control/providers.js +2 -28
- package/dist/slices/designs/artwork.js +66 -0
- package/dist/slices/designs/budget.js +23 -0
- package/dist/slices/designs/calls.js +124 -0
- package/dist/slices/designs/check-context.js +38 -0
- package/dist/slices/designs/check-text.js +43 -0
- package/dist/slices/designs/fields.js +88 -0
- package/dist/slices/designs/frames.js +34 -0
- package/dist/slices/designs/gate.js +130 -0
- package/dist/slices/designs/layout.js +293 -0
- package/dist/slices/designs/model.js +35 -0
- package/dist/slices/designs/pdf-job.js +23 -0
- package/dist/slices/designs/pdf-pages.js +30 -0
- package/dist/slices/designs/pdf-runner.js +68 -0
- package/dist/slices/designs/pdf-worker.js +24 -0
- package/dist/slices/designs/picture-size.js +79 -0
- package/dist/slices/designs/pictures.js +55 -0
- package/dist/slices/designs/quote.js +24 -0
- package/dist/slices/designs/render-args.js +36 -0
- package/dist/slices/designs/render-input.js +59 -0
- package/dist/slices/designs/render.js +215 -0
- package/dist/slices/designs/repo.js +101 -0
- package/dist/slices/designs/requests.js +80 -0
- package/dist/slices/designs/runner.js +239 -0
- package/dist/slices/designs/sample-repo.js +91 -0
- package/dist/slices/designs/sample.js +223 -0
- package/dist/slices/designs/schema.js +87 -0
- package/dist/slices/designs/sections.js +44 -0
- package/dist/slices/designs/service.js +233 -0
- package/dist/slices/designs/steps-repo.js +102 -0
- package/dist/slices/designs/studio-kind.js +39 -0
- package/dist/slices/designs/template-checks.js +44 -0
- package/dist/slices/designs/template-make.js +118 -0
- package/dist/slices/designs/templates.js +218 -0
- package/dist/slices/document/fonts.js +2 -1
- package/dist/slices/document/model.js +7 -4
- package/dist/slices/document/render.js +2 -1
- package/dist/slices/document/theme-schema.js +1 -1
- package/dist/slices/document/theme.js +49 -3
- package/dist/slices/episodes/summarize.js +6 -2
- package/dist/slices/estimate/index.js +72 -28
- package/dist/slices/estimate/requests.js +4 -4
- package/dist/slices/fixes/rules.js +3 -1
- package/dist/slices/fonts/catalog.js +5 -3
- package/dist/slices/fonts/coverage.js +2 -1
- package/dist/slices/fonts/discovery.js +3 -2
- package/dist/slices/fonts/files.js +2 -6
- package/dist/slices/fonts/index.js +0 -1
- package/dist/slices/fonts/sfnt.js +45 -10
- package/dist/slices/images/appearance.js +8 -16
- package/dist/slices/images/scenes.js +102 -28
- package/dist/slices/keywords/digest.js +85 -0
- package/dist/slices/keywords/facts.js +92 -0
- package/dist/slices/keywords/fill.js +80 -0
- package/dist/slices/keywords/model.js +75 -0
- package/dist/slices/keywords/rules.js +187 -0
- package/dist/slices/keywords/schema.js +28 -0
- package/dist/slices/keywords/specs.js +260 -0
- package/dist/slices/keywords/values.js +74 -0
- package/dist/slices/library/lint.js +29 -12
- package/dist/slices/library/model.js +2 -0
- package/dist/slices/library/photorealistic.js +4 -12
- package/dist/slices/library/rename.js +9 -7
- package/dist/slices/library/save.js +14 -10
- package/dist/slices/library/slots.js +37 -11
- package/dist/slices/library/transfer.js +5 -4
- package/dist/slices/library/used-by.js +25 -10
- package/dist/slices/loudness/loudnorm.js +53 -12
- package/dist/slices/loudness/model.js +3 -2
- package/dist/slices/loudness/sentence-level.js +2 -1
- package/dist/slices/model-checks/cost.js +61 -0
- package/dist/slices/model-checks/listing.js +124 -0
- package/dist/slices/model-checks/model.js +20 -0
- package/dist/slices/model-checks/record.js +32 -0
- package/dist/slices/model-checks/repo.js +120 -0
- package/dist/slices/model-checks/rules.js +125 -0
- package/dist/slices/model-checks/run.js +143 -0
- package/dist/slices/model-checks/service.js +198 -0
- package/dist/slices/model-upkeep/model.js +1 -1
- package/dist/slices/model-upkeep/switch.js +72 -27
- package/dist/slices/model-upkeep/usage.js +39 -13
- package/dist/slices/narration/breaths.js +3 -1
- package/dist/slices/narration/clean-pieces.js +3 -1
- package/dist/slices/narration/concat.js +2 -1
- package/dist/slices/narration/pauses-model.js +3 -2
- package/dist/slices/narration/peaks.js +3 -4
- package/dist/slices/narration/pronunciation-chunks.js +4 -3
- package/dist/slices/narration/pronunciation.js +6 -4
- package/dist/slices/narration/steering.js +4 -3
- package/dist/slices/notifications/notifier.js +4 -3
- package/dist/slices/notifications/rules.js +5 -2
- package/dist/slices/notifications/settings.js +4 -12
- package/dist/slices/notifications/subject.js +4 -3
- package/dist/slices/onboarding/copy.js +21 -3
- package/dist/slices/onboarding/first-run.js +16 -40
- package/dist/slices/onboarding/full-video.js +3 -2
- package/dist/slices/onboarding/install.js +6 -4
- package/dist/slices/onboarding/model.js +26 -37
- package/dist/slices/onboarding/packs.js +22 -22
- package/dist/slices/onboarding/preferred-model.js +14 -0
- package/dist/slices/onboarding/quick-short.js +105 -65
- package/dist/slices/onboarding/sample.js +4 -2
- package/dist/slices/onboarding/state.js +9 -11
- package/dist/slices/onboarding/template.js +8 -6
- package/dist/slices/outputs/add.js +3 -2
- package/dist/slices/outputs/service.js +2 -2
- package/dist/slices/patch-notes/library.js +4 -3
- package/dist/slices/play-drafts/convert.js +4 -0
- package/dist/slices/play-drafts/readiness.js +3 -3
- package/dist/slices/play-drafts/review-inputs.js +9 -3
- package/dist/slices/play-drafts/review.js +5 -4
- package/dist/slices/play-drafts/schema.js +4 -0
- package/dist/slices/play-drafts/service.js +17 -7
- package/dist/slices/project-templates/from-project.js +9 -2
- package/dist/slices/project-templates/next-chapter.js +2 -1
- package/dist/slices/project-templates/provider-defaults.js +22 -0
- package/dist/slices/project-templates/repo.js +6 -1
- package/dist/slices/project-templates/setup-sections.js +26 -0
- package/dist/slices/project-templates/setup.js +14 -1
- package/dist/slices/project-templates/stand-ins.js +22 -0
- package/dist/slices/rebuild/activity.js +2 -0
- package/dist/slices/rebuild/admission-repo.js +3 -2
- package/dist/slices/rebuild/narration-history.js +4 -5
- package/dist/slices/rebuild/narration-retry.js +2 -1
- package/dist/slices/rebuild/preview-details.js +32 -14
- package/dist/slices/rebuild/preview-plan.js +3 -8
- package/dist/slices/rebuild/recipe-build.js +8 -3
- package/dist/slices/rebuild/recipe-describe.js +3 -3
- package/dist/slices/rebuild/recipe-digest.js +58 -0
- package/dist/slices/rebuild/recipe-input-schema.js +10 -0
- package/dist/slices/rebuild/recipe-keywords.js +71 -0
- package/dist/slices/rebuild/recipe-legacy.js +5 -1
- package/dist/slices/rebuild/recipe-model.js +4 -0
- package/dist/slices/rebuild/recipe-narration-text.js +2 -1
- package/dist/slices/rebuild/recipe-preparation.js +4 -4
- package/dist/slices/rebuild/recipe-reference.js +8 -4
- package/dist/slices/rebuild/recipe-reviews.js +27 -7
- package/dist/slices/rebuild/recipe-save.js +8 -5
- package/dist/slices/rebuild/recipe-scenes.js +40 -11
- package/dist/slices/rebuild/recipe-shorts.js +8 -8
- package/dist/slices/rebuild/recipe-social.js +46 -0
- package/dist/slices/rebuild/recipe-text.js +64 -20
- package/dist/slices/rebuild/recipe-validation.js +102 -31
- package/dist/slices/rebuild/recipe-visual.js +55 -16
- package/dist/slices/rebuild/recipe-voices.js +3 -2
- package/dist/slices/rebuild/recipe-work.js +19 -7
- package/dist/slices/rebuild/recipe-youtube.js +4 -3
- package/dist/slices/rebuild/recovery-selection.js +3 -1
- package/dist/slices/rebuild/recovery.js +9 -8
- package/dist/slices/rebuild/remake-outdated.js +5 -5
- package/dist/slices/rebuild/repo.js +4 -3
- package/dist/slices/rebuild/review-promise.js +25 -0
- package/dist/slices/rebuild/review-redo.js +3 -2
- package/dist/slices/rebuild/runtime-admission.js +4 -3
- package/dist/slices/rebuild/runtime-agent-review.js +11 -5
- package/dist/slices/rebuild/runtime-animate.js +10 -9
- package/dist/slices/rebuild/runtime-article.js +7 -5
- package/dist/slices/rebuild/runtime-checkpoints.js +5 -4
- package/dist/slices/rebuild/runtime-document.js +11 -13
- package/dist/slices/rebuild/runtime-export-bed.js +8 -12
- package/dist/slices/rebuild/runtime-export-edit.js +8 -16
- package/dist/slices/rebuild/runtime-export-inputs.js +12 -11
- package/dist/slices/rebuild/runtime-export-short.js +9 -5
- package/dist/slices/rebuild/runtime-export.js +38 -15
- package/dist/slices/rebuild/runtime-figure-card.js +2 -1
- package/dist/slices/rebuild/runtime-image.js +8 -12
- package/dist/slices/rebuild/runtime-instructions.js +2 -0
- package/dist/slices/rebuild/runtime-keywords.js +59 -0
- package/dist/slices/rebuild/runtime-lines.js +2 -11
- package/dist/slices/rebuild/runtime-local.js +17 -22
- package/dist/slices/rebuild/runtime-narration-publication.js +2 -5
- package/dist/slices/rebuild/runtime-narration-reuse.js +9 -13
- package/dist/slices/rebuild/runtime-narration-text.js +13 -17
- package/dist/slices/rebuild/runtime-pictures.js +2 -4
- package/dist/slices/rebuild/runtime-piece-label.js +10 -6
- package/dist/slices/rebuild/runtime-plan.js +31 -5
- package/dist/slices/rebuild/runtime-provider.js +67 -25
- package/dist/slices/rebuild/runtime-publication.js +10 -9
- package/dist/slices/rebuild/runtime-review.js +39 -33
- package/dist/slices/rebuild/runtime-run.js +4 -1
- package/dist/slices/rebuild/runtime-shorts.js +31 -50
- package/dist/slices/rebuild/runtime-store.js +20 -10
- package/dist/slices/rebuild/runtime-subtitles.js +28 -25
- package/dist/slices/rebuild/runtime-voices.js +10 -16
- package/dist/slices/rebuild/runtime-youtube.js +14 -31
- package/dist/slices/rebuild/service-readiness.js +11 -3
- package/dist/slices/rebuild/transition-repo.js +6 -5
- package/dist/slices/rebuild/work-records.js +6 -0
- package/dist/slices/reruns/cascade.js +1 -2
- package/dist/slices/reruns/index.js +6 -9
- package/dist/slices/research/synthesis.js +3 -2
- package/dist/slices/reviews/external-model.js +4 -1
- package/dist/slices/reviews/external-repo.js +2 -1
- package/dist/slices/reviews/external-rows.js +2 -3
- package/dist/slices/reviews/holds.js +5 -4
- package/dist/slices/reviews/model.js +32 -11
- package/dist/slices/reviews/repo.js +2 -1
- package/dist/slices/reviews/rules.js +4 -3
- package/dist/slices/reviews/verdict.js +2 -1
- package/dist/slices/reviews/view.js +5 -2
- package/dist/slices/revisions/downloads.js +4 -5
- package/dist/slices/revisions/image-plan.js +1 -1
- package/dist/slices/revisions/mutation-assets.js +9 -5
- package/dist/slices/revisions/mutation-cues.js +2 -5
- package/dist/slices/revisions/mutations.js +3 -3
- package/dist/slices/revisions/repo.js +3 -1
- package/dist/slices/revisions/schema.js +1 -0
- package/dist/slices/revisions/view.js +20 -0
- package/dist/slices/run-cost/limits.js +5 -2
- package/dist/slices/run-cost/meter.js +12 -5
- package/dist/slices/run-cost/panel.js +8 -74
- package/dist/slices/run-cost/plan-readings.js +127 -0
- package/dist/slices/run-cost/plan-use.js +169 -0
- package/dist/slices/run-cost/pricing.js +3 -3
- package/dist/slices/run-cost/week.js +32 -4
- package/dist/slices/schedules/agenda.js +18 -7
- package/dist/slices/schedules/by-date.js +42 -0
- package/dist/slices/schedules/calendar.js +5 -0
- package/dist/slices/schedules/design-agenda.js +36 -0
- package/dist/slices/schedules/design-check.js +41 -0
- package/dist/slices/schedules/design-run.js +126 -0
- package/dist/slices/schedules/next-run.js +62 -0
- package/dist/slices/schedules/prepare.js +18 -2
- package/dist/slices/schedules/repo.js +30 -21
- package/dist/slices/schedules/rescore.js +35 -0
- package/dist/slices/schedules/scheduler.js +13 -3
- package/dist/slices/schedules/schema.js +57 -3
- package/dist/slices/schedules/score.js +107 -0
- package/dist/slices/schedules/service.js +57 -24
- package/dist/slices/schedules/topic-list.js +15 -0
- package/dist/slices/schedules/topic-scores.js +104 -0
- package/dist/slices/schedules/topics.js +53 -41
- package/dist/slices/settings/cli-paths.js +4 -6
- package/dist/slices/settings/first-run.js +8 -43
- package/dist/slices/settings/health.js +30 -15
- package/dist/slices/settings/key-test.js +1 -1
- package/dist/slices/settings/model-reach.js +3 -17
- package/dist/slices/settings/model.js +14 -2
- package/dist/slices/settings/playback.js +34 -23
- package/dist/slices/settings/probe-read.js +16 -0
- package/dist/slices/settings/repo.js +33 -0
- package/dist/slices/settings/tutorial.js +2 -2
- package/dist/slices/settings/voices.js +4 -12
- package/dist/slices/shorts/keep.js +2 -1
- package/dist/slices/shorts/pick.js +6 -18
- package/dist/slices/shorts/prompts.js +4 -14
- package/dist/slices/shorts/render.js +6 -2
- package/dist/slices/social/channel.js +44 -0
- package/dist/slices/social/defaults.js +17 -0
- package/dist/slices/social/due.js +36 -0
- package/dist/slices/social/extension.js +18 -0
- package/dist/slices/social/fit.js +115 -0
- package/dist/slices/social/limits.js +186 -0
- package/dist/slices/social/links.js +21 -0
- package/dist/slices/social/media.js +132 -0
- package/dist/slices/social/model.js +75 -0
- package/dist/slices/social/notice.js +19 -0
- package/dist/slices/social/pack.js +176 -0
- package/dist/slices/social/post-prompt.js +56 -0
- package/dist/slices/social/queue.js +31 -0
- package/dist/slices/social/repo.js +133 -0
- package/dist/slices/social/reshape.js +97 -0
- package/dist/slices/social/rules.js +5 -0
- package/dist/slices/social/schema.js +70 -0
- package/dist/slices/social/serve.js +51 -0
- package/dist/slices/social/service.js +129 -0
- package/dist/slices/social/settings.js +21 -0
- package/dist/slices/social/sources.js +114 -0
- package/dist/slices/social/state.js +110 -0
- package/dist/slices/social/text.js +149 -0
- package/dist/slices/storage/arrange.js +3 -1
- package/dist/slices/storage/assets.js +8 -10
- package/dist/slices/storage/backup-designs.js +74 -0
- package/dist/slices/storage/backup-export.js +8 -3
- package/dist/slices/storage/backup-format.js +10 -0
- package/dist/slices/storage/backup-import.js +22 -4
- package/dist/slices/storage/delete-project.js +6 -5
- package/dist/slices/storage/files-location.js +6 -8
- package/dist/slices/storage/layout.js +13 -2
- package/dist/slices/storage/model.js +3 -0
- package/dist/slices/storage/portable.js +17 -12
- package/dist/slices/storage/schema.js +2 -0
- package/dist/slices/storage/staging-refs.js +2 -1
- package/dist/slices/storage/staging.js +6 -9
- package/dist/slices/storage/trim.js +26 -9
- package/dist/slices/studio/calendar.js +7 -2
- package/dist/slices/studio/disclosure.js +4 -4
- package/dist/slices/studio/model.js +1 -1
- package/dist/slices/studio/pack.js +9 -8
- package/dist/slices/studio/pick.js +2 -11
- package/dist/slices/studio/plan.js +7 -16
- package/dist/slices/studio/queue.js +3 -14
- package/dist/slices/studio/releases.js +26 -0
- package/dist/slices/studio/settings.js +20 -57
- package/dist/slices/studio/videos.js +35 -4
- package/dist/slices/style-preview/render.js +37 -16
- package/dist/slices/style-preview/schema.js +14 -1
- package/dist/slices/style-preview/service.js +2 -1
- package/dist/slices/style-preview/settings.js +33 -5
- package/dist/slices/subtitles/captions.js +1 -1
- package/dist/slices/telemetry/collector-client.js +2 -4
- package/dist/slices/telemetry/flush.js +2 -4
- package/dist/slices/telemetry/model.js +0 -7
- package/dist/slices/telemetry/record.js +10 -3
- package/dist/slices/template-studio/anatomy-view.js +161 -0
- package/dist/slices/template-studio/anatomy.js +73 -0
- package/dist/slices/template-studio/bakeoff-make.js +225 -0
- package/dist/slices/template-studio/bakeoff-repo.js +83 -0
- package/dist/slices/template-studio/bakeoff.js +333 -0
- package/dist/slices/template-studio/budget.js +106 -0
- package/dist/slices/template-studio/cards.js +78 -0
- package/dist/slices/template-studio/checks.js +322 -0
- package/dist/slices/template-studio/document-sample.js +56 -0
- package/dist/slices/template-studio/edit.js +15 -0
- package/dist/slices/template-studio/for-all.js +161 -0
- package/dist/slices/template-studio/free-video.js +31 -0
- package/dist/slices/template-studio/free.js +176 -0
- package/dist/slices/template-studio/gate.js +40 -0
- package/dist/slices/template-studio/hidden.js +20 -0
- package/dist/slices/template-studio/jobs.js +79 -0
- package/dist/slices/template-studio/loudness.js +111 -0
- package/dist/slices/template-studio/make.js +40 -0
- package/dist/slices/template-studio/model.js +58 -0
- package/dist/slices/template-studio/pack-import.js +253 -0
- package/dist/slices/template-studio/pack-samples.js +60 -0
- package/dist/slices/template-studio/pack.js +207 -0
- package/dist/slices/template-studio/paid-view.js +66 -0
- package/dist/slices/template-studio/paid.js +355 -0
- package/dist/slices/template-studio/quote.js +155 -0
- package/dist/slices/template-studio/ready.js +104 -0
- package/dist/slices/template-studio/repo.js +134 -0
- package/dist/slices/template-studio/reviews-path.js +58 -0
- package/dist/slices/template-studio/runner.js +84 -0
- package/dist/slices/template-studio/save.js +236 -0
- package/dist/slices/template-studio/say-it-as.js +248 -0
- package/dist/slices/template-studio/schedule-gate.js +34 -0
- package/dist/slices/template-studio/schedule-price.js +32 -0
- package/dist/slices/template-studio/schedule-sample.js +91 -0
- package/dist/slices/template-studio/schema.js +243 -0
- package/dist/slices/template-studio/scope.js +124 -0
- package/dist/slices/template-studio/sections.js +176 -0
- package/dist/slices/template-studio/service.js +175 -0
- package/dist/slices/template-studio/status.js +191 -0
- package/dist/slices/template-studio/topic.js +223 -0
- package/dist/slices/thumbnail/by-llm.js +1 -1
- package/dist/slices/trash/designs.js +76 -0
- package/dist/slices/trash/model.js +13 -4
- package/dist/slices/trash/service.js +52 -2
- package/dist/slices/tutorials/library.js +3 -2
- package/dist/slices/uploads/repo.js +37 -1
- package/dist/slices/uploads/rules.js +3 -2
- package/dist/slices/video/ass-text.js +17 -0
- package/dist/slices/video/audio-export.js +2 -64
- package/dist/slices/video/edit-list.js +2 -2
- package/dist/slices/video/edit-settings.js +1 -1
- package/dist/slices/video/encoding.js +169 -0
- package/dist/slices/video/ffmpeg.js +23 -21
- package/dist/slices/video/figure-card.js +1 -15
- package/dist/slices/video/plan.js +2 -1
- package/dist/slices/video/slideshow.js +43 -18
- package/dist/slices/voices/attribution.js +3 -2
- package/dist/slices/voices/model.js +9 -8
- package/dist/slices/voices/palette.js +0 -3
- package/dist/slices/voices/script.js +2 -1
- package/dist/slices/youtube/answer.js +4 -16
- package/dist/slices/youtube/edits-repo.js +3 -12
- package/dist/tutorials/AI-CLIs.md +25 -25
- package/dist/tutorials/Agents-MCP.md +34 -33
- package/dist/tutorials/Assistant.md +42 -0
- package/dist/tutorials/Backups.md +7 -7
- package/dist/tutorials/Calendar.md +17 -25
- package/dist/tutorials/Cast-Library.md +19 -19
- package/dist/tutorials/Channels.md +42 -35
- package/dist/tutorials/Costs-and-Run-Cost.md +38 -40
- package/dist/tutorials/Create-Article.md +114 -0
- package/dist/tutorials/Create-Extras.md +112 -0
- package/dist/tutorials/Create-Images.md +165 -0
- package/dist/tutorials/Create-Narration.md +178 -0
- package/dist/tutorials/Create-Overview.md +244 -0
- package/dist/tutorials/Create-Video-and-Style.md +144 -0
- package/dist/tutorials/Docker.md +3 -3
- package/dist/tutorials/Document-Themes.md +32 -32
- package/dist/tutorials/Editing-a-Project.md +94 -94
- package/dist/tutorials/FAQ.md +18 -18
- package/dist/tutorials/First-Launch-and-Welcome.md +50 -64
- package/dist/tutorials/Home-and-Projects.md +115 -71
- package/dist/tutorials/Home.md +33 -33
- package/dist/tutorials/Install.md +14 -13
- package/dist/tutorials/Intros-and-Outros.md +33 -34
- package/dist/tutorials/Keyboard-Shortcuts-and-Command-Palette.md +62 -58
- package/dist/tutorials/Keywords-Slopify-Fills.md +87 -0
- package/dist/tutorials/Models.md +53 -21
- package/dist/tutorials/Multiple-Voices.md +41 -40
- package/dist/tutorials/Narration-Aliases-and-Glossary.md +14 -14
- package/dist/tutorials/Notifications.md +27 -17
- package/dist/tutorials/Other-Languages.md +15 -15
- package/dist/tutorials/PDF-Documents.md +38 -29
- package/dist/tutorials/Posting-to-Social-Sites.md +121 -0
- package/dist/tutorials/Project-Page.md +118 -120
- package/dist/tutorials/Prompts-and-Templates.md +84 -0
- package/dist/tutorials/Prompts.md +48 -44
- package/dist/tutorials/Providers-and-Keys.md +105 -98
- package/dist/tutorials/Publishing-to-YouTube.md +31 -31
- package/dist/tutorials/Recovery-and-Retries.md +31 -31
- package/dist/tutorials/Remote-Access.md +63 -0
- package/dist/tutorials/Reviews-and-Checkpoints.md +98 -90
- package/dist/tutorials/Schedules.md +46 -27
- package/dist/tutorials/Settings-Reference.md +194 -174
- package/dist/tutorials/Shorts.md +34 -33
- package/dist/tutorials/Start-at-Login.md +3 -3
- package/dist/tutorials/Studio-Extension.md +22 -24
- package/dist/tutorials/Template-Studio.md +128 -0
- package/dist/tutorials/Templates.md +51 -77
- package/dist/tutorials/Trash.md +4 -4
- package/dist/tutorials/Troubleshooting.md +44 -44
- package/dist/tutorials/Uninstalling-and-Moving.md +5 -5
- package/dist/tutorials/Updating-and-Patch-Notes.md +18 -18
- package/dist/tutorials/Video-Editing.md +34 -34
- package/dist/tutorials/Where-Your-Files-Live.md +10 -10
- package/dist/tutorials/YouTube-Description.md +26 -26
- package/dist/tutorials/Your-First-Short.md +35 -35
- package/dist/tutorials/_Sidebar.md +19 -14
- package/dist/updater/work-in-progress.js +42 -12
- package/dist/web/assets/index-BNftKQrA.css +1 -0
- package/dist/web/assets/index-Cpa58woP.js +459 -0
- package/dist/web/assets/pdf-BKh8f7R6.js +56 -0
- package/dist/web/assets/pdf.worker.min-BmVo14Nb.mjs +28 -0
- package/dist/web/assets/pdf.worker.min-D7i8o3wR.js +1 -0
- package/dist/web/index.html +2 -2
- package/package.json +6 -2
- package/dist/slices/article/provided-entries.js +0 -66
- package/dist/slices/article/run.js +0 -145
- package/dist/slices/images/run.js +0 -234
- package/dist/slices/narration/legacy-plan.js +0 -58
- package/dist/slices/narration/run.js +0 -270
- package/dist/slices/rebuild/runtime-actions.js +0 -90
- package/dist/slices/research/run.js +0 -224
- package/dist/slices/subtitles/prepare.js +0 -194
- package/dist/slices/subtitles/transcript.js +0 -34
- package/dist/slices/thumbnail/run.js +0 -219
- package/dist/slices/video/audio-inputs.js +0 -33
- package/dist/slices/video/reuse-audio.js +0 -62
- package/dist/slices/video/run.js +0 -78
- package/dist/slices/video/write-export.js +0 -158
- package/dist/slices/video/write-subtitles.js +0 -59
- package/dist/tutorials/Library-Overview.md +0 -76
- package/dist/tutorials/Play-Images.md +0 -161
- package/dist/tutorials/Play-Narration.md +0 -167
- package/dist/tutorials/Play-Outputs.md +0 -109
- package/dist/tutorials/Play-Overview.md +0 -227
- package/dist/tutorials/Play-Title-and-Article.md +0 -136
- package/dist/tutorials/Play-Video-and-Style.md +0 -143
- package/dist/web/assets/index-BadsoORk.css +0 -1
- package/dist/web/assets/index-D8LqNsCl.js +0 -326
- package/dist/web/assets/pdf-T7MCwjIv.js +0 -54
- package/dist/web/assets/pdf.worker.min-Dswkl-cV.mjs +0 -29
- package/dist/web/assets/pdf.worker.min-zC6nfbxG.js +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { randomBytes, timingSafeEqual } from "node:crypto";
|
|
2
2
|
import { z } from "zod";
|
|
3
|
-
import {
|
|
3
|
+
import { deleteSetting, readJsonSetting, stringListSchema, writeSetting, } from "../settings/repo.js";
|
|
4
4
|
import { playlistUses, studioPlaylistMax, } from "./model.js";
|
|
5
5
|
// Rows of the key/value `settings` table. The playlists travel with a backup; the
|
|
6
6
|
// pairing stays on this machine (`slices/storage/portable.ts`): its token is what lets the
|
|
@@ -14,7 +14,7 @@ const pairingSchema = z.object({
|
|
|
14
14
|
});
|
|
15
15
|
// A channel's own playlists are a row of their own, `studio.playlist.<channelId>`; a channel
|
|
16
16
|
// without one uses the default list above. Each playlist is ticked by default or not; a
|
|
17
|
-
// project's
|
|
17
|
+
// project's Copy for YouTube Studio can change which it goes into. A row saved before lists existed
|
|
18
18
|
// holds one name, read as one playlist ticked by default.
|
|
19
19
|
export const studioChannelPlaylistPrefix = `${studioPlaylistKey}.`;
|
|
20
20
|
function playlistKey(channelId) {
|
|
@@ -58,31 +58,23 @@ export function readChannelPlaylists(db) {
|
|
|
58
58
|
return out;
|
|
59
59
|
}
|
|
60
60
|
function storedPlaylists(db, key) {
|
|
61
|
-
const stored =
|
|
62
|
-
if (stored ===
|
|
61
|
+
const stored = readJsonSetting(db, key, storedPlaylistsSchema, null);
|
|
62
|
+
if (stored === null)
|
|
63
63
|
return null;
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
return null;
|
|
68
|
-
if (typeof parsed.data === "string")
|
|
69
|
-
return parsed.data.trim() === "" ? null : [{ name: parsed.data.trim(), byDefault: true }];
|
|
70
|
-
return parsed.data.length === 0 ? null : parsed.data;
|
|
71
|
-
}
|
|
72
|
-
catch {
|
|
73
|
-
return null;
|
|
74
|
-
}
|
|
64
|
+
if (typeof stored === "string")
|
|
65
|
+
return stored.trim() === "" ? null : [{ name: stored.trim(), byDefault: true }];
|
|
66
|
+
return stored.length === 0 ? null : stored;
|
|
75
67
|
}
|
|
76
|
-
// Why a list can't be saved, in words for Settings → YouTube Studio; undefined when it can.
|
|
68
|
+
// Why a list can't be saved, in words for Settings → YouTube Studio and posting; undefined when it can.
|
|
77
69
|
export function studioPlaylistsProblem(list) {
|
|
78
70
|
const long = list.find((one) => one.name.trim().length > studioPlaylistMax);
|
|
79
71
|
if (long !== undefined)
|
|
80
|
-
return `The playlist name "${long.name.slice(0, 40)}…" is longer than YouTube allows (${String(studioPlaylistMax)} characters). Shorten it in Settings → YouTube Studio.`;
|
|
72
|
+
return `The playlist name "${long.name.slice(0, 40)}…" is longer than YouTube allows (${String(studioPlaylistMax)} characters). Shorten it in Settings → YouTube Studio and posting.`;
|
|
81
73
|
const seen = new Set();
|
|
82
74
|
for (const one of list) {
|
|
83
75
|
const key = one.name.trim().toLowerCase();
|
|
84
76
|
if (seen.has(key))
|
|
85
|
-
return `"${one.name.trim()}" is listed twice. Remove one in Settings → YouTube Studio.`;
|
|
77
|
+
return `"${one.name.trim()}" is listed twice. Remove one in Settings → YouTube Studio and posting.`;
|
|
86
78
|
seen.add(key);
|
|
87
79
|
}
|
|
88
80
|
return undefined;
|
|
@@ -100,27 +92,18 @@ export function saveStudioPlaylists(db, list, channelId) {
|
|
|
100
92
|
.filter((one) => one.name !== "");
|
|
101
93
|
const key = playlistKey(channelId);
|
|
102
94
|
if (value.length === 0) {
|
|
103
|
-
db
|
|
95
|
+
deleteSetting(db, key);
|
|
104
96
|
return [];
|
|
105
97
|
}
|
|
106
98
|
writeSetting(db, key, JSON.stringify(value));
|
|
107
99
|
return value;
|
|
108
100
|
}
|
|
109
|
-
// The playlists a project's uploads go into, when its
|
|
101
|
+
// The playlists a project's uploads go into, when its Copy for YouTube Studio changed them from the
|
|
110
102
|
// channel's defaults: one row, project id to names.
|
|
111
103
|
export const studioProjectPlaylistsKey = "studio.projectPlaylists";
|
|
112
104
|
export const storedProjectPlaylistsSchema = z.record(z.string().max(64), z.array(z.string().max(studioPlaylistMax)).max(studioPlaylistsMax));
|
|
113
105
|
function projectChoices(db) {
|
|
114
|
-
|
|
115
|
-
if (stored === undefined)
|
|
116
|
-
return {};
|
|
117
|
-
try {
|
|
118
|
-
const parsed = storedProjectPlaylistsSchema.safeParse(JSON.parse(stored));
|
|
119
|
-
return parsed.success ? parsed.data : {};
|
|
120
|
-
}
|
|
121
|
-
catch {
|
|
122
|
-
return {};
|
|
123
|
-
}
|
|
106
|
+
return readJsonSetting(db, studioProjectPlaylistsKey, storedProjectPlaylistsSchema, {});
|
|
124
107
|
}
|
|
125
108
|
// The channel's playlists, each ticked as this project goes into it: the project's own choice
|
|
126
109
|
// when it made one (a playlist the channel no longer lists is dropped), else the defaults.
|
|
@@ -139,29 +122,19 @@ export function saveProjectPlaylists(db, projectId, names) {
|
|
|
139
122
|
const { [projectId]: _previous, ...others } = projectChoices(db);
|
|
140
123
|
const next = names === null ? others : { ...others, [projectId]: [...names] };
|
|
141
124
|
if (Object.keys(next).length === 0)
|
|
142
|
-
db
|
|
125
|
+
deleteSetting(db, studioProjectPlaylistsKey);
|
|
143
126
|
else
|
|
144
127
|
writeSetting(db, studioProjectPlaylistsKey, JSON.stringify(next));
|
|
145
128
|
}
|
|
146
129
|
// The projects whose uploaded clips are real footage (filmed, not generated): ticked in the
|
|
147
|
-
// project's
|
|
130
|
+
// project's Copy for YouTube Studio, under AI use. One row holding their ids; YouTube's second AI use
|
|
148
131
|
// case is footage of a real event or place altered by AI (`disclosure.ts`).
|
|
149
132
|
export const studioRealFootageKey = "studio.realFootage";
|
|
150
133
|
// "on" or "off": whether the extension posts and pins each video's comment once it is public.
|
|
151
134
|
export const autoCommentKey = "studio.autoComment";
|
|
152
135
|
function realFootageIds(db) {
|
|
153
|
-
const
|
|
154
|
-
|
|
155
|
-
return [];
|
|
156
|
-
try {
|
|
157
|
-
const value = JSON.parse(stored);
|
|
158
|
-
return Array.isArray(value)
|
|
159
|
-
? value.filter((one) => typeof one === "string")
|
|
160
|
-
: [];
|
|
161
|
-
}
|
|
162
|
-
catch {
|
|
163
|
-
return [];
|
|
164
|
-
}
|
|
136
|
+
const value = readJsonSetting(db, studioRealFootageKey, stringListSchema, []);
|
|
137
|
+
return value;
|
|
165
138
|
}
|
|
166
139
|
export function readRealFootage(db, projectId) {
|
|
167
140
|
return realFootageIds(db).includes(projectId);
|
|
@@ -170,25 +143,15 @@ export function saveRealFootage(db, projectId, on) {
|
|
|
170
143
|
const others = realFootageIds(db).filter((one) => one !== projectId);
|
|
171
144
|
const next = on ? [...others, projectId].sort() : others;
|
|
172
145
|
if (next.length === 0)
|
|
173
|
-
db
|
|
146
|
+
deleteSetting(db, studioRealFootageKey);
|
|
174
147
|
else
|
|
175
148
|
writeSetting(db, studioRealFootageKey, JSON.stringify(next));
|
|
176
149
|
}
|
|
177
150
|
// The pairing token, made on first read. One per install: a new one (Settings → YouTube
|
|
178
151
|
// Studio → New pairing token) forgets the extension that used the old one.
|
|
179
152
|
export function studioPairing(db) {
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
try {
|
|
183
|
-
const parsed = pairingSchema.safeParse(JSON.parse(stored));
|
|
184
|
-
if (parsed.success)
|
|
185
|
-
return parsed.data;
|
|
186
|
-
}
|
|
187
|
-
catch {
|
|
188
|
-
// A damaged row is replaced below.
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
return resetStudioPairing(db);
|
|
153
|
+
// A damaged row is replaced.
|
|
154
|
+
return readJsonSetting(db, studioPairingKey, pairingSchema, undefined) ?? resetStudioPairing(db);
|
|
192
155
|
}
|
|
193
156
|
// What is waiting to be filled in Studio is kept per pairing (`queue.ts`): one row,
|
|
194
157
|
// `studio.fillQueue.<token hash>`, so a new token starts with nothing waiting.
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { markUploaded } from "../uploads/repo.js";
|
|
1
2
|
const taskState = (value) => value === "waiting" || value === "done" || value === "failed" ? value : "none";
|
|
2
3
|
// A YouTube video id: 11 letters, digits, `-` and `_`.
|
|
3
4
|
export const videoIdPattern = /^[A-Za-z0-9_-]{11}$/;
|
|
@@ -41,15 +42,33 @@ export function recordVideo(db, projectId, short, videoId, at, state = "done") {
|
|
|
41
42
|
upload_state=CASE WHEN video_id=excluded.video_id AND upload_state='done' THEN 'done'
|
|
42
43
|
ELSE excluded.upload_state END,
|
|
43
44
|
video_id=excluded.video_id, recorded_at=excluded.recorded_at`).run(projectId, slot(short), videoId, at, state);
|
|
45
|
+
if (short === null && videoOf(db, projectId, null)?.uploadState === "done")
|
|
46
|
+
markUploaded(db, projectId, true, at);
|
|
44
47
|
}
|
|
45
48
|
// Studio said the upload was scheduled or published. False when no such upload was filled.
|
|
46
|
-
export function confirmUpload(db, projectId, short, videoId) {
|
|
47
|
-
|
|
49
|
+
export function confirmUpload(db, projectId, short, videoId, at) {
|
|
50
|
+
const confirmed = db
|
|
48
51
|
.prepare("UPDATE youtube_videos SET upload_state='done' WHERE project_id=? AND short=? AND video_id=?")
|
|
49
|
-
.run(projectId, slot(short), videoId).changes > 0
|
|
52
|
+
.run(projectId, slot(short), videoId).changes > 0;
|
|
53
|
+
if (confirmed && short === null)
|
|
54
|
+
markUploaded(db, projectId, true, at);
|
|
55
|
+
return confirmed;
|
|
50
56
|
}
|
|
51
|
-
|
|
57
|
+
// Forgets the video an upload became (deleted on YouTube, or a wrong link). Forgetting a long
|
|
58
|
+
// video that was on YouTube takes the project's uploaded mark off with it; an upload only
|
|
59
|
+
// filled in Studio never set the mark, so forgetting it leaves a mark made by hand.
|
|
60
|
+
export function forgetVideo(db, projectId, short, at) {
|
|
61
|
+
const was = videoOf(db, projectId, short);
|
|
52
62
|
db.prepare("DELETE FROM youtube_videos WHERE project_id=? AND short=?").run(projectId, slot(short));
|
|
63
|
+
if (short === null && was?.uploadState === "done")
|
|
64
|
+
markUploaded(db, projectId, false, at);
|
|
65
|
+
}
|
|
66
|
+
// "Mark not uploaded" (Home, Projects): the long video's link goes with the mark, so the two
|
|
67
|
+
// never disagree. An upload only filled in Studio is not on YouTube and stays.
|
|
68
|
+
export function markNotUploaded(db, projectId, at) {
|
|
69
|
+
if (videoOf(db, projectId, null)?.uploadState === "done")
|
|
70
|
+
forgetVideo(db, projectId, null, at);
|
|
71
|
+
return markUploaded(db, projectId, false, at);
|
|
53
72
|
}
|
|
54
73
|
export function projectVideos(db, projectId) {
|
|
55
74
|
return db
|
|
@@ -63,6 +82,18 @@ export function videoOf(db, projectId, short) {
|
|
|
63
82
|
.get(projectId, slot(short));
|
|
64
83
|
return row === undefined ? undefined : rowOf(row);
|
|
65
84
|
}
|
|
85
|
+
// What the extension reported after setting up Studio's A/B Testing on the video's Details page,
|
|
86
|
+
// asked for from On YouTube or its popup: "started" once filled (the person presses Set test),
|
|
87
|
+
// "failed" with its reason. A failed later attempt keeps a test already set up ("started"), so
|
|
88
|
+
// its result is still read. False when the project has no video recorded for that upload.
|
|
89
|
+
export function setAbState(db, projectId, short, state, message, at) {
|
|
90
|
+
return (db
|
|
91
|
+
.prepare(`UPDATE youtube_videos SET
|
|
92
|
+
ab_state=CASE WHEN ?='failed' AND ab_state='started' THEN 'started' ELSE ? END,
|
|
93
|
+
ab_message=?, ab_at=?
|
|
94
|
+
WHERE project_id=? AND short=?`)
|
|
95
|
+
.run(state, state, message, at, projectId, slot(short)).changes > 0);
|
|
96
|
+
}
|
|
66
97
|
export function setTaskState(db, task, projectId, short, state, message) {
|
|
67
98
|
const column = task === "finish" ? "finish" : "comment";
|
|
68
99
|
db.prepare(`UPDATE youtube_videos SET ${column}_state=?, ${column}_message=? WHERE project_id=? AND short=?`).run(state, message, projectId, slot(short));
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { copyFileSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
|
+
import { errorText } from "../../kernel/errors.js";
|
|
3
4
|
import { defaultMotionStyle, defaultZoomPercent } from "../admission/rules.js";
|
|
4
5
|
import { isMissingFont, resolveBoldFont, resolveFont } from "../fonts/index.js";
|
|
5
6
|
import { renderShort } from "../shorts/render.js";
|
|
@@ -9,7 +10,7 @@ import { planRender } from "../video/plan.js";
|
|
|
9
10
|
import { renderSlideshow } from "../video/slideshow.js";
|
|
10
11
|
import { bundledSampleAssets, sampleNarrationSeconds } from "./narration.js";
|
|
11
12
|
import { stylePreviewSeconds } from "./schema.js";
|
|
12
|
-
import { previewCues, previewWords } from "./settings.js";
|
|
13
|
+
import { previewCues, previewShots, previewWords } from "./settings.js";
|
|
13
14
|
export class StylePreviewError extends Error {
|
|
14
15
|
reason;
|
|
15
16
|
constructor(reason, message) {
|
|
@@ -25,7 +26,6 @@ const previewFrame = {
|
|
|
25
26
|
"9:16": { width: 270, height: 480 },
|
|
26
27
|
"1:1": { width: 360, height: 360 },
|
|
27
28
|
};
|
|
28
|
-
const shotSeconds = stylePreviewSeconds / 3;
|
|
29
29
|
const chapterTitle = "Chapter one";
|
|
30
30
|
export function ffmpegStylePreview(deps) {
|
|
31
31
|
const assets = deps.assets ?? bundledSampleAssets();
|
|
@@ -33,25 +33,32 @@ export function ffmpegStylePreview(deps) {
|
|
|
33
33
|
try {
|
|
34
34
|
// A real picture is shown for all three shots: the motion, the Look and the captions read
|
|
35
35
|
// on it, and the transition and chapter card still show at the cuts.
|
|
36
|
-
const
|
|
36
|
+
const stills = picture !== undefined
|
|
37
37
|
? [picture, picture, picture]
|
|
38
38
|
: settings.format === "9:16"
|
|
39
39
|
? assets.tall
|
|
40
40
|
: assets.wide;
|
|
41
|
+
// A longer preview shows the stills again in turn.
|
|
42
|
+
const { shots } = previewShots(settings);
|
|
43
|
+
const images = settings.short !== undefined
|
|
44
|
+
? stills
|
|
45
|
+
: Array.from({ length: shots }, (_, index) => stills[index % stills.length] ?? "");
|
|
46
|
+
const machine = await deps.machine?.();
|
|
41
47
|
if (settings.short !== undefined)
|
|
42
|
-
await renderShortPreview(deps, settings, settings.short, assets, images, output, signal);
|
|
48
|
+
await renderShortPreview(deps, settings, settings.short, assets, images, output, signal, machine);
|
|
43
49
|
else
|
|
44
|
-
await renderPreview(deps, settings, assets, images, output, signal);
|
|
50
|
+
await renderPreview(deps, settings, assets, images, output, signal, machine);
|
|
45
51
|
}
|
|
46
52
|
catch (error) {
|
|
47
53
|
throw explained(deps.log, error);
|
|
48
54
|
}
|
|
49
55
|
};
|
|
50
56
|
}
|
|
51
|
-
async function renderPreview(deps, settings, assets, images, output, signal) {
|
|
57
|
+
async function renderPreview(deps, settings, assets, images, output, signal, machine) {
|
|
52
58
|
mkdirSync(deps.dir, { recursive: true, mode: 0o700 });
|
|
53
59
|
const workspace = mkdtempSync(join(deps.dir, "work-"));
|
|
54
60
|
try {
|
|
61
|
+
const { shotSeconds } = previewShots(settings);
|
|
55
62
|
const cardFont = settings.chapterCard === null
|
|
56
63
|
? undefined
|
|
57
64
|
: await resolveFont(deps.paths, settings.chapterCard.fontId);
|
|
@@ -60,8 +67,8 @@ async function renderPreview(deps, settings, assets, images, output, signal) {
|
|
|
60
67
|
gapSeconds: 0,
|
|
61
68
|
edgeSeconds: 0,
|
|
62
69
|
imageSeconds: shotSeconds,
|
|
63
|
-
zoomPercent: defaultZoomPercent,
|
|
64
|
-
motionStyle: defaultMotionStyle,
|
|
70
|
+
zoomPercent: settings.timing?.zoomPercent ?? defaultZoomPercent,
|
|
71
|
+
motionStyle: settings.timing?.motionStyle ?? defaultMotionStyle,
|
|
65
72
|
images,
|
|
66
73
|
output,
|
|
67
74
|
edit: {
|
|
@@ -81,14 +88,14 @@ async function renderPreview(deps, settings, assets, images, output, signal) {
|
|
|
81
88
|
const edit = {
|
|
82
89
|
...plan.editList,
|
|
83
90
|
...previewFrame[settings.format],
|
|
84
|
-
audio:
|
|
91
|
+
audio: narrationFor(assets.narration, plan.totalSeconds),
|
|
85
92
|
};
|
|
86
93
|
const captions = settings.captions;
|
|
87
94
|
if (captions !== null) {
|
|
88
95
|
const font = await resolveFont(deps.paths, captions.fontId);
|
|
89
96
|
mkdirSync(join(workspace, "fonts"), { mode: 0o700 });
|
|
90
97
|
copyFileSync(font.path, join(workspace, "fonts", `selected${font.extension}`));
|
|
91
|
-
writeFileSync(join(workspace, "subtitles.ass"), serializeAss(previewCues(captions.text), {
|
|
98
|
+
writeFileSync(join(workspace, "subtitles.ass"), serializeAss(previewCues(captions.text, plan.totalSeconds), {
|
|
92
99
|
...subtitleFrame(settings.format),
|
|
93
100
|
fontName: font.assName,
|
|
94
101
|
fontSize: captions.fontSize,
|
|
@@ -105,6 +112,7 @@ async function renderPreview(deps, settings, assets, images, output, signal) {
|
|
|
105
112
|
signal,
|
|
106
113
|
log: deps.log,
|
|
107
114
|
onProgress: () => { },
|
|
115
|
+
machine,
|
|
108
116
|
});
|
|
109
117
|
}
|
|
110
118
|
finally {
|
|
@@ -113,7 +121,7 @@ async function renderPreview(deps, settings, assets, images, output, signal) {
|
|
|
113
121
|
}
|
|
114
122
|
// The Shorts layout, drawn at the preview's size: the same audio cut, image timing, captions
|
|
115
123
|
// and headline a short gets, from the sample narration.
|
|
116
|
-
async function renderShortPreview(deps, settings, short, assets, images, output, signal) {
|
|
124
|
+
async function renderShortPreview(deps, settings, short, assets, images, output, signal, machine) {
|
|
117
125
|
mkdirSync(deps.dir, { recursive: true, mode: 0o700 });
|
|
118
126
|
await renderShort({
|
|
119
127
|
bin: deps.ffmpeg,
|
|
@@ -121,7 +129,7 @@ async function renderShortPreview(deps, settings, short, assets, images, output,
|
|
|
121
129
|
start: 0,
|
|
122
130
|
end: sampleNarrationSeconds,
|
|
123
131
|
images,
|
|
124
|
-
imageSeconds:
|
|
132
|
+
imageSeconds: stylePreviewSeconds / 3,
|
|
125
133
|
motionStyle: defaultMotionStyle,
|
|
126
134
|
zoomPercent: defaultZoomPercent,
|
|
127
135
|
words: previewWords(short.text),
|
|
@@ -134,16 +142,29 @@ async function renderShortPreview(deps, settings, short, assets, images, output,
|
|
|
134
142
|
signal,
|
|
135
143
|
log: deps.log,
|
|
136
144
|
onProgress: () => { },
|
|
145
|
+
machine,
|
|
137
146
|
});
|
|
138
147
|
}
|
|
148
|
+
// The six seconds of sample narration back to back under a longer preview, the last cut to
|
|
149
|
+
// what is left.
|
|
150
|
+
function narrationFor(path, seconds) {
|
|
151
|
+
const pieces = [];
|
|
152
|
+
for (let at = 0; at < seconds - 0.001; at += sampleNarrationSeconds)
|
|
153
|
+
pieces.push({
|
|
154
|
+
kind: "body",
|
|
155
|
+
path,
|
|
156
|
+
seconds: Math.round(Math.min(sampleNarrationSeconds, seconds - at) * 1000) / 1000,
|
|
157
|
+
});
|
|
158
|
+
return pieces;
|
|
159
|
+
}
|
|
139
160
|
function explained(log, error) {
|
|
140
161
|
if (error instanceof StylePreviewError)
|
|
141
162
|
return error;
|
|
142
|
-
const message =
|
|
163
|
+
const message = errorText(error);
|
|
143
164
|
if (isMissingFont(error))
|
|
144
|
-
return new StylePreviewError("font-missing", "The style preview couldn't render because the chosen caption font is no longer available; it may have been uninstalled or deleted. Choose another font
|
|
165
|
+
return new StylePreviewError("font-missing", "The style preview couldn't render because the chosen caption font is no longer available; it may have been uninstalled or deleted. Choose another caption font, then press Make the preview again.");
|
|
145
166
|
if (message.startsWith("Slopify could not start ffmpeg") || /\bENOENT\b/.test(message))
|
|
146
|
-
return new StylePreviewError("ffmpeg-missing", "The style preview couldn't render because ffmpeg wasn't found. Install ffmpeg, or use the Docker image, then press
|
|
167
|
+
return new StylePreviewError("ffmpeg-missing", "The style preview couldn't render because ffmpeg wasn't found. Install ffmpeg, or use the Docker image, then press Make the preview again.");
|
|
147
168
|
log.write("error", "style-preview.render", { detail: message });
|
|
148
|
-
return new StylePreviewError("render-failed", "The style preview couldn't render because ffmpeg stopped with an error. Press
|
|
169
|
+
return new StylePreviewError("render-failed", "The style preview couldn't render because ffmpeg stopped with an error. Press Make the preview again; if it fails again, use Download diagnostics in Settings and report it.");
|
|
149
170
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { formats } from "../../kernel/pipeline.js";
|
|
3
|
+
import { motionStyles } from "../admission/model.js";
|
|
3
4
|
import { videoEditSchema } from "../admission/schema.js";
|
|
4
5
|
import { subtitleModes, subtitlePositions } from "../subtitles/model.js";
|
|
5
6
|
// "See it before you make it": a few seconds rendered by the real renderer with a project's
|
|
@@ -8,6 +9,8 @@ import { subtitleModes, subtitlePositions } from "../subtitles/model.js";
|
|
|
8
9
|
// How long the preview runs: three images of two seconds, so a transition and a chapter
|
|
9
10
|
// card both show, under six seconds of the sample narration.
|
|
10
11
|
export const stylePreviewSeconds = 6;
|
|
12
|
+
// The longest preview: the template studio's 30-second video sample.
|
|
13
|
+
export const stylePreviewSecondsMax = 30;
|
|
11
14
|
export const stylePreviewTextMax = 200;
|
|
12
15
|
// The sample text Play starts with. It, or no text, captions the sample narration with its own
|
|
13
16
|
// words; any other text is spread over the stretches the narration speaks.
|
|
@@ -47,7 +50,17 @@ export const stylePreviewRequestSchema = z.object({
|
|
|
47
50
|
title: z.string().max(shortTitlePreviewMax).optional(),
|
|
48
51
|
})
|
|
49
52
|
.optional(),
|
|
50
|
-
//
|
|
53
|
+
// How long it runs, in whole seconds; absent is six. The Shorts layout ignores it.
|
|
54
|
+
seconds: z.number().int().min(stylePreviewSeconds).max(stylePreviewSecondsMax).optional(),
|
|
55
|
+
// The run's own picture timing and motion; absent is two-second shots with the defaults.
|
|
56
|
+
timing: z
|
|
57
|
+
.object({
|
|
58
|
+
imageSeconds: z.number().finite().min(1).max(120),
|
|
59
|
+
zoomPercent: z.number().finite().min(0).max(100),
|
|
60
|
+
motionStyle: z.enum(motionStyles),
|
|
61
|
+
})
|
|
62
|
+
.optional(),
|
|
63
|
+
// Make the preview again even when this exact preview is already saved.
|
|
51
64
|
force: z.boolean().optional(),
|
|
52
65
|
});
|
|
53
66
|
export const stylePreviewReplySchema = z.object({
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
2
|
import { mkdirSync, readdirSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
3
3
|
import { join } from "node:path";
|
|
4
|
+
import { errorText } from "../../kernel/errors.js";
|
|
4
5
|
import { normalizeStylePreview, previewSeconds, stylePreviewHash } from "./settings.js";
|
|
5
6
|
// Rendered previews are kept in the data folder by the hash of their settings, so a setting
|
|
6
7
|
// changed back, or the same style in another project, plays at once. `force` renders again
|
|
@@ -86,7 +87,7 @@ function prune(deps) {
|
|
|
86
87
|
}
|
|
87
88
|
catch (error) {
|
|
88
89
|
deps.log.write("warn", "style-preview.prune", {
|
|
89
|
-
detail:
|
|
90
|
+
detail: errorText(error),
|
|
90
91
|
});
|
|
91
92
|
}
|
|
92
93
|
}
|
|
@@ -61,8 +61,27 @@ image) {
|
|
|
61
61
|
},
|
|
62
62
|
chapterCard: edit.chapterCards ? { fontId: subtitles.fontId } : null,
|
|
63
63
|
...(image === undefined ? {} : { image }),
|
|
64
|
+
...(request.seconds === undefined || request.seconds === stylePreviewSeconds
|
|
65
|
+
? {}
|
|
66
|
+
: { seconds: request.seconds }),
|
|
67
|
+
...(request.timing === undefined
|
|
68
|
+
? {}
|
|
69
|
+
: {
|
|
70
|
+
timing: {
|
|
71
|
+
imageSeconds: Math.round(request.timing.imageSeconds * 10) / 10,
|
|
72
|
+
zoomPercent: Math.round(request.timing.zoomPercent * 10) / 10,
|
|
73
|
+
motionStyle: request.timing.motionStyle,
|
|
74
|
+
},
|
|
75
|
+
}),
|
|
64
76
|
};
|
|
65
77
|
}
|
|
78
|
+
// The shots a preview is cut into: two seconds each by default, else the run's own picture
|
|
79
|
+
// length, as many as fill its seconds (at least one).
|
|
80
|
+
export function previewShots(settings) {
|
|
81
|
+
const seconds = settings.seconds ?? stylePreviewSeconds;
|
|
82
|
+
const shotSeconds = settings.timing?.imageSeconds ?? stylePreviewSeconds / 3;
|
|
83
|
+
return { shotSeconds, shots: Math.max(1, Math.round(seconds / shotSeconds)) };
|
|
84
|
+
}
|
|
66
85
|
// JSON with every object's keys in order, so equal settings always hash alike.
|
|
67
86
|
export function stableJson(value) {
|
|
68
87
|
if (Array.isArray(value))
|
|
@@ -80,9 +99,10 @@ export function stylePreviewHash(settings) {
|
|
|
80
99
|
}
|
|
81
100
|
// How long the rendered preview runs: a Shorts preview at a higher speed is shorter.
|
|
82
101
|
export function previewSeconds(settings) {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
102
|
+
if (settings.short !== undefined)
|
|
103
|
+
return round(stylePreviewSeconds / settings.short.speed);
|
|
104
|
+
const { shotSeconds, shots } = previewShots(settings);
|
|
105
|
+
return round(shotSeconds * shots);
|
|
86
106
|
}
|
|
87
107
|
// ceiling: a pause this long between two words of the sample narration starts a new phrase,
|
|
88
108
|
// the same pause `captionCues` starts a new cue at.
|
|
@@ -131,8 +151,16 @@ export function previewWords(text, narration = sampleNarrationWords) {
|
|
|
131
151
|
}
|
|
132
152
|
return timed;
|
|
133
153
|
}
|
|
134
|
-
|
|
135
|
-
|
|
154
|
+
// The captions of `seconds` of preview: the six seconds' words again every six seconds, as the
|
|
155
|
+
// sample narration repeats under a longer preview.
|
|
156
|
+
export function previewCues(text, seconds = stylePreviewSeconds) {
|
|
157
|
+
const once = previewWords(text);
|
|
158
|
+
const words = [];
|
|
159
|
+
for (let start = 0; start < seconds; start += stylePreviewSeconds)
|
|
160
|
+
for (const word of once)
|
|
161
|
+
if (start + word.end <= seconds)
|
|
162
|
+
words.push({ ...word, start: round(start + word.start), end: round(start + word.end) });
|
|
163
|
+
return captionCues(words);
|
|
136
164
|
}
|
|
137
165
|
function round(value) {
|
|
138
166
|
return Math.round(value * 1000) / 1000;
|
|
@@ -24,7 +24,7 @@ export function captionCues(words) {
|
|
|
24
24
|
!Number.isFinite(word.end) ||
|
|
25
25
|
word.start < previousEnd - 0.001 ||
|
|
26
26
|
word.end <= word.start) {
|
|
27
|
-
throw new Error("The saved caption timing is damaged.
|
|
27
|
+
throw new Error("The saved caption timing is damaged. Press Make the video again in the project's Video section to time them again, then Try again.");
|
|
28
28
|
}
|
|
29
29
|
const first = pending[0];
|
|
30
30
|
if (first !== undefined &&
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { errorText } from "../../kernel/errors.js";
|
|
1
2
|
// The collector URL is built into the release and is not user
|
|
2
3
|
// configurable. The environment variable below is a test seam, not a documented knob:
|
|
3
4
|
// packages/app/test/telemetry-flush.test.ts points it at a fake collector.
|
|
@@ -42,10 +43,7 @@ export function httpPostEvents(endpoint, timeoutMs) {
|
|
|
42
43
|
catch (error) {
|
|
43
44
|
// Offline is the ordinary case, not a fault: the events stay queued and the user is
|
|
44
45
|
// told nothing.
|
|
45
|
-
return { ok: false, retriable: true, reason:
|
|
46
|
+
return { ok: false, retriable: true, reason: errorText(error) };
|
|
46
47
|
}
|
|
47
48
|
};
|
|
48
49
|
}
|
|
49
|
-
function messageOf(error) {
|
|
50
|
-
return error instanceof Error ? error.message : String(error);
|
|
51
|
-
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { errorText } from "../../kernel/errors.js";
|
|
1
2
|
import { machineOf, markDelivered, undeliveredEvents } from "./repo.js";
|
|
2
3
|
// ceiling: 200 events per request against the collector's cap of 500, and at most 25
|
|
3
4
|
// requests per flush. A queue longer than 5000 undelivered events drains over several
|
|
@@ -75,7 +76,7 @@ export function createFlusher(deps, delayMs) {
|
|
|
75
76
|
.catch((error) => {
|
|
76
77
|
// The timer has no caller to fail: a broken flush is logged and the next one
|
|
77
78
|
// tries again.
|
|
78
|
-
deps.log.write("warn", "telemetry.flush", { detail:
|
|
79
|
+
deps.log.write("warn", "telemetry.flush", { detail: errorText(error) });
|
|
79
80
|
})
|
|
80
81
|
.finally(() => {
|
|
81
82
|
running = false;
|
|
@@ -106,6 +107,3 @@ function envelope(event, machineId) {
|
|
|
106
107
|
createdAt: event.createdAt,
|
|
107
108
|
};
|
|
108
109
|
}
|
|
109
|
-
function messageOf(error) {
|
|
110
|
-
return error instanceof Error ? error.message : String(error);
|
|
111
|
-
}
|
|
@@ -8,13 +8,6 @@ export const telemetryEventTypes = ["install", "project.created", "stage.complet
|
|
|
8
8
|
// writes the intro and outro texts, the audio stage narrates all three - so the event type
|
|
9
9
|
// stays `stage.completed` and the pair (stage, segment) says which unit it is.
|
|
10
10
|
export const audioSegments = ["body", "intro", "outro"];
|
|
11
|
-
export const noTokens = { tokensIn: 0, tokensOut: 0 };
|
|
12
|
-
export function plusUsage(tokens, usage) {
|
|
13
|
-
return {
|
|
14
|
-
tokensIn: tokens.tokensIn + (usage?.inputTokens ?? 0),
|
|
15
|
-
tokensOut: tokens.tokensOut + (usage?.outputTokens ?? 0),
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
11
|
// The whole privacy surface. API keys, prompt bodies, keyword values, titles, article and
|
|
19
12
|
// research text, files, filenames, OS, locale and hardware are all barred from a payload,
|
|
20
13
|
// which is exactly what the first-run notice promises. The schema below is strict, so a
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { errorText } from "../../kernel/errors.js";
|
|
1
2
|
import { payloadSchema } from "./model.js";
|
|
2
3
|
import { insertTelemetryEvent, machineOf } from "./repo.js";
|
|
3
4
|
// Appends one row to the local queue and hands it back. Throws: the notice dismissal
|
|
@@ -32,10 +33,16 @@ export function record(deps, type, counters) {
|
|
|
32
33
|
}
|
|
33
34
|
catch (error) {
|
|
34
35
|
deps.log.write("warn", "telemetry.record", {
|
|
35
|
-
detail: `${type}: ${
|
|
36
|
+
detail: `${type}: ${errorText(error)}`,
|
|
36
37
|
});
|
|
37
38
|
}
|
|
38
39
|
}
|
|
39
|
-
|
|
40
|
-
|
|
40
|
+
// A template studio sample (or bake-off copy) is the studio's, not a video of the person's:
|
|
41
|
+
// Settings → Usage and the public counters leave its stages out.
|
|
42
|
+
export function skippingProjects(count, skipped) {
|
|
43
|
+
return (type, counters, projectId) => {
|
|
44
|
+
if (projectId !== undefined && skipped(projectId))
|
|
45
|
+
return;
|
|
46
|
+
count(type, counters, projectId);
|
|
47
|
+
};
|
|
41
48
|
}
|