@herbertgao/pi-extensions 2026.8.5 → 2026.8.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +2 -2
- package/node_modules/@herbertgao/pi-cc-extensions/README.md +2 -2
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/config.ts +19 -7
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +30 -9
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/compact-thinking.ts +272 -22
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/context.ts +74 -5
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/compact-mode.ts +94 -77
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/markdown-enhance.ts +48 -6
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/message-display.ts +1 -1
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/hover.ts +14 -0
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/interaction.ts +55 -17
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/layout.ts +41 -2
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-renderer.ts +75 -6
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/types.ts +7 -3
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/grouping.ts +64 -1
- package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
- package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +16 -0
- package/node_modules/@herbertgao/pi-subagents/README.md +30 -22
- package/node_modules/@herbertgao/pi-subagents/examples/agent-tool-description.md +5 -5
- package/node_modules/@herbertgao/pi-subagents/package.json +7 -7
- package/node_modules/@herbertgao/pi-subagents/src/agent-file-toggle.ts +7 -1
- package/node_modules/@herbertgao/pi-subagents/src/agent-manager.ts +48 -19
- package/node_modules/@herbertgao/pi-subagents/src/agent-runner.ts +22 -15
- package/node_modules/@herbertgao/pi-subagents/src/custom-agents.ts +26 -2
- package/node_modules/@herbertgao/pi-subagents/src/index.ts +219 -40
- package/node_modules/@herbertgao/pi-subagents/src/invocation-config.ts +101 -3
- package/node_modules/@herbertgao/pi-subagents/src/nested-tools.ts +18 -4
- package/node_modules/@herbertgao/pi-subagents/src/settings.ts +99 -0
- package/node_modules/@herbertgao/pi-subagents/src/types.ts +22 -3
- package/node_modules/@herbertgao/pi-subagents/src/ui/agent-widget.ts +51 -3
- package/node_modules/@herbertgao/pi-subagents/src/ui/conversation-viewer.ts +20 -2
- package/node_modules/@herbertgao/pi-subagents/src/ui/fleet-list.ts +34 -10
- package/node_modules/@herbertgao/pi-subagents/src/usage.ts +129 -1
- package/node_modules/@herbertgao/pi-subagents/src/worktree.ts +29 -5
- package/node_modules/@juicesharp/rpiv-ask-user-question/README.md +3 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/ask-user-question.ts +46 -10
- package/node_modules/@juicesharp/rpiv-ask-user-question/config.ts +25 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/docs/configuration.md +13 -4
- package/node_modules/@juicesharp/rpiv-ask-user-question/docs/hosts.md +8 -1
- package/node_modules/@juicesharp/rpiv-ask-user-question/docs/localization.md +3 -1
- package/node_modules/@juicesharp/rpiv-ask-user-question/locales/en.json +2 -2
- package/node_modules/@juicesharp/rpiv-ask-user-question/locales/zh.json +2 -2
- package/node_modules/@juicesharp/rpiv-ask-user-question/package.json +3 -2
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/build-questionnaire.ts +10 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/key-router.ts +3 -1
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/questionnaire-session.ts +30 -7
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/state.ts +14 -6
- package/node_modules/@juicesharp/rpiv-ask-user-question/view/dialog-builder.ts +30 -4
- package/node_modules/@juicesharp/rpiv-ask-user-question/view/tab-content-strategy.ts +26 -5
- package/node_modules/@narumitw/pi-btw/README.md +119 -103
- package/node_modules/@narumitw/pi-btw/dist/index.ts +2898 -0
- package/node_modules/@narumitw/pi-btw/dist/index.ts.map +7 -0
- package/node_modules/@narumitw/pi-btw/package.json +13 -9
- package/node_modules/@narumitw/pi-btw/src/btw.ts +40 -42
- package/node_modules/@narumitw/pi-btw/src/fullscreen-ui.ts +55 -10
- package/node_modules/@narumitw/pi-btw/src/main-tree-picker.ts +390 -0
- package/node_modules/@narumitw/pi-btw/src/menu.ts +78 -15
- package/node_modules/@narumitw/pi-btw/src/settings.ts +22 -2
- package/node_modules/@narumitw/pi-btw/src/transcript-pager.ts +136 -45
- package/node_modules/pi-lens/CHANGELOG.md +1004 -0
- package/node_modules/pi-lens/README.md +11 -3
- package/node_modules/pi-lens/config/ruff/core.toml +42 -0
- package/node_modules/pi-lens/dist/clients/actionable-warnings.js +130 -27
- package/node_modules/pi-lens/dist/clients/advisory-provenance.js +427 -0
- package/node_modules/pi-lens/dist/clients/agent-nudge.js +79 -16
- package/node_modules/pi-lens/dist/clients/ast-grep-client.js +9 -3
- package/node_modules/pi-lens/dist/clients/atomic-write.js +9 -3
- package/node_modules/pi-lens/dist/clients/bash-file-access.js +285 -8
- package/node_modules/pi-lens/dist/clients/biome-client.js +176 -37
- package/node_modules/pi-lens/dist/clients/blocker-freshness.js +428 -0
- package/node_modules/pi-lens/dist/clients/blocker-past-eof.js +119 -0
- package/node_modules/pi-lens/dist/clients/bootstrap.js +12 -1
- package/node_modules/pi-lens/dist/clients/bounded-pid-file-lock.js +12 -3
- package/node_modules/pi-lens/dist/clients/bounded-telemetry.js +192 -0
- package/node_modules/pi-lens/dist/clients/bus-events-logger.js +62 -6
- package/node_modules/pi-lens/dist/clients/bus-publish.js +11 -3
- package/node_modules/pi-lens/dist/clients/cascade-budget.js +196 -0
- package/node_modules/pi-lens/dist/clients/cascade-format.js +76 -2
- package/node_modules/pi-lens/dist/clients/cascade-types.js +9 -1
- package/node_modules/pi-lens/dist/clients/child-unref.js +54 -6
- package/node_modules/pi-lens/dist/clients/code-quality-warnings.js +76 -24
- package/node_modules/pi-lens/dist/clients/console-guard-install.js +16 -4
- package/node_modules/pi-lens/dist/clients/dead-code-client.js +249 -52
- package/node_modules/pi-lens/dist/clients/deadline-utils.js +8 -1
- package/node_modules/pi-lens/dist/clients/debug-handles.js +5 -0
- package/node_modules/pi-lens/dist/clients/degradation-ledger.js +62 -13
- package/node_modules/pi-lens/dist/clients/dependency-checker.js +43 -9
- package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +153 -37
- package/node_modules/pi-lens/dist/clients/diagnostic-line-freshness.js +298 -0
- package/node_modules/pi-lens/dist/clients/diagnostics-publish.js +10 -3
- package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +165 -11
- package/node_modules/pi-lens/dist/clients/dispatch/integration.js +325 -72
- package/node_modules/pi-lens/dist/clients/dispatch/lazy.js +7 -4
- package/node_modules/pi-lens/dist/clients/dispatch/plan.js +5 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ast-grep-napi.js +234 -18
- package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +187 -19
- package/node_modules/pi-lens/dist/clients/dispatch/runners/cpp-check.js +6 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/credo.js +11 -9
- package/node_modules/pi-lens/dist/clients/dispatch/runners/cue-vet.js +398 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/elixir-check.js +11 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/eslint.js +12 -7
- package/node_modules/pi-lens/dist/clients/dispatch/runners/go-vet.js +18 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-render.js +895 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/index.js +4 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/javac.js +16 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +81 -41
- package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +16 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/mypy.js +23 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/psscriptanalyzer.js +331 -55
- package/node_modules/pi-lens/dist/clients/dispatch/runners/pyright.js +38 -5
- package/node_modules/pi-lens/dist/clients/dispatch/runners/rust-clippy.js +97 -19
- package/node_modules/pi-lens/dist/clients/dispatch/runners/spellcheck.js +14 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/sqlfluff.js +20 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/stylelint.js +22 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/swiftlint.js +10 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/taplo.js +18 -6
- package/node_modules/pi-lens/dist/clients/dispatch/runners/trivy-config.js +73 -12
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/availability-policy.js +488 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/candidate-probe.js +84 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/lazy-installer.js +260 -27
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +943 -93
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/spawn-outcome.js +86 -11
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/tool-failure.js +72 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/toolchain-availability.js +106 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/vale.js +9 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/yamllint.js +18 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/zig-check.js +4 -2
- package/node_modules/pi-lens/dist/clients/disposition-publish.js +10 -3
- package/node_modules/pi-lens/dist/clients/eval-timestamp.js +17 -0
- package/node_modules/pi-lens/dist/clients/event-loop-monitor.js +28 -5
- package/node_modules/pi-lens/dist/clients/extension-log.js +317 -3
- package/node_modules/pi-lens/dist/clients/file-kinds.js +8 -2
- package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +294 -0
- package/node_modules/pi-lens/dist/clients/finding-identity.js +88 -0
- package/node_modules/pi-lens/dist/clients/fix-worklog.js +5 -1
- package/node_modules/pi-lens/dist/clients/format-events-publish.js +39 -8
- package/node_modules/pi-lens/dist/clients/formatters-lazy.js +3 -2
- package/node_modules/pi-lens/dist/clients/formatters.js +500 -115
- package/node_modules/pi-lens/dist/clients/generation-guard.js +216 -0
- package/node_modules/pi-lens/dist/clients/git-guard.js +49 -21
- package/node_modules/pi-lens/dist/clients/gitleaks-client.js +181 -8
- package/node_modules/pi-lens/dist/clients/go-client.js +21 -39
- package/node_modules/pi-lens/dist/clients/govulncheck-client.js +219 -10
- package/node_modules/pi-lens/dist/clients/grammar-source.js +333 -10
- package/node_modules/pi-lens/dist/clients/host-ports.js +9 -1
- package/node_modules/pi-lens/dist/clients/installer/index.js +1119 -101
- package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh-session.js +58 -0
- package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh.js +715 -0
- package/node_modules/pi-lens/dist/clients/instance-reaper.js +643 -97
- package/node_modules/pi-lens/dist/clients/instance-registry.js +87 -17
- package/node_modules/pi-lens/dist/clients/jscpd-client.js +86 -15
- package/node_modules/pi-lens/dist/clients/knip-client.js +361 -24
- package/node_modules/pi-lens/dist/clients/language-policy.js +8 -2
- package/node_modules/pi-lens/dist/clients/language-profile.js +2 -0
- package/node_modules/pi-lens/dist/clients/latency-logger.js +487 -9
- package/node_modules/pi-lens/dist/clients/lazy-import.js +21 -0
- package/node_modules/pi-lens/dist/clients/ledger-bounds.js +21 -0
- package/node_modules/pi-lens/dist/clients/lens-events.js +56 -25
- package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +16 -0
- package/node_modules/pi-lens/dist/clients/live-bus-emitter.js +45 -2
- package/node_modules/pi-lens/dist/clients/lsp/aggregation.js +30 -4
- package/node_modules/pi-lens/dist/clients/lsp/cascade-tier.js +160 -20
- package/node_modules/pi-lens/dist/clients/lsp/client.js +1666 -148
- package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +111 -0
- package/node_modules/pi-lens/dist/clients/lsp/document-drift.js +389 -0
- package/node_modules/pi-lens/dist/clients/lsp/index.js +2496 -171
- package/node_modules/pi-lens/dist/clients/lsp/inferred-project.js +215 -0
- package/node_modules/pi-lens/dist/clients/lsp/jvm-runtime.js +146 -14
- package/node_modules/pi-lens/dist/clients/lsp/language.js +48 -4
- package/node_modules/pi-lens/dist/clients/lsp/server.js +517 -69
- package/node_modules/pi-lens/dist/clients/lsp/spawn-history.js +22 -0
- package/node_modules/pi-lens/dist/clients/lsp/sync-kind.js +43 -0
- package/node_modules/pi-lens/dist/clients/lsp/tsserver-sync.js +172 -0
- package/node_modules/pi-lens/dist/clients/lsp/wait-policy/classification.js +21 -5
- package/node_modules/pi-lens/dist/clients/lsp/wait-policy/strategies.js +61 -3
- package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +422 -28
- package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-session.js +30 -0
- package/node_modules/pi-lens/dist/clients/lsp/workspace-sweep-hold.js +175 -0
- package/node_modules/pi-lens/dist/clients/lsp-lazy.js +3 -2
- package/node_modules/pi-lens/dist/clients/mcp/analyze.js +4 -0
- package/node_modules/pi-lens/dist/clients/mcp/session.js +39 -18
- package/node_modules/pi-lens/dist/clients/model-provider.js +53 -0
- package/node_modules/pi-lens/dist/clients/module-report.js +8 -0
- package/node_modules/pi-lens/dist/clients/opengrep-client.js +15 -1
- package/node_modules/pi-lens/dist/clients/package-manager.js +170 -14
- package/node_modules/pi-lens/dist/clients/path-attribution-telemetry.js +27 -0
- package/node_modules/pi-lens/dist/clients/path-utils.js +160 -0
- package/node_modules/pi-lens/dist/clients/pipeline.js +178 -30
- package/node_modules/pi-lens/dist/clients/post-autofix-notice.js +37 -0
- package/node_modules/pi-lens/dist/clients/project-diagnostics/cache.js +17 -3
- package/node_modules/pi-lens/dist/clients/project-diagnostics/extractors.js +89 -22
- package/node_modules/pi-lens/dist/clients/project-diagnostics/fresh-fetch.js +85 -15
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/gitleaks.js +15 -3
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/runner-findings.js +23 -2
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/trivy.js +50 -2
- package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +5 -0
- package/node_modules/pi-lens/dist/clients/project-lens-config.js +3 -0
- package/node_modules/pi-lens/dist/clients/project-snapshot.js +299 -0
- package/node_modules/pi-lens/dist/clients/quiet-window-config.js +47 -0
- package/node_modules/pi-lens/dist/clients/quiet-window.js +11 -25
- package/node_modules/pi-lens/dist/clients/read-guard-logger.js +1 -1
- package/node_modules/pi-lens/dist/clients/read-guard.js +184 -10
- package/node_modules/pi-lens/dist/clients/resource-sampler.js +49 -17
- package/node_modules/pi-lens/dist/clients/reverse-deps.js +50 -11
- package/node_modules/pi-lens/dist/clients/review-graph/query.js +76 -4
- package/node_modules/pi-lens/dist/clients/run-duration.js +55 -0
- package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +248 -13
- package/node_modules/pi-lens/dist/clients/runtime-context.js +112 -12
- package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +472 -61
- package/node_modules/pi-lens/dist/clients/runtime-session.js +359 -13
- package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +217 -22
- package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +269 -22
- package/node_modules/pi-lens/dist/clients/runtime-turn.js +948 -87
- package/node_modules/pi-lens/dist/clients/rust-client.js +21 -37
- package/node_modules/pi-lens/dist/clients/safe-spawn.js +220 -7
- package/node_modules/pi-lens/dist/clients/scratch-tree-policy.js +161 -0
- package/node_modules/pi-lens/dist/clients/search-read-registration.js +34 -6
- package/node_modules/pi-lens/dist/clients/security-scan-client.js +224 -8
- package/node_modules/pi-lens/dist/clients/sg-runner.js +249 -37
- package/node_modules/pi-lens/dist/clients/single-flight.js +158 -0
- package/node_modules/pi-lens/dist/clients/smells-rollup.js +18 -11
- package/node_modules/pi-lens/dist/clients/stale-marker.js +17 -0
- package/node_modules/pi-lens/dist/clients/startup-timing.js +26 -2
- package/node_modules/pi-lens/dist/clients/test-runner-client.js +574 -32
- package/node_modules/pi-lens/dist/clients/tool-event.js +56 -5
- package/node_modules/pi-lens/dist/clients/tool-policy.js +127 -20
- package/node_modules/pi-lens/dist/clients/tool-set-policy.js +76 -0
- package/node_modules/pi-lens/dist/clients/tree-sitter-cache.js +75 -1
- package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +769 -64
- package/node_modules/pi-lens/dist/clients/tree-sitter-shared.js +11 -0
- package/node_modules/pi-lens/dist/clients/tree-sitter-symbol-extractor.js +90 -0
- package/node_modules/pi-lens/dist/clients/trivy-client.js +19 -1
- package/node_modules/pi-lens/dist/clients/warm-attach.js +17 -0
- package/node_modules/pi-lens/dist/clients/widget-state.js +336 -36
- package/node_modules/pi-lens/dist/clients/word-index.js +305 -33
- package/node_modules/pi-lens/dist/clients/zizmor-config.js +214 -14
- package/node_modules/pi-lens/dist/index.js +64677 -49484
- package/node_modules/pi-lens/dist/mcp/server.js +8 -2
- package/node_modules/pi-lens/dist/tools/activate-tools.js +17 -5
- package/node_modules/pi-lens/dist/tools/ast-grep-replace.js +9 -4
- package/node_modules/pi-lens/dist/tools/lens-diagnostic-mark.js +5 -2
- package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +469 -56
- package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +190 -46
- package/node_modules/pi-lens/dist/tools/lsp-navigation.js +46 -7
- package/node_modules/pi-lens/dist/tools/symbol-search.js +1 -1
- package/node_modules/pi-lens/docs/agent-guide.md +44 -14
- package/node_modules/pi-lens/docs/ast-grep_rules_catalog.md +518 -501
- package/node_modules/pi-lens/docs/dispositions.md +21 -0
- package/node_modules/pi-lens/docs/features.md +33 -6
- package/node_modules/pi-lens/docs/globalconfig.md +14 -0
- package/node_modules/pi-lens/docs/language-coverage.md +71 -5
- package/node_modules/pi-lens/docs/mcp.md +2 -2
- package/node_modules/pi-lens/docs/servercapabilities.md +4 -1
- package/node_modules/pi-lens/docs/settings.md +25 -1
- package/node_modules/pi-lens/docs/usage.md +24 -5
- package/node_modules/pi-lens/docs/word-index.md +35 -0
- package/node_modules/pi-lens/package.json +10 -6
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/__snapshots__/no-reflect-get-js-snapshot.yml +23 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/__snapshots__/no-reflect-get-snapshot.yml +23 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/__snapshots__/ts-void-zero-snapshot.yml +23 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-bare-object-param-test.yml +16 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-chained-type-assertions-test.yml +22 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-compile-call-test.yml +29 -1
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-conditional-empty-object-spread-js-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-conditional-empty-object-spread-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-dupe-class-members-test.yml +33 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-inner-html-js-test.yml +7 -1
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-inner-html-test.yml +7 -1
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-known-value-widening-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-non-null-assertion-test.yml +216 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-js-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-js-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-return-value-in-generator-test.yml +12 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-runtime-typeof-test.yml +33 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-server-bind-wildcard-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-shape-in-symbol-names-test.yml +13 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-sql-in-code-js-test.yml +5 -1
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-sql-in-code-test.yml +5 -1
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unknown-laundering-test.yml +11 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unknown-parameters-test.yml +12 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unknown-returns-test.yml +16 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unsafe-dictionary-any-test.yml +10 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unsafe-dictionary-unknown-test.yml +8 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/redundant-unsafe-function-test.yml +35 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/require-safety-comment-for-as-unknown-as-test.yml +177 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/ts-void-zero-test.yml +1 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-await-expression-member-js.yml +13 -2
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-await-expression-member.yml +13 -2
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-host-path-in-win32-branch.yml +2 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-object-param.yml +60 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-chained-type-assertions.yml +66 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-compile-call.yml +63 -5
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-conditional-empty-object-spread-js.yml +21 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-conditional-empty-object-spread.yml +29 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-dupe-class-members.yml +52 -8
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-inner-html-js.yml +27 -2
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-inner-html.yml +27 -2
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-known-value-widening.yml +71 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-non-null-assertion.yml +316 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-raw-json-store-write.yml +7 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply-js.yml +29 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply.yml +30 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get-js.yml +41 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get.yml +42 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-return-value-in-generator.yml +22 -5
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-runtime-typeof.yml +121 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-server-bind-wildcard.yml +23 -7
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-shape-in-symbol-names.yml +68 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-sql-in-code-js.yml +41 -2
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-sql-in-code.yml +41 -2
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-laundering.yml +32 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-parameters.yml +67 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-returns.yml +106 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unsafe-dictionary-any.yml +50 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unsafe-dictionary-unknown.yml +56 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-win32-isabsolute-for-qualification.yml +2 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/redundant-unsafe-function.yml +32 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/require-safety-comment-for-as-unknown-as.yml +184 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/ts-void-zero.yml +5 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/self-scan-baseline.json +5 -0
- package/node_modules/pi-lens/scripts/analyze-pi-lens-logs.mjs +132 -1
- package/node_modules/pi-lens/scripts/download-grammars.js +25 -0
- package/node_modules/pi-lens/scripts/grammars.lock.json +9 -0
- package/node_modules/pi-lens/skills/pi-lens-ast-grep/SKILL.md +12 -11
- package/node_modules/pi-lens/skills/pi-lens-lsp-navigation/SKILL.md +22 -22
- package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/SKILL.md +87 -116
- package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/reference.md +170 -0
- package/node_modules/pi-lens/skills/pi-lens-write-tree-sitter-rule/SKILL.md +3 -1
- package/node_modules/pi-lens/vendor/grammars/tree-sitter-cue.wasm +0 -0
- package/node_modules/pi-mcp-adapter/CHANGELOG.md +49 -0
- package/node_modules/pi-mcp-adapter/README.md +51 -6
- package/node_modules/pi-mcp-adapter/agent-dir.ts +12 -4
- package/node_modules/pi-mcp-adapter/cli.js +188 -5
- package/node_modules/pi-mcp-adapter/commands.ts +128 -22
- package/node_modules/pi-mcp-adapter/config.ts +28 -10
- package/node_modules/pi-mcp-adapter/direct-tools.ts +23 -19
- package/node_modules/pi-mcp-adapter/index.ts +219 -32
- package/node_modules/pi-mcp-adapter/init.ts +36 -4
- package/node_modules/pi-mcp-adapter/lifecycle.ts +315 -24
- package/node_modules/pi-mcp-adapter/mcp-auth-flow.ts +39 -6
- package/node_modules/pi-mcp-adapter/mcp-bearer-store.ts +387 -0
- package/node_modules/pi-mcp-adapter/mcp-callback-server.ts +27 -3
- package/node_modules/pi-mcp-adapter/mcp-code.ts +4 -0
- package/node_modules/pi-mcp-adapter/mcp-panel.ts +42 -13
- package/node_modules/pi-mcp-adapter/mcp-setup-panel.ts +2 -1
- package/node_modules/pi-mcp-adapter/metadata-cache.ts +46 -25
- package/node_modules/pi-mcp-adapter/package-mcp-loader.ts +168 -0
- package/node_modules/pi-mcp-adapter/package.json +4 -1
- package/node_modules/pi-mcp-adapter/proxy-modes.ts +5 -4
- package/node_modules/pi-mcp-adapter/request-headers-command.ts +330 -0
- package/node_modules/pi-mcp-adapter/search-ranking.ts +92 -22
- package/node_modules/pi-mcp-adapter/server-manager.ts +145 -2
- package/node_modules/pi-mcp-adapter/session-recovery.ts +7 -0
- package/node_modules/pi-mcp-adapter/tool-approval.ts +15 -2
- package/node_modules/pi-mcp-adapter/tool-metadata.ts +38 -18
- package/node_modules/pi-mcp-adapter/tool-result-renderer.ts +44 -4
- package/node_modules/pi-mcp-adapter/types.ts +95 -10
- package/node_modules/pi-mcp-adapter/ui-server.ts +18 -16
- package/node_modules/pi-mcp-adapter/utils.ts +70 -0
- package/node_modules/pi-web-access/CHANGELOG.md +37 -0
- package/node_modules/pi-web-access/README.md +38 -14
- package/node_modules/pi-web-access/anysearch.ts +4 -2
- package/node_modules/pi-web-access/auth-fetch.ts +148 -0
- package/node_modules/pi-web-access/brave.ts +16 -4
- package/node_modules/pi-web-access/chrome-cookies.ts +110 -23
- package/node_modules/pi-web-access/curator-page.ts +8 -3
- package/node_modules/pi-web-access/curator-server.ts +5 -1
- package/node_modules/pi-web-access/exa.ts +18 -7
- package/node_modules/pi-web-access/extract.ts +134 -37
- package/node_modules/pi-web-access/fetch-params.ts +17 -3
- package/node_modules/pi-web-access/firecrawl.ts +172 -12
- package/node_modules/pi-web-access/gemini-search.ts +33 -7
- package/node_modules/pi-web-access/index.ts +160 -104
- package/node_modules/pi-web-access/package.json +2 -2
- package/node_modules/pi-web-access/page-query.ts +4 -2
- package/node_modules/pi-web-access/parallel-mcp.ts +249 -0
- package/node_modules/pi-web-access/parallel.ts +2 -2
- package/node_modules/pi-web-access/query-rewrite.ts +51 -0
- package/node_modules/pi-web-access/serper.ts +211 -0
- package/node_modules/pi-web-access/summary-model-scope.ts +12 -4
- package/node_modules/pi-web-access/summary-review.ts +51 -23
- package/node_modules/pi-web-access/tavily.ts +16 -4
- package/node_modules/pi-web-access/utils.ts +87 -0
- package/node_modules/pi-web-access/valyu.ts +199 -0
- package/node_modules/pi-web-access/youtube-extract.ts +2 -2
- package/package.json +13 -13
|
@@ -10,15 +10,16 @@ import { Type } from "../clients/deps/typebox.js";
|
|
|
10
10
|
import { getProjectIgnoreMatcher, isExcludedDirName, } from "../clients/file-utils.js";
|
|
11
11
|
import { getLSPService, groupFilesByPrimaryServer, runPerServerGroups, } from "../clients/lsp/index.js";
|
|
12
12
|
import { buildScopeKey, createWorkspaceDiagnosticsCacheContext, } from "../clients/lsp/workspace-diagnostics-cache.js";
|
|
13
|
-
import { primaryServerId } from "../clients/lsp/config.js";
|
|
13
|
+
import { getServersForFileWithConfig, primaryServerId, } from "../clients/lsp/config.js";
|
|
14
14
|
import { combineAbortSignals, withDeadline } from "../clients/deadline-utils.js";
|
|
15
15
|
import { applyAuxiliarySuppressions, retagAuxiliaryDiagnostics, } from "../clients/dispatch/auxiliary-lsp.js";
|
|
16
16
|
import { detectFileRole } from "../clients/file-role.js";
|
|
17
|
-
import { hashDiagnosticContent, } from "../clients/lsp/diagnostic-binding.js";
|
|
17
|
+
import { hashDiagnosticContent, touchCompletedConfirmationPolicy, touchCoverageGap, } from "../clients/lsp/diagnostic-binding.js";
|
|
18
18
|
import { classifyCascadeWaitTier } from "../clients/lsp/wait-policy/index.js";
|
|
19
19
|
import { attemptTsserverSyncDiagnostics, } from "../clients/lsp/tsserver-sync.js";
|
|
20
20
|
import { convertLspDiagnostics } from "../clients/dispatch/utils/lsp-diagnostics.js";
|
|
21
|
-
import {
|
|
21
|
+
import { demoteInferredProjectDiagnostics } from "../clients/lsp/inferred-project.js";
|
|
22
|
+
import { isBlocking, reconcileScanDiagnostics } from "../clients/widget-state.js";
|
|
22
23
|
import { baseName, compactRenderResult } from "./render-compact.js";
|
|
23
24
|
import { makeProgressReporter, scanningSummaryLine } from "./scan-progress.js";
|
|
24
25
|
import { isWarmAttached, tryWarmAttachedDiagnostics, } from "../clients/warm-attach.js";
|
|
@@ -239,7 +240,14 @@ export function createLspDiagnosticsTool(
|
|
|
239
240
|
// confirmed result reconciled into the footer reserves its token when the
|
|
240
241
|
// per-file check starts, so settlement order cannot make an older result look
|
|
241
242
|
// newer. Optional/undefined in tests.
|
|
242
|
-
nextWriteIndex
|
|
243
|
+
nextWriteIndex,
|
|
244
|
+
// #1561: #571 wired this tool's confirmed result into the widget footer and
|
|
245
|
+
// stopped there. The inline-blocker map is a SECOND agent-facing store fed by
|
|
246
|
+
// the same dispatch verdict, and nothing retired it — so pi-lens kept
|
|
247
|
+
// injecting "Unresolved from this turn" for three more turns after answering
|
|
248
|
+
// "confirmed clean" for the same file. index.ts injects
|
|
249
|
+
// `runtime.retireInlineBlockerOnConfirmedClean`. Optional/undefined in tests.
|
|
250
|
+
onConfirmedNoBlockers) {
|
|
243
251
|
return {
|
|
244
252
|
name: "lsp_diagnostics",
|
|
245
253
|
label: "LSP Diagnostics",
|
|
@@ -387,6 +395,7 @@ nextWriteIndex) {
|
|
|
387
395
|
nextWriteIndex,
|
|
388
396
|
serverScope,
|
|
389
397
|
cwd,
|
|
398
|
+
onConfirmedNoBlockers,
|
|
390
399
|
});
|
|
391
400
|
}
|
|
392
401
|
const rawPath = typedParams.path;
|
|
@@ -427,9 +436,10 @@ nextWriteIndex) {
|
|
|
427
436
|
nextWriteIndex,
|
|
428
437
|
serverScope,
|
|
429
438
|
cwd,
|
|
439
|
+
onConfirmedNoBlockers,
|
|
430
440
|
});
|
|
431
441
|
}
|
|
432
|
-
return runFileDiagnostics(absPath, severity, lspService, waitMs, nextWriteIndex, serverScope, cwd);
|
|
442
|
+
return runFileDiagnostics(absPath, severity, lspService, waitMs, nextWriteIndex, serverScope, cwd, onConfirmedNoBlockers);
|
|
433
443
|
},
|
|
434
444
|
};
|
|
435
445
|
}
|
|
@@ -471,8 +481,15 @@ async function collectDiagnosticsForFile(absPath, lspService, waitMs, serverScop
|
|
|
471
481
|
// confirmation: it carries the same caveat all-scope local
|
|
472
482
|
// touches do, and classic TypeScript still needs the primary-only
|
|
473
483
|
// tsserver sync check below rather than this verdict.
|
|
474
|
-
|
|
484
|
+
// #1470: `"partial"` counts, for the same reason the local touch
|
|
485
|
+
// branch below accepts it — the incumbent's primary confirmed; only
|
|
486
|
+
// a named auxiliary did not.
|
|
487
|
+
confirmedByTouch: attached.response.confirmation !== undefined &&
|
|
475
488
|
primaryServerId(absPath) !== "typescript",
|
|
489
|
+
// #1470: the incumbent's narrowed verdict, carried as an explicit DTO
|
|
490
|
+
// field across the socket. An older incumbent omits it → empty → the
|
|
491
|
+
// pre-#1470 handling, unchanged.
|
|
492
|
+
unconfirmedServerIds: attached.response.unconfirmedServerIds ?? [],
|
|
476
493
|
content,
|
|
477
494
|
};
|
|
478
495
|
}
|
|
@@ -526,11 +543,20 @@ async function collectDiagnosticsForFile(absPath, lspService, waitMs, serverScop
|
|
|
526
543
|
// one; the openFile-only / getDiagnostics fallback leaves it undefined →
|
|
527
544
|
// "unknown", no demotion).
|
|
528
545
|
const binding = usedTouch ? touched?.binding : undefined;
|
|
529
|
-
|
|
546
|
+
// #1470: `"partial"` counts here. `confirmedByTouch` feeds
|
|
547
|
+
// `canTrustTouchConfirmation`, which asks about the PRIMARY's own verdict —
|
|
548
|
+
// and a partial touch is one whose primary confirmed while an auxiliary was
|
|
549
|
+
// cut off. Excluding it would render "Primary LSP: unconfirmed" for a primary
|
|
550
|
+
// that did confirm. The coverage gap is carried separately, below.
|
|
551
|
+
const confirmedByTouch = usedTouch && touchCompletedConfirmationPolicy(touched);
|
|
530
552
|
return {
|
|
531
553
|
diagnostics: filtered,
|
|
532
554
|
timedOut,
|
|
533
555
|
confirmedByTouch,
|
|
556
|
+
// #1470: only a touch actually contributes a coverage gap; the
|
|
557
|
+
// openFile+getDiagnostics fallback never reports one, which is honest —
|
|
558
|
+
// that path claims no confirmation at all.
|
|
559
|
+
unconfirmedServerIds: usedTouch ? touchCoverageGap(touched) : [],
|
|
534
560
|
content,
|
|
535
561
|
binding,
|
|
536
562
|
};
|
|
@@ -616,35 +642,66 @@ function canTrustTouchConfirmation(file, serverScope, confirmedByTouch) {
|
|
|
616
642
|
(serverScope === "primary" || primaryServerId(file) !== "typescript"));
|
|
617
643
|
}
|
|
618
644
|
/**
|
|
619
|
-
* #
|
|
620
|
-
* (`widget-state.ts`'s `allDiagnostics`) — same shared choke point
|
|
621
|
-
* `lens_diagnostics` mode=full uses (`clients/widget-state.ts`'s
|
|
622
|
-
* `reconcileScanDiagnostics`). A manual `lsp_diagnostics` check that proves a
|
|
623
|
-
* stale footer error is actually gone (the real-world case that surfaced
|
|
624
|
-
* #571) is exactly the kind of confirmed result that should correct it.
|
|
625
|
-
* Direct `lsp_diagnostics` deliberately does not perform a second disk read at
|
|
626
|
-
* this reconciliation seam: its collecting touch already read the content and
|
|
627
|
-
* supplies the binding verdict. `false` is unconfirmed and is never written;
|
|
628
|
-
* `true` is trusted, while an absent/`unknown` verdict preserves the legacy
|
|
629
|
-
* fail-open policy for servers that cannot bind their diagnostics to content.
|
|
645
|
+
* #1561 F1: what this check is entitled to speak for.
|
|
630
646
|
*
|
|
631
|
-
*
|
|
632
|
-
*
|
|
633
|
-
*
|
|
634
|
-
*
|
|
635
|
-
* `
|
|
636
|
-
*
|
|
637
|
-
*
|
|
647
|
+
* Inline blockers are raised by the whole dispatch — eslint, biome-check,
|
|
648
|
+
* actionlint, ast-grep security rules — while this tool only ever consults
|
|
649
|
+
* language servers. Retiring one therefore needs an explicit coverage claim,
|
|
650
|
+
* and the honest claim is exactly the servers this check consulted and got an
|
|
651
|
+
* answer from. `serverScope: "primary"` consults only the primary, so its claim
|
|
652
|
+
* is `"lsp"` alone; an all-scope check adds each auxiliary server by id, which
|
|
653
|
+
* is the same vocabulary `retagAuxiliaryDiagnostics` tags their findings with.
|
|
638
654
|
*
|
|
639
|
-
*
|
|
640
|
-
*
|
|
641
|
-
*
|
|
642
|
-
*
|
|
643
|
-
* is the file content `collectDiagnosticsForFile`/the cache already read (or
|
|
644
|
-
* undefined for a cache-hit branch, whose `rawDiags` were already suppression-
|
|
645
|
-
* /skipTestFiles-filtered at write time — an empty string here is then a safe
|
|
646
|
-
* no-op re-check, not a behavior gap).
|
|
655
|
+
* A server named in `unconfirmedServerIds` is dropped: it produced no evidence
|
|
656
|
+
* for this content, so claiming coverage for it would be the #1470/#1493 lie one
|
|
657
|
+
* layer up. (Today an aux gap also demotes the whole verdict to "unconfirmed",
|
|
658
|
+
* so the hook does not fire at all — this stays correct if that ever narrows.)
|
|
647
659
|
*/
|
|
660
|
+
function coveredSourcesForCheck(file, serverScope, unconfirmedServerIds) {
|
|
661
|
+
const unconfirmed = new Set(unconfirmedServerIds);
|
|
662
|
+
const covered = new Set();
|
|
663
|
+
let servers = [];
|
|
664
|
+
try {
|
|
665
|
+
servers = (getServersForFileWithConfig(file) ?? []);
|
|
666
|
+
}
|
|
667
|
+
catch {
|
|
668
|
+
// A registry we cannot read is not a coverage claim. Returning an empty
|
|
669
|
+
// set makes every retire fail closed, which is the safe direction for a
|
|
670
|
+
// commit gate.
|
|
671
|
+
return [];
|
|
672
|
+
}
|
|
673
|
+
for (const server of servers) {
|
|
674
|
+
const auxiliary = server.role === "auxiliary";
|
|
675
|
+
if (auxiliary && serverScope === "primary")
|
|
676
|
+
continue;
|
|
677
|
+
if (unconfirmed.has(server.id))
|
|
678
|
+
continue;
|
|
679
|
+
// The dispatch runner tags the primary language server's findings `lsp`;
|
|
680
|
+
// auxiliaries keep their own tool id.
|
|
681
|
+
covered.add(auxiliary ? server.id : "lsp");
|
|
682
|
+
}
|
|
683
|
+
return [...covered];
|
|
684
|
+
}
|
|
685
|
+
/**
|
|
686
|
+
* #1645 review F3: `lsp_diagnostics` writes into the SAME widget store as
|
|
687
|
+
* `lens_diagnostics mode=full`. Two tools writing one store must apply ONE rule
|
|
688
|
+
* for "is this file's diagnostics demoted" — otherwise an orphan file blocks or
|
|
689
|
+
* does not depending purely on which tool ran last, which is the #1633-V1
|
|
690
|
+
* lesson. Every path in this file that reaches `reconcileWidgetFromLspResult`
|
|
691
|
+
* or the rendered output routes its raw diagnostics through here first, so the
|
|
692
|
+
* store, the counts, and the text all agree.
|
|
693
|
+
*
|
|
694
|
+
* Applied AFTER the confirmation verdict is computed, never before: confirmation
|
|
695
|
+
* asks "did the server answer for this content", which the demotion must not
|
|
696
|
+
* influence.
|
|
697
|
+
*/
|
|
698
|
+
function demoteInferredForFile(file, diagnostics, cwd, lspService) {
|
|
699
|
+
return demoteInferredProjectDiagnostics(diagnostics, {
|
|
700
|
+
filePath: file,
|
|
701
|
+
cwd,
|
|
702
|
+
service: lspService,
|
|
703
|
+
});
|
|
704
|
+
}
|
|
648
705
|
function reconcileWidgetFromLspResult(file, rawDiags, confirmation, writeIndex, cwd, content,
|
|
649
706
|
// #1095: true when the result's content binding demonstrably mismatches disk
|
|
650
707
|
// (boundToCurrentDisk === false). Such a result — even a NON-EMPTY one, which
|
|
@@ -662,7 +719,7 @@ boundMismatch = false,
|
|
|
662
719
|
observedAt) {
|
|
663
720
|
const confirmed = (rawDiags.length > 0 || confirmation !== "unconfirmed") && !boundMismatch;
|
|
664
721
|
if (!confirmed)
|
|
665
|
-
return;
|
|
722
|
+
return { confirmed: false, blocking: true };
|
|
666
723
|
try {
|
|
667
724
|
// #692: provenance label ONLY — must never affect `rule`/identity (see
|
|
668
725
|
// `ConvertLspDiagnosticsOptions.scanOrigin`'s doc comment).
|
|
@@ -671,9 +728,16 @@ observedAt) {
|
|
|
671
728
|
});
|
|
672
729
|
const retagged = retagAuxiliaryDiagnostics(diagnostics, rawDiags, content ?? "", { cwd, fileRole: detectFileRole(file, content) });
|
|
673
730
|
reconcileScanDiagnostics(file, retagged, true, writeIndex, observedAt);
|
|
731
|
+
// #1561: the blocking tally comes from the SAME `isBlocking` predicate the
|
|
732
|
+
// footer counts with — no second severity rule for the blocker-retire
|
|
733
|
+
// decision to drift away from.
|
|
734
|
+
return { confirmed: true, blocking: retagged.some(isBlocking) };
|
|
674
735
|
}
|
|
675
736
|
catch {
|
|
676
737
|
// Never let a footer-reconciliation hiccup fail the diagnostics check.
|
|
738
|
+
// A verdict we could not compute is NOT evidence of clean: report it as
|
|
739
|
+
// still-blocking so no caller retires a blocker off a failed reconcile.
|
|
740
|
+
return { confirmed: false, blocking: true };
|
|
677
741
|
}
|
|
678
742
|
}
|
|
679
743
|
async function collectFileDiagnosticResult(file, severity, lspService, waitMs, nextWriteIndex, serverScope = "all",
|
|
@@ -687,7 +751,11 @@ cacheCtx, scopeKey,
|
|
|
687
751
|
// `allowBlocking(cwd)` for a scan-reconciled aux finding — defaults to
|
|
688
752
|
// `process.cwd()` for any call site that predates this (there are none
|
|
689
753
|
// today besides the two below, both of which now pass it explicitly).
|
|
690
|
-
cwd = process.cwd()
|
|
754
|
+
cwd = process.cwd(),
|
|
755
|
+
// #1561: see `createLspDiagnosticsTool`'s parameter doc. Called only for a
|
|
756
|
+
// FRESH observation — never on the cache-hit replay below, whose `rawDiags`
|
|
757
|
+
// are an OLD observation (#1093) and therefore no evidence about now.
|
|
758
|
+
onConfirmedNoBlockers) {
|
|
691
759
|
// Reserve the ordering token when this diagnostic operation starts, not when
|
|
692
760
|
// its LSP promise settles. A slower old result must not receive a newer token
|
|
693
761
|
// merely because it completed later (#1198).
|
|
@@ -709,8 +777,13 @@ cwd = process.cwd()) {
|
|
|
709
777
|
// NOT served — fall through to a fresh touch instead of replaying a stale
|
|
710
778
|
// cached result. "unknown"/true bindings serve as before.
|
|
711
779
|
if (cached && cached.binding.boundToCurrentDisk !== false) {
|
|
712
|
-
const filteredDiags = applySeverityFilter(cached.diagnostics, severity);
|
|
713
780
|
const confirmation = cached.diagnostics.length === 0 ? "clean" : undefined;
|
|
781
|
+
// #1645 review F3: a cache REPLAY writes the widget store exactly like a
|
|
782
|
+
// fresh touch does, so it gets the same demotion. Without this, replaying
|
|
783
|
+
// yesterday's cached blocker would re-cement an orphan file as blocking
|
|
784
|
+
// after mode=full had demoted it.
|
|
785
|
+
const cachedDiags = await demoteInferredForFile(file, cached.diagnostics, cwd, lspService);
|
|
786
|
+
const filteredDiags = applySeverityFilter(cachedDiags, severity);
|
|
714
787
|
// #692: cached.diagnostics were already suppression-/skipTestFiles-
|
|
715
788
|
// filtered at write time (this same code path); no file content was
|
|
716
789
|
// cached alongside them, so `undefined` here is a safe re-check, not
|
|
@@ -720,7 +793,7 @@ cwd = process.cwd()) {
|
|
|
720
793
|
// now(), or a repeat check that only re-serves the cache would keep
|
|
721
794
|
// re-arming the mtime-staleness gate and a resolved finding would render
|
|
722
795
|
// forever (the #1092 defect).
|
|
723
|
-
reconcileWidgetFromLspResult(file,
|
|
796
|
+
reconcileWidgetFromLspResult(file, cachedDiags, confirmation, writeIndex, cwd, undefined,
|
|
724
797
|
// This branch only runs when the cache binding is not a mismatch
|
|
725
798
|
// (guarded above), so boundMismatch is false; #1093's observedAt is
|
|
726
799
|
// the cache entry's original scan time.
|
|
@@ -733,7 +806,7 @@ cwd = process.cwd()) {
|
|
|
733
806
|
};
|
|
734
807
|
}
|
|
735
808
|
}
|
|
736
|
-
const { diagnostics: rawDiags, timedOut, confirmedByTouch, content: collectedContent, binding, } = await collectDiagnosticsForFile(file, lspService, waitMs, serverScope);
|
|
809
|
+
const { diagnostics: rawDiags, timedOut, confirmedByTouch, unconfirmedServerIds, content: collectedContent, binding, } = await collectDiagnosticsForFile(file, lspService, waitMs, serverScope);
|
|
737
810
|
const health = lspService.getDiagnosticsHealth?.(file);
|
|
738
811
|
// #570: a timed-out priming check is never a confirmed "clean" — treat it
|
|
739
812
|
// as unconfirmed without consulting the (unrelated) silent-tier
|
|
@@ -773,8 +846,27 @@ cwd = process.cwd()) {
|
|
|
773
846
|
const boundMismatch = binding?.boundToCurrentDisk === false;
|
|
774
847
|
if (boundMismatch)
|
|
775
848
|
confirmation = "unconfirmed";
|
|
849
|
+
// #1470/#1493: an auxiliary that never reported — cut off by the aux grace timer,
|
|
850
|
+
// or silent with nothing published for this content — contributed no evidence
|
|
851
|
+
// about this file, so a "clean" verdict computed from the merged result would
|
|
852
|
+
// be claiming coverage this batch does not have. Demote it — that also keeps
|
|
853
|
+
// the entry out of the workspace cache below, which would otherwise replay the
|
|
854
|
+
// partial answer as a confirmed clean on every later sweep.
|
|
855
|
+
if (unconfirmedServerIds.length > 0 && confirmation === "clean") {
|
|
856
|
+
confirmation = "unconfirmed";
|
|
857
|
+
}
|
|
858
|
+
// #1645 review F3: one demotion rule for every writer of the widget store.
|
|
859
|
+
effectiveRawDiags = await demoteInferredForFile(file, effectiveRawDiags, cwd, lspService);
|
|
776
860
|
const filteredDiags = applySeverityFilter(effectiveRawDiags, severity);
|
|
777
|
-
reconcileWidgetFromLspResult(file, effectiveRawDiags, confirmation, writeIndex, cwd, collectedContent, boundMismatch);
|
|
861
|
+
const verdict = reconcileWidgetFromLspResult(file, effectiveRawDiags, confirmation, writeIndex, cwd, collectedContent, boundMismatch);
|
|
862
|
+
if (verdict.confirmed && !verdict.blocking) {
|
|
863
|
+
onConfirmedNoBlockers?.({
|
|
864
|
+
filePath: file,
|
|
865
|
+
writeIndex,
|
|
866
|
+
coveredSources: coveredSourcesForCheck(file, serverScope, unconfirmedServerIds),
|
|
867
|
+
cwd,
|
|
868
|
+
});
|
|
869
|
+
}
|
|
778
870
|
// #671: only a CONFIRMED outcome ("clean", or a non-empty result — either
|
|
779
871
|
// is definitionally confirmed per this function's own doctrine above) is
|
|
780
872
|
// safe to cache; "unconfirmed" (timeout OR a silent-tier server's
|
|
@@ -782,7 +874,10 @@ cwd = process.cwd()) {
|
|
|
782
874
|
// result — same false-clean bug class `runWorkspaceDiagnostics`'s cache
|
|
783
875
|
// wiring guards against. #1095: the entry carries the content fingerprint so a
|
|
784
876
|
// later lookup can verify it against disk beyond the mtime proxy.
|
|
785
|
-
if (cacheCtx &&
|
|
877
|
+
if (cacheCtx &&
|
|
878
|
+
scopeKey !== undefined &&
|
|
879
|
+
confirmation !== "unconfirmed" &&
|
|
880
|
+
unconfirmedServerIds.length === 0) {
|
|
786
881
|
cacheCtx.record(file, scopeKey, effectiveRawDiags, stat.mtimeMs, collectedContent !== undefined
|
|
787
882
|
? hashDiagnosticContent(collectedContent)
|
|
788
883
|
: undefined);
|
|
@@ -796,11 +891,14 @@ cwd = process.cwd()) {
|
|
|
796
891
|
primaryServerId: primaryServerId(file),
|
|
797
892
|
};
|
|
798
893
|
}
|
|
799
|
-
async function runFileDiagnostics(absPath, severity, lspService, waitMs, nextWriteIndex, serverScope = "all", cwd = process.cwd()
|
|
894
|
+
async function runFileDiagnostics(absPath, severity, lspService, waitMs, nextWriteIndex, serverScope = "all", cwd = process.cwd(),
|
|
895
|
+
// #1561: see `createLspDiagnosticsTool`'s parameter doc. This is the path the
|
|
896
|
+
// live incident took (`mode: "file"`).
|
|
897
|
+
onConfirmedNoBlockers) {
|
|
800
898
|
// Reserve the token before awaiting this file's LSP result. The direct-file
|
|
801
899
|
// path performs its own confirmation/reconciliation below (#1198).
|
|
802
900
|
const writeIndex = nextWriteIndex?.();
|
|
803
|
-
const { diagnostics: rawDiags, timedOut, confirmedByTouch, content: collectedContent, binding, } = await collectDiagnosticsForFile(absPath, lspService, waitMs, serverScope);
|
|
901
|
+
const { diagnostics: rawDiags, timedOut, confirmedByTouch, unconfirmedServerIds, content: collectedContent, binding, } = await collectDiagnosticsForFile(absPath, lspService, waitMs, serverScope);
|
|
804
902
|
const lspHealth = lspService.getDiagnosticsHealth?.(absPath);
|
|
805
903
|
const unavailable = lspUnavailableMessage(absPath, lspHealth);
|
|
806
904
|
// #533: an empty result needs a confirmed/unconfirmed verdict — a push-only,
|
|
@@ -842,12 +940,36 @@ async function runFileDiagnostics(absPath, severity, lspService, waitMs, nextWri
|
|
|
842
940
|
const boundMismatch = binding?.boundToCurrentDisk === false;
|
|
843
941
|
if (boundMismatch)
|
|
844
942
|
confirmation = "unconfirmed";
|
|
943
|
+
// #1470/#1493: NARROWED, not collapsed. An auxiliary that never reported — the aux
|
|
944
|
+
// grace timer cut it off, or it stayed silent with nothing published for this
|
|
945
|
+
// content — makes the FILE-level verdict unconfirmed. The merged result is missing
|
|
946
|
+
// whatever that scanner would have said, and this tool is the security lane's read surface. The
|
|
947
|
+
// PRIMARY's own verdict is untouched (`primaryCoverageGapOnly` below), so a
|
|
948
|
+
// TypeScript answer stays "confirmed clean" on its own line while an explicit
|
|
949
|
+
// line names the scanner whose coverage is absent.
|
|
950
|
+
const primaryCoverageGapOnly = unconfirmedServerIds.length > 0 && confirmation === "clean";
|
|
951
|
+
if (primaryCoverageGapOnly)
|
|
952
|
+
confirmation = "unconfirmed";
|
|
953
|
+
// #1645 review F3: one demotion rule for every writer of the widget store.
|
|
954
|
+
effectiveRawDiags = await demoteInferredForFile(absPath, effectiveRawDiags, cwd, lspService);
|
|
845
955
|
const filtered = applySeverityFilter(effectiveRawDiags, severity);
|
|
846
956
|
const total = filtered.length;
|
|
847
957
|
const truncated = total > MAX_DIAGNOSTICS;
|
|
848
958
|
const limited = truncated ? filtered.slice(0, MAX_DIAGNOSTICS) : filtered;
|
|
849
959
|
const unconfirmed = confirmation === "unconfirmed";
|
|
850
|
-
reconcileWidgetFromLspResult(absPath, effectiveRawDiags, confirmation, writeIndex, cwd, collectedContent, boundMismatch);
|
|
960
|
+
const verdict = reconcileWidgetFromLspResult(absPath, effectiveRawDiags, confirmation, writeIndex, cwd, collectedContent, boundMismatch);
|
|
961
|
+
// #1561: a confirmed current view with nothing at the blocking tier retires
|
|
962
|
+
// this file's stale inline blocker — the store #571 corrected the footer for
|
|
963
|
+
// but never reached, which is how a resolved cross-file finding kept being
|
|
964
|
+
// injected as "Unresolved from this turn" for the rest of the session.
|
|
965
|
+
if (verdict.confirmed && !verdict.blocking) {
|
|
966
|
+
onConfirmedNoBlockers?.({
|
|
967
|
+
filePath: absPath,
|
|
968
|
+
writeIndex,
|
|
969
|
+
coveredSources: coveredSourcesForCheck(absPath, serverScope, unconfirmedServerIds),
|
|
970
|
+
cwd,
|
|
971
|
+
});
|
|
972
|
+
}
|
|
851
973
|
const primaryId = primaryServerId(absPath);
|
|
852
974
|
const primaryDiags = limited.filter((d) => d.source === primaryId);
|
|
853
975
|
const auxiliaryDiags = limited.filter((d) => d.source !== primaryId);
|
|
@@ -860,7 +982,11 @@ async function runFileDiagnostics(absPath, severity, lspService, waitMs, nextWri
|
|
|
860
982
|
"file may still have errors that just hadn't been reported yet. " +
|
|
861
983
|
"Re-check after the server settles, or increase waitMs.");
|
|
862
984
|
}
|
|
863
|
-
|
|
985
|
+
// #1470: a file demoted ONLY because an auxiliary was cut off must not render
|
|
986
|
+
// the silent-on-clean text — the primary did confirm, and saying otherwise is
|
|
987
|
+
// the same overclaim in the opposite direction. The coverage line below names
|
|
988
|
+
// what is actually missing.
|
|
989
|
+
if (unconfirmed && !primaryCoverageGapOnly) {
|
|
864
990
|
return (`Primary LSP${primaryId ? ` (${primaryId})` : ""}: unconfirmed — ` +
|
|
865
991
|
"cannot confirm clean (push-only, silent-on-clean, e.g. classic " +
|
|
866
992
|
"typescript-language-server never publishes on a clean re-check). " +
|
|
@@ -872,9 +998,20 @@ async function runFileDiagnostics(absPath, severity, lspService, waitMs, nextWri
|
|
|
872
998
|
}
|
|
873
999
|
return `Primary LSP${primaryId ? ` (${primaryId})` : ""}: ${primaryDiags.length} diagnostic${primaryDiags.length === 1 ? "" : "s"}.`;
|
|
874
1000
|
})();
|
|
1001
|
+
// #1470: this is the narrowing made readable. It states exactly which servers
|
|
1002
|
+
// this result does NOT speak for, so "no auxiliary findings" can never be read
|
|
1003
|
+
// as "the security scanners found nothing".
|
|
1004
|
+
const coverageLine = unconfirmedServerIds.length > 0
|
|
1005
|
+
? `Auxiliary coverage INCOMPLETE — ${[...unconfirmedServerIds].join(", ")} did not answer within the wait budget, so ${unconfirmedServerIds.length === 1 ? "its findings are" : "their findings are"} NOT included here. This is not a clean bill of health for ${unconfirmedServerIds.length === 1 ? "that scanner" : "those scanners"}; re-check after the next edit, or use waitMs to wait longer.`
|
|
1006
|
+
: undefined;
|
|
875
1007
|
let text;
|
|
876
1008
|
if (total === 0) {
|
|
877
|
-
text = [
|
|
1009
|
+
text = [
|
|
1010
|
+
primaryLine,
|
|
1011
|
+
"",
|
|
1012
|
+
unavailable ?? "No auxiliary findings.",
|
|
1013
|
+
...(coverageLine ? [coverageLine] : []),
|
|
1014
|
+
].join("\n");
|
|
878
1015
|
}
|
|
879
1016
|
else {
|
|
880
1017
|
const lines = [primaryLine, ""];
|
|
@@ -885,6 +1022,8 @@ async function runFileDiagnostics(absPath, severity, lspService, waitMs, nextWri
|
|
|
885
1022
|
lines.push(`Auxiliary findings (${auxiliaryDiags.length}):`);
|
|
886
1023
|
lines.push(...auxiliaryDiags.map(formatDiag));
|
|
887
1024
|
}
|
|
1025
|
+
if (coverageLine)
|
|
1026
|
+
lines.push("", coverageLine);
|
|
888
1027
|
if (unavailable)
|
|
889
1028
|
lines.unshift(unavailable, "");
|
|
890
1029
|
if (truncated) {
|
|
@@ -914,6 +1053,11 @@ async function runFileDiagnostics(absPath, severity, lspService, waitMs, nextWri
|
|
|
914
1053
|
truncated,
|
|
915
1054
|
unconfirmed,
|
|
916
1055
|
timedOut: unconfirmed ? timedOut : undefined,
|
|
1056
|
+
// #1470: which servers this result does NOT speak for. Absent when it
|
|
1057
|
+
// speaks for all of them.
|
|
1058
|
+
...(unconfirmedServerIds.length > 0 && {
|
|
1059
|
+
unconfirmedServerIds: [...unconfirmedServerIds],
|
|
1060
|
+
}),
|
|
917
1061
|
lspHealth,
|
|
918
1062
|
waitMs,
|
|
919
1063
|
},
|
|
@@ -1023,7 +1167,7 @@ async function collectBatchDiagnostics(files, severity, lspService, options) {
|
|
|
1023
1167
|
const cacheCtx = createWorkspaceDiagnosticsCacheContext(resolvedCwd);
|
|
1024
1168
|
const scopeKey = buildScopeKey(options.serverScope ?? "all");
|
|
1025
1169
|
const results = await mapWithConcurrency(files, options.concurrency, async (file) => {
|
|
1026
|
-
const work = collectFileDiagnosticResult(file, severity, lspService, options.waitMs, options.nextWriteIndex, options.serverScope, cacheCtx, scopeKey, resolvedCwd);
|
|
1170
|
+
const work = collectFileDiagnosticResult(file, severity, lspService, options.waitMs, options.nextWriteIndex, options.serverScope, cacheCtx, scopeKey, resolvedCwd, options.onConfirmedNoBlockers);
|
|
1027
1171
|
const bounded = withDeadline(work, {
|
|
1028
1172
|
ms: batchFileDeadlineMs(),
|
|
1029
1173
|
onTimeout: "undefined",
|
|
@@ -9,9 +9,10 @@ import { fileURLToPath, pathToFileURL } from "node:url";
|
|
|
9
9
|
import { Type } from "../clients/deps/typebox.js";
|
|
10
10
|
import { logLatency } from "../clients/latency-logger.js";
|
|
11
11
|
import { newLspMutationCorrelationId, recordLspMutationOutcome, } from "../clients/lsp-mutation.js";
|
|
12
|
+
import { uriToPath } from "../clients/path-utils.js";
|
|
12
13
|
import { compactRenderResult } from "./render-compact.js";
|
|
13
14
|
import { applyWorkspaceEdit, summarizeWorkspaceEdit, } from "../clients/lsp/edits.js";
|
|
14
|
-
import { getLSPService } from "../clients/lsp/index.js";
|
|
15
|
+
import { getLSPService, } from "../clients/lsp/index.js";
|
|
15
16
|
import { buildLspNavigationEnvelope } from "./lsp-structured-output.js";
|
|
16
17
|
import { SYMBOL_KIND_NAMES } from "../clients/lsp-document-symbols.js";
|
|
17
18
|
const VALID_OPERATIONS = [
|
|
@@ -678,6 +679,7 @@ getFlag, mutationDeps) {
|
|
|
678
679
|
let columnResolution;
|
|
679
680
|
let mutationContext;
|
|
680
681
|
let requestedApply = false;
|
|
682
|
+
const workspaceScopeAttribution = {};
|
|
681
683
|
const finalize = (payload, meta) => {
|
|
682
684
|
if (payload.isError &&
|
|
683
685
|
requestedApply &&
|
|
@@ -698,6 +700,9 @@ getFlag, mutationDeps) {
|
|
|
698
700
|
supported,
|
|
699
701
|
diagnosticsMode,
|
|
700
702
|
columnResolution,
|
|
703
|
+
...(Object.keys(workspaceScopeAttribution).length > 0
|
|
704
|
+
? { workspaceScopeAttribution }
|
|
705
|
+
: {}),
|
|
701
706
|
},
|
|
702
707
|
});
|
|
703
708
|
const text = payload.content[0]?.text ?? "";
|
|
@@ -821,7 +826,9 @@ getFlag, mutationDeps) {
|
|
|
821
826
|
}
|
|
822
827
|
const lspService = getLSPService();
|
|
823
828
|
if (operation === "capabilities") {
|
|
824
|
-
const snapshots =
|
|
829
|
+
const snapshots = rawPath
|
|
830
|
+
? await lspService.getCapabilitySnapshots(filePath)
|
|
831
|
+
: await lspService.getCapabilitySnapshots(undefined, workspaceScopeAttribution);
|
|
825
832
|
const output = formatCapabilities(snapshots, rawPath ? filePath : undefined);
|
|
826
833
|
return finalize({
|
|
827
834
|
content: [{ type: "text", text: output }],
|
|
@@ -838,7 +845,9 @@ getFlag, mutationDeps) {
|
|
|
838
845
|
});
|
|
839
846
|
}
|
|
840
847
|
if (operation === "workspaceDiagnostics") {
|
|
841
|
-
const wsDiagSupport =
|
|
848
|
+
const wsDiagSupport = rawPath
|
|
849
|
+
? await lspService.getWorkspaceDiagnosticsSupport(filePath)
|
|
850
|
+
: await lspService.getWorkspaceDiagnosticsSupport(undefined, workspaceScopeAttribution);
|
|
842
851
|
diagnosticsMode = wsDiagSupport?.mode ?? "unknown";
|
|
843
852
|
if (rawPath && !filePathIsDirectory) {
|
|
844
853
|
const hasLSP = lspService.supportsLSP(filePath);
|
|
@@ -1007,7 +1016,10 @@ getFlag, mutationDeps) {
|
|
|
1007
1016
|
const lspEndLine = (endLine ?? line ?? 1) - 1;
|
|
1008
1017
|
const lspEndChar = (endCharacter ?? resolvedCharacter.character) - 1;
|
|
1009
1018
|
const runWorkspaceSymbolOperation = async () => {
|
|
1010
|
-
|
|
1019
|
+
const support = rawPath
|
|
1020
|
+
? await lspService.getOperationSupport(filePath)
|
|
1021
|
+
: await lspService.getOperationSupport(undefined, workspaceScopeAttribution);
|
|
1022
|
+
supported = operationSupportStatus(operation, support);
|
|
1011
1023
|
if (supported === false) {
|
|
1012
1024
|
throw new Error("__UNSUPPORTED__ Active LSP server does not advertise support for workspaceSymbol");
|
|
1013
1025
|
}
|
|
@@ -1018,7 +1030,9 @@ getFlag, mutationDeps) {
|
|
|
1018
1030
|
await openFileBestEffort(lspService, filePath);
|
|
1019
1031
|
}
|
|
1020
1032
|
try {
|
|
1021
|
-
const raw =
|
|
1033
|
+
const raw = rawPath
|
|
1034
|
+
? await lspService.workspaceSymbol(query ?? "", filePath)
|
|
1035
|
+
: await lspService.workspaceSymbol(query ?? "", undefined, workspaceScopeAttribution);
|
|
1022
1036
|
const filtered = (Array.isArray(raw) ? raw : [raw]).filter((s) => typeof s === "object" &&
|
|
1023
1037
|
s !== null &&
|
|
1024
1038
|
(!s.kind || NAVIGABLE_SYMBOL_KINDS.has(s.kind)));
|
|
@@ -1127,7 +1141,9 @@ getFlag, mutationDeps) {
|
|
|
1127
1141
|
if (!command || command.trim().length === 0) {
|
|
1128
1142
|
throw new Error("__BADINPUT__ command parameter required for executeCommand");
|
|
1129
1143
|
}
|
|
1130
|
-
const advertised =
|
|
1144
|
+
const advertised = rawPath
|
|
1145
|
+
? await lspService.getAdvertisedCommands(filePath)
|
|
1146
|
+
: await lspService.getAdvertisedCommands(undefined, workspaceScopeAttribution);
|
|
1131
1147
|
const isAdvertised = advertised.includes(command);
|
|
1132
1148
|
// Dry-run by default: report advertisement status without running.
|
|
1133
1149
|
// Mutation only on explicit apply:true (and the client re-checks
|
|
@@ -1147,18 +1163,41 @@ getFlag, mutationDeps) {
|
|
|
1147
1163
|
if (!isAdvertised) {
|
|
1148
1164
|
throw new Error(`__UNSUPPORTED__ command "${command}" is not advertised by the active LSP server (advertised: ${advertised.join(", ") || "none"})`);
|
|
1149
1165
|
}
|
|
1150
|
-
return
|
|
1166
|
+
return rawPath
|
|
1167
|
+
? lspService.executeCommand(filePath, command, commandArguments, mutationContext)
|
|
1168
|
+
: lspService.executeCommand(undefined, command, commandArguments, mutationContext, workspaceScopeAttribution);
|
|
1151
1169
|
}
|
|
1152
1170
|
case "incomingCalls": {
|
|
1153
1171
|
if (!callHierarchyItem) {
|
|
1154
1172
|
throw new Error("__BADINPUT__ callHierarchyItem parameter required for incomingCalls");
|
|
1155
1173
|
}
|
|
1174
|
+
// #1803 fix-round F1: needsFilePath is false for call-hierarchy
|
|
1175
|
+
// traversal (the operand is callHierarchyItem, not path), so the
|
|
1176
|
+
// shared needsFilePath pre-check at line ~1319 never runs for
|
|
1177
|
+
// this operation — LSPService.incomingCalls' own capability gate
|
|
1178
|
+
// (clients/lsp/index.ts) returns a bare [], which this tool layer
|
|
1179
|
+
// cannot distinguish from "supported server, zero callers found".
|
|
1180
|
+
// Pre-check here, keyed off the item's own uri (the file the
|
|
1181
|
+
// resolved server is scoped to), mirrors
|
|
1182
|
+
// runWorkspaceSymbolOperation's supported-check above: throwing
|
|
1183
|
+
// __UNSUPPORTED__ routes through the catch block below into the
|
|
1184
|
+
// same discriminated isError:true/emptyReason:"unsupported" shape
|
|
1185
|
+
// every other capability-gated operation already reports.
|
|
1186
|
+
supported = operationSupportStatus(operation, await lspService.getOperationSupport(uriToPath(callHierarchyItem.uri)));
|
|
1187
|
+
if (supported === false) {
|
|
1188
|
+
throw new Error("__UNSUPPORTED__ Active LSP server does not advertise support for incomingCalls");
|
|
1189
|
+
}
|
|
1156
1190
|
return lspService.incomingCalls(callHierarchyItem);
|
|
1157
1191
|
}
|
|
1158
1192
|
case "outgoingCalls": {
|
|
1159
1193
|
if (!callHierarchyItem) {
|
|
1160
1194
|
throw new Error("__BADINPUT__ callHierarchyItem parameter required for outgoingCalls");
|
|
1161
1195
|
}
|
|
1196
|
+
// #1803 fix-round F1: same pre-check as incomingCalls above.
|
|
1197
|
+
supported = operationSupportStatus(operation, await lspService.getOperationSupport(uriToPath(callHierarchyItem.uri)));
|
|
1198
|
+
if (supported === false) {
|
|
1199
|
+
throw new Error("__UNSUPPORTED__ Active LSP server does not advertise support for outgoingCalls");
|
|
1200
|
+
}
|
|
1162
1201
|
return lspService.outgoingCalls(callHierarchyItem);
|
|
1163
1202
|
}
|
|
1164
1203
|
default:
|
|
@@ -33,7 +33,7 @@ export function createSymbolSearchTool(getProjectRoot) {
|
|
|
33
33
|
}),
|
|
34
34
|
parameters: Type.Object({
|
|
35
35
|
query: Type.String({
|
|
36
|
-
description: "Identifier-ish query, e.g. 'authenticate user'.",
|
|
36
|
+
description: "Identifier-ish query, e.g. 'authenticate user'. Mix in composable prefix filters: lang:<kind> (e.g. lang:jsts, lang:python — kinds from file-kinds.ts), file:<substr> (path substring), ext:<ext> (e.g. ext:ts or ext:.ts), each optionally negated with a leading '-' (-file:test). Filters apply before ranking; e.g. 'lang:jsts file:clients/ -file:test rank'. Unknown prefixes/kinds error with the supported list.",
|
|
37
37
|
}),
|
|
38
38
|
limit: Type.Optional(Type.Number({
|
|
39
39
|
description: "Max files to return (default 20).",
|