@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
|
@@ -9,20 +9,277 @@
|
|
|
9
9
|
* session's actual cacheRead/cacheWrite behavior is queryable after the
|
|
10
10
|
* fact. This is what the provider DID, not what we hoped it would do.
|
|
11
11
|
*
|
|
12
|
-
* 2. Request-side
|
|
12
|
+
* 2. Request-side context observations (`cache_context`) — one bounded record
|
|
13
|
+
* for every `context` call, describing pi-lens's own before/after message
|
|
14
|
+
* transformation, placement, injection sources, and privacy-preserving
|
|
15
|
+
* hashes. This is what pi-lens observed locally, not the final provider
|
|
16
|
+
* request after other context handlers have run and not a provider cache
|
|
17
|
+
* result.
|
|
18
|
+
*
|
|
19
|
+
* 3. Request-side prefix stability (`cache_prefix_break`) — a content hash of
|
|
13
20
|
* `messages[0]` observed on every `context` call. After #1016 the first
|
|
14
21
|
* message must stay byte-stable across a whole session; a logged CHANGE
|
|
15
|
-
* flags that something (pi-lens or otherwise) broke the cache prefix
|
|
16
|
-
*
|
|
17
|
-
* provider. Pure observation — it never alters context injection.
|
|
22
|
+
* flags that something (pi-lens or otherwise) broke the cache prefix. This
|
|
23
|
+
* remains a local observation, never a provider cache-miss claim.
|
|
18
24
|
*
|
|
19
|
-
*
|
|
25
|
+
* All paths are defensive: `usage` (and its fields) may be absent on older
|
|
20
26
|
* hosts or non-assistant messages, so every access is guarded and the handlers
|
|
21
27
|
* never throw — on error they `dbg(...)` and no-op, like the other index.ts
|
|
22
28
|
* event handlers.
|
|
23
29
|
*/
|
|
24
30
|
import { createHash } from "node:crypto";
|
|
25
31
|
import { logLatency } from "./latency-logger.js";
|
|
32
|
+
/** RuntimeCoordinator's counter is process-global when sessions share a host. */
|
|
33
|
+
const PROCESS_TURN_SCOPE = "process-global-runtime";
|
|
34
|
+
const SECONDARY_TURN_SCOPE = "unavailable-concurrent-secondary";
|
|
35
|
+
/**
|
|
36
|
+
* Keep context telemetry bounded even when a tool result or user message is
|
|
37
|
+
* unexpectedly large. This is a hash input only; none of the sampled text is
|
|
38
|
+
* written to the log.
|
|
39
|
+
*/
|
|
40
|
+
const MAX_HASHED_MESSAGES = 64;
|
|
41
|
+
const MAX_HASHED_CONTENT_CHARS = 2048;
|
|
42
|
+
const MAX_REPORTED_MESSAGES = 10_000;
|
|
43
|
+
const MAX_INJECTED_CHARS = 16_384;
|
|
44
|
+
const MAX_INJECTED_BYTES = 65_536;
|
|
45
|
+
let contextObservationCounter = 0;
|
|
46
|
+
function boundedHashScalar(value, state) {
|
|
47
|
+
if (value === null)
|
|
48
|
+
return "null";
|
|
49
|
+
if (value === undefined)
|
|
50
|
+
return "undefined";
|
|
51
|
+
if (typeof value === "string") {
|
|
52
|
+
const truncated = value.length > MAX_HASHED_CONTENT_CHARS;
|
|
53
|
+
if (truncated)
|
|
54
|
+
state.contentTruncated = true;
|
|
55
|
+
const suffix = truncated ? ":content-truncated" : "";
|
|
56
|
+
return `string:${value.length}:${value.slice(0, MAX_HASHED_CONTENT_CHARS)}${suffix}`;
|
|
57
|
+
}
|
|
58
|
+
if (typeof value === "number" ||
|
|
59
|
+
typeof value === "boolean" ||
|
|
60
|
+
typeof value === "bigint") {
|
|
61
|
+
return `${typeof value}:${String(value)}`;
|
|
62
|
+
}
|
|
63
|
+
return typeof value;
|
|
64
|
+
}
|
|
65
|
+
function boundedHashArray(value, depth, seen, state) {
|
|
66
|
+
if (value.length > 12)
|
|
67
|
+
state.contentTruncated = true;
|
|
68
|
+
const items = value
|
|
69
|
+
.slice(0, 12)
|
|
70
|
+
.map((item) => boundedHashValue(item, depth + 1, seen, state));
|
|
71
|
+
return `array:${value.length}:[${items.join(",")}]`;
|
|
72
|
+
}
|
|
73
|
+
function boundedHashObject(value, depth, seen, state) {
|
|
74
|
+
const keys = Object.keys(value).sort((left, right) => left.localeCompare(right));
|
|
75
|
+
if (keys.length > 24)
|
|
76
|
+
state.contentTruncated = true;
|
|
77
|
+
const fields = keys
|
|
78
|
+
.slice(0, 24)
|
|
79
|
+
.map((key) => `${key}:${boundedHashValue(value[key], depth + 1, seen, state)}`);
|
|
80
|
+
return `object:${keys.length}:{${fields.join(",")}}`;
|
|
81
|
+
}
|
|
82
|
+
function boundedHashValue(value, depth = 0, seen = new Set(), state) {
|
|
83
|
+
const hashState = state ?? { contentTruncated: false };
|
|
84
|
+
if (value === null || typeof value !== "object") {
|
|
85
|
+
return boundedHashScalar(value, hashState);
|
|
86
|
+
}
|
|
87
|
+
if (depth >= 3) {
|
|
88
|
+
hashState.contentTruncated = true;
|
|
89
|
+
return Object.prototype.toString.call(value);
|
|
90
|
+
}
|
|
91
|
+
if (seen.has(value))
|
|
92
|
+
return "[cycle]";
|
|
93
|
+
seen.add(value);
|
|
94
|
+
try {
|
|
95
|
+
if (Array.isArray(value)) {
|
|
96
|
+
return boundedHashArray(value, depth, seen, hashState);
|
|
97
|
+
}
|
|
98
|
+
return boundedHashObject(value, depth, seen, hashState);
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
return "[unreadable]";
|
|
102
|
+
}
|
|
103
|
+
finally {
|
|
104
|
+
seen.delete(value);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
function hashMessageSequence(messages) {
|
|
108
|
+
const hash = createHash("sha256");
|
|
109
|
+
const state = { contentTruncated: false };
|
|
110
|
+
hash.update(`message-count:${messages.length};`);
|
|
111
|
+
const sampled = Math.min(messages.length, MAX_HASHED_MESSAGES);
|
|
112
|
+
for (let i = 0; i < sampled; i++) {
|
|
113
|
+
const message = messages[i];
|
|
114
|
+
const seen = new Set();
|
|
115
|
+
hash.update(`${i}|role:${boundedHashValue(message?.role, 0, seen, state)}|content:${boundedHashValue(message?.content, 0, seen, state)};`);
|
|
116
|
+
}
|
|
117
|
+
const truncated = messages.length > sampled;
|
|
118
|
+
if (truncated)
|
|
119
|
+
hash.update(`truncated-after:${sampled};`);
|
|
120
|
+
return {
|
|
121
|
+
hash: hash.digest("hex"),
|
|
122
|
+
truncated,
|
|
123
|
+
contentTruncated: state.contentTruncated,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
function messageTextSize(content) {
|
|
127
|
+
if (typeof content === "string") {
|
|
128
|
+
const chars = Math.min(content.length, MAX_INJECTED_CHARS);
|
|
129
|
+
return {
|
|
130
|
+
chars,
|
|
131
|
+
bytes: Math.min(Buffer.byteLength(content.slice(0, chars), "utf8"), MAX_INJECTED_BYTES),
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
const bounded = boundedHashValue(content);
|
|
135
|
+
return {
|
|
136
|
+
chars: Math.min(bounded.length, MAX_INJECTED_CHARS),
|
|
137
|
+
bytes: Math.min(Buffer.byteLength(bounded.slice(0, MAX_INJECTED_CHARS), "utf8"), MAX_INJECTED_BYTES),
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
function measureInjectedMessages(messages) {
|
|
141
|
+
let chars = 0;
|
|
142
|
+
let bytes = 0;
|
|
143
|
+
const measuredCount = Math.min(messages.length, MAX_REPORTED_MESSAGES);
|
|
144
|
+
for (let i = 0; i < measuredCount; i++) {
|
|
145
|
+
const message = messages[i];
|
|
146
|
+
const size = messageTextSize(message?.content);
|
|
147
|
+
chars = Math.min(MAX_INJECTED_CHARS, chars + size.chars);
|
|
148
|
+
bytes = Math.min(MAX_INJECTED_BYTES, bytes + size.bytes);
|
|
149
|
+
if (chars === MAX_INJECTED_CHARS || bytes === MAX_INJECTED_BYTES)
|
|
150
|
+
break;
|
|
151
|
+
}
|
|
152
|
+
return {
|
|
153
|
+
chars,
|
|
154
|
+
bytes,
|
|
155
|
+
capped: chars >= MAX_INJECTED_CHARS || bytes >= MAX_INJECTED_BYTES,
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
function sessionKey(sessionId) {
|
|
159
|
+
return sessionId?.trim() ? sessionId.trim() : NO_SESSION_KEY;
|
|
160
|
+
}
|
|
161
|
+
function prefixLengthForPlacement(placement, messageCount) {
|
|
162
|
+
if (placement === "insert-before-final") {
|
|
163
|
+
return Math.max(0, messageCount - 1);
|
|
164
|
+
}
|
|
165
|
+
if (placement === "prepend")
|
|
166
|
+
return 0;
|
|
167
|
+
return messageCount;
|
|
168
|
+
}
|
|
169
|
+
function resolvePrefixObservation(truncated, observation) {
|
|
170
|
+
if (truncated)
|
|
171
|
+
return "unknown";
|
|
172
|
+
return observation ?? "empty";
|
|
173
|
+
}
|
|
174
|
+
function prefixBaselineForObservation(observation) {
|
|
175
|
+
if (observation === "baseline")
|
|
176
|
+
return true;
|
|
177
|
+
if (observation === "empty" || observation === "unknown")
|
|
178
|
+
return null;
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
181
|
+
function firstMessageChangeFor(truncated, before, after) {
|
|
182
|
+
if (truncated)
|
|
183
|
+
return "unknown";
|
|
184
|
+
return before !== after ? "changed" : "unchanged";
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Log one bounded request-side observation for every `context` call. This is
|
|
188
|
+
* deliberately a separate phase from `cache_prefix_break`: it describes the
|
|
189
|
+
* messages pi-lens saw and returned from its own context handler, not the final
|
|
190
|
+
* provider request after other context handlers and not whether a provider
|
|
191
|
+
* reused or missed a prompt cache. `observationId` is local to this process; the
|
|
192
|
+
* host currently exposes no request id on ContextEvent/MessageEndEvent. A
|
|
193
|
+
* RuntimeCoordinator turn is process-global, so it is explicitly scoped as
|
|
194
|
+
* such and is omitted for concurrent secondary sessions.
|
|
195
|
+
*/
|
|
196
|
+
export function observeCacheContext(args) {
|
|
197
|
+
try {
|
|
198
|
+
const existingMessages = args.existingMessages ?? [];
|
|
199
|
+
const resultMessages = args.resultMessages ?? existingMessages;
|
|
200
|
+
const injectedMessages = args.injectedMessages ?? [];
|
|
201
|
+
const placement = args.placement ?? "none";
|
|
202
|
+
const beforeSequence = hashMessageSequence(existingMessages);
|
|
203
|
+
const afterSequence = hashMessageSequence(resultMessages);
|
|
204
|
+
const beforePrefixLength = prefixLengthForPlacement(placement, existingMessages.length);
|
|
205
|
+
const afterPrefixLength = Math.min(beforePrefixLength, resultMessages.length);
|
|
206
|
+
const beforePrefix = hashMessageSequence(existingMessages.slice(0, beforePrefixLength));
|
|
207
|
+
const afterPrefix = hashMessageSequence(resultMessages.slice(0, afterPrefixLength));
|
|
208
|
+
const beforeFirstSequence = existingMessages.length
|
|
209
|
+
? hashMessageSequence([existingMessages[0]])
|
|
210
|
+
: undefined;
|
|
211
|
+
const afterFirstSequence = resultMessages.length
|
|
212
|
+
? hashMessageSequence([resultMessages[0]])
|
|
213
|
+
: undefined;
|
|
214
|
+
const beforeFirst = beforeFirstSequence?.hash ?? null;
|
|
215
|
+
const afterFirst = afterFirstSequence?.hash ?? null;
|
|
216
|
+
const firstMessageHashTruncated = beforeFirstSequence?.truncated === true ||
|
|
217
|
+
beforeFirstSequence?.contentTruncated === true ||
|
|
218
|
+
afterFirstSequence?.truncated === true ||
|
|
219
|
+
afterFirstSequence?.contentTruncated === true;
|
|
220
|
+
const prefixHashTruncated = beforePrefix.truncated ||
|
|
221
|
+
afterPrefix.truncated ||
|
|
222
|
+
beforePrefix.contentTruncated ||
|
|
223
|
+
afterPrefix.contentTruncated;
|
|
224
|
+
const prefixObservation = resolvePrefixObservation(prefixHashTruncated, args.prefixObservation);
|
|
225
|
+
const sizes = measureInjectedMessages(injectedMessages);
|
|
226
|
+
const messageCountCapped = existingMessages.length > MAX_REPORTED_MESSAGES ||
|
|
227
|
+
resultMessages.length > MAX_REPORTED_MESSAGES;
|
|
228
|
+
logLatency({
|
|
229
|
+
type: "phase",
|
|
230
|
+
filePath: "<pi-lens>",
|
|
231
|
+
phase: "cache_context",
|
|
232
|
+
durationMs: 0,
|
|
233
|
+
metadata: {
|
|
234
|
+
version: 1,
|
|
235
|
+
observedStage: "pi-lens-context-handler",
|
|
236
|
+
observationId: `ctx-${(++contextObservationCounter).toString(36)}`,
|
|
237
|
+
sessionId: sessionKey(args.sessionId),
|
|
238
|
+
sessionRole: args.sessionRole,
|
|
239
|
+
...(args.sessionRole === "concurrent-secondary"
|
|
240
|
+
? { turnScope: SECONDARY_TURN_SCOPE }
|
|
241
|
+
: { turnIndex: args.turnIndex, turnScope: PROCESS_TURN_SCOPE }),
|
|
242
|
+
injectionEnabled: args.injectionEnabled,
|
|
243
|
+
injectionSources: Array.from(args.injectionSources ?? []),
|
|
244
|
+
injectedMessageCount: Math.min(injectedMessages.length, MAX_REPORTED_MESSAGES),
|
|
245
|
+
injectedMessageCountCapped: injectedMessages.length > MAX_REPORTED_MESSAGES,
|
|
246
|
+
injectedChars: sizes.chars,
|
|
247
|
+
injectedBytes: sizes.bytes,
|
|
248
|
+
injectedCountsCapped: sizes.capped,
|
|
249
|
+
existingMessageCount: Math.min(existingMessages.length, MAX_REPORTED_MESSAGES),
|
|
250
|
+
resultMessageCount: Math.min(resultMessages.length, MAX_REPORTED_MESSAGES),
|
|
251
|
+
messageCountCapped,
|
|
252
|
+
placement,
|
|
253
|
+
prefixObservation,
|
|
254
|
+
prefixObservationUnknown: prefixObservation === "unknown",
|
|
255
|
+
prefixBaseline: prefixBaselineForObservation(prefixObservation),
|
|
256
|
+
firstMessageChanged: firstMessageHashTruncated
|
|
257
|
+
? null
|
|
258
|
+
: beforeFirst !== afterFirst,
|
|
259
|
+
firstMessageChange: firstMessageChangeFor(firstMessageHashTruncated, beforeFirst, afterFirst),
|
|
260
|
+
firstMessageHashTruncated,
|
|
261
|
+
beforeFirstMessageHash: beforeFirst,
|
|
262
|
+
afterFirstMessageHash: afterFirst,
|
|
263
|
+
beforeSequenceHash: beforeSequence.hash,
|
|
264
|
+
afterSequenceHash: afterSequence.hash,
|
|
265
|
+
beforePrefixHash: beforePrefix.hash,
|
|
266
|
+
afterPrefixHash: afterPrefix.hash,
|
|
267
|
+
sequenceHashTruncated: beforeSequence.truncated ||
|
|
268
|
+
afterSequence.truncated ||
|
|
269
|
+
beforeSequence.contentTruncated ||
|
|
270
|
+
afterSequence.contentTruncated,
|
|
271
|
+
sequenceMessageCountTruncated: beforeSequence.truncated || afterSequence.truncated,
|
|
272
|
+
sequenceContentHashTruncated: beforeSequence.contentTruncated || afterSequence.contentTruncated,
|
|
273
|
+
prefixHashTruncated,
|
|
274
|
+
prefixMessageCountTruncated: beforePrefix.truncated || afterPrefix.truncated,
|
|
275
|
+
prefixContentHashTruncated: beforePrefix.contentTruncated || afterPrefix.contentTruncated,
|
|
276
|
+
},
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
catch (err) {
|
|
280
|
+
args.dbg?.(`cache-context: failed to log context observation: ${err}`);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
26
283
|
/**
|
|
27
284
|
* Part 1 — log one `cache_usage` record for an assistant `message_end` that
|
|
28
285
|
* carries a `usage`. Provider/model come straight off the message itself
|
|
@@ -31,7 +288,7 @@ import { logLatency } from "./latency-logger.js";
|
|
|
31
288
|
* not an assistant message or has no usage; never logs a zeros-only record for
|
|
32
289
|
* a message that simply lacks usage.
|
|
33
290
|
*/
|
|
34
|
-
export function logCacheUsage(message, dbg) {
|
|
291
|
+
export function logCacheUsage(message, dbg, context) {
|
|
35
292
|
try {
|
|
36
293
|
if (!message || typeof message !== "object")
|
|
37
294
|
return;
|
|
@@ -58,6 +315,24 @@ export function logCacheUsage(message, dbg) {
|
|
|
58
315
|
output: u.output,
|
|
59
316
|
// `Usage.cost` is a breakdown object; the total is the headline number.
|
|
60
317
|
cost: u.cost?.total,
|
|
318
|
+
...(context
|
|
319
|
+
? {
|
|
320
|
+
// MessageEndEvent has no request/context id in the host API. These
|
|
321
|
+
// fields permit session correlation without inventing an exact
|
|
322
|
+
// provider-request linkage. The process-global turn is omitted
|
|
323
|
+
// for a concurrent secondary session.
|
|
324
|
+
sessionId: sessionKey(context.sessionId),
|
|
325
|
+
...(context.sessionRole === "concurrent-secondary"
|
|
326
|
+
? { turnScope: SECONDARY_TURN_SCOPE }
|
|
327
|
+
: {
|
|
328
|
+
turnIndex: context.turnIndex,
|
|
329
|
+
turnScope: PROCESS_TURN_SCOPE,
|
|
330
|
+
}),
|
|
331
|
+
contextCorrelation: context.sessionId
|
|
332
|
+
? "session-only-no-request-id"
|
|
333
|
+
: "no-stable-session-id",
|
|
334
|
+
}
|
|
335
|
+
: {}),
|
|
61
336
|
},
|
|
62
337
|
});
|
|
63
338
|
}
|
|
@@ -71,7 +346,13 @@ export function logCacheUsage(message, dbg) {
|
|
|
71
346
|
* `messages[0]` actually changed byte-for-byte.
|
|
72
347
|
*/
|
|
73
348
|
function hashFirstMessage(first) {
|
|
74
|
-
|
|
349
|
+
// Keep the original full local hash semantics for the existing
|
|
350
|
+
// `cache_prefix_break` signal. The new `cache_context` hashes above are the
|
|
351
|
+
// bounded hashes; this signal must not silently miss a suffix-only change.
|
|
352
|
+
const serialized = JSON.stringify({
|
|
353
|
+
role: first.role,
|
|
354
|
+
content: first.content,
|
|
355
|
+
});
|
|
75
356
|
return createHash("sha256").update(serialized).digest("hex");
|
|
76
357
|
}
|
|
77
358
|
/**
|
|
@@ -144,11 +425,11 @@ function recordSessionHash(key, hash) {
|
|
|
144
425
|
export function observeCachePrefix(messages, turnIndex, sessionId, sessionRole, dbg) {
|
|
145
426
|
try {
|
|
146
427
|
if (!messages || messages.length === 0)
|
|
147
|
-
return;
|
|
428
|
+
return "empty";
|
|
148
429
|
const first = messages[0];
|
|
149
430
|
if (!first || typeof first !== "object")
|
|
150
|
-
return;
|
|
151
|
-
const key =
|
|
431
|
+
return "empty";
|
|
432
|
+
const key = sessionKey(sessionId);
|
|
152
433
|
const currentHash = hashFirstMessage(first);
|
|
153
434
|
const previousHash = prefixHashBySession.get(key);
|
|
154
435
|
if (previousHash === undefined) {
|
|
@@ -161,7 +442,9 @@ export function observeCachePrefix(messages, turnIndex, sessionId, sessionRole,
|
|
|
161
442
|
phase: "cache_prefix_break",
|
|
162
443
|
durationMs: 0,
|
|
163
444
|
metadata: {
|
|
164
|
-
|
|
445
|
+
...(sessionRole === "concurrent-secondary"
|
|
446
|
+
? { turnScope: SECONDARY_TURN_SCOPE }
|
|
447
|
+
: { turnIndex, turnScope: PROCESS_TURN_SCOPE }),
|
|
165
448
|
previousHash: null,
|
|
166
449
|
currentHash,
|
|
167
450
|
baseline: true,
|
|
@@ -169,7 +452,7 @@ export function observeCachePrefix(messages, turnIndex, sessionId, sessionRole,
|
|
|
169
452
|
sessionRole,
|
|
170
453
|
},
|
|
171
454
|
});
|
|
172
|
-
return;
|
|
455
|
+
return "baseline";
|
|
173
456
|
}
|
|
174
457
|
if (currentHash !== previousHash) {
|
|
175
458
|
logLatency({
|
|
@@ -178,7 +461,9 @@ export function observeCachePrefix(messages, turnIndex, sessionId, sessionRole,
|
|
|
178
461
|
phase: "cache_prefix_break",
|
|
179
462
|
durationMs: 0,
|
|
180
463
|
metadata: {
|
|
181
|
-
|
|
464
|
+
...(sessionRole === "concurrent-secondary"
|
|
465
|
+
? { turnScope: SECONDARY_TURN_SCOPE }
|
|
466
|
+
: { turnIndex, turnScope: PROCESS_TURN_SCOPE }),
|
|
182
467
|
previousHash,
|
|
183
468
|
currentHash,
|
|
184
469
|
sessionId: key,
|
|
@@ -189,9 +474,11 @@ export function observeCachePrefix(messages, turnIndex, sessionId, sessionRole,
|
|
|
189
474
|
// Refresh recency (and update the stored hash after a break) so an active
|
|
190
475
|
// session stays warm in the LRU and isn't evicted while still in use.
|
|
191
476
|
recordSessionHash(key, currentHash);
|
|
477
|
+
return currentHash === previousHash ? "unchanged" : "changed";
|
|
192
478
|
}
|
|
193
479
|
catch (err) {
|
|
194
480
|
dbg?.(`cache-prefix: failed to observe messages[0]: ${err}`);
|
|
481
|
+
return "empty";
|
|
195
482
|
}
|
|
196
483
|
}
|
|
197
484
|
/**
|
|
@@ -202,7 +489,7 @@ export function observeCachePrefix(messages, turnIndex, sessionId, sessionRole,
|
|
|
202
489
|
* evicts it. Idempotent and never throws.
|
|
203
490
|
*/
|
|
204
491
|
export function clearCachePrefixSession(sessionId) {
|
|
205
|
-
const key =
|
|
492
|
+
const key = sessionKey(sessionId);
|
|
206
493
|
prefixHashBySession.delete(key);
|
|
207
494
|
}
|
|
208
495
|
/** Clear all per-session prefix hashes. For tests / session boundaries. */
|