@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,9 +1,11 @@
|
|
|
1
1
|
import { basename } from "node:path";
|
|
2
|
+
import { internalError } from "../../kernel/errors.js";
|
|
2
3
|
import { referenceKey, thumbnailVariant } from "../admission/model.js";
|
|
3
4
|
import { plainText } from "../article/plain.js";
|
|
4
5
|
import { splitEndMatter } from "../article/split.js";
|
|
5
6
|
import { checkAppearance } from "../images/appearance.js";
|
|
6
7
|
import { checkScenes, sceneCountOf } from "../images/scenes.js";
|
|
8
|
+
import { checkDigest } from "../keywords/digest.js";
|
|
7
9
|
import { spokenPassage } from "../narration/describe.js";
|
|
8
10
|
import { observeNarration } from "../narration/live.js";
|
|
9
11
|
import { validatePreparation } from "../narration/preparation.js";
|
|
@@ -11,24 +13,25 @@ import { prepareRequests } from "../narration/steering.js";
|
|
|
11
13
|
import { chaptersFrom } from "../research/planner.js";
|
|
12
14
|
import { sourcedAnswer } from "../research/synthesis.js";
|
|
13
15
|
import { imageReviewers } from "../reviews/model.js";
|
|
16
|
+
import { checkPost, postText } from "../social/post-prompt.js";
|
|
14
17
|
import { discardPreparedAssets, writeAsset } from "../storage/assets.js";
|
|
15
18
|
import { outputPath } from "../storage/layout.js";
|
|
16
19
|
import { probeDurationMs } from "../video/ffmpeg.js";
|
|
17
20
|
import { parseAttribution } from "../voices/attribution.js";
|
|
18
21
|
import { parseScript } from "../voices/script.js";
|
|
19
22
|
import { imageAppearanceKey } from "./recipe-appearance.js";
|
|
23
|
+
import { digestKey } from "./recipe-digest.js";
|
|
20
24
|
import { imageScenesKey, thumbnailScenesKey } from "./recipe-scenes.js";
|
|
21
25
|
import { executeArticleRequests } from "./runtime-article.js";
|
|
22
26
|
import { imageCall } from "./runtime-image.js";
|
|
23
27
|
import { frozenInstructions } from "./runtime-instructions.js";
|
|
24
28
|
import { articlePicture } from "./runtime-pictures.js";
|
|
25
|
-
import { executionPlan, executionView,
|
|
29
|
+
import { executionPlan, executionView, workCatalogue, workCatalogueIfSaved, } from "./runtime-plan.js";
|
|
26
30
|
import { preparedResult, preparedTexts, publishResult } from "./runtime-publication.js";
|
|
27
31
|
import { clearSoftening, softenedPrompt, softeningRequested, softenMessages } from "./soften.js";
|
|
32
|
+
import { pieceAlreadyDone } from "./work-records.js";
|
|
28
33
|
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")
|
|
34
|
+
if (pieceAlreadyDone(deps.db, context.work.workId, piece.id))
|
|
32
35
|
return "done";
|
|
33
36
|
const input = piece.input;
|
|
34
37
|
const wrapped = providers.forPiece(piece.id);
|
|
@@ -64,7 +67,7 @@ export async function executeProviderRecipe(deps, context, providers, piece) {
|
|
|
64
67
|
...(segment === undefined ? {} : { segment }),
|
|
65
68
|
tokensIn: answer.value.usage?.inputTokens ?? 0,
|
|
66
69
|
tokensOut: answer.value.usage?.outputTokens ?? 0,
|
|
67
|
-
});
|
|
70
|
+
}, context.work.projectId);
|
|
68
71
|
return "done";
|
|
69
72
|
}
|
|
70
73
|
if (input.kind === "tts") {
|
|
@@ -116,7 +119,7 @@ export async function executeProviderRecipe(deps, context, providers, piece) {
|
|
|
116
119
|
provider: input.provider,
|
|
117
120
|
model: input.model,
|
|
118
121
|
...(durationMs === undefined ? {} : { audioSeconds: durationMs / 1000 }),
|
|
119
|
-
});
|
|
122
|
+
}, context.work.projectId);
|
|
120
123
|
}
|
|
121
124
|
finally {
|
|
122
125
|
discardPreparedAssets(deps, [asset]);
|
|
@@ -164,10 +167,10 @@ export async function executeProviderRecipe(deps, context, providers, piece) {
|
|
|
164
167
|
provider: input.provider,
|
|
165
168
|
model: input.model,
|
|
166
169
|
...(variant !== undefined ? { thumbnails: 1 } : { images: 1 }),
|
|
167
|
-
});
|
|
170
|
+
}, context.work.projectId);
|
|
168
171
|
return "done";
|
|
169
172
|
}
|
|
170
|
-
throw new Error("
|
|
173
|
+
throw new Error(internalError("this step has no provider request to run"));
|
|
171
174
|
}
|
|
172
175
|
// Soften and retry (`soften.ts`): the project's AI model rewords a refused image prompt
|
|
173
176
|
// before the image is drawn again. Undefined when nobody asked, or the project has no model.
|
|
@@ -209,6 +212,14 @@ function checkAnswer(piece, answer) {
|
|
|
209
212
|
const checked = checkAppearance(answer.text);
|
|
210
213
|
return checked.ok ? undefined : checked.reason;
|
|
211
214
|
}
|
|
215
|
+
// The keyword digest: every part written.
|
|
216
|
+
if (piece.key === digestKey && piece.input.kind === "llm") {
|
|
217
|
+
const checked = checkDigest(answer.text);
|
|
218
|
+
return checked.ok ? undefined : checked.reason;
|
|
219
|
+
}
|
|
220
|
+
// A post for another site: within its limit.
|
|
221
|
+
if (piece.input.kind === "llm" && piece.input.social !== undefined)
|
|
222
|
+
return checkPost(answer.text, piece.input.social);
|
|
212
223
|
if (piece.key === "research:planner")
|
|
213
224
|
return chaptersFrom(answer.text).length === 0
|
|
214
225
|
? "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 the Providers section of Edit project."
|
|
@@ -240,7 +251,11 @@ async function publishText(deps, context, piece, answer) {
|
|
|
240
251
|
throw new Error(checked.reason);
|
|
241
252
|
await publishResult(deps, context, piece, preparedTexts(deps, context, piece, [
|
|
242
253
|
["instructions", "instructions.md", frozenInstructions(deps, context, piece)],
|
|
243
|
-
]), {
|
|
254
|
+
]), {
|
|
255
|
+
scenes: checked.scenes,
|
|
256
|
+
...(checked.details === undefined ? {} : { details: checked.details }),
|
|
257
|
+
text: answer.text,
|
|
258
|
+
});
|
|
244
259
|
return;
|
|
245
260
|
}
|
|
246
261
|
if (piece.key === imageAppearanceKey && piece.input.kind === "llm") {
|
|
@@ -252,6 +267,37 @@ async function publishText(deps, context, piece, answer) {
|
|
|
252
267
|
]), { appearance: checked.appearance, text: answer.text });
|
|
253
268
|
return;
|
|
254
269
|
}
|
|
270
|
+
if (piece.input.kind === "llm" && piece.input.social !== undefined) {
|
|
271
|
+
const target = piece.input.social;
|
|
272
|
+
const problem = checkPost(answer.text, target);
|
|
273
|
+
if (problem !== undefined)
|
|
274
|
+
throw new Error(problem);
|
|
275
|
+
const text = postText(answer.text);
|
|
276
|
+
const asset = writeAsset(deps, context.work.projectId, `post-${target.platform}.txt`, Buffer.from(text));
|
|
277
|
+
let outputs;
|
|
278
|
+
try {
|
|
279
|
+
outputs = [
|
|
280
|
+
preparedResult(deps, context, piece, "social_post", asset, null, {
|
|
281
|
+
platform: target.platform,
|
|
282
|
+
}),
|
|
283
|
+
];
|
|
284
|
+
}
|
|
285
|
+
catch (error) {
|
|
286
|
+
discardPreparedAssets(deps, [asset]);
|
|
287
|
+
throw error;
|
|
288
|
+
}
|
|
289
|
+
await publishResult(deps, context, piece, outputs, { text });
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
if (piece.key === digestKey && piece.input.kind === "llm") {
|
|
293
|
+
const checked = checkDigest(answer.text);
|
|
294
|
+
if (!checked.ok)
|
|
295
|
+
throw new Error(checked.reason);
|
|
296
|
+
await publishResult(deps, context, piece, preparedTexts(deps, context, piece, [
|
|
297
|
+
["instructions", "instructions.md", frozenInstructions(deps, context, piece)],
|
|
298
|
+
]), { digest: checked.digest, text: answer.text });
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
255
301
|
if (piece.input.kind === "llm" && piece.input.preparation !== undefined) {
|
|
256
302
|
const checked = validatePreparation(answer.text, piece.input.preparation.source);
|
|
257
303
|
if (!checked.ok)
|
|
@@ -314,7 +360,7 @@ async function publishText(deps, context, piece, answer) {
|
|
|
314
360
|
: [];
|
|
315
361
|
const title = titles[Number(piece.key.split(":").at(-1)) - 1];
|
|
316
362
|
if (typeof title !== "string")
|
|
317
|
-
throw new Error("
|
|
363
|
+
throw new Error(internalError("a research chapter has no title in the research plan"));
|
|
318
364
|
const asset = writeAsset(deps, context.work.projectId, `research-${piece.key.split(":").at(-1)}.md`, Buffer.from(answer.text));
|
|
319
365
|
await publishResult(deps, context, piece, [], { title, notes: answer.text }, asset);
|
|
320
366
|
return;
|
|
@@ -328,13 +374,11 @@ function narrationLabel(deps, context, piece) {
|
|
|
328
374
|
return "Narration";
|
|
329
375
|
const name = piece.input.segment === "body" ? "Body" : piece.input.segment === "intro" ? "Intro" : "Outro";
|
|
330
376
|
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)
|
|
377
|
+
const catalogue = workCatalogueIfSaved(deps.db, context.work.workId);
|
|
378
|
+
if (view === undefined || catalogue === undefined)
|
|
335
379
|
return name;
|
|
336
380
|
const segment = piece.input.segment;
|
|
337
|
-
const parts = executionPlan(deps, view,
|
|
381
|
+
const parts = executionPlan(deps, view, catalogue).recipes.filter((recipe) => recipe.input.kind === "tts" && recipe.input.segment === segment);
|
|
338
382
|
const index = parts.findIndex((recipe) => recipe.key === piece.key);
|
|
339
383
|
return parts.length > 1 && index >= 0 ? `${name} part ${index + 1} of ${parts.length}` : name;
|
|
340
384
|
}
|
|
@@ -345,10 +389,7 @@ function checkPreparation(deps, context, piece, answer) {
|
|
|
345
389
|
const checked = validatePreparation(answer.text, source);
|
|
346
390
|
if (!checked.ok)
|
|
347
391
|
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");
|
|
392
|
+
const model = workCatalogue(deps.db, context.work.workId).tts.find((model) => model.provider === "inworld" && model.id === "inworld-tts-2");
|
|
352
393
|
const prepared = prepareRequests(source, checked.cues, model?.tts.maxCharacters ?? 4000);
|
|
353
394
|
return prepared.ok ? undefined : prepared.reason;
|
|
354
395
|
}
|
|
@@ -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}`,
|
|
@@ -1,17 +1,21 @@
|
|
|
1
1
|
import { readFileSync } from "node:fs";
|
|
2
2
|
import { z } from "zod";
|
|
3
|
+
import { internalError } from "../../kernel/errors.js";
|
|
3
4
|
import { thinkingModes } from "../../kernel/ports/llm.js";
|
|
4
5
|
import { plainText } from "../article/plain.js";
|
|
5
6
|
import { defaultReviewPrompts, narrationItemKey, reviewStages, } from "../reviews/model.js";
|
|
6
7
|
import { nextAttempt, reviewOutcome } from "../reviews/outcome.js";
|
|
7
8
|
import { latestVerdict, saveVerdict } from "../reviews/repo.js";
|
|
8
9
|
import { parseVerdict, reviewMessages } from "../reviews/verdict.js";
|
|
10
|
+
import { isReadyOutput } from "../revisions/view.js";
|
|
9
11
|
import { pickedShortsOf } from "../shorts/clips.js";
|
|
10
12
|
import { outputPath } from "../storage/layout.js";
|
|
13
|
+
import { openingOf, spokenArticle } from "./review-promise.js";
|
|
11
14
|
import { exportSnapshot, revisionTranscript, } from "./runtime-export-inputs.js";
|
|
12
|
-
import {
|
|
15
|
+
import { workLlm } from "./runtime-plan.js";
|
|
13
16
|
import { publishResult } from "./runtime-publication.js";
|
|
14
17
|
import { wordsSchema } from "./runtime-subtitles.js";
|
|
18
|
+
import { pieceAlreadyDone } from "./work-records.js";
|
|
15
19
|
// What `recipe-reviews.ts` saves in the step's values, by position.
|
|
16
20
|
const valuesSchema = z.tuple([
|
|
17
21
|
z.enum(reviewStages),
|
|
@@ -32,9 +36,7 @@ const textMax = 60_000;
|
|
|
32
36
|
// saved as a pending redo, which `review-redo.ts` starts once this step has finished, and
|
|
33
37
|
// until then the item's dependents are held (`reviewHold`).
|
|
34
38
|
export async function executeReviewRecipe(deps, context, providers, piece) {
|
|
35
|
-
if (deps.db
|
|
36
|
-
.prepare("SELECT state FROM revision_work_pieces WHERE id=? AND work_id=?")
|
|
37
|
-
.get(piece.id, context.work.workId)?.state === "done")
|
|
39
|
+
if (pieceAlreadyDone(deps.db, context.work.workId, piece.id))
|
|
38
40
|
return "done";
|
|
39
41
|
if (!context.maySubmit(piece.id))
|
|
40
42
|
return "held";
|
|
@@ -44,33 +46,24 @@ export async function executeReviewRecipe(deps, context, providers, piece) {
|
|
|
44
46
|
? valuesSchema.safeParse(input.values)
|
|
45
47
|
: undefined;
|
|
46
48
|
if (values === undefined || !values.success)
|
|
47
|
-
throw new Error("
|
|
49
|
+
throw new Error(internalError("a review step was set up wrongly"));
|
|
48
50
|
const [stage, itemKey, , provider, model, thinking, prompt, mode, retries] = values.data;
|
|
49
51
|
const snapshot = exportSnapshot(deps, context, piece);
|
|
50
52
|
const material = reviewMaterial(deps, context, snapshot, stage, itemKey, prompt);
|
|
51
53
|
const previous = latestVerdict(deps.db, context.work.projectId, itemKey);
|
|
52
54
|
const attempt = nextAttempt(previous, material.itemFingerprint);
|
|
53
|
-
const row = deps.db
|
|
54
|
-
.prepare("SELECT recipe_context FROM revision_work WHERE id=?")
|
|
55
|
-
.get(context.work.workId);
|
|
56
|
-
const catalogued = savedCatalogue(row?.recipe_context).llm.find((one) => one.provider === provider && one.id === model);
|
|
57
55
|
const level = thinking === null ? undefined : z.enum(thinkingModes).parse(thinking);
|
|
56
|
+
const call = workLlm(deps.db, context.work.workId, { provider, model, thinking: level }, piece.key);
|
|
58
57
|
if (!context.maySubmit(piece.id))
|
|
59
58
|
return "held";
|
|
60
|
-
const answer = await providers.forPiece(piece.id).llm({
|
|
61
|
-
provider,
|
|
62
|
-
model,
|
|
63
|
-
...(level === undefined ? {} : { thinking: level }),
|
|
64
|
-
thinkingConfig: level === undefined ? null : (catalogued?.llm.thinking?.[level] ?? null),
|
|
59
|
+
const answer = await providers.forPiece(piece.id).llm(call({
|
|
65
60
|
messages: reviewMessages(material.request),
|
|
66
|
-
webSearch: false,
|
|
67
61
|
...(material.images.length === 0 ? {} : { images: material.images }),
|
|
68
|
-
previewLabel: piece.key,
|
|
69
62
|
check: (value) => {
|
|
70
63
|
const parsed = parseVerdict(value.text);
|
|
71
64
|
return parsed.ok ? undefined : parsed.reason;
|
|
72
65
|
},
|
|
73
|
-
});
|
|
66
|
+
}));
|
|
74
67
|
if (!answer.ok)
|
|
75
68
|
return "held";
|
|
76
69
|
const verdict = parseVerdict(answer.value.text);
|
|
@@ -126,10 +119,7 @@ export async function executeReviewRecipe(deps, context, providers, piece) {
|
|
|
126
119
|
// and outro, and the prepared or hand-edited spoken text rather than the article as written.
|
|
127
120
|
// Falls back to the article when those texts can't be read.
|
|
128
121
|
function spokenText(deps, snapshot) {
|
|
129
|
-
const present = ["intro", "body", "outro"].filter((kind) => snapshot.view.outputs.some((one) => one.
|
|
130
|
-
one.available &&
|
|
131
|
-
one.state === "ready" &&
|
|
132
|
-
one.output.role === `audio_${kind}`));
|
|
122
|
+
const present = ["intro", "body", "outro"].filter((kind) => snapshot.view.outputs.some((one) => isReadyOutput(one) && one.output.role === `audio_${kind}`));
|
|
133
123
|
try {
|
|
134
124
|
const text = present.map((kind) => revisionTranscript(deps, snapshot, kind)).join("\n\n");
|
|
135
125
|
if (text.trim() !== "")
|
|
@@ -145,9 +135,7 @@ export function reviewMaterial(deps, context, snapshot, stage, itemKey, prompt)
|
|
|
145
135
|
const recipes = snapshot.plan.recipes;
|
|
146
136
|
const config = view.revision.config;
|
|
147
137
|
const output = (workKey, role) => view.outputs.find((row) => row.workKey === workKey &&
|
|
148
|
-
row
|
|
149
|
-
row.available &&
|
|
150
|
-
row.state === "ready" &&
|
|
138
|
+
isReadyOutput(row) &&
|
|
151
139
|
(role === undefined || row.output.role === role));
|
|
152
140
|
const path = (row) => outputPath(deps.paths, context.work.projectId, row.output.path);
|
|
153
141
|
const text = (row) => clip(readFileSync(path(row), "utf8"));
|
|
@@ -178,6 +166,26 @@ export function reviewMaterial(deps, context, snapshot, stage, itemKey, prompt)
|
|
|
178
166
|
itemFingerprint: article.fingerprint,
|
|
179
167
|
};
|
|
180
168
|
}
|
|
169
|
+
// The opening as the viewer will hear it, against what the title and the thumbnail brief
|
|
170
|
+
// promise; the whole article shows whether the promise is kept later on.
|
|
171
|
+
case "promise": {
|
|
172
|
+
const article = output("article:body", "article_md");
|
|
173
|
+
if (article === undefined)
|
|
174
|
+
throw missing("article", "Use More → Write the article again in the Article section");
|
|
175
|
+
const spoken = spokenArticle(readFileSync(path(article), "utf8"));
|
|
176
|
+
const thumbnail = recipes.find((one) => one.key === "thumbnail:image");
|
|
177
|
+
const brief = thumbnail?.input.kind === "image" ? thumbnail.input.prompt.trim() : "";
|
|
178
|
+
return {
|
|
179
|
+
request: request([
|
|
180
|
+
{ label: "Video title", text: config.title },
|
|
181
|
+
...(brief === "" ? [] : [{ label: "Thumbnail brief", text: clip(brief) }]),
|
|
182
|
+
{ label: "Opening (first ~30 s)", text: openingOf(spoken) },
|
|
183
|
+
{ label: "Whole article", text: clip(spoken) },
|
|
184
|
+
]),
|
|
185
|
+
images: [],
|
|
186
|
+
itemFingerprint: article.fingerprint,
|
|
187
|
+
};
|
|
188
|
+
}
|
|
181
189
|
case "images":
|
|
182
190
|
case "thumbnail": {
|
|
183
191
|
const image = output(itemKey);
|
|
@@ -252,10 +260,7 @@ export function reviewMaterial(deps, context, snapshot, stage, itemKey, prompt)
|
|
|
252
260
|
const title = pickedShortsOf(pick?.piece.payload)?.shorts.find((clip) => clip.number === number)?.title ??
|
|
253
261
|
"";
|
|
254
262
|
const stills = view.outputs
|
|
255
|
-
.filter((row) => row.workKey.startsWith(`${itemKey}:image:`) &&
|
|
256
|
-
row.selected &&
|
|
257
|
-
row.available &&
|
|
258
|
-
row.state === "ready")
|
|
263
|
+
.filter((row) => row.workKey.startsWith(`${itemKey}:image:`) && isReadyOutput(row))
|
|
259
264
|
.slice(0, 6);
|
|
260
265
|
if (stills.length === 0)
|
|
261
266
|
throw missing("short's images", "Use Make this short again in Edit project → Shorts");
|
|
@@ -2,6 +2,7 @@ import { executeAgentReviewRecipe } from "./runtime-agent-review.js";
|
|
|
2
2
|
import { executeAnimateRecipe } from "./runtime-animate.js";
|
|
3
3
|
import { executeDocumentRecipe } from "./runtime-document.js";
|
|
4
4
|
import { executeExportRecipe } from "./runtime-export.js";
|
|
5
|
+
import { lateKeywordProviders, lateValuesOf } from "./runtime-keywords.js";
|
|
5
6
|
import { executeLocalRecipe } from "./runtime-local.js";
|
|
6
7
|
import { pieceLabel } from "./runtime-piece-label.js";
|
|
7
8
|
import { executeProviderRecipe } from "./runtime-provider.js";
|
|
@@ -11,7 +12,9 @@ import { executeSubtitleRecipe } from "./runtime-subtitles.js";
|
|
|
11
12
|
import { executeVoicesRecipe } from "./runtime-voices.js";
|
|
12
13
|
import { executeYoutubeRecipe } from "./runtime-youtube.js";
|
|
13
14
|
import { workPieces } from "./work-records.js";
|
|
14
|
-
export async function runRevisionInvocation(deps, context,
|
|
15
|
+
export async function runRevisionInvocation(deps, context, sent) {
|
|
16
|
+
// `{{Slopify_Release_Date}}` and `{{Slopify_Duration}}` are filled as a request is sent.
|
|
17
|
+
const providers = lateKeywordProviders(sent, () => lateValuesOf(deps, context));
|
|
15
18
|
const pieces = workPieces(deps.db, context.work.workId).filter((piece) => !piece.key.startsWith("article:continuation:"));
|
|
16
19
|
let waiting = false;
|
|
17
20
|
for (const piece of pieces) {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { z } from "zod";
|
|
1
|
+
import { errorText, internalError } from "../../kernel/errors.js";
|
|
3
2
|
import { withLanguage, wordTimingUnavailable } from "../../kernel/ports/languages.js";
|
|
4
3
|
import { usesFigureCards, usesShorts } from "../admission/rules.js";
|
|
5
4
|
import { captionBoldFont } from "../fonts/coverage.js";
|
|
6
|
-
import { resolveBoldFont } from "../fonts/index.js";
|
|
7
5
|
import { masterGoal } from "../loudness/model.js";
|
|
6
|
+
import { assetPathOrUndefined } from "../revisions/mutation-assets.js";
|
|
7
|
+
import { readyOutput } from "../revisions/view.js";
|
|
8
8
|
import { clipWords } from "../shorts/captions.js";
|
|
9
9
|
import { effectiveClips, pickedShortsOf } from "../shorts/clips.js";
|
|
10
10
|
import { anchorKept, lostMessage, withNewPicks } from "../shorts/keep.js";
|
|
@@ -18,21 +18,21 @@ import { probeDurationMs } from "../video/ffmpeg.js";
|
|
|
18
18
|
import { usesVoices } from "../voices/model.js";
|
|
19
19
|
import { sentencesText, transcriptSentences } from "../youtube/transcript.js";
|
|
20
20
|
import { shortsPickKey } from "./recipe-shorts.js";
|
|
21
|
+
import { exportMachine, warningsOf } from "./runtime-export.js";
|
|
21
22
|
import { figureShots } from "./runtime-export-edit.js";
|
|
22
23
|
import { exportSnapshot, revisionAudio } from "./runtime-export-inputs.js";
|
|
23
24
|
import { imageCall } from "./runtime-image.js";
|
|
24
|
-
import {
|
|
25
|
+
import { workLlm } from "./runtime-plan.js";
|
|
25
26
|
import { softenIfAsked } from "./runtime-provider.js";
|
|
26
27
|
import { preparedResult, preparedTexts, publishResult } from "./runtime-publication.js";
|
|
27
|
-
import {
|
|
28
|
+
import { readTimingWords } from "./runtime-subtitles.js";
|
|
28
29
|
import { clearSoftening } from "./soften.js";
|
|
30
|
+
import { pieceAlreadyDone } from "./work-records.js";
|
|
29
31
|
// The Shorts step's four kinds of work (`recipe-shorts.ts`): the pick, each clip's image
|
|
30
32
|
// prompts, each image, and each clip's render. Each is one piece of its own, so a failure
|
|
31
33
|
// names the clip it belongs to and Try again redoes only what did not finish.
|
|
32
34
|
export async function executeShortsRecipe(deps, context, providers, piece) {
|
|
33
|
-
if (deps.db
|
|
34
|
-
.prepare("SELECT state FROM revision_work_pieces WHERE id=? AND work_id=?")
|
|
35
|
-
.get(piece.id, context.work.workId)?.state === "done")
|
|
35
|
+
if (pieceAlreadyDone(deps.db, context.work.workId, piece.id))
|
|
36
36
|
return "done";
|
|
37
37
|
if (!context.maySubmit(piece.id))
|
|
38
38
|
return "held";
|
|
@@ -67,7 +67,7 @@ async function pick(deps, context, providers, piece, snapshot) {
|
|
|
67
67
|
const llm = config.llm;
|
|
68
68
|
if (llm === undefined || llm.provider.trim() === "" || llm.model.trim() === "")
|
|
69
69
|
throw new Error("Shorts need an AI text model to pick the clips, and none is chosen. Choose one in Edit project → Providers, then Try again.");
|
|
70
|
-
const sentences = transcriptSentences(
|
|
70
|
+
const sentences = transcriptSentences(readTimingWords(deps, context, view, shortsTimingPurpose).words);
|
|
71
71
|
if (sentences.length === 0)
|
|
72
72
|
throw new Error("The narration's word timing holds no words, so there is nothing to cut shorts from. Use More → Render the video again in the Video section, then Try again.");
|
|
73
73
|
const audio = await revisionAudio(deps, context, view);
|
|
@@ -236,12 +236,12 @@ async function render(deps, context, piece, snapshot, clip) {
|
|
|
236
236
|
.filter((recipe) => recipe.key.startsWith(prefix))
|
|
237
237
|
.toSorted((left, right) => imageIndex(left.key) - imageIndex(right.key))
|
|
238
238
|
.map((recipe) => {
|
|
239
|
-
const row = view
|
|
239
|
+
const row = readyOutput(view, { workKey: recipe.key });
|
|
240
240
|
if (row === undefined)
|
|
241
241
|
throw new Error(`Short ${String(clip.number)} is missing one of its images. Try again to make it again; if it keeps happening, use Make this short again in Edit project → Shorts.`);
|
|
242
242
|
return outputPath(deps.paths, context.work.projectId, row.output.path);
|
|
243
243
|
});
|
|
244
|
-
const allWords =
|
|
244
|
+
const allWords = readTimingWords(deps, context, view, shortsTimingPurpose).words;
|
|
245
245
|
const words = clipWords(allWords, clip.start, clip.end);
|
|
246
246
|
// The upright cards whose descriptions fall in the clip, on the clip's own timeline.
|
|
247
247
|
const figures = usesFigureCards(config)
|
|
@@ -268,8 +268,11 @@ async function render(deps, context, piece, snapshot, clip) {
|
|
|
268
268
|
const prepared = [];
|
|
269
269
|
const seconds = (clip.end - clip.start) / speed;
|
|
270
270
|
try {
|
|
271
|
+
const machine = await exportMachine(deps, context.work.projectId);
|
|
271
272
|
const master = await renderShort({
|
|
272
273
|
bin: deps.ffmpeg,
|
|
274
|
+
machine: machine.machine,
|
|
275
|
+
notice: machine.notice,
|
|
273
276
|
master: masterGoal(config, "video"),
|
|
274
277
|
timeline,
|
|
275
278
|
start: clip.start,
|
|
@@ -303,12 +306,13 @@ async function render(deps, context, piece, snapshot, clip) {
|
|
|
303
306
|
prepared.push(preparedResult(deps, context, piece, "short_video", asset, durationMs, {
|
|
304
307
|
short: clip.number,
|
|
305
308
|
sentences: [clip.first, clip.last],
|
|
309
|
+
...warningsOf(machine.notices),
|
|
306
310
|
...(master === undefined ? {} : { master }),
|
|
307
311
|
}));
|
|
308
312
|
await publishResult(deps, context, piece, prepared, { short: clip.number, start: clip.start, end: clip.end, durationMs }, asset);
|
|
309
313
|
// One per rendered short, with no stage: stage "video" would read as a finished video.
|
|
310
314
|
// Its pick and prompt tokens are not counted here.
|
|
311
|
-
deps.count?.("stage.completed", { shorts: 1 });
|
|
315
|
+
deps.count?.("stage.completed", { shorts: 1 }, context.work.projectId);
|
|
312
316
|
return "done";
|
|
313
317
|
}
|
|
314
318
|
finally {
|
|
@@ -317,12 +321,16 @@ async function render(deps, context, piece, snapshot, clip) {
|
|
|
317
321
|
}
|
|
318
322
|
// The clips the pick saved for this plan, with any range set by hand in place: the
|
|
319
323
|
// selected pick whose fingerprint is the one the plan asks for.
|
|
320
|
-
function savedClips(snapshot) {
|
|
324
|
+
export function savedClips(snapshot) {
|
|
321
325
|
const recipe = snapshot.plan.recipes.find((one) => one.key === shortsPickKey);
|
|
322
|
-
const
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
+
const done = snapshot.view.pieces.filter((one) => one.key === shortsPickKey && one.selected && one.piece.state === "done");
|
|
327
|
+
// A project from before an older fingerprint scheme keeps its pick under another
|
|
328
|
+
// fingerprint; the plan planned its clips from the version's one selected pick
|
|
329
|
+
// (`savedPicked` in `recipe-shorts.ts`), so the clips are that pick's.
|
|
330
|
+
const row = done.find((one) => one.fingerprint === recipe?.fingerprint) ??
|
|
331
|
+
(done.length === 1 && snapshot.plan.recipes.some((one) => /^shorts:\d+:/.test(one.key))
|
|
332
|
+
? done[0]
|
|
333
|
+
: undefined);
|
|
326
334
|
const picked = pickedShortsOf(row?.piece.payload);
|
|
327
335
|
const shorts = snapshot.view.revision.config.shorts;
|
|
328
336
|
if (picked === undefined || recipe === undefined || shorts === undefined)
|
|
@@ -337,57 +345,33 @@ async function backgroundMusic(deps, context, view) {
|
|
|
337
345
|
if (assetId === undefined || shorts === undefined)
|
|
338
346
|
return undefined;
|
|
339
347
|
const fix = "Choose another file under Background music in Edit project → Shorts, or remove the music, then Try again.";
|
|
340
|
-
const
|
|
341
|
-
|
|
342
|
-
.safeParse(deps.db
|
|
343
|
-
.prepare("SELECT path FROM project_assets WHERE project_id=? AND id=?")
|
|
344
|
-
.get(context.work.projectId, assetId));
|
|
345
|
-
if (!row.success)
|
|
348
|
+
const saved = assetPathOrUndefined(deps, context.work.projectId, assetId);
|
|
349
|
+
if (saved === undefined)
|
|
346
350
|
throw new Error(`The shorts' background music file is no longer in the project. ${fix}`);
|
|
347
|
-
const path = outputPath(deps.paths, context.work.projectId,
|
|
351
|
+
const path = outputPath(deps.paths, context.work.projectId, saved);
|
|
348
352
|
let durationMs;
|
|
349
353
|
try {
|
|
350
354
|
durationMs = await probeDurationMs(deps.ffmpeg, path, context.signal, deps.log);
|
|
351
355
|
}
|
|
352
356
|
catch (error) {
|
|
353
357
|
context.signal.throwIfAborted();
|
|
354
|
-
throw new Error(`The shorts' background music couldn't be read as audio (${
|
|
358
|
+
throw new Error(`The shorts' background music couldn't be read as audio (${errorText(error)}). ${fix}`);
|
|
355
359
|
}
|
|
356
360
|
if (durationMs <= 0)
|
|
357
361
|
throw new Error(`The shorts' background music file holds no sound. ${fix}`);
|
|
358
362
|
return { path, volume: musicVolumeOf(shorts) };
|
|
359
363
|
}
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
row.available &&
|
|
363
|
-
row.state === "ready" &&
|
|
364
|
-
row.workKey === "subtitles:timing" &&
|
|
365
|
-
row.output.role === "subtitle_words");
|
|
366
|
-
if (timing === undefined)
|
|
367
|
-
throw new Error("The narration's word timing, which the shorts are cut and captioned from, is missing. Use More → Render the video again in the Video section, then Try again.");
|
|
368
|
-
return wordsSchema.parse(JSON.parse(readFileSync(outputPath(deps.paths, context.work.projectId, timing.output.path), "utf8"))).words;
|
|
369
|
-
}
|
|
364
|
+
// What the shorts read the narration's word timing for, in the sentence a missing one fails with.
|
|
365
|
+
const shortsTimingPurpose = "the shorts are cut and captioned from";
|
|
370
366
|
// The project's text model, with the thinking settings saved for this step's catalogue.
|
|
371
367
|
function llmCall(deps, context, piece, view, check) {
|
|
372
368
|
const llm = view.revision.config.llm ?? { provider: "", model: "" };
|
|
373
|
-
const
|
|
374
|
-
|
|
375
|
-
.get(context.work.workId);
|
|
376
|
-
const model = savedCatalogue(row?.recipe_context).llm.find((one) => one.provider === llm.provider && one.id === llm.model);
|
|
377
|
-
return (messages) => ({
|
|
378
|
-
provider: llm.provider,
|
|
379
|
-
model: llm.model,
|
|
380
|
-
...(llm.thinking === undefined ? {} : { thinking: llm.thinking }),
|
|
381
|
-
thinkingConfig: llm.thinking === undefined ? null : (model?.llm.thinking?.[llm.thinking] ?? null),
|
|
382
|
-
messages,
|
|
383
|
-
webSearch: false,
|
|
384
|
-
previewLabel: piece.key,
|
|
385
|
-
check: (value) => check(value.text),
|
|
386
|
-
});
|
|
369
|
+
const call = workLlm(deps.db, context.work.workId, llm, piece.key);
|
|
370
|
+
return (messages) => call({ messages, check: (value) => check(value.text) });
|
|
387
371
|
}
|
|
388
372
|
function imageIndex(key) {
|
|
389
373
|
return Number(key.split(":").at(-1));
|
|
390
374
|
}
|
|
391
375
|
function setupError() {
|
|
392
|
-
return new Error("
|
|
376
|
+
return new Error(internalError("a Shorts step was set up wrongly"));
|
|
393
377
|
}
|
|
@@ -6,7 +6,7 @@ import { sourceOf } from "../admission/model.js";
|
|
|
6
6
|
import { usesShorts, usesYoutubeDescription } from "../admission/rules.js";
|
|
7
7
|
import { reviewsNarration } from "../reviews/rules.js";
|
|
8
8
|
import { currentRevisionId } from "../revisions/repo.js";
|
|
9
|
-
import { getRevisionView } from "../revisions/view.js";
|
|
9
|
+
import { getRevisionView, isDonePiece, isReadyOutput } from "../revisions/view.js";
|
|
10
10
|
import { settleScheduleRunsForProject } from "../schedules/repo.js";
|
|
11
11
|
import { editNeedsTiming } from "../video/edit-settings.js";
|
|
12
12
|
import { executionPlan, executionView, savedCatalogue } from "./runtime-plan.js";
|
|
@@ -146,14 +146,9 @@ export function executionStandings(deps, projectId, derived) {
|
|
|
146
146
|
.map((entry) => {
|
|
147
147
|
const pieces = workPieces(deps.db, entry.work.workId);
|
|
148
148
|
const retained = pieces.length > 0 &&
|
|
149
|
-
pieces.every((piece) => view.outputs.some((output) => output.workKey === piece.key &&
|
|
150
|
-
output.selected &&
|
|
151
|
-
output.available &&
|
|
152
|
-
output.state === "ready") ||
|
|
149
|
+
pieces.every((piece) => view.outputs.some((output) => output.workKey === piece.key && isReadyOutput(output)) ||
|
|
153
150
|
view.pieces.some((output) => output.key === piece.key &&
|
|
154
|
-
output
|
|
155
|
-
output.available &&
|
|
156
|
-
output.piece.state === "done" &&
|
|
151
|
+
isDonePiece(output) &&
|
|
157
152
|
(output.fingerprint === piece.fingerprint ||
|
|
158
153
|
madeFrom(deps, projectId, piece.key, output.fingerprint, piece.fingerprint))));
|
|
159
154
|
// Save can bind an existing asset without granting its placeholder invocation.
|