@gentbajko/slopify 3.25.8 → 4.0.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/cache.js +3 -5
- package/dist/adapters/alignment/ctc.js +1 -2
- package/dist/adapters/alignment/lock.js +4 -3
- package/dist/adapters/alignment/multilingual.js +0 -3
- package/dist/adapters/alignment/prefetch.js +2 -1
- package/dist/adapters/alignment/worker.js +2 -1
- package/dist/adapters/explain.js +0 -3
- package/dist/adapters/ffmpeg.js +19 -1
- package/dist/adapters/host-cli/index.js +19 -3
- package/dist/adapters/http-failure.js +53 -0
- package/dist/adapters/image/codex.js +36 -4
- package/dist/adapters/image/fal.js +17 -50
- package/dist/adapters/image/google.js +31 -55
- package/dist/adapters/image/openai.js +20 -47
- package/dist/adapters/image/reference.js +36 -0
- package/dist/adapters/image/replicate.js +18 -47
- package/dist/adapters/interest/search-interest.js +113 -0
- package/dist/adapters/key-probes.js +53 -2
- package/dist/adapters/llm/antigravity.js +4 -0
- 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 +51 -98
- package/dist/adapters/llm/claude-code.js +13 -2
- package/dist/adapters/llm/codex-limits.js +27 -68
- package/dist/adapters/llm/codex-server-models.js +61 -109
- package/dist/adapters/llm/codex.js +12 -1
- package/dist/adapters/llm/openrouter.js +10 -47
- package/dist/adapters/llm/run-cli.js +6 -22
- 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 +19 -40
- package/dist/adapters/tts/inworld-async.js +4 -1
- package/dist/adapters/tts/inworld.js +3 -0
- package/dist/adapters/tts/openai.js +20 -50
- 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 +3 -1
- package/dist/catalog/schema.js +2 -0
- package/dist/catalog/store.js +39 -0
- 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 +4 -25
- package/dist/edge/http/actor.js +5 -3
- package/dist/edge/http/app.js +85 -10
- package/dist/edge/http/assistant.js +127 -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 +1 -3
- package/dist/edge/http/channel-memory.js +7 -20
- package/dist/edge/http/channels.js +13 -26
- package/dist/edge/http/checkpoints.js +33 -17
- 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 +2 -11
- package/dist/edge/http/draft-files.js +1 -3
- package/dist/edge/http/draft-problem.js +4 -9
- 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 +38 -13
- 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 +1 -14
- package/dist/edge/http/open-folder.js +5 -10
- package/dist/edge/http/outputs.js +4 -12
- package/dist/edge/http/patch-notes.js +4 -10
- package/dist/edge/http/planning.js +2 -6
- package/dist/edge/http/problem.js +2 -4
- package/dist/edge/http/project-create.js +1 -0
- package/dist/edge/http/project-templates.js +29 -17
- package/dist/edge/http/projects.js +2 -12
- package/dist/edge/http/prompts.js +7 -14
- package/dist/edge/http/pronunciations.js +1 -2
- package/dist/edge/http/providers.js +39 -24
- 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 +11 -24
- package/dist/edge/http/revision-files.js +5 -10
- package/dist/edge/http/revisions.js +10 -15
- package/dist/edge/http/run-cost.js +1 -2
- package/dist/edge/http/same-page.js +80 -0
- package/dist/edge/http/schedules.js +59 -32
- package/dist/edge/http/settings.js +22 -13
- package/dist/edge/http/social.js +282 -0
- package/dist/edge/http/staging.js +2 -4
- package/dist/edge/http/storage-files.js +5 -7
- package/dist/edge/http/storage.js +23 -23
- package/dist/edge/http/studio.js +23 -50
- package/dist/edge/http/style-preview.js +1 -4
- package/dist/edge/http/subtitles.js +3 -17
- package/dist/edge/http/template-studio.js +433 -0
- package/dist/edge/http/trash.js +10 -11
- 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 +2 -3
- 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 +25 -0
- package/dist/edge/mcp/http.js +11 -2
- package/dist/edge/mcp/instructions.js +5 -3
- package/dist/edge/mcp/library-tools.js +1 -0
- package/dist/edge/mcp/route-tool.js +35 -15
- package/dist/edge/mcp/server.js +13 -8
- package/dist/edge/mcp/tools-channels.js +2 -0
- package/dist/edge/mcp/tools-designs.js +165 -0
- package/dist/edge/mcp/tools-library.js +14 -2
- package/dist/edge/mcp/tools-planning.js +23 -4
- package/dist/edge/mcp/tools-projects.js +28 -1
- package/dist/edge/mcp/tools-runs.js +14 -1
- package/dist/edge/mcp/tools-schedules.js +28 -4
- package/dist/edge/mcp/tools-setup.js +61 -3
- package/dist/edge/mcp/tools-social.js +46 -0
- package/dist/edge/mcp/tools-storage.js +8 -0
- 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/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/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/runner/attempt.js +3 -1
- 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 +15 -10
- package/dist/kernel/runner/standalone.js +9 -5
- package/dist/main.js +334 -19
- package/dist/model-checks.js +166 -0
- package/dist/patch-notes/3.25.9.md +5 -0
- package/dist/patch-notes/4.0.0.md +51 -0
- package/dist/patch-notes/index.json +12 -0
- package/dist/slices/admission/heads.js +2 -1
- package/dist/slices/admission/repo.js +2 -1
- package/dist/slices/admission/rules.js +43 -8
- 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/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 +79 -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 +342 -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 +4 -3
- package/dist/slices/channels/cast-images.js +2 -1
- 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 +6 -0
- package/dist/slices/channels/service.js +10 -0
- package/dist/slices/channels/videos.js +2 -14
- package/dist/slices/checkpoints/index.js +0 -1
- package/dist/slices/control/providers.js +0 -26
- 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 +128 -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 +222 -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/episodes/summarize.js +5 -1
- package/dist/slices/estimate/index.js +45 -7
- package/dist/slices/fonts/catalog.js +3 -2
- 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 +6 -15
- package/dist/slices/images/scenes.js +100 -27
- package/dist/slices/keywords/digest.js +84 -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 +2 -1
- package/dist/slices/library/used-by.js +25 -10
- package/dist/slices/loudness/loudnorm.js +51 -11
- 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 +112 -0
- package/dist/slices/model-checks/run.js +143 -0
- package/dist/slices/model-checks/service.js +198 -0
- package/dist/slices/model-upkeep/switch.js +70 -25
- package/dist/slices/model-upkeep/usage.js +26 -11
- package/dist/slices/narration/breaths.js +2 -1
- package/dist/slices/narration/clean-pieces.js +2 -1
- package/dist/slices/narration/concat.js +2 -1
- package/dist/slices/narration/peaks.js +3 -4
- package/dist/slices/narration/pronunciation-chunks.js +4 -3
- package/dist/slices/narration/pronunciation.js +3 -2
- 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 +2 -1
- package/dist/slices/onboarding/copy.js +2 -1
- package/dist/slices/onboarding/first-run.js +3 -2
- package/dist/slices/onboarding/full-video.js +3 -2
- package/dist/slices/onboarding/install.js +4 -3
- package/dist/slices/onboarding/model.js +0 -16
- package/dist/slices/onboarding/packs.js +22 -22
- package/dist/slices/onboarding/quick-short.js +2 -1
- package/dist/slices/onboarding/sample.js +0 -1
- package/dist/slices/onboarding/state.js +2 -11
- package/dist/slices/onboarding/template.js +2 -1
- package/dist/slices/patch-notes/library.js +3 -2
- package/dist/slices/play-drafts/convert.js +4 -0
- package/dist/slices/play-drafts/review-inputs.js +8 -2
- package/dist/slices/play-drafts/review.js +5 -4
- package/dist/slices/play-drafts/schema.js +4 -0
- package/dist/slices/project-templates/from-project.js +9 -2
- package/dist/slices/project-templates/repo.js +6 -1
- package/dist/slices/project-templates/setup.js +8 -0
- 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 +27 -9
- 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 +3 -3
- 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 +6 -3
- 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 +98 -28
- package/dist/slices/rebuild/recipe-visual.js +55 -16
- package/dist/slices/rebuild/recipe-work.js +15 -3
- package/dist/slices/rebuild/recipe-youtube.js +4 -3
- package/dist/slices/rebuild/recovery-selection.js +3 -1
- package/dist/slices/rebuild/recovery.js +3 -2
- package/dist/slices/rebuild/repo.js +4 -3
- package/dist/slices/rebuild/review-promise.js +25 -0
- package/dist/slices/rebuild/review-redo.js +2 -1
- 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 +9 -8
- package/dist/slices/rebuild/runtime-article.js +3 -2
- package/dist/slices/rebuild/runtime-checkpoints.js +5 -4
- package/dist/slices/rebuild/runtime-document.js +8 -11
- package/dist/slices/rebuild/runtime-export-bed.js +6 -11
- package/dist/slices/rebuild/runtime-export-edit.js +6 -15
- package/dist/slices/rebuild/runtime-export-inputs.js +7 -7
- package/dist/slices/rebuild/runtime-export-short.js +8 -4
- package/dist/slices/rebuild/runtime-export.js +34 -12
- package/dist/slices/rebuild/runtime-figure-card.js +2 -1
- package/dist/slices/rebuild/runtime-image.js +4 -9
- 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 +14 -20
- 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 +10 -15
- 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 +60 -19
- package/dist/slices/rebuild/runtime-publication.js +10 -9
- package/dist/slices/rebuild/runtime-review.js +33 -28
- package/dist/slices/rebuild/runtime-run.js +4 -1
- package/dist/slices/rebuild/runtime-shorts.js +34 -50
- package/dist/slices/rebuild/runtime-store.js +3 -8
- package/dist/slices/rebuild/runtime-subtitles.js +16 -14
- package/dist/slices/rebuild/runtime-voices.js +8 -15
- package/dist/slices/rebuild/runtime-youtube.js +11 -29
- 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/reviews/external-model.js +3 -0
- package/dist/slices/reviews/external-repo.js +2 -1
- package/dist/slices/reviews/external-rows.js +2 -3
- package/dist/slices/reviews/model.js +26 -8
- package/dist/slices/reviews/repo.js +2 -1
- package/dist/slices/reviews/rules.js +1 -0
- package/dist/slices/reviews/view.js +5 -2
- package/dist/slices/revisions/downloads.js +4 -5
- package/dist/slices/revisions/mutation-assets.js +7 -4
- package/dist/slices/revisions/mutation-cues.js +2 -5
- package/dist/slices/revisions/mutations.js +0 -1
- 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 +11 -2
- 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 +24 -16
- package/dist/slices/schedules/rescore.js +35 -0
- package/dist/slices/schedules/scheduler.js +13 -3
- package/dist/slices/schedules/schema.js +54 -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 +48 -36
- package/dist/slices/settings/cli-paths.js +4 -6
- package/dist/slices/settings/first-run.js +2 -11
- package/dist/slices/settings/model-reach.js +3 -17
- package/dist/slices/settings/model.js +10 -0
- package/dist/slices/settings/playback.js +33 -22
- 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/pick.js +2 -15
- package/dist/slices/shorts/prompts.js +2 -13
- package/dist/slices/shorts/render.js +3 -0
- 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 +131 -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 +55 -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 +128 -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 +20 -2
- 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 +16 -11
- 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 +10 -3
- package/dist/slices/studio/calendar.js +4 -1
- package/dist/slices/studio/pick.js +2 -11
- package/dist/slices/studio/plan.js +6 -15
- package/dist/slices/studio/queue.js +3 -14
- package/dist/slices/studio/releases.js +26 -0
- package/dist/slices/studio/settings.js +14 -51
- package/dist/slices/studio/videos.js +12 -0
- package/dist/slices/style-preview/render.js +34 -13
- package/dist/slices/style-preview/schema.js +13 -0
- package/dist/slices/style-preview/service.js +2 -1
- package/dist/slices/style-preview/settings.js +33 -5
- 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 +118 -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 +103 -0
- package/dist/slices/template-studio/checks.js +273 -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 +54 -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 +205 -0
- package/dist/slices/template-studio/paid-view.js +66 -0
- package/dist/slices/template-studio/paid.js +348 -0
- package/dist/slices/template-studio/quote.js +148 -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 +30 -0
- package/dist/slices/template-studio/schedule-sample.js +87 -0
- package/dist/slices/template-studio/schema.js +218 -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 +173 -0
- package/dist/slices/template-studio/status.js +174 -0
- package/dist/slices/template-studio/topic.js +223 -0
- 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/video/ass-text.js +17 -0
- package/dist/slices/video/audio-export.js +2 -64
- package/dist/slices/video/encoding.js +160 -0
- package/dist/slices/video/ffmpeg.js +23 -21
- package/dist/slices/video/figure-card.js +1 -15
- package/dist/slices/video/slideshow.js +43 -18
- package/dist/slices/voices/palette.js +0 -3
- package/dist/slices/youtube/answer.js +2 -15
- package/dist/slices/youtube/edits-repo.js +2 -11
- package/dist/tutorials/Agents-MCP.md +2 -1
- package/dist/tutorials/Assistant.md +42 -0
- package/dist/tutorials/Channels.md +2 -0
- package/dist/tutorials/Home-and-Projects.md +19 -0
- package/dist/tutorials/Install.md +1 -0
- package/dist/tutorials/Keywords-Slopify-Fills.md +87 -0
- package/dist/tutorials/Models.md +33 -1
- package/dist/tutorials/Notifications.md +6 -0
- package/dist/tutorials/Play-Images.md +4 -0
- package/dist/tutorials/Posting-to-Social-Sites.md +121 -0
- package/dist/tutorials/Prompts.md +10 -6
- package/dist/tutorials/Remote-Access.md +63 -0
- package/dist/tutorials/Reviews-and-Checkpoints.md +13 -2
- package/dist/tutorials/Schedules.md +21 -1
- package/dist/tutorials/Settings-Reference.md +50 -8
- package/dist/tutorials/Template-Studio.md +125 -0
- package/dist/tutorials/Templates.md +3 -0
- package/dist/tutorials/_Sidebar.md +5 -0
- package/dist/updater/work-in-progress.js +42 -12
- package/dist/web/assets/index-CkAI_2E7.css +1 -0
- package/dist/web/assets/index-DcD0cdfo.js +334 -0
- package/dist/web/assets/{pdf-T7MCwjIv.js → pdf-TODRwF31.js} +1 -1
- package/dist/web/index.html +2 -2
- package/package.json +5 -1
- 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/web/assets/index-BadsoORk.css +0 -1
- package/dist/web/assets/index-D8LqNsCl.js +0 -326
package/dist/edge/events/hub.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { errorText } from "../../kernel/errors.js";
|
|
1
2
|
import { createPreviewCache } from "./preview-cache.js";
|
|
2
3
|
export function createHub(deps) {
|
|
3
4
|
const previews = createPreviewCache();
|
|
@@ -20,7 +21,7 @@ export function createHub(deps) {
|
|
|
20
21
|
.writeSSE({ event: event.type, data: JSON.stringify(event), id: deps.ids.next() })
|
|
21
22
|
.catch((error) => {
|
|
22
23
|
subscriber.drop();
|
|
23
|
-
deps.log.write("warn", "sse.write", { detail: `${event.type}: ${
|
|
24
|
+
deps.log.write("warn", "sse.write", { detail: `${event.type}: ${errorText(error)}` });
|
|
24
25
|
});
|
|
25
26
|
};
|
|
26
27
|
const join = (set, stream, signal, prune) => {
|
|
@@ -80,7 +81,7 @@ export function createHub(deps) {
|
|
|
80
81
|
// What the AI models are writing right now, so a page opened mid-call shows it.
|
|
81
82
|
for (const event of previews.snapshotAll()) {
|
|
82
83
|
const shown = present(event);
|
|
83
|
-
if (shown !== undefined)
|
|
84
|
+
if (shown !== undefined && deps.quiet?.(shown.projectId) !== true)
|
|
84
85
|
send(subscriber, shown);
|
|
85
86
|
}
|
|
86
87
|
}
|
|
@@ -96,6 +97,8 @@ export function createHub(deps) {
|
|
|
96
97
|
return;
|
|
97
98
|
for (const subscriber of projects.get(projectId) ?? [])
|
|
98
99
|
send(subscriber, shown);
|
|
100
|
+
if (deps.quiet?.(projectId) === true)
|
|
101
|
+
return;
|
|
99
102
|
for (const subscriber of globals)
|
|
100
103
|
send(subscriber, shown);
|
|
101
104
|
},
|
|
@@ -120,6 +123,3 @@ export function observedHub(hub, observe) {
|
|
|
120
123
|
},
|
|
121
124
|
};
|
|
122
125
|
}
|
|
123
|
-
function messageOf(error) {
|
|
124
|
-
return error instanceof Error ? error.message : String(error);
|
|
125
|
-
}
|
|
@@ -17,21 +17,12 @@ import { currentRevisionId } from "../../slices/revisions/repo.js";
|
|
|
17
17
|
import { allowsCustomModel } from "../../slices/settings/models.js";
|
|
18
18
|
import { providerStatuses } from "../../slices/settings/readiness.js";
|
|
19
19
|
import { outputsOf } from "../../slices/storage/repo.js";
|
|
20
|
-
import {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
.string()
|
|
24
|
-
.min(1)
|
|
25
|
-
.max(64)
|
|
26
|
-
.regex(/^[0-9A-Za-z_-]+$/),
|
|
27
|
-
});
|
|
20
|
+
import { idParam, idString } from "./ids.js";
|
|
21
|
+
import { onInvalid, problem } from "./problem.js";
|
|
22
|
+
import { revisionRequired } from "./refusal.js";
|
|
28
23
|
const stageParam = idParam.extend({ kind: z.enum(stageKinds) });
|
|
29
24
|
const imageParam = idParam.extend({
|
|
30
|
-
outputId:
|
|
31
|
-
.string()
|
|
32
|
-
.min(1)
|
|
33
|
-
.max(64)
|
|
34
|
-
.regex(/^[0-9A-Za-z_-]+$/),
|
|
25
|
+
outputId: idString,
|
|
35
26
|
});
|
|
36
27
|
// The return type is inferred so Hono keeps the route types the SPA's client is
|
|
37
28
|
// generated from; see stagingRoutes.
|
|
@@ -109,7 +100,6 @@ export function actionRoutes(deps) {
|
|
|
109
100
|
};
|
|
110
101
|
return problem(c, {
|
|
111
102
|
status: codes[result.reason],
|
|
112
|
-
title: titleOf(codes[result.reason]),
|
|
113
103
|
detail: messages[result.reason],
|
|
114
104
|
extensions: {
|
|
115
105
|
reason: result.reason,
|
|
@@ -122,7 +112,6 @@ export function actionRoutes(deps) {
|
|
|
122
112
|
if (deps.rebuild === undefined)
|
|
123
113
|
return problem(c, {
|
|
124
114
|
status: 503,
|
|
125
|
-
title: titleOf(503),
|
|
126
115
|
detail: "Resume and retry are not ready yet because Slopify is still starting. Wait a moment, reload the page and try again.",
|
|
127
116
|
});
|
|
128
117
|
const result = recoveryResultSchema.parse(await recoverProject(deps.rebuild, id, { ...input, action }));
|
|
@@ -159,7 +148,6 @@ export function actionRoutes(deps) {
|
|
|
159
148
|
].join(" ");
|
|
160
149
|
return problem(c, {
|
|
161
150
|
status,
|
|
162
|
-
title: titleOf(status),
|
|
163
151
|
detail,
|
|
164
152
|
extensions: {
|
|
165
153
|
reason: result.reason,
|
|
@@ -222,7 +210,6 @@ export function actionRoutes(deps) {
|
|
|
222
210
|
if (keys.length === 0)
|
|
223
211
|
return problem(c, {
|
|
224
212
|
status: 409,
|
|
225
|
-
title: titleOf(409),
|
|
226
213
|
detail: "Nothing in this section was refused by a content filter, so there is no prompt to soften. Reload the page; if the section still shows an error, use Try again.",
|
|
227
214
|
extensions: { reason: "nothing-refused" },
|
|
228
215
|
});
|
|
@@ -243,11 +230,3 @@ export function actionRoutes(deps) {
|
|
|
243
230
|
.delete("/:id/images/:outputId", zValidator("param", imageParam, onInvalid), revisionRequired)
|
|
244
231
|
.post("/:id/images/:outputId/regenerate", zValidator("param", imageParam, onInvalid), revisionRequired));
|
|
245
232
|
}
|
|
246
|
-
function revisionRequired(c) {
|
|
247
|
-
return problem(c, {
|
|
248
|
-
status: 409,
|
|
249
|
-
title: titleOf(409),
|
|
250
|
-
detail: "This change is now made from the Edit tab. Choose Edit project, save your change, then use Choose what to remake (in the project's More menu).",
|
|
251
|
-
extensions: { reason: "revision-required" },
|
|
252
|
-
});
|
|
253
|
-
}
|
package/dist/edge/http/actor.js
CHANGED
|
@@ -2,9 +2,11 @@
|
|
|
2
2
|
// No network request can set them (the Node server passes its own `{ incoming, outgoing }`),
|
|
3
3
|
// which is how a route knows an agent asked, not the person.
|
|
4
4
|
export const agentBindings = { actor: "agent" };
|
|
5
|
+
// The in-app assistant's calls, through its own MCP endpoint (`/mcp/assistant`).
|
|
6
|
+
export const assistantBindings = { actor: "assistant" };
|
|
5
7
|
export function actorOf(c) {
|
|
6
8
|
const env = c.env;
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
9
|
+
if (typeof env !== "object" || env === null || !("actor" in env))
|
|
10
|
+
return "person";
|
|
11
|
+
return env.actor === "agent" || env.actor === "assistant" ? env.actor : "person";
|
|
10
12
|
}
|
package/dist/edge/http/app.js
CHANGED
|
@@ -4,9 +4,12 @@ import { Hono } from "hono";
|
|
|
4
4
|
import { streamSSE } from "hono/streaming";
|
|
5
5
|
import { mcpPath } from "../../slices/agents/model.js";
|
|
6
6
|
import { isSampleProject } from "../../slices/onboarding/sample.js";
|
|
7
|
+
import { sampleOwner } from "../../slices/template-studio/repo.js";
|
|
8
|
+
import { assistantMcpPath, assistantMcpRoutes, runAllowedCall } from "../mcp/assistant.js";
|
|
7
9
|
import { mcpRoutes } from "../mcp/http.js";
|
|
8
10
|
import { actionRoutes } from "./actions.js";
|
|
9
|
-
import { agentBindings } from "./actor.js";
|
|
11
|
+
import { agentBindings, assistantBindings } from "./actor.js";
|
|
12
|
+
import { assistantRoutes } from "./assistant.js";
|
|
10
13
|
import { audioPreviewRoutes } from "./audio-preview.js";
|
|
11
14
|
import { auditionRoutes } from "./auditions.js";
|
|
12
15
|
import { autostartRoutes } from "./autostart.js";
|
|
@@ -14,6 +17,8 @@ import { backupRoutes } from "./backups.js";
|
|
|
14
17
|
import { channelMemoryRoutes } from "./channel-memory.js";
|
|
15
18
|
import { channelRoutes } from "./channels.js";
|
|
16
19
|
import { checkpointRoutes } from "./checkpoints.js";
|
|
20
|
+
import { designTemplateRoutes } from "./design-templates.js";
|
|
21
|
+
import { designRoutes } from "./designs.js";
|
|
17
22
|
import { diagnosticsRoutes } from "./diagnostics.js";
|
|
18
23
|
import { documentThemeRoutes } from "./document-themes.js";
|
|
19
24
|
import { draftRoutes } from "./drafts.js";
|
|
@@ -22,24 +27,31 @@ import { externalReviewRoutes } from "./external-reviews.js";
|
|
|
22
27
|
import { fileRoutes } from "./files.js";
|
|
23
28
|
import { fontsRoutes } from "./fonts.js";
|
|
24
29
|
import { homeRoutes, uploadedRoutes } from "./home.js";
|
|
30
|
+
import { keywordRoutes } from "./keywords.js";
|
|
31
|
+
import { modelCheckRoutes, providerCheckRoutes } from "./model-checks.js";
|
|
25
32
|
import { narrationPeakRoutes } from "./narration-peaks.js";
|
|
26
33
|
import { onboardingRoutes } from "./onboarding.js";
|
|
27
34
|
import { openFolderRoutes } from "./open-folder.js";
|
|
28
35
|
import { outputRoutes } from "./outputs.js";
|
|
29
36
|
import { patchNotesRoutes } from "./patch-notes.js";
|
|
30
37
|
import { planningRoutes } from "./planning.js";
|
|
31
|
-
import { problem, problemFromError
|
|
38
|
+
import { problem, problemFromError } from "./problem.js";
|
|
32
39
|
import { projectTemplateRoutes } from "./project-templates.js";
|
|
33
40
|
import { projectRoutes } from "./projects.js";
|
|
34
41
|
import { promptRoutes } from "./prompts.js";
|
|
35
42
|
import { pronunciationRoutes } from "./pronunciations.js";
|
|
36
43
|
import { providerRoutes } from "./providers.js";
|
|
44
|
+
import { remoteAccessRoutes } from "./remote-access.js";
|
|
45
|
+
import { remoteGuard } from "./remote-guard.js";
|
|
46
|
+
import { requestGuard } from "./request-guard.js";
|
|
37
47
|
import { reviewRoutes } from "./reviews.js";
|
|
38
48
|
import { revisionFileRoutes, revisionFolderRoutes } from "./revision-files.js";
|
|
39
49
|
import { revisionRoutes } from "./revisions.js";
|
|
40
50
|
import { runCostRoutes } from "./run-cost.js";
|
|
51
|
+
import { viaFunnel } from "./same-page.js";
|
|
41
52
|
import { calendarRoutes, scheduleRoutes } from "./schedules.js";
|
|
42
53
|
import { settingsRoutes } from "./settings.js";
|
|
54
|
+
import { socialRoutes } from "./social.js";
|
|
43
55
|
import { stagingRoutes } from "./staging.js";
|
|
44
56
|
import { startRecorder } from "./starts.js";
|
|
45
57
|
import { storageRoutes } from "./storage.js";
|
|
@@ -48,6 +60,7 @@ import { studioRoutes } from "./studio.js";
|
|
|
48
60
|
import { stylePreviewRoutes } from "./style-preview.js";
|
|
49
61
|
import { subtitleRoutes } from "./subtitles.js";
|
|
50
62
|
import { telemetryRoutes } from "./telemetry.js";
|
|
63
|
+
import { templateStudioRoutes } from "./template-studio.js";
|
|
51
64
|
import { trashRoutes } from "./trash.js";
|
|
52
65
|
import { tutorialRoutes } from "./tutorial.js";
|
|
53
66
|
import { tutorialPagesRoutes } from "./tutorials.js";
|
|
@@ -57,7 +70,7 @@ import { whatsNewRoutes } from "./whats-new.js";
|
|
|
57
70
|
import { youtubeEditRoutes } from "./youtube-edits.js";
|
|
58
71
|
const notBuilt = "The Slopify UI is not built yet. The API is running: try /api/health.\n" +
|
|
59
72
|
"Build the SPA with `npm run build` at the repository root.\n";
|
|
60
|
-
function apiRoutes(deps, startedAt) {
|
|
73
|
+
function apiRoutes(deps, startedAt, runAllowed) {
|
|
61
74
|
return (new Hono()
|
|
62
75
|
.get("/health", (c) => c.json({
|
|
63
76
|
status: "ok",
|
|
@@ -72,9 +85,12 @@ function apiRoutes(deps, startedAt) {
|
|
|
72
85
|
.route("/drafts", draftRoutes(deps.drafts))
|
|
73
86
|
.route("/diagnostics", diagnosticsRoutes(deps))
|
|
74
87
|
.route("/project-templates", projectTemplateRoutes(deps.drafts))
|
|
88
|
+
.route("/template-studio", templateStudioRoutes(deps))
|
|
75
89
|
.route("/schedules", scheduleRoutes(deps.schedules))
|
|
76
90
|
.route("/channels", channelRoutes(deps))
|
|
77
91
|
.route("/channels", channelMemoryRoutes(deps))
|
|
92
|
+
.route("/designs", designRoutes(deps.designs))
|
|
93
|
+
.route("/design-templates", designTemplateRoutes(deps.designTemplates))
|
|
78
94
|
.route("/calendar", calendarRoutes(deps.schedules))
|
|
79
95
|
.route("/projects", planningRoutes(deps))
|
|
80
96
|
.route("/projects", projectRoutes(deps))
|
|
@@ -98,6 +114,7 @@ function apiRoutes(deps, startedAt) {
|
|
|
98
114
|
.route("/projects", youtubeEditRoutes(deps))
|
|
99
115
|
.route("/fonts", fontsRoutes(deps))
|
|
100
116
|
.route("/prompts", promptRoutes(deps))
|
|
117
|
+
.route("/keywords", keywordRoutes(deps))
|
|
101
118
|
.route("/entries", entryRoutes(deps))
|
|
102
119
|
.route("/document-themes", documentThemeRoutes(deps))
|
|
103
120
|
.route("/pronunciations", pronunciationRoutes(deps))
|
|
@@ -105,19 +122,51 @@ function apiRoutes(deps, startedAt) {
|
|
|
105
122
|
.route("/telemetry", telemetryRoutes(deps))
|
|
106
123
|
.route("/usage", usageRoutes(deps))
|
|
107
124
|
.route("/settings/autostart", autostartRoutes(deps.autostart))
|
|
125
|
+
.route("/settings/remote-access", remoteAccessRoutes(deps.remoteAccess))
|
|
108
126
|
.route("/settings", settingsRoutes(deps))
|
|
109
127
|
.route("/studio", studioRoutes(deps))
|
|
128
|
+
.route("/social", socialRoutes(deps))
|
|
110
129
|
.route("/style-preview", stylePreviewRoutes(deps))
|
|
111
130
|
.route("/tutorial", tutorialRoutes(deps))
|
|
112
131
|
.route("/whats-new", whatsNewRoutes(deps))
|
|
113
132
|
.route("/patch-notes", patchNotesRoutes(deps))
|
|
114
133
|
.route("/tutorials", tutorialPagesRoutes(deps))
|
|
134
|
+
.route("/providers", providerCheckRoutes(deps))
|
|
115
135
|
.route("/providers", providerRoutes(deps))
|
|
116
|
-
.route("/
|
|
136
|
+
.route("/model-checks", modelCheckRoutes(deps))
|
|
137
|
+
.route("/onboarding", onboardingRoutes(deps))
|
|
138
|
+
.route("/assistant", assistantRoutes(deps, runAllowed)));
|
|
117
139
|
}
|
|
118
140
|
export function createApp(deps) {
|
|
119
141
|
const startedAt = deps.clock.now().getTime();
|
|
142
|
+
// An Allow's call goes through the API in-process as the assistant, like its MCP calls.
|
|
143
|
+
const runAllowed = (call) => runAllowedCall({
|
|
144
|
+
db: deps.db,
|
|
145
|
+
ids: deps.ids,
|
|
146
|
+
clock: deps.clock,
|
|
147
|
+
log: deps.log,
|
|
148
|
+
api: async (request) => app.request(request, undefined, assistantBindings),
|
|
149
|
+
}, call);
|
|
120
150
|
const app = new Hono()
|
|
151
|
+
// Slopify has no login, so it never answers the public internet. Tailscale marks every
|
|
152
|
+
// request that came through Funnel; Slopify never turns Funnel on, and this holds even if
|
|
153
|
+
// someone else does.
|
|
154
|
+
.use("*", async (c, next) => {
|
|
155
|
+
if (!viaFunnel(c.req.raw.headers))
|
|
156
|
+
return next();
|
|
157
|
+
return problem(c, {
|
|
158
|
+
status: 403,
|
|
159
|
+
detail: "Slopify doesn't answer the public internet: this request came through Tailscale Funnel. On the computer Slopify runs on, run tailscale funnel status to see which port has Funnel, turn it off with tailscale funnel --https=<that port> off, and open Slopify on your other devices through Settings → General → Remote access instead.",
|
|
160
|
+
});
|
|
161
|
+
})
|
|
162
|
+
// Only Slopify's own names, and changes only from its own page (`request-guard.ts`).
|
|
163
|
+
.use("*", requestGuard({
|
|
164
|
+
listenHost: deps.host,
|
|
165
|
+
remoteHost: deps.remoteAccess?.remoteHost,
|
|
166
|
+
extraHosts: deps.allowedHosts ?? [],
|
|
167
|
+
}))
|
|
168
|
+
// Over remote access: only the account that turned it on, and no host setup.
|
|
169
|
+
.use("*", remoteGuard(deps.remoteAccess))
|
|
121
170
|
.use("*", async (c, next) => {
|
|
122
171
|
// A provisional candidate must not trigger the stale-tab Reload dialog.
|
|
123
172
|
if (!deps.updater?.locked())
|
|
@@ -130,14 +179,12 @@ export function createApp(deps) {
|
|
|
130
179
|
if (deps.installationPending?.() && new URL(c.req.url).pathname !== "/api/update/activate")
|
|
131
180
|
return problem(c, {
|
|
132
181
|
status: 503,
|
|
133
|
-
title: titleOf(503),
|
|
134
182
|
detail: "Slopify is still finishing its Docker setup. Wait for the launcher to finish, then try again.",
|
|
135
183
|
});
|
|
136
184
|
const releaseRequest = deps.mutations?.begin();
|
|
137
185
|
if (deps.mutations !== undefined && releaseRequest === undefined)
|
|
138
186
|
return problem(c, {
|
|
139
187
|
status: 503,
|
|
140
|
-
title: titleOf(503),
|
|
141
188
|
detail: "Slopify is shutting down, so changes cannot be saved right now. Start it again, reload the page and try again.",
|
|
142
189
|
});
|
|
143
190
|
const updateRoute = [
|
|
@@ -151,7 +198,6 @@ export function createApp(deps) {
|
|
|
151
198
|
releaseRequest?.();
|
|
152
199
|
return problem(c, {
|
|
153
200
|
status: 409,
|
|
154
|
-
title: titleOf(409),
|
|
155
201
|
detail: "Slopify is updating. Wait for it to restart, reload the page and try again.",
|
|
156
202
|
});
|
|
157
203
|
}
|
|
@@ -176,15 +222,28 @@ export function createApp(deps) {
|
|
|
176
222
|
return next();
|
|
177
223
|
return problem(c, {
|
|
178
224
|
status: 409,
|
|
179
|
-
title: titleOf(409),
|
|
180
225
|
detail: "This is the sample project, which is read-only so trying things on it never spends anything. Press Make my own copy at the top of the sample's page, then edit and rebuild the copy.",
|
|
181
226
|
extensions: { reason: "sample-read-only" },
|
|
182
227
|
});
|
|
228
|
+
})
|
|
229
|
+
// A template's studio sample is changed only through its studio (`slices/template-studio`),
|
|
230
|
+
// whose runner reaches the project's slices directly: no project route may change it.
|
|
231
|
+
.use("/api/projects/:id/*", async (c, next) => {
|
|
232
|
+
if (["GET", "HEAD", "OPTIONS"].includes(c.req.method))
|
|
233
|
+
return next();
|
|
234
|
+
const owner = sampleOwner(deps.db, c.req.param("id"));
|
|
235
|
+
if (owner === undefined)
|
|
236
|
+
return next();
|
|
237
|
+
return problem(c, {
|
|
238
|
+
status: 409,
|
|
239
|
+
detail: `This is the studio sample of ${owner.name}. Change the template in its studio instead: Library → Templates → ${owner.name} → Open studio.`,
|
|
240
|
+
extensions: { reason: "template-sample" },
|
|
241
|
+
});
|
|
183
242
|
})
|
|
184
243
|
.use("/api/*", startRecorder(deps))
|
|
185
244
|
.onError((error, c) => problemFromError(c, error, deps))
|
|
186
245
|
.notFound(missing)
|
|
187
|
-
.route("/api", apiRoutes(deps, startedAt))
|
|
246
|
+
.route("/api", apiRoutes(deps, startedAt, runAllowed))
|
|
188
247
|
.get("/api/events/global", (c) => streamSSE(c, (stream) => deps.hub.subscribeGlobal(stream, c.req.raw.signal)))
|
|
189
248
|
.get("/api/events/projects/:id", (c) => streamSSE(c, (stream) => deps.hub.subscribe(c.req.param("id"), stream, c.req.raw.signal)))
|
|
190
249
|
// Files are served by URL, not through the API.
|
|
@@ -193,6 +252,23 @@ export function createApp(deps) {
|
|
|
193
252
|
// The API answers for its whole prefix, so an unknown endpoint is a problem+json 404
|
|
194
253
|
// rather than the SPA's index.html with a 200.
|
|
195
254
|
.all("/api/*", missing);
|
|
255
|
+
const mcpDeps = {
|
|
256
|
+
db: deps.db,
|
|
257
|
+
paths: deps.paths,
|
|
258
|
+
ids: deps.ids,
|
|
259
|
+
clock: deps.clock,
|
|
260
|
+
log: deps.log,
|
|
261
|
+
version: deps.version,
|
|
262
|
+
host: deps.host,
|
|
263
|
+
...(deps.measureAudio === undefined ? {} : { measureAudio: deps.measureAudio }),
|
|
264
|
+
};
|
|
265
|
+
// The in-app assistant reaches it the same way, as the assistant, with its turn's token.
|
|
266
|
+
// Mounted first: `/mcp` must never answer for it.
|
|
267
|
+
app.route(assistantMcpPath, assistantMcpRoutes({
|
|
268
|
+
...mcpDeps,
|
|
269
|
+
turns: deps.assistant?.tokens ?? deps.assistantTurns,
|
|
270
|
+
api: async (request) => app.request(request, undefined, assistantBindings),
|
|
271
|
+
}));
|
|
196
272
|
// Agents reach the same API in-process, as the agent (`actor.ts`): every tool validates,
|
|
197
273
|
// refuses and answers exactly like the page's own request.
|
|
198
274
|
app.route(mcpPath, mcpRoutes({
|
|
@@ -225,7 +301,6 @@ const sampleReadOnlyExempt = /\/(revisions\/prepare|rebuild\/preview|open-folder
|
|
|
225
301
|
function missing(c) {
|
|
226
302
|
return problem(c, {
|
|
227
303
|
status: 404,
|
|
228
|
-
title: titleOf(404),
|
|
229
304
|
detail: `${c.req.method} ${c.req.path} is not a route of this API.`,
|
|
230
305
|
});
|
|
231
306
|
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { zValidator } from "@hono/zod-validator";
|
|
2
|
+
import { Hono } from "hono";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import { assistantCliPreferences, assistantScreenSchema, assistantTextMax, } from "../../slices/assistant/model.js";
|
|
5
|
+
import { setCliPreference } from "../../slices/assistant/repo.js";
|
|
6
|
+
import { actorOf } from "./actor.js";
|
|
7
|
+
import { idParam } from "./ids.js";
|
|
8
|
+
import { onInvalid, problem } from "./problem.js";
|
|
9
|
+
import { hostOnlySentence } from "./remote-guard.js";
|
|
10
|
+
import { viaProxy } from "./same-page.js";
|
|
11
|
+
// The assistant panel's chat. The person's own: an agent or the assistant itself is refused
|
|
12
|
+
// here, so nothing but a press in the page answers an ask.
|
|
13
|
+
const messageBody = z
|
|
14
|
+
.object({
|
|
15
|
+
text: z
|
|
16
|
+
.string()
|
|
17
|
+
.trim()
|
|
18
|
+
.min(1, "Write a message first.")
|
|
19
|
+
.max(assistantTextMax, `Keep a message to ${String(assistantTextMax)} characters.`),
|
|
20
|
+
screen: assistantScreenSchema.optional(),
|
|
21
|
+
})
|
|
22
|
+
.strict();
|
|
23
|
+
const answerBody = z.object({ answer: z.enum(["allow", "deny"]) }).strict();
|
|
24
|
+
const cliBody = z.object({ preference: z.enum(assistantCliPreferences) }).strict();
|
|
25
|
+
const notWired = "This copy of Slopify was started without the assistant. Restart Slopify, then open the assistant again.";
|
|
26
|
+
function personOnly(c) {
|
|
27
|
+
return actorOf(c) === "person"
|
|
28
|
+
? undefined
|
|
29
|
+
: problem(c, {
|
|
30
|
+
status: 403,
|
|
31
|
+
detail: "The assistant's chat is the person's: only a press in Slopify's page sends a message or answers an ask.",
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
export function assistantRoutes(deps,
|
|
35
|
+
// On Allow, the asked call is made by Slopify itself (`edge/mcp/assistant.ts`).
|
|
36
|
+
runAllowed) {
|
|
37
|
+
const assistant = deps.assistant;
|
|
38
|
+
const wired = (c) => personOnly(c) ?? assistant ?? problem(c, { status: 503, detail: notWired });
|
|
39
|
+
return new Hono()
|
|
40
|
+
.get("/", async (c) => {
|
|
41
|
+
const refused = personOnly(c);
|
|
42
|
+
if (refused !== undefined)
|
|
43
|
+
return refused;
|
|
44
|
+
if (assistant === undefined)
|
|
45
|
+
return c.json({
|
|
46
|
+
available: false,
|
|
47
|
+
cli: null,
|
|
48
|
+
reason: notWired,
|
|
49
|
+
fix: null,
|
|
50
|
+
preference: "auto",
|
|
51
|
+
session: null,
|
|
52
|
+
});
|
|
53
|
+
const { choice, preference } = await assistant.status();
|
|
54
|
+
return c.json({
|
|
55
|
+
available: choice.ok,
|
|
56
|
+
cli: choice.ok ? choice.cli : null,
|
|
57
|
+
reason: choice.ok ? null : choice.reason,
|
|
58
|
+
fix: choice.ok ? null : choice.fix,
|
|
59
|
+
preference,
|
|
60
|
+
session: assistant.session() ?? null,
|
|
61
|
+
});
|
|
62
|
+
})
|
|
63
|
+
.post("/sessions", (c) => {
|
|
64
|
+
const service = wired(c);
|
|
65
|
+
if (service instanceof Response)
|
|
66
|
+
return service;
|
|
67
|
+
const id = service.newSession();
|
|
68
|
+
return c.json({ session: service.session(id) }, 201);
|
|
69
|
+
})
|
|
70
|
+
.post("/sessions/:id/messages", zValidator("param", idParam, onInvalid), zValidator("json", messageBody, onInvalid), (c) => {
|
|
71
|
+
const service = wired(c);
|
|
72
|
+
if (service instanceof Response)
|
|
73
|
+
return service;
|
|
74
|
+
const { text, screen } = c.req.valid("json");
|
|
75
|
+
const sent = service.send(c.req.valid("param").id, text, screen);
|
|
76
|
+
if (sent.ok)
|
|
77
|
+
return c.json({ turnId: sent.turnId }, 202);
|
|
78
|
+
return problem(c, {
|
|
79
|
+
status: sent.reason === "unknown-session" ? 404 : 409,
|
|
80
|
+
detail: sent.reason === "unknown-session"
|
|
81
|
+
? "This chat no longer exists. Press New chat and send your message again."
|
|
82
|
+
: sent.reason === "busy"
|
|
83
|
+
? "The assistant is still answering in this chat. Wait for it, or press Stop, then send your message."
|
|
84
|
+
: "Two assistant chats are answering already. Wait for one to finish, or press Stop in it, then send your message.",
|
|
85
|
+
extensions: { reason: sent.reason },
|
|
86
|
+
});
|
|
87
|
+
})
|
|
88
|
+
.post("/sessions/:id/stop", zValidator("param", idParam, onInvalid), (c) => {
|
|
89
|
+
const service = wired(c);
|
|
90
|
+
if (service instanceof Response)
|
|
91
|
+
return service;
|
|
92
|
+
return c.json({ stopped: service.stop(c.req.valid("param").id) });
|
|
93
|
+
})
|
|
94
|
+
.post("/asks/:id", zValidator("param", idParam, onInvalid), zValidator("json", answerBody, onInvalid), (c) => {
|
|
95
|
+
// An Allow starts paid or removing work: it is pressed on this computer, or on the
|
|
96
|
+
// person's own device through remote access, never by another account (`remote-guard.ts`).
|
|
97
|
+
if (c.req.valid("json").answer === "allow" && viaProxy(c.req.raw.headers))
|
|
98
|
+
return problem(c, {
|
|
99
|
+
status: 403,
|
|
100
|
+
detail: hostOnlySentence("The assistant's Allow is pressed"),
|
|
101
|
+
extensions: { reason: "host-only" },
|
|
102
|
+
});
|
|
103
|
+
const service = wired(c);
|
|
104
|
+
if (service instanceof Response)
|
|
105
|
+
return service;
|
|
106
|
+
const answered = service.answer(c.req.valid("param").id, c.req.valid("json").answer, runAllowed);
|
|
107
|
+
if (answered.ok)
|
|
108
|
+
return c.json({ ask: answered.ask });
|
|
109
|
+
return problem(c, {
|
|
110
|
+
status: answered.reason === "unknown" ? 404 : 409,
|
|
111
|
+
detail: answered.reason === "unknown"
|
|
112
|
+
? "This ask no longer exists. Ask the assistant again."
|
|
113
|
+
: answered.reason === "expired"
|
|
114
|
+
? "This ask waited more than 15 minutes, so it expired before your answer. Ask the assistant again, so it can check the cost again."
|
|
115
|
+
: "This ask was already answered.",
|
|
116
|
+
extensions: { reason: answered.reason },
|
|
117
|
+
});
|
|
118
|
+
})
|
|
119
|
+
.put("/cli", zValidator("json", cliBody, onInvalid), (c) => {
|
|
120
|
+
const refused = personOnly(c);
|
|
121
|
+
if (refused !== undefined)
|
|
122
|
+
return refused;
|
|
123
|
+
const { preference } = c.req.valid("json");
|
|
124
|
+
setCliPreference(deps.db, preference);
|
|
125
|
+
return c.json({ preference });
|
|
126
|
+
});
|
|
127
|
+
}
|
|
@@ -4,18 +4,12 @@ import { z } from "zod";
|
|
|
4
4
|
import { currentRevisionId } from "../../slices/revisions/repo.js";
|
|
5
5
|
import { projectTitle } from "../../slices/storage/repo.js";
|
|
6
6
|
import { currentWorkOrigin } from "../events/visibility.js";
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
.string()
|
|
11
|
-
.min(1)
|
|
12
|
-
.max(64)
|
|
13
|
-
.regex(/^[0-9A-Za-z_-]+$/),
|
|
14
|
-
});
|
|
15
|
-
const previewParam = projectParam.extend({ previewId: z.uuid() });
|
|
7
|
+
import { projectIdParam } from "./ids.js";
|
|
8
|
+
import { onInvalid, problem } from "./problem.js";
|
|
9
|
+
const previewParam = projectIdParam.extend({ previewId: z.uuid() });
|
|
16
10
|
export function audioPreviewRoutes(deps) {
|
|
17
11
|
return new Hono()
|
|
18
|
-
.get("/:projectId/audio-preview", zValidator("param",
|
|
12
|
+
.get("/:projectId/audio-preview", zValidator("param", projectIdParam, onInvalid), (c) => {
|
|
19
13
|
const { projectId } = c.req.valid("param");
|
|
20
14
|
if (projectTitle(deps.db, projectId) === undefined)
|
|
21
15
|
return missing(c);
|
|
@@ -48,7 +42,6 @@ export function audioPreviewRoutes(deps) {
|
|
|
48
42
|
function missing(c) {
|
|
49
43
|
return problem(c, {
|
|
50
44
|
status: 404,
|
|
51
|
-
title: titleOf(404),
|
|
52
45
|
detail: "This live audio preview has ended. Play the finished narration from the project's audio outputs instead.",
|
|
53
46
|
});
|
|
54
47
|
}
|
|
@@ -10,7 +10,7 @@ const line = z.object({
|
|
|
10
10
|
model: z.string().min(1).max(200),
|
|
11
11
|
text: z.string().trim().min(1).max(auditionLineMax),
|
|
12
12
|
});
|
|
13
|
-
const quoteBody = z.object({
|
|
13
|
+
export const quoteBody = z.object({
|
|
14
14
|
lines: z
|
|
15
15
|
.array(line.extend({ speaker: z.string().max(100) }))
|
|
16
16
|
.min(1)
|
|
@@ -2,7 +2,7 @@ import { zValidator } from "@hono/zod-validator";
|
|
|
2
2
|
import { Hono } from "hono";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
import { AutostartRefusal } from "../autostart/service.js";
|
|
5
|
-
import { onInvalid, problem
|
|
5
|
+
import { onInvalid, problem } from "./problem.js";
|
|
6
6
|
const body = z.object({ enabled: z.boolean() });
|
|
7
7
|
// Settings → General's "Start Slopify when I log in", and the first-run screen's offer of it.
|
|
8
8
|
// In Docker the view says whether Docker starts at login, and turning it on or off is refused
|
|
@@ -12,26 +12,26 @@ export function autostartRoutes(service) {
|
|
|
12
12
|
return (new Hono()
|
|
13
13
|
.get("/", async (c) => {
|
|
14
14
|
if (service === undefined)
|
|
15
|
-
return problem(c, { status: 404,
|
|
15
|
+
return problem(c, { status: 404, detail: unavailable });
|
|
16
16
|
c.header("Cache-Control", "no-store");
|
|
17
17
|
return c.json(await service.view());
|
|
18
18
|
})
|
|
19
19
|
.put("/", zValidator("json", body, onInvalid), async (c) => {
|
|
20
20
|
if (service === undefined)
|
|
21
|
-
return problem(c, { status: 404,
|
|
21
|
+
return problem(c, { status: 404, detail: unavailable });
|
|
22
22
|
try {
|
|
23
23
|
return c.json(await service.set(c.req.valid("json").enabled));
|
|
24
24
|
}
|
|
25
25
|
catch (error) {
|
|
26
26
|
if (!(error instanceof AutostartRefusal))
|
|
27
27
|
throw error;
|
|
28
|
-
return problem(c, { status: 409,
|
|
28
|
+
return problem(c, { status: 409, detail: error.message });
|
|
29
29
|
}
|
|
30
30
|
})
|
|
31
31
|
// The first-run screen's No thanks: never offer it there again, change nothing.
|
|
32
32
|
.post("/answer", async (c) => {
|
|
33
33
|
if (service === undefined)
|
|
34
|
-
return problem(c, { status: 404,
|
|
34
|
+
return problem(c, { status: 404, detail: unavailable });
|
|
35
35
|
return c.json(await service.answer());
|
|
36
36
|
}));
|
|
37
37
|
}
|
|
@@ -2,7 +2,7 @@ import { zValidator } from "@hono/zod-validator";
|
|
|
2
2
|
import { Hono } from "hono";
|
|
3
3
|
import { HTTPException } from "hono/http-exception";
|
|
4
4
|
import { backupConfigInputSchema } from "../../slices/backups/model.js";
|
|
5
|
-
import { onInvalid, problem
|
|
5
|
+
import { onInvalid, problem } from "./problem.js";
|
|
6
6
|
// Settings → Backups: the schedule, the folder, the last result and Back up now. Writing an
|
|
7
7
|
// archive takes minutes, so Back up now answers at once and the screen polls this view.
|
|
8
8
|
export function backupRoutes(service) {
|
|
@@ -21,7 +21,6 @@ export function backupRoutes(service) {
|
|
|
21
21
|
if (!saved.ok)
|
|
22
22
|
return problem(c, {
|
|
23
23
|
status: 400,
|
|
24
|
-
title: titleOf(400),
|
|
25
24
|
detail: saved.detail,
|
|
26
25
|
extensions: { field: "folder" },
|
|
27
26
|
});
|
|
@@ -32,7 +31,6 @@ export function backupRoutes(service) {
|
|
|
32
31
|
if (!started.ok)
|
|
33
32
|
return problem(c, {
|
|
34
33
|
status: started.status,
|
|
35
|
-
title: titleOf(started.status),
|
|
36
34
|
detail: started.detail,
|
|
37
35
|
});
|
|
38
36
|
return c.json(await backups().view(), 202);
|
|
@@ -5,7 +5,8 @@ import { bodyLimit } from "hono/body-limit";
|
|
|
5
5
|
import { z } from "zod";
|
|
6
6
|
import { clearChannelVideos, deleteChannelVideo, importChannelVideos, listChannelVideos, previewChannelVideos, } from "../../slices/channels/videos.js";
|
|
7
7
|
import { channelEpisodes, deleteMemory, editMemory, setEpisodeMemory, } from "../../slices/episodes/service.js";
|
|
8
|
-
import { onInvalid
|
|
8
|
+
import { onInvalid } from "./problem.js";
|
|
9
|
+
import { jsonBody, refusal } from "./refusal.js";
|
|
9
10
|
const idParam = z.object({ id: z.uuid() });
|
|
10
11
|
const memoryParam = idParam.extend({ memoryId: z.string().min(1).max(100) });
|
|
11
12
|
const videoParam = idParam.extend({ videoId: z.uuid() });
|
|
@@ -22,12 +23,12 @@ export function channelMemoryRoutes(deps) {
|
|
|
22
23
|
return result.ok ? c.json(result.value) : refused(c, result, "episode");
|
|
23
24
|
})
|
|
24
25
|
.put("/:id/episodes/setting", zValidator("param", idParam, onInvalid), async (c) => {
|
|
25
|
-
const result = setEpisodeMemory(service, c.req.valid("param").id, await
|
|
26
|
+
const result = setEpisodeMemory(service, c.req.valid("param").id, await jsonBody(c));
|
|
26
27
|
return result.ok ? c.json(result.value) : refused(c, result, "episode");
|
|
27
28
|
})
|
|
28
29
|
.put("/:id/episodes/:memoryId", zValidator("param", memoryParam, onInvalid), async (c) => {
|
|
29
30
|
const { id, memoryId } = c.req.valid("param");
|
|
30
|
-
const result = editMemory(service, id, memoryId, await
|
|
31
|
+
const result = editMemory(service, id, memoryId, await jsonBody(c));
|
|
31
32
|
return result.ok ? c.json(result.value) : refused(c, result, "episode");
|
|
32
33
|
})
|
|
33
34
|
.delete("/:id/episodes/:memoryId", zValidator("param", memoryParam, onInvalid), (c) => {
|
|
@@ -40,11 +41,11 @@ export function channelMemoryRoutes(deps) {
|
|
|
40
41
|
return result.ok ? c.json({ videos: result.value }) : refused(c, result, "video");
|
|
41
42
|
})
|
|
42
43
|
.post("/:id/videos/preview", zValidator("param", idParam, onInvalid), importLimit(), async (c) => {
|
|
43
|
-
const result = previewChannelVideos(service, c.req.valid("param").id, await
|
|
44
|
+
const result = previewChannelVideos(service, c.req.valid("param").id, await jsonBody(c));
|
|
44
45
|
return result.ok ? c.json(result.value) : refused(c, result, "video");
|
|
45
46
|
})
|
|
46
47
|
.post("/:id/videos", zValidator("param", idParam, onInvalid), importLimit(), async (c) => {
|
|
47
|
-
const result = importChannelVideos(service, c.req.valid("param").id, await
|
|
48
|
+
const result = importChannelVideos(service, c.req.valid("param").id, await jsonBody(c));
|
|
48
49
|
return result.ok ? c.json(result.value, 201) : refused(c, result, "video");
|
|
49
50
|
})
|
|
50
51
|
.delete("/:id/videos", zValidator("param", idParam, onInvalid), (c) => {
|
|
@@ -67,26 +68,12 @@ function importLimit() {
|
|
|
67
68
|
}, "video"),
|
|
68
69
|
});
|
|
69
70
|
}
|
|
70
|
-
async function body(c) {
|
|
71
|
-
try {
|
|
72
|
-
return await c.req.json();
|
|
73
|
-
}
|
|
74
|
-
catch {
|
|
75
|
-
return undefined;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
71
|
function refused(c, result, about) {
|
|
79
|
-
const status = result.reason === "not-found" ? 404 : 400;
|
|
80
72
|
const detail = result.message ??
|
|
81
73
|
(result.reason === "not-found"
|
|
82
74
|
? about === "episode"
|
|
83
75
|
? "This channel or episode summary no longer exists; it may have been deleted in another tab. Reload the channel's Episodes tab."
|
|
84
76
|
: "This channel or video title no longer exists; it may have been deleted in another tab. Reload the channel's Existing videos tab."
|
|
85
77
|
: "This request isn't valid. Reload the page and try again.");
|
|
86
|
-
return
|
|
87
|
-
status,
|
|
88
|
-
title: titleOf(status),
|
|
89
|
-
detail,
|
|
90
|
-
extensions: { reason: result.reason },
|
|
91
|
-
});
|
|
78
|
+
return refusal(c, result.reason, { statuses: { "not-found": 404 }, otherwise: 400, detail });
|
|
92
79
|
}
|