@gentbajko/slopify 4.0.0 → 4.2.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 +1 -1
- package/dist/adapters/alignment/audio.js +1 -1
- package/dist/adapters/alignment/cache.js +1 -1
- package/dist/adapters/alignment/multilingual.js +2 -1
- package/dist/adapters/alignment/runner.js +1 -1
- package/dist/adapters/alignment/worker.js +1 -1
- package/dist/adapters/explain.js +10 -9
- package/dist/adapters/host-cli/index.js +2 -1
- package/dist/adapters/host-cli/transport.js +2 -1
- package/dist/adapters/image/bytes.js +2 -1
- package/dist/adapters/image/codex.js +6 -5
- package/dist/adapters/image/fal.js +4 -3
- package/dist/adapters/image/google.js +3 -2
- package/dist/adapters/image/models.js +2 -2
- package/dist/adapters/image/openai.js +2 -1
- package/dist/adapters/image/replicate.js +3 -2
- package/dist/adapters/image/video.js +2 -1
- package/dist/adapters/key-probes.js +1 -1
- package/dist/adapters/llm/antigravity-models.js +1 -1
- package/dist/adapters/llm/antigravity.js +7 -6
- package/dist/adapters/llm/assistant-cli.js +1 -1
- package/dist/adapters/llm/claude-code-models.js +1 -1
- package/dist/adapters/llm/claude-code.js +3 -2
- package/dist/adapters/llm/codex-models.js +1 -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 +2 -1
- package/dist/adapters/llm/run-cli.js +3 -2
- package/dist/adapters/tts/gemini.js +2 -1
- package/dist/adapters/tts/inworld-async.js +2 -1
- package/dist/adapters/tts/inworld.js +3 -2
- package/dist/adapters/tts/system.js +2 -1
- package/dist/catalog/registry.js +20 -13
- package/dist/catalog/schema.js +2 -1
- package/dist/catalog/validate.js +5 -2
- package/dist/edge/http/actions.js +7 -7
- package/dist/edge/http/app.js +5 -3
- package/dist/edge/http/assistant.js +3 -1
- package/dist/edge/http/backups.js +1 -1
- package/dist/edge/http/channel-memory.js +2 -2
- package/dist/edge/http/channels.js +1 -1
- package/dist/edge/http/checkpoints.js +7 -5
- package/dist/edge/http/design-templates.js +3 -3
- package/dist/edge/http/designs.js +1 -1
- package/dist/edge/http/document-themes.js +3 -3
- package/dist/edge/http/draft-problem.js +1 -1
- package/dist/edge/http/extension-auth.js +1 -1
- package/dist/edge/http/home.js +9 -1
- package/dist/edge/http/model-checks.js +4 -4
- package/dist/edge/http/onboarding.js +29 -12
- package/dist/edge/http/outputs.js +3 -2
- package/dist/edge/http/patch-notes.js +2 -2
- package/dist/edge/http/planning.js +1 -1
- package/dist/edge/http/project-create.js +1 -1
- package/dist/edge/http/project-templates.js +2 -2
- package/dist/edge/http/projects.js +22 -4
- package/dist/edge/http/prompts.js +2 -2
- package/dist/edge/http/pronunciation-check.js +133 -0
- package/dist/edge/http/pronunciations.js +26 -0
- package/dist/edge/http/providers.js +9 -10
- package/dist/edge/http/refusal.js +1 -1
- package/dist/edge/http/remote-access.js +4 -4
- package/dist/edge/http/remote-guard.js +2 -2
- package/dist/edge/http/reviews.js +1 -1
- package/dist/edge/http/revision-files.js +1 -1
- package/dist/edge/http/revisions.js +4 -4
- package/dist/edge/http/schedules.js +13 -11
- package/dist/edge/http/settings.js +6 -2
- package/dist/edge/http/social.js +5 -4
- package/dist/edge/http/staging.js +1 -1
- package/dist/edge/http/storage.js +12 -4
- package/dist/edge/http/studio.js +71 -19
- package/dist/edge/http/style-preview.js +2 -2
- package/dist/edge/http/template-studio.js +12 -9
- package/dist/edge/http/trash.js +1 -1
- package/dist/edge/http/youtube-edits.js +1 -1
- package/dist/edge/mcp/excluded-routes.js +4 -3
- package/dist/edge/mcp/instructions.js +3 -3
- package/dist/edge/mcp/library-tools.js +8 -5
- package/dist/edge/mcp/remake-tools.js +7 -4
- package/dist/edge/mcp/server.js +1 -1
- package/dist/edge/mcp/tools-channels.js +9 -9
- package/dist/edge/mcp/tools-designs.js +9 -9
- package/dist/edge/mcp/tools-library.js +31 -7
- package/dist/edge/mcp/tools-planning.js +18 -18
- package/dist/edge/mcp/tools-projects.js +10 -10
- package/dist/edge/mcp/tools-publishing.js +9 -9
- package/dist/edge/mcp/tools-runs.js +9 -9
- package/dist/edge/mcp/tools-schedules.js +6 -6
- package/dist/edge/mcp/tools-setup.js +20 -14
- package/dist/edge/mcp/tools-social.js +5 -4
- package/dist/edge/mcp/tools-storage.js +3 -3
- package/dist/edge/mcp/tools-template-studio.js +18 -18
- package/dist/edge/remote-access/model.js +1 -1
- package/dist/extension/slopify-studio-chrome.zip +0 -0
- package/dist/extension/slopify-studio-firefox.zip +0 -0
- package/dist/kernel/db/migrations/0078-uploaded-from-links.sql +7 -0
- package/dist/kernel/pipeline.js +12 -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 +11 -3
- package/dist/kernel/runner/providers.js +3 -2
- package/dist/kernel/runner/standalone.js +2 -2
- package/dist/main.js +5 -3
- package/dist/model-catalog.js +20 -0
- package/dist/patch-notes/4.0.0.md +13 -13
- package/dist/patch-notes/4.1.0.md +42 -0
- package/dist/patch-notes/4.2.0.md +28 -0
- package/dist/patch-notes/index.json +12 -0
- package/dist/slices/admission/listing-facts.js +95 -0
- package/dist/slices/admission/repo.js +9 -6
- package/dist/slices/admission/rules.js +7 -7
- package/dist/slices/admission/schema.js +2 -0
- package/dist/slices/admission/start.js +7 -0
- package/dist/slices/admission/state-words.js +34 -5
- package/dist/slices/assistant/cost.js +1 -1
- package/dist/slices/assistant/gate.js +1 -0
- package/dist/slices/assistant/model.js +10 -3
- package/dist/slices/assistant/turn.js +5 -3
- package/dist/slices/autopilot/warnings.js +1 -1
- package/dist/slices/backups/service.js +5 -5
- package/dist/slices/channels/cast-images.js +1 -1
- package/dist/slices/channels/schema.js +1 -1
- package/dist/slices/channels/videos.js +1 -1
- package/dist/slices/control/providers.js +2 -2
- package/dist/slices/designs/budget.js +1 -1
- package/dist/slices/designs/calls.js +2 -2
- package/dist/slices/designs/check-context.js +4 -4
- package/dist/slices/designs/fields.js +4 -4
- package/dist/slices/designs/gate.js +7 -5
- package/dist/slices/designs/render-input.js +1 -1
- package/dist/slices/designs/requests.js +1 -1
- package/dist/slices/designs/runner.js +1 -1
- package/dist/slices/designs/sample.js +2 -1
- package/dist/slices/designs/service.js +1 -1
- package/dist/slices/designs/template-checks.js +2 -2
- package/dist/slices/designs/template-make.js +3 -3
- package/dist/slices/designs/templates.js +3 -3
- package/dist/slices/document/fonts.js +1 -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 +2 -2
- package/dist/slices/estimate/index.js +28 -22
- package/dist/slices/estimate/requests.js +4 -4
- package/dist/slices/fixes/rules.js +3 -1
- package/dist/slices/fonts/catalog.js +2 -1
- package/dist/slices/fonts/coverage.js +2 -1
- package/dist/slices/images/appearance.js +2 -1
- package/dist/slices/images/scenes.js +2 -1
- package/dist/slices/keywords/digest.js +2 -1
- package/dist/slices/keywords/rules.js +2 -2
- package/dist/slices/keywords/specs.js +5 -5
- package/dist/slices/keywords/values.js +1 -1
- package/dist/slices/library/transfer.js +3 -3
- package/dist/slices/loudness/loudnorm.js +2 -1
- package/dist/slices/loudness/model.js +3 -2
- package/dist/slices/loudness/sentence-level.js +2 -1
- package/dist/slices/model-checks/rules.js +13 -0
- package/dist/slices/model-upkeep/model.js +1 -1
- package/dist/slices/model-upkeep/switch.js +3 -3
- package/dist/slices/model-upkeep/usage.js +13 -2
- package/dist/slices/narration/breaths.js +2 -1
- package/dist/slices/narration/clean-pieces.js +2 -1
- package/dist/slices/narration/pauses-model.js +3 -2
- package/dist/slices/narration/pronunciation-check.js +226 -0
- package/dist/slices/narration/pronunciation.js +7 -2
- package/dist/slices/narration/pronunciations-library.js +94 -0
- package/dist/slices/notifications/subject.js +2 -2
- package/dist/slices/onboarding/copy.js +19 -2
- package/dist/slices/onboarding/first-run.js +13 -38
- package/dist/slices/onboarding/install.js +2 -1
- package/dist/slices/onboarding/model.js +26 -21
- package/dist/slices/onboarding/preferred-model.js +14 -0
- package/dist/slices/onboarding/quick-short.js +103 -64
- package/dist/slices/onboarding/sample.js +4 -1
- package/dist/slices/onboarding/state.js +7 -0
- package/dist/slices/onboarding/template.js +6 -5
- package/dist/slices/outputs/add.js +3 -2
- package/dist/slices/outputs/service.js +2 -2
- package/dist/slices/patch-notes/library.js +1 -1
- package/dist/slices/play-drafts/readiness.js +3 -3
- package/dist/slices/play-drafts/review-inputs.js +1 -1
- package/dist/slices/play-drafts/service.js +17 -7
- 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/setup-sections.js +26 -0
- package/dist/slices/project-templates/setup.js +6 -1
- package/dist/slices/rebuild/preview-details.js +5 -5
- package/dist/slices/rebuild/recipe-preparation.js +1 -1
- package/dist/slices/rebuild/recipe-save.js +2 -2
- package/dist/slices/rebuild/recipe-text.js +16 -4
- package/dist/slices/rebuild/recipe-validation.js +5 -4
- package/dist/slices/rebuild/recipe-voices.js +3 -2
- package/dist/slices/rebuild/recipe-work.js +4 -4
- package/dist/slices/rebuild/recovery.js +6 -6
- package/dist/slices/rebuild/remake-outdated.js +5 -5
- package/dist/slices/rebuild/review-redo.js +1 -1
- package/dist/slices/rebuild/runtime-animate.js +2 -2
- package/dist/slices/rebuild/runtime-article.js +4 -3
- package/dist/slices/rebuild/runtime-document.js +5 -4
- package/dist/slices/rebuild/runtime-export-bed.js +2 -1
- package/dist/slices/rebuild/runtime-export-edit.js +2 -1
- package/dist/slices/rebuild/runtime-export-inputs.js +5 -4
- package/dist/slices/rebuild/runtime-export-short.js +1 -1
- package/dist/slices/rebuild/runtime-export.js +4 -3
- package/dist/slices/rebuild/runtime-image.js +4 -3
- package/dist/slices/rebuild/runtime-local.js +3 -2
- package/dist/slices/rebuild/runtime-narration-text.js +3 -2
- package/dist/slices/rebuild/runtime-provider.js +7 -6
- package/dist/slices/rebuild/runtime-review.js +6 -5
- package/dist/slices/rebuild/runtime-shorts.js +6 -5
- package/dist/slices/rebuild/runtime-store.js +17 -2
- package/dist/slices/rebuild/runtime-subtitles.js +13 -12
- package/dist/slices/rebuild/runtime-voices.js +2 -1
- package/dist/slices/rebuild/runtime-youtube.js +3 -2
- package/dist/slices/rebuild/service-readiness.js +11 -3
- package/dist/slices/research/synthesis.js +3 -2
- package/dist/slices/reviews/external-model.js +1 -1
- package/dist/slices/reviews/holds.js +5 -4
- package/dist/slices/reviews/model.js +8 -5
- package/dist/slices/reviews/rules.js +3 -3
- package/dist/slices/reviews/verdict.js +2 -1
- package/dist/slices/revisions/image-plan.js +1 -1
- package/dist/slices/revisions/mutation-assets.js +2 -1
- package/dist/slices/revisions/mutations.js +3 -2
- package/dist/slices/schedules/agenda.js +7 -5
- package/dist/slices/schedules/design-check.js +4 -4
- package/dist/slices/schedules/design-run.js +3 -3
- package/dist/slices/schedules/repo.js +6 -5
- package/dist/slices/schedules/schema.js +3 -0
- package/dist/slices/schedules/topics.js +5 -5
- package/dist/slices/settings/first-run.js +6 -32
- package/dist/slices/settings/health.js +30 -15
- package/dist/slices/settings/key-test.js +1 -1
- package/dist/slices/settings/model.js +4 -2
- package/dist/slices/settings/playback.js +2 -2
- package/dist/slices/shorts/keep.js +2 -1
- package/dist/slices/shorts/pick.js +4 -3
- package/dist/slices/shorts/prompts.js +2 -1
- package/dist/slices/shorts/render.js +3 -2
- package/dist/slices/social/media.js +5 -4
- package/dist/slices/social/pack.js +1 -1
- package/dist/slices/social/post-prompt.js +2 -1
- package/dist/slices/social/reshape.js +2 -2
- package/dist/slices/social/serve.js +1 -1
- package/dist/slices/social/service.js +3 -2
- package/dist/slices/social/state.js +1 -1
- package/dist/slices/storage/backup-import.js +2 -2
- package/dist/slices/storage/portable.js +1 -1
- package/dist/slices/storage/trim.js +23 -13
- package/dist/slices/studio/calendar.js +3 -1
- 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/plan.js +1 -1
- package/dist/slices/studio/settings.js +6 -6
- package/dist/slices/studio/videos.js +23 -4
- package/dist/slices/style-preview/render.js +3 -3
- package/dist/slices/style-preview/schema.js +1 -1
- package/dist/slices/subtitles/captions.js +1 -1
- package/dist/slices/template-studio/anatomy-view.js +46 -3
- package/dist/slices/template-studio/bakeoff.js +3 -3
- package/dist/slices/template-studio/budget.js +6 -3
- package/dist/slices/template-studio/cards.js +78 -0
- package/dist/slices/template-studio/checks.js +99 -50
- package/dist/slices/template-studio/for-all.js +5 -5
- package/dist/slices/template-studio/free-video.js +1 -1
- package/dist/slices/template-studio/free.js +5 -5
- package/dist/slices/template-studio/model.js +19 -15
- package/dist/slices/template-studio/pack-import.js +14 -14
- package/dist/slices/template-studio/pack.js +9 -7
- package/dist/slices/template-studio/paid.js +12 -5
- package/dist/slices/template-studio/quote.js +18 -11
- package/dist/slices/template-studio/ready.js +7 -7
- package/dist/slices/template-studio/runner.js +1 -1
- package/dist/slices/template-studio/save.js +12 -12
- package/dist/slices/template-studio/say-it-as.js +3 -3
- package/dist/slices/template-studio/schedule-gate.js +1 -1
- package/dist/slices/template-studio/schedule-price.js +3 -1
- package/dist/slices/template-studio/schedule-sample.js +5 -1
- package/dist/slices/template-studio/schema.js +25 -0
- package/dist/slices/template-studio/service.js +3 -1
- package/dist/slices/template-studio/status.js +26 -9
- package/dist/slices/template-studio/topic.js +3 -3
- package/dist/slices/thumbnail/by-llm.js +1 -1
- package/dist/slices/uploads/repo.js +37 -1
- package/dist/slices/uploads/rules.js +3 -2
- package/dist/slices/video/edit-list.js +2 -2
- package/dist/slices/video/edit-settings.js +1 -1
- package/dist/slices/video/encoding.js +14 -5
- package/dist/slices/video/ffmpeg.js +2 -2
- package/dist/slices/video/plan.js +2 -1
- package/dist/slices/video/slideshow.js +1 -1
- package/dist/slices/voices/attribution.js +3 -2
- package/dist/slices/voices/model.js +9 -8
- package/dist/slices/voices/script.js +2 -1
- package/dist/slices/youtube/answer.js +2 -1
- package/dist/slices/youtube/edits-repo.js +1 -1
- package/dist/tutorials/AI-CLIs.md +25 -25
- package/dist/tutorials/Agents-MCP.md +32 -32
- package/dist/tutorials/Assistant.md +5 -5
- 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 +40 -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 +95 -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 +101 -76
- package/dist/tutorials/Home.md +33 -33
- package/dist/tutorials/Install.md +13 -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 +21 -21
- package/dist/tutorials/Models.md +27 -27
- package/dist/tutorials/Multiple-Voices.md +41 -40
- package/dist/tutorials/Narration-Aliases-and-Glossary.md +101 -19
- package/dist/tutorials/Notifications.md +21 -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 +12 -12
- package/dist/tutorials/Project-Page.md +118 -120
- package/dist/tutorials/Prompts-and-Templates.md +84 -0
- package/dist/tutorials/Prompts.md +45 -45
- 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 +2 -2
- package/dist/tutorials/Reviews-and-Checkpoints.md +90 -93
- package/dist/tutorials/Schedules.md +27 -28
- package/dist/tutorials/Settings-Reference.md +183 -204
- 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 +45 -42
- package/dist/tutorials/Templates.md +50 -79
- 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 +15 -15
- package/dist/web/assets/index-BNftKQrA.css +1 -0
- package/dist/web/assets/index-CQASqwjT.js +460 -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 +2 -2
- package/dist/tutorials/Library-Overview.md +0 -76
- package/dist/tutorials/Play-Images.md +0 -165
- 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-CkAI_2E7.css +0 -1
- package/dist/web/assets/index-DcD0cdfo.js +0 -334
- package/dist/web/assets/pdf-TODRwF31.js +0 -54
- package/dist/web/assets/pdf.worker.min-Dswkl-cV.mjs +0 -29
- package/dist/web/assets/pdf.worker.min-zC6nfbxG.js +0 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { readinessIsUsable } from "../../kernel/ports/model.js";
|
|
3
|
+
import { costPhrase } from "../../slices/model-checks/rules.js";
|
|
3
4
|
import { quoteBody } from "../http/auditions.js";
|
|
4
5
|
import { checkBody } from "../http/model-checks.js";
|
|
5
6
|
import { switchBody } from "../http/providers.js";
|
|
@@ -56,7 +57,7 @@ const settings = [
|
|
|
56
57
|
name: "get_remote_access",
|
|
57
58
|
route: "GET /api/settings/remote-access",
|
|
58
59
|
title: "Read remote access",
|
|
59
|
-
description: "Settings →
|
|
60
|
+
description: "Settings → Remote access: whether Slopify's page is open on the person's other devices through Tailscale serve (their tailnet only, never the public internet), its https address, and any problem with the exact fix. Turning it on or off is the person's; agents can't.",
|
|
60
61
|
},
|
|
61
62
|
{
|
|
62
63
|
name: "get_settings",
|
|
@@ -80,7 +81,7 @@ const settings = [
|
|
|
80
81
|
name: "get_default_channel_links",
|
|
81
82
|
route: "GET /api/settings/channel-links",
|
|
82
83
|
title: "Read the default channel links",
|
|
83
|
-
description: "Settings →
|
|
84
|
+
description: "Settings → YouTube Studio and posting: the links a description's {{Name}} placeholders fill from.",
|
|
84
85
|
},
|
|
85
86
|
{
|
|
86
87
|
name: "set_default_channel_links",
|
|
@@ -147,7 +148,7 @@ const settings = [
|
|
|
147
148
|
route: "POST /api/auditions/quote",
|
|
148
149
|
body: quoteBody,
|
|
149
150
|
title: "Price a voice sample",
|
|
150
|
-
description: "Try a sample's price, as
|
|
151
|
+
description: "Try a sample's price, as Create shows it before playing one. Body: {lines: [{speaker, provider, model, text}]}.",
|
|
151
152
|
unrecorded: true,
|
|
152
153
|
},
|
|
153
154
|
{
|
|
@@ -166,7 +167,7 @@ const settings = [
|
|
|
166
167
|
name: "get_studio_settings",
|
|
167
168
|
route: "GET /api/studio/settings",
|
|
168
169
|
title: "Read YouTube Studio settings",
|
|
169
|
-
description: "Settings → YouTube Studio: the playlists upload packs name, and whether the comment is posted.",
|
|
170
|
+
description: "Settings → YouTube Studio and posting: the playlists upload packs name, and whether the comment is posted.",
|
|
170
171
|
shape: withoutExtensionSecrets,
|
|
171
172
|
},
|
|
172
173
|
{
|
|
@@ -186,14 +187,14 @@ const providers = [
|
|
|
186
187
|
{
|
|
187
188
|
name: "list_providers",
|
|
188
189
|
route: "GET /api/providers",
|
|
189
|
-
title: "List
|
|
190
|
-
description: "Each
|
|
190
|
+
title: "List the services",
|
|
191
|
+
description: "Each service on Settings → Keys & services, as configured or missing.",
|
|
191
192
|
shape: configuredOrMissing,
|
|
192
193
|
},
|
|
193
194
|
{
|
|
194
195
|
name: "list_models",
|
|
195
196
|
route: "GET /api/providers/:id/models",
|
|
196
|
-
title: "List a
|
|
197
|
+
title: "List a service's models",
|
|
197
198
|
description: "The models Slopify offers for the provider, with prices where known, and each model's standing for the saved key or CLI under standings: works (a check or a run succeeded), listed (the key's own model list names it), known (only Slopify's model list does), no-access (the provider said it is not on the plan, with its sentence), and retiring with its replacement when one is due. Standings never stop a run: a model chosen anywhere keeps working as before.",
|
|
198
199
|
},
|
|
199
200
|
{
|
|
@@ -205,26 +206,31 @@ const providers = [
|
|
|
205
206
|
{
|
|
206
207
|
name: "estimate_model_checks",
|
|
207
208
|
route: "GET /api/providers/:id/models/check/estimate",
|
|
208
|
-
title: "Estimate checking a
|
|
209
|
+
title: "Estimate checking a service's models",
|
|
209
210
|
description: "What Check models in Settings → Models would check for this provider and what it costs at list price, before anything is sent. Query: models (optional, comma-separated ids).",
|
|
210
211
|
},
|
|
211
212
|
{
|
|
212
213
|
name: "check_models",
|
|
213
214
|
route: "POST /api/providers/:id/models/check",
|
|
214
215
|
body: checkBody,
|
|
215
|
-
title: "Check a
|
|
216
|
+
title: "Check a service's models",
|
|
216
217
|
description: "Settings → Models' Check models: sends each model the smallest request (one word, a spoken Hi, one small image) to learn whether it works for the saved key or CLI, in the background. A check that costs money is refused with its estimate until the body carries confirmedDollars of at least the estimate's totalDollars (read estimate_model_checks first). Body: {models?: [ids], confirmedDollars?: number}.",
|
|
217
218
|
confirm: "Each model checked is sent one small paid request at list price (a CLI's checks use its plan's allowance instead).",
|
|
218
219
|
confirmFrom: {
|
|
219
220
|
route: "/api/providers/:id/models/check/estimate",
|
|
220
221
|
text: (value) => {
|
|
221
222
|
const estimate = z
|
|
222
|
-
.object({
|
|
223
|
+
.object({
|
|
224
|
+
count: z.number(),
|
|
225
|
+
totalDollars: z.number(),
|
|
226
|
+
unpriced: z.number(),
|
|
227
|
+
planAccounts: z.array(z.string()),
|
|
228
|
+
})
|
|
223
229
|
.safeParse(value);
|
|
224
230
|
if (!estimate.success)
|
|
225
231
|
return undefined;
|
|
226
|
-
const { count,
|
|
227
|
-
return `Checks ${String(count)} model${count === 1 ? "" : "s"}, one small request each: ${
|
|
232
|
+
const { count, totalDollars, unpriced, planAccounts } = estimate.data;
|
|
233
|
+
return `Checks ${String(count)} model${count === 1 ? "" : "s"}, one small request each: ${costPhrase(totalDollars, unpriced)}${planAccounts.length > 0 ? ", using the CLI plan's allowance" : ""}.`;
|
|
228
234
|
},
|
|
229
235
|
},
|
|
230
236
|
reachesOut: "asks",
|
|
@@ -244,8 +250,8 @@ const providers = [
|
|
|
244
250
|
{
|
|
245
251
|
name: "check_providers",
|
|
246
252
|
route: "POST /api/providers/health",
|
|
247
|
-
title: "Check
|
|
248
|
-
description: "Settings →
|
|
253
|
+
title: "Check every service",
|
|
254
|
+
description: "Settings → Keys & services' Check every service: which services answer and which CLIs are signed in.",
|
|
249
255
|
unrecorded: true,
|
|
250
256
|
reachesOut: "asks",
|
|
251
257
|
},
|
|
@@ -1,18 +1,19 @@
|
|
|
1
|
+
import { setupSectionNames } from "../../slices/project-templates/setup-sections.js";
|
|
1
2
|
import { choiceBody, linkBody, redditBody, textBody } from "../../slices/social/schema.js";
|
|
2
|
-
// A project's posts to X, LinkedIn, Instagram, TikTok, Reddit and Bluesky, as
|
|
3
|
-
// shows them. Agents prepare them; Fill in <site> and posting are the person's.
|
|
3
|
+
// A project's posts to X, LinkedIn, Instagram, TikTok, Reddit and Bluesky, as Copy for YouTube
|
|
4
|
+
// Studio shows them. Agents prepare them; Fill in <site> and posting are the person's.
|
|
4
5
|
export const socialTools = [
|
|
5
6
|
{
|
|
6
7
|
name: "get_post_packs",
|
|
7
8
|
route: "GET /api/social/packs/:projectId",
|
|
8
9
|
title: "Read the posts for other sites",
|
|
9
|
-
description: "
|
|
10
|
+
description: "Copy for YouTube Studio's posts: for each site the project posts to, the text as it goes in (with its count and limit), hashtags, link, media, AI label, when it goes out, warnings and where the post stands. The agent's work ends here: filling a site's form and posting are the person's.",
|
|
10
11
|
},
|
|
11
12
|
{
|
|
12
13
|
name: "set_post_choice",
|
|
13
14
|
route: "PUT /api/social/packs/:projectId/:platform/choice",
|
|
14
15
|
title: "Change what a post carries",
|
|
15
|
-
description:
|
|
16
|
+
description: `The project's own settings for one site (platform: x, linkedin, instagram, tiktok, reddit or bluesky): its text source, media, hashtags and link; {off: true} to not post there; null to go back to the template's. A post prompt (text "prompt") is a paid step picked only in the template (Edit template → ${setupSectionNames.youtube}) or in Create, where Save shows its cost. Body: {choice}.`,
|
|
16
17
|
body: choiceBody,
|
|
17
18
|
},
|
|
18
19
|
{
|
|
@@ -63,13 +63,13 @@ const onboarding = [
|
|
|
63
63
|
name: "get_onboarding",
|
|
64
64
|
route: "GET /api/onboarding",
|
|
65
65
|
title: "Read the welcome state",
|
|
66
|
-
description: "Starter
|
|
66
|
+
description: "Starter templates and what the welcome offers.",
|
|
67
67
|
},
|
|
68
68
|
{
|
|
69
69
|
name: "install_starter_pack",
|
|
70
70
|
route: "POST /api/onboarding/packs/:id",
|
|
71
|
-
title: "Install a starter
|
|
72
|
-
description: "Adds a starter
|
|
71
|
+
title: "Install a starter template",
|
|
72
|
+
description: "Adds a starter template's prompts and templates.",
|
|
73
73
|
},
|
|
74
74
|
{
|
|
75
75
|
name: "make_quick_short",
|
|
@@ -5,33 +5,33 @@ import { markReadySchema } from "../../slices/template-studio/ready.js";
|
|
|
5
5
|
import { makeSampleSchema, saveStudioSchema } from "../../slices/template-studio/save.js";
|
|
6
6
|
import { sayItAsSchema } from "../../slices/template-studio/say-it-as.js";
|
|
7
7
|
import { fullScriptSchema, topicSchema } from "../../slices/template-studio/topic.js";
|
|
8
|
-
//
|
|
8
|
+
// Edit template (Templates → a template → Edit template). Not the YouTube Studio tools.
|
|
9
9
|
export const templateStudioTools = [
|
|
10
10
|
{
|
|
11
11
|
name: "get_template_studio",
|
|
12
12
|
route: "GET /api/template-studio/:id",
|
|
13
|
-
title: "Read a template
|
|
13
|
+
title: "Read a template in Edit template",
|
|
14
14
|
description: "The template's sections with each sample's state (current, making, waiting, needs-fix, stale, off, provided), the sample topic, and which version schedules run. Its checks are read with get_template_checks.",
|
|
15
15
|
},
|
|
16
16
|
{
|
|
17
17
|
name: "get_template_checks",
|
|
18
18
|
route: "GET /api/template-studio/:id/checks",
|
|
19
19
|
title: "Read a template's checks",
|
|
20
|
-
description: "The free checks the template's current version passes before
|
|
20
|
+
description: "The free checks the template's current version passes before Approve for schedules, each failing one with what is wrong and where it is fixed: keywords filled, providers set up, a voice that is one of yours (Settings → Voices), release times, a known monthly cost, someone to answer each pause.",
|
|
21
21
|
},
|
|
22
22
|
{
|
|
23
23
|
name: "mark_template_ready",
|
|
24
24
|
route: "POST /api/template-studio/:id/ready",
|
|
25
25
|
body: markReadySchema,
|
|
26
|
-
title: "
|
|
27
|
-
description: "
|
|
28
|
-
confirm: "Schedules run this version from their next run, and each version saved later waits until it is
|
|
26
|
+
title: "Approve a template for its schedules",
|
|
27
|
+
description: "Approves the template's newest version (pass it as version) for its schedules, so they run it from their next run on: Edit template's Approve for schedules. Refused, approving nothing, while a check fails or a section's sample isn't current, with each thing to fix (problems). A version already approved is answered again. Until a template's first approval its schedules run its newest version; from then on a schedule runs only a version approved for schedules, saved before Edit template, or carried over from one by Slopify, and each version saved later waits until it is approved.",
|
|
28
|
+
confirm: "Schedules run this version from their next run, and each version saved later waits until it is approved.",
|
|
29
29
|
},
|
|
30
30
|
{
|
|
31
31
|
name: "get_prompt_anatomy",
|
|
32
32
|
route: "GET /api/template-studio/:id/anatomy",
|
|
33
33
|
title: "Read a section's prompt anatomy",
|
|
34
|
-
description: "One of the prompts a template section sends (section: subject, script, voice, pictures, thumbnail, shorts, upload, reviews; item: the prompt's key from items), cut into segments: the person's own words (yours), their keywords' values (keyword), what Slopify fills itself (slopify) and what settings add (setting). Read from the prompt the sample sent when it was made from
|
|
34
|
+
description: "One of the prompts a template section sends (section: subject, script, voice, pictures, thumbnail, shorts, upload, reviews; item: the prompt's key from items), cut into segments: the person's own words (yours), their keywords' values (keyword), what Slopify fills itself (slopify) and what settings add (setting). Read from the prompt the sample sent when it was made from these settings.",
|
|
35
35
|
},
|
|
36
36
|
{
|
|
37
37
|
name: "quote_template_save",
|
|
@@ -44,7 +44,7 @@ export const templateStudioTools = [
|
|
|
44
44
|
name: "save_template_studio",
|
|
45
45
|
route: "POST /api/template-studio/:id/save",
|
|
46
46
|
body: saveStudioSchema,
|
|
47
|
-
title: "Save a template in
|
|
47
|
+
title: "Save a template in Edit template",
|
|
48
48
|
description: 'Saves the template document as its next version. With sample "make" it also makes the paid sample of what changed, which spends money: price it first with quote_template_save and pass that quote\'s high as acknowledgedHigh (and acknowledgedUnknown: true when the quote counts steps with no price). A higher price, an unaccepted unknown one or a sample past today\'s budget is refused with the new quote and nothing is saved. With sample "skip" only the free samples are made. Send the same mutationId to retry the very same Save.',
|
|
49
49
|
},
|
|
50
50
|
{
|
|
@@ -72,7 +72,7 @@ export const templateStudioTools = [
|
|
|
72
72
|
name: "get_sample_pronunciations",
|
|
73
73
|
route: "GET /api/template-studio/:id/pronunciations",
|
|
74
74
|
title: "Read the names a template's voice may say wrong",
|
|
75
|
-
description: "The names the template's sample script says that a voice may get wrong (its Pronunciation Glossary, and words
|
|
75
|
+
description: "The names the template's sample script says that a voice may get wrong (its Pronunciation Glossary, and words the Pronunciation list (Settings → Voices → Pronunciation) already changes), each with its IPA, the first line it is said in and the alias it has (spokenAs). aliasesOn says whether the template's voice uses the Pronunciation list.",
|
|
76
76
|
},
|
|
77
77
|
{
|
|
78
78
|
name: "quote_say_it_as",
|
|
@@ -86,20 +86,20 @@ export const templateStudioTools = [
|
|
|
86
86
|
route: "POST /api/template-studio/:id/say-it-as",
|
|
87
87
|
body: sayItAsSchema,
|
|
88
88
|
title: "Say a word another way",
|
|
89
|
-
description: "Writes a
|
|
89
|
+
description: "Writes a row of the Pronunciation list (Settings → Voices → Pronunciation) (written said as spoken, whole word, any case; it replaces one for the same word) and voices again only the template sample's lines that say it, which spends money: price it first with quote_say_it_as and pass its high as acknowledgedHigh. The alias applies to every project started after it. Refused, writing nothing, at a higher price, with unaccepted unknown prices, past today's budget, or when the template's voice doesn't use aliases.",
|
|
90
90
|
},
|
|
91
91
|
{
|
|
92
92
|
name: "get_template_studio_settings",
|
|
93
93
|
route: "GET /api/template-studio/settings",
|
|
94
|
-
title: "Read the template
|
|
95
|
-
description: "The most
|
|
94
|
+
title: "Read the template samples' budgets",
|
|
95
|
+
description: "The most Edit template's samples may spend in one day (dailyBudget, US dollars), whether they may run steps on a CLI plan (samplesUsePlans; off by default, such a sample waits; it applies to designed pieces' samples too), the most designed pieces' template samples may spend in one day (designDailyBudget, $1 by default), and what each spent today and has left (today, designToday).",
|
|
96
96
|
},
|
|
97
97
|
{
|
|
98
98
|
name: "update_template_studio_settings",
|
|
99
99
|
route: "PUT /api/template-studio/settings",
|
|
100
100
|
body: studioSettingsSchema,
|
|
101
|
-
title: "Change the template
|
|
102
|
-
description: "Sets any of: dailyBudget, the most
|
|
101
|
+
title: "Change the template samples' daily budgets",
|
|
102
|
+
description: "Sets any of: dailyBudget, the most Edit template's samples may spend in one day, in US dollars (0 to 1000); designDailyBudget, the same for designed pieces' template samples (0 to 1000); samplesUsePlans, whether either may run steps on a Claude Code or Codex plan, which the dollar budgets can't limit. A field left out keeps what it was. A sample that would go over its budget, or needs a plan while plans are off, waits.",
|
|
103
103
|
},
|
|
104
104
|
{
|
|
105
105
|
name: "quote_samples_for_all",
|
|
@@ -125,15 +125,15 @@ export const templateStudioTools = [
|
|
|
125
125
|
{
|
|
126
126
|
name: "import_template_pack",
|
|
127
127
|
route: "POST /api/template-studio/packs/import",
|
|
128
|
-
title: "Import a template
|
|
129
|
-
description: "Makes a new template from a template
|
|
128
|
+
title: "Import a template file",
|
|
129
|
+
description: "Makes a new template from a template file (the .zip Edit template's Export as a file (.zip) made, at most 30 MB): its prompts and intros join Prompts (a name taken by other text comes in as \"<name> (2)\" and the template names that one), its voice is used as it is, and it is not checked in Edit template yet: look its samples over and approve it for schedules (mark_template_ready). A file holding anything that looks like a key, a file a template file never has or a newer format is refused, writing nothing. Answers templateId, the name it got, how many prompts and intros it added and which were renamed, whether Settings → Voices has its voice (voiceKnown; when false, get_template_checks' voice check says what to do) and how many samples it brought.",
|
|
130
130
|
upload: "multipart",
|
|
131
131
|
},
|
|
132
132
|
{
|
|
133
133
|
name: "get_template_pack_samples",
|
|
134
134
|
route: "GET /api/template-studio/:id/pack-samples",
|
|
135
|
-
title: "List the samples a template's
|
|
136
|
-
description: "The samples an imported
|
|
135
|
+
title: "List the samples a template's file brought",
|
|
136
|
+
description: "The samples an imported template file came with (role: thumbnail, picture or narration; name; url), shown in Edit template until the template makes its own. Empty for a template that didn't come from a file.",
|
|
137
137
|
},
|
|
138
138
|
{
|
|
139
139
|
name: "quote_bakeoff",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// What Settings →
|
|
1
|
+
// What Settings → Remote access shows. The web client imports this file, so it stays
|
|
2
2
|
// free of Node imports.
|
|
3
3
|
export const remoteAccessStates = [
|
|
4
4
|
// The switch is off: Slopify answers only on this computer.
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
-- The long video on YouTube and the project's "uploaded" mark are one fact
|
|
2
|
+
-- (`slices/studio/videos.ts`): saving or confirming the long video's link marks the project
|
|
3
|
+
-- uploaded. A long video already on YouTube before that marks its project now, from when its
|
|
4
|
+
-- link was recorded; a mark made by hand keeps its own time.
|
|
5
|
+
INSERT INTO project_uploads (project_id, uploaded_at)
|
|
6
|
+
SELECT project_id, recorded_at FROM youtube_videos WHERE short = 0 AND upload_state = 'done'
|
|
7
|
+
ON CONFLICT(project_id) DO NOTHING;
|
package/dist/kernel/pipeline.js
CHANGED
|
@@ -19,6 +19,18 @@ export const stageKinds = [
|
|
|
19
19
|
"video",
|
|
20
20
|
"document",
|
|
21
21
|
];
|
|
22
|
+
// One name per stage, everywhere a stage is named, on screen (the web app reads it through
|
|
23
|
+
// `@/lib/stage-words`) and in the server's sentences. The pipeline calls the narration stage
|
|
24
|
+
// `audio` and the PDF stage `document`; a person never sees those words.
|
|
25
|
+
export const stageWords = {
|
|
26
|
+
research: "Research",
|
|
27
|
+
article: "Article",
|
|
28
|
+
audio: "Narration",
|
|
29
|
+
images: "Images",
|
|
30
|
+
thumbnail: "Thumbnail",
|
|
31
|
+
video: "Video",
|
|
32
|
+
document: "PDF",
|
|
33
|
+
};
|
|
22
34
|
export const stageStates = [
|
|
23
35
|
"pending",
|
|
24
36
|
"running",
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// Where a server sentence sends a person to change something: a project's Edit settings and its
|
|
2
|
+
// sections (the web app's project/revision-form.tsx), and Create's rows (play/setup-rows.ts).
|
|
3
|
+
// Named once here, so every refusal and failure says the same path, and a section that is
|
|
4
|
+
// renamed on screen is renamed in its sentences by changing one line. Browser-safe.
|
|
5
|
+
export const editSettings = {
|
|
6
|
+
open: "Edit settings",
|
|
7
|
+
title: "Edit settings → Title and keywords",
|
|
8
|
+
article: "Edit settings → Article",
|
|
9
|
+
// The one text model a project's AI writing uses: the article, its research, the narration's
|
|
10
|
+
// preparation, the image prompts, the description, the shorts' picks and the speaker split.
|
|
11
|
+
writer: "Edit settings → Article → Written by",
|
|
12
|
+
narration: "Edit settings → Narration",
|
|
13
|
+
images: "Edit settings → Images",
|
|
14
|
+
video: "Edit settings → Video and style",
|
|
15
|
+
look: "Edit settings → Video and style → Look",
|
|
16
|
+
sound: "Edit settings → Video and style → Sound polish",
|
|
17
|
+
captions: "Edit settings → Captions",
|
|
18
|
+
// The thumbnail, the YouTube description, the shorts and the PDF, together as in Create.
|
|
19
|
+
extras: "Edit settings → Extras",
|
|
20
|
+
shorts: "Edit settings → Extras → Shorts",
|
|
21
|
+
checks: "Edit settings → Pauses and checks",
|
|
22
|
+
channel: "Edit settings → Channel",
|
|
23
|
+
language: "Edit settings → Channel → Language",
|
|
24
|
+
};
|
|
25
|
+
export const createRows = {
|
|
26
|
+
article: "Create → Article",
|
|
27
|
+
narration: "Create → Narration",
|
|
28
|
+
images: "Create → Images",
|
|
29
|
+
video: "Create → Video and style",
|
|
30
|
+
extras: "Create → Extras",
|
|
31
|
+
};
|
|
@@ -30,7 +30,30 @@ const picoVoices = [
|
|
|
30
30
|
{ id: "fr-FR", name: "French", language: "fr-FR" },
|
|
31
31
|
{ id: "it-IT", name: "Italian", language: "it-IT" },
|
|
32
32
|
];
|
|
33
|
-
|
|
33
|
+
// OpenAI is named alone: the voices the starter templates set up are OpenAI voices, so its key
|
|
34
|
+
// narrates at once, while ElevenLabs, Cartesia and Inworld also need a voice saved first.
|
|
35
|
+
export const noSpeechFix = "or add an OpenAI key in Settings → Keys & services: its voices work at once and sound better.";
|
|
36
|
+
// How to get a speech program onto this computer from a terminal, for a screen that lists the
|
|
37
|
+
// commands apart from the sentence (the first-run checklist), or undefined where none is
|
|
38
|
+
// installed that way: macOS and Windows have their own, which only a broken setup lacks. The
|
|
39
|
+
// issue sentences below name the fix in words and leave the commands to this.
|
|
40
|
+
export function speechInstall(host) {
|
|
41
|
+
if (host.platform === "darwin" || host.platform === "win32")
|
|
42
|
+
return undefined;
|
|
43
|
+
return host.env.SLOPIFY_CONTAINER === "1"
|
|
44
|
+
? {
|
|
45
|
+
text: "Update Slopify's Docker image, which has one built in:",
|
|
46
|
+
commands: ["docker compose pull", "docker compose up -d"],
|
|
47
|
+
}
|
|
48
|
+
: {
|
|
49
|
+
text: "Install espeak-ng with one of these:",
|
|
50
|
+
commands: [
|
|
51
|
+
"sudo apt install espeak-ng",
|
|
52
|
+
"sudo pacman -S espeak-ng",
|
|
53
|
+
"sudo dnf install espeak-ng",
|
|
54
|
+
],
|
|
55
|
+
};
|
|
56
|
+
}
|
|
34
57
|
export async function detectSpeech(given, host) {
|
|
35
58
|
// A probe that throws (a host bridge that cannot run local programs) found nothing.
|
|
36
59
|
const probe = (binary, args, timeoutMs) => Promise.resolve()
|
|
@@ -84,8 +107,8 @@ export async function detectSpeech(given, host) {
|
|
|
84
107
|
return {
|
|
85
108
|
engines,
|
|
86
109
|
issue: host.env.SLOPIFY_CONTAINER === "1"
|
|
87
|
-
? `Slopify runs in Docker and this image has no speech program, so the system voice can't narrate. Update
|
|
88
|
-
: `No speech program was found on this computer, so the system voice can't narrate. Install
|
|
110
|
+
? `Slopify runs in Docker and this image has no speech program, so the system voice can't narrate. Update Slopify's Docker image, which has one built in, ${noSpeechFix}`
|
|
111
|
+
: `No speech program was found on this computer, so the system voice can't narrate. Install the free program eSpeak NG, ${noSpeechFix}`,
|
|
89
112
|
};
|
|
90
113
|
}
|
|
91
114
|
async function onPath(probe, binary) {
|
|
@@ -185,6 +208,11 @@ export function primaryLanguage(voice) {
|
|
|
185
208
|
// processes each time is wasted work for something that changes when a program is installed.
|
|
186
209
|
const cacheMs = 60_000;
|
|
187
210
|
const cached = new WeakMap();
|
|
211
|
+
// "Check again" after installing a speech program: the next look runs the programs again
|
|
212
|
+
// instead of answering from the last minute's.
|
|
213
|
+
export function forgetDetectedSpeech(probe) {
|
|
214
|
+
cached.delete(probe);
|
|
215
|
+
}
|
|
188
216
|
export function detectSpeechCached(probe, host) {
|
|
189
217
|
const now = performance.now();
|
|
190
218
|
const key = [
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { errorText } from "../errors.js";
|
|
2
2
|
import { redact } from "../log.js";
|
|
3
3
|
import { isProviderError, providerError } from "../ports/model.js";
|
|
4
|
+
import { editSettings } from "../ports/settings-places.js";
|
|
4
5
|
// The retry policy, in one place. A stage slice is handed the wrapped calls of
|
|
5
6
|
// `providers.ts` and never an adapter, so there is no way round it.
|
|
6
7
|
// Four attempts - the first plus 3 retries - waiting 2 s, 8 s, 30 s.
|
|
@@ -112,7 +113,7 @@ function classify(error, expired, opts, limit) {
|
|
|
112
113
|
kind: "timeout",
|
|
113
114
|
message: opts.streaming === true
|
|
114
115
|
? `The ${callee[opts.kind]} sent nothing for ${seconds} seconds, so Slopify stopped waiting. It may be overloaded: wait a few minutes, then use Try again.`
|
|
115
|
-
: `The ${callee[opts.kind]} did not answer within ${seconds} seconds. It may be overloaded: wait a few minutes, then use Try again, or choose another model in
|
|
116
|
+
: `The ${callee[opts.kind]} did not answer within ${seconds} seconds. It may be overloaded: wait a few minutes, then use Try again, or choose another model in ${modelPlace[opts.kind]}.`,
|
|
116
117
|
});
|
|
117
118
|
}
|
|
118
119
|
if (isProviderError(error)) {
|
|
@@ -142,10 +143,17 @@ function classify(error, expired, opts, limit) {
|
|
|
142
143
|
// What the user calls the other end of each kind of call.
|
|
143
144
|
const callee = {
|
|
144
145
|
llm: "AI model",
|
|
145
|
-
tts: "
|
|
146
|
-
image: "image
|
|
146
|
+
tts: "voice service",
|
|
147
|
+
image: "image service",
|
|
147
148
|
video: "image-to-video model",
|
|
148
149
|
};
|
|
150
|
+
// Where a project's settings choose the model of each kind of call.
|
|
151
|
+
const modelPlace = {
|
|
152
|
+
llm: editSettings.writer,
|
|
153
|
+
tts: editSettings.narration,
|
|
154
|
+
image: editSettings.images,
|
|
155
|
+
video: editSettings.look,
|
|
156
|
+
};
|
|
149
157
|
// Node's `fetch` rejects a request that never reached the server with this TypeError.
|
|
150
158
|
function unreachable(error) {
|
|
151
159
|
return error instanceof TypeError && error.message === "fetch failed";
|
|
@@ -2,6 +2,7 @@ import { randomUUID } from "node:crypto";
|
|
|
2
2
|
import { errorText } from "../errors.js";
|
|
3
3
|
import { isProviderError, providerError } from "../ports/model.js";
|
|
4
4
|
import { planAccountOf } from "../ports/plan-limits.js";
|
|
5
|
+
import { createRows, editSettings } from "../ports/settings-places.js";
|
|
5
6
|
import { attempt } from "./attempt.js";
|
|
6
7
|
import { observed } from "./model-access.js";
|
|
7
8
|
export function stageProviders(deps, context, pieceId) {
|
|
@@ -183,7 +184,7 @@ export function stageProviders(deps, context, pieceId) {
|
|
|
183
184
|
if (call.dialogue !== undefined && port.capabilities.dialogue !== true)
|
|
184
185
|
throw providerError({
|
|
185
186
|
kind: "unsupported",
|
|
186
|
-
message: `${call.provider} can't speak several voices in one request. Turn off
|
|
187
|
+
message: `${call.provider} can't speak several voices in one request. Turn off One request for consecutive turns under Speakers (${createRows.narration}, or ${editSettings.narration}), then Try again.`,
|
|
187
188
|
});
|
|
188
189
|
const spoken = await port.synthesize({
|
|
189
190
|
model: call.model,
|
|
@@ -303,7 +304,7 @@ export function stageProviders(deps, context, pieceId) {
|
|
|
303
304
|
if (animate === undefined)
|
|
304
305
|
return Promise.reject(providerError({
|
|
305
306
|
kind: "unsupported",
|
|
306
|
-
message: `${call.provider} can't turn images into video clips. Choose fal.ai or Replicate as the image
|
|
307
|
+
message: `${call.provider} can't turn images into video clips. Choose fal.ai or Replicate as the image service in ${editSettings.images}, or turn Animate images off in ${editSettings.look}.`,
|
|
307
308
|
}));
|
|
308
309
|
const started = deps.clock.now().getTime();
|
|
309
310
|
const animated = learn({ provider: call.provider, family: "image", model: call.model }, schedule(call.provider, () => attempt(ctx, (signal) => animate({
|
|
@@ -105,9 +105,9 @@ function standaloneError(error) {
|
|
|
105
105
|
if (!isProviderError(error))
|
|
106
106
|
return error;
|
|
107
107
|
const kept = error.message
|
|
108
|
-
.replace(/,? then use (?:Retry stage|Try again)(?:, or choose another model in
|
|
108
|
+
.replace(/,? then use (?:Retry stage|Try again)(?:, or choose another model in Edit settings[^.,;]*)?/g, "")
|
|
109
109
|
.split(/(?<=\.)\s+/)
|
|
110
|
-
.filter((sentence) => !/Retry stage|Try again|Edit
|
|
110
|
+
.filter((sentence) => !/Retry stage|Try again|Edit settings/.test(sentence))
|
|
111
111
|
.join(" ")
|
|
112
112
|
.trim();
|
|
113
113
|
if (kept === error.message || kept === "")
|
package/dist/main.js
CHANGED
|
@@ -45,7 +45,7 @@ import { stageProviders } from "./kernel/runner/providers.js";
|
|
|
45
45
|
import { createProviderQueue } from "./kernel/runner/queue.js";
|
|
46
46
|
import { standaloneImage, standaloneLlm } from "./kernel/runner/standalone.js";
|
|
47
47
|
import { readVersion } from "./kernel/version.js";
|
|
48
|
-
import { modelSources } from "./model-catalog.js";
|
|
48
|
+
import { keptModels, modelSources } from "./model-catalog.js";
|
|
49
49
|
import { cliWatcher, lookAtModels, wireModelChecks } from "./model-checks.js";
|
|
50
50
|
import { projectPaused, projectTrashed } from "./slices/admission/repo.js";
|
|
51
51
|
import { createBackupService } from "./slices/backups/service.js";
|
|
@@ -493,7 +493,9 @@ export async function boot(config, options = {}) {
|
|
|
493
493
|
uuid: randomUUID,
|
|
494
494
|
resolveFont: (fontId) => resolveFont(paths, fontId),
|
|
495
495
|
providers: rebuild.providers,
|
|
496
|
-
|
|
496
|
+
// Create checks the draft after every pause in typing; the model lists it checks against
|
|
497
|
+
// are read once a minute at most, not each time (`keptModels`).
|
|
498
|
+
modelsFor: keptModels(rebuild.modelsFor, 60_000),
|
|
497
499
|
emit: (event) => hub.emitGlobal(event),
|
|
498
500
|
recordStarted: (projectIds) => {
|
|
499
501
|
for (const _projectId of projectIds)
|
|
@@ -632,7 +634,7 @@ export async function boot(config, options = {}) {
|
|
|
632
634
|
version,
|
|
633
635
|
env: process.env,
|
|
634
636
|
});
|
|
635
|
-
// Settings →
|
|
637
|
+
// Settings → Remote access. It proxies to the port the server really got, read
|
|
636
638
|
// when it applies; nothing applies before the server listens.
|
|
637
639
|
const remoteAccess = createRemoteAccessService({
|
|
638
640
|
db,
|
package/dist/model-catalog.js
CHANGED
|
@@ -31,3 +31,23 @@ export function modelSources(registry) {
|
|
|
31
31
|
fallbackModelsFor: (provider) => Object.hasOwn(fallbacks, provider) ? (fallbacks[provider] ?? []) : [],
|
|
32
32
|
};
|
|
33
33
|
}
|
|
34
|
+
// A model list kept for a short while. Create checks a draft again after every pause in typing,
|
|
35
|
+
// and Claude Code lists its models by running its CLI (about a second each time), so the check
|
|
36
|
+
// and the start that follows read one list. A list that failed is asked for again.
|
|
37
|
+
export function keptModels(modelsFor, keepMs, now = Date.now) {
|
|
38
|
+
const kept = new Map();
|
|
39
|
+
return (provider, family) => {
|
|
40
|
+
const key = `${family}:${provider}`;
|
|
41
|
+
const at = now();
|
|
42
|
+
const held = kept.get(key);
|
|
43
|
+
if (held !== undefined && at - held.at < keepMs)
|
|
44
|
+
return held.models;
|
|
45
|
+
const models = modelsFor(provider, family);
|
|
46
|
+
kept.set(key, { at, models });
|
|
47
|
+
models.catch(() => {
|
|
48
|
+
if (kept.get(key)?.models === models)
|
|
49
|
+
kept.delete(key);
|
|
50
|
+
});
|
|
51
|
+
return models;
|
|
52
|
+
};
|
|
53
|
+
}
|
|
@@ -2,21 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
Released 18 October 2026.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Edit template
|
|
6
6
|
|
|
7
|
-
- **Set a template up once, with real samples.**
|
|
8
|
-
- Every paid Save shows its price on the button. A daily sample budget (Settings → Template
|
|
9
|
-
- **
|
|
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
|
|
11
|
-
- Create opens on template
|
|
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
12
|
|
|
13
13
|
## Posting to X, LinkedIn, Instagram, TikTok, Bluesky and Reddit
|
|
14
14
|
|
|
15
|
-
-
|
|
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
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
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
18
|
|
|
19
|
-
##
|
|
19
|
+
## Images and designed pieces
|
|
20
20
|
|
|
21
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
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.
|
|
@@ -28,15 +28,15 @@ Released 18 October 2026.
|
|
|
28
28
|
## Assistant, health and checks
|
|
29
29
|
|
|
30
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
|
-
- **
|
|
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
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
33
|
- **Promise check.** An optional cheap review before narration: does the opening deliver what the title and thumbnail promise.
|
|
34
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
35
|
|
|
36
|
-
## Remote access and
|
|
36
|
+
## Remote access and encoding
|
|
37
37
|
|
|
38
|
-
- **Open Slopify on your phone or laptop** through Tailscale (Settings →
|
|
39
|
-
- **
|
|
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
40
|
|
|
41
41
|
## Fixes
|
|
42
42
|
|
|
@@ -46,6 +46,6 @@ Released 18 October 2026.
|
|
|
46
46
|
|
|
47
47
|
## Upgrading from 3.25.9
|
|
48
48
|
|
|
49
|
-
- Your projects, templates and schedules carry over unchanged; existing projects are not remade. Every template version you had
|
|
49
|
+
- Your projects, templates and schedules carry over unchanged; existing projects are not remade. Every template version you had keeps running, as before.
|
|
50
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
51
|
- `/mcp` now answers only on this computer: connect agents to `http://127.0.0.1:<port>/mcp`, not through a proxy.
|