@shareai-lab/kode 1.2.0 → 2.0.1
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 +25 -388
- package/cli-acp.js +82 -0
- package/cli.js +89 -79
- package/dist/REPL-CW7AYLVL.js +42 -0
- package/dist/acp-VEPJ74LT.js +1357 -0
- package/dist/acp-VEPJ74LT.js.map +7 -0
- package/dist/agentsValidate-7LH4HTNR.js +373 -0
- package/dist/agentsValidate-7LH4HTNR.js.map +7 -0
- package/dist/ask-3NHFFUQG.js +125 -0
- package/dist/ask-3NHFFUQG.js.map +7 -0
- package/dist/autoUpdater-ITPIHCOI.js +17 -0
- package/dist/{utils/autoUpdater.js → chunk-3IN27HA5.js} +38 -21
- package/dist/chunk-3IN27HA5.js.map +7 -0
- package/dist/chunk-3RUXVV4S.js +23 -0
- package/dist/chunk-3RUXVV4S.js.map +7 -0
- package/dist/chunk-4FX3IVPT.js +164 -0
- package/dist/chunk-4FX3IVPT.js.map +7 -0
- package/dist/chunk-4RTX4AG4.js +249 -0
- package/dist/chunk-4RTX4AG4.js.map +7 -0
- package/dist/chunk-5PDP7R6N.js +515 -0
- package/dist/chunk-5PDP7R6N.js.map +7 -0
- package/dist/chunk-73WGVYLQ.js +735 -0
- package/dist/chunk-73WGVYLQ.js.map +7 -0
- package/dist/{services/systemReminder.js → chunk-7M2YN6TU.js} +221 -59
- package/dist/chunk-7M2YN6TU.js.map +7 -0
- package/dist/{utils/theme.js → chunk-7U7L4NMD.js} +28 -6
- package/dist/chunk-7U7L4NMD.js.map +7 -0
- package/dist/chunk-ABLVTESJ.js +19 -0
- package/dist/chunk-ABLVTESJ.js.map +7 -0
- package/dist/chunk-AFFSCMYS.js +191 -0
- package/dist/chunk-AFFSCMYS.js.map +7 -0
- package/dist/chunk-ARZSBOAO.js +1256 -0
- package/dist/chunk-ARZSBOAO.js.map +7 -0
- package/dist/chunk-CIG63V4E.js +72 -0
- package/dist/chunk-CIG63V4E.js.map +7 -0
- package/dist/chunk-CM3EGTG6.js +1609 -0
- package/dist/chunk-CM3EGTG6.js.map +7 -0
- package/dist/{services/openai.js → chunk-DZE5YA7L.js} +168 -234
- package/dist/chunk-DZE5YA7L.js.map +7 -0
- package/dist/chunk-E6YNABER.js +24 -0
- package/dist/chunk-E6YNABER.js.map +7 -0
- package/dist/{cost-tracker.js → chunk-EZXMVTDU.js} +51 -32
- package/dist/chunk-EZXMVTDU.js.map +7 -0
- package/dist/chunk-F2SJXUDI.js +148 -0
- package/dist/chunk-F2SJXUDI.js.map +7 -0
- package/dist/chunk-FC5ZCKBI.js +30167 -0
- package/dist/chunk-FC5ZCKBI.js.map +7 -0
- package/dist/chunk-HCBELH4J.js +145 -0
- package/dist/chunk-HCBELH4J.js.map +7 -0
- package/dist/chunk-HN4E4UUQ.js +96 -0
- package/dist/chunk-HN4E4UUQ.js.map +7 -0
- package/dist/{utils/model.js → chunk-IZVMU4S2.js} +194 -227
- package/dist/chunk-IZVMU4S2.js.map +7 -0
- package/dist/chunk-JC6NCUG5.js +11 -0
- package/dist/chunk-K2CWOTI2.js +196 -0
- package/dist/chunk-K2CWOTI2.js.map +7 -0
- package/dist/chunk-KAA5BGMQ.js +12 -0
- package/dist/chunk-KAA5BGMQ.js.map +7 -0
- package/dist/{utils/config.js → chunk-LC4TVOCZ.js} +351 -171
- package/dist/chunk-LC4TVOCZ.js.map +7 -0
- package/dist/chunk-MIW7N2MY.js +2613 -0
- package/dist/chunk-MIW7N2MY.js.map +7 -0
- package/dist/chunk-MWRSY4X6.js +240 -0
- package/dist/chunk-MWRSY4X6.js.map +7 -0
- package/dist/chunk-ND3XWFO6.js +34 -0
- package/dist/chunk-ND3XWFO6.js.map +7 -0
- package/dist/chunk-NPFOMITO.js +21 -0
- package/dist/chunk-NPFOMITO.js.map +7 -0
- package/dist/chunk-QVLYOPO5.js +1097 -0
- package/dist/chunk-QVLYOPO5.js.map +7 -0
- package/dist/chunk-RZWOUA25.js +490 -0
- package/dist/chunk-RZWOUA25.js.map +7 -0
- package/dist/chunk-S3J2TLV6.js +16 -0
- package/dist/chunk-S3J2TLV6.js.map +7 -0
- package/dist/chunk-S6HRABTA.js +95 -0
- package/dist/chunk-S6HRABTA.js.map +7 -0
- package/dist/{utils/debugLogger.js → chunk-STSX7GIX.js} +107 -204
- package/dist/chunk-STSX7GIX.js.map +7 -0
- package/dist/chunk-UHYRLID6.js +472 -0
- package/dist/chunk-UHYRLID6.js.map +7 -0
- package/dist/chunk-UKHTVRJM.js +47 -0
- package/dist/chunk-UKHTVRJM.js.map +7 -0
- package/dist/chunk-UYXEDKOZ.js +24 -0
- package/dist/chunk-UYXEDKOZ.js.map +7 -0
- package/dist/chunk-W7GRKO7Q.js +766 -0
- package/dist/chunk-W7GRKO7Q.js.map +7 -0
- package/dist/chunk-WVHORZQ5.js +17 -0
- package/dist/chunk-WVHORZQ5.js.map +7 -0
- package/dist/chunk-WWUWDNWW.js +49 -0
- package/dist/chunk-WWUWDNWW.js.map +7 -0
- package/dist/chunk-YC6LJCDE.js +511 -0
- package/dist/chunk-YC6LJCDE.js.map +7 -0
- package/dist/chunk-YXYYDIMI.js +2931 -0
- package/dist/chunk-YXYYDIMI.js.map +7 -0
- package/dist/chunk-ZVDRDPII.js +138 -0
- package/dist/chunk-ZVDRDPII.js.map +7 -0
- package/dist/cli-DOPVY2CW.js +3917 -0
- package/dist/cli-DOPVY2CW.js.map +7 -0
- package/dist/commands-2BF2CJ3A.js +46 -0
- package/dist/config-RUSD6G5Y.js +81 -0
- package/dist/context-6FXPETYH.js +30 -0
- package/dist/costTracker-6SL26FDB.js +19 -0
- package/dist/customCommands-TOIJFZAL.js +25 -0
- package/dist/customCommands-TOIJFZAL.js.map +7 -0
- package/dist/env-XGKBLU3D.js +22 -0
- package/dist/env-XGKBLU3D.js.map +7 -0
- package/dist/index.js +34 -5
- package/dist/index.js.map +4 -4
- package/dist/kodeAgentSessionId-X6XWQW7B.js +13 -0
- package/dist/kodeAgentSessionId-X6XWQW7B.js.map +7 -0
- package/dist/kodeAgentSessionLoad-MITZADPB.js +18 -0
- package/dist/kodeAgentSessionLoad-MITZADPB.js.map +7 -0
- package/dist/kodeAgentSessionResume-GVRWB4WO.js +16 -0
- package/dist/kodeAgentSessionResume-GVRWB4WO.js.map +7 -0
- package/dist/kodeAgentStreamJson-NXFN7TXH.js +13 -0
- package/dist/kodeAgentStreamJson-NXFN7TXH.js.map +7 -0
- package/dist/kodeAgentStreamJsonSession-UGEZJJEB.js +131 -0
- package/dist/kodeAgentStreamJsonSession-UGEZJJEB.js.map +7 -0
- package/dist/kodeAgentStructuredStdio-HGWJT7CU.js +10 -0
- package/dist/kodeAgentStructuredStdio-HGWJT7CU.js.map +7 -0
- package/dist/kodeHooks-QWM36A3D.js +36 -0
- package/dist/kodeHooks-QWM36A3D.js.map +7 -0
- package/dist/llm-ZUQC4WYM.js +3118 -0
- package/dist/llm-ZUQC4WYM.js.map +7 -0
- package/dist/llmLazy-54QQHA54.js +15 -0
- package/dist/llmLazy-54QQHA54.js.map +7 -0
- package/dist/loader-FYHJQES5.js +28 -0
- package/dist/loader-FYHJQES5.js.map +7 -0
- package/dist/mcp-J332IKT3.js +49 -0
- package/dist/mcp-J332IKT3.js.map +7 -0
- package/dist/{services/mentionProcessor.js → mentionProcessor-EE3XFHCJ.js} +61 -50
- package/dist/mentionProcessor-EE3XFHCJ.js.map +7 -0
- package/dist/messages-EOYQKPGM.js +63 -0
- package/dist/messages-EOYQKPGM.js.map +7 -0
- package/dist/model-FV3JDJKH.js +30 -0
- package/dist/model-FV3JDJKH.js.map +7 -0
- package/dist/openai-RRCWW33N.js +29 -0
- package/dist/openai-RRCWW33N.js.map +7 -0
- package/dist/outputStyles-62Q3VH2J.js +28 -0
- package/dist/outputStyles-62Q3VH2J.js.map +7 -0
- package/dist/package.json +1 -1
- package/dist/pluginRuntime-6ETCZ2LL.js +218 -0
- package/dist/pluginRuntime-6ETCZ2LL.js.map +7 -0
- package/dist/pluginValidation-I4YKUWGS.js +17 -0
- package/dist/pluginValidation-I4YKUWGS.js.map +7 -0
- package/dist/prompts-ZLEKDD77.js +48 -0
- package/dist/prompts-ZLEKDD77.js.map +7 -0
- package/dist/query-VFRJPBGD.js +50 -0
- package/dist/query-VFRJPBGD.js.map +7 -0
- package/dist/responsesStreaming-AW344PQO.js +10 -0
- package/dist/responsesStreaming-AW344PQO.js.map +7 -0
- package/dist/ripgrep-3NTIKQYW.js +17 -0
- package/dist/ripgrep-3NTIKQYW.js.map +7 -0
- package/dist/skillMarketplace-3RXQBVOL.js +37 -0
- package/dist/skillMarketplace-3RXQBVOL.js.map +7 -0
- package/dist/state-P5G6CO5V.js +16 -0
- package/dist/state-P5G6CO5V.js.map +7 -0
- package/dist/theme-3LWP3BG7.js +14 -0
- package/dist/theme-3LWP3BG7.js.map +7 -0
- package/dist/toolPermissionContext-65L65VEZ.js +17 -0
- package/dist/toolPermissionContext-65L65VEZ.js.map +7 -0
- package/dist/toolPermissionSettings-3ROBVTUK.js +18 -0
- package/dist/toolPermissionSettings-3ROBVTUK.js.map +7 -0
- package/dist/tools-RO7HSSE5.js +47 -0
- package/dist/tools-RO7HSSE5.js.map +7 -0
- package/dist/userInput-JSBJRFSK.js +311 -0
- package/dist/userInput-JSBJRFSK.js.map +7 -0
- package/dist/uuid-QN2CNKKN.js +9 -0
- package/dist/uuid-QN2CNKKN.js.map +7 -0
- package/package.json +43 -14
- package/scripts/binary-utils.cjs +62 -0
- package/scripts/cli-acp-wrapper.cjs +82 -0
- package/scripts/cli-wrapper.cjs +105 -0
- package/scripts/postinstall.js +135 -9
- package/LICENSE +0 -201
- package/README.zh-CN.md +0 -312
- package/dist/ProjectOnboarding.js +0 -99
- package/dist/ProjectOnboarding.js.map +0 -7
- package/dist/Tool.js +0 -1
- package/dist/commands/agents.js +0 -2087
- package/dist/commands/agents.js.map +0 -7
- package/dist/commands/approvedTools.js +0 -36
- package/dist/commands/approvedTools.js.map +0 -7
- package/dist/commands/bug.js +0 -21
- package/dist/commands/bug.js.map +0 -7
- package/dist/commands/clear.js +0 -37
- package/dist/commands/clear.js.map +0 -7
- package/dist/commands/compact.js +0 -104
- package/dist/commands/compact.js.map +0 -7
- package/dist/commands/config.js +0 -20
- package/dist/commands/config.js.map +0 -7
- package/dist/commands/cost.js +0 -19
- package/dist/commands/cost.js.map +0 -7
- package/dist/commands/ctx_viz.js +0 -152
- package/dist/commands/ctx_viz.js.map +0 -7
- package/dist/commands/doctor.js +0 -25
- package/dist/commands/doctor.js.map +0 -7
- package/dist/commands/help.js +0 -20
- package/dist/commands/help.js.map +0 -7
- package/dist/commands/init.js +0 -38
- package/dist/commands/init.js.map +0 -7
- package/dist/commands/listen.js +0 -37
- package/dist/commands/listen.js.map +0 -7
- package/dist/commands/login.js +0 -37
- package/dist/commands/login.js.map +0 -7
- package/dist/commands/logout.js +0 -33
- package/dist/commands/logout.js.map +0 -7
- package/dist/commands/mcp.js +0 -34
- package/dist/commands/mcp.js.map +0 -7
- package/dist/commands/model.js +0 -41
- package/dist/commands/model.js.map +0 -7
- package/dist/commands/modelstatus.js +0 -21
- package/dist/commands/modelstatus.js.map +0 -7
- package/dist/commands/onboarding.js +0 -36
- package/dist/commands/onboarding.js.map +0 -7
- package/dist/commands/pr_comments.js +0 -61
- package/dist/commands/pr_comments.js.map +0 -7
- package/dist/commands/refreshCommands.js +0 -37
- package/dist/commands/refreshCommands.js.map +0 -7
- package/dist/commands/release-notes.js +0 -30
- package/dist/commands/release-notes.js.map +0 -7
- package/dist/commands/resume.js +0 -35
- package/dist/commands/resume.js.map +0 -7
- package/dist/commands/review.js +0 -51
- package/dist/commands/review.js.map +0 -7
- package/dist/commands/terminalSetup.js +0 -163
- package/dist/commands/terminalSetup.js.map +0 -7
- package/dist/commands.js +0 -84
- package/dist/commands.js.map +0 -7
- package/dist/components/ApproveApiKey.js +0 -74
- package/dist/components/ApproveApiKey.js.map +0 -7
- package/dist/components/AsciiLogo.js +0 -12
- package/dist/components/AsciiLogo.js.map +0 -7
- package/dist/components/AutoUpdater.js +0 -74
- package/dist/components/AutoUpdater.js.map +0 -7
- package/dist/components/Bug.js +0 -147
- package/dist/components/Bug.js.map +0 -7
- package/dist/components/Config.js +0 -166
- package/dist/components/Config.js.map +0 -7
- package/dist/components/ConsoleOAuthFlow.js +0 -188
- package/dist/components/ConsoleOAuthFlow.js.map +0 -7
- package/dist/components/Cost.js +0 -13
- package/dist/components/Cost.js.map +0 -7
- package/dist/components/CostThresholdDialog.js +0 -38
- package/dist/components/CostThresholdDialog.js.map +0 -7
- package/dist/components/CustomSelect/option-map.js +0 -32
- package/dist/components/CustomSelect/option-map.js.map +0 -7
- package/dist/components/CustomSelect/select-option.js +0 -34
- package/dist/components/CustomSelect/select-option.js.map +0 -7
- package/dist/components/CustomSelect/select.js +0 -64
- package/dist/components/CustomSelect/select.js.map +0 -7
- package/dist/components/CustomSelect/theme.js +0 -1
- package/dist/components/CustomSelect/use-select-state.js +0 -220
- package/dist/components/CustomSelect/use-select-state.js.map +0 -7
- package/dist/components/CustomSelect/use-select.js +0 -21
- package/dist/components/CustomSelect/use-select.js.map +0 -7
- package/dist/components/FallbackToolUseRejectedMessage.js +0 -11
- package/dist/components/FallbackToolUseRejectedMessage.js.map +0 -7
- package/dist/components/FileEditToolUpdatedMessage.js +0 -32
- package/dist/components/FileEditToolUpdatedMessage.js.map +0 -7
- package/dist/components/Help.js +0 -41
- package/dist/components/Help.js.map +0 -7
- package/dist/components/HighlightedCode.js +0 -30
- package/dist/components/HighlightedCode.js.map +0 -7
- package/dist/components/InvalidConfigDialog.js +0 -83
- package/dist/components/InvalidConfigDialog.js.map +0 -7
- package/dist/components/Link.js +0 -18
- package/dist/components/Link.js.map +0 -7
- package/dist/components/LogSelector.js +0 -50
- package/dist/components/LogSelector.js.map +0 -7
- package/dist/components/Logo.js +0 -94
- package/dist/components/Logo.js.map +0 -7
- package/dist/components/MCPServerApprovalDialog.js +0 -79
- package/dist/components/MCPServerApprovalDialog.js.map +0 -7
- package/dist/components/MCPServerDialogCopy.js +0 -11
- package/dist/components/MCPServerDialogCopy.js.map +0 -7
- package/dist/components/MCPServerMultiselectDialog.js +0 -80
- package/dist/components/MCPServerMultiselectDialog.js.map +0 -7
- package/dist/components/Message.js +0 -146
- package/dist/components/Message.js.map +0 -7
- package/dist/components/MessageResponse.js +0 -9
- package/dist/components/MessageResponse.js.map +0 -7
- package/dist/components/MessageSelector.js +0 -133
- package/dist/components/MessageSelector.js.map +0 -7
- package/dist/components/ModeIndicator.js +0 -38
- package/dist/components/ModeIndicator.js.map +0 -7
- package/dist/components/ModelConfig.js +0 -208
- package/dist/components/ModelConfig.js.map +0 -7
- package/dist/components/ModelListManager.js +0 -140
- package/dist/components/ModelListManager.js.map +0 -7
- package/dist/components/ModelSelector.js +0 -1985
- package/dist/components/ModelSelector.js.map +0 -7
- package/dist/components/ModelStatusDisplay.js +0 -87
- package/dist/components/ModelStatusDisplay.js.map +0 -7
- package/dist/components/Onboarding.js +0 -153
- package/dist/components/Onboarding.js.map +0 -7
- package/dist/components/PressEnterToContinue.js +0 -10
- package/dist/components/PressEnterToContinue.js.map +0 -7
- package/dist/components/PromptInput.js +0 -488
- package/dist/components/PromptInput.js.map +0 -7
- package/dist/components/SentryErrorBoundary.js +0 -27
- package/dist/components/SentryErrorBoundary.js.map +0 -7
- package/dist/components/Spinner.js +0 -101
- package/dist/components/Spinner.js.map +0 -7
- package/dist/components/StickerRequestForm.js +0 -7
- package/dist/components/StickerRequestForm.js.map +0 -7
- package/dist/components/StructuredDiff.js +0 -148
- package/dist/components/StructuredDiff.js.map +0 -7
- package/dist/components/TextInput.js +0 -100
- package/dist/components/TextInput.js.map +0 -7
- package/dist/components/TodoItem.js +0 -35
- package/dist/components/TodoItem.js.map +0 -7
- package/dist/components/TokenWarning.js +0 -19
- package/dist/components/TokenWarning.js.map +0 -7
- package/dist/components/ToolUseLoader.js +0 -24
- package/dist/components/ToolUseLoader.js.map +0 -7
- package/dist/components/TrustDialog.js +0 -76
- package/dist/components/TrustDialog.js.map +0 -7
- package/dist/components/binary-feedback/BinaryFeedback.js +0 -50
- package/dist/components/binary-feedback/BinaryFeedback.js.map +0 -7
- package/dist/components/binary-feedback/BinaryFeedbackOption.js +0 -94
- package/dist/components/binary-feedback/BinaryFeedbackOption.js.map +0 -7
- package/dist/components/binary-feedback/BinaryFeedbackView.js +0 -139
- package/dist/components/binary-feedback/BinaryFeedbackView.js.map +0 -7
- package/dist/components/binary-feedback/utils.js +0 -161
- package/dist/components/binary-feedback/utils.js.map +0 -7
- package/dist/components/messages/AssistantBashOutputMessage.js +0 -23
- package/dist/components/messages/AssistantBashOutputMessage.js.map +0 -7
- package/dist/components/messages/AssistantLocalCommandOutputMessage.js +0 -36
- package/dist/components/messages/AssistantLocalCommandOutputMessage.js.map +0 -7
- package/dist/components/messages/AssistantRedactedThinkingMessage.js +0 -12
- package/dist/components/messages/AssistantRedactedThinkingMessage.js.map +0 -7
- package/dist/components/messages/AssistantTextMessage.js +0 -78
- package/dist/components/messages/AssistantTextMessage.js.map +0 -7
- package/dist/components/messages/AssistantThinkingMessage.js +0 -27
- package/dist/components/messages/AssistantThinkingMessage.js.map +0 -7
- package/dist/components/messages/AssistantToolUseMessage.js +0 -91
- package/dist/components/messages/AssistantToolUseMessage.js.map +0 -7
- package/dist/components/messages/TaskProgressMessage.js +0 -11
- package/dist/components/messages/TaskProgressMessage.js.map +0 -7
- package/dist/components/messages/TaskToolMessage.js +0 -39
- package/dist/components/messages/TaskToolMessage.js.map +0 -7
- package/dist/components/messages/UserBashInputMessage.js +0 -18
- package/dist/components/messages/UserBashInputMessage.js.map +0 -7
- package/dist/components/messages/UserCommandMessage.js +0 -20
- package/dist/components/messages/UserCommandMessage.js.map +0 -7
- package/dist/components/messages/UserKodingInputMessage.js +0 -18
- package/dist/components/messages/UserKodingInputMessage.js.map +0 -7
- package/dist/components/messages/UserPromptMessage.js +0 -20
- package/dist/components/messages/UserPromptMessage.js.map +0 -7
- package/dist/components/messages/UserTextMessage.js +0 -25
- package/dist/components/messages/UserTextMessage.js.map +0 -7
- package/dist/components/messages/UserToolResultMessage/UserToolCanceledMessage.js +0 -10
- package/dist/components/messages/UserToolResultMessage/UserToolCanceledMessage.js.map +0 -7
- package/dist/components/messages/UserToolResultMessage/UserToolErrorMessage.js +0 -15
- package/dist/components/messages/UserToolResultMessage/UserToolErrorMessage.js.map +0 -7
- package/dist/components/messages/UserToolResultMessage/UserToolRejectMessage.js +0 -25
- package/dist/components/messages/UserToolResultMessage/UserToolRejectMessage.js.map +0 -7
- package/dist/components/messages/UserToolResultMessage/UserToolResultMessage.js +0 -47
- package/dist/components/messages/UserToolResultMessage/UserToolResultMessage.js.map +0 -7
- package/dist/components/messages/UserToolResultMessage/UserToolSuccessMessage.js +0 -23
- package/dist/components/messages/UserToolResultMessage/UserToolSuccessMessage.js.map +0 -7
- package/dist/components/messages/UserToolResultMessage/utils.js +0 -42
- package/dist/components/messages/UserToolResultMessage/utils.js.map +0 -7
- package/dist/components/permissions/BashPermissionRequest/BashPermissionRequest.js +0 -112
- package/dist/components/permissions/BashPermissionRequest/BashPermissionRequest.js.map +0 -7
- package/dist/components/permissions/FallbackPermissionRequest.js +0 -131
- package/dist/components/permissions/FallbackPermissionRequest.js.map +0 -7
- package/dist/components/permissions/FileEditPermissionRequest/FileEditPermissionRequest.js +0 -159
- package/dist/components/permissions/FileEditPermissionRequest/FileEditPermissionRequest.js.map +0 -7
- package/dist/components/permissions/FileEditPermissionRequest/FileEditToolDiff.js +0 -58
- package/dist/components/permissions/FileEditPermissionRequest/FileEditToolDiff.js.map +0 -7
- package/dist/components/permissions/FileWritePermissionRequest/FileWritePermissionRequest.js +0 -153
- package/dist/components/permissions/FileWritePermissionRequest/FileWritePermissionRequest.js.map +0 -7
- package/dist/components/permissions/FileWritePermissionRequest/FileWriteToolDiff.js +0 -70
- package/dist/components/permissions/FileWritePermissionRequest/FileWriteToolDiff.js.map +0 -7
- package/dist/components/permissions/FilesystemPermissionRequest/FilesystemPermissionRequest.js +0 -212
- package/dist/components/permissions/FilesystemPermissionRequest/FilesystemPermissionRequest.js.map +0 -7
- package/dist/components/permissions/PermissionRequest.js +0 -70
- package/dist/components/permissions/PermissionRequest.js.map +0 -7
- package/dist/components/permissions/PermissionRequestTitle.js +0 -52
- package/dist/components/permissions/PermissionRequestTitle.js.map +0 -7
- package/dist/components/permissions/hooks.js +0 -28
- package/dist/components/permissions/hooks.js.map +0 -7
- package/dist/components/permissions/toolUseOptions.js +0 -46
- package/dist/components/permissions/toolUseOptions.js.map +0 -7
- package/dist/components/permissions/utils.js +0 -21
- package/dist/components/permissions/utils.js.map +0 -7
- package/dist/constants/betas.js +0 -11
- package/dist/constants/betas.js.map +0 -7
- package/dist/constants/claude-asterisk-ascii-art.js +0 -242
- package/dist/constants/claude-asterisk-ascii-art.js.map +0 -7
- package/dist/constants/figures.js +0 -6
- package/dist/constants/figures.js.map +0 -7
- package/dist/constants/keys.js +0 -7
- package/dist/constants/keys.js.map +0 -7
- package/dist/constants/macros.js +0 -13
- package/dist/constants/macros.js.map +0 -7
- package/dist/constants/modelCapabilities.js +0 -154
- package/dist/constants/modelCapabilities.js.map +0 -7
- package/dist/constants/models.js +0 -1034
- package/dist/constants/models.js.map +0 -7
- package/dist/constants/oauth.js +0 -18
- package/dist/constants/oauth.js.map +0 -7
- package/dist/constants/product.js +0 -26
- package/dist/constants/product.js.map +0 -7
- package/dist/constants/prompts.js +0 -168
- package/dist/constants/prompts.js.map +0 -7
- package/dist/constants/releaseNotes.js +0 -9
- package/dist/constants/releaseNotes.js.map +0 -7
- package/dist/context/PermissionContext.js +0 -111
- package/dist/context/PermissionContext.js.map +0 -7
- package/dist/context.js +0 -259
- package/dist/context.js.map +0 -7
- package/dist/cost-tracker.js.map +0 -7
- package/dist/entrypoints/cli.js +0 -1107
- package/dist/entrypoints/cli.js.map +0 -7
- package/dist/entrypoints/mcp.js +0 -150
- package/dist/entrypoints/mcp.js.map +0 -7
- package/dist/history.js +0 -25
- package/dist/history.js.map +0 -7
- package/dist/hooks/useApiKeyVerification.js +0 -12
- package/dist/hooks/useApiKeyVerification.js.map +0 -7
- package/dist/hooks/useArrowKeyHistory.js +0 -50
- package/dist/hooks/useArrowKeyHistory.js.map +0 -7
- package/dist/hooks/useCanUseTool.js +0 -112
- package/dist/hooks/useCanUseTool.js.map +0 -7
- package/dist/hooks/useCancelRequest.js +0 -30
- package/dist/hooks/useCancelRequest.js.map +0 -7
- package/dist/hooks/useDoublePress.js +0 -31
- package/dist/hooks/useDoublePress.js.map +0 -7
- package/dist/hooks/useExitOnCtrlCD.js +0 -26
- package/dist/hooks/useExitOnCtrlCD.js.map +0 -7
- package/dist/hooks/useInterval.js +0 -18
- package/dist/hooks/useInterval.js.map +0 -7
- package/dist/hooks/useLogMessages.js +0 -14
- package/dist/hooks/useLogMessages.js.map +0 -7
- package/dist/hooks/useLogStartupTime.js +0 -15
- package/dist/hooks/useLogStartupTime.js.map +0 -7
- package/dist/hooks/useNotifyAfterTimeout.js +0 -42
- package/dist/hooks/useNotifyAfterTimeout.js.map +0 -7
- package/dist/hooks/usePermissionRequestLogging.js +0 -28
- package/dist/hooks/usePermissionRequestLogging.js.map +0 -7
- package/dist/hooks/useTerminalSize.js +0 -38
- package/dist/hooks/useTerminalSize.js.map +0 -7
- package/dist/hooks/useTextInput.js +0 -250
- package/dist/hooks/useTextInput.js.map +0 -7
- package/dist/hooks/useUnifiedCompletion.js +0 -929
- package/dist/hooks/useUnifiedCompletion.js.map +0 -7
- package/dist/messages.js +0 -33
- package/dist/messages.js.map +0 -7
- package/dist/permissions.js +0 -194
- package/dist/permissions.js.map +0 -7
- package/dist/query.js +0 -492
- package/dist/query.js.map +0 -7
- package/dist/screens/ConfigureNpmPrefix.js +0 -128
- package/dist/screens/ConfigureNpmPrefix.js.map +0 -7
- package/dist/screens/Doctor.js +0 -22
- package/dist/screens/Doctor.js.map +0 -7
- package/dist/screens/LogList.js +0 -55
- package/dist/screens/LogList.js.map +0 -7
- package/dist/screens/REPL.js +0 -593
- package/dist/screens/REPL.js.map +0 -7
- package/dist/screens/ResumeConversation.js +0 -56
- package/dist/screens/ResumeConversation.js.map +0 -7
- package/dist/services/adapters/base.js +0 -29
- package/dist/services/adapters/base.js.map +0 -7
- package/dist/services/adapters/chatCompletions.js +0 -69
- package/dist/services/adapters/chatCompletions.js.map +0 -7
- package/dist/services/adapters/responsesAPI.js +0 -126
- package/dist/services/adapters/responsesAPI.js.map +0 -7
- package/dist/services/browserMocks.js +0 -48
- package/dist/services/browserMocks.js.map +0 -7
- package/dist/services/claude.js +0 -1605
- package/dist/services/claude.js.map +0 -7
- package/dist/services/customCommands.js +0 -359
- package/dist/services/customCommands.js.map +0 -7
- package/dist/services/fileFreshness.js +0 -280
- package/dist/services/fileFreshness.js.map +0 -7
- package/dist/services/gpt5ConnectionTest.js +0 -248
- package/dist/services/gpt5ConnectionTest.js.map +0 -7
- package/dist/services/mcpClient.js +0 -435
- package/dist/services/mcpClient.js.map +0 -7
- package/dist/services/mcpServerApproval.js +0 -55
- package/dist/services/mcpServerApproval.js.map +0 -7
- package/dist/services/mentionProcessor.js.map +0 -7
- package/dist/services/modelAdapterFactory.js +0 -47
- package/dist/services/modelAdapterFactory.js.map +0 -7
- package/dist/services/notifier.js +0 -35
- package/dist/services/notifier.js.map +0 -7
- package/dist/services/oauth.js +0 -259
- package/dist/services/oauth.js.map +0 -7
- package/dist/services/openai.js.map +0 -7
- package/dist/services/responseStateManager.js +0 -68
- package/dist/services/responseStateManager.js.map +0 -7
- package/dist/services/sentry.js +0 -9
- package/dist/services/sentry.js.map +0 -7
- package/dist/services/statsig.js +0 -112
- package/dist/services/statsig.js.map +0 -7
- package/dist/services/statsigStorage.js +0 -75
- package/dist/services/statsigStorage.js.map +0 -7
- package/dist/services/systemReminder.js.map +0 -7
- package/dist/services/vcr.js +0 -133
- package/dist/services/vcr.js.map +0 -7
- package/dist/tools/ArchitectTool/ArchitectTool.js +0 -119
- package/dist/tools/ArchitectTool/ArchitectTool.js.map +0 -7
- package/dist/tools/ArchitectTool/prompt.js +0 -18
- package/dist/tools/ArchitectTool/prompt.js.map +0 -7
- package/dist/tools/AskExpertModelTool/AskExpertModelTool.js +0 -423
- package/dist/tools/AskExpertModelTool/AskExpertModelTool.js.map +0 -7
- package/dist/tools/BashTool/BashTool.js +0 -188
- package/dist/tools/BashTool/BashTool.js.map +0 -7
- package/dist/tools/BashTool/BashToolResultMessage.js +0 -21
- package/dist/tools/BashTool/BashToolResultMessage.js.map +0 -7
- package/dist/tools/BashTool/OutputLine.js +0 -30
- package/dist/tools/BashTool/OutputLine.js.map +0 -7
- package/dist/tools/BashTool/prompt.js +0 -179
- package/dist/tools/BashTool/prompt.js.map +0 -7
- package/dist/tools/BashTool/utils.js +0 -51
- package/dist/tools/BashTool/utils.js.map +0 -7
- package/dist/tools/FileEditTool/FileEditTool.js +0 -228
- package/dist/tools/FileEditTool/FileEditTool.js.map +0 -7
- package/dist/tools/FileEditTool/prompt.js +0 -54
- package/dist/tools/FileEditTool/prompt.js.map +0 -7
- package/dist/tools/FileEditTool/utils.js +0 -42
- package/dist/tools/FileEditTool/utils.js.map +0 -7
- package/dist/tools/FileReadTool/FileReadTool.js +0 -272
- package/dist/tools/FileReadTool/FileReadTool.js.map +0 -7
- package/dist/tools/FileReadTool/prompt.js +0 -10
- package/dist/tools/FileReadTool/prompt.js.map +0 -7
- package/dist/tools/FileWriteTool/FileWriteTool.js +0 -204
- package/dist/tools/FileWriteTool/FileWriteTool.js.map +0 -7
- package/dist/tools/FileWriteTool/prompt.js +0 -14
- package/dist/tools/FileWriteTool/prompt.js.map +0 -7
- package/dist/tools/GlobTool/GlobTool.js +0 -88
- package/dist/tools/GlobTool/GlobTool.js.map +0 -7
- package/dist/tools/GlobTool/prompt.js +0 -12
- package/dist/tools/GlobTool/prompt.js.map +0 -7
- package/dist/tools/GrepTool/GrepTool.js +0 -107
- package/dist/tools/GrepTool/GrepTool.js.map +0 -7
- package/dist/tools/GrepTool/prompt.js +0 -15
- package/dist/tools/GrepTool/prompt.js.map +0 -7
- package/dist/tools/MCPTool/MCPTool.js +0 -90
- package/dist/tools/MCPTool/MCPTool.js.map +0 -7
- package/dist/tools/MCPTool/prompt.js +0 -7
- package/dist/tools/MCPTool/prompt.js.map +0 -7
- package/dist/tools/MemoryReadTool/MemoryReadTool.js +0 -103
- package/dist/tools/MemoryReadTool/MemoryReadTool.js.map +0 -7
- package/dist/tools/MemoryReadTool/prompt.js +0 -7
- package/dist/tools/MemoryReadTool/prompt.js.map +0 -7
- package/dist/tools/MemoryWriteTool/MemoryWriteTool.js +0 -77
- package/dist/tools/MemoryWriteTool/MemoryWriteTool.js.map +0 -7
- package/dist/tools/MemoryWriteTool/prompt.js +0 -7
- package/dist/tools/MemoryWriteTool/prompt.js.map +0 -7
- package/dist/tools/MultiEditTool/MultiEditTool.js +0 -308
- package/dist/tools/MultiEditTool/MultiEditTool.js.map +0 -7
- package/dist/tools/MultiEditTool/prompt.js +0 -48
- package/dist/tools/MultiEditTool/prompt.js.map +0 -7
- package/dist/tools/NotebookEditTool/NotebookEditTool.js +0 -238
- package/dist/tools/NotebookEditTool/NotebookEditTool.js.map +0 -7
- package/dist/tools/NotebookEditTool/prompt.js +0 -7
- package/dist/tools/NotebookEditTool/prompt.js.map +0 -7
- package/dist/tools/NotebookReadTool/NotebookReadTool.js +0 -212
- package/dist/tools/NotebookReadTool/NotebookReadTool.js.map +0 -7
- package/dist/tools/NotebookReadTool/prompt.js +0 -7
- package/dist/tools/NotebookReadTool/prompt.js.map +0 -7
- package/dist/tools/StickerRequestTool/StickerRequestTool.js +0 -86
- package/dist/tools/StickerRequestTool/StickerRequestTool.js.map +0 -7
- package/dist/tools/StickerRequestTool/prompt.js +0 -23
- package/dist/tools/StickerRequestTool/prompt.js.map +0 -7
- package/dist/tools/TaskTool/TaskTool.js +0 -351
- package/dist/tools/TaskTool/TaskTool.js.map +0 -7
- package/dist/tools/TaskTool/constants.js +0 -5
- package/dist/tools/TaskTool/constants.js.map +0 -7
- package/dist/tools/TaskTool/prompt.js +0 -82
- package/dist/tools/TaskTool/prompt.js.map +0 -7
- package/dist/tools/ThinkTool/ThinkTool.js +0 -48
- package/dist/tools/ThinkTool/ThinkTool.js.map +0 -7
- package/dist/tools/ThinkTool/prompt.js +0 -16
- package/dist/tools/ThinkTool/prompt.js.map +0 -7
- package/dist/tools/TodoWriteTool/TodoWriteTool.js +0 -216
- package/dist/tools/TodoWriteTool/TodoWriteTool.js.map +0 -7
- package/dist/tools/TodoWriteTool/prompt.js +0 -66
- package/dist/tools/TodoWriteTool/prompt.js.map +0 -7
- package/dist/tools/URLFetcherTool/URLFetcherTool.js +0 -137
- package/dist/tools/URLFetcherTool/URLFetcherTool.js.map +0 -7
- package/dist/tools/URLFetcherTool/cache.js +0 -45
- package/dist/tools/URLFetcherTool/cache.js.map +0 -7
- package/dist/tools/URLFetcherTool/htmlToMarkdown.js +0 -42
- package/dist/tools/URLFetcherTool/htmlToMarkdown.js.map +0 -7
- package/dist/tools/URLFetcherTool/prompt.js +0 -22
- package/dist/tools/URLFetcherTool/prompt.js.map +0 -7
- package/dist/tools/WebSearchTool/WebSearchTool.js +0 -86
- package/dist/tools/WebSearchTool/WebSearchTool.js.map +0 -7
- package/dist/tools/WebSearchTool/prompt.js +0 -17
- package/dist/tools/WebSearchTool/prompt.js.map +0 -7
- package/dist/tools/WebSearchTool/searchProviders.js +0 -48
- package/dist/tools/WebSearchTool/searchProviders.js.map +0 -7
- package/dist/tools/lsTool/lsTool.js +0 -201
- package/dist/tools/lsTool/lsTool.js.map +0 -7
- package/dist/tools/lsTool/prompt.js +0 -5
- package/dist/tools/lsTool/prompt.js.map +0 -7
- package/dist/tools.js +0 -64
- package/dist/tools.js.map +0 -7
- package/dist/types/PermissionMode.js +0 -82
- package/dist/types/PermissionMode.js.map +0 -7
- package/dist/types/RequestContext.js +0 -47
- package/dist/types/RequestContext.js.map +0 -7
- package/dist/types/common.d.js +0 -1
- package/dist/types/conversation.js +0 -1
- package/dist/types/logs.js +0 -1
- package/dist/types/modelCapabilities.js +0 -1
- package/dist/types/notebook.js +0 -1
- package/dist/utils/Cursor.js +0 -313
- package/dist/utils/Cursor.js.map +0 -7
- package/dist/utils/PersistentShell.js +0 -382
- package/dist/utils/PersistentShell.js.map +0 -7
- package/dist/utils/advancedFuzzyMatcher.js +0 -206
- package/dist/utils/advancedFuzzyMatcher.js.map +0 -7
- package/dist/utils/agentLoader.js +0 -199
- package/dist/utils/agentLoader.js.map +0 -7
- package/dist/utils/agentStorage.js +0 -59
- package/dist/utils/agentStorage.js.map +0 -7
- package/dist/utils/array.js +0 -7
- package/dist/utils/array.js.map +0 -7
- package/dist/utils/ask.js +0 -77
- package/dist/utils/ask.js.map +0 -7
- package/dist/utils/auth.js +0 -11
- package/dist/utils/auth.js.map +0 -7
- package/dist/utils/autoCompactCore.js +0 -149
- package/dist/utils/autoCompactCore.js.map +0 -7
- package/dist/utils/autoUpdater.js.map +0 -7
- package/dist/utils/betas.js +0 -21
- package/dist/utils/betas.js.map +0 -7
- package/dist/utils/browser.js +0 -15
- package/dist/utils/browser.js.map +0 -7
- package/dist/utils/cleanup.js +0 -54
- package/dist/utils/cleanup.js.map +0 -7
- package/dist/utils/commands.js +0 -207
- package/dist/utils/commands.js.map +0 -7
- package/dist/utils/commonUnixCommands.js +0 -687
- package/dist/utils/commonUnixCommands.js.map +0 -7
- package/dist/utils/config.js.map +0 -7
- package/dist/utils/conversationRecovery.js +0 -35
- package/dist/utils/conversationRecovery.js.map +0 -7
- package/dist/utils/debugLogger.js.map +0 -7
- package/dist/utils/diff.js +0 -32
- package/dist/utils/diff.js.map +0 -7
- package/dist/utils/env.js +0 -44
- package/dist/utils/env.js.map +0 -7
- package/dist/utils/errors.js +0 -23
- package/dist/utils/errors.js.map +0 -7
- package/dist/utils/exampleCommands.js +0 -80
- package/dist/utils/exampleCommands.js.map +0 -7
- package/dist/utils/execFileNoThrow.js +0 -44
- package/dist/utils/execFileNoThrow.js.map +0 -7
- package/dist/utils/expertChatStorage.js +0 -78
- package/dist/utils/expertChatStorage.js.map +0 -7
- package/dist/utils/file.js +0 -282
- package/dist/utils/file.js.map +0 -7
- package/dist/utils/fileRecoveryCore.js +0 -41
- package/dist/utils/fileRecoveryCore.js.map +0 -7
- package/dist/utils/format.js +0 -41
- package/dist/utils/format.js.map +0 -7
- package/dist/utils/fuzzyMatcher.js +0 -252
- package/dist/utils/fuzzyMatcher.js.map +0 -7
- package/dist/utils/generators.js +0 -46
- package/dist/utils/generators.js.map +0 -7
- package/dist/utils/git.js +0 -83
- package/dist/utils/git.js.map +0 -7
- package/dist/utils/globalLogger.js +0 -54
- package/dist/utils/globalLogger.js.map +0 -7
- package/dist/utils/http.js +0 -7
- package/dist/utils/http.js.map +0 -7
- package/dist/utils/imagePaste.js +0 -29
- package/dist/utils/imagePaste.js.map +0 -7
- package/dist/utils/json.js +0 -16
- package/dist/utils/json.js.map +0 -7
- package/dist/utils/log.js +0 -298
- package/dist/utils/log.js.map +0 -7
- package/dist/utils/markdown.js +0 -187
- package/dist/utils/markdown.js.map +0 -7
- package/dist/utils/messageContextManager.js +0 -195
- package/dist/utils/messageContextManager.js.map +0 -7
- package/dist/utils/messages.js +0 -633
- package/dist/utils/messages.js.map +0 -7
- package/dist/utils/model.js.map +0 -7
- package/dist/utils/permissions/filesystem.js +0 -80
- package/dist/utils/permissions/filesystem.js.map +0 -7
- package/dist/utils/responseState.js +0 -20
- package/dist/utils/responseState.js.map +0 -7
- package/dist/utils/ripgrep.js +0 -131
- package/dist/utils/ripgrep.js.map +0 -7
- package/dist/utils/secureFile.js +0 -483
- package/dist/utils/secureFile.js.map +0 -7
- package/dist/utils/sessionState.js +0 -31
- package/dist/utils/sessionState.js.map +0 -7
- package/dist/utils/state.js +0 -24
- package/dist/utils/state.js.map +0 -7
- package/dist/utils/style.js +0 -31
- package/dist/utils/style.js.map +0 -7
- package/dist/utils/terminal.js +0 -43
- package/dist/utils/terminal.js.map +0 -7
- package/dist/utils/theme.js.map +0 -7
- package/dist/utils/thinking.js +0 -103
- package/dist/utils/thinking.js.map +0 -7
- package/dist/utils/todoStorage.js +0 -291
- package/dist/utils/todoStorage.js.map +0 -7
- package/dist/utils/tokens.js +0 -30
- package/dist/utils/tokens.js.map +0 -7
- package/dist/utils/toolExecutionController.js +0 -109
- package/dist/utils/toolExecutionController.js.map +0 -7
- package/dist/utils/unaryLogging.js +0 -14
- package/dist/utils/unaryLogging.js.map +0 -7
- package/dist/utils/user.js +0 -40
- package/dist/utils/user.js.map +0 -7
- package/dist/utils/validate.js +0 -132
- package/dist/utils/validate.js.map +0 -7
- /package/dist/{Tool.js.map → REPL-CW7AYLVL.js.map} +0 -0
- /package/dist/{components/CustomSelect/theme.js.map → autoUpdater-ITPIHCOI.js.map} +0 -0
- /package/dist/{types/common.d.js.map → chunk-JC6NCUG5.js.map} +0 -0
- /package/dist/{types/conversation.js.map → commands-2BF2CJ3A.js.map} +0 -0
- /package/dist/{types/logs.js.map → config-RUSD6G5Y.js.map} +0 -0
- /package/dist/{types/modelCapabilities.js.map → context-6FXPETYH.js.map} +0 -0
- /package/dist/{types/notebook.js.map → costTracker-6SL26FDB.js.map} +0 -0
|
@@ -0,0 +1,1609 @@
|
|
|
1
|
+
import { createRequire as __kodeCreateRequire } from "node:module";
|
|
2
|
+
const require = __kodeCreateRequire(import.meta.url);
|
|
3
|
+
import {
|
|
4
|
+
getSettingsFileCandidates,
|
|
5
|
+
loadSettingsWithLegacyFallback
|
|
6
|
+
} from "./chunk-HCBELH4J.js";
|
|
7
|
+
import {
|
|
8
|
+
getSessionPlugins
|
|
9
|
+
} from "./chunk-S3J2TLV6.js";
|
|
10
|
+
import {
|
|
11
|
+
getTheme
|
|
12
|
+
} from "./chunk-7U7L4NMD.js";
|
|
13
|
+
import {
|
|
14
|
+
addMcprcServerForTesting,
|
|
15
|
+
getCurrentProjectConfig,
|
|
16
|
+
getGlobalConfig,
|
|
17
|
+
getProjectMcpServerDefinitions,
|
|
18
|
+
removeMcprcServerForTesting,
|
|
19
|
+
safeParseJSON,
|
|
20
|
+
saveCurrentProjectConfig,
|
|
21
|
+
saveGlobalConfig
|
|
22
|
+
} from "./chunk-LC4TVOCZ.js";
|
|
23
|
+
import {
|
|
24
|
+
PRODUCT_COMMAND,
|
|
25
|
+
PRODUCT_NAME,
|
|
26
|
+
getCwd,
|
|
27
|
+
logMCPError
|
|
28
|
+
} from "./chunk-YXYYDIMI.js";
|
|
29
|
+
|
|
30
|
+
// src/services/mcp/client.ts
|
|
31
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
|
|
32
|
+
import { resolve } from "path";
|
|
33
|
+
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
34
|
+
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
35
|
+
import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
|
|
36
|
+
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
37
|
+
import { WebSocketClientTransport } from "@modelcontextprotocol/sdk/client/websocket.js";
|
|
38
|
+
import { memoize, pickBy } from "lodash-es";
|
|
39
|
+
|
|
40
|
+
// src/services/mcp/internal/jsonc.ts
|
|
41
|
+
function stripJsonComments(input) {
|
|
42
|
+
let out = "";
|
|
43
|
+
let inString = false;
|
|
44
|
+
let escaped = false;
|
|
45
|
+
let inLineComment = false;
|
|
46
|
+
let inBlockComment = false;
|
|
47
|
+
for (let i = 0; i < input.length; i++) {
|
|
48
|
+
const ch = input[i];
|
|
49
|
+
const next = i + 1 < input.length ? input[i + 1] : "";
|
|
50
|
+
if (inLineComment) {
|
|
51
|
+
if (ch === "\n") {
|
|
52
|
+
inLineComment = false;
|
|
53
|
+
out += ch;
|
|
54
|
+
}
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
if (inBlockComment) {
|
|
58
|
+
if (ch === "*" && next === "/") {
|
|
59
|
+
inBlockComment = false;
|
|
60
|
+
i++;
|
|
61
|
+
}
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
if (inString) {
|
|
65
|
+
out += ch;
|
|
66
|
+
if (escaped) {
|
|
67
|
+
escaped = false;
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
if (ch === "\\") {
|
|
71
|
+
escaped = true;
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
if (ch === '"') inString = false;
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
if (ch === '"') {
|
|
78
|
+
inString = true;
|
|
79
|
+
out += ch;
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
if (ch === "/" && next === "/") {
|
|
83
|
+
inLineComment = true;
|
|
84
|
+
i++;
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
if (ch === "/" && next === "*") {
|
|
88
|
+
inBlockComment = true;
|
|
89
|
+
i++;
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
out += ch;
|
|
93
|
+
}
|
|
94
|
+
return out;
|
|
95
|
+
}
|
|
96
|
+
function parseJsonOrJsonc(text) {
|
|
97
|
+
const raw = String(text ?? "");
|
|
98
|
+
if (!raw.trim()) return null;
|
|
99
|
+
try {
|
|
100
|
+
return JSON.parse(raw);
|
|
101
|
+
} catch {
|
|
102
|
+
try {
|
|
103
|
+
return JSON.parse(stripJsonComments(raw));
|
|
104
|
+
} catch {
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// src/services/mcp/discovery.ts
|
|
111
|
+
import { existsSync, readFileSync, writeFileSync } from "fs";
|
|
112
|
+
import { join } from "path";
|
|
113
|
+
function expandTemplateString(value, pluginRoot) {
|
|
114
|
+
return value.replace(/\$\{([^}]+)\}/g, (match, key) => {
|
|
115
|
+
const k = String(key ?? "").trim();
|
|
116
|
+
if (!k) return match;
|
|
117
|
+
if (k === "CLAUDE_PLUGIN_ROOT") return pluginRoot;
|
|
118
|
+
const env = process.env[k];
|
|
119
|
+
return env !== void 0 ? env : match;
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
function expandTemplateDeep(value, pluginRoot) {
|
|
123
|
+
if (typeof value === "string") return expandTemplateString(value, pluginRoot);
|
|
124
|
+
if (Array.isArray(value))
|
|
125
|
+
return value.map((v) => expandTemplateDeep(v, pluginRoot));
|
|
126
|
+
if (value && typeof value === "object") {
|
|
127
|
+
const out = {};
|
|
128
|
+
for (const [k, v] of Object.entries(value)) {
|
|
129
|
+
out[k] = expandTemplateDeep(v, pluginRoot);
|
|
130
|
+
}
|
|
131
|
+
return out;
|
|
132
|
+
}
|
|
133
|
+
return value;
|
|
134
|
+
}
|
|
135
|
+
function listPluginMCPServers() {
|
|
136
|
+
const plugins = getSessionPlugins();
|
|
137
|
+
if (plugins.length === 0) return {};
|
|
138
|
+
const out = {};
|
|
139
|
+
for (const plugin of plugins) {
|
|
140
|
+
const pluginRoot = plugin.rootDir;
|
|
141
|
+
const pluginName = plugin.name;
|
|
142
|
+
const configs = [];
|
|
143
|
+
for (const configPath of plugin.mcpConfigFiles ?? []) {
|
|
144
|
+
try {
|
|
145
|
+
const raw = readFileSync(configPath, "utf8");
|
|
146
|
+
const parsed = parseJsonOrJsonc(raw);
|
|
147
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
|
|
148
|
+
continue;
|
|
149
|
+
const rawServers = parsed.mcpServers && typeof parsed.mcpServers === "object" && !Array.isArray(parsed.mcpServers) ? parsed.mcpServers : parsed;
|
|
150
|
+
if (!rawServers || typeof rawServers !== "object" || Array.isArray(rawServers))
|
|
151
|
+
continue;
|
|
152
|
+
const servers = {};
|
|
153
|
+
for (const [name, cfg] of Object.entries(rawServers)) {
|
|
154
|
+
if (!cfg || typeof cfg !== "object" || Array.isArray(cfg)) continue;
|
|
155
|
+
servers[name] = expandTemplateDeep(cfg, pluginRoot);
|
|
156
|
+
}
|
|
157
|
+
configs.push(servers);
|
|
158
|
+
} catch {
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
const manifestRaw = plugin.manifest?.mcpServers;
|
|
163
|
+
if (manifestRaw && typeof manifestRaw === "object" && !Array.isArray(manifestRaw)) {
|
|
164
|
+
const rawServers = manifestRaw.mcpServers && typeof manifestRaw.mcpServers === "object" && !Array.isArray(manifestRaw.mcpServers) ? manifestRaw.mcpServers : manifestRaw;
|
|
165
|
+
if (rawServers && typeof rawServers === "object" && !Array.isArray(rawServers)) {
|
|
166
|
+
const servers = {};
|
|
167
|
+
for (const [name, cfg] of Object.entries(rawServers)) {
|
|
168
|
+
if (!cfg || typeof cfg !== "object" || Array.isArray(cfg)) continue;
|
|
169
|
+
servers[name] = expandTemplateDeep(cfg, pluginRoot);
|
|
170
|
+
}
|
|
171
|
+
configs.push(servers);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
const merged = Object.assign({}, ...configs);
|
|
175
|
+
for (const [serverName, cfg] of Object.entries(merged)) {
|
|
176
|
+
const fullName = `plugin_${pluginName}_${serverName}`;
|
|
177
|
+
out[fullName] = cfg;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return out;
|
|
181
|
+
}
|
|
182
|
+
function parseEnvVars(rawEnvArgs) {
|
|
183
|
+
const parsedEnv = {};
|
|
184
|
+
if (rawEnvArgs) {
|
|
185
|
+
for (const envStr of rawEnvArgs) {
|
|
186
|
+
const [key, ...valueParts] = envStr.split("=");
|
|
187
|
+
if (!key || valueParts.length === 0) {
|
|
188
|
+
throw new Error(
|
|
189
|
+
`Invalid environment variable format: ${envStr}, environment variables should be added as: -e KEY1=value1 -e KEY2=value2`
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
parsedEnv[key] = valueParts.join("=");
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return parsedEnv;
|
|
196
|
+
}
|
|
197
|
+
var VALID_SCOPES = ["project", "global", "mcprc", "mcpjson"];
|
|
198
|
+
var EXTERNAL_SCOPES = [
|
|
199
|
+
"project",
|
|
200
|
+
"global",
|
|
201
|
+
"mcprc",
|
|
202
|
+
"mcpjson"
|
|
203
|
+
];
|
|
204
|
+
function ensureConfigScope(scope) {
|
|
205
|
+
if (!scope) return "project";
|
|
206
|
+
const scopesToCheck = process.env.USER_TYPE === "external" ? EXTERNAL_SCOPES : VALID_SCOPES;
|
|
207
|
+
if (!scopesToCheck.includes(scope)) {
|
|
208
|
+
throw new Error(
|
|
209
|
+
`Invalid scope: ${scope}. Must be one of: ${scopesToCheck.join(", ")}`
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
return scope;
|
|
213
|
+
}
|
|
214
|
+
function addMcpServer(name, server, scope = "project") {
|
|
215
|
+
if (scope === "mcprc") {
|
|
216
|
+
if (process.env.NODE_ENV === "test") {
|
|
217
|
+
addMcprcServerForTesting(name, server);
|
|
218
|
+
} else {
|
|
219
|
+
const mcprcPath = join(getCwd(), ".mcprc");
|
|
220
|
+
let mcprcConfig = {};
|
|
221
|
+
if (existsSync(mcprcPath)) {
|
|
222
|
+
try {
|
|
223
|
+
const mcprcContent = readFileSync(mcprcPath, "utf-8");
|
|
224
|
+
const existingConfig = safeParseJSON(mcprcContent);
|
|
225
|
+
if (existingConfig && typeof existingConfig === "object") {
|
|
226
|
+
mcprcConfig = existingConfig;
|
|
227
|
+
}
|
|
228
|
+
} catch {
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
mcprcConfig[name] = server;
|
|
232
|
+
try {
|
|
233
|
+
writeFileSync(mcprcPath, JSON.stringify(mcprcConfig, null, 2), "utf-8");
|
|
234
|
+
} catch (error) {
|
|
235
|
+
throw new Error(`Failed to write to .mcprc: ${error}`);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
} else if (scope === "mcpjson") {
|
|
239
|
+
const mcpJsonPath = join(getCwd(), ".mcp.json");
|
|
240
|
+
let config = { mcpServers: {} };
|
|
241
|
+
if (existsSync(mcpJsonPath)) {
|
|
242
|
+
try {
|
|
243
|
+
const content = readFileSync(mcpJsonPath, "utf-8");
|
|
244
|
+
const parsed = safeParseJSON(content);
|
|
245
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
246
|
+
config = parsed;
|
|
247
|
+
}
|
|
248
|
+
} catch {
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
const rawServers = config.mcpServers;
|
|
252
|
+
const servers = rawServers && typeof rawServers === "object" && !Array.isArray(rawServers) ? rawServers : {};
|
|
253
|
+
servers[name] = server;
|
|
254
|
+
config.mcpServers = servers;
|
|
255
|
+
try {
|
|
256
|
+
writeFileSync(mcpJsonPath, JSON.stringify(config, null, 2), "utf-8");
|
|
257
|
+
} catch (error) {
|
|
258
|
+
throw new Error(`Failed to write to .mcp.json: ${error}`);
|
|
259
|
+
}
|
|
260
|
+
} else if (scope === "global") {
|
|
261
|
+
const config = getGlobalConfig();
|
|
262
|
+
if (!config.mcpServers) {
|
|
263
|
+
config.mcpServers = {};
|
|
264
|
+
}
|
|
265
|
+
config.mcpServers[name] = server;
|
|
266
|
+
saveGlobalConfig(config);
|
|
267
|
+
} else {
|
|
268
|
+
const config = getCurrentProjectConfig();
|
|
269
|
+
if (!config.mcpServers) {
|
|
270
|
+
config.mcpServers = {};
|
|
271
|
+
}
|
|
272
|
+
config.mcpServers[name] = server;
|
|
273
|
+
saveCurrentProjectConfig(config);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
function removeMcpServer(name, scope = "project") {
|
|
277
|
+
if (scope === "mcprc") {
|
|
278
|
+
if (process.env.NODE_ENV === "test") {
|
|
279
|
+
removeMcprcServerForTesting(name);
|
|
280
|
+
} else {
|
|
281
|
+
const mcprcPath = join(getCwd(), ".mcprc");
|
|
282
|
+
if (!existsSync(mcprcPath)) {
|
|
283
|
+
throw new Error("No .mcprc file found in this directory");
|
|
284
|
+
}
|
|
285
|
+
try {
|
|
286
|
+
const mcprcContent = readFileSync(mcprcPath, "utf-8");
|
|
287
|
+
const mcprcConfig = safeParseJSON(mcprcContent);
|
|
288
|
+
if (!mcprcConfig || typeof mcprcConfig !== "object" || !mcprcConfig[name]) {
|
|
289
|
+
throw new Error(`No MCP server found with name: ${name} in .mcprc`);
|
|
290
|
+
}
|
|
291
|
+
delete mcprcConfig[name];
|
|
292
|
+
writeFileSync(mcprcPath, JSON.stringify(mcprcConfig, null, 2), "utf-8");
|
|
293
|
+
} catch (error) {
|
|
294
|
+
if (error instanceof Error) {
|
|
295
|
+
throw error;
|
|
296
|
+
}
|
|
297
|
+
throw new Error(`Failed to remove from .mcprc: ${error}`);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
} else if (scope === "mcpjson") {
|
|
301
|
+
const mcpJsonPath = join(getCwd(), ".mcp.json");
|
|
302
|
+
if (!existsSync(mcpJsonPath)) {
|
|
303
|
+
throw new Error("No .mcp.json file found in this directory");
|
|
304
|
+
}
|
|
305
|
+
try {
|
|
306
|
+
const content = readFileSync(mcpJsonPath, "utf-8");
|
|
307
|
+
const parsed = safeParseJSON(content);
|
|
308
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
309
|
+
throw new Error("Invalid .mcp.json format");
|
|
310
|
+
}
|
|
311
|
+
const rawServers = parsed.mcpServers;
|
|
312
|
+
if (!rawServers || typeof rawServers !== "object" || Array.isArray(rawServers)) {
|
|
313
|
+
throw new Error("Invalid .mcp.json format (missing mcpServers)");
|
|
314
|
+
}
|
|
315
|
+
const servers = rawServers;
|
|
316
|
+
if (!servers[name]) {
|
|
317
|
+
throw new Error(`No MCP server found with name: ${name} in .mcp.json`);
|
|
318
|
+
}
|
|
319
|
+
delete servers[name];
|
|
320
|
+
parsed.mcpServers = servers;
|
|
321
|
+
writeFileSync(mcpJsonPath, JSON.stringify(parsed, null, 2), "utf-8");
|
|
322
|
+
} catch (error) {
|
|
323
|
+
if (error instanceof Error) throw error;
|
|
324
|
+
throw new Error(`Failed to remove from .mcp.json: ${error}`);
|
|
325
|
+
}
|
|
326
|
+
} else if (scope === "global") {
|
|
327
|
+
const config = getGlobalConfig();
|
|
328
|
+
if (!config.mcpServers?.[name]) {
|
|
329
|
+
throw new Error(`No global MCP server found with name: ${name}`);
|
|
330
|
+
}
|
|
331
|
+
delete config.mcpServers[name];
|
|
332
|
+
saveGlobalConfig(config);
|
|
333
|
+
} else {
|
|
334
|
+
const config = getCurrentProjectConfig();
|
|
335
|
+
if (!config.mcpServers?.[name]) {
|
|
336
|
+
throw new Error(`No local MCP server found with name: ${name}`);
|
|
337
|
+
}
|
|
338
|
+
delete config.mcpServers[name];
|
|
339
|
+
saveCurrentProjectConfig(config);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
function listMCPServers() {
|
|
343
|
+
const pluginServers = listPluginMCPServers();
|
|
344
|
+
const globalConfig = getGlobalConfig();
|
|
345
|
+
const projectFileConfig = getProjectMcpServerDefinitions().servers;
|
|
346
|
+
const projectConfig = getCurrentProjectConfig();
|
|
347
|
+
return {
|
|
348
|
+
...pluginServers ?? {},
|
|
349
|
+
...globalConfig.mcpServers ?? {},
|
|
350
|
+
...projectFileConfig ?? {},
|
|
351
|
+
...projectConfig.mcpServers ?? {}
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
function getMcpServer(name) {
|
|
355
|
+
const projectConfig = getCurrentProjectConfig();
|
|
356
|
+
const projectFileDefinitions = getProjectMcpServerDefinitions();
|
|
357
|
+
const projectFileConfig = projectFileDefinitions.servers;
|
|
358
|
+
const globalConfig = getGlobalConfig();
|
|
359
|
+
if (projectConfig.mcpServers?.[name]) {
|
|
360
|
+
return { ...projectConfig.mcpServers[name], scope: "project" };
|
|
361
|
+
}
|
|
362
|
+
if (projectFileConfig?.[name]) {
|
|
363
|
+
const source = projectFileDefinitions.sources[name];
|
|
364
|
+
const scope = source === ".mcp.json" ? "mcpjson" : "mcprc";
|
|
365
|
+
return { ...projectFileConfig[name], scope };
|
|
366
|
+
}
|
|
367
|
+
if (globalConfig.mcpServers?.[name]) {
|
|
368
|
+
return { ...globalConfig.mcpServers[name], scope: "global" };
|
|
369
|
+
}
|
|
370
|
+
return void 0;
|
|
371
|
+
}
|
|
372
|
+
function getMcprcServerStatus(serverName) {
|
|
373
|
+
const config = getCurrentProjectConfig();
|
|
374
|
+
if (config.approvedMcprcServers?.includes(serverName)) {
|
|
375
|
+
return "approved";
|
|
376
|
+
}
|
|
377
|
+
if (config.rejectedMcprcServers?.includes(serverName)) {
|
|
378
|
+
return "rejected";
|
|
379
|
+
}
|
|
380
|
+
return "pending";
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
// src/services/mcp/client.ts
|
|
384
|
+
function getMcpServerConnectionBatchSize() {
|
|
385
|
+
const raw = process.env.MCP_SERVER_CONNECTION_BATCH_SIZE;
|
|
386
|
+
const parsed = raw ? Number.parseInt(raw, 10) : NaN;
|
|
387
|
+
if (Number.isFinite(parsed) && parsed > 0 && parsed <= 50) return parsed;
|
|
388
|
+
return 3;
|
|
389
|
+
}
|
|
390
|
+
async function connectToServer(name, serverRef) {
|
|
391
|
+
const ensureWebSocketGlobal = async () => {
|
|
392
|
+
if (typeof globalThis.WebSocket === "function") return;
|
|
393
|
+
try {
|
|
394
|
+
const undici = await import("undici");
|
|
395
|
+
if (typeof undici.WebSocket === "function") {
|
|
396
|
+
;
|
|
397
|
+
globalThis.WebSocket = undici.WebSocket;
|
|
398
|
+
}
|
|
399
|
+
} catch {
|
|
400
|
+
}
|
|
401
|
+
};
|
|
402
|
+
const candidates = await (async () => {
|
|
403
|
+
switch (serverRef.type) {
|
|
404
|
+
case "sse": {
|
|
405
|
+
const ref = serverRef;
|
|
406
|
+
return [
|
|
407
|
+
{
|
|
408
|
+
kind: "sse",
|
|
409
|
+
transport: new SSEClientTransport(new URL(ref.url), {
|
|
410
|
+
...ref.headers ? { requestInit: { headers: ref.headers } } : {}
|
|
411
|
+
})
|
|
412
|
+
},
|
|
413
|
+
{
|
|
414
|
+
kind: "http",
|
|
415
|
+
transport: new StreamableHTTPClientTransport(new URL(ref.url), {
|
|
416
|
+
...ref.headers ? { requestInit: { headers: ref.headers } } : {}
|
|
417
|
+
})
|
|
418
|
+
}
|
|
419
|
+
];
|
|
420
|
+
}
|
|
421
|
+
case "sse-ide": {
|
|
422
|
+
const ref = serverRef;
|
|
423
|
+
return [
|
|
424
|
+
{
|
|
425
|
+
kind: "sse",
|
|
426
|
+
transport: new SSEClientTransport(new URL(ref.url), {
|
|
427
|
+
...ref.headers ? { requestInit: { headers: ref.headers } } : {}
|
|
428
|
+
})
|
|
429
|
+
}
|
|
430
|
+
];
|
|
431
|
+
}
|
|
432
|
+
case "http": {
|
|
433
|
+
const ref = serverRef;
|
|
434
|
+
return [
|
|
435
|
+
{
|
|
436
|
+
kind: "http",
|
|
437
|
+
transport: new StreamableHTTPClientTransport(new URL(ref.url), {
|
|
438
|
+
...ref.headers ? { requestInit: { headers: ref.headers } } : {}
|
|
439
|
+
})
|
|
440
|
+
},
|
|
441
|
+
{
|
|
442
|
+
kind: "sse",
|
|
443
|
+
transport: new SSEClientTransport(new URL(ref.url), {
|
|
444
|
+
...ref.headers ? { requestInit: { headers: ref.headers } } : {}
|
|
445
|
+
})
|
|
446
|
+
}
|
|
447
|
+
];
|
|
448
|
+
}
|
|
449
|
+
case "ws": {
|
|
450
|
+
const ref = serverRef;
|
|
451
|
+
await ensureWebSocketGlobal();
|
|
452
|
+
return [
|
|
453
|
+
{
|
|
454
|
+
kind: "ws",
|
|
455
|
+
transport: new WebSocketClientTransport(new URL(ref.url))
|
|
456
|
+
}
|
|
457
|
+
];
|
|
458
|
+
}
|
|
459
|
+
case "ws-ide": {
|
|
460
|
+
const ref = serverRef;
|
|
461
|
+
let url = ref.url;
|
|
462
|
+
if (ref.authToken) {
|
|
463
|
+
try {
|
|
464
|
+
const parsed = new URL(url);
|
|
465
|
+
if (!parsed.searchParams.has("authToken")) {
|
|
466
|
+
parsed.searchParams.set("authToken", ref.authToken);
|
|
467
|
+
url = parsed.toString();
|
|
468
|
+
}
|
|
469
|
+
} catch {
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
await ensureWebSocketGlobal();
|
|
473
|
+
return [
|
|
474
|
+
{
|
|
475
|
+
kind: "ws",
|
|
476
|
+
transport: new WebSocketClientTransport(new URL(url))
|
|
477
|
+
}
|
|
478
|
+
];
|
|
479
|
+
}
|
|
480
|
+
case "stdio":
|
|
481
|
+
default: {
|
|
482
|
+
const ref = serverRef;
|
|
483
|
+
return [
|
|
484
|
+
{
|
|
485
|
+
kind: "stdio",
|
|
486
|
+
transport: new StdioClientTransport({
|
|
487
|
+
command: ref.command,
|
|
488
|
+
args: ref.args,
|
|
489
|
+
env: {
|
|
490
|
+
...process.env,
|
|
491
|
+
...ref.env
|
|
492
|
+
},
|
|
493
|
+
stderr: "pipe"
|
|
494
|
+
})
|
|
495
|
+
}
|
|
496
|
+
];
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
})();
|
|
500
|
+
const rawTimeout = process.env.MCP_CONNECTION_TIMEOUT_MS;
|
|
501
|
+
const parsedTimeout = rawTimeout ? Number.parseInt(rawTimeout, 10) : NaN;
|
|
502
|
+
const CONNECTION_TIMEOUT_MS = Number.isFinite(parsedTimeout) ? parsedTimeout : 3e4;
|
|
503
|
+
let lastError;
|
|
504
|
+
for (const candidate of candidates) {
|
|
505
|
+
const client = new Client(
|
|
506
|
+
{
|
|
507
|
+
name: PRODUCT_COMMAND,
|
|
508
|
+
version: "0.1.0"
|
|
509
|
+
},
|
|
510
|
+
{
|
|
511
|
+
capabilities: {}
|
|
512
|
+
}
|
|
513
|
+
);
|
|
514
|
+
try {
|
|
515
|
+
const connectPromise = client.connect(candidate.transport);
|
|
516
|
+
if (CONNECTION_TIMEOUT_MS > 0) {
|
|
517
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
518
|
+
const timeoutId = setTimeout(() => {
|
|
519
|
+
reject(
|
|
520
|
+
new Error(
|
|
521
|
+
`Connection to MCP server "${name}" timed out after ${CONNECTION_TIMEOUT_MS}ms`
|
|
522
|
+
)
|
|
523
|
+
);
|
|
524
|
+
}, CONNECTION_TIMEOUT_MS);
|
|
525
|
+
connectPromise.then(
|
|
526
|
+
() => clearTimeout(timeoutId),
|
|
527
|
+
() => clearTimeout(timeoutId)
|
|
528
|
+
);
|
|
529
|
+
});
|
|
530
|
+
await Promise.race([connectPromise, timeoutPromise]);
|
|
531
|
+
} else {
|
|
532
|
+
await connectPromise;
|
|
533
|
+
}
|
|
534
|
+
if (candidate.kind === "stdio") {
|
|
535
|
+
;
|
|
536
|
+
candidate.transport.stderr?.on(
|
|
537
|
+
"data",
|
|
538
|
+
(data) => {
|
|
539
|
+
const errorText = data.toString().trim();
|
|
540
|
+
if (errorText) {
|
|
541
|
+
logMCPError(name, `Server stderr: ${errorText}`);
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
);
|
|
545
|
+
}
|
|
546
|
+
if (candidates.length > 1 && candidate !== candidates[0]) {
|
|
547
|
+
logMCPError(
|
|
548
|
+
name,
|
|
549
|
+
`Connected using fallback transport "${candidate.kind}". Consider setting the server type explicitly in your MCP config.`
|
|
550
|
+
);
|
|
551
|
+
}
|
|
552
|
+
return client;
|
|
553
|
+
} catch (error) {
|
|
554
|
+
lastError = error;
|
|
555
|
+
try {
|
|
556
|
+
await client.close();
|
|
557
|
+
} catch {
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
throw lastError instanceof Error ? lastError : new Error(`Failed to connect to MCP server "${name}"`);
|
|
562
|
+
}
|
|
563
|
+
var getClients = memoize(async () => {
|
|
564
|
+
if (process.env.CI && process.env.NODE_ENV !== "test") {
|
|
565
|
+
return [];
|
|
566
|
+
}
|
|
567
|
+
const pluginServers = listPluginMCPServers();
|
|
568
|
+
const globalServers = getGlobalConfig().mcpServers ?? {};
|
|
569
|
+
const projectFileServers = getProjectMcpServerDefinitions().servers;
|
|
570
|
+
const projectServers = getCurrentProjectConfig().mcpServers ?? {};
|
|
571
|
+
const approvedProjectFileServers = pickBy(
|
|
572
|
+
projectFileServers,
|
|
573
|
+
(_, name) => getMcprcServerStatus(name) === "approved"
|
|
574
|
+
);
|
|
575
|
+
const allServers = {
|
|
576
|
+
...pluginServers,
|
|
577
|
+
...globalServers,
|
|
578
|
+
...approvedProjectFileServers,
|
|
579
|
+
...projectServers
|
|
580
|
+
};
|
|
581
|
+
const batchSize = getMcpServerConnectionBatchSize();
|
|
582
|
+
const entries = Object.entries(allServers);
|
|
583
|
+
const results = [];
|
|
584
|
+
for (let i = 0; i < entries.length; i += batchSize) {
|
|
585
|
+
const batch = entries.slice(i, i + batchSize);
|
|
586
|
+
const batchResults = await Promise.all(
|
|
587
|
+
batch.map(async ([name, serverRef]) => {
|
|
588
|
+
try {
|
|
589
|
+
const client = await connectToServer(name, serverRef);
|
|
590
|
+
let capabilities = null;
|
|
591
|
+
try {
|
|
592
|
+
capabilities = client.getServerCapabilities();
|
|
593
|
+
} catch {
|
|
594
|
+
capabilities = null;
|
|
595
|
+
}
|
|
596
|
+
return { name, client, capabilities, type: "connected" };
|
|
597
|
+
} catch (error) {
|
|
598
|
+
logMCPError(
|
|
599
|
+
name,
|
|
600
|
+
`Connection failed: ${error instanceof Error ? error.message : String(error)}`
|
|
601
|
+
);
|
|
602
|
+
return { name, type: "failed" };
|
|
603
|
+
}
|
|
604
|
+
})
|
|
605
|
+
);
|
|
606
|
+
results.push(...batchResults);
|
|
607
|
+
}
|
|
608
|
+
return results;
|
|
609
|
+
});
|
|
610
|
+
function parseMcpServersFromCliConfigEntries(options) {
|
|
611
|
+
const out = {};
|
|
612
|
+
for (const rawEntry of options.entries) {
|
|
613
|
+
const entry = String(rawEntry ?? "").trim();
|
|
614
|
+
if (!entry) continue;
|
|
615
|
+
const resolvedPath = resolve(options.projectDir, entry);
|
|
616
|
+
const payload = existsSync2(resolvedPath) ? readFileSync2(resolvedPath, "utf8") : existsSync2(entry) ? readFileSync2(entry, "utf8") : entry;
|
|
617
|
+
const parsed = parseJsonOrJsonc(payload);
|
|
618
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) continue;
|
|
619
|
+
const rawServers = parsed.mcpServers && typeof parsed.mcpServers === "object" && !Array.isArray(parsed.mcpServers) ? parsed.mcpServers : parsed;
|
|
620
|
+
if (!rawServers || typeof rawServers !== "object" || Array.isArray(rawServers))
|
|
621
|
+
continue;
|
|
622
|
+
for (const [name, cfg] of Object.entries(rawServers)) {
|
|
623
|
+
if (!cfg || typeof cfg !== "object" || Array.isArray(cfg)) continue;
|
|
624
|
+
out[name] = cfg;
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
return out;
|
|
628
|
+
}
|
|
629
|
+
async function getClientsForCliMcpConfig(options) {
|
|
630
|
+
const projectDir = options.projectDir ?? getCwd();
|
|
631
|
+
const entries = Array.isArray(options.mcpConfig) && options.mcpConfig.length > 0 ? options.mcpConfig : [];
|
|
632
|
+
const strict = options.strictMcpConfig === true;
|
|
633
|
+
if (entries.length === 0 && !strict) {
|
|
634
|
+
return getClients();
|
|
635
|
+
}
|
|
636
|
+
const cliServers = parseMcpServersFromCliConfigEntries({
|
|
637
|
+
entries,
|
|
638
|
+
projectDir
|
|
639
|
+
});
|
|
640
|
+
const pluginServers = strict ? {} : listPluginMCPServers();
|
|
641
|
+
const globalServers = strict ? {} : getGlobalConfig().mcpServers ?? {};
|
|
642
|
+
const projectFileServers = strict ? {} : getProjectMcpServerDefinitions().servers;
|
|
643
|
+
const projectServers = strict ? {} : getCurrentProjectConfig().mcpServers ?? {};
|
|
644
|
+
const approvedProjectFileServers = strict ? {} : pickBy(projectFileServers, (_, name) => getMcprcServerStatus(name) === "approved");
|
|
645
|
+
const allServers = {
|
|
646
|
+
...pluginServers ?? {},
|
|
647
|
+
...globalServers ?? {},
|
|
648
|
+
...approvedProjectFileServers ?? {},
|
|
649
|
+
...projectServers ?? {},
|
|
650
|
+
...cliServers ?? {}
|
|
651
|
+
};
|
|
652
|
+
const batchSize = getMcpServerConnectionBatchSize();
|
|
653
|
+
const entriesToConnect = Object.entries(allServers);
|
|
654
|
+
const results = [];
|
|
655
|
+
for (let i = 0; i < entriesToConnect.length; i += batchSize) {
|
|
656
|
+
const batch = entriesToConnect.slice(i, i + batchSize);
|
|
657
|
+
const batchResults = await Promise.all(
|
|
658
|
+
batch.map(async ([name, serverRef]) => {
|
|
659
|
+
try {
|
|
660
|
+
const client = await connectToServer(name, serverRef);
|
|
661
|
+
let capabilities = null;
|
|
662
|
+
try {
|
|
663
|
+
capabilities = client.getServerCapabilities();
|
|
664
|
+
} catch {
|
|
665
|
+
capabilities = null;
|
|
666
|
+
}
|
|
667
|
+
return { name, client, capabilities, type: "connected" };
|
|
668
|
+
} catch (error) {
|
|
669
|
+
logMCPError(
|
|
670
|
+
name,
|
|
671
|
+
`Connection failed: ${error instanceof Error ? error.message : String(error)}`
|
|
672
|
+
);
|
|
673
|
+
return { name, type: "failed" };
|
|
674
|
+
}
|
|
675
|
+
})
|
|
676
|
+
);
|
|
677
|
+
results.push(...batchResults);
|
|
678
|
+
}
|
|
679
|
+
return results;
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
// src/services/mcp/tools-integration.ts
|
|
683
|
+
import { zipObject, memoize as memoize2 } from "lodash-es";
|
|
684
|
+
|
|
685
|
+
// src/tools/mcp/MCPTool/MCPTool.tsx
|
|
686
|
+
import { Box as Box2, Text as Text3 } from "ink";
|
|
687
|
+
import * as React3 from "react";
|
|
688
|
+
import { z } from "zod";
|
|
689
|
+
|
|
690
|
+
// src/ui/components/FallbackToolUseRejectedMessage.tsx
|
|
691
|
+
import * as React from "react";
|
|
692
|
+
import { Text } from "ink";
|
|
693
|
+
function FallbackToolUseRejectedMessage() {
|
|
694
|
+
return /* @__PURE__ */ React.createElement(Text, null, "\xA0\xA0\u23BF \xA0", /* @__PURE__ */ React.createElement(Text, { color: getTheme().error }, "No (tell ", PRODUCT_NAME, " what to do differently)"));
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
// src/tools/mcp/MCPTool/prompt.ts
|
|
698
|
+
var PROMPT = "";
|
|
699
|
+
var DESCRIPTION = "";
|
|
700
|
+
|
|
701
|
+
// src/tools/system/BashTool/OutputLine.tsx
|
|
702
|
+
import { Box, Text as Text2 } from "ink";
|
|
703
|
+
import * as React2 from "react";
|
|
704
|
+
|
|
705
|
+
// src/utils/sandbox/sandboxConfig.ts
|
|
706
|
+
import { homedir } from "os";
|
|
707
|
+
function parseToolRuleString(rule) {
|
|
708
|
+
const match = rule.match(/^([^(]+)\(([^)]+)\)$/);
|
|
709
|
+
if (!match) return { toolName: rule };
|
|
710
|
+
const toolName = match[1];
|
|
711
|
+
const ruleContent = match[2];
|
|
712
|
+
if (!toolName || !ruleContent) return { toolName: rule };
|
|
713
|
+
return { toolName, ruleContent };
|
|
714
|
+
}
|
|
715
|
+
function uniqueStrings(value) {
|
|
716
|
+
if (!Array.isArray(value)) return [];
|
|
717
|
+
const out = [];
|
|
718
|
+
const seen = /* @__PURE__ */ new Set();
|
|
719
|
+
for (const item of value) {
|
|
720
|
+
if (typeof item !== "string") continue;
|
|
721
|
+
const trimmed = item.trim();
|
|
722
|
+
if (!trimmed) continue;
|
|
723
|
+
if (seen.has(trimmed)) continue;
|
|
724
|
+
seen.add(trimmed);
|
|
725
|
+
out.push(trimmed);
|
|
726
|
+
}
|
|
727
|
+
return out;
|
|
728
|
+
}
|
|
729
|
+
function uniqueStringsUnion(...lists) {
|
|
730
|
+
const out = [];
|
|
731
|
+
const seen = /* @__PURE__ */ new Set();
|
|
732
|
+
for (const list of lists) {
|
|
733
|
+
for (const item of list) {
|
|
734
|
+
const trimmed = item.trim();
|
|
735
|
+
if (!trimmed) continue;
|
|
736
|
+
if (seen.has(trimmed)) continue;
|
|
737
|
+
seen.add(trimmed);
|
|
738
|
+
out.push(trimmed);
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
return out;
|
|
742
|
+
}
|
|
743
|
+
function mergeSandboxSettings(base, next) {
|
|
744
|
+
if (!base && !next) return void 0;
|
|
745
|
+
const merged = { ...base ?? {} };
|
|
746
|
+
const mergeBool = (k) => {
|
|
747
|
+
if (next && k in next && next[k] !== void 0) merged[k] = next[k];
|
|
748
|
+
};
|
|
749
|
+
mergeBool("enabled");
|
|
750
|
+
mergeBool("autoAllowBashIfSandboxed");
|
|
751
|
+
mergeBool("allowUnsandboxedCommands");
|
|
752
|
+
mergeBool("ignoreViolations");
|
|
753
|
+
mergeBool("enableWeakerNestedSandbox");
|
|
754
|
+
mergeBool("excludedCommands");
|
|
755
|
+
if (next?.network) {
|
|
756
|
+
merged.network = { ...merged.network ?? {}, ...next.network };
|
|
757
|
+
}
|
|
758
|
+
if (next?.ripgrep) {
|
|
759
|
+
merged.ripgrep = { ...merged.ripgrep ?? {}, ...next.ripgrep };
|
|
760
|
+
}
|
|
761
|
+
return merged;
|
|
762
|
+
}
|
|
763
|
+
function loadMergedSettings(options) {
|
|
764
|
+
const projectDir = options?.projectDir ?? process.cwd();
|
|
765
|
+
const homeDir = options?.homeDir;
|
|
766
|
+
const user = loadSettingsWithLegacyFallback({
|
|
767
|
+
destination: "userSettings",
|
|
768
|
+
homeDir,
|
|
769
|
+
migrateToPrimary: true
|
|
770
|
+
}).settings;
|
|
771
|
+
const project = loadSettingsWithLegacyFallback({
|
|
772
|
+
destination: "projectSettings",
|
|
773
|
+
projectDir,
|
|
774
|
+
homeDir,
|
|
775
|
+
migrateToPrimary: true
|
|
776
|
+
}).settings;
|
|
777
|
+
const local = loadSettingsWithLegacyFallback({
|
|
778
|
+
destination: "localSettings",
|
|
779
|
+
projectDir,
|
|
780
|
+
homeDir,
|
|
781
|
+
migrateToPrimary: true
|
|
782
|
+
}).settings;
|
|
783
|
+
const allow = uniqueStringsUnion(
|
|
784
|
+
uniqueStrings(user?.permissions?.allow),
|
|
785
|
+
uniqueStrings(project?.permissions?.allow),
|
|
786
|
+
uniqueStrings(local?.permissions?.allow)
|
|
787
|
+
);
|
|
788
|
+
const deny = uniqueStringsUnion(
|
|
789
|
+
uniqueStrings(user?.permissions?.deny),
|
|
790
|
+
uniqueStrings(project?.permissions?.deny),
|
|
791
|
+
uniqueStrings(local?.permissions?.deny)
|
|
792
|
+
);
|
|
793
|
+
const sandbox = mergeSandboxSettings(
|
|
794
|
+
mergeSandboxSettings(user?.sandbox, project?.sandbox),
|
|
795
|
+
local?.sandbox
|
|
796
|
+
);
|
|
797
|
+
return {
|
|
798
|
+
permissions: { allow, deny },
|
|
799
|
+
...sandbox ? { sandbox } : {}
|
|
800
|
+
};
|
|
801
|
+
}
|
|
802
|
+
function normalizeSandboxRuntimeConfigFromSettings(settings, options) {
|
|
803
|
+
const projectDir = options?.projectDir ?? process.cwd();
|
|
804
|
+
const homeDir = options?.homeDir ?? homedir();
|
|
805
|
+
const permissions = settings.permissions ?? {};
|
|
806
|
+
const allowRules = uniqueStrings(permissions.allow);
|
|
807
|
+
const denyRules = uniqueStrings(permissions.deny);
|
|
808
|
+
const explicitAllowedDomains = uniqueStrings(
|
|
809
|
+
settings.sandbox?.network?.allowedDomains
|
|
810
|
+
);
|
|
811
|
+
const allowedDomains = [...explicitAllowedDomains];
|
|
812
|
+
const deniedDomains = [];
|
|
813
|
+
for (const rule of allowRules) {
|
|
814
|
+
const parsed = parseToolRuleString(rule);
|
|
815
|
+
if (parsed?.toolName === "WebFetch" && parsed.ruleContent?.startsWith("domain:")) {
|
|
816
|
+
allowedDomains.push(parsed.ruleContent.substring(7));
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
for (const rule of denyRules) {
|
|
820
|
+
const parsed = parseToolRuleString(rule);
|
|
821
|
+
if (parsed?.toolName === "WebFetch" && parsed.ruleContent?.startsWith("domain:")) {
|
|
822
|
+
deniedDomains.push(parsed.ruleContent.substring(7));
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
const allowWrite = ["."];
|
|
826
|
+
const denyWrite = [];
|
|
827
|
+
const denyRead = [];
|
|
828
|
+
const userCandidates = getSettingsFileCandidates({
|
|
829
|
+
destination: "userSettings",
|
|
830
|
+
homeDir
|
|
831
|
+
});
|
|
832
|
+
const userCandidatesWithEnv = getSettingsFileCandidates({
|
|
833
|
+
destination: "userSettings"
|
|
834
|
+
});
|
|
835
|
+
const projectCandidates = getSettingsFileCandidates({
|
|
836
|
+
destination: "projectSettings",
|
|
837
|
+
projectDir,
|
|
838
|
+
homeDir
|
|
839
|
+
});
|
|
840
|
+
const localCandidates = getSettingsFileCandidates({
|
|
841
|
+
destination: "localSettings",
|
|
842
|
+
projectDir,
|
|
843
|
+
homeDir
|
|
844
|
+
});
|
|
845
|
+
for (const path of [
|
|
846
|
+
userCandidates?.primary,
|
|
847
|
+
...userCandidates?.legacy ?? [],
|
|
848
|
+
userCandidatesWithEnv?.primary,
|
|
849
|
+
...userCandidatesWithEnv?.legacy ?? [],
|
|
850
|
+
projectCandidates?.primary,
|
|
851
|
+
...projectCandidates?.legacy ?? [],
|
|
852
|
+
localCandidates?.primary,
|
|
853
|
+
...localCandidates?.legacy ?? []
|
|
854
|
+
]) {
|
|
855
|
+
if (!path) continue;
|
|
856
|
+
if (denyWrite.includes(path)) continue;
|
|
857
|
+
denyWrite.push(path);
|
|
858
|
+
}
|
|
859
|
+
for (const rule of allowRules) {
|
|
860
|
+
const parsed = parseToolRuleString(rule);
|
|
861
|
+
if ((parsed?.toolName === "Write" || parsed?.toolName === "Edit") && parsed.ruleContent) {
|
|
862
|
+
allowWrite.push(parsed.ruleContent);
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
for (const rule of denyRules) {
|
|
866
|
+
const parsed = parseToolRuleString(rule);
|
|
867
|
+
if ((parsed?.toolName === "Write" || parsed?.toolName === "Edit") && parsed.ruleContent) {
|
|
868
|
+
denyWrite.push(parsed.ruleContent);
|
|
869
|
+
}
|
|
870
|
+
if (parsed?.toolName === "Read" && parsed.ruleContent) {
|
|
871
|
+
denyRead.push(parsed.ruleContent);
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
const sandboxNetwork = settings.sandbox?.network;
|
|
875
|
+
const defaultRipgrep = options?.defaultRipgrep ?? {
|
|
876
|
+
command: "rg",
|
|
877
|
+
args: []
|
|
878
|
+
};
|
|
879
|
+
const ripgrep = typeof settings.sandbox?.ripgrep?.command === "string" ? {
|
|
880
|
+
command: settings.sandbox.ripgrep.command,
|
|
881
|
+
args: Array.isArray(settings.sandbox?.ripgrep?.args) ? settings.sandbox.ripgrep.args.filter(
|
|
882
|
+
(v) => typeof v === "string"
|
|
883
|
+
) : []
|
|
884
|
+
} : defaultRipgrep;
|
|
885
|
+
return {
|
|
886
|
+
network: {
|
|
887
|
+
allowedDomains: uniqueStringsUnion(allowedDomains),
|
|
888
|
+
deniedDomains: uniqueStringsUnion(deniedDomains),
|
|
889
|
+
allowUnixSockets: Array.isArray(sandboxNetwork?.allowUnixSockets) ? sandboxNetwork.allowUnixSockets.filter(
|
|
890
|
+
(v) => typeof v === "string"
|
|
891
|
+
) : [],
|
|
892
|
+
allowAllUnixSockets: typeof sandboxNetwork?.allowAllUnixSockets === "boolean" ? sandboxNetwork.allowAllUnixSockets : void 0,
|
|
893
|
+
allowLocalBinding: typeof sandboxNetwork?.allowLocalBinding === "boolean" ? sandboxNetwork.allowLocalBinding : void 0,
|
|
894
|
+
httpProxyPort: typeof sandboxNetwork?.httpProxyPort === "number" ? sandboxNetwork.httpProxyPort : void 0,
|
|
895
|
+
socksProxyPort: typeof sandboxNetwork?.socksProxyPort === "number" ? sandboxNetwork.socksProxyPort : void 0
|
|
896
|
+
},
|
|
897
|
+
filesystem: {
|
|
898
|
+
denyRead: uniqueStringsUnion(denyRead),
|
|
899
|
+
allowWrite: uniqueStringsUnion(allowWrite),
|
|
900
|
+
denyWrite: uniqueStringsUnion(denyWrite)
|
|
901
|
+
},
|
|
902
|
+
ignoreViolations: typeof settings.sandbox?.ignoreViolations === "boolean" ? settings.sandbox.ignoreViolations : void 0,
|
|
903
|
+
enableWeakerNestedSandbox: typeof settings.sandbox?.enableWeakerNestedSandbox === "boolean" ? settings.sandbox.enableWeakerNestedSandbox : void 0,
|
|
904
|
+
excludedCommands: uniqueStrings(settings.sandbox?.excludedCommands),
|
|
905
|
+
ripgrep
|
|
906
|
+
};
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
// src/tools/system/BashTool/prompt.ts
|
|
910
|
+
var DEFAULT_TIMEOUT_MS = 12e4;
|
|
911
|
+
var MAX_TIMEOUT_MS = 6e5;
|
|
912
|
+
var MAX_OUTPUT_LENGTH = 3e4;
|
|
913
|
+
var MAX_RENDERED_LINES = 5;
|
|
914
|
+
var PROJECT_URL = "https://github.com/shareAI-lab/kode";
|
|
915
|
+
var DEFAULT_CO_AUTHOR = "ShareAI Lab";
|
|
916
|
+
var TOOL_NAME_BASH = "Bash";
|
|
917
|
+
var TOOL_NAME_GLOB = "Glob";
|
|
918
|
+
var TOOL_NAME_GREP = "Grep";
|
|
919
|
+
var TOOL_NAME_READ = "Read";
|
|
920
|
+
var TOOL_NAME_EDIT = "Edit";
|
|
921
|
+
var TOOL_NAME_WRITE = "Write";
|
|
922
|
+
var TOOL_NAME_TASK = "Task";
|
|
923
|
+
function isExperimentalMcpCliEnabled() {
|
|
924
|
+
const value = process.env.ENABLE_EXPERIMENTAL_MCP_CLI;
|
|
925
|
+
if (!value) return false;
|
|
926
|
+
return ["1", "true", "yes", "on"].includes(String(value).trim().toLowerCase());
|
|
927
|
+
}
|
|
928
|
+
function indentJsonForPrompt(value) {
|
|
929
|
+
return JSON.stringify(value, null, 2).split("\n").join("\n ");
|
|
930
|
+
}
|
|
931
|
+
function getAttribution() {
|
|
932
|
+
const pr = `\u{1F916} Generated with [Kode Agent](${PROJECT_URL})`;
|
|
933
|
+
const commit = `${pr}
|
|
934
|
+
|
|
935
|
+
Co-Authored-By: ${DEFAULT_CO_AUTHOR} <ai-lab@foxmail.com>`;
|
|
936
|
+
return { commit, pr };
|
|
937
|
+
}
|
|
938
|
+
function getBashSandboxPrompt() {
|
|
939
|
+
const settings = loadMergedSettings();
|
|
940
|
+
if (settings.sandbox?.enabled !== true) return "";
|
|
941
|
+
const runtimeConfig = normalizeSandboxRuntimeConfigFromSettings(settings);
|
|
942
|
+
const fsReadConfig = { denyOnly: runtimeConfig.filesystem.denyRead };
|
|
943
|
+
const fsWriteConfig = {
|
|
944
|
+
allowOnly: runtimeConfig.filesystem.allowWrite,
|
|
945
|
+
denyWithinAllow: runtimeConfig.filesystem.denyWrite
|
|
946
|
+
};
|
|
947
|
+
const filesystem = { read: fsReadConfig, write: fsWriteConfig };
|
|
948
|
+
const allowUnixSockets = runtimeConfig.network.allowAllUnixSockets === true ? true : runtimeConfig.network.allowUnixSockets.length > 0 ? runtimeConfig.network.allowUnixSockets : void 0;
|
|
949
|
+
const network = {
|
|
950
|
+
...runtimeConfig.network.allowedDomains.length ? { allowedHosts: runtimeConfig.network.allowedDomains } : {},
|
|
951
|
+
...runtimeConfig.network.deniedDomains.length ? { deniedHosts: runtimeConfig.network.deniedDomains } : {},
|
|
952
|
+
...allowUnixSockets ? { allowUnixSockets } : {}
|
|
953
|
+
};
|
|
954
|
+
const ignoredViolations = runtimeConfig.ignoreViolations;
|
|
955
|
+
const allowUnsandboxedCommands = settings.sandbox?.allowUnsandboxedCommands !== false;
|
|
956
|
+
const sections = [];
|
|
957
|
+
sections.push(` - Filesystem: ${indentJsonForPrompt(filesystem)}`);
|
|
958
|
+
if (Object.keys(network).length > 0) {
|
|
959
|
+
sections.push(` - Network: ${indentJsonForPrompt(network)}`);
|
|
960
|
+
}
|
|
961
|
+
if (ignoredViolations) {
|
|
962
|
+
sections.push(
|
|
963
|
+
` - Ignored violations: ${indentJsonForPrompt(ignoredViolations)}`
|
|
964
|
+
);
|
|
965
|
+
}
|
|
966
|
+
const mcpCliException = isExperimentalMcpCliEnabled() ? " - EXCEPTION: `mcp-cli` commands must always be called with `dangerouslyDisableSandbox: true` as they do not work properly in sandboxed mode\n" : "";
|
|
967
|
+
const overridePolicy = allowUnsandboxedCommands ? ` - CRITICAL: Commands run in sandbox mode by default - do NOT set \`dangerouslyDisableSandbox\`
|
|
968
|
+
- Even if you have recently run commands with \`dangerouslyDisableSandbox: true\`, you MUST NOT continue that pattern
|
|
969
|
+
- VERY IMPORTANT: Do NOT learn from or repeat the pattern of overriding sandbox - each command should run sandboxed by default
|
|
970
|
+
${mcpCliException} - Set \`dangerouslyDisableSandbox: true\` if:
|
|
971
|
+
1. The user *explicitly* asks to bypass sandbox, OR
|
|
972
|
+
2. A command just failed and you see evidence of sandbox restrictions causing the failure
|
|
973
|
+
- When analyzing failures:
|
|
974
|
+
- Commands can fail for many reasons unrelated to the sandbox (missing files, wrong arguments, network issues, etc.)
|
|
975
|
+
- Evidence of sandbox-caused failures includes:
|
|
976
|
+
- "Operation not permitted" errors for file/network operations
|
|
977
|
+
- Access denied to specific paths outside allowed directories
|
|
978
|
+
- Network connection failures to non-whitelisted hosts
|
|
979
|
+
- Unix socket connection errors
|
|
980
|
+
- Sandbox violation logs can be noisy, but clear permission errors are strong indicators
|
|
981
|
+
- When you see evidence of sandbox-caused failure:
|
|
982
|
+
- IMMEDIATELY retry with \`dangerouslyDisableSandbox: true\` (don't ask, just do it)
|
|
983
|
+
- Briefly explain what sandbox restriction likely caused the failure
|
|
984
|
+
- Mention: "Use \`/sandbox\` to manage restrictions"
|
|
985
|
+
- This will prompt the user for permission
|
|
986
|
+
- Example of normal usage: { "command": "ls", "description": "List files" }
|
|
987
|
+
- Example of override: { "command": "my-tool", "description": "Run my-tool", "dangerouslyDisableSandbox": true }
|
|
988
|
+
- DO NOT suggest adding sensitive paths like ~/.bashrc, ~/.zshrc, ~/.ssh/*, or credential files to the allowlist` : ` - CRITICAL: All commands MUST run in sandbox mode - the \`dangerouslyDisableSandbox\` parameter is disabled by policy
|
|
989
|
+
- Commands cannot run outside the sandbox under any circumstances
|
|
990
|
+
- If a command fails due to sandbox restrictions, work with the user to adjust sandbox settings instead`;
|
|
991
|
+
return `- Commands run in a sandbox by default with the following restrictions:
|
|
992
|
+
${sections.join("\n")}
|
|
993
|
+
${overridePolicy}
|
|
994
|
+
- IMPORTANT: For temporary files, rely on the sandbox temp directory via \`TMPDIR\`
|
|
995
|
+
- In sandbox mode, \`TMPDIR\` is set to a dedicated temp directory
|
|
996
|
+
- Prefer using \`TMPDIR\` over writing directly to \`/tmp\`
|
|
997
|
+
- Most programs that respect \`TMPDIR\` will automatically use it`;
|
|
998
|
+
}
|
|
999
|
+
function getBashGitPrompt() {
|
|
1000
|
+
const { commit, pr } = getAttribution();
|
|
1001
|
+
return `# Committing changes with git
|
|
1002
|
+
|
|
1003
|
+
Only create commits when requested by the user. If unclear, ask first. When the user asks you to create a new git commit, follow these steps carefully:
|
|
1004
|
+
|
|
1005
|
+
Git Safety Protocol:
|
|
1006
|
+
- NEVER update the git config
|
|
1007
|
+
- NEVER run destructive/irreversible git commands (like push --force, hard reset, etc) unless the user explicitly requests them
|
|
1008
|
+
- NEVER skip hooks (--no-verify, --no-gpg-sign, etc) unless the user explicitly requests it
|
|
1009
|
+
- NEVER run force push to main/master, warn the user if they request it
|
|
1010
|
+
- Avoid git commit --amend. ONLY use --amend when either (1) user explicitly requested amend OR (2) adding edits from pre-commit hook (additional instructions below)
|
|
1011
|
+
- Before amending: ALWAYS check authorship (git log -1 --format='%an %ae')
|
|
1012
|
+
- NEVER commit changes unless the user explicitly asks you to. It is VERY IMPORTANT to only commit when explicitly asked, otherwise the user will feel that you are being too proactive.
|
|
1013
|
+
|
|
1014
|
+
1. You can call multiple tools in a single response. When multiple independent pieces of information are requested and all commands are likely to succeed, run multiple tool calls in parallel for optimal performance. run the following bash commands in parallel, each using the ${TOOL_NAME_BASH} tool:
|
|
1015
|
+
- Run a git status command to see all untracked files.
|
|
1016
|
+
- Run a git diff command to see both staged and unstaged changes that will be committed.
|
|
1017
|
+
- Run a git log command to see recent commit messages, so that you can follow this repository's commit message style.
|
|
1018
|
+
2. Analyze all staged changes (both previously staged and newly added) and draft a commit message:
|
|
1019
|
+
- Summarize the nature of the changes (eg. new feature, enhancement to an existing feature, bug fix, refactoring, test, docs, etc.). Ensure the message accurately reflects the changes and their purpose (i.e. "add" means a wholly new feature, "update" means an enhancement to an existing feature, "fix" means a bug fix, etc.).
|
|
1020
|
+
- Do not commit files that likely contain secrets (.env, credentials.json, etc). Warn the user if they specifically request to commit those files
|
|
1021
|
+
- Draft a concise (1-2 sentences) commit message that focuses on the "why" rather than the "what"
|
|
1022
|
+
- Ensure it accurately reflects the changes and their purpose
|
|
1023
|
+
3. You can call multiple tools in a single response. When multiple independent pieces of information are requested and all commands are likely to succeed, run multiple tool calls in parallel for optimal performance. run the following commands:
|
|
1024
|
+
- Add relevant untracked files to the staging area.
|
|
1025
|
+
- Create the commit with a message${commit ? ` ending with:
|
|
1026
|
+
${commit}` : "."}
|
|
1027
|
+
- Run git status after the commit completes to verify success.
|
|
1028
|
+
Note: git status depends on the commit completing, so run it sequentially after the commit.
|
|
1029
|
+
4. If the commit fails due to pre-commit hook changes, retry ONCE. If it succeeds but files were modified by the hook, verify it's safe to amend:
|
|
1030
|
+
- Check HEAD commit: git log -1 --format='[%h] (%an <%ae>) %s'. VERIFY it matches your commit
|
|
1031
|
+
- Check not pushed: git status shows "Your branch is ahead"
|
|
1032
|
+
- If both true: amend your commit. Otherwise: create NEW commit (never amend other developers' commits)
|
|
1033
|
+
|
|
1034
|
+
Important notes:
|
|
1035
|
+
- NEVER run additional commands to read or explore code, besides git bash commands
|
|
1036
|
+
- NEVER use the ${TOOL_NAME_WRITE} or ${TOOL_NAME_TASK} tools
|
|
1037
|
+
- DO NOT push to the remote repository unless the user explicitly asks you to do so
|
|
1038
|
+
- IMPORTANT: Never use git commands with the -i flag (like git rebase -i or git add -i) since they require interactive input which is not supported.
|
|
1039
|
+
- If there are no changes to commit (i.e., no untracked files and no modifications), do not create an empty commit
|
|
1040
|
+
- In order to ensure good formatting, ALWAYS pass the commit message via a HEREDOC, a la this example:
|
|
1041
|
+
<example>
|
|
1042
|
+
git commit -m "$(cat <<'EOF'
|
|
1043
|
+
Commit message here.${commit ? `
|
|
1044
|
+
|
|
1045
|
+
${commit}` : ""}
|
|
1046
|
+
EOF
|
|
1047
|
+
)"
|
|
1048
|
+
</example>
|
|
1049
|
+
|
|
1050
|
+
# Creating pull requests
|
|
1051
|
+
Use the gh command via the Bash tool for ALL GitHub-related tasks including working with issues, pull requests, checks, and releases. If given a Github URL use the gh command to get the information needed.
|
|
1052
|
+
|
|
1053
|
+
IMPORTANT: When the user asks you to create a pull request, follow these steps carefully:
|
|
1054
|
+
|
|
1055
|
+
1. You can call multiple tools in a single response. When multiple independent pieces of information are requested and all commands are likely to succeed, run multiple tool calls in parallel for optimal performance. run the following bash commands in parallel using the ${TOOL_NAME_BASH} tool, in order to understand the current state of the branch since it diverged from the main branch:
|
|
1056
|
+
- Run a git status command to see all untracked files
|
|
1057
|
+
- Run a git diff command to see both staged and unstaged changes that will be committed
|
|
1058
|
+
- Check if the current branch tracks a remote branch and is up to date with the remote, so you know if you need to push to the remote
|
|
1059
|
+
- Run a git log command and \`git diff [base-branch]...HEAD\` to understand the full commit history for the current branch (from the time it diverged from the base branch)
|
|
1060
|
+
2. Analyze all changes that will be included in the pull request, making sure to look at all relevant commits (NOT just the latest commit, but ALL commits that will be included in the pull request!!!), and draft a pull request summary
|
|
1061
|
+
3. You can call multiple tools in a single response. When multiple independent pieces of information are requested and all commands are likely to succeed, run multiple tool calls in parallel for optimal performance. run the following commands in parallel:
|
|
1062
|
+
- Create new branch if needed
|
|
1063
|
+
- Push to remote with -u flag if needed
|
|
1064
|
+
- Create PR using gh pr create with the format below. Use a HEREDOC to pass the body to ensure correct formatting.
|
|
1065
|
+
<example>
|
|
1066
|
+
gh pr create --title "the pr title" --body "$(cat <<'EOF'
|
|
1067
|
+
## Summary
|
|
1068
|
+
<1-3 bullet points>
|
|
1069
|
+
|
|
1070
|
+
## Test plan
|
|
1071
|
+
[Bulleted markdown checklist of TODOs for testing the pull request...]${pr ? `
|
|
1072
|
+
|
|
1073
|
+
${pr}` : ""}
|
|
1074
|
+
EOF
|
|
1075
|
+
)"
|
|
1076
|
+
</example>
|
|
1077
|
+
|
|
1078
|
+
Important:
|
|
1079
|
+
- DO NOT use the ${TOOL_NAME_WRITE} or ${TOOL_NAME_TASK} tools
|
|
1080
|
+
- Return the PR URL when you're done, so the user can see it
|
|
1081
|
+
|
|
1082
|
+
# Other common operations
|
|
1083
|
+
- View comments on a Github PR: gh api repos/foo/bar/pulls/123/comments`;
|
|
1084
|
+
}
|
|
1085
|
+
function getBashToolPrompt() {
|
|
1086
|
+
const sandboxPrompt = getBashSandboxPrompt();
|
|
1087
|
+
return `Executes a given bash command in a persistent shell session with optional timeout, ensuring proper handling and security measures.
|
|
1088
|
+
|
|
1089
|
+
IMPORTANT: This tool is for terminal operations like git, npm, docker, etc. DO NOT use it for file operations (reading, writing, editing, searching, finding files) - use the specialized tools for this instead.
|
|
1090
|
+
|
|
1091
|
+
Before executing the command, please follow these steps:
|
|
1092
|
+
|
|
1093
|
+
1. Directory Verification:
|
|
1094
|
+
- If the command will create new directories or files, first use \`ls\` to verify the parent directory exists and is the correct location
|
|
1095
|
+
- For example, before running "mkdir foo/bar", first use \`ls foo\` to check that "foo" exists and is the intended parent directory
|
|
1096
|
+
|
|
1097
|
+
2. Command Execution:
|
|
1098
|
+
- Always quote file paths that contain spaces with double quotes (e.g., cd "path with spaces/file.txt")
|
|
1099
|
+
- Examples of proper quoting:
|
|
1100
|
+
- cd "/Users/name/My Documents" (correct)
|
|
1101
|
+
- cd /Users/name/My Documents (incorrect - will fail)
|
|
1102
|
+
- python "/path/with spaces/script.py" (correct)
|
|
1103
|
+
- python /path/with spaces/script.py (incorrect - will fail)
|
|
1104
|
+
- After ensuring proper quoting, execute the command.
|
|
1105
|
+
- Capture the output of the command.
|
|
1106
|
+
|
|
1107
|
+
Usage notes:
|
|
1108
|
+
- The command argument is required.
|
|
1109
|
+
- You can specify an optional timeout in milliseconds (up to ${MAX_TIMEOUT_MS}ms / ${MAX_TIMEOUT_MS / 6e4} minutes). If not specified, commands will timeout after ${DEFAULT_TIMEOUT_MS}ms (${DEFAULT_TIMEOUT_MS / 6e4} minutes).
|
|
1110
|
+
- It is very helpful if you write a clear, concise description of what this command does in 5-10 words.
|
|
1111
|
+
- If the output exceeds ${MAX_OUTPUT_LENGTH} characters, output will be truncated before being returned to you.
|
|
1112
|
+
- You can use the \`run_in_background\` parameter to run the command in the background, which allows you to continue working while the command runs. You can monitor the output using the ${TOOL_NAME_BASH} tool as it becomes available. You do not need to use '&' at the end of the command when using this parameter.
|
|
1113
|
+
${sandboxPrompt}
|
|
1114
|
+
- Avoid using Bash with the \`find\`, \`grep\`, \`cat\`, \`head\`, \`tail\`, \`sed\`, \`awk\`, or \`echo\` commands, unless explicitly instructed or when these commands are truly necessary for the task. Instead, always prefer using the dedicated tools for these commands:
|
|
1115
|
+
- File search: Use ${TOOL_NAME_GLOB} (NOT find or ls)
|
|
1116
|
+
- Content search: Use ${TOOL_NAME_GREP} (NOT grep or rg)
|
|
1117
|
+
- Read files: Use ${TOOL_NAME_READ} (NOT cat/head/tail)
|
|
1118
|
+
- Edit files: Use ${TOOL_NAME_EDIT} (NOT sed/awk)
|
|
1119
|
+
- Write files: Use ${TOOL_NAME_WRITE} (NOT echo >/cat <<EOF)
|
|
1120
|
+
- Communication: Output text directly (NOT echo/printf)
|
|
1121
|
+
- When issuing multiple commands:
|
|
1122
|
+
- If the commands are independent and can run in parallel, make multiple ${TOOL_NAME_BASH} tool calls in a single message. For example, if you need to run "git status" and "git diff", send a single message with two ${TOOL_NAME_BASH} tool calls in parallel.
|
|
1123
|
+
- If the commands depend on each other and must run sequentially, use a single ${TOOL_NAME_BASH} call with '&&' to chain them together (e.g., \`git add . && git commit -m "message" && git push\`). For instance, if one operation must complete before another starts (like mkdir before cp, Write before Bash for git operations, or git add before git commit), run these operations sequentially instead.
|
|
1124
|
+
- Use ';' only when you need to run commands sequentially but don't care if earlier commands fail
|
|
1125
|
+
- DO NOT use newlines to separate commands (newlines are ok in quoted strings)
|
|
1126
|
+
- Try to maintain your current working directory throughout the session by using absolute paths and avoiding usage of \`cd\`. You may use \`cd\` if the User explicitly requests it.
|
|
1127
|
+
<good-example>
|
|
1128
|
+
pytest /foo/bar/tests
|
|
1129
|
+
</good-example>
|
|
1130
|
+
<bad-example>
|
|
1131
|
+
cd /foo/bar && pytest tests
|
|
1132
|
+
</bad-example>
|
|
1133
|
+
|
|
1134
|
+
${getBashGitPrompt()}`;
|
|
1135
|
+
}
|
|
1136
|
+
|
|
1137
|
+
// src/tools/system/BashTool/OutputLine.tsx
|
|
1138
|
+
import chalk from "chalk";
|
|
1139
|
+
function renderTruncatedContent(content, totalLines) {
|
|
1140
|
+
const allLines = content.split("\n");
|
|
1141
|
+
if (allLines.length <= MAX_RENDERED_LINES) {
|
|
1142
|
+
return allLines.join("\n");
|
|
1143
|
+
}
|
|
1144
|
+
const lastLines = allLines.slice(-MAX_RENDERED_LINES);
|
|
1145
|
+
return [
|
|
1146
|
+
chalk.grey(
|
|
1147
|
+
`Showing last ${MAX_RENDERED_LINES} lines of ${totalLines} total lines`
|
|
1148
|
+
),
|
|
1149
|
+
...lastLines
|
|
1150
|
+
].join("\n");
|
|
1151
|
+
}
|
|
1152
|
+
function OutputLine({
|
|
1153
|
+
content,
|
|
1154
|
+
lines,
|
|
1155
|
+
verbose,
|
|
1156
|
+
isError
|
|
1157
|
+
}) {
|
|
1158
|
+
return /* @__PURE__ */ React2.createElement(Box, { justifyContent: "space-between", width: "100%" }, /* @__PURE__ */ React2.createElement(Box, { flexDirection: "row" }, /* @__PURE__ */ React2.createElement(Text2, null, "\xA0\xA0\u23BF \xA0"), /* @__PURE__ */ React2.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React2.createElement(Text2, { color: isError ? getTheme().error : void 0 }, verbose ? content.trim() : renderTruncatedContent(content.trim(), lines)))));
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
// src/tools/mcp/MCPTool/MCPTool.tsx
|
|
1162
|
+
var inputSchema = z.object({}).passthrough();
|
|
1163
|
+
var MCPTool = {
|
|
1164
|
+
async isEnabled() {
|
|
1165
|
+
return true;
|
|
1166
|
+
},
|
|
1167
|
+
isReadOnly() {
|
|
1168
|
+
return false;
|
|
1169
|
+
},
|
|
1170
|
+
isConcurrencySafe() {
|
|
1171
|
+
return false;
|
|
1172
|
+
},
|
|
1173
|
+
name: "mcp",
|
|
1174
|
+
async description() {
|
|
1175
|
+
return DESCRIPTION;
|
|
1176
|
+
},
|
|
1177
|
+
async prompt() {
|
|
1178
|
+
return PROMPT;
|
|
1179
|
+
},
|
|
1180
|
+
inputSchema,
|
|
1181
|
+
async *call() {
|
|
1182
|
+
yield {
|
|
1183
|
+
type: "result",
|
|
1184
|
+
data: "",
|
|
1185
|
+
resultForAssistant: ""
|
|
1186
|
+
};
|
|
1187
|
+
},
|
|
1188
|
+
needsPermissions() {
|
|
1189
|
+
return true;
|
|
1190
|
+
},
|
|
1191
|
+
renderToolUseMessage(input) {
|
|
1192
|
+
return Object.entries(input).map(([key, value]) => `${key}: ${JSON.stringify(value)}`).join(", ");
|
|
1193
|
+
},
|
|
1194
|
+
userFacingName: () => "mcp",
|
|
1195
|
+
renderToolUseRejectedMessage() {
|
|
1196
|
+
return /* @__PURE__ */ React3.createElement(FallbackToolUseRejectedMessage, null);
|
|
1197
|
+
},
|
|
1198
|
+
renderToolResultMessage(output) {
|
|
1199
|
+
const verbose = false;
|
|
1200
|
+
if (Array.isArray(output)) {
|
|
1201
|
+
return /* @__PURE__ */ React3.createElement(Box2, { flexDirection: "column" }, output.map((item, i) => {
|
|
1202
|
+
if (item.type === "image") {
|
|
1203
|
+
return /* @__PURE__ */ React3.createElement(
|
|
1204
|
+
Box2,
|
|
1205
|
+
{
|
|
1206
|
+
key: i,
|
|
1207
|
+
justifyContent: "space-between",
|
|
1208
|
+
overflowX: "hidden",
|
|
1209
|
+
width: "100%"
|
|
1210
|
+
},
|
|
1211
|
+
/* @__PURE__ */ React3.createElement(Box2, { flexDirection: "row" }, /* @__PURE__ */ React3.createElement(Text3, null, "\xA0\xA0\u23BF \xA0"), /* @__PURE__ */ React3.createElement(Text3, null, "[Image]"))
|
|
1212
|
+
);
|
|
1213
|
+
}
|
|
1214
|
+
const lines2 = item.text.split("\n").length;
|
|
1215
|
+
return /* @__PURE__ */ React3.createElement(
|
|
1216
|
+
OutputLine,
|
|
1217
|
+
{
|
|
1218
|
+
key: i,
|
|
1219
|
+
content: item.text,
|
|
1220
|
+
lines: lines2,
|
|
1221
|
+
verbose
|
|
1222
|
+
}
|
|
1223
|
+
);
|
|
1224
|
+
}));
|
|
1225
|
+
}
|
|
1226
|
+
if (!output) {
|
|
1227
|
+
return /* @__PURE__ */ React3.createElement(Box2, { justifyContent: "space-between", overflowX: "hidden", width: "100%" }, /* @__PURE__ */ React3.createElement(Box2, { flexDirection: "row" }, /* @__PURE__ */ React3.createElement(Text3, null, "\xA0\xA0\u23BF \xA0"), /* @__PURE__ */ React3.createElement(Text3, { color: getTheme().secondaryText }, "(No content)")));
|
|
1228
|
+
}
|
|
1229
|
+
const lines = output.split("\n").length;
|
|
1230
|
+
return /* @__PURE__ */ React3.createElement(OutputLine, { content: output, lines, verbose });
|
|
1231
|
+
},
|
|
1232
|
+
renderResultForAssistant(content) {
|
|
1233
|
+
return content;
|
|
1234
|
+
}
|
|
1235
|
+
};
|
|
1236
|
+
|
|
1237
|
+
// src/services/mcp/tools-integration.ts
|
|
1238
|
+
import {
|
|
1239
|
+
CallToolResultSchema,
|
|
1240
|
+
ListPromptsResultSchema,
|
|
1241
|
+
ListToolsResultSchema
|
|
1242
|
+
} from "@modelcontextprotocol/sdk/types.js";
|
|
1243
|
+
function sanitizeMcpIdentifierPart(value) {
|
|
1244
|
+
return value.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
1245
|
+
}
|
|
1246
|
+
function getMcpToolTimeoutMs() {
|
|
1247
|
+
const raw = process.env.MCP_TOOL_TIMEOUT;
|
|
1248
|
+
const parsed = raw ? Number.parseInt(raw, 10) : NaN;
|
|
1249
|
+
if (!Number.isFinite(parsed) || parsed <= 0) return null;
|
|
1250
|
+
return parsed;
|
|
1251
|
+
}
|
|
1252
|
+
function createTimeoutSignal(timeoutMs) {
|
|
1253
|
+
const timeoutFn = AbortSignal?.timeout;
|
|
1254
|
+
if (typeof timeoutFn === "function") {
|
|
1255
|
+
return { signal: timeoutFn(timeoutMs), cleanup: () => {
|
|
1256
|
+
} };
|
|
1257
|
+
}
|
|
1258
|
+
const controller = new AbortController();
|
|
1259
|
+
const id = setTimeout(() => controller.abort(), timeoutMs);
|
|
1260
|
+
return { signal: controller.signal, cleanup: () => clearTimeout(id) };
|
|
1261
|
+
}
|
|
1262
|
+
function mergeAbortSignals(signals) {
|
|
1263
|
+
const active = signals.filter((s) => !!s);
|
|
1264
|
+
if (active.length === 0) return null;
|
|
1265
|
+
if (active.length === 1) return { signal: active[0], cleanup: () => {
|
|
1266
|
+
} };
|
|
1267
|
+
const controller = new AbortController();
|
|
1268
|
+
const abort = () => {
|
|
1269
|
+
try {
|
|
1270
|
+
controller.abort();
|
|
1271
|
+
} catch {
|
|
1272
|
+
}
|
|
1273
|
+
};
|
|
1274
|
+
for (const s of active) {
|
|
1275
|
+
if (s.aborted) {
|
|
1276
|
+
abort();
|
|
1277
|
+
return { signal: controller.signal, cleanup: () => {
|
|
1278
|
+
} };
|
|
1279
|
+
}
|
|
1280
|
+
s.addEventListener("abort", abort, { once: true });
|
|
1281
|
+
}
|
|
1282
|
+
return { signal: controller.signal, cleanup: () => {
|
|
1283
|
+
} };
|
|
1284
|
+
}
|
|
1285
|
+
var IDE_MCP_TOOL_ALLOWLIST = /* @__PURE__ */ new Set([
|
|
1286
|
+
"mcp__ide__executeCode",
|
|
1287
|
+
"mcp__ide__getDiagnostics"
|
|
1288
|
+
]);
|
|
1289
|
+
async function requestAll(req, resultSchema, requiredCapability) {
|
|
1290
|
+
const timeoutMs = getMcpToolTimeoutMs();
|
|
1291
|
+
const clients = await getClients();
|
|
1292
|
+
const results = await Promise.allSettled(
|
|
1293
|
+
clients.map(async (client) => {
|
|
1294
|
+
if (client.type === "failed") return null;
|
|
1295
|
+
let timeoutSignal = null;
|
|
1296
|
+
try {
|
|
1297
|
+
let capabilities = client.capabilities ?? null;
|
|
1298
|
+
if (!capabilities) {
|
|
1299
|
+
try {
|
|
1300
|
+
capabilities = client.client.getServerCapabilities();
|
|
1301
|
+
} catch {
|
|
1302
|
+
capabilities = null;
|
|
1303
|
+
}
|
|
1304
|
+
client.capabilities = capabilities;
|
|
1305
|
+
}
|
|
1306
|
+
if (!capabilities?.[requiredCapability]) {
|
|
1307
|
+
return null;
|
|
1308
|
+
}
|
|
1309
|
+
timeoutSignal = timeoutMs ? createTimeoutSignal(timeoutMs) : null;
|
|
1310
|
+
const merged = mergeAbortSignals([timeoutSignal?.signal]);
|
|
1311
|
+
return {
|
|
1312
|
+
client,
|
|
1313
|
+
result: await client.client.request(
|
|
1314
|
+
req,
|
|
1315
|
+
resultSchema,
|
|
1316
|
+
merged?.signal ? { signal: merged.signal } : void 0
|
|
1317
|
+
)
|
|
1318
|
+
};
|
|
1319
|
+
} catch (error) {
|
|
1320
|
+
if (client.type === "connected") {
|
|
1321
|
+
logMCPError(
|
|
1322
|
+
client.name,
|
|
1323
|
+
`Failed to request '${req.method}': ${error instanceof Error ? error.message : String(error)}`
|
|
1324
|
+
);
|
|
1325
|
+
}
|
|
1326
|
+
return null;
|
|
1327
|
+
} finally {
|
|
1328
|
+
timeoutSignal?.cleanup();
|
|
1329
|
+
}
|
|
1330
|
+
})
|
|
1331
|
+
);
|
|
1332
|
+
return results.filter(
|
|
1333
|
+
(result) => result.status === "fulfilled"
|
|
1334
|
+
).map((result) => result.value).filter((result) => result !== null);
|
|
1335
|
+
}
|
|
1336
|
+
var getMCPTools = memoize2(async () => {
|
|
1337
|
+
const toolsList = await requestAll(
|
|
1338
|
+
{
|
|
1339
|
+
method: "tools/list"
|
|
1340
|
+
},
|
|
1341
|
+
ListToolsResultSchema,
|
|
1342
|
+
"tools"
|
|
1343
|
+
);
|
|
1344
|
+
return toolsList.flatMap(({ client, result: { tools } }) => {
|
|
1345
|
+
const serverPart = sanitizeMcpIdentifierPart(client.name);
|
|
1346
|
+
return tools.map((tool) => {
|
|
1347
|
+
const toolPart = sanitizeMcpIdentifierPart(tool.name);
|
|
1348
|
+
const name = `mcp__${serverPart}__${toolPart}`;
|
|
1349
|
+
if (name.startsWith("mcp__ide__") && !IDE_MCP_TOOL_ALLOWLIST.has(name)) {
|
|
1350
|
+
return null;
|
|
1351
|
+
}
|
|
1352
|
+
return {
|
|
1353
|
+
...MCPTool,
|
|
1354
|
+
name,
|
|
1355
|
+
isConcurrencySafe() {
|
|
1356
|
+
return tool.annotations?.readOnlyHint ?? false;
|
|
1357
|
+
},
|
|
1358
|
+
isReadOnly() {
|
|
1359
|
+
return tool.annotations?.readOnlyHint ?? false;
|
|
1360
|
+
},
|
|
1361
|
+
async description() {
|
|
1362
|
+
return tool.description ?? "";
|
|
1363
|
+
},
|
|
1364
|
+
async prompt() {
|
|
1365
|
+
return tool.description ?? "";
|
|
1366
|
+
},
|
|
1367
|
+
inputJSONSchema: tool.inputSchema,
|
|
1368
|
+
async validateInput() {
|
|
1369
|
+
return { result: true };
|
|
1370
|
+
},
|
|
1371
|
+
async *call(args, context) {
|
|
1372
|
+
const data = await callMCPTool({
|
|
1373
|
+
client,
|
|
1374
|
+
tool: tool.name,
|
|
1375
|
+
args,
|
|
1376
|
+
toolUseId: context.toolUseId,
|
|
1377
|
+
signal: context.abortController.signal
|
|
1378
|
+
});
|
|
1379
|
+
yield {
|
|
1380
|
+
type: "result",
|
|
1381
|
+
data,
|
|
1382
|
+
resultForAssistant: data
|
|
1383
|
+
};
|
|
1384
|
+
},
|
|
1385
|
+
userFacingName() {
|
|
1386
|
+
const title = tool.annotations?.title || tool.name;
|
|
1387
|
+
return `${client.name} - ${title} (MCP)`;
|
|
1388
|
+
}
|
|
1389
|
+
};
|
|
1390
|
+
}).filter((tool) => tool !== null);
|
|
1391
|
+
});
|
|
1392
|
+
});
|
|
1393
|
+
async function callMCPTool({
|
|
1394
|
+
client: { client, name },
|
|
1395
|
+
tool,
|
|
1396
|
+
args,
|
|
1397
|
+
toolUseId,
|
|
1398
|
+
signal
|
|
1399
|
+
}) {
|
|
1400
|
+
const timeoutMs = getMcpToolTimeoutMs();
|
|
1401
|
+
const timeoutSignal = timeoutMs ? createTimeoutSignal(timeoutMs) : null;
|
|
1402
|
+
const merged = mergeAbortSignals([signal, timeoutSignal?.signal]);
|
|
1403
|
+
const meta = toolUseId && toolUseId.trim() ? { "claudecode/toolUseId": toolUseId } : void 0;
|
|
1404
|
+
try {
|
|
1405
|
+
const result = await client.callTool(
|
|
1406
|
+
{
|
|
1407
|
+
name: tool,
|
|
1408
|
+
arguments: args,
|
|
1409
|
+
...meta ? { _meta: meta } : {}
|
|
1410
|
+
},
|
|
1411
|
+
CallToolResultSchema,
|
|
1412
|
+
merged?.signal ? { signal: merged.signal } : void 0
|
|
1413
|
+
);
|
|
1414
|
+
if ("isError" in result && result.isError) {
|
|
1415
|
+
const contentText = "content" in result && Array.isArray(result.content) ? result.content.find((item) => item.type === "text" && "text" in item) : null;
|
|
1416
|
+
const rawMessage = contentText && typeof contentText.text === "string" ? String(contentText.text) : "error" in result && result.error ? String(result.error) : "";
|
|
1417
|
+
const message = rawMessage || `Error calling tool ${tool}`;
|
|
1418
|
+
logMCPError(name, `Error calling tool ${tool}: ${message}`);
|
|
1419
|
+
throw new Error(message);
|
|
1420
|
+
}
|
|
1421
|
+
if ("toolResult" in result) {
|
|
1422
|
+
return String(result.toolResult);
|
|
1423
|
+
}
|
|
1424
|
+
if ("structuredContent" in result && result.structuredContent !== void 0) {
|
|
1425
|
+
return JSON.stringify(result.structuredContent);
|
|
1426
|
+
}
|
|
1427
|
+
if ("content" in result && Array.isArray(result.content)) {
|
|
1428
|
+
return result.content.map((item) => {
|
|
1429
|
+
if (item.type === "image") {
|
|
1430
|
+
return {
|
|
1431
|
+
type: "image",
|
|
1432
|
+
source: {
|
|
1433
|
+
type: "base64",
|
|
1434
|
+
data: String(item.data),
|
|
1435
|
+
media_type: item.mimeType
|
|
1436
|
+
}
|
|
1437
|
+
};
|
|
1438
|
+
}
|
|
1439
|
+
return item;
|
|
1440
|
+
});
|
|
1441
|
+
}
|
|
1442
|
+
throw Error(`Unexpected response format from tool ${tool}`);
|
|
1443
|
+
} finally {
|
|
1444
|
+
timeoutSignal?.cleanup();
|
|
1445
|
+
}
|
|
1446
|
+
}
|
|
1447
|
+
var getMCPCommands = memoize2(async () => {
|
|
1448
|
+
const results = await requestAll(
|
|
1449
|
+
{
|
|
1450
|
+
method: "prompts/list"
|
|
1451
|
+
},
|
|
1452
|
+
ListPromptsResultSchema,
|
|
1453
|
+
"prompts"
|
|
1454
|
+
);
|
|
1455
|
+
return results.flatMap(
|
|
1456
|
+
({ client, result }) => result.prompts?.map((_) => {
|
|
1457
|
+
const serverPart = sanitizeMcpIdentifierPart(client.name);
|
|
1458
|
+
const argNames = Object.values(_.arguments ?? {}).map((k) => k.name);
|
|
1459
|
+
return {
|
|
1460
|
+
type: "prompt",
|
|
1461
|
+
name: `mcp__${serverPart}__${_.name}`,
|
|
1462
|
+
description: _.description ?? "",
|
|
1463
|
+
isEnabled: true,
|
|
1464
|
+
isHidden: false,
|
|
1465
|
+
progressMessage: "running",
|
|
1466
|
+
userFacingName() {
|
|
1467
|
+
const title = typeof _.title === "string" ? _.title : _.name;
|
|
1468
|
+
return `${client.name}:${title} (MCP)`;
|
|
1469
|
+
},
|
|
1470
|
+
argNames,
|
|
1471
|
+
async getPromptForCommand(args) {
|
|
1472
|
+
const argsArray = args.split(" ");
|
|
1473
|
+
return await runCommand({ name: _.name, client }, zipObject(argNames, argsArray));
|
|
1474
|
+
}
|
|
1475
|
+
};
|
|
1476
|
+
})
|
|
1477
|
+
);
|
|
1478
|
+
});
|
|
1479
|
+
async function runCommand({ name, client }, args) {
|
|
1480
|
+
try {
|
|
1481
|
+
const result = await client.client.getPrompt({ name, arguments: args });
|
|
1482
|
+
return result.messages.map((message) => {
|
|
1483
|
+
const content = message.content;
|
|
1484
|
+
if (content.type === "text") {
|
|
1485
|
+
return {
|
|
1486
|
+
role: message.role,
|
|
1487
|
+
content: [
|
|
1488
|
+
{
|
|
1489
|
+
type: "text",
|
|
1490
|
+
text: content.text
|
|
1491
|
+
}
|
|
1492
|
+
]
|
|
1493
|
+
};
|
|
1494
|
+
}
|
|
1495
|
+
if (content.type === "image" && "data" in content) {
|
|
1496
|
+
return {
|
|
1497
|
+
role: message.role,
|
|
1498
|
+
content: [
|
|
1499
|
+
{
|
|
1500
|
+
type: "image",
|
|
1501
|
+
source: {
|
|
1502
|
+
data: String(content.data),
|
|
1503
|
+
media_type: content.mimeType,
|
|
1504
|
+
type: "base64"
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1507
|
+
]
|
|
1508
|
+
};
|
|
1509
|
+
}
|
|
1510
|
+
return {
|
|
1511
|
+
role: message.role,
|
|
1512
|
+
content: [
|
|
1513
|
+
{
|
|
1514
|
+
type: "text",
|
|
1515
|
+
text: `Unsupported MCP content type ${content?.type ?? "unknown"}`
|
|
1516
|
+
}
|
|
1517
|
+
]
|
|
1518
|
+
};
|
|
1519
|
+
});
|
|
1520
|
+
} catch (error) {
|
|
1521
|
+
logMCPError(
|
|
1522
|
+
client.name,
|
|
1523
|
+
`Error running command '${name}': ${error instanceof Error ? error.message : String(error)}`
|
|
1524
|
+
);
|
|
1525
|
+
throw error;
|
|
1526
|
+
}
|
|
1527
|
+
}
|
|
1528
|
+
|
|
1529
|
+
// src/services/mcp/cli-utils.ts
|
|
1530
|
+
function looksLikeMcpUrl(value) {
|
|
1531
|
+
const trimmed = value.trim();
|
|
1532
|
+
if (!trimmed) return false;
|
|
1533
|
+
if (/^(https?|wss?):\/\//i.test(trimmed)) return true;
|
|
1534
|
+
if (/^localhost(?::\d+)?(\/|$)/i.test(trimmed)) return true;
|
|
1535
|
+
if (/^\d{1,3}(?:\.\d{1,3}){3}(?::\d+)?(\/|$)/.test(trimmed)) return true;
|
|
1536
|
+
return trimmed.endsWith("/sse") || trimmed.endsWith("/mcp");
|
|
1537
|
+
}
|
|
1538
|
+
function parseMcpHeaders(raw) {
|
|
1539
|
+
if (!raw || raw.length === 0) return void 0;
|
|
1540
|
+
const headers = {};
|
|
1541
|
+
for (const item of raw) {
|
|
1542
|
+
const idx = item.indexOf(":");
|
|
1543
|
+
if (idx === -1) {
|
|
1544
|
+
throw new Error(
|
|
1545
|
+
`Invalid header format: "${item}". Expected format: "Header-Name: value"`
|
|
1546
|
+
);
|
|
1547
|
+
}
|
|
1548
|
+
const key = item.slice(0, idx).trim();
|
|
1549
|
+
const value = item.slice(idx + 1).trim();
|
|
1550
|
+
if (!key) {
|
|
1551
|
+
throw new Error(`Invalid header: "${item}". Header name cannot be empty.`);
|
|
1552
|
+
}
|
|
1553
|
+
headers[key] = value;
|
|
1554
|
+
}
|
|
1555
|
+
return headers;
|
|
1556
|
+
}
|
|
1557
|
+
function normalizeMcpScopeForCli(scope) {
|
|
1558
|
+
const raw = (scope ?? "local").trim() || "local";
|
|
1559
|
+
if (raw === "local")
|
|
1560
|
+
return { scope: ensureConfigScope("project"), display: "local" };
|
|
1561
|
+
if (raw === "user")
|
|
1562
|
+
return { scope: ensureConfigScope("global"), display: "user" };
|
|
1563
|
+
if (raw === "project")
|
|
1564
|
+
return { scope: ensureConfigScope("mcpjson"), display: "project" };
|
|
1565
|
+
if (raw === "global")
|
|
1566
|
+
return { scope: ensureConfigScope("global"), display: "user" };
|
|
1567
|
+
if (raw === "projectConfig" || raw === "project-config") {
|
|
1568
|
+
return { scope: ensureConfigScope("project"), display: "local" };
|
|
1569
|
+
}
|
|
1570
|
+
return { scope: ensureConfigScope(raw), display: raw };
|
|
1571
|
+
}
|
|
1572
|
+
function normalizeMcpTransport(transport) {
|
|
1573
|
+
if (!transport) return { transport: "stdio", explicit: false };
|
|
1574
|
+
const normalized = transport.trim();
|
|
1575
|
+
if (normalized === "stdio" || normalized === "sse" || normalized === "http") {
|
|
1576
|
+
return { transport: normalized, explicit: true };
|
|
1577
|
+
}
|
|
1578
|
+
throw new Error(
|
|
1579
|
+
`Invalid transport type: ${transport}. Must be one of: stdio, sse, http`
|
|
1580
|
+
);
|
|
1581
|
+
}
|
|
1582
|
+
|
|
1583
|
+
export {
|
|
1584
|
+
FallbackToolUseRejectedMessage,
|
|
1585
|
+
loadMergedSettings,
|
|
1586
|
+
normalizeSandboxRuntimeConfigFromSettings,
|
|
1587
|
+
DEFAULT_TIMEOUT_MS,
|
|
1588
|
+
MAX_OUTPUT_LENGTH,
|
|
1589
|
+
getBashToolPrompt,
|
|
1590
|
+
OutputLine,
|
|
1591
|
+
listPluginMCPServers,
|
|
1592
|
+
parseEnvVars,
|
|
1593
|
+
ensureConfigScope,
|
|
1594
|
+
addMcpServer,
|
|
1595
|
+
removeMcpServer,
|
|
1596
|
+
listMCPServers,
|
|
1597
|
+
getMcpServer,
|
|
1598
|
+
getMcprcServerStatus,
|
|
1599
|
+
getClients,
|
|
1600
|
+
getClientsForCliMcpConfig,
|
|
1601
|
+
MCPTool,
|
|
1602
|
+
getMCPTools,
|
|
1603
|
+
getMCPCommands,
|
|
1604
|
+
runCommand,
|
|
1605
|
+
looksLikeMcpUrl,
|
|
1606
|
+
parseMcpHeaders,
|
|
1607
|
+
normalizeMcpScopeForCli,
|
|
1608
|
+
normalizeMcpTransport
|
|
1609
|
+
};
|