@herbertgao/pi-extensions 2026.8.4 → 2026.8.6
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 +11 -3
- package/node_modules/@herbertgao/pi-cc-extensions/README.md +11 -3
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/config.ts +24 -0
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +91 -1
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/compact-thinking.ts +7 -3
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/context.ts +74 -5
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/index.ts +7 -6
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/compact-mode.ts +21 -12
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/default-mode.ts +4 -5
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/markdown-enhance.ts +53 -14
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/grouping.ts +22 -12
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/result.ts +2 -4
- package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
- package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +18 -0
- package/node_modules/@herbertgao/pi-subagents/package.json +8 -4
- package/node_modules/@herbertgao/pi-subagents/src/agent-color.ts +72 -67
- package/node_modules/@herbertgao/pi-subagents/src/agent-file-toggle.ts +255 -0
- package/node_modules/@herbertgao/pi-subagents/src/agent-manager.ts +191 -3
- package/node_modules/@herbertgao/pi-subagents/src/agent-runner.ts +20 -4
- package/node_modules/@herbertgao/pi-subagents/src/index.ts +289 -113
- package/node_modules/@herbertgao/pi-subagents/src/output-file.ts +24 -1
- package/node_modules/@herbertgao/pi-subagents/src/ui/agent-widget.ts +24 -2
- package/node_modules/@herbertgao/pi-subagents/src/ui/fleet-list.ts +15 -6
- package/node_modules/@herbertgao/pi-subagents/src/ui/schedule-menu.ts +9 -8
- package/node_modules/@herbertgao/pi-subagents/src/ui/select-item.ts +48 -0
- package/node_modules/@herbertgao/pi-subagents/src/worktree.ts +9 -5
- package/node_modules/@juicesharp/rpiv-ask-user-question/README.md +2 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/ask-user-question.ts +20 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/docs/hosts.md +6 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/docs/keyboard.md +7 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/package.json +2 -2
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/build-questionnaire.ts +7 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/key-router.ts +16 -5
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/questionnaire-session.ts +4 -2
- package/node_modules/@narumitw/pi-btw/README.md +32 -24
- package/node_modules/@narumitw/pi-btw/package.json +6 -6
- package/node_modules/@narumitw/pi-btw/src/btw.ts +4 -2
- package/node_modules/@narumitw/pi-btw/src/menu.ts +34 -13
- package/node_modules/@narumitw/pi-btw/src/settings.ts +22 -2
- package/node_modules/pi-lens/CHANGELOG.md +2535 -954
- package/node_modules/pi-lens/README.md +13 -0
- package/node_modules/pi-lens/dist/clients/actionable-warnings.js +73 -18
- package/node_modules/pi-lens/dist/clients/advisory-provenance.js +314 -0
- package/node_modules/pi-lens/dist/clients/agent-behavior-client.js +21 -4
- package/node_modules/pi-lens/dist/clients/agent-nudge.js +14 -7
- package/node_modules/pi-lens/dist/clients/ast-grep-client.js +68 -16
- package/node_modules/pi-lens/dist/clients/ast-grep-types.js +0 -1
- package/node_modules/pi-lens/dist/clients/ast-grep-yaml-synth.js +37 -10
- package/node_modules/pi-lens/dist/clients/atomic-write-staging.js +63 -0
- package/node_modules/pi-lens/dist/clients/atomic-write.js +114 -14
- package/node_modules/pi-lens/dist/clients/bash-file-access.js +193 -23
- package/node_modules/pi-lens/dist/clients/biome-client.js +136 -24
- package/node_modules/pi-lens/dist/clients/bootstrap.js +11 -2
- package/node_modules/pi-lens/dist/clients/bounded-cache.js +34 -0
- package/node_modules/pi-lens/dist/clients/bounded-pid-file-lock.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 +19 -4
- package/node_modules/pi-lens/dist/clients/cache/rule-cache.js +47 -5
- package/node_modules/pi-lens/dist/clients/cache-manager.js +97 -9
- package/node_modules/pi-lens/dist/clients/cache-observability.js +301 -14
- package/node_modules/pi-lens/dist/clients/call-graph.js +449 -117
- package/node_modules/pi-lens/dist/clients/cascade-format.js +57 -2
- package/node_modules/pi-lens/dist/clients/child-unref.js +85 -0
- package/node_modules/pi-lens/dist/clients/codebase-model.js +52 -23
- package/node_modules/pi-lens/dist/clients/collateral-test-role.js +40 -0
- package/node_modules/pi-lens/dist/clients/complexity-client.js +2 -1
- package/node_modules/pi-lens/dist/clients/console-guard-install.js +26 -0
- package/node_modules/pi-lens/dist/clients/cooperative-budget.js +42 -0
- package/node_modules/pi-lens/dist/clients/dead-code-client.js +137 -31
- package/node_modules/pi-lens/dist/clients/debug-handles.js +206 -0
- package/node_modules/pi-lens/dist/clients/debug-heap.js +167 -0
- package/node_modules/pi-lens/dist/clients/degradation-ledger.js +153 -0
- package/node_modules/pi-lens/dist/clients/dependency-checker.js +361 -77
- package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +65 -13
- package/node_modules/pi-lens/dist/clients/diagnostics-publish.js +18 -4
- package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +176 -29
- package/node_modules/pi-lens/dist/clients/dispatch/facts/function-facts.js +23 -7
- package/node_modules/pi-lens/dist/clients/dispatch/facts/import-facts.js +8 -18
- package/node_modules/pi-lens/dist/clients/dispatch/facts/tree-sitter-facts.js +8 -5
- package/node_modules/pi-lens/dist/clients/dispatch/indent-detect.js +35 -0
- package/node_modules/pi-lens/dist/clients/dispatch/inline-suppressions.js +17 -8
- package/node_modules/pi-lens/dist/clients/dispatch/integration.js +1172 -683
- package/node_modules/pi-lens/dist/clients/dispatch/lazy.js +14 -0
- package/node_modules/pi-lens/dist/clients/dispatch/plan.js +11 -1
- package/node_modules/pi-lens/dist/clients/dispatch/rule-id-normalize.js +50 -0
- package/node_modules/pi-lens/dist/clients/dispatch/rule-policy.js +135 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ast-grep-napi.js +23 -5
- package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +5 -9
- package/node_modules/pi-lens/dist/clients/dispatch/runners/detekt.js +3 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/hadolint.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-lint.js +154 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/htmlhint.js +3 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/index.js +5 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +47 -6
- package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +4 -9
- package/node_modules/pi-lens/dist/clients/dispatch/runners/pyright.js +9 -5
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ruff.js +4 -8
- package/node_modules/pi-lens/dist/clients/dispatch/runners/shellcheck.js +2 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/shfmt.js +2 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/spotbugs.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/taplo.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/terragrunt.js +163 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/tflint.js +37 -5
- package/node_modules/pi-lens/dist/clients/dispatch/runners/tree-sitter.js +3 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/trivy-config.js +13 -7
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/availability-policy.js +226 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/candidate-probe.js +69 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/lazy-installer.js +3 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +473 -42
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/spawn-outcome.js +22 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/toolchain-availability.js +97 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/yaml-rule-parser.js +5 -4
- package/node_modules/pi-lens/dist/clients/disposition-publish.js +18 -4
- package/node_modules/pi-lens/dist/clients/durable-store.js +97 -0
- package/node_modules/pi-lens/dist/clients/eval-timestamp.js +17 -0
- package/node_modules/pi-lens/dist/clients/event-loop-monitor.js +94 -3
- package/node_modules/pi-lens/dist/clients/extension-log.js +432 -0
- package/node_modules/pi-lens/dist/clients/extension-mode.js +73 -0
- package/node_modules/pi-lens/dist/clients/file-kinds.js +57 -0
- package/node_modules/pi-lens/dist/clients/file-role.js +18 -3
- package/node_modules/pi-lens/dist/clients/file-utils.js +56 -34
- package/node_modules/pi-lens/dist/clients/fix-worklog.js +5 -1
- package/node_modules/pi-lens/dist/clients/format-events-publish.js +51 -7
- package/node_modules/pi-lens/dist/clients/format-service.js +24 -8
- package/node_modules/pi-lens/dist/clients/formatters-lazy.js +8 -0
- package/node_modules/pi-lens/dist/clients/formatters.js +358 -61
- package/node_modules/pi-lens/dist/clients/generated-artifacts.js +148 -15
- package/node_modules/pi-lens/dist/clients/git-guard.js +678 -11
- package/node_modules/pi-lens/dist/clients/git-tracked-ignore.js +4 -0
- package/node_modules/pi-lens/dist/clients/go-client.js +23 -40
- package/node_modules/pi-lens/dist/clients/govulncheck-client.js +124 -7
- package/node_modules/pi-lens/dist/clients/grammar-source.js +12 -4
- package/node_modules/pi-lens/dist/clients/gzip-stage-write.js +21 -3
- package/node_modules/pi-lens/dist/clients/host-ports.js +31 -0
- package/node_modules/pi-lens/dist/clients/installer/index.js +395 -100
- package/node_modules/pi-lens/dist/clients/instance-reaper.js +142 -172
- package/node_modules/pi-lens/dist/clients/jscpd-client.js +27 -55
- package/node_modules/pi-lens/dist/clients/knip-client.js +58 -42
- package/node_modules/pi-lens/dist/clients/language-policy.js +14 -2
- package/node_modules/pi-lens/dist/clients/language-profile.js +13 -7
- package/node_modules/pi-lens/dist/clients/latency-logger.js +72 -1
- package/node_modules/pi-lens/dist/clients/lens-config.js +12 -1
- package/node_modules/pi-lens/dist/clients/lens-engine.js +86 -17
- package/node_modules/pi-lens/dist/clients/lens-events.js +63 -9
- package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +16 -0
- package/node_modules/pi-lens/dist/clients/lens-map.js +94 -19
- package/node_modules/pi-lens/dist/clients/live-bus-emitter.js +73 -0
- package/node_modules/pi-lens/dist/clients/log-cleanup.js +2 -1
- package/node_modules/pi-lens/dist/clients/lsp/aggregation.js +30 -4
- package/node_modules/pi-lens/dist/clients/lsp/cascade-tier.js +59 -14
- package/node_modules/pi-lens/dist/clients/lsp/client.js +662 -56
- package/node_modules/pi-lens/dist/clients/lsp/config.js +13 -2
- package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +115 -0
- package/node_modules/pi-lens/dist/clients/lsp/edits.js +1012 -121
- package/node_modules/pi-lens/dist/clients/lsp/index.js +2025 -800
- package/node_modules/pi-lens/dist/clients/lsp/launch.js +32 -26
- package/node_modules/pi-lens/dist/clients/lsp/path-utils.js +1 -1
- package/node_modules/pi-lens/dist/clients/lsp/ruby-drive-dirs.js +83 -0
- package/node_modules/pi-lens/dist/clients/lsp/server.js +437 -86
- package/node_modules/pi-lens/dist/clients/lsp/tsserver-sync.js +96 -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 +18 -3
- package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +28 -4
- package/node_modules/pi-lens/dist/clients/lsp-lazy.js +8 -0
- package/node_modules/pi-lens/dist/clients/lsp-mutation.js +248 -0
- package/node_modules/pi-lens/dist/clients/mcp/analyze.js +127 -32
- package/node_modules/pi-lens/dist/clients/mcp/ipc.js +157 -24
- package/node_modules/pi-lens/dist/clients/mcp/session.js +235 -14
- package/node_modules/pi-lens/dist/clients/memory-sampler.js +115 -0
- package/node_modules/pi-lens/dist/clients/metrics-client.js +2 -1
- package/node_modules/pi-lens/dist/clients/metrics-history.js +2 -1
- package/node_modules/pi-lens/dist/clients/model-provider.js +53 -0
- package/node_modules/pi-lens/dist/clients/module-report-lsp.js +5 -0
- package/node_modules/pi-lens/dist/clients/module-report.js +168 -3
- package/node_modules/pi-lens/dist/clients/ndjson-logger.js +319 -118
- package/node_modules/pi-lens/dist/clients/opengrep-client.js +1 -1
- package/node_modules/pi-lens/dist/clients/partial-edit-apply.js +120 -5
- package/node_modules/pi-lens/dist/clients/path-utils.js +110 -9
- package/node_modules/pi-lens/dist/clients/pipeline.js +76 -15
- package/node_modules/pi-lens/dist/clients/print-mode.js +21 -0
- package/node_modules/pi-lens/dist/clients/project-changes.js +40 -0
- package/node_modules/pi-lens/dist/clients/project-diagnostics/cache.js +3 -2
- package/node_modules/pi-lens/dist/clients/project-diagnostics/fresh-fetch.js +1 -1
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/call-graph-impact.js +8 -0
- 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/scanner.js +21 -1
- package/node_modules/pi-lens/dist/clients/project-lens-config.js +86 -9
- package/node_modules/pi-lens/dist/clients/project-report.js +27 -13
- package/node_modules/pi-lens/dist/clients/project-snapshot.js +175 -20
- package/node_modules/pi-lens/dist/clients/project-trust.js +181 -0
- package/node_modules/pi-lens/dist/clients/quiet-window.js +18 -4
- package/node_modules/pi-lens/dist/clients/read-bridge.js +147 -0
- package/node_modules/pi-lens/dist/clients/read-guard-logger.js +159 -1
- package/node_modules/pi-lens/dist/clients/read-guard-tool-lines.js +150 -29
- package/node_modules/pi-lens/dist/clients/read-guard.js +185 -4
- package/node_modules/pi-lens/dist/clients/resource-sampler.js +70 -84
- package/node_modules/pi-lens/dist/clients/review-graph/builder.js +1122 -221
- package/node_modules/pi-lens/dist/clients/review-graph/git-identity.js +2 -1
- package/node_modules/pi-lens/dist/clients/review-graph/import-resolvers.js +21 -10
- package/node_modules/pi-lens/dist/clients/review-graph/query.js +24 -0
- package/node_modules/pi-lens/dist/clients/review-graph/symbol-id.js +46 -0
- package/node_modules/pi-lens/dist/clients/review-graph/tsconfig-paths.js +57 -6
- package/node_modules/pi-lens/dist/clients/review-graph/workspace-modules.js +51 -3
- package/node_modules/pi-lens/dist/clients/review-graph-logger.js +30 -1
- package/node_modules/pi-lens/dist/clients/ruff-client.js +27 -44
- package/node_modules/pi-lens/dist/clients/run-duration.js +55 -0
- package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +257 -77
- package/node_modules/pi-lens/dist/clients/runtime-context.js +129 -12
- package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +242 -26
- package/node_modules/pi-lens/dist/clients/runtime-session.js +428 -117
- package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +71 -48
- package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +342 -33
- package/node_modules/pi-lens/dist/clients/runtime-turn.js +619 -93
- package/node_modules/pi-lens/dist/clients/rust-client.js +23 -38
- package/node_modules/pi-lens/dist/clients/safe-spawn.js +777 -62
- package/node_modules/pi-lens/dist/clients/security-scan-client.js +90 -6
- package/node_modules/pi-lens/dist/clients/session-state-store.js +3 -2
- package/node_modules/pi-lens/dist/clients/sg-runner.js +424 -196
- package/node_modules/pi-lens/dist/clients/slow-fs.js +2 -1
- package/node_modules/pi-lens/dist/clients/smells-rollup.js +231 -0
- package/node_modules/pi-lens/dist/clients/source-filter.js +184 -20
- package/node_modules/pi-lens/dist/clients/source-walker.js +66 -10
- package/node_modules/pi-lens/dist/clients/startup-scan.js +15 -16
- package/node_modules/pi-lens/dist/clients/startup-timing.js +7 -1
- package/node_modules/pi-lens/dist/clients/test-runner-client.js +469 -32
- package/node_modules/pi-lens/dist/clients/tool-event.js +35 -0
- package/node_modules/pi-lens/dist/clients/tool-policy.js +390 -39
- package/node_modules/pi-lens/dist/clients/tool-render.js +155 -0
- package/node_modules/pi-lens/dist/clients/tool-set-policy.js +76 -0
- package/node_modules/pi-lens/dist/clients/tree-sitter-cache.js +6 -1
- package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +419 -50
- package/node_modules/pi-lens/dist/clients/tree-sitter-logger.js +21 -0
- package/node_modules/pi-lens/dist/clients/tree-sitter-query-loader.js +7 -1
- package/node_modules/pi-lens/dist/clients/tree-sitter-shared.js +7 -2
- package/node_modules/pi-lens/dist/clients/tree-sitter-symbol-extractor.js +44 -7
- package/node_modules/pi-lens/dist/clients/user-notify.js +51 -0
- package/node_modules/pi-lens/dist/clients/vanished-instance-marker.js +57 -0
- package/node_modules/pi-lens/dist/clients/warm-attach.js +50 -13
- package/node_modules/pi-lens/dist/clients/widget-state.js +300 -43
- package/node_modules/pi-lens/dist/clients/word-index.js +680 -81
- package/node_modules/pi-lens/dist/clients/workspace-topology.js +89 -6
- package/node_modules/pi-lens/dist/index.js +51785 -36118
- package/node_modules/pi-lens/dist/mcp/analyze-cli.js +182 -29
- package/node_modules/pi-lens/dist/mcp/server.js +219 -46
- 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/ast-grep-search.js +93 -27
- package/node_modules/pi-lens/dist/tools/lens-diagnostic-mark.js +5 -2
- package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +203 -38
- package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +210 -42
- package/node_modules/pi-lens/dist/tools/lsp-navigation.js +46 -3
- package/node_modules/pi-lens/dist/tools/module-report.js +9 -0
- package/node_modules/pi-lens/dist/tools/symbol-search.js +1 -1
- package/node_modules/pi-lens/docs/agent-guide.md +40 -15
- package/node_modules/pi-lens/docs/agent-tools.md +21 -10
- package/node_modules/pi-lens/docs/analysisall.md +192 -0
- package/node_modules/pi-lens/docs/api-ports-inventory.md +165 -0
- package/node_modules/pi-lens/docs/ast-grep_rules_catalog.md +14 -3
- package/node_modules/pi-lens/docs/durable-store-audit-1202.md +32 -0
- package/node_modules/pi-lens/docs/environment-variables.md +44 -0
- package/node_modules/pi-lens/docs/fable.md +27 -0
- package/node_modules/pi-lens/docs/features.md +45 -3
- package/node_modules/pi-lens/docs/globalconfig.md +56 -1
- package/node_modules/pi-lens/docs/language-coverage.md +4 -3
- package/node_modules/pi-lens/docs/lsp-capability-matrix.md +2 -2
- package/node_modules/pi-lens/docs/mcp.md +37 -4
- package/node_modules/pi-lens/docs/servercapabilities.md +3 -3
- package/node_modules/pi-lens/docs/settings.md +18 -1
- package/node_modules/pi-lens/docs/tools.md +4 -1
- package/node_modules/pi-lens/docs/usage.md +41 -5
- package/node_modules/pi-lens/docs/word-index.md +35 -0
- package/node_modules/pi-lens/package.json +10 -10
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-bare-except-test.yml +49 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-bare-host-path-in-win32-branch-test.yml +87 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-chained-type-assertions-test.yml +8 -0
- 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-nested-links-test.yml +11 -1
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-raw-json-store-write-test.yml +17 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-js-test.yml +7 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-test.yml +7 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-js-test.yml +8 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-test.yml +8 -0
- 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-win32-isabsolute-for-qualification-test.yml +16 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-except.yml +3 -15
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-host-path-in-win32-branch.yml +25 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-chained-type-assertions.yml +21 -0
- 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-nested-links.yml +7 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-raw-json-store-write.yml +30 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply-js.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get-js.yml +13 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get.yml +16 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-laundering.yml +27 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-win32-isabsolute-for-qualification.yml +23 -0
- package/node_modules/pi-lens/rules/tree-sitter-queries/tsx/no-nested-links.yml +4 -6
- package/node_modules/pi-lens/rules/tree-sitter-queries/typescript/duplicate-function-arg.yml +2 -2
- package/node_modules/pi-lens/scripts/analyze-pi-lens-logs.mjs +134 -2
- package/node_modules/pi-lens/skills/pi-lens-ast-grep/SKILL.md +10 -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 +8 -114
- package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/reference.md +129 -0
- package/node_modules/pi-lens/skills/pi-lens-write-tree-sitter-rule/SKILL.md +3 -1
- package/node_modules/pi-mcp-adapter/CHANGELOG.md +38 -0
- package/node_modules/pi-mcp-adapter/README.md +38 -4
- package/node_modules/pi-mcp-adapter/agent-dir.ts +12 -4
- package/node_modules/pi-mcp-adapter/agent-plugin-loader.ts +1 -1
- package/node_modules/pi-mcp-adapter/cli.js +25 -4
- package/node_modules/pi-mcp-adapter/commands.ts +15 -7
- package/node_modules/pi-mcp-adapter/config.ts +4 -4
- package/node_modules/pi-mcp-adapter/direct-tools.ts +58 -8
- package/node_modules/pi-mcp-adapter/host-html-template.ts +0 -8
- package/node_modules/pi-mcp-adapter/index.ts +8 -3
- package/node_modules/pi-mcp-adapter/init.ts +29 -5
- package/node_modules/pi-mcp-adapter/lifecycle.ts +0 -4
- package/node_modules/pi-mcp-adapter/mcp-auth-flow.ts +1 -2
- package/node_modules/pi-mcp-adapter/mcp-auth.ts +60 -2
- package/node_modules/pi-mcp-adapter/mcp-panel.ts +45 -9
- package/node_modules/pi-mcp-adapter/mcp-script-worker.mjs +22 -20
- package/node_modules/pi-mcp-adapter/mcp-setup-panel.ts +2 -1
- package/node_modules/pi-mcp-adapter/metadata-cache.ts +37 -4
- package/node_modules/pi-mcp-adapter/npx-resolver.ts +81 -26
- package/node_modules/pi-mcp-adapter/package.json +4 -3
- package/node_modules/pi-mcp-adapter/proxy-modes.ts +108 -26
- package/node_modules/pi-mcp-adapter/request-headers-command.ts +336 -0
- package/node_modules/pi-mcp-adapter/search-ranking.ts +86 -7
- package/node_modules/pi-mcp-adapter/server-manager.ts +41 -7
- package/node_modules/pi-mcp-adapter/session-recovery.ts +8 -2
- package/node_modules/pi-mcp-adapter/tool-approval.ts +48 -7
- package/node_modules/pi-mcp-adapter/tool-metadata.ts +62 -4
- package/node_modules/pi-mcp-adapter/tool-result-renderer.ts +138 -12
- package/node_modules/pi-mcp-adapter/types.ts +176 -27
- package/node_modules/pi-mcp-adapter/ui-server.ts +20 -1
- package/node_modules/pi-web-access/CHANGELOG.md +14 -0
- package/node_modules/pi-web-access/README.md +18 -12
- package/node_modules/pi-web-access/auth-fetch.ts +148 -0
- package/node_modules/pi-web-access/chrome-cookies.ts +110 -23
- package/node_modules/pi-web-access/curator-page.ts +5 -3
- package/node_modules/pi-web-access/curator-server.ts +2 -1
- package/node_modules/pi-web-access/extract.ts +106 -34
- 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 +18 -4
- package/node_modules/pi-web-access/index.ts +120 -48
- package/node_modules/pi-web-access/package.json +2 -2
- package/node_modules/pi-web-access/summary-review.ts +11 -5
- package/node_modules/pi-web-access/youtube-extract.ts +2 -2
- package/package.json +12 -13
- package/node_modules/pi-lens/dist/clients/ast-grep-parser.js +0 -86
- package/node_modules/pi-lens/dist/clients/lsp/interactive-install.js +0 -367
- package/node_modules/pi-lens/dist/clients/lsp/lsp-index.js +0 -10
- package/node_modules/pi-lens/dist/clients/lsp/server-strategies.js +0 -5
- package/node_modules/pi-lens/dist/clients/project-metadata.js +0 -690
- package/node_modules/pi-lens/dist/clients/source-groups.js +0 -96
- package/node_modules/pi-lens/dist/clients/startup-marker.js +0 -6
- package/node_modules/pi-lens/dist/clients/types.js +0 -11
|
@@ -8,11 +8,14 @@
|
|
|
8
8
|
* Requires: npm install -D knip
|
|
9
9
|
* Docs: https://knip.dev/
|
|
10
10
|
*/
|
|
11
|
+
import { createSubsystemLogger } from "./extension-log.js";
|
|
11
12
|
import * as fs from "node:fs";
|
|
12
13
|
import * as path from "node:path";
|
|
13
14
|
import { getProjectDataDir } from "./file-utils.js";
|
|
14
15
|
import { findNearestMarkerRoot } from "./path-utils.js";
|
|
15
16
|
import { safeSpawnAsync } from "./safe-spawn.js";
|
|
17
|
+
import { createAvailabilityChecker, findManagedNodeToolBinary, getManagedToolEnvironment, resolveAvailableOrInstall, } from "./dispatch/runners/utils/runner-helpers.js";
|
|
18
|
+
import { createAvailabilityLatch, describeUnavailability, } from "./dispatch/runners/utils/availability-policy.js";
|
|
16
19
|
const EMPTY_RESULT = {
|
|
17
20
|
success: false,
|
|
18
21
|
issues: [],
|
|
@@ -56,7 +59,18 @@ export function readOverridePinnedPackageNames(targetDir) {
|
|
|
56
59
|
}
|
|
57
60
|
// --- Client ---
|
|
58
61
|
export class KnipClient {
|
|
59
|
-
|
|
62
|
+
knipAvailability = createAvailabilityChecker("knip", ".cmd", ["--version"], {
|
|
63
|
+
environment: (cwd) => getManagedToolEnvironment("knip", cwd),
|
|
64
|
+
unclassifiedFailureOutcome: "missing",
|
|
65
|
+
fastPath: () => findManagedNodeToolBinary("knip"),
|
|
66
|
+
});
|
|
67
|
+
/**
|
|
68
|
+
* Client-side memo. Only a DURABLE verdict is latched — a transient probe
|
|
69
|
+
* failure expires, so an installed knip becomes available again without a
|
|
70
|
+
* host restart (#1467).
|
|
71
|
+
*/
|
|
72
|
+
availabilityLatch = createAvailabilityLatch();
|
|
73
|
+
knipCommand = "knip";
|
|
60
74
|
ensureInFlight = null;
|
|
61
75
|
log;
|
|
62
76
|
/**
|
|
@@ -75,7 +89,7 @@ export class KnipClient {
|
|
|
75
89
|
inFlight = new Map();
|
|
76
90
|
constructor(verbose = false) {
|
|
77
91
|
this.log = verbose
|
|
78
|
-
? (
|
|
92
|
+
? createSubsystemLogger("knip")
|
|
79
93
|
: () => { };
|
|
80
94
|
}
|
|
81
95
|
/**
|
|
@@ -97,12 +111,17 @@ export class KnipClient {
|
|
|
97
111
|
return findNearestMarkerRoot(startDir, ["package.json", "knip.json", "knip.ts", "knip.config.js", "knip.config.ts"], { boundaries: [".git", ".hg", ".svn"], homeDir: homeDirOverride });
|
|
98
112
|
}
|
|
99
113
|
/**
|
|
100
|
-
* Check if knip CLI is available, auto-install if not
|
|
114
|
+
* Check if knip CLI is available, auto-install if not.
|
|
115
|
+
*
|
|
116
|
+
* The memo returns `null` when the last verdict was transient and its
|
|
117
|
+
* cooldown has expired, which re-enters the probe. That is the difference
|
|
118
|
+
* between "knip is missing" (a fact worth caching) and "the probe timed out"
|
|
119
|
+
* (a moment worth retrying).
|
|
101
120
|
*/
|
|
102
121
|
async ensureAvailable() {
|
|
103
|
-
|
|
104
|
-
if (
|
|
105
|
-
return
|
|
122
|
+
const memo = this.availabilityLatch.read();
|
|
123
|
+
if (memo !== null)
|
|
124
|
+
return memo;
|
|
106
125
|
if (this.ensureInFlight)
|
|
107
126
|
return this.ensureInFlight;
|
|
108
127
|
this.ensureInFlight = this.doEnsureAvailable();
|
|
@@ -114,27 +133,40 @@ export class KnipClient {
|
|
|
114
133
|
}
|
|
115
134
|
}
|
|
116
135
|
async doEnsureAvailable() {
|
|
117
|
-
|
|
118
|
-
const
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
this.knipAvailable = true;
|
|
123
|
-
this.log("Knip found in PATH");
|
|
136
|
+
const cwd = process.cwd();
|
|
137
|
+
const resolved = await resolveAvailableOrInstall(this.knipAvailability, "knip", cwd);
|
|
138
|
+
if (resolved !== null) {
|
|
139
|
+
this.knipCommand = resolved;
|
|
140
|
+
this.availabilityLatch.noteAvailable();
|
|
124
141
|
return true;
|
|
125
142
|
}
|
|
126
|
-
|
|
127
|
-
this.
|
|
128
|
-
const { ensureTool } = await import("./installer/index.js");
|
|
129
|
-
const installedPath = await ensureTool("knip");
|
|
130
|
-
if (installedPath) {
|
|
131
|
-
this.knipAvailable = true;
|
|
132
|
-
this.log(`Knip auto-installed: ${installedPath}`);
|
|
133
|
-
return true;
|
|
134
|
-
}
|
|
135
|
-
this.knipAvailable = false;
|
|
143
|
+
const verdict = this.knipAvailability.getVerdict(cwd);
|
|
144
|
+
this.availabilityLatch.noteUnavailable(verdict.outcome ?? "missing", verdict.cause ?? "not-found");
|
|
136
145
|
return false;
|
|
137
146
|
}
|
|
147
|
+
/**
|
|
148
|
+
* The single place a knip-unavailable result is worded. A transient probe
|
|
149
|
+
* failure must never be reported as "install knip" — knip is on disk.
|
|
150
|
+
*/
|
|
151
|
+
unavailableResult() {
|
|
152
|
+
const verdict = this.knipAvailability.getVerdict(process.cwd());
|
|
153
|
+
const transient = verdict.outcome === "transient";
|
|
154
|
+
const retryAfterMs = verdict.retryAtMs
|
|
155
|
+
? Math.max(0, verdict.retryAtMs - Date.now())
|
|
156
|
+
: undefined;
|
|
157
|
+
return {
|
|
158
|
+
...EMPTY_RESULT,
|
|
159
|
+
failureKind: transient ? "unavailable-transient" : "unavailable-missing",
|
|
160
|
+
summary: describeUnavailability({
|
|
161
|
+
tool: "Knip",
|
|
162
|
+
installHint: "npm install -D knip",
|
|
163
|
+
outcome: verdict.outcome,
|
|
164
|
+
cause: verdict.cause,
|
|
165
|
+
elapsedMs: verdict.elapsedMs,
|
|
166
|
+
retryAfterMs,
|
|
167
|
+
}),
|
|
168
|
+
};
|
|
169
|
+
}
|
|
138
170
|
/**
|
|
139
171
|
* Run knip analysis on the project.
|
|
140
172
|
*
|
|
@@ -160,10 +192,7 @@ export class KnipClient {
|
|
|
160
192
|
};
|
|
161
193
|
}
|
|
162
194
|
if (!(await this.ensureAvailable())) {
|
|
163
|
-
return
|
|
164
|
-
...EMPTY_RESULT,
|
|
165
|
-
summary: "Knip not available. Install with: npm install -D knip",
|
|
166
|
-
};
|
|
195
|
+
return this.unavailableResult();
|
|
167
196
|
}
|
|
168
197
|
const key = path.resolve(targetDir);
|
|
169
198
|
const existing = this.inFlight.get(key);
|
|
@@ -213,10 +242,10 @@ export class KnipClient {
|
|
|
213
242
|
"--cache-location",
|
|
214
243
|
cacheLocation,
|
|
215
244
|
];
|
|
216
|
-
const result = await safeSpawnAsync(
|
|
245
|
+
const result = await safeSpawnAsync(this.knipCommand, args, {
|
|
217
246
|
timeout: ANALYSIS_TIMEOUT_MS,
|
|
218
247
|
cwd: targetDir,
|
|
219
|
-
env: await
|
|
248
|
+
env: await getManagedToolEnvironment("knip", targetDir),
|
|
220
249
|
});
|
|
221
250
|
if (result.error) {
|
|
222
251
|
this.log(`Analysis error: ${result.error.message}`);
|
|
@@ -271,19 +300,6 @@ export class KnipClient {
|
|
|
271
300
|
? result
|
|
272
301
|
: { ...result, issues, unusedDeps };
|
|
273
302
|
}
|
|
274
|
-
async getKnipEnvironment(targetDir) {
|
|
275
|
-
const { getToolEnvironment } = await import("./installer/index.js");
|
|
276
|
-
const env = await getToolEnvironment();
|
|
277
|
-
const separator = process.platform === "win32" ? ";" : ":";
|
|
278
|
-
const currentPath = env.PATH || env.Path || process.env.PATH || "";
|
|
279
|
-
const localBin = path.join(targetDir, "node_modules", ".bin");
|
|
280
|
-
const augmentedPath = `${localBin}${separator}${currentPath}`;
|
|
281
|
-
return {
|
|
282
|
-
...env,
|
|
283
|
-
PATH: augmentedPath,
|
|
284
|
-
...(process.platform === "win32" ? { Path: augmentedPath } : {}),
|
|
285
|
-
};
|
|
286
|
-
}
|
|
287
303
|
/**
|
|
288
304
|
* Find unused exports in a specific file
|
|
289
305
|
*/
|
|
@@ -56,11 +56,13 @@ export const LANGUAGE_POLICY = {
|
|
|
56
56
|
lua: { lspCapable: true },
|
|
57
57
|
zig: { lspCapable: true },
|
|
58
58
|
haskell: { lspCapable: true },
|
|
59
|
+
"helm-template": { lspCapable: false },
|
|
59
60
|
elixir: { lspCapable: true },
|
|
60
61
|
gleam: { lspCapable: true },
|
|
61
62
|
ocaml: { lspCapable: true },
|
|
62
63
|
clojure: { lspCapable: true },
|
|
63
64
|
terraform: { lspCapable: true },
|
|
65
|
+
terragrunt: { lspCapable: false },
|
|
64
66
|
nix: { lspCapable: true },
|
|
65
67
|
toml: { lspCapable: true, startup: { defaults: ["taplo"] } },
|
|
66
68
|
};
|
|
@@ -117,7 +119,7 @@ const PRIMARY_DISPATCH_GROUPS = {
|
|
|
117
119
|
},
|
|
118
120
|
yaml: {
|
|
119
121
|
mode: "all",
|
|
120
|
-
runnerIds: ["lsp", "yamllint", "trivy-config"],
|
|
122
|
+
runnerIds: ["lsp", "yamllint", "trivy-config", "helm-lint"],
|
|
121
123
|
filterKinds: ["yaml"],
|
|
122
124
|
},
|
|
123
125
|
sql: {
|
|
@@ -179,6 +181,11 @@ const PRIMARY_DISPATCH_GROUPS = {
|
|
|
179
181
|
lua: { mode: "fallback", runnerIds: ["lsp"], filterKinds: ["lua"] },
|
|
180
182
|
zig: { mode: "all", runnerIds: ["lsp", "zig-check"], filterKinds: ["zig"] },
|
|
181
183
|
haskell: { mode: "fallback", runnerIds: ["lsp"], filterKinds: ["haskell"] },
|
|
184
|
+
"helm-template": {
|
|
185
|
+
mode: "all",
|
|
186
|
+
runnerIds: ["helm-lint"],
|
|
187
|
+
filterKinds: ["helm-template"],
|
|
188
|
+
},
|
|
182
189
|
elixir: {
|
|
183
190
|
mode: "all",
|
|
184
191
|
runnerIds: ["lsp", "elixir-check", "credo"],
|
|
@@ -193,9 +200,14 @@ const PRIMARY_DISPATCH_GROUPS = {
|
|
|
193
200
|
clojure: { mode: "fallback", runnerIds: ["lsp"], filterKinds: ["clojure"] },
|
|
194
201
|
terraform: {
|
|
195
202
|
mode: "all",
|
|
196
|
-
runnerIds: ["lsp", "tflint"],
|
|
203
|
+
runnerIds: ["lsp", "tflint", "trivy-config"],
|
|
197
204
|
filterKinds: ["terraform"],
|
|
198
205
|
},
|
|
206
|
+
terragrunt: {
|
|
207
|
+
mode: "all",
|
|
208
|
+
runnerIds: ["terragrunt"],
|
|
209
|
+
filterKinds: ["terragrunt"],
|
|
210
|
+
},
|
|
199
211
|
nix: { mode: "fallback", runnerIds: ["lsp"], filterKinds: ["nix"] },
|
|
200
212
|
toml: {
|
|
201
213
|
mode: "all",
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
|
-
import { CODE_KINDS, detectFileKind, DOTNET_CSHARP_ROOT_MARKERS, DOTNET_FSHARP_ROOT_MARKERS, KIND_EXTENSIONS, } from "./file-kinds.js";
|
|
3
|
+
import { CODE_KINDS, detectFileKind, DOTNET_CSHARP_ROOT_MARKERS, DOTNET_FSHARP_ROOT_MARKERS, KIND_EXTENSIONS, TERRAGRUNT_FILENAMES, } from "./file-kinds.js";
|
|
4
4
|
import { getProjectIgnoreMatcher } from "./file-utils.js";
|
|
5
|
-
import { direntsHaveMarkerGlobMatch } from "./path-utils.js";
|
|
5
|
+
import { direntsHaveMarkerGlobMatch, normalizeMapKey } from "./path-utils.js";
|
|
6
6
|
import { LANGUAGE_POLICY, } from "./language-policy.js";
|
|
7
7
|
import { getSourceFiles } from "./scan-utils.js";
|
|
8
8
|
import { readDirEntriesSafe, shouldRecurseIntoDir } from "./source-walker.js";
|
|
9
9
|
import { findNearestDirWithAnyBasename } from "./workspace-topology.js";
|
|
10
|
+
import { BoundedLruCache } from "./bounded-cache.js";
|
|
10
11
|
/** Every registered kind participates in project-language detection (#894). */
|
|
11
12
|
export const SUPPORTED_FILE_KINDS = Object.keys(KIND_EXTENSIONS);
|
|
12
13
|
const PROJECT_MARKERS_BY_KIND = {
|
|
@@ -36,6 +37,7 @@ const PROJECT_MARKERS_BY_KIND = {
|
|
|
36
37
|
elixir: ["mix.exs"],
|
|
37
38
|
gleam: ["gleam.toml"],
|
|
38
39
|
terraform: [".terraform.lock.hcl"],
|
|
40
|
+
terragrunt: TERRAGRUNT_FILENAMES,
|
|
39
41
|
nix: ["flake.nix"],
|
|
40
42
|
toml: ["pyproject.toml", "Cargo.toml", "taplo.toml"],
|
|
41
43
|
csharp: DOTNET_CSHARP_ROOT_MARKERS,
|
|
@@ -80,6 +82,7 @@ const ROOT_MARKERS_BY_KIND = {
|
|
|
80
82
|
elixir: ["mix.exs"],
|
|
81
83
|
gleam: ["gleam.toml"],
|
|
82
84
|
terraform: [".terraform.lock.hcl"],
|
|
85
|
+
terragrunt: TERRAGRUNT_FILENAMES,
|
|
83
86
|
nix: ["flake.nix"],
|
|
84
87
|
toml: ["pyproject.toml", "Cargo.toml", "taplo.toml"],
|
|
85
88
|
csharp: DOTNET_CSHARP_ROOT_MARKERS,
|
|
@@ -101,16 +104,16 @@ function hasProjectMarker(projectRoot, marker) {
|
|
|
101
104
|
// must not pollute the no-arg cache. The synchronous getSourceFiles() call
|
|
102
105
|
// inside this function does the same expensive ignoreMatcher-driven walk
|
|
103
106
|
// as resolveStartupScanContext, so the same memo strategy applies.
|
|
104
|
-
const languageProfileCache = new
|
|
107
|
+
const languageProfileCache = new BoundedLruCache(32);
|
|
105
108
|
export function detectProjectLanguageProfile(projectRoot, sourceFiles) {
|
|
106
109
|
if (sourceFiles === undefined) {
|
|
107
|
-
const cached = languageProfileCache.get(projectRoot);
|
|
110
|
+
const cached = languageProfileCache.get(normalizeMapKey(projectRoot));
|
|
108
111
|
if (cached)
|
|
109
112
|
return cached;
|
|
110
113
|
}
|
|
111
114
|
const result = computeProjectLanguageProfile(projectRoot, sourceFiles);
|
|
112
115
|
if (sourceFiles === undefined) {
|
|
113
|
-
languageProfileCache.set(projectRoot, result);
|
|
116
|
+
languageProfileCache.set(normalizeMapKey(projectRoot), result);
|
|
114
117
|
}
|
|
115
118
|
return result;
|
|
116
119
|
}
|
|
@@ -297,6 +300,9 @@ export async function collectSourceFilesForWarmup(rootDir, maxFiles = MAX_WARMUP
|
|
|
297
300
|
break walk;
|
|
298
301
|
}
|
|
299
302
|
}
|
|
303
|
+
// Each iteration performs only bounded dirent/ext/ignore checks. Keep the
|
|
304
|
+
// count cadence: the cost does not scale with the corpus item size, and
|
|
305
|
+
// this walk's existing matched-file ceiling bounds the total work.
|
|
300
306
|
if (++processedSinceYield % yieldEvery === 0) {
|
|
301
307
|
// See countSourceFilesWithinLimitAsync for why setImmediate.
|
|
302
308
|
await new Promise((resolve) => setImmediate(resolve));
|
|
@@ -306,7 +312,7 @@ export async function collectSourceFilesForWarmup(rootDir, maxFiles = MAX_WARMUP
|
|
|
306
312
|
return [...codeOut, ...nonCodeOut];
|
|
307
313
|
}
|
|
308
314
|
export async function detectProjectLanguageProfileAsync(projectRoot) {
|
|
309
|
-
const cached = languageProfileCache.get(projectRoot);
|
|
315
|
+
const cached = languageProfileCache.get(normalizeMapKey(projectRoot));
|
|
310
316
|
if (cached)
|
|
311
317
|
return cached;
|
|
312
318
|
const files = await collectSourceFilesForWarmup(projectRoot);
|
|
@@ -315,6 +321,6 @@ export async function detectProjectLanguageProfileAsync(projectRoot) {
|
|
|
315
321
|
// probe (`existsSync` for package.json / pyproject.toml / etc.) which
|
|
316
322
|
// is constant-time and cheap.
|
|
317
323
|
const result = detectProjectLanguageProfile(projectRoot, files);
|
|
318
|
-
languageProfileCache.set(projectRoot, result);
|
|
324
|
+
languageProfileCache.set(normalizeMapKey(projectRoot), result);
|
|
319
325
|
return result;
|
|
320
326
|
}
|
|
@@ -9,11 +9,82 @@ const writer = createNdjsonLogger({
|
|
|
9
9
|
filePath: LATENCY_LOG_FILE,
|
|
10
10
|
maxBytes: getMaxLogSizeMB() * 1024 * 1024,
|
|
11
11
|
});
|
|
12
|
+
/**
|
|
13
|
+
* Most recent non-`loop_block` phase seen by `logLatency`, for cheap block
|
|
14
|
+
* attribution (#1122 / #1123 item 1): the event-loop-block probe fires at
|
|
15
|
+
* turn_end and cannot see *what* stalled the loop, so it stamps the last phase
|
|
16
|
+
* that ran as a starting point for root-causing a genuine block. Tracked before
|
|
17
|
+
* the test-mode guard so it is deterministic and unit-testable.
|
|
18
|
+
*/
|
|
19
|
+
let lastPhase;
|
|
20
|
+
/**
|
|
21
|
+
* Phases excluded from `lastPhase` attribution alongside `loop_block`.
|
|
22
|
+
* #1412 L3: `lsp_typescript_project_identity` is the classic-TS first-open
|
|
23
|
+
* project-identity probe (tsserver-sync.ts) — a detached, best-effort
|
|
24
|
+
* telemetry sample fired on every first didOpen, not genuine work. Letting it
|
|
25
|
+
* win `lastPhase` would overwrite the real stall attribution for a
|
|
26
|
+
* loop_block that happens to land right after a first open.
|
|
27
|
+
* #1432 review: `advisory_provenance_decision`,
|
|
28
|
+
* `authoritative_content_attachment_decision`, and
|
|
29
|
+
* `agent_end_deferred_mutation_drain` are the same shape — zero-duration
|
|
30
|
+
* decision telemetry, not genuine work — so they get the same exclusion.
|
|
31
|
+
* `agent_end_deferred_mutation_requeue` (S2d gap 4's per-requeue record) and
|
|
32
|
+
* `session_end_bus_rollup` (S2d gap 5's session-end rollup) are new
|
|
33
|
+
* zero-duration siblings of the same shape, added alongside them.
|
|
34
|
+
*
|
|
35
|
+
* `lsp_aux_wait_outcome` (#1458) is DIFFERENT from every entry above: its
|
|
36
|
+
* `durationMs` is a REAL bounded wait (the post-primary auxiliary grace, up
|
|
37
|
+
* to a few seconds), not zero-duration decision telemetry. It is still
|
|
38
|
+
* excluded because it is a WAIT-OUTCOME RECORD written after the aux wait
|
|
39
|
+
* already completed, not the stall itself — that wait ran inside the
|
|
40
|
+
* `lsp_touch_file`/diagnostics phase surrounding it, so letting this summary
|
|
41
|
+
* row win `lastPhase` would misattribute a `loop_block` to the record instead
|
|
42
|
+
* of to whatever phase is actually stalled when the block fires.
|
|
43
|
+
* #1453: `tool_set_mutation` records an active-tool-set rewrite (zero-duration
|
|
44
|
+
* bookkeeping, and it fires during session_start where a real stall must stay
|
|
45
|
+
* attributed to the work around it), so it is excluded for the same reason.
|
|
46
|
+
* #1467: `availability_decision` records a tool-probe verdict. Its `durationMs`
|
|
47
|
+
* is the child's own probe time (often zero for a fast path or a cached
|
|
48
|
+
* decision) and the record is bookkeeping ABOUT a probe, not host work — a
|
|
49
|
+
* loop_block landing next to one must stay attributed to whatever really
|
|
50
|
+
* stalled the loop, which is frequently the very thing that expired the probe.
|
|
51
|
+
*
|
|
52
|
+
* #1461 slice 1: `finding_dead_path_drop` is the same shape — the record a
|
|
53
|
+
* delivery seam writes when it drops findings whose cited path no longer
|
|
54
|
+
* exists.
|
|
55
|
+
*/
|
|
56
|
+
const LAST_PHASE_EXCLUDED = new Set([
|
|
57
|
+
"loop_block",
|
|
58
|
+
"lsp_typescript_project_identity",
|
|
59
|
+
"advisory_provenance_decision",
|
|
60
|
+
"authoritative_content_attachment_decision",
|
|
61
|
+
"agent_end_deferred_mutation_drain",
|
|
62
|
+
"agent_end_deferred_mutation_requeue",
|
|
63
|
+
"session_end_bus_rollup",
|
|
64
|
+
"lsp_aux_wait_outcome",
|
|
65
|
+
"tool_set_mutation",
|
|
66
|
+
"availability_decision",
|
|
67
|
+
"finding_dead_path_drop",
|
|
68
|
+
]);
|
|
69
|
+
/**
|
|
70
|
+
* The last non-`loop_block` phase logged, or undefined if none yet. Carries its
|
|
71
|
+
* own `ts` so a consumer can gauge staleness: it is intentionally NOT cleared at
|
|
72
|
+
* turn/window boundaries, so on a turn that logged no phase of its own it may
|
|
73
|
+
* point at a prior turn's phase — compare `ts` against the block time before
|
|
74
|
+
* trusting it as the cause (it is a breadcrumb, not proof).
|
|
75
|
+
*/
|
|
76
|
+
export function getLastLoggedPhase() {
|
|
77
|
+
return lastPhase;
|
|
78
|
+
}
|
|
12
79
|
export function logLatency(entry) {
|
|
80
|
+
const ts = new Date().toISOString();
|
|
81
|
+
if (entry.type === "phase" && entry.phase && !LAST_PHASE_EXCLUDED.has(entry.phase)) {
|
|
82
|
+
lastPhase = { phase: entry.phase, ts };
|
|
83
|
+
}
|
|
13
84
|
if (isTestMode()) {
|
|
14
85
|
return;
|
|
15
86
|
}
|
|
16
|
-
writer.log({ ...entry, ts
|
|
87
|
+
writer.log({ ...entry, ts, pid: process.pid });
|
|
17
88
|
}
|
|
18
89
|
export function getLatencyLogPath() {
|
|
19
90
|
return LATENCY_LOG_FILE;
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { logExtension } from "./extension-log.js";
|
|
2
|
+
import { notifyUserDegradation } from "./user-notify.js";
|
|
1
3
|
import * as fs from "node:fs";
|
|
2
4
|
import * as os from "node:os";
|
|
3
5
|
import * as path from "node:path";
|
|
@@ -20,7 +22,16 @@ function warnInvalidGlobalConfigOnce(configPath, reason) {
|
|
|
20
22
|
if (warnedInvalidGlobalConfigs.has(key))
|
|
21
23
|
return;
|
|
22
24
|
warnedInvalidGlobalConfigs.add(key);
|
|
23
|
-
|
|
25
|
+
const message = `ignoring invalid global config ${configPath}: ${reason}`;
|
|
26
|
+
logExtension({
|
|
27
|
+
subsystem: "lens-config",
|
|
28
|
+
level: "warn",
|
|
29
|
+
message,
|
|
30
|
+
metadata: { configPath, reason },
|
|
31
|
+
});
|
|
32
|
+
// HUMAN-audience too: a config the user wrote is being ignored. Routed
|
|
33
|
+
// through the host's own render path (#1333), never a raw write.
|
|
34
|
+
notifyUserDegradation(`pi-lens: ${message}`);
|
|
24
35
|
}
|
|
25
36
|
/** For tests that need to force the warn-once cache to reset between cases. */
|
|
26
37
|
export function resetGlobalConfigWarnCache() {
|
|
@@ -13,27 +13,28 @@
|
|
|
13
13
|
* adds thin wrappers over the remaining internal reach-ins (latency, project
|
|
14
14
|
* scan, LSP status, diagnostic stats, LSP config).
|
|
15
15
|
*/
|
|
16
|
+
import * as path from "node:path";
|
|
17
|
+
import { minimatch } from "./deps/minimatch.js";
|
|
16
18
|
import { getDiagnosticTracker } from "./diagnostic-tracker.js";
|
|
17
19
|
import { getLatencyReports, } from "./dispatch/integration.js";
|
|
18
20
|
import { getResourceFootprint as getResourceFootprintSnapshot, } from "./instance-registry.js";
|
|
19
21
|
import { initLSPConfig } from "./lsp/config.js";
|
|
20
22
|
import { getLSPService } from "./lsp/index.js";
|
|
21
|
-
import {
|
|
23
|
+
import { acquireWarmWordIndex } from "./mcp/analyze.js";
|
|
24
|
+
import { normalizeMapKey } from "./path-utils.js";
|
|
22
25
|
import { scanProjectDiagnostics } from "./project-diagnostics/scanner.js";
|
|
26
|
+
import { loadProjectSnapshotWithoutWordIndex } from "./project-snapshot.js";
|
|
23
27
|
import { getTreeSitterRuntimeStatus, } from "./tree-sitter-shared.js";
|
|
24
|
-
import
|
|
25
|
-
import { minimatch } from "./deps/minimatch.js";
|
|
26
|
-
import { normalizeMapKey } from "./path-utils.js";
|
|
27
|
-
import { loadProjectSnapshot } from "./project-snapshot.js";
|
|
28
|
-
import { centralityFromReverseDeps, deserializeWordIndex, getWordIndexBuildStatus, searchWordIndex, triggerBackgroundWordIndexBuild, } from "./word-index.js";
|
|
28
|
+
import { centralityFromReverseDeps, getWordIndexBuildStatus, searchWordIndex, triggerBackgroundWordIndexBuild, } from "./word-index.js";
|
|
29
29
|
// --- Facades (re-exported so adapters import only this module) ---------------
|
|
30
30
|
export { analyzeFile, } from "./mcp/analyze.js";
|
|
31
31
|
export { createMcpHost } from "./mcp/host-shim.js";
|
|
32
|
-
export { ipcPathForCwd, requestWarmAnalyze, } from "./mcp/ipc.js";
|
|
32
|
+
export { createWarmIpcLineReader, createWarmIpcRequestQueue, ipcPathForCwd, readTurnEndStatus, requestWarmAnalyze, WARM_TURN_END_SCHEMA_VERSION, } from "./mcp/ipc.js";
|
|
33
33
|
export { analyzeFileFresh, canRebuildPiLens, REBUILD_UNAVAILABLE_MESSAGE, resolveRebuildScript, runRebuild, summarizeScan, } from "./mcp/review.js";
|
|
34
|
-
export { runSessionStart, runTurnEnd, } from "./mcp/session.js";
|
|
34
|
+
export { acknowledgeTurnEnd, runSessionStart, runTurnEnd, runTurnEndForIpc, } from "./mcp/session.js";
|
|
35
35
|
export { moduleReport, readEnclosing, readSymbol, renderCompactModuleReport, } from "./module-report.js";
|
|
36
36
|
export { projectReport, renderCompactProjectReport, } from "./project-report.js";
|
|
37
|
+
export { createDefaultHostPorts, } from "./host-ports.js";
|
|
37
38
|
// --- Query wrappers (own the remaining internal reach-ins) -------------------
|
|
38
39
|
/** Recent dispatch latency reports (latency.log schema), newest first. */
|
|
39
40
|
export function recentLatency(limit = 5, fileFilter) {
|
|
@@ -44,9 +45,21 @@ export function recentLatency(limit = 5, fileFilter) {
|
|
|
44
45
|
}
|
|
45
46
|
return reports.slice(-limit).reverse();
|
|
46
47
|
}
|
|
47
|
-
/**
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
/**
|
|
49
|
+
* Cheap project-wide scan (tree-sitter + fact rules).
|
|
50
|
+
*
|
|
51
|
+
* `includeGenerated` (#1107 phase 2 review): scan WITHOUT the generated/
|
|
52
|
+
* artifact NAME-heuristic filter — the actionable opt-out
|
|
53
|
+
* `generatedSkipNotice` below points a user at. Default `false` (existing
|
|
54
|
+
* filtering behavior unchanged).
|
|
55
|
+
*/
|
|
56
|
+
export function projectScan(cwd, maxFiles, includeGenerated) {
|
|
57
|
+
return scanProjectDiagnostics({
|
|
58
|
+
cwd,
|
|
59
|
+
tier: "cheap",
|
|
60
|
+
maxFiles,
|
|
61
|
+
includeGenerated,
|
|
62
|
+
});
|
|
50
63
|
}
|
|
51
64
|
/**
|
|
52
65
|
* #784: `scanTruncated` (#760) reaches this seam intact but, until now, no
|
|
@@ -66,6 +79,53 @@ export function scanTruncationNotice(snapshot) {
|
|
|
66
79
|
return (`⚠ Scan truncated at ${snapshot.filesScanned} file(s) — results are partial; ` +
|
|
67
80
|
"raise maxProjectFiles in .pi-lens.json to scan fully.");
|
|
68
81
|
}
|
|
82
|
+
/**
|
|
83
|
+
* #1107 phase 2: `generatedNameOnlySkips`/`generatedDirSkips` reach this seam
|
|
84
|
+
* via `ProjectDiagnosticsSnapshot` but need explicit rendering, same pattern
|
|
85
|
+
* as `scanTruncationNotice` above — otherwise a user has no way to learn the
|
|
86
|
+
* generated-name heuristic silently excluded files/directories short of
|
|
87
|
+
* reading `latency.log`'s `source_walk_skip_summary` line directly.
|
|
88
|
+
*
|
|
89
|
+
* #1107 phase 2 review round 2 (P1, empirically proven): this deliberately
|
|
90
|
+
* keys off `generatedNameOnlySkips`, NOT the raw `generatedFileSkips` total.
|
|
91
|
+
* `generatedFileSkips` counts every file the generated/artifact heuristic
|
|
92
|
+
* skipped, including STRONG evidence (lockfiles, declaration files, minified/
|
|
93
|
+
* bundle/chunk output — expected on nearly every real repo) and
|
|
94
|
+
* content-CONFIRMED WEAK matches (the escape hatch checked and a genuine
|
|
95
|
+
* generated-code header was present). Keying the notice off that total meant
|
|
96
|
+
* a repo with nothing more unusual than a `package-lock.json` and an ambient
|
|
97
|
+
* `.d.ts` showed "2 file(s) excluded" on literally every scan forever — the
|
|
98
|
+
* signal drowned itself on day one. `generatedNameOnlySkips` is the narrower,
|
|
99
|
+
* genuinely at-risk residual: a WEAK name match trusted with NO corroborating
|
|
100
|
+
* evidence check at all (only reachable when a caller opts out of the header
|
|
101
|
+
* probe — source-filter.ts's default project-walk path always enables it).
|
|
102
|
+
* Post-escape-hatch, this should be rare-to-zero on the default path, which
|
|
103
|
+
* is exactly what makes the notice meaningful again when it DOES fire.
|
|
104
|
+
* `generatedDirSkips` stays in the trigger condition unchanged: directory-
|
|
105
|
+
* level pruning has no escape hatch at all (the walk never enumerates a
|
|
106
|
+
* pruned directory's contents to check them), so it is always a genuine
|
|
107
|
+
* "real files may be hiding in here, unverified" signal, not a
|
|
108
|
+
* false-positive-prone one — see `generatedDirSkips`'s doc on
|
|
109
|
+
* `SourceCollectionResult`.
|
|
110
|
+
*
|
|
111
|
+
* Returns `undefined` when neither counter is set (nothing to append).
|
|
112
|
+
*/
|
|
113
|
+
export function generatedSkipNotice(snapshot) {
|
|
114
|
+
const files = snapshot.generatedNameOnlySkips ?? 0;
|
|
115
|
+
const dirs = snapshot.generatedDirSkips ?? 0;
|
|
116
|
+
if (files === 0 && dirs === 0)
|
|
117
|
+
return undefined;
|
|
118
|
+
const parts = [];
|
|
119
|
+
if (files > 0)
|
|
120
|
+
parts.push(`${files} file(s)`);
|
|
121
|
+
if (dirs > 0)
|
|
122
|
+
parts.push(`${dirs} director${dirs === 1 ? "y" : "ies"}`);
|
|
123
|
+
return (`ℹ ${parts.join(" and ")} excluded by generated-name heuristics with no ` +
|
|
124
|
+
"confirming evidence — a real hand-written file/directory whose name " +
|
|
125
|
+
"looks generated (e.g. `gen.ts`, `generated/`) can be excluded too; " +
|
|
126
|
+
"pass includeGenerated: true to pilens_project_scan / lens_diagnostics " +
|
|
127
|
+
"to scan without this filter if you suspect a false skip.");
|
|
128
|
+
}
|
|
69
129
|
/** Process-wide tree-sitter health for host status surfaces. */
|
|
70
130
|
export function treeSitterRuntimeStatus() {
|
|
71
131
|
return getTreeSitterRuntimeStatus();
|
|
@@ -213,7 +273,7 @@ function toSymbolSearchHit(result) {
|
|
|
213
273
|
* cwd, never blocking this call) so a retry shortly after succeeds (#348
|
|
214
274
|
* decision 3).
|
|
215
275
|
*
|
|
216
|
-
* #536 rider: prefers the warm in-memory index (`
|
|
276
|
+
* #536 rider: prefers the warm in-memory index (`acquireWarmWordIndex`,
|
|
217
277
|
* clients/mcp/analyze.ts) over a fresh disk read when one exists for this
|
|
218
278
|
* cwd — a warm `pilens_analyze` call updates that live copy synchronously but
|
|
219
279
|
* persists it to disk on a debounce (default 1500ms), so without this a query
|
|
@@ -239,9 +299,11 @@ function toSymbolSearchHit(result) {
|
|
|
239
299
|
* nothing on this hot path.
|
|
240
300
|
*/
|
|
241
301
|
export async function symbolSearch(query, cwd, limit = 20, options = {}) {
|
|
242
|
-
const
|
|
243
|
-
const
|
|
302
|
+
const warmLease = acquireWarmWordIndex(cwd);
|
|
303
|
+
const snapshot = loadProjectSnapshotWithoutWordIndex(cwd);
|
|
304
|
+
const index = warmLease.index;
|
|
244
305
|
if (!index) {
|
|
306
|
+
warmLease.release();
|
|
245
307
|
const priorStatus = getWordIndexBuildStatus(cwd);
|
|
246
308
|
const status = priorStatus?.state === "refused"
|
|
247
309
|
? priorStatus
|
|
@@ -266,9 +328,16 @@ export async function symbolSearch(query, cwd, limit = 20, options = {}) {
|
|
|
266
328
|
}
|
|
267
329
|
// Boost well-connected files using the snapshot's reverse-dependency
|
|
268
330
|
// (importedBy) counts; snapshot keys are normalized, index keys are raw.
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
331
|
+
let centrality;
|
|
332
|
+
let results;
|
|
333
|
+
try {
|
|
334
|
+
centrality = centralityFromReverseDeps(index, snapshot?.reverseDeps, (file) => normalizeMapKey(path.resolve(file)));
|
|
335
|
+
const fileFilter = buildSymbolSearchFileFilter(cwd, options);
|
|
336
|
+
results = searchWordIndex(index, query, { limit, centrality, fileFilter });
|
|
337
|
+
}
|
|
338
|
+
finally {
|
|
339
|
+
warmLease.release();
|
|
340
|
+
}
|
|
272
341
|
const hits = results.map(toSymbolSearchHit);
|
|
273
342
|
const { getCachedReviewGraph } = await import("./review-graph/builder.js");
|
|
274
343
|
const graph = getCachedReviewGraph(cwd);
|
|
@@ -1,12 +1,17 @@
|
|
|
1
|
+
import { logExtension } from "./extension-log.js";
|
|
2
|
+
import { logBusEvent } from "./bus-events-logger.js";
|
|
3
|
+
import { normalizeFilePath } from "./path-utils.js";
|
|
4
|
+
import { createLiveBusEmitter, recordStaleBusFailure, resolveLiveBusEmitter, } from "./live-bus-emitter.js";
|
|
1
5
|
export const LENS_EVENT_VERSION = 1;
|
|
2
6
|
export const LENS_EVENT_NAMES = {
|
|
3
7
|
analysisComplete: "pi-lens/analysis-complete",
|
|
4
8
|
findings: "pi-lens/findings",
|
|
5
9
|
turnFindings: "pi-lens/turn-findings",
|
|
6
10
|
};
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
11
|
+
const liveEmitter = createLiveBusEmitter();
|
|
12
|
+
/** Keep deferred deliveries on the live extension activation. */
|
|
13
|
+
export function initLensEventsGetter(getter) {
|
|
14
|
+
liveEmitter.wireGetter(getter);
|
|
10
15
|
}
|
|
11
16
|
function truncateText(value, maxChars) {
|
|
12
17
|
if (value === undefined)
|
|
@@ -26,17 +31,66 @@ function normalizeDiagnostic(diagnostic) {
|
|
|
26
31
|
function normalizeDiagnostics(diagnostics) {
|
|
27
32
|
return diagnostics.map(normalizeDiagnostic);
|
|
28
33
|
}
|
|
34
|
+
// Dropped-emit observability (#1128 review): drops are legitimate (no bus
|
|
35
|
+
// during startup/replacement windows) but must not be invisible. One line per
|
|
36
|
+
// process — enough to notice a permanently-missing bus without spamming.
|
|
37
|
+
let _droppedEmitLogged = false;
|
|
38
|
+
// Emit-failure gating (H1, #1415 review): occurrence-scoped, matching every
|
|
39
|
+
// other producer's `hasLoggedFailure` guard (see clients/bus-publish.ts) and
|
|
40
|
+
// AGENTS.md's "one bus-stale degradation per occurrence" invariant. A success
|
|
41
|
+
// re-arms it, so a later failure records a fresh degradation rather than
|
|
42
|
+
// being silently absorbed by an earlier one.
|
|
43
|
+
let hasLoggedFailure = false;
|
|
44
|
+
/** Test-only: reset module state between test files. */
|
|
45
|
+
export function _resetForTests() {
|
|
46
|
+
liveEmitter.reset();
|
|
47
|
+
_droppedEmitLogged = false;
|
|
48
|
+
hasLoggedFailure = false;
|
|
49
|
+
}
|
|
29
50
|
function emitLensEvent(eventName, payload) {
|
|
30
|
-
const emit = lensEventBus?.emit;
|
|
31
|
-
if (!emit)
|
|
32
|
-
return;
|
|
33
51
|
setImmediate(() => {
|
|
52
|
+
const rawCwd = payload.cwd ?? process.cwd();
|
|
53
|
+
// M1: normalizeFilePath is a sync realpathSync.native on Windows — build
|
|
54
|
+
// the resolveLiveBusEmitter log entry lazily so the ready-path (the
|
|
55
|
+
// common case) never pays it. Only the stale-session branch needs it.
|
|
56
|
+
const resolution = resolveLiveBusEmitter(liveEmitter, () => ({
|
|
57
|
+
event: eventName,
|
|
58
|
+
cwd: normalizeFilePath(rawCwd),
|
|
59
|
+
}));
|
|
60
|
+
if (resolution.outcome === "stale-session")
|
|
61
|
+
return;
|
|
62
|
+
if (resolution.outcome === "unwired") {
|
|
63
|
+
if (!_droppedEmitLogged) {
|
|
64
|
+
_droppedEmitLogged = true;
|
|
65
|
+
logExtension({
|
|
66
|
+
subsystem: "lens-events",
|
|
67
|
+
level: "warn",
|
|
68
|
+
message: `lens event dropped (no live bus): ${eventName} — further drops logged once per process`,
|
|
69
|
+
metadata: { eventName },
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const cwd = normalizeFilePath(rawCwd);
|
|
34
75
|
try {
|
|
35
|
-
emit
|
|
76
|
+
resolution.emit(eventName, payload);
|
|
77
|
+
hasLoggedFailure = false;
|
|
78
|
+
logBusEvent({ event: eventName, outcome: "emitted", cwd });
|
|
36
79
|
}
|
|
37
|
-
catch {
|
|
80
|
+
catch (err) {
|
|
81
|
+
logBusEvent({
|
|
82
|
+
event: eventName,
|
|
83
|
+
outcome: "emit_failed",
|
|
84
|
+
cwd,
|
|
85
|
+
error: String(err),
|
|
86
|
+
ctxSource: resolution.ctxSource,
|
|
87
|
+
});
|
|
88
|
+
if (!hasLoggedFailure) {
|
|
89
|
+
hasLoggedFailure = true;
|
|
90
|
+
recordStaleBusFailure(eventName, err);
|
|
91
|
+
}
|
|
38
92
|
// Inter-extension events are observational. A listener must never break
|
|
39
|
-
// the pi-lens hook path or delay agent progress
|
|
93
|
+
// the pi-lens hook path or delay agent progress.
|
|
40
94
|
}
|
|
41
95
|
});
|
|
42
96
|
}
|