davinci-resolve-mcp 2.57.4 → 2.58.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +20 -0
- package/CHANGELOG.md +197 -2
- package/LICENSE +1 -1
- package/README.md +73 -1
- package/bin/davinci-resolve-advanced-mcp.mjs +20 -0
- package/docs/README.md +19 -0
- package/docs/SKILL.md +62 -1
- package/docs/contributing.md +1 -1
- package/docs/guides/control-panel.md +9 -0
- package/docs/kernels/README.md +21 -0
- package/docs/kernels/audio-fairlight-kernel.md +22 -0
- package/docs/kernels/color-grade-kernel.md +51 -0
- package/docs/kernels/fusion-composition-kernel.md +17 -0
- package/docs/kernels/media-pool-ingest-kernel.md +20 -0
- package/docs/kernels/render-deliver-kernel.md +32 -0
- package/docs/kernels/timeline-conform-interchange-kernel.md +39 -0
- package/docs/kernels/timeline-edit-kernel.md +17 -0
- package/docs/process/release-process.md +29 -7
- package/docs/reference/api-coverage.md +1 -1
- package/docs/reference/api-limitations.md +38 -1
- package/install.py +27 -4
- package/package.json +23 -2
- package/resolve-advanced/README.md +194 -0
- package/resolve-advanced/package.json +50 -0
- package/resolve-advanced/server/black-balance.mjs +92 -0
- package/resolve-advanced/server/capabilities.mjs +86 -0
- package/resolve-advanced/server/cdl-io.mjs +76 -0
- package/resolve-advanced/server/contrast-normalize.mjs +180 -0
- package/resolve-advanced/server/db-patch.mjs +91 -0
- package/resolve-advanced/server/deliverable-entities.mjs +86 -0
- package/resolve-advanced/server/deliverable-qc.mjs +270 -0
- package/resolve-advanced/server/editorial.mjs +370 -0
- package/resolve-advanced/server/exposure-level.mjs +129 -0
- package/resolve-advanced/server/extract-frames.mjs +196 -0
- package/resolve-advanced/server/ffprobe-media.mjs +88 -0
- package/resolve-advanced/server/gamut-legal.mjs +112 -0
- package/resolve-advanced/server/grade-body-patch.mjs +246 -0
- package/resolve-advanced/server/grade-transfer.mjs +66 -0
- package/resolve-advanced/server/group-grade-read.mjs +137 -0
- package/resolve-advanced/server/index.mjs +105 -0
- package/resolve-advanced/server/lib.mjs +84 -0
- package/resolve-advanced/server/libs.mjs +65 -0
- package/resolve-advanced/server/lineage-db.mjs +479 -0
- package/resolve-advanced/server/lut-apply.mjs +61 -0
- package/resolve-advanced/server/match-to-reference.mjs +173 -0
- package/resolve-advanced/server/media-inventory.mjs +169 -0
- package/resolve-advanced/server/media-ops.mjs +243 -0
- package/resolve-advanced/server/node-meta-db.mjs +62 -0
- package/resolve-advanced/server/node-provenance.mjs +102 -0
- package/resolve-advanced/server/offline-ref-db.mjs +420 -0
- package/resolve-advanced/server/offline-ref.mjs +179 -0
- package/resolve-advanced/server/project-db.mjs +233 -0
- package/resolve-advanced/server/provenance-audit.mjs +210 -0
- package/resolve-advanced/server/qc-frame.mjs +224 -0
- package/resolve-advanced/server/qc-sampler.mjs +67 -0
- package/resolve-advanced/server/readback.mjs +77 -0
- package/resolve-advanced/server/render-manifest.mjs +93 -0
- package/resolve-advanced/server/reverse-clip-db.mjs +270 -0
- package/resolve-advanced/server/runner-apply-contract.mjs +64 -0
- package/resolve-advanced/server/runner.mjs +244 -0
- package/resolve-advanced/server/saturation-match.mjs +108 -0
- package/resolve-advanced/server/scope-read.mjs +257 -0
- package/resolve-advanced/server/season-look.mjs +96 -0
- package/resolve-advanced/server/shot-intent.mjs +82 -0
- package/resolve-advanced/server/shot-match.mjs +147 -0
- package/resolve-advanced/server/skin-match.mjs +205 -0
- package/resolve-advanced/server/spec-compile.mjs +217 -0
- package/resolve-advanced/server/tone-curve-transfer.mjs +184 -0
- package/resolve-advanced/server/tool-catalog.mjs +265 -0
- package/resolve-advanced/server/tools/audio.mjs +54 -0
- package/resolve-advanced/server/tools/audio_plan.mjs +58 -0
- package/resolve-advanced/server/tools/capabilities.mjs +16 -0
- package/resolve-advanced/server/tools/color_trace.mjs +165 -0
- package/resolve-advanced/server/tools/conform.mjs +291 -0
- package/resolve-advanced/server/tools/deliverable.mjs +105 -0
- package/resolve-advanced/server/tools/drp.mjs +232 -0
- package/resolve-advanced/server/tools/drt.mjs +200 -0
- package/resolve-advanced/server/tools/drx.mjs +943 -0
- package/resolve-advanced/server/tools/editorial.mjs +69 -0
- package/resolve-advanced/server/tools/fairlight.mjs +108 -0
- package/resolve-advanced/server/tools/fusion.mjs +64 -0
- package/resolve-advanced/server/tools/media.mjs +102 -0
- package/resolve-advanced/server/tools/offline_ref.mjs +123 -0
- package/resolve-advanced/server/tools/pipeline.mjs +137 -0
- package/resolve-advanced/server/tools/project_db.mjs +200 -0
- package/resolve-advanced/server/tools/project_read.mjs +212 -0
- package/resolve-advanced/server/tools/provenance.mjs +73 -0
- package/resolve-advanced/server/verify-grade.mjs +113 -0
- package/resolve-advanced/server/white-balance-match.mjs +122 -0
- package/resolve-advanced/vendor/audio/format-converter.js +330 -0
- package/resolve-advanced/vendor/audio/split.js +173 -0
- package/resolve-advanced/vendor/audio/trim.js +188 -0
- package/resolve-advanced/vendor/audio-fairlight/index.js +391 -0
- package/resolve-advanced/vendor/conform-qc/adapters/frame-sampler.js +56 -0
- package/resolve-advanced/vendor/conform-qc/adapters/local-ffmpeg-sampler.js +65 -0
- package/resolve-advanced/vendor/conform-qc/adapters/rendernode-ffmpeg-sampler.js +50 -0
- package/resolve-advanced/vendor/conform-qc/adapters/resolve/driver.py +176 -0
- package/resolve-advanced/vendor/conform-qc/adapters/resolve-driver.js +61 -0
- package/resolve-advanced/vendor/conform-qc/adapters/resolve-headless-driver.js +86 -0
- package/resolve-advanced/vendor/conform-qc/adapters/vision-validator.js +75 -0
- package/resolve-advanced/vendor/conform-qc/cli.js +63 -0
- package/resolve-advanced/vendor/conform-qc/compare/advisory.js +106 -0
- package/resolve-advanced/vendor/conform-qc/compare/decode.js +36 -0
- package/resolve-advanced/vendor/conform-qc/compare/index.js +61 -0
- package/resolve-advanced/vendor/conform-qc/compare/locate.js +70 -0
- package/resolve-advanced/vendor/conform-qc/compare/metrics.js +409 -0
- package/resolve-advanced/vendor/conform-qc/docs/runbook.md +72 -0
- package/resolve-advanced/vendor/conform-qc/index.js +49 -0
- package/resolve-advanced/vendor/conform-qc/knowledge/index.js +110 -0
- package/resolve-advanced/vendor/conform-qc/ops/conform-core.js +137 -0
- package/resolve-advanced/vendor/conform-qc/ops/conform-diff.js +109 -0
- package/resolve-advanced/vendor/conform-qc/ops/insert.js +108 -0
- package/resolve-advanced/vendor/conform-qc/ops/local-conform.js +61 -0
- package/resolve-advanced/vendor/conform-qc/ops/patch.js +80 -0
- package/resolve-advanced/vendor/conform-qc/ops/trigger.js +32 -0
- package/resolve-advanced/vendor/conform-qc/ops/verify.js +105 -0
- package/resolve-advanced/vendor/conform-qc/ops/workflow.js +30 -0
- package/resolve-advanced/vendor/conform-qc/oracle/emulate.js +155 -0
- package/resolve-advanced/vendor/conform-qc/oracle/index.js +38 -0
- package/resolve-advanced/vendor/conform-qc/oracle/resolve.js +196 -0
- package/resolve-advanced/vendor/conform-qc/package.json +16 -0
- package/resolve-advanced/vendor/conform-qc/packaging/emit-aaf.js +30 -0
- package/resolve-advanced/vendor/conform-qc/packaging/emit-fcp7.js +64 -0
- package/resolve-advanced/vendor/conform-qc/packaging/index.js +169 -0
- package/resolve-advanced/vendor/conform-qc/packaging/media-ops.js +56 -0
- package/resolve-advanced/vendor/conform-qc/packaging/otio.js +50 -0
- package/resolve-advanced/vendor/conform-qc/packaging/relink.js +50 -0
- package/resolve-advanced/vendor/conform-qc/packaging/surgical-relink.js +195 -0
- package/resolve-advanced/vendor/conform-qc/parse/index.js +54 -0
- package/resolve-advanced/vendor/conform-qc/parse/merge-dto.js +27 -0
- package/resolve-advanced/vendor/conform-qc/parse/xmeml-geometry.js +256 -0
- package/resolve-advanced/vendor/conform-qc/reference/burnin-ocr.js +100 -0
- package/resolve-advanced/vendor/conform-qc/reference/sidecar.js +37 -0
- package/resolve-advanced/vendor/conform-qc/repair/analysis.js +62 -0
- package/resolve-advanced/vendor/conform-qc/repair/index.js +78 -0
- package/resolve-advanced/vendor/conform-qc/repair/media-analysis.js +139 -0
- package/resolve-advanced/vendor/conform-qc/repair/media-index.js +135 -0
- package/resolve-advanced/vendor/conform-qc/repair/strategies.js +250 -0
- package/resolve-advanced/vendor/conform-qc/report/index.js +133 -0
- package/resolve-advanced/vendor/conform-qc/roles/index.js +96 -0
- package/resolve-advanced/vendor/conform-qc/synthetic/generate.js +233 -0
- package/resolve-advanced/vendor/conform-qc/test/advisory.test.js +85 -0
- package/resolve-advanced/vendor/conform-qc/test/cli.test.js +39 -0
- package/resolve-advanced/vendor/conform-qc/test/compare.test.js +152 -0
- package/resolve-advanced/vendor/conform-qc/test/conform-diff.test.js +70 -0
- package/resolve-advanced/vendor/conform-qc/test/emulate.test.js +51 -0
- package/resolve-advanced/vendor/conform-qc/test/frame-sampler.test.js +30 -0
- package/resolve-advanced/vendor/conform-qc/test/geometry.test.js +112 -0
- package/resolve-advanced/vendor/conform-qc/test/knowledge.test.js +56 -0
- package/resolve-advanced/vendor/conform-qc/test/lifecycle.test.js +110 -0
- package/resolve-advanced/vendor/conform-qc/test/local-ffmpeg-sampler.test.js +66 -0
- package/resolve-advanced/vendor/conform-qc/test/locate.test.js +63 -0
- package/resolve-advanced/vendor/conform-qc/test/media-analysis.test.js +63 -0
- package/resolve-advanced/vendor/conform-qc/test/media-index-normalized.test.js +65 -0
- package/resolve-advanced/vendor/conform-qc/test/media-index-origin.test.js +53 -0
- package/resolve-advanced/vendor/conform-qc/test/metrics-fast.test.js +91 -0
- package/resolve-advanced/vendor/conform-qc/test/oracle-reverse.test.js +86 -0
- package/resolve-advanced/vendor/conform-qc/test/oracle.test.js +136 -0
- package/resolve-advanced/vendor/conform-qc/test/p0-acceptance.test.js +60 -0
- package/resolve-advanced/vendor/conform-qc/test/p1-acceptance.test.js +75 -0
- package/resolve-advanced/vendor/conform-qc/test/p45-patch-acceptance.test.js +102 -0
- package/resolve-advanced/vendor/conform-qc/test/packaging.test.js +133 -0
- package/resolve-advanced/vendor/conform-qc/test/parse-stubs.test.js +28 -0
- package/resolve-advanced/vendor/conform-qc/test/repair-strategies.test.js +128 -0
- package/resolve-advanced/vendor/conform-qc/test/repair.test.js +84 -0
- package/resolve-advanced/vendor/conform-qc/test/report.test.js +52 -0
- package/resolve-advanced/vendor/conform-qc/test/resolve-readback.test.js +71 -0
- package/resolve-advanced/vendor/conform-qc/test/roles.test.js +107 -0
- package/resolve-advanced/vendor/conform-qc/test/runbook.test.js +30 -0
- package/resolve-advanced/vendor/conform-qc/test/scale-residual.test.js +40 -0
- package/resolve-advanced/vendor/conform-qc/test/sidecar.test.js +51 -0
- package/resolve-advanced/vendor/conform-qc/test/smoke.test.js +87 -0
- package/resolve-advanced/vendor/conform-qc/test/surgical-relink.test.js +73 -0
- package/resolve-advanced/vendor/conform-qc/test/synthetic.test.js +98 -0
- package/resolve-advanced/vendor/conform-qc/test/verify.test.js +93 -0
- package/resolve-advanced/vendor/conform-qc/test/vision-validator.test.js +43 -0
- package/resolve-advanced/vendor/conform-qc/test/workflow-driver.test.js +46 -0
- package/resolve-advanced/vendor/conform-qc/toolset/index.js +53 -0
- package/resolve-advanced/vendor/drp-format/README.md +116 -0
- package/resolve-advanced/vendor/drp-format/__tests__/_resolve-verify.js +39 -0
- package/resolve-advanced/vendor/drp-format/__tests__/add-media-clip.test.js +30 -0
- package/resolve-advanced/vendor/drp-format/__tests__/assemble-timeline.test.js +68 -0
- package/resolve-advanced/vendor/drp-format/__tests__/author-project.test.js +57 -0
- package/resolve-advanced/vendor/drp-format/__tests__/composition-text.test.js +98 -0
- package/resolve-advanced/vendor/drp-format/__tests__/diff.test.js +272 -0
- package/resolve-advanced/vendor/drp-format/__tests__/effect-filters-compressed.test.js +143 -0
- package/resolve-advanced/vendor/drp-format/__tests__/fixtures/p0-3-session30-empty-effectfilters.drp +0 -0
- package/resolve-advanced/vendor/drp-format/__tests__/fixtures/retimed-timemap-50pct.hex +1 -0
- package/resolve-advanced/vendor/drp-format/__tests__/fixtures/retimed-timemap-dynamic.hex +1 -0
- package/resolve-advanced/vendor/drp-format/__tests__/inject-grades.test.js +238 -0
- package/resolve-advanced/vendor/drp-format/__tests__/keyed-dict.test.js +85 -0
- package/resolve-advanced/vendor/drp-format/__tests__/lut-refs.test.js +119 -0
- package/resolve-advanced/vendor/drp-format/__tests__/media-blobs.test.js +25 -0
- package/resolve-advanced/vendor/drp-format/__tests__/media-timemap.test.js +119 -0
- package/resolve-advanced/vendor/drp-format/__tests__/place-fusion-title.test.js +52 -0
- package/resolve-advanced/vendor/drp-format/__tests__/place-generator.test.js +40 -0
- package/resolve-advanced/vendor/drp-format/__tests__/place-transition.test.js +48 -0
- package/resolve-advanced/vendor/drp-format/__tests__/protobuf-wire.test.js +64 -0
- package/resolve-advanced/vendor/drp-format/__tests__/relink-media.test.js +106 -0
- package/resolve-advanced/vendor/drp-format/__tests__/splice-clips.test.js +256 -0
- package/resolve-advanced/vendor/drp-format/assemble-timeline.js +65 -0
- package/resolve-advanced/vendor/drp-format/author-project.js +118 -0
- package/resolve-advanced/vendor/drp-format/composition-text.js +213 -0
- package/resolve-advanced/vendor/drp-format/curves-encoder.js +763 -0
- package/resolve-advanced/vendor/drp-format/diff.js +310 -0
- package/resolve-advanced/vendor/drp-format/drp-packager.js +201 -0
- package/resolve-advanced/vendor/drp-format/drp-validator.js +809 -0
- package/resolve-advanced/vendor/drp-format/effect-encoder.js +640 -0
- package/resolve-advanced/vendor/drp-format/extract-lut-refs.js +119 -0
- package/resolve-advanced/vendor/drp-format/grade-encoder.example.js +133 -0
- package/resolve-advanced/vendor/drp-format/grade-encoder.js +401 -0
- package/resolve-advanced/vendor/drp-format/grade-encoder.test.js +171 -0
- package/resolve-advanced/vendor/drp-format/grade-encoder.verify.js +249 -0
- package/resolve-advanced/vendor/drp-format/grade-node-extractor.js +495 -0
- package/resolve-advanced/vendor/drp-format/grade-parameter-decoder.js +774 -0
- package/resolve-advanced/vendor/drp-format/index.js +174 -0
- package/resolve-advanced/vendor/drp-format/inject-grades.js +219 -0
- package/resolve-advanced/vendor/drp-format/keyed-dict.js +227 -0
- package/resolve-advanced/vendor/drp-format/marker-encoder.js +532 -0
- package/resolve-advanced/vendor/drp-format/media-blobs.js +53 -0
- package/resolve-advanced/vendor/drp-format/media-timemap.js +164 -0
- package/resolve-advanced/vendor/drp-format/mp-folder-builder.js +293 -0
- package/resolve-advanced/vendor/drp-format/node-tree-encoder.js +1246 -0
- package/resolve-advanced/vendor/drp-format/package.json +18 -0
- package/resolve-advanced/vendor/drp-format/place-fusion-title.js +131 -0
- package/resolve-advanced/vendor/drp-format/place-generator.js +77 -0
- package/resolve-advanced/vendor/drp-format/place-transition.js +91 -0
- package/resolve-advanced/vendor/drp-format/power-window-encoder.js +776 -0
- package/resolve-advanced/vendor/drp-format/protobuf-wire.js +111 -0
- package/resolve-advanced/vendor/drp-format/qualifier-encoder.js +706 -0
- package/resolve-advanced/vendor/drp-format/relink-media.js +218 -0
- package/resolve-advanced/vendor/drp-format/rich-title-encoder.js +447 -0
- package/resolve-advanced/vendor/drp-format/seq-container-builder.js +572 -0
- package/resolve-advanced/vendor/drp-format/seq-surgery.js +155 -0
- package/resolve-advanced/vendor/drp-format/splice-clips.js +445 -0
- package/resolve-advanced/vendor/drp-format/templates/empty-project.drp +0 -0
- package/resolve-advanced/vendor/drp-format/templates/fusion-title.xml +56 -0
- package/resolve-advanced/vendor/drp-format/templates/generator-solid-color.xml +21 -0
- package/resolve-advanced/vendor/drp-format/templates/media-clip-h264.drp +0 -0
- package/resolve-advanced/vendor/drp-format/templates/transition-cross-dissolve.xml +22 -0
- package/resolve-advanced/vendor/drp-format/tool-registry.descriptor.js +80 -0
- package/resolve-advanced/vendor/drp-format/utils/safe-archive.js +54 -0
- package/resolve-advanced/vendor/drp-format/xml-builder.js +759 -0
- package/resolve-advanced/vendor/drt-format/__tests__/_resolve-verify.js +21 -0
- package/resolve-advanced/vendor/drt-format/__tests__/build.test.js +113 -0
- package/resolve-advanced/vendor/drt-format/__tests__/multi-format.test.js +93 -0
- package/resolve-advanced/vendor/drt-format/__tests__/parse-real-resolve21.test.js +51 -0
- package/resolve-advanced/vendor/drt-format/__tests__/parse.test.js +134 -0
- package/resolve-advanced/vendor/drt-format/__tests__/resolve-versions.test.js +120 -0
- package/resolve-advanced/vendor/drt-format/__tests__/schema-fingerprint.test.js +62 -0
- package/resolve-advanced/vendor/drt-format/__tests__/smoke.test.js +27 -0
- package/resolve-advanced/vendor/drt-format/__tests__/validate.test.js +109 -0
- package/resolve-advanced/vendor/drt-format/capabilities.js +69 -0
- package/resolve-advanced/vendor/drt-format/capability-domains.js +56 -0
- package/resolve-advanced/vendor/drt-format/drt-builder.js +42 -0
- package/resolve-advanced/vendor/drt-format/drt-parser.js +164 -0
- package/resolve-advanced/vendor/drt-format/drt-validator.js +98 -0
- package/resolve-advanced/vendor/drt-format/index.js +45 -0
- package/resolve-advanced/vendor/drt-format/package.json +17 -0
- package/resolve-advanced/vendor/drt-format/resolve-versions.js +153 -0
- package/resolve-advanced/vendor/drt-format/schema-fingerprint.js +74 -0
- package/resolve-advanced/vendor/drt-format/templates/drt-project-shell.xml +124 -0
- package/resolve-advanced/vendor/drx-codec/__tests__/curves-roundtrip.test.js +148 -0
- package/resolve-advanced/vendor/drx-codec/__tests__/fixtures/p2-1-face-refinement.drx +58 -0
- package/resolve-advanced/vendor/drx-codec/__tests__/fixtures/p2-1-filmgrain.drx +58 -0
- package/resolve-advanced/vendor/drx-codec/__tests__/fixtures/p2-1-glow.drx +58 -0
- package/resolve-advanced/vendor/drx-codec/__tests__/fixtures/p2-1-lens-flare.drx +58 -0
- package/resolve-advanced/vendor/drx-codec/__tests__/fixtures/p2-3-beauty-25.drx +58 -0
- package/resolve-advanced/vendor/drx-codec/__tests__/fixtures/p2-3-beauty-75.drx +58 -0
- package/resolve-advanced/vendor/drx-codec/__tests__/fixtures/p5-1-node-no-lut.drx +58 -0
- package/resolve-advanced/vendor/drx-codec/__tests__/fixtures/p5-1-node-with-lut.drx +58 -0
- package/resolve-advanced/vendor/drx-codec/__tests__/hsl-curves-roundtrip.test.js +117 -0
- package/resolve-advanced/vendor/drx-codec/__tests__/lut-refs-roundtrip.test.js +112 -0
- package/resolve-advanced/vendor/drx-codec/__tests__/matte-roundtrip.test.js +167 -0
- package/resolve-advanced/vendor/drx-codec/__tests__/ofx-roundtrip.test.js +215 -0
- package/resolve-advanced/vendor/drx-codec/__tests__/ofx-slugs-discovery.test.js +149 -0
- package/resolve-advanced/vendor/drx-codec/__tests__/power-window-roundtrip.test.js +230 -0
- package/resolve-advanced/vendor/drx-codec/__tests__/qualifier-roundtrip.test.js +226 -0
- package/resolve-advanced/vendor/drx-codec/cdl-exporter.js +470 -0
- package/resolve-advanced/vendor/drx-codec/color-nlp-parser.js +833 -0
- package/resolve-advanced/vendor/drx-codec/data/color-nlp-action-mappings.json +2232 -0
- package/resolve-advanced/vendor/drx-codec/drx-generator.js +4123 -0
- package/resolve-advanced/vendor/drx-codec/drx-merger.js +320 -0
- package/resolve-advanced/vendor/drx-codec/drx-parser.js +1808 -0
- package/resolve-advanced/vendor/drx-codec/extract-custom-curves.js +215 -0
- package/resolve-advanced/vendor/drx-codec/extract-hsl-curves.js +180 -0
- package/resolve-advanced/vendor/drx-codec/extract-lut-refs.js +158 -0
- package/resolve-advanced/vendor/drx-codec/extract-matte-finesse.js +83 -0
- package/resolve-advanced/vendor/drx-codec/extract-ofx-params.js +226 -0
- package/resolve-advanced/vendor/drx-codec/extract-power-window.js +184 -0
- package/resolve-advanced/vendor/drx-codec/extract-qualifier.js +99 -0
- package/resolve-advanced/vendor/drx-codec/index.js +109 -0
- package/resolve-advanced/vendor/drx-codec/node-layout.js +249 -0
- package/resolve-advanced/vendor/drx-codec/resolved-drx-generator.js +393 -0
- package/resolve-advanced/vendor/drx-codec/tool-resolver.js +974 -0
- package/resolve-advanced/vendor/drx-codec/training-examples.js +548 -0
- package/resolve-advanced/vendor/drx-codec/vocabulary-intents.js +539 -0
- package/resolve-advanced/vendor/drx-parameters/CALIBRATION-STATUS.md +319 -0
- package/resolve-advanced/vendor/drx-parameters/DRX-VALUE-SCALING.md +251 -0
- package/resolve-advanced/vendor/drx-parameters/calibrated-ranges.json +17737 -0
- package/resolve-advanced/vendor/drx-parameters/corrector-types.js +120 -0
- package/resolve-advanced/vendor/drx-parameters/index.js +193 -0
- package/resolve-advanced/vendor/drx-parameters/parameter-codec.js +451 -0
- package/resolve-advanced/vendor/drx-parameters/parameter-ids.js +1292 -0
- package/resolve-advanced/vendor/drx-parameters/parameter-ranges.js +570 -0
- package/resolve-advanced/vendor/drx-parameters/parameter-validator.js +392 -0
- package/resolve-advanced/vendor/drx-parameters/resolvefx-registry.json +14973 -0
- package/resolve-advanced/vendor/drx-parameters/tool-registry.descriptor.js +38 -0
- package/resolve-advanced/vendor/drx-parameters/tools/drx-analyzer.js +371 -0
- package/resolve-advanced/vendor/fairlight/index.js +833 -0
- package/resolve-advanced/vendor/fusion-codec/composition-generator.js +401 -0
- package/resolve-advanced/vendor/fusion-codec/templates/blur-region.js +103 -0
- package/resolve-advanced/vendor/fusion-codec/templates/color-correct.js +87 -0
- package/resolve-advanced/vendor/fusion-codec/templates/film-grain.js +106 -0
- package/resolve-advanced/vendor/fusion-codec/templates/lower-third.js +241 -0
- package/resolve-advanced/vendor/fusion-codec/templates/picture-in-picture.js +188 -0
- package/resolve-advanced/vendor/fusion-codec/templates/text-overlay.js +161 -0
- package/resolve-advanced/vendor/fusion-codec/templates/title-card.js +184 -0
- package/resolve-advanced/vendor/fusion-codec/templates/vignette.js +107 -0
- package/resolve-advanced/vendor/fusion-codec/templates/watermark.js +101 -0
- package/scripts/agent-rules/README.md +68 -0
- package/src/analysis_dashboard.py +233 -1
- package/src/granular/common.py +1 -1
- package/src/server.py +479 -29
- package/src/utils/api_truth.py +117 -0
- package/src/utils/cut_ir.py +1 -1
- package/src/utils/failure_tracker.py +0 -2
- package/src/utils/timeline_xml.py +405 -0
|
@@ -0,0 +1,833 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Color Grading NLP Parser
|
|
3
|
+
*
|
|
4
|
+
* Natural language parser for color grading instructions.
|
|
5
|
+
* Uses comprehensive glossary and action mappings to interpret
|
|
6
|
+
* cinematographer/colorist directions into DaVinci Resolve parameters.
|
|
7
|
+
*
|
|
8
|
+
* @module drx/color-nlp-parser
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const fs = require('fs');
|
|
12
|
+
const path = require('path');
|
|
13
|
+
|
|
14
|
+
// Load action mappings
|
|
15
|
+
let ACTION_MAPPINGS = null;
|
|
16
|
+
let _customDataPath = null;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Set a custom data path for loading action mappings.
|
|
20
|
+
* Call before first parse to point at your app's knowledge directory.
|
|
21
|
+
* @param {string} dataPath - Absolute path to the directory containing color-nlp-action-mappings.json
|
|
22
|
+
*/
|
|
23
|
+
function setDataPath(dataPath) {
|
|
24
|
+
_customDataPath = dataPath;
|
|
25
|
+
ACTION_MAPPINGS = null; // force reload on next access
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function loadActionMappings() {
|
|
29
|
+
if (ACTION_MAPPINGS) return ACTION_MAPPINGS;
|
|
30
|
+
|
|
31
|
+
// Method 1: require() — works in Vercel serverless bundles and Node.js
|
|
32
|
+
// require() is resolved by bundlers (ncc, webpack) at build time,
|
|
33
|
+
// unlike fs.readFileSync which needs runtime path resolution.
|
|
34
|
+
try {
|
|
35
|
+
ACTION_MAPPINGS = require('./data/color-nlp-action-mappings.json');
|
|
36
|
+
return ACTION_MAPPINGS;
|
|
37
|
+
} catch {
|
|
38
|
+
// Not available as a require-able module
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Method 2: fs.readFileSync with path search (works in dev/Electron)
|
|
42
|
+
const searchPaths = [
|
|
43
|
+
_customDataPath ? path.join(_customDataPath, 'color-nlp-action-mappings.json') : null,
|
|
44
|
+
path.join(__dirname, 'data', 'color-nlp-action-mappings.json'),
|
|
45
|
+
].filter(Boolean);
|
|
46
|
+
|
|
47
|
+
for (const mappingsPath of searchPaths) {
|
|
48
|
+
try {
|
|
49
|
+
const content = fs.readFileSync(mappingsPath, 'utf8');
|
|
50
|
+
ACTION_MAPPINGS = JSON.parse(content);
|
|
51
|
+
return ACTION_MAPPINGS;
|
|
52
|
+
} catch {
|
|
53
|
+
// try next path
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
console.error('[NLP Parser] Failed to load action mappings from any known path');
|
|
58
|
+
return {
|
|
59
|
+
intent_classification: {},
|
|
60
|
+
phrase_to_action: {},
|
|
61
|
+
modifiers: { intensity: {}, scope: {} },
|
|
62
|
+
parameters: {},
|
|
63
|
+
synonyms: {},
|
|
64
|
+
problem_patterns: {},
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Normalize input text for matching
|
|
70
|
+
*/
|
|
71
|
+
function normalizeText(text) {
|
|
72
|
+
return text
|
|
73
|
+
.toLowerCase()
|
|
74
|
+
.trim()
|
|
75
|
+
.replace(/['']/g, "'")
|
|
76
|
+
.replace(/[""]/g, '"')
|
|
77
|
+
.replace(/\s+/g, ' ')
|
|
78
|
+
.replace(/[.,!?;:]+$/, ''); // Remove trailing punctuation
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Expand synonyms in input text
|
|
83
|
+
*/
|
|
84
|
+
function expandSynonyms(text, synonyms) {
|
|
85
|
+
let expanded = text;
|
|
86
|
+
for (const [canonical, alternatives] of Object.entries(synonyms)) {
|
|
87
|
+
for (const alt of alternatives) {
|
|
88
|
+
const regex = new RegExp(`\\b${alt}\\b`, 'gi');
|
|
89
|
+
if (regex.test(expanded)) {
|
|
90
|
+
// Don't replace, just note the canonical form
|
|
91
|
+
expanded = expanded.replace(regex, canonical);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return expanded;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Classify the intent of the input
|
|
100
|
+
*/
|
|
101
|
+
function classifyIntent(text, mappings) {
|
|
102
|
+
const normalized = normalizeText(text);
|
|
103
|
+
const intents = mappings.intent_classification;
|
|
104
|
+
|
|
105
|
+
const scores = {};
|
|
106
|
+
|
|
107
|
+
for (const [intentName, intentData] of Object.entries(intents)) {
|
|
108
|
+
let score = 0;
|
|
109
|
+
|
|
110
|
+
// Check keywords
|
|
111
|
+
if (intentData.keywords) {
|
|
112
|
+
for (const keyword of intentData.keywords) {
|
|
113
|
+
if (normalized.includes(keyword.toLowerCase())) {
|
|
114
|
+
score += 2;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Check regex patterns
|
|
120
|
+
if (intentData.regex_patterns) {
|
|
121
|
+
for (const pattern of intentData.regex_patterns) {
|
|
122
|
+
try {
|
|
123
|
+
const regex = new RegExp(pattern, 'i');
|
|
124
|
+
if (regex.test(normalized)) {
|
|
125
|
+
score += 5;
|
|
126
|
+
}
|
|
127
|
+
} catch (e) {
|
|
128
|
+
// Invalid regex, skip
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (score > 0) {
|
|
134
|
+
scores[intentName] = {
|
|
135
|
+
score,
|
|
136
|
+
requires_secondary: intentData.requires_secondary || false,
|
|
137
|
+
is_compound: intentData.is_compound || false,
|
|
138
|
+
primary_tools: intentData.primary_tools || [],
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Sort by score and return top intent(s)
|
|
144
|
+
const sorted = Object.entries(scores)
|
|
145
|
+
.sort((a, b) => b[1].score - a[1].score);
|
|
146
|
+
|
|
147
|
+
if (sorted.length === 0) {
|
|
148
|
+
return { primary: null, all: [] };
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return {
|
|
152
|
+
primary: sorted[0][0],
|
|
153
|
+
primaryData: sorted[0][1],
|
|
154
|
+
all: sorted.map(([name, data]) => ({ name, ...data })),
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Extract intensity modifier from input with emphatic language detection
|
|
160
|
+
*/
|
|
161
|
+
function extractIntensityModifier(text, mappings) {
|
|
162
|
+
const normalized = normalizeText(text);
|
|
163
|
+
const original = text; // Keep original for caps detection
|
|
164
|
+
const intensityMods = mappings.modifiers?.intensity || {};
|
|
165
|
+
|
|
166
|
+
let baseMultiplier = 1.0; // Default to significant (1.0)
|
|
167
|
+
let emphasisBoost = 0;
|
|
168
|
+
let matchedLevel = 'significant';
|
|
169
|
+
|
|
170
|
+
// === EMPHATIC LANGUAGE DETECTION ===
|
|
171
|
+
|
|
172
|
+
// 1. Check for ALL CAPS words (emphasis indicator)
|
|
173
|
+
const capsWords = original.match(/\b[A-Z]{2,}\b/g) || [];
|
|
174
|
+
const significantCapsWords = capsWords.filter(w =>
|
|
175
|
+
!['A', 'I', 'TV', 'OK', 'HD', 'SDR', 'HDR', 'RGB', 'LOG', 'LUT', 'DCI', 'REC'].includes(w)
|
|
176
|
+
);
|
|
177
|
+
if (significantCapsWords.length > 0) {
|
|
178
|
+
emphasisBoost += 0.2 * significantCapsWords.length;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// 2. Check for exclamation marks (! = +0.15, !! = +0.3, !!! = +0.5)
|
|
182
|
+
const exclamationCount = (original.match(/!/g) || []).length;
|
|
183
|
+
if (exclamationCount === 1) emphasisBoost += 0.15;
|
|
184
|
+
else if (exclamationCount === 2) emphasisBoost += 0.3;
|
|
185
|
+
else if (exclamationCount >= 3) emphasisBoost += 0.5;
|
|
186
|
+
|
|
187
|
+
// 3. Check for repetition patterns ("really really", "way way", "much much", "very very")
|
|
188
|
+
const repetitionPatterns = [
|
|
189
|
+
/\b(really|very|much|way|super|so|extra)\s+\1\b/gi,
|
|
190
|
+
/\b(really|very|much|way|super|so|extra)\s+(really|very|much|way|super|so|extra)\b/gi,
|
|
191
|
+
];
|
|
192
|
+
for (const pattern of repetitionPatterns) {
|
|
193
|
+
const matches = normalized.match(pattern) || [];
|
|
194
|
+
emphasisBoost += 0.25 * matches.length;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// 4. Check for stacked intensifiers ("really very", "super extremely", "way too much")
|
|
198
|
+
const stackedPatterns = [
|
|
199
|
+
/\b(really|very|super|extremely|incredibly|insanely)\s+(really|very|super|extremely|incredibly|insanely|much|more)\b/gi,
|
|
200
|
+
/\bway\s+too\s+(much|more|far)\b/gi,
|
|
201
|
+
/\bso\s+(much|very|incredibly)\b/gi,
|
|
202
|
+
];
|
|
203
|
+
for (const pattern of stackedPatterns) {
|
|
204
|
+
if (pattern.test(normalized)) {
|
|
205
|
+
emphasisBoost += 0.3;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// 5. Check for intensity amplifier words (cumulative!)
|
|
210
|
+
const intensityAmplifiers = {
|
|
211
|
+
// Tier 1: Mild amplifiers (+0.1 each)
|
|
212
|
+
mild: {
|
|
213
|
+
boost: 0.1,
|
|
214
|
+
words: ['pretty', 'quite', 'fairly', 'rather', 'somewhat', 'kinda', 'sorta', 'more']
|
|
215
|
+
},
|
|
216
|
+
// Tier 2: Moderate amplifiers (+0.15 each)
|
|
217
|
+
moderate: {
|
|
218
|
+
boost: 0.15,
|
|
219
|
+
words: ['very', 'really', 'definitely', 'certainly', 'clearly', 'noticeably', 'visibly', 'obviously', 'actually', 'truly', 'genuinely']
|
|
220
|
+
},
|
|
221
|
+
// Tier 3: Strong amplifiers (+0.2 each)
|
|
222
|
+
strong: {
|
|
223
|
+
boost: 0.2,
|
|
224
|
+
words: ['super', 'extra', 'hella', 'mad', 'wicked', 'damn', 'dang', 'bloody', 'friggin', 'freaking', 'frickin', 'heckin', 'real', 'proper', 'straight up', 'legit', 'lowkey', 'highkey', 'deadass']
|
|
225
|
+
},
|
|
226
|
+
// Tier 4: Very strong amplifiers (+0.25 each)
|
|
227
|
+
very_strong: {
|
|
228
|
+
boost: 0.25,
|
|
229
|
+
words: ['extremely', 'incredibly', 'seriously', 'majorly', 'heavily', 'intensely', 'severely', 'deeply', 'profoundly', 'remarkably', 'exceptionally', 'particularly', 'especially', 'significantly', 'substantially', 'considerably', 'dramatically']
|
|
230
|
+
},
|
|
231
|
+
// Tier 5: Extreme amplifiers (+0.35 each)
|
|
232
|
+
extreme: {
|
|
233
|
+
boost: 0.35,
|
|
234
|
+
words: ['ultra', 'mega', 'hyper', 'uber', 'turbo', 'giga', 'tera', 'maximum', 'max', 'peak', 'ultimate', 'supreme', 'paramount', 'radical', 'drastic', 'severe', 'massive', 'enormous', 'tremendous', 'immense', 'colossal', 'monumental', 'epic']
|
|
235
|
+
},
|
|
236
|
+
// Tier 6: Insane/absurd amplifiers (+0.45 each)
|
|
237
|
+
insane: {
|
|
238
|
+
boost: 0.45,
|
|
239
|
+
words: ['insanely', 'ridiculously', 'absurdly', 'outrageously', 'obscenely', 'ludicrously', 'preposterously', 'stupidly', 'crazy', 'bonkers', 'mental', 'nuts', 'bananas', 'wild', 'savage', 'brutal', 'beastly', 'godly', 'ungodly', 'otherworldly', 'astronomical']
|
|
240
|
+
},
|
|
241
|
+
// Tier 7: Nuclear/max amplifiers (+0.55 each)
|
|
242
|
+
nuclear: {
|
|
243
|
+
boost: 0.55,
|
|
244
|
+
words: ['nuclear', 'atomic', 'thermonuclear', 'apocalyptic', 'cataclysmic', 'earth-shattering', 'mind-blowing', 'face-melting', 'brain-melting', 'soul-crushing', 'maxed', 'cranked', 'slammed', 'pegged', 'pinned', 'redlined', 'balls to the wall', 'full send', 'all out', 'gonzo', 'off the charts', 'through the roof', 'to eleven', 'to the max', 'to the moon']
|
|
245
|
+
}
|
|
246
|
+
};
|
|
247
|
+
|
|
248
|
+
// Count all amplifier words (they stack!)
|
|
249
|
+
for (const [tier, data] of Object.entries(intensityAmplifiers)) {
|
|
250
|
+
for (const word of data.words) {
|
|
251
|
+
// Use word boundary matching for accuracy
|
|
252
|
+
const regex = new RegExp(`\\b${word.replace(/\s+/g, '\\s+')}\\b`, 'gi');
|
|
253
|
+
const matches = normalized.match(regex) || [];
|
|
254
|
+
emphasisBoost += data.boost * matches.length;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// 5b. Check for action/verb intensifiers (+0.3 each)
|
|
259
|
+
const actionIntensifiers = [
|
|
260
|
+
'crank', 'cranked', 'slam', 'slammed', 'blast', 'blasted', 'nuke', 'nuked',
|
|
261
|
+
'crush', 'crushed', 'smash', 'smashed', 'kill', 'killed', 'destroy', 'destroyed',
|
|
262
|
+
'hammer', 'hammered', 'pound', 'pounded', 'pump', 'pumped', 'jack', 'jacked',
|
|
263
|
+
'boost', 'boosted', 'amp', 'amped', 'juice', 'juiced', 'goose', 'goosed',
|
|
264
|
+
'ramp', 'ramped', 'dial', 'dialed', 'push', 'pushed', 'shove', 'shoved',
|
|
265
|
+
'yank', 'yanked', 'rip', 'ripped', 'tear', 'send', 'sent', 'launch', 'launched'
|
|
266
|
+
];
|
|
267
|
+
for (const word of actionIntensifiers) {
|
|
268
|
+
if (normalized.includes(word)) {
|
|
269
|
+
emphasisBoost += 0.3;
|
|
270
|
+
break; // Only count action verbs once
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// 5c. Check for "all the way" / "as X as possible" patterns
|
|
275
|
+
const maxPatterns = [
|
|
276
|
+
/\ball\s+the\s+way\b/gi,
|
|
277
|
+
/\bas\s+\w+\s+as\s+(?:possible|it\s+(?:can|will)\s+go|you\s+can)\b/gi,
|
|
278
|
+
/\bto\s+the\s+(?:max|limit|extreme|moon|stars)\b/gi,
|
|
279
|
+
/\b(?:full|max|complete|total)\s+(?:blast|power|throttle|strength|force|effect)\b/gi,
|
|
280
|
+
/\b(?:100|hundred)\s*(?:percent|%)\b/gi,
|
|
281
|
+
/\bgive\s+(?:it|me)\s+(?:everything|all\s+(?:of\s+it|you(?:'ve)?\s+got))\b/gi,
|
|
282
|
+
/\bdon'?t\s+hold\s+back\b/gi,
|
|
283
|
+
/\bgo\s+(?:hard|ham|crazy|nuts|wild|all\s+in|all\s+out|big)\b/gi,
|
|
284
|
+
/\blet\s+(?:it|her|'?er)\s+rip\b/gi,
|
|
285
|
+
];
|
|
286
|
+
for (const pattern of maxPatterns) {
|
|
287
|
+
if (pattern.test(normalized)) {
|
|
288
|
+
emphasisBoost += 0.4;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// 6. Check for diminutive patterns (reduce intensity)
|
|
293
|
+
const diminutivePatterns = [
|
|
294
|
+
/\bjust\s+a\s+(bit|touch|tad|hair|smidge|little)\b/gi,
|
|
295
|
+
/\bonly\s+(slightly|a\s+bit|a\s+touch)\b/gi,
|
|
296
|
+
/\bhardly\s+any\b/gi,
|
|
297
|
+
/\bbarely\s+(any|noticeable)\b/gi,
|
|
298
|
+
];
|
|
299
|
+
for (const pattern of diminutivePatterns) {
|
|
300
|
+
if (pattern.test(normalized)) {
|
|
301
|
+
emphasisBoost -= 0.4; // Reduce intensity
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// === FIND BASE INTENSITY FROM MAPPINGS ===
|
|
306
|
+
|
|
307
|
+
// Sort by multiplier descending so we match strongest first
|
|
308
|
+
const sortedIntensities = Object.entries(intensityMods)
|
|
309
|
+
.sort((a, b) => (b[1].multiplier || 0) - (a[1].multiplier || 0));
|
|
310
|
+
|
|
311
|
+
for (const [level, data] of sortedIntensities) {
|
|
312
|
+
// Check the level name itself
|
|
313
|
+
if (normalized.includes(level)) {
|
|
314
|
+
baseMultiplier = data.multiplier;
|
|
315
|
+
matchedLevel = level;
|
|
316
|
+
break;
|
|
317
|
+
}
|
|
318
|
+
// Check synonyms
|
|
319
|
+
if (data.synonyms) {
|
|
320
|
+
let found = false;
|
|
321
|
+
for (const syn of data.synonyms) {
|
|
322
|
+
if (normalized.includes(syn.toLowerCase())) {
|
|
323
|
+
baseMultiplier = data.multiplier;
|
|
324
|
+
matchedLevel = level;
|
|
325
|
+
found = true;
|
|
326
|
+
break;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
if (found) break;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// === COMBINE BASE + EMPHASIS ===
|
|
334
|
+
|
|
335
|
+
let finalMultiplier = baseMultiplier + emphasisBoost;
|
|
336
|
+
|
|
337
|
+
// Clamp to reasonable range (0.1 to 2.5)
|
|
338
|
+
finalMultiplier = Math.max(0.1, Math.min(2.5, finalMultiplier));
|
|
339
|
+
|
|
340
|
+
// Determine effective level based on final multiplier
|
|
341
|
+
let effectiveLevel = matchedLevel;
|
|
342
|
+
if (emphasisBoost > 0) {
|
|
343
|
+
if (finalMultiplier >= 2.0) effectiveLevel = 'nuclear';
|
|
344
|
+
else if (finalMultiplier >= 1.75) effectiveLevel = 'massive';
|
|
345
|
+
else if (finalMultiplier >= 1.5) effectiveLevel = 'extreme';
|
|
346
|
+
else if (finalMultiplier >= 1.35) effectiveLevel = 'heavy';
|
|
347
|
+
else if (finalMultiplier >= 1.2) effectiveLevel = 'bold';
|
|
348
|
+
} else if (emphasisBoost < 0) {
|
|
349
|
+
if (finalMultiplier <= 0.3) effectiveLevel = 'very_subtle';
|
|
350
|
+
else if (finalMultiplier <= 0.5) effectiveLevel = 'subtle';
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
return {
|
|
354
|
+
level: effectiveLevel,
|
|
355
|
+
baseLevel: matchedLevel,
|
|
356
|
+
multiplier: finalMultiplier,
|
|
357
|
+
emphasisBoost,
|
|
358
|
+
emphasisDetected: emphasisBoost !== 0,
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* Extract scope modifier from input
|
|
364
|
+
*/
|
|
365
|
+
function extractScopeModifier(text, mappings) {
|
|
366
|
+
const normalized = normalizeText(text);
|
|
367
|
+
const scopeMods = mappings.modifiers?.scope || {};
|
|
368
|
+
|
|
369
|
+
for (const [scopeName, data] of Object.entries(scopeMods)) {
|
|
370
|
+
// Check synonyms
|
|
371
|
+
if (data.synonyms) {
|
|
372
|
+
for (const syn of data.synonyms) {
|
|
373
|
+
if (normalized.includes(syn.toLowerCase())) {
|
|
374
|
+
return {
|
|
375
|
+
scope: scopeName,
|
|
376
|
+
target_range: data.target_range || null,
|
|
377
|
+
requires_secondary: data.requires_secondary || false,
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
// Default to global
|
|
385
|
+
return { scope: 'global', target_range: null, requires_secondary: false };
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* Find best matching phrase action
|
|
390
|
+
* Checks both phrase_to_action and compound_adjustments
|
|
391
|
+
*/
|
|
392
|
+
function findPhraseMatch(text, mappings) {
|
|
393
|
+
const normalized = normalizeText(text);
|
|
394
|
+
|
|
395
|
+
// Combine phrase_to_action and compound_adjustments into one lookup
|
|
396
|
+
const phrases = mappings.phrase_to_action || {};
|
|
397
|
+
const compounds = mappings.compound_adjustments || {};
|
|
398
|
+
|
|
399
|
+
// Convert compound_adjustments to same format as phrase_to_action
|
|
400
|
+
const allPhrases = { ...phrases };
|
|
401
|
+
for (const [phrase, data] of Object.entries(compounds)) {
|
|
402
|
+
if (!allPhrases[phrase]) {
|
|
403
|
+
allPhrases[phrase] = {
|
|
404
|
+
intent: data.intent || 'style',
|
|
405
|
+
is_compound: true,
|
|
406
|
+
actions: data.actions || [],
|
|
407
|
+
};
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
let bestMatch = null;
|
|
412
|
+
let bestScore = 0;
|
|
413
|
+
|
|
414
|
+
for (const [phrase, actionData] of Object.entries(allPhrases)) {
|
|
415
|
+
const normalizedPhrase = normalizeText(phrase);
|
|
416
|
+
|
|
417
|
+
// Exact match
|
|
418
|
+
if (normalized === normalizedPhrase) {
|
|
419
|
+
return { phrase, score: 100, exact: true, ...actionData };
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
// Contains match (phrase is in input)
|
|
423
|
+
if (normalized.includes(normalizedPhrase)) {
|
|
424
|
+
const score = (normalizedPhrase.length / normalized.length) * 80;
|
|
425
|
+
if (score > bestScore) {
|
|
426
|
+
bestScore = score;
|
|
427
|
+
bestMatch = { phrase, score, exact: false, ...actionData };
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
// Input contains phrase (for "make it look like X" patterns)
|
|
432
|
+
if (normalizedPhrase.length >= 3 && normalized.includes(normalizedPhrase)) {
|
|
433
|
+
const score = Math.min(90, normalizedPhrase.length * 5);
|
|
434
|
+
if (score > bestScore) {
|
|
435
|
+
bestScore = score;
|
|
436
|
+
bestMatch = { phrase, score, exact: false, ...actionData };
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
// Word overlap match
|
|
441
|
+
const phraseWords = normalizedPhrase.split(' ');
|
|
442
|
+
const inputWords = normalized.split(' ');
|
|
443
|
+
const overlap = phraseWords.filter(w => inputWords.includes(w)).length;
|
|
444
|
+
const overlapScore = (overlap / phraseWords.length) * 60;
|
|
445
|
+
|
|
446
|
+
if (overlapScore > bestScore && overlap >= 2) {
|
|
447
|
+
bestScore = overlapScore;
|
|
448
|
+
bestMatch = { phrase, score: overlapScore, exact: false, ...actionData };
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
return bestMatch;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
/**
|
|
456
|
+
* Detect problem patterns in input
|
|
457
|
+
*/
|
|
458
|
+
function detectProblemPattern(text, mappings) {
|
|
459
|
+
const normalized = normalizeText(text);
|
|
460
|
+
const patterns = mappings.problem_patterns || {};
|
|
461
|
+
|
|
462
|
+
for (const [problemName, data] of Object.entries(patterns)) {
|
|
463
|
+
if (data.indicators) {
|
|
464
|
+
for (const indicator of data.indicators) {
|
|
465
|
+
if (normalized.includes(indicator.toLowerCase())) {
|
|
466
|
+
return {
|
|
467
|
+
problem: problemName,
|
|
468
|
+
fix: data.fix,
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
return null;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
/**
|
|
479
|
+
* Parse color terms from input
|
|
480
|
+
*/
|
|
481
|
+
function parseColorTerms(text, mappings) {
|
|
482
|
+
const normalized = normalizeText(text);
|
|
483
|
+
const colorTerms = mappings.color_terms || {};
|
|
484
|
+
const found = [];
|
|
485
|
+
|
|
486
|
+
for (const [category, terms] of Object.entries(colorTerms)) {
|
|
487
|
+
for (const term of terms) {
|
|
488
|
+
if (normalized.includes(term.toLowerCase())) {
|
|
489
|
+
found.push({ term, category });
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
return found;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
/**
|
|
498
|
+
* Convert parsed result to interpreter-compatible format
|
|
499
|
+
*/
|
|
500
|
+
function toInterpreterFormat(parseResult) {
|
|
501
|
+
const params = {
|
|
502
|
+
temperature: 0,
|
|
503
|
+
tint: 0,
|
|
504
|
+
contrast: 0,
|
|
505
|
+
saturation: 0,
|
|
506
|
+
exposure: 0,
|
|
507
|
+
shadowLift: 0,
|
|
508
|
+
highlightCompression: 0,
|
|
509
|
+
midtoneDetail: 0,
|
|
510
|
+
pivot: 0.435,
|
|
511
|
+
explanation: '',
|
|
512
|
+
};
|
|
513
|
+
|
|
514
|
+
if (!parseResult.actions || parseResult.actions.length === 0) {
|
|
515
|
+
params.explanation = 'No actions matched';
|
|
516
|
+
return params;
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
const multiplier = parseResult.intensity?.multiplier || 1.0;
|
|
520
|
+
const explanations = [];
|
|
521
|
+
|
|
522
|
+
for (const action of parseResult.actions) {
|
|
523
|
+
const param = action.parameter;
|
|
524
|
+
const amount = (action.default_amount || 0) * multiplier;
|
|
525
|
+
|
|
526
|
+
// Map Resolve parameters to our simplified format
|
|
527
|
+
if (param.includes('temp')) {
|
|
528
|
+
// Temperature is in Kelvin-like units, convert to our -1 to 1 range
|
|
529
|
+
params.temperature = (amount / 1000) * (action.operation === 'decrease' ? -1 : 1);
|
|
530
|
+
explanations.push(`temperature ${action.operation}`);
|
|
531
|
+
} else if (param.includes('tint')) {
|
|
532
|
+
params.tint = (amount / 50) * (action.operation === 'decrease' ? -1 : 1);
|
|
533
|
+
explanations.push(`tint ${action.operation}`);
|
|
534
|
+
} else if (param.includes('contrast')) {
|
|
535
|
+
// TUNED: Production contrast multipliers average 1.18 (delta 0.18)
|
|
536
|
+
// Changed from /50 to /60 for more subtle, production-like adjustments
|
|
537
|
+
params.contrast = (amount / 60) * (action.operation === 'decrease' ? -1 : 1);
|
|
538
|
+
explanations.push(`contrast ${action.operation}`);
|
|
539
|
+
} else if (param.includes('saturation')) {
|
|
540
|
+
if (action.operation === 'set') {
|
|
541
|
+
params.saturation = (action.value - 50) / 50; // Convert 0-100 to -1 to 1
|
|
542
|
+
} else {
|
|
543
|
+
// TUNED: Production analysis shows 95th percentile saturation boost is 0.48 (1.48x)
|
|
544
|
+
// Changed from /25 to /35 for more natural, production-like adjustments
|
|
545
|
+
params.saturation = (amount / 35) * (action.operation === 'decrease' ? -1 : 1);
|
|
546
|
+
}
|
|
547
|
+
explanations.push(`saturation ${action.operation}`);
|
|
548
|
+
} else if (param.includes('offset.y') || param.includes('gamma.y') ||
|
|
549
|
+
(param.includes('offset') && !param.includes('.r') && !param.includes('.g') && !param.includes('.b'))) {
|
|
550
|
+
params.exposure += amount * (action.operation === 'decrease' ? -1 : 1);
|
|
551
|
+
explanations.push(`exposure ${action.operation}`);
|
|
552
|
+
} else if (param.includes('lift.y')) {
|
|
553
|
+
params.shadowLift = amount * (action.operation === 'decrease' ? -1 : 1);
|
|
554
|
+
explanations.push(`shadows ${action.operation}`);
|
|
555
|
+
} else if (param.includes('gain.y')) {
|
|
556
|
+
// Highlight adjustment via gain
|
|
557
|
+
if (action.operation === 'decrease') {
|
|
558
|
+
params.highlightCompression = Math.abs(amount);
|
|
559
|
+
}
|
|
560
|
+
explanations.push(`highlights ${action.operation}`);
|
|
561
|
+
} else if (param.includes('md')) {
|
|
562
|
+
params.midtoneDetail = (amount / 50) * (action.operation === 'decrease' ? -1 : 1);
|
|
563
|
+
explanations.push(`detail ${action.operation}`);
|
|
564
|
+
} else if (param.includes('color_boost')) {
|
|
565
|
+
// Color boost acts like saturation but preserves skin tones
|
|
566
|
+
// TUNED: Reduced from /50 to /70 to stay within production 95th percentile
|
|
567
|
+
params.saturation = (amount / 70) * (action.operation === 'decrease' ? -1 : 1);
|
|
568
|
+
explanations.push(`color boost ${action.operation}`);
|
|
569
|
+
} else if (param.includes('lift.r') || param.includes('lift.b') ||
|
|
570
|
+
param.includes('gain.r') || param.includes('gain.b')) {
|
|
571
|
+
// Color balance via wheels - convert to temperature/tint approximation
|
|
572
|
+
if (param.includes('.r') && param.includes('gain')) {
|
|
573
|
+
params.temperature += amount * 0.5 * (action.operation === 'decrease' ? -1 : 1);
|
|
574
|
+
}
|
|
575
|
+
if (param.includes('.b') && param.includes('lift')) {
|
|
576
|
+
params.temperature -= amount * 0.5 * (action.operation === 'decrease' ? -1 : 1);
|
|
577
|
+
}
|
|
578
|
+
explanations.push(`color balance adjusted`);
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
params.explanation = `NLP: ${parseResult.phrase || parseResult.intent} (${explanations.join(', ')})`;
|
|
583
|
+
|
|
584
|
+
// Clamp all values to valid ranges
|
|
585
|
+
params.temperature = Math.max(-1, Math.min(1, params.temperature));
|
|
586
|
+
params.tint = Math.max(-1, Math.min(1, params.tint));
|
|
587
|
+
params.contrast = Math.max(-1, Math.min(1, params.contrast));
|
|
588
|
+
params.saturation = Math.max(-1, Math.min(1, params.saturation));
|
|
589
|
+
params.exposure = Math.max(-1, Math.min(1, params.exposure));
|
|
590
|
+
params.shadowLift = Math.max(-1, Math.min(1, params.shadowLift));
|
|
591
|
+
params.highlightCompression = Math.max(0, Math.min(1, params.highlightCompression));
|
|
592
|
+
params.midtoneDetail = Math.max(-1, Math.min(1, params.midtoneDetail));
|
|
593
|
+
|
|
594
|
+
return params;
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
/**
|
|
598
|
+
* Main parse function
|
|
599
|
+
*
|
|
600
|
+
* @param {string} input - Natural language color grading instruction
|
|
601
|
+
* @returns {Object} - Parsed result with intent, actions, modifiers
|
|
602
|
+
*/
|
|
603
|
+
/**
|
|
604
|
+
* Build fallback actions from intent when no phrase matches.
|
|
605
|
+
* Uses the intent's primary_tools and keyword direction to generate
|
|
606
|
+
* reasonable default adjustments for single-word inputs.
|
|
607
|
+
*/
|
|
608
|
+
function buildFallbackActions(normalized, intentName, intentData, mappings) {
|
|
609
|
+
const actions = [];
|
|
610
|
+
|
|
611
|
+
// Determine direction from common keywords
|
|
612
|
+
const decreaseWords = /\b(less|reduce|remove|lower|cooler|colder|desaturate|flatten|softer|darker|dimmer|muted|dull|subtract)\b/;
|
|
613
|
+
const increaseWords = /\b(more|add|boost|increase|warmer|hotter|saturate|punch|brighter|lighter|vivid|rich|crispy|sharper)\b/;
|
|
614
|
+
const isDecrease = decreaseWords.test(normalized);
|
|
615
|
+
const isIncrease = increaseWords.test(normalized) || !isDecrease; // default to increase
|
|
616
|
+
|
|
617
|
+
const operation = isDecrease ? 'decrease' : 'increase';
|
|
618
|
+
|
|
619
|
+
// Default amounts per tool type (moderate adjustments)
|
|
620
|
+
const defaultAmounts = {
|
|
621
|
+
temp: 600,
|
|
622
|
+
tint: 15,
|
|
623
|
+
contrast: 12,
|
|
624
|
+
saturation: 15,
|
|
625
|
+
color_boost: 15,
|
|
626
|
+
md: 20,
|
|
627
|
+
shadows: 10,
|
|
628
|
+
highlights: 10,
|
|
629
|
+
exposure: 0.15,
|
|
630
|
+
lift: 0.03,
|
|
631
|
+
gamma: 0.02,
|
|
632
|
+
gain: 0.05,
|
|
633
|
+
offset: 0.02,
|
|
634
|
+
};
|
|
635
|
+
|
|
636
|
+
// Map intent primary_tools to parameter names and generate actions
|
|
637
|
+
for (const tool of intentData.primary_tools) {
|
|
638
|
+
// Only use the most relevant tool for single-word inputs
|
|
639
|
+
// For "warmer" → temp, for "contrast" → contrast, etc.
|
|
640
|
+
const toolLower = tool.toLowerCase();
|
|
641
|
+
|
|
642
|
+
// Check if the normalized input relates to this specific tool
|
|
643
|
+
const toolRelevant =
|
|
644
|
+
(toolLower.includes('temp') && /\b(warm|cool|cold|hot|golden|amber|orange|blue|ice|icy|tungsten|daylight|kelvin|temperature)\b/.test(normalized)) ||
|
|
645
|
+
(toolLower.includes('tint') && /\b(tint|green|magenta|pink)\b/.test(normalized)) ||
|
|
646
|
+
(toolLower.includes('contrast') && /\b(contrast|punch|punchy|flat|flatten|crispy|pop)\b/.test(normalized)) ||
|
|
647
|
+
(toolLower.includes('saturation') && /\b(saturat|desat|vivid|muted|dull|rich|vibran|color)\b/.test(normalized)) ||
|
|
648
|
+
(toolLower.includes('color_boost') && /\b(vibran|boost|color)\b/.test(normalized)) ||
|
|
649
|
+
(toolLower.includes('md') && /\b(detail|sharp|soft|clarity|texture)\b/.test(normalized)) ||
|
|
650
|
+
(toolLower.includes('exposure') || toolLower.includes('offset') || toolLower.includes('gamma')) &&
|
|
651
|
+
/\b(bright|dark|light|dim|expose|level)\b/.test(normalized);
|
|
652
|
+
|
|
653
|
+
if (toolRelevant) {
|
|
654
|
+
// Find the best matching default amount
|
|
655
|
+
let amount = 10; // generic fallback
|
|
656
|
+
for (const [key, val] of Object.entries(defaultAmounts)) {
|
|
657
|
+
if (toolLower.includes(key)) {
|
|
658
|
+
amount = val;
|
|
659
|
+
break;
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
actions.push({
|
|
664
|
+
parameter: `primaries.${tool}`,
|
|
665
|
+
operation,
|
|
666
|
+
default_amount: amount,
|
|
667
|
+
});
|
|
668
|
+
break; // Only one primary action for single-word inputs
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
// If no specific tool matched but we have an intent, use the first primary tool
|
|
673
|
+
if (actions.length === 0 && intentData.primary_tools.length > 0) {
|
|
674
|
+
const firstTool = intentData.primary_tools[0];
|
|
675
|
+
let amount = 10;
|
|
676
|
+
for (const [key, val] of Object.entries(defaultAmounts)) {
|
|
677
|
+
if (firstTool.toLowerCase().includes(key)) {
|
|
678
|
+
amount = val;
|
|
679
|
+
break;
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
actions.push({
|
|
683
|
+
parameter: `primaries.${firstTool}`,
|
|
684
|
+
operation,
|
|
685
|
+
default_amount: amount,
|
|
686
|
+
});
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
return actions;
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
function parse(input) {
|
|
693
|
+
const mappings = loadActionMappings();
|
|
694
|
+
const normalized = normalizeText(input);
|
|
695
|
+
|
|
696
|
+
// 1. Classify intent
|
|
697
|
+
const intent = classifyIntent(normalized, mappings);
|
|
698
|
+
|
|
699
|
+
// 2. Find phrase match
|
|
700
|
+
const phraseMatch = findPhraseMatch(normalized, mappings);
|
|
701
|
+
|
|
702
|
+
// 3. Extract modifiers
|
|
703
|
+
const intensity = extractIntensityModifier(normalized, mappings);
|
|
704
|
+
const scope = extractScopeModifier(normalized, mappings);
|
|
705
|
+
|
|
706
|
+
// 4. Detect problem patterns
|
|
707
|
+
const problem = detectProblemPattern(normalized, mappings);
|
|
708
|
+
|
|
709
|
+
// 5. Parse color terms
|
|
710
|
+
const colorTerms = parseColorTerms(normalized, mappings);
|
|
711
|
+
|
|
712
|
+
// 6. Build result
|
|
713
|
+
const result = {
|
|
714
|
+
input,
|
|
715
|
+
normalized,
|
|
716
|
+
intent: intent.primary,
|
|
717
|
+
intentData: intent.primaryData,
|
|
718
|
+
allIntents: intent.all,
|
|
719
|
+
phrase: phraseMatch?.phrase || null,
|
|
720
|
+
phraseScore: phraseMatch?.score || 0,
|
|
721
|
+
actions: phraseMatch?.actions || [],
|
|
722
|
+
workflow: phraseMatch?.workflow || null,
|
|
723
|
+
intensity,
|
|
724
|
+
scope,
|
|
725
|
+
problem,
|
|
726
|
+
colorTerms,
|
|
727
|
+
requires_secondary: phraseMatch?.requires_secondary || scope.requires_secondary || false,
|
|
728
|
+
is_compound: phraseMatch?.is_compound || false,
|
|
729
|
+
side_effects: phraseMatch?.side_effects || [],
|
|
730
|
+
alternatives: phraseMatch?.alternatives || [],
|
|
731
|
+
};
|
|
732
|
+
|
|
733
|
+
// If we have a problem pattern but no phrase match, use the problem fix
|
|
734
|
+
if (problem && !phraseMatch) {
|
|
735
|
+
result.actions = [problem.fix];
|
|
736
|
+
result.phrase = `fix: ${problem.problem}`;
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
// Intent-based fallback: when intent is detected but no phrase matched,
|
|
740
|
+
// generate default actions from the intent's primary tools and keywords.
|
|
741
|
+
// This handles single-word inputs like "warmer", "contrast", "desaturate"
|
|
742
|
+
// that don't match any full phrase in the phrase_to_action dictionary.
|
|
743
|
+
if (result.intent && result.actions.length === 0 && !problem) {
|
|
744
|
+
const intentData = mappings.intent_classification?.[result.intent];
|
|
745
|
+
if (intentData?.primary_tools) {
|
|
746
|
+
const fallbackActions = buildFallbackActions(normalized, result.intent, intentData, mappings);
|
|
747
|
+
if (fallbackActions.length > 0) {
|
|
748
|
+
result.actions = fallbackActions;
|
|
749
|
+
result.phrase = `intent-fallback: ${result.intent}`;
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
return result;
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
/**
|
|
758
|
+
* Parse and convert to interpreter format
|
|
759
|
+
*
|
|
760
|
+
* @param {string} input - Natural language input
|
|
761
|
+
* @returns {Object} - Parameters compatible with cinematographer-interpreter
|
|
762
|
+
*/
|
|
763
|
+
function parseToParams(input) {
|
|
764
|
+
const parseResult = parse(input);
|
|
765
|
+
return toInterpreterFormat(parseResult);
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
/**
|
|
769
|
+
* Get available actions for an intent
|
|
770
|
+
*/
|
|
771
|
+
function getActionsForIntent(intentName) {
|
|
772
|
+
const mappings = loadActionMappings();
|
|
773
|
+
const phrases = mappings.phrase_to_action || {};
|
|
774
|
+
|
|
775
|
+
return Object.entries(phrases)
|
|
776
|
+
.filter(([_, data]) => data.intent === intentName)
|
|
777
|
+
.map(([phrase, data]) => ({ phrase, ...data }));
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
/**
|
|
781
|
+
* Get all available intents
|
|
782
|
+
*/
|
|
783
|
+
function getAvailableIntents() {
|
|
784
|
+
const mappings = loadActionMappings();
|
|
785
|
+
return Object.keys(mappings.intent_classification || {});
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
/**
|
|
789
|
+
* Get parameter info
|
|
790
|
+
*/
|
|
791
|
+
function getParameterInfo(paramPath) {
|
|
792
|
+
const mappings = loadActionMappings();
|
|
793
|
+
return mappings.parameters?.[paramPath] || null;
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
/**
|
|
797
|
+
* Suggest completions for partial input
|
|
798
|
+
*/
|
|
799
|
+
function suggestCompletions(partialInput, limit = 5) {
|
|
800
|
+
const mappings = loadActionMappings();
|
|
801
|
+
const normalized = normalizeText(partialInput);
|
|
802
|
+
const phrases = Object.keys(mappings.phrase_to_action || {});
|
|
803
|
+
|
|
804
|
+
const suggestions = phrases
|
|
805
|
+
.filter(phrase => {
|
|
806
|
+
const normPhrase = normalizeText(phrase);
|
|
807
|
+
return normPhrase.includes(normalized) ||
|
|
808
|
+
normalized.split(' ').some(word => normPhrase.includes(word));
|
|
809
|
+
})
|
|
810
|
+
.slice(0, limit);
|
|
811
|
+
|
|
812
|
+
return suggestions;
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
module.exports = {
|
|
816
|
+
parse,
|
|
817
|
+
parseToParams,
|
|
818
|
+
classifyIntent,
|
|
819
|
+
findPhraseMatch,
|
|
820
|
+
extractIntensityModifier,
|
|
821
|
+
extractScopeModifier,
|
|
822
|
+
detectProblemPattern,
|
|
823
|
+
parseColorTerms,
|
|
824
|
+
toInterpreterFormat,
|
|
825
|
+
getActionsForIntent,
|
|
826
|
+
getAvailableIntents,
|
|
827
|
+
getParameterInfo,
|
|
828
|
+
suggestCompletions,
|
|
829
|
+
normalizeText,
|
|
830
|
+
expandSynonyms,
|
|
831
|
+
loadActionMappings,
|
|
832
|
+
setDataPath,
|
|
833
|
+
};
|