@mrclrchtr/supi-code-intelligence 1.16.1 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +373 -63
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/package.json +6 -1
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/abort-utils.ts +31 -0
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/api.ts +8 -0
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/config/config-settings.ts +10 -4
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/config.ts +1 -0
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/footer-registry.ts +1 -1
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/index.ts +6 -0
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/model-selection.ts +134 -0
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings/settings-registry.ts +9 -2
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings/settings-ui.ts +109 -4
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings-ui.ts +5 -1
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/spinner-frames.ts +11 -0
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/status-spinner.ts +68 -0
- package/node_modules/@mrclrchtr/supi-code-runtime/package.json +3 -2
- package/node_modules/@mrclrchtr/supi-code-runtime/src/api.ts +7 -0
- package/node_modules/@mrclrchtr/supi-code-runtime/src/capability/types.ts +56 -2
- package/node_modules/@mrclrchtr/supi-code-runtime/src/evidence-badge.ts +40 -0
- package/node_modules/@mrclrchtr/supi-code-runtime/src/index.ts +5 -0
- package/node_modules/@mrclrchtr/supi-code-runtime/src/types.ts +76 -3
- package/node_modules/@mrclrchtr/supi-code-runtime/src/workspace/runtime.ts +37 -2
- package/node_modules/@mrclrchtr/supi-core/package.json +6 -1
- package/node_modules/@mrclrchtr/supi-core/src/abort-utils.ts +31 -0
- package/node_modules/@mrclrchtr/supi-core/src/api.ts +8 -0
- package/node_modules/@mrclrchtr/supi-core/src/config/config-settings.ts +10 -4
- package/node_modules/@mrclrchtr/supi-core/src/config.ts +1 -0
- package/node_modules/@mrclrchtr/supi-core/src/footer-registry.ts +1 -1
- package/node_modules/@mrclrchtr/supi-core/src/index.ts +6 -0
- package/node_modules/@mrclrchtr/supi-core/src/model-selection.ts +134 -0
- package/node_modules/@mrclrchtr/supi-core/src/settings/settings-registry.ts +9 -2
- package/node_modules/@mrclrchtr/supi-core/src/settings/settings-ui.ts +109 -4
- package/node_modules/@mrclrchtr/supi-core/src/settings-ui.ts +5 -1
- package/node_modules/@mrclrchtr/supi-core/src/spinner-frames.ts +11 -0
- package/node_modules/@mrclrchtr/supi-core/src/status-spinner.ts +68 -0
- package/node_modules/@mrclrchtr/supi-lsp/README.md +44 -56
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/package.json +6 -1
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/abort-utils.ts +31 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/api.ts +8 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/config/config-settings.ts +10 -4
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/config.ts +1 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/footer-registry.ts +1 -1
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/index.ts +6 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/model-selection.ts +134 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings/settings-registry.ts +9 -2
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings/settings-ui.ts +109 -4
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings-ui.ts +5 -1
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/spinner-frames.ts +11 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/status-spinner.ts +68 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/package.json +3 -2
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/src/api.ts +7 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/src/capability/types.ts +56 -2
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/src/evidence-badge.ts +40 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/src/index.ts +5 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/src/types.ts +76 -3
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/src/workspace/runtime.ts +37 -2
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/package.json +6 -1
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/abort-utils.ts +31 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/api.ts +8 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/config/config-settings.ts +10 -4
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/config.ts +1 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/footer-registry.ts +1 -1
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/index.ts +6 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/model-selection.ts +134 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/settings/settings-registry.ts +9 -2
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/settings/settings-ui.ts +109 -4
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/settings-ui.ts +5 -1
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/spinner-frames.ts +11 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/status-spinner.ts +68 -0
- package/node_modules/@mrclrchtr/supi-lsp/package.json +4 -31
- package/node_modules/@mrclrchtr/supi-lsp/src/api.ts +27 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-refresh.ts +5 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client.ts +246 -1
- package/node_modules/@mrclrchtr/supi-lsp/src/client/transport.ts +4 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/config/capabilities.ts +3 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/config/config.ts +4 -2
- package/node_modules/@mrclrchtr/supi-lsp/src/config/lsp-settings.ts +102 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/config/server-actions.ts +59 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/config/server-config.ts +4 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/index.ts +11 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/manager/capability-index.ts +1 -1
- package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-project-info.ts +2 -1
- package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager.ts +115 -26
- package/node_modules/@mrclrchtr/supi-lsp/src/provider/lsp-semantic-provider.ts +177 -134
- package/node_modules/@mrclrchtr/supi-lsp/src/provider/refactor-planning.ts +214 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-controller.ts +320 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-registration.ts +26 -5
- package/node_modules/@mrclrchtr/supi-lsp/src/session/service-registry.ts +81 -4
- package/node_modules/@mrclrchtr/supi-lsp/src/summary.ts +2 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/README.md +18 -37
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/package.json +6 -1
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/abort-utils.ts +31 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/api.ts +8 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/config/config-settings.ts +10 -4
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/config.ts +1 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/footer-registry.ts +1 -1
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/index.ts +6 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/model-selection.ts +134 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings/settings-registry.ts +9 -2
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings/settings-ui.ts +109 -4
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings-ui.ts +5 -1
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/spinner-frames.ts +11 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/status-spinner.ts +68 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/package.json +3 -2
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/src/api.ts +7 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/src/capability/types.ts +56 -2
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/src/evidence-badge.ts +40 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/src/index.ts +5 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/src/types.ts +76 -3
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/src/workspace/runtime.ts +37 -2
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/package.json +6 -1
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/abort-utils.ts +31 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/api.ts +8 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/config/config-settings.ts +10 -4
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/config.ts +1 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/footer-registry.ts +1 -1
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/index.ts +6 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/model-selection.ts +134 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/settings/settings-registry.ts +9 -2
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/settings/settings-ui.ts +109 -4
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/settings-ui.ts +5 -1
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/spinner-frames.ts +11 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/status-spinner.ts +68 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/LICENSE +21 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/README.md +265 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/debug/web-tree-sitter.cjs +4661 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/debug/web-tree-sitter.cjs.map +7 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/debug/web-tree-sitter.js +4605 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/debug/web-tree-sitter.js.map +7 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/debug/web-tree-sitter.wasm +0 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/debug/web-tree-sitter.wasm.map +57 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/package.json +100 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.cjs +4063 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.cjs.map +7 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.d.cts +1025 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.d.cts.map +58 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.d.ts +1025 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.d.ts.map +58 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.js +4007 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.js.map +7 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.wasm +0 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.wasm.map +55 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/package.json +6 -12
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/api.ts +29 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/index.ts +28 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/language.ts +5 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/provider/tree-sitter-provider.ts +14 -2
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/runtime-controller.ts +157 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/session.ts +8 -1
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/call-sites.ts +86 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/callees.ts +35 -16
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/structure.ts +1 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/types.ts +10 -0
- package/package.json +14 -9
- package/src/{model.ts → analysis/architecture/discovery.ts} +15 -72
- package/src/analysis/architecture/model.ts +76 -0
- package/src/analysis/brief/directory.ts +324 -0
- package/src/analysis/brief/enrich.ts +157 -0
- package/src/analysis/brief/file.ts +84 -0
- package/src/analysis/brief/inventory.ts +177 -0
- package/src/analysis/brief/main.ts +176 -0
- package/src/analysis/brief/models.ts +75 -0
- package/src/{brief.ts → analysis/brief/public-brief.ts} +21 -26
- package/src/analysis/brief/summarize.ts +208 -0
- package/src/analysis/brief/types.ts +27 -0
- package/src/{use-case/generate-brief.ts → analysis/brief/use-case.ts} +67 -144
- package/src/analysis/coverage/coverage-warnings.ts +224 -0
- package/src/analysis/evidence.ts +91 -0
- package/src/{semantic-action-helpers.ts → analysis/helpers.ts} +4 -4
- package/src/analysis/provider.ts +186 -0
- package/src/analysis/read-next.ts +126 -0
- package/src/analysis/readiness.ts +73 -0
- package/src/{refactor → analysis/refactor}/safety.ts +1 -1
- package/src/{use-case/support/semantic-references.ts → analysis/references/semantic-refs.ts} +58 -26
- package/src/analysis/search/pattern.ts +345 -0
- package/src/analysis/search/ripgrep.ts +473 -0
- package/src/{git-context.ts → analysis/signals/git.ts} +20 -7
- package/src/{prioritization-signals.ts → analysis/signals/project.ts} +33 -19
- package/src/analysis/target/anchored.ts +349 -0
- package/src/analysis/target/bridge.ts +152 -0
- package/src/analysis/target/file-resolution.ts +125 -0
- package/src/{targeting/resolve-file.ts → analysis/target/file.ts} +40 -20
- package/src/{planner → analysis/target}/planner.ts +30 -20
- package/src/{targeting → analysis/target}/query.ts +17 -3
- package/src/analysis/target/resolve-common.ts +115 -0
- package/src/analysis/target/service.ts +229 -0
- package/src/analysis/target/symbol.ts +196 -0
- package/src/{targeting → analysis/target}/types.ts +17 -1
- package/src/analysis/tests/likely-tests.ts +174 -0
- package/src/analysis/tests/test-discovery.ts +540 -0
- package/src/analysis/tests/vitest.ts +87 -0
- package/src/api.ts +34 -41
- package/src/app/app.ts +125 -0
- package/src/app/manager.ts +65 -0
- package/src/extension.ts +132 -1
- package/src/index.ts +1 -57
- package/src/session/refactor-plans.ts +82 -0
- package/src/session/session.ts +300 -0
- package/src/session/target-store.ts +293 -0
- package/src/substrate/lsp/diagnostic-injection.ts +218 -0
- package/src/substrate/lsp/lifecycle.ts +66 -0
- package/src/substrate/lsp/overrides.ts +132 -0
- package/src/substrate/lsp/recovery.ts +55 -0
- package/src/substrate/lsp/settings.ts +286 -0
- package/src/substrate/lsp/state.ts +46 -0
- package/src/substrate/lsp/utils.ts +17 -0
- package/src/substrate/tree-sitter/lifecycle.ts +52 -0
- package/src/tool/find/execute.ts +118 -0
- package/src/{presentation/markdown/pattern.ts → tool/find/markdown.ts} +102 -53
- package/src/{use-case/generate-pattern.ts → tool/find/orchestrate.ts} +67 -33
- package/src/tool/find/semantic-search.ts +114 -0
- package/src/tool/find/tui.ts +39 -0
- package/src/tool/graph/callees.ts +87 -0
- package/src/tool/graph/calls-md.ts +54 -0
- package/src/tool/graph/collect-relation.ts +371 -0
- package/src/tool/graph/execute.ts +95 -0
- package/src/tool/graph/implementations-md.ts +79 -0
- package/src/tool/graph/implementations.ts +76 -0
- package/src/tool/graph/markdown-base.ts +243 -0
- package/src/tool/graph/orchestrate.ts +285 -0
- package/src/tool/graph/references-md.ts +34 -0
- package/src/tool/graph/references.ts +81 -0
- package/src/tool/graph/tui.ts +120 -0
- package/src/tool/graph/types.ts +97 -0
- package/src/tool/guidance.ts +96 -49
- package/src/tool/health/execute.ts +76 -0
- package/src/tool/health/markdown.ts +280 -0
- package/src/tool/health/orchestrate.ts +159 -0
- package/src/tool/health/sections/diagnostics.ts +182 -0
- package/src/tool/health/sections/recovery.ts +89 -0
- package/src/tool/health/sections/signals.ts +89 -0
- package/src/tool/health/tui.ts +137 -0
- package/src/tool/impact/analysis.ts +247 -0
- package/src/tool/impact/change-set-impact.ts +151 -0
- package/src/tool/impact/execute.ts +98 -0
- package/src/tool/impact/file-level-impact.ts +81 -0
- package/src/tool/impact/markdown.ts +283 -0
- package/src/tool/impact/orchestrate.ts +97 -0
- package/src/tool/impact/result.ts +21 -0
- package/src/tool/impact/single-impact.ts +89 -0
- package/src/tool/impact/tui.ts +39 -0
- package/src/tool/impact/types.ts +34 -0
- package/src/tool/infra/cross-field.ts +335 -0
- package/src/tool/infra/error-results.ts +199 -0
- package/src/tool/infra/pipeline.ts +311 -0
- package/src/tool/infra/progress.ts +21 -0
- package/src/tool/infra/readiness-message.ts +5 -0
- package/src/tool/infra/truncate.ts +49 -0
- package/src/tool/inspect/execute.ts +76 -0
- package/src/tool/inspect/markdown.ts +169 -0
- package/src/tool/inspect/orchestrate.ts +156 -0
- package/src/tool/inspect/tui.ts +36 -0
- package/src/tool/orientation/deps.ts +63 -0
- package/src/tool/orientation/execute.ts +50 -0
- package/src/tool/orientation/markdown.ts +35 -0
- package/src/tool/orientation/mode.ts +88 -0
- package/src/tool/orientation/orchestrate.ts +478 -0
- package/src/tool/orientation/precise-target.ts +257 -0
- package/src/tool/orientation/tui.ts +131 -0
- package/src/{refactor/apply-workspace-edit.ts → tool/refactor-apply/apply.ts} +39 -16
- package/src/tool/refactor-apply/execute.ts +20 -0
- package/src/tool/refactor-apply/markdown.ts +118 -0
- package/src/tool/refactor-apply/orchestrate.ts +89 -0
- package/src/tool/refactor-apply/tui.ts +51 -0
- package/src/tool/refactor-plan/execute.ts +73 -0
- package/src/tool/refactor-plan/markdown.ts +118 -0
- package/src/tool/refactor-plan/orchestrate.ts +363 -0
- package/src/tool/refactor-plan/tui.ts +42 -0
- package/src/tool/register.ts +123 -0
- package/src/tool/resolve/execute.ts +82 -0
- package/src/tool/resolve/markdown.ts +150 -0
- package/src/tool/resolve/orchestrate.ts +134 -0
- package/src/tool/resolve/tui.ts +40 -0
- package/src/tool/schemas.ts +337 -0
- package/src/tool/specs.ts +257 -0
- package/src/types/details.ts +188 -0
- package/src/types/execution.ts +60 -0
- package/src/types/index.ts +28 -0
- package/src/{intent/types.ts → types/tool-names.ts} +15 -14
- package/src/ui/footer.ts +52 -0
- package/src/ui/markdown/brief.ts +218 -0
- package/src/ui/markdown/gather.ts +177 -0
- package/src/{use-case/build-overview.ts → ui/markdown/overview-data.ts} +2 -2
- package/src/{presentation → ui}/markdown/overview.ts +2 -2
- package/src/ui/markdown/types.ts +80 -0
- package/{node_modules/@mrclrchtr/supi-lsp/src/ui/renderer.ts → src/ui/message-renderer.ts} +11 -10
- package/src/ui/status-command.ts +260 -0
- package/src/ui/status-overlay.ts +500 -0
- package/src/ui/tui/common.ts +220 -0
- package/src/ui/tui/index.ts +37 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/extension.ts +0 -1
- package/node_modules/@mrclrchtr/supi-lsp/src/format.ts +0 -373
- package/node_modules/@mrclrchtr/supi-lsp/src/handlers/diagnostic-injection.ts +0 -182
- package/node_modules/@mrclrchtr/supi-lsp/src/handlers/session-lifecycle.ts +0 -149
- package/node_modules/@mrclrchtr/supi-lsp/src/handlers/status-command.ts +0 -38
- package/node_modules/@mrclrchtr/supi-lsp/src/handlers/workspace-recovery.ts +0 -92
- package/node_modules/@mrclrchtr/supi-lsp/src/lsp.ts +0 -37
- package/node_modules/@mrclrchtr/supi-lsp/src/session/lsp-state.ts +0 -93
- package/node_modules/@mrclrchtr/supi-lsp/src/session/settings-registration.ts +0 -296
- package/node_modules/@mrclrchtr/supi-lsp/src/session/tree-persist.ts +0 -75
- package/node_modules/@mrclrchtr/supi-lsp/src/tool/guidance.ts +0 -69
- package/node_modules/@mrclrchtr/supi-lsp/src/tool/names.ts +0 -27
- package/node_modules/@mrclrchtr/supi-lsp/src/tool/overrides.ts +0 -204
- package/node_modules/@mrclrchtr/supi-lsp/src/tool/register-tools.ts +0 -69
- package/node_modules/@mrclrchtr/supi-lsp/src/tool/service-actions.ts +0 -399
- package/node_modules/@mrclrchtr/supi-lsp/src/tool/tool-specs.ts +0 -248
- package/node_modules/@mrclrchtr/supi-lsp/src/ui/ui.ts +0 -360
- package/node_modules/@mrclrchtr/supi-lsp/src/workspace-change.ts +0 -40
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/extension.ts +0 -1
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/formatting.ts +0 -104
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/guidance.ts +0 -35
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/handlers.ts +0 -196
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/register-tools.ts +0 -107
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/tool-specs.ts +0 -117
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/tree-sitter.ts +0 -47
- package/src/brief-focused.ts +0 -563
- package/src/code-intelligence.ts +0 -70
- package/src/pattern-structured.ts +0 -194
- package/src/presentation/markdown/affected.ts +0 -170
- package/src/presentation/markdown/brief.ts +0 -174
- package/src/presentation/markdown/map.ts +0 -54
- package/src/presentation/markdown/refactor.ts +0 -27
- package/src/presentation/markdown/relations.ts +0 -121
- package/src/resolve-target.ts +0 -130
- package/src/search-helpers.ts +0 -303
- package/src/substrates/types.ts +0 -30
- package/src/target-resolution.ts +0 -122
- package/src/targeting/resolve-anchored.ts +0 -80
- package/src/targeting/resolve-symbol.ts +0 -110
- package/src/tool/execute-affected.ts +0 -71
- package/src/tool/execute-brief.ts +0 -59
- package/src/tool/execute-map.ts +0 -35
- package/src/tool/execute-pattern.ts +0 -29
- package/src/tool/execute-refactor.ts +0 -101
- package/src/tool/execute-relations.ts +0 -79
- package/src/tool/register-tools.ts +0 -32
- package/src/tool/tool-specs.ts +0 -190
- package/src/tool/validation.ts +0 -43
- package/src/types.ts +0 -169
- package/src/use-case/generate-affected.ts +0 -297
- package/src/use-case/generate-map.ts +0 -176
- package/src/use-case/generate-relations.ts +0 -438
- package/src/use-case/types.ts +0 -43
- package/src/workspace/request-context.ts +0 -139
- /package/src/{query-params.ts → tool/params.ts} +0 -0
|
@@ -0,0 +1,473 @@
|
|
|
1
|
+
// biome-ignore-all lint/style/noExcessiveLinesPerFile: ripgrep abort/process handling, JSON parsing, and path/scope helpers are cohesive search infrastructure
|
|
2
|
+
// Shared search helpers for code-intelligence search and routing helpers.
|
|
3
|
+
|
|
4
|
+
import { type ChildProcess, spawn } from "node:child_process";
|
|
5
|
+
import { existsSync } from "node:fs";
|
|
6
|
+
import * as path from "node:path";
|
|
7
|
+
import { resolveToolPath, uriToFile as uriToFileShared } from "@mrclrchtr/supi-core/path";
|
|
8
|
+
|
|
9
|
+
const LOW_SIGNAL_DIRS = new Set([
|
|
10
|
+
"node_modules",
|
|
11
|
+
".git",
|
|
12
|
+
".pnpm",
|
|
13
|
+
"dist",
|
|
14
|
+
"build",
|
|
15
|
+
"out",
|
|
16
|
+
".next",
|
|
17
|
+
".nuxt",
|
|
18
|
+
"coverage",
|
|
19
|
+
".turbo",
|
|
20
|
+
".cache",
|
|
21
|
+
"__pycache__",
|
|
22
|
+
".tsbuildinfo",
|
|
23
|
+
]);
|
|
24
|
+
|
|
25
|
+
/** Check if a file path contains an obviously low-signal directory segment. */
|
|
26
|
+
export function isLowSignalPath(filePath: string): boolean {
|
|
27
|
+
const segments = filePath.split(path.sep);
|
|
28
|
+
return segments.some((s) => LOW_SIGNAL_DIRS.has(s));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** Convert a file:// URI to a file path, matching the shared SuPi normalization. */
|
|
32
|
+
export const uriToFile = uriToFileShared;
|
|
33
|
+
|
|
34
|
+
/** Check whether a resolved file path is inside the current project (within cwd, not under node_modules or .pnpm). */
|
|
35
|
+
export function isInProjectPath(filePath: string, cwd: string): boolean {
|
|
36
|
+
const relativePath = path.relative(cwd, path.resolve(cwd, filePath));
|
|
37
|
+
if (relativePath.startsWith(`..${path.sep}`) || relativePath === "..") return false;
|
|
38
|
+
const normalized = relativePath.replaceAll("\\", "/");
|
|
39
|
+
return !(
|
|
40
|
+
normalized.includes("/node_modules/") ||
|
|
41
|
+
normalized.startsWith("node_modules/") ||
|
|
42
|
+
normalized.includes("/.pnpm/") ||
|
|
43
|
+
normalized.startsWith(".pnpm/")
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** Result of resolving a user-provided `scope` value to an absolute path. */
|
|
48
|
+
export type ScopeResolution = { kind: "ok"; path: string } | { kind: "error"; reason: string };
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Resolve a `scope` value to an absolute path using pi scope semantics:
|
|
52
|
+
* - strip leading `@`
|
|
53
|
+
* - resolve relative paths from `cwd`
|
|
54
|
+
* - require the resolved path to exist
|
|
55
|
+
*/
|
|
56
|
+
export function resolveScope(scope: string | undefined, cwd: string): ScopeResolution {
|
|
57
|
+
if (!scope) return { kind: "ok", path: cwd };
|
|
58
|
+
if (/[,;\s]/.test(scope)) {
|
|
59
|
+
return {
|
|
60
|
+
kind: "error",
|
|
61
|
+
reason: `Scope accepts a single directory or file path, not multiple: \`${scope}\``,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
const resolved = normalizePath(scope, cwd);
|
|
65
|
+
if (!existsSync(resolved)) {
|
|
66
|
+
return { kind: "error", reason: `Scope path not found: \`${scope}\`` };
|
|
67
|
+
}
|
|
68
|
+
return { kind: "ok", path: resolved };
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** Escape regex special characters. */
|
|
72
|
+
export function escapeRegex(s: string): string {
|
|
73
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** Normalize a file/path value: strip leading @, resolve relative to cwd. */
|
|
77
|
+
export function normalizePath(input: string, cwd: string): string {
|
|
78
|
+
return resolveToolPath(cwd, input);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** Render a file path relative to cwd when it is inside the workspace. */
|
|
82
|
+
export function toDisplayPath(cwd: string, filePath: string): string {
|
|
83
|
+
if (!path.isAbsolute(filePath)) {
|
|
84
|
+
return filePath.replaceAll("\\", "/");
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const relativePath = path.relative(cwd, filePath);
|
|
88
|
+
if (!relativePath || relativePath === ".") {
|
|
89
|
+
return filePath;
|
|
90
|
+
}
|
|
91
|
+
if (relativePath.startsWith(`..${path.sep}`) || relativePath === "..") {
|
|
92
|
+
return filePath;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return relativePath.replaceAll("\\", "/");
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export interface RgMatch {
|
|
99
|
+
file: string;
|
|
100
|
+
line: number;
|
|
101
|
+
text: string;
|
|
102
|
+
/** Context lines surrounding this match (from -C flag). */
|
|
103
|
+
context?: Array<{ line: number; text: string }>;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/** Result of a ripgrep invocation for callers that need both matches and execution errors. */
|
|
107
|
+
export interface RipgrepRunResult {
|
|
108
|
+
/** Parsed ripgrep matches, if any. */
|
|
109
|
+
matches: RgMatch[];
|
|
110
|
+
/** Non-no-match ripgrep execution error text, such as invalid regex syntax. */
|
|
111
|
+
error?: string;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/** Options for {@link runRipgrep} / {@link runRipgrepDetailed}. */
|
|
115
|
+
export interface RipgrepOptions {
|
|
116
|
+
maxMatches?: number;
|
|
117
|
+
contextLines?: number;
|
|
118
|
+
literal?: boolean;
|
|
119
|
+
filterLowSignal?: boolean;
|
|
120
|
+
/**
|
|
121
|
+
* Abort signal from the agent runtime. When aborted, the ripgrep child is
|
|
122
|
+
* killed and the call rejects with {@link RipgrepAbortedError} so the
|
|
123
|
+
* executor (and pi) can treat the tool call as cancelled rather than
|
|
124
|
+
* silently completing with partial matches.
|
|
125
|
+
*/
|
|
126
|
+
signal?: AbortSignal;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/** Hard upper bound on a single ripgrep invocation, matching the prior `execFileSync` timeout. */
|
|
130
|
+
const RIPGREP_TIMEOUT_MS = 10_000;
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Thrown by {@link runRipgrepDetailed} when the supplied `AbortSignal` fires.
|
|
134
|
+
* Propagates out of executors so pi cancels the tool call instead of returning
|
|
135
|
+
* partial results.
|
|
136
|
+
*/
|
|
137
|
+
export class RipgrepAbortedError extends Error {
|
|
138
|
+
constructor(signal?: AbortSignal) {
|
|
139
|
+
const reason = signal?.reason;
|
|
140
|
+
super(reason instanceof Error ? reason.message : "ripgrep search was aborted");
|
|
141
|
+
this.name = "RipgrepAbortedError";
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Run ripgrep with JSON output and parse matches, filtering low-signal paths.
|
|
147
|
+
*
|
|
148
|
+
* Async and abort-aware: when `opts.signal` aborts, the ripgrep child is killed
|
|
149
|
+
* and the returned promise rejects with {@link RipgrepAbortedError}. Any
|
|
150
|
+
* non-abort ripgrep execution failure is still treated like an empty match set
|
|
151
|
+
* (or surfaces an error via {@link runRipgrepDetailed}).
|
|
152
|
+
*/
|
|
153
|
+
export async function runRipgrep(
|
|
154
|
+
pattern: string,
|
|
155
|
+
scopePath: string,
|
|
156
|
+
cwd: string,
|
|
157
|
+
opts?: RipgrepOptions,
|
|
158
|
+
): Promise<RgMatch[]> {
|
|
159
|
+
return (await runRipgrepDetailed(pattern, scopePath, cwd, opts)).matches;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Run ripgrep and preserve non-no-match execution errors for callers that need
|
|
164
|
+
* to distinguish invalid regex syntax from a genuine empty search result.
|
|
165
|
+
* Abort-aware: rejects with {@link RipgrepAbortedError} when `opts.signal` fires.
|
|
166
|
+
*/
|
|
167
|
+
export async function runRipgrepDetailed(
|
|
168
|
+
pattern: string,
|
|
169
|
+
scopePath: string,
|
|
170
|
+
cwd: string,
|
|
171
|
+
opts?: RipgrepOptions,
|
|
172
|
+
): Promise<RipgrepRunResult> {
|
|
173
|
+
const filter = opts?.filterLowSignal ?? true;
|
|
174
|
+
let proc: RgProcessResult;
|
|
175
|
+
try {
|
|
176
|
+
proc = await runRgProcess(
|
|
177
|
+
buildRipgrepArgs(pattern, scopePath, opts),
|
|
178
|
+
cwd,
|
|
179
|
+
RIPGREP_TIMEOUT_MS,
|
|
180
|
+
opts?.signal,
|
|
181
|
+
);
|
|
182
|
+
} catch (err: unknown) {
|
|
183
|
+
// Abort propagates so pi cancels the tool call. Any other unexpected spawn
|
|
184
|
+
// failure is treated like an empty match set, preserving prior behavior.
|
|
185
|
+
if (err instanceof RipgrepAbortedError) throw err;
|
|
186
|
+
return { matches: [] };
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
switch (proc.kind) {
|
|
190
|
+
case "missing":
|
|
191
|
+
return {
|
|
192
|
+
matches: [],
|
|
193
|
+
error:
|
|
194
|
+
"ripgrep (rg) is not available. Install it (e.g., `apt install ripgrep` or `brew install ripgrep`).",
|
|
195
|
+
};
|
|
196
|
+
case "ok":
|
|
197
|
+
case "nomatch":
|
|
198
|
+
return { matches: parseRgJson(proc.stdout, filter) };
|
|
199
|
+
case "timeout":
|
|
200
|
+
// Timeout: yield any partial stdout matches with no error surfaced — an
|
|
201
|
+
// improvement over the prior execFileSync path, which discarded partial
|
|
202
|
+
// output on timeout (the timeout error lacked a `status`, so the old
|
|
203
|
+
// handleRipgrepError returned an empty match set).
|
|
204
|
+
return { matches: proc.stdout ? parseRgJson(proc.stdout, filter) : [] };
|
|
205
|
+
case "error":
|
|
206
|
+
return {
|
|
207
|
+
matches: proc.stdout ? parseRgJson(proc.stdout, filter) : [],
|
|
208
|
+
...(proc.stderr.trim() ? { error: proc.stderr.trim() } : {}),
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
function buildRipgrepArgs(
|
|
214
|
+
pattern: string,
|
|
215
|
+
scopePath: string,
|
|
216
|
+
opts?: { maxMatches?: number; contextLines?: number; literal?: boolean },
|
|
217
|
+
): string[] {
|
|
218
|
+
const args = ["--json", "-m", String(opts?.maxMatches ?? 30)];
|
|
219
|
+
if ((opts?.contextLines ?? 0) > 0) {
|
|
220
|
+
args.push("-C", String(opts?.contextLines ?? 0));
|
|
221
|
+
}
|
|
222
|
+
if (opts?.literal) {
|
|
223
|
+
args.push("-F");
|
|
224
|
+
}
|
|
225
|
+
args.push("-e", pattern, scopePath);
|
|
226
|
+
return args;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/** Discriminated result of a single ripgrep process run (see {@link runRgProcess}). */
|
|
230
|
+
type RgProcessResult =
|
|
231
|
+
| { kind: "ok"; stdout: string; stderr: string; status: number }
|
|
232
|
+
| { kind: "nomatch"; stdout: string; stderr: string; status: 1 }
|
|
233
|
+
| { kind: "error"; stdout: string; stderr: string; status: number }
|
|
234
|
+
| { kind: "timeout"; stdout: string; stderr: string }
|
|
235
|
+
| { kind: "missing" };
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Spawn ripgrep, collect stdout/stderr, and resolve a discriminated result.
|
|
239
|
+
* Rejects with {@link RipgrepAbortedError} when `signal` aborts (the child is
|
|
240
|
+
* killed with SIGKILL). Maps exit codes: 0 → ok, 1 → nomatch, 2+ → error;
|
|
241
|
+
* ENOENT → missing (rg not installed); timeout → timeout.
|
|
242
|
+
*/
|
|
243
|
+
function runRgProcess(
|
|
244
|
+
args: string[],
|
|
245
|
+
cwd: string,
|
|
246
|
+
timeoutMs: number,
|
|
247
|
+
signal?: AbortSignal,
|
|
248
|
+
): Promise<RgProcessResult> {
|
|
249
|
+
return new Promise<RgProcessResult>((resolve, reject) => {
|
|
250
|
+
let child: ChildProcess;
|
|
251
|
+
try {
|
|
252
|
+
child = spawn("rg", args, { cwd, stdio: ["pipe", "pipe", "pipe"] });
|
|
253
|
+
} catch (err: unknown) {
|
|
254
|
+
if (isCodeError(err, "ENOENT")) {
|
|
255
|
+
resolve({ kind: "missing" });
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
reject(err);
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
let stdout = "";
|
|
263
|
+
let stderr = "";
|
|
264
|
+
let timedOut = false;
|
|
265
|
+
let settled = false;
|
|
266
|
+
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
267
|
+
let abortListener: (() => void) | null = null;
|
|
268
|
+
|
|
269
|
+
const cleanup = (): void => {
|
|
270
|
+
if (timer) clearTimeout(timer);
|
|
271
|
+
if (abortListener && signal) signal.removeEventListener("abort", abortListener);
|
|
272
|
+
};
|
|
273
|
+
const settle = (r: RgProcessResult): void => {
|
|
274
|
+
if (settled) return;
|
|
275
|
+
settled = true;
|
|
276
|
+
cleanup();
|
|
277
|
+
resolve(r);
|
|
278
|
+
};
|
|
279
|
+
const failAbort = (): void => {
|
|
280
|
+
if (settled) return;
|
|
281
|
+
settled = true;
|
|
282
|
+
cleanup();
|
|
283
|
+
try {
|
|
284
|
+
child.kill("SIGKILL");
|
|
285
|
+
} catch {
|
|
286
|
+
// Child may already have exited; ignore.
|
|
287
|
+
}
|
|
288
|
+
reject(new RipgrepAbortedError(signal));
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
// Fast path: signal already aborted before any work is scheduled.
|
|
292
|
+
if (signal?.aborted) {
|
|
293
|
+
failAbort();
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
child.stdout?.setEncoding("utf-8");
|
|
298
|
+
child.stderr?.setEncoding("utf-8");
|
|
299
|
+
child.stdout?.on("data", (d: string) => {
|
|
300
|
+
stdout += d;
|
|
301
|
+
});
|
|
302
|
+
child.stderr?.on("data", (d: string) => {
|
|
303
|
+
stderr += d;
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
timer = setTimeout(() => {
|
|
307
|
+
timedOut = true;
|
|
308
|
+
try {
|
|
309
|
+
child.kill("SIGTERM");
|
|
310
|
+
} catch {
|
|
311
|
+
// Ignore; the close handler will still fire.
|
|
312
|
+
}
|
|
313
|
+
}, timeoutMs);
|
|
314
|
+
|
|
315
|
+
if (signal) {
|
|
316
|
+
abortListener = () => failAbort();
|
|
317
|
+
signal.addEventListener("abort", abortListener);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
child.on("error", (err: NodeJS.ErrnoException) => {
|
|
321
|
+
if (settled) return;
|
|
322
|
+
if (isCodeError(err, "ENOENT")) {
|
|
323
|
+
settle({ kind: "missing" });
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
settle({ kind: "error", stdout, stderr, status: -1 });
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
child.on("close", (status: number | null) => {
|
|
330
|
+
if (settled) return;
|
|
331
|
+
if (timedOut) {
|
|
332
|
+
settle({ kind: "timeout", stdout, stderr });
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
if (status === 0) settle({ kind: "ok", stdout, stderr, status });
|
|
336
|
+
else if (status === 1) settle({ kind: "nomatch", stdout, stderr, status });
|
|
337
|
+
else settle({ kind: "error", stdout, stderr, status: status ?? -1 });
|
|
338
|
+
});
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
function isCodeError(err: unknown, code: string): boolean {
|
|
343
|
+
return (
|
|
344
|
+
typeof err === "object" &&
|
|
345
|
+
err !== null &&
|
|
346
|
+
"code" in err &&
|
|
347
|
+
(err as { code: unknown }).code === code
|
|
348
|
+
);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
interface RawRgEvent {
|
|
352
|
+
type: string;
|
|
353
|
+
data?: {
|
|
354
|
+
path?: { text: string };
|
|
355
|
+
line_number?: number;
|
|
356
|
+
lines?: { text: string };
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: JSON ripgrep output parsing with context line collection
|
|
361
|
+
function parseRgJson(output: string, filterLowSignal: boolean): RgMatch[] {
|
|
362
|
+
const matches: RgMatch[] = [];
|
|
363
|
+
// Pending context lines that precede the next match
|
|
364
|
+
let pendingContext: Array<{ line: number; text: string }> = [];
|
|
365
|
+
|
|
366
|
+
for (const line of output.split("\n")) {
|
|
367
|
+
if (!line.trim()) continue;
|
|
368
|
+
let parsed: RawRgEvent;
|
|
369
|
+
try {
|
|
370
|
+
parsed = JSON.parse(line);
|
|
371
|
+
} catch {
|
|
372
|
+
continue;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
if (parsed.type === "context" && parsed.data) {
|
|
376
|
+
const lineNum = parsed.data.line_number;
|
|
377
|
+
const text = (parsed.data.lines?.text ?? "").trim();
|
|
378
|
+
if (lineNum) pendingContext.push({ line: lineNum, text });
|
|
379
|
+
continue;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
if (parsed.type === "match" && parsed.data) {
|
|
383
|
+
const filePath = parsed.data.path?.text;
|
|
384
|
+
const lineNum = parsed.data.line_number;
|
|
385
|
+
const text = (parsed.data.lines?.text ?? "").trim();
|
|
386
|
+
if (filePath && lineNum) {
|
|
387
|
+
// Split pendingContext: lines before this match are "before" context,
|
|
388
|
+
// lines from before this match line that trail the previous match stay with it.
|
|
389
|
+
const beforeCtx = pendingContext.filter((c) => c.line < lineNum);
|
|
390
|
+
const trailingCtx = pendingContext.filter((c) => c.line >= lineNum);
|
|
391
|
+
|
|
392
|
+
// Attach trailing context from previous match to the last accepted match
|
|
393
|
+
if (beforeCtx.length > 0 && matches.length > 0) {
|
|
394
|
+
const prev = matches[matches.length - 1];
|
|
395
|
+
const prevTrailing = beforeCtx.filter((c) => c.line > prev.line);
|
|
396
|
+
if (prevTrailing.length > 0) {
|
|
397
|
+
prev.context = [...(prev.context ?? []), ...prevTrailing];
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
if (filterLowSignal && isLowSignalPath(filePath)) {
|
|
402
|
+
pendingContext = [];
|
|
403
|
+
continue;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
const match: RgMatch = { file: filePath, line: lineNum, text };
|
|
407
|
+
// Leading context: lines just before this match
|
|
408
|
+
const leadingCtx =
|
|
409
|
+
matches.length > 0
|
|
410
|
+
? beforeCtx.filter(
|
|
411
|
+
(c) => c.line <= lineNum && c.line > (matches[matches.length - 1]?.line ?? 0),
|
|
412
|
+
)
|
|
413
|
+
: beforeCtx;
|
|
414
|
+
if (leadingCtx.length > 0) {
|
|
415
|
+
match.context = leadingCtx;
|
|
416
|
+
}
|
|
417
|
+
// Also include any pending context at/after this match's line (trailing from rg ordering)
|
|
418
|
+
pendingContext = trailingCtx;
|
|
419
|
+
matches.push(match);
|
|
420
|
+
} else {
|
|
421
|
+
pendingContext = [];
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
// Attach any trailing context lines to the last match
|
|
427
|
+
if (pendingContext.length > 0 && matches.length > 0) {
|
|
428
|
+
const last = matches[matches.length - 1];
|
|
429
|
+
last.context = [...(last.context ?? []), ...pendingContext];
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
return matches;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
/**
|
|
436
|
+
* Minimal interface for a reference-like object with a URI and range start.
|
|
437
|
+
* Used by {@link filterOutDeclaration} to avoid coupling to a specific LspRef type.
|
|
438
|
+
*/
|
|
439
|
+
export interface HasLspPosition {
|
|
440
|
+
uri: string;
|
|
441
|
+
range: { start: { line: number; character: number } };
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
/**
|
|
445
|
+
* Filter out the declaration/definition location from LSP references.
|
|
446
|
+
* LSP's `textDocument/references` includes the declaration by default;
|
|
447
|
+
* for callers/affected analysis, the declaration is not a call site or affected reference.
|
|
448
|
+
*
|
|
449
|
+
* Uses {@link uriToFile} for robust URI-to-path conversion.
|
|
450
|
+
*/
|
|
451
|
+
export function filterOutDeclaration<T extends HasLspPosition>(
|
|
452
|
+
refs: T[],
|
|
453
|
+
targetFile: string,
|
|
454
|
+
targetPos: { line: number; character: number },
|
|
455
|
+
): T[] {
|
|
456
|
+
return refs.filter((ref) => {
|
|
457
|
+
const filePath = uriToFile(ref.uri);
|
|
458
|
+
if (filePath !== targetFile) return true;
|
|
459
|
+
const start = ref.range.start;
|
|
460
|
+
return start.line !== targetPos.line || start.character !== targetPos.character;
|
|
461
|
+
});
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
/** Group matches by file. */
|
|
465
|
+
export function groupByFile(matches: RgMatch[]): Map<string, RgMatch[]> {
|
|
466
|
+
const byFile = new Map<string, RgMatch[]>();
|
|
467
|
+
for (const m of matches) {
|
|
468
|
+
const group = byFile.get(m.file) ?? [];
|
|
469
|
+
group.push(m);
|
|
470
|
+
byFile.set(m.file, group);
|
|
471
|
+
}
|
|
472
|
+
return byFile;
|
|
473
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { execFileSync } from "node:child_process";
|
|
2
|
+
import { createEvidenceList, renderEvidenceListDisclosure } from "../evidence.ts";
|
|
2
3
|
|
|
3
4
|
function scrubGitEnv(env: NodeJS.ProcessEnv): NodeJS.ProcessEnv {
|
|
4
5
|
const next = { ...env };
|
|
@@ -32,10 +33,7 @@ export function gatherGitContext(cwd: string): GitContext | null {
|
|
|
32
33
|
|
|
33
34
|
const status = execGit(cwd, ["status", "--porcelain"]).trim();
|
|
34
35
|
|
|
35
|
-
const dirtyFiles = status
|
|
36
|
-
.split("\n")
|
|
37
|
-
.filter(Boolean)
|
|
38
|
-
.map((line) => line.slice(3).trim());
|
|
36
|
+
const dirtyFiles = status.split("\n").filter(Boolean).map(parsePorcelainPath);
|
|
39
37
|
|
|
40
38
|
let lastCommitMessage: string | null = null;
|
|
41
39
|
try {
|
|
@@ -59,11 +57,17 @@ export function formatGitContext(ctx: GitContext): string {
|
|
|
59
57
|
lines.push(
|
|
60
58
|
`Uncommitted: ${ctx.dirtyFiles.length} file${ctx.dirtyFiles.length !== 1 ? "s" : ""}`,
|
|
61
59
|
);
|
|
62
|
-
|
|
60
|
+
const evidence = createEvidenceList({
|
|
61
|
+
key: "health.dirtyFiles",
|
|
62
|
+
items: ctx.dirtyFiles,
|
|
63
|
+
maxResults: 5,
|
|
64
|
+
});
|
|
65
|
+
for (const f of evidence.items) {
|
|
63
66
|
lines.push(`- \`${f}\``);
|
|
64
67
|
}
|
|
65
|
-
|
|
66
|
-
|
|
68
|
+
const disclosure = renderEvidenceListDisclosure(evidence);
|
|
69
|
+
if (disclosure) {
|
|
70
|
+
lines.push(disclosure);
|
|
67
71
|
}
|
|
68
72
|
} else {
|
|
69
73
|
lines.push("Working tree clean.");
|
|
@@ -74,3 +78,12 @@ export function formatGitContext(ctx: GitContext): string {
|
|
|
74
78
|
lines.push("");
|
|
75
79
|
return lines.join("\n");
|
|
76
80
|
}
|
|
81
|
+
|
|
82
|
+
function parsePorcelainPath(line: string): string {
|
|
83
|
+
const rawPath = line[2] === " " ? line.slice(3) : line.slice(2);
|
|
84
|
+
const renameSeparator = " -> ";
|
|
85
|
+
const renamedPath = rawPath.includes(renameSeparator)
|
|
86
|
+
? (rawPath.split(renameSeparator).at(-1) ?? rawPath)
|
|
87
|
+
: rawPath;
|
|
88
|
+
return renamedPath.trim();
|
|
89
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as path from "node:path";
|
|
2
2
|
import { readJsonFile } from "@mrclrchtr/supi-core/config";
|
|
3
|
-
import {
|
|
3
|
+
import type { SessionLspServiceState } from "@mrclrchtr/supi-lsp/api";
|
|
4
4
|
|
|
5
5
|
export interface PrioritySignalsSummary {
|
|
6
6
|
diagnosticsCount: number;
|
|
@@ -9,18 +9,24 @@ export interface PrioritySignalsSummary {
|
|
|
9
9
|
warnings: string[];
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
interface LoadedSignals {
|
|
12
|
+
export interface LoadedSignals {
|
|
13
13
|
diagnostics: Array<{ file: string; total: number; errors: number; warnings: number }>;
|
|
14
14
|
coverageByFile: Map<string, number>;
|
|
15
15
|
unusedFiles: Set<string>;
|
|
16
16
|
unusedExports: Array<{ file: string; name: string }>;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
export interface LoadPrioritizationSignalsOptions {
|
|
20
|
+
coveragePath?: string;
|
|
21
|
+
unusedPath?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
19
24
|
export function summarizePrioritySignalsForFiles(
|
|
20
25
|
cwd: string,
|
|
21
26
|
files: Iterable<string>,
|
|
27
|
+
lspService: SessionLspServiceState,
|
|
22
28
|
): PrioritySignalsSummary | null {
|
|
23
|
-
const loaded = loadPrioritizationSignals(cwd);
|
|
29
|
+
const loaded = loadPrioritizationSignals(cwd, lspService);
|
|
24
30
|
const relevantFiles = new Set([...files].map((file) => path.resolve(cwd, file)));
|
|
25
31
|
if (relevantFiles.size === 0) return null;
|
|
26
32
|
|
|
@@ -69,12 +75,16 @@ export function summarizePrioritySignalsForFiles(
|
|
|
69
75
|
: null;
|
|
70
76
|
}
|
|
71
77
|
|
|
72
|
-
export function loadPrioritizationSignals(
|
|
78
|
+
export function loadPrioritizationSignals(
|
|
79
|
+
cwd: string,
|
|
80
|
+
lspService: SessionLspServiceState,
|
|
81
|
+
options: LoadPrioritizationSignalsOptions = {},
|
|
82
|
+
): LoadedSignals {
|
|
73
83
|
return {
|
|
74
|
-
diagnostics: loadDiagnostics(cwd),
|
|
75
|
-
coverageByFile: loadCoverageSummary(cwd),
|
|
76
|
-
unusedFiles: loadUnusedFiles(cwd),
|
|
77
|
-
unusedExports: loadUnusedExports(cwd),
|
|
84
|
+
diagnostics: loadDiagnostics(cwd, lspService),
|
|
85
|
+
coverageByFile: loadCoverageSummary(cwd, options.coveragePath),
|
|
86
|
+
unusedFiles: loadUnusedFiles(cwd, options.unusedPath),
|
|
87
|
+
unusedExports: loadUnusedExports(cwd, options.unusedPath),
|
|
78
88
|
};
|
|
79
89
|
}
|
|
80
90
|
|
|
@@ -92,11 +102,12 @@ export function appendPrioritySignalsSection(
|
|
|
92
102
|
|
|
93
103
|
function loadDiagnostics(
|
|
94
104
|
cwd: string,
|
|
105
|
+
lspService: SessionLspServiceState,
|
|
95
106
|
): Array<{ file: string; total: number; errors: number; warnings: number }> {
|
|
96
|
-
|
|
97
|
-
if (
|
|
107
|
+
if (lspService.kind !== "ready") return [];
|
|
108
|
+
if (typeof lspService.service.getOutstandingDiagnosticSummary !== "function") return [];
|
|
98
109
|
|
|
99
|
-
return
|
|
110
|
+
return lspService.service.getOutstandingDiagnosticSummary(2).map((entry) => ({
|
|
100
111
|
file: path.resolve(cwd, entry.file),
|
|
101
112
|
total: entry.total,
|
|
102
113
|
errors: entry.errors,
|
|
@@ -104,8 +115,8 @@ function loadDiagnostics(
|
|
|
104
115
|
}));
|
|
105
116
|
}
|
|
106
117
|
|
|
107
|
-
function loadCoverageSummary(cwd: string): Map<string, number> {
|
|
108
|
-
const coveragePath = path.
|
|
118
|
+
function loadCoverageSummary(cwd: string, coveragePathInput?: string): Map<string, number> {
|
|
119
|
+
const coveragePath = path.resolve(cwd, coveragePathInput ?? "coverage/coverage-summary.json");
|
|
109
120
|
const parsed = readJsonFile(coveragePath);
|
|
110
121
|
if (!parsed) return new Map();
|
|
111
122
|
|
|
@@ -120,8 +131,8 @@ function loadCoverageSummary(cwd: string): Map<string, number> {
|
|
|
120
131
|
return map;
|
|
121
132
|
}
|
|
122
133
|
|
|
123
|
-
function loadUnusedFiles(cwd: string): Set<string> {
|
|
124
|
-
const parsed = loadKnipJson(cwd);
|
|
134
|
+
function loadUnusedFiles(cwd: string, unusedPath?: string): Set<string> {
|
|
135
|
+
const parsed = loadKnipJson(cwd, unusedPath);
|
|
125
136
|
const values = Array.isArray(parsed?.files) ? parsed.files : [];
|
|
126
137
|
const files = values
|
|
127
138
|
.map((value) => toPathString(value))
|
|
@@ -130,8 +141,11 @@ function loadUnusedFiles(cwd: string): Set<string> {
|
|
|
130
141
|
return new Set(files);
|
|
131
142
|
}
|
|
132
143
|
|
|
133
|
-
function loadUnusedExports(
|
|
134
|
-
|
|
144
|
+
function loadUnusedExports(
|
|
145
|
+
cwd: string,
|
|
146
|
+
unusedPath?: string,
|
|
147
|
+
): Array<{ file: string; name: string }> {
|
|
148
|
+
const parsed = loadKnipJson(cwd, unusedPath);
|
|
135
149
|
const values = Array.isArray(parsed?.exports) ? parsed.exports : [];
|
|
136
150
|
const exports: Array<{ file: string; name: string }> = [];
|
|
137
151
|
|
|
@@ -152,8 +166,8 @@ function loadUnusedExports(cwd: string): Array<{ file: string; name: string }> {
|
|
|
152
166
|
return exports;
|
|
153
167
|
}
|
|
154
168
|
|
|
155
|
-
function loadKnipJson(cwd: string): Record<string, unknown> | null {
|
|
156
|
-
return readJsonFile(path.
|
|
169
|
+
function loadKnipJson(cwd: string, unusedPath?: string): Record<string, unknown> | null {
|
|
170
|
+
return readJsonFile(path.resolve(cwd, unusedPath ?? "knip.json"));
|
|
157
171
|
}
|
|
158
172
|
|
|
159
173
|
function getPct(value: object, key: string): number | null {
|