@astralyn/pi 0.99.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +39 -3
- package/dist/bundle/chunks/anthropic-messages-CG2BSDQS.js +6 -0
- package/dist/bundle/chunks/anthropic.js +2 -2
- package/dist/bundle/chunks/{azure-openai-responses-RPBERDXD.js → azure-openai-responses-PBA4QKCM.js} +1 -1
- package/dist/bundle/chunks/bedrock-converse-stream.js +2 -2
- package/dist/bundle/chunks/{chunk-ABVRAYXT.js → chunk-6UFFVA7M.js} +2 -2
- package/dist/bundle/chunks/chunk-GIG5IHES.js +2 -0
- package/dist/bundle/chunks/{chunk-VW2P3X6P.js → chunk-HESRDUKO.js} +414 -666
- package/dist/bundle/chunks/{chunk-A576H74Y.js → chunk-PFZKRUMO.js} +1 -1
- package/dist/bundle/chunks/chunk-SGLYRVQL.js +2 -0
- package/dist/bundle/chunks/chunk-TRHTWM3C.js +2 -0
- package/dist/bundle/chunks/{chunk-DEWXBB6W.js → chunk-V66VGGOM.js} +1 -1
- package/dist/bundle/chunks/chunk-Z2RKSI3O.js +2 -0
- package/dist/bundle/chunks/{cloudflare-workers-ai-system-one-ZYSAFXXL.js → cloudflare-workers-ai-system-one-YB7XPPP4.js} +1 -1
- package/dist/bundle/chunks/codemode-worker.js +67 -8
- package/dist/bundle/chunks/github-copilot.js +1 -1
- package/dist/bundle/chunks/{google-generative-ai-SDNQVVXA.js → google-generative-ai-V5ZM5MCL.js} +1 -1
- package/dist/bundle/chunks/{google-vertex-LZXOLBIO.js → google-vertex-22THOFP5.js} +1 -1
- package/dist/bundle/chunks/{llama-cpp-classify-7IYGGPND.js → llama-cpp-classify-R7DQLTQN.js} +1 -1
- package/dist/bundle/chunks/{mistral-conversations-VYKPSSAM.js → mistral-conversations-WHSCJJWP.js} +1 -1
- package/dist/bundle/chunks/openai-chatgpt.js +1 -1
- package/dist/bundle/chunks/{openai-codex-responses-HZ4VUDXD.js → openai-codex-responses-N7GDPBPP.js} +1 -1
- package/dist/bundle/chunks/openai-codex.js +1 -1
- package/dist/bundle/chunks/{openai-completions-SKDGF6OE.js → openai-completions-RGGQK5UW.js} +1 -1
- package/dist/bundle/chunks/{openai-responses-FPML4SSG.js → openai-responses-3ZLD5JYI.js} +1 -1
- package/dist/bundle/chunks/{openrouter-images-5524IQHX.js → openrouter-images-YP3YVB54.js} +1 -1
- package/dist/bundle/chunks/openrouter.js +1 -1
- package/dist/bundle/chunks/radius.js +1 -1
- package/dist/bundle/chunks/{typesafe-system-one-Z2CDLKEY.js → typesafe-system-one-RREJAKWB.js} +1 -1
- package/dist/bundle/chunks/virtual-modules-4RQ2L6W4.js +2 -0
- package/dist/bundle/cli.js +1 -1
- package/dist/bundle/index.js +1 -1
- package/dist/bundle/rpc-entry.js +1 -1
- package/dist/cli/args.js +1 -1
- package/dist/cli/args.js.map +1 -1
- package/dist/config.d.ts +5 -8
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +16 -13
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session.d.ts +21 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +64 -11
- package/dist/core/agent-session.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 +13 -1
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/types.d.ts +6 -1
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/keybindings.d.ts +51 -11
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +11 -3
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/mcp-servers.d.ts +34 -7
- package/dist/core/mcp-servers.d.ts.map +1 -1
- package/dist/core/mcp-servers.js +52 -11
- package/dist/core/mcp-servers.js.map +1 -1
- package/dist/core/model-registry.d.ts +3 -1
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +4 -0
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-runtime.d.ts +6 -0
- package/dist/core/model-runtime.d.ts.map +1 -1
- package/dist/core/model-runtime.js +22 -18
- package/dist/core/model-runtime.js.map +1 -1
- package/dist/core/radius.d.ts +2 -0
- package/dist/core/radius.d.ts.map +1 -1
- package/dist/core/radius.js +2 -0
- package/dist/core/radius.js.map +1 -1
- package/dist/core/remote-catalog-provider.d.ts.map +1 -1
- package/dist/core/remote-catalog-provider.js +4 -9
- package/dist/core/remote-catalog-provider.js.map +1 -1
- 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/settings-manager.d.ts +7 -5
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +2 -1
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/system-prompt.js +1 -1
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tasks/format.d.ts +7 -0
- package/dist/core/tasks/format.d.ts.map +1 -0
- package/dist/core/tasks/format.js +14 -0
- package/dist/core/tasks/format.js.map +1 -0
- package/dist/core/tasks/history.d.ts.map +1 -1
- package/dist/core/tasks/history.js +0 -19
- package/dist/core/tasks/history.js.map +1 -1
- package/dist/core/tasks/output.d.ts +8 -0
- package/dist/core/tasks/output.d.ts.map +1 -1
- package/dist/core/tasks/output.js +19 -0
- package/dist/core/tasks/output.js.map +1 -1
- package/dist/core/tasks/presentation.d.ts +1 -3
- package/dist/core/tasks/presentation.d.ts.map +1 -1
- package/dist/core/tasks/presentation.js +79 -166
- package/dist/core/tasks/presentation.js.map +1 -1
- package/dist/core/tasks/runtime.d.ts +16 -9
- package/dist/core/tasks/runtime.d.ts.map +1 -1
- package/dist/core/tasks/runtime.js +89 -106
- package/dist/core/tasks/runtime.js.map +1 -1
- package/dist/core/tasks/session.d.ts.map +1 -1
- package/dist/core/tasks/session.js +13 -4
- package/dist/core/tasks/session.js.map +1 -1
- package/dist/core/tasks/store.d.ts +20 -6
- package/dist/core/tasks/store.d.ts.map +1 -1
- package/dist/core/tasks/store.js +45 -18
- package/dist/core/tasks/store.js.map +1 -1
- package/dist/core/tasks/types.d.ts +14 -54
- package/dist/core/tasks/types.d.ts.map +1 -1
- package/dist/core/tasks/types.js +1 -5
- package/dist/core/tasks/types.js.map +1 -1
- package/dist/core/tools/renderers/bash.d.ts.map +1 -1
- package/dist/core/tools/renderers/bash.js +11 -34
- package/dist/core/tools/renderers/bash.js.map +1 -1
- package/dist/core/tools/shell-execution.d.ts +0 -1
- package/dist/core/tools/shell-execution.d.ts.map +1 -1
- package/dist/core/tools/shell-execution.js +3 -10
- package/dist/core/tools/shell-execution.js.map +1 -1
- package/dist/core/tools/shell-tool.d.ts.map +1 -1
- package/dist/core/tools/shell-tool.js +2 -4
- package/dist/core/tools/shell-tool.js.map +1 -1
- package/dist/core/tools/tasks/actions.d.ts +1 -1
- package/dist/core/tools/tasks/actions.d.ts.map +1 -1
- package/dist/core/tools/tasks/actions.js +26 -12
- package/dist/core/tools/tasks/actions.js.map +1 -1
- package/dist/core/tools/tasks/constants.d.ts +2 -6
- package/dist/core/tools/tasks/constants.d.ts.map +1 -1
- package/dist/core/tools/tasks/constants.js +2 -6
- package/dist/core/tools/tasks/constants.js.map +1 -1
- package/dist/core/tools/tasks/schema.d.ts +1 -1
- package/dist/core/tools/tasks/schema.d.ts.map +1 -1
- package/dist/core/tools/tasks/schema.js +8 -7
- package/dist/core/tools/tasks/schema.js.map +1 -1
- package/dist/core/tools/tasks/types.d.ts +8 -38
- package/dist/core/tools/tasks/types.d.ts.map +1 -1
- package/dist/core/tools/tasks/types.js +6 -11
- package/dist/core/tools/tasks/types.js.map +1 -1
- package/dist/core/virtual-models.d.ts +2 -0
- package/dist/core/virtual-models.d.ts.map +1 -1
- package/dist/core/virtual-models.js +19 -12
- package/dist/core/virtual-models.js.map +1 -1
- package/dist/extensions/btw/agent.d.ts +17 -8
- package/dist/extensions/btw/agent.d.ts.map +1 -1
- package/dist/extensions/btw/agent.js +74 -76
- package/dist/extensions/btw/agent.js.map +1 -1
- package/dist/extensions/btw/controller.d.ts +0 -1
- package/dist/extensions/btw/controller.d.ts.map +1 -1
- package/dist/extensions/btw/controller.js +26 -33
- package/dist/extensions/btw/controller.js.map +1 -1
- package/dist/extensions/btw/panel.d.ts +13 -14
- package/dist/extensions/btw/panel.d.ts.map +1 -1
- package/dist/extensions/btw/panel.js +38 -29
- package/dist/extensions/btw/panel.js.map +1 -1
- package/dist/extensions/codemode/execute.d.ts.map +1 -1
- package/dist/extensions/codemode/execute.js +197 -51
- package/dist/extensions/codemode/execute.js.map +1 -1
- package/dist/extensions/codemode/renderer.d.ts.map +1 -1
- package/dist/extensions/codemode/renderer.js +43 -25
- package/dist/extensions/codemode/renderer.js.map +1 -1
- package/dist/extensions/codemode/tool.d.ts +12 -11
- package/dist/extensions/codemode/tool.d.ts.map +1 -1
- package/dist/extensions/codemode/tool.js +73 -129
- package/dist/extensions/codemode/tool.js.map +1 -1
- package/dist/extensions/codemode/worker.d.ts +1 -1
- package/dist/extensions/codemode/worker.js +1 -1
- package/dist/extensions/codemode/worker.js.map +1 -1
- package/dist/extensions/deepwiki/schema.d.ts +1 -1
- package/dist/extensions/index.d.ts.map +1 -1
- package/dist/extensions/index.js +0 -2
- package/dist/extensions/index.js.map +1 -1
- package/dist/extensions/mcp/cli.d.ts.map +1 -1
- package/dist/extensions/mcp/cli.js +20 -5
- package/dist/extensions/mcp/cli.js.map +1 -1
- package/dist/extensions/mcp/config.d.ts +4 -2
- package/dist/extensions/mcp/config.d.ts.map +1 -1
- package/dist/extensions/mcp/config.js +14 -2
- package/dist/extensions/mcp/config.js.map +1 -1
- package/dist/extensions/mcp/index.d.ts +32 -8
- package/dist/extensions/mcp/index.d.ts.map +1 -1
- package/dist/extensions/mcp/index.js +235 -61
- package/dist/extensions/mcp/index.js.map +1 -1
- package/dist/extensions/mcp/oauth.d.ts +10 -7
- package/dist/extensions/mcp/oauth.d.ts.map +1 -1
- package/dist/extensions/mcp/oauth.js +56 -31
- package/dist/extensions/mcp/oauth.js.map +1 -1
- package/dist/extensions/mcp/runtime.d.ts +2 -0
- package/dist/extensions/mcp/runtime.d.ts.map +1 -1
- package/dist/extensions/mcp/runtime.js +16 -9
- package/dist/extensions/mcp/runtime.js.map +1 -1
- package/dist/extensions/mcp/tools.d.ts +5 -4
- package/dist/extensions/mcp/tools.d.ts.map +1 -1
- package/dist/extensions/mcp/tools.js +33 -15
- package/dist/extensions/mcp/tools.js.map +1 -1
- package/dist/extensions/mcp/ui.d.ts.map +1 -1
- package/dist/extensions/mcp/ui.js +4 -2
- package/dist/extensions/mcp/ui.js.map +1 -1
- package/dist/extensions/provider/catalog.d.ts +8 -1
- package/dist/extensions/provider/catalog.d.ts.map +1 -1
- package/dist/extensions/provider/catalog.js +31 -0
- package/dist/extensions/provider/catalog.js.map +1 -1
- package/dist/extensions/provider/connection.d.ts +4 -1
- package/dist/extensions/provider/connection.d.ts.map +1 -1
- package/dist/extensions/provider/connection.js +1 -5
- package/dist/extensions/provider/connection.js.map +1 -1
- package/dist/extensions/provider/editing.d.ts +36 -0
- package/dist/extensions/provider/editing.d.ts.map +1 -0
- package/dist/extensions/provider/editing.js +99 -0
- package/dist/extensions/provider/editing.js.map +1 -0
- package/dist/extensions/provider/json-fields.d.ts +5 -0
- package/dist/extensions/provider/json-fields.d.ts.map +1 -0
- package/dist/extensions/provider/json-fields.js +31 -0
- package/dist/extensions/provider/json-fields.js.map +1 -0
- package/dist/extensions/provider/store.d.ts +1 -4
- package/dist/extensions/provider/store.d.ts.map +1 -1
- package/dist/extensions/provider/store.js +2 -30
- package/dist/extensions/provider/store.js.map +1 -1
- package/dist/extensions/provider/ui/builtin-data.d.ts +0 -2
- package/dist/extensions/provider/ui/builtin-data.d.ts.map +1 -1
- package/dist/extensions/provider/ui/builtin-data.js +14 -79
- package/dist/extensions/provider/ui/builtin-data.js.map +1 -1
- package/dist/extensions/provider/ui/compat.d.ts.map +1 -1
- package/dist/extensions/provider/ui/compat.js +6 -9
- package/dist/extensions/provider/ui/compat.js.map +1 -1
- package/dist/extensions/provider/ui/controls.d.ts +48 -0
- package/dist/extensions/provider/ui/controls.d.ts.map +1 -0
- package/dist/extensions/provider/ui/controls.js +108 -0
- package/dist/extensions/provider/ui/controls.js.map +1 -0
- package/dist/extensions/provider/ui/dictionary.d.ts.map +1 -1
- package/dist/extensions/provider/ui/dictionary.js +6 -9
- package/dist/extensions/provider/ui/dictionary.js.map +1 -1
- package/dist/extensions/provider/ui/editor.d.ts +3 -3
- package/dist/extensions/provider/ui/editor.d.ts.map +1 -1
- package/dist/extensions/provider/ui/editor.js +35 -140
- package/dist/extensions/provider/ui/editor.js.map +1 -1
- package/dist/extensions/provider/ui/fetch-models.d.ts +0 -3
- package/dist/extensions/provider/ui/fetch-models.d.ts.map +1 -1
- package/dist/extensions/provider/ui/fetch-models.js +49 -44
- package/dist/extensions/provider/ui/fetch-models.js.map +1 -1
- package/dist/extensions/provider/ui/model-fields.d.ts.map +1 -1
- package/dist/extensions/provider/ui/model-fields.js +11 -14
- package/dist/extensions/provider/ui/model-fields.js.map +1 -1
- package/dist/extensions/provider/ui/model-options.d.ts +4 -34
- package/dist/extensions/provider/ui/model-options.d.ts.map +1 -1
- package/dist/extensions/provider/ui/model-options.js +90 -271
- package/dist/extensions/provider/ui/model-options.js.map +1 -1
- package/dist/extensions/provider/ui/pane.d.ts +4 -18
- package/dist/extensions/provider/ui/pane.d.ts.map +1 -1
- package/dist/extensions/provider/ui/pane.js.map +1 -1
- package/dist/extensions/provider/ui/provider-fields.d.ts +2 -19
- package/dist/extensions/provider/ui/provider-fields.d.ts.map +1 -1
- package/dist/extensions/provider/ui/provider-fields.js +58 -171
- package/dist/extensions/provider/ui/provider-fields.js.map +1 -1
- package/dist/extensions/provider/ui/thinking-map.d.ts.map +1 -1
- package/dist/extensions/provider/ui/thinking-map.js +6 -9
- package/dist/extensions/provider/ui/thinking-map.js.map +1 -1
- package/dist/extensions/question/detail-pane.d.ts +7 -2
- package/dist/extensions/question/detail-pane.d.ts.map +1 -1
- package/dist/extensions/question/detail-pane.js +16 -5
- package/dist/extensions/question/detail-pane.js.map +1 -1
- package/dist/extensions/question/dialog-view.d.ts +41 -0
- package/dist/extensions/question/dialog-view.d.ts.map +1 -0
- package/dist/extensions/question/dialog-view.js +329 -0
- package/dist/extensions/question/dialog-view.js.map +1 -0
- package/dist/extensions/question/dialog.d.ts +3 -3
- package/dist/extensions/question/dialog.d.ts.map +1 -1
- package/dist/extensions/question/dialog.js +220 -634
- package/dist/extensions/question/dialog.js.map +1 -1
- package/dist/extensions/question/index.d.ts.map +1 -1
- package/dist/extensions/question/index.js +2 -3
- package/dist/extensions/question/index.js.map +1 -1
- package/dist/extensions/question/render.d.ts.map +1 -1
- package/dist/extensions/question/render.js +22 -32
- package/dist/extensions/question/render.js.map +1 -1
- package/dist/extensions/question/results.d.ts.map +1 -1
- package/dist/extensions/question/results.js +56 -12
- package/dist/extensions/question/results.js.map +1 -1
- package/dist/extensions/question/schema.d.ts +21 -6
- package/dist/extensions/question/schema.d.ts.map +1 -1
- package/dist/extensions/question/schema.js.map +1 -1
- package/dist/extensions/question/state.d.ts +9 -7
- package/dist/extensions/question/state.d.ts.map +1 -1
- package/dist/extensions/question/state.js +63 -54
- package/dist/extensions/question/state.js.map +1 -1
- package/dist/extensions/question/types.d.ts +41 -18
- package/dist/extensions/question/types.d.ts.map +1 -1
- package/dist/extensions/question/types.js.map +1 -1
- package/dist/extensions/statusline/index.d.ts +4 -0
- package/dist/extensions/statusline/index.d.ts.map +1 -1
- package/dist/extensions/statusline/index.js +18 -355
- package/dist/extensions/statusline/index.js.map +1 -1
- package/dist/extensions/statusline/render.d.ts +19 -0
- package/dist/extensions/statusline/render.d.ts.map +1 -0
- package/dist/extensions/statusline/render.js +163 -0
- package/dist/extensions/statusline/render.js.map +1 -0
- package/dist/extensions/statusline/usage.d.ts +12 -0
- package/dist/extensions/statusline/usage.d.ts.map +1 -0
- package/dist/extensions/statusline/usage.js +36 -0
- package/dist/extensions/statusline/usage.js.map +1 -0
- package/dist/extensions/tool-search/tool.d.ts +5 -4
- package/dist/extensions/tool-search/tool.d.ts.map +1 -1
- package/dist/extensions/tool-search/tool.js +7 -28
- package/dist/extensions/tool-search/tool.js.map +1 -1
- package/dist/extensions/web-search/execute.d.ts +1 -5
- package/dist/extensions/web-search/execute.d.ts.map +1 -1
- package/dist/extensions/web-search/execute.js +4 -9
- package/dist/extensions/web-search/execute.js.map +1 -1
- package/dist/extensions/web-search/format.d.ts +12 -3
- package/dist/extensions/web-search/format.d.ts.map +1 -1
- package/dist/extensions/web-search/format.js +33 -25
- package/dist/extensions/web-search/format.js.map +1 -1
- package/dist/extensions/web-search/index.d.ts.map +1 -1
- package/dist/extensions/web-search/index.js +6 -29
- package/dist/extensions/web-search/index.js.map +1 -1
- package/dist/extensions/web-search/providers/deepseek.d.ts.map +1 -1
- package/dist/extensions/web-search/providers/deepseek.js +0 -1
- package/dist/extensions/web-search/providers/deepseek.js.map +1 -1
- package/dist/extensions/web-search/providers/http.d.ts +1 -1
- package/dist/extensions/web-search/providers/http.d.ts.map +1 -1
- package/dist/extensions/web-search/providers/http.js.map +1 -1
- package/dist/extensions/web-search/providers/minimax.d.ts.map +1 -1
- package/dist/extensions/web-search/providers/minimax.js +0 -1
- package/dist/extensions/web-search/providers/minimax.js.map +1 -1
- package/dist/extensions/web-search/render.d.ts +7 -2
- package/dist/extensions/web-search/render.d.ts.map +1 -1
- package/dist/extensions/web-search/render.js +32 -4
- package/dist/extensions/web-search/render.js.map +1 -1
- package/dist/extensions/web-search/results.d.ts.map +1 -1
- package/dist/extensions/web-search/results.js +3 -8
- package/dist/extensions/web-search/results.js.map +1 -1
- package/dist/extensions/web-search/types.d.ts +4 -2
- package/dist/extensions/web-search/types.d.ts.map +1 -1
- package/dist/extensions/web-search/types.js.map +1 -1
- package/dist/index.d.ts +2 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -1
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +6 -0
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.d.ts +8 -2
- package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.js +24 -21
- package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
- package/dist/modes/interactive/components/pi-logo-animation.d.ts +68 -0
- package/dist/modes/interactive/components/pi-logo-animation.d.ts.map +1 -0
- package/dist/modes/interactive/components/pi-logo-animation.js +1076 -0
- package/dist/modes/interactive/components/pi-logo-animation.js.map +1 -0
- package/dist/modes/interactive/components/pi-logo-animation.lazy.d.ts +7 -0
- package/dist/modes/interactive/components/pi-logo-animation.lazy.d.ts.map +1 -0
- package/dist/modes/interactive/components/pi-logo-animation.lazy.js +12 -0
- package/dist/modes/interactive/components/pi-logo-animation.lazy.js.map +1 -0
- package/dist/modes/interactive/components/pi-logo.d.ts +7 -0
- package/dist/modes/interactive/components/pi-logo.d.ts.map +1 -1
- package/dist/modes/interactive/components/pi-logo.js +13 -1
- package/dist/modes/interactive/components/pi-logo.js.map +1 -1
- package/dist/modes/interactive/components/radius-login-selector.d.ts +15 -0
- package/dist/modes/interactive/components/radius-login-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/radius-login-selector.js +83 -0
- package/dist/modes/interactive/components/radius-login-selector.js.map +1 -0
- package/dist/modes/interactive/components/settings-selector.d.ts +3 -3
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +5 -5
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/status-marker.d.ts +0 -2
- package/dist/modes/interactive/components/status-marker.d.ts.map +1 -1
- package/dist/modes/interactive/components/status-marker.js +0 -4
- package/dist/modes/interactive/components/status-marker.js.map +1 -1
- package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/user-message.js +5 -4
- package/dist/modes/interactive/components/user-message.js.map +1 -1
- package/dist/modes/interactive/components/visual-truncate.d.ts +27 -3
- package/dist/modes/interactive/components/visual-truncate.d.ts.map +1 -1
- package/dist/modes/interactive/components/visual-truncate.js +36 -6
- package/dist/modes/interactive/components/visual-truncate.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +10 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +167 -40
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/tasks/completion-render.d.ts +1 -1
- package/dist/modes/interactive/tasks/completion-render.d.ts.map +1 -1
- package/dist/modes/interactive/tasks/completion-render.js +28 -82
- package/dist/modes/interactive/tasks/completion-render.js.map +1 -1
- package/dist/modes/interactive/tasks/index.d.ts.map +1 -1
- package/dist/modes/interactive/tasks/index.js +18 -13
- package/dist/modes/interactive/tasks/index.js.map +1 -1
- package/dist/modes/interactive/tasks/inspector.d.ts +35 -0
- package/dist/modes/interactive/tasks/inspector.d.ts.map +1 -0
- package/dist/modes/interactive/tasks/inspector.js +93 -0
- package/dist/modes/interactive/tasks/inspector.js.map +1 -0
- package/dist/modes/interactive/tasks/layout.d.ts +40 -0
- package/dist/modes/interactive/tasks/layout.d.ts.map +1 -0
- package/dist/modes/interactive/tasks/layout.js +212 -0
- package/dist/modes/interactive/tasks/layout.js.map +1 -0
- package/dist/modes/interactive/tasks/list.d.ts +21 -0
- package/dist/modes/interactive/tasks/list.d.ts.map +1 -0
- package/dist/modes/interactive/tasks/list.js +96 -0
- package/dist/modes/interactive/tasks/list.js.map +1 -0
- package/dist/modes/interactive/tasks/manager.d.ts +29 -36
- package/dist/modes/interactive/tasks/manager.d.ts.map +1 -1
- package/dist/modes/interactive/tasks/manager.js +315 -315
- package/dist/modes/interactive/tasks/manager.js.map +1 -1
- package/dist/modes/interactive/tasks/model.d.ts +21 -0
- package/dist/modes/interactive/tasks/model.d.ts.map +1 -0
- package/dist/modes/interactive/tasks/model.js +41 -0
- package/dist/modes/interactive/tasks/model.js.map +1 -0
- package/dist/modes/interactive/tasks/render.d.ts +5 -19
- package/dist/modes/interactive/tasks/render.d.ts.map +1 -1
- package/dist/modes/interactive/tasks/render.js +18 -102
- package/dist/modes/interactive/tasks/render.js.map +1 -1
- package/dist/modes/interactive/tasks/task-view.d.ts +8 -48
- package/dist/modes/interactive/tasks/task-view.d.ts.map +1 -1
- package/dist/modes/interactive/tasks/task-view.js +11 -51
- package/dist/modes/interactive/tasks/task-view.js.map +1 -1
- package/dist/modes/interactive/tasks/text.d.ts +1 -7
- package/dist/modes/interactive/tasks/text.d.ts.map +1 -1
- package/dist/modes/interactive/tasks/text.js +6 -29
- package/dist/modes/interactive/tasks/text.js.map +1 -1
- package/dist/modes/interactive/tasks/viewport.d.ts +2 -0
- package/dist/modes/interactive/tasks/viewport.d.ts.map +1 -1
- package/dist/modes/interactive/tasks/viewport.js +17 -7
- package/dist/modes/interactive/tasks/viewport.js.map +1 -1
- package/dist/modes/interactive/tasks/views.d.ts +9 -0
- package/dist/modes/interactive/tasks/views.d.ts.map +1 -0
- package/dist/modes/interactive/tasks/views.js +42 -0
- package/dist/modes/interactive/tasks/views.js.map +1 -0
- package/dist/modes/interactive/theme/system-theme.d.ts +2 -1
- package/dist/modes/interactive/theme/system-theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/system-theme.js +16 -5
- package/dist/modes/interactive/theme/system-theme.js.map +1 -1
- package/docs/bundled/README.md +0 -1
- package/docs/bundled/extensions/question.md +2 -2
- package/docs/bundled/extensions/statusline.md +24 -15
- package/docs/bundled/tasks.md +34 -48
- package/docs/codemode.md +207 -0
- package/docs/docs.json +4 -4
- package/docs/environment-variables.md +1 -1
- package/docs/extensions.md +7 -9
- package/docs/keybindings.md +13 -6
- package/docs/mcp.md +142 -82
- package/docs/models.md +21 -0
- package/docs/providers.md +8 -0
- package/docs/sdk.md +2 -2
- package/docs/session-format.md +12 -22
- package/docs/settings.md +4 -2
- package/docs/tui.md +1 -1
- package/docs/usage.md +6 -16
- package/examples/README.md +1 -1
- package/examples/extensions/README.md +1 -2
- package/examples/extensions/built-in-tool-renderer.ts +16 -40
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/gondolin/package-lock.json +2 -2
- package/examples/extensions/gondolin/package.json +1 -1
- package/examples/extensions/minimal-mode.ts +24 -96
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/examples/sdk/14-codemode-mcp.ts +2 -2
- package/npm-shrinkwrap.json +69 -58
- package/package.json +11 -10
- package/dist/bundle/chunks/anthropic-messages-KIXY7EDT.js +0 -6
- package/dist/bundle/chunks/chunk-CLLDCO64.js +0 -2
- package/dist/bundle/chunks/chunk-UUSTLCVC.js +0 -2
- package/dist/bundle/chunks/chunk-VWCWZD6E.js +0 -2
- package/dist/bundle/chunks/virtual-modules-TQRORWJQ.js +0 -2
- package/dist/core/tasks/view-data.d.ts +0 -8
- package/dist/core/tasks/view-data.d.ts.map +0 -1
- package/dist/core/tasks/view-data.js +0 -61
- package/dist/core/tasks/view-data.js.map +0 -1
- package/dist/core/tasks/view.d.ts +0 -30
- package/dist/core/tasks/view.d.ts.map +0 -1
- package/dist/core/tasks/view.js +0 -50
- package/dist/core/tasks/view.js.map +0 -1
- package/dist/core/tools/renderers/shell-task.d.ts +0 -4
- package/dist/core/tools/renderers/shell-task.d.ts.map +0 -1
- package/dist/core/tools/renderers/shell-task.js +0 -35
- package/dist/core/tools/renderers/shell-task.js.map +0 -1
- package/dist/extensions/todo/constants.d.ts +0 -16
- package/dist/extensions/todo/constants.d.ts.map +0 -1
- package/dist/extensions/todo/constants.js +0 -30
- package/dist/extensions/todo/constants.js.map +0 -1
- package/dist/extensions/todo/index.d.ts +0 -3
- package/dist/extensions/todo/index.d.ts.map +0 -1
- package/dist/extensions/todo/index.js +0 -98
- package/dist/extensions/todo/index.js.map +0 -1
- package/dist/extensions/todo/schema.d.ts +0 -60
- package/dist/extensions/todo/schema.d.ts.map +0 -1
- package/dist/extensions/todo/schema.js +0 -56
- package/dist/extensions/todo/schema.js.map +0 -1
- package/dist/extensions/todo/state.d.ts +0 -34
- package/dist/extensions/todo/state.d.ts.map +0 -1
- package/dist/extensions/todo/state.js +0 -425
- package/dist/extensions/todo/state.js.map +0 -1
- package/dist/extensions/todo/view.d.ts +0 -36
- package/dist/extensions/todo/view.d.ts.map +0 -1
- package/dist/extensions/todo/view.js +0 -580
- package/dist/extensions/todo/view.js.map +0 -1
- package/dist/extensions/todo/widget.d.ts +0 -15
- package/dist/extensions/todo/widget.d.ts.map +0 -1
- package/dist/extensions/todo/widget.js +0 -50
- package/dist/extensions/todo/widget.js.map +0 -1
- package/dist/modes/interactive/tasks/fallback-view.d.ts +0 -4
- package/dist/modes/interactive/tasks/fallback-view.d.ts.map +0 -1
- package/dist/modes/interactive/tasks/fallback-view.js +0 -27
- package/dist/modes/interactive/tasks/fallback-view.js.map +0 -1
- package/docs/bundled/extensions/todo.md +0 -104
- package/examples/extensions/todo.ts +0 -297
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/extensions/mcp/config.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * MCP server configuration.\n *\n * Servers are read from `mcp.json` in the agent directory and, for trusted projects, from\n * `<project>/.pi/mcp.json`. Both use the `mcpServers` shape shared by other MCP clients, so\n * existing configurations can be copied over. Project entries replace global entries with the\n * same name.\n *\n * ```json\n * {\n * \"mcpServers\": {\n * \"filesystem\": { \"command\": \"npx\", \"args\": [\"-y\", \"@modelcontextprotocol/server-filesystem\", \".\"] },\n * \"docs\": { \"url\": \"https://example.com/mcp\", \"headers\": { \"Authorization\": \"Bearer ${DOCS_TOKEN}\" } },\n * \"sentry\": { \"url\": \"https://mcp.sentry.dev/mcp\" }\n * }\n * }\n * ```\n *\n * HTTP servers without an `Authorization` header use OAuth when they answer 401 (sign in with `/mcp`).\n *\n * The top-level `autoEnableCodemode` (default true) activates the codemode tool when a server\n * with `codemode` or `codemode-deferred` exposure connects. A project value overrides the global one.\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { CONFIG_DIR_NAME } from \"../../config.ts\";\nimport { type McpExposure, type McpServerConfig, validateMcpServerConfig } from \"../../core/mcp-servers.ts\";\n\nexport type {\n\tMcpExposure,\n\tMcpHttpServerConfig,\n\tMcpOAuthConfig,\n\tMcpServerConfig,\n\tMcpStdioServerConfig,\n} from \"../../core/mcp-servers.ts\";\nexport { getMcpToolExposure } from \"../../core/mcp-servers.ts\";\n\nexport interface McpServerEntry {\n\tname: string;\n\tconfig: McpServerConfig;\n\t/** Config file that defined the entry, or the path of the extension that registered it. */\n\tsource: string;\n\t/**\n\t * The global or the project `mcp.json`, or `extension` for servers registered with\n\t * `pi.registerMcpServer()`. Changes to extension servers are not saved.\n\t */\n\tscope?: \"global\" | \"project\" | \"extension\";\n}\n\nexport interface LoadedMcpConfig {\n\tservers: McpServerEntry[];\n\t/** Activate the codemode tool when `codemode` or `codemode-deferred` servers connect. Default: true. */\n\tautoEnableCodemode?: boolean;\n\terrors: string[];\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\ninterface McpConfigState {\n\tservers: Map<string, McpServerEntry>;\n\tautoEnableCodemode?: boolean;\n\terrors: string[];\n}\n\nfunction readConfigFile(path: string, scope: \"global\" | \"project\", state: McpConfigState): void {\n\tconst { servers, errors } = state;\n\tif (!existsSync(path)) return;\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(readFileSync(path, \"utf8\"));\n\t} catch (error) {\n\t\terrors.push(`${path}: ${error instanceof Error ? error.message : String(error)}`);\n\t\treturn;\n\t}\n\tif (!isRecord(parsed) || (parsed.mcpServers !== undefined && !isRecord(parsed.mcpServers))) {\n\t\terrors.push(`${path}: expected an object with an \"mcpServers\" object`);\n\t\treturn;\n\t}\n\tif (typeof parsed.autoEnableCodemode === \"boolean\") state.autoEnableCodemode = parsed.autoEnableCodemode;\n\telse if (parsed.autoEnableCodemode !== undefined) errors.push(`${path}: autoEnableCodemode must be a boolean`);\n\tfor (const [name, value] of Object.entries(parsed.mcpServers ?? {})) {\n\t\tconst config = validateMcpServerConfig(name, value);\n\t\tif (typeof config === \"string\") {\n\t\t\terrors.push(`${path}: ${config}`);\n\t\t\tcontinue;\n\t\t}\n\t\tservers.set(name, { name, config, source: path, scope });\n\t}\n}\n\n/**\n * Load global and (when trusted) project MCP configuration. Disabled servers are included with\n * `enabled: false`, so they can be enabled again.\n */\nexport function loadMcpConfig(options: { agentDir: string; cwd: string; projectTrusted: boolean }): LoadedMcpConfig {\n\tconst state: McpConfigState = { servers: new Map(), errors: [] };\n\treadConfigFile(join(options.agentDir, \"mcp.json\"), \"global\", state);\n\tif (options.projectTrusted) readConfigFile(join(options.cwd, CONFIG_DIR_NAME, \"mcp.json\"), \"project\", state);\n\treturn {\n\t\tservers: [...state.servers.values()],\n\t\t...(state.autoEnableCodemode === undefined ? {} : { autoEnableCodemode: state.autoEnableCodemode }),\n\t\terrors: state.errors,\n\t};\n}\n\n/** Settings `/mcp` changes. `enabled: true` and `exposure: \"codemode\"` are the defaults and remove the key. */\nexport interface McpServerConfigPatch {\n\tenabled?: boolean;\n\texposure?: McpExposure;\n}\n\n/**\n * Change one server's settings in the `mcp.json` that defines it. Other content is kept; the file is\n * rewritten with its indentation.\n */\nexport function updateMcpServerConfig(path: string, name: string, patch: McpServerConfigPatch): void {\n\teditMcpServers(path, (servers) => {\n\t\tconst server = servers?.[name];\n\t\tif (!isRecord(server)) throw new Error(`${path} does not define MCP server \"${name}\"`);\n\t\tif (patch.enabled !== undefined) {\n\t\t\tif (patch.enabled) delete server.enabled;\n\t\t\telse server.enabled = false;\n\t\t}\n\t\tif (patch.exposure !== undefined) {\n\t\t\tif (patch.exposure === \"codemode\") delete server.exposure;\n\t\t\telse server.exposure = patch.exposure;\n\t\t}\n\t\treturn true;\n\t});\n}\n\n/**\n * Add a server to an `mcp.json`, creating the file when missing. An existing entry with the same\n * name is replaced. Returns true when an entry was replaced.\n */\nexport function addMcpServerConfig(path: string, name: string, config: McpServerConfig): boolean {\n\tlet replaced = false;\n\teditMcpServers(path, (servers, parsed) => {\n\t\tconst target = servers ?? {};\n\t\treplaced = target[name] !== undefined;\n\t\ttarget[name] = config;\n\t\tparsed.mcpServers = target;\n\t\treturn true;\n\t});\n\treturn replaced;\n}\n\n/** Remove a server from an `mcp.json`. Returns false when the file does not define it. */\nexport function removeMcpServerConfig(path: string, name: string): boolean {\n\tif (!existsSync(path)) return false;\n\tlet removed = false;\n\teditMcpServers(path, (servers) => {\n\t\tif (!servers || servers[name] === undefined) return false;\n\t\tdelete servers[name];\n\t\tremoved = true;\n\t\treturn true;\n\t});\n\treturn removed;\n}\n\n/**\n * Read an `mcp.json` (an empty config when missing), let `edit` change its `mcpServers`, and write\n * it back with its indentation when `edit` returns true. Other content is kept.\n */\nfunction editMcpServers(\n\tpath: string,\n\tedit: (servers: Record<string, unknown> | undefined, parsed: Record<string, unknown>) => boolean,\n): void {\n\tconst text = existsSync(path) ? readFileSync(path, \"utf8\") : undefined;\n\tconst parsed: unknown = text === undefined ? {} : JSON.parse(text);\n\tif (!isRecord(parsed) || (parsed.mcpServers !== undefined && !isRecord(parsed.mcpServers))) {\n\t\tthrow new Error(`${path}: expected an object with an \"mcpServers\" object`);\n\t}\n\tconst servers = isRecord(parsed.mcpServers) ? parsed.mcpServers : undefined;\n\tif (!edit(servers, parsed)) return;\n\tconst indent = (text && /^([ \\t]+)\\S/m.exec(text)?.[1]) || \" \";\n\tmkdirSync(dirname(path), { recursive: true });\n\twriteFileSync(path, `${JSON.stringify(parsed, null, indent)}\\n`);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/extensions/mcp/config.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * MCP server configuration.\n *\n * Servers are read from `mcp.json` in the agent directory and, for trusted projects, from\n * `<project>/.pi/mcp.json`. Both use the `mcpServers` shape shared by other MCP clients, so\n * existing configurations can be copied over. Project entries replace global entries with the\n * same name.\n *\n * ```json\n * {\n * \"mcpServers\": {\n * \"filesystem\": { \"command\": \"npx\", \"args\": [\"-y\", \"@modelcontextprotocol/server-filesystem\", \".\"] },\n * \"docs\": { \"url\": \"https://example.com/mcp\", \"headers\": { \"Authorization\": \"Bearer ${DOCS_TOKEN}\" } },\n * \"sentry\": { \"url\": \"https://mcp.sentry.dev/mcp\" }\n * }\n * }\n * ```\n *\n * HTTP servers without an `Authorization` header use OAuth when they answer 401 (sign in with `/mcp`).\n * `\"auth\": { \"provider\": \"<provider>\" }` sends the token of a `/login` provider instead. Project files\n * cannot use it, so a repository cannot pick where the credential goes.\n *\n * The top-level `autoEnableCodemode` (default true) activates the codemode tool when a server\n * with `codemode` exposure connects. A project value overrides the global one.\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { CONFIG_DIR_NAME } from \"../../config.ts\";\nimport {\n\ttype McpExposure,\n\ttype McpServerConfig,\n\tmcpNamespace,\n\tvalidateMcpServerConfig,\n} from \"../../core/mcp-servers.ts\";\n\nexport type {\n\tMcpExposure,\n\tMcpHttpServerConfig,\n\tMcpOAuthConfig,\n\tMcpServerConfig,\n\tMcpStdioServerConfig,\n} from \"../../core/mcp-servers.ts\";\nexport { getMcpToolExposure } from \"../../core/mcp-servers.ts\";\n\nexport interface McpServerEntry {\n\tname: string;\n\tconfig: McpServerConfig;\n\t/** Config file that defined the entry, or the path of the extension that registered it. */\n\tsource: string;\n\t/**\n\t * The global or the project `mcp.json`, or `extension` for servers registered with\n\t * `pi.registerMcpServer()`. Changes to extension servers are not saved.\n\t */\n\tscope?: \"global\" | \"project\" | \"extension\";\n}\n\nexport interface LoadedMcpConfig {\n\tservers: McpServerEntry[];\n\t/** Activate the codemode tool when `codemode` servers connect. Default: true. */\n\tautoEnableCodemode?: boolean;\n\terrors: string[];\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\ninterface McpConfigState {\n\tservers: Map<string, McpServerEntry>;\n\tautoEnableCodemode?: boolean;\n\terrors: string[];\n}\n\nfunction readConfigFile(path: string, scope: \"global\" | \"project\", state: McpConfigState): void {\n\tconst { servers, errors } = state;\n\tif (!existsSync(path)) return;\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(readFileSync(path, \"utf8\"));\n\t} catch (error) {\n\t\terrors.push(`${path}: ${error instanceof Error ? error.message : String(error)}`);\n\t\treturn;\n\t}\n\tif (!isRecord(parsed) || (parsed.mcpServers !== undefined && !isRecord(parsed.mcpServers))) {\n\t\terrors.push(`${path}: expected an object with an \"mcpServers\" object`);\n\t\treturn;\n\t}\n\tif (typeof parsed.autoEnableCodemode === \"boolean\") state.autoEnableCodemode = parsed.autoEnableCodemode;\n\telse if (parsed.autoEnableCodemode !== undefined) errors.push(`${path}: autoEnableCodemode must be a boolean`);\n\tfor (const [name, value] of Object.entries(parsed.mcpServers ?? {})) {\n\t\tconst config = validateMcpServerConfig(name, value);\n\t\tif (typeof config === \"string\") {\n\t\t\terrors.push(`${path}: ${config}`);\n\t\t\tcontinue;\n\t\t}\n\t\t// Names that differ only in `-` and `_` would share a namespace.\n\t\tconst clash = [...servers.keys()].find((other) => other !== name && mcpNamespace(other) === mcpNamespace(name));\n\t\tif (clash) {\n\t\t\terrors.push(`${path}: server \"${name}\" conflicts with \"${clash}\"`);\n\t\t\tcontinue;\n\t\t}\n\t\tif (scope === \"project\" && \"url\" in config && config.auth) {\n\t\t\terrors.push(`${path}: server \"${name}\": auth is only allowed in the global mcp.json`);\n\t\t\tcontinue;\n\t\t}\n\t\tservers.set(name, { name, config, source: path, scope });\n\t}\n}\n\n/**\n * Load global and (when trusted) project MCP configuration. Disabled servers are included with\n * `enabled: false`, so they can be enabled again.\n */\nexport function loadMcpConfig(options: { agentDir: string; cwd: string; projectTrusted: boolean }): LoadedMcpConfig {\n\tconst state: McpConfigState = { servers: new Map(), errors: [] };\n\treadConfigFile(join(options.agentDir, \"mcp.json\"), \"global\", state);\n\tif (options.projectTrusted) readConfigFile(join(options.cwd, CONFIG_DIR_NAME, \"mcp.json\"), \"project\", state);\n\treturn {\n\t\tservers: [...state.servers.values()],\n\t\t...(state.autoEnableCodemode === undefined ? {} : { autoEnableCodemode: state.autoEnableCodemode }),\n\t\terrors: state.errors,\n\t};\n}\n\n/** Settings `/mcp` changes. `enabled: true` and `exposure: \"codemode\"` are the defaults and remove the key. */\nexport interface McpServerConfigPatch {\n\tenabled?: boolean;\n\texposure?: McpExposure;\n}\n\n/**\n * Change one server's settings in the `mcp.json` that defines it. Other content is kept; the file is\n * rewritten with its indentation.\n */\nexport function updateMcpServerConfig(path: string, name: string, patch: McpServerConfigPatch): void {\n\teditMcpServers(path, (servers) => {\n\t\tconst server = servers?.[name];\n\t\tif (!isRecord(server)) throw new Error(`${path} does not define MCP server \"${name}\"`);\n\t\tif (patch.enabled !== undefined) {\n\t\t\tif (patch.enabled) delete server.enabled;\n\t\t\telse server.enabled = false;\n\t\t}\n\t\tif (patch.exposure !== undefined) {\n\t\t\tif (patch.exposure === \"codemode\") delete server.exposure;\n\t\t\telse server.exposure = patch.exposure;\n\t\t}\n\t\treturn true;\n\t});\n}\n\n/**\n * Add a server to an `mcp.json`, creating the file when missing. An existing entry with the same\n * name is replaced. Returns true when an entry was replaced.\n */\nexport function addMcpServerConfig(path: string, name: string, config: McpServerConfig): boolean {\n\tlet replaced = false;\n\teditMcpServers(path, (servers, parsed) => {\n\t\tconst target = servers ?? {};\n\t\treplaced = target[name] !== undefined;\n\t\ttarget[name] = config;\n\t\tparsed.mcpServers = target;\n\t\treturn true;\n\t});\n\treturn replaced;\n}\n\n/** Remove a server from an `mcp.json`. Returns false when the file does not define it. */\nexport function removeMcpServerConfig(path: string, name: string): boolean {\n\tif (!existsSync(path)) return false;\n\tlet removed = false;\n\teditMcpServers(path, (servers) => {\n\t\tif (!servers || servers[name] === undefined) return false;\n\t\tdelete servers[name];\n\t\tremoved = true;\n\t\treturn true;\n\t});\n\treturn removed;\n}\n\n/**\n * Read an `mcp.json` (an empty config when missing), let `edit` change its `mcpServers`, and write\n * it back with its indentation when `edit` returns true. Other content is kept.\n */\nfunction editMcpServers(\n\tpath: string,\n\tedit: (servers: Record<string, unknown> | undefined, parsed: Record<string, unknown>) => boolean,\n): void {\n\tconst text = existsSync(path) ? readFileSync(path, \"utf8\") : undefined;\n\tconst parsed: unknown = text === undefined ? {} : JSON.parse(text);\n\tif (!isRecord(parsed) || (parsed.mcpServers !== undefined && !isRecord(parsed.mcpServers))) {\n\t\tthrow new Error(`${path}: expected an object with an \"mcpServers\" object`);\n\t}\n\tconst servers = isRecord(parsed.mcpServers) ? parsed.mcpServers : undefined;\n\tif (!edit(servers, parsed)) return;\n\tconst indent = (text && /^([ \\t]+)\\S/m.exec(text)?.[1]) || \" \";\n\tmkdirSync(dirname(path), { recursive: true });\n\twriteFileSync(path, `${JSON.stringify(parsed, null, indent)}\\n`);\n}\n"]}
|
|
@@ -3,12 +3,15 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Connects the servers from `mcp.json` and the servers extensions register with
|
|
5
5
|
* `pi.registerMcpServer()` when a session starts, and servers registered later right away. A server
|
|
6
|
-
* in `mcp.json` takes precedence over a registered server of the same name.
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* the
|
|
6
|
+
* in `mcp.json` takes precedence over a registered server of the same name. Connections run in the
|
|
7
|
+
* background: the first prompt waits only for servers with `direct` tools, and codemode scripts,
|
|
8
|
+
* `tool_search`, and the resource tools wait for the servers they need when they run. Tools are
|
|
9
|
+
* registered as `mcp__<server>__<tool>`. By default (`"exposure": "codemode"`) the tools are only
|
|
10
|
+
* callable from codemode scripts, which keeps MCP tools out of the model's tool declarations and
|
|
11
|
+
* the codemode description: scripts find the tools with `searchTools()` and the server instructions
|
|
12
|
+
* with `describeNamespace()`. The codemode tool is activated for that unless `autoEnableCodemode` is
|
|
13
|
+
* false. `"deferred"` declares the tools to the model once the `tool_search` tool loads them, and
|
|
14
|
+
* activates `tool_search` instead of codemode.
|
|
12
15
|
* `"exposure": "direct"` declares them to the model right away, and `"hidden"` makes them
|
|
13
16
|
* unreachable. `toolExposure` overrides the exposure of single tools. Servers with resources are
|
|
14
17
|
* reached through Codex's `list_mcp_resources`, `list_mcp_resource_templates`, and
|
|
@@ -41,11 +44,32 @@ export interface McpExtensionOptions {
|
|
|
41
44
|
/** Saves `/mcp` changes to the server's config file. Defaults to editing its `mcp.json`. */
|
|
42
45
|
updateConfig?: (entry: McpServerEntry, patch: McpServerConfigPatch) => void;
|
|
43
46
|
/**
|
|
44
|
-
* How long the first prompt waits for servers that are still connecting at
|
|
45
|
-
* milliseconds. Their tools become available when they connect.
|
|
47
|
+
* How long the first prompt waits for servers with `direct` tools that are still connecting at
|
|
48
|
+
* startup, in milliseconds. Their tools become available when they connect. Other servers are
|
|
49
|
+
* waited for when a script or search needs them. Default: 10000.
|
|
46
50
|
*/
|
|
47
51
|
startupWaitMs?: number;
|
|
48
52
|
}
|
|
53
|
+
/** Name of the system prompt section that lists the servers whose tools are not declared. */
|
|
54
|
+
export declare const MCP_SERVERS_SECTION = "mcp_servers";
|
|
55
|
+
/**
|
|
56
|
+
* Characters of the whole section. Descriptions shrink to fit; when the server lines alone do not
|
|
57
|
+
* fit, the last servers are left out and counted in a closing line.
|
|
58
|
+
*/
|
|
59
|
+
export declare const MAX_SERVERS_SECTION_CHARS = 4096;
|
|
60
|
+
/** What the `mcp_servers` section needs of a server. */
|
|
61
|
+
export interface McpServerListing {
|
|
62
|
+
entry: McpServerEntry;
|
|
63
|
+
connection?: {
|
|
64
|
+
instructions?: string;
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* The `mcp_servers` section: every enabled server with codemode or deferred tools, with how its
|
|
69
|
+
* tools are reached and a one-line summary. The model learns of the servers from it, since neither
|
|
70
|
+
* codemode nor tool_search lists them. Undefined when there are no such servers.
|
|
71
|
+
*/
|
|
72
|
+
export declare function renderServersSection(servers: readonly McpServerListing[]): string | undefined;
|
|
49
73
|
export declare function createMcpExtension(options?: McpExtensionOptions): ExtensionFactory;
|
|
50
74
|
declare const _default: ExtensionFactory;
|
|
51
75
|
export default _default;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/extensions/mcp/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/extensions/mcp/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAMH,OAAO,KAAK,EAGX,gBAAgB,EAChB,gBAAgB,EAEhB,MAAM,gCAAgC,CAAC;AAIxC,OAAO,EAEN,KAAK,eAAe,EAGpB,KAAK,oBAAoB,EACzB,KAAK,cAAc,EAEnB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,uBAAuB,EAAmB,MAAM,YAAY,CAAC;AAS3E,OAAO,KAAK,EAAqC,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAI3F,YAAY,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAExD,MAAM,WAAW,mBAAmB;IACnC,uFAAuF;IACvF,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,gBAAgB,KAAK,eAAe,CAAC;IACxD,qFAAqF;IACrF,eAAe,CAAC,EAAE,mBAAmB,CAAC;IACtC,0DAA0D;IAC1D,WAAW,CAAC,EAAE,uBAAuB,CAAC;IACtC,8FAA8F;IAC9F,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2EAA2E;IAC3E,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,4FAA4F;IAC5F,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,oBAAoB,KAAK,IAAI,CAAC;IAC5E;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACvB;AA8DD,6FAA6F;AAC7F,eAAO,MAAM,mBAAmB,gBAAgB,CAAC;AAGjD;;;GAGG;AACH,eAAO,MAAM,yBAAyB,OAAO,CAAC;AAe9C,wDAAwD;AACxD,MAAM,WAAW,gBAAgB;IAChC,KAAK,EAAE,cAAc,CAAC;IACtB,UAAU,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACvC;AAQD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,SAAS,gBAAgB,EAAE,GAAG,MAAM,GAAG,SAAS,CA0B7F;AA2DD,wBAAgB,kBAAkB,CAAC,OAAO,GAAE,mBAAwB,GAAG,gBAAgB,CAm5BtF;;AAMD,wBAAoC"}
|
|
@@ -3,12 +3,15 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Connects the servers from `mcp.json` and the servers extensions register with
|
|
5
5
|
* `pi.registerMcpServer()` when a session starts, and servers registered later right away. A server
|
|
6
|
-
* in `mcp.json` takes precedence over a registered server of the same name.
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* the
|
|
6
|
+
* in `mcp.json` takes precedence over a registered server of the same name. Connections run in the
|
|
7
|
+
* background: the first prompt waits only for servers with `direct` tools, and codemode scripts,
|
|
8
|
+
* `tool_search`, and the resource tools wait for the servers they need when they run. Tools are
|
|
9
|
+
* registered as `mcp__<server>__<tool>`. By default (`"exposure": "codemode"`) the tools are only
|
|
10
|
+
* callable from codemode scripts, which keeps MCP tools out of the model's tool declarations and
|
|
11
|
+
* the codemode description: scripts find the tools with `searchTools()` and the server instructions
|
|
12
|
+
* with `describeNamespace()`. The codemode tool is activated for that unless `autoEnableCodemode` is
|
|
13
|
+
* false. `"deferred"` declares the tools to the model once the `tool_search` tool loads them, and
|
|
14
|
+
* activates `tool_search` instead of codemode.
|
|
12
15
|
* `"exposure": "direct"` declares them to the model right away, and `"hidden"` makes them
|
|
13
16
|
* unreachable. `toolExposure` overrides the exposure of single tools. Servers with resources are
|
|
14
17
|
* reached through Codex's `list_mcp_resources`, `list_mcp_resource_templates`, and
|
|
@@ -23,19 +26,25 @@
|
|
|
23
26
|
* current session for registered servers.
|
|
24
27
|
*/
|
|
25
28
|
import { join, resolve } from "node:path";
|
|
29
|
+
import { hyperlink } from "@earendil-works/pi-tui";
|
|
26
30
|
import { getAgentDir } from "../../config.js";
|
|
31
|
+
import { mcpNamespace } from "../../core/mcp-servers.js";
|
|
27
32
|
import { openBrowser } from "../../utils/open-browser.js";
|
|
28
33
|
import { getMcpToolExposure, loadMcpConfig, updateMcpServerConfig, } from "./config.js";
|
|
29
|
-
import { createMcpResourceToolDefinitions } from "./resources.js";
|
|
34
|
+
import { createMcpResourceToolDefinitions, LIST_MCP_RESOURCE_TEMPLATES_TOOL, LIST_MCP_RESOURCES_TOOL, READ_MCP_RESOURCE_TOOL, } from "./resources.js";
|
|
30
35
|
import { loadMcpRuntime } from "./runtime.lazy.js";
|
|
31
36
|
import { createMcpToolDefinition, createMcpToolName } from "./tools.js";
|
|
32
37
|
import { showMcpManager } from "./ui.js";
|
|
33
38
|
const DEFAULT_STARTUP_WAIT_MS = 10_000;
|
|
34
39
|
const CODEMODE_TOOL_NAME = "codemode";
|
|
35
40
|
const TOOL_SEARCH_TOOL_NAME = "tool_search";
|
|
41
|
+
const RESOURCE_TOOL_NAMES = new Set([
|
|
42
|
+
LIST_MCP_RESOURCES_TOOL,
|
|
43
|
+
LIST_MCP_RESOURCE_TEMPLATES_TOOL,
|
|
44
|
+
READ_MCP_RESOURCE_TOOL,
|
|
45
|
+
]);
|
|
36
46
|
const EXPOSURE_DESCRIPTIONS = {
|
|
37
|
-
codemode: "called from codemode scripts,
|
|
38
|
-
"codemode-deferred": "called from codemode scripts, not listed; scripts find them with searchTools()",
|
|
47
|
+
codemode: "called from codemode scripts, which find them with searchTools()",
|
|
39
48
|
deferred: "not declared until tool_search loads them, then called directly; no codemode needed",
|
|
40
49
|
direct: "declared to the model like built-in tools",
|
|
41
50
|
};
|
|
@@ -51,6 +60,86 @@ function isEnabled(server) {
|
|
|
51
60
|
function exposureOf(entry) {
|
|
52
61
|
return entry.config.exposure ?? "codemode";
|
|
53
62
|
}
|
|
63
|
+
/** Exposures the server's tools can have, known from its config before it connects. */
|
|
64
|
+
function configuredExposures(entry) {
|
|
65
|
+
return new Set([exposureOf(entry), ...Object.values(entry.config.toolExposure ?? {})]);
|
|
66
|
+
}
|
|
67
|
+
/** Whether some of the server's tools are declared to the model, so the first prompt waits for them. */
|
|
68
|
+
function hasDirectTools(entry) {
|
|
69
|
+
return configuredExposures(entry).has("direct");
|
|
70
|
+
}
|
|
71
|
+
/** Whether some of the server's tools are reached through codemode or tool_search. */
|
|
72
|
+
function hasIndirectTools(entry) {
|
|
73
|
+
const exposures = configuredExposures(entry);
|
|
74
|
+
return exposures.has("codemode") || exposures.has("deferred");
|
|
75
|
+
}
|
|
76
|
+
/** Name of the system prompt section that lists the servers whose tools are not declared. */
|
|
77
|
+
export const MCP_SERVERS_SECTION = "mcp_servers";
|
|
78
|
+
/** Characters of a server description in the section, as Codex allows for deferred namespaces. */
|
|
79
|
+
const MAX_SERVER_DESCRIPTION_CHARS = 250;
|
|
80
|
+
/**
|
|
81
|
+
* Characters of the whole section. Descriptions shrink to fit; when the server lines alone do not
|
|
82
|
+
* fit, the last servers are left out and counted in a closing line.
|
|
83
|
+
*/
|
|
84
|
+
export const MAX_SERVERS_SECTION_CHARS = 4096;
|
|
85
|
+
/** The section's first line. It explains only the ways of reaching tools that the listed servers use. */
|
|
86
|
+
function serversSectionIntro(reaches) {
|
|
87
|
+
let intro = "MCP servers whose tools are not declared to you.";
|
|
88
|
+
if (reaches.has("codemode"))
|
|
89
|
+
intro += " Call the tools of `codemode` servers from codemode scripts.";
|
|
90
|
+
if (reaches.has("tool_search"))
|
|
91
|
+
intro += " Load the tools of `tool_search` servers with `tool_search`.";
|
|
92
|
+
return intro;
|
|
93
|
+
}
|
|
94
|
+
function truncate(text, max) {
|
|
95
|
+
if (text.length <= max)
|
|
96
|
+
return text;
|
|
97
|
+
return max <= 1 ? "" : `${text.slice(0, max - 1).trimEnd()}…`;
|
|
98
|
+
}
|
|
99
|
+
/** First line of the configured description, or of the server instructions once connected. */
|
|
100
|
+
function serverSummary(server) {
|
|
101
|
+
const text = server.entry.config.description?.trim() || server.connection?.instructions || "";
|
|
102
|
+
return (text.split("\n", 1)[0] ?? "").trim();
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* The `mcp_servers` section: every enabled server with codemode or deferred tools, with how its
|
|
106
|
+
* tools are reached and a one-line summary. The model learns of the servers from it, since neither
|
|
107
|
+
* codemode nor tool_search lists them. Undefined when there are no such servers.
|
|
108
|
+
*/
|
|
109
|
+
export function renderServersSection(servers) {
|
|
110
|
+
const listed = servers
|
|
111
|
+
.filter((server) => isEnabled(server) && hasIndirectTools(server.entry))
|
|
112
|
+
.sort((a, b) => a.entry.name.localeCompare(b.entry.name));
|
|
113
|
+
if (listed.length === 0)
|
|
114
|
+
return undefined;
|
|
115
|
+
const reaches = listed.map((server) => configuredExposures(server.entry).has("codemode") ? "codemode" : "tool_search");
|
|
116
|
+
const intro = serversSectionIntro(new Set(reaches));
|
|
117
|
+
const heads = listed.map((server, index) => `- ${mcpNamespace(server.entry.name)} (${reaches[index]})`);
|
|
118
|
+
const omitted = (count) => count > 0 ? [`- … ${count} more server${count === 1 ? "" : "s"}; find their tools with searchTools()`] : [];
|
|
119
|
+
// Characters of the intro, the first `kept` server lines without descriptions, and the omission line.
|
|
120
|
+
const size = (kept) => [intro, ...heads.slice(0, kept), ...omitted(listed.length - kept)].join("\n").length;
|
|
121
|
+
let kept = listed.length;
|
|
122
|
+
while (kept > 0 && size(kept) > MAX_SERVERS_SECTION_CHARS)
|
|
123
|
+
kept--;
|
|
124
|
+
// Each description also takes a ": " separator.
|
|
125
|
+
const perServer = kept === 0
|
|
126
|
+
? 0
|
|
127
|
+
: Math.min(MAX_SERVER_DESCRIPTION_CHARS, Math.floor((MAX_SERVERS_SECTION_CHARS - size(kept)) / kept) - 2);
|
|
128
|
+
const lines = listed.slice(0, kept).map((server, index) => {
|
|
129
|
+
const summary = perServer > 0 ? truncate(serverSummary(server), perServer) : "";
|
|
130
|
+
return summary ? `${heads[index]}: ${summary}` : heads[index];
|
|
131
|
+
});
|
|
132
|
+
return [intro, ...lines, ...omitted(listed.length - kept)].join("\n");
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Whether a codemode script needs the server: it names the server's namespace, or searches,
|
|
136
|
+
* enumerates, or describes tools or namespaces, which may name the server in other forms.
|
|
137
|
+
*/
|
|
138
|
+
function scriptNeedsServer(code, server) {
|
|
139
|
+
if (/\b(searchTools|describeNamespace|describeTool|ALL_TOOLS)\b/.test(code))
|
|
140
|
+
return true;
|
|
141
|
+
return code.includes(mcpNamespace(server));
|
|
142
|
+
}
|
|
54
143
|
/** Short state for lists and the startup report. `withError` appends the first line of a failure. */
|
|
55
144
|
function describeState(server, withError = true) {
|
|
56
145
|
if (!isEnabled(server))
|
|
@@ -121,6 +210,8 @@ export function createMcpExtension(options = {}) {
|
|
|
121
210
|
/** Working directory of the session, for stdio servers. */
|
|
122
211
|
let sessionCwd = process.cwd();
|
|
123
212
|
let credentials = options.credentials;
|
|
213
|
+
/** The session's model registry, which resolves `auth.provider` tokens. */
|
|
214
|
+
let modelRegistry;
|
|
124
215
|
let serverLog;
|
|
125
216
|
const openUrl = options.openUrl ?? openBrowser;
|
|
126
217
|
const updateConfig = options.updateConfig ?? ((entry, patch) => updateMcpServerConfig(entry.source, entry.name, patch));
|
|
@@ -142,9 +233,9 @@ export function createMcpExtension(options = {}) {
|
|
|
142
233
|
const registered = [];
|
|
143
234
|
const overriddenNames = [];
|
|
144
235
|
for (const { name, config, extensionPath } of pi.getMcpServers()) {
|
|
145
|
-
const configured = configuredEntries.find((entry) => entry.name === name);
|
|
236
|
+
const configured = configuredEntries.find((entry) => mcpNamespace(entry.name) === mcpNamespace(name));
|
|
146
237
|
if (configured) {
|
|
147
|
-
overriddenNames.push(`"${name}" registered by ${extensionPath} is overridden by ${configured.source}`);
|
|
238
|
+
overriddenNames.push(`"${name}" registered by ${extensionPath} is overridden by "${configured.name}" in ${configured.source}`);
|
|
148
239
|
continue;
|
|
149
240
|
}
|
|
150
241
|
registered.push({
|
|
@@ -171,17 +262,23 @@ export function createMcpExtension(options = {}) {
|
|
|
171
262
|
const registerTools = (connection) => {
|
|
172
263
|
const server = connection.entry.name;
|
|
173
264
|
const entry = findServer(server)?.entry ?? connection.entry;
|
|
174
|
-
const
|
|
265
|
+
const description = entry.config.description?.trim();
|
|
175
266
|
const namespace = {
|
|
176
|
-
name:
|
|
177
|
-
description
|
|
267
|
+
name: mcpNamespace(server),
|
|
268
|
+
...(description ? { description } : {}),
|
|
269
|
+
...(connection.instructions ? { instructions: connection.instructions } : {}),
|
|
178
270
|
};
|
|
179
271
|
const previous = serverTools.get(server) ?? new Set();
|
|
180
272
|
const current = new Set();
|
|
273
|
+
// Like Codex, all tools whose names sanitize to the same name get the hash suffix, so which
|
|
274
|
+
// one would keep the plain name does not depend on the order of the list.
|
|
275
|
+
const plain = [...new Set(connection.tools.map((tool) => tool.name))].map((tool) => createMcpToolName(server, tool));
|
|
181
276
|
const assignName = (tool, owner) => {
|
|
182
277
|
const name = createMcpToolName(server, tool, (candidate) => {
|
|
183
278
|
const existing = toolOwners.get(candidate);
|
|
184
|
-
return (existing !== undefined && existing !== owner) ||
|
|
279
|
+
return ((existing !== undefined && existing !== owner) ||
|
|
280
|
+
current.has(candidate) ||
|
|
281
|
+
plain.indexOf(candidate) !== plain.lastIndexOf(candidate));
|
|
185
282
|
});
|
|
186
283
|
toolOwners.set(name, owner);
|
|
187
284
|
current.add(name);
|
|
@@ -232,7 +329,7 @@ export function createMcpExtension(options = {}) {
|
|
|
232
329
|
*/
|
|
233
330
|
const syncResourceTools = () => {
|
|
234
331
|
const exposures = new Set(serversWithResources().map((server) => exposureOf(server.entry)));
|
|
235
|
-
const exposure = ["direct", "codemode", "
|
|
332
|
+
const exposure = ["direct", "codemode", "deferred"].find((candidate) => exposures.has(candidate));
|
|
236
333
|
const next = exposure ?? "hidden";
|
|
237
334
|
if (next === resourceToolsExposure || (resourceToolsExposure === undefined && next === "hidden"))
|
|
238
335
|
return;
|
|
@@ -246,33 +343,40 @@ export function createMcpExtension(options = {}) {
|
|
|
246
343
|
pi.setActiveTools(pi.getActiveTools().filter((name) => !names.has(name)));
|
|
247
344
|
}
|
|
248
345
|
};
|
|
346
|
+
/**
|
|
347
|
+
* Which of the tools are the bundled codemode and tool_search tools. Other extensions' tools of
|
|
348
|
+
* the same names cannot reach MCP tools. The owning extensions identify their tools through the
|
|
349
|
+
* event bus, so this extension does not import their internals.
|
|
350
|
+
*/
|
|
351
|
+
const discoverOrchestrators = (tools) => {
|
|
352
|
+
const candidates = new Map(tools.map((tool) => [tool.name, tool.parameters]));
|
|
353
|
+
pi.events.emit("pi:discover-tool-orchestrators", candidates);
|
|
354
|
+
return {
|
|
355
|
+
codemode: candidates.get(CODEMODE_TOOL_NAME) === true,
|
|
356
|
+
toolSearch: candidates.get(TOOL_SEARCH_TOOL_NAME) === true,
|
|
357
|
+
};
|
|
358
|
+
};
|
|
249
359
|
/**
|
|
250
360
|
* Tools that are not declared to the model are reached through the codemode tool (scripts call
|
|
251
361
|
* them) or the tool_search tool (it declares them). Either reaches every such tool. Activate the
|
|
252
|
-
* one the tools' exposure asks for: codemode for `codemode`
|
|
253
|
-
*
|
|
362
|
+
* one the tools' exposure asks for: codemode for `codemode` unless `autoEnableCodemode` is false,
|
|
363
|
+
* tool_search for `deferred`.
|
|
254
364
|
*/
|
|
255
365
|
const ensureDiscoveryActive = (ctx) => {
|
|
366
|
+
// From the config, so the tool is active before the servers connect. Resource tools share
|
|
367
|
+
// their server's exposure.
|
|
256
368
|
const exposures = new Set();
|
|
257
|
-
for (const
|
|
258
|
-
if (
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
if (connection.hasResources)
|
|
262
|
-
exposures.add(exposureOf(entry));
|
|
263
|
-
for (const tool of connection.tools)
|
|
264
|
-
exposures.add(getMcpToolExposure(entry.config, tool.name));
|
|
369
|
+
for (const server of servers) {
|
|
370
|
+
if (isEnabled(server))
|
|
371
|
+
for (const exposure of configuredExposures(server.entry))
|
|
372
|
+
exposures.add(exposure);
|
|
265
373
|
}
|
|
266
|
-
const needsCodemode = exposures.has("codemode")
|
|
374
|
+
const needsCodemode = exposures.has("codemode");
|
|
267
375
|
const needsToolSearch = exposures.has("deferred");
|
|
268
376
|
if (!needsCodemode && !needsToolSearch)
|
|
269
377
|
return;
|
|
270
378
|
// Other extensions' tools of the same names cannot reach MCP tools, so never activate them.
|
|
271
|
-
const
|
|
272
|
-
const candidates = new Map(tools.map((tool) => [tool.name, tool.parameters]));
|
|
273
|
-
pi.events.emit("pi:discover-tool-orchestrators", candidates);
|
|
274
|
-
const hasCodemode = candidates.get(CODEMODE_TOOL_NAME) === true;
|
|
275
|
-
const hasToolSearch = candidates.get(TOOL_SEARCH_TOOL_NAME) === true;
|
|
379
|
+
const { codemode: hasCodemode, toolSearch: hasToolSearch } = discoverOrchestrators(pi.getAllTools());
|
|
276
380
|
const active = pi.getActiveTools();
|
|
277
381
|
const activate = [];
|
|
278
382
|
if (needsCodemode && hasCodemode && autoEnableCodemode && !active.includes(CODEMODE_TOOL_NAME)) {
|
|
@@ -301,7 +405,7 @@ export function createMcpExtension(options = {}) {
|
|
|
301
405
|
const tokensAtSignIn = new Map();
|
|
302
406
|
const storedTokens = (connection) => {
|
|
303
407
|
const url = connection.oauthUrl;
|
|
304
|
-
return url && credentials ? JSON.stringify(credentials.tokens(url) ?? null) : "null";
|
|
408
|
+
return url && credentials ? JSON.stringify(credentials.tokens(connection.name, url) ?? null) : "null";
|
|
305
409
|
};
|
|
306
410
|
const onConnectionChange = (connection) => {
|
|
307
411
|
if (connection.state !== "needs-auth")
|
|
@@ -328,6 +432,7 @@ export function createMcpExtension(options = {}) {
|
|
|
328
432
|
cwd: sessionCwd,
|
|
329
433
|
createTransport: options.createTransport ?? runtime.createDefaultTransport,
|
|
330
434
|
credentials: getCredentials(runtime),
|
|
435
|
+
providerToken: async (provider) => modelRegistry?.getApiKeyForProvider(provider),
|
|
331
436
|
log: getServerLog(runtime),
|
|
332
437
|
onTools: registerTools,
|
|
333
438
|
onChange: onConnectionChange,
|
|
@@ -336,6 +441,40 @@ export function createMcpExtension(options = {}) {
|
|
|
336
441
|
emitChange();
|
|
337
442
|
return connection;
|
|
338
443
|
};
|
|
444
|
+
/**
|
|
445
|
+
* Connect the server in the background. `server.ready` settles when it connected or failed;
|
|
446
|
+
* failures show in its state. It starts after `after`; `isCurrent` stops it when the session ended
|
|
447
|
+
* meanwhile. The returned promise rejects when the MCP runtime cannot be loaded.
|
|
448
|
+
*/
|
|
449
|
+
const startConnection = (server, isCurrent, after) => {
|
|
450
|
+
const ready = (async () => {
|
|
451
|
+
await after;
|
|
452
|
+
if (!isCurrent())
|
|
453
|
+
return;
|
|
454
|
+
const connection = await createConnection(server);
|
|
455
|
+
if (!isCurrent())
|
|
456
|
+
return;
|
|
457
|
+
await connection.getClient().catch(() => undefined);
|
|
458
|
+
})();
|
|
459
|
+
server.ready = ready.catch(() => undefined);
|
|
460
|
+
return ready;
|
|
461
|
+
};
|
|
462
|
+
/** Wait for servers still connecting, until they settle or `signal` aborts. */
|
|
463
|
+
const waitForServers = async (waiting, signal) => {
|
|
464
|
+
const ready = waiting.flatMap((server) => (server.ready ? [server.ready] : []));
|
|
465
|
+
if (ready.length === 0 || signal?.aborted)
|
|
466
|
+
return;
|
|
467
|
+
let onAbort;
|
|
468
|
+
await Promise.race([
|
|
469
|
+
Promise.all(ready),
|
|
470
|
+
new Promise((resolve) => {
|
|
471
|
+
onAbort = () => resolve();
|
|
472
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
473
|
+
}),
|
|
474
|
+
]);
|
|
475
|
+
if (onAbort)
|
|
476
|
+
signal?.removeEventListener("abort", onAbort);
|
|
477
|
+
};
|
|
339
478
|
/**
|
|
340
479
|
* One message for everything that needs the user after startup, or only for `only`, servers
|
|
341
480
|
* that connected later.
|
|
@@ -376,7 +515,7 @@ export function createMcpExtension(options = {}) {
|
|
|
376
515
|
try {
|
|
377
516
|
await runtime.signInMcpServer({
|
|
378
517
|
serverUrl: url,
|
|
379
|
-
store: getCredentials(runtime).forServer(url),
|
|
518
|
+
store: getCredentials(runtime).forServer(server.entry.name, url),
|
|
380
519
|
settings: connection.oauthSettings(),
|
|
381
520
|
challenge: connection.challenge,
|
|
382
521
|
prompt,
|
|
@@ -402,7 +541,7 @@ export function createMcpExtension(options = {}) {
|
|
|
402
541
|
const url = connection?.oauthUrl;
|
|
403
542
|
if (!connection || !url)
|
|
404
543
|
return false;
|
|
405
|
-
const removed = getCredentials(await loadMcpRuntime()).remove(url);
|
|
544
|
+
const removed = getCredentials(await loadMcpRuntime()).remove(server.entry.name, url);
|
|
406
545
|
await connection.signOut();
|
|
407
546
|
return removed;
|
|
408
547
|
};
|
|
@@ -431,8 +570,7 @@ export function createMcpExtension(options = {}) {
|
|
|
431
570
|
await connection?.close();
|
|
432
571
|
return undefined;
|
|
433
572
|
}
|
|
434
|
-
|
|
435
|
-
await connection.getClient().catch(() => undefined);
|
|
573
|
+
await startConnection(server, () => true);
|
|
436
574
|
return undefined;
|
|
437
575
|
};
|
|
438
576
|
const setExposure = (server, exposure) => {
|
|
@@ -694,7 +832,11 @@ export function createMcpExtension(options = {}) {
|
|
|
694
832
|
}
|
|
695
833
|
const failure = await signIn(server, {
|
|
696
834
|
showAuthorizationUrl: (url) => {
|
|
697
|
-
|
|
835
|
+
// Long URLs wrap, which some terminals cannot open; a short link line stays on one line.
|
|
836
|
+
const lines = ctx.mode === "tui"
|
|
837
|
+
? `${hyperlink(url.href, url.href)}\n${hyperlink(process.platform === "darwin" ? "Cmd+click to open" : "Ctrl+click to open", url.href)}`
|
|
838
|
+
: url.href;
|
|
839
|
+
ctx.ui.notify(`Sign in to MCP server "${name}" in your browser:\n${lines}`, "info");
|
|
698
840
|
openUrl(url.href);
|
|
699
841
|
},
|
|
700
842
|
promptForRedirectUrl: (signal) => ctx.ui.input(`Waiting for sign-in to "${name}". If the browser cannot reach this machine, paste the URL it was redirected to.`, "http://127.0.0.1:.../callback?code=...", { signal }),
|
|
@@ -713,6 +855,7 @@ export function createMcpExtension(options = {}) {
|
|
|
713
855
|
warnedUnreachable = false;
|
|
714
856
|
waitedForStartup = false;
|
|
715
857
|
sessionCwd = ctx.cwd;
|
|
858
|
+
modelRegistry = ctx.modelRegistry;
|
|
716
859
|
const current = ++generation;
|
|
717
860
|
sessionActive = true;
|
|
718
861
|
configuredEntries = loaded.servers;
|
|
@@ -720,6 +863,9 @@ export function createMcpExtension(options = {}) {
|
|
|
720
863
|
overridden = registered.overridden;
|
|
721
864
|
servers = [...loaded.servers.map((entry) => ({ entry })), ...registered.servers];
|
|
722
865
|
emitChange();
|
|
866
|
+
// Codemode or tool_search is activated from the config: the first prompt does not wait for
|
|
867
|
+
// servers whose tools are not declared to the model, and scripts or searches wait for them.
|
|
868
|
+
ensureDiscoveryActive(ctx);
|
|
723
869
|
const enabled = servers.filter(isEnabled);
|
|
724
870
|
if (enabled.length === 0) {
|
|
725
871
|
reportProblems(ctx);
|
|
@@ -727,19 +873,12 @@ export function createMcpExtension(options = {}) {
|
|
|
727
873
|
}
|
|
728
874
|
// The MCP client loads only now, so sessions without servers never pay for it. Waiting one
|
|
729
875
|
// event loop turn lets the first render happen before loading and connecting.
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
if (current !== generation)
|
|
737
|
-
return;
|
|
738
|
-
await Promise.allSettled(started.map((connection) => connection.getClient()));
|
|
739
|
-
if (current !== generation)
|
|
740
|
-
return;
|
|
741
|
-
ensureDiscoveryActive(ctx);
|
|
742
|
-
reportProblems(ctx);
|
|
876
|
+
const runtime = new Promise((resolve) => setImmediate(resolve)).then(() => loadMcpRuntime());
|
|
877
|
+
const isCurrent = () => current === generation;
|
|
878
|
+
pending = Promise.all(enabled.map((server) => startConnection(server, isCurrent, runtime)))
|
|
879
|
+
.then(() => {
|
|
880
|
+
if (isCurrent())
|
|
881
|
+
reportProblems(ctx);
|
|
743
882
|
})
|
|
744
883
|
.catch((error) => {
|
|
745
884
|
// The session may have been disposed meanwhile, which makes ctx stale.
|
|
@@ -749,16 +888,19 @@ export function createMcpExtension(options = {}) {
|
|
|
749
888
|
catch { }
|
|
750
889
|
});
|
|
751
890
|
});
|
|
752
|
-
// The first prompt waits for
|
|
753
|
-
// indefinitely: a slow or hanging server must not hold up the
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
if (
|
|
891
|
+
// The first prompt waits for servers whose tools are declared to the model, so they are declared
|
|
892
|
+
// in its first request, but not indefinitely: a slow or hanging server must not hold up the
|
|
893
|
+
// prompt. Other servers are waited for when a script or search needs them (below).
|
|
894
|
+
const waitForDirectServers = async (ctx) => {
|
|
895
|
+
if (waitedForStartup)
|
|
757
896
|
return;
|
|
758
897
|
waitedForStartup = true;
|
|
898
|
+
const ready = servers.flatMap((server) => isEnabled(server) && hasDirectTools(server.entry) && server.ready ? [server.ready] : []);
|
|
899
|
+
if (ready.length === 0)
|
|
900
|
+
return;
|
|
759
901
|
let timer;
|
|
760
902
|
const finished = await Promise.race([
|
|
761
|
-
|
|
903
|
+
Promise.all(ready).then(() => true),
|
|
762
904
|
new Promise((resolve) => {
|
|
763
905
|
timer = setTimeout(() => resolve(false), startupWaitMs);
|
|
764
906
|
}),
|
|
@@ -767,6 +909,39 @@ export function createMcpExtension(options = {}) {
|
|
|
767
909
|
if (!finished) {
|
|
768
910
|
ctx.ui.notify("MCP servers are still connecting; their tools become available once connected.", "info");
|
|
769
911
|
}
|
|
912
|
+
};
|
|
913
|
+
// Every prompt lists the servers in the `mcp_servers` section as they are when it starts. Pi
|
|
914
|
+
// appends the section to the conversation when it changed, for example after a server connected.
|
|
915
|
+
pi.on("before_agent_start", async (event, ctx) => {
|
|
916
|
+
await waitForDirectServers(ctx);
|
|
917
|
+
const { sections } = event.systemPromptOptions;
|
|
918
|
+
const section = renderServersSection(servers);
|
|
919
|
+
if (section)
|
|
920
|
+
sections[MCP_SERVERS_SECTION] = section;
|
|
921
|
+
else
|
|
922
|
+
delete sections[MCP_SERVERS_SECTION];
|
|
923
|
+
});
|
|
924
|
+
// A codemode script waits for the servers it names, or for every server when it searches or
|
|
925
|
+
// enumerates tools, so their tools are registered before the script runs. tool_search and the
|
|
926
|
+
// resource tools reach every server, so they wait for all of them.
|
|
927
|
+
pi.on("tool_call", async (event, ctx) => {
|
|
928
|
+
const tool = pi.getAllTools().find((candidate) => candidate.name === event.toolName);
|
|
929
|
+
if (!tool)
|
|
930
|
+
return;
|
|
931
|
+
const pendingServers = servers.filter((server) => isEnabled(server) && server.connection?.state !== "connected" && server.ready);
|
|
932
|
+
if (pendingServers.length === 0)
|
|
933
|
+
return;
|
|
934
|
+
let waiting = [];
|
|
935
|
+
const orchestrator = discoverOrchestrators([tool]);
|
|
936
|
+
if (orchestrator.codemode) {
|
|
937
|
+
const { code } = event.input;
|
|
938
|
+
const source = typeof code === "string" ? code : "";
|
|
939
|
+
waiting = pendingServers.filter((server) => scriptNeedsServer(source, server.entry.name));
|
|
940
|
+
}
|
|
941
|
+
else if (orchestrator.toolSearch || RESOURCE_TOOL_NAMES.has(tool.name)) {
|
|
942
|
+
waiting = pendingServers;
|
|
943
|
+
}
|
|
944
|
+
await waitForServers(waiting, ctx.signal);
|
|
770
945
|
});
|
|
771
946
|
// Pick up sign-ins done outside the session, such as `pi mcp login` run by the agent.
|
|
772
947
|
pi.on("turn_start", async (_event, ctx) => {
|
|
@@ -790,17 +965,17 @@ export function createMcpExtension(options = {}) {
|
|
|
790
965
|
const added = registered.servers.filter((server) => !findServer(server.entry.name));
|
|
791
966
|
servers.push(...added);
|
|
792
967
|
emitChange();
|
|
968
|
+
ensureDiscoveryActive(ctx);
|
|
793
969
|
await Promise.all(removed.map((server) => server.connection?.close()));
|
|
794
970
|
const connecting = added.filter(isEnabled);
|
|
795
971
|
if (current !== generation || connecting.length === 0)
|
|
796
972
|
return;
|
|
797
973
|
try {
|
|
798
|
-
|
|
974
|
+
await Promise.all(connecting.map((server) => startConnection(server, () => current === generation)));
|
|
799
975
|
if (current !== generation) {
|
|
800
|
-
await Promise.all(
|
|
976
|
+
await Promise.all(connecting.map((server) => server.connection?.close()));
|
|
801
977
|
return;
|
|
802
978
|
}
|
|
803
|
-
await Promise.allSettled(started.map((connection) => connection.getClient()));
|
|
804
979
|
}
|
|
805
980
|
catch (error) {
|
|
806
981
|
ctx.ui.notify(`MCP failed to load: ${errorMessage(error)}`, "error");
|
|
@@ -808,7 +983,6 @@ export function createMcpExtension(options = {}) {
|
|
|
808
983
|
}
|
|
809
984
|
if (current !== generation)
|
|
810
985
|
return;
|
|
811
|
-
ensureDiscoveryActive(ctx);
|
|
812
986
|
reportProblems(ctx, connecting);
|
|
813
987
|
});
|
|
814
988
|
pi.on("session_shutdown", async () => {
|