@herbertgao/pi-extensions 2026.8.4 → 2026.8.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +11 -3
- package/node_modules/@herbertgao/pi-cc-extensions/README.md +11 -3
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/config.ts +24 -0
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +91 -1
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/compact-thinking.ts +7 -3
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/context.ts +74 -5
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/index.ts +7 -6
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/compact-mode.ts +21 -12
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/default-mode.ts +4 -5
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/markdown-enhance.ts +53 -14
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/grouping.ts +22 -12
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/result.ts +2 -4
- package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
- package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +18 -0
- package/node_modules/@herbertgao/pi-subagents/package.json +8 -4
- package/node_modules/@herbertgao/pi-subagents/src/agent-color.ts +72 -67
- package/node_modules/@herbertgao/pi-subagents/src/agent-file-toggle.ts +255 -0
- package/node_modules/@herbertgao/pi-subagents/src/agent-manager.ts +191 -3
- package/node_modules/@herbertgao/pi-subagents/src/agent-runner.ts +20 -4
- package/node_modules/@herbertgao/pi-subagents/src/index.ts +289 -113
- package/node_modules/@herbertgao/pi-subagents/src/output-file.ts +24 -1
- package/node_modules/@herbertgao/pi-subagents/src/ui/agent-widget.ts +24 -2
- package/node_modules/@herbertgao/pi-subagents/src/ui/fleet-list.ts +15 -6
- package/node_modules/@herbertgao/pi-subagents/src/ui/schedule-menu.ts +9 -8
- package/node_modules/@herbertgao/pi-subagents/src/ui/select-item.ts +48 -0
- package/node_modules/@herbertgao/pi-subagents/src/worktree.ts +9 -5
- package/node_modules/@juicesharp/rpiv-ask-user-question/README.md +2 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/ask-user-question.ts +20 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/docs/hosts.md +6 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/docs/keyboard.md +7 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/package.json +2 -2
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/build-questionnaire.ts +7 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/key-router.ts +16 -5
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/questionnaire-session.ts +4 -2
- package/node_modules/@narumitw/pi-btw/README.md +32 -24
- package/node_modules/@narumitw/pi-btw/package.json +6 -6
- package/node_modules/@narumitw/pi-btw/src/btw.ts +4 -2
- package/node_modules/@narumitw/pi-btw/src/menu.ts +34 -13
- package/node_modules/@narumitw/pi-btw/src/settings.ts +22 -2
- package/node_modules/pi-lens/CHANGELOG.md +2535 -954
- package/node_modules/pi-lens/README.md +13 -0
- package/node_modules/pi-lens/dist/clients/actionable-warnings.js +73 -18
- package/node_modules/pi-lens/dist/clients/advisory-provenance.js +314 -0
- package/node_modules/pi-lens/dist/clients/agent-behavior-client.js +21 -4
- package/node_modules/pi-lens/dist/clients/agent-nudge.js +14 -7
- package/node_modules/pi-lens/dist/clients/ast-grep-client.js +68 -16
- package/node_modules/pi-lens/dist/clients/ast-grep-types.js +0 -1
- package/node_modules/pi-lens/dist/clients/ast-grep-yaml-synth.js +37 -10
- package/node_modules/pi-lens/dist/clients/atomic-write-staging.js +63 -0
- package/node_modules/pi-lens/dist/clients/atomic-write.js +114 -14
- package/node_modules/pi-lens/dist/clients/bash-file-access.js +193 -23
- package/node_modules/pi-lens/dist/clients/biome-client.js +136 -24
- package/node_modules/pi-lens/dist/clients/bootstrap.js +11 -2
- package/node_modules/pi-lens/dist/clients/bounded-cache.js +34 -0
- package/node_modules/pi-lens/dist/clients/bounded-pid-file-lock.js +192 -0
- package/node_modules/pi-lens/dist/clients/bus-events-logger.js +62 -6
- package/node_modules/pi-lens/dist/clients/bus-publish.js +19 -4
- package/node_modules/pi-lens/dist/clients/cache/rule-cache.js +47 -5
- package/node_modules/pi-lens/dist/clients/cache-manager.js +97 -9
- package/node_modules/pi-lens/dist/clients/cache-observability.js +301 -14
- package/node_modules/pi-lens/dist/clients/call-graph.js +449 -117
- package/node_modules/pi-lens/dist/clients/cascade-format.js +57 -2
- package/node_modules/pi-lens/dist/clients/child-unref.js +85 -0
- package/node_modules/pi-lens/dist/clients/codebase-model.js +52 -23
- package/node_modules/pi-lens/dist/clients/collateral-test-role.js +40 -0
- package/node_modules/pi-lens/dist/clients/complexity-client.js +2 -1
- package/node_modules/pi-lens/dist/clients/console-guard-install.js +26 -0
- package/node_modules/pi-lens/dist/clients/cooperative-budget.js +42 -0
- package/node_modules/pi-lens/dist/clients/dead-code-client.js +137 -31
- package/node_modules/pi-lens/dist/clients/debug-handles.js +206 -0
- package/node_modules/pi-lens/dist/clients/debug-heap.js +167 -0
- package/node_modules/pi-lens/dist/clients/degradation-ledger.js +153 -0
- package/node_modules/pi-lens/dist/clients/dependency-checker.js +361 -77
- package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +65 -13
- package/node_modules/pi-lens/dist/clients/diagnostics-publish.js +18 -4
- package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +176 -29
- package/node_modules/pi-lens/dist/clients/dispatch/facts/function-facts.js +23 -7
- package/node_modules/pi-lens/dist/clients/dispatch/facts/import-facts.js +8 -18
- package/node_modules/pi-lens/dist/clients/dispatch/facts/tree-sitter-facts.js +8 -5
- package/node_modules/pi-lens/dist/clients/dispatch/indent-detect.js +35 -0
- package/node_modules/pi-lens/dist/clients/dispatch/inline-suppressions.js +17 -8
- package/node_modules/pi-lens/dist/clients/dispatch/integration.js +1172 -683
- package/node_modules/pi-lens/dist/clients/dispatch/lazy.js +14 -0
- package/node_modules/pi-lens/dist/clients/dispatch/plan.js +11 -1
- package/node_modules/pi-lens/dist/clients/dispatch/rule-id-normalize.js +50 -0
- package/node_modules/pi-lens/dist/clients/dispatch/rule-policy.js +135 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ast-grep-napi.js +23 -5
- package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +5 -9
- package/node_modules/pi-lens/dist/clients/dispatch/runners/detekt.js +3 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/hadolint.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-lint.js +154 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/htmlhint.js +3 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/index.js +5 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +47 -6
- package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +4 -9
- package/node_modules/pi-lens/dist/clients/dispatch/runners/pyright.js +9 -5
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ruff.js +4 -8
- package/node_modules/pi-lens/dist/clients/dispatch/runners/shellcheck.js +2 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/shfmt.js +2 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/spotbugs.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/taplo.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/terragrunt.js +163 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/tflint.js +37 -5
- package/node_modules/pi-lens/dist/clients/dispatch/runners/tree-sitter.js +3 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/trivy-config.js +13 -7
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/availability-policy.js +226 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/candidate-probe.js +69 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/lazy-installer.js +3 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +473 -42
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/spawn-outcome.js +22 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/toolchain-availability.js +97 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/yaml-rule-parser.js +5 -4
- package/node_modules/pi-lens/dist/clients/disposition-publish.js +18 -4
- package/node_modules/pi-lens/dist/clients/durable-store.js +97 -0
- package/node_modules/pi-lens/dist/clients/eval-timestamp.js +17 -0
- package/node_modules/pi-lens/dist/clients/event-loop-monitor.js +94 -3
- package/node_modules/pi-lens/dist/clients/extension-log.js +432 -0
- package/node_modules/pi-lens/dist/clients/extension-mode.js +73 -0
- package/node_modules/pi-lens/dist/clients/file-kinds.js +57 -0
- package/node_modules/pi-lens/dist/clients/file-role.js +18 -3
- package/node_modules/pi-lens/dist/clients/file-utils.js +56 -34
- package/node_modules/pi-lens/dist/clients/fix-worklog.js +5 -1
- package/node_modules/pi-lens/dist/clients/format-events-publish.js +51 -7
- package/node_modules/pi-lens/dist/clients/format-service.js +24 -8
- package/node_modules/pi-lens/dist/clients/formatters-lazy.js +8 -0
- package/node_modules/pi-lens/dist/clients/formatters.js +358 -61
- package/node_modules/pi-lens/dist/clients/generated-artifacts.js +148 -15
- package/node_modules/pi-lens/dist/clients/git-guard.js +678 -11
- package/node_modules/pi-lens/dist/clients/git-tracked-ignore.js +4 -0
- package/node_modules/pi-lens/dist/clients/go-client.js +23 -40
- package/node_modules/pi-lens/dist/clients/govulncheck-client.js +124 -7
- package/node_modules/pi-lens/dist/clients/grammar-source.js +12 -4
- package/node_modules/pi-lens/dist/clients/gzip-stage-write.js +21 -3
- package/node_modules/pi-lens/dist/clients/host-ports.js +31 -0
- package/node_modules/pi-lens/dist/clients/installer/index.js +395 -100
- package/node_modules/pi-lens/dist/clients/instance-reaper.js +142 -172
- package/node_modules/pi-lens/dist/clients/jscpd-client.js +27 -55
- package/node_modules/pi-lens/dist/clients/knip-client.js +58 -42
- package/node_modules/pi-lens/dist/clients/language-policy.js +14 -2
- package/node_modules/pi-lens/dist/clients/language-profile.js +13 -7
- package/node_modules/pi-lens/dist/clients/latency-logger.js +72 -1
- package/node_modules/pi-lens/dist/clients/lens-config.js +12 -1
- package/node_modules/pi-lens/dist/clients/lens-engine.js +86 -17
- package/node_modules/pi-lens/dist/clients/lens-events.js +63 -9
- package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +16 -0
- package/node_modules/pi-lens/dist/clients/lens-map.js +94 -19
- package/node_modules/pi-lens/dist/clients/live-bus-emitter.js +73 -0
- package/node_modules/pi-lens/dist/clients/log-cleanup.js +2 -1
- package/node_modules/pi-lens/dist/clients/lsp/aggregation.js +30 -4
- package/node_modules/pi-lens/dist/clients/lsp/cascade-tier.js +59 -14
- package/node_modules/pi-lens/dist/clients/lsp/client.js +662 -56
- package/node_modules/pi-lens/dist/clients/lsp/config.js +13 -2
- package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +115 -0
- package/node_modules/pi-lens/dist/clients/lsp/edits.js +1012 -121
- package/node_modules/pi-lens/dist/clients/lsp/index.js +2025 -800
- package/node_modules/pi-lens/dist/clients/lsp/launch.js +32 -26
- package/node_modules/pi-lens/dist/clients/lsp/path-utils.js +1 -1
- package/node_modules/pi-lens/dist/clients/lsp/ruby-drive-dirs.js +83 -0
- package/node_modules/pi-lens/dist/clients/lsp/server.js +437 -86
- package/node_modules/pi-lens/dist/clients/lsp/tsserver-sync.js +96 -0
- package/node_modules/pi-lens/dist/clients/lsp/wait-policy/classification.js +21 -5
- package/node_modules/pi-lens/dist/clients/lsp/wait-policy/strategies.js +18 -3
- package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +28 -4
- package/node_modules/pi-lens/dist/clients/lsp-lazy.js +8 -0
- package/node_modules/pi-lens/dist/clients/lsp-mutation.js +248 -0
- package/node_modules/pi-lens/dist/clients/mcp/analyze.js +127 -32
- package/node_modules/pi-lens/dist/clients/mcp/ipc.js +157 -24
- package/node_modules/pi-lens/dist/clients/mcp/session.js +235 -14
- package/node_modules/pi-lens/dist/clients/memory-sampler.js +115 -0
- package/node_modules/pi-lens/dist/clients/metrics-client.js +2 -1
- package/node_modules/pi-lens/dist/clients/metrics-history.js +2 -1
- package/node_modules/pi-lens/dist/clients/model-provider.js +53 -0
- package/node_modules/pi-lens/dist/clients/module-report-lsp.js +5 -0
- package/node_modules/pi-lens/dist/clients/module-report.js +168 -3
- package/node_modules/pi-lens/dist/clients/ndjson-logger.js +319 -118
- package/node_modules/pi-lens/dist/clients/opengrep-client.js +1 -1
- package/node_modules/pi-lens/dist/clients/partial-edit-apply.js +120 -5
- package/node_modules/pi-lens/dist/clients/path-utils.js +110 -9
- package/node_modules/pi-lens/dist/clients/pipeline.js +76 -15
- package/node_modules/pi-lens/dist/clients/print-mode.js +21 -0
- package/node_modules/pi-lens/dist/clients/project-changes.js +40 -0
- package/node_modules/pi-lens/dist/clients/project-diagnostics/cache.js +3 -2
- package/node_modules/pi-lens/dist/clients/project-diagnostics/fresh-fetch.js +1 -1
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/call-graph-impact.js +8 -0
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/runner-findings.js +23 -2
- package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +21 -1
- package/node_modules/pi-lens/dist/clients/project-lens-config.js +86 -9
- package/node_modules/pi-lens/dist/clients/project-report.js +27 -13
- package/node_modules/pi-lens/dist/clients/project-snapshot.js +175 -20
- package/node_modules/pi-lens/dist/clients/project-trust.js +181 -0
- package/node_modules/pi-lens/dist/clients/quiet-window.js +18 -4
- package/node_modules/pi-lens/dist/clients/read-bridge.js +147 -0
- package/node_modules/pi-lens/dist/clients/read-guard-logger.js +159 -1
- package/node_modules/pi-lens/dist/clients/read-guard-tool-lines.js +150 -29
- package/node_modules/pi-lens/dist/clients/read-guard.js +185 -4
- package/node_modules/pi-lens/dist/clients/resource-sampler.js +70 -84
- package/node_modules/pi-lens/dist/clients/review-graph/builder.js +1122 -221
- package/node_modules/pi-lens/dist/clients/review-graph/git-identity.js +2 -1
- package/node_modules/pi-lens/dist/clients/review-graph/import-resolvers.js +21 -10
- package/node_modules/pi-lens/dist/clients/review-graph/query.js +24 -0
- package/node_modules/pi-lens/dist/clients/review-graph/symbol-id.js +46 -0
- package/node_modules/pi-lens/dist/clients/review-graph/tsconfig-paths.js +57 -6
- package/node_modules/pi-lens/dist/clients/review-graph/workspace-modules.js +51 -3
- package/node_modules/pi-lens/dist/clients/review-graph-logger.js +30 -1
- package/node_modules/pi-lens/dist/clients/ruff-client.js +27 -44
- package/node_modules/pi-lens/dist/clients/run-duration.js +55 -0
- package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +257 -77
- package/node_modules/pi-lens/dist/clients/runtime-context.js +129 -12
- package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +242 -26
- package/node_modules/pi-lens/dist/clients/runtime-session.js +428 -117
- package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +71 -48
- package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +342 -33
- package/node_modules/pi-lens/dist/clients/runtime-turn.js +619 -93
- package/node_modules/pi-lens/dist/clients/rust-client.js +23 -38
- package/node_modules/pi-lens/dist/clients/safe-spawn.js +777 -62
- package/node_modules/pi-lens/dist/clients/security-scan-client.js +90 -6
- package/node_modules/pi-lens/dist/clients/session-state-store.js +3 -2
- package/node_modules/pi-lens/dist/clients/sg-runner.js +424 -196
- package/node_modules/pi-lens/dist/clients/slow-fs.js +2 -1
- package/node_modules/pi-lens/dist/clients/smells-rollup.js +231 -0
- package/node_modules/pi-lens/dist/clients/source-filter.js +184 -20
- package/node_modules/pi-lens/dist/clients/source-walker.js +66 -10
- package/node_modules/pi-lens/dist/clients/startup-scan.js +15 -16
- package/node_modules/pi-lens/dist/clients/startup-timing.js +7 -1
- package/node_modules/pi-lens/dist/clients/test-runner-client.js +469 -32
- package/node_modules/pi-lens/dist/clients/tool-event.js +35 -0
- package/node_modules/pi-lens/dist/clients/tool-policy.js +390 -39
- package/node_modules/pi-lens/dist/clients/tool-render.js +155 -0
- package/node_modules/pi-lens/dist/clients/tool-set-policy.js +76 -0
- package/node_modules/pi-lens/dist/clients/tree-sitter-cache.js +6 -1
- package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +419 -50
- package/node_modules/pi-lens/dist/clients/tree-sitter-logger.js +21 -0
- package/node_modules/pi-lens/dist/clients/tree-sitter-query-loader.js +7 -1
- package/node_modules/pi-lens/dist/clients/tree-sitter-shared.js +7 -2
- package/node_modules/pi-lens/dist/clients/tree-sitter-symbol-extractor.js +44 -7
- package/node_modules/pi-lens/dist/clients/user-notify.js +51 -0
- package/node_modules/pi-lens/dist/clients/vanished-instance-marker.js +57 -0
- package/node_modules/pi-lens/dist/clients/warm-attach.js +50 -13
- package/node_modules/pi-lens/dist/clients/widget-state.js +300 -43
- package/node_modules/pi-lens/dist/clients/word-index.js +680 -81
- package/node_modules/pi-lens/dist/clients/workspace-topology.js +89 -6
- package/node_modules/pi-lens/dist/index.js +51785 -36118
- package/node_modules/pi-lens/dist/mcp/analyze-cli.js +182 -29
- package/node_modules/pi-lens/dist/mcp/server.js +219 -46
- package/node_modules/pi-lens/dist/tools/activate-tools.js +17 -5
- package/node_modules/pi-lens/dist/tools/ast-grep-replace.js +9 -4
- package/node_modules/pi-lens/dist/tools/ast-grep-search.js +93 -27
- package/node_modules/pi-lens/dist/tools/lens-diagnostic-mark.js +5 -2
- package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +203 -38
- package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +210 -42
- package/node_modules/pi-lens/dist/tools/lsp-navigation.js +46 -3
- package/node_modules/pi-lens/dist/tools/module-report.js +9 -0
- package/node_modules/pi-lens/dist/tools/symbol-search.js +1 -1
- package/node_modules/pi-lens/docs/agent-guide.md +40 -15
- package/node_modules/pi-lens/docs/agent-tools.md +21 -10
- package/node_modules/pi-lens/docs/analysisall.md +192 -0
- package/node_modules/pi-lens/docs/api-ports-inventory.md +165 -0
- package/node_modules/pi-lens/docs/ast-grep_rules_catalog.md +14 -3
- package/node_modules/pi-lens/docs/durable-store-audit-1202.md +32 -0
- package/node_modules/pi-lens/docs/environment-variables.md +44 -0
- package/node_modules/pi-lens/docs/fable.md +27 -0
- package/node_modules/pi-lens/docs/features.md +45 -3
- package/node_modules/pi-lens/docs/globalconfig.md +56 -1
- package/node_modules/pi-lens/docs/language-coverage.md +4 -3
- package/node_modules/pi-lens/docs/lsp-capability-matrix.md +2 -2
- package/node_modules/pi-lens/docs/mcp.md +37 -4
- package/node_modules/pi-lens/docs/servercapabilities.md +3 -3
- package/node_modules/pi-lens/docs/settings.md +18 -1
- package/node_modules/pi-lens/docs/tools.md +4 -1
- package/node_modules/pi-lens/docs/usage.md +41 -5
- package/node_modules/pi-lens/docs/word-index.md +35 -0
- package/node_modules/pi-lens/package.json +10 -10
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-bare-except-test.yml +49 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-bare-host-path-in-win32-branch-test.yml +87 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-chained-type-assertions-test.yml +8 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-conditional-empty-object-spread-js-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-conditional-empty-object-spread-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-nested-links-test.yml +11 -1
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-raw-json-store-write-test.yml +17 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-js-test.yml +7 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-test.yml +7 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-js-test.yml +8 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-test.yml +8 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unknown-laundering-test.yml +11 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-win32-isabsolute-for-qualification-test.yml +16 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-except.yml +3 -15
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-host-path-in-win32-branch.yml +25 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-chained-type-assertions.yml +21 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-conditional-empty-object-spread-js.yml +21 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-conditional-empty-object-spread.yml +29 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-nested-links.yml +7 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-raw-json-store-write.yml +30 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply-js.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get-js.yml +13 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get.yml +16 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-laundering.yml +27 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-win32-isabsolute-for-qualification.yml +23 -0
- package/node_modules/pi-lens/rules/tree-sitter-queries/tsx/no-nested-links.yml +4 -6
- package/node_modules/pi-lens/rules/tree-sitter-queries/typescript/duplicate-function-arg.yml +2 -2
- package/node_modules/pi-lens/scripts/analyze-pi-lens-logs.mjs +134 -2
- package/node_modules/pi-lens/skills/pi-lens-ast-grep/SKILL.md +10 -11
- package/node_modules/pi-lens/skills/pi-lens-lsp-navigation/SKILL.md +22 -22
- package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/SKILL.md +8 -114
- package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/reference.md +129 -0
- package/node_modules/pi-lens/skills/pi-lens-write-tree-sitter-rule/SKILL.md +3 -1
- package/node_modules/pi-mcp-adapter/CHANGELOG.md +38 -0
- package/node_modules/pi-mcp-adapter/README.md +38 -4
- package/node_modules/pi-mcp-adapter/agent-dir.ts +12 -4
- package/node_modules/pi-mcp-adapter/agent-plugin-loader.ts +1 -1
- package/node_modules/pi-mcp-adapter/cli.js +25 -4
- package/node_modules/pi-mcp-adapter/commands.ts +15 -7
- package/node_modules/pi-mcp-adapter/config.ts +4 -4
- package/node_modules/pi-mcp-adapter/direct-tools.ts +58 -8
- package/node_modules/pi-mcp-adapter/host-html-template.ts +0 -8
- package/node_modules/pi-mcp-adapter/index.ts +8 -3
- package/node_modules/pi-mcp-adapter/init.ts +29 -5
- package/node_modules/pi-mcp-adapter/lifecycle.ts +0 -4
- package/node_modules/pi-mcp-adapter/mcp-auth-flow.ts +1 -2
- package/node_modules/pi-mcp-adapter/mcp-auth.ts +60 -2
- package/node_modules/pi-mcp-adapter/mcp-panel.ts +45 -9
- package/node_modules/pi-mcp-adapter/mcp-script-worker.mjs +22 -20
- package/node_modules/pi-mcp-adapter/mcp-setup-panel.ts +2 -1
- package/node_modules/pi-mcp-adapter/metadata-cache.ts +37 -4
- package/node_modules/pi-mcp-adapter/npx-resolver.ts +81 -26
- package/node_modules/pi-mcp-adapter/package.json +4 -3
- package/node_modules/pi-mcp-adapter/proxy-modes.ts +108 -26
- package/node_modules/pi-mcp-adapter/request-headers-command.ts +336 -0
- package/node_modules/pi-mcp-adapter/search-ranking.ts +86 -7
- package/node_modules/pi-mcp-adapter/server-manager.ts +41 -7
- package/node_modules/pi-mcp-adapter/session-recovery.ts +8 -2
- package/node_modules/pi-mcp-adapter/tool-approval.ts +48 -7
- package/node_modules/pi-mcp-adapter/tool-metadata.ts +62 -4
- package/node_modules/pi-mcp-adapter/tool-result-renderer.ts +138 -12
- package/node_modules/pi-mcp-adapter/types.ts +176 -27
- package/node_modules/pi-mcp-adapter/ui-server.ts +20 -1
- package/node_modules/pi-web-access/CHANGELOG.md +14 -0
- package/node_modules/pi-web-access/README.md +18 -12
- package/node_modules/pi-web-access/auth-fetch.ts +148 -0
- package/node_modules/pi-web-access/chrome-cookies.ts +110 -23
- package/node_modules/pi-web-access/curator-page.ts +5 -3
- package/node_modules/pi-web-access/curator-server.ts +2 -1
- package/node_modules/pi-web-access/extract.ts +106 -34
- package/node_modules/pi-web-access/fetch-params.ts +17 -3
- package/node_modules/pi-web-access/firecrawl.ts +172 -12
- package/node_modules/pi-web-access/gemini-search.ts +18 -4
- package/node_modules/pi-web-access/index.ts +120 -48
- package/node_modules/pi-web-access/package.json +2 -2
- package/node_modules/pi-web-access/summary-review.ts +11 -5
- package/node_modules/pi-web-access/youtube-extract.ts +2 -2
- package/package.json +12 -13
- package/node_modules/pi-lens/dist/clients/ast-grep-parser.js +0 -86
- package/node_modules/pi-lens/dist/clients/lsp/interactive-install.js +0 -367
- package/node_modules/pi-lens/dist/clients/lsp/lsp-index.js +0 -10
- package/node_modules/pi-lens/dist/clients/lsp/server-strategies.js +0 -5
- package/node_modules/pi-lens/dist/clients/project-metadata.js +0 -690
- package/node_modules/pi-lens/dist/clients/source-groups.js +0 -96
- package/node_modules/pi-lens/dist/clients/startup-marker.js +0 -6
- package/node_modules/pi-lens/dist/clients/types.js +0 -11
|
@@ -178,6 +178,10 @@ export function collectTrackedFiles(cwd) {
|
|
|
178
178
|
// this file's module doc for why this diverges from `collectUntrackedIgnoredIds`.
|
|
179
179
|
const key = normalizeEphemeralMapKey(cwd);
|
|
180
180
|
const now = Date.now();
|
|
181
|
+
for (const [snapshotKey, entry] of _trackedCache) {
|
|
182
|
+
if (now - entry.fetchedAtMs >= CACHE_TTL_MS)
|
|
183
|
+
_trackedSnapshot.delete(snapshotKey);
|
|
184
|
+
}
|
|
181
185
|
const cached = _trackedCache.get(key);
|
|
182
186
|
if (cached && now - cached.fetchedAtMs < CACHE_TTL_MS)
|
|
183
187
|
return cached.promise;
|
|
@@ -6,15 +6,17 @@
|
|
|
6
6
|
* Requires: gopls (go install golang.org/x/tools/gopls@latest)
|
|
7
7
|
* Docs: https://pkg.go.dev/golang.org/x/tools/gopls
|
|
8
8
|
*/
|
|
9
|
-
import
|
|
9
|
+
import { createSubsystemLogger } from "./extension-log.js";
|
|
10
10
|
import * as path from "node:path";
|
|
11
|
-
import {
|
|
11
|
+
import { createToolchainAvailability, } from "./dispatch/runners/utils/toolchain-availability.js";
|
|
12
12
|
// --- Common install paths ---
|
|
13
13
|
const GO_WINDOWS_PATHS = [
|
|
14
14
|
"C:\\Program Files\\Go\\bin\\go.exe",
|
|
15
15
|
"C:\\Go\\bin\\go.exe",
|
|
16
16
|
"go.exe", // PATH
|
|
17
17
|
];
|
|
18
|
+
/** Budget for the PATH candidate's `go version` probe, ms. */
|
|
19
|
+
const PROBE_TIMEOUT_MS = 3_000;
|
|
18
20
|
const GO_UNIX_PATHS = [
|
|
19
21
|
"/usr/local/go/bin/go",
|
|
20
22
|
"/usr/bin/go",
|
|
@@ -22,58 +24,39 @@ const GO_UNIX_PATHS = [
|
|
|
22
24
|
];
|
|
23
25
|
// --- Client ---
|
|
24
26
|
export class GoClient {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
+
/**
|
|
28
|
+
* Availability lifecycle, behind the shared transient-aware latch (#1476).
|
|
29
|
+
* The PATH candidate is resolved by spawning `go version` with a 3 s budget,
|
|
30
|
+
* so a host stall could latch "no Go toolchain" for the whole session and
|
|
31
|
+
* silently disable every Go diagnostic until restart.
|
|
32
|
+
*/
|
|
33
|
+
availability;
|
|
27
34
|
log;
|
|
28
35
|
constructor(verbose = false) {
|
|
29
36
|
this.log = verbose
|
|
30
|
-
? (
|
|
37
|
+
? createSubsystemLogger("go")
|
|
31
38
|
: () => { };
|
|
39
|
+
this.availability = createToolchainAvailability({
|
|
40
|
+
tool: "go",
|
|
41
|
+
label: "Go",
|
|
42
|
+
windowsPaths: GO_WINDOWS_PATHS,
|
|
43
|
+
unixPaths: GO_UNIX_PATHS,
|
|
44
|
+
probeArgs: ["version"],
|
|
45
|
+
budgetMs: PROBE_TIMEOUT_MS,
|
|
46
|
+
log: (msg) => this.log(msg),
|
|
47
|
+
});
|
|
32
48
|
}
|
|
33
49
|
/**
|
|
34
50
|
* Find go executable path (async — probes PATH candidates off the event loop).
|
|
35
51
|
*/
|
|
36
52
|
async findGoPathAsync() {
|
|
37
|
-
|
|
38
|
-
return this.goPath;
|
|
39
|
-
const paths = process.platform === "win32" ? GO_WINDOWS_PATHS : GO_UNIX_PATHS;
|
|
40
|
-
for (const p of paths) {
|
|
41
|
-
try {
|
|
42
|
-
if (p.includes("\\") || p.includes("/")) {
|
|
43
|
-
// Absolute path - check if exists
|
|
44
|
-
if (fs.existsSync(p)) {
|
|
45
|
-
this.goPath = p;
|
|
46
|
-
return p;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
else {
|
|
50
|
-
// Relative (PATH) - try running it
|
|
51
|
-
const result = await safeSpawnAsync(p, ["version"], {
|
|
52
|
-
timeout: 3000,
|
|
53
|
-
});
|
|
54
|
-
if (!result.error && result.status === 0) {
|
|
55
|
-
this.goPath = p;
|
|
56
|
-
return p;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
catch (err) {
|
|
61
|
-
void err;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
return null;
|
|
53
|
+
return this.availability.findPath();
|
|
65
54
|
}
|
|
66
55
|
/**
|
|
67
56
|
* Check if Go is installed (cached)
|
|
68
57
|
*/
|
|
69
58
|
async isGoAvailableAsync() {
|
|
70
|
-
|
|
71
|
-
return this.goAvailable;
|
|
72
|
-
this.goAvailable = (await this.findGoPathAsync()) !== null;
|
|
73
|
-
if (this.goAvailable) {
|
|
74
|
-
this.log(`Go found: ${this.goPath}`);
|
|
75
|
-
}
|
|
76
|
-
return this.goAvailable;
|
|
59
|
+
return this.availability.isAvailable();
|
|
77
60
|
}
|
|
78
61
|
/**
|
|
79
62
|
* Check if a file is a Go file
|
|
@@ -20,12 +20,16 @@ import * as fs from "node:fs";
|
|
|
20
20
|
import * as os from "node:os";
|
|
21
21
|
import * as path from "node:path";
|
|
22
22
|
import { safeSpawnAsync } from "./safe-spawn.js";
|
|
23
|
+
import { assertInstallAllowed } from "./project-trust.js";
|
|
23
24
|
import { SecurityScanClient } from "./security-scan-client.js";
|
|
25
|
+
import { classifyProbeFailure, logAvailabilityDecision, startHostStallSampler, } from "./dispatch/runners/utils/availability-policy.js";
|
|
24
26
|
const EMPTY_RESULT = {
|
|
25
27
|
success: false,
|
|
26
28
|
findings: [],
|
|
27
29
|
};
|
|
28
30
|
const SCAN_TIMEOUT_MS = 120_000;
|
|
31
|
+
/** Budget for the `go install` auto-install, ms. */
|
|
32
|
+
const INSTALL_TIMEOUT_MS = 60_000;
|
|
29
33
|
// --- Client ---
|
|
30
34
|
export class GovulncheckClient extends SecurityScanClient {
|
|
31
35
|
constructor(verbose = false) {
|
|
@@ -53,33 +57,122 @@ export class GovulncheckClient extends SecurityScanClient {
|
|
|
53
57
|
this.available = true;
|
|
54
58
|
return true;
|
|
55
59
|
}
|
|
60
|
+
if (this.probeWasTransient()) {
|
|
61
|
+
// #1467: a timed-out/killed probe says nothing about whether
|
|
62
|
+
// govulncheck is on PATH. Latching `false` here disabled it for the
|
|
63
|
+
// life of the process; a `go install` here would be a heavyweight
|
|
64
|
+
// reaction to a host hiccup. Record an expiring verdict, retry later.
|
|
65
|
+
this.log("govulncheck probe timed out; retrying later (not installing)");
|
|
66
|
+
this.markTransientlyUnavailable(this.lastProbeCause ?? "probe-timeout");
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
if (!assertInstallAllowed("govulncheck go install")) {
|
|
70
|
+
// Deliberately NOT latching `available = false` (#1350 delta review):
|
|
71
|
+
// trust denial is policy, not tool absence -- a later trust grant
|
|
72
|
+
// (re-adopted at turn_start) must be able to retry the install, and
|
|
73
|
+
// the cached false in ensureAvailable() would make denial permanent.
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
56
76
|
// Not on PATH — auto-install via `go install`. This is safe to assume
|
|
57
77
|
// here because the only path reaching `ensureAvailable()` is the
|
|
58
78
|
// session_start task gated on `hasGoModule(analysisRoot)`; if the
|
|
59
79
|
// project has a go.mod the user has the Go toolchain by definition.
|
|
60
80
|
// Same shape as rust-clippy / cargo: lean on the language's own
|
|
61
81
|
// install mechanism rather than adding a new installer strategy.
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
82
|
+
const goProbeStartedAt = Date.now();
|
|
83
|
+
const goSampler = startHostStallSampler();
|
|
84
|
+
let goOnPath;
|
|
85
|
+
let goHostStallMs;
|
|
86
|
+
try {
|
|
87
|
+
goOnPath = await safeSpawnAsync("go", ["version"], {
|
|
88
|
+
timeout: 5000,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
finally {
|
|
92
|
+
goHostStallMs = goSampler.stop();
|
|
93
|
+
}
|
|
65
94
|
if (goOnPath.error || goOnPath.status !== 0) {
|
|
95
|
+
const { outcome, cause } = classifyProbeFailure(goOnPath, {
|
|
96
|
+
hostStallMs: goHostStallMs,
|
|
97
|
+
});
|
|
98
|
+
if (outcome === "transient") {
|
|
99
|
+
this.log("`go version` probe timed out; retrying govulncheck later");
|
|
100
|
+
const retryAfterMs = this.markTransientlyUnavailable(cause);
|
|
101
|
+
logAvailabilityDecision({
|
|
102
|
+
tool: "govulncheck",
|
|
103
|
+
verdict: "unavailable",
|
|
104
|
+
outcome,
|
|
105
|
+
cause,
|
|
106
|
+
elapsedMs: Date.now() - goProbeStartedAt,
|
|
107
|
+
latched: false,
|
|
108
|
+
hostStallMs: goHostStallMs,
|
|
109
|
+
...(retryAfterMs > 0 && { retryAfterMs }),
|
|
110
|
+
budgetMs: 5000,
|
|
111
|
+
});
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
66
114
|
this.log("go binary not on PATH — cannot auto-install govulncheck");
|
|
67
115
|
this.available = false;
|
|
68
116
|
return false;
|
|
69
117
|
}
|
|
70
118
|
this.log("govulncheck not found, attempting auto-install via go install");
|
|
71
|
-
const
|
|
119
|
+
const installStartedAt = Date.now();
|
|
120
|
+
const installSampler = startHostStallSampler();
|
|
121
|
+
let install;
|
|
122
|
+
let installHostStallMs;
|
|
123
|
+
try {
|
|
124
|
+
install = await safeSpawnAsync("go", ["install", "golang.org/x/vuln/cmd/govulncheck@latest"], { timeout: INSTALL_TIMEOUT_MS });
|
|
125
|
+
}
|
|
126
|
+
finally {
|
|
127
|
+
installHostStallMs = installSampler.stop();
|
|
128
|
+
}
|
|
72
129
|
if (install.error || install.status !== 0) {
|
|
73
130
|
this.log(`govulncheck auto-install failed: ${(install.stderr ?? "").slice(0, 200)}`);
|
|
131
|
+
// #1476: `go install` runs against a 60 s budget over the network. A
|
|
132
|
+
// timed-out or killed install says nothing about whether govulncheck
|
|
133
|
+
// can ever be installed here, so it must not latch the durable
|
|
134
|
+
// "tool is not installed" verdict the way a real install refusal does.
|
|
135
|
+
// A non-zero exit (module not found, compile error) still latches:
|
|
136
|
+
// that IS evidence about this machine, and retrying it every turn
|
|
137
|
+
// would be a `go install` storm.
|
|
138
|
+
const { outcome, cause } = classifyProbeFailure(install, {
|
|
139
|
+
hostStallMs: installHostStallMs,
|
|
140
|
+
});
|
|
141
|
+
if (outcome === "transient") {
|
|
142
|
+
const retryAfterMs = this.markTransientlyUnavailable(cause);
|
|
143
|
+
// One record per decision, so an install that keeps timing out is
|
|
144
|
+
// readable in latency.log the same day (#1467's forensic trail).
|
|
145
|
+
logAvailabilityDecision({
|
|
146
|
+
tool: "govulncheck",
|
|
147
|
+
verdict: "unavailable",
|
|
148
|
+
outcome,
|
|
149
|
+
cause,
|
|
150
|
+
elapsedMs: Date.now() - installStartedAt,
|
|
151
|
+
latched: false,
|
|
152
|
+
hostStallMs: installHostStallMs,
|
|
153
|
+
...(retryAfterMs > 0 && { retryAfterMs }),
|
|
154
|
+
budgetMs: INSTALL_TIMEOUT_MS,
|
|
155
|
+
});
|
|
156
|
+
return false;
|
|
157
|
+
}
|
|
74
158
|
this.available = false;
|
|
75
159
|
return false;
|
|
76
160
|
}
|
|
77
161
|
// `go install` writes to `$GOBIN` or `$GOPATH/bin`. The user may not
|
|
78
162
|
// have that on `$PATH`. Re-probe by name (works when it is on PATH)
|
|
79
163
|
// then fall back to the canonical bin dirs.
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
164
|
+
const reprobeStartedAt = Date.now();
|
|
165
|
+
const reprobeSampler = startHostStallSampler();
|
|
166
|
+
let reprobe;
|
|
167
|
+
let reprobeHostStallMs;
|
|
168
|
+
try {
|
|
169
|
+
reprobe = await safeSpawnAsync("govulncheck", ["-version"], {
|
|
170
|
+
timeout: 5000,
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
finally {
|
|
174
|
+
reprobeHostStallMs = reprobeSampler.stop();
|
|
175
|
+
}
|
|
83
176
|
if (!reprobe.error && reprobe.status === 0) {
|
|
84
177
|
this.log("govulncheck auto-installed and found on PATH");
|
|
85
178
|
this.available = true;
|
|
@@ -110,6 +203,30 @@ export class GovulncheckClient extends SecurityScanClient {
|
|
|
110
203
|
// fall through to next candidate
|
|
111
204
|
}
|
|
112
205
|
}
|
|
206
|
+
// The install SUCCEEDED, so the tool is on this machine somewhere. If the
|
|
207
|
+
// re-probe merely timed out, latching "not installed" would be the #1467
|
|
208
|
+
// mistake one step later in the same function (#1476).
|
|
209
|
+
const { outcome, cause } = classifyProbeFailure(reprobe, {
|
|
210
|
+
hostStallMs: reprobeHostStallMs,
|
|
211
|
+
});
|
|
212
|
+
if (outcome === "transient") {
|
|
213
|
+
this.log("govulncheck installed but the re-probe timed out; retrying later");
|
|
214
|
+
const retryAfterMs = this.markTransientlyUnavailable(cause);
|
|
215
|
+
logAvailabilityDecision({
|
|
216
|
+
tool: "govulncheck",
|
|
217
|
+
verdict: "unavailable",
|
|
218
|
+
outcome,
|
|
219
|
+
cause,
|
|
220
|
+
// The re-probe's own wall time. A hard-coded 0 here was the #1474
|
|
221
|
+
// defect verbatim: a duration field that measures nothing.
|
|
222
|
+
elapsedMs: Date.now() - reprobeStartedAt,
|
|
223
|
+
latched: false,
|
|
224
|
+
hostStallMs: reprobeHostStallMs,
|
|
225
|
+
...(retryAfterMs > 0 && { retryAfterMs }),
|
|
226
|
+
budgetMs: 5000,
|
|
227
|
+
});
|
|
228
|
+
return false;
|
|
229
|
+
}
|
|
113
230
|
this.log("govulncheck auto-install succeeded but binary not locatable — check $GOBIN / $GOPATH");
|
|
114
231
|
this.available = false;
|
|
115
232
|
return false;
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
*/
|
|
12
12
|
import * as fs from "node:fs";
|
|
13
13
|
import * as path from "node:path";
|
|
14
|
+
import { writeFileAtomic } from "./atomic-write.js";
|
|
14
15
|
/** tree-sitter-wasms release the grammars are pulled from. */
|
|
15
16
|
export const TREE_SITTER_WASMS_VERSION = "0.1.13";
|
|
16
17
|
/** unpkg mirror of the tree-sitter-wasms artifacts. */
|
|
@@ -110,11 +111,18 @@ export function grammarBlockReason(filename, rt = currentGrammarRuntime()) {
|
|
|
110
111
|
return block?.blocked(rt) ? block.reason : null;
|
|
111
112
|
}
|
|
112
113
|
/**
|
|
113
|
-
* Fetch one grammar wasm into `destDir
|
|
114
|
+
* Fetch one grammar wasm into `destDir`, staged and renamed via
|
|
115
|
+
* `atomic-write.ts` so a reader never sees a half-written wasm. Returns true
|
|
114
116
|
* on success. Never throws — a failed fetch (offline, 4xx) degrades to "grammar
|
|
115
117
|
* unavailable" so callers can decide how to handle it. A grammar that crashes the
|
|
116
118
|
* runtime is protected at LOAD time (BLOCKED_GRAMMARS / grammarBlockReason), not
|
|
117
119
|
* by refusing to download it.
|
|
120
|
+
*
|
|
121
|
+
* #1217: the staging name used to be hand-rolled `.${filename}.${pid}.tmp` —
|
|
122
|
+
* per-process, so two concurrent fetches of one grammar shared a staging inode
|
|
123
|
+
* (#1205). `tree-sitter-client.ts` de-dupes in-flight fetches per grammar file,
|
|
124
|
+
* which made that hard to reach through the runtime path but did not cover
|
|
125
|
+
* direct callers.
|
|
118
126
|
*/
|
|
119
127
|
export async function downloadGrammar(destDir, filename) {
|
|
120
128
|
try {
|
|
@@ -123,9 +131,9 @@ export async function downloadGrammar(destDir, filename) {
|
|
|
123
131
|
if (!res.ok)
|
|
124
132
|
throw new Error(`HTTP ${res.status}`);
|
|
125
133
|
const data = Buffer.from(await res.arrayBuffer());
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
134
|
+
// bestEffort: false — a swallowed write failure would return true for a
|
|
135
|
+
// grammar that never landed.
|
|
136
|
+
writeFileAtomic(path.join(destDir, filename), data, { bestEffort: false });
|
|
129
137
|
return true;
|
|
130
138
|
}
|
|
131
139
|
catch {
|
|
@@ -4,10 +4,12 @@ import { Readable } from "node:stream";
|
|
|
4
4
|
import { pipeline } from "node:stream/promises";
|
|
5
5
|
import { parentPort } from "node:worker_threads";
|
|
6
6
|
import { createGzip } from "node:zlib";
|
|
7
|
+
import { stagePathFor } from "./atomic-write-staging.js";
|
|
7
8
|
/**
|
|
8
9
|
* Shared worker-thread body-persist core (#958, single source of truth #883):
|
|
9
|
-
* `JSON.stringify` → chunked `createGzip` pipeline →
|
|
10
|
-
* atomic
|
|
10
|
+
* `JSON.stringify` → chunked `createGzip` pipeline → a per-call staging file
|
|
11
|
+
* from `atomic-write.ts`'s {@link stagePathFor} → atomic rename to
|
|
12
|
+
* `stagePath`, returning byte/timing metrics. Both
|
|
11
13
|
* `clients/review-graph/persist-worker.ts` and
|
|
12
14
|
* `clients/project-snapshot-persist-worker.ts` call this so the streamed-gzip
|
|
13
15
|
* write lives in exactly one place; each worker's `parentPort` wiring owns its
|
|
@@ -19,9 +21,25 @@ import { createGzip } from "node:zlib";
|
|
|
19
21
|
* On failure the partial `.tmp` is removed and the error is rethrown for the
|
|
20
22
|
* caller to record; the `stagePath` itself is only ever created by the atomic
|
|
21
23
|
* rename, so a crash mid-write can never leave a torn stage file behind.
|
|
24
|
+
*
|
|
25
|
+
* That crash-safety is NOT the same as concurrency isolation, and this
|
|
26
|
+
* docstring used to conflate the two (#1217). The staging name is what keeps
|
|
27
|
+
* two concurrent calls on one `stagePath` from writing into a shared inode,
|
|
28
|
+
* and it has to come from `stagePathFor` rather than a local
|
|
29
|
+
* `${stagePath}.tmp-${process.pid}`: this module runs on worker threads, which
|
|
30
|
+
* share `process.pid` with the main thread and with each other, so pid alone
|
|
31
|
+
* isolates nothing here (#1205's per-pid tear, verbatim). Callers normally
|
|
32
|
+
* pass a per-generation `stagePath`, which makes the overlap rare — a retry, a
|
|
33
|
+
* re-queued persist, a repeated generation, or a future non-generational
|
|
34
|
+
* caller makes it exact. Beyond tear-freedom this offers nothing: two calls on
|
|
35
|
+
* one `stagePath` are still unordered and last-rename-wins on POSIX — on
|
|
36
|
+
* Windows, MoveFileEx's REPLACE_EXISTING does not serialize concurrent replaces
|
|
37
|
+
* of the same destination, so one rename can fail with EPERM instead, which
|
|
38
|
+
* the caller must treat as a persist failure (both persist workers fall back
|
|
39
|
+
* to a main-thread rewrite on an error result).
|
|
22
40
|
*/
|
|
23
41
|
export async function writeGzipStageFile(data, stagePath, testDelayMs) {
|
|
24
|
-
const tmpPath =
|
|
42
|
+
const tmpPath = stagePathFor(stagePath);
|
|
25
43
|
try {
|
|
26
44
|
if (testDelayMs) {
|
|
27
45
|
await new Promise((resolve) => setTimeout(resolve, testDelayMs));
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/** Host-neutral capabilities available to the pi-lens engine (#1358 S2). */
|
|
2
|
+
/**
|
|
3
|
+
* Headless/test implementation. Its feature-detection defaults deliberately
|
|
4
|
+
* match the pre-ports absent-host paths: unknown trust/mode, fail-open spawn,
|
|
5
|
+
* and no-op delivery surfaces.
|
|
6
|
+
*/
|
|
7
|
+
export function createDefaultHostPorts(overrides = {}) {
|
|
8
|
+
const unknownMode = () => "unknown";
|
|
9
|
+
const defaults = {
|
|
10
|
+
notify: { user: () => { } },
|
|
11
|
+
trust: { isProjectTrusted: () => "unknown" },
|
|
12
|
+
mode: {
|
|
13
|
+
current: unknownMode,
|
|
14
|
+
supportsTuiWidget: () => true,
|
|
15
|
+
suppressesUserNotify: () => false,
|
|
16
|
+
},
|
|
17
|
+
log: { extension: () => { }, debug: () => { }, sink: () => () => { } },
|
|
18
|
+
emit: { bus: () => { } },
|
|
19
|
+
status: { set: () => { } },
|
|
20
|
+
spawn: { abortSignal: () => undefined, isAllowed: () => true },
|
|
21
|
+
render: { invalidate: () => { } },
|
|
22
|
+
session: { id: () => undefined },
|
|
23
|
+
workspace: { cwd: () => undefined, projectRoot: () => undefined },
|
|
24
|
+
flags: { get: () => undefined },
|
|
25
|
+
tools: { has: async () => false, getActive: () => [], setActive: () => { } },
|
|
26
|
+
};
|
|
27
|
+
return Object.fromEntries(Object.entries(defaults).map(([group, value]) => [
|
|
28
|
+
group,
|
|
29
|
+
{ ...value, ...(overrides[group] ?? {}) },
|
|
30
|
+
]));
|
|
31
|
+
}
|