mergestory 0.0.0-stage → 1.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/LICENSE +202 -0
- package/NOTICE +2 -0
- package/README.md +48 -2
- package/assets/kokoro-plugin/package-lock.json +1139 -0
- package/dist/analyzer/analyze.d.ts +8 -0
- package/dist/analyzer/analyze.js +328 -0
- package/dist/analyzer/components.d.ts +18 -0
- package/dist/analyzer/components.js +266 -0
- package/dist/analyzer/dependencies.d.ts +13 -0
- package/dist/analyzer/dependencies.js +349 -0
- package/dist/analyzer/evidence.d.ts +15 -0
- package/dist/analyzer/evidence.js +73 -0
- package/dist/analyzer/hunks.d.ts +21 -0
- package/dist/analyzer/hunks.js +88 -0
- package/dist/analyzer/imports.d.ts +46 -0
- package/dist/analyzer/imports.js +87 -0
- package/dist/analyzer/index.d.ts +14 -0
- package/dist/analyzer/index.js +16 -0
- package/dist/analyzer/languages/go.d.ts +2 -0
- package/dist/analyzer/languages/go.js +76 -0
- package/dist/analyzer/languages/index.d.ts +18 -0
- package/dist/analyzer/languages/index.js +72 -0
- package/dist/analyzer/languages/javascript.d.ts +2 -0
- package/dist/analyzer/languages/javascript.js +336 -0
- package/dist/analyzer/languages/jvm.d.ts +2 -0
- package/dist/analyzer/languages/jvm.js +157 -0
- package/dist/analyzer/languages/others.d.ts +2 -0
- package/dist/analyzer/languages/others.js +40 -0
- package/dist/analyzer/languages/php.d.ts +2 -0
- package/dist/analyzer/languages/php.js +81 -0
- package/dist/analyzer/languages/python.d.ts +2 -0
- package/dist/analyzer/languages/python.js +180 -0
- package/dist/analyzer/languages/ruby.d.ts +2 -0
- package/dist/analyzer/languages/ruby.js +99 -0
- package/dist/analyzer/languages/rust.d.ts +2 -0
- package/dist/analyzer/languages/rust.js +164 -0
- package/dist/analyzer/languages/shared.d.ts +35 -0
- package/dist/analyzer/languages/shared.js +43 -0
- package/dist/analyzer/languages/types.d.ts +78 -0
- package/dist/analyzer/languages/types.js +2 -0
- package/dist/analyzer/pack-format.d.ts +27 -0
- package/dist/analyzer/pack-format.js +139 -0
- package/dist/analyzer/pack.d.ts +26 -0
- package/dist/analyzer/pack.js +498 -0
- package/dist/analyzer/relationships.d.ts +17 -0
- package/dist/analyzer/relationships.js +34 -0
- package/dist/analyzer/risk-rules.d.ts +287 -0
- package/dist/analyzer/risk-rules.js +373 -0
- package/dist/analyzer/risks.d.ts +36 -0
- package/dist/analyzer/risks.js +480 -0
- package/dist/analyzer/roles.d.ts +11 -0
- package/dist/analyzer/roles.js +280 -0
- package/dist/analyzer/scan.d.ts +26 -0
- package/dist/analyzer/scan.js +157 -0
- package/dist/analyzer/signals.d.ts +20 -0
- package/dist/analyzer/signals.js +51 -0
- package/dist/analyzer/symbol-changes.d.ts +11 -0
- package/dist/analyzer/symbol-changes.js +101 -0
- package/dist/analyzer/symbol-types.d.ts +17 -0
- package/dist/analyzer/symbol-types.js +9 -0
- package/dist/analyzer/symbols.d.ts +4 -0
- package/dist/analyzer/symbols.js +16 -0
- package/dist/analyzer/trivial.d.ts +13 -0
- package/dist/analyzer/trivial.js +137 -0
- package/dist/analyzer/util.d.ts +6 -0
- package/dist/analyzer/util.js +24 -0
- package/dist/cli/commands/authoring.d.ts +9 -0
- package/dist/cli/commands/authoring.js +98 -0
- package/dist/cli/commands/cache.d.ts +4 -0
- package/dist/cli/commands/cache.js +37 -0
- package/dist/cli/commands/doctor.d.ts +5 -0
- package/dist/cli/commands/doctor.js +37 -0
- package/dist/cli/commands/generate.d.ts +8 -0
- package/dist/cli/commands/generate.js +69 -0
- package/dist/cli/commands/jobs.d.ts +8 -0
- package/dist/cli/commands/jobs.js +70 -0
- package/dist/cli/commands/publish.d.ts +8 -0
- package/dist/cli/commands/publish.js +120 -0
- package/dist/cli/commands/serve.d.ts +4 -0
- package/dist/cli/commands/serve.js +69 -0
- package/dist/cli/commands/setup.d.ts +14 -0
- package/dist/cli/commands/setup.js +108 -0
- package/dist/cli/commands/shared.d.ts +18 -0
- package/dist/cli/commands/shared.js +24 -0
- package/dist/cli/files.d.ts +26 -0
- package/dist/cli/files.js +98 -0
- package/dist/cli/format.d.ts +55 -0
- package/dist/cli/format.js +295 -0
- package/dist/cli/inputs.d.ts +23 -0
- package/dist/cli/inputs.js +96 -0
- package/dist/cli/io.d.ts +19 -0
- package/dist/cli/io.js +31 -0
- package/dist/cli/main.d.ts +2 -0
- package/dist/cli/main.js +15 -0
- package/dist/cli/options.d.ts +105 -0
- package/dist/cli/options.js +324 -0
- package/dist/cli/program.d.ts +12 -0
- package/dist/cli/program.js +146 -0
- package/dist/cli/runtime.d.ts +59 -0
- package/dist/cli/runtime.js +83 -0
- package/dist/cli/style.d.ts +13 -0
- package/dist/cli/style.js +27 -0
- package/dist/core/binaries.d.ts +7 -0
- package/dist/core/binaries.js +33 -0
- package/dist/core/binary-paths.d.ts +5 -0
- package/dist/core/binary-paths.js +92 -0
- package/dist/core/cache.d.ts +14 -0
- package/dist/core/cache.js +43 -0
- package/dist/core/child-env.d.ts +9 -0
- package/dist/core/child-env.js +61 -0
- package/dist/core/concurrency.d.ts +13 -0
- package/dist/core/concurrency.js +58 -0
- package/dist/core/config.d.ts +223 -0
- package/dist/core/config.js +454 -0
- package/dist/core/context.d.ts +39 -0
- package/dist/core/context.js +44 -0
- package/dist/core/cost.d.ts +46 -0
- package/dist/core/cost.js +108 -0
- package/dist/core/diagram-metrics.d.ts +57 -0
- package/dist/core/diagram-metrics.js +63 -0
- package/dist/core/diff-view.d.ts +44 -0
- package/dist/core/diff-view.js +136 -0
- package/dist/core/errors.d.ts +47 -0
- package/dist/core/errors.js +94 -0
- package/dist/core/ids.d.ts +11 -0
- package/dist/core/ids.js +36 -0
- package/dist/core/json.d.ts +8 -0
- package/dist/core/json.js +17 -0
- package/dist/core/languages.d.ts +19 -0
- package/dist/core/languages.js +292 -0
- package/dist/core/logger.d.ts +29 -0
- package/dist/core/logger.js +68 -0
- package/dist/core/net.d.ts +16 -0
- package/dist/core/net.js +80 -0
- package/dist/core/path-policy.d.ts +20 -0
- package/dist/core/path-policy.js +202 -0
- package/dist/core/paths.d.ts +18 -0
- package/dist/core/paths.js +53 -0
- package/dist/core/posix.d.ts +12 -0
- package/dist/core/posix.js +50 -0
- package/dist/core/process.d.ts +22 -0
- package/dist/core/process.js +117 -0
- package/dist/core/providers.d.ts +204 -0
- package/dist/core/providers.js +2 -0
- package/dist/core/redact.d.ts +11 -0
- package/dist/core/redact.js +70 -0
- package/dist/core/render-plan.d.ts +307 -0
- package/dist/core/render-plan.js +7 -0
- package/dist/core/retry.d.ts +54 -0
- package/dist/core/retry.js +116 -0
- package/dist/core/run-folder.d.ts +74 -0
- package/dist/core/run-folder.js +129 -0
- package/dist/core/secrets.d.ts +56 -0
- package/dist/core/secrets.js +301 -0
- package/dist/core/storyboard-facts.d.ts +22 -0
- package/dist/core/storyboard-facts.js +61 -0
- package/dist/core/storyboard-schema.d.ts +1279 -0
- package/dist/core/storyboard-schema.js +342 -0
- package/dist/core/text.d.ts +43 -0
- package/dist/core/text.js +94 -0
- package/dist/core/types.d.ts +459 -0
- package/dist/core/types.js +17 -0
- package/dist/doctor/check.d.ts +6 -0
- package/dist/doctor/check.js +18 -0
- package/dist/doctor/deps.d.ts +2 -0
- package/dist/doctor/deps.js +90 -0
- package/dist/doctor/format.d.ts +9 -0
- package/dist/doctor/format.js +19 -0
- package/dist/doctor/github.d.ts +2 -0
- package/dist/doctor/github.js +13 -0
- package/dist/doctor/home.d.ts +2 -0
- package/dist/doctor/home.js +26 -0
- package/dist/doctor/index.d.ts +18 -0
- package/dist/doctor/index.js +81 -0
- package/dist/doctor/llm.d.ts +2 -0
- package/dist/doctor/llm.js +32 -0
- package/dist/doctor/publish.d.ts +2 -0
- package/dist/doctor/publish.js +16 -0
- package/dist/doctor/s3.d.ts +2 -0
- package/dist/doctor/s3.js +125 -0
- package/dist/doctor/speech.d.ts +2 -0
- package/dist/doctor/speech.js +112 -0
- package/dist/doctor/tools.d.ts +5 -0
- package/dist/doctor/tools.js +58 -0
- package/dist/doctor/types.d.ts +92 -0
- package/dist/doctor/types.js +2 -0
- package/dist/doctor/youtube.d.ts +2 -0
- package/dist/doctor/youtube.js +73 -0
- package/dist/github/client.d.ts +108 -0
- package/dist/github/client.js +499 -0
- package/dist/github/errors.d.ts +37 -0
- package/dist/github/errors.js +155 -0
- package/dist/github/index.d.ts +13 -0
- package/dist/github/index.js +9 -0
- package/dist/github/linked-issues.d.ts +37 -0
- package/dist/github/linked-issues.js +131 -0
- package/dist/github/model.d.ts +81 -0
- package/dist/github/model.js +114 -0
- package/dist/github/notify.d.ts +27 -0
- package/dist/github/notify.js +118 -0
- package/dist/github/pr-url.d.ts +27 -0
- package/dist/github/pr-url.js +122 -0
- package/dist/github/token.d.ts +16 -0
- package/dist/github/token.js +69 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.js +19 -0
- package/dist/jobs/input-rules.d.ts +20 -0
- package/dist/jobs/input-rules.js +100 -0
- package/dist/jobs/model.d.ts +47 -0
- package/dist/jobs/model.js +18 -0
- package/dist/jobs/runner.d.ts +43 -0
- package/dist/jobs/runner.js +165 -0
- package/dist/jobs/store.d.ts +67 -0
- package/dist/jobs/store.js +314 -0
- package/dist/jobs/view.d.ts +48 -0
- package/dist/jobs/view.js +111 -0
- package/dist/jobs/worker.d.ts +24 -0
- package/dist/jobs/worker.js +47 -0
- package/dist/llm/anthropic.d.ts +11 -0
- package/dist/llm/anthropic.js +225 -0
- package/dist/llm/index.d.ts +10 -0
- package/dist/llm/index.js +27 -0
- package/dist/llm/openai-compatible.d.ts +33 -0
- package/dist/llm/openai-compatible.js +378 -0
- package/dist/llm/prices.d.ts +26 -0
- package/dist/llm/prices.js +41 -0
- package/dist/llm/shared.d.ts +30 -0
- package/dist/llm/shared.js +115 -0
- package/dist/narration/assemble.d.ts +36 -0
- package/dist/narration/assemble.js +282 -0
- package/dist/narration/audio.d.ts +61 -0
- package/dist/narration/audio.js +301 -0
- package/dist/narration/captions.d.ts +37 -0
- package/dist/narration/captions.js +195 -0
- package/dist/narration/chunking.d.ts +6 -0
- package/dist/narration/chunking.js +46 -0
- package/dist/narration/convert.d.ts +9 -0
- package/dist/narration/convert.js +90 -0
- package/dist/narration/elevenlabs.d.ts +5 -0
- package/dist/narration/elevenlabs.js +53 -0
- package/dist/narration/http-errors.d.ts +14 -0
- package/dist/narration/http-errors.js +74 -0
- package/dist/narration/index.d.ts +21 -0
- package/dist/narration/index.js +22 -0
- package/dist/narration/kokoro-install.d.ts +30 -0
- package/dist/narration/kokoro-install.js +284 -0
- package/dist/narration/kokoro-model.d.ts +54 -0
- package/dist/narration/kokoro-model.js +168 -0
- package/dist/narration/kokoro-plugin.d.ts +78 -0
- package/dist/narration/kokoro-plugin.js +245 -0
- package/dist/narration/kokoro.d.ts +22 -0
- package/dist/narration/kokoro.js +231 -0
- package/dist/narration/openai.d.ts +4 -0
- package/dist/narration/openai.js +54 -0
- package/dist/narration/pricing.d.ts +8 -0
- package/dist/narration/pricing.js +17 -0
- package/dist/narration/remote-speech.d.ts +53 -0
- package/dist/narration/remote-speech.js +100 -0
- package/dist/narration/say.d.ts +28 -0
- package/dist/narration/say.js +178 -0
- package/dist/narration/select.d.ts +27 -0
- package/dist/narration/select.js +80 -0
- package/dist/narration/silent.d.ts +2 -0
- package/dist/narration/silent.js +18 -0
- package/dist/narration/speakable.d.ts +20 -0
- package/dist/narration/speakable.js +398 -0
- package/dist/narration/synthesize.d.ts +25 -0
- package/dist/narration/synthesize.js +220 -0
- package/dist/narration/wav.d.ts +37 -0
- package/dist/narration/wav.js +170 -0
- package/dist/pipeline/authoring.d.ts +8 -0
- package/dist/pipeline/authoring.js +117 -0
- package/dist/pipeline/commands.d.ts +9 -0
- package/dist/pipeline/commands.js +21 -0
- package/dist/pipeline/fit-duration.d.ts +41 -0
- package/dist/pipeline/fit-duration.js +150 -0
- package/dist/pipeline/index.d.ts +9 -0
- package/dist/pipeline/index.js +9 -0
- package/dist/pipeline/inputs.d.ts +42 -0
- package/dist/pipeline/inputs.js +171 -0
- package/dist/pipeline/plan.d.ts +8 -0
- package/dist/pipeline/plan.js +85 -0
- package/dist/pipeline/planned-egress.d.ts +21 -0
- package/dist/pipeline/planned-egress.js +43 -0
- package/dist/pipeline/prepare.d.ts +26 -0
- package/dist/pipeline/prepare.js +84 -0
- package/dist/pipeline/presentation.d.ts +26 -0
- package/dist/pipeline/presentation.js +110 -0
- package/dist/pipeline/publish-run.d.ts +71 -0
- package/dist/pipeline/publish-run.js +295 -0
- package/dist/pipeline/run.d.ts +7 -0
- package/dist/pipeline/run.js +196 -0
- package/dist/pipeline/storyboard-choice.d.ts +34 -0
- package/dist/pipeline/storyboard-choice.js +129 -0
- package/dist/pipeline/types.d.ts +76 -0
- package/dist/pipeline/types.js +2 -0
- package/dist/publish/access-probe.d.ts +55 -0
- package/dist/publish/access-probe.js +249 -0
- package/dist/publish/bundle.d.ts +20 -0
- package/dist/publish/bundle.js +57 -0
- package/dist/publish/comment.d.ts +10 -0
- package/dist/publish/comment.js +184 -0
- package/dist/publish/content-types.d.ts +15 -0
- package/dist/publish/content-types.js +41 -0
- package/dist/publish/index.d.ts +18 -0
- package/dist/publish/index.js +30 -0
- package/dist/publish/keys.d.ts +10 -0
- package/dist/publish/keys.js +30 -0
- package/dist/publish/local.d.ts +33 -0
- package/dist/publish/local.js +143 -0
- package/dist/publish/privacy.d.ts +20 -0
- package/dist/publish/privacy.js +21 -0
- package/dist/publish/s3/bucket.d.ts +22 -0
- package/dist/publish/s3/bucket.js +82 -0
- package/dist/publish/s3/client.d.ts +33 -0
- package/dist/publish/s3/client.js +134 -0
- package/dist/publish/s3/failures.d.ts +22 -0
- package/dist/publish/s3/failures.js +110 -0
- package/dist/publish/s3/index.d.ts +5 -0
- package/dist/publish/s3/index.js +6 -0
- package/dist/publish/s3/links.d.ts +38 -0
- package/dist/publish/s3/links.js +60 -0
- package/dist/publish/s3/protected-links.d.ts +29 -0
- package/dist/publish/s3/protected-links.js +67 -0
- package/dist/publish/s3/publisher.d.ts +32 -0
- package/dist/publish/s3/publisher.js +123 -0
- package/dist/publish/s3/settings.d.ts +29 -0
- package/dist/publish/s3/settings.js +64 -0
- package/dist/publish/s3/upload.d.ts +29 -0
- package/dist/publish/s3/upload.js +145 -0
- package/dist/publish/severity.d.ts +9 -0
- package/dist/publish/severity.js +18 -0
- package/dist/publish/text.d.ts +23 -0
- package/dist/publish/text.js +94 -0
- package/dist/publish/types.d.ts +67 -0
- package/dist/publish/types.js +12 -0
- package/dist/publish/vtt.d.ts +9 -0
- package/dist/publish/vtt.js +43 -0
- package/dist/publish/watch-page.d.ts +4 -0
- package/dist/publish/watch-page.js +463 -0
- package/dist/publish/youtube/credentials.d.ts +33 -0
- package/dist/publish/youtube/credentials.js +162 -0
- package/dist/publish/youtube/description.d.ts +56 -0
- package/dist/publish/youtube/description.js +197 -0
- package/dist/publish/youtube/google-api.d.ts +95 -0
- package/dist/publish/youtube/google-api.js +339 -0
- package/dist/publish/youtube/index.d.ts +7 -0
- package/dist/publish/youtube/index.js +8 -0
- package/dist/publish/youtube/loopback.d.ts +13 -0
- package/dist/publish/youtube/loopback.js +144 -0
- package/dist/publish/youtube/oauth.d.ts +68 -0
- package/dist/publish/youtube/oauth.js +159 -0
- package/dist/publish/youtube/prompt.d.ts +27 -0
- package/dist/publish/youtube/prompt.js +94 -0
- package/dist/publish/youtube/publisher.d.ts +38 -0
- package/dist/publish/youtube/publisher.js +346 -0
- package/dist/publish/youtube/scopes.d.ts +32 -0
- package/dist/publish/youtube/scopes.js +55 -0
- package/dist/publish/youtube/sign-in.d.ts +37 -0
- package/dist/publish/youtube/sign-in.js +137 -0
- package/dist/publish/youtube/upload.d.ts +43 -0
- package/dist/publish/youtube/upload.js +210 -0
- package/dist/render/browser.d.ts +23 -0
- package/dist/render/browser.js +219 -0
- package/dist/render/chromium-renderer.d.ts +56 -0
- package/dist/render/chromium-renderer.js +519 -0
- package/dist/render/ffmpeg.d.ts +55 -0
- package/dist/render/ffmpeg.js +212 -0
- package/dist/render/fonts.d.ts +10 -0
- package/dist/render/fonts.js +42 -0
- package/dist/render/index.d.ts +9 -0
- package/dist/render/index.js +11 -0
- package/dist/render/page.d.ts +46 -0
- package/dist/render/page.js +123 -0
- package/dist/render/playwright.d.ts +3 -0
- package/dist/render/playwright.js +6 -0
- package/dist/render/runtime-bundle.d.ts +2 -0
- package/dist/render/runtime-bundle.js +72 -0
- package/dist/runtime/runtime.js +1626 -0
- package/dist/server/auth.d.ts +17 -0
- package/dist/server/auth.js +58 -0
- package/dist/server/http.d.ts +43 -0
- package/dist/server/http.js +119 -0
- package/dist/server/index.d.ts +46 -0
- package/dist/server/index.js +310 -0
- package/dist/server/queue.d.ts +30 -0
- package/dist/server/queue.js +76 -0
- package/dist/server/schema.d.ts +103 -0
- package/dist/server/schema.js +121 -0
- package/dist/server/source.d.ts +17 -0
- package/dist/server/source.js +100 -0
- package/dist/sources/assemble.d.ts +86 -0
- package/dist/sources/assemble.js +117 -0
- package/dist/sources/diff-parser.d.ts +14 -0
- package/dist/sources/diff-parser.js +84 -0
- package/dist/sources/git.d.ts +28 -0
- package/dist/sources/git.js +108 -0
- package/dist/sources/github.d.ts +20 -0
- package/dist/sources/github.js +192 -0
- package/dist/sources/hunk-selection.d.ts +25 -0
- package/dist/sources/hunk-selection.js +46 -0
- package/dist/sources/index.d.ts +23 -0
- package/dist/sources/index.js +62 -0
- package/dist/sources/limits.d.ts +27 -0
- package/dist/sources/limits.js +22 -0
- package/dist/sources/local.d.ts +34 -0
- package/dist/sources/local.js +555 -0
- package/dist/sources/reader.d.ts +13 -0
- package/dist/sources/reader.js +45 -0
- package/dist/sources/remote.d.ts +13 -0
- package/dist/sources/remote.js +41 -0
- package/dist/sources/repo-context.d.ts +34 -0
- package/dist/sources/repo-context.js +144 -0
- package/dist/sources/text.d.ts +25 -0
- package/dist/sources/text.js +71 -0
- package/dist/storyboard/authoring.d.ts +108 -0
- package/dist/storyboard/authoring.js +196 -0
- package/dist/storyboard/claims.d.ts +35 -0
- package/dist/storyboard/claims.js +318 -0
- package/dist/storyboard/coderef.d.ts +28 -0
- package/dist/storyboard/coderef.js +118 -0
- package/dist/storyboard/generate.d.ts +25 -0
- package/dist/storyboard/generate.js +194 -0
- package/dist/storyboard/heuristic-code.d.ts +91 -0
- package/dist/storyboard/heuristic-code.js +524 -0
- package/dist/storyboard/heuristic-context.d.ts +42 -0
- package/dist/storyboard/heuristic-context.js +102 -0
- package/dist/storyboard/heuristic-facts.d.ts +106 -0
- package/dist/storyboard/heuristic-facts.js +415 -0
- package/dist/storyboard/heuristic-overview.d.ts +4 -0
- package/dist/storyboard/heuristic-overview.js +151 -0
- package/dist/storyboard/heuristic-review.d.ts +10 -0
- package/dist/storyboard/heuristic-review.js +158 -0
- package/dist/storyboard/heuristic-scenes.d.ts +8 -0
- package/dist/storyboard/heuristic-scenes.js +357 -0
- package/dist/storyboard/heuristic-shared.d.ts +43 -0
- package/dist/storyboard/heuristic-shared.js +136 -0
- package/dist/storyboard/heuristic.d.ts +15 -0
- package/dist/storyboard/heuristic.js +324 -0
- package/dist/storyboard/identifiers.d.ts +51 -0
- package/dist/storyboard/identifiers.js +195 -0
- package/dist/storyboard/index.d.ts +10 -0
- package/dist/storyboard/index.js +10 -0
- package/dist/storyboard/prompts.d.ts +16 -0
- package/dist/storyboard/prompts.js +61 -0
- package/dist/storyboard/run.d.ts +82 -0
- package/dist/storyboard/run.js +332 -0
- package/dist/storyboard/text.d.ts +16 -0
- package/dist/storyboard/text.js +103 -0
- package/dist/storyboard/types.d.ts +47 -0
- package/dist/storyboard/types.js +2 -0
- package/dist/storyboard/urls.d.ts +15 -0
- package/dist/storyboard/urls.js +83 -0
- package/dist/storyboard/validate.d.ts +8 -0
- package/dist/storyboard/validate.js +525 -0
- package/dist/storyboard/visuals.d.ts +23 -0
- package/dist/storyboard/visuals.js +324 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.js +3 -0
- package/dist/visuals/code.d.ts +68 -0
- package/dist/visuals/code.js +385 -0
- package/dist/visuals/highlight.d.ts +17 -0
- package/dist/visuals/highlight.js +85 -0
- package/dist/visuals/image.d.ts +12 -0
- package/dist/visuals/image.js +96 -0
- package/dist/visuals/index.d.ts +10 -0
- package/dist/visuals/index.js +10 -0
- package/dist/visuals/layout.d.ts +89 -0
- package/dist/visuals/layout.js +506 -0
- package/dist/visuals/plan.d.ts +33 -0
- package/dist/visuals/plan.js +511 -0
- package/dist/visuals/timeline.d.ts +31 -0
- package/dist/visuals/timeline.js +96 -0
- package/package.json +74 -4
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal WAV reading and writing. Every clip MergeStory stores is mono, 48 kHz, 16-bit PCM,
|
|
3
|
+
* so writing is one fixed layout; reading is tolerant because speech engines differ in the
|
|
4
|
+
* chunks they add and in the sample format they use.
|
|
5
|
+
*/
|
|
6
|
+
/** Sample rate of every stored clip and of the final narration track. */
|
|
7
|
+
export const CANONICAL_RATE = 48_000;
|
|
8
|
+
const WAVE_FORMAT_PCM = 1;
|
|
9
|
+
const WAVE_FORMAT_FLOAT = 3;
|
|
10
|
+
const WAVE_FORMAT_EXTENSIBLE = 0xfffe;
|
|
11
|
+
/** Parse the header of a RIFF/WAVE file. Throws a plain Error when the file is not a usable WAV. */
|
|
12
|
+
export function parseWavHeader(buf) {
|
|
13
|
+
if (buf.length < 12 || buf.toString('ascii', 0, 4) !== 'RIFF' || buf.toString('ascii', 8, 12) !== 'WAVE') {
|
|
14
|
+
throw new Error('Not a RIFF/WAVE file');
|
|
15
|
+
}
|
|
16
|
+
let fmt = null;
|
|
17
|
+
let offset = 12;
|
|
18
|
+
while (offset + 8 <= buf.length) {
|
|
19
|
+
const id = buf.toString('ascii', offset, offset + 4);
|
|
20
|
+
const declared = buf.readUInt32LE(offset + 4);
|
|
21
|
+
const body = offset + 8;
|
|
22
|
+
if (id === 'fmt ') {
|
|
23
|
+
if (declared < 16 || body + 16 > buf.length)
|
|
24
|
+
throw new Error('Truncated WAV format chunk');
|
|
25
|
+
let tag = buf.readUInt16LE(body);
|
|
26
|
+
const channels = buf.readUInt16LE(body + 2);
|
|
27
|
+
const sampleRate = buf.readUInt32LE(body + 4);
|
|
28
|
+
const bits = buf.readUInt16LE(body + 14);
|
|
29
|
+
if (tag === WAVE_FORMAT_EXTENSIBLE && declared >= 26 && body + 26 <= buf.length) {
|
|
30
|
+
tag = buf.readUInt16LE(body + 24);
|
|
31
|
+
}
|
|
32
|
+
fmt = { tag, channels, sampleRate, bits };
|
|
33
|
+
}
|
|
34
|
+
else if (id === 'data') {
|
|
35
|
+
if (!fmt)
|
|
36
|
+
throw new Error('WAV data chunk before format chunk');
|
|
37
|
+
// Streamed files may declare 0 or 0xFFFFFFFF; use what is actually there.
|
|
38
|
+
const available = buf.length - body;
|
|
39
|
+
const dataBytes = declared === 0 || declared === 0xffffffff || declared > available ? available : declared;
|
|
40
|
+
const encoding = fmt.tag === WAVE_FORMAT_FLOAT ? 'float' : fmt.tag === WAVE_FORMAT_PCM ? 'pcm' : null;
|
|
41
|
+
if (!encoding)
|
|
42
|
+
throw new Error(`Unsupported WAV encoding ${fmt.tag}`);
|
|
43
|
+
const validBits = encoding === 'float' ? [32, 64] : [8, 16, 24, 32];
|
|
44
|
+
if (!validBits.includes(fmt.bits))
|
|
45
|
+
throw new Error(`Unsupported WAV sample size ${fmt.bits}`);
|
|
46
|
+
if (fmt.channels < 1 || fmt.sampleRate < 1)
|
|
47
|
+
throw new Error('Invalid WAV format chunk');
|
|
48
|
+
return {
|
|
49
|
+
encoding,
|
|
50
|
+
bitsPerSample: fmt.bits,
|
|
51
|
+
channels: fmt.channels,
|
|
52
|
+
sampleRate: fmt.sampleRate,
|
|
53
|
+
dataOffset: body,
|
|
54
|
+
dataBytes,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
offset = body + declared + (declared % 2);
|
|
58
|
+
}
|
|
59
|
+
throw new Error('WAV file has no audio data');
|
|
60
|
+
}
|
|
61
|
+
/** Encode samples as a 16-bit PCM WAV file. */
|
|
62
|
+
export function encodeWavPcm16(samples, sampleRate, channels = 1) {
|
|
63
|
+
const dataBytes = samples.length * 2;
|
|
64
|
+
const out = Buffer.alloc(44 + dataBytes);
|
|
65
|
+
out.write('RIFF', 0, 'ascii');
|
|
66
|
+
out.writeUInt32LE(36 + dataBytes, 4);
|
|
67
|
+
out.write('WAVE', 8, 'ascii');
|
|
68
|
+
out.write('fmt ', 12, 'ascii');
|
|
69
|
+
out.writeUInt32LE(16, 16);
|
|
70
|
+
out.writeUInt16LE(WAVE_FORMAT_PCM, 20);
|
|
71
|
+
out.writeUInt16LE(channels, 22);
|
|
72
|
+
out.writeUInt32LE(sampleRate, 24);
|
|
73
|
+
out.writeUInt32LE(sampleRate * channels * 2, 28);
|
|
74
|
+
out.writeUInt16LE(channels * 2, 32);
|
|
75
|
+
out.writeUInt16LE(16, 34);
|
|
76
|
+
out.write('data', 36, 'ascii');
|
|
77
|
+
out.writeUInt32LE(dataBytes, 40);
|
|
78
|
+
for (let i = 0; i < samples.length; i++)
|
|
79
|
+
out.writeInt16LE(samples[i] ?? 0, 44 + i * 2);
|
|
80
|
+
return out;
|
|
81
|
+
}
|
|
82
|
+
/** Encode mono samples as a 32-bit float WAV (lossless for neural voices that produce floats). */
|
|
83
|
+
export function encodeWavFloat32(samples, sampleRate) {
|
|
84
|
+
const dataBytes = samples.length * 4;
|
|
85
|
+
const out = Buffer.alloc(44 + dataBytes);
|
|
86
|
+
out.write('RIFF', 0, 'ascii');
|
|
87
|
+
out.writeUInt32LE(36 + dataBytes, 4);
|
|
88
|
+
out.write('WAVE', 8, 'ascii');
|
|
89
|
+
out.write('fmt ', 12, 'ascii');
|
|
90
|
+
out.writeUInt32LE(16, 16);
|
|
91
|
+
out.writeUInt16LE(WAVE_FORMAT_FLOAT, 20);
|
|
92
|
+
out.writeUInt16LE(1, 22);
|
|
93
|
+
out.writeUInt32LE(sampleRate, 24);
|
|
94
|
+
out.writeUInt32LE(sampleRate * 4, 28);
|
|
95
|
+
out.writeUInt16LE(4, 32);
|
|
96
|
+
out.writeUInt16LE(32, 34);
|
|
97
|
+
out.write('data', 36, 'ascii');
|
|
98
|
+
out.writeUInt32LE(dataBytes, 40);
|
|
99
|
+
for (let i = 0; i < samples.length; i++)
|
|
100
|
+
out.writeFloatLE(samples[i] ?? 0, 44 + i * 4);
|
|
101
|
+
return out;
|
|
102
|
+
}
|
|
103
|
+
/** Little-endian 16-bit PCM bytes for the given samples. */
|
|
104
|
+
export function int16ToPcmS16le(samples) {
|
|
105
|
+
const out = Buffer.alloc(samples.length * 2);
|
|
106
|
+
for (let i = 0; i < samples.length; i++)
|
|
107
|
+
out.writeInt16LE(samples[i] ?? 0, i * 2);
|
|
108
|
+
return out;
|
|
109
|
+
}
|
|
110
|
+
/** Convert little-endian 16-bit PCM bytes to floats in [-1, 1). A trailing odd byte is ignored. */
|
|
111
|
+
export function pcmS16leToFloat(bytes) {
|
|
112
|
+
const count = Math.floor(bytes.length / 2);
|
|
113
|
+
const out = new Float32Array(count);
|
|
114
|
+
for (let i = 0; i < count; i++)
|
|
115
|
+
out[i] = bytes.readInt16LE(i * 2) / 32768;
|
|
116
|
+
return out;
|
|
117
|
+
}
|
|
118
|
+
/** Decode any PCM or float WAV to mono floats at its own sample rate (channels are averaged). */
|
|
119
|
+
export function decodeWavToMono(buf) {
|
|
120
|
+
const info = parseWavHeader(buf);
|
|
121
|
+
const bytesPerSample = info.bitsPerSample / 8;
|
|
122
|
+
const frameBytes = bytesPerSample * info.channels;
|
|
123
|
+
const frames = Math.floor(info.dataBytes / frameBytes);
|
|
124
|
+
const out = new Float32Array(frames);
|
|
125
|
+
const read = sampleReader(info);
|
|
126
|
+
for (let f = 0; f < frames; f++) {
|
|
127
|
+
let sum = 0;
|
|
128
|
+
const base = info.dataOffset + f * frameBytes;
|
|
129
|
+
for (let c = 0; c < info.channels; c++)
|
|
130
|
+
sum += read(buf, base + c * bytesPerSample);
|
|
131
|
+
out[f] = sum / info.channels;
|
|
132
|
+
}
|
|
133
|
+
return { samples: out, sampleRate: info.sampleRate };
|
|
134
|
+
}
|
|
135
|
+
function sampleReader(info) {
|
|
136
|
+
if (info.encoding === 'float') {
|
|
137
|
+
return info.bitsPerSample === 32 ? (b, at) => b.readFloatLE(at) : (b, at) => b.readDoubleLE(at);
|
|
138
|
+
}
|
|
139
|
+
switch (info.bitsPerSample) {
|
|
140
|
+
case 8:
|
|
141
|
+
return (b, at) => ((b[at] ?? 128) - 128) / 128;
|
|
142
|
+
case 16:
|
|
143
|
+
return (b, at) => b.readInt16LE(at) / 32768;
|
|
144
|
+
case 24:
|
|
145
|
+
return (b, at) => b.readIntLE(at, 3) / 8388608;
|
|
146
|
+
default:
|
|
147
|
+
return (b, at) => b.readInt32LE(at) / 2147483648;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
/** Read a clip written by this module: mono, 48 kHz, 16-bit PCM. Throws for any other layout. */
|
|
151
|
+
export function readCanonicalWav(buf) {
|
|
152
|
+
const info = parseWavHeader(buf);
|
|
153
|
+
if (info.encoding !== 'pcm' ||
|
|
154
|
+
info.bitsPerSample !== 16 ||
|
|
155
|
+
info.channels !== 1 ||
|
|
156
|
+
info.sampleRate !== CANONICAL_RATE) {
|
|
157
|
+
throw new Error('Clip is not mono 48 kHz 16-bit PCM');
|
|
158
|
+
}
|
|
159
|
+
const count = Math.floor(info.dataBytes / 2);
|
|
160
|
+
const out = new Int16Array(count);
|
|
161
|
+
for (let i = 0; i < count; i++)
|
|
162
|
+
out[i] = buf.readInt16LE(info.dataOffset + i * 2);
|
|
163
|
+
return out;
|
|
164
|
+
}
|
|
165
|
+
/** Duration in seconds of a WAV file, from its header. */
|
|
166
|
+
export function wavDurationSec(buf) {
|
|
167
|
+
const info = parseWavHeader(buf);
|
|
168
|
+
return info.dataBytes / (info.channels * (info.bitsPerSample / 8)) / info.sampleRate;
|
|
169
|
+
}
|
|
170
|
+
//# sourceMappingURL=wav.js.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type ValidationResult } from '../storyboard/index.ts';
|
|
2
|
+
import type { AuthoringOptions, AuthoringResult, GenerateHooks, GenerateOptions } from './types.ts';
|
|
3
|
+
/** Analyse a change and write everything an agent needs to author a storyboard itself. Free and offline (besides reading the PR). */
|
|
4
|
+
export declare function prepareAuthoring(options: AuthoringOptions, hooks?: GenerateHooks): Promise<AuthoringResult>;
|
|
5
|
+
/** Validate a storyboard against a change without rendering (mergestory validate). */
|
|
6
|
+
export declare function checkStoryboard(options: Omit<GenerateOptions, 'dryRun'> & {
|
|
7
|
+
storyboard: unknown;
|
|
8
|
+
}, hooks?: GenerateHooks): Promise<ValidationResult>;
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* For callers that write the storyboard themselves (a coding agent, or a person): prepare the
|
|
3
|
+
* evidence and the guide, then check what they wrote without rendering anything.
|
|
4
|
+
*/
|
|
5
|
+
import { writeFile } from 'node:fs/promises';
|
|
6
|
+
import { estimateTokens } from '../core/cost.js';
|
|
7
|
+
import { runFolder, writeRunJson } from '../core/run-folder.js';
|
|
8
|
+
import { wordBudget } from '../core/storyboard-facts.js';
|
|
9
|
+
import { storyboardJsonSchema } from '../core/storyboard-schema.js';
|
|
10
|
+
import { AUTHORING_GUIDE, validateStoryboard } from '../storyboard/index.js';
|
|
11
|
+
import { commandLine } from './commands.js';
|
|
12
|
+
import { describeFit } from './fit-duration.js';
|
|
13
|
+
import { packFor, prepare } from './prepare.js';
|
|
14
|
+
import { changeLabel, repoLabel } from './presentation.js';
|
|
15
|
+
import { fitStoryboard } from './storyboard-choice.js';
|
|
16
|
+
/** The evidence pack for an author may be larger than the one for a model: nobody pays per token here. */
|
|
17
|
+
const AUTHOR_PACK_TOKENS = 40_000;
|
|
18
|
+
/** Analyse a change and write everything an agent needs to author a storyboard itself. Free and offline (besides reading the PR). */
|
|
19
|
+
export async function prepareAuthoring(options, hooks = {}) {
|
|
20
|
+
const p = await prepare({ ...options, dryRun: true }, hooks, options.outDir ?? null);
|
|
21
|
+
const { ctx } = p;
|
|
22
|
+
const pack = packFor(p, Math.max(AUTHOR_PACK_TOKENS, p.config.llm.maxInputTokens));
|
|
23
|
+
const folder = runFolder(ctx.runDir);
|
|
24
|
+
const files = {
|
|
25
|
+
analysis: folder.analysis,
|
|
26
|
+
evidence: folder.evidence,
|
|
27
|
+
guide: folder.guide,
|
|
28
|
+
schema: folder.schema,
|
|
29
|
+
};
|
|
30
|
+
await writeFile(files.evidence, pack.markdown, { mode: 0o600 });
|
|
31
|
+
await writeFile(files.guide, authoringDocument(p, options.followUp ?? null), { mode: 0o600 });
|
|
32
|
+
await writeRunJson(files.schema, storyboardJsonSchema());
|
|
33
|
+
ctx.progress({
|
|
34
|
+
stage: 'analyze',
|
|
35
|
+
status: 'done',
|
|
36
|
+
message: `Wrote the evidence pack (${pack.includedHunks.length} hunks, about ${estimateTokens(pack.markdown)} tokens)`,
|
|
37
|
+
});
|
|
38
|
+
return {
|
|
39
|
+
runId: ctx.runId,
|
|
40
|
+
runDir: ctx.runDir,
|
|
41
|
+
files,
|
|
42
|
+
summary: {
|
|
43
|
+
title: p.changeSet.pr?.title ?? p.changeSet.commits[0]?.subject ?? changeLabel(p.changeSet),
|
|
44
|
+
changeLabel: `${repoLabel(p.changeSet)} ${changeLabel(p.changeSet)}`,
|
|
45
|
+
size: p.analysis.size,
|
|
46
|
+
files: p.changeSet.stats.files,
|
|
47
|
+
suggestedDurationSec: p.targetSec,
|
|
48
|
+
evidenceItems: p.analysis.evidence.length,
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* The text of AUTHORING.md. Steps 3 and 4 show `validate` and `generate` with the source and flags
|
|
54
|
+
* that `analyze` ran with. Task, notes, test results and screenshots are what create the ids TASK,
|
|
55
|
+
* NOTES, T1 and SS1, so a command that leaves them out would remove every line that cites them.
|
|
56
|
+
*/
|
|
57
|
+
function authoringDocument(p, followUp) {
|
|
58
|
+
const storyboard = runFolder(p.ctx.runDir).storyboard;
|
|
59
|
+
const validate = followUp
|
|
60
|
+
? commandLine(['mergestory', 'validate', storyboard, followUp.source, ...followUp.args])
|
|
61
|
+
: 'mergestory validate storyboard.json <source>';
|
|
62
|
+
const generate = followUp
|
|
63
|
+
? commandLine(['mergestory', 'generate', followUp.source, ...followUp.args, '--storyboard', storyboard])
|
|
64
|
+
: 'mergestory generate <source> --storyboard storyboard.json';
|
|
65
|
+
return [
|
|
66
|
+
'# Writing the storyboard',
|
|
67
|
+
'',
|
|
68
|
+
`Target length: about ${p.targetSec} seconds (about ${wordBudget(p.targetSec)} words of narration in total).`,
|
|
69
|
+
`Longest video: ${p.config.maxDurationSec} seconds. When a storyboard is estimated to be longer, \`generate\` leaves out the least important scenes and lines (never the mission or the review scene).`,
|
|
70
|
+
`Style: ${p.config.style}. Narration language: ${p.config.language}.`,
|
|
71
|
+
'',
|
|
72
|
+
'1. Read `evidence.md` in this folder. It lists every fact you may use, each with an id.',
|
|
73
|
+
'2. Write `storyboard.json` that matches `storyboard.schema.json`, following the rules below.',
|
|
74
|
+
`3. Check it: \`${validate}\` (fix every error it reports).`,
|
|
75
|
+
`4. Render it: \`${generate}\`.`,
|
|
76
|
+
...(followUp
|
|
77
|
+
? []
|
|
78
|
+
: [
|
|
79
|
+
'',
|
|
80
|
+
'Give both commands the same source and the same `--base`, `--head`, `--task-file`, `--notes-file`, `--tests-file`',
|
|
81
|
+
'and `--screenshot` flags as the analysis. They create the ids TASK, NOTES, T1 and SS1. Without them those ids do not',
|
|
82
|
+
'exist, and lines that cite only them are removed.',
|
|
83
|
+
]),
|
|
84
|
+
'',
|
|
85
|
+
'You know why the change was made. Put that in the narration, but only claim what the evidence shows.',
|
|
86
|
+
'Decisions and context that are not in the diff belong in the task or notes (`--task-file`, `--notes-file`),',
|
|
87
|
+
'so they become citable evidence (TASK, NOTES).',
|
|
88
|
+
'',
|
|
89
|
+
AUTHORING_GUIDE,
|
|
90
|
+
].join('\n');
|
|
91
|
+
}
|
|
92
|
+
/** Validate a storyboard against a change without rendering (mergestory validate). */
|
|
93
|
+
export async function checkStoryboard(options, hooks = {}) {
|
|
94
|
+
// Nothing here reads analysis.json, so no run folder is made.
|
|
95
|
+
const p = await prepare({ ...options, dryRun: true }, hooks, undefined, { writeAnalysis: false });
|
|
96
|
+
const result = await validateStoryboard(options.storyboard, {
|
|
97
|
+
changeSet: p.changeSet,
|
|
98
|
+
analysis: p.analysis,
|
|
99
|
+
inputs: p.inputs,
|
|
100
|
+
reader: p.reader,
|
|
101
|
+
config: p.config,
|
|
102
|
+
});
|
|
103
|
+
if (!result.storyboard)
|
|
104
|
+
return result;
|
|
105
|
+
// Say what rendering would do when the storyboard is over the maximum length.
|
|
106
|
+
const messages = describeFit(fitStoryboard(p, result.storyboard), p.config.maxDurationSec, 'would');
|
|
107
|
+
if (messages.length === 0)
|
|
108
|
+
return result;
|
|
109
|
+
return {
|
|
110
|
+
...result,
|
|
111
|
+
warnings: [
|
|
112
|
+
...result.warnings,
|
|
113
|
+
...messages.map((message) => ({ path: 'scenes', code: 'over-length', message })),
|
|
114
|
+
],
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=authoring.js.map
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** Command lines that hints and documents show to people. Quoted, so they can be pasted into a shell. */
|
|
2
|
+
import type { Config } from '../core/config.ts';
|
|
3
|
+
/** The words of a command, quoted and joined. */
|
|
4
|
+
export declare function commandLine(args: readonly string[]): string;
|
|
5
|
+
/**
|
|
6
|
+
* The command that uploads a rendered run again, with the settings that this run used, so that
|
|
7
|
+
* a command line that was only typed once (flags are not stored) is not needed to try again.
|
|
8
|
+
*/
|
|
9
|
+
export declare function publishCommand(runDir: string, config: Config): string;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { shellQuote } from '../core/text.js';
|
|
2
|
+
/** The words of a command, quoted and joined. */
|
|
3
|
+
export function commandLine(args) {
|
|
4
|
+
return args.map(shellQuote).join(' ');
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* The command that uploads a rendered run again, with the settings that this run used, so that
|
|
8
|
+
* a command line that was only typed once (flags are not stored) is not needed to try again.
|
|
9
|
+
*/
|
|
10
|
+
export function publishCommand(runDir, config) {
|
|
11
|
+
const { provider, visibility } = config.publish;
|
|
12
|
+
const args = ['mergestory', 'publish', runDir, '--publish', provider === 'none' ? 'local' : provider];
|
|
13
|
+
if (provider === 's3')
|
|
14
|
+
args.push('--visibility', visibility);
|
|
15
|
+
if (config.github.comment)
|
|
16
|
+
args.push('--comment');
|
|
17
|
+
if (config.github.updateDescription)
|
|
18
|
+
args.push('--update-description');
|
|
19
|
+
return commandLine(args);
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=commands.js.map
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { type SceneRole, type Storyboard } from '../core/storyboard-schema.ts';
|
|
2
|
+
export interface EstimateOptions {
|
|
3
|
+
/** Narration language, which decides how identifiers are spoken. */
|
|
4
|
+
language: string;
|
|
5
|
+
/** Whether e-mail addresses are masked, as they are in narration and captions. */
|
|
6
|
+
maskEmails: boolean;
|
|
7
|
+
}
|
|
8
|
+
export interface FitOptions extends EstimateOptions {
|
|
9
|
+
/** The limit in seconds. */
|
|
10
|
+
maxSec: number;
|
|
11
|
+
/** Ids of the changed files, hunks and symbols. A simulated scene keeps a line that cites one of them. */
|
|
12
|
+
backingEvidence: ReadonlySet<string>;
|
|
13
|
+
}
|
|
14
|
+
export interface FitResult {
|
|
15
|
+
/** The storyboard to use: the one that was given when it already fits, else a trimmed copy. */
|
|
16
|
+
storyboard: Storyboard;
|
|
17
|
+
/** Estimated length before and after trimming, in seconds. */
|
|
18
|
+
beforeSec: number;
|
|
19
|
+
afterSec: number;
|
|
20
|
+
droppedScenes: {
|
|
21
|
+
id: string;
|
|
22
|
+
title: string;
|
|
23
|
+
role: SceneRole;
|
|
24
|
+
}[];
|
|
25
|
+
/** Lines that were dropped from scenes that stayed. */
|
|
26
|
+
droppedLines: number;
|
|
27
|
+
/** false when only the scenes that are never dropped are left and they are still too long. */
|
|
28
|
+
fits: boolean;
|
|
29
|
+
}
|
|
30
|
+
/** Estimated length of the finished video, in seconds, including the title and the end card. */
|
|
31
|
+
export declare function estimateVideoSeconds(storyboard: Storyboard, options: EstimateOptions): number;
|
|
32
|
+
/**
|
|
33
|
+
* Trim a storyboard until its estimated length is at most `options.maxSec`, or until only the
|
|
34
|
+
* scenes that must stay are left. The given storyboard is never changed.
|
|
35
|
+
*/
|
|
36
|
+
export declare function fitToMaxDuration(storyboard: Storyboard, options: FitOptions): FitResult;
|
|
37
|
+
/**
|
|
38
|
+
* What to tell the person about a trim. Nothing when the storyboard already fit. `would` is for
|
|
39
|
+
* `validate`, which only checks: it says what rendering would drop.
|
|
40
|
+
*/
|
|
41
|
+
export declare function describeFit(result: FitResult, maxSec: number, mode?: 'trimmed' | 'would'): string[];
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Keeping a storyboard within the maximum video length (--max-duration).
|
|
3
|
+
*
|
|
4
|
+
* The real length is only known once speech exists, and speech is the step that can cost money. So
|
|
5
|
+
* the storyboard is trimmed before narration, against an estimate: every line takes as long as its
|
|
6
|
+
* words need at the speaking rate of the silent provider, and the title, pauses, minimum scene
|
|
7
|
+
* lengths, transitions and end card are added the way the real timeline adds them.
|
|
8
|
+
*
|
|
9
|
+
* Whole scenes go first, the least important first: the wrap-up, the overview, then the code
|
|
10
|
+
* scenes, later ones before earlier ones. When a scene only has to lose a little, it loses its last
|
|
11
|
+
* lines instead of disappearing. The mission and review scenes are never dropped, and every scene
|
|
12
|
+
* keeps at least one line. If those scenes alone are too long, the result says so.
|
|
13
|
+
*
|
|
14
|
+
* What this guarantees: the estimate fits, or the result says that it cannot. It does not
|
|
15
|
+
* guarantee the length of the finished video, because a real voice is a little faster or slower than
|
|
16
|
+
* the estimate.
|
|
17
|
+
*/
|
|
18
|
+
import { beatHolders, isSimulated } from '../core/storyboard-facts.js';
|
|
19
|
+
import { STORYBOARD_LIMITS } from '../core/storyboard-schema.js';
|
|
20
|
+
import { naturalList, plural } from '../core/text.js';
|
|
21
|
+
import { estimateNarration } from '../narration/index.js';
|
|
22
|
+
import { buildTimeline } from '../visuals/timeline.js';
|
|
23
|
+
/** Scenes of these roles are never dropped. */
|
|
24
|
+
const PROTECTED_ROLES = new Set(['mission', 'review']);
|
|
25
|
+
/** Which scenes go first: a lower number is dropped earlier. Scenes with the same number go last to first. */
|
|
26
|
+
const DROP_ORDER = {
|
|
27
|
+
conclusion: 0,
|
|
28
|
+
'big-picture': 1,
|
|
29
|
+
'under-the-hood': 2,
|
|
30
|
+
'before-after': 2,
|
|
31
|
+
mission: 3,
|
|
32
|
+
review: 3,
|
|
33
|
+
};
|
|
34
|
+
/** Estimated length of the finished video, in seconds, including the title and the end card. */
|
|
35
|
+
export function estimateVideoSeconds(storyboard, options) {
|
|
36
|
+
return buildTimeline(storyboard, estimateNarration(storyboard, options)).durationSec;
|
|
37
|
+
}
|
|
38
|
+
/** Whether the last line of a scene can go. A simulated scene must stay backed by a changed file, hunk or symbol. */
|
|
39
|
+
function canDropLastLine(scene, backing) {
|
|
40
|
+
if (scene.narration.length < 2)
|
|
41
|
+
return false;
|
|
42
|
+
if (!isSimulated(scene.visual))
|
|
43
|
+
return true;
|
|
44
|
+
return scene.narration.slice(0, -1).some((line) => line.evidence.some((id) => backing.has(id)));
|
|
45
|
+
}
|
|
46
|
+
/** Drop the last line. Elements that appeared on it appear on the new last line instead. */
|
|
47
|
+
function dropLastLine(scene) {
|
|
48
|
+
scene.narration.pop();
|
|
49
|
+
const last = scene.narration.length - 1;
|
|
50
|
+
for (const holder of beatHolders(scene.visual)) {
|
|
51
|
+
if (holder.beat > last)
|
|
52
|
+
holder.beat = last;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/** The next thing to leave out, or null when only what must stay is left. */
|
|
56
|
+
function nextStep(storyboard, excessSec, options, estimate, currentSec) {
|
|
57
|
+
const { scenes } = storyboard;
|
|
58
|
+
const canDropScene = scenes.length > STORYBOARD_LIMITS.minScenes;
|
|
59
|
+
const optional = scenes
|
|
60
|
+
.map((scene, index) => ({ scene, index }))
|
|
61
|
+
.filter(({ scene }) => !PROTECTED_ROLES.has(scene.role))
|
|
62
|
+
.sort((a, b) => DROP_ORDER[a.scene.role] - DROP_ORDER[b.scene.role] || b.index - a.index);
|
|
63
|
+
for (const { scene, index } of optional) {
|
|
64
|
+
if (canDropLastLine(scene, options.backingEvidence)) {
|
|
65
|
+
// Dropping lines is gentler than dropping the scene, so it is used whenever it is enough.
|
|
66
|
+
const trial = structuredClone(storyboard);
|
|
67
|
+
const trialScene = trial.scenes[index];
|
|
68
|
+
while (canDropLastLine(trialScene, options.backingEvidence))
|
|
69
|
+
dropLastLine(trialScene);
|
|
70
|
+
if (!canDropScene || currentSec - estimate(trial) >= excessSec)
|
|
71
|
+
return { kind: 'line', index };
|
|
72
|
+
}
|
|
73
|
+
if (canDropScene)
|
|
74
|
+
return { kind: 'scene', index };
|
|
75
|
+
}
|
|
76
|
+
// Only the scenes that stay are left: shorten the one with the most lines, the later one on a tie.
|
|
77
|
+
const longest = scenes
|
|
78
|
+
.map((scene, index) => ({ scene, index }))
|
|
79
|
+
.filter(({ scene }) => canDropLastLine(scene, options.backingEvidence))
|
|
80
|
+
.sort((a, b) => b.scene.narration.length - a.scene.narration.length || b.index - a.index)[0];
|
|
81
|
+
return longest ? { kind: 'line', index: longest.index } : null;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Trim a storyboard until its estimated length is at most `options.maxSec`, or until only the
|
|
85
|
+
* scenes that must stay are left. The given storyboard is never changed.
|
|
86
|
+
*/
|
|
87
|
+
export function fitToMaxDuration(storyboard, options) {
|
|
88
|
+
const estimate = (candidate) => estimateVideoSeconds(candidate, options);
|
|
89
|
+
const beforeSec = estimate(storyboard);
|
|
90
|
+
if (beforeSec <= options.maxSec) {
|
|
91
|
+
return { storyboard, beforeSec, afterSec: beforeSec, droppedScenes: [], droppedLines: 0, fits: true };
|
|
92
|
+
}
|
|
93
|
+
const work = structuredClone(storyboard);
|
|
94
|
+
// A length hint can only stretch a scene, so it is the first thing to give up.
|
|
95
|
+
for (const scene of work.scenes)
|
|
96
|
+
scene.targetSeconds = null;
|
|
97
|
+
let seconds = estimate(work);
|
|
98
|
+
const droppedScenes = [];
|
|
99
|
+
while (seconds > options.maxSec) {
|
|
100
|
+
const step = nextStep(work, seconds - options.maxSec, options, estimate, seconds);
|
|
101
|
+
if (!step)
|
|
102
|
+
break;
|
|
103
|
+
if (step.kind === 'scene') {
|
|
104
|
+
const [scene] = work.scenes.splice(step.index, 1);
|
|
105
|
+
droppedScenes.push({ id: scene.id, title: scene.title, role: scene.role });
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
dropLastLine(work.scenes[step.index]);
|
|
109
|
+
}
|
|
110
|
+
seconds = estimate(work);
|
|
111
|
+
}
|
|
112
|
+
// Lines that went with a scene that was dropped later are not counted twice.
|
|
113
|
+
const linesBefore = new Map(storyboard.scenes.map((scene) => [scene.id, scene.narration.length]));
|
|
114
|
+
const droppedLines = work.scenes.reduce((sum, scene) => sum + ((linesBefore.get(scene.id) ?? scene.narration.length) - scene.narration.length), 0);
|
|
115
|
+
return {
|
|
116
|
+
storyboard: work,
|
|
117
|
+
beforeSec,
|
|
118
|
+
afterSec: seconds,
|
|
119
|
+
droppedScenes,
|
|
120
|
+
droppedLines,
|
|
121
|
+
fits: seconds <= options.maxSec,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* What to tell the person about a trim. Nothing when the storyboard already fit. `would` is for
|
|
126
|
+
* `validate`, which only checks: it says what rendering would drop.
|
|
127
|
+
*/
|
|
128
|
+
export function describeFit(result, maxSec, mode = 'trimmed') {
|
|
129
|
+
if (result.beforeSec <= maxSec)
|
|
130
|
+
return [];
|
|
131
|
+
const sec = (value) => `${Math.round(value)} s`;
|
|
132
|
+
const dropped = [];
|
|
133
|
+
if (result.droppedScenes.length > 0) {
|
|
134
|
+
dropped.push(`${result.droppedScenes.length === 1 ? 'the scene' : 'the scenes'} ${naturalList(result.droppedScenes.map((s) => `"${s.title}"`))}`);
|
|
135
|
+
}
|
|
136
|
+
if (result.droppedLines > 0)
|
|
137
|
+
dropped.push(plural(result.droppedLines, 'narration line'));
|
|
138
|
+
let message = `The storyboard is estimated at ${sec(result.beforeSec)}, over the maximum of ${sec(maxSec)} (--max-duration).`;
|
|
139
|
+
if (dropped.length > 0) {
|
|
140
|
+
message +=
|
|
141
|
+
mode === 'trimmed'
|
|
142
|
+
? ` Left out to shorten it: ${dropped.join(', and ')}. It is now estimated at ${sec(result.afterSec)}.`
|
|
143
|
+
: ` Rendering would leave out ${dropped.join(', and ')}, which brings it to ${sec(result.afterSec)}.`;
|
|
144
|
+
}
|
|
145
|
+
if (!result.fits) {
|
|
146
|
+
message += ` The mission and review scenes are never dropped, so the maximum of ${sec(maxSec)} cannot be reached with this storyboard. Raise --max-duration, or write shorter narration.`;
|
|
147
|
+
}
|
|
148
|
+
return [message];
|
|
149
|
+
}
|
|
150
|
+
//# sourceMappingURL=fit-duration.js.map
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The pipeline: source -> analysis -> storyboard -> grounding -> narration -> visuals -> render
|
|
3
|
+
* -> publish -> notify. This is the engine's main entry point; the CLI, the HTTP API, the job
|
|
4
|
+
* runner and library users all call these functions.
|
|
5
|
+
*/
|
|
6
|
+
export { checkStoryboard, prepareAuthoring } from './authoring.ts';
|
|
7
|
+
export { publishRun } from './publish-run.ts';
|
|
8
|
+
export { generate } from './run.ts';
|
|
9
|
+
export type { AuthoringOptions, AuthoringResult, ContextOptions, GenerateHooks, GenerateOptions, PublishRunOptions, } from './types.ts';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The pipeline: source -> analysis -> storyboard -> grounding -> narration -> visuals -> render
|
|
3
|
+
* -> publish -> notify. This is the engine's main entry point; the CLI, the HTTP API, the job
|
|
4
|
+
* runner and library users all call these functions.
|
|
5
|
+
*/
|
|
6
|
+
export { checkStoryboard, prepareAuthoring } from './authoring.js';
|
|
7
|
+
export { publishRun } from './publish-run.js';
|
|
8
|
+
export { generate } from './run.js';
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { Storyboard } from '../core/storyboard-schema.ts';
|
|
3
|
+
import type { ContextInputs, TestEvidence } from '../core/types.ts';
|
|
4
|
+
import type { ContextOptions } from './types.ts';
|
|
5
|
+
/** Limits of the context. Longer lists and texts are cut or refused here, so every caller sees the same ones. */
|
|
6
|
+
export declare const MAX_TEXT: number;
|
|
7
|
+
export declare const MAX_SCREENSHOTS = 6;
|
|
8
|
+
/** Test results that reach the evidence. A longer list is cut, with a warning. */
|
|
9
|
+
export declare const MAX_TESTS = 10;
|
|
10
|
+
/** Most entries accepted in a list of test results at all. */
|
|
11
|
+
export declare const MAX_TEST_ENTRIES = 200;
|
|
12
|
+
export declare const TEST_SOURCES: readonly ['agent', 'ci', 'user'];
|
|
13
|
+
/**
|
|
14
|
+
* One test result the caller reports. Strict on purpose: a typo such as "pass" for "passed", or the
|
|
15
|
+
* string "false" for false, must never turn into a made-up result. The messages complete the
|
|
16
|
+
* sentence "entry 3 ...".
|
|
17
|
+
*/
|
|
18
|
+
export declare const TestResultSchema: z.ZodObject<{
|
|
19
|
+
command: z.ZodString;
|
|
20
|
+
passed: z.ZodBoolean;
|
|
21
|
+
summary: z.ZodString;
|
|
22
|
+
source: z.ZodDefault<z.ZodEnum<{
|
|
23
|
+
agent: "agent";
|
|
24
|
+
ci: "ci";
|
|
25
|
+
user: "user";
|
|
26
|
+
}>>;
|
|
27
|
+
}, z.core.$strict>;
|
|
28
|
+
/** Check a list of test results. `label` names the input in the error ("--tests-file", "tests"). */
|
|
29
|
+
export declare function checkTestResults(value: unknown, label?: string): Omit<TestEvidence, 'id'>[];
|
|
30
|
+
/**
|
|
31
|
+
* Check a screenshot the way the video does: PNG or JPEG by content (never by file name), at most
|
|
32
|
+
* 4 MiB and 40 megapixels. A file that the video could not draw is refused here, at once, and not
|
|
33
|
+
* after narration has been paid for. Returns the absolute path. `label` names the input in errors.
|
|
34
|
+
*/
|
|
35
|
+
export declare function checkScreenshotFile(path: string, cwd: string, label?: string): Promise<string>;
|
|
36
|
+
export declare function buildContextInputs(options: ContextOptions | undefined, cwd: string, warn?: (message: string) => void): Promise<ContextInputs>;
|
|
37
|
+
/**
|
|
38
|
+
* A warning when screenshots were supplied but the storyboard does not show them all, or null.
|
|
39
|
+
* The offline storyboard never uses screenshots, which is worth saying because the person did
|
|
40
|
+
* pass them on purpose.
|
|
41
|
+
*/
|
|
42
|
+
export declare function unusedScreenshotWarning(storyboard: Storyboard, inputs: ContextInputs, source: 'llm' | 'agent' | 'heuristic'): string | null;
|