@herbertgao/pi-extensions 2026.8.5 → 2026.8.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +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 +272 -22
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/context.ts +74 -5
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/compact-mode.ts +94 -77
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/markdown-enhance.ts +48 -6
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/message-display.ts +1 -1
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/hover.ts +14 -0
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/interaction.ts +55 -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 +16 -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 +22 -15
- 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 +34 -10
- package/node_modules/@herbertgao/pi-subagents/src/usage.ts +129 -1
- package/node_modules/@herbertgao/pi-subagents/src/worktree.ts +29 -5
- package/node_modules/@juicesharp/rpiv-ask-user-question/README.md +3 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/ask-user-question.ts +46 -10
- 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 +8 -1
- package/node_modules/@juicesharp/rpiv-ask-user-question/docs/localization.md +3 -1
- package/node_modules/@juicesharp/rpiv-ask-user-question/locales/en.json +2 -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 +3 -1
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/questionnaire-session.ts +30 -7
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/state.ts +14 -6
- package/node_modules/@juicesharp/rpiv-ask-user-question/view/dialog-builder.ts +30 -4
- package/node_modules/@juicesharp/rpiv-ask-user-question/view/tab-content-strategy.ts +26 -5
- package/node_modules/@narumitw/pi-btw/README.md +119 -103
- 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 +13 -9
- package/node_modules/@narumitw/pi-btw/src/btw.ts +40 -42
- 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 +78 -15
- package/node_modules/@narumitw/pi-btw/src/settings.ts +22 -2
- package/node_modules/@narumitw/pi-btw/src/transcript-pager.ts +136 -45
- package/node_modules/pi-lens/CHANGELOG.md +1004 -0
- package/node_modules/pi-lens/README.md +11 -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 +427 -0
- package/node_modules/pi-lens/dist/clients/agent-nudge.js +79 -16
- 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 +285 -8
- package/node_modules/pi-lens/dist/clients/biome-client.js +176 -37
- package/node_modules/pi-lens/dist/clients/blocker-freshness.js +428 -0
- package/node_modules/pi-lens/dist/clients/blocker-past-eof.js +119 -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 +192 -0
- package/node_modules/pi-lens/dist/clients/bus-events-logger.js +62 -6
- package/node_modules/pi-lens/dist/clients/bus-publish.js +11 -3
- package/node_modules/pi-lens/dist/clients/cascade-budget.js +196 -0
- package/node_modules/pi-lens/dist/clients/cascade-format.js +76 -2
- 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/console-guard-install.js +16 -4
- package/node_modules/pi-lens/dist/clients/dead-code-client.js +249 -52
- 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 +62 -13
- package/node_modules/pi-lens/dist/clients/dependency-checker.js +43 -9
- package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +153 -37
- package/node_modules/pi-lens/dist/clients/diagnostic-line-freshness.js +298 -0
- package/node_modules/pi-lens/dist/clients/diagnostics-publish.js +10 -3
- package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +165 -11
- package/node_modules/pi-lens/dist/clients/dispatch/integration.js +325 -72
- 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/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/helm-render.js +895 -0
- 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 +81 -41
- package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +16 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/mypy.js +23 -0
- 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 +14 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/sqlfluff.js +20 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/stylelint.js +22 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/swiftlint.js +10 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/taplo.js +18 -6
- 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 +488 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/candidate-probe.js +84 -0
- 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 +943 -93
- 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 +72 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/toolchain-availability.js +106 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/vale.js +9 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/yamllint.js +18 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/zig-check.js +4 -2
- package/node_modules/pi-lens/dist/clients/disposition-publish.js +10 -3
- package/node_modules/pi-lens/dist/clients/eval-timestamp.js +17 -0
- package/node_modules/pi-lens/dist/clients/event-loop-monitor.js +28 -5
- package/node_modules/pi-lens/dist/clients/extension-log.js +317 -3
- package/node_modules/pi-lens/dist/clients/file-kinds.js +8 -2
- package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +294 -0
- package/node_modules/pi-lens/dist/clients/finding-identity.js +88 -0
- package/node_modules/pi-lens/dist/clients/fix-worklog.js +5 -1
- package/node_modules/pi-lens/dist/clients/format-events-publish.js +39 -8
- 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 +49 -21
- package/node_modules/pi-lens/dist/clients/gitleaks-client.js +181 -8
- package/node_modules/pi-lens/dist/clients/go-client.js +21 -39
- package/node_modules/pi-lens/dist/clients/govulncheck-client.js +219 -10
- package/node_modules/pi-lens/dist/clients/grammar-source.js +333 -10
- package/node_modules/pi-lens/dist/clients/host-ports.js +9 -1
- package/node_modules/pi-lens/dist/clients/installer/index.js +1119 -101
- 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 +86 -15
- package/node_modules/pi-lens/dist/clients/knip-client.js +361 -24
- package/node_modules/pi-lens/dist/clients/language-policy.js +8 -2
- package/node_modules/pi-lens/dist/clients/language-profile.js +2 -0
- package/node_modules/pi-lens/dist/clients/latency-logger.js +487 -9
- 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-events.js +56 -25
- package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +16 -0
- package/node_modules/pi-lens/dist/clients/live-bus-emitter.js +45 -2
- package/node_modules/pi-lens/dist/clients/lsp/aggregation.js +30 -4
- package/node_modules/pi-lens/dist/clients/lsp/cascade-tier.js +160 -20
- package/node_modules/pi-lens/dist/clients/lsp/client.js +1666 -148
- package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +111 -0
- package/node_modules/pi-lens/dist/clients/lsp/document-drift.js +389 -0
- package/node_modules/pi-lens/dist/clients/lsp/index.js +2496 -171
- 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 +517 -69
- 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 +172 -0
- package/node_modules/pi-lens/dist/clients/lsp/wait-policy/classification.js +21 -5
- package/node_modules/pi-lens/dist/clients/lsp/wait-policy/strategies.js +61 -3
- 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/analyze.js +4 -0
- package/node_modules/pi-lens/dist/clients/mcp/session.js +39 -18
- package/node_modules/pi-lens/dist/clients/model-provider.js +53 -0
- package/node_modules/pi-lens/dist/clients/module-report.js +8 -0
- 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 +178 -30
- 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 +85 -15
- 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/runner-findings.js +23 -2
- 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 +5 -0
- package/node_modules/pi-lens/dist/clients/project-lens-config.js +3 -0
- 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 +1 -1
- package/node_modules/pi-lens/dist/clients/read-guard.js +184 -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/query.js +76 -4
- package/node_modules/pi-lens/dist/clients/run-duration.js +55 -0
- package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +248 -13
- package/node_modules/pi-lens/dist/clients/runtime-context.js +112 -12
- package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +472 -61
- package/node_modules/pi-lens/dist/clients/runtime-session.js +359 -13
- package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +217 -22
- package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +269 -22
- package/node_modules/pi-lens/dist/clients/runtime-turn.js +948 -87
- package/node_modules/pi-lens/dist/clients/rust-client.js +21 -37
- 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 +224 -8
- package/node_modules/pi-lens/dist/clients/sg-runner.js +249 -37
- package/node_modules/pi-lens/dist/clients/single-flight.js +158 -0
- package/node_modules/pi-lens/dist/clients/smells-rollup.js +18 -11
- package/node_modules/pi-lens/dist/clients/stale-marker.js +17 -0
- package/node_modules/pi-lens/dist/clients/startup-timing.js +26 -2
- package/node_modules/pi-lens/dist/clients/test-runner-client.js +574 -32
- package/node_modules/pi-lens/dist/clients/tool-event.js +56 -5
- package/node_modules/pi-lens/dist/clients/tool-policy.js +127 -20
- package/node_modules/pi-lens/dist/clients/tool-set-policy.js +76 -0
- 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-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/warm-attach.js +17 -0
- package/node_modules/pi-lens/dist/clients/widget-state.js +336 -36
- package/node_modules/pi-lens/dist/clients/word-index.js +305 -33
- package/node_modules/pi-lens/dist/clients/zizmor-config.js +214 -14
- package/node_modules/pi-lens/dist/index.js +64677 -49484
- package/node_modules/pi-lens/dist/mcp/server.js +8 -2
- package/node_modules/pi-lens/dist/tools/activate-tools.js +17 -5
- package/node_modules/pi-lens/dist/tools/ast-grep-replace.js +9 -4
- package/node_modules/pi-lens/dist/tools/lens-diagnostic-mark.js +5 -2
- package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +469 -56
- package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +190 -46
- package/node_modules/pi-lens/dist/tools/lsp-navigation.js +46 -7
- package/node_modules/pi-lens/dist/tools/symbol-search.js +1 -1
- package/node_modules/pi-lens/docs/agent-guide.md +44 -14
- package/node_modules/pi-lens/docs/ast-grep_rules_catalog.md +518 -501
- package/node_modules/pi-lens/docs/dispositions.md +21 -0
- package/node_modules/pi-lens/docs/features.md +33 -6
- package/node_modules/pi-lens/docs/globalconfig.md +14 -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 +25 -1
- package/node_modules/pi-lens/docs/usage.md +24 -5
- package/node_modules/pi-lens/docs/word-index.md +35 -0
- package/node_modules/pi-lens/package.json +10 -6
- 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 +22 -0
- 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-conditional-empty-object-spread-js-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-conditional-empty-object-spread-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-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 +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-js-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-test.yml +9 -0
- 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-laundering-test.yml +11 -0
- 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 +66 -0
- 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-conditional-empty-object-spread-js.yml +21 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-conditional-empty-object-spread.yml +29 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-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 +29 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply.yml +30 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get-js.yml +41 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get.yml +42 -0
- 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 +32 -0
- 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 +132 -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/skills/pi-lens-ast-grep/SKILL.md +12 -11
- package/node_modules/pi-lens/skills/pi-lens-lsp-navigation/SKILL.md +22 -22
- package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/SKILL.md +87 -116
- package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/reference.md +170 -0
- package/node_modules/pi-lens/skills/pi-lens-write-tree-sitter-rule/SKILL.md +3 -1
- package/node_modules/pi-lens/vendor/grammars/tree-sitter-cue.wasm +0 -0
- package/node_modules/pi-mcp-adapter/CHANGELOG.md +49 -0
- package/node_modules/pi-mcp-adapter/README.md +51 -6
- package/node_modules/pi-mcp-adapter/agent-dir.ts +12 -4
- package/node_modules/pi-mcp-adapter/cli.js +188 -5
- package/node_modules/pi-mcp-adapter/commands.ts +128 -22
- package/node_modules/pi-mcp-adapter/config.ts +28 -10
- package/node_modules/pi-mcp-adapter/direct-tools.ts +23 -19
- 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/mcp-setup-panel.ts +2 -1
- package/node_modules/pi-mcp-adapter/metadata-cache.ts +46 -25
- package/node_modules/pi-mcp-adapter/package-mcp-loader.ts +168 -0
- package/node_modules/pi-mcp-adapter/package.json +4 -1
- package/node_modules/pi-mcp-adapter/proxy-modes.ts +5 -4
- package/node_modules/pi-mcp-adapter/request-headers-command.ts +330 -0
- package/node_modules/pi-mcp-adapter/search-ranking.ts +92 -22
- package/node_modules/pi-mcp-adapter/server-manager.ts +145 -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-metadata.ts +38 -18
- package/node_modules/pi-mcp-adapter/tool-result-renderer.ts +44 -4
- package/node_modules/pi-mcp-adapter/types.ts +95 -10
- 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 +38 -14
- package/node_modules/pi-web-access/anysearch.ts +4 -2
- package/node_modules/pi-web-access/auth-fetch.ts +148 -0
- package/node_modules/pi-web-access/brave.ts +16 -4
- package/node_modules/pi-web-access/chrome-cookies.ts +110 -23
- package/node_modules/pi-web-access/curator-page.ts +8 -3
- package/node_modules/pi-web-access/curator-server.ts +5 -1
- package/node_modules/pi-web-access/exa.ts +18 -7
- package/node_modules/pi-web-access/extract.ts +134 -37
- package/node_modules/pi-web-access/fetch-params.ts +17 -3
- package/node_modules/pi-web-access/firecrawl.ts +172 -12
- package/node_modules/pi-web-access/gemini-search.ts +33 -7
- package/node_modules/pi-web-access/index.ts +160 -104
- package/node_modules/pi-web-access/package.json +2 -2
- 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/query-rewrite.ts +51 -0
- package/node_modules/pi-web-access/serper.ts +211 -0
- package/node_modules/pi-web-access/summary-model-scope.ts +12 -4
- package/node_modules/pi-web-access/summary-review.ts +51 -23
- 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/node_modules/pi-web-access/youtube-extract.ts +2 -2
- package/package.json +13 -13
|
@@ -1,41 +1,274 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one lazy-install seam (#1537).
|
|
3
|
+
*
|
|
4
|
+
* Best-effort installs of language-specific tools, triggered when a runner or a
|
|
5
|
+
* formatter finds its tool absent. There were two copies of this — the
|
|
6
|
+
* `attempted` Set here and `formatters.ts`'s `_lazyInstallAttempts` — and both
|
|
7
|
+
* carried the same defect: the key went in BEFORE the install ran and never came
|
|
8
|
+
* out. A `gem install rubocop` that died on a network blip was therefore never
|
|
9
|
+
* retried for the rest of the session, and the tool stayed skipped.
|
|
10
|
+
*
|
|
11
|
+
* The guard itself is right, and it stays: an install storm is worse than a
|
|
12
|
+
* missed install, and these spawns are up to 3 minutes each. What was wrong is
|
|
13
|
+
* that a transient failure and a genuine refusal were recorded identically, with
|
|
14
|
+
* no expiry on either. So the record is now written AFTER the install, and it
|
|
15
|
+
* carries the outcome:
|
|
16
|
+
*
|
|
17
|
+
* * `succeeded` — nothing more to do this session.
|
|
18
|
+
* * `failed`, transient (timed out, killed, EAGAIN) — retried after a
|
|
19
|
+
* cooldown, at most LAZY_INSTALL_MAX_TRANSIENT_ATTEMPTS times, then held.
|
|
20
|
+
* * `failed`, durable (the package MANAGER is not on this machine) — held for
|
|
21
|
+
* the session. No cooldown can conjure a `gem`.
|
|
22
|
+
*
|
|
23
|
+
* The vocabulary is #1534's `InstallAttemptFact`, so `describeInstallAttempt`
|
|
24
|
+
* turns this record straight into the `availability_decision` install evidence
|
|
25
|
+
* (#1500) — which is what makes "we tried and the network failed" tellable from
|
|
26
|
+
* "this tool cannot be installed here".
|
|
27
|
+
*
|
|
28
|
+
* A trust denial is deliberately NOT recorded: `assertInstallAllowed` is
|
|
29
|
+
* re-evaluated per call and a later grant must retry (#1350).
|
|
30
|
+
*/
|
|
1
31
|
import { safeSpawnAsync } from "../../../safe-spawn.js";
|
|
2
32
|
import { assertInstallAllowed } from "../../../project-trust.js";
|
|
3
|
-
|
|
33
|
+
import { logExtension } from "../../../extension-log.js";
|
|
34
|
+
import { classifyProbeFailure, installRetryDelayMs, } from "./availability-policy.js";
|
|
35
|
+
/**
|
|
36
|
+
* What each install actually runs. Every one of these is a MACHINE-GLOBAL
|
|
37
|
+
* mutation — `gem install rubocop` and `rustup component add` write to the
|
|
38
|
+
* user's gem/toolchain root, not into `cwd` — which is why the hold is shared
|
|
39
|
+
* across seams rather than being per caller (#1537 review F4). A runner and a
|
|
40
|
+
* formatter asking for the same `gem install rubocop` are asking for the same
|
|
41
|
+
* one thing; the second must be suppressed, not run again.
|
|
42
|
+
*/
|
|
43
|
+
// golangci-lint deliberately has no entry here: it auto-installs through the
|
|
44
|
+
// shared TOOL_EXECUTION_POLICY seam instead (`resolveAvailableOrInstall` +
|
|
45
|
+
// `ensureTool` in clients/dispatch/runners/utils/runner-helpers.ts, wired in
|
|
46
|
+
// golangci-lint.ts). A "golangci-lint" arm briefly lived in this map with no
|
|
47
|
+
// caller reaching it through EITHER `tryLazyInstall` or
|
|
48
|
+
// `tryLazyInstallForFormatter` — dead since introduction (#1572 sweep).
|
|
49
|
+
const LAZY_INSTALL_SPECS = {
|
|
50
|
+
rubocop: { command: "gem", args: ["install", "rubocop", "--no-document"] },
|
|
51
|
+
"rust-clippy": { command: "rustup", args: ["component", "add", "clippy"] },
|
|
52
|
+
rustfmt: { command: "rustup", args: ["component", "add", "rustfmt"] },
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* Every lazy install ignores an ambient cancellation.
|
|
56
|
+
*
|
|
57
|
+
* The two merged copies disagreed — the formatter one opted in, the runner one
|
|
58
|
+
* did not — and keeping that difference per CALLER while the two share a hold
|
|
59
|
+
* made the cancellation semantics first-caller-wins: whether a `gem install`
|
|
60
|
+
* could be killed mid-write depended on which seam happened to reach it first
|
|
61
|
+
* (#1537 review F4). Nondeterminism is the worse of the two options, so the
|
|
62
|
+
* property belongs to the tool.
|
|
63
|
+
*
|
|
64
|
+
* `true` is the safe direction and the one the newer copy already chose: a
|
|
65
|
+
* half-finished `gem install` or `rustup component add` leaves a broken
|
|
66
|
+
* toolchain, whereas letting it finish costs at most the spawn's own budget
|
|
67
|
+
* below. This is a deliberate behaviour change for the runner seam.
|
|
68
|
+
*/
|
|
69
|
+
const LAZY_INSTALL_IGNORES_AMBIENT_SIGNAL = true;
|
|
70
|
+
const LAZY_INSTALL_TIMEOUT_MS = 180_000;
|
|
71
|
+
const attempts = new Map();
|
|
4
72
|
function key(cwd, tool) {
|
|
5
73
|
return `${cwd}:${tool}`;
|
|
6
74
|
}
|
|
7
75
|
/**
|
|
8
|
-
*
|
|
76
|
+
* What the last lazy install for this tool+cwd did, in #1534's vocabulary.
|
|
9
77
|
*
|
|
10
|
-
*
|
|
78
|
+
* Feed it to `describeInstallAttempt` to put the install evidence beside the
|
|
79
|
+
* availability verdict it produced. `undefined` means nothing was attempted,
|
|
80
|
+
* which `describeInstallAttempt` renders as `not-attempted` rather than
|
|
81
|
+
* inventing a failure.
|
|
11
82
|
*/
|
|
12
|
-
export
|
|
13
|
-
|
|
14
|
-
|
|
83
|
+
export function getLazyInstallAttempt(tool, cwd) {
|
|
84
|
+
return attempts.get(key(cwd, tool))?.fact;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Drop every lazy-install verdict, so the next call may try again.
|
|
88
|
+
*
|
|
89
|
+
* Called from `session_start`'s per-session reset block in `runtime-session.ts`,
|
|
90
|
+
* beside `resetInstallRetryLatches()` (#1497) — and from NOWHERE else.
|
|
91
|
+
*
|
|
92
|
+
* The boundary is the whole point (#1537 review F1). The first cut wired this
|
|
93
|
+
* into `clearFormatterRuntimeState()`, reasoning that it was "the session-reset
|
|
94
|
+
* path already wired". It is not: that runs from `resetFormatService()`, which
|
|
95
|
+
* `handleTurnEnd` calls every turn. So "held for the session" was held for a
|
|
96
|
+
* TURN — six turns against a missing `gem` meant six 180-second install spawns
|
|
97
|
+
* where the pre-fix bug managed one, the ladder never advanced, and the
|
|
98
|
+
* `InstallAttemptFact` was erased at the same moment. A hold too short is the
|
|
99
|
+
* #1497 storm; a hold too long is the #1494 permanent latch. Only the session
|
|
100
|
+
* boundary is correct, and only a test that drives the real `handleSessionStart`
|
|
101
|
+
* can prove this is wired to it (the #1266 lesson).
|
|
102
|
+
*/
|
|
103
|
+
export function resetLazyInstallAttempts() {
|
|
104
|
+
// Verdicts only. `inFlight` is concurrency bookkeeping, not session state:
|
|
105
|
+
// clearing it mid-install would let the next caller start a SECOND concurrent
|
|
106
|
+
// install of the same tool, which is the very thing it prevents. Its entries
|
|
107
|
+
// are removed by their own `finally`.
|
|
108
|
+
attempts.clear();
|
|
109
|
+
}
|
|
110
|
+
function suppressionFor(state) {
|
|
111
|
+
if (!state)
|
|
112
|
+
return null;
|
|
113
|
+
if (state.fact.outcome === "succeeded")
|
|
114
|
+
return "succeeded";
|
|
115
|
+
if (state.retryAtMs === 0)
|
|
116
|
+
return "held";
|
|
117
|
+
return Date.now() < state.retryAtMs ? "cooling" : null;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Installs currently running, so callers that arrive mid-install join the one in
|
|
121
|
+
* flight instead of starting another (#1537 review F3).
|
|
122
|
+
*
|
|
123
|
+
* The suppression check and the record write are separated by a spawn that can
|
|
124
|
+
* take three minutes, and the sequential storm-guard test could never see it:
|
|
125
|
+
* three concurrent callers each read "no record yet" and each spawned, the
|
|
126
|
+
* ladder counted a single failure for three installs, and whichever finished
|
|
127
|
+
* last overwrote the others' verdict — a stale success could bury a later
|
|
128
|
+
* failure. Keyed identically to `attempts`, and evicted in a `finally` so a
|
|
129
|
+
* rejection cannot leave a permanent phantom in-flight entry.
|
|
130
|
+
*/
|
|
131
|
+
const inFlight = new Map();
|
|
132
|
+
async function runLazyInstall(tool, cwd, spec) {
|
|
15
133
|
const k = key(cwd, tool);
|
|
16
|
-
|
|
134
|
+
const running = inFlight.get(k);
|
|
135
|
+
// Joining, not re-answering: both callers get the outcome of the install they
|
|
136
|
+
// actually waited for.
|
|
137
|
+
if (running)
|
|
138
|
+
return running;
|
|
139
|
+
const previous = attempts.get(k);
|
|
140
|
+
const suppressed = suppressionFor(previous);
|
|
141
|
+
if (suppressed !== null) {
|
|
142
|
+
logExtension({
|
|
143
|
+
subsystem: "install",
|
|
144
|
+
message: `lazy-install ${tool} suppressed (${suppressed})`,
|
|
145
|
+
metadata: {
|
|
146
|
+
tool,
|
|
147
|
+
cwd,
|
|
148
|
+
suppressed,
|
|
149
|
+
outcome: previous?.fact.outcome,
|
|
150
|
+
...(previous?.fact.reason && { reason: previous.fact.reason }),
|
|
151
|
+
...(suppressed === "cooling" && {
|
|
152
|
+
retryAfterMs: Math.max(0, (previous?.retryAtMs ?? 0) - Date.now()),
|
|
153
|
+
}),
|
|
154
|
+
},
|
|
155
|
+
});
|
|
17
156
|
return false;
|
|
18
|
-
|
|
157
|
+
}
|
|
158
|
+
const started = performInstall(k, tool, cwd, spec);
|
|
159
|
+
inFlight.set(k, started);
|
|
19
160
|
try {
|
|
20
|
-
|
|
21
|
-
case "golangci-lint": {
|
|
22
|
-
const result = await safeSpawnAsync("go", [
|
|
23
|
-
"install",
|
|
24
|
-
"github.com/golangci/golangci-lint/cmd/golangci-lint@latest",
|
|
25
|
-
], { timeout: 180000, cwd });
|
|
26
|
-
return !result.error && result.status === 0;
|
|
27
|
-
}
|
|
28
|
-
case "rubocop": {
|
|
29
|
-
const result = await safeSpawnAsync("gem", ["install", "rubocop", "--no-document"], { timeout: 180000, cwd });
|
|
30
|
-
return !result.error && result.status === 0;
|
|
31
|
-
}
|
|
32
|
-
case "rust-clippy": {
|
|
33
|
-
const result = await safeSpawnAsync("rustup", ["component", "add", "clippy"], { timeout: 180000, cwd });
|
|
34
|
-
return !result.error && result.status === 0;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
161
|
+
return await started;
|
|
37
162
|
}
|
|
38
|
-
|
|
39
|
-
|
|
163
|
+
finally {
|
|
164
|
+
inFlight.delete(k);
|
|
40
165
|
}
|
|
41
166
|
}
|
|
167
|
+
async function performInstall(k, tool, cwd, spec) {
|
|
168
|
+
let result;
|
|
169
|
+
try {
|
|
170
|
+
result = await safeSpawnAsync(spec.command, spec.args, {
|
|
171
|
+
timeout: LAZY_INSTALL_TIMEOUT_MS,
|
|
172
|
+
cwd,
|
|
173
|
+
...(LAZY_INSTALL_IGNORES_AMBIENT_SIGNAL && { ignoreAmbientSignal: true }),
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
catch (err) {
|
|
177
|
+
// A throw from the spawn boundary is not evidence that the tool cannot be
|
|
178
|
+
// installed, so it is transient like any other failure to get a fair run.
|
|
179
|
+
result = {
|
|
180
|
+
stdout: "",
|
|
181
|
+
stderr: err?.message ?? String(err),
|
|
182
|
+
status: null,
|
|
183
|
+
error: err,
|
|
184
|
+
failure: "spawn",
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
if (!result.error && result.status === 0) {
|
|
188
|
+
attempts.set(k, {
|
|
189
|
+
fact: { outcome: "succeeded" },
|
|
190
|
+
retryAtMs: 0,
|
|
191
|
+
transientAttempts: 0,
|
|
192
|
+
});
|
|
193
|
+
return true;
|
|
194
|
+
}
|
|
195
|
+
// `classifyProbeFailure` owns the transient taxonomy (timeout, kill, EAGAIN)
|
|
196
|
+
// and the one durable case that matters here: `tool-not-found` on the package
|
|
197
|
+
// MANAGER. Everything else RAN and exited nonzero, which for an install is
|
|
198
|
+
// the retry candidate — a network failure and a nonexistent package are
|
|
199
|
+
// indistinguishable from the exit code, so the attempt CEILING is what stops
|
|
200
|
+
// the second one from retrying forever, not a guess at the cause.
|
|
201
|
+
const classified = classifyProbeFailure(result, {
|
|
202
|
+
command: spec.command,
|
|
203
|
+
unclassifiedFailureOutcome: "transient",
|
|
204
|
+
});
|
|
205
|
+
const durable = classified.outcome === "missing";
|
|
206
|
+
const reason = (result.error?.message ??
|
|
207
|
+
result.stderr ??
|
|
208
|
+
`exit ${result.status}`)
|
|
209
|
+
.trim()
|
|
210
|
+
.slice(0, 200);
|
|
211
|
+
// Re-read the record rather than trusting one captured before the spawn
|
|
212
|
+
// (#1537 review P3). `resetLazyInstallAttempts` clears `attempts` but leaves
|
|
213
|
+
// `inFlight`, so an install can outlive the session that started it — and a
|
|
214
|
+
// captured counter let that survivor stamp the OLD session's attempt count
|
|
215
|
+
// onto the NEW session's empty map, opening a fresh session already HELD with
|
|
216
|
+
// no attempts of its own. Re-reading makes the settle count as attempt 1 of
|
|
217
|
+
// whatever session is current. Nothing else can write this key while the
|
|
218
|
+
// install is in flight (the in-flight map is what guarantees that), so in the
|
|
219
|
+
// ordinary case this reads exactly what was captured.
|
|
220
|
+
const settledPrevious = attempts.get(k);
|
|
221
|
+
const transientAttempts = durable
|
|
222
|
+
? 0
|
|
223
|
+
: (settledPrevious?.transientAttempts ?? 0) + 1;
|
|
224
|
+
// The ceiling is READ OFF the ladder: `installRetryDelayMs` returns 0 once its
|
|
225
|
+
// list is spent, which is the same "no retry, the verdict is latched" signal
|
|
226
|
+
// `noteUnavailable` returns. No separate max-attempts comparison to disagree
|
|
227
|
+
// with the ladder's real length (#1537 review F2).
|
|
228
|
+
const cooldownMs = durable ? 0 : installRetryDelayMs(transientAttempts);
|
|
229
|
+
const retryAtMs = cooldownMs === 0 ? 0 : Date.now() + cooldownMs;
|
|
230
|
+
attempts.set(k, {
|
|
231
|
+
fact: { outcome: "failed", reason },
|
|
232
|
+
retryAtMs,
|
|
233
|
+
transientAttempts,
|
|
234
|
+
});
|
|
235
|
+
logExtension({
|
|
236
|
+
subsystem: "install",
|
|
237
|
+
message: `lazy-install ${tool} failed: ${reason}`,
|
|
238
|
+
metadata: {
|
|
239
|
+
tool,
|
|
240
|
+
cwd,
|
|
241
|
+
command: spec.command,
|
|
242
|
+
cause: classified.cause,
|
|
243
|
+
durable,
|
|
244
|
+
transientAttempts,
|
|
245
|
+
held: retryAtMs === 0,
|
|
246
|
+
...(retryAtMs > 0 && { retryAfterMs: retryAtMs - Date.now() }),
|
|
247
|
+
evidence: classified.evidence,
|
|
248
|
+
},
|
|
249
|
+
});
|
|
250
|
+
return false;
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Best-effort lazy install for language-specific linters.
|
|
254
|
+
*
|
|
255
|
+
* Returns true only when an install just ran and succeeded — a suppressed call
|
|
256
|
+
* returns false rather than repeating the previous answer, so a caller cannot
|
|
257
|
+
* mistake "already handled" for "just installed".
|
|
258
|
+
*/
|
|
259
|
+
export async function tryLazyInstall(tool, cwd) {
|
|
260
|
+
if (!assertInstallAllowed(`runner lazy install: ${tool}`))
|
|
261
|
+
return false;
|
|
262
|
+
return runLazyInstall(tool, cwd, LAZY_INSTALL_SPECS[tool]);
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* The formatter-facing entry point. Distinct only for the trust gate's audit
|
|
266
|
+
* label, which names the seam that asked; the state, the spawn options, the
|
|
267
|
+
* classification and the ladder are all shared, because this was a two-copy
|
|
268
|
+
* shape and a fix in one copy is not a fix (#1537).
|
|
269
|
+
*/
|
|
270
|
+
export async function tryLazyInstallForFormatter(tool, cwd) {
|
|
271
|
+
if (!assertInstallAllowed(`formatter lazy install: ${tool}`))
|
|
272
|
+
return false;
|
|
273
|
+
return runLazyInstall(tool, cwd, LAZY_INSTALL_SPECS[tool]);
|
|
274
|
+
}
|