@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
|
@@ -5,6 +5,7 @@ import { z } from "zod";
|
|
|
5
5
|
import { redact } from "../../kernel/log.js";
|
|
6
6
|
import { providerError } from "../../kernel/ports/model.js";
|
|
7
7
|
import { cliCheck, cliReported } from "../explain.js";
|
|
8
|
+
import { accessField } from "../model-access.js";
|
|
8
9
|
import { cliLoginError } from "./cli-login-error.js";
|
|
9
10
|
import { codexPlanLimit } from "./codex-limits.js";
|
|
10
11
|
import { nodeCodexModels } from "./codex-models.js";
|
|
@@ -52,7 +53,10 @@ const disabledFeatures = [
|
|
|
52
53
|
// "-i, --image <FILE>... Optional image(s) to attach to the initial prompt"), which needs no
|
|
53
54
|
// tool: `view_image` stays disabled. Each is given as its own flag so a path is never read as
|
|
54
55
|
// the prompt.
|
|
55
|
-
|
|
56
|
+
// One ephemeral, read-only turn in `directory` with every local tool, hook, plugin, skill and
|
|
57
|
+
// project document left out. The content adapter and the in-app assistant (`assistant-cli.ts`)
|
|
58
|
+
// both start from it and add their own instructions, search setting and MCP servers.
|
|
59
|
+
export function hardenedCodexBase(directory) {
|
|
56
60
|
return [
|
|
57
61
|
"exec",
|
|
58
62
|
"--json",
|
|
@@ -86,6 +90,11 @@ export function codexArgs(req, directory, documents, images) {
|
|
|
86
90
|
"include_environment_context=false",
|
|
87
91
|
"-c",
|
|
88
92
|
'shell_environment_policy.inherit="none"',
|
|
93
|
+
];
|
|
94
|
+
}
|
|
95
|
+
export function codexArgs(req, directory, documents, images) {
|
|
96
|
+
return [
|
|
97
|
+
...hardenedCodexBase(directory),
|
|
89
98
|
"-c",
|
|
90
99
|
`instructions=${JSON.stringify(writingRole + (documents ? " Use the explicitly supplied research MCP tool to read request documents; it is the only permitted local reference source." : ""))}`,
|
|
91
100
|
"-c",
|
|
@@ -221,6 +230,7 @@ export function codexLlm(deps) {
|
|
|
221
230
|
throw codexLimitError(failed, planLimit);
|
|
222
231
|
throw providerError({
|
|
223
232
|
kind: "other",
|
|
233
|
+
...accessField(null, failed),
|
|
224
234
|
message: cliReported(binary, redact(cliShaped(binary, turnFailed, event.value).error.message), cliCheck(binary)),
|
|
225
235
|
});
|
|
226
236
|
}
|
|
@@ -234,6 +244,7 @@ export function codexLlm(deps) {
|
|
|
234
244
|
throw codexLimitError(failed, planLimit);
|
|
235
245
|
throw providerError({
|
|
236
246
|
kind: "other",
|
|
247
|
+
...accessField(null, failed),
|
|
237
248
|
message: cliReported(binary, redact(cliShaped(binary, errorEvent, event.value).message), cliCheck(binary)),
|
|
238
249
|
});
|
|
239
250
|
}
|
|
@@ -6,6 +6,7 @@ import { fileURLToPath } from "node:url";
|
|
|
6
6
|
import { z } from "zod";
|
|
7
7
|
import { documentIndex, llmDocumentsSchema, } from "../../kernel/ports/llm-documents.js";
|
|
8
8
|
import { providerError } from "../../kernel/ports/model.js";
|
|
9
|
+
import { editSettings } from "../../kernel/ports/settings-places.js";
|
|
9
10
|
export const documentServerName = "slopify_research";
|
|
10
11
|
export const documentTool = "read_document";
|
|
11
12
|
export const documentToolName = `mcp__${documentServerName}__${documentTool}`;
|
|
@@ -16,7 +17,7 @@ export function documentWorkspace(input) {
|
|
|
16
17
|
if (!parsed.success)
|
|
17
18
|
throw providerError({
|
|
18
19
|
kind: "unsupported",
|
|
19
|
-
message:
|
|
20
|
+
message: `The research notes are too large, or not in a form the AI model can be given, so nothing was sent. Make the research notes shorter in ${editSettings.article}, then use Try again; if it keeps happening, use Download diagnostics in Settings and report it.`,
|
|
20
21
|
});
|
|
21
22
|
const documents = parsed.data;
|
|
22
23
|
const directory = mkdtempSync(join(tmpdir(), "slopify-documents-"));
|
|
@@ -82,6 +83,6 @@ export function documentWorkspace(input) {
|
|
|
82
83
|
function unread() {
|
|
83
84
|
return providerError({
|
|
84
85
|
kind: "unavailable",
|
|
85
|
-
message:
|
|
86
|
+
message: `The AI model did not read all of the research notes, so its answer was not used (the attempt may still have used your quota). Use Try again; if it keeps happening, choose another model in ${editSettings.writer}.`,
|
|
86
87
|
});
|
|
87
88
|
}
|
|
@@ -2,6 +2,7 @@ import { copyFileSync, mkdtempSync, rmSync } from "node:fs";
|
|
|
2
2
|
import { tmpdir } from "node:os";
|
|
3
3
|
import { basename, extname, join } from "node:path";
|
|
4
4
|
import { providerError } from "../../kernel/ports/model.js";
|
|
5
|
+
import { editSettings } from "../../kernel/ports/settings-places.js";
|
|
5
6
|
const extensions = new Set([".png", ".jpg", ".jpeg", ".webp"]);
|
|
6
7
|
// ceiling: a review shows one image, or a short's handful plus the establishing image.
|
|
7
8
|
export const imagesMax = 12;
|
|
@@ -47,12 +48,12 @@ export function readFileName(path) {
|
|
|
47
48
|
export function unseenImages() {
|
|
48
49
|
return providerError({
|
|
49
50
|
kind: "unavailable",
|
|
50
|
-
message:
|
|
51
|
+
message: `The reviewer answered without opening every picture it was given, so its verdict was not used (the attempt may still have used your quota). Use Try again; if it keeps happening, choose Codex as the reviewer in ${editSettings.checks}.`,
|
|
51
52
|
});
|
|
52
53
|
}
|
|
53
54
|
export function noImages(provider) {
|
|
54
55
|
return providerError({
|
|
55
56
|
kind: "unsupported",
|
|
56
|
-
message: `Slopify can't show pictures to ${provider}, so a review that needs them was not sent. In
|
|
57
|
+
message: `Slopify can't show pictures to ${provider}, so a review that needs them was not sent. In ${editSettings.checks}, choose Claude Code or Codex as the reviewer, or set the picture reviews to Off, then use Try again.`,
|
|
57
58
|
});
|
|
58
59
|
}
|
|
@@ -2,8 +2,10 @@ import { z } from "zod";
|
|
|
2
2
|
import { redact } from "../../kernel/log.js";
|
|
3
3
|
import { documentMessages } from "../../kernel/ports/llm-documents.js";
|
|
4
4
|
import { providerError } from "../../kernel/ports/model.js";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { editSettings } from "../../kernel/ports/settings-places.js";
|
|
6
|
+
import { droppedStream, httpFailure, providerSaid, refreshList, unreadable } from "../explain.js";
|
|
7
|
+
import { failureText, httpProviderError, kindOfStatus, requireKey, safeJson, } from "../http-failure.js";
|
|
8
|
+
import { accessField, modelAccessOf } from "../model-access.js";
|
|
7
9
|
import { noImages } from "./image-workspace.js";
|
|
8
10
|
import { sseData } from "./sse-lines.js";
|
|
9
11
|
// The HTTP gateway adapter: the platform's own `fetch` plus the line reader beside this
|
|
@@ -86,7 +88,8 @@ export function openRouterLlm(deps) {
|
|
|
86
88
|
// A stream that has already answered 200 reports a mid-flight failure in a data
|
|
87
89
|
// frame; without this the stage would store half an article as a success.
|
|
88
90
|
throw providerError({
|
|
89
|
-
kind:
|
|
91
|
+
kind: kindOfStatus(statusOf(chunk.error.code)),
|
|
92
|
+
...accessField(statusOf(chunk.error.code), chunk.error.message),
|
|
90
93
|
message: streamFailure(statusOf(chunk.error.code), redact(chunk.error.message)),
|
|
91
94
|
});
|
|
92
95
|
}
|
|
@@ -147,53 +150,22 @@ export function openRouterLlm(deps) {
|
|
|
147
150
|
};
|
|
148
151
|
}
|
|
149
152
|
function headers(key) {
|
|
150
|
-
// An attempt that finds no key fails rather than calling anonymously
|
|
151
|
-
//
|
|
152
|
-
|
|
153
|
-
// retry until the user saves a key, and the wrapper is where that is decided.
|
|
154
|
-
if (key === undefined || key === "") {
|
|
155
|
-
throw providerError({ kind: "missing_key", message: missingKey("OpenRouter") });
|
|
156
|
-
}
|
|
157
|
-
return { Authorization: `Bearer ${key}`, ...appHeaders };
|
|
158
|
-
}
|
|
159
|
-
// Only the adapter sees the vendor's status code, so only the adapter names the kind.
|
|
160
|
-
function kindOf(status) {
|
|
161
|
-
if (status === 401 || status === 403) {
|
|
162
|
-
return "auth";
|
|
163
|
-
}
|
|
164
|
-
if (status === 429) {
|
|
165
|
-
return "rate_limit";
|
|
166
|
-
}
|
|
167
|
-
// ceiling: everything else is `other` and is retried, so a 400 or a 402 fails the same
|
|
168
|
-
// way four times over. A terminal "this will never work" kind has to reach the port's
|
|
169
|
-
// error contract first, which is not this adapter's to widen.
|
|
170
|
-
// The provider's own server failed; the same request may well succeed later.
|
|
171
|
-
if (status >= 500)
|
|
172
|
-
return "dropped";
|
|
173
|
-
return "other";
|
|
153
|
+
// An attempt that finds no key fails rather than calling anonymously and being told off by
|
|
154
|
+
// the provider in words the user cannot act on.
|
|
155
|
+
return { Authorization: `Bearer ${requireKey(key, "OpenRouter")}`, ...appHeaders };
|
|
174
156
|
}
|
|
175
157
|
async function failure(response, next) {
|
|
176
|
-
const text = await response
|
|
158
|
+
const text = await failureText(response);
|
|
177
159
|
const parsed = errorBody.safeParse(safeJson(text));
|
|
178
160
|
// The provider's own words, through the redactor - an error body may quote the key back.
|
|
179
161
|
const message = redact(parsed.success ? parsed.data.error.message : text.trim() || response.statusText);
|
|
180
|
-
|
|
181
|
-
return providerError({
|
|
182
|
-
kind: kindOf(response.status),
|
|
183
|
-
message: httpFailure({
|
|
184
|
-
provider: "OpenRouter",
|
|
185
|
-
status: response.status,
|
|
186
|
-
detail: message,
|
|
187
|
-
next,
|
|
188
|
-
}),
|
|
189
|
-
...(retryAfterMs === undefined ? {} : { retryAfterMs }),
|
|
190
|
-
});
|
|
162
|
+
return httpProviderError(response, kindOfStatus(response.status), httpFailure({ provider: "OpenRouter", status: response.status, detail: message, next }), undefined, modelAccessOf(response.status, message));
|
|
191
163
|
}
|
|
192
164
|
// A mid-stream error carries an HTTP-like code; with none, the provider's words are all there is.
|
|
193
165
|
function streamFailure(status, detail) {
|
|
194
166
|
return status >= 400
|
|
195
167
|
? httpFailure({ provider: "OpenRouter", status, detail })
|
|
196
|
-
: providerSaid("OpenRouter", "stopped part-way through the answer", detail,
|
|
168
|
+
: providerSaid("OpenRouter", "stopped part-way through the answer", detail, `Use Try again; if it keeps happening, choose another model in ${editSettings.writer}.`);
|
|
197
169
|
}
|
|
198
170
|
function statusOf(code) {
|
|
199
171
|
return typeof code === "number" ? code : Number(code ?? 0);
|
|
@@ -211,11 +183,3 @@ function parseChunk(data) {
|
|
|
211
183
|
}
|
|
212
184
|
return parsed.data;
|
|
213
185
|
}
|
|
214
|
-
function safeJson(text) {
|
|
215
|
-
try {
|
|
216
|
-
return JSON.parse(text);
|
|
217
|
-
}
|
|
218
|
-
catch {
|
|
219
|
-
return undefined;
|
|
220
|
-
}
|
|
221
|
-
}
|
|
@@ -3,7 +3,9 @@ import { z } from "zod";
|
|
|
3
3
|
import { cliCommand } from "../../kernel/cli-command.js";
|
|
4
4
|
import { redact } from "../../kernel/log.js";
|
|
5
5
|
import { providerError } from "../../kernel/ports/model.js";
|
|
6
|
+
import { editSettings } from "../../kernel/ports/settings-places.js";
|
|
6
7
|
import { cliName, commandOf, quoted } from "../explain.js";
|
|
8
|
+
import { safeJson } from "../http-failure.js";
|
|
7
9
|
// ceiling: the last 8 KiB of stderr is kept. A CLI that writes megabytes of progress there
|
|
8
10
|
// would otherwise be held in memory for the length of a run, and the tail is the part that
|
|
9
11
|
// says why it stopped. Streaming stderr to the log is the upgrade if a provider ever
|
|
@@ -108,7 +110,7 @@ export function nodeRunCli(binary, args, signal, options) {
|
|
|
108
110
|
return {
|
|
109
111
|
...(inputWritten === undefined ? {} : { inputWritten }),
|
|
110
112
|
pid: child.pid,
|
|
111
|
-
stdout:
|
|
113
|
+
stdout: bytesOf(child.stdout),
|
|
112
114
|
stderr: () => stderr,
|
|
113
115
|
ended,
|
|
114
116
|
kill: terminate,
|
|
@@ -139,7 +141,7 @@ export function cliInput(text) {
|
|
|
139
141
|
if (Buffer.byteLength(text) >= 8 * 1024 * 1024)
|
|
140
142
|
throw providerError({
|
|
141
143
|
kind: "unsupported",
|
|
142
|
-
message:
|
|
144
|
+
message: `This prompt is larger than the CLI accepts (8 MB), so nothing was sent. Make the article or its research notes shorter in ${editSettings.article}, or choose an API service such as OpenRouter under Written by there, then use Try again.`,
|
|
143
145
|
});
|
|
144
146
|
return text;
|
|
145
147
|
}
|
|
@@ -168,7 +170,7 @@ export function promptOf(messages) {
|
|
|
168
170
|
export function endedWithout(binary, ended, stderr) {
|
|
169
171
|
const said = redact(stderr.trim());
|
|
170
172
|
if (ended.error !== null)
|
|
171
|
-
return `The ${cliName(binary)} could not be started${quoted("", redact(ended.error.message))}. Check it is installed and set up in Settings →
|
|
173
|
+
return `The ${cliName(binary)} could not be started${quoted("", redact(ended.error.message))}. Check it is installed and set up in Settings → Keys & services, then use Try again.`;
|
|
172
174
|
const how = ended.code === null ? "killed by the system" : `exit code ${String(ended.code)}`;
|
|
173
175
|
return `The ${cliName(binary)} stopped without answering${quoted(how, said)}. Run ${commandOf(binary)} in a terminal to check it works and is signed in, then use Try again.`;
|
|
174
176
|
}
|
|
@@ -181,13 +183,6 @@ export function endedKind(ended) {
|
|
|
181
183
|
export function stuckCli(binary) {
|
|
182
184
|
return `The ${cliName(binary)} stopped responding and could not be shut down. Close any leftover ${commandOf(binary)} processes or restart your computer, then use Try again.`;
|
|
183
185
|
}
|
|
184
|
-
// Unreachable while stdio names `pipe` for fd 1; it is here so the type carries no null
|
|
185
|
-
// and no non-null assertion is needed to read the stream.
|
|
186
|
-
const nothing = {
|
|
187
|
-
[Symbol.asyncIterator]: () => ({
|
|
188
|
-
next: () => Promise.resolve({ done: true, value: undefined }),
|
|
189
|
-
}),
|
|
190
|
-
};
|
|
191
186
|
const typed = z.object({ type: z.string() });
|
|
192
187
|
// A JSONL line off a CLI's stdout. The raw value travels with its `type` because a schema
|
|
193
188
|
// that names only `type` strips every other key, and each event's own shape is checked
|
|
@@ -215,22 +210,12 @@ export function cliShaped(binary, schema, value) {
|
|
|
215
210
|
}
|
|
216
211
|
return parsed.data;
|
|
217
212
|
}
|
|
213
|
+
// fd 1 is always a pipe with no encoding, so its pieces are bytes; the null check is for the type.
|
|
218
214
|
async function* bytesOf(source) {
|
|
215
|
+
if (source === null)
|
|
216
|
+
return;
|
|
219
217
|
for await (const piece of source) {
|
|
220
|
-
if (
|
|
221
|
-
yield new TextEncoder().encode(piece);
|
|
222
|
-
continue;
|
|
223
|
-
}
|
|
224
|
-
if (piece instanceof Uint8Array) {
|
|
218
|
+
if (piece instanceof Uint8Array)
|
|
225
219
|
yield piece;
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
function safeJson(text) {
|
|
230
|
-
try {
|
|
231
|
-
return JSON.parse(text);
|
|
232
|
-
}
|
|
233
|
-
catch {
|
|
234
|
-
return undefined;
|
|
235
220
|
}
|
|
236
221
|
}
|
|
@@ -5,7 +5,9 @@
|
|
|
5
5
|
// the middle of one, or inside a multi-byte character. TextDecoder's streaming mode holds
|
|
6
6
|
// back the tail of a split UTF-8 sequence instead of emitting a replacement character,
|
|
7
7
|
// and the leftover buffer holds back a split line.
|
|
8
|
-
export async function* lines(chunks, signal
|
|
8
|
+
export async function* lines(chunks, signal,
|
|
9
|
+
// A producer that never ends a line would otherwise grow the buffer without bound.
|
|
10
|
+
pending) {
|
|
9
11
|
const decoder = new TextDecoder("utf-8");
|
|
10
12
|
let buffer = "";
|
|
11
13
|
for await (const chunk of chunks) {
|
|
@@ -15,6 +17,8 @@ export async function* lines(chunks, signal) {
|
|
|
15
17
|
yield withoutCr(buffer.slice(0, at));
|
|
16
18
|
buffer = buffer.slice(at + 1);
|
|
17
19
|
}
|
|
20
|
+
if (pending !== undefined && buffer.length > pending.chars)
|
|
21
|
+
throw pending.error();
|
|
18
22
|
}
|
|
19
23
|
buffer += decoder.decode();
|
|
20
24
|
// A producer that ends without a trailing newline still wrote a whole line, and one cut
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// Whether a provider's failure says the account can't use the chosen model. Read from the
|
|
2
|
+
// status and the provider's own words, since only the adapter sees them; it never changes the
|
|
3
|
+
// error's kind, so a run fails exactly as before. Undefined: the failure says nothing about
|
|
4
|
+
// the model.
|
|
5
|
+
// Not-found comes first: OpenAI's "does not exist or you do not have access to it" is about a
|
|
6
|
+
// model id, not a plan. The loose phrases count only when the text is about a model, so a
|
|
7
|
+
// voice or a file that does not exist is not mistaken for one.
|
|
8
|
+
const notFound = /model_not_found|not a valid model|model not found|no endpoints found|invalid model|unknown model|is not found for api version|models\/[^ ]+ is not found/i;
|
|
9
|
+
const looseNotFound = /does not exist|may not exist|not[_ ]found/i;
|
|
10
|
+
const noAccess = /not supported when using codex with a chatgpt account|not (?:available|included|supported) (?:on|in|for|with) your (?:current )?(?:plan|account|subscription|tier|region|country)|upgrade your (?:plan|subscription)|must be verified to use the model|does not have access to (?:the )?model|do not have access to (?:this|the) model|not allowed to (?:use|access) (?:this|the) model|requires a paid plan/i;
|
|
11
|
+
const mentionsModel = /\bmodel/i;
|
|
12
|
+
// `atModel`: the request went to the model's own address (fal.ai's and Replicate's endpoints,
|
|
13
|
+
// Google's models/<id>), so a 404 or 403 there is about the model whatever the words say.
|
|
14
|
+
export function modelAccessOf(status, text, atModel = false) {
|
|
15
|
+
if (notFound.test(text))
|
|
16
|
+
return "not-found";
|
|
17
|
+
// "Upgrade your plan" or "not found" alone is as often about credits, a voice or a feature
|
|
18
|
+
// as about a model.
|
|
19
|
+
if (mentionsModel.test(text)) {
|
|
20
|
+
if (looseNotFound.test(text))
|
|
21
|
+
return "not-found";
|
|
22
|
+
if (noAccess.test(text))
|
|
23
|
+
return "no-access";
|
|
24
|
+
}
|
|
25
|
+
else if (!atModel)
|
|
26
|
+
return undefined;
|
|
27
|
+
if (status === 404)
|
|
28
|
+
return "not-found";
|
|
29
|
+
if (status === 403)
|
|
30
|
+
return "no-access";
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
// Spread into a providerError init.
|
|
34
|
+
export function accessField(status, text, atModel = false) {
|
|
35
|
+
const access = modelAccessOf(status, text, atModel);
|
|
36
|
+
return access === undefined ? {} : { access };
|
|
37
|
+
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { redact } from "../../kernel/log.js";
|
|
3
3
|
import { providerError } from "../../kernel/ports/model.js";
|
|
4
|
-
import { httpFailure,
|
|
5
|
-
import {
|
|
4
|
+
import { httpFailure, noAudio, voiceFix } from "../explain.js";
|
|
5
|
+
import { failureText, httpProviderError, kindOfStatus, requireKey, safeJson, } from "../http-failure.js";
|
|
6
|
+
import { modelAccessOf } from "../model-access.js";
|
|
6
7
|
import { cartesiaLanguages, lookUp } from "./voice-languages.js";
|
|
7
8
|
// The HTTP gateway adapter for Cartesia. `fetch` and
|
|
8
9
|
// nothing else; `/tts/bytes` streams the audio it renders, so the response body is
|
|
@@ -69,45 +70,21 @@ export function cartesiaTts(deps) {
|
|
|
69
70
|
};
|
|
70
71
|
}
|
|
71
72
|
function keyOf(deps) {
|
|
72
|
-
|
|
73
|
-
// An absent key is terminal, so it never becomes a request.
|
|
74
|
-
if (key === undefined || key === "") {
|
|
75
|
-
throw providerError({ kind: "missing_key", message: missingKey("Cartesia") });
|
|
76
|
-
}
|
|
77
|
-
return key;
|
|
78
|
-
}
|
|
79
|
-
function kindOf(status) {
|
|
80
|
-
if (status === 401 || status === 403) {
|
|
81
|
-
return "auth";
|
|
82
|
-
}
|
|
83
|
-
// `concurrency_limited` is the plan's own limit and arrives as a 429 like any other, so
|
|
84
|
-
// the status is enough and the code below only reaches the message.
|
|
85
|
-
if (status === 429) {
|
|
86
|
-
return "rate_limit";
|
|
87
|
-
}
|
|
88
|
-
// ceiling: as in the other two adapters, everything else is `other` and is retried.
|
|
89
|
-
// The provider's own server failed; the same request may well succeed later.
|
|
90
|
-
if (status >= 500)
|
|
91
|
-
return "dropped";
|
|
92
|
-
return "other";
|
|
73
|
+
return requireKey(deps.key(), "Cartesia");
|
|
93
74
|
}
|
|
94
75
|
async function failure(response, voiceId) {
|
|
95
|
-
const text = await response
|
|
76
|
+
const text = await failureText(response);
|
|
96
77
|
const message = redact(detailOf(text) || response.statusText);
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
fix: voiceFix(voiceId),
|
|
108
|
-
}),
|
|
109
|
-
...(retryAfterMs === undefined ? {} : { retryAfterMs }),
|
|
110
|
-
});
|
|
78
|
+
return httpProviderError(response, kindOfStatus(response.status),
|
|
79
|
+
// `voice_not_found` has to say which voice was asked for; Cartesia's
|
|
80
|
+
// own message does not repeat the id.
|
|
81
|
+
httpFailure({
|
|
82
|
+
provider: "Cartesia",
|
|
83
|
+
status: response.status,
|
|
84
|
+
detail: message,
|
|
85
|
+
subject: `narration request for voice "${voiceId}"`,
|
|
86
|
+
fix: voiceFix(voiceId),
|
|
87
|
+
}), undefined, modelAccessOf(response.status, text));
|
|
111
88
|
}
|
|
112
89
|
function detailOf(text) {
|
|
113
90
|
const parsed = errorBody.safeParse(safeJson(text));
|
|
@@ -120,11 +97,3 @@ function detailOf(text) {
|
|
|
120
97
|
const parts = [code, message].filter((part) => part !== undefined && part !== "");
|
|
121
98
|
return parts.length === 0 ? text.trim() : parts.join(": ");
|
|
122
99
|
}
|
|
123
|
-
function safeJson(text) {
|
|
124
|
-
try {
|
|
125
|
-
return JSON.parse(text);
|
|
126
|
-
}
|
|
127
|
-
catch {
|
|
128
|
-
return undefined;
|
|
129
|
-
}
|
|
130
|
-
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { redact } from "../../kernel/log.js";
|
|
3
3
|
import { providerError } from "../../kernel/ports/model.js";
|
|
4
|
-
import { httpFailure,
|
|
5
|
-
import {
|
|
4
|
+
import { httpFailure, noAudio, refreshList, unreadable, voiceFix } from "../explain.js";
|
|
5
|
+
import { failureText, httpProviderError, kindOfStatus, requireKey, safeJson, } from "../http-failure.js";
|
|
6
|
+
import { modelAccessOf } from "../model-access.js";
|
|
6
7
|
import { elevenLabsLanguages, lookUp } from "./voice-languages.js";
|
|
7
8
|
// The HTTP gateway adapter for ElevenLabs: the platform's own `fetch` and nothing else. The
|
|
8
9
|
// response body already is the `ReadableStream<Uint8Array>` the port asks for, so an SDK
|
|
@@ -99,52 +100,27 @@ export function elevenLabsTts(deps) {
|
|
|
99
100
|
};
|
|
100
101
|
}
|
|
101
102
|
function keyOf(deps) {
|
|
102
|
-
|
|
103
|
-
// `missing_key`, not `auth`, because that rule makes it terminal.
|
|
104
|
-
if (key === undefined || key === "") {
|
|
105
|
-
throw providerError({ kind: "missing_key", message: missingKey("ElevenLabs") });
|
|
106
|
-
}
|
|
107
|
-
return key;
|
|
108
|
-
}
|
|
109
|
-
// Only the adapter sees the vendor's status code, so only the adapter names the kind.
|
|
110
|
-
function kindOf(status) {
|
|
111
|
-
if (status === 401 || status === 403) {
|
|
112
|
-
return "auth";
|
|
113
|
-
}
|
|
114
|
-
if (status === 429) {
|
|
115
|
-
return "rate_limit";
|
|
116
|
-
}
|
|
117
|
-
// ceiling: everything else is `other` and is retried, so a text past the character limit
|
|
118
|
-
// fails the same way four times over. A terminal "this will never work" kind has to reach the
|
|
119
|
-
// port's error contract first, which is not this adapter's to widen.
|
|
120
|
-
// The provider's own server failed; the same request may well succeed later.
|
|
121
|
-
if (status >= 500)
|
|
122
|
-
return "dropped";
|
|
123
|
-
return "other";
|
|
103
|
+
return requireKey(deps.key(), "ElevenLabs");
|
|
124
104
|
}
|
|
125
105
|
async function failure(response, voiceId, next) {
|
|
126
|
-
const text = await response
|
|
106
|
+
const text = await failureText(response);
|
|
127
107
|
// The provider's own words, through the redactor - an error body may quote the key back.
|
|
128
108
|
const message = redact(detailOf(text) || response.statusText);
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
:
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
}),
|
|
145
|
-
}),
|
|
146
|
-
...(retryAfterMs === undefined ? {} : { retryAfterMs }),
|
|
147
|
-
});
|
|
109
|
+
return httpProviderError(response, kindOfStatus(response.status),
|
|
110
|
+
// A rejected voice ID has to be named, and it is the one part of the
|
|
111
|
+
// request the user chose. It is not secret, unlike everything else on the wire.
|
|
112
|
+
httpFailure({
|
|
113
|
+
provider: "ElevenLabs",
|
|
114
|
+
status: response.status,
|
|
115
|
+
detail: message,
|
|
116
|
+
next,
|
|
117
|
+
...(voiceId === undefined
|
|
118
|
+
? {}
|
|
119
|
+
: {
|
|
120
|
+
subject: `narration request for voice "${voiceId}"`,
|
|
121
|
+
fix: voiceFix(voiceId),
|
|
122
|
+
}),
|
|
123
|
+
}), undefined, modelAccessOf(response.status, text));
|
|
148
124
|
}
|
|
149
125
|
function detailOf(text) {
|
|
150
126
|
const parsed = errorBody.safeParse(safeJson(text));
|
|
@@ -159,11 +135,3 @@ function detailOf(text) {
|
|
|
159
135
|
// (`max_character_limit_exceeded`, `voice_not_found`) and the message is the sentence.
|
|
160
136
|
return [detail.status, detail.message].filter((part) => part !== undefined).join(": ");
|
|
161
137
|
}
|
|
162
|
-
function safeJson(text) {
|
|
163
|
-
try {
|
|
164
|
-
return JSON.parse(text);
|
|
165
|
-
}
|
|
166
|
-
catch {
|
|
167
|
-
return undefined;
|
|
168
|
-
}
|
|
169
|
-
}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
import { internalError } from "../../kernel/errors.js";
|
|
2
3
|
import { redact } from "../../kernel/log.js";
|
|
3
4
|
import { providerError } from "../../kernel/ports/model.js";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
5
|
+
import { editSettings } from "../../kernel/ports/settings-places.js";
|
|
6
|
+
import { httpFailure, noAudio, providerSaid, refreshList, unreadable, voiceFix, } from "../explain.js";
|
|
7
|
+
import { failureText, httpProviderError, kindOfStatus, requireKey, safeJson, } from "../http-failure.js";
|
|
8
|
+
import { modelAccessOf } from "../model-access.js";
|
|
6
9
|
// The HTTP gateway adapter for Gemini's speech generation (generateContent with an AUDIO
|
|
7
10
|
// response, https://ai.google.dev/gemini-api/docs/speech-generation), billed to a Gemini API
|
|
8
11
|
// key. One voice is `speechConfig.voiceConfig`; a conversation of exactly two voices is
|
|
@@ -132,7 +135,7 @@ function audioOf(text) {
|
|
|
132
135
|
if (blocked)
|
|
133
136
|
throw providerError({
|
|
134
137
|
kind: "refusal",
|
|
135
|
-
message: providerSaid("Google", "refused to speak this narration under its content rules", blocked,
|
|
138
|
+
message: providerSaid("Google", "refused to speak this narration under its content rules", blocked, `Reword that part of the script or article, or choose another voice service under Speakers (${editSettings.narration}).`),
|
|
136
139
|
});
|
|
137
140
|
for (const candidate of parsed.data.candidates ?? [])
|
|
138
141
|
for (const part of candidate.content?.parts ?? []) {
|
|
@@ -156,24 +159,10 @@ function streamOf(bytes) {
|
|
|
156
159
|
});
|
|
157
160
|
}
|
|
158
161
|
function keyOf(deps) {
|
|
159
|
-
|
|
160
|
-
const key = deps.key();
|
|
161
|
-
if (key === undefined || key === "") {
|
|
162
|
-
throw providerError({ kind: "missing_key", message: missingKey("Google") });
|
|
163
|
-
}
|
|
164
|
-
return key;
|
|
165
|
-
}
|
|
166
|
-
function kindOf(status) {
|
|
167
|
-
if (status === 401 || status === 403)
|
|
168
|
-
return "auth";
|
|
169
|
-
if (status === 429)
|
|
170
|
-
return "rate_limit";
|
|
171
|
-
if (status >= 500)
|
|
172
|
-
return "dropped";
|
|
173
|
-
return "other";
|
|
162
|
+
return requireKey(deps.key(), "Google");
|
|
174
163
|
}
|
|
175
164
|
async function failure(response, voiceId, next) {
|
|
176
|
-
const text = await response
|
|
165
|
+
const text = await failureText(response);
|
|
177
166
|
const parsed = errorBody.safeParse(safeJson(text));
|
|
178
167
|
// Through the redactor: an error body may quote the key back.
|
|
179
168
|
const detail = redact((parsed.success ? parsed.data.error.message : undefined) ??
|
|
@@ -181,26 +170,17 @@ async function failure(response, voiceId, next) {
|
|
|
181
170
|
// Google answers an unknown key with 400 API_KEY_INVALID rather than 401.
|
|
182
171
|
const badKey = response.status === 400 && text.includes("API_KEY_INVALID");
|
|
183
172
|
const status = badKey ? 401 : response.status;
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
});
|
|
198
|
-
}
|
|
199
|
-
function safeJson(text) {
|
|
200
|
-
try {
|
|
201
|
-
return JSON.parse(text);
|
|
202
|
-
}
|
|
203
|
-
catch {
|
|
204
|
-
return undefined;
|
|
205
|
-
}
|
|
173
|
+
return httpProviderError(response, badKey ? "auth" : kindOfStatus(response.status), httpFailure({
|
|
174
|
+
provider: "Google",
|
|
175
|
+
status,
|
|
176
|
+
detail,
|
|
177
|
+
next,
|
|
178
|
+
...(voiceId === undefined
|
|
179
|
+
? {}
|
|
180
|
+
: { subject: `narration request for voice "${voiceId}"`, fix: voiceFix(voiceId) }),
|
|
181
|
+
}), undefined,
|
|
182
|
+
// A narration request goes to the model's own address (models/<id>:generateContent).
|
|
183
|
+
badKey || voiceId === undefined
|
|
184
|
+
? undefined
|
|
185
|
+
: modelAccessOf(response.status, `${parsed.success ? (parsed.data.error.status ?? "") : ""} ${detail}`, true));
|
|
206
186
|
}
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
import { internalError } from "../../kernel/errors.js";
|
|
2
3
|
import { redact } from "../../kernel/log.js";
|
|
3
4
|
import { providerError } from "../../kernel/ports/model.js";
|
|
4
|
-
import {
|
|
5
|
+
import { editSettings } from "../../kernel/ports/settings-places.js";
|
|
6
|
+
import { httpFailure, noAudio, providerSaid, unreadable, voiceFix } from "../explain.js";
|
|
7
|
+
import { accessField } from "../model-access.js";
|
|
5
8
|
import { retryAfter } from "../retry-after.js";
|
|
6
9
|
const operationName = /^workspaces\/[A-Za-z0-9_-]+\/ttsAsyncJobs\/[A-Za-z0-9_-]+\/operations\/[A-Za-z0-9_-]+$/;
|
|
7
10
|
const operationSchema = z.object({
|
|
@@ -23,7 +26,7 @@ export async function* inworldAsync(deps, request, key) {
|
|
|
23
26
|
if (saved === undefined && request.text.length > 100_000) {
|
|
24
27
|
throw providerError({
|
|
25
28
|
kind: "unsupported",
|
|
26
|
-
message:
|
|
29
|
+
message: `This narration part is longer than the 100,000 characters Inworld takes at once (10,000 on On-Demand accounts). Set Chunking to Paragraph in ${editSettings.narration}, then use Try again.`,
|
|
27
30
|
});
|
|
28
31
|
}
|
|
29
32
|
const headers = { Authorization: `Basic ${key}`, "Content-Type": "application/json" };
|
|
@@ -137,6 +140,7 @@ async function check(response, key, voiceId) {
|
|
|
137
140
|
const detail = clean(await response.text().catch(() => ""), key);
|
|
138
141
|
const retryAfterMs = retryAfter(response.headers.get("retry-after"));
|
|
139
142
|
throw providerError({
|
|
143
|
+
...accessField(response.status, detail),
|
|
140
144
|
kind: response.status === 401 || response.status === 403
|
|
141
145
|
? "auth"
|
|
142
146
|
: response.status === 429
|