@herbertgao/pi-extensions 2026.9.0 → 2026.9.2
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/@narumitw/pi-btw/README.md +57 -141
- package/node_modules/@narumitw/pi-btw/dist/index.ts +466 -41
- package/node_modules/@narumitw/pi-btw/dist/index.ts.map +4 -4
- package/node_modules/@narumitw/pi-btw/docs/workflows.md +74 -0
- package/node_modules/@narumitw/pi-btw/package.json +2 -1
- package/node_modules/@narumitw/pi-btw/src/btw.ts +15 -1
- package/node_modules/@narumitw/pi-btw/src/fullscreen-ui.ts +32 -2
- package/node_modules/@narumitw/pi-btw/src/keybindings.ts +330 -0
- package/node_modules/@narumitw/pi-btw/src/menu.ts +136 -19
- package/node_modules/@narumitw/pi-btw/src/settings.ts +32 -0
- package/node_modules/@narumitw/pi-btw/src/side-thread.ts +57 -5
- package/node_modules/@narumitw/pi-btw/src/transcript-pager.ts +52 -30
- 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 +1072 -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 -9
- package/node_modules/pi-lens/dist/clients/actionable-warnings.js +927 -80
- package/node_modules/pi-lens/dist/clients/advisory-provenance.js +1 -1
- 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 -9
- package/node_modules/pi-lens/dist/clients/ast-grep-types.js +2 -0
- package/node_modules/pi-lens/dist/clients/bash-file-access.js +133 -3
- package/node_modules/pi-lens/dist/clients/biome-client.js +9 -2
- package/node_modules/pi-lens/dist/clients/blocker-freshness.js +14 -6
- 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-pid-file-lock.js +1 -1
- package/node_modules/pi-lens/dist/clients/bounded-telemetry.js +59 -9
- package/node_modules/pi-lens/dist/clients/bundled-resource-health.js +113 -0
- package/node_modules/pi-lens/dist/clients/bus-events-logger.js +3 -11
- 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 +40 -19
- package/node_modules/pi-lens/dist/clients/cargo-manifest.js +422 -0
- package/node_modules/pi-lens/dist/clients/cascade-logger.js +2 -9
- package/node_modules/pi-lens/dist/clients/child-unref.js +1 -19
- 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 +50 -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 +164 -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 +165 -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 +234 -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 -6
- 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-dispositions.js +1 -1
- package/node_modules/pi-lens/dist/clients/diagnostic-line-freshness.js +12 -9
- package/node_modules/pi-lens/dist/clients/diagnostic-logger.js +15 -5
- package/node_modules/pi-lens/dist/clients/dispatch/collect-later-tier.js +0 -4
- package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +162 -44
- package/node_modules/pi-lens/dist/clients/dispatch/fact-store.js +97 -0
- package/node_modules/pi-lens/dist/clients/dispatch/integration.js +27 -8
- package/node_modules/pi-lens/dist/clients/dispatch/lazy.js +0 -6
- package/node_modules/pi-lens/dist/clients/dispatch/pending-runner-findings.js +1 -1
- package/node_modules/pi-lens/dist/clients/dispatch/plan.js +0 -3
- package/node_modules/pi-lens/dist/clients/dispatch/rules/high-complexity.js +2 -2
- package/node_modules/pi-lens/dist/clients/dispatch/rules/high-fan-out.js +1 -1
- 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 +383 -27
- 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 +4 -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 +1 -2
- 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 +14 -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 +6 -3
- 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 +1 -2
- 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 +1 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/shfmt.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/spellcheck.js +4 -3
- 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 -67
- 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/utils.js +0 -21
- package/node_modules/pi-lens/dist/clients/dispatch/runners/vale.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/yaml-rule-parser.js +2 -20
- package/node_modules/pi-lens/dist/clients/dispatch/runners/yamllint.js +1 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/zig-check.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/utils/format-utils.js +2 -2
- package/node_modules/pi-lens/dist/clients/disposition-logger.js +3 -10
- 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/event-loop-monitor.js +2 -2
- 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-kinds.js +1 -38
- package/node_modules/pi-lens/dist/clients/file-time.js +7 -2
- package/node_modules/pi-lens/dist/clients/file-utils.js +117 -10
- package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +50 -13
- package/node_modules/pi-lens/dist/clients/format-service.js +6 -2
- package/node_modules/pi-lens/dist/clients/formatters.js +385 -104
- package/node_modules/pi-lens/dist/clients/freshness-cadence.js +17 -0
- package/node_modules/pi-lens/dist/clients/generated-artifacts.js +116 -22
- package/node_modules/pi-lens/dist/clients/generation-guard.js +4 -9
- package/node_modules/pi-lens/dist/clients/git-guard.js +6 -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/grammar-source.js +3 -3
- 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 +289 -59
- package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh.js +84 -18
- package/node_modules/pi-lens/dist/clients/instance-reaper.js +110 -236
- package/node_modules/pi-lens/dist/clients/instance-registry.js +6 -3
- package/node_modules/pi-lens/dist/clients/language-profile.js +0 -9
- package/node_modules/pi-lens/dist/clients/language-registry.js +599 -0
- package/node_modules/pi-lens/dist/clients/latency-logger.js +165 -9
- package/node_modules/pi-lens/dist/clients/ledger-bounds.js +34 -1
- package/node_modules/pi-lens/dist/clients/lens-config.js +160 -30
- package/node_modules/pi-lens/dist/clients/lens-engine.js +33 -41
- package/node_modules/pi-lens/dist/clients/lens-events.js +1 -1
- package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +77 -6
- package/node_modules/pi-lens/dist/clients/lens-map.js +1 -1
- package/node_modules/pi-lens/dist/clients/log-cleanup.js +2 -38
- package/node_modules/pi-lens/dist/clients/lsp/aggregation.js +3 -1
- package/node_modules/pi-lens/dist/clients/lsp/client.js +172 -33
- package/node_modules/pi-lens/dist/clients/lsp/config.js +484 -158
- package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +1 -1
- package/node_modules/pi-lens/dist/clients/lsp/document-drift.js +1 -1
- package/node_modules/pi-lens/dist/clients/lsp/edits.js +18 -5
- package/node_modules/pi-lens/dist/clients/lsp/index.js +892 -96
- package/node_modules/pi-lens/dist/clients/lsp/inferred-project.js +1 -1
- package/node_modules/pi-lens/dist/clients/lsp/language.js +18 -177
- package/node_modules/pi-lens/dist/clients/lsp/launch.js +2 -1
- package/node_modules/pi-lens/dist/clients/lsp/path-utils.js +1 -1
- package/node_modules/pi-lens/dist/clients/lsp/pending-aux-coverage.js +5 -18
- 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/sync-kind.js +0 -1
- package/node_modules/pi-lens/dist/clients/lsp/tsserver-sync.js +14 -7
- package/node_modules/pi-lens/dist/clients/lsp/wait-policy/classification.js +6 -0
- package/node_modules/pi-lens/dist/clients/lsp/wait-policy/strategies.js +2 -1
- package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +1 -1
- package/node_modules/pi-lens/dist/clients/lsp-document-symbols.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/metrics-history.js +28 -107
- package/node_modules/pi-lens/dist/clients/middle-man-analysis.js +3 -5
- package/node_modules/pi-lens/dist/clients/module-report.js +21 -46
- 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 -24
- 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 +70 -28
- package/node_modules/pi-lens/dist/clients/opengrep-config.js +5 -1
- 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 +451 -15
- package/node_modules/pi-lens/dist/clients/performance-report.js +2 -2
- 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 +79 -18
- 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-changes.js +1 -1
- package/node_modules/pi-lens/dist/clients/project-diagnostics/extractors.js +1 -1
- 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/jscpd.js +1 -1
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/knip.js +1 -1
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/madge.js +1 -1
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/opengrep.js +1 -1
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/runner-findings.js +28 -4
- package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +51 -20
- package/node_modules/pi-lens/dist/clients/project-lens-config.js +438 -122
- package/node_modules/pi-lens/dist/clients/project-scan-policy.js +3 -51
- 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 +16 -5
- package/node_modules/pi-lens/dist/clients/read-guard-tool-lines.js +364 -212
- package/node_modules/pi-lens/dist/clients/read-guard.js +26 -2
- package/node_modules/pi-lens/dist/clients/recent-touches.js +2 -2
- package/node_modules/pi-lens/dist/clients/resource-sampler.js +195 -96
- package/node_modules/pi-lens/dist/clients/review-graph/builder.js +155 -114
- package/node_modules/pi-lens/dist/clients/review-graph/import-resolvers.js +1 -1
- 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 +19 -3
- 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 +184 -32
- package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +179 -36
- 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 -12
- package/node_modules/pi-lens/dist/clients/scan-utils.js +1 -56
- 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/session-summary.js +0 -24
- package/node_modules/pi-lens/dist/clients/sessionstart-logger.js +12 -3
- package/node_modules/pi-lens/dist/clients/sgconfig.js +7 -6
- package/node_modules/pi-lens/dist/clients/shared-checkout-guard.js +1 -1
- package/node_modules/pi-lens/dist/clients/skills-resolver.js +105 -0
- package/node_modules/pi-lens/dist/clients/smells-rollup.js +4 -4
- package/node_modules/pi-lens/dist/clients/startup-scan.js +2 -10
- 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 +244 -0
- package/node_modules/pi-lens/dist/clients/tool-definition.js +41 -1
- package/node_modules/pi-lens/dist/clients/tool-policy.js +92 -22
- package/node_modules/pi-lens/dist/clients/tree-sitter-cache.js +40 -40
- package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +87 -100
- 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/tui-fit.js +0 -4
- package/node_modules/pi-lens/dist/clients/typos-config.js +5 -0
- package/node_modules/pi-lens/dist/clients/user-notify.js +6 -6
- package/node_modules/pi-lens/dist/clients/widget-state.js +191 -26
- package/node_modules/pi-lens/dist/clients/word-index-logger.js +2 -9
- package/node_modules/pi-lens/dist/clients/word-index-store.js +23 -12
- package/node_modules/pi-lens/dist/clients/word-index.js +252 -47
- package/node_modules/pi-lens/dist/clients/workspace-topology.js +8 -1
- package/node_modules/pi-lens/dist/clients/zizmor-config.js +4 -1
- package/node_modules/pi-lens/dist/index.js +65899 -55340
- package/node_modules/pi-lens/dist/mcp/analyze-cli.js +3 -1
- package/node_modules/pi-lens/dist/mcp/build-staleness.js +1 -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 +96 -25
- package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +104 -86
- package/node_modules/pi-lens/dist/tools/lsp-navigation.js +37 -16
- package/node_modules/pi-lens/dist/tools/lsp-structured-output.js +3 -3
- package/node_modules/pi-lens/dist/tools/render-compact.js +1 -1
- package/node_modules/pi-lens/dist/tools/shared.js +0 -1
- package/node_modules/pi-lens/dist/tools/symbol-search.js +1 -2
- 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/globalconfig.md +20 -0
- package/node_modules/pi-lens/docs/language-coverage.md +2 -2
- package/node_modules/pi-lens/docs/lsp-capability-matrix.md +9 -1
- 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 +33 -0
- package/node_modules/pi-lens/docs/pi-lens-subagent.md +49 -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 +190 -0
- package/node_modules/pi-lens/docs/servercapabilities.md +7 -3
- 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/docs/word-index.md +1 -1
- package/node_modules/pi-lens/package.json +18 -35
- 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/rules/typos/_typos.toml +4 -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/lib/warm-loader-cache.mjs +1 -1
- package/node_modules/pi-lens/scripts/rpc-load-check.mjs +3 -1
- package/node_modules/pi-lens/scripts/warm-loader-cache.mjs +4 -2
- 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 +6 -6
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
* `~/.pi-lens/config.json`. Adding a toggle means adding one entry here; there
|
|
18
18
|
* is no second place to remember.
|
|
19
19
|
*/
|
|
20
|
+
import { DEPRECATED_CONFIG_SURFACES } from "./config-diagnostic-codes.js";
|
|
20
21
|
export const LENS_FLAGS = [
|
|
21
22
|
{
|
|
22
23
|
name: "no-lens",
|
|
@@ -188,6 +189,22 @@ export const LENS_FLAGS = [
|
|
|
188
189
|
default: false,
|
|
189
190
|
scope: "global",
|
|
190
191
|
},
|
|
192
|
+
...[
|
|
193
|
+
"knip",
|
|
194
|
+
"jscpd",
|
|
195
|
+
"madge",
|
|
196
|
+
"gitleaks",
|
|
197
|
+
"govulncheck",
|
|
198
|
+
"deadCode",
|
|
199
|
+
"complexity",
|
|
200
|
+
].map((analyzer) => ({
|
|
201
|
+
name: `no-${analyzer.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`)}`,
|
|
202
|
+
description: `Disable the ${analyzer} session-start analyzer. Also via ${analyzer}.enabled=false in config.`,
|
|
203
|
+
configKey: `${analyzer}.enabled`,
|
|
204
|
+
negated: true,
|
|
205
|
+
default: false,
|
|
206
|
+
scope: "project",
|
|
207
|
+
})),
|
|
191
208
|
];
|
|
192
209
|
const byName = new Map(LENS_FLAGS.map((spec) => [spec.name, spec]));
|
|
193
210
|
export function getLensFlagSpec(name) {
|
|
@@ -215,25 +232,79 @@ export const GLOBAL_NON_FLAG_CONFIG_SECTIONS = [
|
|
|
215
232
|
"ignore",
|
|
216
233
|
"dispatch",
|
|
217
234
|
"widget",
|
|
235
|
+
"startup",
|
|
218
236
|
"$schema",
|
|
219
237
|
];
|
|
238
|
+
/**
|
|
239
|
+
* Recognized TOP-LEVEL sections of a project `.pi-lens.json` that are NOT
|
|
240
|
+
* derived from the flag registry — the project loader's own hand-parsed
|
|
241
|
+
* sections (`ignore`, `rules`, `maxProjectFiles`, `reviewGraph`) plus the two
|
|
242
|
+
* namespaces another pi-lens runner reads off `PiLensProjectConfig.raw`
|
|
243
|
+
* (`trivy` in `trivy-client.ts`, `helm.renderValidation.enabled` in the
|
|
244
|
+
* helm-render runner, #1283).
|
|
245
|
+
*
|
|
246
|
+
* Moved here from `project-lens-config.ts` by #2426 so the canonical schema in
|
|
247
|
+
* `config-schema.ts` derives its namespace list from ONE place instead of
|
|
248
|
+
* importing the project loader (which would close an import cycle, since that
|
|
249
|
+
* loader now resolves through the schema).
|
|
250
|
+
*/
|
|
251
|
+
export const PROJECT_NON_FLAG_CONFIG_SECTIONS = [
|
|
252
|
+
"ignore",
|
|
253
|
+
"rules",
|
|
254
|
+
"maxProjectFiles",
|
|
255
|
+
"reviewGraph",
|
|
256
|
+
"trivy",
|
|
257
|
+
"helm",
|
|
258
|
+
"startup",
|
|
259
|
+
];
|
|
260
|
+
/**
|
|
261
|
+
* The four LSP settings a PROJECT config file may carry — at its root during
|
|
262
|
+
* the deprecation window, and under `lsp` canonically. DERIVED from the
|
|
263
|
+
* registry's `kind: "key"` rows so the accepted set and the removal schedule
|
|
264
|
+
* cannot drift apart, and named once because two places below need it.
|
|
265
|
+
*/
|
|
266
|
+
const LSP_PROJECT_HONORED_KEYS = DEPRECATED_CONFIG_SURFACES.filter((row) => row.kind === "key").map((row) => row.surface);
|
|
220
267
|
/**
|
|
221
268
|
* Foreign top-level namespaces that legitimately appear in a SHARED
|
|
222
269
|
* `.pi-lens.json` but belong to a DIFFERENT loader: the LSP config loader
|
|
223
|
-
* (`clients/lsp/config.ts`) reads `
|
|
224
|
-
*
|
|
270
|
+
* (`clients/lsp/config.ts`) reads the `lsp` namespace — and, for its
|
|
271
|
+
* deprecation window, the legacy ROOT keys `servers` / `serverOverrides` /
|
|
272
|
+
* `disabledServers` / `warmFiles` — out of the very same file. The project-lens
|
|
225
273
|
* loader must TOLERATE these (never warn "unknown key") — they are not typos,
|
|
226
274
|
* just another subsystem's namespace. `$schema` is allowed for editor
|
|
227
275
|
* JSON-schema association. Declared once, here, for the same #883 reason as
|
|
228
276
|
* {@link GLOBAL_NON_FLAG_CONFIG_SECTIONS}.
|
|
277
|
+
*
|
|
278
|
+
* `lsp` joined this list in #2426: it is the canonical home of the four legacy
|
|
279
|
+
* keys beside it, so a project config that has already been migrated must not
|
|
280
|
+
* be told its `lsp` section is a global-only setting. Its tolerance is
|
|
281
|
+
* SUB-KEY-SCOPED — see {@link PROJECT_FOREIGN_NAMESPACE_HONORED_KEYS}.
|
|
229
282
|
*/
|
|
230
283
|
export const PROJECT_FOREIGN_CONFIG_NAMESPACES = [
|
|
231
|
-
"
|
|
232
|
-
|
|
233
|
-
"
|
|
234
|
-
|
|
284
|
+
"lsp",
|
|
285
|
+
// DERIVED, not restated: the four legacy root keys are exactly the
|
|
286
|
+
// `kind: "key"` rows of the deprecation registry, and a hand-copied second
|
|
287
|
+
// list of them would be a place for the accepted set and the removal
|
|
288
|
+
// schedule to drift apart. `config-diagnostic-codes.ts` is a dependency-free
|
|
289
|
+
// data leaf, so importing it keeps this module's own no-cycle property.
|
|
290
|
+
...LSP_PROJECT_HONORED_KEYS,
|
|
235
291
|
"$schema",
|
|
236
292
|
];
|
|
293
|
+
/**
|
|
294
|
+
* For a foreign namespace whose PROJECT-honored surface is only PART of what
|
|
295
|
+
* the namespace can hold: which sub-keys a `.pi-lens.json` may set.
|
|
296
|
+
*
|
|
297
|
+
* `lsp` is tolerated at the top level because the LSP loader reads it out of
|
|
298
|
+
* this same file — but only four of its keys are project-scoped. `lsp.enabled`
|
|
299
|
+
* is a `scope: "global"` flag (`--no-lsp`), so blanket namespace tolerance made
|
|
300
|
+
* a project-file `lsp.enabled: false` do nothing with no signal at all, where
|
|
301
|
+
* before #2426 the user got the honest "global-only setting" notice
|
|
302
|
+
* (#2426 review round 2, F3). `docs/configuration.md` promises that nothing
|
|
303
|
+
* about a config is ignored silently, so the namespace is tolerated KEY BY KEY
|
|
304
|
+
* and anything else under it is scanned by the same global-only-vs-typo rules a
|
|
305
|
+
* top-level key gets.
|
|
306
|
+
*/
|
|
307
|
+
export const PROJECT_FOREIGN_NAMESPACE_HONORED_KEYS = new Map([["lsp", LSP_PROJECT_HONORED_KEYS]]);
|
|
237
308
|
/**
|
|
238
309
|
* The distinct TOP-LEVEL section keys a set of flags lives under (the first
|
|
239
310
|
* dotted segment of each `configKey`). Both config loaders derive their
|
|
@@ -24,7 +24,7 @@ import { normalizeMapKey, toProjectRelativePath } from "./path-utils.js";
|
|
|
24
24
|
import { canonicalSourceTwin } from "./source-filter.js";
|
|
25
25
|
import { buildOrUpdateGraph } from "./review-graph/service.js";
|
|
26
26
|
import { detectFileRole } from "./file-role.js";
|
|
27
|
-
|
|
27
|
+
const DEFAULT_MAX_MAP_NODES = 500;
|
|
28
28
|
/**
|
|
29
29
|
* Aggregates a symbol-level {@link ReviewGraph} into file-level nodes/edges.
|
|
30
30
|
* Pure and side-effect-free — no graph build here, no filesystem access — so
|
|
@@ -22,10 +22,10 @@
|
|
|
22
22
|
*/
|
|
23
23
|
import * as fs from "node:fs";
|
|
24
24
|
import * as path from "node:path";
|
|
25
|
-
import {
|
|
25
|
+
import { getGlobalPiLensLogDir } from "./probe-home-state.js";
|
|
26
26
|
import { getRegisteredLogFiles } from "./ndjson-logger.js";
|
|
27
27
|
import { pathsEqual } from "./path-utils.js";
|
|
28
|
-
const LOG_DIR =
|
|
28
|
+
const LOG_DIR = getGlobalPiLensLogDir();
|
|
29
29
|
const LOGS_SUBDIR = path.join(LOG_DIR, "logs");
|
|
30
30
|
/**
|
|
31
31
|
* Every global `.log` pi-lens writes under ~/.pi-lens, resolved dynamically so
|
|
@@ -220,39 +220,3 @@ export function runLogCleanup(dbg) {
|
|
|
220
220
|
}
|
|
221
221
|
return results;
|
|
222
222
|
}
|
|
223
|
-
/**
|
|
224
|
-
* Get current log storage summary
|
|
225
|
-
*/
|
|
226
|
-
export function getLogStorageSummary() {
|
|
227
|
-
const files = [];
|
|
228
|
-
let totalMB = 0;
|
|
229
|
-
// Main logs
|
|
230
|
-
for (const name of getManagedLogFiles()) {
|
|
231
|
-
const filePath = path.join(LOG_DIR, name);
|
|
232
|
-
if (fs.existsSync(filePath)) {
|
|
233
|
-
const sizeMB = getFileSizeMB(filePath);
|
|
234
|
-
const ageDays = getFileAgeDays(filePath);
|
|
235
|
-
files.push({ name, sizeMB, ageDays });
|
|
236
|
-
totalMB += sizeMB;
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
// Daily logs
|
|
240
|
-
try {
|
|
241
|
-
if (fs.existsSync(LOGS_SUBDIR)) {
|
|
242
|
-
const dailyFiles = fs.readdirSync(LOGS_SUBDIR);
|
|
243
|
-
for (const name of dailyFiles) {
|
|
244
|
-
if (!name.endsWith(".jsonl"))
|
|
245
|
-
continue;
|
|
246
|
-
const filePath = path.join(LOGS_SUBDIR, name);
|
|
247
|
-
const sizeMB = getFileSizeMB(filePath);
|
|
248
|
-
const ageDays = getFileAgeDays(filePath);
|
|
249
|
-
files.push({ name: `logs/${name}`, sizeMB, ageDays });
|
|
250
|
-
totalMB += sizeMB;
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
catch {
|
|
255
|
-
// Ignore
|
|
256
|
-
}
|
|
257
|
-
return { totalMB, files };
|
|
258
|
-
}
|
|
@@ -34,7 +34,9 @@
|
|
|
34
34
|
* `PromiseDescriptor.budgetMs`.
|
|
35
35
|
*/
|
|
36
36
|
export async function raceToCompletion(promises, shouldComplete, options = { timeoutMs: 1500 }) {
|
|
37
|
-
const results =
|
|
37
|
+
const results = [];
|
|
38
|
+
results.length = promises.length;
|
|
39
|
+
results.fill(undefined);
|
|
38
40
|
let graceTimer;
|
|
39
41
|
let auxGraceTimer;
|
|
40
42
|
let completed = false;
|
|
@@ -730,7 +730,7 @@ function retirePullSource(state, identifier) {
|
|
|
730
730
|
for (const source of [state.pullResultIds, state.pullRequestSequences]) {
|
|
731
731
|
if (!source)
|
|
732
732
|
continue;
|
|
733
|
-
for (const key of
|
|
733
|
+
for (const key of source.keys()) {
|
|
734
734
|
if (key.endsWith(suffix))
|
|
735
735
|
source.delete(key);
|
|
736
736
|
}
|
|
@@ -947,7 +947,7 @@ function scanSentContent(content) {
|
|
|
947
947
|
* read on the notification path (I1). Bounded by the same file-size gates the
|
|
948
948
|
* caller already applies to the content it hands us.
|
|
949
949
|
*/
|
|
950
|
-
function recordSentContent(state, normalizedPath, version, content) {
|
|
950
|
+
function recordSentContent(state, normalizedPath, version, content, coalescedCount = 0) {
|
|
951
951
|
const scan = scanSentContent(content);
|
|
952
952
|
const previous = state.documentContentHashes.get(normalizedPath);
|
|
953
953
|
if (previous && previous.version > version) {
|
|
@@ -1049,6 +1049,7 @@ function recordSentContent(state, normalizedPath, version, content) {
|
|
|
1049
1049
|
version,
|
|
1050
1050
|
contentLength: content.length,
|
|
1051
1051
|
contentLineCount: scan.lfNewlineCount + 1,
|
|
1052
|
+
...(coalescedCount > 0 && { coalescedCount }),
|
|
1052
1053
|
},
|
|
1053
1054
|
});
|
|
1054
1055
|
}
|
|
@@ -1172,7 +1173,7 @@ export function resolveConfigurationSection(initialization, section) {
|
|
|
1172
1173
|
// Exported (only) so tests can invoke the publishDiagnostics notification
|
|
1173
1174
|
// handler directly against a mock LSPClientState/connection without spawning
|
|
1174
1175
|
// a real language server. Not part of the public client API surface.
|
|
1175
|
-
export function setupIncomingHandlers(state, initialization) {
|
|
1176
|
+
export function setupIncomingHandlers(state, initialization, onDiagnosticsPublished) {
|
|
1176
1177
|
state.connection.onNotification("textDocument/publishDiagnostics", (params) => {
|
|
1177
1178
|
// #1639: the settle operation's own clock for THIS publish. A
|
|
1178
1179
|
// "quiet-window" settle's durationMs below measures from here (when
|
|
@@ -1187,6 +1188,7 @@ export function setupIncomingHandlers(state, initialization) {
|
|
|
1187
1188
|
// that is no longer open on this client.
|
|
1188
1189
|
if (state.closedDocuments?.has(normalizedPath))
|
|
1189
1190
|
return;
|
|
1191
|
+
onDiagnosticsPublished?.(state.serverId);
|
|
1190
1192
|
const newDiags = normalizeLspDiagnostics(params.diagnostics || []);
|
|
1191
1193
|
const docVersion = params.version;
|
|
1192
1194
|
if (PUB_DEBUG) {
|
|
@@ -1423,14 +1425,33 @@ export function setupIncomingHandlers(state, initialization) {
|
|
|
1423
1425
|
if (state.serverEditsAllowed <= 0 || !params?.edit) {
|
|
1424
1426
|
return { applied: false, failureReason: "edit not solicited" };
|
|
1425
1427
|
}
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1428
|
+
// #2450 fix round 3 (F3) removed a `depth === 1` re-check here as
|
|
1429
|
+
// dead code. It is not dead — it moved to the WRITE side, where it
|
|
1430
|
+
// is the live invariant: `state.activeMutationContext` is assigned
|
|
1431
|
+
// only by `syncMutationContextSlot` (below in this file), which
|
|
1432
|
+
// populates it exactly when `activeMutationDepth === 1` and
|
|
1433
|
+
// empties it on every other frame transition. The depth test
|
|
1434
|
+
// therefore still runs, on each entry and each unwind; repeating
|
|
1435
|
+
// it here would be a second copy of the same predicate, not an
|
|
1436
|
+
// independent gate. What this handler reads is consequently either
|
|
1437
|
+
// the context of the single frame currently in flight or
|
|
1438
|
+
// `undefined` — never a settled frame's context, and never a
|
|
1439
|
+
// context belonging to some other window that is still open
|
|
1440
|
+
// (#2479 review rounds 2/3).
|
|
1441
|
+
const context = state.activeMutationContext;
|
|
1442
|
+
// `workspace/applyEdit` is only ever honored inside the
|
|
1443
|
+
// `serverEditsAllowed` window this handler just checked, which is
|
|
1444
|
+
// opened exclusively by an executeCommand call — so a fallback here is
|
|
1445
|
+
// always executeCommand-solicited, never a bare edit (#2450). This
|
|
1446
|
+
// fallback context carries no runtime/cacheManager (there is no live
|
|
1447
|
+
// reference to those singletons at this call site); lsp-mutation.ts's
|
|
1448
|
+
// bookkeepLspMutation falls back to the mutation bridge for exactly
|
|
1449
|
+
// that reason rather than silently dropping the write's bookkeeping.
|
|
1429
1450
|
const telemetryContext = context ?? {
|
|
1430
1451
|
cwd: state.root,
|
|
1431
1452
|
correlationId: newLspMutationCorrelationId(),
|
|
1432
1453
|
tool: "lsp-workspace-applyEdit",
|
|
1433
|
-
source: "lsp-
|
|
1454
|
+
source: "lsp-execute-command",
|
|
1434
1455
|
};
|
|
1435
1456
|
try {
|
|
1436
1457
|
await applyWorkspaceEdit(params.edit, state.root, {
|
|
@@ -2430,7 +2451,7 @@ export function handleNotifyExternalChange(state, filePath, type) {
|
|
|
2430
2451
|
const uri = state.openDocumentUris?.get(normalizedPath) ?? pathToFileURL(filePath).href;
|
|
2431
2452
|
state.watchQueue.enqueue(uri, type);
|
|
2432
2453
|
}
|
|
2433
|
-
|
|
2454
|
+
async function handleNotifyOpenOnce(state, filePath, content, languageId, preserveDiagnostics = false, silent = false, coalescedCount = 0) {
|
|
2434
2455
|
if (!isClientAlive(state))
|
|
2435
2456
|
return;
|
|
2436
2457
|
const normalizedPath = normalizeMapKey(filePath);
|
|
@@ -2478,7 +2499,7 @@ export async function handleNotifyOpen(state, filePath, content, languageId, pre
|
|
|
2478
2499
|
// #1669 review F7: only mirror the send locally once it actually left
|
|
2479
2500
|
// the process — see safeSendNotification's doc comment.
|
|
2480
2501
|
if (reopenSent)
|
|
2481
|
-
recordSentContent(state, normalizedPath, version, content);
|
|
2502
|
+
recordSentContent(state, normalizedPath, version, content, coalescedCount);
|
|
2482
2503
|
state.openDocuments.add(normalizedPath);
|
|
2483
2504
|
state.openDocumentUris?.set(normalizedPath, uri);
|
|
2484
2505
|
return;
|
|
@@ -2488,7 +2509,7 @@ export async function handleNotifyOpen(state, filePath, content, languageId, pre
|
|
|
2488
2509
|
contentChanges: buildContentChanges(state, normalizedPath, content),
|
|
2489
2510
|
});
|
|
2490
2511
|
if (changeSent)
|
|
2491
|
-
recordSentContent(state, normalizedPath, version, content);
|
|
2512
|
+
recordSentContent(state, normalizedPath, version, content, coalescedCount);
|
|
2492
2513
|
return;
|
|
2493
2514
|
}
|
|
2494
2515
|
state.pendingOpens.add(normalizedPath);
|
|
@@ -2523,7 +2544,7 @@ export async function handleNotifyOpen(state, filePath, content, languageId, pre
|
|
|
2523
2544
|
return;
|
|
2524
2545
|
const openSent = await safeSendNotification(state.connection, "textDocument/didOpen", { textDocument: { uri, languageId, version: 0, text: content } });
|
|
2525
2546
|
if (openSent)
|
|
2526
|
-
recordSentContent(state, normalizedPath, 0, content);
|
|
2547
|
+
recordSentContent(state, normalizedPath, 0, content, coalescedCount);
|
|
2527
2548
|
state.pendingOpens.delete(normalizedPath);
|
|
2528
2549
|
state.openDocuments.add(normalizedPath);
|
|
2529
2550
|
state.closedDocuments?.delete(normalizedPath);
|
|
@@ -2547,7 +2568,81 @@ export async function handleNotifyOpen(state, filePath, content, languageId, pre
|
|
|
2547
2568
|
},
|
|
2548
2569
|
});
|
|
2549
2570
|
}
|
|
2550
|
-
|
|
2571
|
+
/**
|
|
2572
|
+
* Replace only notifications that have not started a transport write. A
|
|
2573
|
+
* microtask starts the first entry so a synchronous burst of callers installs
|
|
2574
|
+
* one latest entry before any bytes are handed to vscode-jsonrpc. Once an
|
|
2575
|
+
* entry starts, it runs to completion; LSP has no cancellation/acknowledgement
|
|
2576
|
+
* for notifications, so dropping a started write could violate didOpen before
|
|
2577
|
+
* didChange ordering or leave a partial message in the pipe.
|
|
2578
|
+
*/
|
|
2579
|
+
function enqueueDocumentNotify(state, normalizedPath, run) {
|
|
2580
|
+
let queue = state.notifyChangeQueues.get(normalizedPath);
|
|
2581
|
+
if (!queue) {
|
|
2582
|
+
queue = { running: false };
|
|
2583
|
+
state.notifyChangeQueues.set(normalizedPath, queue);
|
|
2584
|
+
}
|
|
2585
|
+
return new Promise((resolve, reject) => {
|
|
2586
|
+
const previous = queue?.pending;
|
|
2587
|
+
// Keep superseded callers attached to the replacement's completion. The
|
|
2588
|
+
// notification is dropped, but callers such as the auxiliary backlog
|
|
2589
|
+
// ledger must not observe completion before the newest content is sent.
|
|
2590
|
+
const waiters = previous?.waiters ?? [];
|
|
2591
|
+
waiters.push({ resolve, reject });
|
|
2592
|
+
queue.pending = {
|
|
2593
|
+
run,
|
|
2594
|
+
waiters,
|
|
2595
|
+
coalescedCount: (previous?.coalescedCount ?? 0) + (previous ? 1 : 0),
|
|
2596
|
+
};
|
|
2597
|
+
if (queue.running)
|
|
2598
|
+
return;
|
|
2599
|
+
queue.running = true;
|
|
2600
|
+
// Let same-turn callers replace the unwritten entry before the runner
|
|
2601
|
+
// invokes the transport. Different path queues still start independently.
|
|
2602
|
+
void Promise.resolve().then(async () => {
|
|
2603
|
+
try {
|
|
2604
|
+
for (;;) {
|
|
2605
|
+
const next = queue.pending;
|
|
2606
|
+
if (!next)
|
|
2607
|
+
break;
|
|
2608
|
+
queue.pending = undefined;
|
|
2609
|
+
try {
|
|
2610
|
+
await next.run(next.coalescedCount);
|
|
2611
|
+
for (const waiter of next.waiters)
|
|
2612
|
+
waiter.resolve();
|
|
2613
|
+
}
|
|
2614
|
+
catch (error) {
|
|
2615
|
+
for (const waiter of next.waiters)
|
|
2616
|
+
waiter.reject(error);
|
|
2617
|
+
}
|
|
2618
|
+
}
|
|
2619
|
+
}
|
|
2620
|
+
finally {
|
|
2621
|
+
queue.running = false;
|
|
2622
|
+
if (!queue.pending &&
|
|
2623
|
+
state.notifyChangeQueues.get(normalizedPath) === queue) {
|
|
2624
|
+
state.notifyChangeQueues.delete(normalizedPath);
|
|
2625
|
+
}
|
|
2626
|
+
}
|
|
2627
|
+
});
|
|
2628
|
+
});
|
|
2629
|
+
}
|
|
2630
|
+
/** Drop unwritten document notifications when a client is torn down. */
|
|
2631
|
+
function cancelDocumentNotifyQueues(state) {
|
|
2632
|
+
for (const queue of state.notifyChangeQueues.values()) {
|
|
2633
|
+
for (const waiter of queue.pending?.waiters ?? [])
|
|
2634
|
+
waiter.resolve();
|
|
2635
|
+
queue.pending = undefined;
|
|
2636
|
+
}
|
|
2637
|
+
state.notifyChangeQueues.clear();
|
|
2638
|
+
}
|
|
2639
|
+
export function handleNotifyOpen(state, filePath, content, languageId, preserveDiagnostics = false, silent = false) {
|
|
2640
|
+
if (!isClientAlive(state))
|
|
2641
|
+
return Promise.resolve();
|
|
2642
|
+
const normalizedPath = normalizeMapKey(filePath);
|
|
2643
|
+
return enqueueDocumentNotify(state, normalizedPath, (coalescedCount) => handleNotifyOpenOnce(state, filePath, content, languageId, preserveDiagnostics, silent, coalescedCount));
|
|
2644
|
+
}
|
|
2645
|
+
async function handleNotifyChangeOnce(state, filePath, content, normalizedPath, coalescedCount = 0) {
|
|
2551
2646
|
if (!isClientAlive(state))
|
|
2552
2647
|
return;
|
|
2553
2648
|
const uri = state.openDocumentUris?.get(normalizedPath) ?? pathToFileURL(filePath).href;
|
|
@@ -2566,7 +2661,7 @@ async function handleNotifyChangeOnce(state, filePath, content, normalizedPath)
|
|
|
2566
2661
|
state.documentOpenedAt.set(normalizedPath, Date.now());
|
|
2567
2662
|
state.diagnosticPublicationCounts.set(normalizedPath, 0);
|
|
2568
2663
|
if (fallbackOpenSent)
|
|
2569
|
-
recordSentContent(state, normalizedPath, 0, content);
|
|
2664
|
+
recordSentContent(state, normalizedPath, 0, content, coalescedCount);
|
|
2570
2665
|
state.openDocuments.add(normalizedPath);
|
|
2571
2666
|
state.openDocumentUris?.set(normalizedPath, uri);
|
|
2572
2667
|
return;
|
|
@@ -2581,7 +2676,7 @@ async function handleNotifyChangeOnce(state, filePath, content, normalizedPath)
|
|
|
2581
2676
|
contentChanges: buildContentChanges(state, normalizedPath, content),
|
|
2582
2677
|
});
|
|
2583
2678
|
if (changeSent)
|
|
2584
|
-
recordSentContent(state, normalizedPath, version, content);
|
|
2679
|
+
recordSentContent(state, normalizedPath, version, content, coalescedCount);
|
|
2585
2680
|
}
|
|
2586
2681
|
/**
|
|
2587
2682
|
* #2113: serialize the read/build/send/record transaction per document. The
|
|
@@ -2592,17 +2687,7 @@ export function handleNotifyChange(state, filePath, content) {
|
|
|
2592
2687
|
if (!isClientAlive(state))
|
|
2593
2688
|
return Promise.resolve();
|
|
2594
2689
|
const normalizedPath = normalizeMapKey(filePath);
|
|
2595
|
-
|
|
2596
|
-
const queued = previous
|
|
2597
|
-
.catch(() => undefined)
|
|
2598
|
-
.then(() => handleNotifyChangeOnce(state, filePath, content, normalizedPath));
|
|
2599
|
-
const settled = queued.finally(() => {
|
|
2600
|
-
if (state.notifyChangeQueues.get(normalizedPath) === settled) {
|
|
2601
|
-
state.notifyChangeQueues.delete(normalizedPath);
|
|
2602
|
-
}
|
|
2603
|
-
});
|
|
2604
|
-
state.notifyChangeQueues.set(normalizedPath, settled);
|
|
2605
|
-
return settled;
|
|
2690
|
+
return enqueueDocumentNotify(state, normalizedPath, (coalescedCount) => handleNotifyChangeOnce(state, filePath, content, normalizedPath, coalescedCount));
|
|
2606
2691
|
}
|
|
2607
2692
|
/** Close a document through the same lifecycle path exposed by the client. */
|
|
2608
2693
|
export async function closeDocument(state, filePath) {
|
|
@@ -2739,6 +2824,9 @@ async function clientShutdownOnce(state, options) {
|
|
|
2739
2824
|
state.pendingOpens.clear();
|
|
2740
2825
|
state.openDocuments.clear();
|
|
2741
2826
|
state.openDocumentUris?.clear();
|
|
2827
|
+
// #2357: superseded notifications that have not started writing are moot
|
|
2828
|
+
// once this client is dead; resolve their callers and release the queue.
|
|
2829
|
+
cancelDocumentNotifyQueues(state);
|
|
2742
2830
|
// #1412 L1: mirror openDocuments' clear — a shut-down/evicted client's
|
|
2743
2831
|
// probe memo is moot along with everything else document-scoped.
|
|
2744
2832
|
state.projectIdentityProbedFiles?.clear();
|
|
@@ -3183,6 +3271,35 @@ async function clientPingLiveness(state, timeoutMs = LIVENESS_PING_TIMEOUT_MS) {
|
|
|
3183
3271
|
}
|
|
3184
3272
|
return isClientAlive(state);
|
|
3185
3273
|
}
|
|
3274
|
+
// #2479: `activeMutationContext` is DERIVED state, not a stack. The frame that
|
|
3275
|
+
// takes `activeMutationDepth` 0 -> 1 owns the context for its whole lifetime
|
|
3276
|
+
// (`mutationContextOwner`); the slot merely exposes that owner while it is the
|
|
3277
|
+
// ONLY frame in flight. Deeper or overlapping frames therefore empty the slot
|
|
3278
|
+
// for as long as they are open — concurrent and nested commands deliberately
|
|
3279
|
+
// do not cross-correlate — and it refills by itself when they unwind, with no
|
|
3280
|
+
// frame having to remember anything.
|
|
3281
|
+
//
|
|
3282
|
+
// Recomputing beats saving and restoring because these frames do not nest:
|
|
3283
|
+
// `LSPClient.executeCommand` and `LSPService.executeCommand` fan out with no
|
|
3284
|
+
// mutex, parallel `lsp_navigation` calls with `apply: true` overlap, and #449
|
|
3285
|
+
// light mode shares one client across agents. With A (the owner), B and C
|
|
3286
|
+
// overlapping and the MIDDLE one settling first, a per-frame restore hands A's
|
|
3287
|
+
// context back while C's window is the open one — and `LspMutationContext`
|
|
3288
|
+
// carries a cwd plus a directly-threaded runtime/cacheManager, with
|
|
3289
|
+
// `readTurnState` / `appendProjectChange` cwd-scoped, so that routes a live
|
|
3290
|
+
// edit's bookkeeping into another project's change log (strictly worse than
|
|
3291
|
+
// the honest fallback the pre-#2479 code gave). An owner-liveness flag does
|
|
3292
|
+
// not fix it either: it answers "is an owner live", not "does the slot belong
|
|
3293
|
+
// to the window this edit is in" — and C's own unwind then puts back the
|
|
3294
|
+
// `undefined` it saved while the owner is still running, resurrecting #2479
|
|
3295
|
+
// (review round 3). Deriving answers the second question by construction, and
|
|
3296
|
+
// "no command in flight == no context" — the invariant the
|
|
3297
|
+
// `serverEditsAllowed` gate on `workspace/applyEdit` is paired with — falls
|
|
3298
|
+
// out of it with no depth-0 special case.
|
|
3299
|
+
function syncMutationContextSlot(state) {
|
|
3300
|
+
state.activeMutationContext =
|
|
3301
|
+
state.activeMutationDepth === 1 ? state.mutationContextOwner : undefined;
|
|
3302
|
+
}
|
|
3186
3303
|
// Run an advertised server command via workspace/executeCommand, with the
|
|
3187
3304
|
// generous EXECUTE_COMMAND_TIMEOUT_MS anti-deadlock backstop. Preserves the
|
|
3188
3305
|
// hardening invariants: allowlist-by-advertisement (only commands the server
|
|
@@ -3201,10 +3318,20 @@ export async function runServerCommand(state, command, args, timeoutMs = EXECUTE
|
|
|
3201
3318
|
}
|
|
3202
3319
|
state.serverEditsAllowed += 1;
|
|
3203
3320
|
state.activeMutationDepth = (state.activeMutationDepth ?? 0) + 1;
|
|
3204
|
-
|
|
3205
|
-
|
|
3206
|
-
|
|
3207
|
-
|
|
3321
|
+
// #2479: the frame that takes the depth to 1 owns the context; the slot is
|
|
3322
|
+
// derived from that owner (see `syncMutationContextSlot` above). The
|
|
3323
|
+
// pre-#2479 shape only ever CLEARED the slot, and only once the depth
|
|
3324
|
+
// returned to 0, so a nested `executeCommand` unwinding from depth 2 back
|
|
3325
|
+
// to 1 left the OUTER call without its own context for the rest of its
|
|
3326
|
+
// window: every server-initiated `applyEdit` it still solicited read
|
|
3327
|
+
// `undefined`, fell to the mutation bridge, and carried the generic
|
|
3328
|
+
// `agent-tool:lsp-workspace-applyEdit` receipt instead of the outer
|
|
3329
|
+
// operation's own (`lsp-rename` / `lsp-execute-command`).
|
|
3330
|
+
const isMutationContextOwner = state.activeMutationDepth === 1;
|
|
3331
|
+
if (isMutationContextOwner) {
|
|
3332
|
+
state.mutationContextOwner = mutationContext;
|
|
3333
|
+
}
|
|
3334
|
+
syncMutationContextSlot(state);
|
|
3208
3335
|
try {
|
|
3209
3336
|
let result;
|
|
3210
3337
|
try {
|
|
@@ -3231,8 +3358,15 @@ export async function runServerCommand(state, command, args, timeoutMs = EXECUTE
|
|
|
3231
3358
|
finally {
|
|
3232
3359
|
state.serverEditsAllowed -= 1;
|
|
3233
3360
|
state.activeMutationDepth = Math.max(0, (state.activeMutationDepth ?? 0) - 1);
|
|
3234
|
-
|
|
3235
|
-
|
|
3361
|
+
// The owner drops its context; every frame then resyncs. Both the
|
|
3362
|
+
// hand-back to a still-live owner once the deeper frames unwind and
|
|
3363
|
+
// the empty slot while more than one frame is open are consequences of
|
|
3364
|
+
// the derivation, not separate rules each frame has to get right
|
|
3365
|
+
// (#2479 review rounds 2/3).
|
|
3366
|
+
if (isMutationContextOwner) {
|
|
3367
|
+
state.mutationContextOwner = undefined;
|
|
3368
|
+
}
|
|
3369
|
+
syncMutationContextSlot(state);
|
|
3236
3370
|
}
|
|
3237
3371
|
}
|
|
3238
3372
|
// #1412 H1/H2: read-only sibling of runServerCommand for telemetry/identity
|
|
@@ -3365,7 +3499,7 @@ async function resolveCodeActionBestEffort(state, action) {
|
|
|
3365
3499
|
// --- Client Factory ---
|
|
3366
3500
|
export async function createLSPClient(options) {
|
|
3367
3501
|
installCrashGuard();
|
|
3368
|
-
const { serverId, process: lspProcess, root, sessionCwd, initialization, initializeTimeoutMs = INITIALIZE_TIMEOUT_MS, launchVariant, } = options;
|
|
3502
|
+
const { serverId, process: lspProcess, root, sessionCwd, initialization, initializeTimeoutMs = INITIALIZE_TIMEOUT_MS, launchVariant, onDiagnosticsPublished, } = options;
|
|
3369
3503
|
// #449/#472: register this LSP child in the cross-process instance registry
|
|
3370
3504
|
// as soon as we have a live pid — BEFORE `initialize` completes, not after.
|
|
3371
3505
|
// Registering early means a child that dies/hangs during initialize (the
|
|
@@ -3538,7 +3672,7 @@ export async function createLSPClient(options) {
|
|
|
3538
3672
|
return;
|
|
3539
3673
|
void safeSendNotification(state.connection, "workspace/didChangeWatchedFiles", { changes });
|
|
3540
3674
|
});
|
|
3541
|
-
setupIncomingHandlers(state, initialization);
|
|
3675
|
+
setupIncomingHandlers(state, initialization, onDiagnosticsPublished);
|
|
3542
3676
|
connection.listen();
|
|
3543
3677
|
setupConnectionLifecycle(state, recentStderr);
|
|
3544
3678
|
let initResult;
|
|
@@ -3694,6 +3828,8 @@ export async function createLSPClient(options) {
|
|
|
3694
3828
|
checkAlive: () => checkProcessAlive(),
|
|
3695
3829
|
/** #1277: cheap request round-trip proving the server still responds. */
|
|
3696
3830
|
pingLiveness: (timeoutMs) => clientPingLiveness(state, timeoutMs),
|
|
3831
|
+
/** #2358: the OS pid of the live server process (see interface doc). */
|
|
3832
|
+
getProcessPid: () => lspProcess.pid,
|
|
3697
3833
|
notify: {
|
|
3698
3834
|
async open(filePath, content, languageId, preserveDiagnostics, silent) {
|
|
3699
3835
|
return handleNotifyOpen(state, filePath, content, languageId, preserveDiagnostics, silent);
|
|
@@ -3842,6 +3978,9 @@ export async function createLSPClient(options) {
|
|
|
3842
3978
|
isDocumentOpen(filePath) {
|
|
3843
3979
|
return state.openDocuments.has(normalizeMapKey(filePath));
|
|
3844
3980
|
},
|
|
3981
|
+
openDocumentPaths() {
|
|
3982
|
+
return [...state.openDocuments];
|
|
3983
|
+
},
|
|
3845
3984
|
isBusy() {
|
|
3846
3985
|
return (activeRequestsByConnection.get(connection) ?? 0) > 0;
|
|
3847
3986
|
},
|