@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
|
@@ -31,6 +31,7 @@ import * as fs from "node:fs";
|
|
|
31
31
|
import * as path from "node:path";
|
|
32
32
|
import { isExcludedDirName } from "./file-utils.js";
|
|
33
33
|
import { isGeneratedArtifactDirectoryName } from "./generated-artifacts.js";
|
|
34
|
+
import { createDeadline, yieldIfOverBudget, } from "./cooperative-budget.js";
|
|
34
35
|
/**
|
|
35
36
|
* Read a directory's entries, returning `[]` for a permission-denied or
|
|
36
37
|
* missing directory instead of throwing. Shared by every walker below — a
|
|
@@ -46,12 +47,46 @@ export function readDirEntriesSafe(dirPath) {
|
|
|
46
47
|
return [];
|
|
47
48
|
}
|
|
48
49
|
}
|
|
50
|
+
/**
|
|
51
|
+
* Async twin of {@link readDirEntriesSafe} (refs #1137) — the identical
|
|
52
|
+
* "unreadable directory yields no entries" contract, but the read itself
|
|
53
|
+
* happens off the event loop via `fs.promises.readdir`.
|
|
54
|
+
*
|
|
55
|
+
* Why this exists: chunked yielding is NOT sufficient to keep the loop free.
|
|
56
|
+
* `walkTreeStackAsync` already `setImmediate`-yielded every N entries, yet each
|
|
57
|
+
* per-directory read was still `readdirSync` — so on a cloud-backed tree
|
|
58
|
+
* (OneDrive, network drive) one stalled directory read blocked the Node loop,
|
|
59
|
+
* and pi's TUI, for the *entire* stall regardless of yield cadence. That is the
|
|
60
|
+
* exact shape #1170 already fixed in `pipeline.ts`'s autofix snapshot walk
|
|
61
|
+
* ("the walk was already async + chunk-yielding, but each synchronous per-dir
|
|
62
|
+
* read still blocked on a cloud stall"); #1170 deferred the SHARED engine, and
|
|
63
|
+
* this is that same fix applied here — so every async walker gets it at once.
|
|
64
|
+
*/
|
|
65
|
+
export async function readDirEntriesSafeAsync(dirPath) {
|
|
66
|
+
try {
|
|
67
|
+
return await fs.promises.readdir(dirPath, { withFileTypes: true });
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return [];
|
|
71
|
+
}
|
|
72
|
+
}
|
|
49
73
|
/**
|
|
50
74
|
* The one shared "should this directory be walked into" decision. Every
|
|
51
75
|
* caller's own loop still owns *when* to call this (inline recursion vs. a
|
|
52
76
|
* stack) and what to do with the answer.
|
|
77
|
+
*
|
|
78
|
+
* `onGeneratedDirSkip` (#1107 phase 2) fires exactly once when — and only
|
|
79
|
+
* when — the `isGeneratedArtifactDirectoryName` branch is the reason this
|
|
80
|
+
* directory is pruned, so a caller can count PRUNED DIRECTORIES (one event
|
|
81
|
+
* per directory, regardless of how many files it contains) without
|
|
82
|
+
* enumerating the directory's contents — doing that would defeat the whole
|
|
83
|
+
* point of pruning it. Optional and unused by every caller except
|
|
84
|
+
* `source-filter.ts`'s `classifyEntry`: the other two `shouldRecurseIntoDir`
|
|
85
|
+
* callers (`language-profile.ts`, `startup-scan.ts`) always pass
|
|
86
|
+
* `skipGeneratedArtifactDirs: false`, so this branch — and therefore the
|
|
87
|
+
* callback — never fires for them.
|
|
53
88
|
*/
|
|
54
|
-
export function shouldRecurseIntoDir(entry, fullPath, policy) {
|
|
89
|
+
export function shouldRecurseIntoDir(entry, fullPath, policy, onGeneratedDirSkip) {
|
|
55
90
|
if (isExcludedDirName(entry.name, policy.extraExcludeDirs ?? [])) {
|
|
56
91
|
return false;
|
|
57
92
|
}
|
|
@@ -59,6 +94,7 @@ export function shouldRecurseIntoDir(entry, fullPath, policy) {
|
|
|
59
94
|
return false;
|
|
60
95
|
if (policy.skipGeneratedArtifactDirs === true &&
|
|
61
96
|
isGeneratedArtifactDirectoryName(entry.name)) {
|
|
97
|
+
onGeneratedDirSkip?.();
|
|
62
98
|
return false;
|
|
63
99
|
}
|
|
64
100
|
if (policy.followSymlinks !== true && entry.isSymbolicLink())
|
|
@@ -83,15 +119,24 @@ function* walkTreeStackSteps(rootDir, visit, shouldStop) {
|
|
|
83
119
|
const dir = stack.pop();
|
|
84
120
|
if (dir === undefined)
|
|
85
121
|
continue;
|
|
122
|
+
// Directory-read REQUEST (#1137): the generator never reads the
|
|
123
|
+
// filesystem itself — it yields the directory path and the driver
|
|
124
|
+
// supplies the entries. That is what lets the sync driver stay
|
|
125
|
+
// `readdirSync` while the async driver reads via `fs.promises.readdir`
|
|
126
|
+
// WITHOUT forking the traversal into two implementations that can
|
|
127
|
+
// drift (the invariant this generator exists to protect).
|
|
128
|
+
const entries = (yield dir) ?? [];
|
|
86
129
|
const subDirs = [];
|
|
87
|
-
for (const entry of
|
|
130
|
+
for (const entry of entries) {
|
|
88
131
|
const fullPath = path.join(dir, entry.name);
|
|
89
132
|
const disposition = visit(entry, fullPath);
|
|
90
133
|
if (disposition === "stop")
|
|
91
134
|
return true;
|
|
92
135
|
if (disposition === "recurse")
|
|
93
136
|
subDirs.push(fullPath);
|
|
94
|
-
yield
|
|
137
|
+
// Per-entry yield point: `undefined` distinguishes it from a
|
|
138
|
+
// directory-read request above.
|
|
139
|
+
yield undefined;
|
|
95
140
|
}
|
|
96
141
|
for (let i = subDirs.length - 1; i >= 0; i--)
|
|
97
142
|
stack.push(subDirs[i]);
|
|
@@ -106,27 +151,38 @@ function* walkTreeStackSteps(rootDir, visit, shouldStop) {
|
|
|
106
151
|
export function walkTreeStackSync(rootDir, visit, opts = {}) {
|
|
107
152
|
const steps = walkTreeStackSteps(rootDir, visit, opts.shouldStop);
|
|
108
153
|
let step = steps.next();
|
|
109
|
-
while (!step.done)
|
|
110
|
-
step = steps.next();
|
|
154
|
+
while (!step.done) {
|
|
155
|
+
step = steps.next(step.value === undefined ? undefined : readDirEntriesSafe(step.value));
|
|
156
|
+
}
|
|
111
157
|
return step.value;
|
|
112
158
|
}
|
|
113
159
|
/**
|
|
114
160
|
* Async, chunked-yield twin of {@link walkTreeStackSync} — the identical
|
|
115
161
|
* {@link walkTreeStackSteps} traversal, plus a `setImmediate` yield every
|
|
116
|
-
*
|
|
162
|
+
* its monotonic budget so a large tree never holds the event loop in
|
|
117
163
|
* one synchronous burst. Returns true iff the visitor stopped the walk via
|
|
118
164
|
* `"stop"`.
|
|
165
|
+
*
|
|
166
|
+
* #1137: every per-directory read goes through {@link readDirEntriesSafeAsync},
|
|
167
|
+
* so the walk is non-blocking on BOTH axes — CPU (the `setImmediate` cadence)
|
|
168
|
+
* and I/O (the directory read itself). The yield cadence alone never covered
|
|
169
|
+
* the I/O axis: a stalled cloud-backed `readdirSync` held the loop for the full
|
|
170
|
+
* stall no matter how often the walk yielded around it.
|
|
119
171
|
*/
|
|
120
172
|
export async function walkTreeStackAsync(rootDir, visit, opts) {
|
|
121
173
|
await opts.beforeWalk?.();
|
|
122
174
|
const steps = walkTreeStackSteps(rootDir, visit, opts.shouldStop);
|
|
123
|
-
|
|
175
|
+
const deadline = createDeadline(opts.budgetMs ?? 8);
|
|
124
176
|
let step = steps.next();
|
|
125
177
|
while (!step.done) {
|
|
126
|
-
if (
|
|
127
|
-
|
|
128
|
-
|
|
178
|
+
if (step.value !== undefined) {
|
|
179
|
+
// Directory-read request — satisfy it off the loop. No
|
|
180
|
+
step = steps.next(await readDirEntriesSafeAsync(step.value));
|
|
181
|
+
deadline.reset();
|
|
182
|
+
continue;
|
|
129
183
|
}
|
|
184
|
+
if (deadline.expired())
|
|
185
|
+
await yieldIfOverBudget(deadline);
|
|
130
186
|
step = steps.next();
|
|
131
187
|
}
|
|
132
188
|
return step.value;
|
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import * as os from "node:os";
|
|
10
10
|
import * as path from "node:path";
|
|
11
|
+
import { BoundedLruCache } from "./bounded-cache.js";
|
|
12
|
+
import { normalizeMapKey } from "./path-utils.js";
|
|
11
13
|
import { lazyEnvNumber } from "./env-utils.js";
|
|
12
14
|
import { getProjectIgnoreMatcher, } from "./file-utils.js";
|
|
13
15
|
import { isAtOrAboveHomeDir } from "./path-utils.js";
|
|
@@ -220,15 +222,18 @@ export function countSourceFilesWithinLimit(dir, limit) {
|
|
|
220
222
|
// depends only on the file tree shape and ignore rules — both of which
|
|
221
223
|
// are also captured by the project snapshot freshness check upstream —
|
|
222
224
|
// in-process memoisation is safe for the duration of a single pi process.
|
|
223
|
-
const startupScanContextCache = new
|
|
225
|
+
const startupScanContextCache = new BoundedLruCache(32);
|
|
226
|
+
function startupScanCacheKey(cwd, options) {
|
|
227
|
+
return [
|
|
228
|
+
normalizeMapKey(path.resolve(cwd)),
|
|
229
|
+
options.homeDir ? normalizeMapKey(path.resolve(options.homeDir)) : "",
|
|
230
|
+
options.maxSourceFiles ?? "",
|
|
231
|
+
options.maxScanEntries ?? "",
|
|
232
|
+
].join("|");
|
|
233
|
+
}
|
|
234
|
+
export const __testing = { startupScanCacheKey };
|
|
224
235
|
export function resolveStartupScanContext(cwd, options = {}) {
|
|
225
|
-
const cacheKey =
|
|
226
|
-
"|" +
|
|
227
|
-
(options.homeDir ?? "") +
|
|
228
|
-
"|" +
|
|
229
|
-
(options.maxSourceFiles ?? "") +
|
|
230
|
-
"|" +
|
|
231
|
-
(options.maxScanEntries ?? "");
|
|
236
|
+
const cacheKey = startupScanCacheKey(cwd, options);
|
|
232
237
|
const cached = startupScanContextCache.get(cacheKey);
|
|
233
238
|
if (cached)
|
|
234
239
|
return cached;
|
|
@@ -322,7 +327,7 @@ async function walkSourceCountAsync(dir, limit, maxEntries, opts = {}) {
|
|
|
322
327
|
// ~0.1ms of overhead and a 2k-file project produces ~20 yields, so the
|
|
323
328
|
// total async overhead is well under 5ms while keeping per-burst sync
|
|
324
329
|
// work under 50ms (the perceptual threshold for "instant" keystrokes).
|
|
325
|
-
|
|
330
|
+
budgetMs: opts.budgetMs ?? 8,
|
|
326
331
|
// #703: prime the tracked-files set ONCE before the walk (not per file)
|
|
327
332
|
// so a tracked file matching a `.gitignore`/global pattern isn't dropped
|
|
328
333
|
// from the startup source-file count. Fail-open: resolves even when git
|
|
@@ -338,13 +343,7 @@ export async function countSourceFilesWithinLimitAsync(dir, limit, opts = {}) {
|
|
|
338
343
|
return (await walkSourceCountAsync(dir, limit, Number.POSITIVE_INFINITY, opts)).count;
|
|
339
344
|
}
|
|
340
345
|
export async function resolveStartupScanContextAsync(cwd, options = {}) {
|
|
341
|
-
const cacheKey =
|
|
342
|
-
"|" +
|
|
343
|
-
(options.homeDir ?? "") +
|
|
344
|
-
"|" +
|
|
345
|
-
(options.maxSourceFiles ?? "") +
|
|
346
|
-
"|" +
|
|
347
|
-
(options.maxScanEntries ?? "");
|
|
346
|
+
const cacheKey = startupScanCacheKey(cwd, options);
|
|
348
347
|
const cached = startupScanContextCache.get(cacheKey);
|
|
349
348
|
if (cached)
|
|
350
349
|
return cached;
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* Design: File-level targeted testing — only runs tests for the
|
|
11
11
|
* specific file being edited, not the entire suite.
|
|
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
|
import { minimatch } from "./deps/minimatch.js";
|
|
@@ -64,7 +65,7 @@ const MAX_NODE_MODULES_WALK_UP = 5;
|
|
|
64
65
|
// unbounded walk of the whole tests tree.
|
|
65
66
|
const MAX_PYTEST_RECURSE_DEPTH = 3;
|
|
66
67
|
// --- Runner Detection ---
|
|
67
|
-
const RUNNERS = {
|
|
68
|
+
export const RUNNERS = {
|
|
68
69
|
vitest: {
|
|
69
70
|
configFiles: ["vitest.config.ts", "vitest.config.js", "vitest.config.mjs"],
|
|
70
71
|
command: "npx",
|
|
@@ -140,6 +141,11 @@ const RUNNERS = {
|
|
|
140
141
|
rspec: {
|
|
141
142
|
configFiles: [".rspec", "spec/spec_helper.rb"],
|
|
142
143
|
command: "bundle",
|
|
144
|
+
// The real binary is "bundle" (the command runs `bundle exec rspec
|
|
145
|
+
// <file>`), NOT "rspec" — without this, binName defaulted to the
|
|
146
|
+
// runner key "rspec" and local/global resolution looked for the wrong
|
|
147
|
+
// binary name (#1098).
|
|
148
|
+
binName: "bundle",
|
|
143
149
|
args: (testFile, _cwd) => ["exec", "rspec", testFile],
|
|
144
150
|
parseJson: false,
|
|
145
151
|
},
|
|
@@ -166,6 +172,26 @@ const RUNNERS = {
|
|
|
166
172
|
parseJson: false, // mix test's default output is text-based
|
|
167
173
|
},
|
|
168
174
|
};
|
|
175
|
+
/**
|
|
176
|
+
* Drop the leading arg(s) of a runner's args() that merely NAME the binary
|
|
177
|
+
* being invoked (the npx-wrapper convention: `npx vitest run …` → once
|
|
178
|
+
* `vitest` becomes the resolved command itself, the leading "vitest" arg is
|
|
179
|
+
* redundant). This must NOT strip a real subcommand.
|
|
180
|
+
*
|
|
181
|
+
* Two wrapper shapes are recognized:
|
|
182
|
+
* - `[binName, ...rest]` (vitest/jest-style: `npx <bin> ...`) → drop 1.
|
|
183
|
+
* - `["-m", binName, ...rest]` (pytest-style: `python -m <bin> ...`) → drop 2.
|
|
184
|
+
* Anything else (cargo's `["test", "--no-fail-fast"]`, go's
|
|
185
|
+
* `["test", "-run", …]`, rspec's `["exec", "rspec", file]` once binName is
|
|
186
|
+
* "bundle", etc.) is a real subcommand/argv and is returned unchanged (#1098).
|
|
187
|
+
*/
|
|
188
|
+
export function stripWrapperArgs(binName, args) {
|
|
189
|
+
if (args[0] === binName)
|
|
190
|
+
return args.slice(1);
|
|
191
|
+
if (args[0] === "-m" && args[1] === binName)
|
|
192
|
+
return args.slice(2);
|
|
193
|
+
return args;
|
|
194
|
+
}
|
|
169
195
|
// --- Client ---
|
|
170
196
|
export class TestRunnerClient {
|
|
171
197
|
log;
|
|
@@ -180,7 +206,7 @@ export class TestRunnerClient {
|
|
|
180
206
|
vitestTestGlobsCache = new Map();
|
|
181
207
|
constructor(verbose = false) {
|
|
182
208
|
this.log = verbose
|
|
183
|
-
? (
|
|
209
|
+
? createSubsystemLogger("test-runner")
|
|
184
210
|
: () => { };
|
|
185
211
|
}
|
|
186
212
|
/**
|
|
@@ -1213,8 +1239,12 @@ export class TestRunnerClient {
|
|
|
1213
1239
|
* Resolve the executable and args for a runner, preferring a local
|
|
1214
1240
|
* node_modules/.bin binary over npx to avoid the ~150ms npx startup cost.
|
|
1215
1241
|
*
|
|
1216
|
-
* When a
|
|
1217
|
-
*
|
|
1242
|
+
* When a resolved binary becomes the command itself, `stripWrapperArgs`
|
|
1243
|
+
* drops ONLY the leading arg(s) that named the wrapped binary — never a
|
|
1244
|
+
* real subcommand (#1098: `cargo test --no-fail-fast` unconditionally lost
|
|
1245
|
+
* `test` here because the old code assumed every runner's args() started
|
|
1246
|
+
* with an npx-style runner-name arg, which only holds for wrapper-style
|
|
1247
|
+
* runners like vitest/jest/pytest).
|
|
1218
1248
|
*/
|
|
1219
1249
|
async resolveExec(runner, config, testFile, cwd) {
|
|
1220
1250
|
// PHPUnit has no npx-style automatic local-binary resolution — Composer's
|
|
@@ -1232,15 +1262,15 @@ export class TestRunnerClient {
|
|
|
1232
1262
|
const suffix = process.platform === "win32" ? ".cmd" : "";
|
|
1233
1263
|
const localBin = path.join(cwd, "node_modules", ".bin", binName + suffix);
|
|
1234
1264
|
// A resolved binary (local, or any manager's global bin) becomes the command
|
|
1235
|
-
// itself, so the leading
|
|
1236
|
-
//
|
|
1265
|
+
// itself, so the leading wrapper-name arg(s) that named it (e.g. "vitest",
|
|
1266
|
+
// or "-m pytest") are stripped from args() — see stripWrapperArgs.
|
|
1237
1267
|
if (fs.existsSync(localBin)) {
|
|
1238
|
-
return { command: localBin, args: config.args(testFile, cwd)
|
|
1268
|
+
return { command: localBin, args: stripWrapperArgs(binName, config.args(testFile, cwd)) };
|
|
1239
1269
|
}
|
|
1240
1270
|
// Any package manager's global bin dir (npm/pnpm/yarn/bun) before npx (#375).
|
|
1241
1271
|
const globalBin = await findGlobalBinary(binName);
|
|
1242
1272
|
if (globalBin) {
|
|
1243
|
-
return { command: globalBin, args: config.args(testFile, cwd)
|
|
1273
|
+
return { command: globalBin, args: stripWrapperArgs(binName, config.args(testFile, cwd)) };
|
|
1244
1274
|
}
|
|
1245
1275
|
return { command: config.command, args: config.args(testFile, cwd) };
|
|
1246
1276
|
}
|
|
@@ -11,6 +11,41 @@
|
|
|
11
11
|
*
|
|
12
12
|
* The SDK function is a one-line discriminant check, so we inline it and keep
|
|
13
13
|
* every `@earendil-works/pi-coding-agent` import type-only (types compile away).
|
|
14
|
+
* `tests/host-sdk-type-only.test.ts` pins that invariant.
|
|
15
|
+
*
|
|
16
|
+
* ## S6 audit: the per-tool `is*ToolResult` discriminators (#1334)
|
|
17
|
+
*
|
|
18
|
+
* The SDK also exports seven `tool_result` discriminators — `isBashToolResult`,
|
|
19
|
+
* `isReadToolResult`, `isEditToolResult`, `isWriteToolResult`,
|
|
20
|
+
* `isGrepToolResult`, `isFindToolResult`, `isLsToolResult`. pi-lens does NOT
|
|
21
|
+
* consolidate onto them, and the reasons are worth recording so the question
|
|
22
|
+
* isn't relitigated:
|
|
23
|
+
*
|
|
24
|
+
* 1. **They are runtime values, not types.** Same `--omit=dev` constraint as
|
|
25
|
+
* above — importing them would break on a clean user install. Inlining them
|
|
26
|
+
* is the only option, and each one's entire body is verbatim
|
|
27
|
+
* `e.toolName === "<name>"` (checked against the pinned SDK's `types.js`).
|
|
28
|
+
* 2. **`isToolCallEventType` already subsumes all seven.** It is the SDK's own
|
|
29
|
+
* generic form of the same check, and it is already inlined below and used
|
|
30
|
+
* at pi-lens's `tool_call` sites. Adding seven fixed-name aliases of a
|
|
31
|
+
* generic we already have would be indirection, not consolidation.
|
|
32
|
+
* 3. **The seven cover strictly fewer tools than pi-lens intercepts.** They
|
|
33
|
+
* enumerate the built-ins only; pi-lens's `tool_call`/`tool_result` paths
|
|
34
|
+
* also key off `lsp_navigation` and pi-lens's own registered tools, which no
|
|
35
|
+
* host discriminator names.
|
|
36
|
+
* 4. **Narrowing to the host union would LOSE fields pi-lens reads.** The host
|
|
37
|
+
* `ToolResultEvent` declares `toolCallId`/`input`/`content`/`isError`/
|
|
38
|
+
* `details`/`usage`; pi-lens's local `ToolResultEvent`
|
|
39
|
+
* (`clients/runtime-tool-result.ts`) additionally carries
|
|
40
|
+
* `id`/`callId`/`requestId`/`provider`/`model`/`sessionId`/`session`, which
|
|
41
|
+
* the telemetry-identity path reads. A guard that narrowed to
|
|
42
|
+
* `EditToolResultEvent` would drop them.
|
|
43
|
+
*
|
|
44
|
+
* What IS consolidated is the part that costs nothing: the host's `details`
|
|
45
|
+
* SHAPES are type-only exports, so `EditToolDetails` & co. are imported as
|
|
46
|
+
* types rather than re-declared ad hoc. Genuinely pi-lens-specific `details`
|
|
47
|
+
* payloads (`searchReads`, `piLensPartialApply`) stay hand-declared — no host
|
|
48
|
+
* type describes them.
|
|
14
49
|
*/
|
|
15
50
|
export function isToolCallEventType(toolName, event) {
|
|
16
51
|
return (!!event &&
|