@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,218 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { transact } from "../../kernel/db/tx.js";
|
|
3
|
+
import { defaultChannelId } from "../channels/model.js";
|
|
4
|
+
import { designDocumentSchema } from "./schema.js";
|
|
5
|
+
import { mutationHash, reusedMessage } from "./service.js";
|
|
6
|
+
import { documentChecks } from "./template-checks.js";
|
|
7
|
+
// Design templates: a designed piece saved with fields to make again by hand or from a
|
|
8
|
+
// schedule. Every Save is a new version; a version is marked ready only when its checks pass,
|
|
9
|
+
// and only a ready version is what a schedule makes (`runnableDesignVersion`).
|
|
10
|
+
const id = z
|
|
11
|
+
.string()
|
|
12
|
+
.min(1)
|
|
13
|
+
.max(64)
|
|
14
|
+
.regex(/^[A-Za-z0-9_-]+$/);
|
|
15
|
+
const name = z.string().trim().min(1).max(200);
|
|
16
|
+
export const createTemplateSchema = z
|
|
17
|
+
.object({
|
|
18
|
+
id,
|
|
19
|
+
mutationId: z.string().min(8).max(128),
|
|
20
|
+
name,
|
|
21
|
+
document: designDocumentSchema,
|
|
22
|
+
channelId: id.optional(),
|
|
23
|
+
})
|
|
24
|
+
.strict();
|
|
25
|
+
export const saveTemplateSchema = z
|
|
26
|
+
.object({
|
|
27
|
+
baseVersion: z.number().int().min(1),
|
|
28
|
+
name,
|
|
29
|
+
document: designDocumentSchema,
|
|
30
|
+
// Whether this Save redraws the editor's sample (`sample.ts`); "skip" saves only.
|
|
31
|
+
sample: z.enum(["make", "skip"]).optional(),
|
|
32
|
+
acknowledgedHigh: z.number().min(0).max(1000).optional(),
|
|
33
|
+
})
|
|
34
|
+
.strict();
|
|
35
|
+
export const markReadySchema = z.object({ version: z.number().int().min(1) }).strict();
|
|
36
|
+
const revisionRow = z.object({
|
|
37
|
+
version: z.number(),
|
|
38
|
+
name: z.string(),
|
|
39
|
+
document_json: z.string(),
|
|
40
|
+
gate: z.enum(["unchecked", "ready"]),
|
|
41
|
+
checks_json: z.string().nullable(),
|
|
42
|
+
marked_at: z.string().nullable(),
|
|
43
|
+
created_at: z.string(),
|
|
44
|
+
});
|
|
45
|
+
const checksSchema = z
|
|
46
|
+
.array(z.object({
|
|
47
|
+
id: z.string(),
|
|
48
|
+
ok: z.boolean(),
|
|
49
|
+
sentence: z.string(),
|
|
50
|
+
fix: z.object({ label: z.string(), href: z.string() }).nullable(),
|
|
51
|
+
}))
|
|
52
|
+
.catch([]);
|
|
53
|
+
export function templateRevision(db, templateId, version) {
|
|
54
|
+
const raw = db
|
|
55
|
+
.prepare("SELECT * FROM design_template_revisions WHERE template_id=? AND version=?")
|
|
56
|
+
.get(templateId, version);
|
|
57
|
+
if (raw === undefined)
|
|
58
|
+
return undefined;
|
|
59
|
+
const row = revisionRow.parse(raw);
|
|
60
|
+
return {
|
|
61
|
+
version: row.version,
|
|
62
|
+
name: row.name,
|
|
63
|
+
gate: row.gate,
|
|
64
|
+
markedAt: row.marked_at,
|
|
65
|
+
createdAt: row.created_at,
|
|
66
|
+
document: designDocumentSchema.parse(JSON.parse(row.document_json)),
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
export function getTemplate(db, templateId) {
|
|
70
|
+
const head = db
|
|
71
|
+
.prepare("SELECT id, channel_id, head_version, created_at FROM design_templates WHERE id=? AND deleted_at IS NULL")
|
|
72
|
+
.get(templateId);
|
|
73
|
+
if (head === undefined)
|
|
74
|
+
return undefined;
|
|
75
|
+
const revisions = db
|
|
76
|
+
.prepare("SELECT * FROM design_template_revisions WHERE template_id=? ORDER BY version")
|
|
77
|
+
.all(templateId)
|
|
78
|
+
.map((raw) => revisionRow.parse(raw));
|
|
79
|
+
const current = revisions.find((row) => row.version === head.head_version);
|
|
80
|
+
if (current === undefined)
|
|
81
|
+
return undefined;
|
|
82
|
+
const ready = revisions.filter((row) => row.gate === "ready").at(-1);
|
|
83
|
+
return {
|
|
84
|
+
id: String(head.id),
|
|
85
|
+
channelId: head.channel_id === null ? defaultChannelId : String(head.channel_id),
|
|
86
|
+
headVersion: current.version,
|
|
87
|
+
name: current.name,
|
|
88
|
+
document: designDocumentSchema.parse(JSON.parse(current.document_json)),
|
|
89
|
+
gate: current.gate,
|
|
90
|
+
checks: current.checks_json === null ? [] : checksSchema.parse(JSON.parse(current.checks_json)),
|
|
91
|
+
readyVersion: ready?.version ?? null,
|
|
92
|
+
versions: revisions.map((row) => ({
|
|
93
|
+
version: row.version,
|
|
94
|
+
name: row.name,
|
|
95
|
+
gate: row.gate,
|
|
96
|
+
markedAt: row.marked_at,
|
|
97
|
+
createdAt: row.created_at,
|
|
98
|
+
})),
|
|
99
|
+
createdAt: String(head.created_at),
|
|
100
|
+
updatedAt: current.created_at,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
export function listTemplates(db) {
|
|
104
|
+
return db
|
|
105
|
+
.prepare("SELECT id FROM design_templates WHERE deleted_at IS NULL ORDER BY created_at DESC, id")
|
|
106
|
+
.all()
|
|
107
|
+
.flatMap((row) => getTemplate(db, String(row.id)) ?? []);
|
|
108
|
+
}
|
|
109
|
+
const notFound = {
|
|
110
|
+
ok: false,
|
|
111
|
+
reason: "not-found",
|
|
112
|
+
message: "This design template no longer exists. Open Templates → Poster templates to choose another.",
|
|
113
|
+
};
|
|
114
|
+
function invalid(error) {
|
|
115
|
+
return {
|
|
116
|
+
ok: false,
|
|
117
|
+
reason: "invalid",
|
|
118
|
+
message: `The template can't be saved: ${error.issues[0]?.message ?? "a field is missing"}.`,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
export function createTemplate(deps, raw) {
|
|
122
|
+
const parsed = createTemplateSchema.safeParse(raw);
|
|
123
|
+
if (!parsed.success)
|
|
124
|
+
return invalid(parsed.error);
|
|
125
|
+
const { mutationId, ...input } = parsed.data;
|
|
126
|
+
const hash = mutationHash(input);
|
|
127
|
+
const replay = deps.db
|
|
128
|
+
.prepare("SELECT id, mutation_hash FROM design_templates WHERE mutation_id=?")
|
|
129
|
+
.get(mutationId);
|
|
130
|
+
if (replay !== undefined) {
|
|
131
|
+
if (replay.mutation_hash !== hash)
|
|
132
|
+
return { ok: false, reason: "mutation-reused", message: reusedMessage };
|
|
133
|
+
const template = getTemplate(deps.db, String(replay.id));
|
|
134
|
+
return template === undefined ? notFound : { ok: true, value: template };
|
|
135
|
+
}
|
|
136
|
+
if (deps.db.prepare("SELECT 1 FROM design_templates WHERE id=?").get(input.id) !== undefined)
|
|
137
|
+
return { ok: false, reason: "mutation-reused", message: reusedMessage };
|
|
138
|
+
const at = deps.clock.now().toISOString();
|
|
139
|
+
transact(deps.db, () => {
|
|
140
|
+
deps.db
|
|
141
|
+
.prepare("INSERT INTO design_templates (id,channel_id,head_version,created_at,mutation_id,mutation_hash) VALUES (?,?,1,?,?,?)")
|
|
142
|
+
.run(input.id, input.channelId ?? null, at, mutationId, hash);
|
|
143
|
+
deps.db
|
|
144
|
+
.prepare("INSERT INTO design_template_revisions (template_id,version,name,document_json,created_at) VALUES (?,1,?,?,?)")
|
|
145
|
+
.run(input.id, input.name, JSON.stringify(input.document), at);
|
|
146
|
+
});
|
|
147
|
+
const template = getTemplate(deps.db, input.id);
|
|
148
|
+
return template === undefined ? notFound : { ok: true, value: template };
|
|
149
|
+
}
|
|
150
|
+
// A Save on the version it was made on becomes the next version; one made on an older version
|
|
151
|
+
// is refused with the current template. Saving exactly what the head already holds is a no-op.
|
|
152
|
+
export function saveTemplate(deps, templateId, raw) {
|
|
153
|
+
const parsed = saveTemplateSchema.safeParse(raw);
|
|
154
|
+
if (!parsed.success)
|
|
155
|
+
return invalid(parsed.error);
|
|
156
|
+
const current = getTemplate(deps.db, templateId);
|
|
157
|
+
if (current === undefined)
|
|
158
|
+
return notFound;
|
|
159
|
+
const input = parsed.data;
|
|
160
|
+
const same = input.name === current.name &&
|
|
161
|
+
JSON.stringify(input.document) === JSON.stringify(current.document);
|
|
162
|
+
if (same)
|
|
163
|
+
return { ok: true, value: { template: current, saved: false, before: current.document } };
|
|
164
|
+
if (input.baseVersion !== current.headVersion)
|
|
165
|
+
return {
|
|
166
|
+
ok: false,
|
|
167
|
+
reason: "changed",
|
|
168
|
+
message: "This template was saved in another tab or by an agent. Reload it to see that version, then make your change again.",
|
|
169
|
+
current,
|
|
170
|
+
};
|
|
171
|
+
const version = current.headVersion + 1;
|
|
172
|
+
transact(deps.db, () => {
|
|
173
|
+
deps.db
|
|
174
|
+
.prepare("INSERT INTO design_template_revisions (template_id,version,name,document_json,created_at) VALUES (?,?,?,?,?)")
|
|
175
|
+
.run(templateId, version, input.name, JSON.stringify(input.document), deps.clock.now().toISOString());
|
|
176
|
+
deps.db
|
|
177
|
+
.prepare("UPDATE design_templates SET head_version=? WHERE id=?")
|
|
178
|
+
.run(version, templateId);
|
|
179
|
+
});
|
|
180
|
+
const template = getTemplate(deps.db, templateId);
|
|
181
|
+
return template === undefined
|
|
182
|
+
? notFound
|
|
183
|
+
: { ok: true, value: { template, saved: true, before: current.document } };
|
|
184
|
+
}
|
|
185
|
+
// Mark ready: the version's checks are run and kept; it is marked only when every one passes,
|
|
186
|
+
// and otherwise refused with the list.
|
|
187
|
+
export async function markTemplateReady(deps, templateId, raw, more = async () => []) {
|
|
188
|
+
const parsed = markReadySchema.safeParse(raw);
|
|
189
|
+
if (!parsed.success)
|
|
190
|
+
return { ok: false, reason: "invalid", message: "Say which version to approve for schedules." };
|
|
191
|
+
if (getTemplate(deps.db, templateId) === undefined)
|
|
192
|
+
return notFound;
|
|
193
|
+
const revision = templateRevision(deps.db, templateId, parsed.data.version);
|
|
194
|
+
if (revision === undefined)
|
|
195
|
+
return {
|
|
196
|
+
ok: false,
|
|
197
|
+
reason: "not-found",
|
|
198
|
+
message: "That version of the template doesn't exist. Reload the template.",
|
|
199
|
+
};
|
|
200
|
+
const checks = [
|
|
201
|
+
...documentChecks(revision.document, templateId),
|
|
202
|
+
...(await more(revision.document, parsed.data.version)),
|
|
203
|
+
];
|
|
204
|
+
const passed = checks.every((check) => check.ok);
|
|
205
|
+
deps.db
|
|
206
|
+
.prepare("UPDATE design_template_revisions SET checks_json=?, gate=?, marked_at=? WHERE template_id=? AND version=?")
|
|
207
|
+
.run(JSON.stringify(checks), passed ? "ready" : revision.gate, passed ? deps.clock.now().toISOString() : revision.markedAt, templateId, parsed.data.version);
|
|
208
|
+
const failed = checks.filter((check) => !check.ok);
|
|
209
|
+
if (failed.length > 0)
|
|
210
|
+
return {
|
|
211
|
+
ok: false,
|
|
212
|
+
reason: "not-ready",
|
|
213
|
+
message: `Version ${String(parsed.data.version)} can't be approved for schedules yet: ${failed.map((check) => check.sentence).join(" ")}`,
|
|
214
|
+
current: failed,
|
|
215
|
+
};
|
|
216
|
+
const template = getTemplate(deps.db, templateId);
|
|
217
|
+
return template === undefined ? notFound : { ok: true, value: template };
|
|
218
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { readFileSync } from "node:fs";
|
|
2
|
+
import { errorText } from "../../kernel/errors.js";
|
|
2
3
|
// The bundled Cinzel weights and Literata styles (SIL OFL 1.1, assets/document/fonts) and the
|
|
3
4
|
// page texture. Read on every render rather than kept in memory: eight fonts and one image
|
|
4
5
|
// are about a megabyte and a half, and a document is made once per article.
|
|
@@ -32,7 +33,7 @@ export function readDocumentAssets() {
|
|
|
32
33
|
};
|
|
33
34
|
}
|
|
34
35
|
catch (error) {
|
|
35
|
-
throw new Error(`Slopify couldn't read the fonts and page texture it makes documents with (${
|
|
36
|
+
throw new Error(`Slopify couldn't read the fonts and page texture it makes documents with (${errorText(error)}). Its installation is incomplete: reinstall or update Slopify, then use Try again on PDF.`, { cause: error });
|
|
36
37
|
}
|
|
37
38
|
}
|
|
38
39
|
export function registerFonts(doc, fonts) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
// The
|
|
2
|
-
//
|
|
3
|
-
|
|
1
|
+
// The ready looks a project's PDF can be given, so a PDF looks right without a theme of one's
|
|
2
|
+
// own: Plain, Book (book type on parchment) and Modern (a sans-serif on white). Browser-safe:
|
|
3
|
+
// Create, Edit template, Edit settings and the server all offer the same names from here.
|
|
4
|
+
export const documentThemes = ["plain", "book", "modern"];
|
|
4
5
|
// DiceMaster was built in before 2.3.0 and is one brand's look, not Slopify's. A project
|
|
5
6
|
// saved with it keeps it (see legacy-dicemaster.ts), so the name is still read everywhere a
|
|
6
7
|
// config is parsed, but it is never offered.
|
|
@@ -11,6 +12,8 @@ export const documentThemeNames = [...documentThemes, legacyDocumentTheme];
|
|
|
11
12
|
export const defaultDocumentTheme = "plain";
|
|
12
13
|
export const documentThemeLabels = {
|
|
13
14
|
plain: "Plain",
|
|
15
|
+
book: "Book",
|
|
16
|
+
modern: "Modern",
|
|
14
17
|
dicemaster: "DiceMaster",
|
|
15
18
|
};
|
|
16
19
|
// The built-in a saved project config is drawn with. A project saved before the Document stage
|
|
@@ -34,7 +37,7 @@ export const documentThemeNameMax = 80;
|
|
|
34
37
|
export function documentThemeNameProblems(name) {
|
|
35
38
|
const trimmed = name.trim();
|
|
36
39
|
if (trimmed === "")
|
|
37
|
-
return [{ field: "name", message: "Give the
|
|
40
|
+
return [{ field: "name", message: "Give the look a name." }];
|
|
38
41
|
if (trimmed.length > documentThemeNameMax)
|
|
39
42
|
return [
|
|
40
43
|
{
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsPDF } from "jspdf";
|
|
2
|
+
import { editSettings } from "../../kernel/ports/settings-places.js";
|
|
2
3
|
import { runsText } from "./blocks.js";
|
|
3
4
|
import { drawLine, wrapRuns } from "./flow.js";
|
|
4
5
|
import { faceWidth, registerFonts, useFace } from "./fonts.js";
|
|
@@ -10,7 +11,7 @@ export function renderDocument(input) {
|
|
|
10
11
|
const text = documentText(input.articleMarkdown, input.researchNotes);
|
|
11
12
|
const blocks = withoutTitle(text.blocks, input.title);
|
|
12
13
|
if (blocks.length === 0)
|
|
13
|
-
throw new Error(
|
|
14
|
+
throw new Error(`The article has no text to put in the PDF. Write it in ${editSettings.article}, or press Write the article again in the project's Article section, then use Try again on PDF.`);
|
|
14
15
|
const words = blocks
|
|
15
16
|
.map((block) => block.kind === "heading" ? block.text : "runs" in block ? runsText(block.runs) : "")
|
|
16
17
|
.join(" ")
|
|
@@ -8,7 +8,7 @@ const mm = (min, max) => {
|
|
|
8
8
|
const range = { error: `Use a value from ${String(min)} to ${String(max)}.` };
|
|
9
9
|
return z.number({ error: "Enter a number." }).finite(range).min(min, range).max(max, range);
|
|
10
10
|
};
|
|
11
|
-
const color = z.string().regex(/^#?([0-9a-f]{3}|[0-9a-f]{6})$/i, "Use a
|
|
11
|
+
const color = z.string().regex(/^#?([0-9a-f]{3}|[0-9a-f]{6})$/i, "Use a color like #8c1e14.");
|
|
12
12
|
const line = z.string().max(300, { error: "Keep this under 300 characters." });
|
|
13
13
|
const nullableLine = line.nullable();
|
|
14
14
|
const url = z.string().max(500, { error: "Keep this under 500 characters." }).nullable();
|
|
@@ -9,8 +9,11 @@ const cinzel = (style, letterSpacing) => ({
|
|
|
9
9
|
style,
|
|
10
10
|
letterSpacing,
|
|
11
11
|
});
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
const literata = (style) => ({ family: "Literata", style, letterSpacing: 0 });
|
|
13
|
+
const sans = (style) => ({ family: "helvetica", style, letterSpacing: 0 });
|
|
14
|
+
// The first built-in, and the default: an unbranded flat page. Its layout is the one Slopify
|
|
15
|
+
// has always drawn, written out in full rather than as changes to another theme. The other
|
|
16
|
+
// built-ins are changes to it.
|
|
14
17
|
const plain = {
|
|
15
18
|
page: { format: "a4", margin: 22, contentTop: 32 },
|
|
16
19
|
background: { image: null, color: "#fdfaf3" },
|
|
@@ -91,10 +94,53 @@ const plain = {
|
|
|
91
94
|
closing: null,
|
|
92
95
|
},
|
|
93
96
|
};
|
|
97
|
+
// Book: the article set like a novel, in Literata on the parchment texture, with Plain's Cinzel
|
|
98
|
+
// headings and drop caps in a warm brown.
|
|
99
|
+
const book = {
|
|
100
|
+
background: { image: "parchment", color: "#f5ebd7" },
|
|
101
|
+
colors: { heading: "#5a3214", text: "#231a12", muted: "#5e5246", faint: "#857767" },
|
|
102
|
+
fonts: {
|
|
103
|
+
body: literata("normal"),
|
|
104
|
+
strong: literata("bold"),
|
|
105
|
+
emphasis: literata("italic"),
|
|
106
|
+
footer: literata("italic"),
|
|
107
|
+
},
|
|
108
|
+
sizes: { body: 11 },
|
|
109
|
+
spacing: { bodyLine: 6.5, paragraphGap: 0.6 },
|
|
110
|
+
// A paragraph of a line or two starts plainly: a three-line initial beside it looks lost.
|
|
111
|
+
dropCap: { minLength: 120 },
|
|
112
|
+
};
|
|
113
|
+
// Modern: a sans-serif on a white page, blue headings and no drop caps, like a report.
|
|
114
|
+
const modern = {
|
|
115
|
+
background: { image: null, color: "#ffffff" },
|
|
116
|
+
colors: { heading: "#1d4e89", text: "#1c1c1c", muted: "#5a5a5a", faint: "#8a8a8a" },
|
|
117
|
+
fonts: {
|
|
118
|
+
body: sans("normal"),
|
|
119
|
+
strong: sans("bold"),
|
|
120
|
+
emphasis: sans("italic"),
|
|
121
|
+
heading: sans("bold"),
|
|
122
|
+
dramatic: sans("bold"),
|
|
123
|
+
decorative: sans("normal"),
|
|
124
|
+
dropCap: sans("bold"),
|
|
125
|
+
footer: sans("normal"),
|
|
126
|
+
},
|
|
127
|
+
sizes: { brand: 28, title: 24, section: 18, heading: 15, subheading: 12, body: 10.5 },
|
|
128
|
+
spacing: { bodyLine: 6, headingLine: 9, subheadingLine: 7, paragraphGap: 0.7 },
|
|
129
|
+
dropCap: { enabled: false },
|
|
130
|
+
};
|
|
94
131
|
// A built-in by name. "dicemaster" is still read, from projects saved while it was built in,
|
|
95
132
|
// and gives exactly the values it gave then.
|
|
96
133
|
export function builtInTheme(name) {
|
|
97
|
-
|
|
134
|
+
switch (name) {
|
|
135
|
+
case "book":
|
|
136
|
+
return resolveTheme(book, plain);
|
|
137
|
+
case "modern":
|
|
138
|
+
return resolveTheme(modern, plain);
|
|
139
|
+
case legacyDocumentTheme:
|
|
140
|
+
return resolveTheme({}, legacyDiceMasterTheme);
|
|
141
|
+
default:
|
|
142
|
+
return resolveTheme({}, plain);
|
|
143
|
+
}
|
|
98
144
|
}
|
|
99
145
|
// The theme a project's document is drawn with: its copy of a Library theme, or a built-in.
|
|
100
146
|
export function resolvedDocumentTheme(settings) {
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import { existsSync, readFileSync } from "node:fs";
|
|
3
|
+
import { errorText } from "../../kernel/errors.js";
|
|
3
4
|
import { projectById } from "../admission/repo.js";
|
|
4
5
|
import { castMentions } from "../channels/cast-match.js";
|
|
5
6
|
import { castOfChannel, projectChannelId } from "../channels/repo.js";
|
|
6
7
|
import { reviewedByAgent } from "../reviews/model.js";
|
|
7
8
|
import { outputPath } from "../storage/layout.js";
|
|
8
9
|
import { outputsOf } from "../storage/repo.js";
|
|
10
|
+
import { isTemplateSample } from "../template-studio/repo.js";
|
|
9
11
|
import { episodeMemoryOn, memoryOfProject, saveGeneratedMemory } from "./repo.js";
|
|
10
12
|
// When a project finishes, a small LLM call writes what the episode covered (at most
|
|
11
13
|
// `summaryWordsMax` words) for its channel's episode memory. It never fails the project: every
|
|
@@ -51,7 +53,7 @@ export async function summarizeEpisode(deps, projectId, signal) {
|
|
|
51
53
|
return "failed";
|
|
52
54
|
deps.log.write("warn", "episode.memory", {
|
|
53
55
|
projectId,
|
|
54
|
-
detail: `The episode summary wasn't saved: ${
|
|
56
|
+
detail: `The episode summary wasn't saved: ${errorText(error)}. The project is unaffected; only later episodes won't be reminded of this one. Check the service it writes with in Settings → Keys & services.`,
|
|
55
57
|
});
|
|
56
58
|
return "failed";
|
|
57
59
|
}
|
|
@@ -60,6 +62,8 @@ async function summarize(deps, projectId, signal) {
|
|
|
60
62
|
const project = projectById(deps.db, projectId);
|
|
61
63
|
if (project === undefined)
|
|
62
64
|
return "gone";
|
|
65
|
+
if (isTemplateSample(deps.db, projectId))
|
|
66
|
+
return "sample";
|
|
63
67
|
const channelId = projectChannelId(deps.db, projectId);
|
|
64
68
|
if (!episodeMemoryOn(deps.db, channelId))
|
|
65
69
|
return "off";
|
|
@@ -78,7 +82,7 @@ async function summarize(deps, projectId, signal) {
|
|
|
78
82
|
if (choice === undefined) {
|
|
79
83
|
deps.log.write("info", "episode.memory", {
|
|
80
84
|
projectId,
|
|
81
|
-
detail: "No episode summary: this project has no
|
|
85
|
+
detail: "No episode summary: this project has no AI model chosen, so later episodes won't be reminded of it.",
|
|
82
86
|
});
|
|
83
87
|
return "no-llm";
|
|
84
88
|
}
|
|
@@ -3,7 +3,10 @@ import { sourceOf, thumbnailCountOf } from "../admission/model.js";
|
|
|
3
3
|
import { imageSecondsProblem, usesDescribedNarration, usesNarrationPreparation, usesReference, usesShorts, usesYoutubeDescription, } from "../admission/rules.js";
|
|
4
4
|
import { plainText } from "../article/plain.js";
|
|
5
5
|
import { splitEndMatter } from "../article/split.js";
|
|
6
|
+
import { usesAppearance } from "../images/appearance.js";
|
|
6
7
|
import { narrationMinutes, plannedImageCount, scalesImages } from "../images/scale.js";
|
|
8
|
+
import { usesSlopifyScene } from "../images/scenes.js";
|
|
9
|
+
import { keywordUsesOf, placeOfKey } from "../keywords/rules.js";
|
|
7
10
|
import { describedBlocks, narrationBlocks } from "../narration/blocks.js";
|
|
8
11
|
import { chunkNarration, defaultChunking } from "../narration/chunk.js";
|
|
9
12
|
import { describeMessages } from "../narration/describe.js";
|
|
@@ -13,12 +16,15 @@ import { defaultReviewPrompts, reviewedByAgent, reviewPromptKey, reviewRetriesOf
|
|
|
13
16
|
import { activeReviewStages } from "../reviews/rules.js";
|
|
14
17
|
import { isLocalCliProvider } from "../settings/model.js";
|
|
15
18
|
import { defaultShortsImagePrompt, defaultShortsPrompt, shortsImageUpperBound, shortsSettingsProblems, } from "../shorts/model.js";
|
|
19
|
+
import { socialPlatforms } from "../social/model.js";
|
|
20
|
+
import { defaultPostPrompt } from "../social/post-prompt.js";
|
|
16
21
|
import { animatedClipSeconds, animatedImageIndexes, usesAnimation, videoEditProblems, } from "../video/edit-settings.js";
|
|
17
|
-
import { usesVoices } from "../voices/model.js";
|
|
22
|
+
import { usesScriptPrompt, usesVoices } from "../voices/model.js";
|
|
18
23
|
import { defaultDescriptionPrompt } from "../youtube/model.js";
|
|
19
24
|
// ceiling: the most chapters "Chapter openers" is charged for before the article exists, the
|
|
20
25
|
// top of the 5-12 chapters the built-in YouTube description prompt asks for.
|
|
21
26
|
const chapterOpenersMax = 12;
|
|
27
|
+
import { sampleSpokenWords } from "../template-studio/scope.js";
|
|
22
28
|
import { estimateRequests, groupEstimateRows } from "./requests.js";
|
|
23
29
|
export { estimateRequests } from "./requests.js";
|
|
24
30
|
export function estimateRun(draft, rendered, expectedWords, catalogue) {
|
|
@@ -36,14 +42,13 @@ export function estimateRun(draft, rendered, expectedWords, catalogue) {
|
|
|
36
42
|
const tts = draft.audio ?? { provider: "", model: "" };
|
|
37
43
|
const image = draft.images ?? { provider: "", model: "" };
|
|
38
44
|
const textNote = isLocalCliProvider(llm.provider)
|
|
39
|
-
? "Runs on your
|
|
45
|
+
? "Runs on your subscription at no extra charge; the API figure is what the same work would cost through the API."
|
|
40
46
|
: (data.llm.find((model) => model.provider === llm.provider &&
|
|
41
47
|
model.id === llm.model &&
|
|
42
48
|
model.enabled &&
|
|
43
|
-
!model.deprecated)?.pricing.note ??
|
|
44
|
-
"CLI subscription or model pricing is unavailable; usage may be billed by your account.");
|
|
49
|
+
!model.deprecated)?.pricing.note ?? "No price is listed for this model; your account may be billed for it.");
|
|
45
50
|
const imageNote = isLocalCliProvider(image.provider)
|
|
46
|
-
? "Runs on your Codex
|
|
51
|
+
? "Runs on your Codex subscription at no extra charge."
|
|
47
52
|
: (data.image.find((model) => model.provider === image.provider &&
|
|
48
53
|
model.id === image.model &&
|
|
49
54
|
model.enabled &&
|
|
@@ -55,7 +60,8 @@ export function estimateRun(draft, rendered, expectedWords, catalogue) {
|
|
|
55
60
|
key === "description" ||
|
|
56
61
|
key === "shorts" ||
|
|
57
62
|
key === "shortsImage" ||
|
|
58
|
-
key.startsWith("review.")
|
|
63
|
+
key.startsWith("review.") ||
|
|
64
|
+
key.startsWith("social.")
|
|
59
65
|
? 0
|
|
60
66
|
: value.length), 0);
|
|
61
67
|
const local = (stage, detail) => {
|
|
@@ -91,15 +97,18 @@ export function estimateRun(draft, rendered, expectedWords, catalogue) {
|
|
|
91
97
|
code: draft.audio?.skipCode === true ? "skip" : "describe",
|
|
92
98
|
language: draft.language,
|
|
93
99
|
}));
|
|
94
|
-
|
|
100
|
+
// On a subscription the count does not change the price.
|
|
101
|
+
if (blocks === undefined && isLocalCliProvider(llm.provider))
|
|
102
|
+
local("Describing tables and figures", "One AI call per table, figure, equation or code block in the article, on your subscription at no extra charge.");
|
|
103
|
+
else if (blocks === undefined)
|
|
95
104
|
requests.push({
|
|
96
105
|
kind: "unknown",
|
|
97
|
-
stage: "
|
|
98
|
-
detail: "One
|
|
106
|
+
stage: "Describing tables and figures",
|
|
107
|
+
detail: "One AI call per table, figure, equation or code block in the article; how many is known once the article is written.",
|
|
99
108
|
});
|
|
100
109
|
else
|
|
101
110
|
for (const block of blocks)
|
|
102
|
-
text("
|
|
111
|
+
text("Describing tables and figures", describeMessages(block, rendered.narration ?? "", draft.language).reduce((n, message) => n + message.content.length, 0), 600, `${String(blocks.length)} AI ${blocks.length === 1 ? "call" : "calls"}: one per table, figure, equation or code block.`);
|
|
103
112
|
}
|
|
104
113
|
if (draft.sources.audio === "generate") {
|
|
105
114
|
if (usesNarrationPreparation(draft)) {
|
|
@@ -115,18 +124,20 @@ export function estimateRun(draft, rendered, expectedWords, catalogue) {
|
|
|
115
124
|
if (unknown)
|
|
116
125
|
requests.push({
|
|
117
126
|
kind: "unknown",
|
|
118
|
-
stage: "Narration
|
|
119
|
-
detail: "One
|
|
127
|
+
stage: "Narration preparation",
|
|
128
|
+
detail: "One AI call per narration piece and per intro or outro written for it; how many is known once the text is written.",
|
|
120
129
|
});
|
|
121
130
|
else
|
|
122
131
|
for (const source of known)
|
|
123
|
-
text("Narration
|
|
132
|
+
text("Narration preparation", preparationMessages(rendered.narration ?? "", source, [], draft.language).reduce((n, message) => n + message.content.length, 0), 2400, `${known.length} AI calls: one per narration piece or intro or outro.`);
|
|
124
133
|
requests.push({
|
|
125
134
|
kind: "unknown",
|
|
126
|
-
stage: "Delivery
|
|
127
|
-
detail: "
|
|
135
|
+
stage: "Delivery cues",
|
|
136
|
+
detail: "The voice service charges per character, delivery tags included; their length is known after preparation.",
|
|
128
137
|
});
|
|
129
138
|
}
|
|
139
|
+
// A template studio sample says only the narration's opening (`template-studio/scope.ts`).
|
|
140
|
+
const spokenChars = draft.sample === undefined ? articleChars : Math.min(articleChars, sampleSpokenWords * 6);
|
|
130
141
|
const extras = ["intro", "outro"].reduce((n, key) => n + (rendered[key]?.length ?? 0), 0);
|
|
131
142
|
const llmExtras = (draft.intro?.mode === "llm" ? 1200 : 0) + (draft.outro?.mode === "llm" ? 1200 : 0);
|
|
132
143
|
const choice = { stage: "Narration", provider: tts.provider, model: tts.model };
|
|
@@ -140,19 +151,19 @@ export function estimateRun(draft, rendered, expectedWords, catalogue) {
|
|
|
140
151
|
stage: "Narration",
|
|
141
152
|
provider: speaker.voice.provider,
|
|
142
153
|
model: speaker.voice.model,
|
|
143
|
-
characters: Math.round(
|
|
154
|
+
characters: Math.round(spokenChars / speakers.length),
|
|
144
155
|
detail: `${speaker.name.trim() || "A speaker"}: assumes every speaker says about the same.`,
|
|
145
156
|
});
|
|
146
157
|
if (extras + llmExtras > 0)
|
|
147
158
|
requests.push({ ...choice, kind: "tts-estimate", characters: extras + llmExtras });
|
|
148
159
|
if (draft.voices?.source === "attribute")
|
|
149
|
-
text("Speaker split", articleChars + 1500, Math.round(articleChars * 1.1), "One
|
|
160
|
+
text("Speaker split", articleChars + 1500, Math.round(articleChars * 1.1), "One AI call hands the text's passages to the speakers.");
|
|
150
161
|
if (draft.voices?.source === "adapt")
|
|
151
|
-
text("Conversation script", articleChars + 1500, Math.round(articleChars * 1.2), "One
|
|
162
|
+
text("Conversation script", articleChars + 1500, Math.round(articleChars * 1.2), "One AI call rewrites the text as a conversation between the speakers; the article stays as written.");
|
|
152
163
|
}
|
|
153
164
|
else
|
|
154
165
|
requests.push(generatedArticle || llmExtras > 0
|
|
155
|
-
? { ...choice, kind: "tts-estimate", characters:
|
|
166
|
+
? { ...choice, kind: "tts-estimate", characters: spokenChars + extras + llmExtras }
|
|
156
167
|
: {
|
|
157
168
|
...choice,
|
|
158
169
|
kind: "tts",
|
|
@@ -178,9 +189,29 @@ export function estimateRun(draft, rendered, expectedWords, catalogue) {
|
|
|
178
189
|
});
|
|
179
190
|
if (images === 0)
|
|
180
191
|
local("Images", "Provided or off.");
|
|
181
|
-
// Scenes from the article: one call reads the article and writes every image's scene.
|
|
182
|
-
|
|
192
|
+
// Scenes from the article: one call reads the article and writes every image's scene. A
|
|
193
|
+
// `Slopify_` scene keyword turns it on for the pictures that use it, switch or no switch.
|
|
194
|
+
const pictureKeys = Object.keys(rendered).filter((key) => /^imagePrompts\.\d+$/.test(key));
|
|
195
|
+
if (images > 0 &&
|
|
196
|
+
(draft.imageScenes === true || pictureKeys.some((key) => usesSlopifyScene(rendered[key]))))
|
|
183
197
|
text("Image scenes", articleChars + 1500, 120 * images);
|
|
198
|
+
if (draft.sources.thumbnail === "from_prompt" && usesSlopifyScene(rendered.thumbnailPrompt))
|
|
199
|
+
text("Thumbnail scenes", articleChars + 1500, 120 * thumbnailCountOf(draft));
|
|
200
|
+
// The keyword digest: one call reads the article and writes every digest keyword.
|
|
201
|
+
const placed = Object.entries(rendered).flatMap(([key, body]) => {
|
|
202
|
+
const place = placeOfKey(key, { script: usesScriptPrompt(draft) });
|
|
203
|
+
return place === undefined ? [] : [{ field: key, place, body }];
|
|
204
|
+
});
|
|
205
|
+
if (keywordUsesOf(placed).digest !== undefined)
|
|
206
|
+
text("Keyword digest", articleChars + 1500, 600, "One call reads the article and writes every digest keyword the run uses.");
|
|
207
|
+
// `{{Appearance}}` (or `{{Slopify_Appearance}}`): one call with web search looks up the looks.
|
|
208
|
+
if ([
|
|
209
|
+
...(images > 0 ? pictureKeys : []),
|
|
210
|
+
...(draft.sources.thumbnail === "from_prompt" ? ["thumbnailPrompt"] : []),
|
|
211
|
+
"referencePrompt",
|
|
212
|
+
"shortsImage",
|
|
213
|
+
].some((key) => usesAppearance(rendered[key])))
|
|
214
|
+
text("Appearance lookup", articleChars + 1500, 1500, "One call with web search looks up how the subject and characters look.");
|
|
184
215
|
// The establishing image is one more image when it is made from a prompt.
|
|
185
216
|
if (usesReference(draft) && draft.reference?.source === "prompt")
|
|
186
217
|
requests.push({
|
|
@@ -201,7 +232,11 @@ export function estimateRun(draft, rendered, expectedWords, catalogue) {
|
|
|
201
232
|
local("Thumbnail", "Provided or off.");
|
|
202
233
|
if (draft.sources.thumbnail === "prompt_by_llm")
|
|
203
234
|
text("Thumbnail prompt", promptChars + articleChars, 1200);
|
|
204
|
-
|
|
235
|
+
// Putting it together on this computer: the video (with its captions), or the sound alone.
|
|
236
|
+
if (draft.sources.video === "generate")
|
|
237
|
+
local("Video", "Made on this computer; no API fee.");
|
|
238
|
+
else if (draft.sources.audio !== "off")
|
|
239
|
+
local("Audio export", "Made on this computer; no API fee.");
|
|
205
240
|
// The timed transcript is the narration with a time before every passage of about 20 s,
|
|
206
241
|
// plus the fixed rules of the answer.
|
|
207
242
|
if (usesYoutubeDescription(draft))
|
|
@@ -209,7 +244,14 @@ export function estimateRun(draft, rendered, expectedWords, catalogue) {
|
|
|
209
244
|
? rendered.description.length
|
|
210
245
|
: defaultDescriptionPrompt.length) +
|
|
211
246
|
Math.round(articleChars * 1.05) +
|
|
212
|
-
1500, 2400, "One
|
|
247
|
+
1500, 2400, "One AI call on the timed transcript.");
|
|
248
|
+
// Each site whose post is written by a post prompt: one call that reads the article.
|
|
249
|
+
for (const platform of socialPlatforms) {
|
|
250
|
+
if (draft.social?.[platform]?.text !== "prompt")
|
|
251
|
+
continue;
|
|
252
|
+
const own = rendered[`social.${platform}`]?.trim() ?? "";
|
|
253
|
+
text("Posts", (own === "" ? defaultPostPrompt.length : own.length) + articleChars + 400, 600, "One AI call per site whose post a post prompt writes, reading the article.");
|
|
254
|
+
}
|
|
213
255
|
// Shorts: one call picks the clips from the numbered transcript, one per clip writes its
|
|
214
256
|
// image prompts, and the images are charged at the most the step can ask for, every clip
|
|
215
257
|
// at the longest length allowed.
|
|
@@ -221,12 +263,12 @@ export function estimateRun(draft, rendered, expectedWords, catalogue) {
|
|
|
221
263
|
imageSecondsProblem(draft.imageSeconds) === undefined) {
|
|
222
264
|
text("Shorts", (rendered.shorts?.trim() ? rendered.shorts.length : defaultShortsPrompt.length) +
|
|
223
265
|
Math.round(articleChars * 1.15) +
|
|
224
|
-
1500, 400 * shorts.count, "One
|
|
266
|
+
1500, 400 * shorts.count, "One AI call on the numbered transcript picks the clips.");
|
|
225
267
|
const style = rendered.shortsImage?.trim()
|
|
226
268
|
? rendered.shortsImage.length
|
|
227
269
|
: defaultShortsImagePrompt.length;
|
|
228
270
|
for (let clip = 0; clip < shorts.count; clip++)
|
|
229
|
-
text("Shorts", style + 3000, 2400, "One
|
|
271
|
+
text("Shorts", style + 3000, 2400, "One AI call per short writes its image prompts.");
|
|
230
272
|
const count = shortsImageUpperBound(shorts, draft.imageSeconds);
|
|
231
273
|
for (let index = 0; index < count; index++)
|
|
232
274
|
requests.push({
|
|
@@ -262,7 +304,7 @@ export function estimateRun(draft, rendered, expectedWords, catalogue) {
|
|
|
262
304
|
const reviews = draft.reviews;
|
|
263
305
|
if (reviews !== undefined && reviewedByAgent(reviews)) {
|
|
264
306
|
if (activeReviewStages(draft).length > 0)
|
|
265
|
-
local("Reviews", "
|
|
307
|
+
local("Reviews", "Your own AI agent answers each check; no API fee.");
|
|
266
308
|
}
|
|
267
309
|
else if (reviews !== undefined)
|
|
268
310
|
for (const stage of activeReviewStages(draft)) {
|
|
@@ -273,7 +315,9 @@ export function estimateRun(draft, rendered, expectedWords, catalogue) {
|
|
|
273
315
|
? articleChars + promptChars
|
|
274
316
|
: stage === "narration"
|
|
275
317
|
? Math.round(articleChars * 2.1)
|
|
276
|
-
:
|
|
318
|
+
: stage === "promise"
|
|
319
|
+
? articleChars + 1500
|
|
320
|
+
: 1500;
|
|
277
321
|
for (let index = 0; index < items; index++)
|
|
278
322
|
requests.push({
|
|
279
323
|
kind: "llm",
|
|
@@ -286,7 +330,7 @@ export function estimateRun(draft, rendered, expectedWords, catalogue) {
|
|
|
286
330
|
});
|
|
287
331
|
}
|
|
288
332
|
if (sourceOf(draft.sources, "document") === "generate")
|
|
289
|
-
local("
|
|
333
|
+
local("PDF", "Laid out on this computer from the article; no API fee.");
|
|
290
334
|
return {
|
|
291
335
|
...groupEstimateRows(estimateRequests(requests, data)),
|
|
292
336
|
expectedWords,
|