@lingjingai/scriptctl 0.63.14 → 0.63.15
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 +7 -1
- package/changes/0.63.15.md +15 -0
- package/dist/bin.js +1 -20844
- package/dist/chunk-3LPIMYYI.js +823 -0
- package/dist/cli.d.ts +214 -5
- package/dist/cli.js +1 -187
- package/dist/review-agent.js +56 -3593
- package/package.json +12 -5
- package/dist/bin.d.ts +0 -2
- package/dist/bin.js.map +0 -7
- package/dist/cli/register-authoring.d.ts +0 -4
- package/dist/cli/register-authoring.js +0 -35
- package/dist/cli/register-authoring.js.map +0 -1
- package/dist/cli/register-review.d.ts +0 -3
- package/dist/cli/register-review.js +0 -20
- package/dist/cli/register-review.js.map +0 -1
- package/dist/cli/register-script.d.ts +0 -3
- package/dist/cli/register-script.js +0 -297
- package/dist/cli/register-script.js.map +0 -1
- package/dist/cli/register-tools.d.ts +0 -3
- package/dist/cli/register-tools.js +0 -23
- package/dist/cli/register-tools.js.map +0 -1
- package/dist/cli/register-workflows.d.ts +0 -4
- package/dist/cli/register-workflows.js +0 -108
- package/dist/cli/register-workflows.js.map +0 -1
- package/dist/cli/registry.d.ts +0 -14
- package/dist/cli/registry.js +0 -65
- package/dist/cli/registry.js.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/common.d.ts +0 -93
- package/dist/common.js +0 -240
- package/dist/common.js.map +0 -1
- package/dist/domain/authoring/apply.d.ts +0 -1
- package/dist/domain/authoring/apply.js +0 -2
- package/dist/domain/authoring/apply.js.map +0 -1
- package/dist/domain/authoring/export.d.ts +0 -1
- package/dist/domain/authoring/export.js +0 -2
- package/dist/domain/authoring/export.js.map +0 -1
- package/dist/domain/authoring/parser.d.ts +0 -2
- package/dist/domain/authoring/parser.js +0 -3
- package/dist/domain/authoring/parser.js.map +0 -1
- package/dist/domain/authoring/serializer.d.ts +0 -1
- package/dist/domain/authoring/serializer.js +0 -2
- package/dist/domain/authoring/serializer.js.map +0 -1
- package/dist/domain/authoring/shared/bracket.d.ts +0 -4
- package/dist/domain/authoring/shared/bracket.js +0 -95
- package/dist/domain/authoring/shared/bracket.js.map +0 -1
- package/dist/domain/authoring/shared/types.d.ts +0 -12
- package/dist/domain/authoring/shared/types.js +0 -2
- package/dist/domain/authoring/shared/types.js.map +0 -1
- package/dist/domain/authoring/types.d.ts +0 -2
- package/dist/domain/authoring/types.js +0 -3
- package/dist/domain/authoring/types.js.map +0 -1
- package/dist/domain/authoring/v3/apply.d.ts +0 -33
- package/dist/domain/authoring/v3/apply.js +0 -784
- package/dist/domain/authoring/v3/apply.js.map +0 -1
- package/dist/domain/authoring/v3/export.d.ts +0 -7
- package/dist/domain/authoring/v3/export.js +0 -85
- package/dist/domain/authoring/v3/export.js.map +0 -1
- package/dist/domain/authoring/v3/parser.d.ts +0 -3
- package/dist/domain/authoring/v3/parser.js +0 -823
- package/dist/domain/authoring/v3/parser.js.map +0 -1
- package/dist/domain/authoring/v3/serializer.d.ts +0 -2
- package/dist/domain/authoring/v3/serializer.js +0 -244
- package/dist/domain/authoring/v3/serializer.js.map +0 -1
- package/dist/domain/authoring/v3/types.d.ts +0 -76
- package/dist/domain/authoring/v3/types.js +0 -2
- package/dist/domain/authoring/v3/types.js.map +0 -1
- package/dist/domain/authoring/v4/apply.d.ts +0 -40
- package/dist/domain/authoring/v4/apply.js +0 -451
- package/dist/domain/authoring/v4/apply.js.map +0 -1
- package/dist/domain/authoring/v4/parser.d.ts +0 -2
- package/dist/domain/authoring/v4/parser.js +0 -729
- package/dist/domain/authoring/v4/parser.js.map +0 -1
- package/dist/domain/authoring/v4/serializer.d.ts +0 -6
- package/dist/domain/authoring/v4/serializer.js +0 -280
- package/dist/domain/authoring/v4/serializer.js.map +0 -1
- package/dist/domain/authoring/v4/types.d.ts +0 -50
- package/dist/domain/authoring/v4/types.js +0 -2
- package/dist/domain/authoring/v4/types.js.map +0 -1
- package/dist/domain/creative-draft/compose.d.ts +0 -18
- package/dist/domain/creative-draft/compose.js +0 -448
- package/dist/domain/creative-draft/compose.js.map +0 -1
- package/dist/domain/ingest/apply-plan.d.ts +0 -23
- package/dist/domain/ingest/apply-plan.js +0 -210
- package/dist/domain/ingest/apply-plan.js.map +0 -1
- package/dist/domain/ingest/assembler.d.ts +0 -65
- package/dist/domain/ingest/assembler.js +0 -263
- package/dist/domain/ingest/assembler.js.map +0 -1
- package/dist/domain/ingest/asset-audit.d.ts +0 -50
- package/dist/domain/ingest/asset-audit.js +0 -196
- package/dist/domain/ingest/asset-audit.js.map +0 -1
- package/dist/domain/ingest/chunker.d.ts +0 -9
- package/dist/domain/ingest/chunker.js +0 -49
- package/dist/domain/ingest/chunker.js.map +0 -1
- package/dist/domain/ingest/environment.d.ts +0 -3
- package/dist/domain/ingest/environment.js +0 -32
- package/dist/domain/ingest/environment.js.map +0 -1
- package/dist/domain/ingest/evidence.d.ts +0 -5
- package/dist/domain/ingest/evidence.js +0 -66
- package/dist/domain/ingest/evidence.js.map +0 -1
- package/dist/domain/ingest/govern.d.ts +0 -3
- package/dist/domain/ingest/govern.js +0 -157
- package/dist/domain/ingest/govern.js.map +0 -1
- package/dist/domain/ingest/jsonl-parser.d.ts +0 -6
- package/dist/domain/ingest/jsonl-parser.js +0 -204
- package/dist/domain/ingest/jsonl-parser.js.map +0 -1
- package/dist/domain/ingest/markdown-parser.d.ts +0 -6
- package/dist/domain/ingest/markdown-parser.js +0 -187
- package/dist/domain/ingest/markdown-parser.js.map +0 -1
- package/dist/domain/ingest/production-validation.d.ts +0 -8
- package/dist/domain/ingest/production-validation.js +0 -37
- package/dist/domain/ingest/production-validation.js.map +0 -1
- package/dist/domain/ingest/records.d.ts +0 -72
- package/dist/domain/ingest/records.js +0 -10
- package/dist/domain/ingest/records.js.map +0 -1
- package/dist/domain/ingest/renumber.d.ts +0 -14
- package/dist/domain/ingest/renumber.js +0 -130
- package/dist/domain/ingest/renumber.js.map +0 -1
- package/dist/domain/ingest/serial-context.d.ts +0 -93
- package/dist/domain/ingest/serial-context.js +0 -355
- package/dist/domain/ingest/serial-context.js.map +0 -1
- package/dist/domain/ingest/state-identity.d.ts +0 -2
- package/dist/domain/ingest/state-identity.js +0 -3
- package/dist/domain/ingest/state-identity.js.map +0 -1
- package/dist/domain/ingest/state-reconcile.d.ts +0 -12
- package/dist/domain/ingest/state-reconcile.js +0 -92
- package/dist/domain/ingest/state-reconcile.js.map +0 -1
- package/dist/domain/ingest/validation.d.ts +0 -1
- package/dist/domain/ingest/validation.js +0 -2
- package/dist/domain/ingest/validation.js.map +0 -1
- package/dist/domain/ingest/video-apply.d.ts +0 -4
- package/dist/domain/ingest/video-apply.js +0 -128
- package/dist/domain/ingest/video-apply.js.map +0 -1
- package/dist/domain/ingest/video-context.d.ts +0 -64
- package/dist/domain/ingest/video-context.js +0 -480
- package/dist/domain/ingest/video-context.js.map +0 -1
- package/dist/domain/ingest/video-records.d.ts +0 -57
- package/dist/domain/ingest/video-records.js +0 -9
- package/dist/domain/ingest/video-records.js.map +0 -1
- package/dist/domain/ingest/video-serial-md.d.ts +0 -81
- package/dist/domain/ingest/video-serial-md.js +0 -297
- package/dist/domain/ingest/video-serial-md.js.map +0 -1
- package/dist/domain/ingest/video-source-evolution.d.ts +0 -25
- package/dist/domain/ingest/video-source-evolution.js +0 -40
- package/dist/domain/ingest/video-source-evolution.js.map +0 -1
- package/dist/domain/ingest/video-state-evidence.d.ts +0 -66
- package/dist/domain/ingest/video-state-evidence.js +0 -385
- package/dist/domain/ingest/video-state-evidence.js.map +0 -1
- package/dist/domain/ingest/video-timestamp.d.ts +0 -8
- package/dist/domain/ingest/video-timestamp.js +0 -26
- package/dist/domain/ingest/video-timestamp.js.map +0 -1
- package/dist/domain/loom/checkpointer.d.ts +0 -3
- package/dist/domain/loom/checkpointer.js +0 -30
- package/dist/domain/loom/checkpointer.js.map +0 -1
- package/dist/domain/loom/index.d.ts +0 -45
- package/dist/domain/loom/index.js +0 -277
- package/dist/domain/loom/index.js.map +0 -1
- package/dist/domain/loom/types.d.ts +0 -101
- package/dist/domain/loom/types.js +0 -2
- package/dist/domain/loom/types.js.map +0 -1
- package/dist/domain/script/address.d.ts +0 -1
- package/dist/domain/script/address.js +0 -2
- package/dist/domain/script/address.js.map +0 -1
- package/dist/domain/script/dispatch.d.ts +0 -18
- package/dist/domain/script/dispatch.js +0 -55
- package/dist/domain/script/dispatch.js.map +0 -1
- package/dist/domain/script/lookups.d.ts +0 -1
- package/dist/domain/script/lookups.js +0 -2
- package/dist/domain/script/lookups.js.map +0 -1
- package/dist/domain/script/migrations/registry.d.ts +0 -4
- package/dist/domain/script/migrations/registry.js +0 -76
- package/dist/domain/script/migrations/registry.js.map +0 -1
- package/dist/domain/script/migrations/types.d.ts +0 -17
- package/dist/domain/script/migrations/types.js +0 -2
- package/dist/domain/script/migrations/types.js.map +0 -1
- package/dist/domain/script/migrations/v3-to-v4.d.ts +0 -3
- package/dist/domain/script/migrations/v3-to-v4.js +0 -57
- package/dist/domain/script/migrations/v3-to-v4.js.map +0 -1
- package/dist/domain/script/names.d.ts +0 -1
- package/dist/domain/script/names.js +0 -2
- package/dist/domain/script/names.js.map +0 -1
- package/dist/domain/script/parse.d.ts +0 -1
- package/dist/domain/script/parse.js +0 -2
- package/dist/domain/script/parse.js.map +0 -1
- package/dist/domain/script/patch/apply.d.ts +0 -1
- package/dist/domain/script/patch/apply.js +0 -2
- package/dist/domain/script/patch/apply.js.map +0 -1
- package/dist/domain/script/patch/helpers.d.ts +0 -1
- package/dist/domain/script/patch/helpers.js +0 -2
- package/dist/domain/script/patch/helpers.js.map +0 -1
- package/dist/domain/script/patch/inline-speaker.d.ts +0 -1
- package/dist/domain/script/patch/inline-speaker.js +0 -2
- package/dist/domain/script/patch/inline-speaker.js.map +0 -1
- package/dist/domain/script/patch/ops-action.d.ts +0 -1
- package/dist/domain/script/patch/ops-action.js +0 -2
- package/dist/domain/script/patch/ops-action.js.map +0 -1
- package/dist/domain/script/patch/ops-asset.d.ts +0 -1
- package/dist/domain/script/patch/ops-asset.js +0 -2
- package/dist/domain/script/patch/ops-asset.js.map +0 -1
- package/dist/domain/script/patch/ops-dialogue.d.ts +0 -1
- package/dist/domain/script/patch/ops-dialogue.js +0 -2
- package/dist/domain/script/patch/ops-dialogue.js.map +0 -1
- package/dist/domain/script/patch/ops-extend.d.ts +0 -1
- package/dist/domain/script/patch/ops-extend.js +0 -2
- package/dist/domain/script/patch/ops-extend.js.map +0 -1
- package/dist/domain/script/patch/ops-meta.d.ts +0 -1
- package/dist/domain/script/patch/ops-meta.js +0 -2
- package/dist/domain/script/patch/ops-meta.js.map +0 -1
- package/dist/domain/script/patch/ops-scene.d.ts +0 -1
- package/dist/domain/script/patch/ops-scene.js +0 -2
- package/dist/domain/script/patch/ops-scene.js.map +0 -1
- package/dist/domain/script/patch/ops-state.d.ts +0 -1
- package/dist/domain/script/patch/ops-state.js +0 -2
- package/dist/domain/script/patch/ops-state.js.map +0 -1
- package/dist/domain/script/patch/registry.d.ts +0 -1
- package/dist/domain/script/patch/registry.js +0 -2
- package/dist/domain/script/patch/registry.js.map +0 -1
- package/dist/domain/script/patch/types.d.ts +0 -1
- package/dist/domain/script/patch/types.js +0 -2
- package/dist/domain/script/patch/types.js.map +0 -1
- package/dist/domain/script/refs.d.ts +0 -1
- package/dist/domain/script/refs.js +0 -2
- package/dist/domain/script/refs.js.map +0 -1
- package/dist/domain/script/scene-refs.d.ts +0 -1
- package/dist/domain/script/scene-refs.js +0 -2
- package/dist/domain/script/scene-refs.js.map +0 -1
- package/dist/domain/script/schema.d.ts +0 -1
- package/dist/domain/script/schema.js +0 -2
- package/dist/domain/script/schema.js.map +0 -1
- package/dist/domain/script/selector.d.ts +0 -1
- package/dist/domain/script/selector.js +0 -2
- package/dist/domain/script/selector.js.map +0 -1
- package/dist/domain/script/shared/regex.d.ts +0 -2
- package/dist/domain/script/shared/regex.js +0 -7
- package/dist/domain/script/shared/regex.js.map +0 -1
- package/dist/domain/script/shared/types.d.ts +0 -1
- package/dist/domain/script/shared/types.js +0 -5
- package/dist/domain/script/shared/types.js.map +0 -1
- package/dist/domain/script/shared/validation.d.ts +0 -1
- package/dist/domain/script/shared/validation.js +0 -3
- package/dist/domain/script/shared/validation.js.map +0 -1
- package/dist/domain/script/shared.d.ts +0 -15
- package/dist/domain/script/shared.js +0 -35
- package/dist/domain/script/shared.js.map +0 -1
- package/dist/domain/script/text-util.d.ts +0 -7
- package/dist/domain/script/text-util.js +0 -95
- package/dist/domain/script/text-util.js.map +0 -1
- package/dist/domain/script/timestamp.d.ts +0 -1
- package/dist/domain/script/timestamp.js +0 -3
- package/dist/domain/script/timestamp.js.map +0 -1
- package/dist/domain/script/types.d.ts +0 -1
- package/dist/domain/script/types.js +0 -2
- package/dist/domain/script/types.js.map +0 -1
- package/dist/domain/script/v3/address.d.ts +0 -32
- package/dist/domain/script/v3/address.js +0 -136
- package/dist/domain/script/v3/address.js.map +0 -1
- package/dist/domain/script/v3/lookups.d.ts +0 -33
- package/dist/domain/script/v3/lookups.js +0 -316
- package/dist/domain/script/v3/lookups.js.map +0 -1
- package/dist/domain/script/v3/ordinal.d.ts +0 -8
- package/dist/domain/script/v3/ordinal.js +0 -91
- package/dist/domain/script/v3/ordinal.js.map +0 -1
- package/dist/domain/script/v3/parse.d.ts +0 -3
- package/dist/domain/script/v3/parse.js +0 -164
- package/dist/domain/script/v3/parse.js.map +0 -1
- package/dist/domain/script/v3/patch/apply.d.ts +0 -2
- package/dist/domain/script/v3/patch/apply.js +0 -31
- package/dist/domain/script/v3/patch/apply.js.map +0 -1
- package/dist/domain/script/v3/patch/helpers.d.ts +0 -15
- package/dist/domain/script/v3/patch/helpers.js +0 -155
- package/dist/domain/script/v3/patch/helpers.js.map +0 -1
- package/dist/domain/script/v3/patch/inline-speaker.d.ts +0 -2
- package/dist/domain/script/v3/patch/inline-speaker.js +0 -50
- package/dist/domain/script/v3/patch/inline-speaker.js.map +0 -1
- package/dist/domain/script/v3/patch/ops-action.d.ts +0 -12
- package/dist/domain/script/v3/patch/ops-action.js +0 -355
- package/dist/domain/script/v3/patch/ops-action.js.map +0 -1
- package/dist/domain/script/v3/patch/ops-asset.d.ts +0 -14
- package/dist/domain/script/v3/patch/ops-asset.js +0 -347
- package/dist/domain/script/v3/patch/ops-asset.js.map +0 -1
- package/dist/domain/script/v3/patch/ops-dialogue.d.ts +0 -2
- package/dist/domain/script/v3/patch/ops-dialogue.js +0 -21
- package/dist/domain/script/v3/patch/ops-dialogue.js.map +0 -1
- package/dist/domain/script/v3/patch/ops-extend.d.ts +0 -8
- package/dist/domain/script/v3/patch/ops-extend.js +0 -122
- package/dist/domain/script/v3/patch/ops-extend.js.map +0 -1
- package/dist/domain/script/v3/patch/ops-meta.d.ts +0 -5
- package/dist/domain/script/v3/patch/ops-meta.js +0 -82
- package/dist/domain/script/v3/patch/ops-meta.js.map +0 -1
- package/dist/domain/script/v3/patch/ops-scene.d.ts +0 -6
- package/dist/domain/script/v3/patch/ops-scene.js +0 -351
- package/dist/domain/script/v3/patch/ops-scene.js.map +0 -1
- package/dist/domain/script/v3/patch/ops-state.d.ts +0 -8
- package/dist/domain/script/v3/patch/ops-state.js +0 -155
- package/dist/domain/script/v3/patch/ops-state.js.map +0 -1
- package/dist/domain/script/v3/patch/ops-timestamp.d.ts +0 -6
- package/dist/domain/script/v3/patch/ops-timestamp.js +0 -47
- package/dist/domain/script/v3/patch/ops-timestamp.js.map +0 -1
- package/dist/domain/script/v3/patch/registry.d.ts +0 -2
- package/dist/domain/script/v3/patch/registry.js +0 -56
- package/dist/domain/script/v3/patch/registry.js.map +0 -1
- package/dist/domain/script/v3/patch/types.d.ts +0 -10
- package/dist/domain/script/v3/patch/types.js +0 -2
- package/dist/domain/script/v3/patch/types.js.map +0 -1
- package/dist/domain/script/v3/refs.d.ts +0 -4
- package/dist/domain/script/v3/refs.js +0 -64
- package/dist/domain/script/v3/refs.js.map +0 -1
- package/dist/domain/script/v3/scene-refs.d.ts +0 -3
- package/dist/domain/script/v3/scene-refs.js +0 -35
- package/dist/domain/script/v3/scene-refs.js.map +0 -1
- package/dist/domain/script/v3/schema.d.ts +0 -6
- package/dist/domain/script/v3/schema.js +0 -58
- package/dist/domain/script/v3/schema.js.map +0 -1
- package/dist/domain/script/v3/selector.d.ts +0 -44
- package/dist/domain/script/v3/selector.js +0 -178
- package/dist/domain/script/v3/selector.js.map +0 -1
- package/dist/domain/script/v3/types.d.ts +0 -106
- package/dist/domain/script/v3/types.js +0 -2
- package/dist/domain/script/v3/types.js.map +0 -1
- package/dist/domain/script/v3/validation.d.ts +0 -2
- package/dist/domain/script/v3/validation.js +0 -2
- package/dist/domain/script/v3/validation.js.map +0 -1
- package/dist/domain/script/v4/address.d.ts +0 -61
- package/dist/domain/script/v4/address.js +0 -99
- package/dist/domain/script/v4/address.js.map +0 -1
- package/dist/domain/script/v4/factory.d.ts +0 -2
- package/dist/domain/script/v4/factory.js +0 -13
- package/dist/domain/script/v4/factory.js.map +0 -1
- package/dist/domain/script/v4/from-v3.d.ts +0 -29
- package/dist/domain/script/v4/from-v3.js +0 -307
- package/dist/domain/script/v4/from-v3.js.map +0 -1
- package/dist/domain/script/v4/ids.d.ts +0 -5
- package/dist/domain/script/v4/ids.js +0 -41
- package/dist/domain/script/v4/ids.js.map +0 -1
- package/dist/domain/script/v4/ordinal.d.ts +0 -3
- package/dist/domain/script/v4/ordinal.js +0 -66
- package/dist/domain/script/v4/ordinal.js.map +0 -1
- package/dist/domain/script/v4/parse.d.ts +0 -5
- package/dist/domain/script/v4/parse.js +0 -196
- package/dist/domain/script/v4/parse.js.map +0 -1
- package/dist/domain/script/v4/patch/apply.d.ts +0 -3
- package/dist/domain/script/v4/patch/apply.js +0 -24
- package/dist/domain/script/v4/patch/apply.js.map +0 -1
- package/dist/domain/script/v4/patch/helpers.d.ts +0 -32
- package/dist/domain/script/v4/patch/helpers.js +0 -138
- package/dist/domain/script/v4/patch/helpers.js.map +0 -1
- package/dist/domain/script/v4/patch/ops-action.d.ts +0 -13
- package/dist/domain/script/v4/patch/ops-action.js +0 -351
- package/dist/domain/script/v4/patch/ops-action.js.map +0 -1
- package/dist/domain/script/v4/patch/ops-asset.d.ts +0 -17
- package/dist/domain/script/v4/patch/ops-asset.js +0 -556
- package/dist/domain/script/v4/patch/ops-asset.js.map +0 -1
- package/dist/domain/script/v4/patch/ops-extend.d.ts +0 -11
- package/dist/domain/script/v4/patch/ops-extend.js +0 -103
- package/dist/domain/script/v4/patch/ops-extend.js.map +0 -1
- package/dist/domain/script/v4/patch/ops-meta.d.ts +0 -5
- package/dist/domain/script/v4/patch/ops-meta.js +0 -49
- package/dist/domain/script/v4/patch/ops-meta.js.map +0 -1
- package/dist/domain/script/v4/patch/ops-scene-ref.d.ts +0 -3
- package/dist/domain/script/v4/patch/ops-scene-ref.js +0 -74
- package/dist/domain/script/v4/patch/ops-scene-ref.js.map +0 -1
- package/dist/domain/script/v4/patch/ops-structure.d.ts +0 -6
- package/dist/domain/script/v4/patch/ops-structure.js +0 -236
- package/dist/domain/script/v4/patch/ops-structure.js.map +0 -1
- package/dist/domain/script/v4/patch/ops-timestamp.d.ts +0 -6
- package/dist/domain/script/v4/patch/ops-timestamp.js +0 -40
- package/dist/domain/script/v4/patch/ops-timestamp.js.map +0 -1
- package/dist/domain/script/v4/patch/registry.d.ts +0 -2
- package/dist/domain/script/v4/patch/registry.js +0 -53
- package/dist/domain/script/v4/patch/registry.js.map +0 -1
- package/dist/domain/script/v4/patch/schema.d.ts +0 -7
- package/dist/domain/script/v4/patch/schema.js +0 -77
- package/dist/domain/script/v4/patch/schema.js.map +0 -1
- package/dist/domain/script/v4/patch/types.d.ts +0 -10
- package/dist/domain/script/v4/patch/types.js +0 -2
- package/dist/domain/script/v4/patch/types.js.map +0 -1
- package/dist/domain/script/v4/selector.d.ts +0 -11
- package/dist/domain/script/v4/selector.js +0 -124
- package/dist/domain/script/v4/selector.js.map +0 -1
- package/dist/domain/script/v4/types.d.ts +0 -120
- package/dist/domain/script/v4/types.js +0 -2
- package/dist/domain/script/v4/types.js.map +0 -1
- package/dist/domain/script/v4/validation.d.ts +0 -2
- package/dist/domain/script/v4/validation.js +0 -2
- package/dist/domain/script/v4/validation.js.map +0 -1
- package/dist/failures.d.ts +0 -58
- package/dist/failures.js +0 -96
- package/dist/failures.js.map +0 -1
- package/dist/infra/converters.d.ts +0 -9
- package/dist/infra/converters.js +0 -689
- package/dist/infra/converters.js.map +0 -1
- package/dist/infra/env.d.ts +0 -2
- package/dist/infra/env.js +0 -81
- package/dist/infra/env.js.map +0 -1
- package/dist/infra/episode-title.d.ts +0 -4
- package/dist/infra/episode-title.js +0 -129
- package/dist/infra/episode-title.js.map +0 -1
- package/dist/infra/ingest/review-renderer.d.ts +0 -1
- package/dist/infra/ingest/review-renderer.js +0 -440
- package/dist/infra/ingest/review-renderer.js.map +0 -1
- package/dist/infra/ingest/source-resolver.d.ts +0 -21
- package/dist/infra/ingest/source-resolver.js +0 -51
- package/dist/infra/ingest/source-resolver.js.map +0 -1
- package/dist/infra/ingest/text-reader.d.ts +0 -3
- package/dist/infra/ingest/text-reader.js +0 -27
- package/dist/infra/ingest/text-reader.js.map +0 -1
- package/dist/infra/ingest/video-discovery.d.ts +0 -8
- package/dist/infra/ingest/video-discovery.js +0 -69
- package/dist/infra/ingest/video-discovery.js.map +0 -1
- package/dist/infra/ingest/video-source-snapshot.d.ts +0 -4
- package/dist/infra/ingest/video-source-snapshot.js +0 -47
- package/dist/infra/ingest/video-source-snapshot.js.map +0 -1
- package/dist/infra/ingest/video-state-evidence.d.ts +0 -14
- package/dist/infra/ingest/video-state-evidence.js +0 -140
- package/dist/infra/ingest/video-state-evidence.js.map +0 -1
- package/dist/infra/ingest/video-transcode.d.ts +0 -7
- package/dist/infra/ingest/video-transcode.js +0 -98
- package/dist/infra/ingest/video-transcode.js.map +0 -1
- package/dist/infra/ingest/workspace-lock.d.ts +0 -1
- package/dist/infra/ingest/workspace-lock.js +0 -32
- package/dist/infra/ingest/workspace-lock.js.map +0 -1
- package/dist/infra/ingest/workspace-store.d.ts +0 -18
- package/dist/infra/ingest/workspace-store.js +0 -70
- package/dist/infra/ingest/workspace-store.js.map +0 -1
- package/dist/infra/llm/anthropic-model.d.ts +0 -11
- package/dist/infra/llm/anthropic-model.js +0 -130
- package/dist/infra/llm/anthropic-model.js.map +0 -1
- package/dist/infra/llm/doubao-model.d.ts +0 -60
- package/dist/infra/llm/doubao-model.js +0 -249
- package/dist/infra/llm/doubao-model.js.map +0 -1
- package/dist/infra/llm/failure-mapping.d.ts +0 -6
- package/dist/infra/llm/failure-mapping.js +0 -146
- package/dist/infra/llm/failure-mapping.js.map +0 -1
- package/dist/infra/llm/gemini-upload.d.ts +0 -13
- package/dist/infra/llm/gemini-upload.js +0 -138
- package/dist/infra/llm/gemini-upload.js.map +0 -1
- package/dist/infra/llm/gemini-video-model.d.ts +0 -50
- package/dist/infra/llm/gemini-video-model.js +0 -371
- package/dist/infra/llm/gemini-video-model.js.map +0 -1
- package/dist/infra/llm/openai-compatible-model.d.ts +0 -14
- package/dist/infra/llm/openai-compatible-model.js +0 -207
- package/dist/infra/llm/openai-compatible-model.js.map +0 -1
- package/dist/infra/llm/retry.d.ts +0 -8
- package/dist/infra/llm/retry.js +0 -41
- package/dist/infra/llm/retry.js.map +0 -1
- package/dist/infra/local-script-output-store.d.ts +0 -43
- package/dist/infra/local-script-output-store.js +0 -168
- package/dist/infra/local-script-output-store.js.map +0 -1
- package/dist/infra/script-output-api.d.ts +0 -50
- package/dist/infra/script-output-api.js +0 -251
- package/dist/infra/script-output-api.js.map +0 -1
- package/dist/infra/script-output-store.d.ts +0 -152
- package/dist/infra/script-output-store.js +0 -114
- package/dist/infra/script-output-store.js.map +0 -1
- package/dist/infra/script-working-copy.d.ts +0 -23
- package/dist/infra/script-working-copy.js +0 -157
- package/dist/infra/script-working-copy.js.map +0 -1
- package/dist/infra/storage.d.ts +0 -35
- package/dist/infra/storage.js +0 -91
- package/dist/infra/storage.js.map +0 -1
- package/dist/llm/composition.d.ts +0 -5
- package/dist/llm/composition.js +0 -5
- package/dist/llm/composition.js.map +0 -1
- package/dist/llm/config.d.ts +0 -28
- package/dist/llm/config.js +0 -231
- package/dist/llm/config.js.map +0 -1
- package/dist/llm/registry.d.ts +0 -43
- package/dist/llm/registry.js +0 -69
- package/dist/llm/registry.js.map +0 -1
- package/dist/llm/router.d.ts +0 -46
- package/dist/llm/router.js +0 -512
- package/dist/llm/router.js.map +0 -1
- package/dist/llm/tasks/ingest/arc-summary.d.ts +0 -8
- package/dist/llm/tasks/ingest/arc-summary.js +0 -26
- package/dist/llm/tasks/ingest/arc-summary.js.map +0 -1
- package/dist/llm/tasks/ingest/asset-audit.d.ts +0 -6
- package/dist/llm/tasks/ingest/asset-audit.js +0 -158
- package/dist/llm/tasks/ingest/asset-audit.js.map +0 -1
- package/dist/llm/tasks/ingest/asset-curate.d.ts +0 -13
- package/dist/llm/tasks/ingest/asset-curate.js +0 -45
- package/dist/llm/tasks/ingest/asset-curate.js.map +0 -1
- package/dist/llm/tasks/ingest/asset-extract.d.ts +0 -12
- package/dist/llm/tasks/ingest/asset-extract.js +0 -51
- package/dist/llm/tasks/ingest/asset-extract.js.map +0 -1
- package/dist/llm/tasks/ingest/asset-govern.d.ts +0 -22
- package/dist/llm/tasks/ingest/asset-govern.js +0 -143
- package/dist/llm/tasks/ingest/asset-govern.js.map +0 -1
- package/dist/llm/tasks/ingest/body-start.d.ts +0 -10
- package/dist/llm/tasks/ingest/body-start.js +0 -41
- package/dist/llm/tasks/ingest/body-start.js.map +0 -1
- package/dist/llm/tasks/ingest/episode-assets.d.ts +0 -29
- package/dist/llm/tasks/ingest/episode-assets.js +0 -282
- package/dist/llm/tasks/ingest/episode-assets.js.map +0 -1
- package/dist/llm/tasks/ingest/mention-resolve.d.ts +0 -9
- package/dist/llm/tasks/ingest/mention-resolve.js +0 -39
- package/dist/llm/tasks/ingest/mention-resolve.js.map +0 -1
- package/dist/llm/tasks/ingest/name-fix.d.ts +0 -9
- package/dist/llm/tasks/ingest/name-fix.js +0 -56
- package/dist/llm/tasks/ingest/name-fix.js.map +0 -1
- package/dist/llm/tasks/ingest/state-reconcile.d.ts +0 -8
- package/dist/llm/tasks/ingest/state-reconcile.js +0 -44
- package/dist/llm/tasks/ingest/state-reconcile.js.map +0 -1
- package/dist/llm/tasks/ingest/text-normalize.d.ts +0 -10
- package/dist/llm/tasks/ingest/text-normalize.js +0 -122
- package/dist/llm/tasks/ingest/text-normalize.js.map +0 -1
- package/dist/llm/tasks/ingest/video-serial.d.ts +0 -24
- package/dist/llm/tasks/ingest/video-serial.js +0 -416
- package/dist/llm/tasks/ingest/video-serial.js.map +0 -1
- package/dist/llm/tasks/schemas.d.ts +0 -9
- package/dist/llm/tasks/schemas.js +0 -466
- package/dist/llm/tasks/schemas.js.map +0 -1
- package/dist/llm/types.d.ts +0 -178
- package/dist/llm/types.js +0 -44
- package/dist/llm/types.js.map +0 -1
- package/dist/output.d.ts +0 -3
- package/dist/output.js +0 -94
- package/dist/output.js.map +0 -1
- package/dist/package-root.d.ts +0 -2
- package/dist/package-root.js +0 -38
- package/dist/package-root.js.map +0 -1
- package/dist/review-agent.js.map +0 -7
- package/dist/usecases/changelog.d.ts +0 -9
- package/dist/usecases/changelog.js +0 -134
- package/dist/usecases/changelog.js.map +0 -1
- package/dist/usecases/doctor.d.ts +0 -2
- package/dist/usecases/doctor.js +0 -231
- package/dist/usecases/doctor.js.map +0 -1
- package/dist/usecases/ingest/body-start.d.ts +0 -8
- package/dist/usecases/ingest/body-start.js +0 -36
- package/dist/usecases/ingest/body-start.js.map +0 -1
- package/dist/usecases/ingest/command.d.ts +0 -5
- package/dist/usecases/ingest/command.js +0 -183
- package/dist/usecases/ingest/command.js.map +0 -1
- package/dist/usecases/ingest/failure.d.ts +0 -26
- package/dist/usecases/ingest/failure.js +0 -153
- package/dist/usecases/ingest/failure.js.map +0 -1
- package/dist/usecases/ingest/fanout.d.ts +0 -10
- package/dist/usecases/ingest/fanout.js +0 -23
- package/dist/usecases/ingest/fanout.js.map +0 -1
- package/dist/usecases/ingest/final-asset-audit.d.ts +0 -39
- package/dist/usecases/ingest/final-asset-audit.js +0 -88
- package/dist/usecases/ingest/final-asset-audit.js.map +0 -1
- package/dist/usecases/ingest/generate-video-state-evidence.d.ts +0 -23
- package/dist/usecases/ingest/generate-video-state-evidence.js +0 -124
- package/dist/usecases/ingest/generate-video-state-evidence.js.map +0 -1
- package/dist/usecases/ingest/pass4-mention-resolve.d.ts +0 -11
- package/dist/usecases/ingest/pass4-mention-resolve.js +0 -52
- package/dist/usecases/ingest/pass4-mention-resolve.js.map +0 -1
- package/dist/usecases/ingest/pass5-extract.d.ts +0 -7
- package/dist/usecases/ingest/pass5-extract.js +0 -51
- package/dist/usecases/ingest/pass5-extract.js.map +0 -1
- package/dist/usecases/ingest/pass5-govern.d.ts +0 -13
- package/dist/usecases/ingest/pass5-govern.js +0 -157
- package/dist/usecases/ingest/pass5-govern.js.map +0 -1
- package/dist/usecases/ingest/pipeline.d.ts +0 -28
- package/dist/usecases/ingest/pipeline.js +0 -335
- package/dist/usecases/ingest/pipeline.js.map +0 -1
- package/dist/usecases/ingest/publish-command.d.ts +0 -1
- package/dist/usecases/ingest/publish-command.js +0 -4
- package/dist/usecases/ingest/publish-command.js.map +0 -1
- package/dist/usecases/ingest/serial-govern.d.ts +0 -40
- package/dist/usecases/ingest/serial-govern.js +0 -488
- package/dist/usecases/ingest/serial-govern.js.map +0 -1
- package/dist/usecases/ingest/skip-video-episode.d.ts +0 -4
- package/dist/usecases/ingest/skip-video-episode.js +0 -120
- package/dist/usecases/ingest/skip-video-episode.js.map +0 -1
- package/dist/usecases/ingest/status.d.ts +0 -61
- package/dist/usecases/ingest/status.js +0 -347
- package/dist/usecases/ingest/status.js.map +0 -1
- package/dist/usecases/ingest/timings.d.ts +0 -51
- package/dist/usecases/ingest/timings.js +0 -68
- package/dist/usecases/ingest/timings.js.map +0 -1
- package/dist/usecases/ingest/usage-report.d.ts +0 -125
- package/dist/usecases/ingest/usage-report.js +0 -248
- package/dist/usecases/ingest/usage-report.js.map +0 -1
- package/dist/usecases/ingest/video-pipeline.d.ts +0 -81
- package/dist/usecases/ingest/video-pipeline.js +0 -548
- package/dist/usecases/ingest/video-pipeline.js.map +0 -1
- package/dist/usecases/ingest/video-skip-state.d.ts +0 -29
- package/dist/usecases/ingest/video-skip-state.js +0 -148
- package/dist/usecases/ingest/video-skip-state.js.map +0 -1
- package/dist/usecases/ingest/view-command.d.ts +0 -4
- package/dist/usecases/ingest/view-command.js +0 -67
- package/dist/usecases/ingest/view-command.js.map +0 -1
- package/dist/usecases/ingest/view-server.d.ts +0 -29
- package/dist/usecases/ingest/view-server.js +0 -364
- package/dist/usecases/ingest/view-server.js.map +0 -1
- package/dist/usecases/script/action-span.d.ts +0 -10
- package/dist/usecases/script/action-span.js +0 -42
- package/dist/usecases/script/action-span.js.map +0 -1
- package/dist/usecases/script/actions.d.ts +0 -3
- package/dist/usecases/script/actions.js +0 -184
- package/dist/usecases/script/actions.js.map +0 -1
- package/dist/usecases/script/actor.d.ts +0 -3
- package/dist/usecases/script/actor.js +0 -26
- package/dist/usecases/script/actor.js.map +0 -1
- package/dist/usecases/script/actors.d.ts +0 -3
- package/dist/usecases/script/actors.js +0 -25
- package/dist/usecases/script/actors.js.map +0 -1
- package/dist/usecases/script/add-actor.d.ts +0 -3
- package/dist/usecases/script/add-actor.js +0 -13
- package/dist/usecases/script/add-actor.js.map +0 -1
- package/dist/usecases/script/add-episode.d.ts +0 -3
- package/dist/usecases/script/add-episode.js +0 -9
- package/dist/usecases/script/add-episode.js.map +0 -1
- package/dist/usecases/script/add-location.d.ts +0 -3
- package/dist/usecases/script/add-location.js +0 -11
- package/dist/usecases/script/add-location.js.map +0 -1
- package/dist/usecases/script/add-prop.d.ts +0 -3
- package/dist/usecases/script/add-prop.js +0 -11
- package/dist/usecases/script/add-prop.js.map +0 -1
- package/dist/usecases/script/alias.d.ts +0 -3
- package/dist/usecases/script/alias.js +0 -39
- package/dist/usecases/script/alias.js.map +0 -1
- package/dist/usecases/script/assets.d.ts +0 -3
- package/dist/usecases/script/assets.js +0 -46
- package/dist/usecases/script/assets.js.map +0 -1
- package/dist/usecases/script/audit-assets.d.ts +0 -4
- package/dist/usecases/script/audit-assets.js +0 -37
- package/dist/usecases/script/audit-assets.js.map +0 -1
- package/dist/usecases/script/command-constraints.d.ts +0 -38
- package/dist/usecases/script/command-constraints.js +0 -143
- package/dist/usecases/script/command-constraints.js.map +0 -1
- package/dist/usecases/script/compose-creative-draft.d.ts +0 -3
- package/dist/usecases/script/compose-creative-draft.js +0 -106
- package/dist/usecases/script/compose-creative-draft.js.map +0 -1
- package/dist/usecases/script/context.d.ts +0 -3
- package/dist/usecases/script/context.js +0 -52
- package/dist/usecases/script/context.js.map +0 -1
- package/dist/usecases/script/create.d.ts +0 -3
- package/dist/usecases/script/create.js +0 -27
- package/dist/usecases/script/create.js.map +0 -1
- package/dist/usecases/script/delete.d.ts +0 -3
- package/dist/usecases/script/delete.js +0 -88
- package/dist/usecases/script/delete.js.map +0 -1
- package/dist/usecases/script/describe.d.ts +0 -3
- package/dist/usecases/script/describe.js +0 -32
- package/dist/usecases/script/describe.js.map +0 -1
- package/dist/usecases/script/dialogue.d.ts +0 -3
- package/dist/usecases/script/dialogue.js +0 -30
- package/dist/usecases/script/dialogue.js.map +0 -1
- package/dist/usecases/script/dispatch.d.ts +0 -3
- package/dist/usecases/script/dispatch.js +0 -10
- package/dist/usecases/script/dispatch.js.map +0 -1
- package/dist/usecases/script/do.d.ts +0 -3
- package/dist/usecases/script/do.js +0 -186
- package/dist/usecases/script/do.js.map +0 -1
- package/dist/usecases/script/emotion.d.ts +0 -3
- package/dist/usecases/script/emotion.js +0 -24
- package/dist/usecases/script/emotion.js.map +0 -1
- package/dist/usecases/script/episodes.d.ts +0 -3
- package/dist/usecases/script/episodes.js +0 -62
- package/dist/usecases/script/episodes.js.map +0 -1
- package/dist/usecases/script/export-authoring.d.ts +0 -4
- package/dist/usecases/script/export-authoring.js +0 -326
- package/dist/usecases/script/export-authoring.js.map +0 -1
- package/dist/usecases/script/extend.d.ts +0 -3
- package/dist/usecases/script/extend.js +0 -94
- package/dist/usecases/script/extend.js.map +0 -1
- package/dist/usecases/script/ids.d.ts +0 -3
- package/dist/usecases/script/ids.js +0 -148
- package/dist/usecases/script/ids.js.map +0 -1
- package/dist/usecases/script/importance.d.ts +0 -3
- package/dist/usecases/script/importance.js +0 -16
- package/dist/usecases/script/importance.js.map +0 -1
- package/dist/usecases/script/insert.d.ts +0 -3
- package/dist/usecases/script/insert.js +0 -127
- package/dist/usecases/script/insert.js.map +0 -1
- package/dist/usecases/script/issues.d.ts +0 -3
- package/dist/usecases/script/issues.js +0 -35
- package/dist/usecases/script/issues.js.map +0 -1
- package/dist/usecases/script/lib.d.ts +0 -152
- package/dist/usecases/script/lib.js +0 -1654
- package/dist/usecases/script/lib.js.map +0 -1
- package/dist/usecases/script/locations.d.ts +0 -3
- package/dist/usecases/script/locations.js +0 -25
- package/dist/usecases/script/locations.js.map +0 -1
- package/dist/usecases/script/merge.d.ts +0 -3
- package/dist/usecases/script/merge.js +0 -43
- package/dist/usecases/script/merge.js.map +0 -1
- package/dist/usecases/script/migrate.d.ts +0 -3
- package/dist/usecases/script/migrate.js +0 -210
- package/dist/usecases/script/migrate.js.map +0 -1
- package/dist/usecases/script/move.d.ts +0 -3
- package/dist/usecases/script/move.js +0 -50
- package/dist/usecases/script/move.js.map +0 -1
- package/dist/usecases/script/parenthetical.d.ts +0 -3
- package/dist/usecases/script/parenthetical.js +0 -52
- package/dist/usecases/script/parenthetical.js.map +0 -1
- package/dist/usecases/script/props.d.ts +0 -3
- package/dist/usecases/script/props.js +0 -25
- package/dist/usecases/script/props.js.map +0 -1
- package/dist/usecases/script/refs.d.ts +0 -3
- package/dist/usecases/script/refs.js +0 -111
- package/dist/usecases/script/refs.js.map +0 -1
- package/dist/usecases/script/rename.d.ts +0 -3
- package/dist/usecases/script/rename.js +0 -35
- package/dist/usecases/script/rename.js.map +0 -1
- package/dist/usecases/script/replace.d.ts +0 -3
- package/dist/usecases/script/replace.js +0 -33
- package/dist/usecases/script/replace.js.map +0 -1
- package/dist/usecases/script/review.d.ts +0 -3
- package/dist/usecases/script/review.js +0 -187
- package/dist/usecases/script/review.js.map +0 -1
- package/dist/usecases/script/role.d.ts +0 -3
- package/dist/usecases/script/role.js +0 -16
- package/dist/usecases/script/role.js.map +0 -1
- package/dist/usecases/script/scenes.d.ts +0 -3
- package/dist/usecases/script/scenes.js +0 -66
- package/dist/usecases/script/scenes.js.map +0 -1
- package/dist/usecases/script/script-patch.d.ts +0 -3
- package/dist/usecases/script/script-patch.js +0 -321
- package/dist/usecases/script/script-patch.js.map +0 -1
- package/dist/usecases/script/script-validate.d.ts +0 -3
- package/dist/usecases/script/script-validate.js +0 -27
- package/dist/usecases/script/script-validate.js.map +0 -1
- package/dist/usecases/script/session.d.ts +0 -62
- package/dist/usecases/script/session.js +0 -567
- package/dist/usecases/script/session.js.map +0 -1
- package/dist/usecases/script/split.d.ts +0 -3
- package/dist/usecases/script/split.js +0 -41
- package/dist/usecases/script/split.js.map +0 -1
- package/dist/usecases/script/state-add.d.ts +0 -3
- package/dist/usecases/script/state-add.js +0 -22
- package/dist/usecases/script/state-add.js.map +0 -1
- package/dist/usecases/script/state-delete.d.ts +0 -3
- package/dist/usecases/script/state-delete.js +0 -22
- package/dist/usecases/script/state-delete.js.map +0 -1
- package/dist/usecases/script/state-rename.d.ts +0 -3
- package/dist/usecases/script/state-rename.js +0 -16
- package/dist/usecases/script/state-rename.js.map +0 -1
- package/dist/usecases/script/states.d.ts +0 -3
- package/dist/usecases/script/states.js +0 -197
- package/dist/usecases/script/states.js.map +0 -1
- package/dist/usecases/script/summary.d.ts +0 -3
- package/dist/usecases/script/summary.js +0 -72
- package/dist/usecases/script/summary.js.map +0 -1
- package/dist/usecases/script/synopsis-generate.d.ts +0 -115
- package/dist/usecases/script/synopsis-generate.js +0 -776
- package/dist/usecases/script/synopsis-generate.js.map +0 -1
- package/dist/usecases/script/synopsis.d.ts +0 -3
- package/dist/usecases/script/synopsis.js +0 -45
- package/dist/usecases/script/synopsis.js.map +0 -1
- package/dist/usecases/script/timestamp-filter.d.ts +0 -4
- package/dist/usecases/script/timestamp-filter.js +0 -55
- package/dist/usecases/script/timestamp-filter.js.map +0 -1
- package/dist/usecases/script/timestamp.d.ts +0 -3
- package/dist/usecases/script/timestamp.js +0 -11
- package/dist/usecases/script/timestamp.js.map +0 -1
- package/dist/usecases/script/transition.d.ts +0 -3
- package/dist/usecases/script/transition.js +0 -23
- package/dist/usecases/script/transition.js.map +0 -1
- package/dist/usecases/script/type.d.ts +0 -3
- package/dist/usecases/script/type.js +0 -23
- package/dist/usecases/script/type.js.map +0 -1
- package/dist/usecases/script/v3/mutations.d.ts +0 -2
- package/dist/usecases/script/v3/mutations.js +0 -5
- package/dist/usecases/script/v3/mutations.js.map +0 -1
- package/dist/usecases/script/v4/mutations.d.ts +0 -2
- package/dist/usecases/script/v4/mutations.js +0 -6
- package/dist/usecases/script/v4/mutations.js.map +0 -1
- package/dist/usecases/script/v4/queries.d.ts +0 -15
- package/dist/usecases/script/v4/queries.js +0 -196
- package/dist/usecases/script/v4/queries.js.map +0 -1
- package/dist/usecases/script/working-copy.d.ts +0 -5
- package/dist/usecases/script/working-copy.js +0 -399
- package/dist/usecases/script/working-copy.js.map +0 -1
- package/dist/usecases/script/worldview.d.ts +0 -3
- package/dist/usecases/script/worldview.js +0 -17
- package/dist/usecases/script/worldview.js.map +0 -1
- package/dist/usecases/script/write-authoring.d.ts +0 -3
- package/dist/usecases/script/write-authoring.js +0 -263
- package/dist/usecases/script/write-authoring.js.map +0 -1
- package/dist/usecases/update.d.ts +0 -13
- package/dist/usecases/update.js +0 -128
- package/dist/usecases/update.js.map +0 -1
|
@@ -1,1654 +0,0 @@
|
|
|
1
|
-
import { CliError, EXIT_INPUT, EXIT_OK, EXIT_USAGE, sha256Text, } from "../../common.js";
|
|
2
|
-
import { applyPatchOperationsV4 } from "../../domain/script/v4/patch/apply.js";
|
|
3
|
-
import { isV4Id } from "../../domain/script/v4/ids.js";
|
|
4
|
-
import { requireStructurallyReadableScriptV4 } from "../../domain/script/v4/parse.js";
|
|
5
|
-
import { validateScriptV4 } from "../../domain/script/v4/validation.js";
|
|
6
|
-
import { sceneRefs } from "../../domain/script/scene-refs.js";
|
|
7
|
-
import { isDangerousRegex, MAX_GREP_PATTERN_LEN, parseInSelector, selectorSingleActionPoint, WHOLE_SCRIPT, } from "../../domain/script/selector.js";
|
|
8
|
-
import { parseAnyAddress, } from "../../domain/script/address.js";
|
|
9
|
-
import { parseV4Address } from "../../domain/script/v4/address.js";
|
|
10
|
-
import { summarizeIssues } from "../../domain/script/text-util.js";
|
|
11
|
-
import { sortDeep } from "../../domain/script/text-util.js";
|
|
12
|
-
import { asList, idNum, isDict, strOf, } from "../../domain/script/shared.js";
|
|
13
|
-
import { loadScriptForEdit, validateSession, saveScriptSession, syncValidationResult, scriptSourceText, mutationValidationWarnings, } from "./session.js";
|
|
14
|
-
import { resolveActionTargetsV4 } from "./v4/queries.js";
|
|
15
|
-
import { actionTimestampFilter, actionTimestampMatches } from "./timestamp-filter.js";
|
|
16
|
-
import { applyVersionedMutations } from "./dispatch.js";
|
|
17
|
-
import { assertInsertCommandFlags, assertMoveCommandFlags, assertSceneRefCommandFlags, buildTimestampOperation, } from "./command-constraints.js";
|
|
18
|
-
export function tokenizeLine(line) {
|
|
19
|
-
const out = [];
|
|
20
|
-
let cur = "";
|
|
21
|
-
let started = false;
|
|
22
|
-
let quoted = false;
|
|
23
|
-
let inSingle = false;
|
|
24
|
-
let inDouble = false;
|
|
25
|
-
const flush = () => { if (started) {
|
|
26
|
-
out.push({ text: cur, quoted });
|
|
27
|
-
cur = "";
|
|
28
|
-
started = false;
|
|
29
|
-
quoted = false;
|
|
30
|
-
} };
|
|
31
|
-
for (let i = 0; i < line.length; i++) {
|
|
32
|
-
const ch = line[i];
|
|
33
|
-
if (inSingle) {
|
|
34
|
-
if (ch === "'")
|
|
35
|
-
inSingle = false;
|
|
36
|
-
else {
|
|
37
|
-
cur += ch;
|
|
38
|
-
quoted = true;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
else if (inDouble) {
|
|
42
|
-
if (ch === '"')
|
|
43
|
-
inDouble = false;
|
|
44
|
-
else if (ch === "\\" && i + 1 < line.length) {
|
|
45
|
-
cur += line[++i];
|
|
46
|
-
quoted = true;
|
|
47
|
-
}
|
|
48
|
-
else {
|
|
49
|
-
cur += ch;
|
|
50
|
-
quoted = true;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
else if (ch === "'") {
|
|
54
|
-
inSingle = true;
|
|
55
|
-
started = true;
|
|
56
|
-
}
|
|
57
|
-
else if (ch === '"') {
|
|
58
|
-
inDouble = true;
|
|
59
|
-
started = true;
|
|
60
|
-
}
|
|
61
|
-
else if (ch === "\\" && i + 1 < line.length) {
|
|
62
|
-
cur += line[++i];
|
|
63
|
-
started = true;
|
|
64
|
-
quoted = true;
|
|
65
|
-
}
|
|
66
|
-
else if (ch === " " || ch === "\t" || ch === "\r") {
|
|
67
|
-
flush();
|
|
68
|
-
}
|
|
69
|
-
else {
|
|
70
|
-
cur += ch;
|
|
71
|
-
started = true;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
flush();
|
|
75
|
-
return out;
|
|
76
|
-
}
|
|
77
|
-
// A token is a flag only if it was unquoted AND starts with `--`.
|
|
78
|
-
function isDoFlag(t) {
|
|
79
|
-
return !t.quoted && t.text.startsWith("--");
|
|
80
|
-
}
|
|
81
|
-
// Per-verb flag arity. Everything else takes the next token as its value.
|
|
82
|
-
export const DO_BOOL_FLAGS = {
|
|
83
|
-
replace: new Set(["all", "regex"]),
|
|
84
|
-
transition: new Set(["clear"]),
|
|
85
|
-
emotion: new Set(["clear"]),
|
|
86
|
-
parenthetical: new Set(["remove"]),
|
|
87
|
-
timestamp: new Set(["remove"]),
|
|
88
|
-
"scene-ref": new Set(["clear", "remove", "append"]),
|
|
89
|
-
delete: new Set(["force"]),
|
|
90
|
-
extend: new Set(["clear", "json-value"]),
|
|
91
|
-
};
|
|
92
|
-
export const DO_REPEAT_FLAGS = {
|
|
93
|
-
alias: new Set(["add", "remove"]),
|
|
94
|
-
"add-actor": new Set(["alias"]),
|
|
95
|
-
"scene-ref": new Set(["state"]),
|
|
96
|
-
insert: new Set(["state"]),
|
|
97
|
-
};
|
|
98
|
-
function pushFlag(flags, repeats, name, val) {
|
|
99
|
-
if (repeats.has(name)) {
|
|
100
|
-
const arr = flags[name] ?? [];
|
|
101
|
-
arr.push(val);
|
|
102
|
-
flags[name] = arr;
|
|
103
|
-
}
|
|
104
|
-
else {
|
|
105
|
-
flags[name] = val;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
export function parseDoLine(tokens) {
|
|
109
|
-
if (tokens.length === 0 || isDoFlag(tokens[0])) {
|
|
110
|
-
throw doErr("a line must start with a verb (not a flag)");
|
|
111
|
-
}
|
|
112
|
-
const verb = tokens[0].text;
|
|
113
|
-
const bools = DO_BOOL_FLAGS[verb] ?? new Set();
|
|
114
|
-
const repeats = DO_REPEAT_FLAGS[verb] ?? new Set();
|
|
115
|
-
const args = [];
|
|
116
|
-
const flags = {};
|
|
117
|
-
for (let i = 1; i < tokens.length; i++) {
|
|
118
|
-
const t = tokens[i];
|
|
119
|
-
if (isDoFlag(t)) {
|
|
120
|
-
let name = t.text.slice(2);
|
|
121
|
-
// Support `--flag=value` (a common CLI habit) alongside `--flag value`.
|
|
122
|
-
const eq = name.indexOf("=");
|
|
123
|
-
if (eq >= 0) {
|
|
124
|
-
const inlineVal = name.slice(eq + 1);
|
|
125
|
-
name = name.slice(0, eq);
|
|
126
|
-
if (!name)
|
|
127
|
-
throw doErr(`empty flag name in "${t.text}"`);
|
|
128
|
-
// A boolean flag written as `--all=false` must become false, not the
|
|
129
|
-
// truthy string "false" — `--force=false` especially must NOT force.
|
|
130
|
-
if (bools.has(name)) {
|
|
131
|
-
flags[name] = !["false", "0", "no", "off"].includes(inlineVal.toLowerCase());
|
|
132
|
-
}
|
|
133
|
-
else {
|
|
134
|
-
pushFlag(flags, repeats, name, inlineVal);
|
|
135
|
-
}
|
|
136
|
-
continue;
|
|
137
|
-
}
|
|
138
|
-
if (!name)
|
|
139
|
-
throw doErr(`empty flag name "${t.text}"`);
|
|
140
|
-
if (bools.has(name)) {
|
|
141
|
-
flags[name] = true;
|
|
142
|
-
continue;
|
|
143
|
-
}
|
|
144
|
-
// A value-taking flag must be followed by an actual value, not another
|
|
145
|
-
// unquoted `--flag` (or end-of-line) — otherwise `--to --from x` silently
|
|
146
|
-
// binds '--from' as --to's value. A quoted `"--x"` IS a valid value.
|
|
147
|
-
const next = tokens[i + 1];
|
|
148
|
-
if (next === undefined || isDoFlag(next)) {
|
|
149
|
-
throw doErr(`--${name} needs a value`);
|
|
150
|
-
}
|
|
151
|
-
pushFlag(flags, repeats, name, tokens[++i].text);
|
|
152
|
-
}
|
|
153
|
-
else {
|
|
154
|
-
args.push(t.text);
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
return { verb, args, flags };
|
|
158
|
-
}
|
|
159
|
-
export function doErr(detail) {
|
|
160
|
-
return new CliError(detail, {
|
|
161
|
-
exitCode: EXIT_USAGE,
|
|
162
|
-
errorCode: "DO_LINE_INVALID",
|
|
163
|
-
hint: "Each line is a scriptctl verb minus the leading `scriptctl`; see `scriptctl do --help`.",
|
|
164
|
-
data: { expected: ["a valid <verb> ...args... line"], actual: [detail] },
|
|
165
|
-
});
|
|
166
|
-
}
|
|
167
|
-
// ---- shared op-template builders ------------------------------------------
|
|
168
|
-
// One source of truth for the verbs whose op has validation/defaults, so the
|
|
169
|
-
// typed CLI handler and `do`'s lineToOp can never drift. Each returns the op
|
|
170
|
-
// WITHOUT `at` (the caller adds the single address or sweeps it over a selector)
|
|
171
|
-
// and throws the SAME CliError the handler used to throw inline.
|
|
172
|
-
export function stateChangeTemplate(target, f) {
|
|
173
|
-
const toSet = f.to !== undefined;
|
|
174
|
-
const clearSet = Boolean(f.clear);
|
|
175
|
-
if (toSet && clearSet) {
|
|
176
|
-
throw new CliError("state-change: --to and --clear are mutually exclusive.", {
|
|
177
|
-
exitCode: EXIT_USAGE,
|
|
178
|
-
errorCode: "STATE_CHANGE_FLAG_CONFLICT",
|
|
179
|
-
hint: "Pick one and retry.",
|
|
180
|
-
data: { expected: ["exactly one of --to <state> / --clear"], actual: ["--to", "--clear"] },
|
|
181
|
-
});
|
|
182
|
-
}
|
|
183
|
-
if (!toSet && !clearSet) {
|
|
184
|
-
throw new CliError("state-change: must specify --to <state> or --clear.", {
|
|
185
|
-
exitCode: EXIT_USAGE,
|
|
186
|
-
errorCode: "STATE_CHANGE_FLAG_MISSING",
|
|
187
|
-
hint: "Pick exactly one flag.",
|
|
188
|
-
data: { expected: ["one of --to <state> / --clear"], actual: ["<missing>"] },
|
|
189
|
-
});
|
|
190
|
-
}
|
|
191
|
-
// v3 has no per-action state_changes; state lives on scene.ref.* only.
|
|
192
|
-
throw new CliError("state-change was removed in v3; set a scene ref's state instead.", {
|
|
193
|
-
exitCode: EXIT_USAGE,
|
|
194
|
-
errorCode: "STATE_CHANGE_REMOVED",
|
|
195
|
-
hint: "Use `scene-ref <ep/scn> <kind:id> --state <state_id>` (op scene.ref.set).",
|
|
196
|
-
data: { expected: ["scene-ref state edit"], actual: ["state-change"] },
|
|
197
|
-
});
|
|
198
|
-
}
|
|
199
|
-
export function transitionTemplate(target, f) {
|
|
200
|
-
const setBoth = f.process !== undefined || f.contrast !== undefined;
|
|
201
|
-
const clearSet = Boolean(f.clear);
|
|
202
|
-
if (setBoth && clearSet) {
|
|
203
|
-
throw new CliError("transition: --clear is mutually exclusive with --process/--contrast.", {
|
|
204
|
-
exitCode: EXIT_USAGE,
|
|
205
|
-
errorCode: "TRANSITION_FLAG_CONFLICT",
|
|
206
|
-
hint: "Pick one mode and retry.",
|
|
207
|
-
data: { expected: ["either --clear, or --process + --contrast"], actual: ["--clear", "--process/--contrast"] },
|
|
208
|
-
});
|
|
209
|
-
}
|
|
210
|
-
if (!setBoth && !clearSet) {
|
|
211
|
-
throw new CliError("transition: must specify --process/--contrast or --clear.", {
|
|
212
|
-
exitCode: EXIT_USAGE,
|
|
213
|
-
errorCode: "TRANSITION_FLAG_MISSING",
|
|
214
|
-
hint: "Pick exactly one mode.",
|
|
215
|
-
data: { expected: ["--process + --contrast, or --clear"], actual: ["<missing>"] },
|
|
216
|
-
});
|
|
217
|
-
}
|
|
218
|
-
return clearSet
|
|
219
|
-
? { op: "action.transition.clear", target }
|
|
220
|
-
: { op: "action.transition.set", target, process: f.process, contrast: f.contrast };
|
|
221
|
-
}
|
|
222
|
-
export function emotionTemplate(f) {
|
|
223
|
-
const emotionSet = f.emotion !== undefined;
|
|
224
|
-
const clearSet = Boolean(f.clear);
|
|
225
|
-
if (emotionSet && clearSet) {
|
|
226
|
-
throw new CliError("emotion: value and --clear are mutually exclusive.", {
|
|
227
|
-
exitCode: EXIT_USAGE,
|
|
228
|
-
errorCode: "EMOTION_FLAG_CONFLICT",
|
|
229
|
-
hint: "Pick one mode and retry.",
|
|
230
|
-
data: { expected: ["either <emotion>, or --clear"], actual: ["<emotion>", "--clear"] },
|
|
231
|
-
});
|
|
232
|
-
}
|
|
233
|
-
if (!emotionSet && !clearSet) {
|
|
234
|
-
throw new CliError("emotion: must specify <emotion> or --clear.", {
|
|
235
|
-
exitCode: EXIT_USAGE,
|
|
236
|
-
errorCode: "EMOTION_VALUE_MISSING",
|
|
237
|
-
hint: "Pass an emotion label, or use --clear.",
|
|
238
|
-
data: { expected: ["<emotion>, or --clear"], actual: ["<missing>"] },
|
|
239
|
-
});
|
|
240
|
-
}
|
|
241
|
-
return clearSet
|
|
242
|
-
? { op: "action.emotion.clear" }
|
|
243
|
-
: { op: "action.emotion.set", emotion: f.emotion };
|
|
244
|
-
}
|
|
245
|
-
export function contextTemplate(target, f) {
|
|
246
|
-
const stateSet = f.state !== undefined;
|
|
247
|
-
const clearSet = Boolean(f.clear);
|
|
248
|
-
const removeSet = Boolean(f.remove);
|
|
249
|
-
const n = (stateSet ? 1 : 0) + (clearSet ? 1 : 0) + (removeSet ? 1 : 0);
|
|
250
|
-
if (n === 0) {
|
|
251
|
-
throw new CliError("context: must specify --state X, --clear, or --remove.", {
|
|
252
|
-
exitCode: EXIT_USAGE,
|
|
253
|
-
errorCode: "CONTEXT_FLAG_MISSING",
|
|
254
|
-
hint: "Pick exactly one flag.",
|
|
255
|
-
data: { expected: ["one of --state <state_id> / --clear / --remove"], actual: ["<missing>"] },
|
|
256
|
-
});
|
|
257
|
-
}
|
|
258
|
-
if (n > 1) {
|
|
259
|
-
const passed = [];
|
|
260
|
-
if (stateSet)
|
|
261
|
-
passed.push("--state");
|
|
262
|
-
if (clearSet)
|
|
263
|
-
passed.push("--clear");
|
|
264
|
-
if (removeSet)
|
|
265
|
-
passed.push("--remove");
|
|
266
|
-
throw new CliError("context: --state / --clear / --remove are mutually exclusive.", {
|
|
267
|
-
exitCode: EXIT_USAGE,
|
|
268
|
-
errorCode: "CONTEXT_FLAG_CONFLICT",
|
|
269
|
-
hint: "Pick one and retry.",
|
|
270
|
-
data: { expected: ["exactly one of --state / --clear / --remove"], actual: passed },
|
|
271
|
-
});
|
|
272
|
-
}
|
|
273
|
-
const append = Boolean(f.append);
|
|
274
|
-
const occurrenceRaw = strOf(f.occurrence).trim();
|
|
275
|
-
const occurrence = occurrenceRaw ? Number(occurrenceRaw) : undefined;
|
|
276
|
-
if (occurrence !== undefined && (!Number.isInteger(occurrence) || occurrence < 1)) {
|
|
277
|
-
throw new CliError("scene-ref: --occurrence must be a positive integer.", {
|
|
278
|
-
exitCode: EXIT_USAGE,
|
|
279
|
-
errorCode: "SCENE_REF_OCCURRENCE_INVALID",
|
|
280
|
-
hint: "Use 1 for the first matching scene ref, 2 for the second, and so on.",
|
|
281
|
-
data: { expected: ["--occurrence <positive integer> (1-based)"], actual: [occurrenceRaw] },
|
|
282
|
-
});
|
|
283
|
-
}
|
|
284
|
-
if (append && (!stateSet || occurrence !== undefined)) {
|
|
285
|
-
throw new CliError("scene-ref: --append requires --state and cannot be combined with --occurrence.", {
|
|
286
|
-
exitCode: EXIT_USAGE,
|
|
287
|
-
errorCode: "SCENE_REF_APPEND_FLAG_CONFLICT",
|
|
288
|
-
hint: "Append a new actor ref with --state <state_id> --append, or target an existing ref with --occurrence <n>.",
|
|
289
|
-
data: { expected: ["--state <state_id> --append"], actual: [append ? "--append" : "", occurrence !== undefined ? "--occurrence" : "", clearSet ? "--clear" : "", removeSet ? "--remove" : ""].filter(Boolean) },
|
|
290
|
-
});
|
|
291
|
-
}
|
|
292
|
-
if (removeSet)
|
|
293
|
-
return { op: "scene.ref.remove", target, occurrence };
|
|
294
|
-
if (clearSet)
|
|
295
|
-
return { op: "scene.ref.clear", target, occurrence };
|
|
296
|
-
return { op: "scene.ref.set", target, state: f.state === "none" ? "" : f.state, append, occurrence };
|
|
297
|
-
}
|
|
298
|
-
// v3 dialogue speaker: a single inline speaker — an actor, OR a non-actor kind
|
|
299
|
-
// (system|broadcast|offscreen|group) with an optional label.
|
|
300
|
-
export function dialogueTemplate(f) {
|
|
301
|
-
const actorId = strOf(f.actor).trim();
|
|
302
|
-
const speakerKind = strOf(f.kind).trim();
|
|
303
|
-
const label = strOf(f.label).trim();
|
|
304
|
-
if (actorId && speakerKind) {
|
|
305
|
-
throw new CliError("dialogue: --actor and --kind are mutually exclusive.", {
|
|
306
|
-
exitCode: EXIT_USAGE,
|
|
307
|
-
errorCode: "SPEAKER_AMBIGUOUS",
|
|
308
|
-
hint: "Keep --actor for a character, or --kind for a non-actor source.",
|
|
309
|
-
data: { expected: ["exactly one of --actor <actor_id> or --kind <non-actor kind>"], actual: ["--actor", "--kind"] },
|
|
310
|
-
});
|
|
311
|
-
}
|
|
312
|
-
if (actorId && label) {
|
|
313
|
-
throw new CliError("dialogue: --label is only valid with --kind.", {
|
|
314
|
-
exitCode: EXIT_USAGE,
|
|
315
|
-
errorCode: "SPEAKER_LABEL_WITHOUT_KIND",
|
|
316
|
-
hint: "Remove --label for an actor line, or use --kind for a labeled non-actor source.",
|
|
317
|
-
data: { expected: ["omit --label with --actor, or pair --label with --kind"], actual: ["--actor", "--label"] },
|
|
318
|
-
});
|
|
319
|
-
}
|
|
320
|
-
if (actorId)
|
|
321
|
-
return { op: "dialogue.speaker.set", actor_id: actorId };
|
|
322
|
-
if (speakerKind)
|
|
323
|
-
return { op: "dialogue.speaker.set", kind: speakerKind, label: label || undefined };
|
|
324
|
-
throw new CliError("dialogue: pass --actor <id> or --kind <system|broadcast|offscreen|group>.", {
|
|
325
|
-
exitCode: EXIT_USAGE,
|
|
326
|
-
errorCode: "DIALOGUE_SPEAKER_MISSING",
|
|
327
|
-
hint: "Set --actor for an actor line, or --kind for a non-actor line.",
|
|
328
|
-
data: { expected: ["--actor <actor_id> or --kind <non-actor kind>"], actual: ["<missing>"] },
|
|
329
|
-
});
|
|
330
|
-
}
|
|
331
|
-
// Translate one parsed verb line into a patch op dict (the SAME ops `patch`
|
|
332
|
-
// consumes). `do` = the human/agent-friendly notation for those ops: no JSON,
|
|
333
|
-
// no field-name guessing — the verbs you already type. Multipolar verbs
|
|
334
|
-
// (delete/move/insert/merge/describe) pick their op by the address kind.
|
|
335
|
-
function repeatedDoFlag(raw) {
|
|
336
|
-
if (raw === undefined)
|
|
337
|
-
return [];
|
|
338
|
-
return Array.isArray(raw) ? raw.map(strOf) : [strOf(raw)];
|
|
339
|
-
}
|
|
340
|
-
function doInsertFlags(flags) {
|
|
341
|
-
return {
|
|
342
|
-
type: flags["type"],
|
|
343
|
-
content: flags["content"],
|
|
344
|
-
emotion: flags["emotion"],
|
|
345
|
-
parenthetical: flags["parenthetical"],
|
|
346
|
-
actionId: flags["action-id"],
|
|
347
|
-
at: flags["at"],
|
|
348
|
-
before: flags["before"],
|
|
349
|
-
after: flags["after"],
|
|
350
|
-
actor: flags["actor"],
|
|
351
|
-
speaker: flags["speaker"],
|
|
352
|
-
speakerState: flags["speaker-state"],
|
|
353
|
-
kind: flags["kind"],
|
|
354
|
-
label: flags["label"],
|
|
355
|
-
location: flags["location"],
|
|
356
|
-
time: flags["time"],
|
|
357
|
-
space: flags["space"],
|
|
358
|
-
sceneId: flags["scene-id"],
|
|
359
|
-
states: repeatedDoFlag(flags["state"]),
|
|
360
|
-
};
|
|
361
|
-
}
|
|
362
|
-
export function lineToOp(verb, args, flags, scriptVersion = 3) {
|
|
363
|
-
const a0 = strOf(args[0]);
|
|
364
|
-
const a1 = strOf(args[1]);
|
|
365
|
-
const parseAddress = (raw) => scriptVersion === 4 ? parseV4Address(raw) : parseAnyAddress(raw);
|
|
366
|
-
switch (verb) {
|
|
367
|
-
case "replace":
|
|
368
|
-
return flags["regex"]
|
|
369
|
-
? { op: "action.content.regex-replace", at: a0, pattern: regexPattern(strOf(flags["from"])), to: flags["to"] ?? "", all: Boolean(flags["all"]) }
|
|
370
|
-
: { op: "action.content.replace", at: a0, from: strOf(flags["from"]), to: flags["to"] ?? "", all: Boolean(flags["all"]) };
|
|
371
|
-
case "type":
|
|
372
|
-
return { op: "action.type.set", at: a0, type: a1 };
|
|
373
|
-
case "actor":
|
|
374
|
-
return { op: "action.actor.set", at: a0, actor_id: a1 };
|
|
375
|
-
case "transition":
|
|
376
|
-
return { ...transitionTemplate(a1, { process: flags["process"], contrast: flags["contrast"], clear: Boolean(flags["clear"]) }), at: a0 };
|
|
377
|
-
case "emotion":
|
|
378
|
-
if (scriptVersion === 4)
|
|
379
|
-
throw doErr("emotion belongs to Script v3; use parenthetical for Script v4");
|
|
380
|
-
return { ...emotionTemplate({ emotion: args[1], clear: Boolean(flags["clear"]) }), at: a0 };
|
|
381
|
-
case "parenthetical":
|
|
382
|
-
if (scriptVersion === 3)
|
|
383
|
-
throw doErr("parenthetical belongs to Script v4; use emotion for Script v3");
|
|
384
|
-
if (Boolean(flags["remove"]) === (flags["set"] !== undefined)) {
|
|
385
|
-
throw doErr("parenthetical needs exactly one of --set <text> or --remove");
|
|
386
|
-
}
|
|
387
|
-
return Boolean(flags["remove"])
|
|
388
|
-
? { op: "action.parenthetical.remove", at: a0 }
|
|
389
|
-
: { op: "action.parenthetical.set", at: a0, parenthetical: strOf(flags["set"]) };
|
|
390
|
-
case "timestamp":
|
|
391
|
-
return buildTimestampOperation(a0, flags["set"], Boolean(flags["remove"]));
|
|
392
|
-
case "scene-ref": {
|
|
393
|
-
const sceneRefFlags = {
|
|
394
|
-
states: repeatedDoFlag(flags["state"]),
|
|
395
|
-
clear: Boolean(flags["clear"]),
|
|
396
|
-
remove: Boolean(flags["remove"]),
|
|
397
|
-
append: Boolean(flags["append"]),
|
|
398
|
-
occurrence: flags["occurrence"],
|
|
399
|
-
};
|
|
400
|
-
assertSceneRefCommandFlags(scriptVersion, sceneRefFlags);
|
|
401
|
-
if (scriptVersion === 4) {
|
|
402
|
-
return sceneRefFlags.remove
|
|
403
|
-
? { op: "scene.ref.remove", at: a0, target: a1 }
|
|
404
|
-
: { op: "scene.ref.set", at: a0, target: a1, state_ids: sceneRefFlags.states };
|
|
405
|
-
}
|
|
406
|
-
return {
|
|
407
|
-
...contextTemplate(a1, {
|
|
408
|
-
state: sceneRefFlags.states[0],
|
|
409
|
-
clear: sceneRefFlags.clear,
|
|
410
|
-
remove: sceneRefFlags.remove,
|
|
411
|
-
append: sceneRefFlags.append,
|
|
412
|
-
occurrence: sceneRefFlags.occurrence,
|
|
413
|
-
}),
|
|
414
|
-
at: a0,
|
|
415
|
-
};
|
|
416
|
-
}
|
|
417
|
-
case "dialogue":
|
|
418
|
-
if (scriptVersion === 3 && flags["state"] !== undefined) {
|
|
419
|
-
throw doErr("dialogue --state belongs to Script v4");
|
|
420
|
-
}
|
|
421
|
-
return {
|
|
422
|
-
...dialogueTemplate({ actor: flags["actor"], kind: flags["kind"], label: flags["label"] }),
|
|
423
|
-
...(scriptVersion === 4 && flags["state"] !== undefined ? { state_id: flags["state"] } : {}),
|
|
424
|
-
at: a0,
|
|
425
|
-
};
|
|
426
|
-
case "rename":
|
|
427
|
-
return { op: "asset.rename", target: a0, name: a1 };
|
|
428
|
-
case "role":
|
|
429
|
-
return { op: "asset.role.set", target: a0, role_type: a1 };
|
|
430
|
-
case "worldview":
|
|
431
|
-
return { op: "meta.worldview.set", worldview: a0 };
|
|
432
|
-
case "synopsis": {
|
|
433
|
-
if (args.length === 0)
|
|
434
|
-
throw doErr("synopsis needs <text> or <episode_id> <text>");
|
|
435
|
-
if (args.length > 2)
|
|
436
|
-
throw doErr("synopsis text with spaces must be quoted");
|
|
437
|
-
if (args.length === 1) {
|
|
438
|
-
if (/^ep_/.test(a0) || /^ep[1-9A-HJ-NP-Za-km-z]{6}$/.test(a0)) {
|
|
439
|
-
throw doErr(`synopsis for ${a0} needs text`);
|
|
440
|
-
}
|
|
441
|
-
return { op: "meta.synopsis.set", synopsis: a0 };
|
|
442
|
-
}
|
|
443
|
-
const addr = parseAddress(a0);
|
|
444
|
-
if (addr.kind !== "episode")
|
|
445
|
-
throw doErr(`synopsis target must be an episode id or omitted for global (${a0})`);
|
|
446
|
-
return { op: "episode.synopsis.set", episode_id: "id" in addr ? addr.id : addr.episodeId, synopsis: a1 };
|
|
447
|
-
}
|
|
448
|
-
case "alias": {
|
|
449
|
-
const add = flags["add"] ?? [];
|
|
450
|
-
const remove = flags["remove"] ?? [];
|
|
451
|
-
if (add.length)
|
|
452
|
-
return { op: "asset.alias.add", target: a0, alias: add };
|
|
453
|
-
if (remove.length)
|
|
454
|
-
return { op: "asset.alias.remove", target: a0, alias: remove };
|
|
455
|
-
throw doErr("alias needs --add <alias> or --remove <alias>");
|
|
456
|
-
}
|
|
457
|
-
case "describe": {
|
|
458
|
-
const addr = parseAddress(a0);
|
|
459
|
-
if (addr.kind === "state")
|
|
460
|
-
return { op: "state.describe", target: a0, description: a1 };
|
|
461
|
-
if (addr.kind === "asset")
|
|
462
|
-
return { op: "asset.describe", target: a0, description: a1 };
|
|
463
|
-
throw doErr(`describe cannot operate on a ${addr.kind} address (${a0}); use an asset or asset/state target`);
|
|
464
|
-
}
|
|
465
|
-
case "extend": {
|
|
466
|
-
if (a0 !== "global")
|
|
467
|
-
parseAddress(a0);
|
|
468
|
-
if (flags["clear"]) {
|
|
469
|
-
if (args.length >= 3)
|
|
470
|
-
throw doErr("extend --clear takes no value (drop --clear to set, or drop the value to delete)");
|
|
471
|
-
return { op: "extend.clear", at: a0, key: a1 || undefined };
|
|
472
|
-
}
|
|
473
|
-
if (args.length < 3)
|
|
474
|
-
throw doErr("extend needs <addr> <key> <value> (or --clear)");
|
|
475
|
-
let value = args[2];
|
|
476
|
-
if (flags["json-value"]) {
|
|
477
|
-
try {
|
|
478
|
-
value = JSON.parse(strOf(args[2]));
|
|
479
|
-
}
|
|
480
|
-
catch {
|
|
481
|
-
throw doErr("extend --json-value: value is not valid JSON");
|
|
482
|
-
}
|
|
483
|
-
}
|
|
484
|
-
return { op: "extend.set", at: a0, key: a1, value };
|
|
485
|
-
}
|
|
486
|
-
case "state-add":
|
|
487
|
-
return { op: "state.add", target: a0, name: a1, description: flags["description"], state_id: flags["state-id"] };
|
|
488
|
-
case "state-rename":
|
|
489
|
-
return { op: "state.rename", target: a0, name: a1 };
|
|
490
|
-
case "state-delete":
|
|
491
|
-
return { op: "state.delete", target: a0, strategy: flags["strategy"], replacement: flags["replacement"] };
|
|
492
|
-
case "add-actor":
|
|
493
|
-
return { op: "actor.add", actor_id: flags["id"], name: a0, role_type: flags["role"], description: flags["description"], aliases: flags["alias"] ?? undefined };
|
|
494
|
-
case "add-location":
|
|
495
|
-
return { op: "location.add", location_id: flags["id"], name: a0, description: flags["description"] };
|
|
496
|
-
case "add-prop":
|
|
497
|
-
return { op: "prop.add", prop_id: flags["id"], name: a0, description: flags["description"] };
|
|
498
|
-
case "add-episode":
|
|
499
|
-
return { op: "episode.add", title: flags["title"], episode_id: flags["id"] };
|
|
500
|
-
case "importance":
|
|
501
|
-
return { op: "importance.set", target: a0, importance: a1 };
|
|
502
|
-
case "split":
|
|
503
|
-
return scriptVersion === 4
|
|
504
|
-
? { op: "scene.split", at: a0, at_action: flags["at"], new_scene_id: flags["new-scene-id"] }
|
|
505
|
-
: { op: "scene.split", at: a0, at_index: Number(flags["at"]), new_scene_id: flags["new-scene-id"] };
|
|
506
|
-
case "delete": {
|
|
507
|
-
const addr = parseAddress(a0);
|
|
508
|
-
if (addr.kind === "action")
|
|
509
|
-
return { op: "action.delete", at: a0 };
|
|
510
|
-
if (addr.kind === "scene")
|
|
511
|
-
return { op: "scene.delete", at: a0, force: Boolean(flags["force"]) };
|
|
512
|
-
if (addr.kind === "state")
|
|
513
|
-
return { op: "state.delete", target: a0, strategy: flags["strategy"], replacement: flags["replacement"] };
|
|
514
|
-
if (addr.kind === "asset")
|
|
515
|
-
return { op: "asset.delete", target: a0, strategy: flags["strategy"], replacement: flags["replacement"] };
|
|
516
|
-
throw doErr(`delete cannot operate on a ${addr.kind} address (${a0})`);
|
|
517
|
-
}
|
|
518
|
-
case "move": {
|
|
519
|
-
assertMoveCommandFlags(scriptVersion, {
|
|
520
|
-
at: flags["at"],
|
|
521
|
-
before: flags["before"],
|
|
522
|
-
after: flags["after"],
|
|
523
|
-
});
|
|
524
|
-
const addr = parseAddress(a0);
|
|
525
|
-
if (addr.kind === "scene") {
|
|
526
|
-
return scriptVersion === 4
|
|
527
|
-
? { op: "scene.move", at: a0, to: a1, before: flags["before"], after: flags["after"] }
|
|
528
|
-
: { op: "scene.move", at: a0, to: a1, at_index: flags["at"] };
|
|
529
|
-
}
|
|
530
|
-
if (addr.kind === "action") {
|
|
531
|
-
return scriptVersion === 4
|
|
532
|
-
? { op: "action.move", at: a0, to: a1, before: flags["before"], after: flags["after"] }
|
|
533
|
-
: { op: "action.move", at: a0, to: a1 };
|
|
534
|
-
}
|
|
535
|
-
throw doErr(`move cannot operate on a ${addr.kind} address (${a0}); move an action or a scene`);
|
|
536
|
-
}
|
|
537
|
-
case "merge": {
|
|
538
|
-
const addr = parseAddress(a0);
|
|
539
|
-
if (addr.kind === "scene")
|
|
540
|
-
return { op: "scene.merge", from: a0, into: strOf(flags["into"]) };
|
|
541
|
-
if (addr.kind === "asset")
|
|
542
|
-
return { op: "asset.merge", from: a0, into: strOf(flags["into"]) };
|
|
543
|
-
throw doErr(`merge cannot operate on a ${addr.kind} address (${a0}); merge two assets or two scenes`);
|
|
544
|
-
}
|
|
545
|
-
case "insert": {
|
|
546
|
-
const addr = parseAddress(a0);
|
|
547
|
-
const insertFlags = doInsertFlags(flags);
|
|
548
|
-
if (addr.kind === "episode") {
|
|
549
|
-
assertInsertCommandFlags(scriptVersion, "scene", insertFlags);
|
|
550
|
-
return {
|
|
551
|
-
op: "scene.insert",
|
|
552
|
-
at: a0,
|
|
553
|
-
location: flags["location"],
|
|
554
|
-
time: flags["time"],
|
|
555
|
-
space: flags["space"],
|
|
556
|
-
...(scriptVersion === 4
|
|
557
|
-
? { location_state_ids: insertFlags.states, before: flags["before"], after: flags["after"] }
|
|
558
|
-
: { at_index: flags["at"], before: flags["before"], after: flags["after"] }),
|
|
559
|
-
scene_id: flags["scene-id"],
|
|
560
|
-
};
|
|
561
|
-
}
|
|
562
|
-
if (addr.kind === "scene") {
|
|
563
|
-
assertInsertCommandFlags(scriptVersion, "action", insertFlags);
|
|
564
|
-
return {
|
|
565
|
-
op: "action.insert",
|
|
566
|
-
at: a0,
|
|
567
|
-
type: flags["type"],
|
|
568
|
-
content: flags["content"],
|
|
569
|
-
before: flags["before"],
|
|
570
|
-
after: flags["after"],
|
|
571
|
-
actor_id: flags["actor"],
|
|
572
|
-
kind: flags["kind"],
|
|
573
|
-
label: flags["label"],
|
|
574
|
-
...(scriptVersion === 4
|
|
575
|
-
? {
|
|
576
|
-
action_id: flags["action-id"],
|
|
577
|
-
state_id: flags["speaker-state"],
|
|
578
|
-
parenthetical: flags["parenthetical"],
|
|
579
|
-
}
|
|
580
|
-
: {
|
|
581
|
-
at_index: flags["at"],
|
|
582
|
-
speaker_id: flags["speaker"],
|
|
583
|
-
emotion: flags["emotion"],
|
|
584
|
-
}),
|
|
585
|
-
};
|
|
586
|
-
}
|
|
587
|
-
throw doErr(`insert needs ep_NNN (scene insert) or ep_NNN/scn_NNN (action insert), got a ${addr.kind} address (${a0})`);
|
|
588
|
-
}
|
|
589
|
-
default:
|
|
590
|
-
throw doErr(`unknown verb '${verb}' (structural/edit/create verbs are supported; queries are not)`);
|
|
591
|
-
}
|
|
592
|
-
}
|
|
593
|
-
export function actionAddress(epId, sceneId, idx) {
|
|
594
|
-
return `${epId}/${sceneId}#${idx}`;
|
|
595
|
-
}
|
|
596
|
-
// The action's authored timeline position, carried in extend.timestamp as a
|
|
597
|
-
// "M:SS" / "MM:SS" string (episode-local by convention). Empty string when the
|
|
598
|
-
// action carries no timestamp. This is the anchor event-level alignment reads:
|
|
599
|
-
// an event's span is the delta between its first and last action timestamp.
|
|
600
|
-
export function actionTimestamp(action) {
|
|
601
|
-
const extend = isDict(action["extend"]) ? action["extend"] : {};
|
|
602
|
-
return strOf(extend["timestamp"]).trim();
|
|
603
|
-
}
|
|
604
|
-
// First and last non-empty action timestamps within a scene, in document order.
|
|
605
|
-
// Timestamps are monotonic within an episode, so first = t_start, last = t_end.
|
|
606
|
-
export function sceneTimeSpan(scene) {
|
|
607
|
-
let t_start = "";
|
|
608
|
-
let t_end = "";
|
|
609
|
-
for (const action of asList(scene["actions"])) {
|
|
610
|
-
const ts = actionTimestamp(action);
|
|
611
|
-
if (!ts)
|
|
612
|
-
continue;
|
|
613
|
-
if (!t_start)
|
|
614
|
-
t_start = ts;
|
|
615
|
-
t_end = ts;
|
|
616
|
-
}
|
|
617
|
-
return { t_start, t_end };
|
|
618
|
-
}
|
|
619
|
-
export function actionDisplayFields(epId, sceneId, idx, action) {
|
|
620
|
-
const actorId = actionActorId(action);
|
|
621
|
-
const s = isDict(action["speaker"]) ? action["speaker"] : null;
|
|
622
|
-
// For a non-actor speaker ({kind,label}) surface it under `speaker`; an actor
|
|
623
|
-
// line surfaces under `actor` (its id). Narrative lines have neither.
|
|
624
|
-
const speaker = s && !actorId ? (strOf(s["label"]).trim() || strOf(s["kind"]).trim()) : "";
|
|
625
|
-
return {
|
|
626
|
-
addr: actionAddress(epId, sceneId, idx),
|
|
627
|
-
timestamp: actionTimestamp(action),
|
|
628
|
-
type: strOf(action["type"]).trim() || "action",
|
|
629
|
-
speaker,
|
|
630
|
-
actor: actorId,
|
|
631
|
-
emotion: strOf(action["emotion"]).trim(),
|
|
632
|
-
content: strOf(action["content"]),
|
|
633
|
-
};
|
|
634
|
-
}
|
|
635
|
-
export function formatInspectAction(epId, sceneId, idx, action) {
|
|
636
|
-
const fields = actionDisplayFields(epId, sceneId, idx, action);
|
|
637
|
-
const addr = strOf(fields["addr"]);
|
|
638
|
-
const type = strOf(fields["type"]);
|
|
639
|
-
const delivery = strOf(fields["delivery"]);
|
|
640
|
-
const tag = delivery ? `${type} ${delivery}` : type;
|
|
641
|
-
// Prefer the speaker_id (concrete) over actor_id (asset), and skip both when
|
|
642
|
-
// the action is narrative (no speaker). Format kept on a single line so agents
|
|
643
|
-
// can grep the output.
|
|
644
|
-
const speakerId = strOf(fields["speaker"]);
|
|
645
|
-
const actorId = strOf(fields["actor"]);
|
|
646
|
-
const who = speakerId || actorId;
|
|
647
|
-
const emotion = strOf(fields["emotion"]);
|
|
648
|
-
const timestamp = strOf(fields["timestamp"]);
|
|
649
|
-
const content = strOf(fields["content"]);
|
|
650
|
-
const meta = [tag, timestamp ? `t=${timestamp}` : "", emotion ? `emotion=${emotion}` : "", who].filter((v) => v).join(" ");
|
|
651
|
-
const prefix = `${addr} [${meta}]`;
|
|
652
|
-
return content ? `${prefix} ${content}` : prefix;
|
|
653
|
-
}
|
|
654
|
-
// ---------------------------------------------------------------------------
|
|
655
|
-
// command_script_patch
|
|
656
|
-
// ---------------------------------------------------------------------------
|
|
657
|
-
export const SKIPPABLE_EDIT_CODES = new Set([
|
|
658
|
-
"REGEX_NO_MATCH",
|
|
659
|
-
"FROM_TEXT_NOT_FOUND",
|
|
660
|
-
"OVERLAP_DIALOGUE_UNSUPPORTED",
|
|
661
|
-
]);
|
|
662
|
-
export function applyPatchOperationsForSession(session, source, operations) {
|
|
663
|
-
return applyVersionedMutations(session.version, session.script, source, operations);
|
|
664
|
-
}
|
|
665
|
-
function v4Counts(script) {
|
|
666
|
-
return {
|
|
667
|
-
episodes: script.episodes.length,
|
|
668
|
-
scenes: script.episodes.reduce((sum, episode) => sum + episode.scenes.length, 0),
|
|
669
|
-
actions: script.episodes.reduce((sum, episode) => sum + episode.scenes.reduce((sceneSum, scene) => sceneSum + scene.actions.length, 0), 0),
|
|
670
|
-
actors: script.actors.length,
|
|
671
|
-
locations: script.locations.length,
|
|
672
|
-
props: script.props.length,
|
|
673
|
-
states: [...script.actors, ...script.locations, ...script.props]
|
|
674
|
-
.reduce((sum, asset) => sum + asset.states.length, 0),
|
|
675
|
-
};
|
|
676
|
-
}
|
|
677
|
-
function v4CanonicalIds(script) {
|
|
678
|
-
return [
|
|
679
|
-
...script.actors.flatMap((asset) => [
|
|
680
|
-
asset.actor_id,
|
|
681
|
-
...asset.states.map((state) => `${asset.actor_id}/${state.state_id}`),
|
|
682
|
-
]),
|
|
683
|
-
...script.locations.flatMap((asset) => [
|
|
684
|
-
asset.location_id,
|
|
685
|
-
...asset.states.map((state) => `${asset.location_id}/${state.state_id}`),
|
|
686
|
-
]),
|
|
687
|
-
...script.props.flatMap((asset) => [
|
|
688
|
-
asset.prop_id,
|
|
689
|
-
...asset.states.map((state) => `${asset.prop_id}/${state.state_id}`),
|
|
690
|
-
]),
|
|
691
|
-
...script.episodes.flatMap((episode) => [
|
|
692
|
-
episode.episode_id,
|
|
693
|
-
...episode.scenes.flatMap((scene) => [
|
|
694
|
-
scene.scene_id,
|
|
695
|
-
...scene.actions.map((action) => action.action_id),
|
|
696
|
-
]),
|
|
697
|
-
]),
|
|
698
|
-
];
|
|
699
|
-
}
|
|
700
|
-
function orderedIntersection(left, right) {
|
|
701
|
-
return left.filter((value) => right.has(value));
|
|
702
|
-
}
|
|
703
|
-
function v4OperationTargets(operation) {
|
|
704
|
-
const values = [];
|
|
705
|
-
const isIdentity = (value) => {
|
|
706
|
-
if (value === "global")
|
|
707
|
-
return true;
|
|
708
|
-
if (isV4Id("episode", value)
|
|
709
|
-
|| isV4Id("scene", value)
|
|
710
|
-
|| isV4Id("action", value)
|
|
711
|
-
|| isV4Id("actor", value)
|
|
712
|
-
|| isV4Id("location", value)
|
|
713
|
-
|| isV4Id("prop", value))
|
|
714
|
-
return true;
|
|
715
|
-
const slash = value.indexOf("/");
|
|
716
|
-
if (slash < 0 || slash !== value.lastIndexOf("/"))
|
|
717
|
-
return false;
|
|
718
|
-
const owner = value.slice(0, slash);
|
|
719
|
-
const state = value.slice(slash + 1);
|
|
720
|
-
return (isV4Id("actor", owner)
|
|
721
|
-
|| isV4Id("location", owner)
|
|
722
|
-
|| isV4Id("prop", owner)) && (state === "default" || isV4Id("state", state));
|
|
723
|
-
};
|
|
724
|
-
const add = (value) => {
|
|
725
|
-
if (typeof value !== "string" || value.trim() === "")
|
|
726
|
-
return;
|
|
727
|
-
const normalized = value.trim();
|
|
728
|
-
if (isIdentity(normalized))
|
|
729
|
-
values.push(normalized);
|
|
730
|
-
};
|
|
731
|
-
const first = (...fields) => {
|
|
732
|
-
for (const field of fields) {
|
|
733
|
-
const value = operation[field];
|
|
734
|
-
if (typeof value === "string" && value.trim() !== "")
|
|
735
|
-
return value;
|
|
736
|
-
}
|
|
737
|
-
return undefined;
|
|
738
|
-
};
|
|
739
|
-
const addState = (ownerValue, stateValue) => {
|
|
740
|
-
const owner = strOf(ownerValue).trim();
|
|
741
|
-
const state = strOf(stateValue).trim();
|
|
742
|
-
if (owner && state)
|
|
743
|
-
add(`${owner}/${state}`);
|
|
744
|
-
};
|
|
745
|
-
const addStates = (ownerValue, stateValues) => {
|
|
746
|
-
if (!Array.isArray(stateValues))
|
|
747
|
-
return;
|
|
748
|
-
stateValues.forEach((state) => addState(ownerValue, state));
|
|
749
|
-
};
|
|
750
|
-
const addPlacement = () => {
|
|
751
|
-
add(operation["before"]);
|
|
752
|
-
add(operation["after"]);
|
|
753
|
-
};
|
|
754
|
-
const kind = strOf(operation["op"]);
|
|
755
|
-
switch (kind) {
|
|
756
|
-
case "action.parenthetical.set":
|
|
757
|
-
case "action.parenthetical.remove":
|
|
758
|
-
case "action.timestamp.set":
|
|
759
|
-
case "action.timestamp.remove":
|
|
760
|
-
case "action.content.replace":
|
|
761
|
-
case "action.content.regex-replace":
|
|
762
|
-
case "action.type.set":
|
|
763
|
-
case "action.delete":
|
|
764
|
-
case "action.transition.clear":
|
|
765
|
-
add(operation["at"]);
|
|
766
|
-
break;
|
|
767
|
-
case "action.actor.set":
|
|
768
|
-
case "dialogue.speaker.set":
|
|
769
|
-
add(operation["at"]);
|
|
770
|
-
add(operation["actor_id"]);
|
|
771
|
-
addState(operation["actor_id"], operation["state_id"]);
|
|
772
|
-
break;
|
|
773
|
-
case "action.insert":
|
|
774
|
-
add(operation["at"]);
|
|
775
|
-
add(first("action_id", "id"));
|
|
776
|
-
add(operation["actor_id"]);
|
|
777
|
-
addState(operation["actor_id"], operation["state_id"]);
|
|
778
|
-
addPlacement();
|
|
779
|
-
break;
|
|
780
|
-
case "action.move":
|
|
781
|
-
add(operation["at"]);
|
|
782
|
-
add(operation["to"]);
|
|
783
|
-
addPlacement();
|
|
784
|
-
break;
|
|
785
|
-
case "action.transition.set":
|
|
786
|
-
add(operation["at"]);
|
|
787
|
-
add(operation["target"]);
|
|
788
|
-
break;
|
|
789
|
-
case "scene.ref.set":
|
|
790
|
-
case "scene.ref.remove":
|
|
791
|
-
add(operation["at"]);
|
|
792
|
-
add(operation["target"]);
|
|
793
|
-
addStates(operation["target"], operation["state_ids"]);
|
|
794
|
-
break;
|
|
795
|
-
case "actor.add":
|
|
796
|
-
add(first("actor_id", "id"));
|
|
797
|
-
break;
|
|
798
|
-
case "location.add":
|
|
799
|
-
add(first("location_id", "id"));
|
|
800
|
-
break;
|
|
801
|
-
case "prop.add":
|
|
802
|
-
add(first("prop_id", "id"));
|
|
803
|
-
break;
|
|
804
|
-
case "state.add": {
|
|
805
|
-
const owner = operation["target"];
|
|
806
|
-
add(owner);
|
|
807
|
-
addState(owner, first("state_id", "id"));
|
|
808
|
-
break;
|
|
809
|
-
}
|
|
810
|
-
case "state.rename":
|
|
811
|
-
case "state.describe":
|
|
812
|
-
add(operation["target"]);
|
|
813
|
-
break;
|
|
814
|
-
case "state.delete": {
|
|
815
|
-
const target = strOf(operation["target"]).trim();
|
|
816
|
-
add(target);
|
|
817
|
-
const slash = target.indexOf("/");
|
|
818
|
-
if (slash > 0)
|
|
819
|
-
addState(target.slice(0, slash), operation["replacement"]);
|
|
820
|
-
break;
|
|
821
|
-
}
|
|
822
|
-
case "asset.rename":
|
|
823
|
-
case "asset.describe":
|
|
824
|
-
case "asset.role.set":
|
|
825
|
-
case "asset.alias.set":
|
|
826
|
-
case "asset.alias.add":
|
|
827
|
-
case "asset.alias.remove":
|
|
828
|
-
case "importance.set":
|
|
829
|
-
add(operation["target"]);
|
|
830
|
-
break;
|
|
831
|
-
case "asset.merge":
|
|
832
|
-
add(first("from", "source"));
|
|
833
|
-
add(first("into", "target"));
|
|
834
|
-
break;
|
|
835
|
-
case "asset.delete":
|
|
836
|
-
add(operation["target"]);
|
|
837
|
-
if (operation["strategy"] === "replace")
|
|
838
|
-
add(operation["replacement"]);
|
|
839
|
-
break;
|
|
840
|
-
case "episode.add":
|
|
841
|
-
add(first("episode_id", "id"));
|
|
842
|
-
break;
|
|
843
|
-
case "episode.synopsis.set":
|
|
844
|
-
add(first("episode_id", "target", "at"));
|
|
845
|
-
break;
|
|
846
|
-
case "meta.worldview.set":
|
|
847
|
-
case "meta.synopsis.set":
|
|
848
|
-
add("global");
|
|
849
|
-
break;
|
|
850
|
-
case "scene.insert": {
|
|
851
|
-
const location = first("location", "location_id");
|
|
852
|
-
add(first("at", "episode_id"));
|
|
853
|
-
add(first("scene_id", "id"));
|
|
854
|
-
add(location);
|
|
855
|
-
addStates(location, operation["location_state_ids"]);
|
|
856
|
-
addPlacement();
|
|
857
|
-
break;
|
|
858
|
-
}
|
|
859
|
-
case "scene.move":
|
|
860
|
-
add(operation["at"]);
|
|
861
|
-
add(operation["to"]);
|
|
862
|
-
addPlacement();
|
|
863
|
-
break;
|
|
864
|
-
case "scene.delete":
|
|
865
|
-
add(operation["at"]);
|
|
866
|
-
break;
|
|
867
|
-
case "scene.split":
|
|
868
|
-
add(operation["at"]);
|
|
869
|
-
add(first("at_action", "action_id"));
|
|
870
|
-
add(first("new_scene_id", "scene_id"));
|
|
871
|
-
break;
|
|
872
|
-
case "scene.merge":
|
|
873
|
-
add(operation["from"]);
|
|
874
|
-
add(operation["into"]);
|
|
875
|
-
break;
|
|
876
|
-
case "extend.set":
|
|
877
|
-
case "extend.clear":
|
|
878
|
-
add(operation["at"]);
|
|
879
|
-
break;
|
|
880
|
-
default:
|
|
881
|
-
throw new Error(`V4 plan target mapping is missing for operation ${kind}`);
|
|
882
|
-
}
|
|
883
|
-
return [...new Set(values)];
|
|
884
|
-
}
|
|
885
|
-
export function buildV4MutationPlan(session, operations, options = {}) {
|
|
886
|
-
if (session.version !== 4) {
|
|
887
|
-
throw new CliError("A v4 mutation plan requires Script v4.", {
|
|
888
|
-
exitCode: EXIT_USAGE,
|
|
889
|
-
errorCode: "V4_PLAN_VERSION_INVALID",
|
|
890
|
-
data: { actual: [`Script v${session.version}`] },
|
|
891
|
-
});
|
|
892
|
-
}
|
|
893
|
-
const original = requireStructurallyReadableScriptV4(session.script);
|
|
894
|
-
const proposed = structuredClone(original);
|
|
895
|
-
const originalIds = v4CanonicalIds(original);
|
|
896
|
-
const applied = [];
|
|
897
|
-
const steps = [];
|
|
898
|
-
for (const [index, operation] of operations.entries()) {
|
|
899
|
-
const beforeIds = v4CanonicalIds(proposed);
|
|
900
|
-
const beforeSet = new Set(beforeIds);
|
|
901
|
-
const before = v4Counts(proposed);
|
|
902
|
-
let status = "applied";
|
|
903
|
-
try {
|
|
904
|
-
applied.push(...applyPatchOperationsV4(proposed, [operation]));
|
|
905
|
-
}
|
|
906
|
-
catch (error) {
|
|
907
|
-
if (error instanceof CliError
|
|
908
|
-
&& error.errorCode
|
|
909
|
-
&& options.skipCodes?.has(error.errorCode)) {
|
|
910
|
-
status = "skipped";
|
|
911
|
-
}
|
|
912
|
-
else {
|
|
913
|
-
throw error;
|
|
914
|
-
}
|
|
915
|
-
}
|
|
916
|
-
const afterIds = v4CanonicalIds(proposed);
|
|
917
|
-
const afterSet = new Set(afterIds);
|
|
918
|
-
steps.push({
|
|
919
|
-
index,
|
|
920
|
-
operation,
|
|
921
|
-
targets: v4OperationTargets(operation),
|
|
922
|
-
status,
|
|
923
|
-
before,
|
|
924
|
-
after: v4Counts(proposed),
|
|
925
|
-
created_ids: afterIds.filter((id) => !beforeSet.has(id)),
|
|
926
|
-
removed_ids: beforeIds.filter((id) => !afterSet.has(id)),
|
|
927
|
-
retained_ids: orderedIntersection(beforeIds, afterSet),
|
|
928
|
-
});
|
|
929
|
-
}
|
|
930
|
-
const proposedIds = v4CanonicalIds(proposed);
|
|
931
|
-
const originalSet = new Set(originalIds);
|
|
932
|
-
const proposedSet = new Set(proposedIds);
|
|
933
|
-
const targets = [...new Set(steps.flatMap((step) => step.targets))];
|
|
934
|
-
const touched = new Set([
|
|
935
|
-
...targets,
|
|
936
|
-
...steps.flatMap((step) => step.created_ids),
|
|
937
|
-
...steps.flatMap((step) => step.removed_ids),
|
|
938
|
-
]);
|
|
939
|
-
const plan = {
|
|
940
|
-
version: 1,
|
|
941
|
-
script_version: 4,
|
|
942
|
-
baseline: session.baselineHash,
|
|
943
|
-
operations,
|
|
944
|
-
targets,
|
|
945
|
-
steps,
|
|
946
|
-
before: v4Counts(original),
|
|
947
|
-
after: v4Counts(proposed),
|
|
948
|
-
created_ids: proposedIds.filter((id) => !originalSet.has(id)),
|
|
949
|
-
removed_ids: originalIds.filter((id) => !proposedSet.has(id)),
|
|
950
|
-
retained_ids: orderedIntersection(originalIds, proposedSet),
|
|
951
|
-
untouched_ids: orderedIntersection(originalIds, proposedSet)
|
|
952
|
-
.filter((id) => !touched.has(id)),
|
|
953
|
-
validation: validateScriptV4(proposed),
|
|
954
|
-
};
|
|
955
|
-
return {
|
|
956
|
-
plan,
|
|
957
|
-
digest: `sha256:${sha256Text(JSON.stringify(sortDeep(plan)))}`,
|
|
958
|
-
applied,
|
|
959
|
-
};
|
|
960
|
-
}
|
|
961
|
-
const V4_PLANNED_ID_FIELDS = {
|
|
962
|
-
"actor.add": "actor_id",
|
|
963
|
-
"location.add": "location_id",
|
|
964
|
-
"prop.add": "prop_id",
|
|
965
|
-
"state.add": "state_id",
|
|
966
|
-
"episode.add": "episode_id",
|
|
967
|
-
"scene.insert": "scene_id",
|
|
968
|
-
"scene.split": "new_scene_id",
|
|
969
|
-
"action.insert": "action_id",
|
|
970
|
-
};
|
|
971
|
-
export function assertV4PlanHasExplicitNewIds(operations) {
|
|
972
|
-
for (const operation of operations) {
|
|
973
|
-
const kind = strOf(operation["op"]);
|
|
974
|
-
const field = V4_PLANNED_ID_FIELDS[kind];
|
|
975
|
-
if (!field || strOf(operation[field]).trim())
|
|
976
|
-
continue;
|
|
977
|
-
const idKind = field === "new_scene_id" ? "scene" : field.replace(/_id$/, "");
|
|
978
|
-
throw new CliError("Planned creation operations require an explicit candidate ID.", {
|
|
979
|
-
exitCode: EXIT_USAGE,
|
|
980
|
-
errorCode: "V4_PLAN_ID_REQUIRED",
|
|
981
|
-
hint: `Generate a candidate with \`scriptctl ids --kind ${idKind} --count 1\`, then include it in the operation.`,
|
|
982
|
-
data: { expected: [`${kind}.${field}`], actual: [`${kind}.${field}=<missing>`] },
|
|
983
|
-
});
|
|
984
|
-
}
|
|
985
|
-
}
|
|
986
|
-
// ---------------------------------------------------------------------------
|
|
987
|
-
// Single-op helpers
|
|
988
|
-
// ---------------------------------------------------------------------------
|
|
989
|
-
export async function applySingleScriptOpToSession(session, opts, op) {
|
|
990
|
-
const plan = strOf(opts["plan"]).trim();
|
|
991
|
-
if (plan) {
|
|
992
|
-
throw new CliError("Single-point writes do not use plan digests.", {
|
|
993
|
-
exitCode: EXIT_USAGE,
|
|
994
|
-
errorCode: "MULTI_PLAN_USAGE_INVALID",
|
|
995
|
-
hint: "Remove --plan from this single-point edit.",
|
|
996
|
-
data: { actual: [plan] },
|
|
997
|
-
});
|
|
998
|
-
}
|
|
999
|
-
return applyScriptOpsToSession(session, opts, [op]);
|
|
1000
|
-
}
|
|
1001
|
-
export async function applyScriptOpsToSession(session, opts, operations) {
|
|
1002
|
-
const workspace = strOf(opts["workspace_path"] || "workspace");
|
|
1003
|
-
const applied = applyPatchOperationsForSession(session, scriptSourceText(workspace), operations);
|
|
1004
|
-
const opName = applied.length === 1 ? applied[0] : "script.ops";
|
|
1005
|
-
const [newRevision, idempotent] = await saveScriptSession(session, opts, opName);
|
|
1006
|
-
const validation = validateSession(session);
|
|
1007
|
-
await syncValidationResult(session, validation, newRevision);
|
|
1008
|
-
const passed = Boolean(validation["passed"]);
|
|
1009
|
-
const warnings = mutationValidationWarnings(session, validation);
|
|
1010
|
-
// One outcome line: what changed + revision (remote) + validation verdict.
|
|
1011
|
-
const rev = session.remote ? `; rev ${newRevision}` : "";
|
|
1012
|
-
const resultLine = `${applied.join(", ")} applied${rev}; validation ${passed ? "passed" : "needs repair"}`;
|
|
1013
|
-
const issues = summarizeIssues(asList(validation["issues"]));
|
|
1014
|
-
const warningLines = summarizeIssues(warnings);
|
|
1015
|
-
const report = {
|
|
1016
|
-
text: [resultLine, ...warningLines].join("\n"),
|
|
1017
|
-
data: {
|
|
1018
|
-
op: opName,
|
|
1019
|
-
changed: applied.length > 0,
|
|
1020
|
-
revision: session.remote ? newRevision : undefined,
|
|
1021
|
-
idempotent: session.remote ? idempotent : undefined,
|
|
1022
|
-
validation,
|
|
1023
|
-
issues,
|
|
1024
|
-
warnings,
|
|
1025
|
-
script_path: session.artifactLabel,
|
|
1026
|
-
},
|
|
1027
|
-
};
|
|
1028
|
-
return [report, EXIT_OK];
|
|
1029
|
-
}
|
|
1030
|
-
export async function applySingleScriptOp(opts, op) {
|
|
1031
|
-
const session = await loadScriptForEdit(opts);
|
|
1032
|
-
return applySingleScriptOpToSession(session, opts, op);
|
|
1033
|
-
}
|
|
1034
|
-
export function summarizeScriptOp(_script, op) {
|
|
1035
|
-
const kind = strOf(op["op"]);
|
|
1036
|
-
if (kind === "actor.add")
|
|
1037
|
-
return `Added actor ${op["name"] || op["actor_name"]}${op["role_type"] ? ` (${op["role_type"]})` : ""}`;
|
|
1038
|
-
if (kind === "location.add")
|
|
1039
|
-
return `Added location ${op["name"] || op["location_name"]}`;
|
|
1040
|
-
if (kind === "prop.add")
|
|
1041
|
-
return `Added prop ${op["name"] || op["prop_name"]}`;
|
|
1042
|
-
if (kind === "episode.add")
|
|
1043
|
-
return `Added episode${op["episode_id"] ? ` ${op["episode_id"]}` : " (generated ID)"}${op["title"] ? `: ${op["title"]}` : ""}`;
|
|
1044
|
-
if (kind === "meta.synopsis.set")
|
|
1045
|
-
return "Updated script synopsis";
|
|
1046
|
-
if (kind === "episode.synopsis.set")
|
|
1047
|
-
return `Updated episode synopsis ${op["episode_id"] ?? op["target"] ?? op["at"]}`;
|
|
1048
|
-
if (kind === "state.add")
|
|
1049
|
-
return `Added state ${op["state_id"]}: ${op["name"] || op["state_name"]} to ${op["target"]}`;
|
|
1050
|
-
if (kind === "importance.set")
|
|
1051
|
-
return `Set ${op["target"]} importance to ${op["importance"]}`;
|
|
1052
|
-
if (kind === "scene.ref.set")
|
|
1053
|
-
return `Set reference ${op["target"]} on ${op["at"]}${op["state"] ? ` (state ${op["state"]})` : ""}`;
|
|
1054
|
-
if (kind === "extend.set")
|
|
1055
|
-
return `Set extend.${op["key"]} on ${op["at"]}`;
|
|
1056
|
-
if (kind === "extend.clear")
|
|
1057
|
-
return op["key"] ? `Removed extend.${op["key"]} from ${op["at"]}` : `Cleared extend on ${op["at"]}`;
|
|
1058
|
-
if (kind === "action.timestamp.set")
|
|
1059
|
-
return `Set timestamp on ${op["at"]}`;
|
|
1060
|
-
if (kind === "action.timestamp.remove")
|
|
1061
|
-
return `Removed timestamp from ${op["at"]}`;
|
|
1062
|
-
if (kind.startsWith("state."))
|
|
1063
|
-
return `Applied ${kind}: ${op["target"]}`;
|
|
1064
|
-
if (kind.startsWith("dialogue."))
|
|
1065
|
-
return `Applied ${kind}: ${op["at"]}`;
|
|
1066
|
-
return `Applied ${kind}`;
|
|
1067
|
-
}
|
|
1068
|
-
// Accept `/re/flags` as-is; wrap a bare pattern as `/pattern/` so
|
|
1069
|
-
// `replace --regex --from '^\s*\[[^\]]*\]'` works without the user typing slashes.
|
|
1070
|
-
export function regexPattern(raw) {
|
|
1071
|
-
const s = raw.trim();
|
|
1072
|
-
if (s.length >= 2 && s.startsWith("/") && s.lastIndexOf("/") > 0)
|
|
1073
|
-
return s;
|
|
1074
|
-
return `/${s}/`;
|
|
1075
|
-
}
|
|
1076
|
-
// The selector-driven write runner. Resolves `opts` to its matched actions
|
|
1077
|
-
// (range/region + predicates) and applies one op template to each, as a single
|
|
1078
|
-
// in-memory pass committed once. Guardrail: with no --apply it's a DRY-RUN that
|
|
1079
|
-
// reports the blast radius and writes nothing; --apply commits. Per-action
|
|
1080
|
-
// "no match here / overlap dialogue" errors are skipped (a sweep); anything else
|
|
1081
|
-
// aborts the whole edit before any write. Shared by every selector-capable verb.
|
|
1082
|
-
export async function applySelectorEditsToSession(session, opts, template, verbLabel) {
|
|
1083
|
-
const workspace = strOf(opts["workspace_path"] || "workspace");
|
|
1084
|
-
const apply = Boolean(opts["apply"]);
|
|
1085
|
-
const opName = strOf(template["op"]);
|
|
1086
|
-
const script = session.script;
|
|
1087
|
-
const refs = session.version === 3
|
|
1088
|
-
? resolveActionTargets(script, opts).map((target) => `${target.epId}/${target.sceneId}#${target.idx}`)
|
|
1089
|
-
: resolveActionTargetsV4(requireStructurallyReadableScriptV4(script), opts, { allowOrdinals: false })
|
|
1090
|
-
.map((target) => target.action.action_id);
|
|
1091
|
-
const operations = refs.map((ref) => ({ ...template, at: ref }));
|
|
1092
|
-
const multiV4 = session.version === 4 && refs.length > 1;
|
|
1093
|
-
const planned = multiV4
|
|
1094
|
-
? buildV4MutationPlan(session, operations, { skipCodes: SKIPPABLE_EDIT_CODES })
|
|
1095
|
-
: null;
|
|
1096
|
-
const planDigest = planned?.digest ?? null;
|
|
1097
|
-
const suppliedPlan = strOf(opts["plan"]).trim();
|
|
1098
|
-
if (suppliedPlan && (!multiV4 || !apply)) {
|
|
1099
|
-
throw new CliError("A plan digest is only accepted for a v4 multi-target apply.", {
|
|
1100
|
-
exitCode: EXIT_USAGE,
|
|
1101
|
-
errorCode: "MULTI_PLAN_USAGE_INVALID",
|
|
1102
|
-
hint: "Remove --plan, or apply the same v4 multi-target selection that produced the digest.",
|
|
1103
|
-
data: { actual: [suppliedPlan] },
|
|
1104
|
-
});
|
|
1105
|
-
}
|
|
1106
|
-
if (multiV4 && apply && !suppliedPlan) {
|
|
1107
|
-
throw new CliError("A v4 multi-target write requires its dry-run plan digest.", {
|
|
1108
|
-
exitCode: EXIT_USAGE,
|
|
1109
|
-
errorCode: "MULTI_PLAN_REQUIRED",
|
|
1110
|
-
hint: "Run the same command without --apply, review the full plan, then retry with `--apply --plan <digest>`.",
|
|
1111
|
-
data: { expected: [planDigest ?? ""], actual: ["<missing>"] },
|
|
1112
|
-
});
|
|
1113
|
-
}
|
|
1114
|
-
if (multiV4 && apply && suppliedPlan !== planDigest) {
|
|
1115
|
-
throw new CliError("The supplied digest does not match the current targets and operations.", {
|
|
1116
|
-
exitCode: EXIT_INPUT,
|
|
1117
|
-
errorCode: "MULTI_PLAN_MISMATCH",
|
|
1118
|
-
hint: "Review the newly computed dry-run plan, then apply its exact digest.",
|
|
1119
|
-
data: { expected: [planDigest ?? ""], actual: [suppliedPlan] },
|
|
1120
|
-
});
|
|
1121
|
-
}
|
|
1122
|
-
const source = scriptSourceText(workspace);
|
|
1123
|
-
let applied = planned?.plan.steps.filter((step) => step.status === "applied").length ?? 0;
|
|
1124
|
-
let skipped = planned?.plan.steps.filter((step) => step.status === "skipped").length ?? 0;
|
|
1125
|
-
if (!planned) {
|
|
1126
|
-
for (const ref of refs) {
|
|
1127
|
-
try {
|
|
1128
|
-
applyPatchOperationsForSession(session, source, [{ ...template, at: ref }]);
|
|
1129
|
-
applied += 1;
|
|
1130
|
-
}
|
|
1131
|
-
catch (err) {
|
|
1132
|
-
if (err instanceof CliError && err.errorCode && SKIPPABLE_EDIT_CODES.has(err.errorCode)) {
|
|
1133
|
-
skipped += 1;
|
|
1134
|
-
continue;
|
|
1135
|
-
}
|
|
1136
|
-
throw err;
|
|
1137
|
-
}
|
|
1138
|
-
}
|
|
1139
|
-
}
|
|
1140
|
-
else if (apply) {
|
|
1141
|
-
for (const step of planned.plan.steps) {
|
|
1142
|
-
if (step.status === "applied") {
|
|
1143
|
-
applyPatchOperationsForSession(session, source, [step.operation]);
|
|
1144
|
-
}
|
|
1145
|
-
}
|
|
1146
|
-
}
|
|
1147
|
-
const displayedRefs = multiV4 ? refs : refs.slice(0, 12);
|
|
1148
|
-
const blast = [
|
|
1149
|
-
`verb: ${verbLabel} (${opName})`,
|
|
1150
|
-
`matched: ${refs.length} action(s)`,
|
|
1151
|
-
`${apply ? "applied" : "would-apply"}: ${applied}`,
|
|
1152
|
-
`${apply ? "skipped" : "would-skip"}: ${skipped}`,
|
|
1153
|
-
...(displayedRefs.length ? [`targets: ${displayedRefs.join(", ")}${refs.length > displayedRefs.length ? ` … (+${refs.length - displayedRefs.length} more)` : ""}`] : []),
|
|
1154
|
-
...(planDigest ? [`plan_digest: ${planDigest}`] : []),
|
|
1155
|
-
];
|
|
1156
|
-
if (!apply) {
|
|
1157
|
-
const legacyValidation = planned ? null : validateSession(session);
|
|
1158
|
-
const passed = planned
|
|
1159
|
-
? planned.plan.validation.ok
|
|
1160
|
-
: Boolean(legacyValidation?.["passed"]);
|
|
1161
|
-
const plannedIssueLines = planned
|
|
1162
|
-
? [...planned.plan.validation.errors, ...planned.plan.validation.warnings]
|
|
1163
|
-
.map((issue) => `${issue.path}: ${issue.code} - ${issue.message}`)
|
|
1164
|
-
: null;
|
|
1165
|
-
const legacyIssueLines = legacyValidation === null
|
|
1166
|
-
? []
|
|
1167
|
-
: summarizeIssues(asList(legacyValidation["issues"]));
|
|
1168
|
-
const issues = plannedIssueLines ?? legacyIssueLines;
|
|
1169
|
-
const hint = refs.length === 0
|
|
1170
|
-
? "Widen the selection with --in, --grep, or predicates."
|
|
1171
|
-
: planDigest
|
|
1172
|
-
? `Run again with --apply --plan ${planDigest} to commit this exact plan${passed ? "." : "; validation issues will remain available as follow-up diagnostics."}`
|
|
1173
|
-
: `Run again with --apply to commit${passed ? "." : "; validation issues will remain available as follow-up diagnostics."}`;
|
|
1174
|
-
const lines = [...blast, `validation: ${passed ? "would pass" : "would need repair"}; no write`, ...issues, hint];
|
|
1175
|
-
const report = {
|
|
1176
|
-
text: lines.join("\n"),
|
|
1177
|
-
data: {
|
|
1178
|
-
op: `${opName}.dry-run`,
|
|
1179
|
-
changed: false,
|
|
1180
|
-
matched: refs.length,
|
|
1181
|
-
applied,
|
|
1182
|
-
skipped,
|
|
1183
|
-
issues,
|
|
1184
|
-
script_path: session.artifactLabel,
|
|
1185
|
-
...(planDigest ? {
|
|
1186
|
-
baseline: session.baselineHash,
|
|
1187
|
-
plan_digest: planDigest,
|
|
1188
|
-
operations,
|
|
1189
|
-
targets: refs,
|
|
1190
|
-
plan: planned?.plan,
|
|
1191
|
-
} : {}),
|
|
1192
|
-
},
|
|
1193
|
-
};
|
|
1194
|
-
return [report, EXIT_OK];
|
|
1195
|
-
}
|
|
1196
|
-
if (refs.length === 0) {
|
|
1197
|
-
return [{
|
|
1198
|
-
text: [...blast, "Widen the selection with --in, --grep, or predicates."].join("\n"),
|
|
1199
|
-
data: {
|
|
1200
|
-
op: opName,
|
|
1201
|
-
changed: false,
|
|
1202
|
-
matched: 0,
|
|
1203
|
-
script_path: session.artifactLabel,
|
|
1204
|
-
},
|
|
1205
|
-
}, EXIT_OK];
|
|
1206
|
-
}
|
|
1207
|
-
const [newRevision, idempotent] = await saveScriptSession(session, opts, opName);
|
|
1208
|
-
const validation = validateSession(session);
|
|
1209
|
-
await syncValidationResult(session, validation, newRevision);
|
|
1210
|
-
const passed = Boolean(validation["passed"]);
|
|
1211
|
-
const warnings = mutationValidationWarnings(session, validation);
|
|
1212
|
-
const rev = session.remote ? `; rev ${newRevision}` : "";
|
|
1213
|
-
const issues = summarizeIssues(asList(validation["issues"]));
|
|
1214
|
-
const warningLines = summarizeIssues(warnings);
|
|
1215
|
-
const report = {
|
|
1216
|
-
text: [...blast, `validation: ${passed ? "passed" : "needs repair"}${rev}`, ...warningLines].join("\n"),
|
|
1217
|
-
data: {
|
|
1218
|
-
op: opName,
|
|
1219
|
-
changed: applied > 0,
|
|
1220
|
-
matched: refs.length,
|
|
1221
|
-
applied,
|
|
1222
|
-
skipped,
|
|
1223
|
-
revision: session.remote ? newRevision : undefined,
|
|
1224
|
-
idempotent: session.remote ? idempotent : undefined,
|
|
1225
|
-
validation,
|
|
1226
|
-
issues,
|
|
1227
|
-
warnings,
|
|
1228
|
-
script_path: session.artifactLabel,
|
|
1229
|
-
...(planDigest ? {
|
|
1230
|
-
baseline: session.baselineHash,
|
|
1231
|
-
plan_digest: planDigest,
|
|
1232
|
-
operations,
|
|
1233
|
-
targets: refs,
|
|
1234
|
-
plan: planned?.plan,
|
|
1235
|
-
} : {}),
|
|
1236
|
-
},
|
|
1237
|
-
};
|
|
1238
|
-
return [report, EXIT_OK];
|
|
1239
|
-
}
|
|
1240
|
-
export async function applySelectorEdits(opts, template, verbLabel) {
|
|
1241
|
-
const session = await loadScriptForEdit(opts);
|
|
1242
|
-
return applySelectorEditsToSession(session, opts, template, verbLabel);
|
|
1243
|
-
}
|
|
1244
|
-
export { sortDeep };
|
|
1245
|
-
// ===========================================================================
|
|
1246
|
-
// 0.6.0 plural-noun query commands (replace `commandScriptInspect --target X`)
|
|
1247
|
-
// ===========================================================================
|
|
1248
|
-
//
|
|
1249
|
-
// Each command is a thin read-only wrapper around the underlying script
|
|
1250
|
-
// document. They all return a CommandOutput shaped like inspect's existing output but
|
|
1251
|
-
// without the `--target` flag — the verb itself encodes the target. Filters
|
|
1252
|
-
// use `--in <addr>` (compose with the address parsers) plus per-target
|
|
1253
|
-
// predicates (--name / --kind / --has / --grep / --context / --type / --actor
|
|
1254
|
-
// / --speaker / --severity / --code / --has-{actor,location,prop}).
|
|
1255
|
-
// Resolve the speaker_id → source actor mapping once per call. Used by
|
|
1256
|
-
// commandActions's --actor filter when the action speaks via a speaker.
|
|
1257
|
-
// v3: a dialogue line carries a single inline speaker — an actor ({actor_id})
|
|
1258
|
-
// or a non-actor source ({kind, label?}). These read that shape.
|
|
1259
|
-
// The actor id behind an action's speaker, or "" for a non-actor / narrative line.
|
|
1260
|
-
export function actionActorId(action) {
|
|
1261
|
-
const s = action["speaker"];
|
|
1262
|
-
if (isDict(s) && strOf(s["actor_id"]).trim())
|
|
1263
|
-
return strOf(s["actor_id"]).trim();
|
|
1264
|
-
return "";
|
|
1265
|
-
}
|
|
1266
|
-
// A human label for the speaker: the actor's name (resolved via `names`), or a
|
|
1267
|
-
// non-actor kind's label / kind, or "" when the line has no speaker.
|
|
1268
|
-
export function actionSpeakerLabel(action, actorNames) {
|
|
1269
|
-
const s = action["speaker"];
|
|
1270
|
-
if (!isDict(s))
|
|
1271
|
-
return "";
|
|
1272
|
-
const actorId = strOf(s["actor_id"]).trim();
|
|
1273
|
-
if (actorId)
|
|
1274
|
-
return actorNames?.get(actorId) || actorId;
|
|
1275
|
-
const kind = strOf(s["kind"]).trim();
|
|
1276
|
-
if (kind)
|
|
1277
|
-
return strOf(s["label"]).trim() || kind;
|
|
1278
|
-
return "";
|
|
1279
|
-
}
|
|
1280
|
-
export function actorIdsInAction(action) {
|
|
1281
|
-
const ids = new Set();
|
|
1282
|
-
const id = actionActorId(action);
|
|
1283
|
-
if (id)
|
|
1284
|
-
ids.add(id);
|
|
1285
|
-
return ids;
|
|
1286
|
-
}
|
|
1287
|
-
// Build a grep matcher. /pattern/flags → RegExp, otherwise literal substring.
|
|
1288
|
-
// Pre-flight checks block the common ReDoS shapes before they hit V8's regex
|
|
1289
|
-
// engine: nested quantifiers like (a+)+, (a*)+, (a*|b*)+ etc. compile fine
|
|
1290
|
-
// but hang the process on adversarial input. Since --grep accepts caller-
|
|
1291
|
-
// controlled patterns and runs over every action in scope, the safe move is
|
|
1292
|
-
// to reject patterns with quantifier-on-group-with-internal-quantifier and
|
|
1293
|
-
// cap the pattern length.
|
|
1294
|
-
export function buildGrepMatcher(raw) {
|
|
1295
|
-
if (!raw)
|
|
1296
|
-
return null;
|
|
1297
|
-
const m = /^\/(.+)\/([gimsuy]*)$/.exec(raw);
|
|
1298
|
-
if (m) {
|
|
1299
|
-
const pattern = m[1];
|
|
1300
|
-
if (isDangerousRegex(pattern)) {
|
|
1301
|
-
throw new CliError("regex pattern has nested quantifiers (ReDoS risk) or exceeds the length limit.", {
|
|
1302
|
-
exitCode: EXIT_USAGE,
|
|
1303
|
-
errorCode: "REGEX_UNSAFE",
|
|
1304
|
-
hint: "Rewrite the regex to avoid nested quantifiers, or use a literal substring (drop the /…/ wrapper).",
|
|
1305
|
-
data: { expected: [`pattern length <= ${MAX_GREP_PATTERN_LEN}; no quantifier-on-group-with-internal-quantifier (e.g. (a+)+)`], actual: [`length=${pattern.length}, sample=${pattern.slice(0, 80)}`] },
|
|
1306
|
-
});
|
|
1307
|
-
}
|
|
1308
|
-
try {
|
|
1309
|
-
const re = new RegExp(pattern, m[2]);
|
|
1310
|
-
return (hay) => {
|
|
1311
|
-
re.lastIndex = 0;
|
|
1312
|
-
return re.test(hay);
|
|
1313
|
-
};
|
|
1314
|
-
}
|
|
1315
|
-
catch {
|
|
1316
|
-
// Malformed regex — treat as literal.
|
|
1317
|
-
}
|
|
1318
|
-
}
|
|
1319
|
-
return (hay) => hay.includes(raw);
|
|
1320
|
-
}
|
|
1321
|
-
export function buildReport(op, lines) {
|
|
1322
|
-
const outputLines = lines.length > 0 ? lines : ["No matches."];
|
|
1323
|
-
return {
|
|
1324
|
-
text: outputLines.join("\n"),
|
|
1325
|
-
data: {
|
|
1326
|
-
op,
|
|
1327
|
-
changed: false,
|
|
1328
|
-
},
|
|
1329
|
-
};
|
|
1330
|
-
}
|
|
1331
|
-
export function buildTableReport(op, lines, rowColumns, rows) {
|
|
1332
|
-
const report = buildReport(op, lines);
|
|
1333
|
-
report.data["row_columns"] = rowColumns;
|
|
1334
|
-
report.data["rows"] = rows;
|
|
1335
|
-
return report;
|
|
1336
|
-
}
|
|
1337
|
-
// ----- summary --------------------------------------------------------------
|
|
1338
|
-
export function synopsisPreview(text, limit) {
|
|
1339
|
-
const oneLine = text.replace(/\s+/g, " ").trim();
|
|
1340
|
-
return oneLine.length > limit ? `${oneLine.slice(0, limit)}…` : oneLine;
|
|
1341
|
-
}
|
|
1342
|
-
export function episodeInSelector(selector, epId, scenes) {
|
|
1343
|
-
if (selector.isEmpty)
|
|
1344
|
-
return true;
|
|
1345
|
-
if (selector.matchesScene(epId, "scn_000000"))
|
|
1346
|
-
return true;
|
|
1347
|
-
for (const scene of scenes) {
|
|
1348
|
-
if (selector.matchesScene(epId, strOf(scene["scene_id"])))
|
|
1349
|
-
return true;
|
|
1350
|
-
}
|
|
1351
|
-
return false;
|
|
1352
|
-
}
|
|
1353
|
-
export function nameMaps(script) {
|
|
1354
|
-
const out = { actor: new Map(), location: new Map(), prop: new Map() };
|
|
1355
|
-
for (const a of asList(script["actors"]))
|
|
1356
|
-
out.actor.set(strOf(a["actor_id"]), strOf(a["actor_name"]));
|
|
1357
|
-
for (const l of asList(script["locations"]))
|
|
1358
|
-
out.location.set(strOf(l["location_id"]), strOf(l["location_name"]));
|
|
1359
|
-
for (const p of asList(script["props"]))
|
|
1360
|
-
out.prop.set(strOf(p["prop_id"]), strOf(p["prop_name"]));
|
|
1361
|
-
return out;
|
|
1362
|
-
}
|
|
1363
|
-
export function formatScene(epId, scene, names) {
|
|
1364
|
-
const ctx = sceneRefs(scene);
|
|
1365
|
-
const env = isDict(scene["environment"]) ? scene["environment"] : {};
|
|
1366
|
-
const space = strOf(env["space"]) || "-";
|
|
1367
|
-
const time = strOf(env["time"]) || "-";
|
|
1368
|
-
const locations = asList(ctx["locations"]).map((r) => {
|
|
1369
|
-
const id = strOf(r["location_id"]);
|
|
1370
|
-
return `${id}(${names.location.get(id) || "?"})`;
|
|
1371
|
-
});
|
|
1372
|
-
const actors = asList(ctx["actors"]).map((r) => {
|
|
1373
|
-
const id = strOf(r["actor_id"]);
|
|
1374
|
-
return `${id}(${names.actor.get(id) || "?"})`;
|
|
1375
|
-
});
|
|
1376
|
-
const props = asList(ctx["props"]).map((r) => {
|
|
1377
|
-
const id = strOf(r["prop_id"]);
|
|
1378
|
-
return `${id}(${names.prop.get(id) || "?"})`;
|
|
1379
|
-
});
|
|
1380
|
-
const actionCount = asList(scene["actions"]).length;
|
|
1381
|
-
const { t_start, t_end } = sceneTimeSpan(scene);
|
|
1382
|
-
const timePart = t_start || t_end ? ` t=${t_start || "?"}..${t_end || "?"}` : "";
|
|
1383
|
-
return `${epId}/${scene["scene_id"]} [${space} ${time}] location=${locations.join(",") || "-"} actors=${actors.join(",") || "-"} props=${props.join(",") || "-"} actions=${actionCount}${timePart}`;
|
|
1384
|
-
}
|
|
1385
|
-
export const HAS_FILTERS = new Set(["transition", "speaker"]);
|
|
1386
|
-
// Resolve a selection (--in range/region selector + --type/--actor/--speaker/
|
|
1387
|
-
// --grep/--has predicates, AND-combined) to the matching actions, in document
|
|
1388
|
-
// order. The single matcher behind both `actions` queries and selector-driven
|
|
1389
|
-
// writes. Does NOT enforce "at least one filter" — that policy is caller-owned
|
|
1390
|
-
// (queries refuse a bare dump; writes gate on --all). Validates the --has value.
|
|
1391
|
-
export function resolveActionTargets(script, opts) {
|
|
1392
|
-
const selector = parseInSelector(strOf(opts["in"]));
|
|
1393
|
-
const timestampRange = actionTimestampFilter(opts);
|
|
1394
|
-
const typeFilter = strOf(opts["type"]).trim();
|
|
1395
|
-
const actorFilter = strOf(opts["actor"]).trim();
|
|
1396
|
-
const hasFilter = strOf(opts["has"]).trim();
|
|
1397
|
-
// Whitelist --has: silently accepting unknown values means a typo like
|
|
1398
|
-
// "state_changes" (underscore) passed the filter-missing guard but bypassed
|
|
1399
|
-
// every concrete predicate, returning the whole script.
|
|
1400
|
-
if (hasFilter && !HAS_FILTERS.has(hasFilter)) {
|
|
1401
|
-
throw new CliError("--has value invalid.", {
|
|
1402
|
-
exitCode: EXIT_USAGE,
|
|
1403
|
-
errorCode: "HAS_FILTER_INVALID",
|
|
1404
|
-
hint: "Use a supported --has value.",
|
|
1405
|
-
data: { expected: [`--has: one of ${[...HAS_FILTERS].join(", ")}`], actual: [hasFilter] },
|
|
1406
|
-
});
|
|
1407
|
-
}
|
|
1408
|
-
const grepMatcher = buildGrepMatcher(strOf(opts["grep"]));
|
|
1409
|
-
const out = [];
|
|
1410
|
-
for (const ep of asList(script["episodes"])) {
|
|
1411
|
-
const epId = strOf(ep["episode_id"]);
|
|
1412
|
-
for (const scene of asList(ep["scenes"])) {
|
|
1413
|
-
const sceneId = strOf(scene["scene_id"]);
|
|
1414
|
-
if (!selector.matchesScene(epId, sceneId))
|
|
1415
|
-
continue;
|
|
1416
|
-
const actions = asList(scene["actions"]);
|
|
1417
|
-
for (let i = 0; i < actions.length; i++) {
|
|
1418
|
-
if (!selector.matchesAction(epId, sceneId, i))
|
|
1419
|
-
continue;
|
|
1420
|
-
const a = actions[i];
|
|
1421
|
-
if (timestampRange
|
|
1422
|
-
&& !actionTimestampMatches(isDict(a["extend"]) ? a["extend"]["timestamp"] : undefined, timestampRange, actionAddress(epId, sceneId, i)))
|
|
1423
|
-
continue;
|
|
1424
|
-
if (typeFilter && strOf(a["type"]).trim() !== typeFilter)
|
|
1425
|
-
continue;
|
|
1426
|
-
if (actorFilter && !actorIdsInAction(a).has(actorFilter))
|
|
1427
|
-
continue;
|
|
1428
|
-
if (hasFilter === "transition" && !isDict(a["transition_prompt"]))
|
|
1429
|
-
continue;
|
|
1430
|
-
if (hasFilter === "speaker" && !isDict(a["speaker"]))
|
|
1431
|
-
continue;
|
|
1432
|
-
if (grepMatcher && !grepMatcher(strOf(a["content"])))
|
|
1433
|
-
continue;
|
|
1434
|
-
out.push({ epId, sceneId, idx: i, action: a });
|
|
1435
|
-
}
|
|
1436
|
-
}
|
|
1437
|
-
}
|
|
1438
|
-
return out;
|
|
1439
|
-
}
|
|
1440
|
-
// Whether a selection in `opts` has any filter at all (scope or predicate).
|
|
1441
|
-
export function selectionHasAnyFilter(opts) {
|
|
1442
|
-
return Boolean(strOf(opts["in"]).trim() ||
|
|
1443
|
-
strOf(opts["grep"]) || strOf(opts["type"]).trim() || strOf(opts["actor"]).trim() ||
|
|
1444
|
-
strOf(opts["has"]).trim());
|
|
1445
|
-
}
|
|
1446
|
-
// Collapse a set of episode ids into sorted, comma-joined ranges:
|
|
1447
|
-
// {ep_001, ep_002, ep_003, ep_007} → "ep_001..ep_003,ep_007". Keeps the state
|
|
1448
|
-
// arc / appearance lines readable even when an item spans dozens of episodes.
|
|
1449
|
-
export function compactEpisodeRanges(ids) {
|
|
1450
|
-
const nums = [...new Set([...ids])]
|
|
1451
|
-
.map((id) => ({ id, n: idNum(id, "ep") }))
|
|
1452
|
-
.filter((x) => Number.isFinite(x.n))
|
|
1453
|
-
.sort((a, b) => a.n - b.n);
|
|
1454
|
-
if (nums.length === 0)
|
|
1455
|
-
return "";
|
|
1456
|
-
const parts = [];
|
|
1457
|
-
let start = nums[0];
|
|
1458
|
-
let prev = nums[0];
|
|
1459
|
-
const flush = () => parts.push(start.id === prev.id ? start.id : `${start.id}..${prev.id}`);
|
|
1460
|
-
for (let i = 1; i < nums.length; i++) {
|
|
1461
|
-
const cur = nums[i];
|
|
1462
|
-
if (cur.n === prev.n + 1) {
|
|
1463
|
-
prev = cur;
|
|
1464
|
-
continue;
|
|
1465
|
-
}
|
|
1466
|
-
flush();
|
|
1467
|
-
start = cur;
|
|
1468
|
-
prev = cur;
|
|
1469
|
-
}
|
|
1470
|
-
flush();
|
|
1471
|
-
return parts.join(",");
|
|
1472
|
-
}
|
|
1473
|
-
// One pass over scene context: for each asset id of `kind`, the set of episodes
|
|
1474
|
-
// and count of scenes it is referenced in. "Appearance" = presence in a scene's
|
|
1475
|
-
// context (the canonical who/what-is-in-this-scene list direct-init populates).
|
|
1476
|
-
export function assetAppearanceCounts(script, kind) {
|
|
1477
|
-
const idKey = kind === "actor" ? "actor_id" : kind === "location" ? "location_id" : "prop_id";
|
|
1478
|
-
const pluralKey = kind === "actor" ? "actors" : kind === "location" ? "locations" : "props";
|
|
1479
|
-
const out = new Map();
|
|
1480
|
-
for (const ep of asList(script["episodes"])) {
|
|
1481
|
-
const epId = strOf(ep["episode_id"]);
|
|
1482
|
-
for (const scene of asList(ep["scenes"])) {
|
|
1483
|
-
const ctx = sceneRefs(scene);
|
|
1484
|
-
const seen = new Set();
|
|
1485
|
-
for (const ref of asList(ctx[pluralKey])) {
|
|
1486
|
-
const id = strOf(ref[idKey]);
|
|
1487
|
-
if (!id || seen.has(id))
|
|
1488
|
-
continue;
|
|
1489
|
-
seen.add(id);
|
|
1490
|
-
const entry = out.get(id) ?? { episodes: new Set(), scenes: 0 };
|
|
1491
|
-
entry.episodes.add(epId);
|
|
1492
|
-
entry.scenes += 1;
|
|
1493
|
-
out.set(id, entry);
|
|
1494
|
-
}
|
|
1495
|
-
}
|
|
1496
|
-
}
|
|
1497
|
-
return out;
|
|
1498
|
-
}
|
|
1499
|
-
export function listAssetsByKind(script, kind, opts) {
|
|
1500
|
-
const lines = [];
|
|
1501
|
-
const rows = [];
|
|
1502
|
-
const [key, idKey, nameKey] = (() => {
|
|
1503
|
-
switch (kind) {
|
|
1504
|
-
case "actor": return ["actors", "actor_id", "actor_name"];
|
|
1505
|
-
case "location": return ["locations", "location_id", "location_name"];
|
|
1506
|
-
case "prop": return ["props", "prop_id", "prop_name"];
|
|
1507
|
-
}
|
|
1508
|
-
})();
|
|
1509
|
-
// Build the set of asset ids referenced inside the --in scope. A range or
|
|
1510
|
-
// multi-region selector takes the union of context refs over every matched
|
|
1511
|
-
// scene; a bare single action point (e.g. ep_001/scn_003#2) keeps the legacy
|
|
1512
|
-
// "narrow to that one action's actor" behavior.
|
|
1513
|
-
// WHOLE_SCRIPT ('--in *') means "all assets" — it must NOT narrow to the set
|
|
1514
|
-
// of assets referenced in scene context (that would drop registered-but-not-
|
|
1515
|
-
// yet-placed assets). Only a real address-region selector narrows.
|
|
1516
|
-
let scopeIds = null;
|
|
1517
|
-
if (!opts.selector.isEmpty && opts.selector !== WHOLE_SCRIPT) {
|
|
1518
|
-
scopeIds = new Set();
|
|
1519
|
-
const single = selectorSingleActionPoint(opts.selector);
|
|
1520
|
-
const pluralKey = kind === "actor" ? "actors" : kind === "location" ? "locations" : "props";
|
|
1521
|
-
for (const ep of asList(script["episodes"])) {
|
|
1522
|
-
const epId = strOf(ep["episode_id"]);
|
|
1523
|
-
for (const scene of asList(ep["scenes"])) {
|
|
1524
|
-
const sceneId = strOf(scene["scene_id"]);
|
|
1525
|
-
if (!opts.selector.matchesScene(epId, sceneId))
|
|
1526
|
-
continue;
|
|
1527
|
-
if (single) {
|
|
1528
|
-
// Single action point: matchesScene already isolates the target
|
|
1529
|
-
// scene. Legacy narrowing is implemented for actor only.
|
|
1530
|
-
if (kind === "actor") {
|
|
1531
|
-
const a = asList(scene["actions"])[single.idx];
|
|
1532
|
-
const aid = a ? actionActorId(a) : "";
|
|
1533
|
-
if (aid)
|
|
1534
|
-
scopeIds.add(aid);
|
|
1535
|
-
}
|
|
1536
|
-
continue;
|
|
1537
|
-
}
|
|
1538
|
-
const ctx = sceneRefs(scene);
|
|
1539
|
-
for (const ref of asList(ctx[pluralKey])) {
|
|
1540
|
-
scopeIds.add(strOf(ref[idKey]));
|
|
1541
|
-
}
|
|
1542
|
-
}
|
|
1543
|
-
}
|
|
1544
|
-
}
|
|
1545
|
-
// Appearance counts (scenes / episodes) computed in one pass, only when asked
|
|
1546
|
-
// — keeps the default listing lean.
|
|
1547
|
-
const appearances = opts.counts ? assetAppearanceCounts(script, kind) : null;
|
|
1548
|
-
for (const asset of asList(script[key])) {
|
|
1549
|
-
const id = strOf(asset[idKey]);
|
|
1550
|
-
const name = strOf(asset[nameKey]);
|
|
1551
|
-
if (opts.id && opts.id !== id)
|
|
1552
|
-
continue;
|
|
1553
|
-
if (opts.name && !name.includes(opts.name))
|
|
1554
|
-
continue;
|
|
1555
|
-
if (scopeIds && !scopeIds.has(id))
|
|
1556
|
-
continue;
|
|
1557
|
-
const aliases = asList(asset["aliases"]).map((s) => strOf(s));
|
|
1558
|
-
const role = strOf(asset["role_type"]);
|
|
1559
|
-
const importance = strOf(asset["importance"]);
|
|
1560
|
-
const descPresent = strOf(asset["description"]).trim() ? "yes" : "missing";
|
|
1561
|
-
const states = asList(asset["states"]).length;
|
|
1562
|
-
const extra = [];
|
|
1563
|
-
if (aliases.length > 0)
|
|
1564
|
-
extra.push(`aliases=(${aliases.join(",")})`);
|
|
1565
|
-
if (importance)
|
|
1566
|
-
extra.push(`importance=${importance}`);
|
|
1567
|
-
if (role)
|
|
1568
|
-
extra.push(`role=${role}`);
|
|
1569
|
-
extra.push(`states=${states}`, `description=${descPresent}`);
|
|
1570
|
-
if (appearances) {
|
|
1571
|
-
const seen = appearances.get(id);
|
|
1572
|
-
const eps = seen ? seen.episodes.size : 0;
|
|
1573
|
-
const scns = seen ? seen.scenes : 0;
|
|
1574
|
-
const arc = seen && eps > 0 ? ` episodes=${compactEpisodeRanges(seen.episodes)}` : "";
|
|
1575
|
-
extra.push(`scenes=${scns}`, `episodes_count=${eps}${arc}`);
|
|
1576
|
-
}
|
|
1577
|
-
lines.push(`${kind} ${id}: ${name || "-"} ${extra.join(" ")}`);
|
|
1578
|
-
const seen = appearances?.get(id);
|
|
1579
|
-
rows.push({
|
|
1580
|
-
addr: `${kind}:${id}`,
|
|
1581
|
-
kind,
|
|
1582
|
-
id,
|
|
1583
|
-
name,
|
|
1584
|
-
aliases,
|
|
1585
|
-
importance,
|
|
1586
|
-
role,
|
|
1587
|
-
states,
|
|
1588
|
-
description_present: descPresent === "yes",
|
|
1589
|
-
...(appearances
|
|
1590
|
-
? {
|
|
1591
|
-
scenes: seen?.scenes ?? 0,
|
|
1592
|
-
episodes_count: seen?.episodes.size ?? 0,
|
|
1593
|
-
episodes: seen ? compactEpisodeRanges(seen.episodes) : "",
|
|
1594
|
-
}
|
|
1595
|
-
: {}),
|
|
1596
|
-
});
|
|
1597
|
-
}
|
|
1598
|
-
return {
|
|
1599
|
-
lines,
|
|
1600
|
-
rows,
|
|
1601
|
-
rowColumns: [
|
|
1602
|
-
"addr",
|
|
1603
|
-
"kind",
|
|
1604
|
-
"id",
|
|
1605
|
-
"name",
|
|
1606
|
-
"aliases",
|
|
1607
|
-
"importance",
|
|
1608
|
-
"role",
|
|
1609
|
-
"states",
|
|
1610
|
-
"description_present",
|
|
1611
|
-
...(appearances ? ["scenes", "episodes_count", "episodes"] : []),
|
|
1612
|
-
],
|
|
1613
|
-
};
|
|
1614
|
-
}
|
|
1615
|
-
export function splitSpeakerList(raw) {
|
|
1616
|
-
if (Array.isArray(raw))
|
|
1617
|
-
return raw.map((v) => strOf(v)).filter((v) => v);
|
|
1618
|
-
return strOf(raw).split(",").map((s) => s.trim()).filter((s) => s);
|
|
1619
|
-
}
|
|
1620
|
-
export function blankCreateReport(session, validation, idempotent) {
|
|
1621
|
-
const passed = Boolean(validation["passed"]);
|
|
1622
|
-
const resultLines = [`created: blank script (Script v${session.version})`, `validation: ${passed ? "passed" : "needs repair"}`];
|
|
1623
|
-
if (session.remote) {
|
|
1624
|
-
resultLines.push(`revision: ${session.revision}`);
|
|
1625
|
-
if (idempotent !== null)
|
|
1626
|
-
resultLines.push(`idempotent: ${String(idempotent).toLowerCase()}`);
|
|
1627
|
-
}
|
|
1628
|
-
return {
|
|
1629
|
-
text: resultLines.join("\n"),
|
|
1630
|
-
data: {
|
|
1631
|
-
op: "script.create",
|
|
1632
|
-
changed: true,
|
|
1633
|
-
validation,
|
|
1634
|
-
script_path: session.artifactLabel,
|
|
1635
|
-
...(session.remote ? { revision: session.revision, idempotent } : {}),
|
|
1636
|
-
},
|
|
1637
|
-
};
|
|
1638
|
-
}
|
|
1639
|
-
// ----- add-* (register new entities) ----------------------------------------
|
|
1640
|
-
// Read the single positional <name> arg shared by add-actor/location/prop, or
|
|
1641
|
-
// throw the common ARGS_MISSING usage error with a verb-specific example.
|
|
1642
|
-
export function requireNameArg(opts, verb, example) {
|
|
1643
|
-
const args = asList(opts["_args"]);
|
|
1644
|
-
if (args.length < 1) {
|
|
1645
|
-
throw new CliError("Name missing.", {
|
|
1646
|
-
exitCode: EXIT_USAGE,
|
|
1647
|
-
errorCode: "ARGS_MISSING",
|
|
1648
|
-
hint: example,
|
|
1649
|
-
data: { expected: ["<name>"], actual: ["<empty>"] },
|
|
1650
|
-
});
|
|
1651
|
-
}
|
|
1652
|
-
return args[0];
|
|
1653
|
-
}
|
|
1654
|
-
//# sourceMappingURL=lib.js.map
|