@cjhyy/code-shell-core 0.5.0-rc.2 → 0.6.0-rc.10
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/README.md +13 -10
- package/dist/agent/agent-definition-registry.d.ts +3 -0
- package/dist/agent/agent-definition-registry.js +3 -1
- package/dist/agent/agent-definition.d.ts +15 -0
- package/dist/agent/agent-definition.js +27 -3
- package/dist/arena/context/context-tools.js +47 -4
- package/dist/arena/ledger.js +9 -1
- package/dist/arena/strategies/utils.d.ts +1 -4
- package/dist/arena/strategies/utils.js +7 -84
- package/dist/automation/cron-expr.d.ts +10 -0
- package/dist/automation/cron-expr.js +23 -5
- package/dist/automation/runner.d.ts +21 -4
- package/dist/automation/runner.js +48 -12
- package/dist/automation/scheduler.d.ts +38 -0
- package/dist/automation/scheduler.js +89 -12
- package/dist/automation/store.js +5 -2
- package/dist/capability-control/disabled-lists.d.ts +25 -0
- package/dist/capability-control/disabled-lists.js +57 -0
- package/dist/capability-control/overlay.d.ts +15 -0
- package/dist/capability-control/overlay.js +27 -0
- package/dist/cc-orchestrator/agent-adapter.d.ts +50 -0
- package/dist/cc-orchestrator/agent-adapter.js +133 -0
- package/dist/cc-orchestrator/cc-capability.d.ts +19 -0
- package/dist/cc-orchestrator/cc-capability.js +53 -0
- package/dist/cc-orchestrator/codex-session-discovery.d.ts +24 -0
- package/dist/cc-orchestrator/codex-session-discovery.js +191 -0
- package/dist/cc-orchestrator/codex-session-history.d.ts +25 -0
- package/dist/cc-orchestrator/codex-session-history.js +187 -0
- package/dist/cc-orchestrator/external-agent-changes.d.ts +19 -0
- package/dist/cc-orchestrator/external-agent-changes.js +214 -0
- package/dist/cc-orchestrator/external-agent-driver.d.ts +18 -0
- package/dist/cc-orchestrator/external-agent-driver.js +69 -0
- package/dist/cc-orchestrator/index.d.ts +8 -0
- package/dist/cc-orchestrator/index.js +8 -0
- package/dist/cc-orchestrator/relevance-judge.d.ts +15 -0
- package/dist/cc-orchestrator/relevance-judge.js +29 -0
- package/dist/cc-orchestrator/session-discovery.d.ts +46 -0
- package/dist/cc-orchestrator/session-discovery.js +125 -0
- package/dist/cc-orchestrator/session-history.d.ts +19 -0
- package/dist/cc-orchestrator/session-history.js +67 -0
- package/dist/cli/agent-server-stdio.d.ts +15 -1
- package/dist/cli/agent-server-stdio.js +115 -17
- package/dist/cli/agent-server-tcp.js +40 -26
- package/dist/context/compaction.d.ts +86 -0
- package/dist/context/compaction.js +279 -0
- package/dist/context/manager.d.ts +18 -0
- package/dist/context/manager.js +181 -48
- package/dist/context/token-counter.js +13 -0
- package/dist/cost-tracker.js +5 -61
- package/dist/credentials/cipher.d.ts +49 -0
- package/dist/credentials/cipher.js +45 -0
- package/dist/credentials/cookie-jar.d.ts +24 -0
- package/dist/credentials/cookie-jar.js +40 -0
- package/dist/credentials/index.d.ts +7 -0
- package/dist/credentials/index.js +5 -0
- package/dist/credentials/inject-credential-tool.d.ts +20 -0
- package/dist/credentials/inject-credential-tool.js +130 -0
- package/dist/credentials/store.d.ts +72 -0
- package/dist/credentials/store.js +184 -0
- package/dist/credentials/types.d.ts +56 -0
- package/dist/credentials/use-credential-tool.d.ts +29 -0
- package/dist/credentials/use-credential-tool.js +205 -0
- package/dist/credentials/use-gate.d.ts +56 -0
- package/dist/credentials/use-gate.js +52 -0
- package/dist/data/model-metadata.d.ts +77 -0
- package/dist/data/model-metadata.js +56 -0
- package/dist/data/model-metadata.json +216 -0
- package/dist/data/openrouter-models.d.ts +18 -7
- package/dist/data/openrouter-models.js +35 -8
- package/dist/engine/aux-key.d.ts +10 -0
- package/dist/engine/aux-key.js +11 -0
- package/dist/engine/dynamic-tool-defs.d.ts +19 -0
- package/dist/engine/dynamic-tool-defs.js +36 -0
- package/dist/engine/engine.d.ts +280 -141
- package/dist/engine/engine.js +1193 -245
- package/dist/engine/friendly-error.d.ts +18 -0
- package/dist/engine/friendly-error.js +63 -0
- package/dist/engine/goal.d.ts +145 -0
- package/dist/engine/goal.js +144 -0
- package/dist/engine/image-policy.d.ts +13 -0
- package/dist/engine/image-policy.js +24 -0
- package/dist/engine/model-connections-pool.d.ts +17 -0
- package/dist/engine/model-connections-pool.js +67 -0
- package/dist/engine/model-facade.d.ts +10 -0
- package/dist/engine/model-facade.js +15 -0
- package/dist/engine/patch-orphaned-tools.js +3 -0
- package/dist/engine/query.js +2 -0
- package/dist/engine/resolve-llm-config.d.ts +16 -0
- package/dist/engine/resolve-llm-config.js +44 -0
- package/dist/engine/runtime.d.ts +2 -0
- package/dist/engine/runtime.js +27 -1
- package/dist/engine/sandbox-cache-key.d.ts +10 -0
- package/dist/engine/sandbox-cache-key.js +9 -0
- package/dist/engine/sandbox-config.d.ts +31 -0
- package/dist/engine/sandbox-config.js +38 -0
- package/dist/engine/session-usage.d.ts +31 -0
- package/dist/engine/session-usage.js +81 -0
- package/dist/engine/steer-queue.d.ts +33 -0
- package/dist/engine/steer-queue.js +26 -0
- package/dist/engine/streaming-tool-queue.d.ts +12 -0
- package/dist/engine/streaming-tool-queue.js +50 -10
- package/dist/engine/turn-loop.d.ts +94 -4
- package/dist/engine/turn-loop.js +432 -54
- package/dist/engine/types.d.ts +175 -0
- package/dist/engine/types.js +13 -0
- package/dist/external-agents/config.d.ts +2 -0
- package/dist/external-agents/config.js +15 -0
- package/dist/external-agents/types.d.ts +31 -0
- package/dist/external-agents/types.js +1 -0
- package/dist/git/utils.d.ts +12 -0
- package/dist/git/utils.js +38 -6
- package/dist/git/worktree.d.ts +48 -0
- package/dist/git/worktree.js +86 -10
- package/dist/hooks/goal-stop-hook.d.ts +28 -0
- package/dist/hooks/goal-stop-hook.js +186 -9
- package/dist/hooks/registry.d.ts +8 -0
- package/dist/hooks/registry.js +19 -0
- package/dist/hooks/shell-runner.js +10 -21
- package/dist/index.d.ts +51 -7
- package/dist/index.js +62 -5
- package/dist/llm/capabilities/param-specs.d.ts +14 -0
- package/dist/llm/capabilities/param-specs.js +62 -0
- package/dist/llm/capabilities/rules.js +5 -1
- package/dist/llm/capabilities/types.d.ts +10 -0
- package/dist/llm/client-base.d.ts +28 -1
- package/dist/llm/client-base.js +119 -13
- package/dist/llm/model-cache.js +4 -2
- package/dist/llm/model-pool.d.ts +21 -0
- package/dist/llm/model-pool.js +21 -1
- package/dist/llm/provider-auth.d.ts +41 -0
- package/dist/llm/provider-auth.js +76 -0
- package/dist/llm/provider-catalog.d.ts +4 -0
- package/dist/llm/providers/anthropic.js +64 -14
- package/dist/llm/providers/openai.d.ts +36 -0
- package/dist/llm/providers/openai.js +257 -51
- package/dist/llm/reasoning-setting.d.ts +3 -3
- package/dist/llm/reasoning-setting.js +9 -1
- package/dist/llm/stream-watchdog.js +5 -1
- package/dist/llm/token-counter.js +9 -2
- package/dist/llm/types.d.ts +4 -0
- package/dist/logging/sanitize-messages.js +22 -0
- package/dist/lsp/manager.d.ts +1 -1
- package/dist/lsp/manager.js +40 -10
- package/dist/model-catalog/builtin.d.ts +12 -0
- package/dist/model-catalog/builtin.js +412 -0
- package/dist/model-catalog/gen-connections.d.ts +20 -0
- package/dist/model-catalog/gen-connections.js +28 -0
- package/dist/model-catalog/index.d.ts +41 -0
- package/dist/model-catalog/index.js +90 -0
- package/dist/model-catalog/params.d.ts +20 -0
- package/dist/model-catalog/params.js +45 -0
- package/dist/model-catalog/resolve.d.ts +48 -0
- package/dist/model-catalog/resolve.js +33 -0
- package/dist/model-catalog/save-entry.d.ts +32 -0
- package/dist/model-catalog/save-entry.js +104 -0
- package/dist/model-catalog/types.d.ts +561 -0
- package/dist/model-catalog/types.js +93 -0
- package/dist/model-catalog/upsert.d.ts +9 -0
- package/dist/model-catalog/upsert.js +8 -0
- package/dist/onboarding.d.ts +12 -82
- package/dist/onboarding.js +61 -326
- package/dist/plugins/gitOps.d.ts +19 -0
- package/dist/plugins/gitOps.js +73 -4
- package/dist/plugins/installer/checkUpdate.d.ts +16 -0
- package/dist/plugins/installer/checkUpdate.js +32 -0
- package/dist/plugins/installer/codex/convertCommands.d.ts +19 -0
- package/dist/plugins/installer/codex/convertCommands.js +46 -0
- package/dist/plugins/installer/codex/convertMcp.d.ts +5 -2
- package/dist/plugins/installer/codex/convertMcp.js +45 -5
- package/dist/plugins/installer/install.js +25 -1
- package/dist/plugins/installer/installFromArchive.d.ts +43 -0
- package/dist/plugins/installer/installFromArchive.js +134 -0
- package/dist/plugins/installer/installFromSource.js +8 -2
- package/dist/plugins/installer/loadPluginAgents.js +6 -2
- package/dist/plugins/installer/loadPluginMcp.d.ts +9 -2
- package/dist/plugins/installer/loadPluginMcp.js +35 -2
- package/dist/plugins/installer/pruneDisabled.d.ts +24 -0
- package/dist/plugins/installer/pruneDisabled.js +73 -0
- package/dist/plugins/installer/types.d.ts +5 -2
- package/dist/plugins/installer/types.js +1 -0
- package/dist/plugins/installer/uninstall.js +4 -0
- package/dist/plugins/installer/unzip.d.ts +14 -0
- package/dist/plugins/installer/unzip.js +82 -0
- package/dist/plugins/installer/update.d.ts +14 -0
- package/dist/plugins/installer/update.js +53 -21
- package/dist/plugins/loadPluginHooks.d.ts +47 -1
- package/dist/plugins/loadPluginHooks.js +73 -1
- package/dist/plugins/marketplaceManager.d.ts +7 -0
- package/dist/plugins/marketplaceManager.js +20 -0
- package/dist/plugins/pluginCommandHook.js +4 -18
- package/dist/plugins/pluginContent.d.ts +30 -0
- package/dist/plugins/pluginContent.js +83 -0
- package/dist/plugins/pluginInstaller.d.ts +13 -0
- package/dist/plugins/pluginInstaller.js +42 -8
- package/dist/plugins/schemas.js +1 -0
- package/dist/plugins/types.d.ts +6 -0
- package/dist/preset/index.d.ts +11 -1
- package/dist/preset/index.js +115 -6
- package/dist/product/types.d.ts +1 -1
- package/dist/prompt/composer.d.ts +32 -0
- package/dist/prompt/composer.js +75 -21
- package/dist/prompt/instruction-scanner.js +5 -3
- package/dist/prompt/section-loader.js +1 -0
- package/dist/prompt/sections/base.md +2 -0
- package/dist/prompt/sections/browser.md +10 -0
- package/dist/prompt/sections/coding.md +4 -0
- package/dist/protocol/chat-session-manager.d.ts +9 -2
- package/dist/protocol/chat-session-manager.js +38 -0
- package/dist/protocol/chat-session.d.ts +69 -1
- package/dist/protocol/chat-session.js +102 -4
- package/dist/protocol/client.d.ts +31 -0
- package/dist/protocol/client.js +44 -0
- package/dist/protocol/server.d.ts +120 -7
- package/dist/protocol/server.js +753 -51
- package/dist/protocol/transport.js +3 -2
- package/dist/protocol/types.d.ts +60 -0
- package/dist/protocol/types.js +16 -0
- package/dist/quota/credentials.d.ts +3 -0
- package/dist/quota/credentials.js +80 -0
- package/dist/quota/index.d.ts +36 -0
- package/dist/quota/index.js +155 -0
- package/dist/quota/types.d.ts +48 -0
- package/dist/quota/types.js +13 -0
- package/dist/review/review-prompt.d.ts +28 -0
- package/dist/review/review-prompt.js +81 -0
- package/dist/run/FileRunStore.js +8 -3
- package/dist/run/RunApprovalBackend.js +25 -5
- package/dist/run/RunManager.d.ts +12 -0
- package/dist/run/RunManager.js +35 -0
- package/dist/run/factory.d.ts +1 -1
- package/dist/runtime/background-shell.d.ts +139 -0
- package/dist/runtime/background-shell.js +509 -0
- package/dist/runtime/output-clean.d.ts +24 -0
- package/dist/runtime/output-clean.js +41 -0
- package/dist/runtime/ring-file.d.ts +64 -0
- package/dist/runtime/ring-file.js +174 -0
- package/dist/runtime/safe-spawn.js +98 -39
- package/dist/runtime/spawn-common.d.ts +159 -0
- package/dist/runtime/spawn-common.js +404 -0
- package/dist/runtime/truncate-output.d.ts +22 -0
- package/dist/runtime/truncate-output.js +49 -0
- package/dist/runtime/utf8-cut.d.ts +11 -0
- package/dist/runtime/utf8-cut.js +23 -0
- package/dist/services/auto-dream.d.ts +4 -0
- package/dist/services/auto-dream.js +26 -26
- package/dist/services/diagnostics.d.ts +1 -2
- package/dist/services/diagnostics.js +12 -7
- package/dist/services/extract-memories.d.ts +14 -1
- package/dist/services/extract-memories.js +45 -6
- package/dist/services/memory-orchestrator.d.ts +21 -0
- package/dist/services/memory-orchestrator.js +125 -50
- package/dist/services/session-memory.js +24 -12
- package/dist/session/file-history.d.ts +124 -1
- package/dist/session/file-history.js +222 -6
- package/dist/session/memory.d.ts +116 -2
- package/dist/session/memory.js +250 -28
- package/dist/session/session-manager.d.ts +40 -0
- package/dist/session/session-manager.js +119 -3
- package/dist/session/simple-diff.d.ts +23 -0
- package/dist/session/simple-diff.js +84 -0
- package/dist/session/transcript.d.ts +29 -1
- package/dist/session/transcript.js +56 -2
- package/dist/session/undo-target.d.ts +67 -0
- package/dist/session/undo-target.js +144 -0
- package/dist/settings/disk-defaults.d.ts +9 -2
- package/dist/settings/disk-defaults.js +11 -2
- package/dist/settings/feature-flags.d.ts +64 -0
- package/dist/settings/feature-flags.js +61 -0
- package/dist/settings/manager.d.ts +68 -1
- package/dist/settings/manager.js +266 -29
- package/dist/settings/migrate-config.d.ts +45 -0
- package/dist/settings/migrate-config.js +125 -0
- package/dist/settings/schema-export.d.ts +25 -0
- package/dist/settings/schema-export.js +38 -0
- package/dist/settings/schema.d.ts +1186 -771
- package/dist/settings/schema.js +268 -97
- package/dist/skills/scanner.d.ts +9 -0
- package/dist/skills/scanner.js +30 -2
- package/dist/stt/resolve-transcribe.d.ts +31 -0
- package/dist/stt/resolve-transcribe.js +108 -0
- package/dist/stt/transcribe.d.ts +51 -0
- package/dist/stt/transcribe.js +65 -0
- package/dist/tool-system/browser-bridge.d.ts +226 -0
- package/dist/tool-system/browser-bridge.js +163 -0
- package/dist/tool-system/builtin/agent-heartbeat.d.ts +49 -0
- package/dist/tool-system/builtin/agent-heartbeat.js +89 -0
- package/dist/tool-system/builtin/agent-notifications.d.ts +12 -3
- package/dist/tool-system/builtin/agent-notifications.js +9 -3
- package/dist/tool-system/builtin/agent-output-file.d.ts +38 -0
- package/dist/tool-system/builtin/agent-output-file.js +72 -0
- package/dist/tool-system/builtin/agent-registry.d.ts +12 -0
- package/dist/tool-system/builtin/agent-registry.js +8 -0
- package/dist/tool-system/builtin/agent.d.ts +21 -1
- package/dist/tool-system/builtin/agent.js +489 -42
- package/dist/tool-system/builtin/apply-patch/applier.js +66 -8
- package/dist/tool-system/builtin/apply-patch/backup-targets.d.ts +10 -0
- package/dist/tool-system/builtin/apply-patch/backup-targets.js +30 -0
- package/dist/tool-system/builtin/apply-patch/index.js +0 -15
- package/dist/tool-system/builtin/background-jobs.d.ts +76 -0
- package/dist/tool-system/builtin/background-jobs.js +124 -0
- package/dist/tool-system/builtin/background-shell-tools.d.ts +20 -0
- package/dist/tool-system/builtin/background-shell-tools.js +108 -0
- package/dist/tool-system/builtin/background-work.d.ts +67 -0
- package/dist/tool-system/builtin/background-work.js +86 -0
- package/dist/tool-system/builtin/bash-output-style.d.ts +32 -0
- package/dist/tool-system/builtin/bash-output-style.js +40 -0
- package/dist/tool-system/builtin/bash.d.ts +5 -2
- package/dist/tool-system/builtin/bash.js +101 -64
- package/dist/tool-system/builtin/browser-tools.d.ts +33 -0
- package/dist/tool-system/builtin/browser-tools.js +312 -0
- package/dist/tool-system/builtin/cancel-goal.d.ts +31 -0
- package/dist/tool-system/builtin/cancel-goal.js +64 -0
- package/dist/tool-system/builtin/check-quota.d.ts +15 -0
- package/dist/tool-system/builtin/check-quota.js +34 -0
- package/dist/tool-system/builtin/config.js +7 -0
- package/dist/tool-system/builtin/cron.d.ts +7 -0
- package/dist/tool-system/builtin/cron.js +64 -4
- package/dist/tool-system/builtin/drive-claude-code.d.ts +30 -0
- package/dist/tool-system/builtin/drive-claude-code.js +157 -0
- package/dist/tool-system/builtin/edit-model-catalog.d.ts +3 -0
- package/dist/tool-system/builtin/edit-model-catalog.js +104 -0
- package/dist/tool-system/builtin/edit.js +20 -16
- package/dist/tool-system/builtin/eol.d.ts +29 -0
- package/dist/tool-system/builtin/eol.js +37 -0
- package/dist/tool-system/builtin/file-cache.d.ts +6 -0
- package/dist/tool-system/builtin/file-cache.js +8 -0
- package/dist/tool-system/builtin/generate-image.d.ts +35 -0
- package/dist/tool-system/builtin/generate-image.js +278 -50
- package/dist/tool-system/builtin/generate-video.d.ts +55 -0
- package/dist/tool-system/builtin/generate-video.js +364 -0
- package/dist/tool-system/builtin/glob.js +0 -7
- package/dist/tool-system/builtin/grep.d.ts +9 -0
- package/dist/tool-system/builtin/grep.js +106 -11
- package/dist/tool-system/builtin/image-providers.d.ts +86 -0
- package/dist/tool-system/builtin/image-providers.js +190 -0
- package/dist/tool-system/builtin/image-uploader.d.ts +33 -0
- package/dist/tool-system/builtin/image-uploader.js +74 -0
- package/dist/tool-system/builtin/index.d.ts +10 -2
- package/dist/tool-system/builtin/index.js +251 -27
- package/dist/tool-system/builtin/mcp-tools.js +23 -3
- package/dist/tool-system/builtin/memory.js +45 -7
- package/dist/tool-system/builtin/notebook-edit.js +0 -7
- package/dist/tool-system/builtin/powershell.js +8 -2
- package/dist/tool-system/builtin/read.js +10 -10
- package/dist/tool-system/builtin/repl.js +4 -1
- package/dist/tool-system/builtin/skill.js +9 -0
- package/dist/tool-system/builtin/sleep.js +8 -2
- package/dist/tool-system/builtin/tool-search.js +25 -7
- package/dist/tool-system/builtin/video-providers.d.ts +154 -0
- package/dist/tool-system/builtin/video-providers.js +235 -0
- package/dist/tool-system/builtin/web-fetch.js +12 -2
- package/dist/tool-system/builtin/web-search.js +21 -7
- package/dist/tool-system/builtin/worktree.d.ts +2 -1
- package/dist/tool-system/builtin/worktree.js +31 -4
- package/dist/tool-system/builtin/write.js +0 -6
- package/dist/tool-system/context.d.ts +164 -6
- package/dist/tool-system/executor.d.ts +3 -1
- package/dist/tool-system/executor.js +197 -90
- package/dist/tool-system/investigation-guard.js +1 -1
- package/dist/tool-system/mcp-manager.d.ts +42 -4
- package/dist/tool-system/mcp-manager.js +203 -20
- package/dist/tool-system/mcp-stdio-diagnostics.d.ts +9 -0
- package/dist/tool-system/mcp-stdio-diagnostics.js +93 -0
- package/dist/tool-system/path-policy.d.ts +5 -0
- package/dist/tool-system/path-policy.js +307 -8
- package/dist/tool-system/permission.d.ts +39 -2
- package/dist/tool-system/permission.js +283 -70
- package/dist/tool-system/plan-mode-allowlist.d.ts +13 -2
- package/dist/tool-system/plan-mode-allowlist.js +24 -2
- package/dist/tool-system/registry.d.ts +1 -0
- package/dist/tool-system/registry.js +16 -2
- package/dist/tool-system/sandbox/index.d.ts +8 -0
- package/dist/tool-system/sandbox/index.js +7 -2
- package/dist/tool-system/sandbox/off.js +7 -1
- package/dist/tool-system/validate-tool-metadata.d.ts +36 -0
- package/dist/tool-system/validate-tool-metadata.js +63 -0
- package/dist/types.d.ts +252 -7
- package/dist/updater.js +20 -9
- package/dist/utils/envUtils.d.ts +0 -9
- package/dist/utils/envUtils.js +3 -28
- package/dist/utils/exec.d.ts +48 -0
- package/dist/utils/exec.js +154 -0
- package/dist/utils/json.d.ts +12 -0
- package/dist/utils/json.js +92 -0
- package/dist/utils/theme.d.ts +1 -1
- package/dist/utils/theme.js +1 -1
- package/dist/utils/toolDisplay.js +0 -1
- package/package.json +13 -7
- package/dist/agent/coordinator.d.ts +0 -49
- package/dist/agent/coordinator.js +0 -77
- package/dist/settings/manager.test.js +0 -73
- package/dist/tool-system/builtin/remote-trigger.d.ts +0 -6
- package/dist/tool-system/builtin/remote-trigger.js +0 -54
- package/dist/tool-system/builtin/send-message.d.ts +0 -6
- package/dist/tool-system/builtin/send-message.js +0 -47
- /package/dist/{settings/manager.test.d.ts → credentials/types.js} +0 -0
|
@@ -7,8 +7,98 @@ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
|
7
7
|
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
8
8
|
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
9
9
|
import { logger } from "../logging/logger.js";
|
|
10
|
+
import { CredentialStore } from "../credentials/index.js";
|
|
11
|
+
import { ENV_ALLOWLIST } from "../runtime/spawn-common.js";
|
|
10
12
|
import { writeFile, mkdir } from "node:fs/promises";
|
|
11
13
|
import { join } from "node:path";
|
|
14
|
+
import { diagnoseMcpStdioMissingCommand, previewPath } from "./mcp-stdio-diagnostics.js";
|
|
15
|
+
/**
|
|
16
|
+
* Read a required secret from `process.env` by NAME (Codex-style env-secret
|
|
17
|
+
* handling — the value is never persisted in MCP config). A referenced env var
|
|
18
|
+
* that is undefined OR empty string is treated as missing so the connection
|
|
19
|
+
* fails with a clear, actionable error naming the server, the config field,
|
|
20
|
+
* and the env var.
|
|
21
|
+
*/
|
|
22
|
+
export function readRequiredEnv(serverName, field, envName) {
|
|
23
|
+
const v = process.env[envName];
|
|
24
|
+
if (v === undefined || v === "") {
|
|
25
|
+
throw new Error(`MCP server "${serverName}": env var "${envName}" (from ${field}) is not set`);
|
|
26
|
+
}
|
|
27
|
+
return v;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Minimal set of host env vars a spawned stdio MCP server inherits by default.
|
|
31
|
+
* Allowlist, not blacklist — aligned with CC/Codex's env-secret-by-name model:
|
|
32
|
+
* a server gets only the runtime basics (PATH/HOME/LANG/…), and ANYTHING else
|
|
33
|
+
* it needs (an API key, a custom config dir) must be declared explicitly via
|
|
34
|
+
* `envVars` (forward by name) or `config.env` (literal). This avoids the
|
|
35
|
+
* fragile "guess which key looks like a secret" regex and its two failure
|
|
36
|
+
* modes (a bespoke key name leaks; a benign `FOO_TOKENIZER` gets stripped).
|
|
37
|
+
*
|
|
38
|
+
* Reuses the sandboxed-shell {@link ENV_ALLOWLIST} so the two spawn paths share
|
|
39
|
+
* one source of truth for "what's safe to forward".
|
|
40
|
+
*/
|
|
41
|
+
function inheritAllowlistedEnv(source) {
|
|
42
|
+
const out = {};
|
|
43
|
+
for (const name of ENV_ALLOWLIST) {
|
|
44
|
+
const v = source[name];
|
|
45
|
+
if (v !== undefined)
|
|
46
|
+
out[name] = v;
|
|
47
|
+
}
|
|
48
|
+
return out;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Build the spawned stdio server's environment. Priority (lowest → highest):
|
|
52
|
+
* a minimal inherited allowlist < forwarded `envVars` (read from process.env by
|
|
53
|
+
* name) < explicit plaintext `config.env`. Returns `undefined` when neither
|
|
54
|
+
* `env` nor `envVars` is present, preserving the old "inherit nothing extra"
|
|
55
|
+
* behavior (transport gets `env: undefined`). Pure + exported for unit testing.
|
|
56
|
+
*/
|
|
57
|
+
export function buildStdioEnv(serverName, config) {
|
|
58
|
+
if (!config.env && !config.envVars?.length)
|
|
59
|
+
return undefined;
|
|
60
|
+
const forwarded = {};
|
|
61
|
+
for (const en of config.envVars ?? []) {
|
|
62
|
+
forwarded[en] = readRequiredEnv(serverName, "envVars", en);
|
|
63
|
+
}
|
|
64
|
+
return {
|
|
65
|
+
...inheritAllowlistedEnv(process.env),
|
|
66
|
+
...forwarded,
|
|
67
|
+
...(config.env ?? {}),
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Build the HTTP transport's request headers. Static `config.headers` form the
|
|
72
|
+
* base; env-sourced secrets (`bearerTokenEnvVar`, `envHeaders`) layer on top
|
|
73
|
+
* and win on conflict. Pure + exported for unit testing.
|
|
74
|
+
*/
|
|
75
|
+
export function buildHttpHeaders(serverName, config, resolveCredential) {
|
|
76
|
+
const headers = { ...(config.headers ?? {}) };
|
|
77
|
+
if (config.credentialRef) {
|
|
78
|
+
const secret = resolveCredential?.(config.credentialRef);
|
|
79
|
+
if (secret === undefined || secret === "") {
|
|
80
|
+
throw new Error(`MCP server "${serverName}": credential "${config.credentialRef}" not found or empty`);
|
|
81
|
+
}
|
|
82
|
+
headers["Authorization"] = `Bearer ${secret}`;
|
|
83
|
+
}
|
|
84
|
+
else if (config.bearerTokenEnvVar) {
|
|
85
|
+
headers["Authorization"] = `Bearer ${readRequiredEnv(serverName, "bearerTokenEnvVar", config.bearerTokenEnvVar)}`;
|
|
86
|
+
}
|
|
87
|
+
for (const [hName, envName] of Object.entries(config.envHeaders ?? {})) {
|
|
88
|
+
headers[hName] = readRequiredEnv(serverName, "envHeaders", envName);
|
|
89
|
+
}
|
|
90
|
+
return headers;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Infer the transport when the config doesn't name one: a url-only entry is
|
|
94
|
+
* HTTP, everything else stdio. This is the CC `.mcp.json` convention —
|
|
95
|
+
* plugin-bundled servers commonly write just `{ "url": "..." }`, and the old
|
|
96
|
+
* blind `?? "stdio"` default then failed them with "command is required for
|
|
97
|
+
* stdio transport" despite a perfectly good url. Pure + exported for testing.
|
|
98
|
+
*/
|
|
99
|
+
export function inferTransportType(config) {
|
|
100
|
+
return config.transport ?? (config.url && !config.command ? "streamable-http" : "stdio");
|
|
101
|
+
}
|
|
12
102
|
/**
|
|
13
103
|
* Wrap raw MCP server output with an explicit untrusted-content marker
|
|
14
104
|
* before it reaches the LLM. The wrapper does two things:
|
|
@@ -87,7 +177,9 @@ export function wrapMcpOutput(serverName, toolName, body) {
|
|
|
87
177
|
].join("\n");
|
|
88
178
|
}
|
|
89
179
|
export function stripInternalToolArgs(args) {
|
|
90
|
-
|
|
180
|
+
// Drop executor-injected internal fields so they never reach the MCP server as
|
|
181
|
+
// tool arguments: __signal (abort) and __allowedMcpServers (auth allowlist).
|
|
182
|
+
const { __signal: _signal, __allowedMcpServers: _allowed, ...toolArgs } = args;
|
|
91
183
|
return toolArgs;
|
|
92
184
|
}
|
|
93
185
|
/**
|
|
@@ -125,6 +217,8 @@ export class MCPManager {
|
|
|
125
217
|
toolRegistry;
|
|
126
218
|
static instance = null;
|
|
127
219
|
connections = new Map();
|
|
220
|
+
registeredToolsByServer = new Map();
|
|
221
|
+
desiredServerNames = null;
|
|
128
222
|
/**
|
|
129
223
|
* In-flight connect()s keyed by server name. When the broadcast config
|
|
130
224
|
* reload (server.ts forEachSession → every session's refreshRuntimeConfig)
|
|
@@ -137,6 +231,8 @@ export class MCPManager {
|
|
|
137
231
|
* connect can be retried later.
|
|
138
232
|
*/
|
|
139
233
|
connecting = new Map();
|
|
234
|
+
/** Per-owner (engine) desired server sets — see reconcile()'s shared-pool note. */
|
|
235
|
+
desiredByOwner = new Map();
|
|
140
236
|
constructor(toolRegistry) {
|
|
141
237
|
this.toolRegistry = toolRegistry;
|
|
142
238
|
MCPManager.instance = this;
|
|
@@ -150,7 +246,15 @@ export class MCPManager {
|
|
|
150
246
|
/**
|
|
151
247
|
* Connect to all configured MCP servers and register their tools.
|
|
152
248
|
*/
|
|
153
|
-
async connectAll(servers) {
|
|
249
|
+
async connectAll(servers, owner) {
|
|
250
|
+
// Register this owner's desired set up front (see reconcile's shared-pool
|
|
251
|
+
// note) so a later reconcile from ANOTHER session can't disconnect servers
|
|
252
|
+
// this session connected at run start.
|
|
253
|
+
if (owner !== undefined) {
|
|
254
|
+
this.desiredByOwner.set(owner, new Set(Object.entries(servers)
|
|
255
|
+
.filter(([, c]) => c.enabled !== false)
|
|
256
|
+
.map(([n]) => n)));
|
|
257
|
+
}
|
|
154
258
|
// Codex-style toggle: skip servers explicitly disabled in settings.
|
|
155
259
|
// Only the literal `false` disables — absent / true / any other value
|
|
156
260
|
// stays connected, matching the schema default semantics.
|
|
@@ -174,6 +278,37 @@ export class MCPManager {
|
|
|
174
278
|
}
|
|
175
279
|
}
|
|
176
280
|
}
|
|
281
|
+
async reconcile(servers, owner) {
|
|
282
|
+
const enabledNames = new Set(Object.entries(servers)
|
|
283
|
+
.filter(([, config]) => config.enabled !== false)
|
|
284
|
+
.map(([name]) => name));
|
|
285
|
+
this.desiredServerNames = enabledNames;
|
|
286
|
+
// Shared-pool semantics: this ONE pool serves every session in the worker,
|
|
287
|
+
// and sessions in different projects legitimately want DIFFERENT server
|
|
288
|
+
// sets (per-project capabilityOverrides). Disconnect only servers that NO
|
|
289
|
+
// registered owner wants — otherwise the per-session hot-reload patches
|
|
290
|
+
// would thrash each other's connections (last reconcile wins, killing a
|
|
291
|
+
// server another project's session is using). Owners are engines; a
|
|
292
|
+
// closed session's desires linger (no engine-teardown hook), which merely
|
|
293
|
+
// over-RETAINS idle connections — per-session tool visibility keeps
|
|
294
|
+
// correctness regardless.
|
|
295
|
+
if (owner !== undefined)
|
|
296
|
+
this.desiredByOwner.set(owner, enabledNames);
|
|
297
|
+
const union = this.unionDesired() ?? enabledNames;
|
|
298
|
+
const stale = this.listServers().filter((name) => !union.has(name));
|
|
299
|
+
await Promise.all(stale.map((name) => this.disconnect(name)));
|
|
300
|
+
await this.connectAll(servers, owner);
|
|
301
|
+
}
|
|
302
|
+
/** Union of every registered owner's desired set; null when none registered. */
|
|
303
|
+
unionDesired() {
|
|
304
|
+
if (this.desiredByOwner.size === 0)
|
|
305
|
+
return null;
|
|
306
|
+
const u = new Set();
|
|
307
|
+
for (const names of this.desiredByOwner.values())
|
|
308
|
+
for (const n of names)
|
|
309
|
+
u.add(n);
|
|
310
|
+
return u;
|
|
311
|
+
}
|
|
177
312
|
/**
|
|
178
313
|
* Connect to a single MCP server.
|
|
179
314
|
*
|
|
@@ -208,10 +343,10 @@ export class MCPManager {
|
|
|
208
343
|
logger.info("mcp.already_connected", { server: name });
|
|
209
344
|
return;
|
|
210
345
|
}
|
|
211
|
-
|
|
346
|
+
const transportType = inferTransportType(config);
|
|
347
|
+
logger.info("mcp.connecting", { server: name, transport: transportType });
|
|
212
348
|
const client = new Client({ name: "code-shell", version: "0.1.0" }, { capabilities: {} });
|
|
213
349
|
let transport;
|
|
214
|
-
const transportType = config.transport ?? "stdio";
|
|
215
350
|
if (transportType === "stdio") {
|
|
216
351
|
if (!config.command) {
|
|
217
352
|
throw new Error(`MCP server "${name}": command is required for stdio transport`);
|
|
@@ -219,15 +354,21 @@ export class MCPManager {
|
|
|
219
354
|
transport = new StdioClientTransport({
|
|
220
355
|
command: config.command,
|
|
221
356
|
args: config.args,
|
|
222
|
-
env:
|
|
357
|
+
env: buildStdioEnv(name, config),
|
|
223
358
|
});
|
|
224
359
|
}
|
|
225
360
|
else if (transportType === "streamable-http" || transportType === "sse") {
|
|
226
361
|
if (!config.url) {
|
|
227
362
|
throw new Error(`MCP server "${name}": url is required for ${transportType} transport`);
|
|
228
363
|
}
|
|
364
|
+
// credentialRef resolves against the user-scope CredentialStore. The
|
|
365
|
+
// shared MCPManager pool has no per-session cwd (see desiredByOwner note),
|
|
366
|
+
// and MCP-referenced credentials (e.g. a Figma token) are user-global by
|
|
367
|
+
// nature, so user scope is the right resolution surface here.
|
|
368
|
+
const credStore = new CredentialStore(undefined);
|
|
369
|
+
const headers = buildHttpHeaders(name, config, (id) => credStore.resolve(id)?.secret);
|
|
229
370
|
transport = new StreamableHTTPClientTransport(new URL(config.url), {
|
|
230
|
-
requestInit:
|
|
371
|
+
requestInit: Object.keys(headers).length ? { headers } : undefined,
|
|
231
372
|
});
|
|
232
373
|
}
|
|
233
374
|
else {
|
|
@@ -253,6 +394,22 @@ export class MCPManager {
|
|
|
253
394
|
catch {
|
|
254
395
|
// ignore cleanup errors
|
|
255
396
|
}
|
|
397
|
+
if (transportType === "stdio" && config.command) {
|
|
398
|
+
const diagnostic = await diagnoseMcpStdioMissingCommand(config.command, err);
|
|
399
|
+
if (diagnostic) {
|
|
400
|
+
logger.warn("mcp.stdio_command_missing", {
|
|
401
|
+
server: name,
|
|
402
|
+
command: config.command,
|
|
403
|
+
foundPaths: diagnostic.foundPaths,
|
|
404
|
+
path: previewPath(),
|
|
405
|
+
message: diagnostic.message,
|
|
406
|
+
});
|
|
407
|
+
const original = err instanceof Error ? err.message : String(err);
|
|
408
|
+
const enhanced = new Error(`${original}\n${diagnostic.message}`);
|
|
409
|
+
enhanced.cause = err;
|
|
410
|
+
throw enhanced;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
256
413
|
throw err;
|
|
257
414
|
}
|
|
258
415
|
finally {
|
|
@@ -262,6 +419,10 @@ export class MCPManager {
|
|
|
262
419
|
this.connections.set(name, { client, serverName: name, transport });
|
|
263
420
|
// Discover and register tools
|
|
264
421
|
await this.discoverTools(name, client);
|
|
422
|
+
if (this.desiredServerNames && !this.desiredServerNames.has(name)) {
|
|
423
|
+
await this.disconnect(name);
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
265
426
|
logger.info("mcp.connected", { server: name });
|
|
266
427
|
}
|
|
267
428
|
/**
|
|
@@ -317,6 +478,9 @@ export class MCPManager {
|
|
|
317
478
|
// strings can't fake their way out.
|
|
318
479
|
return wrapMcpOutput(serverName, tool.name, body);
|
|
319
480
|
});
|
|
481
|
+
const set = this.registeredToolsByServer.get(serverName) ?? new Set();
|
|
482
|
+
set.add(registered.name);
|
|
483
|
+
this.registeredToolsByServer.set(serverName, set);
|
|
320
484
|
logger.info("mcp.tool_registered", { server: serverName, tool: registered.name });
|
|
321
485
|
}
|
|
322
486
|
}
|
|
@@ -324,16 +488,27 @@ export class MCPManager {
|
|
|
324
488
|
* Disconnect all MCP servers.
|
|
325
489
|
*/
|
|
326
490
|
async disconnectAll() {
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
491
|
+
await Promise.all([...this.connections.keys()].map((name) => this.disconnect(name)));
|
|
492
|
+
}
|
|
493
|
+
async disconnect(name) {
|
|
494
|
+
const conn = this.connections.get(name);
|
|
495
|
+
if (!conn)
|
|
496
|
+
return;
|
|
497
|
+
try {
|
|
498
|
+
await conn.client.close();
|
|
499
|
+
logger.info("mcp.disconnected", { server: name });
|
|
500
|
+
}
|
|
501
|
+
catch (err) {
|
|
502
|
+
logger.warn("mcp.disconnect_error", { server: name, error: err.message });
|
|
503
|
+
}
|
|
504
|
+
finally {
|
|
505
|
+
this.connections.delete(name);
|
|
506
|
+
for (const toolName of this.registeredToolsByServer.get(name) ?? []) {
|
|
507
|
+
this.toolRegistry.unregisterTool(toolName);
|
|
508
|
+
logger.info("mcp.tool_unregistered", { server: name, tool: toolName });
|
|
334
509
|
}
|
|
510
|
+
this.registeredToolsByServer.delete(name);
|
|
335
511
|
}
|
|
336
|
-
this.connections.clear();
|
|
337
512
|
}
|
|
338
513
|
/**
|
|
339
514
|
* List connected servers.
|
|
@@ -344,12 +519,15 @@ export class MCPManager {
|
|
|
344
519
|
/**
|
|
345
520
|
* Call a tool on a specific MCP server.
|
|
346
521
|
*/
|
|
347
|
-
async callTool(serverName, toolName, args) {
|
|
522
|
+
async callTool(serverName, toolName, args, signal) {
|
|
348
523
|
const conn = this.connections.get(serverName);
|
|
349
524
|
if (!conn) {
|
|
350
525
|
throw new Error(`MCP server "${serverName}" is not connected.`);
|
|
351
526
|
}
|
|
352
|
-
|
|
527
|
+
// Forward the run's abort signal so a user Stop cancels an in-flight MCP
|
|
528
|
+
// call promptly instead of blocking until the SDK's default request timeout.
|
|
529
|
+
// (The SDK still enforces its default timeout when no signal is provided.)
|
|
530
|
+
const result = await conn.client.callTool({ name: toolName, arguments: stripInternalToolArgs(args) }, undefined, signal ? { signal } : undefined);
|
|
353
531
|
const parts = [];
|
|
354
532
|
if (Array.isArray(result.content)) {
|
|
355
533
|
for (const item of result.content) {
|
|
@@ -367,7 +545,7 @@ export class MCPManager {
|
|
|
367
545
|
/**
|
|
368
546
|
* List resources from MCP servers.
|
|
369
547
|
*/
|
|
370
|
-
async listResources(serverName) {
|
|
548
|
+
async listResources(serverName, signal) {
|
|
371
549
|
const results = [];
|
|
372
550
|
const servers = serverName ? [serverName] : [...this.connections.keys()];
|
|
373
551
|
for (const name of servers) {
|
|
@@ -375,7 +553,10 @@ export class MCPManager {
|
|
|
375
553
|
if (!conn)
|
|
376
554
|
continue;
|
|
377
555
|
try {
|
|
378
|
-
|
|
556
|
+
// Forward the run's abort signal so a user Stop cancels promptly
|
|
557
|
+
// instead of waiting out the SDK's default request timeout (same as
|
|
558
|
+
// callTool). The SDK still enforces its default timeout when no signal.
|
|
559
|
+
const res = await conn.client.listResources(undefined, signal ? { signal } : undefined);
|
|
379
560
|
for (const r of res.resources) {
|
|
380
561
|
results.push({
|
|
381
562
|
uri: r.uri,
|
|
@@ -393,12 +574,14 @@ export class MCPManager {
|
|
|
393
574
|
/**
|
|
394
575
|
* Read a resource from an MCP server.
|
|
395
576
|
*/
|
|
396
|
-
async readResource(serverName, uri) {
|
|
577
|
+
async readResource(serverName, uri, signal) {
|
|
397
578
|
const conn = this.connections.get(serverName);
|
|
398
579
|
if (!conn) {
|
|
399
580
|
throw new Error(`MCP server "${serverName}" is not connected.`);
|
|
400
581
|
}
|
|
401
|
-
|
|
582
|
+
// Forward the run's abort signal so a user Stop cancels promptly (same as
|
|
583
|
+
// callTool); the SDK still enforces its default timeout when no signal.
|
|
584
|
+
const result = await conn.client.readResource({ uri }, signal ? { signal } : undefined);
|
|
402
585
|
const parts = [];
|
|
403
586
|
if (Array.isArray(result.contents)) {
|
|
404
587
|
for (const item of result.contents) {
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare function isBareCommand(command: string): boolean;
|
|
2
|
+
export declare function isMissingCommandError(error: unknown): boolean;
|
|
3
|
+
export declare function probeCommonExecutableLocations(command: string, env?: NodeJS.ProcessEnv): Promise<string[]>;
|
|
4
|
+
export declare function classifyMcpStdioMissingCommand(command: string, foundPaths: readonly string[]): string;
|
|
5
|
+
export declare function diagnoseMcpStdioMissingCommand(command: string, error: unknown, env?: NodeJS.ProcessEnv): Promise<{
|
|
6
|
+
message: string;
|
|
7
|
+
foundPaths: string[];
|
|
8
|
+
} | null>;
|
|
9
|
+
export declare function previewPath(env?: NodeJS.ProcessEnv): string;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { constants } from "node:fs";
|
|
2
|
+
import { access } from "node:fs/promises";
|
|
3
|
+
import { delimiter, isAbsolute, join } from "node:path";
|
|
4
|
+
const COMMON_POSIX_BIN_DIRS = [
|
|
5
|
+
"/opt/homebrew/bin",
|
|
6
|
+
"/usr/local/bin",
|
|
7
|
+
"/home/linuxbrew/.linuxbrew/bin",
|
|
8
|
+
"/usr/bin",
|
|
9
|
+
"/bin",
|
|
10
|
+
];
|
|
11
|
+
function unique(entries) {
|
|
12
|
+
const seen = new Set();
|
|
13
|
+
const out = [];
|
|
14
|
+
for (const entry of entries) {
|
|
15
|
+
const trimmed = entry.trim();
|
|
16
|
+
if (!trimmed || seen.has(trimmed))
|
|
17
|
+
continue;
|
|
18
|
+
seen.add(trimmed);
|
|
19
|
+
out.push(trimmed);
|
|
20
|
+
}
|
|
21
|
+
return out;
|
|
22
|
+
}
|
|
23
|
+
function commonExecutableDirs(env = process.env) {
|
|
24
|
+
const home = env.HOME?.trim();
|
|
25
|
+
return unique([
|
|
26
|
+
...COMMON_POSIX_BIN_DIRS,
|
|
27
|
+
...(home
|
|
28
|
+
? [join(home, ".bun", "bin"), join(home, ".local", "bin"), join(home, ".npm-global", "bin")]
|
|
29
|
+
: []),
|
|
30
|
+
]);
|
|
31
|
+
}
|
|
32
|
+
export function isBareCommand(command) {
|
|
33
|
+
const trimmed = command.trim();
|
|
34
|
+
return !!trimmed && !trimmed.includes("/") && !trimmed.includes("\\") && !isAbsolute(trimmed);
|
|
35
|
+
}
|
|
36
|
+
export function isMissingCommandError(error) {
|
|
37
|
+
const err = error;
|
|
38
|
+
const message = typeof err.message === "string" ? err.message : String(error);
|
|
39
|
+
return err.code === "ENOENT" || /\bENOENT\b/i.test(message) || /command not found/i.test(message);
|
|
40
|
+
}
|
|
41
|
+
async function isExecutable(filePath) {
|
|
42
|
+
try {
|
|
43
|
+
await access(filePath, constants.X_OK);
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
export async function probeCommonExecutableLocations(command, env = process.env) {
|
|
51
|
+
if (!isBareCommand(command) || process.platform === "win32")
|
|
52
|
+
return [];
|
|
53
|
+
const found = [];
|
|
54
|
+
for (const dir of commonExecutableDirs(env)) {
|
|
55
|
+
const candidate = join(dir, command);
|
|
56
|
+
if (await isExecutable(candidate))
|
|
57
|
+
found.push(candidate);
|
|
58
|
+
}
|
|
59
|
+
return found;
|
|
60
|
+
}
|
|
61
|
+
function installGuidance(command) {
|
|
62
|
+
if (command === "node" || command === "npx")
|
|
63
|
+
return "Please install Node.js and restart CodeShell.";
|
|
64
|
+
if (command === "bun" || command === "bunx")
|
|
65
|
+
return "Please install Bun and restart CodeShell.";
|
|
66
|
+
return `Please install "${command}" and restart CodeShell.`;
|
|
67
|
+
}
|
|
68
|
+
export function classifyMcpStdioMissingCommand(command, foundPaths) {
|
|
69
|
+
const trimmed = command.trim();
|
|
70
|
+
if (foundPaths.length > 0) {
|
|
71
|
+
return [
|
|
72
|
+
`MCP stdio command "${trimmed}" failed to start: detected ${trimmed} at ${foundPaths[0]},`,
|
|
73
|
+
"but that directory was not available on PATH.",
|
|
74
|
+
"Login-shell PATH injection may have failed; restart CodeShell or configure this MCP command as an absolute path.",
|
|
75
|
+
].join(" ");
|
|
76
|
+
}
|
|
77
|
+
return [
|
|
78
|
+
`MCP stdio command "${trimmed}" failed to start: ${trimmed} was not found on PATH or in common install locations.`,
|
|
79
|
+
installGuidance(trimmed),
|
|
80
|
+
].join(" ");
|
|
81
|
+
}
|
|
82
|
+
export async function diagnoseMcpStdioMissingCommand(command, error, env = process.env) {
|
|
83
|
+
if (!isBareCommand(command) || !isMissingCommandError(error))
|
|
84
|
+
return null;
|
|
85
|
+
const foundPaths = await probeCommonExecutableLocations(command, env);
|
|
86
|
+
return {
|
|
87
|
+
message: classifyMcpStdioMissingCommand(command, foundPaths),
|
|
88
|
+
foundPaths,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
export function previewPath(env = process.env) {
|
|
92
|
+
return (env.PATH ?? "").split(delimiter).filter(Boolean).join(delimiter);
|
|
93
|
+
}
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
* approval round-trip; it is not an authority to write anywhere on disk.
|
|
30
30
|
* Callers must consult classifyPath before honoring acceptEdits.
|
|
31
31
|
*/
|
|
32
|
+
import type { ToolContext } from "./context.js";
|
|
32
33
|
export type PathDecision = "allow" | "ask" | "deny";
|
|
33
34
|
export type PathOperation = "read" | "write";
|
|
34
35
|
export interface PathClassification {
|
|
@@ -48,6 +49,9 @@ export interface ClassifyOptions {
|
|
|
48
49
|
/** "read" or "write" — different defaults for sensitive paths. */
|
|
49
50
|
operation: PathOperation;
|
|
50
51
|
}
|
|
52
|
+
export type PathApprovalScope = "once" | "session" | "project";
|
|
53
|
+
/** Test seam: clear the in-memory session grants. */
|
|
54
|
+
export declare function _resetSessionPathGrants(): void;
|
|
51
55
|
/**
|
|
52
56
|
* Classify a file path against the workspace + sensitive-path policy.
|
|
53
57
|
*
|
|
@@ -86,6 +90,7 @@ export declare function classifyPath(rawPath: string, opts: ClassifyOptions): Pa
|
|
|
86
90
|
* remains the rollback knob for the LLM-driven path.
|
|
87
91
|
*/
|
|
88
92
|
export declare function enforcePathPolicy(filePath: string, operation: PathOperation, workspaceRoot?: string): string | null;
|
|
93
|
+
export declare function enforcePathPolicyWithApproval(filePath: string, operation: PathOperation, ctx?: ToolContext): Promise<string | null>;
|
|
89
94
|
/**
|
|
90
95
|
* Internal: reset the "disabled warning" latch. Tests flip the env var
|
|
91
96
|
* between cases and need each one to be able to re-trigger the warning.
|