@herbertgao/pi-extensions 2026.8.4 → 2026.8.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +11 -3
- package/node_modules/@herbertgao/pi-cc-extensions/README.md +11 -3
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/config.ts +24 -0
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +91 -1
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/compact-thinking.ts +7 -3
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/context.ts +74 -5
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/index.ts +7 -6
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/compact-mode.ts +21 -12
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/default-mode.ts +4 -5
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/markdown-enhance.ts +53 -14
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/grouping.ts +22 -12
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/result.ts +2 -4
- package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
- package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +18 -0
- package/node_modules/@herbertgao/pi-subagents/package.json +8 -4
- package/node_modules/@herbertgao/pi-subagents/src/agent-color.ts +72 -67
- package/node_modules/@herbertgao/pi-subagents/src/agent-file-toggle.ts +255 -0
- package/node_modules/@herbertgao/pi-subagents/src/agent-manager.ts +191 -3
- package/node_modules/@herbertgao/pi-subagents/src/agent-runner.ts +20 -4
- package/node_modules/@herbertgao/pi-subagents/src/index.ts +289 -113
- package/node_modules/@herbertgao/pi-subagents/src/output-file.ts +24 -1
- package/node_modules/@herbertgao/pi-subagents/src/ui/agent-widget.ts +24 -2
- package/node_modules/@herbertgao/pi-subagents/src/ui/fleet-list.ts +15 -6
- package/node_modules/@herbertgao/pi-subagents/src/ui/schedule-menu.ts +9 -8
- package/node_modules/@herbertgao/pi-subagents/src/ui/select-item.ts +48 -0
- package/node_modules/@herbertgao/pi-subagents/src/worktree.ts +9 -5
- package/node_modules/@juicesharp/rpiv-ask-user-question/README.md +2 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/ask-user-question.ts +20 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/docs/hosts.md +6 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/docs/keyboard.md +7 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/package.json +2 -2
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/build-questionnaire.ts +7 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/key-router.ts +16 -5
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/questionnaire-session.ts +4 -2
- package/node_modules/@narumitw/pi-btw/README.md +32 -24
- package/node_modules/@narumitw/pi-btw/package.json +6 -6
- package/node_modules/@narumitw/pi-btw/src/btw.ts +4 -2
- package/node_modules/@narumitw/pi-btw/src/menu.ts +34 -13
- package/node_modules/@narumitw/pi-btw/src/settings.ts +22 -2
- package/node_modules/pi-lens/CHANGELOG.md +2535 -954
- package/node_modules/pi-lens/README.md +13 -0
- package/node_modules/pi-lens/dist/clients/actionable-warnings.js +73 -18
- package/node_modules/pi-lens/dist/clients/advisory-provenance.js +314 -0
- package/node_modules/pi-lens/dist/clients/agent-behavior-client.js +21 -4
- package/node_modules/pi-lens/dist/clients/agent-nudge.js +14 -7
- package/node_modules/pi-lens/dist/clients/ast-grep-client.js +68 -16
- package/node_modules/pi-lens/dist/clients/ast-grep-types.js +0 -1
- package/node_modules/pi-lens/dist/clients/ast-grep-yaml-synth.js +37 -10
- package/node_modules/pi-lens/dist/clients/atomic-write-staging.js +63 -0
- package/node_modules/pi-lens/dist/clients/atomic-write.js +114 -14
- package/node_modules/pi-lens/dist/clients/bash-file-access.js +193 -23
- package/node_modules/pi-lens/dist/clients/biome-client.js +136 -24
- package/node_modules/pi-lens/dist/clients/bootstrap.js +11 -2
- package/node_modules/pi-lens/dist/clients/bounded-cache.js +34 -0
- package/node_modules/pi-lens/dist/clients/bounded-pid-file-lock.js +192 -0
- package/node_modules/pi-lens/dist/clients/bus-events-logger.js +62 -6
- package/node_modules/pi-lens/dist/clients/bus-publish.js +19 -4
- package/node_modules/pi-lens/dist/clients/cache/rule-cache.js +47 -5
- package/node_modules/pi-lens/dist/clients/cache-manager.js +97 -9
- package/node_modules/pi-lens/dist/clients/cache-observability.js +301 -14
- package/node_modules/pi-lens/dist/clients/call-graph.js +449 -117
- package/node_modules/pi-lens/dist/clients/cascade-format.js +57 -2
- package/node_modules/pi-lens/dist/clients/child-unref.js +85 -0
- package/node_modules/pi-lens/dist/clients/codebase-model.js +52 -23
- package/node_modules/pi-lens/dist/clients/collateral-test-role.js +40 -0
- package/node_modules/pi-lens/dist/clients/complexity-client.js +2 -1
- package/node_modules/pi-lens/dist/clients/console-guard-install.js +26 -0
- package/node_modules/pi-lens/dist/clients/cooperative-budget.js +42 -0
- package/node_modules/pi-lens/dist/clients/dead-code-client.js +137 -31
- package/node_modules/pi-lens/dist/clients/debug-handles.js +206 -0
- package/node_modules/pi-lens/dist/clients/debug-heap.js +167 -0
- package/node_modules/pi-lens/dist/clients/degradation-ledger.js +153 -0
- package/node_modules/pi-lens/dist/clients/dependency-checker.js +361 -77
- package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +65 -13
- package/node_modules/pi-lens/dist/clients/diagnostics-publish.js +18 -4
- package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +176 -29
- package/node_modules/pi-lens/dist/clients/dispatch/facts/function-facts.js +23 -7
- package/node_modules/pi-lens/dist/clients/dispatch/facts/import-facts.js +8 -18
- package/node_modules/pi-lens/dist/clients/dispatch/facts/tree-sitter-facts.js +8 -5
- package/node_modules/pi-lens/dist/clients/dispatch/indent-detect.js +35 -0
- package/node_modules/pi-lens/dist/clients/dispatch/inline-suppressions.js +17 -8
- package/node_modules/pi-lens/dist/clients/dispatch/integration.js +1172 -683
- package/node_modules/pi-lens/dist/clients/dispatch/lazy.js +14 -0
- package/node_modules/pi-lens/dist/clients/dispatch/plan.js +11 -1
- package/node_modules/pi-lens/dist/clients/dispatch/rule-id-normalize.js +50 -0
- package/node_modules/pi-lens/dist/clients/dispatch/rule-policy.js +135 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ast-grep-napi.js +23 -5
- package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +5 -9
- package/node_modules/pi-lens/dist/clients/dispatch/runners/detekt.js +3 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/hadolint.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-lint.js +154 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/htmlhint.js +3 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/index.js +5 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +47 -6
- package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +4 -9
- package/node_modules/pi-lens/dist/clients/dispatch/runners/pyright.js +9 -5
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ruff.js +4 -8
- package/node_modules/pi-lens/dist/clients/dispatch/runners/shellcheck.js +2 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/shfmt.js +2 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/spotbugs.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/taplo.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/terragrunt.js +163 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/tflint.js +37 -5
- package/node_modules/pi-lens/dist/clients/dispatch/runners/tree-sitter.js +3 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/trivy-config.js +13 -7
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/availability-policy.js +226 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/candidate-probe.js +69 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/lazy-installer.js +3 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +473 -42
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/spawn-outcome.js +22 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/toolchain-availability.js +97 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/yaml-rule-parser.js +5 -4
- package/node_modules/pi-lens/dist/clients/disposition-publish.js +18 -4
- package/node_modules/pi-lens/dist/clients/durable-store.js +97 -0
- package/node_modules/pi-lens/dist/clients/eval-timestamp.js +17 -0
- package/node_modules/pi-lens/dist/clients/event-loop-monitor.js +94 -3
- package/node_modules/pi-lens/dist/clients/extension-log.js +432 -0
- package/node_modules/pi-lens/dist/clients/extension-mode.js +73 -0
- package/node_modules/pi-lens/dist/clients/file-kinds.js +57 -0
- package/node_modules/pi-lens/dist/clients/file-role.js +18 -3
- package/node_modules/pi-lens/dist/clients/file-utils.js +56 -34
- package/node_modules/pi-lens/dist/clients/fix-worklog.js +5 -1
- package/node_modules/pi-lens/dist/clients/format-events-publish.js +51 -7
- package/node_modules/pi-lens/dist/clients/format-service.js +24 -8
- package/node_modules/pi-lens/dist/clients/formatters-lazy.js +8 -0
- package/node_modules/pi-lens/dist/clients/formatters.js +358 -61
- package/node_modules/pi-lens/dist/clients/generated-artifacts.js +148 -15
- package/node_modules/pi-lens/dist/clients/git-guard.js +678 -11
- package/node_modules/pi-lens/dist/clients/git-tracked-ignore.js +4 -0
- package/node_modules/pi-lens/dist/clients/go-client.js +23 -40
- package/node_modules/pi-lens/dist/clients/govulncheck-client.js +124 -7
- package/node_modules/pi-lens/dist/clients/grammar-source.js +12 -4
- package/node_modules/pi-lens/dist/clients/gzip-stage-write.js +21 -3
- package/node_modules/pi-lens/dist/clients/host-ports.js +31 -0
- package/node_modules/pi-lens/dist/clients/installer/index.js +395 -100
- package/node_modules/pi-lens/dist/clients/instance-reaper.js +142 -172
- package/node_modules/pi-lens/dist/clients/jscpd-client.js +27 -55
- package/node_modules/pi-lens/dist/clients/knip-client.js +58 -42
- package/node_modules/pi-lens/dist/clients/language-policy.js +14 -2
- package/node_modules/pi-lens/dist/clients/language-profile.js +13 -7
- package/node_modules/pi-lens/dist/clients/latency-logger.js +72 -1
- package/node_modules/pi-lens/dist/clients/lens-config.js +12 -1
- package/node_modules/pi-lens/dist/clients/lens-engine.js +86 -17
- package/node_modules/pi-lens/dist/clients/lens-events.js +63 -9
- package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +16 -0
- package/node_modules/pi-lens/dist/clients/lens-map.js +94 -19
- package/node_modules/pi-lens/dist/clients/live-bus-emitter.js +73 -0
- package/node_modules/pi-lens/dist/clients/log-cleanup.js +2 -1
- package/node_modules/pi-lens/dist/clients/lsp/aggregation.js +30 -4
- package/node_modules/pi-lens/dist/clients/lsp/cascade-tier.js +59 -14
- package/node_modules/pi-lens/dist/clients/lsp/client.js +662 -56
- package/node_modules/pi-lens/dist/clients/lsp/config.js +13 -2
- package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +115 -0
- package/node_modules/pi-lens/dist/clients/lsp/edits.js +1012 -121
- package/node_modules/pi-lens/dist/clients/lsp/index.js +2025 -800
- package/node_modules/pi-lens/dist/clients/lsp/launch.js +32 -26
- package/node_modules/pi-lens/dist/clients/lsp/path-utils.js +1 -1
- package/node_modules/pi-lens/dist/clients/lsp/ruby-drive-dirs.js +83 -0
- package/node_modules/pi-lens/dist/clients/lsp/server.js +437 -86
- package/node_modules/pi-lens/dist/clients/lsp/tsserver-sync.js +96 -0
- package/node_modules/pi-lens/dist/clients/lsp/wait-policy/classification.js +21 -5
- package/node_modules/pi-lens/dist/clients/lsp/wait-policy/strategies.js +18 -3
- package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +28 -4
- package/node_modules/pi-lens/dist/clients/lsp-lazy.js +8 -0
- package/node_modules/pi-lens/dist/clients/lsp-mutation.js +248 -0
- package/node_modules/pi-lens/dist/clients/mcp/analyze.js +127 -32
- package/node_modules/pi-lens/dist/clients/mcp/ipc.js +157 -24
- package/node_modules/pi-lens/dist/clients/mcp/session.js +235 -14
- package/node_modules/pi-lens/dist/clients/memory-sampler.js +115 -0
- package/node_modules/pi-lens/dist/clients/metrics-client.js +2 -1
- package/node_modules/pi-lens/dist/clients/metrics-history.js +2 -1
- package/node_modules/pi-lens/dist/clients/model-provider.js +53 -0
- package/node_modules/pi-lens/dist/clients/module-report-lsp.js +5 -0
- package/node_modules/pi-lens/dist/clients/module-report.js +168 -3
- package/node_modules/pi-lens/dist/clients/ndjson-logger.js +319 -118
- package/node_modules/pi-lens/dist/clients/opengrep-client.js +1 -1
- package/node_modules/pi-lens/dist/clients/partial-edit-apply.js +120 -5
- package/node_modules/pi-lens/dist/clients/path-utils.js +110 -9
- package/node_modules/pi-lens/dist/clients/pipeline.js +76 -15
- package/node_modules/pi-lens/dist/clients/print-mode.js +21 -0
- package/node_modules/pi-lens/dist/clients/project-changes.js +40 -0
- package/node_modules/pi-lens/dist/clients/project-diagnostics/cache.js +3 -2
- package/node_modules/pi-lens/dist/clients/project-diagnostics/fresh-fetch.js +1 -1
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/call-graph-impact.js +8 -0
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/runner-findings.js +23 -2
- package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +21 -1
- package/node_modules/pi-lens/dist/clients/project-lens-config.js +86 -9
- package/node_modules/pi-lens/dist/clients/project-report.js +27 -13
- package/node_modules/pi-lens/dist/clients/project-snapshot.js +175 -20
- package/node_modules/pi-lens/dist/clients/project-trust.js +181 -0
- package/node_modules/pi-lens/dist/clients/quiet-window.js +18 -4
- package/node_modules/pi-lens/dist/clients/read-bridge.js +147 -0
- package/node_modules/pi-lens/dist/clients/read-guard-logger.js +159 -1
- package/node_modules/pi-lens/dist/clients/read-guard-tool-lines.js +150 -29
- package/node_modules/pi-lens/dist/clients/read-guard.js +185 -4
- package/node_modules/pi-lens/dist/clients/resource-sampler.js +70 -84
- package/node_modules/pi-lens/dist/clients/review-graph/builder.js +1122 -221
- package/node_modules/pi-lens/dist/clients/review-graph/git-identity.js +2 -1
- package/node_modules/pi-lens/dist/clients/review-graph/import-resolvers.js +21 -10
- package/node_modules/pi-lens/dist/clients/review-graph/query.js +24 -0
- package/node_modules/pi-lens/dist/clients/review-graph/symbol-id.js +46 -0
- package/node_modules/pi-lens/dist/clients/review-graph/tsconfig-paths.js +57 -6
- package/node_modules/pi-lens/dist/clients/review-graph/workspace-modules.js +51 -3
- package/node_modules/pi-lens/dist/clients/review-graph-logger.js +30 -1
- package/node_modules/pi-lens/dist/clients/ruff-client.js +27 -44
- package/node_modules/pi-lens/dist/clients/run-duration.js +55 -0
- package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +257 -77
- package/node_modules/pi-lens/dist/clients/runtime-context.js +129 -12
- package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +242 -26
- package/node_modules/pi-lens/dist/clients/runtime-session.js +428 -117
- package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +71 -48
- package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +342 -33
- package/node_modules/pi-lens/dist/clients/runtime-turn.js +619 -93
- package/node_modules/pi-lens/dist/clients/rust-client.js +23 -38
- package/node_modules/pi-lens/dist/clients/safe-spawn.js +777 -62
- package/node_modules/pi-lens/dist/clients/security-scan-client.js +90 -6
- package/node_modules/pi-lens/dist/clients/session-state-store.js +3 -2
- package/node_modules/pi-lens/dist/clients/sg-runner.js +424 -196
- package/node_modules/pi-lens/dist/clients/slow-fs.js +2 -1
- package/node_modules/pi-lens/dist/clients/smells-rollup.js +231 -0
- package/node_modules/pi-lens/dist/clients/source-filter.js +184 -20
- package/node_modules/pi-lens/dist/clients/source-walker.js +66 -10
- package/node_modules/pi-lens/dist/clients/startup-scan.js +15 -16
- package/node_modules/pi-lens/dist/clients/startup-timing.js +7 -1
- package/node_modules/pi-lens/dist/clients/test-runner-client.js +469 -32
- package/node_modules/pi-lens/dist/clients/tool-event.js +35 -0
- package/node_modules/pi-lens/dist/clients/tool-policy.js +390 -39
- package/node_modules/pi-lens/dist/clients/tool-render.js +155 -0
- package/node_modules/pi-lens/dist/clients/tool-set-policy.js +76 -0
- package/node_modules/pi-lens/dist/clients/tree-sitter-cache.js +6 -1
- package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +419 -50
- package/node_modules/pi-lens/dist/clients/tree-sitter-logger.js +21 -0
- package/node_modules/pi-lens/dist/clients/tree-sitter-query-loader.js +7 -1
- package/node_modules/pi-lens/dist/clients/tree-sitter-shared.js +7 -2
- package/node_modules/pi-lens/dist/clients/tree-sitter-symbol-extractor.js +44 -7
- package/node_modules/pi-lens/dist/clients/user-notify.js +51 -0
- package/node_modules/pi-lens/dist/clients/vanished-instance-marker.js +57 -0
- package/node_modules/pi-lens/dist/clients/warm-attach.js +50 -13
- package/node_modules/pi-lens/dist/clients/widget-state.js +300 -43
- package/node_modules/pi-lens/dist/clients/word-index.js +680 -81
- package/node_modules/pi-lens/dist/clients/workspace-topology.js +89 -6
- package/node_modules/pi-lens/dist/index.js +51785 -36118
- package/node_modules/pi-lens/dist/mcp/analyze-cli.js +182 -29
- package/node_modules/pi-lens/dist/mcp/server.js +219 -46
- package/node_modules/pi-lens/dist/tools/activate-tools.js +17 -5
- package/node_modules/pi-lens/dist/tools/ast-grep-replace.js +9 -4
- package/node_modules/pi-lens/dist/tools/ast-grep-search.js +93 -27
- package/node_modules/pi-lens/dist/tools/lens-diagnostic-mark.js +5 -2
- package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +203 -38
- package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +210 -42
- package/node_modules/pi-lens/dist/tools/lsp-navigation.js +46 -3
- package/node_modules/pi-lens/dist/tools/module-report.js +9 -0
- package/node_modules/pi-lens/dist/tools/symbol-search.js +1 -1
- package/node_modules/pi-lens/docs/agent-guide.md +40 -15
- package/node_modules/pi-lens/docs/agent-tools.md +21 -10
- package/node_modules/pi-lens/docs/analysisall.md +192 -0
- package/node_modules/pi-lens/docs/api-ports-inventory.md +165 -0
- package/node_modules/pi-lens/docs/ast-grep_rules_catalog.md +14 -3
- package/node_modules/pi-lens/docs/durable-store-audit-1202.md +32 -0
- package/node_modules/pi-lens/docs/environment-variables.md +44 -0
- package/node_modules/pi-lens/docs/fable.md +27 -0
- package/node_modules/pi-lens/docs/features.md +45 -3
- package/node_modules/pi-lens/docs/globalconfig.md +56 -1
- package/node_modules/pi-lens/docs/language-coverage.md +4 -3
- package/node_modules/pi-lens/docs/lsp-capability-matrix.md +2 -2
- package/node_modules/pi-lens/docs/mcp.md +37 -4
- package/node_modules/pi-lens/docs/servercapabilities.md +3 -3
- package/node_modules/pi-lens/docs/settings.md +18 -1
- package/node_modules/pi-lens/docs/tools.md +4 -1
- package/node_modules/pi-lens/docs/usage.md +41 -5
- package/node_modules/pi-lens/docs/word-index.md +35 -0
- package/node_modules/pi-lens/package.json +10 -10
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-bare-except-test.yml +49 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-bare-host-path-in-win32-branch-test.yml +87 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-chained-type-assertions-test.yml +8 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-conditional-empty-object-spread-js-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-conditional-empty-object-spread-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-nested-links-test.yml +11 -1
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-raw-json-store-write-test.yml +17 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-js-test.yml +7 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-test.yml +7 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-js-test.yml +8 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-test.yml +8 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unknown-laundering-test.yml +11 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-win32-isabsolute-for-qualification-test.yml +16 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-except.yml +3 -15
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-host-path-in-win32-branch.yml +25 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-chained-type-assertions.yml +21 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-conditional-empty-object-spread-js.yml +21 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-conditional-empty-object-spread.yml +29 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-nested-links.yml +7 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-raw-json-store-write.yml +30 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply-js.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get-js.yml +13 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get.yml +16 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-laundering.yml +27 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-win32-isabsolute-for-qualification.yml +23 -0
- package/node_modules/pi-lens/rules/tree-sitter-queries/tsx/no-nested-links.yml +4 -6
- package/node_modules/pi-lens/rules/tree-sitter-queries/typescript/duplicate-function-arg.yml +2 -2
- package/node_modules/pi-lens/scripts/analyze-pi-lens-logs.mjs +134 -2
- package/node_modules/pi-lens/skills/pi-lens-ast-grep/SKILL.md +10 -11
- package/node_modules/pi-lens/skills/pi-lens-lsp-navigation/SKILL.md +22 -22
- package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/SKILL.md +8 -114
- package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/reference.md +129 -0
- package/node_modules/pi-lens/skills/pi-lens-write-tree-sitter-rule/SKILL.md +3 -1
- package/node_modules/pi-mcp-adapter/CHANGELOG.md +38 -0
- package/node_modules/pi-mcp-adapter/README.md +38 -4
- package/node_modules/pi-mcp-adapter/agent-dir.ts +12 -4
- package/node_modules/pi-mcp-adapter/agent-plugin-loader.ts +1 -1
- package/node_modules/pi-mcp-adapter/cli.js +25 -4
- package/node_modules/pi-mcp-adapter/commands.ts +15 -7
- package/node_modules/pi-mcp-adapter/config.ts +4 -4
- package/node_modules/pi-mcp-adapter/direct-tools.ts +58 -8
- package/node_modules/pi-mcp-adapter/host-html-template.ts +0 -8
- package/node_modules/pi-mcp-adapter/index.ts +8 -3
- package/node_modules/pi-mcp-adapter/init.ts +29 -5
- package/node_modules/pi-mcp-adapter/lifecycle.ts +0 -4
- package/node_modules/pi-mcp-adapter/mcp-auth-flow.ts +1 -2
- package/node_modules/pi-mcp-adapter/mcp-auth.ts +60 -2
- package/node_modules/pi-mcp-adapter/mcp-panel.ts +45 -9
- package/node_modules/pi-mcp-adapter/mcp-script-worker.mjs +22 -20
- package/node_modules/pi-mcp-adapter/mcp-setup-panel.ts +2 -1
- package/node_modules/pi-mcp-adapter/metadata-cache.ts +37 -4
- package/node_modules/pi-mcp-adapter/npx-resolver.ts +81 -26
- package/node_modules/pi-mcp-adapter/package.json +4 -3
- package/node_modules/pi-mcp-adapter/proxy-modes.ts +108 -26
- package/node_modules/pi-mcp-adapter/request-headers-command.ts +336 -0
- package/node_modules/pi-mcp-adapter/search-ranking.ts +86 -7
- package/node_modules/pi-mcp-adapter/server-manager.ts +41 -7
- package/node_modules/pi-mcp-adapter/session-recovery.ts +8 -2
- package/node_modules/pi-mcp-adapter/tool-approval.ts +48 -7
- package/node_modules/pi-mcp-adapter/tool-metadata.ts +62 -4
- package/node_modules/pi-mcp-adapter/tool-result-renderer.ts +138 -12
- package/node_modules/pi-mcp-adapter/types.ts +176 -27
- package/node_modules/pi-mcp-adapter/ui-server.ts +20 -1
- package/node_modules/pi-web-access/CHANGELOG.md +14 -0
- package/node_modules/pi-web-access/README.md +18 -12
- package/node_modules/pi-web-access/auth-fetch.ts +148 -0
- package/node_modules/pi-web-access/chrome-cookies.ts +110 -23
- package/node_modules/pi-web-access/curator-page.ts +5 -3
- package/node_modules/pi-web-access/curator-server.ts +2 -1
- package/node_modules/pi-web-access/extract.ts +106 -34
- package/node_modules/pi-web-access/fetch-params.ts +17 -3
- package/node_modules/pi-web-access/firecrawl.ts +172 -12
- package/node_modules/pi-web-access/gemini-search.ts +18 -4
- package/node_modules/pi-web-access/index.ts +120 -48
- package/node_modules/pi-web-access/package.json +2 -2
- package/node_modules/pi-web-access/summary-review.ts +11 -5
- package/node_modules/pi-web-access/youtube-extract.ts +2 -2
- package/package.json +12 -13
- package/node_modules/pi-lens/dist/clients/ast-grep-parser.js +0 -86
- package/node_modules/pi-lens/dist/clients/lsp/interactive-install.js +0 -367
- package/node_modules/pi-lens/dist/clients/lsp/lsp-index.js +0 -10
- package/node_modules/pi-lens/dist/clients/lsp/server-strategies.js +0 -5
- package/node_modules/pi-lens/dist/clients/project-metadata.js +0 -690
- package/node_modules/pi-lens/dist/clients/source-groups.js +0 -96
- package/node_modules/pi-lens/dist/clients/startup-marker.js +0 -6
- package/node_modules/pi-lens/dist/clients/types.js +0 -11
|
@@ -24,13 +24,15 @@ import * as path from "node:path";
|
|
|
24
24
|
import { fileURLToPath } from "node:url";
|
|
25
25
|
import { AstGrepClient } from "../clients/ast-grep-client.js";
|
|
26
26
|
import { CacheManager } from "../clients/cache-manager.js";
|
|
27
|
-
import {
|
|
28
|
-
import { analyzeFile, analyzeFileFresh, canRebuildPiLens, createMcpHost, diagnosticStats, ensureLspConfig, ipcPathForCwd, lspStatus,
|
|
27
|
+
import { getDegradationSummary, renderDegradationLines, } from "../clients/degradation-ledger.js";
|
|
28
|
+
import { acknowledgeTurnEnd, analyzeFile, analyzeFileFresh, canRebuildPiLens, createMcpHost, createWarmIpcLineReader, createWarmIpcRequestQueue, diagnosticStats, ensureLspConfig, generatedSkipNotice, ipcPathForCwd, lspStatus, moduleReport, projectReport, projectScan, readEnclosing, readSymbol, readTurnEndStatus, recentLatency, renderCompactModuleReport, renderCompactProjectReport, renderLspBrokenStatusLines, resolveRebuildScript, resourceFootprint, runRebuild, runSessionStart, runTurnEnd, runTurnEndForIpc, scanTruncationNotice, summarizeScan, symbolSearch, treeSitterRuntimeStatus, WARM_TURN_END_SCHEMA_VERSION, } from "../clients/lens-engine.js";
|
|
29
29
|
import { createAstGrepReplaceTool } from "../tools/ast-grep-replace.js";
|
|
30
30
|
import { createAstGrepSearchTool } from "../tools/ast-grep-search.js";
|
|
31
31
|
import { createLensDiagnosticsTool } from "../tools/lens-diagnostics.js";
|
|
32
|
+
import { peekMcpSessionRuntime } from "../clients/mcp/session.js";
|
|
32
33
|
import { createLspDiagnosticsTool } from "../tools/lsp-diagnostics.js";
|
|
33
34
|
import { createLspNavigationTool } from "../tools/lsp-navigation.js";
|
|
35
|
+
import { computeBuildStamp, STALE_SERVED_BY_FRESH, STALE_WARN_ONLY, StalenessGate, stalenessCheckEnabled, } from "./build-staleness.js";
|
|
34
36
|
// Any stray stdout write corrupts the JSON-RPC stream; force it onto stderr.
|
|
35
37
|
console.log = (...args) => {
|
|
36
38
|
console.error(...args);
|
|
@@ -191,6 +193,32 @@ function getAutoSessionStatus() {
|
|
|
191
193
|
// runs in THIS warm process (LSP-complete) instead of a cold hook process.
|
|
192
194
|
// Responses go over the socket — never stdout — so the MCP stream is untouched.
|
|
193
195
|
const IPC_PATH = ipcPathForCwd(DEFAULT_CWD);
|
|
196
|
+
/**
|
|
197
|
+
* #1273: the turn-end route runs the TARGET directory's configured test runner
|
|
198
|
+
* and spins up an LSP for it, from a client-supplied `cwd`. Every legitimate
|
|
199
|
+
* client derived the socket path from that same cwd, so a workspace check costs
|
|
200
|
+
* nothing legitimate — but without it, anything that can reach this endpoint
|
|
201
|
+
* (same-uid processes, a permissive-umask shared host, a Windows named pipe's
|
|
202
|
+
* more generous default DACL) can make the server execute an arbitrary
|
|
203
|
+
* directory's test suite. "Lint one file" and "run this directory's test suite"
|
|
204
|
+
* are different blast radii, so the guard is on turn-end and its ack.
|
|
205
|
+
*/
|
|
206
|
+
function rejectForeignTurnCwd(route, cwd) {
|
|
207
|
+
const message = `${route} cwd outside this server's workspace: ${path.resolve(cwd)} not within ${DEFAULT_CWD}`;
|
|
208
|
+
console.error(`[pi-lens-mcp] rejected ${message}`);
|
|
209
|
+
return message;
|
|
210
|
+
}
|
|
211
|
+
function isWithinServerWorkspace(cwd) {
|
|
212
|
+
const target = path.resolve(cwd);
|
|
213
|
+
// `path.relative` applies the platform's own path semantics (including
|
|
214
|
+
// win32 case-insensitivity), which is what "inside the workspace" means
|
|
215
|
+
// here — do NOT hand-roll a case fold. An empty result means `target`
|
|
216
|
+
// IS `DEFAULT_CWD` (win32 can reach that via a pure case/drive-letter
|
|
217
|
+
// difference, since path.relative there is case-insensitive) and must
|
|
218
|
+
// be accepted, not rejected — do NOT reintroduce a `rel !== ""` guard.
|
|
219
|
+
const rel = path.relative(DEFAULT_CWD, target);
|
|
220
|
+
return !rel.startsWith("..") && !path.isAbsolute(rel);
|
|
221
|
+
}
|
|
194
222
|
function startIpcServer() {
|
|
195
223
|
// POSIX: a stale socket file blocks listen; remove it first. (Named pipes on
|
|
196
224
|
// Windows don't need this.)
|
|
@@ -202,33 +230,77 @@ function startIpcServer() {
|
|
|
202
230
|
// no stale socket — fine
|
|
203
231
|
}
|
|
204
232
|
}
|
|
233
|
+
const requestQueue = createWarmIpcRequestQueue();
|
|
205
234
|
const ipc = net.createServer((socket) => {
|
|
206
235
|
socket.setEncoding("utf8");
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
const line = buffer.slice(0, newline);
|
|
214
|
-
void (async () => {
|
|
236
|
+
// One-shot per connection (#1219): clients write exactly one request and
|
|
237
|
+
// read one reply, so a handler that kept re-reading the same buffered
|
|
238
|
+
// line re-dispatched the request on stray bytes. The reader consumes the
|
|
239
|
+
// line and ignores anything after it.
|
|
240
|
+
socket.on("data", createWarmIpcLineReader((line) => {
|
|
241
|
+
void requestQueue.enqueue(async () => {
|
|
215
242
|
try {
|
|
216
|
-
// #535: the PostToolUse hook bin (mcp/analyze-cli.ts) already treats
|
|
217
|
-
// ANY error response as "no usable warm server" and falls back to
|
|
218
|
-
// its own cold, load-fresh-from-disk analysis path — so on a stale
|
|
219
|
-
// warm build, replying with an error IS the fresh-fork behavior for
|
|
220
|
-
// this channel, for free. No separate fresh-fork plumbing needed
|
|
221
|
-
// here: the client-side fallback already loads current code.
|
|
222
243
|
if (isWarmBuildStale()) {
|
|
223
|
-
console.error("[pi-lens-mcp] warm
|
|
224
|
-
socket.end(`${JSON.stringify({ error: "warm build stale
|
|
244
|
+
console.error("[pi-lens-mcp] warm request: build stale, replying with an error");
|
|
245
|
+
socket.end(`${JSON.stringify({ error: "warm build stale" })}\n`);
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
const parsed = JSON.parse(line);
|
|
249
|
+
if (parsed.route === "turn-end-ack") {
|
|
250
|
+
if (parsed.version !== WARM_TURN_END_SCHEMA_VERSION ||
|
|
251
|
+
typeof parsed.deliveryId !==
|
|
252
|
+
"string") {
|
|
253
|
+
socket.end(`${JSON.stringify({ error: `turn-end ack schema ${parsed.version} != ${WARM_TURN_END_SCHEMA_VERSION}` })}\n`);
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
const turnCwd = parsed.cwd ?? DEFAULT_CWD;
|
|
257
|
+
if (!isWithinServerWorkspace(turnCwd)) {
|
|
258
|
+
socket.end(`${JSON.stringify({ error: rejectForeignTurnCwd("turn-end-ack", turnCwd) })}\n`);
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
const acknowledged = acknowledgeTurnEnd(turnCwd, parsed.deliveryId);
|
|
262
|
+
socket.end(`${JSON.stringify({
|
|
263
|
+
result: {
|
|
264
|
+
route: "turn-end-ack",
|
|
265
|
+
version: WARM_TURN_END_SCHEMA_VERSION,
|
|
266
|
+
acknowledged,
|
|
267
|
+
},
|
|
268
|
+
})}\n`);
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
if (parsed.route === "turn-end") {
|
|
272
|
+
if (parsed.version !== WARM_TURN_END_SCHEMA_VERSION) {
|
|
273
|
+
socket.end(`${JSON.stringify({ error: `turn-end schema ${parsed.version} != ${WARM_TURN_END_SCHEMA_VERSION}` })}\n`);
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
const turnCwd = parsed.cwd ?? DEFAULT_CWD;
|
|
277
|
+
if (!isWithinServerWorkspace(turnCwd)) {
|
|
278
|
+
socket.end(`${JSON.stringify({ error: rejectForeignTurnCwd("turn-end", turnCwd) })}\n`);
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
// #1274: a client that already gave up (hook timeout, killed
|
|
282
|
+
// Claude Code) leaves a destroyed socket. Starting a heavy
|
|
283
|
+
// pass whose reply nobody can read is pure waste; the findings
|
|
284
|
+
// stay in the cache for the next Stop either way.
|
|
285
|
+
if (socket.destroyed) {
|
|
286
|
+
console.error(`[pi-lens-mcp] warm turn-end: client gone before the pass started (${turnCwd})`);
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
console.error(`[pi-lens-mcp] warm turn-end: ${turnCwd}`);
|
|
290
|
+
await ensureReady(turnCwd);
|
|
291
|
+
const delivery = await runTurnEndForIpc(turnCwd);
|
|
292
|
+
const result = {
|
|
293
|
+
route: "turn-end",
|
|
294
|
+
version: WARM_TURN_END_SCHEMA_VERSION,
|
|
295
|
+
turnEnd: delivery.outcome.turnEnd,
|
|
296
|
+
tests: delivery.outcome.tests,
|
|
297
|
+
deliveryId: delivery.deliveryId,
|
|
298
|
+
};
|
|
299
|
+
socket.end(`${JSON.stringify({ result })}\n`);
|
|
225
300
|
return;
|
|
226
301
|
}
|
|
227
|
-
const req =
|
|
302
|
+
const req = parsed;
|
|
228
303
|
console.error(`[pi-lens-mcp] warm analyze: ${req.file}`);
|
|
229
|
-
// Warm = full LSP + an edit-detection path (register turn-state) +
|
|
230
|
-
// review-graph maintenance (#536 — this is an in-process, long-lived
|
|
231
|
-
// path, unlike the ephemeral `fresh` worker).
|
|
232
304
|
const result = await analyzeFile(req.file, req.cwd, {
|
|
233
305
|
registerTurnState: true,
|
|
234
306
|
updateGraph: true,
|
|
@@ -238,8 +310,8 @@ function startIpcServer() {
|
|
|
238
310
|
catch (err) {
|
|
239
311
|
socket.end(`${JSON.stringify({ error: String(err) })}\n`);
|
|
240
312
|
}
|
|
241
|
-
})
|
|
242
|
-
});
|
|
313
|
+
});
|
|
314
|
+
}));
|
|
243
315
|
socket.on("error", () => socket.destroy());
|
|
244
316
|
});
|
|
245
317
|
ipc.on("error", (err) => {
|
|
@@ -340,7 +412,12 @@ const cacheManager = new CacheManager();
|
|
|
340
412
|
// nothing — a no-op dressed as a fix, not a real parity gap. The 4th arg is left
|
|
341
413
|
// at its default (`async () => {}`, already a no-op) rather than importing and
|
|
342
414
|
// wiring a flush with nothing to flush.
|
|
343
|
-
const lensDiagnosticsTool = createLensDiagnosticsTool(cacheManager, () => DEFAULT_CWD
|
|
415
|
+
const lensDiagnosticsTool = createLensDiagnosticsTool(cacheManager, () => DEFAULT_CWD, undefined, undefined, undefined, undefined,
|
|
416
|
+
// #1413 surface parity: validate cached test-runner findings against the
|
|
417
|
+
// same session identity the in-process path uses. Resolved lazily — until
|
|
418
|
+
// an MCP session context exists there is no session to compare against and
|
|
419
|
+
// validation skips the check, which is the honest classification.
|
|
420
|
+
() => peekMcpSessionRuntime());
|
|
344
421
|
const astGrepClient = new AstGrepClient();
|
|
345
422
|
const astGrepSearchTool = createAstGrepSearchTool(astGrepClient);
|
|
346
423
|
const astGrepReplaceTool = createAstGrepReplaceTool(astGrepClient);
|
|
@@ -395,7 +472,7 @@ const ALL_TOOLS = [
|
|
|
395
472
|
},
|
|
396
473
|
flags: {
|
|
397
474
|
type: "object",
|
|
398
|
-
description:
|
|
475
|
+
description: 'Optional pi-lens flag overrides for this run, e.g. {"no-lsp": true} to bench the non-LSP path.',
|
|
399
476
|
},
|
|
400
477
|
},
|
|
401
478
|
required: ["file"],
|
|
@@ -415,8 +492,14 @@ const ALL_TOOLS = [
|
|
|
415
492
|
inputSchema: {
|
|
416
493
|
type: "object",
|
|
417
494
|
properties: {
|
|
418
|
-
limit: {
|
|
419
|
-
|
|
495
|
+
limit: {
|
|
496
|
+
type: "number",
|
|
497
|
+
description: "Max reports to return (default 5).",
|
|
498
|
+
},
|
|
499
|
+
file: {
|
|
500
|
+
type: "string",
|
|
501
|
+
description: "Only reports whose path ends with this.",
|
|
502
|
+
},
|
|
420
503
|
},
|
|
421
504
|
},
|
|
422
505
|
},
|
|
@@ -439,6 +522,13 @@ const ALL_TOOLS = [
|
|
|
439
522
|
properties: {
|
|
440
523
|
cwd: { type: "string" },
|
|
441
524
|
maxFiles: { type: "number", description: "Cap files scanned." },
|
|
525
|
+
includeGenerated: {
|
|
526
|
+
type: "boolean",
|
|
527
|
+
description: "Scan WITHOUT the generated/artifact NAME-heuristic filter " +
|
|
528
|
+
"(lockfiles, gen.ts-style names, generated/ dirs, …). Default " +
|
|
529
|
+
"false. Use when a scan's 'excluded by generated-name " +
|
|
530
|
+
"heuristics' notice suggests a real file was skipped.",
|
|
531
|
+
},
|
|
442
532
|
},
|
|
443
533
|
},
|
|
444
534
|
},
|
|
@@ -460,7 +550,7 @@ const ALL_TOOLS = [
|
|
|
460
550
|
properties: {
|
|
461
551
|
query: {
|
|
462
552
|
type: "string",
|
|
463
|
-
description: "Identifier-ish query, e.g. 'authenticate user'.",
|
|
553
|
+
description: "Identifier-ish query, e.g. 'authenticate user'. Mix in composable prefix filters: lang:<kind> (e.g. lang:jsts, lang:python — kinds from file-kinds.ts), file:<substr> (path substring), ext:<ext> (e.g. ext:ts or ext:.ts), each optionally negated with a leading '-' (-file:test). Filters apply before ranking; e.g. 'lang:jsts file:clients/ -file:test rank'. Unknown prefixes/kinds error with the supported list.",
|
|
464
554
|
},
|
|
465
555
|
cwd: { type: "string" },
|
|
466
556
|
limit: {
|
|
@@ -495,7 +585,9 @@ const ALL_TOOLS = [
|
|
|
495
585
|
"(this path never calls LSP). `semantic.source` reports whether graph " +
|
|
496
586
|
"data was used. Pass `blastRadius: true` for the cross-file blast radius " +
|
|
497
587
|
"(transitive dependents as ranked file reads, read-only over the cached " +
|
|
498
|
-
|
|
588
|
+
"graph). Pass `callGraph: true` for bounded derived callers/callees; a " +
|
|
589
|
+
"cold or stale call-graph cache is reported explicitly, never as zero calls. " +
|
|
590
|
+
'`view: "compact"` returns a line-oriented text rendering ' +
|
|
499
591
|
"(cheapest option) instead of JSON. An outline shows shape, not bodies.",
|
|
500
592
|
inputSchema: {
|
|
501
593
|
type: "object",
|
|
@@ -526,6 +618,14 @@ const ALL_TOOLS = [
|
|
|
526
618
|
type: "number",
|
|
527
619
|
description: "Max hops for the blast-radius walk (default 3). Only used with blastRadius.",
|
|
528
620
|
},
|
|
621
|
+
callGraph: {
|
|
622
|
+
type: "boolean",
|
|
623
|
+
description: "Include bounded derived callers/callees from the cached FunctionCallGraph; cold or stale cache state is explicit.",
|
|
624
|
+
},
|
|
625
|
+
maxCallGraphEntries: {
|
|
626
|
+
type: "number",
|
|
627
|
+
description: "Per-direction cap for call-graph relations (default 20).",
|
|
628
|
+
},
|
|
529
629
|
},
|
|
530
630
|
required: ["file"],
|
|
531
631
|
},
|
|
@@ -685,8 +785,11 @@ const ALL_TOOLS = [
|
|
|
685
785
|
{
|
|
686
786
|
name: "pilens_ast_grep_search",
|
|
687
787
|
description: "Structural (AST) code search via ast-grep — match by code structure, not " +
|
|
688
|
-
"text. Use
|
|
689
|
-
"'function $NAME() { $$$ }')
|
|
788
|
+
"text. Use complete patterns with arguments (e.g. 'console.log($MSG)', " +
|
|
789
|
+
"'function $NAME($$$ARGS) { $$$BODY }'), or use nodeKind to find every " +
|
|
790
|
+
"node of a known grammar kind. Metavariables do not match text inside " +
|
|
791
|
+
"quoted string literals; use an exact string or grep for wildcard text. " +
|
|
792
|
+
"This is the same schema and synthesis path as the pi tool.",
|
|
690
793
|
inputSchema: schemaWithCwd(astGrepSearchTool.parameters),
|
|
691
794
|
},
|
|
692
795
|
{
|
|
@@ -739,7 +842,10 @@ async function callTool(name, args) {
|
|
|
739
842
|
if (name === "pilens_analyze") {
|
|
740
843
|
const file = args.file;
|
|
741
844
|
if (typeof file !== "string" || file.length === 0) {
|
|
742
|
-
return {
|
|
845
|
+
return {
|
|
846
|
+
...toolText("pilens_analyze requires a 'file' string."),
|
|
847
|
+
isError: true,
|
|
848
|
+
};
|
|
743
849
|
}
|
|
744
850
|
const cwd = typeof args.cwd === "string" ? args.cwd : DEFAULT_CWD;
|
|
745
851
|
const requestedMode = args.mode === "fresh" ? "fresh" : "warm";
|
|
@@ -814,7 +920,8 @@ async function callTool(name, args) {
|
|
|
814
920
|
const maxFiles = typeof args.maxFiles === "number" && Number.isFinite(args.maxFiles)
|
|
815
921
|
? Math.max(1, Math.floor(args.maxFiles))
|
|
816
922
|
: undefined;
|
|
817
|
-
const
|
|
923
|
+
const includeGenerated = args.includeGenerated === true;
|
|
924
|
+
const snapshot = await projectScan(cwd, maxFiles, includeGenerated);
|
|
818
925
|
// #747: a cwd at/above $HOME refuses to walk — say so instead of letting
|
|
819
926
|
// "Scanned 0 file(s) → 0 diagnostics" read as a clean project.
|
|
820
927
|
if (snapshot.unsafeRoot) {
|
|
@@ -840,6 +947,11 @@ async function callTool(name, args) {
|
|
|
840
947
|
const truncationNotice = scanTruncationNotice(snapshot);
|
|
841
948
|
if (truncationNotice)
|
|
842
949
|
summaryLines.push(truncationNotice);
|
|
950
|
+
// #1107 phase 2: same "reached the seam but nothing rendered it" gap as
|
|
951
|
+
// #784's scanTruncationNotice, for the generated-name skip counters.
|
|
952
|
+
const skipNotice = generatedSkipNotice(snapshot);
|
|
953
|
+
if (skipNotice)
|
|
954
|
+
summaryLines.push(skipNotice);
|
|
843
955
|
return toolText(summaryLines.join("\n"), {
|
|
844
956
|
filesScanned: snapshot.filesScanned,
|
|
845
957
|
runners: snapshot.runners,
|
|
@@ -852,6 +964,15 @@ async function callTool(name, args) {
|
|
|
852
964
|
...(snapshot.treeSitterStatus
|
|
853
965
|
? { treeSitterStatus: snapshot.treeSitterStatus }
|
|
854
966
|
: {}),
|
|
967
|
+
...(snapshot.generatedFileSkips
|
|
968
|
+
? { generatedFileSkips: snapshot.generatedFileSkips }
|
|
969
|
+
: {}),
|
|
970
|
+
...(snapshot.generatedNameOnlySkips
|
|
971
|
+
? { generatedNameOnlySkips: snapshot.generatedNameOnlySkips }
|
|
972
|
+
: {}),
|
|
973
|
+
...(snapshot.generatedDirSkips
|
|
974
|
+
? { generatedDirSkips: snapshot.generatedDirSkips }
|
|
975
|
+
: {}),
|
|
855
976
|
});
|
|
856
977
|
}
|
|
857
978
|
if (name === "pilens_symbol_search") {
|
|
@@ -868,7 +989,8 @@ async function callTool(name, args) {
|
|
|
868
989
|
const lang = typeof args.lang === "string" ? args.lang : undefined;
|
|
869
990
|
const { available, results, hint, unavailableReason, coverage, snapshotGeneratedAt, } = await symbolSearch(query, cwd, limit, { paths, lang });
|
|
870
991
|
if (!available) {
|
|
871
|
-
return toolText(hint ??
|
|
992
|
+
return toolText(hint ??
|
|
993
|
+
"No word index for this workspace yet — run pilens_session_start first.", { available: false, query, hint, unavailableReason }, true);
|
|
872
994
|
}
|
|
873
995
|
const stalenessNote = graphStalenessNote(snapshotGeneratedAt, "Project snapshot");
|
|
874
996
|
if (results.length === 0) {
|
|
@@ -934,12 +1056,21 @@ async function callTool(name, args) {
|
|
|
934
1056
|
Number.isFinite(args.blastRadiusDepth)
|
|
935
1057
|
? Math.max(1, Math.floor(args.blastRadiusDepth))
|
|
936
1058
|
: undefined;
|
|
937
|
-
const
|
|
1059
|
+
const callGraph = args.callGraph === true;
|
|
1060
|
+
const maxCallGraphEntries = typeof args.maxCallGraphEntries === "number" &&
|
|
1061
|
+
Number.isFinite(args.maxCallGraphEntries)
|
|
1062
|
+
? Math.max(1, Math.floor(args.maxCallGraphEntries))
|
|
1063
|
+
: undefined;
|
|
1064
|
+
const view = args.view === "summary" || args.view === "compact"
|
|
1065
|
+
? args.view
|
|
1066
|
+
: undefined;
|
|
938
1067
|
const focus = typeof args.focus === "string" ? args.focus : undefined;
|
|
939
1068
|
const report = await moduleReport(file, cwd, {
|
|
940
1069
|
maxRefsPerSymbol,
|
|
941
1070
|
blastRadius,
|
|
942
1071
|
blastRadiusDepth,
|
|
1072
|
+
callGraph,
|
|
1073
|
+
maxCallGraphEntries,
|
|
943
1074
|
view,
|
|
944
1075
|
focus,
|
|
945
1076
|
});
|
|
@@ -960,14 +1091,18 @@ async function callTool(name, args) {
|
|
|
960
1091
|
content: [
|
|
961
1092
|
{
|
|
962
1093
|
type: "text",
|
|
963
|
-
text: graphStaleness
|
|
1094
|
+
text: graphStaleness
|
|
1095
|
+
? `${compactText}\n\n${graphStaleness}`
|
|
1096
|
+
: compactText,
|
|
964
1097
|
},
|
|
965
1098
|
],
|
|
966
1099
|
};
|
|
967
1100
|
}
|
|
968
1101
|
// Compact (unindented) JSON — matches the pi tool's mirror (#512); an
|
|
969
1102
|
// agent parses this payload, it doesn't read it formatted.
|
|
970
|
-
return toolText(summary, graphStaleness
|
|
1103
|
+
return toolText(summary, graphStaleness
|
|
1104
|
+
? { ...report, graphStalenessNote: graphStaleness }
|
|
1105
|
+
: report, true);
|
|
971
1106
|
}
|
|
972
1107
|
if (name === "pilens_project_report") {
|
|
973
1108
|
const cwd = typeof args.cwd === "string" ? args.cwd : DEFAULT_CWD;
|
|
@@ -992,7 +1127,9 @@ async function callTool(name, args) {
|
|
|
992
1127
|
content: [
|
|
993
1128
|
{
|
|
994
1129
|
type: "text",
|
|
995
|
-
text: graphStaleness
|
|
1130
|
+
text: graphStaleness
|
|
1131
|
+
? `${compactText}\n\n${graphStaleness}`
|
|
1132
|
+
: compactText,
|
|
996
1133
|
},
|
|
997
1134
|
],
|
|
998
1135
|
};
|
|
@@ -1001,7 +1138,9 @@ async function callTool(name, args) {
|
|
|
1001
1138
|
`${report.entryPoints?.length ?? 0} entry point(s), ` +
|
|
1002
1139
|
`${report.riskHotspots?.length ?? 0} risk hotspot(s)` +
|
|
1003
1140
|
(graphStaleness ? `\n\n${graphStaleness}` : "");
|
|
1004
|
-
return toolText(summary, graphStaleness
|
|
1141
|
+
return toolText(summary, graphStaleness
|
|
1142
|
+
? { ...report, graphStalenessNote: graphStaleness }
|
|
1143
|
+
: report, true);
|
|
1005
1144
|
}
|
|
1006
1145
|
if (name === "pilens_read_symbol") {
|
|
1007
1146
|
const file = typeof args.file === "string" ? args.file : "";
|
|
@@ -1032,13 +1171,20 @@ async function callTool(name, args) {
|
|
|
1032
1171
|
? ` (${result.ambiguous.count} matches — returned the ${result.kind}; pass \`kind\` to disambiguate: ${result.ambiguous.kinds.join(", ")})`
|
|
1033
1172
|
: "";
|
|
1034
1173
|
const header = `${result.kind} ${result.name}${ambiguityNote}${sigSuffix} ${path.relative(cwd, result.path)}:${result.startLine}-${result.endLine}`;
|
|
1035
|
-
return {
|
|
1174
|
+
return {
|
|
1175
|
+
content: [
|
|
1176
|
+
{ type: "text", text: `${header}\n\n${result.source ?? ""}` },
|
|
1177
|
+
],
|
|
1178
|
+
};
|
|
1036
1179
|
}
|
|
1037
1180
|
if (name === "pilens_read_enclosing") {
|
|
1038
1181
|
const file = typeof args.file === "string" ? args.file : "";
|
|
1039
1182
|
const line = typeof args.line === "number" ? args.line : Number.NaN;
|
|
1040
1183
|
if (!file.trim() || !Number.isFinite(line)) {
|
|
1041
|
-
return {
|
|
1184
|
+
return {
|
|
1185
|
+
...toolText("Provide `file` and a numeric `line`."),
|
|
1186
|
+
isError: true,
|
|
1187
|
+
};
|
|
1042
1188
|
}
|
|
1043
1189
|
const cwd = typeof args.cwd === "string" ? args.cwd : DEFAULT_CWD;
|
|
1044
1190
|
const kinds = Array.isArray(args.kinds)
|
|
@@ -1082,7 +1228,11 @@ async function callTool(name, args) {
|
|
|
1082
1228
|
? `${result.startLine}-${result.endLine} (partial of ${result.enclosingStartLine}-${result.enclosingEndLine})`
|
|
1083
1229
|
: `${result.startLine}-${result.endLine}`;
|
|
1084
1230
|
const header = `${result.kind} ${result.name} ${path.relative(cwd, result.path)}:${range}`;
|
|
1085
|
-
return {
|
|
1231
|
+
return {
|
|
1232
|
+
content: [
|
|
1233
|
+
{ type: "text", text: `${header}\n\n${result.source ?? ""}` },
|
|
1234
|
+
],
|
|
1235
|
+
};
|
|
1086
1236
|
}
|
|
1087
1237
|
if (name === "pilens_health") {
|
|
1088
1238
|
const { aliveClients, servers, brokenServers } = lspStatus();
|
|
@@ -1090,6 +1240,13 @@ async function callTool(name, args) {
|
|
|
1090
1240
|
const stats = diagnosticStats();
|
|
1091
1241
|
const autoSession = getAutoSessionStatus();
|
|
1092
1242
|
const treeSitter = treeSitterRuntimeStatus();
|
|
1243
|
+
const degradations = getDegradationSummary();
|
|
1244
|
+
// #1272, following the #544 precedent: the Stop hook is a separate,
|
|
1245
|
+
// short-lived process, so a turn-end it skipped left no trace here at all
|
|
1246
|
+
// — a dead integration looked exactly like a clean turn, forever. The
|
|
1247
|
+
// hook records its outcome per workspace; this is where it becomes
|
|
1248
|
+
// visible without `claude --debug` log spelunking.
|
|
1249
|
+
const turnEnd = readTurnEndStatus(DEFAULT_CWD) ?? null;
|
|
1093
1250
|
// #620: best-effort — a footprint read failure must never break the rest
|
|
1094
1251
|
// of pilens_health's (much older, more load-bearing) reporting.
|
|
1095
1252
|
const footprint = await resourceFootprint().catch(() => null);
|
|
@@ -1098,8 +1255,12 @@ async function callTool(name, args) {
|
|
|
1098
1255
|
? `Tree-sitter: DEGRADED — WASM runtime aborted${treeSitter.abortedAt ? ` at ${treeSitter.abortedAt}` : ""}; restart this server to recover`
|
|
1099
1256
|
: "Tree-sitter: available",
|
|
1100
1257
|
`LSP: ${aliveClients} alive client(s)`,
|
|
1101
|
-
...servers.
|
|
1258
|
+
...servers.flatMap((server) => [
|
|
1259
|
+
` ${server.connected ? "✓" : "✗"} ${server.serverId} (${server.root})`,
|
|
1260
|
+
...server.pullFailureHistory.slice(-1).map((failure) => ` ⚠ diagnostics pull failed: ${failure.method}${failure.code !== undefined ? ` (${failure.code})` : ""} — ${failure.message.length > 200 ? `${failure.message.slice(0, 200)}…` : failure.message}`),
|
|
1261
|
+
]),
|
|
1102
1262
|
...renderLspBrokenStatusLines(brokenServers),
|
|
1263
|
+
...renderDegradationLines(degradations),
|
|
1103
1264
|
last
|
|
1104
1265
|
? `Last dispatch: ${path.basename(last.filePath)} — ${last.totalDurationMs}ms, ${last.totalDiagnostics} diagnostic(s)`
|
|
1105
1266
|
: "Last dispatch: none yet",
|
|
@@ -1107,6 +1268,11 @@ async function callTool(name, args) {
|
|
|
1107
1268
|
autoSession
|
|
1108
1269
|
? `Auto session_start: ${autoSession.succeeded ? "succeeded" : autoSession.error ? "FAILED" : autoSession.attempted ? "in progress" : "not yet attempted"}${autoSession.firedAt ? ` (fired ${autoSession.firedAt})` : ""}${autoSession.error ? ` — ${autoSession.error}` : ""}`
|
|
1109
1270
|
: "Auto session_start: disabled (PI_LENS_MCP_AUTO_SESSION not set)",
|
|
1271
|
+
turnEnd
|
|
1272
|
+
? `Stop-hook turn-end: ${turnEnd.ran} ran · ${turnEnd.skipped} skipped` +
|
|
1273
|
+
`${turnEnd.lastRunAt ? ` (last ran ${turnEnd.lastRunAt})` : ""}` +
|
|
1274
|
+
`${turnEnd.lastSkipReason ? ` — last skip: ${turnEnd.lastSkipReason}${turnEnd.lastSkipAt ? ` at ${turnEnd.lastSkipAt}` : ""}` : ""}`
|
|
1275
|
+
: "Stop-hook turn-end: no activity recorded (hook not installed, or no Stop yet)",
|
|
1110
1276
|
footprint
|
|
1111
1277
|
? `Resource footprint: ${footprint.instanceCount} pi-lens instance(s) · ` +
|
|
1112
1278
|
`${(footprint.totalRssBytes / 1024 / 1024).toFixed(0)}MB RSS · ` +
|
|
@@ -1132,7 +1298,9 @@ async function callTool(name, args) {
|
|
|
1132
1298
|
},
|
|
1133
1299
|
autoSession,
|
|
1134
1300
|
treeSitter,
|
|
1301
|
+
turnEnd,
|
|
1135
1302
|
resourceFootprint: footprint,
|
|
1303
|
+
degradations,
|
|
1136
1304
|
});
|
|
1137
1305
|
}
|
|
1138
1306
|
if (name === "pilens_diagnostics") {
|
|
@@ -1186,7 +1354,9 @@ async function callTool(name, args) {
|
|
|
1186
1354
|
}
|
|
1187
1355
|
if (name === "pilens_ast_grep_search" || name === "pilens_ast_grep_replace") {
|
|
1188
1356
|
const cwd = typeof args.cwd === "string" ? args.cwd : DEFAULT_CWD;
|
|
1189
|
-
const tool = name === "pilens_ast_grep_search"
|
|
1357
|
+
const tool = name === "pilens_ast_grep_search"
|
|
1358
|
+
? astGrepSearchTool
|
|
1359
|
+
: astGrepReplaceTool;
|
|
1190
1360
|
const out = (await tool.execute("mcp", args, new AbortController().signal, undefined, { cwd }));
|
|
1191
1361
|
return { content: out.content };
|
|
1192
1362
|
}
|
|
@@ -1270,7 +1440,10 @@ function withStaleWarning(result) {
|
|
|
1270
1440
|
...result,
|
|
1271
1441
|
content: [
|
|
1272
1442
|
...result.content.slice(0, -1),
|
|
1273
|
-
{
|
|
1443
|
+
{
|
|
1444
|
+
...last,
|
|
1445
|
+
text: `${last.text}\n\nwarmCodeStale: true\n${STALE_WARN_ONLY}`,
|
|
1446
|
+
},
|
|
1274
1447
|
],
|
|
1275
1448
|
};
|
|
1276
1449
|
}
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* instead, so calling this tool is harmless, just unnecessary.
|
|
19
19
|
*/
|
|
20
20
|
import { Type } from "../clients/deps/typebox.js";
|
|
21
|
-
export function createActivateToolsTool(pi, lazyTools) {
|
|
21
|
+
export function createActivateToolsTool(pi, lazyTools, options = {}) {
|
|
22
22
|
const lazyNames = lazyTools.map((t) => t.name);
|
|
23
23
|
const lazyNameSet = new Set(lazyNames);
|
|
24
24
|
const catalog = lazyTools.map((t) => `${t.name} — ${t.summary}`).join("\n");
|
|
@@ -35,7 +35,7 @@ export function createActivateToolsTool(pi, lazyTools) {
|
|
|
35
35
|
description: "Names of situational tools to activate (see this tool's description for the catalog).",
|
|
36
36
|
}),
|
|
37
37
|
}),
|
|
38
|
-
async execute(_toolCallId, params, _signal, _onUpdate) {
|
|
38
|
+
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
39
39
|
const requested = Array.isArray(params.tools)
|
|
40
40
|
? params.tools.filter((t) => typeof t === "string" && lazyNameSet.has(t))
|
|
41
41
|
: [];
|
|
@@ -53,10 +53,22 @@ export function createActivateToolsTool(pi, lazyTools) {
|
|
|
53
53
|
}
|
|
54
54
|
// Additive only, per the docs' contract: never drop currently active
|
|
55
55
|
// tools in the same call.
|
|
56
|
+
// Remember every requested tool, not just the newly-added ones: a
|
|
57
|
+
// tool that is already active still has to survive the next
|
|
58
|
+
// fork/reload/resume restore.
|
|
59
|
+
options.onActivated?.(requested);
|
|
56
60
|
const active = typeof pi.getActiveTools === "function" ? pi.getActiveTools() : [];
|
|
57
|
-
const
|
|
58
|
-
|
|
61
|
+
const activeSet = new Set(active);
|
|
62
|
+
const added = requested.filter((name) => !activeSet.has(name));
|
|
63
|
+
const merged = [...new Set([...active, ...added])];
|
|
64
|
+
if (added.length > 0 && typeof pi.setActiveTools === "function") {
|
|
59
65
|
pi.setActiveTools(merged);
|
|
66
|
+
options.onMutation?.({
|
|
67
|
+
addedCount: added.length,
|
|
68
|
+
removedCount: 0,
|
|
69
|
+
reason: "lazy_activation",
|
|
70
|
+
deferralApplies: options.deferredToolSupport?.(ctx) ?? false,
|
|
71
|
+
});
|
|
60
72
|
}
|
|
61
73
|
return {
|
|
62
74
|
content: [
|
|
@@ -65,7 +77,7 @@ export function createActivateToolsTool(pi, lazyTools) {
|
|
|
65
77
|
text: `Activated: ${requested.join(", ")}. Available starting next turn.`,
|
|
66
78
|
},
|
|
67
79
|
],
|
|
68
|
-
details: { matches: requested, added
|
|
80
|
+
details: { matches: requested, added },
|
|
69
81
|
};
|
|
70
82
|
},
|
|
71
83
|
};
|
|
@@ -67,7 +67,12 @@ export function createAstGrepReplaceTool(astGrepClient) {
|
|
|
67
67
|
}),
|
|
68
68
|
paths: Type.Optional(Type.Array(Type.String(), { description: "Specific files/folders" })),
|
|
69
69
|
insideKind: Type.Optional(Type.String({ description: "Restrict matches to nodes inside an ancestor of this AST node kind. Synthesizes a YAML rule." })),
|
|
70
|
-
hasKind: Type.Optional(Type.String({
|
|
70
|
+
hasKind: Type.Optional(Type.String({
|
|
71
|
+
description: 'Restrict matches to nodes whose immediate child has this AST node kind (ast-grep default stopBy: neighbor). Example: `hasKind: "await_expression"`.',
|
|
72
|
+
})),
|
|
73
|
+
hasDescendantKind: Type.Optional(Type.String({
|
|
74
|
+
description: "Restrict matches to nodes containing this AST node kind anywhere in their descendants. Explicit recursive form (`stopBy: end`); use this instead of `hasKind` when nesting is not immediate.",
|
|
75
|
+
})),
|
|
71
76
|
follows: Type.Optional(Type.String({ description: "Restrict matches to nodes that immediately follow a sibling matching this pattern." })),
|
|
72
77
|
precedes: Type.Optional(Type.String({ description: "Restrict matches to nodes that immediately precede a sibling matching this pattern." })),
|
|
73
78
|
apply: Type.Optional(Type.Boolean({ description: "Apply changes (default: false)" })),
|
|
@@ -78,7 +83,7 @@ export function createAstGrepReplaceTool(astGrepClient) {
|
|
|
78
83
|
}),
|
|
79
84
|
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
80
85
|
const startedAt = Date.now();
|
|
81
|
-
const { pattern, rewrite, paths, apply, strictness, insideKind, hasKind, follows, precedes } = params;
|
|
86
|
+
const { pattern, rewrite, paths, apply, strictness, insideKind, hasKind, hasDescendantKind, follows, precedes } = params;
|
|
82
87
|
const lang = (params.lang ?? "").replace(/^"|"$/g, "");
|
|
83
88
|
const pathsCount = paths?.length ?? 1;
|
|
84
89
|
const applyFlag = apply ?? false;
|
|
@@ -122,10 +127,10 @@ export function createAstGrepReplaceTool(astGrepClient) {
|
|
|
122
127
|
}
|
|
123
128
|
const searchPaths = paths?.length ? paths : [ctx.cwd || "."];
|
|
124
129
|
// Phase 3: structural-intent params → synthesize YAML with fix: field
|
|
125
|
-
if (hasStructuralIntent({ insideKind, hasKind, follows, precedes })) {
|
|
130
|
+
if (hasStructuralIntent({ insideKind, hasKind, hasDescendantKind, follows, precedes })) {
|
|
126
131
|
let ruleYaml;
|
|
127
132
|
try {
|
|
128
|
-
ruleYaml = synthesizeReplaceRule({ pattern, lang, rewrite, insideKind, hasKind, follows, precedes });
|
|
133
|
+
ruleYaml = synthesizeReplaceRule({ pattern, lang, rewrite, insideKind, hasKind, hasDescendantKind, follows, precedes });
|
|
129
134
|
}
|
|
130
135
|
catch (err) {
|
|
131
136
|
logOutcome("error", { errorRaw: String(err) });
|