@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,166 @@
|
|
|
1
|
+
import { keyProbes } from "./adapters/key-probes.js";
|
|
2
|
+
import { emptyLifecycle, retirementOf } from "./catalog/lifecycle.js";
|
|
3
|
+
import { thinkingModes } from "./kernel/ports/llm.js";
|
|
4
|
+
import { readinessIsUsable } from "./kernel/ports/model.js";
|
|
5
|
+
import { checkModel } from "./kernel/runner/model-check.js";
|
|
6
|
+
import { modelSources } from "./model-catalog.js";
|
|
7
|
+
import { isVideoTarget, spentOn } from "./slices/model-checks/cost.js";
|
|
8
|
+
import { createListing } from "./slices/model-checks/listing.js";
|
|
9
|
+
import { createModelChecks } from "./slices/model-checks/service.js";
|
|
10
|
+
import { isLocalCliProvider, systemVoiceProvider, } from "./slices/settings/model.js";
|
|
11
|
+
import { listVoices } from "./slices/settings/repo.js";
|
|
12
|
+
// The composition layer's check recipes: what the smallest request is for each kind of model.
|
|
13
|
+
// A reply of one word at the lowest thinking setting, a voice saying "Hi", a one-to-one grey
|
|
14
|
+
// dot. Image-to-video models are listed only, never generated.
|
|
15
|
+
export const checkPrompt = "Reply with OK.";
|
|
16
|
+
export const checkSpeech = "Hi";
|
|
17
|
+
export const checkPicture = "a small grey dot";
|
|
18
|
+
// A voice every account of these providers has, for a check made before any voice is saved.
|
|
19
|
+
const defaultVoices = {
|
|
20
|
+
"openai-tts": "alloy",
|
|
21
|
+
"google-tts": "Kore",
|
|
22
|
+
// ElevenLabs' premade "Rachel".
|
|
23
|
+
elevenlabs: "21m00Tcm4TlvDq8ikWAM",
|
|
24
|
+
};
|
|
25
|
+
function lowest(modes) {
|
|
26
|
+
if (modes === undefined || modes.length === 0)
|
|
27
|
+
return undefined;
|
|
28
|
+
return thinkingModes.find((mode) => modes.includes(mode));
|
|
29
|
+
}
|
|
30
|
+
export async function recipeFor(deps, target) {
|
|
31
|
+
const catalogue = deps.catalogue();
|
|
32
|
+
const { provider, model } = target;
|
|
33
|
+
if (target.family === "llm") {
|
|
34
|
+
let modes;
|
|
35
|
+
if (isLocalCliProvider(provider))
|
|
36
|
+
modes = (await deps.cliModels(provider, "llm").catch(() => [])).find((m) => m.id === model)?.thinkingModes;
|
|
37
|
+
else {
|
|
38
|
+
const row = catalogue.llm.find((m) => m.provider === provider && m.id === model);
|
|
39
|
+
modes = row?.llm.thinking === undefined ? undefined : Object.keys(row.llm.thinking);
|
|
40
|
+
}
|
|
41
|
+
const thinking = lowest(modes);
|
|
42
|
+
return {
|
|
43
|
+
kind: "call",
|
|
44
|
+
call: {
|
|
45
|
+
kind: "llm",
|
|
46
|
+
provider,
|
|
47
|
+
model,
|
|
48
|
+
prompt: checkPrompt,
|
|
49
|
+
...(thinking === undefined ? {} : { thinking }),
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
if (target.family === "tts") {
|
|
54
|
+
if (provider === systemVoiceProvider)
|
|
55
|
+
return (await deps.systemVoiceReady())
|
|
56
|
+
? { kind: "free-works" }
|
|
57
|
+
: { kind: "skip", reason: "No speech program was found on this computer." };
|
|
58
|
+
const voiceId = deps.voices().find((voice) => voice.provider === provider)?.voiceId ??
|
|
59
|
+
(Object.hasOwn(defaultVoices, provider) ? defaultVoices[provider] : undefined);
|
|
60
|
+
if (voiceId === undefined)
|
|
61
|
+
return {
|
|
62
|
+
kind: "skip",
|
|
63
|
+
reason: "Add a voice for this provider in Settings → Voices, then choose Check models.",
|
|
64
|
+
};
|
|
65
|
+
return { kind: "call", call: { kind: "tts", provider, model, voiceId, text: checkSpeech } };
|
|
66
|
+
}
|
|
67
|
+
if (isVideoTarget(catalogue, target))
|
|
68
|
+
return { kind: "skip", reason: "Image-to-video models are listed, never checked." };
|
|
69
|
+
const row = catalogue.image.find((m) => m.provider === provider && m.id === model);
|
|
70
|
+
const ratios = row?.image.aspectRatios ?? ["1:1"];
|
|
71
|
+
const aspect = ratios.includes("1:1") ? "1:1" : (ratios[0] ?? "1:1");
|
|
72
|
+
let thinking;
|
|
73
|
+
if (isLocalCliProvider(provider))
|
|
74
|
+
thinking = lowest((await deps.cliModels(provider, "image").catch(() => [])).find((m) => m.id === model)
|
|
75
|
+
?.thinkingModes);
|
|
76
|
+
return {
|
|
77
|
+
kind: "call",
|
|
78
|
+
call: {
|
|
79
|
+
kind: "image",
|
|
80
|
+
provider,
|
|
81
|
+
model,
|
|
82
|
+
prompt: checkPicture,
|
|
83
|
+
aspect,
|
|
84
|
+
...(thinking === undefined ? {} : { thinking }),
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
export function modelChecker(deps) {
|
|
89
|
+
return async (target, signal) => {
|
|
90
|
+
const recipe = await recipeFor(deps, target);
|
|
91
|
+
if (recipe.kind === "skip")
|
|
92
|
+
return { kind: "skipped", reason: recipe.reason };
|
|
93
|
+
if (recipe.kind === "free-works")
|
|
94
|
+
return { kind: "checked", verdict: "works", sentence: null, stopProvider: false, spent: 0 };
|
|
95
|
+
const answer = await checkModel(deps, recipe.call, signal);
|
|
96
|
+
return {
|
|
97
|
+
kind: "checked",
|
|
98
|
+
verdict: answer.verdict,
|
|
99
|
+
sentence: answer.sentence,
|
|
100
|
+
stopProvider: answer.stopProvider,
|
|
101
|
+
// A failure the provider may have billed is counted at the estimate the check showed.
|
|
102
|
+
spent: answer.verdict === "works"
|
|
103
|
+
? spentOn(deps.catalogue(), target, answer.use)
|
|
104
|
+
: answer.mayHaveBilled
|
|
105
|
+
? spentOn(deps.catalogue(), target, null)
|
|
106
|
+
: 0,
|
|
107
|
+
};
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
// The model-checks service as main.ts runs it: free listings from the providers' own model
|
|
111
|
+
// endpoints, and checks made through the recipes above.
|
|
112
|
+
export function wireModelChecks(deps) {
|
|
113
|
+
const { modelsFor } = modelSources(deps.registry);
|
|
114
|
+
const listing = createListing({
|
|
115
|
+
db: deps.db,
|
|
116
|
+
clock: deps.clock,
|
|
117
|
+
fetch: deps.fetch,
|
|
118
|
+
probes: keyProbes,
|
|
119
|
+
known: (provider, family) => deps
|
|
120
|
+
.catalogue()[family].filter((row) => row.provider === provider && row.enabled && !row.deprecated)
|
|
121
|
+
.map((row) => row.id),
|
|
122
|
+
cliModels: async (provider, family) => (await modelsFor(provider, family)).map((m) => m.id),
|
|
123
|
+
});
|
|
124
|
+
const checks = createModelChecks({
|
|
125
|
+
db: deps.db,
|
|
126
|
+
clock: deps.clock,
|
|
127
|
+
log: deps.log,
|
|
128
|
+
catalogue: deps.catalogue,
|
|
129
|
+
listing,
|
|
130
|
+
providerModels: modelsFor,
|
|
131
|
+
retiring: (model) => retirementOf(deps.lifecycle?.() ?? emptyLifecycle, deps.catalogue(), model),
|
|
132
|
+
check: modelChecker({
|
|
133
|
+
registry: deps.registry,
|
|
134
|
+
clock: deps.clock,
|
|
135
|
+
log: deps.log,
|
|
136
|
+
catalogue: deps.catalogue,
|
|
137
|
+
voices: () => listVoices(deps.db),
|
|
138
|
+
cliModels: modelsFor,
|
|
139
|
+
systemVoiceReady: async () => (await deps.statuses()).some((status) => status.id === systemVoiceProvider && readinessIsUsable(status.readiness)),
|
|
140
|
+
}),
|
|
141
|
+
});
|
|
142
|
+
return { checks, listing };
|
|
143
|
+
}
|
|
144
|
+
// A CLI that has become usable - installed and signed in - since the last look, or one that is
|
|
145
|
+
// usable and was never listed, is checked as if it had just been added.
|
|
146
|
+
export function cliWatcher(checks, statuses, known) {
|
|
147
|
+
const usable = new Map();
|
|
148
|
+
return async () => {
|
|
149
|
+
for (const status of await statuses()) {
|
|
150
|
+
if (status.readiness.kind !== "cli")
|
|
151
|
+
continue;
|
|
152
|
+
const now = readinessIsUsable(status.readiness);
|
|
153
|
+
const before = usable.get(status.id);
|
|
154
|
+
usable.set(status.id, now);
|
|
155
|
+
if (now && (before === false || (before === undefined && !known(status.id))))
|
|
156
|
+
await checks.automatic("cli-added", status.id);
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
// The hourly look. The weekly look goes first: it lists and checks every provider, a CLI
|
|
161
|
+
// among them, so a CLI it has just checked is known and isn't checked again as newly added.
|
|
162
|
+
export async function lookAtModels(checks, lookForClis) {
|
|
163
|
+
if (checks.weeklyDue())
|
|
164
|
+
await checks.automatic("weekly");
|
|
165
|
+
await lookForClis();
|
|
166
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Slopify 4.0.0
|
|
2
|
+
|
|
3
|
+
Released 18 October 2026.
|
|
4
|
+
|
|
5
|
+
## Edit template
|
|
6
|
+
|
|
7
|
+
- **Set a template up once, with real samples.** Templates → **Edit template** shows a template section by section: Title and keywords, Article, Narration, Images, Video and style, Thumbnail, Shorts, PDF, Pauses and checks, YouTube description and posts, and Schedule. Each Save makes a short sample of the sections it changed with your own services. The sample is the opening of the article, about 30 seconds of narration, 4 images, a 30-second clip, a short, the PDF and the description, so you see and hear the result before a schedule uses it.
|
|
8
|
+
- Every paid Save shows its price on the button. A daily sample budget (Settings → Production defaults → Template samples, $2 by default) holds samples that would go over it. Claude Code and Codex plans are used only when you turn on "Let samples use my Claude Code or Codex plan".
|
|
9
|
+
- **Approve for schedules.** Once you approve a version in Edit template, schedules run the newest approved version and later edits wait until you approve them. Templates you never approve keep following their newest version, as before.
|
|
10
|
+
- **Compare models** makes one section's sample with 2–3 models side by side, with cost and time. **Say it as…** fixes a name the voice mispronounces. **Export as a file (.zip)** and **Import a template file (.zip)** share a template with its samples.
|
|
11
|
+
- Create opens on a template and a topic; **Make the video** starts it.
|
|
12
|
+
|
|
13
|
+
## Posting to X, LinkedIn, Instagram, TikTok, Bluesky and Reddit
|
|
14
|
+
|
|
15
|
+
- **Copy for YouTube Studio** has a **Where** choice: YouTube plus each site the project posts to. Each post shows its text, its media in the site's shape, a live character count and plain warnings. Templates set the defaults in Edit template → YouTube description and posts.
|
|
16
|
+
- **Fill in <site>** opens the site and the Slopify Studio extension fills the post: text, media, the site's AI label, and its own scheduler where it has one (X, LinkedIn, TikTok). You press Post. On Instagram, Bluesky and Reddit, which have no scheduler, the extension fills the post at its release time and notifies you.
|
|
17
|
+
- The extension never presses Post, Share or Publish, and it only fills tabs Slopify opened. Allow each site in the extension's options with "Allow posting on …". Reddit has not been checked live yet.
|
|
18
|
+
|
|
19
|
+
## Images and designed pieces
|
|
20
|
+
|
|
21
|
+
- **Edit a picture** you upload with an instruction, and keep editing the result. Every step is a version you can go back to.
|
|
22
|
+
- **Design posters and flyers.** The AI makes the artwork and Slopify sets the names, dates and prices in real fonts, so they are always spelled right. Download PNG or a print-ready PDF in A4, A3, A5 and social sizes. A design template with fields (event, date, venue…) makes a piece per row ahead of its date, or one at a time with Make a piece.
|
|
23
|
+
|
|
24
|
+
## Keywords Slopify fills
|
|
25
|
+
|
|
26
|
+
- New built-in keywords such as {{Slopify_Title}}, {{Slopify_Summary}}, {{Slopify_Hook}}, {{Slopify_Chapters}}, {{Slopify_Setting}} and {{Slopify_Thumbnail_Text}}. The Insert bar above each prompt lists the ones that work there, with an example and what they cost. {{Scene}} and {{Appearance}} keep working; the editor offers to update them to {{Slopify_Scene}} and {{Slopify_Appearance}}.
|
|
27
|
+
|
|
28
|
+
## Assistant, health and checks
|
|
29
|
+
|
|
30
|
+
- **Assistant.** A chat panel that runs on your Claude Code or Codex and can only use Slopify's own tools. It asks before anything that costs money, deletes or sends something, and shows what it will do. Its changes show as "by assistant".
|
|
31
|
+
- **Coming up on Home** says how many days of videos are ready, when a schedule's topics run out, and warns before something breaks: Claude Code or Codex signed out, a plan near its limit, disk filling, a model being retired. A weekly report can go to your notification URL (off by default).
|
|
32
|
+
- **Models that work for you.** Model pickers show which models your key or plan can actually run, with Check models and a weekly free check. Models that are being retired show their replacement.
|
|
33
|
+
- **Promise check.** An optional cheap review before narration: does the opening deliver what the title and thumbnail promise.
|
|
34
|
+
- **Topic ranking.** Schedules can rank new topics by what your library already covers, or also by public search interest (sends topic titles to Google, DuckDuckGo and Wikipedia; off by default).
|
|
35
|
+
|
|
36
|
+
## Remote access and encoding
|
|
37
|
+
|
|
38
|
+
- **Open Slopify on your phone or laptop** through Tailscale (Settings → Remote access). Only devices on your own tailnet can open it, never the public internet. Keys, imports and updates can only be changed on this computer.
|
|
39
|
+
- **Encoding settings** (Settings → Production defaults → Encoding): video encoder (processor or NVIDIA graphics card), clip encoding speed and encoding priority.
|
|
40
|
+
|
|
41
|
+
## Fixes
|
|
42
|
+
|
|
43
|
+
- A run's share of your Claude or Codex plan is now its own use only, never above 100%.
|
|
44
|
+
- Narration levelling now reaches the target loudness (−14 LUFS lands within 0.1 LU).
|
|
45
|
+
- The extension reads A/B test results again after it sets up A/B Testing.
|
|
46
|
+
|
|
47
|
+
## Upgrading from 3.25.9
|
|
48
|
+
|
|
49
|
+
- Your projects, templates and schedules carry over unchanged; existing projects are not remade. Every template version you had keeps running, as before.
|
|
50
|
+
- The extension goes to 2.0.0. Posting needs its new optional permissions, granted in its options; YouTube works as before without them.
|
|
51
|
+
- `/mcp` now answers only on this computer: connect agents to `http://127.0.0.1:<port>/mcp`, not through a proxy.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Slopify 4.1.0
|
|
2
|
+
|
|
3
|
+
Released 7 November 2026.
|
|
4
|
+
|
|
5
|
+
This release is about making Slopify easy to use without reading anything first: every button says what it does, each screen shows more and wastes less space, and the same thing has the same name everywhere.
|
|
6
|
+
|
|
7
|
+
## Finding your way around
|
|
8
|
+
|
|
9
|
+
- **A new rail.** The left rail is narrow, with a word under every icon: Create, Home, Projects, Prompts, Templates, Calendar, Channels (once you have two or more) and Settings, then Search, Assistant, Help and Support Slopify at the foot. On a phone the bottom bar has Create in the middle.
|
|
10
|
+
- **Library is split in two.** **Prompts** holds your prompts and intros and outros, with every kind listed down the left. **Templates** holds video and poster templates. PDF looks are under Settings → Production defaults and Create's PDF choice, Pronunciation is under Settings → Voices, and What worked on YouTube is on the channel page. Old addresses still open the right page.
|
|
11
|
+
- The channel picker reads **Showing: All channels** in the header of Home, Projects and Calendar, and only appears with two or more channels.
|
|
12
|
+
|
|
13
|
+
## Your first video
|
|
14
|
+
|
|
15
|
+
- The welcome is a checklist of what a short needs (Article, Narration, Images), each with its state and one button to fix it. The usage notice is a single line at the bottom of the window instead of a dialog, and start at login is asked once.
|
|
16
|
+
- **Create is one screen.** Pick what you're making, type the topic (the box has the cursor already) and press **Make the video**. Each part of the run is one sentence with Change, and anything missing is named once, with Fix. On a phone the Make button stays pinned within reach.
|
|
17
|
+
- **New prompt** opens beside Create and picks the prompt when you save, so you never leave the page. If you skipped the starter templates, Create offers them.
|
|
18
|
+
- **Everything this run will do** shows the whole run in plain sentences before you start.
|
|
19
|
+
|
|
20
|
+
## A finished project
|
|
21
|
+
|
|
22
|
+
- The video, its downloads, the chapters, the shorts and every stage's status are on the first screen. Each section (Article, Narration, Images, Video, Shorts, YouTube, PDF, All files) leads with what it made and a named download.
|
|
23
|
+
- **Edit settings** uses Create's sections and names. **Versions** replaces History.
|
|
24
|
+
- Every action is a visible button: Mark uploaded, Rename, Save as template and Delete. Paid work says so on its button ("Make this image again").
|
|
25
|
+
|
|
26
|
+
## Lists and settings
|
|
27
|
+
|
|
28
|
+
- **Home** shows your finished videos first, with Watch and Download, then what needs you and what's running, step by step.
|
|
29
|
+
- **Projects** rows show a picture, the length, what was made and when, with Open and Download.
|
|
30
|
+
- **Templates** are cards that say what each one makes, with **Make a video** and **Edit template**. Edit template's sections match Create's.
|
|
31
|
+
- **Prompts** searches every kind at once. The editor reads like text, **Insert a keyword** shows exactly what goes in, and every kind has examples to start from.
|
|
32
|
+
- **Settings** is one list of pages. **Keys & services** opens on three lines (who writes, who reads, who draws), each Ready or with a button to set it up. Trash has its own page, and Projects and Prompts show **Trash (n)** when something is in it.
|
|
33
|
+
|
|
34
|
+
## One word per thing
|
|
35
|
+
|
|
36
|
+
- Captions (not subtitles), Narration, Voice, Images, Make … again (not Remake or Regenerate), Copy for YouTube Studio, Pauses and checks, PDF looks, and US spelling throughout.
|
|
37
|
+
- Info buttons are gone where a short line under the setting says it better. A status dot always has its word next to it, and each area has at most one lime button.
|
|
38
|
+
|
|
39
|
+
## Fixes
|
|
40
|
+
|
|
41
|
+
- Typing the topic the moment Create opens no longer drops the starter template's writer and image service.
|
|
42
|
+
- Make the video is ready about a second after you stop typing, instead of three or four.
|
|
@@ -1,4 +1,16 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"id": "4.1.0",
|
|
4
|
+
"title": "Slopify 4.1.0",
|
|
5
|
+
"version": "4.1.0",
|
|
6
|
+
"date": "2026-11-07"
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"id": "4.0.0",
|
|
10
|
+
"title": "Slopify 4.0.0",
|
|
11
|
+
"version": "4.0.0",
|
|
12
|
+
"date": "2026-10-18"
|
|
13
|
+
},
|
|
2
14
|
{
|
|
3
15
|
"id": "3.25.9",
|
|
4
16
|
"title": "Slopify 3.25.9",
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
import { notTemplateSample } from "../template-studio/repo.js";
|
|
2
3
|
import { bookSchema } from "../voices/model.js";
|
|
3
4
|
import { formats } from "./model.js";
|
|
4
5
|
import { liveProject } from "./repo.js";
|
|
@@ -33,7 +34,7 @@ const headSelect = `SELECT projects.id, projects.title, projects.format, project
|
|
|
33
34
|
FROM projects LEFT JOIN project_controls ON project_controls.project_id = projects.id`;
|
|
34
35
|
export function listProjectHeads(db) {
|
|
35
36
|
return db
|
|
36
|
-
.prepare(`${headSelect} WHERE ${liveProject()} ORDER BY created_at DESC, id DESC`)
|
|
37
|
+
.prepare(`${headSelect} WHERE ${liveProject()} AND ${notTemplateSample()} ORDER BY created_at DESC, id DESC`)
|
|
37
38
|
.all()
|
|
38
39
|
.map((raw) => {
|
|
39
40
|
const row = headRow.parse(raw);
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { stageKinds } from "../../kernel/pipeline.js";
|
|
3
|
+
const outputRow = z.object({
|
|
4
|
+
project_id: z.string(),
|
|
5
|
+
role: z.string(),
|
|
6
|
+
count: z.number(),
|
|
7
|
+
duration_ms: z.number().nullable(),
|
|
8
|
+
});
|
|
9
|
+
const stageRow = z.object({
|
|
10
|
+
project_id: z.string(),
|
|
11
|
+
kind: z.enum(stageKinds),
|
|
12
|
+
state: z.string(),
|
|
13
|
+
finished_at: z.string().nullable(),
|
|
14
|
+
});
|
|
15
|
+
const outdatedRow = z.object({ project_id: z.string() });
|
|
16
|
+
// The roles a row names. A sound-only run's length comes from its export.
|
|
17
|
+
const namedRoles = [
|
|
18
|
+
"video",
|
|
19
|
+
"short_video",
|
|
20
|
+
"document_pdf",
|
|
21
|
+
"audio_mp3",
|
|
22
|
+
"audio_m4b",
|
|
23
|
+
"audio_export",
|
|
24
|
+
];
|
|
25
|
+
const audioRoles = new Set(["audio_mp3", "audio_m4b", "audio_export"]);
|
|
26
|
+
export function listingFacts(db) {
|
|
27
|
+
const gathered = new Map();
|
|
28
|
+
const of = (projectId) => {
|
|
29
|
+
let one = gathered.get(projectId);
|
|
30
|
+
if (one === undefined) {
|
|
31
|
+
one = {
|
|
32
|
+
outputs: { video: false, shorts: 0, pdf: false, audio: false },
|
|
33
|
+
videoMs: null,
|
|
34
|
+
audioMs: null,
|
|
35
|
+
finishedAt: null,
|
|
36
|
+
failed: [],
|
|
37
|
+
};
|
|
38
|
+
gathered.set(projectId, one);
|
|
39
|
+
}
|
|
40
|
+
return one;
|
|
41
|
+
};
|
|
42
|
+
const roles = namedRoles.map(() => "?").join(",");
|
|
43
|
+
for (const row of db
|
|
44
|
+
.prepare(`SELECT project_id, role, COUNT(*) AS count, MAX(duration_ms) AS duration_ms FROM outputs WHERE role IN (${roles}) GROUP BY project_id, role`)
|
|
45
|
+
.all(...namedRoles)) {
|
|
46
|
+
const parsed = outputRow.parse(row);
|
|
47
|
+
const one = of(parsed.project_id);
|
|
48
|
+
if (parsed.role === "video") {
|
|
49
|
+
one.outputs.video = true;
|
|
50
|
+
one.videoMs = parsed.duration_ms;
|
|
51
|
+
}
|
|
52
|
+
else if (parsed.role === "short_video")
|
|
53
|
+
one.outputs.shorts = parsed.count;
|
|
54
|
+
else if (parsed.role === "document_pdf")
|
|
55
|
+
one.outputs.pdf = true;
|
|
56
|
+
else if (audioRoles.has(parsed.role)) {
|
|
57
|
+
one.outputs.audio = true;
|
|
58
|
+
if (parsed.duration_ms !== null)
|
|
59
|
+
one.audioMs = Math.max(one.audioMs ?? 0, parsed.duration_ms);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
for (const row of db
|
|
63
|
+
.prepare("SELECT project_id, kind, state, finished_at FROM stages WHERE state IN ('done','failed','provided') ORDER BY rowid")
|
|
64
|
+
.all()) {
|
|
65
|
+
const parsed = stageRow.parse(row);
|
|
66
|
+
const one = of(parsed.project_id);
|
|
67
|
+
if (parsed.finished_at !== null &&
|
|
68
|
+
(one.finishedAt === null || parsed.finished_at > one.finishedAt))
|
|
69
|
+
one.finishedAt = parsed.finished_at;
|
|
70
|
+
if (parsed.state === "failed")
|
|
71
|
+
one.failed.push(parsed.kind);
|
|
72
|
+
}
|
|
73
|
+
const outdated = new Set(db
|
|
74
|
+
.prepare("SELECT DISTINCT revision_outputs.project_id FROM revision_outputs JOIN project_heads ON project_heads.project_id = revision_outputs.project_id AND project_heads.revision_id = revision_outputs.revision_id WHERE revision_outputs.selected = 1 AND revision_outputs.state = 'outdated'")
|
|
75
|
+
.all()
|
|
76
|
+
.map((row) => outdatedRow.parse(row).project_id));
|
|
77
|
+
const facts = new Map();
|
|
78
|
+
for (const [projectId, one] of gathered) {
|
|
79
|
+
const made = one.outputs;
|
|
80
|
+
const ms = one.videoMs ?? one.audioMs;
|
|
81
|
+
facts.set(projectId, {
|
|
82
|
+
...(one.finishedAt === null ? {} : { finishedAt: one.finishedAt }),
|
|
83
|
+
...(ms === null || ms <= 0 ? {} : { durationSeconds: Math.round(ms / 1000) }),
|
|
84
|
+
...(made.video || made.shorts > 0 || made.pdf || made.audio
|
|
85
|
+
? { outputs: { ...made } }
|
|
86
|
+
: {}),
|
|
87
|
+
...(one.failed.length === 0 ? {} : { failedSteps: one.failed }),
|
|
88
|
+
...(outdated.has(projectId) ? { outdated: true } : {}),
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
for (const projectId of outdated)
|
|
92
|
+
if (!facts.has(projectId))
|
|
93
|
+
facts.set(projectId, { outdated: true });
|
|
94
|
+
return facts;
|
|
95
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { failureId, stageKinds, stageStates } from "../../kernel/pipeline.js";
|
|
3
|
+
import { notTemplateSample } from "../template-studio/repo.js";
|
|
3
4
|
import { admittedInItsState, parkedOnReview } from "./admitted-work.js";
|
|
4
5
|
import { formats, stageSources } from "./model.js";
|
|
5
6
|
import { runConfigSchema } from "./schema.js";
|
|
@@ -20,6 +21,7 @@ const standingRow = z.object({
|
|
|
20
21
|
progress_current: z.number().nullable(),
|
|
21
22
|
progress_total: z.number().nullable(),
|
|
22
23
|
source: z.enum(stageSources),
|
|
24
|
+
retry_at: z.string().nullable(),
|
|
23
25
|
admitted: z.number(),
|
|
24
26
|
parked: z.number(),
|
|
25
27
|
});
|
|
@@ -78,18 +80,19 @@ export function projectExists(db, id) {
|
|
|
78
80
|
// Newest first.
|
|
79
81
|
export function listProjects(db) {
|
|
80
82
|
return db
|
|
81
|
-
.prepare(`${projectSelect} WHERE ${liveProject()} ORDER BY created_at DESC, id DESC`)
|
|
83
|
+
.prepare(`${projectSelect} WHERE ${liveProject()} AND ${notTemplateSample()} ORDER BY created_at DESC, id DESC`)
|
|
82
84
|
.all()
|
|
83
85
|
.map((row) => toProject(projectRow.parse(row)));
|
|
84
86
|
}
|
|
85
|
-
// What 07 Projects needs of every project's stages and no more: the state each one is in
|
|
86
|
-
//
|
|
87
|
-
//
|
|
88
|
-
//
|
|
89
|
-
//
|
|
87
|
+
// What 07 Projects needs of every project's stages and no more: the state each one is in,
|
|
88
|
+
// how far through itself a running one is, and when one waiting to run again by itself tries
|
|
89
|
+
// (without it, `derive` reads that run as waiting its turn while its own page says Running).
|
|
90
|
+
// One statement for the whole list rather than `stagesOf` per row, and a few columns rather
|
|
91
|
+
// than the whole stage table, because the screen shows a status word and a meter and reads
|
|
92
|
+
// nothing else from a stage. One project's alone when `projectId` is given.
|
|
90
93
|
export function stageStandingsByProject(db, projectId) {
|
|
91
94
|
const grouped = new Map();
|
|
92
|
-
const select = `SELECT project_id, kind, state, progress_current, progress_total, source, ${admittedInItsState("stages")} AS admitted, ${parkedOnReview("stages")} AS parked FROM stages${projectId === undefined ? "" : " WHERE project_id=?"} ORDER BY rowid`;
|
|
95
|
+
const select = `SELECT project_id, kind, state, progress_current, progress_total, source, retry_at, ${admittedInItsState("stages")} AS admitted, ${parkedOnReview("stages")} AS parked FROM stages${projectId === undefined ? "" : " WHERE project_id=?"} ORDER BY rowid`;
|
|
93
96
|
const rows = projectId === undefined ? db.prepare(select).all() : db.prepare(select).all(projectId);
|
|
94
97
|
for (const row of rows) {
|
|
95
98
|
const parsed = standingRow.parse(row);
|
|
@@ -99,6 +102,7 @@ export function stageStandingsByProject(db, projectId) {
|
|
|
99
102
|
progressCurrent: parsed.progress_current,
|
|
100
103
|
progressTotal: parsed.progress_total,
|
|
101
104
|
source: parsed.source,
|
|
105
|
+
...(parsed.retry_at === null ? {} : { retryAt: parsed.retry_at }),
|
|
102
106
|
...(parsed.admitted === 1 ? { admitted: true } : {}),
|
|
103
107
|
...(parsed.parked === 1 ? { parked: true } : {}),
|
|
104
108
|
};
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { stageKinds } from "../../kernel/pipeline.js";
|
|
2
2
|
import { imageScaleProblem } from "../images/scale.js";
|
|
3
|
+
import { placedProblems } from "../keywords/rules.js";
|
|
3
4
|
import { loudnessFields } from "../loudness/model.js";
|
|
4
5
|
import { pauseFields } from "../narration/pauses-model.js";
|
|
5
6
|
import { reviewFields } from "../reviews/rules.js";
|
|
6
7
|
import { shortsSettingsProblems } from "../shorts/model.js";
|
|
8
|
+
import { usesPostPrompt } from "../social/rules.js";
|
|
7
9
|
import { ambientBedProblems, usesAmbientBed } from "../video/ambient-bed.js";
|
|
8
10
|
import { usesAnimation, videoEditProblems } from "../video/edit-settings.js";
|
|
9
11
|
import { usesVoices, voicesProblems } from "../voices/model.js";
|
|
@@ -75,6 +77,8 @@ export function admit(input) {
|
|
|
75
77
|
else if (draft.title.length > titleMax) {
|
|
76
78
|
fields.push({ field: "title", message: `Keep the title to ${titleMax} characters or fewer.` });
|
|
77
79
|
}
|
|
80
|
+
// Slopify fills its keywords from the title, so the title can't use them.
|
|
81
|
+
fields.push(...placedProblems([{ field: "title", place: "title", body: draft.title }], draft.values));
|
|
78
82
|
for (const kind of stageKinds) {
|
|
79
83
|
if (!allowedSources[kind].includes(sourceOf(sources, kind))) {
|
|
80
84
|
fields.push({
|
|
@@ -83,8 +87,8 @@ export function admit(input) {
|
|
|
83
87
|
});
|
|
84
88
|
}
|
|
85
89
|
}
|
|
86
|
-
if (needsLlmFor(draft) && !chosen(draft.llm)) {
|
|
87
|
-
fields.push({ field: "llm", message: "Choose a
|
|
90
|
+
if (needsLlmFor(draft, input.keywordUses) && !chosen(draft.llm)) {
|
|
91
|
+
fields.push({ field: "llm", message: "Choose a Service and a Model under Written by." });
|
|
88
92
|
}
|
|
89
93
|
if (sources.article === "generate" && blank(draft.articlePrompt)) {
|
|
90
94
|
fields.push({ field: "articlePrompt", message: "Pick an article prompt." });
|
|
@@ -94,7 +98,7 @@ export function admit(input) {
|
|
|
94
98
|
fields.push(...voicesFields(draft));
|
|
95
99
|
if (sources.audio === "generate") {
|
|
96
100
|
if (voiced === undefined || !chosen(voiced)) {
|
|
97
|
-
fields.push({ field: "audio", message: "Choose a
|
|
101
|
+
fields.push({ field: "audio", message: "Choose a Service and a Model under Read by." });
|
|
98
102
|
}
|
|
99
103
|
else if (voiced.voice.trim() === "") {
|
|
100
104
|
fields.push({ field: "audio.voice", message: "Choose a voice for the narration." });
|
|
@@ -109,7 +113,7 @@ export function admit(input) {
|
|
|
109
113
|
usesShorts(draft) ||
|
|
110
114
|
usesAnimation(draft)) &&
|
|
111
115
|
!chosen(draft.images)) {
|
|
112
|
-
fields.push({ field: "images", message: "Choose
|
|
116
|
+
fields.push({ field: "images", message: "Choose a Service and a Model under Images by." });
|
|
113
117
|
}
|
|
114
118
|
if ((sources.thumbnail === "from_prompt" || sources.thumbnail === "prompt_by_llm") &&
|
|
115
119
|
blank(draft.thumbnailPrompt)) {
|
|
@@ -118,7 +122,7 @@ export function admit(input) {
|
|
|
118
122
|
if (sources.audio === "off" && draft.subtitles !== undefined && draft.subtitles.mode !== "off") {
|
|
119
123
|
fields.push({
|
|
120
124
|
field: "subtitles.mode",
|
|
121
|
-
message: "
|
|
125
|
+
message: "Captions need narration. Turn narration on, or turn captions off.",
|
|
122
126
|
});
|
|
123
127
|
}
|
|
124
128
|
fields.push(...youtubeDescriptionFields(draft));
|
|
@@ -132,7 +136,7 @@ export function admit(input) {
|
|
|
132
136
|
fields.push(...reviewFields(draft));
|
|
133
137
|
if (usesReference(draft) && draft.reference?.source === "provide")
|
|
134
138
|
checkFile(input.staged, draft.provided.reference, "images", "provided.reference", "Upload the establishing image, or set Establishing image to Off in the Images section.", fields);
|
|
135
|
-
checkProvided(draft, input.staged, fields);
|
|
139
|
+
checkProvided(draft, input.staged, fields, input.keywordUses);
|
|
136
140
|
checkValues(draft, input.requiredSlots, fields);
|
|
137
141
|
if (!Number.isFinite(draft.silenceGapSeconds) ||
|
|
138
142
|
draft.silenceGapSeconds < 0 ||
|
|
@@ -219,7 +223,7 @@ function checkImagePrompts(draft, fields) {
|
|
|
219
223
|
if (scaleProblem !== undefined)
|
|
220
224
|
fields.push({ field: "imageScale", message: scaleProblem });
|
|
221
225
|
}
|
|
222
|
-
function checkProvided(draft, staged, fields) {
|
|
226
|
+
function checkProvided(draft, staged, fields, uses = {}) {
|
|
223
227
|
const { sources, provided } = draft;
|
|
224
228
|
if (sources.research === "provide" && blank(provided.research)) {
|
|
225
229
|
fields.push({
|
|
@@ -230,7 +234,7 @@ function checkProvided(draft, staged, fields) {
|
|
|
230
234
|
if (sources.article === "provide" && blank(provided.article)) {
|
|
231
235
|
fields.push({ field: "provided.article", message: "Paste the article." });
|
|
232
236
|
}
|
|
233
|
-
fields.push(...articleOffFields(draft));
|
|
237
|
+
fields.push(...articleOffFields(draft, uses));
|
|
234
238
|
if (sources.audio === "provide") {
|
|
235
239
|
checkFile(staged, provided.audio, "audio", "provided.audio", "Pick an audio file.", fields);
|
|
236
240
|
}
|
|
@@ -318,7 +322,7 @@ function checkValues(draft, requiredSlots, fields) {
|
|
|
318
322
|
function blank(value) {
|
|
319
323
|
return value === undefined || value.trim() === "";
|
|
320
324
|
}
|
|
321
|
-
export function llmUses(draft) {
|
|
325
|
+
export function llmUses(draft, keywords = {}) {
|
|
322
326
|
const sources = draft.sources;
|
|
323
327
|
const uses = [];
|
|
324
328
|
if (sources.research === "generate")
|
|
@@ -341,10 +345,16 @@ export function llmUses(draft) {
|
|
|
341
345
|
uses.push({ section: "outputs", label: "writing the YouTube description" });
|
|
342
346
|
if (usesShorts(draft))
|
|
343
347
|
uses.push({ section: "outputs", label: "picking the shorts" });
|
|
348
|
+
if (usesPostPrompt(draft))
|
|
349
|
+
uses.push({ section: "outputs", label: "writing the posts for other sites" });
|
|
350
|
+
if (keywords.scenes !== undefined)
|
|
351
|
+
uses.push({ section: "outputs", label: "writing image scenes" });
|
|
352
|
+
if (keywords.digest !== undefined)
|
|
353
|
+
uses.push({ section: "outputs", label: "writing the keyword digest" });
|
|
344
354
|
return uses;
|
|
345
355
|
}
|
|
346
|
-
export function needsLlmFor(draft) {
|
|
347
|
-
return llmUses(draft).length > 0;
|
|
356
|
+
export function needsLlmFor(draft, keywords = {}) {
|
|
357
|
+
return llmUses(draft, keywords).length > 0;
|
|
348
358
|
}
|
|
349
359
|
export function usesNarrationPreparation(draft) {
|
|
350
360
|
return draft.sources.audio === "generate" && !blank(draft.narrationPrompt);
|
|
@@ -371,7 +381,7 @@ export function voicesFields(draft) {
|
|
|
371
381
|
!draft.voices.speakers.some((speaker) => speaker.voice.provider === "inworld" && speaker.voice.model === "inworld-tts-2"))
|
|
372
382
|
fields.push({
|
|
373
383
|
field: "narrationPrompt",
|
|
374
|
-
message: "Narration preparation adds delivery cues only to speakers on Inworld's TTS-2 model, and no speaker uses it. Choose that model for a speaker under Speakers, or
|
|
384
|
+
message: "Narration preparation adds delivery cues only to speakers on Inworld's TTS-2 model, and no speaker uses it. Choose that model for a speaker under Speakers, or set Narration preparation to Off under Narration → More narration settings.",
|
|
375
385
|
});
|
|
376
386
|
return fields;
|
|
377
387
|
}
|
|
@@ -479,8 +489,8 @@ export function ambientBedFields(draft, staged) {
|
|
|
479
489
|
function chosen(choice) {
|
|
480
490
|
return choice !== undefined && choice.provider.trim() !== "" && choice.model.trim() !== "";
|
|
481
491
|
}
|
|
482
|
-
// The aliases a run narrates with: its copied
|
|
483
|
-
// on for generated audio, otherwise none. Any voice provider: an alias is plain text.
|
|
492
|
+
// The aliases a run narrates with: its copied Pronunciation list while Use your pronunciation
|
|
493
|
+
// list is on for generated audio, otherwise none. Any voice provider: an alias is plain text.
|
|
484
494
|
export function narrationAliasesOf(draft) {
|
|
485
495
|
return draft.sources.audio === "generate" && draft.audio?.useNarrationAliases === true
|
|
486
496
|
? (draft.narrationAliases ?? [])
|
|
@@ -506,7 +516,7 @@ export function usesPronunciationGlossary(draft) {
|
|
|
506
516
|
}
|
|
507
517
|
// Article Off: a project of images or a thumbnail from prompts, with no text at all. What reads
|
|
508
518
|
// the article can't be on with it.
|
|
509
|
-
export function articleOffFields(draft) {
|
|
519
|
+
export function articleOffFields(draft, keywords = {}) {
|
|
510
520
|
const { sources } = draft;
|
|
511
521
|
if (sources.article !== "off")
|
|
512
522
|
return [];
|
|
@@ -569,5 +579,30 @@ export function articleOffFields(draft) {
|
|
|
569
579
|
},
|
|
570
580
|
]
|
|
571
581
|
: []),
|
|
582
|
+
// The keywords Slopify writes from the article (`keywords/specs.ts`).
|
|
583
|
+
...(keywords.digest === undefined
|
|
584
|
+
? []
|
|
585
|
+
: [
|
|
586
|
+
{
|
|
587
|
+
field: keywords.digest,
|
|
588
|
+
message: `{{Slopify_Summary}}, {{Slopify_Hook}} and the other digest keywords are written from the article, and Article is Off. ${fix}, or remove them from this prompt.`,
|
|
589
|
+
},
|
|
590
|
+
]),
|
|
591
|
+
...(keywords.chapters === undefined
|
|
592
|
+
? []
|
|
593
|
+
: [
|
|
594
|
+
{
|
|
595
|
+
field: keywords.chapters,
|
|
596
|
+
message: `{{Slopify_Chapters}} lists the article's chapters, and Article is Off. ${fix}, or remove it from this prompt.`,
|
|
597
|
+
},
|
|
598
|
+
]),
|
|
599
|
+
...(keywords.scenes === undefined
|
|
600
|
+
? []
|
|
601
|
+
: [
|
|
602
|
+
{
|
|
603
|
+
field: keywords.scenes,
|
|
604
|
+
message: `{{Slopify_Scene}}, {{Slopify_Setting}} and {{Slopify_Mood}} are written from the article, and Article is Off. ${fix}, or remove them from this prompt.`,
|
|
605
|
+
},
|
|
606
|
+
]),
|
|
572
607
|
];
|
|
573
608
|
}
|
|
@@ -4,9 +4,11 @@ import { thinkingModes } from "../../kernel/ports/llm.js";
|
|
|
4
4
|
import { castSnapshotSchema } from "../channels/schema.js";
|
|
5
5
|
import { checkpointStageSchema } from "../checkpoints/schema.js";
|
|
6
6
|
import { documentSettingsSchema } from "../document/theme-schema.js";
|
|
7
|
+
import { keywordFactsSchema } from "../keywords/schema.js";
|
|
7
8
|
import { narrationAliasesSchema } from "../narration/aliases-schema.js";
|
|
8
9
|
import { chunkModes } from "../narration/chunk.js";
|
|
9
10
|
import { reviewModes, reviewStages } from "../reviews/model.js";
|
|
11
|
+
import { socialSettingsSchema } from "../social/schema.js";
|
|
10
12
|
import { subtitleConfigSchema } from "../subtitles/model.js";
|
|
11
13
|
import { ambientBedSchema } from "../video/ambient-bed-schema.js";
|
|
12
14
|
import { animateModes, atmospheres, colorGrades, cutModes, lookLevels, transitionKinds, } from "../video/edit-settings.js";
|
|
@@ -156,6 +158,7 @@ export const runDraftSchema = z.object({
|
|
|
156
158
|
.array(z.object({ title: z.string(), summary: z.string() }))
|
|
157
159
|
.readonly()
|
|
158
160
|
.optional(),
|
|
161
|
+
keywordFacts: keywordFactsSchema.optional(),
|
|
159
162
|
titleStyle: z
|
|
160
163
|
.object({
|
|
161
164
|
fontId: z
|
|
@@ -193,6 +196,11 @@ export const runDraftSchema = z.object({
|
|
|
193
196
|
levelSentences: z.boolean().optional(),
|
|
194
197
|
// Absent is English (`kernel/ports/languages.ts`).
|
|
195
198
|
language: languageSchema.optional(),
|
|
199
|
+
// Posting to other sites (`slices/social`); absent is posting nowhere.
|
|
200
|
+
social: socialSettingsSchema.optional(),
|
|
201
|
+
// A template studio sample (`slices/template-studio/scope.ts`): its steps make a short taste
|
|
202
|
+
// of the video, not all of it. Absent on every other project, whose steps it never changes.
|
|
203
|
+
sample: z.object({ fullScript: z.boolean() }).strict().optional(),
|
|
196
204
|
});
|
|
197
205
|
export const runConfigSchema = runDraftSchema.extend({
|
|
198
206
|
rendered: z.record(z.string(), z.string()),
|
|
@@ -16,6 +16,3 @@ export function finishStage(db, stageId, state, failureReason, at) {
|
|
|
16
16
|
export function resetStage(db, stageId) {
|
|
17
17
|
db.prepare("UPDATE stages SET state = 'pending', failure_reason = NULL, failure_kind = NULL, retry_at = NULL, attempt_count = 0, progress_current = NULL, progress_total = NULL, started_at = NULL, finished_at = NULL WHERE id = ?").run(stageId);
|
|
18
18
|
}
|
|
19
|
-
export function setStageProgress(db, stageId, current, total) {
|
|
20
|
-
db.prepare("UPDATE stages SET progress_current = ?, progress_total = ? WHERE id = ?").run(current, total, stageId);
|
|
21
|
-
}
|