@astralyn/pi 1.0.4 → 1.1.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 +53 -0
- package/dist/bundle/chunks/{anthropic-messages-YIOJIMVL.js → anthropic-messages-3K3DWVY6.js} +1 -1
- package/dist/bundle/chunks/anthropic.js +1 -1
- package/dist/bundle/chunks/{azure-openai-responses-LDW4FGAQ.js → azure-openai-responses-CH74HGP4.js} +1 -1
- package/dist/bundle/chunks/bedrock-converse-stream.js +2 -2
- package/dist/bundle/chunks/{chunk-UCXU7KLO.js → chunk-3MMB5I7J.js} +1 -1
- package/dist/bundle/chunks/{chunk-GIG5IHES.js → chunk-5KJH3GGH.js} +1 -1
- package/dist/bundle/chunks/chunk-6VYRLG5F.js +2 -0
- package/dist/bundle/chunks/{chunk-73WG7F7N.js → chunk-C2ARIVS3.js} +1 -1
- package/dist/bundle/chunks/{chunk-23OTKHCH.js → chunk-D3XW5X3Z.js} +490 -260
- package/dist/bundle/chunks/{chunk-IFELM7MW.js → chunk-EJEOEBSJ.js} +1 -1
- package/dist/bundle/chunks/chunk-H35KWBT5.js +11 -0
- package/dist/bundle/chunks/chunk-KAC2YPTW.js +2 -0
- package/dist/bundle/chunks/chunk-MAC4N3BW.js +2 -0
- package/dist/bundle/chunks/chunk-QLU3LESZ.js +2 -0
- package/dist/bundle/chunks/{chunk-A6ALEEY5.js → chunk-TEAAYBTS.js} +1 -1
- package/dist/bundle/chunks/cloudflare-workers-ai-system-one-XO45ZT3V.js +2 -0
- package/dist/bundle/chunks/codemode-worker.js +101 -5
- package/dist/bundle/chunks/github-copilot.js +1 -1
- package/dist/bundle/chunks/{google-generative-ai-S5A5IBU4.js → google-generative-ai-VVO64ZRQ.js} +1 -1
- package/dist/bundle/chunks/{google-vertex-UBRQFDB4.js → google-vertex-LKS5NUHA.js} +1 -1
- package/dist/bundle/chunks/image-resize-worker.js +1 -1
- package/dist/bundle/chunks/{llama-cpp-classify-R7DQLTQN.js → llama-cpp-classify-H3IZDR5O.js} +2 -2
- package/dist/bundle/chunks/{mistral-conversations-A2N5FSOV.js → mistral-conversations-NJUOG4ET.js} +2 -2
- package/dist/bundle/chunks/openai-chatgpt.js +1 -1
- package/dist/bundle/chunks/{openai-codex-responses-Q6JHCWLE.js → openai-codex-responses-TZWBTTYM.js} +2 -2
- package/dist/bundle/chunks/openai-codex.js +1 -1
- package/dist/bundle/chunks/{openai-completions-H4VMO7AU.js → openai-completions-7HTTU6FH.js} +1 -1
- package/dist/bundle/chunks/openai-decisions-776H4VDZ.js +5 -0
- package/dist/bundle/chunks/{openai-responses-G4PGNM2H.js → openai-responses-7A6BAQ5X.js} +1 -1
- package/dist/bundle/chunks/{openrouter-images-YP3YVB54.js → openrouter-images-TDLJV5N4.js} +1 -1
- package/dist/bundle/chunks/{pi-messages-HZZ7GEEW.js → pi-messages-ZXNERWJG.js} +1 -1
- package/dist/bundle/chunks/typesafe-system-one-2DQLG4R2.js +2 -0
- package/dist/bundle/chunks/{virtual-modules-IJTAY26N.js → virtual-modules-2NHGQRS6.js} +1 -1
- 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.d.ts +2 -1
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +24 -5
- package/dist/cli/args.js.map +1 -1
- package/dist/core/agent-session.d.ts +38 -10
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +190 -186
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/bash-executor.d.ts.map +1 -1
- package/dist/core/bash-executor.js +40 -45
- package/dist/core/bash-executor.js.map +1 -1
- package/dist/core/context-snapshot.d.ts +4 -1
- package/dist/core/context-snapshot.d.ts.map +1 -1
- package/dist/core/context-snapshot.js +45 -0
- package/dist/core/context-snapshot.js.map +1 -1
- package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
- package/dist/core/export-html/tool-renderer.js +2 -0
- package/dist/core/export-html/tool-renderer.js.map +1 -1
- package/dist/core/extensions/types.d.ts +13 -0
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/mcp-servers.d.ts +8 -0
- package/dist/core/mcp-servers.d.ts.map +1 -1
- package/dist/core/mcp-servers.js +30 -7
- package/dist/core/mcp-servers.js.map +1 -1
- package/dist/core/model-runtime.d.ts.map +1 -1
- package/dist/core/model-runtime.js +2 -1
- package/dist/core/model-runtime.js.map +1 -1
- package/dist/core/nested-tool-calls.d.ts +1 -0
- package/dist/core/nested-tool-calls.d.ts.map +1 -1
- package/dist/core/nested-tool-calls.js +1 -0
- package/dist/core/nested-tool-calls.js.map +1 -1
- package/dist/core/resource-loader.d.ts +3 -0
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +3 -3
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/sdk.d.ts +13 -4
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +19 -6
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/settings-manager.d.ts +13 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +37 -13
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/skills.d.ts +4 -1
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js +6 -1
- package/dist/core/skills.js.map +1 -1
- package/dist/core/system-prompt.d.ts +6 -0
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +9 -4
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tasks/session.d.ts +9 -0
- package/dist/core/tasks/session.d.ts.map +1 -1
- package/dist/core/tasks/session.js +21 -0
- package/dist/core/tasks/session.js.map +1 -1
- package/dist/core/tools/read.d.ts +13 -0
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +18 -1
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/renderers/bash.d.ts.map +1 -1
- package/dist/core/tools/renderers/bash.js +8 -3
- package/dist/core/tools/renderers/bash.js.map +1 -1
- package/dist/core/tools/renderers/edit.js +1 -1
- package/dist/core/tools/renderers/edit.js.map +1 -1
- package/dist/extensions/codemode/execute.d.ts.map +1 -1
- package/dist/extensions/codemode/execute.js +65 -8
- package/dist/extensions/codemode/execute.js.map +1 -1
- package/dist/extensions/codemode/index.d.ts.map +1 -1
- package/dist/extensions/codemode/index.js +1 -0
- package/dist/extensions/codemode/index.js.map +1 -1
- package/dist/extensions/codemode/tool.d.ts +9 -2
- package/dist/extensions/codemode/tool.d.ts.map +1 -1
- package/dist/extensions/codemode/tool.js +14 -6
- package/dist/extensions/codemode/tool.js.map +1 -1
- package/dist/extensions/index.js +2 -2
- package/dist/extensions/index.js.map +1 -1
- package/dist/extensions/llama/provider.d.ts.map +1 -1
- package/dist/extensions/llama/provider.js +34 -11
- package/dist/extensions/llama/provider.js.map +1 -1
- package/dist/extensions/mcp/cli.js +17 -23
- package/dist/extensions/mcp/cli.js.map +1 -1
- package/dist/extensions/mcp/index.d.ts.map +1 -1
- package/dist/extensions/mcp/index.js +165 -64
- package/dist/extensions/mcp/index.js.map +1 -1
- package/dist/extensions/mcp/oauth.d.ts +5 -3
- package/dist/extensions/mcp/oauth.d.ts.map +1 -1
- package/dist/extensions/mcp/oauth.js +36 -10
- package/dist/extensions/mcp/oauth.js.map +1 -1
- package/dist/extensions/mcp/resources.d.ts +3 -4
- package/dist/extensions/mcp/resources.d.ts.map +1 -1
- package/dist/extensions/mcp/resources.js +3 -4
- package/dist/extensions/mcp/resources.js.map +1 -1
- package/dist/extensions/mcp/runtime.d.ts +4 -1
- package/dist/extensions/mcp/runtime.d.ts.map +1 -1
- package/dist/extensions/mcp/runtime.js +22 -5
- package/dist/extensions/mcp/runtime.js.map +1 -1
- package/dist/extensions/mcp/tools.d.ts +2 -1
- package/dist/extensions/mcp/tools.d.ts.map +1 -1
- package/dist/extensions/mcp/tools.js +2 -1
- package/dist/extensions/mcp/tools.js.map +1 -1
- package/dist/extensions/mcp/ui.d.ts +3 -3
- package/dist/extensions/mcp/ui.d.ts.map +1 -1
- package/dist/extensions/mcp/ui.js +10 -2
- package/dist/extensions/mcp/ui.js.map +1 -1
- package/dist/extensions/search/code-search.d.ts +29 -0
- package/dist/extensions/search/code-search.d.ts.map +1 -0
- package/dist/extensions/search/code-search.js +120 -0
- package/dist/extensions/search/code-search.js.map +1 -0
- package/dist/extensions/search/command.d.ts +5 -0
- package/dist/extensions/search/command.d.ts.map +1 -0
- package/dist/extensions/search/command.js +69 -0
- package/dist/extensions/search/command.js.map +1 -0
- package/dist/extensions/search/credential.d.ts +25 -0
- package/dist/extensions/search/credential.d.ts.map +1 -0
- package/dist/extensions/search/credential.js +117 -0
- package/dist/extensions/search/credential.js.map +1 -0
- package/dist/extensions/search/devin.d.ts +34 -0
- package/dist/extensions/search/devin.d.ts.map +1 -0
- package/dist/extensions/search/devin.js +210 -0
- package/dist/extensions/search/devin.js.map +1 -0
- package/dist/extensions/search/index.d.ts +5 -0
- package/dist/extensions/search/index.d.ts.map +1 -0
- package/dist/extensions/search/index.js +110 -0
- package/dist/extensions/search/index.js.map +1 -0
- package/dist/extensions/search/panel.d.ts +53 -0
- package/dist/extensions/search/panel.d.ts.map +1 -0
- package/dist/extensions/search/panel.js +157 -0
- package/dist/extensions/search/panel.js.map +1 -0
- package/dist/extensions/search/prompt.d.ts +14 -0
- package/dist/extensions/search/prompt.d.ts.map +1 -0
- package/dist/extensions/search/prompt.js +221 -0
- package/dist/extensions/search/prompt.js.map +1 -0
- package/dist/extensions/search/render.d.ts +28 -0
- package/dist/extensions/search/render.d.ts.map +1 -0
- package/dist/extensions/search/render.js +86 -0
- package/dist/extensions/search/render.js.map +1 -0
- package/dist/extensions/search/workspace.d.ts +38 -0
- package/dist/extensions/search/workspace.d.ts.map +1 -0
- package/dist/extensions/search/workspace.js +245 -0
- package/dist/extensions/search/workspace.js.map +1 -0
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +1 -0
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/bash-execution.d.ts +5 -1
- package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/bash-execution.js +14 -14
- package/dist/modes/interactive/components/bash-execution.js.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.d.ts +2 -1
- package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.js +5 -2
- package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.d.ts +2 -1
- package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.js +5 -2
- package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/custom-entry.d.ts +3 -1
- package/dist/modes/interactive/components/custom-entry.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-entry.js +7 -2
- package/dist/modes/interactive/components/custom-entry.js.map +1 -1
- package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-message.js +1 -0
- package/dist/modes/interactive/components/custom-message.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +1 -1
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/skill-invocation-message.d.ts +2 -1
- package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/skill-invocation-message.js +5 -2
- package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +2 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +52 -59
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/program-status-reporter.d.ts +34 -0
- package/dist/modes/interactive/program-status-reporter.d.ts.map +1 -0
- package/dist/modes/interactive/program-status-reporter.js +107 -0
- package/dist/modes/interactive/program-status-reporter.js.map +1 -0
- package/dist/modes/interactive/tasks/host-hooks.d.ts +14 -0
- package/dist/modes/interactive/tasks/host-hooks.d.ts.map +1 -0
- package/dist/modes/interactive/tasks/host-hooks.js +31 -0
- package/dist/modes/interactive/tasks/host-hooks.js.map +1 -0
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +1 -0
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/modes/interactive/tool-view/tool-execution.d.ts +5 -0
- package/dist/modes/interactive/tool-view/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/tool-view/tool-execution.js +7 -0
- package/dist/modes/interactive/tool-view/tool-execution.js.map +1 -1
- package/dist/package-manager-cli.d.ts.map +1 -1
- package/dist/package-manager-cli.js +24 -0
- package/dist/package-manager-cli.js.map +1 -1
- package/dist/utils/ansi.d.ts +8 -0
- package/dist/utils/ansi.d.ts.map +1 -1
- package/dist/utils/ansi.js +30 -11
- package/dist/utils/ansi.js.map +1 -1
- package/dist/utils/clipboard.d.ts.map +1 -1
- package/dist/utils/clipboard.js +12 -11
- package/dist/utils/clipboard.js.map +1 -1
- package/dist/utils/image-resize-core.d.ts +12 -0
- package/dist/utils/image-resize-core.d.ts.map +1 -1
- package/dist/utils/image-resize-core.js +5 -0
- package/dist/utils/image-resize-core.js.map +1 -1
- package/dist/utils/image-resize-worker.js +3 -2
- package/dist/utils/image-resize-worker.js.map +1 -1
- package/dist/utils/image-resize.d.ts.map +1 -1
- package/dist/utils/image-resize.js +9 -10
- package/dist/utils/image-resize.js.map +1 -1
- package/dist/utils/syntax-highlight.d.ts.map +1 -1
- package/dist/utils/syntax-highlight.js +6 -1
- package/dist/utils/syntax-highlight.js.map +1 -1
- package/docs/bundled/README.md +1 -1
- package/docs/bundled/extensions/provider.md +1 -1
- package/docs/bundled/extensions/question.md +1 -1
- package/docs/bundled/extensions/search.md +50 -0
- package/docs/bundled/extensions/statusline.md +15 -41
- package/docs/codemode.md +26 -5
- package/docs/docs.json +0 -4
- package/docs/environment-variables.md +1 -0
- package/docs/extensions.md +6 -2
- package/docs/json.md +2 -2
- package/docs/llama-cpp.md +8 -1
- package/docs/mcp.md +3 -1
- package/docs/models.md +4 -1
- package/docs/providers.md +17 -0
- package/docs/rpc.md +6 -3
- package/docs/session-format.md +1 -0
- package/docs/settings.md +4 -4
- package/docs/terminal-setup.md +14 -0
- package/docs/usage.md +19 -5
- 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/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/npm-shrinkwrap.json +54 -54
- package/package.json +13 -11
- package/dist/bundle/chunks/chunk-57XI7YJH.js +0 -2
- package/dist/bundle/chunks/chunk-JI4WGISU.js +0 -2
- package/dist/bundle/chunks/chunk-TCQ4HHQD.js +0 -2
- package/dist/bundle/chunks/chunk-TXJO4AJ7.js +0 -11
- package/dist/bundle/chunks/cloudflare-workers-ai-system-one-OWU5SM6J.js +0 -2
- package/dist/bundle/chunks/typesafe-system-one-KYKKNU3E.js +0 -2
- package/dist/extensions/web-search/auth.d.ts +0 -12
- package/dist/extensions/web-search/auth.d.ts.map +0 -1
- package/dist/extensions/web-search/auth.js +0 -90
- package/dist/extensions/web-search/auth.js.map +0 -1
- package/dist/extensions/web-search/constants.d.ts +0 -13
- package/dist/extensions/web-search/constants.d.ts.map +0 -1
- package/dist/extensions/web-search/constants.js +0 -26
- package/dist/extensions/web-search/constants.js.map +0 -1
- package/dist/extensions/web-search/execute.d.ts +0 -9
- package/dist/extensions/web-search/execute.d.ts.map +0 -1
- package/dist/extensions/web-search/execute.js +0 -96
- package/dist/extensions/web-search/execute.js.map +0 -1
- package/dist/extensions/web-search/format.d.ts +0 -21
- package/dist/extensions/web-search/format.d.ts.map +0 -1
- package/dist/extensions/web-search/format.js +0 -117
- package/dist/extensions/web-search/format.js.map +0 -1
- package/dist/extensions/web-search/index.d.ts +0 -6
- package/dist/extensions/web-search/index.d.ts.map +0 -1
- package/dist/extensions/web-search/index.js +0 -50
- package/dist/extensions/web-search/index.js.map +0 -1
- package/dist/extensions/web-search/providers/deepseek.d.ts +0 -13
- package/dist/extensions/web-search/providers/deepseek.d.ts.map +0 -1
- package/dist/extensions/web-search/providers/deepseek.js +0 -110
- package/dist/extensions/web-search/providers/deepseek.js.map +0 -1
- package/dist/extensions/web-search/providers/http.d.ts +0 -4
- package/dist/extensions/web-search/providers/http.d.ts.map +0 -1
- package/dist/extensions/web-search/providers/http.js +0 -42
- package/dist/extensions/web-search/providers/http.js.map +0 -1
- package/dist/extensions/web-search/providers/minimax.d.ts +0 -12
- package/dist/extensions/web-search/providers/minimax.d.ts.map +0 -1
- package/dist/extensions/web-search/providers/minimax.js +0 -61
- package/dist/extensions/web-search/providers/minimax.js.map +0 -1
- package/dist/extensions/web-search/render.d.ts +0 -15
- package/dist/extensions/web-search/render.d.ts.map +0 -1
- package/dist/extensions/web-search/render.js +0 -142
- package/dist/extensions/web-search/render.js.map +0 -1
- package/dist/extensions/web-search/results.d.ts +0 -35
- package/dist/extensions/web-search/results.d.ts.map +0 -1
- package/dist/extensions/web-search/results.js +0 -167
- package/dist/extensions/web-search/results.js.map +0 -1
- package/dist/extensions/web-search/schema.d.ts +0 -10
- package/dist/extensions/web-search/schema.d.ts.map +0 -1
- package/dist/extensions/web-search/schema.js +0 -36
- package/dist/extensions/web-search/schema.js.map +0 -1
- package/dist/extensions/web-search/types.d.ts +0 -51
- package/dist/extensions/web-search/types.d.ts.map +0 -1
- package/dist/extensions/web-search/types.js +0 -5
- package/dist/extensions/web-search/types.js.map +0 -1
- package/docs/bundled/extensions/web-search.md +0 -46
|
@@ -197,8 +197,6 @@ export function createMcpExtension(options = {}) {
|
|
|
197
197
|
let projectConfig;
|
|
198
198
|
/** Registered servers that `mcp.json` overrides, shown in `/mcp`. */
|
|
199
199
|
let overridden = [];
|
|
200
|
-
/** Between session_start and session_shutdown. Registrations before that are read on session_start. */
|
|
201
|
-
let sessionActive = false;
|
|
202
200
|
let autoEnableCodemode = true;
|
|
203
201
|
/** Whether the "codemode tools unreachable" warning was shown since the session started. */
|
|
204
202
|
let warnedUnreachable = false;
|
|
@@ -206,8 +204,6 @@ export function createMcpExtension(options = {}) {
|
|
|
206
204
|
/** Whether a prompt already waited for the startup connections since the session started. */
|
|
207
205
|
let waitedForStartup = false;
|
|
208
206
|
const startupWaitMs = options.startupWaitMs ?? DEFAULT_STARTUP_WAIT_MS;
|
|
209
|
-
/** Bumped on every session start and shutdown so a runtime load that resolves late is dropped. */
|
|
210
|
-
let generation = 0;
|
|
211
207
|
/** Working directory of the session, for stdio servers. */
|
|
212
208
|
let sessionCwd = process.cwd();
|
|
213
209
|
let credentials = options.credentials;
|
|
@@ -219,6 +215,23 @@ export function createMcpExtension(options = {}) {
|
|
|
219
215
|
((entry, patch) => updateMcpServerConfig(entry.override ?? entry.source, entry.name, patch, {
|
|
220
216
|
override: entry.override !== undefined,
|
|
221
217
|
}));
|
|
218
|
+
/**
|
|
219
|
+
* Lifetime of the current session: aborted on session_shutdown, and before the first session_start
|
|
220
|
+
* (registrations before that are read on session_start). Work captures `session.signal` when it
|
|
221
|
+
* starts and drops late results once it aborted, for example a runtime load that resolves after
|
|
222
|
+
* shutdown. Work that outlives the command that started it also stops on the signal and is
|
|
223
|
+
* registered with `track`, so shutdown can wait for its cleanup.
|
|
224
|
+
*/
|
|
225
|
+
let session = new AbortController();
|
|
226
|
+
session.abort();
|
|
227
|
+
/** Work registered with `track`: manager actions opening or closing connections, and sign-ins. */
|
|
228
|
+
const backgroundActions = new Set();
|
|
229
|
+
const track = (work) => {
|
|
230
|
+
const task = work.then(() => undefined, () => undefined);
|
|
231
|
+
backgroundActions.add(task);
|
|
232
|
+
void task.finally(() => backgroundActions.delete(task));
|
|
233
|
+
return work;
|
|
234
|
+
};
|
|
222
235
|
const listeners = new Set();
|
|
223
236
|
const emitChange = () => {
|
|
224
237
|
for (const listener of listeners)
|
|
@@ -301,8 +314,22 @@ export function createMcpExtension(options = {}) {
|
|
|
301
314
|
exposure: getMcpToolExposure(entry.config, tool.name),
|
|
302
315
|
namespace,
|
|
303
316
|
timeoutMs: connection.timeoutMs,
|
|
304
|
-
getClient: async () =>
|
|
305
|
-
|
|
317
|
+
getClient: async () => {
|
|
318
|
+
// A prepared call can outlive this definition's connection while the readiness
|
|
319
|
+
// hook waits for a disable/re-enable. Resolve the replacement at execution time.
|
|
320
|
+
const current = findServer(server);
|
|
321
|
+
if (!current || !isEnabled(current))
|
|
322
|
+
throw new Error(`MCP server "${server}" is disabled.`);
|
|
323
|
+
const client = current.connection;
|
|
324
|
+
if (!client)
|
|
325
|
+
throw new Error(`MCP server "${server}" is still starting.`);
|
|
326
|
+
if (getMcpToolExposure(current.entry.config, tool.name) === "hidden" ||
|
|
327
|
+
(client.state === "connected" && !client.tools.some((offered) => offered.name === tool.name))) {
|
|
328
|
+
throw new Error(`MCP tool "${server}/${tool.name}" is no longer available.`);
|
|
329
|
+
}
|
|
330
|
+
return client;
|
|
331
|
+
},
|
|
332
|
+
readableResources: () => resourceServers().some((current) => current.name === server),
|
|
306
333
|
});
|
|
307
334
|
definitions.set(definition.name, definition);
|
|
308
335
|
pi.registerTool(definition);
|
|
@@ -434,8 +461,10 @@ export function createMcpExtension(options = {}) {
|
|
|
434
461
|
ensureDiscoveryActive(ctx);
|
|
435
462
|
};
|
|
436
463
|
/** Create the server's connection, loading the MCP runtime on first use. */
|
|
437
|
-
const createConnection = async (server) => {
|
|
464
|
+
const createConnection = async (server, isCurrent) => {
|
|
438
465
|
const runtime = await loadMcpRuntime();
|
|
466
|
+
if (!isCurrent())
|
|
467
|
+
return undefined;
|
|
439
468
|
const connection = new runtime.McpServerConnection({
|
|
440
469
|
entry: server.entry,
|
|
441
470
|
cwd: sessionCwd,
|
|
@@ -443,8 +472,16 @@ export function createMcpExtension(options = {}) {
|
|
|
443
472
|
credentials: getCredentials(runtime),
|
|
444
473
|
providerToken: async (provider) => modelRegistry?.getApiKeyForProvider(provider),
|
|
445
474
|
log: getServerLog(runtime),
|
|
446
|
-
onTools:
|
|
447
|
-
|
|
475
|
+
onTools: (connection) => {
|
|
476
|
+
if (isCurrent())
|
|
477
|
+
registerTools(connection);
|
|
478
|
+
},
|
|
479
|
+
onChange: (connection) => {
|
|
480
|
+
if (isCurrent())
|
|
481
|
+
onConnectionChange(connection);
|
|
482
|
+
else
|
|
483
|
+
tokensAtSignIn.delete(connection);
|
|
484
|
+
},
|
|
448
485
|
});
|
|
449
486
|
server.connection = connection;
|
|
450
487
|
emitChange();
|
|
@@ -452,37 +489,48 @@ export function createMcpExtension(options = {}) {
|
|
|
452
489
|
};
|
|
453
490
|
/**
|
|
454
491
|
* Connect the server in the background. `server.ready` settles when it connected or failed;
|
|
455
|
-
* failures show in its state. It starts after `after
|
|
492
|
+
* failures show in its state. It starts after `after`, unless disabled, replaced, or shut down
|
|
456
493
|
* meanwhile. The returned promise rejects when the MCP runtime cannot be loaded.
|
|
457
494
|
*/
|
|
458
|
-
const startConnection = (server,
|
|
495
|
+
const startConnection = (server, after) => {
|
|
496
|
+
const { signal } = session;
|
|
497
|
+
const attempt = Symbol();
|
|
498
|
+
server.attempt = attempt;
|
|
499
|
+
const isCurrent = () => !signal.aborted && server.attempt === attempt && isEnabled(server) && servers.includes(server);
|
|
459
500
|
const ready = (async () => {
|
|
460
501
|
await after;
|
|
461
502
|
if (!isCurrent())
|
|
462
503
|
return;
|
|
463
|
-
const connection = await createConnection(server);
|
|
464
|
-
if (!isCurrent())
|
|
504
|
+
const connection = await createConnection(server, isCurrent);
|
|
505
|
+
if (!connection || !isCurrent())
|
|
465
506
|
return;
|
|
466
507
|
await connection.getClient().catch(() => undefined);
|
|
467
508
|
})();
|
|
468
509
|
server.ready = ready.catch(() => undefined);
|
|
469
510
|
return ready;
|
|
470
511
|
};
|
|
471
|
-
/** Wait for
|
|
512
|
+
/** Wait for the latest connection attempts, including ones queued while waiting, or an abort. */
|
|
472
513
|
const waitForServers = async (waiting, signal) => {
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
Promise.
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
514
|
+
for (;;) {
|
|
515
|
+
const ready = waiting.flatMap((server) => isEnabled(server) && servers.includes(server) && server.ready ? [{ server, ready: server.ready }] : []);
|
|
516
|
+
if (ready.length === 0 || signal?.aborted)
|
|
517
|
+
return;
|
|
518
|
+
let onAbort;
|
|
519
|
+
await Promise.race([
|
|
520
|
+
Promise.all(ready.map((attempt) => attempt.ready)),
|
|
521
|
+
new Promise((resolve) => {
|
|
522
|
+
onAbort = () => resolve();
|
|
523
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
524
|
+
}),
|
|
525
|
+
]);
|
|
526
|
+
if (onAbort)
|
|
527
|
+
signal?.removeEventListener("abort", onAbort);
|
|
528
|
+
if (signal?.aborted ||
|
|
529
|
+
ready.every((attempt) => !isEnabled(attempt.server) ||
|
|
530
|
+
!servers.includes(attempt.server) ||
|
|
531
|
+
attempt.ready === attempt.server.ready))
|
|
532
|
+
return;
|
|
533
|
+
}
|
|
486
534
|
};
|
|
487
535
|
/**
|
|
488
536
|
* One message for everything that needs the user after startup, or only for `only`, servers
|
|
@@ -517,20 +565,23 @@ export function createMcpExtension(options = {}) {
|
|
|
517
565
|
server.entry = { ...entry, config: { ...entry.config, ...patch } };
|
|
518
566
|
return undefined;
|
|
519
567
|
};
|
|
520
|
-
|
|
568
|
+
/** Sign in, then reconnect. Returns an error message on failure. `cancel` or the session's end stops the sign-in. */
|
|
569
|
+
const signIn = async (server, prompt, cancel) => {
|
|
521
570
|
const connection = server.connection;
|
|
522
571
|
const url = connection?.oauthUrl;
|
|
523
572
|
if (!connection || !url)
|
|
524
573
|
return `MCP server "${server.entry.name}" does not use OAuth.`;
|
|
525
574
|
const runtime = await loadMcpRuntime();
|
|
575
|
+
const signal = cancel ? AbortSignal.any([session.signal, cancel]) : session.signal;
|
|
526
576
|
try {
|
|
527
|
-
await runtime.signInMcpServer({
|
|
577
|
+
await track(runtime.signInMcpServer({
|
|
528
578
|
serverUrl: url,
|
|
529
579
|
store: getCredentials(runtime).forServer(server.entry.name, url),
|
|
530
580
|
settings: connection.oauthSettings(),
|
|
531
581
|
challenge: connection.challenge,
|
|
532
582
|
prompt,
|
|
533
|
-
|
|
583
|
+
signal,
|
|
584
|
+
}));
|
|
534
585
|
}
|
|
535
586
|
catch (error) {
|
|
536
587
|
if (error instanceof runtime.McpSignInCancelledError)
|
|
@@ -560,8 +611,14 @@ export function createMcpExtension(options = {}) {
|
|
|
560
611
|
const connection = server.connection;
|
|
561
612
|
if (!connection)
|
|
562
613
|
return `MCP server "${server.entry.name}" is disabled.`;
|
|
563
|
-
|
|
614
|
+
const previous = server.ready;
|
|
615
|
+
const ready = (async () => {
|
|
616
|
+
await previous;
|
|
564
617
|
await connection.reconnect();
|
|
618
|
+
})();
|
|
619
|
+
server.ready = ready.catch(() => undefined);
|
|
620
|
+
try {
|
|
621
|
+
await ready;
|
|
565
622
|
return undefined;
|
|
566
623
|
}
|
|
567
624
|
catch (error) {
|
|
@@ -575,13 +632,26 @@ export function createMcpExtension(options = {}) {
|
|
|
575
632
|
return failed;
|
|
576
633
|
if (!enabled) {
|
|
577
634
|
const connection = server.connection;
|
|
635
|
+
server.attempt = undefined;
|
|
578
636
|
server.connection = undefined;
|
|
637
|
+
if (connection) {
|
|
638
|
+
// A reconnect may already have detached its old client while awaiting transport
|
|
639
|
+
// shutdown. Closing the connection alone does not wait for that reconnect.
|
|
640
|
+
server.closing = Promise.all([connection.close(), server.ready]).then(() => undefined);
|
|
641
|
+
}
|
|
642
|
+
const closing = server.closing;
|
|
579
643
|
hideTools(server.entry.name);
|
|
580
644
|
emitChange();
|
|
581
|
-
|
|
645
|
+
try {
|
|
646
|
+
await closing;
|
|
647
|
+
}
|
|
648
|
+
finally {
|
|
649
|
+
if (server.closing === closing)
|
|
650
|
+
server.closing = undefined;
|
|
651
|
+
}
|
|
582
652
|
return undefined;
|
|
583
653
|
}
|
|
584
|
-
await startConnection(server,
|
|
654
|
+
await startConnection(server, server.closing);
|
|
585
655
|
return undefined;
|
|
586
656
|
};
|
|
587
657
|
const setExposure = (server, exposure) => {
|
|
@@ -729,11 +799,13 @@ export function createMcpExtension(options = {}) {
|
|
|
729
799
|
return undefined;
|
|
730
800
|
return setExposure(server, choice);
|
|
731
801
|
};
|
|
732
|
-
/** Sign in with the manager view's sign-in screen, which shows the URL with a copy key. */
|
|
802
|
+
/** Sign in with the manager view's sign-in screen, which shows the URL with a copy key and cancels with Esc. */
|
|
733
803
|
const signInWithUi = (ui, server) => {
|
|
734
804
|
const title = `Sign in to ${server.entry.name}`;
|
|
805
|
+
const cancel = new AbortController();
|
|
806
|
+
const status = (message) => ui.status(title, message, () => cancel.abort());
|
|
735
807
|
let authorizationUrl = "";
|
|
736
|
-
|
|
808
|
+
status("Contacting the authorization server…");
|
|
737
809
|
return signIn(server, {
|
|
738
810
|
showAuthorizationUrl: (url) => {
|
|
739
811
|
authorizationUrl = url.href;
|
|
@@ -741,22 +813,38 @@ export function createMcpExtension(options = {}) {
|
|
|
741
813
|
},
|
|
742
814
|
promptForRedirectUrl: async (signal) => {
|
|
743
815
|
const value = await ui.redirectUrl(title, authorizationUrl, signal);
|
|
744
|
-
|
|
816
|
+
status("Connecting…");
|
|
745
817
|
return value;
|
|
746
818
|
},
|
|
747
|
-
});
|
|
819
|
+
}, cancel.signal);
|
|
820
|
+
};
|
|
821
|
+
/** Keep the subscribed menu usable while a connection opens or closes. */
|
|
822
|
+
const runInBackground = (ctx, server, operation) => {
|
|
823
|
+
const ready = operation();
|
|
824
|
+
const attempt = server.attempt;
|
|
825
|
+
const { signal } = session;
|
|
826
|
+
const finish = (message) => {
|
|
827
|
+
if (signal.aborted || server.attempt !== attempt || !servers.includes(server))
|
|
828
|
+
return;
|
|
829
|
+
server.message = message;
|
|
830
|
+
ensureDiscoveryActive(ctx);
|
|
831
|
+
emitChange();
|
|
832
|
+
};
|
|
833
|
+
void track(ready.then(finish, (error) => finish(errorMessage(error))));
|
|
748
834
|
};
|
|
749
835
|
const runAction = async (ui, ctx, server, action) => {
|
|
750
|
-
const {
|
|
836
|
+
const { signal } = session;
|
|
751
837
|
let message;
|
|
752
838
|
switch (action) {
|
|
753
839
|
case "signin":
|
|
754
840
|
message = await signInWithUi(ui, server);
|
|
755
841
|
break;
|
|
756
842
|
case "reconnect":
|
|
757
|
-
//
|
|
758
|
-
|
|
759
|
-
|
|
843
|
+
// Connection state and error already report failures, including required sign-ins.
|
|
844
|
+
runInBackground(ctx, server, async () => {
|
|
845
|
+
await reconnect(server);
|
|
846
|
+
return undefined;
|
|
847
|
+
});
|
|
760
848
|
break;
|
|
761
849
|
case "signout":
|
|
762
850
|
await signOut(server);
|
|
@@ -772,11 +860,13 @@ export function createMcpExtension(options = {}) {
|
|
|
772
860
|
case "enable-project":
|
|
773
861
|
case "disable-project": {
|
|
774
862
|
const enable = action.startsWith("enable");
|
|
775
|
-
|
|
776
|
-
message = await setEnabled(server, enable, action.endsWith("-project"));
|
|
863
|
+
runInBackground(ctx, server, () => setEnabled(server, enable, action.endsWith("-project")));
|
|
777
864
|
break;
|
|
778
865
|
}
|
|
779
866
|
}
|
|
867
|
+
// The session ended meanwhile (for example during a sign-in), which made ctx stale.
|
|
868
|
+
if (signal.aborted)
|
|
869
|
+
return;
|
|
780
870
|
server.message = message;
|
|
781
871
|
ensureDiscoveryActive(ctx);
|
|
782
872
|
emitChange();
|
|
@@ -860,6 +950,7 @@ export function createMcpExtension(options = {}) {
|
|
|
860
950
|
ctx.ui.notify(`Signing in to MCP server "${name}" requires interactive mode.`, "error");
|
|
861
951
|
return;
|
|
862
952
|
}
|
|
953
|
+
const { signal } = session;
|
|
863
954
|
let failure;
|
|
864
955
|
if (ctx.mode === "tui") {
|
|
865
956
|
await showMcpManager(ctx, async (ui) => {
|
|
@@ -875,6 +966,9 @@ export function createMcpExtension(options = {}) {
|
|
|
875
966
|
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 }),
|
|
876
967
|
});
|
|
877
968
|
}
|
|
969
|
+
// The session ended meanwhile, which cancelled the sign-in and made ctx stale.
|
|
970
|
+
if (signal.aborted)
|
|
971
|
+
return;
|
|
878
972
|
if (failure) {
|
|
879
973
|
ctx.ui.notify(failure, failure === "Sign-in cancelled." ? "info" : "error");
|
|
880
974
|
return;
|
|
@@ -891,8 +985,8 @@ export function createMcpExtension(options = {}) {
|
|
|
891
985
|
waitedForStartup = false;
|
|
892
986
|
sessionCwd = ctx.cwd;
|
|
893
987
|
modelRegistry = ctx.modelRegistry;
|
|
894
|
-
|
|
895
|
-
|
|
988
|
+
session = new AbortController();
|
|
989
|
+
const { signal } = session;
|
|
896
990
|
configuredEntries = loaded.servers;
|
|
897
991
|
const registered = registeredServers();
|
|
898
992
|
overridden = registered.overridden;
|
|
@@ -909,10 +1003,9 @@ export function createMcpExtension(options = {}) {
|
|
|
909
1003
|
// The MCP client loads only now, so sessions without servers never pay for it. Waiting one
|
|
910
1004
|
// event loop turn lets the first render happen before loading and connecting.
|
|
911
1005
|
const runtime = new Promise((resolve) => setImmediate(resolve)).then(() => loadMcpRuntime());
|
|
912
|
-
|
|
913
|
-
pending = Promise.all(enabled.map((server) => startConnection(server, isCurrent, runtime)))
|
|
1006
|
+
pending = Promise.all(enabled.map((server) => startConnection(server, runtime)))
|
|
914
1007
|
.then(() => {
|
|
915
|
-
if (
|
|
1008
|
+
if (!signal.aborted)
|
|
916
1009
|
reportProblems(ctx);
|
|
917
1010
|
})
|
|
918
1011
|
.catch((error) => {
|
|
@@ -958,23 +1051,30 @@ export function createMcpExtension(options = {}) {
|
|
|
958
1051
|
});
|
|
959
1052
|
// A codemode script waits for the servers it names, or for every server when it searches or
|
|
960
1053
|
// enumerates tools, so their tools are registered before the script runs. tool_search and the
|
|
961
|
-
// resource tools reach every server, so they wait for all of them.
|
|
1054
|
+
// resource tools reach every server, so they wait for all of them. Direct MCP calls wait only
|
|
1055
|
+
// for their own server, including a reconnect still closing its old transport.
|
|
962
1056
|
pi.on("tool_call", async (event, ctx) => {
|
|
963
1057
|
const tool = pi.getAllTools().find((candidate) => candidate.name === event.toolName);
|
|
964
1058
|
if (!tool)
|
|
965
1059
|
return;
|
|
966
|
-
|
|
967
|
-
|
|
1060
|
+
// Readiness can be pending while the display state is still connected: reconnect first
|
|
1061
|
+
// closes the old transport, then opens a new one. Settled promises return immediately.
|
|
1062
|
+
const readyServers = servers.filter((server) => isEnabled(server) && server.ready);
|
|
1063
|
+
if (readyServers.length === 0)
|
|
968
1064
|
return;
|
|
969
1065
|
let waiting = [];
|
|
970
1066
|
const orchestrator = discoverOrchestrators([tool]);
|
|
971
1067
|
if (orchestrator.codemode) {
|
|
972
1068
|
const { code } = event.input;
|
|
973
1069
|
const source = typeof code === "string" ? code : "";
|
|
974
|
-
waiting =
|
|
1070
|
+
waiting = readyServers.filter((server) => scriptNeedsServer(source, server.entry.name));
|
|
975
1071
|
}
|
|
976
1072
|
else if (orchestrator.toolSearch || RESOURCE_TOOL_NAMES.has(tool.name)) {
|
|
977
|
-
waiting =
|
|
1073
|
+
waiting = readyServers;
|
|
1074
|
+
}
|
|
1075
|
+
else {
|
|
1076
|
+
const owner = toolOwners.get(event.toolName)?.split("\0", 1)[0];
|
|
1077
|
+
waiting = readyServers.filter((server) => server.entry.name === owner);
|
|
978
1078
|
}
|
|
979
1079
|
await waitForServers(waiting, ctx.signal);
|
|
980
1080
|
});
|
|
@@ -985,9 +1085,9 @@ export function createMcpExtension(options = {}) {
|
|
|
985
1085
|
});
|
|
986
1086
|
// Servers registered or unregistered during the session connect or disconnect right away.
|
|
987
1087
|
pi.on("mcp_servers_change", async (_event, ctx) => {
|
|
988
|
-
|
|
1088
|
+
const { signal } = session;
|
|
1089
|
+
if (signal.aborted)
|
|
989
1090
|
return;
|
|
990
|
-
const current = generation;
|
|
991
1091
|
const registered = registeredServers();
|
|
992
1092
|
overridden = registered.overridden;
|
|
993
1093
|
const next = new Map(registered.servers.map((server) => [server.entry.name, server]));
|
|
@@ -1003,11 +1103,11 @@ export function createMcpExtension(options = {}) {
|
|
|
1003
1103
|
ensureDiscoveryActive(ctx);
|
|
1004
1104
|
await Promise.all(removed.map((server) => server.connection?.close()));
|
|
1005
1105
|
const connecting = added.filter(isEnabled);
|
|
1006
|
-
if (
|
|
1106
|
+
if (signal.aborted || connecting.length === 0)
|
|
1007
1107
|
return;
|
|
1008
1108
|
try {
|
|
1009
|
-
await Promise.all(connecting.map((server) => startConnection(server
|
|
1010
|
-
if (
|
|
1109
|
+
await Promise.all(connecting.map((server) => startConnection(server)));
|
|
1110
|
+
if (signal.aborted) {
|
|
1011
1111
|
await Promise.all(connecting.map((server) => server.connection?.close()));
|
|
1012
1112
|
return;
|
|
1013
1113
|
}
|
|
@@ -1016,17 +1116,16 @@ export function createMcpExtension(options = {}) {
|
|
|
1016
1116
|
ctx.ui.notify(`MCP failed to load: ${errorMessage(error)}`, "error");
|
|
1017
1117
|
return;
|
|
1018
1118
|
}
|
|
1019
|
-
if (
|
|
1119
|
+
if (signal.aborted)
|
|
1020
1120
|
return;
|
|
1021
1121
|
reportProblems(ctx, connecting);
|
|
1022
1122
|
});
|
|
1023
1123
|
pi.on("session_shutdown", async () => {
|
|
1024
|
-
|
|
1025
|
-
generation++;
|
|
1124
|
+
session.abort();
|
|
1026
1125
|
const closing = connections();
|
|
1027
1126
|
servers = [];
|
|
1028
1127
|
emitChange();
|
|
1029
|
-
await Promise.all(closing.map((connection) => connection.close()));
|
|
1128
|
+
await Promise.all([...backgroundActions, ...closing.map((connection) => connection.close())]);
|
|
1030
1129
|
});
|
|
1031
1130
|
pi.registerCommand("mcp", {
|
|
1032
1131
|
description: "Manage MCP servers: sign in, reconnect, enable or disable, and change exposure",
|
|
@@ -1052,19 +1151,21 @@ export function createMcpExtension(options = {}) {
|
|
|
1052
1151
|
return items.length > 0 ? items : null;
|
|
1053
1152
|
},
|
|
1054
1153
|
handler: async (args, ctx) => {
|
|
1055
|
-
await pending;
|
|
1056
1154
|
const [action, name, ...extra] = args.trim().split(/\s+/).filter(Boolean);
|
|
1057
1155
|
if (action === undefined) {
|
|
1058
1156
|
if (ctx.mode === "tui")
|
|
1059
1157
|
await showMcpManager(ctx, (ui) => manage(ui, ctx));
|
|
1060
|
-
else
|
|
1158
|
+
else {
|
|
1159
|
+
await pending;
|
|
1061
1160
|
ctx.ui.notify(formatStatus(), "info");
|
|
1161
|
+
}
|
|
1062
1162
|
return;
|
|
1063
1163
|
}
|
|
1064
1164
|
if (extra.length > 0) {
|
|
1065
1165
|
ctx.ui.notify(MCP_USAGE, "warning");
|
|
1066
1166
|
return;
|
|
1067
1167
|
}
|
|
1168
|
+
await pending;
|
|
1068
1169
|
switch (action) {
|
|
1069
1170
|
case "login": {
|
|
1070
1171
|
const server = await pickServer(name, ctx, oauthPick);
|