@herbertgao/pi-extensions 2026.8.4 → 2026.8.5
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 -4
- package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +10 -2
- package/node_modules/@herbertgao/pi-cc-extensions/README.md +10 -2
- 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/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 +5 -8
- 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 +8 -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 +15 -2
- 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/schedule-menu.ts +9 -8
- package/node_modules/@herbertgao/pi-subagents/src/ui/select-item.ts +48 -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 +8 -7
- package/node_modules/@narumitw/pi-btw/package.json +2 -2
- package/node_modules/@narumitw/pi-btw/src/menu.ts +1 -0
- package/node_modules/pi-lens/CHANGELOG.md +2440 -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/agent-behavior-client.js +21 -4
- 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 +29 -25
- 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-publish.js +10 -3
- 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/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 +14 -0
- package/node_modules/pi-lens/dist/clients/cooperative-budget.js +42 -0
- package/node_modules/pi-lens/dist/clients/dead-code-client.js +2 -1
- 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 +347 -75
- package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +61 -11
- package/node_modules/pi-lens/dist/clients/diagnostics-publish.js +10 -3
- package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +63 -20
- 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 +1085 -681
- 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 +14 -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/lazy-installer.js +3 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +277 -26
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/spawn-outcome.js +22 -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 +10 -3
- package/node_modules/pi-lens/dist/clients/durable-store.js +97 -0
- package/node_modules/pi-lens/dist/clients/event-loop-monitor.js +94 -3
- package/node_modules/pi-lens/dist/clients/extension-log.js +139 -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/format-events-publish.js +16 -3
- 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 +681 -11
- package/node_modules/pi-lens/dist/clients/git-tracked-ignore.js +4 -0
- package/node_modules/pi-lens/dist/clients/go-client.js +2 -1
- package/node_modules/pi-lens/dist/clients/govulncheck-client.js +8 -0
- 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 +390 -99
- package/node_modules/pi-lens/dist/clients/instance-reaper.js +142 -172
- package/node_modules/pi-lens/dist/clients/jscpd-client.js +31 -54
- package/node_modules/pi-lens/dist/clients/knip-client.js +15 -36
- 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 +23 -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 +27 -4
- package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +8 -0
- package/node_modules/pi-lens/dist/clients/lens-map.js +94 -19
- package/node_modules/pi-lens/dist/clients/live-bus-emitter.js +30 -0
- package/node_modules/pi-lens/dist/clients/log-cleanup.js +2 -1
- package/node_modules/pi-lens/dist/clients/lsp/cascade-tier.js +1 -1
- package/node_modules/pi-lens/dist/clients/lsp/client.js +493 -48
- package/node_modules/pi-lens/dist/clients/lsp/config.js +13 -2
- package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +86 -0
- package/node_modules/pi-lens/dist/clients/lsp/edits.js +1012 -121
- package/node_modules/pi-lens/dist/clients/lsp/index.js +1807 -780
- 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 +196 -32
- 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 +123 -32
- package/node_modules/pi-lens/dist/clients/mcp/ipc.js +157 -24
- package/node_modules/pi-lens/dist/clients/mcp/session.js +216 -8
- 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/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 +47 -13
- 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/runner-adapters/call-graph-impact.js +8 -0
- 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/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/runtime-agent-end.js +107 -73
- package/node_modules/pi-lens/dist/clients/runtime-context.js +36 -12
- package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +74 -6
- package/node_modules/pi-lens/dist/clients/runtime-session.js +405 -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 +218 -23
- package/node_modules/pi-lens/dist/clients/runtime-turn.js +237 -64
- package/node_modules/pi-lens/dist/clients/rust-client.js +2 -1
- package/node_modules/pi-lens/dist/clients/safe-spawn.js +777 -62
- package/node_modules/pi-lens/dist/clients/security-scan-client.js +2 -1
- package/node_modules/pi-lens/dist/clients/session-state-store.js +3 -2
- package/node_modules/pi-lens/dist/clients/sg-runner.js +284 -174
- package/node_modules/pi-lens/dist/clients/slow-fs.js +2 -1
- package/node_modules/pi-lens/dist/clients/smells-rollup.js +224 -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 +1 -1
- package/node_modules/pi-lens/dist/clients/test-runner-client.js +38 -8
- package/node_modules/pi-lens/dist/clients/tool-event.js +35 -0
- package/node_modules/pi-lens/dist/clients/tool-policy.js +388 -39
- package/node_modules/pi-lens/dist/clients/tool-render.js +155 -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 +33 -13
- package/node_modules/pi-lens/dist/clients/widget-state.js +300 -43
- package/node_modules/pi-lens/dist/clients/word-index.js +391 -64
- package/node_modules/pi-lens/dist/clients/workspace-topology.js +89 -6
- package/node_modules/pi-lens/dist/index.js +49361 -36888
- package/node_modules/pi-lens/dist/mcp/analyze-cli.js +182 -29
- package/node_modules/pi-lens/dist/mcp/server.js +211 -44
- package/node_modules/pi-lens/dist/tools/ast-grep-search.js +93 -27
- package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +200 -36
- package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +153 -40
- 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/docs/agent-guide.md +2 -2
- 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 +5 -2
- 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 +31 -2
- package/node_modules/pi-lens/docs/globalconfig.md +45 -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 +12 -1
- package/node_modules/pi-lens/docs/tools.md +4 -1
- package/node_modules/pi-lens/docs/usage.md +18 -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-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-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-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-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 +55 -2
- package/node_modules/pi-mcp-adapter/CHANGELOG.md +25 -0
- package/node_modules/pi-mcp-adapter/README.md +34 -3
- package/node_modules/pi-mcp-adapter/agent-plugin-loader.ts +1 -1
- package/node_modules/pi-mcp-adapter/commands.ts +15 -7
- package/node_modules/pi-mcp-adapter/direct-tools.ts +54 -7
- 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/metadata-cache.ts +27 -4
- package/node_modules/pi-mcp-adapter/npx-resolver.ts +81 -26
- package/node_modules/pi-mcp-adapter/package.json +3 -3
- package/node_modules/pi-mcp-adapter/proxy-modes.ts +108 -26
- package/node_modules/pi-mcp-adapter/search-ranking.ts +86 -7
- package/node_modules/pi-mcp-adapter/server-manager.ts +36 -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 +42 -4
- package/node_modules/pi-mcp-adapter/tool-result-renderer.ts +138 -12
- package/node_modules/pi-mcp-adapter/types.ts +93 -27
- package/node_modules/pi-mcp-adapter/ui-server.ts +20 -1
- package/package.json +11 -12
- 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
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
id: no-bare-host-path-in-win32-branch
|
|
2
|
+
language: TypeScript
|
|
3
|
+
severity: warning
|
|
4
|
+
message: "Use win32 path operations inside a branch committed to Windows path semantics"
|
|
5
|
+
note: |
|
|
6
|
+
A branch guarded by isWindowsPath/isFullyQualifiedWin32 has committed to
|
|
7
|
+
Windows path parsing. Host-default dirname/basename/join/relative/sep
|
|
8
|
+
follows the process OS and is wrong for a Windows-shaped path on POSIX.
|
|
9
|
+
|
|
10
|
+
SCOPE (review-verified, #1339): same-function consequence only. The
|
|
11
|
+
original #1150 defect — a bare dirname inside an UNGUARDED helper that
|
|
12
|
+
the guarded branch calls (cross-function) — is NOT reachable by this
|
|
13
|
+
engine and stays review-enforced via AGENTS.md defect-shape 2. The
|
|
14
|
+
rule's fixture file encodes that miss as a documented negative; flip it
|
|
15
|
+
to a positive only if cross-function reach is ever added. What this
|
|
16
|
+
rule does catch is the in-branch shape (#1152 class).
|
|
17
|
+
rule:
|
|
18
|
+
all:
|
|
19
|
+
- kind: if_statement
|
|
20
|
+
- has:
|
|
21
|
+
field: condition
|
|
22
|
+
regex: "\\b(isWindowsPath|isFullyQualifiedWin32)\\s*\\("
|
|
23
|
+
- has:
|
|
24
|
+
field: consequence
|
|
25
|
+
regex: "(?s)\\bpath\\.(dirname|basename|join|relative)\\s*\\(|\\bpath\\.sep\\b|(^|[^.])\\b(dirname|basename|join|relative)\\s*\\("
|
|
@@ -8,6 +8,12 @@ note: |
|
|
|
8
8
|
rule:
|
|
9
9
|
all:
|
|
10
10
|
- kind: jsx_element
|
|
11
|
+
- has:
|
|
12
|
+
field: open_tag
|
|
13
|
+
kind: jsx_opening_element
|
|
14
|
+
has:
|
|
15
|
+
field: name
|
|
16
|
+
regex: "^a$"
|
|
11
17
|
- has:
|
|
12
18
|
kind: jsx_element
|
|
13
19
|
stopBy: end
|
|
@@ -20,6 +26,7 @@ rule:
|
|
|
20
26
|
not:
|
|
21
27
|
inside:
|
|
22
28
|
kind: jsx_element
|
|
29
|
+
stopBy: end
|
|
23
30
|
has:
|
|
24
31
|
field: open_tag
|
|
25
32
|
kind: jsx_opening_element
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
id: no-raw-json-store-write
|
|
2
|
+
language: TypeScript
|
|
3
|
+
severity: warning
|
|
4
|
+
message: "Use the atomic write seam for JSON stores instead of writeFileSync"
|
|
5
|
+
note: |
|
|
6
|
+
JSON-backed durable state must be committed through clients/durable-store.ts
|
|
7
|
+
when read-modify-write isolation is required; that seam publishes through
|
|
8
|
+
clients/atomic-write.ts. This rule covers the direct
|
|
9
|
+
writeFileSync(path, JSON.stringify(data)) shape. Build scripts and the
|
|
10
|
+
installer's wx lock writes are intentionally outside this rule's scope.
|
|
11
|
+
ignores:
|
|
12
|
+
- "**/clients/atomic-write.ts"
|
|
13
|
+
- "**/clients/installer/index.ts"
|
|
14
|
+
- "**/scripts/**"
|
|
15
|
+
rule:
|
|
16
|
+
any:
|
|
17
|
+
- pattern: writeFileSync($PATH, JSON.stringify($$$ARGS))
|
|
18
|
+
- pattern: $FS.writeFileSync($PATH, JSON.stringify($$$ARGS))
|
|
19
|
+
- pattern: writeFileSync($PATH, JSON.stringify($$$ARGS), $OPTS)
|
|
20
|
+
- pattern: $FS.writeFileSync($PATH, JSON.stringify($$$ARGS), $OPTS)
|
|
21
|
+
- kind: expression_statement
|
|
22
|
+
has:
|
|
23
|
+
pattern: writeFileSync($PATH, $PAYLOAD)
|
|
24
|
+
follows:
|
|
25
|
+
pattern: const $PAYLOAD = JSON.stringify($DATA)
|
|
26
|
+
- kind: expression_statement
|
|
27
|
+
has:
|
|
28
|
+
pattern: $FS.writeFileSync($PATH, $PAYLOAD)
|
|
29
|
+
follows:
|
|
30
|
+
pattern: const $PAYLOAD = JSON.stringify($DATA)
|
package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-win32-isabsolute-for-qualification.yml
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
id: no-win32-isabsolute-for-qualification
|
|
2
|
+
language: TypeScript
|
|
3
|
+
severity: warning
|
|
4
|
+
message: "Use isFullyQualified for path qualification instead of win32.isAbsolute"
|
|
5
|
+
note: |
|
|
6
|
+
Qualification must follow the input path's shape. Use clients/path-utils.ts
|
|
7
|
+
isFullyQualified(), which distinguishes drive-absolute, UNC, rooted-relative,
|
|
8
|
+
POSIX-absolute, and relative paths across host operating systems. The
|
|
9
|
+
implementation of isFullyQualified itself is excluded because it is the
|
|
10
|
+
compatibility seam that owns the win32 parser call.
|
|
11
|
+
|
|
12
|
+
SCOPE (review-verified, #1349): direct call forms only --
|
|
13
|
+
path.win32.isAbsolute(...) and a destructured win32.isAbsolute(...). An
|
|
14
|
+
ALIASED parser (const w = path.win32; w.isAbsolute(p) -- the shape the
|
|
15
|
+
actual pre-#1330 defect used) is beyond the engine's reach and stays
|
|
16
|
+
review-enforced; the fixture file encodes that miss as a documented
|
|
17
|
+
negative, matching the #1339 precedent.
|
|
18
|
+
ignores:
|
|
19
|
+
- "**/clients/path-utils.ts"
|
|
20
|
+
rule:
|
|
21
|
+
any:
|
|
22
|
+
- pattern: path.win32.isAbsolute($P)
|
|
23
|
+
- pattern: win32.isAbsolute($P)
|
|
@@ -18,15 +18,13 @@ query: |
|
|
|
18
18
|
(jsx_element
|
|
19
19
|
open_tag: (jsx_opening_element
|
|
20
20
|
(identifier) @OUTER
|
|
21
|
-
(#eq? @OUTER "a"))
|
|
22
|
-
(jsx_element
|
|
23
|
-
open_tag: (jsx_opening_element
|
|
24
|
-
(identifier) @INNER
|
|
25
|
-
(#eq? @INNER "a"))))
|
|
21
|
+
(#eq? @OUTER "a"))) @OUTER_ELEMENT
|
|
26
22
|
|
|
27
23
|
metavars:
|
|
28
24
|
- OUTER
|
|
29
|
-
-
|
|
25
|
+
- OUTER_ELEMENT
|
|
26
|
+
|
|
27
|
+
post_filter: no_nested_anchor_chain
|
|
30
28
|
|
|
31
29
|
tags:
|
|
32
30
|
- correctness
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
* ~/.pi-lens/cascade*.log JSONL impact-cascade logs
|
|
9
9
|
* ~/.pi-lens/read-guard*.log JSONL read-guard friction logs
|
|
10
10
|
* ~/.pi-lens/tree-sitter*.log JSONL structural runner logs
|
|
11
|
+
* ~/.pi-lens/extension*.log JSONL extension diagnostics and console-guard telemetry
|
|
11
12
|
* ~/.pi-lens/actionable-warnings*.log JSONL advisory pipeline (inject/suppress)
|
|
12
13
|
* ~/.pi-lens/ast-grep-tools*.log JSONL MCP ast-grep search/replace telemetry
|
|
13
14
|
* ~/.pi-lens/logs/*.jsonl JSONL diagnostic findings
|
|
@@ -18,10 +19,12 @@ import os from "node:os";
|
|
|
18
19
|
import path from "node:path";
|
|
19
20
|
import readline from "node:readline";
|
|
20
21
|
import { fileURLToPath } from "node:url";
|
|
22
|
+
import { minimatch } from "minimatch";
|
|
21
23
|
|
|
22
24
|
const DEFAULT_ROOT = path.join(os.homedir(), ".pi-lens");
|
|
23
25
|
const DEFAULT_SINCE = "2d";
|
|
24
26
|
const DEFAULT_LIMIT = 12;
|
|
27
|
+
const DEFAULT_EXCLUDE_GLOBS = ["**/AppData/Local/Temp/claude/**", "**/heap-corpus*/**", "**/.plegma/work/**"];
|
|
25
28
|
|
|
26
29
|
const args = parseArgs(process.argv.slice(2));
|
|
27
30
|
const root = path.resolve(expandHome(args.root ?? DEFAULT_ROOT));
|
|
@@ -30,6 +33,10 @@ const limit =
|
|
|
30
33
|
Number.parseInt(args.limit ?? `${DEFAULT_LIMIT}`, 10) || DEFAULT_LIMIT;
|
|
31
34
|
const outputJson = Boolean(args.json);
|
|
32
35
|
const includeArchived = Boolean(args.archived);
|
|
36
|
+
const excludeGlobs = [
|
|
37
|
+
...DEFAULT_EXCLUDE_GLOBS,
|
|
38
|
+
...(Array.isArray(args.exclude) ? args.exclude : args.exclude ? [args.exclude] : []),
|
|
39
|
+
];
|
|
33
40
|
|
|
34
41
|
const thresholds = {
|
|
35
42
|
startupSlowMs: Number.parseInt(args.startupSlowMs ?? "500", 10),
|
|
@@ -83,7 +90,14 @@ function parseArgs(argv) {
|
|
|
83
90
|
const key = arg.slice(2);
|
|
84
91
|
const next = argv[i + 1];
|
|
85
92
|
if (!next || next.startsWith("--")) out[key] = "true";
|
|
86
|
-
else
|
|
93
|
+
else if (key === "exclude") {
|
|
94
|
+
const value = argv[++i];
|
|
95
|
+
out.exclude = out.exclude
|
|
96
|
+
? Array.isArray(out.exclude)
|
|
97
|
+
? [...out.exclude, value]
|
|
98
|
+
: [out.exclude, value]
|
|
99
|
+
: value;
|
|
100
|
+
} else out[key] = argv[++i];
|
|
87
101
|
}
|
|
88
102
|
}
|
|
89
103
|
return out;
|
|
@@ -158,6 +172,7 @@ function createState(files) {
|
|
|
158
172
|
window: { since: since?.toISOString() ?? "all", root },
|
|
159
173
|
files,
|
|
160
174
|
parseErrors: counter(),
|
|
175
|
+
excludedRows: 0,
|
|
161
176
|
seen: counter(),
|
|
162
177
|
projects: counter(),
|
|
163
178
|
smellTotals: counter(),
|
|
@@ -557,6 +572,10 @@ async function analyzeSessionStart(files, state) {
|
|
|
557
572
|
const ts = dateOf(match[1]);
|
|
558
573
|
if (!inWindow(ts)) return;
|
|
559
574
|
const message = match[2];
|
|
575
|
+
if (isExcludedText(message)) {
|
|
576
|
+
state.excludedRows++;
|
|
577
|
+
return;
|
|
578
|
+
}
|
|
560
579
|
state.seen.inc("sessionstart");
|
|
561
580
|
|
|
562
581
|
const cwd = /session_start cwd:\s*(.*)$/.exec(message)?.[1];
|
|
@@ -722,13 +741,45 @@ async function forEachJsonLine(file, bucket, state, visitor) {
|
|
|
722
741
|
await forEachLine(file, async (line) => {
|
|
723
742
|
if (!line.trim()) return;
|
|
724
743
|
try {
|
|
725
|
-
|
|
744
|
+
const entry = JSON.parse(line);
|
|
745
|
+
if (isExcludedEntry(entry)) {
|
|
746
|
+
state.excludedRows++;
|
|
747
|
+
return;
|
|
748
|
+
}
|
|
749
|
+
visitor(entry);
|
|
726
750
|
} catch {
|
|
727
751
|
state.parseErrors.inc(`${bucket}:${path.basename(file)}`);
|
|
728
752
|
}
|
|
729
753
|
});
|
|
730
754
|
}
|
|
731
755
|
|
|
756
|
+
function isExcludedEntry(entry) {
|
|
757
|
+
return pathValues(entry).some((value) =>
|
|
758
|
+
excludeGlobs.some((glob) =>
|
|
759
|
+
minimatch(value, glob, { nocase: true, dot: true }),
|
|
760
|
+
),
|
|
761
|
+
);
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
function pathValues(value, key = "") {
|
|
765
|
+
if (typeof value === "string") {
|
|
766
|
+
return /(file|path|cwd|root|project)/i.test(key) ? [normalizePath(value)] : [];
|
|
767
|
+
}
|
|
768
|
+
if (!value || typeof value !== "object") return [];
|
|
769
|
+
return Object.entries(value).flatMap(([childKey, child]) =>
|
|
770
|
+
pathValues(child, childKey),
|
|
771
|
+
);
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
function isExcludedText(text) {
|
|
775
|
+
const cwd = /session_start cwd:\s*(.*)$/.exec(text)?.[1];
|
|
776
|
+
return cwd
|
|
777
|
+
? excludeGlobs.some((glob) =>
|
|
778
|
+
minimatch(normalizePath(cwd), glob, { nocase: true, dot: true }),
|
|
779
|
+
)
|
|
780
|
+
: false;
|
|
781
|
+
}
|
|
782
|
+
|
|
732
783
|
async function forEachLine(file, visitor) {
|
|
733
784
|
if (!fs.existsSync(file)) return;
|
|
734
785
|
const rl = readline.createInterface({
|
|
@@ -1129,6 +1180,7 @@ function buildReport(state) {
|
|
|
1129
1180
|
Object.entries(state.files).map(([key, list]) => [key, list.length]),
|
|
1130
1181
|
),
|
|
1131
1182
|
rowsSeen: state.seen.toJSON(),
|
|
1183
|
+
rowsExcluded: state.excludedRows,
|
|
1132
1184
|
parseErrors: state.parseErrors.toJSON(),
|
|
1133
1185
|
projects: state.projects.top(limit),
|
|
1134
1186
|
smells,
|
|
@@ -1232,6 +1284,7 @@ function printReport(report) {
|
|
|
1232
1284
|
.map(([k, v]) => `${k}=${v}`)
|
|
1233
1285
|
.join(", ")}`,
|
|
1234
1286
|
);
|
|
1287
|
+
console.log(`${report.rowsExcluded} rows excluded (synthetic corpora)`);
|
|
1235
1288
|
if (Object.keys(report.parseErrors).length)
|
|
1236
1289
|
console.log(`parse errors: ${JSON.stringify(report.parseErrors)}`);
|
|
1237
1290
|
|
|
@@ -7,6 +7,31 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [2.25.0] - 2026-08-13
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- Added `settings.notifyOnStartupConnect` to suppress successful MCP startup connection notices. Thanks @pierre-mgmt for issue #341.
|
|
14
|
+
- Added compact self-rendered MCP proxy and direct-tool result rows by default, with `settings.toolResultRendering: "boxed"` for the legacy boxed row and `settings.collapsedResultLines` for 1-3 collapsed result lines. Thanks @pierre-mgmt for issue #349.
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
- Removed unused TypeScript declarations found by stricter compiler checks.
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
- Kept `mcpScript` tool-call replies flowing when Pi runs as a Bun-compiled binary by starting worker execution without module-level top-level await. Thanks @AndreiKopylov for issue #340 and @thesobercoder for the verified fix.
|
|
21
|
+
- Fixed direct-tool server prefixes to preserve provider-valid underscores and hyphens, including `codebase-memory-mcp`, while retaining safe escaping, collision handling, and exact proxy routing. Thanks @mightymatth for issue #342 and @JasonLandbridge for issue #343.
|
|
22
|
+
|
|
23
|
+
## [2.24.0] - 2026-08-13
|
|
24
|
+
|
|
25
|
+
### Added
|
|
26
|
+
- Added per-server `searchKeywords` so `mcp({ search })` and `mcpScript` `tools.search` understand user-defined synonyms and aliases for tools. Keywords are keyed by tool name or glob and boost ranked and regex search only. They never appear in tool schemas, describe output, or the metadata cache. Thanks @Serisium for PR #336.
|
|
27
|
+
|
|
28
|
+
### Fixed
|
|
29
|
+
- Interpolated environment placeholders in stdio server arguments. Thanks @vjik for issue #333.
|
|
30
|
+
- Kept remote `/mcp-auth` authorization links reachable before the callback input opens. Thanks @trevorleibert-mixpanel for PR #331.
|
|
31
|
+
- Cached OAuth credentials in memory and refreshed them after OAuth-backed 401 responses. Thanks @daniel-sampliner for PR #335.
|
|
32
|
+
- Sanitized MCP server-name prefixes for provider-safe tool names while preserving server resolution. Thanks @triple-dex for issue #334.
|
|
33
|
+
- Validated persisted npx resolver cache entries before reuse, including malformed and prototype-sensitive persisted keys.
|
|
34
|
+
|
|
10
35
|
## [2.23.0] - 2026-08-11
|
|
11
36
|
|
|
12
37
|
### Added
|
|
@@ -227,6 +227,7 @@ In the configuration examples below, `30000` is illustrative only. If `requestTi
|
|
|
227
227
|
| `toolPrefix` | Override global `settings.toolPrefix` for this server (`"server"`, `"short"`, `"none"`, or `"mcp"`) |
|
|
228
228
|
| `includeTools` | `string[]` of tool names or glob patterns to expose (matches original names like `get_screenshot`, generated resource names like `read_figjam`, and prefixed names like `figma_get_screenshot`) |
|
|
229
229
|
| `excludeTools` | `string[]` of tool names or glob patterns to hide (applied after `includeTools`) |
|
|
230
|
+
| `searchKeywords` | `{ "tool-or-glob": ["keyword", ...] }` — extra keywords that boost `mcp({ search })` ranking for matching tools; never shown to the model |
|
|
230
231
|
| `debug` | Show server stderr (default: false) |
|
|
231
232
|
| `trace` | Enable metadata-only JSONL protocol tracing for this server; payloads, prompts, tool arguments/results, authorization data, and URLs are never persisted |
|
|
232
233
|
| `disabled` | Keep the server visible in config and status, but prevent connections, authentication, tools, and resource calls (only literal `true` disables it) |
|
|
@@ -265,7 +266,7 @@ The adapter owns only its client socket and closes that connection when the Pi r
|
|
|
265
266
|
|
|
266
267
|
### Remote/headless OAuth
|
|
267
268
|
|
|
268
|
-
If Pi is running on a remote server, `/mcp-auth <server>`
|
|
269
|
+
If Pi is running on a remote server, `/mcp-auth <server>` shows a clickable authorization URL first. Open it in your local browser and approve access, then select **Yes** in Pi to open the callback input. The browser may fail to load the localhost callback page because localhost refers to your workstation; copy the full URL from its address bar and paste it into Pi. The authorization screen closes automatically instead when the browser can reach Pi's callback directly.
|
|
269
270
|
|
|
270
271
|
The same flow is available through the proxy tool for non-interactive clients. Persistent OAuth still requires an available OS credential store; on headless Linux that usually means an unlocked Secret Service/libsecret keyring. The adapter fails closed instead of falling back to plaintext credentials when the secure store is unavailable.
|
|
271
272
|
|
|
@@ -306,6 +307,9 @@ When any enabled server uses `eager` or `keep-alive`, initialization also starts
|
|
|
306
307
|
"requestTimeoutMs": 30000,
|
|
307
308
|
"showStatusIcon": true,
|
|
308
309
|
"mcpFooterStatus": "full",
|
|
310
|
+
"toolResultRendering": "compact",
|
|
311
|
+
"collapsedResultLines": 1,
|
|
312
|
+
"notifyOnStartupConnect": true,
|
|
309
313
|
"hostConfigDiscovery": "off",
|
|
310
314
|
"approveTools": ["github_delete_*", "notion_update_*"],
|
|
311
315
|
"oauthDir": ".pi/mcp-oauth",
|
|
@@ -327,6 +331,9 @@ When any enabled server uses `eager` or `keep-alive`, initialization also starts
|
|
|
327
331
|
| `requestTimeoutMs` | Global request timeout in milliseconds for live MCP calls (if omitted or `<= 0`, the MCP SDK default timeout is used) |
|
|
328
332
|
| `showStatusIcon` | Show the plug icon in MCP status and connection text (default: `true`). Set to `false` for plain `MCP: ...` text. |
|
|
329
333
|
| `mcpFooterStatus` | MCP footer verbosity: `"full"` (default), `"compact"` for `MCP connected/enabled`, or `"off"` to clear the persistent footer status. `/mcp status` remains available. |
|
|
334
|
+
| `toolResultRendering` | MCP tool result row style: `"compact"` (default) uses self-rendered rows, or `"boxed"` restores the legacy Pi boxed tool row. |
|
|
335
|
+
| `collapsedResultLines` | Number of result text lines to show before expansion: `1`, `2`, or `3`. Defaults to `1` in compact mode and `3` in boxed mode. |
|
|
336
|
+
| `notifyOnStartupConnect` | Show successful startup connection notices (default: `true`). Set to `false` to suppress routine `MCP: N servers connected (M tools)` notices. Connection errors and authentication warnings remain visible. |
|
|
330
337
|
| `hostConfigDiscovery` | Host-specific config policy: `"off"` (default), `"prompt"` (detect/report only), or `"on"` (explicitly load detected host configs as the lowest-precedence fallback) |
|
|
331
338
|
| `agentPluginPaths` | Agent Plugins package directories to load MCP servers from. Relative paths resolve from the active project cwd. |
|
|
332
339
|
| `approveTools` | `true` to require approval before every MCP tool call, or an array of glob patterns such as `["github_delete_*", "notion_update_*"]`. Per-server `approveTools` overrides this. |
|
|
@@ -648,12 +655,35 @@ Prefer `.mcp.json` for project-local shared MCP config. Use `.pi/mcp.json` only
|
|
|
648
655
|
|
|
649
656
|
`mcp({ connect: "server-name" })` refreshes an already connected server, so new tools, resources, prompts, and instructions can load without restarting Pi.
|
|
650
657
|
|
|
651
|
-
MCP proxy and direct-tool results
|
|
658
|
+
MCP proxy and direct-tool results use compact self-rendered rows by default. Collapsed success output shows the call title and the first result line, with a `Ctrl+O to expand` hint when more text is hidden. The full result remains available when expanded and is still returned unchanged to the model. Set `settings.toolResultRendering` to `"boxed"` to restore the legacy boxed Pi row, or set `settings.collapsedResultLines` to `2` or `3` when you want more collapsed text.
|
|
652
659
|
|
|
653
|
-
Search includes both MCP tools and Pi tools (from extensions). Pi tools appear first with `[pi tool]` prefix. Space-separated words are ranked by weighted matches across name, server,
|
|
660
|
+
Search includes both MCP tools and Pi tools (from extensions). Pi tools appear first with `[pi tool]` prefix. Space-separated words are ranked by weighted matches across name, server, description, and any configured `searchKeywords`, then returned one page at a time (`limit` defaults to 12). Use `details.nextOffset` for the next page. Regex search is still available with `regex: true`, but regex results are paginated without ranking.
|
|
654
661
|
|
|
655
662
|
Tool names are fuzzy-matched on hyphens and underscores — `context7_resolve_library_id` finds `context7_resolve-library-id`. When `describe` or `tool` cannot resolve a name, the result includes top suggestions so the agent can correct a typo or missing prefix in the same turn.
|
|
656
663
|
|
|
664
|
+
### Search keywords
|
|
665
|
+
|
|
666
|
+
Search uses literal matching so a tool whose name and description use different vocabulary than the query won't be found. Per-server `searchKeywords` adds extra vocabulary for matching tools:
|
|
667
|
+
|
|
668
|
+
```json
|
|
669
|
+
{
|
|
670
|
+
"mcpServers": {
|
|
671
|
+
"github": {
|
|
672
|
+
"command": "npx",
|
|
673
|
+
"args": ["-y", "@modelcontextprotocol/server-github"],
|
|
674
|
+
"searchKeywords": {
|
|
675
|
+
"search_code": ["grep"],
|
|
676
|
+
"*": ["gh"]
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
```
|
|
682
|
+
|
|
683
|
+
With this config, `mcp({ search: "grep" })` finds `github_search_code` even though neither its name nor description contains that word. Similarly, `mcp({ search: "gh" })` finds all tools provided by the github server.
|
|
684
|
+
|
|
685
|
+
Keys match a tool's original name, prefixed name, or a glob (`*` applies to every tool on the server) and all matching entries combine. Keywords are weighted like description text, with an extra boost when the query exactly matches a configured phrase. They affect ranked and regex search only (including `tools.search` in `mcpScript`): they never appear in tool schemas, `describe` output, direct-tool registration, or the metadata cache, and search with keywords works offline from cached metadata.
|
|
686
|
+
|
|
657
687
|
When `includeSchemas` is enabled, search and describe render common JSON Schema parameters as compact TypeScript shapes like `{ query: string; limit?: number; }`, with the older schema formatter retained as a fallback for unsupported schemas.
|
|
658
688
|
|
|
659
689
|
For HTTP servers, failed connects run a one-request shape probe that can turn opaque transport errors into setup hints such as `endpoint returned HTML (200) — this URL does not appear to speak MCP`. Healthy connections are not probed.
|
|
@@ -699,4 +729,5 @@ Advertised tool `outputSchema` values support JSON Schema draft-07 and 2020-12.
|
|
|
699
729
|
|
|
700
730
|
- Cross-session server sharing not yet implemented (each Pi session runs its own server processes)
|
|
701
731
|
- Compact MCP result rendering summarizes text, but inline images are still controlled by Pi's image display settings and may render below the compact text summary.
|
|
732
|
+
- Pi still owns one separator row before self-rendered tool output, so compact mode reduces adapter rendering height but cannot promise true zero-gap rows.
|
|
702
733
|
- MCP sampling support is text-only; context inclusion, tools, stop sequences, audio, and image content are rejected with explicit errors.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { existsSync,
|
|
1
|
+
import { existsSync, readFileSync, statSync } from "node:fs";
|
|
2
2
|
import { isAbsolute, relative, resolve, sep } from "node:path";
|
|
3
3
|
import { getAgentPath } from "./agent-dir.ts";
|
|
4
4
|
import type { McpConfig, ServerEntry } from "./types.ts";
|
|
@@ -12,7 +12,6 @@ import {
|
|
|
12
12
|
previewSharedServerEntry,
|
|
13
13
|
previewStarterProjectConfig,
|
|
14
14
|
writeDirectToolsConfig,
|
|
15
|
-
writeProjectServerDisabledOverride,
|
|
16
15
|
writeSharedServerEntry,
|
|
17
16
|
writeStarterProjectConfig,
|
|
18
17
|
} from "./config.ts";
|
|
@@ -170,7 +169,7 @@ export async function reconnectServer(
|
|
|
170
169
|
}
|
|
171
170
|
|
|
172
171
|
const prefix = state.config.settings?.toolPrefix ?? "server";
|
|
173
|
-
const { metadata, failedTools } = buildToolMetadata(connection.tools, connection.resources, definition, name, prefix);
|
|
172
|
+
const { metadata, failedTools } = buildToolMetadata(connection.tools, connection.resources, definition, name, prefix, state.config.mcpServers, state.toolMetadata);
|
|
174
173
|
state.toolMetadata.set(name, metadata);
|
|
175
174
|
if (!connection.promptDiscoveryFailed) {
|
|
176
175
|
state.promptMetadata?.set(name, reconstructPromptMetadata(name, connection.prompts ?? [], prefix, definition));
|
|
@@ -283,11 +282,20 @@ export async function authenticateServer(
|
|
|
283
282
|
"info"
|
|
284
283
|
);
|
|
285
284
|
},
|
|
286
|
-
onAuthorizationInput: (
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
285
|
+
onAuthorizationInput: async (authorizationUrl, inputSignal) => {
|
|
286
|
+
const readyToPaste = await ui.confirm(
|
|
287
|
+
`Authorize ${serverName}`,
|
|
288
|
+
`Open this link in your browser:\n${terminalHyperlink(authorizationUrl, authorizationUrl)}\n\n` +
|
|
289
|
+
"After approving access, select Yes to paste the callback URL.",
|
|
290
|
+
{ signal: inputSignal },
|
|
291
|
+
);
|
|
292
|
+
if (!readyToPaste || inputSignal.aborted) return undefined;
|
|
293
|
+
return ui.input(
|
|
294
|
+
`Complete ${serverName} OAuth`,
|
|
295
|
+
"Paste the full callback URL",
|
|
296
|
+
{ signal: inputSignal },
|
|
297
|
+
);
|
|
298
|
+
},
|
|
291
299
|
...(signal ? { signal } : {}),
|
|
292
300
|
...(runtime ? { runtime } : {}),
|
|
293
301
|
});
|
|
@@ -11,7 +11,8 @@ import { formatSchema } from "./tool-metadata.ts";
|
|
|
11
11
|
import { resolveMcpResultContent, transformMcpContent, transformMcpResourceContents } from "./tool-registrar.ts";
|
|
12
12
|
import { guardMcpOutput, guardedMcpDetails, resolveMcpOutputGuardOptions } from "./mcp-output-guard.ts";
|
|
13
13
|
import { maybeStartUiSession, summarizeUiSessionResult, type UiSessionRuntime } from "./ui-session.ts";
|
|
14
|
-
import { formatToolName, isServerDisabled, isToolAllowed, resolveToolPrefix } from "./types.ts";
|
|
14
|
+
import { formatToolName, getToolNameCandidates, isServerDisabled, isToolAllowed, resolveToolPrefix } from "./types.ts";
|
|
15
|
+
import { isUiToolVisibleToModel } from "./ui-tool-visibility.ts";
|
|
15
16
|
import { resourceNameToToolName } from "./resource-tools.ts";
|
|
16
17
|
import { authenticate, supportsOAuth } from "./mcp-auth-flow.ts";
|
|
17
18
|
import { formatAuthRequiredMessage, resolveServerUrl, truncateAtWord } from "./utils.ts";
|
|
@@ -149,10 +150,31 @@ export function resolveDirectTools(
|
|
|
149
150
|
if (!toolFilter) continue;
|
|
150
151
|
|
|
151
152
|
const effectivePrefix = resolveToolPrefix(definition, prefix);
|
|
153
|
+
const getOtherCurrentCandidates = (toolName: string): Set<string> => {
|
|
154
|
+
const candidates = new Set<string>();
|
|
155
|
+
for (const [otherServerName, otherDefinition] of Object.entries(config.mcpServers)) {
|
|
156
|
+
const otherCache = cache.servers[otherServerName];
|
|
157
|
+
if (!otherCache || !isServerCacheValid(otherCache, otherDefinition) || isServerDisabled(otherDefinition)) continue;
|
|
158
|
+
const otherPrefix = resolveToolPrefix(otherDefinition, prefix);
|
|
159
|
+
for (const otherTool of otherCache.tools ?? []) {
|
|
160
|
+
if (!isUiToolVisibleToModel(otherTool.uiVisibility)) continue;
|
|
161
|
+
for (const candidate of getToolNameCandidates(otherTool.name, otherServerName, otherPrefix, false)) candidates.add(candidate);
|
|
162
|
+
}
|
|
163
|
+
if (otherDefinition.exposeResources !== false) {
|
|
164
|
+
for (const resource of otherCache.resources ?? []) {
|
|
165
|
+
const baseName = `read_${resourceNameToToolName(resource.name)}`;
|
|
166
|
+
for (const candidate of getToolNameCandidates(baseName, otherServerName, otherPrefix, false)) candidates.add(candidate);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
for (const candidate of getToolNameCandidates(toolName, serverName, effectivePrefix, false)) candidates.delete(candidate);
|
|
171
|
+
return candidates;
|
|
172
|
+
};
|
|
152
173
|
|
|
153
174
|
for (const tool of serverCache.tools ?? []) {
|
|
175
|
+
if (!isUiToolVisibleToModel(tool.uiVisibility)) continue;
|
|
154
176
|
if (toolFilter !== true && !toolFilter.includes(tool.name)) continue;
|
|
155
|
-
if (!isToolAllowed(tool.name, serverName, effectivePrefix, definition.includeTools, definition.excludeTools)) continue;
|
|
177
|
+
if (!isToolAllowed(tool.name, serverName, effectivePrefix, definition.includeTools, definition.excludeTools, getOtherCurrentCandidates(tool.name))) continue;
|
|
156
178
|
const prefixedName = formatToolName(tool.name, serverName, effectivePrefix);
|
|
157
179
|
if (BUILTIN_NAMES.has(prefixedName)) {
|
|
158
180
|
console.warn(`MCP: skipping direct tool "${prefixedName}" (collides with builtin)`);
|
|
@@ -178,7 +200,7 @@ export function resolveDirectTools(
|
|
|
178
200
|
for (const resource of serverCache.resources ?? []) {
|
|
179
201
|
const baseName = `read_${resourceNameToToolName(resource.name)}`;
|
|
180
202
|
if (toolFilter !== true && !toolFilter.includes(baseName)) continue;
|
|
181
|
-
if (!isToolAllowed(baseName, serverName, effectivePrefix, definition.includeTools, definition.excludeTools)) continue;
|
|
203
|
+
if (!isToolAllowed(baseName, serverName, effectivePrefix, definition.includeTools, definition.excludeTools, getOtherCurrentCandidates(baseName))) continue;
|
|
182
204
|
const prefixedName = formatToolName(baseName, serverName, effectivePrefix);
|
|
183
205
|
if (BUILTIN_NAMES.has(prefixedName)) {
|
|
184
206
|
console.warn(`MCP: skipping direct resource tool "${prefixedName}" (collides with builtin)`);
|
|
@@ -230,15 +252,38 @@ export function buildProxyDescription(
|
|
|
230
252
|
for (const serverName of Object.keys(config.mcpServers)) {
|
|
231
253
|
const definition = config.mcpServers[serverName];
|
|
232
254
|
if (!definition || isServerDisabled(definition)) continue;
|
|
233
|
-
const
|
|
255
|
+
const cachedEntry = cache?.servers?.[serverName];
|
|
256
|
+
const entry = cachedEntry && isServerCacheValid(cachedEntry, definition) ? cachedEntry : undefined;
|
|
234
257
|
const effectivePrefix = resolveToolPrefix(definition, prefix);
|
|
258
|
+
const getOtherCurrentCandidates = (toolName: string): Set<string> | undefined => {
|
|
259
|
+
if (!cache) return undefined;
|
|
260
|
+
const candidates = new Set<string>();
|
|
261
|
+
for (const [otherServerName, otherDefinition] of Object.entries(config.mcpServers)) {
|
|
262
|
+
const otherEntry = cache.servers[otherServerName];
|
|
263
|
+
if (!otherEntry || !isServerCacheValid(otherEntry, otherDefinition) || isServerDisabled(otherDefinition)) continue;
|
|
264
|
+
const otherPrefix = resolveToolPrefix(otherDefinition, prefix);
|
|
265
|
+
for (const otherTool of otherEntry.tools ?? []) {
|
|
266
|
+
if (!isUiToolVisibleToModel(otherTool.uiVisibility)) continue;
|
|
267
|
+
for (const candidate of getToolNameCandidates(otherTool.name, otherServerName, otherPrefix, false)) candidates.add(candidate);
|
|
268
|
+
}
|
|
269
|
+
if (otherDefinition.exposeResources !== false) {
|
|
270
|
+
for (const resource of otherEntry.resources ?? []) {
|
|
271
|
+
const baseName = `read_${resourceNameToToolName(resource.name)}`;
|
|
272
|
+
for (const candidate of getToolNameCandidates(baseName, otherServerName, otherPrefix, false)) candidates.add(candidate);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
for (const candidate of getToolNameCandidates(toolName, serverName, effectivePrefix, false)) candidates.delete(candidate);
|
|
277
|
+
return candidates;
|
|
278
|
+
};
|
|
235
279
|
const toolCount = (entry?.tools ?? []).filter(
|
|
236
|
-
(tool) =>
|
|
280
|
+
(tool) => isUiToolVisibleToModel(tool.uiVisibility)
|
|
281
|
+
&& isToolAllowed(tool.name, serverName, effectivePrefix, definition.includeTools, definition.excludeTools, getOtherCurrentCandidates(tool.name)),
|
|
237
282
|
).length;
|
|
238
283
|
const resourceCount = definition?.exposeResources !== false
|
|
239
284
|
? (entry?.resources ?? []).filter((resource) => {
|
|
240
285
|
const baseName = `read_${resourceNameToToolName(resource.name)}`;
|
|
241
|
-
return isToolAllowed(baseName, serverName, effectivePrefix, definition.includeTools, definition.excludeTools);
|
|
286
|
+
return isToolAllowed(baseName, serverName, effectivePrefix, definition.includeTools, definition.excludeTools, getOtherCurrentCandidates(baseName));
|
|
242
287
|
}).length
|
|
243
288
|
: 0;
|
|
244
289
|
const totalItems = toolCount + resourceCount;
|
|
@@ -264,7 +309,9 @@ export function buildProxyDescription(
|
|
|
264
309
|
const instructionSummaries: string[] = [];
|
|
265
310
|
for (const serverName of Object.keys(config.mcpServers)) {
|
|
266
311
|
if (isServerDisabled(config.mcpServers[serverName])) continue;
|
|
267
|
-
const
|
|
312
|
+
const definition = config.mcpServers[serverName];
|
|
313
|
+
const entry = definition && cache?.servers?.[serverName];
|
|
314
|
+
const instructions = entry && definition && isServerCacheValid(entry, definition) ? entry.instructions : undefined;
|
|
268
315
|
if (!instructions) continue;
|
|
269
316
|
const snippet = truncateAtWord(instructions.replace(/\s+/g, " ").trim(), INSTRUCTIONS_SNIPPET_LENGTH);
|
|
270
317
|
instructionSummaries.push(` ${serverName}: ${snippet}`);
|
|
@@ -459,11 +459,3 @@ function escapeHtml(value: string): string {
|
|
|
459
459
|
.replace(/"/g, """)
|
|
460
460
|
.replace(/'/g, "'");
|
|
461
461
|
}
|
|
462
|
-
|
|
463
|
-
function escapeHtmlAttribute(value: string): string {
|
|
464
|
-
return value
|
|
465
|
-
.replace(/&/g, "&")
|
|
466
|
-
.replace(/"/g, """)
|
|
467
|
-
.replace(/</g, "<")
|
|
468
|
-
.replace(/>/g, ">");
|
|
469
|
-
}
|
|
@@ -14,7 +14,7 @@ import { logger } from "./logger.ts";
|
|
|
14
14
|
import { executeAuthComplete, executeAuthStart, executeCall, executeConnect, executeDescribe, executeInstructions, executeList, executeSearch, executeStatus, executeUiMessages } from "./proxy-modes.ts";
|
|
15
15
|
import { formatTerminalError, getConfigPathFromArgv, normalizeDirectToolInputSchema, truncateAtWord } from "./utils.ts";
|
|
16
16
|
import { createOAuthRuntime, shutdownOAuth } from "./mcp-auth-flow.ts";
|
|
17
|
-
import { createMcpDirectToolCallRenderer,
|
|
17
|
+
import { createMcpDirectToolCallRenderer, createMcpProxyToolCallRenderer, createMcpToolResultRenderer, resolveMcpToolRenderOptions } from "./tool-result-renderer.ts";
|
|
18
18
|
import { toolErrorOverride } from "./error-signal.ts";
|
|
19
19
|
import { createMcpRuntimeOwner, createOwnedUi, isAbortError, type McpRuntimeOwner } from "./runtime-owner.ts";
|
|
20
20
|
import { publishMcpStatusShutdown } from "./mcp-status.ts";
|
|
@@ -124,6 +124,9 @@ function installMcpAdapter(pi: ExtensionAPI, options: McpAdapterOptions) {
|
|
|
124
124
|
const envDirectToolOverride = envRaw?.split(",").map(s => s.trim()).filter(Boolean);
|
|
125
125
|
const registeredDirectTools = new Map<string, string>();
|
|
126
126
|
const fallbackDeactivatedTools = new Set<string>();
|
|
127
|
+
const toolRenderOptions = resolveMcpToolRenderOptions(earlyConfig.settings);
|
|
128
|
+
const toolRenderShell = toolRenderOptions.resultRendering === "compact" ? "self" : "default";
|
|
129
|
+
const renderMcpToolResult = createMcpToolResultRenderer(toolRenderOptions);
|
|
127
130
|
let proxyToolRegistered = false;
|
|
128
131
|
let proxyToolDescription: string | null = null;
|
|
129
132
|
let directToolsFrozen = false;
|
|
@@ -158,7 +161,8 @@ function installMcpAdapter(pi: ExtensionAPI, options: McpAdapterOptions) {
|
|
|
158
161
|
promptSnippet: truncateAtWord(spec.description, 100) || `MCP tool from ${spec.serverName}`,
|
|
159
162
|
parameters: toToolParameters(normalizeDirectToolInputSchema(spec.inputSchema)),
|
|
160
163
|
execute: createDirectToolExecutor(() => state, () => initPromise, spec),
|
|
161
|
-
|
|
164
|
+
renderShell: toolRenderShell,
|
|
165
|
+
renderCall: createMcpDirectToolCallRenderer(spec.prefixedName, toolRenderOptions),
|
|
162
166
|
renderResult: renderMcpToolResult,
|
|
163
167
|
});
|
|
164
168
|
}
|
|
@@ -695,7 +699,8 @@ function installMcpAdapter(pi: ExtensionAPI, options: McpAdapterOptions) {
|
|
|
695
699
|
label: "MCP",
|
|
696
700
|
description,
|
|
697
701
|
promptSnippet: "MCP gateway — status, search, describe, auth, and single MCP tool calls",
|
|
698
|
-
|
|
702
|
+
renderShell: toolRenderShell,
|
|
703
|
+
renderCall: createMcpProxyToolCallRenderer(toolRenderOptions),
|
|
699
704
|
parameters: Type.Object({
|
|
700
705
|
tool: Type.Optional(Type.String({ description: "Tool name to call (e.g., 'xcodebuild_list_sims')" })),
|
|
701
706
|
args: Type.Optional(Type.Union([
|