@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
|
@@ -1,10 +1,13 @@
|
|
|
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 { createRows, editSettings } from "../../kernel/ports/settings-places.js";
|
|
6
|
+
import { httpFailure, noImage, providerSaid, unreadable } from "../explain.js";
|
|
7
|
+
import { failureText, httpProviderError, kindOfStatus, requireKey, safeJson, } from "../http-failure.js";
|
|
8
|
+
import { modelAccessOf } from "../model-access.js";
|
|
6
9
|
import { downloadImage } from "./bytes.js";
|
|
7
|
-
import {
|
|
10
|
+
import { attachedPictures, promptFor } from "./reference.js";
|
|
8
11
|
import { dataUri, downloadVideo } from "./video.js";
|
|
9
12
|
// The HTTP gateway adapter for fal.ai: `fetch` and the downloader beside this file, no SDK.
|
|
10
13
|
// `@fal-ai/client` would buy queue polling, which only the video clips need and which is three
|
|
@@ -60,6 +63,7 @@ const editModels = [
|
|
|
60
63
|
function editEndpoint(model) {
|
|
61
64
|
return editModels.includes(model) ? `${model}/edit` : undefined;
|
|
62
65
|
}
|
|
66
|
+
export const falEditRefusal = "This fal.ai model can't edit a picture. Choose FLUX.2 or Nano Banana 2 on fal.ai, or Codex CLI, OpenAI or Google, under Made with … · change.";
|
|
63
67
|
// Image-to-video runs on fal's queue, not the synchronous host: a clip takes one to five
|
|
64
68
|
// minutes, and fal documents the queue as the way to call anything that slow. A request is
|
|
65
69
|
// submitted, its status polled until it completes, and its answer fetched from the links the
|
|
@@ -104,19 +108,21 @@ export function falImage(deps) {
|
|
|
104
108
|
// `image_urls`; only the models that have one are marked as taking a reference.
|
|
105
109
|
// Cast pictures ride the same list; a model without an edit endpoint gets the cast in
|
|
106
110
|
// words instead, since only the establishing image is something the user turned on.
|
|
107
|
-
const pictures =
|
|
111
|
+
const pictures = attachedPictures(req);
|
|
108
112
|
const edit = pictures.length === 0 ? undefined : editEndpoint(req.model);
|
|
113
|
+
if (req.edit !== undefined && edit === undefined)
|
|
114
|
+
throw providerError({ kind: "unsupported", message: falEditRefusal });
|
|
109
115
|
if (req.reference !== undefined && edit === undefined)
|
|
110
116
|
throw providerError({
|
|
111
117
|
kind: "unsupported",
|
|
112
|
-
message:
|
|
118
|
+
message: `This fal.ai model can't use an establishing image as a reference. Choose FLUX.2 or Nano Banana 2 as the image model in ${createRows.images} or ${editSettings.images}, or set Establishing image to Off there.`,
|
|
113
119
|
});
|
|
114
120
|
const response = await deps.fetch(`${falBase}/${edit ?? req.model}`, {
|
|
115
121
|
method: "POST",
|
|
116
122
|
signal: req.signal,
|
|
117
123
|
headers: { Authorization: `Key ${keyOf(deps)}`, "Content-Type": "application/json" },
|
|
118
124
|
body: JSON.stringify({
|
|
119
|
-
prompt:
|
|
125
|
+
prompt: promptFor(req.prompt, req, edit === undefined ? 0 : pictures.length),
|
|
120
126
|
...(edit === undefined
|
|
121
127
|
? {}
|
|
122
128
|
: { image_urls: pictures.map((picture) => dataUri(picture.image)) }),
|
|
@@ -129,7 +135,7 @@ export function falImage(deps) {
|
|
|
129
135
|
}),
|
|
130
136
|
});
|
|
131
137
|
if (!response.ok) {
|
|
132
|
-
throw await failure(response);
|
|
138
|
+
throw await failure(response, "image request", true);
|
|
133
139
|
}
|
|
134
140
|
const answer = parse(await response.text());
|
|
135
141
|
refused(answer, req.prompt);
|
|
@@ -162,7 +168,7 @@ export function falImage(deps) {
|
|
|
162
168
|
}),
|
|
163
169
|
});
|
|
164
170
|
if (!submitted.ok)
|
|
165
|
-
throw await failure(submitted, "video clip request");
|
|
171
|
+
throw await failure(submitted, "video clip request", true);
|
|
166
172
|
const links = read(queued, await submitted.text());
|
|
167
173
|
for (;;) {
|
|
168
174
|
const status = await deps.fetch(links.status_url, { signal: req.signal, headers });
|
|
@@ -172,7 +178,7 @@ export function falImage(deps) {
|
|
|
172
178
|
if (current.error)
|
|
173
179
|
throw providerError({
|
|
174
180
|
kind: "other",
|
|
175
|
-
message: providerSaid("fal.ai", "could not make the video clip", redact(current.error),
|
|
181
|
+
message: providerSaid("fal.ai", "could not make the video clip", redact(current.error), `Use Try again; if it keeps happening, choose another image-to-video model under Animate images in ${editSettings.look}.`),
|
|
176
182
|
});
|
|
177
183
|
if (current.status === "COMPLETED")
|
|
178
184
|
break;
|
|
@@ -198,12 +204,7 @@ function read(schema, text) {
|
|
|
198
204
|
return parsed.data;
|
|
199
205
|
}
|
|
200
206
|
function keyOf(deps) {
|
|
201
|
-
|
|
202
|
-
const key = deps.key();
|
|
203
|
-
if (key === undefined || key === "") {
|
|
204
|
-
throw providerError({ kind: "missing_key", message: missingKey("fal.ai") });
|
|
205
|
-
}
|
|
206
|
-
return key;
|
|
207
|
+
return requireKey(deps.key(), "fal.ai");
|
|
207
208
|
}
|
|
208
209
|
// A content-policy refusal is final, named here and made terminal by the wrapper. fal declines
|
|
209
210
|
// inside a 200 - the safety checker flags the image and hands back a blank one. With no
|
|
@@ -213,41 +214,16 @@ function refused(answer, prompt) {
|
|
|
213
214
|
if (flags.length > 0 && flags.every((flagged) => flagged)) {
|
|
214
215
|
throw providerError({
|
|
215
216
|
kind: "refusal",
|
|
216
|
-
message: `fal.ai's safety checker blocked the image for this prompt: "${redact(prompt)}". Reword the image prompt in
|
|
217
|
+
message: `fal.ai's safety checker blocked the image for this prompt: "${redact(prompt)}". Reword the image prompt in ${editSettings.images}, or choose another image service there.`,
|
|
217
218
|
});
|
|
218
219
|
}
|
|
219
220
|
}
|
|
220
|
-
//
|
|
221
|
-
function
|
|
222
|
-
|
|
223
|
-
return "auth";
|
|
224
|
-
}
|
|
225
|
-
if (status === 429) {
|
|
226
|
-
return "rate_limit";
|
|
227
|
-
}
|
|
228
|
-
// ceiling: everything else is `other` and is retried, so a 422 naming an input this model
|
|
229
|
-
// does not take fails the same way four times over. A terminal "this will never work" kind
|
|
230
|
-
// has to reach the port's error contract first, which is not this adapter's to widen.
|
|
231
|
-
// The provider's own server failed; the same request may well succeed later.
|
|
232
|
-
if (status >= 500)
|
|
233
|
-
return "dropped";
|
|
234
|
-
return "other";
|
|
235
|
-
}
|
|
236
|
-
async function failure(response, subject = "image request") {
|
|
237
|
-
const text = await response.text().catch(() => "");
|
|
221
|
+
// `atModel`: the request went to the model's own address, so a 404 or 403 is about the model.
|
|
222
|
+
async function failure(response, subject = "image request", atModel = false) {
|
|
223
|
+
const text = await failureText(response);
|
|
238
224
|
// The provider's own words, through the redactor - an error body may quote the key back.
|
|
239
225
|
const message = redact(detailOf(text) || response.statusText);
|
|
240
|
-
|
|
241
|
-
return providerError({
|
|
242
|
-
kind: kindOf(response.status),
|
|
243
|
-
message: httpFailure({
|
|
244
|
-
provider: "fal.ai",
|
|
245
|
-
status: response.status,
|
|
246
|
-
detail: message,
|
|
247
|
-
subject,
|
|
248
|
-
}),
|
|
249
|
-
...(retryAfterMs === undefined ? {} : { retryAfterMs }),
|
|
250
|
-
});
|
|
226
|
+
return httpProviderError(response, kindOfStatus(response.status), httpFailure({ provider: "fal.ai", status: response.status, detail: message, subject }), undefined, modelAccessOf(response.status, text, atModel));
|
|
251
227
|
}
|
|
252
228
|
function detailOf(text) {
|
|
253
229
|
const parsed = errorBody.safeParse(safeJson(text));
|
|
@@ -270,11 +246,3 @@ function parse(text) {
|
|
|
270
246
|
}
|
|
271
247
|
return parsed.data;
|
|
272
248
|
}
|
|
273
|
-
function safeJson(text) {
|
|
274
|
-
try {
|
|
275
|
-
return JSON.parse(text);
|
|
276
|
-
}
|
|
277
|
-
catch {
|
|
278
|
-
return undefined;
|
|
279
|
-
}
|
|
280
|
-
}
|
|
@@ -1,11 +1,13 @@
|
|
|
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 {
|
|
5
|
-
import {
|
|
4
|
+
import { editSettings } from "../../kernel/ports/settings-places.js";
|
|
5
|
+
import { httpFailure, noImage, quoted, refusedImage, unreadable } from "../explain.js";
|
|
6
|
+
import { failureText, httpProviderError, kindOfStatus, requireKey, safeJson, } from "../http-failure.js";
|
|
7
|
+
import { modelAccessOf } from "../model-access.js";
|
|
6
8
|
import { describeBytes, sniffImage } from "./bytes.js";
|
|
7
9
|
import { discoverGoogleImages } from "./models.js";
|
|
8
|
-
import {
|
|
10
|
+
import { attachedPictures, promptFor } from "./reference.js";
|
|
9
11
|
// The HTTP gateway adapter for Google's own image generation, billed to a Gemini API key
|
|
10
12
|
// rather than to a host reselling the same models. Like the OpenAI one it hands back the
|
|
11
13
|
// bytes with the call, so there is no link to follow.
|
|
@@ -65,15 +67,15 @@ export function googleImage(deps) {
|
|
|
65
67
|
model: req.model,
|
|
66
68
|
// With an establishing image the input is two parts, the image first; the Gemini
|
|
67
69
|
// image models draw with an input image as their reference.
|
|
68
|
-
input:
|
|
70
|
+
input: attachedPictures(req).length === 0
|
|
69
71
|
? req.prompt
|
|
70
72
|
: [
|
|
71
|
-
...
|
|
73
|
+
...attachedPictures(req).map(({ image }) => ({
|
|
72
74
|
type: "image",
|
|
73
75
|
mime_type: image.mime,
|
|
74
76
|
data: Buffer.from(image.bytes).toString("base64"),
|
|
75
77
|
})),
|
|
76
|
-
{ type: "text", text:
|
|
78
|
+
{ type: "text", text: promptFor(req.prompt, req) },
|
|
77
79
|
],
|
|
78
80
|
// The stage sends Number as that many independent calls, one piece each, so one
|
|
79
81
|
// image per request is what it asks for. Nothing about style is set: the stage
|
|
@@ -117,18 +119,13 @@ function decode(part) {
|
|
|
117
119
|
const claimed = part.mime_type ?? "nothing";
|
|
118
120
|
throw providerError({
|
|
119
121
|
kind: "other",
|
|
120
|
-
message: `Google sent back something that is not a PNG or JPEG image (labelled ${claimed}, but ${describeBytes(bytes)}). Use Try again; if it keeps happening, choose another image model in
|
|
122
|
+
message: `Google sent back something that is not a PNG or JPEG image (labelled ${claimed}, but ${describeBytes(bytes)}). Use Try again; if it keeps happening, choose another image model in ${editSettings.images}.`,
|
|
121
123
|
});
|
|
122
124
|
}
|
|
123
125
|
return { bytes, mime };
|
|
124
126
|
}
|
|
125
127
|
function keyOf(deps) {
|
|
126
|
-
|
|
127
|
-
const key = deps.key();
|
|
128
|
-
if (key === undefined || key === "") {
|
|
129
|
-
throw providerError({ kind: "missing_key", message: missingKey("Google") });
|
|
130
|
-
}
|
|
131
|
-
return key;
|
|
128
|
+
return requireKey(deps.key(), "Google");
|
|
132
129
|
}
|
|
133
130
|
// Only the adapter sees the vendor's status code, so only the adapter names the kind.
|
|
134
131
|
function kindOf(status, named, message) {
|
|
@@ -141,27 +138,16 @@ function kindOf(status, named, message) {
|
|
|
141
138
|
if (status === 400 && refusalWords.test(message)) {
|
|
142
139
|
return "refusal";
|
|
143
140
|
}
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
// in the message. Zero allocated capacity cannot be fixed by waiting and retrying.
|
|
150
|
-
if (/quota exceeded for metric:[^\r\n]*?\blimit:\s*0\s*(?:,|$)/im.test(message)) {
|
|
151
|
-
return "unsupported";
|
|
152
|
-
}
|
|
153
|
-
return "rate_limit";
|
|
141
|
+
// Interactions wraps quota failures in a string-coded error and exposes the limit
|
|
142
|
+
// in the message. Zero allocated capacity cannot be fixed by waiting and retrying.
|
|
143
|
+
if (status === 429 &&
|
|
144
|
+
/quota exceeded for metric:[^\r\n]*?\blimit:\s*0\s*(?:,|$)/im.test(message)) {
|
|
145
|
+
return "unsupported";
|
|
154
146
|
}
|
|
155
|
-
|
|
156
|
-
// fails the same way four times over. A terminal "this will never work" kind has to reach
|
|
157
|
-
// the port's error contract first, which is not this adapter's to widen.
|
|
158
|
-
// The provider's own server failed; the same request may well succeed later.
|
|
159
|
-
if (status >= 500)
|
|
160
|
-
return "dropped";
|
|
161
|
-
return "other";
|
|
147
|
+
return kindOfStatus(status);
|
|
162
148
|
}
|
|
163
149
|
async function failure(response) {
|
|
164
|
-
const text = await response
|
|
150
|
+
const text = await failureText(response);
|
|
165
151
|
const parsed = errorBody.safeParse(safeJson(text));
|
|
166
152
|
// The provider's own words, through the redactor - an error body may quote the key back.
|
|
167
153
|
const named = parsed.success ? parsed.data.error.status : undefined;
|
|
@@ -170,24 +156,23 @@ async function failure(response) {
|
|
|
170
156
|
const delay = parsed.success
|
|
171
157
|
? parsed.data.error.details?.find((one) => one["@type"] === "type.googleapis.com/google.rpc.RetryInfo")?.retryDelay
|
|
172
158
|
: undefined;
|
|
173
|
-
const retryAfterMs = retryAfter(response.headers.get("retry-after")) ?? googleRetryDelay(delay, message);
|
|
174
159
|
const detail = message || response.statusText;
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
:
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
});
|
|
160
|
+
const refused = kind === "refusal" && refusalWords.test(message);
|
|
161
|
+
return httpProviderError(response, kind, kind === "unsupported"
|
|
162
|
+
? `Google gives this API key no image quota for this model${quoted(`error ${String(response.status)}`, detail)}. Retrying will not help: turn on billing for the key's project in Google AI Studio, or choose another image service in ${editSettings.images}.`
|
|
163
|
+
: // PERMISSION_DENIED and FAILED_PRECONDITION also cover keys without access, billing
|
|
164
|
+
// and region limits, so they read as a content refusal only when Google says so.
|
|
165
|
+
refused
|
|
166
|
+
? refusedImage("Google", detail)
|
|
167
|
+
: httpFailure({
|
|
168
|
+
provider: "Google",
|
|
169
|
+
status: response.status,
|
|
170
|
+
detail,
|
|
171
|
+
subject: "image request",
|
|
172
|
+
}), googleRetryDelay(delay, message),
|
|
173
|
+
// A key that reads the model list but is denied or told "not found" here is denied the
|
|
174
|
+
// model the request names: Google answers a bad key with 400 API_KEY_INVALID.
|
|
175
|
+
refused ? undefined : modelAccessOf(response.status, `${named ?? ""} ${message}`, true));
|
|
191
176
|
}
|
|
192
177
|
function googleRetryDelay(delay, message) {
|
|
193
178
|
const seconds = delay?.match(/^(\d+(?:\.\d+)?)s$/)?.[1] ??
|
|
@@ -207,11 +192,3 @@ function parse(text) {
|
|
|
207
192
|
}
|
|
208
193
|
return parsed.data;
|
|
209
194
|
}
|
|
210
|
-
function safeJson(text) {
|
|
211
|
-
try {
|
|
212
|
-
return JSON.parse(text);
|
|
213
|
-
}
|
|
214
|
-
catch {
|
|
215
|
-
return undefined;
|
|
216
|
-
}
|
|
217
|
-
}
|
|
@@ -66,13 +66,13 @@ function requireKey(deps) {
|
|
|
66
66
|
if (key === undefined || key === "")
|
|
67
67
|
throw providerError({
|
|
68
68
|
kind: "missing_key",
|
|
69
|
-
message: "Save this provider's API key in Settings →
|
|
69
|
+
message: "Save this provider's API key in Settings → Keys & services to load its models.",
|
|
70
70
|
});
|
|
71
71
|
return key;
|
|
72
72
|
}
|
|
73
73
|
function unavailable() {
|
|
74
74
|
return providerError({
|
|
75
75
|
kind: "other",
|
|
76
|
-
message: "Slopify could not load this provider's model list. Check the API key in Settings →
|
|
76
|
+
message: "Slopify could not load this provider's model list. Check the API key in Settings → Keys & services and your internet connection, then refresh the list.",
|
|
77
77
|
});
|
|
78
78
|
}
|
|
@@ -1,11 +1,13 @@
|
|
|
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 {
|
|
5
|
-
import {
|
|
4
|
+
import { editSettings } from "../../kernel/ports/settings-places.js";
|
|
5
|
+
import { httpFailure, noImage, refusedImage, unreadable } from "../explain.js";
|
|
6
|
+
import { failureText, httpProviderError, kindOfStatus, requireKey, safeJson, } from "../http-failure.js";
|
|
7
|
+
import { modelAccessOf } from "../model-access.js";
|
|
6
8
|
import { describeBytes, sniffImage } from "./bytes.js";
|
|
7
9
|
import { discoverOpenAiImages } from "./models.js";
|
|
8
|
-
import {
|
|
10
|
+
import { attachedPictures, promptFor } from "./reference.js";
|
|
9
11
|
// The HTTP gateway adapter for OpenAI's images endpoint: the platform's own `fetch` and
|
|
10
12
|
// nothing else, because the whole call is one request. Unlike fal and Replicate this one
|
|
11
13
|
// hands back the image itself - a GPT image model always answers with base64, never a URL -
|
|
@@ -56,7 +58,7 @@ export function openAiImage(deps) {
|
|
|
56
58
|
id: "openai-image",
|
|
57
59
|
models: () => discoverOpenAiImages(deps),
|
|
58
60
|
generate: async (req) => {
|
|
59
|
-
const pictures =
|
|
61
|
+
const pictures = attachedPictures(req);
|
|
60
62
|
const response = pictures.length === 0
|
|
61
63
|
? await deps.fetch(`${openAiImagesBase}/images/generations`, {
|
|
62
64
|
method: "POST",
|
|
@@ -96,11 +98,11 @@ export function openAiImage(deps) {
|
|
|
96
98
|
};
|
|
97
99
|
}
|
|
98
100
|
// The edits endpoint takes several input images as repeated `image[]` parts: the establishing
|
|
99
|
-
// image first, then the cast pictures.
|
|
101
|
+
// image (or, for a design's edit, the picture to change) first, then the cast pictures.
|
|
100
102
|
function editForm(req, pictures) {
|
|
101
103
|
const form = new FormData();
|
|
102
104
|
form.set("model", req.model);
|
|
103
|
-
form.set("prompt",
|
|
105
|
+
form.set("prompt", promptFor(req.prompt, req));
|
|
104
106
|
form.set("n", "1");
|
|
105
107
|
form.set("size", sizeFor(req.model, req.aspect));
|
|
106
108
|
for (const [index, { image }] of pictures.entries())
|
|
@@ -116,57 +118,37 @@ function decode(b64) {
|
|
|
116
118
|
if (mime === undefined) {
|
|
117
119
|
throw providerError({
|
|
118
120
|
kind: "other",
|
|
119
|
-
message: `OpenAI sent back something that is not a PNG or JPEG image (${describeBytes(bytes)}). Use Try again; if it keeps happening, choose another image model in
|
|
121
|
+
message: `OpenAI sent back something that is not a PNG or JPEG image (${describeBytes(bytes)}). Use Try again; if it keeps happening, choose another image model in ${editSettings.images}.`,
|
|
120
122
|
});
|
|
121
123
|
}
|
|
122
124
|
return { bytes, mime };
|
|
123
125
|
}
|
|
124
126
|
function keyOf(deps) {
|
|
125
|
-
|
|
126
|
-
const key = deps.key();
|
|
127
|
-
if (key === undefined || key === "") {
|
|
128
|
-
throw providerError({ kind: "missing_key", message: missingKey("OpenAI") });
|
|
129
|
-
}
|
|
130
|
-
return key;
|
|
127
|
+
return requireKey(deps.key(), "OpenAI");
|
|
131
128
|
}
|
|
132
129
|
// Only the adapter sees the vendor's status code, so only the adapter names the kind.
|
|
133
130
|
function kindOf(status, code) {
|
|
134
131
|
if (code !== undefined && code !== null && refusalCodes.includes(code)) {
|
|
135
132
|
return "refusal";
|
|
136
133
|
}
|
|
137
|
-
|
|
138
|
-
return "auth";
|
|
139
|
-
}
|
|
140
|
-
if (status === 429) {
|
|
141
|
-
return "rate_limit";
|
|
142
|
-
}
|
|
143
|
-
// ceiling: everything else is `other` and is retried, so a prompt past the model's length
|
|
144
|
-
// limit fails the same way four times over. A terminal "this will never work" kind has to
|
|
145
|
-
// reach the port's error contract first, which is not this adapter's to widen.
|
|
146
|
-
// The provider's own server failed; the same request may well succeed later.
|
|
147
|
-
if (status >= 500)
|
|
148
|
-
return "dropped";
|
|
149
|
-
return "other";
|
|
134
|
+
return kindOfStatus(status);
|
|
150
135
|
}
|
|
151
136
|
async function failure(response) {
|
|
152
|
-
const text = await response
|
|
137
|
+
const text = await failureText(response);
|
|
153
138
|
const parsed = errorBody.safeParse(safeJson(text));
|
|
154
139
|
// The provider's own words, through the redactor - an error body may quote the key back.
|
|
155
140
|
const message = redact(parsed.success ? parsed.data.error.message : text.trim() || response.statusText);
|
|
156
|
-
const retryAfterMs = retryAfter(response.headers.get("retry-after"));
|
|
157
141
|
const kind = kindOf(response.status, parsed.success ? parsed.data.error.code : undefined);
|
|
158
|
-
return
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
:
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
...(retryAfterMs === undefined ? {} : { retryAfterMs }),
|
|
169
|
-
});
|
|
142
|
+
return httpProviderError(response, kind, kind === "refusal"
|
|
143
|
+
? refusedImage("OpenAI", message)
|
|
144
|
+
: httpFailure({
|
|
145
|
+
provider: "OpenAI",
|
|
146
|
+
status: response.status,
|
|
147
|
+
detail: message,
|
|
148
|
+
subject: "image request",
|
|
149
|
+
}), undefined, kind === "refusal"
|
|
150
|
+
? undefined
|
|
151
|
+
: modelAccessOf(response.status, `${parsed.success ? (parsed.data.error.code ?? "") : ""} ${message}`));
|
|
170
152
|
}
|
|
171
153
|
function parse(text) {
|
|
172
154
|
const parsed = generated.safeParse(safeJson(text));
|
|
@@ -178,11 +160,3 @@ function parse(text) {
|
|
|
178
160
|
}
|
|
179
161
|
return parsed.data;
|
|
180
162
|
}
|
|
181
|
-
function safeJson(text) {
|
|
182
|
-
try {
|
|
183
|
-
return JSON.parse(text);
|
|
184
|
-
}
|
|
185
|
-
catch {
|
|
186
|
-
return undefined;
|
|
187
|
-
}
|
|
188
|
-
}
|
|
@@ -39,3 +39,39 @@ export function withReferences(prompt, req, limit = Number.POSITIVE_INFINITY) {
|
|
|
39
39
|
function describe(description) {
|
|
40
40
|
return description.trim() === "" ? "" : ` (${description.trim()})`;
|
|
41
41
|
}
|
|
42
|
+
// What an edit model is told about the first attached picture: it is the canvas to change,
|
|
43
|
+
// the opposite of a reference.
|
|
44
|
+
export const editNote = "Change the first attached image as follows. Keep everything the instruction does not mention exactly as it is: people, faces, composition and framing.";
|
|
45
|
+
// The pictures an edit request attaches: the picture to change, then each cast member's
|
|
46
|
+
// pictures. An edit never sends an establishing image.
|
|
47
|
+
export function editPictures(req) {
|
|
48
|
+
return [
|
|
49
|
+
...(req.edit === undefined ? [] : [{ image: req.edit.source }]),
|
|
50
|
+
...(req.cast ?? []).flatMap((member) => member.images.map((image) => ({ image, member: member.name }))),
|
|
51
|
+
];
|
|
52
|
+
}
|
|
53
|
+
// The prompt an edit request sends with the first `limit` of `editPictures(req)` attached.
|
|
54
|
+
export function withEditInstruction(instruction, req, limit = Number.POSITIVE_INFINITY) {
|
|
55
|
+
const sent = editPictures(req).slice(0, limit);
|
|
56
|
+
const lines = [editNote];
|
|
57
|
+
for (const [index, picture] of sent.entries()) {
|
|
58
|
+
const member = req.cast?.find((row) => row.name === picture.member);
|
|
59
|
+
if (member !== undefined)
|
|
60
|
+
lines.push(`Image ${String(index + 1)} shows ${member.name}${describe(member.description)}: draw ${member.name} to look exactly like this.`);
|
|
61
|
+
}
|
|
62
|
+
const shown = new Set(sent.flatMap((picture) => picture.member ?? []));
|
|
63
|
+
for (const member of req.cast ?? [])
|
|
64
|
+
if (!shown.has(member.name))
|
|
65
|
+
lines.push(`${member.name} appears in this image${describe(member.description)}.`);
|
|
66
|
+
return `${lines.join("\n")}\n\n${instruction}`;
|
|
67
|
+
}
|
|
68
|
+
// What an adapter attaches and says: an edit's pictures and instruction, or, for every other
|
|
69
|
+
// request, exactly what it always attached and said.
|
|
70
|
+
export function attachedPictures(req) {
|
|
71
|
+
return req.edit === undefined ? referencePictures(req) : editPictures(req);
|
|
72
|
+
}
|
|
73
|
+
export function promptFor(prompt, req, limit = Number.POSITIVE_INFINITY) {
|
|
74
|
+
return req.edit === undefined
|
|
75
|
+
? withReferences(prompt, req, limit)
|
|
76
|
+
: withEditInstruction(prompt, req, limit);
|
|
77
|
+
}
|
|
@@ -1,8 +1,10 @@
|
|
|
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 {
|
|
5
|
-
import {
|
|
4
|
+
import { createRows, editSettings } from "../../kernel/ports/settings-places.js";
|
|
5
|
+
import { httpFailure, noImage, providerSaid, refusedImage, unreadable } from "../explain.js";
|
|
6
|
+
import { failureText, httpProviderError, kindOfStatus, requireKey, safeJson, } from "../http-failure.js";
|
|
7
|
+
import { modelAccessOf } from "../model-access.js";
|
|
6
8
|
import { downloadImage } from "./bytes.js";
|
|
7
9
|
import { withReferences } from "./reference.js";
|
|
8
10
|
import { dataUri, downloadVideo } from "./video.js";
|
|
@@ -37,6 +39,7 @@ const errorBody = z.object({ detail: z.string().optional(), title: z.string().op
|
|
|
37
39
|
// `canceled` cannot happen here - nothing cancels a prediction this app made - but reading
|
|
38
40
|
// it as terminal beats polling forever.
|
|
39
41
|
const settled = ["succeeded", "failed", "canceled"];
|
|
42
|
+
export const replicateEditRefusal = "Replicate's image models can't edit a picture. Choose Codex CLI, OpenAI, Google, or FLUX.2 or Nano Banana 2 on fal.ai under Made with … · change.";
|
|
40
43
|
export function replicateImage(deps) {
|
|
41
44
|
return {
|
|
42
45
|
id: "replicate",
|
|
@@ -44,10 +47,12 @@ export function replicateImage(deps) {
|
|
|
44
47
|
generate: async (req) => {
|
|
45
48
|
// The Replicate models listed take no input image to draw from (the FLUX image inputs
|
|
46
49
|
// copy the picture's composition), so an establishing image is refused, not dropped.
|
|
50
|
+
if (req.edit !== undefined)
|
|
51
|
+
throw providerError({ kind: "unsupported", message: replicateEditRefusal });
|
|
47
52
|
if (req.reference !== undefined)
|
|
48
53
|
throw providerError({
|
|
49
54
|
kind: "unsupported",
|
|
50
|
-
message:
|
|
55
|
+
message: `Replicate's image models can't use an establishing image as a reference. Choose Codex CLI, OpenAI, Google or fal.ai as the image service in ${createRows.images} or ${editSettings.images}, or set Establishing image to Off there.`,
|
|
51
56
|
});
|
|
52
57
|
const response = await deps.fetch(`${replicateBase}/models/${req.model}/predictions`, {
|
|
53
58
|
method: "POST",
|
|
@@ -70,7 +75,7 @@ export function replicateImage(deps) {
|
|
|
70
75
|
}),
|
|
71
76
|
});
|
|
72
77
|
if (!response.ok) {
|
|
73
|
-
throw await failure(response);
|
|
78
|
+
throw await failure(response, "image request", true);
|
|
74
79
|
}
|
|
75
80
|
const url = await settle(deps, parse(await response.text()), req.signal);
|
|
76
81
|
// The download rides inside the attempt: a link that 404s is a failed attempt.
|
|
@@ -100,7 +105,7 @@ export function replicateImage(deps) {
|
|
|
100
105
|
}),
|
|
101
106
|
});
|
|
102
107
|
if (!response.ok)
|
|
103
|
-
throw await failure(response, "video clip request");
|
|
108
|
+
throw await failure(response, "video clip request", true);
|
|
104
109
|
const url = await settle(deps, parse(await response.text()), req.signal);
|
|
105
110
|
return await downloadVideo({
|
|
106
111
|
fetch: deps.fetch,
|
|
@@ -168,50 +173,25 @@ function declined(current) {
|
|
|
168
173
|
kind: refusal ? "refusal" : "other",
|
|
169
174
|
message: refusal
|
|
170
175
|
? refusedImage("Replicate", message)
|
|
171
|
-
: providerSaid("Replicate", "could not make the image", message,
|
|
176
|
+
: providerSaid("Replicate", "could not make the image", message, `Use Try again; if it keeps happening, reword the image prompt in ${editSettings.images} or choose another image model there.`),
|
|
172
177
|
});
|
|
173
178
|
}
|
|
174
179
|
function auth(deps) {
|
|
175
|
-
|
|
176
|
-
const key = deps.key();
|
|
177
|
-
if (key === undefined || key === "") {
|
|
178
|
-
throw providerError({ kind: "missing_key", message: missingKey("Replicate") });
|
|
179
|
-
}
|
|
180
|
-
return { Authorization: `Bearer ${key}` };
|
|
180
|
+
return { Authorization: `Bearer ${requireKey(deps.key(), "Replicate")}` };
|
|
181
181
|
}
|
|
182
|
-
//
|
|
183
|
-
function
|
|
184
|
-
|
|
185
|
-
return "auth";
|
|
186
|
-
}
|
|
187
|
-
if (status === 429) {
|
|
188
|
-
return "rate_limit";
|
|
189
|
-
}
|
|
190
|
-
// ceiling: everything else is `other` and is retried, so a 402 with no credit left fails the
|
|
191
|
-
// same way four times over. A terminal "this will never work" kind has to reach the port's
|
|
192
|
-
// error contract first, which is not this adapter's to widen.
|
|
193
|
-
// The provider's own server failed; the same request may well succeed later.
|
|
194
|
-
if (status >= 500)
|
|
195
|
-
return "dropped";
|
|
196
|
-
return "other";
|
|
197
|
-
}
|
|
198
|
-
async function failure(response, subject = "image request") {
|
|
199
|
-
const text = await response.text().catch(() => "");
|
|
182
|
+
// `atModel`: the request went to the model's own address, so a 404 or 403 is about the model.
|
|
183
|
+
async function failure(response, subject = "image request", atModel = false) {
|
|
184
|
+
const text = await failureText(response);
|
|
200
185
|
const parsed = errorBody.safeParse(safeJson(text));
|
|
201
186
|
// The provider's own words, through the redactor - an error body may quote the key back.
|
|
202
187
|
const detail = parsed.success ? (parsed.data.detail ?? parsed.data.title) : undefined;
|
|
203
188
|
const message = redact(detail ?? text.trim());
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
detail: message || response.statusText,
|
|
211
|
-
subject,
|
|
212
|
-
}),
|
|
213
|
-
...(retryAfterMs === undefined ? {} : { retryAfterMs }),
|
|
214
|
-
});
|
|
189
|
+
return httpProviderError(response, kindOfStatus(response.status), httpFailure({
|
|
190
|
+
provider: "Replicate",
|
|
191
|
+
status: response.status,
|
|
192
|
+
detail: message || response.statusText,
|
|
193
|
+
subject,
|
|
194
|
+
}), undefined, modelAccessOf(response.status, text, atModel));
|
|
215
195
|
}
|
|
216
196
|
function parse(text) {
|
|
217
197
|
const parsed = prediction.safeParse(safeJson(text));
|
|
@@ -223,11 +203,3 @@ function parse(text) {
|
|
|
223
203
|
}
|
|
224
204
|
return parsed.data;
|
|
225
205
|
}
|
|
226
|
-
function safeJson(text) {
|
|
227
|
-
try {
|
|
228
|
-
return JSON.parse(text);
|
|
229
|
-
}
|
|
230
|
-
catch {
|
|
231
|
-
return undefined;
|
|
232
|
-
}
|
|
233
|
-
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { providerError } from "../../kernel/ports/model.js";
|
|
2
|
+
import { editSettings } from "../../kernel/ports/settings-places.js";
|
|
2
3
|
import { describeBytes } from "./bytes.js";
|
|
3
4
|
// What the two image-to-video adapters share: the still goes up inline as a data URI (the
|
|
4
5
|
// render sends a small JPEG, `slices/rebuild/runtime-animate.ts`), and the clip comes back
|
|
@@ -22,7 +23,7 @@ export async function downloadVideo(download) {
|
|
|
22
23
|
if (!sniffVideo(bytes))
|
|
23
24
|
throw providerError({
|
|
24
25
|
kind: "other",
|
|
25
|
-
message: `${download.provider} sent back something that is not an MP4 video clip (${describeBytes(bytes)}). Use Try again; if it keeps happening, choose another image-to-video model under Animate images in
|
|
26
|
+
message: `${download.provider} sent back something that is not an MP4 video clip (${describeBytes(bytes)}). Use Try again; if it keeps happening, choose another image-to-video model under Animate images in ${editSettings.look}.`,
|
|
26
27
|
});
|
|
27
28
|
return { bytes, mime: "video/mp4" };
|
|
28
29
|
}
|