@ashx-j/lunr 0.2.25 → 0.2.27
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 +31 -1
- package/LICENSE +22 -0
- package/dist/builtin-extensions/ashxj-thinking.d.ts +1 -1
- package/dist/builtin-extensions/ashxj-thinking.d.ts.map +1 -1
- package/dist/builtin-extensions/ashxj-thinking.js +1 -1
- package/dist/builtin-extensions/ashxj-thinking.js.map +1 -1
- package/dist/builtin-extensions/ashxj-tui.d.ts +11 -1
- package/dist/builtin-extensions/ashxj-tui.d.ts.map +1 -1
- package/dist/builtin-extensions/ashxj-tui.js +6 -10
- package/dist/builtin-extensions/ashxj-tui.js.map +1 -1
- package/dist/builtin-extensions/index.d.ts.map +1 -1
- package/dist/builtin-extensions/index.js +1 -0
- package/dist/builtin-extensions/index.js.map +1 -1
- package/dist/builtin-extensions/lunr-computer-use.d.ts +3 -0
- package/dist/builtin-extensions/lunr-computer-use.d.ts.map +1 -0
- package/dist/builtin-extensions/lunr-computer-use.js +179 -0
- package/dist/builtin-extensions/lunr-computer-use.js.map +1 -0
- package/dist/builtin-extensions/lunr-cron.d.ts +4 -5
- package/dist/builtin-extensions/lunr-cron.d.ts.map +1 -1
- package/dist/builtin-extensions/lunr-cron.js +94 -108
- package/dist/builtin-extensions/lunr-cron.js.map +1 -1
- package/dist/builtin-extensions/lunr-local-providers/local-servers.d.ts.map +1 -1
- package/dist/builtin-extensions/lunr-local-providers/local-servers.js +3 -1
- package/dist/builtin-extensions/lunr-local-providers/local-servers.js.map +1 -1
- package/dist/builtin-extensions/narumiruna-pi-goal/src/commands.d.ts.map +1 -1
- package/dist/builtin-extensions/narumiruna-pi-goal/src/commands.js +2 -2
- package/dist/builtin-extensions/narumiruna-pi-goal/src/commands.js.map +1 -1
- package/dist/builtin-extensions/narumiruna-pi-goal/src/goal.d.ts.map +1 -1
- package/dist/builtin-extensions/narumiruna-pi-goal/src/goal.js +1 -1
- package/dist/builtin-extensions/narumiruna-pi-goal/src/goal.js.map +1 -1
- package/dist/builtin-extensions/narumiruna-pi-goal/src/runtime.d.ts.map +1 -1
- package/dist/builtin-extensions/narumiruna-pi-goal/src/runtime.js +1 -1
- package/dist/builtin-extensions/narumiruna-pi-goal/src/runtime.js.map +1 -1
- package/dist/builtin-extensions/pi-intercom/index.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-intercom/index.js +2 -2
- package/dist/builtin-extensions/pi-intercom/index.js.map +1 -1
- package/dist/builtin-extensions/pi-lsp-extension/bemol-extension/index.d.ts +1 -1
- package/dist/builtin-extensions/pi-lsp-extension/bemol-extension/index.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-lsp-extension/bemol-extension/index.js +1 -1
- package/dist/builtin-extensions/pi-lsp-extension/bemol-extension/index.js.map +1 -1
- package/dist/builtin-extensions/pi-lsp-extension/src/index.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-lsp-extension/src/index.js +1 -15
- package/dist/builtin-extensions/pi-lsp-extension/src/index.js.map +1 -1
- package/dist/builtin-extensions/pi-lsp-extension/src/lsp-client.d.ts +6 -0
- package/dist/builtin-extensions/pi-lsp-extension/src/lsp-client.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-lsp-extension/src/lsp-client.js +187 -132
- package/dist/builtin-extensions/pi-lsp-extension/src/lsp-client.js.map +1 -1
- package/dist/builtin-extensions/pi-lsp-extension/src/lsp-manager.d.ts +8 -0
- package/dist/builtin-extensions/pi-lsp-extension/src/lsp-manager.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-lsp-extension/src/lsp-manager.js +142 -112
- package/dist/builtin-extensions/pi-lsp-extension/src/lsp-manager.js.map +1 -1
- package/dist/builtin-extensions/pi-lsp-extension/src/tools/code-rewrite.d.ts +12 -1
- package/dist/builtin-extensions/pi-lsp-extension/src/tools/code-rewrite.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-lsp-extension/src/tools/code-rewrite.js +14 -7
- package/dist/builtin-extensions/pi-lsp-extension/src/tools/code-rewrite.js.map +1 -1
- package/dist/builtin-extensions/pi-lsp-extension/src/tree-sitter/rewrite-engine.d.ts +11 -3
- package/dist/builtin-extensions/pi-lsp-extension/src/tree-sitter/rewrite-engine.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-lsp-extension/src/tree-sitter/rewrite-engine.js +67 -41
- package/dist/builtin-extensions/pi-lsp-extension/src/tree-sitter/rewrite-engine.js.map +1 -1
- package/dist/builtin-extensions/pi-lsp-extension/src/tree-sitter/search-engine.d.ts +4 -2
- package/dist/builtin-extensions/pi-lsp-extension/src/tree-sitter/search-engine.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-lsp-extension/src/tree-sitter/search-engine.js +3 -0
- package/dist/builtin-extensions/pi-lsp-extension/src/tree-sitter/search-engine.js.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/commands.d.ts +2 -1
- package/dist/builtin-extensions/pi-mcp-adapter/commands.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/commands.js +6 -6
- package/dist/builtin-extensions/pi-mcp-adapter/commands.js.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/config.d.ts +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/config.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/config.js +11 -5
- package/dist/builtin-extensions/pi-mcp-adapter/config.js.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/direct-tool-executor.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/direct-tool-executor.js +2 -2
- package/dist/builtin-extensions/pi-mcp-adapter/direct-tool-executor.js.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/host-html-template.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/host-html-template.js +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/host-html-template.js.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/index.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/index.js +48 -40
- package/dist/builtin-extensions/pi-mcp-adapter/index.js.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/init.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/init.js +3 -1
- package/dist/builtin-extensions/pi-mcp-adapter/init.js.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/mcp-auth-flow.d.ts +12 -40
- package/dist/builtin-extensions/pi-mcp-adapter/mcp-auth-flow.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/mcp-auth-flow.js +166 -235
- package/dist/builtin-extensions/pi-mcp-adapter/mcp-auth-flow.js.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/mcp-callback-server.d.ts +5 -0
- package/dist/builtin-extensions/pi-mcp-adapter/mcp-callback-server.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/mcp-callback-server.js +43 -13
- package/dist/builtin-extensions/pi-mcp-adapter/mcp-callback-server.js.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/mcp-oauth-provider.d.ts +14 -3
- package/dist/builtin-extensions/pi-mcp-adapter/mcp-oauth-provider.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/mcp-oauth-provider.js +73 -21
- package/dist/builtin-extensions/pi-mcp-adapter/mcp-oauth-provider.js.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/proxy-modes.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/proxy-modes.js +4 -4
- package/dist/builtin-extensions/pi-mcp-adapter/proxy-modes.js.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/server-manager.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/server-manager.js +2 -2
- package/dist/builtin-extensions/pi-mcp-adapter/server-manager.js.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/state.d.ts +2 -0
- package/dist/builtin-extensions/pi-mcp-adapter/state.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/state.js.map +1 -1
- package/dist/builtin-extensions/pi-ollama-cloud/index.d.ts +1 -1
- package/dist/builtin-extensions/pi-ollama-cloud/index.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-ollama-cloud/index.js +1 -1
- package/dist/builtin-extensions/pi-ollama-cloud/index.js.map +1 -1
- package/dist/builtin-extensions/pi-ollama-cloud/models.d.ts +11 -5
- package/dist/builtin-extensions/pi-ollama-cloud/models.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-ollama-cloud/models.js +12 -32
- package/dist/builtin-extensions/pi-ollama-cloud/models.js.map +1 -1
- package/dist/builtin-extensions/pi-prompt-template-model/index.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-prompt-template-model/index.js +5 -3
- package/dist/builtin-extensions/pi-prompt-template-model/index.js.map +1 -1
- package/dist/builtin-extensions/pi-prompt-template-model/prompt-loader.d.ts +2 -1
- package/dist/builtin-extensions/pi-prompt-template-model/prompt-loader.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-prompt-template-model/prompt-loader.js +21 -12
- package/dist/builtin-extensions/pi-prompt-template-model/prompt-loader.js.map +1 -1
- package/dist/builtin-extensions/pi-prompt-template-model/tool-manager.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-prompt-template-model/tool-manager.js +7 -24
- package/dist/builtin-extensions/pi-prompt-template-model/tool-manager.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/index.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/index.js +39 -77
- package/dist/builtin-extensions/pi-subagents/src/extension/index.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/schemas.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/schemas.js +1 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/schemas.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.d.ts +4 -4
- package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.js +8 -5
- package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/notify.d.ts +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/notify.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/notify.js +15 -31
- package/dist/builtin-extensions/pi-subagents/src/runs/background/notify.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/result-watcher.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/result-watcher.js +7 -2
- package/dist/builtin-extensions/pi-subagents/src/runs/background/result-watcher.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-runner.d.ts +1 -0
- package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-runner.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-runner.js +21 -4
- package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-runner.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-execution.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-execution.js +11 -4
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-execution.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/execution.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/execution.js +121 -25
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/execution.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.js +25 -5
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/chain-outputs.d.ts +1 -0
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/chain-outputs.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/chain-outputs.js +5 -0
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/chain-outputs.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/child-tools.d.ts +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/child-tools.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/child-tools.js +2 -0
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/child-tools.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.d.ts +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.js +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.d.ts +7 -8
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.js +60 -32
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/shared/utils.d.ts +1 -1
- package/dist/builtin-extensions/pi-subagents/src/shared/utils.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/shared/utils.js +15 -5
- package/dist/builtin-extensions/pi-subagents/src/shared/utils.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.js +4 -3
- package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/tui/communication.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/tui/communication.js +1 -1
- package/dist/builtin-extensions/pi-subagents/src/tui/communication.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/tui/render.d.ts +2 -1
- package/dist/builtin-extensions/pi-subagents/src/tui/render.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/tui/render.js +22 -11
- package/dist/builtin-extensions/pi-subagents/src/tui/render.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/watchdog/review.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/watchdog/review.js +3 -3
- package/dist/builtin-extensions/pi-subagents/src/watchdog/review.js.map +1 -1
- package/dist/builtin-extensions/pi-tps.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-tps.js +20 -17
- package/dist/builtin-extensions/pi-tps.js.map +1 -1
- package/dist/builtin-extensions/pi-web-access/activity.d.ts +1 -0
- package/dist/builtin-extensions/pi-web-access/activity.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-web-access/activity.js +27 -5
- package/dist/builtin-extensions/pi-web-access/activity.js.map +1 -1
- package/dist/builtin-extensions/pi-web-access/bounded-body.d.ts +3 -0
- package/dist/builtin-extensions/pi-web-access/bounded-body.d.ts.map +1 -0
- package/dist/builtin-extensions/pi-web-access/bounded-body.js +43 -0
- package/dist/builtin-extensions/pi-web-access/bounded-body.js.map +1 -0
- package/dist/builtin-extensions/pi-web-access/content-page.d.ts +24 -0
- package/dist/builtin-extensions/pi-web-access/content-page.d.ts.map +1 -0
- package/dist/builtin-extensions/pi-web-access/content-page.js +57 -0
- package/dist/builtin-extensions/pi-web-access/content-page.js.map +1 -0
- package/dist/builtin-extensions/pi-web-access/extract.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-web-access/extract.js +7 -2
- package/dist/builtin-extensions/pi-web-access/extract.js.map +1 -1
- package/dist/builtin-extensions/pi-web-access/github-extract.d.ts +0 -1
- package/dist/builtin-extensions/pi-web-access/github-extract.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-web-access/github-extract.js +147 -36
- package/dist/builtin-extensions/pi-web-access/github-extract.js.map +1 -1
- package/dist/builtin-extensions/pi-web-access/index.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-web-access/index.js +48 -73
- package/dist/builtin-extensions/pi-web-access/index.js.map +1 -1
- package/dist/builtin-extensions/pi-web-access/session-cleanup.d.ts +12 -4
- package/dist/builtin-extensions/pi-web-access/session-cleanup.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-web-access/session-cleanup.js +35 -12
- package/dist/builtin-extensions/pi-web-access/session-cleanup.js.map +1 -1
- package/dist/builtin-extensions/pi-web-access/storage.d.ts +9 -6
- package/dist/builtin-extensions/pi-web-access/storage.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-web-access/storage.js +36 -24
- package/dist/builtin-extensions/pi-web-access/storage.js.map +1 -1
- package/dist/builtin-extensions/simple-pi-memory.d.ts +1 -1
- package/dist/builtin-extensions/simple-pi-memory.d.ts.map +1 -1
- package/dist/builtin-extensions/simple-pi-memory.js +1 -1
- package/dist/builtin-extensions/simple-pi-memory.js.map +1 -1
- package/dist/cli/install-cli.d.ts.map +1 -1
- package/dist/cli/install-cli.js +38 -30
- package/dist/cli/install-cli.js.map +1 -1
- package/dist/core/agent-session-runtime.d.ts +13 -0
- package/dist/core/agent-session-runtime.d.ts.map +1 -1
- package/dist/core/agent-session-runtime.js +75 -11
- package/dist/core/agent-session-runtime.js.map +1 -1
- package/dist/core/agent-session-services.d.ts +1 -0
- package/dist/core/agent-session-services.d.ts.map +1 -1
- package/dist/core/agent-session-services.js +1 -0
- package/dist/core/agent-session-services.js.map +1 -1
- package/dist/core/agent-session.d.ts +40 -6
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +309 -76
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/browser/runtime.d.ts +2 -0
- package/dist/core/browser/runtime.d.ts.map +1 -1
- package/dist/core/browser/runtime.js +80 -45
- package/dist/core/browser/runtime.js.map +1 -1
- package/dist/core/browser/setup.d.ts.map +1 -1
- package/dist/core/browser/setup.js +12 -1
- package/dist/core/browser/setup.js.map +1 -1
- package/dist/core/computer-use/adapter.d.ts +28 -0
- package/dist/core/computer-use/adapter.d.ts.map +1 -0
- package/dist/core/computer-use/adapter.js +138 -0
- package/dist/core/computer-use/adapter.js.map +1 -0
- package/dist/core/computer-use/image.d.ts +27 -0
- package/dist/core/computer-use/image.d.ts.map +1 -0
- package/dist/core/computer-use/image.js +84 -0
- package/dist/core/computer-use/image.js.map +1 -0
- package/dist/core/computer-use/lease.d.ts +18 -0
- package/dist/core/computer-use/lease.d.ts.map +1 -0
- package/dist/core/computer-use/lease.js +129 -0
- package/dist/core/computer-use/lease.js.map +1 -0
- package/dist/core/computer-use/macos-runtime.d.ts +14 -0
- package/dist/core/computer-use/macos-runtime.d.ts.map +1 -0
- package/dist/core/computer-use/macos-runtime.js +148 -0
- package/dist/core/computer-use/macos-runtime.js.map +1 -0
- package/dist/core/computer-use/policy.d.ts +19 -0
- package/dist/core/computer-use/policy.d.ts.map +1 -0
- package/dist/core/computer-use/policy.js +67 -0
- package/dist/core/computer-use/policy.js.map +1 -0
- package/dist/core/computer-use/release.generated.d.ts +31 -0
- package/dist/core/computer-use/release.generated.d.ts.map +1 -0
- package/dist/core/computer-use/release.generated.js +36 -0
- package/dist/core/computer-use/release.generated.js.map +1 -0
- package/dist/core/computer-use/runtime.d.ts +13 -0
- package/dist/core/computer-use/runtime.d.ts.map +1 -0
- package/dist/core/computer-use/runtime.js +158 -0
- package/dist/core/computer-use/runtime.js.map +1 -0
- package/dist/core/computer-use/schemas.d.ts +100 -0
- package/dist/core/computer-use/schemas.d.ts.map +1 -0
- package/dist/core/computer-use/schemas.js +96 -0
- package/dist/core/computer-use/schemas.js.map +1 -0
- package/dist/core/computer-use/windows-desktop.d.ts +3 -0
- package/dist/core/computer-use/windows-desktop.d.ts.map +1 -0
- package/dist/core/computer-use/windows-desktop.js +48 -0
- package/dist/core/computer-use/windows-desktop.js.map +1 -0
- package/dist/core/computer-use/workflow.d.ts +38 -0
- package/dist/core/computer-use/workflow.d.ts.map +1 -0
- package/dist/core/computer-use/workflow.js +900 -0
- package/dist/core/computer-use/workflow.js.map +1 -0
- package/dist/core/cron/jobs.d.ts +26 -8
- package/dist/core/cron/jobs.d.ts.map +1 -1
- package/dist/core/cron/jobs.js +357 -232
- package/dist/core/cron/jobs.js.map +1 -1
- package/dist/core/cron/origin-context.d.ts +1 -0
- package/dist/core/cron/origin-context.d.ts.map +1 -1
- package/dist/core/cron/origin-context.js.map +1 -1
- package/dist/core/cron/scheduler.d.ts +22 -17
- package/dist/core/cron/scheduler.d.ts.map +1 -1
- package/dist/core/cron/scheduler.js +153 -73
- package/dist/core/cron/scheduler.js.map +1 -1
- package/dist/core/extensions/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +4 -0
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +1 -0
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +8 -0
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +8 -0
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/footer-data-provider.d.ts +4 -0
- package/dist/core/footer-data-provider.d.ts.map +1 -1
- package/dist/core/footer-data-provider.js +22 -1
- package/dist/core/footer-data-provider.js.map +1 -1
- package/dist/core/large-subagent-launch.d.ts +1 -1
- package/dist/core/large-subagent-launch.d.ts.map +1 -1
- package/dist/core/large-subagent-launch.js +7 -7
- package/dist/core/large-subagent-launch.js.map +1 -1
- package/dist/core/model-registry.d.ts +2 -0
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +5 -0
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-runtime.d.ts +4 -1
- package/dist/core/model-runtime.d.ts.map +1 -1
- package/dist/core/model-runtime.js +40 -4
- package/dist/core/model-runtime.js.map +1 -1
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/permissions.d.ts +4 -4
- package/dist/core/permissions.d.ts.map +1 -1
- package/dist/core/permissions.js +25 -38
- package/dist/core/permissions.js.map +1 -1
- package/dist/core/plan-mode.d.ts +5 -13
- package/dist/core/plan-mode.d.ts.map +1 -1
- package/dist/core/plan-mode.js +135 -116
- package/dist/core/plan-mode.js.map +1 -1
- package/dist/core/project-trust.d.ts.map +1 -1
- package/dist/core/project-trust.js +1 -1
- package/dist/core/project-trust.js.map +1 -1
- package/dist/core/prompt-resource-bridge.d.ts +12 -0
- package/dist/core/prompt-resource-bridge.d.ts.map +1 -0
- package/dist/core/prompt-resource-bridge.js +9 -0
- package/dist/core/prompt-resource-bridge.js.map +1 -0
- package/dist/core/protected-targets.d.ts +6 -0
- package/dist/core/protected-targets.d.ts.map +1 -0
- package/dist/core/protected-targets.js +45 -0
- package/dist/core/protected-targets.js.map +1 -0
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +7 -0
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/rollback.d.ts +19 -3
- package/dist/core/rollback.d.ts.map +1 -1
- package/dist/core/rollback.js +172 -56
- package/dist/core/rollback.js.map +1 -1
- package/dist/core/runtime-credentials.d.ts +3 -0
- package/dist/core/runtime-credentials.d.ts.map +1 -1
- package/dist/core/runtime-credentials.js +14 -1
- package/dist/core/runtime-credentials.js.map +1 -1
- package/dist/core/sdk.d.ts +3 -0
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +1 -0
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager.d.ts +6 -0
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +95 -32
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/session-ownership.d.ts.map +1 -1
- package/dist/core/session-ownership.js +8 -3
- package/dist/core/session-ownership.js.map +1 -1
- package/dist/core/session-retention.d.ts.map +1 -1
- package/dist/core/session-retention.js +18 -7
- package/dist/core/session-retention.js.map +1 -1
- package/dist/core/session-startup-settings.d.ts +10 -0
- package/dist/core/session-startup-settings.d.ts.map +1 -0
- package/dist/core/session-startup-settings.js +70 -0
- package/dist/core/session-startup-settings.js.map +1 -0
- 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 -0
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/subagent-event-transport.d.ts +3 -0
- package/dist/core/subagent-event-transport.d.ts.map +1 -0
- package/dist/core/subagent-event-transport.js +61 -0
- package/dist/core/subagent-event-transport.js.map +1 -0
- package/dist/core/subscriptions.d.ts +16 -7
- package/dist/core/subscriptions.d.ts.map +1 -1
- package/dist/core/subscriptions.js +96 -55
- package/dist/core/subscriptions.js.map +1 -1
- package/dist/core/trust-manager.d.ts +2 -1
- package/dist/core/trust-manager.d.ts.map +1 -1
- package/dist/core/trust-manager.js +6 -1
- package/dist/core/trust-manager.js.map +1 -1
- package/dist/core/update-check.d.ts.map +1 -1
- package/dist/core/update-check.js.map +1 -1
- package/dist/core/usage-adapters/kimi-coding.d.ts +2 -2
- package/dist/core/usage-adapters/kimi-coding.d.ts.map +1 -1
- package/dist/core/usage-adapters/kimi-coding.js +2 -2
- package/dist/core/usage-adapters/kimi-coding.js.map +1 -1
- package/dist/core/usage-adapters/openai-codex.d.ts +3 -2
- package/dist/core/usage-adapters/openai-codex.d.ts.map +1 -1
- package/dist/core/usage-adapters/openai-codex.js +3 -3
- package/dist/core/usage-adapters/openai-codex.js.map +1 -1
- package/dist/core/usage-adapters/xai.d.ts +2 -2
- package/dist/core/usage-adapters/xai.d.ts.map +1 -1
- package/dist/core/usage-adapters/xai.js +3 -3
- package/dist/core/usage-adapters/xai.js.map +1 -1
- package/dist/core/usage-adapters/zai.d.ts +2 -2
- package/dist/core/usage-adapters/zai.d.ts.map +1 -1
- package/dist/core/usage-adapters/zai.js +2 -2
- package/dist/core/usage-adapters/zai.js.map +1 -1
- package/dist/core/usage-service.d.ts +9 -2
- package/dist/core/usage-service.d.ts.map +1 -1
- package/dist/core/usage-service.js +95 -50
- package/dist/core/usage-service.js.map +1 -1
- package/dist/gateway/adapters/discord.d.ts.map +1 -1
- package/dist/gateway/adapters/discord.js +2 -2
- package/dist/gateway/adapters/discord.js.map +1 -1
- package/dist/gateway/agent-bridge.d.ts +9 -1
- package/dist/gateway/agent-bridge.d.ts.map +1 -1
- package/dist/gateway/agent-bridge.js +91 -37
- package/dist/gateway/agent-bridge.js.map +1 -1
- package/dist/gateway/approval.d.ts.map +1 -1
- package/dist/gateway/approval.js +3 -3
- package/dist/gateway/approval.js.map +1 -1
- package/dist/gateway/authz.d.ts +4 -4
- package/dist/gateway/authz.d.ts.map +1 -1
- package/dist/gateway/authz.js +8 -12
- package/dist/gateway/authz.js.map +1 -1
- package/dist/gateway/buttons.d.ts +8 -1
- package/dist/gateway/buttons.d.ts.map +1 -1
- package/dist/gateway/buttons.js +76 -18
- package/dist/gateway/buttons.js.map +1 -1
- package/dist/gateway/commands.d.ts +1 -0
- package/dist/gateway/commands.d.ts.map +1 -1
- package/dist/gateway/commands.js +12 -10
- package/dist/gateway/commands.js.map +1 -1
- package/dist/gateway/cron.d.ts +12 -11
- package/dist/gateway/cron.d.ts.map +1 -1
- package/dist/gateway/cron.js +85 -62
- package/dist/gateway/cron.js.map +1 -1
- package/dist/gateway/index.d.ts.map +1 -1
- package/dist/gateway/index.js +5 -4
- package/dist/gateway/index.js.map +1 -1
- package/dist/gateway/mobile-commands.d.ts +1 -0
- package/dist/gateway/mobile-commands.d.ts.map +1 -1
- package/dist/gateway/mobile-commands.js +64 -22
- package/dist/gateway/mobile-commands.js.map +1 -1
- package/dist/gateway/presenter.d.ts +12 -2
- package/dist/gateway/presenter.d.ts.map +1 -1
- package/dist/gateway/presenter.js +74 -39
- package/dist/gateway/presenter.js.map +1 -1
- package/dist/gateway/router.d.ts +2 -2
- package/dist/gateway/router.d.ts.map +1 -1
- package/dist/gateway/router.js +22 -9
- package/dist/gateway/router.js.map +1 -1
- package/dist/gateway/service.d.ts +2 -0
- package/dist/gateway/service.d.ts.map +1 -1
- package/dist/gateway/service.js +153 -0
- package/dist/gateway/service.js.map +1 -1
- package/dist/gateway/setup.d.ts.map +1 -1
- package/dist/gateway/setup.js +6 -4
- package/dist/gateway/setup.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +86 -33
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/assistant-message.js +6 -4
- package/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/dist/modes/interactive/components/copyable-text.d.ts.map +1 -1
- package/dist/modes/interactive/components/copyable-text.js +3 -2
- package/dist/modes/interactive/components/copyable-text.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 -1
- package/dist/modes/interactive/components/extension-editor.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts +4 -0
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +20 -0
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +2 -2
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +104 -109
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/smooth-streaming.d.ts.map +1 -1
- package/dist/modes/interactive/smooth-streaming.js.map +1 -1
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js +9 -1
- package/dist/modes/print-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +2 -1
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/node-runtime/adapter-247RTYLS.js +16 -0
- package/dist/node-runtime/agent-session-services-KDMSPQDY.js +53 -0
- package/dist/node-runtime/{brave-UWDA3I22.js → brave-2AFFAXNN.js} +1 -1
- package/dist/node-runtime/{builtin-extensions-ZLAX7TUH.js → builtin-extensions-OX6KELNX.js} +9 -7
- package/dist/node-runtime/{chunk-QH6YL7VK.js → chunk-252ZVPPF.js} +3 -3
- package/dist/node-runtime/{chunk-PCEW76PM.js → chunk-2OIPYKLZ.js} +6 -6
- package/dist/node-runtime/{chunk-XBWPBZBN.js → chunk-2SWW7KMW.js} +1 -1
- package/dist/node-runtime/{chunk-UQUCFAJ3.js → chunk-2VIW3IMF.js} +40 -7
- package/dist/node-runtime/{chunk-UOEDI7RP.js → chunk-4KNKQGHM.js} +2 -2
- package/dist/node-runtime/{chunk-FQMM2EZ2.js → chunk-64XTQNLA.js} +29 -7
- package/dist/node-runtime/{chunk-NRKGMJYU.js → chunk-6O3IW3IA.js} +2 -2
- package/dist/node-runtime/{chunk-5ZQXRPMC.js → chunk-6ZZHGUSA.js} +2 -2
- package/dist/node-runtime/chunk-A2WO6WIN.js +1197 -0
- package/dist/node-runtime/{chunk-ZXSGTGJ6.js → chunk-APVM5NEU.js} +169 -148
- package/dist/node-runtime/{chunk-RC7DMV45.js → chunk-AYHH7YSD.js} +205 -144
- package/dist/node-runtime/{chunk-LWYIVUGV.js → chunk-B2IBAXNX.js} +48 -31
- package/dist/node-runtime/{chunk-M3LZLQW2.js → chunk-BDRGN3L2.js} +1 -0
- package/dist/node-runtime/{chunk-GJ2RDBRL.js → chunk-BYC6RKCN.js} +4 -2
- package/dist/node-runtime/{chunk-KWIYUUZK.js → chunk-C3P6Q3B2.js} +469 -283
- package/dist/node-runtime/{chunk-YCUZEGJG.js → chunk-DQSCFU7R.js} +17 -8
- package/dist/node-runtime/chunk-EBLAZVSA.js +4170 -0
- package/dist/node-runtime/{chunk-2KIPT4HJ.js → chunk-EPR2F3GU.js} +68 -20
- package/dist/node-runtime/{chunk-CSFI6YXL.js → chunk-ES6PBSIE.js} +1 -1
- package/dist/node-runtime/{chunk-IF24A3FH.js → chunk-EVM653DD.js} +4 -4
- package/dist/node-runtime/{chunk-HTFRRDSF.js → chunk-F2SMQ6ES.js} +3 -2
- package/dist/node-runtime/chunk-F2V2F4ZG.js +114 -0
- package/dist/node-runtime/chunk-FE3WZI7F.js +290 -0
- package/dist/node-runtime/{chunk-GYIXXQAO.js → chunk-FIRA54AC.js} +2 -5
- package/dist/node-runtime/{chunk-6VYZ5UFP.js → chunk-FLGEEH27.js} +1 -1
- package/dist/node-runtime/{chunk-5EFIU3OM.js → chunk-FTKEZL27.js} +1 -1
- package/dist/node-runtime/chunk-FY4A63RK.js +73 -0
- package/dist/node-runtime/chunk-FYIFPFXE.js +98 -0
- package/dist/node-runtime/{chunk-HMBGROQK.js → chunk-GLDXBBL6.js} +3 -3
- package/dist/node-runtime/{chunk-KWA4OC2J.js → chunk-H6YBCWKG.js} +1 -1
- package/dist/node-runtime/{chunk-2MI5OPMN.js → chunk-HNNHHJAB.js} +68 -50
- package/dist/node-runtime/{chunk-6XL67VVY.js → chunk-HUD2RFJW.js} +17 -2
- package/dist/node-runtime/{chunk-I54LGHWM.js → chunk-I2H5QMWW.js} +3 -3
- package/dist/node-runtime/chunk-IAZSK7KK.js +108 -0
- package/dist/node-runtime/{chunk-2HHLJWGD.js → chunk-IHHTWSXN.js} +9 -9
- package/dist/node-runtime/{chunk-DAPBPCBP.js → chunk-IPP5BIV5.js} +25 -3
- package/dist/node-runtime/{chunk-QFWG2RVL.js → chunk-IXG6F4NT.js} +11 -0
- package/dist/node-runtime/{chunk-RDDAZOMU.js → chunk-JL4HYQXK.js} +1 -1
- package/dist/node-runtime/{chunk-CDVHZOOK.js → chunk-JQYNHAKX.js} +1 -1
- package/dist/node-runtime/{chunk-WF7PGWRZ.js → chunk-JWEVT363.js} +37 -28
- package/dist/node-runtime/{chunk-2HMIRK7W.js → chunk-LHV3V67B.js} +5 -5
- package/dist/node-runtime/{chunk-UAEOTO52.js → chunk-MNQXDFPV.js} +6 -2
- package/dist/node-runtime/{chunk-IJIFHRTB.js → chunk-MQPKUHRN.js} +165 -85
- package/dist/node-runtime/{chunk-MPKSOJBT.js → chunk-NHATCSOI.js} +4 -7
- package/dist/node-runtime/{chunk-RMQZU2YU.js → chunk-NNNR3QIY.js} +1 -1
- package/dist/node-runtime/{chunk-RWTKOC3B.js → chunk-QBTJG3UM.js} +1 -1
- package/dist/node-runtime/{chunk-E4D3IGP2.js → chunk-QNVMKNNN.js} +20 -17
- package/dist/node-runtime/{chunk-GS42T6MX.js → chunk-QW3AAHWN.js} +1 -1
- package/dist/node-runtime/{chunk-7S3T6YEA.js → chunk-R4WSB2MQ.js} +5 -5
- package/dist/node-runtime/{chunk-B4HP6ZWM.js → chunk-RHCGYWO7.js} +1 -1
- package/dist/node-runtime/{chunk-3XPLBUEM.js → chunk-RLGY2QIL.js} +49 -59
- package/dist/node-runtime/{chunk-KKUTQQV7.js → chunk-RYRGL7P4.js} +1 -1
- package/dist/node-runtime/{chunk-AD6VXAO7.js → chunk-TCT6PCUR.js} +47 -115
- package/dist/node-runtime/chunk-U5F4IC7R.js +53 -0
- package/dist/node-runtime/{chunk-OCVIXVTZ.js → chunk-UBWW2PID.js} +13 -2
- package/dist/node-runtime/{chunk-HFVZUPFJ.js → chunk-UNUZICC4.js} +3 -3
- package/dist/node-runtime/{chunk-LQP3RB67.js → chunk-UYRKUKFE.js} +1 -1
- package/dist/node-runtime/{chunk-DSIKTUPW.js → chunk-VSUEAI7O.js} +2993 -3820
- package/dist/node-runtime/{chunk-NAY6UUQZ.js → chunk-WDIVLMOH.js} +1 -1
- package/dist/node-runtime/{chunk-E24EO34J.js → chunk-WPXUR3HE.js} +1 -1
- package/dist/node-runtime/{chunk-SLVOAQOY.js → chunk-WXYNALHD.js} +113 -1
- package/dist/node-runtime/{chunk-KJ6DWS3K.js → chunk-XEOCUEUJ.js} +121 -60
- package/dist/node-runtime/chunk-YD3IZAZ7.js +47 -0
- package/dist/node-runtime/chunk-YSB6URMT.js +41 -0
- package/dist/node-runtime/{chunk-VQFSUJJG.js → chunk-ZDJUR45D.js} +430 -129
- package/dist/node-runtime/{chunk-YDO2F2IA.js → chunk-ZEVFBFNF.js} +95 -142
- package/dist/node-runtime/chunk-ZIQUS5QO.js +180 -0
- package/dist/node-runtime/cli-runtime.js +4 -4
- package/dist/node-runtime/{command-6WDOYKS6.js → command-3HMSY6W2.js} +5 -5
- package/dist/node-runtime/{commands-NZLSOHPE.js → commands-D6A6H4TS.js} +11 -16
- package/dist/node-runtime/commands-OCSSEEWJ.js +37 -0
- package/dist/node-runtime/{config-QDD5PUE2.js → config-CU7M7BTK.js} +1 -1
- package/dist/node-runtime/{config-D4QUPAHX.js → config-DS7XLMEM.js} +2 -2
- package/dist/node-runtime/{direct-tool-executor-77GW4F5P.js → direct-tool-executor-2QJXVQD2.js} +8 -10
- package/dist/node-runtime/{exa-LL64QZR2.js → exa-6VBZNPGE.js} +1 -1
- package/dist/node-runtime/{export-html-VM4J2MNR.js → export-html-BRWF5AHI.js} +4 -4
- package/dist/node-runtime/{extension-input-E7BJZ35H.js → extension-input-VBBMX7YV.js} +5 -5
- package/dist/node-runtime/{extension-selector-WU42XDTU.js → extension-selector-T5AOG5XB.js} +5 -5
- package/dist/node-runtime/{extract-EQJE7FZZ.js → extract-BFX2N35A.js} +3 -3
- package/dist/node-runtime/{gateway-INAYBF4Q.js → gateway-6623C2U3.js} +61 -53
- package/dist/node-runtime/{gemini-search-35OCRFLN.js → gemini-search-C66QHDT6.js} +2 -2
- package/dist/node-runtime/{gemini-url-context-UQY3PHHW.js → gemini-url-context-T7DEK73R.js} +3 -3
- package/dist/node-runtime/{github-extract-F64RZOEA.js → github-extract-HOGE3D6F.js} +107 -38
- package/dist/node-runtime/{goal-NJEE5CTU.js → goal-AIHEDUYA.js} +5 -5
- package/dist/node-runtime/index.js +54 -48
- package/dist/node-runtime/{init-HS6NQXSK.js → init-JBQJIPYI.js} +3 -4
- package/dist/node-runtime/{install-cli-KL4UDDAD.js → install-cli-INGHIVBY.js} +30 -25
- package/dist/node-runtime/interactive-mode-FM5DNUSW.js +74 -0
- package/dist/node-runtime/{interactive-view-NGFAMHPW.js → interactive-view-K33PM4OS.js} +8 -8
- package/dist/node-runtime/{lsp-manager-3ASUSO4T.js → lsp-manager-S554V5HR.js} +240 -155
- package/dist/node-runtime/{lunr-browser-IR7TL3J7.js → lunr-browser-H4FDOR3C.js} +7 -7
- package/dist/node-runtime/lunr-computer-use-VDP2QNRQ.js +158 -0
- package/dist/node-runtime/{lunr-cron-LWIZJM2N.js → lunr-cron-LKVA5CZZ.js} +94 -79
- package/dist/node-runtime/main.js +42 -39
- package/dist/node-runtime/{mobile-commands-J7OJEKFO.js → mobile-commands-XT3NQXLD.js} +13 -12
- package/dist/node-runtime/{model-runtime-OO5HFLWE.js → model-runtime-MZ2JMDV4.js} +4 -4
- package/dist/node-runtime/{openai-search-B3MSNCQA.js → openai-search-K72LJDYN.js} +1 -1
- package/dist/node-runtime/{package-manager-cli-VYZM5WHN.js → package-manager-cli-CYM262SI.js} +20 -19
- package/dist/node-runtime/{parallel-AI2MNSCU.js → parallel-X724NCNU.js} +1 -1
- package/dist/node-runtime/{perplexity-QVJW3I35.js → perplexity-RDHQHVMK.js} +2 -2
- package/dist/node-runtime/{pi-intercom-QM53RLTS.js → pi-intercom-NHHEPBMI.js} +2 -2
- package/dist/node-runtime/{pi-mcp-adapter-5UKBZP44.js → pi-mcp-adapter-PP3GQJQ2.js} +98 -94
- package/dist/node-runtime/{pi-ollama-cloud-2F3Y2QNM.js → pi-ollama-cloud-4MNWIMFN.js} +11 -24
- package/dist/node-runtime/{pi-prompt-template-model-QWTCGLJU.js → pi-prompt-template-model-FTGELLS5.js} +32 -36
- package/dist/node-runtime/{pi-subagents-DNY7EAIG.js → pi-subagents-LT3CTO4E.js} +114 -116
- package/dist/node-runtime/{pi-web-access-WTGMNZ32.js → pi-web-access-Z3LP246C.js} +144 -108
- package/dist/node-runtime/{print-mode-XSFM26EL.js → print-mode-2XHN5SUA.js} +4 -3
- package/dist/node-runtime/{process-registry-4FAKZQOL.js → process-registry-Q4QWIU33.js} +3 -3
- package/dist/node-runtime/{proxy-modes-LGEUYD7R.js → proxy-modes-VEGC6QG5.js} +9 -13
- package/dist/node-runtime/rpc-entry.js +42 -39
- package/dist/node-runtime/{rpc-mode-O3XV4SID.js → rpc-mode-32DHJPEJ.js} +4 -4
- package/dist/node-runtime/{runtime-4VA6JKNF.js → runtime-EDUUGAQD.js} +56 -46
- package/dist/node-runtime/runtime-UGXM4NPQ.js +21 -0
- package/dist/node-runtime/{runtime-bridges-VRDDR73P.js → runtime-bridges-DNKMNJCF.js} +8 -7
- package/dist/node-runtime/{service-MDQIPQ26.js → service-IHLGFLBT.js} +6 -4
- package/dist/node-runtime/{session-handoff-GWARVEWT.js → session-handoff-LNSPDTKY.js} +4 -4
- package/dist/node-runtime/{session-manager-JB5J6XBN.js → session-manager-YIFIAVGC.js} +3 -3
- package/dist/node-runtime/{session-selector-GIM4DHQ2.js → session-selector-I73U3EIO.js} +7 -7
- package/dist/node-runtime/{settings-manager-J4SPQPDJ.js → settings-manager-P2TKGYTR.js} +6 -5
- package/dist/node-runtime/{setup-JBKOLJ6F.js → setup-H7CCELIL.js} +15 -1
- package/dist/node-runtime/{setup-CQ2NLVK5.js → setup-OLQ4GXWS.js} +22 -21
- package/dist/node-runtime/{src-IVPNZ2BX.js → src-6RV4PXKJ.js} +64 -36
- package/dist/node-runtime/{subagent-executor-KZZQGAKV.js → subagent-executor-Q5F7DBVM.js} +141 -62
- package/dist/node-runtime/{tavily-WEZFVFP7.js → tavily-KZBFYQB6.js} +1 -1
- package/dist/node-runtime/{theme-UOO5RVFN.js → theme-YLVZKKZD.js} +2 -2
- package/dist/node-runtime/{trust-manager-MMISNCYO.js → trust-manager-ZCU76D23.js} +2 -2
- package/dist/node-runtime/{update-cli-GTFJC7XK.js → update-cli-F3XXJANQ.js} +7 -6
- package/dist/node-runtime/{usage-service-LFB2SWYV.js → usage-service-CPAGBED5.js} +1 -1
- package/dist/node-runtime/{video-extract-OOZHR7SU.js → video-extract-UPKYIBW3.js} +3 -3
- package/dist/node-runtime/workflow-ICDI4N3J.js +767 -0
- package/dist/node-runtime/{youtube-extract-FNPAUNHU.js → youtube-extract-77NT7FWH.js} +4 -4
- package/dist/utils/clipboard-image.d.ts.map +1 -1
- package/dist/utils/clipboard-image.js.map +1 -1
- package/dist/utils/exif-orientation.d.ts.map +1 -1
- package/dist/utils/exif-orientation.js +25 -10
- package/dist/utils/exif-orientation.js.map +1 -1
- package/dist/utils/image-resize-core.d.ts +2 -0
- package/dist/utils/image-resize-core.d.ts.map +1 -1
- package/dist/utils/image-resize-core.js +12 -0
- package/dist/utils/image-resize-core.js.map +1 -1
- package/dist/utils/paths.d.ts +4 -0
- package/dist/utils/paths.d.ts.map +1 -1
- package/dist/utils/paths.js +33 -2
- package/dist/utils/paths.js.map +1 -1
- package/dist/utils/sanitize-terminal-text.d.ts +7 -0
- package/dist/utils/sanitize-terminal-text.d.ts.map +1 -0
- package/dist/utils/sanitize-terminal-text.js +67 -0
- package/dist/utils/sanitize-terminal-text.js.map +1 -0
- package/docs/browser.md +1 -1
- package/docs/computer-use.md +362 -0
- package/docs/custom-provider.md +3 -3
- package/docs/extensions.md +8 -4
- package/docs/features.md +22 -12
- package/docs/keybindings.md +1 -1
- package/docs/models.md +5 -5
- package/docs/packages.md +1 -1
- package/docs/providers.md +2 -2
- package/docs/rpc.md +7 -7
- package/docs/security.md +10 -5
- package/docs/sessions.md +2 -2
- package/docs/skills.md +1 -1
- package/docs/terminal-setup.md +7 -7
- package/docs/themes.md +1 -1
- package/docs/usage.md +1 -1
- package/examples/extensions/auto-commit-on-exit.ts +1 -1
- package/examples/extensions/bash-spawn-hook.ts +1 -1
- package/examples/extensions/built-in-tool-renderer.ts +1 -1
- package/examples/extensions/claude-rules.ts +1 -1
- package/examples/extensions/commands.ts +1 -1
- package/examples/extensions/custom-compaction.ts +1 -1
- package/examples/extensions/custom-provider-anthropic/index.ts +3 -3
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/index.ts +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/doom-overlay/index.ts +1 -1
- package/examples/extensions/git-merge-and-resolve.ts +2 -2
- package/examples/extensions/gondolin/index.ts +1 -1
- package/examples/extensions/gondolin/package-lock.json +2 -2
- package/examples/extensions/gondolin/package.json +1 -1
- package/examples/extensions/hidden-thinking-label.ts +1 -1
- package/examples/extensions/inline-bash.ts +2 -2
- package/examples/extensions/input-transform-streaming.ts +2 -2
- package/examples/extensions/input-transform.ts +2 -2
- package/examples/extensions/interactive-shell.ts +1 -1
- package/examples/extensions/kimi-deferred-tools.ts +1 -1
- package/examples/extensions/mac-system-theme.ts +1 -1
- package/examples/extensions/minimal-mode.ts +1 -1
- package/examples/extensions/modal-editor.ts +1 -1
- package/examples/extensions/model-status.ts +1 -1
- package/examples/extensions/notify.ts +3 -3
- package/examples/extensions/overlay-qa-tests.ts +1 -1
- package/examples/extensions/overlay-test.ts +1 -1
- package/examples/extensions/pirate.ts +1 -1
- package/examples/extensions/preset.ts +3 -3
- package/examples/extensions/project-trust.ts +4 -4
- package/examples/extensions/prompt-customizer.ts +1 -1
- package/examples/extensions/rainbow-editor.ts +1 -1
- package/examples/extensions/rpc-demo.ts +1 -1
- package/examples/extensions/sandbox/index.ts +7 -7
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/shutdown-command.ts +5 -5
- package/examples/extensions/ssh.ts +2 -2
- package/examples/extensions/subagent/README.md +3 -3
- package/examples/extensions/subagent/index.ts +2 -2
- package/examples/extensions/titlebar-spinner.ts +1 -1
- package/examples/extensions/tool-override.ts +1 -1
- package/examples/extensions/tools.ts +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/examples/extensions/working-indicator.ts +1 -1
- package/examples/extensions/working-message-test.ts +1 -1
- package/examples/sdk/01-minimal.ts +1 -1
- package/examples/sdk/03-custom-prompt.ts +1 -1
- package/examples/sdk/04-skills.ts +1 -1
- package/examples/sdk/06-extensions.ts +2 -2
- package/examples/sdk/08-prompt-templates.ts +1 -1
- package/install-lock/package-lock.json +3841 -0
- package/install-lock/package.json +18 -0
- package/native/computer-use/LICENSE.md +21 -0
- package/npm-shrinkwrap.json +3858 -0
- package/package.json +15 -9
- package/dist/modes/interactive/components/exit-card.d.ts +0 -22
- package/dist/modes/interactive/components/exit-card.d.ts.map +0 -1
- package/dist/modes/interactive/components/exit-card.js +0 -69
- package/dist/modes/interactive/components/exit-card.js.map +0 -1
- package/dist/node-runtime/agent-session-services-YXXFCP5J.js +0 -49
- package/dist/node-runtime/chunk-4HXHDDCF.js +0 -16
- package/dist/node-runtime/chunk-4TLO4PO2.js +0 -3427
- package/dist/node-runtime/chunk-AUXVGBO4.js +0 -19
- package/dist/node-runtime/chunk-OVX6X377.js +0 -50
- package/dist/node-runtime/chunk-QTU6AKNJ.js +0 -773
- package/dist/node-runtime/chunk-TORR5XBV.js +0 -356
- package/dist/node-runtime/commands-QC6VUZJQ.js +0 -36
- package/dist/node-runtime/interactive-mode-Z5M7WYYZ.js +0 -72
- package/dist/node-runtime/mcp-auth-flow-QIXHW6QN.js +0 -32
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"direct-tool-executor.d.ts","sourceRoot":"","sources":["../../../src/builtin-extensions/pi-mcp-adapter/direct-tool-executor.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAElH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACpD,OAAO,KAAK,EAAE,cAAc,EAAc,MAAM,YAAY,CAAC;AAuE7D,KAAK,iBAAiB,GAAG,CACvB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,MAAM,EAAE,WAAW,GAAG,SAAS,EAC/B,QAAQ,EAAE,uBAAuB,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,SAAS,EACtE,GAAG,EAAE,gBAAgB,KAClB,OAAO,CAAC,eAAe,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;AAEvD,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,MAAM,iBAAiB,GAAG,IAAI,EACxC,cAAc,EAAE,MAAM,OAAO,CAAC,iBAAiB,CAAC,GAAG,IAAI,EACvD,IAAI,EAAE,cAAc,GACnB,iBAAiB,CA6KnB","sourcesContent":["// @ts-nocheck\nimport type { AgentToolResult, AgentToolUpdateCallback, ExtensionContext } from \"@ashx-j/lunr\";\nimport { UrlElicitationRequiredError } from \"@modelcontextprotocol/sdk/types.js\";\nimport type { McpExtensionState } from \"./state.ts\";\nimport type { DirectToolSpec, McpContent } from \"./types.ts\";\nimport { lazyConnect, getFailureAgeSeconds } from \"./init.ts\";\nimport { abortable, throwIfAborted } from \"./abort.ts\";\nimport { formatSchema } from \"./tool-metadata.ts\";\nimport { resolveMcpResultContent, transformMcpContent } from \"./tool-registrar.ts\";\nimport { guardMcpOutput, guardedMcpDetails, resolveMcpOutputGuardOptions } from \"./mcp-output-guard.ts\";\nimport { maybeStartUiSession, type UiSessionRuntime } from \"./ui-session.ts\";\nimport { authenticate, supportsOAuth } from \"./mcp-auth-flow.ts\";\nimport { formatAuthRequiredMessage } from \"./utils.ts\";\n\ntype DirectAutoAuthResult =\n | { status: \"skipped\" }\n | { status: \"success\" }\n | { status: \"failed\"; message: string };\n\nfunction getDirectAuthRequiredMessage(\n state: McpExtensionState,\n serverName: string,\n defaultMessage = `MCP server \"${serverName}\" requires OAuth authentication. Run mcp({ action: \"auth-start\", server: \"${serverName}\" }) to get a browser URL, or /mcp-auth ${serverName} in an interactive local session.`,\n): string {\n return formatAuthRequiredMessage(state.config, serverName, defaultMessage);\n}\n\nfunction getDirectAuthFailedMessage(state: McpExtensionState, serverName: string, message: string): string {\n const customGuidance = state.config.settings?.authRequiredMessage;\n if (customGuidance) {\n return `OAuth authentication failed for \"${serverName}\": ${message}. ${getDirectAuthRequiredMessage(state, serverName)}`;\n }\n return `OAuth authentication failed for \"${serverName}\": ${message}. Run mcp({ action: \"auth-start\", server: \"${serverName}\" }) to get a browser URL, or /mcp-auth ${serverName} in an interactive local session.`;\n}\n\nasync function attemptDirectAutoAuth(\n state: McpExtensionState,\n serverName: string,\n signal?: AbortSignal,\n): Promise<DirectAutoAuthResult> {\n if (state.config.settings?.autoAuth !== true) {\n return { status: \"skipped\" };\n }\n\n const definition = state.config.mcpServers[serverName];\n if (!definition || !supportsOAuth(definition) || !definition.url) {\n return { status: \"skipped\" };\n }\n\n const grantType = definition.oauth ? definition.oauth.grantType ?? \"authorization_code\" : \"authorization_code\";\n if (!state.ui && grantType !== \"client_credentials\") {\n return {\n status: \"failed\",\n message: getDirectAuthRequiredMessage(\n state,\n serverName,\n `MCP server \"${serverName}\" requires OAuth authentication. Run mcp({ action: \"auth-start\", server: \"${serverName}\" }) to get a browser URL, or /mcp-auth ${serverName} in an interactive local session.`,\n ),\n };\n }\n\n try {\n await abortable(authenticate(serverName, definition.url, definition), signal);\n throwIfAborted(signal);\n return { status: \"success\" };\n } catch (error) {\n throwIfAborted(signal);\n const message = error instanceof Error ? error.message : String(error);\n return {\n status: \"failed\",\n message: getDirectAuthFailedMessage(state, serverName, message),\n };\n }\n}\n\ntype DirectToolExecute = (\n toolCallId: string,\n params: Record<string, unknown>,\n signal: AbortSignal | undefined,\n onUpdate: AgentToolUpdateCallback<Record<string, unknown>> | undefined,\n ctx: ExtensionContext,\n) => Promise<AgentToolResult<Record<string, unknown>>>;\n\nexport function createDirectToolExecutor(\n getState: () => McpExtensionState | null,\n getInitPromise: () => Promise<McpExtensionState> | null,\n spec: DirectToolSpec\n): DirectToolExecute {\n return async function execute(_toolCallId, params, signal) {\n throwIfAborted(signal);\n let state = getState();\n const initPromise = getInitPromise();\n\n if (!state && initPromise) {\n try {\n state = await initPromise;\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [{ type: \"text\" as const, text: `MCP initialization failed: ${message}` }],\n details: { error: \"init_failed\", message },\n };\n }\n }\n if (!state) {\n return {\n content: [{ type: \"text\" as const, text: \"MCP not initialized\" }],\n details: { error: \"not_initialized\" },\n };\n }\n\n let connected = await lazyConnect(state, spec.serverName, signal);\n throwIfAborted(signal);\n let autoAuthAttempted = false;\n\n if (!connected && state.manager.getConnection(spec.serverName)?.status === \"needs-auth\") {\n autoAuthAttempted = true;\n const autoAuth = await attemptDirectAutoAuth(state, spec.serverName, signal);\n throwIfAborted(signal);\n if (autoAuth.status === \"failed\") {\n return {\n content: [{ type: \"text\" as const, text: autoAuth.message }],\n details: { error: \"auth_required\", server: spec.serverName, message: autoAuth.message },\n };\n }\n if (autoAuth.status === \"success\") {\n await state.manager.close(spec.serverName);\n throwIfAborted(signal);\n state.failureTracker.delete(spec.serverName);\n connected = await lazyConnect(state, spec.serverName, signal);\n throwIfAborted(signal);\n }\n }\n\n if (!connected) {\n const authConnection = state.manager.getConnection(spec.serverName);\n if (authConnection?.status === \"needs-auth\") {\n const message = getDirectAuthRequiredMessage(state, spec.serverName);\n return {\n content: [{ type: \"text\" as const, text: message }],\n details: { error: \"auth_required\", server: spec.serverName, message, autoAuthAttempted },\n };\n }\n const failedAgo = getFailureAgeSeconds(state, spec.serverName);\n return {\n content: [{ type: \"text\" as const, text: `MCP server \"${spec.serverName}\" not available${failedAgo !== null ? ` (failed ${failedAgo}s ago)` : \"\"}` }],\n details: { error: \"server_unavailable\", server: spec.serverName },\n };\n }\n\n const connection = state.manager.getConnection(spec.serverName);\n if (!connection || connection.status !== \"connected\") {\n return {\n content: [{ type: \"text\" as const, text: `MCP server \"${spec.serverName}\" not connected` }],\n details: { error: \"not_connected\", server: spec.serverName },\n };\n }\n\n let uiSession: UiSessionRuntime | null = null;\n const requestOptions = state.manager.getRequestOptions?.(spec.serverName, signal) ?? (signal ? { signal } : undefined);\n\n const outputGuardOptions = resolveMcpOutputGuardOptions(state.config.settings);\n\n try {\n state.manager.touch(spec.serverName);\n state.manager.incrementInFlight(spec.serverName);\n\n if (spec.resourceUri) {\n const result = await connection.client.readResource({ uri: spec.resourceUri }, requestOptions);\n const content = (result.contents ?? []).map(c => ({\n type: \"text\" as const,\n text: \"text\" in c ? c.text : (\"blob\" in c ? `[Binary data: ${(c as { mimeType?: string }).mimeType ?? \"unknown\"}]` : JSON.stringify(c)),\n }));\n const guarded = await guardMcpOutput(content.length > 0 ? content : [{ type: \"text\" as const, text: \"(empty resource)\" }], outputGuardOptions);\n return {\n content: guarded.content,\n details: { server: spec.serverName, resourceUri: spec.resourceUri, ...guardedMcpDetails(guarded) },\n };\n }\n\n const hasUi = !!spec.uiResourceUri;\n uiSession = hasUi\n ? await maybeStartUiSession(state, {\n serverName: spec.serverName,\n toolName: spec.originalName,\n toolArgs: params ?? {},\n uiResourceUri: spec.uiResourceUri!,\n streamMode: spec.uiStreamMode,\n })\n : null;\n\n throwIfAborted(signal);\n const resultPromise = connection.client.callTool({\n name: spec.originalName,\n arguments: params ?? {},\n _meta: uiSession?.requestMeta,\n }, undefined, requestOptions);\n\n const result = await abortable(resultPromise, signal);\n throwIfAborted(signal);\n uiSession?.sendToolResult(result as unknown as import(\"@modelcontextprotocol/sdk/types.js\").CallToolResult);\n\n if (result.isError) {\n const mcpContent = (result.content ?? []) as McpContent[];\n const content = transformMcpContent(mcpContent);\n const outputContent = content.length > 0 ? content : [{ type: \"text\" as const, text: \"(empty result)\" }];\n const schemaText = spec.inputSchema ? `\\n\\nExpected parameters:\\n${formatSchema(spec.inputSchema)}` : \"\";\n const guarded = await guardMcpOutput(outputContent, { ...outputGuardOptions, prefix: \"Error: \", suffix: schemaText, emptyTextFallback: \"Tool execution failed\" });\n return {\n content: guarded.content,\n details: { error: \"tool_error\", server: spec.serverName, ...guardedMcpDetails(guarded) },\n };\n }\n\n const content = resolveMcpResultContent(result as Record<string, unknown>);\n const outputContent = content.length > 0 ? content : [{ type: \"text\" as const, text: \"(empty result)\" }];\n if (hasUi) {\n const uiMessage = uiSession?.reused\n ? \"Updated the open UI.\"\n : \"📺 Interactive UI is now open in your browser. I'll respond to your prompts and intents as you interact with it.\";\n const guarded = await guardMcpOutput(outputContent, { ...outputGuardOptions, suffix: `\\n\\n${uiMessage}` });\n return {\n content: guarded.content,\n details: { server: spec.serverName, tool: spec.originalName, uiOpen: true, ...guardedMcpDetails(guarded) },\n };\n }\n\n const guarded = await guardMcpOutput(outputContent, { ...outputGuardOptions });\n return {\n content: guarded.content,\n details: { server: spec.serverName, tool: spec.originalName, ...guardedMcpDetails(guarded) },\n };\n } catch (error) {\n if (error instanceof UrlElicitationRequiredError) {\n const action = await state.manager.handleUrlElicitationRequired(spec.serverName, error);\n const message = action === \"accept\"\n ? \"The original MCP tool did not run. Complete the opened browser interaction, then retry the tool.\"\n : `The URL interaction was ${action === \"decline\" ? \"declined\" : \"cancelled\"}.`;\n uiSession?.sendToolCancelled(message);\n return {\n content: [{ type: \"text\" as const, text: message }],\n details: { error: \"url_elicitation_required\", server: spec.serverName, action },\n };\n }\n const message = error instanceof Error ? error.message : String(error);\n uiSession?.sendToolCancelled(message);\n const schemaText = spec.inputSchema ? `\\n\\nExpected parameters:\\n${formatSchema(spec.inputSchema)}` : \"\";\n const guarded = await guardMcpOutput([{ type: \"text\" as const, text: message }], { ...outputGuardOptions, prefix: \"Failed to call tool: \", suffix: schemaText });\n return {\n content: guarded.content,\n details: { error: \"call_failed\", server: spec.serverName, ...guardedMcpDetails(guarded) },\n };\n } finally {\n if (uiSession?.reused) {\n uiSession.close();\n }\n state.manager.decrementInFlight(spec.serverName);\n state.manager.touch(spec.serverName);\n }\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"direct-tool-executor.d.ts","sourceRoot":"","sources":["../../../src/builtin-extensions/pi-mcp-adapter/direct-tool-executor.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAElH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACpD,OAAO,KAAK,EAAE,cAAc,EAAc,MAAM,YAAY,CAAC;AAuE7D,KAAK,iBAAiB,GAAG,CACvB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,MAAM,EAAE,WAAW,GAAG,SAAS,EAC/B,QAAQ,EAAE,uBAAuB,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,SAAS,EACtE,GAAG,EAAE,gBAAgB,KAClB,OAAO,CAAC,eAAe,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;AAEvD,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,MAAM,iBAAiB,GAAG,IAAI,EACxC,cAAc,EAAE,MAAM,OAAO,CAAC,iBAAiB,CAAC,GAAG,IAAI,EACvD,IAAI,EAAE,cAAc,GACnB,iBAAiB,CA6KnB","sourcesContent":["// @ts-nocheck\nimport type { AgentToolResult, AgentToolUpdateCallback, ExtensionContext } from \"@ashx-j/lunr\";\nimport { UrlElicitationRequiredError } from \"@modelcontextprotocol/sdk/types.js\";\nimport type { McpExtensionState } from \"./state.ts\";\nimport type { DirectToolSpec, McpContent } from \"./types.ts\";\nimport { lazyConnect, getFailureAgeSeconds } from \"./init.ts\";\nimport { abortable, throwIfAborted } from \"./abort.ts\";\nimport { formatSchema } from \"./tool-metadata.ts\";\nimport { resolveMcpResultContent, transformMcpContent } from \"./tool-registrar.ts\";\nimport { guardMcpOutput, guardedMcpDetails, resolveMcpOutputGuardOptions } from \"./mcp-output-guard.ts\";\nimport { maybeStartUiSession, type UiSessionRuntime } from \"./ui-session.ts\";\nimport { supportsOAuth } from \"./mcp-auth-flow.ts\";\nimport { formatAuthRequiredMessage } from \"./utils.ts\";\n\ntype DirectAutoAuthResult =\n | { status: \"skipped\" }\n | { status: \"success\" }\n | { status: \"failed\"; message: string };\n\nfunction getDirectAuthRequiredMessage(\n state: McpExtensionState,\n serverName: string,\n defaultMessage = `MCP server \"${serverName}\" requires OAuth authentication. Run mcp({ action: \"auth-start\", server: \"${serverName}\" }) to get a browser URL, or /mcp-auth ${serverName} in an interactive local session.`,\n): string {\n return formatAuthRequiredMessage(state.config, serverName, defaultMessage);\n}\n\nfunction getDirectAuthFailedMessage(state: McpExtensionState, serverName: string, message: string): string {\n const customGuidance = state.config.settings?.authRequiredMessage;\n if (customGuidance) {\n return `OAuth authentication failed for \"${serverName}\": ${message}. ${getDirectAuthRequiredMessage(state, serverName)}`;\n }\n return `OAuth authentication failed for \"${serverName}\": ${message}. Run mcp({ action: \"auth-start\", server: \"${serverName}\" }) to get a browser URL, or /mcp-auth ${serverName} in an interactive local session.`;\n}\n\nasync function attemptDirectAutoAuth(\n state: McpExtensionState,\n serverName: string,\n signal?: AbortSignal,\n): Promise<DirectAutoAuthResult> {\n if (state.config.settings?.autoAuth !== true) {\n return { status: \"skipped\" };\n }\n\n const definition = state.config.mcpServers[serverName];\n if (!definition || !supportsOAuth(definition) || !definition.url) {\n return { status: \"skipped\" };\n }\n\n const grantType = definition.oauth ? definition.oauth.grantType ?? \"authorization_code\" : \"authorization_code\";\n if (!state.ui && grantType !== \"client_credentials\") {\n return {\n status: \"failed\",\n message: getDirectAuthRequiredMessage(\n state,\n serverName,\n `MCP server \"${serverName}\" requires OAuth authentication. Run mcp({ action: \"auth-start\", server: \"${serverName}\" }) to get a browser URL, or /mcp-auth ${serverName} in an interactive local session.`,\n ),\n };\n }\n\n try {\n await abortable(state.authFlow.authenticate(serverName, definition.url, definition), signal);\n throwIfAborted(signal);\n return { status: \"success\" };\n } catch (error) {\n throwIfAborted(signal);\n const message = error instanceof Error ? error.message : String(error);\n return {\n status: \"failed\",\n message: getDirectAuthFailedMessage(state, serverName, message),\n };\n }\n}\n\ntype DirectToolExecute = (\n toolCallId: string,\n params: Record<string, unknown>,\n signal: AbortSignal | undefined,\n onUpdate: AgentToolUpdateCallback<Record<string, unknown>> | undefined,\n ctx: ExtensionContext,\n) => Promise<AgentToolResult<Record<string, unknown>>>;\n\nexport function createDirectToolExecutor(\n getState: () => McpExtensionState | null,\n getInitPromise: () => Promise<McpExtensionState> | null,\n spec: DirectToolSpec\n): DirectToolExecute {\n return async function execute(_toolCallId, params, signal) {\n throwIfAborted(signal);\n let state = getState();\n const initPromise = getInitPromise();\n\n if (!state && initPromise) {\n try {\n state = await initPromise;\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [{ type: \"text\" as const, text: `MCP initialization failed: ${message}` }],\n details: { error: \"init_failed\", message },\n };\n }\n }\n if (!state) {\n return {\n content: [{ type: \"text\" as const, text: \"MCP not initialized\" }],\n details: { error: \"not_initialized\" },\n };\n }\n\n let connected = await lazyConnect(state, spec.serverName, signal);\n throwIfAborted(signal);\n let autoAuthAttempted = false;\n\n if (!connected && state.manager.getConnection(spec.serverName)?.status === \"needs-auth\") {\n autoAuthAttempted = true;\n const autoAuth = await attemptDirectAutoAuth(state, spec.serverName, signal);\n throwIfAborted(signal);\n if (autoAuth.status === \"failed\") {\n return {\n content: [{ type: \"text\" as const, text: autoAuth.message }],\n details: { error: \"auth_required\", server: spec.serverName, message: autoAuth.message },\n };\n }\n if (autoAuth.status === \"success\") {\n await state.manager.close(spec.serverName);\n throwIfAborted(signal);\n state.failureTracker.delete(spec.serverName);\n connected = await lazyConnect(state, spec.serverName, signal);\n throwIfAborted(signal);\n }\n }\n\n if (!connected) {\n const authConnection = state.manager.getConnection(spec.serverName);\n if (authConnection?.status === \"needs-auth\") {\n const message = getDirectAuthRequiredMessage(state, spec.serverName);\n return {\n content: [{ type: \"text\" as const, text: message }],\n details: { error: \"auth_required\", server: spec.serverName, message, autoAuthAttempted },\n };\n }\n const failedAgo = getFailureAgeSeconds(state, spec.serverName);\n return {\n content: [{ type: \"text\" as const, text: `MCP server \"${spec.serverName}\" not available${failedAgo !== null ? ` (failed ${failedAgo}s ago)` : \"\"}` }],\n details: { error: \"server_unavailable\", server: spec.serverName },\n };\n }\n\n const connection = state.manager.getConnection(spec.serverName);\n if (!connection || connection.status !== \"connected\") {\n return {\n content: [{ type: \"text\" as const, text: `MCP server \"${spec.serverName}\" not connected` }],\n details: { error: \"not_connected\", server: spec.serverName },\n };\n }\n\n let uiSession: UiSessionRuntime | null = null;\n const requestOptions = state.manager.getRequestOptions?.(spec.serverName, signal) ?? (signal ? { signal } : undefined);\n\n const outputGuardOptions = resolveMcpOutputGuardOptions(state.config.settings);\n\n try {\n state.manager.touch(spec.serverName);\n state.manager.incrementInFlight(spec.serverName);\n\n if (spec.resourceUri) {\n const result = await connection.client.readResource({ uri: spec.resourceUri }, requestOptions);\n const content = (result.contents ?? []).map(c => ({\n type: \"text\" as const,\n text: \"text\" in c ? c.text : (\"blob\" in c ? `[Binary data: ${(c as { mimeType?: string }).mimeType ?? \"unknown\"}]` : JSON.stringify(c)),\n }));\n const guarded = await guardMcpOutput(content.length > 0 ? content : [{ type: \"text\" as const, text: \"(empty resource)\" }], outputGuardOptions);\n return {\n content: guarded.content,\n details: { server: spec.serverName, resourceUri: spec.resourceUri, ...guardedMcpDetails(guarded) },\n };\n }\n\n const hasUi = !!spec.uiResourceUri;\n uiSession = hasUi\n ? await maybeStartUiSession(state, {\n serverName: spec.serverName,\n toolName: spec.originalName,\n toolArgs: params ?? {},\n uiResourceUri: spec.uiResourceUri!,\n streamMode: spec.uiStreamMode,\n })\n : null;\n\n throwIfAborted(signal);\n const resultPromise = connection.client.callTool({\n name: spec.originalName,\n arguments: params ?? {},\n _meta: uiSession?.requestMeta,\n }, undefined, requestOptions);\n\n const result = await abortable(resultPromise, signal);\n throwIfAborted(signal);\n uiSession?.sendToolResult(result as unknown as import(\"@modelcontextprotocol/sdk/types.js\").CallToolResult);\n\n if (result.isError) {\n const mcpContent = (result.content ?? []) as McpContent[];\n const content = transformMcpContent(mcpContent);\n const outputContent = content.length > 0 ? content : [{ type: \"text\" as const, text: \"(empty result)\" }];\n const schemaText = spec.inputSchema ? `\\n\\nExpected parameters:\\n${formatSchema(spec.inputSchema)}` : \"\";\n const guarded = await guardMcpOutput(outputContent, { ...outputGuardOptions, prefix: \"Error: \", suffix: schemaText, emptyTextFallback: \"Tool execution failed\" });\n return {\n content: guarded.content,\n details: { error: \"tool_error\", server: spec.serverName, ...guardedMcpDetails(guarded) },\n };\n }\n\n const content = resolveMcpResultContent(result as Record<string, unknown>);\n const outputContent = content.length > 0 ? content : [{ type: \"text\" as const, text: \"(empty result)\" }];\n if (hasUi) {\n const uiMessage = uiSession?.reused\n ? \"Updated the open UI.\"\n : \"📺 Interactive UI is now open in your browser. I'll respond to your prompts and intents as you interact with it.\";\n const guarded = await guardMcpOutput(outputContent, { ...outputGuardOptions, suffix: `\\n\\n${uiMessage}` });\n return {\n content: guarded.content,\n details: { server: spec.serverName, tool: spec.originalName, uiOpen: true, ...guardedMcpDetails(guarded) },\n };\n }\n\n const guarded = await guardMcpOutput(outputContent, { ...outputGuardOptions });\n return {\n content: guarded.content,\n details: { server: spec.serverName, tool: spec.originalName, ...guardedMcpDetails(guarded) },\n };\n } catch (error) {\n if (error instanceof UrlElicitationRequiredError) {\n const action = await state.manager.handleUrlElicitationRequired(spec.serverName, error);\n const message = action === \"accept\"\n ? \"The original MCP tool did not run. Complete the opened browser interaction, then retry the tool.\"\n : `The URL interaction was ${action === \"decline\" ? \"declined\" : \"cancelled\"}.`;\n uiSession?.sendToolCancelled(message);\n return {\n content: [{ type: \"text\" as const, text: message }],\n details: { error: \"url_elicitation_required\", server: spec.serverName, action },\n };\n }\n const message = error instanceof Error ? error.message : String(error);\n uiSession?.sendToolCancelled(message);\n const schemaText = spec.inputSchema ? `\\n\\nExpected parameters:\\n${formatSchema(spec.inputSchema)}` : \"\";\n const guarded = await guardMcpOutput([{ type: \"text\" as const, text: message }], { ...outputGuardOptions, prefix: \"Failed to call tool: \", suffix: schemaText });\n return {\n content: guarded.content,\n details: { error: \"call_failed\", server: spec.serverName, ...guardedMcpDetails(guarded) },\n };\n } finally {\n if (uiSession?.reused) {\n uiSession.close();\n }\n state.manager.decrementInFlight(spec.serverName);\n state.manager.touch(spec.serverName);\n }\n };\n}\n"]}
|
|
@@ -5,7 +5,7 @@ import { formatSchema } from "./tool-metadata.js";
|
|
|
5
5
|
import { resolveMcpResultContent, transformMcpContent } from "./tool-registrar.js";
|
|
6
6
|
import { guardMcpOutput, guardedMcpDetails, resolveMcpOutputGuardOptions } from "./mcp-output-guard.js";
|
|
7
7
|
import { maybeStartUiSession } from "./ui-session.js";
|
|
8
|
-
import {
|
|
8
|
+
import { supportsOAuth } from "./mcp-auth-flow.js";
|
|
9
9
|
import { formatAuthRequiredMessage } from "./utils.js";
|
|
10
10
|
function getDirectAuthRequiredMessage(state, serverName, defaultMessage = `MCP server "${serverName}" requires OAuth authentication. Run mcp({ action: "auth-start", server: "${serverName}" }) to get a browser URL, or /mcp-auth ${serverName} in an interactive local session.`) {
|
|
11
11
|
return formatAuthRequiredMessage(state.config, serverName, defaultMessage);
|
|
@@ -33,7 +33,7 @@ async function attemptDirectAutoAuth(state, serverName, signal) {
|
|
|
33
33
|
};
|
|
34
34
|
}
|
|
35
35
|
try {
|
|
36
|
-
await abortable(authenticate(serverName, definition.url, definition), signal);
|
|
36
|
+
await abortable(state.authFlow.authenticate(serverName, definition.url, definition), signal);
|
|
37
37
|
throwIfAborted(signal);
|
|
38
38
|
return { status: "success" };
|
|
39
39
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"direct-tool-executor.js","sourceRoot":"","sources":["../../../src/builtin-extensions/pi-mcp-adapter/direct-tool-executor.ts"],"names":[],"mappings":"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","sourcesContent":["// @ts-nocheck\nimport type { AgentToolResult, AgentToolUpdateCallback, ExtensionContext } from \"@ashx-j/lunr\";\nimport { UrlElicitationRequiredError } from \"@modelcontextprotocol/sdk/types.js\";\nimport type { McpExtensionState } from \"./state.ts\";\nimport type { DirectToolSpec, McpContent } from \"./types.ts\";\nimport { lazyConnect, getFailureAgeSeconds } from \"./init.ts\";\nimport { abortable, throwIfAborted } from \"./abort.ts\";\nimport { formatSchema } from \"./tool-metadata.ts\";\nimport { resolveMcpResultContent, transformMcpContent } from \"./tool-registrar.ts\";\nimport { guardMcpOutput, guardedMcpDetails, resolveMcpOutputGuardOptions } from \"./mcp-output-guard.ts\";\nimport { maybeStartUiSession, type UiSessionRuntime } from \"./ui-session.ts\";\nimport { authenticate, supportsOAuth } from \"./mcp-auth-flow.ts\";\nimport { formatAuthRequiredMessage } from \"./utils.ts\";\n\ntype DirectAutoAuthResult =\n | { status: \"skipped\" }\n | { status: \"success\" }\n | { status: \"failed\"; message: string };\n\nfunction getDirectAuthRequiredMessage(\n state: McpExtensionState,\n serverName: string,\n defaultMessage = `MCP server \"${serverName}\" requires OAuth authentication. Run mcp({ action: \"auth-start\", server: \"${serverName}\" }) to get a browser URL, or /mcp-auth ${serverName} in an interactive local session.`,\n): string {\n return formatAuthRequiredMessage(state.config, serverName, defaultMessage);\n}\n\nfunction getDirectAuthFailedMessage(state: McpExtensionState, serverName: string, message: string): string {\n const customGuidance = state.config.settings?.authRequiredMessage;\n if (customGuidance) {\n return `OAuth authentication failed for \"${serverName}\": ${message}. ${getDirectAuthRequiredMessage(state, serverName)}`;\n }\n return `OAuth authentication failed for \"${serverName}\": ${message}. Run mcp({ action: \"auth-start\", server: \"${serverName}\" }) to get a browser URL, or /mcp-auth ${serverName} in an interactive local session.`;\n}\n\nasync function attemptDirectAutoAuth(\n state: McpExtensionState,\n serverName: string,\n signal?: AbortSignal,\n): Promise<DirectAutoAuthResult> {\n if (state.config.settings?.autoAuth !== true) {\n return { status: \"skipped\" };\n }\n\n const definition = state.config.mcpServers[serverName];\n if (!definition || !supportsOAuth(definition) || !definition.url) {\n return { status: \"skipped\" };\n }\n\n const grantType = definition.oauth ? definition.oauth.grantType ?? \"authorization_code\" : \"authorization_code\";\n if (!state.ui && grantType !== \"client_credentials\") {\n return {\n status: \"failed\",\n message: getDirectAuthRequiredMessage(\n state,\n serverName,\n `MCP server \"${serverName}\" requires OAuth authentication. Run mcp({ action: \"auth-start\", server: \"${serverName}\" }) to get a browser URL, or /mcp-auth ${serverName} in an interactive local session.`,\n ),\n };\n }\n\n try {\n await abortable(authenticate(serverName, definition.url, definition), signal);\n throwIfAborted(signal);\n return { status: \"success\" };\n } catch (error) {\n throwIfAborted(signal);\n const message = error instanceof Error ? error.message : String(error);\n return {\n status: \"failed\",\n message: getDirectAuthFailedMessage(state, serverName, message),\n };\n }\n}\n\ntype DirectToolExecute = (\n toolCallId: string,\n params: Record<string, unknown>,\n signal: AbortSignal | undefined,\n onUpdate: AgentToolUpdateCallback<Record<string, unknown>> | undefined,\n ctx: ExtensionContext,\n) => Promise<AgentToolResult<Record<string, unknown>>>;\n\nexport function createDirectToolExecutor(\n getState: () => McpExtensionState | null,\n getInitPromise: () => Promise<McpExtensionState> | null,\n spec: DirectToolSpec\n): DirectToolExecute {\n return async function execute(_toolCallId, params, signal) {\n throwIfAborted(signal);\n let state = getState();\n const initPromise = getInitPromise();\n\n if (!state && initPromise) {\n try {\n state = await initPromise;\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [{ type: \"text\" as const, text: `MCP initialization failed: ${message}` }],\n details: { error: \"init_failed\", message },\n };\n }\n }\n if (!state) {\n return {\n content: [{ type: \"text\" as const, text: \"MCP not initialized\" }],\n details: { error: \"not_initialized\" },\n };\n }\n\n let connected = await lazyConnect(state, spec.serverName, signal);\n throwIfAborted(signal);\n let autoAuthAttempted = false;\n\n if (!connected && state.manager.getConnection(spec.serverName)?.status === \"needs-auth\") {\n autoAuthAttempted = true;\n const autoAuth = await attemptDirectAutoAuth(state, spec.serverName, signal);\n throwIfAborted(signal);\n if (autoAuth.status === \"failed\") {\n return {\n content: [{ type: \"text\" as const, text: autoAuth.message }],\n details: { error: \"auth_required\", server: spec.serverName, message: autoAuth.message },\n };\n }\n if (autoAuth.status === \"success\") {\n await state.manager.close(spec.serverName);\n throwIfAborted(signal);\n state.failureTracker.delete(spec.serverName);\n connected = await lazyConnect(state, spec.serverName, signal);\n throwIfAborted(signal);\n }\n }\n\n if (!connected) {\n const authConnection = state.manager.getConnection(spec.serverName);\n if (authConnection?.status === \"needs-auth\") {\n const message = getDirectAuthRequiredMessage(state, spec.serverName);\n return {\n content: [{ type: \"text\" as const, text: message }],\n details: { error: \"auth_required\", server: spec.serverName, message, autoAuthAttempted },\n };\n }\n const failedAgo = getFailureAgeSeconds(state, spec.serverName);\n return {\n content: [{ type: \"text\" as const, text: `MCP server \"${spec.serverName}\" not available${failedAgo !== null ? ` (failed ${failedAgo}s ago)` : \"\"}` }],\n details: { error: \"server_unavailable\", server: spec.serverName },\n };\n }\n\n const connection = state.manager.getConnection(spec.serverName);\n if (!connection || connection.status !== \"connected\") {\n return {\n content: [{ type: \"text\" as const, text: `MCP server \"${spec.serverName}\" not connected` }],\n details: { error: \"not_connected\", server: spec.serverName },\n };\n }\n\n let uiSession: UiSessionRuntime | null = null;\n const requestOptions = state.manager.getRequestOptions?.(spec.serverName, signal) ?? (signal ? { signal } : undefined);\n\n const outputGuardOptions = resolveMcpOutputGuardOptions(state.config.settings);\n\n try {\n state.manager.touch(spec.serverName);\n state.manager.incrementInFlight(spec.serverName);\n\n if (spec.resourceUri) {\n const result = await connection.client.readResource({ uri: spec.resourceUri }, requestOptions);\n const content = (result.contents ?? []).map(c => ({\n type: \"text\" as const,\n text: \"text\" in c ? c.text : (\"blob\" in c ? `[Binary data: ${(c as { mimeType?: string }).mimeType ?? \"unknown\"}]` : JSON.stringify(c)),\n }));\n const guarded = await guardMcpOutput(content.length > 0 ? content : [{ type: \"text\" as const, text: \"(empty resource)\" }], outputGuardOptions);\n return {\n content: guarded.content,\n details: { server: spec.serverName, resourceUri: spec.resourceUri, ...guardedMcpDetails(guarded) },\n };\n }\n\n const hasUi = !!spec.uiResourceUri;\n uiSession = hasUi\n ? await maybeStartUiSession(state, {\n serverName: spec.serverName,\n toolName: spec.originalName,\n toolArgs: params ?? {},\n uiResourceUri: spec.uiResourceUri!,\n streamMode: spec.uiStreamMode,\n })\n : null;\n\n throwIfAborted(signal);\n const resultPromise = connection.client.callTool({\n name: spec.originalName,\n arguments: params ?? {},\n _meta: uiSession?.requestMeta,\n }, undefined, requestOptions);\n\n const result = await abortable(resultPromise, signal);\n throwIfAborted(signal);\n uiSession?.sendToolResult(result as unknown as import(\"@modelcontextprotocol/sdk/types.js\").CallToolResult);\n\n if (result.isError) {\n const mcpContent = (result.content ?? []) as McpContent[];\n const content = transformMcpContent(mcpContent);\n const outputContent = content.length > 0 ? content : [{ type: \"text\" as const, text: \"(empty result)\" }];\n const schemaText = spec.inputSchema ? `\\n\\nExpected parameters:\\n${formatSchema(spec.inputSchema)}` : \"\";\n const guarded = await guardMcpOutput(outputContent, { ...outputGuardOptions, prefix: \"Error: \", suffix: schemaText, emptyTextFallback: \"Tool execution failed\" });\n return {\n content: guarded.content,\n details: { error: \"tool_error\", server: spec.serverName, ...guardedMcpDetails(guarded) },\n };\n }\n\n const content = resolveMcpResultContent(result as Record<string, unknown>);\n const outputContent = content.length > 0 ? content : [{ type: \"text\" as const, text: \"(empty result)\" }];\n if (hasUi) {\n const uiMessage = uiSession?.reused\n ? \"Updated the open UI.\"\n : \"📺 Interactive UI is now open in your browser. I'll respond to your prompts and intents as you interact with it.\";\n const guarded = await guardMcpOutput(outputContent, { ...outputGuardOptions, suffix: `\\n\\n${uiMessage}` });\n return {\n content: guarded.content,\n details: { server: spec.serverName, tool: spec.originalName, uiOpen: true, ...guardedMcpDetails(guarded) },\n };\n }\n\n const guarded = await guardMcpOutput(outputContent, { ...outputGuardOptions });\n return {\n content: guarded.content,\n details: { server: spec.serverName, tool: spec.originalName, ...guardedMcpDetails(guarded) },\n };\n } catch (error) {\n if (error instanceof UrlElicitationRequiredError) {\n const action = await state.manager.handleUrlElicitationRequired(spec.serverName, error);\n const message = action === \"accept\"\n ? \"The original MCP tool did not run. Complete the opened browser interaction, then retry the tool.\"\n : `The URL interaction was ${action === \"decline\" ? \"declined\" : \"cancelled\"}.`;\n uiSession?.sendToolCancelled(message);\n return {\n content: [{ type: \"text\" as const, text: message }],\n details: { error: \"url_elicitation_required\", server: spec.serverName, action },\n };\n }\n const message = error instanceof Error ? error.message : String(error);\n uiSession?.sendToolCancelled(message);\n const schemaText = spec.inputSchema ? `\\n\\nExpected parameters:\\n${formatSchema(spec.inputSchema)}` : \"\";\n const guarded = await guardMcpOutput([{ type: \"text\" as const, text: message }], { ...outputGuardOptions, prefix: \"Failed to call tool: \", suffix: schemaText });\n return {\n content: guarded.content,\n details: { error: \"call_failed\", server: spec.serverName, ...guardedMcpDetails(guarded) },\n };\n } finally {\n if (uiSession?.reused) {\n uiSession.close();\n }\n state.manager.decrementInFlight(spec.serverName);\n state.manager.touch(spec.serverName);\n }\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"direct-tool-executor.js","sourceRoot":"","sources":["../../../src/builtin-extensions/pi-mcp-adapter/direct-tool-executor.ts"],"names":[],"mappings":"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","sourcesContent":["// @ts-nocheck\nimport type { AgentToolResult, AgentToolUpdateCallback, ExtensionContext } from \"@ashx-j/lunr\";\nimport { UrlElicitationRequiredError } from \"@modelcontextprotocol/sdk/types.js\";\nimport type { McpExtensionState } from \"./state.ts\";\nimport type { DirectToolSpec, McpContent } from \"./types.ts\";\nimport { lazyConnect, getFailureAgeSeconds } from \"./init.ts\";\nimport { abortable, throwIfAborted } from \"./abort.ts\";\nimport { formatSchema } from \"./tool-metadata.ts\";\nimport { resolveMcpResultContent, transformMcpContent } from \"./tool-registrar.ts\";\nimport { guardMcpOutput, guardedMcpDetails, resolveMcpOutputGuardOptions } from \"./mcp-output-guard.ts\";\nimport { maybeStartUiSession, type UiSessionRuntime } from \"./ui-session.ts\";\nimport { supportsOAuth } from \"./mcp-auth-flow.ts\";\nimport { formatAuthRequiredMessage } from \"./utils.ts\";\n\ntype DirectAutoAuthResult =\n | { status: \"skipped\" }\n | { status: \"success\" }\n | { status: \"failed\"; message: string };\n\nfunction getDirectAuthRequiredMessage(\n state: McpExtensionState,\n serverName: string,\n defaultMessage = `MCP server \"${serverName}\" requires OAuth authentication. Run mcp({ action: \"auth-start\", server: \"${serverName}\" }) to get a browser URL, or /mcp-auth ${serverName} in an interactive local session.`,\n): string {\n return formatAuthRequiredMessage(state.config, serverName, defaultMessage);\n}\n\nfunction getDirectAuthFailedMessage(state: McpExtensionState, serverName: string, message: string): string {\n const customGuidance = state.config.settings?.authRequiredMessage;\n if (customGuidance) {\n return `OAuth authentication failed for \"${serverName}\": ${message}. ${getDirectAuthRequiredMessage(state, serverName)}`;\n }\n return `OAuth authentication failed for \"${serverName}\": ${message}. Run mcp({ action: \"auth-start\", server: \"${serverName}\" }) to get a browser URL, or /mcp-auth ${serverName} in an interactive local session.`;\n}\n\nasync function attemptDirectAutoAuth(\n state: McpExtensionState,\n serverName: string,\n signal?: AbortSignal,\n): Promise<DirectAutoAuthResult> {\n if (state.config.settings?.autoAuth !== true) {\n return { status: \"skipped\" };\n }\n\n const definition = state.config.mcpServers[serverName];\n if (!definition || !supportsOAuth(definition) || !definition.url) {\n return { status: \"skipped\" };\n }\n\n const grantType = definition.oauth ? definition.oauth.grantType ?? \"authorization_code\" : \"authorization_code\";\n if (!state.ui && grantType !== \"client_credentials\") {\n return {\n status: \"failed\",\n message: getDirectAuthRequiredMessage(\n state,\n serverName,\n `MCP server \"${serverName}\" requires OAuth authentication. Run mcp({ action: \"auth-start\", server: \"${serverName}\" }) to get a browser URL, or /mcp-auth ${serverName} in an interactive local session.`,\n ),\n };\n }\n\n try {\n await abortable(state.authFlow.authenticate(serverName, definition.url, definition), signal);\n throwIfAborted(signal);\n return { status: \"success\" };\n } catch (error) {\n throwIfAborted(signal);\n const message = error instanceof Error ? error.message : String(error);\n return {\n status: \"failed\",\n message: getDirectAuthFailedMessage(state, serverName, message),\n };\n }\n}\n\ntype DirectToolExecute = (\n toolCallId: string,\n params: Record<string, unknown>,\n signal: AbortSignal | undefined,\n onUpdate: AgentToolUpdateCallback<Record<string, unknown>> | undefined,\n ctx: ExtensionContext,\n) => Promise<AgentToolResult<Record<string, unknown>>>;\n\nexport function createDirectToolExecutor(\n getState: () => McpExtensionState | null,\n getInitPromise: () => Promise<McpExtensionState> | null,\n spec: DirectToolSpec\n): DirectToolExecute {\n return async function execute(_toolCallId, params, signal) {\n throwIfAborted(signal);\n let state = getState();\n const initPromise = getInitPromise();\n\n if (!state && initPromise) {\n try {\n state = await initPromise;\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [{ type: \"text\" as const, text: `MCP initialization failed: ${message}` }],\n details: { error: \"init_failed\", message },\n };\n }\n }\n if (!state) {\n return {\n content: [{ type: \"text\" as const, text: \"MCP not initialized\" }],\n details: { error: \"not_initialized\" },\n };\n }\n\n let connected = await lazyConnect(state, spec.serverName, signal);\n throwIfAborted(signal);\n let autoAuthAttempted = false;\n\n if (!connected && state.manager.getConnection(spec.serverName)?.status === \"needs-auth\") {\n autoAuthAttempted = true;\n const autoAuth = await attemptDirectAutoAuth(state, spec.serverName, signal);\n throwIfAborted(signal);\n if (autoAuth.status === \"failed\") {\n return {\n content: [{ type: \"text\" as const, text: autoAuth.message }],\n details: { error: \"auth_required\", server: spec.serverName, message: autoAuth.message },\n };\n }\n if (autoAuth.status === \"success\") {\n await state.manager.close(spec.serverName);\n throwIfAborted(signal);\n state.failureTracker.delete(spec.serverName);\n connected = await lazyConnect(state, spec.serverName, signal);\n throwIfAborted(signal);\n }\n }\n\n if (!connected) {\n const authConnection = state.manager.getConnection(spec.serverName);\n if (authConnection?.status === \"needs-auth\") {\n const message = getDirectAuthRequiredMessage(state, spec.serverName);\n return {\n content: [{ type: \"text\" as const, text: message }],\n details: { error: \"auth_required\", server: spec.serverName, message, autoAuthAttempted },\n };\n }\n const failedAgo = getFailureAgeSeconds(state, spec.serverName);\n return {\n content: [{ type: \"text\" as const, text: `MCP server \"${spec.serverName}\" not available${failedAgo !== null ? ` (failed ${failedAgo}s ago)` : \"\"}` }],\n details: { error: \"server_unavailable\", server: spec.serverName },\n };\n }\n\n const connection = state.manager.getConnection(spec.serverName);\n if (!connection || connection.status !== \"connected\") {\n return {\n content: [{ type: \"text\" as const, text: `MCP server \"${spec.serverName}\" not connected` }],\n details: { error: \"not_connected\", server: spec.serverName },\n };\n }\n\n let uiSession: UiSessionRuntime | null = null;\n const requestOptions = state.manager.getRequestOptions?.(spec.serverName, signal) ?? (signal ? { signal } : undefined);\n\n const outputGuardOptions = resolveMcpOutputGuardOptions(state.config.settings);\n\n try {\n state.manager.touch(spec.serverName);\n state.manager.incrementInFlight(spec.serverName);\n\n if (spec.resourceUri) {\n const result = await connection.client.readResource({ uri: spec.resourceUri }, requestOptions);\n const content = (result.contents ?? []).map(c => ({\n type: \"text\" as const,\n text: \"text\" in c ? c.text : (\"blob\" in c ? `[Binary data: ${(c as { mimeType?: string }).mimeType ?? \"unknown\"}]` : JSON.stringify(c)),\n }));\n const guarded = await guardMcpOutput(content.length > 0 ? content : [{ type: \"text\" as const, text: \"(empty resource)\" }], outputGuardOptions);\n return {\n content: guarded.content,\n details: { server: spec.serverName, resourceUri: spec.resourceUri, ...guardedMcpDetails(guarded) },\n };\n }\n\n const hasUi = !!spec.uiResourceUri;\n uiSession = hasUi\n ? await maybeStartUiSession(state, {\n serverName: spec.serverName,\n toolName: spec.originalName,\n toolArgs: params ?? {},\n uiResourceUri: spec.uiResourceUri!,\n streamMode: spec.uiStreamMode,\n })\n : null;\n\n throwIfAborted(signal);\n const resultPromise = connection.client.callTool({\n name: spec.originalName,\n arguments: params ?? {},\n _meta: uiSession?.requestMeta,\n }, undefined, requestOptions);\n\n const result = await abortable(resultPromise, signal);\n throwIfAborted(signal);\n uiSession?.sendToolResult(result as unknown as import(\"@modelcontextprotocol/sdk/types.js\").CallToolResult);\n\n if (result.isError) {\n const mcpContent = (result.content ?? []) as McpContent[];\n const content = transformMcpContent(mcpContent);\n const outputContent = content.length > 0 ? content : [{ type: \"text\" as const, text: \"(empty result)\" }];\n const schemaText = spec.inputSchema ? `\\n\\nExpected parameters:\\n${formatSchema(spec.inputSchema)}` : \"\";\n const guarded = await guardMcpOutput(outputContent, { ...outputGuardOptions, prefix: \"Error: \", suffix: schemaText, emptyTextFallback: \"Tool execution failed\" });\n return {\n content: guarded.content,\n details: { error: \"tool_error\", server: spec.serverName, ...guardedMcpDetails(guarded) },\n };\n }\n\n const content = resolveMcpResultContent(result as Record<string, unknown>);\n const outputContent = content.length > 0 ? content : [{ type: \"text\" as const, text: \"(empty result)\" }];\n if (hasUi) {\n const uiMessage = uiSession?.reused\n ? \"Updated the open UI.\"\n : \"📺 Interactive UI is now open in your browser. I'll respond to your prompts and intents as you interact with it.\";\n const guarded = await guardMcpOutput(outputContent, { ...outputGuardOptions, suffix: `\\n\\n${uiMessage}` });\n return {\n content: guarded.content,\n details: { server: spec.serverName, tool: spec.originalName, uiOpen: true, ...guardedMcpDetails(guarded) },\n };\n }\n\n const guarded = await guardMcpOutput(outputContent, { ...outputGuardOptions });\n return {\n content: guarded.content,\n details: { server: spec.serverName, tool: spec.originalName, ...guardedMcpDetails(guarded) },\n };\n } catch (error) {\n if (error instanceof UrlElicitationRequiredError) {\n const action = await state.manager.handleUrlElicitationRequired(spec.serverName, error);\n const message = action === \"accept\"\n ? \"The original MCP tool did not run. Complete the opened browser interaction, then retry the tool.\"\n : `The URL interaction was ${action === \"decline\" ? \"declined\" : \"cancelled\"}.`;\n uiSession?.sendToolCancelled(message);\n return {\n content: [{ type: \"text\" as const, text: message }],\n details: { error: \"url_elicitation_required\", server: spec.serverName, action },\n };\n }\n const message = error instanceof Error ? error.message : String(error);\n uiSession?.sendToolCancelled(message);\n const schemaText = spec.inputSchema ? `\\n\\nExpected parameters:\\n${formatSchema(spec.inputSchema)}` : \"\";\n const guarded = await guardMcpOutput([{ type: \"text\" as const, text: message }], { ...outputGuardOptions, prefix: \"Failed to call tool: \", suffix: schemaText });\n return {\n content: guarded.content,\n details: { error: \"call_failed\", server: spec.serverName, ...guardedMcpDetails(guarded) },\n };\n } finally {\n if (uiSession?.reused) {\n uiSession.close();\n }\n state.manager.decrementInFlight(spec.serverName);\n state.manager.touch(spec.serverName);\n }\n };\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"host-html-template.d.ts","sourceRoot":"","sources":["../../../src/builtin-extensions/pi-mcp-adapter/host-html-template.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAKlF,MAAM,WAAW,qBAAqB;IACpC,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,cAAc,EAAE,MAAM,CAAC;IACvB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,WAAW,CAAC,EAAE,aAAa,CAAC;IAC5B,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,qBAAqB,GAAG,MAAM,CAkV1E;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,aAAa,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CA2BtF;AAOD,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAQjF","sourcesContent":["// @ts-nocheck\nimport type { UiHostContext, UiResourceContent, UiResourceCsp } from \"./types.ts\";\n\n// Use locally bundled AppBridge to avoid CDN Zod bundling issues\nconst DEFAULT_APP_BRIDGE_MODULE_URL = \"/app-bridge.bundle.js\";\n\nexport interface HostHtmlTemplateInput {\n sessionToken: string;\n serverName: string;\n toolName: string;\n toolArgs: Record<string, unknown>;\n resource: UiResourceContent;\n allowAttribute: string;\n requireToolConsent: boolean;\n cacheToolConsent: boolean;\n hostContext?: UiHostContext;\n appBridgeModuleUrl?: string;\n}\n\nexport function buildHostHtmlTemplate(input: HostHtmlTemplateInput): string {\n const cspContent = buildCspMetaContent(input.resource.meta.csp);\n const resourceHtml = applyCspMeta(input.resource.html, cspContent);\n const hostContext = input.hostContext ?? {};\n\n const sessionToken = safeInlineJSON(input.sessionToken);\n const toolArgs = safeInlineJSON(input.toolArgs);\n const uiHtml = safeInlineJSON(resourceHtml);\n const serverName = safeInlineJSON(input.serverName);\n const toolName = safeInlineJSON(input.toolName);\n const hostContextJson = safeInlineJSON(hostContext);\n const allowAttribute = safeInlineJSON(input.allowAttribute);\n const requireToolConsent = safeInlineJSON(input.requireToolConsent);\n const cacheToolConsent = safeInlineJSON(input.cacheToolConsent);\n const moduleUrl = safeInlineJSON(input.appBridgeModuleUrl ?? DEFAULT_APP_BRIDGE_MODULE_URL);\n\n return `<!doctype html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n <title>MCP UI - ${escapeHtml(input.serverName)} / ${escapeHtml(input.toolName)}</title>\n <style>\n :root {\n color-scheme: light dark;\n --bg: #0f1115;\n --surface: #181c22;\n --text: #ecf0f5;\n --muted: #a9b2bf;\n --accent: #43c0ff;\n --border: rgba(255, 255, 255, 0.12);\n --good: #34d399;\n --warn: #fbbf24;\n --bad: #f87171;\n }\n @media (prefers-color-scheme: light) {\n :root {\n --bg: #f6f7fb;\n --surface: #ffffff;\n --text: #1d2939;\n --muted: #667085;\n --accent: #0ea5e9;\n --border: rgba(15, 23, 42, 0.14);\n --good: #059669;\n --warn: #b45309;\n --bad: #b91c1c;\n }\n }\n * { box-sizing: border-box; }\n html, body { margin: 0; padding: 0; height: 100%; font-family: ui-sans-serif, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif; background: var(--bg); color: var(--text); }\n body { display: flex; flex-direction: column; min-height: 100vh; }\n header { background: var(--surface); border-bottom: 1px solid var(--border); padding: 10px 14px; display: flex; align-items: center; justify-content: space-between; gap: 10px; }\n .title { display: flex; gap: 8px; align-items: baseline; min-width: 0; }\n .server { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.08em; white-space: nowrap; }\n .tool { font-size: 14px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n .badge { border: 1px solid var(--border); border-radius: 999px; padding: 2px 8px; font-size: 11px; color: var(--muted); white-space: nowrap; }\n .controls { display: flex; gap: 8px; align-items: center; }\n .status { font-size: 12px; color: var(--muted); white-space: nowrap; }\n button { border: 1px solid var(--border); background: transparent; color: var(--text); border-radius: 8px; padding: 6px 10px; cursor: pointer; font-size: 12px; }\n button.primary { border-color: color-mix(in srgb, var(--good) 40%, var(--border) 60%); color: var(--good); }\n button.danger { border-color: color-mix(in srgb, var(--bad) 40%, var(--border) 60%); color: var(--bad); }\n button:hover { background: color-mix(in srgb, var(--surface) 75%, var(--accent) 25%); }\n main { flex: 1; min-height: 0; padding: 10px; display: flex; }\n iframe { width: 100%; height: 100%; border: 1px solid var(--border); border-radius: 10px; background: white; }\n .overlay { position: fixed; inset: 0; background: color-mix(in srgb, var(--bg) 90%, black 10%); display: none; align-items: center; justify-content: center; z-index: 2; }\n .overlay.visible { display: flex; }\n .panel { width: min(680px, calc(100vw - 40px)); background: var(--surface); border: 1px solid var(--border); border-radius: 12px; padding: 18px; }\n .panel h2 { margin: 0 0 8px; font-size: 16px; }\n .panel p { margin: 0; color: var(--muted); line-height: 1.4; font-size: 14px; white-space: pre-wrap; }\n </style>\n</head>\n<body>\n <header>\n <div class=\"title\">\n <span class=\"server\">MCP · <span id=\"server-name\"></span></span>\n <span class=\"tool\" id=\"tool-name\"></span>\n <span class=\"badge\">Sandboxed</span>\n </div>\n <div class=\"controls\">\n <span class=\"status\" id=\"status\">Loading UI...</span>\n <button class=\"primary\" id=\"done-btn\" title=\"Cmd/Ctrl+Enter\">Done</button>\n <button class=\"danger\" id=\"cancel-btn\" title=\"Escape\">Cancel</button>\n </div>\n </header>\n <main>\n <iframe id=\"mcp-app\" referrerpolicy=\"no-referrer\"></iframe>\n </main>\n <div class=\"overlay\" id=\"error-overlay\">\n <div class=\"panel\">\n <h2>UI Error</h2>\n <p id=\"error-message\"></p>\n </div>\n </div>\n <script type=\"module\">\n import { AppBridge, PostMessageTransport } from ${moduleUrl};\n\n const SESSION_TOKEN = ${sessionToken};\n const SERVER_NAME = ${serverName};\n const TOOL_NAME = ${toolName};\n const TOOL_ARGS = ${toolArgs};\n const HOST_CONTEXT = ${hostContextJson};\n const ALLOW_ATTRIBUTE = ${allowAttribute};\n const REQUIRE_TOOL_CONSENT = ${requireToolConsent};\n const CACHE_TOOL_CONSENT = ${cacheToolConsent};\n const STREAM_CONTEXT_KEY = \"pi-mcp-adapter/stream\";\n const STREAM_PATCH_METHOD = \"notifications/pi-mcp-adapter/ui-result-patch\";\n\n const iframe = document.getElementById(\"mcp-app\");\n const statusNode = document.getElementById(\"status\");\n const doneBtn = document.getElementById(\"done-btn\");\n const cancelBtn = document.getElementById(\"cancel-btn\");\n const errorOverlay = document.getElementById(\"error-overlay\");\n const errorMessage = document.getElementById(\"error-message\");\n\n document.getElementById(\"server-name\").textContent = SERVER_NAME;\n document.getElementById(\"tool-name\").textContent = TOOL_NAME;\n\n const setStatus = (text, isError = false) => {\n statusNode.textContent = text;\n statusNode.style.color = isError ? \"var(--bad)\" : \"var(--muted)\";\n };\n\n const showError = (message) => {\n errorMessage.textContent = message;\n errorOverlay.classList.add(\"visible\");\n setStatus(\"Error\", true);\n };\n\n const post = async (endpoint, params) => {\n const response = await fetch(endpoint, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ token: SESSION_TOKEN, params }),\n });\n\n const body = await response.json().catch(() => ({ ok: false, error: \"Invalid JSON response\" }));\n if (!response.ok || !body.ok) {\n const message = body.error || (\"HTTP \" + response.status);\n throw new Error(message);\n }\n return body.result ?? {};\n };\n\n let consentGranted = !REQUIRE_TOOL_CONSENT;\n const initialStreamContext = HOST_CONTEXT?.[STREAM_CONTEXT_KEY];\n const streamMode = initialStreamContext?.mode === \"stream-first\" ? \"stream-first\" : \"eager\";\n\n const bridge = new AppBridge(\n null,\n { name: \"pi\", version: \"1.0.0\" },\n { serverTools: {}, openLinks: {}, logging: {}, updateModelContext: {}, message: {} },\n { hostContext: HOST_CONTEXT }\n );\n\n bridge.oncalltool = async (params) => {\n if (!consentGranted) {\n const accepted = window.confirm(\"Allow this UI to call server tools for this session?\");\n if (!accepted) {\n await post(\"/proxy/ui/consent\", { approved: false }).catch(() => {});\n return {\n isError: true,\n content: [{ type: \"text\", text: \"Tool call denied by user.\" }],\n };\n }\n await post(\"/proxy/ui/consent\", { approved: true });\n if (CACHE_TOOL_CONSENT) {\n consentGranted = true;\n }\n }\n const result = await post(\"/proxy/tools/call\", params);\n // Notify agent about the tool call\n await post(\"/proxy/ui/message\", {\n type: \"intent\",\n intent: \"call_tool\",\n params: { tool: params.name, arguments: params.arguments, isError: result.isError }\n }).catch(() => {});\n return result;\n };\n\n bridge.onmessage = async (params) => post(\"/proxy/ui/message\", params);\n bridge.onupdatemodelcontext = async (params) => post(\"/proxy/ui/context\", params);\n \n // Also listen for raw postMessage events with custom types (notify, prompt, intent, etc.)\n // These bypass the AppBridge protocol but are used by some MCP UI implementations\n window.addEventListener(\"message\", async (event) => {\n const data = event.data;\n if (!data || typeof data !== \"object\") return;\n \n // Skip AppBridge protocol messages (handled by bridge)\n if (data.jsonrpc || (typeof data.method === \"string\" && (data.method.startsWith(\"app/\") || data.method.startsWith(\"host/\")))) return;\n \n // Handle raw UI action messages\n const msgType = data.type;\n if (typeof msgType !== \"string\") return;\n \n if (msgType === \"notify\" || msgType === \"prompt\" || msgType === \"intent\" || msgType === \"message\") {\n // Standard MCP-UI types - preserve their semantics\n // Support both { type, payload: {...} } and { type, field: value } formats\n const { type: _, payload, ...directFields } = data;\n await post(\"/proxy/ui/message\", { type: msgType, ...directFields, ...(payload || {}) }).catch(() => {});\n } else if (!msgType.startsWith(\"ui-lifecycle-\") && !msgType.startsWith(\"ui-message-\")) {\n // Any other custom type - forward as intent with type as intent name\n // (Skip internal lifecycle/ack messages)\n const payload = data.payload || {};\n await post(\"/proxy/ui/message\", {\n type: \"intent\",\n intent: msgType,\n params: payload,\n }).catch(() => {});\n }\n });\n bridge.ondownloadfile = async (params) => post(\"/proxy/ui/download-file\", params);\n bridge.onrequestdisplaymode = async (params) => post(\"/proxy/ui/request-display-mode\", params);\n bridge.onopenlink = async (params) => {\n const result = await post(\"/proxy/ui/open-link\", params);\n if (!result.isError) {\n window.open(params.url, \"_blank\", \"noopener,noreferrer\");\n // Notify agent about the link open\n await post(\"/proxy/ui/message\", {\n type: \"intent\",\n intent: \"open_link\",\n params: { url: params.url }\n }).catch(() => {});\n }\n return result;\n };\n\n bridge.oninitialized = () => {\n if (streamMode !== \"stream-first\") {\n bridge.sendToolInput({ arguments: TOOL_ARGS });\n }\n setStatus(streamMode === \"stream-first\" ? \"Streaming…\" : \"Connected\");\n };\n\n bridge.onsizechange = ({ width, height }) => {\n if (typeof width === \"number\" && width > 0) {\n iframe.style.minWidth = Math.min(width, window.innerWidth - 24) + \"px\";\n }\n if (typeof height === \"number\" && height > 0) {\n iframe.style.height = Math.max(height, 320) + \"px\";\n }\n };\n\n if (ALLOW_ATTRIBUTE) {\n iframe.setAttribute(\"allow\", ALLOW_ATTRIBUTE);\n }\n\n // Connect bridge BEFORE loading iframe to ensure we're listening when the app sends ui/initialize\n try {\n const transport = new PostMessageTransport(iframe.contentWindow, null);\n await bridge.connect(transport);\n } catch (error) {\n console.error(\"[host] Bridge connection failed:\", error);\n showError(\"Failed to initialize AppBridge: \" + String(error));\n }\n\n const iframeLoaded = new Promise((resolve) => {\n iframe.onload = resolve;\n });\n iframe.src = \"/ui-app?session=\" + encodeURIComponent(SESSION_TOKEN);\n await iframeLoaded;\n\n const eventSource = new EventSource(\"/events?session=\" + encodeURIComponent(SESSION_TOKEN));\n eventSource.addEventListener(\"tool-input\", (event) => {\n try {\n bridge.sendToolInput(JSON.parse(event.data));\n } catch (error) {\n showError(\"Failed to forward tool input: \" + String(error));\n }\n });\n eventSource.addEventListener(\"tool-result\", (event) => {\n try {\n bridge.sendToolResult(JSON.parse(event.data));\n } catch (error) {\n showError(\"Failed to forward tool result: \" + String(error));\n }\n });\n eventSource.addEventListener(\"tool-cancelled\", (event) => {\n try {\n bridge.sendToolCancelled(JSON.parse(event.data));\n } catch (error) {\n showError(\"Failed to forward cancellation: \" + String(error));\n }\n });\n eventSource.addEventListener(\"result-patch\", async (event) => {\n try {\n await bridge.notification({\n method: STREAM_PATCH_METHOD,\n params: JSON.parse(event.data),\n });\n } catch (error) {\n showError(\"Failed to forward stream patch: \" + String(error));\n }\n });\n eventSource.addEventListener(\"host-context\", (event) => {\n try {\n bridge.setHostContext(JSON.parse(event.data));\n } catch {}\n });\n eventSource.addEventListener(\"session-complete\", async () => {\n await bridge.teardownResource({}).catch(() => {});\n eventSource.close();\n window.close();\n });\n eventSource.onerror = () => {\n setStatus(\"Connection lost\", true);\n };\n\n const heartbeat = setInterval(() => {\n post(\"/proxy/ui/heartbeat\", {}).catch(() => {});\n }, 10000);\n\n const complete = async (reason) => {\n try {\n await post(\"/proxy/ui/complete\", { reason });\n } catch {}\n try {\n await bridge.teardownResource({});\n } catch {}\n clearInterval(heartbeat);\n eventSource.close();\n window.close();\n };\n\n doneBtn.addEventListener(\"click\", () => complete(\"done\"));\n cancelBtn.addEventListener(\"click\", () => complete(\"cancel\"));\n window.addEventListener(\"keydown\", (event) => {\n if (event.key === \"Escape\") {\n event.preventDefault();\n complete(\"cancel\");\n } else if ((event.metaKey || event.ctrlKey) && event.key === \"Enter\") {\n event.preventDefault();\n complete(\"done\");\n }\n });\n </script>\n</body>\n</html>`;\n}\n\nexport function buildCspMetaContent(csp: UiResourceCsp | undefined): string | undefined {\n if (!csp) return undefined;\n\n const directives: string[] = [];\n directives.push(\"default-src 'none'\");\n\n const scriptSrc = toDirective(\"script-src\", csp.scriptDomains);\n const styleSrc = toDirective(\"style-src\", csp.styleDomains);\n const fontSrc = toDirective(\"font-src\", csp.fontDomains);\n const imgSrc = toDirective(\"img-src\", csp.imgDomains);\n const mediaSrc = toDirective(\"media-src\", csp.mediaDomains);\n const connectSrc = toDirective(\"connect-src\", csp.connectDomains);\n const frameSrc = toDirective(\"frame-src\", csp.frameDomains);\n const workerSrc = toDirective(\"worker-src\", csp.workerDomains);\n const baseUri = toDirective(\"base-uri\", csp.baseUriDomains);\n\n if (scriptSrc) directives.push(scriptSrc);\n if (styleSrc) directives.push(styleSrc);\n if (fontSrc) directives.push(fontSrc);\n if (imgSrc) directives.push(imgSrc);\n if (mediaSrc) directives.push(mediaSrc);\n if (connectSrc) directives.push(connectSrc);\n if (frameSrc) directives.push(frameSrc);\n if (workerSrc) directives.push(workerSrc);\n if (baseUri) directives.push(baseUri);\n\n return directives.join(\"; \");\n}\n\nfunction toDirective(name: string, domains: string[] | undefined): string | null {\n if (!domains || domains.length === 0) return null;\n return `${name} ${domains.join(\" \")}`;\n}\n\nexport function applyCspMeta(html: string, cspContent: string | undefined): string {\n if (!cspContent) return html;\n if (/http-equiv=[\"']Content-Security-Policy[\"']/i.test(html)) return html;\n const metaTag = `<meta http-equiv=\"Content-Security-Policy\" content=\"${escapeHtmlAttribute(cspContent)}\">`;\n if (/<head[^>]*>/i.test(html)) {\n return html.replace(/<head[^>]*>/i, (match) => `${match}\\n${metaTag}`);\n }\n return `${metaTag}\\n${html}`;\n}\n\nfunction safeInlineJSON(value: unknown): string {\n return JSON.stringify(value)\n .replace(/</g, \"\\\\u003c\")\n .replace(/>/g, \"\\\\u003e\")\n .replace(/&/g, \"\\\\u0026\")\n .replace(/\\u2028/g, \"\\\\u2028\")\n .replace(/\\u2029/g, \"\\\\u2029\");\n}\n\nfunction escapeHtml(value: string): string {\n return value\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\");\n}\n\nfunction escapeHtmlAttribute(value: string): string {\n return value\n .replace(/&/g, \"&\")\n .replace(/\"/g, \""\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\");\n}\n"]}
|
|
1
|
+
{"version":3,"file":"host-html-template.d.ts","sourceRoot":"","sources":["../../../src/builtin-extensions/pi-mcp-adapter/host-html-template.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAKlF,MAAM,WAAW,qBAAqB;IACpC,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,cAAc,EAAE,MAAM,CAAC;IACvB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,WAAW,CAAC,EAAE,aAAa,CAAC;IAC5B,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,qBAAqB,GAAG,MAAM,CAkV1E;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,aAAa,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CA2BtF;AAOD,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAQjF","sourcesContent":["// @ts-nocheck\nimport type { UiHostContext, UiResourceContent, UiResourceCsp } from \"./types.ts\";\n\n// Use locally bundled AppBridge to avoid CDN Zod bundling issues\nconst DEFAULT_APP_BRIDGE_MODULE_URL = \"/app-bridge.bundle.js\";\n\nexport interface HostHtmlTemplateInput {\n sessionToken: string;\n serverName: string;\n toolName: string;\n toolArgs: Record<string, unknown>;\n resource: UiResourceContent;\n allowAttribute: string;\n requireToolConsent: boolean;\n cacheToolConsent: boolean;\n hostContext?: UiHostContext;\n appBridgeModuleUrl?: string;\n}\n\nexport function buildHostHtmlTemplate(input: HostHtmlTemplateInput): string {\n const cspContent = buildCspMetaContent(input.resource.meta.csp);\n const resourceHtml = applyCspMeta(input.resource.html, cspContent);\n const hostContext = input.hostContext ?? {};\n\n const sessionToken = safeInlineJSON(input.sessionToken);\n const toolArgs = safeInlineJSON(input.toolArgs);\n const uiHtml = safeInlineJSON(resourceHtml);\n const serverName = safeInlineJSON(input.serverName);\n const toolName = safeInlineJSON(input.toolName);\n const hostContextJson = safeInlineJSON(hostContext);\n const allowAttribute = safeInlineJSON(input.allowAttribute);\n const requireToolConsent = safeInlineJSON(input.requireToolConsent);\n const cacheToolConsent = safeInlineJSON(input.cacheToolConsent);\n const moduleUrl = safeInlineJSON(input.appBridgeModuleUrl ?? DEFAULT_APP_BRIDGE_MODULE_URL);\n\n return `<!doctype html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n <title>MCP UI - ${escapeHtml(input.serverName)} / ${escapeHtml(input.toolName)}</title>\n <style>\n :root {\n color-scheme: light dark;\n --bg: #0f1115;\n --surface: #181c22;\n --text: #ecf0f5;\n --muted: #a9b2bf;\n --accent: #43c0ff;\n --border: rgba(255, 255, 255, 0.12);\n --good: #34d399;\n --warn: #fbbf24;\n --bad: #f87171;\n }\n @media (prefers-color-scheme: light) {\n :root {\n --bg: #f6f7fb;\n --surface: #ffffff;\n --text: #1d2939;\n --muted: #667085;\n --accent: #0ea5e9;\n --border: rgba(15, 23, 42, 0.14);\n --good: #059669;\n --warn: #b45309;\n --bad: #b91c1c;\n }\n }\n * { box-sizing: border-box; }\n html, body { margin: 0; padding: 0; height: 100%; font-family: ui-sans-serif, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif; background: var(--bg); color: var(--text); }\n body { display: flex; flex-direction: column; min-height: 100vh; }\n header { background: var(--surface); border-bottom: 1px solid var(--border); padding: 10px 14px; display: flex; align-items: center; justify-content: space-between; gap: 10px; }\n .title { display: flex; gap: 8px; align-items: baseline; min-width: 0; }\n .server { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.08em; white-space: nowrap; }\n .tool { font-size: 14px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n .badge { border: 1px solid var(--border); border-radius: 999px; padding: 2px 8px; font-size: 11px; color: var(--muted); white-space: nowrap; }\n .controls { display: flex; gap: 8px; align-items: center; }\n .status { font-size: 12px; color: var(--muted); white-space: nowrap; }\n button { border: 1px solid var(--border); background: transparent; color: var(--text); border-radius: 8px; padding: 6px 10px; cursor: pointer; font-size: 12px; }\n button.primary { border-color: color-mix(in srgb, var(--good) 40%, var(--border) 60%); color: var(--good); }\n button.danger { border-color: color-mix(in srgb, var(--bad) 40%, var(--border) 60%); color: var(--bad); }\n button:hover { background: color-mix(in srgb, var(--surface) 75%, var(--accent) 25%); }\n main { flex: 1; min-height: 0; padding: 10px; display: flex; }\n iframe { width: 100%; height: 100%; border: 1px solid var(--border); border-radius: 10px; background: white; }\n .overlay { position: fixed; inset: 0; background: color-mix(in srgb, var(--bg) 90%, black 10%); display: none; align-items: center; justify-content: center; z-index: 2; }\n .overlay.visible { display: flex; }\n .panel { width: min(680px, calc(100vw - 40px)); background: var(--surface); border: 1px solid var(--border); border-radius: 12px; padding: 18px; }\n .panel h2 { margin: 0 0 8px; font-size: 16px; }\n .panel p { margin: 0; color: var(--muted); line-height: 1.4; font-size: 14px; white-space: pre-wrap; }\n </style>\n</head>\n<body>\n <header>\n <div class=\"title\">\n <span class=\"server\">MCP · <span id=\"server-name\"></span></span>\n <span class=\"tool\" id=\"tool-name\"></span>\n <span class=\"badge\">Sandboxed</span>\n </div>\n <div class=\"controls\">\n <span class=\"status\" id=\"status\">Loading UI...</span>\n <button class=\"primary\" id=\"done-btn\" title=\"Cmd/Ctrl+Enter\">Done</button>\n <button class=\"danger\" id=\"cancel-btn\" title=\"Escape\">Cancel</button>\n </div>\n </header>\n <main>\n <iframe id=\"mcp-app\" referrerpolicy=\"no-referrer\"></iframe>\n </main>\n <div class=\"overlay\" id=\"error-overlay\">\n <div class=\"panel\">\n <h2>UI Error</h2>\n <p id=\"error-message\"></p>\n </div>\n </div>\n <script type=\"module\">\n import { AppBridge, PostMessageTransport } from ${moduleUrl};\n\n const SESSION_TOKEN = ${sessionToken};\n const SERVER_NAME = ${serverName};\n const TOOL_NAME = ${toolName};\n const TOOL_ARGS = ${toolArgs};\n const HOST_CONTEXT = ${hostContextJson};\n const ALLOW_ATTRIBUTE = ${allowAttribute};\n const REQUIRE_TOOL_CONSENT = ${requireToolConsent};\n const CACHE_TOOL_CONSENT = ${cacheToolConsent};\n const STREAM_CONTEXT_KEY = \"pi-mcp-adapter/stream\";\n const STREAM_PATCH_METHOD = \"notifications/pi-mcp-adapter/ui-result-patch\";\n\n const iframe = document.getElementById(\"mcp-app\");\n const statusNode = document.getElementById(\"status\");\n const doneBtn = document.getElementById(\"done-btn\");\n const cancelBtn = document.getElementById(\"cancel-btn\");\n const errorOverlay = document.getElementById(\"error-overlay\");\n const errorMessage = document.getElementById(\"error-message\");\n\n document.getElementById(\"server-name\").textContent = SERVER_NAME;\n document.getElementById(\"tool-name\").textContent = TOOL_NAME;\n\n const setStatus = (text, isError = false) => {\n statusNode.textContent = text;\n statusNode.style.color = isError ? \"var(--bad)\" : \"var(--muted)\";\n };\n\n const showError = (message) => {\n errorMessage.textContent = message;\n errorOverlay.classList.add(\"visible\");\n setStatus(\"Error\", true);\n };\n\n const post = async (endpoint, params) => {\n const response = await fetch(endpoint, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ token: SESSION_TOKEN, params }),\n });\n\n const body = await response.json().catch(() => ({ ok: false, error: \"Invalid JSON response\" }));\n if (!response.ok || !body.ok) {\n const message = body.error || (\"HTTP \" + response.status);\n throw new Error(message);\n }\n return body.result ?? {};\n };\n\n let consentGranted = !REQUIRE_TOOL_CONSENT;\n const initialStreamContext = HOST_CONTEXT?.[STREAM_CONTEXT_KEY];\n const streamMode = initialStreamContext?.mode === \"stream-first\" ? \"stream-first\" : \"eager\";\n\n const bridge = new AppBridge(\n null,\n { name: \"lunR\", version: \"1.0.0\" },\n { serverTools: {}, openLinks: {}, logging: {}, updateModelContext: {}, message: {} },\n { hostContext: HOST_CONTEXT }\n );\n\n bridge.oncalltool = async (params) => {\n if (!consentGranted) {\n const accepted = window.confirm(\"Allow this UI to call server tools for this session?\");\n if (!accepted) {\n await post(\"/proxy/ui/consent\", { approved: false }).catch(() => {});\n return {\n isError: true,\n content: [{ type: \"text\", text: \"Tool call denied by user.\" }],\n };\n }\n await post(\"/proxy/ui/consent\", { approved: true });\n if (CACHE_TOOL_CONSENT) {\n consentGranted = true;\n }\n }\n const result = await post(\"/proxy/tools/call\", params);\n // Notify agent about the tool call\n await post(\"/proxy/ui/message\", {\n type: \"intent\",\n intent: \"call_tool\",\n params: { tool: params.name, arguments: params.arguments, isError: result.isError }\n }).catch(() => {});\n return result;\n };\n\n bridge.onmessage = async (params) => post(\"/proxy/ui/message\", params);\n bridge.onupdatemodelcontext = async (params) => post(\"/proxy/ui/context\", params);\n \n // Also listen for raw postMessage events with custom types (notify, prompt, intent, etc.)\n // These bypass the AppBridge protocol but are used by some MCP UI implementations\n window.addEventListener(\"message\", async (event) => {\n const data = event.data;\n if (!data || typeof data !== \"object\") return;\n \n // Skip AppBridge protocol messages (handled by bridge)\n if (data.jsonrpc || (typeof data.method === \"string\" && (data.method.startsWith(\"app/\") || data.method.startsWith(\"host/\")))) return;\n \n // Handle raw UI action messages\n const msgType = data.type;\n if (typeof msgType !== \"string\") return;\n \n if (msgType === \"notify\" || msgType === \"prompt\" || msgType === \"intent\" || msgType === \"message\") {\n // Standard MCP-UI types - preserve their semantics\n // Support both { type, payload: {...} } and { type, field: value } formats\n const { type: _, payload, ...directFields } = data;\n await post(\"/proxy/ui/message\", { type: msgType, ...directFields, ...(payload || {}) }).catch(() => {});\n } else if (!msgType.startsWith(\"ui-lifecycle-\") && !msgType.startsWith(\"ui-message-\")) {\n // Any other custom type - forward as intent with type as intent name\n // (Skip internal lifecycle/ack messages)\n const payload = data.payload || {};\n await post(\"/proxy/ui/message\", {\n type: \"intent\",\n intent: msgType,\n params: payload,\n }).catch(() => {});\n }\n });\n bridge.ondownloadfile = async (params) => post(\"/proxy/ui/download-file\", params);\n bridge.onrequestdisplaymode = async (params) => post(\"/proxy/ui/request-display-mode\", params);\n bridge.onopenlink = async (params) => {\n const result = await post(\"/proxy/ui/open-link\", params);\n if (!result.isError) {\n window.open(params.url, \"_blank\", \"noopener,noreferrer\");\n // Notify agent about the link open\n await post(\"/proxy/ui/message\", {\n type: \"intent\",\n intent: \"open_link\",\n params: { url: params.url }\n }).catch(() => {});\n }\n return result;\n };\n\n bridge.oninitialized = () => {\n if (streamMode !== \"stream-first\") {\n bridge.sendToolInput({ arguments: TOOL_ARGS });\n }\n setStatus(streamMode === \"stream-first\" ? \"Streaming…\" : \"Connected\");\n };\n\n bridge.onsizechange = ({ width, height }) => {\n if (typeof width === \"number\" && width > 0) {\n iframe.style.minWidth = Math.min(width, window.innerWidth - 24) + \"px\";\n }\n if (typeof height === \"number\" && height > 0) {\n iframe.style.height = Math.max(height, 320) + \"px\";\n }\n };\n\n if (ALLOW_ATTRIBUTE) {\n iframe.setAttribute(\"allow\", ALLOW_ATTRIBUTE);\n }\n\n // Connect bridge BEFORE loading iframe to ensure we're listening when the app sends ui/initialize\n try {\n const transport = new PostMessageTransport(iframe.contentWindow, null);\n await bridge.connect(transport);\n } catch (error) {\n console.error(\"[host] Bridge connection failed:\", error);\n showError(\"Failed to initialize AppBridge: \" + String(error));\n }\n\n const iframeLoaded = new Promise((resolve) => {\n iframe.onload = resolve;\n });\n iframe.src = \"/ui-app?session=\" + encodeURIComponent(SESSION_TOKEN);\n await iframeLoaded;\n\n const eventSource = new EventSource(\"/events?session=\" + encodeURIComponent(SESSION_TOKEN));\n eventSource.addEventListener(\"tool-input\", (event) => {\n try {\n bridge.sendToolInput(JSON.parse(event.data));\n } catch (error) {\n showError(\"Failed to forward tool input: \" + String(error));\n }\n });\n eventSource.addEventListener(\"tool-result\", (event) => {\n try {\n bridge.sendToolResult(JSON.parse(event.data));\n } catch (error) {\n showError(\"Failed to forward tool result: \" + String(error));\n }\n });\n eventSource.addEventListener(\"tool-cancelled\", (event) => {\n try {\n bridge.sendToolCancelled(JSON.parse(event.data));\n } catch (error) {\n showError(\"Failed to forward cancellation: \" + String(error));\n }\n });\n eventSource.addEventListener(\"result-patch\", async (event) => {\n try {\n await bridge.notification({\n method: STREAM_PATCH_METHOD,\n params: JSON.parse(event.data),\n });\n } catch (error) {\n showError(\"Failed to forward stream patch: \" + String(error));\n }\n });\n eventSource.addEventListener(\"host-context\", (event) => {\n try {\n bridge.setHostContext(JSON.parse(event.data));\n } catch {}\n });\n eventSource.addEventListener(\"session-complete\", async () => {\n await bridge.teardownResource({}).catch(() => {});\n eventSource.close();\n window.close();\n });\n eventSource.onerror = () => {\n setStatus(\"Connection lost\", true);\n };\n\n const heartbeat = setInterval(() => {\n post(\"/proxy/ui/heartbeat\", {}).catch(() => {});\n }, 10000);\n\n const complete = async (reason) => {\n try {\n await post(\"/proxy/ui/complete\", { reason });\n } catch {}\n try {\n await bridge.teardownResource({});\n } catch {}\n clearInterval(heartbeat);\n eventSource.close();\n window.close();\n };\n\n doneBtn.addEventListener(\"click\", () => complete(\"done\"));\n cancelBtn.addEventListener(\"click\", () => complete(\"cancel\"));\n window.addEventListener(\"keydown\", (event) => {\n if (event.key === \"Escape\") {\n event.preventDefault();\n complete(\"cancel\");\n } else if ((event.metaKey || event.ctrlKey) && event.key === \"Enter\") {\n event.preventDefault();\n complete(\"done\");\n }\n });\n </script>\n</body>\n</html>`;\n}\n\nexport function buildCspMetaContent(csp: UiResourceCsp | undefined): string | undefined {\n if (!csp) return undefined;\n\n const directives: string[] = [];\n directives.push(\"default-src 'none'\");\n\n const scriptSrc = toDirective(\"script-src\", csp.scriptDomains);\n const styleSrc = toDirective(\"style-src\", csp.styleDomains);\n const fontSrc = toDirective(\"font-src\", csp.fontDomains);\n const imgSrc = toDirective(\"img-src\", csp.imgDomains);\n const mediaSrc = toDirective(\"media-src\", csp.mediaDomains);\n const connectSrc = toDirective(\"connect-src\", csp.connectDomains);\n const frameSrc = toDirective(\"frame-src\", csp.frameDomains);\n const workerSrc = toDirective(\"worker-src\", csp.workerDomains);\n const baseUri = toDirective(\"base-uri\", csp.baseUriDomains);\n\n if (scriptSrc) directives.push(scriptSrc);\n if (styleSrc) directives.push(styleSrc);\n if (fontSrc) directives.push(fontSrc);\n if (imgSrc) directives.push(imgSrc);\n if (mediaSrc) directives.push(mediaSrc);\n if (connectSrc) directives.push(connectSrc);\n if (frameSrc) directives.push(frameSrc);\n if (workerSrc) directives.push(workerSrc);\n if (baseUri) directives.push(baseUri);\n\n return directives.join(\"; \");\n}\n\nfunction toDirective(name: string, domains: string[] | undefined): string | null {\n if (!domains || domains.length === 0) return null;\n return `${name} ${domains.join(\" \")}`;\n}\n\nexport function applyCspMeta(html: string, cspContent: string | undefined): string {\n if (!cspContent) return html;\n if (/http-equiv=[\"']Content-Security-Policy[\"']/i.test(html)) return html;\n const metaTag = `<meta http-equiv=\"Content-Security-Policy\" content=\"${escapeHtmlAttribute(cspContent)}\">`;\n if (/<head[^>]*>/i.test(html)) {\n return html.replace(/<head[^>]*>/i, (match) => `${match}\\n${metaTag}`);\n }\n return `${metaTag}\\n${html}`;\n}\n\nfunction safeInlineJSON(value: unknown): string {\n return JSON.stringify(value)\n .replace(/</g, \"\\\\u003c\")\n .replace(/>/g, \"\\\\u003e\")\n .replace(/&/g, \"\\\\u0026\")\n .replace(/\\u2028/g, \"\\\\u2028\")\n .replace(/\\u2029/g, \"\\\\u2029\");\n}\n\nfunction escapeHtml(value: string): string {\n return value\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\");\n}\n\nfunction escapeHtmlAttribute(value: string): string {\n return value\n .replace(/&/g, \"&\")\n .replace(/\"/g, \""\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\");\n}\n"]}
|
|
@@ -147,7 +147,7 @@ export function buildHostHtmlTemplate(input) {
|
|
|
147
147
|
|
|
148
148
|
const bridge = new AppBridge(
|
|
149
149
|
null,
|
|
150
|
-
{ name: "
|
|
150
|
+
{ name: "lunR", version: "1.0.0" },
|
|
151
151
|
{ serverTools: {}, openLinks: {}, logging: {}, updateModelContext: {}, message: {} },
|
|
152
152
|
{ hostContext: HOST_CONTEXT }
|
|
153
153
|
);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"host-html-template.js","sourceRoot":"","sources":["../../../src/builtin-extensions/pi-mcp-adapter/host-html-template.ts"],"names":[],"mappings":"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","sourcesContent":["// @ts-nocheck\nimport type { UiHostContext, UiResourceContent, UiResourceCsp } from \"./types.ts\";\n\n// Use locally bundled AppBridge to avoid CDN Zod bundling issues\nconst DEFAULT_APP_BRIDGE_MODULE_URL = \"/app-bridge.bundle.js\";\n\nexport interface HostHtmlTemplateInput {\n sessionToken: string;\n serverName: string;\n toolName: string;\n toolArgs: Record<string, unknown>;\n resource: UiResourceContent;\n allowAttribute: string;\n requireToolConsent: boolean;\n cacheToolConsent: boolean;\n hostContext?: UiHostContext;\n appBridgeModuleUrl?: string;\n}\n\nexport function buildHostHtmlTemplate(input: HostHtmlTemplateInput): string {\n const cspContent = buildCspMetaContent(input.resource.meta.csp);\n const resourceHtml = applyCspMeta(input.resource.html, cspContent);\n const hostContext = input.hostContext ?? {};\n\n const sessionToken = safeInlineJSON(input.sessionToken);\n const toolArgs = safeInlineJSON(input.toolArgs);\n const uiHtml = safeInlineJSON(resourceHtml);\n const serverName = safeInlineJSON(input.serverName);\n const toolName = safeInlineJSON(input.toolName);\n const hostContextJson = safeInlineJSON(hostContext);\n const allowAttribute = safeInlineJSON(input.allowAttribute);\n const requireToolConsent = safeInlineJSON(input.requireToolConsent);\n const cacheToolConsent = safeInlineJSON(input.cacheToolConsent);\n const moduleUrl = safeInlineJSON(input.appBridgeModuleUrl ?? DEFAULT_APP_BRIDGE_MODULE_URL);\n\n return `<!doctype html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n <title>MCP UI - ${escapeHtml(input.serverName)} / ${escapeHtml(input.toolName)}</title>\n <style>\n :root {\n color-scheme: light dark;\n --bg: #0f1115;\n --surface: #181c22;\n --text: #ecf0f5;\n --muted: #a9b2bf;\n --accent: #43c0ff;\n --border: rgba(255, 255, 255, 0.12);\n --good: #34d399;\n --warn: #fbbf24;\n --bad: #f87171;\n }\n @media (prefers-color-scheme: light) {\n :root {\n --bg: #f6f7fb;\n --surface: #ffffff;\n --text: #1d2939;\n --muted: #667085;\n --accent: #0ea5e9;\n --border: rgba(15, 23, 42, 0.14);\n --good: #059669;\n --warn: #b45309;\n --bad: #b91c1c;\n }\n }\n * { box-sizing: border-box; }\n html, body { margin: 0; padding: 0; height: 100%; font-family: ui-sans-serif, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif; background: var(--bg); color: var(--text); }\n body { display: flex; flex-direction: column; min-height: 100vh; }\n header { background: var(--surface); border-bottom: 1px solid var(--border); padding: 10px 14px; display: flex; align-items: center; justify-content: space-between; gap: 10px; }\n .title { display: flex; gap: 8px; align-items: baseline; min-width: 0; }\n .server { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.08em; white-space: nowrap; }\n .tool { font-size: 14px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n .badge { border: 1px solid var(--border); border-radius: 999px; padding: 2px 8px; font-size: 11px; color: var(--muted); white-space: nowrap; }\n .controls { display: flex; gap: 8px; align-items: center; }\n .status { font-size: 12px; color: var(--muted); white-space: nowrap; }\n button { border: 1px solid var(--border); background: transparent; color: var(--text); border-radius: 8px; padding: 6px 10px; cursor: pointer; font-size: 12px; }\n button.primary { border-color: color-mix(in srgb, var(--good) 40%, var(--border) 60%); color: var(--good); }\n button.danger { border-color: color-mix(in srgb, var(--bad) 40%, var(--border) 60%); color: var(--bad); }\n button:hover { background: color-mix(in srgb, var(--surface) 75%, var(--accent) 25%); }\n main { flex: 1; min-height: 0; padding: 10px; display: flex; }\n iframe { width: 100%; height: 100%; border: 1px solid var(--border); border-radius: 10px; background: white; }\n .overlay { position: fixed; inset: 0; background: color-mix(in srgb, var(--bg) 90%, black 10%); display: none; align-items: center; justify-content: center; z-index: 2; }\n .overlay.visible { display: flex; }\n .panel { width: min(680px, calc(100vw - 40px)); background: var(--surface); border: 1px solid var(--border); border-radius: 12px; padding: 18px; }\n .panel h2 { margin: 0 0 8px; font-size: 16px; }\n .panel p { margin: 0; color: var(--muted); line-height: 1.4; font-size: 14px; white-space: pre-wrap; }\n </style>\n</head>\n<body>\n <header>\n <div class=\"title\">\n <span class=\"server\">MCP · <span id=\"server-name\"></span></span>\n <span class=\"tool\" id=\"tool-name\"></span>\n <span class=\"badge\">Sandboxed</span>\n </div>\n <div class=\"controls\">\n <span class=\"status\" id=\"status\">Loading UI...</span>\n <button class=\"primary\" id=\"done-btn\" title=\"Cmd/Ctrl+Enter\">Done</button>\n <button class=\"danger\" id=\"cancel-btn\" title=\"Escape\">Cancel</button>\n </div>\n </header>\n <main>\n <iframe id=\"mcp-app\" referrerpolicy=\"no-referrer\"></iframe>\n </main>\n <div class=\"overlay\" id=\"error-overlay\">\n <div class=\"panel\">\n <h2>UI Error</h2>\n <p id=\"error-message\"></p>\n </div>\n </div>\n <script type=\"module\">\n import { AppBridge, PostMessageTransport } from ${moduleUrl};\n\n const SESSION_TOKEN = ${sessionToken};\n const SERVER_NAME = ${serverName};\n const TOOL_NAME = ${toolName};\n const TOOL_ARGS = ${toolArgs};\n const HOST_CONTEXT = ${hostContextJson};\n const ALLOW_ATTRIBUTE = ${allowAttribute};\n const REQUIRE_TOOL_CONSENT = ${requireToolConsent};\n const CACHE_TOOL_CONSENT = ${cacheToolConsent};\n const STREAM_CONTEXT_KEY = \"pi-mcp-adapter/stream\";\n const STREAM_PATCH_METHOD = \"notifications/pi-mcp-adapter/ui-result-patch\";\n\n const iframe = document.getElementById(\"mcp-app\");\n const statusNode = document.getElementById(\"status\");\n const doneBtn = document.getElementById(\"done-btn\");\n const cancelBtn = document.getElementById(\"cancel-btn\");\n const errorOverlay = document.getElementById(\"error-overlay\");\n const errorMessage = document.getElementById(\"error-message\");\n\n document.getElementById(\"server-name\").textContent = SERVER_NAME;\n document.getElementById(\"tool-name\").textContent = TOOL_NAME;\n\n const setStatus = (text, isError = false) => {\n statusNode.textContent = text;\n statusNode.style.color = isError ? \"var(--bad)\" : \"var(--muted)\";\n };\n\n const showError = (message) => {\n errorMessage.textContent = message;\n errorOverlay.classList.add(\"visible\");\n setStatus(\"Error\", true);\n };\n\n const post = async (endpoint, params) => {\n const response = await fetch(endpoint, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ token: SESSION_TOKEN, params }),\n });\n\n const body = await response.json().catch(() => ({ ok: false, error: \"Invalid JSON response\" }));\n if (!response.ok || !body.ok) {\n const message = body.error || (\"HTTP \" + response.status);\n throw new Error(message);\n }\n return body.result ?? {};\n };\n\n let consentGranted = !REQUIRE_TOOL_CONSENT;\n const initialStreamContext = HOST_CONTEXT?.[STREAM_CONTEXT_KEY];\n const streamMode = initialStreamContext?.mode === \"stream-first\" ? \"stream-first\" : \"eager\";\n\n const bridge = new AppBridge(\n null,\n { name: \"pi\", version: \"1.0.0\" },\n { serverTools: {}, openLinks: {}, logging: {}, updateModelContext: {}, message: {} },\n { hostContext: HOST_CONTEXT }\n );\n\n bridge.oncalltool = async (params) => {\n if (!consentGranted) {\n const accepted = window.confirm(\"Allow this UI to call server tools for this session?\");\n if (!accepted) {\n await post(\"/proxy/ui/consent\", { approved: false }).catch(() => {});\n return {\n isError: true,\n content: [{ type: \"text\", text: \"Tool call denied by user.\" }],\n };\n }\n await post(\"/proxy/ui/consent\", { approved: true });\n if (CACHE_TOOL_CONSENT) {\n consentGranted = true;\n }\n }\n const result = await post(\"/proxy/tools/call\", params);\n // Notify agent about the tool call\n await post(\"/proxy/ui/message\", {\n type: \"intent\",\n intent: \"call_tool\",\n params: { tool: params.name, arguments: params.arguments, isError: result.isError }\n }).catch(() => {});\n return result;\n };\n\n bridge.onmessage = async (params) => post(\"/proxy/ui/message\", params);\n bridge.onupdatemodelcontext = async (params) => post(\"/proxy/ui/context\", params);\n \n // Also listen for raw postMessage events with custom types (notify, prompt, intent, etc.)\n // These bypass the AppBridge protocol but are used by some MCP UI implementations\n window.addEventListener(\"message\", async (event) => {\n const data = event.data;\n if (!data || typeof data !== \"object\") return;\n \n // Skip AppBridge protocol messages (handled by bridge)\n if (data.jsonrpc || (typeof data.method === \"string\" && (data.method.startsWith(\"app/\") || data.method.startsWith(\"host/\")))) return;\n \n // Handle raw UI action messages\n const msgType = data.type;\n if (typeof msgType !== \"string\") return;\n \n if (msgType === \"notify\" || msgType === \"prompt\" || msgType === \"intent\" || msgType === \"message\") {\n // Standard MCP-UI types - preserve their semantics\n // Support both { type, payload: {...} } and { type, field: value } formats\n const { type: _, payload, ...directFields } = data;\n await post(\"/proxy/ui/message\", { type: msgType, ...directFields, ...(payload || {}) }).catch(() => {});\n } else if (!msgType.startsWith(\"ui-lifecycle-\") && !msgType.startsWith(\"ui-message-\")) {\n // Any other custom type - forward as intent with type as intent name\n // (Skip internal lifecycle/ack messages)\n const payload = data.payload || {};\n await post(\"/proxy/ui/message\", {\n type: \"intent\",\n intent: msgType,\n params: payload,\n }).catch(() => {});\n }\n });\n bridge.ondownloadfile = async (params) => post(\"/proxy/ui/download-file\", params);\n bridge.onrequestdisplaymode = async (params) => post(\"/proxy/ui/request-display-mode\", params);\n bridge.onopenlink = async (params) => {\n const result = await post(\"/proxy/ui/open-link\", params);\n if (!result.isError) {\n window.open(params.url, \"_blank\", \"noopener,noreferrer\");\n // Notify agent about the link open\n await post(\"/proxy/ui/message\", {\n type: \"intent\",\n intent: \"open_link\",\n params: { url: params.url }\n }).catch(() => {});\n }\n return result;\n };\n\n bridge.oninitialized = () => {\n if (streamMode !== \"stream-first\") {\n bridge.sendToolInput({ arguments: TOOL_ARGS });\n }\n setStatus(streamMode === \"stream-first\" ? \"Streaming…\" : \"Connected\");\n };\n\n bridge.onsizechange = ({ width, height }) => {\n if (typeof width === \"number\" && width > 0) {\n iframe.style.minWidth = Math.min(width, window.innerWidth - 24) + \"px\";\n }\n if (typeof height === \"number\" && height > 0) {\n iframe.style.height = Math.max(height, 320) + \"px\";\n }\n };\n\n if (ALLOW_ATTRIBUTE) {\n iframe.setAttribute(\"allow\", ALLOW_ATTRIBUTE);\n }\n\n // Connect bridge BEFORE loading iframe to ensure we're listening when the app sends ui/initialize\n try {\n const transport = new PostMessageTransport(iframe.contentWindow, null);\n await bridge.connect(transport);\n } catch (error) {\n console.error(\"[host] Bridge connection failed:\", error);\n showError(\"Failed to initialize AppBridge: \" + String(error));\n }\n\n const iframeLoaded = new Promise((resolve) => {\n iframe.onload = resolve;\n });\n iframe.src = \"/ui-app?session=\" + encodeURIComponent(SESSION_TOKEN);\n await iframeLoaded;\n\n const eventSource = new EventSource(\"/events?session=\" + encodeURIComponent(SESSION_TOKEN));\n eventSource.addEventListener(\"tool-input\", (event) => {\n try {\n bridge.sendToolInput(JSON.parse(event.data));\n } catch (error) {\n showError(\"Failed to forward tool input: \" + String(error));\n }\n });\n eventSource.addEventListener(\"tool-result\", (event) => {\n try {\n bridge.sendToolResult(JSON.parse(event.data));\n } catch (error) {\n showError(\"Failed to forward tool result: \" + String(error));\n }\n });\n eventSource.addEventListener(\"tool-cancelled\", (event) => {\n try {\n bridge.sendToolCancelled(JSON.parse(event.data));\n } catch (error) {\n showError(\"Failed to forward cancellation: \" + String(error));\n }\n });\n eventSource.addEventListener(\"result-patch\", async (event) => {\n try {\n await bridge.notification({\n method: STREAM_PATCH_METHOD,\n params: JSON.parse(event.data),\n });\n } catch (error) {\n showError(\"Failed to forward stream patch: \" + String(error));\n }\n });\n eventSource.addEventListener(\"host-context\", (event) => {\n try {\n bridge.setHostContext(JSON.parse(event.data));\n } catch {}\n });\n eventSource.addEventListener(\"session-complete\", async () => {\n await bridge.teardownResource({}).catch(() => {});\n eventSource.close();\n window.close();\n });\n eventSource.onerror = () => {\n setStatus(\"Connection lost\", true);\n };\n\n const heartbeat = setInterval(() => {\n post(\"/proxy/ui/heartbeat\", {}).catch(() => {});\n }, 10000);\n\n const complete = async (reason) => {\n try {\n await post(\"/proxy/ui/complete\", { reason });\n } catch {}\n try {\n await bridge.teardownResource({});\n } catch {}\n clearInterval(heartbeat);\n eventSource.close();\n window.close();\n };\n\n doneBtn.addEventListener(\"click\", () => complete(\"done\"));\n cancelBtn.addEventListener(\"click\", () => complete(\"cancel\"));\n window.addEventListener(\"keydown\", (event) => {\n if (event.key === \"Escape\") {\n event.preventDefault();\n complete(\"cancel\");\n } else if ((event.metaKey || event.ctrlKey) && event.key === \"Enter\") {\n event.preventDefault();\n complete(\"done\");\n }\n });\n </script>\n</body>\n</html>`;\n}\n\nexport function buildCspMetaContent(csp: UiResourceCsp | undefined): string | undefined {\n if (!csp) return undefined;\n\n const directives: string[] = [];\n directives.push(\"default-src 'none'\");\n\n const scriptSrc = toDirective(\"script-src\", csp.scriptDomains);\n const styleSrc = toDirective(\"style-src\", csp.styleDomains);\n const fontSrc = toDirective(\"font-src\", csp.fontDomains);\n const imgSrc = toDirective(\"img-src\", csp.imgDomains);\n const mediaSrc = toDirective(\"media-src\", csp.mediaDomains);\n const connectSrc = toDirective(\"connect-src\", csp.connectDomains);\n const frameSrc = toDirective(\"frame-src\", csp.frameDomains);\n const workerSrc = toDirective(\"worker-src\", csp.workerDomains);\n const baseUri = toDirective(\"base-uri\", csp.baseUriDomains);\n\n if (scriptSrc) directives.push(scriptSrc);\n if (styleSrc) directives.push(styleSrc);\n if (fontSrc) directives.push(fontSrc);\n if (imgSrc) directives.push(imgSrc);\n if (mediaSrc) directives.push(mediaSrc);\n if (connectSrc) directives.push(connectSrc);\n if (frameSrc) directives.push(frameSrc);\n if (workerSrc) directives.push(workerSrc);\n if (baseUri) directives.push(baseUri);\n\n return directives.join(\"; \");\n}\n\nfunction toDirective(name: string, domains: string[] | undefined): string | null {\n if (!domains || domains.length === 0) return null;\n return `${name} ${domains.join(\" \")}`;\n}\n\nexport function applyCspMeta(html: string, cspContent: string | undefined): string {\n if (!cspContent) return html;\n if (/http-equiv=[\"']Content-Security-Policy[\"']/i.test(html)) return html;\n const metaTag = `<meta http-equiv=\"Content-Security-Policy\" content=\"${escapeHtmlAttribute(cspContent)}\">`;\n if (/<head[^>]*>/i.test(html)) {\n return html.replace(/<head[^>]*>/i, (match) => `${match}\\n${metaTag}`);\n }\n return `${metaTag}\\n${html}`;\n}\n\nfunction safeInlineJSON(value: unknown): string {\n return JSON.stringify(value)\n .replace(/</g, \"\\\\u003c\")\n .replace(/>/g, \"\\\\u003e\")\n .replace(/&/g, \"\\\\u0026\")\n .replace(/\\u2028/g, \"\\\\u2028\")\n .replace(/\\u2029/g, \"\\\\u2029\");\n}\n\nfunction escapeHtml(value: string): string {\n return value\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\");\n}\n\nfunction escapeHtmlAttribute(value: string): string {\n return value\n .replace(/&/g, \"&\")\n .replace(/\"/g, \""\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\");\n}\n"]}
|
|
1
|
+
{"version":3,"file":"host-html-template.js","sourceRoot":"","sources":["../../../src/builtin-extensions/pi-mcp-adapter/host-html-template.ts"],"names":[],"mappings":"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","sourcesContent":["// @ts-nocheck\nimport type { UiHostContext, UiResourceContent, UiResourceCsp } from \"./types.ts\";\n\n// Use locally bundled AppBridge to avoid CDN Zod bundling issues\nconst DEFAULT_APP_BRIDGE_MODULE_URL = \"/app-bridge.bundle.js\";\n\nexport interface HostHtmlTemplateInput {\n sessionToken: string;\n serverName: string;\n toolName: string;\n toolArgs: Record<string, unknown>;\n resource: UiResourceContent;\n allowAttribute: string;\n requireToolConsent: boolean;\n cacheToolConsent: boolean;\n hostContext?: UiHostContext;\n appBridgeModuleUrl?: string;\n}\n\nexport function buildHostHtmlTemplate(input: HostHtmlTemplateInput): string {\n const cspContent = buildCspMetaContent(input.resource.meta.csp);\n const resourceHtml = applyCspMeta(input.resource.html, cspContent);\n const hostContext = input.hostContext ?? {};\n\n const sessionToken = safeInlineJSON(input.sessionToken);\n const toolArgs = safeInlineJSON(input.toolArgs);\n const uiHtml = safeInlineJSON(resourceHtml);\n const serverName = safeInlineJSON(input.serverName);\n const toolName = safeInlineJSON(input.toolName);\n const hostContextJson = safeInlineJSON(hostContext);\n const allowAttribute = safeInlineJSON(input.allowAttribute);\n const requireToolConsent = safeInlineJSON(input.requireToolConsent);\n const cacheToolConsent = safeInlineJSON(input.cacheToolConsent);\n const moduleUrl = safeInlineJSON(input.appBridgeModuleUrl ?? DEFAULT_APP_BRIDGE_MODULE_URL);\n\n return `<!doctype html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n <title>MCP UI - ${escapeHtml(input.serverName)} / ${escapeHtml(input.toolName)}</title>\n <style>\n :root {\n color-scheme: light dark;\n --bg: #0f1115;\n --surface: #181c22;\n --text: #ecf0f5;\n --muted: #a9b2bf;\n --accent: #43c0ff;\n --border: rgba(255, 255, 255, 0.12);\n --good: #34d399;\n --warn: #fbbf24;\n --bad: #f87171;\n }\n @media (prefers-color-scheme: light) {\n :root {\n --bg: #f6f7fb;\n --surface: #ffffff;\n --text: #1d2939;\n --muted: #667085;\n --accent: #0ea5e9;\n --border: rgba(15, 23, 42, 0.14);\n --good: #059669;\n --warn: #b45309;\n --bad: #b91c1c;\n }\n }\n * { box-sizing: border-box; }\n html, body { margin: 0; padding: 0; height: 100%; font-family: ui-sans-serif, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif; background: var(--bg); color: var(--text); }\n body { display: flex; flex-direction: column; min-height: 100vh; }\n header { background: var(--surface); border-bottom: 1px solid var(--border); padding: 10px 14px; display: flex; align-items: center; justify-content: space-between; gap: 10px; }\n .title { display: flex; gap: 8px; align-items: baseline; min-width: 0; }\n .server { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.08em; white-space: nowrap; }\n .tool { font-size: 14px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n .badge { border: 1px solid var(--border); border-radius: 999px; padding: 2px 8px; font-size: 11px; color: var(--muted); white-space: nowrap; }\n .controls { display: flex; gap: 8px; align-items: center; }\n .status { font-size: 12px; color: var(--muted); white-space: nowrap; }\n button { border: 1px solid var(--border); background: transparent; color: var(--text); border-radius: 8px; padding: 6px 10px; cursor: pointer; font-size: 12px; }\n button.primary { border-color: color-mix(in srgb, var(--good) 40%, var(--border) 60%); color: var(--good); }\n button.danger { border-color: color-mix(in srgb, var(--bad) 40%, var(--border) 60%); color: var(--bad); }\n button:hover { background: color-mix(in srgb, var(--surface) 75%, var(--accent) 25%); }\n main { flex: 1; min-height: 0; padding: 10px; display: flex; }\n iframe { width: 100%; height: 100%; border: 1px solid var(--border); border-radius: 10px; background: white; }\n .overlay { position: fixed; inset: 0; background: color-mix(in srgb, var(--bg) 90%, black 10%); display: none; align-items: center; justify-content: center; z-index: 2; }\n .overlay.visible { display: flex; }\n .panel { width: min(680px, calc(100vw - 40px)); background: var(--surface); border: 1px solid var(--border); border-radius: 12px; padding: 18px; }\n .panel h2 { margin: 0 0 8px; font-size: 16px; }\n .panel p { margin: 0; color: var(--muted); line-height: 1.4; font-size: 14px; white-space: pre-wrap; }\n </style>\n</head>\n<body>\n <header>\n <div class=\"title\">\n <span class=\"server\">MCP · <span id=\"server-name\"></span></span>\n <span class=\"tool\" id=\"tool-name\"></span>\n <span class=\"badge\">Sandboxed</span>\n </div>\n <div class=\"controls\">\n <span class=\"status\" id=\"status\">Loading UI...</span>\n <button class=\"primary\" id=\"done-btn\" title=\"Cmd/Ctrl+Enter\">Done</button>\n <button class=\"danger\" id=\"cancel-btn\" title=\"Escape\">Cancel</button>\n </div>\n </header>\n <main>\n <iframe id=\"mcp-app\" referrerpolicy=\"no-referrer\"></iframe>\n </main>\n <div class=\"overlay\" id=\"error-overlay\">\n <div class=\"panel\">\n <h2>UI Error</h2>\n <p id=\"error-message\"></p>\n </div>\n </div>\n <script type=\"module\">\n import { AppBridge, PostMessageTransport } from ${moduleUrl};\n\n const SESSION_TOKEN = ${sessionToken};\n const SERVER_NAME = ${serverName};\n const TOOL_NAME = ${toolName};\n const TOOL_ARGS = ${toolArgs};\n const HOST_CONTEXT = ${hostContextJson};\n const ALLOW_ATTRIBUTE = ${allowAttribute};\n const REQUIRE_TOOL_CONSENT = ${requireToolConsent};\n const CACHE_TOOL_CONSENT = ${cacheToolConsent};\n const STREAM_CONTEXT_KEY = \"pi-mcp-adapter/stream\";\n const STREAM_PATCH_METHOD = \"notifications/pi-mcp-adapter/ui-result-patch\";\n\n const iframe = document.getElementById(\"mcp-app\");\n const statusNode = document.getElementById(\"status\");\n const doneBtn = document.getElementById(\"done-btn\");\n const cancelBtn = document.getElementById(\"cancel-btn\");\n const errorOverlay = document.getElementById(\"error-overlay\");\n const errorMessage = document.getElementById(\"error-message\");\n\n document.getElementById(\"server-name\").textContent = SERVER_NAME;\n document.getElementById(\"tool-name\").textContent = TOOL_NAME;\n\n const setStatus = (text, isError = false) => {\n statusNode.textContent = text;\n statusNode.style.color = isError ? \"var(--bad)\" : \"var(--muted)\";\n };\n\n const showError = (message) => {\n errorMessage.textContent = message;\n errorOverlay.classList.add(\"visible\");\n setStatus(\"Error\", true);\n };\n\n const post = async (endpoint, params) => {\n const response = await fetch(endpoint, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ token: SESSION_TOKEN, params }),\n });\n\n const body = await response.json().catch(() => ({ ok: false, error: \"Invalid JSON response\" }));\n if (!response.ok || !body.ok) {\n const message = body.error || (\"HTTP \" + response.status);\n throw new Error(message);\n }\n return body.result ?? {};\n };\n\n let consentGranted = !REQUIRE_TOOL_CONSENT;\n const initialStreamContext = HOST_CONTEXT?.[STREAM_CONTEXT_KEY];\n const streamMode = initialStreamContext?.mode === \"stream-first\" ? \"stream-first\" : \"eager\";\n\n const bridge = new AppBridge(\n null,\n { name: \"lunR\", version: \"1.0.0\" },\n { serverTools: {}, openLinks: {}, logging: {}, updateModelContext: {}, message: {} },\n { hostContext: HOST_CONTEXT }\n );\n\n bridge.oncalltool = async (params) => {\n if (!consentGranted) {\n const accepted = window.confirm(\"Allow this UI to call server tools for this session?\");\n if (!accepted) {\n await post(\"/proxy/ui/consent\", { approved: false }).catch(() => {});\n return {\n isError: true,\n content: [{ type: \"text\", text: \"Tool call denied by user.\" }],\n };\n }\n await post(\"/proxy/ui/consent\", { approved: true });\n if (CACHE_TOOL_CONSENT) {\n consentGranted = true;\n }\n }\n const result = await post(\"/proxy/tools/call\", params);\n // Notify agent about the tool call\n await post(\"/proxy/ui/message\", {\n type: \"intent\",\n intent: \"call_tool\",\n params: { tool: params.name, arguments: params.arguments, isError: result.isError }\n }).catch(() => {});\n return result;\n };\n\n bridge.onmessage = async (params) => post(\"/proxy/ui/message\", params);\n bridge.onupdatemodelcontext = async (params) => post(\"/proxy/ui/context\", params);\n \n // Also listen for raw postMessage events with custom types (notify, prompt, intent, etc.)\n // These bypass the AppBridge protocol but are used by some MCP UI implementations\n window.addEventListener(\"message\", async (event) => {\n const data = event.data;\n if (!data || typeof data !== \"object\") return;\n \n // Skip AppBridge protocol messages (handled by bridge)\n if (data.jsonrpc || (typeof data.method === \"string\" && (data.method.startsWith(\"app/\") || data.method.startsWith(\"host/\")))) return;\n \n // Handle raw UI action messages\n const msgType = data.type;\n if (typeof msgType !== \"string\") return;\n \n if (msgType === \"notify\" || msgType === \"prompt\" || msgType === \"intent\" || msgType === \"message\") {\n // Standard MCP-UI types - preserve their semantics\n // Support both { type, payload: {...} } and { type, field: value } formats\n const { type: _, payload, ...directFields } = data;\n await post(\"/proxy/ui/message\", { type: msgType, ...directFields, ...(payload || {}) }).catch(() => {});\n } else if (!msgType.startsWith(\"ui-lifecycle-\") && !msgType.startsWith(\"ui-message-\")) {\n // Any other custom type - forward as intent with type as intent name\n // (Skip internal lifecycle/ack messages)\n const payload = data.payload || {};\n await post(\"/proxy/ui/message\", {\n type: \"intent\",\n intent: msgType,\n params: payload,\n }).catch(() => {});\n }\n });\n bridge.ondownloadfile = async (params) => post(\"/proxy/ui/download-file\", params);\n bridge.onrequestdisplaymode = async (params) => post(\"/proxy/ui/request-display-mode\", params);\n bridge.onopenlink = async (params) => {\n const result = await post(\"/proxy/ui/open-link\", params);\n if (!result.isError) {\n window.open(params.url, \"_blank\", \"noopener,noreferrer\");\n // Notify agent about the link open\n await post(\"/proxy/ui/message\", {\n type: \"intent\",\n intent: \"open_link\",\n params: { url: params.url }\n }).catch(() => {});\n }\n return result;\n };\n\n bridge.oninitialized = () => {\n if (streamMode !== \"stream-first\") {\n bridge.sendToolInput({ arguments: TOOL_ARGS });\n }\n setStatus(streamMode === \"stream-first\" ? \"Streaming…\" : \"Connected\");\n };\n\n bridge.onsizechange = ({ width, height }) => {\n if (typeof width === \"number\" && width > 0) {\n iframe.style.minWidth = Math.min(width, window.innerWidth - 24) + \"px\";\n }\n if (typeof height === \"number\" && height > 0) {\n iframe.style.height = Math.max(height, 320) + \"px\";\n }\n };\n\n if (ALLOW_ATTRIBUTE) {\n iframe.setAttribute(\"allow\", ALLOW_ATTRIBUTE);\n }\n\n // Connect bridge BEFORE loading iframe to ensure we're listening when the app sends ui/initialize\n try {\n const transport = new PostMessageTransport(iframe.contentWindow, null);\n await bridge.connect(transport);\n } catch (error) {\n console.error(\"[host] Bridge connection failed:\", error);\n showError(\"Failed to initialize AppBridge: \" + String(error));\n }\n\n const iframeLoaded = new Promise((resolve) => {\n iframe.onload = resolve;\n });\n iframe.src = \"/ui-app?session=\" + encodeURIComponent(SESSION_TOKEN);\n await iframeLoaded;\n\n const eventSource = new EventSource(\"/events?session=\" + encodeURIComponent(SESSION_TOKEN));\n eventSource.addEventListener(\"tool-input\", (event) => {\n try {\n bridge.sendToolInput(JSON.parse(event.data));\n } catch (error) {\n showError(\"Failed to forward tool input: \" + String(error));\n }\n });\n eventSource.addEventListener(\"tool-result\", (event) => {\n try {\n bridge.sendToolResult(JSON.parse(event.data));\n } catch (error) {\n showError(\"Failed to forward tool result: \" + String(error));\n }\n });\n eventSource.addEventListener(\"tool-cancelled\", (event) => {\n try {\n bridge.sendToolCancelled(JSON.parse(event.data));\n } catch (error) {\n showError(\"Failed to forward cancellation: \" + String(error));\n }\n });\n eventSource.addEventListener(\"result-patch\", async (event) => {\n try {\n await bridge.notification({\n method: STREAM_PATCH_METHOD,\n params: JSON.parse(event.data),\n });\n } catch (error) {\n showError(\"Failed to forward stream patch: \" + String(error));\n }\n });\n eventSource.addEventListener(\"host-context\", (event) => {\n try {\n bridge.setHostContext(JSON.parse(event.data));\n } catch {}\n });\n eventSource.addEventListener(\"session-complete\", async () => {\n await bridge.teardownResource({}).catch(() => {});\n eventSource.close();\n window.close();\n });\n eventSource.onerror = () => {\n setStatus(\"Connection lost\", true);\n };\n\n const heartbeat = setInterval(() => {\n post(\"/proxy/ui/heartbeat\", {}).catch(() => {});\n }, 10000);\n\n const complete = async (reason) => {\n try {\n await post(\"/proxy/ui/complete\", { reason });\n } catch {}\n try {\n await bridge.teardownResource({});\n } catch {}\n clearInterval(heartbeat);\n eventSource.close();\n window.close();\n };\n\n doneBtn.addEventListener(\"click\", () => complete(\"done\"));\n cancelBtn.addEventListener(\"click\", () => complete(\"cancel\"));\n window.addEventListener(\"keydown\", (event) => {\n if (event.key === \"Escape\") {\n event.preventDefault();\n complete(\"cancel\");\n } else if ((event.metaKey || event.ctrlKey) && event.key === \"Enter\") {\n event.preventDefault();\n complete(\"done\");\n }\n });\n </script>\n</body>\n</html>`;\n}\n\nexport function buildCspMetaContent(csp: UiResourceCsp | undefined): string | undefined {\n if (!csp) return undefined;\n\n const directives: string[] = [];\n directives.push(\"default-src 'none'\");\n\n const scriptSrc = toDirective(\"script-src\", csp.scriptDomains);\n const styleSrc = toDirective(\"style-src\", csp.styleDomains);\n const fontSrc = toDirective(\"font-src\", csp.fontDomains);\n const imgSrc = toDirective(\"img-src\", csp.imgDomains);\n const mediaSrc = toDirective(\"media-src\", csp.mediaDomains);\n const connectSrc = toDirective(\"connect-src\", csp.connectDomains);\n const frameSrc = toDirective(\"frame-src\", csp.frameDomains);\n const workerSrc = toDirective(\"worker-src\", csp.workerDomains);\n const baseUri = toDirective(\"base-uri\", csp.baseUriDomains);\n\n if (scriptSrc) directives.push(scriptSrc);\n if (styleSrc) directives.push(styleSrc);\n if (fontSrc) directives.push(fontSrc);\n if (imgSrc) directives.push(imgSrc);\n if (mediaSrc) directives.push(mediaSrc);\n if (connectSrc) directives.push(connectSrc);\n if (frameSrc) directives.push(frameSrc);\n if (workerSrc) directives.push(workerSrc);\n if (baseUri) directives.push(baseUri);\n\n return directives.join(\"; \");\n}\n\nfunction toDirective(name: string, domains: string[] | undefined): string | null {\n if (!domains || domains.length === 0) return null;\n return `${name} ${domains.join(\" \")}`;\n}\n\nexport function applyCspMeta(html: string, cspContent: string | undefined): string {\n if (!cspContent) return html;\n if (/http-equiv=[\"']Content-Security-Policy[\"']/i.test(html)) return html;\n const metaTag = `<meta http-equiv=\"Content-Security-Policy\" content=\"${escapeHtmlAttribute(cspContent)}\">`;\n if (/<head[^>]*>/i.test(html)) {\n return html.replace(/<head[^>]*>/i, (match) => `${match}\\n${metaTag}`);\n }\n return `${metaTag}\\n${html}`;\n}\n\nfunction safeInlineJSON(value: unknown): string {\n return JSON.stringify(value)\n .replace(/</g, \"\\\\u003c\")\n .replace(/>/g, \"\\\\u003e\")\n .replace(/&/g, \"\\\\u0026\")\n .replace(/\\u2028/g, \"\\\\u2028\")\n .replace(/\\u2029/g, \"\\\\u2029\");\n}\n\nfunction escapeHtml(value: string): string {\n return value\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\");\n}\n\nfunction escapeHtmlAttribute(value: string): string {\n return value\n .replace(/&/g, \"&\")\n .replace(/\"/g, \""\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\");\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/builtin-extensions/pi-mcp-adapter/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAA8B,MAAM,iCAAiC,CAAC;AAqChG,MAAM,CAAC,OAAO,UAAU,UAAU,CAAC,EAAE,EAAE,YAAY,QAqgBlD","sourcesContent":["// @ts-nocheck\nimport type { ExtensionAPI, ExtensionContext, ToolInfo } from \"@ashx-j/lunr\";\nimport type { McpExtensionState } from \"./state.ts\";\nimport type { DirectToolSpec, McpConfig } from \"./types.ts\";\nimport type { MetadataCache } from \"./metadata-cache.ts\";\nimport { existsSync } from \"node:fs\";\nimport { Type } from \"typebox\";\nimport { loadMcpConfig } from \"./config.ts\";\nimport { buildProxyDescription, getMissingConfiguredDirectToolServers, resolveDirectTools } from \"./direct-tools.ts\";\nimport { getMetadataCachePath, loadMetadataCache } from \"./metadata-cache.ts\";\nimport { getConfigPathFromArgv, normalizeDirectToolInputSchema, truncateAtWord } from \"./utils.ts\";\nimport { createMcpDirectToolCallRenderer, renderMcpProxyToolCall, renderMcpToolResult } from \"./tool-result-renderer.ts\";\nimport { toolErrorOverride } from \"./error-signal.ts\";\nimport { abortable, throwIfAborted } from \"./abort.ts\";\n\ntype McpHeavyModules = {\n init: typeof import(\"./init.ts\");\n authFlow: typeof import(\"./mcp-auth-flow.ts\");\n commands: typeof import(\"./commands.ts\");\n proxyModes: typeof import(\"./proxy-modes.ts\");\n directToolExecutor: typeof import(\"./direct-tool-executor.ts\");\n};\n\nfunction shouldBackgroundAutostart(config: McpConfig, cache: MetadataCache | null): boolean {\n const serverEntries = Object.entries(config.mcpServers);\n if (serverEntries.length === 0) return false;\n\n if (!existsSync(getMetadataCachePath())) return true;\n\n for (const [, definition] of serverEntries) {\n const mode = definition.lifecycle ?? \"lazy\";\n if (mode === \"keep-alive\" || mode === \"eager\") return true;\n }\n\n if (process.env.MCP_DIRECT_TOOLS === \"__none__\") return false;\n return getMissingConfiguredDirectToolServers(config, cache).length > 0;\n}\n\nexport default function mcpAdapter(pi: ExtensionAPI) {\n let state: McpExtensionState | null = null;\n let initPromise: Promise<McpExtensionState> | null = null;\n let lifecycleGeneration = 0;\n let sessionAbort = new AbortController();\n const initializingStates = new Set<McpExtensionState>();\n const shutdownPromises = new WeakMap<McpExtensionState, Promise<void>>();\n let heavyModules: McpHeavyModules | null = null;\n let heavyModulesPromise: Promise<McpHeavyModules> | null = null;\n const directExecutors = new Map<string, ReturnType<McpHeavyModules[\"directToolExecutor\"][\"createDirectToolExecutor\"]>>();\n\n function loadHeavyModules(): Promise<McpHeavyModules> {\n if (heavyModules) return Promise.resolve(heavyModules);\n if (!heavyModulesPromise) {\n heavyModulesPromise = (async () => {\n const [init, authFlow, commands, proxyModes, directToolExecutor] = await Promise.all([\n import(\"./init.ts\"),\n import(\"./mcp-auth-flow.ts\"),\n import(\"./commands.ts\"),\n import(\"./proxy-modes.ts\"),\n import(\"./direct-tool-executor.ts\"),\n ]);\n const loaded: McpHeavyModules = { init, authFlow, commands, proxyModes, directToolExecutor };\n heavyModules = loaded;\n return loaded;\n })().catch((error) => {\n heavyModulesPromise = null;\n throw error;\n });\n }\n return heavyModulesPromise;\n }\n\n function shutdownState(currentState: McpExtensionState | null, reason: string): Promise<void> {\n if (!currentState) return Promise.resolve();\n const existing = shutdownPromises.get(currentState);\n if (existing) return existing;\n\n const shutdown = (async () => {\n if (currentState.uiServer) {\n currentState.uiServer.close(reason);\n currentState.uiServer = null;\n }\n\n let flushError: unknown;\n try {\n if (heavyModules) {\n heavyModules.init.flushMetadataCache(currentState);\n }\n } catch (error) {\n flushError = error;\n }\n\n try {\n await currentState.lifecycle.gracefulShutdown();\n } catch (error) {\n if (flushError) {\n console.error(\"MCP: graceful shutdown failed after metadata flush error\", error);\n } else {\n throw error;\n }\n }\n\n if (flushError) {\n throw flushError;\n }\n })();\n shutdownPromises.set(currentState, shutdown);\n return shutdown;\n }\n\n async function shutdownInitializingStates(): Promise<void> {\n const pending = [...initializingStates];\n initializingStates.clear();\n await Promise.all(pending.map((entry) => shutdownState(entry, \"initialization_cancelled\")));\n }\n\n async function shutdownLoadedRuntime(): Promise<void> {\n if (!heavyModules) return;\n await heavyModules.authFlow.shutdownOAuth();\n }\n\n async function runInitialize(\n generation: number,\n sessionPi: ExtensionAPI,\n ctx: ExtensionContext,\n ): Promise<McpExtensionState> {\n const signal = sessionAbort.signal;\n const heavy = await loadHeavyModules();\n throwIfAborted(signal);\n if (generation !== lifecycleGeneration) {\n throw new Error(\"MCP initialization aborted (session changed)\");\n }\n\n await heavy.authFlow.initializeOAuth().catch(err => {\n console.error(\"MCP OAuth initialization failed:\", err);\n });\n\n if (generation !== lifecycleGeneration) {\n throw new Error(\"MCP initialization aborted (session changed)\");\n }\n\n let partial: McpExtensionState | undefined;\n try {\n const initialized = await heavy.init.initializeMcp(sessionPi, ctx, {\n signal,\n onState: (entry: McpExtensionState) => {\n partial = entry;\n initializingStates.add(entry);\n },\n });\n if (!partial) {\n partial = initialized;\n initializingStates.add(initialized);\n }\n throwIfAborted(signal);\n return initialized;\n } catch (error) {\n if (partial) {\n initializingStates.delete(partial);\n await shutdownState(partial, \"initialization_failed\");\n }\n throw error;\n } finally {\n if (partial) initializingStates.delete(partial);\n }\n }\n\n function startSessionInit(generation: number, sessionPi: ExtensionAPI, ctx: ExtensionContext): Promise<McpExtensionState> {\n const promise = runInitialize(generation, sessionPi, ctx);\n initPromise = promise;\n\n promise.then(async (nextState) => {\n if (generation !== lifecycleGeneration || initPromise !== promise) {\n try {\n await shutdownState(nextState, \"stale_session_start\");\n } catch (error) {\n console.error(\"MCP: failed to clean stale session state\", error);\n }\n return;\n }\n\n state = nextState;\n if (heavyModules) {\n heavyModules.init.updateStatusBar(nextState);\n }\n initPromise = null;\n }).catch(err => {\n if (generation !== lifecycleGeneration) {\n return;\n }\n if (initPromise !== promise && initPromise !== null) {\n return;\n }\n console.error(\"MCP initialization failed:\", err);\n initPromise = null;\n });\n\n return promise;\n }\n\n async function ensureState(sessionPi: ExtensionAPI, ctx: ExtensionContext, signal?: AbortSignal): Promise<McpExtensionState> {\n throwIfAborted(signal);\n if (state) return state;\n\n const generation = lifecycleGeneration;\n if (!initPromise) {\n startSessionInit(generation, sessionPi, ctx);\n }\n const promise = initPromise;\n if (!promise) {\n throw new Error(\"MCP not initialized\");\n }\n\n try {\n const nextState = await abortable(promise, signal);\n if (generation !== lifecycleGeneration) {\n throw new Error(\"MCP initialization aborted (session changed)\");\n }\n if (state) return state;\n state = nextState;\n if (initPromise === promise) {\n initPromise = null;\n }\n return state;\n } catch (error) {\n if (initPromise === promise && !signal?.aborted) {\n initPromise = null;\n }\n throw error;\n }\n }\n\n function assertCurrentState(currentState: McpExtensionState): void {\n if (currentState !== state) throw new Error(\"MCP session changed before execution\");\n }\n\n function createLazyDirectToolExecute(spec: DirectToolSpec) {\n return async function execute(toolCallId, params, incomingSignal, onUpdate, ctx) {\n const signal = incomingSignal ? AbortSignal.any([incomingSignal, sessionAbort.signal]) : sessionAbort.signal;\n let currentState: McpExtensionState;\n try {\n currentState = await ensureState(pi, ctx, signal);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [{ type: \"text\" as const, text: `MCP initialization failed: ${message}` }],\n details: { error: \"init_failed\", message },\n };\n }\n\n const heavy = await loadHeavyModules();\n throwIfAborted(signal);\n assertCurrentState(currentState);\n let executor = directExecutors.get(spec.prefixedName);\n if (!executor) {\n executor = heavy.directToolExecutor.createDirectToolExecutor(() => currentState, () => null, spec);\n directExecutors.set(spec.prefixedName, executor);\n }\n return executor(toolCallId, params, signal, onUpdate, ctx);\n };\n }\n\n const earlyConfigPath = getConfigPathFromArgv();\n const earlyConfig = loadMcpConfig(earlyConfigPath);\n const earlyCache = loadMetadataCache();\n const prefix = earlyConfig.settings?.toolPrefix ?? \"server\";\n\n const envRaw = process.env.MCP_DIRECT_TOOLS;\n const directSpecs = envRaw === \"__none__\"\n ? []\n : resolveDirectTools(\n earlyConfig,\n earlyCache,\n prefix,\n envRaw?.split(\",\").map(s => s.trim()).filter(Boolean),\n );\n const missingConfiguredDirectToolServers = getMissingConfiguredDirectToolServers(earlyConfig, earlyCache);\n const shouldRegisterProxyTool =\n earlyConfig.settings?.disableProxyTool !== true\n || directSpecs.length === 0\n || missingConfiguredDirectToolServers.length > 0;\n\n for (const spec of directSpecs) {\n (pi.registerTool as (tool: unknown) => unknown)({\n name: spec.prefixedName,\n label: `MCP: ${spec.originalName}`,\n description: `${spec.description || \"(no description)\"}\\nUnavailable in read-only mode; switch to yolo or auto to call.`,\n promptSnippet: truncateAtWord(spec.description, 100) || `MCP tool from ${spec.serverName}`,\n parameters: Type.Unsafe(normalizeDirectToolInputSchema(spec.inputSchema) as never),\n execute: createLazyDirectToolExecute(spec),\n renderCall: createMcpDirectToolCallRenderer(spec.prefixedName),\n renderResult: renderMcpToolResult,\n });\n }\n\n const getPiTools = (): ToolInfo[] => pi.getAllTools();\n\n pi.registerFlag(\"mcp-config\", {\n description: \"Path to MCP config file\",\n type: \"string\",\n });\n\n pi.on(\"session_start\", async (_event, ctx) => {\n const generation = ++lifecycleGeneration;\n sessionAbort.abort(new Error(\"MCP session changed\"));\n sessionAbort = new AbortController();\n const previousState = state;\n state = null;\n initPromise = null;\n directExecutors.clear();\n\n try {\n await Promise.all([\n shutdownState(previousState, \"session_restart\"),\n shutdownInitializingStates(),\n shutdownLoadedRuntime(),\n ]);\n } catch (error) {\n console.error(\"MCP: failed to shut down previous session state\", error);\n }\n\n if (generation !== lifecycleGeneration) {\n return;\n }\n\n const configPath = (pi.getFlag(\"mcp-config\") as string | undefined) ?? earlyConfigPath;\n const sessionConfig = loadMcpConfig(configPath, ctx.cwd);\n const sessionCache = loadMetadataCache();\n\n if (!shouldBackgroundAutostart(sessionConfig, sessionCache)) {\n return;\n }\n\n startSessionInit(generation, pi, ctx);\n });\n\n pi.on(\"session_shutdown\", async () => {\n ++lifecycleGeneration;\n sessionAbort.abort(new Error(\"MCP session ended\"));\n const currentState = state;\n state = null;\n initPromise = null;\n directExecutors.clear();\n\n try {\n await Promise.all([\n shutdownState(currentState, \"session_shutdown\"),\n shutdownInitializingStates(),\n shutdownLoadedRuntime(),\n ]);\n } catch (error) {\n console.error(\"MCP: session shutdown cleanup failed\", error);\n }\n });\n\n // Re-flag returned MCP tool failures so pi registers them as errors (see toolErrorOverride).\n pi.on(\"tool_result\", (event) => toolErrorOverride(event.details));\n\n pi.registerCommand(\"mcp\", {\n description: \"Show MCP server status\",\n handler: async (args, ctx) => {\n let currentState: McpExtensionState;\n try {\n currentState = await ensureState(pi, ctx);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n if (ctx.hasUI) ctx.ui.notify(`MCP initialization failed: ${message}`, \"error\");\n return;\n }\n\n const heavy = await loadHeavyModules();\n assertCurrentState(currentState);\n const parts = args?.trim()?.split(/\\s+/) ?? [];\n const subcommand = parts[0] ?? \"\";\n const targetServer = parts[1];\n const rest = parts.slice(1).join(\" \");\n\n switch (subcommand) {\n case \"reconnect\":\n await heavy.commands.reconnectServers(currentState, ctx, targetServer);\n break;\n case \"tools\":\n await heavy.commands.showTools(currentState, ctx);\n break;\n case \"setup\": {\n const result = await heavy.commands.openMcpSetup(currentState, pi, ctx, earlyConfigPath, \"setup\");\n if (result?.configChanged) {\n await ctx.reload();\n return;\n }\n break;\n }\n case \"logout\": {\n const serverName = rest;\n if (!serverName) {\n if (ctx.hasUI) ctx.ui.notify(\"Usage: /mcp logout <server>\", \"error\");\n return;\n }\n await heavy.commands.logoutServer(serverName, currentState, ctx);\n break;\n }\n case \"status\":\n case \"\":\n default:\n if (ctx.hasUI) {\n const result = await heavy.commands.openMcpPanel(currentState, pi, ctx, earlyConfigPath);\n if (result?.configChanged) {\n await ctx.reload();\n return;\n }\n } else {\n await heavy.commands.showStatus(currentState, ctx);\n }\n break;\n }\n },\n });\n\n pi.registerCommand(\"mcp-auth\", {\n description: \"Authenticate with an MCP server (OAuth)\",\n handler: async (args, ctx) => {\n const serverName = args?.trim();\n if (!serverName && !ctx.hasUI) {\n return;\n }\n\n let currentState: McpExtensionState;\n try {\n currentState = await ensureState(pi, ctx);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n if (ctx.hasUI) ctx.ui.notify(`MCP initialization failed: ${message}`, \"error\");\n return;\n }\n\n const heavy = await loadHeavyModules();\n assertCurrentState(currentState);\n\n if (!serverName) {\n await heavy.commands.openMcpAuthPanel(currentState, pi, ctx, earlyConfigPath);\n return;\n }\n\n await heavy.commands.authenticateServer(serverName, currentState.config, ctx);\n },\n });\n\n if (shouldRegisterProxyTool) {\n (pi.registerTool as (tool: unknown) => unknown)({\n name: \"mcp\",\n label: \"MCP\",\n description: buildProxyDescription(earlyConfig, earlyCache, directSpecs),\n promptSnippet: \"MCP gateway - connect to MCP servers and call their tools\",\n renderCall: renderMcpProxyToolCall,\n parameters: Type.Object({\n tool: Type.Optional(Type.String({ description: \"Tool name to call (e.g., 'xcodebuild_list_sims')\" })),\n args: Type.Optional(Type.String({ description: \"Arguments as JSON string (e.g., '{\\\"key\\\": \\\"value\\\"}')\" })),\n connect: Type.Optional(Type.String({ description: \"Server name to connect (lazy connect + metadata refresh)\" })),\n describe: Type.Optional(Type.String({ description: \"Tool name to describe (shows parameters)\" })),\n search: Type.Optional(Type.String({ description: \"Search tools by name/description\" })),\n regex: Type.Optional(Type.Boolean({ description: \"Treat search as regex (default: substring match)\" })),\n includeSchemas: Type.Optional(Type.Boolean({ description: \"Include parameter schemas in search results (default: true)\" })),\n server: Type.Optional(Type.String({ description: \"Filter to specific server (also disambiguates tool calls)\" })),\n action: Type.Optional(Type.String({ description: \"Action: 'ui-messages', 'auth-start', or 'auth-complete'\" })),\n }),\n renderResult: renderMcpToolResult,\n async execute(_toolCallId, params: {\n tool?: string;\n args?: string;\n connect?: string;\n describe?: string;\n search?: string;\n regex?: boolean;\n includeSchemas?: boolean;\n server?: string;\n action?: string;\n }, incomingSignal, _onUpdate, ctx) {\n const signal = incomingSignal ? AbortSignal.any([incomingSignal, sessionAbort.signal]) : sessionAbort.signal;\n let parsedArgs: Record<string, unknown> | undefined;\n if (params.args) {\n try {\n parsedArgs = JSON.parse(params.args);\n if (typeof parsedArgs !== \"object\" || parsedArgs === null || Array.isArray(parsedArgs)) {\n const gotType = Array.isArray(parsedArgs) ? \"array\" : parsedArgs === null ? \"null\" : typeof parsedArgs;\n throw new Error(`Invalid args: expected a JSON object, got ${gotType}`);\n }\n } catch (error) {\n if (error instanceof SyntaxError) {\n throw new Error(`Invalid args JSON: ${error.message}`, { cause: error });\n }\n throw error;\n }\n }\n\n let currentState: McpExtensionState;\n try {\n currentState = await ensureState(pi, ctx, signal);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [{ type: \"text\" as const, text: `MCP initialization failed: ${message}` }],\n details: { error: \"init_failed\", message },\n };\n }\n\n const heavy = await loadHeavyModules();\n throwIfAborted(signal);\n assertCurrentState(currentState);\n\n if (params.action === \"ui-messages\") {\n return heavy.proxyModes.executeUiMessages(currentState);\n }\n if (params.action === \"auth-start\") {\n if (!params.server) {\n return {\n content: [{ type: \"text\" as const, text: \"auth-start requires `server`. Example: mcp({ action: \\\"auth-start\\\", server: \\\"linear-server\\\" })\" }],\n details: { mode: \"auth-start\", error: \"missing_server\" },\n };\n }\n return heavy.proxyModes.executeAuthStart(currentState, params.server);\n }\n if (params.action === \"auth-complete\") {\n if (!params.server) {\n return {\n content: [{ type: \"text\" as const, text: \"auth-complete requires `server`.\" }],\n details: { mode: \"auth-complete\", error: \"missing_server\" },\n };\n }\n const input = parsedArgs?.redirectUrl ?? parsedArgs?.code ?? parsedArgs?.input;\n if (typeof input !== \"string\" || input.trim().length === 0) {\n return {\n content: [{ type: \"text\" as const, text: \"auth-complete requires args with `redirectUrl`, `code`, or `input`.\" }],\n details: { mode: \"auth-complete\", error: \"missing_input\" },\n };\n }\n return heavy.proxyModes.executeAuthComplete(currentState, params.server, input);\n }\n if (params.tool) {\n return heavy.proxyModes.executeCall(currentState, params.tool, parsedArgs, params.server, getPiTools, signal);\n }\n if (params.connect) {\n return heavy.proxyModes.executeConnect(currentState, params.connect, signal);\n }\n if (params.describe) {\n return heavy.proxyModes.executeDescribe(currentState, params.describe);\n }\n if (params.search) {\n return heavy.proxyModes.executeSearch(currentState, params.search, params.regex, params.server, params.includeSchemas);\n }\n if (params.server) {\n return heavy.proxyModes.executeList(currentState, params.server);\n }\n return heavy.proxyModes.executeStatus(currentState);\n },\n });\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/builtin-extensions/pi-mcp-adapter/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAA8B,MAAM,iCAAiC,CAAC;AAoChG,MAAM,CAAC,OAAO,UAAU,UAAU,CAAC,EAAE,EAAE,YAAY,QA2gBlD","sourcesContent":["// @ts-nocheck\nimport type { ExtensionAPI, ExtensionContext, ToolInfo } from \"@ashx-j/lunr\";\nimport type { McpExtensionState } from \"./state.ts\";\nimport type { DirectToolSpec, McpConfig } from \"./types.ts\";\nimport type { MetadataCache } from \"./metadata-cache.ts\";\nimport { existsSync } from \"node:fs\";\nimport { Type } from \"typebox\";\nimport { loadMcpConfig } from \"./config.ts\";\nimport { buildProxyDescription, getMissingConfiguredDirectToolServers, resolveDirectTools } from \"./direct-tools.ts\";\nimport { getMetadataCachePath, loadMetadataCache } from \"./metadata-cache.ts\";\nimport { getConfigPathFromArgv, normalizeDirectToolInputSchema, truncateAtWord } from \"./utils.ts\";\nimport { createMcpDirectToolCallRenderer, renderMcpProxyToolCall, renderMcpToolResult } from \"./tool-result-renderer.ts\";\nimport { toolErrorOverride } from \"./error-signal.ts\";\nimport { abortable, throwIfAborted } from \"./abort.ts\";\n\ntype McpHeavyModules = {\n init: typeof import(\"./init.ts\");\n commands: typeof import(\"./commands.ts\");\n proxyModes: typeof import(\"./proxy-modes.ts\");\n directToolExecutor: typeof import(\"./direct-tool-executor.ts\");\n};\n\nfunction shouldBackgroundAutostart(config: McpConfig, cache: MetadataCache | null): boolean {\n const serverEntries = Object.entries(config.mcpServers);\n if (serverEntries.length === 0) return false;\n\n if (!existsSync(getMetadataCachePath())) return true;\n\n for (const [, definition] of serverEntries) {\n const mode = definition.lifecycle ?? \"lazy\";\n if (mode === \"keep-alive\" || mode === \"eager\") return true;\n }\n\n if (process.env.MCP_DIRECT_TOOLS === \"__none__\") return false;\n return getMissingConfiguredDirectToolServers(config, cache).length > 0;\n}\n\nexport default function mcpAdapter(pi: ExtensionAPI) {\n let state: McpExtensionState | null = null;\n let initPromise: Promise<McpExtensionState> | null = null;\n let lifecycleGeneration = 0;\n let sessionAbort = new AbortController();\n const initializingStates = new Set<McpExtensionState>();\n const shutdownPromises = new WeakMap<McpExtensionState, Promise<void>>();\n let heavyModules: McpHeavyModules | null = null;\n let heavyModulesPromise: Promise<McpHeavyModules> | null = null;\n const directExecutors = new Map<string, ReturnType<McpHeavyModules[\"directToolExecutor\"][\"createDirectToolExecutor\"]>>();\n\n function loadHeavyModules(): Promise<McpHeavyModules> {\n if (heavyModules) return Promise.resolve(heavyModules);\n if (!heavyModulesPromise) {\n heavyModulesPromise = (async () => {\n const [init, commands, proxyModes, directToolExecutor] = await Promise.all([\n import(\"./init.ts\"),\n import(\"./commands.ts\"),\n import(\"./proxy-modes.ts\"),\n import(\"./direct-tool-executor.ts\"),\n ]);\n const loaded: McpHeavyModules = { init, commands, proxyModes, directToolExecutor };\n heavyModules = loaded;\n return loaded;\n })().catch((error) => {\n heavyModulesPromise = null;\n throw error;\n });\n }\n return heavyModulesPromise;\n }\n\n function shutdownState(currentState: McpExtensionState | null, reason: string): Promise<void> {\n if (!currentState) return Promise.resolve();\n const existing = shutdownPromises.get(currentState);\n if (existing) return existing;\n\n const shutdown = (async () => {\n await currentState.authFlow.shutdown();\n if (currentState.uiServer) {\n currentState.uiServer.close(reason);\n currentState.uiServer = null;\n }\n\n let flushError: unknown;\n try {\n if (heavyModules) {\n heavyModules.init.flushMetadataCache(currentState);\n }\n } catch (error) {\n flushError = error;\n }\n\n try {\n await currentState.lifecycle.gracefulShutdown();\n } catch (error) {\n if (flushError) {\n console.error(\"MCP: graceful shutdown failed after metadata flush error\", error);\n } else {\n throw error;\n }\n }\n\n if (flushError) {\n throw flushError;\n }\n })();\n shutdownPromises.set(currentState, shutdown);\n return shutdown;\n }\n\n async function shutdownInitializingStates(): Promise<void> {\n const pending = [...initializingStates];\n initializingStates.clear();\n await Promise.all(pending.map((entry) => shutdownState(entry, \"initialization_cancelled\")));\n }\n\n async function runInitialize(\n generation: number,\n sessionPi: ExtensionAPI,\n ctx: ExtensionContext,\n ): Promise<McpExtensionState> {\n const signal = sessionAbort.signal;\n const heavy = await loadHeavyModules();\n throwIfAborted(signal);\n if (generation !== lifecycleGeneration) {\n throw new Error(\"MCP initialization aborted (session changed)\");\n }\n\n let partial: McpExtensionState | undefined;\n try {\n const initialized = await heavy.init.initializeMcp(sessionPi, ctx, {\n signal,\n onState: (entry: McpExtensionState) => {\n partial = entry;\n initializingStates.add(entry);\n },\n });\n if (!partial) {\n partial = initialized;\n initializingStates.add(initialized);\n }\n throwIfAborted(signal);\n return initialized;\n } catch (error) {\n if (partial) {\n initializingStates.delete(partial);\n await shutdownState(partial, \"initialization_failed\");\n }\n throw error;\n } finally {\n if (partial) initializingStates.delete(partial);\n }\n }\n\n function startSessionInit(generation: number, sessionPi: ExtensionAPI, ctx: ExtensionContext): Promise<McpExtensionState> {\n const promise = runInitialize(generation, sessionPi, ctx);\n initPromise = promise;\n\n promise.then(async (nextState) => {\n if (generation !== lifecycleGeneration || initPromise !== promise) {\n try {\n await shutdownState(nextState, \"stale_session_start\");\n } catch (error) {\n console.error(\"MCP: failed to clean stale session state\", error);\n }\n return;\n }\n\n state = nextState;\n if (heavyModules) {\n heavyModules.init.updateStatusBar(nextState);\n }\n initPromise = null;\n }).catch(err => {\n if (generation !== lifecycleGeneration) {\n return;\n }\n if (initPromise !== promise && initPromise !== null) {\n return;\n }\n console.error(\"MCP initialization failed:\", err);\n initPromise = null;\n });\n\n return promise;\n }\n\n async function ensureState(sessionPi: ExtensionAPI, ctx: ExtensionContext, signal?: AbortSignal): Promise<McpExtensionState> {\n throwIfAborted(signal);\n if (state) return state;\n\n const generation = lifecycleGeneration;\n if (!initPromise) {\n startSessionInit(generation, sessionPi, ctx);\n }\n const promise = initPromise;\n if (!promise) {\n throw new Error(\"MCP not initialized\");\n }\n\n try {\n const nextState = await abortable(promise, signal);\n if (generation !== lifecycleGeneration) {\n throw new Error(\"MCP initialization aborted (session changed)\");\n }\n if (state) return state;\n state = nextState;\n if (initPromise === promise) {\n initPromise = null;\n }\n return state;\n } catch (error) {\n if (initPromise === promise && !signal?.aborted) {\n initPromise = null;\n }\n throw error;\n }\n }\n\n function assertCurrentState(currentState: McpExtensionState): void {\n if (currentState !== state) throw new Error(\"MCP session changed before execution\");\n }\n\n function createLazyDirectToolExecute(spec: DirectToolSpec) {\n return async function execute(toolCallId, params, incomingSignal, onUpdate, ctx) {\n const signal = incomingSignal ? AbortSignal.any([incomingSignal, sessionAbort.signal]) : sessionAbort.signal;\n const currentSpec = currentDirectSpecs.get(spec.prefixedName);\n if (!currentSpec || JSON.stringify(currentSpec) !== JSON.stringify(spec)) {\n throw new Error(\"MCP tool is unavailable in the current trusted configuration\");\n }\n let currentState: McpExtensionState;\n try {\n currentState = await ensureState(pi, ctx, signal);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [{ type: \"text\" as const, text: `MCP initialization failed: ${message}` }],\n details: { error: \"init_failed\", message },\n };\n }\n\n const heavy = await loadHeavyModules();\n throwIfAborted(signal);\n assertCurrentState(currentState);\n let executor = directExecutors.get(spec.prefixedName);\n if (!executor) {\n executor = heavy.directToolExecutor.createDirectToolExecutor(() => currentState, () => null, spec);\n directExecutors.set(spec.prefixedName, executor);\n }\n return executor(toolCallId, params, signal, onUpdate, ctx);\n };\n }\n\n const earlyConfigPath = getConfigPathFromArgv();\n const earlyConfig = loadMcpConfig(earlyConfigPath);\n const earlyCache = loadMetadataCache();\n const registeredDirectTools = new Map<string, string>();\n let currentDirectSpecs = new Map<string, DirectToolSpec>();\n function registerConfiguredTools(config: McpConfig, cache: MetadataCache | null) {\n const prefix = config.settings?.toolPrefix ?? \"server\";\n\n const envRaw = process.env.MCP_DIRECT_TOOLS;\n const directSpecs = envRaw === \"__none__\"\n ? []\n : resolveDirectTools(\n config,\n cache,\n prefix,\n envRaw?.split(\",\").map(s => s.trim()).filter(Boolean),\n );\n currentDirectSpecs = new Map(directSpecs.map(spec => [spec.prefixedName, spec]));\n const missingConfiguredDirectToolServers = getMissingConfiguredDirectToolServers(config, cache);\n const shouldRegisterProxyTool =\n config.settings?.disableProxyTool !== true\n || directSpecs.length === 0\n || missingConfiguredDirectToolServers.length > 0;\n\n for (const spec of directSpecs) {\n const fingerprint = JSON.stringify(spec);\n if (registeredDirectTools.get(spec.prefixedName) === fingerprint) continue;\n registeredDirectTools.set(spec.prefixedName, fingerprint);\n (pi.registerTool as (tool: unknown) => unknown)({\n name: spec.prefixedName,\n label: `MCP: ${spec.originalName}`,\n description: `${spec.description || \"(no description)\"}\\nUnavailable in read-only mode; switch to yolo or auto to call.`,\n promptSnippet: truncateAtWord(spec.description, 100) || `MCP tool from ${spec.serverName}`,\n parameters: Type.Unsafe(normalizeDirectToolInputSchema(spec.inputSchema) as never),\n execute: createLazyDirectToolExecute(spec),\n renderCall: createMcpDirectToolCallRenderer(spec.prefixedName),\n renderResult: renderMcpToolResult,\n });\n }\n\n if (shouldRegisterProxyTool) registerProxyTool(config, cache, directSpecs);\n return { names: directSpecs.map(spec => spec.prefixedName), proxy: shouldRegisterProxyTool };\n }\n\n registerConfiguredTools(earlyConfig, earlyCache);\n\n const getPiTools = (): ToolInfo[] => pi.getAllTools();\n\n pi.registerFlag(\"mcp-config\", {\n description: \"Path to MCP config file\",\n type: \"string\",\n });\n\n pi.on(\"session_start\", async (_event, ctx) => {\n const generation = ++lifecycleGeneration;\n sessionAbort.abort(new Error(\"MCP session changed\"));\n sessionAbort = new AbortController();\n const previousState = state;\n state = null;\n initPromise = null;\n directExecutors.clear();\n\n try {\n await Promise.all([\n shutdownState(previousState, \"session_restart\"),\n shutdownInitializingStates(),\n ]);\n } catch (error) {\n console.error(\"MCP: failed to shut down previous session state\", error);\n }\n\n if (generation !== lifecycleGeneration) {\n return;\n }\n\n const configPath = (pi.getFlag(\"mcp-config\") as string | undefined) ?? earlyConfigPath;\n const sessionConfig = loadMcpConfig(configPath, ctx.cwd, ctx.isProjectTrusted());\n const sessionCache = loadMetadataCache();\n const registered = registerConfiguredTools(sessionConfig, sessionCache);\n // Session replacement can reuse the factory. Retire definitions from its prior config.\n const active = pi.getActiveTools().filter(name => !registeredDirectTools.has(name) && name !== \"mcp\");\n pi.setActiveTools([...active, ...registered.names, ...(registered.proxy ? [\"mcp\"] : [])]);\n\n if (!shouldBackgroundAutostart(sessionConfig, sessionCache)) {\n return;\n }\n\n startSessionInit(generation, pi, ctx);\n });\n\n pi.on(\"session_shutdown\", async () => {\n ++lifecycleGeneration;\n sessionAbort.abort(new Error(\"MCP session ended\"));\n const currentState = state;\n state = null;\n initPromise = null;\n directExecutors.clear();\n\n try {\n await Promise.all([\n shutdownState(currentState, \"session_shutdown\"),\n shutdownInitializingStates(),\n ]);\n } catch (error) {\n console.error(\"MCP: session shutdown cleanup failed\", error);\n }\n });\n\n // Re-flag returned MCP tool failures so pi registers them as errors (see toolErrorOverride).\n pi.on(\"tool_result\", (event) => toolErrorOverride(event.details));\n\n pi.registerCommand(\"mcp\", {\n description: \"Show MCP server status\",\n handler: async (args, ctx) => {\n let currentState: McpExtensionState;\n try {\n currentState = await ensureState(pi, ctx);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n if (ctx.hasUI) ctx.ui.notify(`MCP initialization failed: ${message}`, \"error\");\n return;\n }\n\n const heavy = await loadHeavyModules();\n assertCurrentState(currentState);\n const parts = args?.trim()?.split(/\\s+/) ?? [];\n const subcommand = parts[0] ?? \"\";\n const targetServer = parts[1];\n const rest = parts.slice(1).join(\" \");\n\n switch (subcommand) {\n case \"reconnect\":\n await heavy.commands.reconnectServers(currentState, ctx, targetServer);\n break;\n case \"tools\":\n await heavy.commands.showTools(currentState, ctx);\n break;\n case \"setup\": {\n const result = await heavy.commands.openMcpSetup(currentState, pi, ctx, earlyConfigPath, \"setup\");\n if (result?.configChanged) {\n await ctx.reload();\n return;\n }\n break;\n }\n case \"logout\": {\n const serverName = rest;\n if (!serverName) {\n if (ctx.hasUI) ctx.ui.notify(\"Usage: /mcp logout <server>\", \"error\");\n return;\n }\n await heavy.commands.logoutServer(serverName, currentState, ctx);\n break;\n }\n case \"status\":\n case \"\":\n default:\n if (ctx.hasUI) {\n const result = await heavy.commands.openMcpPanel(currentState, pi, ctx, earlyConfigPath);\n if (result?.configChanged) {\n await ctx.reload();\n return;\n }\n } else {\n await heavy.commands.showStatus(currentState, ctx);\n }\n break;\n }\n },\n });\n\n pi.registerCommand(\"mcp-auth\", {\n description: \"Authenticate with an MCP server (OAuth)\",\n handler: async (args, ctx) => {\n const serverName = args?.trim();\n if (!serverName && !ctx.hasUI) {\n return;\n }\n\n let currentState: McpExtensionState;\n try {\n currentState = await ensureState(pi, ctx);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n if (ctx.hasUI) ctx.ui.notify(`MCP initialization failed: ${message}`, \"error\");\n return;\n }\n\n const heavy = await loadHeavyModules();\n assertCurrentState(currentState);\n\n if (!serverName) {\n await heavy.commands.openMcpAuthPanel(currentState, pi, ctx, earlyConfigPath);\n return;\n }\n\n await heavy.commands.authenticateServer(serverName, currentState.config, ctx, currentState.authFlow);\n },\n });\n\n function registerProxyTool(config: McpConfig, cache: MetadataCache | null, specs: DirectToolSpec[]) {\n (pi.registerTool as (tool: unknown) => unknown)({\n name: \"mcp\",\n label: \"MCP\",\n description: buildProxyDescription(config, cache, specs),\n promptSnippet: \"MCP gateway - connect to MCP servers and call their tools\",\n renderCall: renderMcpProxyToolCall,\n parameters: Type.Object({\n tool: Type.Optional(Type.String({ description: \"Tool name to call (e.g., 'xcodebuild_list_sims')\" })),\n args: Type.Optional(Type.String({ description: \"Arguments as JSON string (e.g., '{\\\"key\\\": \\\"value\\\"}')\" })),\n connect: Type.Optional(Type.String({ description: \"Server name to connect (lazy connect + metadata refresh)\" })),\n describe: Type.Optional(Type.String({ description: \"Tool name to describe (shows parameters)\" })),\n search: Type.Optional(Type.String({ description: \"Search tools by name/description\" })),\n regex: Type.Optional(Type.Boolean({ description: \"Treat search as regex (default: substring match)\" })),\n includeSchemas: Type.Optional(Type.Boolean({ description: \"Include parameter schemas in search results (default: true)\" })),\n server: Type.Optional(Type.String({ description: \"Filter to specific server (also disambiguates tool calls)\" })),\n action: Type.Optional(Type.String({ description: \"Action: 'ui-messages', 'auth-start', or 'auth-complete'\" })),\n }),\n renderResult: renderMcpToolResult,\n async execute(_toolCallId, params: {\n tool?: string;\n args?: string;\n connect?: string;\n describe?: string;\n search?: string;\n regex?: boolean;\n includeSchemas?: boolean;\n server?: string;\n action?: string;\n }, incomingSignal, _onUpdate, ctx) {\n const signal = incomingSignal ? AbortSignal.any([incomingSignal, sessionAbort.signal]) : sessionAbort.signal;\n let parsedArgs: Record<string, unknown> | undefined;\n if (params.args) {\n try {\n parsedArgs = JSON.parse(params.args);\n if (typeof parsedArgs !== \"object\" || parsedArgs === null || Array.isArray(parsedArgs)) {\n const gotType = Array.isArray(parsedArgs) ? \"array\" : parsedArgs === null ? \"null\" : typeof parsedArgs;\n throw new Error(`Invalid args: expected a JSON object, got ${gotType}`);\n }\n } catch (error) {\n if (error instanceof SyntaxError) {\n throw new Error(`Invalid args JSON: ${error.message}`, { cause: error });\n }\n throw error;\n }\n }\n\n let currentState: McpExtensionState;\n try {\n currentState = await ensureState(pi, ctx, signal);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [{ type: \"text\" as const, text: `MCP initialization failed: ${message}` }],\n details: { error: \"init_failed\", message },\n };\n }\n\n const heavy = await loadHeavyModules();\n throwIfAborted(signal);\n assertCurrentState(currentState);\n\n if (params.action === \"ui-messages\") {\n return heavy.proxyModes.executeUiMessages(currentState);\n }\n if (params.action === \"auth-start\") {\n if (!params.server) {\n return {\n content: [{ type: \"text\" as const, text: \"auth-start requires `server`. Example: mcp({ action: \\\"auth-start\\\", server: \\\"linear-server\\\" })\" }],\n details: { mode: \"auth-start\", error: \"missing_server\" },\n };\n }\n return heavy.proxyModes.executeAuthStart(currentState, params.server);\n }\n if (params.action === \"auth-complete\") {\n if (!params.server) {\n return {\n content: [{ type: \"text\" as const, text: \"auth-complete requires `server`.\" }],\n details: { mode: \"auth-complete\", error: \"missing_server\" },\n };\n }\n const input = parsedArgs?.redirectUrl ?? parsedArgs?.code ?? parsedArgs?.input;\n if (typeof input !== \"string\" || input.trim().length === 0) {\n return {\n content: [{ type: \"text\" as const, text: \"auth-complete requires args with `redirectUrl`, `code`, or `input`.\" }],\n details: { mode: \"auth-complete\", error: \"missing_input\" },\n };\n }\n return heavy.proxyModes.executeAuthComplete(currentState, params.server, input);\n }\n if (params.tool) {\n return heavy.proxyModes.executeCall(currentState, params.tool, parsedArgs, params.server, getPiTools, signal);\n }\n if (params.connect) {\n return heavy.proxyModes.executeConnect(currentState, params.connect, signal);\n }\n if (params.describe) {\n return heavy.proxyModes.executeDescribe(currentState, params.describe);\n }\n if (params.search) {\n return heavy.proxyModes.executeSearch(currentState, params.search, params.regex, params.server, params.includeSchemas);\n }\n if (params.server) {\n return heavy.proxyModes.executeList(currentState, params.server);\n }\n return heavy.proxyModes.executeStatus(currentState);\n },\n });\n }\n}\n"]}
|