gitnexus 1.6.9 → 1.6.10-aptos.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/README.md +211 -53
- package/dist/_shared/graph/types.d.ts +67 -3
- package/dist/_shared/graph/types.d.ts.map +1 -1
- package/dist/_shared/index.d.ts +1 -0
- package/dist/_shared/index.d.ts.map +1 -1
- package/dist/_shared/index.js.map +1 -1
- package/dist/_shared/integrations/resilient-fetch.d.ts +3 -1
- package/dist/_shared/integrations/resilient-fetch.d.ts.map +1 -1
- package/dist/_shared/integrations/resilient-fetch.js +4 -3
- package/dist/_shared/integrations/resilient-fetch.js.map +1 -1
- package/dist/_shared/language-detection.d.ts.map +1 -1
- package/dist/_shared/language-detection.js +2 -0
- package/dist/_shared/language-detection.js.map +1 -1
- package/dist/_shared/languages.d.ts +2 -0
- package/dist/_shared/languages.d.ts.map +1 -1
- package/dist/_shared/languages.js +2 -0
- package/dist/_shared/languages.js.map +1 -1
- package/dist/_shared/lbug/schema-constants.d.ts +2 -2
- package/dist/_shared/lbug/schema-constants.d.ts.map +1 -1
- package/dist/_shared/lbug/schema-constants.js +8 -0
- package/dist/_shared/lbug/schema-constants.js.map +1 -1
- package/dist/_shared/pipeline.d.ts +1 -1
- package/dist/_shared/pipeline.d.ts.map +1 -1
- package/dist/_shared/scope-resolution/callable-flow-site.d.ts +110 -0
- package/dist/_shared/scope-resolution/callable-flow-site.d.ts.map +1 -0
- package/dist/_shared/scope-resolution/callable-flow-site.js +11 -0
- package/dist/_shared/scope-resolution/callable-flow-site.js.map +1 -0
- package/dist/_shared/scope-resolution/finalize-algorithm.d.ts +1 -1
- package/dist/_shared/scope-resolution/finalize-algorithm.d.ts.map +1 -1
- package/dist/_shared/scope-resolution/finalize-algorithm.js +1 -1
- package/dist/_shared/scope-resolution/finalize-algorithm.js.map +1 -1
- package/dist/_shared/scope-resolution/language-classification.d.ts.map +1 -1
- package/dist/_shared/scope-resolution/language-classification.js +1 -0
- package/dist/_shared/scope-resolution/language-classification.js.map +1 -1
- package/dist/_shared/scope-resolution/parsed-file.d.ts +7 -0
- package/dist/_shared/scope-resolution/parsed-file.d.ts.map +1 -1
- package/dist/_shared/scope-resolution/reference-site.d.ts +9 -1
- package/dist/_shared/scope-resolution/reference-site.d.ts.map +1 -1
- package/dist/_shared/scope-resolution/types.d.ts +20 -3
- package/dist/_shared/scope-resolution/types.d.ts.map +1 -1
- package/dist/cli/ai-context.d.ts +1 -1
- package/dist/cli/ai-context.js +25 -44
- package/dist/cli/analyze.d.ts +5 -2
- package/dist/cli/analyze.js +197 -11
- package/dist/cli/clean.js +17 -3
- package/dist/cli/cli-message.d.ts +1 -1
- package/dist/cli/doctor.d.ts +18 -0
- package/dist/cli/doctor.js +96 -5
- package/dist/cli/editor-targets.d.ts +17 -2
- package/dist/cli/editor-targets.js +44 -0
- package/dist/cli/embeddings.d.ts +12 -0
- package/dist/cli/embeddings.js +49 -0
- package/dist/cli/eval-server.d.ts +23 -1
- package/dist/cli/eval-server.js +126 -8
- package/dist/cli/help-i18n.js +6 -0
- package/dist/cli/i18n/en.d.ts +18 -8
- package/dist/cli/i18n/en.js +18 -8
- package/dist/cli/i18n/resources.d.ts +28 -8
- package/dist/cli/i18n/zh-CN.d.ts +10 -0
- package/dist/cli/i18n/zh-CN.js +18 -8
- package/dist/cli/index.js +21 -7
- package/dist/cli/lazy-action.d.ts +7 -0
- package/dist/cli/lazy-action.js +27 -0
- package/dist/cli/mcp.js +6 -3
- package/dist/cli/move-availability.d.ts +5 -0
- package/dist/cli/move-availability.js +11 -0
- package/dist/cli/setup.d.ts +8 -0
- package/dist/cli/setup.js +230 -32
- package/dist/cli/skill-gen.js +38 -18
- package/dist/cli/standard-skills.d.ts +76 -0
- package/dist/cli/standard-skills.js +45 -0
- package/dist/cli/status.d.ts +4 -1
- package/dist/cli/status.js +57 -4
- package/dist/cli/tool.js +11 -0
- package/dist/cli/uninstall.js +77 -18
- package/dist/cli/wiki.d.ts +1 -0
- package/dist/cli/wiki.js +7 -1
- package/dist/config/ignore-service.d.ts +2 -0
- package/dist/config/ignore-service.js +27 -0
- package/dist/core/analysis-features.d.ts +21 -0
- package/dist/core/analysis-features.js +59 -0
- package/dist/core/analyzer-identity.d.ts +74 -0
- package/dist/core/analyzer-identity.js +1820 -0
- package/dist/core/augmentation/engine.js +13 -8
- package/dist/core/embeddings/embedder.d.ts +3 -2
- package/dist/core/embeddings/embedder.js +24 -7
- package/dist/core/embeddings/embedding-identity.d.ts +11 -0
- package/dist/core/embeddings/embedding-identity.js +24 -0
- package/dist/core/embeddings/embedding-pipeline.d.ts +36 -1
- package/dist/core/embeddings/embedding-pipeline.js +100 -9
- package/dist/core/embeddings/http-client.d.ts +33 -3
- package/dist/core/embeddings/http-client.js +237 -25
- package/dist/core/embeddings/node-module-compat.d.ts +25 -0
- package/dist/core/embeddings/node-module-compat.js +25 -0
- package/dist/core/embeddings/onnxruntime-common-resolver.js +8 -5
- package/dist/core/embeddings/onnxruntime-node-resolver.js +33 -7
- package/dist/core/embeddings/runtime-install.d.ts +119 -0
- package/dist/core/embeddings/runtime-install.js +372 -0
- package/dist/core/embeddings/runtime-support.d.ts +48 -17
- package/dist/core/embeddings/runtime-support.js +96 -0
- package/dist/core/git-staleness.js +1 -1
- package/dist/core/group/bridge-db.js +2 -0
- package/dist/core/group/extractors/http-patterns/python.js +246 -108
- package/dist/core/group/extractors/manifest-extractor.js +4 -0
- package/dist/core/incremental/escalation-gate.d.ts +38 -0
- package/dist/core/incremental/escalation-gate.js +48 -0
- package/dist/core/incremental/shadow-candidates.d.ts +3 -3
- package/dist/core/incremental/shadow-candidates.js +3 -3
- package/dist/core/incremental/subgraph-extract.d.ts +2 -2
- package/dist/core/incremental/subgraph-extract.js +2 -2
- package/dist/core/index-freshness.d.ts +5 -0
- package/dist/core/index-freshness.js +13 -0
- package/dist/core/ingestion/class-extractors/configs/jvm.js +29 -0
- package/dist/core/ingestion/cobol/cobol-preprocessor.js +1 -1
- package/dist/core/ingestion/cobol/jcl-processor.js +9 -8
- package/dist/core/ingestion/cobol-processor.js +27 -26
- package/dist/core/ingestion/community-processor.d.ts +51 -1
- package/dist/core/ingestion/community-processor.js +323 -64
- package/dist/core/ingestion/emit-references.js +7 -2
- package/dist/core/ingestion/filesystem-walker.js +4 -0
- package/dist/core/ingestion/frameworks/spring/analysis-features.d.ts +3 -0
- package/dist/core/ingestion/frameworks/spring/analysis-features.js +7 -0
- package/dist/core/ingestion/frameworks/spring/bean-candidates.d.ts +30 -0
- package/dist/core/ingestion/frameworks/spring/bean-candidates.js +182 -0
- package/dist/core/ingestion/frameworks/spring/bean-catalog.d.ts +12 -0
- package/dist/core/ingestion/frameworks/spring/bean-catalog.js +26 -0
- package/dist/core/ingestion/frameworks/spring/config-bindings.d.ts +24 -0
- package/dist/core/ingestion/frameworks/spring/config-bindings.js +115 -0
- package/dist/core/ingestion/languages/c/captures.js +56 -0
- package/dist/core/ingestion/languages/c/query.js +17 -0
- package/dist/core/ingestion/languages/c/scope-resolver.js +6 -0
- package/dist/core/ingestion/languages/cobol/captures.js +93 -0
- package/dist/core/ingestion/languages/cobol/scope-resolver.js +7 -0
- package/dist/core/ingestion/languages/cpp/captures.js +365 -75
- package/dist/core/ingestion/languages/cpp/scope-resolver.js +14 -0
- package/dist/core/ingestion/languages/csharp/captures.js +25 -0
- package/dist/core/ingestion/languages/dart/captures.js +90 -2
- package/dist/core/ingestion/languages/dart/extension-type-preprocess.d.ts +7 -0
- package/dist/core/ingestion/languages/dart/extension-type-preprocess.js +30 -0
- package/dist/core/ingestion/languages/dart.js +2 -0
- package/dist/core/ingestion/languages/go/captures.js +34 -0
- package/dist/core/ingestion/languages/index.d.ts +1 -0
- package/dist/core/ingestion/languages/index.js +2 -0
- package/dist/core/ingestion/languages/java/analysis-features.d.ts +3 -0
- package/dist/core/ingestion/languages/java/analysis-features.js +13 -0
- package/dist/core/ingestion/languages/java/capture-side-channel.d.ts +22 -0
- package/dist/core/ingestion/languages/java/capture-side-channel.js +58 -0
- package/dist/core/ingestion/languages/java/captures.d.ts +4 -3
- package/dist/core/ingestion/languages/java/captures.js +193 -17
- package/dist/core/ingestion/languages/java/package-facts.d.ts +5 -0
- package/dist/core/ingestion/languages/java/package-facts.js +9 -0
- package/dist/core/ingestion/languages/java/package-siblings.d.ts +3 -16
- package/dist/core/ingestion/languages/java/package-siblings.js +8 -147
- package/dist/core/ingestion/languages/java/query.js +23 -0
- package/dist/core/ingestion/languages/java/scope-resolver.js +23 -0
- package/dist/core/ingestion/languages/java/spring-bean-metadata.d.ts +2 -0
- package/dist/core/ingestion/languages/java/spring-bean-metadata.js +8 -0
- package/dist/core/ingestion/languages/java/spring-config-bindings.d.ts +23 -0
- package/dist/core/ingestion/languages/java/spring-config-bindings.js +215 -0
- package/dist/core/ingestion/languages/java.js +3 -0
- package/dist/core/ingestion/languages/javascript/captures.js +16 -0
- package/dist/core/ingestion/languages/javascript/query.js +21 -0
- package/dist/core/ingestion/languages/jvm/package-facts.d.ts +35 -0
- package/dist/core/ingestion/languages/jvm/package-facts.js +40 -0
- package/dist/core/ingestion/languages/jvm/package-siblings.d.ts +14 -0
- package/dist/core/ingestion/languages/jvm/package-siblings.js +129 -0
- package/dist/core/ingestion/languages/kotlin/capture-side-channel.d.ts +17 -3
- package/dist/core/ingestion/languages/kotlin/capture-side-channel.js +42 -8
- package/dist/core/ingestion/languages/kotlin/captures.js +59 -0
- package/dist/core/ingestion/languages/kotlin/package-facts.d.ts +5 -0
- package/dist/core/ingestion/languages/kotlin/package-facts.js +9 -0
- package/dist/core/ingestion/languages/kotlin/package-siblings.d.ts +4 -0
- package/dist/core/ingestion/languages/kotlin/package-siblings.js +8 -0
- package/dist/core/ingestion/languages/kotlin/query.js +19 -0
- package/dist/core/ingestion/languages/kotlin/scope-resolver.js +9 -1
- package/dist/core/ingestion/languages/kotlin/spring-bean-metadata.d.ts +2 -0
- package/dist/core/ingestion/languages/kotlin/spring-bean-metadata.js +8 -0
- package/dist/core/ingestion/languages/kotlin.js +5 -6
- package/dist/core/ingestion/languages/move.d.ts +1 -0
- package/dist/core/ingestion/languages/move.js +27 -0
- package/dist/core/ingestion/languages/php/captures.js +40 -0
- package/dist/core/ingestion/languages/php/import-decomposer.js +12 -0
- package/dist/core/ingestion/languages/php/import-target.d.ts +2 -1
- package/dist/core/ingestion/languages/php/import-target.js +110 -2
- package/dist/core/ingestion/languages/php/interpret.js +10 -0
- package/dist/core/ingestion/languages/php/scope-resolver.js +1 -1
- package/dist/core/ingestion/languages/python/captures.d.ts +3 -4
- package/dist/core/ingestion/languages/python/captures.js +24 -5
- package/dist/core/ingestion/languages/python/interpret.js +4 -0
- package/dist/core/ingestion/languages/python/receiver-binding.d.ts +15 -2
- package/dist/core/ingestion/languages/python/receiver-binding.js +96 -2
- package/dist/core/ingestion/languages/python/simple-hooks.d.ts +5 -5
- package/dist/core/ingestion/languages/python/simple-hooks.js +15 -5
- package/dist/core/ingestion/languages/ruby/captures.js +42 -0
- package/dist/core/ingestion/languages/rust/captures.js +13 -0
- package/dist/core/ingestion/languages/rust/interpret.js +18 -0
- package/dist/core/ingestion/languages/rust/query.js +9 -0
- package/dist/core/ingestion/languages/rust/range-binding.js +6 -2
- package/dist/core/ingestion/languages/swift/captures.js +12 -0
- package/dist/core/ingestion/languages/typescript/captures.js +21 -0
- package/dist/core/ingestion/languages/typescript/nuxt-auto-imports.js +2 -1
- package/dist/core/ingestion/languages/typescript/query.js +37 -0
- package/dist/core/ingestion/markdown-processor.js +3 -2
- package/dist/core/ingestion/model/registration-table.js +1 -0
- package/dist/core/ingestion/parsing-processor.d.ts +3 -1
- package/dist/core/ingestion/parsing-processor.js +36 -1
- package/dist/core/ingestion/pipeline-phases/index.d.ts +2 -0
- package/dist/core/ingestion/pipeline-phases/index.js +2 -0
- package/dist/core/ingestion/pipeline-phases/parse-impl.js +56 -2
- package/dist/core/ingestion/pipeline-phases/parse.d.ts +0 -2
- package/dist/core/ingestion/pipeline-phases/parse.js +12 -3
- package/dist/core/ingestion/pipeline-phases/processes.d.ts +8 -0
- package/dist/core/ingestion/pipeline-phases/processes.js +11 -1
- package/dist/core/ingestion/pipeline-phases/spring-config.d.ts +37 -0
- package/dist/core/ingestion/pipeline-phases/spring-config.js +433 -0
- package/dist/core/ingestion/pipeline-phases/standalone-ingest.d.ts +10 -0
- package/dist/core/ingestion/pipeline-phases/standalone-ingest.js +6 -0
- package/dist/core/ingestion/pipeline.d.ts +4 -2
- package/dist/core/ingestion/pipeline.js +5 -2
- package/dist/core/ingestion/resolve-references.js +12 -0
- package/dist/core/ingestion/route-extractors/constant-resolver.d.ts +83 -0
- package/dist/core/ingestion/route-extractors/constant-resolver.js +131 -0
- package/dist/core/ingestion/route-extractors/python-const-resolver.d.ts +75 -0
- package/dist/core/ingestion/route-extractors/python-const-resolver.js +299 -0
- package/dist/core/ingestion/scope-extractor.js +306 -43
- package/dist/core/ingestion/scope-resolution/contract/scope-resolver.d.ts +71 -2
- package/dist/core/ingestion/scope-resolution/graph-bridge/callee-id-sink.d.ts +7 -7
- package/dist/core/ingestion/scope-resolution/graph-bridge/callee-id-sink.js +8 -7
- package/dist/core/ingestion/scope-resolution/graph-bridge/edges.d.ts +3 -1
- package/dist/core/ingestion/scope-resolution/graph-bridge/edges.js +6 -0
- package/dist/core/ingestion/scope-resolution/graph-bridge/ids.js +1 -0
- package/dist/core/ingestion/scope-resolution/graph-bridge/node-lookup.js +4 -1
- package/dist/core/ingestion/scope-resolution/graph-bridge/references-to-edges.js +7 -2
- package/dist/core/ingestion/scope-resolution/passes/callable-value-flow.d.ts +47 -0
- package/dist/core/ingestion/scope-resolution/passes/callable-value-flow.js +1138 -0
- package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.d.ts +16 -4
- package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.js +97 -1
- package/dist/core/ingestion/scope-resolution/passes/property-dispatch.d.ts +60 -0
- package/dist/core/ingestion/scope-resolution/passes/property-dispatch.js +111 -0
- package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.d.ts +4 -3
- package/dist/core/ingestion/scope-resolution/pipeline/phase.d.ts +5 -0
- package/dist/core/ingestion/scope-resolution/pipeline/phase.js +25 -38
- package/dist/core/ingestion/scope-resolution/pipeline/run.d.ts +6 -0
- package/dist/core/ingestion/scope-resolution/pipeline/run.js +147 -35
- package/dist/core/ingestion/scope-resolution/resolution-outcome.d.ts +1 -1
- package/dist/core/ingestion/scope-resolution/scope/walkers.js +73 -44
- package/dist/core/ingestion/taint/typescript-model.js +34 -2
- package/dist/core/ingestion/tree-sitter-queries.d.ts +2 -2
- package/dist/core/ingestion/tree-sitter-queries.js +23 -2
- package/dist/core/ingestion/type-extractors/jvm.js +17 -2
- package/dist/core/ingestion/utils/ast-helpers.d.ts +1 -0
- package/dist/core/ingestion/utils/ast-helpers.js +153 -2
- package/dist/core/ingestion/utils/callable-flow-captures.d.ts +94 -0
- package/dist/core/ingestion/utils/callable-flow-captures.js +878 -0
- package/dist/core/ingestion/utils/line-base.d.ts +20 -0
- package/dist/core/ingestion/utils/line-base.js +20 -0
- package/dist/core/ingestion/utils/symbol-labels.d.ts +21 -0
- package/dist/core/ingestion/utils/symbol-labels.js +45 -0
- package/dist/core/ingestion/workers/parse-worker.d.ts +34 -0
- package/dist/core/ingestion/workers/parse-worker.js +40 -5
- package/dist/core/ingestion/workers/result-merge.js +4 -0
- package/dist/core/ingestion/workers/worker-pool.d.ts +28 -0
- package/dist/core/ingestion/workers/worker-pool.js +128 -28
- package/dist/core/lbug/csv-generator.d.ts +15 -0
- package/dist/core/lbug/csv-generator.js +124 -27
- package/dist/core/lbug/cypher-escape.d.ts +20 -0
- package/dist/core/lbug/cypher-escape.js +20 -0
- package/dist/core/lbug/extension-load-error.d.ts +67 -0
- package/dist/core/lbug/extension-load-error.js +326 -0
- package/dist/core/lbug/extension-loader.d.ts +17 -2
- package/dist/core/lbug/extension-loader.js +38 -13
- package/dist/core/lbug/lbug-adapter.d.ts +203 -2
- package/dist/core/lbug/lbug-adapter.js +527 -86
- package/dist/core/lbug/lbug-config.d.ts +56 -2
- package/dist/core/lbug/lbug-config.js +267 -7
- package/dist/core/lbug/move-columns.d.ts +7 -0
- package/dist/core/lbug/move-columns.js +86 -0
- package/dist/core/lbug/native-check.d.ts +40 -0
- package/dist/core/lbug/native-check.js +90 -0
- package/dist/core/lbug/node-table-layout.d.ts +29 -0
- package/dist/core/lbug/node-table-layout.js +119 -0
- package/dist/core/lbug/pool-adapter.d.ts +23 -1
- package/dist/core/lbug/pool-adapter.js +115 -8
- package/dist/core/lbug/schema.d.ts +4 -3
- package/dist/core/lbug/schema.js +16 -16
- package/dist/core/lbug/sidecar-recovery.d.ts +172 -0
- package/dist/core/lbug/sidecar-recovery.js +418 -16
- package/dist/core/lbug/wal-checkpoint-driver.js +3 -0
- package/dist/core/move/artifact-download.d.ts +19 -0
- package/dist/core/move/artifact-download.js +179 -0
- package/dist/core/move/compiler-facts.d.ts +120 -0
- package/dist/core/move/compiler-facts.js +9 -0
- package/dist/core/move/consistency.d.ts +28 -0
- package/dist/core/move/consistency.js +98 -0
- package/dist/core/move/constants.d.ts +98 -0
- package/dist/core/move/constants.js +136 -0
- package/dist/core/move/discovery.d.ts +10 -0
- package/dist/core/move/discovery.js +22 -0
- package/dist/core/move/entry-points.d.ts +14 -0
- package/dist/core/move/entry-points.js +40 -0
- package/dist/core/move/facts-mapper.d.ts +75 -0
- package/dist/core/move/facts-mapper.js +534 -0
- package/dist/core/move/install-lock.d.ts +14 -0
- package/dist/core/move/install-lock.js +102 -0
- package/dist/core/move/install.d.ts +39 -0
- package/dist/core/move/install.js +391 -0
- package/dist/core/move/mcp-client.d.ts +115 -0
- package/dist/core/move/mcp-client.js +436 -0
- package/dist/core/move/move-ingest.d.ts +49 -0
- package/dist/core/move/move-ingest.js +320 -0
- package/dist/core/move/provision.d.ts +19 -0
- package/dist/core/move/provision.js +91 -0
- package/dist/core/move/release.d.ts +6 -0
- package/dist/core/move/release.js +10 -0
- package/dist/core/move/symbol-id.d.ts +35 -0
- package/dist/core/move/symbol-id.js +65 -0
- package/dist/core/move/type-parser.d.ts +11 -0
- package/dist/core/move/type-parser.js +38 -0
- package/dist/core/platform/capabilities.d.ts +0 -1
- package/dist/core/platform/capabilities.js +39 -8
- package/dist/core/run-analyze.d.ts +3 -3
- package/dist/core/run-analyze.js +1001 -184
- package/dist/core/search/fts-indexes.d.ts +31 -0
- package/dist/core/search/fts-indexes.js +73 -0
- package/dist/core/search/fts-schema.js +2 -0
- package/dist/core/tree-sitter/safe-parse.d.ts +8 -3
- package/dist/core/tree-sitter/safe-parse.js +21 -7
- package/dist/core/wiki/graph-queries.js +6 -5
- package/dist/core/wiki/llm-client.d.ts +8 -2
- package/dist/core/wiki/llm-client.js +41 -5
- package/dist/mcp/core/embedder.js +16 -2
- package/dist/mcp/http-transport.d.ts +5 -0
- package/dist/mcp/http-transport.js +19 -5
- package/dist/mcp/local/bean-metadata.d.ts +2 -0
- package/dist/mcp/local/bean-metadata.js +25 -0
- package/dist/mcp/local/line-display.d.ts +22 -0
- package/dist/mcp/local/line-display.js +3 -0
- package/dist/mcp/local/local-backend.d.ts +19 -1
- package/dist/mcp/local/local-backend.js +402 -155
- package/dist/mcp/local/pdg-impact.d.ts +5 -3
- package/dist/mcp/local/pdg-impact.js +5 -2
- package/dist/mcp/output-budget.d.ts +5 -0
- package/dist/mcp/output-budget.js +52 -0
- package/dist/mcp/read-only-policy.d.ts +12 -0
- package/dist/mcp/read-only-policy.js +102 -0
- package/dist/mcp/repository-policy.d.ts +34 -0
- package/dist/mcp/repository-policy.js +328 -0
- package/dist/mcp/resources.js +32 -5
- package/dist/mcp/server.d.ts +5 -2
- package/dist/mcp/server.js +29 -9
- package/dist/mcp/tools.d.ts +0 -8
- package/dist/mcp/tools.js +102 -5
- package/dist/server/analyze-job.d.ts +3 -0
- package/dist/server/analyze-job.js +17 -0
- package/dist/server/analyze-launch.d.ts +6 -0
- package/dist/server/analyze-launch.js +82 -6
- package/dist/server/analyze-worker-core.d.ts +2 -1
- package/dist/server/analyze-worker-core.js +5 -2
- package/dist/server/analyze-worker.js +29 -6
- package/dist/server/api.d.ts +30 -0
- package/dist/server/api.js +120 -34
- package/dist/server/mcp-http.d.ts +1 -1
- package/dist/server/mcp-http.js +4 -2
- package/dist/server/upload-ingest.js +2 -1
- package/dist/server/validation.js +2 -1
- package/dist/storage/git.d.ts +31 -0
- package/dist/storage/git.js +111 -1
- package/dist/storage/parse-cache.js +7 -1
- package/dist/storage/parsedfile-store.d.ts +8 -0
- package/dist/storage/parsedfile-store.js +165 -1
- package/dist/storage/repo-manager.d.ts +194 -2
- package/dist/storage/repo-manager.js +56 -1
- package/hooks/antigravity/gitnexus-antigravity-hook.cjs +50 -3
- package/hooks/claude/gitnexus-hook.cjs +59 -9
- package/hooks/claude/pre-tool-use.sh +0 -0
- package/hooks/claude/session-start.sh +0 -0
- package/package.json +21 -15
- package/scripts/cross-platform-tests.ts +56 -0
- package/scripts/ensure-fts.ts +43 -0
- package/scripts/install-duckdb-extension.mjs +85 -24
- package/scripts/run-cross-platform.ts +61 -6
- package/scripts/shard-arg.ts +30 -0
- package/scripts/sync-plugin-manifests.mjs +192 -0
- package/skills/gitnexus-lfg/README.md +55 -0
- package/skills/gitnexus-lfg/SKILL.md +86 -0
- package/skills/gitnexus-plan/README.md +142 -0
- package/skills/gitnexus-plan/SKILL.md +348 -0
- package/skills/gitnexus-plan/references/context-ledger.md +137 -0
- package/skills/gitnexus-plan/references/context-pack.md +126 -0
- package/skills/gitnexus-plan/references/evidence-provenance.md +272 -0
- package/skills/gitnexus-plan/references/pdg-slice.md +109 -0
- package/skills/gitnexus-plan/references/plan-template.md +201 -0
- package/skills/gitnexus-plan/scripts/evidence-provenance.mjs +2084 -0
- package/skills/gitnexus-review/SKILL.md +273 -0
- package/skills/gitnexus-review/ci-personas/ci-adversarial-lens.md +42 -0
- package/skills/gitnexus-review/ci-personas/ci-blast-radius-lens.md +39 -0
- package/skills/gitnexus-review/ci-personas/ci-correctness-lens.md +37 -0
- package/skills/gitnexus-review/ci-personas/ci-coverage-lens.md +40 -0
- package/skills/gitnexus-review/ci-personas/ci-critic-lens.md +42 -0
- package/skills/gitnexus-review/ci-personas/ci-security-lens.md +39 -0
- package/skills/gitnexus-work/README.md +71 -0
- package/skills/gitnexus-work/SKILL.md +269 -0
- package/skills/gitnexus-work/references/evidence-provenance.md +272 -0
- package/skills/gitnexus-work/scripts/evidence-provenance.mjs +2084 -0
- package/web/assets/ProcessFlowModal-B_bfBySy.js +22 -0
- package/web/assets/__vite-browser-external-bMKyYQkO.js +1 -0
- package/web/assets/agent-Bqxn-abU.js +626 -0
- package/web/assets/architecture-7EHR7CIX-6QZW5X65-BVWFvYz2.js +1 -0
- package/web/assets/architectureDiagram-UL44E2DR-CmG3uPWf.js +36 -0
- package/web/assets/{blockDiagram-7IZFK4PR-BkWhpzWB.js → blockDiagram-7IZFK4PR-DBefcjof.js} +7 -7
- package/web/assets/{c4Diagram-Y2BXMSZH-DtBvpzWD.js → c4Diagram-Y2BXMSZH-EjWnjEJl.js} +6 -6
- package/web/assets/chunk-2T2R6R2M-Bb6Sy3_j.js +4 -0
- package/web/assets/chunk-2UTLFMKG-CXlhF3Pt.js +1 -0
- package/web/assets/chunk-3SSMPTDK-rPsRM1x0.js +321 -0
- package/web/assets/chunk-4R4BOZG6-Be_F0JoX.js +159 -0
- package/web/assets/{chunk-6764PJDD-DpIS7hxD.js → chunk-6764PJDD-C7xxk063.js} +1 -1
- package/web/assets/chunk-67TQ5CYL-CA7OhIEf.js +124 -0
- package/web/assets/chunk-7FYTHRHK-CsmYIswB.js +32 -0
- package/web/assets/chunk-7J6CGLKN-BlKwgXKs.js +10 -0
- package/web/assets/chunk-7W6UQGC5-pyKGssV3.js +1 -0
- package/web/assets/chunk-C62D2QBJ-3gdL8EKc.js +1 -0
- package/web/assets/chunk-CEXFNPSA-CjwtMDkc.js +1 -0
- package/web/assets/{chunk-INKRHTLW-Nu4ri9P-.js → chunk-INKRHTLW-Ckl3_KkO.js} +13 -13
- package/web/assets/chunk-J5EP6P6S-L19oz55R.js +1 -0
- package/web/assets/{chunk-KGFNY3KK-JGMJvKCK.js → chunk-KGFNY3KK-BZeP-55u.js} +17 -17
- package/web/assets/chunk-KGYTTC2M-zm6n242I.js +1 -0
- package/web/assets/{chunk-KRXBNO2N-BW5o0KUN.js → chunk-KRXBNO2N-C-UNuKKf.js} +1 -1
- package/web/assets/{chunk-LCXTWHL2-CfLLCywY.js → chunk-LCXTWHL2-C162wE5z.js} +5 -5
- package/web/assets/chunk-LII3EMHJ-BL6lKJ_P.js +1 -0
- package/web/assets/chunk-LRIF4GLE-n59lhprL.js +1 -0
- package/web/assets/chunk-QA3QBVWF-DVXPOIxe.js +2 -0
- package/web/assets/chunk-RERM46MO-B5dAdWpP.js +1 -0
- package/web/assets/chunk-RG4AUYOV-ZNgyLFq6.js +206 -0
- package/web/assets/chunk-RKZBBQEN-MyIQbGgD.js +1 -0
- package/web/assets/chunk-RLI5ZMPA-CkXZ0y0U.js +1 -0
- package/web/assets/chunk-T2UQINTJ-BEyXhZWe.js +1 -0
- package/web/assets/chunk-UP6H54XL-BG-n7qDp.js +1 -0
- package/web/assets/chunk-UXSXWOXI-CW1_r5cS.js +1 -0
- package/web/assets/chunk-UY5QBCOK-ByqTVLvh.js +1 -0
- package/web/assets/chunk-VU6ZFW4Y-BLeasdkU.js +2 -0
- package/web/assets/{chunk-W44A43WB-JqMLIpR0.js → chunk-W44A43WB-BN8EQc_u.js} +1 -1
- package/web/assets/chunk-ZXARS5L4-C3v-4Fsw.js +1 -0
- package/web/assets/classDiagram-KGZ6W3CR-olpO3fMe.js +1 -0
- package/web/assets/classDiagram-v2-72OJOZXJ-olpO3fMe.js +1 -0
- package/web/assets/cose-bilkent-UX7MHV2Q-BmnZ7Mvj.js +1 -0
- package/web/assets/dagre-ND4H6XIP-CY4iIF7v.js +4 -0
- package/web/assets/diagram-3NCE3AQN-CO6QpzEE.js +43 -0
- package/web/assets/diagram-GF46GFSD-B2atbzmU.js +24 -0
- package/web/assets/diagram-HNR7UZ2L-DVRltWbL.js +3 -0
- package/web/assets/diagram-QXG6HAR7-DR6AHD2h.js +24 -0
- package/web/assets/diagram-WEQXMOUZ-DkpoMwTL.js +10 -0
- package/web/assets/erDiagram-L5TCEMPS-n8g_90bc.js +85 -0
- package/web/assets/eventmodeling-FCH6USID-MREXMVOE-CgFBM7e-.js +1 -0
- package/web/assets/flowDiagram-H6V6AXG4-SGMDiCkB.js +162 -0
- package/web/assets/ganttDiagram-JCBTUEKG-Cb3UBqRS.js +292 -0
- package/web/assets/gitGraph-WXDBUCRP-R675I2BI-DCJv7SII.js +1 -0
- package/web/assets/gitGraphDiagram-S2ZK5IYY-Bs9CR7tq.js +106 -0
- package/web/assets/index-CX_fADmQ.css +2 -0
- package/web/assets/index-D1Z3dGGz.js +575 -0
- package/web/assets/info-J43DQDTF-KCYPFFUO-BfNy-9Nd.js +1 -0
- package/web/assets/infoDiagram-3YFTVSEB-T368on4D.js +2 -0
- package/web/assets/{ishikawaDiagram-BNXS4ZKH-DfYpxnE5.js → ishikawaDiagram-BNXS4ZKH-XpjJRU9h.js} +6 -6
- package/web/assets/journeyDiagram-M6C3CM3L-C6wjooas.js +139 -0
- package/web/assets/kanban-definition-75IXJCU3-5_UVY79g.js +89 -0
- package/web/assets/{katex-K3KEBU37-CTc5BslQ.js → katex-K3KEBU37-qRQBy-EZ.js} +2 -2
- package/web/assets/{mindmap-definition-2TDM6QVE-DypvbOMQ.js → mindmap-definition-2TDM6QVE-8xDLzk2e.js} +29 -29
- package/web/assets/node-Ct_zna8U.js +8 -0
- package/web/assets/packet-YPE3B663-LP52Z2RK-D4qkeG9k.js +1 -0
- package/web/assets/pie-LRSECV5Y-TCRJHUBD-B_yMKyQa.js +1 -0
- package/web/assets/pieDiagram-CU6KROY3-Bv4LpAbr.js +30 -0
- package/web/assets/preload-helper-Czpn1I53.js +1 -0
- package/web/assets/{quadrantDiagram-VICAPDV7-yXSZ2lLz.js → quadrantDiagram-VICAPDV7-DR54jOeR.js} +6 -6
- package/web/assets/radar-GUYGQ44K-RDLRG3WG-DeD6yN_0.js +1 -0
- package/web/assets/requirementDiagram-JXO7QTGE-PEkg7sKC.js +84 -0
- package/web/assets/rolldown-runtime-QTnfLwEv.js +1 -0
- package/web/assets/sankeyDiagram-URQDO5SZ-DDWEtjcs.js +40 -0
- package/web/assets/sdk-CzHHH8tD.js +37 -0
- package/web/assets/sequenceDiagram-VS2MUI6T-Bv-uwANx.js +162 -0
- package/web/assets/src-JV30wyV8.js +1 -0
- package/web/assets/stateDiagram-7D4R322I-DVNjmkEq.js +1 -0
- package/web/assets/stateDiagram-v2-36443NZ5-CyN4Fh7_.js +1 -0
- package/web/assets/timeline-definition-O6YCAMPW-Qmsuo7qS.js +120 -0
- package/web/assets/treeView-BLDUP644-QA4HXRO3-CDuSYnd4.js +1 -0
- package/web/assets/treemap-LRROVOQU-LLAWBHMP-imazucyJ.js +1 -0
- package/web/assets/vennDiagram-MWXL3ELB-BD1iK1SX.js +34 -0
- package/web/assets/wardley-L42UT6IY-5TKZOOLJ-DqrT9tB8.js +1 -0
- package/web/assets/wardleyDiagram-CUQ6CDDI-D6TzLVob.js +78 -0
- package/web/assets/{xychartDiagram-N2JHSOCM-BOLm0eNm.js → xychartDiagram-N2JHSOCM-CoZ_Tits.js} +6 -6
- package/web/index.html +18 -10
- package/skills/gitnexus-pr-review.md +0 -163
- package/web/assets/agent-Dli_x7bU.js +0 -660
- package/web/assets/architecture-7EHR7CIX-6QZW5X65-DxJw65fT.js +0 -1
- package/web/assets/architectureDiagram-UL44E2DR-dEkqUZN9.js +0 -36
- package/web/assets/chunk-3SSMPTDK-B4_etUhr.js +0 -321
- package/web/assets/chunk-67TQ5CYL-4sNPJU1q.js +0 -124
- package/web/assets/chunk-7W6UQGC5-KyEG0HQg.js +0 -1
- package/web/assets/chunk-KGYTTC2M-CWC_c3H9.js +0 -161
- package/web/assets/chunk-LII3EMHJ-D-jm-dLa.js +0 -1
- package/web/assets/chunk-QA3QBVWF-BgRW3SXd.js +0 -2
- package/web/assets/chunk-RG4AUYOV-CqWzWsV3.js +0 -206
- package/web/assets/chunk-T2UQINTJ-DSBqkzH7.js +0 -1
- package/web/assets/chunk-UY5QBCOK-DyF0vyGd.js +0 -1
- package/web/assets/chunk-ZXARS5L4-CxN8oiwI.js +0 -1
- package/web/assets/classDiagram-KGZ6W3CR-CMne4tG9.js +0 -1
- package/web/assets/classDiagram-v2-72OJOZXJ-CMne4tG9.js +0 -1
- package/web/assets/cose-bilkent-UX7MHV2Q-D71wNYRJ.js +0 -1
- package/web/assets/dagre-ND4H6XIP-Co5rRx9X.js +0 -4
- package/web/assets/diagram-3NCE3AQN-DBp4O00j.js +0 -43
- package/web/assets/diagram-GF46GFSD-6N_8yS0i.js +0 -24
- package/web/assets/diagram-HNR7UZ2L-DFCfd5LI.js +0 -3
- package/web/assets/diagram-QXG6HAR7-Di093rFg.js +0 -24
- package/web/assets/diagram-WEQXMOUZ-DZWi4SUN.js +0 -10
- package/web/assets/erDiagram-L5TCEMPS-8X1y6R4Y.js +0 -85
- package/web/assets/eventmodeling-FCH6USID-MREXMVOE-BQm9QzEa.js +0 -1
- package/web/assets/flowDiagram-H6V6AXG4-CMpY8Ufn.js +0 -162
- package/web/assets/ganttDiagram-JCBTUEKG-D3iL2Aet.js +0 -292
- package/web/assets/gitGraph-WXDBUCRP-R675I2BI-Cr_Bm2Nb.js +0 -1
- package/web/assets/gitGraphDiagram-S2ZK5IYY-CPIDgxGm.js +0 -106
- package/web/assets/index-KctnI3Vq.js +0 -635
- package/web/assets/index-_lgn7hs5.css +0 -2
- package/web/assets/info-J43DQDTF-KCYPFFUO-Cs4p2oyk.js +0 -1
- package/web/assets/infoDiagram-3YFTVSEB-BaLMZkUg.js +0 -2
- package/web/assets/journeyDiagram-M6C3CM3L-CvArszLo.js +0 -139
- package/web/assets/kanban-definition-75IXJCU3-CpfVLLf9.js +0 -89
- package/web/assets/packet-YPE3B663-LP52Z2RK-CKCrztD2.js +0 -1
- package/web/assets/pie-LRSECV5Y-TCRJHUBD-BB7pHqoD.js +0 -1
- package/web/assets/pieDiagram-CU6KROY3-s27EFWgP.js +0 -30
- package/web/assets/radar-GUYGQ44K-RDLRG3WG-DhoTOcuK.js +0 -1
- package/web/assets/requirementDiagram-JXO7QTGE-CWhqInuf.js +0 -84
- package/web/assets/sankeyDiagram-URQDO5SZ-1qEjlFIB.js +0 -40
- package/web/assets/sequenceDiagram-VS2MUI6T-RyTlZ5cR.js +0 -162
- package/web/assets/stateDiagram-7D4R322I-DTjVfX4A.js +0 -1
- package/web/assets/stateDiagram-v2-36443NZ5-xY9_k9_Q.js +0 -1
- package/web/assets/timeline-definition-O6YCAMPW-DrrqLYAf.js +0 -120
- package/web/assets/treeView-BLDUP644-QA4HXRO3-ODehyGKL.js +0 -1
- package/web/assets/treemap-LRROVOQU-LLAWBHMP-BfpgC-7o.js +0 -1
- package/web/assets/vennDiagram-MWXL3ELB-B0RkWAim.js +0 -34
- package/web/assets/wardley-L42UT6IY-5TKZOOLJ-CNeL6VHE.js +0 -1
- package/web/assets/wardleyDiagram-CUQ6CDDI-boUxiQ5F.js +0 -78
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Warning attached to search responses when BM25/FTS is degraded. Prefers the
|
|
3
|
+
* live extension-load failure (with LadybugDB's real reason, #2374) over the
|
|
4
|
+
* generic indexes-missing message, so "indexes exist but the extension broke"
|
|
5
|
+
* is not misreported as missing indexes.
|
|
6
|
+
*/
|
|
7
|
+
export declare const ftsDegradedWarning: () => string;
|
|
1
8
|
export declare const SUPPORTED_FTS_STEMMERS: ReadonlySet<string>;
|
|
2
9
|
export interface CreateSearchFTSIndexesOptions {
|
|
3
10
|
onIndexStart?: (table: string, indexName: string) => void;
|
|
@@ -17,5 +24,29 @@ export declare function initialiseSearchFTSStemmer(): string;
|
|
|
17
24
|
* tests) so validation always applies.
|
|
18
25
|
*/
|
|
19
26
|
export declare function getSearchFTSStemmer(): string;
|
|
27
|
+
/**
|
|
28
|
+
* Drop every configured FTS index (no-op per index when absent or unloadable
|
|
29
|
+
* — `dropFTSIndex` tolerates both). Callable ahead of any DML that mutates an
|
|
30
|
+
* FTS-indexed table's rows: LadybugDB's FTS extension is not proven to
|
|
31
|
+
* survive a DETACH DELETE against a table that still carries a live index
|
|
32
|
+
* from a prior run (#2589) — dropping first removes that hazard entirely,
|
|
33
|
+
* regardless of whether it also fixed a specific native inconsistency.
|
|
34
|
+
*/
|
|
35
|
+
export declare function dropSearchFTSIndexes(): Promise<void>;
|
|
20
36
|
export declare function createSearchFTSIndexes(options?: CreateSearchFTSIndexesOptions): Promise<void>;
|
|
21
37
|
export declare function verifySearchFTSIndexes(executeQuery: (cypher: string) => Promise<unknown[]>): Promise<string[]>;
|
|
38
|
+
export interface BuildSearchIndexesResult {
|
|
39
|
+
ok: boolean;
|
|
40
|
+
error?: string;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Build + verify FTS indexes, catching any failure instead of letting it
|
|
44
|
+
* propagate. `createSearchFTSIndexes` re-tokenizes every stored row on every
|
|
45
|
+
* analyze run (see the `ponytail:` comment above) — a native LadybugDB
|
|
46
|
+
* tokenizer error on a single pre-existing row (e.g. a "Failed calling
|
|
47
|
+
* LOWER: Invalid UTF-8", #2544/#2546) must not discard an otherwise-
|
|
48
|
+
* successful analyze's graph/embeddings work. The caller degrades keyword
|
|
49
|
+
* search for this run instead, mirroring the existing FTS-extension-
|
|
50
|
+
* unavailable degrade path in `run-analyze.ts`.
|
|
51
|
+
*/
|
|
52
|
+
export declare function buildSearchIndexesOrDegrade(executeQuery: (cypher: string) => Promise<unknown[]>, options?: CreateSearchFTSIndexesOptions): Promise<BuildSearchIndexesResult>;
|
|
@@ -1,5 +1,42 @@
|
|
|
1
1
|
import { createFTSIndex, dropFTSIndex, DEFAULT_FTS_STEMMER } from '../lbug/lbug-adapter.js';
|
|
2
|
+
import { getExtensionCapabilities } from '../lbug/extension-loader.js';
|
|
3
|
+
import { classifyExtensionLoadError } from '../lbug/extension-load-error.js';
|
|
2
4
|
import { FTS_INDEXES } from './fts-schema.js';
|
|
5
|
+
/**
|
|
6
|
+
* Strip filesystem paths from a LadybugDB error before it reaches the HTTP
|
|
7
|
+
* `/api/search` and MCP query surfaces (#2374, PR #2375): the raw LOAD error
|
|
8
|
+
* embeds the absolute extension path (username, home dir) which must not leak to
|
|
9
|
+
* a network client. The error class words ("Failed to load library", "invalid
|
|
10
|
+
* ELF header", "has not been installed") have no leading path separator and
|
|
11
|
+
* survive. CLI/doctor/log surfaces keep the full path (they read the reason
|
|
12
|
+
* directly, not through this function).
|
|
13
|
+
*/
|
|
14
|
+
const redactPaths = (reason) => reason.replace(/(?:[A-Za-z]:\\|\/)[^\s'"]+/g, '<path>');
|
|
15
|
+
/**
|
|
16
|
+
* Warning attached to search responses when BM25/FTS is degraded. Prefers the
|
|
17
|
+
* live extension-load failure (with LadybugDB's real reason, #2374) over the
|
|
18
|
+
* generic indexes-missing message, so "indexes exist but the extension broke"
|
|
19
|
+
* is not misreported as missing indexes.
|
|
20
|
+
*/
|
|
21
|
+
export const ftsDegradedWarning = () => {
|
|
22
|
+
const fts = getExtensionCapabilities().find((c) => c.name === 'fts');
|
|
23
|
+
if (fts && !fts.loaded) {
|
|
24
|
+
const reason = fts.reason ? redactPaths(fts.reason).replace(/\.$/, '') : undefined;
|
|
25
|
+
// A missing *runtime dependency* (Windows error 126, etc.) is not healed by
|
|
26
|
+
// reinstalling (#2374) — surface the classified remedy instead of the generic
|
|
27
|
+
// reinstall tail. Read the diagnosis cached at mark-unavailable time so this
|
|
28
|
+
// per-request path (HTTP /api/search + MCP query) does NO file I/O (#2383 F3);
|
|
29
|
+
// fall back to the pure, no-I/O string classifier if it is somehow absent.
|
|
30
|
+
const { kind, remedy } = fts.diagnosis ?? classifyExtensionLoadError(fts.reason);
|
|
31
|
+
const tail = kind === 'missing_dependency'
|
|
32
|
+
? ` ${remedy}`
|
|
33
|
+
: '. Run `gitnexus doctor` for details, then `gitnexus analyze --repair-fts` with network access to reinstall.';
|
|
34
|
+
return ('FTS extension failed to load — keyword search degraded' +
|
|
35
|
+
(reason ? ` (${reason})` : '') +
|
|
36
|
+
tail);
|
|
37
|
+
}
|
|
38
|
+
return 'FTS indexes missing — keyword search degraded. Run: gitnexus analyze --repair-fts (or gitnexus analyze --force) to rebuild indexes.';
|
|
39
|
+
};
|
|
3
40
|
// Stemmers shipped by the LadybugDB FTS extension. Mirrors the lowercase token
|
|
4
41
|
// set in the extension bundled with @ladybugdb/core 0.18.x (see package.json).
|
|
5
42
|
// Keep in sync on a LadybugDB minor bump — a value here that the installed
|
|
@@ -66,6 +103,19 @@ export function initialiseSearchFTSStemmer() {
|
|
|
66
103
|
export function getSearchFTSStemmer() {
|
|
67
104
|
return resolvedStemmer ?? resolveFTSStemmer();
|
|
68
105
|
}
|
|
106
|
+
/**
|
|
107
|
+
* Drop every configured FTS index (no-op per index when absent or unloadable
|
|
108
|
+
* — `dropFTSIndex` tolerates both). Callable ahead of any DML that mutates an
|
|
109
|
+
* FTS-indexed table's rows: LadybugDB's FTS extension is not proven to
|
|
110
|
+
* survive a DETACH DELETE against a table that still carries a live index
|
|
111
|
+
* from a prior run (#2589) — dropping first removes that hazard entirely,
|
|
112
|
+
* regardless of whether it also fixed a specific native inconsistency.
|
|
113
|
+
*/
|
|
114
|
+
export async function dropSearchFTSIndexes() {
|
|
115
|
+
for (const { table, indexName } of FTS_INDEXES) {
|
|
116
|
+
await dropFTSIndex(table, indexName);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
69
119
|
export async function createSearchFTSIndexes(options) {
|
|
70
120
|
const stemmer = getSearchFTSStemmer();
|
|
71
121
|
for (const { table, indexName, properties } of FTS_INDEXES) {
|
|
@@ -115,3 +165,26 @@ export async function verifySearchFTSIndexes(executeQuery) {
|
|
|
115
165
|
}
|
|
116
166
|
return missing;
|
|
117
167
|
}
|
|
168
|
+
/**
|
|
169
|
+
* Build + verify FTS indexes, catching any failure instead of letting it
|
|
170
|
+
* propagate. `createSearchFTSIndexes` re-tokenizes every stored row on every
|
|
171
|
+
* analyze run (see the `ponytail:` comment above) — a native LadybugDB
|
|
172
|
+
* tokenizer error on a single pre-existing row (e.g. a "Failed calling
|
|
173
|
+
* LOWER: Invalid UTF-8", #2544/#2546) must not discard an otherwise-
|
|
174
|
+
* successful analyze's graph/embeddings work. The caller degrades keyword
|
|
175
|
+
* search for this run instead, mirroring the existing FTS-extension-
|
|
176
|
+
* unavailable degrade path in `run-analyze.ts`.
|
|
177
|
+
*/
|
|
178
|
+
export async function buildSearchIndexesOrDegrade(executeQuery, options) {
|
|
179
|
+
try {
|
|
180
|
+
await createSearchFTSIndexes(options);
|
|
181
|
+
const missing = await verifySearchFTSIndexes(executeQuery);
|
|
182
|
+
if (missing.length > 0) {
|
|
183
|
+
return { ok: false, error: `missing indexes after build: ${missing.join(', ')}` };
|
|
184
|
+
}
|
|
185
|
+
return { ok: true };
|
|
186
|
+
}
|
|
187
|
+
catch (e) {
|
|
188
|
+
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
189
|
+
}
|
|
190
|
+
}
|
|
@@ -37,4 +37,6 @@ export const FTS_INDEXES = [
|
|
|
37
37
|
{ table: 'Union', indexName: 'union_fts', properties: FTS_PROPERTIES },
|
|
38
38
|
{ table: 'Static', indexName: 'static_fts', properties: FTS_PROPERTIES },
|
|
39
39
|
{ table: 'Variable', indexName: 'variable_fts', properties: FTS_PROPERTIES },
|
|
40
|
+
// Move/Aptos module nodes also carry description/content columns.
|
|
41
|
+
{ table: 'Module', indexName: 'module_fts', properties: FTS_PROPERTIES },
|
|
40
42
|
];
|
|
@@ -42,7 +42,7 @@ export declare function getParseDiagnostics(tree: Parser.Tree): {
|
|
|
42
42
|
/**
|
|
43
43
|
* Parse `sourceText` safely on every platform.
|
|
44
44
|
*
|
|
45
|
-
* This is the single "parse safely" entry point and its contract covers
|
|
45
|
+
* This is the single "parse safely" entry point and its contract covers four
|
|
46
46
|
* concerns:
|
|
47
47
|
*
|
|
48
48
|
* 1. **Windows crash workaround.** Inputs longer than 32 767 chars are fed
|
|
@@ -62,7 +62,12 @@ export declare function getParseDiagnostics(tree: Parser.Tree): {
|
|
|
62
62
|
* the tree is **returned anyway** — error recovery is a downgrade, never a
|
|
63
63
|
* drop. Callers wanting the boolean use {@link parseHadErrors}.
|
|
64
64
|
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
65
|
+
* 4. **Embedded NUL recovery.** U+0000 is replaced with one ASCII space in
|
|
66
|
+
* the parser-only input. The one-for-one substitution keeps tree indices
|
|
67
|
+
* aligned with the original source while preventing language lexers from
|
|
68
|
+
* swallowing declarations during error recovery.
|
|
69
|
+
*
|
|
70
|
+
* @param label optional context (e.g. file path) attached to timeout errors,
|
|
71
|
+
* recovery warnings, and degraded-parse logs. Non-breaking trailing param.
|
|
67
72
|
*/
|
|
68
73
|
export declare function parseSourceSafe(parser: Parser, sourceText: string, oldTree?: Parser.Tree, options?: Parser.Options, label?: string): Parser.Tree;
|
|
@@ -155,7 +155,7 @@ export function getParseDiagnostics(tree) {
|
|
|
155
155
|
/**
|
|
156
156
|
* Parse `sourceText` safely on every platform.
|
|
157
157
|
*
|
|
158
|
-
* This is the single "parse safely" entry point and its contract covers
|
|
158
|
+
* This is the single "parse safely" entry point and its contract covers four
|
|
159
159
|
* concerns:
|
|
160
160
|
*
|
|
161
161
|
* 1. **Windows crash workaround.** Inputs longer than 32 767 chars are fed
|
|
@@ -175,22 +175,36 @@ export function getParseDiagnostics(tree) {
|
|
|
175
175
|
* the tree is **returned anyway** — error recovery is a downgrade, never a
|
|
176
176
|
* drop. Callers wanting the boolean use {@link parseHadErrors}.
|
|
177
177
|
*
|
|
178
|
-
*
|
|
179
|
-
*
|
|
178
|
+
* 4. **Embedded NUL recovery.** U+0000 is replaced with one ASCII space in
|
|
179
|
+
* the parser-only input. The one-for-one substitution keeps tree indices
|
|
180
|
+
* aligned with the original source while preventing language lexers from
|
|
181
|
+
* swallowing declarations during error recovery.
|
|
182
|
+
*
|
|
183
|
+
* @param label optional context (e.g. file path) attached to timeout errors,
|
|
184
|
+
* recovery warnings, and degraded-parse logs. Non-breaking trailing param.
|
|
180
185
|
*/
|
|
181
186
|
export function parseSourceSafe(parser, sourceText, oldTree, options, label) {
|
|
187
|
+
let parserInput = sourceText;
|
|
188
|
+
if (sourceText.includes('\0')) {
|
|
189
|
+
let nullByteCount = 0;
|
|
190
|
+
parserInput = sourceText.replaceAll('\0', () => {
|
|
191
|
+
nullByteCount += 1;
|
|
192
|
+
return ' ';
|
|
193
|
+
});
|
|
194
|
+
logger.warn({ ...(label ? { file: label } : {}), nullByteCount }, 'replaced embedded NUL bytes before tree-sitter parsing');
|
|
195
|
+
}
|
|
182
196
|
const budgetMs = resolveParseTimeoutMs();
|
|
183
197
|
const armed = armParseBudget(parser, budgetMs);
|
|
184
198
|
let tree;
|
|
185
199
|
try {
|
|
186
|
-
if (
|
|
187
|
-
tree = parser.parse(
|
|
200
|
+
if (parserInput.length <= DIRECT_PARSE_LIMIT_CHARS) {
|
|
201
|
+
tree = parser.parse(parserInput, oldTree, options);
|
|
188
202
|
}
|
|
189
203
|
else {
|
|
190
204
|
const input = (index) => {
|
|
191
|
-
if (index >=
|
|
205
|
+
if (index >= parserInput.length)
|
|
192
206
|
return null;
|
|
193
|
-
return
|
|
207
|
+
return parserInput.slice(index, index + SAFE_PARSE_CHUNK_CHARS);
|
|
194
208
|
};
|
|
195
209
|
tree = parser.parse(input, oldTree, options);
|
|
196
210
|
}
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* Uses the MCP-style pooled lbug-adapter for connection management.
|
|
6
6
|
*/
|
|
7
7
|
import { initLbug, executeQuery, closeLbug, touchRepo, pinRepo } from '../lbug/pool-adapter.js';
|
|
8
|
+
import { escapeCypherString } from '../lbug/cypher-escape.js';
|
|
8
9
|
const REPO_ID = '__wiki__';
|
|
9
10
|
/**
|
|
10
11
|
* Touch the wiki DB connection to prevent idle timeout during long LLM calls.
|
|
@@ -98,7 +99,7 @@ export async function getInterFileCallEdges() {
|
|
|
98
99
|
export async function getIntraModuleCallEdges(filePaths) {
|
|
99
100
|
if (filePaths.length === 0)
|
|
100
101
|
return [];
|
|
101
|
-
const fileList = filePaths.map((f) => `'${f
|
|
102
|
+
const fileList = filePaths.map((f) => `'${escapeCypherString(f)}'`).join(', ');
|
|
102
103
|
const rows = await executeQuery(REPO_ID, `
|
|
103
104
|
MATCH (a)-[:CodeRelation {type: 'CALLS'}]->(b)
|
|
104
105
|
WHERE a.filePath IN [${fileList}] AND b.filePath IN [${fileList}]
|
|
@@ -118,7 +119,7 @@ export async function getIntraModuleCallEdges(filePaths) {
|
|
|
118
119
|
export async function getInterModuleCallEdges(filePaths) {
|
|
119
120
|
if (filePaths.length === 0)
|
|
120
121
|
return { outgoing: [], incoming: [] };
|
|
121
|
-
const fileList = filePaths.map((f) => `'${f
|
|
122
|
+
const fileList = filePaths.map((f) => `'${escapeCypherString(f)}'`).join(', ');
|
|
122
123
|
const outRows = await executeQuery(REPO_ID, `
|
|
123
124
|
MATCH (a)-[:CodeRelation {type: 'CALLS'}]->(b)
|
|
124
125
|
WHERE a.filePath IN [${fileList}] AND NOT b.filePath IN [${fileList}]
|
|
@@ -155,7 +156,7 @@ export async function getInterModuleCallEdges(filePaths) {
|
|
|
155
156
|
export async function getProcessesForFiles(filePaths, limit = 5) {
|
|
156
157
|
if (filePaths.length === 0)
|
|
157
158
|
return [];
|
|
158
|
-
const fileList = filePaths.map((f) => `'${f
|
|
159
|
+
const fileList = filePaths.map((f) => `'${escapeCypherString(f)}'`).join(', ');
|
|
159
160
|
// Find processes that have steps in the given files
|
|
160
161
|
const procRows = await executeQuery(REPO_ID, `
|
|
161
162
|
MATCH (s)-[r:CodeRelation {type: 'STEP_IN_PROCESS'}]->(p:Process)
|
|
@@ -173,7 +174,7 @@ export async function getProcessesForFiles(filePaths, limit = 5) {
|
|
|
173
174
|
const stepCount = row.stepCount || row[3] || 0;
|
|
174
175
|
// Get the full step trace for this process
|
|
175
176
|
const stepRows = await executeQuery(REPO_ID, `
|
|
176
|
-
MATCH (s)-[r:CodeRelation {type: 'STEP_IN_PROCESS'}]->(p:Process {id: '${procId
|
|
177
|
+
MATCH (s)-[r:CodeRelation {type: 'STEP_IN_PROCESS'}]->(p:Process {id: '${escapeCypherString(procId)}'})
|
|
177
178
|
RETURN s.name AS name, s.filePath AS filePath, labels(s)[0] AS type, r.step AS step
|
|
178
179
|
ORDER BY r.step
|
|
179
180
|
`);
|
|
@@ -210,7 +211,7 @@ export async function getAllProcesses(limit = 20) {
|
|
|
210
211
|
const type = row.type || row[2] || 'unknown';
|
|
211
212
|
const stepCount = row.stepCount || row[3] || 0;
|
|
212
213
|
const stepRows = await executeQuery(REPO_ID, `
|
|
213
|
-
MATCH (s)-[r:CodeRelation {type: 'STEP_IN_PROCESS'}]->(p:Process {id: '${procId
|
|
214
|
+
MATCH (s)-[r:CodeRelation {type: 'STEP_IN_PROCESS'}]->(p:Process {id: '${escapeCypherString(procId)}'})
|
|
214
215
|
RETURN s.name AS name, s.filePath AS filePath, labels(s)[0] AS type, r.step AS step
|
|
215
216
|
ORDER BY r.step
|
|
216
217
|
`);
|
|
@@ -23,6 +23,8 @@ export interface LLMConfig {
|
|
|
23
23
|
requestTimeoutMs?: number;
|
|
24
24
|
/** Max fetch attempts before giving up (default: 3). */
|
|
25
25
|
maxAttempts?: number;
|
|
26
|
+
/** Exact hostnames allowed for explicit http:// LLM endpoints. */
|
|
27
|
+
allowedInsecureHttpHosts?: readonly string[];
|
|
26
28
|
}
|
|
27
29
|
export interface LLMResponse {
|
|
28
30
|
content: string;
|
|
@@ -40,6 +42,8 @@ export declare function resolveLLMConfig(overrides?: Partial<LLMConfig>): Promis
|
|
|
40
42
|
* Estimate token count from text (rough heuristic: ~4 chars per token).
|
|
41
43
|
*/
|
|
42
44
|
export declare function estimateTokens(text: string): number;
|
|
45
|
+
export declare const LLM_ALLOW_INSECURE_CONNECTION_ENV = "GITNEXUS_ALLOW_INSECURE_CONNECTION";
|
|
46
|
+
export declare function parseLLMAllowedInsecureHttpHosts(value: string | undefined): string[];
|
|
43
47
|
/**
|
|
44
48
|
* Validate that a base URL supplied for LLM API calls is a safe HTTP/HTTPS
|
|
45
49
|
* endpoint (CWE-918 / CodeQL js/http-to-file-access).
|
|
@@ -47,15 +51,17 @@ export declare function estimateTokens(text: string): number;
|
|
|
47
51
|
* Allowed:
|
|
48
52
|
* - https:// with any hostname (public LLM APIs, Azure, OpenRouter, …)
|
|
49
53
|
* - http:// restricted to localhost / 127.0.0.1 (local servers: Ollama, LiteLLM, …)
|
|
54
|
+
* - http:// to exact hosts explicitly allowlisted for LAN/self-hosted LLMs
|
|
50
55
|
*
|
|
51
56
|
* Rejected:
|
|
52
57
|
* - file://, data:, javascript:, and any other non-HTTP scheme
|
|
53
|
-
* - http:// aimed at non-loopback hosts
|
|
58
|
+
* - http:// aimed at non-loopback hosts unless explicitly allowlisted
|
|
59
|
+
* (avoids SSRF against internal networks by default)
|
|
54
60
|
*
|
|
55
61
|
* Throws with a descriptive message on validation failure so callers surface a
|
|
56
62
|
* clear error rather than an opaque network error.
|
|
57
63
|
*/
|
|
58
|
-
export declare function validateLLMBaseUrl(baseUrl: string): void;
|
|
64
|
+
export declare function validateLLMBaseUrl(baseUrl: string, allowedInsecureHttpHosts?: readonly string[]): void;
|
|
59
65
|
/**
|
|
60
66
|
* Returns true if the given base URL is an Azure OpenAI endpoint.
|
|
61
67
|
* Uses proper hostname matching to avoid spoofed URLs like
|
|
@@ -43,6 +43,8 @@ export async function resolveLLMConfig(overrides) {
|
|
|
43
43
|
provider: savedProvider ?? 'openai',
|
|
44
44
|
apiVersion: overrides?.apiVersion || process.env.GITNEXUS_AZURE_API_VERSION || savedConfig.apiVersion,
|
|
45
45
|
isReasoningModel: overrides?.isReasoningModel ?? savedConfig.isReasoningModel,
|
|
46
|
+
allowedInsecureHttpHosts: overrides?.allowedInsecureHttpHosts ??
|
|
47
|
+
parseLLMAllowedInsecureHttpHosts(process.env[LLM_ALLOW_INSECURE_CONNECTION_ENV]),
|
|
46
48
|
};
|
|
47
49
|
}
|
|
48
50
|
/**
|
|
@@ -64,6 +66,36 @@ function isTimeoutLikeError(err) {
|
|
|
64
66
|
return true;
|
|
65
67
|
return /time(d)?\s*out|timeout/i.test(err.message);
|
|
66
68
|
}
|
|
69
|
+
export const LLM_ALLOW_INSECURE_CONNECTION_ENV = 'GITNEXUS_ALLOW_INSECURE_CONNECTION';
|
|
70
|
+
function normalizeAllowedInsecureHttpHost(host) {
|
|
71
|
+
const trimmed = host.trim().toLowerCase();
|
|
72
|
+
const fail = () => {
|
|
73
|
+
throw new Error(`--allow-insecure-connection / ${LLM_ALLOW_INSECURE_CONNECTION_ENV} entries must be exact hostnames or IP addresses`);
|
|
74
|
+
};
|
|
75
|
+
if (!trimmed || /[/@?#]/.test(trimmed))
|
|
76
|
+
fail();
|
|
77
|
+
if (trimmed.startsWith('[')) {
|
|
78
|
+
if (!trimmed.endsWith(']'))
|
|
79
|
+
fail();
|
|
80
|
+
const normalized = trimmed.slice(1, -1);
|
|
81
|
+
if (!normalized || /[\[\]]/.test(normalized))
|
|
82
|
+
fail();
|
|
83
|
+
return normalized;
|
|
84
|
+
}
|
|
85
|
+
if (/[\[\]]/.test(trimmed))
|
|
86
|
+
fail();
|
|
87
|
+
if ((trimmed.match(/:/g)?.length ?? 0) === 1) {
|
|
88
|
+
// URL.hostname never includes the port, so accepting "host:port" would
|
|
89
|
+
// create a confusing no-op allowlist entry.
|
|
90
|
+
fail();
|
|
91
|
+
}
|
|
92
|
+
return trimmed;
|
|
93
|
+
}
|
|
94
|
+
export function parseLLMAllowedInsecureHttpHosts(value) {
|
|
95
|
+
if (value === undefined || value.trim() === '')
|
|
96
|
+
return [];
|
|
97
|
+
return [...new Set(value.split(',').map(normalizeAllowedInsecureHttpHost))];
|
|
98
|
+
}
|
|
67
99
|
/**
|
|
68
100
|
* Validate that a base URL supplied for LLM API calls is a safe HTTP/HTTPS
|
|
69
101
|
* endpoint (CWE-918 / CodeQL js/http-to-file-access).
|
|
@@ -71,15 +103,17 @@ function isTimeoutLikeError(err) {
|
|
|
71
103
|
* Allowed:
|
|
72
104
|
* - https:// with any hostname (public LLM APIs, Azure, OpenRouter, …)
|
|
73
105
|
* - http:// restricted to localhost / 127.0.0.1 (local servers: Ollama, LiteLLM, …)
|
|
106
|
+
* - http:// to exact hosts explicitly allowlisted for LAN/self-hosted LLMs
|
|
74
107
|
*
|
|
75
108
|
* Rejected:
|
|
76
109
|
* - file://, data:, javascript:, and any other non-HTTP scheme
|
|
77
|
-
* - http:// aimed at non-loopback hosts
|
|
110
|
+
* - http:// aimed at non-loopback hosts unless explicitly allowlisted
|
|
111
|
+
* (avoids SSRF against internal networks by default)
|
|
78
112
|
*
|
|
79
113
|
* Throws with a descriptive message on validation failure so callers surface a
|
|
80
114
|
* clear error rather than an opaque network error.
|
|
81
115
|
*/
|
|
82
|
-
export function validateLLMBaseUrl(baseUrl) {
|
|
116
|
+
export function validateLLMBaseUrl(baseUrl, allowedInsecureHttpHosts = parseLLMAllowedInsecureHttpHosts(process.env[LLM_ALLOW_INSECURE_CONNECTION_ENV])) {
|
|
83
117
|
let parsed;
|
|
84
118
|
try {
|
|
85
119
|
parsed = new URL(baseUrl);
|
|
@@ -96,9 +130,11 @@ export function validateLLMBaseUrl(baseUrl) {
|
|
|
96
130
|
// Node's URL parser preserves IPv6 brackets in hostname (e.g. "[::1]"),
|
|
97
131
|
// so strip them before comparing to bare address literals.
|
|
98
132
|
const host = parsed.hostname.toLowerCase().replace(/^\[|\]$/g, '');
|
|
99
|
-
|
|
133
|
+
const allowedHosts = new Set(allowedInsecureHttpHosts.map(normalizeAllowedInsecureHttpHost));
|
|
134
|
+
if (host !== 'localhost' && host !== '127.0.0.1' && host !== '::1' && !allowedHosts.has(host)) {
|
|
100
135
|
// Use parsed.origin (scheme+host+port, no credentials) instead of the full URL.
|
|
101
|
-
throw new Error(`Insecure http:// LLM base URLs are only allowed for localhost/127.0.0.1
|
|
136
|
+
throw new Error(`Insecure http:// LLM base URLs are only allowed for localhost/127.0.0.1 ` +
|
|
137
|
+
`or hosts listed by --allow-insecure-connection / ${LLM_ALLOW_INSECURE_CONNECTION_ENV}. ` +
|
|
102
138
|
`Use https:// for remote endpoints (got ${parsed.origin})`);
|
|
103
139
|
}
|
|
104
140
|
}
|
|
@@ -145,7 +181,7 @@ export function buildRequestUrl(baseUrl, apiVersion) {
|
|
|
145
181
|
*/
|
|
146
182
|
export async function callLLM(prompt, config, systemPrompt, options) {
|
|
147
183
|
// Validate base URL before any fetch (CodeQL js/http-to-file-access)
|
|
148
|
-
validateLLMBaseUrl(config.baseUrl);
|
|
184
|
+
validateLLMBaseUrl(config.baseUrl, config.allowedInsecureHttpHosts);
|
|
149
185
|
const messages = [];
|
|
150
186
|
if (systemPrompt) {
|
|
151
187
|
messages.push({ role: 'system', content: systemPrompt });
|
|
@@ -7,8 +7,9 @@
|
|
|
7
7
|
import { isHttpMode, getHttpDimensions, httpEmbedQuery, } from '../../core/embeddings/http-client.js';
|
|
8
8
|
import { resolveEmbeddingConfig } from '../../core/embeddings/config.js';
|
|
9
9
|
import { applyHfEnvOverrides, isHfDownloadFailure, withHfDownloadRetry, } from '../../core/embeddings/hf-env.js';
|
|
10
|
-
import { getLocalEmbeddingRuntimeBlocker } from '../../core/embeddings/runtime-support.js';
|
|
10
|
+
import { getLocalEmbeddingRuntimeBlocker, getMissingLocalEmbeddingStackMessage, } from '../../core/embeddings/runtime-support.js';
|
|
11
11
|
import { ensureOnnxRuntimeCommonResolvable } from '../../core/embeddings/onnxruntime-common-resolver.js';
|
|
12
|
+
import { ensureEmbeddingStackResolvable } from '../../core/embeddings/runtime-install.js';
|
|
12
13
|
import { ensureOnnxRuntimeNodeMatchesSystem } from '../../core/embeddings/onnxruntime-node-resolver.js';
|
|
13
14
|
import { silenceStdout, restoreStdout, realStderrWrite } from '../../core/lbug/pool-adapter.js';
|
|
14
15
|
import { logger } from '../../core/logger.js';
|
|
@@ -45,6 +46,11 @@ export const initEmbedder = async () => {
|
|
|
45
46
|
try {
|
|
46
47
|
// Lazy-load transformers.js only after the runtime guard has passed, so
|
|
47
48
|
// unsupported platforms never reach the native ONNX import (#1515).
|
|
49
|
+
// Registered FIRST so it sits last in the hook chain (registerHooks runs
|
|
50
|
+
// the most recent hook first): when the optional stack was pruned at
|
|
51
|
+
// install time (#2370), its bare specifiers fall back to the on-demand
|
|
52
|
+
// runtime prefix.
|
|
53
|
+
ensureEmbeddingStackResolvable();
|
|
48
54
|
// Under pnpm-strict / `pnpm dlx`, transformers' phantom `onnxruntime-common`
|
|
49
55
|
// import is unresolvable; register the fallback resolver first (#307).
|
|
50
56
|
ensureOnnxRuntimeCommonResolvable();
|
|
@@ -55,7 +61,15 @@ export const initEmbedder = async () => {
|
|
|
55
61
|
// Windows/DirectML, and macOS. Mirrors the core embedder's call site so
|
|
56
62
|
// MCP query-time embedding gets the same CUDA-13 fix.
|
|
57
63
|
ensureOnnxRuntimeNodeMatchesSystem();
|
|
58
|
-
|
|
64
|
+
// The stack is an optionalDependency: npm prunes it when onnxruntime-node's
|
|
65
|
+
// postinstall can't reach api.nuget.org (#2370). Rethrow with actionable
|
|
66
|
+
// reinstall guidance instead of a raw ERR_MODULE_NOT_FOUND.
|
|
67
|
+
const { pipeline, env } = await import('@huggingface/transformers').catch((err) => {
|
|
68
|
+
const missing = getMissingLocalEmbeddingStackMessage(err);
|
|
69
|
+
if (missing)
|
|
70
|
+
throw new Error(missing);
|
|
71
|
+
throw err;
|
|
72
|
+
});
|
|
59
73
|
env.allowLocalModels = false;
|
|
60
74
|
// Bridge user-controlled env vars to transformers.js: HF_HOME →
|
|
61
75
|
// env.cacheDir, HF_ENDPOINT → env.remoteHost (#1205). Centralised in
|
|
@@ -23,6 +23,7 @@ import type { Server as HttpServer } from 'http';
|
|
|
23
23
|
import { type Request, type Response, type NextFunction } from 'express';
|
|
24
24
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
25
25
|
import type { LocalBackend } from './local/local-backend.js';
|
|
26
|
+
import { type McpRepositoryPolicy } from './repository-policy.js';
|
|
26
27
|
/** HTTP server configuration options. */
|
|
27
28
|
export interface McpHttpOptions {
|
|
28
29
|
/** Listening port. */
|
|
@@ -31,6 +32,8 @@ export interface McpHttpOptions {
|
|
|
31
32
|
host: string;
|
|
32
33
|
/** Bearer auth token (optional; no auth when omitted). */
|
|
33
34
|
authToken?: string;
|
|
35
|
+
/** Prevalidated repository policy shared by startup logging and transports. */
|
|
36
|
+
repositoryPolicy?: McpRepositoryPolicy;
|
|
34
37
|
}
|
|
35
38
|
/**
|
|
36
39
|
* Creates a Bearer Token authentication middleware.
|
|
@@ -93,6 +96,7 @@ export declare function createStreamableHttpHandler(backend: LocalBackend, opts?
|
|
|
93
96
|
createServer?: () => Server;
|
|
94
97
|
host?: string;
|
|
95
98
|
port?: number;
|
|
99
|
+
repositoryPolicy?: McpRepositoryPolicy;
|
|
96
100
|
}): {
|
|
97
101
|
handler: (req: Request, res: Response) => Promise<void>;
|
|
98
102
|
cleanup: () => Promise<void>;
|
|
@@ -113,6 +117,7 @@ export declare function createSseHandlers(backend: LocalBackend, messagesPath?:
|
|
|
113
117
|
maxSessions?: number;
|
|
114
118
|
host?: string;
|
|
115
119
|
port?: number;
|
|
120
|
+
repositoryPolicy?: McpRepositoryPolicy;
|
|
116
121
|
}): {
|
|
117
122
|
sseHandler: (req: Request, res: Response) => Promise<void>;
|
|
118
123
|
messageHandler: (req: Request, res: Response) => Promise<void>;
|
|
@@ -27,6 +27,7 @@ import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
|
|
|
27
27
|
import { isInitializeRequest } from '@modelcontextprotocol/sdk/types.js';
|
|
28
28
|
import { createMCPServer, installSignalShutdown } from './server.js';
|
|
29
29
|
import { logger } from '../core/logger.js';
|
|
30
|
+
import { createMcpRepositoryPolicy, mcpRepositoryPolicyConfigured, } from './repository-policy.js';
|
|
30
31
|
/** Sessions idle longer than this are evicted. */
|
|
31
32
|
const SESSION_TTL_MS = 30 * 60 * 1000;
|
|
32
33
|
/** Cleanup sweep runs every 5 minutes. */
|
|
@@ -170,8 +171,14 @@ export function startIdleSweep(sessions, ttlMs, intervalMs) {
|
|
|
170
171
|
* route mount in server/mcp-http.ts (/api/mcp).
|
|
171
172
|
*/
|
|
172
173
|
export function createStreamableHttpHandler(backend, opts = {}) {
|
|
174
|
+
if (opts.createServer && !opts.repositoryPolicy && mcpRepositoryPolicyConfigured()) {
|
|
175
|
+
throw new Error('A custom MCP server factory cannot bypass configured repository policy.');
|
|
176
|
+
}
|
|
173
177
|
// Seam: tests inject createServer to observe the per-session Server lifecycle.
|
|
174
|
-
|
|
178
|
+
let repositoryPolicy = opts.repositoryPolicy
|
|
179
|
+
? Promise.resolve(opts.repositoryPolicy)
|
|
180
|
+
: undefined;
|
|
181
|
+
const getRepositoryPolicy = () => (repositoryPolicy ??= createMcpRepositoryPolicy(backend));
|
|
175
182
|
// DNS-rebinding protection (Host-header allowlist) when the bind host is known.
|
|
176
183
|
const dnsRebinding = dnsRebindingOptions(opts.host, opts.port);
|
|
177
184
|
const sessions = new Map();
|
|
@@ -226,7 +233,9 @@ export function createStreamableHttpHandler(backend, opts = {}) {
|
|
|
226
233
|
sessionIdGenerator: () => randomUUID(),
|
|
227
234
|
...dnsRebinding,
|
|
228
235
|
});
|
|
229
|
-
const server = createServer
|
|
236
|
+
const server = opts.createServer
|
|
237
|
+
? opts.createServer()
|
|
238
|
+
: createMCPServer(backend, { repositoryPolicy: await getRepositoryPolicy() });
|
|
230
239
|
await server.connect(transport);
|
|
231
240
|
await transport.handleRequest(req, res, req.body);
|
|
232
241
|
if (transport.sessionId) {
|
|
@@ -282,6 +291,10 @@ export function createStreamableHttpHandler(backend, opts = {}) {
|
|
|
282
291
|
*/
|
|
283
292
|
export function createSseHandlers(backend, messagesPath = '/messages', opts = {}) {
|
|
284
293
|
const maxSessions = opts.maxSessions ?? MAX_SESSIONS;
|
|
294
|
+
let repositoryPolicy = opts.repositoryPolicy
|
|
295
|
+
? Promise.resolve(opts.repositoryPolicy)
|
|
296
|
+
: undefined;
|
|
297
|
+
const getRepositoryPolicy = () => (repositoryPolicy ??= createMcpRepositoryPolicy(backend));
|
|
285
298
|
// DNS-rebinding protection (Host-header allowlist) when the bind host is known.
|
|
286
299
|
const dnsRebinding = dnsRebindingOptions(opts.host, opts.port);
|
|
287
300
|
const sseSessions = new Map();
|
|
@@ -300,7 +313,7 @@ export function createSseHandlers(backend, messagesPath = '/messages', opts = {}
|
|
|
300
313
|
}
|
|
301
314
|
// SSEServerTransport(endpoint, res, options): endpoint is the path clients POST to.
|
|
302
315
|
const transport = new SSEServerTransport(messagesPath, res, dnsRebinding);
|
|
303
|
-
const server = createMCPServer(backend);
|
|
316
|
+
const server = createMCPServer(backend, { repositoryPolicy: await getRepositoryPolicy() });
|
|
304
317
|
sseSessions.set(transport.sessionId, { server, transport, lastActivity: Date.now() });
|
|
305
318
|
transport.onclose = () => {
|
|
306
319
|
sseSessions.delete(transport.sessionId);
|
|
@@ -370,6 +383,7 @@ export async function startMcpHttpServer(backend, options) {
|
|
|
370
383
|
'Pass --auth-token (or set GITNEXUS_MCP_AUTH_TOKEN), or bind --host 127.0.0.1. ' +
|
|
371
384
|
'This applies to --host 0.0.0.0 and --host :: as well.');
|
|
372
385
|
}
|
|
386
|
+
const repositoryPolicy = options.repositoryPolicy ?? (await createMcpRepositoryPolicy(backend));
|
|
373
387
|
const app = express();
|
|
374
388
|
// Suppress X-Powered-By to reduce information leakage.
|
|
375
389
|
app.disable('x-powered-by');
|
|
@@ -410,7 +424,7 @@ export async function startMcpHttpServer(backend, options) {
|
|
|
410
424
|
res.json({ status: 'ok' });
|
|
411
425
|
});
|
|
412
426
|
// Streamable HTTP (modern MCP clients) at POST /mcp.
|
|
413
|
-
const streamable = createStreamableHttpHandler(backend, { host, port });
|
|
427
|
+
const streamable = createStreamableHttpHandler(backend, { host, port, repositoryPolicy });
|
|
414
428
|
app.all('/mcp', auth, jsonBody, (req, res) => {
|
|
415
429
|
void streamable.handler(req, res).catch((err) => {
|
|
416
430
|
logger.error({ err }, 'MCP /mcp request failed');
|
|
@@ -424,7 +438,7 @@ export async function startMcpHttpServer(backend, options) {
|
|
|
424
438
|
});
|
|
425
439
|
});
|
|
426
440
|
// Legacy SSE: GET /sse opens the stream; POST /messages receives JSON-RPC messages.
|
|
427
|
-
const sse = createSseHandlers(backend, '/messages', { host, port });
|
|
441
|
+
const sse = createSseHandlers(backend, '/messages', { host, port, repositoryPolicy });
|
|
428
442
|
app.get('/sse', auth, (req, res) => {
|
|
429
443
|
void sse.sseHandler(req, res).catch((err) => {
|
|
430
444
|
logger.error({ err }, 'MCP /sse failed');
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { executeParameterized } from '../../core/lbug/pool-adapter.js';
|
|
2
|
+
import { deriveSpringBeanMetadata, } from '../../core/ingestion/frameworks/spring/bean-catalog.js';
|
|
3
|
+
export async function queryClassBeanMetadata(lbugPath, symbolId, symbolType) {
|
|
4
|
+
if (symbolType !== 'Class')
|
|
5
|
+
return undefined;
|
|
6
|
+
try {
|
|
7
|
+
const rows = await executeParameterized(lbugPath, `
|
|
8
|
+
MATCH (c:Class {id: $symbolId})
|
|
9
|
+
RETURN c.frameworkAnnotations AS frameworkAnnotations
|
|
10
|
+
LIMIT 1
|
|
11
|
+
`, { symbolId });
|
|
12
|
+
const row = rows[0];
|
|
13
|
+
if (!row)
|
|
14
|
+
return undefined;
|
|
15
|
+
const value = row.frameworkAnnotations ?? row[0];
|
|
16
|
+
if (!Array.isArray(value))
|
|
17
|
+
return undefined;
|
|
18
|
+
return deriveSpringBeanMetadata(value.filter((annotation) => typeof annotation === 'string'));
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
// Older or partially upgraded indexes may not have the column. This
|
|
22
|
+
// enrichment is additive, so context and impact must still succeed.
|
|
23
|
+
return undefined;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convert a 0-based GraphNode `startLine`/`endLine` to the 1-based line number
|
|
3
|
+
* shown to humans and LLMs in MCP tool output.
|
|
4
|
+
*
|
|
5
|
+
* Storage is 0-based (tree-sitter `startPosition.row`; see
|
|
6
|
+
* `ingestion/utils/line-base.ts`), which matches editors/`sed`/`less -N` only
|
|
7
|
+
* after `+ 1`. The `context`, `query`, and `impact` tools present line numbers a
|
|
8
|
+
* user cross-references against source, so they convert here at the response
|
|
9
|
+
* boundary (#2377).
|
|
10
|
+
*
|
|
11
|
+
* Apply ONLY to a symbol node's 0-based `startLine`/`endLine`. Do NOT apply to:
|
|
12
|
+
* - BasicBlock / CFG `functionStartLine` and PDG statement lines — already
|
|
13
|
+
* 1-based (they use `startPosition.row + 1`);
|
|
14
|
+
* - the internal `sym.startLine + 1` join params that target the 1-based
|
|
15
|
+
* BasicBlock id space;
|
|
16
|
+
* - raw `cypher` results, which pass LadybugDB columns through verbatim and
|
|
17
|
+
* stay 0-based (documented).
|
|
18
|
+
*
|
|
19
|
+
* `undefined`/`null` pass through so optional line fields stay absent.
|
|
20
|
+
*/
|
|
21
|
+
export declare function toDisplayLine(zeroBasedLine: number): number;
|
|
22
|
+
export declare function toDisplayLine(zeroBasedLine: number | null | undefined): number | undefined;
|