@herbertgao/pi-extensions 2026.8.15 → 2026.9.1
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 +4 -1
- package/THIRD_PARTY_NOTICES.md +26 -0
- package/node_modules/@czottmann/pi-automode/CHANGELOG.md +13 -1
- package/node_modules/@czottmann/pi-automode/README.md +20 -0
- package/node_modules/@czottmann/pi-automode/docs/GLOSSARY.md +1 -1
- package/node_modules/@czottmann/pi-automode/docs/automode-classifier-flow.md +2 -1
- package/node_modules/@czottmann/pi-automode/docs/defaults.md +3 -2
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/classifier.ts +38 -2
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/constants.ts +5 -3
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/extension.ts +11 -3
- package/node_modules/@czottmann/pi-automode/package.json +1 -1
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/config.ts +20 -0
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +46 -3
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/interaction.ts +55 -17
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/packets.ts +6 -0
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/scroll.ts +5 -0
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/result.ts +34 -30
- package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
- package/node_modules/@juicesharp/rpiv-ask-user-question/package.json +2 -2
- package/node_modules/@narumitw/pi-btw/README.md +5 -1
- package/node_modules/@narumitw/pi-btw/dist/index.ts +143 -14
- package/node_modules/@narumitw/pi-btw/dist/index.ts.map +3 -3
- package/node_modules/@narumitw/pi-btw/package.json +4 -4
- package/node_modules/@narumitw/pi-btw/src/fullscreen-ui.ts +158 -7
- package/node_modules/@narumitw/pi-btw/src/text.ts +18 -0
- package/node_modules/@narumitw/pi-btw/src/transcript-pager.ts +5 -16
- package/node_modules/@narumitw/pi-caffeinate/LICENSE +21 -0
- package/node_modules/@narumitw/pi-caffeinate/README.md +224 -0
- package/node_modules/@narumitw/pi-caffeinate/dist/index.ts +1112 -0
- package/node_modules/@narumitw/pi-caffeinate/dist/index.ts.map +7 -0
- package/node_modules/@narumitw/pi-caffeinate/package.json +53 -0
- package/node_modules/@narumitw/pi-caffeinate/src/caffeinate.ts +811 -0
- package/node_modules/@narumitw/pi-caffeinate/src/dbus-inhibit.ts +153 -0
- package/node_modules/@narumitw/pi-caffeinate/src/index.ts +1 -0
- package/node_modules/@narumitw/pi-caffeinate/src/inhibitor-process.ts +43 -0
- package/node_modules/@narumitw/pi-caffeinate/src/inhibitors.ts +167 -0
- package/node_modules/@narumitw/pi-caffeinate/src/settings.ts +202 -0
- package/node_modules/@pi-plugins/fast-mode/README.md +5 -3
- package/node_modules/@pi-plugins/fast-mode/dist/index.d.mts.map +1 -1
- package/node_modules/@pi-plugins/fast-mode/dist/index.mjs +20 -55
- package/node_modules/@pi-plugins/fast-mode/dist/index.mjs.map +1 -1
- package/node_modules/@pi-plugins/fast-mode/package.json +1 -1
- package/node_modules/@tifan/pi-handoff/README.md +6 -3
- package/node_modules/@tifan/pi-handoff/package.json +1 -1
- package/node_modules/@tifan/pi-handoff/src/index.ts +8 -3
- package/node_modules/pi-lens/CHANGELOG.md +988 -0
- package/node_modules/pi-lens/README.md +3 -0
- package/node_modules/pi-lens/config/biome/core.jsonc +11 -2
- package/node_modules/pi-lens/config/dependency-cruiser-eager-allowlist.json +13 -1
- package/node_modules/pi-lens/dist/clients/actionable-warnings-logger.js +2 -2
- package/node_modules/pi-lens/dist/clients/actionable-warnings.js +927 -80
- package/node_modules/pi-lens/dist/clients/agent-behavior-client.js +13 -4
- package/node_modules/pi-lens/dist/clients/ast-grep-client.js +123 -3
- package/node_modules/pi-lens/dist/clients/ast-grep-rule-manager.js +60 -5
- package/node_modules/pi-lens/dist/clients/ast-grep-tool-logger.js +2 -2
- package/node_modules/pi-lens/dist/clients/bash-file-access.js +1 -3
- package/node_modules/pi-lens/dist/clients/biome-client.js +9 -2
- package/node_modules/pi-lens/dist/clients/blocker-freshness.js +14 -0
- package/node_modules/pi-lens/dist/clients/bootstrap.js +509 -73
- package/node_modules/pi-lens/dist/clients/bounded-cache.js +152 -12
- package/node_modules/pi-lens/dist/clients/bounded-telemetry.js +59 -4
- package/node_modules/pi-lens/dist/clients/bundled-resource-health.js +113 -0
- package/node_modules/pi-lens/dist/clients/bus-events-logger.js +2 -2
- package/node_modules/pi-lens/dist/clients/cache/rule-cache.js +31 -4
- package/node_modules/pi-lens/dist/clients/cache-manager.js +105 -6
- package/node_modules/pi-lens/dist/clients/cache-observability.js +44 -18
- package/node_modules/pi-lens/dist/clients/cargo-manifest.js +422 -0
- package/node_modules/pi-lens/dist/clients/cascade-logger.js +2 -2
- package/node_modules/pi-lens/dist/clients/code-quality-warnings.js +13 -3
- package/node_modules/pi-lens/dist/clients/complexity-client.js +16 -5
- package/node_modules/pi-lens/dist/clients/config-core/deny.js +221 -0
- package/node_modules/pi-lens/dist/clients/config-core/index.js +47 -0
- package/node_modules/pi-lens/dist/clients/config-core/merge.js +357 -0
- package/node_modules/pi-lens/dist/clients/config-core/normalize.js +340 -0
- package/node_modules/pi-lens/dist/clients/config-core/process-spec.js +248 -0
- package/node_modules/pi-lens/dist/clients/config-core/provenance.js +171 -0
- package/node_modules/pi-lens/dist/clients/config-core/records.js +218 -0
- package/node_modules/pi-lens/dist/clients/config-core/resolve.js +125 -0
- package/node_modules/pi-lens/dist/clients/config-core/safe-object.js +78 -0
- package/node_modules/pi-lens/dist/clients/config-core/schema.js +167 -0
- package/node_modules/pi-lens/dist/clients/config-diagnostic-codes.js +281 -0
- package/node_modules/pi-lens/dist/clients/config-locations.js +160 -0
- package/node_modules/pi-lens/dist/clients/config-resolve.js +789 -0
- package/node_modules/pi-lens/dist/clients/config-schema.js +197 -0
- package/node_modules/pi-lens/dist/clients/config-warn.js +407 -0
- package/node_modules/pi-lens/dist/clients/dead-code-client.js +19 -14
- package/node_modules/pi-lens/dist/clients/dead-code-logger.js +2 -2
- package/node_modules/pi-lens/dist/clients/deadline-utils.js +178 -0
- package/node_modules/pi-lens/dist/clients/debug-handles.js +2 -2
- package/node_modules/pi-lens/dist/clients/debug-heap.js +3 -3
- package/node_modules/pi-lens/dist/clients/deferred-lsp-work.js +106 -0
- package/node_modules/pi-lens/dist/clients/degradation-ledger.js +113 -7
- package/node_modules/pi-lens/dist/clients/dependency-checker.js +8 -19
- package/node_modules/pi-lens/dist/clients/diagnostic-line-freshness.js +12 -9
- package/node_modules/pi-lens/dist/clients/diagnostic-logger.js +14 -4
- package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +162 -18
- package/node_modules/pi-lens/dist/clients/dispatch/fact-store.js +97 -0
- package/node_modules/pi-lens/dist/clients/dispatch/integration.js +9 -7
- package/node_modules/pi-lens/dist/clients/dispatch/runners/actionlint.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ast-grep-napi.js +380 -26
- package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/cpp-check.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/credo.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/cue-vet.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/dart-analyze.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/detekt.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/dotnet-build.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/elixir-check.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/eslint.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/fact-rules.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/fish-indent.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/gleam-check.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/go-vet.js +1 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/golangci-lint.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/hadolint.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-lint.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-render.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/htmlhint.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/javac.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ktlint.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/mypy.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/oxlint.js +13 -18
- package/node_modules/pi-lens/dist/clients/dispatch/runners/php-lint.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/phpstan.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/prisma-validate.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/psscriptanalyzer.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/pyright.js +7 -4
- package/node_modules/pi-lens/dist/clients/dispatch/runners/rubocop.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ruff.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/rust-clippy.js +1 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/shellcheck.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/shfmt.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/spellcheck.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/spotbugs.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/sqlfluff.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/stylelint.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/swiftlint.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/taplo.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/terragrunt.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/tflint.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/tree-sitter.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/trivy-config.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/availability-policy.js +3 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/diagnostic-parsers.js +3 -4
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +194 -80
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/toolchain-availability.js +84 -15
- package/node_modules/pi-lens/dist/clients/dispatch/runners/vale.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/yamllint.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/zig-check.js +0 -1
- package/node_modules/pi-lens/dist/clients/disposition-logger.js +3 -3
- package/node_modules/pi-lens/dist/clients/effective-config.js +403 -0
- package/node_modules/pi-lens/dist/clients/error-class.js +23 -0
- package/node_modules/pi-lens/dist/clients/event-loop-hold.js +274 -0
- package/node_modules/pi-lens/dist/clients/extension-log.js +2 -2
- package/node_modules/pi-lens/dist/clients/feature-hints.js +2 -1
- package/node_modules/pi-lens/dist/clients/file-time.js +6 -1
- package/node_modules/pi-lens/dist/clients/file-utils.js +112 -9
- package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +50 -13
- package/node_modules/pi-lens/dist/clients/format-service.js +6 -1
- package/node_modules/pi-lens/dist/clients/formatters.js +276 -102
- package/node_modules/pi-lens/dist/clients/freshness-cadence.js +17 -0
- package/node_modules/pi-lens/dist/clients/generated-artifacts.js +114 -19
- package/node_modules/pi-lens/dist/clients/generation-guard.js +4 -9
- package/node_modules/pi-lens/dist/clients/git-guard.js +1 -1
- package/node_modules/pi-lens/dist/clients/go-client.js +39 -0
- package/node_modules/pi-lens/dist/clients/gradle-ktfmt-style.js +252 -0
- package/node_modules/pi-lens/dist/clients/hashline-anchor.js +424 -0
- package/node_modules/pi-lens/dist/clients/hook-budgets.js +76 -0
- package/node_modules/pi-lens/dist/clients/host-edit-normalize.js +5 -2
- package/node_modules/pi-lens/dist/clients/host-ports.js +1 -1
- package/node_modules/pi-lens/dist/clients/installer/index.js +71 -52
- package/node_modules/pi-lens/dist/clients/instance-reaper.js +104 -230
- package/node_modules/pi-lens/dist/clients/instance-registry.js +6 -3
- package/node_modules/pi-lens/dist/clients/language-registry.js +595 -0
- package/node_modules/pi-lens/dist/clients/latency-logger.js +160 -2
- package/node_modules/pi-lens/dist/clients/ledger-bounds.js +13 -0
- package/node_modules/pi-lens/dist/clients/lens-config.js +141 -30
- package/node_modules/pi-lens/dist/clients/lens-engine.js +30 -37
- package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +59 -6
- package/node_modules/pi-lens/dist/clients/log-cleanup.js +2 -2
- package/node_modules/pi-lens/dist/clients/lsp/aggregation.js +3 -1
- package/node_modules/pi-lens/dist/clients/lsp/client.js +168 -30
- package/node_modules/pi-lens/dist/clients/lsp/config.js +483 -158
- package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +1 -1
- package/node_modules/pi-lens/dist/clients/lsp/edits.js +15 -2
- package/node_modules/pi-lens/dist/clients/lsp/index.js +676 -71
- package/node_modules/pi-lens/dist/clients/lsp/language.js +18 -169
- package/node_modules/pi-lens/dist/clients/lsp/launch.js +2 -1
- package/node_modules/pi-lens/dist/clients/lsp/pending-aux-coverage.js +5 -16
- package/node_modules/pi-lens/dist/clients/lsp/server.js +284 -147
- package/node_modules/pi-lens/dist/clients/lsp/session-roots.js +116 -23
- package/node_modules/pi-lens/dist/clients/lsp/spawn-history.js +2 -7
- package/node_modules/pi-lens/dist/clients/lsp/tsserver-sync.js +9 -2
- package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +1 -1
- package/node_modules/pi-lens/dist/clients/lsp-mutation.js +163 -21
- package/node_modules/pi-lens/dist/clients/map-with-concurrency.js +36 -0
- package/node_modules/pi-lens/dist/clients/mcp/analyze.js +33 -4
- package/node_modules/pi-lens/dist/clients/mcp/session.js +5 -16
- package/node_modules/pi-lens/dist/clients/memory-sampler.js +8 -3
- package/node_modules/pi-lens/dist/clients/middle-man-analysis.js +2 -4
- package/node_modules/pi-lens/dist/clients/module-report.js +20 -45
- package/node_modules/pi-lens/dist/clients/mutating-tool.js +651 -0
- package/node_modules/pi-lens/dist/clients/mutation-attribution.js +368 -0
- package/node_modules/pi-lens/dist/clients/mutation-bridge.js +240 -0
- package/node_modules/pi-lens/dist/clients/ndjson-logger.js +247 -20
- package/node_modules/pi-lens/dist/clients/observed-mutation-sources.js +101 -0
- package/node_modules/pi-lens/dist/clients/observed-mutation.js +1215 -0
- package/node_modules/pi-lens/dist/clients/opaque-mutation-scan.js +68 -22
- package/node_modules/pi-lens/dist/clients/opengrep-config.js +4 -0
- package/node_modules/pi-lens/dist/clients/package-manager.js +195 -26
- package/node_modules/pi-lens/dist/clients/partial-edit-apply.js +359 -80
- package/node_modules/pi-lens/dist/clients/path-attribution-telemetry.js +23 -7
- package/node_modules/pi-lens/dist/clients/path-keyed-map.js +21 -2
- package/node_modules/pi-lens/dist/clients/path-utils.js +428 -13
- package/node_modules/pi-lens/dist/clients/persist-debounce.js +8 -1
- package/node_modules/pi-lens/dist/clients/php-cs-fixer-config.js +114 -0
- package/node_modules/pi-lens/dist/clients/pipeline.js +77 -16
- package/node_modules/pi-lens/dist/clients/probe-home-state.js +228 -0
- package/node_modules/pi-lens/dist/clients/process-bridge.js +66 -0
- package/node_modules/pi-lens/dist/clients/process-snapshot.js +68 -0
- package/node_modules/pi-lens/dist/clients/project-diagnostics/fresh-fetch.js +4 -3
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/runner-findings.js +27 -3
- package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +51 -20
- package/node_modules/pi-lens/dist/clients/project-lens-config.js +393 -122
- package/node_modules/pi-lens/dist/clients/project-snapshot.js +52 -24
- package/node_modules/pi-lens/dist/clients/python-environment.js +217 -0
- package/node_modules/pi-lens/dist/clients/python-provenance.js +639 -0
- package/node_modules/pi-lens/dist/clients/quiet-window.js +6 -1
- package/node_modules/pi-lens/dist/clients/read-bridge.js +13 -21
- package/node_modules/pi-lens/dist/clients/read-expansion.js +9 -46
- package/node_modules/pi-lens/dist/clients/read-guard-logger.js +15 -4
- package/node_modules/pi-lens/dist/clients/read-guard-tool-lines.js +364 -212
- package/node_modules/pi-lens/dist/clients/read-guard.js +21 -0
- package/node_modules/pi-lens/dist/clients/resource-sampler.js +195 -96
- package/node_modules/pi-lens/dist/clients/review-graph/builder.js +152 -109
- package/node_modules/pi-lens/dist/clients/review-graph/service.js +55 -3
- package/node_modules/pi-lens/dist/clients/review-graph/shared-extraction-ir.js +7 -15
- package/node_modules/pi-lens/dist/clients/review-graph/workspace-modules.js +10 -74
- package/node_modules/pi-lens/dist/clients/review-graph-logger.js +9 -3
- package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +18 -2
- package/node_modules/pi-lens/dist/clients/runtime-context.js +49 -16
- package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +25 -6
- package/node_modules/pi-lens/dist/clients/runtime-session.js +139 -22
- package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +168 -35
- package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +797 -243
- package/node_modules/pi-lens/dist/clients/runtime-turn.js +1028 -53
- package/node_modules/pi-lens/dist/clients/rust-client.js +31 -0
- package/node_modules/pi-lens/dist/clients/safe-spawn.js +33 -10
- package/node_modules/pi-lens/dist/clients/sanitize.js +7 -1
- package/node_modules/pi-lens/dist/clients/scratch-tree-policy.js +1 -3
- package/node_modules/pi-lens/dist/clients/security-scan-client.js +3 -0
- package/node_modules/pi-lens/dist/clients/session-lifecycle.js +1 -1
- package/node_modules/pi-lens/dist/clients/session-start-observability.js +79 -0
- package/node_modules/pi-lens/dist/clients/sessionstart-logger.js +12 -3
- package/node_modules/pi-lens/dist/clients/sgconfig.js +6 -1
- package/node_modules/pi-lens/dist/clients/skills-resolver.js +105 -0
- package/node_modules/pi-lens/dist/clients/smells-rollup.js +2 -2
- package/node_modules/pi-lens/dist/clients/string-utils.js +13 -0
- package/node_modules/pi-lens/dist/clients/subagent-mode.js +17 -4
- package/node_modules/pi-lens/dist/clients/test-runner-client.js +176 -39
- package/node_modules/pi-lens/dist/clients/test-runner-delivery.js +239 -0
- package/node_modules/pi-lens/dist/clients/tool-definition.js +41 -1
- package/node_modules/pi-lens/dist/clients/tool-policy.js +91 -21
- package/node_modules/pi-lens/dist/clients/tree-sitter-cache.js +40 -40
- package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +86 -48
- package/node_modules/pi-lens/dist/clients/tree-sitter-logger.js +2 -2
- package/node_modules/pi-lens/dist/clients/tree-sitter-query-loader.js +81 -1
- package/node_modules/pi-lens/dist/clients/tree-sitter-shared.js +51 -46
- package/node_modules/pi-lens/dist/clients/tree-sitter-symbol-extractor.js +28 -0
- package/node_modules/pi-lens/dist/clients/typos-config.js +5 -0
- package/node_modules/pi-lens/dist/clients/user-notify.js +6 -2
- package/node_modules/pi-lens/dist/clients/widget-state.js +191 -26
- package/node_modules/pi-lens/dist/clients/word-index-logger.js +2 -2
- package/node_modules/pi-lens/dist/clients/word-index-store.js +20 -5
- package/node_modules/pi-lens/dist/clients/word-index.js +243 -31
- package/node_modules/pi-lens/dist/clients/workspace-topology.js +8 -1
- package/node_modules/pi-lens/dist/clients/zizmor-config.js +3 -0
- package/node_modules/pi-lens/dist/index.js +64335 -54300
- package/node_modules/pi-lens/dist/mcp/analyze-cli.js +3 -1
- package/node_modules/pi-lens/dist/mcp/server.js +127 -5
- package/node_modules/pi-lens/dist/scripts/lib/process-scan.mjs +583 -0
- package/node_modules/pi-lens/dist/scripts/lib/skills-predicate.mjs +129 -0
- package/node_modules/pi-lens/dist/tools/effective-config.js +89 -0
- package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +95 -24
- package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +67 -80
- package/node_modules/pi-lens/dist/tools/lsp-navigation.js +37 -16
- package/node_modules/pi-lens/dist/tools/shared.js +0 -1
- package/node_modules/pi-lens/docs/agent-guide.md +64 -1
- package/node_modules/pi-lens/docs/configuration.md +222 -0
- package/node_modules/pi-lens/docs/dependencies.md +3 -3
- package/node_modules/pi-lens/docs/features.md +44 -5
- package/node_modules/pi-lens/docs/language-coverage.md +2 -2
- package/node_modules/pi-lens/docs/pi-lens-fixer.md +25 -0
- package/node_modules/pi-lens/docs/pi-lens-investigator.md +25 -0
- package/node_modules/pi-lens/docs/pi-lens-reviewer.md +27 -0
- package/node_modules/pi-lens/docs/pi-lens-subagent.md +38 -0
- package/node_modules/pi-lens/docs/pi-lens-warden.md +55 -0
- package/node_modules/pi-lens/docs/public-api-stability.md +359 -0
- package/node_modules/pi-lens/docs/release-qa-baseline.md +182 -0
- package/node_modules/pi-lens/docs/subagent-compat.md +110 -30
- package/node_modules/pi-lens/docs/tree-sitter_rules_catalog.md +2 -2
- package/node_modules/pi-lens/package.json +15 -23
- package/node_modules/pi-lens/rules/tree-sitter-queries/python/python-cross-language-method.yml +3 -3
- package/node_modules/pi-lens/rules/tree-sitter-queries/python/python-hallucinated-import.yml +2 -2
- package/node_modules/pi-lens/rules/tree-sitter-queries/python/python-sql-injection.yml +12 -2
- package/node_modules/pi-lens/scripts/analyze-pi-lens-logs.mjs +192 -1
- package/node_modules/pi-lens/scripts/install-selftest.mjs +58 -2
- package/node_modules/pi-lens/scripts/lib/skills-predicate.mjs +129 -0
- package/node_modules/pi-lens/scripts/rpc-load-check.mjs +3 -1
- package/node_modules/pi-mcp-adapter/CHANGELOG.md +27 -0
- package/node_modules/pi-mcp-adapter/README.md +13 -13
- package/node_modules/pi-mcp-adapter/commands.ts +58 -21
- package/node_modules/pi-mcp-adapter/config.ts +18 -4
- package/node_modules/pi-mcp-adapter/direct-tools.ts +26 -6
- package/node_modules/pi-mcp-adapter/dist/config.d.ts +4 -0
- package/node_modules/pi-mcp-adapter/dist/config.js +13 -4
- package/node_modules/pi-mcp-adapter/dist/config.js.map +1 -1
- package/node_modules/pi-mcp-adapter/dist/types.d.ts +11 -3
- package/node_modules/pi-mcp-adapter/dist/types.js.map +1 -1
- package/node_modules/pi-mcp-adapter/error-signal.ts +15 -4
- package/node_modules/pi-mcp-adapter/errors.ts +141 -0
- package/node_modules/pi-mcp-adapter/host-html-template.ts +58 -5
- package/node_modules/pi-mcp-adapter/index.ts +2 -3
- package/node_modules/pi-mcp-adapter/init.ts +5 -0
- package/node_modules/pi-mcp-adapter/mcp-panel.ts +30 -9
- package/node_modules/pi-mcp-adapter/mcp-setup-panel.ts +66 -28
- package/node_modules/pi-mcp-adapter/mcp-status.ts +2 -0
- package/node_modules/pi-mcp-adapter/package.json +2 -1
- package/node_modules/pi-mcp-adapter/proxy-modes.ts +66 -13
- package/node_modules/pi-mcp-adapter/sandbox-proxy-template.ts +217 -0
- package/node_modules/pi-mcp-adapter/server-manager.ts +337 -6
- package/node_modules/pi-mcp-adapter/skills/mcp-scripting/SKILL.md +1 -0
- package/node_modules/pi-mcp-adapter/types.ts +18 -3
- package/node_modules/pi-mcp-adapter/ui-resource-handler.ts +18 -2
- package/node_modules/pi-mcp-adapter/ui-server.ts +179 -54
- package/node_modules/pi-mcp-adapter/ui-session.ts +28 -8
- package/node_modules/pi-web-access/CHANGELOG.md +28 -0
- package/node_modules/pi-web-access/README.md +62 -15
- package/node_modules/pi-web-access/curator-page.ts +3 -1
- package/node_modules/pi-web-access/curator-server.ts +5 -1
- package/node_modules/pi-web-access/gemini-search.ts +8 -4
- package/node_modules/pi-web-access/github-extract.ts +242 -1
- package/node_modules/pi-web-access/index.ts +118 -64
- package/node_modules/pi-web-access/mistral-search.ts +281 -0
- package/node_modules/pi-web-access/package.json +2 -2
- package/node_modules/pi-web-access/perplexity.ts +14 -1
- package/node_modules/pi-web-access/utils.ts +23 -6
- package/node_modules/pi-web-access/xai-search.ts +96 -33
- package/package.json +15 -11
|
@@ -221,6 +221,35 @@ function createState(files) {
|
|
|
221
221
|
progress: [],
|
|
222
222
|
},
|
|
223
223
|
},
|
|
224
|
+
// #2526: the config stack's positive-observability rows. `resolved`
|
|
225
|
+
// counts `config_resolved` phase records; `legacyWithoutRecords` counts
|
|
226
|
+
// the rows that carry a deprecated document but produced no
|
|
227
|
+
// migration/notice record — the deprecation machinery gone silent.
|
|
228
|
+
//
|
|
229
|
+
// Round 2, F2: the session->row relation is a JOIN on the session id both
|
|
230
|
+
// sides carry, not a subtraction of two counts.
|
|
231
|
+
//
|
|
232
|
+
// Round 3, S1: the session-side half of the join is no longer a
|
|
233
|
+
// PREDICTION. `pendingSessions` holds every session id that published a
|
|
234
|
+
// `config_resolution_pending` mark — written by `loadLSPConfig` itself,
|
|
235
|
+
// at the instant a resolution is actually attempted, never by a
|
|
236
|
+
// `runtime-session.ts` handler guessing from `no-lsp`/subagent/warm-attach
|
|
237
|
+
// flags ahead of time. A session that never reaches that call (quick or
|
|
238
|
+
// minimal mode's second-and-later session in a process, for the same
|
|
239
|
+
// root) never gets a mark, so it is silently excluded rather than
|
|
240
|
+
// counted against. `resolvedSessions` holds every session id a
|
|
241
|
+
// resolution actually reported, from EITHER sink (the latency row or the
|
|
242
|
+
// sessionstart line — one call writes both, so this is one fact
|
|
243
|
+
// surviving an independent rotation of either log, not a second source
|
|
244
|
+
// of truth).
|
|
245
|
+
config: {
|
|
246
|
+
resolved: 0,
|
|
247
|
+
pendingSessions: new Map(),
|
|
248
|
+
resolvedSessions: new Set(),
|
|
249
|
+
legacyDocuments: 0,
|
|
250
|
+
legacyWithoutRecords: 0,
|
|
251
|
+
examples: [],
|
|
252
|
+
},
|
|
224
253
|
diagnostics: {
|
|
225
254
|
bySeverity: counter(),
|
|
226
255
|
byTool: counter(),
|
|
@@ -351,7 +380,44 @@ async function analyzeLatency(files, state) {
|
|
|
351
380
|
} else if (entry.type === "phase") {
|
|
352
381
|
const phase = entry.phase ?? "unknown";
|
|
353
382
|
state.latency.phaseCounts.inc(phase);
|
|
354
|
-
if (
|
|
383
|
+
if (phase.endsWith("_timeout")) state.latency.phaseTimeouts.inc(phase);
|
|
384
|
+
if (phase === "config_resolved") {
|
|
385
|
+
// #2526. Counted here rather than derived from phaseCounts so the
|
|
386
|
+
// legacy/record cross-check reads the same row it counts.
|
|
387
|
+
state.config.resolved += 1;
|
|
388
|
+
const md = entry.metadata ?? {};
|
|
389
|
+
// #2526 R2 F2 / #2552 R4: the join key is (session, root), not
|
|
390
|
+
// session alone — see `configJoinKey`'s doc comment. `entry.filePath`
|
|
391
|
+
// is this row's root (the same `configResolutionKey(cwd)` value the
|
|
392
|
+
// pending mark's `root=` carries); a row from a build that predates
|
|
393
|
+
// the session id carries none, and simply joins to nothing.
|
|
394
|
+
if (
|
|
395
|
+
typeof md.sessionId === "string" &&
|
|
396
|
+
md.sessionId.length > 0 &&
|
|
397
|
+
typeof entry.filePath === "string" &&
|
|
398
|
+
entry.filePath.length > 0
|
|
399
|
+
) {
|
|
400
|
+
state.config.resolvedSessions.add(
|
|
401
|
+
configJoinKey(md.sessionId, entry.filePath),
|
|
402
|
+
);
|
|
403
|
+
}
|
|
404
|
+
const documents = Array.isArray(md.documents) ? md.documents : [];
|
|
405
|
+
const legacy = documents.filter((doc) => doc?.legacy === true);
|
|
406
|
+
state.config.legacyDocuments += legacy.length;
|
|
407
|
+
// A deprecated document that produced NO record means the
|
|
408
|
+
// migration notices went silent — the user is on a removal
|
|
409
|
+
// schedule and is never told. Zero records with zero legacy
|
|
410
|
+
// documents is the correct canonical-only answer, not a smell.
|
|
411
|
+
if (legacy.length > 0 && Number(md.recordCount ?? 0) === 0) {
|
|
412
|
+
state.config.legacyWithoutRecords += 1;
|
|
413
|
+
pushTop(
|
|
414
|
+
state.config.examples,
|
|
415
|
+
summarizeConfigResolved(entry, "legacy document with 0 records"),
|
|
416
|
+
limit * 3,
|
|
417
|
+
byDuration,
|
|
418
|
+
);
|
|
419
|
+
}
|
|
420
|
+
}
|
|
355
421
|
if (
|
|
356
422
|
phase === "total" &&
|
|
357
423
|
(entry.durationMs ?? 0) >= thresholds.totalSlowMs
|
|
@@ -636,6 +702,40 @@ async function analyzeSessionStart(files, state) {
|
|
|
636
702
|
trackProject(state, cwd);
|
|
637
703
|
}
|
|
638
704
|
|
|
705
|
+
// #2526 R3 S1: this session's config-resolution PENDING mark, published
|
|
706
|
+
// by `loadLSPConfig` itself at the instant a resolution is actually
|
|
707
|
+
// attempted — never a start-line prediction from `no-lsp`/subagent/
|
|
708
|
+
// warm-attach flags. A session that never calls `loadLSPConfig` (quick
|
|
709
|
+
// or minimal mode's second-and-later session in a process, for the
|
|
710
|
+
// same root) never writes this line, and is correctly absent from the
|
|
711
|
+
// join rather than counted against.
|
|
712
|
+
//
|
|
713
|
+
// #2552 R4: `root=` is REQUIRED in the match — a warm MCP process keeps
|
|
714
|
+
// one session id for its whole life but marks once per served root
|
|
715
|
+
// (`configJoinKey`'s doc comment), so a line missing it cannot be
|
|
716
|
+
// attributed to a specific root and is left out of the join rather than
|
|
717
|
+
// guessed into a wrong one.
|
|
718
|
+
const pending =
|
|
719
|
+
/session_start config_resolution_pending session=(\S+) root=(.*)$/.exec(
|
|
720
|
+
message,
|
|
721
|
+
);
|
|
722
|
+
if (pending) {
|
|
723
|
+
const [, sessionId, root] = pending;
|
|
724
|
+
state.config.pendingSessions.set(configJoinKey(sessionId, root), {
|
|
725
|
+
ts: iso(ts),
|
|
726
|
+
sessionId,
|
|
727
|
+
root,
|
|
728
|
+
});
|
|
729
|
+
}
|
|
730
|
+
// The loader's own line is the second half of the join, so a rotated
|
|
731
|
+
// latency.log cannot manufacture a deficit on its own.
|
|
732
|
+
const resolvedSession =
|
|
733
|
+
/config resolved .*\bsession=(\S+) root=(.*)$/.exec(message);
|
|
734
|
+
if (resolvedSession) {
|
|
735
|
+
const [, sessionId, root] = resolvedSession;
|
|
736
|
+
state.config.resolvedSessions.add(configJoinKey(sessionId, root));
|
|
737
|
+
}
|
|
738
|
+
|
|
639
739
|
const total = /session_start total:\s*(\d+)ms/.exec(message);
|
|
640
740
|
if (total && Number(total[1]) >= thresholds.startupSlowMs) {
|
|
641
741
|
state.smellTotals.inc("slow-session-start");
|
|
@@ -899,6 +999,23 @@ function iso(date) {
|
|
|
899
999
|
return date?.toISOString?.() ?? "unknown";
|
|
900
1000
|
}
|
|
901
1001
|
|
|
1002
|
+
/**
|
|
1003
|
+
* The config-resolution join key (#2552 review round 4). A warm MCP process
|
|
1004
|
+
* keeps ONE session id for its entire life but calls `loadLSPConfig` once per
|
|
1005
|
+
* SERVED ROOT (#2526 review round 2, F3's premise, reintroduced one layer up
|
|
1006
|
+
* here) — joining on session id alone let one root's row silently clear every
|
|
1007
|
+
* OTHER root's deficit under the same session id. `root` is whatever string
|
|
1008
|
+
* the producer already wrote (the pending mark's `root=`, or the row's own
|
|
1009
|
+
* `filePath` — both come from the SAME `configResolutionKey(cwd)` call in
|
|
1010
|
+
* `clients/lsp/config.ts`, which folds separators, canonicalizes, then folds
|
|
1011
|
+
* again — `normalizeFilePath(path.resolve(normalizeFilePath(cwd)))`, in that
|
|
1012
|
+
* order (#2518 review F6; resolving first breaks POSIX backslash names), so they compare equal without this script re-deriving any
|
|
1013
|
+
* path normalization of its own).
|
|
1014
|
+
*/
|
|
1015
|
+
function configJoinKey(sessionId, root) {
|
|
1016
|
+
return `${sessionId} ${root}`;
|
|
1017
|
+
}
|
|
1018
|
+
|
|
902
1019
|
function counter() {
|
|
903
1020
|
const map = new Map();
|
|
904
1021
|
return {
|
|
@@ -985,6 +1102,33 @@ function summarizeLatency(entry) {
|
|
|
985
1102
|
};
|
|
986
1103
|
}
|
|
987
1104
|
|
|
1105
|
+
/**
|
|
1106
|
+
* A `config_resolved` row (#2526), summarised for a smell example.
|
|
1107
|
+
*
|
|
1108
|
+
* Deliberately NOT `summarizeLatency`: that helper's metadata whitelist would
|
|
1109
|
+
* drop every field this row carries, so the example would print a phase name
|
|
1110
|
+
* and nothing a reader could act on.
|
|
1111
|
+
*/
|
|
1112
|
+
function summarizeConfigResolved(entry, note) {
|
|
1113
|
+
const md = entry.metadata ?? {};
|
|
1114
|
+
const documents = Array.isArray(md.documents) ? md.documents : [];
|
|
1115
|
+
return {
|
|
1116
|
+
ts: entry.ts,
|
|
1117
|
+
durationMs: entry.durationMs,
|
|
1118
|
+
phase: entry.phase,
|
|
1119
|
+
project: projectOf(entry.filePath),
|
|
1120
|
+
note,
|
|
1121
|
+
documents: documents
|
|
1122
|
+
.map(
|
|
1123
|
+
(doc) =>
|
|
1124
|
+
`${doc?.tier ?? "?"}:${doc?.file ?? "?"}${doc?.legacy ? " (legacy)" : ""}`,
|
|
1125
|
+
)
|
|
1126
|
+
.slice(0, 8),
|
|
1127
|
+
recordCount: md.recordCount,
|
|
1128
|
+
deniedServers: md.deniedServers,
|
|
1129
|
+
};
|
|
1130
|
+
}
|
|
1131
|
+
|
|
988
1132
|
function summarizeWorkspaceSweep(entry) {
|
|
989
1133
|
const md = entry.metadata ?? {};
|
|
990
1134
|
const bits = [];
|
|
@@ -1193,6 +1337,43 @@ function buildReport(state) {
|
|
|
1193
1337
|
`session_start background tasks >= ${thresholds.backgroundSlowMs}ms`,
|
|
1194
1338
|
state.session.slowTasks.slice(0, limit),
|
|
1195
1339
|
);
|
|
1340
|
+
// #2526: config resolution has to prove it HAPPENED. Two shapes, one smell:
|
|
1341
|
+
//
|
|
1342
|
+
// (a) a session that has a `config_resolution_pending` mark and produced no
|
|
1343
|
+
// `config_resolved` row. Round 3, S1: the pending mark is written by
|
|
1344
|
+
// `loadLSPConfig` itself, at the instant a resolution is actually
|
|
1345
|
+
// attempted — never predicted from a handler's own flags ahead of time.
|
|
1346
|
+
// Round 2, F2 established the JOIN itself: on the session id both sides
|
|
1347
|
+
// carry, never a subtraction of two counts (subtracting counted quick
|
|
1348
|
+
// sessions' rows against full sessions' start lines — different
|
|
1349
|
+
// populations — which both masked total silence and charged
|
|
1350
|
+
// `--no-lsp`/subagent sessions with a permanent deficit they could never
|
|
1351
|
+
// clear).
|
|
1352
|
+
// Round 4, #2552 review: the join is on (session, root), not session
|
|
1353
|
+
// alone — a warm MCP process keeps one session id for its whole life but
|
|
1354
|
+
// marks once per SERVED ROOT (`configJoinKey`'s doc comment), so one
|
|
1355
|
+
// root's row must not clear another root's deficit under the same id.
|
|
1356
|
+
// (b) a legacy document present with zero records — the deprecation
|
|
1357
|
+
// machinery went silent while the user is on a removal schedule.
|
|
1358
|
+
const pendingConfigResolution = [...state.config.pendingSessions.entries()];
|
|
1359
|
+
const unresolvedSessions = pendingConfigResolution.filter(
|
|
1360
|
+
([key]) => !state.config.resolvedSessions.has(key),
|
|
1361
|
+
);
|
|
1362
|
+
for (const [, value] of unresolvedSessions.slice(0, limit * 3)) {
|
|
1363
|
+
state.config.examples.push({
|
|
1364
|
+
ts: value.ts,
|
|
1365
|
+
session: value.sessionId,
|
|
1366
|
+
root: value.root,
|
|
1367
|
+
note: "session had a config_resolution_pending mark and produced no config_resolved row",
|
|
1368
|
+
});
|
|
1369
|
+
}
|
|
1370
|
+
addSmell(
|
|
1371
|
+
smells,
|
|
1372
|
+
"config-resolution",
|
|
1373
|
+
unresolvedSessions.length + state.config.legacyWithoutRecords,
|
|
1374
|
+
`Sessions with a config_resolution_pending mark but no config_resolved row (${unresolvedSessions.length} of ${pendingConfigResolution.length}) or a legacy config document that produced no migration record (${state.config.legacyWithoutRecords})`,
|
|
1375
|
+
state.config.examples.slice(0, limit),
|
|
1376
|
+
);
|
|
1196
1377
|
addSmell(
|
|
1197
1378
|
smells,
|
|
1198
1379
|
"cascade-fallbacks",
|
|
@@ -1352,6 +1533,16 @@ function buildReport(state) {
|
|
|
1352
1533
|
rotations: state.session.rotations.toJSON(),
|
|
1353
1534
|
errors: state.session.errors.slice(0, limit),
|
|
1354
1535
|
},
|
|
1536
|
+
// #2526: the positive-observability counters behind the
|
|
1537
|
+
// `config-resolution` smell, so a reader can see WHY it fired (or that
|
|
1538
|
+
// it correctly did not) without re-deriving the deficit.
|
|
1539
|
+
config: {
|
|
1540
|
+
resolved: state.config.resolved,
|
|
1541
|
+
sessionsPendingResolution: pendingConfigResolution.length,
|
|
1542
|
+
sessionsWithoutResolution: unresolvedSessions.length,
|
|
1543
|
+
legacyDocuments: state.config.legacyDocuments,
|
|
1544
|
+
legacyWithoutRecords: state.config.legacyWithoutRecords,
|
|
1545
|
+
},
|
|
1355
1546
|
actionable: {
|
|
1356
1547
|
events: state.actionable.events.toJSON(),
|
|
1357
1548
|
reports: state.actionable.reports,
|
|
@@ -17,7 +17,9 @@
|
|
|
17
17
|
* Force-imports the modules whose TOP-LEVEL bare imports are the documented
|
|
18
18
|
* failure points, plus the bare specifiers directly, and checks the two
|
|
19
19
|
* build-script-provided assets (ast-grep CLI binary + tree-sitter grammars)
|
|
20
|
-
* that pnpm/bun skip by default. It
|
|
20
|
+
* that pnpm/bun skip by default. It also resolves the `pi.skills` manifest
|
|
21
|
+
* entries the way pi does, from the installed package root (#2587). It runs no
|
|
22
|
+
* model and needs no credentials.
|
|
21
23
|
*
|
|
22
24
|
* WHAT IT NO LONGER COVERS (#1926)
|
|
23
25
|
* pi supplies `typebox` and `@earendil-works/pi-tui` from its own runtime, so
|
|
@@ -47,6 +49,7 @@ import { createRequire } from "node:module";
|
|
|
47
49
|
import * as path from "node:path";
|
|
48
50
|
import { fileURLToPath } from "node:url";
|
|
49
51
|
import { HOST_PROVIDED_PACKAGES } from "./lib/host-provided-deps.mjs";
|
|
52
|
+
import { collectSkillEntryPaths } from "./lib/skills-predicate.mjs";
|
|
50
53
|
|
|
51
54
|
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
52
55
|
const pkgRoot = path.resolve(here, "..");
|
|
@@ -242,6 +245,56 @@ try {
|
|
|
242
245
|
}
|
|
243
246
|
record("tree-sitter grammars", "asset", hasCoreGrammar, grammarDetail);
|
|
244
247
|
|
|
248
|
+
// --- 4. pi.skills manifest resolution, AS INSTALLED (#2587) ----------------
|
|
249
|
+
// Guards the recurrence of #2587: a `pi.skills` entry that resolves outside the
|
|
250
|
+
// installed package, so pi registers none of the shipped skills. This probe runs
|
|
251
|
+
// from the INSTALLED package (`require.resolve("pi-lens/scripts/…")`), so it sees
|
|
252
|
+
// the real layout — hoisted node_modules, pnpm's symlink store, bun, yarn — which
|
|
253
|
+
// is exactly where `../../skills` escaped and where a static check on the source
|
|
254
|
+
// tree cannot look. Replicates pi's own resolver, `PackageManager#collectFiles\
|
|
255
|
+
// FromManifestEntries` in `@earendil-works/pi-coding-agent`
|
|
256
|
+
// `dist/core/package-manager.js`: a non-glob entry is `resolve(packageRoot, entry)`
|
|
257
|
+
// (verified identical in 0.78.1 / 0.84.1 / 0.85.1).
|
|
258
|
+
//
|
|
259
|
+
// #2626 review round 2 (F2): the "does this dir have a skill" walk used to be
|
|
260
|
+
// a hand-rolled `countSkillFiles` here AND a second, differently-wrong one in
|
|
261
|
+
// `clients/skills-resolver.ts`. Both now derive from the ONE structural
|
|
262
|
+
// predicate in `./lib/skills-predicate.mjs`, which replicates pi's actual
|
|
263
|
+
// `loadSkillsFromDirInternal` walk (see that module's header for the exact
|
|
264
|
+
// discovery rules and the two documented scope gaps).
|
|
265
|
+
{
|
|
266
|
+
const pkgJson = JSON.parse(
|
|
267
|
+
fs.readFileSync(path.join(pkgRoot, "package.json"), "utf8"),
|
|
268
|
+
);
|
|
269
|
+
const entries = pkgJson.pi?.skills ?? [];
|
|
270
|
+
if (entries.length === 0) {
|
|
271
|
+
record("pi.skills declared", "manifest", false, "pi.skills is empty");
|
|
272
|
+
}
|
|
273
|
+
for (const entry of entries) {
|
|
274
|
+
const label = `pi.skills "${entry}"`;
|
|
275
|
+
// pi globs entries containing * or ? through a different branch; this
|
|
276
|
+
// probe only replicates the non-glob one.
|
|
277
|
+
if (/[*?]/.test(entry)) {
|
|
278
|
+
record(label, "manifest", true, "glob entry — not probed");
|
|
279
|
+
continue;
|
|
280
|
+
}
|
|
281
|
+
const resolved = path.resolve(pkgRoot, entry);
|
|
282
|
+
if (resolved !== pkgRoot && !resolved.startsWith(pkgRoot + path.sep)) {
|
|
283
|
+
record(label, "manifest", false, `escapes the package: ${resolved}`);
|
|
284
|
+
continue;
|
|
285
|
+
}
|
|
286
|
+
const found = collectSkillEntryPaths(resolved).length;
|
|
287
|
+
record(
|
|
288
|
+
label,
|
|
289
|
+
"manifest",
|
|
290
|
+
found > 0,
|
|
291
|
+
found > 0
|
|
292
|
+
? `${found} SKILL.md under ${resolved}`
|
|
293
|
+
: `no SKILL.md under ${resolved}`,
|
|
294
|
+
);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
245
298
|
// --- Report ----------------------------------------------------------------
|
|
246
299
|
const pad = Math.max(...results.map((r) => r.name.length));
|
|
247
300
|
let hardFail = 0;
|
|
@@ -249,7 +302,10 @@ let softFail = 0;
|
|
|
249
302
|
for (const r of results) {
|
|
250
303
|
const soft = (r.kind === "asset" || r.kind === "tool") && allowSoft;
|
|
251
304
|
const status = r.ok ? "PASS" : soft ? "WARN" : "FAIL";
|
|
252
|
-
if (!r.ok)
|
|
305
|
+
if (!r.ok) {
|
|
306
|
+
if (soft) softFail++;
|
|
307
|
+
else hardFail++;
|
|
308
|
+
}
|
|
253
309
|
console.log(
|
|
254
310
|
` [${status}] ${r.name.padEnd(pad)} ${r.detail ? "— " + r.detail : ""}`,
|
|
255
311
|
);
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
// The ONE structural replica of pi's own skill-loading walk (#2626 review
|
|
2
|
+
// round 2, F1/F2).
|
|
3
|
+
//
|
|
4
|
+
// Two independent detectors used to answer "does this directory tree hold a
|
|
5
|
+
// skill pi would load" with two DIFFERENT, hand-rolled heuristics that both
|
|
6
|
+
// diverged from pi's real resolver:
|
|
7
|
+
// - `clients/skills-resolver.ts` (a `SKILL.md` one level down only, no
|
|
8
|
+
// recursion, no root `.md` acceptance, no symlink-follow, no dot/
|
|
9
|
+
// node_modules skip)
|
|
10
|
+
// - `scripts/install-selftest.mjs`'s `countSkillFiles` (recursed
|
|
11
|
+
// UNBOUNDED — would double-count a `SKILL.md` sitting inside another
|
|
12
|
+
// skill's own resource subdirectory — with no dot/node_modules skip, no
|
|
13
|
+
// root `.md` acceptance, no symlink handling)
|
|
14
|
+
// Neither matched `loadSkillsFromDirInternal` in
|
|
15
|
+
// `@earendil-works/pi-coding-agent` `dist/core/skills.js` (mirrored by
|
|
16
|
+
// `collectSkillEntries` in `dist/core/package-manager.js`, byte-identical
|
|
17
|
+
// walk, confirmed against the 0.85.1 tarball). This module is the fold: BOTH
|
|
18
|
+
// consumers now derive from `collectSkillEntryPaths` below.
|
|
19
|
+
//
|
|
20
|
+
// Discovery rules, replicated from `loadSkillsFromDirInternal` (verified
|
|
21
|
+
// against the extracted 0.85.1 `skills.js`):
|
|
22
|
+
// 1. If `dir` directly contains a (non-symlink-broken) `SKILL.md`, `dir` IS
|
|
23
|
+
// one skill root — return immediately, do NOT look at `dir`'s other
|
|
24
|
+
// entries or recurse into its subdirectories (a `SKILL.md` inside a
|
|
25
|
+
// skill's own reference/ subfolder is the skill's OWN resource, not a
|
|
26
|
+
// second skill).
|
|
27
|
+
// 2. Otherwise, skip dot-prefixed entries and `node_modules`; recurse into
|
|
28
|
+
// every remaining subdirectory (same two rules, one level down); at the
|
|
29
|
+
// OUTERMOST call only (`isRoot`), a loose `*.md` file directly in `dir`
|
|
30
|
+
// also counts (pi's `includeRootFiles`, true only for the top call).
|
|
31
|
+
// 3. A symlink is followed via `statSync` (broken symlink = skip) for BOTH
|
|
32
|
+
// the `SKILL.md` check and the directory/file classification in step 2.
|
|
33
|
+
//
|
|
34
|
+
// Deliberately NOT replicated (out of #2626's scope — packaging/path
|
|
35
|
+
// resolution, not skill-content validation):
|
|
36
|
+
// - `.gitignore`/`.ignore`/`.fdignore` matching inside the skills tree.
|
|
37
|
+
// - frontmatter parsing: pi additionally requires a non-empty `description`
|
|
38
|
+
// field before a discovered file becomes a loaded skill. A `SKILL.md`
|
|
39
|
+
// file that exists but fails THAT validation is a content-authoring
|
|
40
|
+
// defect a maintainer would see in normal use, not a silent zero.
|
|
41
|
+
// Both gaps mean this predicate can be a bit more OPTIMISTIC than pi's true
|
|
42
|
+
// count in a pathological case (an ignored or description-less file still
|
|
43
|
+
// counts as "found" here); it is never more PESSIMISTIC — every real skill
|
|
44
|
+
// pi loads is found by this walk too — which is the direction #2626 cares
|
|
45
|
+
// about (never claim "no skills" when pi would load one).
|
|
46
|
+
|
|
47
|
+
import * as fs from "node:fs";
|
|
48
|
+
import * as path from "node:path";
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Symlink-aware entry classification, mirroring `loadSkillsFromDirInternal`'s
|
|
52
|
+
* own `entry.isSymbolicLink() ? statSync(fullPath) : entry`.
|
|
53
|
+
* @param {string} fullPath
|
|
54
|
+
* @param {import("node:fs").Dirent} entry
|
|
55
|
+
* @returns {"file" | "dir" | "other"}
|
|
56
|
+
*/
|
|
57
|
+
export function resolvedEntryKind(fullPath, entry) {
|
|
58
|
+
if (entry.isSymbolicLink()) {
|
|
59
|
+
try {
|
|
60
|
+
const stats = fs.statSync(fullPath);
|
|
61
|
+
if (stats.isDirectory()) return "dir";
|
|
62
|
+
if (stats.isFile()) return "file";
|
|
63
|
+
return "other";
|
|
64
|
+
} catch {
|
|
65
|
+
return "other"; // broken symlink
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
if (entry.isDirectory()) return "dir";
|
|
69
|
+
if (entry.isFile()) return "file";
|
|
70
|
+
return "other";
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* The structural walk over an ALREADY-READ directory listing — split out
|
|
75
|
+
* from `collectSkillEntryPaths` so a caller that already has `entries` (a
|
|
76
|
+
* top-level ENOENT/EACCES distinction, say) is not forced into a second
|
|
77
|
+
* `readdirSync`.
|
|
78
|
+
* @param {string} dir
|
|
79
|
+
* @param {import("node:fs").Dirent[]} entries
|
|
80
|
+
* @param {boolean} isRoot
|
|
81
|
+
* @returns {string[]} absolute paths of every `SKILL.md` (or, at the root,
|
|
82
|
+
* loose `.md`) file pi's own resolver would treat as a skill entry point.
|
|
83
|
+
*/
|
|
84
|
+
export function scanEntriesForSkills(dir, entries, isRoot) {
|
|
85
|
+
for (const entry of entries) {
|
|
86
|
+
if (
|
|
87
|
+
entry.name === "SKILL.md" &&
|
|
88
|
+
resolvedEntryKind(path.join(dir, entry.name), entry) === "file"
|
|
89
|
+
) {
|
|
90
|
+
return [path.join(dir, entry.name)];
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
const found = [];
|
|
94
|
+
for (const entry of entries) {
|
|
95
|
+
if (entry.name.startsWith(".") || entry.name === "node_modules") {
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
const fullPath = path.join(dir, entry.name);
|
|
99
|
+
const kind = resolvedEntryKind(fullPath, entry);
|
|
100
|
+
if (kind === "dir") {
|
|
101
|
+
found.push(...collectSkillEntryPaths(fullPath, false));
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
if (isRoot && kind === "file" && entry.name.endsWith(".md")) {
|
|
105
|
+
found.push(fullPath);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return found;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Every skill entry point under `dir`, recursively, per pi's discovery
|
|
113
|
+
* rules. Fail-closed: a `readdirSync` error at `dir` (absent, unreadable) or
|
|
114
|
+
* any recursed-into subdirectory returns `[]` for that branch rather than
|
|
115
|
+
* throwing — matching `loadSkillsFromDirInternal`'s own bare `try { … }
|
|
116
|
+
* catch {}` per directory.
|
|
117
|
+
* @param {string} dir
|
|
118
|
+
* @param {boolean} [isRoot]
|
|
119
|
+
* @returns {string[]}
|
|
120
|
+
*/
|
|
121
|
+
export function collectSkillEntryPaths(dir, isRoot = true) {
|
|
122
|
+
let entries;
|
|
123
|
+
try {
|
|
124
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
125
|
+
} catch {
|
|
126
|
+
return [];
|
|
127
|
+
}
|
|
128
|
+
return scanEntriesForSkills(dir, entries, isRoot);
|
|
129
|
+
}
|
|
@@ -61,7 +61,9 @@ function handle(line) {
|
|
|
61
61
|
if (m.type === "response" && m.command === "get_commands") {
|
|
62
62
|
const cmds = (m.data && m.data.commands) || [];
|
|
63
63
|
const lens = cmds.filter(
|
|
64
|
-
(c) =>
|
|
64
|
+
(c) =>
|
|
65
|
+
String(c.name || "").startsWith("lens-") ||
|
|
66
|
+
String(c.path || "").includes("pi-lens"),
|
|
65
67
|
);
|
|
66
68
|
console.log(
|
|
67
69
|
`total commands: ${cmds.length}; pi-lens commands: ${lens.map((c) => c.name).join(", ") || "(none)"}`,
|
|
@@ -7,6 +7,33 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [2.32.1] - 2026-09-01
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
- The published package now includes the updated public helper build artifacts for the `2.32.0` config and MCP Apps changes.
|
|
14
|
+
|
|
15
|
+
## [2.32.0] - 2026-09-01
|
|
16
|
+
|
|
17
|
+
### Highlights
|
|
18
|
+
- You can now enable and disable MCP servers directly from the `/mcp` panel.
|
|
19
|
+
- `/mcp setup` is clearer about where new shared servers will be saved.
|
|
20
|
+
- MCP App views that use browser storage now render reliably without exposing host session access.
|
|
21
|
+
- Long-running sessions handle MCP 2026 input flows, catalog updates, and UI resource refreshes more reliably.
|
|
22
|
+
- OAuth reuse and per-server status messages are less confusing.
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
- The `/mcp` panel now supports enabling and disabling servers in place with `ctrl+d` on a server row. Saving persists the `disabled` flag to the project Pi layer and reloads the session, matching `/mcp disable` and `/mcp enable`. Thanks to [@ericykim](https://github.com/ericykim) for PR #479.
|
|
26
|
+
|
|
27
|
+
### Changed
|
|
28
|
+
- `/mcp setup` now lets you choose project `.mcp.json` or global `~/.config/mcp/mcp.json` as the write target for new shared MCP servers, while keeping Pi-owned files and compatibility inputs in the advanced flow. The bundled `mcp-scripting` skill is manual-only by default. Thanks to [@w-winter](https://github.com/w-winter) for #477.
|
|
29
|
+
|
|
30
|
+
### Fixed
|
|
31
|
+
- MCP 2026 multi-round input flows now work more reliably across proxy, direct, resource, and UI-resource calls, with clearer no-UI errors and cancellation cleanup.
|
|
32
|
+
- MCP 2026-07-28 catalog listens now recover from dropped listens, refresh quietly when catalogs change, and notify open UIs when resources update. (#468)
|
|
33
|
+
- MCP App views now load through a separate loopback sandbox proxy origin so storage APIs work without exposing host session capabilities. Thanks to [@drewbitt](https://github.com/drewbitt) for #480.
|
|
34
|
+
- Implicit OAuth now reuses URL-bound stored credentials while preserving anonymous fallback. Thanks to [@wilt00](https://github.com/wilt00) for #471.
|
|
35
|
+
- Per-server proxy lists now distinguish cached lazy tools from servers that need authentication while preserving active failure backoff. Thanks to [@inattendu](https://github.com/inattendu) for PR #474.
|
|
36
|
+
|
|
10
37
|
## [2.31.0] - 2026-08-28
|
|
11
38
|
|
|
12
39
|
### Highlights
|
|
@@ -32,9 +32,9 @@ The adapter reads standard MCP files automatically. No extra setup needed if you
|
|
|
32
32
|
|
|
33
33
|
| You already have... | What happens |
|
|
34
34
|
|---------------------|--------------|
|
|
35
|
-
| `.mcp.json` or `~/.config/mcp/mcp.json` | Pi uses it immediately. The first time you open `/mcp`, you'll see a short heads-up explaining which file Pi detected and that Pi only writes adapter-specific overrides to its own files. |
|
|
35
|
+
| `.mcp.json` or `~/.config/mcp/mcp.json` | Pi uses it immediately. Use `.mcp.json` for project/team sharing and `~/.config/mcp/mcp.json` for all projects. The first time you open `/mcp`, you'll see a short heads-up explaining which file Pi detected and that Pi only writes adapter-specific overrides to its own files. |
|
|
36
36
|
| Host-specific configs (Cursor, Claude Code, Codex, etc.) but no standard MCP files | Run `/mcp setup` to adopt those host configs into Pi. The setup flow shows exactly what it found, lets you pick which ones to import, and previews the exact file changes before writing. |
|
|
37
|
-
| Nothing configured yet | Run `/mcp setup
|
|
37
|
+
| Nothing configured yet | Run `/mcp setup`, choose project `.mcp.json` or global `~/.config/mcp/mcp.json`, then scaffold a minimal config, add a curated known server, quick-add RepoPrompt, or inspect what the adapter discovered on your machine. |
|
|
38
38
|
|
|
39
39
|
If you prefer the terminal, you can also run `pi-mcp-adapter init` after install to scan for host-specific configs and add missing compatibility imports to the Pi agent dir (`~/.pi/agent/mcp.json` by default, or `$PI_CODING_AGENT_DIR/mcp.json` when set).
|
|
40
40
|
|
|
@@ -53,16 +53,16 @@ Preferred project config: `.mcp.json`
|
|
|
53
53
|
}
|
|
54
54
|
```
|
|
55
55
|
|
|
56
|
-
Preferred user-global shared config: `~/.config/mcp/mcp.json
|
|
56
|
+
Preferred user-global shared config: `~/.config/mcp/mcp.json` (for all projects). Pi also reads the tool-agnostic global paths `~/.agents/mcp.json` and `~/.agents/mcp/mcp.json` as compatibility inputs.
|
|
57
57
|
|
|
58
|
-
Pi
|
|
58
|
+
Pi-owned files are not additional normal setup choices. They hold Pi-specific settings, compatibility imports, and adapter-only overrides:
|
|
59
59
|
|
|
60
60
|
- `<Pi agent dir>/mcp.json` — Pi global override (`~/.pi/agent/mcp.json` by default)
|
|
61
61
|
- `.pi/mcp.json` — Pi project override
|
|
62
62
|
|
|
63
|
-
Host-specific configs are detected and shown by `/mcp setup` and `pi-mcp-adapter init`, but they are not loaded automatically. The normal `/mcp` panel does not scan host-specific files when `settings.hostConfigDiscovery` is `"off"`. To explicitly opt in to host-config fallback discovery, set `settings.hostConfigDiscovery` to `"on"` or run `pi-mcp-adapter init --discover-host-configs`. The default is `"off"`; `"prompt"` is available for integrations that want detection without activation. Host configs are lower precedence than every shared and Pi-owned source, and `/mcp setup` continues to offer explicit import adoption. Discovery reports source paths, provenance, and same-name conflicts; it never writes to external host files or silently launches commands from them.
|
|
63
|
+
Host-specific configs are detected and shown by `/mcp setup` and `pi-mcp-adapter init`, but they are compatibility inputs rather than normal setup paths and are not loaded automatically. The normal `/mcp` panel does not scan host-specific files when `settings.hostConfigDiscovery` is `"off"`. To explicitly opt in to host-config fallback discovery, set `settings.hostConfigDiscovery` to `"on"` or run `pi-mcp-adapter init --discover-host-configs`. The default is `"off"`; `"prompt"` is available for integrations that want detection without activation. Host configs are lower precedence than every shared and Pi-owned source, and `/mcp setup` continues to offer explicit import adoption. Discovery reports source paths, provenance, and same-name conflicts; it never writes to external host files or silently launches commands from them.
|
|
64
64
|
|
|
65
|
-
Precedence is:
|
|
65
|
+
Precedence is (later entries win):
|
|
66
66
|
|
|
67
67
|
1. `~/.config/mcp/mcp.json`
|
|
68
68
|
2. `~/.agents/mcp.json`
|
|
@@ -302,7 +302,7 @@ Use `"auto"` to probe for MCP 2026-07-28 and conservatively fall back to the cla
|
|
|
302
302
|
|
|
303
303
|
Use `"2026-07-28"` to pin that revision. Pinning has no legacy or SSE fallback and fails if the server does not offer the requested version.
|
|
304
304
|
|
|
305
|
-
The stable SDK handles era-specific request envelopes, result decoding, list-changed subscriptions, cancellation, and multi-round-trip sampling/elicitation. The adapter keeps strict OAuth issuer validation in every mode. Adapter-level roots support, standard MCP logging presentation, and configuration/UI for protocol cache hints are not yet implemented.
|
|
305
|
+
The stable SDK handles era-specific request envelopes, result decoding, list-changed subscriptions, cancellation, and multi-round-trip sampling/elicitation. The SDK's embedded-input progress callback does not expose the originating tool or resource identity, so the adapter cannot maintain a durable per-tool waiting status row; interactive sessions keep the existing input dialog visible, and proxy calls show request progress when UI is available. The adapter keeps strict OAuth issuer validation in every mode. Adapter-level roots support, standard MCP logging presentation, and configuration/UI for protocol cache hints are not yet implemented.
|
|
306
306
|
|
|
307
307
|
For pre-registered browser OAuth clients, set `oauth.redirectUri` to the exact callback registered with the provider, for example `"http://localhost:3118/callback"`. Dynamic clients normally omit it and use a lazy OS-assigned localhost callback port. A configured `https://` callback runs in manual mode because the adapter cannot receive a callback on another host. After authorization, copy the full callback URL from the browser address bar and paste it into `/mcp-auth` or `mcp({ action: "auth-complete", ... })`.
|
|
308
308
|
|
|
@@ -412,7 +412,7 @@ When any enabled server uses `eager` or `keep-alive`, initialization also starts
|
|
|
412
412
|
| `strictDirectToolArguments` | Validate direct-tool inputs against their advertised schemas and recover one JSON string layer for object and array properties (default: false). |
|
|
413
413
|
| `directToolResultDetails` | Direct-tool result details: `"lean"` (default) or `"bounded"` to retain the guarded raw MCP result. |
|
|
414
414
|
| `warnOnLargeDirectTools` | Show the advisory when 75 or more direct tools resolve (default: `true`). Set to `false` to suppress only this advisory. |
|
|
415
|
-
| `freezeDirectTools` | Keep direct-tool registration stable after the initial sync so
|
|
415
|
+
| `freezeDirectTools` | Keep direct-tool registration stable after the initial sync so metadata updates and explicit reconnects do not rebuild the system prompt. Proxy/search/cache metadata still refreshes. Default: false. |
|
|
416
416
|
| `scriptMode` | Register the MCP-only `mcpScript` plain-JavaScript tool (default: true). Set to `false` to hide it. |
|
|
417
417
|
| `disableProxyTool` | Hide the `mcp` proxy tool once configured direct tools are fully available from cache. |
|
|
418
418
|
| `autoAuth` | Auto-run OAuth on `connect`/tool calls when a server needs auth, then retry once (default: false). |
|
|
@@ -484,7 +484,7 @@ Set `"outputGuard": false` — or the env kill switch `MCP_OUTPUT_GUARD=0` — t
|
|
|
484
484
|
|
|
485
485
|
For multi-call MCP work, write ordinary JavaScript: discover, inspect, call, loop, filter, chain, or fan out, then return one result. Run that code with the default-on `mcpScript` tool. For a single MCP call, search, describe, status check, or auth action, use `mcp` instead. Set `settings.scriptMode` to `false` to hide the scripting tool.
|
|
486
486
|
|
|
487
|
-
The bundled `mcp-scripting` skill is a separate Pi package resource. To
|
|
487
|
+
The bundled `mcp-scripting` skill is a separate Pi package resource and is manual-only by default, so its description is not added to the model's automatic skill context. Use `/skill:mcp-scripting` when you want its detailed workflow. To remove the manual skill command as well while keeping the adapter extension and `mcpScript` tool installed, replace the package entry in Pi settings with the object form and disable package skills:
|
|
488
488
|
|
|
489
489
|
```json
|
|
490
490
|
{
|
|
@@ -624,13 +624,13 @@ Models sometimes encode an object or array argument as a JSON string. Set `setti
|
|
|
624
624
|
|
|
625
625
|
Set `settings.directToolResultDetails` to `"bounded"` when an extension needs structured MCP result fields in Pi's direct-tool result details. The same output guard limits apply. Small leading structured fields stay available, while large fields receive bounded summaries and the complete guarded result follows the output guard's spill-file policy. The default `"lean"` mode keeps the existing server and tool metadata only.
|
|
626
626
|
|
|
627
|
-
If prompt-cache stability matters more than
|
|
627
|
+
If prompt-cache stability matters more than direct-tool hot-loading, set `settings.freezeDirectTools` to `true`. The initial direct-tool sync still runs, but later metadata updates and explicit reconnects keep the registered tool surface unchanged while proxy/search/cache metadata refreshes normally.
|
|
628
628
|
|
|
629
629
|
When you change direct-tool toggles in `/mcp`, the extension updates direct tool registration in the current session. Broader setup writes from `/mcp setup` still use Pi's normal reload flow because they can add or restructure MCP config files.
|
|
630
630
|
|
|
631
|
-
**Interactive configuration:** Run `/mcp` to open an interactive panel showing all servers with connection status, tools, and direct/proxy toggles. You can reconnect servers
|
|
631
|
+
**Interactive configuration:** Run `/mcp` to open an interactive panel showing all servers with connection status, tools, and direct/proxy toggles. You can reconnect servers, toggle tools between direct and proxy, and enable or disable servers (`ctrl+d`) from the same overlay. For OAuth, press Enter on a server that needs auth or `ctrl+a` on any OAuth server. The Save action defaults to `ctrl+s` and can be remapped with the `mcp.panel.save` keybinding.
|
|
632
632
|
|
|
633
|
-
**Guided first-run setup:** Run `/mcp setup` to inspect detected shared MCP files, adopt compatibility imports from other hosts, open discovered config paths, preview exact before/after file diffs for writes, scaffold a minimal
|
|
633
|
+
**Guided first-run setup:** Run `/mcp setup` to choose the normal write target for new shared servers — project `.mcp.json` or global `~/.config/mcp/mcp.json` — inspect detected shared MCP files, adopt compatibility imports from other hosts, open discovered config paths, preview exact before/after file diffs for writes, scaffold a minimal selected config, add a curated known server (DeepWiki, Context7, Notion, GitHub, or Chrome DevTools), or quick-add RepoPrompt into a standard/shared MCP file.
|
|
634
634
|
|
|
635
635
|
**Subagent integration:** If you use the subagent extension, agents can request direct MCP tools in their frontmatter with `mcp:server-name` syntax. See the subagent README for details.
|
|
636
636
|
|
|
@@ -712,7 +712,7 @@ Supported compatibility imports: `cursor`, `claude-code`, `claude-desktop`, `ope
|
|
|
712
712
|
|
|
713
713
|
### Project Config
|
|
714
714
|
|
|
715
|
-
Prefer `.mcp.json` for project-local shared MCP config. Use `.pi/mcp.json` only when you need a Pi-specific project override. Project files override both user-global shared MCP config and Pi global overrides.
|
|
715
|
+
Prefer `.mcp.json` for project-local shared MCP config and `~/.config/mcp/mcp.json` for user-global shared MCP config. Use `.pi/mcp.json` only when you need a Pi-specific project override. Project files override both user-global shared MCP config and Pi global overrides.
|
|
716
716
|
|
|
717
717
|
## Usage
|
|
718
718
|
|