@herbertgao/pi-extensions 2026.9.0 → 2026.9.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/node_modules/@czottmann/pi-automode/CHANGELOG.md +13 -1
- package/node_modules/@czottmann/pi-automode/README.md +20 -0
- package/node_modules/@czottmann/pi-automode/docs/GLOSSARY.md +1 -1
- package/node_modules/@czottmann/pi-automode/docs/automode-classifier-flow.md +2 -1
- package/node_modules/@czottmann/pi-automode/docs/defaults.md +3 -2
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/classifier.ts +38 -2
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/constants.ts +5 -3
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/extension.ts +11 -3
- package/node_modules/@czottmann/pi-automode/package.json +1 -1
- package/node_modules/@pi-plugins/fast-mode/README.md +5 -3
- package/node_modules/@pi-plugins/fast-mode/dist/index.d.mts.map +1 -1
- package/node_modules/@pi-plugins/fast-mode/dist/index.mjs +20 -55
- package/node_modules/@pi-plugins/fast-mode/dist/index.mjs.map +1 -1
- package/node_modules/@pi-plugins/fast-mode/package.json +1 -1
- package/node_modules/pi-lens/CHANGELOG.md +988 -0
- package/node_modules/pi-lens/README.md +3 -0
- package/node_modules/pi-lens/config/biome/core.jsonc +11 -2
- package/node_modules/pi-lens/config/dependency-cruiser-eager-allowlist.json +13 -1
- package/node_modules/pi-lens/dist/clients/actionable-warnings-logger.js +2 -2
- package/node_modules/pi-lens/dist/clients/actionable-warnings.js +927 -80
- package/node_modules/pi-lens/dist/clients/agent-behavior-client.js +13 -4
- package/node_modules/pi-lens/dist/clients/ast-grep-client.js +123 -3
- package/node_modules/pi-lens/dist/clients/ast-grep-rule-manager.js +60 -5
- package/node_modules/pi-lens/dist/clients/ast-grep-tool-logger.js +2 -2
- package/node_modules/pi-lens/dist/clients/bash-file-access.js +1 -3
- package/node_modules/pi-lens/dist/clients/biome-client.js +9 -2
- package/node_modules/pi-lens/dist/clients/blocker-freshness.js +14 -0
- package/node_modules/pi-lens/dist/clients/bootstrap.js +509 -73
- package/node_modules/pi-lens/dist/clients/bounded-cache.js +152 -12
- package/node_modules/pi-lens/dist/clients/bounded-telemetry.js +59 -4
- package/node_modules/pi-lens/dist/clients/bundled-resource-health.js +113 -0
- package/node_modules/pi-lens/dist/clients/bus-events-logger.js +2 -2
- package/node_modules/pi-lens/dist/clients/cache/rule-cache.js +31 -4
- package/node_modules/pi-lens/dist/clients/cache-manager.js +105 -6
- package/node_modules/pi-lens/dist/clients/cache-observability.js +44 -18
- package/node_modules/pi-lens/dist/clients/cargo-manifest.js +422 -0
- package/node_modules/pi-lens/dist/clients/cascade-logger.js +2 -2
- package/node_modules/pi-lens/dist/clients/code-quality-warnings.js +13 -3
- package/node_modules/pi-lens/dist/clients/complexity-client.js +16 -5
- package/node_modules/pi-lens/dist/clients/config-core/deny.js +221 -0
- package/node_modules/pi-lens/dist/clients/config-core/index.js +47 -0
- package/node_modules/pi-lens/dist/clients/config-core/merge.js +357 -0
- package/node_modules/pi-lens/dist/clients/config-core/normalize.js +340 -0
- package/node_modules/pi-lens/dist/clients/config-core/process-spec.js +248 -0
- package/node_modules/pi-lens/dist/clients/config-core/provenance.js +171 -0
- package/node_modules/pi-lens/dist/clients/config-core/records.js +218 -0
- package/node_modules/pi-lens/dist/clients/config-core/resolve.js +125 -0
- package/node_modules/pi-lens/dist/clients/config-core/safe-object.js +78 -0
- package/node_modules/pi-lens/dist/clients/config-core/schema.js +167 -0
- package/node_modules/pi-lens/dist/clients/config-diagnostic-codes.js +281 -0
- package/node_modules/pi-lens/dist/clients/config-locations.js +160 -0
- package/node_modules/pi-lens/dist/clients/config-resolve.js +789 -0
- package/node_modules/pi-lens/dist/clients/config-schema.js +197 -0
- package/node_modules/pi-lens/dist/clients/config-warn.js +407 -0
- package/node_modules/pi-lens/dist/clients/dead-code-client.js +19 -14
- package/node_modules/pi-lens/dist/clients/dead-code-logger.js +2 -2
- package/node_modules/pi-lens/dist/clients/deadline-utils.js +178 -0
- package/node_modules/pi-lens/dist/clients/debug-handles.js +2 -2
- package/node_modules/pi-lens/dist/clients/debug-heap.js +3 -3
- package/node_modules/pi-lens/dist/clients/deferred-lsp-work.js +106 -0
- package/node_modules/pi-lens/dist/clients/degradation-ledger.js +113 -7
- package/node_modules/pi-lens/dist/clients/dependency-checker.js +8 -19
- package/node_modules/pi-lens/dist/clients/diagnostic-line-freshness.js +12 -9
- package/node_modules/pi-lens/dist/clients/diagnostic-logger.js +14 -4
- package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +162 -18
- package/node_modules/pi-lens/dist/clients/dispatch/fact-store.js +97 -0
- package/node_modules/pi-lens/dist/clients/dispatch/integration.js +9 -7
- package/node_modules/pi-lens/dist/clients/dispatch/runners/actionlint.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ast-grep-napi.js +380 -26
- package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/cpp-check.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/credo.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/cue-vet.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/dart-analyze.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/detekt.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/dotnet-build.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/elixir-check.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/eslint.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/fact-rules.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/fish-indent.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/gleam-check.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/go-vet.js +1 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/golangci-lint.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/hadolint.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-lint.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-render.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/htmlhint.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/javac.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ktlint.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/mypy.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/oxlint.js +13 -18
- package/node_modules/pi-lens/dist/clients/dispatch/runners/php-lint.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/phpstan.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/prisma-validate.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/psscriptanalyzer.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/pyright.js +7 -4
- package/node_modules/pi-lens/dist/clients/dispatch/runners/rubocop.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ruff.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/rust-clippy.js +1 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/shellcheck.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/shfmt.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/spellcheck.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/spotbugs.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/sqlfluff.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/stylelint.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/swiftlint.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/taplo.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/terragrunt.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/tflint.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/tree-sitter.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/trivy-config.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/availability-policy.js +3 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/diagnostic-parsers.js +3 -4
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +194 -80
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/toolchain-availability.js +84 -15
- package/node_modules/pi-lens/dist/clients/dispatch/runners/vale.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/yamllint.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/zig-check.js +0 -1
- package/node_modules/pi-lens/dist/clients/disposition-logger.js +3 -3
- package/node_modules/pi-lens/dist/clients/effective-config.js +403 -0
- package/node_modules/pi-lens/dist/clients/error-class.js +23 -0
- package/node_modules/pi-lens/dist/clients/event-loop-hold.js +274 -0
- package/node_modules/pi-lens/dist/clients/extension-log.js +2 -2
- package/node_modules/pi-lens/dist/clients/feature-hints.js +2 -1
- package/node_modules/pi-lens/dist/clients/file-time.js +6 -1
- package/node_modules/pi-lens/dist/clients/file-utils.js +112 -9
- package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +50 -13
- package/node_modules/pi-lens/dist/clients/format-service.js +6 -1
- package/node_modules/pi-lens/dist/clients/formatters.js +276 -102
- package/node_modules/pi-lens/dist/clients/freshness-cadence.js +17 -0
- package/node_modules/pi-lens/dist/clients/generated-artifacts.js +114 -19
- package/node_modules/pi-lens/dist/clients/generation-guard.js +4 -9
- package/node_modules/pi-lens/dist/clients/git-guard.js +1 -1
- package/node_modules/pi-lens/dist/clients/go-client.js +39 -0
- package/node_modules/pi-lens/dist/clients/gradle-ktfmt-style.js +252 -0
- package/node_modules/pi-lens/dist/clients/hashline-anchor.js +424 -0
- package/node_modules/pi-lens/dist/clients/hook-budgets.js +76 -0
- package/node_modules/pi-lens/dist/clients/host-edit-normalize.js +5 -2
- package/node_modules/pi-lens/dist/clients/host-ports.js +1 -1
- package/node_modules/pi-lens/dist/clients/installer/index.js +71 -52
- package/node_modules/pi-lens/dist/clients/instance-reaper.js +104 -230
- package/node_modules/pi-lens/dist/clients/instance-registry.js +6 -3
- package/node_modules/pi-lens/dist/clients/language-registry.js +595 -0
- package/node_modules/pi-lens/dist/clients/latency-logger.js +160 -2
- package/node_modules/pi-lens/dist/clients/ledger-bounds.js +13 -0
- package/node_modules/pi-lens/dist/clients/lens-config.js +141 -30
- package/node_modules/pi-lens/dist/clients/lens-engine.js +30 -37
- package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +59 -6
- package/node_modules/pi-lens/dist/clients/log-cleanup.js +2 -2
- package/node_modules/pi-lens/dist/clients/lsp/aggregation.js +3 -1
- package/node_modules/pi-lens/dist/clients/lsp/client.js +168 -30
- package/node_modules/pi-lens/dist/clients/lsp/config.js +483 -158
- package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +1 -1
- package/node_modules/pi-lens/dist/clients/lsp/edits.js +15 -2
- package/node_modules/pi-lens/dist/clients/lsp/index.js +676 -71
- package/node_modules/pi-lens/dist/clients/lsp/language.js +18 -169
- package/node_modules/pi-lens/dist/clients/lsp/launch.js +2 -1
- package/node_modules/pi-lens/dist/clients/lsp/pending-aux-coverage.js +5 -16
- package/node_modules/pi-lens/dist/clients/lsp/server.js +284 -147
- package/node_modules/pi-lens/dist/clients/lsp/session-roots.js +116 -23
- package/node_modules/pi-lens/dist/clients/lsp/spawn-history.js +2 -7
- package/node_modules/pi-lens/dist/clients/lsp/tsserver-sync.js +9 -2
- package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +1 -1
- package/node_modules/pi-lens/dist/clients/lsp-mutation.js +163 -21
- package/node_modules/pi-lens/dist/clients/map-with-concurrency.js +36 -0
- package/node_modules/pi-lens/dist/clients/mcp/analyze.js +33 -4
- package/node_modules/pi-lens/dist/clients/mcp/session.js +5 -16
- package/node_modules/pi-lens/dist/clients/memory-sampler.js +8 -3
- package/node_modules/pi-lens/dist/clients/middle-man-analysis.js +2 -4
- package/node_modules/pi-lens/dist/clients/module-report.js +20 -45
- package/node_modules/pi-lens/dist/clients/mutating-tool.js +651 -0
- package/node_modules/pi-lens/dist/clients/mutation-attribution.js +368 -0
- package/node_modules/pi-lens/dist/clients/mutation-bridge.js +240 -0
- package/node_modules/pi-lens/dist/clients/ndjson-logger.js +247 -20
- package/node_modules/pi-lens/dist/clients/observed-mutation-sources.js +101 -0
- package/node_modules/pi-lens/dist/clients/observed-mutation.js +1215 -0
- package/node_modules/pi-lens/dist/clients/opaque-mutation-scan.js +68 -22
- package/node_modules/pi-lens/dist/clients/opengrep-config.js +4 -0
- package/node_modules/pi-lens/dist/clients/package-manager.js +195 -26
- package/node_modules/pi-lens/dist/clients/partial-edit-apply.js +359 -80
- package/node_modules/pi-lens/dist/clients/path-attribution-telemetry.js +23 -7
- package/node_modules/pi-lens/dist/clients/path-keyed-map.js +21 -2
- package/node_modules/pi-lens/dist/clients/path-utils.js +428 -13
- package/node_modules/pi-lens/dist/clients/persist-debounce.js +8 -1
- package/node_modules/pi-lens/dist/clients/php-cs-fixer-config.js +114 -0
- package/node_modules/pi-lens/dist/clients/pipeline.js +77 -16
- package/node_modules/pi-lens/dist/clients/probe-home-state.js +228 -0
- package/node_modules/pi-lens/dist/clients/process-bridge.js +66 -0
- package/node_modules/pi-lens/dist/clients/process-snapshot.js +68 -0
- package/node_modules/pi-lens/dist/clients/project-diagnostics/fresh-fetch.js +4 -3
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/runner-findings.js +27 -3
- package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +51 -20
- package/node_modules/pi-lens/dist/clients/project-lens-config.js +393 -122
- package/node_modules/pi-lens/dist/clients/project-snapshot.js +52 -24
- package/node_modules/pi-lens/dist/clients/python-environment.js +217 -0
- package/node_modules/pi-lens/dist/clients/python-provenance.js +639 -0
- package/node_modules/pi-lens/dist/clients/quiet-window.js +6 -1
- package/node_modules/pi-lens/dist/clients/read-bridge.js +13 -21
- package/node_modules/pi-lens/dist/clients/read-expansion.js +9 -46
- package/node_modules/pi-lens/dist/clients/read-guard-logger.js +15 -4
- package/node_modules/pi-lens/dist/clients/read-guard-tool-lines.js +364 -212
- package/node_modules/pi-lens/dist/clients/read-guard.js +21 -0
- package/node_modules/pi-lens/dist/clients/resource-sampler.js +195 -96
- package/node_modules/pi-lens/dist/clients/review-graph/builder.js +152 -109
- package/node_modules/pi-lens/dist/clients/review-graph/service.js +55 -3
- package/node_modules/pi-lens/dist/clients/review-graph/shared-extraction-ir.js +7 -15
- package/node_modules/pi-lens/dist/clients/review-graph/workspace-modules.js +10 -74
- package/node_modules/pi-lens/dist/clients/review-graph-logger.js +9 -3
- package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +18 -2
- package/node_modules/pi-lens/dist/clients/runtime-context.js +49 -16
- package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +25 -6
- package/node_modules/pi-lens/dist/clients/runtime-session.js +139 -22
- package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +168 -35
- package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +797 -243
- package/node_modules/pi-lens/dist/clients/runtime-turn.js +1028 -53
- package/node_modules/pi-lens/dist/clients/rust-client.js +31 -0
- package/node_modules/pi-lens/dist/clients/safe-spawn.js +33 -10
- package/node_modules/pi-lens/dist/clients/sanitize.js +7 -1
- package/node_modules/pi-lens/dist/clients/scratch-tree-policy.js +1 -3
- package/node_modules/pi-lens/dist/clients/security-scan-client.js +3 -0
- package/node_modules/pi-lens/dist/clients/session-lifecycle.js +1 -1
- package/node_modules/pi-lens/dist/clients/session-start-observability.js +79 -0
- package/node_modules/pi-lens/dist/clients/sessionstart-logger.js +12 -3
- package/node_modules/pi-lens/dist/clients/sgconfig.js +6 -1
- package/node_modules/pi-lens/dist/clients/skills-resolver.js +105 -0
- package/node_modules/pi-lens/dist/clients/smells-rollup.js +2 -2
- package/node_modules/pi-lens/dist/clients/string-utils.js +13 -0
- package/node_modules/pi-lens/dist/clients/subagent-mode.js +17 -4
- package/node_modules/pi-lens/dist/clients/test-runner-client.js +176 -39
- package/node_modules/pi-lens/dist/clients/test-runner-delivery.js +239 -0
- package/node_modules/pi-lens/dist/clients/tool-definition.js +41 -1
- package/node_modules/pi-lens/dist/clients/tool-policy.js +91 -21
- package/node_modules/pi-lens/dist/clients/tree-sitter-cache.js +40 -40
- package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +86 -48
- package/node_modules/pi-lens/dist/clients/tree-sitter-logger.js +2 -2
- package/node_modules/pi-lens/dist/clients/tree-sitter-query-loader.js +81 -1
- package/node_modules/pi-lens/dist/clients/tree-sitter-shared.js +51 -46
- package/node_modules/pi-lens/dist/clients/tree-sitter-symbol-extractor.js +28 -0
- package/node_modules/pi-lens/dist/clients/typos-config.js +5 -0
- package/node_modules/pi-lens/dist/clients/user-notify.js +6 -2
- package/node_modules/pi-lens/dist/clients/widget-state.js +191 -26
- package/node_modules/pi-lens/dist/clients/word-index-logger.js +2 -2
- package/node_modules/pi-lens/dist/clients/word-index-store.js +20 -5
- package/node_modules/pi-lens/dist/clients/word-index.js +243 -31
- package/node_modules/pi-lens/dist/clients/workspace-topology.js +8 -1
- package/node_modules/pi-lens/dist/clients/zizmor-config.js +3 -0
- package/node_modules/pi-lens/dist/index.js +64335 -54300
- package/node_modules/pi-lens/dist/mcp/analyze-cli.js +3 -1
- package/node_modules/pi-lens/dist/mcp/server.js +127 -5
- package/node_modules/pi-lens/dist/scripts/lib/process-scan.mjs +583 -0
- package/node_modules/pi-lens/dist/scripts/lib/skills-predicate.mjs +129 -0
- package/node_modules/pi-lens/dist/tools/effective-config.js +89 -0
- package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +95 -24
- package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +67 -80
- package/node_modules/pi-lens/dist/tools/lsp-navigation.js +37 -16
- package/node_modules/pi-lens/dist/tools/shared.js +0 -1
- package/node_modules/pi-lens/docs/agent-guide.md +64 -1
- package/node_modules/pi-lens/docs/configuration.md +222 -0
- package/node_modules/pi-lens/docs/dependencies.md +3 -3
- package/node_modules/pi-lens/docs/features.md +44 -5
- package/node_modules/pi-lens/docs/language-coverage.md +2 -2
- package/node_modules/pi-lens/docs/pi-lens-fixer.md +25 -0
- package/node_modules/pi-lens/docs/pi-lens-investigator.md +25 -0
- package/node_modules/pi-lens/docs/pi-lens-reviewer.md +27 -0
- package/node_modules/pi-lens/docs/pi-lens-subagent.md +38 -0
- package/node_modules/pi-lens/docs/pi-lens-warden.md +55 -0
- package/node_modules/pi-lens/docs/public-api-stability.md +359 -0
- package/node_modules/pi-lens/docs/release-qa-baseline.md +182 -0
- package/node_modules/pi-lens/docs/subagent-compat.md +110 -30
- package/node_modules/pi-lens/docs/tree-sitter_rules_catalog.md +2 -2
- package/node_modules/pi-lens/package.json +15 -23
- package/node_modules/pi-lens/rules/tree-sitter-queries/python/python-cross-language-method.yml +3 -3
- package/node_modules/pi-lens/rules/tree-sitter-queries/python/python-hallucinated-import.yml +2 -2
- package/node_modules/pi-lens/rules/tree-sitter-queries/python/python-sql-injection.yml +12 -2
- package/node_modules/pi-lens/scripts/analyze-pi-lens-logs.mjs +192 -1
- package/node_modules/pi-lens/scripts/install-selftest.mjs +58 -2
- package/node_modules/pi-lens/scripts/lib/skills-predicate.mjs +129 -0
- package/node_modules/pi-lens/scripts/rpc-load-check.mjs +3 -1
- package/node_modules/pi-web-access/CHANGELOG.md +28 -0
- package/node_modules/pi-web-access/README.md +62 -15
- package/node_modules/pi-web-access/curator-page.ts +3 -1
- package/node_modules/pi-web-access/curator-server.ts +5 -1
- package/node_modules/pi-web-access/gemini-search.ts +8 -4
- package/node_modules/pi-web-access/github-extract.ts +242 -1
- package/node_modules/pi-web-access/index.ts +118 -64
- package/node_modules/pi-web-access/mistral-search.ts +281 -0
- package/node_modules/pi-web-access/package.json +2 -2
- package/node_modules/pi-web-access/perplexity.ts +14 -1
- package/node_modules/pi-web-access/utils.ts +23 -6
- package/node_modules/pi-web-access/xai-search.ts +96 -33
- package/package.json +5 -5
|
@@ -4,6 +4,7 @@ import { fileURLToPath } from "node:url";
|
|
|
4
4
|
import { Worker } from "node:worker_threads";
|
|
5
5
|
import { gunzipSync, gzipSync } from "node:zlib";
|
|
6
6
|
import { writeFileAtomic } from "./atomic-write.js";
|
|
7
|
+
import { BoundedFifoMap } from "./bounded-cache.js";
|
|
7
8
|
import { getProjectDataDir } from "./file-utils.js";
|
|
8
9
|
import { incrementDegradationCount } from "./degradation-ledger.js";
|
|
9
10
|
import { readJsonCache } from "./json-cache-read.js";
|
|
@@ -130,14 +131,14 @@ export function readProjectSnapshotMeta(cwd) {
|
|
|
130
131
|
export function isProjectSnapshotMetaStale(meta, currentProjectSeq) {
|
|
131
132
|
return (meta.version !== PROJECT_SNAPSHOT_VERSION || meta.seq !== currentProjectSeq);
|
|
132
133
|
}
|
|
133
|
-
const SNAPSHOT_PARSE_CACHE_MAX = 4;
|
|
134
|
+
export const SNAPSHOT_PARSE_CACHE_MAX = 4;
|
|
134
135
|
// #957 review: the cache exists to avoid re-parsing NORMAL snapshots within a
|
|
135
136
|
// session. A 112MB-class body parses to hundreds of MB of heap — pinning that
|
|
136
137
|
// for process lifetime inverts the win, so oversized bodies are simply never
|
|
137
138
|
// cached (they re-parse per read, exactly the pre-#947 behavior). Measured
|
|
138
139
|
// against the UNCOMPRESSED body size, never the (much smaller) gz file size.
|
|
139
140
|
const SNAPSHOT_PARSE_CACHE_MAX_BYTES = 24 * 1024 * 1024;
|
|
140
|
-
const snapshotParseCache = new
|
|
141
|
+
const snapshotParseCache = new BoundedFifoMap(SNAPSHOT_PARSE_CACHE_MAX);
|
|
141
142
|
function withoutWordIndex(snapshot) {
|
|
142
143
|
if (!snapshot?.wordIndex)
|
|
143
144
|
return snapshot;
|
|
@@ -145,18 +146,13 @@ function withoutWordIndex(snapshot) {
|
|
|
145
146
|
return stripped;
|
|
146
147
|
}
|
|
147
148
|
function cacheParsedSnapshot(snapshotPath, entry) {
|
|
148
|
-
// Refresh recency (
|
|
149
|
+
// Refresh recency (delete then set moves the key to the newest position;
|
|
150
|
+
// BoundedFifoMap itself never reorders an already-present key on set()).
|
|
149
151
|
snapshotParseCache.delete(snapshotPath);
|
|
150
152
|
snapshotParseCache.set(snapshotPath, entry);
|
|
151
|
-
while (snapshotParseCache.size > SNAPSHOT_PARSE_CACHE_MAX) {
|
|
152
|
-
const oldest = snapshotParseCache.keys().next().value;
|
|
153
|
-
if (oldest === undefined)
|
|
154
|
-
break;
|
|
155
|
-
snapshotParseCache.delete(oldest);
|
|
156
|
-
}
|
|
157
153
|
}
|
|
158
154
|
const authoritativeSnapshots = new Map();
|
|
159
|
-
const PROJECT_SNAPSHOT_MAX_WARM_ROOTS = 8;
|
|
155
|
+
export const PROJECT_SNAPSHOT_MAX_WARM_ROOTS = 8;
|
|
160
156
|
const PROJECT_SNAPSHOT_IDLE_EVICT_MS_DEFAULT = 20 * 60_000;
|
|
161
157
|
function projectSnapshotIdleEvictMs() {
|
|
162
158
|
const value = Number.parseInt(process.env.PI_LENS_PROJECT_SNAPSHOT_IDLE_EVICT_MS ?? "", 10);
|
|
@@ -620,8 +616,8 @@ export function loadProjectSnapshotWithoutWordIndex(cwd) {
|
|
|
620
616
|
return loadProjectSnapshotInternal(cwd, false);
|
|
621
617
|
}
|
|
622
618
|
const _snapshotGenerationStates = new Map();
|
|
623
|
-
const _successfulSnapshotPersists = new
|
|
624
|
-
const _failedSnapshotPersists = new
|
|
619
|
+
const _successfulSnapshotPersists = new BoundedFifoMap(PROJECT_SNAPSHOT_MAX_WARM_ROOTS);
|
|
620
|
+
const _failedSnapshotPersists = new BoundedFifoMap(PROJECT_SNAPSHOT_MAX_WARM_ROOTS);
|
|
625
621
|
const _activeSnapshotPersists = new Map();
|
|
626
622
|
const _queuedSnapshotPersists = new Map();
|
|
627
623
|
const _snapshotWorkerRequests = new Map();
|
|
@@ -648,12 +644,6 @@ function pendingSnapshotIsCurrent(pending) {
|
|
|
648
644
|
function rememberSuccessfulSnapshotPersist(key, record) {
|
|
649
645
|
_successfulSnapshotPersists.delete(key);
|
|
650
646
|
_successfulSnapshotPersists.set(key, record);
|
|
651
|
-
while (_successfulSnapshotPersists.size > PROJECT_SNAPSHOT_MAX_WARM_ROOTS) {
|
|
652
|
-
const oldest = _successfulSnapshotPersists.keys().next().value;
|
|
653
|
-
if (oldest === undefined)
|
|
654
|
-
break;
|
|
655
|
-
_successfulSnapshotPersists.delete(oldest);
|
|
656
|
-
}
|
|
657
647
|
}
|
|
658
648
|
function assessSnapshotBodyIntegrity(meta, body) {
|
|
659
649
|
if (meta.gzBytes === undefined) {
|
|
@@ -808,12 +798,6 @@ function recordSnapshotPersistFailure(pending, error, bodyPersisted = false) {
|
|
|
808
798
|
seq: pending.snapshot.seq,
|
|
809
799
|
generation: pending.generation,
|
|
810
800
|
});
|
|
811
|
-
while (_failedSnapshotPersists.size > PROJECT_SNAPSHOT_MAX_WARM_ROOTS) {
|
|
812
|
-
const oldest = _failedSnapshotPersists.keys().next().value;
|
|
813
|
-
if (oldest === undefined)
|
|
814
|
-
break;
|
|
815
|
-
_failedSnapshotPersists.delete(oldest);
|
|
816
|
-
}
|
|
817
801
|
deleteAuthoritativeSnapshot(pending.key);
|
|
818
802
|
logLatency({
|
|
819
803
|
type: "phase",
|
|
@@ -1492,6 +1476,50 @@ export function setProjectSnapshotPromotionSeamForTests(seam) {
|
|
|
1492
1476
|
export function getProjectSnapshotPersistErrorForTests() {
|
|
1493
1477
|
return _lastSnapshotPersistErrorForTests;
|
|
1494
1478
|
}
|
|
1479
|
+
// ── #2442 test-only seams: exercise the three BoundedFifoMap-backed caches ──
|
|
1480
|
+
// through the exact same write path production uses (cacheParsedSnapshot /
|
|
1481
|
+
// rememberSuccessfulSnapshotPersist's delete+set refresh, and a direct write
|
|
1482
|
+
// mirroring recordSnapshotPersistFailure's), without the real gzip/worker
|
|
1483
|
+
// persistence pipeline or a full ProjectSnapshot fixture.
|
|
1484
|
+
/** Test-only: seed the parse cache exactly as `cacheParsedSnapshot` would. */
|
|
1485
|
+
export function _seedSnapshotParseCacheForTests(key, entry) {
|
|
1486
|
+
cacheParsedSnapshot(key, entry);
|
|
1487
|
+
}
|
|
1488
|
+
export function _snapshotParseCacheKeysForTests() {
|
|
1489
|
+
return [...snapshotParseCache.keys()];
|
|
1490
|
+
}
|
|
1491
|
+
/**
|
|
1492
|
+
* #2442 test-only: the exact `snapshotParseCache.get(key)` the production
|
|
1493
|
+
* read at {@link loadProjectSnapshot}'s parse-cache hit performs. A `.has()`
|
|
1494
|
+
* would not do — `.has()` reorders nothing on either bounded class, so a
|
|
1495
|
+
* has-based test cannot tell FIFO from LRU, which is the axis these bounded
|
|
1496
|
+
* tests exist to pin (#2442 review F4).
|
|
1497
|
+
*/
|
|
1498
|
+
export function _snapshotParseCacheGetForTests(key) {
|
|
1499
|
+
return snapshotParseCache.get(key) !== undefined;
|
|
1500
|
+
}
|
|
1501
|
+
/** Test-only: seed the successful-persist cache exactly as production would. */
|
|
1502
|
+
export function _seedSuccessfulSnapshotPersistForTests(key, record) {
|
|
1503
|
+
rememberSuccessfulSnapshotPersist(key, record);
|
|
1504
|
+
}
|
|
1505
|
+
export function _successfulSnapshotPersistKeysForTests() {
|
|
1506
|
+
return [..._successfulSnapshotPersists.keys()];
|
|
1507
|
+
}
|
|
1508
|
+
/** #2442 test-only: the same `_successfulSnapshotPersists.get(key)` the
|
|
1509
|
+
* persist-dedupe read and `getProjectSnapshotPersistStateForTests` perform.
|
|
1510
|
+
* See {@link _snapshotParseCacheGetForTests} for why `.has()` will not do. */
|
|
1511
|
+
export function _successfulSnapshotPersistGetForTests(key) {
|
|
1512
|
+
return _successfulSnapshotPersists.get(key) !== undefined;
|
|
1513
|
+
}
|
|
1514
|
+
/** Test-only: seed the failed-persist cache with the same write
|
|
1515
|
+
* `recordSnapshotPersistFailure` performs, without its side effects
|
|
1516
|
+
* (deleteAuthoritativeSnapshot / logLatency) or a full PendingSnapshotBody. */
|
|
1517
|
+
export function _seedFailedSnapshotPersistForTests(key, record) {
|
|
1518
|
+
_failedSnapshotPersists.set(key, record);
|
|
1519
|
+
}
|
|
1520
|
+
export function _failedSnapshotPersistKeysForTests() {
|
|
1521
|
+
return [..._failedSnapshotPersists.keys()];
|
|
1522
|
+
}
|
|
1495
1523
|
export function buildProjectSnapshotFromRuntime(args) {
|
|
1496
1524
|
return {
|
|
1497
1525
|
version: PROJECT_SNAPSHOT_VERSION,
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import { access, readFile } from "node:fs/promises";
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { extractTomlTableSection, hasTomlTable, parseTomlStringArray, } from "./cargo-manifest.js";
|
|
5
|
+
import { isAtOrAboveHomeDir, matchesWorkspaceMemberPattern, toPosix, UV_WORKSPACE_EXCLUDE_DIALECT, UV_WORKSPACE_MEMBERS_DIALECT, walkUpDirs, } from "./path-utils.js";
|
|
6
|
+
const UV_WORKSPACE_TABLE = "tool\\.uv\\.workspace";
|
|
7
|
+
/**
|
|
8
|
+
* Resolve the uv workspace root using the same discovery shape as uv:
|
|
9
|
+
* start at the nearest pyproject, then continue upward for an explicit
|
|
10
|
+
* `[tool.uv.workspace]` declaration. A nearest pyproject without that table
|
|
11
|
+
* is an implicit single-project workspace.
|
|
12
|
+
*
|
|
13
|
+
* The walk stops AT `homeDir` (`isAtOrAboveHomeDir`, the shared ceiling
|
|
14
|
+
* primitive from #625) so a `pyproject.toml` sitting in `/tmp`, `/home`, or
|
|
15
|
+
* `$HOME` itself cannot supply the environment for every project beneath it.
|
|
16
|
+
* `homeDir` is injected rather than read from `os.homedir()` inside the walk
|
|
17
|
+
* for the same reason every sibling walker takes it (#2536, #2544 F2): the
|
|
18
|
+
* ceiling is otherwise untestable.
|
|
19
|
+
*/
|
|
20
|
+
async function findUvWorkspace(startDir, homeDir) {
|
|
21
|
+
const resolvedStart = path.resolve(startDir);
|
|
22
|
+
let nearestProject;
|
|
23
|
+
for (const dir of walkUpDirs(startDir)) {
|
|
24
|
+
if (isAtOrAboveHomeDir(dir, homeDir))
|
|
25
|
+
break;
|
|
26
|
+
let content;
|
|
27
|
+
try {
|
|
28
|
+
content = await readFile(path.join(dir, "pyproject.toml"), "utf8");
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
if (!nearestProject)
|
|
34
|
+
nearestProject = dir;
|
|
35
|
+
if (hasTomlTable(content, UV_WORKSPACE_TABLE)) {
|
|
36
|
+
const workspaceTable = extractTomlTableSection(content, UV_WORKSPACE_TABLE);
|
|
37
|
+
return {
|
|
38
|
+
root: dir,
|
|
39
|
+
explicit: true,
|
|
40
|
+
projectRoot: nearestProject,
|
|
41
|
+
isStartDir: nearestProject === resolvedStart,
|
|
42
|
+
members: parseTomlStringArray(workspaceTable, "members"),
|
|
43
|
+
exclude: parseTomlStringArray(workspaceTable, "exclude"),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return nearestProject
|
|
48
|
+
? {
|
|
49
|
+
root: nearestProject,
|
|
50
|
+
explicit: false,
|
|
51
|
+
projectRoot: nearestProject,
|
|
52
|
+
isStartDir: nearestProject === resolvedStart,
|
|
53
|
+
members: [],
|
|
54
|
+
exclude: [],
|
|
55
|
+
}
|
|
56
|
+
: undefined;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Apply uv's explicit-workspace membership rules before inheriting its root
|
|
60
|
+
* environment. The workspace root is always a member; descendants must match
|
|
61
|
+
* a declared member glob and must not match an exclusion glob.
|
|
62
|
+
*
|
|
63
|
+
* The glob dialects are pinned to uv 3c979abda4530fe9bf3d92e9bcf5c5575e3b3126,
|
|
64
|
+
* `crates/uv-workspace/src/workspace.rs`, and live beside the ONE shared
|
|
65
|
+
* workspace-member matcher (#2591) instead of as a minimatch options block
|
|
66
|
+
* here: `UV_WORKSPACE_MEMBERS_DIALECT` for `members`
|
|
67
|
+
* (`is_included_in_workspace` — `MatchOptions { require_literal_separator:
|
|
68
|
+
* true, ..MatchOptions::new() }`) and `UV_WORKSPACE_EXCLUDE_DIALECT` for
|
|
69
|
+
* `exclude` (`WorkspaceExclusions::matches` — `Pattern::matches_path`, i.e.
|
|
70
|
+
* `MatchOptions::new()` defaults, where `require_literal_separator` is FALSE
|
|
71
|
+
* and a `*` therefore crosses `/`). Both normalize the pattern first
|
|
72
|
+
* (`normalize_path`, so a leading `./` is not part of the pattern) and are
|
|
73
|
+
* case-SENSITIVE on every platform with no literal-leading-dot requirement.
|
|
74
|
+
*
|
|
75
|
+
* That `exclude` option set used to be a documented limitation rather than
|
|
76
|
+
* behavior: minimatch cannot express a separator-crossing `*`, so
|
|
77
|
+
* `exclude = ['packages/a*c']` did not exclude `packages/a/b/c`. A dialect
|
|
78
|
+
* object can, so #2591 implements it — the one intentional answer change in
|
|
79
|
+
* that fold.
|
|
80
|
+
*/
|
|
81
|
+
function isUvWorkspaceMember(workspace, projectRoot) {
|
|
82
|
+
// No `projectRoot === workspace.root` shortcut. uv treats the workspace
|
|
83
|
+
// root as a member of its own workspace, but only in its capacity as a
|
|
84
|
+
// PROJECT — and a project already gets uv's settings through `isStartDir`,
|
|
85
|
+
// with its own `<root>/.venv` reached by the ordinary project candidate at
|
|
86
|
+
// the very same path. Answering "member" on directory equality made every
|
|
87
|
+
// non-project subdirectory of the workspace root inherit the workspace
|
|
88
|
+
// `.venv`, `exclude` included, because equality was tested before the
|
|
89
|
+
// walk result was consulted (review round 3, S2). The relative-path guard
|
|
90
|
+
// below returns false for the root itself, which is the intended answer.
|
|
91
|
+
const relative = toPosix(path.relative(workspace.root, projectRoot));
|
|
92
|
+
if (relative.length === 0 ||
|
|
93
|
+
relative === ".." ||
|
|
94
|
+
relative.startsWith("../") ||
|
|
95
|
+
path.isAbsolute(relative)) {
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
const matches = (dialect) => (pattern) => matchesWorkspaceMemberPattern(pattern, relative, dialect);
|
|
99
|
+
return (!workspace.exclude.some(matches(UV_WORKSPACE_EXCLUDE_DIALECT)) &&
|
|
100
|
+
workspace.members.some(matches(UV_WORKSPACE_MEMBERS_DIALECT)));
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Resolve the interpreter and executable directory for the project's Python
|
|
104
|
+
* environment without activating it or invoking a package manager.
|
|
105
|
+
*/
|
|
106
|
+
export async function detectPythonEnvironment(projectRoot, homeDir = os.homedir()) {
|
|
107
|
+
// `path.resolve` once at the seam entry so `isStartDir` below compares like
|
|
108
|
+
// with like: `walkUpDirs` resolves its input, a caller's argument need not
|
|
109
|
+
// be normalized.
|
|
110
|
+
const root = path.resolve(projectRoot);
|
|
111
|
+
const uvWorkspace = await findUvWorkspace(root, homeDir);
|
|
112
|
+
// `UV_PROJECT_ENVIRONMENT` and the workspace `.venv` are uv PROJECT
|
|
113
|
+
// settings. uv applies them to a directory only when that directory IS the
|
|
114
|
+
// project — a `pyproject.toml` merely sitting somewhere ABOVE it makes it a
|
|
115
|
+
// subdirectory of a project, not a project, and nothing below a project
|
|
116
|
+
// root inherits from it (the F3 decision, applied consistently). Exporting
|
|
117
|
+
// `UV_PROJECT_ENVIRONMENT` process-wide is uv's own documented CI/Docker
|
|
118
|
+
// recipe, so a gate on "a pyproject exists at or above root" lets one
|
|
119
|
+
// image-level variable capture every subdirectory on the box that happens
|
|
120
|
+
// to sit under some Python project.
|
|
121
|
+
const isProjectRoot = uvWorkspace?.isStartDir === true;
|
|
122
|
+
// A declared, non-excluded member of an EXPLICIT workspace is itself a
|
|
123
|
+
// project root, so this is a strict refinement of `isProjectRoot`: it adds
|
|
124
|
+
// the workspace `.venv` candidate and re-anchors a relative
|
|
125
|
+
// `UV_PROJECT_ENVIRONMENT` at the workspace root.
|
|
126
|
+
const memberWorkspaceRoot = isProjectRoot &&
|
|
127
|
+
uvWorkspace.explicit &&
|
|
128
|
+
isUvWorkspaceMember(uvWorkspace, root)
|
|
129
|
+
? uvWorkspace.root
|
|
130
|
+
: undefined;
|
|
131
|
+
const uvEnvironmentRoot = isProjectRoot
|
|
132
|
+
? (memberWorkspaceRoot ?? uvWorkspace.projectRoot)
|
|
133
|
+
: undefined;
|
|
134
|
+
const uvProjectEnvironment = process.env.UV_PROJECT_ENVIRONMENT;
|
|
135
|
+
// PEP 723 `uv run --script` environments are cache-keyed by script content;
|
|
136
|
+
// without a stable project marker or explicit path, they remain undiscoverable.
|
|
137
|
+
const candidates = [
|
|
138
|
+
...(uvEnvironmentRoot !== undefined && uvProjectEnvironment
|
|
139
|
+
? [
|
|
140
|
+
{
|
|
141
|
+
// `path.resolve` leaves an absolute value untouched and
|
|
142
|
+
// anchors a relative one at the project's workspace root.
|
|
143
|
+
root: path.resolve(uvEnvironmentRoot, uvProjectEnvironment),
|
|
144
|
+
source: "uv-project-environment",
|
|
145
|
+
},
|
|
146
|
+
]
|
|
147
|
+
: []),
|
|
148
|
+
...(memberWorkspaceRoot !== undefined
|
|
149
|
+
? [
|
|
150
|
+
{
|
|
151
|
+
root: path.join(memberWorkspaceRoot, ".venv"),
|
|
152
|
+
source: "uv-workspace",
|
|
153
|
+
},
|
|
154
|
+
]
|
|
155
|
+
: []),
|
|
156
|
+
{ root: process.env.VIRTUAL_ENV, source: "virtual-env" },
|
|
157
|
+
{ root: process.env.CONDA_PREFIX, source: "conda" },
|
|
158
|
+
{ root: path.join(root, ".venv"), source: "project-dot-venv" },
|
|
159
|
+
{ root: path.join(root, "venv"), source: "project-venv" },
|
|
160
|
+
];
|
|
161
|
+
for (const candidate of candidates) {
|
|
162
|
+
if (!candidate.root)
|
|
163
|
+
continue;
|
|
164
|
+
const binDir = path.join(candidate.root, process.platform === "win32" ? "Scripts" : "bin");
|
|
165
|
+
const pythonPath = path.join(binDir, process.platform === "win32" ? "python.exe" : "python");
|
|
166
|
+
try {
|
|
167
|
+
await access(pythonPath);
|
|
168
|
+
return {
|
|
169
|
+
root: candidate.root,
|
|
170
|
+
binDir,
|
|
171
|
+
pythonPath,
|
|
172
|
+
source: candidate.source,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
catch {
|
|
176
|
+
// The marker can outlive its environment. Continue to the next candidate.
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return undefined;
|
|
180
|
+
}
|
|
181
|
+
/** Preserve the existing interpreter-only API used by LSP initialization. */
|
|
182
|
+
export async function detectPythonVenv(projectRoot) {
|
|
183
|
+
return (await detectPythonEnvironment(projectRoot))?.pythonPath;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Build a child-only environment for Python tools. The host process remains
|
|
187
|
+
* unchanged, so another project can resolve a different environment.
|
|
188
|
+
*/
|
|
189
|
+
export function augmentPythonEnvironment(baseEnvironment, environment) {
|
|
190
|
+
if (!environment)
|
|
191
|
+
return baseEnvironment;
|
|
192
|
+
const inheritedPath = baseEnvironment.PATH ?? baseEnvironment.Path ?? baseEnvironment.path ?? "";
|
|
193
|
+
const augmentedPath = inheritedPath
|
|
194
|
+
? `${environment.binDir}${path.delimiter}${inheritedPath}`
|
|
195
|
+
: environment.binDir;
|
|
196
|
+
const childEnvironment = {
|
|
197
|
+
...baseEnvironment,
|
|
198
|
+
PATH: augmentedPath,
|
|
199
|
+
VIRTUAL_ENV: environment.root,
|
|
200
|
+
};
|
|
201
|
+
if (process.platform === "win32")
|
|
202
|
+
childEnvironment.Path = augmentedPath;
|
|
203
|
+
return childEnvironment;
|
|
204
|
+
}
|
|
205
|
+
/** Return explicit project-environment candidates before a bare PATH fallback. */
|
|
206
|
+
export function pythonEnvironmentToolCandidates(environment, command) {
|
|
207
|
+
if (!environment)
|
|
208
|
+
return [];
|
|
209
|
+
if (process.platform !== "win32") {
|
|
210
|
+
return [path.join(environment.binDir, command)];
|
|
211
|
+
}
|
|
212
|
+
return [
|
|
213
|
+
path.join(environment.binDir, `${command}.exe`),
|
|
214
|
+
path.join(environment.binDir, `${command}.cmd`),
|
|
215
|
+
path.join(environment.binDir, command),
|
|
216
|
+
];
|
|
217
|
+
}
|