@herbertgao/pi-extensions 2026.8.6 → 2026.8.8
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 +8 -6
- package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +2 -2
- package/node_modules/@herbertgao/pi-cc-extensions/README.md +2 -2
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/config.ts +19 -7
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +30 -9
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/compact-thinking.ts +320 -22
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/compact-mode.ts +94 -77
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/message-display.ts +79 -17
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/hover.ts +27 -0
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/interaction.ts +66 -17
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/layout.ts +41 -2
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-renderer.ts +75 -6
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/types.ts +7 -3
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/grouping.ts +64 -1
- package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
- package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +6 -0
- package/node_modules/@herbertgao/pi-subagents/README.md +30 -22
- package/node_modules/@herbertgao/pi-subagents/examples/agent-tool-description.md +5 -5
- package/node_modules/@herbertgao/pi-subagents/package.json +7 -7
- package/node_modules/@herbertgao/pi-subagents/src/agent-file-toggle.ts +7 -1
- package/node_modules/@herbertgao/pi-subagents/src/agent-manager.ts +48 -19
- package/node_modules/@herbertgao/pi-subagents/src/agent-runner.ts +17 -13
- package/node_modules/@herbertgao/pi-subagents/src/custom-agents.ts +26 -2
- package/node_modules/@herbertgao/pi-subagents/src/index.ts +219 -40
- package/node_modules/@herbertgao/pi-subagents/src/invocation-config.ts +101 -3
- package/node_modules/@herbertgao/pi-subagents/src/nested-tools.ts +18 -4
- package/node_modules/@herbertgao/pi-subagents/src/settings.ts +99 -0
- package/node_modules/@herbertgao/pi-subagents/src/types.ts +22 -3
- package/node_modules/@herbertgao/pi-subagents/src/ui/agent-widget.ts +51 -3
- package/node_modules/@herbertgao/pi-subagents/src/ui/conversation-viewer.ts +20 -2
- package/node_modules/@herbertgao/pi-subagents/src/ui/fleet-list.ts +21 -6
- package/node_modules/@herbertgao/pi-subagents/src/usage.ts +129 -1
- package/node_modules/@herbertgao/pi-subagents/src/worktree.ts +20 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/README.md +5 -4
- package/node_modules/@juicesharp/rpiv-ask-user-question/ask-user-question.ts +174 -100
- package/node_modules/@juicesharp/rpiv-ask-user-question/config.ts +25 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/docs/configuration.md +13 -4
- package/node_modules/@juicesharp/rpiv-ask-user-question/docs/hosts.md +5 -1
- package/node_modules/@juicesharp/rpiv-ask-user-question/docs/keyboard.md +10 -2
- package/node_modules/@juicesharp/rpiv-ask-user-question/docs/localization.md +10 -6
- package/node_modules/@juicesharp/rpiv-ask-user-question/docs/tool-schema.md +11 -5
- package/node_modules/@juicesharp/rpiv-ask-user-question/locales/en.json +5 -2
- package/node_modules/@juicesharp/rpiv-ask-user-question/locales/zh.json +2 -2
- package/node_modules/@juicesharp/rpiv-ask-user-question/package.json +3 -2
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/build-questionnaire.ts +10 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/key-router.ts +140 -97
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/questionnaire-session.ts +63 -28
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/selectors/projections.ts +22 -15
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/state-reducer.ts +11 -1
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/state.ts +14 -6
- package/node_modules/@juicesharp/rpiv-ask-user-question/tool/response-envelope.ts +11 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/tool/types.ts +11 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/view/components/multi-select-view.ts +31 -17
- package/node_modules/@juicesharp/rpiv-ask-user-question/view/components/preview/preview-block-renderer.ts +15 -6
- package/node_modules/@juicesharp/rpiv-ask-user-question/view/components/wrapping-select.ts +15 -6
- package/node_modules/@juicesharp/rpiv-ask-user-question/view/dialog-builder.ts +86 -38
- package/node_modules/@juicesharp/rpiv-ask-user-question/view/tab-content-strategy.ts +76 -9
- package/node_modules/@narumitw/pi-btw/README.md +120 -111
- package/node_modules/@narumitw/pi-btw/dist/index.ts +2898 -0
- package/node_modules/@narumitw/pi-btw/dist/index.ts.map +7 -0
- package/node_modules/@narumitw/pi-btw/package.json +10 -6
- package/node_modules/@narumitw/pi-btw/src/btw.ts +36 -40
- package/node_modules/@narumitw/pi-btw/src/fullscreen-ui.ts +55 -10
- package/node_modules/@narumitw/pi-btw/src/main-tree-picker.ts +390 -0
- package/node_modules/@narumitw/pi-btw/src/menu.ts +45 -2
- package/node_modules/@narumitw/pi-btw/src/transcript-pager.ts +136 -45
- package/node_modules/@pi-plugins/fast-mode/dist/index.mjs +44 -1856
- package/node_modules/@pi-plugins/fast-mode/dist/index.mjs.map +1 -1
- package/node_modules/@pi-plugins/fast-mode/package.json +4 -6
- package/node_modules/pi-lens/CHANGELOG.md +999 -0
- package/node_modules/pi-lens/README.md +117 -3
- package/node_modules/pi-lens/config/ruff/core.toml +42 -0
- package/node_modules/pi-lens/dist/clients/actionable-warnings.js +130 -27
- package/node_modules/pi-lens/dist/clients/advisory-provenance.js +126 -13
- package/node_modules/pi-lens/dist/clients/agent-nudge.js +67 -11
- package/node_modules/pi-lens/dist/clients/ast-grep-client.js +9 -3
- package/node_modules/pi-lens/dist/clients/atomic-write.js +9 -3
- package/node_modules/pi-lens/dist/clients/bash-file-access.js +381 -13
- package/node_modules/pi-lens/dist/clients/biome-client.js +61 -30
- package/node_modules/pi-lens/dist/clients/blocker-freshness.js +428 -0
- package/node_modules/pi-lens/dist/clients/blocker-past-eof.js +129 -0
- package/node_modules/pi-lens/dist/clients/bootstrap.js +12 -1
- package/node_modules/pi-lens/dist/clients/bounded-pid-file-lock.js +12 -3
- package/node_modules/pi-lens/dist/clients/bounded-telemetry.js +206 -0
- package/node_modules/pi-lens/dist/clients/cache-observability.js +353 -76
- package/node_modules/pi-lens/dist/clients/cascade-budget.js +196 -0
- package/node_modules/pi-lens/dist/clients/cascade-format.js +20 -1
- package/node_modules/pi-lens/dist/clients/cascade-types.js +9 -1
- package/node_modules/pi-lens/dist/clients/child-unref.js +54 -6
- package/node_modules/pi-lens/dist/clients/code-quality-warnings.js +76 -24
- package/node_modules/pi-lens/dist/clients/dead-code-client.js +123 -31
- package/node_modules/pi-lens/dist/clients/deadline-utils.js +8 -1
- package/node_modules/pi-lens/dist/clients/debug-handles.js +5 -0
- package/node_modules/pi-lens/dist/clients/degradation-ledger.js +84 -14
- package/node_modules/pi-lens/dist/clients/demoted-finding-render.js +155 -0
- package/node_modules/pi-lens/dist/clients/dependency-checker.js +25 -3
- package/node_modules/pi-lens/dist/clients/deps/pi-tui.js +8 -2
- package/node_modules/pi-lens/dist/clients/deps/typebox.js +8 -3
- package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +147 -33
- package/node_modules/pi-lens/dist/clients/diagnostic-line-freshness.js +298 -0
- package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +52 -2
- package/node_modules/pi-lens/dist/clients/dispatch/integration.js +256 -88
- package/node_modules/pi-lens/dist/clients/dispatch/lazy.js +7 -4
- package/node_modules/pi-lens/dist/clients/dispatch/plan.js +5 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ast-grep-napi.js +234 -18
- package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +187 -19
- package/node_modules/pi-lens/dist/clients/dispatch/runners/cpp-check.js +6 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/credo.js +11 -9
- package/node_modules/pi-lens/dist/clients/dispatch/runners/cue-vet.js +398 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/detekt.js +9 -6
- package/node_modules/pi-lens/dist/clients/dispatch/runners/elixir-check.js +11 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/eslint.js +12 -7
- package/node_modules/pi-lens/dist/clients/dispatch/runners/go-vet.js +18 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/hadolint.js +9 -7
- package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-render.js +895 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/htmlhint.js +8 -6
- package/node_modules/pi-lens/dist/clients/dispatch/runners/index.js +4 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/javac.js +16 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +60 -53
- package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +16 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/mypy.js +25 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/oxlint.js +20 -5
- package/node_modules/pi-lens/dist/clients/dispatch/runners/phpstan.js +44 -11
- package/node_modules/pi-lens/dist/clients/dispatch/runners/psscriptanalyzer.js +331 -55
- package/node_modules/pi-lens/dist/clients/dispatch/runners/pyright.js +38 -5
- package/node_modules/pi-lens/dist/clients/dispatch/runners/rust-clippy.js +97 -19
- package/node_modules/pi-lens/dist/clients/dispatch/runners/spellcheck.js +17 -8
- package/node_modules/pi-lens/dist/clients/dispatch/runners/sqlfluff.js +32 -4
- package/node_modules/pi-lens/dist/clients/dispatch/runners/stylelint.js +47 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/swiftlint.js +14 -4
- package/node_modules/pi-lens/dist/clients/dispatch/runners/taplo.js +127 -28
- package/node_modules/pi-lens/dist/clients/dispatch/runners/tflint.js +12 -7
- package/node_modules/pi-lens/dist/clients/dispatch/runners/trivy-config.js +73 -12
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/availability-policy.js +275 -13
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/candidate-probe.js +21 -6
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/lazy-installer.js +260 -27
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +734 -64
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/spawn-outcome.js +86 -11
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/tool-failure.js +188 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/toolchain-availability.js +9 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/vale.js +21 -10
- package/node_modules/pi-lens/dist/clients/dispatch/runners/yamllint.js +18 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/zig-check.js +4 -2
- package/node_modules/pi-lens/dist/clients/event-loop-monitor.js +28 -5
- package/node_modules/pi-lens/dist/clients/extension-log.js +22 -1
- package/node_modules/pi-lens/dist/clients/file-kinds.js +8 -2
- package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +316 -0
- package/node_modules/pi-lens/dist/clients/finding-identity.js +88 -0
- package/node_modules/pi-lens/dist/clients/formatters-lazy.js +3 -2
- package/node_modules/pi-lens/dist/clients/formatters.js +500 -115
- package/node_modules/pi-lens/dist/clients/generation-guard.js +216 -0
- package/node_modules/pi-lens/dist/clients/git-guard.js +31 -0
- package/node_modules/pi-lens/dist/clients/gitleaks-client.js +181 -8
- package/node_modules/pi-lens/dist/clients/govulncheck-client.js +109 -9
- package/node_modules/pi-lens/dist/clients/grammar-source.js +333 -10
- package/node_modules/pi-lens/dist/clients/host-ports.js +8 -0
- package/node_modules/pi-lens/dist/clients/installer/index.js +1114 -100
- package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh-session.js +58 -0
- package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh.js +715 -0
- package/node_modules/pi-lens/dist/clients/instance-reaper.js +643 -97
- package/node_modules/pi-lens/dist/clients/instance-registry.js +87 -17
- package/node_modules/pi-lens/dist/clients/jscpd-client.js +87 -8
- package/node_modules/pi-lens/dist/clients/knip-client.js +310 -10
- package/node_modules/pi-lens/dist/clients/language-policy.js +8 -2
- package/node_modules/pi-lens/dist/clients/language-profile.js +9 -2
- package/node_modules/pi-lens/dist/clients/latency-logger.js +440 -11
- package/node_modules/pi-lens/dist/clients/lazy-import.js +21 -0
- package/node_modules/pi-lens/dist/clients/ledger-bounds.js +21 -0
- package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +8 -0
- package/node_modules/pi-lens/dist/clients/lsp/cascade-tier.js +128 -8
- package/node_modules/pi-lens/dist/clients/lsp/client.js +1660 -164
- package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +83 -1
- package/node_modules/pi-lens/dist/clients/lsp/document-drift.js +389 -0
- package/node_modules/pi-lens/dist/clients/lsp/index.js +2423 -151
- package/node_modules/pi-lens/dist/clients/lsp/inferred-project.js +215 -0
- package/node_modules/pi-lens/dist/clients/lsp/jvm-runtime.js +146 -14
- package/node_modules/pi-lens/dist/clients/lsp/language.js +48 -4
- package/node_modules/pi-lens/dist/clients/lsp/server.js +277 -16
- package/node_modules/pi-lens/dist/clients/lsp/spawn-history.js +22 -0
- package/node_modules/pi-lens/dist/clients/lsp/sync-kind.js +43 -0
- package/node_modules/pi-lens/dist/clients/lsp/tsserver-sync.js +79 -3
- package/node_modules/pi-lens/dist/clients/lsp/wait-policy/strategies.js +43 -0
- package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +422 -28
- package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-session.js +30 -0
- package/node_modules/pi-lens/dist/clients/lsp/workspace-sweep-hold.js +175 -0
- package/node_modules/pi-lens/dist/clients/lsp-lazy.js +3 -2
- package/node_modules/pi-lens/dist/clients/mcp/session.js +10 -2
- package/node_modules/pi-lens/dist/clients/module-report.js +22 -1
- package/node_modules/pi-lens/dist/clients/ndjson-logger.js +114 -23
- package/node_modules/pi-lens/dist/clients/opengrep-client.js +15 -1
- package/node_modules/pi-lens/dist/clients/package-manager.js +170 -14
- package/node_modules/pi-lens/dist/clients/path-attribution-telemetry.js +27 -0
- package/node_modules/pi-lens/dist/clients/path-utils.js +160 -0
- package/node_modules/pi-lens/dist/clients/pipeline.js +154 -33
- package/node_modules/pi-lens/dist/clients/post-autofix-notice.js +37 -0
- package/node_modules/pi-lens/dist/clients/project-diagnostics/cache.js +17 -3
- package/node_modules/pi-lens/dist/clients/project-diagnostics/extractors.js +89 -22
- package/node_modules/pi-lens/dist/clients/project-diagnostics/fresh-fetch.js +84 -14
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/gitleaks.js +15 -3
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/trivy.js +50 -2
- package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +23 -9
- package/node_modules/pi-lens/dist/clients/project-lens-config.js +3 -0
- package/node_modules/pi-lens/dist/clients/project-report.js +62 -27
- package/node_modules/pi-lens/dist/clients/project-snapshot.js +299 -0
- package/node_modules/pi-lens/dist/clients/quiet-window-config.js +47 -0
- package/node_modules/pi-lens/dist/clients/quiet-window.js +11 -25
- package/node_modules/pi-lens/dist/clients/read-guard-logger.js +8 -3
- package/node_modules/pi-lens/dist/clients/read-guard.js +253 -10
- package/node_modules/pi-lens/dist/clients/resource-sampler.js +49 -17
- package/node_modules/pi-lens/dist/clients/reverse-deps.js +50 -11
- package/node_modules/pi-lens/dist/clients/review-graph/builder.js +194 -31
- package/node_modules/pi-lens/dist/clients/review-graph/query.js +52 -4
- package/node_modules/pi-lens/dist/clients/review-graph/revision-drift.js +21 -0
- package/node_modules/pi-lens/dist/clients/review-graph/workspace-modules.js +6 -3
- package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +96 -7
- package/node_modules/pi-lens/dist/clients/runtime-context.js +8 -1
- package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +352 -45
- package/node_modules/pi-lens/dist/clients/runtime-session.js +373 -9
- package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +217 -22
- package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +212 -79
- package/node_modules/pi-lens/dist/clients/runtime-turn.js +620 -67
- package/node_modules/pi-lens/dist/clients/safe-spawn.js +220 -7
- package/node_modules/pi-lens/dist/clients/scratch-tree-policy.js +161 -0
- package/node_modules/pi-lens/dist/clients/search-read-registration.js +34 -6
- package/node_modules/pi-lens/dist/clients/security-scan-client.js +157 -24
- package/node_modules/pi-lens/dist/clients/session-event-guard.js +184 -0
- package/node_modules/pi-lens/dist/clients/sg-runner.js +116 -22
- package/node_modules/pi-lens/dist/clients/single-flight.js +158 -0
- package/node_modules/pi-lens/dist/clients/source-filter.js +6 -2
- package/node_modules/pi-lens/dist/clients/stale-marker.js +17 -0
- package/node_modules/pi-lens/dist/clients/startup-scan.js +5 -2
- package/node_modules/pi-lens/dist/clients/startup-timing.js +19 -1
- package/node_modules/pi-lens/dist/clients/test-runner-client.js +151 -16
- package/node_modules/pi-lens/dist/clients/tool-event.js +56 -5
- package/node_modules/pi-lens/dist/clients/tool-policy.js +125 -20
- package/node_modules/pi-lens/dist/clients/tree-sitter-cache.js +75 -1
- package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +769 -64
- package/node_modules/pi-lens/dist/clients/tree-sitter-logger.js +1 -0
- package/node_modules/pi-lens/dist/clients/tree-sitter-shared.js +11 -0
- package/node_modules/pi-lens/dist/clients/tree-sitter-symbol-extractor.js +90 -0
- package/node_modules/pi-lens/dist/clients/trivy-client.js +19 -1
- package/node_modules/pi-lens/dist/clients/widget-state.js +336 -36
- package/node_modules/pi-lens/dist/clients/zizmor-config.js +214 -14
- package/node_modules/pi-lens/dist/index.js +61407 -48577
- package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +476 -57
- package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +132 -43
- package/node_modules/pi-lens/dist/tools/lsp-navigation.js +46 -7
- package/node_modules/pi-lens/docs/agent-guide.md +6 -1
- package/node_modules/pi-lens/docs/ast-grep_rules_catalog.md +515 -506
- package/node_modules/pi-lens/docs/dispositions.md +21 -0
- package/node_modules/pi-lens/docs/features.md +19 -5
- package/node_modules/pi-lens/docs/globalconfig.md +3 -0
- package/node_modules/pi-lens/docs/language-coverage.md +71 -5
- package/node_modules/pi-lens/docs/mcp.md +2 -2
- package/node_modules/pi-lens/docs/servercapabilities.md +4 -1
- package/node_modules/pi-lens/docs/settings.md +19 -1
- package/node_modules/pi-lens/docs/usage.md +1 -0
- package/node_modules/pi-lens/package.json +27 -10
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/__snapshots__/no-reflect-get-js-snapshot.yml +23 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/__snapshots__/no-reflect-get-snapshot.yml +23 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/__snapshots__/ts-void-zero-snapshot.yml +23 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-bare-object-param-test.yml +16 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-chained-type-assertions-test.yml +15 -1
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-compile-call-test.yml +29 -1
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-dupe-class-members-test.yml +33 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-inner-html-js-test.yml +7 -1
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-inner-html-test.yml +7 -1
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-known-value-widening-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-non-null-assertion-test.yml +216 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-js-test.yml +2 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-test.yml +2 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-js-test.yml +2 -1
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-test.yml +2 -1
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-return-value-in-generator-test.yml +12 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-runtime-typeof-test.yml +33 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-server-bind-wildcard-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-shape-in-symbol-names-test.yml +13 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-sql-in-code-js-test.yml +5 -1
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-sql-in-code-test.yml +5 -1
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unknown-parameters-test.yml +12 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unknown-returns-test.yml +16 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unsafe-dictionary-any-test.yml +10 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unsafe-dictionary-unknown-test.yml +8 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/redundant-unsafe-function-test.yml +35 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/require-safety-comment-for-as-unknown-as-test.yml +177 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/ts-void-zero-test.yml +1 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-await-expression-member-js.yml +13 -2
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-await-expression-member.yml +13 -2
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-host-path-in-win32-branch.yml +2 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-object-param.yml +60 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-chained-type-assertions.yml +57 -12
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-compile-call.yml +63 -5
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-dupe-class-members.yml +52 -8
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-inner-html-js.yml +27 -2
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-inner-html.yml +27 -2
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-known-value-widening.yml +71 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-non-null-assertion.yml +316 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-raw-json-store-write.yml +7 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply-js.yml +22 -2
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply.yml +23 -2
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get-js.yml +33 -5
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get.yml +34 -8
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-return-value-in-generator.yml +22 -5
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-runtime-typeof.yml +121 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-server-bind-wildcard.yml +23 -7
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-shape-in-symbol-names.yml +68 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-sql-in-code-js.yml +41 -2
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-sql-in-code.yml +41 -2
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-laundering.yml +6 -1
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-parameters.yml +67 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-returns.yml +106 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unsafe-dictionary-any.yml +50 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unsafe-dictionary-unknown.yml +56 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-win32-isabsolute-for-qualification.yml +2 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/redundant-unsafe-function.yml +32 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/require-safety-comment-for-as-unknown-as.yml +184 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/ts-void-zero.yml +5 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/self-scan-baseline.json +5 -0
- package/node_modules/pi-lens/scripts/analyze-pi-lens-logs.mjs +53 -1
- package/node_modules/pi-lens/scripts/download-grammars.js +25 -0
- package/node_modules/pi-lens/scripts/grammars.lock.json +9 -0
- package/node_modules/pi-lens/scripts/install-selftest.mjs +99 -11
- package/node_modules/pi-lens/scripts/lib/host-provided-deps.mjs +75 -0
- package/node_modules/pi-lens/scripts/lib/warm-loader-cache.mjs +285 -0
- package/node_modules/pi-lens/scripts/warm-loader-cache.mjs +233 -0
- package/node_modules/pi-lens/skills/pi-lens-ast-grep/SKILL.md +2 -0
- package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/SKILL.md +80 -3
- package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/reference.md +41 -0
- package/node_modules/pi-lens/vendor/grammars/tree-sitter-cue.wasm +0 -0
- package/node_modules/pi-mcp-adapter/CHANGELOG.md +36 -0
- package/node_modules/pi-mcp-adapter/README.md +47 -5
- package/node_modules/pi-mcp-adapter/cli.js +163 -1
- package/node_modules/pi-mcp-adapter/commands.ts +128 -22
- package/node_modules/pi-mcp-adapter/config.ts +25 -7
- package/node_modules/pi-mcp-adapter/direct-tools.ts +5 -4
- package/node_modules/pi-mcp-adapter/index.ts +219 -32
- package/node_modules/pi-mcp-adapter/init.ts +36 -4
- package/node_modules/pi-mcp-adapter/lifecycle.ts +315 -24
- package/node_modules/pi-mcp-adapter/mcp-auth-flow.ts +39 -6
- package/node_modules/pi-mcp-adapter/mcp-bearer-store.ts +387 -0
- package/node_modules/pi-mcp-adapter/mcp-callback-server.ts +27 -3
- package/node_modules/pi-mcp-adapter/mcp-code.ts +4 -0
- package/node_modules/pi-mcp-adapter/mcp-panel.ts +42 -13
- package/node_modules/pi-mcp-adapter/metadata-cache.ts +32 -21
- package/node_modules/pi-mcp-adapter/package-mcp-loader.ts +168 -0
- package/node_modules/pi-mcp-adapter/package.json +3 -1
- package/node_modules/pi-mcp-adapter/proxy-modes.ts +5 -4
- package/node_modules/pi-mcp-adapter/request-headers-command.ts +31 -37
- package/node_modules/pi-mcp-adapter/search-ranking.ts +92 -22
- package/node_modules/pi-mcp-adapter/server-manager.ts +140 -2
- package/node_modules/pi-mcp-adapter/session-recovery.ts +7 -0
- package/node_modules/pi-mcp-adapter/tool-approval.ts +15 -2
- package/node_modules/pi-mcp-adapter/tool-result-renderer.ts +44 -4
- package/node_modules/pi-mcp-adapter/types.ts +2 -0
- package/node_modules/pi-mcp-adapter/ui-server.ts +18 -16
- package/node_modules/pi-mcp-adapter/utils.ts +70 -0
- package/node_modules/pi-web-access/CHANGELOG.md +37 -0
- package/node_modules/pi-web-access/README.md +32 -13
- package/node_modules/pi-web-access/anysearch.ts +4 -2
- package/node_modules/pi-web-access/brave.ts +16 -4
- package/node_modules/pi-web-access/chrome-cookies.ts +86 -15
- package/node_modules/pi-web-access/curator-page.ts +6 -3
- package/node_modules/pi-web-access/curator-server.ts +4 -1
- package/node_modules/pi-web-access/data-uri-sanitize.ts +406 -0
- package/node_modules/pi-web-access/exa.ts +18 -7
- package/node_modules/pi-web-access/extract.ts +40 -5
- package/node_modules/pi-web-access/firecrawl.ts +18 -2
- package/node_modules/pi-web-access/gemini-search.ts +16 -4
- package/node_modules/pi-web-access/github-extract.ts +65 -36
- package/node_modules/pi-web-access/index.ts +60 -61
- package/node_modules/pi-web-access/openai-search.ts +17 -6
- package/node_modules/pi-web-access/package.json +1 -1
- package/node_modules/pi-web-access/page-query.ts +4 -2
- package/node_modules/pi-web-access/parallel-mcp.ts +249 -0
- package/node_modules/pi-web-access/parallel.ts +2 -2
- package/node_modules/pi-web-access/pdf-extract.ts +18 -5
- package/node_modules/pi-web-access/query-rewrite.ts +51 -0
- package/node_modules/pi-web-access/serper.ts +211 -0
- package/node_modules/pi-web-access/ssrf-protection.ts +12 -2
- package/node_modules/pi-web-access/summary-model-scope.ts +12 -4
- package/node_modules/pi-web-access/summary-review.ts +44 -22
- package/node_modules/pi-web-access/tavily.ts +16 -4
- package/node_modules/pi-web-access/utils.ts +87 -0
- package/node_modules/pi-web-access/valyu.ts +199 -0
- package/package.json +14 -14
|
@@ -16,7 +16,8 @@
|
|
|
16
16
|
import * as fs from "node:fs";
|
|
17
17
|
import * as os from "node:os";
|
|
18
18
|
import * as path from "node:path";
|
|
19
|
-
import {
|
|
19
|
+
import { classifyProbeFailure, createAvailabilityLatch, isTransientDecision, logAvailabilityDecision, startHostStallSampler, } from "./dispatch/runners/utils/availability-policy.js";
|
|
20
|
+
import { safeSpawnAsync } from "./safe-spawn.js";
|
|
20
21
|
/**
|
|
21
22
|
* Fallback preference when nothing is declared (or the declared manager is
|
|
22
23
|
* missing). npm first for maximum compatibility; bun last. A project lockfile
|
|
@@ -72,18 +73,142 @@ function readPackageManagerField(targetPath) {
|
|
|
72
73
|
// ============================================================================
|
|
73
74
|
// AVAILABILITY (cached per process; reset in tests)
|
|
74
75
|
// ============================================================================
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
76
|
+
/**
|
|
77
|
+
* Budget for the `where`/`which <pm>` probe. Matches the previous
|
|
78
|
+
* `isCommandAvailableAsync` default so the observable timing is unchanged.
|
|
79
|
+
*/
|
|
80
|
+
const PROBE_TIMEOUT_MS = 5_000;
|
|
81
|
+
/**
|
|
82
|
+
* A timed-out probe used to be memoized as a permanent `false` — the process
|
|
83
|
+
* would silently downgrade a declared pnpm/yarn manager to npm for its whole
|
|
84
|
+
* life. The blast radius was internal: this resolver only serves installs
|
|
85
|
+
* into pi-lens's own managed tools directory and `pilens_rebuild` on a
|
|
86
|
+
* pi-lens source checkout, never a user project's lockfile (#1496). Each
|
|
87
|
+
* manager now sits behind the shared transient-aware latch (#1467/#1476):
|
|
88
|
+
* only a genuine absence (`where`/`which` exits non-zero, or ENOENT) latches;
|
|
89
|
+
* a timeout, abort or host stall expires on a cooldown and is re-probed.
|
|
90
|
+
*/
|
|
91
|
+
const availabilityLatches = new Map();
|
|
92
|
+
const inFlightProbes = new Map();
|
|
93
|
+
function getLatch(pm) {
|
|
94
|
+
let latch = availabilityLatches.get(pm);
|
|
95
|
+
if (!latch) {
|
|
96
|
+
latch = createAvailabilityLatch();
|
|
97
|
+
availabilityLatches.set(pm, latch);
|
|
98
|
+
}
|
|
99
|
+
return latch;
|
|
100
|
+
}
|
|
101
|
+
async function probeAvailability(pm) {
|
|
102
|
+
const latch = getLatch(pm);
|
|
103
|
+
const startedAt = Date.now();
|
|
104
|
+
const finder = onWindows() ? "where" : "which";
|
|
105
|
+
const sampler = startHostStallSampler();
|
|
106
|
+
let result;
|
|
107
|
+
let hostStallMs;
|
|
108
|
+
try {
|
|
109
|
+
result = await safeSpawnAsync(finder, [pm], { timeout: PROBE_TIMEOUT_MS });
|
|
81
110
|
}
|
|
82
|
-
|
|
111
|
+
finally {
|
|
112
|
+
hostStallMs = sampler.stop();
|
|
113
|
+
}
|
|
114
|
+
const elapsedMs = Date.now() - startedAt;
|
|
115
|
+
if (result.status === 0 && !result.error) {
|
|
116
|
+
latch.noteAvailable();
|
|
117
|
+
logAvailabilityDecision({
|
|
118
|
+
tool: pm,
|
|
119
|
+
verdict: "available",
|
|
120
|
+
outcome: "success",
|
|
121
|
+
cause: "ok",
|
|
122
|
+
elapsedMs,
|
|
123
|
+
latched: true,
|
|
124
|
+
hostStallMs,
|
|
125
|
+
budgetMs: PROBE_TIMEOUT_MS,
|
|
126
|
+
});
|
|
127
|
+
return true;
|
|
128
|
+
}
|
|
129
|
+
const { outcome, cause, evidence } = classifyProbeFailure(result, {
|
|
130
|
+
hostStallMs,
|
|
131
|
+
// Preserve pre-#1496 meaning for anything the classifier can't place: a
|
|
132
|
+
// present manager that rejects its probe is durable, same as before.
|
|
133
|
+
unclassifiedFailureOutcome: "missing",
|
|
134
|
+
});
|
|
135
|
+
const retryAfterMs = latch.noteUnavailable(outcome, cause);
|
|
136
|
+
logAvailabilityDecision({
|
|
137
|
+
tool: pm,
|
|
138
|
+
verdict: "unavailable",
|
|
139
|
+
outcome,
|
|
140
|
+
cause,
|
|
141
|
+
elapsedMs,
|
|
142
|
+
latched: outcome !== "transient",
|
|
143
|
+
hostStallMs,
|
|
144
|
+
...(retryAfterMs > 0 && { retryAfterMs }),
|
|
145
|
+
budgetMs: PROBE_TIMEOUT_MS,
|
|
146
|
+
classifiedBy: "probe",
|
|
147
|
+
evidence,
|
|
148
|
+
});
|
|
149
|
+
return false;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Resolve whether `pm` is available. `onTransient`, when given, fires
|
|
153
|
+
* whenever the resolved `false` came from a probe that never got a fair
|
|
154
|
+
* hearing (a stall, an abort, a host-level failure classified `transient` by
|
|
155
|
+
* `classifyProbeFailure`) rather than a genuine absence — including when that
|
|
156
|
+
* verdict is served from the latch's own cooldown-bounded memo, not just on a
|
|
157
|
+
* fresh probe (#1585).
|
|
158
|
+
*
|
|
159
|
+
* Before this, the return type was a bare boolean: a caller like
|
|
160
|
+
* `allAvailableGlobalBinDirs` could not tell "pnpm isn't installed" from
|
|
161
|
+
* "the `where pnpm` probe stalled", so a transient miss silently dropped
|
|
162
|
+
* pnpm's global bin dir with no way to flag the result as provisional —
|
|
163
|
+
* exactly the boolean-collapse `getToolPath`'s `onTransient` plumbing (#1569)
|
|
164
|
+
* was built to avoid, one layer up.
|
|
165
|
+
*/
|
|
166
|
+
function isAvailable(pm, onTransient) {
|
|
167
|
+
const latch = getLatch(pm);
|
|
168
|
+
const reportIfTransient = (result) => {
|
|
169
|
+
if (!result && isTransientDecision({ outcome: latch.getOutcome() })) {
|
|
170
|
+
onTransient?.();
|
|
171
|
+
}
|
|
172
|
+
return result;
|
|
173
|
+
};
|
|
174
|
+
const memo = latch.read();
|
|
175
|
+
if (memo !== null)
|
|
176
|
+
return Promise.resolve(reportIfTransient(memo));
|
|
177
|
+
// A verdict can now expire, so concurrent callers arriving just after a
|
|
178
|
+
// cooldown must share ONE probe rather than each spawning their own.
|
|
179
|
+
const inFlight = inFlightProbes.get(pm);
|
|
180
|
+
if (inFlight)
|
|
181
|
+
return inFlight.then(reportIfTransient);
|
|
182
|
+
// #1653 review F1: a probe started before a session reset can settle AFTER
|
|
183
|
+
// a later session's own probe for the same manager is already in flight.
|
|
184
|
+
// An unconditional delete-by-key would evict that NEWER entry out from
|
|
185
|
+
// under it, so a third caller in the gap finds nothing in-flight and
|
|
186
|
+
// spawns a duplicate. Only remove the entry if it is still THIS call's
|
|
187
|
+
// promise — the same identity guard `resolveMadge` uses in
|
|
188
|
+
// dependency-checker.ts for the equivalent race.
|
|
189
|
+
const probe = probeAvailability(pm).finally(() => {
|
|
190
|
+
if (inFlightProbes.get(pm) === probe)
|
|
191
|
+
inFlightProbes.delete(pm);
|
|
192
|
+
});
|
|
193
|
+
inFlightProbes.set(pm, probe);
|
|
194
|
+
return probe.then(reportIfTransient);
|
|
83
195
|
}
|
|
84
|
-
/**
|
|
196
|
+
/**
|
|
197
|
+
* Clear the process-wide availability cache: pnpm/yarn/bun/npm each sit
|
|
198
|
+
* behind their own module-local `AvailabilityLatch` in `availabilityLatches`,
|
|
199
|
+
* so `resetDispatchAvailabilityState`'s generation counter (the mechanism
|
|
200
|
+
* most dispatch runners inherit) never reaches them — the same shape as
|
|
201
|
+
* psscriptanalyzer's (#1490) and zizmor's (#1535) module-local latches.
|
|
202
|
+
* Without this wired into `session_start`, a genuine "pnpm is missing"
|
|
203
|
+
* verdict from one session stayed latched into the next: install pnpm mid
|
|
204
|
+
* day, start a fresh session, pi-lens still reports it missing until a
|
|
205
|
+
* process restart (#1653). Called from `handleSessionStart`'s per-session
|
|
206
|
+
* reset block beside `resetZizmorTokenAvailability()` /
|
|
207
|
+
* `resetPsScriptAnalyzerAvailability()`; also used directly by tests.
|
|
208
|
+
*/
|
|
85
209
|
export function _resetPackageManagerCache() {
|
|
86
|
-
|
|
210
|
+
availabilityLatches.clear();
|
|
211
|
+
inFlightProbes.clear();
|
|
87
212
|
}
|
|
88
213
|
// ============================================================================
|
|
89
214
|
// RESOLUTION
|
|
@@ -134,6 +259,24 @@ export function installArgs(pm, pkg, options = {}) {
|
|
|
134
259
|
args.push(pkg);
|
|
135
260
|
return args;
|
|
136
261
|
}
|
|
262
|
+
/**
|
|
263
|
+
* Args to re-resolve an already-declared dependency to the newest version its
|
|
264
|
+
* recorded range still permits. npm/pnpm/bun spell this `update`; yarn classic
|
|
265
|
+
* spells it `upgrade`.
|
|
266
|
+
*
|
|
267
|
+
* This is the command that repairs a dependency frozen by its own lockfile.
|
|
268
|
+
* `installArgs` re-runs the install, and a lockfile entry that already
|
|
269
|
+
* satisfies the range makes that a no-op: pi-lens's managed tools tree stayed
|
|
270
|
+
* on the version written at first install for the life of the machine even
|
|
271
|
+
* though the declared caret range permitted 28 newer minors (#1730).
|
|
272
|
+
*/
|
|
273
|
+
export function updateArgs(pm, pkg, options = {}) {
|
|
274
|
+
const args = [pm === "yarn" ? "upgrade" : "update"];
|
|
275
|
+
if (options.ignoreScripts)
|
|
276
|
+
args.push("--ignore-scripts");
|
|
277
|
+
args.push(pkg);
|
|
278
|
+
return args;
|
|
279
|
+
}
|
|
137
280
|
/**
|
|
138
281
|
* Args to install a single package **globally** (`-g`). npm/pnpm/bun spell this
|
|
139
282
|
* `install -g` / `add -g`; yarn uses `global add` (yarn classic — Berry removed
|
|
@@ -204,12 +347,18 @@ async function globalBinDirsFor(pm) {
|
|
|
204
347
|
* Global bin directories for every installed manager, deduped. Used to locate a
|
|
205
348
|
* globally-installed tool binary when PATH is stale (e.g. right after an
|
|
206
349
|
* `install -g`) or when the tool was installed via a non-npm manager.
|
|
350
|
+
*
|
|
351
|
+
* `onTransient`, when given, fires once per manager whose `isAvailable` probe
|
|
352
|
+
* was transient (stalled/unspawnable, not a genuine absence) — the boolean
|
|
353
|
+
* `allAvailableGlobalBinDirs` returns can't itself distinguish "not
|
|
354
|
+
* installed" from "couldn't tell", so a caller that persists this result
|
|
355
|
+
* needs the callback to know the answer may be incomplete (#1585).
|
|
207
356
|
*/
|
|
208
|
-
export async function allAvailableGlobalBinDirs() {
|
|
357
|
+
export async function allAvailableGlobalBinDirs(onTransient) {
|
|
209
358
|
const dirs = [];
|
|
210
359
|
const seen = new Set();
|
|
211
360
|
for (const pm of PREFERENCE) {
|
|
212
|
-
if (!(await isAvailable(pm)))
|
|
361
|
+
if (!(await isAvailable(pm, onTransient)))
|
|
213
362
|
continue;
|
|
214
363
|
for (const dir of await globalBinDirsFor(pm)) {
|
|
215
364
|
const normalized = path.resolve(dir);
|
|
@@ -251,8 +400,15 @@ export async function findGlobalBinary(command, windowsExt = ".cmd") {
|
|
|
251
400
|
}
|
|
252
401
|
return undefined;
|
|
253
402
|
}
|
|
254
|
-
/**
|
|
255
|
-
|
|
403
|
+
/**
|
|
404
|
+
* Local `node_modules/.bin/<tool>` walking up from `startDir` to the fs root.
|
|
405
|
+
*
|
|
406
|
+
* Exported so callers that must NOT pay for global-bin discovery can reuse this
|
|
407
|
+
* walk instead of copying it. `findNodeToolBinary` below adds `findGlobalBinary`,
|
|
408
|
+
* which spawns a probe per package manager; a caller resolving a command on
|
|
409
|
+
* every run (knip, #1721) needs the filesystem half only.
|
|
410
|
+
*/
|
|
411
|
+
export function findLocalBinUpwards(tool, startDir, windowsExt = ".cmd") {
|
|
256
412
|
const names = onWindows() ? [`${tool}${windowsExt}`, tool] : [tool];
|
|
257
413
|
let dir = path.resolve(startDir);
|
|
258
414
|
const root = path.parse(dir).root;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { logLatency } from "./latency-logger.js";
|
|
2
|
+
// Verified guesses are expected host behavior, not degradations. Keep their
|
|
3
|
+
// exact session count in memory and publish one bounded row at session end.
|
|
4
|
+
// This tally is intentionally memory-only: a process crash loses its count.
|
|
5
|
+
// The rollup is best-effort session telemetry, not durable accounting.
|
|
6
|
+
let verifiedGuessCount = 0;
|
|
7
|
+
export function recordVerifiedPathAttributionGuess() {
|
|
8
|
+
verifiedGuessCount += 1;
|
|
9
|
+
}
|
|
10
|
+
export function getVerifiedPathAttributionGuessCount() {
|
|
11
|
+
return verifiedGuessCount;
|
|
12
|
+
}
|
|
13
|
+
export function emitVerifiedPathAttributionRollup(filePath) {
|
|
14
|
+
if (verifiedGuessCount === 0)
|
|
15
|
+
return;
|
|
16
|
+
logLatency({
|
|
17
|
+
type: "phase",
|
|
18
|
+
phase: "path_attribution_verified_rollup",
|
|
19
|
+
filePath,
|
|
20
|
+
durationMs: 0,
|
|
21
|
+
metadata: { count: verifiedGuessCount },
|
|
22
|
+
});
|
|
23
|
+
verifiedGuessCount = 0;
|
|
24
|
+
}
|
|
25
|
+
export function resetVerifiedPathAttributionGuessCount() {
|
|
26
|
+
verifiedGuessCount = 0;
|
|
27
|
+
}
|
|
@@ -452,3 +452,163 @@ export function direntsHaveMarkerGlobMatch(entries, pattern) {
|
|
|
452
452
|
return entries.some((entry) => (entry.isFile() || entry.isSymbolicLink()) &&
|
|
453
453
|
nameMatchesMarkerGlob(entry.name, pattern));
|
|
454
454
|
}
|
|
455
|
+
/**
|
|
456
|
+
* Narrow no-break space, U+202F. macOS writes it before AM/PM in screenshot
|
|
457
|
+
* file names; users type an ordinary space.
|
|
458
|
+
*/
|
|
459
|
+
const NARROW_NO_BREAK_SPACE = "\u202F";
|
|
460
|
+
/** Right single quotation mark, U+2019. macOS writes it; users type U+0027. */
|
|
461
|
+
const RIGHT_SINGLE_QUOTE = "\u2019";
|
|
462
|
+
/**
|
|
463
|
+
* The unicode space class pi folds to U+0020, copied character-for-character
|
|
464
|
+
* from `@earendil-works/pi-coding-agent/dist/utils/paths.js:6`
|
|
465
|
+
* (`UNICODE_SPACES`, source `src/utils/paths.ts`). Widening or narrowing this
|
|
466
|
+
* set makes pi-lens resolve a different file than pi does.
|
|
467
|
+
*/
|
|
468
|
+
const HOST_UNICODE_SPACES = /[\u00A0\u2000-\u200A\u202F\u205F\u3000]/g;
|
|
469
|
+
/**
|
|
470
|
+
* Mirror pi's `normalizeWindowsShellPath`
|
|
471
|
+
* (`@earendil-works/pi-coding-agent/dist/utils/paths.js:47-56`): convert Git
|
|
472
|
+
* Bash, MSYS, Cygwin, and WSL drive paths to a form native Windows APIs
|
|
473
|
+
* accept.
|
|
474
|
+
*/
|
|
475
|
+
function hostNormalizeWindowsShellPath(filePath) {
|
|
476
|
+
if (!filePath.startsWith("/") ||
|
|
477
|
+
filePath.startsWith("//") ||
|
|
478
|
+
filePath.includes("\\")) {
|
|
479
|
+
return filePath;
|
|
480
|
+
}
|
|
481
|
+
const match = filePath.match(/^\/(?:mnt\/|cygdrive\/)?([a-z])(?:\/(.*))?$/i);
|
|
482
|
+
if (!match)
|
|
483
|
+
return filePath;
|
|
484
|
+
const suffix = match[2]?.replaceAll("/", "\\");
|
|
485
|
+
return `${match[1].toUpperCase()}:\\${suffix ?? ""}`;
|
|
486
|
+
}
|
|
487
|
+
/**
|
|
488
|
+
* Mirror pi's `normalizePath`
|
|
489
|
+
* (`@earendil-works/pi-coding-agent/dist/utils/paths.js:57-79`, source
|
|
490
|
+
* `src/utils/paths.ts`), in pi's order, which is load-bearing: the unicode
|
|
491
|
+
* fold runs BEFORE the `@` strip, and the tilde expansion before the
|
|
492
|
+
* `file://` conversion.
|
|
493
|
+
*
|
|
494
|
+
* The `win32` step is gated on `process.platform`, exactly as pi gates it.
|
|
495
|
+
* This is a deliberate exception to the usual probe-the-filesystem rule
|
|
496
|
+
* (AGENTS.md shape 2): pi-lens runs in pi's own process, so mirroring the
|
|
497
|
+
* host's own platform branch is what keeps the two resolvers in agreement.
|
|
498
|
+
* Shape-based parsing here would DIVERGE from the host, not protect against
|
|
499
|
+
* it.
|
|
500
|
+
*/
|
|
501
|
+
export function normalizeHostToolPath(input, options = {}) {
|
|
502
|
+
let normalized = input;
|
|
503
|
+
if (options.normalizeUnicodeSpaces) {
|
|
504
|
+
normalized = normalized.replace(HOST_UNICODE_SPACES, " ");
|
|
505
|
+
}
|
|
506
|
+
if (options.stripAtPrefix && normalized.startsWith("@")) {
|
|
507
|
+
normalized = normalized.slice(1);
|
|
508
|
+
}
|
|
509
|
+
if (process.platform === "win32") {
|
|
510
|
+
normalized = hostNormalizeWindowsShellPath(normalized);
|
|
511
|
+
}
|
|
512
|
+
// `homedir()` is resolved inside the branch, as pi does. This runs on every
|
|
513
|
+
// tool_call and a `~` path is the rare case.
|
|
514
|
+
if (normalized === "~")
|
|
515
|
+
return os.homedir();
|
|
516
|
+
if (normalized.startsWith("~/") ||
|
|
517
|
+
(process.platform === "win32" && normalized.startsWith("~\\"))) {
|
|
518
|
+
return path.join(os.homedir(), normalized.slice(2));
|
|
519
|
+
}
|
|
520
|
+
if (/^file:\/\//.test(normalized)) {
|
|
521
|
+
try {
|
|
522
|
+
return fileURLToPath(normalized);
|
|
523
|
+
}
|
|
524
|
+
catch {
|
|
525
|
+
// pi lets a malformed file: URL throw out of normalizePath, but pi-lens
|
|
526
|
+
// is advisory instrumentation on the same event: a URL pi rejects must
|
|
527
|
+
// degrade to "no path" here, never take down the tool_call handler.
|
|
528
|
+
return normalized;
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
return normalized;
|
|
532
|
+
}
|
|
533
|
+
/**
|
|
534
|
+
* Mirror pi's `resolveToCwd`
|
|
535
|
+
* (`@earendil-works/pi-coding-agent/dist/core/tools/path-utils.js:42-44`,
|
|
536
|
+
* source `src/core/tools/path-utils.ts:~44-46`) \u2014 the BASE resolution every
|
|
537
|
+
* read/edit/write path goes through before the variant ladder below ever
|
|
538
|
+
* runs.
|
|
539
|
+
*
|
|
540
|
+
* Two details are pi's, not ours, and both matter:
|
|
541
|
+
* - the input is normalized with `normalizeUnicodeSpaces` + `stripAtPrefix`;
|
|
542
|
+
* the BASE DIR is normalized with neither (`resolvePath`,
|
|
543
|
+
* `dist/utils/paths.js:80-84`).
|
|
544
|
+
* - an already-absolute input is re-resolved on its own, ignoring the cwd.
|
|
545
|
+
*/
|
|
546
|
+
export function resolveHostToolPath(input, baseDir) {
|
|
547
|
+
const normalized = normalizeHostToolPath(input, {
|
|
548
|
+
normalizeUnicodeSpaces: true,
|
|
549
|
+
stripAtPrefix: true,
|
|
550
|
+
});
|
|
551
|
+
const normalizedBaseDir = normalizeHostToolPath(baseDir);
|
|
552
|
+
return path.isAbsolute(normalized)
|
|
553
|
+
? path.resolve(normalized)
|
|
554
|
+
: path.resolve(normalizedBaseDir, normalized);
|
|
555
|
+
}
|
|
556
|
+
/**
|
|
557
|
+
* Mirror pi's read-path fallback ladder (#1655 item 5).
|
|
558
|
+
*
|
|
559
|
+
* pi does NOT open `resolve(cwd, input.path)`. `resolveReadPath`
|
|
560
|
+
* (`@earendil-works/pi-coding-agent/dist/core/tools/path-utils.js:45-70`,
|
|
561
|
+
* source `src/core/tools/path-utils.ts:52-83`) resolves, and when that path
|
|
562
|
+
* does not exist it silently retries four unicode/spacing variants in this
|
|
563
|
+
* exact order:
|
|
564
|
+
*
|
|
565
|
+
* 1. narrow no-break space before `AM.`/`PM.` (`tryMacOSScreenshotPath`)
|
|
566
|
+
* 2. NFD normalization (`tryNFDVariant`) — macOS stores names decomposed
|
|
567
|
+
* 3. U+0027 → U+2019 (`tryCurlyQuoteVariant`)
|
|
568
|
+
* 4. NFD + curly quote combined
|
|
569
|
+
*
|
|
570
|
+
* Each candidate is used only when it DIFFERS from the resolved path and the
|
|
571
|
+
* file exists; otherwise pi falls back to the resolved path. So the file pi
|
|
572
|
+
* actually read can differ from what a naive `path.resolve` produces, and
|
|
573
|
+
* pi-lens keyed its read guard, LSP touch, and dispatch off the naive form —
|
|
574
|
+
* silently doing nothing for exactly those files.
|
|
575
|
+
*
|
|
576
|
+
* Order matters: it is pi's, so pi-lens picks the same file pi did when more
|
|
577
|
+
* than one variant happens to exist.
|
|
578
|
+
*
|
|
579
|
+
* @param resolvedPath an already-resolved absolute path (the naive form)
|
|
580
|
+
* @param fileExists injectable existence probe; defaults to `existsSync`
|
|
581
|
+
*/
|
|
582
|
+
export function resolveHostPathVariants(resolvedPath, fileExists = existsSync) {
|
|
583
|
+
if (fileExists(resolvedPath)) {
|
|
584
|
+
return { path: resolvedPath, unresolved: false, triedVariants: [] };
|
|
585
|
+
}
|
|
586
|
+
const nfd = resolvedPath.normalize("NFD");
|
|
587
|
+
const candidates = [
|
|
588
|
+
{
|
|
589
|
+
variant: "narrow-nbsp",
|
|
590
|
+
candidate: resolvedPath.replace(/ (AM|PM)\./gi, `${NARROW_NO_BREAK_SPACE}$1.`),
|
|
591
|
+
},
|
|
592
|
+
{ variant: "nfd", candidate: nfd },
|
|
593
|
+
{
|
|
594
|
+
variant: "curly-quote",
|
|
595
|
+
candidate: resolvedPath.replaceAll("'", RIGHT_SINGLE_QUOTE),
|
|
596
|
+
},
|
|
597
|
+
{
|
|
598
|
+
variant: "nfd-curly-quote",
|
|
599
|
+
candidate: nfd.replaceAll("'", RIGHT_SINGLE_QUOTE),
|
|
600
|
+
},
|
|
601
|
+
];
|
|
602
|
+
const triedVariants = [];
|
|
603
|
+
for (const { variant, candidate } of candidates) {
|
|
604
|
+
// pi skips a candidate identical to the resolved path, so pi-lens does
|
|
605
|
+
// too — otherwise a no-op "variant" would be reported as a match.
|
|
606
|
+
if (candidate === resolvedPath)
|
|
607
|
+
continue;
|
|
608
|
+
triedVariants.push(variant);
|
|
609
|
+
if (fileExists(candidate)) {
|
|
610
|
+
return { path: candidate, variant, unresolved: false, triedVariants };
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
return { path: resolvedPath, unresolved: true, triedVariants };
|
|
614
|
+
}
|