@herbertgao/pi-extensions 2026.8.14 → 2026.9.0
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 +19 -13
- package/THIRD_PARTY_NOTICES.md +26 -1
- package/node_modules/@czottmann/pi-automode/CHANGELOG.md +8 -1
- package/node_modules/@czottmann/pi-automode/README.md +4 -0
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/classifier.ts +71 -9
- package/node_modules/@czottmann/pi-automode/package.json +1 -1
- package/node_modules/@herbertgao/pi-bark/LICENSE +21 -0
- package/node_modules/@herbertgao/pi-bark/README.md +44 -0
- package/node_modules/@herbertgao/pi-bark/assets/pi-icon.png +0 -0
- package/node_modules/@herbertgao/pi-bark/package.json +53 -0
- package/node_modules/@herbertgao/pi-bark/src/index.ts +178 -0
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/config.ts +20 -0
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +46 -3
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/interaction.ts +55 -17
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/packets.ts +6 -0
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/scroll.ts +5 -0
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/result.ts +34 -30
- package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
- package/node_modules/@juicesharp/rpiv-ask-user-question/package.json +2 -2
- package/node_modules/@narumitw/pi-btw/README.md +129 -88
- package/node_modules/@narumitw/pi-btw/dist/index.ts +283 -59
- package/node_modules/@narumitw/pi-btw/dist/index.ts.map +3 -3
- package/node_modules/@narumitw/pi-btw/package.json +5 -8
- package/node_modules/@narumitw/pi-btw/src/btw.ts +31 -26
- package/node_modules/@narumitw/pi-btw/src/fullscreen-ui.ts +264 -24
- package/node_modules/@narumitw/pi-btw/src/menu.ts +34 -2
- package/node_modules/@narumitw/pi-btw/src/settings.ts +16 -0
- package/node_modules/@narumitw/pi-btw/src/text.ts +18 -0
- package/node_modules/@narumitw/pi-btw/src/transcript-pager.ts +5 -16
- package/node_modules/@narumitw/pi-caffeinate/LICENSE +21 -0
- package/node_modules/@narumitw/pi-caffeinate/README.md +224 -0
- package/node_modules/@narumitw/pi-caffeinate/dist/index.ts +1112 -0
- package/node_modules/@narumitw/pi-caffeinate/dist/index.ts.map +7 -0
- package/node_modules/@narumitw/pi-caffeinate/package.json +53 -0
- package/node_modules/@narumitw/pi-caffeinate/src/caffeinate.ts +811 -0
- package/node_modules/@narumitw/pi-caffeinate/src/dbus-inhibit.ts +153 -0
- package/node_modules/@narumitw/pi-caffeinate/src/index.ts +1 -0
- package/node_modules/@narumitw/pi-caffeinate/src/inhibitor-process.ts +43 -0
- package/node_modules/@narumitw/pi-caffeinate/src/inhibitors.ts +167 -0
- package/node_modules/@narumitw/pi-caffeinate/src/settings.ts +202 -0
- package/node_modules/@tifan/pi-handoff/README.md +39 -13
- package/node_modules/@tifan/pi-handoff/package.json +2 -2
- package/node_modules/@tifan/pi-handoff/src/index.ts +166 -5
- package/node_modules/@tifan/pi-recap/README.md +1 -1
- package/node_modules/@tifan/pi-recap/package.json +2 -2
- package/node_modules/@tifan/pi-recap/src/index.ts +15 -0
- package/node_modules/@tifan/pi-rename/README.md +42 -21
- package/node_modules/@tifan/pi-rename/package.json +1 -1
- package/node_modules/@tifan/pi-rename/src/index.ts +62 -11
- package/node_modules/@tifan/pi-rename/src/language.ts +18 -0
- package/node_modules/@tifan/pi-rename/src/models.ts +69 -13
- package/node_modules/@tifan/pi-rename/src/naming.ts +36 -7
- package/node_modules/@tifan/pi-rename/src/sanitize.ts +22 -14
- package/node_modules/pi-lens/CHANGELOG.md +320 -0
- package/node_modules/pi-lens/config/dependency-cruiser-eager-allowlist.json +79 -0
- package/node_modules/pi-lens/dist/clients/actionable-warnings-logger.js +16 -1
- package/node_modules/pi-lens/dist/clients/ast-grep-client.js +13 -6
- package/node_modules/pi-lens/dist/clients/availability-probe-flight.js +12 -0
- package/node_modules/pi-lens/dist/clients/biome-client.js +7 -0
- package/node_modules/pi-lens/dist/clients/blocker-freshness.js +20 -0
- package/node_modules/pi-lens/dist/clients/bounded-telemetry.js +56 -19
- package/node_modules/pi-lens/dist/clients/build-identity.js +95 -0
- package/node_modules/pi-lens/dist/clients/bus-publish.js +3 -0
- package/node_modules/pi-lens/dist/clients/cache/rule-cache.js +2 -1
- package/node_modules/pi-lens/dist/clients/cache-observability.js +2 -1
- package/node_modules/pi-lens/dist/clients/cascade-logger.js +15 -1
- package/node_modules/pi-lens/dist/clients/dead-code-client.js +14 -11
- package/node_modules/pi-lens/dist/clients/degradation-ledger.js +56 -4
- package/node_modules/pi-lens/dist/clients/demoted-finding-render.js +14 -0
- package/node_modules/pi-lens/dist/clients/dependency-checker.js +20 -3
- package/node_modules/pi-lens/dist/clients/deps/minimatch.js +1 -1
- package/node_modules/pi-lens/dist/clients/dispatch/collect-later-tier.js +39 -0
- package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +150 -9
- package/node_modules/pi-lens/dist/clients/dispatch/fact-store.js +231 -9
- package/node_modules/pi-lens/dist/clients/dispatch/integration.js +205 -100
- package/node_modules/pi-lens/dist/clients/dispatch/pending-runner-findings.js +87 -0
- package/node_modules/pi-lens/dist/clients/dispatch/plan.js +21 -5
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ast-grep-napi.js +174 -55
- package/node_modules/pi-lens/dist/clients/dispatch/runners/eslint.js +5 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-lint.js +16 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-render.js +54 -9
- package/node_modules/pi-lens/dist/clients/dispatch/runners/index.js +1 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +37 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +4 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/oxlint.js +11 -4
- package/node_modules/pi-lens/dist/clients/dispatch/runners/psscriptanalyzer.js +4 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/rust-clippy.js +8 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +76 -25
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/spawn-outcome.js +4 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/tool-failure.js +19 -7
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/toolchain-availability.js +7 -13
- package/node_modules/pi-lens/dist/clients/dispatch/runners/yaml-rule-parser.js +51 -17
- package/node_modules/pi-lens/dist/clients/event-loop-monitor.js +66 -1
- package/node_modules/pi-lens/dist/clients/file-utils.js +157 -7
- package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +5 -0
- package/node_modules/pi-lens/dist/clients/formatters.js +28 -3
- package/node_modules/pi-lens/dist/clients/git-guard.js +197 -47
- package/node_modules/pi-lens/dist/clients/git-tracked-ignore.js +32 -1
- package/node_modules/pi-lens/dist/clients/govulncheck-client.js +5 -1
- package/node_modules/pi-lens/dist/clients/gzip-stage-write.js +7 -0
- package/node_modules/pi-lens/dist/clients/installer/index.js +131 -34
- package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh.js +3 -1
- package/node_modules/pi-lens/dist/clients/instance-reaper.js +4 -13
- package/node_modules/pi-lens/dist/clients/instance-registry-lock.js +145 -0
- package/node_modules/pi-lens/dist/clients/instance-registry.js +432 -122
- package/node_modules/pi-lens/dist/clients/jscpd-client.js +6 -1
- package/node_modules/pi-lens/dist/clients/language-profile.js +4 -2
- package/node_modules/pi-lens/dist/clients/latency-logger.js +19 -1
- package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +8 -0
- package/node_modules/pi-lens/dist/clients/lens-map.js +3 -1
- package/node_modules/pi-lens/dist/clients/lsp/cascade-tier.js +4 -0
- package/node_modules/pi-lens/dist/clients/lsp/client.js +516 -31
- package/node_modules/pi-lens/dist/clients/lsp/config.js +25 -2
- package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +9 -4
- package/node_modules/pi-lens/dist/clients/lsp/index.js +509 -182
- package/node_modules/pi-lens/dist/clients/lsp/jvm-runtime.js +5 -0
- package/node_modules/pi-lens/dist/clients/lsp/launch.js +36 -8
- package/node_modules/pi-lens/dist/clients/lsp/pending-aux-coverage.js +116 -4
- package/node_modules/pi-lens/dist/clients/lsp/server.js +142 -13
- package/node_modules/pi-lens/dist/clients/lsp/session-roots.js +99 -0
- package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +16 -6
- package/node_modules/pi-lens/dist/clients/lsp/workspace-sweep-hold.js +32 -23
- package/node_modules/pi-lens/dist/clients/lsp-mutation.js +16 -2
- package/node_modules/pi-lens/dist/clients/mcp/analyze.js +12 -6
- package/node_modules/pi-lens/dist/clients/mcp/session.js +14 -1
- package/node_modules/pi-lens/dist/clients/memory-sampler.js +23 -1
- package/node_modules/pi-lens/dist/clients/message-end-attribution.js +30 -0
- package/node_modules/pi-lens/dist/clients/metrics-history.js +21 -4
- package/node_modules/pi-lens/dist/clients/opaque-mutation-scan.js +232 -18
- package/node_modules/pi-lens/dist/clients/package-manager.js +6 -18
- package/node_modules/pi-lens/dist/clients/path-keyed-map.js +14 -1
- package/node_modules/pi-lens/dist/clients/path-utils.js +32 -0
- package/node_modules/pi-lens/dist/clients/pipeline.js +0 -8
- package/node_modules/pi-lens/dist/clients/process-singletons.js +210 -0
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/madge.js +2 -1
- package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +10 -4
- package/node_modules/pi-lens/dist/clients/project-snapshot.js +33 -11
- package/node_modules/pi-lens/dist/clients/read-guard-logger.js +24 -2
- package/node_modules/pi-lens/dist/clients/read-guard.js +74 -7
- package/node_modules/pi-lens/dist/clients/recent-touches.js +17 -5
- package/node_modules/pi-lens/dist/clients/review-graph/builder.js +639 -62
- package/node_modules/pi-lens/dist/clients/review-graph/tsconfig-paths.js +5 -1
- package/node_modules/pi-lens/dist/clients/review-graph-logger.js +21 -1
- package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +68 -0
- package/node_modules/pi-lens/dist/clients/runtime-session.js +30 -12
- package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +15 -0
- package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +106 -7
- package/node_modules/pi-lens/dist/clients/runtime-turn.js +242 -27
- package/node_modules/pi-lens/dist/clients/safe-spawn.js +158 -18
- package/node_modules/pi-lens/dist/clients/security-scan-client.js +48 -17
- package/node_modules/pi-lens/dist/clients/session-lifecycle.js +238 -42
- package/node_modules/pi-lens/dist/clients/sg-runner.js +27 -15
- package/node_modules/pi-lens/dist/clients/shared-checkout-guard.js +338 -0
- package/node_modules/pi-lens/dist/clients/spawn-output-cap.js +37 -0
- package/node_modules/pi-lens/dist/clients/spawn-timeout-cooldown.js +15 -1
- package/node_modules/pi-lens/dist/clients/startup-scan.js +6 -7
- package/node_modules/pi-lens/dist/clients/startup-timing.js +69 -4
- package/node_modules/pi-lens/dist/clients/string-utils.js +20 -0
- package/node_modules/pi-lens/dist/clients/test-runner-client.js +419 -88
- package/node_modules/pi-lens/dist/clients/tool-policy.js +1 -1
- package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +11 -5
- package/node_modules/pi-lens/dist/clients/tree-sitter-logger.js +17 -1
- package/node_modules/pi-lens/dist/clients/warm-attach.js +8 -10
- package/node_modules/pi-lens/dist/clients/word-index-logger.js +13 -1
- package/node_modules/pi-lens/dist/clients/word-index-store.js +448 -0
- package/node_modules/pi-lens/dist/clients/word-index.js +582 -104
- package/node_modules/pi-lens/dist/clients/workspace-topology.js +17 -0
- package/node_modules/pi-lens/dist/clients/zizmor-config.js +26 -6
- package/node_modules/pi-lens/dist/index.js +11243 -6651
- package/node_modules/pi-lens/dist/mcp/build-staleness.js +8 -7
- package/node_modules/pi-lens/dist/mcp/cli.js +3 -1
- package/node_modules/pi-lens/dist/mcp/server.js +6 -1
- package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +4 -0
- package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +14 -5
- package/node_modules/pi-lens/dist/tools/lsp-navigation.js +3 -1
- package/node_modules/pi-lens/docs/agent-guide.md +4 -2
- package/node_modules/pi-lens/docs/ast-grep_rules_catalog.md +41 -10
- package/node_modules/pi-lens/docs/astplayground.md +26 -17
- package/node_modules/pi-lens/package.json +5 -1
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/c-no-malloc-free-test.yml +20 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/cpp-no-malloc-free-test.yml +25 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/cpp-no-printf-test.yml +19 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/go-no-fmt-println-test.yml +19 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/go-no-panic-in-lib-test.yml +17 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/go-no-underscore-func-name-test.yml +18 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/go-prefer-errors-is-test.yml +15 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/go-prefer-string-builder-test.yml +21 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/hyphenated-svg-attribute-test.yml +11 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/kotlin-no-lateinit-test.yml +17 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/kotlin-no-nullable-boolean-test.yml +15 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/kotlin-no-println-test.yml +19 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/kotlin-no-unnecessary-let-test.yml +7 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/kotlin-no-unsafe-cast-test.yml +7 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/kotlin-no-var-test.yml +7 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/kotlin-prefer-data-class-test.yml +25 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/kotlin-prefer-is-empty-test.yml +11 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-important-test.yml +21 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-raw-types-test.yml +30 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-string-concat-in-loop-test.yml +100 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-system-out-println-test.yml +7 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/prefer-string-is-empty-test.yml +7 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/python-optional-type-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/reducible-list-comprehension-test.yml +11 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/ruby-symbol-to-proc-candidate-test.yml +10 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/rust-no-chars-enumerate-test.yml +7 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/c-no-malloc-free.yml +39 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/cpp-no-malloc-free.yml +45 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/cpp-no-printf.yml +41 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/go-no-fmt-println.yml +43 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/go-no-panic-in-lib.yml +41 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/go-no-underscore-func-name.yml +35 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/go-prefer-errors-is.yml +40 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/go-prefer-string-builder.yml +43 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/hyphenated-svg-attribute.yml +32 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/kotlin-no-lateinit.yml +37 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/kotlin-no-nullable-boolean.yml +33 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/kotlin-no-println.yml +42 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/kotlin-no-unnecessary-let.yml +28 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/kotlin-no-unsafe-cast.yml +28 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/kotlin-no-var.yml +35 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/kotlin-prefer-data-class.yml +66 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/kotlin-prefer-is-empty.yml +35 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-important.yml +21 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-raw-types.yml +33 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-string-concat-in-loop.yml +90 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-system-out-println.yml +16 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/prefer-string-is-empty.yml +11 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/python-optional-type.yml +22 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/reducible-list-comprehension.yml +29 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/ruby-symbol-to-proc-candidate.yml +25 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/rust-no-chars-enumerate.yml +19 -0
- package/node_modules/pi-mcp-adapter/CHANGELOG.md +42 -0
- package/node_modules/pi-mcp-adapter/README.md +15 -15
- package/node_modules/pi-mcp-adapter/commands.ts +59 -22
- package/node_modules/pi-mcp-adapter/config.ts +18 -4
- package/node_modules/pi-mcp-adapter/direct-tools.ts +26 -6
- package/node_modules/pi-mcp-adapter/dist/config.d.ts +4 -0
- package/node_modules/pi-mcp-adapter/dist/config.js +13 -4
- package/node_modules/pi-mcp-adapter/dist/config.js.map +1 -1
- package/node_modules/pi-mcp-adapter/dist/types.d.ts +12 -4
- package/node_modules/pi-mcp-adapter/dist/types.js.map +1 -1
- package/node_modules/pi-mcp-adapter/error-signal.ts +15 -4
- package/node_modules/pi-mcp-adapter/errors.ts +141 -0
- package/node_modules/pi-mcp-adapter/host-html-template.ts +58 -5
- package/node_modules/pi-mcp-adapter/index.ts +2 -3
- package/node_modules/pi-mcp-adapter/init.ts +5 -0
- package/node_modules/pi-mcp-adapter/mcp-auth-flow.ts +105 -32
- package/node_modules/pi-mcp-adapter/mcp-panel.ts +30 -9
- package/node_modules/pi-mcp-adapter/mcp-setup-panel.ts +66 -28
- package/node_modules/pi-mcp-adapter/mcp-status.ts +2 -0
- package/node_modules/pi-mcp-adapter/package.json +2 -1
- package/node_modules/pi-mcp-adapter/proxy-modes.ts +88 -25
- package/node_modules/pi-mcp-adapter/sandbox-proxy-template.ts +217 -0
- package/node_modules/pi-mcp-adapter/server-manager.ts +343 -6
- package/node_modules/pi-mcp-adapter/skills/mcp-scripting/SKILL.md +1 -0
- package/node_modules/pi-mcp-adapter/types.ts +19 -4
- package/node_modules/pi-mcp-adapter/ui-resource-handler.ts +18 -2
- package/node_modules/pi-mcp-adapter/ui-server.ts +179 -54
- package/node_modules/pi-mcp-adapter/ui-session.ts +28 -8
- package/node_modules/pi-web-access/CHANGELOG.md +20 -0
- package/node_modules/pi-web-access/README.md +15 -2
- package/node_modules/pi-web-access/extract.ts +57 -12
- package/node_modules/pi-web-access/github-extract.ts +47 -3
- package/node_modules/pi-web-access/index.ts +1 -1
- package/node_modules/pi-web-access/package.json +1 -1
- package/node_modules/pi-web-access/page-query.ts +61 -8
- package/package.json +21 -17
- package/node_modules/@tifan/pi-titlebar-spinner/README.md +0 -24
- package/node_modules/@tifan/pi-titlebar-spinner/package.json +0 -39
- package/node_modules/@tifan/pi-titlebar-spinner/src/index.ts +0 -49
|
@@ -2,7 +2,7 @@ import { matchesKey, truncateToWidth, visibleWidth } from "@earendil-works/pi-tu
|
|
|
2
2
|
import { createPanelKeys, type PanelKeybindings, type PanelKeys } from "./panel-keys.ts";
|
|
3
3
|
import type { ImportKind } from "./types.ts";
|
|
4
4
|
import { getConfigDirName } from "./agent-dir.ts";
|
|
5
|
-
import { KNOWN_SERVER_PRESETS, type ConfigWritePreview, type KnownServerPreset, type McpDiscoverySummary } from "./config.ts";
|
|
5
|
+
import { KNOWN_SERVER_PRESETS, type ConfigWritePreview, type KnownServerPreset, type McpDiscoverySummary, type SharedConfigTarget } from "./config.ts";
|
|
6
6
|
import type { McpOnboardingState } from "./onboarding-state.ts";
|
|
7
7
|
|
|
8
8
|
interface SetupTheme {
|
|
@@ -54,13 +54,13 @@ function wrapText(text: string, width: number): string[] {
|
|
|
54
54
|
|
|
55
55
|
export interface SetupPanelCallbacks {
|
|
56
56
|
previewImports: (imports: ImportKind[]) => ConfigWritePreview;
|
|
57
|
-
|
|
58
|
-
previewRepoPrompt: () => ConfigWritePreview | null;
|
|
59
|
-
previewKnownServer: (preset: KnownServerPreset) => ConfigWritePreview;
|
|
57
|
+
previewStarterConfig: (target: SharedConfigTarget) => ConfigWritePreview;
|
|
58
|
+
previewRepoPrompt: (target: SharedConfigTarget) => ConfigWritePreview | null;
|
|
59
|
+
previewKnownServer: (preset: KnownServerPreset, target: SharedConfigTarget) => ConfigWritePreview;
|
|
60
60
|
adoptImports: (imports: ImportKind[]) => Promise<{ added: ImportKind[]; path: string }>;
|
|
61
|
-
|
|
62
|
-
addRepoPrompt: () => Promise<{ path: string; serverName: string }>;
|
|
63
|
-
addKnownServer: (preset: KnownServerPreset) => Promise<{ path: string; serverName: string }>;
|
|
61
|
+
scaffoldConfig: (target: SharedConfigTarget) => Promise<{ path: string }>;
|
|
62
|
+
addRepoPrompt: (target: SharedConfigTarget) => Promise<{ path: string; serverName: string }>;
|
|
63
|
+
addKnownServer: (preset: KnownServerPreset, target: SharedConfigTarget) => Promise<{ path: string; serverName: string }>;
|
|
64
64
|
openPath: (path: string) => Promise<void>;
|
|
65
65
|
markSetupCompleted: () => void;
|
|
66
66
|
}
|
|
@@ -75,13 +75,14 @@ type Screen = "empty" | "setup" | "imports" | "paths";
|
|
|
75
75
|
|
|
76
76
|
type ActionId =
|
|
77
77
|
| "run-setup"
|
|
78
|
+
| "select-shared-target"
|
|
78
79
|
| "adopt-imports"
|
|
79
80
|
| "view-example"
|
|
80
81
|
| "show-precedence"
|
|
81
82
|
| "open-paths"
|
|
82
83
|
| "add-repoprompt"
|
|
83
84
|
| "add-known-server"
|
|
84
|
-
| "scaffold-
|
|
85
|
+
| "scaffold-shared-config"
|
|
85
86
|
| "close";
|
|
86
87
|
|
|
87
88
|
interface Action {
|
|
@@ -89,6 +90,7 @@ interface Action {
|
|
|
89
90
|
label: string;
|
|
90
91
|
description: string;
|
|
91
92
|
preset?: KnownServerPreset;
|
|
93
|
+
target?: SharedConfigTarget;
|
|
92
94
|
}
|
|
93
95
|
|
|
94
96
|
export class McpSetupPanel {
|
|
@@ -96,6 +98,7 @@ export class McpSetupPanel {
|
|
|
96
98
|
private actionCursor = 0;
|
|
97
99
|
private importCursor = 0;
|
|
98
100
|
private pathCursor = 0;
|
|
101
|
+
private sharedConfigTarget: SharedConfigTarget = "project";
|
|
99
102
|
private selectedImports = new Set<ImportKind>();
|
|
100
103
|
private busy = false;
|
|
101
104
|
private notice: { text: string; tone: "success" | "warning" | "muted" } | null = null;
|
|
@@ -144,9 +147,13 @@ export class McpSetupPanel {
|
|
|
144
147
|
if (this.discovery.imports.length > 0) {
|
|
145
148
|
actions.push({ id: "adopt-imports", label: "Adopt detected compatibility imports", description: `Choose which host-specific MCP configs Pi should import into its own override file. ${this.discovery.imports.length} source${this.discovery.imports.length === 1 ? "" : "s"} found.` });
|
|
146
149
|
}
|
|
147
|
-
actions.push(
|
|
148
|
-
|
|
149
|
-
|
|
150
|
+
actions.push(
|
|
151
|
+
{ id: "select-shared-target", label: `${this.sharedConfigTarget === "project" ? "●" : "○"} Add to this project (.mcp.json)`, description: "Write new shared MCP servers to the project/team config.", target: "project" },
|
|
152
|
+
{ id: "select-shared-target", label: `${this.sharedConfigTarget === "global" ? "●" : "○"} Add globally (~/.config/mcp/mcp.json)`, description: "Write new shared MCP servers to your all-projects config.", target: "global" },
|
|
153
|
+
);
|
|
154
|
+
actions.push({ id: "view-example", label: "View example shared config", description: "Preview a working shared MCP config you can paste or adapt." });
|
|
155
|
+
if (!this.selectedSharedConfigExists()) {
|
|
156
|
+
actions.push({ id: "scaffold-shared-config", label: `Scaffold ${this.sharedTargetLabel()}`, description: "Write a minimal config at the selected normal MCP setup path, then reload Pi." });
|
|
150
157
|
}
|
|
151
158
|
actions.push({ id: "show-precedence", label: "Explain config precedence", description: "Show the read order and where Pi writes compatibility settings." });
|
|
152
159
|
if (this.getDetectedPaths().length > 0) {
|
|
@@ -156,7 +163,7 @@ export class McpSetupPanel {
|
|
|
156
163
|
actions.push({ id: "add-known-server", label: preset.name, description: preset.summary, preset });
|
|
157
164
|
}
|
|
158
165
|
if (!this.discovery.repoPrompt.configured && this.discovery.repoPrompt.executablePath && this.discovery.repoPrompt.targetPath && this.discovery.repoPrompt.entry && this.discovery.repoPrompt.serverName) {
|
|
159
|
-
actions.push({ id: "add-repoprompt", label: "Add RepoPrompt to shared
|
|
166
|
+
actions.push({ id: "add-repoprompt", label: "Add RepoPrompt to selected shared config", description: "Write a standard MCP entry for RepoPrompt to the selected normal setup path, then reload MCP in-session." });
|
|
160
167
|
}
|
|
161
168
|
actions.push({ id: "close", label: "Close", description: "Exit the onboarding flow." });
|
|
162
169
|
return actions;
|
|
@@ -170,6 +177,15 @@ export class McpSetupPanel {
|
|
|
170
177
|
return [...new Set(paths)];
|
|
171
178
|
}
|
|
172
179
|
|
|
180
|
+
private sharedTargetLabel(): string {
|
|
181
|
+
return this.sharedConfigTarget === "project" ? "project .mcp.json" : "global ~/.config/mcp/mcp.json";
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
private selectedSharedConfigExists(): boolean {
|
|
185
|
+
const sourceId = this.sharedConfigTarget === "project" ? "shared-project" : "shared-global";
|
|
186
|
+
return this.discovery.sources.some((source) => source.id === sourceId && source.exists);
|
|
187
|
+
}
|
|
188
|
+
|
|
173
189
|
private getSelectedAction(): Action | undefined {
|
|
174
190
|
const actions = this.getActions();
|
|
175
191
|
return actions[this.actionCursor];
|
|
@@ -293,9 +309,15 @@ export class McpSetupPanel {
|
|
|
293
309
|
this.tui.requestRender();
|
|
294
310
|
return;
|
|
295
311
|
}
|
|
296
|
-
if (action.id === "
|
|
312
|
+
if (action.id === "select-shared-target" && action.target) {
|
|
313
|
+
this.sharedConfigTarget = action.target;
|
|
314
|
+
this.notice = { text: `New shared servers will be written to ${this.sharedTargetLabel()}.`, tone: "muted" };
|
|
315
|
+
this.tui.requestRender();
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
if (action.id === "scaffold-shared-config") {
|
|
297
319
|
await this.runBusy(async () => {
|
|
298
|
-
const result = await this.callbacks.
|
|
320
|
+
const result = await this.callbacks.scaffoldConfig(this.sharedConfigTarget);
|
|
299
321
|
this.callbacks.markSetupCompleted();
|
|
300
322
|
this.notice = { text: `Wrote starter config to ${result.path}. Pi will reload after this panel closes.`, tone: "success" };
|
|
301
323
|
});
|
|
@@ -303,7 +325,7 @@ export class McpSetupPanel {
|
|
|
303
325
|
}
|
|
304
326
|
if (action.id === "add-repoprompt") {
|
|
305
327
|
await this.runBusy(async () => {
|
|
306
|
-
const result = await this.callbacks.addRepoPrompt();
|
|
328
|
+
const result = await this.callbacks.addRepoPrompt(this.sharedConfigTarget);
|
|
307
329
|
this.callbacks.markSetupCompleted();
|
|
308
330
|
this.notice = { text: `Added ${result.serverName} to ${result.path}. Pi will reload after this panel closes.`, tone: "success" };
|
|
309
331
|
});
|
|
@@ -312,7 +334,7 @@ export class McpSetupPanel {
|
|
|
312
334
|
if (action.id === "add-known-server" && action.preset) {
|
|
313
335
|
const preset = action.preset;
|
|
314
336
|
await this.runBusy(async () => {
|
|
315
|
-
const result = await this.callbacks.addKnownServer(preset);
|
|
337
|
+
const result = await this.callbacks.addKnownServer(preset, this.sharedConfigTarget);
|
|
316
338
|
this.callbacks.markSetupCompleted();
|
|
317
339
|
this.notice = { text: `Added ${result.serverName} to ${result.path}. Pi will reload after this panel closes.`, tone: "success" };
|
|
318
340
|
});
|
|
@@ -416,8 +438,11 @@ export class McpSetupPanel {
|
|
|
416
438
|
for (let index = start; index < end; index++) {
|
|
417
439
|
const action = actions[index];
|
|
418
440
|
if (!action) continue;
|
|
441
|
+
if (action.id === "select-shared-target" && (index === start || actions[index - 1]?.id !== "select-shared-target")) {
|
|
442
|
+
lines.push(this.padLine(fg(this.t.title, "Choose where new shared servers go"), innerW));
|
|
443
|
+
}
|
|
419
444
|
if (action.id === "add-known-server" && (index === start || actions[index - 1]?.id !== "add-known-server")) {
|
|
420
|
-
lines.push(this.padLine(fg(this.t.title,
|
|
445
|
+
lines.push(this.padLine(fg(this.t.title, `Add a known server to ${this.sharedTargetLabel()}`), innerW));
|
|
421
446
|
}
|
|
422
447
|
const selected = index === this.actionCursor;
|
|
423
448
|
const cursor = selected ? fg(this.t.selected, "›") : " ";
|
|
@@ -495,12 +520,12 @@ export class McpSetupPanel {
|
|
|
495
520
|
? ` ${this.discovery.conflicts.length} same-name conflict${this.discovery.conflicts.length === 1 ? "" : "s"} reported.`
|
|
496
521
|
: "";
|
|
497
522
|
if (!this.discovery.hasAnyConfig) {
|
|
498
|
-
return `
|
|
523
|
+
return `Add shared servers to .mcp.json for this project/team or ~/.config/mcp/mcp.json for all projects. Adopt host imports or quick-add RepoPrompt from this screen.${hostNote}${conflictNote}`;
|
|
499
524
|
}
|
|
500
525
|
if (this.discovery.totalServerCount === 0 && this.discovery.imports.length > 0) {
|
|
501
526
|
return `Detected ${this.discovery.imports.length} compatibility import source${this.discovery.imports.length === 1 ? "" : "s"}. Adopt them into Pi or inspect the underlying files.${hostNote}${conflictNote}`;
|
|
502
527
|
}
|
|
503
|
-
return `
|
|
528
|
+
return `Use .mcp.json for project/team servers or ~/.config/mcp/mcp.json for all projects. Pi-owned files are for compatibility imports and adapter-specific overrides, not another normal setup path.${hostNote}${conflictNote}`;
|
|
504
529
|
}
|
|
505
530
|
|
|
506
531
|
private visibleActionRange(total: number): { start: number; end: number } {
|
|
@@ -534,6 +559,12 @@ export class McpSetupPanel {
|
|
|
534
559
|
],
|
|
535
560
|
previewW,
|
|
536
561
|
);
|
|
562
|
+
case "select-shared-target":
|
|
563
|
+
return this.formatPreview([
|
|
564
|
+
action.target === "project" ? "Project target: .mcp.json" : "Global target: ~/.config/mcp/mcp.json",
|
|
565
|
+
"Known server presets and starter configs will be written to the selected normal MCP setup path.",
|
|
566
|
+
"Pi-owned mcp.json files remain compatibility and adapter-only override state.",
|
|
567
|
+
], previewW);
|
|
537
568
|
case "view-example":
|
|
538
569
|
return this.formatPreview([
|
|
539
570
|
"Example shared `.mcp.json`:",
|
|
@@ -546,10 +577,17 @@ export class McpSetupPanel {
|
|
|
546
577
|
" }",
|
|
547
578
|
"}",
|
|
548
579
|
"",
|
|
549
|
-
"Use Scaffold
|
|
580
|
+
"Use Scaffold selected config when you want a safe empty shell instead of a live example server.",
|
|
550
581
|
], previewW);
|
|
551
582
|
case "show-precedence":
|
|
552
583
|
return this.formatPreview([
|
|
584
|
+
"Recommended shared config:",
|
|
585
|
+
" project/team: .mcp.json",
|
|
586
|
+
" all projects: ~/.config/mcp/mcp.json",
|
|
587
|
+
"",
|
|
588
|
+
"Advanced compatibility and Pi-owned layers:",
|
|
589
|
+
" host imports, .agents files, package MCP manifests, and Pi overrides",
|
|
590
|
+
"",
|
|
553
591
|
"Read order (later entries win):",
|
|
554
592
|
"0. detected host configs (opt-in lowest-precedence fallback)",
|
|
555
593
|
"1. ~/.config/mcp/mcp.json",
|
|
@@ -570,7 +608,7 @@ export class McpSetupPanel {
|
|
|
570
608
|
: ["No config paths were detected."], previewW);
|
|
571
609
|
case "add-repoprompt": {
|
|
572
610
|
const repoPrompt = this.discovery.repoPrompt;
|
|
573
|
-
const preview = this.callbacks.previewRepoPrompt();
|
|
611
|
+
const preview = this.callbacks.previewRepoPrompt(this.sharedConfigTarget);
|
|
574
612
|
if (!preview) {
|
|
575
613
|
return this.formatPreview(["RepoPrompt is not available to add from this setup screen."], previewW);
|
|
576
614
|
}
|
|
@@ -579,7 +617,7 @@ export class McpSetupPanel {
|
|
|
579
617
|
preview,
|
|
580
618
|
[
|
|
581
619
|
`Executable: ${repoPrompt.executablePath ?? "not found"}`,
|
|
582
|
-
`Target: ${
|
|
620
|
+
`Target: ${this.sharedTargetLabel()}`,
|
|
583
621
|
`Server name: ${repoPrompt.serverName ?? "repoprompt"}`,
|
|
584
622
|
],
|
|
585
623
|
previewW,
|
|
@@ -590,17 +628,17 @@ export class McpSetupPanel {
|
|
|
590
628
|
if (!preset) return this.formatPreview(["Known server preset is unavailable."], previewW);
|
|
591
629
|
return this.formatWritePreview(
|
|
592
630
|
`${preset.name} write preview`,
|
|
593
|
-
this.callbacks.previewKnownServer(preset),
|
|
594
|
-
[preset.summary],
|
|
631
|
+
this.callbacks.previewKnownServer(preset, this.sharedConfigTarget),
|
|
632
|
+
[preset.summary, `Target: ${this.sharedTargetLabel()}`],
|
|
595
633
|
previewW,
|
|
596
634
|
);
|
|
597
635
|
}
|
|
598
|
-
case "scaffold-
|
|
636
|
+
case "scaffold-shared-config":
|
|
599
637
|
return this.formatWritePreview(
|
|
600
|
-
|
|
601
|
-
this.callbacks.
|
|
638
|
+
`${this.sharedTargetLabel()} starter write preview`,
|
|
639
|
+
this.callbacks.previewStarterConfig(this.sharedConfigTarget),
|
|
602
640
|
[
|
|
603
|
-
"This writes a minimal
|
|
641
|
+
"This writes a minimal config at the selected normal MCP setup path.",
|
|
604
642
|
"It intentionally avoids adding a fake placeholder server that would fail on first reload.",
|
|
605
643
|
],
|
|
606
644
|
previewW,
|
|
@@ -48,7 +48,9 @@ export function createMcpStatusSnapshot(state: McpExtensionState): McpStatusSnap
|
|
|
48
48
|
servers.push({
|
|
49
49
|
name,
|
|
50
50
|
status,
|
|
51
|
+
listenState: connection?.status === "connected" ? connection.listenState : "disconnected",
|
|
51
52
|
toolCount,
|
|
53
|
+
...(connection?.status === "connected" && connection.listenCatalogStale ? { catalogStale: true } : {}),
|
|
52
54
|
...(resourceCount !== undefined ? { resourceCount } : {}),
|
|
53
55
|
...(status === "failed" && failedAgoSeconds !== null ? { failedAgoSeconds } : {}),
|
|
54
56
|
disabled,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-mcp-adapter",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.32.1",
|
|
4
4
|
"description": "MCP (Model Context Protocol) adapter extension for Pi coding agent",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "./index.ts",
|
|
@@ -125,6 +125,7 @@
|
|
|
125
125
|
"mcp-status.ts",
|
|
126
126
|
"metadata-cache.ts",
|
|
127
127
|
"host-html-template.ts",
|
|
128
|
+
"sandbox-proxy-template.ts",
|
|
128
129
|
"ui-resource-handler.ts",
|
|
129
130
|
"consent-manager.ts",
|
|
130
131
|
"ui-server.ts",
|
|
@@ -19,6 +19,7 @@ import { SessionRecoveryAuthRequiredError, withSessionRecovery } from "./session
|
|
|
19
19
|
import { paginate, rankSuggestions, rankToolMatches, resolveSearchKeywords } from "./search-ranking.ts";
|
|
20
20
|
import { ensureToolCallApproved, isToolCallApprovalRequired } from "./tool-approval.ts";
|
|
21
21
|
import { isServerInActiveFailureBackoff } from "./failure-backoff.ts";
|
|
22
|
+
import { getInputRequiredNeedsUiDetails } from "./errors.ts";
|
|
22
23
|
|
|
23
24
|
type ProxyToolResult = AgentToolResult<Record<string, unknown>>;
|
|
24
25
|
type ClientCallToolResult = Awaited<ReturnType<Client["callTool"]>>;
|
|
@@ -143,22 +144,30 @@ function getAuthFailedMessage(state: McpExtensionState, serverName: string, mess
|
|
|
143
144
|
return `OAuth authentication failed for "${serverName}": ${message}. Run mcp({ action: "auth-start", server: "${serverName}" }) to get a browser URL, or /mcp-auth ${serverName} in an interactive local session.`;
|
|
144
145
|
}
|
|
145
146
|
|
|
146
|
-
function
|
|
147
|
+
function getRedirectDetails(authorizationUrl: string): { port?: number; remote: boolean } {
|
|
147
148
|
try {
|
|
148
149
|
const redirectUri = new URL(authorizationUrl).searchParams.get("redirect_uri");
|
|
149
|
-
if (!redirectUri) return
|
|
150
|
-
const
|
|
151
|
-
|
|
150
|
+
if (!redirectUri) return { remote: false };
|
|
151
|
+
const redirect = new URL(redirectUri);
|
|
152
|
+
const hostname = redirect.hostname.toLowerCase();
|
|
153
|
+
const local = hostname === "localhost" || hostname === "127.0.0.1" || hostname === "[::1]" || hostname === "::1";
|
|
154
|
+
const port = Number.parseInt(redirect.port, 10);
|
|
155
|
+
return {
|
|
156
|
+
...(Number.isInteger(port) ? { port } : {}),
|
|
157
|
+
remote: !local,
|
|
158
|
+
};
|
|
152
159
|
} catch {
|
|
153
|
-
return
|
|
160
|
+
return { remote: false };
|
|
154
161
|
}
|
|
155
162
|
}
|
|
156
163
|
|
|
157
164
|
function formatManualAuthInstructions(serverName: string, authorizationUrl: string): string {
|
|
158
|
-
const
|
|
159
|
-
const
|
|
160
|
-
?
|
|
161
|
-
:
|
|
165
|
+
const redirect = getRedirectDetails(authorizationUrl);
|
|
166
|
+
const redirectNote = redirect.remote
|
|
167
|
+
? "The provider uses a pre-registered HTTPS callback. Copy its full URL from the browser address bar, even if the destination page reports an error."
|
|
168
|
+
: redirect.port
|
|
169
|
+
? `The redirect URL will use local port ${redirect.port}. On a remote server it is expected for that localhost page to fail locally; copy the address bar URL anyway.`
|
|
170
|
+
: "";
|
|
162
171
|
|
|
163
172
|
return [
|
|
164
173
|
`MCP OAuth required for "${serverName}".`,
|
|
@@ -167,11 +176,13 @@ function formatManualAuthInstructions(serverName: string, authorizationUrl: stri
|
|
|
167
176
|
"",
|
|
168
177
|
authorizationUrl,
|
|
169
178
|
"",
|
|
170
|
-
"After approving, copy the full
|
|
179
|
+
"After approving, copy the full callback URL from your browser address bar and send it back with:",
|
|
171
180
|
`mcp({ action: "auth-complete", server: "${serverName}", args: { redirectUrl: "PASTE_REDIRECT_URL_HERE" } })`,
|
|
172
181
|
"",
|
|
173
|
-
|
|
174
|
-
|
|
182
|
+
redirect.remote
|
|
183
|
+
? "Remote HTTPS callbacks must include the full callback URL so the OAuth state can be checked. JSON-string args remain supported."
|
|
184
|
+
: 'You can also pass just the `code` query parameter as `args: { code: "PASTE_CODE_HERE" }`. JSON-string args remain supported.',
|
|
185
|
+
redirectNote,
|
|
175
186
|
].filter(Boolean).join("\n");
|
|
176
187
|
}
|
|
177
188
|
|
|
@@ -329,7 +340,7 @@ export function executeUiMessages(state: McpExtensionState): ProxyToolResult {
|
|
|
329
340
|
}
|
|
330
341
|
|
|
331
342
|
export function executeStatus(state: McpExtensionState): ProxyToolResult {
|
|
332
|
-
const servers: Array<{ name: string; status: string; toolCount: number; failedAgo: number | null; disabled?: boolean }> = [];
|
|
343
|
+
const servers: Array<{ name: string; status: string; listenState: string; catalogStale?: boolean; toolCount: number; failedAgo: number | null; disabled?: boolean }> = [];
|
|
333
344
|
|
|
334
345
|
for (const name of Object.keys(state.config.mcpServers)) {
|
|
335
346
|
const definition = state.config.mcpServers[name];
|
|
@@ -350,7 +361,16 @@ export function executeStatus(state: McpExtensionState): ProxyToolResult {
|
|
|
350
361
|
|
|
351
362
|
const toolCount = status === "failed" ? 0 : metadata?.length ?? 0;
|
|
352
363
|
|
|
353
|
-
|
|
364
|
+
const listenState = connection?.status === "connected" ? connection.listenState : "disconnected";
|
|
365
|
+
servers.push({
|
|
366
|
+
name,
|
|
367
|
+
status,
|
|
368
|
+
listenState,
|
|
369
|
+
...(connection?.status === "connected" && connection.listenCatalogStale ? { catalogStale: true } : {}),
|
|
370
|
+
toolCount,
|
|
371
|
+
failedAgo,
|
|
372
|
+
...(disabled ? { disabled: true } : {}),
|
|
373
|
+
});
|
|
354
374
|
}
|
|
355
375
|
|
|
356
376
|
const disabledCount = servers.filter(s => s.disabled).length;
|
|
@@ -367,7 +387,18 @@ export function executeStatus(state: McpExtensionState): ProxyToolResult {
|
|
|
367
387
|
continue;
|
|
368
388
|
}
|
|
369
389
|
if (server.status === "connected") {
|
|
370
|
-
|
|
390
|
+
const listen = server.listenState === "active"
|
|
391
|
+
? server.catalogStale
|
|
392
|
+
? ", listen active, catalog may be stale"
|
|
393
|
+
: ", listen active"
|
|
394
|
+
: server.listenState === "dropped"
|
|
395
|
+
? ", catalog may be stale; will reconcile on next keep-alive or tool use"
|
|
396
|
+
: server.listenState === "re-establishing"
|
|
397
|
+
? ", re-establishing listen"
|
|
398
|
+
: server.listenState === "legacy"
|
|
399
|
+
? ", legacy notification path"
|
|
400
|
+
: ", not listening for catalog updates";
|
|
401
|
+
text += `✓ ${server.name} (${server.toolCount} tools${listen})\n`;
|
|
371
402
|
continue;
|
|
372
403
|
}
|
|
373
404
|
if (server.status === "needs-auth") {
|
|
@@ -375,14 +406,19 @@ export function executeStatus(state: McpExtensionState): ProxyToolResult {
|
|
|
375
406
|
continue;
|
|
376
407
|
}
|
|
377
408
|
if (server.status === "cached") {
|
|
378
|
-
text += `○ ${server.name} (${server.toolCount} tools, cached)\n`;
|
|
409
|
+
text += `○ ${server.name} (${server.toolCount} tools, cached; not listening)\n`;
|
|
379
410
|
continue;
|
|
380
411
|
}
|
|
381
412
|
if (server.status === "failed") {
|
|
382
413
|
text += `✗ ${server.name} (failed ${server.failedAgo ?? 0}s ago)\n`;
|
|
383
414
|
continue;
|
|
384
415
|
}
|
|
385
|
-
text += `○ ${server.name} (not
|
|
416
|
+
text += `○ ${server.name} (not listening; disconnected)\n`;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
const directToolsFrozen = state.config.settings?.freezeDirectTools === true;
|
|
420
|
+
if (directToolsFrozen) {
|
|
421
|
+
text += "\nDirect tools frozen; active registrations may differ from current metadata.\n";
|
|
386
422
|
}
|
|
387
423
|
|
|
388
424
|
if (servers.length > 0) {
|
|
@@ -391,7 +427,7 @@ export function executeStatus(state: McpExtensionState): ProxyToolResult {
|
|
|
391
427
|
|
|
392
428
|
return {
|
|
393
429
|
content: [{ type: "text" as const, text: text.trim() }],
|
|
394
|
-
details: { mode: "status", servers, totalTools, connectedCount, disabledCount },
|
|
430
|
+
details: { mode: "status", servers, totalTools, connectedCount, disabledCount, directToolsFrozen },
|
|
395
431
|
};
|
|
396
432
|
}
|
|
397
433
|
|
|
@@ -741,7 +777,17 @@ export function executeList(state: McpExtensionState, server: string): ProxyTool
|
|
|
741
777
|
};
|
|
742
778
|
}
|
|
743
779
|
|
|
744
|
-
|
|
780
|
+
// "not connected" alone reads as an outage while the tools listed below are
|
|
781
|
+
// real and the connection is simply lazy (tools served from cache).
|
|
782
|
+
// Distinguish auth from plain laziness so the caller knows which remedy applies.
|
|
783
|
+
let cachedNote = "";
|
|
784
|
+
if (connection?.status !== "connected") {
|
|
785
|
+
if (connection?.status === "needs-auth") {
|
|
786
|
+
cachedNote = ` (needs auth — run mcp({ action: "auth-start", server: "${server}" }))`;
|
|
787
|
+
} else {
|
|
788
|
+
cachedNote = ` (lazy: tools from cache, not connected yet — mcp({ connect: "${server}" }) to connect)`;
|
|
789
|
+
}
|
|
790
|
+
}
|
|
745
791
|
let text = `${server} (${toolNames.length} tools${cachedNote}):\n\n`;
|
|
746
792
|
|
|
747
793
|
const descMap = new Map<string, string>();
|
|
@@ -1290,7 +1336,13 @@ export async function executeCall(
|
|
|
1290
1336
|
onNeedsAuth: recoverAuthConnection,
|
|
1291
1337
|
},
|
|
1292
1338
|
serverName,
|
|
1293
|
-
(conn) =>
|
|
1339
|
+
async (conn) => {
|
|
1340
|
+
const refreshRead = await state.manager.prepareResourceUse?.(serverName, toolMeta.resourceUri!, conn);
|
|
1341
|
+
return conn.client.readResource(
|
|
1342
|
+
{ uri: toolMeta.resourceUri! },
|
|
1343
|
+
refreshRead ? { ...requestOptions, cacheMode: "refresh" } : requestOptions,
|
|
1344
|
+
);
|
|
1345
|
+
},
|
|
1294
1346
|
);
|
|
1295
1347
|
const content = transformMcpResourceContents(result.contents ?? [], state.owner?.signal);
|
|
1296
1348
|
const guarded = await guardMcpOutput(content.length > 0 ? content : [{ type: "text" as const, text: "(empty resource)" }], outputGuardOptions);
|
|
@@ -1320,11 +1372,14 @@ export async function executeCall(
|
|
|
1320
1372
|
onNeedsAuth: recoverAuthConnection,
|
|
1321
1373
|
},
|
|
1322
1374
|
serverName,
|
|
1323
|
-
(conn) =>
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1375
|
+
async (conn) => {
|
|
1376
|
+
await state.manager.ensureListen?.(serverName, conn);
|
|
1377
|
+
return abortable(conn.client.callTool({
|
|
1378
|
+
name: toolMeta.originalName,
|
|
1379
|
+
arguments: normalizedArgs,
|
|
1380
|
+
_meta: uiSession?.requestMeta,
|
|
1381
|
+
}, requestOptions), ownedSignal);
|
|
1382
|
+
},
|
|
1328
1383
|
);
|
|
1329
1384
|
|
|
1330
1385
|
if (toolMeta.uiResourceUri) {
|
|
@@ -1398,6 +1453,14 @@ export async function executeCall(
|
|
|
1398
1453
|
details: { mode: "call", error: "url_elicitation_required", ...callIdentity, action },
|
|
1399
1454
|
};
|
|
1400
1455
|
}
|
|
1456
|
+
const inputRequired = getInputRequiredNeedsUiDetails(error, callIdentity);
|
|
1457
|
+
if (inputRequired) {
|
|
1458
|
+
uiSession?.sendToolCancelled(inputRequired.message);
|
|
1459
|
+
return {
|
|
1460
|
+
content: [{ type: "text" as const, text: inputRequired.message }],
|
|
1461
|
+
details: { mode: "call", ...inputRequired },
|
|
1462
|
+
};
|
|
1463
|
+
}
|
|
1401
1464
|
const message = error instanceof Error ? error.message : String(error);
|
|
1402
1465
|
uiSession?.sendToolCancelled(message);
|
|
1403
1466
|
|