@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
|
@@ -265,11 +265,19 @@ function buildProjectIgnoreMatcher(resolvedRoot, patterns) {
|
|
|
265
265
|
const patternsForDir = (dir) => {
|
|
266
266
|
if (dir === resolvedRoot)
|
|
267
267
|
return patterns;
|
|
268
|
-
const
|
|
269
|
-
|
|
268
|
+
const gitignoreSig = gitignoreSignature(dir);
|
|
269
|
+
// #1105: gate on size too. `findPiLensConfigInDir` returns `size` alongside
|
|
270
|
+
// `mtimeMs` (both from one stat), and `gitignoreSignature` reads both for
|
|
271
|
+
// the nested `.gitignore`, so an mtime-preserving, length-changing edit to
|
|
272
|
+
// EITHER nested source can no longer replay stale patterns for this subtree.
|
|
273
|
+
const pilensInfo = findPiLensConfigInDir(dir);
|
|
274
|
+
const pilensMtime = pilensInfo?.mtimeMs ?? -1;
|
|
275
|
+
const pilensSize = pilensInfo?.size ?? -1;
|
|
270
276
|
const cached = nestedCache.get(dir);
|
|
271
|
-
if (cached?.gitignoreMtimeMs ===
|
|
272
|
-
cached?.
|
|
277
|
+
if (cached?.gitignoreMtimeMs === gitignoreSig.mtimeMs &&
|
|
278
|
+
cached?.gitignoreSize === gitignoreSig.size &&
|
|
279
|
+
cached?.pilensMtimeMs === pilensMtime &&
|
|
280
|
+
cached?.pilensSize === pilensSize) {
|
|
273
281
|
return cached.patterns;
|
|
274
282
|
}
|
|
275
283
|
const nestedConfig = loadPiLensConfigInDir(dir);
|
|
@@ -278,15 +286,17 @@ function buildProjectIgnoreMatcher(resolvedRoot, patterns) {
|
|
|
278
286
|
...parseGitignoreContent(nestedConfig.ignore.join("\n"), "pilens"),
|
|
279
287
|
];
|
|
280
288
|
nestedCache.set(dir, {
|
|
281
|
-
gitignoreMtimeMs:
|
|
289
|
+
gitignoreMtimeMs: gitignoreSig.mtimeMs,
|
|
290
|
+
gitignoreSize: gitignoreSig.size,
|
|
282
291
|
pilensMtimeMs: pilensMtime,
|
|
292
|
+
pilensSize: pilensSize,
|
|
283
293
|
patterns: nextPatterns,
|
|
284
294
|
});
|
|
285
295
|
return nextPatterns;
|
|
286
296
|
};
|
|
287
297
|
// Per-matcher path → pattern-verdict memo. The matcher itself is cached by
|
|
288
|
-
// `getProjectIgnoreMatcher` keyed on `.gitignore` mtime, so this
|
|
289
|
-
// lifetime is bounded to a single set of ignore rules — when any
|
|
298
|
+
// `getProjectIgnoreMatcher` keyed on `.gitignore` size+mtime (#1105), so this
|
|
299
|
+
// Map's lifetime is bounded to a single set of ignore rules — when any
|
|
290
300
|
// `.gitignore` changes, the matcher is rebuilt and the memo is dropped
|
|
291
301
|
// with it. Without this memo, every background scan (comment scan, knip,
|
|
292
302
|
// jscpd, call-graph, source-filter, pipeline) recomputes O(ancestorDirs ×
|
|
@@ -402,26 +412,20 @@ export function createProjectIgnoreMatcher(rootDir, extraPatterns = [], globalPa
|
|
|
402
412
|
return buildProjectIgnoreMatcher(resolvedRoot, patterns);
|
|
403
413
|
}
|
|
404
414
|
const projectIgnoreMatcherCache = new Map();
|
|
405
|
-
|
|
406
|
-
* mtime of the global `~/.pi-lens/config.json` (or the PI_LENS_CONFIG_PATH
|
|
407
|
-
* override). Part of the ignore-matcher cache key so editing global ignore
|
|
408
|
-
* patterns takes effect without a restart (#252). -1 when absent.
|
|
409
|
-
*/
|
|
410
|
-
function globalConfigMtimeMs() {
|
|
415
|
+
function fileFreshnessSignature(filePath) {
|
|
411
416
|
try {
|
|
412
|
-
|
|
417
|
+
const stat = fs.statSync(filePath);
|
|
418
|
+
return { mtimeMs: stat.mtimeMs, size: stat.size };
|
|
413
419
|
}
|
|
414
420
|
catch {
|
|
415
|
-
return -1;
|
|
421
|
+
return { mtimeMs: -1, size: -1 };
|
|
416
422
|
}
|
|
417
423
|
}
|
|
418
|
-
function
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
return -1;
|
|
424
|
-
}
|
|
424
|
+
function globalConfigSignature() {
|
|
425
|
+
return fileFreshnessSignature(getPiLensGlobalConfigPath());
|
|
426
|
+
}
|
|
427
|
+
function gitignoreSignature(rootDir) {
|
|
428
|
+
return fileFreshnessSignature(path.join(rootDir, ".gitignore"));
|
|
425
429
|
}
|
|
426
430
|
/**
|
|
427
431
|
* The project config file found by the same upward walk as the loader. Cache
|
|
@@ -432,32 +436,39 @@ function gitignoreMtimeMs(rootDir) {
|
|
|
432
436
|
function lensConfigInfo(rootDir) {
|
|
433
437
|
const info = findPiLensProjectConfig(rootDir);
|
|
434
438
|
return info
|
|
435
|
-
? { info, path: info.path, mtimeMs: info.mtimeMs }
|
|
436
|
-
: { info, path: undefined, mtimeMs: -1 };
|
|
439
|
+
? { info, path: info.path, mtimeMs: info.mtimeMs, size: info.size }
|
|
440
|
+
: { info, path: undefined, mtimeMs: -1, size: -1 };
|
|
437
441
|
}
|
|
438
442
|
export function getProjectIgnoreMatcher(rootDir) {
|
|
439
443
|
const resolvedRoot = resolveGitIgnoreRoot(rootDir);
|
|
440
|
-
const
|
|
444
|
+
const gitignoreSig = gitignoreSignature(resolvedRoot);
|
|
441
445
|
const lensConfig = lensConfigInfo(resolvedRoot);
|
|
442
|
-
const
|
|
446
|
+
const globalSig = globalConfigSignature();
|
|
443
447
|
const cached = projectIgnoreMatcherCache.get(resolvedRoot);
|
|
444
|
-
if (cached?.gitignoreMtimeMs ===
|
|
448
|
+
if (cached?.gitignoreMtimeMs === gitignoreSig.mtimeMs &&
|
|
449
|
+
cached?.gitignoreSize === gitignoreSig.size &&
|
|
445
450
|
cached?.lensConfigPath === lensConfig.path &&
|
|
446
451
|
cached?.lensConfigMtimeMs === lensConfig.mtimeMs &&
|
|
447
|
-
cached?.
|
|
452
|
+
cached?.lensConfigSize === lensConfig.size &&
|
|
453
|
+
cached?.globalConfigMtimeMs === globalSig.mtimeMs &&
|
|
454
|
+
cached?.globalConfigSize === globalSig.size) {
|
|
448
455
|
return cached.matcher;
|
|
449
456
|
}
|
|
450
457
|
// Load both configs fresh on cache miss. On a cache HIT (the common case)
|
|
451
|
-
// none of this runs — the only per-call cost is the
|
|
452
|
-
//
|
|
453
|
-
//
|
|
458
|
+
// none of this runs — the only per-call cost is the size:mtimeMs stats above
|
|
459
|
+
// (size is free from the same stat). The project loader is itself
|
|
460
|
+
// size:mtimeMs-cached; the global loader re-parses, but only here on miss
|
|
461
|
+
// (when some tracked signature changed).
|
|
454
462
|
const projectConfig = loadPiLensProjectConfig(resolvedRoot, lensConfig.info);
|
|
455
463
|
const matcher = createProjectIgnoreMatcher(resolvedRoot, projectConfig.ignore, getGlobalIgnorePatterns());
|
|
456
464
|
projectIgnoreMatcherCache.set(resolvedRoot, {
|
|
457
|
-
gitignoreMtimeMs:
|
|
465
|
+
gitignoreMtimeMs: gitignoreSig.mtimeMs,
|
|
466
|
+
gitignoreSize: gitignoreSig.size,
|
|
458
467
|
lensConfigPath: lensConfig.path,
|
|
459
468
|
lensConfigMtimeMs: lensConfig.mtimeMs,
|
|
460
|
-
|
|
469
|
+
lensConfigSize: lensConfig.size,
|
|
470
|
+
globalConfigMtimeMs: globalSig.mtimeMs,
|
|
471
|
+
globalConfigSize: globalSig.size,
|
|
461
472
|
matcher,
|
|
462
473
|
});
|
|
463
474
|
return matcher;
|
|
@@ -465,10 +476,21 @@ export function getProjectIgnoreMatcher(rootDir) {
|
|
|
465
476
|
export function isPathIgnoredByProject(filePath, rootDir, isDirectory = false) {
|
|
466
477
|
return getProjectIgnoreMatcher(rootDir).isIgnored(filePath, isDirectory);
|
|
467
478
|
}
|
|
479
|
+
const projectIgnoreGlobsCache = new Map();
|
|
468
480
|
export function getProjectIgnoreGlobs(rootDir) {
|
|
469
|
-
|
|
481
|
+
const resolvedRoot = path.resolve(rootDir);
|
|
482
|
+
const signature = gitignoreSignature(resolvedRoot);
|
|
483
|
+
const cached = projectIgnoreGlobsCache.get(resolvedRoot);
|
|
484
|
+
if (cached &&
|
|
485
|
+
cached.mtimeMs === signature.mtimeMs &&
|
|
486
|
+
cached.size === signature.size) {
|
|
487
|
+
return cached.globs;
|
|
488
|
+
}
|
|
489
|
+
const globs = readGitignorePatterns(resolvedRoot)
|
|
470
490
|
.filter((pattern) => !pattern.negated)
|
|
471
491
|
.flatMap((pattern) => expandGitignorePattern(pattern));
|
|
492
|
+
projectIgnoreGlobsCache.set(resolvedRoot, { ...signature, globs });
|
|
493
|
+
return globs;
|
|
472
494
|
}
|
|
473
495
|
/**
|
|
474
496
|
* Read simple directory-name entries from a root .gitignore.
|
|
@@ -18,13 +18,15 @@ export function getWorklogPath(cwd) {
|
|
|
18
18
|
* diagnostics that were already fixed by the tool, `false` for
|
|
19
19
|
* diagnostics that are fixable but require agent action.
|
|
20
20
|
*/
|
|
21
|
-
export function appendToWorklog(cwd, diagnostics, autoFixed) {
|
|
21
|
+
export function appendToWorklog(cwd, diagnostics, autoFixed, identity) {
|
|
22
22
|
if (diagnostics.length === 0)
|
|
23
23
|
return;
|
|
24
24
|
const worklogPath = getWorklogPath(cwd);
|
|
25
25
|
try {
|
|
26
26
|
fs.mkdirSync(path.dirname(worklogPath), { recursive: true });
|
|
27
27
|
const timestamp = new Date().toISOString();
|
|
28
|
+
const model = identity?.model?.trim() || undefined;
|
|
29
|
+
const provider = identity?.provider?.trim() || undefined;
|
|
28
30
|
const lines = diagnostics
|
|
29
31
|
.map((d) => {
|
|
30
32
|
const entry = {
|
|
@@ -38,6 +40,8 @@ export function appendToWorklog(cwd, diagnostics, autoFixed) {
|
|
|
38
40
|
fixable: d.fixable ?? false,
|
|
39
41
|
fixSuggestion: d.fixSuggestion,
|
|
40
42
|
autoFixed,
|
|
43
|
+
model,
|
|
44
|
+
provider,
|
|
41
45
|
};
|
|
42
46
|
return JSON.stringify(entry);
|
|
43
47
|
})
|
|
@@ -59,7 +59,15 @@
|
|
|
59
59
|
* New optional fields may be added under the same `v: 1` for any of the three
|
|
60
60
|
* events; a breaking change to an existing field's meaning must bump that
|
|
61
61
|
* event's `v` independently (each event versions separately since they're
|
|
62
|
-
* unrelated payloads).
|
|
62
|
+
* unrelated payloads). `FormatQueuedPayload.kinds` (S3d, #1432 review) is now
|
|
63
|
+
* an always-present required field at `publishFormatQueued`'s call boundary —
|
|
64
|
+
* both in-repo callers already passed it, so the `?? ["format"]` fallback
|
|
65
|
+
* was fabricating data no caller asked for. This is NOT a `v` bump: `kinds`
|
|
66
|
+
* was already part of the v1 payload shape and every wire-format consumer
|
|
67
|
+
* still reads the same field; a v1 emitter built against an older copy of
|
|
68
|
+
* this module that omits `kinds` at the call site now fails to compile
|
|
69
|
+
* rather than silently emitting a guessed value, and any reader written
|
|
70
|
+
* against v1 that still treats `kinds` as possibly-absent remains correct.
|
|
63
71
|
*
|
|
64
72
|
* Fire-and-forget: publishing must never affect the write path's or
|
|
65
73
|
* `agent_end`'s success or latency. Any failure (bus unavailable, emit
|
|
@@ -70,13 +78,14 @@
|
|
|
70
78
|
import { logBusEvent } from "./bus-events-logger.js";
|
|
71
79
|
import { isBusPublishEnabled } from "./bus-publish.js";
|
|
72
80
|
import { normalizeFilePath } from "./path-utils.js";
|
|
81
|
+
import { createLiveBusEmitter, recordStaleBusFailure, resolveLiveBusEmitter, } from "./live-bus-emitter.js";
|
|
73
82
|
export const BUS_FORMAT_QUEUED_EVENT = "pilens:format:queued";
|
|
74
83
|
export const BUS_FORMAT_QUEUED_VERSION = 1;
|
|
75
84
|
export const BUS_FORMAT_START_EVENT = "pilens:format:start";
|
|
76
85
|
export const BUS_FORMAT_START_VERSION = 1;
|
|
77
86
|
export const BUS_AUTOFIX_START_EVENT = "pilens:autofix:start";
|
|
78
87
|
export const BUS_AUTOFIX_START_VERSION = 1;
|
|
79
|
-
|
|
88
|
+
const liveEmitter = createLiveBusEmitter();
|
|
80
89
|
let hasLoggedQueuedFailure = false;
|
|
81
90
|
let hasLoggedQueuedUnwired = false;
|
|
82
91
|
let hasLoggedQueuedDisabled = false;
|
|
@@ -93,11 +102,14 @@ let hasLoggedAutofixStartDisabled = false;
|
|
|
93
102
|
* identical `pi.events.emit` binding, wired separately per producer.
|
|
94
103
|
*/
|
|
95
104
|
export function wireFormatEventsBusEmitter(emitFn) {
|
|
96
|
-
|
|
105
|
+
liveEmitter.wire(emitFn);
|
|
106
|
+
}
|
|
107
|
+
export function wireFormatEventsBusEmitterGetter(getter) {
|
|
108
|
+
liveEmitter.wireGetter(getter);
|
|
97
109
|
}
|
|
98
110
|
/** Test-only: reset module state between test files. */
|
|
99
111
|
export function _resetFormatEventsPublishForTests() {
|
|
100
|
-
|
|
112
|
+
liveEmitter.reset();
|
|
101
113
|
hasLoggedQueuedFailure = false;
|
|
102
114
|
hasLoggedQueuedUnwired = false;
|
|
103
115
|
hasLoggedQueuedDisabled = false;
|
|
@@ -127,7 +139,13 @@ export function publishFormatQueued(args) {
|
|
|
127
139
|
}
|
|
128
140
|
return;
|
|
129
141
|
}
|
|
130
|
-
|
|
142
|
+
const resolution = resolveLiveBusEmitter(liveEmitter, () => ({
|
|
143
|
+
event: BUS_FORMAT_QUEUED_EVENT,
|
|
144
|
+
cwd: normalizeFilePath(args.cwd),
|
|
145
|
+
}));
|
|
146
|
+
if (resolution.outcome === "stale-session")
|
|
147
|
+
return;
|
|
148
|
+
if (resolution.outcome === "unwired") {
|
|
131
149
|
if (!hasLoggedQueuedUnwired) {
|
|
132
150
|
hasLoggedQueuedUnwired = true;
|
|
133
151
|
logBusEvent({
|
|
@@ -138,6 +156,7 @@ export function publishFormatQueued(args) {
|
|
|
138
156
|
}
|
|
139
157
|
return;
|
|
140
158
|
}
|
|
159
|
+
const busEmit = resolution.emit;
|
|
141
160
|
try {
|
|
142
161
|
const payload = {
|
|
143
162
|
v: BUS_FORMAT_QUEUED_VERSION,
|
|
@@ -145,8 +164,10 @@ export function publishFormatQueued(args) {
|
|
|
145
164
|
filePath: normalizeFilePath(args.filePath),
|
|
146
165
|
cwd: normalizeFilePath(args.cwd),
|
|
147
166
|
tool: args.tool,
|
|
167
|
+
kinds: args.kinds,
|
|
148
168
|
};
|
|
149
169
|
busEmit(BUS_FORMAT_QUEUED_EVENT, payload);
|
|
170
|
+
hasLoggedQueuedFailure = false;
|
|
150
171
|
logBusEvent({
|
|
151
172
|
event: BUS_FORMAT_QUEUED_EVENT,
|
|
152
173
|
outcome: "emitted",
|
|
@@ -160,9 +181,11 @@ export function publishFormatQueued(args) {
|
|
|
160
181
|
outcome: "emit_failed",
|
|
161
182
|
cwd: normalizeFilePath(args.cwd),
|
|
162
183
|
error: String(err),
|
|
184
|
+
ctxSource: resolution.ctxSource,
|
|
163
185
|
});
|
|
164
186
|
if (!hasLoggedQueuedFailure) {
|
|
165
187
|
hasLoggedQueuedFailure = true;
|
|
188
|
+
recordStaleBusFailure(BUS_FORMAT_QUEUED_EVENT, err);
|
|
166
189
|
args.dbg?.(`format-events-publish: pilens:format:queued emit failed (further failures suppressed): ${err}`);
|
|
167
190
|
}
|
|
168
191
|
}
|
|
@@ -189,7 +212,13 @@ export function publishFormatStart(args) {
|
|
|
189
212
|
}
|
|
190
213
|
return;
|
|
191
214
|
}
|
|
192
|
-
|
|
215
|
+
const resolution = resolveLiveBusEmitter(liveEmitter, () => ({
|
|
216
|
+
event: BUS_FORMAT_START_EVENT,
|
|
217
|
+
cwd: normalizeFilePath(args.cwd),
|
|
218
|
+
}));
|
|
219
|
+
if (resolution.outcome === "stale-session")
|
|
220
|
+
return;
|
|
221
|
+
if (resolution.outcome === "unwired") {
|
|
193
222
|
if (!hasLoggedStartUnwired) {
|
|
194
223
|
hasLoggedStartUnwired = true;
|
|
195
224
|
logBusEvent({
|
|
@@ -200,6 +229,7 @@ export function publishFormatStart(args) {
|
|
|
200
229
|
}
|
|
201
230
|
return;
|
|
202
231
|
}
|
|
232
|
+
const busEmit = resolution.emit;
|
|
203
233
|
try {
|
|
204
234
|
const paths = args.paths.map((p) => normalizeFilePath(p));
|
|
205
235
|
const payload = {
|
|
@@ -208,8 +238,10 @@ export function publishFormatStart(args) {
|
|
|
208
238
|
cwd: normalizeFilePath(args.cwd),
|
|
209
239
|
paths,
|
|
210
240
|
fileCount: paths.length,
|
|
241
|
+
kinds: args.kinds ?? ["format"],
|
|
211
242
|
};
|
|
212
243
|
busEmit(BUS_FORMAT_START_EVENT, payload);
|
|
244
|
+
hasLoggedStartFailure = false;
|
|
213
245
|
logBusEvent({
|
|
214
246
|
event: BUS_FORMAT_START_EVENT,
|
|
215
247
|
outcome: "emitted",
|
|
@@ -223,9 +255,11 @@ export function publishFormatStart(args) {
|
|
|
223
255
|
outcome: "emit_failed",
|
|
224
256
|
cwd: normalizeFilePath(args.cwd),
|
|
225
257
|
error: String(err),
|
|
258
|
+
ctxSource: resolution.ctxSource,
|
|
226
259
|
});
|
|
227
260
|
if (!hasLoggedStartFailure) {
|
|
228
261
|
hasLoggedStartFailure = true;
|
|
262
|
+
recordStaleBusFailure(BUS_FORMAT_START_EVENT, err);
|
|
229
263
|
args.dbg?.(`format-events-publish: pilens:format:start emit failed (further failures suppressed): ${err}`);
|
|
230
264
|
}
|
|
231
265
|
}
|
|
@@ -255,7 +289,13 @@ export function publishAutofixStart(args) {
|
|
|
255
289
|
}
|
|
256
290
|
return;
|
|
257
291
|
}
|
|
258
|
-
|
|
292
|
+
const resolution = resolveLiveBusEmitter(liveEmitter, () => ({
|
|
293
|
+
event: BUS_AUTOFIX_START_EVENT,
|
|
294
|
+
cwd: normalizeFilePath(args.cwd),
|
|
295
|
+
}));
|
|
296
|
+
if (resolution.outcome === "stale-session")
|
|
297
|
+
return;
|
|
298
|
+
if (resolution.outcome === "unwired") {
|
|
259
299
|
if (!hasLoggedAutofixStartUnwired) {
|
|
260
300
|
hasLoggedAutofixStartUnwired = true;
|
|
261
301
|
logBusEvent({
|
|
@@ -266,6 +306,7 @@ export function publishAutofixStart(args) {
|
|
|
266
306
|
}
|
|
267
307
|
return;
|
|
268
308
|
}
|
|
309
|
+
const busEmit = resolution.emit;
|
|
269
310
|
try {
|
|
270
311
|
const paths = args.paths.map((p) => normalizeFilePath(p));
|
|
271
312
|
const payload = {
|
|
@@ -277,6 +318,7 @@ export function publishAutofixStart(args) {
|
|
|
277
318
|
eligibleCount: args.eligibleCount,
|
|
278
319
|
};
|
|
279
320
|
busEmit(BUS_AUTOFIX_START_EVENT, payload);
|
|
321
|
+
hasLoggedAutofixStartFailure = false;
|
|
280
322
|
logBusEvent({
|
|
281
323
|
event: BUS_AUTOFIX_START_EVENT,
|
|
282
324
|
outcome: "emitted",
|
|
@@ -290,9 +332,11 @@ export function publishAutofixStart(args) {
|
|
|
290
332
|
outcome: "emit_failed",
|
|
291
333
|
cwd: normalizeFilePath(args.cwd),
|
|
292
334
|
error: String(err),
|
|
335
|
+
ctxSource: resolution.ctxSource,
|
|
293
336
|
});
|
|
294
337
|
if (!hasLoggedAutofixStartFailure) {
|
|
295
338
|
hasLoggedAutofixStartFailure = true;
|
|
339
|
+
recordStaleBusFailure(BUS_AUTOFIX_START_EVENT, err);
|
|
296
340
|
args.dbg?.(`format-events-publish: pilens:autofix:start emit failed (further failures suppressed): ${err}`);
|
|
297
341
|
}
|
|
298
342
|
}
|
|
@@ -10,10 +10,11 @@
|
|
|
10
10
|
* - FileTime integration for safety
|
|
11
11
|
* - Explicit config wins; otherwise smart defaults apply
|
|
12
12
|
*/
|
|
13
|
+
import { logExtension } from "./extension-log.js";
|
|
13
14
|
import * as path from "node:path";
|
|
14
15
|
import { recordFormatter } from "./widget-state.js";
|
|
15
16
|
import { FileTime } from "./file-time.js";
|
|
16
|
-
import {
|
|
17
|
+
import { loadFormatters } from "./formatters-lazy.js";
|
|
17
18
|
// --- Configuration ---
|
|
18
19
|
/** Reserved for future batching; formatting currently runs one selected formatter per file. */
|
|
19
20
|
const DEFAULT_FORMATTER_CONCURRENCY = 1;
|
|
@@ -42,7 +43,12 @@ export class FormatService {
|
|
|
42
43
|
}
|
|
43
44
|
// Check if file was modified externally (safety check)
|
|
44
45
|
if (this.fileTime.hasChanged(absolutePath)) {
|
|
45
|
-
|
|
46
|
+
logExtension({
|
|
47
|
+
subsystem: "format",
|
|
48
|
+
level: "warn",
|
|
49
|
+
message: `File ${absolutePath} modified externally, skipping format`,
|
|
50
|
+
metadata: { filePath: absolutePath },
|
|
51
|
+
});
|
|
46
52
|
return {
|
|
47
53
|
filePath: absolutePath,
|
|
48
54
|
formatters: [],
|
|
@@ -53,7 +59,7 @@ export class FormatService {
|
|
|
53
59
|
// Get formatters for this file
|
|
54
60
|
const formatters = options.formatters
|
|
55
61
|
? await this.getFormattersByName(options.formatters)
|
|
56
|
-
: await getFormattersForFile(absolutePath, cwd);
|
|
62
|
+
: await (await loadFormatters()).getFormattersForFile(absolutePath, cwd);
|
|
57
63
|
if (formatters.length === 0) {
|
|
58
64
|
return {
|
|
59
65
|
filePath: absolutePath,
|
|
@@ -90,13 +96,19 @@ export class FormatService {
|
|
|
90
96
|
async runFormattersWithConcurrency(filePath, formatters, _concurrency = DEFAULT_FORMATTER_CONCURRENCY) {
|
|
91
97
|
const results = [];
|
|
92
98
|
for (const formatter of formatters) {
|
|
99
|
+
// #1097: keep the timer handle so it can be cleared once the race
|
|
100
|
+
// settles. An uncleared, REF'D 30s setTimeout that outlives a fast
|
|
101
|
+
// `formatFile` win would keep a one-shot `pi --print` process alive for
|
|
102
|
+
// up to 30s after completion (same uncleared-race-timeout class as the
|
|
103
|
+
// LSP client-wait leak fixed in clients/lsp/index.ts).
|
|
104
|
+
let formatTimer;
|
|
93
105
|
try {
|
|
94
106
|
const timeoutMs = 30000;
|
|
95
107
|
const timeoutPromise = new Promise((_, reject) => {
|
|
96
|
-
setTimeout(() => reject(new Error(`Formatter ${formatter.name} timed out after ${timeoutMs}ms`)), timeoutMs);
|
|
108
|
+
formatTimer = setTimeout(() => reject(new Error(`Formatter ${formatter.name} timed out after ${timeoutMs}ms`)), timeoutMs);
|
|
97
109
|
});
|
|
98
110
|
const result = await Promise.race([
|
|
99
|
-
formatFile(filePath, formatter),
|
|
111
|
+
loadFormatters().then(({ formatFile }) => formatFile(filePath, formatter)),
|
|
100
112
|
timeoutPromise,
|
|
101
113
|
]);
|
|
102
114
|
results.push(result);
|
|
@@ -108,6 +120,10 @@ export class FormatService {
|
|
|
108
120
|
error: error instanceof Error ? error.message : String(error),
|
|
109
121
|
});
|
|
110
122
|
}
|
|
123
|
+
finally {
|
|
124
|
+
if (formatTimer)
|
|
125
|
+
clearTimeout(formatTimer);
|
|
126
|
+
}
|
|
111
127
|
}
|
|
112
128
|
return results;
|
|
113
129
|
}
|
|
@@ -115,7 +131,7 @@ export class FormatService {
|
|
|
115
131
|
* Get formatters by name (for explicit formatter selection)
|
|
116
132
|
*/
|
|
117
133
|
async getFormattersByName(names) {
|
|
118
|
-
const { listAllFormatters, ...formatters } = await
|
|
134
|
+
const { listAllFormatters, ...formatters } = await loadFormatters();
|
|
119
135
|
const allNames = listAllFormatters();
|
|
120
136
|
return names
|
|
121
137
|
.filter((name) => allNames.includes(name))
|
|
@@ -151,7 +167,7 @@ export class FormatService {
|
|
|
151
167
|
* Clear detection cache
|
|
152
168
|
*/
|
|
153
169
|
clearCache() {
|
|
154
|
-
clearFormatterRuntimeState();
|
|
170
|
+
void loadFormatters().then(({ clearFormatterRuntimeState }) => clearFormatterRuntimeState());
|
|
155
171
|
}
|
|
156
172
|
}
|
|
157
173
|
// --- Singleton Instance ---
|
|
@@ -169,7 +185,7 @@ export function getFormatService(sessionID, enabled = true) {
|
|
|
169
185
|
return globalFormatService;
|
|
170
186
|
}
|
|
171
187
|
export function resetFormatService() {
|
|
172
|
-
clearFormatterRuntimeState();
|
|
188
|
+
void loadFormatters().then(({ clearFormatterRuntimeState }) => clearFormatterRuntimeState());
|
|
173
189
|
globalFormatService = null;
|
|
174
190
|
currentSessionID = null;
|
|
175
191
|
}
|