pi-lens 4.3.0 → 4.4.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 +1064 -0
- package/README.md +115 -25
- package/config/dependency-cruiser-eager-allowlist.json +6 -2
- package/dist/chunk-22AVIGXS.js +560 -0
- package/dist/chunk-27BBHSZC.js +106 -0
- package/dist/chunk-2BEMIWEW.js +51 -0
- package/dist/chunk-2EECBNC5.js +89 -0
- package/dist/chunk-34U7PLGE.js +23 -0
- package/dist/chunk-3I5QFT3N.js +181 -0
- package/dist/chunk-3MED75HT.js +37 -0
- package/dist/chunk-47D2BO4S.js +87 -0
- package/dist/chunk-4RERDEXR.js +348 -0
- package/dist/chunk-4W2PLC4J.js +27 -0
- package/dist/chunk-52H5B5TC.js +202 -0
- package/dist/chunk-54B42YRX.js +27 -0
- package/dist/chunk-5RXBNSW2.js +266 -0
- package/dist/chunk-5THXD6X5.js +201 -0
- package/dist/chunk-5W3R6LFT.js +24 -0
- package/dist/chunk-5ZEJHV35.js +341 -0
- package/dist/chunk-6P62QVEA.js +118 -0
- package/dist/chunk-6QIUX4EP.js +459 -0
- package/dist/chunk-6VCD4VKZ.js +78 -0
- package/dist/chunk-7F72PXY2.js +326 -0
- package/dist/chunk-7FBF7NPR.js +998 -0
- package/dist/chunk-7U2IDNXN.js +37 -0
- package/dist/chunk-ABBOA7UD.js +157 -0
- package/dist/chunk-AHDW3GPE.js +50 -0
- package/dist/chunk-AJ3QXTRQ.js +756 -0
- package/dist/chunk-AJVLWNFN.js +1610 -0
- package/dist/chunk-AJXODZY6.js +112 -0
- package/dist/chunk-ARFCXG7S.js +84 -0
- package/dist/chunk-AS44CFQ4.js +708 -0
- package/dist/chunk-AWE5TMPO.js +38 -0
- package/dist/chunk-B3I2UUT4.js +4692 -0
- package/dist/chunk-BRJKOBZP.js +331 -0
- package/dist/chunk-BW5KFIQC.js +59 -0
- package/dist/chunk-C2AUYXQH.js +149 -0
- package/dist/chunk-CGGAIP7J.js +29 -0
- package/dist/chunk-D6QS3U6M.js +30 -0
- package/dist/chunk-DFVMIKMQ.js +349 -0
- package/dist/chunk-DIULIWKU.js +169 -0
- package/dist/chunk-DQ2NZ7C4.js +2317 -0
- package/dist/chunk-E2WFBRHM.js +213 -0
- package/dist/chunk-E4MAEDPM.js +50 -0
- package/dist/chunk-EOKRQ3SA.js +30 -0
- package/dist/chunk-F3AU2TMM.js +2626 -0
- package/dist/chunk-F3P7VQ7H.js +170 -0
- package/dist/chunk-FC4RP4I2.js +12 -0
- package/dist/chunk-FJNKANOS.js +32 -0
- package/dist/chunk-GUOGVTCQ.js +146 -0
- package/dist/chunk-GVXA6CCE.js +18 -0
- package/dist/chunk-HHYAELLJ.js +2334 -0
- package/dist/chunk-HMFXILPV.js +83 -0
- package/dist/chunk-HVUZXSWK.js +421 -0
- package/dist/chunk-HWBZIGMJ.js +62 -0
- package/dist/chunk-I3R7GKDR.js +17 -0
- package/dist/chunk-I7SPGOWI.js +55 -0
- package/dist/chunk-IIXOAGHR.js +38 -0
- package/dist/chunk-IVP5KAB7.js +2250 -0
- package/dist/chunk-IXEBJSUE.js +22 -0
- package/dist/chunk-JOLITGCC.js +27 -0
- package/dist/chunk-K6VYLB2U.js +145 -0
- package/dist/chunk-LJDODBBZ.js +78 -0
- package/dist/chunk-LNAKEO63.js +78 -0
- package/dist/chunk-LSMJ6KBE.js +4139 -0
- package/dist/chunk-LW6XKDZQ.js +5565 -0
- package/dist/chunk-N3YQJI6O.js +899 -0
- package/dist/chunk-NABLC7W3.js +148 -0
- package/dist/chunk-NKOUFPQF.js +659 -0
- package/dist/chunk-NL5GLMFI.js +211 -0
- package/dist/chunk-NMABWBZN.js +327 -0
- package/dist/chunk-NTHH2J74.js +27 -0
- package/dist/chunk-NTUJEGDZ.js +59 -0
- package/dist/chunk-NXL4FFQQ.js +47 -0
- package/dist/chunk-NXPS2L6U.js +466 -0
- package/dist/chunk-O5WILGMI.js +42 -0
- package/dist/chunk-O6TQT6RI.js +48 -0
- package/dist/chunk-OAXNDZJ7.js +323 -0
- package/dist/chunk-ODEEOXPH.js +44 -0
- package/dist/chunk-OQGFCZJ4.js +4533 -0
- package/dist/chunk-ORTMY4Q4.js +282 -0
- package/dist/chunk-OS32RNR2.js +442 -0
- package/dist/chunk-PAK6IDME.js +189 -0
- package/dist/chunk-PWFHBTSF.js +406 -0
- package/dist/chunk-Q5U6FMDI.js +2352 -0
- package/dist/chunk-QOZXJ4NA.js +3364 -0
- package/dist/chunk-QYF5S6P6.js +45 -0
- package/dist/chunk-RIISMHKN.js +36 -0
- package/dist/chunk-RPD4ZSB7.js +25 -0
- package/dist/chunk-RPD5K5NC.js +79 -0
- package/dist/chunk-RUOG5D2C.js +262 -0
- package/dist/chunk-T4ERT73Y.js +599 -0
- package/dist/chunk-T6D4Q4AQ.js +54 -0
- package/dist/chunk-TGPXLY2J.js +391 -0
- package/dist/chunk-TLGFBM3F.js +12116 -0
- package/dist/chunk-TO6WL3GM.js +88 -0
- package/dist/chunk-TT22N74J.js +517 -0
- package/dist/chunk-TVN5N6GY.js +21216 -0
- package/dist/chunk-U3VGR4VU.js +308 -0
- package/dist/chunk-UK3CMEAL.js +1250 -0
- package/dist/chunk-UOPVJQ4N.js +103 -0
- package/dist/chunk-UXVNL3D7.js +23 -0
- package/dist/chunk-UY752QSN.js +45 -0
- package/dist/chunk-V5PXFSZK.js +188 -0
- package/dist/chunk-V7R425XG.js +398 -0
- package/dist/chunk-VCSRSYLF.js +81 -0
- package/dist/chunk-VD4JQCQC.js +162 -0
- package/dist/chunk-VDBPVIKD.js +62 -0
- package/dist/chunk-VHQLPIRJ.js +114 -0
- package/dist/chunk-VN2AXLEX.js +5414 -0
- package/dist/chunk-VNMT7C64.js +478 -0
- package/dist/chunk-WONERJTP.js +309 -0
- package/dist/chunk-XECLWQZN.js +85 -0
- package/dist/chunk-XIMYZ3JA.js +27 -0
- package/dist/chunk-XK4CIILI.js +144 -0
- package/dist/chunk-Y4T27COV.js +562 -0
- package/dist/chunk-YGVYKNSN.js +1860 -0
- package/dist/chunk-YLF3PPT5.js +308 -0
- package/dist/chunk-YSNFMJKN.js +14 -0
- package/dist/chunk-Z3CCVDUB.js +76 -0
- package/dist/chunk-Z54ZSOBZ.js +61 -0
- package/dist/chunk-ZAWW3AF6.js +97 -0
- package/dist/chunk-ZMOL6RQC.js +167 -0
- package/dist/index.js +16456 -8335
- package/dist/mcp/analyze-cli.js +186 -232
- package/dist/mcp/cli.js +137 -98
- package/dist/mcp/server.js +22589 -1573
- package/dist/mcp/worker.js +97 -38
- package/dist/probes/installer.js +135 -0
- package/dist/workers/project-snapshot-persist-worker.js +22 -0
- package/dist/workers/review-graph-persist-worker.js +15 -0
- package/docs/agent-guide.md +13 -4
- package/docs/agent-tools.md +42 -0
- package/docs/ast-grep_rules_catalog.md +3 -2
- package/docs/configuration.md +20 -1
- package/docs/environment-variables.md +52 -2
- package/docs/features.md +8 -4
- package/docs/globalconfig.md +1 -0
- package/docs/io-bridge-v2-migration.md +94 -0
- package/docs/lsp-capability-matrix.md +36 -4
- package/docs/lsp-idle-eviction.md +124 -0
- package/docs/mcp.md +21 -5
- package/docs/merge-queue-rollout.md +77 -0
- package/docs/pi-lens-fixer.md +156 -88
- package/docs/pi-lens-investigator.md +74 -26
- package/docs/pi-lens-merge-policy.md +694 -0
- package/docs/pi-lens-monitor.md +73 -7
- package/docs/pi-lens-retro.md +6 -4
- package/docs/pi-lens-reviewer.md +188 -48
- package/docs/pi-lens-subagent.md +246 -45
- package/docs/pi-lens-warden.md +18 -7
- package/docs/public-api-stability.md +55 -0
- package/docs/release-qa-baseline.md +84 -17
- package/docs/rfcs/3654-unified-io-bridge-v2.md +316 -0
- package/docs/servercapabilities.md +53 -49
- package/docs/settings.md +1 -0
- package/docs/usage.md +5 -1
- package/grammars/tree-sitter-bash.wasm +0 -0
- package/grammars/tree-sitter-bash.wasm.json +3 -3
- package/package.json +19 -7
- package/rules/ast-grep-rules/rule-tests/advisory-registry-subset-test.yml +41 -0
- package/rules/ast-grep-rules/rules/advisory-registry-subset.yml +50 -0
- package/scripts/analyze-pi-lens-logs.mjs +1275 -62
- package/scripts/download-grammars.js +5 -0
- package/scripts/grammars.lock.json +6 -1
- package/scripts/install-selftest.mjs +33 -34
- package/scripts/lib/host-provided-deps.mjs +13 -4
- package/scripts/lib/web-tree-sitter-dir.mjs +18 -0
- package/dist/clients/actionable-warnings-logger.js +0 -35
- package/dist/clients/actionable-warnings.js +0 -1610
- package/dist/clients/advisory-provenance.js +0 -593
- package/dist/clients/agent-behavior-client.js +0 -147
- package/dist/clients/agent-nudge.js +0 -325
- package/dist/clients/analysed-root.js +0 -1
- package/dist/clients/ast-grep-client.js +0 -731
- package/dist/clients/ast-grep-rule-manager.js +0 -146
- package/dist/clients/ast-grep-tool-logger.js +0 -118
- package/dist/clients/ast-grep-types.js +0 -10
- package/dist/clients/ast-grep-yaml-synth.js +0 -154
- package/dist/clients/atomic-write-staging.js +0 -75
- package/dist/clients/atomic-write.js +0 -189
- package/dist/clients/availability-probe-flight.js +0 -12
- package/dist/clients/bash-file-access.js +0 -1056
- package/dist/clients/biome-client.js +0 -357
- package/dist/clients/blocker-freshness.js +0 -837
- package/dist/clients/blocker-past-eof.js +0 -129
- package/dist/clients/bootstrap.js +0 -569
- package/dist/clients/bounded-cache.js +0 -190
- package/dist/clients/bounded-pid-file-lock.js +0 -202
- package/dist/clients/bounded-telemetry.js +0 -295
- package/dist/clients/build-identity.js +0 -95
- package/dist/clients/bundled-resource-health.js +0 -113
- package/dist/clients/bus-events-logger.js +0 -105
- package/dist/clients/bus-publish.js +0 -171
- package/dist/clients/cache/rule-cache.js +0 -190
- package/dist/clients/cache-manager.js +0 -524
- package/dist/clients/cache-observability.js +0 -1313
- package/dist/clients/call-graph.js +0 -852
- package/dist/clients/cargo-manifest.js +0 -422
- package/dist/clients/cascade-budget.js +0 -196
- package/dist/clients/cascade-format.js +0 -315
- package/dist/clients/cascade-logger.js +0 -31
- package/dist/clients/cascade-types.js +0 -9
- package/dist/clients/child-unref.js +0 -124
- package/dist/clients/code-quality-warnings.js +0 -286
- package/dist/clients/codebase-model.js +0 -173
- package/dist/clients/collateral-test-role.js +0 -40
- package/dist/clients/complexity-client.js +0 -462
- package/dist/clients/config-core/deny.js +0 -221
- package/dist/clients/config-core/index.js +0 -50
- package/dist/clients/config-core/merge.js +0 -357
- package/dist/clients/config-core/normalize.js +0 -340
- package/dist/clients/config-core/process-spec.js +0 -248
- package/dist/clients/config-core/provenance.js +0 -164
- package/dist/clients/config-core/records.js +0 -218
- package/dist/clients/config-core/resolve.js +0 -125
- package/dist/clients/config-core/safe-object.js +0 -78
- package/dist/clients/config-core/schema.js +0 -165
- package/dist/clients/config-diagnostic-codes.js +0 -285
- package/dist/clients/config-locations.js +0 -388
- package/dist/clients/config-resolve.js +0 -798
- package/dist/clients/config-schema.js +0 -251
- package/dist/clients/config-warn.js +0 -407
- package/dist/clients/console-guard-install.js +0 -26
- package/dist/clients/cooperative-budget.js +0 -42
- package/dist/clients/dead-code-client.js +0 -510
- package/dist/clients/dead-code-logger.js +0 -30
- package/dist/clients/deadline-utils.js +0 -280
- package/dist/clients/debug-handles.js +0 -211
- package/dist/clients/debug-heap.js +0 -174
- package/dist/clients/deferred-lsp-work.js +0 -106
- package/dist/clients/degradation-ledger.js +0 -426
- package/dist/clients/demoted-finding-render.js +0 -169
- package/dist/clients/dependency-checker.js +0 -885
- package/dist/clients/deps/ast-grep-napi.js +0 -22
- package/dist/clients/deps/js-yaml.js +0 -9
- package/dist/clients/deps/minimatch.js +0 -4
- package/dist/clients/deps/pi-tui.js +0 -14
- package/dist/clients/deps/typebox.js +0 -14
- package/dist/clients/deps/vscode-jsonrpc.js +0 -1
- package/dist/clients/deps/web-tree-sitter.js +0 -24
- package/dist/clients/diagnostic-dispositions.js +0 -630
- package/dist/clients/diagnostic-line-freshness.js +0 -305
- package/dist/clients/diagnostic-logger.js +0 -73
- package/dist/clients/diagnostic-tracker.js +0 -105
- package/dist/clients/diagnostics-publish.js +0 -230
- package/dist/clients/dispatch/ast-grep-catalog.js +0 -65
- package/dist/clients/dispatch/auxiliary-lsp.js +0 -343
- package/dist/clients/dispatch/collect-later-tier.js +0 -35
- package/dist/clients/dispatch/diagnostic-taxonomy.js +0 -66
- package/dist/clients/dispatch/dispatcher.js +0 -1269
- package/dist/clients/dispatch/fact-provider-types.js +0 -1
- package/dist/clients/dispatch/fact-rule-runner.js +0 -17
- package/dist/clients/dispatch/fact-runner.js +0 -30
- package/dist/clients/dispatch/fact-scheduler.js +0 -68
- package/dist/clients/dispatch/fact-store.js +0 -377
- package/dist/clients/dispatch/facts/comment-facts.js +0 -22
- package/dist/clients/dispatch/facts/file-content.js +0 -19
- package/dist/clients/dispatch/facts/function-facts.js +0 -348
- package/dist/clients/dispatch/facts/import-facts.js +0 -204
- package/dist/clients/dispatch/facts/tree-sitter-facts.js +0 -34
- package/dist/clients/dispatch/facts/try-catch-facts.js +0 -119
- package/dist/clients/dispatch/finding-policy.js +0 -339
- package/dist/clients/dispatch/indent-detect.js +0 -417
- package/dist/clients/dispatch/inline-suppressions.js +0 -89
- package/dist/clients/dispatch/integration.js +0 -2377
- package/dist/clients/dispatch/lazy.js +0 -11
- package/dist/clients/dispatch/pending-runner-findings.js +0 -87
- package/dist/clients/dispatch/plan.js +0 -278
- package/dist/clients/dispatch/priorities.js +0 -20
- package/dist/clients/dispatch/rule-id-normalize.js +0 -50
- package/dist/clients/dispatch/rule-ignores.js +0 -69
- package/dist/clients/dispatch/rule-policy.js +0 -135
- package/dist/clients/dispatch/rules/async-noise.js +0 -40
- package/dist/clients/dispatch/rules/async-unnecessary-wrapper.js +0 -27
- package/dist/clients/dispatch/rules/cors-wildcard.js +0 -54
- package/dist/clients/dispatch/rules/error-obscuring.js +0 -32
- package/dist/clients/dispatch/rules/error-swallowing.js +0 -31
- package/dist/clients/dispatch/rules/framework-call-noise.js +0 -67
- package/dist/clients/dispatch/rules/high-complexity.js +0 -72
- package/dist/clients/dispatch/rules/high-fan-out.js +0 -74
- package/dist/clients/dispatch/rules/high-import-coupling.js +0 -37
- package/dist/clients/dispatch/rules/missing-error-propagation.js +0 -62
- package/dist/clients/dispatch/rules/no-commented-credentials.js +0 -52
- package/dist/clients/dispatch/rules/pass-through-wrappers.js +0 -42
- package/dist/clients/dispatch/rules/placeholder-comments.js +0 -40
- package/dist/clients/dispatch/rules/unsafe-boundary.js +0 -126
- package/dist/clients/dispatch/runner-context.js +0 -52
- package/dist/clients/dispatch/runners/actionlint.js +0 -111
- package/dist/clients/dispatch/runners/ast-grep-napi.js +0 -1196
- package/dist/clients/dispatch/runners/biome-check.js +0 -296
- package/dist/clients/dispatch/runners/cpp-check.js +0 -219
- package/dist/clients/dispatch/runners/credo.js +0 -82
- package/dist/clients/dispatch/runners/cue-vet.js +0 -416
- package/dist/clients/dispatch/runners/dart-analyze.js +0 -183
- package/dist/clients/dispatch/runners/detekt.js +0 -176
- package/dist/clients/dispatch/runners/dotnet-build.js +0 -164
- package/dist/clients/dispatch/runners/elixir-check.js +0 -195
- package/dist/clients/dispatch/runners/eslint.js +0 -137
- package/dist/clients/dispatch/runners/fact-rules.js +0 -29
- package/dist/clients/dispatch/runners/fish-indent.js +0 -69
- package/dist/clients/dispatch/runners/gleam-check.js +0 -167
- package/dist/clients/dispatch/runners/go-vet.js +0 -104
- package/dist/clients/dispatch/runners/golangci-lint.js +0 -135
- package/dist/clients/dispatch/runners/hadolint.js +0 -91
- package/dist/clients/dispatch/runners/helm-lint.js +0 -171
- package/dist/clients/dispatch/runners/helm-render.js +0 -940
- package/dist/clients/dispatch/runners/htmlhint.js +0 -117
- package/dist/clients/dispatch/runners/index.js +0 -108
- package/dist/clients/dispatch/runners/javac.js +0 -99
- package/dist/clients/dispatch/runners/ktlint.js +0 -110
- package/dist/clients/dispatch/runners/lsp.js +0 -379
- package/dist/clients/dispatch/runners/markdownlint.js +0 -167
- package/dist/clients/dispatch/runners/mypy.js +0 -102
- package/dist/clients/dispatch/runners/oxlint.js +0 -414
- package/dist/clients/dispatch/runners/php-lint.js +0 -85
- package/dist/clients/dispatch/runners/phpstan.js +0 -120
- package/dist/clients/dispatch/runners/prisma-validate.js +0 -62
- package/dist/clients/dispatch/runners/psscriptanalyzer.js +0 -445
- package/dist/clients/dispatch/runners/pyright.js +0 -169
- package/dist/clients/dispatch/runners/rubocop.js +0 -99
- package/dist/clients/dispatch/runners/ruff.js +0 -88
- package/dist/clients/dispatch/runners/rust-clippy.js +0 -256
- package/dist/clients/dispatch/runners/shellcheck.js +0 -173
- package/dist/clients/dispatch/runners/shfmt.js +0 -102
- package/dist/clients/dispatch/runners/spellcheck.js +0 -128
- package/dist/clients/dispatch/runners/spotbugs.js +0 -259
- package/dist/clients/dispatch/runners/sqlfluff.js +0 -183
- package/dist/clients/dispatch/runners/stylelint.js +0 -166
- package/dist/clients/dispatch/runners/swiftlint.js +0 -163
- package/dist/clients/dispatch/runners/taplo.js +0 -174
- package/dist/clients/dispatch/runners/terragrunt.js +0 -168
- package/dist/clients/dispatch/runners/tflint.js +0 -125
- package/dist/clients/dispatch/runners/tree-sitter.js +0 -643
- package/dist/clients/dispatch/runners/trivy-config.js +0 -253
- package/dist/clients/dispatch/runners/utils/availability-policy.js +0 -496
- package/dist/clients/dispatch/runners/utils/candidate-probe.js +0 -90
- package/dist/clients/dispatch/runners/utils/diagnostic-parsers.js +0 -95
- package/dist/clients/dispatch/runners/utils/lazy-installer.js +0 -274
- package/dist/clients/dispatch/runners/utils/runner-helpers.js +0 -1701
- package/dist/clients/dispatch/runners/utils/spawn-outcome.js +0 -101
- package/dist/clients/dispatch/runners/utils/tool-failure.js +0 -235
- package/dist/clients/dispatch/runners/utils/toolchain-availability.js +0 -169
- package/dist/clients/dispatch/runners/utils.js +0 -15
- package/dist/clients/dispatch/runners/vale.js +0 -128
- package/dist/clients/dispatch/runners/yaml-rule-parser.js +0 -242
- package/dist/clients/dispatch/runners/yamllint.js +0 -95
- package/dist/clients/dispatch/runners/zig-check.js +0 -79
- package/dist/clients/dispatch/suppress-writer.js +0 -79
- package/dist/clients/dispatch/tool-profile.js +0 -30
- package/dist/clients/dispatch/types.js +0 -21
- package/dist/clients/dispatch/utils/format-utils.js +0 -45
- package/dist/clients/dispatch/utils/lsp-diagnostics.js +0 -35
- package/dist/clients/disposition-logger.js +0 -32
- package/dist/clients/disposition-publish.js +0 -124
- package/dist/clients/durable-store.js +0 -97
- package/dist/clients/effective-config.js +0 -415
- package/dist/clients/env-utils.js +0 -83
- package/dist/clients/error-class.js +0 -23
- package/dist/clients/eval-timestamp.js +0 -17
- package/dist/clients/event-loop-hold.js +0 -274
- package/dist/clients/event-loop-monitor.js +0 -250
- package/dist/clients/extension-log.js +0 -504
- package/dist/clients/extension-mode.js +0 -73
- package/dist/clients/feature-hints.js +0 -103
- package/dist/clients/file-kinds.js +0 -412
- package/dist/clients/file-role.js +0 -134
- package/dist/clients/file-time.js +0 -160
- package/dist/clients/file-utils.js +0 -1032
- package/dist/clients/finding-delivery-gate.js +0 -494
- package/dist/clients/finding-identity.js +0 -88
- package/dist/clients/fix-worklog.js +0 -103
- package/dist/clients/format-events-publish.js +0 -343
- package/dist/clients/format-service.js +0 -222
- package/dist/clients/formatters-lazy.js +0 -9
- package/dist/clients/formatters.js +0 -2032
- package/dist/clients/freshness-cadence.js +0 -17
- package/dist/clients/freshness.js +0 -38
- package/dist/clients/generated-artifacts.js +0 -394
- package/dist/clients/generation-guard.js +0 -215
- package/dist/clients/git-guard.js +0 -1136
- package/dist/clients/git-tracked-ignore.js +0 -243
- package/dist/clients/gitleaks-client.js +0 -509
- package/dist/clients/go-client.js +0 -104
- package/dist/clients/govulncheck-client.js +0 -605
- package/dist/clients/gradle-ktfmt-style.js +0 -348
- package/dist/clients/grammar-source.js +0 -465
- package/dist/clients/gzip-stage-write.js +0 -135
- package/dist/clients/hashline-anchor.js +0 -424
- package/dist/clients/hook-budgets.js +0 -76
- package/dist/clients/host-edit-normalize.js +0 -140
- package/dist/clients/host-ports.js +0 -39
- package/dist/clients/indent-retarget.js +0 -154
- package/dist/clients/inline-blocker-dispositions.js +0 -186
- package/dist/clients/install-diagnostics.js +0 -156
- package/dist/clients/installer/index.js +0 -5416
- package/dist/clients/installer/managed-tool-refresh-session.js +0 -58
- package/dist/clients/installer/managed-tool-refresh.js +0 -783
- package/dist/clients/instance-reaper-state.js +0 -7
- package/dist/clients/instance-reaper.js +0 -1137
- package/dist/clients/instance-registry-lock.js +0 -145
- package/dist/clients/instance-registry.js +0 -773
- package/dist/clients/jscpd-client.js +0 -378
- package/dist/clients/json-cache-read.js +0 -65
- package/dist/clients/knip-client.js +0 -788
- package/dist/clients/language-policy.js +0 -252
- package/dist/clients/language-profile.js +0 -361
- package/dist/clients/language-registry.js +0 -603
- package/dist/clients/latency-logger.js +0 -727
- package/dist/clients/lazy-import.js +0 -21
- package/dist/clients/ledger-bounds.js +0 -54
- package/dist/clients/lens-config.js +0 -404
- package/dist/clients/lens-engine.js +0 -358
- package/dist/clients/lens-events.js +0 -125
- package/dist/clients/lens-flag-registry.js +0 -467
- package/dist/clients/lens-map.js +0 -1156
- package/dist/clients/live-bus-emitter.js +0 -74
- package/dist/clients/log-cleanup.js +0 -222
- package/dist/clients/lsp/aggregation.js +0 -178
- package/dist/clients/lsp/cascade-tier.js +0 -421
- package/dist/clients/lsp/client.js +0 -4593
- package/dist/clients/lsp/config.js +0 -691
- package/dist/clients/lsp/content-limits.js +0 -41
- package/dist/clients/lsp/diagnostic-binding.js +0 -225
- package/dist/clients/lsp/document-drift.js +0 -467
- package/dist/clients/lsp/edits.js +0 -1219
- package/dist/clients/lsp/index.js +0 -8305
- package/dist/clients/lsp/inferred-project.js +0 -216
- package/dist/clients/lsp/jvm-runtime.js +0 -298
- package/dist/clients/lsp/language.js +0 -63
- package/dist/clients/lsp/launch.js +0 -746
- package/dist/clients/lsp/lombok.js +0 -158
- package/dist/clients/lsp/path-utils.js +0 -5
- package/dist/clients/lsp/pending-aux-coverage.js +0 -251
- package/dist/clients/lsp/position-encoding.js +0 -61
- package/dist/clients/lsp/ruby-drive-dirs.js +0 -83
- package/dist/clients/lsp/server.js +0 -3290
- package/dist/clients/lsp/session-roots.js +0 -192
- package/dist/clients/lsp/spawn-history.js +0 -17
- package/dist/clients/lsp/sync-kind.js +0 -56
- package/dist/clients/lsp/tsserver-sync.js +0 -332
- package/dist/clients/lsp/wait-policy/capability-snapshot.js +0 -1
- package/dist/clients/lsp/wait-policy/classification.js +0 -85
- package/dist/clients/lsp/wait-policy/index.js +0 -10
- package/dist/clients/lsp/wait-policy/strategies.js +0 -392
- package/dist/clients/lsp/watch-queue.js +0 -61
- package/dist/clients/lsp/workspace-diagnostics-cache.js +0 -639
- package/dist/clients/lsp/workspace-diagnostics-session.js +0 -30
- package/dist/clients/lsp/workspace-sweep-hold.js +0 -184
- package/dist/clients/lsp-budget.js +0 -186
- package/dist/clients/lsp-document-symbols.js +0 -110
- package/dist/clients/lsp-lazy.js +0 -9
- package/dist/clients/lsp-mutation.js +0 -396
- package/dist/clients/lsp-status.js +0 -59
- package/dist/clients/map-with-concurrency.js +0 -40
- package/dist/clients/mcp/analyze.js +0 -420
- package/dist/clients/mcp/host-shim.js +0 -31
- package/dist/clients/mcp/ipc.js +0 -523
- package/dist/clients/mcp/review.js +0 -197
- package/dist/clients/mcp/session.js +0 -412
- package/dist/clients/memory-sampler.js +0 -208
- package/dist/clients/message-end-attribution.js +0 -30
- package/dist/clients/metrics-client.js +0 -107
- package/dist/clients/metrics-history.js +0 -327
- package/dist/clients/middle-man-analysis.js +0 -263
- package/dist/clients/model-provider.js +0 -53
- package/dist/clients/module-report-lsp.js +0 -189
- package/dist/clients/module-report.js +0 -2150
- package/dist/clients/mutating-tool.js +0 -651
- package/dist/clients/mutation-attribution.js +0 -368
- package/dist/clients/mutation-bridge.js +0 -240
- package/dist/clients/ndjson-logger.js +0 -734
- package/dist/clients/observed-mutation-sources.js +0 -101
- package/dist/clients/observed-mutation.js +0 -1253
- package/dist/clients/oldtext-autopatch.js +0 -128
- package/dist/clients/opaque-mutation-scan.js +0 -496
- package/dist/clients/opengrep-client.js +0 -333
- package/dist/clients/opengrep-config.js +0 -76
- package/dist/clients/package-manager.js +0 -607
- package/dist/clients/package-root.js +0 -38
- package/dist/clients/partial-edit-apply.js +0 -439
- package/dist/clients/path-attribution-telemetry.js +0 -43
- package/dist/clients/path-keyed-map.js +0 -108
- package/dist/clients/path-utils.js +0 -1244
- package/dist/clients/performance-report.js +0 -331
- package/dist/clients/persist-debounce.js +0 -70
- package/dist/clients/persistent-reverify.js +0 -271
- package/dist/clients/php-cs-fixer-config.js +0 -119
- package/dist/clients/pipeline.js +0 -1480
- package/dist/clients/post-autofix-notice.js +0 -37
- package/dist/clients/print-mode.js +0 -21
- package/dist/clients/probe-home-state.js +0 -228
- package/dist/clients/process-bridge.js +0 -66
- package/dist/clients/process-singletons.js +0 -210
- package/dist/clients/process-snapshot.js +0 -68
- package/dist/clients/project-changes.js +0 -181
- package/dist/clients/project-conventions.js +0 -171
- package/dist/clients/project-diagnostics/cache.js +0 -137
- package/dist/clients/project-diagnostics/extractors.js +0 -109
- package/dist/clients/project-diagnostics/fresh-fetch.js +0 -668
- package/dist/clients/project-diagnostics/runner-adapters/call-graph-impact.js +0 -118
- package/dist/clients/project-diagnostics/runner-adapters/dead-code.js +0 -47
- package/dist/clients/project-diagnostics/runner-adapters/gitleaks.js +0 -40
- package/dist/clients/project-diagnostics/runner-adapters/govulncheck.js +0 -34
- package/dist/clients/project-diagnostics/runner-adapters/jscpd.js +0 -38
- package/dist/clients/project-diagnostics/runner-adapters/knip.js +0 -47
- package/dist/clients/project-diagnostics/runner-adapters/madge.js +0 -48
- package/dist/clients/project-diagnostics/runner-adapters/opengrep.js +0 -40
- package/dist/clients/project-diagnostics/runner-adapters/runner-findings.js +0 -127
- package/dist/clients/project-diagnostics/runner-adapters/trivy.js +0 -81
- package/dist/clients/project-diagnostics/scanner.js +0 -520
- package/dist/clients/project-diagnostics/types.js +0 -1
- package/dist/clients/project-lens-config.js +0 -807
- package/dist/clients/project-report.js +0 -701
- package/dist/clients/project-scale.js +0 -237
- package/dist/clients/project-scan-policy.js +0 -11
- package/dist/clients/project-snapshot-fingerprint.js +0 -48
- package/dist/clients/project-snapshot-persist-worker.js +0 -20
- package/dist/clients/project-snapshot.js +0 -1653
- package/dist/clients/project-trust.js +0 -181
- package/dist/clients/python-environment.js +0 -217
- package/dist/clients/python-provenance.js +0 -639
- package/dist/clients/quiet-window-config.js +0 -47
- package/dist/clients/quiet-window.js +0 -236
- package/dist/clients/read-bridge.js +0 -139
- package/dist/clients/read-expansion.js +0 -266
- package/dist/clients/read-guard-logger.js +0 -251
- package/dist/clients/read-guard-tool-lines.js +0 -1306
- package/dist/clients/read-guard.js +0 -1561
- package/dist/clients/recent-touches.js +0 -240
- package/dist/clients/redact/secrets.js +0 -449
- package/dist/clients/resource-sampler.js +0 -628
- package/dist/clients/reverse-deps.js +0 -270
- package/dist/clients/review-graph/builder.js +0 -5126
- package/dist/clients/review-graph/format.js +0 -33
- package/dist/clients/review-graph/git-identity.js +0 -163
- package/dist/clients/review-graph/import-resolvers.js +0 -481
- package/dist/clients/review-graph/persist-worker.js +0 -10
- package/dist/clients/review-graph/query.js +0 -244
- package/dist/clients/review-graph/revision-drift.js +0 -21
- package/dist/clients/review-graph/service.js +0 -96
- package/dist/clients/review-graph/shared-extraction-ir.js +0 -82
- package/dist/clients/review-graph/symbol-id.js +0 -103
- package/dist/clients/review-graph/tsconfig-paths.js +0 -299
- package/dist/clients/review-graph/types.js +0 -1
- package/dist/clients/review-graph/workspace-modules.js +0 -449
- package/dist/clients/review-graph-logger.js +0 -81
- package/dist/clients/ruff-client.js +0 -179
- package/dist/clients/rules-scanner.js +0 -131
- package/dist/clients/run-duration.js +0 -55
- package/dist/clients/runtime-agent-end.js +0 -746
- package/dist/clients/runtime-config.js +0 -77
- package/dist/clients/runtime-context.js +0 -211
- package/dist/clients/runtime-coordinator.js +0 -1324
- package/dist/clients/runtime-session.js +0 -2485
- package/dist/clients/runtime-tool-call.js +0 -1295
- package/dist/clients/runtime-tool-result.js +0 -2049
- package/dist/clients/runtime-turn.js +0 -3767
- package/dist/clients/rust-client.js +0 -97
- package/dist/clients/safe-spawn.js +0 -2357
- package/dist/clients/sanitize.js +0 -286
- package/dist/clients/scan-utils.js +0 -25
- package/dist/clients/scratch-tree-policy.js +0 -165
- package/dist/clients/search-read-registration.js +0 -94
- package/dist/clients/secret-findings.js +0 -114
- package/dist/clients/security-scan-client.js +0 -352
- package/dist/clients/session-event-guard.js +0 -297
- package/dist/clients/session-lifecycle.js +0 -484
- package/dist/clients/session-start-observability.js +0 -94
- package/dist/clients/session-state-store.js +0 -101
- package/dist/clients/session-summary.js +0 -15
- package/dist/clients/sessionstart-logger.js +0 -27
- package/dist/clients/sg-runner.js +0 -876
- package/dist/clients/sgconfig.js +0 -347
- package/dist/clients/shared-checkout-guard.js +0 -338
- package/dist/clients/single-flight.js +0 -158
- package/dist/clients/situational-tool-telemetry.js +0 -108
- package/dist/clients/skills-resolver.js +0 -141
- package/dist/clients/slow-fs.js +0 -138
- package/dist/clients/smells-rollup.js +0 -231
- package/dist/clients/source-filter.js +0 -596
- package/dist/clients/source-walker.js +0 -211
- package/dist/clients/spawn-output-cap.js +0 -120
- package/dist/clients/spawn-timeout-cooldown.js +0 -110
- package/dist/clients/stale-marker.js +0 -17
- package/dist/clients/startup-scan.js +0 -400
- package/dist/clients/startup-timing.js +0 -130
- package/dist/clients/string-utils.js +0 -33
- package/dist/clients/subagent-mode.js +0 -111
- package/dist/clients/symbol-containment.js +0 -24
- package/dist/clients/symbol-types.js +0 -5
- package/dist/clients/test-runner-client.js +0 -2507
- package/dist/clients/test-runner-delivery.js +0 -287
- package/dist/clients/todo-scanner.js +0 -229
- package/dist/clients/tool-agreement.js +0 -423
- package/dist/clients/tool-config.js +0 -249
- package/dist/clients/tool-cwd.js +0 -270
- package/dist/clients/tool-definition.js +0 -47
- package/dist/clients/tool-event.js +0 -105
- package/dist/clients/tool-policy.js +0 -2755
- package/dist/clients/tool-probe.js +0 -53
- package/dist/clients/tool-render.js +0 -156
- package/dist/clients/tool-set-policy.js +0 -118
- package/dist/clients/tree-sitter-cache.js +0 -364
- package/dist/clients/tree-sitter-client.js +0 -4195
- package/dist/clients/tree-sitter-logger.js +0 -100
- package/dist/clients/tree-sitter-navigator.js +0 -269
- package/dist/clients/tree-sitter-query-loader.js +0 -569
- package/dist/clients/tree-sitter-shared.js +0 -158
- package/dist/clients/tree-sitter-symbol-extractor.js +0 -1265
- package/dist/clients/trivy-client.js +0 -467
- package/dist/clients/tui-fit.js +0 -50
- package/dist/clients/turn-context.js +0 -52
- package/dist/clients/turn-end/lane.js +0 -51
- package/dist/clients/turn-end/lanes/govulncheck.js +0 -112
- package/dist/clients/turn-end/lanes/secrets.js +0 -204
- package/dist/clients/turn-summary-render.js +0 -72
- package/dist/clients/turn-summary.js +0 -132
- package/dist/clients/typos-config.js +0 -29
- package/dist/clients/user-notify.js +0 -51
- package/dist/clients/vanished-instance-marker.js +0 -57
- package/dist/clients/warm-attach.js +0 -305
- package/dist/clients/widget-state.js +0 -1808
- package/dist/clients/word-index-logger.js +0 -49
- package/dist/clients/word-index-store.js +0 -459
- package/dist/clients/word-index.js +0 -2080
- package/dist/clients/workspace-topology.js +0 -443
- package/dist/clients/write-ordering-guard.js +0 -65
- package/dist/clients/zizmor-config.js +0 -340
- package/dist/i18n.js +0 -69
- package/dist/mcp/build-staleness.js +0 -124
- package/dist/scripts/lib/process-scan.mjs +0 -583
- package/dist/scripts/lib/skills-predicate.mjs +0 -129
- package/dist/scripts/lib/web-tree-sitter-dir.mjs +0 -123
- package/dist/tools/activate-tools.js +0 -87
- package/dist/tools/ast-grep-outline.js +0 -137
- package/dist/tools/ast-grep-replace.js +0 -244
- package/dist/tools/ast-grep-search.js +0 -762
- package/dist/tools/effective-config.js +0 -90
- package/dist/tools/lens-diagnostic-mark.js +0 -375
- package/dist/tools/lens-diagnostics.js +0 -2571
- package/dist/tools/lsp-diagnostics.js +0 -1745
- package/dist/tools/lsp-navigation.js +0 -1367
- package/dist/tools/lsp-structured-output.js +0 -294
- package/dist/tools/module-report.js +0 -382
- package/dist/tools/project-report.js +0 -86
- package/dist/tools/render-compact.js +0 -374
- package/dist/tools/scan-progress.js +0 -53
- package/dist/tools/shared.js +0 -29
- package/dist/tools/symbol-search.js +0 -155
|
@@ -1,762 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ast_grep_search tool definition
|
|
3
|
-
*
|
|
4
|
-
* Extracted from index.ts for maintainability.
|
|
5
|
-
*/
|
|
6
|
-
import { Type } from "../clients/deps/typebox.js";
|
|
7
|
-
import { astGrepRemediationHint, classifyAstGrepError, logAstGrepToolEvent, } from "../clients/ast-grep-tool-logger.js";
|
|
8
|
-
import { hasStructuralIntent, synthesizeRule, } from "../clients/ast-grep-yaml-synth.js";
|
|
9
|
-
import { isAtOrAboveHomeDir } from "../clients/path-utils.js";
|
|
10
|
-
import { compactRenderResult } from "./render-compact.js";
|
|
11
|
-
import { combineAbortSignals } from "../clients/deadline-utils.js";
|
|
12
|
-
import { LANGUAGES } from "./shared.js";
|
|
13
|
-
/**
|
|
14
|
-
* Build the agent-facing error text, appending a remediation hint derived from
|
|
15
|
-
* the same classification we log. The two curated spawn errors return null from
|
|
16
|
-
* the hint map (their message already carries guidance), so this never doubles
|
|
17
|
-
* up — it only adds value for the raw-stderr categories (#ast-grep tool errors).
|
|
18
|
-
*/
|
|
19
|
-
function errorTextWithHint(raw) {
|
|
20
|
-
const hint = astGrepRemediationHint(classifyAstGrepError(raw));
|
|
21
|
-
return hint ? `Error: ${raw}\n\n${hint}` : `Error: ${raw}`;
|
|
22
|
-
}
|
|
23
|
-
export function _telemetryErrorForTest(raw) {
|
|
24
|
-
if (!raw)
|
|
25
|
-
return undefined;
|
|
26
|
-
return raw.replace(/\0/g, "\\0").slice(0, 2_000);
|
|
27
|
-
}
|
|
28
|
-
export function _telemetryClassificationErrorForTest(raw) {
|
|
29
|
-
return raw?.replace(/\0/g, "");
|
|
30
|
-
}
|
|
31
|
-
/** Map matches to the 1-based line spans shown, for read-guard registration (#169). */
|
|
32
|
-
function toSearchReads(matches) {
|
|
33
|
-
const out = [];
|
|
34
|
-
for (const m of matches) {
|
|
35
|
-
const span = toLineSpan(m);
|
|
36
|
-
if (!span)
|
|
37
|
-
continue;
|
|
38
|
-
out.push({
|
|
39
|
-
file: span.file,
|
|
40
|
-
startLine: span.startLine,
|
|
41
|
-
endLine: span.endLine,
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
return out;
|
|
45
|
-
}
|
|
46
|
-
// Default and ceilings for agent-facing search inputs. `maxMatches` lets a caller
|
|
47
|
-
// trade volume for completeness within these bounds (the default preserves the
|
|
48
|
-
// historical page size). Explicit path lists are capped like the other bounded
|
|
49
|
-
// multi-file tools, while a single directory path remains a valid project scope.
|
|
50
|
-
const DEFAULT_PAGE_SIZE = 50;
|
|
51
|
-
const MAX_PAGE_SIZE = 200;
|
|
52
|
-
const MAX_PATHS = 200;
|
|
53
|
-
const AST_GREP_SEARCH_TIMEOUT_MS = 30_000;
|
|
54
|
-
/**
|
|
55
|
-
* Compact, file-grouped rendering for high-volume searches (refs #345). Instead
|
|
56
|
-
* of each match's full body, emit one line per file with its 1-based
|
|
57
|
-
* `L<line>:<col>` locations — a distribution view that drills in via the read
|
|
58
|
-
* slices already surfaced in `details.matchLocations`/`searchReads`.
|
|
59
|
-
*/
|
|
60
|
-
function formatGroupedByFile(matches) {
|
|
61
|
-
const byFile = new Map();
|
|
62
|
-
for (const m of matches) {
|
|
63
|
-
if (!m.file)
|
|
64
|
-
continue;
|
|
65
|
-
const list = byFile.get(m.file);
|
|
66
|
-
if (list)
|
|
67
|
-
list.push(m);
|
|
68
|
-
else
|
|
69
|
-
byFile.set(m.file, [m]);
|
|
70
|
-
}
|
|
71
|
-
const total = matches.length;
|
|
72
|
-
const fileCount = byFile.size;
|
|
73
|
-
const lines = [
|
|
74
|
-
`${fileCount} file${fileCount === 1 ? "" : "s"}, ${total} match${total === 1 ? "" : "es"}:`,
|
|
75
|
-
];
|
|
76
|
-
for (const [file, group] of byFile) {
|
|
77
|
-
const locs = group
|
|
78
|
-
.map((m) => {
|
|
79
|
-
const line = (m.range?.start?.line ?? 0) + 1;
|
|
80
|
-
const col = (m.range?.start?.column ?? 0) + 1;
|
|
81
|
-
return `L${line}:${col}`;
|
|
82
|
-
})
|
|
83
|
-
.join(", ");
|
|
84
|
-
lines.push(`${file} (${group.length}): ${locs}`);
|
|
85
|
-
}
|
|
86
|
-
return lines.join("\n");
|
|
87
|
-
}
|
|
88
|
-
const DEFAULT_READ_SLICE_MARGIN = 3;
|
|
89
|
-
const MAX_READ_SLICE_MARGIN = 20;
|
|
90
|
-
const MAX_RAW_RULE_CHARS = 100_000;
|
|
91
|
-
function rawRuleValidationError(rule) {
|
|
92
|
-
if (rule === undefined)
|
|
93
|
-
return null;
|
|
94
|
-
if (rule.includes("\0"))
|
|
95
|
-
return "rule contains a NUL byte";
|
|
96
|
-
if (rule.length > MAX_RAW_RULE_CHARS)
|
|
97
|
-
return "rule is too long";
|
|
98
|
-
return null;
|
|
99
|
-
}
|
|
100
|
-
function patternValidationError(pattern) {
|
|
101
|
-
if (pattern.includes("\0"))
|
|
102
|
-
return "pattern contains a NUL byte";
|
|
103
|
-
if (pattern.length > 4_000)
|
|
104
|
-
return "pattern is too long";
|
|
105
|
-
return null;
|
|
106
|
-
}
|
|
107
|
-
function toLineSpan(match) {
|
|
108
|
-
const start = match.range?.start?.line; // ast-grep ranges are 0-based
|
|
109
|
-
if (!match.file || typeof start !== "number")
|
|
110
|
-
return null;
|
|
111
|
-
const end = match.range?.end?.line;
|
|
112
|
-
return {
|
|
113
|
-
file: match.file,
|
|
114
|
-
startLine: start + 1,
|
|
115
|
-
endLine: (typeof end === "number" ? end : start) + 1,
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
function toMatchLocations(matches, contextLines) {
|
|
119
|
-
const margin = typeof contextLines === "number" && Number.isFinite(contextLines)
|
|
120
|
-
? Math.min(MAX_READ_SLICE_MARGIN, Math.max(0, Math.floor(contextLines)))
|
|
121
|
-
: DEFAULT_READ_SLICE_MARGIN;
|
|
122
|
-
const out = [];
|
|
123
|
-
for (const match of matches) {
|
|
124
|
-
const span = toLineSpan(match);
|
|
125
|
-
if (!span)
|
|
126
|
-
continue;
|
|
127
|
-
const offset = Math.max(1, span.startLine - margin);
|
|
128
|
-
out.push({
|
|
129
|
-
file: span.file,
|
|
130
|
-
line: span.startLine,
|
|
131
|
-
endLine: span.endLine,
|
|
132
|
-
readSlice: {
|
|
133
|
-
path: span.file,
|
|
134
|
-
offset,
|
|
135
|
-
limit: span.endLine - offset + 1 + margin,
|
|
136
|
-
},
|
|
137
|
-
});
|
|
138
|
-
}
|
|
139
|
-
return out;
|
|
140
|
-
}
|
|
141
|
-
function suggestedDump(lang) {
|
|
142
|
-
return {
|
|
143
|
-
tool: "ast_grep_search",
|
|
144
|
-
mode: "dump",
|
|
145
|
-
lang,
|
|
146
|
-
note: "Run ast_grep_search with dump=true on a small representative source snippet (not a whole file) to inspect AST node kinds before retrying the search.",
|
|
147
|
-
};
|
|
148
|
-
}
|
|
149
|
-
function lineCount(value) {
|
|
150
|
-
if (!value)
|
|
151
|
-
return 0;
|
|
152
|
-
let lines = 1;
|
|
153
|
-
for (let i = 0; i < value.length; i++) {
|
|
154
|
-
if (value.charCodeAt(i) === 10)
|
|
155
|
-
lines++;
|
|
156
|
-
}
|
|
157
|
-
return lines;
|
|
158
|
-
}
|
|
159
|
-
function looksLikeRuleYamlOrPlainText(pattern) {
|
|
160
|
-
const text = pattern.trim();
|
|
161
|
-
if (!text)
|
|
162
|
-
return true;
|
|
163
|
-
const lower = text.toLowerCase();
|
|
164
|
-
if (/(^|\n)\s*(id|language|rule|rules|kind|pattern|message|severity)\s*:/.test(lower)) {
|
|
165
|
-
return true;
|
|
166
|
-
}
|
|
167
|
-
if (/\b(id|language|rule|rules|kind|pattern|message|severity)\s*:\s*[a-z0-9_-]+/i.test(text)) {
|
|
168
|
-
return true;
|
|
169
|
-
}
|
|
170
|
-
if (/^[-*]\s+/.test(text))
|
|
171
|
-
return true;
|
|
172
|
-
const hasAstSignals = /[$(){}[\].;:'"`]/.test(text);
|
|
173
|
-
const hasWhitespace = /\s/.test(text);
|
|
174
|
-
if (hasWhitespace && !hasAstSignals)
|
|
175
|
-
return true;
|
|
176
|
-
return false;
|
|
177
|
-
}
|
|
178
|
-
/**
|
|
179
|
-
* Detect common mistakes in ast-grep patterns and return a hint.
|
|
180
|
-
* Helps the LLM self-correct when a search returns zero matches.
|
|
181
|
-
*/
|
|
182
|
-
function getPatternHint(pattern, lang, selector) {
|
|
183
|
-
const src = pattern.trim();
|
|
184
|
-
if (selector) {
|
|
185
|
-
return `Hint: selector=${JSON.stringify(selector)} narrows the AST node kind searched; it does not extract fields from matches. Retry once without selector, or use a selector that is the outer node kind you want to match.`;
|
|
186
|
-
}
|
|
187
|
-
// --- regex misuse ---
|
|
188
|
-
if (/\\[wWdDsSbB]/.test(src)) {
|
|
189
|
-
return 'Hint: "\\w", "\\d", "\\s", "\\b" are regex escapes. ast-grep matches AST nodes, not text — use $VAR for identifiers, $$$ for node lists, or switch to grep for text search.';
|
|
190
|
-
}
|
|
191
|
-
if (/\[[a-zA-Z0-9]-[a-zA-Z0-9]\]/.test(src)) {
|
|
192
|
-
return 'Hint: "[a-z]" and similar character classes are regex, not AST. Use $VAR to match any identifier, or switch to grep for text search.';
|
|
193
|
-
}
|
|
194
|
-
if (!src.includes("$") && /\w\.[*+]/.test(src)) {
|
|
195
|
-
return 'Hint: ".*" and ".+" are regex wildcards. In ast-grep use $$$ for multiple AST nodes and $VAR for a single node. For text patterns, switch to grep.';
|
|
196
|
-
}
|
|
197
|
-
if (/^[-\w.*]+\|[-\w.*|]+$/.test(src)) {
|
|
198
|
-
return 'Hint: "|" is regex alternation and does NOT work in ast-grep patterns. Options: (a) fire one ast_grep_search per alternative, or (b) switch to grep with a regex pattern like "foo|bar".';
|
|
199
|
-
}
|
|
200
|
-
// --- language-specific mistakes ---
|
|
201
|
-
if (lang === "python") {
|
|
202
|
-
if ((src.startsWith("def ") || src.startsWith("async def ")) &&
|
|
203
|
-
src.endsWith(":")) {
|
|
204
|
-
return `Hint: Remove trailing colon from Python patterns. Try: "${src.slice(0, -1)}"`;
|
|
205
|
-
}
|
|
206
|
-
if (src.startsWith("class ") && src.endsWith(":")) {
|
|
207
|
-
return `Hint: Remove trailing colon from class patterns. Try: "${src.slice(0, -1)}"`;
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
if (["javascript", "typescript", "tsx"].includes(lang)) {
|
|
211
|
-
if (/^(export\s+)?(async\s+)?function\s+\$[A-Z_]+\s*$/i.test(src)) {
|
|
212
|
-
return 'Hint: Function patterns need params and body. Try "function $NAME($$$) { $$$ }"';
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
if (lang === "go") {
|
|
216
|
-
if (/^func\s+\$[A-Z_]+\s*$/i.test(src)) {
|
|
217
|
-
return 'Hint: Go function patterns need params and body. Try "func $NAME($$$) { $$$ }"';
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
if (lang === "rust") {
|
|
221
|
-
if (/^fn\s+\$[A-Z_]+\s*$/i.test(src)) {
|
|
222
|
-
return 'Hint: Rust fn patterns need params and body. Try "fn $NAME($$$) { $$$ }"';
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
return "Hint: No matches. Retry once with a smaller valid AST pattern scoped to the same paths (for example a call like `foo($$$ARGS)`, an import statement, or `function $NAME($$$ARGS) { $$$BODY }`). If you're actually looking for a name/usage rather than a structural pattern, prefer symbol_search (ranked identifier search) or module_report (file outline) over another AST retry; lsp_navigation findReferences finds exact call sites once you have a definition. If that also fails, use grep for text search, or ast_grep_search with dump=true on a small representative snippet to inspect node kinds.";
|
|
226
|
-
}
|
|
227
|
-
/** One-session response for callers holding a pre-fold tool name. */
|
|
228
|
-
export function astGrepDumpCompatibilityResult(params, surface) {
|
|
229
|
-
return {
|
|
230
|
-
content: [
|
|
231
|
-
{
|
|
232
|
-
type: "text",
|
|
233
|
-
text: `The ast_grep_dump tool was retired. Call ${surface === "mcp" ? "pilens_" : ""}ast_grep_search with dump=true and put the snippet in pattern instead.`,
|
|
234
|
-
},
|
|
235
|
-
],
|
|
236
|
-
isError: true,
|
|
237
|
-
details: {
|
|
238
|
-
compatibility: "ast_grep_dump -> ast_grep_search",
|
|
239
|
-
call: {
|
|
240
|
-
tool: surface === "mcp" ? "pilens_ast_grep_search" : "ast_grep_search",
|
|
241
|
-
arguments: {
|
|
242
|
-
dump: true,
|
|
243
|
-
pattern: params.source,
|
|
244
|
-
lang: params.lang,
|
|
245
|
-
},
|
|
246
|
-
},
|
|
247
|
-
},
|
|
248
|
-
};
|
|
249
|
-
}
|
|
250
|
-
export function createAstGrepSearchTool(astGrepClient) {
|
|
251
|
-
return {
|
|
252
|
-
name: "ast_grep_search",
|
|
253
|
-
label: "AST Search",
|
|
254
|
-
description: "Search source by AST structure rather than text. Example: find calls with `console.log($MSG)`.",
|
|
255
|
-
promptSnippet: "Search source by AST structure",
|
|
256
|
-
renderResult: compactRenderResult(({ details, isError, text }) => {
|
|
257
|
-
if (details?.validateOnly) {
|
|
258
|
-
const mode = details.mode ?? "pattern";
|
|
259
|
-
return details.valid
|
|
260
|
-
? `ast_grep_search — valid ${mode}`
|
|
261
|
-
: `ast_grep_search — invalid ${mode}`;
|
|
262
|
-
}
|
|
263
|
-
if (isError) {
|
|
264
|
-
return `ast_grep_search — ${text.split("\n")[0] ?? "error"}`;
|
|
265
|
-
}
|
|
266
|
-
const count = details?.matchCount ?? 0;
|
|
267
|
-
const total = details?.totalMatches;
|
|
268
|
-
const ofTotal = typeof total === "number" && total > count ? ` of ${total}` : "";
|
|
269
|
-
const applied = details?.applied ? " (applied)" : "";
|
|
270
|
-
return `ast_grep_search — ${count}${ofTotal} match${count === 1 && !ofTotal ? "" : "es"}${applied}`;
|
|
271
|
-
}),
|
|
272
|
-
parameters: Type.Object({
|
|
273
|
-
dump: Type.Optional(Type.Boolean()),
|
|
274
|
-
pattern: Type.Optional(Type.String({ description: "AST pattern." })),
|
|
275
|
-
lang: Type.String({
|
|
276
|
-
enum: [...LANGUAGES],
|
|
277
|
-
description: "Target language",
|
|
278
|
-
}),
|
|
279
|
-
paths: Type.Optional(Type.Array(Type.String(), {
|
|
280
|
-
maxItems: MAX_PATHS,
|
|
281
|
-
description: "Files or directories to search.",
|
|
282
|
-
})),
|
|
283
|
-
selector: Type.Optional(Type.String({
|
|
284
|
-
description: "AST node kind filter.",
|
|
285
|
-
})),
|
|
286
|
-
context: Type.Optional(Type.Number({
|
|
287
|
-
description: "Context lines around matches.",
|
|
288
|
-
})),
|
|
289
|
-
nodeKind: Type.Optional(Type.String({
|
|
290
|
-
description: "AST node kind without a pattern.",
|
|
291
|
-
})),
|
|
292
|
-
insideKind: Type.Optional(Type.String({
|
|
293
|
-
description: "Ancestor AST node kind filter.",
|
|
294
|
-
})),
|
|
295
|
-
hasKind: Type.Optional(Type.String({
|
|
296
|
-
description: "Immediate-child AST node kind filter.",
|
|
297
|
-
})),
|
|
298
|
-
hasDescendantKind: Type.Optional(Type.String({
|
|
299
|
-
description: "Recursive descendant AST node kind filter.",
|
|
300
|
-
})),
|
|
301
|
-
follows: Type.Optional(Type.String({
|
|
302
|
-
description: "Preceding sibling pattern filter.",
|
|
303
|
-
})),
|
|
304
|
-
precedes: Type.Optional(Type.String({
|
|
305
|
-
description: "Following sibling pattern filter.",
|
|
306
|
-
})),
|
|
307
|
-
rule: Type.Optional(Type.String({
|
|
308
|
-
description: "Raw ast-grep YAML rule.",
|
|
309
|
-
})),
|
|
310
|
-
skip: Type.Optional(Type.Number({
|
|
311
|
-
description: "Matches to skip for pagination.",
|
|
312
|
-
})),
|
|
313
|
-
maxMatches: Type.Optional(Type.Number({
|
|
314
|
-
description: "Maximum matches to return.",
|
|
315
|
-
})),
|
|
316
|
-
groupByFile: Type.Optional(Type.Boolean({
|
|
317
|
-
description: "Group matches by file.",
|
|
318
|
-
})),
|
|
319
|
-
strictness: Type.Optional(Type.String({
|
|
320
|
-
enum: ["smart", "relaxed", "ast", "cst", "signature", "template"],
|
|
321
|
-
description: "Pattern matching strictness.",
|
|
322
|
-
})),
|
|
323
|
-
validateOnly: Type.Optional(Type.Boolean({
|
|
324
|
-
description: "Validate without scanning.",
|
|
325
|
-
})),
|
|
326
|
-
}),
|
|
327
|
-
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
328
|
-
// Escape aborts the turn via ctx.signal; the positional signal is the
|
|
329
|
-
// tool-call one. Honor both so a broad search cancels on Escape.
|
|
330
|
-
const abortSignal = combineAbortSignals(_signal, ctx.signal);
|
|
331
|
-
const startedAt = Date.now();
|
|
332
|
-
const deadlineAt = startedAt + AST_GREP_SEARCH_TIMEOUT_MS;
|
|
333
|
-
const { paths, nodeKind, selector, context, skip, maxMatches, groupByFile, strictness, rule, insideKind, hasKind, hasDescendantKind, follows, precedes, validateOnly, dump, } = params;
|
|
334
|
-
const pattern = typeof params.pattern === "string" ? params.pattern : "";
|
|
335
|
-
const rawLang = typeof params.lang === "string" ? params.lang : "";
|
|
336
|
-
const normalizedNodeKind = typeof nodeKind === "string" ? nodeKind.trim() : "";
|
|
337
|
-
const skipOffset = Math.max(0, Math.floor(skip ?? 0));
|
|
338
|
-
const lang = rawLang.replace(/^"|"$/g, "");
|
|
339
|
-
const searchPathsCount = paths?.length ?? 1;
|
|
340
|
-
const executionOptions = { signal: abortSignal, deadlineAt };
|
|
341
|
-
const dumpMode = dump === true;
|
|
342
|
-
function logOutcome(outcome, details = {}) {
|
|
343
|
-
try {
|
|
344
|
-
const errorRaw = _telemetryErrorForTest(details.errorRaw);
|
|
345
|
-
const classificationError = _telemetryClassificationErrorForTest(details.errorRaw);
|
|
346
|
-
logAstGrepToolEvent({
|
|
347
|
-
tool: "ast_grep_search",
|
|
348
|
-
lang,
|
|
349
|
-
pattern,
|
|
350
|
-
patternLineCount: lineCount(pattern),
|
|
351
|
-
pathsCount: searchPathsCount,
|
|
352
|
-
outcome,
|
|
353
|
-
errorKind: outcome === "error"
|
|
354
|
-
? classifyAstGrepError(classificationError)
|
|
355
|
-
: undefined,
|
|
356
|
-
errorRaw,
|
|
357
|
-
matchCount: details.matchCount ?? 0,
|
|
358
|
-
truncated: details.truncated ?? false,
|
|
359
|
-
durationMs: Date.now() - startedAt,
|
|
360
|
-
});
|
|
361
|
-
}
|
|
362
|
-
catch (err) {
|
|
363
|
-
// Telemetry must never break the tool path. Surface failures through
|
|
364
|
-
// Node's warning channel instead of console output.
|
|
365
|
-
try {
|
|
366
|
-
process.emitWarning(`ast_grep_search telemetry failed: ${err}`, {
|
|
367
|
-
code: "PI_LENS_AST_GREP_SEARCH_TELEMETRY_FAILED",
|
|
368
|
-
});
|
|
369
|
-
}
|
|
370
|
-
catch {
|
|
371
|
-
void err;
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
function abortError() {
|
|
376
|
-
logOutcome("error", { errorRaw: "operation aborted" });
|
|
377
|
-
return {
|
|
378
|
-
content: [
|
|
379
|
-
{ type: "text", text: "Error: operation aborted" },
|
|
380
|
-
],
|
|
381
|
-
isError: true,
|
|
382
|
-
details: {},
|
|
383
|
-
};
|
|
384
|
-
}
|
|
385
|
-
try {
|
|
386
|
-
const rawRule = typeof rule === "string" ? rule : undefined;
|
|
387
|
-
const hasRawRule = Boolean(rawRule?.trim());
|
|
388
|
-
const hasPattern = Boolean(pattern.trim());
|
|
389
|
-
const hasNodeKind = normalizedNodeKind.length > 0;
|
|
390
|
-
const rawPaths = params.paths;
|
|
391
|
-
if (rawPaths !== undefined &&
|
|
392
|
-
(!Array.isArray(rawPaths) ||
|
|
393
|
-
rawPaths.length > MAX_PATHS ||
|
|
394
|
-
rawPaths.some((value) => typeof value !== "string"))) {
|
|
395
|
-
const errorRaw = `paths must contain at most ${MAX_PATHS} string entries`;
|
|
396
|
-
logOutcome("error", { errorRaw });
|
|
397
|
-
return {
|
|
398
|
-
content: [{ type: "text", text: `Error: ${errorRaw}` }],
|
|
399
|
-
isError: true,
|
|
400
|
-
details: {},
|
|
401
|
-
};
|
|
402
|
-
}
|
|
403
|
-
const rawRuleError = rawRuleValidationError(rawRule);
|
|
404
|
-
if (rawRuleError) {
|
|
405
|
-
logOutcome("error", { errorRaw: rawRuleError });
|
|
406
|
-
return {
|
|
407
|
-
content: [
|
|
408
|
-
{ type: "text", text: `Error: ${rawRuleError}` },
|
|
409
|
-
],
|
|
410
|
-
isError: true,
|
|
411
|
-
details: {},
|
|
412
|
-
};
|
|
413
|
-
}
|
|
414
|
-
if (!dumpMode && !hasPattern && !hasRawRule && !hasNodeKind) {
|
|
415
|
-
logOutcome("error", {
|
|
416
|
-
errorRaw: "pattern is required unless rule or nodeKind is provided",
|
|
417
|
-
});
|
|
418
|
-
return {
|
|
419
|
-
content: [
|
|
420
|
-
{
|
|
421
|
-
type: "text",
|
|
422
|
-
text: "Error: pattern is required unless rule or nodeKind is provided",
|
|
423
|
-
},
|
|
424
|
-
],
|
|
425
|
-
isError: true,
|
|
426
|
-
details: {},
|
|
427
|
-
};
|
|
428
|
-
}
|
|
429
|
-
const patternError = patternValidationError(pattern);
|
|
430
|
-
if (pattern.trim() && patternError) {
|
|
431
|
-
logOutcome("error", { errorRaw: patternError });
|
|
432
|
-
return {
|
|
433
|
-
content: [
|
|
434
|
-
{ type: "text", text: `Error: ${patternError}` },
|
|
435
|
-
],
|
|
436
|
-
isError: true,
|
|
437
|
-
details: {},
|
|
438
|
-
};
|
|
439
|
-
}
|
|
440
|
-
if (!lang.trim()) {
|
|
441
|
-
logOutcome("error", { errorRaw: "lang is required" });
|
|
442
|
-
return {
|
|
443
|
-
content: [
|
|
444
|
-
{ type: "text", text: "Error: lang is required" },
|
|
445
|
-
],
|
|
446
|
-
isError: true,
|
|
447
|
-
details: {},
|
|
448
|
-
};
|
|
449
|
-
}
|
|
450
|
-
if (abortSignal?.aborted)
|
|
451
|
-
return abortError();
|
|
452
|
-
if (!(await astGrepClient.ensureAvailable())) {
|
|
453
|
-
logOutcome("error", {
|
|
454
|
-
errorRaw: "ast-grep CLI not found",
|
|
455
|
-
});
|
|
456
|
-
return {
|
|
457
|
-
content: [
|
|
458
|
-
{
|
|
459
|
-
type: "text",
|
|
460
|
-
text: "ast-grep CLI not found. Install: npm i -D @ast-grep/cli",
|
|
461
|
-
},
|
|
462
|
-
],
|
|
463
|
-
isError: true,
|
|
464
|
-
details: {},
|
|
465
|
-
};
|
|
466
|
-
}
|
|
467
|
-
if (abortSignal?.aborted)
|
|
468
|
-
return abortError();
|
|
469
|
-
if (dumpMode) {
|
|
470
|
-
if (!pattern.trim()) {
|
|
471
|
-
const errorRaw = "source is required when dump is true";
|
|
472
|
-
logOutcome("error", { errorRaw });
|
|
473
|
-
return {
|
|
474
|
-
content: [{ type: "text", text: `Error: ${errorRaw}` }],
|
|
475
|
-
isError: true,
|
|
476
|
-
details: { mode: "dump", lang },
|
|
477
|
-
};
|
|
478
|
-
}
|
|
479
|
-
const result = await astGrepClient.dumpAst(pattern, lang);
|
|
480
|
-
if (result.error) {
|
|
481
|
-
logOutcome("error", { errorRaw: result.error });
|
|
482
|
-
return {
|
|
483
|
-
content: [
|
|
484
|
-
{ type: "text", text: `Error: ${result.error}` },
|
|
485
|
-
],
|
|
486
|
-
isError: true,
|
|
487
|
-
details: { mode: "dump", lang },
|
|
488
|
-
};
|
|
489
|
-
}
|
|
490
|
-
const output = result.output ?? "";
|
|
491
|
-
logOutcome("success", { matchCount: lineCount(output) });
|
|
492
|
-
return {
|
|
493
|
-
content: [{ type: "text", text: output }],
|
|
494
|
-
details: {
|
|
495
|
-
mode: "dump",
|
|
496
|
-
lang,
|
|
497
|
-
matchCount: lineCount(output),
|
|
498
|
-
totalMatches: lineCount(output),
|
|
499
|
-
truncated: false,
|
|
500
|
-
},
|
|
501
|
-
};
|
|
502
|
-
}
|
|
503
|
-
if (!hasRawRule &&
|
|
504
|
-
hasPattern &&
|
|
505
|
-
looksLikeRuleYamlOrPlainText(pattern)) {
|
|
506
|
-
logOutcome("error", {
|
|
507
|
-
errorRaw: "pattern looks like rule YAML or plain text (rejected pre-spawn)",
|
|
508
|
-
});
|
|
509
|
-
return {
|
|
510
|
-
content: [
|
|
511
|
-
{
|
|
512
|
-
type: "text",
|
|
513
|
-
text: "Error: ast_grep_search expects a valid AST code pattern, not plain text/rule YAML. Use patterns like `function $NAME($$$ARGS) { $$$BODY }` or use grep/read for plain text diagnostics.",
|
|
514
|
-
},
|
|
515
|
-
],
|
|
516
|
-
isError: true,
|
|
517
|
-
details: {},
|
|
518
|
-
};
|
|
519
|
-
}
|
|
520
|
-
// #747/#250: only guard the DEFAULTED-cwd case. Explicit `paths` are
|
|
521
|
-
// what the user asked to search — never second-guessed. But when no
|
|
522
|
-
// paths are given we fall back to `ctx.cwd`, and if that resolves at or
|
|
523
|
-
// above $HOME a full structural scan of the entire home tree would be
|
|
524
|
-
// spawned. Refuse and tell the caller how to scope it.
|
|
525
|
-
if (!paths?.length && isAtOrAboveHomeDir(ctx.cwd || ".")) {
|
|
526
|
-
logOutcome("error", {
|
|
527
|
-
errorRaw: "defaulted cwd resolves at or above home directory",
|
|
528
|
-
});
|
|
529
|
-
return {
|
|
530
|
-
content: [
|
|
531
|
-
{
|
|
532
|
-
type: "text",
|
|
533
|
-
text: `Refused: no \`paths\` given and the working directory (${ctx.cwd || "."}) resolves at or above the home directory — searching it would scan every unrelated tree under your home. Pass explicit \`paths\`, or run from a project directory.`,
|
|
534
|
-
},
|
|
535
|
-
],
|
|
536
|
-
isError: true,
|
|
537
|
-
details: {},
|
|
538
|
-
};
|
|
539
|
-
}
|
|
540
|
-
if (hasNodeKind && hasPattern) {
|
|
541
|
-
const errorRaw = "nodeKind cannot be combined with pattern";
|
|
542
|
-
logOutcome("error", { errorRaw });
|
|
543
|
-
return {
|
|
544
|
-
content: [{ type: "text", text: `Error: ${errorRaw}` }],
|
|
545
|
-
isError: true,
|
|
546
|
-
details: {},
|
|
547
|
-
};
|
|
548
|
-
}
|
|
549
|
-
if (hasNodeKind && hasRawRule) {
|
|
550
|
-
const errorRaw = "nodeKind cannot be combined with rule";
|
|
551
|
-
logOutcome("error", { errorRaw });
|
|
552
|
-
return {
|
|
553
|
-
content: [{ type: "text", text: `Error: ${errorRaw}` }],
|
|
554
|
-
isError: true,
|
|
555
|
-
details: {},
|
|
556
|
-
};
|
|
557
|
-
}
|
|
558
|
-
const searchPaths = paths?.length ? paths : [ctx.cwd || "."];
|
|
559
|
-
const PAGE_SIZE = Math.max(1, Math.min(MAX_PAGE_SIZE, Number.isFinite(maxMatches)
|
|
560
|
-
? Math.floor(maxMatches)
|
|
561
|
-
: DEFAULT_PAGE_SIZE));
|
|
562
|
-
// Phase 3: synthesize YAML from structural-intent params
|
|
563
|
-
let effectiveRule = hasRawRule ? rawRule : undefined;
|
|
564
|
-
if (!effectiveRule &&
|
|
565
|
-
(hasNodeKind ||
|
|
566
|
-
hasStructuralIntent({
|
|
567
|
-
nodeKind: normalizedNodeKind,
|
|
568
|
-
insideKind,
|
|
569
|
-
hasKind,
|
|
570
|
-
hasDescendantKind,
|
|
571
|
-
follows,
|
|
572
|
-
precedes,
|
|
573
|
-
}))) {
|
|
574
|
-
try {
|
|
575
|
-
effectiveRule = synthesizeRule({
|
|
576
|
-
pattern: hasPattern ? pattern : undefined,
|
|
577
|
-
nodeKind: hasNodeKind ? normalizedNodeKind : undefined,
|
|
578
|
-
lang,
|
|
579
|
-
insideKind,
|
|
580
|
-
hasKind,
|
|
581
|
-
hasDescendantKind,
|
|
582
|
-
follows,
|
|
583
|
-
precedes,
|
|
584
|
-
});
|
|
585
|
-
}
|
|
586
|
-
catch (err) {
|
|
587
|
-
logOutcome("error", { errorRaw: String(err) });
|
|
588
|
-
return {
|
|
589
|
-
content: [
|
|
590
|
-
{
|
|
591
|
-
type: "text",
|
|
592
|
-
text: `Error synthesizing rule: ${err}`,
|
|
593
|
-
},
|
|
594
|
-
],
|
|
595
|
-
isError: true,
|
|
596
|
-
details: {},
|
|
597
|
-
};
|
|
598
|
-
}
|
|
599
|
-
}
|
|
600
|
-
if (validateOnly) {
|
|
601
|
-
const validation = effectiveRule?.trim()
|
|
602
|
-
? await astGrepClient.validateRule(effectiveRule, executionOptions)
|
|
603
|
-
: await astGrepClient.validatePattern(pattern, lang, {
|
|
604
|
-
selector,
|
|
605
|
-
strictness,
|
|
606
|
-
...executionOptions,
|
|
607
|
-
});
|
|
608
|
-
if (!validation.valid) {
|
|
609
|
-
logOutcome("error", { errorRaw: validation.error });
|
|
610
|
-
return {
|
|
611
|
-
content: [
|
|
612
|
-
{
|
|
613
|
-
type: "text",
|
|
614
|
-
text: `Invalid ast-grep ${effectiveRule ? "rule" : "pattern"}: ${validation.error ?? "unknown error"}`,
|
|
615
|
-
},
|
|
616
|
-
],
|
|
617
|
-
isError: true,
|
|
618
|
-
details: { valid: false, validateOnly: true },
|
|
619
|
-
};
|
|
620
|
-
}
|
|
621
|
-
logOutcome("success", { matchCount: 0 });
|
|
622
|
-
const warning = "warning" in validation ? validation.warning : undefined;
|
|
623
|
-
return {
|
|
624
|
-
content: [
|
|
625
|
-
{
|
|
626
|
-
type: "text",
|
|
627
|
-
text: `Valid ast-grep ${effectiveRule ? "rule" : "pattern"}.${warning ? ` Warning: ${warning}` : ""}`,
|
|
628
|
-
},
|
|
629
|
-
],
|
|
630
|
-
details: {
|
|
631
|
-
valid: true,
|
|
632
|
-
validateOnly: true,
|
|
633
|
-
mode: effectiveRule ? "rule" : "pattern",
|
|
634
|
-
...(warning ? { warning } : {}),
|
|
635
|
-
},
|
|
636
|
-
};
|
|
637
|
-
}
|
|
638
|
-
// Phase 4: raw YAML rule passthrough — routes through sg scan --config
|
|
639
|
-
if (effectiveRule && effectiveRule.trim().length > 0) {
|
|
640
|
-
if (abortSignal?.aborted)
|
|
641
|
-
return abortError();
|
|
642
|
-
const ruleResult = await astGrepClient.searchWithRule(effectiveRule, searchPaths, executionOptions);
|
|
643
|
-
if (abortSignal?.aborted)
|
|
644
|
-
return abortError();
|
|
645
|
-
if (ruleResult.error) {
|
|
646
|
-
logOutcome("error", { errorRaw: ruleResult.error });
|
|
647
|
-
return {
|
|
648
|
-
content: [
|
|
649
|
-
{
|
|
650
|
-
type: "text",
|
|
651
|
-
text: errorTextWithHint(ruleResult.error),
|
|
652
|
-
},
|
|
653
|
-
],
|
|
654
|
-
isError: true,
|
|
655
|
-
details: {},
|
|
656
|
-
};
|
|
657
|
-
}
|
|
658
|
-
const afterSkip = ruleResult.matches.slice(skipOffset);
|
|
659
|
-
const page = afterSkip.slice(0, PAGE_SIZE);
|
|
660
|
-
const hasMore = afterSkip.length > PAGE_SIZE;
|
|
661
|
-
const output = groupByFile
|
|
662
|
-
? formatGroupedByFile(page)
|
|
663
|
-
: astGrepClient.formatMatches(page, false, false, PAGE_SIZE);
|
|
664
|
-
const paginationNote = hasMore && page.length > 0
|
|
665
|
-
? `\n\n(Showing ${page.length} of ${ruleResult.matches.length - skipOffset} remaining matches. Use skip=${skipOffset + PAGE_SIZE} for the next page.)`
|
|
666
|
-
: "";
|
|
667
|
-
logOutcome(page.length === 0 ? "no_matches" : "success", {
|
|
668
|
-
matchCount: page.length,
|
|
669
|
-
truncated: hasMore,
|
|
670
|
-
});
|
|
671
|
-
const matchLocations = toMatchLocations(page, context);
|
|
672
|
-
return {
|
|
673
|
-
content: [
|
|
674
|
-
{ type: "text", text: `${output}${paginationNote}` },
|
|
675
|
-
],
|
|
676
|
-
details: {
|
|
677
|
-
matchCount: page.length,
|
|
678
|
-
totalMatches: ruleResult.totalMatches,
|
|
679
|
-
truncated: hasMore,
|
|
680
|
-
hasMore,
|
|
681
|
-
skip: skipOffset,
|
|
682
|
-
groupByFile: groupByFile === true,
|
|
683
|
-
// Lines shown to the agent — the read-guard registers these so a
|
|
684
|
-
// follow-up edit to a match isn't blocked (#169). 1-based.
|
|
685
|
-
searchReads: toSearchReads(page),
|
|
686
|
-
// Agent-facing follow-up handles for bounded context reads.
|
|
687
|
-
matchLocations,
|
|
688
|
-
suggestedDump: page.length === 0 ? suggestedDump(lang) : undefined,
|
|
689
|
-
},
|
|
690
|
-
};
|
|
691
|
-
}
|
|
692
|
-
if (abortSignal?.aborted)
|
|
693
|
-
return abortError();
|
|
694
|
-
const result = await astGrepClient.search(pattern, lang, searchPaths, {
|
|
695
|
-
selector,
|
|
696
|
-
context,
|
|
697
|
-
strictness,
|
|
698
|
-
...executionOptions,
|
|
699
|
-
});
|
|
700
|
-
if (abortSignal?.aborted)
|
|
701
|
-
return abortError();
|
|
702
|
-
if (result.error) {
|
|
703
|
-
logOutcome("error", { errorRaw: result.error });
|
|
704
|
-
return {
|
|
705
|
-
content: [
|
|
706
|
-
{ type: "text", text: errorTextWithHint(result.error) },
|
|
707
|
-
],
|
|
708
|
-
isError: true,
|
|
709
|
-
details: {},
|
|
710
|
-
};
|
|
711
|
-
}
|
|
712
|
-
// Apply skip-based pagination over the full in-memory match list.
|
|
713
|
-
const afterSkip = result.matches.slice(skipOffset);
|
|
714
|
-
const page = afterSkip.slice(0, PAGE_SIZE);
|
|
715
|
-
const hasMore = afterSkip.length > PAGE_SIZE || result.truncated;
|
|
716
|
-
const output = groupByFile
|
|
717
|
-
? formatGroupedByFile(page)
|
|
718
|
-
: astGrepClient.formatMatches(page, false, false, PAGE_SIZE);
|
|
719
|
-
const hint = page.length === 0 && !result.error
|
|
720
|
-
? getPatternHint(pattern, lang, selector)
|
|
721
|
-
: undefined;
|
|
722
|
-
const paginationNote = hasMore && page.length > 0
|
|
723
|
-
? `\n\n(Showing ${page.length} of ${result.matches.length - skipOffset} remaining matches. Use skip=${skipOffset + PAGE_SIZE} for the next page.)`
|
|
724
|
-
: "";
|
|
725
|
-
const finalOutput = hint
|
|
726
|
-
? `${output}\n\n${hint}`
|
|
727
|
-
: `${output}${paginationNote}`;
|
|
728
|
-
logOutcome(page.length === 0 ? "no_matches" : "success", {
|
|
729
|
-
matchCount: page.length,
|
|
730
|
-
truncated: hasMore,
|
|
731
|
-
});
|
|
732
|
-
const matchLocations = toMatchLocations(page, context);
|
|
733
|
-
return {
|
|
734
|
-
content: [{ type: "text", text: finalOutput }],
|
|
735
|
-
details: {
|
|
736
|
-
matchCount: page.length,
|
|
737
|
-
totalMatches: result.matches.length,
|
|
738
|
-
truncated: hasMore,
|
|
739
|
-
hasMore,
|
|
740
|
-
skip: skipOffset,
|
|
741
|
-
groupByFile: groupByFile === true,
|
|
742
|
-
// Lines shown to the agent — registered as reads by the read-guard
|
|
743
|
-
// so a follow-up edit to a match isn't blocked (#169). 1-based.
|
|
744
|
-
searchReads: toSearchReads(page),
|
|
745
|
-
// Agent-facing follow-up handles for bounded context reads.
|
|
746
|
-
matchLocations,
|
|
747
|
-
suggestedDump: page.length === 0 ? suggestedDump(lang) : undefined,
|
|
748
|
-
},
|
|
749
|
-
};
|
|
750
|
-
}
|
|
751
|
-
catch (err) {
|
|
752
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
753
|
-
logOutcome("error", { errorRaw: message });
|
|
754
|
-
return {
|
|
755
|
-
content: [{ type: "text", text: `Error: ${message}` }],
|
|
756
|
-
isError: true,
|
|
757
|
-
details: {},
|
|
758
|
-
};
|
|
759
|
-
}
|
|
760
|
-
},
|
|
761
|
-
};
|
|
762
|
-
}
|