@gentbajko/slopify 3.25.9 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/account-limits.js +30 -0
- package/dist/adapters/alignment/audio.js +1 -1
- package/dist/adapters/alignment/cache.js +4 -6
- package/dist/adapters/alignment/ctc.js +1 -2
- package/dist/adapters/alignment/lock.js +4 -3
- package/dist/adapters/alignment/multilingual.js +2 -4
- package/dist/adapters/alignment/prefetch.js +2 -1
- package/dist/adapters/alignment/runner.js +1 -1
- package/dist/adapters/alignment/worker.js +3 -2
- package/dist/adapters/explain.js +10 -12
- package/dist/adapters/ffmpeg.js +19 -1
- package/dist/adapters/host-cli/index.js +21 -4
- package/dist/adapters/host-cli/transport.js +2 -1
- package/dist/adapters/http-failure.js +53 -0
- package/dist/adapters/image/bytes.js +2 -1
- package/dist/adapters/image/codex.js +42 -9
- package/dist/adapters/image/fal.js +21 -53
- package/dist/adapters/image/google.js +33 -56
- package/dist/adapters/image/models.js +2 -2
- package/dist/adapters/image/openai.js +22 -48
- package/dist/adapters/image/reference.js +36 -0
- package/dist/adapters/image/replicate.js +21 -49
- package/dist/adapters/image/video.js +2 -1
- package/dist/adapters/interest/search-interest.js +113 -0
- package/dist/adapters/key-probes.js +54 -3
- package/dist/adapters/llm/antigravity-models.js +1 -1
- package/dist/adapters/llm/antigravity.js +11 -6
- package/dist/adapters/llm/assistant-cli.js +388 -0
- package/dist/adapters/llm/child-session.js +83 -0
- package/dist/adapters/llm/claude-code-models.js +52 -99
- package/dist/adapters/llm/claude-code.js +16 -4
- package/dist/adapters/llm/codex-limits.js +27 -68
- package/dist/adapters/llm/codex-models.js +1 -1
- package/dist/adapters/llm/codex-server-models.js +61 -109
- package/dist/adapters/llm/codex.js +12 -1
- package/dist/adapters/llm/document-workspace.js +3 -2
- package/dist/adapters/llm/image-workspace.js +3 -2
- package/dist/adapters/llm/openrouter.js +12 -48
- package/dist/adapters/llm/run-cli.js +9 -24
- package/dist/adapters/llm/sse-lines.js +5 -1
- package/dist/adapters/model-access.js +37 -0
- package/dist/adapters/tts/cartesia.js +15 -46
- package/dist/adapters/tts/elevenlabs.js +20 -52
- package/dist/adapters/tts/gemini.js +21 -41
- package/dist/adapters/tts/inworld-async.js +6 -2
- package/dist/adapters/tts/inworld.js +6 -2
- package/dist/adapters/tts/openai.js +20 -50
- package/dist/adapters/tts/system.js +2 -1
- package/dist/assets/models-lifecycle.yaml +6 -0
- package/dist/assistant-wiring.js +60 -0
- package/dist/autopilot-timers.js +59 -0
- package/dist/catalog/lifecycle.js +52 -0
- package/dist/catalog/propose.js +204 -0
- package/dist/catalog/registry.js +23 -14
- package/dist/catalog/schema.js +4 -1
- package/dist/catalog/store.js +39 -0
- package/dist/catalog/validate.js +5 -2
- package/dist/edge/autostart/native.js +3 -5
- package/dist/edge/autostart/prompt.js +2 -1
- package/dist/edge/autostart/service.js +3 -4
- package/dist/edge/cli-args.js +3 -4
- package/dist/edge/cli.js +2 -1
- package/dist/edge/docker-install/apply.js +11 -11
- package/dist/edge/docker-install/run.js +2 -1
- package/dist/edge/docker-install/state.js +4 -3
- package/dist/edge/docker-install/tree.js +2 -4
- package/dist/edge/docker-install/volume.js +3 -2
- package/dist/edge/docker.js +5 -4
- package/dist/edge/events/hub.js +5 -5
- package/dist/edge/http/actions.js +11 -32
- package/dist/edge/http/actor.js +5 -3
- package/dist/edge/http/app.js +86 -11
- package/dist/edge/http/assistant.js +129 -0
- package/dist/edge/http/audio-preview.js +4 -11
- package/dist/edge/http/auditions.js +1 -1
- package/dist/edge/http/autostart.js +5 -5
- package/dist/edge/http/backups.js +2 -4
- package/dist/edge/http/channel-memory.js +9 -22
- package/dist/edge/http/channels.js +14 -27
- package/dist/edge/http/checkpoints.js +39 -21
- package/dist/edge/http/design-templates.js +167 -0
- package/dist/edge/http/designs.js +178 -0
- package/dist/edge/http/diagnostics.js +5 -1
- package/dist/edge/http/document-themes.js +5 -14
- package/dist/edge/http/draft-files.js +1 -3
- package/dist/edge/http/draft-problem.js +5 -10
- package/dist/edge/http/drafts.js +3 -3
- package/dist/edge/http/entries.js +6 -9
- package/dist/edge/http/extension-auth.js +27 -0
- package/dist/edge/http/external-reviews.js +12 -11
- package/dist/edge/http/files.js +5 -11
- package/dist/edge/http/folder-location.js +1 -4
- package/dist/edge/http/fonts.js +0 -7
- package/dist/edge/http/home.js +47 -14
- package/dist/edge/http/host-cli.js +18 -8
- package/dist/edge/http/ids.js +8 -0
- package/dist/edge/http/keywords.js +35 -0
- package/dist/edge/http/model-checks.js +132 -0
- package/dist/edge/http/narration-peaks.js +5 -13
- package/dist/edge/http/onboarding.js +30 -26
- package/dist/edge/http/open-folder.js +5 -10
- package/dist/edge/http/outputs.js +7 -14
- package/dist/edge/http/patch-notes.js +6 -12
- package/dist/edge/http/planning.js +3 -7
- package/dist/edge/http/problem.js +2 -4
- package/dist/edge/http/project-create.js +2 -1
- package/dist/edge/http/project-templates.js +31 -19
- package/dist/edge/http/projects.js +24 -16
- package/dist/edge/http/prompts.js +9 -16
- package/dist/edge/http/pronunciations.js +1 -2
- package/dist/edge/http/providers.js +48 -34
- package/dist/edge/http/refusal.js +29 -0
- package/dist/edge/http/remote-access.js +40 -0
- package/dist/edge/http/remote-guard.js +71 -0
- package/dist/edge/http/request-guard.js +91 -0
- package/dist/edge/http/reviews.js +12 -25
- package/dist/edge/http/revision-files.js +6 -11
- package/dist/edge/http/revisions.js +14 -19
- package/dist/edge/http/run-cost.js +1 -2
- package/dist/edge/http/same-page.js +80 -0
- package/dist/edge/http/schedules.js +69 -40
- package/dist/edge/http/settings.js +27 -14
- package/dist/edge/http/social.js +283 -0
- package/dist/edge/http/staging.js +3 -5
- package/dist/edge/http/storage-files.js +5 -7
- package/dist/edge/http/storage.js +33 -25
- package/dist/edge/http/studio.js +94 -69
- package/dist/edge/http/style-preview.js +3 -6
- package/dist/edge/http/subtitles.js +3 -17
- package/dist/edge/http/template-studio.js +436 -0
- package/dist/edge/http/trash.js +11 -12
- package/dist/edge/http/tutorial.js +1 -2
- package/dist/edge/http/tutorials.js +5 -11
- package/dist/edge/http/update.js +7 -13
- package/dist/edge/http/waveform.js +3 -6
- package/dist/edge/http/youtube-edits.js +3 -4
- package/dist/edge/mcp/assistant.js +279 -0
- package/dist/edge/mcp/attribution.js +8 -2
- package/dist/edge/mcp/call-route.js +11 -2
- package/dist/edge/mcp/excluded-routes.js +29 -3
- package/dist/edge/mcp/http.js +11 -2
- package/dist/edge/mcp/instructions.js +6 -4
- package/dist/edge/mcp/library-tools.js +9 -5
- package/dist/edge/mcp/remake-tools.js +7 -4
- package/dist/edge/mcp/route-tool.js +35 -15
- package/dist/edge/mcp/server.js +13 -8
- package/dist/edge/mcp/tools-channels.js +11 -9
- package/dist/edge/mcp/tools-designs.js +165 -0
- package/dist/edge/mcp/tools-library.js +19 -7
- package/dist/edge/mcp/tools-planning.js +40 -21
- package/dist/edge/mcp/tools-projects.js +38 -11
- package/dist/edge/mcp/tools-publishing.js +9 -9
- package/dist/edge/mcp/tools-runs.js +23 -10
- package/dist/edge/mcp/tools-schedules.js +32 -8
- package/dist/edge/mcp/tools-setup.js +75 -11
- package/dist/edge/mcp/tools-social.js +47 -0
- package/dist/edge/mcp/tools-storage.js +11 -3
- package/dist/edge/mcp/tools-template-studio.js +166 -0
- package/dist/edge/mcp/tools.js +6 -0
- package/dist/edge/remote-access/cli.js +71 -0
- package/dist/edge/remote-access/model.js +32 -0
- package/dist/edge/remote-access/rules.js +207 -0
- package/dist/edge/remote-access/service.js +203 -0
- package/dist/edge/remote-access/store.js +44 -0
- package/dist/edge/remote-access/views.js +43 -0
- package/dist/extension/slopify-studio-chrome.zip +0 -0
- package/dist/extension/slopify-studio-firefox.zip +0 -0
- package/dist/host-cli/install.js +2 -2
- package/dist/host-cli/open-folder.js +2 -2
- package/dist/host-cli/paths.js +2 -4
- package/dist/host-cli/server.js +4 -4
- package/dist/host-cli/service.js +3 -3
- package/dist/host-cli/status.js +7 -7
- package/dist/kernel/db/migrations/0063-model-checks.sql +20 -0
- package/dist/kernel/db/migrations/0064-template-studio.sql +46 -0
- package/dist/kernel/db/migrations/0065-promise-and-assistant-reviews.sql +58 -0
- package/dist/kernel/db/migrations/0066-assistant.sql +44 -0
- package/dist/kernel/db/migrations/0067-autopilot.sql +6 -0
- package/dist/kernel/db/migrations/0068-topic-scores.sql +17 -0
- package/dist/kernel/db/migrations/0070-designs.sql +53 -0
- package/dist/kernel/db/migrations/0071-design-usage.sql +33 -0
- package/dist/kernel/db/migrations/0072-design-templates.sql +33 -0
- package/dist/kernel/db/migrations/0073-schedule-design-kind.sql +5 -0
- package/dist/kernel/db/migrations/0074-template-bakeoffs.sql +44 -0
- package/dist/kernel/db/migrations/0075-social-posts.sql +25 -0
- package/dist/kernel/db/migrations/0076-channel-social.sql +5 -0
- package/dist/kernel/db/migrations/0077-post-prompts.sql +17 -0
- package/dist/kernel/db/migrations/0078-uploaded-from-links.sql +7 -0
- package/dist/kernel/db/tx.js +2 -4
- package/dist/kernel/errors.js +27 -1
- package/dist/kernel/json-answer.js +15 -0
- package/dist/kernel/lock.js +4 -9
- package/dist/kernel/paths.js +8 -0
- package/dist/kernel/pipeline.js +12 -0
- package/dist/kernel/ports/assistant-cli.js +4 -0
- package/dist/kernel/ports/host-cli.js +3 -0
- package/dist/kernel/ports/interest.js +4 -0
- package/dist/kernel/ports/languages.js +0 -3
- package/dist/kernel/ports/model.js +2 -0
- package/dist/kernel/ports/settings-places.js +31 -0
- package/dist/kernel/ports/system-speech.js +31 -3
- package/dist/kernel/runner/attempt.js +14 -4
- package/dist/kernel/runner/audition.js +3 -1
- package/dist/kernel/runner/checkpoint-authority.js +2 -1
- package/dist/kernel/runner/index.js +8 -10
- package/dist/kernel/runner/model-access.js +40 -0
- package/dist/kernel/runner/model-check.js +153 -0
- package/dist/kernel/runner/providers.js +18 -12
- package/dist/kernel/runner/standalone.js +11 -7
- package/dist/main.js +338 -21
- package/dist/model-catalog.js +20 -0
- package/dist/model-checks.js +166 -0
- package/dist/patch-notes/4.0.0.md +51 -0
- package/dist/patch-notes/4.1.0.md +42 -0
- package/dist/patch-notes/index.json +12 -0
- package/dist/slices/admission/heads.js +2 -1
- package/dist/slices/admission/listing-facts.js +95 -0
- package/dist/slices/admission/repo.js +11 -7
- package/dist/slices/admission/rules.js +50 -15
- package/dist/slices/admission/schema.js +8 -0
- package/dist/slices/admission/stage-writes.js +0 -3
- package/dist/slices/admission/start.js +48 -31
- package/dist/slices/admission/state-words.js +34 -5
- package/dist/slices/admission/substitute.js +7 -4
- package/dist/slices/agents/attention-posts.js +31 -0
- package/dist/slices/agents/attention-templates.js +33 -0
- package/dist/slices/agents/attention.js +10 -1
- package/dist/slices/agents/connection.js +2 -6
- package/dist/slices/agents/model.js +6 -3
- package/dist/slices/agents/repo.js +15 -7
- package/dist/slices/article/continuation.js +0 -63
- package/dist/slices/article/plain.js +3 -2
- package/dist/slices/article/segments.js +2 -62
- package/dist/slices/assistant/access.js +1 -0
- package/dist/slices/assistant/asks.js +80 -0
- package/dist/slices/assistant/cost.js +54 -0
- package/dist/slices/assistant/gate.js +222 -0
- package/dist/slices/assistant/model.js +86 -0
- package/dist/slices/assistant/names.js +23 -0
- package/dist/slices/assistant/prompt.js +74 -0
- package/dist/slices/assistant/repo.js +74 -0
- package/dist/slices/assistant/tokens.js +18 -0
- package/dist/slices/assistant/turn.js +344 -0
- package/dist/slices/autopilot/buffer.js +76 -0
- package/dist/slices/autopilot/model.js +14 -0
- package/dist/slices/autopilot/notify.js +27 -0
- package/dist/slices/autopilot/repo.js +34 -0
- package/dist/slices/autopilot/signals.js +194 -0
- package/dist/slices/autopilot/warnings.js +85 -0
- package/dist/slices/autopilot/weekly.js +100 -0
- package/dist/slices/backups/files.js +2 -6
- package/dist/slices/backups/repo.js +3 -15
- package/dist/slices/backups/service.js +8 -7
- package/dist/slices/channels/cast-images.js +3 -2
- package/dist/slices/channels/model.js +0 -1
- package/dist/slices/channels/rebrand.js +0 -3
- package/dist/slices/channels/repo.js +4 -0
- package/dist/slices/channels/schema.js +7 -1
- package/dist/slices/channels/service.js +10 -0
- package/dist/slices/channels/videos.js +3 -15
- package/dist/slices/checkpoints/index.js +0 -1
- package/dist/slices/control/providers.js +2 -28
- package/dist/slices/designs/artwork.js +66 -0
- package/dist/slices/designs/budget.js +23 -0
- package/dist/slices/designs/calls.js +124 -0
- package/dist/slices/designs/check-context.js +38 -0
- package/dist/slices/designs/check-text.js +43 -0
- package/dist/slices/designs/fields.js +88 -0
- package/dist/slices/designs/frames.js +34 -0
- package/dist/slices/designs/gate.js +130 -0
- package/dist/slices/designs/layout.js +293 -0
- package/dist/slices/designs/model.js +35 -0
- package/dist/slices/designs/pdf-job.js +23 -0
- package/dist/slices/designs/pdf-pages.js +30 -0
- package/dist/slices/designs/pdf-runner.js +68 -0
- package/dist/slices/designs/pdf-worker.js +24 -0
- package/dist/slices/designs/picture-size.js +79 -0
- package/dist/slices/designs/pictures.js +55 -0
- package/dist/slices/designs/quote.js +24 -0
- package/dist/slices/designs/render-args.js +36 -0
- package/dist/slices/designs/render-input.js +59 -0
- package/dist/slices/designs/render.js +215 -0
- package/dist/slices/designs/repo.js +101 -0
- package/dist/slices/designs/requests.js +80 -0
- package/dist/slices/designs/runner.js +239 -0
- package/dist/slices/designs/sample-repo.js +91 -0
- package/dist/slices/designs/sample.js +223 -0
- package/dist/slices/designs/schema.js +87 -0
- package/dist/slices/designs/sections.js +44 -0
- package/dist/slices/designs/service.js +233 -0
- package/dist/slices/designs/steps-repo.js +102 -0
- package/dist/slices/designs/studio-kind.js +39 -0
- package/dist/slices/designs/template-checks.js +44 -0
- package/dist/slices/designs/template-make.js +118 -0
- package/dist/slices/designs/templates.js +218 -0
- package/dist/slices/document/fonts.js +2 -1
- package/dist/slices/document/model.js +7 -4
- package/dist/slices/document/render.js +2 -1
- package/dist/slices/document/theme-schema.js +1 -1
- package/dist/slices/document/theme.js +49 -3
- package/dist/slices/episodes/summarize.js +6 -2
- package/dist/slices/estimate/index.js +72 -28
- package/dist/slices/estimate/requests.js +4 -4
- package/dist/slices/fixes/rules.js +3 -1
- package/dist/slices/fonts/catalog.js +5 -3
- package/dist/slices/fonts/coverage.js +2 -1
- package/dist/slices/fonts/discovery.js +3 -2
- package/dist/slices/fonts/files.js +2 -6
- package/dist/slices/fonts/index.js +0 -1
- package/dist/slices/fonts/sfnt.js +45 -10
- package/dist/slices/images/appearance.js +8 -16
- package/dist/slices/images/scenes.js +102 -28
- package/dist/slices/keywords/digest.js +85 -0
- package/dist/slices/keywords/facts.js +92 -0
- package/dist/slices/keywords/fill.js +80 -0
- package/dist/slices/keywords/model.js +75 -0
- package/dist/slices/keywords/rules.js +187 -0
- package/dist/slices/keywords/schema.js +28 -0
- package/dist/slices/keywords/specs.js +260 -0
- package/dist/slices/keywords/values.js +74 -0
- package/dist/slices/library/lint.js +29 -12
- package/dist/slices/library/model.js +2 -0
- package/dist/slices/library/photorealistic.js +4 -12
- package/dist/slices/library/rename.js +9 -7
- package/dist/slices/library/save.js +14 -10
- package/dist/slices/library/slots.js +37 -11
- package/dist/slices/library/transfer.js +5 -4
- package/dist/slices/library/used-by.js +25 -10
- package/dist/slices/loudness/loudnorm.js +53 -12
- package/dist/slices/loudness/model.js +3 -2
- package/dist/slices/loudness/sentence-level.js +2 -1
- package/dist/slices/model-checks/cost.js +61 -0
- package/dist/slices/model-checks/listing.js +124 -0
- package/dist/slices/model-checks/model.js +20 -0
- package/dist/slices/model-checks/record.js +32 -0
- package/dist/slices/model-checks/repo.js +120 -0
- package/dist/slices/model-checks/rules.js +125 -0
- package/dist/slices/model-checks/run.js +143 -0
- package/dist/slices/model-checks/service.js +198 -0
- package/dist/slices/model-upkeep/model.js +1 -1
- package/dist/slices/model-upkeep/switch.js +72 -27
- package/dist/slices/model-upkeep/usage.js +39 -13
- package/dist/slices/narration/breaths.js +3 -1
- package/dist/slices/narration/clean-pieces.js +3 -1
- package/dist/slices/narration/concat.js +2 -1
- package/dist/slices/narration/pauses-model.js +3 -2
- package/dist/slices/narration/peaks.js +3 -4
- package/dist/slices/narration/pronunciation-chunks.js +4 -3
- package/dist/slices/narration/pronunciation.js +6 -4
- package/dist/slices/narration/steering.js +4 -3
- package/dist/slices/notifications/notifier.js +4 -3
- package/dist/slices/notifications/rules.js +5 -2
- package/dist/slices/notifications/settings.js +4 -12
- package/dist/slices/notifications/subject.js +4 -3
- package/dist/slices/onboarding/copy.js +21 -3
- package/dist/slices/onboarding/first-run.js +16 -40
- package/dist/slices/onboarding/full-video.js +3 -2
- package/dist/slices/onboarding/install.js +6 -4
- package/dist/slices/onboarding/model.js +26 -37
- package/dist/slices/onboarding/packs.js +22 -22
- package/dist/slices/onboarding/preferred-model.js +14 -0
- package/dist/slices/onboarding/quick-short.js +105 -65
- package/dist/slices/onboarding/sample.js +4 -2
- package/dist/slices/onboarding/state.js +9 -11
- package/dist/slices/onboarding/template.js +8 -6
- package/dist/slices/outputs/add.js +3 -2
- package/dist/slices/outputs/service.js +2 -2
- package/dist/slices/patch-notes/library.js +4 -3
- package/dist/slices/play-drafts/convert.js +4 -0
- package/dist/slices/play-drafts/readiness.js +3 -3
- package/dist/slices/play-drafts/review-inputs.js +9 -3
- package/dist/slices/play-drafts/review.js +5 -4
- package/dist/slices/play-drafts/schema.js +4 -0
- package/dist/slices/play-drafts/service.js +17 -7
- package/dist/slices/project-templates/from-project.js +9 -2
- package/dist/slices/project-templates/next-chapter.js +2 -1
- package/dist/slices/project-templates/provider-defaults.js +22 -0
- package/dist/slices/project-templates/repo.js +6 -1
- package/dist/slices/project-templates/setup-sections.js +26 -0
- package/dist/slices/project-templates/setup.js +14 -1
- package/dist/slices/project-templates/stand-ins.js +22 -0
- package/dist/slices/rebuild/activity.js +2 -0
- package/dist/slices/rebuild/admission-repo.js +3 -2
- package/dist/slices/rebuild/narration-history.js +4 -5
- package/dist/slices/rebuild/narration-retry.js +2 -1
- package/dist/slices/rebuild/preview-details.js +32 -14
- package/dist/slices/rebuild/preview-plan.js +3 -8
- package/dist/slices/rebuild/recipe-build.js +8 -3
- package/dist/slices/rebuild/recipe-describe.js +3 -3
- package/dist/slices/rebuild/recipe-digest.js +58 -0
- package/dist/slices/rebuild/recipe-input-schema.js +10 -0
- package/dist/slices/rebuild/recipe-keywords.js +71 -0
- package/dist/slices/rebuild/recipe-legacy.js +5 -1
- package/dist/slices/rebuild/recipe-model.js +4 -0
- package/dist/slices/rebuild/recipe-narration-text.js +2 -1
- package/dist/slices/rebuild/recipe-preparation.js +4 -4
- package/dist/slices/rebuild/recipe-reference.js +8 -4
- package/dist/slices/rebuild/recipe-reviews.js +27 -7
- package/dist/slices/rebuild/recipe-save.js +8 -5
- package/dist/slices/rebuild/recipe-scenes.js +40 -11
- package/dist/slices/rebuild/recipe-shorts.js +8 -8
- package/dist/slices/rebuild/recipe-social.js +46 -0
- package/dist/slices/rebuild/recipe-text.js +64 -20
- package/dist/slices/rebuild/recipe-validation.js +102 -31
- package/dist/slices/rebuild/recipe-visual.js +55 -16
- package/dist/slices/rebuild/recipe-voices.js +3 -2
- package/dist/slices/rebuild/recipe-work.js +19 -7
- package/dist/slices/rebuild/recipe-youtube.js +4 -3
- package/dist/slices/rebuild/recovery-selection.js +3 -1
- package/dist/slices/rebuild/recovery.js +9 -8
- package/dist/slices/rebuild/remake-outdated.js +5 -5
- package/dist/slices/rebuild/repo.js +4 -3
- package/dist/slices/rebuild/review-promise.js +25 -0
- package/dist/slices/rebuild/review-redo.js +3 -2
- package/dist/slices/rebuild/runtime-admission.js +4 -3
- package/dist/slices/rebuild/runtime-agent-review.js +11 -5
- package/dist/slices/rebuild/runtime-animate.js +10 -9
- package/dist/slices/rebuild/runtime-article.js +7 -5
- package/dist/slices/rebuild/runtime-checkpoints.js +5 -4
- package/dist/slices/rebuild/runtime-document.js +11 -13
- package/dist/slices/rebuild/runtime-export-bed.js +8 -12
- package/dist/slices/rebuild/runtime-export-edit.js +8 -16
- package/dist/slices/rebuild/runtime-export-inputs.js +12 -11
- package/dist/slices/rebuild/runtime-export-short.js +9 -5
- package/dist/slices/rebuild/runtime-export.js +38 -15
- package/dist/slices/rebuild/runtime-figure-card.js +2 -1
- package/dist/slices/rebuild/runtime-image.js +8 -12
- package/dist/slices/rebuild/runtime-instructions.js +2 -0
- package/dist/slices/rebuild/runtime-keywords.js +59 -0
- package/dist/slices/rebuild/runtime-lines.js +2 -11
- package/dist/slices/rebuild/runtime-local.js +17 -22
- package/dist/slices/rebuild/runtime-narration-publication.js +2 -5
- package/dist/slices/rebuild/runtime-narration-reuse.js +9 -13
- package/dist/slices/rebuild/runtime-narration-text.js +13 -17
- package/dist/slices/rebuild/runtime-pictures.js +2 -4
- package/dist/slices/rebuild/runtime-piece-label.js +10 -6
- package/dist/slices/rebuild/runtime-plan.js +31 -5
- package/dist/slices/rebuild/runtime-provider.js +67 -25
- package/dist/slices/rebuild/runtime-publication.js +10 -9
- package/dist/slices/rebuild/runtime-review.js +39 -33
- package/dist/slices/rebuild/runtime-run.js +4 -1
- package/dist/slices/rebuild/runtime-shorts.js +31 -50
- package/dist/slices/rebuild/runtime-store.js +20 -10
- package/dist/slices/rebuild/runtime-subtitles.js +28 -25
- package/dist/slices/rebuild/runtime-voices.js +10 -16
- package/dist/slices/rebuild/runtime-youtube.js +14 -31
- package/dist/slices/rebuild/service-readiness.js +11 -3
- package/dist/slices/rebuild/transition-repo.js +6 -5
- package/dist/slices/rebuild/work-records.js +6 -0
- package/dist/slices/reruns/cascade.js +1 -2
- package/dist/slices/reruns/index.js +6 -9
- package/dist/slices/research/synthesis.js +3 -2
- package/dist/slices/reviews/external-model.js +4 -1
- package/dist/slices/reviews/external-repo.js +2 -1
- package/dist/slices/reviews/external-rows.js +2 -3
- package/dist/slices/reviews/holds.js +5 -4
- package/dist/slices/reviews/model.js +32 -11
- package/dist/slices/reviews/repo.js +2 -1
- package/dist/slices/reviews/rules.js +4 -3
- package/dist/slices/reviews/verdict.js +2 -1
- package/dist/slices/reviews/view.js +5 -2
- package/dist/slices/revisions/downloads.js +4 -5
- package/dist/slices/revisions/image-plan.js +1 -1
- package/dist/slices/revisions/mutation-assets.js +9 -5
- package/dist/slices/revisions/mutation-cues.js +2 -5
- package/dist/slices/revisions/mutations.js +3 -3
- package/dist/slices/revisions/repo.js +3 -1
- package/dist/slices/revisions/schema.js +1 -0
- package/dist/slices/revisions/view.js +20 -0
- package/dist/slices/run-cost/limits.js +5 -2
- package/dist/slices/run-cost/meter.js +12 -5
- package/dist/slices/run-cost/panel.js +8 -74
- package/dist/slices/run-cost/plan-readings.js +127 -0
- package/dist/slices/run-cost/plan-use.js +169 -0
- package/dist/slices/run-cost/pricing.js +3 -3
- package/dist/slices/run-cost/week.js +32 -4
- package/dist/slices/schedules/agenda.js +18 -7
- package/dist/slices/schedules/by-date.js +42 -0
- package/dist/slices/schedules/calendar.js +5 -0
- package/dist/slices/schedules/design-agenda.js +36 -0
- package/dist/slices/schedules/design-check.js +41 -0
- package/dist/slices/schedules/design-run.js +126 -0
- package/dist/slices/schedules/next-run.js +62 -0
- package/dist/slices/schedules/prepare.js +18 -2
- package/dist/slices/schedules/repo.js +30 -21
- package/dist/slices/schedules/rescore.js +35 -0
- package/dist/slices/schedules/scheduler.js +13 -3
- package/dist/slices/schedules/schema.js +57 -3
- package/dist/slices/schedules/score.js +107 -0
- package/dist/slices/schedules/service.js +57 -24
- package/dist/slices/schedules/topic-list.js +15 -0
- package/dist/slices/schedules/topic-scores.js +104 -0
- package/dist/slices/schedules/topics.js +53 -41
- package/dist/slices/settings/cli-paths.js +4 -6
- package/dist/slices/settings/first-run.js +8 -43
- package/dist/slices/settings/health.js +30 -15
- package/dist/slices/settings/key-test.js +1 -1
- package/dist/slices/settings/model-reach.js +3 -17
- package/dist/slices/settings/model.js +14 -2
- package/dist/slices/settings/playback.js +34 -23
- package/dist/slices/settings/probe-read.js +16 -0
- package/dist/slices/settings/repo.js +33 -0
- package/dist/slices/settings/tutorial.js +2 -2
- package/dist/slices/settings/voices.js +4 -12
- package/dist/slices/shorts/keep.js +2 -1
- package/dist/slices/shorts/pick.js +6 -18
- package/dist/slices/shorts/prompts.js +4 -14
- package/dist/slices/shorts/render.js +6 -2
- package/dist/slices/social/channel.js +44 -0
- package/dist/slices/social/defaults.js +17 -0
- package/dist/slices/social/due.js +36 -0
- package/dist/slices/social/extension.js +18 -0
- package/dist/slices/social/fit.js +115 -0
- package/dist/slices/social/limits.js +186 -0
- package/dist/slices/social/links.js +21 -0
- package/dist/slices/social/media.js +132 -0
- package/dist/slices/social/model.js +75 -0
- package/dist/slices/social/notice.js +19 -0
- package/dist/slices/social/pack.js +176 -0
- package/dist/slices/social/post-prompt.js +56 -0
- package/dist/slices/social/queue.js +31 -0
- package/dist/slices/social/repo.js +133 -0
- package/dist/slices/social/reshape.js +97 -0
- package/dist/slices/social/rules.js +5 -0
- package/dist/slices/social/schema.js +70 -0
- package/dist/slices/social/serve.js +51 -0
- package/dist/slices/social/service.js +129 -0
- package/dist/slices/social/settings.js +21 -0
- package/dist/slices/social/sources.js +114 -0
- package/dist/slices/social/state.js +110 -0
- package/dist/slices/social/text.js +149 -0
- package/dist/slices/storage/arrange.js +3 -1
- package/dist/slices/storage/assets.js +8 -10
- package/dist/slices/storage/backup-designs.js +74 -0
- package/dist/slices/storage/backup-export.js +8 -3
- package/dist/slices/storage/backup-format.js +10 -0
- package/dist/slices/storage/backup-import.js +22 -4
- package/dist/slices/storage/delete-project.js +6 -5
- package/dist/slices/storage/files-location.js +6 -8
- package/dist/slices/storage/layout.js +13 -2
- package/dist/slices/storage/model.js +3 -0
- package/dist/slices/storage/portable.js +17 -12
- package/dist/slices/storage/schema.js +2 -0
- package/dist/slices/storage/staging-refs.js +2 -1
- package/dist/slices/storage/staging.js +6 -9
- package/dist/slices/storage/trim.js +26 -9
- package/dist/slices/studio/calendar.js +7 -2
- package/dist/slices/studio/disclosure.js +4 -4
- package/dist/slices/studio/model.js +1 -1
- package/dist/slices/studio/pack.js +9 -8
- package/dist/slices/studio/pick.js +2 -11
- package/dist/slices/studio/plan.js +7 -16
- package/dist/slices/studio/queue.js +3 -14
- package/dist/slices/studio/releases.js +26 -0
- package/dist/slices/studio/settings.js +20 -57
- package/dist/slices/studio/videos.js +35 -4
- package/dist/slices/style-preview/render.js +37 -16
- package/dist/slices/style-preview/schema.js +14 -1
- package/dist/slices/style-preview/service.js +2 -1
- package/dist/slices/style-preview/settings.js +33 -5
- package/dist/slices/subtitles/captions.js +1 -1
- package/dist/slices/telemetry/collector-client.js +2 -4
- package/dist/slices/telemetry/flush.js +2 -4
- package/dist/slices/telemetry/model.js +0 -7
- package/dist/slices/telemetry/record.js +10 -3
- package/dist/slices/template-studio/anatomy-view.js +161 -0
- package/dist/slices/template-studio/anatomy.js +73 -0
- package/dist/slices/template-studio/bakeoff-make.js +225 -0
- package/dist/slices/template-studio/bakeoff-repo.js +83 -0
- package/dist/slices/template-studio/bakeoff.js +333 -0
- package/dist/slices/template-studio/budget.js +106 -0
- package/dist/slices/template-studio/cards.js +78 -0
- package/dist/slices/template-studio/checks.js +322 -0
- package/dist/slices/template-studio/document-sample.js +56 -0
- package/dist/slices/template-studio/edit.js +15 -0
- package/dist/slices/template-studio/for-all.js +161 -0
- package/dist/slices/template-studio/free-video.js +31 -0
- package/dist/slices/template-studio/free.js +176 -0
- package/dist/slices/template-studio/gate.js +40 -0
- package/dist/slices/template-studio/hidden.js +20 -0
- package/dist/slices/template-studio/jobs.js +79 -0
- package/dist/slices/template-studio/loudness.js +111 -0
- package/dist/slices/template-studio/make.js +40 -0
- package/dist/slices/template-studio/model.js +58 -0
- package/dist/slices/template-studio/pack-import.js +253 -0
- package/dist/slices/template-studio/pack-samples.js +60 -0
- package/dist/slices/template-studio/pack.js +207 -0
- package/dist/slices/template-studio/paid-view.js +66 -0
- package/dist/slices/template-studio/paid.js +355 -0
- package/dist/slices/template-studio/quote.js +155 -0
- package/dist/slices/template-studio/ready.js +104 -0
- package/dist/slices/template-studio/repo.js +134 -0
- package/dist/slices/template-studio/reviews-path.js +58 -0
- package/dist/slices/template-studio/runner.js +84 -0
- package/dist/slices/template-studio/save.js +236 -0
- package/dist/slices/template-studio/say-it-as.js +248 -0
- package/dist/slices/template-studio/schedule-gate.js +34 -0
- package/dist/slices/template-studio/schedule-price.js +32 -0
- package/dist/slices/template-studio/schedule-sample.js +91 -0
- package/dist/slices/template-studio/schema.js +243 -0
- package/dist/slices/template-studio/scope.js +124 -0
- package/dist/slices/template-studio/sections.js +176 -0
- package/dist/slices/template-studio/service.js +175 -0
- package/dist/slices/template-studio/status.js +191 -0
- package/dist/slices/template-studio/topic.js +223 -0
- package/dist/slices/thumbnail/by-llm.js +1 -1
- package/dist/slices/trash/designs.js +76 -0
- package/dist/slices/trash/model.js +13 -4
- package/dist/slices/trash/service.js +52 -2
- package/dist/slices/tutorials/library.js +3 -2
- package/dist/slices/uploads/repo.js +37 -1
- package/dist/slices/uploads/rules.js +3 -2
- package/dist/slices/video/ass-text.js +17 -0
- package/dist/slices/video/audio-export.js +2 -64
- package/dist/slices/video/edit-list.js +2 -2
- package/dist/slices/video/edit-settings.js +1 -1
- package/dist/slices/video/encoding.js +169 -0
- package/dist/slices/video/ffmpeg.js +23 -21
- package/dist/slices/video/figure-card.js +1 -15
- package/dist/slices/video/plan.js +2 -1
- package/dist/slices/video/slideshow.js +43 -18
- package/dist/slices/voices/attribution.js +3 -2
- package/dist/slices/voices/model.js +9 -8
- package/dist/slices/voices/palette.js +0 -3
- package/dist/slices/voices/script.js +2 -1
- package/dist/slices/youtube/answer.js +4 -16
- package/dist/slices/youtube/edits-repo.js +3 -12
- package/dist/tutorials/AI-CLIs.md +25 -25
- package/dist/tutorials/Agents-MCP.md +34 -33
- package/dist/tutorials/Assistant.md +42 -0
- package/dist/tutorials/Backups.md +7 -7
- package/dist/tutorials/Calendar.md +17 -25
- package/dist/tutorials/Cast-Library.md +19 -19
- package/dist/tutorials/Channels.md +42 -35
- package/dist/tutorials/Costs-and-Run-Cost.md +38 -40
- package/dist/tutorials/Create-Article.md +114 -0
- package/dist/tutorials/Create-Extras.md +112 -0
- package/dist/tutorials/Create-Images.md +165 -0
- package/dist/tutorials/Create-Narration.md +178 -0
- package/dist/tutorials/Create-Overview.md +244 -0
- package/dist/tutorials/Create-Video-and-Style.md +144 -0
- package/dist/tutorials/Docker.md +3 -3
- package/dist/tutorials/Document-Themes.md +32 -32
- package/dist/tutorials/Editing-a-Project.md +94 -94
- package/dist/tutorials/FAQ.md +18 -18
- package/dist/tutorials/First-Launch-and-Welcome.md +50 -64
- package/dist/tutorials/Home-and-Projects.md +115 -71
- package/dist/tutorials/Home.md +33 -33
- package/dist/tutorials/Install.md +14 -13
- package/dist/tutorials/Intros-and-Outros.md +33 -34
- package/dist/tutorials/Keyboard-Shortcuts-and-Command-Palette.md +62 -58
- package/dist/tutorials/Keywords-Slopify-Fills.md +87 -0
- package/dist/tutorials/Models.md +53 -21
- package/dist/tutorials/Multiple-Voices.md +41 -40
- package/dist/tutorials/Narration-Aliases-and-Glossary.md +14 -14
- package/dist/tutorials/Notifications.md +27 -17
- package/dist/tutorials/Other-Languages.md +15 -15
- package/dist/tutorials/PDF-Documents.md +38 -29
- package/dist/tutorials/Posting-to-Social-Sites.md +121 -0
- package/dist/tutorials/Project-Page.md +118 -120
- package/dist/tutorials/Prompts-and-Templates.md +84 -0
- package/dist/tutorials/Prompts.md +48 -44
- package/dist/tutorials/Providers-and-Keys.md +105 -98
- package/dist/tutorials/Publishing-to-YouTube.md +31 -31
- package/dist/tutorials/Recovery-and-Retries.md +31 -31
- package/dist/tutorials/Remote-Access.md +63 -0
- package/dist/tutorials/Reviews-and-Checkpoints.md +98 -90
- package/dist/tutorials/Schedules.md +46 -27
- package/dist/tutorials/Settings-Reference.md +194 -174
- package/dist/tutorials/Shorts.md +34 -33
- package/dist/tutorials/Start-at-Login.md +3 -3
- package/dist/tutorials/Studio-Extension.md +22 -24
- package/dist/tutorials/Template-Studio.md +128 -0
- package/dist/tutorials/Templates.md +51 -77
- package/dist/tutorials/Trash.md +4 -4
- package/dist/tutorials/Troubleshooting.md +44 -44
- package/dist/tutorials/Uninstalling-and-Moving.md +5 -5
- package/dist/tutorials/Updating-and-Patch-Notes.md +18 -18
- package/dist/tutorials/Video-Editing.md +34 -34
- package/dist/tutorials/Where-Your-Files-Live.md +10 -10
- package/dist/tutorials/YouTube-Description.md +26 -26
- package/dist/tutorials/Your-First-Short.md +35 -35
- package/dist/tutorials/_Sidebar.md +19 -14
- package/dist/updater/work-in-progress.js +42 -12
- package/dist/web/assets/index-BNftKQrA.css +1 -0
- package/dist/web/assets/index-Cpa58woP.js +459 -0
- package/dist/web/assets/pdf-BKh8f7R6.js +56 -0
- package/dist/web/assets/pdf.worker.min-BmVo14Nb.mjs +28 -0
- package/dist/web/assets/pdf.worker.min-D7i8o3wR.js +1 -0
- package/dist/web/index.html +2 -2
- package/package.json +6 -2
- package/dist/slices/article/provided-entries.js +0 -66
- package/dist/slices/article/run.js +0 -145
- package/dist/slices/images/run.js +0 -234
- package/dist/slices/narration/legacy-plan.js +0 -58
- package/dist/slices/narration/run.js +0 -270
- package/dist/slices/rebuild/runtime-actions.js +0 -90
- package/dist/slices/research/run.js +0 -224
- package/dist/slices/subtitles/prepare.js +0 -194
- package/dist/slices/subtitles/transcript.js +0 -34
- package/dist/slices/thumbnail/run.js +0 -219
- package/dist/slices/video/audio-inputs.js +0 -33
- package/dist/slices/video/reuse-audio.js +0 -62
- package/dist/slices/video/run.js +0 -78
- package/dist/slices/video/write-export.js +0 -158
- package/dist/slices/video/write-subtitles.js +0 -59
- package/dist/tutorials/Library-Overview.md +0 -76
- package/dist/tutorials/Play-Images.md +0 -161
- package/dist/tutorials/Play-Narration.md +0 -167
- package/dist/tutorials/Play-Outputs.md +0 -109
- package/dist/tutorials/Play-Overview.md +0 -227
- package/dist/tutorials/Play-Title-and-Article.md +0 -136
- package/dist/tutorials/Play-Video-and-Style.md +0 -143
- package/dist/web/assets/index-BadsoORk.css +0 -1
- package/dist/web/assets/index-D8LqNsCl.js +0 -326
- package/dist/web/assets/pdf-T7MCwjIv.js +0 -54
- package/dist/web/assets/pdf.worker.min-Dswkl-cV.mjs +0 -29
- package/dist/web/assets/pdf.worker.min-zC6nfbxG.js +0 -1
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
import { detectSlots, filledKeywords } from "../admission/substitute.js";
|
|
2
|
+
import { isReserved } from "../keywords/model.js";
|
|
3
|
+
import { topicKeywords } from "../project-templates/one-off.js";
|
|
4
|
+
import { withProviderDefaults, } from "../project-templates/provider-defaults.js";
|
|
5
|
+
import { usesPostPrompt } from "../social/rules.js";
|
|
6
|
+
import { sectionLabel } from "./model.js";
|
|
7
|
+
export const freeCheckIds = [
|
|
8
|
+
"keywords",
|
|
9
|
+
"providers",
|
|
10
|
+
"voice",
|
|
11
|
+
"release-slots",
|
|
12
|
+
"monthly-cost",
|
|
13
|
+
"answerers",
|
|
14
|
+
];
|
|
15
|
+
const nameOf = (schedule) => schedule.paused === true ? `${schedule.name} (paused)` : schedule.name;
|
|
16
|
+
export const studioHref = (templateId, section) => `/templates/${encodeURIComponent(templateId)}?section=${section}`;
|
|
17
|
+
const scheduleHref = (id) => `/calendar?tab=schedules&schedule=${encodeURIComponent(id)}`;
|
|
18
|
+
const weekdays = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
|
|
19
|
+
const agentWindowMs = 7 * 24 * 60 * 60 * 1000;
|
|
20
|
+
// The checks in order. Providers is one line per missing thing, each with its own fix, so the
|
|
21
|
+
// count of lines to fix is the count of things to fix. A run that can't start can't be priced
|
|
22
|
+
// either: while a line above says why, the monthly cost's line would only say it again, so it
|
|
23
|
+
// waits until they are fixed.
|
|
24
|
+
export function freeChecks(input) {
|
|
25
|
+
const start = [keywordsCheck(input), ...providersChecks(input), voiceCheck(input)];
|
|
26
|
+
const blocked = start.some((check) => !check.ok);
|
|
27
|
+
const cost = monthlyCostCheck(input);
|
|
28
|
+
return [
|
|
29
|
+
...start,
|
|
30
|
+
releaseSlotsCheck(input),
|
|
31
|
+
...(blocked && !cost.ok ? [] : [cost]),
|
|
32
|
+
answerersCheck(input),
|
|
33
|
+
];
|
|
34
|
+
}
|
|
35
|
+
function list(names) {
|
|
36
|
+
if (names.length <= 1)
|
|
37
|
+
return names.join("");
|
|
38
|
+
return `${names.slice(0, -1).join(", ")} and ${names.at(-1) ?? ""}`;
|
|
39
|
+
}
|
|
40
|
+
// A keyword is filled when it has a value, is the topic a schedule fills each run, or is one
|
|
41
|
+
// Slopify fills itself ({{Scene}}, {{Appearance}} and every {{Slopify_…}} name).
|
|
42
|
+
function keywordsCheck(input) {
|
|
43
|
+
const { form } = input.document;
|
|
44
|
+
const topics = new Set([
|
|
45
|
+
...topicKeywords(form.title),
|
|
46
|
+
...input.schedules.flatMap((schedule) => schedule.topicKeyword === null ? [] : [schedule.topicKeyword]),
|
|
47
|
+
]);
|
|
48
|
+
const names = new Set([form.title, ...input.bodies].flatMap((body) => detectSlots(body).names));
|
|
49
|
+
const empty = [...names].filter((name) => !topics.has(name) &&
|
|
50
|
+
!filledKeywords.includes(name) &&
|
|
51
|
+
// The keywords registry's: an unknown Slopify_ name is refused when the prompt is saved.
|
|
52
|
+
!isReserved(name) &&
|
|
53
|
+
(form.values[name] ?? "").trim() === "");
|
|
54
|
+
if (empty.length === 0)
|
|
55
|
+
return {
|
|
56
|
+
id: "keywords",
|
|
57
|
+
ok: true,
|
|
58
|
+
sentence: "Every keyword has a value or is filled per video.",
|
|
59
|
+
};
|
|
60
|
+
return {
|
|
61
|
+
id: "keywords",
|
|
62
|
+
ok: false,
|
|
63
|
+
sentence: `${empty.length === 1 ? "A keyword is" : "Keywords are"} empty: ${list(empty.map((name) => `{{${name}}}`))}. A run would send the prompt with nothing in ${empty.length === 1 ? "its place" : "their place"}.`,
|
|
64
|
+
fix: {
|
|
65
|
+
label: `Fill them in ${sectionLabel.subject}`,
|
|
66
|
+
href: studioHref(input.templateId, "subject"),
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
function usedProviders(document) {
|
|
71
|
+
const { form } = document;
|
|
72
|
+
const generates = (source) => source !== undefined && source !== "off" && source !== "provide";
|
|
73
|
+
const text = generates(form.sources.research) ||
|
|
74
|
+
generates(form.sources.article) ||
|
|
75
|
+
form.sources.thumbnail === "prompt_by_llm" ||
|
|
76
|
+
form.youtubeDescription === true ||
|
|
77
|
+
usesPostPrompt(form) ||
|
|
78
|
+
form.shorts?.enabled === true;
|
|
79
|
+
const reviews = form.reviews !== undefined &&
|
|
80
|
+
(form.reviews.reviewer ?? "model") === "model" &&
|
|
81
|
+
Object.values(form.reviews.stages).some((stage) => stage.mode !== "off");
|
|
82
|
+
return [
|
|
83
|
+
...(text
|
|
84
|
+
? [
|
|
85
|
+
{
|
|
86
|
+
family: "llm",
|
|
87
|
+
provider: form.llm.provider,
|
|
88
|
+
model: form.llm.model,
|
|
89
|
+
section: "script",
|
|
90
|
+
what: "writing service",
|
|
91
|
+
},
|
|
92
|
+
]
|
|
93
|
+
: []),
|
|
94
|
+
...(generates(form.sources.audio)
|
|
95
|
+
? [
|
|
96
|
+
{
|
|
97
|
+
family: "tts",
|
|
98
|
+
provider: form.audio.provider,
|
|
99
|
+
model: form.audio.model,
|
|
100
|
+
section: "voice",
|
|
101
|
+
what: "voice service",
|
|
102
|
+
},
|
|
103
|
+
]
|
|
104
|
+
: []),
|
|
105
|
+
...(generates(form.sources.images) || generates(form.sources.thumbnail)
|
|
106
|
+
? [
|
|
107
|
+
{
|
|
108
|
+
family: "image",
|
|
109
|
+
provider: form.images.provider,
|
|
110
|
+
model: form.images.model,
|
|
111
|
+
section: "pictures",
|
|
112
|
+
what: "image service",
|
|
113
|
+
},
|
|
114
|
+
]
|
|
115
|
+
: []),
|
|
116
|
+
...(reviews && form.reviews !== undefined
|
|
117
|
+
? [
|
|
118
|
+
{
|
|
119
|
+
family: "llm",
|
|
120
|
+
provider: form.reviews.provider,
|
|
121
|
+
model: form.reviews.model,
|
|
122
|
+
section: "reviews",
|
|
123
|
+
what: "service for the AI checks",
|
|
124
|
+
},
|
|
125
|
+
]
|
|
126
|
+
: []),
|
|
127
|
+
];
|
|
128
|
+
}
|
|
129
|
+
function providersChecks(input) {
|
|
130
|
+
const used = usedProviders(withProviderDefaults(input.document, input.defaults ?? {}));
|
|
131
|
+
const unchosen = used.filter((one, index) => one.provider === "" && used.findIndex((other) => other.what === one.what) === index);
|
|
132
|
+
// A service picked without its model is refused by every run, as the sample says.
|
|
133
|
+
const modelless = used.filter((one, index) => one.provider !== "" &&
|
|
134
|
+
one.model.trim() === "" &&
|
|
135
|
+
used.findIndex((other) => other.what === one.what) === index);
|
|
136
|
+
const missing = used.filter((one, index) => one.provider !== "" &&
|
|
137
|
+
input.providers.get(one.provider)?.ready !== true &&
|
|
138
|
+
used.findIndex((other) => other.provider === one.provider) === index);
|
|
139
|
+
const lines = [
|
|
140
|
+
...unchosen.map((one) => ({
|
|
141
|
+
id: "providers",
|
|
142
|
+
ok: false,
|
|
143
|
+
sentence: `No ${one.what} is chosen, so a run can't start.`,
|
|
144
|
+
fix: {
|
|
145
|
+
label: `Choose one in ${sectionLabel[one.section]}`,
|
|
146
|
+
href: studioHref(input.templateId, one.section),
|
|
147
|
+
},
|
|
148
|
+
})),
|
|
149
|
+
...modelless.map((one) => {
|
|
150
|
+
const name = input.providers.get(one.provider)?.name ?? one.provider;
|
|
151
|
+
return {
|
|
152
|
+
id: "providers",
|
|
153
|
+
ok: false,
|
|
154
|
+
sentence: `No model is chosen for ${name}, the ${one.what}, so a run can't start.`,
|
|
155
|
+
fix: {
|
|
156
|
+
label: `Choose one in ${sectionLabel[one.section]}`,
|
|
157
|
+
href: studioHref(input.templateId, one.section),
|
|
158
|
+
},
|
|
159
|
+
};
|
|
160
|
+
}),
|
|
161
|
+
...missing.map((one) => {
|
|
162
|
+
const name = input.providers.get(one.provider)?.name ?? one.provider;
|
|
163
|
+
return {
|
|
164
|
+
id: "providers",
|
|
165
|
+
ok: false,
|
|
166
|
+
sentence: `${name}, the ${one.what}, isn't set up on this computer: no key is stored or its program wasn't found.`,
|
|
167
|
+
fix: {
|
|
168
|
+
label: "Set it up in Settings → Keys & services",
|
|
169
|
+
href: "/settings?section=providers",
|
|
170
|
+
},
|
|
171
|
+
};
|
|
172
|
+
}),
|
|
173
|
+
];
|
|
174
|
+
return lines.length > 0
|
|
175
|
+
? lines
|
|
176
|
+
: [{ id: "providers", ok: true, sentence: "Every service this template uses is set up." }];
|
|
177
|
+
}
|
|
178
|
+
// The narration's voice (and each speaker's) is chosen and is one of the voices this computer
|
|
179
|
+
// keeps in Settings → Voices: an imported pack's voice may be someone else's.
|
|
180
|
+
function voiceCheck(input) {
|
|
181
|
+
const { form } = input.document;
|
|
182
|
+
const voiced = form.sources.audio === "generate";
|
|
183
|
+
const fix = {
|
|
184
|
+
label: `Choose a voice in ${sectionLabel.voice}`,
|
|
185
|
+
href: studioHref(input.templateId, "voice"),
|
|
186
|
+
};
|
|
187
|
+
if (!voiced)
|
|
188
|
+
return { id: "voice", ok: true, sentence: "The narration isn't voiced by Slopify." };
|
|
189
|
+
const picks = [
|
|
190
|
+
{ who: "The narration's", provider: form.audio.provider, voice: form.audio.voice },
|
|
191
|
+
...(form.voices?.speakers ?? []).map((speaker) => ({
|
|
192
|
+
who: `${speaker.name.trim() === "" ? "A speaker" : speaker.name}'s`,
|
|
193
|
+
provider: speaker.voice.provider,
|
|
194
|
+
voice: speaker.voice.voice,
|
|
195
|
+
})),
|
|
196
|
+
];
|
|
197
|
+
if (form.audio.voice.trim() === "" && form.voices === undefined)
|
|
198
|
+
return {
|
|
199
|
+
id: "voice",
|
|
200
|
+
ok: false,
|
|
201
|
+
sentence: "No voice is chosen for the narration, so a run can't start.",
|
|
202
|
+
fix,
|
|
203
|
+
};
|
|
204
|
+
const known = input.voices;
|
|
205
|
+
const unknown = known === undefined
|
|
206
|
+
? undefined
|
|
207
|
+
: picks.find((pick) => pick.voice.trim() !== "" &&
|
|
208
|
+
!known.some((one) => one.provider === pick.provider && one.voiceId === pick.voice));
|
|
209
|
+
if (unknown !== undefined)
|
|
210
|
+
return {
|
|
211
|
+
id: "voice",
|
|
212
|
+
ok: false,
|
|
213
|
+
sentence: `${unknown.who} voice (ID ${unknown.voice}) isn't one of your voices in Settings → Voices. Add it there under that ID, or choose one of yours.`,
|
|
214
|
+
fix,
|
|
215
|
+
};
|
|
216
|
+
return { id: "voice", ok: true, sentence: "The narration's voice is one of your voices." };
|
|
217
|
+
}
|
|
218
|
+
function releaseSlotsCheck(input) {
|
|
219
|
+
const shorts = input.document.form.shorts;
|
|
220
|
+
const wanted = shorts?.enabled === true ? Math.max(0, Number.parseInt(shorts.count, 10) || 0) : 0;
|
|
221
|
+
for (const schedule of input.schedules) {
|
|
222
|
+
if (schedule.releases.length === 0)
|
|
223
|
+
continue;
|
|
224
|
+
const missing = schedule.runDays.filter((day) => !schedule.releases.some((release) => release.day === day));
|
|
225
|
+
if (missing.length > 0)
|
|
226
|
+
return {
|
|
227
|
+
id: "release-slots",
|
|
228
|
+
ok: false,
|
|
229
|
+
sentence: `${nameOf(schedule)} runs on ${list(missing.map((day) => weekdays[day] ?? String(day)))} but has no release time for ${missing.length === 1 ? "that day" : "those days"}.`,
|
|
230
|
+
fix: {
|
|
231
|
+
label: `Add the release times in ${schedule.name}`,
|
|
232
|
+
href: scheduleHref(schedule.id),
|
|
233
|
+
},
|
|
234
|
+
};
|
|
235
|
+
const short = schedule.releases.find((release) => release.shorts < wanted);
|
|
236
|
+
if (short !== undefined)
|
|
237
|
+
return {
|
|
238
|
+
id: "release-slots",
|
|
239
|
+
ok: false,
|
|
240
|
+
sentence: `This template makes ${String(wanted)} shorts a video, but ${nameOf(schedule)} gives ${weekdays[short.day] ?? ""}'s run release times for ${String(short.shorts)}.`,
|
|
241
|
+
fix: {
|
|
242
|
+
label: `Add short release times in ${schedule.name}`,
|
|
243
|
+
href: scheduleHref(schedule.id),
|
|
244
|
+
},
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
return {
|
|
248
|
+
id: "release-slots",
|
|
249
|
+
ok: true,
|
|
250
|
+
sentence: input.schedules.length === 0
|
|
251
|
+
? "No schedule runs this template yet."
|
|
252
|
+
: "Every run has a release time for the video and its shorts.",
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
// A run that can't be priced at all fails: it can't start either, and the sentence says why.
|
|
256
|
+
// Steps with no price (how many tables a written article describes is known only once it is
|
|
257
|
+
// written) never fail it, since nothing fixes them: they are named as not counted, here and in
|
|
258
|
+
// Schedule, so the dollar figure reads as the least it costs.
|
|
259
|
+
function monthlyCostCheck(input) {
|
|
260
|
+
const cost = input.monthlyCost;
|
|
261
|
+
if (cost === null)
|
|
262
|
+
return {
|
|
263
|
+
id: "monthly-cost",
|
|
264
|
+
ok: true,
|
|
265
|
+
sentence: "No schedule runs this template, so it costs nothing a month.",
|
|
266
|
+
};
|
|
267
|
+
if (cost.problem !== undefined && cost.problem !== null)
|
|
268
|
+
return {
|
|
269
|
+
id: "monthly-cost",
|
|
270
|
+
ok: false,
|
|
271
|
+
sentence: cost.problem,
|
|
272
|
+
fix: { label: "See its runs in Schedule", href: studioHref(input.templateId, "schedule") },
|
|
273
|
+
};
|
|
274
|
+
const paused = cost.paused?.schedules ?? 0;
|
|
275
|
+
const resumed = `up to about $${(cost.paused?.high ?? 0).toFixed(2)} a month when resumed`;
|
|
276
|
+
const many = (n) => `${String(n)} paused ${n === 1 ? "schedule" : "schedules"}`;
|
|
277
|
+
const activeCost = `Its schedules cost ${cost.unknown === 0 ? "up to about" : "at least"} $${cost.high.toFixed(2)} a month`;
|
|
278
|
+
const sentence = paused === 0
|
|
279
|
+
? `${activeCost}.`
|
|
280
|
+
: cost.high === 0 && (cost.runs ?? 0) === 0
|
|
281
|
+
? `${many(paused)} ${paused === 1 ? "uses" : "use"} this template: ${paused === 1 ? "it costs" : "they cost"} nothing while paused, and ${resumed}.`
|
|
282
|
+
: `${activeCost}; ${many(paused)} would add ${resumed}.`;
|
|
283
|
+
return {
|
|
284
|
+
id: "monthly-cost",
|
|
285
|
+
ok: true,
|
|
286
|
+
sentence: cost.unknown === 0 ? sentence : `${sentence} ${unpricedSentence(cost)}`,
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
// "Not counted, with no known price: Narration descriptions and Delivery cue overhead."
|
|
290
|
+
function unpricedSentence(cost) {
|
|
291
|
+
const names = cost.unpriced ?? [];
|
|
292
|
+
return names.length === 0
|
|
293
|
+
? `${String(cost.unknown)} ${cost.unknown === 1 ? "step has" : "steps have"} no known price and ${cost.unknown === 1 ? "isn't" : "aren't"} counted.`
|
|
294
|
+
: `Not counted, with no known price: ${list(names)}.`;
|
|
295
|
+
}
|
|
296
|
+
function answerersCheck(input) {
|
|
297
|
+
const { form } = input.document;
|
|
298
|
+
const asks = (form.checkpoints?.length ?? 0) > 0 ||
|
|
299
|
+
(form.reviews?.reviewer === "agent" &&
|
|
300
|
+
Object.values(form.reviews.stages).some((stage) => stage.mode !== "off"));
|
|
301
|
+
if (!asks)
|
|
302
|
+
return { id: "answerers", ok: true, sentence: "Nothing in a run waits for an answer." };
|
|
303
|
+
const agent = input.agentSeenAt !== null &&
|
|
304
|
+
input.now.getTime() - new Date(input.agentSeenAt).getTime() <= agentWindowMs;
|
|
305
|
+
if (input.notificationUrl || agent)
|
|
306
|
+
return {
|
|
307
|
+
id: "answerers",
|
|
308
|
+
ok: true,
|
|
309
|
+
sentence: agent
|
|
310
|
+
? "An agent connected this week answers when a run pauses."
|
|
311
|
+
: "You're notified when a run pauses for you.",
|
|
312
|
+
};
|
|
313
|
+
return {
|
|
314
|
+
id: "answerers",
|
|
315
|
+
ok: false,
|
|
316
|
+
sentence: "A run pauses for your approval and nobody would know: no notification address is set and no agent connected in the last 7 days.",
|
|
317
|
+
fix: {
|
|
318
|
+
label: "Set a notification address in Settings → Notifications",
|
|
319
|
+
href: "/settings?section=notifications",
|
|
320
|
+
},
|
|
321
|
+
};
|
|
322
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
2
|
+
import { mkdirSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { draftDocumentThemeOf } from "../document/model.js";
|
|
5
|
+
import { renderSampleDocument } from "../document/sample.js";
|
|
6
|
+
import { resolvedDocumentTheme } from "../document/theme.js";
|
|
7
|
+
import { stableJson } from "../style-preview/settings.js";
|
|
8
|
+
// The Document (PDF) sample: the Library theme editor's sample article laid out in the
|
|
9
|
+
// template's theme. Local and free.
|
|
10
|
+
export function documentThemeOfTemplate(document) {
|
|
11
|
+
const settings = document.form.document;
|
|
12
|
+
return resolvedDocumentTheme({
|
|
13
|
+
theme: draftDocumentThemeOf(settings),
|
|
14
|
+
...(settings?.custom === undefined ? {} : { custom: settings.custom }),
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
export function documentHash(theme) {
|
|
18
|
+
return createHash("sha256")
|
|
19
|
+
.update(stableJson({ version: 1, theme }))
|
|
20
|
+
.digest("hex");
|
|
21
|
+
}
|
|
22
|
+
const hashPattern = /^[a-f0-9]{64}$/;
|
|
23
|
+
export function createDocumentSamples(deps) {
|
|
24
|
+
const render = deps.render ?? ((theme) => renderSampleDocument(theme).bytes);
|
|
25
|
+
const pathOf = (hash) => join(deps.dir, `${hash}.pdf`);
|
|
26
|
+
const file = (hash) => {
|
|
27
|
+
if (!hashPattern.test(hash))
|
|
28
|
+
return undefined;
|
|
29
|
+
try {
|
|
30
|
+
const stats = statSync(pathOf(hash));
|
|
31
|
+
return stats.isFile() && stats.size > 0
|
|
32
|
+
? { path: pathOf(hash), bytes: stats.size }
|
|
33
|
+
: undefined;
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
return {
|
|
40
|
+
file,
|
|
41
|
+
make: (theme) => {
|
|
42
|
+
const hash = documentHash(theme);
|
|
43
|
+
if (file(hash) !== undefined)
|
|
44
|
+
return;
|
|
45
|
+
mkdirSync(deps.dir, { recursive: true, mode: 0o700 });
|
|
46
|
+
const part = join(deps.dir, `${hash}.${randomUUID()}.part`);
|
|
47
|
+
try {
|
|
48
|
+
writeFileSync(part, render(theme), { mode: 0o600 });
|
|
49
|
+
renameSync(part, pathOf(hash));
|
|
50
|
+
}
|
|
51
|
+
finally {
|
|
52
|
+
rmSync(part, { force: true });
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { configOf } from "../admission/start.js";
|
|
2
|
+
// The sample project's next revision for a template's newer setup: the config a fresh run of it
|
|
3
|
+
// would start with (`configOf`, so aliases and rules are copied as they are now) and the
|
|
4
|
+
// current content with each prompt's template body replaced, so a changed prompt is sent as
|
|
5
|
+
// written now. Saving it outdates exactly what the change touches; the rebuild makes only that.
|
|
6
|
+
export function sampleEdit(deps, base, run) {
|
|
7
|
+
const config = configOf(deps, run.draft, run.rendered, deps.clock.now(), run.templates, base.revision.projectId);
|
|
8
|
+
return {
|
|
9
|
+
config,
|
|
10
|
+
content: {
|
|
11
|
+
...base.revision.content,
|
|
12
|
+
promptTemplates: Object.fromEntries(Object.keys(config.rendered).map((key) => [key, run.templates[key] ?? null])),
|
|
13
|
+
},
|
|
14
|
+
};
|
|
15
|
+
}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { setImmediate as yieldTurn } from "node:timers/promises";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { transact } from "../../kernel/db/tx.js";
|
|
4
|
+
import { templateById, templateSummaries } from "../project-templates/repo.js";
|
|
5
|
+
import { budgetRoom, budgetWords, fitsBudget, plansSwitch } from "./budget.js";
|
|
6
|
+
import { enqueueJob } from "./jobs.js";
|
|
7
|
+
import { quoteSample } from "./quote.js";
|
|
8
|
+
import { sampleVersions, setSampleVersion } from "./repo.js";
|
|
9
|
+
import { exceedsAcknowledged } from "./save.js";
|
|
10
|
+
import { affectedSections } from "./sections.js";
|
|
11
|
+
import { paidSections } from "./status.js";
|
|
12
|
+
const money = (value) => `$${value.toFixed(2)}`;
|
|
13
|
+
// The sections a template's newest version has no sample of: every one before its first
|
|
14
|
+
// sample, the ones changed since the last one made, none when it is made or on its way.
|
|
15
|
+
function wanted(deps, templateId) {
|
|
16
|
+
const head = templateById(deps.db, templateId);
|
|
17
|
+
if (head === undefined)
|
|
18
|
+
return "none";
|
|
19
|
+
const versions = sampleVersions(deps.db, templateId);
|
|
20
|
+
const row = versions.find((one) => one.templateVersion === head.version);
|
|
21
|
+
if (row !== undefined && ["done", "queued", "making"].includes(row.state))
|
|
22
|
+
return "none";
|
|
23
|
+
const done = versions.find((one) => one.state === "done" && one.templateVersion <= head.version);
|
|
24
|
+
const from = done === undefined ? undefined : templateById(deps.db, templateId, done.templateVersion);
|
|
25
|
+
if (from === undefined)
|
|
26
|
+
return "all";
|
|
27
|
+
const paid = new Set(paidSections);
|
|
28
|
+
const changed = affectedSections(from.document, head.document).filter((one) => paid.has(one));
|
|
29
|
+
return changed.length === 0 ? "none" : changed;
|
|
30
|
+
}
|
|
31
|
+
export async function quoteSamplesForAll(deps) {
|
|
32
|
+
const room = budgetRoom(deps.db, deps.clock.now(), deps.timeZone);
|
|
33
|
+
const items = [];
|
|
34
|
+
let used = 0;
|
|
35
|
+
for (const template of templateSummaries(deps.db)) {
|
|
36
|
+
const sections = wanted(deps, template.id);
|
|
37
|
+
if (sections === "none")
|
|
38
|
+
continue;
|
|
39
|
+
// Each price resolves a draft through Play's review: the server stays answering between them.
|
|
40
|
+
await yieldTurn();
|
|
41
|
+
const quoted = await quoteSample(deps, template.id, { sections });
|
|
42
|
+
if (!quoted.ok)
|
|
43
|
+
continue;
|
|
44
|
+
const { high, unknown, problem, usesPlan } = quoted.value;
|
|
45
|
+
const fits = problem === null && fitsBudget(room, used + high, usesPlan);
|
|
46
|
+
if (fits)
|
|
47
|
+
used += high;
|
|
48
|
+
items.push({
|
|
49
|
+
templateId: template.id,
|
|
50
|
+
name: template.name,
|
|
51
|
+
version: quoted.value.version,
|
|
52
|
+
high: problem === null ? high : 0,
|
|
53
|
+
unknown: problem === null ? unknown : 0,
|
|
54
|
+
usesPlan: problem === null && usesPlan,
|
|
55
|
+
fits,
|
|
56
|
+
problem,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
const makeable = items.filter((item) => item.problem === null);
|
|
60
|
+
const total = makeable.reduce((sum, item) => sum + item.high, 0);
|
|
61
|
+
const fitting = makeable.filter((item) => item.fits).length;
|
|
62
|
+
return {
|
|
63
|
+
items,
|
|
64
|
+
total,
|
|
65
|
+
fitting,
|
|
66
|
+
budget: room,
|
|
67
|
+
sentence: sentenceOf(makeable, room),
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
function sentenceOf(makeable, room) {
|
|
71
|
+
const count = makeable.length;
|
|
72
|
+
if (count === 0)
|
|
73
|
+
return "Every template's sample is made for its newest version. Nothing to make.";
|
|
74
|
+
const total = makeable.reduce((sum, item) => sum + item.high, 0);
|
|
75
|
+
const fitting = makeable.filter((item) => item.fits).length;
|
|
76
|
+
const head = `${String(count)} ${count === 1 ? "template needs" : "templates need"} a sample: about ${money(total)} in all.`;
|
|
77
|
+
if (fitting === count)
|
|
78
|
+
return head;
|
|
79
|
+
const waiting = count - fitting;
|
|
80
|
+
const onPlan = makeable.filter((item) => !item.fits && item.usesPlan && !room.plans).length;
|
|
81
|
+
const why = onPlan === waiting
|
|
82
|
+
? `: they run on your Claude Code or Codex plan, which samples may not use (turn on ${plansSwitch} in Settings → Production defaults)`
|
|
83
|
+
: onPlan > 0
|
|
84
|
+
? `: ${String(onPlan)} run on your Claude Code or Codex plan, which samples may not use (turn on ${plansSwitch} in Settings → Production defaults), and the rest wait for tomorrow or a higher budget`
|
|
85
|
+
: " for tomorrow or a higher budget in Settings → Production defaults";
|
|
86
|
+
return `${head} ${String(fitting)} of them ${fitting === 1 ? "fits" : "fit"} today's budget; the other ${String(waiting)} wait${why}.`;
|
|
87
|
+
}
|
|
88
|
+
export const samplesForAllSchema = z
|
|
89
|
+
.object({
|
|
90
|
+
// The total the button showed.
|
|
91
|
+
acknowledgedTotal: z.number().finite().min(0).max(100_000),
|
|
92
|
+
// That some steps have no price, and the person accepts it.
|
|
93
|
+
acknowledgedUnknown: z.boolean().optional(),
|
|
94
|
+
})
|
|
95
|
+
.strict()
|
|
96
|
+
.readonly();
|
|
97
|
+
const budgetHeld = "Waiting: today's sample budget is used by the other templates' samples. Press Make sample tomorrow, or raise the budget in Settings → Production defaults.";
|
|
98
|
+
export async function makeSamplesForAll(deps, raw) {
|
|
99
|
+
const parsed = samplesForAllSchema.safeParse(raw);
|
|
100
|
+
if (!parsed.success)
|
|
101
|
+
return {
|
|
102
|
+
ok: false,
|
|
103
|
+
reason: "invalid-input",
|
|
104
|
+
message: "Settings sent a request Slopify couldn't read. Reload the page and press Make samples for all again.",
|
|
105
|
+
};
|
|
106
|
+
const quote = await quoteSamplesForAll(deps);
|
|
107
|
+
if (exceedsAcknowledged(quote.total, parsed.data.acknowledgedTotal))
|
|
108
|
+
return {
|
|
109
|
+
ok: false,
|
|
110
|
+
reason: "cost-changed",
|
|
111
|
+
message: `Making them now costs about ${money(quote.total)}, more than the ${money(parsed.data.acknowledgedTotal)} you saw. Press Make samples for all again to accept the new price.`,
|
|
112
|
+
quote,
|
|
113
|
+
};
|
|
114
|
+
const at = deps.clock.now().toISOString();
|
|
115
|
+
// Each sample's share of the total the person saw: its leeway is applied once, at make time.
|
|
116
|
+
const seenShare = quote.total > 0 ? Math.min(1, parsed.data.acknowledgedTotal / quote.total) : 1;
|
|
117
|
+
const queued = [];
|
|
118
|
+
const held = [];
|
|
119
|
+
transact(deps.db, () => {
|
|
120
|
+
for (const item of quote.items) {
|
|
121
|
+
if (item.problem !== null)
|
|
122
|
+
continue;
|
|
123
|
+
const head = templateById(deps.db, item.templateId);
|
|
124
|
+
// Saved again meanwhile: its own Save made (or skipped) that version's sample.
|
|
125
|
+
if (head === undefined || head.version !== item.version)
|
|
126
|
+
continue;
|
|
127
|
+
const unpriced = item.unknown > 0 && parsed.data.acknowledgedUnknown !== true;
|
|
128
|
+
if (!item.fits || unpriced) {
|
|
129
|
+
setSampleVersion(deps.db, item.templateId, item.version, {
|
|
130
|
+
state: "held",
|
|
131
|
+
at,
|
|
132
|
+
quotedHigh: item.high,
|
|
133
|
+
heldReason: unpriced
|
|
134
|
+
? `Waiting: ${String(item.unknown)} ${item.unknown === 1 ? "step of this sample has" : "steps of this sample have"} no known price. Press Make sample to accept that and make it.`
|
|
135
|
+
: item.usesPlan && !quote.budget.plans
|
|
136
|
+
? `Waiting: ${budgetWords(quote.budget, item, "this sample")}, then press Make sample.`
|
|
137
|
+
: budgetHeld,
|
|
138
|
+
});
|
|
139
|
+
held.push(item.templateId);
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
// Its unknown prices were accepted above, or its quote priced every step.
|
|
143
|
+
deps.acks.accept(item.templateId, item.version);
|
|
144
|
+
setSampleVersion(deps.db, item.templateId, item.version, {
|
|
145
|
+
state: "queued",
|
|
146
|
+
at,
|
|
147
|
+
quotedHigh: item.high,
|
|
148
|
+
heldReason: null,
|
|
149
|
+
});
|
|
150
|
+
enqueueJob(deps.db, {
|
|
151
|
+
templateId: item.templateId,
|
|
152
|
+
templateVersion: item.version,
|
|
153
|
+
ackHigh: item.high * seenShare,
|
|
154
|
+
kind: "save",
|
|
155
|
+
requestedAt: at,
|
|
156
|
+
});
|
|
157
|
+
queued.push(item.templateId);
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
return { ok: true, value: { queued, held, quote } };
|
|
161
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { defaultImageSeconds, defaultMotionStyle, defaultZoomPercent } from "../admission/rules.js";
|
|
2
|
+
// The Video and style sample: 30 seconds made by the style preview's renderer from the
|
|
3
|
+
// template's frame, captions, Look and picture timing, on the bundled sample's pictures and
|
|
4
|
+
// narration. Local and free; no provider is called.
|
|
5
|
+
export const videoSampleSeconds = 30;
|
|
6
|
+
function number(raw, fallback, min, max) {
|
|
7
|
+
const value = Number(raw);
|
|
8
|
+
return raw === undefined || raw.trim() === "" || !Number.isFinite(value)
|
|
9
|
+
? fallback
|
|
10
|
+
: Math.min(max, Math.max(min, value));
|
|
11
|
+
}
|
|
12
|
+
export function videoSampleRequest(document) {
|
|
13
|
+
const { form } = document;
|
|
14
|
+
return {
|
|
15
|
+
format: form.format,
|
|
16
|
+
subtitles: {
|
|
17
|
+
mode: form.subtitles.mode,
|
|
18
|
+
fontId: /^[A-Za-z0-9_-]+$/.test(form.subtitles.fontId) ? form.subtitles.fontId : "default",
|
|
19
|
+
fontSize: number(form.subtitles.fontSize, 48, 16, 120),
|
|
20
|
+
position: form.subtitles.position,
|
|
21
|
+
},
|
|
22
|
+
...(form.videoEdit === undefined ? {} : { videoEdit: form.videoEdit }),
|
|
23
|
+
previewText: document.previewText.slice(0, 200),
|
|
24
|
+
seconds: videoSampleSeconds,
|
|
25
|
+
timing: {
|
|
26
|
+
imageSeconds: number(form.imageSeconds, defaultImageSeconds, 1, 120),
|
|
27
|
+
zoomPercent: number(form.zoomPercent, defaultZoomPercent, 0, 100),
|
|
28
|
+
motionStyle: form.motionStyle ?? defaultMotionStyle,
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
}
|