pi-lens 4.3.0 → 4.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1159 -0
- package/README.md +116 -25
- package/config/dependency-cruiser-eager-allowlist.json +6 -2
- package/dist/chunk-2BEMIWEW.js +51 -0
- package/dist/chunk-2EECBNC5.js +89 -0
- package/dist/chunk-2FQ62SPM.js +83 -0
- package/dist/chunk-2UMYMRI3.js +118 -0
- package/dist/chunk-34OCDWOS.js +48 -0
- package/dist/chunk-3FERWMCH.js +144 -0
- package/dist/chunk-3JL6IFD7.js +97 -0
- package/dist/chunk-3JSEWUWI.js +327 -0
- package/dist/chunk-3MED75HT.js +37 -0
- package/dist/chunk-3MRXIJ6I.js +79 -0
- package/dist/chunk-3P4PF2BX.js +2250 -0
- package/dist/chunk-3PNFWVHT.js +201 -0
- package/dist/chunk-3TTPKMEF.js +162 -0
- package/dist/chunk-5JHXUETW.js +326 -0
- package/dist/chunk-5W3R6LFT.js +24 -0
- package/dist/chunk-64LU2OVH.js +341 -0
- package/dist/chunk-6B5I6ICN.js +44 -0
- package/dist/chunk-6P54TMWL.js +274 -0
- package/dist/chunk-6UYA642J.js +145 -0
- package/dist/chunk-6XX5HCLK.js +398 -0
- package/dist/chunk-7AXO3ZDF.js +30 -0
- package/dist/chunk-7BX5DWSA.js +1907 -0
- package/dist/chunk-7ELY2CSM.js +902 -0
- package/dist/chunk-7M4T5N3V.js +38 -0
- package/dist/chunk-7U2IDNXN.js +37 -0
- package/dist/chunk-ABBOA7UD.js +157 -0
- package/dist/chunk-AFZYMAIV.js +756 -0
- package/dist/chunk-ALQRYH6O.js +112 -0
- package/dist/chunk-AXKPQ6ZI.js +1610 -0
- package/dist/chunk-BHWHXMQ2.js +62 -0
- package/dist/chunk-BJF25SUG.js +22 -0
- package/dist/chunk-BNKLYOOO.js +18 -0
- package/dist/chunk-BW5KFIQC.js +59 -0
- package/dist/chunk-CBD2B5CP.js +599 -0
- package/dist/chunk-CFYISHUW.js +42 -0
- package/dist/chunk-CMU4RMJB.js +30 -0
- package/dist/chunk-CULQYFLU.js +14 -0
- package/dist/chunk-D65GOCJB.js +289 -0
- package/dist/chunk-D6YF5HKX.js +59 -0
- package/dist/chunk-DMS52BEP.js +342 -0
- package/dist/chunk-ELVWJYRV.js +211 -0
- package/dist/chunk-EUT3B22Y.js +27 -0
- package/dist/chunk-F5VLZHUW.js +146 -0
- package/dist/chunk-FC4RP4I2.js +12 -0
- package/dist/chunk-FGALODG3.js +55 -0
- package/dist/chunk-G3RLJYA2.js +2358 -0
- package/dist/chunk-GAYGGICG.js +32 -0
- package/dist/chunk-H2W2AXD3.js +419 -0
- package/dist/chunk-H5EV3VMF.js +114 -0
- package/dist/chunk-HREZQCT3.js +106 -0
- package/dist/chunk-HSIRMK2D.js +517 -0
- package/dist/chunk-IMSQR4WO.js +184 -0
- package/dist/chunk-IQZXOZ7S.js +4816 -0
- package/dist/chunk-IR6XFA5P.js +37 -0
- package/dist/chunk-IUKPRZER.js +78 -0
- package/dist/chunk-IUR76K6A.js +262 -0
- package/dist/chunk-J3FZR3YY.js +98 -0
- package/dist/chunk-J6DFZDFA.js +562 -0
- package/dist/chunk-J7WJZ6W7.js +50 -0
- package/dist/chunk-JONGANYH.js +202 -0
- package/dist/chunk-KJCWXUUS.js +425 -0
- package/dist/chunk-KJN4IOEJ.js +17 -0
- package/dist/chunk-KMGPUKFD.js +25 -0
- package/dist/chunk-LD7WFTRX.js +4533 -0
- package/dist/chunk-LJDODBBZ.js +78 -0
- package/dist/chunk-LNOMA3MP.js +169 -0
- package/dist/chunk-MGIWSROG.js +2334 -0
- package/dist/chunk-MQA2YBAH.js +308 -0
- package/dist/chunk-MTDRLSI7.js +21720 -0
- package/dist/chunk-N2IRDBZI.js +2355 -0
- package/dist/chunk-N77WFUL7.js +50 -0
- package/dist/chunk-N7YNJE5R.js +466 -0
- package/dist/chunk-NABLC7W3.js +148 -0
- package/dist/chunk-NFXP47RV.js +999 -0
- package/dist/chunk-NJF2X5XF.js +45 -0
- package/dist/chunk-NXL4FFQQ.js +47 -0
- package/dist/chunk-O7HZX7CA.js +309 -0
- package/dist/chunk-OC7LYAU5.js +708 -0
- package/dist/chunk-OEX24ECI.js +348 -0
- package/dist/chunk-OYOB3ZFG.js +78 -0
- package/dist/chunk-OYTMZXRF.js +41 -0
- package/dist/chunk-OZJINN4O.js +84 -0
- package/dist/chunk-PCHDGUKT.js +23 -0
- package/dist/chunk-QOZXJ4NA.js +3364 -0
- package/dist/chunk-QYF5S6P6.js +45 -0
- package/dist/chunk-RJFED73B.js +79 -0
- package/dist/chunk-RTQNRM5X.js +27 -0
- package/dist/chunk-S6AMWKPC.js +189 -0
- package/dist/chunk-T4QZ6FEH.js +308 -0
- package/dist/chunk-T54VJRAD.js +5456 -0
- package/dist/chunk-TA5L5KWQ.js +167 -0
- package/dist/chunk-TQFBZVCG.js +27 -0
- package/dist/chunk-U52SAGRM.js +62 -0
- package/dist/chunk-UEAHAMEI.js +5814 -0
- package/dist/chunk-UGSMCQ4D.js +327 -0
- package/dist/chunk-UOPVJQ4N.js +103 -0
- package/dist/chunk-USHG4DLH.js +459 -0
- package/dist/chunk-UXVNL3D7.js +23 -0
- package/dist/chunk-V5MEBST3.js +4139 -0
- package/dist/chunk-VGEVL5EQ.js +29 -0
- package/dist/chunk-VPWKF3GN.js +87 -0
- package/dist/chunk-VSMJK3ZJ.js +1250 -0
- package/dist/chunk-VYKKMYVT.js +560 -0
- package/dist/chunk-VZHJS6DR.js +442 -0
- package/dist/chunk-WATC3IQR.js +213 -0
- package/dist/chunk-WPE5FPGR.js +54 -0
- package/dist/chunk-WSEWKCXU.js +188 -0
- package/dist/chunk-WW5BLB74.js +659 -0
- package/dist/chunk-XGUL4SLQ.js +406 -0
- package/dist/chunk-XHSCVSOL.js +170 -0
- package/dist/chunk-XIMYZ3JA.js +27 -0
- package/dist/chunk-YLN4K6WD.js +385 -0
- package/dist/chunk-Z3CCVDUB.js +76 -0
- package/dist/chunk-Z54ZSOBZ.js +61 -0
- package/dist/chunk-Z6BB4JLQ.js +478 -0
- package/dist/chunk-Z7QQA2KT.js +27 -0
- package/dist/chunk-ZETYB3XG.js +2626 -0
- package/dist/chunk-ZMOMPX2Z.js +87 -0
- package/dist/chunk-ZOEYVXSV.js +149 -0
- package/dist/chunk-ZZUFZUQZ.js +12120 -0
- package/dist/index.js +39712 -29876
- package/dist/mcp/analyze-cli.js +186 -232
- package/dist/mcp/cli.js +137 -98
- package/dist/mcp/server.js +22688 -1573
- package/dist/mcp/worker.js +97 -38
- package/dist/probes/installer.js +135 -0
- package/dist/workers/project-snapshot-persist-worker.js +22 -0
- package/dist/workers/review-graph-persist-worker.js +15 -0
- package/docs/agent-guide.md +13 -4
- package/docs/agent-tools.md +42 -0
- package/docs/ast-grep_rules_catalog.md +5 -4
- package/docs/configuration.md +28 -2
- package/docs/custom-rules.md +25 -2
- package/docs/environment-variables.md +86 -8
- package/docs/features.md +45 -5
- package/docs/globalconfig.md +2 -1
- package/docs/io-bridge-v2-migration.md +94 -0
- package/docs/lsp-capability-matrix.md +37 -4
- package/docs/lsp-idle-eviction.md +124 -0
- package/docs/mcp.md +21 -5
- package/docs/merge-queue-rollout.md +77 -0
- package/docs/pi-lens-fixer.md +160 -88
- package/docs/pi-lens-investigator.md +74 -26
- package/docs/pi-lens-merge-policy.md +736 -0
- package/docs/pi-lens-monitor.md +75 -7
- package/docs/pi-lens-retro.md +6 -4
- package/docs/pi-lens-reviewer.md +189 -48
- package/docs/pi-lens-subagent.md +246 -45
- package/docs/pi-lens-warden.md +18 -7
- package/docs/public-api-stability.md +55 -0
- package/docs/release-qa-baseline.md +84 -17
- package/docs/rfcs/3654-unified-io-bridge-v2.md +316 -0
- package/docs/schema/pi-lens-config-v1.json +530 -0
- package/docs/servercapabilities.md +56 -49
- package/docs/settings.md +1 -0
- package/docs/usage.md +5 -1
- package/docs/word-index.md +6 -0
- package/grammars/tree-sitter-bash.wasm +0 -0
- package/grammars/tree-sitter-bash.wasm.json +3 -3
- package/package.json +19 -7
- package/rules/ast-grep-rules/rule-tests/advisory-registry-subset-test.yml +41 -0
- package/rules/ast-grep-rules/rule-tests/no-identity-operator-on-literals-test.yml +12 -2
- package/rules/ast-grep-rules/rule-tests/throw-new-error-js-test.yml +2 -0
- package/rules/ast-grep-rules/rule-tests/throw-new-error-test.yml +2 -0
- package/rules/ast-grep-rules/rules/advisory-registry-subset.yml +50 -0
- package/rules/ast-grep-rules/rules/no-identity-operator-on-literals.yml +20 -12
- package/rules/ast-grep-rules/rules/throw-new-error-js.yml +2 -2
- package/rules/ast-grep-rules/rules/throw-new-error.yml +2 -2
- package/scripts/analyze-pi-lens-logs.mjs +1275 -62
- package/scripts/download-grammars.js +5 -0
- package/scripts/grammars.lock.json +6 -1
- package/scripts/install-selftest.mjs +33 -34
- package/scripts/lib/host-provided-deps.mjs +13 -4
- package/scripts/lib/web-tree-sitter-dir.mjs +18 -0
- package/dist/clients/actionable-warnings-logger.js +0 -35
- package/dist/clients/actionable-warnings.js +0 -1610
- package/dist/clients/advisory-provenance.js +0 -593
- package/dist/clients/agent-behavior-client.js +0 -147
- package/dist/clients/agent-nudge.js +0 -325
- package/dist/clients/analysed-root.js +0 -1
- package/dist/clients/ast-grep-client.js +0 -731
- package/dist/clients/ast-grep-rule-manager.js +0 -146
- package/dist/clients/ast-grep-tool-logger.js +0 -118
- package/dist/clients/ast-grep-types.js +0 -10
- package/dist/clients/ast-grep-yaml-synth.js +0 -154
- package/dist/clients/atomic-write-staging.js +0 -75
- package/dist/clients/atomic-write.js +0 -189
- package/dist/clients/availability-probe-flight.js +0 -12
- package/dist/clients/bash-file-access.js +0 -1056
- package/dist/clients/biome-client.js +0 -357
- package/dist/clients/blocker-freshness.js +0 -837
- package/dist/clients/blocker-past-eof.js +0 -129
- package/dist/clients/bootstrap.js +0 -569
- package/dist/clients/bounded-cache.js +0 -190
- package/dist/clients/bounded-pid-file-lock.js +0 -202
- package/dist/clients/bounded-telemetry.js +0 -295
- package/dist/clients/build-identity.js +0 -95
- package/dist/clients/bundled-resource-health.js +0 -113
- package/dist/clients/bus-events-logger.js +0 -105
- package/dist/clients/bus-publish.js +0 -171
- package/dist/clients/cache/rule-cache.js +0 -190
- package/dist/clients/cache-manager.js +0 -524
- package/dist/clients/cache-observability.js +0 -1313
- package/dist/clients/call-graph.js +0 -852
- package/dist/clients/cargo-manifest.js +0 -422
- package/dist/clients/cascade-budget.js +0 -196
- package/dist/clients/cascade-format.js +0 -315
- package/dist/clients/cascade-logger.js +0 -31
- package/dist/clients/cascade-types.js +0 -9
- package/dist/clients/child-unref.js +0 -124
- package/dist/clients/code-quality-warnings.js +0 -286
- package/dist/clients/codebase-model.js +0 -173
- package/dist/clients/collateral-test-role.js +0 -40
- package/dist/clients/complexity-client.js +0 -462
- package/dist/clients/config-core/deny.js +0 -221
- package/dist/clients/config-core/index.js +0 -50
- package/dist/clients/config-core/merge.js +0 -357
- package/dist/clients/config-core/normalize.js +0 -340
- package/dist/clients/config-core/process-spec.js +0 -248
- package/dist/clients/config-core/provenance.js +0 -164
- package/dist/clients/config-core/records.js +0 -218
- package/dist/clients/config-core/resolve.js +0 -125
- package/dist/clients/config-core/safe-object.js +0 -78
- package/dist/clients/config-core/schema.js +0 -165
- package/dist/clients/config-diagnostic-codes.js +0 -285
- package/dist/clients/config-locations.js +0 -388
- package/dist/clients/config-resolve.js +0 -798
- package/dist/clients/config-schema.js +0 -251
- package/dist/clients/config-warn.js +0 -407
- package/dist/clients/console-guard-install.js +0 -26
- package/dist/clients/cooperative-budget.js +0 -42
- package/dist/clients/dead-code-client.js +0 -510
- package/dist/clients/dead-code-logger.js +0 -30
- package/dist/clients/deadline-utils.js +0 -280
- package/dist/clients/debug-handles.js +0 -211
- package/dist/clients/debug-heap.js +0 -174
- package/dist/clients/deferred-lsp-work.js +0 -106
- package/dist/clients/degradation-ledger.js +0 -426
- package/dist/clients/demoted-finding-render.js +0 -169
- package/dist/clients/dependency-checker.js +0 -885
- package/dist/clients/deps/ast-grep-napi.js +0 -22
- package/dist/clients/deps/js-yaml.js +0 -9
- package/dist/clients/deps/minimatch.js +0 -4
- package/dist/clients/deps/pi-tui.js +0 -14
- package/dist/clients/deps/typebox.js +0 -14
- package/dist/clients/deps/vscode-jsonrpc.js +0 -1
- package/dist/clients/deps/web-tree-sitter.js +0 -24
- package/dist/clients/diagnostic-dispositions.js +0 -630
- package/dist/clients/diagnostic-line-freshness.js +0 -305
- package/dist/clients/diagnostic-logger.js +0 -73
- package/dist/clients/diagnostic-tracker.js +0 -105
- package/dist/clients/diagnostics-publish.js +0 -230
- package/dist/clients/dispatch/ast-grep-catalog.js +0 -65
- package/dist/clients/dispatch/auxiliary-lsp.js +0 -343
- package/dist/clients/dispatch/collect-later-tier.js +0 -35
- package/dist/clients/dispatch/diagnostic-taxonomy.js +0 -66
- package/dist/clients/dispatch/dispatcher.js +0 -1269
- package/dist/clients/dispatch/fact-provider-types.js +0 -1
- package/dist/clients/dispatch/fact-rule-runner.js +0 -17
- package/dist/clients/dispatch/fact-runner.js +0 -30
- package/dist/clients/dispatch/fact-scheduler.js +0 -68
- package/dist/clients/dispatch/fact-store.js +0 -377
- package/dist/clients/dispatch/facts/comment-facts.js +0 -22
- package/dist/clients/dispatch/facts/file-content.js +0 -19
- package/dist/clients/dispatch/facts/function-facts.js +0 -348
- package/dist/clients/dispatch/facts/import-facts.js +0 -204
- package/dist/clients/dispatch/facts/tree-sitter-facts.js +0 -34
- package/dist/clients/dispatch/facts/try-catch-facts.js +0 -119
- package/dist/clients/dispatch/finding-policy.js +0 -339
- package/dist/clients/dispatch/indent-detect.js +0 -417
- package/dist/clients/dispatch/inline-suppressions.js +0 -89
- package/dist/clients/dispatch/integration.js +0 -2377
- package/dist/clients/dispatch/lazy.js +0 -11
- package/dist/clients/dispatch/pending-runner-findings.js +0 -87
- package/dist/clients/dispatch/plan.js +0 -278
- package/dist/clients/dispatch/priorities.js +0 -20
- package/dist/clients/dispatch/rule-id-normalize.js +0 -50
- package/dist/clients/dispatch/rule-ignores.js +0 -69
- package/dist/clients/dispatch/rule-policy.js +0 -135
- package/dist/clients/dispatch/rules/async-noise.js +0 -40
- package/dist/clients/dispatch/rules/async-unnecessary-wrapper.js +0 -27
- package/dist/clients/dispatch/rules/cors-wildcard.js +0 -54
- package/dist/clients/dispatch/rules/error-obscuring.js +0 -32
- package/dist/clients/dispatch/rules/error-swallowing.js +0 -31
- package/dist/clients/dispatch/rules/framework-call-noise.js +0 -67
- package/dist/clients/dispatch/rules/high-complexity.js +0 -72
- package/dist/clients/dispatch/rules/high-fan-out.js +0 -74
- package/dist/clients/dispatch/rules/high-import-coupling.js +0 -37
- package/dist/clients/dispatch/rules/missing-error-propagation.js +0 -62
- package/dist/clients/dispatch/rules/no-commented-credentials.js +0 -52
- package/dist/clients/dispatch/rules/pass-through-wrappers.js +0 -42
- package/dist/clients/dispatch/rules/placeholder-comments.js +0 -40
- package/dist/clients/dispatch/rules/unsafe-boundary.js +0 -126
- package/dist/clients/dispatch/runner-context.js +0 -52
- package/dist/clients/dispatch/runners/actionlint.js +0 -111
- package/dist/clients/dispatch/runners/ast-grep-napi.js +0 -1196
- package/dist/clients/dispatch/runners/biome-check.js +0 -296
- package/dist/clients/dispatch/runners/cpp-check.js +0 -219
- package/dist/clients/dispatch/runners/credo.js +0 -82
- package/dist/clients/dispatch/runners/cue-vet.js +0 -416
- package/dist/clients/dispatch/runners/dart-analyze.js +0 -183
- package/dist/clients/dispatch/runners/detekt.js +0 -176
- package/dist/clients/dispatch/runners/dotnet-build.js +0 -164
- package/dist/clients/dispatch/runners/elixir-check.js +0 -195
- package/dist/clients/dispatch/runners/eslint.js +0 -137
- package/dist/clients/dispatch/runners/fact-rules.js +0 -29
- package/dist/clients/dispatch/runners/fish-indent.js +0 -69
- package/dist/clients/dispatch/runners/gleam-check.js +0 -167
- package/dist/clients/dispatch/runners/go-vet.js +0 -104
- package/dist/clients/dispatch/runners/golangci-lint.js +0 -135
- package/dist/clients/dispatch/runners/hadolint.js +0 -91
- package/dist/clients/dispatch/runners/helm-lint.js +0 -171
- package/dist/clients/dispatch/runners/helm-render.js +0 -940
- package/dist/clients/dispatch/runners/htmlhint.js +0 -117
- package/dist/clients/dispatch/runners/index.js +0 -108
- package/dist/clients/dispatch/runners/javac.js +0 -99
- package/dist/clients/dispatch/runners/ktlint.js +0 -110
- package/dist/clients/dispatch/runners/lsp.js +0 -379
- package/dist/clients/dispatch/runners/markdownlint.js +0 -167
- package/dist/clients/dispatch/runners/mypy.js +0 -102
- package/dist/clients/dispatch/runners/oxlint.js +0 -414
- package/dist/clients/dispatch/runners/php-lint.js +0 -85
- package/dist/clients/dispatch/runners/phpstan.js +0 -120
- package/dist/clients/dispatch/runners/prisma-validate.js +0 -62
- package/dist/clients/dispatch/runners/psscriptanalyzer.js +0 -445
- package/dist/clients/dispatch/runners/pyright.js +0 -169
- package/dist/clients/dispatch/runners/rubocop.js +0 -99
- package/dist/clients/dispatch/runners/ruff.js +0 -88
- package/dist/clients/dispatch/runners/rust-clippy.js +0 -256
- package/dist/clients/dispatch/runners/shellcheck.js +0 -173
- package/dist/clients/dispatch/runners/shfmt.js +0 -102
- package/dist/clients/dispatch/runners/spellcheck.js +0 -128
- package/dist/clients/dispatch/runners/spotbugs.js +0 -259
- package/dist/clients/dispatch/runners/sqlfluff.js +0 -183
- package/dist/clients/dispatch/runners/stylelint.js +0 -166
- package/dist/clients/dispatch/runners/swiftlint.js +0 -163
- package/dist/clients/dispatch/runners/taplo.js +0 -174
- package/dist/clients/dispatch/runners/terragrunt.js +0 -168
- package/dist/clients/dispatch/runners/tflint.js +0 -125
- package/dist/clients/dispatch/runners/tree-sitter.js +0 -643
- package/dist/clients/dispatch/runners/trivy-config.js +0 -253
- package/dist/clients/dispatch/runners/utils/availability-policy.js +0 -496
- package/dist/clients/dispatch/runners/utils/candidate-probe.js +0 -90
- package/dist/clients/dispatch/runners/utils/diagnostic-parsers.js +0 -95
- package/dist/clients/dispatch/runners/utils/lazy-installer.js +0 -274
- package/dist/clients/dispatch/runners/utils/runner-helpers.js +0 -1701
- package/dist/clients/dispatch/runners/utils/spawn-outcome.js +0 -101
- package/dist/clients/dispatch/runners/utils/tool-failure.js +0 -235
- package/dist/clients/dispatch/runners/utils/toolchain-availability.js +0 -169
- package/dist/clients/dispatch/runners/utils.js +0 -15
- package/dist/clients/dispatch/runners/vale.js +0 -128
- package/dist/clients/dispatch/runners/yaml-rule-parser.js +0 -242
- package/dist/clients/dispatch/runners/yamllint.js +0 -95
- package/dist/clients/dispatch/runners/zig-check.js +0 -79
- package/dist/clients/dispatch/suppress-writer.js +0 -79
- package/dist/clients/dispatch/tool-profile.js +0 -30
- package/dist/clients/dispatch/types.js +0 -21
- package/dist/clients/dispatch/utils/format-utils.js +0 -45
- package/dist/clients/dispatch/utils/lsp-diagnostics.js +0 -35
- package/dist/clients/disposition-logger.js +0 -32
- package/dist/clients/disposition-publish.js +0 -124
- package/dist/clients/durable-store.js +0 -97
- package/dist/clients/effective-config.js +0 -415
- package/dist/clients/env-utils.js +0 -83
- package/dist/clients/error-class.js +0 -23
- package/dist/clients/eval-timestamp.js +0 -17
- package/dist/clients/event-loop-hold.js +0 -274
- package/dist/clients/event-loop-monitor.js +0 -250
- package/dist/clients/extension-log.js +0 -504
- package/dist/clients/extension-mode.js +0 -73
- package/dist/clients/feature-hints.js +0 -103
- package/dist/clients/file-kinds.js +0 -412
- package/dist/clients/file-role.js +0 -134
- package/dist/clients/file-time.js +0 -160
- package/dist/clients/file-utils.js +0 -1032
- package/dist/clients/finding-delivery-gate.js +0 -494
- package/dist/clients/finding-identity.js +0 -88
- package/dist/clients/fix-worklog.js +0 -103
- package/dist/clients/format-events-publish.js +0 -343
- package/dist/clients/format-service.js +0 -222
- package/dist/clients/formatters-lazy.js +0 -9
- package/dist/clients/formatters.js +0 -2032
- package/dist/clients/freshness-cadence.js +0 -17
- package/dist/clients/freshness.js +0 -38
- package/dist/clients/generated-artifacts.js +0 -394
- package/dist/clients/generation-guard.js +0 -215
- package/dist/clients/git-guard.js +0 -1136
- package/dist/clients/git-tracked-ignore.js +0 -243
- package/dist/clients/gitleaks-client.js +0 -509
- package/dist/clients/go-client.js +0 -104
- package/dist/clients/govulncheck-client.js +0 -605
- package/dist/clients/gradle-ktfmt-style.js +0 -348
- package/dist/clients/grammar-source.js +0 -465
- package/dist/clients/gzip-stage-write.js +0 -135
- package/dist/clients/hashline-anchor.js +0 -424
- package/dist/clients/hook-budgets.js +0 -76
- package/dist/clients/host-edit-normalize.js +0 -140
- package/dist/clients/host-ports.js +0 -39
- package/dist/clients/indent-retarget.js +0 -154
- package/dist/clients/inline-blocker-dispositions.js +0 -186
- package/dist/clients/install-diagnostics.js +0 -156
- package/dist/clients/installer/index.js +0 -5416
- package/dist/clients/installer/managed-tool-refresh-session.js +0 -58
- package/dist/clients/installer/managed-tool-refresh.js +0 -783
- package/dist/clients/instance-reaper-state.js +0 -7
- package/dist/clients/instance-reaper.js +0 -1137
- package/dist/clients/instance-registry-lock.js +0 -145
- package/dist/clients/instance-registry.js +0 -773
- package/dist/clients/jscpd-client.js +0 -378
- package/dist/clients/json-cache-read.js +0 -65
- package/dist/clients/knip-client.js +0 -788
- package/dist/clients/language-policy.js +0 -252
- package/dist/clients/language-profile.js +0 -361
- package/dist/clients/language-registry.js +0 -603
- package/dist/clients/latency-logger.js +0 -727
- package/dist/clients/lazy-import.js +0 -21
- package/dist/clients/ledger-bounds.js +0 -54
- package/dist/clients/lens-config.js +0 -404
- package/dist/clients/lens-engine.js +0 -358
- package/dist/clients/lens-events.js +0 -125
- package/dist/clients/lens-flag-registry.js +0 -467
- package/dist/clients/lens-map.js +0 -1156
- package/dist/clients/live-bus-emitter.js +0 -74
- package/dist/clients/log-cleanup.js +0 -222
- package/dist/clients/lsp/aggregation.js +0 -178
- package/dist/clients/lsp/cascade-tier.js +0 -421
- package/dist/clients/lsp/client.js +0 -4593
- package/dist/clients/lsp/config.js +0 -691
- package/dist/clients/lsp/content-limits.js +0 -41
- package/dist/clients/lsp/diagnostic-binding.js +0 -225
- package/dist/clients/lsp/document-drift.js +0 -467
- package/dist/clients/lsp/edits.js +0 -1219
- package/dist/clients/lsp/index.js +0 -8305
- package/dist/clients/lsp/inferred-project.js +0 -216
- package/dist/clients/lsp/jvm-runtime.js +0 -298
- package/dist/clients/lsp/language.js +0 -63
- package/dist/clients/lsp/launch.js +0 -746
- package/dist/clients/lsp/lombok.js +0 -158
- package/dist/clients/lsp/path-utils.js +0 -5
- package/dist/clients/lsp/pending-aux-coverage.js +0 -251
- package/dist/clients/lsp/position-encoding.js +0 -61
- package/dist/clients/lsp/ruby-drive-dirs.js +0 -83
- package/dist/clients/lsp/server.js +0 -3290
- package/dist/clients/lsp/session-roots.js +0 -192
- package/dist/clients/lsp/spawn-history.js +0 -17
- package/dist/clients/lsp/sync-kind.js +0 -56
- package/dist/clients/lsp/tsserver-sync.js +0 -332
- package/dist/clients/lsp/wait-policy/capability-snapshot.js +0 -1
- package/dist/clients/lsp/wait-policy/classification.js +0 -85
- package/dist/clients/lsp/wait-policy/index.js +0 -10
- package/dist/clients/lsp/wait-policy/strategies.js +0 -392
- package/dist/clients/lsp/watch-queue.js +0 -61
- package/dist/clients/lsp/workspace-diagnostics-cache.js +0 -639
- package/dist/clients/lsp/workspace-diagnostics-session.js +0 -30
- package/dist/clients/lsp/workspace-sweep-hold.js +0 -184
- package/dist/clients/lsp-budget.js +0 -186
- package/dist/clients/lsp-document-symbols.js +0 -110
- package/dist/clients/lsp-lazy.js +0 -9
- package/dist/clients/lsp-mutation.js +0 -396
- package/dist/clients/lsp-status.js +0 -59
- package/dist/clients/map-with-concurrency.js +0 -40
- package/dist/clients/mcp/analyze.js +0 -420
- package/dist/clients/mcp/host-shim.js +0 -31
- package/dist/clients/mcp/ipc.js +0 -523
- package/dist/clients/mcp/review.js +0 -197
- package/dist/clients/mcp/session.js +0 -412
- package/dist/clients/memory-sampler.js +0 -208
- package/dist/clients/message-end-attribution.js +0 -30
- package/dist/clients/metrics-client.js +0 -107
- package/dist/clients/metrics-history.js +0 -327
- package/dist/clients/middle-man-analysis.js +0 -263
- package/dist/clients/model-provider.js +0 -53
- package/dist/clients/module-report-lsp.js +0 -189
- package/dist/clients/module-report.js +0 -2150
- package/dist/clients/mutating-tool.js +0 -651
- package/dist/clients/mutation-attribution.js +0 -368
- package/dist/clients/mutation-bridge.js +0 -240
- package/dist/clients/ndjson-logger.js +0 -734
- package/dist/clients/observed-mutation-sources.js +0 -101
- package/dist/clients/observed-mutation.js +0 -1253
- package/dist/clients/oldtext-autopatch.js +0 -128
- package/dist/clients/opaque-mutation-scan.js +0 -496
- package/dist/clients/opengrep-client.js +0 -333
- package/dist/clients/opengrep-config.js +0 -76
- package/dist/clients/package-manager.js +0 -607
- package/dist/clients/package-root.js +0 -38
- package/dist/clients/partial-edit-apply.js +0 -439
- package/dist/clients/path-attribution-telemetry.js +0 -43
- package/dist/clients/path-keyed-map.js +0 -108
- package/dist/clients/path-utils.js +0 -1244
- package/dist/clients/performance-report.js +0 -331
- package/dist/clients/persist-debounce.js +0 -70
- package/dist/clients/persistent-reverify.js +0 -271
- package/dist/clients/php-cs-fixer-config.js +0 -119
- package/dist/clients/pipeline.js +0 -1480
- package/dist/clients/post-autofix-notice.js +0 -37
- package/dist/clients/print-mode.js +0 -21
- package/dist/clients/probe-home-state.js +0 -228
- package/dist/clients/process-bridge.js +0 -66
- package/dist/clients/process-singletons.js +0 -210
- package/dist/clients/process-snapshot.js +0 -68
- package/dist/clients/project-changes.js +0 -181
- package/dist/clients/project-conventions.js +0 -171
- package/dist/clients/project-diagnostics/cache.js +0 -137
- package/dist/clients/project-diagnostics/extractors.js +0 -109
- package/dist/clients/project-diagnostics/fresh-fetch.js +0 -668
- package/dist/clients/project-diagnostics/runner-adapters/call-graph-impact.js +0 -118
- package/dist/clients/project-diagnostics/runner-adapters/dead-code.js +0 -47
- package/dist/clients/project-diagnostics/runner-adapters/gitleaks.js +0 -40
- package/dist/clients/project-diagnostics/runner-adapters/govulncheck.js +0 -34
- package/dist/clients/project-diagnostics/runner-adapters/jscpd.js +0 -38
- package/dist/clients/project-diagnostics/runner-adapters/knip.js +0 -47
- package/dist/clients/project-diagnostics/runner-adapters/madge.js +0 -48
- package/dist/clients/project-diagnostics/runner-adapters/opengrep.js +0 -40
- package/dist/clients/project-diagnostics/runner-adapters/runner-findings.js +0 -127
- package/dist/clients/project-diagnostics/runner-adapters/trivy.js +0 -81
- package/dist/clients/project-diagnostics/scanner.js +0 -520
- package/dist/clients/project-diagnostics/types.js +0 -1
- package/dist/clients/project-lens-config.js +0 -807
- package/dist/clients/project-report.js +0 -701
- package/dist/clients/project-scale.js +0 -237
- package/dist/clients/project-scan-policy.js +0 -11
- package/dist/clients/project-snapshot-fingerprint.js +0 -48
- package/dist/clients/project-snapshot-persist-worker.js +0 -20
- package/dist/clients/project-snapshot.js +0 -1653
- package/dist/clients/project-trust.js +0 -181
- package/dist/clients/python-environment.js +0 -217
- package/dist/clients/python-provenance.js +0 -639
- package/dist/clients/quiet-window-config.js +0 -47
- package/dist/clients/quiet-window.js +0 -236
- package/dist/clients/read-bridge.js +0 -139
- package/dist/clients/read-expansion.js +0 -266
- package/dist/clients/read-guard-logger.js +0 -251
- package/dist/clients/read-guard-tool-lines.js +0 -1306
- package/dist/clients/read-guard.js +0 -1561
- package/dist/clients/recent-touches.js +0 -240
- package/dist/clients/redact/secrets.js +0 -449
- package/dist/clients/resource-sampler.js +0 -628
- package/dist/clients/reverse-deps.js +0 -270
- package/dist/clients/review-graph/builder.js +0 -5126
- package/dist/clients/review-graph/format.js +0 -33
- package/dist/clients/review-graph/git-identity.js +0 -163
- package/dist/clients/review-graph/import-resolvers.js +0 -481
- package/dist/clients/review-graph/persist-worker.js +0 -10
- package/dist/clients/review-graph/query.js +0 -244
- package/dist/clients/review-graph/revision-drift.js +0 -21
- package/dist/clients/review-graph/service.js +0 -96
- package/dist/clients/review-graph/shared-extraction-ir.js +0 -82
- package/dist/clients/review-graph/symbol-id.js +0 -103
- package/dist/clients/review-graph/tsconfig-paths.js +0 -299
- package/dist/clients/review-graph/types.js +0 -1
- package/dist/clients/review-graph/workspace-modules.js +0 -449
- package/dist/clients/review-graph-logger.js +0 -81
- package/dist/clients/ruff-client.js +0 -179
- package/dist/clients/rules-scanner.js +0 -131
- package/dist/clients/run-duration.js +0 -55
- package/dist/clients/runtime-agent-end.js +0 -746
- package/dist/clients/runtime-config.js +0 -77
- package/dist/clients/runtime-context.js +0 -211
- package/dist/clients/runtime-coordinator.js +0 -1324
- package/dist/clients/runtime-session.js +0 -2485
- package/dist/clients/runtime-tool-call.js +0 -1295
- package/dist/clients/runtime-tool-result.js +0 -2049
- package/dist/clients/runtime-turn.js +0 -3767
- package/dist/clients/rust-client.js +0 -97
- package/dist/clients/safe-spawn.js +0 -2357
- package/dist/clients/sanitize.js +0 -286
- package/dist/clients/scan-utils.js +0 -25
- package/dist/clients/scratch-tree-policy.js +0 -165
- package/dist/clients/search-read-registration.js +0 -94
- package/dist/clients/secret-findings.js +0 -114
- package/dist/clients/security-scan-client.js +0 -352
- package/dist/clients/session-event-guard.js +0 -297
- package/dist/clients/session-lifecycle.js +0 -484
- package/dist/clients/session-start-observability.js +0 -94
- package/dist/clients/session-state-store.js +0 -101
- package/dist/clients/session-summary.js +0 -15
- package/dist/clients/sessionstart-logger.js +0 -27
- package/dist/clients/sg-runner.js +0 -876
- package/dist/clients/sgconfig.js +0 -347
- package/dist/clients/shared-checkout-guard.js +0 -338
- package/dist/clients/single-flight.js +0 -158
- package/dist/clients/situational-tool-telemetry.js +0 -108
- package/dist/clients/skills-resolver.js +0 -141
- package/dist/clients/slow-fs.js +0 -138
- package/dist/clients/smells-rollup.js +0 -231
- package/dist/clients/source-filter.js +0 -596
- package/dist/clients/source-walker.js +0 -211
- package/dist/clients/spawn-output-cap.js +0 -120
- package/dist/clients/spawn-timeout-cooldown.js +0 -110
- package/dist/clients/stale-marker.js +0 -17
- package/dist/clients/startup-scan.js +0 -400
- package/dist/clients/startup-timing.js +0 -130
- package/dist/clients/string-utils.js +0 -33
- package/dist/clients/subagent-mode.js +0 -111
- package/dist/clients/symbol-containment.js +0 -24
- package/dist/clients/symbol-types.js +0 -5
- package/dist/clients/test-runner-client.js +0 -2507
- package/dist/clients/test-runner-delivery.js +0 -287
- package/dist/clients/todo-scanner.js +0 -229
- package/dist/clients/tool-agreement.js +0 -423
- package/dist/clients/tool-config.js +0 -249
- package/dist/clients/tool-cwd.js +0 -270
- package/dist/clients/tool-definition.js +0 -47
- package/dist/clients/tool-event.js +0 -105
- package/dist/clients/tool-policy.js +0 -2755
- package/dist/clients/tool-probe.js +0 -53
- package/dist/clients/tool-render.js +0 -156
- package/dist/clients/tool-set-policy.js +0 -118
- package/dist/clients/tree-sitter-cache.js +0 -364
- package/dist/clients/tree-sitter-client.js +0 -4195
- package/dist/clients/tree-sitter-logger.js +0 -100
- package/dist/clients/tree-sitter-navigator.js +0 -269
- package/dist/clients/tree-sitter-query-loader.js +0 -569
- package/dist/clients/tree-sitter-shared.js +0 -158
- package/dist/clients/tree-sitter-symbol-extractor.js +0 -1265
- package/dist/clients/trivy-client.js +0 -467
- package/dist/clients/tui-fit.js +0 -50
- package/dist/clients/turn-context.js +0 -52
- package/dist/clients/turn-end/lane.js +0 -51
- package/dist/clients/turn-end/lanes/govulncheck.js +0 -112
- package/dist/clients/turn-end/lanes/secrets.js +0 -204
- package/dist/clients/turn-summary-render.js +0 -72
- package/dist/clients/turn-summary.js +0 -132
- package/dist/clients/typos-config.js +0 -29
- package/dist/clients/user-notify.js +0 -51
- package/dist/clients/vanished-instance-marker.js +0 -57
- package/dist/clients/warm-attach.js +0 -305
- package/dist/clients/widget-state.js +0 -1808
- package/dist/clients/word-index-logger.js +0 -49
- package/dist/clients/word-index-store.js +0 -459
- package/dist/clients/word-index.js +0 -2080
- package/dist/clients/workspace-topology.js +0 -443
- package/dist/clients/write-ordering-guard.js +0 -65
- package/dist/clients/zizmor-config.js +0 -340
- package/dist/i18n.js +0 -69
- package/dist/mcp/build-staleness.js +0 -124
- package/dist/scripts/lib/process-scan.mjs +0 -583
- package/dist/scripts/lib/skills-predicate.mjs +0 -129
- package/dist/scripts/lib/web-tree-sitter-dir.mjs +0 -123
- package/dist/tools/activate-tools.js +0 -87
- package/dist/tools/ast-grep-outline.js +0 -137
- package/dist/tools/ast-grep-replace.js +0 -244
- package/dist/tools/ast-grep-search.js +0 -762
- package/dist/tools/effective-config.js +0 -90
- package/dist/tools/lens-diagnostic-mark.js +0 -375
- package/dist/tools/lens-diagnostics.js +0 -2571
- package/dist/tools/lsp-diagnostics.js +0 -1745
- package/dist/tools/lsp-navigation.js +0 -1367
- package/dist/tools/lsp-structured-output.js +0 -294
- package/dist/tools/module-report.js +0 -382
- package/dist/tools/project-report.js +0 -86
- package/dist/tools/render-compact.js +0 -374
- package/dist/tools/scan-progress.js +0 -53
- package/dist/tools/shared.js +0 -29
- package/dist/tools/symbol-search.js +0 -155
|
@@ -0,0 +1,999 @@
|
|
|
1
|
+
import { createRequire as __pilensCreateRequire } from "node:module"; const require = __pilensCreateRequire(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
getToolCommandSpec,
|
|
4
|
+
shouldAutoInstallTool
|
|
5
|
+
} from "./chunk-MGIWSROG.js";
|
|
6
|
+
import {
|
|
7
|
+
BUILTIN_SERVER_RUNNER_COVERS,
|
|
8
|
+
getServersForFileWithConfig,
|
|
9
|
+
isAuxiliary
|
|
10
|
+
} from "./chunk-IQZXOZ7S.js";
|
|
11
|
+
import {
|
|
12
|
+
PathKeyedMap
|
|
13
|
+
} from "./chunk-Z3CCVDUB.js";
|
|
14
|
+
import {
|
|
15
|
+
ensureTool,
|
|
16
|
+
findManagedToolBinary,
|
|
17
|
+
getInstallAttempt,
|
|
18
|
+
getLastEnsureResolutionSource,
|
|
19
|
+
getToolInstallStrategy,
|
|
20
|
+
isSpawnableCommand,
|
|
21
|
+
logSessionStart,
|
|
22
|
+
resetPathWalkMemo
|
|
23
|
+
} from "./chunk-LD7WFTRX.js";
|
|
24
|
+
import {
|
|
25
|
+
resolveToolCwd
|
|
26
|
+
} from "./chunk-IUR76K6A.js";
|
|
27
|
+
import {
|
|
28
|
+
VENDOR_BIN_DIRS,
|
|
29
|
+
VENV_BIN_DIRS,
|
|
30
|
+
findGlobalBinary,
|
|
31
|
+
findLocalBinAt,
|
|
32
|
+
findLocalBinUpwards
|
|
33
|
+
} from "./chunk-T4QZ6FEH.js";
|
|
34
|
+
import {
|
|
35
|
+
createAvailabilityProbeFlight,
|
|
36
|
+
probeToolAsync
|
|
37
|
+
} from "./chunk-CMU4RMJB.js";
|
|
38
|
+
import {
|
|
39
|
+
classifyProbeFailure,
|
|
40
|
+
createAvailabilityLatch,
|
|
41
|
+
describeInstallAttempt,
|
|
42
|
+
describeProbeEvidence,
|
|
43
|
+
isLatchingOutcome,
|
|
44
|
+
logAvailabilityDecision,
|
|
45
|
+
startHostStallSampler,
|
|
46
|
+
transientRetryDelayMs
|
|
47
|
+
} from "./chunk-O7HZX7CA.js";
|
|
48
|
+
import {
|
|
49
|
+
createGenerationSource,
|
|
50
|
+
getGlobalPiLensDir,
|
|
51
|
+
isInSpawnTimeoutCooldown,
|
|
52
|
+
safeSpawnAsync
|
|
53
|
+
} from "./chunk-T54VJRAD.js";
|
|
54
|
+
import {
|
|
55
|
+
compareOrdinal,
|
|
56
|
+
incrementDegradationCount
|
|
57
|
+
} from "./chunk-7ELY2CSM.js";
|
|
58
|
+
import {
|
|
59
|
+
normalizeEphemeralMapKey,
|
|
60
|
+
normalizeMapKey
|
|
61
|
+
} from "./chunk-G3RLJYA2.js";
|
|
62
|
+
|
|
63
|
+
// dist/clients/dispatch/runners/utils/runner-helpers.js
|
|
64
|
+
import * as fs from "node:fs";
|
|
65
|
+
import * as path from "node:path";
|
|
66
|
+
import { fileURLToPath } from "node:url";
|
|
67
|
+
function lspPrimaryCoversFile(ctx, runnerId) {
|
|
68
|
+
if (ctx.pi?.getFlag?.("no-lsp"))
|
|
69
|
+
return void 0;
|
|
70
|
+
const primary = getServersForFileWithConfig(ctx.filePath).find((s) => !isAuxiliary(s));
|
|
71
|
+
if (!primary)
|
|
72
|
+
return void 0;
|
|
73
|
+
const fact = primary.custom ? void 0 : BUILTIN_SERVER_RUNNER_COVERS.get(primary.id);
|
|
74
|
+
const covers = primary.covers ?? fact?.runnerIds;
|
|
75
|
+
if (!covers?.includes(runnerId))
|
|
76
|
+
return void 0;
|
|
77
|
+
const gateCommands = fact ? fact.gateCommands : primary.custom ? primary.command ? [primary.command] : void 0 : [];
|
|
78
|
+
if (gateCommands === void 0)
|
|
79
|
+
return void 0;
|
|
80
|
+
return {
|
|
81
|
+
serverId: primary.id,
|
|
82
|
+
gateCommands,
|
|
83
|
+
claimSource: fact ? "builtin-fact" : "declared"
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
async function coveringLaneAvailable(ctx, cover) {
|
|
87
|
+
for (const gate of cover.gateCommands) {
|
|
88
|
+
if (!await ctx.hasTool(gate))
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
var _realThisDir = (() => {
|
|
94
|
+
if (typeof __dirname !== "undefined")
|
|
95
|
+
return __dirname;
|
|
96
|
+
return path.dirname(fileURLToPath(import.meta.url));
|
|
97
|
+
})();
|
|
98
|
+
var _managedToolsDir = path.join(getGlobalPiLensDir(), "tools");
|
|
99
|
+
function managedNodeToolCandidates(tool) {
|
|
100
|
+
const base = path.join(getGlobalPiLensDir(), "tools", "node_modules", ".bin", tool);
|
|
101
|
+
return process.platform === "win32" ? [`${base}.cmd`, `${base}.exe`, base] : [base];
|
|
102
|
+
}
|
|
103
|
+
var managedBinaryVerdicts = /* @__PURE__ */ new Map();
|
|
104
|
+
var managedVerifyInFlight = /* @__PURE__ */ new Map();
|
|
105
|
+
var MANAGED_VERIFY_TIMEOUT_MS = 5e3;
|
|
106
|
+
var MANAGED_VERIFY_COOLDOWN_MS = 6e4;
|
|
107
|
+
var MANAGED_VERIFY_COOLDOWN_MAX_MS = 15 * 6e4;
|
|
108
|
+
function managedVerifyCooldownMs(attempts) {
|
|
109
|
+
return Math.min(MANAGED_VERIFY_COOLDOWN_MAX_MS, MANAGED_VERIFY_COOLDOWN_MS * 2 ** (attempts - 1));
|
|
110
|
+
}
|
|
111
|
+
async function runManagedVerification(candidate, stamp, priorAttempts, generation, verificationArgs = ["--version"]) {
|
|
112
|
+
let transient = false;
|
|
113
|
+
let ok;
|
|
114
|
+
try {
|
|
115
|
+
const { verifyToolBinary } = await import("./probes/installer.js");
|
|
116
|
+
ok = await verifyToolBinary(candidate, void 0, () => {
|
|
117
|
+
transient = true;
|
|
118
|
+
}, MANAGED_VERIFY_TIMEOUT_MS, verificationArgs);
|
|
119
|
+
} catch {
|
|
120
|
+
transient = true;
|
|
121
|
+
ok = false;
|
|
122
|
+
}
|
|
123
|
+
if (!ok && transient) {
|
|
124
|
+
const attempts = priorAttempts + 1;
|
|
125
|
+
generation.guardedWrite(stamp, () => {
|
|
126
|
+
managedBinaryVerdicts.set(stamp, {
|
|
127
|
+
verdict: "unverified",
|
|
128
|
+
attempts,
|
|
129
|
+
retryAtMs: Date.now() + managedVerifyCooldownMs(attempts)
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
return "unverified";
|
|
133
|
+
}
|
|
134
|
+
generation.guardedWrite(stamp, () => {
|
|
135
|
+
managedBinaryVerdicts.set(stamp, { verdict: ok ? "ok" : "broken" });
|
|
136
|
+
});
|
|
137
|
+
if (!ok) {
|
|
138
|
+
logSessionStart(`dispatch availability: managed shim ${candidate} exists but does not run; falling through to PATH`);
|
|
139
|
+
}
|
|
140
|
+
return ok ? "ok" : "broken";
|
|
141
|
+
}
|
|
142
|
+
async function verifyManagedCandidate(candidate, verificationArgs = ["--version"]) {
|
|
143
|
+
let stamp;
|
|
144
|
+
try {
|
|
145
|
+
const stat = fs.statSync(candidate);
|
|
146
|
+
stamp = `${candidate}:${stat.mtimeMs}:${stat.size}`;
|
|
147
|
+
} catch {
|
|
148
|
+
return "absent";
|
|
149
|
+
}
|
|
150
|
+
const memo = managedBinaryVerdicts.get(stamp);
|
|
151
|
+
let priorAttempts = 0;
|
|
152
|
+
if (memo) {
|
|
153
|
+
if (memo.verdict !== "unverified")
|
|
154
|
+
return memo.verdict;
|
|
155
|
+
if (Date.now() < memo.retryAtMs)
|
|
156
|
+
return "unverified";
|
|
157
|
+
priorAttempts = memo.attempts;
|
|
158
|
+
}
|
|
159
|
+
const existing = managedVerifyInFlight.get(stamp);
|
|
160
|
+
if (existing)
|
|
161
|
+
return existing;
|
|
162
|
+
const generation = availabilityGeneration.capture();
|
|
163
|
+
const probe = runManagedVerification(candidate, stamp, priorAttempts, generation, verificationArgs).finally(() => {
|
|
164
|
+
generation.guardedWrite(stamp, () => {
|
|
165
|
+
if (managedVerifyInFlight.get(stamp) === probe) {
|
|
166
|
+
managedVerifyInFlight.delete(stamp);
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
managedVerifyInFlight.set(stamp, probe);
|
|
171
|
+
return probe;
|
|
172
|
+
}
|
|
173
|
+
async function findManagedNodeToolBinary(tool, verificationArgs = ["--version"]) {
|
|
174
|
+
for (const candidate of managedNodeToolCandidates(tool)) {
|
|
175
|
+
const verdict = await verifyManagedCandidate(candidate, verificationArgs);
|
|
176
|
+
if (verdict === "ok" || verdict === "unverified")
|
|
177
|
+
return candidate;
|
|
178
|
+
}
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
async function findManagedReleaseBinary(tool, verificationArgs = ["--version"]) {
|
|
182
|
+
const candidate = await findManagedToolBinary(tool);
|
|
183
|
+
if (!candidate)
|
|
184
|
+
return null;
|
|
185
|
+
const verdict = await verifyManagedCandidate(candidate, verificationArgs);
|
|
186
|
+
return verdict === "ok" || verdict === "unverified" ? candidate : null;
|
|
187
|
+
}
|
|
188
|
+
function createVenvFinder(command, windowsExt = "", verificationArgs = ["--version"]) {
|
|
189
|
+
return async (cwd) => {
|
|
190
|
+
const venvBin = findLocalBinAt(command, cwd, {
|
|
191
|
+
windowsExt,
|
|
192
|
+
binDirs: VENV_BIN_DIRS
|
|
193
|
+
});
|
|
194
|
+
if (venvBin)
|
|
195
|
+
return { path: venvBin, rung: "venv" };
|
|
196
|
+
const managed = await findManagedNodeToolBinary(command, verificationArgs);
|
|
197
|
+
if (managed)
|
|
198
|
+
return { path: managed, rung: "managed-dir" };
|
|
199
|
+
const release = await findManagedReleaseBinary(command, verificationArgs);
|
|
200
|
+
if (release)
|
|
201
|
+
return { path: release, rung: "managed-release" };
|
|
202
|
+
return { path: command, rung: "path" };
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
async function resolveManagedToolClient(options) {
|
|
206
|
+
const probed = await options.probe();
|
|
207
|
+
if (probed.outcome !== "missing")
|
|
208
|
+
return probed;
|
|
209
|
+
if (!shouldAutoInstallTool(options.toolId))
|
|
210
|
+
return probed;
|
|
211
|
+
const state = installStateFor(options.cwd, options.toolId);
|
|
212
|
+
if (state.suppressed)
|
|
213
|
+
return probed;
|
|
214
|
+
const installed = await ensureTool(options.toolId);
|
|
215
|
+
if (!installed) {
|
|
216
|
+
noteInstallFailure(options.toolId, options.cwd);
|
|
217
|
+
return probed;
|
|
218
|
+
}
|
|
219
|
+
const value = await options.acceptInstalled(installed);
|
|
220
|
+
if (value === null) {
|
|
221
|
+
noteInstallFailure(options.toolId, options.cwd);
|
|
222
|
+
return { outcome: "non-installable" };
|
|
223
|
+
}
|
|
224
|
+
noteInstallSuccess(options.toolId, options.cwd);
|
|
225
|
+
return { outcome: "success", value };
|
|
226
|
+
}
|
|
227
|
+
async function getManagedToolEnvironment(_toolId, cwd) {
|
|
228
|
+
let env;
|
|
229
|
+
try {
|
|
230
|
+
const { getToolEnvironment } = await import("./probes/installer.js");
|
|
231
|
+
env = await getToolEnvironment();
|
|
232
|
+
} catch {
|
|
233
|
+
env = { ...process.env };
|
|
234
|
+
}
|
|
235
|
+
if (!cwd)
|
|
236
|
+
return env;
|
|
237
|
+
const separator = process.platform === "win32" ? ";" : ":";
|
|
238
|
+
const currentPath = env.PATH || env.Path || process.env.PATH || "";
|
|
239
|
+
const localBin = path.join(cwd, "node_modules", ".bin");
|
|
240
|
+
const augmentedPath = `${localBin}${separator}${currentPath}`;
|
|
241
|
+
return {
|
|
242
|
+
...env,
|
|
243
|
+
PATH: augmentedPath,
|
|
244
|
+
...process.platform === "win32" ? { Path: augmentedPath } : {}
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
async function discoverManagedTool(toolId) {
|
|
248
|
+
return await ensureTool(toolId, { allowInstall: false }) ?? null;
|
|
249
|
+
}
|
|
250
|
+
var installAttemptsByCwd = new PathKeyedMap(normalizeMapKey);
|
|
251
|
+
var resolveInstallInFlightByCwd = new PathKeyedMap(normalizeEphemeralMapKey);
|
|
252
|
+
var correctedAvailabilityByCwd = new PathKeyedMap(normalizeMapKey);
|
|
253
|
+
var uncorrectedEmissionsByCwd = new PathKeyedMap(normalizeMapKey);
|
|
254
|
+
var latchedUnavailableByCwd = new PathKeyedMap(normalizeMapKey);
|
|
255
|
+
var availabilityGeneration = createGenerationSource("dispatch-availability");
|
|
256
|
+
var getDispatchAvailabilityGeneration = () => availabilityGeneration.current();
|
|
257
|
+
var checkerProbeFlights = createAvailabilityProbeFlight({ generation: getDispatchAvailabilityGeneration });
|
|
258
|
+
function recordAvailabilityProbeOverrun(tool, key, elapsedMs, budgetMs, failure) {
|
|
259
|
+
if (budgetMs === void 0 || elapsedMs <= budgetMs)
|
|
260
|
+
return;
|
|
261
|
+
if (failure === "timeout" && elapsedMs <= budgetMs * 2)
|
|
262
|
+
return;
|
|
263
|
+
incrementDegradationCount({
|
|
264
|
+
kind: "availability-probe-overrun",
|
|
265
|
+
subject: `${tool}:${key}`,
|
|
266
|
+
reason: `probe took ${Math.round(elapsedMs)}ms; budget was ${Math.round(budgetMs)}ms`
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
function installStateFor(cwd, toolId) {
|
|
270
|
+
let states = installAttemptsByCwd.get(cwd);
|
|
271
|
+
if (!states) {
|
|
272
|
+
states = /* @__PURE__ */ new Map();
|
|
273
|
+
installAttemptsByCwd.set(cwd, states);
|
|
274
|
+
}
|
|
275
|
+
let state = states.get(toolId);
|
|
276
|
+
if (!state) {
|
|
277
|
+
state = { attempts: 0, suppressed: false };
|
|
278
|
+
states.set(toolId, state);
|
|
279
|
+
}
|
|
280
|
+
return state;
|
|
281
|
+
}
|
|
282
|
+
function noteInstallFailure(toolId, cwd) {
|
|
283
|
+
const state = installStateFor(cwd, toolId);
|
|
284
|
+
state.attempts += 1;
|
|
285
|
+
state.suppressed = true;
|
|
286
|
+
logSessionStart(`dispatch availability ${toolId}: install attempt ${state.attempts} failed; suppressing retries until the next session or a successful install`);
|
|
287
|
+
}
|
|
288
|
+
function noteInstallSuccess(toolId, cwd) {
|
|
289
|
+
const states = installAttemptsByCwd.get(cwd);
|
|
290
|
+
states?.delete(toolId);
|
|
291
|
+
if (states?.size === 0)
|
|
292
|
+
installAttemptsByCwd.delete(cwd);
|
|
293
|
+
}
|
|
294
|
+
function hasId(map, cwd, id) {
|
|
295
|
+
return map.get(cwd)?.has(id) ?? false;
|
|
296
|
+
}
|
|
297
|
+
function addId(map, cwd, id) {
|
|
298
|
+
let ids = map.get(cwd);
|
|
299
|
+
if (!ids) {
|
|
300
|
+
ids = /* @__PURE__ */ new Set();
|
|
301
|
+
map.set(cwd, ids);
|
|
302
|
+
}
|
|
303
|
+
ids.add(id);
|
|
304
|
+
}
|
|
305
|
+
function deleteIds(map, cwd, ids) {
|
|
306
|
+
const existing = map.get(cwd);
|
|
307
|
+
if (!existing)
|
|
308
|
+
return;
|
|
309
|
+
for (const id of ids)
|
|
310
|
+
existing.delete(id);
|
|
311
|
+
if (existing.size === 0)
|
|
312
|
+
map.delete(cwd);
|
|
313
|
+
}
|
|
314
|
+
function hasCorrectedAvailability(cwd, toolId) {
|
|
315
|
+
return hasId(correctedAvailabilityByCwd, cwd, toolId);
|
|
316
|
+
}
|
|
317
|
+
function noteAvailabilityCorrected(cwd, toolId) {
|
|
318
|
+
addId(correctedAvailabilityByCwd, cwd, toolId);
|
|
319
|
+
}
|
|
320
|
+
function noteLatchedUnavailable(cwd, tool) {
|
|
321
|
+
addId(latchedUnavailableByCwd, cwd, tool);
|
|
322
|
+
}
|
|
323
|
+
function clearLatchedUnavailable(cwd, ...tools) {
|
|
324
|
+
deleteIds(latchedUnavailableByCwd, cwd, tools);
|
|
325
|
+
}
|
|
326
|
+
function latchKeysFor(toolId, command) {
|
|
327
|
+
const keys = [toolId];
|
|
328
|
+
if (command)
|
|
329
|
+
keys.push(command, path.basename(command));
|
|
330
|
+
return keys;
|
|
331
|
+
}
|
|
332
|
+
function hasLatchedUnavailable(cwd, tools) {
|
|
333
|
+
return tools.some((tool) => hasId(latchedUnavailableByCwd, cwd, tool));
|
|
334
|
+
}
|
|
335
|
+
function sourceTagForToolId(toolId) {
|
|
336
|
+
switch (getToolInstallStrategy(toolId)) {
|
|
337
|
+
case "npm":
|
|
338
|
+
return "managed-dir";
|
|
339
|
+
case "pip":
|
|
340
|
+
return "pip-user";
|
|
341
|
+
case "github":
|
|
342
|
+
return "github-release";
|
|
343
|
+
case "archive":
|
|
344
|
+
return "archive-dist";
|
|
345
|
+
case "maven":
|
|
346
|
+
return "maven-jar";
|
|
347
|
+
default:
|
|
348
|
+
return void 0;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
function describeManagedResolution(tool, resolution) {
|
|
352
|
+
if (resolution.rung !== "managed-dir" && resolution.rung !== "managed-release") {
|
|
353
|
+
return {};
|
|
354
|
+
}
|
|
355
|
+
const source = sourceTagForToolId(tool);
|
|
356
|
+
return {
|
|
357
|
+
binary: path.basename(resolution.path),
|
|
358
|
+
...source !== void 0 && { source }
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
function resolvedTagForAttempt(toolId, attempt) {
|
|
362
|
+
if (attempt?.outcome === "declined" || attempt?.outcome === "skipped") {
|
|
363
|
+
return "declined";
|
|
364
|
+
}
|
|
365
|
+
return getLastEnsureResolutionSource(toolId) === "path" ? "path" : "cache";
|
|
366
|
+
}
|
|
367
|
+
function emitCompensatingAvailableRow(cwd, toolId, installStartedAt, installedPath, latchKeys) {
|
|
368
|
+
if (hasCorrectedAvailability(cwd, toolId))
|
|
369
|
+
return;
|
|
370
|
+
const correctsLatchedRow = hasLatchedUnavailable(cwd, latchKeys);
|
|
371
|
+
if (correctsLatchedRow) {
|
|
372
|
+
noteAvailabilityCorrected(cwd, toolId);
|
|
373
|
+
clearLatchedUnavailable(cwd, ...latchKeys);
|
|
374
|
+
} else {
|
|
375
|
+
if (hasId(uncorrectedEmissionsByCwd, cwd, toolId))
|
|
376
|
+
return;
|
|
377
|
+
addId(uncorrectedEmissionsByCwd, cwd, toolId);
|
|
378
|
+
}
|
|
379
|
+
const attempt = getInstallAttempt(toolId);
|
|
380
|
+
const installEvidence = describeInstallAttempt(attempt);
|
|
381
|
+
const evidence = {
|
|
382
|
+
...installEvidence,
|
|
383
|
+
binary: path.basename(installedPath),
|
|
384
|
+
source: sourceTagForToolId(toolId),
|
|
385
|
+
// Set alongside any non-"succeeded" outcome: the path is truthy but
|
|
386
|
+
// nothing ran this call, so it came from an already-known-good answer
|
|
387
|
+
// rather than a fresh attempt (#1612 review F2).
|
|
388
|
+
...installEvidence.install !== "succeeded" && {
|
|
389
|
+
resolved: resolvedTagForAttempt(toolId, attempt)
|
|
390
|
+
},
|
|
391
|
+
// The whole point of the memo split, on the record: a reader can tell a
|
|
392
|
+
// row that cleared a latched `unavailable` from one that corrected
|
|
393
|
+
// nothing, without re-deriving it from the surrounding rows (#1674
|
|
394
|
+
// review F4).
|
|
395
|
+
correctsLatchedRow
|
|
396
|
+
};
|
|
397
|
+
logAvailabilityDecision({
|
|
398
|
+
tool: toolId,
|
|
399
|
+
verdict: "available",
|
|
400
|
+
outcome: "success",
|
|
401
|
+
cause: "ok",
|
|
402
|
+
elapsedMs: Date.now() - installStartedAt,
|
|
403
|
+
// `checker.reset()`/a fresh probe just cleared whatever cache stood
|
|
404
|
+
// behind this call, so nothing is actually held pinned the instant
|
|
405
|
+
// this row is written — the very next probe starts fresh
|
|
406
|
+
// (#1612 review F3). Writing `true` here would claim a durability
|
|
407
|
+
// this call doesn't have.
|
|
408
|
+
latched: false,
|
|
409
|
+
classifiedBy: "caller",
|
|
410
|
+
evidence
|
|
411
|
+
}, cwd);
|
|
412
|
+
}
|
|
413
|
+
function resetDispatchAvailabilityState() {
|
|
414
|
+
installAttemptsByCwd.clear();
|
|
415
|
+
resolveInstallInFlightByCwd.clear();
|
|
416
|
+
correctedAvailabilityByCwd.clear();
|
|
417
|
+
uncorrectedEmissionsByCwd.clear();
|
|
418
|
+
latchedUnavailableByCwd.clear();
|
|
419
|
+
managedBinaryVerdicts.clear();
|
|
420
|
+
managedVerifyInFlight.clear();
|
|
421
|
+
resetPathWalkMemo();
|
|
422
|
+
availabilityGeneration.bump();
|
|
423
|
+
checkerProbeFlights.clear();
|
|
424
|
+
cwdProbeFlights.clear();
|
|
425
|
+
}
|
|
426
|
+
function createAvailabilityChecker(command, windowsExt = "", versionArgs = ["--version"], options = {}) {
|
|
427
|
+
const cacheByCwd = new PathKeyedMap(normalizeEphemeralMapKey);
|
|
428
|
+
const inFlightByCwd = new PathKeyedMap(normalizeEphemeralMapKey);
|
|
429
|
+
let checkerGeneration = availabilityGeneration.current();
|
|
430
|
+
let checkerFlightGeneration = 0;
|
|
431
|
+
const findCommand = createVenvFinder(command, windowsExt, versionArgs);
|
|
432
|
+
function ensureCurrentGeneration() {
|
|
433
|
+
if (checkerGeneration === availabilityGeneration.current())
|
|
434
|
+
return;
|
|
435
|
+
cacheByCwd.clear();
|
|
436
|
+
inFlightByCwd.clear();
|
|
437
|
+
checkerGeneration = availabilityGeneration.current();
|
|
438
|
+
checkerFlightGeneration++;
|
|
439
|
+
}
|
|
440
|
+
const reset = () => {
|
|
441
|
+
cacheByCwd.clear();
|
|
442
|
+
inFlightByCwd.clear();
|
|
443
|
+
checkerGeneration = availabilityGeneration.current();
|
|
444
|
+
checkerFlightGeneration++;
|
|
445
|
+
};
|
|
446
|
+
function getCache(cwd) {
|
|
447
|
+
ensureCurrentGeneration();
|
|
448
|
+
const key = path.resolve(cwd || process.cwd());
|
|
449
|
+
const existing = cacheByCwd.get(key);
|
|
450
|
+
if (existing)
|
|
451
|
+
return existing;
|
|
452
|
+
const created = {
|
|
453
|
+
available: null,
|
|
454
|
+
command: null,
|
|
455
|
+
outcome: null,
|
|
456
|
+
cause: null,
|
|
457
|
+
elapsedMs: 0,
|
|
458
|
+
retryAtMs: 0,
|
|
459
|
+
transientAttempts: 0
|
|
460
|
+
};
|
|
461
|
+
cacheByCwd.set(key, created);
|
|
462
|
+
return created;
|
|
463
|
+
}
|
|
464
|
+
function noteDecision(cache, resolvedCwd, verdict) {
|
|
465
|
+
cache.available = verdict.available;
|
|
466
|
+
cache.outcome = verdict.outcome;
|
|
467
|
+
cache.cause = verdict.cause;
|
|
468
|
+
cache.elapsedMs = verdict.elapsedMs;
|
|
469
|
+
let retryAfterMs;
|
|
470
|
+
if (verdict.available) {
|
|
471
|
+
cache.retryAtMs = 0;
|
|
472
|
+
cache.transientAttempts = 0;
|
|
473
|
+
} else if (isLatchingOutcome(verdict.outcome)) {
|
|
474
|
+
cache.retryAtMs = 0;
|
|
475
|
+
cache.transientAttempts = 0;
|
|
476
|
+
} else {
|
|
477
|
+
cache.transientAttempts += 1;
|
|
478
|
+
retryAfterMs = transientRetryDelayMs(cache.transientAttempts, verdict.cause);
|
|
479
|
+
cache.retryAtMs = Date.now() + retryAfterMs;
|
|
480
|
+
}
|
|
481
|
+
const latched = verdict.available || isLatchingOutcome(verdict.outcome);
|
|
482
|
+
if (!verdict.available && latched) {
|
|
483
|
+
noteLatchedUnavailable(resolvedCwd, command);
|
|
484
|
+
} else if (verdict.available) {
|
|
485
|
+
clearLatchedUnavailable(resolvedCwd, ...latchKeysFor(command));
|
|
486
|
+
}
|
|
487
|
+
logAvailabilityDecision({
|
|
488
|
+
tool: command,
|
|
489
|
+
verdict: verdict.available ? "available" : "unavailable",
|
|
490
|
+
outcome: verdict.outcome,
|
|
491
|
+
cause: verdict.cause,
|
|
492
|
+
elapsedMs: verdict.elapsedMs,
|
|
493
|
+
latched,
|
|
494
|
+
// Every caller passes this (#2209); a direct key, not a conditional
|
|
495
|
+
// spread, keeps it visible to the call-shaped classifiedBy sweep.
|
|
496
|
+
classifiedBy: verdict.classifiedBy,
|
|
497
|
+
...verdict.evidence !== void 0 && { evidence: verdict.evidence },
|
|
498
|
+
...verdict.hostStallMs !== void 0 && {
|
|
499
|
+
hostStallMs: verdict.hostStallMs
|
|
500
|
+
},
|
|
501
|
+
...retryAfterMs !== void 0 && { retryAfterMs },
|
|
502
|
+
budgetMs: options.probeTimeout ?? 5e3
|
|
503
|
+
}, resolvedCwd);
|
|
504
|
+
}
|
|
505
|
+
async function isAvailableAsync(cwd) {
|
|
506
|
+
ensureCurrentGeneration();
|
|
507
|
+
const resolvedCwd = cwd || process.cwd();
|
|
508
|
+
const cache = getCache(resolvedCwd);
|
|
509
|
+
if (cache.available === false) {
|
|
510
|
+
if (cache.outcome !== "transient")
|
|
511
|
+
return false;
|
|
512
|
+
if (Date.now() < cache.retryAtMs)
|
|
513
|
+
return false;
|
|
514
|
+
cache.available = null;
|
|
515
|
+
}
|
|
516
|
+
if (cache.available === true && cache.command) {
|
|
517
|
+
if (await isSpawnableCommand(cache.command))
|
|
518
|
+
return true;
|
|
519
|
+
cache.available = null;
|
|
520
|
+
cache.command = null;
|
|
521
|
+
cache.outcome = null;
|
|
522
|
+
cache.cause = null;
|
|
523
|
+
}
|
|
524
|
+
const key = path.resolve(resolvedCwd);
|
|
525
|
+
const existing = inFlightByCwd.get(key);
|
|
526
|
+
if (existing)
|
|
527
|
+
return existing;
|
|
528
|
+
const promiseGeneration = checkerGeneration;
|
|
529
|
+
let promise;
|
|
530
|
+
promise = (async () => {
|
|
531
|
+
const fastPath = await options.fastPath?.();
|
|
532
|
+
if (fastPath) {
|
|
533
|
+
cache.command = fastPath;
|
|
534
|
+
noteDecision(cache, resolvedCwd, {
|
|
535
|
+
available: true,
|
|
536
|
+
outcome: "success",
|
|
537
|
+
cause: "fast-path",
|
|
538
|
+
elapsedMs: 0,
|
|
539
|
+
// Caller-asserted, and justifiably: an on-disk shim IS the tool, so
|
|
540
|
+
// there is no spawn to derive anything from (#1500).
|
|
541
|
+
classifiedBy: "caller"
|
|
542
|
+
});
|
|
543
|
+
return true;
|
|
544
|
+
}
|
|
545
|
+
try {
|
|
546
|
+
const cwdStat = await fs.promises.stat(resolvedCwd);
|
|
547
|
+
if (!cwdStat.isDirectory()) {
|
|
548
|
+
noteDecision(cache, resolvedCwd, {
|
|
549
|
+
available: false,
|
|
550
|
+
outcome: "non-installable",
|
|
551
|
+
cause: "bad-cwd",
|
|
552
|
+
elapsedMs: 0,
|
|
553
|
+
// The workspace is gone. Asserted from a stat, not a probe, and it
|
|
554
|
+
// must never read as "the tool is missing" (#1500).
|
|
555
|
+
classifiedBy: "caller"
|
|
556
|
+
});
|
|
557
|
+
return false;
|
|
558
|
+
}
|
|
559
|
+
} catch {
|
|
560
|
+
noteDecision(cache, resolvedCwd, {
|
|
561
|
+
available: false,
|
|
562
|
+
outcome: "non-installable",
|
|
563
|
+
cause: "bad-cwd",
|
|
564
|
+
elapsedMs: 0,
|
|
565
|
+
classifiedBy: "caller"
|
|
566
|
+
});
|
|
567
|
+
return false;
|
|
568
|
+
}
|
|
569
|
+
const resolveStartedAt = Date.now();
|
|
570
|
+
const resolution = await findCommand(resolvedCwd);
|
|
571
|
+
const cmd = resolution.path;
|
|
572
|
+
const resolveMs = Date.now() - resolveStartedAt;
|
|
573
|
+
if (isInSpawnTimeoutCooldown(cmd)) {
|
|
574
|
+
noteDecision(cache, resolvedCwd, {
|
|
575
|
+
available: false,
|
|
576
|
+
outcome: "transient",
|
|
577
|
+
cause: "probe-timeout",
|
|
578
|
+
elapsedMs: 0,
|
|
579
|
+
classifiedBy: "caller",
|
|
580
|
+
evidence: {
|
|
581
|
+
command: cmd,
|
|
582
|
+
status: null
|
|
583
|
+
}
|
|
584
|
+
});
|
|
585
|
+
return false;
|
|
586
|
+
}
|
|
587
|
+
const env = await options.environment?.(resolvedCwd);
|
|
588
|
+
const stallSampler = startHostStallSampler();
|
|
589
|
+
const startedAt = Date.now();
|
|
590
|
+
let result;
|
|
591
|
+
let hostStallMs;
|
|
592
|
+
let probeJoined = false;
|
|
593
|
+
try {
|
|
594
|
+
const shared = checkerProbeFlights.run(`checker:${command}|${versionArgs.join("|")}|${key}|${checkerFlightGeneration}|${windowsExt}|${cmd}|${JSON.stringify(Object.entries(env ?? {}).sort(([a], [b]) => compareOrdinal(a, b)))}`, () => safeSpawnAsync(cmd, versionArgs, {
|
|
595
|
+
timeout: options.probeTimeout ?? 5e3,
|
|
596
|
+
cwd: resolvedCwd,
|
|
597
|
+
env,
|
|
598
|
+
input: ""
|
|
599
|
+
}));
|
|
600
|
+
probeJoined = shared.joined;
|
|
601
|
+
result = await shared.promise;
|
|
602
|
+
} finally {
|
|
603
|
+
hostStallMs = stallSampler.stop();
|
|
604
|
+
}
|
|
605
|
+
const elapsedMs = Date.now() - startedAt;
|
|
606
|
+
recordAvailabilityProbeOverrun(command, resolvedCwd, elapsedMs, options.probeTimeout ?? 5e3, result.failure);
|
|
607
|
+
if (!result.error && result.status === 0) {
|
|
608
|
+
cache.command = cmd;
|
|
609
|
+
noteDecision(cache, resolvedCwd, {
|
|
610
|
+
available: true,
|
|
611
|
+
outcome: "success",
|
|
612
|
+
cause: "ok",
|
|
613
|
+
elapsedMs,
|
|
614
|
+
hostStallMs,
|
|
615
|
+
classifiedBy: probeJoined ? "joined" : "probe",
|
|
616
|
+
evidence: {
|
|
617
|
+
...describeProbeEvidence(result),
|
|
618
|
+
...describeManagedResolution(command, resolution),
|
|
619
|
+
resolveMs
|
|
620
|
+
}
|
|
621
|
+
});
|
|
622
|
+
return true;
|
|
623
|
+
}
|
|
624
|
+
const { outcome, cause, evidence } = classifyProbeFailure(result, {
|
|
625
|
+
hostStallMs,
|
|
626
|
+
unclassifiedFailureOutcome: options.unclassifiedFailureOutcome
|
|
627
|
+
});
|
|
628
|
+
if (result.spawnFailure?.kind === "tool-not-found")
|
|
629
|
+
resetPathWalkMemo();
|
|
630
|
+
noteDecision(cache, resolvedCwd, {
|
|
631
|
+
available: false,
|
|
632
|
+
outcome,
|
|
633
|
+
cause,
|
|
634
|
+
elapsedMs,
|
|
635
|
+
hostStallMs,
|
|
636
|
+
classifiedBy: probeJoined ? "joined" : "probe",
|
|
637
|
+
evidence
|
|
638
|
+
});
|
|
639
|
+
return false;
|
|
640
|
+
})().finally(() => {
|
|
641
|
+
if (checkerGeneration === promiseGeneration && inFlightByCwd.get(key) === promise) {
|
|
642
|
+
inFlightByCwd.delete(key);
|
|
643
|
+
}
|
|
644
|
+
});
|
|
645
|
+
inFlightByCwd.set(key, promise);
|
|
646
|
+
return promise;
|
|
647
|
+
}
|
|
648
|
+
function getCommand(cwd) {
|
|
649
|
+
ensureCurrentGeneration();
|
|
650
|
+
const cache = getCache(cwd || process.cwd());
|
|
651
|
+
return cache.command;
|
|
652
|
+
}
|
|
653
|
+
function getOutcome(cwd) {
|
|
654
|
+
ensureCurrentGeneration();
|
|
655
|
+
return getCache(cwd || process.cwd()).outcome;
|
|
656
|
+
}
|
|
657
|
+
function getVerdict(cwd) {
|
|
658
|
+
ensureCurrentGeneration();
|
|
659
|
+
const cache = getCache(cwd || process.cwd());
|
|
660
|
+
return {
|
|
661
|
+
outcome: cache.outcome,
|
|
662
|
+
cause: cache.cause,
|
|
663
|
+
elapsedMs: cache.elapsedMs,
|
|
664
|
+
latched: cache.available !== false || isLatchingOutcome(cache.outcome ?? "missing"),
|
|
665
|
+
retryAtMs: cache.retryAtMs
|
|
666
|
+
};
|
|
667
|
+
}
|
|
668
|
+
return { isAvailableAsync, getCommand, getOutcome, getVerdict, reset };
|
|
669
|
+
}
|
|
670
|
+
var cwdProbeFlights = createAvailabilityProbeFlight({
|
|
671
|
+
generation: getDispatchAvailabilityGeneration
|
|
672
|
+
});
|
|
673
|
+
function createCwdCachedProbe(probe, options) {
|
|
674
|
+
const latchByCwd = new PathKeyedMap(normalizeEphemeralMapKey);
|
|
675
|
+
const inFlightByCwd = new PathKeyedMap(normalizeEphemeralMapKey);
|
|
676
|
+
let probeGeneration = availabilityGeneration.current();
|
|
677
|
+
function clear() {
|
|
678
|
+
latchByCwd.clear();
|
|
679
|
+
inFlightByCwd.clear();
|
|
680
|
+
}
|
|
681
|
+
function ensureCurrentGeneration() {
|
|
682
|
+
if (probeGeneration === availabilityGeneration.current())
|
|
683
|
+
return;
|
|
684
|
+
clear();
|
|
685
|
+
probeGeneration = availabilityGeneration.current();
|
|
686
|
+
}
|
|
687
|
+
function latchFor(key) {
|
|
688
|
+
const existing = latchByCwd.get(key);
|
|
689
|
+
if (existing)
|
|
690
|
+
return existing;
|
|
691
|
+
const created = createAvailabilityLatch();
|
|
692
|
+
latchByCwd.set(key, created);
|
|
693
|
+
return created;
|
|
694
|
+
}
|
|
695
|
+
function note(latch, key, verdict) {
|
|
696
|
+
let retryAfterMs;
|
|
697
|
+
if (verdict.available) {
|
|
698
|
+
latch.noteAvailable(verdict.cause);
|
|
699
|
+
} else {
|
|
700
|
+
const delay = latch.noteUnavailable(verdict.outcome, verdict.cause);
|
|
701
|
+
if (delay > 0)
|
|
702
|
+
retryAfterMs = delay;
|
|
703
|
+
}
|
|
704
|
+
const latched = verdict.available || isLatchingOutcome(verdict.outcome);
|
|
705
|
+
if (!verdict.available && latched) {
|
|
706
|
+
noteLatchedUnavailable(key, options.tool);
|
|
707
|
+
} else if (verdict.available) {
|
|
708
|
+
clearLatchedUnavailable(key, ...latchKeysFor(options.tool));
|
|
709
|
+
}
|
|
710
|
+
logAvailabilityDecision({
|
|
711
|
+
tool: options.tool,
|
|
712
|
+
verdict: verdict.available ? "available" : "unavailable",
|
|
713
|
+
outcome: verdict.outcome,
|
|
714
|
+
cause: verdict.cause,
|
|
715
|
+
elapsedMs: verdict.elapsedMs,
|
|
716
|
+
latched,
|
|
717
|
+
hostStallMs: verdict.hostStallMs,
|
|
718
|
+
...retryAfterMs !== void 0 && { retryAfterMs },
|
|
719
|
+
...options.budgetMs !== void 0 && { budgetMs: options.budgetMs },
|
|
720
|
+
// Every verdict here is derived from the probe this seam just ran.
|
|
721
|
+
classifiedBy: verdict.classifiedBy ?? "probe",
|
|
722
|
+
...verdict.evidence !== void 0 && { evidence: verdict.evidence }
|
|
723
|
+
}, key);
|
|
724
|
+
}
|
|
725
|
+
const run = (cwd) => {
|
|
726
|
+
ensureCurrentGeneration();
|
|
727
|
+
const key = path.resolve(cwd || process.cwd());
|
|
728
|
+
const latch = latchFor(key);
|
|
729
|
+
const memo = latch.read();
|
|
730
|
+
if (memo !== null)
|
|
731
|
+
return Promise.resolve(memo);
|
|
732
|
+
const existing = inFlightByCwd.get(key);
|
|
733
|
+
if (existing)
|
|
734
|
+
return existing;
|
|
735
|
+
const promiseGeneration = probeGeneration;
|
|
736
|
+
let promise;
|
|
737
|
+
promise = (async () => {
|
|
738
|
+
const stallSampler = startHostStallSampler();
|
|
739
|
+
const startedAt = Date.now();
|
|
740
|
+
let result;
|
|
741
|
+
let thrown;
|
|
742
|
+
let probeJoined = false;
|
|
743
|
+
try {
|
|
744
|
+
const shared = cwdProbeFlights.run(`cwd:${options.tool}|${options.flightKeyComponent ?? ""}|${key}`, () => probe(key));
|
|
745
|
+
probeJoined = shared.joined;
|
|
746
|
+
result = await shared.promise;
|
|
747
|
+
} catch (error) {
|
|
748
|
+
thrown = error;
|
|
749
|
+
}
|
|
750
|
+
const hostStallMs = stallSampler.stop();
|
|
751
|
+
const elapsedMs = Date.now() - startedAt;
|
|
752
|
+
const shape = result ?? {
|
|
753
|
+
error: thrown instanceof Error ? thrown : new Error(String(thrown))
|
|
754
|
+
};
|
|
755
|
+
recordAvailabilityProbeOverrun(options.tool, key, elapsedMs, options.budgetMs, shape.failure);
|
|
756
|
+
if (result && !result.error && result.status === 0) {
|
|
757
|
+
note(latch, key, {
|
|
758
|
+
available: true,
|
|
759
|
+
outcome: "success",
|
|
760
|
+
cause: "ok",
|
|
761
|
+
elapsedMs,
|
|
762
|
+
hostStallMs,
|
|
763
|
+
classifiedBy: probeJoined ? "joined" : "probe",
|
|
764
|
+
evidence: describeProbeEvidence(result, options.tool)
|
|
765
|
+
});
|
|
766
|
+
return true;
|
|
767
|
+
}
|
|
768
|
+
const { outcome, cause, evidence } = classifyProbeFailure(shape, {
|
|
769
|
+
hostStallMs,
|
|
770
|
+
command: options.tool,
|
|
771
|
+
unclassifiedFailureOutcome: options.unclassifiedFailureOutcome
|
|
772
|
+
});
|
|
773
|
+
note(latch, key, {
|
|
774
|
+
available: false,
|
|
775
|
+
outcome,
|
|
776
|
+
cause,
|
|
777
|
+
elapsedMs,
|
|
778
|
+
hostStallMs,
|
|
779
|
+
classifiedBy: probeJoined ? "joined" : "probe",
|
|
780
|
+
evidence
|
|
781
|
+
});
|
|
782
|
+
return false;
|
|
783
|
+
})().finally(() => {
|
|
784
|
+
if (probeGeneration === promiseGeneration && inFlightByCwd.get(key) === promise) {
|
|
785
|
+
inFlightByCwd.delete(key);
|
|
786
|
+
}
|
|
787
|
+
});
|
|
788
|
+
inFlightByCwd.set(key, promise);
|
|
789
|
+
return promise;
|
|
790
|
+
};
|
|
791
|
+
const cached = run;
|
|
792
|
+
cached.getVerdict = (cwd) => {
|
|
793
|
+
ensureCurrentGeneration();
|
|
794
|
+
const latch = latchFor(path.resolve(cwd || process.cwd()));
|
|
795
|
+
const outcome = latch.getOutcome();
|
|
796
|
+
return {
|
|
797
|
+
outcome,
|
|
798
|
+
cause: latch.getCause(),
|
|
799
|
+
elapsedMs: 0,
|
|
800
|
+
// Read the OUTCOME, never `read()`: `read()` answers `null` both for a
|
|
801
|
+
// cwd that was never probed and for a transient verdict whose cooldown
|
|
802
|
+
// expired, and `!== false` turned both of those into `latched: true` —
|
|
803
|
+
// the opposite of the truth in the expired case.
|
|
804
|
+
latched: outcome !== null && isLatchingOutcome(outcome),
|
|
805
|
+
retryAtMs: latch.getRetryAtMs()
|
|
806
|
+
};
|
|
807
|
+
};
|
|
808
|
+
cached.reset = () => {
|
|
809
|
+
clear();
|
|
810
|
+
probeGeneration = availabilityGeneration.current();
|
|
811
|
+
};
|
|
812
|
+
return cached;
|
|
813
|
+
}
|
|
814
|
+
function resolveNodeToolCommand(cwd, toolName, windowsExt = ".cmd") {
|
|
815
|
+
const isWin = process.platform === "win32";
|
|
816
|
+
const binName = isWin ? `${toolName}${windowsExt}` : toolName;
|
|
817
|
+
const local = path.join(cwd, "node_modules", ".bin", binName);
|
|
818
|
+
if (fs.existsSync(local))
|
|
819
|
+
return local;
|
|
820
|
+
return toolName;
|
|
821
|
+
}
|
|
822
|
+
function resolveToolCommand(cwd, toolId) {
|
|
823
|
+
const spec = getToolCommandSpec(toolId);
|
|
824
|
+
if (!spec)
|
|
825
|
+
return null;
|
|
826
|
+
return resolveNodeToolCommand(cwd, spec.command, spec.windowsExt ?? ".cmd");
|
|
827
|
+
}
|
|
828
|
+
function resolveVendorToolCommand(cwd, toolName, windowsExt = ".bat") {
|
|
829
|
+
return findLocalBinUpwards(toolName, cwd, {
|
|
830
|
+
windowsExt,
|
|
831
|
+
binDirs: VENDOR_BIN_DIRS
|
|
832
|
+
}) ?? null;
|
|
833
|
+
}
|
|
834
|
+
async function resolveToolCommandWithInstallFallback(cwd, toolId, timeout = 5e3) {
|
|
835
|
+
const spec = getToolCommandSpec(toolId);
|
|
836
|
+
if (!spec)
|
|
837
|
+
return null;
|
|
838
|
+
return resolveCommandWithInstallFallback(resolveToolCommand(cwd, toolId) ?? spec.command, spec.managedToolId ?? toolId, cwd, spec.versionArgs ?? ["--version"], timeout);
|
|
839
|
+
}
|
|
840
|
+
async function verifyOrInstallCommand(command, toolId, cwd, versionArgs = ["--version"], timeout = 5e3) {
|
|
841
|
+
const spawnable = await isSpawnableCommand(command);
|
|
842
|
+
if (spawnable) {
|
|
843
|
+
const versionCheck = await safeSpawnAsync(command, versionArgs, {
|
|
844
|
+
timeout,
|
|
845
|
+
cwd,
|
|
846
|
+
input: ""
|
|
847
|
+
});
|
|
848
|
+
if (!versionCheck.error && versionCheck.status === 0) {
|
|
849
|
+
return command;
|
|
850
|
+
}
|
|
851
|
+
return null;
|
|
852
|
+
}
|
|
853
|
+
if (!shouldAutoInstallTool(toolId))
|
|
854
|
+
return null;
|
|
855
|
+
const state = installStateFor(cwd, toolId);
|
|
856
|
+
if (state.suppressed)
|
|
857
|
+
return null;
|
|
858
|
+
const installStartedAt = Date.now();
|
|
859
|
+
const installed = await ensureTool(toolId);
|
|
860
|
+
if (installed) {
|
|
861
|
+
noteInstallSuccess(toolId, cwd);
|
|
862
|
+
emitCompensatingAvailableRow(cwd, toolId, installStartedAt, installed, latchKeysFor(toolId, command));
|
|
863
|
+
return installed;
|
|
864
|
+
}
|
|
865
|
+
noteInstallFailure(toolId, cwd);
|
|
866
|
+
return null;
|
|
867
|
+
}
|
|
868
|
+
async function resolveCommandArgsWithInstallFallback(command, toolId, cwd, versionArgs = ["--version"], timeout = 5e3) {
|
|
869
|
+
const versionCheck = await safeSpawnAsync(command.cmd, [...command.args, ...versionArgs], { timeout, cwd, input: "" });
|
|
870
|
+
if (!versionCheck.error && versionCheck.status === 0) {
|
|
871
|
+
return command;
|
|
872
|
+
}
|
|
873
|
+
const installed = await verifyOrInstallCommand(command.cmd, toolId, cwd, versionArgs, timeout);
|
|
874
|
+
if (!installed) {
|
|
875
|
+
return null;
|
|
876
|
+
}
|
|
877
|
+
if (installed === command.cmd) {
|
|
878
|
+
return command;
|
|
879
|
+
}
|
|
880
|
+
return { cmd: installed, args: [] };
|
|
881
|
+
}
|
|
882
|
+
async function resolveCommandWithInstallFallback(command, toolId, cwd, versionArgs = ["--version"], timeout = 5e3) {
|
|
883
|
+
return verifyOrInstallCommand(command, toolId, cwd, versionArgs, timeout);
|
|
884
|
+
}
|
|
885
|
+
async function resolveAvailableOrInstallUnshared(checker, toolId, cwd) {
|
|
886
|
+
const available = await checker.isAvailableAsync(cwd);
|
|
887
|
+
if (available) {
|
|
888
|
+
return checker.getCommand(cwd);
|
|
889
|
+
}
|
|
890
|
+
if (checker.getOutcome?.(cwd) !== "missing")
|
|
891
|
+
return null;
|
|
892
|
+
if (!shouldAutoInstallTool(toolId))
|
|
893
|
+
return null;
|
|
894
|
+
const state = installStateFor(cwd, toolId);
|
|
895
|
+
if (state.suppressed) {
|
|
896
|
+
return null;
|
|
897
|
+
}
|
|
898
|
+
const installStartedAt = Date.now();
|
|
899
|
+
const installed = await ensureTool(toolId);
|
|
900
|
+
if (installed) {
|
|
901
|
+
noteInstallSuccess(toolId, cwd);
|
|
902
|
+
checker.reset?.();
|
|
903
|
+
noteLatchedUnavailable(cwd, toolId);
|
|
904
|
+
emitCompensatingAvailableRow(cwd, toolId, installStartedAt, installed, latchKeysFor(toolId, checker.getCommand(cwd) ?? void 0));
|
|
905
|
+
return installed;
|
|
906
|
+
}
|
|
907
|
+
noteInstallFailure(toolId, cwd);
|
|
908
|
+
return null;
|
|
909
|
+
}
|
|
910
|
+
function resolveAvailableOrInstall(checker, toolId, cwd) {
|
|
911
|
+
const key = normalizeEphemeralMapKey(cwd);
|
|
912
|
+
let byTool = resolveInstallInFlightByCwd.get(key);
|
|
913
|
+
if (!byTool) {
|
|
914
|
+
byTool = /* @__PURE__ */ new Map();
|
|
915
|
+
resolveInstallInFlightByCwd.set(key, byTool);
|
|
916
|
+
}
|
|
917
|
+
const existing = byTool.get(toolId);
|
|
918
|
+
if (existing)
|
|
919
|
+
return existing;
|
|
920
|
+
const generation = availabilityGeneration.capture();
|
|
921
|
+
const promise = resolveAvailableOrInstallUnshared(checker, toolId, cwd).finally(() => {
|
|
922
|
+
generation.guardedWrite(`${toolId}@${key}`, () => {
|
|
923
|
+
const current = resolveInstallInFlightByCwd.get(key);
|
|
924
|
+
if (current?.get(toolId) === promise) {
|
|
925
|
+
current.delete(toolId);
|
|
926
|
+
if (current.size === 0)
|
|
927
|
+
resolveInstallInFlightByCwd.delete(key);
|
|
928
|
+
}
|
|
929
|
+
});
|
|
930
|
+
});
|
|
931
|
+
byTool.set(toolId, promise);
|
|
932
|
+
return promise;
|
|
933
|
+
}
|
|
934
|
+
var sgLatch = createAvailabilityLatch();
|
|
935
|
+
var sgCmd = null;
|
|
936
|
+
var sgCmdArgs = [];
|
|
937
|
+
var sgAvailableInFlight = null;
|
|
938
|
+
var sgAvailabilityGeneration = availabilityGeneration.current();
|
|
939
|
+
function ensureCurrentSgGeneration() {
|
|
940
|
+
if (sgAvailabilityGeneration === availabilityGeneration.current())
|
|
941
|
+
return;
|
|
942
|
+
sgLatch.reset();
|
|
943
|
+
sgCmd = null;
|
|
944
|
+
sgCmdArgs = [];
|
|
945
|
+
sgAvailableInFlight = null;
|
|
946
|
+
sgAvailabilityGeneration = availabilityGeneration.current();
|
|
947
|
+
}
|
|
948
|
+
function getSgCommand() {
|
|
949
|
+
ensureCurrentSgGeneration();
|
|
950
|
+
return {
|
|
951
|
+
cmd: sgCmd ?? "npx",
|
|
952
|
+
args: sgCmdArgs.length ? sgCmdArgs : ["--no", "--", "ast-grep"]
|
|
953
|
+
};
|
|
954
|
+
}
|
|
955
|
+
async function resolveLocalFirstAsync(toolName, cwd, windowsExt = ".cmd") {
|
|
956
|
+
const isWin = process.platform === "win32";
|
|
957
|
+
const binName = isWin ? `${toolName}${windowsExt}` : toolName;
|
|
958
|
+
const local = path.join(cwd, "node_modules", ".bin", binName);
|
|
959
|
+
if (fs.existsSync(local))
|
|
960
|
+
return { cmd: local, args: [] };
|
|
961
|
+
const globalBin = await findGlobalBinary(toolName, windowsExt);
|
|
962
|
+
if (globalBin)
|
|
963
|
+
return { cmd: globalBin, args: [] };
|
|
964
|
+
const globalCheck = await probeToolAsync(toolName, ["--version"], {
|
|
965
|
+
timeout: 3e3
|
|
966
|
+
});
|
|
967
|
+
if (!globalCheck.error && globalCheck.status === 0) {
|
|
968
|
+
return { cmd: toolName, args: [] };
|
|
969
|
+
}
|
|
970
|
+
return { cmd: "npx", args: ["--no", toolName] };
|
|
971
|
+
}
|
|
972
|
+
var pyright = createAvailabilityChecker("pyright", ".exe");
|
|
973
|
+
var ruff = createAvailabilityChecker("ruff", ".exe");
|
|
974
|
+
var biome = createAvailabilityChecker("biome");
|
|
975
|
+
function resolveRunnerCwd(ctx, tool) {
|
|
976
|
+
return resolveToolCwd("runner", tool, ctx.filePath, ctx).cwd;
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
export {
|
|
980
|
+
lspPrimaryCoversFile,
|
|
981
|
+
coveringLaneAvailable,
|
|
982
|
+
findManagedNodeToolBinary,
|
|
983
|
+
resolveManagedToolClient,
|
|
984
|
+
getManagedToolEnvironment,
|
|
985
|
+
discoverManagedTool,
|
|
986
|
+
getDispatchAvailabilityGeneration,
|
|
987
|
+
recordAvailabilityProbeOverrun,
|
|
988
|
+
resetDispatchAvailabilityState,
|
|
989
|
+
createAvailabilityChecker,
|
|
990
|
+
createCwdCachedProbe,
|
|
991
|
+
resolveToolCommand,
|
|
992
|
+
resolveVendorToolCommand,
|
|
993
|
+
resolveToolCommandWithInstallFallback,
|
|
994
|
+
resolveCommandArgsWithInstallFallback,
|
|
995
|
+
resolveAvailableOrInstall,
|
|
996
|
+
getSgCommand,
|
|
997
|
+
resolveLocalFirstAsync,
|
|
998
|
+
resolveRunnerCwd
|
|
999
|
+
};
|