@humain/terminal 0.0.3-beta.3 → 0.0.4-beta.2
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 +30 -0
- package/README.md +1 -0
- package/dist/bun/cli.d.ts.map +1 -1
- package/dist/bun/cli.js.map +1 -1
- package/dist/bun/restore-sandbox-env.d.ts.map +1 -1
- package/dist/bun/restore-sandbox-env.js.map +1 -1
- package/dist/cli/args.d.ts +1 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +11 -0
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/auth-check.d.ts.map +1 -1
- package/dist/cli/auth-check.js.map +1 -1
- package/dist/cli/auth-command.d.ts.map +1 -1
- package/dist/cli/auth-command.js.map +1 -1
- package/dist/cli/config-selector.d.ts.map +1 -1
- package/dist/cli/config-selector.js.map +1 -1
- package/dist/cli/credential-print.d.ts.map +1 -1
- package/dist/cli/credential-print.js.map +1 -1
- package/dist/cli/experimental/auth.d.ts.map +1 -1
- package/dist/cli/experimental/auth.js.map +1 -1
- package/dist/cli/experimental/cli.d.ts.map +1 -1
- package/dist/cli/experimental/command-options.d.ts.map +1 -1
- package/dist/cli/experimental/command-options.js.map +1 -1
- package/dist/cli/experimental/command.d.ts.map +1 -1
- package/dist/cli/experimental/command.js +2 -5
- package/dist/cli/experimental/command.js.map +1 -1
- package/dist/cli/experimental/commands/client.d.ts.map +1 -1
- package/dist/cli/experimental/commands/client.js.map +1 -1
- package/dist/cli/experimental/commands/pi.d.ts.map +1 -1
- package/dist/cli/experimental/commands/pi.js.map +1 -1
- package/dist/cli/experimental/commands/server.d.ts.map +1 -1
- package/dist/cli/experimental/commands/server.js.map +1 -1
- package/dist/cli/experimental/transport-address.d.ts.map +1 -1
- package/dist/cli/experimental/transport-address.js.map +1 -1
- package/dist/cli/file-processor.d.ts.map +1 -1
- package/dist/cli/file-processor.js.map +1 -1
- package/dist/cli/initial-message.d.ts +1 -1
- package/dist/cli/initial-message.d.ts.map +1 -1
- package/dist/cli/initial-message.js.map +1 -1
- package/dist/cli/list-models.d.ts.map +1 -1
- package/dist/cli/list-models.js.map +1 -1
- package/dist/cli/project-trust.d.ts.map +1 -1
- package/dist/cli/project-trust.js.map +1 -1
- package/dist/cli/session-picker.d.ts.map +1 -1
- package/dist/cli/session-picker.js.map +1 -1
- package/dist/cli/startup-ui.d.ts.map +1 -1
- package/dist/cli/startup-ui.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js.map +1 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/remote-session.d.ts.map +1 -1
- package/dist/client/remote-session.js.map +1 -1
- package/dist/client/transcript.d.ts.map +1 -1
- package/dist/client/transcript.js +1 -1
- package/dist/client/transcript.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session-runtime.d.ts.map +1 -1
- package/dist/core/agent-session-runtime.js +0 -8
- package/dist/core/agent-session-runtime.js.map +1 -1
- package/dist/core/agent-session-services.d.ts.map +1 -1
- package/dist/core/agent-session-services.js.map +1 -1
- package/dist/core/agent-session.d.ts +36 -2
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +107 -129
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-guidance.d.ts.map +1 -1
- package/dist/core/auth-guidance.js.map +1 -1
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +3 -8
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/bash-executor.d.ts.map +1 -1
- package/dist/core/bash-executor.js.map +1 -1
- package/dist/core/cache-stats.d.ts.map +1 -1
- package/dist/core/cache-stats.js.map +1 -1
- package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
- package/dist/core/compaction/branch-summarization.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/compaction/index.d.ts.map +1 -1
- package/dist/core/compaction/utils.d.ts.map +1 -1
- package/dist/core/compaction/utils.js.map +1 -1
- package/dist/core/defaults.d.ts.map +1 -1
- package/dist/core/diagnostics.d.ts.map +1 -1
- package/dist/core/event-bus.d.ts.map +1 -1
- package/dist/core/event-bus.js.map +1 -1
- package/dist/core/exec.d.ts.map +1 -1
- package/dist/core/exec.js.map +1 -1
- package/dist/core/experimental.d.ts +4 -0
- package/dist/core/experimental.d.ts.map +1 -1
- package/dist/core/experimental.js +4 -0
- package/dist/core/experimental.js.map +1 -1
- package/dist/core/export-html/ansi-to-html.d.ts.map +1 -1
- package/dist/core/export-html/ansi-to-html.js.map +1 -1
- package/dist/core/export-html/index.d.ts.map +1 -1
- package/dist/core/export-html/index.js.map +1 -1
- package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
- package/dist/core/export-html/tool-renderer.js.map +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +22 -30
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +4 -0
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/extensions/wrapper.d.ts.map +1 -1
- package/dist/core/extensions/wrapper.js.map +1 -1
- package/dist/core/footer-data-provider.d.ts.map +1 -1
- package/dist/core/footer-data-provider.js +17 -18
- package/dist/core/footer-data-provider.js.map +1 -1
- package/dist/core/http-dispatcher.d.ts.map +1 -1
- package/dist/core/http-dispatcher.js.map +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/keybindings.d.ts +24 -0
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +0 -1
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/messages.d.ts.map +1 -1
- package/dist/core/messages.js.map +1 -1
- package/dist/core/model-config.d.ts +5 -0
- package/dist/core/model-config.d.ts.map +1 -1
- package/dist/core/model-config.js +1 -2
- package/dist/core/model-config.js.map +1 -1
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +0 -1
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/model-runtime.d.ts.map +1 -1
- package/dist/core/model-runtime.js +15 -25
- package/dist/core/model-runtime.js.map +1 -1
- package/dist/core/models-store.d.ts.map +1 -1
- package/dist/core/models-store.js +3 -4
- package/dist/core/models-store.js.map +1 -1
- package/dist/core/output-guard.d.ts.map +1 -1
- package/dist/core/output-guard.js.map +1 -1
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +0 -7
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/pi-manifest.d.ts.map +1 -1
- package/dist/core/pi-manifest.js.map +1 -1
- package/dist/core/project-trust.d.ts.map +1 -1
- package/dist/core/project-trust.js.map +1 -1
- package/dist/core/prompt-templates.d.ts.map +1 -1
- package/dist/core/prompt-templates.js.map +1 -1
- package/dist/core/provider-attribution.d.ts.map +1 -1
- package/dist/core/provider-attribution.js.map +1 -1
- package/dist/core/provider-composer.d.ts.map +1 -1
- package/dist/core/provider-composer.js.map +1 -1
- package/dist/core/radius.d.ts.map +1 -1
- package/dist/core/remote-catalog-provider.d.ts.map +1 -1
- package/dist/core/remote-catalog-provider.js.map +1 -1
- package/dist/core/resolve-config-value.d.ts.map +1 -1
- package/dist/core/resolve-config-value.js.map +1 -1
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +0 -44
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/runtime-credentials.d.ts.map +1 -1
- package/dist/core/runtime-credentials.js +1 -2
- package/dist/core/runtime-credentials.js.map +1 -1
- package/dist/core/sdk.d.ts +5 -3
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +3 -2
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-cwd.d.ts.map +1 -1
- package/dist/core/session-cwd.js +0 -1
- package/dist/core/session-cwd.js.map +1 -1
- package/dist/core/session-manager.d.ts +4 -0
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +55 -35
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +6 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +19 -17
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/source-info.d.ts.map +1 -1
- package/dist/core/source-info.js.map +1 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +1 -1
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/telemetry.d.ts.map +1 -1
- package/dist/core/telemetry.js.map +1 -1
- package/dist/core/timings.d.ts.map +1 -1
- package/dist/core/timings.js.map +1 -1
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +10 -5
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/edit-diff.d.ts.map +1 -1
- package/dist/core/tools/edit-diff.js.map +1 -1
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +2 -0
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/file-mutation-queue.d.ts.map +1 -1
- package/dist/core/tools/file-mutation-queue.js.map +1 -1
- package/dist/core/tools/find.d.ts +1 -1
- package/dist/core/tools/find.d.ts.map +1 -1
- package/dist/core/tools/find.js +1 -1
- package/dist/core/tools/find.js.map +1 -1
- package/dist/core/tools/grep.d.ts.map +1 -1
- package/dist/core/tools/grep.js +1 -1
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/core/tools/index.d.ts +2 -1
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js +9 -1
- package/dist/core/tools/index.js.map +1 -1
- package/dist/core/tools/ls.d.ts.map +1 -1
- package/dist/core/tools/ls.js.map +1 -1
- package/dist/core/tools/output-accumulator.d.ts.map +1 -1
- package/dist/core/tools/output-accumulator.js +12 -18
- package/dist/core/tools/output-accumulator.js.map +1 -1
- package/dist/core/tools/path-utils.d.ts.map +1 -1
- package/dist/core/tools/path-utils.js.map +1 -1
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +2 -0
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/render-utils.d.ts.map +1 -1
- package/dist/core/tools/render-utils.js.map +1 -1
- package/dist/core/tools/subagent.d.ts +82 -0
- package/dist/core/tools/subagent.d.ts.map +1 -0
- package/dist/core/tools/subagent.js +980 -0
- package/dist/core/tools/subagent.js.map +1 -0
- package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
- package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
- package/dist/core/tools/truncate.d.ts.map +1 -1
- package/dist/core/tools/truncate.js.map +1 -1
- package/dist/core/tools/write.d.ts.map +1 -1
- package/dist/core/tools/write.js +2 -1
- package/dist/core/tools/write.js.map +1 -1
- package/dist/core/trust-manager.d.ts.map +1 -1
- package/dist/core/trust-manager.js +0 -1
- package/dist/core/trust-manager.js.map +1 -1
- package/dist/core/usage-totals.d.ts.map +1 -1
- package/dist/core/usage-totals.js.map +1 -1
- package/dist/extensions/index.d.ts.map +1 -1
- package/dist/extensions/llama/client.d.ts.map +1 -1
- package/dist/extensions/llama/client.js +0 -2
- package/dist/extensions/llama/client.js.map +1 -1
- package/dist/extensions/llama/huggingface.d.ts.map +1 -1
- package/dist/extensions/llama/huggingface.js +0 -2
- package/dist/extensions/llama/huggingface.js.map +1 -1
- package/dist/extensions/llama/index.d.ts.map +1 -1
- package/dist/extensions/llama/index.js.map +1 -1
- package/dist/extensions/llama/provider.d.ts.map +1 -1
- package/dist/extensions/llama/provider.js.map +1 -1
- package/dist/extensions/llama/ui.d.ts.map +1 -1
- package/dist/extensions/llama/ui.js +12 -28
- package/dist/extensions/llama/ui.js.map +1 -1
- package/dist/humain/agent-execution-protocol.d.ts.map +1 -1
- package/dist/humain/agent-execution-protocol.js.map +1 -1
- package/dist/humain/agent-execution-runtime.d.ts.map +1 -1
- package/dist/humain/agent-execution-runtime.js.map +1 -1
- package/dist/humain/bedrock-provider/vendor/index.bundle.mjs +127 -7
- package/dist/humain/brand-logo.d.ts.map +1 -1
- package/dist/humain/index.d.ts.map +1 -1
- package/dist/humain/index.js.map +1 -1
- package/dist/humain/legacy-workflow-tiers.d.ts.map +1 -1
- package/dist/humain/legacy-workflow-tiers.js.map +1 -1
- package/dist/humain/mcp-adapter/vendor/CHANGELOG.md +36 -0
- package/dist/humain/mcp-adapter/vendor/README.md +47 -5
- package/dist/humain/mcp-adapter/vendor/cli.js +163 -1
- package/dist/humain/mcp-adapter/vendor/commands.ts +128 -22
- package/dist/humain/mcp-adapter/vendor/config.ts +25 -7
- package/dist/humain/mcp-adapter/vendor/direct-tools.ts +5 -4
- package/dist/humain/mcp-adapter/vendor/index.bundle.mjs +1663 -458
- package/dist/humain/mcp-adapter/vendor/index.ts +219 -32
- package/dist/humain/mcp-adapter/vendor/init.ts +36 -4
- package/dist/humain/mcp-adapter/vendor/lifecycle.ts +315 -24
- package/dist/humain/mcp-adapter/vendor/mcp-auth-flow.ts +39 -6
- package/dist/humain/mcp-adapter/vendor/mcp-bearer-store.ts +387 -0
- package/dist/humain/mcp-adapter/vendor/mcp-callback-server.ts +27 -3
- package/dist/humain/mcp-adapter/vendor/mcp-code.ts +4 -0
- package/dist/humain/mcp-adapter/vendor/mcp-panel.ts +42 -13
- package/dist/humain/mcp-adapter/vendor/metadata-cache.ts +32 -21
- package/dist/humain/mcp-adapter/vendor/package-mcp-loader.ts +168 -0
- package/dist/humain/mcp-adapter/vendor/package.json +179 -177
- package/dist/humain/mcp-adapter/vendor/proxy-modes.ts +5 -4
- package/dist/humain/mcp-adapter/vendor/request-headers-command.ts +31 -37
- package/dist/humain/mcp-adapter/vendor/search-ranking.ts +92 -22
- package/dist/humain/mcp-adapter/vendor/server-manager.ts +140 -2
- package/dist/humain/mcp-adapter/vendor/session-recovery.ts +7 -0
- package/dist/humain/mcp-adapter/vendor/tool-approval.ts +15 -2
- package/dist/humain/mcp-adapter/vendor/tool-result-renderer.ts +44 -4
- package/dist/humain/mcp-adapter/vendor/types.ts +2 -0
- package/dist/humain/mcp-adapter/vendor/ui-server.ts +18 -16
- package/dist/humain/mcp-adapter/vendor/utils.ts +70 -0
- package/dist/humain/mcp-adapter.d.ts.map +1 -1
- package/dist/humain/mcp-adapter.js.map +1 -1
- package/dist/humain/pi-agent-execution-host.d.ts.map +1 -1
- package/dist/humain/pi-agent-execution-host.js.map +1 -1
- package/dist/humain/web-access/host.d.ts.map +1 -1
- package/dist/humain/web-access/index.d.ts.map +1 -1
- package/dist/humain/web-access/index.js.map +1 -1
- package/dist/humain/web-access/vendor/activity.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/activity.js +7 -5
- package/dist/humain/web-access/vendor/activity.js.map +1 -1
- package/dist/humain/web-access/vendor/anysearch.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/anysearch.js +3 -2
- package/dist/humain/web-access/vendor/anysearch.js.map +1 -1
- package/dist/humain/web-access/vendor/auth-fetch.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/auth-fetch.js.map +1 -1
- package/dist/humain/web-access/vendor/bocha.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/bocha.js.map +1 -1
- package/dist/humain/web-access/vendor/brave.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/brave.js +14 -4
- package/dist/humain/web-access/vendor/brave.js.map +1 -1
- package/dist/humain/web-access/vendor/brightdata-unlocker.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/brightdata-unlocker.js.map +1 -1
- package/dist/humain/web-access/vendor/brightdata.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/brightdata.js.map +1 -1
- package/dist/humain/web-access/vendor/chrome-cookies.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/chrome-cookies.js +92 -14
- package/dist/humain/web-access/vendor/chrome-cookies.js.map +1 -1
- package/dist/humain/web-access/vendor/content-find.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/content-find.js.map +1 -1
- package/dist/humain/web-access/vendor/credential-source.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/credential-source.js +0 -2
- package/dist/humain/web-access/vendor/credential-source.js.map +1 -1
- package/dist/humain/web-access/vendor/curator-page.d.ts +3 -0
- package/dist/humain/web-access/vendor/curator-page.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/curator-page.js +4 -1
- package/dist/humain/web-access/vendor/curator-page.js.map +1 -1
- package/dist/humain/web-access/vendor/curator-server.d.ts +3 -0
- package/dist/humain/web-access/vendor/curator-server.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/curator-server.js +6 -0
- package/dist/humain/web-access/vendor/curator-server.js.map +1 -1
- package/dist/humain/web-access/vendor/data-uri-sanitize.d.ts +21 -0
- package/dist/humain/web-access/vendor/data-uri-sanitize.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/data-uri-sanitize.js +373 -0
- package/dist/humain/web-access/vendor/data-uri-sanitize.js.map +1 -0
- package/dist/humain/web-access/vendor/datalab-pdf-extract.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/datalab-pdf-extract.js.map +1 -1
- package/dist/humain/web-access/vendor/declared-web-links.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/declared-web-links.js.map +1 -1
- package/dist/humain/web-access/vendor/duckduckgo.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/duckduckgo.js.map +1 -1
- package/dist/humain/web-access/vendor/exa.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/exa.js +16 -7
- package/dist/humain/web-access/vendor/exa.js.map +1 -1
- package/dist/humain/web-access/vendor/extract.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/extract.js +45 -5
- package/dist/humain/web-access/vendor/extract.js.map +1 -1
- package/dist/humain/web-access/vendor/feature-config.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/feature-config.js.map +1 -1
- package/dist/humain/web-access/vendor/fetch-params.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/fetch-params.js.map +1 -1
- package/dist/humain/web-access/vendor/firecrawl.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/firecrawl.js +15 -2
- package/dist/humain/web-access/vendor/firecrawl.js.map +1 -1
- package/dist/humain/web-access/vendor/gemini-api.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/gemini-api.js.map +1 -1
- package/dist/humain/web-access/vendor/gemini-pdf-extract.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/gemini-pdf-extract.js.map +1 -1
- package/dist/humain/web-access/vendor/gemini-search.d.ts +2 -2
- package/dist/humain/web-access/vendor/gemini-search.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/gemini-search.js +25 -8
- package/dist/humain/web-access/vendor/gemini-search.js.map +1 -1
- package/dist/humain/web-access/vendor/gemini-url-context.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/gemini-url-context.js.map +1 -1
- package/dist/humain/web-access/vendor/gemini-web-config.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/gemini-web-config.js.map +1 -1
- package/dist/humain/web-access/vendor/gemini-web.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/gemini-web.js.map +1 -1
- package/dist/humain/web-access/vendor/github-api.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/github-api.js.map +1 -1
- package/dist/humain/web-access/vendor/github-extract.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/github-extract.js +69 -35
- package/dist/humain/web-access/vendor/github-extract.js.map +1 -1
- package/dist/humain/web-access/vendor/index.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/index.js +58 -54
- package/dist/humain/web-access/vendor/index.js.map +1 -1
- package/dist/humain/web-access/vendor/jina-search.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/jina-search.js.map +1 -1
- package/dist/humain/web-access/vendor/kagi.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/kagi.js.map +1 -1
- package/dist/humain/web-access/vendor/ollama.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/ollama.js.map +1 -1
- package/dist/humain/web-access/vendor/openai-search.d.ts +1 -1
- package/dist/humain/web-access/vendor/openai-search.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/openai-search.js +15 -5
- package/dist/humain/web-access/vendor/openai-search.js.map +1 -1
- package/dist/humain/web-access/vendor/page-query.d.ts +1 -2
- package/dist/humain/web-access/vendor/page-query.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/page-query.js +5 -2
- package/dist/humain/web-access/vendor/page-query.js.map +1 -1
- package/dist/humain/web-access/vendor/parallel-mcp.d.ts +10 -0
- package/dist/humain/web-access/vendor/parallel-mcp.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/parallel-mcp.js +224 -0
- package/dist/humain/web-access/vendor/parallel-mcp.js.map +1 -0
- package/dist/humain/web-access/vendor/parallel.d.ts +1 -0
- package/dist/humain/web-access/vendor/parallel.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/parallel.js +2 -2
- package/dist/humain/web-access/vendor/parallel.js.map +1 -1
- package/dist/humain/web-access/vendor/pdf-extract.d.ts +1 -0
- package/dist/humain/web-access/vendor/pdf-extract.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/pdf-extract.js +15 -5
- package/dist/humain/web-access/vendor/pdf-extract.js.map +1 -1
- package/dist/humain/web-access/vendor/perplexity.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/perplexity.js.map +1 -1
- package/dist/humain/web-access/vendor/querit.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/querit.js.map +1 -1
- package/dist/humain/web-access/vendor/query-rewrite.d.ts +3 -0
- package/dist/humain/web-access/vendor/query-rewrite.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/query-rewrite.js +42 -0
- package/dist/humain/web-access/vendor/query-rewrite.js.map +1 -0
- package/dist/humain/web-access/vendor/render-search-error.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/render-search-error.js.map +1 -1
- package/dist/humain/web-access/vendor/rsc-extract.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/rsc-extract.js.map +1 -1
- package/dist/humain/web-access/vendor/search1api.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/search1api.js.map +1 -1
- package/dist/humain/web-access/vendor/searchinfinity.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/searchinfinity.js.map +1 -1
- package/dist/humain/web-access/vendor/searxng.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/searxng.js.map +1 -1
- package/dist/humain/web-access/vendor/serpbase.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/serpbase.js.map +1 -1
- package/dist/humain/web-access/vendor/serpdive.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/serpdive.js.map +1 -1
- package/dist/humain/web-access/vendor/serper.d.ts +4 -0
- package/dist/humain/web-access/vendor/serper.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/serper.js +206 -0
- package/dist/humain/web-access/vendor/serper.js.map +1 -0
- package/dist/humain/web-access/vendor/source-check.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/source-check.js.map +1 -1
- package/dist/humain/web-access/vendor/ssrf-protection.d.ts +2 -0
- package/dist/humain/web-access/vendor/ssrf-protection.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/ssrf-protection.js +11 -2
- package/dist/humain/web-access/vendor/ssrf-protection.js.map +1 -1
- package/dist/humain/web-access/vendor/storage.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/storage.js.map +1 -1
- package/dist/humain/web-access/vendor/summary-model-scope.d.ts +5 -0
- package/dist/humain/web-access/vendor/summary-model-scope.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/summary-model-scope.js +10 -5
- package/dist/humain/web-access/vendor/summary-model-scope.js.map +1 -1
- package/dist/humain/web-access/vendor/summary-review.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/summary-review.js +40 -14
- package/dist/humain/web-access/vendor/summary-review.js.map +1 -1
- package/dist/humain/web-access/vendor/tavily.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/tavily.js +14 -4
- package/dist/humain/web-access/vendor/tavily.js.map +1 -1
- package/dist/humain/web-access/vendor/tinyfish.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/tinyfish.js.map +1 -1
- package/dist/humain/web-access/vendor/utils.d.ts +10 -0
- package/dist/humain/web-access/vendor/utils.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/utils.js +70 -0
- package/dist/humain/web-access/vendor/utils.js.map +1 -1
- package/dist/humain/web-access/vendor/valyu.d.ts +6 -0
- package/dist/humain/web-access/vendor/valyu.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/valyu.js +194 -0
- package/dist/humain/web-access/vendor/valyu.js.map +1 -0
- package/dist/humain/web-access/vendor/video-extract.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/video-extract.js.map +1 -1
- package/dist/humain/web-access/vendor/xai-search.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/xai-search.js.map +1 -1
- package/dist/humain/web-access/vendor/youtube-extract.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/youtube-extract.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +4 -0
- package/dist/main.js.map +1 -1
- package/dist/migrations.d.ts.map +1 -1
- package/dist/migrations.js.map +1 -1
- package/dist/modes/agent-exec-mode.d.ts.map +1 -1
- package/dist/modes/agent-exec-mode.js.map +1 -1
- package/dist/modes/index.d.ts.map +1 -1
- package/dist/modes/interactive/components/armin.d.ts.map +1 -1
- package/dist/modes/interactive/components/armin.js +6 -10
- package/dist/modes/interactive/components/armin.js.map +1 -1
- package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/assistant-message.js +2 -9
- package/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/bash-execution.js +4 -9
- package/dist/modes/interactive/components/bash-execution.js.map +1 -1
- package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -1
- package/dist/modes/interactive/components/bordered-loader.js +0 -3
- package/dist/modes/interactive/components/bordered-loader.js.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.js +1 -3
- package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.js +1 -3
- package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/config-selector.js +5 -22
- package/dist/modes/interactive/components/config-selector.js.map +1 -1
- package/dist/modes/interactive/components/countdown-timer.d.ts.map +1 -1
- package/dist/modes/interactive/components/countdown-timer.js +0 -5
- package/dist/modes/interactive/components/countdown-timer.js.map +1 -1
- package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-editor.js +1 -8
- package/dist/modes/interactive/components/custom-editor.js.map +1 -1
- package/dist/modes/interactive/components/custom-entry.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-entry.js +1 -4
- package/dist/modes/interactive/components/custom-entry.js.map +1 -1
- package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-message.js +1 -7
- package/dist/modes/interactive/components/custom-message.js.map +1 -1
- package/dist/modes/interactive/components/daxnuts.d.ts.map +1 -1
- package/dist/modes/interactive/components/daxnuts.js +6 -8
- package/dist/modes/interactive/components/daxnuts.js.map +1 -1
- package/dist/modes/interactive/components/diff.d.ts.map +1 -1
- package/dist/modes/interactive/components/diff.js +2 -2
- package/dist/modes/interactive/components/diff.js.map +1 -1
- package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
- package/dist/modes/interactive/components/dynamic-border.js +0 -1
- package/dist/modes/interactive/components/dynamic-border.js.map +1 -1
- package/dist/modes/interactive/components/earendil-announcement.d.ts.map +1 -1
- package/dist/modes/interactive/components/earendil-announcement.js.map +1 -1
- package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-editor.js +1 -7
- package/dist/modes/interactive/components/extension-editor.js.map +1 -1
- package/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-input.js +2 -8
- package/dist/modes/interactive/components/extension-input.js.map +1 -1
- package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-selector.js +1 -9
- package/dist/modes/interactive/components/extension-selector.js.map +1 -1
- package/dist/modes/interactive/components/first-time-setup.d.ts.map +1 -1
- package/dist/modes/interactive/components/first-time-setup.js +2 -4
- package/dist/modes/interactive/components/first-time-setup.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +1 -3
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/index.d.ts.map +1 -1
- package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
- package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
- package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
- package/dist/modes/interactive/components/login-dialog.js +3 -9
- package/dist/modes/interactive/components/login-dialog.js.map +1 -1
- package/dist/modes/interactive/components/markdown-transform.d.ts.map +1 -1
- package/dist/modes/interactive/components/markdown-transform.js.map +1 -1
- package/dist/modes/interactive/components/mermaid.d.ts.map +1 -1
- package/dist/modes/interactive/components/mermaid.js.map +1 -1
- package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/model-selector.js +14 -26
- package/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.js +3 -11
- package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.js +9 -14
- package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
- package/dist/modes/interactive/components/session-selector-search.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector-search.js.map +1 -1
- package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector.js +33 -57
- package/dist/modes/interactive/components/session-selector.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts +3 -1
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +10 -14
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/show-images-selector.js +0 -1
- package/dist/modes/interactive/components/show-images-selector.js.map +1 -1
- package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/skill-invocation-message.js +1 -3
- package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
- package/dist/modes/interactive/components/status-indicator.d.ts.map +1 -1
- package/dist/modes/interactive/components/status-indicator.js +0 -2
- package/dist/modes/interactive/components/status-indicator.js.map +1 -1
- package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/theme-selector.js +0 -2
- package/dist/modes/interactive/components/theme-selector.js.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.js +0 -1
- package/dist/modes/interactive/components/thinking-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 +19 -25
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/tree-selector.js +18 -34
- package/dist/modes/interactive/components/tree-selector.js.map +1 -1
- package/dist/modes/interactive/components/trust-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/trust-selector.js +0 -6
- package/dist/modes/interactive/components/trust-selector.js.map +1 -1
- package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/user-message-selector.js +3 -6
- package/dist/modes/interactive/components/user-message-selector.js.map +1 -1
- package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/user-message.js +0 -4
- package/dist/modes/interactive/components/user-message.js.map +1 -1
- package/dist/modes/interactive/components/visual-truncate.d.ts.map +1 -1
- package/dist/modes/interactive/components/visual-truncate.js.map +1 -1
- package/dist/modes/interactive/external-editor.d.ts.map +1 -1
- package/dist/modes/interactive/external-editor.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +18 -2
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +147 -137
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/model-catalog-refresh.d.ts +7 -0
- package/dist/modes/interactive/model-catalog-refresh.d.ts.map +1 -0
- package/dist/modes/interactive/model-catalog-refresh.js +36 -0
- package/dist/modes/interactive/model-catalog-refresh.js.map +1 -0
- package/dist/modes/interactive/model-search.d.ts.map +1 -1
- package/dist/modes/interactive/model-search.js.map +1 -1
- package/dist/modes/interactive/theme/dark.json +2 -0
- package/dist/modes/interactive/theme/light.json +2 -0
- package/dist/modes/interactive/theme/theme-controller.d.ts +10 -2
- package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme-controller.js +25 -18
- package/dist/modes/interactive/theme/theme-controller.js.map +1 -1
- package/dist/modes/interactive/theme/theme-schema.json +9 -1
- package/dist/modes/interactive/theme/theme.d.ts +7 -5
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +12 -8
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/modes/json-event.d.ts +4 -1
- package/dist/modes/json-event.d.ts.map +1 -1
- package/dist/modes/json-event.js +5 -2
- package/dist/modes/json-event.js.map +1 -1
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js.map +1 -1
- package/dist/modes/rpc/jsonl.d.ts.map +1 -1
- package/dist/modes/rpc/jsonl.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +9 -10
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/package-manager-cli.d.ts.map +1 -1
- package/dist/package-manager-cli.js.map +1 -1
- package/dist/rpc-entry.d.ts.map +1 -1
- package/dist/rpc-entry.js.map +1 -1
- package/dist/server/create-harness.d.ts.map +1 -1
- package/dist/server/create-harness.js +2 -0
- package/dist/server/create-harness.js.map +1 -1
- package/dist/utils/abort.d.ts.map +1 -1
- package/dist/utils/abort.js.map +1 -1
- package/dist/utils/ansi.d.ts.map +1 -1
- package/dist/utils/ansi.js.map +1 -1
- package/dist/utils/changelog.d.ts.map +1 -1
- package/dist/utils/changelog.js.map +1 -1
- package/dist/utils/child-process.d.ts.map +1 -1
- package/dist/utils/child-process.js.map +1 -1
- package/dist/utils/clipboard-image.d.ts.map +1 -1
- package/dist/utils/clipboard-image.js +1 -1
- package/dist/utils/clipboard-image.js.map +1 -1
- package/dist/utils/clipboard-native.d.ts.map +1 -1
- package/dist/utils/clipboard-native.js.map +1 -1
- package/dist/utils/clipboard.d.ts.map +1 -1
- package/dist/utils/clipboard.js.map +1 -1
- package/dist/utils/deprecation.d.ts.map +1 -1
- package/dist/utils/deprecation.js.map +1 -1
- package/dist/utils/exif-orientation.d.ts.map +1 -1
- package/dist/utils/exif-orientation.js.map +1 -1
- package/dist/utils/frontmatter.d.ts.map +1 -1
- package/dist/utils/frontmatter.js.map +1 -1
- package/dist/utils/fs-watch.d.ts.map +1 -1
- package/dist/utils/fs-watch.js.map +1 -1
- package/dist/utils/git.d.ts.map +1 -1
- package/dist/utils/git.js.map +1 -1
- package/dist/utils/html.d.ts.map +1 -1
- package/dist/utils/html.js.map +1 -1
- package/dist/utils/image-convert.d.ts.map +1 -1
- package/dist/utils/image-convert.js.map +1 -1
- package/dist/utils/image-process.d.ts.map +1 -1
- package/dist/utils/image-process.js.map +1 -1
- package/dist/utils/image-resize-core.d.ts.map +1 -1
- package/dist/utils/image-resize-core.js.map +1 -1
- package/dist/utils/image-resize-worker.d.ts.map +1 -1
- package/dist/utils/image-resize-worker.js.map +1 -1
- package/dist/utils/image-resize.d.ts.map +1 -1
- package/dist/utils/image-resize.js.map +1 -1
- package/dist/utils/json.d.ts.map +1 -1
- package/dist/utils/json.js.map +1 -1
- package/dist/utils/management-http.d.ts.map +1 -1
- package/dist/utils/management-http.js.map +1 -1
- package/dist/utils/mime.d.ts.map +1 -1
- package/dist/utils/mime.js.map +1 -1
- package/dist/utils/open-browser.d.ts.map +1 -1
- package/dist/utils/open-browser.js.map +1 -1
- package/dist/utils/paths.d.ts.map +1 -1
- package/dist/utils/paths.js.map +1 -1
- package/dist/utils/photon.d.ts.map +1 -1
- package/dist/utils/photon.js.map +1 -1
- package/dist/utils/pi-user-agent.d.ts.map +1 -1
- package/dist/utils/pi-user-agent.js.map +1 -1
- package/dist/utils/shell.d.ts.map +1 -1
- package/dist/utils/shell.js.map +1 -1
- package/dist/utils/sleep.d.ts.map +1 -1
- package/dist/utils/sleep.js.map +1 -1
- package/dist/utils/syntax-highlight.d.ts.map +1 -1
- package/dist/utils/syntax-highlight.js +1 -1
- package/dist/utils/syntax-highlight.js.map +1 -1
- package/dist/utils/tool-result-images.d.ts.map +1 -1
- package/dist/utils/tool-result-images.js.map +1 -1
- package/dist/utils/tools-manager.d.ts +10 -1
- package/dist/utils/tools-manager.d.ts.map +1 -1
- package/dist/utils/tools-manager.js +14 -19
- package/dist/utils/tools-manager.js.map +1 -1
- package/dist/utils/version-check.d.ts.map +1 -1
- package/dist/utils/version-check.js.map +1 -1
- package/dist/utils/windows-self-update.d.ts.map +1 -1
- package/dist/utils/windows-self-update.js.map +1 -1
- package/docs/compaction.md +3 -3
- package/docs/custom-provider.md +1 -1
- package/docs/environment-variables.md +1 -0
- package/docs/extensions.md +5 -1
- package/docs/json.md +6 -4
- package/docs/keybindings.md +8 -2
- package/docs/rpc.md +15 -4
- package/docs/sdk.md +9 -0
- package/docs/settings.md +31 -0
- package/docs/terminal-setup.md +23 -2
- package/docs/themes.md +23 -3
- package/docs/tui.md +2 -2
- package/docs/usage.md +3 -2
- package/examples/extensions/README.md +1 -1
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +2 -2
- 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/minimal-mode.ts +6 -6
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +2 -2
- package/examples/extensions/subagent/README.md +24 -147
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/npm-shrinkwrap.json +853 -661
- package/package.json +33 -33
- package/src/humain/mcp-adapter/UPSTREAM.md +1 -1
- package/src/humain/mcp-adapter/upstream.json +3 -3
- package/src/humain/mcp-adapter/vendor/CHANGELOG.md +36 -0
- package/src/humain/web-access/UPSTREAM.md +1 -1
- package/src/humain/web-access/upstream.json +4 -4
- package/examples/extensions/subagent/agents.ts +0 -126
- package/examples/extensions/subagent/index.ts +0 -1015
|
@@ -662,15 +662,155 @@ var init_agent_plugin_loader = __esm({
|
|
|
662
662
|
}
|
|
663
663
|
});
|
|
664
664
|
|
|
665
|
+
// packages/coding-agent/src/humain/mcp-adapter/vendor/package-mcp-loader.ts
|
|
666
|
+
import { existsSync as existsSync2, readFileSync as readFileSync3, realpathSync, statSync as statSync2 } from "node:fs";
|
|
667
|
+
import { isAbsolute as isAbsolute2, join as join2, relative as relative2, resolve as resolve3, sep as sep2 } from "node:path";
|
|
668
|
+
import stripJsonComments from "strip-json-comments";
|
|
669
|
+
function loadPackageMcpConfigs(cwd = process.cwd()) {
|
|
670
|
+
const mcpServers = {};
|
|
671
|
+
const seen = /* @__PURE__ */ new Set();
|
|
672
|
+
for (const packageRoot of getConfiguredPackageRoots(cwd)) {
|
|
673
|
+
const manifest = readPackageManifest(packageRoot);
|
|
674
|
+
if (!manifest || typeof manifest.name !== "string" || !manifest.name) continue;
|
|
675
|
+
const paths = getManifestMcpPaths(manifest.pi?.mcp, manifest.name);
|
|
676
|
+
if (!paths) continue;
|
|
677
|
+
const packagePrefix = formatPackageName(manifest.name);
|
|
678
|
+
const packageServers = /* @__PURE__ */ new Set();
|
|
679
|
+
for (const path2 of paths) {
|
|
680
|
+
const configPath = resolvePackageConfigPath(packageRoot, path2);
|
|
681
|
+
if (!configPath) {
|
|
682
|
+
console.warn(`Pi package ${manifest.name} skips MCP config ${path2}: file must stay inside the package`);
|
|
683
|
+
continue;
|
|
684
|
+
}
|
|
685
|
+
const config = readMcpConfig(configPath, manifest.name);
|
|
686
|
+
if (!config) continue;
|
|
687
|
+
for (const [serverName, server2] of Object.entries(config.mcpServers)) {
|
|
688
|
+
const normalizedName = `${packagePrefix}__${formatServerName(serverName)}`;
|
|
689
|
+
if (packageServers.has(normalizedName) || seen.has(normalizedName)) {
|
|
690
|
+
console.warn(`Pi package ${manifest.name} skips duplicate normalized MCP server ${normalizedName}`);
|
|
691
|
+
continue;
|
|
692
|
+
}
|
|
693
|
+
packageServers.add(normalizedName);
|
|
694
|
+
seen.add(normalizedName);
|
|
695
|
+
mcpServers[normalizedName] = server2;
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
return { mcpServers };
|
|
700
|
+
}
|
|
701
|
+
function getConfiguredPackageRoots(cwd) {
|
|
702
|
+
const roots = [];
|
|
703
|
+
for (const [settingsPath, scope] of [
|
|
704
|
+
[join2(cwd, getConfigDirName(), "settings.json"), "project"],
|
|
705
|
+
[join2(getAgentDir(), "settings.json"), "user"]
|
|
706
|
+
]) {
|
|
707
|
+
const settings = readOptionalJson(settingsPath, `${scope} Pi settings`);
|
|
708
|
+
if (settings === void 0) continue;
|
|
709
|
+
if (typeof settings !== "object" || settings === null || Array.isArray(settings)) {
|
|
710
|
+
throw new Error(`${scope} Pi settings ${settingsPath} must be a JSON object`);
|
|
711
|
+
}
|
|
712
|
+
const packages = settings.packages;
|
|
713
|
+
if (packages === void 0) continue;
|
|
714
|
+
if (!Array.isArray(packages)) throw new Error(`${scope} Pi settings ${settingsPath} packages must be an array`);
|
|
715
|
+
for (const entry of packages) {
|
|
716
|
+
const source = typeof entry === "string" ? entry : entry && typeof entry === "object" && !Array.isArray(entry) && typeof entry.source === "string" ? entry.source : void 0;
|
|
717
|
+
if (!source) throw new Error(`${scope} Pi settings ${settingsPath} package entries must be strings or objects with a string source`);
|
|
718
|
+
const root = resolvePackageRoot(source, scope, cwd);
|
|
719
|
+
if (root && !roots.includes(root)) roots.push(root);
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
return roots;
|
|
723
|
+
}
|
|
724
|
+
function resolvePackageRoot(source, scope, cwd) {
|
|
725
|
+
const baseDir = scope === "user" ? getAgentDir() : join2(cwd, getConfigDirName());
|
|
726
|
+
if (source.startsWith("npm:")) {
|
|
727
|
+
const name = source.slice(4).trim().match(/^(@?[^@]+(?:\/[^@]+)?)/)?.[1];
|
|
728
|
+
return name ? resolveContainedPath2(join2(baseDir, "npm", "node_modules"), name) : null;
|
|
729
|
+
}
|
|
730
|
+
const gitSource = source.startsWith("git:") ? source.slice(4).trim() : /^(?:(?:https?|ssh):\/\/|git@[^:]+:)/.test(source) ? source : null;
|
|
731
|
+
if (gitSource) {
|
|
732
|
+
const value = gitSource.replace(/^ssh:\/\/git@/, "").replace(/^git@([^:]+):/, "$1/").replace(/^[a-z]+:\/\//i, "");
|
|
733
|
+
const path2 = value.replace(/@[^/]+$/, "").replace(/\.git$/, "");
|
|
734
|
+
return path2 && !path2.startsWith("/") ? resolveContainedPath2(join2(baseDir, "git"), path2) : null;
|
|
735
|
+
}
|
|
736
|
+
return isAbsolute2(source) ? resolve3(source) : resolve3(baseDir, source);
|
|
737
|
+
}
|
|
738
|
+
function readPackageManifest(packageRoot) {
|
|
739
|
+
const manifest = readOptionalJson(join2(packageRoot, "package.json"), `Pi package manifest ${packageRoot}`);
|
|
740
|
+
return manifest && typeof manifest === "object" && !Array.isArray(manifest) ? manifest : null;
|
|
741
|
+
}
|
|
742
|
+
function getManifestMcpPaths(value, packageName) {
|
|
743
|
+
const paths = typeof value === "string" ? [value] : Array.isArray(value) && value.every((path2) => typeof path2 === "string") ? value : null;
|
|
744
|
+
if (value !== void 0 && !paths) console.warn(`Pi package ${packageName} ignores invalid pi.mcp manifest entry`);
|
|
745
|
+
return paths;
|
|
746
|
+
}
|
|
747
|
+
function readMcpConfig(path2, packageName) {
|
|
748
|
+
const config = readRequiredJson(path2, `Pi package ${packageName} MCP config`);
|
|
749
|
+
if (!config || typeof config !== "object" || Array.isArray(config)) {
|
|
750
|
+
throw new Error(`Pi package ${packageName} MCP config ${path2} must be a JSON object`);
|
|
751
|
+
}
|
|
752
|
+
const servers = config.mcpServers;
|
|
753
|
+
if (!servers || typeof servers !== "object" || Array.isArray(servers)) {
|
|
754
|
+
throw new Error(`Pi package ${packageName} MCP config ${path2} must contain a JSON object mcpServers field`);
|
|
755
|
+
}
|
|
756
|
+
const mcpServers = {};
|
|
757
|
+
for (const [name, server2] of Object.entries(servers)) {
|
|
758
|
+
if (!server2 || typeof server2 !== "object" || Array.isArray(server2)) {
|
|
759
|
+
throw new Error(`Pi package ${packageName} MCP config ${path2} server ${name} must be a JSON object`);
|
|
760
|
+
}
|
|
761
|
+
mcpServers[name] = server2;
|
|
762
|
+
}
|
|
763
|
+
return { mcpServers };
|
|
764
|
+
}
|
|
765
|
+
function readRequiredJson(path2, description) {
|
|
766
|
+
try {
|
|
767
|
+
return JSON.parse(stripJsonComments(readFileSync3(path2, "utf8"), { trailingCommas: true }));
|
|
768
|
+
} catch (error) {
|
|
769
|
+
throw new Error(`${description} ${path2} contains invalid JSON: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
function readOptionalJson(path2, description) {
|
|
773
|
+
if (!existsSync2(path2)) return void 0;
|
|
774
|
+
return readRequiredJson(path2, description);
|
|
775
|
+
}
|
|
776
|
+
function resolveContainedPath2(root, path2) {
|
|
777
|
+
const resolved = resolve3(root, path2);
|
|
778
|
+
const rel = relative2(root, resolved);
|
|
779
|
+
return rel === "" || !rel.startsWith("..") && !rel.startsWith(sep2) && !isAbsolute2(rel) ? resolved : null;
|
|
780
|
+
}
|
|
781
|
+
function resolvePackageConfigPath(packageRoot, path2) {
|
|
782
|
+
const lexicalPath = resolveContainedPath2(packageRoot, path2);
|
|
783
|
+
if (!lexicalPath || !existsSync2(lexicalPath) || !statSync2(lexicalPath).isFile()) return null;
|
|
784
|
+
try {
|
|
785
|
+
const realPackageRoot = realpathSync(packageRoot);
|
|
786
|
+
const realConfigPath = realpathSync(lexicalPath);
|
|
787
|
+
return resolveContainedPath2(realPackageRoot, realConfigPath);
|
|
788
|
+
} catch {
|
|
789
|
+
return null;
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
function formatPackageName(name) {
|
|
793
|
+
return name.replace(/[^A-Za-z0-9_-]+/g, "_").replace(/^[_-]+|[_-]+$/g, "") || "package";
|
|
794
|
+
}
|
|
795
|
+
function formatServerName(name) {
|
|
796
|
+
return name.replace(/[^A-Za-z0-9_-]+/g, "_").replace(/^[_-]+|[_-]+$/g, "") || "server";
|
|
797
|
+
}
|
|
798
|
+
var init_package_mcp_loader = __esm({
|
|
799
|
+
"packages/coding-agent/src/humain/mcp-adapter/vendor/package-mcp-loader.ts"() {
|
|
800
|
+
"use strict";
|
|
801
|
+
init_agent_dir();
|
|
802
|
+
}
|
|
803
|
+
});
|
|
804
|
+
|
|
665
805
|
// packages/coding-agent/src/humain/mcp-adapter/vendor/utils.ts
|
|
666
806
|
import { spawnSync } from "node:child_process";
|
|
667
807
|
import { homedir as homedir2, platform } from "node:os";
|
|
668
|
-
import { extname, isAbsolute as
|
|
808
|
+
import { extname, isAbsolute as isAbsolute3, join as join3 } from "node:path";
|
|
669
809
|
async function execOpen(pi, target, browser, signal) {
|
|
670
810
|
const os = platform();
|
|
671
811
|
if (os === "darwin") {
|
|
672
812
|
if (browser) {
|
|
673
|
-
return
|
|
813
|
+
return isAbsolute3(browser) && extname(browser).toLowerCase() !== ".app" ? pi.exec(browser, [target], signal ? { signal } : {}) : pi.exec("open", ["-a", browser, target], signal ? { signal } : {});
|
|
674
814
|
}
|
|
675
815
|
return pi.exec("open", [target], signal ? { signal } : {});
|
|
676
816
|
}
|
|
@@ -798,7 +938,7 @@ function resolveConfigPath(value) {
|
|
|
798
938
|
const resolved = interpolateEnvVars(value);
|
|
799
939
|
if (resolved === "~") return homedir2();
|
|
800
940
|
if (resolved.startsWith("~/") || resolved.startsWith("~\\")) {
|
|
801
|
-
return
|
|
941
|
+
return join3(homedir2(), resolved.slice(2));
|
|
802
942
|
}
|
|
803
943
|
return resolved;
|
|
804
944
|
}
|
|
@@ -870,6 +1010,67 @@ function normalizeDirectToolInputSchema(schema) {
|
|
|
870
1010
|
const { $schema, additionalProperties, ...normalized } = inputSchema;
|
|
871
1011
|
return normalized;
|
|
872
1012
|
}
|
|
1013
|
+
function normalizeToolArguments(value, context = "tool arguments") {
|
|
1014
|
+
if (value === void 0 || value === null || value === "") return {};
|
|
1015
|
+
if (typeof value === "string") {
|
|
1016
|
+
const trimmed = value.trim();
|
|
1017
|
+
if (trimmed === "") return {};
|
|
1018
|
+
let parsed;
|
|
1019
|
+
try {
|
|
1020
|
+
parsed = JSON.parse(trimmed);
|
|
1021
|
+
} catch (error) {
|
|
1022
|
+
throw new Error(
|
|
1023
|
+
`${context}: invalid args JSON (${error instanceof SyntaxError ? error.message : String(error)}); pass args as a JSON object, or as a valid JSON string encoding one`,
|
|
1024
|
+
{ cause: error }
|
|
1025
|
+
);
|
|
1026
|
+
}
|
|
1027
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
1028
|
+
throw new Error(
|
|
1029
|
+
`${context}: expected a JSON object, got ${Array.isArray(parsed) ? "array" : typeof parsed}`
|
|
1030
|
+
);
|
|
1031
|
+
}
|
|
1032
|
+
return parsed;
|
|
1033
|
+
}
|
|
1034
|
+
if (typeof value !== "object" || Array.isArray(value)) {
|
|
1035
|
+
throw new Error(
|
|
1036
|
+
`${context}: expected a JSON object, got ${Array.isArray(value) ? "array" : typeof value}`
|
|
1037
|
+
);
|
|
1038
|
+
}
|
|
1039
|
+
assertJsonSerializable(value, context);
|
|
1040
|
+
try {
|
|
1041
|
+
return JSON.parse(JSON.stringify(value));
|
|
1042
|
+
} catch (error) {
|
|
1043
|
+
throw new Error(
|
|
1044
|
+
`${context}: value is not JSON-serializable: ${error instanceof Error ? error.message : String(error)}`,
|
|
1045
|
+
{ cause: error }
|
|
1046
|
+
);
|
|
1047
|
+
}
|
|
1048
|
+
}
|
|
1049
|
+
function assertJsonSerializable(value, context, path2 = "") {
|
|
1050
|
+
if (value === null) return;
|
|
1051
|
+
if (typeof value === "string" || typeof value === "boolean") return;
|
|
1052
|
+
if (typeof value === "number") {
|
|
1053
|
+
if (!Number.isFinite(value)) throw new Error(`${context}: value at ${path2 || "root"} is not a finite number`);
|
|
1054
|
+
return;
|
|
1055
|
+
}
|
|
1056
|
+
if (Array.isArray(value)) {
|
|
1057
|
+
for (const [index, item] of value.entries()) assertJsonSerializable(item, context, `${path2}[${index}]`);
|
|
1058
|
+
return;
|
|
1059
|
+
}
|
|
1060
|
+
if (typeof value === "object") {
|
|
1061
|
+
if (Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null) {
|
|
1062
|
+
throw new Error(`${context}: value at ${path2 || "root"} is not a plain JSON object`);
|
|
1063
|
+
}
|
|
1064
|
+
if (Object.getOwnPropertySymbols(value).length > 0) {
|
|
1065
|
+
throw new Error(`${context}: value at ${path2 || "root"} has symbol keys`);
|
|
1066
|
+
}
|
|
1067
|
+
for (const [key, item] of Object.entries(value)) {
|
|
1068
|
+
assertJsonSerializable(item, context, path2 ? `${path2}.${key}` : key);
|
|
1069
|
+
}
|
|
1070
|
+
return;
|
|
1071
|
+
}
|
|
1072
|
+
throw new Error(`${context}: value at ${path2 || "root"} is not JSON-serializable`);
|
|
1073
|
+
}
|
|
873
1074
|
function formatAuthRequiredMessage(config, serverName, defaultMessage) {
|
|
874
1075
|
const template = config.settings?.authRequiredMessage;
|
|
875
1076
|
return template ? template.replaceAll("${server}", serverName) : defaultMessage;
|
|
@@ -897,19 +1098,19 @@ var init_utils = __esm({
|
|
|
897
1098
|
});
|
|
898
1099
|
|
|
899
1100
|
// packages/coding-agent/src/humain/mcp-adapter/vendor/config.ts
|
|
900
|
-
import { existsSync as
|
|
1101
|
+
import { existsSync as existsSync3, readFileSync as readFileSync4, writeFileSync, mkdirSync, renameSync } from "node:fs";
|
|
901
1102
|
import { homedir as homedir3 } from "node:os";
|
|
902
|
-
import { dirname, join as
|
|
1103
|
+
import { dirname, join as join4, resolve as resolve4 } from "node:path";
|
|
903
1104
|
import { parse as parseToml } from "smol-toml";
|
|
904
|
-
import
|
|
1105
|
+
import stripJsonComments2 from "strip-json-comments";
|
|
905
1106
|
function getPiGlobalConfigPath(overridePath) {
|
|
906
|
-
return overridePath ?
|
|
1107
|
+
return overridePath ? resolve4(overridePath) : getAgentPath("mcp.json");
|
|
907
1108
|
}
|
|
908
1109
|
function getProjectConfigPath(cwd = process.cwd()) {
|
|
909
|
-
return
|
|
1110
|
+
return resolve4(cwd, PROJECT_CONFIG_NAME);
|
|
910
1111
|
}
|
|
911
1112
|
function getProjectPiConfigPath(cwd = process.cwd()) {
|
|
912
|
-
return
|
|
1113
|
+
return resolve4(cwd, getConfigDirName(), PROJECT_PI_CONFIG_NAME);
|
|
913
1114
|
}
|
|
914
1115
|
function getConfigSourceSummaries(sourceSpecs) {
|
|
915
1116
|
return sourceSpecs.map((source) => {
|
|
@@ -918,7 +1119,7 @@ function getConfigSourceSummaries(sourceSpecs) {
|
|
|
918
1119
|
id: source.id,
|
|
919
1120
|
label: source.label,
|
|
920
1121
|
path: source.readPath,
|
|
921
|
-
exists:
|
|
1122
|
+
exists: existsSync3(source.readPath),
|
|
922
1123
|
scope: source.scope,
|
|
923
1124
|
kind: source.shared ? "shared" : "pi",
|
|
924
1125
|
serverCount: loaded ? Object.keys(loaded.mcpServers).length : 0
|
|
@@ -993,8 +1194,12 @@ function loadMcpConfig(overridePath, cwd = process.cwd()) {
|
|
|
993
1194
|
if (!loaded) continue;
|
|
994
1195
|
config = mergeConfigs(config, expandImports(loaded, cwd));
|
|
995
1196
|
}
|
|
1197
|
+
const packageConfig = loadPackageMcpConfigs(cwd);
|
|
996
1198
|
const pluginConfig = loadAgentPluginConfigs(config.settings?.agentPluginPaths, cwd);
|
|
997
|
-
|
|
1199
|
+
const packageServers = Object.fromEntries(
|
|
1200
|
+
Object.entries(packageConfig.mcpServers).filter(([name]) => !Object.hasOwn(pluginConfig.mcpServers, name))
|
|
1201
|
+
);
|
|
1202
|
+
return mergeConfigs({ mcpServers: packageServers }, mergeConfigs(pluginConfig, config));
|
|
998
1203
|
}
|
|
999
1204
|
function getMergedSettings(overridePath, cwd = process.cwd()) {
|
|
1000
1205
|
let settings;
|
|
@@ -1134,25 +1339,54 @@ function mergeServerMaps(base, next) {
|
|
|
1134
1339
|
for (const [name, definition] of Object.entries(next)) {
|
|
1135
1340
|
const existing = merged[name];
|
|
1136
1341
|
let baseEntry = existing ?? {};
|
|
1137
|
-
if (existing && typeof definition.
|
|
1342
|
+
if (existing && typeof definition.command === "string") {
|
|
1343
|
+
baseEntry = { ...existing };
|
|
1344
|
+
for (const field of [
|
|
1345
|
+
"url",
|
|
1346
|
+
"headers",
|
|
1347
|
+
"requestHeadersCommand",
|
|
1348
|
+
"auth",
|
|
1349
|
+
"bearerToken",
|
|
1350
|
+
"bearerTokenEnv",
|
|
1351
|
+
"oauth",
|
|
1352
|
+
"httpTransport",
|
|
1353
|
+
"socket"
|
|
1354
|
+
]) {
|
|
1355
|
+
delete baseEntry[field];
|
|
1356
|
+
}
|
|
1357
|
+
} else if (existing && typeof definition.url === "string") {
|
|
1138
1358
|
baseEntry = { ...existing };
|
|
1139
1359
|
for (const field of [
|
|
1140
1360
|
"command",
|
|
1141
1361
|
"args",
|
|
1142
1362
|
"env",
|
|
1143
1363
|
"cwd",
|
|
1364
|
+
"pluginDataDir",
|
|
1365
|
+
"literalEnv",
|
|
1366
|
+
"socket"
|
|
1367
|
+
]) {
|
|
1368
|
+
delete baseEntry[field];
|
|
1369
|
+
}
|
|
1370
|
+
} else if (existing && typeof definition.socket === "string") {
|
|
1371
|
+
baseEntry = { ...existing };
|
|
1372
|
+
for (const field of [
|
|
1373
|
+
"command",
|
|
1374
|
+
"args",
|
|
1375
|
+
"env",
|
|
1376
|
+
"cwd",
|
|
1377
|
+
"pluginDataDir",
|
|
1378
|
+
"literalEnv",
|
|
1144
1379
|
"url",
|
|
1145
1380
|
"headers",
|
|
1381
|
+
"requestHeadersCommand",
|
|
1146
1382
|
"auth",
|
|
1147
1383
|
"bearerToken",
|
|
1148
1384
|
"bearerTokenEnv",
|
|
1149
|
-
"oauth"
|
|
1385
|
+
"oauth",
|
|
1386
|
+
"httpTransport"
|
|
1150
1387
|
]) {
|
|
1151
1388
|
delete baseEntry[field];
|
|
1152
1389
|
}
|
|
1153
|
-
} else if (existing?.socket && (typeof definition.command === "string" || typeof definition.url === "string")) {
|
|
1154
|
-
baseEntry = { ...existing };
|
|
1155
|
-
delete baseEntry.socket;
|
|
1156
1390
|
}
|
|
1157
1391
|
if (existing && typeof definition.url === "string" && definition.url !== existing.url) {
|
|
1158
1392
|
if (baseEntry === existing) baseEntry = { ...existing };
|
|
@@ -1194,11 +1428,11 @@ function expandImports(config, cwd = process.cwd()) {
|
|
|
1194
1428
|
function resolveImportCandidates(importKind, cwd) {
|
|
1195
1429
|
return (IMPORT_PATHS[importKind] ?? []).map((candidate) => {
|
|
1196
1430
|
if (importKind === "opencode" && candidate === "./opencode.json") {
|
|
1197
|
-
const start =
|
|
1431
|
+
const start = resolve4(cwd);
|
|
1198
1432
|
let gitRoot;
|
|
1199
1433
|
let current = start;
|
|
1200
1434
|
while (true) {
|
|
1201
|
-
if (
|
|
1435
|
+
if (existsSync3(join4(current, ".git"))) {
|
|
1202
1436
|
gitRoot = current;
|
|
1203
1437
|
break;
|
|
1204
1438
|
}
|
|
@@ -1206,22 +1440,22 @@ function resolveImportCandidates(importKind, cwd) {
|
|
|
1206
1440
|
if (parent === current) break;
|
|
1207
1441
|
current = parent;
|
|
1208
1442
|
}
|
|
1209
|
-
if (!gitRoot) return
|
|
1443
|
+
if (!gitRoot) return join4(start, "opencode.json");
|
|
1210
1444
|
current = start;
|
|
1211
1445
|
while (true) {
|
|
1212
|
-
const projectConfig =
|
|
1213
|
-
if (
|
|
1446
|
+
const projectConfig = join4(current, "opencode.json");
|
|
1447
|
+
if (existsSync3(projectConfig) || current === gitRoot) return projectConfig;
|
|
1214
1448
|
current = dirname(current);
|
|
1215
1449
|
}
|
|
1216
1450
|
}
|
|
1217
|
-
return candidate.startsWith(".") ?
|
|
1451
|
+
return candidate.startsWith(".") ? resolve4(cwd, candidate) : candidate;
|
|
1218
1452
|
});
|
|
1219
1453
|
}
|
|
1220
1454
|
function parseJsonConfig(raw) {
|
|
1221
|
-
return JSON.parse(
|
|
1455
|
+
return JSON.parse(stripJsonComments2(raw, { trailingCommas: true }));
|
|
1222
1456
|
}
|
|
1223
1457
|
function readImportedConfig(path2) {
|
|
1224
|
-
const raw =
|
|
1458
|
+
const raw = readFileSync4(path2, "utf-8");
|
|
1225
1459
|
return path2.endsWith(".toml") ? parseToml(raw) : parseJsonConfig(raw);
|
|
1226
1460
|
}
|
|
1227
1461
|
function loadImportedConfig(importKind, cwd, warningPrefix) {
|
|
@@ -1229,7 +1463,7 @@ function loadImportedConfig(importKind, cwd, warningPrefix) {
|
|
|
1229
1463
|
let merged = {};
|
|
1230
1464
|
let highestPrecedencePath;
|
|
1231
1465
|
for (const path2 of resolveImportCandidates(importKind, cwd)) {
|
|
1232
|
-
if (!
|
|
1466
|
+
if (!existsSync3(path2)) continue;
|
|
1233
1467
|
try {
|
|
1234
1468
|
const value = readImportedConfig(path2);
|
|
1235
1469
|
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
@@ -1243,7 +1477,7 @@ function loadImportedConfig(importKind, cwd, warningPrefix) {
|
|
|
1243
1477
|
return highestPrecedencePath ? { path: highestPrecedencePath, value: merged } : null;
|
|
1244
1478
|
}
|
|
1245
1479
|
for (const path2 of resolveImportCandidates(importKind, cwd)) {
|
|
1246
|
-
if (!
|
|
1480
|
+
if (!existsSync3(path2)) continue;
|
|
1247
1481
|
try {
|
|
1248
1482
|
return { path: path2, value: readImportedConfig(path2) };
|
|
1249
1483
|
} catch (error) {
|
|
@@ -1253,9 +1487,9 @@ function loadImportedConfig(importKind, cwd, warningPrefix) {
|
|
|
1253
1487
|
return null;
|
|
1254
1488
|
}
|
|
1255
1489
|
function readValidatedConfig(path2, label) {
|
|
1256
|
-
if (!
|
|
1490
|
+
if (!existsSync3(path2)) return null;
|
|
1257
1491
|
try {
|
|
1258
|
-
return validateConfig(parseJsonConfig(
|
|
1492
|
+
return validateConfig(parseJsonConfig(readFileSync4(path2, "utf-8")));
|
|
1259
1493
|
} catch (error) {
|
|
1260
1494
|
console.warn(`Failed to load ${label}:`, error);
|
|
1261
1495
|
return null;
|
|
@@ -1467,7 +1701,7 @@ function buildUnifiedDiff(beforeText, afterText) {
|
|
|
1467
1701
|
return lines.join("\n");
|
|
1468
1702
|
}
|
|
1469
1703
|
function buildConfigWritePreview(filePath, nextRaw) {
|
|
1470
|
-
const existed =
|
|
1704
|
+
const existed = existsSync3(filePath);
|
|
1471
1705
|
const beforeRaw = readRawConfigObject(filePath);
|
|
1472
1706
|
const beforeText = existed ? serializeRawConfig(beforeRaw) : "";
|
|
1473
1707
|
const afterText = serializeRawConfig(nextRaw);
|
|
@@ -1481,9 +1715,9 @@ function buildConfigWritePreview(filePath, nextRaw) {
|
|
|
1481
1715
|
};
|
|
1482
1716
|
}
|
|
1483
1717
|
function readRawConfigObject(filePath) {
|
|
1484
|
-
if (!
|
|
1718
|
+
if (!existsSync3(filePath)) return {};
|
|
1485
1719
|
try {
|
|
1486
|
-
const raw = parseJsonConfig(
|
|
1720
|
+
const raw = parseJsonConfig(readFileSync4(filePath, "utf-8"));
|
|
1487
1721
|
return raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
|
|
1488
1722
|
} catch {
|
|
1489
1723
|
return {};
|
|
@@ -1510,9 +1744,9 @@ function setServersObject(raw, servers) {
|
|
|
1510
1744
|
function writeProjectServerDisabledOverride(overridePath, cwd, serverName, disabled) {
|
|
1511
1745
|
const filePath = getProjectPiConfigPath(cwd);
|
|
1512
1746
|
let raw = {};
|
|
1513
|
-
if (
|
|
1747
|
+
if (existsSync3(filePath)) {
|
|
1514
1748
|
try {
|
|
1515
|
-
const parsed = parseJsonConfig(
|
|
1749
|
+
const parsed = parseJsonConfig(readFileSync4(filePath, "utf-8"));
|
|
1516
1750
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
1517
1751
|
throw new Error("root value must be an object");
|
|
1518
1752
|
}
|
|
@@ -1572,9 +1806,9 @@ function isRepoPromptServer(name, entry) {
|
|
|
1572
1806
|
return (entry.args ?? []).some((arg) => typeof arg === "string" && arg.toLowerCase().includes("repoprompt"));
|
|
1573
1807
|
}
|
|
1574
1808
|
function findProjectRoot(cwd = process.cwd()) {
|
|
1575
|
-
let current =
|
|
1809
|
+
let current = resolve4(cwd);
|
|
1576
1810
|
while (true) {
|
|
1577
|
-
if (
|
|
1811
|
+
if (existsSync3(join4(current, ".git")) || existsSync3(join4(current, "package.json")) || existsSync3(join4(current, PROJECT_CONFIG_NAME)) || existsSync3(join4(current, ".pi"))) {
|
|
1578
1812
|
return current;
|
|
1579
1813
|
}
|
|
1580
1814
|
const parent = dirname(current);
|
|
@@ -1600,12 +1834,12 @@ function detectRepoPrompt(summary, cwd = process.cwd()) {
|
|
|
1600
1834
|
}
|
|
1601
1835
|
}
|
|
1602
1836
|
}
|
|
1603
|
-
const executablePath = REPOPROMPT_BINARY_CANDIDATES.find((candidate) =>
|
|
1837
|
+
const executablePath = REPOPROMPT_BINARY_CANDIDATES.find((candidate) => existsSync3(candidate));
|
|
1604
1838
|
if (!executablePath) {
|
|
1605
1839
|
return { configured: false };
|
|
1606
1840
|
}
|
|
1607
1841
|
const projectRoot = findProjectRoot(cwd);
|
|
1608
|
-
const targetPath = projectRoot ?
|
|
1842
|
+
const targetPath = projectRoot ? join4(projectRoot, PROJECT_CONFIG_NAME) : GENERIC_GLOBAL_CONFIG_PATH;
|
|
1609
1843
|
return {
|
|
1610
1844
|
configured: false,
|
|
1611
1845
|
executablePath,
|
|
@@ -1740,7 +1974,7 @@ function resolveConfiguredOAuthDir(raw, cwd = process.cwd()) {
|
|
|
1740
1974
|
}
|
|
1741
1975
|
const trimmed = raw.trim();
|
|
1742
1976
|
if (!trimmed) return void 0;
|
|
1743
|
-
return
|
|
1977
|
+
return resolve4(cwd, trimmed);
|
|
1744
1978
|
}
|
|
1745
1979
|
var GENERIC_GLOBAL_CONFIG_PATH, AGENTS_GLOBAL_CONFIG_PATHS, PROJECT_CONFIG_NAME, PROJECT_PI_CONFIG_NAME, REPOPROMPT_BINARY_CANDIDATES, KNOWN_SERVER_PRESETS, IMPORT_PATHS, URL_BOUND_AUTH_FIELDS;
|
|
1746
1980
|
var init_config = __esm({
|
|
@@ -1748,17 +1982,18 @@ var init_config = __esm({
|
|
|
1748
1982
|
"use strict";
|
|
1749
1983
|
init_agent_dir();
|
|
1750
1984
|
init_agent_plugin_loader();
|
|
1985
|
+
init_package_mcp_loader();
|
|
1751
1986
|
init_types();
|
|
1752
1987
|
init_utils();
|
|
1753
|
-
GENERIC_GLOBAL_CONFIG_PATH =
|
|
1988
|
+
GENERIC_GLOBAL_CONFIG_PATH = join4(homedir3(), ".config", "mcp", "mcp.json");
|
|
1754
1989
|
AGENTS_GLOBAL_CONFIG_PATHS = [
|
|
1755
|
-
|
|
1756
|
-
|
|
1990
|
+
join4(homedir3(), ".agents", "mcp.json"),
|
|
1991
|
+
join4(homedir3(), ".agents", "mcp", "mcp.json")
|
|
1757
1992
|
];
|
|
1758
1993
|
PROJECT_CONFIG_NAME = ".mcp.json";
|
|
1759
1994
|
PROJECT_PI_CONFIG_NAME = "mcp.json";
|
|
1760
1995
|
REPOPROMPT_BINARY_CANDIDATES = [
|
|
1761
|
-
|
|
1996
|
+
join4(homedir3(), "RepoPrompt", "repoprompt_cli"),
|
|
1762
1997
|
"/Applications/Repo Prompt.app/Contents/MacOS/repoprompt-mcp"
|
|
1763
1998
|
];
|
|
1764
1999
|
KNOWN_SERVER_PRESETS = [
|
|
@@ -1794,25 +2029,25 @@ var init_config = __esm({
|
|
|
1794
2029
|
}
|
|
1795
2030
|
];
|
|
1796
2031
|
IMPORT_PATHS = {
|
|
1797
|
-
cursor: [
|
|
2032
|
+
cursor: [join4(homedir3(), ".cursor", "mcp.json")],
|
|
1798
2033
|
"claude-code": [
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
2034
|
+
join4(homedir3(), ".claude", "mcp.json"),
|
|
2035
|
+
join4(homedir3(), ".claude.json"),
|
|
2036
|
+
join4(homedir3(), ".claude", "claude_desktop_config.json")
|
|
1802
2037
|
],
|
|
1803
|
-
"claude-desktop": [
|
|
2038
|
+
"claude-desktop": [join4(homedir3(), "Library", "Application Support", "Claude", "claude_desktop_config.json")],
|
|
1804
2039
|
codex: [
|
|
1805
|
-
|
|
1806
|
-
|
|
2040
|
+
join4(homedir3(), ".codex", "config.toml"),
|
|
2041
|
+
join4(homedir3(), ".codex", "config.json")
|
|
1807
2042
|
],
|
|
1808
2043
|
opencode: [
|
|
1809
|
-
|
|
2044
|
+
join4(homedir3(), ".config", "opencode", "opencode.json"),
|
|
1810
2045
|
"./opencode.json"
|
|
1811
2046
|
],
|
|
1812
|
-
windsurf: [
|
|
2047
|
+
windsurf: [join4(homedir3(), ".windsurf", "mcp.json")],
|
|
1813
2048
|
vscode: [".vscode/mcp.json"]
|
|
1814
2049
|
};
|
|
1815
|
-
URL_BOUND_AUTH_FIELDS = ["headers", "bearerToken", "bearerTokenEnv", "requestHeadersCommand"];
|
|
2050
|
+
URL_BOUND_AUTH_FIELDS = ["headers", "bearerToken", "bearerTokenEnv", "bearerTokenStore", "requestHeadersCommand"];
|
|
1816
2051
|
}
|
|
1817
2052
|
});
|
|
1818
2053
|
|
|
@@ -1896,7 +2131,7 @@ var init_ui_tool_visibility = __esm({
|
|
|
1896
2131
|
});
|
|
1897
2132
|
|
|
1898
2133
|
// packages/coding-agent/src/humain/mcp-adapter/vendor/metadata-cache.ts
|
|
1899
|
-
import { existsSync as
|
|
2134
|
+
import { existsSync as existsSync5, readFileSync as readFileSync6, writeFileSync as writeFileSync2, renameSync as renameSync2, mkdirSync as mkdirSync2 } from "node:fs";
|
|
1900
2135
|
import { dirname as dirname3 } from "node:path";
|
|
1901
2136
|
import { createHash as createHash2 } from "node:crypto";
|
|
1902
2137
|
function getMetadataCachePath() {
|
|
@@ -1904,9 +2139,9 @@ function getMetadataCachePath() {
|
|
|
1904
2139
|
}
|
|
1905
2140
|
function loadMetadataCache() {
|
|
1906
2141
|
const cachePath = getMetadataCachePath();
|
|
1907
|
-
if (!
|
|
2142
|
+
if (!existsSync5(cachePath)) return null;
|
|
1908
2143
|
try {
|
|
1909
|
-
const raw = JSON.parse(
|
|
2144
|
+
const raw = JSON.parse(readFileSync6(cachePath, "utf-8"));
|
|
1910
2145
|
if (!raw || typeof raw !== "object") return null;
|
|
1911
2146
|
if (raw.version !== CACHE_VERSION) return null;
|
|
1912
2147
|
if (!raw.servers || typeof raw.servers !== "object") return null;
|
|
@@ -1921,8 +2156,8 @@ function saveMetadataCache(cache) {
|
|
|
1921
2156
|
mkdirSync2(dir, { recursive: true });
|
|
1922
2157
|
let merged = { version: CACHE_VERSION, servers: {} };
|
|
1923
2158
|
try {
|
|
1924
|
-
if (
|
|
1925
|
-
const existing = JSON.parse(
|
|
2159
|
+
if (existsSync5(cachePath)) {
|
|
2160
|
+
const existing = JSON.parse(readFileSync6(cachePath, "utf-8"));
|
|
1926
2161
|
if (existing && existing.version === CACHE_VERSION && existing.servers) {
|
|
1927
2162
|
merged.servers = { ...existing.servers };
|
|
1928
2163
|
}
|
|
@@ -1932,7 +2167,7 @@ function saveMetadataCache(cache) {
|
|
|
1932
2167
|
merged.version = CACHE_VERSION;
|
|
1933
2168
|
merged.servers = { ...merged.servers, ...cache.servers };
|
|
1934
2169
|
const tmpPath = `${cachePath}.${process.pid}.tmp`;
|
|
1935
|
-
writeFileSync2(tmpPath, JSON.stringify(merged
|
|
2170
|
+
writeFileSync2(tmpPath, JSON.stringify(merged), "utf-8");
|
|
1936
2171
|
renameSync2(tmpPath, cachePath);
|
|
1937
2172
|
}
|
|
1938
2173
|
function computeServerHash(definition) {
|
|
@@ -2008,30 +2243,12 @@ function getMissingConfiguredDirectToolServers(config, cache, envOverride) {
|
|
|
2008
2243
|
}
|
|
2009
2244
|
return missing;
|
|
2010
2245
|
}
|
|
2011
|
-
function reconstructToolMetadata(serverName, entry, prefix, definition, configuredServers, cache) {
|
|
2246
|
+
function reconstructToolMetadata(serverName, entry, prefix, definition, configuredServers, cache, sharedSelectorCandidateIndex) {
|
|
2012
2247
|
const metadata = [];
|
|
2013
2248
|
const seenNames = /* @__PURE__ */ new Set();
|
|
2014
2249
|
const effectivePrefix = resolveToolPrefix(definition, prefix);
|
|
2015
2250
|
const hasToolFilters = Array.isArray(definition.includeTools) && definition.includeTools.length > 0 || Array.isArray(definition.excludeTools) && definition.excludeTools.length > 0;
|
|
2016
|
-
const selectorCandidateIndex = hasToolFilters
|
|
2017
|
-
const candidates = /* @__PURE__ */ new Set();
|
|
2018
|
-
for (const [otherServerName, otherDefinition] of Object.entries(configuredServers)) {
|
|
2019
|
-
const otherEntry = cache.servers[otherServerName];
|
|
2020
|
-
if (!otherEntry || !isServerCacheValid(otherEntry, otherDefinition) || isServerDisabled(otherDefinition)) continue;
|
|
2021
|
-
const otherPrefix = resolveToolPrefix(otherDefinition, prefix);
|
|
2022
|
-
for (const otherTool of otherEntry.tools ?? []) {
|
|
2023
|
-
if (!isUiToolVisibleToModel(otherTool.uiVisibility)) continue;
|
|
2024
|
-
for (const candidate of getToolNameCandidates(otherTool.name, otherServerName, otherPrefix, false)) candidates.add(candidate);
|
|
2025
|
-
}
|
|
2026
|
-
if (otherDefinition.exposeResources !== false) {
|
|
2027
|
-
for (const resource of otherEntry.resources ?? []) {
|
|
2028
|
-
const baseName = `read_${resourceNameToToolName(resource.name)}`;
|
|
2029
|
-
for (const candidate of getToolNameCandidates(baseName, otherServerName, otherPrefix, false)) candidates.add(candidate);
|
|
2030
|
-
}
|
|
2031
|
-
}
|
|
2032
|
-
}
|
|
2033
|
-
return createToolSelectorCandidateIndex(candidates);
|
|
2034
|
-
})() : void 0;
|
|
2251
|
+
const selectorCandidateIndex = hasToolFilters ? sharedSelectorCandidateIndex ?? (configuredServers && cache ? createCachedToolSelectorCandidateIndex(configuredServers, cache, prefix) : void 0) : void 0;
|
|
2035
2252
|
for (const tool of entry.tools ?? []) {
|
|
2036
2253
|
if (!tool?.name) continue;
|
|
2037
2254
|
if (!isUiToolVisibleToModel(tool.uiVisibility)) {
|
|
@@ -2077,6 +2294,25 @@ function reconstructToolMetadata(serverName, entry, prefix, definition, configur
|
|
|
2077
2294
|
}
|
|
2078
2295
|
return metadata;
|
|
2079
2296
|
}
|
|
2297
|
+
function createCachedToolSelectorCandidateIndex(configuredServers, cache, prefix) {
|
|
2298
|
+
const candidates = /* @__PURE__ */ new Set();
|
|
2299
|
+
for (const [serverName, definition] of Object.entries(configuredServers)) {
|
|
2300
|
+
const entry = cache.servers[serverName];
|
|
2301
|
+
if (!entry || !isServerCacheValid(entry, definition) || isServerDisabled(definition)) continue;
|
|
2302
|
+
const effectivePrefix = resolveToolPrefix(definition, prefix);
|
|
2303
|
+
for (const tool of entry.tools ?? []) {
|
|
2304
|
+
if (!isUiToolVisibleToModel(tool.uiVisibility)) continue;
|
|
2305
|
+
for (const candidate of getToolNameCandidates(tool.name, serverName, effectivePrefix, false)) candidates.add(candidate);
|
|
2306
|
+
}
|
|
2307
|
+
if (definition.exposeResources !== false) {
|
|
2308
|
+
for (const resource of entry.resources ?? []) {
|
|
2309
|
+
const baseName = `read_${resourceNameToToolName(resource.name)}`;
|
|
2310
|
+
for (const candidate of getToolNameCandidates(baseName, serverName, effectivePrefix, false)) candidates.add(candidate);
|
|
2311
|
+
}
|
|
2312
|
+
}
|
|
2313
|
+
}
|
|
2314
|
+
return createToolSelectorCandidateIndex(candidates);
|
|
2315
|
+
}
|
|
2080
2316
|
function serializeTools(tools) {
|
|
2081
2317
|
return tools.filter((t) => t?.name).map((t) => {
|
|
2082
2318
|
const uiResourceUri = tryGetToolUiResourceUri(t);
|
|
@@ -2759,8 +2995,8 @@ var init_mcp_setup_panel = __esm({
|
|
|
2759
2995
|
});
|
|
2760
2996
|
|
|
2761
2997
|
// packages/coding-agent/src/utils/clipboard-native.ts
|
|
2762
|
-
import { createRequire as
|
|
2763
|
-
import { dirname as
|
|
2998
|
+
import { createRequire as createRequire3 } from "module";
|
|
2999
|
+
import { dirname as dirname8, join as join8 } from "path";
|
|
2764
3000
|
import { pathToFileURL } from "url";
|
|
2765
3001
|
function loadClipboardNative(requires = [moduleRequire, executableDirRequire]) {
|
|
2766
3002
|
for (const requireClipboard of requires) {
|
|
@@ -2775,21 +3011,21 @@ var moduleRequire, executableDirRequire, hasDisplay, clipboard;
|
|
|
2775
3011
|
var init_clipboard_native = __esm({
|
|
2776
3012
|
"packages/coding-agent/src/utils/clipboard-native.ts"() {
|
|
2777
3013
|
"use strict";
|
|
2778
|
-
moduleRequire =
|
|
2779
|
-
executableDirRequire =
|
|
3014
|
+
moduleRequire = createRequire3(import.meta.url);
|
|
3015
|
+
executableDirRequire = createRequire3(pathToFileURL(join8(dirname8(process.execPath), "package.json")).href);
|
|
2780
3016
|
hasDisplay = process.platform !== "linux" || Boolean(process.env.DISPLAY || process.env.WAYLAND_DISPLAY);
|
|
2781
3017
|
clipboard = !process.env.TERMUX_VERSION && hasDisplay ? loadClipboardNative() : null;
|
|
2782
3018
|
}
|
|
2783
3019
|
});
|
|
2784
3020
|
|
|
2785
3021
|
// packages/coding-agent/src/utils/photon.ts
|
|
2786
|
-
import { createRequire as
|
|
2787
|
-
var
|
|
3022
|
+
import { createRequire as createRequire4 } from "module";
|
|
3023
|
+
var require4, fs;
|
|
2788
3024
|
var init_photon = __esm({
|
|
2789
3025
|
"packages/coding-agent/src/utils/photon.ts"() {
|
|
2790
3026
|
"use strict";
|
|
2791
|
-
|
|
2792
|
-
fs =
|
|
3027
|
+
require4 = createRequire4(import.meta.url);
|
|
3028
|
+
fs = require4("fs");
|
|
2793
3029
|
}
|
|
2794
3030
|
});
|
|
2795
3031
|
|
|
@@ -2866,10 +3102,10 @@ async function copyToClipboard(text) {
|
|
|
2866
3102
|
if (isWayland && hasWaylandDisplay) {
|
|
2867
3103
|
try {
|
|
2868
3104
|
execSync("which wl-copy", { stdio: "ignore" });
|
|
2869
|
-
const wlCopyExit = await new Promise((
|
|
3105
|
+
const wlCopyExit = await new Promise((resolve7) => {
|
|
2870
3106
|
const proc = spawn2("wl-copy", [], { stdio: ["pipe", "ignore", "ignore"] });
|
|
2871
|
-
proc.on("error", () =>
|
|
2872
|
-
proc.on("close", (code) =>
|
|
3107
|
+
proc.on("error", () => resolve7(1));
|
|
3108
|
+
proc.on("close", (code) => resolve7(code ?? 1));
|
|
2873
3109
|
proc.stdin.on("error", () => {
|
|
2874
3110
|
});
|
|
2875
3111
|
proc.stdin.write(text);
|
|
@@ -3100,6 +3336,13 @@ var init_mcp_panel = __esm({
|
|
|
3100
3336
|
}
|
|
3101
3337
|
const status = callbacks.getConnectionStatus(serverName);
|
|
3102
3338
|
const failureMessage = callbacks.getFailureMessage?.(serverName) ?? null;
|
|
3339
|
+
let directCount = 0;
|
|
3340
|
+
let directTokens = 0;
|
|
3341
|
+
for (const tool of tools) {
|
|
3342
|
+
if (!tool.isDirect) continue;
|
|
3343
|
+
directCount++;
|
|
3344
|
+
directTokens += tool.estimatedTokens;
|
|
3345
|
+
}
|
|
3103
3346
|
this.servers.push({
|
|
3104
3347
|
name: serverName,
|
|
3105
3348
|
expanded: false,
|
|
@@ -3111,6 +3354,8 @@ var init_mcp_panel = __esm({
|
|
|
3111
3354
|
connectionStatus: status,
|
|
3112
3355
|
failureMessage,
|
|
3113
3356
|
tools,
|
|
3357
|
+
directCount,
|
|
3358
|
+
directTokens,
|
|
3114
3359
|
hasCachedData: !!serverCache
|
|
3115
3360
|
});
|
|
3116
3361
|
}
|
|
@@ -3297,7 +3542,7 @@ var init_mcp_panel = __esm({
|
|
|
3297
3542
|
} else if (item.toolIndex !== void 0) {
|
|
3298
3543
|
const tool = server2.tools[item.toolIndex];
|
|
3299
3544
|
if (!tool) return;
|
|
3300
|
-
|
|
3545
|
+
this.toggleToolDirect(server2, tool);
|
|
3301
3546
|
if (tool.isDirect && server2.source === "import") {
|
|
3302
3547
|
this.importNotice = `Imported from ${sanitizeDisplayText(server2.importKind ?? "external")} \u2014 will copy to user config on save`;
|
|
3303
3548
|
}
|
|
@@ -3430,17 +3675,28 @@ var init_mcp_panel = __esm({
|
|
|
3430
3675
|
if (server2.source === "import" && newState) {
|
|
3431
3676
|
this.importNotice = `Imported from ${sanitizeDisplayText(server2.importKind ?? "external")} \u2014 will copy to user config on save`;
|
|
3432
3677
|
}
|
|
3433
|
-
|
|
3678
|
+
let directTokens = 0;
|
|
3679
|
+
for (const tool of server2.tools) {
|
|
3680
|
+
tool.isDirect = newState;
|
|
3681
|
+
if (newState) directTokens += tool.estimatedTokens;
|
|
3682
|
+
}
|
|
3683
|
+
server2.directCount = newState ? server2.tools.length : 0;
|
|
3684
|
+
server2.directTokens = directTokens;
|
|
3434
3685
|
} else if (item.toolIndex !== void 0) {
|
|
3435
3686
|
const tool = server2.tools[item.toolIndex];
|
|
3436
3687
|
if (!tool) return;
|
|
3437
|
-
|
|
3688
|
+
this.toggleToolDirect(server2, tool);
|
|
3438
3689
|
if (tool.isDirect && server2.source === "import") {
|
|
3439
3690
|
this.importNotice = `Imported from ${sanitizeDisplayText(server2.importKind ?? "external")} \u2014 will copy to user config on save`;
|
|
3440
3691
|
}
|
|
3441
3692
|
}
|
|
3442
3693
|
this.updateDirty();
|
|
3443
3694
|
}
|
|
3695
|
+
toggleToolDirect(server2, tool) {
|
|
3696
|
+
tool.isDirect = !tool.isDirect;
|
|
3697
|
+
server2.directCount += tool.isDirect ? 1 : -1;
|
|
3698
|
+
server2.directTokens += tool.isDirect ? tool.estimatedTokens : -tool.estimatedTokens;
|
|
3699
|
+
}
|
|
3444
3700
|
handleDiscardInput(data) {
|
|
3445
3701
|
if (matchesKey3(data, "ctrl+c")) {
|
|
3446
3702
|
this.cleanup();
|
|
@@ -3536,6 +3792,13 @@ var init_mcp_panel = __esm({
|
|
|
3536
3792
|
}
|
|
3537
3793
|
}
|
|
3538
3794
|
server2.tools = newTools;
|
|
3795
|
+
server2.directCount = 0;
|
|
3796
|
+
server2.directTokens = 0;
|
|
3797
|
+
for (const tool of newTools) {
|
|
3798
|
+
if (!tool.isDirect) continue;
|
|
3799
|
+
server2.directCount++;
|
|
3800
|
+
server2.directTokens += tool.estimatedTokens;
|
|
3801
|
+
}
|
|
3539
3802
|
this.rebuildVisibleItems();
|
|
3540
3803
|
this.updateDirty();
|
|
3541
3804
|
}
|
|
@@ -3625,12 +3888,13 @@ var init_mcp_panel = __esm({
|
|
|
3625
3888
|
if (this.authOnly) {
|
|
3626
3889
|
lines.push(row(fg2(t.description, "select a server to authenticate")));
|
|
3627
3890
|
} else {
|
|
3628
|
-
|
|
3629
|
-
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
|
|
3633
|
-
|
|
3891
|
+
let directCount = 0;
|
|
3892
|
+
let directTokens = 0;
|
|
3893
|
+
for (const server2 of this.servers) {
|
|
3894
|
+
directCount += server2.directCount;
|
|
3895
|
+
directTokens += server2.directTokens;
|
|
3896
|
+
}
|
|
3897
|
+
const stats = directCount > 0 ? `${directCount} direct ~${directTokens.toLocaleString()} tokens` : "no direct tools";
|
|
3634
3898
|
lines.push(row(fg2(t.description, stats + (this.dirty ? fg2(t.needsAuth, " (unsaved)") : ""))));
|
|
3635
3899
|
}
|
|
3636
3900
|
}
|
|
@@ -3688,7 +3952,7 @@ var init_mcp_panel = __esm({
|
|
|
3688
3952
|
if (!server2.hasCachedData && !this.authOnly) {
|
|
3689
3953
|
return `${prefix} ${nameStr}${importLabel} ${fg2(t.description, "(not cached)")}${statusLabel}`;
|
|
3690
3954
|
}
|
|
3691
|
-
const directCount = server2.
|
|
3955
|
+
const directCount = server2.directCount;
|
|
3692
3956
|
const totalCount = server2.tools.length;
|
|
3693
3957
|
let toggleIcon = fg2(t.description, "\u25CB");
|
|
3694
3958
|
if (directCount === totalCount && totalCount > 0) {
|
|
@@ -3700,8 +3964,7 @@ var init_mcp_panel = __esm({
|
|
|
3700
3964
|
if (totalCount > 0) {
|
|
3701
3965
|
toolInfo = `${directCount}/${totalCount}`;
|
|
3702
3966
|
if (directCount > 0) {
|
|
3703
|
-
|
|
3704
|
-
toolInfo += ` ~${tokens.toLocaleString()}`;
|
|
3967
|
+
toolInfo += ` ~${server2.directTokens.toLocaleString()}`;
|
|
3705
3968
|
}
|
|
3706
3969
|
toolInfo = fg2(t.description, toolInfo);
|
|
3707
3970
|
}
|
|
@@ -3788,7 +4051,7 @@ init_config();
|
|
|
3788
4051
|
// packages/coding-agent/src/humain/mcp-adapter/vendor/init.ts
|
|
3789
4052
|
init_types();
|
|
3790
4053
|
init_config();
|
|
3791
|
-
import { existsSync as
|
|
4054
|
+
import { existsSync as existsSync7 } from "node:fs";
|
|
3792
4055
|
|
|
3793
4056
|
// packages/coding-agent/src/humain/mcp-adapter/vendor/errors.ts
|
|
3794
4057
|
var McpUiError = class extends Error {
|
|
@@ -4053,6 +4316,7 @@ var ConsentManager = class {
|
|
|
4053
4316
|
|
|
4054
4317
|
// packages/coding-agent/src/humain/mcp-adapter/vendor/lifecycle.ts
|
|
4055
4318
|
init_types();
|
|
4319
|
+
import { SdkError, SdkErrorCode } from "@modelcontextprotocol/client";
|
|
4056
4320
|
|
|
4057
4321
|
// packages/coding-agent/src/humain/mcp-adapter/vendor/mcp-auth-flow.ts
|
|
4058
4322
|
import {
|
|
@@ -4074,8 +4338,8 @@ init_config();
|
|
|
4074
4338
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
4075
4339
|
import { createHash } from "crypto";
|
|
4076
4340
|
import { createRequire } from "module";
|
|
4077
|
-
import { readFileSync as
|
|
4078
|
-
import { dirname as dirname2, join as
|
|
4341
|
+
import { readFileSync as readFileSync5, existsSync as existsSync4, rmSync } from "fs";
|
|
4342
|
+
import { dirname as dirname2, join as join5 } from "path";
|
|
4079
4343
|
import { fileURLToPath } from "url";
|
|
4080
4344
|
var require2 = createRequire(import.meta.url);
|
|
4081
4345
|
var AUTH_SECRET_SERVICE = "pi-mcp-adapter.oauth";
|
|
@@ -4230,7 +4494,7 @@ function loadKeyringNativeBindingFallback(keyringRequire, platform4, arch) {
|
|
|
4230
4494
|
for (const target of targets) {
|
|
4231
4495
|
try {
|
|
4232
4496
|
const packageJsonPath = keyringRequire.resolve(`${target.packageName}/package.json`);
|
|
4233
|
-
return keyringRequire(
|
|
4497
|
+
return keyringRequire(join5(dirname2(packageJsonPath), target.bindingFile));
|
|
4234
4498
|
} catch (error) {
|
|
4235
4499
|
lastError = error;
|
|
4236
4500
|
}
|
|
@@ -4335,7 +4599,7 @@ function getServerDir(serverName, options) {
|
|
|
4335
4599
|
throw new Error(`Invalid MCP server name: ${JSON.stringify(serverName)}`);
|
|
4336
4600
|
}
|
|
4337
4601
|
const storageKey = getAuthEntryAccount(serverName);
|
|
4338
|
-
return
|
|
4602
|
+
return join5(getAuthBaseDir(options), storageKey);
|
|
4339
4603
|
}
|
|
4340
4604
|
function getAuthEntryAccount(serverName) {
|
|
4341
4605
|
if (typeof serverName !== "string") {
|
|
@@ -4344,7 +4608,7 @@ function getAuthEntryAccount(serverName) {
|
|
|
4344
4608
|
return `sha256-${createHash("sha256").update(serverName, "utf8").digest("hex")}`;
|
|
4345
4609
|
}
|
|
4346
4610
|
function getAuthEntryFilePath(serverName, options) {
|
|
4347
|
-
return
|
|
4611
|
+
return join5(getServerDir(serverName, options), "tokens.json");
|
|
4348
4612
|
}
|
|
4349
4613
|
function parseJsonPayload(serverName, payload, source) {
|
|
4350
4614
|
try {
|
|
@@ -4455,8 +4719,8 @@ function readExistingChunkManifest(store, serverName, account) {
|
|
|
4455
4719
|
}
|
|
4456
4720
|
}
|
|
4457
4721
|
function removeChunkPayloads(store, account, manifest) {
|
|
4458
|
-
for (const
|
|
4459
|
-
store.remove(
|
|
4722
|
+
for (const chunkAccount2 of getAuthEntryChunkAccounts(account, manifest)) {
|
|
4723
|
+
store.remove(chunkAccount2);
|
|
4460
4724
|
}
|
|
4461
4725
|
}
|
|
4462
4726
|
function tryRemoveChunkPayloads(store, account, manifest) {
|
|
@@ -4474,11 +4738,11 @@ function createChunkManifest(payload) {
|
|
|
4474
4738
|
};
|
|
4475
4739
|
}
|
|
4476
4740
|
function readChunkedAuthEntry(store, serverName, account, manifest) {
|
|
4477
|
-
const chunks = getAuthEntryChunkAccounts(account, manifest).map((
|
|
4741
|
+
const chunks = getAuthEntryChunkAccounts(account, manifest).map((chunkAccount2) => {
|
|
4478
4742
|
try {
|
|
4479
|
-
const chunk = store.read(
|
|
4743
|
+
const chunk = store.read(chunkAccount2);
|
|
4480
4744
|
if (chunk === void 0) {
|
|
4481
|
-
throw new Error(`Missing OAuth credential chunk ${
|
|
4745
|
+
throw new Error(`Missing OAuth credential chunk ${chunkAccount2} for ${serverName}`);
|
|
4482
4746
|
}
|
|
4483
4747
|
return chunk;
|
|
4484
4748
|
} catch (error) {
|
|
@@ -4493,13 +4757,13 @@ function readChunkedAuthEntry(store, serverName, account, manifest) {
|
|
|
4493
4757
|
}
|
|
4494
4758
|
function readLegacyAuthEntry(serverName, options) {
|
|
4495
4759
|
const filePath = getAuthEntryFilePath(serverName, options);
|
|
4496
|
-
if (!
|
|
4497
|
-
const data =
|
|
4760
|
+
if (!existsSync4(filePath)) return void 0;
|
|
4761
|
+
const data = readFileSync5(filePath, "utf-8");
|
|
4498
4762
|
return parseAuthEntryPayload(serverName, data, filePath);
|
|
4499
4763
|
}
|
|
4500
4764
|
function removeLegacyAuthEntry(serverName, options) {
|
|
4501
4765
|
const filePath = getAuthEntryFilePath(serverName, options);
|
|
4502
|
-
if (!
|
|
4766
|
+
if (!existsSync4(filePath)) return;
|
|
4503
4767
|
try {
|
|
4504
4768
|
rmSync(filePath, { force: true });
|
|
4505
4769
|
} catch (error) {
|
|
@@ -5260,6 +5524,7 @@ function htmlError(error) {
|
|
|
5260
5524
|
var server;
|
|
5261
5525
|
var bindingPromise;
|
|
5262
5526
|
var stoppingPromise;
|
|
5527
|
+
var restartableStoppingPromise;
|
|
5263
5528
|
var callbackGeneration = 0;
|
|
5264
5529
|
var pendingAuths = /* @__PURE__ */ new Map();
|
|
5265
5530
|
var reservedAuthStates = /* @__PURE__ */ new Set();
|
|
@@ -5327,10 +5592,16 @@ function handleRequest(req, res) {
|
|
|
5327
5592
|
res.end(htmlSuccess());
|
|
5328
5593
|
}
|
|
5329
5594
|
async function ensureCallbackServer(options = {}) {
|
|
5595
|
+
const generation = callbackGeneration;
|
|
5330
5596
|
if (stoppingPromise) {
|
|
5331
|
-
|
|
5597
|
+
if (!restartableStoppingPromise) {
|
|
5598
|
+
throw new Error("OAuth callback server stopped");
|
|
5599
|
+
}
|
|
5600
|
+
await restartableStoppingPromise;
|
|
5601
|
+
if (generation !== callbackGeneration) {
|
|
5602
|
+
throw new Error("OAuth callback server stopped");
|
|
5603
|
+
}
|
|
5332
5604
|
}
|
|
5333
|
-
const generation = callbackGeneration;
|
|
5334
5605
|
while (bindingPromise) {
|
|
5335
5606
|
await bindingPromise;
|
|
5336
5607
|
if (generation !== callbackGeneration) {
|
|
@@ -5389,12 +5660,12 @@ async function ensureCallbackServerLocked(options = {}) {
|
|
|
5389
5660
|
const candidateServer = createServer(handleRequest);
|
|
5390
5661
|
const listenPort = strictPort ? requiredPort : 0;
|
|
5391
5662
|
try {
|
|
5392
|
-
await new Promise((
|
|
5663
|
+
await new Promise((resolve7, reject) => {
|
|
5393
5664
|
candidateServer.once("error", (err) => {
|
|
5394
5665
|
reject(err);
|
|
5395
5666
|
});
|
|
5396
5667
|
candidateServer.listen(listenPort, requestedHost, () => {
|
|
5397
|
-
|
|
5668
|
+
resolve7();
|
|
5398
5669
|
});
|
|
5399
5670
|
});
|
|
5400
5671
|
if (strictPort) {
|
|
@@ -5407,8 +5678,8 @@ async function ensureCallbackServerLocked(options = {}) {
|
|
|
5407
5678
|
setOAuthCallbackPort(address.port);
|
|
5408
5679
|
}
|
|
5409
5680
|
if (previousServer && (needsStrictRebind || needsHostSwitch)) {
|
|
5410
|
-
await new Promise((
|
|
5411
|
-
previousServer.close(() =>
|
|
5681
|
+
await new Promise((resolve7) => {
|
|
5682
|
+
previousServer.close(() => resolve7());
|
|
5412
5683
|
});
|
|
5413
5684
|
}
|
|
5414
5685
|
callbackServerHost = requestedHost;
|
|
@@ -5424,8 +5695,8 @@ async function ensureCallbackServerLocked(options = {}) {
|
|
|
5424
5695
|
reservedAuthStates.delete(reservedState);
|
|
5425
5696
|
}
|
|
5426
5697
|
const nodeError = error;
|
|
5427
|
-
await new Promise((
|
|
5428
|
-
candidateServer.close(() =>
|
|
5698
|
+
await new Promise((resolve7) => {
|
|
5699
|
+
candidateServer.close(() => resolve7());
|
|
5429
5700
|
});
|
|
5430
5701
|
if (strictPort && nodeError.code === "EADDRINUSE") {
|
|
5431
5702
|
throw new Error(
|
|
@@ -5441,14 +5712,14 @@ function releaseCallbackServer(oauthState) {
|
|
|
5441
5712
|
}
|
|
5442
5713
|
function waitForCallback(oauthState) {
|
|
5443
5714
|
reservedAuthStates.delete(oauthState);
|
|
5444
|
-
return new Promise((
|
|
5715
|
+
return new Promise((resolve7, reject) => {
|
|
5445
5716
|
const timeout = setTimeout(() => {
|
|
5446
5717
|
if (pendingAuths.has(oauthState)) {
|
|
5447
5718
|
pendingAuths.delete(oauthState);
|
|
5448
5719
|
reject(new Error("OAuth callback timeout - authorization took too long"));
|
|
5449
5720
|
}
|
|
5450
5721
|
}, CALLBACK_TIMEOUT_MS);
|
|
5451
|
-
pendingAuths.set(oauthState, { resolve:
|
|
5722
|
+
pendingAuths.set(oauthState, { resolve: resolve7, reject, timeout });
|
|
5452
5723
|
});
|
|
5453
5724
|
}
|
|
5454
5725
|
function cancelPendingCallback(oauthState) {
|
|
@@ -5461,7 +5732,11 @@ function cancelPendingCallback(oauthState) {
|
|
|
5461
5732
|
}
|
|
5462
5733
|
}
|
|
5463
5734
|
function stopCallbackServer() {
|
|
5464
|
-
if (stoppingPromise)
|
|
5735
|
+
if (stoppingPromise) {
|
|
5736
|
+
restartableStoppingPromise = void 0;
|
|
5737
|
+
callbackGeneration += 1;
|
|
5738
|
+
return stoppingPromise;
|
|
5739
|
+
}
|
|
5465
5740
|
callbackGeneration += 1;
|
|
5466
5741
|
const cleanup = (async () => {
|
|
5467
5742
|
while (bindingPromise) {
|
|
@@ -5469,9 +5744,9 @@ function stopCallbackServer() {
|
|
|
5469
5744
|
});
|
|
5470
5745
|
}
|
|
5471
5746
|
if (server) {
|
|
5472
|
-
await new Promise((
|
|
5747
|
+
await new Promise((resolve7) => {
|
|
5473
5748
|
server.close(() => {
|
|
5474
|
-
|
|
5749
|
+
resolve7();
|
|
5475
5750
|
});
|
|
5476
5751
|
});
|
|
5477
5752
|
server = void 0;
|
|
@@ -5495,6 +5770,17 @@ function stopCallbackServer() {
|
|
|
5495
5770
|
stoppingPromise = operation;
|
|
5496
5771
|
return operation;
|
|
5497
5772
|
}
|
|
5773
|
+
function stopCallbackServerIfIdle() {
|
|
5774
|
+
if (stoppingPromise) return stoppingPromise;
|
|
5775
|
+
if (bindingPromise || !server || pendingAuths.size > 0 || reservedAuthStates.size > 0) {
|
|
5776
|
+
return Promise.resolve();
|
|
5777
|
+
}
|
|
5778
|
+
const operation = stopCallbackServer().finally(() => {
|
|
5779
|
+
if (restartableStoppingPromise === operation) restartableStoppingPromise = void 0;
|
|
5780
|
+
});
|
|
5781
|
+
restartableStoppingPromise = operation;
|
|
5782
|
+
return operation;
|
|
5783
|
+
}
|
|
5498
5784
|
|
|
5499
5785
|
// packages/coding-agent/src/humain/mcp-adapter/vendor/mcp-auth-flow.ts
|
|
5500
5786
|
init_types();
|
|
@@ -5508,7 +5794,7 @@ function throwIfAborted(signal) {
|
|
|
5508
5794
|
async function abortable(promise, signal) {
|
|
5509
5795
|
if (!signal) return promise;
|
|
5510
5796
|
throwIfAborted(signal);
|
|
5511
|
-
return await new Promise((
|
|
5797
|
+
return await new Promise((resolve7, reject) => {
|
|
5512
5798
|
let settled = false;
|
|
5513
5799
|
const cleanup = () => signal.removeEventListener("abort", onAbort);
|
|
5514
5800
|
const onAbort = () => {
|
|
@@ -5523,7 +5809,7 @@ async function abortable(promise, signal) {
|
|
|
5523
5809
|
if (settled) return;
|
|
5524
5810
|
settled = true;
|
|
5525
5811
|
cleanup();
|
|
5526
|
-
|
|
5812
|
+
resolve7(value);
|
|
5527
5813
|
},
|
|
5528
5814
|
(error) => {
|
|
5529
5815
|
if (settled) return;
|
|
@@ -5867,7 +6153,7 @@ async function startAuth(serverName, serverUrl, definition, options = {}) {
|
|
|
5867
6153
|
} catch (error) {
|
|
5868
6154
|
releaseCallbackServer(oauthState);
|
|
5869
6155
|
try {
|
|
5870
|
-
await clearOAuthState(serverName, authStorageOptions);
|
|
6156
|
+
await cleanupAndReleaseCallbackServerIfIdle(() => clearOAuthState(serverName, authStorageOptions));
|
|
5871
6157
|
} catch (cleanupError) {
|
|
5872
6158
|
throw new AggregateError([error, cleanupError], "OAuth startup cleanup failed");
|
|
5873
6159
|
}
|
|
@@ -5905,6 +6191,7 @@ async function startAuth(serverName, serverUrl, definition, options = {}) {
|
|
|
5905
6191
|
authProvider.deactivate();
|
|
5906
6192
|
releaseCallbackServer(oauthState);
|
|
5907
6193
|
await clearOAuthState(serverName, authStorageOptions);
|
|
6194
|
+
await stopCallbackServerIfIdle();
|
|
5908
6195
|
return { authorizationUrl: "" };
|
|
5909
6196
|
}
|
|
5910
6197
|
if (!capturedUrl) {
|
|
@@ -5915,7 +6202,7 @@ async function startAuth(serverName, serverUrl, definition, options = {}) {
|
|
|
5915
6202
|
} catch (error) {
|
|
5916
6203
|
authProvider.deactivate();
|
|
5917
6204
|
try {
|
|
5918
|
-
await
|
|
6205
|
+
await clearPendingAuthAndReleaseIfIdle(runtime, serverName, oauthState, authStorageOptions);
|
|
5919
6206
|
} catch (cleanupError) {
|
|
5920
6207
|
throw new AggregateError([error, cleanupError], "OAuth startup cleanup failed");
|
|
5921
6208
|
}
|
|
@@ -5931,7 +6218,7 @@ async function setPendingAuth(runtime, serverName, pendingAuth, oauthState, sign
|
|
|
5931
6218
|
state.pendingAuths.set(key, pendingAuth);
|
|
5932
6219
|
state.pendingAuthStates.set(key, oauthState);
|
|
5933
6220
|
const cleanupTimer = setTimeout(() => {
|
|
5934
|
-
void
|
|
6221
|
+
void clearPendingAuthAndReleaseIfIdle(runtime, serverName, oauthState, pendingAuth.authStorageOptions).catch((error) => {
|
|
5935
6222
|
console.error(`MCP Auth: Timed-out flow cleanup failed: ${formatTerminalError(error)}`);
|
|
5936
6223
|
});
|
|
5937
6224
|
}, MANUAL_AUTH_TIMEOUT_MS);
|
|
@@ -5962,6 +6249,28 @@ async function clearPendingAuth(runtime, serverName, oauthState, fallbackStorage
|
|
|
5962
6249
|
}
|
|
5963
6250
|
}
|
|
5964
6251
|
}
|
|
6252
|
+
async function clearPendingAuthAndReleaseIfIdle(runtime, serverName, oauthState, fallbackStorageOptions = {}) {
|
|
6253
|
+
await cleanupAndReleaseCallbackServerIfIdle(
|
|
6254
|
+
() => clearPendingAuth(runtime, serverName, oauthState, fallbackStorageOptions)
|
|
6255
|
+
);
|
|
6256
|
+
}
|
|
6257
|
+
async function cleanupAndReleaseCallbackServerIfIdle(cleanup) {
|
|
6258
|
+
let cleanupFailure;
|
|
6259
|
+
try {
|
|
6260
|
+
await cleanup();
|
|
6261
|
+
} catch (error) {
|
|
6262
|
+
cleanupFailure = { error };
|
|
6263
|
+
}
|
|
6264
|
+
try {
|
|
6265
|
+
await stopCallbackServerIfIdle();
|
|
6266
|
+
} catch (releaseError) {
|
|
6267
|
+
if (cleanupFailure) {
|
|
6268
|
+
throw new AggregateError([cleanupFailure.error, releaseError], "OAuth callback cleanup failed");
|
|
6269
|
+
}
|
|
6270
|
+
throw releaseError;
|
|
6271
|
+
}
|
|
6272
|
+
if (cleanupFailure) throw cleanupFailure.error;
|
|
6273
|
+
}
|
|
5965
6274
|
function getSearchParamsFromInput(input) {
|
|
5966
6275
|
try {
|
|
5967
6276
|
const url = new URL(input);
|
|
@@ -6099,7 +6408,7 @@ async function completeAuth(serverName, authorizationCode, options = {}) {
|
|
|
6099
6408
|
} finally {
|
|
6100
6409
|
if (!keepPendingForRetry) {
|
|
6101
6410
|
try {
|
|
6102
|
-
await
|
|
6411
|
+
await clearPendingAuthAndReleaseIfIdle(runtime, serverName, oauthState, authStorageOptions);
|
|
6103
6412
|
} catch (cleanupError) {
|
|
6104
6413
|
if (caughtError !== void 0) {
|
|
6105
6414
|
throw new AggregateError([caughtError, cleanupError], "OAuth completion cleanup failed");
|
|
@@ -6171,7 +6480,7 @@ ${authorizationUrl}`);
|
|
|
6171
6480
|
} catch (error) {
|
|
6172
6481
|
if (oauthState) cancelPendingCallback(oauthState);
|
|
6173
6482
|
try {
|
|
6174
|
-
await
|
|
6483
|
+
await clearPendingAuthAndReleaseIfIdle(runtime, serverName, oauthState, authStorageOptions);
|
|
6175
6484
|
} catch (cleanupError) {
|
|
6176
6485
|
throw new AggregateError([error, cleanupError], "OAuth cancellation cleanup failed");
|
|
6177
6486
|
}
|
|
@@ -6197,7 +6506,7 @@ async function removeAuth(serverName, options = {}) {
|
|
|
6197
6506
|
if (oauthState) {
|
|
6198
6507
|
cancelPendingCallback(oauthState);
|
|
6199
6508
|
}
|
|
6200
|
-
await
|
|
6509
|
+
await clearPendingAuthAndReleaseIfIdle(runtime, serverName, oauthState, authStorageOptions);
|
|
6201
6510
|
throwIfAborted(signal);
|
|
6202
6511
|
clearAllCredentials(serverName, authStorageOptions);
|
|
6203
6512
|
await clearOAuthState(serverName, authStorageOptions);
|
|
@@ -6230,6 +6539,87 @@ async function shutdownOAuth(runtime = legacyRuntime) {
|
|
|
6230
6539
|
|
|
6231
6540
|
// packages/coding-agent/src/humain/mcp-adapter/vendor/lifecycle.ts
|
|
6232
6541
|
init_utils();
|
|
6542
|
+
|
|
6543
|
+
// packages/coding-agent/src/humain/mcp-adapter/vendor/session-recovery.ts
|
|
6544
|
+
import { ProtocolError, SdkHttpError, UnauthorizedError as UnauthorizedError3 } from "@modelcontextprotocol/client";
|
|
6545
|
+
init_types();
|
|
6546
|
+
var CONNECTION_CLOSED_PROTOCOL_CODE = -32e3;
|
|
6547
|
+
var SERVER_NOT_INITIALIZED_MCP_MESSAGES = /* @__PURE__ */ new Set([
|
|
6548
|
+
"Server not initialized",
|
|
6549
|
+
"Bad Request: Server not initialized"
|
|
6550
|
+
]);
|
|
6551
|
+
function isTerminatedSession(err, hadSessionId) {
|
|
6552
|
+
if (!hadSessionId) return false;
|
|
6553
|
+
if (err instanceof SdkHttpError) {
|
|
6554
|
+
return err.status === 404 || err.status === 400 && /"code"\s*:\s*-32000/.test(err.message) && /"message"\s*:\s*"Bad Request: Server not initialized"/.test(err.message);
|
|
6555
|
+
}
|
|
6556
|
+
return err instanceof ProtocolError && err.code === CONNECTION_CLOSED_PROTOCOL_CODE && SERVER_NOT_INITIALIZED_MCP_MESSAGES.has(err.message);
|
|
6557
|
+
}
|
|
6558
|
+
function hasSessionId(connection) {
|
|
6559
|
+
const transport = connection.transport;
|
|
6560
|
+
return transport?.sessionId != null;
|
|
6561
|
+
}
|
|
6562
|
+
var SessionRecoveryAuthRequiredError = class extends Error {
|
|
6563
|
+
constructor(serverName, authMessage) {
|
|
6564
|
+
super(authMessage ?? `MCP server "${serverName}" requires OAuth authentication after reconnect.`);
|
|
6565
|
+
this.serverName = serverName;
|
|
6566
|
+
this.authMessage = authMessage;
|
|
6567
|
+
this.name = "SessionRecoveryAuthRequiredError";
|
|
6568
|
+
}
|
|
6569
|
+
};
|
|
6570
|
+
async function withSessionRecovery(deps, serverName, fn) {
|
|
6571
|
+
if (isServerDisabled(deps.config.mcpServers[serverName])) {
|
|
6572
|
+
throw new Error(`MCP server "${serverName}" is disabled`);
|
|
6573
|
+
}
|
|
6574
|
+
const connection = deps.manager.getConnection(serverName);
|
|
6575
|
+
if (!connection) {
|
|
6576
|
+
throw new Error(`Server "${serverName}" is not connected`);
|
|
6577
|
+
}
|
|
6578
|
+
const hadSessionId = hasSessionId(connection);
|
|
6579
|
+
try {
|
|
6580
|
+
return await fn(connection);
|
|
6581
|
+
} catch (err) {
|
|
6582
|
+
const definition = deps.config.mcpServers[serverName];
|
|
6583
|
+
if (definition && supportsOAuth(definition) && (err instanceof UnauthorizedError3 || err instanceof SdkHttpError && err.status === 401)) {
|
|
6584
|
+
invalidateAuthEntryCache(serverName);
|
|
6585
|
+
}
|
|
6586
|
+
if (!isTerminatedSession(err, hadSessionId)) {
|
|
6587
|
+
throw err;
|
|
6588
|
+
}
|
|
6589
|
+
if (!definition) {
|
|
6590
|
+
throw err;
|
|
6591
|
+
}
|
|
6592
|
+
throwIfAborted(deps.signal);
|
|
6593
|
+
logger.debug(`MCP session for "${serverName}" expired; reconnecting`, {
|
|
6594
|
+
server: serverName
|
|
6595
|
+
});
|
|
6596
|
+
let freshConnection = deps.signal ? await deps.manager.reconnect(serverName, definition, connection, deps.signal) : await deps.manager.reconnect(serverName, definition, connection);
|
|
6597
|
+
throwIfAborted(deps.signal);
|
|
6598
|
+
if (freshConnection.status === "needs-auth") {
|
|
6599
|
+
freshConnection = await deps.onNeedsAuth?.(serverName) ?? freshConnection;
|
|
6600
|
+
throwIfAborted(deps.signal);
|
|
6601
|
+
}
|
|
6602
|
+
if (freshConnection.status === "needs-auth") {
|
|
6603
|
+
throw new SessionRecoveryAuthRequiredError(serverName);
|
|
6604
|
+
}
|
|
6605
|
+
if (freshConnection.status !== "connected") {
|
|
6606
|
+
throw err;
|
|
6607
|
+
}
|
|
6608
|
+
try {
|
|
6609
|
+
deps.manager.publishMetadataChanged(serverName, freshConnection, "session-reconnect");
|
|
6610
|
+
} catch (publicationError) {
|
|
6611
|
+
const message = publicationError instanceof Error ? publicationError.message : String(publicationError);
|
|
6612
|
+
logger.debug(`MCP metadata publication after reconnect failed for "${serverName}": ${message}`);
|
|
6613
|
+
}
|
|
6614
|
+
throwIfAborted(deps.signal);
|
|
6615
|
+
return fn(freshConnection);
|
|
6616
|
+
}
|
|
6617
|
+
}
|
|
6618
|
+
|
|
6619
|
+
// packages/coding-agent/src/humain/mcp-adapter/vendor/lifecycle.ts
|
|
6620
|
+
var KEEP_ALIVE_RETRY_BASE_MS = 3e4;
|
|
6621
|
+
var KEEP_ALIVE_RETRY_MAX_MS = 5 * 6e4;
|
|
6622
|
+
var KEEP_ALIVE_CHECK_CONCURRENCY = 10;
|
|
6233
6623
|
var McpLifecycleManager = class {
|
|
6234
6624
|
constructor(manager, hasPendingAuthForServer = hasPendingAuth) {
|
|
6235
6625
|
this.manager = manager;
|
|
@@ -6238,6 +6628,8 @@ var McpLifecycleManager = class {
|
|
|
6238
6628
|
this.allServers = /* @__PURE__ */ new Map();
|
|
6239
6629
|
this.serverSettings = /* @__PURE__ */ new Map();
|
|
6240
6630
|
this.globalIdleTimeout = 10 * 60 * 1e3;
|
|
6631
|
+
this.retryStates = /* @__PURE__ */ new Map();
|
|
6632
|
+
this.pendingMetadataPublications = /* @__PURE__ */ new Set();
|
|
6241
6633
|
this.stopped = false;
|
|
6242
6634
|
}
|
|
6243
6635
|
setReconnectCallback(callback) {
|
|
@@ -6246,6 +6638,12 @@ var McpLifecycleManager = class {
|
|
|
6246
6638
|
setReconnectFailureCallback(callback) {
|
|
6247
6639
|
this.onReconnectFailure = callback;
|
|
6248
6640
|
}
|
|
6641
|
+
setHealthRestoredCallback(callback) {
|
|
6642
|
+
this.onHealthRestored = callback;
|
|
6643
|
+
}
|
|
6644
|
+
setAuthRequiredCallback(callback) {
|
|
6645
|
+
this.onAuthRequired = callback;
|
|
6646
|
+
}
|
|
6249
6647
|
markKeepAlive(name, definition) {
|
|
6250
6648
|
if (isServerDisabled(definition)) return;
|
|
6251
6649
|
this.keepAliveServers.set(name, definition);
|
|
@@ -6255,6 +6653,13 @@ var McpLifecycleManager = class {
|
|
|
6255
6653
|
this.allServers.set(name, definition);
|
|
6256
6654
|
if (settings?.idleTimeout !== void 0) this.serverSettings.set(name, settings);
|
|
6257
6655
|
}
|
|
6656
|
+
unregisterServer(name) {
|
|
6657
|
+
this.allServers.delete(name);
|
|
6658
|
+
this.keepAliveServers.delete(name);
|
|
6659
|
+
this.serverSettings.delete(name);
|
|
6660
|
+
this.retryStates.delete(name);
|
|
6661
|
+
this.pendingMetadataPublications.delete(name);
|
|
6662
|
+
}
|
|
6258
6663
|
setGlobalIdleTimeout(minutes) {
|
|
6259
6664
|
this.globalIdleTimeout = minutes * 60 * 1e3;
|
|
6260
6665
|
}
|
|
@@ -6287,29 +6692,21 @@ var McpLifecycleManager = class {
|
|
|
6287
6692
|
}, intervalMs);
|
|
6288
6693
|
this.healthCheckInterval.unref();
|
|
6289
6694
|
}
|
|
6290
|
-
async
|
|
6695
|
+
async ensureConverged(signal) {
|
|
6291
6696
|
if (this.stopped || signal?.aborted) return;
|
|
6292
|
-
|
|
6293
|
-
|
|
6294
|
-
|
|
6295
|
-
|
|
6296
|
-
|
|
6297
|
-
|
|
6298
|
-
|
|
6299
|
-
}
|
|
6300
|
-
try {
|
|
6301
|
-
await this.manager.connect(name, definition, signal);
|
|
6302
|
-
if (this.stopped || signal?.aborted) return;
|
|
6303
|
-
logger.debug(`Reconnected to ${name}`);
|
|
6304
|
-
this.onReconnect?.(name);
|
|
6305
|
-
} catch (error) {
|
|
6306
|
-
if (this.stopped || signal?.aborted) return;
|
|
6307
|
-
this.onReconnectFailure?.(name, error);
|
|
6308
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
6309
|
-
console.error(`MCP: Failed to reconnect to ${name}: ${sanitizeTerminalText(message)}`);
|
|
6310
|
-
}
|
|
6311
|
-
}
|
|
6697
|
+
if (this.activeConvergence) return this.activeConvergence;
|
|
6698
|
+
const check = this.checkKeepAliveConnections(signal);
|
|
6699
|
+
this.activeConvergence = check;
|
|
6700
|
+
try {
|
|
6701
|
+
await check;
|
|
6702
|
+
} finally {
|
|
6703
|
+
if (this.activeConvergence === check) this.activeConvergence = void 0;
|
|
6312
6704
|
}
|
|
6705
|
+
}
|
|
6706
|
+
async checkConnections(signal) {
|
|
6707
|
+
if (this.stopped || signal?.aborted) return;
|
|
6708
|
+
await this.ensureConverged(signal);
|
|
6709
|
+
if (this.stopped || signal?.aborted) return;
|
|
6313
6710
|
for (const [name] of this.allServers) {
|
|
6314
6711
|
if (this.keepAliveServers.has(name)) continue;
|
|
6315
6712
|
const timeout = this.getIdleTimeout(name);
|
|
@@ -6320,6 +6717,202 @@ var McpLifecycleManager = class {
|
|
|
6320
6717
|
}
|
|
6321
6718
|
}
|
|
6322
6719
|
}
|
|
6720
|
+
async checkKeepAliveConnections(signal) {
|
|
6721
|
+
if (this.stopped || signal?.aborted) return;
|
|
6722
|
+
await parallelLimit(
|
|
6723
|
+
[...this.keepAliveServers],
|
|
6724
|
+
KEEP_ALIVE_CHECK_CONCURRENCY,
|
|
6725
|
+
([name, definition]) => this.checkKeepAliveConnection(name, definition, signal)
|
|
6726
|
+
);
|
|
6727
|
+
}
|
|
6728
|
+
async checkKeepAliveConnection(name, definition, signal, retrySuperseded = true) {
|
|
6729
|
+
if (isServerDisabled(definition) || this.stopped || signal?.aborted) return;
|
|
6730
|
+
if (this.keepAliveServers.get(name) !== definition) return;
|
|
6731
|
+
const connection = this.manager.getConnection(name);
|
|
6732
|
+
if (connection?.status === "needs-auth") {
|
|
6733
|
+
this.pendingMetadataPublications.delete(name);
|
|
6734
|
+
return;
|
|
6735
|
+
}
|
|
6736
|
+
if (!this.shouldAttemptConnection(name, connection)) return;
|
|
6737
|
+
if (!connection || connection.status !== "connected") {
|
|
6738
|
+
if (this.hasPendingAuthForServer(name)) {
|
|
6739
|
+
logger.debug(`Skipping reconnect for ${name} while OAuth authorization is pending`);
|
|
6740
|
+
return;
|
|
6741
|
+
}
|
|
6742
|
+
let freshConnection;
|
|
6743
|
+
try {
|
|
6744
|
+
freshConnection = await this.manager.connect(name, definition, signal);
|
|
6745
|
+
} catch (error) {
|
|
6746
|
+
if (this.stopped || signal?.aborted) return;
|
|
6747
|
+
this.reportConnectionFailure(name, definition, error, "reconnect", this.manager.getConnection(name));
|
|
6748
|
+
return;
|
|
6749
|
+
}
|
|
6750
|
+
if (this.stopped || signal?.aborted) return;
|
|
6751
|
+
if (freshConnection.status === "needs-auth") {
|
|
6752
|
+
await this.notifyAuthRequired(name, definition, freshConnection);
|
|
6753
|
+
return;
|
|
6754
|
+
}
|
|
6755
|
+
if (freshConnection.status !== "connected") {
|
|
6756
|
+
this.reportConnectionFailure(
|
|
6757
|
+
name,
|
|
6758
|
+
definition,
|
|
6759
|
+
new Error(`MCP server ${name} did not return a connected session`),
|
|
6760
|
+
"reconnect",
|
|
6761
|
+
freshConnection
|
|
6762
|
+
);
|
|
6763
|
+
return;
|
|
6764
|
+
}
|
|
6765
|
+
logger.debug(`Reconnected to ${name}`);
|
|
6766
|
+
await this.publishConnectedMetadata(name, definition, freshConnection);
|
|
6767
|
+
return;
|
|
6768
|
+
}
|
|
6769
|
+
if (this.pendingMetadataPublications.has(name)) {
|
|
6770
|
+
await this.publishConnectedMetadata(name, definition, connection);
|
|
6771
|
+
return;
|
|
6772
|
+
}
|
|
6773
|
+
if (!definition.url) return;
|
|
6774
|
+
const hadSessionId = connection.transport?.sessionId != null;
|
|
6775
|
+
let refreshResult;
|
|
6776
|
+
try {
|
|
6777
|
+
refreshResult = await this.manager.refreshTools(name, connection, signal);
|
|
6778
|
+
} catch (error) {
|
|
6779
|
+
if (this.stopped || signal?.aborted) return;
|
|
6780
|
+
const current = this.manager.getConnection(name);
|
|
6781
|
+
if (current !== connection || connection.status !== "connected") {
|
|
6782
|
+
await this.handleSupersededConnection(name, definition, connection, signal, retrySuperseded);
|
|
6783
|
+
return;
|
|
6784
|
+
}
|
|
6785
|
+
if (!shouldReconnectAfterRefresh(error, hadSessionId)) {
|
|
6786
|
+
this.reportConnectionFailure(name, definition, error, "refresh", connection);
|
|
6787
|
+
return;
|
|
6788
|
+
}
|
|
6789
|
+
if (this.hasPendingAuthForServer(name)) {
|
|
6790
|
+
logger.debug(`Skipping reconnect for ${name} while OAuth authorization is pending`);
|
|
6791
|
+
return;
|
|
6792
|
+
}
|
|
6793
|
+
let freshConnection;
|
|
6794
|
+
try {
|
|
6795
|
+
freshConnection = await this.manager.reconnect(name, definition, connection, signal);
|
|
6796
|
+
} catch (reconnectError) {
|
|
6797
|
+
if (this.stopped || signal?.aborted) return;
|
|
6798
|
+
this.reportConnectionFailure(name, definition, reconnectError, "reconnect", this.manager.getConnection(name));
|
|
6799
|
+
return;
|
|
6800
|
+
}
|
|
6801
|
+
if (this.stopped || signal?.aborted) return;
|
|
6802
|
+
if (freshConnection.status === "needs-auth") {
|
|
6803
|
+
await this.notifyAuthRequired(name, definition, freshConnection);
|
|
6804
|
+
return;
|
|
6805
|
+
}
|
|
6806
|
+
if (freshConnection.status !== "connected") {
|
|
6807
|
+
this.reportConnectionFailure(
|
|
6808
|
+
name,
|
|
6809
|
+
definition,
|
|
6810
|
+
new Error(`MCP server ${name} did not return a connected session`),
|
|
6811
|
+
"reconnect",
|
|
6812
|
+
freshConnection
|
|
6813
|
+
);
|
|
6814
|
+
return;
|
|
6815
|
+
}
|
|
6816
|
+
logger.debug(`Reconnected stale MCP session for ${name}`);
|
|
6817
|
+
await this.publishConnectedMetadata(name, definition, freshConnection);
|
|
6818
|
+
return;
|
|
6819
|
+
}
|
|
6820
|
+
if (refreshResult === "superseded") {
|
|
6821
|
+
await this.handleSupersededConnection(name, definition, connection, signal, retrySuperseded);
|
|
6822
|
+
return;
|
|
6823
|
+
}
|
|
6824
|
+
if (refreshResult === "refresh-timeout") {
|
|
6825
|
+
this.deferRefreshTimeout(name, definition, connection);
|
|
6826
|
+
return;
|
|
6827
|
+
}
|
|
6828
|
+
if (this.keepAliveServers.get(name) !== definition) return;
|
|
6829
|
+
if (this.retryStates.delete(name)) {
|
|
6830
|
+
await this.onHealthRestored?.(name);
|
|
6831
|
+
}
|
|
6832
|
+
}
|
|
6833
|
+
async handleSupersededConnection(name, definition, staleConnection, signal, retrySuperseded) {
|
|
6834
|
+
const current = this.manager.getConnection(name);
|
|
6835
|
+
if (this.keepAliveServers.get(name) !== definition) return;
|
|
6836
|
+
if (current === staleConnection && current.status === "connected") {
|
|
6837
|
+
if (this.retryStates.delete(name)) await this.onHealthRestored?.(name);
|
|
6838
|
+
return;
|
|
6839
|
+
}
|
|
6840
|
+
if (current?.status === "connected") {
|
|
6841
|
+
await this.publishConnectedMetadata(name, definition, current);
|
|
6842
|
+
return;
|
|
6843
|
+
}
|
|
6844
|
+
if (current?.status === "needs-auth") {
|
|
6845
|
+
await this.notifyAuthRequired(name, definition, current);
|
|
6846
|
+
return;
|
|
6847
|
+
}
|
|
6848
|
+
if (retrySuperseded) {
|
|
6849
|
+
await this.checkKeepAliveConnection(name, definition, signal, false);
|
|
6850
|
+
}
|
|
6851
|
+
}
|
|
6852
|
+
async publishConnectedMetadata(name, definition, connection) {
|
|
6853
|
+
if (this.keepAliveServers.get(name) !== definition) {
|
|
6854
|
+
if (this.manager.getConnection(name) === connection) await this.manager.close(name);
|
|
6855
|
+
return;
|
|
6856
|
+
}
|
|
6857
|
+
this.pendingMetadataPublications.add(name);
|
|
6858
|
+
try {
|
|
6859
|
+
await this.onReconnect?.(name);
|
|
6860
|
+
this.pendingMetadataPublications.delete(name);
|
|
6861
|
+
this.retryStates.delete(name);
|
|
6862
|
+
} catch (error) {
|
|
6863
|
+
if (this.stopped) return;
|
|
6864
|
+
this.reportConnectionFailure(name, definition, error, "publish", connection);
|
|
6865
|
+
}
|
|
6866
|
+
}
|
|
6867
|
+
async notifyAuthRequired(name, definition, connection) {
|
|
6868
|
+
if (this.keepAliveServers.get(name) !== definition) {
|
|
6869
|
+
if (this.manager.getConnection(name) === connection) await this.manager.close(name);
|
|
6870
|
+
return;
|
|
6871
|
+
}
|
|
6872
|
+
this.pendingMetadataPublications.delete(name);
|
|
6873
|
+
this.retryStates.delete(name);
|
|
6874
|
+
try {
|
|
6875
|
+
await this.onAuthRequired?.(name);
|
|
6876
|
+
} catch (error) {
|
|
6877
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
6878
|
+
logger.debug(`MCP: auth-required callback failed for ${name}: ${sanitizeTerminalText(message)}`);
|
|
6879
|
+
}
|
|
6880
|
+
}
|
|
6881
|
+
shouldAttemptConnection(name, connection) {
|
|
6882
|
+
const retry = this.retryStates.get(name);
|
|
6883
|
+
if (!retry) return true;
|
|
6884
|
+
if (retry.connection !== connection || retry.status !== connection?.status) {
|
|
6885
|
+
this.retryStates.delete(name);
|
|
6886
|
+
return true;
|
|
6887
|
+
}
|
|
6888
|
+
return Date.now() >= retry.nextAttemptAt;
|
|
6889
|
+
}
|
|
6890
|
+
reportConnectionFailure(name, definition, error, action, connection) {
|
|
6891
|
+
if (!this.recordRetry(name, definition, connection)) return;
|
|
6892
|
+
this.onReconnectFailure?.(name, error);
|
|
6893
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
6894
|
+
const target = action === "reconnect" ? `reconnect to ${name}` : action === "publish" ? `publish metadata for ${name}` : `refresh ${name}`;
|
|
6895
|
+
console.error(`MCP: Failed to ${target}: ${sanitizeTerminalText(message)}`);
|
|
6896
|
+
}
|
|
6897
|
+
deferRefreshTimeout(name, definition, connection) {
|
|
6898
|
+
if (!this.recordRetry(name, definition, connection)) return;
|
|
6899
|
+
logger.debug(`MCP: keep-alive tools/list refresh timed out for ${name}; retrying after backoff`);
|
|
6900
|
+
}
|
|
6901
|
+
recordRetry(name, definition, connection) {
|
|
6902
|
+
if (this.keepAliveServers.get(name) !== definition) return false;
|
|
6903
|
+
const attempts = (this.retryStates.get(name)?.attempts ?? 0) + 1;
|
|
6904
|
+
const delay = Math.min(
|
|
6905
|
+
KEEP_ALIVE_RETRY_BASE_MS * 2 ** Math.min(attempts - 1, 10),
|
|
6906
|
+
KEEP_ALIVE_RETRY_MAX_MS
|
|
6907
|
+
);
|
|
6908
|
+
this.retryStates.set(name, {
|
|
6909
|
+
attempts,
|
|
6910
|
+
nextAttemptAt: Date.now() + delay,
|
|
6911
|
+
connection,
|
|
6912
|
+
status: connection?.status
|
|
6913
|
+
});
|
|
6914
|
+
return true;
|
|
6915
|
+
}
|
|
6323
6916
|
getIdleTimeout(name) {
|
|
6324
6917
|
const perServer = this.serverSettings.get(name)?.idleTimeout;
|
|
6325
6918
|
if (perServer !== void 0) return perServer * 60 * 1e3;
|
|
@@ -6338,26 +6931,39 @@ var McpLifecycleManager = class {
|
|
|
6338
6931
|
this.removeHealthAbortListener = void 0;
|
|
6339
6932
|
await this.activeHealthCheck;
|
|
6340
6933
|
this.activeHealthCheck = void 0;
|
|
6934
|
+
await this.activeConvergence;
|
|
6935
|
+
this.activeConvergence = void 0;
|
|
6341
6936
|
this.onReconnect = void 0;
|
|
6342
6937
|
this.onReconnectFailure = void 0;
|
|
6938
|
+
this.onHealthRestored = void 0;
|
|
6939
|
+
this.onAuthRequired = void 0;
|
|
6343
6940
|
this.onIdleShutdown = void 0;
|
|
6941
|
+
this.retryStates.clear();
|
|
6942
|
+
this.pendingMetadataPublications.clear();
|
|
6344
6943
|
if (typeof this.manager.closeAll === "function") {
|
|
6345
6944
|
await this.manager.closeAll();
|
|
6346
6945
|
}
|
|
6347
6946
|
}
|
|
6348
6947
|
};
|
|
6948
|
+
function shouldReconnectAfterRefresh(error, hadSessionId) {
|
|
6949
|
+
if (isTerminatedSession(error, hadSessionId)) return true;
|
|
6950
|
+
return error instanceof SdkError && (error.code === SdkErrorCode.NotConnected || error.code === SdkErrorCode.ConnectionClosed);
|
|
6951
|
+
}
|
|
6349
6952
|
|
|
6350
6953
|
// packages/coding-agent/src/humain/mcp-adapter/vendor/init.ts
|
|
6351
6954
|
init_metadata_cache();
|
|
6352
6955
|
|
|
6353
6956
|
// packages/coding-agent/src/humain/mcp-adapter/vendor/server-manager.ts
|
|
6354
6957
|
import { mkdirSync as mkdirSync4 } from "node:fs";
|
|
6958
|
+
import { isDeepStrictEqual } from "node:util";
|
|
6355
6959
|
import {
|
|
6356
6960
|
Client,
|
|
6357
|
-
|
|
6961
|
+
SdkError as SdkError2,
|
|
6962
|
+
SdkErrorCode as SdkErrorCode2,
|
|
6963
|
+
SdkHttpError as SdkHttpError2,
|
|
6358
6964
|
SSEClientTransport,
|
|
6359
6965
|
StreamableHTTPClientTransport,
|
|
6360
|
-
UnauthorizedError as
|
|
6966
|
+
UnauthorizedError as UnauthorizedError4
|
|
6361
6967
|
} from "@modelcontextprotocol/client";
|
|
6362
6968
|
import { StdioClientTransport } from "@modelcontextprotocol/client/stdio";
|
|
6363
6969
|
|
|
@@ -6373,13 +6979,13 @@ var UnixSocketClientTransport = class {
|
|
|
6373
6979
|
if (this.socket) {
|
|
6374
6980
|
throw new Error("UnixSocketClientTransport already started");
|
|
6375
6981
|
}
|
|
6376
|
-
await new Promise((
|
|
6982
|
+
await new Promise((resolve7, reject) => {
|
|
6377
6983
|
const socket = createConnection(this.socketPath);
|
|
6378
6984
|
this.socket = socket;
|
|
6379
6985
|
let connected = false;
|
|
6380
6986
|
socket.once("connect", () => {
|
|
6381
6987
|
connected = true;
|
|
6382
|
-
|
|
6988
|
+
resolve7();
|
|
6383
6989
|
});
|
|
6384
6990
|
socket.on("data", (chunk) => {
|
|
6385
6991
|
try {
|
|
@@ -6411,12 +7017,12 @@ var UnixSocketClientTransport = class {
|
|
|
6411
7017
|
this.socket = void 0;
|
|
6412
7018
|
this.readBuffer.clear();
|
|
6413
7019
|
if (!socket || socket.destroyed) return;
|
|
6414
|
-
await new Promise((
|
|
7020
|
+
await new Promise((resolve7) => {
|
|
6415
7021
|
const timeout = setTimeout(() => socket.destroy(), 2e3);
|
|
6416
7022
|
timeout.unref();
|
|
6417
7023
|
socket.once("close", () => {
|
|
6418
7024
|
clearTimeout(timeout);
|
|
6419
|
-
|
|
7025
|
+
resolve7();
|
|
6420
7026
|
});
|
|
6421
7027
|
socket.end();
|
|
6422
7028
|
});
|
|
@@ -6424,10 +7030,10 @@ var UnixSocketClientTransport = class {
|
|
|
6424
7030
|
async send(message) {
|
|
6425
7031
|
const socket = this.socket;
|
|
6426
7032
|
if (!socket || socket.destroyed) throw new Error("Unix socket is not connected");
|
|
6427
|
-
await new Promise((
|
|
7033
|
+
await new Promise((resolve7, reject) => {
|
|
6428
7034
|
socket.write(serializeMessage(message), (error) => {
|
|
6429
7035
|
if (error) reject(error);
|
|
6430
|
-
else
|
|
7036
|
+
else resolve7();
|
|
6431
7037
|
});
|
|
6432
7038
|
});
|
|
6433
7039
|
}
|
|
@@ -6578,8 +7184,8 @@ init_types();
|
|
|
6578
7184
|
|
|
6579
7185
|
// packages/coding-agent/src/humain/mcp-adapter/vendor/npx-resolver.ts
|
|
6580
7186
|
init_agent_dir();
|
|
6581
|
-
import { existsSync as
|
|
6582
|
-
import { join as
|
|
7187
|
+
import { existsSync as existsSync6, readFileSync as readFileSync7, realpathSync as realpathSync2, readdirSync, statSync as statSync3, writeFileSync as writeFileSync3, renameSync as renameSync3, mkdirSync as mkdirSync3, openSync, readSync, closeSync, unlinkSync } from "node:fs";
|
|
7188
|
+
import { join as join6, dirname as dirname4, extname as extname2, resolve as resolve5, sep as sep3 } from "node:path";
|
|
6583
7189
|
import crossSpawn from "cross-spawn";
|
|
6584
7190
|
var CACHE_VERSION2 = 2;
|
|
6585
7191
|
var CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -6592,7 +7198,7 @@ async function resolveNpxBinary(command, args, signal) {
|
|
|
6592
7198
|
const cacheKey = JSON.stringify([command, parsed.packageSpec, parsed.binName ?? ""]);
|
|
6593
7199
|
const cache = loadCache();
|
|
6594
7200
|
const cached = cache?.entries?.[cacheKey];
|
|
6595
|
-
if (cached && Date.now() - cached.resolvedAt < CACHE_TTL_MS &&
|
|
7201
|
+
if (cached && Date.now() - cached.resolvedAt < CACHE_TTL_MS && existsSync6(cached.resolvedBin) && (!packageSpec?.exactVersion || cached.packageVersion === packageSpec.exactVersion)) {
|
|
6596
7202
|
return { binPath: cached.resolvedBin, extraArgs: parsed.extraArgs, isJs: cached.isJs };
|
|
6597
7203
|
}
|
|
6598
7204
|
const resolved = resolveFromNpmCache(parsed.packageSpec, parsed.binName);
|
|
@@ -6699,11 +7305,11 @@ function resolveFromNpmCache(packageSpec, binName) {
|
|
|
6699
7305
|
const { packageName, exactVersion } = parsedSpec;
|
|
6700
7306
|
const packageDir = findCachedPackageDir(cacheDir, packageName, exactVersion);
|
|
6701
7307
|
if (!packageDir) return null;
|
|
6702
|
-
const packageJsonPath =
|
|
6703
|
-
if (!
|
|
7308
|
+
const packageJsonPath = join6(packageDir, "package.json");
|
|
7309
|
+
if (!existsSync6(packageJsonPath)) return null;
|
|
6704
7310
|
let pkg = null;
|
|
6705
7311
|
try {
|
|
6706
|
-
pkg = JSON.parse(
|
|
7312
|
+
pkg = JSON.parse(readFileSync7(packageJsonPath, "utf-8"));
|
|
6707
7313
|
} catch {
|
|
6708
7314
|
return null;
|
|
6709
7315
|
}
|
|
@@ -6733,11 +7339,11 @@ function resolveFromNpmCache(packageSpec, binName) {
|
|
|
6733
7339
|
}
|
|
6734
7340
|
if (!binRel) return null;
|
|
6735
7341
|
const nodeModulesDir = findNodeModulesDir(packageDir);
|
|
6736
|
-
const binLink = chosenBinName ?
|
|
6737
|
-
let resolvedBin = binLink &&
|
|
7342
|
+
const binLink = chosenBinName ? join6(nodeModulesDir, ".bin", chosenBinName) : null;
|
|
7343
|
+
let resolvedBin = binLink && existsSync6(binLink) ? safeRealpath(binLink) : "";
|
|
6738
7344
|
if (!resolvedBin) {
|
|
6739
|
-
resolvedBin =
|
|
6740
|
-
if (!
|
|
7345
|
+
resolvedBin = resolve5(packageDir, binRel);
|
|
7346
|
+
if (!existsSync6(resolvedBin)) return null;
|
|
6741
7347
|
}
|
|
6742
7348
|
const isJs = detectJsBinary(resolvedBin);
|
|
6743
7349
|
return {
|
|
@@ -6751,7 +7357,7 @@ var FORCE_CACHE_TIMEOUT_MS = 3e4;
|
|
|
6751
7357
|
async function forceNpxCache(packageSpec, signal) {
|
|
6752
7358
|
throwIfAborted(signal);
|
|
6753
7359
|
try {
|
|
6754
|
-
await new Promise((
|
|
7360
|
+
await new Promise((resolve7, reject) => {
|
|
6755
7361
|
const proc = crossSpawn(
|
|
6756
7362
|
"npm",
|
|
6757
7363
|
["exec", "--yes", "--package", packageSpec, "--", "node", "-e", "1"],
|
|
@@ -6770,7 +7376,7 @@ async function forceNpxCache(packageSpec, signal) {
|
|
|
6770
7376
|
proc.on("close", () => {
|
|
6771
7377
|
clearTimeout(timer);
|
|
6772
7378
|
signal?.removeEventListener("abort", abort);
|
|
6773
|
-
|
|
7379
|
+
resolve7();
|
|
6774
7380
|
});
|
|
6775
7381
|
proc.on("error", (err) => {
|
|
6776
7382
|
clearTimeout(timer);
|
|
@@ -6835,21 +7441,21 @@ function defaultBinName(packageName) {
|
|
|
6835
7441
|
return packageName;
|
|
6836
7442
|
}
|
|
6837
7443
|
function findCachedPackageDir(cacheDir, packageName, exactVersion) {
|
|
6838
|
-
const npxDir =
|
|
6839
|
-
if (!
|
|
7444
|
+
const npxDir = join6(cacheDir, "_npx");
|
|
7445
|
+
if (!existsSync6(npxDir)) return null;
|
|
6840
7446
|
const packagePathParts = packageName.startsWith("@") ? packageName.split("/") : [packageName];
|
|
6841
7447
|
const candidates = readdirSync(npxDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => {
|
|
6842
|
-
const full =
|
|
7448
|
+
const full = join6(npxDir, entry.name);
|
|
6843
7449
|
const mtime = safeStatMtime(full);
|
|
6844
7450
|
return { name: entry.name, mtime };
|
|
6845
7451
|
}).sort((a, b) => b.mtime - a.mtime);
|
|
6846
7452
|
for (const entry of candidates) {
|
|
6847
|
-
const pkgDir =
|
|
6848
|
-
const packageJsonPath =
|
|
6849
|
-
if (!
|
|
7453
|
+
const pkgDir = join6(npxDir, entry.name, "node_modules", ...packagePathParts);
|
|
7454
|
+
const packageJsonPath = join6(pkgDir, "package.json");
|
|
7455
|
+
if (!existsSync6(packageJsonPath)) continue;
|
|
6850
7456
|
if (exactVersion) {
|
|
6851
7457
|
try {
|
|
6852
|
-
const pkg = JSON.parse(
|
|
7458
|
+
const pkg = JSON.parse(readFileSync7(packageJsonPath, "utf-8"));
|
|
6853
7459
|
if (pkg.version !== exactVersion) continue;
|
|
6854
7460
|
} catch {
|
|
6855
7461
|
continue;
|
|
@@ -6860,12 +7466,12 @@ function findCachedPackageDir(cacheDir, packageName, exactVersion) {
|
|
|
6860
7466
|
return null;
|
|
6861
7467
|
}
|
|
6862
7468
|
function findNodeModulesDir(packageDir) {
|
|
6863
|
-
const parts = packageDir.split(
|
|
7469
|
+
const parts = packageDir.split(sep3);
|
|
6864
7470
|
const idx = parts.lastIndexOf("node_modules");
|
|
6865
7471
|
if (idx >= 0) {
|
|
6866
|
-
return parts.slice(0, idx + 1).join(
|
|
7472
|
+
return parts.slice(0, idx + 1).join(sep3);
|
|
6867
7473
|
}
|
|
6868
|
-
return
|
|
7474
|
+
return join6(packageDir, "..");
|
|
6869
7475
|
}
|
|
6870
7476
|
function detectJsBinary(binPath) {
|
|
6871
7477
|
const ext = extname2(binPath).toLowerCase();
|
|
@@ -6909,9 +7515,9 @@ function getNpxCachePath() {
|
|
|
6909
7515
|
return getAgentPath("mcp-npx-cache.json");
|
|
6910
7516
|
}
|
|
6911
7517
|
function readNpxCachePayload(cachePath) {
|
|
6912
|
-
if (!
|
|
7518
|
+
if (!existsSync6(cachePath)) return null;
|
|
6913
7519
|
try {
|
|
6914
|
-
return JSON.parse(
|
|
7520
|
+
return JSON.parse(readFileSync7(cachePath, "utf-8"));
|
|
6915
7521
|
} catch {
|
|
6916
7522
|
return null;
|
|
6917
7523
|
}
|
|
@@ -6985,14 +7591,14 @@ function saveCacheEntry(key, entry) {
|
|
|
6985
7591
|
}
|
|
6986
7592
|
function safeRealpath(path2) {
|
|
6987
7593
|
try {
|
|
6988
|
-
return
|
|
7594
|
+
return realpathSync2(path2);
|
|
6989
7595
|
} catch {
|
|
6990
7596
|
return "";
|
|
6991
7597
|
}
|
|
6992
7598
|
}
|
|
6993
7599
|
function safeStatMtime(path2) {
|
|
6994
7600
|
try {
|
|
6995
|
-
return
|
|
7601
|
+
return statSync3(path2).mtimeMs;
|
|
6996
7602
|
} catch {
|
|
6997
7603
|
return 0;
|
|
6998
7604
|
}
|
|
@@ -7053,6 +7659,245 @@ function createJsonSchemaValidator() {
|
|
|
7053
7659
|
};
|
|
7054
7660
|
}
|
|
7055
7661
|
|
|
7662
|
+
// packages/coding-agent/src/humain/mcp-adapter/vendor/mcp-bearer-store.ts
|
|
7663
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
7664
|
+
import { createRequire as createRequire2 } from "node:module";
|
|
7665
|
+
import { dirname as dirname5, join as join7 } from "node:path";
|
|
7666
|
+
var require3 = createRequire2(import.meta.url);
|
|
7667
|
+
var BEARER_SECRET_SERVICE = "pi-mcp-adapter.bearer";
|
|
7668
|
+
var TEST_AUTH_STORE_ENV2 = "PI_MCP_ADAPTER_TEST_AUTH_STORE";
|
|
7669
|
+
var BEARER_SECRET_VALUE_LIMIT = 1280;
|
|
7670
|
+
var KeyringEntryClass2;
|
|
7671
|
+
var memoryBearerEntries = /* @__PURE__ */ new Map();
|
|
7672
|
+
var testBearerSecretStoreReadCount = 0;
|
|
7673
|
+
var BearerCredentialStoreError = class extends Error {
|
|
7674
|
+
// No parameter properties: cli.js loads this module under plain Node
|
|
7675
|
+
// type stripping, which rejects non-erasable TypeScript syntax.
|
|
7676
|
+
constructor(message, operation, cause) {
|
|
7677
|
+
super(message, { cause });
|
|
7678
|
+
this.code = "BEARER_CREDENTIAL_STORE_UNAVAILABLE";
|
|
7679
|
+
this.name = "BearerCredentialStoreError";
|
|
7680
|
+
this.operation = operation;
|
|
7681
|
+
}
|
|
7682
|
+
};
|
|
7683
|
+
var memoryBearerSecretStore = {
|
|
7684
|
+
read(account) {
|
|
7685
|
+
testBearerSecretStoreReadCount++;
|
|
7686
|
+
return memoryBearerEntries.get(account);
|
|
7687
|
+
},
|
|
7688
|
+
write(account, payload) {
|
|
7689
|
+
memoryBearerEntries.set(account, payload);
|
|
7690
|
+
},
|
|
7691
|
+
remove(account) {
|
|
7692
|
+
memoryBearerEntries.delete(account);
|
|
7693
|
+
}
|
|
7694
|
+
};
|
|
7695
|
+
var sizeLimitedBearerSecretStore = {
|
|
7696
|
+
read(account) {
|
|
7697
|
+
testBearerSecretStoreReadCount++;
|
|
7698
|
+
return memoryBearerEntries.get(account);
|
|
7699
|
+
},
|
|
7700
|
+
write(account, payload) {
|
|
7701
|
+
if (payload.length > BEARER_SECRET_VALUE_LIMIT) {
|
|
7702
|
+
throw new Error(`Value of 'password encoded as UTF-16' is longer than the platform limit of ${BEARER_SECRET_VALUE_LIMIT * 2} chars`);
|
|
7703
|
+
}
|
|
7704
|
+
memoryBearerEntries.set(account, payload);
|
|
7705
|
+
},
|
|
7706
|
+
remove(account) {
|
|
7707
|
+
memoryBearerEntries.delete(account);
|
|
7708
|
+
}
|
|
7709
|
+
};
|
|
7710
|
+
var unavailableBearerSecretStore = {
|
|
7711
|
+
read() {
|
|
7712
|
+
testBearerSecretStoreReadCount++;
|
|
7713
|
+
throw new Error("simulated secure credential store unavailable");
|
|
7714
|
+
},
|
|
7715
|
+
write() {
|
|
7716
|
+
throw new Error("simulated secure credential store unavailable");
|
|
7717
|
+
},
|
|
7718
|
+
remove() {
|
|
7719
|
+
throw new Error("simulated secure credential store unavailable");
|
|
7720
|
+
}
|
|
7721
|
+
};
|
|
7722
|
+
var keyringBearerSecretStore = {
|
|
7723
|
+
read(account) {
|
|
7724
|
+
return getKeyringEntry2(account).getPassword() ?? void 0;
|
|
7725
|
+
},
|
|
7726
|
+
write(account, payload) {
|
|
7727
|
+
getKeyringEntry2(account).setPassword(payload);
|
|
7728
|
+
},
|
|
7729
|
+
remove(account) {
|
|
7730
|
+
getKeyringEntry2(account).deleteCredential();
|
|
7731
|
+
}
|
|
7732
|
+
};
|
|
7733
|
+
function getBearerSecretStore() {
|
|
7734
|
+
if (process.env[TEST_AUTH_STORE_ENV2] === "memory") return memoryBearerSecretStore;
|
|
7735
|
+
if (process.env[TEST_AUTH_STORE_ENV2] === "sizelimited") return sizeLimitedBearerSecretStore;
|
|
7736
|
+
if (process.env[TEST_AUTH_STORE_ENV2] === "unavailable") return unavailableBearerSecretStore;
|
|
7737
|
+
return keyringBearerSecretStore;
|
|
7738
|
+
}
|
|
7739
|
+
function getKeyringEntry2(account) {
|
|
7740
|
+
try {
|
|
7741
|
+
KeyringEntryClass2 ??= loadKeyringEntryClass2();
|
|
7742
|
+
return new KeyringEntryClass2(BEARER_SECRET_SERVICE, account);
|
|
7743
|
+
} catch (error) {
|
|
7744
|
+
throw new Error("Bearer token secure credential storage is unavailable. Configure the OS credential store and retry.", { cause: error });
|
|
7745
|
+
}
|
|
7746
|
+
}
|
|
7747
|
+
function loadKeyringEntryClass2(keyringRequire = require3, platform4 = process.platform, arch = process.arch) {
|
|
7748
|
+
try {
|
|
7749
|
+
return keyringRequire("@napi-rs/keyring").Entry;
|
|
7750
|
+
} catch (loaderError) {
|
|
7751
|
+
try {
|
|
7752
|
+
return loadKeyringNativeBindingFallback2(keyringRequire, platform4, arch).Entry;
|
|
7753
|
+
} catch (fallbackError) {
|
|
7754
|
+
const message = fallbackError instanceof Error ? fallbackError.message : String(fallbackError);
|
|
7755
|
+
throw new Error(`Failed to load @napi-rs/keyring; absolute-path native binding fallback also failed: ${message}`, { cause: loaderError });
|
|
7756
|
+
}
|
|
7757
|
+
}
|
|
7758
|
+
}
|
|
7759
|
+
function loadKeyringNativeBindingFallback2(keyringRequire, platform4, arch) {
|
|
7760
|
+
const targets = getKeyringNativeBindingSuffixes2(platform4, arch).map((suffix) => ({
|
|
7761
|
+
packageName: `@napi-rs/keyring-${suffix}`,
|
|
7762
|
+
bindingFile: `keyring.${suffix}.node`
|
|
7763
|
+
}));
|
|
7764
|
+
let lastError;
|
|
7765
|
+
for (const target of targets) {
|
|
7766
|
+
try {
|
|
7767
|
+
const packageJsonPath = keyringRequire.resolve(`${target.packageName}/package.json`);
|
|
7768
|
+
return keyringRequire(join7(dirname5(packageJsonPath), target.bindingFile));
|
|
7769
|
+
} catch (error) {
|
|
7770
|
+
lastError = error;
|
|
7771
|
+
}
|
|
7772
|
+
}
|
|
7773
|
+
throw lastError instanceof Error ? lastError : new Error(String(lastError));
|
|
7774
|
+
}
|
|
7775
|
+
function getKeyringNativeBindingSuffixes2(platform4, arch) {
|
|
7776
|
+
if (platform4 === "darwin") {
|
|
7777
|
+
if (arch === "arm64") return ["darwin-arm64"];
|
|
7778
|
+
if (arch === "x64") return ["darwin-x64"];
|
|
7779
|
+
}
|
|
7780
|
+
if (platform4 === "win32") {
|
|
7781
|
+
if (arch === "arm64") return ["win32-arm64-msvc"];
|
|
7782
|
+
if (arch === "x64") return ["win32-x64-msvc"];
|
|
7783
|
+
if (arch === "ia32") return ["win32-ia32-msvc"];
|
|
7784
|
+
}
|
|
7785
|
+
if (platform4 === "linux") {
|
|
7786
|
+
if (arch === "arm64") return ["linux-arm64-gnu", "linux-arm64-musl"];
|
|
7787
|
+
if (arch === "arm") return ["linux-arm-gnueabihf"];
|
|
7788
|
+
if (arch === "riscv64") return ["linux-riscv64-gnu"];
|
|
7789
|
+
if (arch === "x64") return ["linux-x64-gnu", "linux-x64-musl"];
|
|
7790
|
+
}
|
|
7791
|
+
if (platform4 === "freebsd" && arch === "x64") return ["freebsd-x64"];
|
|
7792
|
+
return [];
|
|
7793
|
+
}
|
|
7794
|
+
function getBearerAccount(serverName) {
|
|
7795
|
+
if (typeof serverName !== "string") {
|
|
7796
|
+
throw new Error(`Invalid MCP server name: ${JSON.stringify(serverName)}`);
|
|
7797
|
+
}
|
|
7798
|
+
return `sha256-${createHash3("sha256").update(serverName, "utf8").digest("hex")}`;
|
|
7799
|
+
}
|
|
7800
|
+
function parseBearerPayload(serverName, payload) {
|
|
7801
|
+
const parsed = parseStoredBearerJson(serverName, payload);
|
|
7802
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
7803
|
+
throw new Error(`Stored bearer token record for ${serverName} has invalid shape`);
|
|
7804
|
+
}
|
|
7805
|
+
const record = parsed;
|
|
7806
|
+
if (typeof record.token !== "string" || typeof record.serverUrl !== "string") {
|
|
7807
|
+
throw new Error(`Stored bearer token record for ${serverName} has invalid shape`);
|
|
7808
|
+
}
|
|
7809
|
+
return { token: record.token, serverUrl: record.serverUrl };
|
|
7810
|
+
}
|
|
7811
|
+
function parseStoredBearerJson(serverName, payload) {
|
|
7812
|
+
try {
|
|
7813
|
+
return JSON.parse(payload);
|
|
7814
|
+
} catch {
|
|
7815
|
+
throw new Error(`Failed to parse stored bearer token record for ${serverName}`);
|
|
7816
|
+
}
|
|
7817
|
+
}
|
|
7818
|
+
function isBearerChunkManifest(value) {
|
|
7819
|
+
if (typeof value !== "object" || value === null) return false;
|
|
7820
|
+
const manifest = value;
|
|
7821
|
+
return manifest.__piMcpAdapterBearerChunked === 1 && typeof manifest.chunkCount === "number" && Number.isInteger(manifest.chunkCount) && manifest.chunkCount > 0 && typeof manifest.chunkDigest === "string" && /^[a-f0-9]{16}$/.test(manifest.chunkDigest);
|
|
7822
|
+
}
|
|
7823
|
+
function readManifest(serverName, payload) {
|
|
7824
|
+
const parsed = parseStoredBearerJson(serverName, payload);
|
|
7825
|
+
return isBearerChunkManifest(parsed) ? parsed : void 0;
|
|
7826
|
+
}
|
|
7827
|
+
function chunkAccount(account, manifest, index) {
|
|
7828
|
+
return `${account}.chunk.${manifest.chunkDigest}.${index}`;
|
|
7829
|
+
}
|
|
7830
|
+
function chunkAccounts(account, manifest) {
|
|
7831
|
+
return Array.from({ length: manifest.chunkCount }, (_, index) => chunkAccount(account, manifest, index));
|
|
7832
|
+
}
|
|
7833
|
+
function removeChunks(store, account, manifest) {
|
|
7834
|
+
if (!manifest) return;
|
|
7835
|
+
for (const accountName of chunkAccounts(account, manifest)) store.remove(accountName);
|
|
7836
|
+
}
|
|
7837
|
+
function readBearerRecordFromStore(store, serverName) {
|
|
7838
|
+
const account = getBearerAccount(serverName);
|
|
7839
|
+
let payload;
|
|
7840
|
+
try {
|
|
7841
|
+
payload = store.read(account);
|
|
7842
|
+
} catch (error) {
|
|
7843
|
+
throw new BearerCredentialStoreError(
|
|
7844
|
+
`Failed to read bearer token for ${serverName} from the OS secure credential store`,
|
|
7845
|
+
"read",
|
|
7846
|
+
error
|
|
7847
|
+
);
|
|
7848
|
+
}
|
|
7849
|
+
if (payload === void 0) return void 0;
|
|
7850
|
+
try {
|
|
7851
|
+
const manifest = readManifest(serverName, payload);
|
|
7852
|
+
const recordPayload = manifest ? chunkAccounts(account, manifest).map((chunkName) => {
|
|
7853
|
+
const chunk = store.read(chunkName);
|
|
7854
|
+
if (chunk === void 0) throw new Error(`Missing bearer token chunk for ${serverName}`);
|
|
7855
|
+
return chunk;
|
|
7856
|
+
}).join("") : payload;
|
|
7857
|
+
return parseBearerPayload(serverName, recordPayload);
|
|
7858
|
+
} catch (error) {
|
|
7859
|
+
throw new BearerCredentialStoreError(
|
|
7860
|
+
`Failed to read bearer token for ${serverName} from the OS secure credential store`,
|
|
7861
|
+
"read",
|
|
7862
|
+
error
|
|
7863
|
+
);
|
|
7864
|
+
}
|
|
7865
|
+
}
|
|
7866
|
+
function removeBearerRecordFromStore(store, serverName) {
|
|
7867
|
+
const account = getBearerAccount(serverName);
|
|
7868
|
+
try {
|
|
7869
|
+
const payload = store.read(account);
|
|
7870
|
+
const manifest = payload === void 0 ? void 0 : readManifest(serverName, payload);
|
|
7871
|
+
removeChunks(store, account, manifest);
|
|
7872
|
+
store.remove(account);
|
|
7873
|
+
} catch (error) {
|
|
7874
|
+
throw new BearerCredentialStoreError(
|
|
7875
|
+
`Failed to remove bearer token for ${serverName} from the OS secure credential store`,
|
|
7876
|
+
"remove",
|
|
7877
|
+
error
|
|
7878
|
+
);
|
|
7879
|
+
}
|
|
7880
|
+
}
|
|
7881
|
+
function getBearerTokenForUrl(serverName, serverUrl) {
|
|
7882
|
+
const record = readBearerRecordFromStore(getBearerSecretStore(), serverName);
|
|
7883
|
+
if (!record) return void 0;
|
|
7884
|
+
return record.serverUrl === serverUrl ? record.token : void 0;
|
|
7885
|
+
}
|
|
7886
|
+
function removeBearerToken(serverName) {
|
|
7887
|
+
removeBearerRecordFromStore(getBearerSecretStore(), serverName);
|
|
7888
|
+
}
|
|
7889
|
+
function inspectBearerTokenForUrl(serverName, serverUrl) {
|
|
7890
|
+
try {
|
|
7891
|
+
const record = readBearerRecordFromStore(getBearerSecretStore(), serverName);
|
|
7892
|
+
if (!record) return { status: "missing" };
|
|
7893
|
+
if (record.serverUrl !== serverUrl) return { status: "url-mismatch" };
|
|
7894
|
+
return { status: "present" };
|
|
7895
|
+
} catch (error) {
|
|
7896
|
+
if (!(error instanceof BearerCredentialStoreError)) throw error;
|
|
7897
|
+
return { status: "unavailable", message: "Bearer token secure credential store unavailable. Configure or unlock the OS credential store and retry." };
|
|
7898
|
+
}
|
|
7899
|
+
}
|
|
7900
|
+
|
|
7056
7901
|
// packages/coding-agent/src/humain/mcp-adapter/vendor/sampling-handler.ts
|
|
7057
7902
|
init_utils();
|
|
7058
7903
|
import { complete } from "@earendil-works/pi-ai/compat";
|
|
@@ -7272,7 +8117,7 @@ function zeroUsage() {
|
|
|
7272
8117
|
|
|
7273
8118
|
// packages/coding-agent/src/humain/mcp-adapter/vendor/elicitation-handler.ts
|
|
7274
8119
|
import {
|
|
7275
|
-
ProtocolError,
|
|
8120
|
+
ProtocolError as ProtocolError2,
|
|
7276
8121
|
ProtocolErrorCode
|
|
7277
8122
|
} from "@modelcontextprotocol/client";
|
|
7278
8123
|
import { AjvJsonSchemaValidator as AjvJsonSchemaValidator2 } from "@modelcontextprotocol/client/validators/ajv";
|
|
@@ -7501,15 +8346,15 @@ function formatReview(serverName, properties, content) {
|
|
|
7501
8346
|
return [`Review input for ${serverName}`, "", ...rows].join("\n");
|
|
7502
8347
|
}
|
|
7503
8348
|
async function handleUrlElicitation(options, params) {
|
|
7504
|
-
if (!options.allowUrl) throw new
|
|
8349
|
+
if (!options.allowUrl) throw new ProtocolError2(ProtocolErrorCode.InvalidParams, "URL elicitation is not supported");
|
|
7505
8350
|
let parsed;
|
|
7506
8351
|
try {
|
|
7507
8352
|
parsed = new URL(params.url);
|
|
7508
8353
|
} catch {
|
|
7509
|
-
throw new
|
|
8354
|
+
throw new ProtocolError2(ProtocolErrorCode.InvalidParams, "URL elicitation supplied an invalid URL");
|
|
7510
8355
|
}
|
|
7511
8356
|
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
7512
|
-
throw new
|
|
8357
|
+
throw new ProtocolError2(ProtocolErrorCode.InvalidParams, "URL elicitation only supports HTTP and HTTPS URLs");
|
|
7513
8358
|
}
|
|
7514
8359
|
const decision = await options.ui.select([
|
|
7515
8360
|
"MCP Browser Request",
|
|
@@ -7544,7 +8389,7 @@ init_utils();
|
|
|
7544
8389
|
// packages/coding-agent/src/humain/mcp-adapter/vendor/mcp-trace.ts
|
|
7545
8390
|
import { appendFile, mkdir, writeFile } from "node:fs/promises";
|
|
7546
8391
|
import { Buffer as Buffer2 } from "node:buffer";
|
|
7547
|
-
import { dirname as
|
|
8392
|
+
import { dirname as dirname6, isAbsolute as isAbsolute4, resolve as resolve6 } from "node:path";
|
|
7548
8393
|
var MCP_TRACE_SCHEMA_VERSION = 1;
|
|
7549
8394
|
var DEFAULT_MCP_TRACE_MAX_BYTES = 256 * 1024;
|
|
7550
8395
|
var DEFAULT_MCP_TRACE_MAX_EVENTS = 1e4;
|
|
@@ -7622,7 +8467,7 @@ var McpTraceWriter = class {
|
|
|
7622
8467
|
await mkdir(path2, { recursive: true });
|
|
7623
8468
|
return void 0;
|
|
7624
8469
|
});
|
|
7625
|
-
this.fileReady = this.makeDirectory(
|
|
8470
|
+
this.fileReady = this.makeDirectory(dirname6(this.options.filePath), { recursive: true }).then(() => this.resetFile(this.options.filePath, "", { encoding: "utf8" })).catch(() => {
|
|
7626
8471
|
this.initializationFailed = true;
|
|
7627
8472
|
this.disabled = true;
|
|
7628
8473
|
});
|
|
@@ -7669,7 +8514,7 @@ var McpTraceWriter = class {
|
|
|
7669
8514
|
function createMcpTraceWriter(sessionCwd, settings = {}, randomSuffix = Math.random().toString(36).slice(2, 10)) {
|
|
7670
8515
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
7671
8516
|
const configuredPath = settings.file;
|
|
7672
|
-
const filePath = configuredPath ?
|
|
8517
|
+
const filePath = configuredPath ? isAbsolute4(configuredPath) ? configuredPath : resolve6(sessionCwd ?? process.cwd(), configuredPath) : resolve6(sessionCwd ?? process.cwd(), ".pi", "mcp-traces", `mcp-${timestamp}-${randomSuffix}.jsonl`);
|
|
7673
8518
|
return new McpTraceWriter({
|
|
7674
8519
|
filePath,
|
|
7675
8520
|
...settings.maxBytes !== void 0 ? { maxBytes: settings.maxBytes } : {},
|
|
@@ -7745,56 +8590,50 @@ var DEFAULT_TIMEOUT_MS = 1e4;
|
|
|
7745
8590
|
var MAX_OUTPUT_BYTES = 64 * 1024;
|
|
7746
8591
|
var USE_PROCESS_GROUP = process.platform !== "win32";
|
|
7747
8592
|
var CLEANUP_TOKEN_ENV = "PI_MCP_REQUEST_HEADERS_CLEANUP_TOKEN";
|
|
8593
|
+
var PS_MAX_BUFFER_BYTES = 8 * 1024 * 1024;
|
|
7748
8594
|
function isNoSuchProcessError(error) {
|
|
7749
8595
|
return typeof error === "object" && error !== null && "code" in error && error.code === "ESRCH";
|
|
7750
8596
|
}
|
|
7751
8597
|
function runPosixPs(args) {
|
|
7752
|
-
if (process.env.PI_MCP_ADAPTER_TEST_FAIL_PS === "1") return { status: 1, stdout: "" };
|
|
7753
|
-
|
|
8598
|
+
if (process.env.PI_MCP_ADAPTER_TEST_FAIL_PS === "1") return { status: 1, signal: null, stdout: "" };
|
|
8599
|
+
const result = spawnSync3("ps", args, { encoding: "utf8", maxBuffer: PS_MAX_BUFFER_BYTES });
|
|
8600
|
+
return { status: result.status, signal: result.signal, stdout: result.stdout };
|
|
8601
|
+
}
|
|
8602
|
+
function psFailureReason(result) {
|
|
8603
|
+
return result.status === null ? `ps was killed by signal ${result.signal ?? "unknown"}` : `ps exited with code ${result.status}`;
|
|
7754
8604
|
}
|
|
7755
|
-
function
|
|
7756
|
-
const result = runPosixPs(["-
|
|
8605
|
+
function collectPosixProcessPids(rootPid, cleanupToken) {
|
|
8606
|
+
const result = runPosixPs(["axeww", "-o", "pid=,ppid=,command="]);
|
|
7757
8607
|
if (result.status !== 0) {
|
|
7758
|
-
throw new Error(`HTTP request headers command cleanup failed:
|
|
8608
|
+
throw new Error(`HTTP request headers command cleanup failed: ${psFailureReason(result)}`);
|
|
7759
8609
|
}
|
|
7760
8610
|
const childrenByParent = /* @__PURE__ */ new Map();
|
|
8611
|
+
const processPids = /* @__PURE__ */ new Set();
|
|
8612
|
+
const needle = cleanupToken ? `${CLEANUP_TOKEN_ENV}=${cleanupToken}` : void 0;
|
|
7761
8613
|
for (const line of result.stdout.split("\n")) {
|
|
7762
|
-
const
|
|
7763
|
-
|
|
7764
|
-
const
|
|
8614
|
+
const match = /^\s*(\d+)\s+(\d+)(?:\s+(.*))?$/.exec(line);
|
|
8615
|
+
if (!match) continue;
|
|
8616
|
+
const pid = Number(match[1]);
|
|
8617
|
+
const ppid = Number(match[2]);
|
|
7765
8618
|
if (!Number.isInteger(pid) || !Number.isInteger(ppid)) continue;
|
|
7766
8619
|
const children = childrenByParent.get(ppid);
|
|
7767
8620
|
if (children) children.push(pid);
|
|
7768
8621
|
else childrenByParent.set(ppid, [pid]);
|
|
8622
|
+
if (needle && pid !== process.pid && match[3]?.includes(needle)) processPids.add(pid);
|
|
7769
8623
|
}
|
|
7770
|
-
const descendants = [];
|
|
7771
8624
|
const stack = [...childrenByParent.get(rootPid) ?? []];
|
|
7772
8625
|
while (stack.length > 0) {
|
|
7773
8626
|
const pid = stack.pop();
|
|
7774
|
-
|
|
8627
|
+
processPids.add(pid);
|
|
7775
8628
|
stack.push(...childrenByParent.get(pid) ?? []);
|
|
7776
8629
|
}
|
|
7777
|
-
return
|
|
8630
|
+
return [...processPids];
|
|
7778
8631
|
}
|
|
7779
|
-
function
|
|
7780
|
-
const result = runPosixPs(["axeww", "-o", "pid=,command="]);
|
|
8632
|
+
function assertPosixProcessDiscoveryAvailable() {
|
|
8633
|
+
const result = runPosixPs(["axeww", "-o", "pid=,ppid=,command="]);
|
|
7781
8634
|
if (result.status !== 0) {
|
|
7782
|
-
throw new Error(`HTTP request headers command cleanup failed:
|
|
7783
|
-
}
|
|
7784
|
-
const needle = `${CLEANUP_TOKEN_ENV}=${cleanupToken}`;
|
|
7785
|
-
const pids = [];
|
|
7786
|
-
for (const line of result.stdout.split("\n")) {
|
|
7787
|
-
const trimmed = line.trim();
|
|
7788
|
-
if (!trimmed.includes(needle)) continue;
|
|
7789
|
-
const [pidText] = trimmed.split(/\s+/, 1);
|
|
7790
|
-
const pid = Number(pidText);
|
|
7791
|
-
if (Number.isInteger(pid) && pid !== process.pid) pids.push(pid);
|
|
8635
|
+
throw new Error(`HTTP request headers command cleanup failed: ${psFailureReason(result)}`);
|
|
7792
8636
|
}
|
|
7793
|
-
return pids;
|
|
7794
|
-
}
|
|
7795
|
-
function assertPosixProcessDiscoveryAvailable() {
|
|
7796
|
-
collectPosixDescendantPids(process.pid);
|
|
7797
|
-
collectPosixCleanupTokenPids(`${process.pid}-preflight`);
|
|
7798
8637
|
}
|
|
7799
8638
|
function isTaskkillNoSuchProcess(result) {
|
|
7800
8639
|
return `${result.stdout ?? ""}
|
|
@@ -7834,10 +8673,7 @@ function killRequestHeadersCommand(child, trackedPosixDescendantPids = /* @__PUR
|
|
|
7834
8673
|
}
|
|
7835
8674
|
let stablePasses = 0;
|
|
7836
8675
|
for (let pass = 0; pass < 16; pass++) {
|
|
7837
|
-
const candidates =
|
|
7838
|
-
...collectPosixDescendantPids(child.pid),
|
|
7839
|
-
...cleanupToken ? collectPosixCleanupTokenPids(cleanupToken) : []
|
|
7840
|
-
];
|
|
8676
|
+
const candidates = collectPosixProcessPids(child.pid, cleanupToken);
|
|
7841
8677
|
const newPids = candidates.filter((pid) => !frozenPids.has(pid));
|
|
7842
8678
|
if (newPids.length === 0) {
|
|
7843
8679
|
stablePasses++;
|
|
@@ -7894,7 +8730,7 @@ function resolvedCommand(config) {
|
|
|
7894
8730
|
async function invokeRequestHeadersCommand(config, envelope, signal) {
|
|
7895
8731
|
const resolved = resolvedCommand(config);
|
|
7896
8732
|
if (USE_PROCESS_GROUP) assertPosixProcessDiscoveryAvailable();
|
|
7897
|
-
return new Promise((
|
|
8733
|
+
return new Promise((resolve7, reject) => {
|
|
7898
8734
|
let stdout = Buffer.alloc(0);
|
|
7899
8735
|
let settled = false;
|
|
7900
8736
|
const cleanupToken = randomUUID();
|
|
@@ -7909,8 +8745,7 @@ async function invokeRequestHeadersCommand(config, envelope, signal) {
|
|
|
7909
8745
|
const trackPosixDescendants = () => {
|
|
7910
8746
|
if (!USE_PROCESS_GROUP || child.pid === void 0 || settled || trackingError) return;
|
|
7911
8747
|
try {
|
|
7912
|
-
for (const pid of
|
|
7913
|
-
for (const pid of collectPosixCleanupTokenPids(cleanupToken)) trackedPosixDescendantPids.add(pid);
|
|
8748
|
+
for (const pid of collectPosixProcessPids(child.pid, cleanupToken)) trackedPosixDescendantPids.add(pid);
|
|
7914
8749
|
} catch (error) {
|
|
7915
8750
|
trackingError = error instanceof Error ? error : new Error(String(error));
|
|
7916
8751
|
}
|
|
@@ -7924,7 +8759,7 @@ async function invokeRequestHeadersCommand(config, envelope, signal) {
|
|
|
7924
8759
|
if (descendantTracker) clearInterval(descendantTracker);
|
|
7925
8760
|
signal.removeEventListener("abort", abort);
|
|
7926
8761
|
if (result.status === "error") reject(result.error);
|
|
7927
|
-
else
|
|
8762
|
+
else resolve7(result.headers);
|
|
7928
8763
|
};
|
|
7929
8764
|
const finishAfterKill = (result) => {
|
|
7930
8765
|
try {
|
|
@@ -8028,11 +8863,11 @@ var MAX_CAPTURED_STDERR_BYTES = 8 * 1024;
|
|
|
8028
8863
|
var MAX_CAPTURED_STDERR_LINES = 3;
|
|
8029
8864
|
var abortCleanupPromises = /* @__PURE__ */ new WeakMap();
|
|
8030
8865
|
function isUnauthorizedHttpError(error) {
|
|
8031
|
-
return error instanceof
|
|
8866
|
+
return error instanceof UnauthorizedError4 || error instanceof SdkHttpError2 && error.status === 401;
|
|
8032
8867
|
}
|
|
8033
8868
|
function shouldFallbackToSse(error, definition) {
|
|
8034
8869
|
if (definition.protocolVersion === "2026-07-28") return false;
|
|
8035
|
-
return error instanceof
|
|
8870
|
+
return error instanceof SdkHttpError2 && [404, 405, 406, 415].includes(error.status);
|
|
8036
8871
|
}
|
|
8037
8872
|
function resolveVersionNegotiation(definition) {
|
|
8038
8873
|
switch (definition.protocolVersion) {
|
|
@@ -8063,6 +8898,7 @@ function appendStderrTail(tail, chunk) {
|
|
|
8063
8898
|
const combined = Buffer.concat([tail, bytes]);
|
|
8064
8899
|
return combined.length > MAX_CAPTURED_STDERR_BYTES ? Buffer.from(combined.subarray(combined.length - MAX_CAPTURED_STDERR_BYTES)) : combined;
|
|
8065
8900
|
}
|
|
8901
|
+
var KEEP_ALIVE_REFRESH_TIMEOUT_MS = 5e3;
|
|
8066
8902
|
var McpServerManager = class {
|
|
8067
8903
|
/** Default cwd for stdio servers without an explicit config `cwd`. */
|
|
8068
8904
|
constructor(defaultCwd) {
|
|
@@ -8071,6 +8907,7 @@ var McpServerManager = class {
|
|
|
8071
8907
|
this.connectPromises = /* @__PURE__ */ new Map();
|
|
8072
8908
|
this.reconnectPromises = /* @__PURE__ */ new Map();
|
|
8073
8909
|
this.uiStreamListeners = /* @__PURE__ */ new Map();
|
|
8910
|
+
this.pendingMetadataPublications = /* @__PURE__ */ new Map();
|
|
8074
8911
|
this.authStorageOptions = {};
|
|
8075
8912
|
this.acceptedUrlElicitations = /* @__PURE__ */ new Map();
|
|
8076
8913
|
this.closePromises = /* @__PURE__ */ new Map();
|
|
@@ -8084,6 +8921,20 @@ var McpServerManager = class {
|
|
|
8084
8921
|
setMetadataListChangedListener(listener) {
|
|
8085
8922
|
this.metadataListChangedListener = listener;
|
|
8086
8923
|
}
|
|
8924
|
+
publishMetadataChanged(name, expectedConnection, reason) {
|
|
8925
|
+
const current = this.connections.get(name);
|
|
8926
|
+
if (current !== expectedConnection || current.status !== "connected") return false;
|
|
8927
|
+
try {
|
|
8928
|
+
this.metadataListChangedListener?.(name, reason);
|
|
8929
|
+
this.pendingMetadataPublications.delete(name);
|
|
8930
|
+
return true;
|
|
8931
|
+
} catch (error) {
|
|
8932
|
+
this.pendingMetadataPublications.set(name, { connection: expectedConnection, reason });
|
|
8933
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
8934
|
+
logger.debug(`MCP: metadata publication failed for ${name}; queued for retry: ${message}`);
|
|
8935
|
+
return false;
|
|
8936
|
+
}
|
|
8937
|
+
}
|
|
8087
8938
|
setElicitationConfig(config) {
|
|
8088
8939
|
this.elicitationConfig = config;
|
|
8089
8940
|
}
|
|
@@ -8189,6 +9040,88 @@ var McpServerManager = class {
|
|
|
8189
9040
|
this.reconnectPromises.set(name, promise);
|
|
8190
9041
|
return abortable(promise, ownedSignal);
|
|
8191
9042
|
}
|
|
9043
|
+
/**
|
|
9044
|
+
* Fetch the authoritative tool catalog for a connection that still appears
|
|
9045
|
+
* connected. The SDK response cache is explicitly bypassed so this request
|
|
9046
|
+
* also proves the remote Streamable HTTP session is usable. Results are
|
|
9047
|
+
* identity-guarded: a late response from a replaced connection is ignored.
|
|
9048
|
+
*/
|
|
9049
|
+
async refreshTools(name, expectedConnection, signal) {
|
|
9050
|
+
if (this.stopped) throw new Error("MCP server manager is closed");
|
|
9051
|
+
const ownedSignal = combineAbortSignals(this.runtimeSignal, signal);
|
|
9052
|
+
throwIfAborted(ownedSignal);
|
|
9053
|
+
const current = this.connections.get(name);
|
|
9054
|
+
if (current !== expectedConnection || current.status !== "connected") {
|
|
9055
|
+
return "superseded";
|
|
9056
|
+
}
|
|
9057
|
+
const requestOptions = this.buildRequestOptions(expectedConnection.definition, signal);
|
|
9058
|
+
const timeout = Math.min(requestOptions?.timeout ?? KEEP_ALIVE_REFRESH_TIMEOUT_MS, KEEP_ALIVE_REFRESH_TIMEOUT_MS);
|
|
9059
|
+
const healthOptions = {
|
|
9060
|
+
...requestOptions,
|
|
9061
|
+
timeout
|
|
9062
|
+
};
|
|
9063
|
+
if (!expectedConnection.client.getServerCapabilities?.()?.tools) {
|
|
9064
|
+
await expectedConnection.client.ping(healthOptions);
|
|
9065
|
+
throwIfAborted(ownedSignal);
|
|
9066
|
+
if (this.connections.get(name) !== expectedConnection || expectedConnection.status !== "connected") {
|
|
9067
|
+
return "superseded";
|
|
9068
|
+
}
|
|
9069
|
+
this.retryPendingMetadataPublication(name, expectedConnection);
|
|
9070
|
+
return "unchanged";
|
|
9071
|
+
}
|
|
9072
|
+
const toolsRevision = expectedConnection.toolsRevision ?? 0;
|
|
9073
|
+
const refreshSignal = combineAbortSignals(healthOptions.signal, AbortSignal.timeout(timeout));
|
|
9074
|
+
let tools;
|
|
9075
|
+
try {
|
|
9076
|
+
tools = await this.fetchAllTools(expectedConnection.client, {
|
|
9077
|
+
...healthOptions,
|
|
9078
|
+
...refreshSignal ? { signal: refreshSignal } : {},
|
|
9079
|
+
cacheMode: "refresh"
|
|
9080
|
+
});
|
|
9081
|
+
} catch (error) {
|
|
9082
|
+
throwIfAborted(ownedSignal);
|
|
9083
|
+
if (this.connections.get(name) !== expectedConnection || expectedConnection.status !== "connected") {
|
|
9084
|
+
return "superseded";
|
|
9085
|
+
}
|
|
9086
|
+
if (error instanceof SdkError2 && error.code === SdkErrorCode2.RequestTimeout) {
|
|
9087
|
+
return "refresh-timeout";
|
|
9088
|
+
}
|
|
9089
|
+
throw error;
|
|
9090
|
+
}
|
|
9091
|
+
throwIfAborted(ownedSignal);
|
|
9092
|
+
if (this.connections.get(name) !== expectedConnection || expectedConnection.status !== "connected") {
|
|
9093
|
+
return "superseded";
|
|
9094
|
+
}
|
|
9095
|
+
if ((expectedConnection.toolsRevision ?? 0) !== toolsRevision) {
|
|
9096
|
+
return "superseded";
|
|
9097
|
+
}
|
|
9098
|
+
if (isDeepStrictEqual(expectedConnection.tools, tools)) {
|
|
9099
|
+
this.retryPendingMetadataPublication(name, expectedConnection);
|
|
9100
|
+
return "unchanged";
|
|
9101
|
+
}
|
|
9102
|
+
const previousTools = expectedConnection.tools;
|
|
9103
|
+
expectedConnection.tools = tools;
|
|
9104
|
+
expectedConnection.toolsRevision = toolsRevision + 1;
|
|
9105
|
+
try {
|
|
9106
|
+
await this.metadataListChangedListener?.(name, "keep-alive-refresh");
|
|
9107
|
+
this.pendingMetadataPublications.delete(name);
|
|
9108
|
+
} catch (error) {
|
|
9109
|
+
if (this.connections.get(name) === expectedConnection && expectedConnection.tools === tools) {
|
|
9110
|
+
expectedConnection.tools = previousTools;
|
|
9111
|
+
expectedConnection.toolsRevision = toolsRevision;
|
|
9112
|
+
}
|
|
9113
|
+
throw error;
|
|
9114
|
+
}
|
|
9115
|
+
return "updated";
|
|
9116
|
+
}
|
|
9117
|
+
retryPendingMetadataPublication(name, connection) {
|
|
9118
|
+
const pendingPublication = this.pendingMetadataPublications.get(name);
|
|
9119
|
+
if (pendingPublication?.connection !== connection) return;
|
|
9120
|
+
this.metadataListChangedListener?.(name, pendingPublication.reason);
|
|
9121
|
+
if (this.pendingMetadataPublications.get(name) === pendingPublication) {
|
|
9122
|
+
this.pendingMetadataPublications.delete(name);
|
|
9123
|
+
}
|
|
9124
|
+
}
|
|
8192
9125
|
async doReconnect(name, definition, staleConnection, signal) {
|
|
8193
9126
|
throwIfAborted(signal);
|
|
8194
9127
|
const current = this.connections.get(name);
|
|
@@ -8293,6 +9226,7 @@ var McpServerManager = class {
|
|
|
8293
9226
|
transport,
|
|
8294
9227
|
definition,
|
|
8295
9228
|
tools: [],
|
|
9229
|
+
toolsRevision: 0,
|
|
8296
9230
|
resources: [],
|
|
8297
9231
|
prompts: [],
|
|
8298
9232
|
...instructions !== void 0 ? { instructions } : {},
|
|
@@ -8461,7 +9395,9 @@ var McpServerManager = class {
|
|
|
8461
9395
|
const connection = this.connections.get(serverName);
|
|
8462
9396
|
if (!connection || connection.client !== client || connection.status !== "connected") return;
|
|
8463
9397
|
connection.tools = tools;
|
|
9398
|
+
connection.toolsRevision = (connection.toolsRevision ?? 0) + 1;
|
|
8464
9399
|
this.metadataListChangedListener?.(serverName, "tools-list-changed");
|
|
9400
|
+
this.pendingMetadataPublications.delete(serverName);
|
|
8465
9401
|
}
|
|
8466
9402
|
handlePromptsListChanged(serverName, client, error, prompts) {
|
|
8467
9403
|
if (error) {
|
|
@@ -8474,6 +9410,7 @@ var McpServerManager = class {
|
|
|
8474
9410
|
connection.prompts = prompts;
|
|
8475
9411
|
connection.promptDiscoveryFailed = false;
|
|
8476
9412
|
this.metadataListChangedListener?.(serverName, "prompts-list-changed");
|
|
9413
|
+
this.pendingMetadataPublications.delete(serverName);
|
|
8477
9414
|
}
|
|
8478
9415
|
handleResourcesListChanged(serverName, client, error, resources) {
|
|
8479
9416
|
if (error) {
|
|
@@ -8485,6 +9422,7 @@ var McpServerManager = class {
|
|
|
8485
9422
|
if (!connection || connection.client !== client || connection.status !== "connected") return;
|
|
8486
9423
|
connection.resources = resources;
|
|
8487
9424
|
this.metadataListChangedListener?.(serverName, "resources-list-changed");
|
|
9425
|
+
this.pendingMetadataPublications.delete(serverName);
|
|
8488
9426
|
}
|
|
8489
9427
|
async handleUrlElicitationRequired(serverName, error) {
|
|
8490
9428
|
if (this.runtimeSignal?.aborted || !this.elicitationConfig?.allowUrl) return "cancel";
|
|
@@ -8518,7 +9456,7 @@ var McpServerManager = class {
|
|
|
8518
9456
|
) ?? {};
|
|
8519
9457
|
const commandBearer = definition.bearerToken?.startsWith("!") && !definition.bearerToken.startsWith("!!") ? definition.bearerToken : void 0;
|
|
8520
9458
|
if (definition.auth === "bearer") {
|
|
8521
|
-
const token = commandBearer ? resolveCommandSecret(commandBearer, `MCP server "${serverName}" HTTP bearer token`) : resolveBearerToken(definition);
|
|
9459
|
+
const token = commandBearer ? resolveCommandSecret(commandBearer, `MCP server "${serverName}" HTTP bearer token`) : resolveBearerToken(definition) ?? (definition.bearerToken === void 0 && definition.bearerTokenEnv === void 0 && definition.bearerTokenStore === true ? getBearerTokenForUrl(serverName, serverUrl) : void 0);
|
|
8522
9460
|
if (token) headers["Authorization"] = `Bearer ${token}`;
|
|
8523
9461
|
}
|
|
8524
9462
|
if (hasCommandHeader || commandBearer) {
|
|
@@ -8705,6 +9643,7 @@ var McpServerManager = class {
|
|
|
8705
9643
|
async close(name) {
|
|
8706
9644
|
this.closeGenerations.set(name, (this.closeGenerations.get(name) ?? 0) + 1);
|
|
8707
9645
|
this.connectAttempts.get(name)?.abort(new Error(`MCP connection ${name} was closed`));
|
|
9646
|
+
this.pendingMetadataPublications.delete(name);
|
|
8708
9647
|
const connection = this.connections.get(name);
|
|
8709
9648
|
if (!connection) {
|
|
8710
9649
|
const pendingClose = this.closePromises.get(name);
|
|
@@ -8756,6 +9695,7 @@ var McpServerManager = class {
|
|
|
8756
9695
|
const failures = [...pendingResults, ...results, ...lateResults].flatMap((result) => result.status === "rejected" ? [result.reason] : []).filter((error) => this.containsCleanupFailure(error));
|
|
8757
9696
|
this.uiStreamListeners.clear();
|
|
8758
9697
|
this.acceptedUrlElicitations.clear();
|
|
9698
|
+
this.pendingMetadataPublications.clear();
|
|
8759
9699
|
this.samplingConfig = void 0;
|
|
8760
9700
|
this.elicitationConfig = void 0;
|
|
8761
9701
|
await this.traceWriter?.flush();
|
|
@@ -9071,77 +10011,6 @@ init_resource_tools();
|
|
|
9071
10011
|
// packages/coding-agent/src/humain/mcp-adapter/vendor/ui-resource-handler.ts
|
|
9072
10012
|
init_ui_app_bridge_helpers();
|
|
9073
10013
|
import { UrlElicitationRequiredError } from "@modelcontextprotocol/client";
|
|
9074
|
-
|
|
9075
|
-
// packages/coding-agent/src/humain/mcp-adapter/vendor/session-recovery.ts
|
|
9076
|
-
import { ProtocolError as ProtocolError2, SdkHttpError as SdkHttpError2, UnauthorizedError as UnauthorizedError4 } from "@modelcontextprotocol/client";
|
|
9077
|
-
init_types();
|
|
9078
|
-
var CONNECTION_CLOSED_PROTOCOL_CODE = -32e3;
|
|
9079
|
-
var SERVER_NOT_INITIALIZED_MCP_MESSAGES = /* @__PURE__ */ new Set([
|
|
9080
|
-
"Server not initialized",
|
|
9081
|
-
"Bad Request: Server not initialized"
|
|
9082
|
-
]);
|
|
9083
|
-
function isTerminatedSession(err, hadSessionId) {
|
|
9084
|
-
if (!hadSessionId) return false;
|
|
9085
|
-
if (err instanceof SdkHttpError2) {
|
|
9086
|
-
return err.status === 404 || err.status === 400 && /"code"\s*:\s*-32000/.test(err.message) && /"message"\s*:\s*"Bad Request: Server not initialized"/.test(err.message);
|
|
9087
|
-
}
|
|
9088
|
-
return err instanceof ProtocolError2 && err.code === CONNECTION_CLOSED_PROTOCOL_CODE && SERVER_NOT_INITIALIZED_MCP_MESSAGES.has(err.message);
|
|
9089
|
-
}
|
|
9090
|
-
function hasSessionId(connection) {
|
|
9091
|
-
const transport = connection.transport;
|
|
9092
|
-
return transport?.sessionId != null;
|
|
9093
|
-
}
|
|
9094
|
-
var SessionRecoveryAuthRequiredError = class extends Error {
|
|
9095
|
-
constructor(serverName, authMessage) {
|
|
9096
|
-
super(authMessage ?? `MCP server "${serverName}" requires OAuth authentication after reconnect.`);
|
|
9097
|
-
this.serverName = serverName;
|
|
9098
|
-
this.authMessage = authMessage;
|
|
9099
|
-
this.name = "SessionRecoveryAuthRequiredError";
|
|
9100
|
-
}
|
|
9101
|
-
};
|
|
9102
|
-
async function withSessionRecovery(deps, serverName, fn) {
|
|
9103
|
-
if (isServerDisabled(deps.config.mcpServers[serverName])) {
|
|
9104
|
-
throw new Error(`MCP server "${serverName}" is disabled`);
|
|
9105
|
-
}
|
|
9106
|
-
const connection = deps.manager.getConnection(serverName);
|
|
9107
|
-
if (!connection) {
|
|
9108
|
-
throw new Error(`Server "${serverName}" is not connected`);
|
|
9109
|
-
}
|
|
9110
|
-
const hadSessionId = hasSessionId(connection);
|
|
9111
|
-
try {
|
|
9112
|
-
return await fn(connection);
|
|
9113
|
-
} catch (err) {
|
|
9114
|
-
const definition = deps.config.mcpServers[serverName];
|
|
9115
|
-
if (definition && supportsOAuth(definition) && (err instanceof UnauthorizedError4 || err instanceof SdkHttpError2 && err.status === 401)) {
|
|
9116
|
-
invalidateAuthEntryCache(serverName);
|
|
9117
|
-
}
|
|
9118
|
-
if (!isTerminatedSession(err, hadSessionId)) {
|
|
9119
|
-
throw err;
|
|
9120
|
-
}
|
|
9121
|
-
if (!definition) {
|
|
9122
|
-
throw err;
|
|
9123
|
-
}
|
|
9124
|
-
throwIfAborted(deps.signal);
|
|
9125
|
-
logger.debug(`MCP session for "${serverName}" expired; reconnecting`, {
|
|
9126
|
-
server: serverName
|
|
9127
|
-
});
|
|
9128
|
-
let freshConnection = deps.signal ? await deps.manager.reconnect(serverName, definition, connection, deps.signal) : await deps.manager.reconnect(serverName, definition, connection);
|
|
9129
|
-
throwIfAborted(deps.signal);
|
|
9130
|
-
if (freshConnection.status === "needs-auth") {
|
|
9131
|
-
freshConnection = await deps.onNeedsAuth?.(serverName) ?? freshConnection;
|
|
9132
|
-
throwIfAborted(deps.signal);
|
|
9133
|
-
}
|
|
9134
|
-
if (freshConnection.status === "needs-auth") {
|
|
9135
|
-
throw new SessionRecoveryAuthRequiredError(serverName);
|
|
9136
|
-
}
|
|
9137
|
-
if (freshConnection.status !== "connected") {
|
|
9138
|
-
throw err;
|
|
9139
|
-
}
|
|
9140
|
-
return fn(freshConnection);
|
|
9141
|
-
}
|
|
9142
|
-
}
|
|
9143
|
-
|
|
9144
|
-
// packages/coding-agent/src/humain/mcp-adapter/vendor/ui-resource-handler.ts
|
|
9145
10014
|
init_types();
|
|
9146
10015
|
var UiResourceHandler = class {
|
|
9147
10016
|
constructor(manager, config = void 0) {
|
|
@@ -9532,8 +10401,20 @@ async function initializeMcp(pi, ctx, owner = createMcpRuntimeOwner(), options =
|
|
|
9532
10401
|
},
|
|
9533
10402
|
...ui !== void 0 ? { ui } : {},
|
|
9534
10403
|
sendMessage: (message, options2) => {
|
|
9535
|
-
|
|
9536
|
-
|
|
10404
|
+
const deliver = () => {
|
|
10405
|
+
if (!owner.isActive()) return;
|
|
10406
|
+
pi.sendMessage(message, options2);
|
|
10407
|
+
};
|
|
10408
|
+
if (!options2?.triggerTurn) {
|
|
10409
|
+
deliver();
|
|
10410
|
+
return;
|
|
10411
|
+
}
|
|
10412
|
+
void lifecycle.ensureConverged(owner.signal).then(deliver, (error) => {
|
|
10413
|
+
if (!owner.isActive() || isAbortError(error, owner.signal)) return;
|
|
10414
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
10415
|
+
logger.debug(`MCP: pre-turn keep-alive convergence failed: ${sanitizeTerminalText(detail)}`);
|
|
10416
|
+
deliver();
|
|
10417
|
+
});
|
|
9537
10418
|
},
|
|
9538
10419
|
...options.statusEvents !== void 0 ? { statusEvents: options.statusEvents } : {}
|
|
9539
10420
|
};
|
|
@@ -9564,7 +10445,7 @@ async function initializeMcp(pi, ctx, owner = createMcpRuntimeOwner(), options =
|
|
|
9564
10445
|
const idleSetting = typeof config.settings?.idleTimeout === "number" ? config.settings.idleTimeout : 10;
|
|
9565
10446
|
lifecycle.setGlobalIdleTimeout(idleSetting);
|
|
9566
10447
|
const cachePath = getMetadataCachePath();
|
|
9567
|
-
const cacheFileExists =
|
|
10448
|
+
const cacheFileExists = existsSync7(cachePath);
|
|
9568
10449
|
let cache = loadMetadataCache();
|
|
9569
10450
|
let bootstrapAll = false;
|
|
9570
10451
|
if (!cacheFileExists) {
|
|
@@ -9575,6 +10456,7 @@ async function initializeMcp(pi, ctx, owner = createMcpRuntimeOwner(), options =
|
|
|
9575
10456
|
saveMetadataCache(cache);
|
|
9576
10457
|
}
|
|
9577
10458
|
const prefix = config.settings?.toolPrefix ?? "server";
|
|
10459
|
+
let cachedSelectorCandidateIndex;
|
|
9578
10460
|
for (const [name, definition] of serverEntries) {
|
|
9579
10461
|
const lifecycleMode = definition.lifecycle ?? "lazy";
|
|
9580
10462
|
const persistsAfterFirstSpawn = lifecycleMode === "eager" || lifecycleMode === "lazy-keep-alive";
|
|
@@ -9589,7 +10471,11 @@ async function initializeMcp(pi, ctx, owner = createMcpRuntimeOwner(), options =
|
|
|
9589
10471
|
}
|
|
9590
10472
|
const cachedEntry = cache?.servers?.[name];
|
|
9591
10473
|
if (cachedEntry && isServerCacheValid(cachedEntry, definition)) {
|
|
9592
|
-
const
|
|
10474
|
+
const hasToolFilters = Array.isArray(definition.includeTools) && definition.includeTools.length > 0 || Array.isArray(definition.excludeTools) && definition.excludeTools.length > 0;
|
|
10475
|
+
if (hasToolFilters && !cachedSelectorCandidateIndex && cache) {
|
|
10476
|
+
cachedSelectorCandidateIndex = createCachedToolSelectorCandidateIndex(config.mcpServers, cache, prefix);
|
|
10477
|
+
}
|
|
10478
|
+
const metadata = reconstructToolMetadata(name, cachedEntry, prefix, definition, config.mcpServers, cache ?? void 0, cachedSelectorCandidateIndex);
|
|
9593
10479
|
toolMetadata.set(name, metadata);
|
|
9594
10480
|
if (Array.isArray(cachedEntry.resources)) {
|
|
9595
10481
|
resourceCounts.set(name, cachedEntry.resources.length);
|
|
@@ -9747,6 +10633,16 @@ async function initializeMcp(pi, ctx, owner = createMcpRuntimeOwner(), options =
|
|
|
9747
10633
|
recordFailure(state, serverName, message);
|
|
9748
10634
|
updateStatusBar(state);
|
|
9749
10635
|
});
|
|
10636
|
+
lifecycle.setHealthRestoredCallback((serverName) => {
|
|
10637
|
+
if (!owner.isActive()) return;
|
|
10638
|
+
clearFailure(state, serverName);
|
|
10639
|
+
updateStatusBar(state);
|
|
10640
|
+
});
|
|
10641
|
+
lifecycle.setAuthRequiredCallback((serverName) => {
|
|
10642
|
+
if (!owner.isActive()) return;
|
|
10643
|
+
clearFailure(state, serverName);
|
|
10644
|
+
updateStatusBar(state);
|
|
10645
|
+
});
|
|
9750
10646
|
lifecycle.setIdleShutdownCallback((serverName) => {
|
|
9751
10647
|
if (!owner.isActive()) return;
|
|
9752
10648
|
const idleMinutes = getEffectiveIdleTimeoutMinutes(state, serverName);
|
|
@@ -9942,8 +10838,8 @@ init_metadata_cache();
|
|
|
9942
10838
|
|
|
9943
10839
|
// packages/coding-agent/src/humain/mcp-adapter/vendor/onboarding-state.ts
|
|
9944
10840
|
init_agent_dir();
|
|
9945
|
-
import { existsSync as
|
|
9946
|
-
import { dirname as
|
|
10841
|
+
import { existsSync as existsSync8, mkdirSync as mkdirSync5, readFileSync as readFileSync8, writeFileSync as writeFileSync4, renameSync as renameSync4 } from "node:fs";
|
|
10842
|
+
import { dirname as dirname7 } from "node:path";
|
|
9947
10843
|
var DEFAULT_STATE = {
|
|
9948
10844
|
version: 1,
|
|
9949
10845
|
sharedConfigHintShown: false,
|
|
@@ -9954,9 +10850,9 @@ function getOnboardingStatePath() {
|
|
|
9954
10850
|
}
|
|
9955
10851
|
function loadOnboardingState() {
|
|
9956
10852
|
const path2 = getOnboardingStatePath();
|
|
9957
|
-
if (!
|
|
10853
|
+
if (!existsSync8(path2)) return { ...DEFAULT_STATE };
|
|
9958
10854
|
try {
|
|
9959
|
-
const raw = JSON.parse(
|
|
10855
|
+
const raw = JSON.parse(readFileSync8(path2, "utf-8"));
|
|
9960
10856
|
if (!raw || typeof raw !== "object") return { ...DEFAULT_STATE };
|
|
9961
10857
|
return {
|
|
9962
10858
|
version: 1,
|
|
@@ -9970,7 +10866,7 @@ function loadOnboardingState() {
|
|
|
9970
10866
|
}
|
|
9971
10867
|
function saveOnboardingState(state) {
|
|
9972
10868
|
const path2 = getOnboardingStatePath();
|
|
9973
|
-
mkdirSync5(
|
|
10869
|
+
mkdirSync5(dirname7(path2), { recursive: true });
|
|
9974
10870
|
const tmpPath = `${path2}.${process.pid}.tmp`;
|
|
9975
10871
|
writeFileSync4(tmpPath, `${JSON.stringify(state, null, 2)}
|
|
9976
10872
|
`, "utf-8");
|
|
@@ -10007,6 +10903,9 @@ init_utils();
|
|
|
10007
10903
|
function terminalHyperlink(label, url) {
|
|
10008
10904
|
return `\x1B]8;;${sanitizeTerminalText(url)}\x1B\\${sanitizeTerminalText(label)}\x1B]8;;\x1B\\`;
|
|
10009
10905
|
}
|
|
10906
|
+
function canRenderPanel(ctx) {
|
|
10907
|
+
return ctx.hasUI && ctx.mode === "tui";
|
|
10908
|
+
}
|
|
10010
10909
|
async function showStatus(state, ctx) {
|
|
10011
10910
|
if (!ctx.hasUI) return;
|
|
10012
10911
|
const lines = ["MCP Server Status:", ""];
|
|
@@ -10206,29 +11105,18 @@ Set "auth": "oauth" or omit auth for auto-detection.`,
|
|
|
10206
11105
|
const authStorageOptions = getAuthStorageOptions(config.settings?.oauthDir, cwd);
|
|
10207
11106
|
const status = await authenticate(serverName, serverUrl, definition, {
|
|
10208
11107
|
...authStorageOptions.baseDir ? { authStorageOptions } : {},
|
|
10209
|
-
onAuthorizationUrl: (
|
|
10210
|
-
ui.notify(
|
|
10211
|
-
`Open this URL to authenticate ${serverName}:
|
|
10212
|
-
|
|
10213
|
-
${terminalHyperlink(authorizationUrl, authorizationUrl)}
|
|
10214
|
-
|
|
10215
|
-
After approving, Pi will complete automatically if the browser can reach its localhost callback. On a remote machine, copy the full localhost URL from the browser address bar and paste it into Pi.`,
|
|
10216
|
-
"info"
|
|
10217
|
-
);
|
|
11108
|
+
onAuthorizationUrl: () => {
|
|
10218
11109
|
},
|
|
10219
11110
|
onAuthorizationInput: async (authorizationUrl, inputSignal) => {
|
|
10220
|
-
|
|
10221
|
-
`Authorize ${serverName}`,
|
|
10222
|
-
`Open this link in your browser:
|
|
10223
|
-
${terminalHyperlink(authorizationUrl, authorizationUrl)}
|
|
10224
|
-
|
|
10225
|
-
After approving access, select Yes to paste the callback URL.`,
|
|
10226
|
-
{ signal: inputSignal }
|
|
10227
|
-
);
|
|
10228
|
-
if (!readyToPaste || inputSignal.aborted) return void 0;
|
|
11111
|
+
if (inputSignal.aborted) return void 0;
|
|
10229
11112
|
return ui.input(
|
|
10230
|
-
`Complete ${serverName} OAuth
|
|
10231
|
-
|
|
11113
|
+
`Complete ${serverName} OAuth
|
|
11114
|
+
|
|
11115
|
+
${terminalHyperlink("Open authorization page", authorizationUrl)}
|
|
11116
|
+
${authorizationUrl}
|
|
11117
|
+
|
|
11118
|
+
Approve access, then paste the full localhost callback URL below.`,
|
|
11119
|
+
void 0,
|
|
10232
11120
|
{ signal: inputSignal }
|
|
10233
11121
|
);
|
|
10234
11122
|
},
|
|
@@ -10292,6 +11180,53 @@ async function logoutServer(serverName, state, ctx) {
|
|
|
10292
11180
|
if (ui) ui.notify(message, "info");
|
|
10293
11181
|
return { ok: true, message };
|
|
10294
11182
|
}
|
|
11183
|
+
function validateBearerTokenStoreServer(serverName, state) {
|
|
11184
|
+
const safeName = sanitizeTerminalText(serverName);
|
|
11185
|
+
const definition = state.config.mcpServers[serverName];
|
|
11186
|
+
if (!definition) return { ok: false, message: `Server "${safeName}" not found in config`, type: "error" };
|
|
11187
|
+
if (isServerDisabled(definition)) return { ok: false, message: `Server "${safeName}" is disabled. Run /mcp enable ${safeName}, then /reload.`, type: "warning" };
|
|
11188
|
+
if (definition.auth !== "bearer" || definition.bearerTokenStore !== true) {
|
|
11189
|
+
return { ok: false, message: `Server "${safeName}" is not configured for bearerTokenStore.`, type: "error" };
|
|
11190
|
+
}
|
|
11191
|
+
let serverUrl;
|
|
11192
|
+
try {
|
|
11193
|
+
serverUrl = resolveServerUrl(definition);
|
|
11194
|
+
} catch {
|
|
11195
|
+
return { ok: false, message: `Server "${safeName}" has an invalid or unresolvable URL.`, type: "error" };
|
|
11196
|
+
}
|
|
11197
|
+
if (!serverUrl) return { ok: false, message: `Server "${safeName}" has no URL configured.`, type: "error" };
|
|
11198
|
+
return { ok: true, serverUrl };
|
|
11199
|
+
}
|
|
11200
|
+
async function manageBearerToken(action, serverName, state, ctx) {
|
|
11201
|
+
const ui = ctx.hasUI ? ctx.ui : void 0;
|
|
11202
|
+
const safeName = sanitizeTerminalText(serverName);
|
|
11203
|
+
const validation = validateBearerTokenStoreServer(serverName, state);
|
|
11204
|
+
if (!validation.ok) {
|
|
11205
|
+
if (ui) ui.notify(validation.message, validation.type);
|
|
11206
|
+
return { ok: false, message: validation.message };
|
|
11207
|
+
}
|
|
11208
|
+
if (action === "set") {
|
|
11209
|
+
const message2 = `Cannot store bearer token here: Pi extension UI has no masked secret input primitive. Run \`pi-mcp-adapter token set ${safeName}\` in a terminal; it reads the token from stdin only.`;
|
|
11210
|
+
if (ui) ui.notify(message2, "error");
|
|
11211
|
+
return { ok: false, message: message2 };
|
|
11212
|
+
}
|
|
11213
|
+
if (action === "status") {
|
|
11214
|
+
const status = inspectBearerTokenForUrl(serverName, validation.serverUrl);
|
|
11215
|
+
const message2 = status.status === "present" ? `Bearer token is stored for "${safeName}".` : status.status === "url-mismatch" ? `Bearer token is stored for "${safeName}", but its URL does not match the current server URL.` : status.status === "unavailable" ? status.message : `No bearer token is stored for "${safeName}".`;
|
|
11216
|
+
if (ui) ui.notify(message2, status.status === "unavailable" ? "error" : "info");
|
|
11217
|
+
return { ok: status.status !== "unavailable", message: message2 };
|
|
11218
|
+
}
|
|
11219
|
+
try {
|
|
11220
|
+
removeBearerToken(serverName);
|
|
11221
|
+
} catch (error) {
|
|
11222
|
+
const message2 = error instanceof Error ? error.message : String(error);
|
|
11223
|
+
if (ui) ui.notify(`Failed to remove bearer token for "${safeName}": ${sanitizeTerminalText(message2)}`, "error");
|
|
11224
|
+
return { ok: false, message: message2 };
|
|
11225
|
+
}
|
|
11226
|
+
const message = `Bearer token removed for "${safeName}".`;
|
|
11227
|
+
if (ui) ui.notify(message, "info");
|
|
11228
|
+
return { ok: true, message };
|
|
11229
|
+
}
|
|
10295
11230
|
function buildSharedConfigNoticeLines(configOverridePath, cwd) {
|
|
10296
11231
|
const discovery = getMcpStandardConfigSummary(configOverridePath, cwd);
|
|
10297
11232
|
const onboardingState = loadOnboardingState();
|
|
@@ -10310,6 +11245,10 @@ function buildSharedConfigNoticeLines(configOverridePath, cwd) {
|
|
|
10310
11245
|
}
|
|
10311
11246
|
async function openMcpSetup(state, pi, ctx, configOverridePath, mode = "setup", options = {}) {
|
|
10312
11247
|
if (!ctx.hasUI) return { configChanged: false };
|
|
11248
|
+
if (!canRenderPanel(ctx)) {
|
|
11249
|
+
ctx.ui.notify(`The interactive MCP setup panel is only available in the terminal UI (current mode: ${ctx.mode}). Edit .mcp.json directly, or run /mcp status to review servers.`, "info");
|
|
11250
|
+
return { configChanged: false };
|
|
11251
|
+
}
|
|
10313
11252
|
if (state.programmaticConfig) {
|
|
10314
11253
|
ctx.ui.notify("MCP setup is unavailable when config is supplied by createMcpAdapter().", "info");
|
|
10315
11254
|
return { configChanged: false };
|
|
@@ -10358,19 +11297,19 @@ async function openMcpSetup(state, pi, ctx, configOverridePath, mode = "setup",
|
|
|
10358
11297
|
markSetupCompleted(discovery.fingerprint);
|
|
10359
11298
|
}
|
|
10360
11299
|
};
|
|
10361
|
-
return new Promise((
|
|
11300
|
+
return new Promise((resolve7) => {
|
|
10362
11301
|
ctx.ui.custom(
|
|
10363
11302
|
(tui, _theme, keybindings, done) => {
|
|
10364
11303
|
return createMcpSetupPanel2(discovery, callbacks, { mode, onboardingState, keybindings }, tui, () => {
|
|
10365
11304
|
done(void 0);
|
|
10366
|
-
|
|
11305
|
+
resolve7({ configChanged });
|
|
10367
11306
|
});
|
|
10368
11307
|
},
|
|
10369
11308
|
{ overlay: true, overlayOptions: { anchor: "center", width: 92 } }
|
|
10370
11309
|
);
|
|
10371
11310
|
});
|
|
10372
11311
|
}
|
|
10373
|
-
function buildMcpPanelCallbacks(state, config, ctx) {
|
|
11312
|
+
function buildMcpPanelCallbacks(state, config, ctx, getOverlayHandle) {
|
|
10374
11313
|
const authStatusFailures = /* @__PURE__ */ new Map();
|
|
10375
11314
|
return {
|
|
10376
11315
|
reconnect: (serverName) => reconnectServer(state, ctx, serverName),
|
|
@@ -10378,7 +11317,16 @@ function buildMcpPanelCallbacks(state, config, ctx) {
|
|
|
10378
11317
|
const definition = config.mcpServers[serverName];
|
|
10379
11318
|
return definition ? !isServerDisabled(definition) && supportsOAuth(definition) : false;
|
|
10380
11319
|
},
|
|
10381
|
-
authenticate: (serverName) =>
|
|
11320
|
+
authenticate: async (serverName) => {
|
|
11321
|
+
const overlay = getOverlayHandle?.();
|
|
11322
|
+
overlay?.setHidden(true);
|
|
11323
|
+
try {
|
|
11324
|
+
return await authenticateServer(serverName, config, ctx, state.owner?.signal, state.oauthRuntime);
|
|
11325
|
+
} finally {
|
|
11326
|
+
overlay?.setHidden(false);
|
|
11327
|
+
overlay?.focus();
|
|
11328
|
+
}
|
|
11329
|
+
},
|
|
10382
11330
|
getConnectionStatus: (serverName) => {
|
|
10383
11331
|
authStatusFailures.delete(serverName);
|
|
10384
11332
|
const definition = config.mcpServers[serverName];
|
|
@@ -10420,6 +11368,10 @@ async function openMcpPanel(state, pi, ctx, configOverridePath, onDirectToolsCon
|
|
|
10420
11368
|
}
|
|
10421
11369
|
return { configChanged: false };
|
|
10422
11370
|
}
|
|
11371
|
+
if (!canRenderPanel(ctx)) {
|
|
11372
|
+
await showStatus(state, ctx);
|
|
11373
|
+
return { configChanged: false };
|
|
11374
|
+
}
|
|
10423
11375
|
if (Object.keys(state.config.mcpServers).length === 0) {
|
|
10424
11376
|
return openMcpSetup(state, pi, ctx, configOverridePath, "empty", { includeHostConfigs: false });
|
|
10425
11377
|
}
|
|
@@ -10428,10 +11380,11 @@ async function openMcpPanel(state, pi, ctx, configOverridePath, onDirectToolsCon
|
|
|
10428
11380
|
const configPath = pi.getFlag("mcp-config") ?? configOverridePath;
|
|
10429
11381
|
const provenanceMap = getServerProvenance(configPath, ctx.cwd);
|
|
10430
11382
|
const { lines: noticeLines, fingerprint } = buildSharedConfigNoticeLines(configPath, ctx.cwd);
|
|
10431
|
-
|
|
11383
|
+
let overlayHandle;
|
|
11384
|
+
const callbacks = buildMcpPanelCallbacks(state, config, ctx, () => overlayHandle);
|
|
10432
11385
|
const { createMcpPanel: createMcpPanel2 } = await Promise.resolve().then(() => (init_mcp_panel(), mcp_panel_exports));
|
|
10433
11386
|
let configChanged = false;
|
|
10434
|
-
await new Promise((
|
|
11387
|
+
await new Promise((resolve7) => {
|
|
10435
11388
|
ctx.ui.custom(
|
|
10436
11389
|
(tui, _theme, keybindings, done) => {
|
|
10437
11390
|
return createMcpPanel2(config, cache, provenanceMap, callbacks, tui, (result) => {
|
|
@@ -10442,17 +11395,23 @@ async function openMcpPanel(state, pi, ctx, configOverridePath, onDirectToolsCon
|
|
|
10442
11395
|
ctx.ui.notify("Direct tools updated for this session.", "info");
|
|
10443
11396
|
}
|
|
10444
11397
|
done(void 0);
|
|
10445
|
-
|
|
11398
|
+
resolve7();
|
|
10446
11399
|
})().catch((error) => {
|
|
10447
11400
|
const message = error instanceof Error ? error.message : String(error);
|
|
10448
11401
|
ctx.ui.notify(`Direct tools updated, but live refresh failed: ${message}`, "error");
|
|
10449
11402
|
configChanged = true;
|
|
10450
11403
|
done(void 0);
|
|
10451
|
-
|
|
11404
|
+
resolve7();
|
|
10452
11405
|
});
|
|
10453
11406
|
}, { noticeLines, keybindings });
|
|
10454
11407
|
},
|
|
10455
|
-
{
|
|
11408
|
+
{
|
|
11409
|
+
overlay: true,
|
|
11410
|
+
overlayOptions: { anchor: "center", width: 82 },
|
|
11411
|
+
onHandle: (handle) => {
|
|
11412
|
+
overlayHandle = handle;
|
|
11413
|
+
}
|
|
11414
|
+
}
|
|
10456
11415
|
);
|
|
10457
11416
|
});
|
|
10458
11417
|
if (noticeLines.length > 0 && fingerprint) {
|
|
@@ -10462,6 +11421,10 @@ async function openMcpPanel(state, pi, ctx, configOverridePath, onDirectToolsCon
|
|
|
10462
11421
|
}
|
|
10463
11422
|
async function openMcpAuthPanel(state, pi, ctx, configOverridePath) {
|
|
10464
11423
|
if (!ctx.hasUI) return { configChanged: false };
|
|
11424
|
+
if (!canRenderPanel(ctx)) {
|
|
11425
|
+
ctx.ui.notify(`The interactive MCP auth panel is only available in the terminal UI (current mode: ${ctx.mode}). Use /mcp-auth <server> to authenticate a specific server.`, "info");
|
|
11426
|
+
return { configChanged: false };
|
|
11427
|
+
}
|
|
10465
11428
|
if (state.programmaticConfig) {
|
|
10466
11429
|
ctx.ui.notify("Use /mcp-auth <server> to authenticate a server from the in-memory SDK config.", "info");
|
|
10467
11430
|
return { configChanged: false };
|
|
@@ -10477,21 +11440,28 @@ async function openMcpAuthPanel(state, pi, ctx, configOverridePath) {
|
|
|
10477
11440
|
const cache = loadMetadataCache();
|
|
10478
11441
|
const configPath = pi.getFlag("mcp-config") ?? configOverridePath;
|
|
10479
11442
|
const provenanceMap = getServerProvenance(configPath, ctx.cwd);
|
|
10480
|
-
|
|
11443
|
+
let overlayHandle;
|
|
11444
|
+
const callbacks = buildMcpPanelCallbacks(state, config, ctx, () => overlayHandle);
|
|
10481
11445
|
const { createMcpPanel: createMcpPanel2 } = await Promise.resolve().then(() => (init_mcp_panel(), mcp_panel_exports));
|
|
10482
|
-
await new Promise((
|
|
11446
|
+
await new Promise((resolve7) => {
|
|
10483
11447
|
ctx.ui.custom(
|
|
10484
11448
|
(tui, _theme, keybindings, done) => {
|
|
10485
11449
|
return createMcpPanel2(config, cache, provenanceMap, callbacks, tui, () => {
|
|
10486
11450
|
done(void 0);
|
|
10487
|
-
|
|
11451
|
+
resolve7();
|
|
10488
11452
|
}, {
|
|
10489
11453
|
authOnly: true,
|
|
10490
11454
|
keybindings,
|
|
10491
11455
|
noticeLines: ["Select an OAuth MCP server and press Enter or ctrl+a to authenticate."]
|
|
10492
11456
|
});
|
|
10493
11457
|
},
|
|
10494
|
-
{
|
|
11458
|
+
{
|
|
11459
|
+
overlay: true,
|
|
11460
|
+
overlayOptions: { anchor: "center", width: 82 },
|
|
11461
|
+
onHandle: (handle) => {
|
|
11462
|
+
overlayHandle = handle;
|
|
11463
|
+
}
|
|
11464
|
+
}
|
|
10495
11465
|
);
|
|
10496
11466
|
});
|
|
10497
11467
|
return { configChanged: false };
|
|
@@ -10508,7 +11478,7 @@ init_metadata_cache();
|
|
|
10508
11478
|
// packages/coding-agent/src/humain/mcp-adapter/vendor/tool-registrar.ts
|
|
10509
11479
|
import { mkdtempSync, rmSync as rmSync2, writeFileSync as writeFileSync5 } from "node:fs";
|
|
10510
11480
|
import { tmpdir } from "node:os";
|
|
10511
|
-
import { join as
|
|
11481
|
+
import { join as join9 } from "node:path";
|
|
10512
11482
|
var MAX_BINARY_RESOURCE_BYTES = 10 * 1024 * 1024;
|
|
10513
11483
|
var MAX_SESSION_RESOURCE_BYTES = 100 * 1024 * 1024;
|
|
10514
11484
|
var MAX_SESSION_RESOURCE_FILES = 1e4;
|
|
@@ -10615,11 +11585,11 @@ function materializeBinaryResource(resource, scope) {
|
|
|
10615
11585
|
return omitBinaryResource(resource, "session resource limit reached");
|
|
10616
11586
|
}
|
|
10617
11587
|
try {
|
|
10618
|
-
session.directory ??= mkdtempSync(
|
|
11588
|
+
session.directory ??= mkdtempSync(join9(tmpdir(), "pi-mcp-resource-"));
|
|
10619
11589
|
} catch {
|
|
10620
11590
|
return omitBinaryResource(resource, "could not be saved");
|
|
10621
11591
|
}
|
|
10622
|
-
const filePath =
|
|
11592
|
+
const filePath = join9(session.directory, `resource-${++session.sequence}.bin`);
|
|
10623
11593
|
session.bytes += decodedBytes;
|
|
10624
11594
|
session.files += 1;
|
|
10625
11595
|
try {
|
|
@@ -10712,7 +11682,7 @@ function stringifyStructuredContent(value) {
|
|
|
10712
11682
|
import { randomBytes } from "node:crypto";
|
|
10713
11683
|
import { mkdtemp, writeFile as writeFile2 } from "node:fs/promises";
|
|
10714
11684
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
10715
|
-
import { join as
|
|
11685
|
+
import { join as join10 } from "node:path";
|
|
10716
11686
|
var DEFAULT_MCP_OUTPUT_MAX_BYTES = 50 * 1024;
|
|
10717
11687
|
var DEFAULT_MCP_OUTPUT_MAX_LINES = 2e3;
|
|
10718
11688
|
var DEFAULT_MCP_DETAILS_MAX_BYTES = 16 * 1024;
|
|
@@ -10952,8 +11922,8 @@ function truncateKey(key) {
|
|
|
10952
11922
|
}
|
|
10953
11923
|
async function saveArtifact(kind, text) {
|
|
10954
11924
|
try {
|
|
10955
|
-
const dir = await mkdtemp(
|
|
10956
|
-
const path2 =
|
|
11925
|
+
const dir = await mkdtemp(join10(tmpdir2(), "pi-mcp-output-"));
|
|
11926
|
+
const path2 = join10(dir, `${kind}-${randomBytes(4).toString("hex")}.txt`);
|
|
10957
11927
|
await writeFile2(path2, text, { encoding: "utf8", mode: 384 });
|
|
10958
11928
|
return { path: path2 };
|
|
10959
11929
|
} catch (error) {
|
|
@@ -11427,9 +12397,20 @@ function escapeHtml2(value) {
|
|
|
11427
12397
|
}
|
|
11428
12398
|
|
|
11429
12399
|
// packages/coding-agent/src/humain/mcp-adapter/vendor/tool-approval.ts
|
|
11430
|
-
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
12400
|
+
import { createHash as createHash4, randomUUID as randomUUID2 } from "node:crypto";
|
|
11431
12401
|
init_types();
|
|
11432
12402
|
init_utils();
|
|
12403
|
+
function stableStringify2(value) {
|
|
12404
|
+
if (value === null || value === void 0 || typeof value !== "object") {
|
|
12405
|
+
const serialized = JSON.stringify(value);
|
|
12406
|
+
return serialized === void 0 ? "undefined" : serialized;
|
|
12407
|
+
}
|
|
12408
|
+
if (Array.isArray(value)) {
|
|
12409
|
+
return `[${value.map((item) => stableStringify2(item)).join(",")}]`;
|
|
12410
|
+
}
|
|
12411
|
+
const object = value;
|
|
12412
|
+
return `{${Object.keys(object).sort().map((key) => `${JSON.stringify(key)}:${stableStringify2(object[key])}`).join(",")}}`;
|
|
12413
|
+
}
|
|
11433
12414
|
function isToolCallApprovalRequired(config, serverName, toolMeta, toolMetadata) {
|
|
11434
12415
|
const definition = config.mcpServers[serverName];
|
|
11435
12416
|
const serverApproval = definition?.approveTools;
|
|
@@ -11509,7 +12490,8 @@ async function requestBrokerApproval(state, serverName, toolMeta, args, origin,
|
|
|
11509
12490
|
}
|
|
11510
12491
|
}
|
|
11511
12492
|
async function ensureToolCallApproved(state, serverName, toolMeta, args, signal, origin = toolMeta.resourceUri ? "resource" : "proxy", approvalMetadata) {
|
|
11512
|
-
const
|
|
12493
|
+
const argsHash = createHash4("sha256").update(stableStringify2(args ?? {})).digest("hex");
|
|
12494
|
+
const cacheKey = `${serverName}\0${toolMeta.originalName}\0${argsHash}`;
|
|
11513
12495
|
const approvedToolCalls = state.approvedToolCalls ??= /* @__PURE__ */ new Map();
|
|
11514
12496
|
if (approvedToolCalls.has(cacheKey)) {
|
|
11515
12497
|
return { ok: true };
|
|
@@ -11581,6 +12563,7 @@ async function startUiServer(options) {
|
|
|
11581
12563
|
let currentDisplayMode = options.hostContext?.displayMode ?? "inline";
|
|
11582
12564
|
let nextEventId = 1;
|
|
11583
12565
|
const eventLog = [];
|
|
12566
|
+
let latestCheckpointEventId;
|
|
11584
12567
|
let streamSummary;
|
|
11585
12568
|
const sessionMessages = {
|
|
11586
12569
|
prompts: [],
|
|
@@ -11641,9 +12624,12 @@ async function startUiServer(options) {
|
|
|
11641
12624
|
const touchHeartbeat = () => {
|
|
11642
12625
|
lastHeartbeatAt = Date.now();
|
|
11643
12626
|
};
|
|
11644
|
-
const updateStreamSummary = (payload) => {
|
|
12627
|
+
const updateStreamSummary = (eventId, payload) => {
|
|
11645
12628
|
const envelope = getVisualizationStreamEnvelope(payload?.structuredContent);
|
|
11646
12629
|
if (!envelope) return;
|
|
12630
|
+
if (envelope.frameType === "checkpoint" || envelope.frameType === "final") {
|
|
12631
|
+
latestCheckpointEventId = eventId;
|
|
12632
|
+
}
|
|
11647
12633
|
if (!streamSummary) {
|
|
11648
12634
|
streamSummary = {
|
|
11649
12635
|
streamId: envelope.streamId,
|
|
@@ -11668,15 +12654,9 @@ data: ${JSON.stringify(payload)}
|
|
|
11668
12654
|
`;
|
|
11669
12655
|
};
|
|
11670
12656
|
const getLatestCheckpointIndex = () => {
|
|
11671
|
-
|
|
11672
|
-
|
|
11673
|
-
|
|
11674
|
-
const envelope = getVisualizationStreamEnvelope(entry.payload?.structuredContent);
|
|
11675
|
-
if (envelope?.frameType === "checkpoint" || envelope?.frameType === "final") {
|
|
11676
|
-
return index;
|
|
11677
|
-
}
|
|
11678
|
-
}
|
|
11679
|
-
return -1;
|
|
12657
|
+
const firstEventId = eventLog[0]?.id;
|
|
12658
|
+
if (latestCheckpointEventId === void 0 || firstEventId === void 0 || latestCheckpointEventId < firstEventId) return -1;
|
|
12659
|
+
return latestCheckpointEventId - firstEventId;
|
|
11680
12660
|
};
|
|
11681
12661
|
const pruneEventLog = () => {
|
|
11682
12662
|
if (eventLog.length <= MAX_EVENT_LOG) return;
|
|
@@ -11692,7 +12672,7 @@ data: ${JSON.stringify(payload)}
|
|
|
11692
12672
|
if (completed) return;
|
|
11693
12673
|
const eventId = nextEventId++;
|
|
11694
12674
|
eventLog.push({ id: eventId, name, payload });
|
|
11695
|
-
updateStreamSummary(payload);
|
|
12675
|
+
updateStreamSummary(eventId, payload);
|
|
11696
12676
|
pruneEventLog();
|
|
11697
12677
|
const chunk = serializeEvent(eventId, name, payload);
|
|
11698
12678
|
for (const client of sseClients) {
|
|
@@ -11868,9 +12848,16 @@ data: ${JSON.stringify(payload)}
|
|
|
11868
12848
|
sendJson(res, 403, { ok: false, error: `MCP tool "${callParams.name}" is not callable by apps` });
|
|
11869
12849
|
return;
|
|
11870
12850
|
}
|
|
12851
|
+
let normalizedArguments;
|
|
12852
|
+
try {
|
|
12853
|
+
normalizedArguments = normalizeToolArguments(callParams.arguments, `tool "${callParams.name}" arguments`);
|
|
12854
|
+
} catch (error) {
|
|
12855
|
+
sendJson(res, 400, { ok: false, error: error instanceof Error ? error.message : String(error) });
|
|
12856
|
+
return;
|
|
12857
|
+
}
|
|
11871
12858
|
const callArgs = {
|
|
11872
12859
|
name: callParams.name,
|
|
11873
|
-
arguments:
|
|
12860
|
+
arguments: normalizedArguments
|
|
11874
12861
|
};
|
|
11875
12862
|
const toolMeta = {
|
|
11876
12863
|
name: callParams.name,
|
|
@@ -12077,7 +13064,7 @@ data: ${JSON.stringify(payload)}
|
|
|
12077
13064
|
closeSse();
|
|
12078
13065
|
}, WATCHDOG_INTERVAL_MS);
|
|
12079
13066
|
watchdog.unref();
|
|
12080
|
-
return new Promise((
|
|
13067
|
+
return new Promise((resolve7, reject) => {
|
|
12081
13068
|
const candidates = resolvePortCandidates(options.port);
|
|
12082
13069
|
let candidateIndex = 0;
|
|
12083
13070
|
const listen = () => {
|
|
@@ -12142,7 +13129,7 @@ data: ${JSON.stringify(payload)}
|
|
|
12142
13129
|
getSessionMessages: () => ({ ...sessionMessages }),
|
|
12143
13130
|
getStreamSummary: () => streamSummary ? { ...streamSummary, phases: [...streamSummary.phases] } : void 0
|
|
12144
13131
|
};
|
|
12145
|
-
|
|
13132
|
+
resolve7(handle);
|
|
12146
13133
|
};
|
|
12147
13134
|
listen();
|
|
12148
13135
|
});
|
|
@@ -12161,7 +13148,7 @@ async function parseBody(req, res) {
|
|
|
12161
13148
|
}
|
|
12162
13149
|
}
|
|
12163
13150
|
function readBody(req) {
|
|
12164
|
-
return new Promise((
|
|
13151
|
+
return new Promise((resolve7, reject) => {
|
|
12165
13152
|
let size = 0;
|
|
12166
13153
|
const chunks = [];
|
|
12167
13154
|
req.on("data", (chunk) => {
|
|
@@ -12175,7 +13162,7 @@ function readBody(req) {
|
|
|
12175
13162
|
});
|
|
12176
13163
|
req.on("end", () => {
|
|
12177
13164
|
try {
|
|
12178
|
-
|
|
13165
|
+
resolve7(JSON.parse(Buffer.concat(chunks).toString("utf-8")));
|
|
12179
13166
|
} catch (error) {
|
|
12180
13167
|
reject(error);
|
|
12181
13168
|
}
|
|
@@ -12232,11 +13219,11 @@ function sendText(res, status, text) {
|
|
|
12232
13219
|
}
|
|
12233
13220
|
|
|
12234
13221
|
// packages/coding-agent/src/humain/mcp-adapter/vendor/glimpse-ui.ts
|
|
12235
|
-
import { existsSync as
|
|
13222
|
+
import { existsSync as existsSync9 } from "node:fs";
|
|
12236
13223
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
12237
|
-
import { join as
|
|
13224
|
+
import { join as join11, dirname as dirname9 } from "node:path";
|
|
12238
13225
|
import { platform as platform3 } from "node:os";
|
|
12239
|
-
import { createRequire as
|
|
13226
|
+
import { createRequire as createRequire5 } from "node:module";
|
|
12240
13227
|
var glimpseAvailable = null;
|
|
12241
13228
|
var resolvedBinaryPath = null;
|
|
12242
13229
|
function isGlimpseAvailable() {
|
|
@@ -12250,26 +13237,26 @@ function isGlimpseAvailable() {
|
|
|
12250
13237
|
return glimpseAvailable;
|
|
12251
13238
|
}
|
|
12252
13239
|
function getGlimpseBinaryPath() {
|
|
12253
|
-
if (process.env.GLIMPSE_BINARY &&
|
|
13240
|
+
if (process.env.GLIMPSE_BINARY && existsSync9(process.env.GLIMPSE_BINARY)) {
|
|
12254
13241
|
return process.env.GLIMPSE_BINARY;
|
|
12255
13242
|
}
|
|
12256
13243
|
try {
|
|
12257
|
-
const
|
|
12258
|
-
const glimpseuiPath =
|
|
12259
|
-
const binaryPath =
|
|
12260
|
-
if (
|
|
13244
|
+
const require6 = createRequire5(import.meta.url);
|
|
13245
|
+
const glimpseuiPath = require6.resolve("glimpseui");
|
|
13246
|
+
const binaryPath = join11(dirname9(glimpseuiPath), "glimpse");
|
|
13247
|
+
if (existsSync9(binaryPath)) return binaryPath;
|
|
12261
13248
|
} catch {
|
|
12262
13249
|
}
|
|
12263
13250
|
try {
|
|
12264
13251
|
const globalRoot = execFileSync2("npm", ["root", "-g"], { encoding: "utf-8" }).trim();
|
|
12265
|
-
const binaryPath =
|
|
12266
|
-
if (
|
|
13252
|
+
const binaryPath = join11(globalRoot, "glimpseui", "src", "glimpse");
|
|
13253
|
+
if (existsSync9(binaryPath)) return binaryPath;
|
|
12267
13254
|
} catch {
|
|
12268
13255
|
}
|
|
12269
13256
|
return null;
|
|
12270
13257
|
}
|
|
12271
13258
|
async function openGlimpseWindow(html, options) {
|
|
12272
|
-
const modulePath = resolvedBinaryPath ?
|
|
13259
|
+
const modulePath = resolvedBinaryPath ? join11(dirname9(resolvedBinaryPath), "glimpse.mjs") : "glimpseui";
|
|
12273
13260
|
const glimpse = await import(modulePath);
|
|
12274
13261
|
let active = true;
|
|
12275
13262
|
const win = glimpse.open(html, {
|
|
@@ -12356,22 +13343,22 @@ function isRemoteSession2() {
|
|
|
12356
13343
|
return Boolean(process.env.SSH_CONNECTION || process.env.SSH_TTY);
|
|
12357
13344
|
}
|
|
12358
13345
|
function hasActiveRemoteLogin() {
|
|
12359
|
-
return new Promise((
|
|
13346
|
+
return new Promise((resolve7) => {
|
|
12360
13347
|
execFile("who", { encoding: "utf8", timeout: 2e3 }, (error, out) => {
|
|
12361
13348
|
if (error) {
|
|
12362
|
-
|
|
13349
|
+
resolve7(false);
|
|
12363
13350
|
return;
|
|
12364
13351
|
}
|
|
12365
|
-
|
|
13352
|
+
resolve7(/\(.+\)\s*$/m.test(out));
|
|
12366
13353
|
});
|
|
12367
13354
|
});
|
|
12368
13355
|
}
|
|
12369
13356
|
function probeMoshiGateway() {
|
|
12370
|
-
return new Promise((
|
|
13357
|
+
return new Promise((resolve7) => {
|
|
12371
13358
|
const socket = net.connect({ host: "127.0.0.1", port: 24543 });
|
|
12372
13359
|
const done = (ok) => {
|
|
12373
13360
|
socket.destroy();
|
|
12374
|
-
|
|
13361
|
+
resolve7(ok);
|
|
12375
13362
|
};
|
|
12376
13363
|
socket.setTimeout(300);
|
|
12377
13364
|
socket.once("connect", () => done(true));
|
|
@@ -13084,6 +14071,7 @@ function createDirectToolExecutor(getState, getInitPromise, spec) {
|
|
|
13084
14071
|
details: { error: "not_connected", server: spec.serverName }
|
|
13085
14072
|
};
|
|
13086
14073
|
}
|
|
14074
|
+
const normalizedParams = spec.resourceUri ? params : normalizeToolArguments(params);
|
|
13087
14075
|
const approval = await ensureToolCallApproved(state, spec.serverName, {
|
|
13088
14076
|
name: spec.prefixedName,
|
|
13089
14077
|
originalName: spec.originalName,
|
|
@@ -13092,7 +14080,7 @@ function createDirectToolExecutor(getState, getInitPromise, spec) {
|
|
|
13092
14080
|
...spec.resourceUri !== void 0 ? { resourceUri: spec.resourceUri } : {},
|
|
13093
14081
|
...spec.uiResourceUri !== void 0 ? { uiResourceUri: spec.uiResourceUri } : {},
|
|
13094
14082
|
...spec.uiStreamMode !== void 0 ? { uiStreamMode: spec.uiStreamMode } : {}
|
|
13095
|
-
},
|
|
14083
|
+
}, normalizedParams, ownedSignal, spec.resourceUri ? "resource" : "direct");
|
|
13096
14084
|
if (approval.ok === false) {
|
|
13097
14085
|
const denied = approval.reason === "denied";
|
|
13098
14086
|
const message = denied ? `The user declined approval to run MCP tool "${spec.originalName}" on server "${spec.serverName}".` : `MCP tool "${spec.originalName}" on server "${spec.serverName}" is approval-gated and requires an interactive session.`;
|
|
@@ -13155,7 +14143,7 @@ function createDirectToolExecutor(getState, getInitPromise, spec) {
|
|
|
13155
14143
|
uiSession = hasUi ? await maybeStartUiSession(state, {
|
|
13156
14144
|
serverName: spec.serverName,
|
|
13157
14145
|
toolName: spec.originalName,
|
|
13158
|
-
toolArgs:
|
|
14146
|
+
toolArgs: normalizedParams,
|
|
13159
14147
|
uiResourceUri: spec.uiResourceUri,
|
|
13160
14148
|
...spec.uiStreamMode !== void 0 ? { streamMode: spec.uiStreamMode } : {},
|
|
13161
14149
|
...signal ? { signal } : {},
|
|
@@ -13171,7 +14159,7 @@ function createDirectToolExecutor(getState, getInitPromise, spec) {
|
|
|
13171
14159
|
spec.serverName,
|
|
13172
14160
|
(conn) => abortable(conn.client.callTool({
|
|
13173
14161
|
name: spec.originalName,
|
|
13174
|
-
arguments:
|
|
14162
|
+
arguments: normalizedParams,
|
|
13175
14163
|
_meta: uiSession?.requestMeta
|
|
13176
14164
|
}, requestOptions), ownedSignal)
|
|
13177
14165
|
);
|
|
@@ -13506,7 +14494,7 @@ function buildCommandDescription(metadata) {
|
|
|
13506
14494
|
// packages/coding-agent/src/humain/mcp-adapter/vendor/proxy-modes.ts
|
|
13507
14495
|
init_types();
|
|
13508
14496
|
import { UrlElicitationRequiredError as UrlElicitationRequiredError4 } from "@modelcontextprotocol/client";
|
|
13509
|
-
import { createRequire as
|
|
14497
|
+
import { createRequire as createRequire6 } from "node:module";
|
|
13510
14498
|
|
|
13511
14499
|
// packages/coding-agent/src/humain/mcp-adapter/vendor/ts-shape.ts
|
|
13512
14500
|
var UNSUPPORTED_KEYWORDS = ["if", "then", "else", "allOf", "not", "patternProperties", "additionalProperties"];
|
|
@@ -13657,6 +14645,7 @@ var FIELD_WEIGHTS = {
|
|
|
13657
14645
|
description: 5,
|
|
13658
14646
|
keywords: 5
|
|
13659
14647
|
};
|
|
14648
|
+
var searchCache = /* @__PURE__ */ new WeakMap();
|
|
13660
14649
|
function resolveSearchKeywords(definition, toolOriginalName, serverName, globalPrefix) {
|
|
13661
14650
|
const map = definition?.searchKeywords;
|
|
13662
14651
|
if (!map || typeof map !== "object" || Array.isArray(map)) return [];
|
|
@@ -13682,23 +14671,30 @@ function normalizeSearchText(value) {
|
|
|
13682
14671
|
function tokenize(value) {
|
|
13683
14672
|
return normalizeSearchText(value).split(/[^a-z0-9]+/).filter(Boolean);
|
|
13684
14673
|
}
|
|
13685
|
-
function
|
|
13686
|
-
const normalizedQuery = normalizeSearchText(query).trim();
|
|
13687
|
-
const queryTokens = tokenize(query);
|
|
13688
|
-
if (queryTokens.length === 0) return null;
|
|
14674
|
+
function prepareToolSearch(tool, server2, keywords) {
|
|
13689
14675
|
const fields = {
|
|
13690
14676
|
name: normalizeSearchText(tool.name),
|
|
13691
14677
|
originalName: normalizeSearchText(tool.originalName),
|
|
13692
14678
|
server: normalizeSearchText(server2),
|
|
13693
14679
|
description: normalizeSearchText(tool.description)
|
|
13694
14680
|
};
|
|
14681
|
+
const preparedFields = Object.entries(fields).map(([field, value]) => [field, value, tokenize(value)]);
|
|
14682
|
+
const keywordPhrases = keywords?.map((keyword) => normalizeSearchText(keyword).trim()).filter(Boolean) ?? [];
|
|
14683
|
+
return {
|
|
14684
|
+
tool,
|
|
14685
|
+
fields: preparedFields,
|
|
14686
|
+
nameTokens: preparedFields[0][2],
|
|
14687
|
+
keywordPhrases,
|
|
14688
|
+
keywordTokens: keywordPhrases.flatMap(tokenize)
|
|
14689
|
+
};
|
|
14690
|
+
}
|
|
14691
|
+
function scorePreparedToolMatch(prepared, normalizedQuery, queryTokens) {
|
|
13695
14692
|
let score = 0;
|
|
13696
14693
|
let phraseMatched = false;
|
|
13697
14694
|
let wholeFieldExact = false;
|
|
13698
14695
|
const matchedTokens = /* @__PURE__ */ new Set();
|
|
13699
|
-
for (const [field, value] of
|
|
14696
|
+
for (const [field, value, fieldTokens] of prepared.fields) {
|
|
13700
14697
|
const weight = FIELD_WEIGHTS[field];
|
|
13701
|
-
const fieldTokens = tokenize(value);
|
|
13702
14698
|
if (value === normalizedQuery) {
|
|
13703
14699
|
score += weight * 14;
|
|
13704
14700
|
phraseMatched = true;
|
|
@@ -13723,11 +14719,10 @@ function scoreToolMatch(tool, server2, query, keywords) {
|
|
|
13723
14719
|
}
|
|
13724
14720
|
}
|
|
13725
14721
|
}
|
|
13726
|
-
if (
|
|
14722
|
+
if (prepared.keywordPhrases.length > 0) {
|
|
13727
14723
|
const weight = FIELD_WEIGHTS.keywords;
|
|
13728
|
-
const phrases = keywords.map((keyword) => normalizeSearchText(keyword).trim()).filter(Boolean);
|
|
13729
14724
|
let phraseScore = 0;
|
|
13730
|
-
for (const phrase of
|
|
14725
|
+
for (const phrase of prepared.keywordPhrases) {
|
|
13731
14726
|
if (phrase === normalizedQuery) {
|
|
13732
14727
|
phraseScore = Math.max(phraseScore, weight * 14);
|
|
13733
14728
|
phraseMatched = true;
|
|
@@ -13741,15 +14736,14 @@ function scoreToolMatch(tool, server2, query, keywords) {
|
|
|
13741
14736
|
}
|
|
13742
14737
|
}
|
|
13743
14738
|
score += phraseScore;
|
|
13744
|
-
const keywordTokens = phrases.flatMap(tokenize);
|
|
13745
14739
|
for (const token of queryTokens) {
|
|
13746
|
-
if (keywordTokens.includes(token)) {
|
|
14740
|
+
if (prepared.keywordTokens.includes(token)) {
|
|
13747
14741
|
score += weight * 4;
|
|
13748
14742
|
matchedTokens.add(token);
|
|
13749
|
-
} else if (keywordTokens.some((keywordToken) => keywordToken.startsWith(token) || keywordToken.length >= MIN_STEM_LENGTH && token.startsWith(keywordToken))) {
|
|
14743
|
+
} else if (prepared.keywordTokens.some((keywordToken) => keywordToken.startsWith(token) || keywordToken.length >= MIN_STEM_LENGTH && token.startsWith(keywordToken))) {
|
|
13750
14744
|
score += weight * 2;
|
|
13751
14745
|
matchedTokens.add(token);
|
|
13752
|
-
} else if (
|
|
14746
|
+
} else if (prepared.keywordPhrases.some((phrase) => phrase.includes(token))) {
|
|
13753
14747
|
score += weight;
|
|
13754
14748
|
matchedTokens.add(token);
|
|
13755
14749
|
}
|
|
@@ -13759,22 +14753,47 @@ function scoreToolMatch(tool, server2, query, keywords) {
|
|
|
13759
14753
|
if (!phraseMatched && (queryTokens.length <= 2 ? coverage !== 1 : coverage < 0.6)) return null;
|
|
13760
14754
|
score += coverage === 1 ? 25 : Math.round(coverage * 10);
|
|
13761
14755
|
const firstQueryToken = queryTokens[0];
|
|
13762
|
-
if (firstQueryToken !== void 0 &&
|
|
14756
|
+
if (firstQueryToken !== void 0 && prepared.nameTokens.includes(firstQueryToken)) score += 8;
|
|
13763
14757
|
if (wholeFieldExact) score += 20;
|
|
13764
14758
|
return score;
|
|
13765
14759
|
}
|
|
14760
|
+
function getPreparedTools(state, serverName, metadata, definition, globalPrefix, includeKeywords) {
|
|
14761
|
+
let stateCache = searchCache.get(state);
|
|
14762
|
+
if (!stateCache) {
|
|
14763
|
+
stateCache = /* @__PURE__ */ new Map();
|
|
14764
|
+
searchCache.set(state, stateCache);
|
|
14765
|
+
}
|
|
14766
|
+
const toolPrefix = resolveToolPrefix(definition, globalPrefix);
|
|
14767
|
+
let cached = stateCache.get(serverName);
|
|
14768
|
+
if (cached?.metadata !== metadata || cached.searchKeywords !== definition?.searchKeywords || cached.toolPrefix !== toolPrefix) {
|
|
14769
|
+
cached = { metadata, searchKeywords: definition?.searchKeywords, toolPrefix };
|
|
14770
|
+
stateCache.set(serverName, cached);
|
|
14771
|
+
}
|
|
14772
|
+
const cacheKey = includeKeywords ? "withKeywords" : "withoutKeywords";
|
|
14773
|
+
let prepared = cached[cacheKey];
|
|
14774
|
+
if (!prepared) {
|
|
14775
|
+
prepared = metadata.map((tool) => prepareToolSearch(
|
|
14776
|
+
tool,
|
|
14777
|
+
serverName,
|
|
14778
|
+
includeKeywords && definition?.searchKeywords !== void 0 ? resolveSearchKeywords(definition, tool.originalName, serverName, globalPrefix) : void 0
|
|
14779
|
+
));
|
|
14780
|
+
cached[cacheKey] = prepared;
|
|
14781
|
+
}
|
|
14782
|
+
return prepared;
|
|
14783
|
+
}
|
|
13766
14784
|
function rankToolMatches(state, query, server2, includeKeywords = true) {
|
|
13767
14785
|
const matches = [];
|
|
14786
|
+
const normalizedQuery = normalizeSearchText(query).trim();
|
|
14787
|
+
const queryTokens = tokenize(query);
|
|
14788
|
+
if (queryTokens.length === 0) return matches;
|
|
13768
14789
|
const globalPrefix = state.config.settings?.toolPrefix ?? "server";
|
|
13769
14790
|
for (const [serverName, metadata] of state.toolMetadata.entries()) {
|
|
13770
14791
|
if (server2 && serverName !== server2) continue;
|
|
13771
14792
|
const definition = state.config.mcpServers[serverName];
|
|
13772
14793
|
if (isServerDisabled(definition)) continue;
|
|
13773
|
-
const
|
|
13774
|
-
|
|
13775
|
-
|
|
13776
|
-
const score = scoreToolMatch(tool, serverName, query, keywords);
|
|
13777
|
-
if (score !== null) matches.push({ server: serverName, tool, score });
|
|
14794
|
+
for (const prepared of getPreparedTools(state, serverName, metadata, definition, globalPrefix, includeKeywords)) {
|
|
14795
|
+
const score = scorePreparedToolMatch(prepared, normalizedQuery, queryTokens);
|
|
14796
|
+
if (score !== null) matches.push({ server: serverName, tool: prepared.tool, score });
|
|
13778
14797
|
}
|
|
13779
14798
|
}
|
|
13780
14799
|
return matches.sort((a, b) => b.score - a.score || a.tool.name.localeCompare(b.tool.name));
|
|
@@ -13799,7 +14818,7 @@ function rankSuggestions(state, name, limit) {
|
|
|
13799
14818
|
}
|
|
13800
14819
|
|
|
13801
14820
|
// packages/coding-agent/src/humain/mcp-adapter/vendor/proxy-modes.ts
|
|
13802
|
-
var
|
|
14821
|
+
var require5 = createRequire6(import.meta.url);
|
|
13803
14822
|
var MAX_REGEX_SEARCH_QUERY_LENGTH = 256;
|
|
13804
14823
|
var INSTRUCTIONS_PREVIEW_LENGTH = 300;
|
|
13805
14824
|
var REGEX_SAFETY_CHECK_PARAMS = {
|
|
@@ -14222,7 +15241,7 @@ function executeSearch(state, query, regex, server2, includeSchemas, limit = 12,
|
|
|
14222
15241
|
pattern = new RegExp(query, "i");
|
|
14223
15242
|
let safety;
|
|
14224
15243
|
try {
|
|
14225
|
-
const { checkSync } =
|
|
15244
|
+
const { checkSync } = require5("recheck");
|
|
14226
15245
|
safety = checkSync(query, "i", REGEX_SAFETY_CHECK_PARAMS);
|
|
14227
15246
|
} catch (error) {
|
|
14228
15247
|
const reason = error instanceof Error ? error.message : String(error);
|
|
@@ -14782,11 +15801,12 @@ async function executeCall(state, toolName, args, serverOverride, getPiTools, si
|
|
|
14782
15801
|
if (isServerDisabled(state.config.mcpServers[serverName])) {
|
|
14783
15802
|
return disabledCallResult(serverName, toolMeta);
|
|
14784
15803
|
}
|
|
15804
|
+
const normalizedArgs = toolMeta.resourceUri ? args ?? {} : normalizeToolArguments(args);
|
|
14785
15805
|
const approval = await ensureToolCallApproved(
|
|
14786
15806
|
state,
|
|
14787
15807
|
serverName,
|
|
14788
15808
|
toolMeta,
|
|
14789
|
-
|
|
15809
|
+
normalizedArgs,
|
|
14790
15810
|
ownedSignal,
|
|
14791
15811
|
origin ?? (toolMeta.resourceUri ? "resource" : "proxy")
|
|
14792
15812
|
);
|
|
@@ -14854,7 +15874,7 @@ async function executeCall(state, toolName, args, serverOverride, getPiTools, si
|
|
|
14854
15874
|
uiSession = toolMeta.uiResourceUri ? await maybeStartUiSession(state, {
|
|
14855
15875
|
serverName,
|
|
14856
15876
|
toolName: toolMeta.originalName,
|
|
14857
|
-
toolArgs:
|
|
15877
|
+
toolArgs: normalizedArgs,
|
|
14858
15878
|
uiResourceUri: toolMeta.uiResourceUri,
|
|
14859
15879
|
...toolMeta.uiStreamMode !== void 0 ? { streamMode: toolMeta.uiStreamMode } : {},
|
|
14860
15880
|
...signal ? { signal } : {},
|
|
@@ -14870,7 +15890,7 @@ async function executeCall(state, toolName, args, serverOverride, getPiTools, si
|
|
|
14870
15890
|
serverName,
|
|
14871
15891
|
(conn) => abortable(conn.client.callTool({
|
|
14872
15892
|
name: toolMeta.originalName,
|
|
14873
|
-
arguments:
|
|
15893
|
+
arguments: normalizedArgs,
|
|
14874
15894
|
_meta: uiSession?.requestMeta
|
|
14875
15895
|
}, requestOptions), ownedSignal)
|
|
14876
15896
|
);
|
|
@@ -14974,6 +15994,7 @@ init_utils();
|
|
|
14974
15994
|
import { Text, truncateToWidth as truncateToWidth3, visibleWidth as visibleWidth3 } from "@earendil-works/pi-tui";
|
|
14975
15995
|
var plainTheme = { fg: (_name, text) => text };
|
|
14976
15996
|
var DEFAULT_MAX_CALL_INPUT_CHARS = 1500;
|
|
15997
|
+
var DEFAULT_MAX_COMPACT_INPUT_CHARS = 240;
|
|
14977
15998
|
var DEFAULT_BOXED_COLLAPSED_LINES = 3;
|
|
14978
15999
|
var DEFAULT_COMPACT_COLLAPSED_LINES = 1;
|
|
14979
16000
|
var DEFAULT_MAX_COLLAPSED_CHARS = 8e3;
|
|
@@ -14986,8 +16007,9 @@ var EmptyComponent = class {
|
|
|
14986
16007
|
}
|
|
14987
16008
|
};
|
|
14988
16009
|
var CompactMcpToolResult = class {
|
|
14989
|
-
constructor(title, display, theme) {
|
|
16010
|
+
constructor(title, inputPreview, display, theme) {
|
|
14990
16011
|
this.title = title;
|
|
16012
|
+
this.inputPreview = inputPreview;
|
|
14991
16013
|
this.display = display;
|
|
14992
16014
|
this.theme = theme;
|
|
14993
16015
|
this.rendered = null;
|
|
@@ -15000,7 +16022,7 @@ var CompactMcpToolResult = class {
|
|
|
15000
16022
|
});
|
|
15001
16023
|
const lines = resultLines.length > 0 ? resultLines : [""];
|
|
15002
16024
|
const bodies = lines.map((line, index) => {
|
|
15003
|
-
const prefix = index === 0
|
|
16025
|
+
const prefix = index === 0 ? this.renderPrefix(safeWidth) : "";
|
|
15004
16026
|
return `${prefix}${this.theme.fg("toolOutput", line)}`;
|
|
15005
16027
|
});
|
|
15006
16028
|
const hiddenText = this.display.truncated || bodies.some((body) => visibleWidth3(body) > safeWidth);
|
|
@@ -15022,6 +16044,19 @@ var CompactMcpToolResult = class {
|
|
|
15022
16044
|
invalidate() {
|
|
15023
16045
|
this.rendered = null;
|
|
15024
16046
|
}
|
|
16047
|
+
renderPrefix(width) {
|
|
16048
|
+
if (!this.title) return "";
|
|
16049
|
+
const arrow = " \u2192 ";
|
|
16050
|
+
if (!this.inputPreview) return `${this.theme.fg("toolTitle", this.title)}${arrow}`;
|
|
16051
|
+
const maxPrefixWidth = Math.max(12, Math.floor(width * 0.55));
|
|
16052
|
+
const titleWidth = visibleWidth3(this.title);
|
|
16053
|
+
const inputWidth = Math.max(0, maxPrefixWidth - titleWidth - 1);
|
|
16054
|
+
if (inputWidth <= 3) {
|
|
16055
|
+
return `${this.theme.fg("toolTitle", truncateToWidth3(this.title, maxPrefixWidth, "\u2026"))}${arrow}`;
|
|
16056
|
+
}
|
|
16057
|
+
const input = truncateToWidth3(this.inputPreview, inputWidth, "\u2026");
|
|
16058
|
+
return `${this.theme.fg("toolTitle", this.title)} ${this.theme.fg("muted", input)}${arrow}`;
|
|
16059
|
+
}
|
|
15025
16060
|
};
|
|
15026
16061
|
var CollapsibleText = class {
|
|
15027
16062
|
constructor(text, expanded, maxCollapsedLines, ellipsis, expandHint, preTruncated = false) {
|
|
@@ -15122,6 +16157,9 @@ function renderToolCallLines(lines, theme) {
|
|
|
15122
16157
|
const styledRest = rest.map((line) => activeTheme.fg("muted", line));
|
|
15123
16158
|
return new Text([styledTitle, ...styledRest].join("\n"), 0, 0);
|
|
15124
16159
|
}
|
|
16160
|
+
function formatCompactInputPreview(lines, maxChars = DEFAULT_MAX_COMPACT_INPUT_CHARS) {
|
|
16161
|
+
return truncateText(lines.slice(1).join(" ").replace(/\s+/g, " ").trim(), maxChars);
|
|
16162
|
+
}
|
|
15125
16163
|
function resolveMcpToolRenderOptions(settings) {
|
|
15126
16164
|
const resultRendering = settings?.toolResultRendering === "boxed" ? "boxed" : "compact";
|
|
15127
16165
|
const collapsedLines = settings?.collapsedResultLines;
|
|
@@ -15135,7 +16173,10 @@ function shouldUseCompactFinalRender(options, context) {
|
|
|
15135
16173
|
return options.resultRendering === "compact" && context !== void 0 && context.isPartial === false && context.expanded !== true && context.isError !== true;
|
|
15136
16174
|
}
|
|
15137
16175
|
function renderToolCall(lines, theme, context, options) {
|
|
15138
|
-
if (context?.state)
|
|
16176
|
+
if (context?.state) {
|
|
16177
|
+
context.state.compactTitle = lines[0] ?? "mcp";
|
|
16178
|
+
context.state.compactInputPreview = formatCompactInputPreview(lines);
|
|
16179
|
+
}
|
|
15139
16180
|
if (shouldUseCompactFinalRender(options, context)) return new EmptyComponent();
|
|
15140
16181
|
return renderToolCallLines(lines, theme);
|
|
15141
16182
|
}
|
|
@@ -15161,6 +16202,18 @@ function collectCollapsedResultLines(content, maxLines, maxChars) {
|
|
|
15161
16202
|
let remainingChars = maxChars;
|
|
15162
16203
|
let truncated = false;
|
|
15163
16204
|
const appendLine = (line) => {
|
|
16205
|
+
if (lines.length === 0) {
|
|
16206
|
+
const previewWidth = Math.min(line.length, remainingChars);
|
|
16207
|
+
if (line.slice(0, previewWidth).trim() === "") {
|
|
16208
|
+
if (line.length >= remainingChars) {
|
|
16209
|
+
truncated = true;
|
|
16210
|
+
remainingChars = 0;
|
|
16211
|
+
return false;
|
|
16212
|
+
}
|
|
16213
|
+
remainingChars -= line.length + 1;
|
|
16214
|
+
return true;
|
|
16215
|
+
}
|
|
16216
|
+
}
|
|
15164
16217
|
if (lines.length >= maxLines || remainingChars <= 0) {
|
|
15165
16218
|
truncated = true;
|
|
15166
16219
|
return false;
|
|
@@ -15190,7 +16243,7 @@ function collectCollapsedResultLines(content, maxLines, maxChars) {
|
|
|
15190
16243
|
}
|
|
15191
16244
|
if (truncated) break;
|
|
15192
16245
|
}
|
|
15193
|
-
if (lines.length === 0) lines.push("");
|
|
16246
|
+
if (lines.length === 0) lines.push(truncated ? "(leading blank output omitted)" : "");
|
|
15194
16247
|
if (truncated && lines.length >= maxLines) lines.push("\u2026");
|
|
15195
16248
|
return { lines, truncated };
|
|
15196
16249
|
}
|
|
@@ -15221,7 +16274,8 @@ function renderMcpToolResult(result, options, theme, context, renderOptions = re
|
|
|
15221
16274
|
if (!expanded && renderOptions.resultRendering === "compact") {
|
|
15222
16275
|
const display2 = formatMcpToolResultLines(result, false, renderOptions.collapsedResultLines);
|
|
15223
16276
|
const title = context?.state?.compactTitle ?? formatMcpToolResultIdentity(result.details) ?? "";
|
|
15224
|
-
|
|
16277
|
+
const inputPreview = context?.state?.compactInputPreview ?? "";
|
|
16278
|
+
return new CompactMcpToolResult(title, inputPreview, display2, activeTheme);
|
|
15225
16279
|
}
|
|
15226
16280
|
const display = formatMcpToolResultLines(result, expanded, renderOptions.collapsedResultLines);
|
|
15227
16281
|
const identity = formatMcpToolResultIdentity(result.details);
|
|
@@ -15431,10 +16485,14 @@ async function runMcpScript(state, code, timeoutMs = DEFAULT_MCP_SCRIPT_TIMEOUT_
|
|
|
15431
16485
|
}
|
|
15432
16486
|
worker = new Worker(new URL("./mcp-script-worker.mjs", import.meta.url), {
|
|
15433
16487
|
workerData: { code },
|
|
15434
|
-
env: {}
|
|
16488
|
+
env: {},
|
|
16489
|
+
// The sandbox cannot open files, and the host always terminates this worker.
|
|
16490
|
+
// Disable Node's unmanaged FD bookkeeping, which emits false warnings when
|
|
16491
|
+
// short-lived workers are terminated on Node 24.
|
|
16492
|
+
trackUnmanagedFds: false
|
|
15435
16493
|
});
|
|
15436
16494
|
const activeWorker = worker;
|
|
15437
|
-
const execution = new Promise((
|
|
16495
|
+
const execution = new Promise((resolve7, reject) => {
|
|
15438
16496
|
let completed = false;
|
|
15439
16497
|
activeWorker.on("message", (value) => {
|
|
15440
16498
|
const message = parseWorkerMessage(value);
|
|
@@ -15446,7 +16504,7 @@ async function runMcpScript(state, code, timeoutMs = DEFAULT_MCP_SCRIPT_TIMEOUT_
|
|
|
15446
16504
|
if (message.type === "done") {
|
|
15447
16505
|
completed = true;
|
|
15448
16506
|
if ("returnBlock" in message) output.push(toContentBlock(message.returnBlock));
|
|
15449
|
-
|
|
16507
|
+
resolve7();
|
|
15450
16508
|
return;
|
|
15451
16509
|
}
|
|
15452
16510
|
if (message.type === "error") {
|
|
@@ -15531,13 +16589,14 @@ async function runMcpScript(state, code, timeoutMs = DEFAULT_MCP_SCRIPT_TIMEOUT_
|
|
|
15531
16589
|
init_types();
|
|
15532
16590
|
var INIT_WAIT_TIMEOUT_MS = 3e4;
|
|
15533
16591
|
var INIT_WAIT_TIMED_OUT = /* @__PURE__ */ Symbol("init-wait-timed-out");
|
|
16592
|
+
var runtimeRegistrars = /* @__PURE__ */ new WeakMap();
|
|
15534
16593
|
async function awaitWithTimeout(promise, timeoutMs) {
|
|
15535
16594
|
let timer;
|
|
15536
16595
|
try {
|
|
15537
16596
|
return await Promise.race([
|
|
15538
16597
|
promise,
|
|
15539
|
-
new Promise((
|
|
15540
|
-
timer = setTimeout(() =>
|
|
16598
|
+
new Promise((resolve7) => {
|
|
16599
|
+
timer = setTimeout(() => resolve7(INIT_WAIT_TIMED_OUT), timeoutMs);
|
|
15541
16600
|
timer.unref?.();
|
|
15542
16601
|
})
|
|
15543
16602
|
]);
|
|
@@ -15603,6 +16662,14 @@ function installMcpAdapter(pi, options) {
|
|
|
15603
16662
|
let proxyToolRegistered = false;
|
|
15604
16663
|
let proxyToolDescription = null;
|
|
15605
16664
|
let directToolsFrozen = false;
|
|
16665
|
+
const runtimeServers = /* @__PURE__ */ new Map();
|
|
16666
|
+
function attachRuntimeServerLifecycle(targetState, name, definition) {
|
|
16667
|
+
const lifecycleMode = definition.lifecycle ?? "lazy";
|
|
16668
|
+
const persistsAfterFirstSpawn = lifecycleMode === "eager" || lifecycleMode === "lazy-keep-alive";
|
|
16669
|
+
const idleOverride = definition.idleTimeout ?? (persistsAfterFirstSpawn ? 0 : void 0);
|
|
16670
|
+
targetState.lifecycle.registerServer(name, definition, idleOverride !== void 0 ? { idleTimeout: idleOverride } : void 0);
|
|
16671
|
+
if (lifecycleMode === "keep-alive") targetState.lifecycle.markKeepAlive(name, definition);
|
|
16672
|
+
}
|
|
15606
16673
|
const toToolParameters = (schema) => typeof Type.Unsafe === "function" ? Type.Unsafe(schema) : schema;
|
|
15607
16674
|
function directToolFingerprint(spec) {
|
|
15608
16675
|
return JSON.stringify({
|
|
@@ -15725,6 +16792,42 @@ function installMcpAdapter(pi, options) {
|
|
|
15725
16792
|
registerPromptCommands([...state?.promptMetadata?.values() ?? []].flat());
|
|
15726
16793
|
}
|
|
15727
16794
|
registerPromptCommands(resolveCachedPrompts(earlyConfig));
|
|
16795
|
+
runtimeRegistrars.set(pi, (name, definition) => {
|
|
16796
|
+
if (typeof name !== "string" || name.trim() === "") {
|
|
16797
|
+
throw new Error("MCP server name must be a non-empty string");
|
|
16798
|
+
}
|
|
16799
|
+
if (typeof definition !== "object" || definition === null || Array.isArray(definition)) {
|
|
16800
|
+
throw new Error(`MCP server definition for "${name}" must be an object`);
|
|
16801
|
+
}
|
|
16802
|
+
const effective = state?.config ?? earlyConfig;
|
|
16803
|
+
if (runtimeServers.has(name) || Object.hasOwn(effective.mcpServers, name)) {
|
|
16804
|
+
throw new Error(`MCP server "${name}" is already registered`);
|
|
16805
|
+
}
|
|
16806
|
+
const entry = { ...structuredClone(definition), directTools: false };
|
|
16807
|
+
runtimeServers.set(name, entry);
|
|
16808
|
+
const registeredState = state;
|
|
16809
|
+
if (registeredState) {
|
|
16810
|
+
registeredState.config.mcpServers[name] = entry;
|
|
16811
|
+
attachRuntimeServerLifecycle(registeredState, name, entry);
|
|
16812
|
+
syncToolSurface();
|
|
16813
|
+
updateStatusBar(registeredState);
|
|
16814
|
+
}
|
|
16815
|
+
let disposed = false;
|
|
16816
|
+
return {
|
|
16817
|
+
dispose: async () => {
|
|
16818
|
+
if (disposed) return;
|
|
16819
|
+
disposed = true;
|
|
16820
|
+
runtimeServers.delete(name);
|
|
16821
|
+
const currentState = state;
|
|
16822
|
+
if (!currentState || currentState.config.mcpServers[name] !== entry) return;
|
|
16823
|
+
delete currentState.config.mcpServers[name];
|
|
16824
|
+
currentState.lifecycle.unregisterServer(name);
|
|
16825
|
+
await currentState.manager.close(name);
|
|
16826
|
+
syncToolSurface();
|
|
16827
|
+
updateStatusBar(currentState);
|
|
16828
|
+
}
|
|
16829
|
+
};
|
|
16830
|
+
});
|
|
15728
16831
|
const getPiTools = () => pi.getAllTools();
|
|
15729
16832
|
pi.registerFlag("mcp-config", {
|
|
15730
16833
|
description: "Path to MCP config file",
|
|
@@ -15737,8 +16840,7 @@ function installMcpAdapter(pi, options) {
|
|
|
15737
16840
|
...earlyConfigPath !== void 0 ? { configPath: earlyConfigPath } : {},
|
|
15738
16841
|
...sessionConfig !== void 0 ? { config: sessionConfig } : {}
|
|
15739
16842
|
} : {},
|
|
15740
|
-
oauthRuntime
|
|
15741
|
-
statusEvents: pi.events
|
|
16843
|
+
oauthRuntime
|
|
15742
16844
|
});
|
|
15743
16845
|
initPromise = promise;
|
|
15744
16846
|
return promise.then(async (nextState) => {
|
|
@@ -15751,6 +16853,14 @@ function installMcpAdapter(pi, options) {
|
|
|
15751
16853
|
return;
|
|
15752
16854
|
}
|
|
15753
16855
|
state = nextState;
|
|
16856
|
+
for (const [name, definition] of runtimeServers) {
|
|
16857
|
+
if (Object.hasOwn(nextState.config.mcpServers, name)) {
|
|
16858
|
+
console.error(`MCP: runtime-registered server "${name}" now collides with a configured server; keeping the configured server`);
|
|
16859
|
+
continue;
|
|
16860
|
+
}
|
|
16861
|
+
nextState.config.mcpServers[name] = definition;
|
|
16862
|
+
attachRuntimeServerLifecycle(nextState, name, definition);
|
|
16863
|
+
}
|
|
15754
16864
|
nextState.onToolMetadataUpdated = (_serverName, _reason) => {
|
|
15755
16865
|
if (state !== nextState || !owner.isActive()) return;
|
|
15756
16866
|
syncPromptCommands();
|
|
@@ -15762,6 +16872,7 @@ function installMcpAdapter(pi, options) {
|
|
|
15762
16872
|
};
|
|
15763
16873
|
syncPromptCommands();
|
|
15764
16874
|
syncToolSurface(ctx);
|
|
16875
|
+
nextState.statusEvents = pi.events;
|
|
15765
16876
|
updateStatusBar(nextState);
|
|
15766
16877
|
initPromise = null;
|
|
15767
16878
|
if (earlyConfig.settings?.freezeDirectTools === true) {
|
|
@@ -15845,6 +16956,26 @@ function installMcpAdapter(pi, options) {
|
|
|
15845
16956
|
}
|
|
15846
16957
|
}
|
|
15847
16958
|
});
|
|
16959
|
+
pi.on("input", async () => {
|
|
16960
|
+
const inputOwner = currentOwner;
|
|
16961
|
+
if (!inputOwner?.isActive()) return;
|
|
16962
|
+
if (!state && initPromise) {
|
|
16963
|
+
try {
|
|
16964
|
+
await awaitWithTimeout(initPromise, INIT_WAIT_TIMEOUT_MS);
|
|
16965
|
+
} catch {
|
|
16966
|
+
return;
|
|
16967
|
+
}
|
|
16968
|
+
}
|
|
16969
|
+
const inputState = state;
|
|
16970
|
+
if (!inputState || !inputOwner.isActive()) return;
|
|
16971
|
+
try {
|
|
16972
|
+
await inputState.lifecycle.ensureConverged(inputOwner.signal);
|
|
16973
|
+
} catch (error) {
|
|
16974
|
+
if (!isAbortError(error, inputOwner.signal)) {
|
|
16975
|
+
logger.debug(`MCP: keep-alive convergence failed before input: ${formatTerminalError(error)}`);
|
|
16976
|
+
}
|
|
16977
|
+
}
|
|
16978
|
+
});
|
|
15848
16979
|
pi.on("session_shutdown", async () => {
|
|
15849
16980
|
++lifecycleGeneration;
|
|
15850
16981
|
const currentState = state;
|
|
@@ -15866,7 +16997,7 @@ function installMcpAdapter(pi, options) {
|
|
|
15866
16997
|
}
|
|
15867
16998
|
});
|
|
15868
16999
|
pi.on("tool_result", (event) => toolErrorOverride(event.details));
|
|
15869
|
-
pi.registerCommand(
|
|
17000
|
+
const registerMcpCommand = (commandName) => pi.registerCommand(commandName, {
|
|
15870
17001
|
description: "Show MCP server status",
|
|
15871
17002
|
getArgumentCompletions: (prefix) => {
|
|
15872
17003
|
const normalized = prefix.trimStart();
|
|
@@ -15878,6 +17009,7 @@ function installMcpAdapter(pi, options) {
|
|
|
15878
17009
|
{ value: "prompts", label: "prompts \u2014 List all MCP prompts" },
|
|
15879
17010
|
{ value: "setup", label: "setup \u2014 Configure MCP servers" },
|
|
15880
17011
|
{ value: "logout", label: "logout \u2014 Clear server credentials" },
|
|
17012
|
+
{ value: "token", label: "token \u2014 Manage stored bearer tokens" },
|
|
15881
17013
|
{ value: "disable", label: "disable \u2014 Disable a server" },
|
|
15882
17014
|
{ value: "enable", label: "enable \u2014 Enable a server" },
|
|
15883
17015
|
{ value: "status", label: "status \u2014 Show server status" }
|
|
@@ -15885,7 +17017,18 @@ function installMcpAdapter(pi, options) {
|
|
|
15885
17017
|
return subcommands.length > 0 ? subcommands : null;
|
|
15886
17018
|
}
|
|
15887
17019
|
const [, subcommand, argumentPrefix] = argumentMatch;
|
|
15888
|
-
if (subcommand !== "reconnect" && subcommand !== "logout" && subcommand !== "disable" && subcommand !== "enable" || argumentPrefix === void 0 || !state) return null;
|
|
17020
|
+
if (subcommand !== "reconnect" && subcommand !== "logout" && subcommand !== "disable" && subcommand !== "enable" && subcommand !== "token" || argumentPrefix === void 0 || !state) return null;
|
|
17021
|
+
if (subcommand === "token") {
|
|
17022
|
+
const tokenMatch = argumentPrefix.trimStart().match(/^(set|remove|status)\s+(.*)$/);
|
|
17023
|
+
if (!tokenMatch) {
|
|
17024
|
+
const actions = ["set", "remove", "status"].filter((action2) => action2.startsWith(argumentPrefix.trimStart())).map((action2) => ({ value: `token ${action2} `, label: `${action2} \u2014 Bearer token ${action2}` }));
|
|
17025
|
+
return actions.length > 0 ? actions : null;
|
|
17026
|
+
}
|
|
17027
|
+
const action = tokenMatch[1] ?? "";
|
|
17028
|
+
const serverPrefix = tokenMatch[2] ?? "";
|
|
17029
|
+
const servers2 = Object.keys(state.config.mcpServers).filter((serverName) => serverName.startsWith(serverPrefix.trimStart())).map((serverName) => ({ value: `token ${action} ${serverName}`, label: serverName }));
|
|
17030
|
+
return servers2.length > 0 ? servers2 : null;
|
|
17031
|
+
}
|
|
15889
17032
|
const servers = Object.keys(state.config.mcpServers).filter((serverName) => serverName.startsWith(argumentPrefix.trimStart())).map((serverName) => ({ value: `${subcommand} ${serverName}`, label: serverName }));
|
|
15890
17033
|
return servers.length > 0 ? servers : null;
|
|
15891
17034
|
},
|
|
@@ -15956,6 +17099,21 @@ function installMcpAdapter(pi, options) {
|
|
|
15956
17099
|
await logoutServer(serverName, state, commandCtx);
|
|
15957
17100
|
break;
|
|
15958
17101
|
}
|
|
17102
|
+
case "token": {
|
|
17103
|
+
const action = parts[1];
|
|
17104
|
+
const serverName = parts.slice(2).join(" ");
|
|
17105
|
+
if (action !== "set" && action !== "remove" && action !== "status") {
|
|
17106
|
+
if (commandCtx.hasUI) commandCtx.ui?.notify("Usage: /mcp token set|remove|status <server>", "error");
|
|
17107
|
+
return;
|
|
17108
|
+
}
|
|
17109
|
+
if (!serverName) {
|
|
17110
|
+
if (commandCtx.hasUI) commandCtx.ui?.notify("Usage: /mcp token set|remove|status <server>", "error");
|
|
17111
|
+
return;
|
|
17112
|
+
}
|
|
17113
|
+
commandOwner?.throwIfInactive();
|
|
17114
|
+
await manageBearerToken(action, serverName, state, commandCtx);
|
|
17115
|
+
break;
|
|
17116
|
+
}
|
|
15959
17117
|
case "disable":
|
|
15960
17118
|
case "enable": {
|
|
15961
17119
|
const serverName = rest;
|
|
@@ -16006,6 +17164,8 @@ function installMcpAdapter(pi, options) {
|
|
|
16006
17164
|
}
|
|
16007
17165
|
}
|
|
16008
17166
|
});
|
|
17167
|
+
registerMcpCommand("mcp");
|
|
17168
|
+
registerMcpCommand("pi-mcp");
|
|
16009
17169
|
pi.registerCommand("mcp-auth", {
|
|
16010
17170
|
description: "Authenticate with an MCP server (OAuth)",
|
|
16011
17171
|
handler: async (args, ctx) => {
|
|
@@ -16127,12 +17287,12 @@ function installMcpAdapter(pi, options) {
|
|
|
16127
17287
|
renderResult: renderMcpToolResult2,
|
|
16128
17288
|
async execute(_toolCallId, params, signal, _onUpdate, _ctx) {
|
|
16129
17289
|
const executeOwner = currentOwner;
|
|
16130
|
-
|
|
16131
|
-
|
|
17290
|
+
const parseArgs = (value) => {
|
|
17291
|
+
if (value === void 0 || value === "") return void 0;
|
|
16132
17292
|
let args;
|
|
16133
|
-
if (typeof
|
|
17293
|
+
if (typeof value === "string") {
|
|
16134
17294
|
try {
|
|
16135
|
-
args = JSON.parse(
|
|
17295
|
+
args = JSON.parse(value);
|
|
16136
17296
|
} catch (error) {
|
|
16137
17297
|
if (error instanceof SyntaxError) {
|
|
16138
17298
|
throw new Error(`Invalid args JSON: ${error.message}`, { cause: error });
|
|
@@ -16140,13 +17300,49 @@ function installMcpAdapter(pi, options) {
|
|
|
16140
17300
|
throw error;
|
|
16141
17301
|
}
|
|
16142
17302
|
} else {
|
|
16143
|
-
args =
|
|
17303
|
+
args = value;
|
|
16144
17304
|
}
|
|
16145
17305
|
if (typeof args !== "object" || args === null || Array.isArray(args)) {
|
|
16146
17306
|
const gotType = Array.isArray(args) ? "array" : args === null ? "null" : typeof args;
|
|
16147
17307
|
throw new Error(`Invalid args: expected a JSON object, got ${gotType}`);
|
|
16148
17308
|
}
|
|
16149
|
-
|
|
17309
|
+
return args;
|
|
17310
|
+
};
|
|
17311
|
+
const validateNestedGatewayParams = (value) => {
|
|
17312
|
+
for (const key of ["tool", "connect", "describe", "instructions", "search", "server", "action"]) {
|
|
17313
|
+
if (value[key] !== void 0 && typeof value[key] !== "string") {
|
|
17314
|
+
throw new Error(`Invalid nested gateway param \`${key}\`: expected string, got ${Array.isArray(value[key]) ? "array" : typeof value[key]}`);
|
|
17315
|
+
}
|
|
17316
|
+
}
|
|
17317
|
+
for (const key of ["regex", "includeSchemas"]) {
|
|
17318
|
+
if (value[key] !== void 0 && typeof value[key] !== "boolean") {
|
|
17319
|
+
throw new Error(`Invalid nested gateway param \`${key}\`: expected boolean, got ${Array.isArray(value[key]) ? "array" : typeof value[key]}`);
|
|
17320
|
+
}
|
|
17321
|
+
}
|
|
17322
|
+
for (const key of ["limit", "offset"]) {
|
|
17323
|
+
if (value[key] !== void 0 && typeof value[key] !== "number") {
|
|
17324
|
+
throw new Error(`Invalid nested gateway param \`${key}\`: expected number, got ${Array.isArray(value[key]) ? "array" : typeof value[key]}`);
|
|
17325
|
+
}
|
|
17326
|
+
}
|
|
17327
|
+
const args = value.args;
|
|
17328
|
+
if (args !== void 0 && typeof args !== "string" && (typeof args !== "object" || args === null || Array.isArray(args))) {
|
|
17329
|
+
throw new Error(`Invalid nested gateway param \`args\`: expected JSON object or JSON string, got ${Array.isArray(args) ? "array" : args === null ? "null" : typeof args}`);
|
|
17330
|
+
}
|
|
17331
|
+
return value;
|
|
17332
|
+
};
|
|
17333
|
+
let parsedArgs = parseArgs(params.args);
|
|
17334
|
+
let dispatchParams = params;
|
|
17335
|
+
const hasGatewayMode = (value) => value.tool !== void 0 || value.connect !== void 0 || value.describe !== void 0 || value.instructions !== void 0 || value.search !== void 0 || value.server !== void 0 || value.action !== void 0;
|
|
17336
|
+
if (!hasGatewayMode(params) && parsedArgs) {
|
|
17337
|
+
const nestedParams = validateNestedGatewayParams(parsedArgs);
|
|
17338
|
+
if (hasGatewayMode(nestedParams)) {
|
|
17339
|
+
dispatchParams = nestedParams;
|
|
17340
|
+
parsedArgs = parseArgs(nestedParams.args);
|
|
17341
|
+
} else {
|
|
17342
|
+
throw new Error('Gateway params were nested inside `args`; pass them top-level (for example, mcp({ search: "..." }) or mcp({ tool: "...", args: {} })).');
|
|
17343
|
+
}
|
|
17344
|
+
} else if (!hasGatewayMode(params) && params.args !== void 0) {
|
|
17345
|
+
throw new Error('Gateway params were nested inside `args`; pass them top-level (for example, mcp({ search: "..." }) or mcp({ tool: "...", args: {} })).');
|
|
16150
17346
|
}
|
|
16151
17347
|
if (!state && initPromise) {
|
|
16152
17348
|
try {
|
|
@@ -16175,20 +17371,20 @@ function installMcpAdapter(pi, options) {
|
|
|
16175
17371
|
};
|
|
16176
17372
|
}
|
|
16177
17373
|
executeOwner?.throwIfInactive();
|
|
16178
|
-
if (
|
|
17374
|
+
if (dispatchParams.action === "ui-messages") {
|
|
16179
17375
|
return executeUiMessages(state);
|
|
16180
17376
|
}
|
|
16181
|
-
if (
|
|
16182
|
-
if (!
|
|
17377
|
+
if (dispatchParams.action === "auth-start") {
|
|
17378
|
+
if (!dispatchParams.server) {
|
|
16183
17379
|
return {
|
|
16184
17380
|
content: [{ type: "text", text: 'auth-start requires `server`. Example: mcp({ action: "auth-start", server: "linear-server" })' }],
|
|
16185
17381
|
details: { mode: "auth-start", error: "missing_server" }
|
|
16186
17382
|
};
|
|
16187
17383
|
}
|
|
16188
|
-
return signal ? executeAuthStart(state,
|
|
17384
|
+
return signal ? executeAuthStart(state, dispatchParams.server, signal) : executeAuthStart(state, dispatchParams.server);
|
|
16189
17385
|
}
|
|
16190
|
-
if (
|
|
16191
|
-
if (!
|
|
17386
|
+
if (dispatchParams.action === "auth-complete") {
|
|
17387
|
+
if (!dispatchParams.server) {
|
|
16192
17388
|
return {
|
|
16193
17389
|
content: [{ type: "text", text: "auth-complete requires `server`." }],
|
|
16194
17390
|
details: { mode: "auth-complete", error: "missing_server" }
|
|
@@ -16201,27 +17397,27 @@ function installMcpAdapter(pi, options) {
|
|
|
16201
17397
|
details: { mode: "auth-complete", error: "missing_input" }
|
|
16202
17398
|
};
|
|
16203
17399
|
}
|
|
16204
|
-
return signal ? executeAuthComplete(state,
|
|
17400
|
+
return signal ? executeAuthComplete(state, dispatchParams.server, input, signal) : executeAuthComplete(state, dispatchParams.server, input);
|
|
16205
17401
|
}
|
|
16206
|
-
if (
|
|
16207
|
-
return executeCall(state,
|
|
17402
|
+
if (dispatchParams.tool) {
|
|
17403
|
+
return executeCall(state, dispatchParams.tool, parsedArgs, dispatchParams.server, getPiTools, signal);
|
|
16208
17404
|
}
|
|
16209
|
-
if (
|
|
16210
|
-
const result = await executeConnect(state,
|
|
17405
|
+
if (dispatchParams.connect) {
|
|
17406
|
+
const result = await executeConnect(state, dispatchParams.connect, signal);
|
|
16211
17407
|
syncToolSurface(_ctx);
|
|
16212
17408
|
return result;
|
|
16213
17409
|
}
|
|
16214
|
-
if (
|
|
16215
|
-
return executeDescribe(state,
|
|
17410
|
+
if (dispatchParams.describe) {
|
|
17411
|
+
return executeDescribe(state, dispatchParams.describe);
|
|
16216
17412
|
}
|
|
16217
|
-
if (
|
|
16218
|
-
return executeInstructions(state,
|
|
17413
|
+
if (dispatchParams.instructions) {
|
|
17414
|
+
return executeInstructions(state, dispatchParams.instructions);
|
|
16219
17415
|
}
|
|
16220
|
-
if (
|
|
16221
|
-
return executeSearch(state,
|
|
17416
|
+
if (dispatchParams.search !== void 0) {
|
|
17417
|
+
return executeSearch(state, dispatchParams.search, dispatchParams.regex, dispatchParams.server, dispatchParams.includeSchemas, dispatchParams.limit, dispatchParams.offset);
|
|
16222
17418
|
}
|
|
16223
|
-
if (
|
|
16224
|
-
return executeList(state,
|
|
17419
|
+
if (dispatchParams.server) {
|
|
17420
|
+
return executeList(state, dispatchParams.server);
|
|
16225
17421
|
}
|
|
16226
17422
|
return executeStatus(state);
|
|
16227
17423
|
}
|
|
@@ -16269,11 +17465,20 @@ function createMcpAdapter(options = {}) {
|
|
|
16269
17465
|
});
|
|
16270
17466
|
};
|
|
16271
17467
|
}
|
|
17468
|
+
function registerMcpServer(options) {
|
|
17469
|
+
const { pi, name, definition } = options;
|
|
17470
|
+
const register = runtimeRegistrars.get(pi);
|
|
17471
|
+
if (!register) {
|
|
17472
|
+
throw new Error("pi-mcp-adapter is not installed for this Pi instance");
|
|
17473
|
+
}
|
|
17474
|
+
return register(name, definition);
|
|
17475
|
+
}
|
|
16272
17476
|
var index_default = createMcpAdapter();
|
|
16273
17477
|
export {
|
|
16274
17478
|
MCP_STATUS_EVENT,
|
|
16275
17479
|
MCP_STATUS_SNAPSHOT_VERSION,
|
|
16276
17480
|
MCP_TOOL_APPROVAL_REQUEST_EVENT,
|
|
16277
17481
|
createMcpAdapter,
|
|
16278
|
-
index_default as default
|
|
17482
|
+
index_default as default,
|
|
17483
|
+
registerMcpServer
|
|
16279
17484
|
};
|