@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
|
@@ -6,27 +6,31 @@ import { createTemplateFromProject, templateFromProjectSchema, } from "../../sli
|
|
|
6
6
|
import { makeNextChapter, nextChapterSchema } from "../../slices/project-templates/next-chapter.js";
|
|
7
7
|
import { templateCreateSchema, templateDeleteSchema, templateInstantiateSchema, templateUpdateSchema, } from "../../slices/project-templates/schema.js";
|
|
8
8
|
import { createTemplate, deleteTemplate, instantiateTemplate, listTemplates, readTemplate, updateTemplate, } from "../../slices/project-templates/service.js";
|
|
9
|
-
import {
|
|
9
|
+
import { templateGate } from "../../slices/template-studio/schedule-gate.js";
|
|
10
|
+
import { onInvalid, problem } from "./problem.js";
|
|
11
|
+
import { refusal } from "./refusal.js";
|
|
10
12
|
const param = z.object({ id: z.uuid() });
|
|
13
|
+
// The JSON bodies; the id or project the path names is not part of them.
|
|
14
|
+
export const templateFromProjectBody = templateFromProjectSchema.unwrap().omit({ projectId: true });
|
|
15
|
+
export const nextChapterBody = nextChapterSchema.unwrap().omit({ projectId: true });
|
|
16
|
+
export const templateUpdateBody = templateUpdateSchema.unwrap().omit({ id: true });
|
|
17
|
+
export const templateDeleteBody = templateDeleteSchema.unwrap().omit({ id: true });
|
|
18
|
+
export const templateInstantiateBody = templateInstantiateSchema
|
|
19
|
+
.unwrap()
|
|
20
|
+
.omit({ templateId: true });
|
|
11
21
|
function refused(c, result) {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
:
|
|
15
|
-
? 409
|
|
16
|
-
: 400;
|
|
17
|
-
return problem(c, {
|
|
18
|
-
status,
|
|
19
|
-
title: titleOf(status),
|
|
22
|
+
return refusal(c, result.reason, {
|
|
23
|
+
statuses: { "not-found": 404, conflict: 409, "referenced-by-schedule": 409 },
|
|
24
|
+
otherwise: 400,
|
|
20
25
|
detail: result.reason === "referenced-by-schedule"
|
|
21
|
-
? "Some schedules still use this template. In
|
|
26
|
+
? "Some schedules still use this template. In Calendar → Schedules, cancel and delete them first; their run history is kept."
|
|
22
27
|
: result.reason === "missing-prompt"
|
|
23
28
|
? "A prompt or intro/outro entry this template uses was deleted. Choose another in the template, then save again."
|
|
24
29
|
: result.reason === "not-found"
|
|
25
|
-
? "This template no longer exists; it may have been deleted. Go to
|
|
30
|
+
? "This template no longer exists; it may have been deleted. Go to Templates to see your templates."
|
|
26
31
|
: result.reason === "conflict"
|
|
27
32
|
? "This template or its project changed while you were editing. Reload the page to see the latest, then make your change again."
|
|
28
33
|
: "Some template settings are not valid, for example an image you supplied yourself. Check the template's settings and try again.",
|
|
29
|
-
extensions: { reason: result.reason },
|
|
30
34
|
});
|
|
31
35
|
}
|
|
32
36
|
export function projectTemplateRoutes(deps) {
|
|
@@ -39,8 +43,17 @@ function routes(deps) {
|
|
|
39
43
|
return deps;
|
|
40
44
|
};
|
|
41
45
|
return (new Hono()
|
|
42
|
-
|
|
43
|
-
.
|
|
46
|
+
// Each with the version its schedules run (`template-studio/schedule-gate.ts`).
|
|
47
|
+
.get("/", (c) => {
|
|
48
|
+
const db = service().db;
|
|
49
|
+
return c.json({
|
|
50
|
+
templates: listTemplates(service()).map((template) => {
|
|
51
|
+
const gate = templateGate(db, template.id);
|
|
52
|
+
return gate === undefined ? template : { ...template, gate };
|
|
53
|
+
}),
|
|
54
|
+
});
|
|
55
|
+
})
|
|
56
|
+
.post("/from-project/:projectId", zValidator("param", templateFromProjectSchema.unwrap().pick({ projectId: true }), onInvalid), zValidator("json", templateFromProjectBody, onInvalid), (c) => {
|
|
44
57
|
const result = createTemplateFromProject(service(), {
|
|
45
58
|
...c.req.valid("json"),
|
|
46
59
|
projectId: c.req.valid("param").projectId,
|
|
@@ -48,7 +61,7 @@ function routes(deps) {
|
|
|
48
61
|
return result.ok ? c.json(result.value, 201) : refused(c, result);
|
|
49
62
|
})
|
|
50
63
|
// A finished audiobook chapter's "Make the next chapter": a new Play draft for the book.
|
|
51
|
-
.post("/next-chapter/:projectId", zValidator("param", nextChapterSchema.unwrap().pick({ projectId: true }), onInvalid), zValidator("json",
|
|
64
|
+
.post("/next-chapter/:projectId", zValidator("param", nextChapterSchema.unwrap().pick({ projectId: true }), onInvalid), zValidator("json", nextChapterBody, onInvalid), (c) => {
|
|
52
65
|
const result = makeNextChapter(service(), {
|
|
53
66
|
...c.req.valid("json"),
|
|
54
67
|
projectId: c.req.valid("param").projectId,
|
|
@@ -58,7 +71,6 @@ function routes(deps) {
|
|
|
58
71
|
const status = result.reason === "not-found" ? 404 : result.reason === "conflict" ? 409 : 400;
|
|
59
72
|
return problem(c, {
|
|
60
73
|
status,
|
|
61
|
-
title: titleOf(status),
|
|
62
74
|
detail: result.message,
|
|
63
75
|
extensions: { reason: result.reason },
|
|
64
76
|
});
|
|
@@ -71,21 +83,21 @@ function routes(deps) {
|
|
|
71
83
|
const result = readTemplate(service(), c.req.valid("param").id, c.req.valid("query").version);
|
|
72
84
|
return result.ok ? c.json(result.value) : refused(c, result);
|
|
73
85
|
})
|
|
74
|
-
.put("/:id", zValidator("param", param, onInvalid), zValidator("json",
|
|
86
|
+
.put("/:id", zValidator("param", param, onInvalid), zValidator("json", templateUpdateBody, onInvalid), (c) => {
|
|
75
87
|
const result = updateTemplate(service(), {
|
|
76
88
|
...c.req.valid("json"),
|
|
77
89
|
id: c.req.valid("param").id,
|
|
78
90
|
});
|
|
79
91
|
return result.ok ? c.json(result.value) : refused(c, result);
|
|
80
92
|
})
|
|
81
|
-
.delete("/:id", zValidator("param", param, onInvalid), zValidator("json",
|
|
93
|
+
.delete("/:id", zValidator("param", param, onInvalid), zValidator("json", templateDeleteBody, onInvalid), (c) => {
|
|
82
94
|
const result = deleteTemplate(service(), {
|
|
83
95
|
...c.req.valid("json"),
|
|
84
96
|
id: c.req.valid("param").id,
|
|
85
97
|
});
|
|
86
98
|
return result.ok ? c.json(result.value) : refused(c, result);
|
|
87
99
|
})
|
|
88
|
-
.post("/:id/instantiate", zValidator("param", param, onInvalid), zValidator("json",
|
|
100
|
+
.post("/:id/instantiate", zValidator("param", param, onInvalid), zValidator("json", templateInstantiateBody, onInvalid), (c) => {
|
|
89
101
|
const result = instantiateTemplate(service(), {
|
|
90
102
|
...c.req.valid("json"),
|
|
91
103
|
templateId: c.req.valid("param").id,
|
|
@@ -4,13 +4,15 @@ import { z } from "zod";
|
|
|
4
4
|
import { transact } from "../../kernel/db/tx.js";
|
|
5
5
|
import { derive, progressOf } from "../../kernel/runner/graph.js";
|
|
6
6
|
import { listProjectHeads } from "../../slices/admission/heads.js";
|
|
7
|
+
import { listingFacts } from "../../slices/admission/listing-facts.js";
|
|
7
8
|
import { projectById, projectTrashed, runDraftSchema, stageStandingsByProject, stagesOf, stepFailuresByProject, } from "../../slices/admission/repo.js";
|
|
8
|
-
import { readsByWaitBesideFailure, stepFailedWhileWaiting, } from "../../slices/admission/state-words.js";
|
|
9
|
+
import { readsByWaitBesideFailure, retryingAt, stepFailedWhileWaiting, } from "../../slices/admission/state-words.js";
|
|
9
10
|
import { lastStarter } from "../../slices/agents/repo.js";
|
|
10
11
|
import { defaultChannelId } from "../../slices/channels/model.js";
|
|
11
12
|
import { channelById, projectChannels, setProjectChannel } from "../../slices/channels/repo.js";
|
|
12
13
|
import { withProjectControl } from "../../slices/control/lock.js";
|
|
13
14
|
import { stagesWithEta } from "../../slices/eta/view.js";
|
|
15
|
+
import { sampleProjectIds } from "../../slices/onboarding/sample.js";
|
|
14
16
|
import { videoActivity } from "../../slices/rebuild/activity.js";
|
|
15
17
|
import { projectHolds } from "../../slices/reviews/holds.js";
|
|
16
18
|
import { adoptBaseline } from "../../slices/revisions/adopt.js";
|
|
@@ -18,17 +20,11 @@ import { currentRevisionId } from "../../slices/revisions/repo.js";
|
|
|
18
20
|
import { limitWaitsByProject, listingWait } from "../../slices/run-cost/panel.js";
|
|
19
21
|
import { outputsOf } from "../../slices/storage/repo.js";
|
|
20
22
|
import { trashProject } from "../../slices/trash/service.js";
|
|
21
|
-
import { setAsideProjects,
|
|
23
|
+
import { setAsideProjects, settledProjects, uploadedProjects } from "../../slices/uploads/repo.js";
|
|
22
24
|
import { settledStatus } from "../../slices/uploads/rules.js";
|
|
23
|
-
import {
|
|
25
|
+
import { idParam } from "./ids.js";
|
|
26
|
+
import { onInvalid, problem } from "./problem.js";
|
|
24
27
|
import { createProject } from "./project-create.js";
|
|
25
|
-
const idParam = z.object({
|
|
26
|
-
id: z
|
|
27
|
-
.string()
|
|
28
|
-
.min(1)
|
|
29
|
-
.max(64)
|
|
30
|
-
.regex(/^[0-9A-Za-z_-]+$/),
|
|
31
|
-
});
|
|
32
28
|
// The return type is inferred so Hono keeps the route types the SPA's client is
|
|
33
29
|
// generated from; see stagingRoutes.
|
|
34
30
|
export function projectRoutes(deps) {
|
|
@@ -41,7 +37,7 @@ export function projectRoutes(deps) {
|
|
|
41
37
|
};
|
|
42
38
|
const summarise = (project) => {
|
|
43
39
|
const stages = stagesOf(deps.db, project.id);
|
|
44
|
-
const status = settledStatus(derive(stages, project.paused),
|
|
40
|
+
const status = settledStatus(derive(stages, project.paused), settledProjects(deps.db, project.id).has(project.id));
|
|
45
41
|
return {
|
|
46
42
|
...project,
|
|
47
43
|
status,
|
|
@@ -54,7 +50,6 @@ export function projectRoutes(deps) {
|
|
|
54
50
|
if (!created.ok)
|
|
55
51
|
return problem(c, {
|
|
56
52
|
status: created.status,
|
|
57
|
-
title: titleOf(created.status),
|
|
58
53
|
detail: created.detail,
|
|
59
54
|
...(created.fields.length === 0 ? {} : { extensions: { fields: created.fields } }),
|
|
60
55
|
});
|
|
@@ -72,15 +67,20 @@ export function projectRoutes(deps) {
|
|
|
72
67
|
const channels = projectChannels(deps.db);
|
|
73
68
|
const uploads = uploadedProjects(deps.db);
|
|
74
69
|
const aside = setAsideProjects(deps.db);
|
|
75
|
-
const settled =
|
|
70
|
+
const settled = settledProjects(deps.db);
|
|
76
71
|
const holds = projectHolds(deps.db, { standings, settled });
|
|
77
72
|
const waits = limitWaitsByProject(deps.db);
|
|
78
73
|
const failures = stepFailuresByProject(deps.db);
|
|
74
|
+
const samples = new Set(Object.values(sampleProjectIds(deps.db)));
|
|
75
|
+
const facts = listingFacts(deps.db);
|
|
79
76
|
const projects = listProjectHeads(deps.db).map((project) => {
|
|
80
77
|
const stages = standings.get(project.id) ?? [];
|
|
81
78
|
const waiting = waits.get(project.id);
|
|
82
79
|
const holding = holds.holding.get(project.id);
|
|
83
80
|
const status = settledStatus(derive(stages, project.paused), settled.has(project.id));
|
|
81
|
+
const made = facts.get(project.id);
|
|
82
|
+
const finished = status === "done" || status === "partial";
|
|
83
|
+
const retry = status === "running" ? retryingAt(stages) : undefined;
|
|
84
84
|
return {
|
|
85
85
|
...project,
|
|
86
86
|
status,
|
|
@@ -96,7 +96,18 @@ export function projectRoutes(deps) {
|
|
|
96
96
|
? { stepFailures: failures.get(project.id) ?? [] }
|
|
97
97
|
: {}),
|
|
98
98
|
...(holding === undefined ? {} : { holding }),
|
|
99
|
+
...(retry === undefined ? {} : { retryAt: retry }),
|
|
99
100
|
...(waiting === undefined ? {} : { limitWaits: waiting.map(listingWait) }),
|
|
101
|
+
...(samples.has(project.id) ? { sample: true } : {}),
|
|
102
|
+
...(finished && made?.finishedAt !== undefined ? { finishedAt: made.finishedAt } : {}),
|
|
103
|
+
...(made?.durationSeconds === undefined
|
|
104
|
+
? {}
|
|
105
|
+
: { durationSeconds: made.durationSeconds }),
|
|
106
|
+
...(made?.outputs === undefined ? {} : { outputs: made.outputs }),
|
|
107
|
+
...(status === "partial" && made?.failedSteps !== undefined
|
|
108
|
+
? { failedSteps: made.failedSteps }
|
|
109
|
+
: {}),
|
|
110
|
+
...(made?.outdated === true ? { outdated: true } : {}),
|
|
100
111
|
};
|
|
101
112
|
});
|
|
102
113
|
return c.json({ projects });
|
|
@@ -106,7 +117,6 @@ export function projectRoutes(deps) {
|
|
|
106
117
|
if (project === undefined) {
|
|
107
118
|
return problem(c, {
|
|
108
119
|
status: 404,
|
|
109
|
-
title: titleOf(404),
|
|
110
120
|
detail: projectTrashed(deps.db, c.req.valid("param").id)
|
|
111
121
|
? "This project is in the trash. Restore it in Settings → Trash to open it again."
|
|
112
122
|
: "This project no longer exists. Go back to Projects to pick another.",
|
|
@@ -152,7 +162,6 @@ export function projectRoutes(deps) {
|
|
|
152
162
|
if (channelById(deps.db, channelId) === undefined)
|
|
153
163
|
return problem(c, {
|
|
154
164
|
status: 404,
|
|
155
|
-
title: titleOf(404),
|
|
156
165
|
detail: "That channel no longer exists. Reload the page and pick one from the list, or make it again in Channels.",
|
|
157
166
|
});
|
|
158
167
|
const live = new Set(listProjectHeads(deps.db).map((project) => project.id));
|
|
@@ -172,7 +181,6 @@ export function projectRoutes(deps) {
|
|
|
172
181
|
const status = result.reason === "running" ? 409 : 404;
|
|
173
182
|
return problem(c, {
|
|
174
183
|
status,
|
|
175
|
-
title: titleOf(status),
|
|
176
184
|
detail: result.reason === "running"
|
|
177
185
|
? "This project is still running. Use Cancel run on the project page first, then delete it."
|
|
178
186
|
: "This project no longer exists. Go back to Projects to pick another.",
|
|
@@ -8,14 +8,8 @@ import { formerNames } from "../../slices/library/rename.js";
|
|
|
8
8
|
import { listPrompts, promptById } from "../../slices/library/repo.js";
|
|
9
9
|
import { createPrompt, removePrompt, restorePrompt, updatePrompt, } from "../../slices/library/save.js";
|
|
10
10
|
import { usedBy } from "../../slices/library/used-by.js";
|
|
11
|
-
import {
|
|
12
|
-
|
|
13
|
-
id: z
|
|
14
|
-
.string()
|
|
15
|
-
.min(1)
|
|
16
|
-
.max(64)
|
|
17
|
-
.regex(/^[0-9A-Za-z_-]+$/),
|
|
18
|
-
});
|
|
11
|
+
import { idParam } from "./ids.js";
|
|
12
|
+
import { onInvalid, problem } from "./problem.js";
|
|
19
13
|
// History's Restore names the version by its number.
|
|
20
14
|
export const versionParam = idParam.extend({ version: z.coerce.number().int().positive() });
|
|
21
15
|
// Shape only. The rules - trimming, emptiness, length, the slot lint - are the slice's,
|
|
@@ -25,6 +19,8 @@ const promptBody = z.object({
|
|
|
25
19
|
name: z.string(),
|
|
26
20
|
body: z.string(),
|
|
27
21
|
});
|
|
22
|
+
// Duplicate names the prompt it copies, whose old keyword names the copy may keep.
|
|
23
|
+
const promptCreateBody = promptBody.extend({ copyOf: z.string().min(1).max(100).optional() });
|
|
28
24
|
// The return type is inferred so Hono keeps the route types the SPA's client is
|
|
29
25
|
// generated from; see stagingRoutes.
|
|
30
26
|
export function promptRoutes(deps) {
|
|
@@ -33,8 +29,9 @@ export function promptRoutes(deps) {
|
|
|
33
29
|
// Every kind in one list: 04 Prompts filters by tab, and Duplicate needs the body it
|
|
34
30
|
// is copying.
|
|
35
31
|
.get("/", (c) => c.json({ prompts: withPhotorealistic(deps.db, listPrompts(deps.db)) }))
|
|
36
|
-
.post("/", zValidator("json",
|
|
37
|
-
const
|
|
32
|
+
.post("/", zValidator("json", promptCreateBody, onInvalid), (c) => {
|
|
33
|
+
const { copyOf, ...draft } = c.req.valid("json");
|
|
34
|
+
const result = createPrompt(library, draft, copyOf);
|
|
38
35
|
return result.ok ? c.json(result.value, 201) : refused(c, result, "prompt");
|
|
39
36
|
})
|
|
40
37
|
.put("/:id", zValidator("param", idParam, onInvalid), zValidator("json", promptBody, onInvalid), (c) => {
|
|
@@ -50,8 +47,7 @@ export function promptRoutes(deps) {
|
|
|
50
47
|
? refused(c, { ok: false, reason: "not-found" }, "prompt")
|
|
51
48
|
: problem(c, {
|
|
52
49
|
status: 400,
|
|
53
|
-
|
|
54
|
-
detail: "Only an Image prompt can be marked photorealistic. Open the prompt from the Image tab in Library → Prompts.",
|
|
50
|
+
detail: "Only an Image prompt can be marked photorealistic. Open the prompt under Image in Prompts.",
|
|
55
51
|
});
|
|
56
52
|
})
|
|
57
53
|
// Every saved version, newest first (`slices/library/history.ts`).
|
|
@@ -87,7 +83,6 @@ export function refused(c, failure, noun) {
|
|
|
87
83
|
case "invalid":
|
|
88
84
|
return problem(c, {
|
|
89
85
|
status: 400,
|
|
90
|
-
title: titleOf(400),
|
|
91
86
|
detail: `This ${noun} cannot be saved yet. Fix the highlighted fields and try again.`,
|
|
92
87
|
extensions: { fields: failure.fields },
|
|
93
88
|
});
|
|
@@ -95,7 +90,6 @@ export function refused(c, failure, noun) {
|
|
|
95
90
|
case "duplicate-name":
|
|
96
91
|
return problem(c, {
|
|
97
92
|
status: 409,
|
|
98
|
-
title: titleOf(409),
|
|
99
93
|
detail: `Another ${noun} already has this name. Choose a different name.`,
|
|
100
94
|
extensions: {
|
|
101
95
|
fields: [
|
|
@@ -109,8 +103,7 @@ export function refused(c, failure, noun) {
|
|
|
109
103
|
case "not-found":
|
|
110
104
|
return problem(c, {
|
|
111
105
|
status: 404,
|
|
112
|
-
|
|
113
|
-
detail: `This ${noun} no longer exists; it may have been deleted. Go back to the Library to pick another.`,
|
|
106
|
+
detail: `This ${noun} no longer exists; it may have been deleted. Go back to Prompts to pick another.`,
|
|
114
107
|
});
|
|
115
108
|
}
|
|
116
109
|
}
|
|
@@ -4,7 +4,7 @@ import { z } from "zod";
|
|
|
4
4
|
import { aliasCountMax } from "../../kernel/ports/narration-aliases.js";
|
|
5
5
|
import { listNarrationAliases, saveNarrationAliases, } from "../../slices/narration/aliases-library.js";
|
|
6
6
|
import { collectSharedGlossary } from "../../slices/narration/shared-glossary.js";
|
|
7
|
-
import { onInvalid, problem
|
|
7
|
+
import { onInvalid, problem } from "./problem.js";
|
|
8
8
|
// The pronunciations of every project's glossary, merged, for Edit project to copy into a
|
|
9
9
|
// project that shares them. `except` leaves out the project being edited, whose own glossary
|
|
10
10
|
// already comes first. Library → Aliases lives here too: the other way to change how a word
|
|
@@ -28,7 +28,6 @@ export function pronunciationRoutes(deps) {
|
|
|
28
28
|
return c.json({ aliases: result.aliases });
|
|
29
29
|
return problem(c, {
|
|
30
30
|
status: 400,
|
|
31
|
-
title: titleOf(400),
|
|
32
31
|
detail: `These aliases can't be saved yet: ${result.fields.map((field) => field.message).join(" ")}`,
|
|
33
32
|
extensions: { fields: result.fields },
|
|
34
33
|
});
|
|
@@ -5,11 +5,11 @@ import { z } from "zod";
|
|
|
5
5
|
import { keyProbes } from "../../adapters/key-probes.js";
|
|
6
6
|
import { catalogueModelInfo } from "../../catalog/model-info.js";
|
|
7
7
|
import { videoModelsOf } from "../../catalog/schema.js";
|
|
8
|
-
import { defaultSpeechVoice, detectSpeechCached } from "../../kernel/ports/system-speech.js";
|
|
8
|
+
import { defaultSpeechVoice, detectSpeechCached, speechInstall, } from "../../kernel/ports/system-speech.js";
|
|
9
9
|
import { switchAllRetired, switchRetiredModel } from "../../slices/model-upkeep/switch.js";
|
|
10
10
|
import { retiredModelUsage, usageKinds, usageSlots } from "../../slices/model-upkeep/usage.js";
|
|
11
11
|
import { cliPathMaxLength, saveCliPath } from "../../slices/settings/cli-paths.js";
|
|
12
|
-
import {
|
|
12
|
+
import { firstRunStatus } from "../../slices/settings/first-run.js";
|
|
13
13
|
import { checkProviderHealth } from "../../slices/settings/health.js";
|
|
14
14
|
import { keyGuides } from "../../slices/settings/key-guides.js";
|
|
15
15
|
import { testProviderKey } from "../../slices/settings/key-test.js";
|
|
@@ -17,7 +17,7 @@ import { keyStatus, removeProviderKey, saveProviderKey } from "../../slices/sett
|
|
|
17
17
|
import { isUncataloguedProvider, providerById, providerIds } from "../../slices/settings/model.js";
|
|
18
18
|
import { createModelCatalog } from "../../slices/settings/models.js";
|
|
19
19
|
import { providerStatuses } from "../../slices/settings/readiness.js";
|
|
20
|
-
import { onInvalid, problem
|
|
20
|
+
import { onInvalid, problem } from "./problem.js";
|
|
21
21
|
const providerParam = z.object({ id: z.enum(providerIds) });
|
|
22
22
|
const healthQuery = z.object({ provider: z.enum(providerIds).optional() });
|
|
23
23
|
// ceiling: no format check is allowed on a key, so the only thing said about the value is
|
|
@@ -26,7 +26,7 @@ const healthQuery = z.object({ provider: z.enum(providerIds).optional() });
|
|
|
26
26
|
const pathBody = z.object({ path: z.string().max(cliPathMaxLength) });
|
|
27
27
|
const keyBody = z.object({ key: z.string().min(1).max(4096) });
|
|
28
28
|
const modelId = z.string().min(1).max(200);
|
|
29
|
-
const switchBody = z
|
|
29
|
+
export const switchBody = z
|
|
30
30
|
.object({
|
|
31
31
|
kind: z.enum(usageKinds),
|
|
32
32
|
id: z.string().min(1).max(64),
|
|
@@ -53,24 +53,29 @@ export function providerRoutes(deps) {
|
|
|
53
53
|
report: (provider) => deps.log.write("warn", "model-catalog", { detail: `Could not load models for ${provider}` }),
|
|
54
54
|
});
|
|
55
55
|
const upkeep = () => ({ ...deps, uuid: deps.drafts?.uuid ?? randomUUID });
|
|
56
|
+
// A picker opening reads the key's own model list again when it is due; never waited for.
|
|
57
|
+
const relist = (id) => {
|
|
58
|
+
if (deps.autoModelChecks !== true)
|
|
59
|
+
return;
|
|
60
|
+
void deps.modelListing?.refresh(id).catch((error) => {
|
|
61
|
+
deps.log.write("warn", "model-checks.listing", { detail: `${id}: ${String(error)}` });
|
|
62
|
+
});
|
|
63
|
+
};
|
|
64
|
+
const standingsOf = (id, models) => deps.modelChecks?.standings(id, models);
|
|
56
65
|
return (new Hono()
|
|
57
|
-
// The step lists Settings →
|
|
66
|
+
// The step lists Settings → Keys & services shows beside each key field.
|
|
58
67
|
.get("/key-guides", (c) => c.json({ guides: keyGuides }))
|
|
59
68
|
// What the first launch found, and the providers Play picks by default.
|
|
60
69
|
.get("/first-run", async (c) => {
|
|
61
70
|
c.header("Cache-Control", "no-store");
|
|
62
71
|
return c.json(await firstRunStatus({ db: deps.db, ...(deps.modelsFor === undefined ? {} : { modelsFor: deps.modelsFor }) }, await providerStatuses(readiness)));
|
|
63
|
-
})
|
|
64
|
-
.post("/first-run/dismiss", (c) => {
|
|
65
|
-
dismissFirstRun(deps.db);
|
|
66
|
-
return c.body(null, 204);
|
|
67
72
|
})
|
|
68
73
|
// "Check all": every CLI signed in, every key valid, every chosen model still offered and
|
|
69
74
|
// answering for the key. `?provider=codex` checks that one only (its row's Check again,
|
|
70
75
|
// or a sign-in fix-it's).
|
|
71
76
|
.post("/health", zValidator("query", healthQuery, onInvalid), async (c) => {
|
|
72
77
|
if (deps.fetch === undefined)
|
|
73
|
-
return problem(c, { status: 503,
|
|
78
|
+
return problem(c, { status: 503, detail: noFetch });
|
|
74
79
|
const catalogue = deps.catalogue;
|
|
75
80
|
return c.json(await checkProviderHealth({
|
|
76
81
|
...readiness,
|
|
@@ -87,7 +92,6 @@ export function providerRoutes(deps) {
|
|
|
87
92
|
if (!deps.catalogue?.sync)
|
|
88
93
|
return problem(c, {
|
|
89
94
|
status: 503,
|
|
90
|
-
title: titleOf(503),
|
|
91
95
|
detail: "The model list (models.yaml) is not loaded yet. Wait a moment and reload the page; if it stays like this, restart Slopify.",
|
|
92
96
|
});
|
|
93
97
|
await deps.catalogue.sync();
|
|
@@ -97,21 +101,23 @@ export function providerRoutes(deps) {
|
|
|
97
101
|
.get("/catalogue/retired", (c) => {
|
|
98
102
|
c.header("Cache-Control", "no-store");
|
|
99
103
|
return c.json({
|
|
100
|
-
usages: deps.catalogue === undefined
|
|
104
|
+
usages: deps.catalogue === undefined
|
|
105
|
+
? []
|
|
106
|
+
: retiredModelUsage(deps.db, deps.catalogue.read(), deps.catalogue.lifecycle?.()),
|
|
101
107
|
});
|
|
102
108
|
})
|
|
103
109
|
.post("/catalogue/retired/switch", zValidator("json", switchBody, onInvalid), async (c) => {
|
|
104
110
|
if (deps.catalogue === undefined)
|
|
105
|
-
return problem(c, { status: 503,
|
|
111
|
+
return problem(c, { status: 503, detail: noFetch });
|
|
106
112
|
const result = await switchRetiredModel(upkeep(), deps.catalogue.read(), c.req.valid("json"));
|
|
107
113
|
if (!result.ok)
|
|
108
|
-
return problem(c, { status: 409,
|
|
114
|
+
return problem(c, { status: 409, detail: result.message });
|
|
109
115
|
return c.json(result);
|
|
110
116
|
})
|
|
111
117
|
.post("/catalogue/retired/switch-all", async (c) => {
|
|
112
118
|
if (deps.catalogue === undefined)
|
|
113
|
-
return problem(c, { status: 503,
|
|
114
|
-
return c.json(await switchAllRetired(upkeep(), deps.catalogue.read()));
|
|
119
|
+
return problem(c, { status: 503, detail: noFetch });
|
|
120
|
+
return c.json(await switchAllRetired(upkeep(), deps.catalogue.read(), deps.catalogue.lifecycle?.()));
|
|
115
121
|
})
|
|
116
122
|
.get("/catalogue", (c) => c.json(deps.catalogue?.status() ?? {
|
|
117
123
|
warning: "The model list (models.yaml) is not loaded yet. Wait a moment and reload the page; if it stays like this, restart Slopify.",
|
|
@@ -120,7 +126,6 @@ export function providerRoutes(deps) {
|
|
|
120
126
|
if (!deps.catalogue)
|
|
121
127
|
return problem(c, {
|
|
122
128
|
status: 503,
|
|
123
|
-
title: titleOf(503),
|
|
124
129
|
detail: "The model list (models.yaml) is not loaded yet. Wait a moment and reload the page; if it stays like this, restart Slopify.",
|
|
125
130
|
});
|
|
126
131
|
try {
|
|
@@ -129,7 +134,6 @@ export function providerRoutes(deps) {
|
|
|
129
134
|
catch {
|
|
130
135
|
return problem(c, {
|
|
131
136
|
status: 502,
|
|
132
|
-
title: titleOf(502),
|
|
133
137
|
detail: "Slopify could not download the latest model list. Your current list is still in use; check your internet connection and try Refresh again.",
|
|
134
138
|
});
|
|
135
139
|
}
|
|
@@ -138,9 +142,11 @@ export function providerRoutes(deps) {
|
|
|
138
142
|
// What Settings draws its rails from and Play its dropdowns: every provider, with
|
|
139
143
|
// the one fact that decides whether it is selectable.
|
|
140
144
|
.get("/", async (c) => c.json({ providers: await providerStatuses(readiness) }))
|
|
141
|
-
// The system voice's speech programs and their voices, for Settings → Voices' picker
|
|
145
|
+
// The system voice's speech programs and their voices, for Settings → Voices' picker, and
|
|
146
|
+
// with none, how to install one from a terminal (the commands apart from the sentence).
|
|
142
147
|
.get("/system-voice/voices", async (c) => {
|
|
143
|
-
const
|
|
148
|
+
const host = deps.speechHost ?? process;
|
|
149
|
+
const found = await detectSpeechCached(deps.probe, host);
|
|
144
150
|
return c.json({
|
|
145
151
|
engines: found.engines.map((engine) => ({
|
|
146
152
|
id: engine.id,
|
|
@@ -149,36 +155,43 @@ export function providerRoutes(deps) {
|
|
|
149
155
|
defaultVoice: defaultSpeechVoice(engine)?.id ?? null,
|
|
150
156
|
})),
|
|
151
157
|
issue: found.issue ?? null,
|
|
158
|
+
install: found.engines.length === 0 ? (speechInstall(host) ?? null) : null,
|
|
152
159
|
});
|
|
153
160
|
})
|
|
154
161
|
.get("/:id/models", zValidator("param", providerParam, onInvalid), async (c) => {
|
|
155
162
|
const { id } = c.req.valid("param");
|
|
156
163
|
// Animate images lists the provider's image-to-video models, which only the catalogue
|
|
157
164
|
// names.
|
|
158
|
-
|
|
165
|
+
relist(id);
|
|
166
|
+
if (c.req.query("video") === "1") {
|
|
167
|
+
const videos = deps.catalogue === undefined ? [] : videoModelsOf(deps.catalogue.read(), id);
|
|
159
168
|
return c.json({
|
|
160
|
-
models:
|
|
169
|
+
models: videos,
|
|
161
170
|
allowsCustom: false,
|
|
171
|
+
standings: standingsOf(id, videos),
|
|
162
172
|
});
|
|
163
|
-
|
|
173
|
+
}
|
|
174
|
+
if (deps.catalogue && !isUncataloguedProvider(id)) {
|
|
175
|
+
const models = deps.catalogue
|
|
176
|
+
.models(id, providerById(id).family)
|
|
177
|
+
.map((m) => ({ ...m, ...catalogueModelInfo(m) }));
|
|
164
178
|
return c.json({
|
|
165
|
-
models
|
|
166
|
-
.models(id, providerById(id).family)
|
|
167
|
-
.map((m) => ({ ...m, ...catalogueModelInfo(m) })),
|
|
179
|
+
models,
|
|
168
180
|
allowsCustom: false,
|
|
169
181
|
notice: "Curated active models from models.yaml. Edit it locally or refresh in Settings.",
|
|
170
182
|
warning: deps.catalogue.status().warning ?? undefined,
|
|
183
|
+
standings: standingsOf(id, models),
|
|
171
184
|
});
|
|
185
|
+
}
|
|
172
186
|
const result = await catalog.get(id, providerById(id).family, c.req.query("refresh") === "1");
|
|
173
187
|
c.header("Cache-Control", "no-store");
|
|
174
|
-
return c.json(result);
|
|
188
|
+
return c.json({ ...result, standings: standingsOf(id, result.models) });
|
|
175
189
|
})
|
|
176
190
|
.put("/:id/path", zValidator("param", providerParam, onInvalid), zValidator("json", pathBody, onInvalid), async (c) => {
|
|
177
191
|
const result = await saveCliPath(readiness, c.req.valid("param").id, c.req.valid("json").path);
|
|
178
192
|
if (!result.ok)
|
|
179
193
|
return problem(c, {
|
|
180
194
|
status: 400,
|
|
181
|
-
title: titleOf(400),
|
|
182
195
|
detail: result.message,
|
|
183
196
|
extensions: { fields: [{ field: "path", message: result.message }] },
|
|
184
197
|
});
|
|
@@ -192,6 +205,11 @@ export function providerRoutes(deps) {
|
|
|
192
205
|
return refusal(c, id, result.reason);
|
|
193
206
|
}
|
|
194
207
|
catalog.invalidate(id);
|
|
208
|
+
// A new key: read its model list and check what is free to check, in the background.
|
|
209
|
+
if (deps.autoModelChecks === true)
|
|
210
|
+
void deps.modelChecks?.automatic("key-added", id).catch((error) => {
|
|
211
|
+
deps.log.write("warn", "model-checks", { detail: `${id}: ${String(error)}` });
|
|
212
|
+
});
|
|
195
213
|
// The response says a key is stored and shows the mask, never the value.
|
|
196
214
|
return c.json(keyStatus(keys, id));
|
|
197
215
|
})
|
|
@@ -203,14 +221,13 @@ export function providerRoutes(deps) {
|
|
|
203
221
|
if (providerById(id).auth !== "key")
|
|
204
222
|
return refusal(c, id, "cli-provider");
|
|
205
223
|
if (deps.fetch === undefined)
|
|
206
|
-
return problem(c, { status: 503,
|
|
224
|
+
return problem(c, { status: 503, detail: noFetch });
|
|
207
225
|
const raw = await c.req.json().catch(() => undefined);
|
|
208
226
|
const candidate = raw === undefined ? undefined : keyBody.safeParse(raw);
|
|
209
227
|
if (candidate !== undefined && !candidate.success)
|
|
210
228
|
return problem(c, {
|
|
211
229
|
status: 400,
|
|
212
|
-
|
|
213
|
-
detail: `The pasted ${providerById(id).displayName} key could not be tested: it is empty or longer than any key. Paste the whole key in Settings → Providers → ${providerById(id).displayName}, then choose Test again.`,
|
|
230
|
+
detail: `The pasted ${providerById(id).displayName} key could not be tested: it is empty or longer than any key. Paste the whole key in Settings → Keys & services → ${providerById(id).displayName}, then choose Test again.`,
|
|
214
231
|
});
|
|
215
232
|
return c.json(await testProviderKey({ db: deps.db, clock: deps.clock, fetch: deps.fetch, probes: keyProbes }, id, candidate?.data.key));
|
|
216
233
|
})
|
|
@@ -229,7 +246,6 @@ function refusal(c, id, reason) {
|
|
|
229
246
|
if (reason === "cli-provider") {
|
|
230
247
|
return problem(c, {
|
|
231
248
|
status: 400,
|
|
232
|
-
title: titleOf(400),
|
|
233
249
|
detail: providerById(id).auth === "local"
|
|
234
250
|
? `${name} is your computer's own speech, so it has no API key to save. It works as soon as a speech program is installed.`
|
|
235
251
|
: `${name} signs in through its own command-line tool, so it has no API key to save here. Sign in with that tool on your computer instead.`,
|
|
@@ -238,13 +254,11 @@ function refusal(c, id, reason) {
|
|
|
238
254
|
if (reason === "absent") {
|
|
239
255
|
return problem(c, {
|
|
240
256
|
status: 404,
|
|
241
|
-
title: titleOf(404),
|
|
242
257
|
detail: `There is no saved API key for ${name}, so there is nothing to remove.`,
|
|
243
258
|
});
|
|
244
259
|
}
|
|
245
260
|
return problem(c, {
|
|
246
261
|
status: 400,
|
|
247
|
-
title: titleOf(400),
|
|
248
262
|
detail: "This API key cannot be saved yet. Paste the key and try again.",
|
|
249
263
|
extensions: {
|
|
250
264
|
fields: [{ field: "key", message: "Paste the API key from your provider's account page." }],
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { problem } from "./problem.js";
|
|
2
|
+
export function refusal(c, reason, rules) {
|
|
3
|
+
return problem(c, {
|
|
4
|
+
status: rules.statuses[reason] ?? rules.otherwise,
|
|
5
|
+
detail: rules.detail,
|
|
6
|
+
extensions: { reason, ...rules.extensions },
|
|
7
|
+
});
|
|
8
|
+
}
|
|
9
|
+
export function revisionRequired(c) {
|
|
10
|
+
return problem(c, {
|
|
11
|
+
status: 409,
|
|
12
|
+
detail: "This change is now made in Edit settings: save it there, then use Choose what to make again (in the project's More menu).",
|
|
13
|
+
extensions: { reason: "revision-required" },
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
// A build without its bundled files says so in plain words; anything else is the app's error handler's.
|
|
17
|
+
export function bundleMissing(c, error, Missing) {
|
|
18
|
+
if (!(error instanceof Missing))
|
|
19
|
+
throw error;
|
|
20
|
+
return problem(c, { status: 500, detail: error.message });
|
|
21
|
+
}
|
|
22
|
+
export async function jsonBody(c) {
|
|
23
|
+
try {
|
|
24
|
+
return await c.req.json();
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return undefined;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { zValidator } from "@hono/zod-validator";
|
|
2
|
+
import { Hono } from "hono";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import { actorOf } from "./actor.js";
|
|
5
|
+
import { onInvalid, problem } from "./problem.js";
|
|
6
|
+
import { viaProxy } from "./same-page.js";
|
|
7
|
+
const body = z.object({
|
|
8
|
+
enabled: z.boolean(),
|
|
9
|
+
httpsPort: z.number().int().min(1).max(65535).optional(),
|
|
10
|
+
});
|
|
11
|
+
// Settings → Remote access: Slopify's page on the person's other devices through
|
|
12
|
+
// Tailscale serve. Reading it is open to agents (get_remote_access); turning it on or off is
|
|
13
|
+
// the person's alone, from this computer.
|
|
14
|
+
export function remoteAccessRoutes(service) {
|
|
15
|
+
const unavailable = "Remote access can't be set from this Slopify. Start it with npx @gentbajko/slopify and try Settings → Remote access again.";
|
|
16
|
+
return new Hono()
|
|
17
|
+
.get("/", async (c) => {
|
|
18
|
+
if (service === undefined)
|
|
19
|
+
return problem(c, { status: 404, detail: unavailable });
|
|
20
|
+
c.header("Cache-Control", "no-store");
|
|
21
|
+
const view = await service.view();
|
|
22
|
+
return c.json(viaProxy(c.req.raw.headers) ? { ...view, changeable: false } : view);
|
|
23
|
+
})
|
|
24
|
+
.put("/", zValidator("json", body, onInvalid), async (c) => {
|
|
25
|
+
if (service === undefined)
|
|
26
|
+
return problem(c, { status: 404, detail: unavailable });
|
|
27
|
+
if (actorOf(c) !== "person")
|
|
28
|
+
return problem(c, {
|
|
29
|
+
status: 403,
|
|
30
|
+
detail: "Remote access is the person's to turn on or off, in Settings → Remote access. Agents and the assistant can only read it (get_remote_access).",
|
|
31
|
+
});
|
|
32
|
+
if (viaProxy(c.req.raw.headers))
|
|
33
|
+
return problem(c, {
|
|
34
|
+
status: 403,
|
|
35
|
+
detail: "Remote access is turned on or off only on the computer Slopify runs on. Open Settings → Remote access there, at http://127.0.0.1 and Slopify's port.",
|
|
36
|
+
});
|
|
37
|
+
const { enabled, httpsPort } = c.req.valid("json");
|
|
38
|
+
return c.json(await service.set(enabled, httpsPort));
|
|
39
|
+
});
|
|
40
|
+
}
|