@gentbajko/slopify 3.25.8 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/account-limits.js +30 -0
- package/dist/adapters/alignment/cache.js +3 -5
- package/dist/adapters/alignment/ctc.js +1 -2
- package/dist/adapters/alignment/lock.js +4 -3
- package/dist/adapters/alignment/multilingual.js +0 -3
- package/dist/adapters/alignment/prefetch.js +2 -1
- package/dist/adapters/alignment/worker.js +2 -1
- package/dist/adapters/explain.js +0 -3
- package/dist/adapters/ffmpeg.js +19 -1
- package/dist/adapters/host-cli/index.js +19 -3
- package/dist/adapters/http-failure.js +53 -0
- package/dist/adapters/image/codex.js +36 -4
- package/dist/adapters/image/fal.js +17 -50
- package/dist/adapters/image/google.js +31 -55
- package/dist/adapters/image/openai.js +20 -47
- package/dist/adapters/image/reference.js +36 -0
- package/dist/adapters/image/replicate.js +18 -47
- package/dist/adapters/interest/search-interest.js +113 -0
- package/dist/adapters/key-probes.js +53 -2
- package/dist/adapters/llm/antigravity.js +4 -0
- package/dist/adapters/llm/assistant-cli.js +388 -0
- package/dist/adapters/llm/child-session.js +83 -0
- package/dist/adapters/llm/claude-code-models.js +51 -98
- package/dist/adapters/llm/claude-code.js +13 -2
- package/dist/adapters/llm/codex-limits.js +27 -68
- package/dist/adapters/llm/codex-server-models.js +61 -109
- package/dist/adapters/llm/codex.js +12 -1
- package/dist/adapters/llm/openrouter.js +10 -47
- package/dist/adapters/llm/run-cli.js +6 -22
- package/dist/adapters/llm/sse-lines.js +5 -1
- package/dist/adapters/model-access.js +37 -0
- package/dist/adapters/tts/cartesia.js +15 -46
- package/dist/adapters/tts/elevenlabs.js +20 -52
- package/dist/adapters/tts/gemini.js +19 -40
- package/dist/adapters/tts/inworld-async.js +4 -1
- package/dist/adapters/tts/inworld.js +3 -0
- package/dist/adapters/tts/openai.js +20 -50
- package/dist/assets/models-lifecycle.yaml +6 -0
- package/dist/assistant-wiring.js +60 -0
- package/dist/autopilot-timers.js +59 -0
- package/dist/catalog/lifecycle.js +52 -0
- package/dist/catalog/propose.js +204 -0
- package/dist/catalog/registry.js +3 -1
- package/dist/catalog/schema.js +2 -0
- package/dist/catalog/store.js +39 -0
- package/dist/edge/autostart/native.js +3 -5
- package/dist/edge/autostart/prompt.js +2 -1
- package/dist/edge/autostart/service.js +3 -4
- package/dist/edge/cli-args.js +3 -4
- package/dist/edge/cli.js +2 -1
- package/dist/edge/docker-install/apply.js +11 -11
- package/dist/edge/docker-install/run.js +2 -1
- package/dist/edge/docker-install/state.js +4 -3
- package/dist/edge/docker-install/tree.js +2 -4
- package/dist/edge/docker-install/volume.js +3 -2
- package/dist/edge/docker.js +5 -4
- package/dist/edge/events/hub.js +5 -5
- package/dist/edge/http/actions.js +4 -25
- package/dist/edge/http/actor.js +5 -3
- package/dist/edge/http/app.js +85 -10
- package/dist/edge/http/assistant.js +127 -0
- package/dist/edge/http/audio-preview.js +4 -11
- package/dist/edge/http/auditions.js +1 -1
- package/dist/edge/http/autostart.js +5 -5
- package/dist/edge/http/backups.js +1 -3
- package/dist/edge/http/channel-memory.js +7 -20
- package/dist/edge/http/channels.js +13 -26
- package/dist/edge/http/checkpoints.js +33 -17
- package/dist/edge/http/design-templates.js +167 -0
- package/dist/edge/http/designs.js +178 -0
- package/dist/edge/http/diagnostics.js +5 -1
- package/dist/edge/http/document-themes.js +2 -11
- package/dist/edge/http/draft-files.js +1 -3
- package/dist/edge/http/draft-problem.js +4 -9
- package/dist/edge/http/drafts.js +3 -3
- package/dist/edge/http/entries.js +6 -9
- package/dist/edge/http/extension-auth.js +27 -0
- package/dist/edge/http/external-reviews.js +12 -11
- package/dist/edge/http/files.js +5 -11
- package/dist/edge/http/folder-location.js +1 -4
- package/dist/edge/http/fonts.js +0 -7
- package/dist/edge/http/home.js +38 -13
- package/dist/edge/http/host-cli.js +18 -8
- package/dist/edge/http/ids.js +8 -0
- package/dist/edge/http/keywords.js +35 -0
- package/dist/edge/http/model-checks.js +132 -0
- package/dist/edge/http/narration-peaks.js +5 -13
- package/dist/edge/http/onboarding.js +1 -14
- package/dist/edge/http/open-folder.js +5 -10
- package/dist/edge/http/outputs.js +4 -12
- package/dist/edge/http/patch-notes.js +4 -10
- package/dist/edge/http/planning.js +2 -6
- package/dist/edge/http/problem.js +2 -4
- package/dist/edge/http/project-create.js +1 -0
- package/dist/edge/http/project-templates.js +29 -17
- package/dist/edge/http/projects.js +2 -12
- package/dist/edge/http/prompts.js +7 -14
- package/dist/edge/http/pronunciations.js +1 -2
- package/dist/edge/http/providers.js +39 -24
- package/dist/edge/http/refusal.js +29 -0
- package/dist/edge/http/remote-access.js +40 -0
- package/dist/edge/http/remote-guard.js +71 -0
- package/dist/edge/http/request-guard.js +91 -0
- package/dist/edge/http/reviews.js +11 -24
- package/dist/edge/http/revision-files.js +5 -10
- package/dist/edge/http/revisions.js +10 -15
- package/dist/edge/http/run-cost.js +1 -2
- package/dist/edge/http/same-page.js +80 -0
- package/dist/edge/http/schedules.js +59 -32
- package/dist/edge/http/settings.js +22 -13
- package/dist/edge/http/social.js +282 -0
- package/dist/edge/http/staging.js +2 -4
- package/dist/edge/http/storage-files.js +5 -7
- package/dist/edge/http/storage.js +23 -23
- package/dist/edge/http/studio.js +23 -50
- package/dist/edge/http/style-preview.js +1 -4
- package/dist/edge/http/subtitles.js +3 -17
- package/dist/edge/http/template-studio.js +433 -0
- package/dist/edge/http/trash.js +10 -11
- package/dist/edge/http/tutorial.js +1 -2
- package/dist/edge/http/tutorials.js +5 -11
- package/dist/edge/http/update.js +7 -13
- package/dist/edge/http/waveform.js +3 -6
- package/dist/edge/http/youtube-edits.js +2 -3
- package/dist/edge/mcp/assistant.js +279 -0
- package/dist/edge/mcp/attribution.js +8 -2
- package/dist/edge/mcp/call-route.js +11 -2
- package/dist/edge/mcp/excluded-routes.js +25 -0
- package/dist/edge/mcp/http.js +11 -2
- package/dist/edge/mcp/instructions.js +5 -3
- package/dist/edge/mcp/library-tools.js +1 -0
- package/dist/edge/mcp/route-tool.js +35 -15
- package/dist/edge/mcp/server.js +13 -8
- package/dist/edge/mcp/tools-channels.js +2 -0
- package/dist/edge/mcp/tools-designs.js +165 -0
- package/dist/edge/mcp/tools-library.js +14 -2
- package/dist/edge/mcp/tools-planning.js +23 -4
- package/dist/edge/mcp/tools-projects.js +28 -1
- package/dist/edge/mcp/tools-runs.js +14 -1
- package/dist/edge/mcp/tools-schedules.js +28 -4
- package/dist/edge/mcp/tools-setup.js +61 -3
- package/dist/edge/mcp/tools-social.js +46 -0
- package/dist/edge/mcp/tools-storage.js +8 -0
- package/dist/edge/mcp/tools-template-studio.js +166 -0
- package/dist/edge/mcp/tools.js +6 -0
- package/dist/edge/remote-access/cli.js +71 -0
- package/dist/edge/remote-access/model.js +32 -0
- package/dist/edge/remote-access/rules.js +207 -0
- package/dist/edge/remote-access/service.js +203 -0
- package/dist/edge/remote-access/store.js +44 -0
- package/dist/edge/remote-access/views.js +43 -0
- package/dist/extension/slopify-studio-chrome.zip +0 -0
- package/dist/extension/slopify-studio-firefox.zip +0 -0
- package/dist/host-cli/install.js +2 -2
- package/dist/host-cli/open-folder.js +2 -2
- package/dist/host-cli/paths.js +2 -4
- package/dist/host-cli/server.js +4 -4
- package/dist/host-cli/service.js +3 -3
- package/dist/host-cli/status.js +7 -7
- package/dist/kernel/db/migrations/0063-model-checks.sql +20 -0
- package/dist/kernel/db/migrations/0064-template-studio.sql +46 -0
- package/dist/kernel/db/migrations/0065-promise-and-assistant-reviews.sql +58 -0
- package/dist/kernel/db/migrations/0066-assistant.sql +44 -0
- package/dist/kernel/db/migrations/0067-autopilot.sql +6 -0
- package/dist/kernel/db/migrations/0068-topic-scores.sql +17 -0
- package/dist/kernel/db/migrations/0070-designs.sql +53 -0
- package/dist/kernel/db/migrations/0071-design-usage.sql +33 -0
- package/dist/kernel/db/migrations/0072-design-templates.sql +33 -0
- package/dist/kernel/db/migrations/0073-schedule-design-kind.sql +5 -0
- package/dist/kernel/db/migrations/0074-template-bakeoffs.sql +44 -0
- package/dist/kernel/db/migrations/0075-social-posts.sql +25 -0
- package/dist/kernel/db/migrations/0076-channel-social.sql +5 -0
- package/dist/kernel/db/migrations/0077-post-prompts.sql +17 -0
- package/dist/kernel/db/tx.js +2 -4
- package/dist/kernel/errors.js +27 -1
- package/dist/kernel/json-answer.js +15 -0
- package/dist/kernel/lock.js +4 -9
- package/dist/kernel/paths.js +8 -0
- package/dist/kernel/ports/assistant-cli.js +4 -0
- package/dist/kernel/ports/host-cli.js +3 -0
- package/dist/kernel/ports/interest.js +4 -0
- package/dist/kernel/ports/languages.js +0 -3
- package/dist/kernel/ports/model.js +2 -0
- package/dist/kernel/runner/attempt.js +3 -1
- package/dist/kernel/runner/audition.js +3 -1
- package/dist/kernel/runner/checkpoint-authority.js +2 -1
- package/dist/kernel/runner/index.js +8 -10
- package/dist/kernel/runner/model-access.js +40 -0
- package/dist/kernel/runner/model-check.js +153 -0
- package/dist/kernel/runner/providers.js +15 -10
- package/dist/kernel/runner/standalone.js +9 -5
- package/dist/main.js +334 -19
- package/dist/model-checks.js +166 -0
- package/dist/patch-notes/3.25.9.md +5 -0
- package/dist/patch-notes/4.0.0.md +51 -0
- package/dist/patch-notes/index.json +12 -0
- package/dist/slices/admission/heads.js +2 -1
- package/dist/slices/admission/repo.js +2 -1
- package/dist/slices/admission/rules.js +43 -8
- package/dist/slices/admission/schema.js +8 -0
- package/dist/slices/admission/stage-writes.js +0 -3
- package/dist/slices/admission/start.js +48 -31
- package/dist/slices/admission/substitute.js +7 -4
- package/dist/slices/agents/attention-posts.js +31 -0
- package/dist/slices/agents/attention-templates.js +33 -0
- package/dist/slices/agents/attention.js +10 -1
- package/dist/slices/agents/connection.js +2 -6
- package/dist/slices/agents/model.js +6 -3
- package/dist/slices/agents/repo.js +15 -7
- package/dist/slices/article/continuation.js +0 -63
- package/dist/slices/article/plain.js +3 -2
- package/dist/slices/article/segments.js +2 -62
- package/dist/slices/assistant/access.js +1 -0
- package/dist/slices/assistant/asks.js +80 -0
- package/dist/slices/assistant/cost.js +54 -0
- package/dist/slices/assistant/gate.js +222 -0
- package/dist/slices/assistant/model.js +79 -0
- package/dist/slices/assistant/names.js +23 -0
- package/dist/slices/assistant/prompt.js +74 -0
- package/dist/slices/assistant/repo.js +74 -0
- package/dist/slices/assistant/tokens.js +18 -0
- package/dist/slices/assistant/turn.js +342 -0
- package/dist/slices/autopilot/buffer.js +76 -0
- package/dist/slices/autopilot/model.js +14 -0
- package/dist/slices/autopilot/notify.js +27 -0
- package/dist/slices/autopilot/repo.js +34 -0
- package/dist/slices/autopilot/signals.js +194 -0
- package/dist/slices/autopilot/warnings.js +85 -0
- package/dist/slices/autopilot/weekly.js +100 -0
- package/dist/slices/backups/files.js +2 -6
- package/dist/slices/backups/repo.js +3 -15
- package/dist/slices/backups/service.js +4 -3
- package/dist/slices/channels/cast-images.js +2 -1
- package/dist/slices/channels/model.js +0 -1
- package/dist/slices/channels/rebrand.js +0 -3
- package/dist/slices/channels/repo.js +4 -0
- package/dist/slices/channels/schema.js +6 -0
- package/dist/slices/channels/service.js +10 -0
- package/dist/slices/channels/videos.js +2 -14
- package/dist/slices/checkpoints/index.js +0 -1
- package/dist/slices/control/providers.js +0 -26
- package/dist/slices/designs/artwork.js +66 -0
- package/dist/slices/designs/budget.js +23 -0
- package/dist/slices/designs/calls.js +124 -0
- package/dist/slices/designs/check-context.js +38 -0
- package/dist/slices/designs/check-text.js +43 -0
- package/dist/slices/designs/fields.js +88 -0
- package/dist/slices/designs/frames.js +34 -0
- package/dist/slices/designs/gate.js +128 -0
- package/dist/slices/designs/layout.js +293 -0
- package/dist/slices/designs/model.js +35 -0
- package/dist/slices/designs/pdf-job.js +23 -0
- package/dist/slices/designs/pdf-pages.js +30 -0
- package/dist/slices/designs/pdf-runner.js +68 -0
- package/dist/slices/designs/pdf-worker.js +24 -0
- package/dist/slices/designs/picture-size.js +79 -0
- package/dist/slices/designs/pictures.js +55 -0
- package/dist/slices/designs/quote.js +24 -0
- package/dist/slices/designs/render-args.js +36 -0
- package/dist/slices/designs/render-input.js +59 -0
- package/dist/slices/designs/render.js +215 -0
- package/dist/slices/designs/repo.js +101 -0
- package/dist/slices/designs/requests.js +80 -0
- package/dist/slices/designs/runner.js +239 -0
- package/dist/slices/designs/sample-repo.js +91 -0
- package/dist/slices/designs/sample.js +222 -0
- package/dist/slices/designs/schema.js +87 -0
- package/dist/slices/designs/sections.js +44 -0
- package/dist/slices/designs/service.js +233 -0
- package/dist/slices/designs/steps-repo.js +102 -0
- package/dist/slices/designs/studio-kind.js +39 -0
- package/dist/slices/designs/template-checks.js +44 -0
- package/dist/slices/designs/template-make.js +118 -0
- package/dist/slices/designs/templates.js +218 -0
- package/dist/slices/document/fonts.js +2 -1
- package/dist/slices/episodes/summarize.js +5 -1
- package/dist/slices/estimate/index.js +45 -7
- package/dist/slices/fonts/catalog.js +3 -2
- package/dist/slices/fonts/discovery.js +3 -2
- package/dist/slices/fonts/files.js +2 -6
- package/dist/slices/fonts/index.js +0 -1
- package/dist/slices/fonts/sfnt.js +45 -10
- package/dist/slices/images/appearance.js +6 -15
- package/dist/slices/images/scenes.js +100 -27
- package/dist/slices/keywords/digest.js +84 -0
- package/dist/slices/keywords/facts.js +92 -0
- package/dist/slices/keywords/fill.js +80 -0
- package/dist/slices/keywords/model.js +75 -0
- package/dist/slices/keywords/rules.js +187 -0
- package/dist/slices/keywords/schema.js +28 -0
- package/dist/slices/keywords/specs.js +260 -0
- package/dist/slices/keywords/values.js +74 -0
- package/dist/slices/library/lint.js +29 -12
- package/dist/slices/library/model.js +2 -0
- package/dist/slices/library/photorealistic.js +4 -12
- package/dist/slices/library/rename.js +9 -7
- package/dist/slices/library/save.js +14 -10
- package/dist/slices/library/slots.js +37 -11
- package/dist/slices/library/transfer.js +2 -1
- package/dist/slices/library/used-by.js +25 -10
- package/dist/slices/loudness/loudnorm.js +51 -11
- package/dist/slices/model-checks/cost.js +61 -0
- package/dist/slices/model-checks/listing.js +124 -0
- package/dist/slices/model-checks/model.js +20 -0
- package/dist/slices/model-checks/record.js +32 -0
- package/dist/slices/model-checks/repo.js +120 -0
- package/dist/slices/model-checks/rules.js +112 -0
- package/dist/slices/model-checks/run.js +143 -0
- package/dist/slices/model-checks/service.js +198 -0
- package/dist/slices/model-upkeep/switch.js +70 -25
- package/dist/slices/model-upkeep/usage.js +26 -11
- package/dist/slices/narration/breaths.js +2 -1
- package/dist/slices/narration/clean-pieces.js +2 -1
- package/dist/slices/narration/concat.js +2 -1
- package/dist/slices/narration/peaks.js +3 -4
- package/dist/slices/narration/pronunciation-chunks.js +4 -3
- package/dist/slices/narration/pronunciation.js +3 -2
- package/dist/slices/narration/steering.js +4 -3
- package/dist/slices/notifications/notifier.js +4 -3
- package/dist/slices/notifications/rules.js +5 -2
- package/dist/slices/notifications/settings.js +4 -12
- package/dist/slices/notifications/subject.js +2 -1
- package/dist/slices/onboarding/copy.js +2 -1
- package/dist/slices/onboarding/first-run.js +3 -2
- package/dist/slices/onboarding/full-video.js +3 -2
- package/dist/slices/onboarding/install.js +4 -3
- package/dist/slices/onboarding/model.js +0 -16
- package/dist/slices/onboarding/packs.js +22 -22
- package/dist/slices/onboarding/quick-short.js +2 -1
- package/dist/slices/onboarding/sample.js +0 -1
- package/dist/slices/onboarding/state.js +2 -11
- package/dist/slices/onboarding/template.js +2 -1
- package/dist/slices/patch-notes/library.js +3 -2
- package/dist/slices/play-drafts/convert.js +4 -0
- package/dist/slices/play-drafts/review-inputs.js +8 -2
- package/dist/slices/play-drafts/review.js +5 -4
- package/dist/slices/play-drafts/schema.js +4 -0
- package/dist/slices/project-templates/from-project.js +9 -2
- package/dist/slices/project-templates/repo.js +6 -1
- package/dist/slices/project-templates/setup.js +8 -0
- package/dist/slices/project-templates/stand-ins.js +22 -0
- package/dist/slices/rebuild/activity.js +2 -0
- package/dist/slices/rebuild/admission-repo.js +3 -2
- package/dist/slices/rebuild/narration-history.js +4 -5
- package/dist/slices/rebuild/narration-retry.js +2 -1
- package/dist/slices/rebuild/preview-details.js +27 -9
- package/dist/slices/rebuild/preview-plan.js +3 -8
- package/dist/slices/rebuild/recipe-build.js +8 -3
- package/dist/slices/rebuild/recipe-describe.js +3 -3
- package/dist/slices/rebuild/recipe-digest.js +58 -0
- package/dist/slices/rebuild/recipe-input-schema.js +10 -0
- package/dist/slices/rebuild/recipe-keywords.js +71 -0
- package/dist/slices/rebuild/recipe-legacy.js +5 -1
- package/dist/slices/rebuild/recipe-model.js +4 -0
- package/dist/slices/rebuild/recipe-narration-text.js +2 -1
- package/dist/slices/rebuild/recipe-preparation.js +3 -3
- package/dist/slices/rebuild/recipe-reference.js +8 -4
- package/dist/slices/rebuild/recipe-reviews.js +27 -7
- package/dist/slices/rebuild/recipe-save.js +6 -3
- package/dist/slices/rebuild/recipe-scenes.js +40 -11
- package/dist/slices/rebuild/recipe-shorts.js +8 -8
- package/dist/slices/rebuild/recipe-social.js +46 -0
- package/dist/slices/rebuild/recipe-text.js +64 -20
- package/dist/slices/rebuild/recipe-validation.js +98 -28
- package/dist/slices/rebuild/recipe-visual.js +55 -16
- package/dist/slices/rebuild/recipe-work.js +15 -3
- package/dist/slices/rebuild/recipe-youtube.js +4 -3
- package/dist/slices/rebuild/recovery-selection.js +3 -1
- package/dist/slices/rebuild/recovery.js +3 -2
- package/dist/slices/rebuild/repo.js +4 -3
- package/dist/slices/rebuild/review-promise.js +25 -0
- package/dist/slices/rebuild/review-redo.js +2 -1
- package/dist/slices/rebuild/runtime-admission.js +4 -3
- package/dist/slices/rebuild/runtime-agent-review.js +11 -5
- package/dist/slices/rebuild/runtime-animate.js +9 -8
- package/dist/slices/rebuild/runtime-article.js +3 -2
- package/dist/slices/rebuild/runtime-checkpoints.js +5 -4
- package/dist/slices/rebuild/runtime-document.js +8 -11
- package/dist/slices/rebuild/runtime-export-bed.js +6 -11
- package/dist/slices/rebuild/runtime-export-edit.js +6 -15
- package/dist/slices/rebuild/runtime-export-inputs.js +7 -7
- package/dist/slices/rebuild/runtime-export-short.js +8 -4
- package/dist/slices/rebuild/runtime-export.js +34 -12
- package/dist/slices/rebuild/runtime-figure-card.js +2 -1
- package/dist/slices/rebuild/runtime-image.js +4 -9
- package/dist/slices/rebuild/runtime-instructions.js +2 -0
- package/dist/slices/rebuild/runtime-keywords.js +59 -0
- package/dist/slices/rebuild/runtime-lines.js +2 -11
- package/dist/slices/rebuild/runtime-local.js +14 -20
- package/dist/slices/rebuild/runtime-narration-publication.js +2 -5
- package/dist/slices/rebuild/runtime-narration-reuse.js +9 -13
- package/dist/slices/rebuild/runtime-narration-text.js +10 -15
- package/dist/slices/rebuild/runtime-pictures.js +2 -4
- package/dist/slices/rebuild/runtime-piece-label.js +10 -6
- package/dist/slices/rebuild/runtime-plan.js +31 -5
- package/dist/slices/rebuild/runtime-provider.js +60 -19
- package/dist/slices/rebuild/runtime-publication.js +10 -9
- package/dist/slices/rebuild/runtime-review.js +33 -28
- package/dist/slices/rebuild/runtime-run.js +4 -1
- package/dist/slices/rebuild/runtime-shorts.js +34 -50
- package/dist/slices/rebuild/runtime-store.js +3 -8
- package/dist/slices/rebuild/runtime-subtitles.js +16 -14
- package/dist/slices/rebuild/runtime-voices.js +8 -15
- package/dist/slices/rebuild/runtime-youtube.js +11 -29
- package/dist/slices/rebuild/transition-repo.js +6 -5
- package/dist/slices/rebuild/work-records.js +6 -0
- package/dist/slices/reruns/cascade.js +1 -2
- package/dist/slices/reruns/index.js +6 -9
- package/dist/slices/reviews/external-model.js +3 -0
- package/dist/slices/reviews/external-repo.js +2 -1
- package/dist/slices/reviews/external-rows.js +2 -3
- package/dist/slices/reviews/model.js +26 -8
- package/dist/slices/reviews/repo.js +2 -1
- package/dist/slices/reviews/rules.js +1 -0
- package/dist/slices/reviews/view.js +5 -2
- package/dist/slices/revisions/downloads.js +4 -5
- package/dist/slices/revisions/mutation-assets.js +7 -4
- package/dist/slices/revisions/mutation-cues.js +2 -5
- package/dist/slices/revisions/mutations.js +0 -1
- package/dist/slices/revisions/repo.js +3 -1
- package/dist/slices/revisions/schema.js +1 -0
- package/dist/slices/revisions/view.js +20 -0
- package/dist/slices/run-cost/limits.js +5 -2
- package/dist/slices/run-cost/meter.js +12 -5
- package/dist/slices/run-cost/panel.js +8 -74
- package/dist/slices/run-cost/plan-readings.js +127 -0
- package/dist/slices/run-cost/plan-use.js +169 -0
- package/dist/slices/run-cost/pricing.js +3 -3
- package/dist/slices/run-cost/week.js +32 -4
- package/dist/slices/schedules/agenda.js +11 -2
- package/dist/slices/schedules/by-date.js +42 -0
- package/dist/slices/schedules/calendar.js +5 -0
- package/dist/slices/schedules/design-agenda.js +36 -0
- package/dist/slices/schedules/design-check.js +41 -0
- package/dist/slices/schedules/design-run.js +126 -0
- package/dist/slices/schedules/next-run.js +62 -0
- package/dist/slices/schedules/prepare.js +18 -2
- package/dist/slices/schedules/repo.js +24 -16
- package/dist/slices/schedules/rescore.js +35 -0
- package/dist/slices/schedules/scheduler.js +13 -3
- package/dist/slices/schedules/schema.js +54 -3
- package/dist/slices/schedules/score.js +107 -0
- package/dist/slices/schedules/service.js +57 -24
- package/dist/slices/schedules/topic-list.js +15 -0
- package/dist/slices/schedules/topic-scores.js +104 -0
- package/dist/slices/schedules/topics.js +48 -36
- package/dist/slices/settings/cli-paths.js +4 -6
- package/dist/slices/settings/first-run.js +2 -11
- package/dist/slices/settings/model-reach.js +3 -17
- package/dist/slices/settings/model.js +10 -0
- package/dist/slices/settings/playback.js +33 -22
- package/dist/slices/settings/probe-read.js +16 -0
- package/dist/slices/settings/repo.js +33 -0
- package/dist/slices/settings/tutorial.js +2 -2
- package/dist/slices/settings/voices.js +4 -12
- package/dist/slices/shorts/pick.js +2 -15
- package/dist/slices/shorts/prompts.js +2 -13
- package/dist/slices/shorts/render.js +3 -0
- package/dist/slices/social/channel.js +44 -0
- package/dist/slices/social/defaults.js +17 -0
- package/dist/slices/social/due.js +36 -0
- package/dist/slices/social/extension.js +18 -0
- package/dist/slices/social/fit.js +115 -0
- package/dist/slices/social/limits.js +186 -0
- package/dist/slices/social/links.js +21 -0
- package/dist/slices/social/media.js +131 -0
- package/dist/slices/social/model.js +75 -0
- package/dist/slices/social/notice.js +19 -0
- package/dist/slices/social/pack.js +176 -0
- package/dist/slices/social/post-prompt.js +55 -0
- package/dist/slices/social/queue.js +31 -0
- package/dist/slices/social/repo.js +133 -0
- package/dist/slices/social/reshape.js +97 -0
- package/dist/slices/social/rules.js +5 -0
- package/dist/slices/social/schema.js +70 -0
- package/dist/slices/social/serve.js +51 -0
- package/dist/slices/social/service.js +128 -0
- package/dist/slices/social/settings.js +21 -0
- package/dist/slices/social/sources.js +114 -0
- package/dist/slices/social/state.js +110 -0
- package/dist/slices/social/text.js +149 -0
- package/dist/slices/storage/arrange.js +3 -1
- package/dist/slices/storage/assets.js +8 -10
- package/dist/slices/storage/backup-designs.js +74 -0
- package/dist/slices/storage/backup-export.js +8 -3
- package/dist/slices/storage/backup-format.js +10 -0
- package/dist/slices/storage/backup-import.js +20 -2
- package/dist/slices/storage/delete-project.js +6 -5
- package/dist/slices/storage/files-location.js +6 -8
- package/dist/slices/storage/layout.js +13 -2
- package/dist/slices/storage/model.js +3 -0
- package/dist/slices/storage/portable.js +16 -11
- package/dist/slices/storage/schema.js +2 -0
- package/dist/slices/storage/staging-refs.js +2 -1
- package/dist/slices/storage/staging.js +6 -9
- package/dist/slices/storage/trim.js +10 -3
- package/dist/slices/studio/calendar.js +4 -1
- package/dist/slices/studio/pick.js +2 -11
- package/dist/slices/studio/plan.js +6 -15
- package/dist/slices/studio/queue.js +3 -14
- package/dist/slices/studio/releases.js +26 -0
- package/dist/slices/studio/settings.js +14 -51
- package/dist/slices/studio/videos.js +12 -0
- package/dist/slices/style-preview/render.js +34 -13
- package/dist/slices/style-preview/schema.js +13 -0
- package/dist/slices/style-preview/service.js +2 -1
- package/dist/slices/style-preview/settings.js +33 -5
- package/dist/slices/telemetry/collector-client.js +2 -4
- package/dist/slices/telemetry/flush.js +2 -4
- package/dist/slices/telemetry/model.js +0 -7
- package/dist/slices/telemetry/record.js +10 -3
- package/dist/slices/template-studio/anatomy-view.js +118 -0
- package/dist/slices/template-studio/anatomy.js +73 -0
- package/dist/slices/template-studio/bakeoff-make.js +225 -0
- package/dist/slices/template-studio/bakeoff-repo.js +83 -0
- package/dist/slices/template-studio/bakeoff.js +333 -0
- package/dist/slices/template-studio/budget.js +103 -0
- package/dist/slices/template-studio/checks.js +273 -0
- package/dist/slices/template-studio/document-sample.js +56 -0
- package/dist/slices/template-studio/edit.js +15 -0
- package/dist/slices/template-studio/for-all.js +161 -0
- package/dist/slices/template-studio/free-video.js +31 -0
- package/dist/slices/template-studio/free.js +176 -0
- package/dist/slices/template-studio/gate.js +40 -0
- package/dist/slices/template-studio/hidden.js +20 -0
- package/dist/slices/template-studio/jobs.js +79 -0
- package/dist/slices/template-studio/loudness.js +111 -0
- package/dist/slices/template-studio/make.js +40 -0
- package/dist/slices/template-studio/model.js +54 -0
- package/dist/slices/template-studio/pack-import.js +253 -0
- package/dist/slices/template-studio/pack-samples.js +60 -0
- package/dist/slices/template-studio/pack.js +205 -0
- package/dist/slices/template-studio/paid-view.js +66 -0
- package/dist/slices/template-studio/paid.js +348 -0
- package/dist/slices/template-studio/quote.js +148 -0
- package/dist/slices/template-studio/ready.js +104 -0
- package/dist/slices/template-studio/repo.js +134 -0
- package/dist/slices/template-studio/reviews-path.js +58 -0
- package/dist/slices/template-studio/runner.js +84 -0
- package/dist/slices/template-studio/save.js +236 -0
- package/dist/slices/template-studio/say-it-as.js +248 -0
- package/dist/slices/template-studio/schedule-gate.js +34 -0
- package/dist/slices/template-studio/schedule-price.js +30 -0
- package/dist/slices/template-studio/schedule-sample.js +87 -0
- package/dist/slices/template-studio/schema.js +218 -0
- package/dist/slices/template-studio/scope.js +124 -0
- package/dist/slices/template-studio/sections.js +176 -0
- package/dist/slices/template-studio/service.js +173 -0
- package/dist/slices/template-studio/status.js +174 -0
- package/dist/slices/template-studio/topic.js +223 -0
- package/dist/slices/trash/designs.js +76 -0
- package/dist/slices/trash/model.js +13 -4
- package/dist/slices/trash/service.js +52 -2
- package/dist/slices/tutorials/library.js +3 -2
- package/dist/slices/video/ass-text.js +17 -0
- package/dist/slices/video/audio-export.js +2 -64
- package/dist/slices/video/encoding.js +160 -0
- package/dist/slices/video/ffmpeg.js +23 -21
- package/dist/slices/video/figure-card.js +1 -15
- package/dist/slices/video/slideshow.js +43 -18
- package/dist/slices/voices/palette.js +0 -3
- package/dist/slices/youtube/answer.js +2 -15
- package/dist/slices/youtube/edits-repo.js +2 -11
- package/dist/tutorials/Agents-MCP.md +2 -1
- package/dist/tutorials/Assistant.md +42 -0
- package/dist/tutorials/Channels.md +2 -0
- package/dist/tutorials/Home-and-Projects.md +19 -0
- package/dist/tutorials/Install.md +1 -0
- package/dist/tutorials/Keywords-Slopify-Fills.md +87 -0
- package/dist/tutorials/Models.md +33 -1
- package/dist/tutorials/Notifications.md +6 -0
- package/dist/tutorials/Play-Images.md +4 -0
- package/dist/tutorials/Posting-to-Social-Sites.md +121 -0
- package/dist/tutorials/Prompts.md +10 -6
- package/dist/tutorials/Remote-Access.md +63 -0
- package/dist/tutorials/Reviews-and-Checkpoints.md +13 -2
- package/dist/tutorials/Schedules.md +21 -1
- package/dist/tutorials/Settings-Reference.md +50 -8
- package/dist/tutorials/Template-Studio.md +125 -0
- package/dist/tutorials/Templates.md +3 -0
- package/dist/tutorials/_Sidebar.md +5 -0
- package/dist/updater/work-in-progress.js +42 -12
- package/dist/web/assets/index-CkAI_2E7.css +1 -0
- package/dist/web/assets/index-DcD0cdfo.js +334 -0
- package/dist/web/assets/{pdf-T7MCwjIv.js → pdf-TODRwF31.js} +1 -1
- package/dist/web/index.html +2 -2
- package/package.json +5 -1
- package/dist/slices/article/provided-entries.js +0 -66
- package/dist/slices/article/run.js +0 -145
- package/dist/slices/images/run.js +0 -234
- package/dist/slices/narration/legacy-plan.js +0 -58
- package/dist/slices/narration/run.js +0 -270
- package/dist/slices/rebuild/runtime-actions.js +0 -90
- package/dist/slices/research/run.js +0 -224
- package/dist/slices/subtitles/prepare.js +0 -194
- package/dist/slices/subtitles/transcript.js +0 -34
- package/dist/slices/thumbnail/run.js +0 -219
- package/dist/slices/video/audio-inputs.js +0 -33
- package/dist/slices/video/reuse-audio.js +0 -62
- package/dist/slices/video/run.js +0 -78
- package/dist/slices/video/write-export.js +0 -158
- package/dist/slices/video/write-subtitles.js +0 -59
- package/dist/web/assets/index-BadsoORk.css +0 -1
- package/dist/web/assets/index-D8LqNsCl.js +0 -326
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { subjectOf } from "../admission/model.js";
|
|
2
2
|
import { usesYoutubeDescription } from "../admission/rules.js";
|
|
3
3
|
import { recipe, resourceIdentity, } from "./recipe-model.js";
|
|
4
|
-
import {
|
|
4
|
+
import { promptOf } from "./recipe-text.js";
|
|
5
5
|
// The YouTube description is written from the word timing, so it waits for
|
|
6
6
|
// `subtitles:timing` and nothing else: it runs beside the render, and a change to the
|
|
7
7
|
// motion, zoom, images or captions' look leaves it current. The transcript is only known once
|
|
@@ -12,6 +12,7 @@ export function youtubeRecipes(context, exports) {
|
|
|
12
12
|
const timing = exports.find((value) => value.key === "subtitles:timing");
|
|
13
13
|
if (!usesYoutubeDescription(config) || timing === undefined)
|
|
14
14
|
return [];
|
|
15
|
+
const prompt = config.descriptionPrompt?.trim() ? promptOf(context, "description") : undefined;
|
|
15
16
|
return [
|
|
16
17
|
recipe(context, "youtube:description", "video", {
|
|
17
18
|
kind: "local",
|
|
@@ -24,12 +25,12 @@ export function youtubeRecipes(context, exports) {
|
|
|
24
25
|
config.llm?.thinking ?? null,
|
|
25
26
|
// Blank means the built-in prompt; the step fills it in, so a new built-in wording
|
|
26
27
|
// ships as a new operation version rather than a silent change here.
|
|
27
|
-
|
|
28
|
+
prompt?.text ?? "",
|
|
28
29
|
subjectOf(config),
|
|
29
30
|
// The project language, only when it is not English, so English keeps its fingerprint.
|
|
30
31
|
...(config.language === undefined || config.language === "en" ? [] : [config.language]),
|
|
31
32
|
],
|
|
32
|
-
}, [timing.key],
|
|
33
|
+
}, [timing.key, ...(prompt?.dependsOn ?? [])],
|
|
33
34
|
// A paid LLM call: readiness, the charge warning and the estimate treat it like one.
|
|
34
35
|
{ kind: "provider" }),
|
|
35
36
|
];
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { readmitted } from "../../kernel/runner/graph.js";
|
|
2
2
|
import { narrationRegenerationKey } from "../narration/plan.js";
|
|
3
|
+
import { promiseItemKey } from "../reviews/model.js";
|
|
3
4
|
export function sectionRoots(view, plan, stage) {
|
|
4
5
|
if (stage === "article" &&
|
|
5
6
|
(view.revision.config.sources.article !== "generate" || view.revision.content.articleEdited))
|
|
@@ -35,7 +36,8 @@ export function redoTarget(view, plan, item) {
|
|
|
35
36
|
};
|
|
36
37
|
if (item === "narration")
|
|
37
38
|
return section("audio");
|
|
38
|
-
|
|
39
|
+
// The promise check sends the article back: its opening is what broke the promise.
|
|
40
|
+
if (item === "article:body" || item === promiseItemKey)
|
|
39
41
|
return section("article");
|
|
40
42
|
const own = (roots) => ({
|
|
41
43
|
roots,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { transact } from "../../kernel/db/tx.js";
|
|
2
|
+
import { internalError } from "../../kernel/errors.js";
|
|
2
3
|
import { stagesOf } from "../admission/repo.js";
|
|
3
4
|
import { withProjectControl } from "../control/lock.js";
|
|
4
5
|
import { requestHash } from "../revisions/mutation-request.js";
|
|
@@ -93,7 +94,7 @@ options = {}) {
|
|
|
93
94
|
if (record.edit !== null) {
|
|
94
95
|
const prior = retainedPreviewPlan(deps, base, deps.catalogue.read());
|
|
95
96
|
if (input.action.kind !== "rerun" && input.action.kind !== "redo")
|
|
96
|
-
throw new Error("
|
|
97
|
+
throw new Error(internalError("a recovery edit has nothing to re-run"));
|
|
97
98
|
const affected = dependentClosure(prior.recipes, rootsOf(base, prior));
|
|
98
99
|
const savedIntent = deps.db
|
|
99
100
|
.prepare("SELECT result_revision_id FROM revision_mutations WHERE project_id=? AND idempotency_key=?")
|
|
@@ -200,7 +201,7 @@ options = {}) {
|
|
|
200
201
|
storePreview(deps, preview.value.preview, preview.value.execution);
|
|
201
202
|
const stored = previewById(deps.db, projectId, preview.value.preview.id);
|
|
202
203
|
if (stored === undefined)
|
|
203
|
-
throw new Error("
|
|
204
|
+
throw new Error(internalError("the saved recovery preview is missing"));
|
|
204
205
|
return {
|
|
205
206
|
plan: { preview: stored, execution: preview.value.execution },
|
|
206
207
|
view,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { transact } from "../../kernel/db/tx.js";
|
|
2
|
+
import { internalError } from "../../kernel/errors.js";
|
|
2
3
|
import { workExists } from "../../kernel/runner/work-authority.js";
|
|
3
4
|
import { currentRevisionId, revisionById } from "../revisions/repo.js";
|
|
4
5
|
import { rebuildPreviewSchema } from "./model.js";
|
|
@@ -7,7 +8,7 @@ export { transitionRevisionWork } from "./transition-repo.js";
|
|
|
7
8
|
export function publicationTargets(db, publication, workKey, workFingerprint) {
|
|
8
9
|
const { work, pieceId, publicationId } = publication;
|
|
9
10
|
if (publicationId !== (pieceId ?? work.workId))
|
|
10
|
-
throw new Error("
|
|
11
|
+
throw new Error(internalError("a finished result is filed under the wrong step"));
|
|
11
12
|
if (!workExists(db, work))
|
|
12
13
|
return [];
|
|
13
14
|
if (pieceId !== null) {
|
|
@@ -15,9 +16,9 @@ export function publicationTargets(db, publication, workKey, workFingerprint) {
|
|
|
15
16
|
.prepare("SELECT work_key,fingerprint FROM revision_work_pieces WHERE id=? AND work_id=?")
|
|
16
17
|
.get(pieceId, work.workId);
|
|
17
18
|
if (piece === undefined)
|
|
18
|
-
throw new Error("
|
|
19
|
+
throw new Error(internalError("a finished result belongs to a different step"));
|
|
19
20
|
if (piece.work_key !== workKey || piece.fingerprint !== workFingerprint)
|
|
20
|
-
throw new Error("
|
|
21
|
+
throw new Error(internalError("a finished result doesn't match its saved step"));
|
|
21
22
|
}
|
|
22
23
|
const currentId = currentRevisionId(db, work.projectId);
|
|
23
24
|
const owns = (revisionId) => {
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { plainText } from "../article/plain.js";
|
|
2
|
+
import { splitEndMatter } from "../article/split.js";
|
|
3
|
+
import { spokenWordsPerMinute } from "../images/scale.js";
|
|
4
|
+
import { normalizeNarrationText } from "../narration/plan.js";
|
|
5
|
+
// How long the opening the promise check reads lasts: the span in which a viewer decides
|
|
6
|
+
// whether the video is what its title and thumbnail said.
|
|
7
|
+
export const promiseOpeningSeconds = 30;
|
|
8
|
+
// The article as the voice would say it (no Markdown, no end matter: what `recipe-text.ts`
|
|
9
|
+
// hands the narration), so the reviewer reads what the viewer will hear.
|
|
10
|
+
export function spokenArticle(markdown) {
|
|
11
|
+
return normalizeNarrationText(plainText(splitEndMatter(markdown).body));
|
|
12
|
+
}
|
|
13
|
+
// The spoken text cut after the words said in the opening seconds, its own line breaks kept.
|
|
14
|
+
export function openingOf(spoken, seconds = promiseOpeningSeconds, wordsPerMinute = spokenWordsPerMinute) {
|
|
15
|
+
const words = Math.round((seconds * wordsPerMinute) / 60);
|
|
16
|
+
let end = 0;
|
|
17
|
+
let count = 0;
|
|
18
|
+
for (const match of spoken.matchAll(/\S+/g)) {
|
|
19
|
+
if (count === words)
|
|
20
|
+
break;
|
|
21
|
+
count += 1;
|
|
22
|
+
end = match.index + match[0].length;
|
|
23
|
+
}
|
|
24
|
+
return spoken.slice(0, end);
|
|
25
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
|
+
import { errorText } from "../../kernel/errors.js";
|
|
2
3
|
import { reviewKey } from "../reviews/model.js";
|
|
3
4
|
import { pendingRedos, setRedoState } from "../reviews/repo.js";
|
|
4
5
|
import { currentRevisionId } from "../revisions/repo.js";
|
|
@@ -49,7 +50,7 @@ export function createReviewRedos() {
|
|
|
49
50
|
.catch((error) => {
|
|
50
51
|
deps.log.write("error", "review.redo", {
|
|
51
52
|
projectId: verdict.projectId,
|
|
52
|
-
detail:
|
|
53
|
+
detail: errorText(error),
|
|
53
54
|
});
|
|
54
55
|
setRedoState(deps.db, verdict.id, "failed", "Slopify hit an internal error while making this item again. Use Redo beside it; if it happens again, use Download diagnostics in Settings and report it.");
|
|
55
56
|
})
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { transact } from "../../kernel/db/tx.js";
|
|
2
|
+
import { internalError } from "../../kernel/errors.js";
|
|
2
3
|
import { narrationRegenerationToken } from "../narration/plan.js";
|
|
3
4
|
import { currentRevisionId } from "../revisions/repo.js";
|
|
4
5
|
import { bindNarrationReuse, narrationOrdinal } from "./runtime-narration-reuse.js";
|
|
@@ -25,7 +26,7 @@ export function admitInitialRevision(deps, view, catalogue) {
|
|
|
25
26
|
if (deps.db
|
|
26
27
|
.prepare("SELECT 1 FROM revision_work WHERE project_id=? LIMIT 1")
|
|
27
28
|
.get(view.revision.projectId) !== undefined)
|
|
28
|
-
throw new Error("
|
|
29
|
+
throw new Error(internalError("this project was started twice"));
|
|
29
30
|
const snapshot = executionCatalogue(catalogue, view.revision.config);
|
|
30
31
|
const plan = executionPlan(deps, view, snapshot);
|
|
31
32
|
for (const recipe of plan.recipes) {
|
|
@@ -35,7 +36,7 @@ export function admitInitialRevision(deps, view, catalogue) {
|
|
|
35
36
|
const logicalKey = recipe.input.kind === "tts" ? `${recipe.input.logicalKey}:1` : recipe.key;
|
|
36
37
|
const anchor = view.revision.fingerprints[logicalKey] ?? desired;
|
|
37
38
|
if (anchor === undefined)
|
|
38
|
-
throw new Error(`
|
|
39
|
+
throw new Error(internalError(`step ${recipe.key} has no saved starting point`));
|
|
39
40
|
const reuse = plan.work.find((row) => row.key === recipe.key)?.disposition === "reuse";
|
|
40
41
|
if (reuse)
|
|
41
42
|
bindNarrationReuse(deps, view, recipe, narrationOrdinal(plan.recipes, recipe.key));
|
|
@@ -49,7 +50,7 @@ export function insertInvocation(deps, view, recipe, catalogue, anchor, complete
|
|
|
49
50
|
.prepare("SELECT id FROM stages WHERE project_id=? AND kind=?")
|
|
50
51
|
.get(projectId, recipe.stage);
|
|
51
52
|
if (typeof stage?.id !== "string")
|
|
52
|
-
throw new Error("
|
|
53
|
+
throw new Error(internalError("a step has no matching stage"));
|
|
53
54
|
const work = {
|
|
54
55
|
projectId,
|
|
55
56
|
revisionId,
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
import { internalError } from "../../kernel/errors.js";
|
|
3
|
+
import { fillLateKeywords, mentionsLateKeyword } from "../keywords/fill.js";
|
|
2
4
|
import { externalReviewWaitMs } from "../reviews/external-model.js";
|
|
3
5
|
import { openExternalReview } from "../reviews/external-repo.js";
|
|
4
6
|
import { externalReviewByFingerprint } from "../reviews/external-rows.js";
|
|
@@ -6,8 +8,10 @@ import { reviewStages } from "../reviews/model.js";
|
|
|
6
8
|
import { nextAttempt, reviewOutcome } from "../reviews/outcome.js";
|
|
7
9
|
import { latestVerdict, saveVerdict } from "../reviews/repo.js";
|
|
8
10
|
import { exportSnapshot } from "./runtime-export-inputs.js";
|
|
11
|
+
import { lateValuesOf } from "./runtime-keywords.js";
|
|
9
12
|
import { publishResult } from "./runtime-publication.js";
|
|
10
13
|
import { reviewMaterial } from "./runtime-review.js";
|
|
14
|
+
import { pieceAlreadyDone } from "./work-records.js";
|
|
11
15
|
// What `recipe-reviews.ts` saves for a review an external agent answers, by position.
|
|
12
16
|
const valuesSchema = z.tuple([
|
|
13
17
|
z.enum(reviewStages),
|
|
@@ -21,16 +25,18 @@ const valuesSchema = z.tuple([
|
|
|
21
25
|
// agent's verdict through MCP. Waiting is not "held": the stage's other reviews still open
|
|
22
26
|
// theirs in the same pass, and `agentReviewHold` keeps the runner from claiming it again.
|
|
23
27
|
export async function executeAgentReviewRecipe(deps, context, piece) {
|
|
24
|
-
if (deps.db
|
|
25
|
-
.prepare("SELECT state FROM revision_work_pieces WHERE id=? AND work_id=?")
|
|
26
|
-
.get(piece.id, context.work.workId)?.state === "done")
|
|
28
|
+
if (pieceAlreadyDone(deps.db, context.work.workId, piece.id))
|
|
27
29
|
return "done";
|
|
28
30
|
if (!context.maySubmit(piece.id))
|
|
29
31
|
return "held";
|
|
30
32
|
const values = piece.input.kind === "local" ? valuesSchema.safeParse(piece.input.values) : undefined;
|
|
31
33
|
if (values === undefined || !values.success)
|
|
32
|
-
throw new Error("
|
|
33
|
-
const [stage, itemKey, ,
|
|
34
|
+
throw new Error(internalError("a review step was set up wrongly"));
|
|
35
|
+
const [stage, itemKey, , planned, mode, retries] = values.data;
|
|
36
|
+
// The release date and the length are filled as the review opens, like a request a model is sent.
|
|
37
|
+
const prompt = mentionsLateKeyword(planned)
|
|
38
|
+
? fillLateKeywords(planned, await lateValuesOf(deps, context))
|
|
39
|
+
: planned;
|
|
34
40
|
const projectId = context.work.projectId;
|
|
35
41
|
const known = externalReviewByFingerprint(deps.db, projectId, piece.fingerprint);
|
|
36
42
|
if (known === undefined || known.state === "superseded" || known.state === "canceled") {
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { mkdtempSync, readFileSync, rmSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
|
+
import { errorText, internalError } from "../../kernel/errors.js";
|
|
4
|
+
import { isReadyOutput } from "../revisions/view.js";
|
|
3
5
|
import { discardPreparedAssets, writeAsset } from "../storage/assets.js";
|
|
4
6
|
import { outputPath, projectDir } from "../storage/layout.js";
|
|
5
7
|
import { runFfmpeg } from "../video/ffmpeg.js";
|
|
6
8
|
import { executionView } from "./runtime-plan.js";
|
|
7
9
|
import { preparedResult, publishResult } from "./runtime-publication.js";
|
|
10
|
+
import { pieceAlreadyDone } from "./work-records.js";
|
|
8
11
|
// Animate images: one still of the slideshow sent to the image provider's image-to-video
|
|
9
12
|
// model, and the clip it makes saved beside the image. The still goes up as a small JPEG, so
|
|
10
13
|
// the request stays well under what either provider takes inline.
|
|
@@ -16,17 +19,15 @@ import { preparedResult, publishResult } from "./runtime-publication.js";
|
|
|
16
19
|
// for, and keeps a JPEG to a few hundred KB.
|
|
17
20
|
const sentWidth = 1280;
|
|
18
21
|
export async function executeAnimateRecipe(deps, context, providers, piece) {
|
|
19
|
-
if (deps.db
|
|
20
|
-
.prepare("SELECT state FROM revision_work_pieces WHERE id=? AND work_id=?")
|
|
21
|
-
.get(piece.id, context.work.workId)?.state === "done")
|
|
22
|
+
if (pieceAlreadyDone(deps.db, context.work.workId, piece.id))
|
|
22
23
|
return "done";
|
|
23
24
|
const input = piece.input;
|
|
24
25
|
if (input.kind !== "image" || input.animate === undefined)
|
|
25
|
-
throw new Error("
|
|
26
|
+
throw new Error(internalError("an animated image was set up wrongly"));
|
|
26
27
|
const imageKey = piece.key.slice("animate:".length);
|
|
27
28
|
const view = executionView(deps, context.work.projectId, context.work.revisionId);
|
|
28
29
|
const index = (view?.revision.content.imageOrder.indexOf(imageKey) ?? -1) + 1;
|
|
29
|
-
const still = view?.outputs.find((row) => row.workKey === `image:${imageKey}` && row
|
|
30
|
+
const still = view?.outputs.find((row) => row.workKey === `image:${imageKey}` && isReadyOutput(row));
|
|
30
31
|
const fallback = async (reason) => {
|
|
31
32
|
deps.log.write("warn", "video.animate.fallback", { detail: reason });
|
|
32
33
|
await publishResult(deps, context, piece, [], {
|
|
@@ -38,7 +39,7 @@ export async function executeAnimateRecipe(deps, context, providers, piece) {
|
|
|
38
39
|
return fallback("its image wasn't ready to animate. Use More → Render the video again in the Video section after the image is made.");
|
|
39
40
|
const animate = providers.forPiece(piece.id).animate;
|
|
40
41
|
if (animate === undefined)
|
|
41
|
-
throw new Error("
|
|
42
|
+
throw new Error(internalError("animating images isn't wired up in this build"));
|
|
42
43
|
if (!context.maySubmit(piece.id))
|
|
43
44
|
return "held";
|
|
44
45
|
let made;
|
|
@@ -55,7 +56,7 @@ export async function executeAnimateRecipe(deps, context, providers, piece) {
|
|
|
55
56
|
catch (error) {
|
|
56
57
|
if (context.signal.aborted)
|
|
57
58
|
throw error;
|
|
58
|
-
return fallback(`${
|
|
59
|
+
return fallback(`${errorText(error)} To try again, use More → Render the video again in the Video section.`);
|
|
59
60
|
}
|
|
60
61
|
if (!made.ok)
|
|
61
62
|
return "held";
|
|
@@ -73,7 +74,7 @@ export async function executeAnimateRecipe(deps, context, providers, piece) {
|
|
|
73
74
|
stage: context.work.kind,
|
|
74
75
|
provider: input.provider,
|
|
75
76
|
model: input.model,
|
|
76
|
-
});
|
|
77
|
+
}, context.work.projectId);
|
|
77
78
|
}
|
|
78
79
|
finally {
|
|
79
80
|
discardPreparedAssets(deps, [asset]);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { transact } from "../../kernel/db/tx.js";
|
|
3
|
+
import { internalError } from "../../kernel/errors.js";
|
|
3
4
|
import { continuationLimit, continuationMessages } from "../article/continuation.js";
|
|
4
5
|
import { currentRevisionId, revisionById } from "../revisions/repo.js";
|
|
5
6
|
import { recipe } from "./recipe-model.js";
|
|
@@ -12,14 +13,14 @@ const answerSchema = z.object({
|
|
|
12
13
|
});
|
|
13
14
|
export async function executeArticleRequests(deps, context, providers, initial) {
|
|
14
15
|
if (initial.input.kind !== "llm")
|
|
15
|
-
throw new Error("
|
|
16
|
+
throw new Error(internalError("the article step has no AI request"));
|
|
16
17
|
let piece = initial;
|
|
17
18
|
let text = "";
|
|
18
19
|
let inputTokens = 0;
|
|
19
20
|
let outputTokens = 0;
|
|
20
21
|
for (let part = 0; part <= continuationLimit; part += 1) {
|
|
21
22
|
if (piece.input.kind !== "llm")
|
|
22
|
-
throw new Error("
|
|
23
|
+
throw new Error(internalError("an article continuation has no AI request"));
|
|
23
24
|
const saved = deps.db
|
|
24
25
|
.prepare("SELECT result_json FROM revision_work_pieces WHERE id=? AND work_id=?")
|
|
25
26
|
.get(piece.id, context.work.workId);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { internalError } from "../../kernel/errors.js";
|
|
1
2
|
import { checkpointClosure, checkpointFingerprint } from "../checkpoints/fingerprint.js";
|
|
2
3
|
import { saveCheckpointSet } from "../checkpoints/repo.js";
|
|
3
4
|
import { currentRevisionId } from "../revisions/repo.js";
|
|
@@ -11,14 +12,14 @@ export function admitReviewedCheckpoints(deps, projectIds, reviewed, catalogue)
|
|
|
11
12
|
const revisionId = currentRevisionId(deps.db, projectId);
|
|
12
13
|
const view = revisionId === undefined ? undefined : getRevisionView(deps, projectId, revisionId);
|
|
13
14
|
if (!view)
|
|
14
|
-
throw new Error("
|
|
15
|
+
throw new Error(internalError("the project version to review is missing"));
|
|
15
16
|
const plan = executionPlan(deps, view, executionCatalogue(catalogue, view.revision.config));
|
|
16
17
|
const checkpoints = gates.map((gate) => {
|
|
17
18
|
const work = deps.db
|
|
18
19
|
.prepare("SELECT id FROM revision_work WHERE project_id=? AND revision_id=? AND kind=? ORDER BY id LIMIT 1")
|
|
19
20
|
.get(projectId, view.revision.id, gate.stage);
|
|
20
21
|
if (typeof work?.id !== "string")
|
|
21
|
-
throw new Error("
|
|
22
|
+
throw new Error(internalError("a review checkpoint has no matching stage"));
|
|
22
23
|
return {
|
|
23
24
|
checkpointId: gate.checkpointId,
|
|
24
25
|
stage: gate.stage,
|
|
@@ -34,11 +35,11 @@ export function admitReviewedCheckpoints(deps, projectIds, reviewed, catalogue)
|
|
|
34
35
|
createdAt: deps.clock.now().toISOString(),
|
|
35
36
|
});
|
|
36
37
|
if (!saved.ok)
|
|
37
|
-
throw new Error("
|
|
38
|
+
throw new Error(internalError("the review checkpoints could not be saved"));
|
|
38
39
|
return saved.value.map((row) => {
|
|
39
40
|
const gate = gates.find((gate) => gate.checkpointId === row.checkpointId);
|
|
40
41
|
if (!gate)
|
|
41
|
-
throw new Error("
|
|
42
|
+
throw new Error(internalError("a saved review checkpoint could not be matched"));
|
|
42
43
|
return { ...row, reviewedFingerprint: gate.fingerprint };
|
|
43
44
|
});
|
|
44
45
|
});
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import { readFileSync } from "node:fs";
|
|
2
|
+
import { errorText, internalError } from "../../kernel/errors.js";
|
|
2
3
|
import { readDocumentAssets } from "../document/fonts.js";
|
|
3
4
|
import { renderDocument } from "../document/render.js";
|
|
4
5
|
import { resolvedDocumentTheme } from "../document/theme.js";
|
|
6
|
+
import { readyOutput } from "../revisions/view.js";
|
|
5
7
|
import { writeAsset } from "../storage/assets.js";
|
|
6
8
|
import { outputPath } from "../storage/layout.js";
|
|
7
9
|
import { executionPlan, executionView, savedCatalogue } from "./runtime-plan.js";
|
|
8
10
|
import { preparedResult, publishResult } from "./runtime-publication.js";
|
|
11
|
+
import { pieceAlreadyDone } from "./work-records.js";
|
|
9
12
|
// Lays the saved article out as a PDF. Local and quick: no provider, no charge.
|
|
10
13
|
export async function executeDocumentRecipe(deps, context, piece) {
|
|
11
|
-
if (deps.db
|
|
12
|
-
.prepare("SELECT state FROM revision_work_pieces WHERE id=? AND work_id=?")
|
|
13
|
-
.get(piece.id, context.work.workId)?.state === "done")
|
|
14
|
+
if (pieceAlreadyDone(deps.db, context.work.workId, piece.id))
|
|
14
15
|
return "done";
|
|
15
16
|
if (!context.maySubmit(piece.id))
|
|
16
17
|
return "held";
|
|
@@ -36,7 +37,7 @@ export async function executeDocumentRecipe(deps, context, piece) {
|
|
|
36
37
|
cover = new Uint8Array(readFileSync(outputPath(deps.paths, projectId, thumbnail.output.path)));
|
|
37
38
|
}
|
|
38
39
|
catch (error) {
|
|
39
|
-
throw new Error(`The document's cover is the project's thumbnail, and its file can't be read (${
|
|
40
|
+
throw new Error(`The document's cover is the project's thumbnail, and its file can't be read (${errorText(error)}). Regenerate or upload the thumbnail again (More → make it again in its section on Thumbnail, or Edit project → Thumbnail), then use Try again on Document.`, { cause: error });
|
|
40
41
|
}
|
|
41
42
|
}
|
|
42
43
|
const rendered = renderDocument({
|
|
@@ -60,7 +61,7 @@ export async function executeDocumentRecipe(deps, context, piece) {
|
|
|
60
61
|
const asset = writeAsset(deps, projectId, "document.pdf", rendered.bytes);
|
|
61
62
|
// publishResult discards the file itself when the publication doesn't commit.
|
|
62
63
|
await publishResult(deps, context, piece, [preparedResult(deps, context, piece, "document_pdf", asset)], { pages: rendered.pages, words: rendered.words, cover: rendered.cover });
|
|
63
|
-
deps.count?.("stage.completed", { stage: "document" });
|
|
64
|
+
deps.count?.("stage.completed", { stage: "document" }, context.work.projectId);
|
|
64
65
|
return "done";
|
|
65
66
|
}
|
|
66
67
|
function documentView(deps, context, piece) {
|
|
@@ -69,16 +70,12 @@ function documentView(deps, context, piece) {
|
|
|
69
70
|
.prepare("SELECT recipe_context FROM revision_work WHERE id=?")
|
|
70
71
|
.get(context.work.workId);
|
|
71
72
|
if (view === undefined || row === undefined)
|
|
72
|
-
throw new Error("
|
|
73
|
+
throw new Error(internalError("the project version the document belongs to is missing", "Use Try again on Document"));
|
|
73
74
|
const recipe = executionPlan(deps, view, savedCatalogue(row.recipe_context)).recipes.find((one) => one.key === piece.key && one.fingerprint === piece.fingerprint);
|
|
74
75
|
if (recipe === undefined || recipe.unresolved)
|
|
75
76
|
throw new Error("The project changed after this document was queued, so it no longer matches the saved article. Use Choose what to remake (in the project's More menu) (or Try again on Document) to make it from the current version.");
|
|
76
77
|
return view;
|
|
77
78
|
}
|
|
78
79
|
function ready(view, role, workKey) {
|
|
79
|
-
return view
|
|
80
|
-
row.available &&
|
|
81
|
-
row.state === "ready" &&
|
|
82
|
-
row.workKey === workKey &&
|
|
83
|
-
row.output.role === role);
|
|
80
|
+
return readyOutput(view, { workKey, role });
|
|
84
81
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { errorText } from "../../kernel/errors.js";
|
|
2
|
+
import { assetPathOrUndefined } from "../revisions/mutation-assets.js";
|
|
2
3
|
import { outputPath } from "../storage/layout.js";
|
|
3
4
|
import { usesAmbientBed } from "../video/ambient-bed.js";
|
|
4
5
|
import { probeDurationMs } from "../video/ffmpeg.js";
|
|
@@ -19,23 +20,17 @@ export async function exportBed(deps, context, view) {
|
|
|
19
20
|
return { source: { kind: "noise", preset: bed.source }, ...settings };
|
|
20
21
|
const fix = "Make the video again from Play with another file under Video and style → Ambient sound, or pick Rain, Fireplace or Wind there instead.";
|
|
21
22
|
const assetId = view.revision.content.ambientBed;
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
.safeParse(assetId === undefined
|
|
25
|
-
? undefined
|
|
26
|
-
: deps.db
|
|
27
|
-
.prepare("SELECT path FROM project_assets WHERE project_id=? AND id=?")
|
|
28
|
-
.get(context.work.projectId, assetId));
|
|
29
|
-
if (!row.success)
|
|
23
|
+
const saved = assetId === undefined ? undefined : assetPathOrUndefined(deps, context.work.projectId, assetId);
|
|
24
|
+
if (saved === undefined)
|
|
30
25
|
throw new Error(`The ambient sound's audio file is no longer in the project. ${fix}`);
|
|
31
|
-
const path = outputPath(deps.paths, context.work.projectId,
|
|
26
|
+
const path = outputPath(deps.paths, context.work.projectId, saved);
|
|
32
27
|
let durationMs;
|
|
33
28
|
try {
|
|
34
29
|
durationMs = await probeDurationMs(deps.ffmpeg, path, context.signal, deps.log);
|
|
35
30
|
}
|
|
36
31
|
catch (error) {
|
|
37
32
|
context.signal.throwIfAborted();
|
|
38
|
-
throw new Error(`The ambient sound's audio file couldn't be read as audio (${
|
|
33
|
+
throw new Error(`The ambient sound's audio file couldn't be read as audio (${errorText(error)}). ${fix}`);
|
|
39
34
|
}
|
|
40
35
|
if (durationMs <= 0)
|
|
41
36
|
throw new Error(`The ambient sound's audio file holds no sound. ${fix}`);
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import { readFileSync } from "node:fs";
|
|
2
1
|
import { extname } from "node:path";
|
|
3
2
|
import { z } from "zod";
|
|
4
3
|
import { usesFigureCards, usesYoutubeDescription } from "../admission/rules.js";
|
|
5
4
|
import { captionFont, captionFontDeps } from "../fonts/coverage.js";
|
|
6
5
|
import { resolveFont } from "../fonts/index.js";
|
|
6
|
+
import { isReadyOutput, readyOutput } from "../revisions/view.js";
|
|
7
7
|
import { outputPath } from "../storage/layout.js";
|
|
8
8
|
import { headingChapters } from "../video/chapters.js";
|
|
9
9
|
import { sentenceCutPoints } from "../video/cuts.js";
|
|
10
10
|
import { usesChapterCards, usesNarrationCuts, videoEditOf, } from "../video/edit-settings.js";
|
|
11
11
|
import { probeDurationMs } from "../video/ffmpeg.js";
|
|
12
12
|
import { passageSpans } from "../video/figure-spans.js";
|
|
13
|
-
import {
|
|
13
|
+
import { readTimingWords } from "./runtime-subtitles.js";
|
|
14
14
|
// The containers an uploaded clip may come in; anything else in the images is a still.
|
|
15
15
|
const clipExtensions = new Set([".mp4", ".mov", ".m4v", ".webm", ".mkv"]);
|
|
16
16
|
export function isClipPath(path) {
|
|
@@ -19,7 +19,7 @@ export function isClipPath(path) {
|
|
|
19
19
|
export async function exportEdit(deps, context, view, images) {
|
|
20
20
|
const config = view.revision.config;
|
|
21
21
|
const order = view.revision.content.imageOrder;
|
|
22
|
-
const ready = (key) => view
|
|
22
|
+
const ready = (key) => readyOutput(view, { workKey: key });
|
|
23
23
|
// Clips: an animated image's clip first, then an uploaded clip in the image's own place.
|
|
24
24
|
const clips = [];
|
|
25
25
|
for (const [index, key] of order.entries()) {
|
|
@@ -109,15 +109,8 @@ async function titleFont(deps, config) {
|
|
|
109
109
|
...(config.titleStyle?.color === undefined ? {} : { color: config.titleStyle.color }),
|
|
110
110
|
};
|
|
111
111
|
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
row.available &&
|
|
115
|
-
row.state === "ready" &&
|
|
116
|
-
row.workKey === "subtitles:timing" &&
|
|
117
|
-
row.output.role === "subtitle_words");
|
|
118
|
-
if (timing === undefined)
|
|
119
|
-
throw new Error("The narration's word timing, which the video's cuts and chapter cards follow, is missing. Use More → Render the video again in the Video section, then Try again.");
|
|
120
|
-
return wordsSchema.parse(JSON.parse(readFileSync(outputPath(deps.paths, context.work.projectId, timing.output.path), "utf8"))).words;
|
|
112
|
+
function timingWords(deps, context, view) {
|
|
113
|
+
return readTimingWords(deps, context, view, "the video's cuts and chapter cards follow").words;
|
|
121
114
|
}
|
|
122
115
|
// The YouTube description's chapters when that step runs, the article's headings otherwise.
|
|
123
116
|
function chaptersOf(view, config, words) {
|
|
@@ -150,9 +143,7 @@ async function clipSeconds(deps, context, path, place) {
|
|
|
150
143
|
// found in the timing is left out rather than shown at the wrong moment.
|
|
151
144
|
export function figureShots(deps, context, view, format = view.revision.config.format, words = timingWords(deps, context, view)) {
|
|
152
145
|
const cards = view.outputs
|
|
153
|
-
.filter((row) => row
|
|
154
|
-
row.available &&
|
|
155
|
-
row.state === "ready" &&
|
|
146
|
+
.filter((row) => isReadyOutput(row) &&
|
|
156
147
|
row.output.role === "figure_card" &&
|
|
157
148
|
row.workKey.startsWith("figure:card:") &&
|
|
158
149
|
(row.output.meta.format ?? view.revision.config.format) === format)
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { readFileSync } from "node:fs";
|
|
2
2
|
import { z } from "zod";
|
|
3
|
+
import { internalError } from "../../kernel/errors.js";
|
|
3
4
|
import { narrationAliasesOf, usesNarrationPreparation, usesPronunciationGlossary, } from "../admission/rules.js";
|
|
4
5
|
import { plainText } from "../article/plain.js";
|
|
5
6
|
import { splitEndMatter } from "../article/split.js";
|
|
6
7
|
import { usesLoudness } from "../loudness/model.js";
|
|
8
|
+
import { donePiece, isReadyOutput, readyOutput } from "../revisions/view.js";
|
|
7
9
|
import { outputPath } from "../storage/layout.js";
|
|
8
10
|
import { probeDurationMs } from "../video/ffmpeg.js";
|
|
9
11
|
import { audioTimeline } from "../video/plan.js";
|
|
@@ -17,11 +19,11 @@ export function exportSnapshot(deps, context, piece) {
|
|
|
17
19
|
.prepare("SELECT recipe_context FROM revision_work WHERE id=?")
|
|
18
20
|
.get(context.work.workId);
|
|
19
21
|
if (view === undefined || row === undefined)
|
|
20
|
-
throw new Error("
|
|
22
|
+
throw new Error(internalError("the project version being exported is missing"));
|
|
21
23
|
const plan = executionPlan(deps, view, savedCatalogue(row.recipe_context));
|
|
22
24
|
const recipe = plan.recipes.find((one) => one.key === piece.key && one.fingerprint === piece.fingerprint);
|
|
23
25
|
if (recipe === undefined || recipe.deferred || recipe.unresolved)
|
|
24
|
-
throw new Error("
|
|
26
|
+
throw new Error(internalError("the export no longer matches the project's saved inputs"));
|
|
25
27
|
return { view, plan };
|
|
26
28
|
}
|
|
27
29
|
export async function revisionAudio(deps, context, view,
|
|
@@ -45,9 +47,7 @@ export async function narrationAudio(deps, view, options = {}) {
|
|
|
45
47
|
const levelled = options.levelled === true && usesLoudness(config) && config.sources.audio === "generate";
|
|
46
48
|
const input = async (role) => {
|
|
47
49
|
const segment = role === "audio_body" ? "body" : role === "audio_intro" ? "intro" : "outro";
|
|
48
|
-
const row = view.outputs.find((one) => one
|
|
49
|
-
one.available &&
|
|
50
|
-
one.state === "ready" &&
|
|
50
|
+
const row = view.outputs.find((one) => isReadyOutput(one) &&
|
|
51
51
|
(levelled
|
|
52
52
|
? one.output.role === "audio_levelled" && one.workKey === levelKey(segment)
|
|
53
53
|
: one.output.role === role));
|
|
@@ -95,7 +95,7 @@ export function revisionTranscript(deps, snapshot, kind) {
|
|
|
95
95
|
const concat = plan.recipes.find((one) => one.key === (kind === "body" ? "audio:body:concat" : `audio:${kind}`));
|
|
96
96
|
if (concat !== undefined) {
|
|
97
97
|
const texts = concat.dependsOn.map((key) => {
|
|
98
|
-
const row = view
|
|
98
|
+
const row = donePiece(view, key);
|
|
99
99
|
const payload = row?.piece.payload === null || row?.piece.payload === undefined
|
|
100
100
|
? undefined
|
|
101
101
|
: z.object({ text: z.string().optional() }).parse(JSON.parse(row.piece.payload));
|
|
@@ -114,7 +114,7 @@ export function revisionTranscript(deps, snapshot, kind) {
|
|
|
114
114
|
return texts.join("\n");
|
|
115
115
|
}
|
|
116
116
|
if (kind === "body") {
|
|
117
|
-
const row = view
|
|
117
|
+
const row = readyOutput(view, { role: "article_txt" });
|
|
118
118
|
if (row !== undefined)
|
|
119
119
|
return readFileSync(outputPath(deps.paths, view.revision.projectId, row.output.path), "utf8");
|
|
120
120
|
if (view.articleMarkdown !== null)
|
|
@@ -5,9 +5,9 @@ import { renderShort, shortFrame } from "../shorts/render.js";
|
|
|
5
5
|
import { allocateAsset, discardPreparedAssets, sealAsset } from "../storage/assets.js";
|
|
6
6
|
import { projectDir } from "../storage/layout.js";
|
|
7
7
|
import { probeDurationMs } from "../video/ffmpeg.js";
|
|
8
|
-
import { slideshowImages } from "./runtime-export.js";
|
|
8
|
+
import { exportMachine, slideshowImages, warningsOf, } from "./runtime-export.js";
|
|
9
9
|
import { preparedResult, preparedText, publishResult } from "./runtime-publication.js";
|
|
10
|
-
import {
|
|
10
|
+
import { readTimingWords } from "./runtime-subtitles.js";
|
|
11
11
|
// A short-mode project's video (`admission/short-mode.ts`): the whole narration timeline as
|
|
12
12
|
// one clip through the Shorts renderer, so it looks like every short Slopify cuts from a long
|
|
13
13
|
// video - the images moving as the project says, the title on top and big word-by-word
|
|
@@ -16,7 +16,7 @@ export async function executeShortExport(deps, context, piece, snapshot, timelin
|
|
|
16
16
|
const { view } = snapshot;
|
|
17
17
|
const config = view.revision.config;
|
|
18
18
|
const images = slideshowImages(deps, context, view);
|
|
19
|
-
const words =
|
|
19
|
+
const words = readTimingWords(deps, context, view, "the shorts are cut and captioned from").words;
|
|
20
20
|
const seconds = timeline.reduce((sum, segment) => sum + segment.seconds, 0);
|
|
21
21
|
if (seconds <= 0)
|
|
22
22
|
throw new Error("The short has no narration to play, so there is nothing to render. Let the Narration stage finish (Resume, or Try again on it), then retry this stage.");
|
|
@@ -28,8 +28,11 @@ export async function executeShortExport(deps, context, piece, snapshot, timelin
|
|
|
28
28
|
const directory = projectDir(deps.paths, context.work.projectId);
|
|
29
29
|
const relativePath = (path) => relative(directory, path).split(sep).join("/");
|
|
30
30
|
try {
|
|
31
|
+
const machine = await exportMachine(deps, context.work.projectId);
|
|
31
32
|
const master = await renderShort({
|
|
32
33
|
bin: deps.ffmpeg,
|
|
34
|
+
machine: machine.machine,
|
|
35
|
+
notice: machine.notice,
|
|
33
36
|
master: masterGoal(config, "video"),
|
|
34
37
|
timeline,
|
|
35
38
|
start: 0,
|
|
@@ -58,6 +61,7 @@ export async function executeShortExport(deps, context, piece, snapshot, timelin
|
|
|
58
61
|
const asset = sealAsset(deps, pending);
|
|
59
62
|
prepared.push(preparedResult(deps, context, piece, "video", asset, durationMs, {
|
|
60
63
|
subtitlesMode: "off",
|
|
64
|
+
...warningsOf(machine.notices),
|
|
61
65
|
...(master === undefined ? {} : { master }),
|
|
62
66
|
}));
|
|
63
67
|
prepared.push(preparedText(deps, context, piece, "render_params", "render.json", JSON.stringify({
|
|
@@ -76,7 +80,7 @@ export async function executeShortExport(deps, context, piece, snapshot, timelin
|
|
|
76
80
|
output: pending.path,
|
|
77
81
|
})));
|
|
78
82
|
await publishResult(deps, context, piece, prepared, { totalSeconds: seconds }, asset);
|
|
79
|
-
deps.count?.("stage.completed", { stage: "video" });
|
|
83
|
+
deps.count?.("stage.completed", { stage: "video" }, context.work.projectId);
|
|
80
84
|
return "done";
|
|
81
85
|
}
|
|
82
86
|
finally {
|