@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
|
@@ -278,6 +278,257 @@ function readSnapshotBody(bodyPath, gz) {
|
|
|
278
278
|
return { snapshot: null, rawBytes: 0 };
|
|
279
279
|
}
|
|
280
280
|
}
|
|
281
|
+
/**
|
|
282
|
+
* Scan a JSON value starting at `start` (skipping any leading whitespace)
|
|
283
|
+
* and return the index one past its end. Handles strings, objects, arrays,
|
|
284
|
+
* and bare scalars (numbers/`true`/`false`/`null`) — correctly skipping
|
|
285
|
+
* nested strings/braces/brackets (respecting `\"` escapes) WITHOUT ever
|
|
286
|
+
* constructing a JS value for them. This is the primitive
|
|
287
|
+
* `stripTopLevelJsonKeys` (#1785 F5) is built on: `JSON.parse` has no way to
|
|
288
|
+
* skip a subtree's construction cost — a reviver only prunes the
|
|
289
|
+
* already-built result — so avoiding a field's parse cost requires never
|
|
290
|
+
* handing its text to `JSON.parse` in the first place.
|
|
291
|
+
*/
|
|
292
|
+
function skipJsonValue(text, start) {
|
|
293
|
+
let i = start;
|
|
294
|
+
while (i < text.length && /\s/.test(text[i]))
|
|
295
|
+
i++;
|
|
296
|
+
const ch = text[i];
|
|
297
|
+
if (ch === '"') {
|
|
298
|
+
i++;
|
|
299
|
+
while (i < text.length) {
|
|
300
|
+
if (text[i] === "\\") {
|
|
301
|
+
i += 2;
|
|
302
|
+
continue;
|
|
303
|
+
}
|
|
304
|
+
if (text[i] === '"') {
|
|
305
|
+
i++;
|
|
306
|
+
break;
|
|
307
|
+
}
|
|
308
|
+
i++;
|
|
309
|
+
}
|
|
310
|
+
return i;
|
|
311
|
+
}
|
|
312
|
+
if (ch === "{" || ch === "[") {
|
|
313
|
+
const open = ch;
|
|
314
|
+
const close = open === "{" ? "}" : "]";
|
|
315
|
+
let depth = 0;
|
|
316
|
+
let inString = false;
|
|
317
|
+
for (; i < text.length; i++) {
|
|
318
|
+
const c = text[i];
|
|
319
|
+
if (inString) {
|
|
320
|
+
if (c === "\\") {
|
|
321
|
+
i++;
|
|
322
|
+
continue;
|
|
323
|
+
}
|
|
324
|
+
if (c === '"')
|
|
325
|
+
inString = false;
|
|
326
|
+
continue;
|
|
327
|
+
}
|
|
328
|
+
if (c === '"') {
|
|
329
|
+
inString = true;
|
|
330
|
+
continue;
|
|
331
|
+
}
|
|
332
|
+
if (c === open)
|
|
333
|
+
depth++;
|
|
334
|
+
else if (c === close) {
|
|
335
|
+
depth--;
|
|
336
|
+
if (depth === 0) {
|
|
337
|
+
i++;
|
|
338
|
+
break;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
return i;
|
|
343
|
+
}
|
|
344
|
+
// A bare scalar (number/true/false/null): scan to the next structural
|
|
345
|
+
// character. Every snapshot value is one of the five JSON kinds above, so
|
|
346
|
+
// this branch only ever fires for those scalars.
|
|
347
|
+
while (i < text.length && !",}]".includes(text[i]))
|
|
348
|
+
i++;
|
|
349
|
+
return i;
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* Reconstruct a JSON object literal with the given top-level keys removed,
|
|
353
|
+
* without ever materializing their values as JS objects (#1785 F5). Used to
|
|
354
|
+
* excise the expensive fields — `wordIndex`'s postings graph above all,
|
|
355
|
+
* `files`/`symbols`/`reverseDeps` too — before `JSON.parse` ever sees them,
|
|
356
|
+
* so a caller that only needs a few small top-level fields (`seq`,
|
|
357
|
+
* `cachedExports`, `projectRulesScan`, …) doesn't pay to construct the
|
|
358
|
+
* fields it's about to discard. Correctness relies only on the writer
|
|
359
|
+
* (`JSON.stringify(snapshot)`, `clients/gzip-stage-write.ts`) never emitting
|
|
360
|
+
* pretty-printed/indented output — compact `JSON.stringify` output is what
|
|
361
|
+
* every persist path in this file produces.
|
|
362
|
+
*/
|
|
363
|
+
function stripTopLevelJsonKeys(text, keysToStrip) {
|
|
364
|
+
const objStart = text.indexOf("{");
|
|
365
|
+
if (objStart === -1)
|
|
366
|
+
return text;
|
|
367
|
+
let out = text.slice(0, objStart + 1);
|
|
368
|
+
let i = objStart + 1;
|
|
369
|
+
let wroteField = false;
|
|
370
|
+
while (i < text.length) {
|
|
371
|
+
while (i < text.length && /\s/.test(text[i]))
|
|
372
|
+
i++;
|
|
373
|
+
if (text[i] === "}" || i >= text.length) {
|
|
374
|
+
out += text.slice(i);
|
|
375
|
+
break;
|
|
376
|
+
}
|
|
377
|
+
if (text[i] === ",") {
|
|
378
|
+
i++;
|
|
379
|
+
continue;
|
|
380
|
+
}
|
|
381
|
+
const keyStart = i;
|
|
382
|
+
const keyTextEnd = skipJsonValue(text, keyStart);
|
|
383
|
+
let key;
|
|
384
|
+
try {
|
|
385
|
+
key = JSON.parse(text.slice(keyStart, keyTextEnd));
|
|
386
|
+
}
|
|
387
|
+
catch {
|
|
388
|
+
// Malformed key text — bail out to the untouched original rather
|
|
389
|
+
// than risk producing invalid JSON; the caller's own JSON.parse
|
|
390
|
+
// on the result will then fail loudly instead of silently.
|
|
391
|
+
return text;
|
|
392
|
+
}
|
|
393
|
+
let j = keyTextEnd;
|
|
394
|
+
while (j < text.length && /\s/.test(text[j]))
|
|
395
|
+
j++;
|
|
396
|
+
// text[j] is ':' for a well-formed object.
|
|
397
|
+
const valueStart = j + 1;
|
|
398
|
+
const valueEnd = skipJsonValue(text, valueStart);
|
|
399
|
+
if (!keysToStrip.has(key)) {
|
|
400
|
+
out += (wroteField ? "," : "") + text.slice(keyStart, valueEnd);
|
|
401
|
+
wroteField = true;
|
|
402
|
+
}
|
|
403
|
+
i = valueEnd;
|
|
404
|
+
}
|
|
405
|
+
return out;
|
|
406
|
+
}
|
|
407
|
+
/**
|
|
408
|
+
* Test-only direct access to the raw-text stripper (#1785 F5). Unlike
|
|
409
|
+
* asserting on `loadProjectSnapshotExportsAndRules`'s RETURN shape — which
|
|
410
|
+
* only proves the output omits the heavy fields, not that their parse cost
|
|
411
|
+
* was ever avoided (the function could strip nothing and still hand-pick 4
|
|
412
|
+
* fields out of a fully-parsed object) — this lets a test inspect the
|
|
413
|
+
* INTERMEDIATE text `JSON.parse` actually receives, which is the only way to
|
|
414
|
+
* prove the expensive fields' text never reached `JSON.parse` at all.
|
|
415
|
+
*/
|
|
416
|
+
export function _stripTopLevelJsonKeysForTests(text, keysToStrip) {
|
|
417
|
+
return stripTopLevelJsonKeys(text, new Set(keysToStrip));
|
|
418
|
+
}
|
|
419
|
+
// A fixed, 4-entry, import-time constant — not per-session accumulating
|
|
420
|
+
// state, so it needs no session_start reset (counted in
|
|
421
|
+
// tests/support/session-state-registry.ts's SESSION_STATE_SYMBOL_COUNTS
|
|
422
|
+
// pin for "project-snapshot.ts", alongside the bounded digest hook below).
|
|
423
|
+
//
|
|
424
|
+
// Adding a key here? Add it to `NARROW_DIGEST_HEAVY_KEY_LITERALS` too (~40
|
|
425
|
+
// lines down) — it's a DELIBERATELY separate, independent list (#1785 F7: a
|
|
426
|
+
// digest that reads its own containsHeavyKey answer off THIS set can't
|
|
427
|
+
// detect this set failing/emptying, so it must not).
|
|
428
|
+
const HEAVY_SNAPSHOT_KEYS = new Set([
|
|
429
|
+
"wordIndex",
|
|
430
|
+
"files",
|
|
431
|
+
"symbols",
|
|
432
|
+
"reverseDeps",
|
|
433
|
+
]);
|
|
434
|
+
// #1785 F7 (review round 5): a FIXED LITERAL list, independent of
|
|
435
|
+
// `HEAVY_SNAPSHOT_KEYS` — the digest below exists to detect a broken/emptied
|
|
436
|
+
// `HEAVY_SNAPSHOT_KEYS`, so deriving `containsHeavyKey` from that same
|
|
437
|
+
// constant makes the check vacuous by construction: empty the set and the
|
|
438
|
+
// stripper strips nothing AND `[...HEAVY_SNAPSHOT_KEYS].some(...)` iterates
|
|
439
|
+
// zero entries and reports `false` — the exact failure mode this hook exists
|
|
440
|
+
// to catch, silently passing. Verified: with the shared-constant version,
|
|
441
|
+
// emptying `HEAVY_SNAPSHOT_KEYS` left 38 tests green instead of red.
|
|
442
|
+
const NARROW_DIGEST_HEAVY_KEY_LITERALS = [
|
|
443
|
+
"wordIndex",
|
|
444
|
+
"files",
|
|
445
|
+
"symbols",
|
|
446
|
+
"reverseDeps",
|
|
447
|
+
];
|
|
448
|
+
let _lastNarrowParseDigestForTests;
|
|
449
|
+
export function getLastNarrowParseDigestForTests() {
|
|
450
|
+
return _lastNarrowParseDigestForTests;
|
|
451
|
+
}
|
|
452
|
+
export function resetLastNarrowParseDigestForTests() {
|
|
453
|
+
_lastNarrowParseDigestForTests = undefined;
|
|
454
|
+
}
|
|
455
|
+
function parseExportsAndRulesOnly(json) {
|
|
456
|
+
const narrowed = stripTopLevelJsonKeys(json, HEAVY_SNAPSHOT_KEYS);
|
|
457
|
+
_lastNarrowParseDigestForTests = {
|
|
458
|
+
length: narrowed.length,
|
|
459
|
+
containsHeavyKey: NARROW_DIGEST_HEAVY_KEY_LITERALS.some((key) => narrowed.includes(`"${key}":`)),
|
|
460
|
+
};
|
|
461
|
+
const parsed = JSON.parse(narrowed);
|
|
462
|
+
if (parsed.version !== PROJECT_SNAPSHOT_VERSION)
|
|
463
|
+
return null;
|
|
464
|
+
if (typeof parsed.seq !== "number")
|
|
465
|
+
return null;
|
|
466
|
+
if (!Array.isArray(parsed.cachedExports))
|
|
467
|
+
return null;
|
|
468
|
+
return {
|
|
469
|
+
version: PROJECT_SNAPSHOT_VERSION,
|
|
470
|
+
seq: parsed.seq,
|
|
471
|
+
cachedExports: parsed.cachedExports.filter((entry) => Array.isArray(entry) &&
|
|
472
|
+
typeof entry[0] === "string" &&
|
|
473
|
+
typeof entry[1] === "string"),
|
|
474
|
+
projectRulesScan: parsed.projectRulesScan,
|
|
475
|
+
};
|
|
476
|
+
}
|
|
477
|
+
function readSnapshotExportsAndRulesBody(bodyPath, gz) {
|
|
478
|
+
try {
|
|
479
|
+
const json = gz
|
|
480
|
+
? gunzipSync(fs.readFileSync(bodyPath)).toString("utf-8")
|
|
481
|
+
: fs.readFileSync(bodyPath, "utf-8");
|
|
482
|
+
return parseExportsAndRulesOnly(json);
|
|
483
|
+
}
|
|
484
|
+
catch (err) {
|
|
485
|
+
logLatency({
|
|
486
|
+
type: "phase",
|
|
487
|
+
phase: "project_snapshot_body_corrupt",
|
|
488
|
+
filePath: bodyPath,
|
|
489
|
+
durationMs: 0,
|
|
490
|
+
metadata: {
|
|
491
|
+
error: err instanceof Error ? err.message : String(err),
|
|
492
|
+
narrow: true,
|
|
493
|
+
},
|
|
494
|
+
});
|
|
495
|
+
return null;
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
/**
|
|
499
|
+
* #1785 F5: a narrow counterpart to `loadProjectSnapshot` for callers that
|
|
500
|
+
* only need `seq`/`version`/`cachedExports`/`projectRulesScan` — critically,
|
|
501
|
+
* NOT `wordIndex`, `files`, `symbols`, or `reverseDeps`. The full
|
|
502
|
+
* `loadProjectSnapshot` (even `loadProjectSnapshotWithoutWordIndex`, which
|
|
503
|
+
* only strips the RETAINED copy AFTER a full parse) pays `gunzip` +
|
|
504
|
+
* `JSON.parse` for the ENTIRE body regardless — dominated by `wordIndex`'s
|
|
505
|
+
* postings graph (measured: +200ms warm / +700ms cold on a 29MB body,
|
|
506
|
+
* 209-278ms on this repo's own 16.7MB snapshot). This function excises the
|
|
507
|
+
* heavy fields from the raw text BEFORE parsing (`stripTopLevelJsonKeys`),
|
|
508
|
+
* so their construction cost is never paid at all; the remaining cost is
|
|
509
|
+
* dominated by `cachedExports` (typically a small array), not the postings.
|
|
510
|
+
*
|
|
511
|
+
* Consults the same in-process authoritative-write cache
|
|
512
|
+
* `loadProjectSnapshotInternal` does, for the same read-your-own-write
|
|
513
|
+
* reason — a save's in-memory object is cheap to narrow (no parse needed at
|
|
514
|
+
* all) and must win over a possibly-stale on-disk body exactly like the full
|
|
515
|
+
* loader.
|
|
516
|
+
*/
|
|
517
|
+
export function loadProjectSnapshotExportsAndRules(cwd) {
|
|
518
|
+
const key = normalizeMapKey(cwd);
|
|
519
|
+
const body = resolveSnapshotBodyPath(cwd);
|
|
520
|
+
const authoritative = authoritativeSnapshots.get(key);
|
|
521
|
+
if (authoritative) {
|
|
522
|
+
const diskMtime = body ? body.mtimeMs : Number.NEGATIVE_INFINITY;
|
|
523
|
+
if (diskMtime <= authoritative.knownMtime) {
|
|
524
|
+
const { version, seq, cachedExports, projectRulesScan } = authoritative.snapshot;
|
|
525
|
+
return { version, seq, cachedExports, projectRulesScan };
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
if (!body)
|
|
529
|
+
return null;
|
|
530
|
+
return readSnapshotExportsAndRulesBody(body.path, body.gz);
|
|
531
|
+
}
|
|
281
532
|
function loadProjectSnapshotInternal(cwd, requireWordIndex) {
|
|
282
533
|
const key = normalizeMapKey(cwd);
|
|
283
534
|
const body = resolveSnapshotBodyPath(cwd);
|
|
@@ -851,6 +1102,54 @@ export function hydrateRuntimeFromProjectSnapshot(runtime, snapshot) {
|
|
|
851
1102
|
}
|
|
852
1103
|
runtime.wordIndex = deserializeWordIndex(snapshot.wordIndex);
|
|
853
1104
|
}
|
|
1105
|
+
/**
|
|
1106
|
+
* #1785 F2/F3: additive counterpart to `hydrateRuntimeFromProjectSnapshot`
|
|
1107
|
+
* for a LATE/retroactive hydration attempt — one that runs after other work
|
|
1108
|
+
* may already have populated the runtime for real (e.g. quick mode's
|
|
1109
|
+
* background warmup building a genuine `wordIndex`, docCount > 0). The
|
|
1110
|
+
* unconditional version above is only safe for the FIRST hydration attempt,
|
|
1111
|
+
* made before anything else has run: clearing `cachedExports` is correct
|
|
1112
|
+
* there because there is nothing yet to destroy.
|
|
1113
|
+
*
|
|
1114
|
+
* A late call cannot make that assumption, and `cachedExports` and
|
|
1115
|
+
* `projectRulesScan` are populated by INDEPENDENT tasks from whatever else is
|
|
1116
|
+
* running (nothing else in quick mode touches either), so this guards each
|
|
1117
|
+
* field on its OWN "nothing computed since" check rather than one
|
|
1118
|
+
* all-or-nothing bail-out — the field a concurrent task actually populated is
|
|
1119
|
+
* protected without needlessly withholding the other, still-idle field the
|
|
1120
|
+
* snapshot could still supply. Returns whether it hydrated ANY field, so the
|
|
1121
|
+
* caller can log honestly instead of claiming success when nothing changed.
|
|
1122
|
+
*
|
|
1123
|
+
* #1785 F5: takes ONLY the narrow `{ cachedExports, projectRulesScan }`
|
|
1124
|
+
* shape (see `ProjectSnapshotExportsAndRules`) — deliberately no `wordIndex`
|
|
1125
|
+
* parameter at all, not even an optional one. The retroactive path's
|
|
1126
|
+
* captured/reloaded snapshot always comes from
|
|
1127
|
+
* `loadProjectSnapshotExportsAndRules`, which never parses `wordIndex` in
|
|
1128
|
+
* the first place (avoiding its dominant share of a full body parse's cost —
|
|
1129
|
+
* see that function's doc comment for the measured numbers). This is also
|
|
1130
|
+
* the right behavior, not just a performance shortcut: quick mode's warmup
|
|
1131
|
+
* is the only thing that ever builds a `wordIndex` in this window, and F2's
|
|
1132
|
+
* hazard was this exact late-hydration path nulling that live index from a
|
|
1133
|
+
* disk copy that predated it — removing the parameter removes the hazard by
|
|
1134
|
+
* construction instead of merely guarding against it at runtime.
|
|
1135
|
+
*/
|
|
1136
|
+
export function hydrateRuntimeFromProjectSnapshotIfIdle(runtime, snapshot) {
|
|
1137
|
+
let hydratedAnything = false;
|
|
1138
|
+
if (runtime.cachedExports.size === 0 && snapshot.cachedExports.length > 0) {
|
|
1139
|
+
runtime.cachedExports.clear();
|
|
1140
|
+
for (const [name, filePath] of snapshot.cachedExports) {
|
|
1141
|
+
runtime.cachedExports.set(name, filePath);
|
|
1142
|
+
}
|
|
1143
|
+
hydratedAnything = true;
|
|
1144
|
+
}
|
|
1145
|
+
if (!runtime.projectRulesScan.hasCustomRules &&
|
|
1146
|
+
runtime.projectRulesScan.rules.length === 0 &&
|
|
1147
|
+
snapshot.projectRulesScan) {
|
|
1148
|
+
runtime.projectRulesScan = snapshot.projectRulesScan;
|
|
1149
|
+
hydratedAnything = true;
|
|
1150
|
+
}
|
|
1151
|
+
return hydratedAnything;
|
|
1152
|
+
}
|
|
854
1153
|
export function saveRuntimeProjectSnapshot(args) {
|
|
855
1154
|
try {
|
|
856
1155
|
if (typeof args.runtime.projectSeq !== "number")
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Quiet-window kill switch and wait budget, split out of `quiet-window.ts` so a
|
|
3
|
+
* caller that only needs the NUMBERS does not have to import the scheduler.
|
|
4
|
+
*
|
|
5
|
+
* `cascade-budget.ts` is the caller that forced it (#1462): it reads both knobs
|
|
6
|
+
* to decide how much drain is really left, and depending on `quiet-window.ts`
|
|
7
|
+
* for that would point a pure arithmetic module at a task registry — module
|
|
8
|
+
* state (`_tasks`, `_inProgress`), a heartbeat sampler, latency logging, none
|
|
9
|
+
* of which it wants. Config belongs below the scheduler, not beside it.
|
|
10
|
+
*
|
|
11
|
+
* NOT a load-time win, despite what the first version of this comment claimed:
|
|
12
|
+
* `cascade-budget.ts` imports `runtime-config.ts` for `cascadeMaxFiles`, and
|
|
13
|
+
* that reaches `pidusage` through `lens-config.ts` regardless — probed, and
|
|
14
|
+
* `dispatch/integration.ts` already imported `runtime-config.ts` before #1462.
|
|
15
|
+
* The split is a dependency-direction fix and nothing more.
|
|
16
|
+
*
|
|
17
|
+
* `quiet-window.ts` re-exports all three, so every existing importer keeps
|
|
18
|
+
* working and there is still exactly one memo behind `isQuietWindowEnabled`.
|
|
19
|
+
*/
|
|
20
|
+
import { toPositiveFinite } from "./env-utils.js";
|
|
21
|
+
let _enabledCache;
|
|
22
|
+
/** `PI_LENS_QUIET_WINDOW=0` disables the whole scheduler (no-op, no logging). */
|
|
23
|
+
export function isQuietWindowEnabled() {
|
|
24
|
+
if (_enabledCache !== undefined)
|
|
25
|
+
return _enabledCache;
|
|
26
|
+
_enabledCache = process.env.PI_LENS_QUIET_WINDOW !== "0";
|
|
27
|
+
return _enabledCache;
|
|
28
|
+
}
|
|
29
|
+
/** Test-only: clear the memoized kill-switch read. */
|
|
30
|
+
export function _resetQuietWindowEnabledForTests() {
|
|
31
|
+
_enabledCache = undefined;
|
|
32
|
+
}
|
|
33
|
+
const DEFAULT_QUIET_WINDOW_WAIT_MS = 15_000;
|
|
34
|
+
/**
|
|
35
|
+
* Bounded wait for the quiet-window's own settle attempts (currently just
|
|
36
|
+
* the carried-over cascade drain). Lazy env read, `Number.isFinite`-guarded
|
|
37
|
+
* so a malformed value falls back to the default instead of poisoning
|
|
38
|
+
* `Math.max`/`setTimeout` with `NaN` (see PR #109).
|
|
39
|
+
*
|
|
40
|
+
* This is the task's BUDGET, not a statement that the task runs — it keeps
|
|
41
|
+
* returning the default when `isQuietWindowEnabled()` is false. Callers asking
|
|
42
|
+
* "how long will the pipeline actually keep working on this" must check both.
|
|
43
|
+
*/
|
|
44
|
+
export function quietWindowWaitMs() {
|
|
45
|
+
const raw = toPositiveFinite(process.env.PI_LENS_QUIET_WINDOW_WAIT_MS);
|
|
46
|
+
return raw > 0 ? raw : DEFAULT_QUIET_WINDOW_WAIT_MS;
|
|
47
|
+
}
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
import { readInstanceRegistry, updateHeartbeat, } from "./instance-registry.js";
|
|
33
33
|
import { logLatency } from "./latency-logger.js";
|
|
34
34
|
import { sampleProcesses } from "./resource-sampler.js";
|
|
35
|
-
import {
|
|
35
|
+
import { _resetQuietWindowEnabledForTests, isQuietWindowEnabled, quietWindowWaitMs, } from "./quiet-window-config.js";
|
|
36
36
|
// Module-level registry so future work (#458 Tier-3 reconcile, #236
|
|
37
37
|
// enrichment) can plug into the same scheduler without touching it.
|
|
38
38
|
const _tasks = [];
|
|
@@ -48,30 +48,14 @@ export function registerQuietWindowTask(name, fn) {
|
|
|
48
48
|
export function _resetQuietWindowTasksForTests() {
|
|
49
49
|
_tasks.length = 0;
|
|
50
50
|
}
|
|
51
|
-
// --- Kill switch
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
}
|
|
60
|
-
/** Test-only: clear the memoized kill-switch read. */
|
|
61
|
-
export function _resetQuietWindowEnabledForTests() {
|
|
62
|
-
_enabledCache = undefined;
|
|
63
|
-
}
|
|
64
|
-
const DEFAULT_QUIET_WINDOW_WAIT_MS = 15_000;
|
|
65
|
-
/**
|
|
66
|
-
* Bounded wait for the quiet-window's own settle attempts (currently just
|
|
67
|
-
* the carried-over cascade drain). Lazy env read, `Number.isFinite`-guarded
|
|
68
|
-
* so a malformed value falls back to the default instead of poisoning
|
|
69
|
-
* `Math.max`/`setTimeout` with `NaN` (see PR #109).
|
|
70
|
-
*/
|
|
71
|
-
export function quietWindowWaitMs() {
|
|
72
|
-
const raw = toPositiveFinite(process.env.PI_LENS_QUIET_WINDOW_WAIT_MS);
|
|
73
|
-
return raw > 0 ? raw : DEFAULT_QUIET_WINDOW_WAIT_MS;
|
|
74
|
-
}
|
|
51
|
+
// --- Kill switch and wait budget ---
|
|
52
|
+
//
|
|
53
|
+
// #1462 review (N4): both live in `quiet-window-config.ts` now, so a caller
|
|
54
|
+
// that needs only the numbers (`cascade-budget.ts`, on the dispatch load path)
|
|
55
|
+
// does not drag this module's `resource-sampler` → `pidusage` import in with
|
|
56
|
+
// them. Re-exported here so every existing importer is unaffected and there is
|
|
57
|
+
// still one memo behind `isQuietWindowEnabled`.
|
|
58
|
+
export { isQuietWindowEnabled, quietWindowWaitMs, _resetQuietWindowEnabledForTests, };
|
|
75
59
|
// Re-entrancy guard: agent_settled can fire multiple times per session
|
|
76
60
|
// (once per completed/aborted run). If a previous quiet-window run is still
|
|
77
61
|
// in flight when the next fires, skip rather than queue/overlap.
|
|
@@ -224,6 +208,8 @@ async function buildHeartbeatResourcePatch() {
|
|
|
224
208
|
const self = instances.find((instance) => instance.pid === process.pid);
|
|
225
209
|
const childPids = self?.lspChildren.map((child) => child.pid) ?? [];
|
|
226
210
|
const usage = await sampleProcesses([process.pid, ...childPids]);
|
|
211
|
+
if (usage === null)
|
|
212
|
+
return {};
|
|
227
213
|
const childUsage = {};
|
|
228
214
|
for (const pid of childPids) {
|
|
229
215
|
const sample = usage.get(pid);
|
|
@@ -19,7 +19,7 @@ const SNAPSHOT_LOG_SETTING = (process.env.PI_LENS_READ_GUARD_LOG_SNAPSHOTS ?? "1
|
|
|
19
19
|
const LOG_SNAPSHOT_VALIDATION = !["0", "false", "off"].includes(SNAPSHOT_LOG_SETTING);
|
|
20
20
|
export const MAX_EDIT_BATCH_ITEMS = 100;
|
|
21
21
|
let generatedCorrelationCounter = 0;
|
|
22
|
-
function sanitizeCorrelationId(value) {
|
|
22
|
+
export function sanitizeCorrelationId(value) {
|
|
23
23
|
if (typeof value !== "string" && typeof value !== "number")
|
|
24
24
|
return undefined;
|
|
25
25
|
const sanitized = String(value)
|
|
@@ -112,7 +112,7 @@ export function createReadGuardEditBatchSummary(args) {
|
|
|
112
112
|
durationMs: Math.max(0, Math.min(args.durationMs ?? 0, 86_400_000)),
|
|
113
113
|
};
|
|
114
114
|
}
|
|
115
|
-
function shouldLogEvent(event) {
|
|
115
|
+
export function shouldLogEvent(event) {
|
|
116
116
|
if (VERBOSE_READ_GUARD_LOG)
|
|
117
117
|
return true;
|
|
118
118
|
if (event === "edit_allowed")
|
|
@@ -134,7 +134,12 @@ function shouldLogEvent(event) {
|
|
|
134
134
|
event === "edit_post_edit_pipeline_failed" ||
|
|
135
135
|
event === "edit_batch_summary" ||
|
|
136
136
|
event === "edit_batch_summary_overflow" ||
|
|
137
|
-
event === "touched_lines_missing"
|
|
137
|
+
event === "touched_lines_missing" ||
|
|
138
|
+
// #1913: read-guard record-cap evictions are rare by construction (only
|
|
139
|
+
// READ_GUARD_MAX_RECORDS_PER_FILE overflow triggers one), so this trim
|
|
140
|
+
// record bypasses the per-read verbosity gate — a live eviction
|
|
141
|
+
// regression must be visible without PI_LENS_READ_GUARD_VERBOSE=1.
|
|
142
|
+
event === "read_cap_trimmed");
|
|
138
143
|
}
|
|
139
144
|
const MAX_TELEMETRY_STRING = 512;
|
|
140
145
|
const MAX_TELEMETRY_KEYS = 64;
|