@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,6 +1,8 @@
|
|
|
1
1
|
import { rmSync, statSync } from "node:fs";
|
|
2
2
|
import { dirname, join } from "node:path";
|
|
3
3
|
import { z } from "zod";
|
|
4
|
+
import { internalError } from "../../kernel/errors.js";
|
|
5
|
+
import { editSettings } from "../../kernel/ports/settings-places.js";
|
|
4
6
|
import { referenceKey, thumbnailVariant } from "../admission/model.js";
|
|
5
7
|
import { plainText } from "../article/plain.js";
|
|
6
8
|
import { splitEndMatter } from "../article/split.js";
|
|
@@ -9,6 +11,8 @@ import { levelSentences } from "../loudness/sentence-level.js";
|
|
|
9
11
|
import { cleanPieces } from "../narration/clean-pieces.js";
|
|
10
12
|
import { joinNarration } from "../narration/concat.js";
|
|
11
13
|
import { applyPauses, planPieces } from "../narration/pauses.js";
|
|
14
|
+
import { assetPath } from "../revisions/mutation-assets.js";
|
|
15
|
+
import { isDonePiece } from "../revisions/view.js";
|
|
12
16
|
import { allocateAsset, discardPreparedAssets, sealAsset } from "../storage/assets.js";
|
|
13
17
|
import { outputPath } from "../storage/layout.js";
|
|
14
18
|
import { probeDurationMs, runFfmpeg } from "../video/ffmpeg.js";
|
|
@@ -17,19 +21,18 @@ import { breathsAsked, deEssAsked } from "./recipe-breaths.js";
|
|
|
17
21
|
import { levelOperation, sentencesAsked } from "./recipe-loudness.js";
|
|
18
22
|
import { executeFigureCard } from "./runtime-figure-card.js";
|
|
19
23
|
import { publishNarrationText } from "./runtime-narration-text.js";
|
|
20
|
-
import { executionPlan, executionView,
|
|
24
|
+
import { executionPlan, executionView, workCatalogue } from "./runtime-plan.js";
|
|
21
25
|
import { preparedResult, preparedText, preparedTexts, publishResult, } from "./runtime-publication.js";
|
|
26
|
+
import { pieceAlreadyDone } from "./work-records.js";
|
|
22
27
|
export async function executeLocalRecipe(deps, context, piece) {
|
|
23
|
-
if (deps.db
|
|
24
|
-
.prepare("SELECT state FROM revision_work_pieces WHERE id=? AND work_id=?")
|
|
25
|
-
.get(piece.id, context.work.workId)?.state === "done")
|
|
28
|
+
if (pieceAlreadyDone(deps.db, context.work.workId, piece.id))
|
|
26
29
|
return "done";
|
|
27
30
|
if (!context.maySubmit(piece.id))
|
|
28
31
|
return "held";
|
|
29
32
|
const input = piece.input;
|
|
30
33
|
if (input.kind === "provided") {
|
|
31
34
|
if (input.assetId === null)
|
|
32
|
-
throw new Error("A file you uploaded for this project is missing. Upload it again in Edit
|
|
35
|
+
throw new Error("A file you uploaded for this project is missing. Upload it again in Edit settings, then Try again.");
|
|
33
36
|
const row = z
|
|
34
37
|
.object({ id: z.string(), project_id: z.string(), path: z.string(), created_at: z.string() })
|
|
35
38
|
.parse(deps.db
|
|
@@ -62,7 +65,7 @@ export async function executeLocalRecipe(deps, context, piece) {
|
|
|
62
65
|
return "done";
|
|
63
66
|
}
|
|
64
67
|
if (input.kind !== "local")
|
|
65
|
-
throw new Error("
|
|
68
|
+
throw new Error(internalError("a local step was set up wrongly"));
|
|
66
69
|
if (input.operation === "figure-card-v1")
|
|
67
70
|
return executeFigureCard(deps, context, piece);
|
|
68
71
|
if (input.operation === "narration-files-v1") {
|
|
@@ -98,31 +101,23 @@ export async function executeLocalRecipe(deps, context, piece) {
|
|
|
98
101
|
});
|
|
99
102
|
return "done";
|
|
100
103
|
}
|
|
101
|
-
throw new Error(`
|
|
104
|
+
throw new Error(internalError(`no handler for the step "${input.operation}"`));
|
|
102
105
|
}
|
|
103
106
|
async function concatenate(deps, context, piece) {
|
|
104
107
|
const view = executionView(deps, context.work.projectId, context.work.revisionId);
|
|
105
108
|
if (view === undefined)
|
|
106
|
-
throw new Error("
|
|
107
|
-
const
|
|
108
|
-
.prepare("SELECT recipe_context FROM revision_work WHERE id=?")
|
|
109
|
-
.get(context.work.workId);
|
|
110
|
-
const plan = executionPlan(deps, view, savedCatalogue(row?.recipe_context));
|
|
109
|
+
throw new Error(internalError("the project version being built is missing"));
|
|
110
|
+
const plan = executionPlan(deps, view, workCatalogue(deps.db, context.work.workId));
|
|
111
111
|
const recipe = plan.recipes.find((candidate) => candidate.key === piece.key && candidate.fingerprint === piece.fingerprint);
|
|
112
112
|
if (recipe === undefined)
|
|
113
|
-
throw new Error("
|
|
113
|
+
throw new Error(internalError("the narration chunks to join no longer match the project's saved inputs"));
|
|
114
114
|
const files = recipe.dependsOn.map((key) => {
|
|
115
115
|
const input = view.pieces.find((candidate) => candidate.key === key &&
|
|
116
|
-
candidate
|
|
117
|
-
candidate.available &&
|
|
118
|
-
candidate.piece.state === "done" &&
|
|
116
|
+
isDonePiece(candidate) &&
|
|
119
117
|
candidate.fingerprint === plan.recipes.find((value) => value.key === key)?.fingerprint);
|
|
120
118
|
if (input?.assetId === null || input === undefined)
|
|
121
|
-
throw new Error(
|
|
122
|
-
|
|
123
|
-
.prepare("SELECT path FROM project_assets WHERE id=? AND project_id=?")
|
|
124
|
-
.get(input.assetId, context.work.projectId);
|
|
125
|
-
return outputPath(deps.paths, context.work.projectId, z.string().parse(asset?.path));
|
|
119
|
+
throw new Error(`One narration chunk has no saved audio, so the narration can't be joined together. Make the missing chunk again in ${editSettings.narration}, then Try again.`);
|
|
120
|
+
return outputPath(deps.paths, context.work.projectId, assetPath(deps, context.work.projectId, input.assetId));
|
|
126
121
|
});
|
|
127
122
|
// Level the volume repeats the join its recipe names, from the same pieces, each levelled
|
|
128
123
|
// first (`recipe-loudness.ts`).
|
|
@@ -295,7 +290,7 @@ export async function joinTurns(run, files, values, output) {
|
|
|
295
290
|
.rest(z.unknown())
|
|
296
291
|
.parse(values)[1];
|
|
297
292
|
if (layout.length !== files.length || files.length === 0)
|
|
298
|
-
throw new Error("
|
|
293
|
+
throw new Error(internalError("the speaker turns to join don't match their audio"));
|
|
299
294
|
await runFfmpeg({
|
|
300
295
|
bin: run.bin,
|
|
301
296
|
args: turnJoinArgs(files.map((path, index) => ({
|
|
@@ -2,7 +2,7 @@ import { z } from "zod";
|
|
|
2
2
|
import { projectSelected } from "../revisions/projection.js";
|
|
3
3
|
import { getRevisionView } from "../revisions/view.js";
|
|
4
4
|
import { bindNarrationReuse, narrationOrdinal } from "./runtime-narration-reuse.js";
|
|
5
|
-
import { executionPlan,
|
|
5
|
+
import { executionPlan, workCatalogue } from "./runtime-plan.js";
|
|
6
6
|
export function rebindPublishedNarration(deps, work, piece) {
|
|
7
7
|
if (piece.input.kind !== "tts")
|
|
8
8
|
return;
|
|
@@ -11,10 +11,7 @@ export function rebindPublishedNarration(deps, work, piece) {
|
|
|
11
11
|
.all(work.projectId, piece.id, piece.key, work.revisionId);
|
|
12
12
|
if (targets.length === 0)
|
|
13
13
|
return;
|
|
14
|
-
const
|
|
15
|
-
.prepare("SELECT recipe_context FROM revision_work WHERE id=?")
|
|
16
|
-
.get(work.workId);
|
|
17
|
-
const catalogue = savedCatalogue(row?.recipe_context);
|
|
14
|
+
const catalogue = workCatalogue(deps.db, work.workId);
|
|
18
15
|
for (const target of targets) {
|
|
19
16
|
const view = getRevisionView(deps, work.projectId, z.string().parse(target.revision_id));
|
|
20
17
|
if (view === undefined)
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { insertManifestOutput, insertManifestPiece, selectOutputRecord, selectPieceRecord, } from "../revisions/manifest-repo.js";
|
|
3
|
+
import { assetPathOrUndefined } from "../revisions/mutation-assets.js";
|
|
4
|
+
import { isDonePiece } from "../revisions/view.js";
|
|
3
5
|
import { retainedNarrationPieces } from "./narration-history.js";
|
|
4
6
|
import { matchingNarrationPiece } from "./narration-reuse.js";
|
|
5
7
|
export function bindNarrationReuse(deps, view, recipe, ordinal) {
|
|
@@ -30,17 +32,14 @@ export function bindNarrationReuse(deps, view, recipe, ordinal) {
|
|
|
30
32
|
return;
|
|
31
33
|
}
|
|
32
34
|
if (recipe.input.kind === "provided" && /^audio:(body:.+|intro|outro):[0-9]+$/.test(recipe.key)) {
|
|
33
|
-
if (view.pieces.some((one) => one.
|
|
34
|
-
one.available &&
|
|
35
|
-
one.key === recipe.key &&
|
|
35
|
+
if (view.pieces.some((one) => isDonePiece(one, recipe.key) &&
|
|
36
36
|
one.fingerprint === recipe.fingerprint &&
|
|
37
|
-
one.piece.state === "done" &&
|
|
38
37
|
one.piece.idx === ordinal))
|
|
39
38
|
return;
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
if (
|
|
39
|
+
const file = recipe.input.assetId === null
|
|
40
|
+
? undefined
|
|
41
|
+
: assetPathOrUndefined(deps, view.revision.projectId, recipe.input.assetId);
|
|
42
|
+
if (file === undefined)
|
|
44
43
|
return;
|
|
45
44
|
const semantic = z
|
|
46
45
|
.tuple([z.string(), z.array(z.string().nullable())])
|
|
@@ -67,7 +66,7 @@ export function bindNarrationReuse(deps, view, recipe, ordinal) {
|
|
|
67
66
|
state: "done",
|
|
68
67
|
payload: JSON.stringify({
|
|
69
68
|
provided: true,
|
|
70
|
-
file
|
|
69
|
+
file,
|
|
71
70
|
logicalKey: recipe.key.slice(0, recipe.key.lastIndexOf(":")),
|
|
72
71
|
logicalText: semantic[0],
|
|
73
72
|
text: semantic[0],
|
|
@@ -85,11 +84,8 @@ export function bindNarrationReuse(deps, view, recipe, ordinal) {
|
|
|
85
84
|
if (recipe.input.kind !== "tts")
|
|
86
85
|
return;
|
|
87
86
|
const input = recipe.input;
|
|
88
|
-
if (view.pieces.some((one) => one.
|
|
89
|
-
one.available &&
|
|
90
|
-
one.key === recipe.key &&
|
|
87
|
+
if (view.pieces.some((one) => isDonePiece(one, recipe.key) &&
|
|
91
88
|
one.fingerprint === recipe.fingerprint &&
|
|
92
|
-
one.piece.state === "done" &&
|
|
93
89
|
one.piece.idx === ordinal &&
|
|
94
90
|
narrationMetadataMatches(one.piece.payload, input)))
|
|
95
91
|
return;
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import {
|
|
2
|
+
import { internalError } from "../../kernel/errors.js";
|
|
3
|
+
import { editSettings } from "../../kernel/ports/settings-places.js";
|
|
4
|
+
import { isDonePiece } from "../revisions/view.js";
|
|
5
|
+
import { executionPlan, executionView, savedCatalogue, workCatalogue } from "./runtime-plan.js";
|
|
3
6
|
import { preparedTexts, publishResult } from "./runtime-publication.js";
|
|
4
7
|
export function joinedNarration(parts) {
|
|
5
8
|
return parts
|
|
@@ -9,16 +12,12 @@ export function joinedNarration(parts) {
|
|
|
9
12
|
export function narrationTextParts(view, plan, segment) {
|
|
10
13
|
const concat = plan.recipes.find((row) => row.key === (segment === "body" ? "audio:body:concat" : `audio:${segment}`));
|
|
11
14
|
if (concat === undefined)
|
|
12
|
-
throw new Error(`
|
|
15
|
+
throw new Error(internalError(`the ${segment} narration is missing from the project plan`));
|
|
13
16
|
return concat.dependsOn.map((key) => {
|
|
14
17
|
const recipe = plan.recipes.find((row) => row.key === key);
|
|
15
|
-
const selected = view.pieces.find((row) => row.key === key &&
|
|
16
|
-
row.selected &&
|
|
17
|
-
row.available &&
|
|
18
|
-
row.piece.state === "done" &&
|
|
19
|
-
row.fingerprint === recipe?.fingerprint);
|
|
18
|
+
const selected = view.pieces.find((row) => row.key === key && isDonePiece(row) && row.fingerprint === recipe?.fingerprint);
|
|
20
19
|
if (selected === undefined || recipe === undefined)
|
|
21
|
-
throw new Error(
|
|
20
|
+
throw new Error(`Some narration chunks aren't finished, so the full narration text isn't available. Let the Narration stage finish (Continue the run, or Try again on Narration), or make the missing chunk again in ${editSettings.narration}.`);
|
|
22
21
|
const input = recipe.input;
|
|
23
22
|
if (input.kind === "provided" &&
|
|
24
23
|
Array.isArray(input.semantic) &&
|
|
@@ -29,13 +28,13 @@ export function narrationTextParts(view, plan, segment) {
|
|
|
29
28
|
requestText: null,
|
|
30
29
|
};
|
|
31
30
|
if (input.kind !== "tts")
|
|
32
|
-
throw new Error("
|
|
31
|
+
throw new Error(internalError("a narration chunk's text was never worked out"));
|
|
33
32
|
const payload = z
|
|
34
33
|
.object({ text: z.string().optional(), spokenText: z.string().optional() })
|
|
35
34
|
.parse(JSON.parse(selected.piece.payload ?? "{}"));
|
|
36
35
|
if (input.spokenText !== undefined &&
|
|
37
36
|
(payload.spokenText !== input.spokenText || payload.text !== input.text))
|
|
38
|
-
throw new Error(
|
|
37
|
+
throw new Error(`A narration chunk's audio no longer matches its prepared text. Make that chunk again in ${editSettings.narration}, then Try again.`);
|
|
39
38
|
return {
|
|
40
39
|
logicalKey: input.logicalKey,
|
|
41
40
|
spokenText: input.spokenText === undefined ? (payload.text ?? input.text) : (payload.spokenText ?? ""),
|
|
@@ -45,19 +44,16 @@ export function narrationTextParts(view, plan, segment) {
|
|
|
45
44
|
}
|
|
46
45
|
export async function publishNarrationText(deps, context, piece) {
|
|
47
46
|
if (piece.input.kind !== "local")
|
|
48
|
-
throw new Error("
|
|
47
|
+
throw new Error(internalError("the narration text file step was set up wrongly"));
|
|
49
48
|
const { segment } = z
|
|
50
49
|
.object({ segment: z.enum(["body", "intro", "outro"]) })
|
|
51
50
|
.parse(piece.input.values);
|
|
52
51
|
const view = executionView(deps, context.work.projectId, context.work.revisionId);
|
|
53
|
-
const row = deps.db
|
|
54
|
-
.prepare("SELECT recipe_context FROM revision_work WHERE id=?")
|
|
55
|
-
.get(context.work.workId);
|
|
56
52
|
if (view === undefined)
|
|
57
|
-
throw new Error("
|
|
58
|
-
const plan = executionPlan(deps, view,
|
|
53
|
+
throw new Error(internalError("the project version being narrated is missing"));
|
|
54
|
+
const plan = executionPlan(deps, view, workCatalogue(deps.db, context.work.workId));
|
|
59
55
|
if (!plan.recipes.some((recipe) => recipe.key === piece.key && recipe.fingerprint === piece.fingerprint))
|
|
60
|
-
throw new Error("
|
|
56
|
+
throw new Error(internalError("the narration text no longer matches the project's saved inputs"));
|
|
61
57
|
const parts = narrationTextParts(view, plan, segment);
|
|
62
58
|
const outputs = preparedTexts(deps, context, piece, [
|
|
63
59
|
["narration_txt", `${segment}-narration.txt`, joinedNarration(parts)],
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { existsSync } from "node:fs";
|
|
2
2
|
import { basename } from "node:path";
|
|
3
|
+
import { assetPathOrUndefined } from "../revisions/mutation-assets.js";
|
|
3
4
|
import { outputPath } from "../storage/layout.js";
|
|
4
5
|
// The file behind a picture the article names (``): an image uploaded
|
|
5
6
|
// to the project under that file name. An article's pictures are otherwise web addresses
|
|
@@ -14,10 +15,7 @@ export function articlePicture(deps, view, named) {
|
|
|
14
15
|
for (const image of Object.values(view.revision.content.imageDefinitions)) {
|
|
15
16
|
if (image.source !== "provide" || image.assetId === null)
|
|
16
17
|
continue;
|
|
17
|
-
const
|
|
18
|
-
.prepare("SELECT path FROM project_assets WHERE id=? AND project_id=?")
|
|
19
|
-
.get(image.assetId, view.revision.projectId);
|
|
20
|
-
const path = typeof row?.path === "string" ? row.path : undefined;
|
|
18
|
+
const path = assetPathOrUndefined(deps, view.revision.projectId, image.assetId);
|
|
21
19
|
if (path === undefined || basename(path).toLowerCase() !== name)
|
|
22
20
|
continue;
|
|
23
21
|
const file = outputPath(deps.paths, view.revision.projectId, path);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { platformLabels, socialPlatforms } from "../social/model.js";
|
|
2
|
+
import { executionPlan, executionView, workCatalogueIfSaved } from "./runtime-plan.js";
|
|
2
3
|
// What a failed step is called on screen, so its error says which image, chunk or topic to
|
|
3
4
|
// fix. Worked out only after a failure: numbering a narration chunk means building the plan.
|
|
4
5
|
// Undefined for steps that name their own place (captions, export) or have no single one.
|
|
@@ -17,6 +18,9 @@ export function pieceLabel(deps, context, piece) {
|
|
|
17
18
|
return "Document";
|
|
18
19
|
if (key === "youtube:description")
|
|
19
20
|
return "YouTube description";
|
|
21
|
+
const post = /^social:post:([a-z]+)$/.exec(key);
|
|
22
|
+
if (post !== null)
|
|
23
|
+
return `${platformLabels[socialPlatforms.find((one) => one === post[1]) ?? "x"]} post`;
|
|
20
24
|
if (key.startsWith("review:")) {
|
|
21
25
|
const item = key.slice("review:".length);
|
|
22
26
|
const itemLabel = item === "narration"
|
|
@@ -47,6 +51,8 @@ export function pieceLabel(deps, context, piece) {
|
|
|
47
51
|
return "Animated images";
|
|
48
52
|
if (key === "images:scenes")
|
|
49
53
|
return "Image scenes";
|
|
54
|
+
if (key === "article:digest")
|
|
55
|
+
return "Keyword digest";
|
|
50
56
|
const short = /^shorts:(\d+):(prompts|image:(\d+)|render)$/.exec(key);
|
|
51
57
|
if (short !== null)
|
|
52
58
|
return short[2] === "prompts"
|
|
@@ -84,13 +90,11 @@ export function pieceLabel(deps, context, piece) {
|
|
|
84
90
|
return narrationChunk(deps, context, segment, key, prefix) ?? prefix;
|
|
85
91
|
}
|
|
86
92
|
function narrationChunk(deps, context, segment, key, prefix) {
|
|
87
|
-
const
|
|
88
|
-
.prepare("SELECT recipe_context FROM revision_work WHERE id=?")
|
|
89
|
-
.get(context.work.workId);
|
|
93
|
+
const catalogue = workCatalogueIfSaved(deps.db, context.work.workId);
|
|
90
94
|
const view = executionView(deps, context.work.projectId, context.work.revisionId);
|
|
91
|
-
if (
|
|
95
|
+
if (catalogue === undefined || view === undefined)
|
|
92
96
|
return undefined;
|
|
93
|
-
const plan = executionPlan(deps, view,
|
|
97
|
+
const plan = executionPlan(deps, view, catalogue);
|
|
94
98
|
const concat = plan.recipes.find((recipe) => recipe.key === (segment === "body" ? "audio:body:concat" : `audio:${segment}`));
|
|
95
99
|
if (concat === undefined)
|
|
96
100
|
return undefined;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { readFileSync } from "node:fs";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { catalogueSchema } from "../../catalog/schema.js";
|
|
4
|
-
import { getRevisionView, withEarlierJoins } from "../revisions/view.js";
|
|
4
|
+
import { getRevisionView, readyOutput, withEarlierJoins } from "../revisions/view.js";
|
|
5
5
|
import { outputPath } from "../storage/layout.js";
|
|
6
6
|
import { referencedAssetsAvailable, retainedNarrationPieces } from "./narration-history.js";
|
|
7
7
|
import { applyProvidedReviews } from "./provided-review.js";
|
|
@@ -22,12 +22,38 @@ export function executionCatalogue(catalogue, config) {
|
|
|
22
22
|
export function savedCatalogue(value) {
|
|
23
23
|
return catalogueSchema.parse(JSON.parse(z.string().parse(value)));
|
|
24
24
|
}
|
|
25
|
+
function savedContext(db, workId) {
|
|
26
|
+
return db.prepare("SELECT recipe_context FROM revision_work WHERE id=?").get(workId)
|
|
27
|
+
?.recipe_context;
|
|
28
|
+
}
|
|
29
|
+
// The catalogue a work was admitted with, saved beside it; a work without one is a bug.
|
|
30
|
+
export function workCatalogue(db, workId) {
|
|
31
|
+
return savedCatalogue(savedContext(db, workId));
|
|
32
|
+
}
|
|
33
|
+
// The same, or undefined for a work (or a missing one) that has no catalogue saved.
|
|
34
|
+
export function workCatalogueIfSaved(db, workId) {
|
|
35
|
+
const context = savedContext(db, workId);
|
|
36
|
+
return context === null || context === undefined ? undefined : savedCatalogue(context);
|
|
37
|
+
}
|
|
38
|
+
// A step's LLM call on its work's saved catalogue: the chosen model with the thinking settings
|
|
39
|
+
// the catalogue holds for its level, no web search, labelled with the step. The catalogue is
|
|
40
|
+
// read once, as the builder is made.
|
|
41
|
+
export function workLlm(db, workId, choice, label) {
|
|
42
|
+
const catalogued = workCatalogue(db, workId).llm.find((one) => one.provider === choice.provider && one.id === choice.model);
|
|
43
|
+
const { thinking } = choice;
|
|
44
|
+
return (call) => ({
|
|
45
|
+
provider: choice.provider,
|
|
46
|
+
model: choice.model,
|
|
47
|
+
...(thinking === undefined ? {} : { thinking }),
|
|
48
|
+
thinkingConfig: thinking === undefined ? null : (catalogued?.llm.thinking?.[thinking] ?? null),
|
|
49
|
+
webSearch: false,
|
|
50
|
+
previewLabel: label,
|
|
51
|
+
...call,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
25
54
|
export function executionPlan(deps, view, catalogue) {
|
|
26
55
|
const textOutput = (role) => {
|
|
27
|
-
const row = view
|
|
28
|
-
output.available &&
|
|
29
|
-
output.state === "ready" &&
|
|
30
|
-
output.output.role === role);
|
|
56
|
+
const row = readyOutput(view, { role });
|
|
31
57
|
return row === undefined
|
|
32
58
|
? null
|
|
33
59
|
: readFileSync(outputPath(deps.paths, view.revision.projectId, row.output.path), "utf8");
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { basename } from "node:path";
|
|
2
|
+
import { internalError } from "../../kernel/errors.js";
|
|
3
|
+
import { editSettings } from "../../kernel/ports/settings-places.js";
|
|
2
4
|
import { referenceKey, thumbnailVariant } from "../admission/model.js";
|
|
3
5
|
import { plainText } from "../article/plain.js";
|
|
4
6
|
import { splitEndMatter } from "../article/split.js";
|
|
5
7
|
import { checkAppearance } from "../images/appearance.js";
|
|
6
8
|
import { checkScenes, sceneCountOf } from "../images/scenes.js";
|
|
9
|
+
import { checkDigest } from "../keywords/digest.js";
|
|
7
10
|
import { spokenPassage } from "../narration/describe.js";
|
|
8
11
|
import { observeNarration } from "../narration/live.js";
|
|
9
12
|
import { validatePreparation } from "../narration/preparation.js";
|
|
@@ -11,24 +14,25 @@ import { prepareRequests } from "../narration/steering.js";
|
|
|
11
14
|
import { chaptersFrom } from "../research/planner.js";
|
|
12
15
|
import { sourcedAnswer } from "../research/synthesis.js";
|
|
13
16
|
import { imageReviewers } from "../reviews/model.js";
|
|
17
|
+
import { checkPost, postText } from "../social/post-prompt.js";
|
|
14
18
|
import { discardPreparedAssets, writeAsset } from "../storage/assets.js";
|
|
15
19
|
import { outputPath } from "../storage/layout.js";
|
|
16
20
|
import { probeDurationMs } from "../video/ffmpeg.js";
|
|
17
21
|
import { parseAttribution } from "../voices/attribution.js";
|
|
18
22
|
import { parseScript } from "../voices/script.js";
|
|
19
23
|
import { imageAppearanceKey } from "./recipe-appearance.js";
|
|
24
|
+
import { digestKey } from "./recipe-digest.js";
|
|
20
25
|
import { imageScenesKey, thumbnailScenesKey } from "./recipe-scenes.js";
|
|
21
26
|
import { executeArticleRequests } from "./runtime-article.js";
|
|
22
27
|
import { imageCall } from "./runtime-image.js";
|
|
23
28
|
import { frozenInstructions } from "./runtime-instructions.js";
|
|
24
29
|
import { articlePicture } from "./runtime-pictures.js";
|
|
25
|
-
import { executionPlan, executionView,
|
|
30
|
+
import { executionPlan, executionView, workCatalogue, workCatalogueIfSaved, } from "./runtime-plan.js";
|
|
26
31
|
import { preparedResult, preparedTexts, publishResult } from "./runtime-publication.js";
|
|
27
32
|
import { clearSoftening, softenedPrompt, softeningRequested, softenMessages } from "./soften.js";
|
|
33
|
+
import { pieceAlreadyDone } from "./work-records.js";
|
|
28
34
|
export async function executeProviderRecipe(deps, context, providers, piece) {
|
|
29
|
-
if (deps.db
|
|
30
|
-
.prepare("SELECT state FROM revision_work_pieces WHERE id=? AND work_id=?")
|
|
31
|
-
.get(piece.id, context.work.workId)?.state === "done")
|
|
35
|
+
if (pieceAlreadyDone(deps.db, context.work.workId, piece.id))
|
|
32
36
|
return "done";
|
|
33
37
|
const input = piece.input;
|
|
34
38
|
const wrapped = providers.forPiece(piece.id);
|
|
@@ -64,7 +68,7 @@ export async function executeProviderRecipe(deps, context, providers, piece) {
|
|
|
64
68
|
...(segment === undefined ? {} : { segment }),
|
|
65
69
|
tokensIn: answer.value.usage?.inputTokens ?? 0,
|
|
66
70
|
tokensOut: answer.value.usage?.outputTokens ?? 0,
|
|
67
|
-
});
|
|
71
|
+
}, context.work.projectId);
|
|
68
72
|
return "done";
|
|
69
73
|
}
|
|
70
74
|
if (input.kind === "tts") {
|
|
@@ -116,7 +120,7 @@ export async function executeProviderRecipe(deps, context, providers, piece) {
|
|
|
116
120
|
provider: input.provider,
|
|
117
121
|
model: input.model,
|
|
118
122
|
...(durationMs === undefined ? {} : { audioSeconds: durationMs / 1000 }),
|
|
119
|
-
});
|
|
123
|
+
}, context.work.projectId);
|
|
120
124
|
}
|
|
121
125
|
finally {
|
|
122
126
|
discardPreparedAssets(deps, [asset]);
|
|
@@ -164,10 +168,10 @@ export async function executeProviderRecipe(deps, context, providers, piece) {
|
|
|
164
168
|
provider: input.provider,
|
|
165
169
|
model: input.model,
|
|
166
170
|
...(variant !== undefined ? { thumbnails: 1 } : { images: 1 }),
|
|
167
|
-
});
|
|
171
|
+
}, context.work.projectId);
|
|
168
172
|
return "done";
|
|
169
173
|
}
|
|
170
|
-
throw new Error("
|
|
174
|
+
throw new Error(internalError("this step has no provider request to run"));
|
|
171
175
|
}
|
|
172
176
|
// Soften and retry (`soften.ts`): the project's AI model rewords a refused image prompt
|
|
173
177
|
// before the image is drawn again. Undefined when nobody asked, or the project has no model.
|
|
@@ -186,17 +190,17 @@ export async function softenIfAsked(deps, context, providers, piece, prompt, lab
|
|
|
186
190
|
messages: softenMessages(prompt),
|
|
187
191
|
previewLabel: `${label}: softened prompt`,
|
|
188
192
|
check: (value) => softenedPrompt(value.text) === ""
|
|
189
|
-
?
|
|
193
|
+
? `The AI model sent back an empty prompt while softening it. Use Soften and retry again, or reword the prompt yourself in ${editSettings.images}.`
|
|
190
194
|
: undefined,
|
|
191
195
|
});
|
|
192
196
|
return answer.ok ? softenedPrompt(answer.value.text) : "held";
|
|
193
197
|
}
|
|
194
198
|
function checkAnswer(piece, answer) {
|
|
195
199
|
if (answer.text.trim() === "")
|
|
196
|
-
return
|
|
200
|
+
return `The AI model sent back an empty answer. Use Try again; if it keeps happening, choose another model in ${editSettings.writer}.`;
|
|
197
201
|
if (piece.input.kind === "llm" && piece.input.describe !== undefined)
|
|
198
202
|
return spokenPassage(answer.text) === ""
|
|
199
|
-
?
|
|
203
|
+
? `The AI model's description had no words a narrator could say. Use Try again; if it keeps happening, choose another model in ${editSettings.writer}, or turn off Describe tables and figures in ${editSettings.narration}.`
|
|
200
204
|
: undefined;
|
|
201
205
|
// Scenes from the article: one scene per image, as many as the request lists.
|
|
202
206
|
if ((piece.key === imageScenesKey || piece.key === thumbnailScenesKey) &&
|
|
@@ -209,9 +213,17 @@ function checkAnswer(piece, answer) {
|
|
|
209
213
|
const checked = checkAppearance(answer.text);
|
|
210
214
|
return checked.ok ? undefined : checked.reason;
|
|
211
215
|
}
|
|
216
|
+
// The keyword digest: every part written.
|
|
217
|
+
if (piece.key === digestKey && piece.input.kind === "llm") {
|
|
218
|
+
const checked = checkDigest(answer.text);
|
|
219
|
+
return checked.ok ? undefined : checked.reason;
|
|
220
|
+
}
|
|
221
|
+
// A post for another site: within its limit.
|
|
222
|
+
if (piece.input.kind === "llm" && piece.input.social !== undefined)
|
|
223
|
+
return checkPost(answer.text, piece.input.social);
|
|
212
224
|
if (piece.key === "research:planner")
|
|
213
225
|
return chaptersFrom(answer.text).length === 0
|
|
214
|
-
?
|
|
226
|
+
? `The AI model's research plan listed no chapters, so research could not go on. Use Try again; if it keeps happening, choose another model in ${editSettings.writer}.`
|
|
215
227
|
: undefined;
|
|
216
228
|
if (piece.key === "research:notes" || piece.key.startsWith("research:chapter:"))
|
|
217
229
|
return sourcedAnswer(piece.key, answer.text);
|
|
@@ -225,7 +237,7 @@ function checkAnswer(piece, answer) {
|
|
|
225
237
|
const checked = parseScript(answer.text, piece.input.script.speakers);
|
|
226
238
|
return checked.ok
|
|
227
239
|
? undefined
|
|
228
|
-
: `The conversation the
|
|
240
|
+
: `The conversation the AI model wrote can't be read as a script: ${checked.reason}`;
|
|
229
241
|
}
|
|
230
242
|
return undefined;
|
|
231
243
|
}
|
|
@@ -240,7 +252,11 @@ async function publishText(deps, context, piece, answer) {
|
|
|
240
252
|
throw new Error(checked.reason);
|
|
241
253
|
await publishResult(deps, context, piece, preparedTexts(deps, context, piece, [
|
|
242
254
|
["instructions", "instructions.md", frozenInstructions(deps, context, piece)],
|
|
243
|
-
]), {
|
|
255
|
+
]), {
|
|
256
|
+
scenes: checked.scenes,
|
|
257
|
+
...(checked.details === undefined ? {} : { details: checked.details }),
|
|
258
|
+
text: answer.text,
|
|
259
|
+
});
|
|
244
260
|
return;
|
|
245
261
|
}
|
|
246
262
|
if (piece.key === imageAppearanceKey && piece.input.kind === "llm") {
|
|
@@ -252,6 +268,37 @@ async function publishText(deps, context, piece, answer) {
|
|
|
252
268
|
]), { appearance: checked.appearance, text: answer.text });
|
|
253
269
|
return;
|
|
254
270
|
}
|
|
271
|
+
if (piece.input.kind === "llm" && piece.input.social !== undefined) {
|
|
272
|
+
const target = piece.input.social;
|
|
273
|
+
const problem = checkPost(answer.text, target);
|
|
274
|
+
if (problem !== undefined)
|
|
275
|
+
throw new Error(problem);
|
|
276
|
+
const text = postText(answer.text);
|
|
277
|
+
const asset = writeAsset(deps, context.work.projectId, `post-${target.platform}.txt`, Buffer.from(text));
|
|
278
|
+
let outputs;
|
|
279
|
+
try {
|
|
280
|
+
outputs = [
|
|
281
|
+
preparedResult(deps, context, piece, "social_post", asset, null, {
|
|
282
|
+
platform: target.platform,
|
|
283
|
+
}),
|
|
284
|
+
];
|
|
285
|
+
}
|
|
286
|
+
catch (error) {
|
|
287
|
+
discardPreparedAssets(deps, [asset]);
|
|
288
|
+
throw error;
|
|
289
|
+
}
|
|
290
|
+
await publishResult(deps, context, piece, outputs, { text });
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
if (piece.key === digestKey && piece.input.kind === "llm") {
|
|
294
|
+
const checked = checkDigest(answer.text);
|
|
295
|
+
if (!checked.ok)
|
|
296
|
+
throw new Error(checked.reason);
|
|
297
|
+
await publishResult(deps, context, piece, preparedTexts(deps, context, piece, [
|
|
298
|
+
["instructions", "instructions.md", frozenInstructions(deps, context, piece)],
|
|
299
|
+
]), { digest: checked.digest, text: answer.text });
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
255
302
|
if (piece.input.kind === "llm" && piece.input.preparation !== undefined) {
|
|
256
303
|
const checked = validatePreparation(answer.text, piece.input.preparation.source);
|
|
257
304
|
if (!checked.ok)
|
|
@@ -276,7 +323,7 @@ async function publishText(deps, context, piece, answer) {
|
|
|
276
323
|
if (piece.input.kind === "llm" && piece.input.script !== undefined) {
|
|
277
324
|
const checked = parseScript(parts.body, piece.input.script.speakers);
|
|
278
325
|
if (!checked.ok)
|
|
279
|
-
throw new Error(`The
|
|
326
|
+
throw new Error(`The AI model's script can't be read: ${checked.reason} Try again to have it written again, or fix it in ${editSettings.article}.`);
|
|
280
327
|
}
|
|
281
328
|
await publishResult(deps, context, piece, preparedTexts(deps, context, piece, [
|
|
282
329
|
["instructions", "instructions.md", frozenInstructions(deps, context, piece)],
|
|
@@ -314,7 +361,7 @@ async function publishText(deps, context, piece, answer) {
|
|
|
314
361
|
: [];
|
|
315
362
|
const title = titles[Number(piece.key.split(":").at(-1)) - 1];
|
|
316
363
|
if (typeof title !== "string")
|
|
317
|
-
throw new Error("
|
|
364
|
+
throw new Error(internalError("a research chapter has no title in the research plan"));
|
|
318
365
|
const asset = writeAsset(deps, context.work.projectId, `research-${piece.key.split(":").at(-1)}.md`, Buffer.from(answer.text));
|
|
319
366
|
await publishResult(deps, context, piece, [], { title, notes: answer.text }, asset);
|
|
320
367
|
return;
|
|
@@ -328,13 +375,11 @@ function narrationLabel(deps, context, piece) {
|
|
|
328
375
|
return "Narration";
|
|
329
376
|
const name = piece.input.segment === "body" ? "Body" : piece.input.segment === "intro" ? "Intro" : "Outro";
|
|
330
377
|
const view = executionView(deps, context.work.projectId, context.work.revisionId);
|
|
331
|
-
const
|
|
332
|
-
|
|
333
|
-
.get(context.work.workId);
|
|
334
|
-
if (view === undefined || row?.recipe_context === undefined || row.recipe_context === null)
|
|
378
|
+
const catalogue = workCatalogueIfSaved(deps.db, context.work.workId);
|
|
379
|
+
if (view === undefined || catalogue === undefined)
|
|
335
380
|
return name;
|
|
336
381
|
const segment = piece.input.segment;
|
|
337
|
-
const parts = executionPlan(deps, view,
|
|
382
|
+
const parts = executionPlan(deps, view, catalogue).recipes.filter((recipe) => recipe.input.kind === "tts" && recipe.input.segment === segment);
|
|
338
383
|
const index = parts.findIndex((recipe) => recipe.key === piece.key);
|
|
339
384
|
return parts.length > 1 && index >= 0 ? `${name} part ${index + 1} of ${parts.length}` : name;
|
|
340
385
|
}
|
|
@@ -345,10 +390,7 @@ function checkPreparation(deps, context, piece, answer) {
|
|
|
345
390
|
const checked = validatePreparation(answer.text, source);
|
|
346
391
|
if (!checked.ok)
|
|
347
392
|
return checked.reason;
|
|
348
|
-
const
|
|
349
|
-
.prepare("SELECT recipe_context FROM revision_work WHERE id=?")
|
|
350
|
-
.get(context.work.workId);
|
|
351
|
-
const model = savedCatalogue(row?.recipe_context).tts.find((model) => model.provider === "inworld" && model.id === "inworld-tts-2");
|
|
393
|
+
const model = workCatalogue(deps.db, context.work.workId).tts.find((model) => model.provider === "inworld" && model.id === "inworld-tts-2");
|
|
352
394
|
const prepared = prepareRequests(source, checked.cues, model?.tts.maxCharacters ?? 4000);
|
|
353
395
|
return prepared.ok ? undefined : prepared.reason;
|
|
354
396
|
}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { transact } from "../../kernel/db/tx.js";
|
|
2
|
+
import { internalError } from "../../kernel/errors.js";
|
|
2
3
|
import { fingerprint } from "../../kernel/runner/work.js";
|
|
3
4
|
import { publicationAuthority } from "../revisions/publication-rules.js";
|
|
4
5
|
import { commitRevisionOutputs } from "../revisions/publish.js";
|
|
5
6
|
import { insertAsset, insertManifestOutput, revisionById } from "../revisions/repo.js";
|
|
6
7
|
import { discardPreparedAssets, writeAsset } from "../storage/assets.js";
|
|
7
8
|
import { rebindPublishedNarration } from "./runtime-narration-publication.js";
|
|
8
|
-
import { executionPlan, executionView,
|
|
9
|
+
import { executionPlan, executionView, workCatalogueIfSaved } from "./runtime-plan.js";
|
|
9
10
|
export function preparedResult(deps, context, piece, role, asset, durationMs = null, meta = {}) {
|
|
10
11
|
return {
|
|
11
12
|
// A project holds many images, and one video and several images per short.
|
|
@@ -15,6 +16,8 @@ export function preparedResult(deps, context, piece, role, asset, durationMs = n
|
|
|
15
16
|
role === "animated_image" ||
|
|
16
17
|
// Level the volume: one levelled narration per segment.
|
|
17
18
|
role === "audio_levelled" ||
|
|
19
|
+
// A post per site.
|
|
20
|
+
role === "social_post" ||
|
|
18
21
|
// The second and third thumbnails; the first keeps the slot it always had.
|
|
19
22
|
(role === "thumbnail" && piece.key !== "thumbnail:image")
|
|
20
23
|
? piece.key
|
|
@@ -39,7 +42,7 @@ export function preparedResult(deps, context, piece, role, asset, durationMs = n
|
|
|
39
42
|
export function preparedText(deps, context, piece, role, filename, text) {
|
|
40
43
|
const output = preparedTexts(deps, context, piece, [[role, filename, text]])[0];
|
|
41
44
|
if (output === undefined)
|
|
42
|
-
throw new Error("
|
|
45
|
+
throw new Error(internalError("a text file could not be prepared"));
|
|
43
46
|
return output;
|
|
44
47
|
}
|
|
45
48
|
export function preparedTexts(deps, context, piece, texts) {
|
|
@@ -173,11 +176,9 @@ function pieceIndex(deps, context, piece) {
|
|
|
173
176
|
if (localIndex >= 0)
|
|
174
177
|
return localIndex + 1;
|
|
175
178
|
const view = executionView(deps, context.work.projectId, context.work.revisionId);
|
|
176
|
-
const
|
|
177
|
-
|
|
178
|
-
.
|
|
179
|
-
if (view !== undefined && row?.recipe_context !== null && row?.recipe_context !== undefined) {
|
|
180
|
-
const keys = executionPlan(deps, view, savedCatalogue(row.recipe_context)).recipes.filter((recipe) => recipe.stage === context.work.kind &&
|
|
179
|
+
const catalogue = workCatalogueIfSaved(deps.db, context.work.workId);
|
|
180
|
+
if (view !== undefined && catalogue !== undefined) {
|
|
181
|
+
const keys = executionPlan(deps, view, catalogue).recipes.filter((recipe) => recipe.stage === context.work.kind &&
|
|
181
182
|
(piece.input.kind !== "llm" ||
|
|
182
183
|
piece.input.preparation?.segment !== "body" ||
|
|
183
184
|
(recipe.input.kind === "llm" && recipe.input.preparation?.segment === "body")) &&
|
|
@@ -206,10 +207,10 @@ export function retainPartialArticle(deps, context, piece, text) {
|
|
|
206
207
|
if (authority === undefined)
|
|
207
208
|
return;
|
|
208
209
|
if (authority.key !== piece.key || authority.fingerprint !== piece.fingerprint)
|
|
209
|
-
throw new Error("
|
|
210
|
+
throw new Error(internalError("a partly written article doesn't match its saved step"));
|
|
210
211
|
const revision = revisionById(deps.db, context.work.projectId, context.work.revisionId);
|
|
211
212
|
if (revision === undefined)
|
|
212
|
-
throw new Error("
|
|
213
|
+
throw new Error(internalError("the project version for a partly written article is missing"));
|
|
213
214
|
insertAsset(deps.db, result.asset);
|
|
214
215
|
insertManifestOutput(deps.db, revision, {
|
|
215
216
|
slot: `article:partial:${piece.id}`,
|