@ashx-j/lunr-dev 0.2.16-dev.9.1 → 0.2.21-dev.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +67 -1
- package/README.md +7 -1
- package/dist/builtin-extensions/ashxj-thinking.d.ts +1 -0
- package/dist/builtin-extensions/ashxj-thinking.d.ts.map +1 -1
- package/dist/builtin-extensions/ashxj-thinking.js +44 -19
- package/dist/builtin-extensions/ashxj-thinking.js.map +1 -1
- package/dist/builtin-extensions/index.d.ts.map +1 -1
- package/dist/builtin-extensions/index.js +1 -2
- package/dist/builtin-extensions/index.js.map +1 -1
- package/dist/builtin-extensions/lunr-computer-use.d.ts +3 -0
- package/dist/builtin-extensions/lunr-computer-use.d.ts.map +1 -0
- package/dist/builtin-extensions/lunr-computer-use.js +158 -0
- package/dist/builtin-extensions/lunr-computer-use.js.map +1 -0
- package/dist/builtin-extensions/lunr-todos.d.ts +6 -5
- package/dist/builtin-extensions/lunr-todos.d.ts.map +1 -1
- package/dist/builtin-extensions/lunr-todos.js +9 -7
- package/dist/builtin-extensions/lunr-todos.js.map +1 -1
- package/dist/builtin-extensions/pi-intercom/broker/spawn.d.ts +6 -4
- package/dist/builtin-extensions/pi-intercom/broker/spawn.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-intercom/broker/spawn.js +114 -61
- package/dist/builtin-extensions/pi-intercom/broker/spawn.js.map +1 -1
- package/dist/builtin-extensions/pi-intercom/index.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-intercom/index.js +360 -351
- package/dist/builtin-extensions/pi-intercom/index.js.map +1 -1
- package/dist/builtin-extensions/pi-lsp-extension/src/index.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-lsp-extension/src/index.js +10 -3
- package/dist/builtin-extensions/pi-lsp-extension/src/index.js.map +1 -1
- package/dist/builtin-extensions/pi-lsp-extension/src/runtime.d.ts +5 -1
- package/dist/builtin-extensions/pi-lsp-extension/src/runtime.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-lsp-extension/src/runtime.js +26 -4
- package/dist/builtin-extensions/pi-lsp-extension/src/runtime.js.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/index.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/index.js +37 -27
- package/dist/builtin-extensions/pi-mcp-adapter/index.js.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/server-manager.d.ts +6 -1
- package/dist/builtin-extensions/pi-mcp-adapter/server-manager.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/server-manager.js +33 -8
- package/dist/builtin-extensions/pi-mcp-adapter/server-manager.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/fanout-child.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/fanout-child.js +2 -2
- package/dist/builtin-extensions/pi-subagents/src/extension/fanout-child.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/index.d.ts +8 -6
- package/dist/builtin-extensions/pi-subagents/src/extension/index.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/index.js +179 -79
- package/dist/builtin-extensions/pi-subagents/src/extension/index.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/schemas.d.ts +18 -8
- package/dist/builtin-extensions/pi-subagents/src/extension/schemas.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/schemas.js +44 -15
- package/dist/builtin-extensions/pi-subagents/src/extension/schemas.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.d.ts +4 -3
- package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.js +24 -14
- package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/intercom/native-supervisor-channel.d.ts +8 -1
- package/dist/builtin-extensions/pi-subagents/src/intercom/native-supervisor-channel.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/intercom/native-supervisor-channel.js +247 -18
- package/dist/builtin-extensions/pi-subagents/src/intercom/native-supervisor-channel.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/intercom/result-intercom.d.ts +1 -0
- package/dist/builtin-extensions/pi-subagents/src/intercom/result-intercom.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/intercom/result-intercom.js +1 -1
- package/dist/builtin-extensions/pi-subagents/src/intercom/result-intercom.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-ask.d.ts +29 -0
- package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-ask.d.ts.map +1 -0
- package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-ask.js +179 -0
- package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-ask.js.map +1 -0
- package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-questions.d.ts +89 -0
- package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-questions.d.ts.map +1 -0
- package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-questions.js +541 -0
- package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-questions.js.map +1 -0
- package/dist/builtin-extensions/pi-subagents/src/runs/background/async-execution.d.ts +11 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/async-execution.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/async-execution.js +38 -12
- package/dist/builtin-extensions/pi-subagents/src/runs/background/async-execution.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/async-job-tracker.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/async-job-tracker.js +3 -2
- package/dist/builtin-extensions/pi-subagents/src/runs/background/async-job-tracker.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/async-resume.d.ts +2 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/async-resume.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/async-resume.js +35 -8
- package/dist/builtin-extensions/pi-subagents/src/runs/background/async-resume.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/notify.d.ts +7 -3
- package/dist/builtin-extensions/pi-subagents/src/runs/background/notify.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/notify.js +26 -4
- package/dist/builtin-extensions/pi-subagents/src/runs/background/notify.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/result-watcher.d.ts +1 -0
- package/dist/builtin-extensions/pi-subagents/src/runs/background/result-watcher.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/result-watcher.js +55 -38
- package/dist/builtin-extensions/pi-subagents/src/runs/background/result-watcher.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-runner.d.ts +100 -0
- package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-runner.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-runner.js +46 -31
- package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-runner.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-wait.d.ts +3 -6
- package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-wait.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-wait.js +64 -5
- package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-wait.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/top-level-async.d.ts +15 -2
- package/dist/builtin-extensions/pi-subagents/src/runs/background/top-level-async.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/top-level-async.js +14 -4
- package/dist/builtin-extensions/pi-subagents/src/runs/background/top-level-async.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/wait-tool.d.ts +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/wait-tool.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/wait-tool.js +7 -3
- package/dist/builtin-extensions/pi-subagents/src/runs/background/wait-tool.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-execution.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-execution.js +21 -8
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-execution.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/execution.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/execution.js +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/execution.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/request-params.d.ts +10 -0
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/request-params.d.ts.map +1 -0
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/request-params.js +38 -0
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/request-params.js.map +1 -0
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.d.ts +0 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.js +74 -41
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/acceptance.d.ts +2 -0
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/acceptance.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/acceptance.js +75 -18
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/acceptance.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/child-tools.d.ts +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/child-tools.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/child-tools.js +2 -0
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/child-tools.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/completion-guard.d.ts +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/completion-guard.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/completion-guard.js +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/completion-guard.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.d.ts +13 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.js +67 -11
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.d.ts +1 -0
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/pi-args.d.ts +3 -0
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/pi-args.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/pi-args.js +7 -2
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/pi-args.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.js +13 -3
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/task-intent.d.ts +2 -2
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/task-intent.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/task-intent.js +5 -10
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/task-intent.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/shared/async-guidance.d.ts +2 -0
- package/dist/builtin-extensions/pi-subagents/src/shared/async-guidance.d.ts.map +1 -0
- package/dist/builtin-extensions/pi-subagents/src/shared/async-guidance.js +3 -0
- package/dist/builtin-extensions/pi-subagents/src/shared/async-guidance.js.map +1 -0
- package/dist/builtin-extensions/pi-subagents/src/shared/child-spec.d.ts +3 -0
- package/dist/builtin-extensions/pi-subagents/src/shared/child-spec.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/shared/child-spec.js +68 -11
- package/dist/builtin-extensions/pi-subagents/src/shared/child-spec.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/shared/formatters.d.ts +12 -1
- package/dist/builtin-extensions/pi-subagents/src/shared/formatters.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/shared/formatters.js +21 -2
- package/dist/builtin-extensions/pi-subagents/src/shared/formatters.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/shared/types.d.ts +21 -4
- package/dist/builtin-extensions/pi-subagents/src/shared/types.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/shared/types.js +1 -1
- package/dist/builtin-extensions/pi-subagents/src/shared/types.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/slash/delegation-adapters.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/slash/delegation-adapters.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.d.ts +7 -0
- package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.js +11 -7
- package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.d.ts +6 -0
- package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.js +46 -29
- package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/tui/render.d.ts +47 -4
- package/dist/builtin-extensions/pi-subagents/src/tui/render.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/tui/render.js +428 -431
- package/dist/builtin-extensions/pi-subagents/src/tui/render.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/watchdog/register-main.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/watchdog/register-main.js +1 -1
- package/dist/builtin-extensions/pi-subagents/src/watchdog/register-main.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/watchdog/tool-actions.d.ts +2 -13
- package/dist/builtin-extensions/pi-subagents/src/watchdog/tool-actions.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/watchdog/tool-actions.js +5 -91
- package/dist/builtin-extensions/pi-subagents/src/watchdog/tool-actions.js.map +1 -1
- package/dist/builtin-extensions/pi-web-access/index.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-web-access/index.js +103 -102
- package/dist/builtin-extensions/pi-web-access/index.js.map +1 -1
- package/dist/core/agent-session-services.d.ts.map +1 -1
- package/dist/core/agent-session-services.js +1 -1
- package/dist/core/agent-session-services.js.map +1 -1
- package/dist/core/computer-use/adapter.d.ts +23 -0
- package/dist/core/computer-use/adapter.d.ts.map +1 -0
- package/dist/core/computer-use/adapter.js +116 -0
- package/dist/core/computer-use/adapter.js.map +1 -0
- package/dist/core/computer-use/image.d.ts +26 -0
- package/dist/core/computer-use/image.d.ts.map +1 -0
- package/dist/core/computer-use/image.js +64 -0
- package/dist/core/computer-use/image.js.map +1 -0
- package/dist/core/computer-use/lease.d.ts +18 -0
- package/dist/core/computer-use/lease.d.ts.map +1 -0
- package/dist/core/computer-use/lease.js +129 -0
- package/dist/core/computer-use/lease.js.map +1 -0
- package/dist/core/computer-use/macos-runtime.d.ts +14 -0
- package/dist/core/computer-use/macos-runtime.d.ts.map +1 -0
- package/dist/core/computer-use/macos-runtime.js +148 -0
- package/dist/core/computer-use/macos-runtime.js.map +1 -0
- package/dist/core/computer-use/policy.d.ts +19 -0
- package/dist/core/computer-use/policy.d.ts.map +1 -0
- package/dist/core/computer-use/policy.js +62 -0
- package/dist/core/computer-use/policy.js.map +1 -0
- package/dist/core/computer-use/release.generated.d.ts +31 -0
- package/dist/core/computer-use/release.generated.d.ts.map +1 -0
- package/dist/core/computer-use/release.generated.js +36 -0
- package/dist/core/computer-use/release.generated.js.map +1 -0
- package/dist/core/computer-use/runtime.d.ts +13 -0
- package/dist/core/computer-use/runtime.d.ts.map +1 -0
- package/dist/core/computer-use/runtime.js +158 -0
- package/dist/core/computer-use/runtime.js.map +1 -0
- package/dist/core/computer-use/schemas.d.ts +91 -0
- package/dist/core/computer-use/schemas.d.ts.map +1 -0
- package/dist/core/computer-use/schemas.js +71 -0
- package/dist/core/computer-use/schemas.js.map +1 -0
- package/dist/core/computer-use/windows-desktop.d.ts +3 -0
- package/dist/core/computer-use/windows-desktop.d.ts.map +1 -0
- package/dist/core/computer-use/windows-desktop.js +48 -0
- package/dist/core/computer-use/windows-desktop.js.map +1 -0
- package/dist/core/computer-use/workflow.d.ts +32 -0
- package/dist/core/computer-use/workflow.d.ts.map +1 -0
- package/dist/core/computer-use/workflow.js +341 -0
- package/dist/core/computer-use/workflow.js.map +1 -0
- package/dist/core/customize.d.ts +2 -0
- package/dist/core/customize.d.ts.map +1 -1
- package/dist/core/customize.js +3 -0
- package/dist/core/customize.js.map +1 -1
- package/dist/core/keybindings.d.ts +2 -2
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +2 -2
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/model-runtime.d.ts +0 -3
- package/dist/core/model-runtime.d.ts.map +1 -1
- package/dist/core/model-runtime.js +1 -10
- package/dist/core/model-runtime.js.map +1 -1
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +1 -1
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/permissions.d.ts +2 -1
- package/dist/core/permissions.d.ts.map +1 -1
- package/dist/core/permissions.js +31 -11
- package/dist/core/permissions.js.map +1 -1
- package/dist/core/plan-mode.d.ts.map +1 -1
- package/dist/core/plan-mode.js +9 -5
- package/dist/core/plan-mode.js.map +1 -1
- package/dist/core/rollback.d.ts.map +1 -1
- package/dist/core/rollback.js +13 -90
- package/dist/core/rollback.js.map +1 -1
- package/dist/core/runtime-bridges.d.ts.map +1 -1
- package/dist/core/runtime-bridges.js +0 -2
- package/dist/core/runtime-bridges.js.map +1 -1
- package/dist/core/session-manager.d.ts +0 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +21 -79
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +10 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +30 -0
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/subagent-cancellation.d.ts +21 -0
- package/dist/core/subagent-cancellation.d.ts.map +1 -0
- package/dist/core/subagent-cancellation.js +53 -0
- package/dist/core/subagent-cancellation.js.map +1 -0
- package/dist/core/subagent-spinner-setting.d.ts +6 -0
- package/dist/core/subagent-spinner-setting.d.ts.map +1 -0
- package/dist/core/subagent-spinner-setting.js +12 -0
- package/dist/core/subagent-spinner-setting.js.map +1 -0
- package/dist/core/subagent-spinner.d.ts +4 -0
- package/dist/core/subagent-spinner.d.ts.map +1 -0
- package/dist/core/subagent-spinner.js +6 -0
- package/dist/core/subagent-spinner.js.map +1 -0
- package/dist/dev-cli.js +0 -0
- package/dist/gateway/agent-bridge.d.ts +6 -1
- package/dist/gateway/agent-bridge.d.ts.map +1 -1
- package/dist/gateway/agent-bridge.js +23 -6
- package/dist/gateway/agent-bridge.js.map +1 -1
- package/dist/gateway/cron.d.ts +1 -1
- package/dist/gateway/cron.d.ts.map +1 -1
- package/dist/gateway/cron.js +23 -7
- package/dist/gateway/cron.js.map +1 -1
- package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/assistant-message.js +12 -18
- package/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts +4 -2
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +23 -32
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/processes-selector.d.ts +2 -3
- package/dist/modes/interactive/components/processes-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/processes-selector.js +5 -10
- package/dist/modes/interactive/components/processes-selector.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts +8 -0
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +93 -1
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +12 -0
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/extension-widget-order.d.ts +8 -0
- package/dist/modes/interactive/extension-widget-order.d.ts.map +1 -0
- package/dist/modes/interactive/extension-widget-order.js +37 -0
- package/dist/modes/interactive/extension-widget-order.js.map +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +58 -26
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/thinking-level-slash.d.ts +4 -0
- package/dist/modes/interactive/thinking-level-slash.d.ts.map +1 -0
- package/dist/modes/interactive/thinking-level-slash.js +23 -0
- package/dist/modes/interactive/thinking-level-slash.js.map +1 -0
- package/dist/node-runtime/adapter-AZMY335J.js +279 -0
- package/dist/node-runtime/{agent-session-services-IFJMSX7Z.js → agent-session-services-QANFGM2V.js} +15 -11
- package/dist/node-runtime/{builtin-extensions-LYZ3BFWQ.js → builtin-extensions-SRCYQPZ6.js} +5 -3
- package/dist/node-runtime/chunk-2IDTZAG5.js +1415 -0
- package/dist/node-runtime/chunk-3ONQTOMR.js +68 -0
- package/dist/node-runtime/{chunk-TQNSPERU.js → chunk-5SQDLSZJ.js} +1 -1
- package/dist/node-runtime/chunk-5ZH3ZFIZ.js +308 -0
- package/dist/node-runtime/{chunk-PBC2Y6GS.js → chunk-6UB6NKA3.js} +29 -72
- package/dist/node-runtime/{chunk-A2KQXUJD.js → chunk-7AFOFSDY.js} +1 -1
- package/dist/node-runtime/chunk-A3KMVBZV.js +60 -0
- package/dist/node-runtime/{chunk-N77MY65L.js → chunk-BJ6H7DPI.js} +25 -25
- package/dist/node-runtime/{chunk-PGAJ5MO5.js → chunk-BYQ2MOFI.js} +6 -6
- package/dist/node-runtime/{chunk-QH42CDX3.js → chunk-CZUBYPFP.js} +234 -124
- package/dist/node-runtime/{chunk-LZAW4ZX3.js → chunk-D466UAID.js} +34 -13
- package/dist/node-runtime/{chunk-ZKMFUD3Q.js → chunk-GT5F3OKM.js} +3 -3
- package/dist/node-runtime/chunk-H2BI7G7T.js +73 -0
- package/dist/node-runtime/{chunk-5P7PZMRU.js → chunk-HRS4HMDX.js} +1 -1
- package/dist/node-runtime/{chunk-IPA627GP.js → chunk-HXJS2PJM.js} +4 -4
- package/dist/node-runtime/chunk-JZHEUQRL.js +180 -0
- package/dist/node-runtime/chunk-LISUTZS3.js +19 -0
- package/dist/node-runtime/chunk-LOYUC2ID.js +2185 -0
- package/dist/node-runtime/{chunk-2QKLKMKC.js → chunk-LTXUQJI4.js} +1 -1
- package/dist/node-runtime/{chunk-YF63P5ZT.js → chunk-LTYWTR3V.js} +1 -426
- package/dist/node-runtime/{chunk-MKKH27PH.js → chunk-LWJXTA6Z.js} +274 -2416
- package/dist/node-runtime/chunk-MW2XJZIK.js +108 -0
- package/dist/node-runtime/{chunk-CDFZEWPU.js → chunk-N3PNL74S.js} +537 -262
- package/dist/node-runtime/{chunk-4TLO4PO2.js → chunk-U6C7VTR5.js} +7 -1401
- package/dist/node-runtime/chunk-URD2SLIT.js +1019 -0
- package/dist/node-runtime/{chunk-HQCKFM2O.js → chunk-VGYZ3APQ.js} +3 -0
- package/dist/node-runtime/{chunk-AJX357CL.js → chunk-VQ4UBWSA.js} +30 -1013
- package/dist/node-runtime/{chunk-F4VQFJI2.js → chunk-VTGEKB7R.js} +2 -2
- package/dist/node-runtime/{chunk-AD6VXAO7.js → chunk-VTPM5V35.js} +5 -100
- package/dist/node-runtime/chunk-W3SILANP.js +24 -0
- package/dist/node-runtime/{chunk-WOVTOV5P.js → chunk-XAUQOKYK.js} +421 -63
- package/dist/node-runtime/{chunk-ECD5L7YI.js → chunk-XSRCAQK2.js} +390 -16
- package/dist/node-runtime/{chunk-PCGNAY2O.js → chunk-ZOIIMEN6.js} +54 -433
- package/dist/node-runtime/{chunk-EDBJNRSM.js → chunk-ZVSORYRM.js} +1 -1
- package/dist/node-runtime/cli-runtime.js +1 -1
- package/dist/node-runtime/{command-L3LAHDIH.js → command-ZURZJDXF.js} +1 -1
- package/dist/node-runtime/{commands-RL5YBW5I.js → commands-BZGSLIP7.js} +4 -2
- package/dist/node-runtime/{customize-XEXL2DGQ.js → customize-LF5VST47.js} +1 -1
- package/dist/node-runtime/{direct-tool-executor-JVDXTO7A.js → direct-tool-executor-BSZDHIYR.js} +7 -4
- package/dist/node-runtime/{export-html-KR26FOUZ.js → export-html-E4DT6ZJQ.js} +1 -1
- package/dist/node-runtime/{gateway-X2TI5X7F.js → gateway-FWHRIBK5.js} +24 -369
- package/dist/node-runtime/index.js +49 -42
- package/dist/node-runtime/{init-NJV2T55N.js → init-DVJUAOUO.js} +4 -2
- package/dist/node-runtime/{interactive-mode-KOM35YF2.js → interactive-mode-BBASNWHN.js} +23 -17
- package/dist/node-runtime/{interactive-view-U6OILKF3.js → interactive-view-N6F4KUIT.js} +3 -5
- package/dist/node-runtime/lunr-computer-use-TJNDAMWM.js +135 -0
- package/dist/node-runtime/{lunr-cron-YJ5UHYRD.js → lunr-cron-J64I72C6.js} +7 -1
- package/dist/node-runtime/main.js +25 -20
- package/dist/node-runtime/{mcp-auth-flow-QIXHW6QN.js → mcp-auth-flow-YL6RWPYG.js} +2 -1
- package/dist/node-runtime/{package-manager-cli-TZZHJCVI.js → package-manager-cli-VMYX4Y2S.js} +10 -7
- package/dist/node-runtime/{pi-intercom-EEMBGQID.js → pi-intercom-NV2LW6X7.js} +108 -87
- package/dist/node-runtime/{pi-mcp-adapter-QFB37AVN.js → pi-mcp-adapter-JLB5YL2F.js} +31 -25
- package/dist/node-runtime/{pi-subagents-7XJ4H53P.js → pi-subagents-WEHV3W7H.js} +1321 -631
- package/dist/node-runtime/{pi-web-access-DPGAVKOA.js → pi-web-access-FN5YC5T6.js} +67 -64
- package/dist/node-runtime/{proxy-modes-HEEFK4KC.js → proxy-modes-OR7ISBXK.js} +7 -4
- package/dist/node-runtime/rpc-entry.js +25 -20
- package/dist/node-runtime/runtime-3SB5ATHQ.js +21 -0
- package/dist/node-runtime/{runtime-bridges-PPHNBFWL.js → runtime-bridges-2VQTLPOZ.js} +3 -5
- package/dist/node-runtime/{session-manager-MQNBYACL.js → session-manager-QEMZBMTM.js} +3 -5
- package/dist/node-runtime/{session-selector-5AZLJS6U.js → session-selector-URVJLOTK.js} +2 -2
- package/dist/node-runtime/{settings-manager-5LF2VQWC.js → settings-manager-3CCU326G.js} +4 -1
- package/dist/node-runtime/{src-Y7JSCK64.js → src-BPQFJR76.js} +27 -7
- package/dist/node-runtime/{subagent-executor-5RNDEPIJ.js → subagent-executor-CXKXQDHH.js} +189 -284
- package/dist/node-runtime/{update-cli-A253SZ7P.js → update-cli-NM7B4CKL.js} +4 -1
- package/dist/node-runtime/workflow-C26QCUTW.js +468 -0
- package/dist/rpc.d.ts +3 -0
- package/dist/rpc.d.ts.map +1 -0
- package/dist/rpc.js +18 -0
- package/dist/rpc.js.map +1 -0
- package/dist/startup/interactive-view.d.ts.map +1 -1
- package/dist/startup/interactive-view.js +1 -2
- package/dist/startup/interactive-view.js.map +1 -1
- package/docs/computer-use.md +242 -0
- package/docs/development.md +0 -32
- package/docs/features.md +24 -6
- package/docs/interactive-startup.md +10 -3
- package/docs/keybindings.md +5 -3
- package/docs/settings.md +3 -2
- package/docs/terminal-setup.md +1 -1
- package/docs/usage.md +1 -1
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/gondolin/package-lock.json +2 -2
- package/examples/extensions/gondolin/package.json +1 -1
- package/examples/extensions/hidden-thinking-label.ts +1 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/install-lock/package-lock.json +3827 -0
- package/install-lock/package.json +18 -0
- package/native/computer-use/LICENSE.md +21 -0
- package/npm-shrinkwrap.json +3808 -0
- package/package.json +16 -10
- package/dist/builtin-extensions/lunr-settings-tools.d.ts +0 -4
- package/dist/builtin-extensions/lunr-settings-tools.d.ts.map +0 -1
- package/dist/builtin-extensions/lunr-settings-tools.js +0 -120
- package/dist/builtin-extensions/lunr-settings-tools.js.map +0 -1
- package/dist/core/settings-tools-bridge.d.ts +0 -35
- package/dist/core/settings-tools-bridge.d.ts.map +0 -1
- package/dist/core/settings-tools-bridge.js +0 -56
- package/dist/core/settings-tools-bridge.js.map +0 -1
- package/dist/node-runtime/chunk-AHSTJBIB.js +0 -64
- package/dist/startup/interactive-shell.d.ts +0 -55
- package/dist/startup/interactive-shell.d.ts.map +0 -1
- package/dist/startup/interactive-shell.js +0 -264
- package/dist/startup/interactive-shell.js.map +0 -1
- package/dist/node-runtime/{chunk-YSKSB3BJ.js → chunk-CH6OL6P2.js} +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/builtin-extensions/pi-mcp-adapter/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAA8B,MAAM,iCAAiC,CAAC;AAqChG,MAAM,CAAC,OAAO,UAAU,UAAU,CAAC,EAAE,EAAE,YAAY,QA2flD","sourcesContent":["// @ts-nocheck\nimport type { ExtensionAPI, ExtensionContext, ToolInfo } from \"@ashx-j/lunr-dev\";\nimport type { McpExtensionState } from \"./state.ts\";\nimport type { DirectToolSpec, McpConfig } from \"./types.ts\";\nimport type { MetadataCache } from \"./metadata-cache.ts\";\nimport { existsSync } from \"node:fs\";\nimport { Type } from \"typebox\";\nimport { loadMcpConfig } from \"./config.ts\";\nimport { buildProxyDescription, getMissingConfiguredDirectToolServers, resolveDirectTools } from \"./direct-tools.ts\";\nimport { getMetadataCachePath, loadMetadataCache } from \"./metadata-cache.ts\";\nimport { getConfigPathFromArgv, normalizeDirectToolInputSchema, truncateAtWord } from \"./utils.ts\";\nimport { createMcpDirectToolCallRenderer, renderMcpProxyToolCall, renderMcpToolResult } from \"./tool-result-renderer.ts\";\nimport { toolErrorOverride } from \"./error-signal.ts\";\nimport { abortable, throwIfAborted } from \"./abort.ts\";\n\ntype McpHeavyModules = {\n init: typeof import(\"./init.ts\");\n authFlow: typeof import(\"./mcp-auth-flow.ts\");\n commands: typeof import(\"./commands.ts\");\n proxyModes: typeof import(\"./proxy-modes.ts\");\n directToolExecutor: typeof import(\"./direct-tool-executor.ts\");\n};\n\nfunction shouldBackgroundAutostart(config: McpConfig, cache: MetadataCache | null): boolean {\n const serverEntries = Object.entries(config.mcpServers);\n if (serverEntries.length === 0) return false;\n\n if (!existsSync(getMetadataCachePath())) return true;\n\n for (const [, definition] of serverEntries) {\n const mode = definition.lifecycle ?? \"lazy\";\n if (mode === \"keep-alive\" || mode === \"eager\") return true;\n }\n\n if (process.env.MCP_DIRECT_TOOLS === \"__none__\") return false;\n return getMissingConfiguredDirectToolServers(config, cache).length > 0;\n}\n\nexport default function mcpAdapter(pi: ExtensionAPI) {\n let state: McpExtensionState | null = null;\n let initPromise: Promise<McpExtensionState> | null = null;\n let lifecycleGeneration = 0;\n let sessionAbort = new AbortController();\n const initializingStates = new Set<McpExtensionState>();\n let heavyModules: McpHeavyModules | null = null;\n let heavyModulesPromise: Promise<McpHeavyModules> | null = null;\n const directExecutors = new Map<string, ReturnType<McpHeavyModules[\"directToolExecutor\"][\"createDirectToolExecutor\"]>>();\n\n function loadHeavyModules(): Promise<McpHeavyModules> {\n if (heavyModules) return Promise.resolve(heavyModules);\n if (!heavyModulesPromise) {\n heavyModulesPromise = (async () => {\n const [init, authFlow, commands, proxyModes, directToolExecutor] = await Promise.all([\n import(\"./init.ts\"),\n import(\"./mcp-auth-flow.ts\"),\n import(\"./commands.ts\"),\n import(\"./proxy-modes.ts\"),\n import(\"./direct-tool-executor.ts\"),\n ]);\n const loaded: McpHeavyModules = { init, authFlow, commands, proxyModes, directToolExecutor };\n heavyModules = loaded;\n return loaded;\n })().catch((error) => {\n heavyModulesPromise = null;\n throw error;\n });\n }\n return heavyModulesPromise;\n }\n\n async function shutdownState(currentState: McpExtensionState | null, reason: string): Promise<void> {\n if (!currentState) return;\n\n if (currentState.uiServer) {\n currentState.uiServer.close(reason);\n currentState.uiServer = null;\n }\n\n let flushError: unknown;\n try {\n if (heavyModules) {\n heavyModules.init.flushMetadataCache(currentState);\n }\n } catch (error) {\n flushError = error;\n }\n\n try {\n await currentState.lifecycle.gracefulShutdown();\n } catch (error) {\n if (flushError) {\n console.error(\"MCP: graceful shutdown failed after metadata flush error\", error);\n } else {\n throw error;\n }\n }\n\n if (flushError) {\n throw flushError;\n }\n }\n\n async function shutdownInitializingStates(): Promise<void> {\n const pending = [...initializingStates];\n initializingStates.clear();\n await Promise.all(pending.map((entry) => shutdownState(entry, \"initialization_cancelled\")));\n }\n\n async function shutdownLoadedRuntime(): Promise<void> {\n if (!heavyModules) return;\n await heavyModules.authFlow.shutdownOAuth();\n }\n\n async function runInitialize(\n generation: number,\n sessionPi: ExtensionAPI,\n ctx: ExtensionContext,\n ): Promise<McpExtensionState> {\n const signal = sessionAbort.signal;\n const heavy = await loadHeavyModules();\n throwIfAborted(signal);\n if (generation !== lifecycleGeneration) {\n throw new Error(\"MCP initialization aborted (session changed)\");\n }\n\n await heavy.authFlow.initializeOAuth().catch(err => {\n console.error(\"MCP OAuth initialization failed:\", err);\n });\n\n if (generation !== lifecycleGeneration) {\n throw new Error(\"MCP initialization aborted (session changed)\");\n }\n\n let partial: McpExtensionState | undefined;\n try {\n const initialized = await heavy.init.initializeMcp(sessionPi, ctx, {\n signal,\n onState: (entry: McpExtensionState) => {\n partial = entry;\n initializingStates.add(entry);\n },\n });\n if (!partial) {\n partial = initialized;\n initializingStates.add(initialized);\n }\n throwIfAborted(signal);\n return initialized;\n } catch (error) {\n if (partial && initializingStates.delete(partial)) await shutdownState(partial, \"initialization_failed\");\n throw error;\n } finally {\n if (partial) initializingStates.delete(partial);\n }\n }\n\n function startSessionInit(generation: number, sessionPi: ExtensionAPI, ctx: ExtensionContext): Promise<McpExtensionState> {\n const promise = runInitialize(generation, sessionPi, ctx);\n initPromise = promise;\n\n promise.then(async (nextState) => {\n if (generation !== lifecycleGeneration || initPromise !== promise) {\n try {\n await shutdownState(nextState, \"stale_session_start\");\n } catch (error) {\n console.error(\"MCP: failed to clean stale session state\", error);\n }\n return;\n }\n\n state = nextState;\n if (heavyModules) {\n heavyModules.init.updateStatusBar(nextState);\n }\n initPromise = null;\n }).catch(err => {\n if (generation !== lifecycleGeneration) {\n return;\n }\n if (initPromise !== promise && initPromise !== null) {\n return;\n }\n console.error(\"MCP initialization failed:\", err);\n initPromise = null;\n });\n\n return promise;\n }\n\n async function ensureState(sessionPi: ExtensionAPI, ctx: ExtensionContext, signal?: AbortSignal): Promise<McpExtensionState> {\n throwIfAborted(signal);\n if (state) return state;\n\n const generation = lifecycleGeneration;\n if (!initPromise) {\n startSessionInit(generation, sessionPi, ctx);\n }\n const promise = initPromise;\n if (!promise) {\n throw new Error(\"MCP not initialized\");\n }\n\n try {\n const nextState = await abortable(promise, signal);\n if (generation !== lifecycleGeneration) {\n throw new Error(\"MCP initialization aborted (session changed)\");\n }\n if (state) return state;\n state = nextState;\n if (initPromise === promise) {\n initPromise = null;\n }\n return state;\n } catch (error) {\n if (initPromise === promise && !signal?.aborted) {\n initPromise = null;\n }\n throw error;\n }\n }\n\n function assertCurrentState(currentState: McpExtensionState): void {\n if (currentState !== state) throw new Error(\"MCP session changed before execution\");\n }\n\n function createLazyDirectToolExecute(spec: DirectToolSpec) {\n return async function execute(toolCallId, params, incomingSignal, onUpdate, ctx) {\n const signal = incomingSignal ? AbortSignal.any([incomingSignal, sessionAbort.signal]) : sessionAbort.signal;\n let currentState: McpExtensionState;\n try {\n currentState = await ensureState(pi, ctx, signal);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [{ type: \"text\" as const, text: `MCP initialization failed: ${message}` }],\n details: { error: \"init_failed\", message },\n };\n }\n\n const heavy = await loadHeavyModules();\n throwIfAborted(signal);\n assertCurrentState(currentState);\n let executor = directExecutors.get(spec.prefixedName);\n if (!executor) {\n executor = heavy.directToolExecutor.createDirectToolExecutor(() => currentState, () => null, spec);\n directExecutors.set(spec.prefixedName, executor);\n }\n return executor(toolCallId, params, signal, onUpdate, ctx);\n };\n }\n\n const earlyConfigPath = getConfigPathFromArgv();\n const earlyConfig = loadMcpConfig(earlyConfigPath);\n const earlyCache = loadMetadataCache();\n const prefix = earlyConfig.settings?.toolPrefix ?? \"server\";\n\n const envRaw = process.env.MCP_DIRECT_TOOLS;\n const directSpecs = envRaw === \"__none__\"\n ? []\n : resolveDirectTools(\n earlyConfig,\n earlyCache,\n prefix,\n envRaw?.split(\",\").map(s => s.trim()).filter(Boolean),\n );\n const missingConfiguredDirectToolServers = getMissingConfiguredDirectToolServers(earlyConfig, earlyCache);\n const shouldRegisterProxyTool =\n earlyConfig.settings?.disableProxyTool !== true\n || directSpecs.length === 0\n || missingConfiguredDirectToolServers.length > 0;\n\n for (const spec of directSpecs) {\n (pi.registerTool as (tool: unknown) => unknown)({\n name: spec.prefixedName,\n label: `MCP: ${spec.originalName}`,\n description: spec.description || \"(no description)\",\n promptSnippet: truncateAtWord(spec.description, 100) || `MCP tool from ${spec.serverName}`,\n parameters: Type.Unsafe(normalizeDirectToolInputSchema(spec.inputSchema) as never),\n execute: createLazyDirectToolExecute(spec),\n renderCall: createMcpDirectToolCallRenderer(spec.prefixedName),\n renderResult: renderMcpToolResult,\n });\n }\n\n const getPiTools = (): ToolInfo[] => pi.getAllTools();\n\n pi.registerFlag(\"mcp-config\", {\n description: \"Path to MCP config file\",\n type: \"string\",\n });\n\n pi.on(\"session_start\", async (_event, ctx) => {\n const generation = ++lifecycleGeneration;\n sessionAbort.abort(new Error(\"MCP session changed\"));\n sessionAbort = new AbortController();\n const previousState = state;\n state = null;\n initPromise = null;\n directExecutors.clear();\n\n try {\n await Promise.all([\n shutdownState(previousState, \"session_restart\"),\n shutdownInitializingStates(),\n shutdownLoadedRuntime(),\n ]);\n } catch (error) {\n console.error(\"MCP: failed to shut down previous session state\", error);\n }\n\n if (generation !== lifecycleGeneration) {\n return;\n }\n\n const configPath = (pi.getFlag(\"mcp-config\") as string | undefined) ?? earlyConfigPath;\n const sessionConfig = loadMcpConfig(configPath, ctx.cwd);\n const sessionCache = loadMetadataCache();\n\n if (!shouldBackgroundAutostart(sessionConfig, sessionCache)) {\n return;\n }\n\n startSessionInit(generation, pi, ctx);\n });\n\n pi.on(\"session_shutdown\", async () => {\n ++lifecycleGeneration;\n sessionAbort.abort(new Error(\"MCP session ended\"));\n const currentState = state;\n state = null;\n initPromise = null;\n directExecutors.clear();\n\n try {\n await Promise.all([\n shutdownState(currentState, \"session_shutdown\"),\n shutdownInitializingStates(),\n shutdownLoadedRuntime(),\n ]);\n } catch (error) {\n console.error(\"MCP: session shutdown cleanup failed\", error);\n }\n });\n\n // Re-flag returned MCP tool failures so pi registers them as errors (see toolErrorOverride).\n pi.on(\"tool_result\", (event) => toolErrorOverride(event.details));\n\n pi.registerCommand(\"mcp\", {\n description: \"Show MCP server status\",\n handler: async (args, ctx) => {\n let currentState: McpExtensionState;\n try {\n currentState = await ensureState(pi, ctx);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n if (ctx.hasUI) ctx.ui.notify(`MCP initialization failed: ${message}`, \"error\");\n return;\n }\n\n const heavy = await loadHeavyModules();\n assertCurrentState(currentState);\n const parts = args?.trim()?.split(/\\s+/) ?? [];\n const subcommand = parts[0] ?? \"\";\n const targetServer = parts[1];\n const rest = parts.slice(1).join(\" \");\n\n switch (subcommand) {\n case \"reconnect\":\n await heavy.commands.reconnectServers(currentState, ctx, targetServer);\n break;\n case \"tools\":\n await heavy.commands.showTools(currentState, ctx);\n break;\n case \"setup\": {\n const result = await heavy.commands.openMcpSetup(currentState, pi, ctx, earlyConfigPath, \"setup\");\n if (result?.configChanged) {\n await ctx.reload();\n return;\n }\n break;\n }\n case \"logout\": {\n const serverName = rest;\n if (!serverName) {\n if (ctx.hasUI) ctx.ui.notify(\"Usage: /mcp logout <server>\", \"error\");\n return;\n }\n await heavy.commands.logoutServer(serverName, currentState, ctx);\n break;\n }\n case \"status\":\n case \"\":\n default:\n if (ctx.hasUI) {\n const result = await heavy.commands.openMcpPanel(currentState, pi, ctx, earlyConfigPath);\n if (result?.configChanged) {\n await ctx.reload();\n return;\n }\n } else {\n await heavy.commands.showStatus(currentState, ctx);\n }\n break;\n }\n },\n });\n\n pi.registerCommand(\"mcp-auth\", {\n description: \"Authenticate with an MCP server (OAuth)\",\n handler: async (args, ctx) => {\n const serverName = args?.trim();\n if (!serverName && !ctx.hasUI) {\n return;\n }\n\n let currentState: McpExtensionState;\n try {\n currentState = await ensureState(pi, ctx);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n if (ctx.hasUI) ctx.ui.notify(`MCP initialization failed: ${message}`, \"error\");\n return;\n }\n\n const heavy = await loadHeavyModules();\n assertCurrentState(currentState);\n\n if (!serverName) {\n await heavy.commands.openMcpAuthPanel(currentState, pi, ctx, earlyConfigPath);\n return;\n }\n\n await heavy.commands.authenticateServer(serverName, currentState.config, ctx);\n },\n });\n\n if (shouldRegisterProxyTool) {\n (pi.registerTool as (tool: unknown) => unknown)({\n name: \"mcp\",\n label: \"MCP\",\n description: buildProxyDescription(earlyConfig, earlyCache, directSpecs),\n promptSnippet: \"MCP gateway - connect to MCP servers and call their tools\",\n renderCall: renderMcpProxyToolCall,\n parameters: Type.Object({\n tool: Type.Optional(Type.String({ description: \"Tool name to call (e.g., 'xcodebuild_list_sims')\" })),\n args: Type.Optional(Type.String({ description: \"Arguments as JSON string (e.g., '{\\\"key\\\": \\\"value\\\"}')\" })),\n connect: Type.Optional(Type.String({ description: \"Server name to connect (lazy connect + metadata refresh)\" })),\n describe: Type.Optional(Type.String({ description: \"Tool name to describe (shows parameters)\" })),\n search: Type.Optional(Type.String({ description: \"Search tools by name/description\" })),\n regex: Type.Optional(Type.Boolean({ description: \"Treat search as regex (default: substring match)\" })),\n includeSchemas: Type.Optional(Type.Boolean({ description: \"Include parameter schemas in search results (default: true)\" })),\n server: Type.Optional(Type.String({ description: \"Filter to specific server (also disambiguates tool calls)\" })),\n action: Type.Optional(Type.String({ description: \"Action: 'ui-messages', 'auth-start', or 'auth-complete'\" })),\n }),\n renderResult: renderMcpToolResult,\n async execute(_toolCallId, params: {\n tool?: string;\n args?: string;\n connect?: string;\n describe?: string;\n search?: string;\n regex?: boolean;\n includeSchemas?: boolean;\n server?: string;\n action?: string;\n }, incomingSignal, _onUpdate, ctx) {\n const signal = incomingSignal ? AbortSignal.any([incomingSignal, sessionAbort.signal]) : sessionAbort.signal;\n let parsedArgs: Record<string, unknown> | undefined;\n if (params.args) {\n try {\n parsedArgs = JSON.parse(params.args);\n if (typeof parsedArgs !== \"object\" || parsedArgs === null || Array.isArray(parsedArgs)) {\n const gotType = Array.isArray(parsedArgs) ? \"array\" : parsedArgs === null ? \"null\" : typeof parsedArgs;\n throw new Error(`Invalid args: expected a JSON object, got ${gotType}`);\n }\n } catch (error) {\n if (error instanceof SyntaxError) {\n throw new Error(`Invalid args JSON: ${error.message}`, { cause: error });\n }\n throw error;\n }\n }\n\n let currentState: McpExtensionState;\n try {\n currentState = await ensureState(pi, ctx, signal);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [{ type: \"text\" as const, text: `MCP initialization failed: ${message}` }],\n details: { error: \"init_failed\", message },\n };\n }\n\n const heavy = await loadHeavyModules();\n throwIfAborted(signal);\n assertCurrentState(currentState);\n\n if (params.action === \"ui-messages\") {\n return heavy.proxyModes.executeUiMessages(currentState);\n }\n if (params.action === \"auth-start\") {\n if (!params.server) {\n return {\n content: [{ type: \"text\" as const, text: \"auth-start requires `server`. Example: mcp({ action: \\\"auth-start\\\", server: \\\"linear-server\\\" })\" }],\n details: { mode: \"auth-start\", error: \"missing_server\" },\n };\n }\n return heavy.proxyModes.executeAuthStart(currentState, params.server);\n }\n if (params.action === \"auth-complete\") {\n if (!params.server) {\n return {\n content: [{ type: \"text\" as const, text: \"auth-complete requires `server`.\" }],\n details: { mode: \"auth-complete\", error: \"missing_server\" },\n };\n }\n const input = parsedArgs?.redirectUrl ?? parsedArgs?.code ?? parsedArgs?.input;\n if (typeof input !== \"string\" || input.trim().length === 0) {\n return {\n content: [{ type: \"text\" as const, text: \"auth-complete requires args with `redirectUrl`, `code`, or `input`.\" }],\n details: { mode: \"auth-complete\", error: \"missing_input\" },\n };\n }\n return heavy.proxyModes.executeAuthComplete(currentState, params.server, input);\n }\n if (params.tool) {\n return heavy.proxyModes.executeCall(currentState, params.tool, parsedArgs, params.server, getPiTools, signal);\n }\n if (params.connect) {\n return heavy.proxyModes.executeConnect(currentState, params.connect, signal);\n }\n if (params.describe) {\n return heavy.proxyModes.executeDescribe(currentState, params.describe);\n }\n if (params.search) {\n return heavy.proxyModes.executeSearch(currentState, params.search, params.regex, params.server, params.includeSchemas);\n }\n if (params.server) {\n return heavy.proxyModes.executeList(currentState, params.server);\n }\n return heavy.proxyModes.executeStatus(currentState);\n },\n });\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/builtin-extensions/pi-mcp-adapter/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAA8B,MAAM,iCAAiC,CAAC;AAqChG,MAAM,CAAC,OAAO,UAAU,UAAU,CAAC,EAAE,EAAE,YAAY,QAqgBlD","sourcesContent":["// @ts-nocheck\nimport type { ExtensionAPI, ExtensionContext, ToolInfo } from \"@ashx-j/lunr-dev\";\nimport type { McpExtensionState } from \"./state.ts\";\nimport type { DirectToolSpec, McpConfig } from \"./types.ts\";\nimport type { MetadataCache } from \"./metadata-cache.ts\";\nimport { existsSync } from \"node:fs\";\nimport { Type } from \"typebox\";\nimport { loadMcpConfig } from \"./config.ts\";\nimport { buildProxyDescription, getMissingConfiguredDirectToolServers, resolveDirectTools } from \"./direct-tools.ts\";\nimport { getMetadataCachePath, loadMetadataCache } from \"./metadata-cache.ts\";\nimport { getConfigPathFromArgv, normalizeDirectToolInputSchema, truncateAtWord } from \"./utils.ts\";\nimport { createMcpDirectToolCallRenderer, renderMcpProxyToolCall, renderMcpToolResult } from \"./tool-result-renderer.ts\";\nimport { toolErrorOverride } from \"./error-signal.ts\";\nimport { abortable, throwIfAborted } from \"./abort.ts\";\n\ntype McpHeavyModules = {\n init: typeof import(\"./init.ts\");\n authFlow: typeof import(\"./mcp-auth-flow.ts\");\n commands: typeof import(\"./commands.ts\");\n proxyModes: typeof import(\"./proxy-modes.ts\");\n directToolExecutor: typeof import(\"./direct-tool-executor.ts\");\n};\n\nfunction shouldBackgroundAutostart(config: McpConfig, cache: MetadataCache | null): boolean {\n const serverEntries = Object.entries(config.mcpServers);\n if (serverEntries.length === 0) return false;\n\n if (!existsSync(getMetadataCachePath())) return true;\n\n for (const [, definition] of serverEntries) {\n const mode = definition.lifecycle ?? \"lazy\";\n if (mode === \"keep-alive\" || mode === \"eager\") return true;\n }\n\n if (process.env.MCP_DIRECT_TOOLS === \"__none__\") return false;\n return getMissingConfiguredDirectToolServers(config, cache).length > 0;\n}\n\nexport default function mcpAdapter(pi: ExtensionAPI) {\n let state: McpExtensionState | null = null;\n let initPromise: Promise<McpExtensionState> | null = null;\n let lifecycleGeneration = 0;\n let sessionAbort = new AbortController();\n const initializingStates = new Set<McpExtensionState>();\n const shutdownPromises = new WeakMap<McpExtensionState, Promise<void>>();\n let heavyModules: McpHeavyModules | null = null;\n let heavyModulesPromise: Promise<McpHeavyModules> | null = null;\n const directExecutors = new Map<string, ReturnType<McpHeavyModules[\"directToolExecutor\"][\"createDirectToolExecutor\"]>>();\n\n function loadHeavyModules(): Promise<McpHeavyModules> {\n if (heavyModules) return Promise.resolve(heavyModules);\n if (!heavyModulesPromise) {\n heavyModulesPromise = (async () => {\n const [init, authFlow, commands, proxyModes, directToolExecutor] = await Promise.all([\n import(\"./init.ts\"),\n import(\"./mcp-auth-flow.ts\"),\n import(\"./commands.ts\"),\n import(\"./proxy-modes.ts\"),\n import(\"./direct-tool-executor.ts\"),\n ]);\n const loaded: McpHeavyModules = { init, authFlow, commands, proxyModes, directToolExecutor };\n heavyModules = loaded;\n return loaded;\n })().catch((error) => {\n heavyModulesPromise = null;\n throw error;\n });\n }\n return heavyModulesPromise;\n }\n\n function shutdownState(currentState: McpExtensionState | null, reason: string): Promise<void> {\n if (!currentState) return Promise.resolve();\n const existing = shutdownPromises.get(currentState);\n if (existing) return existing;\n\n const shutdown = (async () => {\n if (currentState.uiServer) {\n currentState.uiServer.close(reason);\n currentState.uiServer = null;\n }\n\n let flushError: unknown;\n try {\n if (heavyModules) {\n heavyModules.init.flushMetadataCache(currentState);\n }\n } catch (error) {\n flushError = error;\n }\n\n try {\n await currentState.lifecycle.gracefulShutdown();\n } catch (error) {\n if (flushError) {\n console.error(\"MCP: graceful shutdown failed after metadata flush error\", error);\n } else {\n throw error;\n }\n }\n\n if (flushError) {\n throw flushError;\n }\n })();\n shutdownPromises.set(currentState, shutdown);\n return shutdown;\n }\n\n async function shutdownInitializingStates(): Promise<void> {\n const pending = [...initializingStates];\n initializingStates.clear();\n await Promise.all(pending.map((entry) => shutdownState(entry, \"initialization_cancelled\")));\n }\n\n async function shutdownLoadedRuntime(): Promise<void> {\n if (!heavyModules) return;\n await heavyModules.authFlow.shutdownOAuth();\n }\n\n async function runInitialize(\n generation: number,\n sessionPi: ExtensionAPI,\n ctx: ExtensionContext,\n ): Promise<McpExtensionState> {\n const signal = sessionAbort.signal;\n const heavy = await loadHeavyModules();\n throwIfAborted(signal);\n if (generation !== lifecycleGeneration) {\n throw new Error(\"MCP initialization aborted (session changed)\");\n }\n\n await heavy.authFlow.initializeOAuth().catch(err => {\n console.error(\"MCP OAuth initialization failed:\", err);\n });\n\n if (generation !== lifecycleGeneration) {\n throw new Error(\"MCP initialization aborted (session changed)\");\n }\n\n let partial: McpExtensionState | undefined;\n try {\n const initialized = await heavy.init.initializeMcp(sessionPi, ctx, {\n signal,\n onState: (entry: McpExtensionState) => {\n partial = entry;\n initializingStates.add(entry);\n },\n });\n if (!partial) {\n partial = initialized;\n initializingStates.add(initialized);\n }\n throwIfAborted(signal);\n return initialized;\n } catch (error) {\n if (partial) {\n initializingStates.delete(partial);\n await shutdownState(partial, \"initialization_failed\");\n }\n throw error;\n } finally {\n if (partial) initializingStates.delete(partial);\n }\n }\n\n function startSessionInit(generation: number, sessionPi: ExtensionAPI, ctx: ExtensionContext): Promise<McpExtensionState> {\n const promise = runInitialize(generation, sessionPi, ctx);\n initPromise = promise;\n\n promise.then(async (nextState) => {\n if (generation !== lifecycleGeneration || initPromise !== promise) {\n try {\n await shutdownState(nextState, \"stale_session_start\");\n } catch (error) {\n console.error(\"MCP: failed to clean stale session state\", error);\n }\n return;\n }\n\n state = nextState;\n if (heavyModules) {\n heavyModules.init.updateStatusBar(nextState);\n }\n initPromise = null;\n }).catch(err => {\n if (generation !== lifecycleGeneration) {\n return;\n }\n if (initPromise !== promise && initPromise !== null) {\n return;\n }\n console.error(\"MCP initialization failed:\", err);\n initPromise = null;\n });\n\n return promise;\n }\n\n async function ensureState(sessionPi: ExtensionAPI, ctx: ExtensionContext, signal?: AbortSignal): Promise<McpExtensionState> {\n throwIfAborted(signal);\n if (state) return state;\n\n const generation = lifecycleGeneration;\n if (!initPromise) {\n startSessionInit(generation, sessionPi, ctx);\n }\n const promise = initPromise;\n if (!promise) {\n throw new Error(\"MCP not initialized\");\n }\n\n try {\n const nextState = await abortable(promise, signal);\n if (generation !== lifecycleGeneration) {\n throw new Error(\"MCP initialization aborted (session changed)\");\n }\n if (state) return state;\n state = nextState;\n if (initPromise === promise) {\n initPromise = null;\n }\n return state;\n } catch (error) {\n if (initPromise === promise && !signal?.aborted) {\n initPromise = null;\n }\n throw error;\n }\n }\n\n function assertCurrentState(currentState: McpExtensionState): void {\n if (currentState !== state) throw new Error(\"MCP session changed before execution\");\n }\n\n function createLazyDirectToolExecute(spec: DirectToolSpec) {\n return async function execute(toolCallId, params, incomingSignal, onUpdate, ctx) {\n const signal = incomingSignal ? AbortSignal.any([incomingSignal, sessionAbort.signal]) : sessionAbort.signal;\n let currentState: McpExtensionState;\n try {\n currentState = await ensureState(pi, ctx, signal);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [{ type: \"text\" as const, text: `MCP initialization failed: ${message}` }],\n details: { error: \"init_failed\", message },\n };\n }\n\n const heavy = await loadHeavyModules();\n throwIfAborted(signal);\n assertCurrentState(currentState);\n let executor = directExecutors.get(spec.prefixedName);\n if (!executor) {\n executor = heavy.directToolExecutor.createDirectToolExecutor(() => currentState, () => null, spec);\n directExecutors.set(spec.prefixedName, executor);\n }\n return executor(toolCallId, params, signal, onUpdate, ctx);\n };\n }\n\n const earlyConfigPath = getConfigPathFromArgv();\n const earlyConfig = loadMcpConfig(earlyConfigPath);\n const earlyCache = loadMetadataCache();\n const prefix = earlyConfig.settings?.toolPrefix ?? \"server\";\n\n const envRaw = process.env.MCP_DIRECT_TOOLS;\n const directSpecs = envRaw === \"__none__\"\n ? []\n : resolveDirectTools(\n earlyConfig,\n earlyCache,\n prefix,\n envRaw?.split(\",\").map(s => s.trim()).filter(Boolean),\n );\n const missingConfiguredDirectToolServers = getMissingConfiguredDirectToolServers(earlyConfig, earlyCache);\n const shouldRegisterProxyTool =\n earlyConfig.settings?.disableProxyTool !== true\n || directSpecs.length === 0\n || missingConfiguredDirectToolServers.length > 0;\n\n for (const spec of directSpecs) {\n (pi.registerTool as (tool: unknown) => unknown)({\n name: spec.prefixedName,\n label: `MCP: ${spec.originalName}`,\n description: spec.description || \"(no description)\",\n promptSnippet: truncateAtWord(spec.description, 100) || `MCP tool from ${spec.serverName}`,\n parameters: Type.Unsafe(normalizeDirectToolInputSchema(spec.inputSchema) as never),\n execute: createLazyDirectToolExecute(spec),\n renderCall: createMcpDirectToolCallRenderer(spec.prefixedName),\n renderResult: renderMcpToolResult,\n });\n }\n\n const getPiTools = (): ToolInfo[] => pi.getAllTools();\n\n pi.registerFlag(\"mcp-config\", {\n description: \"Path to MCP config file\",\n type: \"string\",\n });\n\n pi.on(\"session_start\", async (_event, ctx) => {\n const generation = ++lifecycleGeneration;\n sessionAbort.abort(new Error(\"MCP session changed\"));\n sessionAbort = new AbortController();\n const previousState = state;\n state = null;\n initPromise = null;\n directExecutors.clear();\n\n try {\n await Promise.all([\n shutdownState(previousState, \"session_restart\"),\n shutdownInitializingStates(),\n shutdownLoadedRuntime(),\n ]);\n } catch (error) {\n console.error(\"MCP: failed to shut down previous session state\", error);\n }\n\n if (generation !== lifecycleGeneration) {\n return;\n }\n\n const configPath = (pi.getFlag(\"mcp-config\") as string | undefined) ?? earlyConfigPath;\n const sessionConfig = loadMcpConfig(configPath, ctx.cwd);\n const sessionCache = loadMetadataCache();\n\n if (!shouldBackgroundAutostart(sessionConfig, sessionCache)) {\n return;\n }\n\n startSessionInit(generation, pi, ctx);\n });\n\n pi.on(\"session_shutdown\", async () => {\n ++lifecycleGeneration;\n sessionAbort.abort(new Error(\"MCP session ended\"));\n const currentState = state;\n state = null;\n initPromise = null;\n directExecutors.clear();\n\n try {\n await Promise.all([\n shutdownState(currentState, \"session_shutdown\"),\n shutdownInitializingStates(),\n shutdownLoadedRuntime(),\n ]);\n } catch (error) {\n console.error(\"MCP: session shutdown cleanup failed\", error);\n }\n });\n\n // Re-flag returned MCP tool failures so pi registers them as errors (see toolErrorOverride).\n pi.on(\"tool_result\", (event) => toolErrorOverride(event.details));\n\n pi.registerCommand(\"mcp\", {\n description: \"Show MCP server status\",\n handler: async (args, ctx) => {\n let currentState: McpExtensionState;\n try {\n currentState = await ensureState(pi, ctx);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n if (ctx.hasUI) ctx.ui.notify(`MCP initialization failed: ${message}`, \"error\");\n return;\n }\n\n const heavy = await loadHeavyModules();\n assertCurrentState(currentState);\n const parts = args?.trim()?.split(/\\s+/) ?? [];\n const subcommand = parts[0] ?? \"\";\n const targetServer = parts[1];\n const rest = parts.slice(1).join(\" \");\n\n switch (subcommand) {\n case \"reconnect\":\n await heavy.commands.reconnectServers(currentState, ctx, targetServer);\n break;\n case \"tools\":\n await heavy.commands.showTools(currentState, ctx);\n break;\n case \"setup\": {\n const result = await heavy.commands.openMcpSetup(currentState, pi, ctx, earlyConfigPath, \"setup\");\n if (result?.configChanged) {\n await ctx.reload();\n return;\n }\n break;\n }\n case \"logout\": {\n const serverName = rest;\n if (!serverName) {\n if (ctx.hasUI) ctx.ui.notify(\"Usage: /mcp logout <server>\", \"error\");\n return;\n }\n await heavy.commands.logoutServer(serverName, currentState, ctx);\n break;\n }\n case \"status\":\n case \"\":\n default:\n if (ctx.hasUI) {\n const result = await heavy.commands.openMcpPanel(currentState, pi, ctx, earlyConfigPath);\n if (result?.configChanged) {\n await ctx.reload();\n return;\n }\n } else {\n await heavy.commands.showStatus(currentState, ctx);\n }\n break;\n }\n },\n });\n\n pi.registerCommand(\"mcp-auth\", {\n description: \"Authenticate with an MCP server (OAuth)\",\n handler: async (args, ctx) => {\n const serverName = args?.trim();\n if (!serverName && !ctx.hasUI) {\n return;\n }\n\n let currentState: McpExtensionState;\n try {\n currentState = await ensureState(pi, ctx);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n if (ctx.hasUI) ctx.ui.notify(`MCP initialization failed: ${message}`, \"error\");\n return;\n }\n\n const heavy = await loadHeavyModules();\n assertCurrentState(currentState);\n\n if (!serverName) {\n await heavy.commands.openMcpAuthPanel(currentState, pi, ctx, earlyConfigPath);\n return;\n }\n\n await heavy.commands.authenticateServer(serverName, currentState.config, ctx);\n },\n });\n\n if (shouldRegisterProxyTool) {\n (pi.registerTool as (tool: unknown) => unknown)({\n name: \"mcp\",\n label: \"MCP\",\n description: buildProxyDescription(earlyConfig, earlyCache, directSpecs),\n promptSnippet: \"MCP gateway - connect to MCP servers and call their tools\",\n renderCall: renderMcpProxyToolCall,\n parameters: Type.Object({\n tool: Type.Optional(Type.String({ description: \"Tool name to call (e.g., 'xcodebuild_list_sims')\" })),\n args: Type.Optional(Type.String({ description: \"Arguments as JSON string (e.g., '{\\\"key\\\": \\\"value\\\"}')\" })),\n connect: Type.Optional(Type.String({ description: \"Server name to connect (lazy connect + metadata refresh)\" })),\n describe: Type.Optional(Type.String({ description: \"Tool name to describe (shows parameters)\" })),\n search: Type.Optional(Type.String({ description: \"Search tools by name/description\" })),\n regex: Type.Optional(Type.Boolean({ description: \"Treat search as regex (default: substring match)\" })),\n includeSchemas: Type.Optional(Type.Boolean({ description: \"Include parameter schemas in search results (default: true)\" })),\n server: Type.Optional(Type.String({ description: \"Filter to specific server (also disambiguates tool calls)\" })),\n action: Type.Optional(Type.String({ description: \"Action: 'ui-messages', 'auth-start', or 'auth-complete'\" })),\n }),\n renderResult: renderMcpToolResult,\n async execute(_toolCallId, params: {\n tool?: string;\n args?: string;\n connect?: string;\n describe?: string;\n search?: string;\n regex?: boolean;\n includeSchemas?: boolean;\n server?: string;\n action?: string;\n }, incomingSignal, _onUpdate, ctx) {\n const signal = incomingSignal ? AbortSignal.any([incomingSignal, sessionAbort.signal]) : sessionAbort.signal;\n let parsedArgs: Record<string, unknown> | undefined;\n if (params.args) {\n try {\n parsedArgs = JSON.parse(params.args);\n if (typeof parsedArgs !== \"object\" || parsedArgs === null || Array.isArray(parsedArgs)) {\n const gotType = Array.isArray(parsedArgs) ? \"array\" : parsedArgs === null ? \"null\" : typeof parsedArgs;\n throw new Error(`Invalid args: expected a JSON object, got ${gotType}`);\n }\n } catch (error) {\n if (error instanceof SyntaxError) {\n throw new Error(`Invalid args JSON: ${error.message}`, { cause: error });\n }\n throw error;\n }\n }\n\n let currentState: McpExtensionState;\n try {\n currentState = await ensureState(pi, ctx, signal);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [{ type: \"text\" as const, text: `MCP initialization failed: ${message}` }],\n details: { error: \"init_failed\", message },\n };\n }\n\n const heavy = await loadHeavyModules();\n throwIfAborted(signal);\n assertCurrentState(currentState);\n\n if (params.action === \"ui-messages\") {\n return heavy.proxyModes.executeUiMessages(currentState);\n }\n if (params.action === \"auth-start\") {\n if (!params.server) {\n return {\n content: [{ type: \"text\" as const, text: \"auth-start requires `server`. Example: mcp({ action: \\\"auth-start\\\", server: \\\"linear-server\\\" })\" }],\n details: { mode: \"auth-start\", error: \"missing_server\" },\n };\n }\n return heavy.proxyModes.executeAuthStart(currentState, params.server);\n }\n if (params.action === \"auth-complete\") {\n if (!params.server) {\n return {\n content: [{ type: \"text\" as const, text: \"auth-complete requires `server`.\" }],\n details: { mode: \"auth-complete\", error: \"missing_server\" },\n };\n }\n const input = parsedArgs?.redirectUrl ?? parsedArgs?.code ?? parsedArgs?.input;\n if (typeof input !== \"string\" || input.trim().length === 0) {\n return {\n content: [{ type: \"text\" as const, text: \"auth-complete requires args with `redirectUrl`, `code`, or `input`.\" }],\n details: { mode: \"auth-complete\", error: \"missing_input\" },\n };\n }\n return heavy.proxyModes.executeAuthComplete(currentState, params.server, input);\n }\n if (params.tool) {\n return heavy.proxyModes.executeCall(currentState, params.tool, parsedArgs, params.server, getPiTools, signal);\n }\n if (params.connect) {\n return heavy.proxyModes.executeConnect(currentState, params.connect, signal);\n }\n if (params.describe) {\n return heavy.proxyModes.executeDescribe(currentState, params.describe);\n }\n if (params.search) {\n return heavy.proxyModes.executeSearch(currentState, params.search, params.regex, params.server, params.includeSchemas);\n }\n if (params.server) {\n return heavy.proxyModes.executeList(currentState, params.server);\n }\n return heavy.proxyModes.executeStatus(currentState);\n },\n });\n }\n}\n"]}
|
|
@@ -28,6 +28,7 @@ export default function mcpAdapter(pi) {
|
|
|
28
28
|
let lifecycleGeneration = 0;
|
|
29
29
|
let sessionAbort = new AbortController();
|
|
30
30
|
const initializingStates = new Set();
|
|
31
|
+
const shutdownPromises = new WeakMap();
|
|
31
32
|
let heavyModules = null;
|
|
32
33
|
let heavyModulesPromise = null;
|
|
33
34
|
const directExecutors = new Map();
|
|
@@ -53,36 +54,43 @@ export default function mcpAdapter(pi) {
|
|
|
53
54
|
}
|
|
54
55
|
return heavyModulesPromise;
|
|
55
56
|
}
|
|
56
|
-
|
|
57
|
+
function shutdownState(currentState, reason) {
|
|
57
58
|
if (!currentState)
|
|
58
|
-
return;
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
heavyModules.init.flushMetadataCache(currentState);
|
|
59
|
+
return Promise.resolve();
|
|
60
|
+
const existing = shutdownPromises.get(currentState);
|
|
61
|
+
if (existing)
|
|
62
|
+
return existing;
|
|
63
|
+
const shutdown = (async () => {
|
|
64
|
+
if (currentState.uiServer) {
|
|
65
|
+
currentState.uiServer.close(reason);
|
|
66
|
+
currentState.uiServer = null;
|
|
67
67
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
await currentState.lifecycle.gracefulShutdown();
|
|
74
|
-
}
|
|
75
|
-
catch (error) {
|
|
76
|
-
if (flushError) {
|
|
77
|
-
console.error("MCP: graceful shutdown failed after metadata flush error", error);
|
|
68
|
+
let flushError;
|
|
69
|
+
try {
|
|
70
|
+
if (heavyModules) {
|
|
71
|
+
heavyModules.init.flushMetadataCache(currentState);
|
|
72
|
+
}
|
|
78
73
|
}
|
|
79
|
-
|
|
80
|
-
|
|
74
|
+
catch (error) {
|
|
75
|
+
flushError = error;
|
|
81
76
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
77
|
+
try {
|
|
78
|
+
await currentState.lifecycle.gracefulShutdown();
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
if (flushError) {
|
|
82
|
+
console.error("MCP: graceful shutdown failed after metadata flush error", error);
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
throw error;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (flushError) {
|
|
89
|
+
throw flushError;
|
|
90
|
+
}
|
|
91
|
+
})();
|
|
92
|
+
shutdownPromises.set(currentState, shutdown);
|
|
93
|
+
return shutdown;
|
|
86
94
|
}
|
|
87
95
|
async function shutdownInitializingStates() {
|
|
88
96
|
const pending = [...initializingStates];
|
|
@@ -124,8 +132,10 @@ export default function mcpAdapter(pi) {
|
|
|
124
132
|
return initialized;
|
|
125
133
|
}
|
|
126
134
|
catch (error) {
|
|
127
|
-
if (partial
|
|
135
|
+
if (partial) {
|
|
136
|
+
initializingStates.delete(partial);
|
|
128
137
|
await shutdownState(partial, "initialization_failed");
|
|
138
|
+
}
|
|
129
139
|
throw error;
|
|
130
140
|
}
|
|
131
141
|
finally {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/builtin-extensions/pi-mcp-adapter/index.ts"],"names":[],"mappings":"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","sourcesContent":["// @ts-nocheck\nimport type { ExtensionAPI, ExtensionContext, ToolInfo } from \"@ashx-j/lunr-dev\";\nimport type { McpExtensionState } from \"./state.ts\";\nimport type { DirectToolSpec, McpConfig } from \"./types.ts\";\nimport type { MetadataCache } from \"./metadata-cache.ts\";\nimport { existsSync } from \"node:fs\";\nimport { Type } from \"typebox\";\nimport { loadMcpConfig } from \"./config.ts\";\nimport { buildProxyDescription, getMissingConfiguredDirectToolServers, resolveDirectTools } from \"./direct-tools.ts\";\nimport { getMetadataCachePath, loadMetadataCache } from \"./metadata-cache.ts\";\nimport { getConfigPathFromArgv, normalizeDirectToolInputSchema, truncateAtWord } from \"./utils.ts\";\nimport { createMcpDirectToolCallRenderer, renderMcpProxyToolCall, renderMcpToolResult } from \"./tool-result-renderer.ts\";\nimport { toolErrorOverride } from \"./error-signal.ts\";\nimport { abortable, throwIfAborted } from \"./abort.ts\";\n\ntype McpHeavyModules = {\n init: typeof import(\"./init.ts\");\n authFlow: typeof import(\"./mcp-auth-flow.ts\");\n commands: typeof import(\"./commands.ts\");\n proxyModes: typeof import(\"./proxy-modes.ts\");\n directToolExecutor: typeof import(\"./direct-tool-executor.ts\");\n};\n\nfunction shouldBackgroundAutostart(config: McpConfig, cache: MetadataCache | null): boolean {\n const serverEntries = Object.entries(config.mcpServers);\n if (serverEntries.length === 0) return false;\n\n if (!existsSync(getMetadataCachePath())) return true;\n\n for (const [, definition] of serverEntries) {\n const mode = definition.lifecycle ?? \"lazy\";\n if (mode === \"keep-alive\" || mode === \"eager\") return true;\n }\n\n if (process.env.MCP_DIRECT_TOOLS === \"__none__\") return false;\n return getMissingConfiguredDirectToolServers(config, cache).length > 0;\n}\n\nexport default function mcpAdapter(pi: ExtensionAPI) {\n let state: McpExtensionState | null = null;\n let initPromise: Promise<McpExtensionState> | null = null;\n let lifecycleGeneration = 0;\n let sessionAbort = new AbortController();\n const initializingStates = new Set<McpExtensionState>();\n let heavyModules: McpHeavyModules | null = null;\n let heavyModulesPromise: Promise<McpHeavyModules> | null = null;\n const directExecutors = new Map<string, ReturnType<McpHeavyModules[\"directToolExecutor\"][\"createDirectToolExecutor\"]>>();\n\n function loadHeavyModules(): Promise<McpHeavyModules> {\n if (heavyModules) return Promise.resolve(heavyModules);\n if (!heavyModulesPromise) {\n heavyModulesPromise = (async () => {\n const [init, authFlow, commands, proxyModes, directToolExecutor] = await Promise.all([\n import(\"./init.ts\"),\n import(\"./mcp-auth-flow.ts\"),\n import(\"./commands.ts\"),\n import(\"./proxy-modes.ts\"),\n import(\"./direct-tool-executor.ts\"),\n ]);\n const loaded: McpHeavyModules = { init, authFlow, commands, proxyModes, directToolExecutor };\n heavyModules = loaded;\n return loaded;\n })().catch((error) => {\n heavyModulesPromise = null;\n throw error;\n });\n }\n return heavyModulesPromise;\n }\n\n async function shutdownState(currentState: McpExtensionState | null, reason: string): Promise<void> {\n if (!currentState) return;\n\n if (currentState.uiServer) {\n currentState.uiServer.close(reason);\n currentState.uiServer = null;\n }\n\n let flushError: unknown;\n try {\n if (heavyModules) {\n heavyModules.init.flushMetadataCache(currentState);\n }\n } catch (error) {\n flushError = error;\n }\n\n try {\n await currentState.lifecycle.gracefulShutdown();\n } catch (error) {\n if (flushError) {\n console.error(\"MCP: graceful shutdown failed after metadata flush error\", error);\n } else {\n throw error;\n }\n }\n\n if (flushError) {\n throw flushError;\n }\n }\n\n async function shutdownInitializingStates(): Promise<void> {\n const pending = [...initializingStates];\n initializingStates.clear();\n await Promise.all(pending.map((entry) => shutdownState(entry, \"initialization_cancelled\")));\n }\n\n async function shutdownLoadedRuntime(): Promise<void> {\n if (!heavyModules) return;\n await heavyModules.authFlow.shutdownOAuth();\n }\n\n async function runInitialize(\n generation: number,\n sessionPi: ExtensionAPI,\n ctx: ExtensionContext,\n ): Promise<McpExtensionState> {\n const signal = sessionAbort.signal;\n const heavy = await loadHeavyModules();\n throwIfAborted(signal);\n if (generation !== lifecycleGeneration) {\n throw new Error(\"MCP initialization aborted (session changed)\");\n }\n\n await heavy.authFlow.initializeOAuth().catch(err => {\n console.error(\"MCP OAuth initialization failed:\", err);\n });\n\n if (generation !== lifecycleGeneration) {\n throw new Error(\"MCP initialization aborted (session changed)\");\n }\n\n let partial: McpExtensionState | undefined;\n try {\n const initialized = await heavy.init.initializeMcp(sessionPi, ctx, {\n signal,\n onState: (entry: McpExtensionState) => {\n partial = entry;\n initializingStates.add(entry);\n },\n });\n if (!partial) {\n partial = initialized;\n initializingStates.add(initialized);\n }\n throwIfAborted(signal);\n return initialized;\n } catch (error) {\n if (partial && initializingStates.delete(partial)) await shutdownState(partial, \"initialization_failed\");\n throw error;\n } finally {\n if (partial) initializingStates.delete(partial);\n }\n }\n\n function startSessionInit(generation: number, sessionPi: ExtensionAPI, ctx: ExtensionContext): Promise<McpExtensionState> {\n const promise = runInitialize(generation, sessionPi, ctx);\n initPromise = promise;\n\n promise.then(async (nextState) => {\n if (generation !== lifecycleGeneration || initPromise !== promise) {\n try {\n await shutdownState(nextState, \"stale_session_start\");\n } catch (error) {\n console.error(\"MCP: failed to clean stale session state\", error);\n }\n return;\n }\n\n state = nextState;\n if (heavyModules) {\n heavyModules.init.updateStatusBar(nextState);\n }\n initPromise = null;\n }).catch(err => {\n if (generation !== lifecycleGeneration) {\n return;\n }\n if (initPromise !== promise && initPromise !== null) {\n return;\n }\n console.error(\"MCP initialization failed:\", err);\n initPromise = null;\n });\n\n return promise;\n }\n\n async function ensureState(sessionPi: ExtensionAPI, ctx: ExtensionContext, signal?: AbortSignal): Promise<McpExtensionState> {\n throwIfAborted(signal);\n if (state) return state;\n\n const generation = lifecycleGeneration;\n if (!initPromise) {\n startSessionInit(generation, sessionPi, ctx);\n }\n const promise = initPromise;\n if (!promise) {\n throw new Error(\"MCP not initialized\");\n }\n\n try {\n const nextState = await abortable(promise, signal);\n if (generation !== lifecycleGeneration) {\n throw new Error(\"MCP initialization aborted (session changed)\");\n }\n if (state) return state;\n state = nextState;\n if (initPromise === promise) {\n initPromise = null;\n }\n return state;\n } catch (error) {\n if (initPromise === promise && !signal?.aborted) {\n initPromise = null;\n }\n throw error;\n }\n }\n\n function assertCurrentState(currentState: McpExtensionState): void {\n if (currentState !== state) throw new Error(\"MCP session changed before execution\");\n }\n\n function createLazyDirectToolExecute(spec: DirectToolSpec) {\n return async function execute(toolCallId, params, incomingSignal, onUpdate, ctx) {\n const signal = incomingSignal ? AbortSignal.any([incomingSignal, sessionAbort.signal]) : sessionAbort.signal;\n let currentState: McpExtensionState;\n try {\n currentState = await ensureState(pi, ctx, signal);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [{ type: \"text\" as const, text: `MCP initialization failed: ${message}` }],\n details: { error: \"init_failed\", message },\n };\n }\n\n const heavy = await loadHeavyModules();\n throwIfAborted(signal);\n assertCurrentState(currentState);\n let executor = directExecutors.get(spec.prefixedName);\n if (!executor) {\n executor = heavy.directToolExecutor.createDirectToolExecutor(() => currentState, () => null, spec);\n directExecutors.set(spec.prefixedName, executor);\n }\n return executor(toolCallId, params, signal, onUpdate, ctx);\n };\n }\n\n const earlyConfigPath = getConfigPathFromArgv();\n const earlyConfig = loadMcpConfig(earlyConfigPath);\n const earlyCache = loadMetadataCache();\n const prefix = earlyConfig.settings?.toolPrefix ?? \"server\";\n\n const envRaw = process.env.MCP_DIRECT_TOOLS;\n const directSpecs = envRaw === \"__none__\"\n ? []\n : resolveDirectTools(\n earlyConfig,\n earlyCache,\n prefix,\n envRaw?.split(\",\").map(s => s.trim()).filter(Boolean),\n );\n const missingConfiguredDirectToolServers = getMissingConfiguredDirectToolServers(earlyConfig, earlyCache);\n const shouldRegisterProxyTool =\n earlyConfig.settings?.disableProxyTool !== true\n || directSpecs.length === 0\n || missingConfiguredDirectToolServers.length > 0;\n\n for (const spec of directSpecs) {\n (pi.registerTool as (tool: unknown) => unknown)({\n name: spec.prefixedName,\n label: `MCP: ${spec.originalName}`,\n description: spec.description || \"(no description)\",\n promptSnippet: truncateAtWord(spec.description, 100) || `MCP tool from ${spec.serverName}`,\n parameters: Type.Unsafe(normalizeDirectToolInputSchema(spec.inputSchema) as never),\n execute: createLazyDirectToolExecute(spec),\n renderCall: createMcpDirectToolCallRenderer(spec.prefixedName),\n renderResult: renderMcpToolResult,\n });\n }\n\n const getPiTools = (): ToolInfo[] => pi.getAllTools();\n\n pi.registerFlag(\"mcp-config\", {\n description: \"Path to MCP config file\",\n type: \"string\",\n });\n\n pi.on(\"session_start\", async (_event, ctx) => {\n const generation = ++lifecycleGeneration;\n sessionAbort.abort(new Error(\"MCP session changed\"));\n sessionAbort = new AbortController();\n const previousState = state;\n state = null;\n initPromise = null;\n directExecutors.clear();\n\n try {\n await Promise.all([\n shutdownState(previousState, \"session_restart\"),\n shutdownInitializingStates(),\n shutdownLoadedRuntime(),\n ]);\n } catch (error) {\n console.error(\"MCP: failed to shut down previous session state\", error);\n }\n\n if (generation !== lifecycleGeneration) {\n return;\n }\n\n const configPath = (pi.getFlag(\"mcp-config\") as string | undefined) ?? earlyConfigPath;\n const sessionConfig = loadMcpConfig(configPath, ctx.cwd);\n const sessionCache = loadMetadataCache();\n\n if (!shouldBackgroundAutostart(sessionConfig, sessionCache)) {\n return;\n }\n\n startSessionInit(generation, pi, ctx);\n });\n\n pi.on(\"session_shutdown\", async () => {\n ++lifecycleGeneration;\n sessionAbort.abort(new Error(\"MCP session ended\"));\n const currentState = state;\n state = null;\n initPromise = null;\n directExecutors.clear();\n\n try {\n await Promise.all([\n shutdownState(currentState, \"session_shutdown\"),\n shutdownInitializingStates(),\n shutdownLoadedRuntime(),\n ]);\n } catch (error) {\n console.error(\"MCP: session shutdown cleanup failed\", error);\n }\n });\n\n // Re-flag returned MCP tool failures so pi registers them as errors (see toolErrorOverride).\n pi.on(\"tool_result\", (event) => toolErrorOverride(event.details));\n\n pi.registerCommand(\"mcp\", {\n description: \"Show MCP server status\",\n handler: async (args, ctx) => {\n let currentState: McpExtensionState;\n try {\n currentState = await ensureState(pi, ctx);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n if (ctx.hasUI) ctx.ui.notify(`MCP initialization failed: ${message}`, \"error\");\n return;\n }\n\n const heavy = await loadHeavyModules();\n assertCurrentState(currentState);\n const parts = args?.trim()?.split(/\\s+/) ?? [];\n const subcommand = parts[0] ?? \"\";\n const targetServer = parts[1];\n const rest = parts.slice(1).join(\" \");\n\n switch (subcommand) {\n case \"reconnect\":\n await heavy.commands.reconnectServers(currentState, ctx, targetServer);\n break;\n case \"tools\":\n await heavy.commands.showTools(currentState, ctx);\n break;\n case \"setup\": {\n const result = await heavy.commands.openMcpSetup(currentState, pi, ctx, earlyConfigPath, \"setup\");\n if (result?.configChanged) {\n await ctx.reload();\n return;\n }\n break;\n }\n case \"logout\": {\n const serverName = rest;\n if (!serverName) {\n if (ctx.hasUI) ctx.ui.notify(\"Usage: /mcp logout <server>\", \"error\");\n return;\n }\n await heavy.commands.logoutServer(serverName, currentState, ctx);\n break;\n }\n case \"status\":\n case \"\":\n default:\n if (ctx.hasUI) {\n const result = await heavy.commands.openMcpPanel(currentState, pi, ctx, earlyConfigPath);\n if (result?.configChanged) {\n await ctx.reload();\n return;\n }\n } else {\n await heavy.commands.showStatus(currentState, ctx);\n }\n break;\n }\n },\n });\n\n pi.registerCommand(\"mcp-auth\", {\n description: \"Authenticate with an MCP server (OAuth)\",\n handler: async (args, ctx) => {\n const serverName = args?.trim();\n if (!serverName && !ctx.hasUI) {\n return;\n }\n\n let currentState: McpExtensionState;\n try {\n currentState = await ensureState(pi, ctx);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n if (ctx.hasUI) ctx.ui.notify(`MCP initialization failed: ${message}`, \"error\");\n return;\n }\n\n const heavy = await loadHeavyModules();\n assertCurrentState(currentState);\n\n if (!serverName) {\n await heavy.commands.openMcpAuthPanel(currentState, pi, ctx, earlyConfigPath);\n return;\n }\n\n await heavy.commands.authenticateServer(serverName, currentState.config, ctx);\n },\n });\n\n if (shouldRegisterProxyTool) {\n (pi.registerTool as (tool: unknown) => unknown)({\n name: \"mcp\",\n label: \"MCP\",\n description: buildProxyDescription(earlyConfig, earlyCache, directSpecs),\n promptSnippet: \"MCP gateway - connect to MCP servers and call their tools\",\n renderCall: renderMcpProxyToolCall,\n parameters: Type.Object({\n tool: Type.Optional(Type.String({ description: \"Tool name to call (e.g., 'xcodebuild_list_sims')\" })),\n args: Type.Optional(Type.String({ description: \"Arguments as JSON string (e.g., '{\\\"key\\\": \\\"value\\\"}')\" })),\n connect: Type.Optional(Type.String({ description: \"Server name to connect (lazy connect + metadata refresh)\" })),\n describe: Type.Optional(Type.String({ description: \"Tool name to describe (shows parameters)\" })),\n search: Type.Optional(Type.String({ description: \"Search tools by name/description\" })),\n regex: Type.Optional(Type.Boolean({ description: \"Treat search as regex (default: substring match)\" })),\n includeSchemas: Type.Optional(Type.Boolean({ description: \"Include parameter schemas in search results (default: true)\" })),\n server: Type.Optional(Type.String({ description: \"Filter to specific server (also disambiguates tool calls)\" })),\n action: Type.Optional(Type.String({ description: \"Action: 'ui-messages', 'auth-start', or 'auth-complete'\" })),\n }),\n renderResult: renderMcpToolResult,\n async execute(_toolCallId, params: {\n tool?: string;\n args?: string;\n connect?: string;\n describe?: string;\n search?: string;\n regex?: boolean;\n includeSchemas?: boolean;\n server?: string;\n action?: string;\n }, incomingSignal, _onUpdate, ctx) {\n const signal = incomingSignal ? AbortSignal.any([incomingSignal, sessionAbort.signal]) : sessionAbort.signal;\n let parsedArgs: Record<string, unknown> | undefined;\n if (params.args) {\n try {\n parsedArgs = JSON.parse(params.args);\n if (typeof parsedArgs !== \"object\" || parsedArgs === null || Array.isArray(parsedArgs)) {\n const gotType = Array.isArray(parsedArgs) ? \"array\" : parsedArgs === null ? \"null\" : typeof parsedArgs;\n throw new Error(`Invalid args: expected a JSON object, got ${gotType}`);\n }\n } catch (error) {\n if (error instanceof SyntaxError) {\n throw new Error(`Invalid args JSON: ${error.message}`, { cause: error });\n }\n throw error;\n }\n }\n\n let currentState: McpExtensionState;\n try {\n currentState = await ensureState(pi, ctx, signal);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [{ type: \"text\" as const, text: `MCP initialization failed: ${message}` }],\n details: { error: \"init_failed\", message },\n };\n }\n\n const heavy = await loadHeavyModules();\n throwIfAborted(signal);\n assertCurrentState(currentState);\n\n if (params.action === \"ui-messages\") {\n return heavy.proxyModes.executeUiMessages(currentState);\n }\n if (params.action === \"auth-start\") {\n if (!params.server) {\n return {\n content: [{ type: \"text\" as const, text: \"auth-start requires `server`. Example: mcp({ action: \\\"auth-start\\\", server: \\\"linear-server\\\" })\" }],\n details: { mode: \"auth-start\", error: \"missing_server\" },\n };\n }\n return heavy.proxyModes.executeAuthStart(currentState, params.server);\n }\n if (params.action === \"auth-complete\") {\n if (!params.server) {\n return {\n content: [{ type: \"text\" as const, text: \"auth-complete requires `server`.\" }],\n details: { mode: \"auth-complete\", error: \"missing_server\" },\n };\n }\n const input = parsedArgs?.redirectUrl ?? parsedArgs?.code ?? parsedArgs?.input;\n if (typeof input !== \"string\" || input.trim().length === 0) {\n return {\n content: [{ type: \"text\" as const, text: \"auth-complete requires args with `redirectUrl`, `code`, or `input`.\" }],\n details: { mode: \"auth-complete\", error: \"missing_input\" },\n };\n }\n return heavy.proxyModes.executeAuthComplete(currentState, params.server, input);\n }\n if (params.tool) {\n return heavy.proxyModes.executeCall(currentState, params.tool, parsedArgs, params.server, getPiTools, signal);\n }\n if (params.connect) {\n return heavy.proxyModes.executeConnect(currentState, params.connect, signal);\n }\n if (params.describe) {\n return heavy.proxyModes.executeDescribe(currentState, params.describe);\n }\n if (params.search) {\n return heavy.proxyModes.executeSearch(currentState, params.search, params.regex, params.server, params.includeSchemas);\n }\n if (params.server) {\n return heavy.proxyModes.executeList(currentState, params.server);\n }\n return heavy.proxyModes.executeStatus(currentState);\n },\n });\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/builtin-extensions/pi-mcp-adapter/index.ts"],"names":[],"mappings":"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","sourcesContent":["// @ts-nocheck\nimport type { ExtensionAPI, ExtensionContext, ToolInfo } from \"@ashx-j/lunr-dev\";\nimport type { McpExtensionState } from \"./state.ts\";\nimport type { DirectToolSpec, McpConfig } from \"./types.ts\";\nimport type { MetadataCache } from \"./metadata-cache.ts\";\nimport { existsSync } from \"node:fs\";\nimport { Type } from \"typebox\";\nimport { loadMcpConfig } from \"./config.ts\";\nimport { buildProxyDescription, getMissingConfiguredDirectToolServers, resolveDirectTools } from \"./direct-tools.ts\";\nimport { getMetadataCachePath, loadMetadataCache } from \"./metadata-cache.ts\";\nimport { getConfigPathFromArgv, normalizeDirectToolInputSchema, truncateAtWord } from \"./utils.ts\";\nimport { createMcpDirectToolCallRenderer, renderMcpProxyToolCall, renderMcpToolResult } from \"./tool-result-renderer.ts\";\nimport { toolErrorOverride } from \"./error-signal.ts\";\nimport { abortable, throwIfAborted } from \"./abort.ts\";\n\ntype McpHeavyModules = {\n init: typeof import(\"./init.ts\");\n authFlow: typeof import(\"./mcp-auth-flow.ts\");\n commands: typeof import(\"./commands.ts\");\n proxyModes: typeof import(\"./proxy-modes.ts\");\n directToolExecutor: typeof import(\"./direct-tool-executor.ts\");\n};\n\nfunction shouldBackgroundAutostart(config: McpConfig, cache: MetadataCache | null): boolean {\n const serverEntries = Object.entries(config.mcpServers);\n if (serverEntries.length === 0) return false;\n\n if (!existsSync(getMetadataCachePath())) return true;\n\n for (const [, definition] of serverEntries) {\n const mode = definition.lifecycle ?? \"lazy\";\n if (mode === \"keep-alive\" || mode === \"eager\") return true;\n }\n\n if (process.env.MCP_DIRECT_TOOLS === \"__none__\") return false;\n return getMissingConfiguredDirectToolServers(config, cache).length > 0;\n}\n\nexport default function mcpAdapter(pi: ExtensionAPI) {\n let state: McpExtensionState | null = null;\n let initPromise: Promise<McpExtensionState> | null = null;\n let lifecycleGeneration = 0;\n let sessionAbort = new AbortController();\n const initializingStates = new Set<McpExtensionState>();\n const shutdownPromises = new WeakMap<McpExtensionState, Promise<void>>();\n let heavyModules: McpHeavyModules | null = null;\n let heavyModulesPromise: Promise<McpHeavyModules> | null = null;\n const directExecutors = new Map<string, ReturnType<McpHeavyModules[\"directToolExecutor\"][\"createDirectToolExecutor\"]>>();\n\n function loadHeavyModules(): Promise<McpHeavyModules> {\n if (heavyModules) return Promise.resolve(heavyModules);\n if (!heavyModulesPromise) {\n heavyModulesPromise = (async () => {\n const [init, authFlow, commands, proxyModes, directToolExecutor] = await Promise.all([\n import(\"./init.ts\"),\n import(\"./mcp-auth-flow.ts\"),\n import(\"./commands.ts\"),\n import(\"./proxy-modes.ts\"),\n import(\"./direct-tool-executor.ts\"),\n ]);\n const loaded: McpHeavyModules = { init, authFlow, commands, proxyModes, directToolExecutor };\n heavyModules = loaded;\n return loaded;\n })().catch((error) => {\n heavyModulesPromise = null;\n throw error;\n });\n }\n return heavyModulesPromise;\n }\n\n function shutdownState(currentState: McpExtensionState | null, reason: string): Promise<void> {\n if (!currentState) return Promise.resolve();\n const existing = shutdownPromises.get(currentState);\n if (existing) return existing;\n\n const shutdown = (async () => {\n if (currentState.uiServer) {\n currentState.uiServer.close(reason);\n currentState.uiServer = null;\n }\n\n let flushError: unknown;\n try {\n if (heavyModules) {\n heavyModules.init.flushMetadataCache(currentState);\n }\n } catch (error) {\n flushError = error;\n }\n\n try {\n await currentState.lifecycle.gracefulShutdown();\n } catch (error) {\n if (flushError) {\n console.error(\"MCP: graceful shutdown failed after metadata flush error\", error);\n } else {\n throw error;\n }\n }\n\n if (flushError) {\n throw flushError;\n }\n })();\n shutdownPromises.set(currentState, shutdown);\n return shutdown;\n }\n\n async function shutdownInitializingStates(): Promise<void> {\n const pending = [...initializingStates];\n initializingStates.clear();\n await Promise.all(pending.map((entry) => shutdownState(entry, \"initialization_cancelled\")));\n }\n\n async function shutdownLoadedRuntime(): Promise<void> {\n if (!heavyModules) return;\n await heavyModules.authFlow.shutdownOAuth();\n }\n\n async function runInitialize(\n generation: number,\n sessionPi: ExtensionAPI,\n ctx: ExtensionContext,\n ): Promise<McpExtensionState> {\n const signal = sessionAbort.signal;\n const heavy = await loadHeavyModules();\n throwIfAborted(signal);\n if (generation !== lifecycleGeneration) {\n throw new Error(\"MCP initialization aborted (session changed)\");\n }\n\n await heavy.authFlow.initializeOAuth().catch(err => {\n console.error(\"MCP OAuth initialization failed:\", err);\n });\n\n if (generation !== lifecycleGeneration) {\n throw new Error(\"MCP initialization aborted (session changed)\");\n }\n\n let partial: McpExtensionState | undefined;\n try {\n const initialized = await heavy.init.initializeMcp(sessionPi, ctx, {\n signal,\n onState: (entry: McpExtensionState) => {\n partial = entry;\n initializingStates.add(entry);\n },\n });\n if (!partial) {\n partial = initialized;\n initializingStates.add(initialized);\n }\n throwIfAborted(signal);\n return initialized;\n } catch (error) {\n if (partial) {\n initializingStates.delete(partial);\n await shutdownState(partial, \"initialization_failed\");\n }\n throw error;\n } finally {\n if (partial) initializingStates.delete(partial);\n }\n }\n\n function startSessionInit(generation: number, sessionPi: ExtensionAPI, ctx: ExtensionContext): Promise<McpExtensionState> {\n const promise = runInitialize(generation, sessionPi, ctx);\n initPromise = promise;\n\n promise.then(async (nextState) => {\n if (generation !== lifecycleGeneration || initPromise !== promise) {\n try {\n await shutdownState(nextState, \"stale_session_start\");\n } catch (error) {\n console.error(\"MCP: failed to clean stale session state\", error);\n }\n return;\n }\n\n state = nextState;\n if (heavyModules) {\n heavyModules.init.updateStatusBar(nextState);\n }\n initPromise = null;\n }).catch(err => {\n if (generation !== lifecycleGeneration) {\n return;\n }\n if (initPromise !== promise && initPromise !== null) {\n return;\n }\n console.error(\"MCP initialization failed:\", err);\n initPromise = null;\n });\n\n return promise;\n }\n\n async function ensureState(sessionPi: ExtensionAPI, ctx: ExtensionContext, signal?: AbortSignal): Promise<McpExtensionState> {\n throwIfAborted(signal);\n if (state) return state;\n\n const generation = lifecycleGeneration;\n if (!initPromise) {\n startSessionInit(generation, sessionPi, ctx);\n }\n const promise = initPromise;\n if (!promise) {\n throw new Error(\"MCP not initialized\");\n }\n\n try {\n const nextState = await abortable(promise, signal);\n if (generation !== lifecycleGeneration) {\n throw new Error(\"MCP initialization aborted (session changed)\");\n }\n if (state) return state;\n state = nextState;\n if (initPromise === promise) {\n initPromise = null;\n }\n return state;\n } catch (error) {\n if (initPromise === promise && !signal?.aborted) {\n initPromise = null;\n }\n throw error;\n }\n }\n\n function assertCurrentState(currentState: McpExtensionState): void {\n if (currentState !== state) throw new Error(\"MCP session changed before execution\");\n }\n\n function createLazyDirectToolExecute(spec: DirectToolSpec) {\n return async function execute(toolCallId, params, incomingSignal, onUpdate, ctx) {\n const signal = incomingSignal ? AbortSignal.any([incomingSignal, sessionAbort.signal]) : sessionAbort.signal;\n let currentState: McpExtensionState;\n try {\n currentState = await ensureState(pi, ctx, signal);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [{ type: \"text\" as const, text: `MCP initialization failed: ${message}` }],\n details: { error: \"init_failed\", message },\n };\n }\n\n const heavy = await loadHeavyModules();\n throwIfAborted(signal);\n assertCurrentState(currentState);\n let executor = directExecutors.get(spec.prefixedName);\n if (!executor) {\n executor = heavy.directToolExecutor.createDirectToolExecutor(() => currentState, () => null, spec);\n directExecutors.set(spec.prefixedName, executor);\n }\n return executor(toolCallId, params, signal, onUpdate, ctx);\n };\n }\n\n const earlyConfigPath = getConfigPathFromArgv();\n const earlyConfig = loadMcpConfig(earlyConfigPath);\n const earlyCache = loadMetadataCache();\n const prefix = earlyConfig.settings?.toolPrefix ?? \"server\";\n\n const envRaw = process.env.MCP_DIRECT_TOOLS;\n const directSpecs = envRaw === \"__none__\"\n ? []\n : resolveDirectTools(\n earlyConfig,\n earlyCache,\n prefix,\n envRaw?.split(\",\").map(s => s.trim()).filter(Boolean),\n );\n const missingConfiguredDirectToolServers = getMissingConfiguredDirectToolServers(earlyConfig, earlyCache);\n const shouldRegisterProxyTool =\n earlyConfig.settings?.disableProxyTool !== true\n || directSpecs.length === 0\n || missingConfiguredDirectToolServers.length > 0;\n\n for (const spec of directSpecs) {\n (pi.registerTool as (tool: unknown) => unknown)({\n name: spec.prefixedName,\n label: `MCP: ${spec.originalName}`,\n description: spec.description || \"(no description)\",\n promptSnippet: truncateAtWord(spec.description, 100) || `MCP tool from ${spec.serverName}`,\n parameters: Type.Unsafe(normalizeDirectToolInputSchema(spec.inputSchema) as never),\n execute: createLazyDirectToolExecute(spec),\n renderCall: createMcpDirectToolCallRenderer(spec.prefixedName),\n renderResult: renderMcpToolResult,\n });\n }\n\n const getPiTools = (): ToolInfo[] => pi.getAllTools();\n\n pi.registerFlag(\"mcp-config\", {\n description: \"Path to MCP config file\",\n type: \"string\",\n });\n\n pi.on(\"session_start\", async (_event, ctx) => {\n const generation = ++lifecycleGeneration;\n sessionAbort.abort(new Error(\"MCP session changed\"));\n sessionAbort = new AbortController();\n const previousState = state;\n state = null;\n initPromise = null;\n directExecutors.clear();\n\n try {\n await Promise.all([\n shutdownState(previousState, \"session_restart\"),\n shutdownInitializingStates(),\n shutdownLoadedRuntime(),\n ]);\n } catch (error) {\n console.error(\"MCP: failed to shut down previous session state\", error);\n }\n\n if (generation !== lifecycleGeneration) {\n return;\n }\n\n const configPath = (pi.getFlag(\"mcp-config\") as string | undefined) ?? earlyConfigPath;\n const sessionConfig = loadMcpConfig(configPath, ctx.cwd);\n const sessionCache = loadMetadataCache();\n\n if (!shouldBackgroundAutostart(sessionConfig, sessionCache)) {\n return;\n }\n\n startSessionInit(generation, pi, ctx);\n });\n\n pi.on(\"session_shutdown\", async () => {\n ++lifecycleGeneration;\n sessionAbort.abort(new Error(\"MCP session ended\"));\n const currentState = state;\n state = null;\n initPromise = null;\n directExecutors.clear();\n\n try {\n await Promise.all([\n shutdownState(currentState, \"session_shutdown\"),\n shutdownInitializingStates(),\n shutdownLoadedRuntime(),\n ]);\n } catch (error) {\n console.error(\"MCP: session shutdown cleanup failed\", error);\n }\n });\n\n // Re-flag returned MCP tool failures so pi registers them as errors (see toolErrorOverride).\n pi.on(\"tool_result\", (event) => toolErrorOverride(event.details));\n\n pi.registerCommand(\"mcp\", {\n description: \"Show MCP server status\",\n handler: async (args, ctx) => {\n let currentState: McpExtensionState;\n try {\n currentState = await ensureState(pi, ctx);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n if (ctx.hasUI) ctx.ui.notify(`MCP initialization failed: ${message}`, \"error\");\n return;\n }\n\n const heavy = await loadHeavyModules();\n assertCurrentState(currentState);\n const parts = args?.trim()?.split(/\\s+/) ?? [];\n const subcommand = parts[0] ?? \"\";\n const targetServer = parts[1];\n const rest = parts.slice(1).join(\" \");\n\n switch (subcommand) {\n case \"reconnect\":\n await heavy.commands.reconnectServers(currentState, ctx, targetServer);\n break;\n case \"tools\":\n await heavy.commands.showTools(currentState, ctx);\n break;\n case \"setup\": {\n const result = await heavy.commands.openMcpSetup(currentState, pi, ctx, earlyConfigPath, \"setup\");\n if (result?.configChanged) {\n await ctx.reload();\n return;\n }\n break;\n }\n case \"logout\": {\n const serverName = rest;\n if (!serverName) {\n if (ctx.hasUI) ctx.ui.notify(\"Usage: /mcp logout <server>\", \"error\");\n return;\n }\n await heavy.commands.logoutServer(serverName, currentState, ctx);\n break;\n }\n case \"status\":\n case \"\":\n default:\n if (ctx.hasUI) {\n const result = await heavy.commands.openMcpPanel(currentState, pi, ctx, earlyConfigPath);\n if (result?.configChanged) {\n await ctx.reload();\n return;\n }\n } else {\n await heavy.commands.showStatus(currentState, ctx);\n }\n break;\n }\n },\n });\n\n pi.registerCommand(\"mcp-auth\", {\n description: \"Authenticate with an MCP server (OAuth)\",\n handler: async (args, ctx) => {\n const serverName = args?.trim();\n if (!serverName && !ctx.hasUI) {\n return;\n }\n\n let currentState: McpExtensionState;\n try {\n currentState = await ensureState(pi, ctx);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n if (ctx.hasUI) ctx.ui.notify(`MCP initialization failed: ${message}`, \"error\");\n return;\n }\n\n const heavy = await loadHeavyModules();\n assertCurrentState(currentState);\n\n if (!serverName) {\n await heavy.commands.openMcpAuthPanel(currentState, pi, ctx, earlyConfigPath);\n return;\n }\n\n await heavy.commands.authenticateServer(serverName, currentState.config, ctx);\n },\n });\n\n if (shouldRegisterProxyTool) {\n (pi.registerTool as (tool: unknown) => unknown)({\n name: \"mcp\",\n label: \"MCP\",\n description: buildProxyDescription(earlyConfig, earlyCache, directSpecs),\n promptSnippet: \"MCP gateway - connect to MCP servers and call their tools\",\n renderCall: renderMcpProxyToolCall,\n parameters: Type.Object({\n tool: Type.Optional(Type.String({ description: \"Tool name to call (e.g., 'xcodebuild_list_sims')\" })),\n args: Type.Optional(Type.String({ description: \"Arguments as JSON string (e.g., '{\\\"key\\\": \\\"value\\\"}')\" })),\n connect: Type.Optional(Type.String({ description: \"Server name to connect (lazy connect + metadata refresh)\" })),\n describe: Type.Optional(Type.String({ description: \"Tool name to describe (shows parameters)\" })),\n search: Type.Optional(Type.String({ description: \"Search tools by name/description\" })),\n regex: Type.Optional(Type.Boolean({ description: \"Treat search as regex (default: substring match)\" })),\n includeSchemas: Type.Optional(Type.Boolean({ description: \"Include parameter schemas in search results (default: true)\" })),\n server: Type.Optional(Type.String({ description: \"Filter to specific server (also disambiguates tool calls)\" })),\n action: Type.Optional(Type.String({ description: \"Action: 'ui-messages', 'auth-start', or 'auth-complete'\" })),\n }),\n renderResult: renderMcpToolResult,\n async execute(_toolCallId, params: {\n tool?: string;\n args?: string;\n connect?: string;\n describe?: string;\n search?: string;\n regex?: boolean;\n includeSchemas?: boolean;\n server?: string;\n action?: string;\n }, incomingSignal, _onUpdate, ctx) {\n const signal = incomingSignal ? AbortSignal.any([incomingSignal, sessionAbort.signal]) : sessionAbort.signal;\n let parsedArgs: Record<string, unknown> | undefined;\n if (params.args) {\n try {\n parsedArgs = JSON.parse(params.args);\n if (typeof parsedArgs !== \"object\" || parsedArgs === null || Array.isArray(parsedArgs)) {\n const gotType = Array.isArray(parsedArgs) ? \"array\" : parsedArgs === null ? \"null\" : typeof parsedArgs;\n throw new Error(`Invalid args: expected a JSON object, got ${gotType}`);\n }\n } catch (error) {\n if (error instanceof SyntaxError) {\n throw new Error(`Invalid args JSON: ${error.message}`, { cause: error });\n }\n throw error;\n }\n }\n\n let currentState: McpExtensionState;\n try {\n currentState = await ensureState(pi, ctx, signal);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [{ type: \"text\" as const, text: `MCP initialization failed: ${message}` }],\n details: { error: \"init_failed\", message },\n };\n }\n\n const heavy = await loadHeavyModules();\n throwIfAborted(signal);\n assertCurrentState(currentState);\n\n if (params.action === \"ui-messages\") {\n return heavy.proxyModes.executeUiMessages(currentState);\n }\n if (params.action === \"auth-start\") {\n if (!params.server) {\n return {\n content: [{ type: \"text\" as const, text: \"auth-start requires `server`. Example: mcp({ action: \\\"auth-start\\\", server: \\\"linear-server\\\" })\" }],\n details: { mode: \"auth-start\", error: \"missing_server\" },\n };\n }\n return heavy.proxyModes.executeAuthStart(currentState, params.server);\n }\n if (params.action === \"auth-complete\") {\n if (!params.server) {\n return {\n content: [{ type: \"text\" as const, text: \"auth-complete requires `server`.\" }],\n details: { mode: \"auth-complete\", error: \"missing_server\" },\n };\n }\n const input = parsedArgs?.redirectUrl ?? parsedArgs?.code ?? parsedArgs?.input;\n if (typeof input !== \"string\" || input.trim().length === 0) {\n return {\n content: [{ type: \"text\" as const, text: \"auth-complete requires args with `redirectUrl`, `code`, or `input`.\" }],\n details: { mode: \"auth-complete\", error: \"missing_input\" },\n };\n }\n return heavy.proxyModes.executeAuthComplete(currentState, params.server, input);\n }\n if (params.tool) {\n return heavy.proxyModes.executeCall(currentState, params.tool, parsedArgs, params.server, getPiTools, signal);\n }\n if (params.connect) {\n return heavy.proxyModes.executeConnect(currentState, params.connect, signal);\n }\n if (params.describe) {\n return heavy.proxyModes.executeDescribe(currentState, params.describe);\n }\n if (params.search) {\n return heavy.proxyModes.executeSearch(currentState, params.search, params.regex, params.server, params.includeSchemas);\n }\n if (params.server) {\n return heavy.proxyModes.executeList(currentState, params.server);\n }\n return heavy.proxyModes.executeStatus(currentState);\n },\n });\n }\n}\n"]}
|
|
@@ -4,9 +4,11 @@ import { type ReadResourceResult, type UrlElicitationRequiredError } from "@mode
|
|
|
4
4
|
import type { McpTool, McpResource, ServerDefinition, ServerStreamResultPatchNotification, Transport } from "./types.ts";
|
|
5
5
|
import { type ServerSamplingConfig } from "./sampling-handler.ts";
|
|
6
6
|
import { type ServerElicitationConfig } from "./elicitation-handler.ts";
|
|
7
|
-
interface
|
|
7
|
+
interface PendingConnection {
|
|
8
8
|
client: Client;
|
|
9
9
|
transport: Transport;
|
|
10
|
+
}
|
|
11
|
+
interface ServerConnection extends PendingConnection {
|
|
10
12
|
definition: ServerDefinition;
|
|
11
13
|
tools: McpTool[];
|
|
12
14
|
resources: McpResource[];
|
|
@@ -19,6 +21,8 @@ export declare class McpServerManager {
|
|
|
19
21
|
private readonly defaultCwd?;
|
|
20
22
|
private connections;
|
|
21
23
|
private connectPromises;
|
|
24
|
+
private pendingConnections;
|
|
25
|
+
private closing;
|
|
22
26
|
private uiStreamListeners;
|
|
23
27
|
private samplingConfig;
|
|
24
28
|
private elicitationConfig;
|
|
@@ -45,6 +49,7 @@ export declare class McpServerManager {
|
|
|
45
49
|
registerUiStreamListener(streamToken: string, listener: UiStreamListener): void;
|
|
46
50
|
removeUiStreamListener(streamToken: string): void;
|
|
47
51
|
readResource(name: string, uri: string, signal?: AbortSignal): Promise<ReadResourceResult>;
|
|
52
|
+
private disposeConnection;
|
|
48
53
|
close(name: string): Promise<void>;
|
|
49
54
|
closeAll(): Promise<void>;
|
|
50
55
|
getConnection(name: string): ServerConnection | undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server-manager.d.ts","sourceRoot":"","sources":["../../../src/builtin-extensions/pi-mcp-adapter/server-manager.ts"],"names":[],"mappings":"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","sourcesContent":["// @ts-nocheck\nimport { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport { StdioClientTransport } from \"@modelcontextprotocol/sdk/client/stdio.js\";\nimport { StreamableHTTPClientTransport } from \"@modelcontextprotocol/sdk/client/streamableHttp.js\";\nimport { SSEClientTransport } from \"@modelcontextprotocol/sdk/client/sse.js\";\nimport { UnauthorizedError } from \"@modelcontextprotocol/sdk/client/auth.js\";\nimport type { RequestOptions } from \"@modelcontextprotocol/sdk/shared/protocol.js\";\nimport {\n ElicitationCompleteNotificationSchema,\n type ReadResourceResult,\n type UrlElicitationRequiredError,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport type {\n McpTool,\n McpResource,\n ServerDefinition,\n ServerStreamResultPatchNotification,\n Transport,\n} from \"./types.ts\";\nimport { serverStreamResultPatchNotificationSchema } from \"./types.ts\";\nimport { resolveNpxBinary } from \"./npx-resolver.ts\";\nimport { logger } from \"./logger.ts\";\nimport { McpOAuthProvider } from \"./mcp-oauth-provider.ts\";\nimport { extractOAuthConfig, supportsOAuth } from \"./mcp-auth-flow.ts\";\nimport { registerSamplingHandler, type ServerSamplingConfig } from \"./sampling-handler.ts\";\nimport {\n handleUrlElicitation,\n registerElicitationHandler,\n type ServerElicitationConfig,\n} from \"./elicitation-handler.ts\";\nimport { interpolateEnvRecord, resolveBearerToken, resolveConfigPath } from \"./utils.ts\";\nimport { abortable, throwIfAborted } from \"./abort.ts\";\n\ninterface ServerConnection {\n client: Client;\n transport: Transport;\n definition: ServerDefinition;\n tools: McpTool[];\n resources: McpResource[];\n lastUsedAt: number;\n inFlight: number;\n status: \"connected\" | \"closed\" | \"needs-auth\";\n}\n\ntype UiStreamListener = (serverName: string, notification: ServerStreamResultPatchNotification[\"params\"]) => void;\n\nexport class McpServerManager {\n private connections = new Map<string, ServerConnection>();\n private connectPromises = new Map<string, Promise<ServerConnection>>();\n private uiStreamListeners = new Map<string, UiStreamListener>();\n private samplingConfig: ServerSamplingConfig | undefined;\n private elicitationConfig: ServerElicitationConfig | undefined;\n private acceptedUrlElicitations = new Map<string, Set<string>>();\n private defaultRequestTimeoutMs: number | undefined;\n\n /** Default cwd for stdio servers without an explicit config `cwd`. */\n constructor(private readonly defaultCwd?: string) {}\n\n setSamplingConfig(config: ServerSamplingConfig | undefined): void {\n this.samplingConfig = config;\n }\n\n setElicitationConfig(config: ServerElicitationConfig | undefined): void {\n this.elicitationConfig = config;\n }\n\n setDefaultRequestTimeoutMs(timeoutMs: number | undefined): void {\n this.defaultRequestTimeoutMs = normalizeRequestTimeoutMs(timeoutMs);\n }\n\n getRequestOptions(name: string, signal?: AbortSignal): RequestOptions | undefined {\n const connection = this.connections.get(name);\n return this.buildRequestOptions(connection?.definition, signal);\n }\n\n private getResolvedRequestTimeoutMs(definition?: ServerDefinition): number | undefined {\n if (definition?.requestTimeoutMs !== undefined) {\n return normalizeRequestTimeoutMs(definition.requestTimeoutMs);\n }\n return this.defaultRequestTimeoutMs;\n }\n\n private buildRequestOptions(\n definition?: ServerDefinition,\n signal?: AbortSignal,\n ): RequestOptions | undefined {\n const timeout = this.getResolvedRequestTimeoutMs(definition);\n\n if (!signal && timeout === undefined) {\n return undefined;\n }\n\n return {\n ...(signal ? { signal } : {}),\n ...(timeout !== undefined ? { timeout } : {}),\n };\n }\n\n async connect(name: string, definition: ServerDefinition, signal?: AbortSignal): Promise<ServerConnection> {\n throwIfAborted(signal);\n // Dedupe concurrent connection attempts\n if (this.connectPromises.has(name)) {\n return abortable(this.connectPromises.get(name)!, signal);\n }\n\n // Reuse existing connection if healthy\n const existing = this.connections.get(name);\n if (existing?.status === \"connected\") {\n existing.lastUsedAt = Date.now();\n return existing;\n }\n\n const promise = this.createConnection(name, definition, signal);\n this.connectPromises.set(name, promise);\n\n try {\n const connection = await promise;\n this.connections.set(name, connection);\n return connection;\n } finally {\n this.connectPromises.delete(name);\n }\n }\n\n private async createConnection(\n name: string,\n definition: ServerDefinition,\n signal?: AbortSignal,\n ): Promise<ServerConnection> {\n throwIfAborted(signal);\n const client = this.createClient(name);\n\n let transport: Transport;\n\n if (definition.command) {\n let command = definition.command;\n let args = definition.args ?? [];\n\n if (command === \"npx\" || command === \"npm\") {\n const resolved = await resolveNpxBinary(command, args);\n if (resolved) {\n command = resolved.isJs ? \"node\" : resolved.binPath;\n args = resolved.isJs ? [resolved.binPath, ...resolved.extraArgs] : resolved.extraArgs;\n logger.debug(`${name} resolved to ${resolved.binPath} (skipping npm parent)`);\n }\n }\n\n transport = new StdioClientTransport({\n command,\n args,\n env: resolveEnv(definition.env),\n cwd: resolveConfigPath(definition.cwd) ?? this.defaultCwd,\n stderr: definition.debug ? \"inherit\" : \"ignore\",\n });\n } else if (definition.url) {\n // HTTP transport with fallback\n transport = await this.createHttpTransport(definition, name, signal);\n } else {\n throw new Error(`Server ${name} has no command or url`);\n }\n\n const requestOptions = this.buildRequestOptions(definition, signal);\n\n try {\n await client.connect(transport, requestOptions);\n this.attachAdapterNotificationHandlers(name, client);\n\n // Discover tools and resources\n const [tools, resources] = await Promise.all([\n this.fetchAllTools(client, requestOptions),\n this.fetchAllResources(client, requestOptions),\n ]);\n\n return {\n client,\n transport,\n definition,\n tools,\n resources,\n lastUsedAt: Date.now(),\n inFlight: 0,\n status: \"connected\",\n };\n } catch (error) {\n // Check for UnauthorizedError - server requires OAuth\n if (error instanceof UnauthorizedError && supportsOAuth(definition)) {\n // Clean up both client and transport before reporting needs-auth.\n await client.close().catch(() => {});\n await transport.close().catch(() => {});\n\n return {\n client,\n transport,\n definition,\n tools: [],\n resources: [],\n lastUsedAt: Date.now(),\n inFlight: 0,\n status: \"needs-auth\",\n };\n }\n\n // Clean up both client and transport on any error\n await client.close().catch(() => {});\n await transport.close().catch(() => {});\n throw error;\n }\n }\n\n private buildClientCapabilities() {\n return {\n ...(this.samplingConfig ? { sampling: {} } : {}),\n ...(this.elicitationConfig\n ? {\n elicitation: {\n form: {},\n ...(this.elicitationConfig.allowUrl ? { url: {} } : {}),\n },\n }\n : {}),\n };\n }\n\n private createClient(serverName: string): Client {\n const capabilities = this.buildClientCapabilities();\n const client = new Client(\n { name: `pi-mcp-${serverName}`, version: \"1.0.0\" },\n Object.keys(capabilities).length > 0 ? { capabilities } : undefined,\n );\n if (this.samplingConfig) {\n registerSamplingHandler(client, { ...this.samplingConfig, serverName });\n }\n if (this.elicitationConfig) {\n registerElicitationHandler(client, {\n ...this.elicitationConfig,\n serverName,\n onUrlAccepted: elicitationId => this.rememberUrlElicitation(serverName, elicitationId),\n });\n if (this.elicitationConfig.allowUrl) {\n client.setNotificationHandler(ElicitationCompleteNotificationSchema, notification => {\n const accepted = this.acceptedUrlElicitations.get(serverName);\n if (!accepted?.delete(notification.params.elicitationId)) return;\n this.elicitationConfig?.ui.notify(\n `MCP browser interaction for ${serverName} completed. You can retry the tool now.`,\n \"info\",\n );\n });\n }\n }\n return client;\n }\n\n async handleUrlElicitationRequired(\n serverName: string,\n error: UrlElicitationRequiredError,\n ): Promise<\"accept\" | \"decline\" | \"cancel\"> {\n if (!this.elicitationConfig?.allowUrl) return \"cancel\";\n for (const params of error.elicitations) {\n const result = await handleUrlElicitation({\n ...this.elicitationConfig,\n serverName,\n onUrlAccepted: elicitationId => this.rememberUrlElicitation(serverName, elicitationId),\n }, params);\n if (result.action !== \"accept\") return result.action;\n }\n return \"accept\";\n }\n\n private rememberUrlElicitation(serverName: string, elicitationId: string): void {\n let accepted = this.acceptedUrlElicitations.get(serverName);\n if (!accepted) {\n accepted = new Set();\n this.acceptedUrlElicitations.set(serverName, accepted);\n }\n accepted.add(elicitationId);\n }\n\n private async createHttpTransport(\n definition: ServerDefinition,\n serverName: string,\n signal?: AbortSignal,\n ): Promise<Transport> {\n throwIfAborted(signal);\n const url = new URL(definition.url!);\n\n // Build headers first (including any bearer token)\n const headers = resolveHeaders(definition.headers) ?? {};\n\n // For bearer auth, add the token to headers BEFORE creating requestInit\n if (definition.auth === \"bearer\") {\n const token = resolveBearerToken(definition);\n if (token) {\n headers[\"Authorization\"] = `Bearer ${token}`;\n }\n }\n\n // Create request init with headers (Authorization now included for bearer auth)\n const requestInit = Object.keys(headers).length > 0 ? { headers } : undefined;\n\n // For OAuth servers, create an auth provider\n let authProvider: McpOAuthProvider | undefined;\n if (supportsOAuth(definition)) {\n const oauthConfig = extractOAuthConfig(definition);\n authProvider = new McpOAuthProvider(\n serverName,\n definition.url!,\n oauthConfig,\n {\n onRedirect: async (_authUrl) => {\n // URL is captured by startAuth, no need to log\n },\n }\n );\n }\n\n // Try StreamableHTTP first (modern MCP servers)\n const streamableTransport = new StreamableHTTPClientTransport(url, {\n requestInit,\n authProvider,\n });\n\n try {\n // Create a test client to verify the transport works\n const testClient = new Client({ name: \"pi-mcp-probe\", version: \"2.1.2\" });\n await testClient.connect(streamableTransport, this.buildRequestOptions(definition, signal));\n await testClient.close().catch(() => {});\n // Close probe transport before creating fresh one\n await streamableTransport.close().catch(() => {});\n\n // StreamableHTTP works - create fresh transport for actual use\n return new StreamableHTTPClientTransport(url, { requestInit, authProvider });\n } catch (error) {\n // StreamableHTTP failed, close and try SSE fallback\n await streamableTransport.close().catch(() => {});\n\n // Host cancellation is not transport capability evidence; do not fall\n // through to SSE when the caller is trying to cancel the connect.\n if (signal?.aborted) {\n throwIfAborted(signal);\n }\n\n // If this was an UnauthorizedError, don't try SSE - the server needs auth\n if (error instanceof UnauthorizedError) {\n throw error;\n }\n\n // SSE is the legacy transport\n return new SSEClientTransport(url, { requestInit, authProvider });\n }\n }\n\n private async fetchAllTools(client: Client, requestOptions?: RequestOptions): Promise<McpTool[]> {\n const allTools: McpTool[] = [];\n let cursor: string | undefined;\n\n do {\n const result = await client.listTools(cursor ? { cursor } : undefined, requestOptions);\n allTools.push(...(result.tools ?? []));\n cursor = result.nextCursor;\n } while (cursor);\n\n return allTools;\n }\n\n private async fetchAllResources(client: Client, requestOptions?: RequestOptions): Promise<McpResource[]> {\n try {\n const allResources: McpResource[] = [];\n let cursor: string | undefined;\n\n do {\n const result = await client.listResources(cursor ? { cursor } : undefined, requestOptions);\n allResources.push(...(result.resources ?? []));\n cursor = result.nextCursor;\n } while (cursor);\n\n return allResources;\n } catch {\n if (requestOptions?.signal?.aborted) {\n throwIfAborted(requestOptions.signal);\n }\n // Server may not support resources\n return [];\n }\n }\n\n private attachAdapterNotificationHandlers(serverName: string, client: Client): void {\n client.setNotificationHandler(serverStreamResultPatchNotificationSchema, (notification) => {\n const listener = this.uiStreamListeners.get(notification.params.streamToken);\n if (!listener) return;\n listener(serverName, notification.params);\n });\n }\n\n registerUiStreamListener(streamToken: string, listener: UiStreamListener): void {\n this.uiStreamListeners.set(streamToken, listener);\n }\n\n removeUiStreamListener(streamToken: string): void {\n this.uiStreamListeners.delete(streamToken);\n }\n\n async readResource(name: string, uri: string, signal?: AbortSignal): Promise<ReadResourceResult> {\n const connection = this.connections.get(name);\n if (!connection || connection.status !== \"connected\") {\n throw new Error(`Server \"${name}\" is not connected`);\n }\n\n try {\n this.touch(name);\n this.incrementInFlight(name);\n return await connection.client.readResource({ uri }, this.getRequestOptions(name, signal));\n } finally {\n this.decrementInFlight(name);\n this.touch(name);\n }\n }\n\n async close(name: string): Promise<void> {\n const connection = this.connections.get(name);\n if (!connection) return;\n\n // Delete from map BEFORE async cleanup to prevent a race where a\n // concurrent connect() creates a new connection that our deferred\n // delete() would then remove, orphaning the new server process.\n connection.status = \"closed\";\n this.connections.delete(name);\n this.acceptedUrlElicitations.delete(name);\n await connection.client.close().catch(() => {});\n await connection.transport.close().catch(() => {});\n }\n\n async closeAll(): Promise<void> {\n const names = [...this.connections.keys()];\n await Promise.all(names.map(name => this.close(name)));\n }\n\n getConnection(name: string): ServerConnection | undefined {\n return this.connections.get(name);\n }\n\n getAllConnections(): Map<string, ServerConnection> {\n return new Map(this.connections);\n }\n\n touch(name: string): void {\n const connection = this.connections.get(name);\n if (connection) {\n connection.lastUsedAt = Date.now();\n }\n }\n\n incrementInFlight(name: string): void {\n const connection = this.connections.get(name);\n if (connection) {\n connection.inFlight = (connection.inFlight ?? 0) + 1;\n }\n }\n\n decrementInFlight(name: string): void {\n const connection = this.connections.get(name);\n if (connection && connection.inFlight) {\n connection.inFlight--;\n }\n }\n\n isIdle(name: string, timeoutMs: number): boolean {\n const connection = this.connections.get(name);\n if (!connection || connection.status !== \"connected\") return false;\n if (connection.inFlight > 0) return false;\n return (Date.now() - connection.lastUsedAt) > timeoutMs;\n }\n}\n\n/**\n * Resolve environment variables with interpolation.\n */\nfunction resolveEnv(env?: Record<string, string>): Record<string, string> {\n // Copy process.env, filtering out undefined values\n const resolved: Record<string, string> = {};\n for (const [key, value] of Object.entries(process.env)) {\n if (value !== undefined) {\n resolved[key] = value;\n }\n }\n\n if (!env) return resolved;\n\n const overrides = interpolateEnvRecord(env);\n return overrides ? { ...resolved, ...overrides } : resolved;\n}\n\n/**\n * Resolve headers with environment variable interpolation.\n */\nfunction resolveHeaders(headers?: Record<string, string>): Record<string, string> | undefined {\n return interpolateEnvRecord(headers);\n}\n\nfunction normalizeRequestTimeoutMs(timeoutMs: number | undefined): number | undefined {\n return typeof timeoutMs === \"number\" && Number.isFinite(timeoutMs) && timeoutMs > 0\n ? timeoutMs\n : undefined;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"server-manager.d.ts","sourceRoot":"","sources":["../../../src/builtin-extensions/pi-mcp-adapter/server-manager.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAKnE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8CAA8C,CAAC;AACnF,OAAO,EAEL,KAAK,kBAAkB,EACvB,KAAK,2BAA2B,EACjC,MAAM,oCAAoC,CAAC;AAC5C,OAAO,KAAK,EACV,OAAO,EACP,WAAW,EACX,gBAAgB,EAChB,mCAAmC,EACnC,SAAS,EACV,MAAM,YAAY,CAAC;AAMpB,OAAO,EAA2B,KAAK,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC3F,OAAO,EAGL,KAAK,uBAAuB,EAC7B,MAAM,0BAA0B,CAAC;AAIlC,UAAU,iBAAiB;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,SAAS,CAAC;CACtB;AAED,UAAU,gBAAiB,SAAQ,iBAAiB;IAClD,UAAU,EAAE,gBAAgB,CAAC;IAC7B,KAAK,EAAE,OAAO,EAAE,CAAC;IACjB,SAAS,EAAE,WAAW,EAAE,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,WAAW,GAAG,QAAQ,GAAG,YAAY,CAAC;CAC/C;AAED,KAAK,gBAAgB,GAAG,CAAC,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,mCAAmC,CAAC,QAAQ,CAAC,KAAK,IAAI,CAAC;AAElH,qBAAa,gBAAgB;IAYf,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC;IAXxC,OAAO,CAAC,WAAW,CAAuC;IAC1D,OAAO,CAAC,eAAe,CAAgD;IACvE,OAAO,CAAC,kBAAkB,CAAwC;IAClE,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,iBAAiB,CAAuC;IAChE,OAAO,CAAC,cAAc,CAAmC;IACzD,OAAO,CAAC,iBAAiB,CAAsC;IAC/D,OAAO,CAAC,uBAAuB,CAAkC;IACjE,OAAO,CAAC,uBAAuB,CAAqB;IAEpD,sEAAsE;IACtE,YAA6B,UAAU,CAAC,oBAAQ,EAAI;IAEpD,iBAAiB,CAAC,MAAM,EAAE,oBAAoB,GAAG,SAAS,GAAG,IAAI,CAEhE;IAED,oBAAoB,CAAC,MAAM,EAAE,uBAAuB,GAAG,SAAS,GAAG,IAAI,CAEtE;IAED,0BAA0B,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAE9D;IAED,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,cAAc,GAAG,SAAS,CAGhF;IAED,OAAO,CAAC,2BAA2B;IAOnC,OAAO,CAAC,mBAAmB;IAgBrB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA+BzG;YAEa,gBAAgB;IAyF9B,OAAO,CAAC,uBAAuB;IAc/B,OAAO,CAAC,YAAY;IA6Bd,4BAA4B,CAChC,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,2BAA2B,GACjC,OAAO,CAAC,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAC,CAW1C;IAED,OAAO,CAAC,sBAAsB;YAShB,mBAAmB;YA0EnB,aAAa;YAab,iBAAiB;IAqB/B,OAAO,CAAC,iCAAiC;IAQzC,wBAAwB,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,gBAAgB,GAAG,IAAI,CAE9E;IAED,sBAAsB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAEhD;IAEK,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAc/F;YAEa,iBAAiB;IAKzB,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAWvC;IAEK,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAQ9B;IAED,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS,CAExD;IAED,iBAAiB,IAAI,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAEjD;IAED,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAKxB;IAED,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAKpC;IAED,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAKpC;IAED,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAK/C;CACF","sourcesContent":["// @ts-nocheck\nimport { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport { StdioClientTransport } from \"@modelcontextprotocol/sdk/client/stdio.js\";\nimport { StreamableHTTPClientTransport } from \"@modelcontextprotocol/sdk/client/streamableHttp.js\";\nimport { SSEClientTransport } from \"@modelcontextprotocol/sdk/client/sse.js\";\nimport { UnauthorizedError } from \"@modelcontextprotocol/sdk/client/auth.js\";\nimport type { RequestOptions } from \"@modelcontextprotocol/sdk/shared/protocol.js\";\nimport {\n ElicitationCompleteNotificationSchema,\n type ReadResourceResult,\n type UrlElicitationRequiredError,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport type {\n McpTool,\n McpResource,\n ServerDefinition,\n ServerStreamResultPatchNotification,\n Transport,\n} from \"./types.ts\";\nimport { serverStreamResultPatchNotificationSchema } from \"./types.ts\";\nimport { resolveNpxBinary } from \"./npx-resolver.ts\";\nimport { logger } from \"./logger.ts\";\nimport { McpOAuthProvider } from \"./mcp-oauth-provider.ts\";\nimport { extractOAuthConfig, supportsOAuth } from \"./mcp-auth-flow.ts\";\nimport { registerSamplingHandler, type ServerSamplingConfig } from \"./sampling-handler.ts\";\nimport {\n handleUrlElicitation,\n registerElicitationHandler,\n type ServerElicitationConfig,\n} from \"./elicitation-handler.ts\";\nimport { interpolateEnvRecord, resolveBearerToken, resolveConfigPath } from \"./utils.ts\";\nimport { abortable, throwIfAborted } from \"./abort.ts\";\n\ninterface PendingConnection {\n client: Client;\n transport: Transport;\n}\n\ninterface ServerConnection extends PendingConnection {\n definition: ServerDefinition;\n tools: McpTool[];\n resources: McpResource[];\n lastUsedAt: number;\n inFlight: number;\n status: \"connected\" | \"closed\" | \"needs-auth\";\n}\n\ntype UiStreamListener = (serverName: string, notification: ServerStreamResultPatchNotification[\"params\"]) => void;\n\nexport class McpServerManager {\n private connections = new Map<string, ServerConnection>();\n private connectPromises = new Map<string, Promise<ServerConnection>>();\n private pendingConnections = new Map<string, PendingConnection>();\n private closing = false;\n private uiStreamListeners = new Map<string, UiStreamListener>();\n private samplingConfig: ServerSamplingConfig | undefined;\n private elicitationConfig: ServerElicitationConfig | undefined;\n private acceptedUrlElicitations = new Map<string, Set<string>>();\n private defaultRequestTimeoutMs: number | undefined;\n\n /** Default cwd for stdio servers without an explicit config `cwd`. */\n constructor(private readonly defaultCwd?: string) {}\n\n setSamplingConfig(config: ServerSamplingConfig | undefined): void {\n this.samplingConfig = config;\n }\n\n setElicitationConfig(config: ServerElicitationConfig | undefined): void {\n this.elicitationConfig = config;\n }\n\n setDefaultRequestTimeoutMs(timeoutMs: number | undefined): void {\n this.defaultRequestTimeoutMs = normalizeRequestTimeoutMs(timeoutMs);\n }\n\n getRequestOptions(name: string, signal?: AbortSignal): RequestOptions | undefined {\n const connection = this.connections.get(name);\n return this.buildRequestOptions(connection?.definition, signal);\n }\n\n private getResolvedRequestTimeoutMs(definition?: ServerDefinition): number | undefined {\n if (definition?.requestTimeoutMs !== undefined) {\n return normalizeRequestTimeoutMs(definition.requestTimeoutMs);\n }\n return this.defaultRequestTimeoutMs;\n }\n\n private buildRequestOptions(\n definition?: ServerDefinition,\n signal?: AbortSignal,\n ): RequestOptions | undefined {\n const timeout = this.getResolvedRequestTimeoutMs(definition);\n\n if (!signal && timeout === undefined) {\n return undefined;\n }\n\n return {\n ...(signal ? { signal } : {}),\n ...(timeout !== undefined ? { timeout } : {}),\n };\n }\n\n async connect(name: string, definition: ServerDefinition, signal?: AbortSignal): Promise<ServerConnection> {\n throwIfAborted(signal);\n if (this.closing) throw new Error(\"MCP server manager is closed\");\n // Dedupe concurrent connection attempts\n if (this.connectPromises.has(name)) {\n return abortable(this.connectPromises.get(name)!, signal);\n }\n\n // Reuse existing connection if healthy\n const existing = this.connections.get(name);\n if (existing?.status === \"connected\") {\n existing.lastUsedAt = Date.now();\n return existing;\n }\n\n const promise = this.createConnection(name, definition, signal).then(async connection => {\n if (this.closing || signal?.aborted) {\n await this.disposeConnection(connection);\n throwIfAborted(signal);\n throw new Error(\"MCP server manager closed during connection\");\n }\n this.connections.set(name, connection);\n return connection;\n });\n this.connectPromises.set(name, promise);\n\n try {\n return await promise;\n } finally {\n if (this.connectPromises.get(name) === promise) this.connectPromises.delete(name);\n }\n }\n\n private async createConnection(\n name: string,\n definition: ServerDefinition,\n signal?: AbortSignal,\n ): Promise<ServerConnection> {\n throwIfAborted(signal);\n const client = this.createClient(name);\n\n let transport: Transport;\n\n if (definition.command) {\n let command = definition.command;\n let args = definition.args ?? [];\n\n if (command === \"npx\" || command === \"npm\") {\n const resolved = await resolveNpxBinary(command, args);\n if (resolved) {\n command = resolved.isJs ? \"node\" : resolved.binPath;\n args = resolved.isJs ? [resolved.binPath, ...resolved.extraArgs] : resolved.extraArgs;\n logger.debug(`${name} resolved to ${resolved.binPath} (skipping npm parent)`);\n }\n }\n\n transport = new StdioClientTransport({\n command,\n args,\n env: resolveEnv(definition.env),\n cwd: resolveConfigPath(definition.cwd) ?? this.defaultCwd,\n stderr: definition.debug ? \"inherit\" : \"ignore\",\n });\n } else if (definition.url) {\n // HTTP transport with fallback\n transport = await this.createHttpTransport(definition, name, signal);\n } else {\n throw new Error(`Server ${name} has no command or url`);\n }\n\n const requestOptions = this.buildRequestOptions(definition, signal);\n const pending = { client, transport };\n this.pendingConnections.set(name, pending);\n\n try {\n await client.connect(transport, requestOptions);\n this.attachAdapterNotificationHandlers(name, client);\n\n // Discover tools and resources\n const [tools, resources] = await Promise.all([\n this.fetchAllTools(client, requestOptions),\n this.fetchAllResources(client, requestOptions),\n ]);\n\n return {\n client,\n transport,\n definition,\n tools,\n resources,\n lastUsedAt: Date.now(),\n inFlight: 0,\n status: \"connected\",\n };\n } catch (error) {\n // Check for UnauthorizedError - server requires OAuth\n if (error instanceof UnauthorizedError && supportsOAuth(definition)) {\n // Clean up both client and transport before reporting needs-auth.\n await client.close().catch(() => {});\n await transport.close().catch(() => {});\n\n return {\n client,\n transport,\n definition,\n tools: [],\n resources: [],\n lastUsedAt: Date.now(),\n inFlight: 0,\n status: \"needs-auth\",\n };\n }\n\n // Clean up both client and transport on any error\n await client.close().catch(() => {});\n await transport.close().catch(() => {});\n throw error;\n } finally {\n if (this.pendingConnections.get(name) === pending) this.pendingConnections.delete(name);\n }\n }\n\n private buildClientCapabilities() {\n return {\n ...(this.samplingConfig ? { sampling: {} } : {}),\n ...(this.elicitationConfig\n ? {\n elicitation: {\n form: {},\n ...(this.elicitationConfig.allowUrl ? { url: {} } : {}),\n },\n }\n : {}),\n };\n }\n\n private createClient(serverName: string): Client {\n const capabilities = this.buildClientCapabilities();\n const client = new Client(\n { name: `pi-mcp-${serverName}`, version: \"1.0.0\" },\n Object.keys(capabilities).length > 0 ? { capabilities } : undefined,\n );\n if (this.samplingConfig) {\n registerSamplingHandler(client, { ...this.samplingConfig, serverName });\n }\n if (this.elicitationConfig) {\n registerElicitationHandler(client, {\n ...this.elicitationConfig,\n serverName,\n onUrlAccepted: elicitationId => this.rememberUrlElicitation(serverName, elicitationId),\n });\n if (this.elicitationConfig.allowUrl) {\n client.setNotificationHandler(ElicitationCompleteNotificationSchema, notification => {\n const accepted = this.acceptedUrlElicitations.get(serverName);\n if (!accepted?.delete(notification.params.elicitationId)) return;\n this.elicitationConfig?.ui.notify(\n `MCP browser interaction for ${serverName} completed. You can retry the tool now.`,\n \"info\",\n );\n });\n }\n }\n return client;\n }\n\n async handleUrlElicitationRequired(\n serverName: string,\n error: UrlElicitationRequiredError,\n ): Promise<\"accept\" | \"decline\" | \"cancel\"> {\n if (!this.elicitationConfig?.allowUrl) return \"cancel\";\n for (const params of error.elicitations) {\n const result = await handleUrlElicitation({\n ...this.elicitationConfig,\n serverName,\n onUrlAccepted: elicitationId => this.rememberUrlElicitation(serverName, elicitationId),\n }, params);\n if (result.action !== \"accept\") return result.action;\n }\n return \"accept\";\n }\n\n private rememberUrlElicitation(serverName: string, elicitationId: string): void {\n let accepted = this.acceptedUrlElicitations.get(serverName);\n if (!accepted) {\n accepted = new Set();\n this.acceptedUrlElicitations.set(serverName, accepted);\n }\n accepted.add(elicitationId);\n }\n\n private async createHttpTransport(\n definition: ServerDefinition,\n serverName: string,\n signal?: AbortSignal,\n ): Promise<Transport> {\n throwIfAborted(signal);\n const url = new URL(definition.url!);\n\n // Build headers first (including any bearer token)\n const headers = resolveHeaders(definition.headers) ?? {};\n\n // For bearer auth, add the token to headers BEFORE creating requestInit\n if (definition.auth === \"bearer\") {\n const token = resolveBearerToken(definition);\n if (token) {\n headers[\"Authorization\"] = `Bearer ${token}`;\n }\n }\n\n // Create request init with headers (Authorization now included for bearer auth)\n const requestInit = Object.keys(headers).length > 0 ? { headers } : undefined;\n\n // For OAuth servers, create an auth provider\n let authProvider: McpOAuthProvider | undefined;\n if (supportsOAuth(definition)) {\n const oauthConfig = extractOAuthConfig(definition);\n authProvider = new McpOAuthProvider(\n serverName,\n definition.url!,\n oauthConfig,\n {\n onRedirect: async (_authUrl) => {\n // URL is captured by startAuth, no need to log\n },\n }\n );\n }\n\n // Try StreamableHTTP first (modern MCP servers)\n const streamableTransport = new StreamableHTTPClientTransport(url, {\n requestInit,\n authProvider,\n });\n\n try {\n // Create a test client to verify the transport works\n const testClient = new Client({ name: \"pi-mcp-probe\", version: \"2.1.2\" });\n await testClient.connect(streamableTransport, this.buildRequestOptions(definition, signal));\n await testClient.close().catch(() => {});\n // Close probe transport before creating fresh one\n await streamableTransport.close().catch(() => {});\n\n // StreamableHTTP works - create fresh transport for actual use\n return new StreamableHTTPClientTransport(url, { requestInit, authProvider });\n } catch (error) {\n // StreamableHTTP failed, close and try SSE fallback\n await streamableTransport.close().catch(() => {});\n\n // Host cancellation is not transport capability evidence; do not fall\n // through to SSE when the caller is trying to cancel the connect.\n if (signal?.aborted) {\n throwIfAborted(signal);\n }\n\n // If this was an UnauthorizedError, don't try SSE - the server needs auth\n if (error instanceof UnauthorizedError) {\n throw error;\n }\n\n // SSE is the legacy transport\n return new SSEClientTransport(url, { requestInit, authProvider });\n }\n }\n\n private async fetchAllTools(client: Client, requestOptions?: RequestOptions): Promise<McpTool[]> {\n const allTools: McpTool[] = [];\n let cursor: string | undefined;\n\n do {\n const result = await client.listTools(cursor ? { cursor } : undefined, requestOptions);\n allTools.push(...(result.tools ?? []));\n cursor = result.nextCursor;\n } while (cursor);\n\n return allTools;\n }\n\n private async fetchAllResources(client: Client, requestOptions?: RequestOptions): Promise<McpResource[]> {\n try {\n const allResources: McpResource[] = [];\n let cursor: string | undefined;\n\n do {\n const result = await client.listResources(cursor ? { cursor } : undefined, requestOptions);\n allResources.push(...(result.resources ?? []));\n cursor = result.nextCursor;\n } while (cursor);\n\n return allResources;\n } catch {\n if (requestOptions?.signal?.aborted) {\n throwIfAborted(requestOptions.signal);\n }\n // Server may not support resources\n return [];\n }\n }\n\n private attachAdapterNotificationHandlers(serverName: string, client: Client): void {\n client.setNotificationHandler(serverStreamResultPatchNotificationSchema, (notification) => {\n const listener = this.uiStreamListeners.get(notification.params.streamToken);\n if (!listener) return;\n listener(serverName, notification.params);\n });\n }\n\n registerUiStreamListener(streamToken: string, listener: UiStreamListener): void {\n this.uiStreamListeners.set(streamToken, listener);\n }\n\n removeUiStreamListener(streamToken: string): void {\n this.uiStreamListeners.delete(streamToken);\n }\n\n async readResource(name: string, uri: string, signal?: AbortSignal): Promise<ReadResourceResult> {\n const connection = this.connections.get(name);\n if (!connection || connection.status !== \"connected\") {\n throw new Error(`Server \"${name}\" is not connected`);\n }\n\n try {\n this.touch(name);\n this.incrementInFlight(name);\n return await connection.client.readResource({ uri }, this.getRequestOptions(name, signal));\n } finally {\n this.decrementInFlight(name);\n this.touch(name);\n }\n }\n\n private async disposeConnection(connection: PendingConnection): Promise<void> {\n await connection.client.close().catch(() => {});\n await connection.transport.close().catch(() => {});\n }\n\n async close(name: string): Promise<void> {\n const connection = this.connections.get(name);\n if (!connection) return;\n\n // Delete from map BEFORE async cleanup to prevent a race where a\n // concurrent connect() creates a new connection that our deferred\n // delete() would then remove, orphaning the new server process.\n connection.status = \"closed\";\n this.connections.delete(name);\n this.acceptedUrlElicitations.delete(name);\n await this.disposeConnection(connection);\n }\n\n async closeAll(): Promise<void> {\n this.closing = true;\n const names = [...this.connections.keys()];\n const pending = [...this.pendingConnections.values()];\n await Promise.all([\n ...names.map(name => this.close(name)),\n ...pending.map(connection => this.disposeConnection(connection)),\n ]);\n }\n\n getConnection(name: string): ServerConnection | undefined {\n return this.connections.get(name);\n }\n\n getAllConnections(): Map<string, ServerConnection> {\n return new Map(this.connections);\n }\n\n touch(name: string): void {\n const connection = this.connections.get(name);\n if (connection) {\n connection.lastUsedAt = Date.now();\n }\n }\n\n incrementInFlight(name: string): void {\n const connection = this.connections.get(name);\n if (connection) {\n connection.inFlight = (connection.inFlight ?? 0) + 1;\n }\n }\n\n decrementInFlight(name: string): void {\n const connection = this.connections.get(name);\n if (connection && connection.inFlight) {\n connection.inFlight--;\n }\n }\n\n isIdle(name: string, timeoutMs: number): boolean {\n const connection = this.connections.get(name);\n if (!connection || connection.status !== \"connected\") return false;\n if (connection.inFlight > 0) return false;\n return (Date.now() - connection.lastUsedAt) > timeoutMs;\n }\n}\n\n/**\n * Resolve environment variables with interpolation.\n */\nfunction resolveEnv(env?: Record<string, string>): Record<string, string> {\n // Copy process.env, filtering out undefined values\n const resolved: Record<string, string> = {};\n for (const [key, value] of Object.entries(process.env)) {\n if (value !== undefined) {\n resolved[key] = value;\n }\n }\n\n if (!env) return resolved;\n\n const overrides = interpolateEnvRecord(env);\n return overrides ? { ...resolved, ...overrides } : resolved;\n}\n\n/**\n * Resolve headers with environment variable interpolation.\n */\nfunction resolveHeaders(headers?: Record<string, string>): Record<string, string> | undefined {\n return interpolateEnvRecord(headers);\n}\n\nfunction normalizeRequestTimeoutMs(timeoutMs: number | undefined): number | undefined {\n return typeof timeoutMs === \"number\" && Number.isFinite(timeoutMs) && timeoutMs > 0\n ? timeoutMs\n : undefined;\n}\n"]}
|
|
@@ -18,6 +18,8 @@ export class McpServerManager {
|
|
|
18
18
|
defaultCwd;
|
|
19
19
|
connections = new Map();
|
|
20
20
|
connectPromises = new Map();
|
|
21
|
+
pendingConnections = new Map();
|
|
22
|
+
closing = false;
|
|
21
23
|
uiStreamListeners = new Map();
|
|
22
24
|
samplingConfig;
|
|
23
25
|
elicitationConfig;
|
|
@@ -58,6 +60,8 @@ export class McpServerManager {
|
|
|
58
60
|
}
|
|
59
61
|
async connect(name, definition, signal) {
|
|
60
62
|
throwIfAborted(signal);
|
|
63
|
+
if (this.closing)
|
|
64
|
+
throw new Error("MCP server manager is closed");
|
|
61
65
|
// Dedupe concurrent connection attempts
|
|
62
66
|
if (this.connectPromises.has(name)) {
|
|
63
67
|
return abortable(this.connectPromises.get(name), signal);
|
|
@@ -68,15 +72,22 @@ export class McpServerManager {
|
|
|
68
72
|
existing.lastUsedAt = Date.now();
|
|
69
73
|
return existing;
|
|
70
74
|
}
|
|
71
|
-
const promise = this.createConnection(name, definition, signal)
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
+
const promise = this.createConnection(name, definition, signal).then(async connection => {
|
|
76
|
+
if (this.closing || signal?.aborted) {
|
|
77
|
+
await this.disposeConnection(connection);
|
|
78
|
+
throwIfAborted(signal);
|
|
79
|
+
throw new Error("MCP server manager closed during connection");
|
|
80
|
+
}
|
|
75
81
|
this.connections.set(name, connection);
|
|
76
82
|
return connection;
|
|
83
|
+
});
|
|
84
|
+
this.connectPromises.set(name, promise);
|
|
85
|
+
try {
|
|
86
|
+
return await promise;
|
|
77
87
|
}
|
|
78
88
|
finally {
|
|
79
|
-
this.connectPromises.
|
|
89
|
+
if (this.connectPromises.get(name) === promise)
|
|
90
|
+
this.connectPromises.delete(name);
|
|
80
91
|
}
|
|
81
92
|
}
|
|
82
93
|
async createConnection(name, definition, signal) {
|
|
@@ -110,6 +121,8 @@ export class McpServerManager {
|
|
|
110
121
|
throw new Error(`Server ${name} has no command or url`);
|
|
111
122
|
}
|
|
112
123
|
const requestOptions = this.buildRequestOptions(definition, signal);
|
|
124
|
+
const pending = { client, transport };
|
|
125
|
+
this.pendingConnections.set(name, pending);
|
|
113
126
|
try {
|
|
114
127
|
await client.connect(transport, requestOptions);
|
|
115
128
|
this.attachAdapterNotificationHandlers(name, client);
|
|
@@ -151,6 +164,10 @@ export class McpServerManager {
|
|
|
151
164
|
await transport.close().catch(() => { });
|
|
152
165
|
throw error;
|
|
153
166
|
}
|
|
167
|
+
finally {
|
|
168
|
+
if (this.pendingConnections.get(name) === pending)
|
|
169
|
+
this.pendingConnections.delete(name);
|
|
170
|
+
}
|
|
154
171
|
}
|
|
155
172
|
buildClientCapabilities() {
|
|
156
173
|
return {
|
|
@@ -323,6 +340,10 @@ export class McpServerManager {
|
|
|
323
340
|
this.touch(name);
|
|
324
341
|
}
|
|
325
342
|
}
|
|
343
|
+
async disposeConnection(connection) {
|
|
344
|
+
await connection.client.close().catch(() => { });
|
|
345
|
+
await connection.transport.close().catch(() => { });
|
|
346
|
+
}
|
|
326
347
|
async close(name) {
|
|
327
348
|
const connection = this.connections.get(name);
|
|
328
349
|
if (!connection)
|
|
@@ -333,12 +354,16 @@ export class McpServerManager {
|
|
|
333
354
|
connection.status = "closed";
|
|
334
355
|
this.connections.delete(name);
|
|
335
356
|
this.acceptedUrlElicitations.delete(name);
|
|
336
|
-
await
|
|
337
|
-
await connection.transport.close().catch(() => { });
|
|
357
|
+
await this.disposeConnection(connection);
|
|
338
358
|
}
|
|
339
359
|
async closeAll() {
|
|
360
|
+
this.closing = true;
|
|
340
361
|
const names = [...this.connections.keys()];
|
|
341
|
-
|
|
362
|
+
const pending = [...this.pendingConnections.values()];
|
|
363
|
+
await Promise.all([
|
|
364
|
+
...names.map(name => this.close(name)),
|
|
365
|
+
...pending.map(connection => this.disposeConnection(connection)),
|
|
366
|
+
]);
|
|
342
367
|
}
|
|
343
368
|
getConnection(name) {
|
|
344
369
|
return this.connections.get(name);
|