@herbertgao/pi-extensions 2026.9.2 → 2026.9.4
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 +4 -2
- package/THIRD_PARTY_NOTICES.md +49 -0
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/compact-mode.ts +3 -2
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/default-mode.ts +16 -11
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-renderer.ts +20 -6
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/grouping.ts +12 -7
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/result.ts +98 -0
- package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
- package/node_modules/@herbertgao/sol-pi/LICENSE +19 -0
- package/node_modules/@herbertgao/sol-pi/README.md +159 -0
- package/node_modules/@herbertgao/sol-pi/SECURITY.md +26 -0
- package/node_modules/@herbertgao/sol-pi/THIRD_PARTY_NOTICES.md +19 -0
- package/node_modules/@herbertgao/sol-pi/agents-install.md +150 -0
- package/node_modules/@herbertgao/sol-pi/assets/sol-pi-hero.png +0 -0
- package/node_modules/@herbertgao/sol-pi/docs/compatibility.md +69 -0
- package/node_modules/@herbertgao/sol-pi/docs/configuration.md +75 -0
- package/node_modules/@herbertgao/sol-pi/package.json +76 -0
- package/node_modules/@herbertgao/sol-pi/scripts/check-pi-compat.mjs +32 -0
- package/node_modules/@herbertgao/sol-pi/scripts/check-sol-pi-config.mjs +120 -0
- package/node_modules/@herbertgao/sol-pi/sol-pi.example.json +10 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/config.ts +135 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/action-fusion/file-queue.ts +74 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/action-fusion/index.ts +185 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/action-fusion/then-run.ts +128 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/evidence-preserving-reducer/archive.ts +53 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/evidence-preserving-reducer/candidate.ts +101 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/evidence-preserving-reducer/config.ts +71 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/evidence-preserving-reducer/index.ts +220 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/evidence-preserving-reducer/journal.ts +25 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/evidence-preserving-reducer/provider.ts +164 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/evidence-preserving-reducer/receipt.ts +177 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/observation-pack/index.ts +227 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/observation-pack/ledger.ts +20 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/observation-pack/observation.ts +252 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/economics.ts +237 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/extension.ts +455 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/index.ts +49 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/plan.ts +79 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/state.ts +208 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/tools.ts +100 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/index.ts +42 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/runtime-paths.ts +17 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/tui.ts +71 -0
- package/node_modules/@narumitw/pi-btw/dist/index.ts +12 -2
- package/node_modules/@narumitw/pi-btw/dist/index.ts.map +2 -2
- package/node_modules/@narumitw/pi-btw/package.json +1 -1
- package/node_modules/@narumitw/pi-btw/src/btw.ts +13 -2
- package/node_modules/pi-antigravity/LICENSE +21 -0
- package/node_modules/pi-antigravity/README.md +194 -0
- package/node_modules/pi-antigravity/package.json +67 -0
- package/node_modules/pi-antigravity/src/auth/index.ts +14 -0
- package/node_modules/pi-antigravity/src/auth/oauth.ts +442 -0
- package/node_modules/pi-antigravity/src/client/client.ts +561 -0
- package/node_modules/pi-antigravity/src/client/index.ts +1 -0
- package/node_modules/pi-antigravity/src/diagnostics/diagnostics.ts +96 -0
- package/node_modules/pi-antigravity/src/diagnostics/index.ts +1 -0
- package/node_modules/pi-antigravity/src/image/image.ts +336 -0
- package/node_modules/pi-antigravity/src/image/index.ts +1 -0
- package/node_modules/pi-antigravity/src/index.ts +280 -0
- package/node_modules/pi-antigravity/src/models/discovery.ts +154 -0
- package/node_modules/pi-antigravity/src/models/grouping.ts +424 -0
- package/node_modules/pi-antigravity/src/models/index.ts +3 -0
- package/node_modules/pi-antigravity/src/models/models.ts +500 -0
- package/node_modules/pi-antigravity/src/stream/index.ts +1 -0
- package/node_modules/pi-antigravity/src/stream/stream.ts +1460 -0
- package/node_modules/pi-antigravity/src/types/enums.ts +42 -0
- package/node_modules/pi-antigravity/src/types/index.ts +2 -0
- package/node_modules/pi-antigravity/src/types/types.ts +292 -0
- package/node_modules/pi-antigravity/src/usage/index.ts +1 -0
- package/node_modules/pi-antigravity/src/usage/usage.ts +371 -0
- package/node_modules/pi-antigravity/src/utils/http.ts +91 -0
- package/node_modules/pi-antigravity/src/utils/index.ts +3 -0
- package/node_modules/pi-antigravity/src/utils/security.ts +73 -0
- package/node_modules/pi-antigravity/src/utils/util.ts +132 -0
- package/node_modules/pi-antigravity/tsconfig.json +21 -0
- package/node_modules/pi-lens/CHANGELOG.md +176 -0
- package/node_modules/pi-lens/README.md +13 -8
- package/node_modules/pi-lens/config/dependency-cruiser-eager-allowlist.json +3 -1
- package/node_modules/pi-lens/dist/clients/analysed-root.js +1 -0
- package/node_modules/pi-lens/dist/clients/ast-grep-tool-logger.js +1 -1
- package/node_modules/pi-lens/dist/clients/biome-client.js +13 -2
- package/node_modules/pi-lens/dist/clients/bounded-telemetry.js +2 -0
- package/node_modules/pi-lens/dist/clients/cache-observability.js +122 -1
- package/node_modules/pi-lens/dist/clients/complexity-client.js +5 -0
- package/node_modules/pi-lens/dist/clients/config-diagnostic-codes.js +2 -0
- package/node_modules/pi-lens/dist/clients/config-resolve.js +6 -3
- package/node_modules/pi-lens/dist/clients/config-schema.js +17 -0
- package/node_modules/pi-lens/dist/clients/config-warn.js +2 -2
- package/node_modules/pi-lens/dist/clients/dead-code-client.js +8 -1
- package/node_modules/pi-lens/dist/clients/dependency-checker.js +5 -1
- package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +38 -15
- package/node_modules/pi-lens/dist/clients/dispatch/facts/function-facts.js +1 -1
- package/node_modules/pi-lens/dist/clients/dispatch/facts/import-facts.js +5 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/actionlint.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +2 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/cpp-check.js +4 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/credo.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/cue-vet.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/dart-analyze.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/detekt.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/dotnet-build.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/elixir-check.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/eslint.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/fish-indent.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/gleam-check.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/go-vet.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/golangci-lint.js +2 -1
- 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 +3 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-render.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/htmlhint.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/javac.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ktlint.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +19 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +3 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/mypy.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/oxlint.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/php-lint.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/phpstan.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/prisma-validate.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/psscriptanalyzer.js +12 -12
- package/node_modules/pi-lens/dist/clients/dispatch/runners/pyright.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/rubocop.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ruff.js +2 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/rust-clippy.js +12 -11
- package/node_modules/pi-lens/dist/clients/dispatch/runners/shellcheck.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/shfmt.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/spellcheck.js +2 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/spotbugs.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/sqlfluff.js +3 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/stylelint.js +3 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/swiftlint.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 +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/tflint.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/trivy-config.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/availability-policy.js +5 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/candidate-probe.js +2 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +8 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/vale.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/yamllint.js +4 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/zig-check.js +2 -1
- package/node_modules/pi-lens/dist/clients/effective-config.js +12 -2
- package/node_modules/pi-lens/dist/clients/extension-log.js +2 -0
- package/node_modules/pi-lens/dist/clients/file-role.js +18 -1
- package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +4 -0
- package/node_modules/pi-lens/dist/clients/formatters.js +54 -188
- package/node_modules/pi-lens/dist/clients/generation-guard.js +4 -0
- package/node_modules/pi-lens/dist/clients/gitleaks-client.js +42 -6
- package/node_modules/pi-lens/dist/clients/govulncheck-client.js +48 -7
- package/node_modules/pi-lens/dist/clients/installer/index.js +196 -52
- package/node_modules/pi-lens/dist/clients/jscpd-client.js +9 -1
- package/node_modules/pi-lens/dist/clients/knip-client.js +9 -2
- package/node_modules/pi-lens/dist/clients/language-profile.js +12 -2
- package/node_modules/pi-lens/dist/clients/latency-logger.js +2 -0
- package/node_modules/pi-lens/dist/clients/lens-config.js +4 -0
- package/node_modules/pi-lens/dist/clients/lsp/config.js +36 -7
- package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +24 -1
- package/node_modules/pi-lens/dist/clients/lsp/document-drift.js +78 -0
- package/node_modules/pi-lens/dist/clients/lsp/index.js +281 -45
- package/node_modules/pi-lens/dist/clients/lsp/server.js +62 -15
- package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +37 -4
- package/node_modules/pi-lens/dist/clients/mcp/analyze.js +3 -0
- package/node_modules/pi-lens/dist/clients/mcp/session.js +2 -0
- package/node_modules/pi-lens/dist/clients/opengrep-client.js +2 -0
- package/node_modules/pi-lens/dist/clients/package-manager.js +2 -1
- package/node_modules/pi-lens/dist/clients/php-cs-fixer-config.js +8 -3
- package/node_modules/pi-lens/dist/clients/pipeline.js +3 -2
- package/node_modules/pi-lens/dist/clients/project-diagnostics/fresh-fetch.js +38 -10
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/gitleaks.js +10 -9
- package/node_modules/pi-lens/dist/clients/project-lens-config.js +3 -0
- package/node_modules/pi-lens/dist/clients/read-guard-logger.js +2 -0
- package/node_modules/pi-lens/dist/clients/review-graph-logger.js +2 -0
- package/node_modules/pi-lens/dist/clients/ruff-client.js +18 -9
- package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +9 -0
- package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +5 -0
- package/node_modules/pi-lens/dist/clients/runtime-session.js +13 -4
- package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +4 -1
- package/node_modules/pi-lens/dist/clients/runtime-turn.js +48 -1
- package/node_modules/pi-lens/dist/clients/security-scan-client.js +2 -2
- package/node_modules/pi-lens/dist/clients/session-event-guard.js +69 -1
- package/node_modules/pi-lens/dist/clients/sg-runner.js +2 -1
- package/node_modules/pi-lens/dist/clients/situational-tool-telemetry.js +108 -0
- package/node_modules/pi-lens/dist/clients/test-runner-client.js +291 -76
- package/node_modules/pi-lens/dist/clients/tool-config.js +199 -0
- package/node_modules/pi-lens/dist/clients/tool-cwd.js +299 -0
- package/node_modules/pi-lens/dist/clients/tool-probe.js +53 -0
- package/node_modules/pi-lens/dist/clients/tool-set-policy.js +42 -0
- package/node_modules/pi-lens/dist/clients/trivy-client.js +9 -1
- package/node_modules/pi-lens/dist/clients/turn-context.js +52 -0
- package/node_modules/pi-lens/dist/clients/widget-state.js +4 -3
- package/node_modules/pi-lens/dist/index.js +21969 -20005
- package/node_modules/pi-lens/dist/mcp/analyze-cli.js +3 -2
- package/node_modules/pi-lens/dist/mcp/server.js +135 -159
- package/node_modules/pi-lens/dist/tools/activate-tools.js +10 -7
- package/node_modules/pi-lens/dist/tools/ast-grep-outline.js +2 -13
- package/node_modules/pi-lens/dist/tools/ast-grep-replace.js +8 -13
- package/node_modules/pi-lens/dist/tools/ast-grep-search.js +83 -39
- package/node_modules/pi-lens/dist/tools/effective-config.js +4 -3
- package/node_modules/pi-lens/dist/tools/lens-diagnostic-mark.js +1 -10
- package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +353 -85
- package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +21 -110
- package/node_modules/pi-lens/dist/tools/lsp-navigation.js +20 -44
- package/node_modules/pi-lens/dist/tools/module-report.js +5 -9
- package/node_modules/pi-lens/dist/tools/project-report.js +9 -17
- package/node_modules/pi-lens/dist/tools/render-compact.js +280 -1
- package/node_modules/pi-lens/dist/tools/symbol-search.js +2 -2
- package/node_modules/pi-lens/docs/agent-guide.md +3 -4
- package/node_modules/pi-lens/docs/agent-tools.md +46 -22
- package/node_modules/pi-lens/docs/configuration.md +9 -0
- package/node_modules/pi-lens/docs/environment-variables.md +0 -5
- package/node_modules/pi-lens/docs/features.md +5 -5
- package/node_modules/pi-lens/docs/globalconfig.md +11 -1
- package/node_modules/pi-lens/docs/mcp.md +13 -1
- package/node_modules/pi-lens/docs/pi-lens-fixer.md +71 -0
- package/node_modules/pi-lens/docs/pi-lens-investigator.md +15 -0
- package/node_modules/pi-lens/docs/pi-lens-monitor.md +88 -0
- package/node_modules/pi-lens/docs/pi-lens-reviewer.md +35 -0
- package/node_modules/pi-lens/docs/pi-lens-subagent.md +12 -4
- package/node_modules/pi-lens/docs/public-api-stability.md +1 -0
- package/node_modules/pi-lens/docs/real-harness.md +46 -0
- package/node_modules/pi-lens/docs/release-qa-baseline.md +5 -1
- package/node_modules/pi-lens/docs/servercapabilities.md +1 -6
- package/node_modules/pi-lens/docs/settings.md +37 -2
- package/node_modules/pi-lens/docs/tools_improvement2.md +4 -4
- package/node_modules/pi-lens/docs/tree-sitter_rules_catalog.md +1 -1
- package/node_modules/pi-lens/docs/usage.md +13 -3
- package/node_modules/pi-lens/package.json +10 -1
- package/node_modules/pi-lens/rules/tree-sitter-queries/typescript/sql-injection.yml +7 -3
- package/node_modules/pi-lens/skills/pi-lens-ast-grep/SKILL.md +8 -6
- package/node_modules/pi-lens/skills/pi-lens-lsp-navigation/SKILL.md +19 -9
- package/node_modules/pi-web-access/CHANGELOG.md +29 -0
- package/node_modules/pi-web-access/README.md +33 -22
- package/node_modules/pi-web-access/abortable.ts +17 -0
- package/node_modules/pi-web-access/crawl4ai.ts +204 -0
- package/node_modules/pi-web-access/credential-source.ts +1 -0
- package/node_modules/pi-web-access/curator-page.ts +20 -2
- package/node_modules/pi-web-access/curator-run.ts +44 -0
- package/node_modules/pi-web-access/curator-server.ts +3 -1
- package/node_modules/pi-web-access/duckduckgo.ts +1 -1
- package/node_modules/pi-web-access/extract.ts +57 -12
- package/node_modules/pi-web-access/fetch-params.ts +1 -1
- package/node_modules/pi-web-access/gemini-search.ts +9 -5
- package/node_modules/pi-web-access/index.ts +25 -18
- package/node_modules/pi-web-access/openai-search.ts +35 -13
- package/node_modules/pi-web-access/package.json +2 -2
- package/node_modules/pi-web-access/page-query.ts +5 -2
- package/node_modules/pi-web-access/query-rewrite.ts +5 -2
- package/node_modules/pi-web-access/serpapi.ts +220 -0
- package/node_modules/pi-web-access/ssrf-protection.ts +5 -1
- package/node_modules/pi-web-access/storage.ts +10 -0
- package/node_modules/pi-web-access/summary-review.ts +34 -21
- package/node_modules/pi-web-access/utils.ts +6 -4
- package/package.json +11 -5
- package/node_modules/pi-lens/dist/tools/ast-dump.js +0 -103
|
@@ -60,8 +60,9 @@ function formatReport(result, cwd) {
|
|
|
60
60
|
if (result.diagnostics.length > 30) {
|
|
61
61
|
lines.push(` … ${result.diagnostics.length - 30} more`);
|
|
62
62
|
}
|
|
63
|
-
if (result.lsp &&
|
|
64
|
-
|
|
63
|
+
if (result.lsp &&
|
|
64
|
+
(result.lsp.status === "skipped" || result.lsp.status === "deferred")) {
|
|
65
|
+
lines.push(" (LSP diagnostics were skipped or deferred — run pilens_analyze on the warm MCP server for type errors)");
|
|
65
66
|
}
|
|
66
67
|
return lines.join("\n");
|
|
67
68
|
}
|
|
@@ -22,15 +22,20 @@ import * as fs from "node:fs";
|
|
|
22
22
|
import * as net from "node:net";
|
|
23
23
|
import * as path from "node:path";
|
|
24
24
|
import { fileURLToPath } from "node:url";
|
|
25
|
+
import { finalizeToolResult, finalizeToolResultWithDelivery, renderToolText as toolText, stripResultDetails, } from "../tools/render-compact.js";
|
|
25
26
|
import { AstGrepClient } from "../clients/ast-grep-client.js";
|
|
26
27
|
import { CacheManager } from "../clients/cache-manager.js";
|
|
27
|
-
import { getDegradationSummary, renderDegradationLines, } from "../clients/degradation-ledger.js";
|
|
28
|
+
import { getDegradationSummary, recordDegradationOnce, renderDegradationLines, } from "../clients/degradation-ledger.js";
|
|
28
29
|
import { acknowledgeTurnEnd, analyzeFile, analyzeFileFresh, canRebuildPiLens, createMcpHost, createWarmIpcLineReader, createWarmIpcRequestQueue, diagnosticStats, effectiveConfig, ensureLspConfig, generatedSkipNotice, ipcPathForCwd, isEffectiveFileViewError, 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
30
|
import { createAstGrepReplaceTool } from "../tools/ast-grep-replace.js";
|
|
30
|
-
import { createAstGrepSearchTool } from "../tools/ast-grep-search.js";
|
|
31
|
+
import { astGrepDumpCompatibilityResult, createAstGrepSearchTool, } from "../tools/ast-grep-search.js";
|
|
31
32
|
import { createLensDiagnosticsTool } from "../tools/lens-diagnostics.js";
|
|
32
33
|
import { peekMcpSessionRuntime } from "../clients/mcp/session.js";
|
|
33
|
-
import {
|
|
34
|
+
import { loadPiLensGlobalConfig } from "../clients/lens-config.js";
|
|
35
|
+
import { loadPiLensProjectConfig } from "../clients/project-lens-config.js";
|
|
36
|
+
import { resolveLensToolEnabled, toolRegistryEntryForMcp, } from "../clients/tool-config.js";
|
|
37
|
+
import { endSituationalToolTelemetry, observeSituationalToolCall, startSituationalToolTelemetrySession, } from "../clients/situational-tool-telemetry.js";
|
|
38
|
+
import { flushExtensionLog } from "../clients/extension-log.js";
|
|
34
39
|
import { createLspNavigationTool } from "../tools/lsp-navigation.js";
|
|
35
40
|
import { shouldInitializeSessionRoot } from "../clients/lsp/session-roots.js";
|
|
36
41
|
import { computeBuildStamp, STALE_SERVED_BY_FRESH, STALE_WARN_ONLY, StalenessGate, stalenessCheckEnabled, } from "./build-staleness.js";
|
|
@@ -354,18 +359,6 @@ function sendResult(id, result) {
|
|
|
354
359
|
function sendError(id, code, message) {
|
|
355
360
|
send({ jsonrpc: "2.0", id, error: { code, message } });
|
|
356
361
|
}
|
|
357
|
-
/**
|
|
358
|
-
* A tool result: human-readable text first, full JSON appended for the agent.
|
|
359
|
-
* `compact` omits indentation (#512) — for token-efficient tools like
|
|
360
|
-
* module_report the ~30% saved on the wire is worth losing pretty-printing
|
|
361
|
-
* for a payload the agent parses, not reads formatted.
|
|
362
|
-
*/
|
|
363
|
-
function toolText(summary, structured, compact = false) {
|
|
364
|
-
const text = structured === undefined
|
|
365
|
-
? summary
|
|
366
|
-
: `${summary}\n\n\`\`\`json\n${JSON.stringify(structured, compact ? undefined : null, compact ? undefined : 2)}\n\`\`\``;
|
|
367
|
-
return { content: [{ type: "text", text }] };
|
|
368
|
-
}
|
|
369
362
|
// --- Graph-staleness signal (#536) -------------------------------------------
|
|
370
363
|
//
|
|
371
364
|
// Extends #514's honesty-warning shape from "missing node" (module_report's
|
|
@@ -417,12 +410,20 @@ const cacheManager = new CacheManager();
|
|
|
417
410
|
// nothing — a no-op dressed as a fix, not a real parity gap. The 4th arg is left
|
|
418
411
|
// at its default (`async () => {}`, already a no-op) rather than importing and
|
|
419
412
|
// wiring a flush with nothing to flush.
|
|
413
|
+
const isLensGuardEnabled = () => Boolean(createMcpHost(undefined, DEFAULT_CWD).getFlag("lens-guard"));
|
|
420
414
|
const lensDiagnosticsTool = createLensDiagnosticsTool(cacheManager, () => DEFAULT_CWD, undefined, undefined, undefined, undefined,
|
|
421
415
|
// #1413 surface parity: validate cached test-runner findings against the
|
|
422
416
|
// same session identity the in-process path uses. Resolved lazily — until
|
|
423
417
|
// an MCP session context exists there is no session to compare against and
|
|
424
418
|
// validation skips the check, which is the honest classification.
|
|
425
|
-
() => peekMcpSessionRuntime()
|
|
419
|
+
() => peekMcpSessionRuntime(),
|
|
420
|
+
// #2860: without this, the default `() => true` applies on the MCP
|
|
421
|
+
// surface and every confirmed-clean LSP probe unconditionally resyncs the
|
|
422
|
+
// commit-gate `turn-end-findings` record even when the project has
|
|
423
|
+
// `lens-guard` off — a config bypass on a durable cross-surface store.
|
|
424
|
+
// Matches index.ts:1656 and the two sibling readers
|
|
425
|
+
// (clients/runtime-tool-call.ts, clients/runtime-tool-result.ts).
|
|
426
|
+
() => isLensGuardEnabled());
|
|
426
427
|
const astGrepClient = new AstGrepClient();
|
|
427
428
|
const astGrepSearchTool = createAstGrepSearchTool(astGrepClient);
|
|
428
429
|
const astGrepReplaceTool = createAstGrepReplaceTool(astGrepClient);
|
|
@@ -434,7 +435,6 @@ const astGrepReplaceTool = createAstGrepReplaceTool(astGrepClient);
|
|
|
434
435
|
// Resolve lazily against the call's own `cwd` instead (config loads are
|
|
435
436
|
// mtime-cached, so this stays cheap).
|
|
436
437
|
const lspNavigationTool = createLspNavigationTool((name, cwd) => createMcpHost(undefined, cwd ?? DEFAULT_CWD).getFlag(name));
|
|
437
|
-
const lspDiagnosticsTool = createLspDiagnosticsTool();
|
|
438
438
|
// Wrapped pi tools already declare their params as typebox (which IS JSON
|
|
439
439
|
// Schema). Emit that directly as the MCP inputSchema (+ the MCP-only `cwd`)
|
|
440
440
|
// instead of hand-restating it — no drift between the tool and its schema.
|
|
@@ -455,10 +455,7 @@ function schemaWithCwd(parameters) {
|
|
|
455
455
|
const ALL_TOOLS = [
|
|
456
456
|
{
|
|
457
457
|
name: "pilens_analyze",
|
|
458
|
-
description: "Run pi-lens's per-edit dispatch pipeline
|
|
459
|
-
"rules) on a single file and return its diagnostics plus the latency " +
|
|
460
|
-
"record for that dispatch (same schema as latency.log). The core review " +
|
|
461
|
-
"probe: shows a change's real behavioral + perf impact on a real file.",
|
|
458
|
+
description: "Run pi-lens's per-edit dispatch pipeline on one file. Example: analyze `src/app.ts` after an edit.",
|
|
462
459
|
inputSchema: {
|
|
463
460
|
type: "object",
|
|
464
461
|
properties: {
|
|
@@ -485,15 +482,12 @@ const ALL_TOOLS = [
|
|
|
485
482
|
},
|
|
486
483
|
{
|
|
487
484
|
name: "pilens_diagnostics",
|
|
488
|
-
description:
|
|
489
|
-
"mode=delta (current turn, instant), mode=all (every dispatched file this " +
|
|
490
|
-
"session), mode=full (expensive project-wide active scan).",
|
|
485
|
+
description: lensDiagnosticsTool.description,
|
|
491
486
|
inputSchema: schemaWithCwd(lensDiagnosticsTool.parameters),
|
|
492
487
|
},
|
|
493
488
|
{
|
|
494
489
|
name: "pilens_latency",
|
|
495
|
-
description: "Return recent dispatch latency reports
|
|
496
|
-
"total duration + per-runner timings). The review-loop measurement surface.",
|
|
490
|
+
description: "Return recent dispatch latency reports. Example: limit results to 5.",
|
|
497
491
|
inputSchema: {
|
|
498
492
|
type: "object",
|
|
499
493
|
properties: {
|
|
@@ -510,18 +504,12 @@ const ALL_TOOLS = [
|
|
|
510
504
|
},
|
|
511
505
|
{
|
|
512
506
|
name: "pilens_rebuild",
|
|
513
|
-
description: "Rebuild pi-lens so
|
|
514
|
-
"the latest commit. Runs `npm run build` (in-place dev layout) or " +
|
|
515
|
-
"`npm run build:dist` (precompiled dist layout), matching how this server " +
|
|
516
|
-
"was launched. The missing link that makes the review loop honest: " +
|
|
517
|
-
"commit → pilens_rebuild → pilens_analyze mode=fresh.",
|
|
507
|
+
description: "Rebuild pi-lens so later fresh analyses use the latest commit. Example: rebuild after changing a tool.",
|
|
518
508
|
inputSchema: { type: "object", properties: {} },
|
|
519
509
|
},
|
|
520
510
|
{
|
|
521
511
|
name: "pilens_project_scan",
|
|
522
|
-
description: "
|
|
523
|
-
"returning structural/quality diagnostics. Complements pilens_diagnostics " +
|
|
524
|
-
"mode=full (which adds active LSP).",
|
|
512
|
+
description: "Scan project files for structural and quality diagnostics. Example: cap the scan with `maxFiles: 20`.",
|
|
525
513
|
inputSchema: {
|
|
526
514
|
type: "object",
|
|
527
515
|
properties: {
|
|
@@ -539,17 +527,7 @@ const ALL_TOOLS = [
|
|
|
539
527
|
},
|
|
540
528
|
{
|
|
541
529
|
name: "pilens_symbol_search",
|
|
542
|
-
description: "
|
|
543
|
-
"that demote tests/vendor and doc files). Answers 'which files are most " +
|
|
544
|
-
"relevant to <query>' by identifier — first step of the discovery funnel: " +
|
|
545
|
-
"symbol_search finds candidate files, pilens_module_report explains one, " +
|
|
546
|
-
"pilens_read_symbol reads a body. Complements grep (raw substrings) and " +
|
|
547
|
-
"LSP (exact symbols). Each hit's `startLine`/`endLine` mark its best-matching " +
|
|
548
|
-
"line (offset=startLine, limit=endLine-startLine+1 for a one-line peek) — " +
|
|
549
|
-
"use pilens_module_report on `file` for the real outline. Returns " +
|
|
550
|
-
"`available: false` with a retry hint if the index isn't built yet for this " +
|
|
551
|
-
"workspace (pilens_session_start builds it, or it self-builds in the background " +
|
|
552
|
-
"on first query).",
|
|
530
|
+
description: "Find relevant files by ranked identifier search. On a cold cache, project_report and symbol_search return available: false with a retry hint and start a non-blocking background build; module_report degrades to outline-only with cache freshness explicit. Example: search `authenticate user` before pilens_module_report.",
|
|
553
531
|
inputSchema: {
|
|
554
532
|
type: "object",
|
|
555
533
|
properties: {
|
|
@@ -577,23 +555,7 @@ const ALL_TOOLS = [
|
|
|
577
555
|
},
|
|
578
556
|
{
|
|
579
557
|
name: "pilens_module_report",
|
|
580
|
-
description: "
|
|
581
|
-
"substitute for reading the whole file. Returns each symbol's " +
|
|
582
|
-
"name/kind/signature/line-range (plus a first-line `doc` summary when a " +
|
|
583
|
-
"doc comment is attached), plus who-uses-this, risk flags, and ranked " +
|
|
584
|
-
"recommendedReads. To read a symbol's body: call pilens_read_symbol (or " +
|
|
585
|
-
"read) with offset=startLine, limit=endLine-startLine+1 on THIS report's " +
|
|
586
|
-
"`file` — those aren't repeated per symbol. Prefer this before a full " +
|
|
587
|
-
"read; then use pilens_read_symbol for the exact body. Single mode: " +
|
|
588
|
-
"tree-sitter outline + review-graph who-uses-this + inline executable " +
|
|
589
|
-
"extraction; degrades to outline-only when no cached graph is available " +
|
|
590
|
-
"(this path never calls LSP). `semantic.source` reports whether graph " +
|
|
591
|
-
"data was used. Pass `blastRadius: true` for the cross-file blast radius " +
|
|
592
|
-
"(transitive dependents as ranked file reads, read-only over the cached " +
|
|
593
|
-
"graph). Pass `callGraph: true` for bounded derived callers/callees; a " +
|
|
594
|
-
"cold or stale call-graph cache is reported explicitly, never as zero calls. " +
|
|
595
|
-
'`view: "compact"` returns a line-oriented text rendering ' +
|
|
596
|
-
"(cheapest option) instead of JSON. An outline shows shape, not bodies.",
|
|
558
|
+
description: "Return a navigable source-module outline with references and read handles. An outline shows shape, not bodies, and does not satisfy read-before-edit; `read_symbol` and `read_enclosing` return body text and record read coverage. On a cold cache, project_report and symbol_search return available: false with a retry hint and start a non-blocking background build; module_report degrades to outline-only with cache freshness explicit. Example: use pilens_module_report on `src/app.ts` before pilens_read_symbol.",
|
|
597
559
|
inputSchema: {
|
|
598
560
|
type: "object",
|
|
599
561
|
properties: {
|
|
@@ -637,24 +599,7 @@ const ALL_TOOLS = [
|
|
|
637
599
|
},
|
|
638
600
|
{
|
|
639
601
|
name: "pilens_project_report",
|
|
640
|
-
description: "
|
|
641
|
-
"project' before drilling into any one file. First step of a wider " +
|
|
642
|
-
"discovery funnel: pilens_project_report orients, pilens_module_report " +
|
|
643
|
-
"explains a file, pilens_read_symbol reads a body. Six capped, ranked " +
|
|
644
|
-
"sections: a trust header (graph freshness, file coverage, " +
|
|
645
|
-
"edge-resolution-quality mix), hubs (top fan-in files — the repo's " +
|
|
646
|
-
"contract surface), entry points (near-zero fan-in / high fan-out files " +
|
|
647
|
-
"— activation/CLI/mains), a directory-level subsystem map (import " +
|
|
648
|
-
"cycles + layering violations, e.g. a forbidden clients/ -> tools/ " +
|
|
649
|
-
"edge), risk hotspots (fan-in × max per-symbol cyclomatic complexity), " +
|
|
650
|
-
"and suspected dead weight (zero-importer files, shipped with a " +
|
|
651
|
-
"low-confidence disclaimer). Every file line carries a `suggestedNext` " +
|
|
652
|
-
"module_report call. No per-symbol detail and no prose summary — " +
|
|
653
|
-
"structural facts only. Read-only over the cached graph: returns " +
|
|
654
|
-
"`available: false` with a retry hint on a cold cache and kicks off a " +
|
|
655
|
-
'background build (never blocks this call). `view: "compact"` returns ' +
|
|
656
|
-
"a line-oriented text rendering instead of JSON. Pass `focus` to " +
|
|
657
|
-
"re-rank every section toward a task hint.",
|
|
602
|
+
description: "Orient in a project from its review graph. On a cold cache, project_report and symbol_search return available: false with a retry hint and start a non-blocking background build; module_report degrades to outline-only with cache freshness explicit. Example: use pilens_project_report before choosing a file.",
|
|
658
603
|
inputSchema: {
|
|
659
604
|
type: "object",
|
|
660
605
|
properties: {
|
|
@@ -677,15 +622,7 @@ const ALL_TOOLS = [
|
|
|
677
622
|
},
|
|
678
623
|
{
|
|
679
624
|
name: "pilens_read_symbol",
|
|
680
|
-
description: "Return
|
|
681
|
-
"(function/class/method/interface/type) in a file — a targeted, cheap " +
|
|
682
|
-
"alternative to reading the whole file. Pair with pilens_module_report: it " +
|
|
683
|
-
"finds the symbol, this shows its body. Includes an attached doc comment " +
|
|
684
|
-
"when one exists. Accepts a dotted `Class.method` name to resolve a " +
|
|
685
|
-
"member, falling back to a plain lookup when the qualifier doesn't " +
|
|
686
|
-
"resolve. A miss embeds the ~3 nearest symbol names in the file. When " +
|
|
687
|
-
"multiple same-file symbols share a name, the first is returned with an " +
|
|
688
|
-
"ambiguity note; pass `kind` to pick a specific one.",
|
|
625
|
+
description: "Return one symbol's verbatim source. An outline shows shape, not bodies, and does not satisfy read-before-edit; `read_symbol` and `read_enclosing` return body text and record read coverage. Example: use pilens_read_symbol after pilens_module_report identifies `parseConfig`.",
|
|
689
626
|
inputSchema: {
|
|
690
627
|
type: "object",
|
|
691
628
|
properties: {
|
|
@@ -705,12 +642,7 @@ const ALL_TOOLS = [
|
|
|
705
642
|
},
|
|
706
643
|
{
|
|
707
644
|
name: "pilens_read_enclosing",
|
|
708
|
-
description: "Return the
|
|
709
|
-
"enclosing a line in a file. Use after pilens_ast_grep_search, " +
|
|
710
|
-
"pilens_diagnostics, or pilens_lsp_navigation locations when you need " +
|
|
711
|
-
"exact body text without reading the whole file. Uses tree-sitter only — " +
|
|
712
|
-
"no LSP or graph build. MCP has no read-guard, so unlike the pi tool this " +
|
|
713
|
-
"does not record edit-coverage.",
|
|
645
|
+
description: "Return the smallest symbol or callback enclosing a line. An outline shows shape, not bodies, and does not satisfy read-before-edit; `read_symbol` and `read_enclosing` return body text and record read coverage. Example: use pilens_read_enclosing after a diagnostic points to line 42.",
|
|
714
646
|
inputSchema: {
|
|
715
647
|
type: "object",
|
|
716
648
|
properties: {
|
|
@@ -747,25 +679,12 @@ const ALL_TOOLS = [
|
|
|
747
679
|
},
|
|
748
680
|
{
|
|
749
681
|
name: "pilens_health",
|
|
750
|
-
description: "pi-lens runtime health for
|
|
751
|
-
"summary, session diagnostic counts, how many resolved config leaves each " +
|
|
752
|
-
"source tier decided, and the total CPU/RAM footprint attributable to " +
|
|
753
|
-
"pi-lens across every process it owns (host + LSP children) machine-wide, " +
|
|
754
|
-
"from the shared instance registry.",
|
|
682
|
+
description: "Return pi-lens runtime health for this server. Example: call it after a slow analysis.",
|
|
755
683
|
inputSchema: { type: "object", properties: {} },
|
|
756
684
|
},
|
|
757
685
|
{
|
|
758
686
|
name: "pilens_effective_config",
|
|
759
|
-
description: "
|
|
760
|
-
"decision: which file and source tier each setting came from, the trust " +
|
|
761
|
-
"decision that applied, and which config files contributed. Pass `file` " +
|
|
762
|
-
"to also get, for that path, its canonical language, EVERY LSP server " +
|
|
763
|
-
"with the reason it was selected or denied — including which tier's " +
|
|
764
|
-
"config denied it, which a nearer file cannot lift — and the lint/format " +
|
|
765
|
-
"runners that would dispatch. This is the answer to 'why is X running / " +
|
|
766
|
-
"why is X not running' without reading logs. Redacted by construction: " +
|
|
767
|
-
"it reports sources, never values — no environment values, no command " +
|
|
768
|
-
"arguments beyond the binary itself, and config paths are home-relative.",
|
|
687
|
+
description: "Explain resolved configuration and provenance. Response is redacted by construction: it contains no environment values, no command arguments beyond the binary, and home-relative paths; a tier-denied LSP decision cannot be lifted by a nearer config. Example: pass `file` to explain one selection.",
|
|
769
688
|
inputSchema: {
|
|
770
689
|
type: "object",
|
|
771
690
|
properties: {
|
|
@@ -783,12 +702,7 @@ const ALL_TOOLS = [
|
|
|
783
702
|
},
|
|
784
703
|
{
|
|
785
704
|
name: "pilens_session_start",
|
|
786
|
-
description: "
|
|
787
|
-
"LSP (so subsequent pilens_analyze is LSP-complete), establish the " +
|
|
788
|
-
"error-debt baseline (tests/build pass-state) + complexity baselines, and " +
|
|
789
|
-
"kick off knip/jscpd/type-coverage/dep/secrets project scans. Returns " +
|
|
790
|
-
"project guidance + baseline; scan results land in caches (query via " +
|
|
791
|
-
"pilens_diagnostics afterwards). Run once per workspace before reviewing.",
|
|
705
|
+
description: "Initialize pi-lens for a workspace. Example: run once before reviewing a project.",
|
|
792
706
|
inputSchema: {
|
|
793
707
|
type: "object",
|
|
794
708
|
properties: { cwd: { type: "string" } },
|
|
@@ -796,13 +710,7 @@ const ALL_TOOLS = [
|
|
|
796
710
|
},
|
|
797
711
|
{
|
|
798
712
|
name: "pilens_turn_end",
|
|
799
|
-
description: "
|
|
800
|
-
"knip dead-code + jscpd duplication (incremental), circular-dep checks, " +
|
|
801
|
-
"tests on affected targets, cascade to dependents, and the actionable/" +
|
|
802
|
-
"code-quality warning aggregation. Returns the turn-end advisory + test " +
|
|
803
|
-
"findings. `files` is OPTIONAL — pilens_analyze (and the PostToolUse hook) " +
|
|
804
|
-
"auto-register edited files into turn-state, so you can call this with no " +
|
|
805
|
-
"args after a series of edits; pass `files` to add any not analyzed.",
|
|
713
|
+
description: "Summarize checks for files changed this turn. Example: pass `files` for an unanalysed file.",
|
|
806
714
|
inputSchema: {
|
|
807
715
|
type: "object",
|
|
808
716
|
properties: {
|
|
@@ -815,39 +723,29 @@ const ALL_TOOLS = [
|
|
|
815
723
|
},
|
|
816
724
|
},
|
|
817
725
|
},
|
|
726
|
+
{
|
|
727
|
+
name: "pilens_session_end",
|
|
728
|
+
description: "End the MCP connection's telemetry session and write its bounded situational-tool telemetry line. This is terminal for the connection.",
|
|
729
|
+
inputSchema: {
|
|
730
|
+
type: "object",
|
|
731
|
+
properties: {},
|
|
732
|
+
},
|
|
733
|
+
},
|
|
818
734
|
{
|
|
819
735
|
name: "pilens_ast_grep_search",
|
|
820
|
-
description: "
|
|
821
|
-
"text. Use complete patterns with arguments (e.g. 'console.log($MSG)', " +
|
|
822
|
-
"'function $NAME($$$ARGS) { $$$BODY }'), or use nodeKind to find every " +
|
|
823
|
-
"node of a known grammar kind. Metavariables do not match text inside " +
|
|
824
|
-
"quoted string literals; use an exact string or grep for wildcard text. " +
|
|
825
|
-
"This is the same schema and synthesis path as the pi tool.",
|
|
736
|
+
description: "Search code by AST structure rather than text. Example: find calls with `console.log($MSG)`.",
|
|
826
737
|
inputSchema: schemaWithCwd(astGrepSearchTool.parameters),
|
|
827
738
|
},
|
|
828
739
|
{
|
|
829
740
|
name: "pilens_ast_grep_replace",
|
|
830
|
-
description: "
|
|
831
|
-
"rewrite='let $X'. DRY-RUN by default (apply=false shows the diff); set " +
|
|
832
|
-
"apply=true to write the changes to disk.",
|
|
741
|
+
description: "Find and rewrite code by AST structure; preview by default. Example: set `apply: false` to inspect a diff.",
|
|
833
742
|
inputSchema: schemaWithCwd(astGrepReplaceTool.parameters),
|
|
834
743
|
},
|
|
835
744
|
{
|
|
836
745
|
name: "pilens_lsp_navigation",
|
|
837
|
-
description:
|
|
838
|
-
"references, hover, documentSymbol, " +
|
|
839
|
-
"workspaceSymbol, implementation, call hierarchy (prepareCallHierarchy/" +
|
|
840
|
-
"incomingCalls/outgoingCalls), rename, codeAction, executeCommand " +
|
|
841
|
-
"(allowlisted, dry-run by default) — exact + type-aware, " +
|
|
842
|
-
"~50ms. Use before changing a signature to see every caller.",
|
|
746
|
+
description: 'Navigate source with language-server operations. Example: use `{operation: "references", path: "src/app.ts", line: 12}`.',
|
|
843
747
|
inputSchema: schemaWithCwd(lspNavigationTool.parameters),
|
|
844
748
|
},
|
|
845
|
-
{
|
|
846
|
-
name: "pilens_lsp_diagnostics",
|
|
847
|
-
description: "Pure LSP diagnostics for a file, directory, or batch of files (type " +
|
|
848
|
-
"errors only — narrower than pilens_diagnostics, which spans all runners).",
|
|
849
|
-
inputSchema: schemaWithCwd(lspDiagnosticsTool.parameters),
|
|
850
|
-
},
|
|
851
749
|
];
|
|
852
750
|
// #920: published packages cannot rebuild themselves safely because their
|
|
853
751
|
// build config is intentionally not shipped. Do not advertise the destructive
|
|
@@ -855,6 +753,15 @@ const ALL_TOOLS = [
|
|
|
855
753
|
const TOOLS = canRebuildPiLens(REPO_ROOT)
|
|
856
754
|
? ALL_TOOLS
|
|
857
755
|
: ALL_TOOLS.filter((tool) => tool.name !== "pilens_rebuild");
|
|
756
|
+
function enabledToolsForCwd(cwd) {
|
|
757
|
+
const global = loadPiLensGlobalConfig();
|
|
758
|
+
const project = loadPiLensProjectConfig(cwd);
|
|
759
|
+
return TOOLS.filter((tool) => {
|
|
760
|
+
const entry = toolRegistryEntryForMcp(tool.name);
|
|
761
|
+
return (entry !== undefined &&
|
|
762
|
+
resolveLensToolEnabled(entry.name, global, project.raw));
|
|
763
|
+
});
|
|
764
|
+
}
|
|
858
765
|
function formatAnalyze(result, cwd, mode, servedBy) {
|
|
859
766
|
// Surface the LSP outcome so a cold/indexing server's "0" is never silently
|
|
860
767
|
// read as "clean" — a known limit on large projects (warm mode / re-run once
|
|
@@ -920,6 +827,38 @@ function effectiveDocumentLine(document) {
|
|
|
920
827
|
return ` ${document.tier}: ${document.file}${legacy}`;
|
|
921
828
|
}
|
|
922
829
|
async function callTool(name, args) {
|
|
830
|
+
if (name === "pilens_lsp_diagnostics") {
|
|
831
|
+
recordDegradationOnce({
|
|
832
|
+
kind: "lsp-diagnostics-compatibility",
|
|
833
|
+
subject: "lsp_diagnostics",
|
|
834
|
+
reason: "retired tool name redirected to pilens_diagnostics source=lsp",
|
|
835
|
+
});
|
|
836
|
+
name = "pilens_diagnostics";
|
|
837
|
+
args = {
|
|
838
|
+
...args,
|
|
839
|
+
source: "lsp",
|
|
840
|
+
// #2860: the retired tool's contract was always "path or paths is
|
|
841
|
+
// required" (tools/lsp-diagnostics.ts's own early return) — it never
|
|
842
|
+
// had a bare "sweep the whole workspace" mode. `scope: "paths"` is a
|
|
843
|
+
// no-op for source=lsp (lens-diagnostics.ts only special-cases
|
|
844
|
+
// scope==="workspace"), so whatever `path`/`paths` the caller sent
|
|
845
|
+
// (or didn't) passes straight through to the probe's own path/paths
|
|
846
|
+
// handling unchanged, reproducing master's behavior exactly —
|
|
847
|
+
// including its error when neither is present. Mapping absent
|
|
848
|
+
// `paths` to `scope:"workspace"` here previously caused every
|
|
849
|
+
// no-args call to substitute `cwd` and run a whole-project LSP sweep
|
|
850
|
+
// instead (root-eviction smoke: 129 sweeps, 180s timeout x3).
|
|
851
|
+
scope: "paths",
|
|
852
|
+
};
|
|
853
|
+
}
|
|
854
|
+
if (name === "pilens_ast_grep_dump") {
|
|
855
|
+
recordDegradationOnce({
|
|
856
|
+
kind: "ast-grep-dump-compatibility",
|
|
857
|
+
subject: "ast_grep_dump",
|
|
858
|
+
reason: "retired tool name redirected to ast_grep_search dump mode",
|
|
859
|
+
});
|
|
860
|
+
return astGrepDumpCompatibilityResult(args, "mcp");
|
|
861
|
+
}
|
|
923
862
|
if (name === "pilens_analyze") {
|
|
924
863
|
const file = args.file;
|
|
925
864
|
if (typeof file !== "string" || file.length === 0) {
|
|
@@ -1254,7 +1193,10 @@ async function callTool(name, args) {
|
|
|
1254
1193
|
const header = `${result.kind} ${result.name}${ambiguityNote}${sigSuffix} ${path.relative(cwd, result.path)}:${result.startLine}-${result.endLine}`;
|
|
1255
1194
|
return {
|
|
1256
1195
|
content: [
|
|
1257
|
-
{
|
|
1196
|
+
{
|
|
1197
|
+
type: "text",
|
|
1198
|
+
text: `${header}\n\n${result.source ?? ""}`,
|
|
1199
|
+
},
|
|
1258
1200
|
],
|
|
1259
1201
|
};
|
|
1260
1202
|
}
|
|
@@ -1311,7 +1253,10 @@ async function callTool(name, args) {
|
|
|
1311
1253
|
const header = `${result.kind} ${result.name} ${path.relative(cwd, result.path)}:${range}`;
|
|
1312
1254
|
return {
|
|
1313
1255
|
content: [
|
|
1314
|
-
{
|
|
1256
|
+
{
|
|
1257
|
+
type: "text",
|
|
1258
|
+
text: `${header}\n\n${result.source ?? ""}`,
|
|
1259
|
+
},
|
|
1315
1260
|
],
|
|
1316
1261
|
};
|
|
1317
1262
|
}
|
|
@@ -1431,7 +1376,7 @@ async function callTool(name, args) {
|
|
|
1431
1376
|
const cwd = typeof args.cwd === "string" ? args.cwd : DEFAULT_CWD;
|
|
1432
1377
|
await ensureReady(cwd);
|
|
1433
1378
|
const out = (await lensDiagnosticsTool.execute("mcp", args, new AbortController().signal, undefined, { cwd }));
|
|
1434
|
-
return
|
|
1379
|
+
return out;
|
|
1435
1380
|
}
|
|
1436
1381
|
if (name === "pilens_latency") {
|
|
1437
1382
|
const limit = typeof args.limit === "number" && Number.isFinite(args.limit)
|
|
@@ -1462,6 +1407,10 @@ async function callTool(name, args) {
|
|
|
1462
1407
|
];
|
|
1463
1408
|
return toolText(lines.filter(Boolean).join("\n"), outcome);
|
|
1464
1409
|
}
|
|
1410
|
+
if (name === "pilens_session_end") {
|
|
1411
|
+
endSituationalToolTelemetry();
|
|
1412
|
+
return toolText("Session ended.");
|
|
1413
|
+
}
|
|
1465
1414
|
if (name === "pilens_turn_end") {
|
|
1466
1415
|
const cwd = typeof args.cwd === "string" ? args.cwd : DEFAULT_CWD;
|
|
1467
1416
|
await ensureReady(cwd);
|
|
@@ -1481,15 +1430,15 @@ async function callTool(name, args) {
|
|
|
1481
1430
|
const tool = name === "pilens_ast_grep_search"
|
|
1482
1431
|
? astGrepSearchTool
|
|
1483
1432
|
: astGrepReplaceTool;
|
|
1484
|
-
const out = (await tool.execute("mcp", args, new AbortController().signal, undefined, { cwd }));
|
|
1485
|
-
return
|
|
1433
|
+
const out = (await tool.execute("mcp", args, new AbortController().signal, undefined, { cwd, resultMaxItems: Number.POSITIVE_INFINITY }));
|
|
1434
|
+
return out;
|
|
1486
1435
|
}
|
|
1487
|
-
if (name === "pilens_lsp_navigation"
|
|
1436
|
+
if (name === "pilens_lsp_navigation") {
|
|
1488
1437
|
const cwd = typeof args.cwd === "string" ? args.cwd : DEFAULT_CWD;
|
|
1489
1438
|
await ensureReady(cwd);
|
|
1490
|
-
const tool =
|
|
1439
|
+
const tool = lspNavigationTool;
|
|
1491
1440
|
const out = (await tool.execute("mcp", args, new AbortController().signal, undefined, { cwd }));
|
|
1492
|
-
return
|
|
1441
|
+
return out;
|
|
1493
1442
|
}
|
|
1494
1443
|
return { ...toolText(`Unknown tool: ${name}`), isError: true };
|
|
1495
1444
|
}
|
|
@@ -1520,7 +1469,7 @@ async function callTool(name, args) {
|
|
|
1520
1469
|
// pilens_session_start, pilens_turn_end — mutate warm LSP/graph state;
|
|
1521
1470
|
// must run in-process, can't be forked fresh.
|
|
1522
1471
|
// pilens_ast_grep_search, pilens_ast_grep_replace,
|
|
1523
|
-
// pilens_lsp_navigation,
|
|
1472
|
+
// pilens_lsp_navigation, pilens_diagnostics — depend on the warm LSP
|
|
1524
1473
|
// fleet / ast-grep client instances; no fresh-fork machinery exists for
|
|
1525
1474
|
// them today (only pilens_analyze's worker.ts loads a fresh dispatch
|
|
1526
1475
|
// graph) and the LSP fleet specifically CANNOT be recreated cheaply per
|
|
@@ -1549,7 +1498,6 @@ const WARN_ONLY_STALE_TOOLS = new Set([
|
|
|
1549
1498
|
"pilens_ast_grep_search",
|
|
1550
1499
|
"pilens_ast_grep_replace",
|
|
1551
1500
|
"pilens_lsp_navigation",
|
|
1552
|
-
"pilens_lsp_diagnostics",
|
|
1553
1501
|
"pilens_read_symbol",
|
|
1554
1502
|
"pilens_read_enclosing",
|
|
1555
1503
|
"pilens_effective_config",
|
|
@@ -1582,6 +1530,7 @@ async function handleRequest(request) {
|
|
|
1582
1530
|
const isNotification = id === undefined;
|
|
1583
1531
|
switch (method) {
|
|
1584
1532
|
case "initialize": {
|
|
1533
|
+
startSituationalToolTelemetrySession("mcp");
|
|
1585
1534
|
const requested = params?.protocolVersion;
|
|
1586
1535
|
sendResult(id ?? null, {
|
|
1587
1536
|
protocolVersion: typeof requested === "string" ? requested : FALLBACK_PROTOCOL_VERSION,
|
|
@@ -1599,7 +1548,7 @@ async function handleRequest(request) {
|
|
|
1599
1548
|
sendResult(id ?? null, {});
|
|
1600
1549
|
return;
|
|
1601
1550
|
case "tools/list":
|
|
1602
|
-
sendResult(id ?? null, { tools:
|
|
1551
|
+
sendResult(id ?? null, { tools: enabledToolsForCwd(DEFAULT_CWD) });
|
|
1603
1552
|
return;
|
|
1604
1553
|
case "tools/call": {
|
|
1605
1554
|
const name = params?.name;
|
|
@@ -1610,6 +1559,21 @@ async function handleRequest(request) {
|
|
|
1610
1559
|
sendError(id ?? null, -32602, "tools/call requires a string 'name'");
|
|
1611
1560
|
return;
|
|
1612
1561
|
}
|
|
1562
|
+
const enabledName = name === "pilens_lsp_diagnostics" ? "pilens_diagnostics" : name;
|
|
1563
|
+
if (name !== "pilens_ast_grep_dump" &&
|
|
1564
|
+
name !== "pilens_rebuild" &&
|
|
1565
|
+
!enabledToolsForCwd(typeof args.cwd === "string" ? args.cwd : DEFAULT_CWD).some((tool) => tool.name === enabledName)) {
|
|
1566
|
+
sendResult(id ?? null, stripResultDetails(finalizeToolResult({
|
|
1567
|
+
...toolText(`Unknown or disabled tool: ${name}`),
|
|
1568
|
+
isError: true,
|
|
1569
|
+
})));
|
|
1570
|
+
return;
|
|
1571
|
+
}
|
|
1572
|
+
const entry = toolRegistryEntryForMcp(name);
|
|
1573
|
+
if (entry && "situational" in entry && entry.situational) {
|
|
1574
|
+
startSituationalToolTelemetrySession("mcp");
|
|
1575
|
+
observeSituationalToolCall(entry.name);
|
|
1576
|
+
}
|
|
1613
1577
|
// #544 self-heal: if auto-session was supposed to fire on `initialize`
|
|
1614
1578
|
// (PI_LENS_MCP_AUTO_SESSION=1) but never completed successfully — never
|
|
1615
1579
|
// attempted, still in flight, or threw — nudge it here too. Cheap no-op
|
|
@@ -1623,20 +1587,29 @@ async function handleRequest(request) {
|
|
|
1623
1587
|
// see the forcedFresh branch inside callTool. Every other tool that
|
|
1624
1588
|
// depends on warm-only process state gets an honest-degrade warning
|
|
1625
1589
|
// instead, so the warm boundary never silently serves old code.
|
|
1590
|
+
// The warning precedes the #2800 item 7 gate, so it is part of the
|
|
1591
|
+
// payload the byte bound protects (kept in the retained tail) and
|
|
1592
|
+
// its bytes land in the footer's delivered figure.
|
|
1626
1593
|
if (WARN_ONLY_STALE_TOOLS.has(name) &&
|
|
1627
1594
|
!result.isError &&
|
|
1628
1595
|
isWarmBuildStale()) {
|
|
1629
1596
|
result = withStaleWarning(result);
|
|
1630
1597
|
}
|
|
1631
|
-
|
|
1598
|
+
// #2800 item 7: the payload bound runs first with the footer's own
|
|
1599
|
+
// size reserved, then the footer is stamped with the delivered
|
|
1600
|
+
// payload's byte count and the bound's truncated flag.
|
|
1601
|
+
const delivery = finalizeToolResultWithDelivery(result);
|
|
1602
|
+
// The gate consumed `details` for the footer's diag lines above;
|
|
1603
|
+
// strip it so the wire carries only the bounded text (#2852 N1).
|
|
1604
|
+
sendResult(id ?? null, stripResultDetails(delivery.result));
|
|
1632
1605
|
}
|
|
1633
1606
|
catch (err) {
|
|
1634
1607
|
// Surface as a tool error (isError), not a transport error, so the
|
|
1635
1608
|
// agent sees the message instead of a dead request.
|
|
1636
|
-
sendResult(id ?? null, {
|
|
1609
|
+
sendResult(id ?? null, stripResultDetails(finalizeToolResult({
|
|
1637
1610
|
...toolText(`pi-lens tool '${name}' failed: ${err.message}`),
|
|
1638
1611
|
isError: true,
|
|
1639
|
-
});
|
|
1612
|
+
})));
|
|
1640
1613
|
}
|
|
1641
1614
|
return;
|
|
1642
1615
|
}
|
|
@@ -1669,6 +1642,9 @@ process.stdin.on("data", (chunk) => {
|
|
|
1669
1642
|
newlineIndex = buffer.indexOf("\n");
|
|
1670
1643
|
}
|
|
1671
1644
|
});
|
|
1672
|
-
process.stdin.on("end", () =>
|
|
1645
|
+
process.stdin.on("end", () => {
|
|
1646
|
+
endSituationalToolTelemetry();
|
|
1647
|
+
void flushExtensionLog().finally(() => process.exit(0));
|
|
1648
|
+
});
|
|
1673
1649
|
startIpcServer();
|
|
1674
1650
|
console.error(`[pi-lens-mcp] ready (cwd=${DEFAULT_CWD})`);
|
|
@@ -21,24 +21,27 @@ import { Type } from "../clients/deps/typebox.js";
|
|
|
21
21
|
export function createActivateToolsTool(pi, lazyTools, options = {}) {
|
|
22
22
|
const lazyNames = lazyTools.map((t) => t.name);
|
|
23
23
|
const lazyNameSet = new Set(lazyNames);
|
|
24
|
-
const catalog = lazyTools.map((t) => `${t.name} — ${t.summary}`).join("\n");
|
|
25
24
|
return {
|
|
26
25
|
name: "pi_lens_activate_tools",
|
|
27
26
|
label: "Activate pi-lens Tools",
|
|
28
|
-
description:
|
|
29
|
-
|
|
30
|
-
`Available:\n${catalog}`,
|
|
31
|
-
promptSnippet: "Activate situational ast-grep / lsp_navigation tools before using them",
|
|
27
|
+
description: 'Activate registered situational tools for the next turn. Example: `{tools: ["lsp_navigation"]}`.',
|
|
28
|
+
promptSnippet: "Activate a situational tool",
|
|
32
29
|
parameters: Type.Object({
|
|
33
30
|
tools: Type.Array(Type.String({ enum: lazyNames }), {
|
|
34
31
|
minItems: 1,
|
|
35
|
-
description: "Names of situational tools to activate
|
|
32
|
+
description: "Names of situational tools to activate, e.g. `lsp_navigation`.",
|
|
36
33
|
}),
|
|
37
34
|
}),
|
|
38
35
|
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
39
36
|
const requested = Array.isArray(params.tools)
|
|
40
37
|
? params.tools.filter((t) => typeof t === "string" && lazyNameSet.has(t))
|
|
41
38
|
: [];
|
|
39
|
+
if (Array.isArray(params.tools)) {
|
|
40
|
+
for (const name of params.tools) {
|
|
41
|
+
if (typeof name === "string" && !lazyNameSet.has(name))
|
|
42
|
+
options.onRejected?.(name);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
42
45
|
if (requested.length === 0) {
|
|
43
46
|
return {
|
|
44
47
|
content: [
|
|
@@ -56,7 +59,7 @@ export function createActivateToolsTool(pi, lazyTools, options = {}) {
|
|
|
56
59
|
// Remember every requested tool, not just the newly-added ones: a
|
|
57
60
|
// tool that is already active still has to survive the next
|
|
58
61
|
// fork/reload/resume restore.
|
|
59
|
-
options.onActivated?.(requested);
|
|
62
|
+
options.onActivated?.(requested, ctx);
|
|
60
63
|
const active = typeof pi.getActiveTools === "function" ? pi.getActiveTools() : [];
|
|
61
64
|
const activeSet = new Set(active);
|
|
62
65
|
const added = requested.filter((name) => !activeSet.has(name));
|
|
@@ -29,19 +29,8 @@ export function createAstGrepOutlineTool(astGrepClient) {
|
|
|
29
29
|
return {
|
|
30
30
|
name: "ast_grep_outline",
|
|
31
31
|
label: "AST-Grep Outline",
|
|
32
|
-
description: "
|
|
33
|
-
|
|
34
|
-
"for languages or structures where pi-lens's own extractor is weak, or for a " +
|
|
35
|
-
"raw second opinion.\n\n" +
|
|
36
|
-
"Prefer module_report for pi-lens-aware navigation (who-uses-this, " +
|
|
37
|
-
"complexity/fanout, recommendedReads, blast radius, callback handles). Use " +
|
|
38
|
-
"ast_grep_outline when you want the syntax tree's own view of a file or a " +
|
|
39
|
-
"whole directory.\n\n" +
|
|
40
|
-
"Returns JSON: per file, `items[]` with name/symbolType/signature/range, " +
|
|
41
|
-
"`isExported`/`isImport`, nested `members[]` (with `isPublic`), and ready " +
|
|
42
|
-
"`read` args on every entry. NOTE: structure only — an outline is NOT a read " +
|
|
43
|
-
"of a symbol's body (use read_symbol/read_enclosing for that).",
|
|
44
|
-
promptSnippet: "Syntax-only code outline via ast-grep (no index/LSP); module_report is the richer default",
|
|
32
|
+
description: "Return syntax-only symbols, imports, exports, and members with ast-grep. An outline shows structure, not a symbol body, and does not satisfy read-before-edit; use read_symbol or read_enclosing for body coverage. Example: outline `src/` before choosing a symbol to read.",
|
|
33
|
+
promptSnippet: "Inspect syntax without index or LSP",
|
|
45
34
|
renderResult: compactRenderResult(({ details, isError, text }) => {
|
|
46
35
|
if (isError) {
|
|
47
36
|
return `ast_grep_outline — ${text.split("\n")[0] ?? "error"}`;
|