@herbertgao/pi-extensions 2026.8.3 → 2026.8.5
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 +45 -4
- package/examples/pi-footer.json +275 -0
- package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +10 -2
- package/node_modules/@herbertgao/pi-cc-extensions/README.md +10 -2
- 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/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 +5 -8
- 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 +8 -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 +15 -2
- 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/schedule-menu.ts +9 -8
- package/node_modules/@herbertgao/pi-subagents/src/ui/select-item.ts +48 -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 +8 -7
- package/node_modules/@narumitw/pi-btw/package.json +2 -2
- package/node_modules/@narumitw/pi-btw/src/menu.ts +1 -0
- package/node_modules/pi-footer/CHANGELOG.md +145 -0
- package/node_modules/pi-footer/LICENSE +21 -0
- package/node_modules/pi-footer/README.md +354 -0
- package/node_modules/pi-footer/package.json +68 -0
- package/node_modules/pi-footer/src/cache.ts +106 -0
- package/node_modules/pi-footer/src/colors.ts +237 -0
- package/node_modules/pi-footer/src/config.ts +202 -0
- package/node_modules/pi-footer/src/event-widgets.ts +41 -0
- package/node_modules/pi-footer/src/extension-statuses.ts +102 -0
- package/node_modules/pi-footer/src/git.ts +135 -0
- package/node_modules/pi-footer/src/index.ts +268 -0
- package/node_modules/pi-footer/src/metrics.ts +141 -0
- package/node_modules/pi-footer/src/presets.ts +383 -0
- package/node_modules/pi-footer/src/render.ts +114 -0
- package/node_modules/pi-footer/src/separators.ts +52 -0
- package/node_modules/pi-footer/src/types.ts +122 -0
- package/node_modules/pi-footer/src/ui/color-level-confirm.ts +22 -0
- package/node_modules/pi-footer/src/ui/color-options.ts +195 -0
- package/node_modules/pi-footer/src/ui/config-lifecycle.ts +61 -0
- package/node_modules/pi-footer/src/ui/edit-colors.ts +13 -0
- package/node_modules/pi-footer/src/ui/events.ts +35 -0
- package/node_modules/pi-footer/src/ui/extension-status-picker.ts +60 -0
- package/node_modules/pi-footer/src/ui/extension-statuses.ts +73 -0
- package/node_modules/pi-footer/src/ui/fields.ts +252 -0
- package/node_modules/pi-footer/src/ui/global-menu.ts +126 -0
- package/node_modules/pi-footer/src/ui/helpers.ts +44 -0
- package/node_modules/pi-footer/src/ui/layout.ts +17 -0
- package/node_modules/pi-footer/src/ui/line-list.ts +19 -0
- package/node_modules/pi-footer/src/ui/model.ts +64 -0
- package/node_modules/pi-footer/src/ui/navigation.ts +29 -0
- package/node_modules/pi-footer/src/ui/option-edit.ts +93 -0
- package/node_modules/pi-footer/src/ui/overlay-render.ts +103 -0
- package/node_modules/pi-footer/src/ui/screen-context.ts +18 -0
- package/node_modules/pi-footer/src/ui/screen-controller.ts +27 -0
- package/node_modules/pi-footer/src/ui/screen-render.ts +32 -0
- package/node_modules/pi-footer/src/ui/screen-state.ts +20 -0
- package/node_modules/pi-footer/src/ui/screen.ts +243 -0
- package/node_modules/pi-footer/src/ui/screens/add-widget.ts +92 -0
- package/node_modules/pi-footer/src/ui/screens/confirm-exit.ts +52 -0
- package/node_modules/pi-footer/src/ui/screens/controller.ts +12 -0
- package/node_modules/pi-footer/src/ui/screens/edit-colors.ts +68 -0
- package/node_modules/pi-footer/src/ui/screens/edit-widget.ts +115 -0
- package/node_modules/pi-footer/src/ui/screens/extension-status-row.ts +61 -0
- package/node_modules/pi-footer/src/ui/screens/global.ts +75 -0
- package/node_modules/pi-footer/src/ui/screens/line-list.ts +108 -0
- package/node_modules/pi-footer/src/ui/screens/main.ts +99 -0
- package/node_modules/pi-footer/src/ui/screens/terminal.ts +121 -0
- package/node_modules/pi-footer/src/ui/screens/widget-list.ts +154 -0
- package/node_modules/pi-footer/src/ui/terminal-menu.ts +32 -0
- package/node_modules/pi-footer/src/ui/theme.ts +48 -0
- package/node_modules/pi-footer/src/ui/title-bar.ts +100 -0
- package/node_modules/pi-footer/src/ui/widget-actions.ts +76 -0
- package/node_modules/pi-footer/src/ui.ts +66 -0
- package/node_modules/pi-footer/src/widgets/context.ts +28 -0
- package/node_modules/pi-footer/src/widgets/core/active-tools.ts +17 -0
- package/node_modules/pi-footer/src/widgets/core/context-window.ts +24 -0
- package/node_modules/pi-footer/src/widgets/core/cwd-basename.ts +19 -0
- package/node_modules/pi-footer/src/widgets/core/cwd.ts +108 -0
- package/node_modules/pi-footer/src/widgets/core/event.ts +34 -0
- package/node_modules/pi-footer/src/widgets/core/external-status.ts +102 -0
- package/node_modules/pi-footer/src/widgets/core/model-provider.ts +20 -0
- package/node_modules/pi-footer/src/widgets/core/model.ts +35 -0
- package/node_modules/pi-footer/src/widgets/core/provider.ts +17 -0
- package/node_modules/pi-footer/src/widgets/core/session-name.ts +17 -0
- package/node_modules/pi-footer/src/widgets/core/text-verbosity.ts +17 -0
- package/node_modules/pi-footer/src/widgets/core/thinking-level.ts +17 -0
- package/node_modules/pi-footer/src/widgets/git/ahead-behind.ts +17 -0
- package/node_modules/pi-footer/src/widgets/git/branch.ts +81 -0
- package/node_modules/pi-footer/src/widgets/git/clean.ts +19 -0
- package/node_modules/pi-footer/src/widgets/git/deletions.ts +17 -0
- package/node_modules/pi-footer/src/widgets/git/diff.ts +38 -0
- package/node_modules/pi-footer/src/widgets/git/insertions.ts +17 -0
- package/node_modules/pi-footer/src/widgets/git/remote.ts +17 -0
- package/node_modules/pi-footer/src/widgets/git/root.ts +17 -0
- package/node_modules/pi-footer/src/widgets/git/sha.ts +17 -0
- package/node_modules/pi-footer/src/widgets/git/staged.ts +17 -0
- package/node_modules/pi-footer/src/widgets/git/status.ts +19 -0
- package/node_modules/pi-footer/src/widgets/git/unstaged.ts +17 -0
- package/node_modules/pi-footer/src/widgets/git/untracked.ts +17 -0
- package/node_modules/pi-footer/src/widgets/instance.ts +118 -0
- package/node_modules/pi-footer/src/widgets/layout/custom-text.ts +18 -0
- package/node_modules/pi-footer/src/widgets/layout/flex-separator.ts +32 -0
- package/node_modules/pi-footer/src/widgets/layout/separator.ts +57 -0
- package/node_modules/pi-footer/src/widgets/layout/spacer.ts +31 -0
- package/node_modules/pi-footer/src/widgets/options.ts +122 -0
- package/node_modules/pi-footer/src/widgets/project/runtime.ts +361 -0
- package/node_modules/pi-footer/src/widgets/registry.ts +223 -0
- package/node_modules/pi-footer/src/widgets/session/assistant-messages.ts +17 -0
- package/node_modules/pi-footer/src/widgets/session/compactions.ts +17 -0
- package/node_modules/pi-footer/src/widgets/session/elapsed.ts +18 -0
- package/node_modules/pi-footer/src/widgets/session/last-activity.ts +18 -0
- package/node_modules/pi-footer/src/widgets/session/messages.ts +19 -0
- package/node_modules/pi-footer/src/widgets/session/session-id.ts +17 -0
- package/node_modules/pi-footer/src/widgets/session/session-start.ts +18 -0
- package/node_modules/pi-footer/src/widgets/session/tool-results.ts +17 -0
- package/node_modules/pi-footer/src/widgets/session/total-messages.ts +19 -0
- package/node_modules/pi-footer/src/widgets/session/total-time.ts +18 -0
- package/node_modules/pi-footer/src/widgets/session/user-messages.ts +17 -0
- package/node_modules/pi-footer/src/widgets/store.ts +26 -0
- package/node_modules/pi-footer/src/widgets/tokens/cache-hit-rate.ts +55 -0
- package/node_modules/pi-footer/src/widgets/tokens/cache-read.ts +18 -0
- package/node_modules/pi-footer/src/widgets/tokens/cache-write.ts +18 -0
- package/node_modules/pi-footer/src/widgets/tokens/context-bar.ts +108 -0
- package/node_modules/pi-footer/src/widgets/tokens/context-length.ts +26 -0
- package/node_modules/pi-footer/src/widgets/tokens/context-remaining.ts +29 -0
- package/node_modules/pi-footer/src/widgets/tokens/context.ts +29 -0
- package/node_modules/pi-footer/src/widgets/tokens/cost.ts +51 -0
- package/node_modules/pi-footer/src/widgets/tokens/input-speed.ts +25 -0
- package/node_modules/pi-footer/src/widgets/tokens/input-tokens.ts +18 -0
- package/node_modules/pi-footer/src/widgets/tokens/output-speed.ts +25 -0
- package/node_modules/pi-footer/src/widgets/tokens/output-tokens.ts +18 -0
- package/node_modules/pi-footer/src/widgets/tokens/tokens.ts +20 -0
- package/node_modules/pi-footer/src/widgets/tokens/total-speed.ts +25 -0
- package/node_modules/pi-footer/src/widgets/tokens/total-tokens.ts +18 -0
- package/node_modules/pi-footer/src/widgets/types.ts +181 -0
- package/node_modules/pi-footer/src/widgets/utils/colors.ts +11 -0
- package/node_modules/pi-footer/src/widgets/utils/context.ts +112 -0
- package/node_modules/pi-footer/src/widgets/utils/session.ts +19 -0
- package/node_modules/pi-footer/src/widgets/utils/token-format.ts +78 -0
- package/node_modules/pi-lens/CHANGELOG.md +2440 -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/agent-behavior-client.js +21 -4
- 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 +29 -25
- 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-publish.js +10 -3
- 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/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 +14 -0
- package/node_modules/pi-lens/dist/clients/cooperative-budget.js +42 -0
- package/node_modules/pi-lens/dist/clients/dead-code-client.js +2 -1
- 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 +347 -75
- package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +61 -11
- package/node_modules/pi-lens/dist/clients/diagnostics-publish.js +10 -3
- package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +63 -20
- 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 +1085 -681
- 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 +14 -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/lazy-installer.js +3 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +277 -26
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/spawn-outcome.js +22 -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 +10 -3
- package/node_modules/pi-lens/dist/clients/durable-store.js +97 -0
- package/node_modules/pi-lens/dist/clients/event-loop-monitor.js +94 -3
- package/node_modules/pi-lens/dist/clients/extension-log.js +139 -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/format-events-publish.js +16 -3
- 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 +681 -11
- package/node_modules/pi-lens/dist/clients/git-tracked-ignore.js +4 -0
- package/node_modules/pi-lens/dist/clients/go-client.js +2 -1
- package/node_modules/pi-lens/dist/clients/govulncheck-client.js +8 -0
- 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 +390 -99
- package/node_modules/pi-lens/dist/clients/instance-reaper.js +142 -172
- package/node_modules/pi-lens/dist/clients/jscpd-client.js +31 -54
- package/node_modules/pi-lens/dist/clients/knip-client.js +15 -36
- 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 +23 -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 +27 -4
- package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +8 -0
- package/node_modules/pi-lens/dist/clients/lens-map.js +94 -19
- package/node_modules/pi-lens/dist/clients/live-bus-emitter.js +30 -0
- package/node_modules/pi-lens/dist/clients/log-cleanup.js +2 -1
- package/node_modules/pi-lens/dist/clients/lsp/cascade-tier.js +1 -1
- package/node_modules/pi-lens/dist/clients/lsp/client.js +493 -48
- package/node_modules/pi-lens/dist/clients/lsp/config.js +13 -2
- package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +86 -0
- package/node_modules/pi-lens/dist/clients/lsp/edits.js +1012 -121
- package/node_modules/pi-lens/dist/clients/lsp/index.js +1807 -780
- 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 +196 -32
- 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 +123 -32
- package/node_modules/pi-lens/dist/clients/mcp/ipc.js +157 -24
- package/node_modules/pi-lens/dist/clients/mcp/session.js +216 -8
- 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/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 +47 -13
- 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/runner-adapters/call-graph-impact.js +8 -0
- 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/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/runtime-agent-end.js +107 -73
- package/node_modules/pi-lens/dist/clients/runtime-context.js +36 -12
- package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +74 -6
- package/node_modules/pi-lens/dist/clients/runtime-session.js +405 -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 +218 -23
- package/node_modules/pi-lens/dist/clients/runtime-turn.js +237 -64
- package/node_modules/pi-lens/dist/clients/rust-client.js +2 -1
- package/node_modules/pi-lens/dist/clients/safe-spawn.js +777 -62
- package/node_modules/pi-lens/dist/clients/security-scan-client.js +2 -1
- package/node_modules/pi-lens/dist/clients/session-state-store.js +3 -2
- package/node_modules/pi-lens/dist/clients/sg-runner.js +284 -174
- package/node_modules/pi-lens/dist/clients/slow-fs.js +2 -1
- package/node_modules/pi-lens/dist/clients/smells-rollup.js +224 -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 +1 -1
- package/node_modules/pi-lens/dist/clients/test-runner-client.js +38 -8
- package/node_modules/pi-lens/dist/clients/tool-event.js +35 -0
- package/node_modules/pi-lens/dist/clients/tool-policy.js +388 -39
- package/node_modules/pi-lens/dist/clients/tool-render.js +155 -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 +33 -13
- package/node_modules/pi-lens/dist/clients/widget-state.js +300 -43
- package/node_modules/pi-lens/dist/clients/word-index.js +391 -64
- package/node_modules/pi-lens/dist/clients/workspace-topology.js +89 -6
- package/node_modules/pi-lens/dist/index.js +49361 -36888
- package/node_modules/pi-lens/dist/mcp/analyze-cli.js +182 -29
- package/node_modules/pi-lens/dist/mcp/server.js +211 -44
- package/node_modules/pi-lens/dist/tools/ast-grep-search.js +93 -27
- package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +200 -36
- package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +153 -40
- 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/docs/agent-guide.md +2 -2
- 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 +5 -2
- 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 +31 -2
- package/node_modules/pi-lens/docs/globalconfig.md +45 -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 +12 -1
- package/node_modules/pi-lens/docs/tools.md +4 -1
- package/node_modules/pi-lens/docs/usage.md +18 -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-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-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-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-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 +55 -2
- package/node_modules/pi-mcp-adapter/CHANGELOG.md +25 -0
- package/node_modules/pi-mcp-adapter/README.md +34 -3
- package/node_modules/pi-mcp-adapter/agent-plugin-loader.ts +1 -1
- package/node_modules/pi-mcp-adapter/commands.ts +15 -7
- package/node_modules/pi-mcp-adapter/direct-tools.ts +54 -7
- 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/metadata-cache.ts +27 -4
- package/node_modules/pi-mcp-adapter/npx-resolver.ts +81 -26
- package/node_modules/pi-mcp-adapter/package.json +3 -3
- package/node_modules/pi-mcp-adapter/proxy-modes.ts +108 -26
- package/node_modules/pi-mcp-adapter/search-ranking.ts +86 -7
- package/node_modules/pi-mcp-adapter/server-manager.ts +36 -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 +42 -4
- package/node_modules/pi-mcp-adapter/tool-result-renderer.ts +138 -12
- package/node_modules/pi-mcp-adapter/types.ts +93 -27
- package/node_modules/pi-mcp-adapter/ui-server.ts +20 -1
- package/package.json +17 -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
|
@@ -53,6 +53,27 @@ export function logTreeSitterCacheStats(options) {
|
|
|
53
53
|
},
|
|
54
54
|
});
|
|
55
55
|
}
|
|
56
|
+
/**
|
|
57
|
+
* The tree-sitter stack's terminal-safe diagnostic sink (#1333).
|
|
58
|
+
*
|
|
59
|
+
* pi owns the terminal, so nothing under `clients/` may `console.error`. The
|
|
60
|
+
* tree-sitter subsystem already owns `tree-sitter.log`, so its diagnostics stay
|
|
61
|
+
* there rather than moving to the generic `extension.log` — one log per
|
|
62
|
+
* subsystem, per the AGENTS.md logger invariant.
|
|
63
|
+
*
|
|
64
|
+
* `filePath` is optional because several of these fire process-wide (WASM
|
|
65
|
+
* abort, grammar fetch, rule compile) with no file in hand.
|
|
66
|
+
*/
|
|
67
|
+
export function logTreeSitterDiagnostic(entry) {
|
|
68
|
+
logTreeSitter({
|
|
69
|
+
phase: "diagnostic",
|
|
70
|
+
filePath: entry.filePath ?? "<tree-sitter>",
|
|
71
|
+
...(entry.languageId ? { languageId: entry.languageId } : {}),
|
|
72
|
+
status: entry.level ?? "error",
|
|
73
|
+
reason: entry.message,
|
|
74
|
+
metadata: { subsystem: entry.subsystem, ...(entry.metadata ?? {}) },
|
|
75
|
+
});
|
|
76
|
+
}
|
|
56
77
|
export function getTreeSitterLogPath() {
|
|
57
78
|
return TREE_SITTER_LOG_FILE;
|
|
58
79
|
}
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* Loads tree-sitter queries from YAML files in rules/tree-sitter-queries/
|
|
5
5
|
* and provides them to the TreeSitterClient.
|
|
6
6
|
*/
|
|
7
|
+
import { logTreeSitterDiagnostic } from "./tree-sitter-logger.js";
|
|
7
8
|
import * as fs from "node:fs";
|
|
8
9
|
import * as path from "node:path";
|
|
9
10
|
import { resolvePackagePath } from "./package-root.js";
|
|
@@ -110,7 +111,12 @@ export class TreeSitterQueryLoader {
|
|
|
110
111
|
/** Debug logging helper */
|
|
111
112
|
dbg(msg) {
|
|
112
113
|
if (this.verbose) {
|
|
113
|
-
|
|
114
|
+
// #1333: verbose gate preserved, sink moved to tree-sitter.log.
|
|
115
|
+
logTreeSitterDiagnostic({
|
|
116
|
+
subsystem: "query-loader",
|
|
117
|
+
level: "debug",
|
|
118
|
+
message: msg,
|
|
119
|
+
});
|
|
114
120
|
}
|
|
115
121
|
}
|
|
116
122
|
/**
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
* consumer skips further tree-sitter work (previously only the runner tracked this,
|
|
14
14
|
* while the other subsystems kept calling the dead runtime).
|
|
15
15
|
*/
|
|
16
|
+
import { notifyUserDegradation } from "./user-notify.js";
|
|
16
17
|
import * as path from "node:path";
|
|
17
18
|
import { TreeSitterClient, } from "./tree-sitter-client.js";
|
|
18
19
|
import { logTreeSitter } from "./tree-sitter-logger.js";
|
|
@@ -48,8 +49,12 @@ export function markTreeSitterWasmAborted() {
|
|
|
48
49
|
_wasmAborted = true;
|
|
49
50
|
_wasmAbortedAt = new Date().toISOString();
|
|
50
51
|
_shared = null;
|
|
51
|
-
|
|
52
|
-
|
|
52
|
+
// HUMAN-audience: structural analysis is dead for the rest of the process
|
|
53
|
+
// and only a restart recovers it. Reaches the user through the HOST's
|
|
54
|
+
// render path (#1333); the machine-readable record is the logTreeSitter
|
|
55
|
+
// `runtime_abort` entry below.
|
|
56
|
+
notifyUserDegradation("pi-lens: tree-sitter WASM runtime aborted; structural analysis is disabled " +
|
|
57
|
+
"for this process. Restart the pi-lens extension/MCP server to recover.", "error");
|
|
53
58
|
logTreeSitter({
|
|
54
59
|
phase: "runtime_abort",
|
|
55
60
|
filePath: process.cwd(),
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Symbol extraction via tree-sitter queries
|
|
3
3
|
* Extracts definitions and references from source files
|
|
4
4
|
*/
|
|
5
|
+
import { logTreeSitterDiagnostic } from "./tree-sitter-logger.js";
|
|
5
6
|
import * as path from "node:path";
|
|
6
7
|
import { loadWebTreeSitter } from "./deps/web-tree-sitter.js";
|
|
7
8
|
// Tree-sitter query patterns for symbol extraction
|
|
@@ -505,6 +506,10 @@ SYMBOL_QUERIES.javascript = {
|
|
|
505
506
|
constructor: (identifier) @newIdent) @newRef
|
|
506
507
|
`,
|
|
507
508
|
};
|
|
509
|
+
/** Language keys with symbol queries; used by fixture drift guards. */
|
|
510
|
+
export function getSymbolQueryLanguages() {
|
|
511
|
+
return Object.keys(SYMBOL_QUERIES);
|
|
512
|
+
}
|
|
508
513
|
// Per-language import-source extraction (#249). Optional and independent of
|
|
509
514
|
// SYMBOL_QUERIES: a language without an entry simply yields no imports (its
|
|
510
515
|
// symbols still extract). Each query captures the import source text as
|
|
@@ -653,7 +658,11 @@ export class TreeSitterSymbolExtractor {
|
|
|
653
658
|
}
|
|
654
659
|
catch (err) {
|
|
655
660
|
this.client.reportWasmAbort(err);
|
|
656
|
-
|
|
661
|
+
logTreeSitterDiagnostic({
|
|
662
|
+
subsystem: "symbol-extractor",
|
|
663
|
+
languageId: this.languageId,
|
|
664
|
+
message: `Failed to init ${this.languageId}: ${err instanceof Error ? err.message : String(err)}`,
|
|
665
|
+
});
|
|
657
666
|
return false;
|
|
658
667
|
}
|
|
659
668
|
}
|
|
@@ -665,7 +674,12 @@ export class TreeSitterSymbolExtractor {
|
|
|
665
674
|
catch (err) {
|
|
666
675
|
if (this.client.reportWasmAbort(err))
|
|
667
676
|
throw err;
|
|
668
|
-
|
|
677
|
+
logTreeSitterDiagnostic({
|
|
678
|
+
subsystem: "symbol-extractor",
|
|
679
|
+
languageId: this.languageId,
|
|
680
|
+
message: `${this.languageId} ${label} query failed: ${err.message}`,
|
|
681
|
+
metadata: { query: label },
|
|
682
|
+
});
|
|
669
683
|
return null;
|
|
670
684
|
}
|
|
671
685
|
}
|
|
@@ -704,7 +718,16 @@ export class TreeSitterSymbolExtractor {
|
|
|
704
718
|
imports.push(ref);
|
|
705
719
|
}
|
|
706
720
|
}
|
|
707
|
-
return {
|
|
721
|
+
return {
|
|
722
|
+
symbols,
|
|
723
|
+
refs,
|
|
724
|
+
imports,
|
|
725
|
+
coverage: {
|
|
726
|
+
definitions: this.defQuery ? "complete" : "unavailable",
|
|
727
|
+
references: this.refQuery ? "complete" : "unavailable",
|
|
728
|
+
imports: this.importQuery ? "complete" : "unavailable",
|
|
729
|
+
},
|
|
730
|
+
};
|
|
708
731
|
}
|
|
709
732
|
queryMatches(query, rootNode) {
|
|
710
733
|
try {
|
|
@@ -1001,26 +1024,40 @@ export class TreeSitterSymbolExtractor {
|
|
|
1001
1024
|
parseRefMatch(match, filePath) {
|
|
1002
1025
|
let name;
|
|
1003
1026
|
let refNode;
|
|
1027
|
+
let referenceKind = "unknown";
|
|
1004
1028
|
for (const capture of match.captures) {
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1029
|
+
const captureName = String(capture.name);
|
|
1030
|
+
if (captureName.endsWith("Ident") ||
|
|
1031
|
+
captureName.endsWith("Method") ||
|
|
1032
|
+
captureName.endsWith("Field")) {
|
|
1008
1033
|
name = capture.node.text;
|
|
1009
1034
|
// biome-ignore lint/suspicious/noExplicitAny: Node type
|
|
1010
1035
|
refNode = capture.node;
|
|
1036
|
+
if (captureName.startsWith("type"))
|
|
1037
|
+
referenceKind = "type";
|
|
1038
|
+
else if (captureName.startsWith("call") || captureName.startsWith("new")) {
|
|
1039
|
+
referenceKind = "call";
|
|
1040
|
+
}
|
|
1011
1041
|
}
|
|
1012
|
-
if (
|
|
1042
|
+
if (captureName.endsWith("Ref") && !refNode) {
|
|
1013
1043
|
// biome-ignore lint/suspicious/noExplicitAny: Node type
|
|
1014
1044
|
refNode = capture.node;
|
|
1045
|
+
if (captureName.startsWith("type"))
|
|
1046
|
+
referenceKind = "type";
|
|
1047
|
+
else if (captureName.startsWith("call") || captureName.startsWith("new")) {
|
|
1048
|
+
referenceKind = "call";
|
|
1049
|
+
}
|
|
1015
1050
|
}
|
|
1016
1051
|
}
|
|
1017
1052
|
if (!name || !refNode)
|
|
1018
1053
|
return null;
|
|
1019
1054
|
return {
|
|
1020
1055
|
symbolId: `${filePath}:${name}`, // Will be resolved later
|
|
1056
|
+
symbolName: name,
|
|
1021
1057
|
filePath,
|
|
1022
1058
|
line: refNode.startPosition.row + 1,
|
|
1023
1059
|
column: refNode.startPosition.column + 1,
|
|
1060
|
+
referenceKind,
|
|
1024
1061
|
};
|
|
1025
1062
|
}
|
|
1026
1063
|
// biome-ignore lint/suspicious/noExplicitAny: Node type
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The HUMAN channel for degradations discovered deep in `clients/` (#1333).
|
|
3
|
+
*
|
|
4
|
+
* Most of what the migrated `console.*` sites emitted is LOG-audience and
|
|
5
|
+
* belongs in an ndjson sink (`clients/extension-log.ts`). A small set is
|
|
6
|
+
* genuinely user-facing — "the config file you wrote is being ignored", "this
|
|
7
|
+
* language's grammar could not be fetched, so its structural features are
|
|
8
|
+
* degraded", "the WASM runtime aborted; restart to recover". Those must reach
|
|
9
|
+
* the human through the HOST's own render path, never a raw terminal write
|
|
10
|
+
* (pi owns the terminal — see the module doc in `extension-log.ts`).
|
|
11
|
+
*
|
|
12
|
+
* `index.ts` wires a getter at extension init; modules deep in the tree call
|
|
13
|
+
* `notifyUserDegradation` without knowing anything about `ctx`. Per the
|
|
14
|
+
* #338/#798 detached-callback rule the notifier is resolved through a GETTER
|
|
15
|
+
* at delivery time — never captured once, because a session replacement
|
|
16
|
+
* invalidates the previously captured `ctx.ui`.
|
|
17
|
+
*
|
|
18
|
+
* Fail-soft by construction: with no host wired (MCP server, CLI, tests) this
|
|
19
|
+
* is a no-op and the ndjson sink remains the sole destination — the message is
|
|
20
|
+
* never lost, only un-rendered.
|
|
21
|
+
*/
|
|
22
|
+
let notifierGetter;
|
|
23
|
+
/** Called once from the extension entry with a getter over the live `ctx.ui.notify`. */
|
|
24
|
+
export function wireUserNotifier(portsOrGetter) {
|
|
25
|
+
notifierGetter =
|
|
26
|
+
typeof portsOrGetter === "function"
|
|
27
|
+
? portsOrGetter
|
|
28
|
+
: () => portsOrGetter.notify.user;
|
|
29
|
+
}
|
|
30
|
+
/** Test/teardown-only: drop the wired host. */
|
|
31
|
+
export function resetUserNotifier() {
|
|
32
|
+
notifierGetter = undefined;
|
|
33
|
+
}
|
|
34
|
+
/** True when a host render path is available (for callers that want to branch). */
|
|
35
|
+
export function hasUserNotifier() {
|
|
36
|
+
return notifierGetter !== undefined;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Best-effort delivery of a user-facing degradation. Never throws — a stale
|
|
40
|
+
* `ctx` after a session replacement must degrade to a no-op, not break the
|
|
41
|
+
* diagnostic path that called it.
|
|
42
|
+
*/
|
|
43
|
+
export function notifyUserDegradation(message, level = "warning") {
|
|
44
|
+
try {
|
|
45
|
+
const notify = notifierGetter?.();
|
|
46
|
+
notify?.(message, level);
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
// The ndjson sink already holds this message; a dead host is not an error.
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vanished-instance markers (#1123 item 2, first slice — instance health).
|
|
3
|
+
*
|
|
4
|
+
* `deregisterInstance()` (clients/instance-registry.ts) SYNCHRONOUSLY removes
|
|
5
|
+
* a process's own entry from `instances.json` on a clean `session_shutdown`.
|
|
6
|
+
* That means the entry's mere PRESENCE in the registry, combined with a
|
|
7
|
+
* pid-confirmed-dead owner, is already proof the process never reached that
|
|
8
|
+
* shutdown path — no separate "clean shutdown" flag is needed on
|
|
9
|
+
* `InstanceEntry` (the registry already carries `heartbeatAt`/`rssBytes`,
|
|
10
|
+
* which is exactly the "lastSeen"/"rss" pair this marker needs; both are
|
|
11
|
+
* used AS-IS, per the instruction to add fields only if missing).
|
|
12
|
+
*
|
|
13
|
+
* `sweepOrphans()` (clients/instance-reaper.ts) already prunes these exact
|
|
14
|
+
* dead-pid entries out of the registry as part of #472's orphan-LSP reap —
|
|
15
|
+
* so this marker's read MUST happen against a snapshot taken before (or
|
|
16
|
+
* independently of) that prune, or the vanished set will already be empty by
|
|
17
|
+
* the time this runs. `logVanishedInstances` therefore takes the registry
|
|
18
|
+
* snapshot as an argument rather than reading it itself, so the caller
|
|
19
|
+
* controls ordering (see index.ts's session_start wiring, which reads once
|
|
20
|
+
* and passes the same snapshot to both this marker and `sweepOrphans`).
|
|
21
|
+
*/
|
|
22
|
+
import { logSessionStart } from "./sessionstart-logger.js";
|
|
23
|
+
import { realIsPidAlive } from "./instance-reaper.js";
|
|
24
|
+
/**
|
|
25
|
+
* PURE: registry entries whose owning pid is confirmed dead. Every such entry
|
|
26
|
+
* is, by construction (see module docstring), one that exited without
|
|
27
|
+
* reaching `deregisterInstance()`. Uses the SAME conservative liveness
|
|
28
|
+
* contract as the reaper (`isPidAlive`, defaulting to `realIsPidAlive`):
|
|
29
|
+
* ESRCH-only-means-dead, any ambiguous signal (EPERM, unknown) stays "alive"
|
|
30
|
+
* — never flag a live-but-unverifiable instance as vanished.
|
|
31
|
+
*/
|
|
32
|
+
export function detectVanishedInstances(registry, isPidAlive) {
|
|
33
|
+
return registry
|
|
34
|
+
.filter((entry) => !isPidAlive(entry.pid))
|
|
35
|
+
.map((entry) => ({
|
|
36
|
+
pid: entry.pid,
|
|
37
|
+
lastSeenAt: entry.heartbeatAt,
|
|
38
|
+
rssBytes: entry.rssBytes ?? 0,
|
|
39
|
+
}));
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Log one `sessionstart.log` line per vanished instance found in `registry`.
|
|
43
|
+
* Best-effort (never throws into `session_start`) and read-only — this
|
|
44
|
+
* function never mutates or prunes the registry; that stays the reaper's job.
|
|
45
|
+
*/
|
|
46
|
+
export function logVanishedInstances(registry, isPidAlive = realIsPidAlive) {
|
|
47
|
+
try {
|
|
48
|
+
const vanished = detectVanishedInstances(registry, isPidAlive);
|
|
49
|
+
for (const instance of vanished) {
|
|
50
|
+
const rssMb = Math.round(instance.rssBytes / (1024 * 1024));
|
|
51
|
+
logSessionStart(`previous instance pid ${instance.pid} last seen ${instance.lastSeenAt} (RSS ${rssMb}MB) exited without shutdown`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
// best-effort observability — never fail session_start over this
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -4,8 +4,8 @@ import * as path from "node:path";
|
|
|
4
4
|
import { readInstanceRegistry, } from "./instance-registry.js";
|
|
5
5
|
import { realIsPidAlive, STALE_HEARTBEAT_MS, } from "./instance-reaper.js";
|
|
6
6
|
import { logLatency } from "./latency-logger.js";
|
|
7
|
-
import {
|
|
8
|
-
import { contentHash, diagnosticsIpcPathForCwd, requestWarmCodeActions, requestWarmDiagnostics, WARM_CODE_ACTION_LOOKUP_LIMIT, WARM_DIAGNOSTICS_SCHEMA_VERSION, } from "./mcp/ipc.js";
|
|
7
|
+
import { loadLspService } from "./lsp-lazy.js";
|
|
8
|
+
import { contentHash, createWarmIpcLineReader, diagnosticsIpcPathForCwd, requestWarmCodeActions, requestWarmDiagnostics, WARM_CODE_ACTION_LOOKUP_LIMIT, WARM_DIAGNOSTICS_SCHEMA_VERSION, } from "./mcp/ipc.js";
|
|
9
9
|
import { normalizeFilePath } from "./path-utils.js";
|
|
10
10
|
const state = { local: true, servedDiagnosticHashes: new Map() };
|
|
11
11
|
function record(event, cwd, reason, pid, source) {
|
|
@@ -41,7 +41,7 @@ async function serveRequest(req) {
|
|
|
41
41
|
if (Date.now() > req.deadlineAt) {
|
|
42
42
|
throw new Error("deadline exceeded");
|
|
43
43
|
}
|
|
44
|
-
return getLSPService().codeAction(req.file, range.start.line, range.start.character, range.end.line, range.end.character);
|
|
44
|
+
return (await loadLspService()).getLSPService().codeAction(req.file, range.start.line, range.start.character, range.end.line, range.end.character);
|
|
45
45
|
}));
|
|
46
46
|
const servedAt = Date.now();
|
|
47
47
|
if (servedAt > req.deadlineAt)
|
|
@@ -67,7 +67,7 @@ async function serveRequest(req) {
|
|
|
67
67
|
if (Date.now() > req.deadlineAt || contentHash(req.content) !== req.contentHash) {
|
|
68
68
|
return { error: "stale request" };
|
|
69
69
|
}
|
|
70
|
-
const touched = await getLSPService().touchFile(req.file, req.content, {
|
|
70
|
+
const touched = await (await loadLspService()).getLSPService().touchFile(req.file, req.content, {
|
|
71
71
|
diagnostics: "document",
|
|
72
72
|
collectDiagnostics: true,
|
|
73
73
|
clientScope: "with-auxiliary",
|
|
@@ -83,11 +83,23 @@ async function serveRequest(req) {
|
|
|
83
83
|
result: {
|
|
84
84
|
route: "diagnostics",
|
|
85
85
|
version: WARM_DIAGNOSTICS_SCHEMA_VERSION,
|
|
86
|
-
|
|
86
|
+
// #1179: `touchFile` now returns the `{ diags, inconclusive, binding }`
|
|
87
|
+
// wrapper — take the array off `.diags`. This is the canonical shape-5
|
|
88
|
+
// serialization boundary: the diagnostics array crosses the IPC socket
|
|
89
|
+
// and `inconclusive` is re-surfaced below as an EXPLICIT enumerable DTO
|
|
90
|
+
// field (no side-channel survives `JSON.stringify`).
|
|
91
|
+
diagnostics: touched?.diags ?? [],
|
|
87
92
|
contentHash: req.contentHash,
|
|
88
93
|
servedAt,
|
|
89
94
|
fresh: servedAt <= req.deadlineAt && touched !== undefined,
|
|
90
95
|
inconclusive: touched?.inconclusive === true,
|
|
96
|
+
// #1253: carry the touch's own confirmation verdict across the socket
|
|
97
|
+
// as an explicit enumerable field (same doctrine as `inconclusive`) —
|
|
98
|
+
// without it, an incumbent-served empty result from a silent-on-clean
|
|
99
|
+
// server is indistinguishable from "never answered" on the far side.
|
|
100
|
+
...(touched?.confirmation === "confirmed"
|
|
101
|
+
? { confirmation: "confirmed" }
|
|
102
|
+
: {}),
|
|
91
103
|
},
|
|
92
104
|
};
|
|
93
105
|
}
|
|
@@ -104,22 +116,22 @@ function startServer(cwd) {
|
|
|
104
116
|
}
|
|
105
117
|
const server = net.createServer((socket) => {
|
|
106
118
|
socket.setEncoding("utf8");
|
|
107
|
-
|
|
108
|
-
socket
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
119
|
+
// One-shot per connection (#1219 family): the same defect shape as the
|
|
120
|
+
// MCP warm socket — clients write exactly one request and read one
|
|
121
|
+
// reply, so a handler that kept re-reading the same buffered line
|
|
122
|
+
// re-dispatched the request on stray bytes. The shared reader consumes
|
|
123
|
+
// the line and ignores anything after it.
|
|
124
|
+
socket.on("data", createWarmIpcLineReader((line) => {
|
|
113
125
|
void (async () => {
|
|
114
126
|
try {
|
|
115
|
-
const req = JSON.parse(
|
|
127
|
+
const req = JSON.parse(line);
|
|
116
128
|
socket.end(`${JSON.stringify(await serveRequest(req))}\n`);
|
|
117
129
|
}
|
|
118
130
|
catch (error) {
|
|
119
131
|
socket.end(`${JSON.stringify({ error: String(error) })}\n`);
|
|
120
132
|
}
|
|
121
133
|
})();
|
|
122
|
-
});
|
|
134
|
+
}));
|
|
123
135
|
});
|
|
124
136
|
server.on("error", (error) => {
|
|
125
137
|
record("listener-error", cwd, String(error));
|
|
@@ -202,3 +214,11 @@ export function _setWarmAttachForTests(cwd, incumbentPid) {
|
|
|
202
214
|
state.incumbentPid = incumbentPid;
|
|
203
215
|
state.local = false;
|
|
204
216
|
}
|
|
217
|
+
/**
|
|
218
|
+
* The incumbent-side request handler, exposed for tests. The socket wiring
|
|
219
|
+
* around it (`startServer`) can only be exercised by a test that actually
|
|
220
|
+
* binds a unix socket, which is not available in every sandbox — this seam
|
|
221
|
+
* lets the DTO-composition half (notably the #1253 `confirmation` field, whose
|
|
222
|
+
* absence is what a consumer reads as unconfirmed) be pinned directly.
|
|
223
|
+
*/
|
|
224
|
+
export const _serveWarmRequestForTests = serveRequest;
|