@herbertgao/pi-extensions 2026.8.5 → 2026.8.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +2 -2
- package/node_modules/@herbertgao/pi-cc-extensions/README.md +2 -2
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/config.ts +19 -7
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +30 -9
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/compact-thinking.ts +272 -22
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/context.ts +74 -5
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/compact-mode.ts +94 -77
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/markdown-enhance.ts +48 -6
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/message-display.ts +1 -1
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/hover.ts +14 -0
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/interaction.ts +55 -17
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/layout.ts +41 -2
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-renderer.ts +75 -6
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/types.ts +7 -3
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/grouping.ts +64 -1
- package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
- package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +16 -0
- package/node_modules/@herbertgao/pi-subagents/README.md +30 -22
- package/node_modules/@herbertgao/pi-subagents/examples/agent-tool-description.md +5 -5
- package/node_modules/@herbertgao/pi-subagents/package.json +7 -7
- package/node_modules/@herbertgao/pi-subagents/src/agent-file-toggle.ts +7 -1
- package/node_modules/@herbertgao/pi-subagents/src/agent-manager.ts +48 -19
- package/node_modules/@herbertgao/pi-subagents/src/agent-runner.ts +22 -15
- package/node_modules/@herbertgao/pi-subagents/src/custom-agents.ts +26 -2
- package/node_modules/@herbertgao/pi-subagents/src/index.ts +219 -40
- package/node_modules/@herbertgao/pi-subagents/src/invocation-config.ts +101 -3
- package/node_modules/@herbertgao/pi-subagents/src/nested-tools.ts +18 -4
- package/node_modules/@herbertgao/pi-subagents/src/settings.ts +99 -0
- package/node_modules/@herbertgao/pi-subagents/src/types.ts +22 -3
- package/node_modules/@herbertgao/pi-subagents/src/ui/agent-widget.ts +51 -3
- package/node_modules/@herbertgao/pi-subagents/src/ui/conversation-viewer.ts +20 -2
- package/node_modules/@herbertgao/pi-subagents/src/ui/fleet-list.ts +34 -10
- package/node_modules/@herbertgao/pi-subagents/src/usage.ts +129 -1
- package/node_modules/@herbertgao/pi-subagents/src/worktree.ts +29 -5
- package/node_modules/@juicesharp/rpiv-ask-user-question/README.md +3 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/ask-user-question.ts +46 -10
- package/node_modules/@juicesharp/rpiv-ask-user-question/config.ts +25 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/docs/configuration.md +13 -4
- package/node_modules/@juicesharp/rpiv-ask-user-question/docs/hosts.md +8 -1
- package/node_modules/@juicesharp/rpiv-ask-user-question/docs/localization.md +3 -1
- package/node_modules/@juicesharp/rpiv-ask-user-question/locales/en.json +2 -2
- package/node_modules/@juicesharp/rpiv-ask-user-question/locales/zh.json +2 -2
- package/node_modules/@juicesharp/rpiv-ask-user-question/package.json +3 -2
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/build-questionnaire.ts +10 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/key-router.ts +3 -1
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/questionnaire-session.ts +30 -7
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/state.ts +14 -6
- package/node_modules/@juicesharp/rpiv-ask-user-question/view/dialog-builder.ts +30 -4
- package/node_modules/@juicesharp/rpiv-ask-user-question/view/tab-content-strategy.ts +26 -5
- package/node_modules/@narumitw/pi-btw/README.md +119 -103
- package/node_modules/@narumitw/pi-btw/dist/index.ts +2898 -0
- package/node_modules/@narumitw/pi-btw/dist/index.ts.map +7 -0
- package/node_modules/@narumitw/pi-btw/package.json +13 -9
- package/node_modules/@narumitw/pi-btw/src/btw.ts +40 -42
- package/node_modules/@narumitw/pi-btw/src/fullscreen-ui.ts +55 -10
- package/node_modules/@narumitw/pi-btw/src/main-tree-picker.ts +390 -0
- package/node_modules/@narumitw/pi-btw/src/menu.ts +78 -15
- package/node_modules/@narumitw/pi-btw/src/settings.ts +22 -2
- package/node_modules/@narumitw/pi-btw/src/transcript-pager.ts +136 -45
- package/node_modules/pi-lens/CHANGELOG.md +1004 -0
- package/node_modules/pi-lens/README.md +11 -3
- package/node_modules/pi-lens/config/ruff/core.toml +42 -0
- package/node_modules/pi-lens/dist/clients/actionable-warnings.js +130 -27
- package/node_modules/pi-lens/dist/clients/advisory-provenance.js +427 -0
- package/node_modules/pi-lens/dist/clients/agent-nudge.js +79 -16
- package/node_modules/pi-lens/dist/clients/ast-grep-client.js +9 -3
- package/node_modules/pi-lens/dist/clients/atomic-write.js +9 -3
- package/node_modules/pi-lens/dist/clients/bash-file-access.js +285 -8
- package/node_modules/pi-lens/dist/clients/biome-client.js +176 -37
- package/node_modules/pi-lens/dist/clients/blocker-freshness.js +428 -0
- package/node_modules/pi-lens/dist/clients/blocker-past-eof.js +119 -0
- package/node_modules/pi-lens/dist/clients/bootstrap.js +12 -1
- package/node_modules/pi-lens/dist/clients/bounded-pid-file-lock.js +12 -3
- package/node_modules/pi-lens/dist/clients/bounded-telemetry.js +192 -0
- package/node_modules/pi-lens/dist/clients/bus-events-logger.js +62 -6
- package/node_modules/pi-lens/dist/clients/bus-publish.js +11 -3
- package/node_modules/pi-lens/dist/clients/cascade-budget.js +196 -0
- package/node_modules/pi-lens/dist/clients/cascade-format.js +76 -2
- package/node_modules/pi-lens/dist/clients/cascade-types.js +9 -1
- package/node_modules/pi-lens/dist/clients/child-unref.js +54 -6
- package/node_modules/pi-lens/dist/clients/code-quality-warnings.js +76 -24
- package/node_modules/pi-lens/dist/clients/console-guard-install.js +16 -4
- package/node_modules/pi-lens/dist/clients/dead-code-client.js +249 -52
- package/node_modules/pi-lens/dist/clients/deadline-utils.js +8 -1
- package/node_modules/pi-lens/dist/clients/debug-handles.js +5 -0
- package/node_modules/pi-lens/dist/clients/degradation-ledger.js +62 -13
- package/node_modules/pi-lens/dist/clients/dependency-checker.js +43 -9
- package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +153 -37
- package/node_modules/pi-lens/dist/clients/diagnostic-line-freshness.js +298 -0
- package/node_modules/pi-lens/dist/clients/diagnostics-publish.js +10 -3
- package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +165 -11
- package/node_modules/pi-lens/dist/clients/dispatch/integration.js +325 -72
- package/node_modules/pi-lens/dist/clients/dispatch/lazy.js +7 -4
- package/node_modules/pi-lens/dist/clients/dispatch/plan.js +5 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ast-grep-napi.js +234 -18
- package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +187 -19
- package/node_modules/pi-lens/dist/clients/dispatch/runners/cpp-check.js +6 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/credo.js +11 -9
- package/node_modules/pi-lens/dist/clients/dispatch/runners/cue-vet.js +398 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/elixir-check.js +11 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/eslint.js +12 -7
- package/node_modules/pi-lens/dist/clients/dispatch/runners/go-vet.js +18 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-render.js +895 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/index.js +4 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/javac.js +16 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +81 -41
- package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +16 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/mypy.js +23 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/psscriptanalyzer.js +331 -55
- package/node_modules/pi-lens/dist/clients/dispatch/runners/pyright.js +38 -5
- package/node_modules/pi-lens/dist/clients/dispatch/runners/rust-clippy.js +97 -19
- package/node_modules/pi-lens/dist/clients/dispatch/runners/spellcheck.js +14 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/sqlfluff.js +20 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/stylelint.js +22 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/swiftlint.js +10 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/taplo.js +18 -6
- package/node_modules/pi-lens/dist/clients/dispatch/runners/trivy-config.js +73 -12
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/availability-policy.js +488 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/candidate-probe.js +84 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/lazy-installer.js +260 -27
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +943 -93
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/spawn-outcome.js +86 -11
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/tool-failure.js +72 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/toolchain-availability.js +106 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/vale.js +9 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/yamllint.js +18 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/zig-check.js +4 -2
- package/node_modules/pi-lens/dist/clients/disposition-publish.js +10 -3
- package/node_modules/pi-lens/dist/clients/eval-timestamp.js +17 -0
- package/node_modules/pi-lens/dist/clients/event-loop-monitor.js +28 -5
- package/node_modules/pi-lens/dist/clients/extension-log.js +317 -3
- package/node_modules/pi-lens/dist/clients/file-kinds.js +8 -2
- package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +294 -0
- package/node_modules/pi-lens/dist/clients/finding-identity.js +88 -0
- package/node_modules/pi-lens/dist/clients/fix-worklog.js +5 -1
- package/node_modules/pi-lens/dist/clients/format-events-publish.js +39 -8
- package/node_modules/pi-lens/dist/clients/formatters-lazy.js +3 -2
- package/node_modules/pi-lens/dist/clients/formatters.js +500 -115
- package/node_modules/pi-lens/dist/clients/generation-guard.js +216 -0
- package/node_modules/pi-lens/dist/clients/git-guard.js +49 -21
- package/node_modules/pi-lens/dist/clients/gitleaks-client.js +181 -8
- package/node_modules/pi-lens/dist/clients/go-client.js +21 -39
- package/node_modules/pi-lens/dist/clients/govulncheck-client.js +219 -10
- package/node_modules/pi-lens/dist/clients/grammar-source.js +333 -10
- package/node_modules/pi-lens/dist/clients/host-ports.js +9 -1
- package/node_modules/pi-lens/dist/clients/installer/index.js +1119 -101
- package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh-session.js +58 -0
- package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh.js +715 -0
- package/node_modules/pi-lens/dist/clients/instance-reaper.js +643 -97
- package/node_modules/pi-lens/dist/clients/instance-registry.js +87 -17
- package/node_modules/pi-lens/dist/clients/jscpd-client.js +86 -15
- package/node_modules/pi-lens/dist/clients/knip-client.js +361 -24
- package/node_modules/pi-lens/dist/clients/language-policy.js +8 -2
- package/node_modules/pi-lens/dist/clients/language-profile.js +2 -0
- package/node_modules/pi-lens/dist/clients/latency-logger.js +487 -9
- package/node_modules/pi-lens/dist/clients/lazy-import.js +21 -0
- package/node_modules/pi-lens/dist/clients/ledger-bounds.js +21 -0
- package/node_modules/pi-lens/dist/clients/lens-events.js +56 -25
- package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +16 -0
- package/node_modules/pi-lens/dist/clients/live-bus-emitter.js +45 -2
- package/node_modules/pi-lens/dist/clients/lsp/aggregation.js +30 -4
- package/node_modules/pi-lens/dist/clients/lsp/cascade-tier.js +160 -20
- package/node_modules/pi-lens/dist/clients/lsp/client.js +1666 -148
- package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +111 -0
- package/node_modules/pi-lens/dist/clients/lsp/document-drift.js +389 -0
- package/node_modules/pi-lens/dist/clients/lsp/index.js +2496 -171
- package/node_modules/pi-lens/dist/clients/lsp/inferred-project.js +215 -0
- package/node_modules/pi-lens/dist/clients/lsp/jvm-runtime.js +146 -14
- package/node_modules/pi-lens/dist/clients/lsp/language.js +48 -4
- package/node_modules/pi-lens/dist/clients/lsp/server.js +517 -69
- package/node_modules/pi-lens/dist/clients/lsp/spawn-history.js +22 -0
- package/node_modules/pi-lens/dist/clients/lsp/sync-kind.js +43 -0
- package/node_modules/pi-lens/dist/clients/lsp/tsserver-sync.js +172 -0
- package/node_modules/pi-lens/dist/clients/lsp/wait-policy/classification.js +21 -5
- package/node_modules/pi-lens/dist/clients/lsp/wait-policy/strategies.js +61 -3
- package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +422 -28
- package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-session.js +30 -0
- package/node_modules/pi-lens/dist/clients/lsp/workspace-sweep-hold.js +175 -0
- package/node_modules/pi-lens/dist/clients/lsp-lazy.js +3 -2
- package/node_modules/pi-lens/dist/clients/mcp/analyze.js +4 -0
- package/node_modules/pi-lens/dist/clients/mcp/session.js +39 -18
- package/node_modules/pi-lens/dist/clients/model-provider.js +53 -0
- package/node_modules/pi-lens/dist/clients/module-report.js +8 -0
- package/node_modules/pi-lens/dist/clients/opengrep-client.js +15 -1
- package/node_modules/pi-lens/dist/clients/package-manager.js +170 -14
- package/node_modules/pi-lens/dist/clients/path-attribution-telemetry.js +27 -0
- package/node_modules/pi-lens/dist/clients/path-utils.js +160 -0
- package/node_modules/pi-lens/dist/clients/pipeline.js +178 -30
- package/node_modules/pi-lens/dist/clients/post-autofix-notice.js +37 -0
- package/node_modules/pi-lens/dist/clients/project-diagnostics/cache.js +17 -3
- package/node_modules/pi-lens/dist/clients/project-diagnostics/extractors.js +89 -22
- package/node_modules/pi-lens/dist/clients/project-diagnostics/fresh-fetch.js +85 -15
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/gitleaks.js +15 -3
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/runner-findings.js +23 -2
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/trivy.js +50 -2
- package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +5 -0
- package/node_modules/pi-lens/dist/clients/project-lens-config.js +3 -0
- package/node_modules/pi-lens/dist/clients/project-snapshot.js +299 -0
- package/node_modules/pi-lens/dist/clients/quiet-window-config.js +47 -0
- package/node_modules/pi-lens/dist/clients/quiet-window.js +11 -25
- package/node_modules/pi-lens/dist/clients/read-guard-logger.js +1 -1
- package/node_modules/pi-lens/dist/clients/read-guard.js +184 -10
- package/node_modules/pi-lens/dist/clients/resource-sampler.js +49 -17
- package/node_modules/pi-lens/dist/clients/reverse-deps.js +50 -11
- package/node_modules/pi-lens/dist/clients/review-graph/query.js +76 -4
- package/node_modules/pi-lens/dist/clients/run-duration.js +55 -0
- package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +248 -13
- package/node_modules/pi-lens/dist/clients/runtime-context.js +112 -12
- package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +472 -61
- package/node_modules/pi-lens/dist/clients/runtime-session.js +359 -13
- package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +217 -22
- package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +269 -22
- package/node_modules/pi-lens/dist/clients/runtime-turn.js +948 -87
- package/node_modules/pi-lens/dist/clients/rust-client.js +21 -37
- package/node_modules/pi-lens/dist/clients/safe-spawn.js +220 -7
- package/node_modules/pi-lens/dist/clients/scratch-tree-policy.js +161 -0
- package/node_modules/pi-lens/dist/clients/search-read-registration.js +34 -6
- package/node_modules/pi-lens/dist/clients/security-scan-client.js +224 -8
- package/node_modules/pi-lens/dist/clients/sg-runner.js +249 -37
- package/node_modules/pi-lens/dist/clients/single-flight.js +158 -0
- package/node_modules/pi-lens/dist/clients/smells-rollup.js +18 -11
- package/node_modules/pi-lens/dist/clients/stale-marker.js +17 -0
- package/node_modules/pi-lens/dist/clients/startup-timing.js +26 -2
- package/node_modules/pi-lens/dist/clients/test-runner-client.js +574 -32
- package/node_modules/pi-lens/dist/clients/tool-event.js +56 -5
- package/node_modules/pi-lens/dist/clients/tool-policy.js +127 -20
- package/node_modules/pi-lens/dist/clients/tool-set-policy.js +76 -0
- package/node_modules/pi-lens/dist/clients/tree-sitter-cache.js +75 -1
- package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +769 -64
- package/node_modules/pi-lens/dist/clients/tree-sitter-shared.js +11 -0
- package/node_modules/pi-lens/dist/clients/tree-sitter-symbol-extractor.js +90 -0
- package/node_modules/pi-lens/dist/clients/trivy-client.js +19 -1
- package/node_modules/pi-lens/dist/clients/warm-attach.js +17 -0
- package/node_modules/pi-lens/dist/clients/widget-state.js +336 -36
- package/node_modules/pi-lens/dist/clients/word-index.js +305 -33
- package/node_modules/pi-lens/dist/clients/zizmor-config.js +214 -14
- package/node_modules/pi-lens/dist/index.js +64677 -49484
- package/node_modules/pi-lens/dist/mcp/server.js +8 -2
- package/node_modules/pi-lens/dist/tools/activate-tools.js +17 -5
- package/node_modules/pi-lens/dist/tools/ast-grep-replace.js +9 -4
- package/node_modules/pi-lens/dist/tools/lens-diagnostic-mark.js +5 -2
- package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +469 -56
- package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +190 -46
- package/node_modules/pi-lens/dist/tools/lsp-navigation.js +46 -7
- package/node_modules/pi-lens/dist/tools/symbol-search.js +1 -1
- package/node_modules/pi-lens/docs/agent-guide.md +44 -14
- package/node_modules/pi-lens/docs/ast-grep_rules_catalog.md +518 -501
- package/node_modules/pi-lens/docs/dispositions.md +21 -0
- package/node_modules/pi-lens/docs/features.md +33 -6
- package/node_modules/pi-lens/docs/globalconfig.md +14 -0
- package/node_modules/pi-lens/docs/language-coverage.md +71 -5
- package/node_modules/pi-lens/docs/mcp.md +2 -2
- package/node_modules/pi-lens/docs/servercapabilities.md +4 -1
- package/node_modules/pi-lens/docs/settings.md +25 -1
- package/node_modules/pi-lens/docs/usage.md +24 -5
- package/node_modules/pi-lens/docs/word-index.md +35 -0
- package/node_modules/pi-lens/package.json +10 -6
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/__snapshots__/no-reflect-get-js-snapshot.yml +23 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/__snapshots__/no-reflect-get-snapshot.yml +23 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/__snapshots__/ts-void-zero-snapshot.yml +23 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-bare-object-param-test.yml +16 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-chained-type-assertions-test.yml +22 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-compile-call-test.yml +29 -1
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-conditional-empty-object-spread-js-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-conditional-empty-object-spread-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-dupe-class-members-test.yml +33 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-inner-html-js-test.yml +7 -1
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-inner-html-test.yml +7 -1
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-known-value-widening-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-non-null-assertion-test.yml +216 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-js-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-js-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-return-value-in-generator-test.yml +12 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-runtime-typeof-test.yml +33 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-server-bind-wildcard-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-shape-in-symbol-names-test.yml +13 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-sql-in-code-js-test.yml +5 -1
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-sql-in-code-test.yml +5 -1
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unknown-laundering-test.yml +11 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unknown-parameters-test.yml +12 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unknown-returns-test.yml +16 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unsafe-dictionary-any-test.yml +10 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unsafe-dictionary-unknown-test.yml +8 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/redundant-unsafe-function-test.yml +35 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/require-safety-comment-for-as-unknown-as-test.yml +177 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/ts-void-zero-test.yml +1 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-await-expression-member-js.yml +13 -2
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-await-expression-member.yml +13 -2
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-host-path-in-win32-branch.yml +2 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-object-param.yml +60 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-chained-type-assertions.yml +66 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-compile-call.yml +63 -5
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-conditional-empty-object-spread-js.yml +21 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-conditional-empty-object-spread.yml +29 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-dupe-class-members.yml +52 -8
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-inner-html-js.yml +27 -2
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-inner-html.yml +27 -2
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-known-value-widening.yml +71 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-non-null-assertion.yml +316 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-raw-json-store-write.yml +7 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply-js.yml +29 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply.yml +30 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get-js.yml +41 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get.yml +42 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-return-value-in-generator.yml +22 -5
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-runtime-typeof.yml +121 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-server-bind-wildcard.yml +23 -7
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-shape-in-symbol-names.yml +68 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-sql-in-code-js.yml +41 -2
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-sql-in-code.yml +41 -2
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-laundering.yml +32 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-parameters.yml +67 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-returns.yml +106 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unsafe-dictionary-any.yml +50 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unsafe-dictionary-unknown.yml +56 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-win32-isabsolute-for-qualification.yml +2 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/redundant-unsafe-function.yml +32 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/require-safety-comment-for-as-unknown-as.yml +184 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/ts-void-zero.yml +5 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/self-scan-baseline.json +5 -0
- package/node_modules/pi-lens/scripts/analyze-pi-lens-logs.mjs +132 -1
- package/node_modules/pi-lens/scripts/download-grammars.js +25 -0
- package/node_modules/pi-lens/scripts/grammars.lock.json +9 -0
- package/node_modules/pi-lens/skills/pi-lens-ast-grep/SKILL.md +12 -11
- package/node_modules/pi-lens/skills/pi-lens-lsp-navigation/SKILL.md +22 -22
- package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/SKILL.md +87 -116
- package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/reference.md +170 -0
- package/node_modules/pi-lens/skills/pi-lens-write-tree-sitter-rule/SKILL.md +3 -1
- package/node_modules/pi-lens/vendor/grammars/tree-sitter-cue.wasm +0 -0
- package/node_modules/pi-mcp-adapter/CHANGELOG.md +49 -0
- package/node_modules/pi-mcp-adapter/README.md +51 -6
- package/node_modules/pi-mcp-adapter/agent-dir.ts +12 -4
- package/node_modules/pi-mcp-adapter/cli.js +188 -5
- package/node_modules/pi-mcp-adapter/commands.ts +128 -22
- package/node_modules/pi-mcp-adapter/config.ts +28 -10
- package/node_modules/pi-mcp-adapter/direct-tools.ts +23 -19
- package/node_modules/pi-mcp-adapter/index.ts +219 -32
- package/node_modules/pi-mcp-adapter/init.ts +36 -4
- package/node_modules/pi-mcp-adapter/lifecycle.ts +315 -24
- package/node_modules/pi-mcp-adapter/mcp-auth-flow.ts +39 -6
- package/node_modules/pi-mcp-adapter/mcp-bearer-store.ts +387 -0
- package/node_modules/pi-mcp-adapter/mcp-callback-server.ts +27 -3
- package/node_modules/pi-mcp-adapter/mcp-code.ts +4 -0
- package/node_modules/pi-mcp-adapter/mcp-panel.ts +42 -13
- package/node_modules/pi-mcp-adapter/mcp-setup-panel.ts +2 -1
- package/node_modules/pi-mcp-adapter/metadata-cache.ts +46 -25
- package/node_modules/pi-mcp-adapter/package-mcp-loader.ts +168 -0
- package/node_modules/pi-mcp-adapter/package.json +4 -1
- package/node_modules/pi-mcp-adapter/proxy-modes.ts +5 -4
- package/node_modules/pi-mcp-adapter/request-headers-command.ts +330 -0
- package/node_modules/pi-mcp-adapter/search-ranking.ts +92 -22
- package/node_modules/pi-mcp-adapter/server-manager.ts +145 -2
- package/node_modules/pi-mcp-adapter/session-recovery.ts +7 -0
- package/node_modules/pi-mcp-adapter/tool-approval.ts +15 -2
- package/node_modules/pi-mcp-adapter/tool-metadata.ts +38 -18
- package/node_modules/pi-mcp-adapter/tool-result-renderer.ts +44 -4
- package/node_modules/pi-mcp-adapter/types.ts +95 -10
- package/node_modules/pi-mcp-adapter/ui-server.ts +18 -16
- package/node_modules/pi-mcp-adapter/utils.ts +70 -0
- package/node_modules/pi-web-access/CHANGELOG.md +37 -0
- package/node_modules/pi-web-access/README.md +38 -14
- package/node_modules/pi-web-access/anysearch.ts +4 -2
- package/node_modules/pi-web-access/auth-fetch.ts +148 -0
- package/node_modules/pi-web-access/brave.ts +16 -4
- package/node_modules/pi-web-access/chrome-cookies.ts +110 -23
- package/node_modules/pi-web-access/curator-page.ts +8 -3
- package/node_modules/pi-web-access/curator-server.ts +5 -1
- package/node_modules/pi-web-access/exa.ts +18 -7
- package/node_modules/pi-web-access/extract.ts +134 -37
- package/node_modules/pi-web-access/fetch-params.ts +17 -3
- package/node_modules/pi-web-access/firecrawl.ts +172 -12
- package/node_modules/pi-web-access/gemini-search.ts +33 -7
- package/node_modules/pi-web-access/index.ts +160 -104
- package/node_modules/pi-web-access/package.json +2 -2
- package/node_modules/pi-web-access/page-query.ts +4 -2
- package/node_modules/pi-web-access/parallel-mcp.ts +249 -0
- package/node_modules/pi-web-access/parallel.ts +2 -2
- package/node_modules/pi-web-access/query-rewrite.ts +51 -0
- package/node_modules/pi-web-access/serper.ts +211 -0
- package/node_modules/pi-web-access/summary-model-scope.ts +12 -4
- package/node_modules/pi-web-access/summary-review.ts +51 -23
- package/node_modules/pi-web-access/tavily.ts +16 -4
- package/node_modules/pi-web-access/utils.ts +87 -0
- package/node_modules/pi-web-access/valyu.ts +199 -0
- package/node_modules/pi-web-access/youtube-extract.ts +2 -2
- package/package.json +13 -13
|
@@ -4,8 +4,9 @@ import { homedir } from "node:os";
|
|
|
4
4
|
import { dirname, join, resolve } from "node:path";
|
|
5
5
|
import { parse as parseToml } from "smol-toml";
|
|
6
6
|
import stripJsonComments from "strip-json-comments";
|
|
7
|
-
import { getAgentPath } from "./agent-dir.ts";
|
|
7
|
+
import { getAgentPath, getConfigDirName } from "./agent-dir.ts";
|
|
8
8
|
import { getAgentPluginSummaries, loadAgentPluginConfigs, type AgentPluginSummary } from "./agent-plugin-loader.ts";
|
|
9
|
+
import { loadPackageMcpConfigs } from "./package-mcp-loader.ts";
|
|
9
10
|
import { isServerDisabled, type HostConfigDiscovery, type McpConfig, type ServerEntry, type McpSettings, type ImportKind, type ServerProvenance } from "./types.ts";
|
|
10
11
|
import { toStringRecord } from "./utils.ts";
|
|
11
12
|
|
|
@@ -15,7 +16,7 @@ const AGENTS_GLOBAL_CONFIG_PATHS = [
|
|
|
15
16
|
join(homedir(), ".agents", "mcp", "mcp.json"),
|
|
16
17
|
] as const;
|
|
17
18
|
const PROJECT_CONFIG_NAME = ".mcp.json";
|
|
18
|
-
const PROJECT_PI_CONFIG_NAME = "
|
|
19
|
+
const PROJECT_PI_CONFIG_NAME = "mcp.json";
|
|
19
20
|
const REPOPROMPT_BINARY_CANDIDATES = [
|
|
20
21
|
join(homedir(), "RepoPrompt", "repoprompt_cli"),
|
|
21
22
|
"/Applications/Repo Prompt.app/Contents/MacOS/repoprompt-mcp",
|
|
@@ -177,7 +178,7 @@ export function getProjectConfigPath(cwd = process.cwd()): string {
|
|
|
177
178
|
}
|
|
178
179
|
|
|
179
180
|
export function getProjectPiConfigPath(cwd = process.cwd()): string {
|
|
180
|
-
return resolve(cwd, PROJECT_PI_CONFIG_NAME);
|
|
181
|
+
return resolve(cwd, getConfigDirName(), PROJECT_PI_CONFIG_NAME);
|
|
181
182
|
}
|
|
182
183
|
|
|
183
184
|
export function getConfigDiscoveryPaths(overridePath?: string, cwd = process.cwd()): ConfigDiscoveryPath[] {
|
|
@@ -306,8 +307,12 @@ export function loadMcpConfig(overridePath?: string, cwd = process.cwd()): McpCo
|
|
|
306
307
|
config = mergeConfigs(config, expandImports(loaded, cwd));
|
|
307
308
|
}
|
|
308
309
|
|
|
310
|
+
const packageConfig = loadPackageMcpConfigs(cwd);
|
|
309
311
|
const pluginConfig = loadAgentPluginConfigs(config.settings?.agentPluginPaths, cwd);
|
|
310
|
-
|
|
312
|
+
const packageServers = Object.fromEntries(
|
|
313
|
+
Object.entries(packageConfig.mcpServers).filter(([name]) => !Object.hasOwn(pluginConfig.mcpServers, name)),
|
|
314
|
+
);
|
|
315
|
+
return mergeConfigs({ mcpServers: packageServers }, mergeConfigs(pluginConfig, config));
|
|
311
316
|
}
|
|
312
317
|
|
|
313
318
|
function getMergedSettings(overridePath?: string, cwd = process.cwd()): McpSettings | undefined {
|
|
@@ -471,7 +476,7 @@ function mergeConfigs(base: McpConfig, next: McpConfig): McpConfig {
|
|
|
471
476
|
// different url, these MUST NOT be inherited from the lower-precedence entry —
|
|
472
477
|
// otherwise the original endpoint's credentials would be shipped to the new
|
|
473
478
|
// url. See the SECURITY note in mergeServerMaps.
|
|
474
|
-
const URL_BOUND_AUTH_FIELDS = ["headers", "bearerToken", "bearerTokenEnv"] as const;
|
|
479
|
+
const URL_BOUND_AUTH_FIELDS = ["headers", "bearerToken", "bearerTokenEnv", "bearerTokenStore", "requestHeadersCommand"] as const;
|
|
475
480
|
|
|
476
481
|
function mergeServerMaps(
|
|
477
482
|
base: Record<string, ServerEntry>,
|
|
@@ -491,17 +496,30 @@ function mergeServerMaps(
|
|
|
491
496
|
// applies (it is spread last). Behaviour is unchanged when the url is
|
|
492
497
|
// identical or the override omits `url` (partial overrides still inherit).
|
|
493
498
|
let baseEntry: ServerEntry = existing ?? {};
|
|
494
|
-
if (existing && typeof definition.
|
|
499
|
+
if (existing && typeof definition.command === "string") {
|
|
495
500
|
baseEntry = { ...existing };
|
|
496
501
|
for (const field of [
|
|
497
|
-
"
|
|
498
|
-
"
|
|
502
|
+
"url", "headers", "requestHeadersCommand", "auth", "bearerToken",
|
|
503
|
+
"bearerTokenEnv", "oauth", "httpTransport", "socket",
|
|
499
504
|
] as const) {
|
|
500
505
|
delete baseEntry[field];
|
|
501
506
|
}
|
|
502
|
-
} else if (existing
|
|
507
|
+
} else if (existing && typeof definition.url === "string") {
|
|
503
508
|
baseEntry = { ...existing };
|
|
504
|
-
|
|
509
|
+
for (const field of [
|
|
510
|
+
"command", "args", "env", "cwd", "pluginDataDir", "literalEnv", "socket",
|
|
511
|
+
] as const) {
|
|
512
|
+
delete baseEntry[field];
|
|
513
|
+
}
|
|
514
|
+
} else if (existing && typeof definition.socket === "string") {
|
|
515
|
+
baseEntry = { ...existing };
|
|
516
|
+
for (const field of [
|
|
517
|
+
"command", "args", "env", "cwd", "pluginDataDir", "literalEnv", "url",
|
|
518
|
+
"headers", "requestHeadersCommand", "auth", "bearerToken", "bearerTokenEnv",
|
|
519
|
+
"oauth", "httpTransport",
|
|
520
|
+
] as const) {
|
|
521
|
+
delete baseEntry[field];
|
|
522
|
+
}
|
|
505
523
|
}
|
|
506
524
|
if (existing && typeof definition.url === "string" && definition.url !== existing.url) {
|
|
507
525
|
if (baseEntry === existing) baseEntry = { ...existing };
|
|
@@ -11,11 +11,11 @@ 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, getToolNameCandidates, isServerDisabled, isToolAllowed, resolveToolPrefix } from "./types.ts";
|
|
14
|
+
import { createToolSelectorCandidateIndex, formatToolName, getToolNameCandidates, isServerDisabled, isToolAllowed, resolveToolPrefix } from "./types.ts";
|
|
15
15
|
import { isUiToolVisibleToModel } from "./ui-tool-visibility.ts";
|
|
16
16
|
import { resourceNameToToolName } from "./resource-tools.ts";
|
|
17
17
|
import { authenticate, supportsOAuth } from "./mcp-auth-flow.ts";
|
|
18
|
-
import { formatAuthRequiredMessage, resolveServerUrl, truncateAtWord } from "./utils.ts";
|
|
18
|
+
import { formatAuthRequiredMessage, normalizeToolArguments, resolveServerUrl, truncateAtWord } from "./utils.ts";
|
|
19
19
|
import { SessionRecoveryAuthRequiredError, withSessionRecovery } from "./session-recovery.ts";
|
|
20
20
|
import { combineAbortSignals, isAbortError } from "./runtime-owner.ts";
|
|
21
21
|
import { ensureToolCallApproved } from "./tool-approval.ts";
|
|
@@ -150,7 +150,10 @@ export function resolveDirectTools(
|
|
|
150
150
|
if (!toolFilter) continue;
|
|
151
151
|
|
|
152
152
|
const effectivePrefix = resolveToolPrefix(definition, prefix);
|
|
153
|
-
const
|
|
153
|
+
const hasToolFilters =
|
|
154
|
+
(Array.isArray(definition.includeTools) && definition.includeTools.length > 0) ||
|
|
155
|
+
(Array.isArray(definition.excludeTools) && definition.excludeTools.length > 0);
|
|
156
|
+
const selectorCandidateIndex = hasToolFilters ? (() => {
|
|
154
157
|
const candidates = new Set<string>();
|
|
155
158
|
for (const [otherServerName, otherDefinition] of Object.entries(config.mcpServers)) {
|
|
156
159
|
const otherCache = cache.servers[otherServerName];
|
|
@@ -167,14 +170,13 @@ export function resolveDirectTools(
|
|
|
167
170
|
}
|
|
168
171
|
}
|
|
169
172
|
}
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
};
|
|
173
|
+
return createToolSelectorCandidateIndex(candidates);
|
|
174
|
+
})() : undefined;
|
|
173
175
|
|
|
174
176
|
for (const tool of serverCache.tools ?? []) {
|
|
175
177
|
if (!isUiToolVisibleToModel(tool.uiVisibility)) continue;
|
|
176
178
|
if (toolFilter !== true && !toolFilter.includes(tool.name)) continue;
|
|
177
|
-
if (!isToolAllowed(tool.name, serverName, effectivePrefix, definition.includeTools, definition.excludeTools,
|
|
179
|
+
if (!isToolAllowed(tool.name, serverName, effectivePrefix, definition.includeTools, definition.excludeTools, selectorCandidateIndex)) continue;
|
|
178
180
|
const prefixedName = formatToolName(tool.name, serverName, effectivePrefix);
|
|
179
181
|
if (BUILTIN_NAMES.has(prefixedName)) {
|
|
180
182
|
console.warn(`MCP: skipping direct tool "${prefixedName}" (collides with builtin)`);
|
|
@@ -200,7 +202,7 @@ export function resolveDirectTools(
|
|
|
200
202
|
for (const resource of serverCache.resources ?? []) {
|
|
201
203
|
const baseName = `read_${resourceNameToToolName(resource.name)}`;
|
|
202
204
|
if (toolFilter !== true && !toolFilter.includes(baseName)) continue;
|
|
203
|
-
if (!isToolAllowed(baseName, serverName, effectivePrefix, definition.includeTools, definition.excludeTools,
|
|
205
|
+
if (!isToolAllowed(baseName, serverName, effectivePrefix, definition.includeTools, definition.excludeTools, selectorCandidateIndex)) continue;
|
|
204
206
|
const prefixedName = formatToolName(baseName, serverName, effectivePrefix);
|
|
205
207
|
if (BUILTIN_NAMES.has(prefixedName)) {
|
|
206
208
|
console.warn(`MCP: skipping direct resource tool "${prefixedName}" (collides with builtin)`);
|
|
@@ -222,7 +224,7 @@ export function resolveDirectTools(
|
|
|
222
224
|
}
|
|
223
225
|
}
|
|
224
226
|
|
|
225
|
-
if (specs.length >= DIRECT_TOOLS_ADVISORY_THRESHOLD) {
|
|
227
|
+
if (config.settings?.warnOnLargeDirectTools !== false && specs.length >= DIRECT_TOOLS_ADVISORY_THRESHOLD) {
|
|
226
228
|
console.warn(`MCP: ${specs.length} direct tools resolved. Each direct tool adds prompt context; README guidance recommends targeted sets of 5-20 tools and using the proxy or an explicit string[] when 75+ direct tools would be registered.`);
|
|
227
229
|
}
|
|
228
230
|
|
|
@@ -255,8 +257,10 @@ export function buildProxyDescription(
|
|
|
255
257
|
const cachedEntry = cache?.servers?.[serverName];
|
|
256
258
|
const entry = cachedEntry && isServerCacheValid(cachedEntry, definition) ? cachedEntry : undefined;
|
|
257
259
|
const effectivePrefix = resolveToolPrefix(definition, prefix);
|
|
258
|
-
const
|
|
259
|
-
|
|
260
|
+
const hasToolFilters =
|
|
261
|
+
(Array.isArray(definition.includeTools) && definition.includeTools.length > 0) ||
|
|
262
|
+
(Array.isArray(definition.excludeTools) && definition.excludeTools.length > 0);
|
|
263
|
+
const selectorCandidateIndex = hasToolFilters && cache ? (() => {
|
|
260
264
|
const candidates = new Set<string>();
|
|
261
265
|
for (const [otherServerName, otherDefinition] of Object.entries(config.mcpServers)) {
|
|
262
266
|
const otherEntry = cache.servers[otherServerName];
|
|
@@ -273,17 +277,16 @@ export function buildProxyDescription(
|
|
|
273
277
|
}
|
|
274
278
|
}
|
|
275
279
|
}
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
};
|
|
280
|
+
return createToolSelectorCandidateIndex(candidates);
|
|
281
|
+
})() : undefined;
|
|
279
282
|
const toolCount = (entry?.tools ?? []).filter(
|
|
280
283
|
(tool) => isUiToolVisibleToModel(tool.uiVisibility)
|
|
281
|
-
&& isToolAllowed(tool.name, serverName, effectivePrefix, definition.includeTools, definition.excludeTools,
|
|
284
|
+
&& isToolAllowed(tool.name, serverName, effectivePrefix, definition.includeTools, definition.excludeTools, selectorCandidateIndex),
|
|
282
285
|
).length;
|
|
283
286
|
const resourceCount = definition?.exposeResources !== false
|
|
284
287
|
? (entry?.resources ?? []).filter((resource) => {
|
|
285
288
|
const baseName = `read_${resourceNameToToolName(resource.name)}`;
|
|
286
|
-
return isToolAllowed(baseName, serverName, effectivePrefix, definition.includeTools, definition.excludeTools,
|
|
289
|
+
return isToolAllowed(baseName, serverName, effectivePrefix, definition.includeTools, definition.excludeTools, selectorCandidateIndex);
|
|
287
290
|
}).length
|
|
288
291
|
: 0;
|
|
289
292
|
const totalItems = toolCount + resourceCount;
|
|
@@ -426,6 +429,7 @@ export function createDirectToolExecutor(
|
|
|
426
429
|
};
|
|
427
430
|
}
|
|
428
431
|
|
|
432
|
+
const normalizedParams = spec.resourceUri ? params : normalizeToolArguments(params);
|
|
429
433
|
const approval = await ensureToolCallApproved(state, spec.serverName, {
|
|
430
434
|
name: spec.prefixedName,
|
|
431
435
|
originalName: spec.originalName,
|
|
@@ -434,7 +438,7 @@ export function createDirectToolExecutor(
|
|
|
434
438
|
...(spec.resourceUri !== undefined ? { resourceUri: spec.resourceUri } : {}),
|
|
435
439
|
...(spec.uiResourceUri !== undefined ? { uiResourceUri: spec.uiResourceUri } : {}),
|
|
436
440
|
...(spec.uiStreamMode !== undefined ? { uiStreamMode: spec.uiStreamMode } : {}),
|
|
437
|
-
},
|
|
441
|
+
}, normalizedParams, ownedSignal, spec.resourceUri ? "resource" : "direct");
|
|
438
442
|
if (approval.ok === false) {
|
|
439
443
|
const denied = approval.reason === "denied";
|
|
440
444
|
const message = denied
|
|
@@ -506,7 +510,7 @@ export function createDirectToolExecutor(
|
|
|
506
510
|
? await maybeStartUiSession(state, {
|
|
507
511
|
serverName: spec.serverName,
|
|
508
512
|
toolName: spec.originalName,
|
|
509
|
-
toolArgs:
|
|
513
|
+
toolArgs: normalizedParams,
|
|
510
514
|
uiResourceUri: spec.uiResourceUri!,
|
|
511
515
|
...(spec.uiStreamMode !== undefined ? { streamMode: spec.uiStreamMode } : {}),
|
|
512
516
|
...(signal ? { signal } : {}),
|
|
@@ -524,7 +528,7 @@ export function createDirectToolExecutor(
|
|
|
524
528
|
spec.serverName,
|
|
525
529
|
(conn) => abortable(conn.client.callTool({
|
|
526
530
|
name: spec.originalName,
|
|
527
|
-
arguments:
|
|
531
|
+
arguments: normalizedParams,
|
|
528
532
|
_meta: uiSession?.requestMeta,
|
|
529
533
|
}, requestOptions), ownedSignal),
|
|
530
534
|
);
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import type { AgentToolUpdateCallback, ExtensionAPI, ExtensionContext, ToolInfo } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
import type { McpExtensionState } from "./state.ts";
|
|
3
|
-
import type { DirectToolSpec, McpAdapterOptions, McpConfig, PromptMetadata } from "./types.ts";
|
|
3
|
+
import type { DirectToolSpec, McpAdapterOptions, McpConfig, PromptMetadata, ServerEntry } from "./types.ts";
|
|
4
4
|
import type { McpOAuthRuntime } from "./mcp-auth-flow.ts";
|
|
5
5
|
import { Type } from "typebox";
|
|
6
6
|
import type { TSchema } from "typebox";
|
|
7
|
-
import { showStatus, showTools, showPrompts, reconnectServer, reconnectServers, authenticateServer, logoutServer, openMcpAuthPanel, openMcpPanel, openMcpSetup } from "./commands.ts";
|
|
7
|
+
import { showStatus, showTools, showPrompts, reconnectServer, reconnectServers, authenticateServer, logoutServer, manageBearerToken, openMcpAuthPanel, openMcpPanel, openMcpSetup } from "./commands.ts";
|
|
8
8
|
import { cloneMcpConfig, loadMcpConfig, writeProjectServerDisabledOverride } from "./config.ts";
|
|
9
9
|
import { buildProxyDescription, createDirectToolExecutor, getMissingConfiguredDirectToolServers, resolveDirectTools } from "./direct-tools.ts";
|
|
10
10
|
import { flushMetadataCache, initializeMcp, updateStatusBar } from "./init.ts";
|
|
@@ -22,6 +22,7 @@ import { runMcpScript } from "./mcp-code.ts";
|
|
|
22
22
|
import { cleanupMaterializedBinaryResources } from "./tool-registrar.ts";
|
|
23
23
|
|
|
24
24
|
export type { McpAdapterOptions } from "./types.ts";
|
|
25
|
+
export type { ServerEntry } from "./types.ts";
|
|
25
26
|
export {
|
|
26
27
|
MCP_STATUS_EVENT,
|
|
27
28
|
MCP_STATUS_SNAPSHOT_VERSION,
|
|
@@ -38,6 +39,14 @@ export {
|
|
|
38
39
|
const INIT_WAIT_TIMEOUT_MS = 30_000;
|
|
39
40
|
const INIT_WAIT_TIMED_OUT: unique symbol = Symbol("init-wait-timed-out");
|
|
40
41
|
|
|
42
|
+
export interface McpServerRegistration {
|
|
43
|
+
dispose(): Promise<void>;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Routes runtime registrations to the adapter installed for a specific Pi
|
|
47
|
+
// instance, so a process with several adapters cannot cross-register.
|
|
48
|
+
const runtimeRegistrars = new WeakMap<ExtensionAPI, (name: string, definition: ServerEntry) => McpServerRegistration>();
|
|
49
|
+
|
|
41
50
|
async function awaitWithTimeout<T>(promise: Promise<T>, timeoutMs: number): Promise<T | typeof INIT_WAIT_TIMED_OUT> {
|
|
42
51
|
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
43
52
|
try {
|
|
@@ -130,6 +139,19 @@ function installMcpAdapter(pi: ExtensionAPI, options: McpAdapterOptions) {
|
|
|
130
139
|
let proxyToolRegistered = false;
|
|
131
140
|
let proxyToolDescription: string | null = null;
|
|
132
141
|
let directToolsFrozen = false;
|
|
142
|
+
// Session/runtime scoped server registrations from other extensions. They
|
|
143
|
+
// survive session restarts within this install and die with the process.
|
|
144
|
+
const runtimeServers = new Map<string, ServerEntry>();
|
|
145
|
+
|
|
146
|
+
// Mirrors init's per-server lifecycle registration so runtime servers get
|
|
147
|
+
// idle cleanup and keep-alive health recovery like configured servers.
|
|
148
|
+
function attachRuntimeServerLifecycle(targetState: McpExtensionState, name: string, definition: ServerEntry): void {
|
|
149
|
+
const lifecycleMode = definition.lifecycle ?? "lazy";
|
|
150
|
+
const persistsAfterFirstSpawn = lifecycleMode === "eager" || lifecycleMode === "lazy-keep-alive";
|
|
151
|
+
const idleOverride = definition.idleTimeout ?? (persistsAfterFirstSpawn ? 0 : undefined);
|
|
152
|
+
targetState.lifecycle.registerServer(name, definition, idleOverride !== undefined ? { idleTimeout: idleOverride } : undefined);
|
|
153
|
+
if (lifecycleMode === "keep-alive") targetState.lifecycle.markKeepAlive(name, definition);
|
|
154
|
+
}
|
|
133
155
|
|
|
134
156
|
// OMP remaps `typebox` to a host shim that historically lacked Type.Unsafe.
|
|
135
157
|
// Prefer Unsafe when present (real TypeBox / fixed OMP shim); otherwise pass
|
|
@@ -282,6 +304,45 @@ function installMcpAdapter(pi: ExtensionAPI, options: McpAdapterOptions) {
|
|
|
282
304
|
|
|
283
305
|
registerPromptCommands(resolveCachedPrompts(earlyConfig));
|
|
284
306
|
|
|
307
|
+
runtimeRegistrars.set(pi, (name: string, definition: ServerEntry): McpServerRegistration => {
|
|
308
|
+
if (typeof name !== "string" || name.trim() === "") {
|
|
309
|
+
throw new Error("MCP server name must be a non-empty string");
|
|
310
|
+
}
|
|
311
|
+
if (typeof definition !== "object" || definition === null || Array.isArray(definition)) {
|
|
312
|
+
throw new Error(`MCP server definition for "${name}" must be an object`);
|
|
313
|
+
}
|
|
314
|
+
const effective = state?.config ?? earlyConfig;
|
|
315
|
+
if (runtimeServers.has(name) || Object.hasOwn(effective.mcpServers, name)) {
|
|
316
|
+
throw new Error(`MCP server "${name}" is already registered`);
|
|
317
|
+
}
|
|
318
|
+
// Runtime-registered servers are proxy-tool-only: direct tools are frozen
|
|
319
|
+
// at startup and must not be rebuilt for late registrations.
|
|
320
|
+
const entry: ServerEntry = { ...structuredClone(definition), directTools: false };
|
|
321
|
+
runtimeServers.set(name, entry);
|
|
322
|
+
const registeredState = state;
|
|
323
|
+
if (registeredState) {
|
|
324
|
+
registeredState.config.mcpServers[name] = entry;
|
|
325
|
+
attachRuntimeServerLifecycle(registeredState, name, entry);
|
|
326
|
+
syncToolSurface();
|
|
327
|
+
updateStatusBar(registeredState);
|
|
328
|
+
}
|
|
329
|
+
let disposed = false;
|
|
330
|
+
return {
|
|
331
|
+
dispose: async (): Promise<void> => {
|
|
332
|
+
if (disposed) return;
|
|
333
|
+
disposed = true;
|
|
334
|
+
runtimeServers.delete(name);
|
|
335
|
+
const currentState = state;
|
|
336
|
+
if (!currentState || currentState.config.mcpServers[name] !== entry) return;
|
|
337
|
+
delete currentState.config.mcpServers[name];
|
|
338
|
+
currentState.lifecycle.unregisterServer(name);
|
|
339
|
+
await currentState.manager.close(name);
|
|
340
|
+
syncToolSurface();
|
|
341
|
+
updateStatusBar(currentState);
|
|
342
|
+
},
|
|
343
|
+
};
|
|
344
|
+
});
|
|
345
|
+
|
|
285
346
|
const getPiTools = (): ToolInfo[] => pi.getAllTools();
|
|
286
347
|
|
|
287
348
|
pi.registerFlag("mcp-config", {
|
|
@@ -299,7 +360,6 @@ function installMcpAdapter(pi: ExtensionAPI, options: McpAdapterOptions) {
|
|
|
299
360
|
}
|
|
300
361
|
: {}),
|
|
301
362
|
oauthRuntime,
|
|
302
|
-
statusEvents: pi.events,
|
|
303
363
|
});
|
|
304
364
|
initPromise = promise;
|
|
305
365
|
|
|
@@ -314,6 +374,14 @@ function installMcpAdapter(pi: ExtensionAPI, options: McpAdapterOptions) {
|
|
|
314
374
|
}
|
|
315
375
|
|
|
316
376
|
state = nextState;
|
|
377
|
+
for (const [name, definition] of runtimeServers) {
|
|
378
|
+
if (Object.hasOwn(nextState.config.mcpServers, name)) {
|
|
379
|
+
console.error(`MCP: runtime-registered server "${name}" now collides with a configured server; keeping the configured server`);
|
|
380
|
+
continue;
|
|
381
|
+
}
|
|
382
|
+
nextState.config.mcpServers[name] = definition;
|
|
383
|
+
attachRuntimeServerLifecycle(nextState, name, definition);
|
|
384
|
+
}
|
|
317
385
|
nextState.onToolMetadataUpdated = (_serverName, _reason) => {
|
|
318
386
|
if (state !== nextState || !owner.isActive()) return;
|
|
319
387
|
syncPromptCommands();
|
|
@@ -325,6 +393,9 @@ function installMcpAdapter(pi: ExtensionAPI, options: McpAdapterOptions) {
|
|
|
325
393
|
};
|
|
326
394
|
syncPromptCommands();
|
|
327
395
|
syncToolSurface(ctx);
|
|
396
|
+
// A connected snapshot is readiness-like external state. Publish it only
|
|
397
|
+
// after Pi's model-facing direct-tool surface reflects live metadata.
|
|
398
|
+
nextState.statusEvents = pi.events;
|
|
328
399
|
updateStatusBar(nextState);
|
|
329
400
|
initPromise = null;
|
|
330
401
|
if (earlyConfig.settings?.freezeDirectTools === true) {
|
|
@@ -417,6 +488,29 @@ function installMcpAdapter(pi: ExtensionAPI, options: McpAdapterOptions) {
|
|
|
417
488
|
}
|
|
418
489
|
});
|
|
419
490
|
|
|
491
|
+
pi.on("input", async () => {
|
|
492
|
+
const inputOwner = currentOwner;
|
|
493
|
+
if (!inputOwner?.isActive()) return;
|
|
494
|
+
|
|
495
|
+
if (!state && initPromise) {
|
|
496
|
+
try {
|
|
497
|
+
await awaitWithTimeout(initPromise, INIT_WAIT_TIMEOUT_MS);
|
|
498
|
+
} catch {
|
|
499
|
+
return;
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
const inputState = state;
|
|
504
|
+
if (!inputState || !inputOwner.isActive()) return;
|
|
505
|
+
try {
|
|
506
|
+
await inputState.lifecycle.ensureConverged(inputOwner.signal);
|
|
507
|
+
} catch (error) {
|
|
508
|
+
if (!isAbortError(error, inputOwner.signal)) {
|
|
509
|
+
logger.debug(`MCP: keep-alive convergence failed before input: ${formatTerminalError(error)}`);
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
});
|
|
513
|
+
|
|
420
514
|
pi.on("session_shutdown", async () => {
|
|
421
515
|
++lifecycleGeneration;
|
|
422
516
|
const currentState = state;
|
|
@@ -444,7 +538,7 @@ function installMcpAdapter(pi: ExtensionAPI, options: McpAdapterOptions) {
|
|
|
444
538
|
// Re-flag returned MCP tool failures so pi registers them as errors (see toolErrorOverride).
|
|
445
539
|
pi.on("tool_result", (event) => toolErrorOverride(event.details));
|
|
446
540
|
|
|
447
|
-
pi.registerCommand(
|
|
541
|
+
const registerMcpCommand = (commandName: string) => pi.registerCommand(commandName, {
|
|
448
542
|
description: "Show MCP server status",
|
|
449
543
|
getArgumentCompletions: (prefix: string) => {
|
|
450
544
|
const normalized = prefix.trimStart();
|
|
@@ -456,6 +550,7 @@ function installMcpAdapter(pi: ExtensionAPI, options: McpAdapterOptions) {
|
|
|
456
550
|
{ value: "prompts", label: "prompts — List all MCP prompts" },
|
|
457
551
|
{ value: "setup", label: "setup — Configure MCP servers" },
|
|
458
552
|
{ value: "logout", label: "logout — Clear server credentials" },
|
|
553
|
+
{ value: "token", label: "token — Manage stored bearer tokens" },
|
|
459
554
|
{ value: "disable", label: "disable — Disable a server" },
|
|
460
555
|
{ value: "enable", label: "enable — Enable a server" },
|
|
461
556
|
{ value: "status", label: "status — Show server status" },
|
|
@@ -465,11 +560,27 @@ function installMcpAdapter(pi: ExtensionAPI, options: McpAdapterOptions) {
|
|
|
465
560
|
|
|
466
561
|
const [, subcommand, argumentPrefix] = argumentMatch;
|
|
467
562
|
if (
|
|
468
|
-
(subcommand !== "reconnect" && subcommand !== "logout" && subcommand !== "disable" && subcommand !== "enable")
|
|
563
|
+
(subcommand !== "reconnect" && subcommand !== "logout" && subcommand !== "disable" && subcommand !== "enable" && subcommand !== "token")
|
|
469
564
|
|| argumentPrefix === undefined
|
|
470
565
|
|| !state
|
|
471
566
|
) return null;
|
|
472
567
|
|
|
568
|
+
if (subcommand === "token") {
|
|
569
|
+
const tokenMatch = argumentPrefix.trimStart().match(/^(set|remove|status)\s+(.*)$/);
|
|
570
|
+
if (!tokenMatch) {
|
|
571
|
+
const actions = ["set", "remove", "status"]
|
|
572
|
+
.filter(action => action.startsWith(argumentPrefix.trimStart()))
|
|
573
|
+
.map(action => ({ value: `token ${action} `, label: `${action} — Bearer token ${action}` }));
|
|
574
|
+
return actions.length > 0 ? actions : null;
|
|
575
|
+
}
|
|
576
|
+
const action = tokenMatch[1] ?? "";
|
|
577
|
+
const serverPrefix = tokenMatch[2] ?? "";
|
|
578
|
+
const servers = Object.keys(state.config.mcpServers)
|
|
579
|
+
.filter(serverName => serverName.startsWith(serverPrefix.trimStart()))
|
|
580
|
+
.map(serverName => ({ value: `token ${action} ${serverName}`, label: serverName }));
|
|
581
|
+
return servers.length > 0 ? servers : null;
|
|
582
|
+
}
|
|
583
|
+
|
|
473
584
|
const servers = Object.keys(state.config.mcpServers)
|
|
474
585
|
.filter((serverName) => serverName.startsWith(argumentPrefix.trimStart()))
|
|
475
586
|
.map((serverName) => ({ value: `${subcommand} ${serverName}`, label: serverName }));
|
|
@@ -545,6 +656,21 @@ function installMcpAdapter(pi: ExtensionAPI, options: McpAdapterOptions) {
|
|
|
545
656
|
await logoutServer(serverName, state, commandCtx);
|
|
546
657
|
break;
|
|
547
658
|
}
|
|
659
|
+
case "token": {
|
|
660
|
+
const action = parts[1];
|
|
661
|
+
const serverName = parts.slice(2).join(" ");
|
|
662
|
+
if (action !== "set" && action !== "remove" && action !== "status") {
|
|
663
|
+
if (commandCtx.hasUI) commandCtx.ui?.notify("Usage: /mcp token set|remove|status <server>", "error");
|
|
664
|
+
return;
|
|
665
|
+
}
|
|
666
|
+
if (!serverName) {
|
|
667
|
+
if (commandCtx.hasUI) commandCtx.ui?.notify("Usage: /mcp token set|remove|status <server>", "error");
|
|
668
|
+
return;
|
|
669
|
+
}
|
|
670
|
+
commandOwner?.throwIfInactive();
|
|
671
|
+
await manageBearerToken(action, serverName, state, commandCtx);
|
|
672
|
+
break;
|
|
673
|
+
}
|
|
548
674
|
case "disable":
|
|
549
675
|
case "enable": {
|
|
550
676
|
const serverName = rest;
|
|
@@ -595,6 +721,8 @@ function installMcpAdapter(pi: ExtensionAPI, options: McpAdapterOptions) {
|
|
|
595
721
|
}
|
|
596
722
|
},
|
|
597
723
|
});
|
|
724
|
+
registerMcpCommand("mcp");
|
|
725
|
+
registerMcpCommand("pi-mcp");
|
|
598
726
|
|
|
599
727
|
pi.registerCommand("mcp-auth", {
|
|
600
728
|
description: "Authenticate with an MCP server (OAuth)",
|
|
@@ -737,12 +865,12 @@ function installMcpAdapter(pi: ExtensionAPI, options: McpAdapterOptions) {
|
|
|
737
865
|
action?: string;
|
|
738
866
|
}, signal: AbortSignal | undefined, _onUpdate: AgentToolUpdateCallback<Record<string, unknown>> | undefined, _ctx: ExtensionContext) {
|
|
739
867
|
const executeOwner = currentOwner;
|
|
740
|
-
|
|
741
|
-
|
|
868
|
+
const parseArgs = (value: string | Record<string, unknown> | undefined): Record<string, unknown> | undefined => {
|
|
869
|
+
if (value === undefined || value === "") return undefined;
|
|
742
870
|
let args: unknown;
|
|
743
|
-
if (typeof
|
|
871
|
+
if (typeof value === "string") {
|
|
744
872
|
try {
|
|
745
|
-
args = JSON.parse(
|
|
873
|
+
args = JSON.parse(value);
|
|
746
874
|
} catch (error) {
|
|
747
875
|
if (error instanceof SyntaxError) {
|
|
748
876
|
throw new Error(`Invalid args JSON: ${error.message}`, { cause: error });
|
|
@@ -750,14 +878,57 @@ function installMcpAdapter(pi: ExtensionAPI, options: McpAdapterOptions) {
|
|
|
750
878
|
throw error;
|
|
751
879
|
}
|
|
752
880
|
} else {
|
|
753
|
-
args =
|
|
881
|
+
args = value;
|
|
754
882
|
}
|
|
755
883
|
|
|
756
884
|
if (typeof args !== "object" || args === null || Array.isArray(args)) {
|
|
757
885
|
const gotType = Array.isArray(args) ? "array" : args === null ? "null" : typeof args;
|
|
758
886
|
throw new Error(`Invalid args: expected a JSON object, got ${gotType}`);
|
|
759
887
|
}
|
|
760
|
-
|
|
888
|
+
return args as Record<string, unknown>;
|
|
889
|
+
};
|
|
890
|
+
const validateNestedGatewayParams = (value: Record<string, unknown>): typeof params => {
|
|
891
|
+
for (const key of ["tool", "connect", "describe", "instructions", "search", "server", "action"] as const) {
|
|
892
|
+
if (value[key] !== undefined && typeof value[key] !== "string") {
|
|
893
|
+
throw new Error(`Invalid nested gateway param \`${key}\`: expected string, got ${Array.isArray(value[key]) ? "array" : typeof value[key]}`);
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
for (const key of ["regex", "includeSchemas"] as const) {
|
|
897
|
+
if (value[key] !== undefined && typeof value[key] !== "boolean") {
|
|
898
|
+
throw new Error(`Invalid nested gateway param \`${key}\`: expected boolean, got ${Array.isArray(value[key]) ? "array" : typeof value[key]}`);
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
for (const key of ["limit", "offset"] as const) {
|
|
902
|
+
if (value[key] !== undefined && typeof value[key] !== "number") {
|
|
903
|
+
throw new Error(`Invalid nested gateway param \`${key}\`: expected number, got ${Array.isArray(value[key]) ? "array" : typeof value[key]}`);
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
const args = value.args;
|
|
907
|
+
if (args !== undefined && typeof args !== "string" && (typeof args !== "object" || args === null || Array.isArray(args))) {
|
|
908
|
+
throw new Error(`Invalid nested gateway param \`args\`: expected JSON object or JSON string, got ${Array.isArray(args) ? "array" : args === null ? "null" : typeof args}`);
|
|
909
|
+
}
|
|
910
|
+
return value as typeof params;
|
|
911
|
+
};
|
|
912
|
+
let parsedArgs = parseArgs(params.args);
|
|
913
|
+
let dispatchParams = params;
|
|
914
|
+
const hasGatewayMode = (value: typeof params): boolean =>
|
|
915
|
+
value.tool !== undefined
|
|
916
|
+
|| value.connect !== undefined
|
|
917
|
+
|| value.describe !== undefined
|
|
918
|
+
|| value.instructions !== undefined
|
|
919
|
+
|| value.search !== undefined
|
|
920
|
+
|| value.server !== undefined
|
|
921
|
+
|| value.action !== undefined;
|
|
922
|
+
if (!hasGatewayMode(params) && parsedArgs) {
|
|
923
|
+
const nestedParams = validateNestedGatewayParams(parsedArgs);
|
|
924
|
+
if (hasGatewayMode(nestedParams)) {
|
|
925
|
+
dispatchParams = nestedParams;
|
|
926
|
+
parsedArgs = parseArgs(nestedParams.args);
|
|
927
|
+
} else {
|
|
928
|
+
throw new Error("Gateway params were nested inside `args`; pass them top-level (for example, mcp({ search: \"...\" }) or mcp({ tool: \"...\", args: {} })).");
|
|
929
|
+
}
|
|
930
|
+
} else if (!hasGatewayMode(params) && params.args !== undefined) {
|
|
931
|
+
throw new Error("Gateway params were nested inside `args`; pass them top-level (for example, mcp({ search: \"...\" }) or mcp({ tool: \"...\", args: {} })).");
|
|
761
932
|
}
|
|
762
933
|
|
|
763
934
|
if (!state && initPromise) {
|
|
@@ -788,22 +959,22 @@ function installMcpAdapter(pi: ExtensionAPI, options: McpAdapterOptions) {
|
|
|
788
959
|
}
|
|
789
960
|
executeOwner?.throwIfInactive();
|
|
790
961
|
|
|
791
|
-
if (
|
|
962
|
+
if (dispatchParams.action === "ui-messages") {
|
|
792
963
|
return executeUiMessages(state);
|
|
793
964
|
}
|
|
794
|
-
if (
|
|
795
|
-
if (!
|
|
965
|
+
if (dispatchParams.action === "auth-start") {
|
|
966
|
+
if (!dispatchParams.server) {
|
|
796
967
|
return {
|
|
797
968
|
content: [{ type: "text" as const, text: "auth-start requires `server`. Example: mcp({ action: \"auth-start\", server: \"linear-server\" })" }],
|
|
798
969
|
details: { mode: "auth-start", error: "missing_server" },
|
|
799
970
|
};
|
|
800
971
|
}
|
|
801
972
|
return signal
|
|
802
|
-
? executeAuthStart(state,
|
|
803
|
-
: executeAuthStart(state,
|
|
973
|
+
? executeAuthStart(state, dispatchParams.server, signal)
|
|
974
|
+
: executeAuthStart(state, dispatchParams.server);
|
|
804
975
|
}
|
|
805
|
-
if (
|
|
806
|
-
if (!
|
|
976
|
+
if (dispatchParams.action === "auth-complete") {
|
|
977
|
+
if (!dispatchParams.server) {
|
|
807
978
|
return {
|
|
808
979
|
content: [{ type: "text" as const, text: "auth-complete requires `server`." }],
|
|
809
980
|
details: { mode: "auth-complete", error: "missing_server" },
|
|
@@ -817,28 +988,28 @@ function installMcpAdapter(pi: ExtensionAPI, options: McpAdapterOptions) {
|
|
|
817
988
|
};
|
|
818
989
|
}
|
|
819
990
|
return signal
|
|
820
|
-
? executeAuthComplete(state,
|
|
821
|
-
: executeAuthComplete(state,
|
|
991
|
+
? executeAuthComplete(state, dispatchParams.server, input, signal)
|
|
992
|
+
: executeAuthComplete(state, dispatchParams.server, input);
|
|
822
993
|
}
|
|
823
|
-
if (
|
|
824
|
-
return executeCall(state,
|
|
994
|
+
if (dispatchParams.tool) {
|
|
995
|
+
return executeCall(state, dispatchParams.tool, parsedArgs, dispatchParams.server, getPiTools, signal);
|
|
825
996
|
}
|
|
826
|
-
if (
|
|
827
|
-
const result = await executeConnect(state,
|
|
997
|
+
if (dispatchParams.connect) {
|
|
998
|
+
const result = await executeConnect(state, dispatchParams.connect, signal);
|
|
828
999
|
syncToolSurface(_ctx as ExtensionContext);
|
|
829
1000
|
return result;
|
|
830
1001
|
}
|
|
831
|
-
if (
|
|
832
|
-
return executeDescribe(state,
|
|
1002
|
+
if (dispatchParams.describe) {
|
|
1003
|
+
return executeDescribe(state, dispatchParams.describe);
|
|
833
1004
|
}
|
|
834
|
-
if (
|
|
835
|
-
return executeInstructions(state,
|
|
1005
|
+
if (dispatchParams.instructions) {
|
|
1006
|
+
return executeInstructions(state, dispatchParams.instructions);
|
|
836
1007
|
}
|
|
837
|
-
if (
|
|
838
|
-
return executeSearch(state,
|
|
1008
|
+
if (dispatchParams.search !== undefined) {
|
|
1009
|
+
return executeSearch(state, dispatchParams.search, dispatchParams.regex, dispatchParams.server, dispatchParams.includeSchemas, dispatchParams.limit, dispatchParams.offset);
|
|
839
1010
|
}
|
|
840
|
-
if (
|
|
841
|
-
return executeList(state,
|
|
1011
|
+
if (dispatchParams.server) {
|
|
1012
|
+
return executeList(state, dispatchParams.server);
|
|
842
1013
|
}
|
|
843
1014
|
return executeStatus(state);
|
|
844
1015
|
},
|
|
@@ -895,4 +1066,20 @@ export function createMcpAdapter(options: McpAdapterOptions = {}) {
|
|
|
895
1066
|
};
|
|
896
1067
|
}
|
|
897
1068
|
|
|
1069
|
+
/**
|
|
1070
|
+
* Register an MCP server with the adapter installed for this Pi instance.
|
|
1071
|
+
* Registrations are session/runtime scoped and never persisted. Duplicate
|
|
1072
|
+
* names fail closed. Registered servers are proxy-tool-only; their tools
|
|
1073
|
+
* become visible at the next tool sync. To change a definition, dispose the
|
|
1074
|
+
* registration and register again.
|
|
1075
|
+
*/
|
|
1076
|
+
export function registerMcpServer(options: { pi: ExtensionAPI; name: string; definition: ServerEntry }): McpServerRegistration {
|
|
1077
|
+
const { pi, name, definition } = options;
|
|
1078
|
+
const register = runtimeRegistrars.get(pi);
|
|
1079
|
+
if (!register) {
|
|
1080
|
+
throw new Error("pi-mcp-adapter is not installed for this Pi instance");
|
|
1081
|
+
}
|
|
1082
|
+
return register(name, definition);
|
|
1083
|
+
}
|
|
1084
|
+
|
|
898
1085
|
export default createMcpAdapter();
|