@lingjingai/scriptctl 0.35.0 → 0.36.1
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/README.md +21 -5
- package/changes/0.36.0.md +24 -0
- package/dist/bin.js +0 -0
- package/dist/cli.d.ts +2 -1
- package/dist/cli.js +52 -128
- package/dist/cli.js.map +1 -1
- package/dist/common.d.ts +0 -16
- package/dist/common.js +2 -342
- package/dist/common.js.map +1 -1
- package/dist/domain/ingest/apply-plan.d.ts +23 -0
- package/dist/domain/ingest/apply-plan.js +210 -0
- package/dist/domain/ingest/apply-plan.js.map +1 -0
- package/dist/domain/ingest/assembler.d.ts +57 -0
- package/dist/domain/ingest/assembler.js +181 -0
- package/dist/domain/ingest/assembler.js.map +1 -0
- package/dist/domain/ingest/chunker.d.ts +9 -0
- package/dist/domain/ingest/chunker.js +38 -0
- package/dist/domain/ingest/chunker.js.map +1 -0
- package/dist/domain/ingest/evidence.d.ts +5 -0
- package/dist/domain/ingest/evidence.js +66 -0
- package/dist/domain/ingest/evidence.js.map +1 -0
- package/dist/domain/ingest/govern.d.ts +3 -0
- package/dist/domain/ingest/govern.js +127 -0
- package/dist/domain/ingest/govern.js.map +1 -0
- package/dist/domain/ingest/jsonl-parser.d.ts +6 -0
- package/dist/domain/ingest/jsonl-parser.js +187 -0
- package/dist/domain/ingest/jsonl-parser.js.map +1 -0
- package/dist/domain/ingest/markdown-parser.d.ts +6 -0
- package/dist/domain/ingest/markdown-parser.js +186 -0
- package/dist/domain/ingest/markdown-parser.js.map +1 -0
- package/dist/domain/ingest/records.d.ts +71 -0
- package/dist/domain/ingest/records.js +9 -0
- package/dist/domain/ingest/records.js.map +1 -0
- package/dist/domain/ingest/renumber.d.ts +14 -0
- package/dist/domain/ingest/renumber.js +130 -0
- package/dist/domain/ingest/renumber.js.map +1 -0
- package/dist/domain/ingest/script-v3.d.ts +94 -0
- package/dist/domain/ingest/script-v3.js +7 -0
- package/dist/domain/ingest/script-v3.js.map +1 -0
- package/dist/domain/ingest/state-reconcile.d.ts +11 -0
- package/dist/domain/ingest/state-reconcile.js +90 -0
- package/dist/domain/ingest/state-reconcile.js.map +1 -0
- package/dist/domain/ingest/validation.d.ts +11 -0
- package/dist/domain/ingest/validation.js +168 -0
- package/dist/domain/ingest/validation.js.map +1 -0
- package/dist/domain/ingest/video-aggregate.d.ts +23 -0
- package/dist/domain/ingest/video-aggregate.js +89 -0
- package/dist/domain/ingest/video-aggregate.js.map +1 -0
- package/dist/domain/ingest/video-apply.d.ts +37 -0
- package/dist/domain/ingest/video-apply.js +236 -0
- package/dist/domain/ingest/video-apply.js.map +1 -0
- package/dist/domain/ingest/video-md-parser.d.ts +2 -0
- package/dist/domain/ingest/video-md-parser.js +233 -0
- package/dist/domain/ingest/video-md-parser.js.map +1 -0
- package/dist/domain/ingest/video-records.d.ts +56 -0
- package/dist/domain/ingest/video-records.js +9 -0
- package/dist/domain/ingest/video-records.js.map +1 -0
- package/dist/domain/loom/index.d.ts +2 -1
- package/dist/domain/loom/index.js +12 -10
- package/dist/domain/loom/index.js.map +1 -1
- package/dist/domain/loom/types.d.ts +3 -2
- package/dist/domain/script/lookups.d.ts +3 -2
- package/dist/domain/script/lookups.js +25 -8
- package/dist/domain/script/lookups.js.map +1 -1
- package/dist/domain/script/patch/apply.js +2 -2
- package/dist/domain/script/patch/apply.js.map +1 -1
- package/dist/domain/script/patch/helpers.d.ts +3 -7
- package/dist/domain/script/patch/helpers.js +23 -96
- package/dist/domain/script/patch/helpers.js.map +1 -1
- package/dist/domain/script/patch/ops-action.d.ts +0 -2
- package/dist/domain/script/patch/ops-action.js +34 -100
- package/dist/domain/script/patch/ops-action.js.map +1 -1
- package/dist/domain/script/patch/ops-asset.d.ts +1 -0
- package/dist/domain/script/patch/ops-asset.js +102 -155
- package/dist/domain/script/patch/ops-asset.js.map +1 -1
- package/dist/domain/script/patch/ops-dialogue.d.ts +1 -4
- package/dist/domain/script/patch/ops-dialogue.js +43 -220
- package/dist/domain/script/patch/ops-dialogue.js.map +1 -1
- package/dist/domain/script/patch/ops-extend.js +8 -2
- package/dist/domain/script/patch/ops-extend.js.map +1 -1
- package/dist/domain/script/patch/ops-meta.js.map +1 -1
- package/dist/domain/script/patch/ops-scene.js +26 -39
- package/dist/domain/script/patch/ops-scene.js.map +1 -1
- package/dist/domain/script/patch/ops-state.d.ts +3 -3
- package/dist/domain/script/patch/ops-state.js +33 -49
- package/dist/domain/script/patch/ops-state.js.map +1 -1
- package/dist/domain/script/patch/registry.js +9 -13
- package/dist/domain/script/patch/registry.js.map +1 -1
- package/dist/domain/script/refs.js +23 -111
- package/dist/domain/script/refs.js.map +1 -1
- package/dist/domain/script/scene-refs.d.ts +3 -0
- package/dist/domain/script/scene-refs.js +35 -0
- package/dist/domain/script/scene-refs.js.map +1 -0
- package/dist/domain/script/schema.js +17 -21
- package/dist/domain/script/schema.js.map +1 -1
- package/dist/domain/script/text-util.d.ts +7 -0
- package/dist/domain/script/text-util.js +91 -0
- package/dist/domain/script/text-util.js.map +1 -0
- package/dist/help-text.js +117 -410
- package/dist/help-text.js.map +1 -1
- package/dist/infra/converters.js +1 -1
- package/dist/infra/converters.js.map +1 -1
- package/dist/infra/episode-title.d.ts +4 -0
- package/dist/infra/episode-title.js +129 -0
- package/dist/infra/episode-title.js.map +1 -0
- package/dist/infra/ingest/review-renderer.d.ts +1 -0
- package/dist/infra/ingest/review-renderer.js +431 -0
- package/dist/infra/ingest/review-renderer.js.map +1 -0
- package/dist/infra/ingest/source-resolver.d.ts +21 -0
- package/dist/infra/ingest/source-resolver.js +51 -0
- package/dist/infra/ingest/source-resolver.js.map +1 -0
- package/dist/infra/ingest/text-reader.d.ts +3 -0
- package/dist/infra/ingest/text-reader.js +27 -0
- package/dist/infra/ingest/text-reader.js.map +1 -0
- package/dist/infra/ingest/video-discovery.d.ts +8 -0
- package/dist/infra/ingest/video-discovery.js +60 -0
- package/dist/infra/ingest/video-discovery.js.map +1 -0
- package/dist/infra/ingest/workspace-store.d.ts +18 -0
- package/dist/infra/ingest/workspace-store.js +70 -0
- package/dist/infra/ingest/workspace-store.js.map +1 -0
- package/dist/infra/llm/anthropic-model.d.ts +11 -0
- package/dist/infra/llm/anthropic-model.js +109 -0
- package/dist/infra/llm/anthropic-model.js.map +1 -0
- package/dist/infra/llm/gemini-upload.d.ts +9 -0
- package/dist/infra/llm/gemini-upload.js +94 -0
- package/dist/infra/llm/gemini-upload.js.map +1 -0
- package/dist/infra/llm/gemini-video-model.d.ts +47 -0
- package/dist/infra/llm/gemini-video-model.js +163 -0
- package/dist/infra/llm/gemini-video-model.js.map +1 -0
- package/dist/infra/llm/openai-compatible-model.d.ts +14 -0
- package/dist/infra/llm/openai-compatible-model.js +157 -0
- package/dist/infra/llm/openai-compatible-model.js.map +1 -0
- package/dist/infra/llm/retry.d.ts +5 -0
- package/dist/infra/llm/retry.js +20 -0
- package/dist/infra/llm/retry.js.map +1 -0
- package/dist/llm/composition.d.ts +5 -0
- package/dist/llm/composition.js +5 -0
- package/dist/llm/composition.js.map +1 -0
- package/dist/llm/config.d.ts +26 -0
- package/dist/llm/config.js +201 -0
- package/dist/llm/config.js.map +1 -0
- package/dist/llm/registry.d.ts +44 -0
- package/dist/llm/registry.js +48 -0
- package/dist/llm/registry.js.map +1 -0
- package/dist/llm/router.d.ts +23 -0
- package/dist/llm/router.js +0 -0
- package/dist/llm/router.js.map +1 -0
- package/dist/llm/tasks/ingest/asset-curate.d.ts +13 -0
- package/dist/llm/tasks/ingest/asset-curate.js +45 -0
- package/dist/llm/tasks/ingest/asset-curate.js.map +1 -0
- package/dist/llm/tasks/ingest/asset-extract.d.ts +12 -0
- package/dist/llm/tasks/ingest/asset-extract.js +51 -0
- package/dist/llm/tasks/ingest/asset-extract.js.map +1 -0
- package/dist/llm/tasks/ingest/asset-govern.d.ts +22 -0
- package/dist/llm/tasks/ingest/asset-govern.js +143 -0
- package/dist/llm/tasks/ingest/asset-govern.js.map +1 -0
- package/dist/llm/tasks/ingest/mention-resolve.d.ts +9 -0
- package/dist/llm/tasks/ingest/mention-resolve.js +39 -0
- package/dist/llm/tasks/ingest/mention-resolve.js.map +1 -0
- package/dist/llm/tasks/ingest/plot-speaker.d.ts +11 -0
- package/dist/llm/tasks/ingest/plot-speaker.js +72 -0
- package/dist/llm/tasks/ingest/plot-speaker.js.map +1 -0
- package/dist/llm/tasks/ingest/roster-merge.d.ts +46 -0
- package/dist/llm/tasks/ingest/roster-merge.js +235 -0
- package/dist/llm/tasks/ingest/roster-merge.js.map +1 -0
- package/dist/llm/tasks/ingest/state-merge.d.ts +10 -0
- package/dist/llm/tasks/ingest/state-merge.js +84 -0
- package/dist/llm/tasks/ingest/state-merge.js.map +1 -0
- package/dist/llm/tasks/ingest/state-reconcile.d.ts +8 -0
- package/dist/llm/tasks/ingest/state-reconcile.js +44 -0
- package/dist/llm/tasks/ingest/state-reconcile.js.map +1 -0
- package/dist/llm/tasks/ingest/text-normalize.d.ts +10 -0
- package/dist/llm/tasks/ingest/text-normalize.js +89 -0
- package/dist/llm/tasks/ingest/text-normalize.js.map +1 -0
- package/dist/llm/tasks/ingest/video-correct.d.ts +30 -0
- package/dist/llm/tasks/ingest/video-correct.js +144 -0
- package/dist/llm/tasks/ingest/video-correct.js.map +1 -0
- package/dist/llm/tasks/ingest/video-transcribe.d.ts +4 -0
- package/dist/llm/tasks/ingest/video-transcribe.js +105 -0
- package/dist/llm/tasks/ingest/video-transcribe.js.map +1 -0
- package/dist/llm/tasks/schemas.d.ts +5 -0
- package/dist/llm/tasks/schemas.js +107 -0
- package/dist/llm/tasks/schemas.js.map +1 -0
- package/dist/llm/types.d.ts +97 -0
- package/dist/llm/types.js +13 -0
- package/dist/llm/types.js.map +1 -0
- package/dist/usecases/doctor.d.ts +1 -1
- package/dist/usecases/doctor.js +62 -9
- package/dist/usecases/doctor.js.map +1 -1
- package/dist/usecases/ingest/command.d.ts +5 -0
- package/dist/usecases/ingest/command.js +64 -0
- package/dist/usecases/ingest/command.js.map +1 -0
- package/dist/usecases/ingest/fanout.d.ts +10 -0
- package/dist/usecases/ingest/fanout.js +23 -0
- package/dist/usecases/ingest/fanout.js.map +1 -0
- package/dist/usecases/ingest/pass4-mention-resolve.d.ts +11 -0
- package/dist/usecases/ingest/pass4-mention-resolve.js +52 -0
- package/dist/usecases/ingest/pass4-mention-resolve.js.map +1 -0
- package/dist/usecases/ingest/pass5-extract.d.ts +7 -0
- package/dist/usecases/ingest/pass5-extract.js +50 -0
- package/dist/usecases/ingest/pass5-extract.js.map +1 -0
- package/dist/usecases/ingest/pass5-govern.d.ts +13 -0
- package/dist/usecases/ingest/pass5-govern.js +155 -0
- package/dist/usecases/ingest/pass5-govern.js.map +1 -0
- package/dist/usecases/ingest/pipeline.d.ts +28 -0
- package/dist/usecases/ingest/pipeline.js +144 -0
- package/dist/usecases/ingest/pipeline.js.map +1 -0
- package/dist/usecases/ingest/publish-command.d.ts +4 -0
- package/dist/usecases/ingest/publish-command.js +77 -0
- package/dist/usecases/ingest/publish-command.js.map +1 -0
- package/dist/usecases/ingest/status.d.ts +39 -0
- package/dist/usecases/ingest/status.js +155 -0
- package/dist/usecases/ingest/status.js.map +1 -0
- package/dist/usecases/ingest/video-pass3.d.ts +26 -0
- package/dist/usecases/ingest/video-pass3.js +0 -0
- package/dist/usecases/ingest/video-pass3.js.map +1 -0
- package/dist/usecases/ingest/video-pipeline.d.ts +32 -0
- package/dist/usecases/ingest/video-pipeline.js +202 -0
- package/dist/usecases/ingest/video-pipeline.js.map +1 -0
- package/dist/usecases/ingest/view-command.d.ts +4 -0
- package/dist/usecases/ingest/view-command.js +51 -0
- package/dist/usecases/ingest/view-command.js.map +1 -0
- package/dist/usecases/script/actions.js +2 -2
- package/dist/usecases/script/actions.js.map +1 -1
- package/dist/usecases/script/actor.js.map +1 -1
- package/dist/usecases/script/actors.js.map +1 -1
- package/dist/usecases/script/add-actor.js.map +1 -1
- package/dist/usecases/script/add-episode.js.map +1 -1
- package/dist/usecases/script/add-location.js.map +1 -1
- package/dist/usecases/script/add-prop.js.map +1 -1
- package/dist/usecases/script/alias.js.map +1 -1
- package/dist/usecases/script/assets.js.map +1 -1
- package/dist/usecases/script/context.js.map +1 -1
- package/dist/usecases/script/create.js +3 -6
- package/dist/usecases/script/create.js.map +1 -1
- package/dist/usecases/script/delete.js.map +1 -1
- package/dist/usecases/script/describe.js.map +1 -1
- package/dist/usecases/script/dialogue.js +6 -13
- package/dist/usecases/script/dialogue.js.map +1 -1
- package/dist/usecases/script/do.js +1 -1
- package/dist/usecases/script/do.js.map +1 -1
- package/dist/usecases/script/episodes.js.map +1 -1
- package/dist/usecases/script/{add-speaker.d.ts → importance.d.ts} +1 -1
- package/dist/usecases/script/importance.js +17 -0
- package/dist/usecases/script/importance.js.map +1 -0
- package/dist/usecases/script/insert.js.map +1 -1
- package/dist/usecases/script/issues.js.map +1 -1
- package/dist/usecases/script/lib.d.ts +8 -6
- package/dist/usecases/script/lib.js +81 -97
- package/dist/usecases/script/lib.js.map +1 -1
- package/dist/usecases/script/locations.js.map +1 -1
- package/dist/usecases/script/merge.js.map +1 -1
- package/dist/usecases/script/move.js.map +1 -1
- package/dist/usecases/script/props.js.map +1 -1
- package/dist/usecases/script/refs.js.map +1 -1
- package/dist/usecases/script/rename.js.map +1 -1
- package/dist/usecases/script/replace.js.map +1 -1
- package/dist/usecases/script/role.js.map +1 -1
- package/dist/usecases/script/scenes.js +8 -15
- package/dist/usecases/script/scenes.js.map +1 -1
- package/dist/usecases/script/script-patch.js +1 -1
- package/dist/usecases/script/script-patch.js.map +1 -1
- package/dist/usecases/script/script-validate.js +1 -1
- package/dist/usecases/script/script-validate.js.map +1 -1
- package/dist/usecases/script/session.d.ts +4 -4
- package/dist/usecases/script/session.js +57 -78
- package/dist/usecases/script/session.js.map +1 -1
- package/dist/usecases/script/split.js.map +1 -1
- package/dist/usecases/script/state-add.js.map +1 -1
- package/dist/usecases/script/state-delete.js.map +1 -1
- package/dist/usecases/script/state-rename.js.map +1 -1
- package/dist/usecases/script/summary.js.map +1 -1
- package/dist/usecases/script/synopsis-generate.d.ts +4 -5
- package/dist/usecases/script/synopsis-generate.js +30 -46
- package/dist/usecases/script/synopsis-generate.js.map +1 -1
- package/dist/usecases/script/transition.js.map +1 -1
- package/dist/usecases/script/type.js.map +1 -1
- package/dist/usecases/script/worldview.js.map +1 -1
- package/package.json +21 -17
- package/skills/scriptctl/SKILL.md +140 -120
- package/skills/scriptctl/references/atomic-write-workflow.md +12 -9
- package/skills/scriptctl/references/ingest-workflow.md +85 -0
- package/skills/scriptctl/references/state-reference-repair.md +26 -39
- package/dist/domain/direct/runner.d.ts +0 -25
- package/dist/domain/direct/runner.js +0 -88
- package/dist/domain/direct/runner.js.map +0 -1
- package/dist/domain/direct/stage.d.ts +0 -108
- package/dist/domain/direct/stage.js +0 -134
- package/dist/domain/direct/stage.js.map +0 -1
- package/dist/domain/direct/stages/asset-curation.d.ts +0 -2
- package/dist/domain/direct/stages/asset-curation.js +0 -10
- package/dist/domain/direct/stages/asset-curation.js.map +0 -1
- package/dist/domain/direct/stages/batch-extract.d.ts +0 -2
- package/dist/domain/direct/stages/batch-extract.js +0 -12
- package/dist/domain/direct/stages/batch-extract.js.map +0 -1
- package/dist/domain/direct/stages/batch-plan.d.ts +0 -2
- package/dist/domain/direct/stages/batch-plan.js +0 -9
- package/dist/domain/direct/stages/batch-plan.js.map +0 -1
- package/dist/domain/direct/stages/episode-merge.d.ts +0 -2
- package/dist/domain/direct/stages/episode-merge.js +0 -11
- package/dist/domain/direct/stages/episode-merge.js.map +0 -1
- package/dist/domain/direct/stages/episode-plan.d.ts +0 -2
- package/dist/domain/direct/stages/episode-plan.js +0 -9
- package/dist/domain/direct/stages/episode-plan.js.map +0 -1
- package/dist/domain/direct/stages/episode-synopsis.d.ts +0 -2
- package/dist/domain/direct/stages/episode-synopsis.js +0 -12
- package/dist/domain/direct/stages/episode-synopsis.js.map +0 -1
- package/dist/domain/direct/stages/episode-titles.d.ts +0 -2
- package/dist/domain/direct/stages/episode-titles.js +0 -12
- package/dist/domain/direct/stages/episode-titles.js.map +0 -1
- package/dist/domain/direct/stages/index.d.ts +0 -19
- package/dist/domain/direct/stages/index.js +0 -41
- package/dist/domain/direct/stages/index.js.map +0 -1
- package/dist/domain/direct/stages/metadata.d.ts +0 -2
- package/dist/domain/direct/stages/metadata.js +0 -11
- package/dist/domain/direct/stages/metadata.js.map +0 -1
- package/dist/domain/direct/stages/script-merge.d.ts +0 -2
- package/dist/domain/direct/stages/script-merge.js +0 -15
- package/dist/domain/direct/stages/script-merge.js.map +0 -1
- package/dist/domain/direct/stages/script-synopsis.d.ts +0 -2
- package/dist/domain/direct/stages/script-synopsis.js +0 -12
- package/dist/domain/direct/stages/script-synopsis.js.map +0 -1
- package/dist/domain/direct/stages/source-prepare.d.ts +0 -2
- package/dist/domain/direct/stages/source-prepare.js +0 -9
- package/dist/domain/direct/stages/source-prepare.js.map +0 -1
- package/dist/domain/direct/stages/state-binding.d.ts +0 -2
- package/dist/domain/direct/stages/state-binding.js +0 -9
- package/dist/domain/direct/stages/state-binding.js.map +0 -1
- package/dist/domain/direct/stages/state-curation.d.ts +0 -2
- package/dist/domain/direct/stages/state-curation.js +0 -10
- package/dist/domain/direct/stages/state-curation.js.map +0 -1
- package/dist/domain/direct/stages/validate.d.ts +0 -2
- package/dist/domain/direct/stages/validate.js +0 -10
- package/dist/domain/direct/stages/validate.js.map +0 -1
- package/dist/domain/direct-core.d.ts +0 -313
- package/dist/domain/direct-core.js +0 -8514
- package/dist/domain/direct-core.js.map +0 -1
- package/dist/domain/script/validate.d.ts +0 -22
- package/dist/domain/script/validate.js +0 -997
- package/dist/domain/script/validate.js.map +0 -1
- package/dist/infra/providers.d.ts +0 -97
- package/dist/infra/providers.js +0 -1396
- package/dist/infra/providers.js.map +0 -1
- package/dist/usecases/direct.d.ts +0 -27
- package/dist/usecases/direct.js +0 -4172
- package/dist/usecases/direct.js.map +0 -1
- package/dist/usecases/parse.d.ts +0 -15
- package/dist/usecases/parse.js +0 -429
- package/dist/usecases/parse.js.map +0 -1
- package/dist/usecases/script/add-speaker.js +0 -22
- package/dist/usecases/script/add-speaker.js.map +0 -1
- package/dist/usecases/script/export.d.ts +0 -3
- package/dist/usecases/script/export.js +0 -111
- package/dist/usecases/script/export.js.map +0 -1
- package/dist/usecases/script/overlap.d.ts +0 -3
- package/dist/usecases/script/overlap.js +0 -21
- package/dist/usecases/script/overlap.js.map +0 -1
- package/dist/usecases/script/speakers.d.ts +0 -3
- package/dist/usecases/script/speakers.js +0 -28
- package/dist/usecases/script/speakers.js.map +0 -1
- package/dist/usecases/script/state-change.d.ts +0 -3
- package/dist/usecases/script/state-change.js +0 -24
- package/dist/usecases/script/state-change.js.map +0 -1
- package/skills/scriptctl/references/direct-workflow.md +0 -72
package/dist/usecases/doctor.js
CHANGED
|
@@ -4,6 +4,8 @@ import { createRequire } from "node:module";
|
|
|
4
4
|
import { EXIT_OK, isDebug } from "../common.js";
|
|
5
5
|
import { candidateEnvPaths } from "../infra/env.js";
|
|
6
6
|
import { resolveOutputMode } from "../infra/script-output-store.js";
|
|
7
|
+
import { loadLlmConfig } from "../llm/config.js";
|
|
8
|
+
import { ModelRouter } from "../llm/router.js";
|
|
7
9
|
const require = createRequire(import.meta.url);
|
|
8
10
|
function moduleAvailable(name) {
|
|
9
11
|
try {
|
|
@@ -44,7 +46,7 @@ function probeLocalOutputDir(dir) {
|
|
|
44
46
|
function defaultLocalOutputDir() {
|
|
45
47
|
return path.join(path.dirname(path.resolve("workspace")), "output");
|
|
46
48
|
}
|
|
47
|
-
export function commandDoctor(
|
|
49
|
+
export function commandDoctor(opts = {}) {
|
|
48
50
|
const envPaths = candidateEnvPaths();
|
|
49
51
|
const existingEnvPaths = [];
|
|
50
52
|
const seen = new Set();
|
|
@@ -62,7 +64,34 @@ export function commandDoctor(_opts) {
|
|
|
62
64
|
// ignore individual entries that cannot be inspected
|
|
63
65
|
}
|
|
64
66
|
}
|
|
65
|
-
const
|
|
67
|
+
const explicitLlmConfig = typeof opts["llm_config"] === "string" ? opts["llm_config"].trim() : "";
|
|
68
|
+
const llmConfig = loadLlmConfig(explicitLlmConfig || undefined);
|
|
69
|
+
const llmRouter = new ModelRouter(llmConfig);
|
|
70
|
+
const llmRoutes = llmRouter.routes();
|
|
71
|
+
const credentialChecks = Object.entries(llmConfig.providers).map(([alias, provider]) => ({
|
|
72
|
+
alias,
|
|
73
|
+
configured: Boolean((process.env[provider.apiKeyEnv] ?? "").trim()),
|
|
74
|
+
env: provider.apiKeyEnv,
|
|
75
|
+
}));
|
|
76
|
+
// openai-compatible providers need an explicit endpoint (the built-in `gw`
|
|
77
|
+
// reads PROJECT_LITELLM_GATEWAY_BASE_URL). Report the resolved host so a
|
|
78
|
+
// missing / mis-pointed gateway is visible — a null baseUrl here is why
|
|
79
|
+
// ingest normalization fails at connection time. anthropic/gemini use their
|
|
80
|
+
// SDK default endpoint, so a null baseUrl there is expected and not reported.
|
|
81
|
+
const endpointChecks = Object.entries(llmConfig.providers)
|
|
82
|
+
.filter(([, provider]) => provider.protocol === "openai-compatible")
|
|
83
|
+
.map(([alias, provider]) => {
|
|
84
|
+
let host = "not set";
|
|
85
|
+
if (provider.baseUrl) {
|
|
86
|
+
try {
|
|
87
|
+
host = new URL(provider.baseUrl).host;
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
host = provider.baseUrl;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return { alias, host };
|
|
94
|
+
});
|
|
66
95
|
// doctor reports the AMBIENT binding (env + project-group inference), so it
|
|
67
96
|
// resolves with no per-call flags. mode is null when the env is unbound or
|
|
68
97
|
// holds a typo'd SCRIPTCTL_OUTPUT_MODE — both surface as "not configured".
|
|
@@ -74,6 +103,7 @@ export function commandDoctor(_opts) {
|
|
|
74
103
|
const projectGroupConfigured = Boolean(process.env.SANDBOX_PROJECT_GROUP_NO);
|
|
75
104
|
const dependencies = {
|
|
76
105
|
"@anthropic-ai/sdk": moduleAvailable("@anthropic-ai/sdk"),
|
|
106
|
+
"@google/genai": moduleAvailable("@google/genai"),
|
|
77
107
|
"pdf-parse": moduleAvailable("pdf-parse"),
|
|
78
108
|
jszip: moduleAvailable("jszip"),
|
|
79
109
|
"fast-xml-parser": moduleAvailable("fast-xml-parser"),
|
|
@@ -94,7 +124,10 @@ export function commandDoctor(_opts) {
|
|
|
94
124
|
`node: ${nodeVersion}`,
|
|
95
125
|
storageLine,
|
|
96
126
|
envFileLine,
|
|
97
|
-
`
|
|
127
|
+
`llm config: ${llmConfig.source}`,
|
|
128
|
+
`llm routes: ${llmRoutes.length}`,
|
|
129
|
+
...credentialChecks.map((check) => `llm provider ${check.alias}: ${fmtCheck(check.configured)}`),
|
|
130
|
+
...endpointChecks.map((check) => `llm provider ${check.alias} endpoint: ${check.host}`),
|
|
98
131
|
];
|
|
99
132
|
// Doctor result lines vary by where the published script lands, but the
|
|
100
133
|
// word "mode" / "local" / "remote" is deliberately absent: upper layers
|
|
@@ -121,14 +154,17 @@ export function commandDoctor(_opts) {
|
|
|
121
154
|
if (missingDeps.length > 0) {
|
|
122
155
|
nextSteps.push("Install missing CLI dependencies (see above).");
|
|
123
156
|
}
|
|
124
|
-
if (!
|
|
125
|
-
nextSteps.push("Configure
|
|
157
|
+
if (credentialChecks.some((check) => !check.configured)) {
|
|
158
|
+
nextSteps.push("Configure every credential referenced by the selected LLM configuration.");
|
|
159
|
+
}
|
|
160
|
+
if (endpointChecks.some((check) => check.host === "not set")) {
|
|
161
|
+
nextSteps.push("An openai-compatible provider has no endpoint — set PROJECT_LITELLM_GATEWAY_BASE_URL (built-in gateway) or the provider's baseUrl.");
|
|
126
162
|
}
|
|
127
163
|
// A typo'd SCRIPTCTL_OUTPUT_MODE resolves to mode=null (unbound), same as
|
|
128
164
|
// unset — reported as "not configured" below. We deliberately don't name the
|
|
129
165
|
// env var here: that would leak the mode concept to the upper layer.
|
|
130
166
|
if (mode === null) {
|
|
131
|
-
nextSteps.push("Configure an output target before running `
|
|
167
|
+
nextSteps.push("Configure an output target before running `publish` / script CRUD.");
|
|
132
168
|
}
|
|
133
169
|
else if (mode === "local") {
|
|
134
170
|
if (localProbe && !localProbe.writable) {
|
|
@@ -136,7 +172,7 @@ export function commandDoctor(_opts) {
|
|
|
136
172
|
}
|
|
137
173
|
}
|
|
138
174
|
else if (!gatewayUrlConfigured || !gatewayAccessConfigured || !projectGroupConfigured) {
|
|
139
|
-
nextSteps.push("Configure gateway credentials before running `
|
|
175
|
+
nextSteps.push("Configure gateway credentials before running `publish` / script CRUD against the remote project.");
|
|
140
176
|
}
|
|
141
177
|
if (nextSteps.length === 0) {
|
|
142
178
|
nextSteps.push("Environment looks ready.");
|
|
@@ -168,8 +204,25 @@ export function commandDoctor(_opts) {
|
|
|
168
204
|
ok: existingEnvPaths.length > 0,
|
|
169
205
|
...(debug ? { paths: existingEnvPaths } : { count: existingEnvPaths.length }),
|
|
170
206
|
},
|
|
171
|
-
|
|
172
|
-
|
|
207
|
+
llm: {
|
|
208
|
+
config_source: llmConfig.source,
|
|
209
|
+
...(debug && llmConfig.sourcePath ? { config_path: llmConfig.sourcePath } : {}),
|
|
210
|
+
providers: credentialChecks.map((check) => ({
|
|
211
|
+
alias: check.alias,
|
|
212
|
+
ok: check.configured,
|
|
213
|
+
...(debug ? { credential_env: check.env } : {}),
|
|
214
|
+
...(endpointChecks.find((e) => e.alias === check.alias)
|
|
215
|
+
? { endpoint: endpointChecks.find((e) => e.alias === check.alias).host }
|
|
216
|
+
: {}),
|
|
217
|
+
})),
|
|
218
|
+
profiles: Object.keys(llmConfig.models),
|
|
219
|
+
routes: llmRoutes.map((route) => ({
|
|
220
|
+
task: route.task,
|
|
221
|
+
profile: route.profile,
|
|
222
|
+
provider: route.provider,
|
|
223
|
+
protocol: route.protocol,
|
|
224
|
+
model: route.model,
|
|
225
|
+
})),
|
|
173
226
|
},
|
|
174
227
|
output: outputChecks,
|
|
175
228
|
dependencies,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/usecases/doctor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,OAAO,EAAE,OAAO,EAAE,OAAO,EAAe,MAAM,cAAc,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/usecases/doctor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { type Report } from "../../common.js";
|
|
2
|
+
import { type LlmComposition } from "../../llm/composition.js";
|
|
3
|
+
type Dict = Record<string, unknown>;
|
|
4
|
+
export declare function commandIngest(opts: Dict, composition?: LlmComposition): Promise<[Report, number]>;
|
|
5
|
+
export {};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// `scriptctl ingest` — bare command (§4). Converts a txt/md/docx or video source
|
|
2
|
+
// into a Script v3 workspace (script.jsonl → script.initial.json → script.json).
|
|
3
|
+
// Fully decoupled from `direct`: touches only ingest domain/infra + llm + common.
|
|
4
|
+
import * as path from "node:path";
|
|
5
|
+
import { CliError, EXIT_INPUT, EXIT_OK } from "../../common.js";
|
|
6
|
+
import { resolveSource } from "../../infra/ingest/source-resolver.js";
|
|
7
|
+
import { PRODUCTION_LLM_COMPOSITION } from "../../llm/composition.js";
|
|
8
|
+
import { runTextIngest } from "./pipeline.js";
|
|
9
|
+
import { runVideoIngest } from "./video-pipeline.js";
|
|
10
|
+
const strOf = (v) => (v === null || v === undefined ? "" : String(v));
|
|
11
|
+
const intOf = (v, fallback) => {
|
|
12
|
+
const n = Number(v);
|
|
13
|
+
return Number.isInteger(n) && n > 0 ? n : fallback;
|
|
14
|
+
};
|
|
15
|
+
export async function commandIngest(opts, composition = PRODUCTION_LLM_COMPOSITION) {
|
|
16
|
+
const sourcePath = strOf(opts["source_path"]).trim();
|
|
17
|
+
if (!sourcePath) {
|
|
18
|
+
throw new CliError("INGEST BLOCKED: no source", "ingest needs a source file or directory.", {
|
|
19
|
+
exitCode: EXIT_INPUT,
|
|
20
|
+
errorCode: "INGEST_NO_SOURCE",
|
|
21
|
+
required: ["--source-path <file|dir>"],
|
|
22
|
+
nextSteps: ["Pass a txt/md/docx file or a video file/directory: scriptctl ingest --source-path <path>."],
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
// Resolve to an absolute path so the workspace location is explicit and
|
|
26
|
+
// independent of cwd — the default "workspace" would otherwise land silently
|
|
27
|
+
// under wherever the command happened to run. Downstream (view / publish /
|
|
28
|
+
// ingest status / the runtime watcher) then all agree on one concrete dir.
|
|
29
|
+
const workspacePath = path.resolve(strOf(opts["workspace_path"] || "workspace"));
|
|
30
|
+
const resolved = resolveSource(sourcePath);
|
|
31
|
+
const executor = composition.createExecutor(strOf(opts["llm_config"]).trim() || undefined);
|
|
32
|
+
if (resolved.kind !== "text") {
|
|
33
|
+
const report = await runVideoIngest({
|
|
34
|
+
sourcePath,
|
|
35
|
+
workspacePath,
|
|
36
|
+
executor,
|
|
37
|
+
concurrency: intOf(opts["concurrency"], 30),
|
|
38
|
+
videoConcurrency: intOf(opts["video_concurrency"], 10),
|
|
39
|
+
fps: intOf(opts["fps"], 3),
|
|
40
|
+
force: Boolean(opts["force"]),
|
|
41
|
+
});
|
|
42
|
+
const result = [
|
|
43
|
+
`workspace: ${report.workspacePath}`,
|
|
44
|
+
`${report.episodes} episodes → ${report.scriptPath}`,
|
|
45
|
+
`roster: ${report.roster.input} names → ${report.roster.merged} people`,
|
|
46
|
+
`assets: ${report.assets.actors} actors / ${report.assets.locations} locations / ${report.assets.props} props`,
|
|
47
|
+
];
|
|
48
|
+
return [{ result }, EXIT_OK];
|
|
49
|
+
}
|
|
50
|
+
const report = await runTextIngest({
|
|
51
|
+
sourcePath,
|
|
52
|
+
workspacePath,
|
|
53
|
+
executor,
|
|
54
|
+
concurrency: intOf(opts["concurrency"], 80),
|
|
55
|
+
force: Boolean(opts["force"]),
|
|
56
|
+
});
|
|
57
|
+
const result = [
|
|
58
|
+
`workspace: ${report.workspacePath}`,
|
|
59
|
+
`${report.records} records, ${report.chunks} chunks → ${report.scriptPath}`,
|
|
60
|
+
`assets: ${report.assets.actors} actors / ${report.assets.locations} locations / ${report.assets.props} props`,
|
|
61
|
+
];
|
|
62
|
+
return [{ result }, EXIT_OK];
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command.js","sourceRoot":"","sources":["../../../src/usecases/ingest/command.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type Settled<T> = {
|
|
2
|
+
index: number;
|
|
3
|
+
ok: true;
|
|
4
|
+
value: T;
|
|
5
|
+
} | {
|
|
6
|
+
index: number;
|
|
7
|
+
ok: false;
|
|
8
|
+
error: unknown;
|
|
9
|
+
};
|
|
10
|
+
export declare function mapSettled<I, T>(items: I[], limit: number, fn: (item: I, index: number) => Promise<T>): Promise<Settled<T>[]>;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// Bounded-concurrency batch settle (§12.3). Runs every task, never short-
|
|
2
|
+
// circuits: collects each result or error so the caller can persist all success
|
|
3
|
+
// checkpoints and all error sidecars before blocking the next pass.
|
|
4
|
+
export async function mapSettled(items, limit, fn) {
|
|
5
|
+
const results = new Array(items.length);
|
|
6
|
+
let next = 0;
|
|
7
|
+
const workers = Array.from({ length: Math.max(1, Math.min(limit, items.length)) }, async () => {
|
|
8
|
+
for (;;) {
|
|
9
|
+
const i = next++;
|
|
10
|
+
if (i >= items.length)
|
|
11
|
+
return;
|
|
12
|
+
try {
|
|
13
|
+
results[i] = { index: i, ok: true, value: await fn(items[i], i) };
|
|
14
|
+
}
|
|
15
|
+
catch (error) {
|
|
16
|
+
results[i] = { index: i, ok: false, error };
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
await Promise.all(workers);
|
|
21
|
+
return results;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=fanout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fanout.js","sourceRoot":"","sources":["../../../src/usecases/ingest/fanout.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,gFAAgF;AAChF,oEAAoE;AAIpE,MAAM,CAAC,KAAK,UAAU,UAAU,CAAO,KAAU,EAAE,KAAa,EAAE,EAA0C;IAC1G,MAAM,OAAO,GAAiB,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACtD,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,KAAK,IAAI,EAAE;QAC5F,SAAS,CAAC;YACR,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC;YACjB,IAAI,CAAC,IAAI,KAAK,CAAC,MAAM;gBAAE,OAAO;YAC9B,IAAI,CAAC;gBACH,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,CAAE,EAAE,CAAC,CAAC,EAAE,CAAC;YACrE,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;YAC9C,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAC;IACH,MAAM,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAC3B,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { IngestRecord } from "../../domain/ingest/records.js";
|
|
2
|
+
import type { LlmTaskExecutor } from "../../llm/types.js";
|
|
3
|
+
export interface MentionResolveResult {
|
|
4
|
+
records: IngestRecord[];
|
|
5
|
+
rewritten: number;
|
|
6
|
+
}
|
|
7
|
+
export declare function runMentionResolvePass(records: IngestRecord[], opts: {
|
|
8
|
+
executor: LlmTaskExecutor;
|
|
9
|
+
concurrency?: number;
|
|
10
|
+
signal?: AbortSignal;
|
|
11
|
+
}): Promise<MentionResolveResult>;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// Pass4 mention-resolve orchestrator (§pass4). Per scene, rewrite body-record
|
|
2
|
+
// content so pronouns/vague references become concrete cast names (plain-text,
|
|
3
|
+
// only pronoun substitution). Cast = the scene record's declared 人物 ∪ its
|
|
4
|
+
// dialogue speakers. No-op for scenes without cast or without body records.
|
|
5
|
+
import { runMentionResolve } from "../../llm/tasks/ingest/mention-resolve.js";
|
|
6
|
+
import { mapSettled } from "./fanout.js";
|
|
7
|
+
const BODY = new Set(["action", "dialogue", "inner_thought", "transition"]);
|
|
8
|
+
const contentOf = (r) => ("content" in r ? r.content : "");
|
|
9
|
+
function groupScenes(records) {
|
|
10
|
+
const groups = [];
|
|
11
|
+
let cur = null;
|
|
12
|
+
records.forEach((rec, i) => {
|
|
13
|
+
if (rec.kind === "scene") {
|
|
14
|
+
cur = { cast: (rec.actors ?? []).map((a) => a.name), body: [] };
|
|
15
|
+
groups.push(cur);
|
|
16
|
+
}
|
|
17
|
+
else if (BODY.has(rec.kind)) {
|
|
18
|
+
if (!cur) {
|
|
19
|
+
cur = { cast: [], body: [] };
|
|
20
|
+
groups.push(cur);
|
|
21
|
+
}
|
|
22
|
+
cur.body.push(i);
|
|
23
|
+
if (rec.kind === "dialogue" || rec.kind === "inner_thought") {
|
|
24
|
+
const sp = rec.speaker;
|
|
25
|
+
if (sp && typeof sp === "object" && "name" in sp && !cur.cast.includes(sp.name))
|
|
26
|
+
cur.cast.push(sp.name);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
return groups;
|
|
31
|
+
}
|
|
32
|
+
export async function runMentionResolvePass(records, opts) {
|
|
33
|
+
const groups = groupScenes(records).filter((g) => g.cast.length > 0 && g.body.length > 0);
|
|
34
|
+
if (groups.length === 0)
|
|
35
|
+
return { records, rewritten: 0 };
|
|
36
|
+
const out = records.slice();
|
|
37
|
+
const settled = await mapSettled(groups, opts.concurrency ?? 80, async (g) => {
|
|
38
|
+
const lines = g.body.map((i) => ({ idx: i, text: contentOf(records[i]) }));
|
|
39
|
+
return runMentionResolve(opts.executor, g.cast, lines, opts.signal);
|
|
40
|
+
});
|
|
41
|
+
let rewritten = 0;
|
|
42
|
+
for (const s of settled) {
|
|
43
|
+
if (!s.ok)
|
|
44
|
+
continue;
|
|
45
|
+
for (const [idx, text] of s.value) {
|
|
46
|
+
out[idx] = { ...out[idx], content: text };
|
|
47
|
+
rewritten++;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return { records: out, rewritten };
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=pass4-mention-resolve.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pass4-mention-resolve.js","sourceRoot":"","sources":["../../../src/usecases/ingest/pass4-mention-resolve.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { NameScript } from "../../domain/ingest/assembler.js";
|
|
2
|
+
import type { LlmTaskExecutor } from "../../llm/types.js";
|
|
3
|
+
export declare function runExtractPass(script: NameScript, opts: {
|
|
4
|
+
executor: LlmTaskExecutor;
|
|
5
|
+
concurrency?: number;
|
|
6
|
+
signal?: AbortSignal;
|
|
7
|
+
}): Promise<NameScript>;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// Pass5-extract orchestrator (new). Per scene, augment the name-based scene cast
|
|
2
|
+
// and props from the plain-text body (declared 人物/道具 are the prior). Merges
|
|
3
|
+
// declared ∪ extracted by normalized name, preferring a declared state. A failed
|
|
4
|
+
// scene blocks the pass (no downgrade). Mutates + returns the name-based script.
|
|
5
|
+
import { runAssetExtract } from "../../llm/tasks/ingest/asset-extract.js";
|
|
6
|
+
import { CliError, EXIT_INPUT } from "../../common.js";
|
|
7
|
+
import { mapSettled } from "./fanout.js";
|
|
8
|
+
const norm = (s) => s.normalize("NFC").replace(/\s+/g, " ").trim();
|
|
9
|
+
function mergeRefs(base, add) {
|
|
10
|
+
const byName = new Map();
|
|
11
|
+
for (const r of base)
|
|
12
|
+
byName.set(norm(r.name), { ...r });
|
|
13
|
+
for (const r of add) {
|
|
14
|
+
const key = norm(r.name);
|
|
15
|
+
const existing = byName.get(key);
|
|
16
|
+
if (!existing)
|
|
17
|
+
byName.set(key, { ...r });
|
|
18
|
+
else if (!existing.state && r.state)
|
|
19
|
+
existing.state = r.state; // declared state wins; fill if empty
|
|
20
|
+
}
|
|
21
|
+
return [...byName.values()];
|
|
22
|
+
}
|
|
23
|
+
export async function runExtractPass(script, opts) {
|
|
24
|
+
const scenes = [];
|
|
25
|
+
for (const ep of script.episodes)
|
|
26
|
+
for (const sc of ep.scenes)
|
|
27
|
+
scenes.push(sc);
|
|
28
|
+
if (scenes.length === 0)
|
|
29
|
+
return script;
|
|
30
|
+
const settled = await mapSettled(scenes, opts.concurrency ?? 80, (sc) => {
|
|
31
|
+
const bodyLines = sc.actions.filter((a) => a.type === "action" || a.type === "dialogue" || a.type === "inner_thought").map((a) => a.content);
|
|
32
|
+
return runAssetExtract(opts.executor, bodyLines, sc.actors.map((a) => a.name), sc.props.map((p) => p.name), opts.signal);
|
|
33
|
+
});
|
|
34
|
+
const failures = settled.filter((s) => !s.ok);
|
|
35
|
+
if (failures.length > 0) {
|
|
36
|
+
throw new CliError("INGEST EXTRACT FAILED", `${failures.length} scene(s) failed asset extraction.`, {
|
|
37
|
+
exitCode: EXIT_INPUT, errorCode: "INGEST_EXTRACT_FAILED",
|
|
38
|
+
received: failures.map((f) => (f.error instanceof Error ? f.error.message : String(f.error))).slice(0, 5),
|
|
39
|
+
nextSteps: ["Rerun `scriptctl ingest`; extract failures are not downgraded."],
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
settled.forEach((s, i) => {
|
|
43
|
+
if (!s.ok)
|
|
44
|
+
return;
|
|
45
|
+
scenes[i].actors = mergeRefs(scenes[i].actors, s.value.actors);
|
|
46
|
+
scenes[i].props = mergeRefs(scenes[i].props, s.value.props);
|
|
47
|
+
});
|
|
48
|
+
return script;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=pass5-extract.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pass5-extract.js","sourceRoot":"","sources":["../../../src/usecases/ingest/pass5-extract.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ProvisionalAsset } from "../../domain/ingest/assembler.js";
|
|
2
|
+
import type { LlmTaskExecutor } from "../../llm/types.js";
|
|
3
|
+
export interface GovernCheckpoint {
|
|
4
|
+
read<T>(key: string): T | undefined;
|
|
5
|
+
write(key: string, value: unknown): void;
|
|
6
|
+
}
|
|
7
|
+
export interface GovernOptions {
|
|
8
|
+
executor: LlmTaskExecutor;
|
|
9
|
+
concurrency?: number;
|
|
10
|
+
signal?: AbortSignal;
|
|
11
|
+
checkpoint?: GovernCheckpoint;
|
|
12
|
+
}
|
|
13
|
+
export declare function runGovern(script: Record<string, unknown>, assets: ProvisionalAsset[], opts: GovernOptions): Promise<Record<string, unknown>>;
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
// Pass5 governance orchestrator (§9). Runs recall → per-group refine (LLM) to
|
|
2
|
+
// build a keep/merge/drop + canonical plan, then hands it to the deterministic
|
|
3
|
+
// coverage check + apply. Any refine group failing blocks the pass — no
|
|
4
|
+
// "keep-everything" downgrade (§9.5/§12.3). With no candidate groups the plan is
|
|
5
|
+
// all-keep and apply still materializes state via governDeterministic.
|
|
6
|
+
import { CliError, EXIT_INPUT } from "../../common.js";
|
|
7
|
+
import { applyPlanRaw } from "../../domain/ingest/apply-plan.js";
|
|
8
|
+
import { buildFlatLines, evidenceFor } from "../../domain/ingest/evidence.js";
|
|
9
|
+
import { governDeterministic } from "../../domain/ingest/govern.js";
|
|
10
|
+
import { applyStateReconcile, mergeableStates } from "../../domain/ingest/state-reconcile.js";
|
|
11
|
+
import { runRecall, runRefine } from "../../llm/tasks/ingest/asset-govern.js";
|
|
12
|
+
import { runCurate } from "../../llm/tasks/ingest/asset-curate.js";
|
|
13
|
+
import { runStateReconcile } from "../../llm/tasks/ingest/state-reconcile.js";
|
|
14
|
+
import { mapSettled } from "./fanout.js";
|
|
15
|
+
const CURATE_GROUP = 3;
|
|
16
|
+
function chunk(arr, n) {
|
|
17
|
+
const out = [];
|
|
18
|
+
for (let i = 0; i < arr.length; i += n)
|
|
19
|
+
out.push(arr.slice(i, i + n));
|
|
20
|
+
return out;
|
|
21
|
+
}
|
|
22
|
+
const sceneCount = (a) => new Set(a.occurrences.map((o) => `${o.episode}:${o.scene}`)).size;
|
|
23
|
+
export async function runGovern(script, assets, opts) {
|
|
24
|
+
const ck = opts.checkpoint;
|
|
25
|
+
const cached = async (key, fn) => {
|
|
26
|
+
const hit = ck?.read(key);
|
|
27
|
+
if (hit !== undefined)
|
|
28
|
+
return hit;
|
|
29
|
+
const val = await fn();
|
|
30
|
+
ck?.write(key, val);
|
|
31
|
+
return val;
|
|
32
|
+
};
|
|
33
|
+
// Base plan: every asset kept under its primary name.
|
|
34
|
+
const decisions = new Map();
|
|
35
|
+
const canonical = {};
|
|
36
|
+
for (const a of assets) {
|
|
37
|
+
decisions.set(a.provisional_id, { provisional_id: a.provisional_id, action: "keep" });
|
|
38
|
+
canonical[a.provisional_id] = { name: a.names[0] ?? a.provisional_id };
|
|
39
|
+
}
|
|
40
|
+
const byKind = { actor: [], location: [], prop: [] };
|
|
41
|
+
for (const a of assets)
|
|
42
|
+
byKind[a.kind].push(a);
|
|
43
|
+
const byId = new Map(assets.map((a) => [a.provisional_id, a]));
|
|
44
|
+
// Stage: curate. Classify each asset's importance tier (primary/secondary/
|
|
45
|
+
// background) in small same-kind groups with rich evidence (name occurrences
|
|
46
|
+
// as ±2-line windows). Nothing is dropped; background = 龙套/背景.
|
|
47
|
+
const nameOf = (id) => byId.get(id)?.names[0] ?? id;
|
|
48
|
+
const flatLines = buildFlatLines(script, nameOf);
|
|
49
|
+
const curateGroups = [];
|
|
50
|
+
for (const kind of ["actor", "location", "prop"]) {
|
|
51
|
+
for (const g of chunk(byKind[kind], CURATE_GROUP)) {
|
|
52
|
+
curateGroups.push({ kind, items: g.map((a) => ({ id: a.provisional_id, names: a.names, scenes: sceneCount(a), evidence: evidenceFor(flatLines, a.names) })) });
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
const curated = await mapSettled(curateGroups, opts.concurrency ?? 80, (g) => cached(`curate.${g.kind}.${g.items.map((i) => i.id).join("-")}`, async () => [...(await runCurate(opts.executor, g.kind, g.items, opts.signal))]));
|
|
56
|
+
const curateFail = curated.filter((s) => !s.ok);
|
|
57
|
+
if (curateFail.length > 0) {
|
|
58
|
+
throw new CliError("INGEST CURATE FAILED", `${curateFail.length} curate group(s) failed.`, {
|
|
59
|
+
exitCode: EXIT_INPUT, errorCode: "INGEST_CURATE_FAILED",
|
|
60
|
+
received: curateFail.map((f) => (f.error instanceof Error ? f.error.message : String(f.error))).slice(0, 5),
|
|
61
|
+
nextSteps: ["Rerun `scriptctl ingest`."],
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
const importance = {};
|
|
65
|
+
for (const s of curated)
|
|
66
|
+
if (s.ok)
|
|
67
|
+
for (const [id, tier] of s.value)
|
|
68
|
+
importance[id] = tier;
|
|
69
|
+
// Recall candidate groups per kind (cheap model), then refine.
|
|
70
|
+
const groups = [];
|
|
71
|
+
for (const kind of ["actor", "location", "prop"]) {
|
|
72
|
+
const recalled = await cached(`recall.${kind}`, () => runRecall(opts.executor, byKind[kind], kind, opts.signal));
|
|
73
|
+
for (const ids of recalled)
|
|
74
|
+
groups.push(ids.map((id) => byId.get(id)).filter(Boolean));
|
|
75
|
+
}
|
|
76
|
+
const settled = await mapSettled(groups, opts.concurrency ?? 80, (group) => cached(`refine.${group.map((a) => a.provisional_id).join("-")}`, () => runRefine(opts.executor, group, opts.signal)));
|
|
77
|
+
const failures = settled.filter((s) => !s.ok);
|
|
78
|
+
if (failures.length > 0) {
|
|
79
|
+
throw new CliError("INGEST GOVERN FAILED", `${failures.length} asset refine group(s) failed.`, {
|
|
80
|
+
exitCode: EXIT_INPUT,
|
|
81
|
+
errorCode: "INGEST_GOVERN_FAILED",
|
|
82
|
+
received: failures.map((f) => (f.error instanceof Error ? f.error.message : String(f.error))).slice(0, 5),
|
|
83
|
+
nextSteps: ["Rerun `scriptctl ingest`; refine failures are not downgraded to keep-all."],
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
// Overlay refine outcomes onto the base plan.
|
|
87
|
+
for (const s of settled) {
|
|
88
|
+
if (!s.ok)
|
|
89
|
+
continue;
|
|
90
|
+
for (const d of s.value.decisions)
|
|
91
|
+
decisions.set(d.provisional_id, d);
|
|
92
|
+
for (const [id, info] of Object.entries(s.value.canonical))
|
|
93
|
+
canonical[id] = info;
|
|
94
|
+
}
|
|
95
|
+
const plan = { decisions: [...decisions.values()], canonical, importance };
|
|
96
|
+
// Identity merge (pre-materialize), then state-name reconciliation per owner,
|
|
97
|
+
// then default assignment + materialization.
|
|
98
|
+
const raw = applyPlanRaw(script, plan);
|
|
99
|
+
const merged = await reconcileStates(raw, opts);
|
|
100
|
+
return governDeterministic(merged);
|
|
101
|
+
}
|
|
102
|
+
// Stage G: per owner, select durable appearance states + merge equivalents +
|
|
103
|
+
// drop transient (emotion/pose/moment). Any owner with ≥1 non-default candidate
|
|
104
|
+
// is reconciled. A failed owner blocks the pass (no downgrade).
|
|
105
|
+
async function reconcileStates(doc, opts) {
|
|
106
|
+
const owners = [];
|
|
107
|
+
const backgroundClear = []; // background assets → drop all states deterministically
|
|
108
|
+
for (const kind of ["actors", "locations", "props"]) {
|
|
109
|
+
const list = doc[kind];
|
|
110
|
+
if (!Array.isArray(list))
|
|
111
|
+
continue;
|
|
112
|
+
for (const asset of list) {
|
|
113
|
+
if (typeof asset !== "object" || asset === null)
|
|
114
|
+
continue;
|
|
115
|
+
const a = asset;
|
|
116
|
+
const idField = kind === "actors" ? "actor_id" : kind === "locations" ? "location_id" : "prop_id";
|
|
117
|
+
if (mergeableStates(a).length < 1)
|
|
118
|
+
continue;
|
|
119
|
+
const id = String(a[idField]);
|
|
120
|
+
if (a.importance === "background")
|
|
121
|
+
backgroundClear.push(id); // 龙套/背景:状态不管
|
|
122
|
+
else
|
|
123
|
+
owners.push({ id, states: mergeableStates(a) });
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
if (owners.length === 0 && backgroundClear.length === 0)
|
|
127
|
+
return doc;
|
|
128
|
+
const ck = opts.checkpoint;
|
|
129
|
+
const settled = await mapSettled(owners, opts.concurrency ?? 80, async (o) => {
|
|
130
|
+
const key = `state.${o.id}`;
|
|
131
|
+
const hit = ck?.read(key);
|
|
132
|
+
if (hit !== undefined)
|
|
133
|
+
return hit;
|
|
134
|
+
const val = await runStateReconcile(opts.executor, o.states, opts.signal);
|
|
135
|
+
ck?.write(key, val);
|
|
136
|
+
return val;
|
|
137
|
+
});
|
|
138
|
+
const failures = settled.filter((s) => !s.ok);
|
|
139
|
+
if (failures.length > 0) {
|
|
140
|
+
throw new CliError("INGEST STATE RECONCILE FAILED", `${failures.length} owner(s) failed state reconciliation.`, {
|
|
141
|
+
exitCode: EXIT_INPUT, errorCode: "INGEST_STATE_RECONCILE_FAILED",
|
|
142
|
+
received: failures.map((f) => (f.error instanceof Error ? f.error.message : String(f.error))).slice(0, 5),
|
|
143
|
+
nextSteps: ["Rerun `scriptctl ingest`; state reconcile failures are not downgraded."],
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
// Reconciled owner: keep the selected durable groups (empty → drop all).
|
|
147
|
+
// Background asset: forced empty → all non-default states dropped.
|
|
148
|
+
const keep = new Map();
|
|
149
|
+
settled.forEach((s, i) => { if (s.ok)
|
|
150
|
+
keep.set(owners[i].id, s.value); });
|
|
151
|
+
for (const id of backgroundClear)
|
|
152
|
+
keep.set(id, []);
|
|
153
|
+
return applyStateReconcile(doc, keep);
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=pass5-govern.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pass5-govern.js","sourceRoot":"","sources":["../../../src/usecases/ingest/pass5-govern.ts"],"names":[],"mappings":"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"}
|