@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
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* doesn't — session-start warms the dominant-language LSP (so warm `analyze` is
|
|
6
6
|
* LSP-complete), establishes the error-debt baseline + complexity baselines, and
|
|
7
7
|
* kicks off knip/jscpd/type-coverage/dep/secrets scans; turn-end runs
|
|
8
|
-
* knip
|
|
8
|
+
* knip incrementally, dep-circular, tests, cascade, and the
|
|
9
9
|
* actionable/code-quality aggregation.
|
|
10
10
|
*
|
|
11
11
|
* The handlers don't return findings — they emit them through the same
|
|
@@ -16,33 +16,47 @@
|
|
|
16
16
|
* persistent RuntimeCoordinator + CacheManager (so baselines/turn-state survive
|
|
17
17
|
* across calls, like a real session), and the bootstrap client bundle.
|
|
18
18
|
*/
|
|
19
|
+
import * as crypto from "node:crypto";
|
|
19
20
|
import * as fs from "node:fs";
|
|
20
21
|
import * as path from "node:path";
|
|
21
22
|
import { AstGrepClient } from "../ast-grep-client.js";
|
|
22
23
|
import { loadBootstrapClients } from "../bootstrap.js";
|
|
23
|
-
import { CacheManager } from "../cache-manager.js";
|
|
24
|
+
import { CacheManager, MCP_TURN_STATE_OWNER_ID, } from "../cache-manager.js";
|
|
24
25
|
import { resetDispatchBaselines } from "../dispatch/integration.js";
|
|
25
26
|
import { resetFormatService } from "../format-service.js";
|
|
26
27
|
import { getLSPService, resetLSPService } from "../lsp/index.js";
|
|
27
|
-
import { consumeSessionStartGuidance, consumeTestFindings, consumeTurnEndFindings, } from "../runtime-context.js";
|
|
28
|
+
import { acknowledgeTestFindings, acknowledgeTurnEndFindings, consumeSessionStartGuidance, consumeTestFindings, consumeTurnEndFindings, peekTestFindings, peekTurnEndFindings, } from "../runtime-context.js";
|
|
28
29
|
import { RuntimeCoordinator } from "../runtime-coordinator.js";
|
|
29
30
|
import { handleSessionStart } from "../runtime-session.js";
|
|
30
31
|
import { handleTurnEnd } from "../runtime-turn.js";
|
|
31
32
|
import { createMcpHost } from "./host-shim.js";
|
|
32
33
|
let contextPromise;
|
|
34
|
+
let resolvedRuntime;
|
|
33
35
|
/** Lazily build (once) the persistent session context shared across MCP calls. */
|
|
34
36
|
export function getMcpSessionContext() {
|
|
35
|
-
contextPromise ??= (async () =>
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
37
|
+
contextPromise ??= (async () => {
|
|
38
|
+
const context = {
|
|
39
|
+
runtime: new RuntimeCoordinator(),
|
|
40
|
+
cacheManager: new CacheManager(),
|
|
41
|
+
astGrepClient: new AstGrepClient(),
|
|
42
|
+
clients: await loadBootstrapClients(),
|
|
43
|
+
};
|
|
44
|
+
resolvedRuntime = context.runtime;
|
|
45
|
+
return context;
|
|
46
|
+
})();
|
|
41
47
|
return contextPromise;
|
|
42
48
|
}
|
|
49
|
+
/** Synchronous peek at the session runtime, for construction sites that cannot
|
|
50
|
+
* await (e.g. the MCP server's tool wiring). Returns undefined until a session
|
|
51
|
+
* context has actually been built — advisory validation then honestly skips
|
|
52
|
+
* the session-identity check instead of comparing against a phantom session. */
|
|
53
|
+
export function peekMcpSessionRuntime() {
|
|
54
|
+
return resolvedRuntime;
|
|
55
|
+
}
|
|
43
56
|
/** Test hook — drop the cached context so a fresh one is built next call. */
|
|
44
57
|
export function _resetMcpSessionContext() {
|
|
45
58
|
contextPromise = undefined;
|
|
59
|
+
resolvedRuntime = undefined;
|
|
46
60
|
}
|
|
47
61
|
const noop = () => { };
|
|
48
62
|
function joinMessages(consumed) {
|
|
@@ -105,12 +119,82 @@ export async function runSessionStart(cwd) {
|
|
|
105
119
|
aliveLspClients: getLSPService().getAliveClientCount(),
|
|
106
120
|
};
|
|
107
121
|
}
|
|
122
|
+
/**
|
|
123
|
+
* #1274: the delivery map used to be unbounded — every timed-out client and
|
|
124
|
+
* every distinct raw-cwd alias left an entry for the life of the process.
|
|
125
|
+
* Both bounds drop entries WITHOUT committing, which re-arms the findings in
|
|
126
|
+
* the cache: the safe direction, since an un-consumed finding is re-reported on
|
|
127
|
+
* a later Stop while a wrongly-consumed one is gone for good. The TTL is
|
|
128
|
+
* generous next to Claude Code's 60 s hook budget — it exists to bound the map,
|
|
129
|
+
* not to police clients.
|
|
130
|
+
*/
|
|
131
|
+
const TURN_END_DELIVERY_TTL_MS = 10 * 60_000;
|
|
132
|
+
const TURN_END_DELIVERY_MAX = 8;
|
|
133
|
+
const TURN_END_QUEUE_WAIT_MS = 5_000;
|
|
134
|
+
/**
|
|
135
|
+
* A bounded, cancellable serial queue. A turn_end mutates shared runtime and
|
|
136
|
+
* cache state, so concurrent passes are unsafe; a disconnected/hung pass must
|
|
137
|
+
* nevertheless not accumulate an unbounded tail of Stop requests.
|
|
138
|
+
*/
|
|
139
|
+
class TurnEndQueue {
|
|
140
|
+
running = false;
|
|
141
|
+
pending = [];
|
|
142
|
+
enqueue(work, waitMs = TURN_END_QUEUE_WAIT_MS) {
|
|
143
|
+
if (this.pending.length >= 1) {
|
|
144
|
+
return Promise.reject(new Error("turn_end queue is busy"));
|
|
145
|
+
}
|
|
146
|
+
return new Promise((resolve, reject) => {
|
|
147
|
+
const item = {
|
|
148
|
+
work,
|
|
149
|
+
resolve,
|
|
150
|
+
reject,
|
|
151
|
+
timer: setTimeout(() => {
|
|
152
|
+
const index = this.pending.indexOf(item);
|
|
153
|
+
if (index === -1)
|
|
154
|
+
return;
|
|
155
|
+
this.pending.splice(index, 1);
|
|
156
|
+
reject(new Error("turn_end queue wait timed out"));
|
|
157
|
+
}, waitMs),
|
|
158
|
+
};
|
|
159
|
+
item.timer.unref();
|
|
160
|
+
this.pending.push(item);
|
|
161
|
+
this.drain();
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
drain() {
|
|
165
|
+
if (this.running)
|
|
166
|
+
return;
|
|
167
|
+
const item = this.pending.shift();
|
|
168
|
+
if (!item)
|
|
169
|
+
return;
|
|
170
|
+
clearTimeout(item.timer);
|
|
171
|
+
this.running = true;
|
|
172
|
+
void item
|
|
173
|
+
.work()
|
|
174
|
+
.then(item.resolve, item.reject)
|
|
175
|
+
.finally(() => {
|
|
176
|
+
this.running = false;
|
|
177
|
+
this.drain();
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
reset() {
|
|
181
|
+
for (const item of this.pending.splice(0)) {
|
|
182
|
+
clearTimeout(item.timer);
|
|
183
|
+
item.reject(new Error("turn_end queue reset"));
|
|
184
|
+
}
|
|
185
|
+
this.running = false;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
const turnEndQueue = new TurnEndQueue();
|
|
189
|
+
const pendingTurnEndDeliveries = new Map();
|
|
190
|
+
/** In-flight Stop-hook passes, keyed by cwd — see `runTurnEndForIpc` (#1274). */
|
|
191
|
+
const inFlightIpcTurnEnds = new Map();
|
|
108
192
|
/**
|
|
109
193
|
* Run pi-lens's real turn_end over the files edited this "turn". The handler
|
|
110
194
|
* reads edited files from turn-state, so we register the caller-supplied files
|
|
111
195
|
* first (a full-file range, importsChanged=true so dep/knip re-check broadly).
|
|
112
196
|
*/
|
|
113
|
-
|
|
197
|
+
async function runTurnEndNow(cwd, files = [], deferredDelivery = false) {
|
|
114
198
|
const ctx = await getMcpSessionContext();
|
|
115
199
|
const host = createMcpHost(undefined, cwd);
|
|
116
200
|
let registered = 0;
|
|
@@ -123,9 +207,15 @@ export async function runTurnEnd(cwd, files = []) {
|
|
|
123
207
|
catch {
|
|
124
208
|
continue; // unreadable / deleted — skip
|
|
125
209
|
}
|
|
126
|
-
ctx.cacheManager.addModifiedRange(abs, { start: 1, end: lineCount }, true, cwd,
|
|
210
|
+
ctx.cacheManager.addModifiedRange(abs, { start: 1, end: lineCount }, true, cwd, MCP_TURN_STATE_OWNER_ID, "mcp");
|
|
127
211
|
registered++;
|
|
128
212
|
}
|
|
213
|
+
const owner = {
|
|
214
|
+
kind: "mcp",
|
|
215
|
+
id: MCP_TURN_STATE_OWNER_ID,
|
|
216
|
+
pid: process.pid,
|
|
217
|
+
lastSeen: new Date().toISOString(),
|
|
218
|
+
};
|
|
129
219
|
await handleTurnEnd({
|
|
130
220
|
ctxCwd: cwd,
|
|
131
221
|
getFlag: host.getFlag,
|
|
@@ -136,12 +226,143 @@ export async function runTurnEnd(cwd, files = []) {
|
|
|
136
226
|
deadCodeClients: ctx.clients.deadCodeClients,
|
|
137
227
|
depChecker: ctx.clients.depChecker,
|
|
138
228
|
testRunnerClient: ctx.clients.testRunnerClient,
|
|
229
|
+
owner,
|
|
139
230
|
resetLSPService,
|
|
140
231
|
resetFormatService,
|
|
141
232
|
});
|
|
233
|
+
const outcome = deferredDelivery
|
|
234
|
+
? {
|
|
235
|
+
turnEnd: joinMessages(peekTurnEndFindings(ctx.cacheManager, cwd, ctx.runtime, true)),
|
|
236
|
+
tests: joinMessages(peekTestFindings(ctx.cacheManager, cwd, ctx.runtime, true)),
|
|
237
|
+
filesRegistered: registered,
|
|
238
|
+
}
|
|
239
|
+
: {
|
|
240
|
+
turnEnd: joinMessages(consumeTurnEndFindings(ctx.cacheManager, cwd, ctx.runtime)),
|
|
241
|
+
tests: joinMessages(consumeTestFindings(ctx.cacheManager, cwd, ctx.runtime)),
|
|
242
|
+
filesRegistered: registered,
|
|
243
|
+
};
|
|
142
244
|
return {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
245
|
+
outcome,
|
|
246
|
+
commit: () => {
|
|
247
|
+
if (!deferredDelivery)
|
|
248
|
+
return;
|
|
249
|
+
acknowledgeTurnEndFindings(ctx.cacheManager, cwd);
|
|
250
|
+
acknowledgeTestFindings(ctx.cacheManager, cwd);
|
|
251
|
+
},
|
|
146
252
|
};
|
|
147
253
|
}
|
|
254
|
+
/**
|
|
255
|
+
* Run a normal MCP turn_end. Its caller owns the tool response, so the
|
|
256
|
+
* historical consume-on-return behavior remains unchanged.
|
|
257
|
+
*/
|
|
258
|
+
export function runTurnEnd(cwd, files = []) {
|
|
259
|
+
return turnEndQueue.enqueue(async () => (await runTurnEndNow(cwd, files)).outcome);
|
|
260
|
+
}
|
|
261
|
+
/** A result with no findings needs no durable delivery transaction. */
|
|
262
|
+
function hasTurnEndFindings(outcome) {
|
|
263
|
+
return Boolean(outcome.turnEnd || outcome.tests);
|
|
264
|
+
}
|
|
265
|
+
/** Drop expired deliveries, then the oldest ones over the cap. Never commits. */
|
|
266
|
+
function prunePendingTurnEndDeliveries(now = Date.now()) {
|
|
267
|
+
for (const [deliveryId, delivery] of pendingTurnEndDeliveries) {
|
|
268
|
+
if (now - delivery.createdAt >= TURN_END_DELIVERY_TTL_MS) {
|
|
269
|
+
pendingTurnEndDeliveries.delete(deliveryId);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
// Map iteration is insertion-ordered, so the head is the oldest entry.
|
|
273
|
+
while (pendingTurnEndDeliveries.size > TURN_END_DELIVERY_MAX) {
|
|
274
|
+
const oldest = pendingTurnEndDeliveries.keys().next();
|
|
275
|
+
if (oldest.done)
|
|
276
|
+
break;
|
|
277
|
+
pendingTurnEndDeliveries.delete(oldest.value);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
function pendingForCwd(cwd) {
|
|
281
|
+
for (const [deliveryId, delivery] of pendingTurnEndDeliveries) {
|
|
282
|
+
if (delivery.cwd === cwd)
|
|
283
|
+
return [deliveryId, delivery];
|
|
284
|
+
}
|
|
285
|
+
return undefined;
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Run the Stop-hook pass as a durable delivery transaction. The result is
|
|
289
|
+
* acknowledged through a separate one-shot IPC request. Until that request
|
|
290
|
+
* arrives, the findings cache is deliberately left unconsumed; a client
|
|
291
|
+
* timeout, socket close, or server restart therefore leaves the result for a
|
|
292
|
+
* later Stop request instead of losing it between execution and reply.
|
|
293
|
+
*/
|
|
294
|
+
export function runTurnEndForIpc(cwd) {
|
|
295
|
+
// #1274: the Stop-hook request carries no files and no sessionId, so two
|
|
296
|
+
// overlapping ones are byte-identical and a second pass would be pure waste
|
|
297
|
+
// — worse, the queue only holds ONE waiter, so a third Stop is rejected
|
|
298
|
+
// outright. Identical in-flight requests share the one pass and one
|
|
299
|
+
// deliveryId; the ack is idempotent-by-capability, so the loser of the race
|
|
300
|
+
// simply finds the delivery already committed.
|
|
301
|
+
const inFlight = inFlightIpcTurnEnds.get(cwd);
|
|
302
|
+
if (inFlight)
|
|
303
|
+
return inFlight;
|
|
304
|
+
const run = runTurnEndForIpcNow(cwd).finally(() => {
|
|
305
|
+
inFlightIpcTurnEnds.delete(cwd);
|
|
306
|
+
});
|
|
307
|
+
inFlightIpcTurnEnds.set(cwd, run);
|
|
308
|
+
return run;
|
|
309
|
+
}
|
|
310
|
+
function runTurnEndForIpcNow(cwd) {
|
|
311
|
+
return turnEndQueue.enqueue(async () => {
|
|
312
|
+
prunePendingTurnEndDeliveries();
|
|
313
|
+
const pending = pendingForCwd(cwd);
|
|
314
|
+
if (pending) {
|
|
315
|
+
return {
|
|
316
|
+
outcome: pending[1].transaction.outcome,
|
|
317
|
+
deliveryId: pending[0],
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
const ctx = await getMcpSessionContext();
|
|
321
|
+
const cachedOutcome = {
|
|
322
|
+
turnEnd: joinMessages(peekTurnEndFindings(ctx.cacheManager, cwd, ctx.runtime, true)),
|
|
323
|
+
tests: joinMessages(peekTestFindings(ctx.cacheManager, cwd, ctx.runtime, true)),
|
|
324
|
+
filesRegistered: 0,
|
|
325
|
+
};
|
|
326
|
+
const transaction = hasTurnEndFindings(cachedOutcome)
|
|
327
|
+
? {
|
|
328
|
+
outcome: cachedOutcome,
|
|
329
|
+
commit: () => {
|
|
330
|
+
acknowledgeTurnEndFindings(ctx.cacheManager, cwd);
|
|
331
|
+
acknowledgeTestFindings(ctx.cacheManager, cwd);
|
|
332
|
+
},
|
|
333
|
+
}
|
|
334
|
+
: await runTurnEndNow(cwd, [], true);
|
|
335
|
+
if (!hasTurnEndFindings(transaction.outcome)) {
|
|
336
|
+
return { outcome: transaction.outcome };
|
|
337
|
+
}
|
|
338
|
+
const deliveryId = crypto.randomUUID();
|
|
339
|
+
pendingTurnEndDeliveries.set(deliveryId, {
|
|
340
|
+
cwd,
|
|
341
|
+
transaction,
|
|
342
|
+
createdAt: Date.now(),
|
|
343
|
+
});
|
|
344
|
+
prunePendingTurnEndDeliveries();
|
|
345
|
+
return { outcome: transaction.outcome, deliveryId };
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
/** Commit exactly one admitted delivery capability. */
|
|
349
|
+
export function acknowledgeTurnEnd(cwd, deliveryId) {
|
|
350
|
+
prunePendingTurnEndDeliveries();
|
|
351
|
+
const delivery = pendingTurnEndDeliveries.get(deliveryId);
|
|
352
|
+
if (!delivery || delivery.cwd !== cwd)
|
|
353
|
+
return false;
|
|
354
|
+
// #1274: commit BEFORE dropping the capability. Deleting first meant a
|
|
355
|
+
// throwing consume destroyed the only handle to the findings — precisely the
|
|
356
|
+
// loss this two-phase protocol exists to prevent, reintroduced on the error
|
|
357
|
+
// path. Leaving the entry in place on a throw keeps the delivery re-fetchable
|
|
358
|
+
// by a later Stop.
|
|
359
|
+
delivery.transaction.commit();
|
|
360
|
+
pendingTurnEndDeliveries.delete(deliveryId);
|
|
361
|
+
return true;
|
|
362
|
+
}
|
|
363
|
+
/** Test hook — drop pending requests so one failed test cannot wedge the rest. */
|
|
364
|
+
export function _resetTurnEndChain() {
|
|
365
|
+
turnEndQueue.reset();
|
|
366
|
+
pendingTurnEndDeliveries.clear();
|
|
367
|
+
inFlightIpcTurnEnds.clear();
|
|
368
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Periodic memory-attribution sample (#1123 item 2, expanded on top of item 1's
|
|
3
|
+
* loop_block windowing — the #1126 sizing study's "instrumentation the next
|
|
4
|
+
* report should add" list is this module's requirements).
|
|
5
|
+
*
|
|
6
|
+
* The #1126 sizing study diagnosed a 1.37 GB instance from code + serialized
|
|
7
|
+
* artifacts alone, because nothing recorded a per-subsystem trajectory over
|
|
8
|
+
* time — the same detection-without-attribution gap loop_block had before
|
|
9
|
+
* #1122/#1125. This module answers "what is resident right now, broken down
|
|
10
|
+
* by subsystem" as a single ndjson `memory_sample` `latency.log` line, emitted
|
|
11
|
+
* every `MEMORY_SAMPLE_TURN_INTERVAL` turns (cheap enough not to need finer
|
|
12
|
+
* throttling).
|
|
13
|
+
*
|
|
14
|
+
* HARD CONSTRAINT: every field here is an O(1) `Map`/array `.size`/`.length`
|
|
15
|
+
* read, or a `process.memoryUsage()` call — nothing here iterates a large
|
|
16
|
+
* structure's contents, and nothing takes a heap snapshot. `PI_LENS_DEBUG_HEAP`
|
|
17
|
+
* (item 4's memory sibling) is a SEPARATE, explicitly opt-in mechanism, out of
|
|
18
|
+
* scope here.
|
|
19
|
+
*
|
|
20
|
+
* WASM linear-memory byte length gap (documented, not silently dropped): the
|
|
21
|
+
* #1126 spec asked for `Module.wasmMemory.buffer.byteLength` off the
|
|
22
|
+
* web-tree-sitter parser runtime. Inspecting the installed web-tree-sitter
|
|
23
|
+
* 0.25.10 package (see `clients/tree-sitter-client.ts#getRuntimeStats`'s
|
|
24
|
+
* docstring) confirmed that value is not reachable through any public export
|
|
25
|
+
* — only through package-internal reflection or by overriding Emscripten's
|
|
26
|
+
* `wasmMemory` module option with a hand-built `WebAssembly.Memory` (a
|
|
27
|
+
* stability risk for an observability-only feature, given a memory-import
|
|
28
|
+
* mismatch would break structural analysis entirely). `process.memoryUsage()`
|
|
29
|
+
* `arrayBuffers` is used as the process-wide proxy instead — WASM linear
|
|
30
|
+
* memory backs an ArrayBuffer, so it is already included there.
|
|
31
|
+
*/
|
|
32
|
+
import { getSharedTreeSitterClient } from "./tree-sitter-shared.js";
|
|
33
|
+
import { getReviewGraphWorkspaceCacheSnapshot } from "./review-graph/builder.js";
|
|
34
|
+
import { getDispatchCascadeCacheStats } from "./dispatch/integration.js";
|
|
35
|
+
/** Every N turns, emit one `memory_sample` latency.log line (#1123 item 2). */
|
|
36
|
+
export const MEMORY_SAMPLE_TURN_INTERVAL = 10;
|
|
37
|
+
/** True on turn 10, 20, 30, ... — never on turn 0 (nothing meaningful is
|
|
38
|
+
* resident yet at session start). Pure so the cadence is unit-testable
|
|
39
|
+
* without driving a real turn loop. */
|
|
40
|
+
export function shouldEmitMemorySample(turnIndex) {
|
|
41
|
+
return turnIndex > 0 && turnIndex % MEMORY_SAMPLE_TURN_INTERVAL === 0;
|
|
42
|
+
}
|
|
43
|
+
/** PURE: reshape Node's `process.memoryUsage()` into this module's field
|
|
44
|
+
* names — testable without touching the real process. */
|
|
45
|
+
export function toMemoryProcessUsage(mem) {
|
|
46
|
+
return {
|
|
47
|
+
rssBytes: mem.rss,
|
|
48
|
+
heapUsedBytes: mem.heapUsed,
|
|
49
|
+
heapTotalBytes: mem.heapTotal,
|
|
50
|
+
externalBytes: mem.external,
|
|
51
|
+
arrayBuffersBytes: mem.arrayBuffers,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Live O(1)/O(bounded-cache-size) subsystem counters. Impure (reads
|
|
56
|
+
* process-global singletons) but every individual read is a `.size`/`.length`
|
|
57
|
+
* access — see the module docstring's hard constraint.
|
|
58
|
+
*/
|
|
59
|
+
export function collectMemorySampleSubsystems(wordIndex) {
|
|
60
|
+
const reviewGraph = getReviewGraphWorkspaceCacheSnapshot();
|
|
61
|
+
const treeSitterClient = getSharedTreeSitterClient();
|
|
62
|
+
const treeSitter = treeSitterClient
|
|
63
|
+
? (() => {
|
|
64
|
+
const runtimeStats = treeSitterClient.getRuntimeStats();
|
|
65
|
+
const cacheStats = treeSitterClient.getParseCacheStats();
|
|
66
|
+
return {
|
|
67
|
+
...runtimeStats,
|
|
68
|
+
treeCacheSize: cacheStats.size,
|
|
69
|
+
treeCacheMaxSize: cacheStats.maxSize,
|
|
70
|
+
treeCacheTotalBytes: cacheStats.totalBytes,
|
|
71
|
+
};
|
|
72
|
+
})()
|
|
73
|
+
: null;
|
|
74
|
+
const dispatchCaches = getDispatchCascadeCacheStats();
|
|
75
|
+
return {
|
|
76
|
+
reviewGraph,
|
|
77
|
+
wordIndex: wordIndex
|
|
78
|
+
? {
|
|
79
|
+
docs: wordIndex.docLengths.size,
|
|
80
|
+
postings: wordIndex.postings.size,
|
|
81
|
+
forwardEntries: wordIndex.forward?.size ?? 0,
|
|
82
|
+
}
|
|
83
|
+
: null,
|
|
84
|
+
treeSitter,
|
|
85
|
+
dispatchCaches,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
/** Assemble one full sample. `mem` is injectable for tests; defaults to a
|
|
89
|
+
* live `process.memoryUsage()` read. */
|
|
90
|
+
export function buildMemorySample(wordIndex, mem = process.memoryUsage()) {
|
|
91
|
+
return {
|
|
92
|
+
process: toMemoryProcessUsage(mem),
|
|
93
|
+
subsystems: collectMemorySampleSubsystems(wordIndex),
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
const toMb = (bytes) => Math.round(bytes / (1024 * 1024));
|
|
97
|
+
/**
|
|
98
|
+
* PURE: one compact `/lens-health` line reusing the same sample the periodic
|
|
99
|
+
* latency.log emitter builds — RSS + heap/external, plus the two subsystem
|
|
100
|
+
* numbers most useful for spotting an attribution outlier at a glance: the
|
|
101
|
+
* tree-sitter tree-cache byte total (the only subsystem counter here that is
|
|
102
|
+
* ALREADY in bytes, so it's directly comparable to RSS) and the review-graph
|
|
103
|
+
* node/edge counts (the multiple-graph-copies question #1126 called out).
|
|
104
|
+
* Follows #1125's health-line style (a single summary line, no per-subsystem
|
|
105
|
+
* breakdown table — that's what latency.log's `memory_sample` is for).
|
|
106
|
+
*/
|
|
107
|
+
export function formatMemoryHealthLine(sample) {
|
|
108
|
+
const { process: proc, subsystems } = sample;
|
|
109
|
+
const treeCache = subsystems.treeSitter
|
|
110
|
+
? `${toMb(subsystems.treeSitter.treeCacheTotalBytes)}MB (${subsystems.treeSitter.treeCacheSize} trees)`
|
|
111
|
+
: "n/a";
|
|
112
|
+
const graph = `${subsystems.reviewGraph.totalNodes}n/${subsystems.reviewGraph.totalEdges}e (${subsystems.reviewGraph.cacheEntries} cwd)`;
|
|
113
|
+
return (`Memory: RSS ${toMb(proc.rssBytes)}MB · heap ${toMb(proc.heapUsedBytes)}/${toMb(proc.heapTotalBytes)}MB` +
|
|
114
|
+
` · external ${toMb(proc.externalBytes)}MB · tree-sitter cache ${treeCache} · review-graph ${graph}`);
|
|
115
|
+
}
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* These are observational metrics — they inform the human in session summary,
|
|
11
11
|
* they don't gate or interrupt the agent mid-task.
|
|
12
12
|
*/
|
|
13
|
+
import { createSubsystemLogger } from "./extension-log.js";
|
|
13
14
|
import * as fs from "node:fs";
|
|
14
15
|
import * as path from "node:path";
|
|
15
16
|
// --- Client ---
|
|
@@ -18,7 +19,7 @@ export class MetricsClient {
|
|
|
18
19
|
fileBaselines = new Map();
|
|
19
20
|
constructor(verbose = false) {
|
|
20
21
|
this.log = verbose
|
|
21
|
-
? (
|
|
22
|
+
? createSubsystemLogger("metrics")
|
|
22
23
|
: () => { };
|
|
23
24
|
}
|
|
24
25
|
/**
|
|
@@ -10,6 +10,7 @@ import { execSync } from "node:child_process";
|
|
|
10
10
|
import * as fs from "node:fs";
|
|
11
11
|
import * as path from "node:path";
|
|
12
12
|
import { getProjectDataDir } from "./file-utils.js";
|
|
13
|
+
import { writeFileAtomic } from "./atomic-write.js";
|
|
13
14
|
// --- Constants ---
|
|
14
15
|
const HISTORY_FILE = "metrics-history.json";
|
|
15
16
|
const MAX_HISTORY_PER_FILE = 20;
|
|
@@ -82,7 +83,7 @@ export function saveHistory(history) {
|
|
|
82
83
|
}
|
|
83
84
|
history.capturedAt = new Date().toISOString();
|
|
84
85
|
const historyPath = path.join(historyDir, "metrics-history.json");
|
|
85
|
-
|
|
86
|
+
writeFileAtomic(historyPath, JSON.stringify(history, null, 2));
|
|
86
87
|
}
|
|
87
88
|
// In-memory cache to avoid loading/saving on every capture
|
|
88
89
|
let pendingHistory = null;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider derivation for worklog/disposition attribution (#1448).
|
|
3
|
+
*
|
|
4
|
+
* The host reports `provider` and `model` as separate fields on its telemetry
|
|
5
|
+
* events (see `updateRuntimeIdentityFromEvent` in index.ts and the
|
|
6
|
+
* `tool_result` handler in clients/runtime-tool-result.ts) MOST of the time —
|
|
7
|
+
* so the common case needs no parsing at all. This parser exists only for the
|
|
8
|
+
* fallback: a model id supplied without an explicit provider.
|
|
9
|
+
*
|
|
10
|
+
* Derivation rule (conservative — returns "" rather than guess):
|
|
11
|
+
* 1. A single `/` or `:` separator splits the id into `<provider>/<rest>`
|
|
12
|
+
* or `<provider>:<rest>` — e.g. "anthropic/claude-sonnet-4-5",
|
|
13
|
+
* "openai:gpt-5". The left segment is lowercased and returned AS-IS
|
|
14
|
+
* (no allowlist check) since an explicit separator is deliberate host
|
|
15
|
+
* structure, not a guess.
|
|
16
|
+
* 2. No separator: match a known model-id PREFIX against a small table of
|
|
17
|
+
* vendor naming conventions (claude- -> anthropic; gpt-, o1-, o3- ->
|
|
18
|
+
* openai; gemini- -> google; llama- -> meta; mistral-, mixtral- ->
|
|
19
|
+
* mistral; command- -> cohere). First match wins.
|
|
20
|
+
* 3. Anything else (unrecognized prefix, multiple separators, empty
|
|
21
|
+
* string) is ambiguous -> "".
|
|
22
|
+
*/
|
|
23
|
+
const KNOWN_PREFIXES = [
|
|
24
|
+
["claude-", "anthropic"],
|
|
25
|
+
["gpt-", "openai"],
|
|
26
|
+
["o1-", "openai"],
|
|
27
|
+
["o3-", "openai"],
|
|
28
|
+
["gemini-", "google"],
|
|
29
|
+
["llama-", "meta"],
|
|
30
|
+
["mistral-", "mistral"],
|
|
31
|
+
["mixtral-", "mistral"],
|
|
32
|
+
["command-", "cohere"],
|
|
33
|
+
];
|
|
34
|
+
export function deriveProviderFromModelId(modelId) {
|
|
35
|
+
const id = modelId?.trim().toLowerCase();
|
|
36
|
+
if (!id)
|
|
37
|
+
return "";
|
|
38
|
+
const separators = [...id].filter((c) => c === "/" || c === ":").length;
|
|
39
|
+
if (separators === 1) {
|
|
40
|
+
const sep = id.includes("/") ? "/" : ":";
|
|
41
|
+
const [providerPart, ...rest] = id.split(sep);
|
|
42
|
+
if (providerPart && rest.join(sep).length > 0)
|
|
43
|
+
return providerPart;
|
|
44
|
+
return "";
|
|
45
|
+
}
|
|
46
|
+
if (separators > 1)
|
|
47
|
+
return "";
|
|
48
|
+
for (const [prefix, provider] of KNOWN_PREFIXES) {
|
|
49
|
+
if (id.startsWith(prefix))
|
|
50
|
+
return provider;
|
|
51
|
+
}
|
|
52
|
+
return "";
|
|
53
|
+
}
|
|
@@ -15,6 +15,11 @@
|
|
|
15
15
|
* remaining wall-clock budget.
|
|
16
16
|
* - OPT-IN: disabled by default (budget 0) until validated in a real pi session;
|
|
17
17
|
* enable with PI_LENS_MODULE_REPORT_LSP_BUDGET_MS.
|
|
18
|
+
*
|
|
19
|
+
* PARKED BY DECISION (#1090, 2026-08-12): zero live importers by design —
|
|
20
|
+
* efe3d2a5 unwired module_report's LSP path (#256) and re-homed live
|
|
21
|
+
* enrichment to #236 (LSP-confirmed graph edges). Kept for that future
|
|
22
|
+
* implementation; do not re-flag in dead-code sweeps while #236 is open.
|
|
18
23
|
*/
|
|
19
24
|
import { withinRemaining } from "./deadline-utils.js";
|
|
20
25
|
import { uriToPath } from "./path-utils.js";
|