pi-lens 4.1.5 → 4.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +415 -0
- package/README.md +13 -8
- package/config/dependency-cruiser-eager-allowlist.json +6 -1
- package/dist/clients/actionable-warnings.js +30 -4
- package/dist/clients/agent-behavior-client.js +2 -0
- package/dist/clients/analysed-root.js +1 -0
- package/dist/clients/ast-grep-tool-logger.js +1 -1
- package/dist/clients/bash-file-access.js +26 -0
- package/dist/clients/biome-client.js +13 -2
- package/dist/clients/blocker-freshness.js +403 -35
- package/dist/clients/bootstrap.js +6 -1
- package/dist/clients/bounded-telemetry.js +2 -0
- package/dist/clients/cache-observability.js +122 -1
- package/dist/clients/cascade-format.js +200 -4
- package/dist/clients/code-quality-warnings.js +10 -2
- package/dist/clients/complexity-client.js +5 -0
- package/dist/clients/config-diagnostic-codes.js +2 -0
- package/dist/clients/config-resolve.js +6 -3
- package/dist/clients/config-schema.js +17 -0
- package/dist/clients/config-warn.js +2 -2
- package/dist/clients/dead-code-client.js +8 -1
- package/dist/clients/degradation-ledger.js +16 -1
- package/dist/clients/dependency-checker.js +5 -1
- package/dist/clients/diagnostic-dispositions.js +12 -1
- package/dist/clients/dispatch/ast-grep-catalog.js +65 -0
- package/dist/clients/dispatch/auxiliary-lsp.js +28 -0
- package/dist/clients/dispatch/dispatcher.js +47 -17
- package/dist/clients/dispatch/facts/function-facts.js +1 -1
- package/dist/clients/dispatch/facts/import-facts.js +5 -1
- package/dist/clients/dispatch/finding-policy.js +222 -0
- package/dist/clients/dispatch/indent-detect.js +389 -13
- package/dist/clients/dispatch/integration.js +175 -25
- package/dist/clients/dispatch/rule-ignores.js +62 -0
- package/dist/clients/dispatch/runners/actionlint.js +2 -1
- package/dist/clients/dispatch/runners/ast-grep-napi.js +21 -41
- package/dist/clients/dispatch/runners/biome-check.js +8 -4
- package/dist/clients/dispatch/runners/cpp-check.js +4 -3
- package/dist/clients/dispatch/runners/credo.js +2 -1
- package/dist/clients/dispatch/runners/cue-vet.js +2 -1
- package/dist/clients/dispatch/runners/dart-analyze.js +2 -1
- package/dist/clients/dispatch/runners/detekt.js +2 -1
- package/dist/clients/dispatch/runners/dotnet-build.js +2 -1
- package/dist/clients/dispatch/runners/elixir-check.js +2 -1
- package/dist/clients/dispatch/runners/eslint.js +2 -1
- package/dist/clients/dispatch/runners/fish-indent.js +2 -1
- package/dist/clients/dispatch/runners/gleam-check.js +2 -1
- package/dist/clients/dispatch/runners/go-vet.js +2 -1
- package/dist/clients/dispatch/runners/golangci-lint.js +2 -1
- package/dist/clients/dispatch/runners/hadolint.js +2 -1
- package/dist/clients/dispatch/runners/helm-lint.js +3 -1
- package/dist/clients/dispatch/runners/helm-render.js +2 -1
- package/dist/clients/dispatch/runners/htmlhint.js +2 -1
- package/dist/clients/dispatch/runners/javac.js +2 -1
- package/dist/clients/dispatch/runners/ktlint.js +2 -1
- package/dist/clients/dispatch/runners/lsp.js +19 -1
- package/dist/clients/dispatch/runners/markdownlint.js +3 -2
- package/dist/clients/dispatch/runners/mypy.js +2 -1
- package/dist/clients/dispatch/runners/oxlint.js +2 -1
- package/dist/clients/dispatch/runners/php-lint.js +2 -1
- package/dist/clients/dispatch/runners/phpstan.js +2 -1
- package/dist/clients/dispatch/runners/prisma-validate.js +2 -1
- package/dist/clients/dispatch/runners/psscriptanalyzer.js +12 -12
- package/dist/clients/dispatch/runners/pyright.js +2 -1
- package/dist/clients/dispatch/runners/rubocop.js +2 -1
- package/dist/clients/dispatch/runners/ruff.js +2 -2
- package/dist/clients/dispatch/runners/rust-clippy.js +12 -11
- package/dist/clients/dispatch/runners/shellcheck.js +2 -1
- package/dist/clients/dispatch/runners/shfmt.js +4 -13
- package/dist/clients/dispatch/runners/spellcheck.js +2 -2
- package/dist/clients/dispatch/runners/spotbugs.js +2 -1
- package/dist/clients/dispatch/runners/sqlfluff.js +3 -2
- package/dist/clients/dispatch/runners/stylelint.js +3 -2
- package/dist/clients/dispatch/runners/swiftlint.js +2 -1
- package/dist/clients/dispatch/runners/taplo.js +2 -1
- package/dist/clients/dispatch/runners/terragrunt.js +2 -1
- package/dist/clients/dispatch/runners/tflint.js +2 -1
- package/dist/clients/dispatch/runners/tree-sitter.js +2 -21
- package/dist/clients/dispatch/runners/trivy-config.js +2 -1
- package/dist/clients/dispatch/runners/utils/availability-policy.js +5 -0
- package/dist/clients/dispatch/runners/utils/candidate-probe.js +2 -2
- package/dist/clients/dispatch/runners/utils/runner-helpers.js +8 -2
- package/dist/clients/dispatch/runners/vale.js +2 -1
- package/dist/clients/dispatch/runners/yamllint.js +4 -3
- package/dist/clients/dispatch/runners/zig-check.js +2 -1
- package/dist/clients/dispatch/types.js +4 -1
- package/dist/clients/disposition-publish.js +1 -0
- package/dist/clients/effective-config.js +12 -2
- package/dist/clients/extension-log.js +2 -0
- package/dist/clients/file-kinds.js +26 -1
- package/dist/clients/file-role.js +23 -6
- package/dist/clients/file-utils.js +156 -10
- package/dist/clients/finding-delivery-gate.js +60 -9
- package/dist/clients/format-service.js +39 -21
- package/dist/clients/formatters.js +113 -200
- package/dist/clients/generation-guard.js +6 -2
- package/dist/clients/git-guard.js +11 -3
- package/dist/clients/gitleaks-client.js +42 -6
- package/dist/clients/govulncheck-client.js +48 -7
- package/dist/clients/indent-retarget.js +78 -8
- package/dist/clients/installer/index.js +524 -161
- package/dist/clients/instance-reaper-state.js +7 -0
- package/dist/clients/instance-reaper.js +20 -10
- package/dist/clients/jscpd-client.js +9 -1
- package/dist/clients/knip-client.js +9 -2
- package/dist/clients/language-profile.js +35 -3
- package/dist/clients/language-registry.js +5 -1
- package/dist/clients/latency-logger.js +6 -1
- package/dist/clients/lens-config.js +4 -0
- package/dist/clients/lens-engine.js +12 -3
- package/dist/clients/lens-events.js +2 -1
- package/dist/clients/lens-flag-registry.js +79 -0
- package/dist/clients/live-bus-emitter.js +2 -1
- package/dist/clients/lsp/client.js +25 -21
- package/dist/clients/lsp/config.js +36 -7
- package/dist/clients/lsp/diagnostic-binding.js +24 -1
- package/dist/clients/lsp/document-drift.js +78 -0
- package/dist/clients/lsp/index.js +288 -45
- package/dist/clients/lsp/launch.js +16 -4
- package/dist/clients/lsp/server.js +79 -15
- package/dist/clients/lsp/workspace-diagnostics-cache.js +39 -5
- package/dist/clients/lsp-mutation.js +5 -3
- package/dist/clients/map-with-concurrency.js +12 -8
- package/dist/clients/mcp/analyze.js +3 -0
- package/dist/clients/mcp/session.js +38 -4
- package/dist/clients/ndjson-logger.js +24 -7
- package/dist/clients/observed-mutation.js +40 -2
- package/dist/clients/opaque-mutation-scan.js +23 -3
- package/dist/clients/opengrep-client.js +111 -14
- package/dist/clients/package-manager.js +2 -1
- package/dist/clients/path-utils.js +123 -3
- package/dist/clients/performance-report.js +5 -1
- package/dist/clients/php-cs-fixer-config.js +8 -3
- package/dist/clients/pipeline.js +77 -7
- package/dist/clients/project-diagnostics/cache.js +37 -5
- package/dist/clients/project-diagnostics/fresh-fetch.js +173 -18
- package/dist/clients/project-diagnostics/runner-adapters/dead-code.js +4 -1
- package/dist/clients/project-diagnostics/runner-adapters/gitleaks.js +10 -9
- package/dist/clients/project-diagnostics/scanner.js +59 -3
- package/dist/clients/project-lens-config.js +48 -2
- package/dist/clients/read-guard-logger.js +2 -0
- package/dist/clients/read-guard.js +70 -11
- package/dist/clients/resource-sampler.js +147 -9
- package/dist/clients/review-graph-logger.js +2 -0
- package/dist/clients/ruff-client.js +18 -9
- package/dist/clients/runtime-agent-end.js +42 -5
- package/dist/clients/runtime-context.js +6 -2
- package/dist/clients/runtime-coordinator.js +82 -7
- package/dist/clients/runtime-session.js +33 -5
- package/dist/clients/runtime-tool-call.js +43 -12
- package/dist/clients/runtime-tool-result.js +334 -86
- package/dist/clients/runtime-turn.js +195 -18
- package/dist/clients/safe-spawn.js +258 -5
- package/dist/clients/scratch-tree-policy.js +6 -0
- package/dist/clients/security-scan-client.js +2 -2
- package/dist/clients/session-event-guard.js +119 -6
- package/dist/clients/sg-runner.js +25 -12
- package/dist/clients/sgconfig.js +79 -2
- package/dist/clients/situational-tool-telemetry.js +108 -0
- package/dist/clients/test-runner-client.js +258 -78
- package/dist/clients/test-runner-delivery.js +43 -0
- package/dist/clients/tool-agreement.js +423 -0
- package/dist/clients/tool-config.js +249 -0
- package/dist/clients/tool-cwd.js +270 -0
- package/dist/clients/tool-policy.js +163 -7
- package/dist/clients/tool-probe.js +53 -0
- package/dist/clients/tool-set-policy.js +42 -0
- package/dist/clients/tree-sitter-client.js +120 -0
- package/dist/clients/tree-sitter-query-loader.js +127 -189
- package/dist/clients/trivy-client.js +9 -1
- package/dist/clients/turn-context.js +52 -0
- package/dist/clients/widget-state.js +102 -3
- package/dist/clients/word-index.js +5 -2
- package/dist/clients/write-ordering-guard.js +7 -0
- package/dist/index.js +26968 -21741
- package/dist/mcp/analyze-cli.js +3 -2
- package/dist/mcp/server.js +140 -161
- package/dist/tools/activate-tools.js +10 -7
- package/dist/tools/ast-grep-outline.js +2 -13
- package/dist/tools/ast-grep-replace.js +8 -13
- package/dist/tools/ast-grep-search.js +83 -39
- package/dist/tools/effective-config.js +4 -3
- package/dist/tools/lens-diagnostic-mark.js +8 -11
- package/dist/tools/lens-diagnostics.js +516 -133
- package/dist/tools/lsp-diagnostics.js +265 -182
- package/dist/tools/lsp-navigation.js +20 -44
- package/dist/tools/module-report.js +5 -9
- package/dist/tools/project-report.js +9 -17
- package/dist/tools/render-compact.js +280 -1
- package/dist/tools/symbol-search.js +2 -2
- package/docs/agent-guide.md +3 -4
- package/docs/agent-tools.md +46 -22
- package/docs/audit1.md +5 -5
- package/docs/configuration.md +9 -0
- package/docs/dependencies.md +11 -0
- package/docs/dispositions.md +52 -0
- package/docs/environment-variables.md +2 -7
- package/docs/features.md +7 -7
- package/docs/globalconfig.md +14 -2
- package/docs/language-coverage.md +1 -0
- package/docs/mcp.md +13 -1
- package/docs/pi-lens-fixer.md +48 -18
- package/docs/pi-lens-investigator.md +38 -18
- package/docs/pi-lens-monitor.md +88 -0
- package/docs/pi-lens-retro.md +97 -0
- package/docs/pi-lens-reviewer.md +53 -31
- package/docs/pi-lens-subagent.md +12 -4
- package/docs/public-api-stability.md +1 -0
- package/docs/real-harness.md +46 -0
- package/docs/release-qa-baseline.md +27 -1
- package/docs/servercapabilities.md +1 -6
- package/docs/settings.md +44 -6
- package/docs/tools_improvement2.md +4 -4
- package/docs/usage.md +15 -3
- package/package.json +10 -1
- package/rules/tree-sitter-queries/typescript/sql-injection.yml +23 -7
- package/scripts/analyze-pi-lens-logs.mjs +40 -0
- package/skills/pi-lens-ast-grep/SKILL.md +23 -6
- package/skills/pi-lens-lsp-navigation/SKILL.md +26 -9
- package/dist/tools/ast-dump.js +0 -103
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-lens",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.2.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Real-time code feedback for pi — LSP, linters, formatters, type-checking, structural analysis & booboo",
|
|
6
6
|
"repository": {
|
|
@@ -33,10 +33,13 @@
|
|
|
33
33
|
"test:integration": "node scripts/with-test-lock.mjs -- vitest run tests/index-integration.test.ts tests/clients/lsp/integration.test.ts",
|
|
34
34
|
"test:targeted": "node scripts/with-test-lock.mjs --shared -- vitest run",
|
|
35
35
|
"test:watch": "vitest",
|
|
36
|
+
"test:real-harness": "node scripts/with-test-lock.mjs --shared -- vitest run",
|
|
37
|
+
"mutation:diff": "node scripts/stryker-diff.mjs --base origin/master --max-files 6",
|
|
36
38
|
"hygiene": "node scripts/prune-agent-worktrees.mjs",
|
|
37
39
|
"check": "node scripts/check-extensions.mjs",
|
|
38
40
|
"selftest:install": "node scripts/install-selftest.mjs",
|
|
39
41
|
"check:lockfile": "node scripts/check-lockfile-sync.mjs",
|
|
42
|
+
"preflight": "node scripts/pr-preflight.mjs",
|
|
40
43
|
"knip": "node scripts/run-knip.mjs",
|
|
41
44
|
"check:grammars": "node scripts/check-grammar-provenance.mjs",
|
|
42
45
|
"check:grammar-load": "node scripts/check-grammar-load.mjs",
|
|
@@ -49,7 +52,9 @@
|
|
|
49
52
|
"bench:cascade-budget": "node scripts/bench-cascade-budget.mjs",
|
|
50
53
|
"bench:word-index-replacement": "node scripts/bench-word-index-replacement.mjs",
|
|
51
54
|
"logs:smells": "node scripts/analyze-pi-lens-logs.mjs",
|
|
55
|
+
"complexity": "node scripts/complexity-report.mjs",
|
|
52
56
|
"changelog:check": "node scripts/rollup-changelog.mjs --check",
|
|
57
|
+
"test:regen": "node scripts/regen-test-baseline.mjs",
|
|
53
58
|
"changelog:release": "node scripts/changelog-release.mjs",
|
|
54
59
|
"changelog:extract": "node scripts/changelog-extract.mjs",
|
|
55
60
|
"release:backfill-notes": "node scripts/backfill-github-releases.mjs",
|
|
@@ -83,6 +88,7 @@
|
|
|
83
88
|
"engines": {
|
|
84
89
|
"node": ">=22.19.0"
|
|
85
90
|
},
|
|
91
|
+
"packageManager": "npm@11.18.0",
|
|
86
92
|
"files": [
|
|
87
93
|
"dist/",
|
|
88
94
|
"docs/",
|
|
@@ -145,5 +151,8 @@
|
|
|
145
151
|
"@ast-grep/cli@0.45.3": true,
|
|
146
152
|
"@google/genai@1.52.0": true,
|
|
147
153
|
"protobufjs@7.6.5": true
|
|
154
|
+
},
|
|
155
|
+
"overrides": {
|
|
156
|
+
"qs": "^6.15.4"
|
|
148
157
|
}
|
|
149
158
|
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# SQL Injection Detection
|
|
2
|
-
# Detects unsafe interpolation in SQL-like template literals
|
|
2
|
+
# Detects unsafe interpolation in SQL-like template literals.
|
|
3
|
+
# The structural query keeps the common callee set, while the TypeScript-aware
|
|
4
|
+
# post-filter requires a receiver bound to a known DB client or a SQL-leading template.
|
|
3
5
|
id: sql-injection
|
|
4
6
|
name: SQL Injection Risk
|
|
5
7
|
severity: error
|
|
@@ -26,18 +28,32 @@ description: |
|
|
|
26
28
|
|
|
27
29
|
query: |
|
|
28
30
|
(call_expression
|
|
29
|
-
function:
|
|
30
|
-
(identifier) @SQL_FUNC
|
|
31
|
-
(member_expression property: (property_identifier) @SQL_FUNC)
|
|
32
|
-
]
|
|
31
|
+
function: (identifier) @SQL_FUNC
|
|
33
32
|
arguments: (arguments
|
|
34
|
-
(template_string (template_substitution) @INTERPOLATION))
|
|
35
|
-
(#match? @SQL_FUNC "^(query|execute|exec|run)$"))
|
|
33
|
+
(template_string (template_substitution) @INTERPOLATION) @TEMPLATE)
|
|
34
|
+
(#match? @SQL_FUNC "^(query|execute|exec|run|\\$queryRaw|\\$executeRaw|\\$queryRawUnsafe|\\$executeRawUnsafe|raw|prepare)$"))
|
|
35
|
+
(call_expression
|
|
36
|
+
function: (member_expression
|
|
37
|
+
object: (_) @OBJ
|
|
38
|
+
property: (property_identifier) @SQL_FUNC)
|
|
39
|
+
arguments: (arguments
|
|
40
|
+
(template_string (template_substitution) @INTERPOLATION) @TEMPLATE)
|
|
41
|
+
(#match? @SQL_FUNC "^(query|execute|exec|run|\\$queryRaw|\\$executeRaw|\\$queryRawUnsafe|\\$executeRawUnsafe|raw|prepare)$"))
|
|
42
|
+
(call_expression
|
|
43
|
+
function: (member_expression
|
|
44
|
+
object: (_) @OBJ
|
|
45
|
+
property: (property_identifier) @SQL_FUNC)
|
|
46
|
+
arguments: (template_string (template_substitution) @INTERPOLATION) @TEMPLATE
|
|
47
|
+
(#match? @SQL_FUNC "^(query|execute|exec|run|\\$queryRaw|\\$executeRaw|\\$queryRawUnsafe|\\$executeRawUnsafe|raw|prepare)$"))
|
|
36
48
|
|
|
37
49
|
metavars:
|
|
38
50
|
- SQL_FUNC
|
|
51
|
+
- OBJ
|
|
52
|
+
- TEMPLATE
|
|
39
53
|
- INTERPOLATION
|
|
40
54
|
|
|
55
|
+
post_filter: ts_sql_injection_sink
|
|
56
|
+
|
|
41
57
|
has_fix: false
|
|
42
58
|
|
|
43
59
|
tags:
|
|
@@ -195,6 +195,7 @@ function createState(files) {
|
|
|
195
195
|
projects: counter(),
|
|
196
196
|
smellTotals: counter(),
|
|
197
197
|
latency: {
|
|
198
|
+
testRunnerVerdicts: new Map(),
|
|
198
199
|
runnerStatus: counter(),
|
|
199
200
|
runnerFailureKinds: counter(),
|
|
200
201
|
runnerBlockingFindings: counter(),
|
|
@@ -381,6 +382,22 @@ async function analyzeLatency(files, state) {
|
|
|
381
382
|
const phase = entry.phase ?? "unknown";
|
|
382
383
|
state.latency.phaseCounts.inc(phase);
|
|
383
384
|
if (phase.endsWith("_timeout")) state.latency.phaseTimeouts.inc(phase);
|
|
385
|
+
if (phase === "test_runner_verdict_delivery") {
|
|
386
|
+
const sessionId = entry.metadata?.sessionId ?? "unknown";
|
|
387
|
+
const summary = state.latency.testRunnerVerdicts.get(sessionId) ?? {
|
|
388
|
+
total: 0,
|
|
389
|
+
stale: 0,
|
|
390
|
+
unknown: 0,
|
|
391
|
+
};
|
|
392
|
+
const verdictCount = entry.metadata?.verdictCount;
|
|
393
|
+
const staleCount = entry.metadata?.staleCount;
|
|
394
|
+
const unknownCount = entry.metadata?.unknownCount;
|
|
395
|
+
summary.total += typeof verdictCount === "number" ? verdictCount : 1;
|
|
396
|
+
if (typeof staleCount === "number") summary.stale += staleCount;
|
|
397
|
+
else if (entry.metadata?.stale === true) summary.stale += 1;
|
|
398
|
+
if (typeof unknownCount === "number") summary.unknown += unknownCount;
|
|
399
|
+
state.latency.testRunnerVerdicts.set(sessionId, summary);
|
|
400
|
+
}
|
|
384
401
|
if (phase === "config_resolved") {
|
|
385
402
|
// #2526. Counted here rather than derived from phaseCounts so the
|
|
386
403
|
// legacy/record cross-check reads the same row it counts.
|
|
@@ -1481,6 +1498,18 @@ function buildReport(state) {
|
|
|
1481
1498
|
shownInlineShownAgentUnresolved: state.diagnostics.shownInline.toJSON(),
|
|
1482
1499
|
},
|
|
1483
1500
|
latency: {
|
|
1501
|
+
testRunnerVerdicts: Object.fromEntries(
|
|
1502
|
+
[...state.latency.testRunnerVerdicts.entries()].map(
|
|
1503
|
+
([sessionId, summary]) => [
|
|
1504
|
+
sessionId,
|
|
1505
|
+
{
|
|
1506
|
+
...summary,
|
|
1507
|
+
denominator: summary.total,
|
|
1508
|
+
rate: summary.total ? summary.stale / summary.total : 0,
|
|
1509
|
+
},
|
|
1510
|
+
],
|
|
1511
|
+
),
|
|
1512
|
+
),
|
|
1484
1513
|
runnerStatus: state.latency.runnerStatus.top(limit * 2),
|
|
1485
1514
|
runnerFailureKinds: state.latency.runnerFailureKinds.top(limit * 2),
|
|
1486
1515
|
runnerBlockingFindings: state.latency.runnerBlockingFindings.toJSON(),
|
|
@@ -1672,6 +1701,17 @@ function printReport(report) {
|
|
|
1672
1701
|
report.latency.runnerFailureKinds,
|
|
1673
1702
|
(x) => `${x.count.toString().padStart(5)} ${x.key}`,
|
|
1674
1703
|
);
|
|
1704
|
+
const verdictSessions = Object.entries(
|
|
1705
|
+
report.latency.testRunnerVerdicts ?? {},
|
|
1706
|
+
);
|
|
1707
|
+
if (verdictSessions.length) {
|
|
1708
|
+
console.log("\nTest-runner stale verdicts per session");
|
|
1709
|
+
for (const [sessionId, summary] of verdictSessions) {
|
|
1710
|
+
console.log(
|
|
1711
|
+
` ${sessionId}: ${summary.stale}/${summary.total} stale (${(summary.rate * 100).toFixed(1)}%)`,
|
|
1712
|
+
);
|
|
1713
|
+
}
|
|
1714
|
+
}
|
|
1675
1715
|
|
|
1676
1716
|
const a = report.actionable;
|
|
1677
1717
|
if (a.reports || a.advisoriesInjected) {
|
|
@@ -7,7 +7,22 @@ description: Use when searching or replacing code patterns - use ast-grep instea
|
|
|
7
7
|
|
|
8
8
|
Use `ast_grep_search` and `ast_grep_replace` for semantic code search/replace. ast-grep understands code structure, not just text.
|
|
9
9
|
|
|
10
|
-
These tools (plus `ast_grep_outline`, `
|
|
10
|
+
These tools (plus `ast_grep_outline`, `lsp_navigation`) are registered but inactive by default on hosts that support pi's dynamic tooling. If a call to one of them isn't recognized, activate it first: `pi_lens_activate_tools tools=["ast_grep_search", "ast_grep_replace"]`.
|
|
11
|
+
|
|
12
|
+
On hosts that aggregate pi-lens behind a single `lens` tool, the `ast_grep_*` tools and `pi_lens_activate_tools` may not be registered at all. There, fall back to the `ast-grep` CLI (alias `sg`) — patterns, metavariables, and YAML rules are identical:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
# search (≈ ast_grep_search)
|
|
16
|
+
ast-grep run -p 'fetchMetrics($$$ARGS)' -l ts src/
|
|
17
|
+
|
|
18
|
+
# rewrite (≈ ast_grep_replace; -U applies all)
|
|
19
|
+
ast-grep run -p 'var $X' -r 'let $X' -l js src/ -U
|
|
20
|
+
|
|
21
|
+
# full YAML rule (≈ the rule: parameter)
|
|
22
|
+
ast-grep scan --rule my-rule.yml src/
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Structural-intent parameters map to YAML constraints: `insideKind` → `inside: { kind: ..., stopBy: end }`, `hasKind`/`hasDescendantKind` → `has: { kind: ... }`, `follows` → `follows: { pattern: ... }`, `precedes` → `precedes: { pattern: ... }`.
|
|
11
26
|
|
|
12
27
|
## When to Use
|
|
13
28
|
|
|
@@ -88,15 +103,15 @@ rule:
|
|
|
88
103
|
stopBy: end" lang="typescript"
|
|
89
104
|
```
|
|
90
105
|
|
|
91
|
-
### Debugging unknown node kinds — `
|
|
106
|
+
### Debugging unknown node kinds — `ast_grep_search` dump mode
|
|
92
107
|
|
|
93
|
-
When a pattern returns zero matches and you don't know the correct node kind or field name, use `
|
|
108
|
+
When a pattern returns zero matches and you don't know the correct node kind or field name, use `ast_grep_search` with `dump=true` to inspect a SMALL representative snippet:
|
|
94
109
|
|
|
95
110
|
```
|
|
96
|
-
|
|
111
|
+
ast_grep_search dump=true pattern="function foo() { return 1; }" lang="typescript"
|
|
97
112
|
```
|
|
98
113
|
|
|
99
|
-
Returns the full indented AST with node kinds and positions. Then use the correct kind in your pattern or `insideKind`.
|
|
114
|
+
Returns the full indented AST with node kinds and positions. Then use the correct kind in your pattern or `insideKind`.
|
|
100
115
|
|
|
101
116
|
### Composite (has/inside) in raw YAML
|
|
102
117
|
|
|
@@ -146,8 +161,10 @@ kind: arrow_function
|
|
|
146
161
|
|
|
147
162
|
**No matches?**
|
|
148
163
|
|
|
164
|
+
For `nodeKind`, do not also pass `pattern` or `rule`; those forms are mutually exclusive. For `rule`, provide YAML containing both `id` and `language` fields. Use `strictness: relaxed` when unnamed punctuation is the only mismatch.
|
|
165
|
+
|
|
149
166
|
1. Try `strictness: relaxed` — ignores unnamed punctuation (trailing commas, semicolons) that `smart` mode requires
|
|
150
|
-
2. Use `
|
|
167
|
+
2. Use `ast_grep_search dump=true` on a sample snippet to verify the correct node kind
|
|
151
168
|
3. Simplify the pattern and retry once
|
|
152
169
|
4. Fall back to `grep` or `lsp_navigation`
|
|
153
170
|
|
|
@@ -5,22 +5,35 @@ description: Navigate code with IDE features and run proactive LSP diagnostics o
|
|
|
5
5
|
|
|
6
6
|
# LSP Navigation and Diagnostics
|
|
7
7
|
|
|
8
|
-
Use `lsp_navigation` as **PRIMARY** for code intelligence. Use `
|
|
8
|
+
Use `lsp_navigation` as **PRIMARY** for code intelligence. Use `lens_diagnostics` with `source=lsp` as **PRIMARY** for proactive type/error checks. Do NOT use grep/glob/ast-grep first for code intelligence.
|
|
9
|
+
|
|
10
|
+
## Aggregate-tool hosts
|
|
11
|
+
|
|
12
|
+
Some hosts expose pi-lens through a single aggregate tool — `lens(action=...)` — instead of registering the standalone names below. On those hosts:
|
|
13
|
+
|
|
14
|
+
- Proactive checks: `lens({ action: "lsp_diagnostics", ... })` — same parameters as the table below; the cached-report entry point maps to `lens({ action: "diagnostics", ... })`.
|
|
15
|
+
- If `lsp_navigation` is not among the aggregate's actions, do not call the standalone name: use the host's structural search funnel (`symbol_search` → `module_report` → `read_symbol`) or the `ast-grep` CLI for navigation instead.
|
|
9
16
|
|
|
10
17
|
## Diagnostics
|
|
11
18
|
|
|
12
|
-
Use `
|
|
19
|
+
Use `lens_diagnostics` with `source=lsp` before builds/tests or after touching several files:
|
|
13
20
|
|
|
14
21
|
| Need | Tool call |
|
|
15
22
|
|---|---|
|
|
16
|
-
| Check one file | `
|
|
17
|
-
| Check a folder | `
|
|
18
|
-
| Check exact touched files | `
|
|
19
|
-
| Slow server (Rust, Java) | `
|
|
20
|
-
| Include warnings | `
|
|
23
|
+
| Check one file | `lens_diagnostics({ source: "lsp", scope: "paths", paths: ["src/file.ts"] })` |
|
|
24
|
+
| Check a folder | `lens_diagnostics({ source: "lsp", scope: "workspace", path: "src/", severity: "error" })` |
|
|
25
|
+
| Check exact touched files | `lens_diagnostics({ source: "lsp", scope: "paths", paths: ["src/a.ts", "src/b.ts"] })` |
|
|
26
|
+
| Slow server (Rust, Java) | `lens_diagnostics({ source: "lsp", scope: "paths", paths: files, waitMs: 2000 })` |
|
|
27
|
+
| Include warnings | `lens_diagnostics({ source: "lsp", scope: "paths", paths: files, severity: "all" })` |
|
|
21
28
|
|
|
22
29
|
Prefer explicit `paths` batches after multi-file edits — bounded concurrency, no unrelated directory noise.
|
|
23
30
|
|
|
31
|
+
### Parameter reference
|
|
32
|
+
|
|
33
|
+
`lens_diagnostics` accepts `source: "session" | "lsp"` and `scope: "paths" | "workspace"`. Use `mode: "delta"` for the current turn, `"all"` for the cache-only session view, or `"full"` for an active scan. `path` selects one file or directory; `paths` filters a batch. `severity` is `"error"`, `"warning"`, or `"all"`; `serverScope` is `"primary"` or `"all"`.
|
|
34
|
+
|
|
35
|
+
For `mode: "full"`, `refreshRunners: "cached" | "cheap" | "all" | "none"` (or `false`/`true`) controls project analyzers. The first three string modes can launch a fresh heavyweight analyzer pass, bounded by the slowest runner's roughly 180-second ceiling; `none` disables it. `maxProjectFiles` limits cheap project runners, `maxLspFiles` limits the LSP sweep, and `includeGenerated: true` includes generated-name paths. These three limits apply to full scans. `concurrency` and `waitMs` tune LSP batches.
|
|
36
|
+
|
|
24
37
|
## Navigation (Code Intelligence)
|
|
25
38
|
|
|
26
39
|
| Question | Operation | Parameters |
|
|
@@ -41,6 +54,10 @@ Prefer explicit `paths` batches after multi-file edits — bounded concurrency,
|
|
|
41
54
|
| What commands does the server offer? | `capabilities` | (optional path) — lists advertised commands |
|
|
42
55
|
| Run a server command (e.g. organize imports) | `executeCommand` | command (+ commandArguments); dry-run unless `apply:true` |
|
|
43
56
|
|
|
57
|
+
The `operation` values are `definition`, `typeDefinition`, `declaration`, `references`, `hover`, `signatureHelp`, `documentSymbol`, `findSymbol`, `workspaceSymbol`, `codeAction`, `rename`, `rename_file`, `implementation`, `prepareCallHierarchy`, `incomingCalls`, `outgoingCalls`, `executeCommand`, `workspaceDiagnostics`, and `capabilities`.
|
|
58
|
+
|
|
59
|
+
For `findSymbol`, pass `query`; optionally narrow with `kinds`, `exactMatch`, `topLevelOnly`, and `maxResults`. `rename_file` uses `newFilePath`. `symbol` resolves a character automatically; `character: -1` requests automatic resolution, and `symbol#N` selects a numbered symbol when the result lists one. `callHierarchyItem` is the object returned by `prepareCallHierarchy` and is required by the incoming/outgoing follow-up calls.
|
|
60
|
+
|
|
44
61
|
## Call Hierarchy Pattern
|
|
45
62
|
|
|
46
63
|
```
|
|
@@ -59,7 +76,7 @@ lsp_navigation(operation="outgoingCalls", callHierarchyItem=<item from step 1>)
|
|
|
59
76
|
- **`workspaceSymbol` empty?** Always pass `path`. Unscoped queries are best-effort and frequently return nothing. If TypeScript returns "No Project", open the scoped file first.
|
|
60
77
|
- **`references`** — query from the *definition site* for full cross-file coverage; usage-site queries can be partial.
|
|
61
78
|
- **`signatureHelp`** — only valid at call-site argument positions; declaration positions return empty.
|
|
62
|
-
- **`workspaceDiagnostics`** — tracked push snapshot only, not an active check. Use `
|
|
79
|
+
- **`workspaceDiagnostics`** — tracked push snapshot only, not an active check. Use `lens_diagnostics` with `source=lsp` when you need fresh results.
|
|
63
80
|
- **`codeAction`** — distinguish `quickfix` from generic refactors ("Move to new file"). Generic refactors are not error fixes.
|
|
64
81
|
- **`prepareCallHierarchy`** — server-capability dependent; if unsupported, skip incoming/outgoing calls.
|
|
65
82
|
|
|
@@ -74,4 +91,4 @@ lsp_navigation(operation="outgoingCalls", callHierarchyItem=<item from step 1>)
|
|
|
74
91
|
|
|
75
92
|
## Golden Rule
|
|
76
93
|
|
|
77
|
-
**Code intelligence → `lsp_navigation` first. Type/error validation → `
|
|
94
|
+
**Code intelligence → `lsp_navigation` first. Type/error validation → `lens_diagnostics source=lsp` first. Text/pattern search → grep/ast-grep.**
|
package/dist/tools/ast-dump.js
DELETED
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
import { Type } from "../clients/deps/typebox.js";
|
|
2
|
-
import { compactRenderResult } from "./render-compact.js";
|
|
3
|
-
import { LANGUAGES } from "./shared.js";
|
|
4
|
-
function createAstDumpToolWithName(astGrepClient, name) {
|
|
5
|
-
return {
|
|
6
|
-
name,
|
|
7
|
-
label: "AST-Grep Dump",
|
|
8
|
-
description: "Dump the tree-sitter AST for a source snippet using ast-grep CLI. Use when ast_grep_search returns zero matches and you need exact node kinds, field names, or nesting. Named nodes only by default; includeAnonymous=true shows punctuation/CST nodes too.",
|
|
9
|
-
promptSnippet: "Inspect AST node kinds before writing ast-grep patterns",
|
|
10
|
-
renderResult: compactRenderResult(({ details, args, isError, lineCount, text }) => {
|
|
11
|
-
const lang = details?.lang ?? (typeof args.lang === "string" ? args.lang : "");
|
|
12
|
-
if (isError) {
|
|
13
|
-
return `${name} ${lang} — ${text.split("\n")[0] ?? "error"}`.trim();
|
|
14
|
-
}
|
|
15
|
-
return `${name} ${lang} — ${lineCount} AST nodes`.replace(/\s+/g, " ");
|
|
16
|
-
}),
|
|
17
|
-
parameters: Type.Object({
|
|
18
|
-
source: Type.String({
|
|
19
|
-
description: "Source code snippet to parse and dump",
|
|
20
|
-
}),
|
|
21
|
-
lang: Type.String({
|
|
22
|
-
enum: [...LANGUAGES],
|
|
23
|
-
description: "Target language",
|
|
24
|
-
}),
|
|
25
|
-
includeAnonymous: Type.Optional(Type.Boolean({
|
|
26
|
-
description: "Show anonymous punctuation/CST nodes too (default false)",
|
|
27
|
-
})),
|
|
28
|
-
}),
|
|
29
|
-
async execute(_toolCallId, params, _signal, _onUpdate) {
|
|
30
|
-
const source = typeof params.source === "string" ? params.source : "";
|
|
31
|
-
const lang = typeof params.lang === "string"
|
|
32
|
-
? params.lang.replace(/^"|"$/g, "")
|
|
33
|
-
: "";
|
|
34
|
-
const includeAnonymous = params.includeAnonymous === true;
|
|
35
|
-
try {
|
|
36
|
-
if (!source.trim()) {
|
|
37
|
-
return {
|
|
38
|
-
content: [{ type: "text", text: "source is required" }],
|
|
39
|
-
isError: true,
|
|
40
|
-
details: { lang, includeAnonymous },
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
if (_signal.aborted) {
|
|
44
|
-
return {
|
|
45
|
-
content: [
|
|
46
|
-
{ type: "text", text: "Error: operation aborted" },
|
|
47
|
-
],
|
|
48
|
-
isError: true,
|
|
49
|
-
details: { lang, includeAnonymous },
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
if (!(await astGrepClient.ensureAvailable())) {
|
|
53
|
-
return {
|
|
54
|
-
content: [
|
|
55
|
-
{
|
|
56
|
-
type: "text",
|
|
57
|
-
text: "ast-grep CLI not found. Install: npm i -D @ast-grep/cli",
|
|
58
|
-
},
|
|
59
|
-
],
|
|
60
|
-
isError: true,
|
|
61
|
-
details: { lang, includeAnonymous },
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
if (_signal.aborted) {
|
|
65
|
-
return {
|
|
66
|
-
content: [
|
|
67
|
-
{ type: "text", text: "Error: operation aborted" },
|
|
68
|
-
],
|
|
69
|
-
isError: true,
|
|
70
|
-
details: { lang, includeAnonymous },
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
const result = await astGrepClient.dumpAst(source, lang, {
|
|
74
|
-
includeAnonymous,
|
|
75
|
-
});
|
|
76
|
-
if (result.error) {
|
|
77
|
-
return {
|
|
78
|
-
content: [
|
|
79
|
-
{ type: "text", text: `Error: ${result.error}` },
|
|
80
|
-
],
|
|
81
|
-
isError: true,
|
|
82
|
-
details: { lang, includeAnonymous },
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
return {
|
|
86
|
-
content: [{ type: "text", text: result.output ?? "" }],
|
|
87
|
-
details: { lang, includeAnonymous },
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
catch (err) {
|
|
91
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
92
|
-
return {
|
|
93
|
-
content: [{ type: "text", text: `Error: ${message}` }],
|
|
94
|
-
isError: true,
|
|
95
|
-
details: { lang, includeAnonymous },
|
|
96
|
-
};
|
|
97
|
-
}
|
|
98
|
-
},
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
export function createAstGrepDumpTool(astGrepClient) {
|
|
102
|
-
return createAstDumpToolWithName(astGrepClient, "ast_grep_dump");
|
|
103
|
-
}
|