@shareai-lab/kode 1.2.0 → 2.0.2
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-GIU4ZIXM.js +42 -0
- package/dist/acp-H3VJ77YG.js +1357 -0
- package/dist/acp-H3VJ77YG.js.map +7 -0
- package/dist/agentsValidate-XP3CFN6F.js +373 -0
- package/dist/agentsValidate-XP3CFN6F.js.map +7 -0
- package/dist/ask-3G5H5KD5.js +125 -0
- package/dist/ask-3G5H5KD5.js.map +7 -0
- package/dist/autoUpdater-DNRMJWFQ.js +17 -0
- package/dist/chunk-2KWKUXLT.js +490 -0
- package/dist/chunk-2KWKUXLT.js.map +7 -0
- package/dist/chunk-2PMO2FS2.js +1097 -0
- package/dist/chunk-2PMO2FS2.js.map +7 -0
- package/dist/chunk-3RUXVV4S.js +23 -0
- package/dist/chunk-3RUXVV4S.js.map +7 -0
- package/dist/chunk-3TXNP6HH.js +240 -0
- package/dist/chunk-3TXNP6HH.js.map +7 -0
- package/dist/chunk-4GAIJGRH.js +472 -0
- package/dist/chunk-4GAIJGRH.js.map +7 -0
- package/dist/chunk-4RTX4AG4.js +249 -0
- package/dist/chunk-4RTX4AG4.js.map +7 -0
- package/dist/chunk-54DNHKOD.js +511 -0
- package/dist/chunk-54DNHKOD.js.map +7 -0
- package/dist/chunk-67PY5IX6.js +34 -0
- package/dist/chunk-67PY5IX6.js.map +7 -0
- package/dist/chunk-6DRDLOLP.js +2613 -0
- package/dist/chunk-6DRDLOLP.js.map +7 -0
- package/dist/chunk-7CQVZNQV.js +1609 -0
- package/dist/chunk-7CQVZNQV.js.map +7 -0
- package/dist/chunk-ABLVTESJ.js +19 -0
- package/dist/chunk-ABLVTESJ.js.map +7 -0
- package/dist/{utils/config.js → chunk-AIMIPK4B.js} +351 -171
- package/dist/chunk-AIMIPK4B.js.map +7 -0
- package/dist/{utils/autoUpdater.js → chunk-BHGTA6JQ.js} +38 -21
- package/dist/chunk-BHGTA6JQ.js.map +7 -0
- package/dist/chunk-CIG63V4E.js +72 -0
- package/dist/chunk-CIG63V4E.js.map +7 -0
- package/dist/chunk-E6YNABER.js +24 -0
- package/dist/chunk-E6YNABER.js.map +7 -0
- package/dist/chunk-EH34V7CY.js +191 -0
- package/dist/chunk-EH34V7CY.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-FH5CHM6L.js +148 -0
- package/dist/chunk-FH5CHM6L.js.map +7 -0
- package/dist/chunk-G6I7XROM.js +138 -0
- package/dist/chunk-G6I7XROM.js.map +7 -0
- package/dist/chunk-HN4E4UUQ.js +96 -0
- package/dist/chunk-HN4E4UUQ.js.map +7 -0
- package/dist/chunk-HSPVVDIW.js +30198 -0
- package/dist/chunk-HSPVVDIW.js.map +7 -0
- package/dist/{services/systemReminder.js → chunk-IE2CG2TV.js} +221 -59
- package/dist/chunk-IE2CG2TV.js.map +7 -0
- package/dist/chunk-JC6NCUG5.js +11 -0
- package/dist/chunk-K2MI4TPB.js +1256 -0
- package/dist/chunk-K2MI4TPB.js.map +7 -0
- package/dist/chunk-KAA5BGMQ.js +12 -0
- package/dist/chunk-KAA5BGMQ.js.map +7 -0
- package/dist/chunk-MN77D2F7.js +2931 -0
- package/dist/chunk-MN77D2F7.js.map +7 -0
- package/dist/chunk-NPFOMITO.js +21 -0
- package/dist/chunk-NPFOMITO.js.map +7 -0
- package/dist/chunk-NQLEUHMS.js +196 -0
- package/dist/chunk-NQLEUHMS.js.map +7 -0
- package/dist/chunk-OIFQB3S4.js +515 -0
- package/dist/chunk-OIFQB3S4.js.map +7 -0
- package/dist/chunk-OWTG2W3A.js +164 -0
- package/dist/chunk-OWTG2W3A.js.map +7 -0
- package/dist/chunk-OZNRLY3E.js +735 -0
- package/dist/chunk-OZNRLY3E.js.map +7 -0
- package/dist/{utils/debugLogger.js → chunk-QYFKRZQC.js} +107 -204
- package/dist/chunk-QYFKRZQC.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/theme.js → chunk-SDGKPKDK.js} +28 -6
- package/dist/chunk-SDGKPKDK.js.map +7 -0
- package/dist/chunk-SRZZFAS7.js +766 -0
- package/dist/chunk-SRZZFAS7.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-VBXVYQYY.js +145 -0
- package/dist/chunk-VBXVYQYY.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/{utils/model.js → chunk-Z33T5YN5.js} +194 -227
- package/dist/chunk-Z33T5YN5.js.map +7 -0
- package/dist/{services/openai.js → chunk-ZQU3TXLC.js} +168 -234
- package/dist/chunk-ZQU3TXLC.js.map +7 -0
- package/dist/cli-SRV2INSL.js +3917 -0
- package/dist/cli-SRV2INSL.js.map +7 -0
- package/dist/commands-TWH6PGVG.js +46 -0
- package/dist/config-6ZMBCL23.js +81 -0
- package/dist/context-JQIOOI4W.js +30 -0
- package/dist/costTracker-6SL26FDB.js +19 -0
- package/dist/customCommands-DNEJS3ZU.js +25 -0
- package/dist/customCommands-DNEJS3ZU.js.map +7 -0
- package/dist/env-OFAXZ3XG.js +22 -0
- package/dist/env-OFAXZ3XG.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-6N27AC5K.js +18 -0
- package/dist/kodeAgentSessionLoad-6N27AC5K.js.map +7 -0
- package/dist/kodeAgentSessionResume-HUSAEO24.js +16 -0
- package/dist/kodeAgentSessionResume-HUSAEO24.js.map +7 -0
- package/dist/kodeAgentStreamJson-NXFN7TXH.js +13 -0
- package/dist/kodeAgentStreamJson-NXFN7TXH.js.map +7 -0
- package/dist/kodeAgentStreamJsonSession-GRWG3SPE.js +131 -0
- package/dist/kodeAgentStreamJsonSession-GRWG3SPE.js.map +7 -0
- package/dist/kodeAgentStructuredStdio-HGWJT7CU.js +10 -0
- package/dist/kodeAgentStructuredStdio-HGWJT7CU.js.map +7 -0
- package/dist/kodeHooks-TDMXFWSO.js +36 -0
- package/dist/kodeHooks-TDMXFWSO.js.map +7 -0
- package/dist/llm-XVXWYOHK.js +3118 -0
- package/dist/llm-XVXWYOHK.js.map +7 -0
- package/dist/llmLazy-7TD5N7XP.js +15 -0
- package/dist/llmLazy-7TD5N7XP.js.map +7 -0
- package/dist/loader-AUXIJTY6.js +28 -0
- package/dist/loader-AUXIJTY6.js.map +7 -0
- package/dist/mcp-BXJ3K7NZ.js +49 -0
- package/dist/mcp-BXJ3K7NZ.js.map +7 -0
- package/dist/{services/mentionProcessor.js → mentionProcessor-YD7YXYGF.js} +61 -50
- package/dist/mentionProcessor-YD7YXYGF.js.map +7 -0
- package/dist/messages-OFUJSPRV.js +63 -0
- package/dist/messages-OFUJSPRV.js.map +7 -0
- package/dist/model-KPYCXWBK.js +30 -0
- package/dist/model-KPYCXWBK.js.map +7 -0
- package/dist/openai-5G5D5Q4B.js +29 -0
- package/dist/openai-5G5D5Q4B.js.map +7 -0
- package/dist/outputStyles-HLDXFQK3.js +28 -0
- package/dist/outputStyles-HLDXFQK3.js.map +7 -0
- package/dist/package.json +1 -1
- package/dist/pluginRuntime-FPTKK6NY.js +218 -0
- package/dist/pluginRuntime-FPTKK6NY.js.map +7 -0
- package/dist/pluginValidation-DSFXZ4GF.js +17 -0
- package/dist/pluginValidation-DSFXZ4GF.js.map +7 -0
- package/dist/prompts-LWLAJRS2.js +48 -0
- package/dist/prompts-LWLAJRS2.js.map +7 -0
- package/dist/query-HVPWL27C.js +50 -0
- package/dist/query-HVPWL27C.js.map +7 -0
- package/dist/responsesStreaming-AW344PQO.js +10 -0
- package/dist/responsesStreaming-AW344PQO.js.map +7 -0
- package/dist/ripgrep-YOPCY2GO.js +17 -0
- package/dist/ripgrep-YOPCY2GO.js.map +7 -0
- package/dist/skillMarketplace-PSNKDINM.js +37 -0
- package/dist/skillMarketplace-PSNKDINM.js.map +7 -0
- package/dist/state-KNRWP3FO.js +16 -0
- package/dist/state-KNRWP3FO.js.map +7 -0
- package/dist/theme-7S2QN2FO.js +14 -0
- package/dist/theme-7S2QN2FO.js.map +7 -0
- package/dist/toolPermissionContext-65L65VEZ.js +17 -0
- package/dist/toolPermissionContext-65L65VEZ.js.map +7 -0
- package/dist/toolPermissionSettings-GPOBH4IV.js +18 -0
- package/dist/toolPermissionSettings-GPOBH4IV.js.map +7 -0
- package/dist/tools-FZU2FZBD.js +47 -0
- package/dist/tools-FZU2FZBD.js.map +7 -0
- package/dist/userInput-VHNBN2MW.js +311 -0
- package/dist/userInput-VHNBN2MW.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-GIU4ZIXM.js.map} +0 -0
- /package/dist/{components/CustomSelect/theme.js.map → autoUpdater-DNRMJWFQ.js.map} +0 -0
- /package/dist/{types/common.d.js.map → chunk-JC6NCUG5.js.map} +0 -0
- /package/dist/{types/conversation.js.map → commands-TWH6PGVG.js.map} +0 -0
- /package/dist/{types/logs.js.map → config-6ZMBCL23.js.map} +0 -0
- /package/dist/{types/modelCapabilities.js.map → context-JQIOOI4W.js.map} +0 -0
- /package/dist/{types/notebook.js.map → costTracker-6SL26FDB.js.map} +0 -0
|
@@ -0,0 +1,3917 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
import { createRequire as __kodeCreateRequire } from "node:module";
|
|
3
|
+
const require = __kodeCreateRequire(import.meta.url);
|
|
4
|
+
import {
|
|
5
|
+
ensurePackagedRuntimeEnv,
|
|
6
|
+
ensureYogaWasmPath
|
|
7
|
+
} from "./chunk-WWUWDNWW.js";
|
|
8
|
+
import {
|
|
9
|
+
getAllTools
|
|
10
|
+
} from "./chunk-6DRDLOLP.js";
|
|
11
|
+
import {
|
|
12
|
+
KodeAgentStructuredStdio
|
|
13
|
+
} from "./chunk-4RTX4AG4.js";
|
|
14
|
+
import {
|
|
15
|
+
assertMinVersion
|
|
16
|
+
} from "./chunk-BHGTA6JQ.js";
|
|
17
|
+
import {
|
|
18
|
+
getToolDescription
|
|
19
|
+
} from "./chunk-WVHORZQ5.js";
|
|
20
|
+
import {
|
|
21
|
+
lastX
|
|
22
|
+
} from "./chunk-ABLVTESJ.js";
|
|
23
|
+
import {
|
|
24
|
+
Doctor,
|
|
25
|
+
Onboarding,
|
|
26
|
+
ResumeConversation,
|
|
27
|
+
Select,
|
|
28
|
+
addToHistory,
|
|
29
|
+
clearTerminal,
|
|
30
|
+
grantReadPermissionForOriginalDir,
|
|
31
|
+
hasPermissionsToUseTool,
|
|
32
|
+
review_default,
|
|
33
|
+
useExitOnCtrlCD,
|
|
34
|
+
useTerminalSize
|
|
35
|
+
} from "./chunk-HSPVVDIW.js";
|
|
36
|
+
import "./chunk-NQLEUHMS.js";
|
|
37
|
+
import {
|
|
38
|
+
addMcpServer,
|
|
39
|
+
ensureConfigScope,
|
|
40
|
+
getClients,
|
|
41
|
+
getClientsForCliMcpConfig,
|
|
42
|
+
getMcpServer,
|
|
43
|
+
getMcprcServerStatus,
|
|
44
|
+
listMCPServers,
|
|
45
|
+
looksLikeMcpUrl,
|
|
46
|
+
normalizeMcpScopeForCli,
|
|
47
|
+
normalizeMcpTransport,
|
|
48
|
+
parseEnvVars,
|
|
49
|
+
parseMcpHeaders,
|
|
50
|
+
removeMcpServer
|
|
51
|
+
} from "./chunk-7CQVZNQV.js";
|
|
52
|
+
import "./chunk-4GAIJGRH.js";
|
|
53
|
+
import "./chunk-2PMO2FS2.js";
|
|
54
|
+
import "./chunk-G6I7XROM.js";
|
|
55
|
+
import "./chunk-3TXNP6HH.js";
|
|
56
|
+
import "./chunk-KAA5BGMQ.js";
|
|
57
|
+
import "./chunk-3RUXVV4S.js";
|
|
58
|
+
import "./chunk-K2MI4TPB.js";
|
|
59
|
+
import "./chunk-NPFOMITO.js";
|
|
60
|
+
import {
|
|
61
|
+
clearOutputStyleCache
|
|
62
|
+
} from "./chunk-54DNHKOD.js";
|
|
63
|
+
import "./chunk-ZQU3TXLC.js";
|
|
64
|
+
import "./chunk-67PY5IX6.js";
|
|
65
|
+
import "./chunk-OWTG2W3A.js";
|
|
66
|
+
import "./chunk-SRZZFAS7.js";
|
|
67
|
+
import "./chunk-EH34V7CY.js";
|
|
68
|
+
import "./chunk-VBXVYQYY.js";
|
|
69
|
+
import "./chunk-S6HRABTA.js";
|
|
70
|
+
import "./chunk-IE2CG2TV.js";
|
|
71
|
+
import "./chunk-E6YNABER.js";
|
|
72
|
+
import {
|
|
73
|
+
clearAgentCache,
|
|
74
|
+
setFlagAgentsFromCliJson
|
|
75
|
+
} from "./chunk-OZNRLY3E.js";
|
|
76
|
+
import {
|
|
77
|
+
setEnabledSettingSourcesFromCli
|
|
78
|
+
} from "./chunk-UKHTVRJM.js";
|
|
79
|
+
import "./chunk-S3J2TLV6.js";
|
|
80
|
+
import "./chunk-2KWKUXLT.js";
|
|
81
|
+
import {
|
|
82
|
+
getModelManager,
|
|
83
|
+
isDefaultSlowAndCapableModel
|
|
84
|
+
} from "./chunk-Z33T5YN5.js";
|
|
85
|
+
import {
|
|
86
|
+
getContext,
|
|
87
|
+
removeContext,
|
|
88
|
+
setContext
|
|
89
|
+
} from "./chunk-OIFQB3S4.js";
|
|
90
|
+
import {
|
|
91
|
+
getTheme
|
|
92
|
+
} from "./chunk-SDGKPKDK.js";
|
|
93
|
+
import {
|
|
94
|
+
checkHasTrustDialogAccepted,
|
|
95
|
+
deleteConfigForCLI,
|
|
96
|
+
enableConfigs,
|
|
97
|
+
getConfigForCLI,
|
|
98
|
+
getCurrentProjectConfig,
|
|
99
|
+
getGlobalConfig,
|
|
100
|
+
getProjectMcpServerDefinitions,
|
|
101
|
+
listConfigForCLI,
|
|
102
|
+
saveCurrentProjectConfig,
|
|
103
|
+
saveGlobalConfig,
|
|
104
|
+
setConfigForCLI,
|
|
105
|
+
validateAndRepairAllGPT5Profiles
|
|
106
|
+
} from "./chunk-AIMIPK4B.js";
|
|
107
|
+
import {
|
|
108
|
+
ConfigParseError
|
|
109
|
+
} from "./chunk-UYXEDKOZ.js";
|
|
110
|
+
import {
|
|
111
|
+
debug,
|
|
112
|
+
initDebugLogger
|
|
113
|
+
} from "./chunk-QYFKRZQC.js";
|
|
114
|
+
import {
|
|
115
|
+
BunShell,
|
|
116
|
+
CACHE_PATHS,
|
|
117
|
+
PRODUCT_COMMAND,
|
|
118
|
+
PRODUCT_NAME,
|
|
119
|
+
dateToFilename,
|
|
120
|
+
formatDate,
|
|
121
|
+
getCwd,
|
|
122
|
+
getNextAvailableLogForkNumber,
|
|
123
|
+
initSentry,
|
|
124
|
+
loadLogList,
|
|
125
|
+
logError,
|
|
126
|
+
parseLogFilename,
|
|
127
|
+
setCwd,
|
|
128
|
+
setOriginalCwd
|
|
129
|
+
} from "./chunk-MN77D2F7.js";
|
|
130
|
+
import {
|
|
131
|
+
MACRO
|
|
132
|
+
} from "./chunk-FH5CHM6L.js";
|
|
133
|
+
import "./chunk-EZXMVTDU.js";
|
|
134
|
+
import "./chunk-JC6NCUG5.js";
|
|
135
|
+
|
|
136
|
+
// src/entrypoints/cli/runCli.tsx
|
|
137
|
+
import { existsSync, readFileSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
138
|
+
|
|
139
|
+
// src/entrypoints/cli/stdio/canUseTool.ts
|
|
140
|
+
function createStdioCanUseTool(args) {
|
|
141
|
+
if (args.normalizedPermissionPromptTool !== "stdio" || !args.structured) {
|
|
142
|
+
return args.hasPermissionsToUseTool;
|
|
143
|
+
}
|
|
144
|
+
return (async (tool, input, toolUseContext, assistantMessage) => {
|
|
145
|
+
const base = await args.hasPermissionsToUseTool(
|
|
146
|
+
tool,
|
|
147
|
+
input,
|
|
148
|
+
toolUseContext,
|
|
149
|
+
assistantMessage
|
|
150
|
+
);
|
|
151
|
+
if (base.result === true) return { result: true };
|
|
152
|
+
const denied = base;
|
|
153
|
+
if (denied.shouldPromptUser === false) {
|
|
154
|
+
return { result: false, message: denied.message };
|
|
155
|
+
}
|
|
156
|
+
try {
|
|
157
|
+
const blockedPath = typeof denied.blockedPath === "string" ? String(denied.blockedPath) : typeof input?.file_path === "string" ? String(input.file_path) : typeof input?.notebook_path === "string" ? String(input.notebook_path) : typeof input?.path === "string" ? String(input.path) : void 0;
|
|
158
|
+
const decisionReason = typeof denied.decisionReason === "string" ? String(denied.decisionReason) : void 0;
|
|
159
|
+
const response = await args.structured.sendRequest(
|
|
160
|
+
{
|
|
161
|
+
subtype: "can_use_tool",
|
|
162
|
+
tool_name: tool.name,
|
|
163
|
+
input,
|
|
164
|
+
...typeof toolUseContext?.toolUseId === "string" && toolUseContext.toolUseId ? { tool_use_id: toolUseContext.toolUseId } : {},
|
|
165
|
+
...typeof toolUseContext?.agentId === "string" && toolUseContext.agentId ? { agent_id: toolUseContext.agentId } : {},
|
|
166
|
+
...Array.isArray(denied.suggestions) ? {
|
|
167
|
+
permission_suggestions: denied.suggestions
|
|
168
|
+
} : {},
|
|
169
|
+
...blockedPath ? { blocked_path: blockedPath } : {},
|
|
170
|
+
...decisionReason ? { decision_reason: decisionReason } : {}
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
signal: toolUseContext.abortController.signal,
|
|
174
|
+
timeoutMs: args.permissionTimeoutMs
|
|
175
|
+
}
|
|
176
|
+
);
|
|
177
|
+
if (response && response.behavior === "allow") {
|
|
178
|
+
const updatedInput = response.updatedInput && typeof response.updatedInput === "object" ? response.updatedInput : null;
|
|
179
|
+
if (updatedInput) {
|
|
180
|
+
Object.assign(input, updatedInput);
|
|
181
|
+
}
|
|
182
|
+
const updatedPermissionsRaw = response.updatedPermissions;
|
|
183
|
+
const updatedPermissions = Array.isArray(updatedPermissionsRaw) && updatedPermissionsRaw.every(
|
|
184
|
+
(u) => u && typeof u === "object" && typeof u.type === "string"
|
|
185
|
+
) ? updatedPermissionsRaw : null;
|
|
186
|
+
if (updatedPermissions && args.printOptions.toolPermissionContext) {
|
|
187
|
+
const next = args.applyToolPermissionContextUpdates(
|
|
188
|
+
args.printOptions.toolPermissionContext,
|
|
189
|
+
updatedPermissions
|
|
190
|
+
);
|
|
191
|
+
args.printOptions.toolPermissionContext = next;
|
|
192
|
+
if (toolUseContext?.options) {
|
|
193
|
+
toolUseContext.options.toolPermissionContext = next;
|
|
194
|
+
}
|
|
195
|
+
for (const update of updatedPermissions) {
|
|
196
|
+
args.persistToolPermissionUpdateToDisk({
|
|
197
|
+
update,
|
|
198
|
+
projectDir: args.cwd
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
return { result: true };
|
|
203
|
+
}
|
|
204
|
+
if (response && response.behavior === "deny") {
|
|
205
|
+
if (response.interrupt === true) {
|
|
206
|
+
toolUseContext.abortController.abort();
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
return {
|
|
210
|
+
result: false,
|
|
211
|
+
message: typeof response?.message === "string" ? String(response.message) : denied.message
|
|
212
|
+
};
|
|
213
|
+
} catch (e) {
|
|
214
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
215
|
+
return {
|
|
216
|
+
result: false,
|
|
217
|
+
message: `Permission prompt failed: ${msg}`,
|
|
218
|
+
shouldPromptUser: false
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// src/entrypoints/cli/stdio/controlRequestHandler.ts
|
|
225
|
+
function createPrintModeControlRequestHandler(args) {
|
|
226
|
+
return async (msg) => {
|
|
227
|
+
const subtype = msg.request?.subtype;
|
|
228
|
+
if (subtype === "initialize") {
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
if (subtype === "set_permission_mode") {
|
|
232
|
+
const mode = msg.request?.mode;
|
|
233
|
+
if (mode === "default" || mode === "acceptEdits" || mode === "plan" || mode === "dontAsk" || mode === "bypassPermissions") {
|
|
234
|
+
if (args.printOptions.toolPermissionContext) {
|
|
235
|
+
args.printOptions.toolPermissionContext.mode = mode;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
if (subtype === "set_model") {
|
|
241
|
+
const requested = msg.request?.model;
|
|
242
|
+
if (requested === "default") {
|
|
243
|
+
args.printOptions.model = void 0;
|
|
244
|
+
} else if (typeof requested === "string" && requested.trim()) {
|
|
245
|
+
args.printOptions.model = requested.trim();
|
|
246
|
+
}
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
if (subtype === "set_max_thinking_tokens") {
|
|
250
|
+
const value = msg.request?.max_thinking_tokens;
|
|
251
|
+
if (value === null) {
|
|
252
|
+
args.printOptions.maxThinkingTokens = 0;
|
|
253
|
+
} else if (typeof value === "number" && Number.isFinite(value) && value >= 0) {
|
|
254
|
+
args.printOptions.maxThinkingTokens = value;
|
|
255
|
+
}
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
if (subtype === "mcp_status") {
|
|
259
|
+
return {
|
|
260
|
+
mcpServers: args.mcpClients.map((c) => ({
|
|
261
|
+
name: c.name,
|
|
262
|
+
status: c.type,
|
|
263
|
+
...c.type === "connected" && c.capabilities ? { serverInfo: c.capabilities } : {}
|
|
264
|
+
}))
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
if (subtype === "mcp_message") {
|
|
268
|
+
const serverName = msg.request?.server_name;
|
|
269
|
+
const message = msg.request?.message;
|
|
270
|
+
if (typeof serverName === "string" && serverName) {
|
|
271
|
+
const found = args.mcpClients.find((c) => c.name === serverName);
|
|
272
|
+
if (found && found.type === "connected") {
|
|
273
|
+
const transport = found.client?.transport;
|
|
274
|
+
if (transport && typeof transport.onmessage === "function") {
|
|
275
|
+
transport.onmessage(message);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
if (subtype === "mcp_set_servers") {
|
|
282
|
+
return { ok: true, sdkServersChanged: false };
|
|
283
|
+
}
|
|
284
|
+
if (subtype === "rewind_files") {
|
|
285
|
+
throw new Error("rewind_files is not supported in Kode yet.");
|
|
286
|
+
}
|
|
287
|
+
throw new Error(`Unsupported control request subtype: ${String(subtype)}`);
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// src/entrypoints/cli/stdio/streamJsonSession.ts
|
|
292
|
+
async function runPrintModeStreamJsonSession(args) {
|
|
293
|
+
const { runKodeAgentStreamJsonSession } = await import("./kodeAgentStreamJsonSession-GRWG3SPE.js");
|
|
294
|
+
await runKodeAgentStreamJsonSession(args);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// src/entrypoints/cli/stdio/structuredStdio.ts
|
|
298
|
+
function createPrintModeStructuredStdio(args) {
|
|
299
|
+
if (!args.enabled) return null;
|
|
300
|
+
return new KodeAgentStructuredStdio(args.stdin, args.stdout, {
|
|
301
|
+
onInterrupt: args.onInterrupt,
|
|
302
|
+
onControlRequest: args.onControlRequest
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// src/entrypoints/cli/printMode.ts
|
|
307
|
+
async function runPrintMode({
|
|
308
|
+
prompt,
|
|
309
|
+
stdinContent,
|
|
310
|
+
inputPrompt,
|
|
311
|
+
cwd: cwd2,
|
|
312
|
+
safe,
|
|
313
|
+
verbose,
|
|
314
|
+
outputFormat,
|
|
315
|
+
inputFormat,
|
|
316
|
+
jsonSchema,
|
|
317
|
+
permissionPromptTool,
|
|
318
|
+
replayUserMessages,
|
|
319
|
+
cliTools,
|
|
320
|
+
tools,
|
|
321
|
+
commands,
|
|
322
|
+
ask,
|
|
323
|
+
initialMessages,
|
|
324
|
+
sessionPersistence,
|
|
325
|
+
systemPromptOverride,
|
|
326
|
+
appendSystemPrompt,
|
|
327
|
+
disableSlashCommands,
|
|
328
|
+
allowedTools,
|
|
329
|
+
disallowedTools,
|
|
330
|
+
addDir,
|
|
331
|
+
permissionMode,
|
|
332
|
+
dangerouslySkipPermissions,
|
|
333
|
+
allowDangerouslySkipPermissions,
|
|
334
|
+
model,
|
|
335
|
+
mcpClients
|
|
336
|
+
}) {
|
|
337
|
+
const normalizedOutputFormat = String(outputFormat || "text").toLowerCase().trim();
|
|
338
|
+
const normalizedInputFormat = String(inputFormat || "text").toLowerCase().trim();
|
|
339
|
+
if (!["text", "stream-json"].includes(normalizedInputFormat)) {
|
|
340
|
+
console.error(
|
|
341
|
+
`Error: Invalid --input-format "${inputFormat}". Expected one of: text, stream-json`
|
|
342
|
+
);
|
|
343
|
+
process.exit(1);
|
|
344
|
+
}
|
|
345
|
+
if (!["text", "json", "stream-json"].includes(normalizedOutputFormat)) {
|
|
346
|
+
console.error(
|
|
347
|
+
`Error: Invalid --output-format "${outputFormat}". Expected one of: text, json, stream-json`
|
|
348
|
+
);
|
|
349
|
+
process.exit(1);
|
|
350
|
+
}
|
|
351
|
+
if (normalizedOutputFormat === "stream-json" && !verbose) {
|
|
352
|
+
console.error(
|
|
353
|
+
"Error: When using --print, --output-format=stream-json requires --verbose"
|
|
354
|
+
);
|
|
355
|
+
process.exit(1);
|
|
356
|
+
}
|
|
357
|
+
const normalizedPermissionPromptTool = permissionPromptTool ? String(permissionPromptTool).trim() : null;
|
|
358
|
+
if (normalizedPermissionPromptTool) {
|
|
359
|
+
if (normalizedPermissionPromptTool !== "stdio") {
|
|
360
|
+
console.error(
|
|
361
|
+
`Error: Unsupported --permission-prompt-tool "${normalizedPermissionPromptTool}". Only "stdio" is supported in Kode right now.`
|
|
362
|
+
);
|
|
363
|
+
process.exit(1);
|
|
364
|
+
}
|
|
365
|
+
if (normalizedInputFormat !== "stream-json") {
|
|
366
|
+
console.error(
|
|
367
|
+
"Error: --permission-prompt-tool=stdio requires --input-format=stream-json"
|
|
368
|
+
);
|
|
369
|
+
process.exit(1);
|
|
370
|
+
}
|
|
371
|
+
if (normalizedOutputFormat !== "stream-json") {
|
|
372
|
+
console.error(
|
|
373
|
+
"Error: --permission-prompt-tool=stdio requires --output-format=stream-json"
|
|
374
|
+
);
|
|
375
|
+
process.exit(1);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
if (normalizedInputFormat === "stream-json" && normalizedOutputFormat !== "stream-json") {
|
|
379
|
+
console.error(
|
|
380
|
+
"Error: --input-format=stream-json requires --output-format=stream-json"
|
|
381
|
+
);
|
|
382
|
+
process.exit(1);
|
|
383
|
+
}
|
|
384
|
+
if (replayUserMessages) {
|
|
385
|
+
if (normalizedInputFormat !== "stream-json" || normalizedOutputFormat !== "stream-json") {
|
|
386
|
+
console.error(
|
|
387
|
+
"Error: --replay-user-messages requires --input-format=stream-json and --output-format=stream-json"
|
|
388
|
+
);
|
|
389
|
+
process.exit(1);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
if (normalizedInputFormat === "stream-json") {
|
|
393
|
+
if (prompt) {
|
|
394
|
+
console.error(
|
|
395
|
+
"Error: --input-format=stream-json cannot be used with a prompt argument"
|
|
396
|
+
);
|
|
397
|
+
process.exit(1);
|
|
398
|
+
}
|
|
399
|
+
if (stdinContent) {
|
|
400
|
+
console.error(
|
|
401
|
+
"Error: --input-format=stream-json cannot be used with stdin prompt text"
|
|
402
|
+
);
|
|
403
|
+
process.exit(1);
|
|
404
|
+
}
|
|
405
|
+
} else {
|
|
406
|
+
if (!inputPrompt) {
|
|
407
|
+
console.error(
|
|
408
|
+
"Error: Input must be provided either through stdin or as a prompt argument when using --print"
|
|
409
|
+
);
|
|
410
|
+
process.exit(1);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
const toolsForPrint = (() => {
|
|
414
|
+
if (!cliTools) return tools;
|
|
415
|
+
const raw = Array.isArray(cliTools) ? cliTools : [cliTools];
|
|
416
|
+
const flattened = raw.flatMap((v) => String(v ?? "").split(",")).map((v) => v.trim());
|
|
417
|
+
if (flattened.length === 0) return tools;
|
|
418
|
+
if (flattened.length === 1 && flattened[0] === "") return [];
|
|
419
|
+
if (flattened.length === 1 && flattened[0] === "default") return tools;
|
|
420
|
+
const wanted = new Set(flattened.filter((v) => v && v !== "default"));
|
|
421
|
+
const unknown = [...wanted].filter(
|
|
422
|
+
(name) => !tools.some((t) => t.name === name)
|
|
423
|
+
);
|
|
424
|
+
if (unknown.length > 0) {
|
|
425
|
+
console.error(`Error: Unknown tool(s) in --tools: ${unknown.join(", ")}`);
|
|
426
|
+
process.exit(1);
|
|
427
|
+
}
|
|
428
|
+
return tools.filter((t) => wanted.has(t.name));
|
|
429
|
+
})();
|
|
430
|
+
if (normalizedOutputFormat === "text") {
|
|
431
|
+
addToHistory(inputPrompt);
|
|
432
|
+
const { resultText: response } = await ask({
|
|
433
|
+
commands,
|
|
434
|
+
hasPermissionsToUseTool,
|
|
435
|
+
messageLogName: dateToFilename(/* @__PURE__ */ new Date()),
|
|
436
|
+
prompt: inputPrompt,
|
|
437
|
+
cwd: cwd2,
|
|
438
|
+
tools: toolsForPrint,
|
|
439
|
+
safeMode: safe,
|
|
440
|
+
initialMessages,
|
|
441
|
+
persistSession: sessionPersistence !== false
|
|
442
|
+
});
|
|
443
|
+
process.stdout.write(`${response}
|
|
444
|
+
`);
|
|
445
|
+
process.exit(0);
|
|
446
|
+
}
|
|
447
|
+
const { createUserMessage } = await import("./messages-OFUJSPRV.js");
|
|
448
|
+
const { getSystemPrompt } = await import("./prompts-LWLAJRS2.js");
|
|
449
|
+
const { getContext: getContext2 } = await import("./context-JQIOOI4W.js");
|
|
450
|
+
const { getTotalCost } = await import("./costTracker-6SL26FDB.js");
|
|
451
|
+
const { query } = await import("./query-HVPWL27C.js");
|
|
452
|
+
const { getKodeAgentSessionId } = await import("./kodeAgentSessionId-X6XWQW7B.js");
|
|
453
|
+
const { kodeMessageToSdkMessage, makeSdkInitMessage, makeSdkResultMessage } = await import("./kodeAgentStreamJson-NXFN7TXH.js");
|
|
454
|
+
const { KodeAgentStructuredStdio: KodeAgentStructuredStdio2 } = await import("./kodeAgentStructuredStdio-HGWJT7CU.js");
|
|
455
|
+
const {
|
|
456
|
+
loadToolPermissionContextFromDisk,
|
|
457
|
+
persistToolPermissionUpdateToDisk
|
|
458
|
+
} = await import("./toolPermissionSettings-GPOBH4IV.js");
|
|
459
|
+
const { applyToolPermissionContextUpdates } = await import("./toolPermissionContext-65L65VEZ.js");
|
|
460
|
+
const sessionIdForSdk = getKodeAgentSessionId();
|
|
461
|
+
const startedAt = Date.now();
|
|
462
|
+
const sdkMessages = [];
|
|
463
|
+
const baseSystemPrompt = typeof systemPromptOverride === "string" && systemPromptOverride.trim() ? [systemPromptOverride] : await getSystemPrompt({ disableSlashCommands });
|
|
464
|
+
const systemPrompt = typeof appendSystemPrompt === "string" && appendSystemPrompt.trim() ? [...baseSystemPrompt, appendSystemPrompt] : baseSystemPrompt;
|
|
465
|
+
const normalizedJsonSchema = typeof jsonSchema === "string" ? jsonSchema.trim() : "";
|
|
466
|
+
const parsedJsonSchema = (() => {
|
|
467
|
+
if (!normalizedJsonSchema) return null;
|
|
468
|
+
try {
|
|
469
|
+
const parsed = JSON.parse(normalizedJsonSchema);
|
|
470
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
471
|
+
throw new Error("Schema must be a JSON object");
|
|
472
|
+
}
|
|
473
|
+
return parsed;
|
|
474
|
+
} catch (error) {
|
|
475
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
476
|
+
console.error(`Error: Invalid --json-schema: ${msg}`);
|
|
477
|
+
process.exit(1);
|
|
478
|
+
}
|
|
479
|
+
})();
|
|
480
|
+
if (parsedJsonSchema) {
|
|
481
|
+
systemPrompt.push(
|
|
482
|
+
[
|
|
483
|
+
"You MUST respond with ONLY valid JSON.",
|
|
484
|
+
"The JSON MUST validate against the following JSON Schema.",
|
|
485
|
+
"Do not wrap the JSON in markdown code fences and do not add extra commentary.",
|
|
486
|
+
"",
|
|
487
|
+
`<json_schema>${JSON.stringify(parsedJsonSchema)}</json_schema>`
|
|
488
|
+
].join("\n")
|
|
489
|
+
);
|
|
490
|
+
}
|
|
491
|
+
const ctx = await getContext2();
|
|
492
|
+
const isBypassAvailable = !safe || Boolean(allowDangerouslySkipPermissions) || Boolean(dangerouslySkipPermissions);
|
|
493
|
+
let toolPermissionContext = loadToolPermissionContextFromDisk({
|
|
494
|
+
projectDir: cwd2,
|
|
495
|
+
includeKodeProjectConfig: true,
|
|
496
|
+
isBypassPermissionsModeAvailable: isBypassAvailable
|
|
497
|
+
});
|
|
498
|
+
const cliRuleList = (value) => {
|
|
499
|
+
if (!value) return [];
|
|
500
|
+
const raw = Array.isArray(value) ? value : [value];
|
|
501
|
+
return raw.flatMap((v) => String(v ?? "").split(",")).map((v) => v.trim()).filter(Boolean);
|
|
502
|
+
};
|
|
503
|
+
const allowedRules = cliRuleList(allowedTools);
|
|
504
|
+
const deniedRules = cliRuleList(disallowedTools);
|
|
505
|
+
const additionalDirs = cliRuleList(addDir);
|
|
506
|
+
const updates = [];
|
|
507
|
+
if (allowedRules.length > 0) {
|
|
508
|
+
updates.push({
|
|
509
|
+
type: "addRules",
|
|
510
|
+
destination: "cliArg",
|
|
511
|
+
behavior: "allow",
|
|
512
|
+
rules: allowedRules
|
|
513
|
+
});
|
|
514
|
+
}
|
|
515
|
+
if (deniedRules.length > 0) {
|
|
516
|
+
updates.push({
|
|
517
|
+
type: "addRules",
|
|
518
|
+
destination: "cliArg",
|
|
519
|
+
behavior: "deny",
|
|
520
|
+
rules: deniedRules
|
|
521
|
+
});
|
|
522
|
+
}
|
|
523
|
+
if (additionalDirs.length > 0) {
|
|
524
|
+
updates.push({
|
|
525
|
+
type: "addDirectories",
|
|
526
|
+
destination: "cliArg",
|
|
527
|
+
directories: additionalDirs
|
|
528
|
+
});
|
|
529
|
+
}
|
|
530
|
+
const normalizedPermissionMode = typeof permissionMode === "string" ? permissionMode.trim() : "";
|
|
531
|
+
if (normalizedPermissionMode) {
|
|
532
|
+
const normalized = normalizedPermissionMode === "delegate" ? "default" : normalizedPermissionMode;
|
|
533
|
+
const allowed = /* @__PURE__ */ new Set([
|
|
534
|
+
"acceptEdits",
|
|
535
|
+
"bypassPermissions",
|
|
536
|
+
"default",
|
|
537
|
+
"dontAsk",
|
|
538
|
+
"plan"
|
|
539
|
+
]);
|
|
540
|
+
if (!allowed.has(normalized)) {
|
|
541
|
+
console.error(
|
|
542
|
+
`Error: Invalid --permission-mode "${normalizedPermissionMode}". Expected one of: acceptEdits, bypassPermissions, default, delegate, dontAsk, plan`
|
|
543
|
+
);
|
|
544
|
+
process.exit(1);
|
|
545
|
+
}
|
|
546
|
+
updates.push({
|
|
547
|
+
type: "setMode",
|
|
548
|
+
destination: "cliArg",
|
|
549
|
+
mode: normalized
|
|
550
|
+
});
|
|
551
|
+
}
|
|
552
|
+
if (dangerouslySkipPermissions) {
|
|
553
|
+
updates.push({
|
|
554
|
+
type: "setMode",
|
|
555
|
+
destination: "cliArg",
|
|
556
|
+
mode: "bypassPermissions"
|
|
557
|
+
});
|
|
558
|
+
}
|
|
559
|
+
if (updates.length > 0) {
|
|
560
|
+
toolPermissionContext = applyToolPermissionContextUpdates(
|
|
561
|
+
toolPermissionContext,
|
|
562
|
+
updates
|
|
563
|
+
);
|
|
564
|
+
}
|
|
565
|
+
const printOptions = {
|
|
566
|
+
commands,
|
|
567
|
+
tools: toolsForPrint,
|
|
568
|
+
verbose: true,
|
|
569
|
+
safeMode: safe,
|
|
570
|
+
forkNumber: 0,
|
|
571
|
+
messageLogName: "unused",
|
|
572
|
+
maxThinkingTokens: 0,
|
|
573
|
+
persistSession: sessionPersistence !== false,
|
|
574
|
+
toolPermissionContext,
|
|
575
|
+
mcpClients,
|
|
576
|
+
shouldAvoidPermissionPrompts: normalizedInputFormat !== "stream-json",
|
|
577
|
+
model: typeof model === "string" && model.trim() ? model.trim() : void 0
|
|
578
|
+
};
|
|
579
|
+
const availableTools = toolsForPrint.map((t) => t.name);
|
|
580
|
+
const slashCommands = disableSlashCommands === true ? void 0 : commands.filter((c) => !c.isHidden).map((c) => `/${c.userFacingName()}`);
|
|
581
|
+
const initMsg = makeSdkInitMessage({
|
|
582
|
+
sessionId: sessionIdForSdk,
|
|
583
|
+
cwd: cwd2,
|
|
584
|
+
tools: availableTools,
|
|
585
|
+
slashCommands
|
|
586
|
+
});
|
|
587
|
+
const writeSdkLine = (obj) => {
|
|
588
|
+
process.stdout.write(JSON.stringify(obj) + "\n");
|
|
589
|
+
};
|
|
590
|
+
if (normalizedOutputFormat === "stream-json") {
|
|
591
|
+
writeSdkLine(initMsg);
|
|
592
|
+
} else {
|
|
593
|
+
sdkMessages.push(initMsg);
|
|
594
|
+
}
|
|
595
|
+
let activeTurnAbortController = null;
|
|
596
|
+
const structured = createPrintModeStructuredStdio({
|
|
597
|
+
enabled: normalizedInputFormat === "stream-json",
|
|
598
|
+
stdin: process.stdin,
|
|
599
|
+
stdout: process.stdout,
|
|
600
|
+
onInterrupt: () => {
|
|
601
|
+
activeTurnAbortController?.abort();
|
|
602
|
+
},
|
|
603
|
+
onControlRequest: createPrintModeControlRequestHandler({
|
|
604
|
+
printOptions,
|
|
605
|
+
mcpClients
|
|
606
|
+
})
|
|
607
|
+
});
|
|
608
|
+
if (structured) structured.start();
|
|
609
|
+
const permissionTimeoutMs = (() => {
|
|
610
|
+
const raw = process.env.KODE_STDIO_PERMISSION_TIMEOUT_MS;
|
|
611
|
+
const n = raw ? Number(raw) : NaN;
|
|
612
|
+
return Number.isFinite(n) && n > 0 ? n : 3e4;
|
|
613
|
+
})();
|
|
614
|
+
const canUseTool = createStdioCanUseTool({
|
|
615
|
+
normalizedPermissionPromptTool,
|
|
616
|
+
structured,
|
|
617
|
+
permissionTimeoutMs,
|
|
618
|
+
cwd: cwd2,
|
|
619
|
+
printOptions,
|
|
620
|
+
hasPermissionsToUseTool,
|
|
621
|
+
applyToolPermissionContextUpdates,
|
|
622
|
+
persistToolPermissionUpdateToDisk
|
|
623
|
+
});
|
|
624
|
+
if (normalizedInputFormat === "stream-json") {
|
|
625
|
+
if (!structured) {
|
|
626
|
+
console.error("Error: Structured stdin is not available");
|
|
627
|
+
process.exit(1);
|
|
628
|
+
}
|
|
629
|
+
await runPrintModeStreamJsonSession({
|
|
630
|
+
structured,
|
|
631
|
+
query,
|
|
632
|
+
writeSdkLine,
|
|
633
|
+
sessionId: sessionIdForSdk,
|
|
634
|
+
systemPrompt,
|
|
635
|
+
jsonSchema: parsedJsonSchema,
|
|
636
|
+
context: ctx,
|
|
637
|
+
canUseTool,
|
|
638
|
+
toolUseContextBase: {
|
|
639
|
+
options: printOptions,
|
|
640
|
+
messageId: void 0,
|
|
641
|
+
readFileTimestamps: {},
|
|
642
|
+
setToolJSX: () => {
|
|
643
|
+
}
|
|
644
|
+
},
|
|
645
|
+
replayUserMessages: Boolean(replayUserMessages),
|
|
646
|
+
getTotalCostUsd: () => getTotalCost(),
|
|
647
|
+
onActiveTurnAbortControllerChanged: (controller) => {
|
|
648
|
+
activeTurnAbortController = controller;
|
|
649
|
+
},
|
|
650
|
+
initialMessages
|
|
651
|
+
});
|
|
652
|
+
process.exit(0);
|
|
653
|
+
}
|
|
654
|
+
const abortController = new AbortController();
|
|
655
|
+
const userMsg = await (async () => {
|
|
656
|
+
if (normalizedInputFormat !== "stream-json") {
|
|
657
|
+
addToHistory(inputPrompt);
|
|
658
|
+
return createUserMessage(inputPrompt);
|
|
659
|
+
}
|
|
660
|
+
if (!structured) {
|
|
661
|
+
console.error("Error: Structured stdin is not available");
|
|
662
|
+
process.exit(1);
|
|
663
|
+
}
|
|
664
|
+
const sdkUser2 = await structured.nextUserMessage({
|
|
665
|
+
signal: abortController.signal,
|
|
666
|
+
timeoutMs: 3e4
|
|
667
|
+
});
|
|
668
|
+
if (!sdkUser2 || typeof sdkUser2 !== "object") {
|
|
669
|
+
console.error("Error: Invalid stream-json input (missing user message)");
|
|
670
|
+
process.exit(1);
|
|
671
|
+
}
|
|
672
|
+
const sdkMessage = sdkUser2.message;
|
|
673
|
+
const sdkContent = sdkMessage?.content;
|
|
674
|
+
if (typeof sdkContent !== "string" && !Array.isArray(sdkContent)) {
|
|
675
|
+
console.error("Error: Invalid stream-json user message content");
|
|
676
|
+
process.exit(1);
|
|
677
|
+
}
|
|
678
|
+
const m = createUserMessage(sdkContent);
|
|
679
|
+
if (typeof sdkUser2.uuid === "string" && sdkUser2.uuid) {
|
|
680
|
+
;
|
|
681
|
+
m.uuid = String(sdkUser2.uuid);
|
|
682
|
+
}
|
|
683
|
+
return m;
|
|
684
|
+
})();
|
|
685
|
+
const baseMessages = [...initialMessages ?? [], userMsg];
|
|
686
|
+
const sdkUser = kodeMessageToSdkMessage(userMsg, sessionIdForSdk);
|
|
687
|
+
if (sdkUser) {
|
|
688
|
+
if (normalizedOutputFormat === "stream-json") {
|
|
689
|
+
writeSdkLine(sdkUser);
|
|
690
|
+
} else {
|
|
691
|
+
sdkMessages.push(sdkUser);
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
let lastAssistant = null;
|
|
695
|
+
let queryError = null;
|
|
696
|
+
try {
|
|
697
|
+
for await (const m of query(baseMessages, systemPrompt, ctx, canUseTool, {
|
|
698
|
+
options: printOptions,
|
|
699
|
+
abortController,
|
|
700
|
+
messageId: void 0,
|
|
701
|
+
readFileTimestamps: {},
|
|
702
|
+
setToolJSX: () => {
|
|
703
|
+
}
|
|
704
|
+
})) {
|
|
705
|
+
if (m.type === "assistant") lastAssistant = m;
|
|
706
|
+
const sdk = kodeMessageToSdkMessage(m, sessionIdForSdk);
|
|
707
|
+
if (!sdk) continue;
|
|
708
|
+
if (normalizedOutputFormat === "stream-json") {
|
|
709
|
+
writeSdkLine(sdk);
|
|
710
|
+
} else {
|
|
711
|
+
sdkMessages.push(sdk);
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
} catch (e) {
|
|
715
|
+
abortController.abort();
|
|
716
|
+
queryError = e;
|
|
717
|
+
}
|
|
718
|
+
const textFromAssistant = lastAssistant?.message?.content?.find(
|
|
719
|
+
(c) => c.type === "text"
|
|
720
|
+
)?.text;
|
|
721
|
+
let text = typeof textFromAssistant === "string" ? textFromAssistant : queryError instanceof Error ? queryError.message : queryError ? String(queryError) : "";
|
|
722
|
+
let structuredOutput;
|
|
723
|
+
if (parsedJsonSchema && !queryError) {
|
|
724
|
+
try {
|
|
725
|
+
const raw = typeof textFromAssistant === "string" ? textFromAssistant : "";
|
|
726
|
+
const fenced = raw.trim();
|
|
727
|
+
const unfenced = (() => {
|
|
728
|
+
const m = fenced.match(/^```(?:json)?\\s*([\\s\\S]*?)\\s*```$/i);
|
|
729
|
+
return m ? m[1].trim() : fenced;
|
|
730
|
+
})();
|
|
731
|
+
const parsed = JSON.parse(unfenced);
|
|
732
|
+
const Ajv = (await import("ajv")).default;
|
|
733
|
+
const ajv = new Ajv({ allErrors: true, strict: false });
|
|
734
|
+
const validate = ajv.compile(parsedJsonSchema);
|
|
735
|
+
const ok = validate(parsed);
|
|
736
|
+
if (!ok) {
|
|
737
|
+
const errorText = typeof ajv.errorsText === "function" ? ajv.errorsText(validate.errors, { separator: "; " }) : JSON.stringify(validate.errors ?? []);
|
|
738
|
+
throw new Error(
|
|
739
|
+
`Structured output failed JSON schema validation: ${errorText}`
|
|
740
|
+
);
|
|
741
|
+
}
|
|
742
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
743
|
+
throw new Error("Structured output must be a JSON object");
|
|
744
|
+
}
|
|
745
|
+
structuredOutput = parsed;
|
|
746
|
+
} catch (e) {
|
|
747
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
748
|
+
queryError = new Error(msg);
|
|
749
|
+
text = msg;
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
const usage = lastAssistant?.message?.usage;
|
|
753
|
+
const totalCostUsd = getTotalCost();
|
|
754
|
+
const durationMs = Date.now() - startedAt;
|
|
755
|
+
const resultMsg = makeSdkResultMessage({
|
|
756
|
+
sessionId: sessionIdForSdk,
|
|
757
|
+
result: String(text),
|
|
758
|
+
structuredOutput,
|
|
759
|
+
numTurns: 1,
|
|
760
|
+
usage,
|
|
761
|
+
totalCostUsd,
|
|
762
|
+
durationMs,
|
|
763
|
+
durationApiMs: 0,
|
|
764
|
+
isError: Boolean(queryError)
|
|
765
|
+
});
|
|
766
|
+
if (normalizedOutputFormat === "stream-json") {
|
|
767
|
+
writeSdkLine(resultMsg);
|
|
768
|
+
process.exit(0);
|
|
769
|
+
}
|
|
770
|
+
sdkMessages.push(resultMsg);
|
|
771
|
+
if (verbose) {
|
|
772
|
+
process.stdout.write(`${JSON.stringify(sdkMessages, null, 2)}
|
|
773
|
+
`);
|
|
774
|
+
} else {
|
|
775
|
+
process.stdout.write(`${JSON.stringify(resultMsg, null, 2)}
|
|
776
|
+
`);
|
|
777
|
+
}
|
|
778
|
+
process.exit(0);
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
// src/utils/session/cleanup.ts
|
|
782
|
+
import { promises as fs } from "fs";
|
|
783
|
+
import { join } from "path";
|
|
784
|
+
var THIRTY_DAYS_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
785
|
+
function convertFileNameToDate(filename) {
|
|
786
|
+
const isoStr = filename.split(".")[0].replace(/T(\d{2})-(\d{2})-(\d{2})-(\d{3})Z/, "T$1:$2:$3.$4Z");
|
|
787
|
+
return new Date(isoStr);
|
|
788
|
+
}
|
|
789
|
+
async function cleanupOldMessageFiles() {
|
|
790
|
+
const messagePath = CACHE_PATHS.messages();
|
|
791
|
+
const errorPath = CACHE_PATHS.errors();
|
|
792
|
+
const thirtyDaysAgo = new Date(Date.now() - THIRTY_DAYS_MS);
|
|
793
|
+
const deletedCounts = { messages: 0, errors: 0 };
|
|
794
|
+
for (const path of [messagePath, errorPath]) {
|
|
795
|
+
try {
|
|
796
|
+
const files = await fs.readdir(path);
|
|
797
|
+
for (const file of files) {
|
|
798
|
+
try {
|
|
799
|
+
const timestamp = convertFileNameToDate(file);
|
|
800
|
+
if (timestamp < thirtyDaysAgo) {
|
|
801
|
+
await fs.unlink(join(path, file));
|
|
802
|
+
if (path === messagePath) {
|
|
803
|
+
deletedCounts.messages++;
|
|
804
|
+
} else {
|
|
805
|
+
deletedCounts.errors++;
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
} catch (error) {
|
|
809
|
+
logError(
|
|
810
|
+
`Failed to process file ${file}: ${error instanceof Error ? error.message : String(error)}`
|
|
811
|
+
);
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
} catch (error) {
|
|
815
|
+
if (error instanceof Error && "code" in error && error.code !== "ENOENT") {
|
|
816
|
+
logError(
|
|
817
|
+
`Failed to cleanup directory ${path}: ${error instanceof Error ? error.message : String(error)}`
|
|
818
|
+
);
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
return deletedCounts;
|
|
823
|
+
}
|
|
824
|
+
function cleanupOldMessageFilesInBackground() {
|
|
825
|
+
const immediate = setImmediate(cleanupOldMessageFiles);
|
|
826
|
+
immediate.unref();
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
// src/entrypoints/cli/setup.ts
|
|
830
|
+
async function setup(cwd2, safeMode) {
|
|
831
|
+
if (cwd2 !== process.cwd()) {
|
|
832
|
+
setOriginalCwd(cwd2);
|
|
833
|
+
}
|
|
834
|
+
await setCwd(cwd2);
|
|
835
|
+
grantReadPermissionForOriginalDir();
|
|
836
|
+
let agentLoader;
|
|
837
|
+
try {
|
|
838
|
+
agentLoader = await import("./loader-AUXIJTY6.js");
|
|
839
|
+
} catch {
|
|
840
|
+
agentLoader = await import("./loader-AUXIJTY6.js");
|
|
841
|
+
}
|
|
842
|
+
const { startAgentWatcher } = agentLoader;
|
|
843
|
+
await startAgentWatcher(() => {
|
|
844
|
+
debug.info("AGENTS_HOT_RELOADED", { ok: true });
|
|
845
|
+
});
|
|
846
|
+
if (safeMode) {
|
|
847
|
+
if (process.platform !== "win32" && typeof process.getuid === "function" && process.getuid() === 0) {
|
|
848
|
+
console.error(
|
|
849
|
+
`--safe mode cannot be used with root/sudo privileges for security reasons`
|
|
850
|
+
);
|
|
851
|
+
process.exit(1);
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
if (process.env.NODE_ENV === "test") {
|
|
855
|
+
return;
|
|
856
|
+
}
|
|
857
|
+
cleanupOldMessageFilesInBackground();
|
|
858
|
+
getContext();
|
|
859
|
+
const projectConfig = getCurrentProjectConfig();
|
|
860
|
+
if (projectConfig.lastCost !== void 0 && projectConfig.lastDuration !== void 0) {
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
// src/entrypoints/cli/setupScreens.tsx
|
|
865
|
+
import React6 from "react";
|
|
866
|
+
|
|
867
|
+
// src/ui/components/TrustDialog.tsx
|
|
868
|
+
import React from "react";
|
|
869
|
+
import { Box, Text, useInput } from "ink";
|
|
870
|
+
import { homedir } from "os";
|
|
871
|
+
function TrustDialog({ onDone }) {
|
|
872
|
+
const theme = getTheme();
|
|
873
|
+
React.useEffect(() => {
|
|
874
|
+
}, []);
|
|
875
|
+
function onChange(value) {
|
|
876
|
+
const config = getCurrentProjectConfig();
|
|
877
|
+
switch (value) {
|
|
878
|
+
case "yes": {
|
|
879
|
+
const isHomeDir = homedir() === getCwd();
|
|
880
|
+
if (!isHomeDir) {
|
|
881
|
+
saveCurrentProjectConfig({
|
|
882
|
+
...config,
|
|
883
|
+
hasTrustDialogAccepted: true
|
|
884
|
+
});
|
|
885
|
+
}
|
|
886
|
+
onDone();
|
|
887
|
+
break;
|
|
888
|
+
}
|
|
889
|
+
case "no": {
|
|
890
|
+
process.exit(1);
|
|
891
|
+
break;
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
const exitState = useExitOnCtrlCD(() => process.exit(0));
|
|
896
|
+
useInput((_input, key) => {
|
|
897
|
+
if (key.escape) {
|
|
898
|
+
process.exit(0);
|
|
899
|
+
return;
|
|
900
|
+
}
|
|
901
|
+
});
|
|
902
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(
|
|
903
|
+
Box,
|
|
904
|
+
{
|
|
905
|
+
flexDirection: "column",
|
|
906
|
+
gap: 1,
|
|
907
|
+
padding: 1,
|
|
908
|
+
borderStyle: "round",
|
|
909
|
+
borderColor: theme.warning
|
|
910
|
+
},
|
|
911
|
+
/* @__PURE__ */ React.createElement(Text, { bold: true, color: theme.warning }, "Do you trust the files in this folder?"),
|
|
912
|
+
/* @__PURE__ */ React.createElement(Text, { bold: true }, process.cwd()),
|
|
913
|
+
/* @__PURE__ */ React.createElement(Box, { flexDirection: "column", gap: 1 }, /* @__PURE__ */ React.createElement(Text, null, PRODUCT_NAME, " may read files in this folder. Reading untrusted files may lead to ", PRODUCT_NAME, " to behave in an unexpected ways."), /* @__PURE__ */ React.createElement(Text, null, "With your permission ", PRODUCT_NAME, " may execute files in this folder. Executing untrusted code is unsafe.")),
|
|
914
|
+
/* @__PURE__ */ React.createElement(
|
|
915
|
+
Select,
|
|
916
|
+
{
|
|
917
|
+
options: [
|
|
918
|
+
{ label: "Yes, proceed", value: "yes" },
|
|
919
|
+
{ label: "No, exit", value: "no" }
|
|
920
|
+
],
|
|
921
|
+
onChange: (value) => onChange(value)
|
|
922
|
+
}
|
|
923
|
+
)
|
|
924
|
+
), /* @__PURE__ */ React.createElement(Box, { marginLeft: 3 }, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, exitState.pending ? /* @__PURE__ */ React.createElement(React.Fragment, null, "Press ", exitState.keyName, " again to exit") : /* @__PURE__ */ React.createElement(React.Fragment, null, "Enter to confirm \xB7 Esc to exit"))));
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
// src/ui/screens/MCPServerApproval.tsx
|
|
928
|
+
import React5 from "react";
|
|
929
|
+
import { render } from "ink";
|
|
930
|
+
|
|
931
|
+
// src/ui/components/MCPServerMultiselectDialog.tsx
|
|
932
|
+
import React3 from "react";
|
|
933
|
+
import { Box as Box2, Text as Text3, useInput as useInput2 } from "ink";
|
|
934
|
+
import { MultiSelect } from "@inkjs/ui";
|
|
935
|
+
import { partition } from "lodash-es";
|
|
936
|
+
|
|
937
|
+
// src/ui/components/MCPServerDialogCopy.tsx
|
|
938
|
+
import React2 from "react";
|
|
939
|
+
import { Text as Text2 } from "ink";
|
|
940
|
+
import Link from "ink-link";
|
|
941
|
+
function MCPServerDialogCopy() {
|
|
942
|
+
return /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(Text2, null, "MCP servers provide additional functionality to ", PRODUCT_NAME, ". They may execute code, make network requests, or access system resources via tool calls. All tool calls will require your explicit approval before execution. For more information, see", " ", /* @__PURE__ */ React2.createElement(Link, { url: "https://github.com/shareAI-lab/kode/blob/main/docs/mcp.md" }, "MCP documentation")), /* @__PURE__ */ React2.createElement(Text2, { dimColor: true }, "Remember: You can always change these choices later by running `", PRODUCT_COMMAND, " mcp reset-project-choices`"));
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
// src/ui/components/MCPServerMultiselectDialog.tsx
|
|
946
|
+
function MCPServerMultiselectDialog({
|
|
947
|
+
serverNames,
|
|
948
|
+
onDone
|
|
949
|
+
}) {
|
|
950
|
+
const theme = getTheme();
|
|
951
|
+
function onSubmit(selectedServers) {
|
|
952
|
+
const config = getCurrentProjectConfig();
|
|
953
|
+
if (!config.approvedMcprcServers) {
|
|
954
|
+
config.approvedMcprcServers = [];
|
|
955
|
+
}
|
|
956
|
+
if (!config.rejectedMcprcServers) {
|
|
957
|
+
config.rejectedMcprcServers = [];
|
|
958
|
+
}
|
|
959
|
+
const [approvedServers, rejectedServers] = partition(
|
|
960
|
+
serverNames,
|
|
961
|
+
(server) => selectedServers.includes(server)
|
|
962
|
+
);
|
|
963
|
+
config.approvedMcprcServers.push(...approvedServers);
|
|
964
|
+
config.rejectedMcprcServers.push(...rejectedServers);
|
|
965
|
+
saveCurrentProjectConfig(config);
|
|
966
|
+
onDone();
|
|
967
|
+
}
|
|
968
|
+
const exitState = useExitOnCtrlCD(() => process.exit());
|
|
969
|
+
useInput2((_input, key) => {
|
|
970
|
+
if (key.escape) {
|
|
971
|
+
const config = getCurrentProjectConfig();
|
|
972
|
+
if (!config.rejectedMcprcServers) {
|
|
973
|
+
config.rejectedMcprcServers = [];
|
|
974
|
+
}
|
|
975
|
+
for (const server of serverNames) {
|
|
976
|
+
if (!config.rejectedMcprcServers.includes(server)) {
|
|
977
|
+
config.rejectedMcprcServers.push(server);
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
saveCurrentProjectConfig(config);
|
|
981
|
+
onDone();
|
|
982
|
+
return;
|
|
983
|
+
}
|
|
984
|
+
});
|
|
985
|
+
return /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(
|
|
986
|
+
Box2,
|
|
987
|
+
{
|
|
988
|
+
flexDirection: "column",
|
|
989
|
+
gap: 1,
|
|
990
|
+
padding: 1,
|
|
991
|
+
borderStyle: "round",
|
|
992
|
+
borderColor: theme.warning
|
|
993
|
+
},
|
|
994
|
+
/* @__PURE__ */ React3.createElement(Text3, { bold: true, color: theme.warning }, "New MCP Servers Detected"),
|
|
995
|
+
/* @__PURE__ */ React3.createElement(Text3, null, "This project contains an MCP config file (.mcp.json or .mcprc) with", " ", serverNames.length, " MCP servers that require your approval."),
|
|
996
|
+
/* @__PURE__ */ React3.createElement(MCPServerDialogCopy, null),
|
|
997
|
+
/* @__PURE__ */ React3.createElement(Text3, null, "Please select the servers you want to enable:"),
|
|
998
|
+
/* @__PURE__ */ React3.createElement(
|
|
999
|
+
MultiSelect,
|
|
1000
|
+
{
|
|
1001
|
+
options: serverNames.map((server) => ({
|
|
1002
|
+
label: server,
|
|
1003
|
+
value: server
|
|
1004
|
+
})),
|
|
1005
|
+
defaultValue: serverNames,
|
|
1006
|
+
onSubmit
|
|
1007
|
+
}
|
|
1008
|
+
)
|
|
1009
|
+
), /* @__PURE__ */ React3.createElement(Box2, { marginLeft: 3 }, /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, exitState.pending ? /* @__PURE__ */ React3.createElement(React3.Fragment, null, "Press ", exitState.keyName, " again to exit") : /* @__PURE__ */ React3.createElement(React3.Fragment, null, "Space to select \xB7 Enter to confirm \xB7 Esc to reject all"))));
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
// src/ui/components/MCPServerApprovalDialog.tsx
|
|
1013
|
+
import React4 from "react";
|
|
1014
|
+
import { Box as Box3, Text as Text4, useInput as useInput3 } from "ink";
|
|
1015
|
+
function MCPServerApprovalDialog({
|
|
1016
|
+
serverName,
|
|
1017
|
+
onDone
|
|
1018
|
+
}) {
|
|
1019
|
+
const theme = getTheme();
|
|
1020
|
+
function onChange(value) {
|
|
1021
|
+
const config = getCurrentProjectConfig();
|
|
1022
|
+
switch (value) {
|
|
1023
|
+
case "yes": {
|
|
1024
|
+
if (!config.approvedMcprcServers) {
|
|
1025
|
+
config.approvedMcprcServers = [];
|
|
1026
|
+
}
|
|
1027
|
+
if (!config.approvedMcprcServers.includes(serverName)) {
|
|
1028
|
+
config.approvedMcprcServers.push(serverName);
|
|
1029
|
+
}
|
|
1030
|
+
saveCurrentProjectConfig(config);
|
|
1031
|
+
onDone();
|
|
1032
|
+
break;
|
|
1033
|
+
}
|
|
1034
|
+
case "no": {
|
|
1035
|
+
if (!config.rejectedMcprcServers) {
|
|
1036
|
+
config.rejectedMcprcServers = [];
|
|
1037
|
+
}
|
|
1038
|
+
if (!config.rejectedMcprcServers.includes(serverName)) {
|
|
1039
|
+
config.rejectedMcprcServers.push(serverName);
|
|
1040
|
+
}
|
|
1041
|
+
saveCurrentProjectConfig(config);
|
|
1042
|
+
onDone();
|
|
1043
|
+
break;
|
|
1044
|
+
}
|
|
1045
|
+
}
|
|
1046
|
+
}
|
|
1047
|
+
const exitState = useExitOnCtrlCD(() => process.exit(0));
|
|
1048
|
+
useInput3((_input, key) => {
|
|
1049
|
+
if (key.escape) {
|
|
1050
|
+
onDone();
|
|
1051
|
+
return;
|
|
1052
|
+
}
|
|
1053
|
+
});
|
|
1054
|
+
return /* @__PURE__ */ React4.createElement(React4.Fragment, null, /* @__PURE__ */ React4.createElement(
|
|
1055
|
+
Box3,
|
|
1056
|
+
{
|
|
1057
|
+
flexDirection: "column",
|
|
1058
|
+
gap: 1,
|
|
1059
|
+
padding: 1,
|
|
1060
|
+
borderStyle: "round",
|
|
1061
|
+
borderColor: theme.warning
|
|
1062
|
+
},
|
|
1063
|
+
/* @__PURE__ */ React4.createElement(Text4, { bold: true, color: theme.warning }, "New MCP Server Detected"),
|
|
1064
|
+
/* @__PURE__ */ React4.createElement(Text4, null, "This project contains an MCP config file (.mcp.json or .mcprc) with an MCP server that requires your approval:"),
|
|
1065
|
+
/* @__PURE__ */ React4.createElement(Text4, { bold: true }, serverName),
|
|
1066
|
+
/* @__PURE__ */ React4.createElement(MCPServerDialogCopy, null),
|
|
1067
|
+
/* @__PURE__ */ React4.createElement(Text4, null, "Do you want to approve this MCP server?"),
|
|
1068
|
+
/* @__PURE__ */ React4.createElement(
|
|
1069
|
+
Select,
|
|
1070
|
+
{
|
|
1071
|
+
options: [
|
|
1072
|
+
{ label: "Yes, approve this server", value: "yes" },
|
|
1073
|
+
{ label: "No, reject this server", value: "no" }
|
|
1074
|
+
],
|
|
1075
|
+
onChange: (value) => onChange(value)
|
|
1076
|
+
}
|
|
1077
|
+
)
|
|
1078
|
+
), /* @__PURE__ */ React4.createElement(Box3, { marginLeft: 3 }, /* @__PURE__ */ React4.createElement(Text4, { dimColor: true }, exitState.pending ? /* @__PURE__ */ React4.createElement(React4.Fragment, null, "Press ", exitState.keyName, " again to exit") : /* @__PURE__ */ React4.createElement(React4.Fragment, null, "Enter to confirm \xB7 Esc to reject"))));
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
// src/ui/screens/MCPServerApproval.tsx
|
|
1082
|
+
async function handleMcprcServerApprovals() {
|
|
1083
|
+
const { servers } = getProjectMcpServerDefinitions();
|
|
1084
|
+
const pendingServers = Object.keys(servers).filter(
|
|
1085
|
+
(serverName) => getMcprcServerStatus(serverName) === "pending"
|
|
1086
|
+
);
|
|
1087
|
+
if (pendingServers.length === 0) {
|
|
1088
|
+
return;
|
|
1089
|
+
}
|
|
1090
|
+
await new Promise((resolve) => {
|
|
1091
|
+
const clearScreenAndResolve = () => {
|
|
1092
|
+
process.stdout.write("\x1B[2J\x1B[3J\x1B[H", () => {
|
|
1093
|
+
resolve();
|
|
1094
|
+
});
|
|
1095
|
+
};
|
|
1096
|
+
if (pendingServers.length === 1 && pendingServers[0] !== void 0) {
|
|
1097
|
+
const result = render(
|
|
1098
|
+
/* @__PURE__ */ React5.createElement(
|
|
1099
|
+
MCPServerApprovalDialog,
|
|
1100
|
+
{
|
|
1101
|
+
serverName: pendingServers[0],
|
|
1102
|
+
onDone: () => {
|
|
1103
|
+
result.unmount?.();
|
|
1104
|
+
clearScreenAndResolve();
|
|
1105
|
+
}
|
|
1106
|
+
}
|
|
1107
|
+
),
|
|
1108
|
+
{ exitOnCtrlC: false }
|
|
1109
|
+
);
|
|
1110
|
+
} else {
|
|
1111
|
+
const result = render(
|
|
1112
|
+
/* @__PURE__ */ React5.createElement(
|
|
1113
|
+
MCPServerMultiselectDialog,
|
|
1114
|
+
{
|
|
1115
|
+
serverNames: pendingServers,
|
|
1116
|
+
onDone: () => {
|
|
1117
|
+
result.unmount?.();
|
|
1118
|
+
clearScreenAndResolve();
|
|
1119
|
+
}
|
|
1120
|
+
}
|
|
1121
|
+
),
|
|
1122
|
+
{ exitOnCtrlC: false }
|
|
1123
|
+
);
|
|
1124
|
+
}
|
|
1125
|
+
});
|
|
1126
|
+
}
|
|
1127
|
+
|
|
1128
|
+
// src/entrypoints/cli/setupScreens.tsx
|
|
1129
|
+
function completeOnboarding() {
|
|
1130
|
+
const config = getGlobalConfig();
|
|
1131
|
+
saveGlobalConfig({
|
|
1132
|
+
...config,
|
|
1133
|
+
hasCompletedOnboarding: true,
|
|
1134
|
+
lastOnboardingVersion: MACRO.VERSION
|
|
1135
|
+
});
|
|
1136
|
+
}
|
|
1137
|
+
async function showSetupScreens(safeMode, print) {
|
|
1138
|
+
if (process.env.NODE_ENV === "test") {
|
|
1139
|
+
return;
|
|
1140
|
+
}
|
|
1141
|
+
const config = getGlobalConfig();
|
|
1142
|
+
if (!config.theme || !config.hasCompletedOnboarding) {
|
|
1143
|
+
await clearTerminal();
|
|
1144
|
+
const { render: render3 } = await import("ink");
|
|
1145
|
+
await new Promise((resolve) => {
|
|
1146
|
+
render3(
|
|
1147
|
+
/* @__PURE__ */ React6.createElement(
|
|
1148
|
+
Onboarding,
|
|
1149
|
+
{
|
|
1150
|
+
onDone: async () => {
|
|
1151
|
+
completeOnboarding();
|
|
1152
|
+
await clearTerminal();
|
|
1153
|
+
resolve();
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1156
|
+
),
|
|
1157
|
+
{
|
|
1158
|
+
exitOnCtrlC: false
|
|
1159
|
+
}
|
|
1160
|
+
);
|
|
1161
|
+
});
|
|
1162
|
+
}
|
|
1163
|
+
if (!print) {
|
|
1164
|
+
if (safeMode) {
|
|
1165
|
+
if (!checkHasTrustDialogAccepted()) {
|
|
1166
|
+
await new Promise((resolve) => {
|
|
1167
|
+
const onDone = () => {
|
|
1168
|
+
grantReadPermissionForOriginalDir();
|
|
1169
|
+
resolve();
|
|
1170
|
+
};
|
|
1171
|
+
(async () => {
|
|
1172
|
+
const { render: render3 } = await import("ink");
|
|
1173
|
+
render3(/* @__PURE__ */ React6.createElement(TrustDialog, { onDone }), {
|
|
1174
|
+
exitOnCtrlC: false
|
|
1175
|
+
});
|
|
1176
|
+
})();
|
|
1177
|
+
});
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
await handleMcprcServerApprovals();
|
|
1181
|
+
}
|
|
1182
|
+
}
|
|
1183
|
+
|
|
1184
|
+
// src/entrypoints/cli/runCli.tsx
|
|
1185
|
+
import React10 from "react";
|
|
1186
|
+
import { ReadStream } from "tty";
|
|
1187
|
+
import { openSync } from "fs";
|
|
1188
|
+
import { Command } from "@commander-js/extra-typings";
|
|
1189
|
+
import { cwd } from "process";
|
|
1190
|
+
|
|
1191
|
+
// src/utils/model/modelConfigYaml.ts
|
|
1192
|
+
import yaml from "js-yaml";
|
|
1193
|
+
import { z } from "zod";
|
|
1194
|
+
var ApiKeySpecSchema = z.union([
|
|
1195
|
+
z.object({
|
|
1196
|
+
fromEnv: z.string().min(1)
|
|
1197
|
+
}).strict(),
|
|
1198
|
+
z.object({
|
|
1199
|
+
value: z.string()
|
|
1200
|
+
}).strict()
|
|
1201
|
+
]);
|
|
1202
|
+
var ModelProfileYamlSchema = z.object({
|
|
1203
|
+
name: z.string().min(1),
|
|
1204
|
+
provider: z.string().min(1),
|
|
1205
|
+
modelName: z.string().min(1),
|
|
1206
|
+
baseURL: z.string().min(1).optional(),
|
|
1207
|
+
maxTokens: z.number().int().positive(),
|
|
1208
|
+
contextLength: z.number().int().positive(),
|
|
1209
|
+
reasoningEffort: z.string().optional(),
|
|
1210
|
+
isActive: z.boolean().optional(),
|
|
1211
|
+
apiKey: ApiKeySpecSchema.optional(),
|
|
1212
|
+
apiKeyEnv: z.string().min(1).optional(),
|
|
1213
|
+
createdAt: z.number().int().positive().optional(),
|
|
1214
|
+
lastUsed: z.number().int().positive().optional()
|
|
1215
|
+
}).strict();
|
|
1216
|
+
var ModelPointersYamlSchema = z.object({
|
|
1217
|
+
main: z.string().min(1).optional(),
|
|
1218
|
+
task: z.string().min(1).optional(),
|
|
1219
|
+
compact: z.string().min(1).optional(),
|
|
1220
|
+
quick: z.string().min(1).optional()
|
|
1221
|
+
}).strict().optional();
|
|
1222
|
+
var ModelConfigYamlSchema = z.object({
|
|
1223
|
+
version: z.number().int().positive().default(1),
|
|
1224
|
+
profiles: z.array(ModelProfileYamlSchema).default([]),
|
|
1225
|
+
pointers: ModelPointersYamlSchema
|
|
1226
|
+
}).strict();
|
|
1227
|
+
function suggestedApiKeyEnvForProvider(provider) {
|
|
1228
|
+
switch (provider) {
|
|
1229
|
+
case "anthropic":
|
|
1230
|
+
return "ANTHROPIC_API_KEY";
|
|
1231
|
+
case "openai":
|
|
1232
|
+
case "custom-openai":
|
|
1233
|
+
return "OPENAI_API_KEY";
|
|
1234
|
+
case "azure":
|
|
1235
|
+
return "AZURE_OPENAI_API_KEY";
|
|
1236
|
+
case "gemini":
|
|
1237
|
+
return "GEMINI_API_KEY";
|
|
1238
|
+
default:
|
|
1239
|
+
return void 0;
|
|
1240
|
+
}
|
|
1241
|
+
}
|
|
1242
|
+
function resolveApiKeyFromYaml(input, existingApiKey) {
|
|
1243
|
+
const warnings = [];
|
|
1244
|
+
if (input.apiKeyEnv) {
|
|
1245
|
+
const envValue = process.env[input.apiKeyEnv];
|
|
1246
|
+
if (envValue) return { apiKey: envValue, warnings };
|
|
1247
|
+
if (existingApiKey) return { apiKey: existingApiKey, warnings };
|
|
1248
|
+
warnings.push(`Missing env var '${input.apiKeyEnv}' for apiKey`);
|
|
1249
|
+
return { apiKey: "", warnings };
|
|
1250
|
+
}
|
|
1251
|
+
if (input.apiKey && "fromEnv" in input.apiKey) {
|
|
1252
|
+
const envValue = process.env[input.apiKey.fromEnv];
|
|
1253
|
+
if (envValue) return { apiKey: envValue, warnings };
|
|
1254
|
+
if (existingApiKey) return { apiKey: existingApiKey, warnings };
|
|
1255
|
+
warnings.push(`Missing env var '${input.apiKey.fromEnv}' for apiKey`);
|
|
1256
|
+
return { apiKey: "", warnings };
|
|
1257
|
+
}
|
|
1258
|
+
if (input.apiKey && "value" in input.apiKey) {
|
|
1259
|
+
return { apiKey: input.apiKey.value, warnings };
|
|
1260
|
+
}
|
|
1261
|
+
if (existingApiKey) return { apiKey: existingApiKey, warnings };
|
|
1262
|
+
warnings.push(
|
|
1263
|
+
"Missing apiKey (set apiKey.fromEnv, apiKeyEnv, or apiKey.value)"
|
|
1264
|
+
);
|
|
1265
|
+
return { apiKey: "", warnings };
|
|
1266
|
+
}
|
|
1267
|
+
function resolvePointerTarget(pointerValue, profiles) {
|
|
1268
|
+
if (profiles.some((p) => p.modelName === pointerValue)) return pointerValue;
|
|
1269
|
+
const byName = profiles.find((p) => p.name === pointerValue);
|
|
1270
|
+
return byName?.modelName ?? null;
|
|
1271
|
+
}
|
|
1272
|
+
function parseModelConfigYaml(yamlText) {
|
|
1273
|
+
const parsed = yaml.load(yamlText);
|
|
1274
|
+
return ModelConfigYamlSchema.parse(parsed);
|
|
1275
|
+
}
|
|
1276
|
+
function formatModelConfigYamlForSharing(config) {
|
|
1277
|
+
const modelProfiles = config.modelProfiles ?? [];
|
|
1278
|
+
const pointers = config.modelPointers;
|
|
1279
|
+
const exported = {
|
|
1280
|
+
version: 1,
|
|
1281
|
+
profiles: modelProfiles.map((p) => {
|
|
1282
|
+
const suggestedEnv = suggestedApiKeyEnvForProvider(p.provider);
|
|
1283
|
+
return {
|
|
1284
|
+
name: p.name,
|
|
1285
|
+
provider: p.provider,
|
|
1286
|
+
modelName: p.modelName,
|
|
1287
|
+
...p.baseURL ? { baseURL: p.baseURL } : {},
|
|
1288
|
+
maxTokens: p.maxTokens,
|
|
1289
|
+
contextLength: p.contextLength,
|
|
1290
|
+
...p.reasoningEffort ? { reasoningEffort: p.reasoningEffort } : {},
|
|
1291
|
+
isActive: p.isActive,
|
|
1292
|
+
createdAt: p.createdAt,
|
|
1293
|
+
...typeof p.lastUsed === "number" ? { lastUsed: p.lastUsed } : {},
|
|
1294
|
+
apiKey: { fromEnv: suggestedEnv ?? "API_KEY" }
|
|
1295
|
+
};
|
|
1296
|
+
}),
|
|
1297
|
+
...pointers ? { pointers } : {}
|
|
1298
|
+
};
|
|
1299
|
+
return yaml.dump(exported, {
|
|
1300
|
+
noRefs: true,
|
|
1301
|
+
lineWidth: 120
|
|
1302
|
+
});
|
|
1303
|
+
}
|
|
1304
|
+
function applyModelConfigYamlImport(existingConfig, yamlText, options = {}) {
|
|
1305
|
+
const parsed = parseModelConfigYaml(yamlText);
|
|
1306
|
+
const warnings = [];
|
|
1307
|
+
const existingProfiles = existingConfig.modelProfiles ?? [];
|
|
1308
|
+
const existingByModelName = new Map(
|
|
1309
|
+
existingProfiles.map((p) => [p.modelName, p])
|
|
1310
|
+
);
|
|
1311
|
+
const now = Date.now();
|
|
1312
|
+
const importedProfiles = parsed.profiles.map((profile) => {
|
|
1313
|
+
const existing = existingByModelName.get(profile.modelName);
|
|
1314
|
+
const resolved = resolveApiKeyFromYaml(
|
|
1315
|
+
{ apiKey: profile.apiKey, apiKeyEnv: profile.apiKeyEnv },
|
|
1316
|
+
existing?.apiKey
|
|
1317
|
+
);
|
|
1318
|
+
warnings.push(...resolved.warnings.map((w) => `[${profile.modelName}] ${w}`));
|
|
1319
|
+
return {
|
|
1320
|
+
name: profile.name,
|
|
1321
|
+
provider: profile.provider,
|
|
1322
|
+
modelName: profile.modelName,
|
|
1323
|
+
...profile.baseURL ? { baseURL: profile.baseURL } : {},
|
|
1324
|
+
apiKey: resolved.apiKey,
|
|
1325
|
+
maxTokens: profile.maxTokens,
|
|
1326
|
+
contextLength: profile.contextLength,
|
|
1327
|
+
...profile.reasoningEffort ? { reasoningEffort: profile.reasoningEffort } : {},
|
|
1328
|
+
isActive: profile.isActive ?? true,
|
|
1329
|
+
createdAt: profile.createdAt ?? existing?.createdAt ?? now,
|
|
1330
|
+
...profile.lastUsed ? { lastUsed: profile.lastUsed } : existing?.lastUsed ? { lastUsed: existing.lastUsed } : {},
|
|
1331
|
+
...existing?.isGPT5 ? { isGPT5: existing.isGPT5 } : {},
|
|
1332
|
+
...existing?.validationStatus ? { validationStatus: existing.validationStatus } : {},
|
|
1333
|
+
...existing?.lastValidation ? { lastValidation: existing.lastValidation } : {}
|
|
1334
|
+
};
|
|
1335
|
+
});
|
|
1336
|
+
const mergedProfiles = options.replace ? importedProfiles : [
|
|
1337
|
+
...existingProfiles.filter(
|
|
1338
|
+
(p) => !importedProfiles.some((i) => i.modelName === p.modelName)
|
|
1339
|
+
),
|
|
1340
|
+
...importedProfiles
|
|
1341
|
+
];
|
|
1342
|
+
const nextPointers = {
|
|
1343
|
+
...existingConfig.modelPointers ?? {
|
|
1344
|
+
main: "",
|
|
1345
|
+
task: "",
|
|
1346
|
+
compact: "",
|
|
1347
|
+
quick: ""
|
|
1348
|
+
}
|
|
1349
|
+
};
|
|
1350
|
+
if (parsed.pointers) {
|
|
1351
|
+
const resolvedMain = parsed.pointers.main && resolvePointerTarget(parsed.pointers.main, mergedProfiles);
|
|
1352
|
+
const resolvedTask = parsed.pointers.task && resolvePointerTarget(parsed.pointers.task, mergedProfiles);
|
|
1353
|
+
const resolvedCompact = parsed.pointers.compact && resolvePointerTarget(parsed.pointers.compact, mergedProfiles);
|
|
1354
|
+
const resolvedQuick = parsed.pointers.quick && resolvePointerTarget(parsed.pointers.quick, mergedProfiles);
|
|
1355
|
+
if (parsed.pointers.main && !resolvedMain) {
|
|
1356
|
+
warnings.push(
|
|
1357
|
+
`[pointers.main] Unknown model '${parsed.pointers.main}' (expected modelName or profile name)`
|
|
1358
|
+
);
|
|
1359
|
+
} else if (resolvedMain) {
|
|
1360
|
+
nextPointers.main = resolvedMain;
|
|
1361
|
+
}
|
|
1362
|
+
if (parsed.pointers.task && !resolvedTask) {
|
|
1363
|
+
warnings.push(
|
|
1364
|
+
`[pointers.task] Unknown model '${parsed.pointers.task}' (expected modelName or profile name)`
|
|
1365
|
+
);
|
|
1366
|
+
} else if (resolvedTask) {
|
|
1367
|
+
nextPointers.task = resolvedTask;
|
|
1368
|
+
}
|
|
1369
|
+
if (parsed.pointers.compact && !resolvedCompact) {
|
|
1370
|
+
warnings.push(
|
|
1371
|
+
`[pointers.compact] Unknown model '${parsed.pointers.compact}' (expected modelName or profile name)`
|
|
1372
|
+
);
|
|
1373
|
+
} else if (resolvedCompact) {
|
|
1374
|
+
nextPointers.compact = resolvedCompact;
|
|
1375
|
+
}
|
|
1376
|
+
if (parsed.pointers.quick && !resolvedQuick) {
|
|
1377
|
+
warnings.push(
|
|
1378
|
+
`[pointers.quick] Unknown model '${parsed.pointers.quick}' (expected modelName or profile name)`
|
|
1379
|
+
);
|
|
1380
|
+
} else if (resolvedQuick) {
|
|
1381
|
+
nextPointers.quick = resolvedQuick;
|
|
1382
|
+
}
|
|
1383
|
+
}
|
|
1384
|
+
return {
|
|
1385
|
+
nextConfig: {
|
|
1386
|
+
...existingConfig,
|
|
1387
|
+
modelProfiles: mergedProfiles,
|
|
1388
|
+
modelPointers: nextPointers
|
|
1389
|
+
},
|
|
1390
|
+
warnings
|
|
1391
|
+
};
|
|
1392
|
+
}
|
|
1393
|
+
|
|
1394
|
+
// src/ui/screens/LogList.tsx
|
|
1395
|
+
import React8, { useEffect, useState } from "react";
|
|
1396
|
+
|
|
1397
|
+
// src/ui/components/LogSelector.tsx
|
|
1398
|
+
import React7 from "react";
|
|
1399
|
+
import { Box as Box4, Text as Text5 } from "ink";
|
|
1400
|
+
function LogSelector({
|
|
1401
|
+
logs,
|
|
1402
|
+
onSelect
|
|
1403
|
+
}) {
|
|
1404
|
+
const { rows, columns } = useTerminalSize();
|
|
1405
|
+
if (logs.length === 0) {
|
|
1406
|
+
return null;
|
|
1407
|
+
}
|
|
1408
|
+
const visibleCount = rows - 3;
|
|
1409
|
+
const hiddenCount = Math.max(0, logs.length - visibleCount);
|
|
1410
|
+
const indexWidth = 7;
|
|
1411
|
+
const modifiedWidth = 21;
|
|
1412
|
+
const createdWidth = 21;
|
|
1413
|
+
const countWidth = 9;
|
|
1414
|
+
const options = logs.map((log, i) => {
|
|
1415
|
+
const index = `[${i}]`.padEnd(indexWidth);
|
|
1416
|
+
const modified = formatDate(log.modified).padEnd(modifiedWidth);
|
|
1417
|
+
const created = formatDate(log.created).padEnd(createdWidth);
|
|
1418
|
+
const msgCount = `${log.messageCount}`.padStart(countWidth);
|
|
1419
|
+
const prompt = log.firstPrompt;
|
|
1420
|
+
let branchInfo = "";
|
|
1421
|
+
if (log.forkNumber) branchInfo += ` (fork #${log.forkNumber})`;
|
|
1422
|
+
if (log.sidechainNumber)
|
|
1423
|
+
branchInfo += ` (sidechain #${log.sidechainNumber})`;
|
|
1424
|
+
const labelTxt = `${index}${modified}${created}${msgCount} ${prompt}${branchInfo}`;
|
|
1425
|
+
const truncated = labelTxt.length > columns - 2 ? `${labelTxt.slice(0, columns - 5)}...` : labelTxt;
|
|
1426
|
+
return {
|
|
1427
|
+
label: truncated,
|
|
1428
|
+
value: log.value.toString()
|
|
1429
|
+
};
|
|
1430
|
+
});
|
|
1431
|
+
return /* @__PURE__ */ React7.createElement(Box4, { flexDirection: "column", height: "100%", width: "100%" }, /* @__PURE__ */ React7.createElement(Box4, { paddingLeft: 9 }, /* @__PURE__ */ React7.createElement(Text5, { bold: true, color: getTheme().text }, "Modified"), /* @__PURE__ */ React7.createElement(Text5, null, " "), /* @__PURE__ */ React7.createElement(Text5, { bold: true, color: getTheme().text }, "Created"), /* @__PURE__ */ React7.createElement(Text5, null, " "), /* @__PURE__ */ React7.createElement(Text5, { bold: true, color: getTheme().text }, "# Messages"), /* @__PURE__ */ React7.createElement(Text5, null, " "), /* @__PURE__ */ React7.createElement(Text5, { bold: true, color: getTheme().text }, "First message")), /* @__PURE__ */ React7.createElement(
|
|
1432
|
+
Select,
|
|
1433
|
+
{
|
|
1434
|
+
options,
|
|
1435
|
+
onChange: (index) => onSelect(parseInt(index, 10)),
|
|
1436
|
+
visibleOptionCount: visibleCount
|
|
1437
|
+
}
|
|
1438
|
+
), hiddenCount > 0 && /* @__PURE__ */ React7.createElement(Box4, { paddingLeft: 2 }, /* @__PURE__ */ React7.createElement(Text5, { color: getTheme().secondaryText }, "and ", hiddenCount, " more\u2026")));
|
|
1439
|
+
}
|
|
1440
|
+
|
|
1441
|
+
// src/ui/screens/LogList.tsx
|
|
1442
|
+
function LogList({ context, type, logNumber }) {
|
|
1443
|
+
const [logs, setLogs] = useState([]);
|
|
1444
|
+
const [didSelectLog, setDidSelectLog] = useState(false);
|
|
1445
|
+
useEffect(() => {
|
|
1446
|
+
loadLogList(
|
|
1447
|
+
type === "messages" ? CACHE_PATHS.messages() : CACHE_PATHS.errors()
|
|
1448
|
+
).then((logs2) => {
|
|
1449
|
+
if (logNumber !== void 0) {
|
|
1450
|
+
const log = logs2[logNumber >= 0 ? logNumber : 0];
|
|
1451
|
+
if (log) {
|
|
1452
|
+
console.log(JSON.stringify(log.messages, null, 2));
|
|
1453
|
+
process.exit(0);
|
|
1454
|
+
} else {
|
|
1455
|
+
console.error("No log found at index", logNumber);
|
|
1456
|
+
process.exit(1);
|
|
1457
|
+
}
|
|
1458
|
+
}
|
|
1459
|
+
setLogs(logs2);
|
|
1460
|
+
}).catch((error) => {
|
|
1461
|
+
logError(error);
|
|
1462
|
+
if (logNumber !== void 0) {
|
|
1463
|
+
process.exit(1);
|
|
1464
|
+
} else {
|
|
1465
|
+
context.unmount?.();
|
|
1466
|
+
}
|
|
1467
|
+
});
|
|
1468
|
+
}, [context, type, logNumber]);
|
|
1469
|
+
function onSelect(index) {
|
|
1470
|
+
const log = logs[index];
|
|
1471
|
+
if (!log) {
|
|
1472
|
+
return;
|
|
1473
|
+
}
|
|
1474
|
+
setDidSelectLog(true);
|
|
1475
|
+
setTimeout(() => {
|
|
1476
|
+
console.log(JSON.stringify(log.messages, null, 2));
|
|
1477
|
+
process.exit(0);
|
|
1478
|
+
}, 100);
|
|
1479
|
+
}
|
|
1480
|
+
if (logNumber !== void 0) {
|
|
1481
|
+
return null;
|
|
1482
|
+
}
|
|
1483
|
+
if (didSelectLog) {
|
|
1484
|
+
return null;
|
|
1485
|
+
}
|
|
1486
|
+
return /* @__PURE__ */ React8.createElement(LogSelector, { logs, onSelect });
|
|
1487
|
+
}
|
|
1488
|
+
|
|
1489
|
+
// src/entrypoints/mcp.ts
|
|
1490
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
1491
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
1492
|
+
import {
|
|
1493
|
+
CallToolRequestSchema,
|
|
1494
|
+
ListToolsRequestSchema
|
|
1495
|
+
} from "@modelcontextprotocol/sdk/types.js";
|
|
1496
|
+
import { zodToJsonSchema } from "zod-to-json-schema";
|
|
1497
|
+
var state = {
|
|
1498
|
+
readFileTimestamps: {}
|
|
1499
|
+
};
|
|
1500
|
+
var MCP_COMMANDS = [review_default];
|
|
1501
|
+
var MCP_TOOLS = [...getAllTools()];
|
|
1502
|
+
async function startMCPServer(cwd2) {
|
|
1503
|
+
await setCwd(cwd2);
|
|
1504
|
+
const server = new Server(
|
|
1505
|
+
{
|
|
1506
|
+
name: "claude/tengu",
|
|
1507
|
+
version: MACRO.VERSION
|
|
1508
|
+
},
|
|
1509
|
+
{
|
|
1510
|
+
capabilities: {
|
|
1511
|
+
tools: {}
|
|
1512
|
+
}
|
|
1513
|
+
}
|
|
1514
|
+
);
|
|
1515
|
+
server.setRequestHandler(
|
|
1516
|
+
ListToolsRequestSchema,
|
|
1517
|
+
async () => {
|
|
1518
|
+
const tools = await Promise.all(
|
|
1519
|
+
MCP_TOOLS.map(async (tool) => ({
|
|
1520
|
+
...tool,
|
|
1521
|
+
description: getToolDescription(tool),
|
|
1522
|
+
inputSchema: zodToJsonSchema(
|
|
1523
|
+
tool.inputSchema
|
|
1524
|
+
)
|
|
1525
|
+
}))
|
|
1526
|
+
);
|
|
1527
|
+
return {
|
|
1528
|
+
tools
|
|
1529
|
+
};
|
|
1530
|
+
}
|
|
1531
|
+
);
|
|
1532
|
+
server.setRequestHandler(
|
|
1533
|
+
CallToolRequestSchema,
|
|
1534
|
+
async (request) => {
|
|
1535
|
+
const { name, arguments: args } = request.params;
|
|
1536
|
+
const tool = MCP_TOOLS.find((_) => _.name === name);
|
|
1537
|
+
if (!tool) {
|
|
1538
|
+
throw new Error(`Tool ${name} not found`);
|
|
1539
|
+
}
|
|
1540
|
+
try {
|
|
1541
|
+
if (!await tool.isEnabled()) {
|
|
1542
|
+
throw new Error(`Tool ${name} is not enabled`);
|
|
1543
|
+
}
|
|
1544
|
+
const model = getModelManager().getModelName("main");
|
|
1545
|
+
const validationResult = await tool.validateInput?.(
|
|
1546
|
+
args ?? {},
|
|
1547
|
+
{
|
|
1548
|
+
abortController: new AbortController(),
|
|
1549
|
+
options: {
|
|
1550
|
+
commands: MCP_COMMANDS,
|
|
1551
|
+
tools: MCP_TOOLS,
|
|
1552
|
+
forkNumber: 0,
|
|
1553
|
+
messageLogName: "unused",
|
|
1554
|
+
maxThinkingTokens: 0
|
|
1555
|
+
},
|
|
1556
|
+
messageId: void 0,
|
|
1557
|
+
readFileTimestamps: state.readFileTimestamps
|
|
1558
|
+
}
|
|
1559
|
+
);
|
|
1560
|
+
if (validationResult && !validationResult.result) {
|
|
1561
|
+
throw new Error(
|
|
1562
|
+
`Tool ${name} input is invalid: ${validationResult.message}`
|
|
1563
|
+
);
|
|
1564
|
+
}
|
|
1565
|
+
const result = tool.call(args ?? {}, {
|
|
1566
|
+
abortController: new AbortController(),
|
|
1567
|
+
messageId: void 0,
|
|
1568
|
+
options: {
|
|
1569
|
+
commands: MCP_COMMANDS,
|
|
1570
|
+
tools: MCP_TOOLS,
|
|
1571
|
+
forkNumber: 0,
|
|
1572
|
+
messageLogName: "unused",
|
|
1573
|
+
maxThinkingTokens: 0
|
|
1574
|
+
},
|
|
1575
|
+
readFileTimestamps: state.readFileTimestamps
|
|
1576
|
+
});
|
|
1577
|
+
const finalResult = await lastX(result);
|
|
1578
|
+
if (finalResult.type !== "result") {
|
|
1579
|
+
throw new Error(`Tool ${name} did not return a result`);
|
|
1580
|
+
}
|
|
1581
|
+
return {
|
|
1582
|
+
content: Array.isArray(finalResult) ? finalResult.map((item) => ({
|
|
1583
|
+
type: "text",
|
|
1584
|
+
text: "text" in item ? item.text : JSON.stringify(item)
|
|
1585
|
+
})) : [
|
|
1586
|
+
{
|
|
1587
|
+
type: "text",
|
|
1588
|
+
text: typeof finalResult === "string" ? finalResult : JSON.stringify(finalResult.data)
|
|
1589
|
+
}
|
|
1590
|
+
]
|
|
1591
|
+
};
|
|
1592
|
+
} catch (error) {
|
|
1593
|
+
logError(error);
|
|
1594
|
+
return {
|
|
1595
|
+
isError: true,
|
|
1596
|
+
content: [
|
|
1597
|
+
{
|
|
1598
|
+
type: "text",
|
|
1599
|
+
text: `Error: ${error instanceof Error ? error.message : String(error)}`
|
|
1600
|
+
}
|
|
1601
|
+
]
|
|
1602
|
+
};
|
|
1603
|
+
}
|
|
1604
|
+
}
|
|
1605
|
+
);
|
|
1606
|
+
async function runServer() {
|
|
1607
|
+
const transport = new StdioServerTransport();
|
|
1608
|
+
await server.connect(transport);
|
|
1609
|
+
}
|
|
1610
|
+
return await runServer();
|
|
1611
|
+
}
|
|
1612
|
+
|
|
1613
|
+
// src/utils/session/conversationRecovery.ts
|
|
1614
|
+
import fs2 from "fs/promises";
|
|
1615
|
+
async function loadMessagesFromLog(logPath, tools) {
|
|
1616
|
+
try {
|
|
1617
|
+
const content = await fs2.readFile(logPath, "utf-8");
|
|
1618
|
+
const messages = JSON.parse(content);
|
|
1619
|
+
return deserializeMessages(messages, tools);
|
|
1620
|
+
} catch (error) {
|
|
1621
|
+
logError(`Failed to load messages from ${logPath}: ${error}`);
|
|
1622
|
+
throw new Error(`Failed to load messages from log: ${error}`);
|
|
1623
|
+
}
|
|
1624
|
+
}
|
|
1625
|
+
function deserializeMessages(messages, tools) {
|
|
1626
|
+
const toolMap = new Map(tools.map((tool) => [tool.name, tool]));
|
|
1627
|
+
return messages.map((message) => {
|
|
1628
|
+
const clonedMessage = JSON.parse(JSON.stringify(message));
|
|
1629
|
+
if (clonedMessage.toolCalls) {
|
|
1630
|
+
clonedMessage.toolCalls = clonedMessage.toolCalls.map((toolCall) => {
|
|
1631
|
+
if (toolCall.tool && typeof toolCall.tool === "string") {
|
|
1632
|
+
const actualTool = toolMap.get(toolCall.tool);
|
|
1633
|
+
if (actualTool) {
|
|
1634
|
+
toolCall.tool = actualTool;
|
|
1635
|
+
}
|
|
1636
|
+
}
|
|
1637
|
+
return toolCall;
|
|
1638
|
+
});
|
|
1639
|
+
}
|
|
1640
|
+
return clonedMessage;
|
|
1641
|
+
});
|
|
1642
|
+
}
|
|
1643
|
+
|
|
1644
|
+
// src/commands/approved-tools.ts
|
|
1645
|
+
var defaultConfigHandler = {
|
|
1646
|
+
getCurrentProjectConfig,
|
|
1647
|
+
saveCurrentProjectConfig
|
|
1648
|
+
};
|
|
1649
|
+
function handleListApprovedTools(cwd2, projectConfigHandler = defaultConfigHandler) {
|
|
1650
|
+
const projectConfig = projectConfigHandler.getCurrentProjectConfig();
|
|
1651
|
+
return `Allowed tools for ${cwd2}:
|
|
1652
|
+
${projectConfig.allowedTools.join("\n")}`;
|
|
1653
|
+
}
|
|
1654
|
+
function handleRemoveApprovedTool(tool, projectConfigHandler = defaultConfigHandler) {
|
|
1655
|
+
const projectConfig = projectConfigHandler.getCurrentProjectConfig();
|
|
1656
|
+
const originalToolCount = projectConfig.allowedTools.length;
|
|
1657
|
+
const updatedAllowedTools = projectConfig.allowedTools.filter((t) => t !== tool);
|
|
1658
|
+
if (originalToolCount !== updatedAllowedTools.length) {
|
|
1659
|
+
projectConfig.allowedTools = updatedAllowedTools;
|
|
1660
|
+
projectConfigHandler.saveCurrentProjectConfig(projectConfig);
|
|
1661
|
+
return {
|
|
1662
|
+
success: true,
|
|
1663
|
+
message: `Removed ${tool} from the list of approved tools`
|
|
1664
|
+
};
|
|
1665
|
+
} else {
|
|
1666
|
+
return {
|
|
1667
|
+
success: false,
|
|
1668
|
+
message: `${tool} was not in the list of approved tools`
|
|
1669
|
+
};
|
|
1670
|
+
}
|
|
1671
|
+
}
|
|
1672
|
+
|
|
1673
|
+
// src/entrypoints/cli/runCli.tsx
|
|
1674
|
+
import { cursorShow } from "ansi-escapes";
|
|
1675
|
+
|
|
1676
|
+
// src/ui/components/InvalidConfigDialog.tsx
|
|
1677
|
+
import React9 from "react";
|
|
1678
|
+
import { Box as Box5, Newline, Text as Text6, useInput as useInput4 } from "ink";
|
|
1679
|
+
import { render as render2 } from "ink";
|
|
1680
|
+
import { writeFileSync } from "fs";
|
|
1681
|
+
function InvalidConfigDialog({
|
|
1682
|
+
filePath,
|
|
1683
|
+
errorDescription,
|
|
1684
|
+
onExit,
|
|
1685
|
+
onReset
|
|
1686
|
+
}) {
|
|
1687
|
+
const theme = getTheme();
|
|
1688
|
+
useInput4((_, key) => {
|
|
1689
|
+
if (key.escape) {
|
|
1690
|
+
onExit();
|
|
1691
|
+
}
|
|
1692
|
+
});
|
|
1693
|
+
const exitState = useExitOnCtrlCD(() => process.exit(0));
|
|
1694
|
+
const handleSelect = (value) => {
|
|
1695
|
+
if (value === "exit") {
|
|
1696
|
+
onExit();
|
|
1697
|
+
} else {
|
|
1698
|
+
onReset();
|
|
1699
|
+
}
|
|
1700
|
+
};
|
|
1701
|
+
return /* @__PURE__ */ React9.createElement(React9.Fragment, null, /* @__PURE__ */ React9.createElement(
|
|
1702
|
+
Box5,
|
|
1703
|
+
{
|
|
1704
|
+
flexDirection: "column",
|
|
1705
|
+
borderColor: theme.error,
|
|
1706
|
+
borderStyle: "round",
|
|
1707
|
+
padding: 1,
|
|
1708
|
+
width: 70,
|
|
1709
|
+
gap: 1
|
|
1710
|
+
},
|
|
1711
|
+
/* @__PURE__ */ React9.createElement(Text6, { bold: true }, "Configuration Error"),
|
|
1712
|
+
/* @__PURE__ */ React9.createElement(Box5, { flexDirection: "column", gap: 1 }, /* @__PURE__ */ React9.createElement(Text6, null, "The configuration file at ", /* @__PURE__ */ React9.createElement(Text6, { bold: true }, filePath), " contains invalid JSON."), /* @__PURE__ */ React9.createElement(Text6, null, errorDescription)),
|
|
1713
|
+
/* @__PURE__ */ React9.createElement(Box5, { flexDirection: "column" }, /* @__PURE__ */ React9.createElement(Text6, { bold: true }, "Choose an option:"), /* @__PURE__ */ React9.createElement(
|
|
1714
|
+
Select,
|
|
1715
|
+
{
|
|
1716
|
+
options: [
|
|
1717
|
+
{ label: "Exit and fix manually", value: "exit" },
|
|
1718
|
+
{ label: "Reset with default configuration", value: "reset" }
|
|
1719
|
+
],
|
|
1720
|
+
onChange: handleSelect
|
|
1721
|
+
}
|
|
1722
|
+
))
|
|
1723
|
+
), exitState.pending ? /* @__PURE__ */ React9.createElement(Text6, { dimColor: true }, "Press ", exitState.keyName, " again to exit") : /* @__PURE__ */ React9.createElement(Newline, null));
|
|
1724
|
+
}
|
|
1725
|
+
function showInvalidConfigDialog({
|
|
1726
|
+
error
|
|
1727
|
+
}) {
|
|
1728
|
+
return new Promise((resolve) => {
|
|
1729
|
+
render2(
|
|
1730
|
+
/* @__PURE__ */ React9.createElement(
|
|
1731
|
+
InvalidConfigDialog,
|
|
1732
|
+
{
|
|
1733
|
+
filePath: error.filePath,
|
|
1734
|
+
errorDescription: error.message,
|
|
1735
|
+
onExit: () => {
|
|
1736
|
+
resolve();
|
|
1737
|
+
process.exit(1);
|
|
1738
|
+
},
|
|
1739
|
+
onReset: () => {
|
|
1740
|
+
writeFileSync(
|
|
1741
|
+
error.filePath,
|
|
1742
|
+
JSON.stringify(error.defaultConfig, null, 2)
|
|
1743
|
+
);
|
|
1744
|
+
resolve();
|
|
1745
|
+
process.exit(0);
|
|
1746
|
+
}
|
|
1747
|
+
}
|
|
1748
|
+
),
|
|
1749
|
+
{ exitOnCtrlC: false }
|
|
1750
|
+
);
|
|
1751
|
+
});
|
|
1752
|
+
}
|
|
1753
|
+
|
|
1754
|
+
// src/entrypoints/cli/runCli.tsx
|
|
1755
|
+
function omitKeys(input, ...keys) {
|
|
1756
|
+
const result = { ...input };
|
|
1757
|
+
for (const key of keys) {
|
|
1758
|
+
delete result[key];
|
|
1759
|
+
}
|
|
1760
|
+
return result;
|
|
1761
|
+
}
|
|
1762
|
+
async function runCli() {
|
|
1763
|
+
initDebugLogger();
|
|
1764
|
+
try {
|
|
1765
|
+
enableConfigs();
|
|
1766
|
+
queueMicrotask(() => {
|
|
1767
|
+
try {
|
|
1768
|
+
validateAndRepairAllGPT5Profiles();
|
|
1769
|
+
} catch (repairError) {
|
|
1770
|
+
logError(`GPT-5 configuration validation failed: ${repairError}`);
|
|
1771
|
+
}
|
|
1772
|
+
});
|
|
1773
|
+
} catch (error) {
|
|
1774
|
+
if (error instanceof ConfigParseError) {
|
|
1775
|
+
await showInvalidConfigDialog({ error });
|
|
1776
|
+
return;
|
|
1777
|
+
}
|
|
1778
|
+
}
|
|
1779
|
+
let inputPrompt = "";
|
|
1780
|
+
let renderContext = {
|
|
1781
|
+
exitOnCtrlC: false,
|
|
1782
|
+
onFlicker() {
|
|
1783
|
+
}
|
|
1784
|
+
};
|
|
1785
|
+
const wantsStreamJsonStdin = process.argv.some(
|
|
1786
|
+
(arg, idx, all) => arg === "--input-format" && all[idx + 1] === "stream-json"
|
|
1787
|
+
) || process.argv.some((arg) => arg.startsWith("--input-format=stream-json"));
|
|
1788
|
+
if (!process.stdin.isTTY && !process.env.CI && !process.argv.includes("mcp") && !wantsStreamJsonStdin) {
|
|
1789
|
+
inputPrompt = await stdin();
|
|
1790
|
+
if (process.platform !== "win32") {
|
|
1791
|
+
try {
|
|
1792
|
+
const ttyFd = openSync("/dev/tty", "r");
|
|
1793
|
+
renderContext = { ...renderContext, stdin: new ReadStream(ttyFd) };
|
|
1794
|
+
} catch (err) {
|
|
1795
|
+
logError(`Could not open /dev/tty: ${err}`);
|
|
1796
|
+
}
|
|
1797
|
+
}
|
|
1798
|
+
}
|
|
1799
|
+
await parseArgs(inputPrompt, renderContext);
|
|
1800
|
+
}
|
|
1801
|
+
async function parseArgs(stdinContent, renderContext) {
|
|
1802
|
+
const program = new Command();
|
|
1803
|
+
const renderContextWithExitOnCtrlC = {
|
|
1804
|
+
...renderContext,
|
|
1805
|
+
exitOnCtrlC: true
|
|
1806
|
+
};
|
|
1807
|
+
program.name(PRODUCT_COMMAND).description(
|
|
1808
|
+
`${PRODUCT_NAME} - starts an interactive session by default, use -p/--print for non-interactive output`
|
|
1809
|
+
).argument("[prompt]", "Your prompt", String).option("--cwd <cwd>", "The current working directory", String, cwd()).option(
|
|
1810
|
+
"-d, --debug [filter]",
|
|
1811
|
+
'Enable debug mode with optional category filtering (e.g., "api,hooks" or "!statsig,!file")'
|
|
1812
|
+
).option(
|
|
1813
|
+
"--debug-verbose",
|
|
1814
|
+
"Enable verbose debug terminal output",
|
|
1815
|
+
() => true
|
|
1816
|
+
).option(
|
|
1817
|
+
"--verbose",
|
|
1818
|
+
"Override verbose mode setting from config",
|
|
1819
|
+
() => true
|
|
1820
|
+
).option("-e, --enable-architect", "Enable the Architect tool", () => true).option(
|
|
1821
|
+
"-p, --print",
|
|
1822
|
+
"Print response and exit (useful for pipes)",
|
|
1823
|
+
() => true
|
|
1824
|
+
).option(
|
|
1825
|
+
"--output-format <format>",
|
|
1826
|
+
'Output format (only works with --print): "text" (default), "json", or "stream-json"',
|
|
1827
|
+
String,
|
|
1828
|
+
"text"
|
|
1829
|
+
).option(
|
|
1830
|
+
"--json-schema <schema>",
|
|
1831
|
+
'JSON Schema for structured output validation. Example: {"type":"object","properties":{"name":{"type":"string"}},"required":["name"]}',
|
|
1832
|
+
String
|
|
1833
|
+
).option(
|
|
1834
|
+
"--input-format <format>",
|
|
1835
|
+
'Input format (only works with --print): "text" (default) or "stream-json"',
|
|
1836
|
+
String,
|
|
1837
|
+
"text"
|
|
1838
|
+
).option(
|
|
1839
|
+
"--mcp-debug",
|
|
1840
|
+
"[DEPRECATED. Use --debug instead] Enable MCP debug mode (shows MCP server errors)",
|
|
1841
|
+
() => true
|
|
1842
|
+
).option(
|
|
1843
|
+
"--dangerously-skip-permissions",
|
|
1844
|
+
"Bypass all permission checks. Recommended only for sandboxes with no internet access.",
|
|
1845
|
+
() => true
|
|
1846
|
+
).option(
|
|
1847
|
+
"--allow-dangerously-skip-permissions",
|
|
1848
|
+
"Enable bypassing all permission checks as an option, without it being enabled by default. Recommended only for sandboxes with no internet access.",
|
|
1849
|
+
() => true
|
|
1850
|
+
).option(
|
|
1851
|
+
"--max-budget-usd <amount>",
|
|
1852
|
+
"Maximum dollar amount to spend on API calls (only works with --print)",
|
|
1853
|
+
String
|
|
1854
|
+
).option(
|
|
1855
|
+
"--include-partial-messages",
|
|
1856
|
+
"Include partial message chunks as they arrive (only works with --print and --output-format=stream-json)",
|
|
1857
|
+
() => true
|
|
1858
|
+
).option(
|
|
1859
|
+
"--replay-user-messages",
|
|
1860
|
+
"Re-emit user messages from stdin back on stdout for acknowledgment (only works with --input-format=stream-json and --output-format=stream-json)",
|
|
1861
|
+
() => true
|
|
1862
|
+
).option(
|
|
1863
|
+
"--allowedTools, --allowed-tools <tools...>",
|
|
1864
|
+
'Comma or space-separated list of tool names to allow (e.g. "Bash(git:*) Edit")'
|
|
1865
|
+
).option(
|
|
1866
|
+
"--tools <tools...>",
|
|
1867
|
+
'Specify the list of available tools from the built-in set. Use "" to disable all tools, "default" to use all tools, or specify tool names (e.g. "Bash,Edit,Read"). Only works with --print mode.'
|
|
1868
|
+
).option(
|
|
1869
|
+
"--disallowedTools, --disallowed-tools <tools...>",
|
|
1870
|
+
'Comma or space-separated list of tool names to deny (e.g. "Bash(git:*) Edit")'
|
|
1871
|
+
).option(
|
|
1872
|
+
"--mcp-config <configs...>",
|
|
1873
|
+
"Load MCP servers from JSON files or strings (space-separated)"
|
|
1874
|
+
).option("--system-prompt <prompt>", "System prompt to use for the session").option(
|
|
1875
|
+
"--append-system-prompt <prompt>",
|
|
1876
|
+
"Append a system prompt to the default system prompt"
|
|
1877
|
+
).option(
|
|
1878
|
+
"--permission-mode <mode>",
|
|
1879
|
+
'Permission mode to use for the session (choices: "acceptEdits", "bypassPermissions", "default", "delegate", "dontAsk", "plan")',
|
|
1880
|
+
String
|
|
1881
|
+
).option(
|
|
1882
|
+
"--permission-prompt-tool <tool>",
|
|
1883
|
+
'Permission prompt tool (only works with --print, --output-format=stream-json, and --input-format=stream-json): "stdio"',
|
|
1884
|
+
String
|
|
1885
|
+
).option(
|
|
1886
|
+
"--safe",
|
|
1887
|
+
"Enable strict permission checking mode (default is permissive)",
|
|
1888
|
+
() => true
|
|
1889
|
+
).option(
|
|
1890
|
+
"--disable-slash-commands",
|
|
1891
|
+
"Disable slash commands (treat /... as plain text)",
|
|
1892
|
+
() => true
|
|
1893
|
+
).option(
|
|
1894
|
+
"--plugin-dir <paths...>",
|
|
1895
|
+
"Load plugins from directories for this session only (repeatable)",
|
|
1896
|
+
(value, previous) => {
|
|
1897
|
+
const prev = Array.isArray(previous) ? previous : [];
|
|
1898
|
+
const next = Array.isArray(value) ? value : [value];
|
|
1899
|
+
return [...prev, ...next].filter(Boolean);
|
|
1900
|
+
},
|
|
1901
|
+
[]
|
|
1902
|
+
).option(
|
|
1903
|
+
"--model <model>",
|
|
1904
|
+
"Model for the current session. Provide an alias for the latest model (e.g. 'sonnet' or 'opus') or a model's full name.",
|
|
1905
|
+
String
|
|
1906
|
+
).option(
|
|
1907
|
+
"--agent <agent>",
|
|
1908
|
+
"Agent for the current session. Overrides the 'agent' setting.",
|
|
1909
|
+
String
|
|
1910
|
+
).option(
|
|
1911
|
+
"--betas <betas...>",
|
|
1912
|
+
"Beta headers to include in API requests (API key users only)"
|
|
1913
|
+
).option(
|
|
1914
|
+
"--fallback-model <model>",
|
|
1915
|
+
"Enable automatic fallback to specified model when default model is overloaded (only works with --print)",
|
|
1916
|
+
String
|
|
1917
|
+
).option(
|
|
1918
|
+
"--settings <file-or-json>",
|
|
1919
|
+
"Path to a settings JSON file or a JSON string to load additional settings from",
|
|
1920
|
+
String
|
|
1921
|
+
).option(
|
|
1922
|
+
"--add-dir <directories...>",
|
|
1923
|
+
"Additional directories to allow tool access to"
|
|
1924
|
+
).option(
|
|
1925
|
+
"--ide",
|
|
1926
|
+
"Automatically connect to IDE on startup if exactly one valid IDE is available",
|
|
1927
|
+
() => true
|
|
1928
|
+
).option(
|
|
1929
|
+
"--strict-mcp-config",
|
|
1930
|
+
"Only use MCP servers from --mcp-config, ignoring all other MCP configurations",
|
|
1931
|
+
() => true
|
|
1932
|
+
).option(
|
|
1933
|
+
"--agents <json>",
|
|
1934
|
+
`JSON object defining custom agents (e.g. '{"reviewer": {"description": "Reviews code", "prompt": "You are a code reviewer"}}')`,
|
|
1935
|
+
String
|
|
1936
|
+
).option(
|
|
1937
|
+
"--setting-sources <sources>",
|
|
1938
|
+
"Comma-separated list of setting sources to load (user, project, local).",
|
|
1939
|
+
String
|
|
1940
|
+
).option(
|
|
1941
|
+
"-r, --resume [value]",
|
|
1942
|
+
"Resume a conversation by session ID or session name (omit value to open selector)"
|
|
1943
|
+
).option(
|
|
1944
|
+
"-c, --continue",
|
|
1945
|
+
"Continue the most recent conversation",
|
|
1946
|
+
() => true
|
|
1947
|
+
).option(
|
|
1948
|
+
"--fork-session",
|
|
1949
|
+
"When resuming/continuing, create a new session ID instead of reusing the original (use with --resume or --continue)",
|
|
1950
|
+
() => true
|
|
1951
|
+
).option(
|
|
1952
|
+
"--no-session-persistence",
|
|
1953
|
+
"Disable session persistence - sessions will not be saved to disk and cannot be resumed (only works with --print)"
|
|
1954
|
+
).option(
|
|
1955
|
+
"--session-id <uuid>",
|
|
1956
|
+
"Use a specific session ID for the conversation (must be a valid UUID)",
|
|
1957
|
+
String
|
|
1958
|
+
).action(
|
|
1959
|
+
async (prompt, {
|
|
1960
|
+
cwd: cwd2,
|
|
1961
|
+
debug: debug2,
|
|
1962
|
+
verbose,
|
|
1963
|
+
enableArchitect,
|
|
1964
|
+
print,
|
|
1965
|
+
outputFormat,
|
|
1966
|
+
jsonSchema,
|
|
1967
|
+
inputFormat,
|
|
1968
|
+
mcpDebug,
|
|
1969
|
+
dangerouslySkipPermissions,
|
|
1970
|
+
allowDangerouslySkipPermissions,
|
|
1971
|
+
maxBudgetUsd,
|
|
1972
|
+
includePartialMessages,
|
|
1973
|
+
replayUserMessages,
|
|
1974
|
+
allowedTools: allowedTools2,
|
|
1975
|
+
tools: cliTools,
|
|
1976
|
+
disallowedTools,
|
|
1977
|
+
mcpConfig,
|
|
1978
|
+
systemPrompt: systemPromptOverride,
|
|
1979
|
+
appendSystemPrompt,
|
|
1980
|
+
permissionMode,
|
|
1981
|
+
permissionPromptTool,
|
|
1982
|
+
safe,
|
|
1983
|
+
disableSlashCommands,
|
|
1984
|
+
pluginDir,
|
|
1985
|
+
model,
|
|
1986
|
+
addDir,
|
|
1987
|
+
strictMcpConfig,
|
|
1988
|
+
agents,
|
|
1989
|
+
settingSources,
|
|
1990
|
+
resume,
|
|
1991
|
+
continue: continueConversation,
|
|
1992
|
+
forkSession,
|
|
1993
|
+
sessionId,
|
|
1994
|
+
sessionPersistence
|
|
1995
|
+
}) => {
|
|
1996
|
+
try {
|
|
1997
|
+
setEnabledSettingSourcesFromCli(settingSources);
|
|
1998
|
+
} catch (err) {
|
|
1999
|
+
process.stderr.write(
|
|
2000
|
+
`Error processing --setting-sources: ${err instanceof Error ? err.message : String(err)}
|
|
2001
|
+
`
|
|
2002
|
+
);
|
|
2003
|
+
process.exit(1);
|
|
2004
|
+
}
|
|
2005
|
+
setFlagAgentsFromCliJson(agents);
|
|
2006
|
+
clearAgentCache();
|
|
2007
|
+
clearOutputStyleCache();
|
|
2008
|
+
await setup(cwd2, safe);
|
|
2009
|
+
await showSetupScreens(safe, print);
|
|
2010
|
+
assertMinVersion();
|
|
2011
|
+
{
|
|
2012
|
+
const requested = Array.isArray(pluginDir) && pluginDir.length > 0 ? pluginDir : [];
|
|
2013
|
+
const { listEnabledInstalledPluginPackRoots } = await import("./skillMarketplace-PSNKDINM.js");
|
|
2014
|
+
const installed = listEnabledInstalledPluginPackRoots();
|
|
2015
|
+
const all = [...installed, ...requested].filter(Boolean);
|
|
2016
|
+
const deduped = Array.from(new Set(all));
|
|
2017
|
+
if (deduped.length > 0) {
|
|
2018
|
+
const { configureSessionPlugins } = await import("./pluginRuntime-FPTKK6NY.js");
|
|
2019
|
+
const { errors } = await configureSessionPlugins({
|
|
2020
|
+
pluginDirs: deduped
|
|
2021
|
+
});
|
|
2022
|
+
for (const err of errors) {
|
|
2023
|
+
console.warn(err);
|
|
2024
|
+
}
|
|
2025
|
+
}
|
|
2026
|
+
}
|
|
2027
|
+
const [{ ask }, { getTools }, { getCommands }] = await Promise.all([
|
|
2028
|
+
import("./ask-3G5H5KD5.js"),
|
|
2029
|
+
import("./tools-FZU2FZBD.js"),
|
|
2030
|
+
import("./commands-TWH6PGVG.js")
|
|
2031
|
+
]);
|
|
2032
|
+
const commands = await getCommands();
|
|
2033
|
+
const mcpClientsPromise = Array.isArray(mcpConfig) && mcpConfig.length > 0 || strictMcpConfig === true ? getClientsForCliMcpConfig({
|
|
2034
|
+
mcpConfig: Array.isArray(mcpConfig) ? mcpConfig : [],
|
|
2035
|
+
strictMcpConfig: strictMcpConfig === true,
|
|
2036
|
+
projectDir: cwd2
|
|
2037
|
+
}) : getClients();
|
|
2038
|
+
const [allTools, mcpClients] = await Promise.all([
|
|
2039
|
+
getTools(
|
|
2040
|
+
enableArchitect ?? getCurrentProjectConfig().enableArchitectTool
|
|
2041
|
+
),
|
|
2042
|
+
mcpClientsPromise
|
|
2043
|
+
]);
|
|
2044
|
+
const tools = disableSlashCommands === true ? allTools.filter((t) => t.name !== "SlashCommand") : allTools;
|
|
2045
|
+
const inputPrompt = [prompt, stdinContent].filter(Boolean).join("\n");
|
|
2046
|
+
const {
|
|
2047
|
+
loadKodeAgentSessionMessages,
|
|
2048
|
+
findMostRecentKodeAgentSessionId
|
|
2049
|
+
} = await import("./kodeAgentSessionLoad-6N27AC5K.js");
|
|
2050
|
+
const { listKodeAgentSessions, resolveResumeSessionIdentifier } = await import("./kodeAgentSessionResume-HUSAEO24.js");
|
|
2051
|
+
const { isUuid } = await import("./uuid-QN2CNKKN.js");
|
|
2052
|
+
const { setKodeAgentSessionId, getKodeAgentSessionId } = await import("./kodeAgentSessionId-X6XWQW7B.js");
|
|
2053
|
+
const { randomUUID } = await import("crypto");
|
|
2054
|
+
const wantsContinue = Boolean(continueConversation);
|
|
2055
|
+
const wantsResume = resume !== void 0;
|
|
2056
|
+
const wantsFork = Boolean(forkSession);
|
|
2057
|
+
if (sessionId && !isUuid(String(sessionId))) {
|
|
2058
|
+
console.error(`Error: --session-id must be a valid UUID`);
|
|
2059
|
+
process.exit(1);
|
|
2060
|
+
}
|
|
2061
|
+
if (sessionId && (wantsContinue || wantsResume) && !wantsFork) {
|
|
2062
|
+
console.error(
|
|
2063
|
+
`Error: --session-id can only be used with --continue or --resume if --fork-session is also specified.`
|
|
2064
|
+
);
|
|
2065
|
+
process.exit(1);
|
|
2066
|
+
}
|
|
2067
|
+
let initialMessages;
|
|
2068
|
+
let resumedFromSessionId = null;
|
|
2069
|
+
let needsResumeSelector = false;
|
|
2070
|
+
if (wantsContinue) {
|
|
2071
|
+
const latest = findMostRecentKodeAgentSessionId(cwd2);
|
|
2072
|
+
if (!latest) {
|
|
2073
|
+
console.error("No conversation found to continue");
|
|
2074
|
+
process.exit(1);
|
|
2075
|
+
}
|
|
2076
|
+
initialMessages = loadKodeAgentSessionMessages({
|
|
2077
|
+
cwd: cwd2,
|
|
2078
|
+
sessionId: latest
|
|
2079
|
+
});
|
|
2080
|
+
resumedFromSessionId = latest;
|
|
2081
|
+
} else if (wantsResume) {
|
|
2082
|
+
if (resume === true) {
|
|
2083
|
+
needsResumeSelector = true;
|
|
2084
|
+
} else {
|
|
2085
|
+
const identifier = String(resume);
|
|
2086
|
+
const resolved = resolveResumeSessionIdentifier({ cwd: cwd2, identifier });
|
|
2087
|
+
if (resolved.kind === "ok") {
|
|
2088
|
+
initialMessages = loadKodeAgentSessionMessages({
|
|
2089
|
+
cwd: cwd2,
|
|
2090
|
+
sessionId: resolved.sessionId
|
|
2091
|
+
});
|
|
2092
|
+
resumedFromSessionId = resolved.sessionId;
|
|
2093
|
+
} else if (resolved.kind === "different_directory") {
|
|
2094
|
+
console.error(
|
|
2095
|
+
resolved.otherCwd ? `Error: That session belongs to a different directory: ${resolved.otherCwd}` : `Error: That session belongs to a different directory.`
|
|
2096
|
+
);
|
|
2097
|
+
process.exit(1);
|
|
2098
|
+
} else if (resolved.kind === "ambiguous") {
|
|
2099
|
+
console.error(
|
|
2100
|
+
`Error: Multiple sessions match "${identifier}": ${resolved.matchingSessionIds.join(
|
|
2101
|
+
", "
|
|
2102
|
+
)}`
|
|
2103
|
+
);
|
|
2104
|
+
process.exit(1);
|
|
2105
|
+
} else {
|
|
2106
|
+
console.error(
|
|
2107
|
+
`No conversation found with session ID or name: ${identifier}`
|
|
2108
|
+
);
|
|
2109
|
+
process.exit(1);
|
|
2110
|
+
}
|
|
2111
|
+
}
|
|
2112
|
+
}
|
|
2113
|
+
if (needsResumeSelector && print) {
|
|
2114
|
+
console.error(
|
|
2115
|
+
"Error: --resume without a value requires interactive mode (no --print)."
|
|
2116
|
+
);
|
|
2117
|
+
process.exit(1);
|
|
2118
|
+
}
|
|
2119
|
+
if (!needsResumeSelector) {
|
|
2120
|
+
const effectiveSessionId = (() => {
|
|
2121
|
+
if (resumedFromSessionId) {
|
|
2122
|
+
if (wantsFork) return sessionId ? String(sessionId) : randomUUID();
|
|
2123
|
+
return resumedFromSessionId;
|
|
2124
|
+
}
|
|
2125
|
+
if (sessionId) return String(sessionId);
|
|
2126
|
+
return getKodeAgentSessionId();
|
|
2127
|
+
})();
|
|
2128
|
+
setKodeAgentSessionId(effectiveSessionId);
|
|
2129
|
+
}
|
|
2130
|
+
if (print) {
|
|
2131
|
+
await runPrintMode({
|
|
2132
|
+
prompt,
|
|
2133
|
+
stdinContent,
|
|
2134
|
+
inputPrompt,
|
|
2135
|
+
cwd: cwd2,
|
|
2136
|
+
safe,
|
|
2137
|
+
verbose,
|
|
2138
|
+
outputFormat,
|
|
2139
|
+
inputFormat,
|
|
2140
|
+
jsonSchema,
|
|
2141
|
+
permissionPromptTool,
|
|
2142
|
+
replayUserMessages,
|
|
2143
|
+
cliTools,
|
|
2144
|
+
tools,
|
|
2145
|
+
commands,
|
|
2146
|
+
ask,
|
|
2147
|
+
initialMessages,
|
|
2148
|
+
sessionPersistence,
|
|
2149
|
+
systemPromptOverride,
|
|
2150
|
+
appendSystemPrompt,
|
|
2151
|
+
disableSlashCommands,
|
|
2152
|
+
allowedTools: allowedTools2,
|
|
2153
|
+
disallowedTools,
|
|
2154
|
+
addDir,
|
|
2155
|
+
permissionMode,
|
|
2156
|
+
dangerouslySkipPermissions,
|
|
2157
|
+
allowDangerouslySkipPermissions,
|
|
2158
|
+
model,
|
|
2159
|
+
mcpClients
|
|
2160
|
+
});
|
|
2161
|
+
return;
|
|
2162
|
+
} else {
|
|
2163
|
+
if (sessionPersistence === false) {
|
|
2164
|
+
console.error(
|
|
2165
|
+
"Error: --no-session-persistence only works with --print"
|
|
2166
|
+
);
|
|
2167
|
+
process.exit(1);
|
|
2168
|
+
}
|
|
2169
|
+
const updateInfo = await (async () => {
|
|
2170
|
+
try {
|
|
2171
|
+
const [
|
|
2172
|
+
{ getLatestVersion, getUpdateCommandSuggestions },
|
|
2173
|
+
semverMod
|
|
2174
|
+
] = await Promise.all([
|
|
2175
|
+
import("./autoUpdater-DNRMJWFQ.js"),
|
|
2176
|
+
import("semver")
|
|
2177
|
+
]);
|
|
2178
|
+
const semver = semverMod?.default ?? semverMod;
|
|
2179
|
+
const gt = semver?.gt;
|
|
2180
|
+
if (typeof gt !== "function")
|
|
2181
|
+
return {
|
|
2182
|
+
version: null,
|
|
2183
|
+
commands: null
|
|
2184
|
+
};
|
|
2185
|
+
const latest = await getLatestVersion();
|
|
2186
|
+
if (latest && gt(latest, MACRO.VERSION)) {
|
|
2187
|
+
const cmds = await getUpdateCommandSuggestions();
|
|
2188
|
+
return { version: latest, commands: cmds };
|
|
2189
|
+
}
|
|
2190
|
+
} catch {
|
|
2191
|
+
}
|
|
2192
|
+
return {
|
|
2193
|
+
version: null,
|
|
2194
|
+
commands: null
|
|
2195
|
+
};
|
|
2196
|
+
})();
|
|
2197
|
+
if (needsResumeSelector) {
|
|
2198
|
+
const sessions = listKodeAgentSessions({ cwd: cwd2 });
|
|
2199
|
+
if (sessions.length === 0) {
|
|
2200
|
+
console.error("No conversation found to resume");
|
|
2201
|
+
process.exit(1);
|
|
2202
|
+
}
|
|
2203
|
+
const context2 = {};
|
|
2204
|
+
(async () => {
|
|
2205
|
+
const { render: render3 } = await import("ink");
|
|
2206
|
+
const { unmount } = render3(
|
|
2207
|
+
/* @__PURE__ */ React10.createElement(
|
|
2208
|
+
ResumeConversation,
|
|
2209
|
+
{
|
|
2210
|
+
cwd: cwd2,
|
|
2211
|
+
context: context2,
|
|
2212
|
+
commands,
|
|
2213
|
+
sessions,
|
|
2214
|
+
tools,
|
|
2215
|
+
verbose,
|
|
2216
|
+
safeMode: safe,
|
|
2217
|
+
debug: Boolean(debug2),
|
|
2218
|
+
disableSlashCommands: disableSlashCommands === true,
|
|
2219
|
+
mcpClients,
|
|
2220
|
+
initialPrompt: inputPrompt,
|
|
2221
|
+
forkSession: wantsFork,
|
|
2222
|
+
forkSessionId: sessionId ? String(sessionId) : null,
|
|
2223
|
+
initialUpdateVersion: updateInfo.version,
|
|
2224
|
+
initialUpdateCommands: updateInfo.commands
|
|
2225
|
+
}
|
|
2226
|
+
),
|
|
2227
|
+
renderContextWithExitOnCtrlC
|
|
2228
|
+
);
|
|
2229
|
+
context2.unmount = unmount;
|
|
2230
|
+
})();
|
|
2231
|
+
return;
|
|
2232
|
+
}
|
|
2233
|
+
const isDefaultModel = await isDefaultSlowAndCapableModel();
|
|
2234
|
+
{
|
|
2235
|
+
const { render: render3 } = await import("ink");
|
|
2236
|
+
const { REPL } = await import("./REPL-GIU4ZIXM.js");
|
|
2237
|
+
render3(
|
|
2238
|
+
/* @__PURE__ */ React10.createElement(
|
|
2239
|
+
REPL,
|
|
2240
|
+
{
|
|
2241
|
+
commands,
|
|
2242
|
+
debug: Boolean(debug2),
|
|
2243
|
+
disableSlashCommands: disableSlashCommands === true,
|
|
2244
|
+
initialPrompt: inputPrompt,
|
|
2245
|
+
messageLogName: dateToFilename(/* @__PURE__ */ new Date()),
|
|
2246
|
+
shouldShowPromptInput: true,
|
|
2247
|
+
verbose,
|
|
2248
|
+
tools,
|
|
2249
|
+
safeMode: safe,
|
|
2250
|
+
mcpClients,
|
|
2251
|
+
isDefaultModel,
|
|
2252
|
+
initialUpdateVersion: updateInfo.version,
|
|
2253
|
+
initialUpdateCommands: updateInfo.commands,
|
|
2254
|
+
initialMessages
|
|
2255
|
+
}
|
|
2256
|
+
),
|
|
2257
|
+
renderContext
|
|
2258
|
+
);
|
|
2259
|
+
}
|
|
2260
|
+
}
|
|
2261
|
+
}
|
|
2262
|
+
).version(MACRO.VERSION, "-v, --version");
|
|
2263
|
+
const config = program.command("config").description(
|
|
2264
|
+
`Manage configuration (eg. ${PRODUCT_COMMAND} config set -g theme dark)`
|
|
2265
|
+
);
|
|
2266
|
+
config.command("get <key>").description("Get a config value").option("--cwd <cwd>", "The current working directory", String, cwd()).option("-g, --global", "Use global config").action(async (key, { cwd: cwd2, global }) => {
|
|
2267
|
+
await setup(cwd2, false);
|
|
2268
|
+
console.log(getConfigForCLI(key, global ?? false));
|
|
2269
|
+
process.exit(0);
|
|
2270
|
+
});
|
|
2271
|
+
config.command("set <key> <value>").description("Set a config value").option("--cwd <cwd>", "The current working directory", String, cwd()).option("-g, --global", "Use global config").action(async (key, value, { cwd: cwd2, global }) => {
|
|
2272
|
+
await setup(cwd2, false);
|
|
2273
|
+
setConfigForCLI(key, value, global ?? false);
|
|
2274
|
+
console.log(`Set ${key} to ${value}`);
|
|
2275
|
+
process.exit(0);
|
|
2276
|
+
});
|
|
2277
|
+
config.command("remove <key>").description("Remove a config value").option("--cwd <cwd>", "The current working directory", String, cwd()).option("-g, --global", "Use global config").action(async (key, { cwd: cwd2, global }) => {
|
|
2278
|
+
await setup(cwd2, false);
|
|
2279
|
+
deleteConfigForCLI(key, global ?? false);
|
|
2280
|
+
console.log(`Removed ${key}`);
|
|
2281
|
+
process.exit(0);
|
|
2282
|
+
});
|
|
2283
|
+
config.command("list").description("List all config values").option("--cwd <cwd>", "The current working directory", String, cwd()).option("-g, --global", "Use global config", false).action(async ({ cwd: cwd2, global }) => {
|
|
2284
|
+
await setup(cwd2, false);
|
|
2285
|
+
console.log(
|
|
2286
|
+
JSON.stringify(
|
|
2287
|
+
global ? listConfigForCLI(true) : listConfigForCLI(false),
|
|
2288
|
+
null,
|
|
2289
|
+
2
|
|
2290
|
+
)
|
|
2291
|
+
);
|
|
2292
|
+
process.exit(0);
|
|
2293
|
+
});
|
|
2294
|
+
const modelsCmd = program.command("models").description("Import/export model profiles and pointers (YAML)");
|
|
2295
|
+
modelsCmd.command("export").description(
|
|
2296
|
+
"Export shareable model config as YAML (does not include plaintext API keys)"
|
|
2297
|
+
).option("--cwd <cwd>", "The current working directory", String, cwd()).option("-o, --output <path>", "Write YAML to file instead of stdout").action(async ({ cwd: cwd2, output }) => {
|
|
2298
|
+
try {
|
|
2299
|
+
await setup(cwd2, false);
|
|
2300
|
+
const yamlText = formatModelConfigYamlForSharing(getGlobalConfig());
|
|
2301
|
+
if (output) {
|
|
2302
|
+
writeFileSync2(output, yamlText, "utf-8");
|
|
2303
|
+
console.log(`Wrote model config YAML to ${output}`);
|
|
2304
|
+
} else {
|
|
2305
|
+
console.log(yamlText);
|
|
2306
|
+
}
|
|
2307
|
+
process.exit(0);
|
|
2308
|
+
} catch (error) {
|
|
2309
|
+
console.error(error.message);
|
|
2310
|
+
process.exit(1);
|
|
2311
|
+
}
|
|
2312
|
+
});
|
|
2313
|
+
modelsCmd.command("import <file>").description("Import model config YAML (merges by default)").option("--cwd <cwd>", "The current working directory", String, cwd()).option("--replace", "Replace existing model profiles instead of merging").action(async (file, { cwd: cwd2, replace }) => {
|
|
2314
|
+
try {
|
|
2315
|
+
await setup(cwd2, false);
|
|
2316
|
+
const yamlText = readFileSync(file, "utf-8");
|
|
2317
|
+
const { nextConfig, warnings } = applyModelConfigYamlImport(
|
|
2318
|
+
getGlobalConfig(),
|
|
2319
|
+
yamlText,
|
|
2320
|
+
{ replace: !!replace }
|
|
2321
|
+
);
|
|
2322
|
+
saveGlobalConfig(nextConfig);
|
|
2323
|
+
await import("./model-KPYCXWBK.js").then(({ reloadModelManager }) => {
|
|
2324
|
+
reloadModelManager();
|
|
2325
|
+
});
|
|
2326
|
+
if (warnings.length > 0) {
|
|
2327
|
+
console.error(warnings.join("\n"));
|
|
2328
|
+
}
|
|
2329
|
+
console.log(`Imported model config YAML from ${file}`);
|
|
2330
|
+
process.exit(0);
|
|
2331
|
+
} catch (error) {
|
|
2332
|
+
console.error(error.message);
|
|
2333
|
+
process.exit(1);
|
|
2334
|
+
}
|
|
2335
|
+
});
|
|
2336
|
+
modelsCmd.command("list").description("List configured model profiles and pointers").option("--cwd <cwd>", "The current working directory", String, cwd()).option("--json", "Output as JSON").action(async (options) => {
|
|
2337
|
+
try {
|
|
2338
|
+
const workingDir = typeof options?.cwd === "string" ? options.cwd : cwd();
|
|
2339
|
+
const asJson = options?.json === true;
|
|
2340
|
+
await setup(workingDir, false);
|
|
2341
|
+
const { reloadModelManager, getModelManager: getModelManager2 } = await import("./model-KPYCXWBK.js");
|
|
2342
|
+
reloadModelManager();
|
|
2343
|
+
const manager = getModelManager2();
|
|
2344
|
+
const config2 = getGlobalConfig();
|
|
2345
|
+
const pointers = ["main", "task", "compact", "quick"].map(
|
|
2346
|
+
(pointer) => {
|
|
2347
|
+
const pointerId = config2.modelPointers?.[pointer] ?? null;
|
|
2348
|
+
const resolved = manager.resolveModelWithInfo(pointer);
|
|
2349
|
+
const profile = resolved.success ? resolved.profile : null;
|
|
2350
|
+
return {
|
|
2351
|
+
pointer,
|
|
2352
|
+
pointerId,
|
|
2353
|
+
resolved: profile ? {
|
|
2354
|
+
name: profile.name,
|
|
2355
|
+
provider: profile.provider,
|
|
2356
|
+
modelName: profile.modelName,
|
|
2357
|
+
isActive: profile.isActive
|
|
2358
|
+
} : null,
|
|
2359
|
+
error: resolved.success ? null : resolved.error ?? null
|
|
2360
|
+
};
|
|
2361
|
+
}
|
|
2362
|
+
);
|
|
2363
|
+
const profiles = (config2.modelProfiles ?? []).map((p) => ({
|
|
2364
|
+
name: p.name,
|
|
2365
|
+
provider: p.provider,
|
|
2366
|
+
modelName: p.modelName,
|
|
2367
|
+
baseURL: p.baseURL ?? null,
|
|
2368
|
+
maxTokens: p.maxTokens,
|
|
2369
|
+
contextLength: p.contextLength,
|
|
2370
|
+
reasoningEffort: p.reasoningEffort ?? null,
|
|
2371
|
+
isActive: p.isActive,
|
|
2372
|
+
createdAt: p.createdAt,
|
|
2373
|
+
lastUsed: typeof p.lastUsed === "number" ? p.lastUsed : null,
|
|
2374
|
+
isGPT5: p.isGPT5 ?? null,
|
|
2375
|
+
validationStatus: p.validationStatus ?? null,
|
|
2376
|
+
lastValidation: typeof p.lastValidation === "number" ? p.lastValidation : null,
|
|
2377
|
+
hasApiKey: Boolean(p.apiKey)
|
|
2378
|
+
}));
|
|
2379
|
+
if (asJson) {
|
|
2380
|
+
console.log(JSON.stringify({ pointers, profiles }, null, 2));
|
|
2381
|
+
process.exitCode = 0;
|
|
2382
|
+
return;
|
|
2383
|
+
}
|
|
2384
|
+
console.log("Model pointers:\n");
|
|
2385
|
+
for (const ptr of pointers) {
|
|
2386
|
+
const resolvedLabel = ptr.resolved ? `${ptr.resolved.name} (${ptr.resolved.provider}:${ptr.resolved.modelName})` : "(unresolved)";
|
|
2387
|
+
const configured = ptr.pointerId ? ` -> ${ptr.pointerId}` : "";
|
|
2388
|
+
const err = ptr.error ? ` [${ptr.error}]` : "";
|
|
2389
|
+
console.log(` - ${ptr.pointer}${configured}: ${resolvedLabel}${err}`);
|
|
2390
|
+
}
|
|
2391
|
+
const active = profiles.filter((p) => p.isActive);
|
|
2392
|
+
console.log(`
|
|
2393
|
+
Model profiles (${active.length}/${profiles.length} active):
|
|
2394
|
+
`);
|
|
2395
|
+
for (const p of profiles.sort((a, b) => a.name.localeCompare(b.name))) {
|
|
2396
|
+
const status = p.isActive ? "active" : "inactive";
|
|
2397
|
+
console.log(` - ${p.name} (${status})`);
|
|
2398
|
+
console.log(` provider=${p.provider} modelName=${p.modelName}`);
|
|
2399
|
+
if (p.baseURL) console.log(` baseURL=${p.baseURL}`);
|
|
2400
|
+
}
|
|
2401
|
+
process.exitCode = 0;
|
|
2402
|
+
return;
|
|
2403
|
+
} catch (error) {
|
|
2404
|
+
console.error(error.message);
|
|
2405
|
+
process.exitCode = 1;
|
|
2406
|
+
return;
|
|
2407
|
+
}
|
|
2408
|
+
});
|
|
2409
|
+
const agentsCmd = program.command("agents").description("Agent utilities (validate templates, etc.)");
|
|
2410
|
+
agentsCmd.command("validate [paths...]").description("Validate agent markdown files (defaults to user+project agent dirs)").option("--cwd <cwd>", "The current working directory", String, cwd()).option("--json", "Output as JSON").option("--no-tools-check", "Skip validating tool names against the tool registry").action(
|
|
2411
|
+
async (paths, options) => {
|
|
2412
|
+
try {
|
|
2413
|
+
const workingDir = typeof options?.cwd === "string" ? options.cwd : cwd();
|
|
2414
|
+
await setup(workingDir, false);
|
|
2415
|
+
const { validateAgentTemplates } = await import("./agentsValidate-XP3CFN6F.js");
|
|
2416
|
+
const report = await validateAgentTemplates({
|
|
2417
|
+
cwd: workingDir,
|
|
2418
|
+
paths: Array.isArray(paths) ? paths : [],
|
|
2419
|
+
checkTools: options.toolsCheck !== false
|
|
2420
|
+
});
|
|
2421
|
+
if (options.json) {
|
|
2422
|
+
console.log(JSON.stringify(report, null, 2));
|
|
2423
|
+
process.exitCode = report.ok ? 0 : 1;
|
|
2424
|
+
return;
|
|
2425
|
+
}
|
|
2426
|
+
console.log(
|
|
2427
|
+
`Validated ${report.results.length} agent file(s): ${report.errorCount} error(s), ${report.warningCount} warning(s)
|
|
2428
|
+
`
|
|
2429
|
+
);
|
|
2430
|
+
for (const r of report.results) {
|
|
2431
|
+
const rel = r.filePath;
|
|
2432
|
+
const title = r.agentType ? `${r.agentType}` : "(unknown agent)";
|
|
2433
|
+
console.log(`${title} \u2014 ${rel}`);
|
|
2434
|
+
if (r.model) {
|
|
2435
|
+
const normalized = r.normalizedModel ? ` (normalized: ${r.normalizedModel})` : "";
|
|
2436
|
+
console.log(` model: ${r.model}${normalized}`);
|
|
2437
|
+
}
|
|
2438
|
+
if (r.issues.length === 0) {
|
|
2439
|
+
console.log(` OK`);
|
|
2440
|
+
} else {
|
|
2441
|
+
for (const issue of r.issues) {
|
|
2442
|
+
console.log(` - ${issue.level}: ${issue.message}`);
|
|
2443
|
+
}
|
|
2444
|
+
}
|
|
2445
|
+
console.log("");
|
|
2446
|
+
}
|
|
2447
|
+
process.exitCode = report.ok ? 0 : 1;
|
|
2448
|
+
return;
|
|
2449
|
+
} catch (error) {
|
|
2450
|
+
console.error(error.message);
|
|
2451
|
+
process.exitCode = 1;
|
|
2452
|
+
return;
|
|
2453
|
+
}
|
|
2454
|
+
}
|
|
2455
|
+
);
|
|
2456
|
+
const registerMarketplaceCommands = (marketplaceCmd2) => {
|
|
2457
|
+
marketplaceCmd2.command("add <source>").description("Add a marketplace from a URL, path, or GitHub repo").action(async (source) => {
|
|
2458
|
+
try {
|
|
2459
|
+
const { addMarketplace } = await import("./skillMarketplace-PSNKDINM.js");
|
|
2460
|
+
console.log("Adding marketplace...");
|
|
2461
|
+
const { name } = await addMarketplace(source);
|
|
2462
|
+
console.log(`Successfully added marketplace: ${name}`);
|
|
2463
|
+
process.exit(0);
|
|
2464
|
+
} catch (error) {
|
|
2465
|
+
console.error(error.message);
|
|
2466
|
+
process.exit(1);
|
|
2467
|
+
}
|
|
2468
|
+
});
|
|
2469
|
+
marketplaceCmd2.command("list").description("List all configured marketplaces").option("--json", "Output as JSON").action(async (options) => {
|
|
2470
|
+
try {
|
|
2471
|
+
const { listMarketplaces } = await import("./skillMarketplace-PSNKDINM.js");
|
|
2472
|
+
const marketplaces = listMarketplaces();
|
|
2473
|
+
if (options.json) {
|
|
2474
|
+
console.log(JSON.stringify(marketplaces, null, 2));
|
|
2475
|
+
process.exit(0);
|
|
2476
|
+
}
|
|
2477
|
+
const names = Object.keys(marketplaces).sort();
|
|
2478
|
+
if (names.length === 0) {
|
|
2479
|
+
console.log("No marketplaces configured");
|
|
2480
|
+
process.exit(0);
|
|
2481
|
+
}
|
|
2482
|
+
console.log("Configured marketplaces:\n");
|
|
2483
|
+
for (const name of names) {
|
|
2484
|
+
const entry = marketplaces[name];
|
|
2485
|
+
console.log(` - ${name}`);
|
|
2486
|
+
const src = entry?.source;
|
|
2487
|
+
if (src?.source === "github") {
|
|
2488
|
+
console.log(` Source: GitHub (${src.repo})`);
|
|
2489
|
+
} else if (src?.source === "git") {
|
|
2490
|
+
console.log(` Source: Git (${src.url})`);
|
|
2491
|
+
} else if (src?.source === "url") {
|
|
2492
|
+
console.log(` Source: URL (${src.url})`);
|
|
2493
|
+
} else if (src?.source === "directory") {
|
|
2494
|
+
console.log(` Source: Directory (${src.path})`);
|
|
2495
|
+
} else if (src?.source === "file") {
|
|
2496
|
+
console.log(` Source: File (${src.path})`);
|
|
2497
|
+
} else if (src?.source === "npm") {
|
|
2498
|
+
console.log(` Source: NPM (${src.package})`);
|
|
2499
|
+
}
|
|
2500
|
+
console.log("");
|
|
2501
|
+
}
|
|
2502
|
+
process.exit(0);
|
|
2503
|
+
} catch (error) {
|
|
2504
|
+
console.error(error.message);
|
|
2505
|
+
process.exit(1);
|
|
2506
|
+
}
|
|
2507
|
+
});
|
|
2508
|
+
marketplaceCmd2.command("remove <name>").alias("rm").description("Remove a configured marketplace").action(async (name) => {
|
|
2509
|
+
try {
|
|
2510
|
+
const { removeMarketplace } = await import("./skillMarketplace-PSNKDINM.js");
|
|
2511
|
+
removeMarketplace(name);
|
|
2512
|
+
console.log(`Successfully removed marketplace: ${name}`);
|
|
2513
|
+
process.exit(0);
|
|
2514
|
+
} catch (error) {
|
|
2515
|
+
console.error(error.message);
|
|
2516
|
+
process.exit(1);
|
|
2517
|
+
}
|
|
2518
|
+
});
|
|
2519
|
+
marketplaceCmd2.command("update [name]").description(
|
|
2520
|
+
"Update marketplace(s) from their source - updates all if no name specified"
|
|
2521
|
+
).action(async (name, _options) => {
|
|
2522
|
+
try {
|
|
2523
|
+
const {
|
|
2524
|
+
listMarketplaces,
|
|
2525
|
+
refreshAllMarketplacesAsync,
|
|
2526
|
+
refreshMarketplaceAsync
|
|
2527
|
+
} = await import("./skillMarketplace-PSNKDINM.js");
|
|
2528
|
+
const trimmed = typeof name === "string" ? name.trim() : "";
|
|
2529
|
+
if (trimmed) {
|
|
2530
|
+
console.log(`Updating marketplace: ${trimmed}...`);
|
|
2531
|
+
await refreshMarketplaceAsync(trimmed);
|
|
2532
|
+
console.log(`Successfully updated marketplace: ${trimmed}`);
|
|
2533
|
+
process.exit(0);
|
|
2534
|
+
}
|
|
2535
|
+
const marketplaces = listMarketplaces();
|
|
2536
|
+
const names = Object.keys(marketplaces);
|
|
2537
|
+
if (names.length === 0) {
|
|
2538
|
+
console.log("No marketplaces configured");
|
|
2539
|
+
process.exit(0);
|
|
2540
|
+
}
|
|
2541
|
+
console.log(`Updating ${names.length} marketplace(s)...`);
|
|
2542
|
+
await refreshAllMarketplacesAsync((message) => {
|
|
2543
|
+
console.log(message);
|
|
2544
|
+
});
|
|
2545
|
+
console.log(`Successfully updated ${names.length} marketplace(s)`);
|
|
2546
|
+
process.exit(0);
|
|
2547
|
+
} catch (error) {
|
|
2548
|
+
console.error(error.message);
|
|
2549
|
+
process.exit(1);
|
|
2550
|
+
}
|
|
2551
|
+
});
|
|
2552
|
+
};
|
|
2553
|
+
const pluginCmd = program.command("plugin").description("Manage plugins and marketplaces");
|
|
2554
|
+
const pluginMarketplaceCmd = pluginCmd.command("marketplace").description(
|
|
2555
|
+
"Manage marketplaces (.kode-plugin/marketplace.json; legacy .claude-plugin supported)"
|
|
2556
|
+
);
|
|
2557
|
+
registerMarketplaceCommands(pluginMarketplaceCmd);
|
|
2558
|
+
const PLUGIN_SCOPES = ["user", "project", "local"];
|
|
2559
|
+
const parsePluginScope = (value) => {
|
|
2560
|
+
const normalized = String(value || "user");
|
|
2561
|
+
return PLUGIN_SCOPES.includes(normalized) ? normalized : null;
|
|
2562
|
+
};
|
|
2563
|
+
pluginCmd.command("install <plugin>").alias("i").description(
|
|
2564
|
+
"Install a plugin from available marketplaces (use plugin@marketplace for specific marketplace)"
|
|
2565
|
+
).option("--cwd <cwd>", "The current working directory", String, cwd()).option(
|
|
2566
|
+
"-s, --scope <scope>",
|
|
2567
|
+
"Installation scope: user, project, or local",
|
|
2568
|
+
"user"
|
|
2569
|
+
).option("--force", "Overwrite existing installed files", () => true).action(async (plugin, options) => {
|
|
2570
|
+
try {
|
|
2571
|
+
const scope = parsePluginScope(options.scope);
|
|
2572
|
+
if (!scope) {
|
|
2573
|
+
console.error(
|
|
2574
|
+
`Invalid scope: ${String(options.scope)}. Must be one of: ${PLUGIN_SCOPES.join(", ")}`
|
|
2575
|
+
);
|
|
2576
|
+
process.exit(1);
|
|
2577
|
+
}
|
|
2578
|
+
const { setCwd: setCwd2 } = await import("./state-KNRWP3FO.js");
|
|
2579
|
+
await setCwd2(options.cwd ?? cwd());
|
|
2580
|
+
const { installSkillPlugin } = await import("./skillMarketplace-PSNKDINM.js");
|
|
2581
|
+
const result = installSkillPlugin(plugin, {
|
|
2582
|
+
scope,
|
|
2583
|
+
force: options.force === true
|
|
2584
|
+
});
|
|
2585
|
+
const skillList = result.installedSkills.length > 0 ? `Skills: ${result.installedSkills.join(", ")}` : "Skills: (none)";
|
|
2586
|
+
console.log(`Installed ${result.pluginSpec}
|
|
2587
|
+
${skillList}`);
|
|
2588
|
+
process.exit(0);
|
|
2589
|
+
} catch (error) {
|
|
2590
|
+
console.error(error.message);
|
|
2591
|
+
process.exit(1);
|
|
2592
|
+
}
|
|
2593
|
+
});
|
|
2594
|
+
pluginCmd.command("uninstall <plugin>").alias("remove").alias("rm").description("Uninstall an installed plugin").option("--cwd <cwd>", "The current working directory", String, cwd()).option(
|
|
2595
|
+
"-s, --scope <scope>",
|
|
2596
|
+
`Uninstall from scope: ${PLUGIN_SCOPES.join(", ")} (default: user)`,
|
|
2597
|
+
"user"
|
|
2598
|
+
).action(async (plugin, options) => {
|
|
2599
|
+
try {
|
|
2600
|
+
const scope = parsePluginScope(options.scope);
|
|
2601
|
+
if (!scope) {
|
|
2602
|
+
console.error(
|
|
2603
|
+
`Invalid scope: ${String(options.scope)}. Must be one of: ${PLUGIN_SCOPES.join(", ")}`
|
|
2604
|
+
);
|
|
2605
|
+
process.exit(1);
|
|
2606
|
+
}
|
|
2607
|
+
const { setCwd: setCwd2 } = await import("./state-KNRWP3FO.js");
|
|
2608
|
+
await setCwd2(options.cwd ?? cwd());
|
|
2609
|
+
const { uninstallSkillPlugin } = await import("./skillMarketplace-PSNKDINM.js");
|
|
2610
|
+
const result = uninstallSkillPlugin(plugin, { scope });
|
|
2611
|
+
const skillList = result.removedSkills.length > 0 ? `Skills: ${result.removedSkills.join(", ")}` : "Skills: (none)";
|
|
2612
|
+
console.log(`Uninstalled ${result.pluginSpec}
|
|
2613
|
+
${skillList}`);
|
|
2614
|
+
process.exit(0);
|
|
2615
|
+
} catch (error) {
|
|
2616
|
+
console.error(error.message);
|
|
2617
|
+
process.exit(1);
|
|
2618
|
+
}
|
|
2619
|
+
});
|
|
2620
|
+
pluginCmd.command("list").description("List installed plugins").option("--cwd <cwd>", "The current working directory", String, cwd()).option(
|
|
2621
|
+
"-s, --scope <scope>",
|
|
2622
|
+
`Filter by scope: ${PLUGIN_SCOPES.join(", ")} (default: user)`,
|
|
2623
|
+
"user"
|
|
2624
|
+
).option("--json", "Output as JSON").action(async (options) => {
|
|
2625
|
+
try {
|
|
2626
|
+
const scope = parsePluginScope(options.scope);
|
|
2627
|
+
if (!scope) {
|
|
2628
|
+
console.error(
|
|
2629
|
+
`Invalid scope: ${String(options.scope)}. Must be one of: ${PLUGIN_SCOPES.join(", ")}`
|
|
2630
|
+
);
|
|
2631
|
+
process.exit(1);
|
|
2632
|
+
}
|
|
2633
|
+
const { setCwd: setCwd2, getCwd: getCwd2 } = await import("./state-KNRWP3FO.js");
|
|
2634
|
+
await setCwd2(options.cwd ?? cwd());
|
|
2635
|
+
const { listInstalledSkillPlugins } = await import("./skillMarketplace-PSNKDINM.js");
|
|
2636
|
+
const all = listInstalledSkillPlugins();
|
|
2637
|
+
const filtered = Object.fromEntries(
|
|
2638
|
+
Object.entries(all).filter(([, record]) => {
|
|
2639
|
+
if (record?.scope !== scope) return false;
|
|
2640
|
+
if (scope === "user") return true;
|
|
2641
|
+
return record?.projectPath === getCwd2();
|
|
2642
|
+
})
|
|
2643
|
+
);
|
|
2644
|
+
if (options.json) {
|
|
2645
|
+
console.log(JSON.stringify(filtered, null, 2));
|
|
2646
|
+
process.exit(0);
|
|
2647
|
+
}
|
|
2648
|
+
const names = Object.keys(filtered).sort();
|
|
2649
|
+
if (names.length === 0) {
|
|
2650
|
+
console.log("No plugins installed");
|
|
2651
|
+
process.exit(0);
|
|
2652
|
+
}
|
|
2653
|
+
console.log(`Installed plugins (scope=${scope}):
|
|
2654
|
+
`);
|
|
2655
|
+
for (const spec of names) {
|
|
2656
|
+
const record = filtered[spec];
|
|
2657
|
+
const enabled = record?.isEnabled === false ? "disabled" : "enabled";
|
|
2658
|
+
console.log(` - ${spec} (${enabled})`);
|
|
2659
|
+
}
|
|
2660
|
+
process.exit(0);
|
|
2661
|
+
} catch (error) {
|
|
2662
|
+
console.error(error.message);
|
|
2663
|
+
process.exit(1);
|
|
2664
|
+
}
|
|
2665
|
+
});
|
|
2666
|
+
pluginCmd.command("enable <plugin>").description("Enable a disabled plugin").option("--cwd <cwd>", "The current working directory", String, cwd()).option(
|
|
2667
|
+
"-s, --scope <scope>",
|
|
2668
|
+
`Installation scope: ${PLUGIN_SCOPES.join(", ")} (default: user)`,
|
|
2669
|
+
"user"
|
|
2670
|
+
).action(async (plugin, options) => {
|
|
2671
|
+
try {
|
|
2672
|
+
const scope = parsePluginScope(options.scope);
|
|
2673
|
+
if (!scope) {
|
|
2674
|
+
console.error(
|
|
2675
|
+
`Invalid scope: ${String(options.scope)}. Must be one of: ${PLUGIN_SCOPES.join(", ")}`
|
|
2676
|
+
);
|
|
2677
|
+
process.exit(1);
|
|
2678
|
+
}
|
|
2679
|
+
const { setCwd: setCwd2 } = await import("./state-KNRWP3FO.js");
|
|
2680
|
+
await setCwd2(options.cwd ?? cwd());
|
|
2681
|
+
const { enableSkillPlugin } = await import("./skillMarketplace-PSNKDINM.js");
|
|
2682
|
+
const result = enableSkillPlugin(plugin, { scope });
|
|
2683
|
+
console.log(`Enabled ${result.pluginSpec}`);
|
|
2684
|
+
process.exit(0);
|
|
2685
|
+
} catch (error) {
|
|
2686
|
+
console.error(error.message);
|
|
2687
|
+
process.exit(1);
|
|
2688
|
+
}
|
|
2689
|
+
});
|
|
2690
|
+
pluginCmd.command("disable <plugin>").description("Disable an enabled plugin").option("--cwd <cwd>", "The current working directory", String, cwd()).option(
|
|
2691
|
+
"-s, --scope <scope>",
|
|
2692
|
+
`Installation scope: ${PLUGIN_SCOPES.join(", ")} (default: user)`,
|
|
2693
|
+
"user"
|
|
2694
|
+
).action(async (plugin, options) => {
|
|
2695
|
+
try {
|
|
2696
|
+
const scope = parsePluginScope(options.scope);
|
|
2697
|
+
if (!scope) {
|
|
2698
|
+
console.error(
|
|
2699
|
+
`Invalid scope: ${String(options.scope)}. Must be one of: ${PLUGIN_SCOPES.join(", ")}`
|
|
2700
|
+
);
|
|
2701
|
+
process.exit(1);
|
|
2702
|
+
}
|
|
2703
|
+
const { setCwd: setCwd2 } = await import("./state-KNRWP3FO.js");
|
|
2704
|
+
await setCwd2(options.cwd ?? cwd());
|
|
2705
|
+
const { disableSkillPlugin } = await import("./skillMarketplace-PSNKDINM.js");
|
|
2706
|
+
const result = disableSkillPlugin(plugin, { scope });
|
|
2707
|
+
console.log(`Disabled ${result.pluginSpec}`);
|
|
2708
|
+
process.exit(0);
|
|
2709
|
+
} catch (error) {
|
|
2710
|
+
console.error(error.message);
|
|
2711
|
+
process.exit(1);
|
|
2712
|
+
}
|
|
2713
|
+
});
|
|
2714
|
+
pluginCmd.command("validate <path>").description("Validate a plugin or marketplace manifest").option("--cwd <cwd>", "The current working directory", String, cwd()).action(async (path, options) => {
|
|
2715
|
+
try {
|
|
2716
|
+
const { setCwd: setCwd2 } = await import("./state-KNRWP3FO.js");
|
|
2717
|
+
await setCwd2(options.cwd ?? cwd());
|
|
2718
|
+
const { formatValidationResult, validatePluginOrMarketplacePath } = await import("./pluginValidation-DSFXZ4GF.js");
|
|
2719
|
+
const result = validatePluginOrMarketplacePath(path);
|
|
2720
|
+
console.log(
|
|
2721
|
+
`Validating ${result.fileType} manifest: ${result.filePath}
|
|
2722
|
+
`
|
|
2723
|
+
);
|
|
2724
|
+
console.log(formatValidationResult(result));
|
|
2725
|
+
process.exit(result.success ? 0 : 1);
|
|
2726
|
+
} catch (error) {
|
|
2727
|
+
console.error(
|
|
2728
|
+
`Unexpected error during validation: ${error instanceof Error ? error.message : String(error)}`
|
|
2729
|
+
);
|
|
2730
|
+
process.exit(2);
|
|
2731
|
+
}
|
|
2732
|
+
});
|
|
2733
|
+
const skillsCmd = program.command("skills").description("Manage skills and skill marketplaces");
|
|
2734
|
+
const marketplaceCmd = skillsCmd.command("marketplace").description(
|
|
2735
|
+
"Manage skill marketplaces (.kode-plugin/marketplace.json; legacy .claude-plugin supported)"
|
|
2736
|
+
);
|
|
2737
|
+
registerMarketplaceCommands(marketplaceCmd);
|
|
2738
|
+
skillsCmd.command("install <plugin>").description("Install a skill plugin pack (<plugin>@<marketplace>)").option("--cwd <cwd>", "The current working directory", String, cwd()).option("--project", "Install into this project (.kode/...)", () => true).option("--force", "Overwrite existing installed files", () => true).action(async (plugin, options) => {
|
|
2739
|
+
try {
|
|
2740
|
+
const { setCwd: setCwd2 } = await import("./state-KNRWP3FO.js");
|
|
2741
|
+
await setCwd2(options.cwd ?? cwd());
|
|
2742
|
+
const { installSkillPlugin } = await import("./skillMarketplace-PSNKDINM.js");
|
|
2743
|
+
const result = installSkillPlugin(plugin, {
|
|
2744
|
+
project: options.project === true,
|
|
2745
|
+
force: options.force === true
|
|
2746
|
+
});
|
|
2747
|
+
const skillList = result.installedSkills.length > 0 ? `Skills: ${result.installedSkills.join(", ")}` : "Skills: (none)";
|
|
2748
|
+
console.log(`Installed ${plugin}
|
|
2749
|
+
${skillList}`);
|
|
2750
|
+
process.exit(0);
|
|
2751
|
+
} catch (error) {
|
|
2752
|
+
console.error(error.message);
|
|
2753
|
+
process.exit(1);
|
|
2754
|
+
}
|
|
2755
|
+
});
|
|
2756
|
+
skillsCmd.command("uninstall <plugin>").description("Uninstall a skill plugin pack (<plugin>@<marketplace>)").option("--cwd <cwd>", "The current working directory", String, cwd()).option("--project", "Uninstall from this project (.kode/...)", () => true).action(async (plugin, options) => {
|
|
2757
|
+
try {
|
|
2758
|
+
const { setCwd: setCwd2 } = await import("./state-KNRWP3FO.js");
|
|
2759
|
+
await setCwd2(options.cwd ?? cwd());
|
|
2760
|
+
const { uninstallSkillPlugin } = await import("./skillMarketplace-PSNKDINM.js");
|
|
2761
|
+
const result = uninstallSkillPlugin(plugin, {
|
|
2762
|
+
project: options.project === true
|
|
2763
|
+
});
|
|
2764
|
+
const skillList = result.removedSkills.length > 0 ? `Skills: ${result.removedSkills.join(", ")}` : "Skills: (none)";
|
|
2765
|
+
console.log(`Uninstalled ${plugin}
|
|
2766
|
+
${skillList}`);
|
|
2767
|
+
process.exit(0);
|
|
2768
|
+
} catch (error) {
|
|
2769
|
+
console.error(error.message);
|
|
2770
|
+
process.exit(1);
|
|
2771
|
+
}
|
|
2772
|
+
});
|
|
2773
|
+
skillsCmd.command("list-installed").description("List installed skill plugins").action(async () => {
|
|
2774
|
+
try {
|
|
2775
|
+
const { listInstalledSkillPlugins } = await import("./skillMarketplace-PSNKDINM.js");
|
|
2776
|
+
console.log(JSON.stringify(listInstalledSkillPlugins(), null, 2));
|
|
2777
|
+
process.exit(0);
|
|
2778
|
+
} catch (error) {
|
|
2779
|
+
console.error(error.message);
|
|
2780
|
+
process.exit(1);
|
|
2781
|
+
}
|
|
2782
|
+
});
|
|
2783
|
+
const allowedTools = program.command("approved-tools").description("Manage approved tools");
|
|
2784
|
+
allowedTools.command("list").description("List all approved tools").action(async () => {
|
|
2785
|
+
const result = handleListApprovedTools(getCwd());
|
|
2786
|
+
console.log(result);
|
|
2787
|
+
process.exit(0);
|
|
2788
|
+
});
|
|
2789
|
+
allowedTools.command("remove <tool>").description("Remove a tool from the list of approved tools").action(async (tool) => {
|
|
2790
|
+
const result = handleRemoveApprovedTool(tool);
|
|
2791
|
+
console.log(result.message);
|
|
2792
|
+
process.exit(result.success ? 0 : 1);
|
|
2793
|
+
});
|
|
2794
|
+
const mcp = program.command("mcp").description("Configure and manage MCP servers");
|
|
2795
|
+
mcp.command("serve").description(`Start the ${PRODUCT_NAME} MCP server`).action(async () => {
|
|
2796
|
+
const providedCwd = program.opts().cwd ?? cwd();
|
|
2797
|
+
if (!existsSync(providedCwd)) {
|
|
2798
|
+
console.error(`Error: Directory ${providedCwd} does not exist`);
|
|
2799
|
+
process.exit(1);
|
|
2800
|
+
}
|
|
2801
|
+
try {
|
|
2802
|
+
await setup(providedCwd, false);
|
|
2803
|
+
await startMCPServer(providedCwd);
|
|
2804
|
+
} catch (error) {
|
|
2805
|
+
console.error("Error: Failed to start MCP server:", error);
|
|
2806
|
+
process.exit(1);
|
|
2807
|
+
}
|
|
2808
|
+
});
|
|
2809
|
+
mcp.command("add-sse <name> <url>").description("Add an SSE server").option(
|
|
2810
|
+
"-s, --scope <scope>",
|
|
2811
|
+
"Configuration scope (local, user, or project)",
|
|
2812
|
+
"local"
|
|
2813
|
+
).option(
|
|
2814
|
+
"-H, --header <header...>",
|
|
2815
|
+
'Set headers (e.g. -H "X-Api-Key: abc123" -H "X-Custom: value")'
|
|
2816
|
+
).action(async (name, url, options) => {
|
|
2817
|
+
try {
|
|
2818
|
+
const scopeInfo = normalizeMcpScopeForCli(options.scope);
|
|
2819
|
+
const headers = parseMcpHeaders(options.header);
|
|
2820
|
+
addMcpServer(
|
|
2821
|
+
name,
|
|
2822
|
+
{ type: "sse", url, ...headers ? { headers } : {} },
|
|
2823
|
+
scopeInfo.scope
|
|
2824
|
+
);
|
|
2825
|
+
console.log(
|
|
2826
|
+
`Added SSE MCP server ${name} with URL: ${url} to ${scopeInfo.display} config`
|
|
2827
|
+
);
|
|
2828
|
+
if (headers) {
|
|
2829
|
+
console.log(`Headers: ${JSON.stringify(headers, null, 2)}`);
|
|
2830
|
+
}
|
|
2831
|
+
process.exit(0);
|
|
2832
|
+
} catch (error) {
|
|
2833
|
+
console.error(error.message);
|
|
2834
|
+
process.exit(1);
|
|
2835
|
+
}
|
|
2836
|
+
});
|
|
2837
|
+
mcp.command("add-http <name> <url>").description("Add a Streamable HTTP MCP server").option(
|
|
2838
|
+
"-s, --scope <scope>",
|
|
2839
|
+
"Configuration scope (local, user, or project)",
|
|
2840
|
+
"local"
|
|
2841
|
+
).option(
|
|
2842
|
+
"-H, --header <header...>",
|
|
2843
|
+
'Set headers (e.g. -H "X-Api-Key: abc123" -H "X-Custom: value")'
|
|
2844
|
+
).action(async (name, url, options) => {
|
|
2845
|
+
try {
|
|
2846
|
+
const scopeInfo = normalizeMcpScopeForCli(options.scope);
|
|
2847
|
+
const headers = parseMcpHeaders(options.header);
|
|
2848
|
+
addMcpServer(
|
|
2849
|
+
name,
|
|
2850
|
+
{ type: "http", url, ...headers ? { headers } : {} },
|
|
2851
|
+
scopeInfo.scope
|
|
2852
|
+
);
|
|
2853
|
+
console.log(
|
|
2854
|
+
`Added HTTP MCP server ${name} with URL: ${url} to ${scopeInfo.display} config`
|
|
2855
|
+
);
|
|
2856
|
+
if (headers) {
|
|
2857
|
+
console.log(`Headers: ${JSON.stringify(headers, null, 2)}`);
|
|
2858
|
+
}
|
|
2859
|
+
process.exit(0);
|
|
2860
|
+
} catch (error) {
|
|
2861
|
+
console.error(error.message);
|
|
2862
|
+
process.exit(1);
|
|
2863
|
+
}
|
|
2864
|
+
});
|
|
2865
|
+
mcp.command("add-ws <name> <url>").description("Add a WebSocket MCP server").option(
|
|
2866
|
+
"-s, --scope <scope>",
|
|
2867
|
+
"Configuration scope (local, user, or project)",
|
|
2868
|
+
"local"
|
|
2869
|
+
).action(async (name, url, options) => {
|
|
2870
|
+
try {
|
|
2871
|
+
const scopeInfo = normalizeMcpScopeForCli(options.scope);
|
|
2872
|
+
addMcpServer(name, { type: "ws", url }, scopeInfo.scope);
|
|
2873
|
+
console.log(
|
|
2874
|
+
`Added WebSocket MCP server ${name} with URL ${url} to ${scopeInfo.display} config`
|
|
2875
|
+
);
|
|
2876
|
+
process.exit(0);
|
|
2877
|
+
} catch (error) {
|
|
2878
|
+
console.error(error.message);
|
|
2879
|
+
process.exit(1);
|
|
2880
|
+
}
|
|
2881
|
+
});
|
|
2882
|
+
mcp.command("add [name] [commandOrUrl] [args...]").description("Add a server (run without arguments for interactive wizard)").option(
|
|
2883
|
+
"-s, --scope <scope>",
|
|
2884
|
+
"Configuration scope (local, user, or project)",
|
|
2885
|
+
"local"
|
|
2886
|
+
).option(
|
|
2887
|
+
"-t, --transport <transport>",
|
|
2888
|
+
"MCP transport (stdio, sse, or http)"
|
|
2889
|
+
).option(
|
|
2890
|
+
"-H, --header <header...>",
|
|
2891
|
+
'Set headers (e.g. -H "X-Api-Key: abc123" -H "X-Custom: value")'
|
|
2892
|
+
).option(
|
|
2893
|
+
"-e, --env <env...>",
|
|
2894
|
+
"Set environment variables (e.g. -e KEY=value)"
|
|
2895
|
+
).action(async (name, commandOrUrl, args, options) => {
|
|
2896
|
+
try {
|
|
2897
|
+
if (!name) {
|
|
2898
|
+
console.log("Interactive wizard mode: Enter the server details");
|
|
2899
|
+
const { createInterface } = await import("readline");
|
|
2900
|
+
const rl = createInterface({
|
|
2901
|
+
input: process.stdin,
|
|
2902
|
+
output: process.stdout
|
|
2903
|
+
});
|
|
2904
|
+
const question = (query) => new Promise((resolve) => rl.question(query, resolve));
|
|
2905
|
+
const serverName = await question("Server name: ");
|
|
2906
|
+
if (!serverName) {
|
|
2907
|
+
console.error("Error: Server name is required");
|
|
2908
|
+
rl.close();
|
|
2909
|
+
process.exit(1);
|
|
2910
|
+
}
|
|
2911
|
+
const serverType = await question(
|
|
2912
|
+
"Server type (stdio, http, sse, ws) [stdio]: "
|
|
2913
|
+
);
|
|
2914
|
+
const type = serverType && ["stdio", "http", "sse", "ws"].includes(serverType) ? serverType : "stdio";
|
|
2915
|
+
const prompt = type === "stdio" ? "Command: " : "URL: ";
|
|
2916
|
+
const commandOrUrlValue = await question(prompt);
|
|
2917
|
+
if (!commandOrUrlValue) {
|
|
2918
|
+
console.error(
|
|
2919
|
+
`Error: ${type === "stdio" ? "Command" : "URL"} is required`
|
|
2920
|
+
);
|
|
2921
|
+
rl.close();
|
|
2922
|
+
process.exit(1);
|
|
2923
|
+
}
|
|
2924
|
+
let serverArgs = [];
|
|
2925
|
+
let serverEnv = {};
|
|
2926
|
+
if (type === "stdio") {
|
|
2927
|
+
const argsStr = await question(
|
|
2928
|
+
"Command arguments (space-separated): "
|
|
2929
|
+
);
|
|
2930
|
+
serverArgs = argsStr ? argsStr.split(" ").filter(Boolean) : [];
|
|
2931
|
+
const envStr = await question(
|
|
2932
|
+
"Environment variables (format: KEY1=value1,KEY2=value2): "
|
|
2933
|
+
);
|
|
2934
|
+
if (envStr) {
|
|
2935
|
+
const envPairs = envStr.split(",").map((pair) => pair.trim());
|
|
2936
|
+
serverEnv = parseEnvVars(envPairs.map((pair) => pair));
|
|
2937
|
+
}
|
|
2938
|
+
}
|
|
2939
|
+
const scopeStr = await question(
|
|
2940
|
+
"Configuration scope (local, user, or project) [local]: "
|
|
2941
|
+
);
|
|
2942
|
+
const scopeInfo = normalizeMcpScopeForCli(scopeStr);
|
|
2943
|
+
const serverScope = scopeInfo.scope;
|
|
2944
|
+
rl.close();
|
|
2945
|
+
if (type === "http") {
|
|
2946
|
+
addMcpServer(
|
|
2947
|
+
serverName,
|
|
2948
|
+
{ type: "http", url: commandOrUrlValue },
|
|
2949
|
+
serverScope
|
|
2950
|
+
);
|
|
2951
|
+
console.log(
|
|
2952
|
+
`Added HTTP MCP server ${serverName} with URL ${commandOrUrlValue} to ${scopeInfo.display} config`
|
|
2953
|
+
);
|
|
2954
|
+
} else if (type === "sse") {
|
|
2955
|
+
addMcpServer(
|
|
2956
|
+
serverName,
|
|
2957
|
+
{ type: "sse", url: commandOrUrlValue },
|
|
2958
|
+
serverScope
|
|
2959
|
+
);
|
|
2960
|
+
console.log(
|
|
2961
|
+
`Added SSE MCP server ${serverName} with URL ${commandOrUrlValue} to ${scopeInfo.display} config`
|
|
2962
|
+
);
|
|
2963
|
+
} else if (type === "ws") {
|
|
2964
|
+
addMcpServer(
|
|
2965
|
+
serverName,
|
|
2966
|
+
{ type: "ws", url: commandOrUrlValue },
|
|
2967
|
+
serverScope
|
|
2968
|
+
);
|
|
2969
|
+
console.log(
|
|
2970
|
+
`Added WebSocket MCP server ${serverName} with URL ${commandOrUrlValue} to ${scopeInfo.display} config`
|
|
2971
|
+
);
|
|
2972
|
+
} else {
|
|
2973
|
+
addMcpServer(
|
|
2974
|
+
serverName,
|
|
2975
|
+
{
|
|
2976
|
+
type: "stdio",
|
|
2977
|
+
command: commandOrUrlValue,
|
|
2978
|
+
args: serverArgs,
|
|
2979
|
+
env: serverEnv
|
|
2980
|
+
},
|
|
2981
|
+
serverScope
|
|
2982
|
+
);
|
|
2983
|
+
console.log(
|
|
2984
|
+
`Added stdio MCP server ${serverName} with command: ${commandOrUrlValue} ${serverArgs.join(" ")} to ${scopeInfo.display} config`
|
|
2985
|
+
);
|
|
2986
|
+
}
|
|
2987
|
+
} else if (name && commandOrUrl) {
|
|
2988
|
+
const scopeInfo = normalizeMcpScopeForCli(options.scope);
|
|
2989
|
+
const transportInfo = normalizeMcpTransport(options.transport);
|
|
2990
|
+
if (transportInfo.transport === "stdio") {
|
|
2991
|
+
if (options.header?.length) {
|
|
2992
|
+
throw new Error(
|
|
2993
|
+
"--header can only be used with --transport http or --transport sse"
|
|
2994
|
+
);
|
|
2995
|
+
}
|
|
2996
|
+
const env = parseEnvVars(options.env);
|
|
2997
|
+
if (!transportInfo.explicit && looksLikeMcpUrl(commandOrUrl)) {
|
|
2998
|
+
console.warn(
|
|
2999
|
+
`Warning: "${commandOrUrl}" looks like a URL. Default transport is stdio, so it will be treated as a command.`
|
|
3000
|
+
);
|
|
3001
|
+
console.warn(
|
|
3002
|
+
`If you meant to add an HTTP MCP server, run: ${PRODUCT_COMMAND} mcp add ${name} ${commandOrUrl} --transport http`
|
|
3003
|
+
);
|
|
3004
|
+
console.warn(
|
|
3005
|
+
`If you meant to add a legacy SSE MCP server, run: ${PRODUCT_COMMAND} mcp add ${name} ${commandOrUrl} --transport sse`
|
|
3006
|
+
);
|
|
3007
|
+
}
|
|
3008
|
+
addMcpServer(
|
|
3009
|
+
name,
|
|
3010
|
+
{ type: "stdio", command: commandOrUrl, args: args || [], env },
|
|
3011
|
+
scopeInfo.scope
|
|
3012
|
+
);
|
|
3013
|
+
console.log(
|
|
3014
|
+
`Added stdio MCP server ${name} with command: ${commandOrUrl} ${(args || []).join(" ")} to ${scopeInfo.display} config`
|
|
3015
|
+
);
|
|
3016
|
+
} else {
|
|
3017
|
+
if (options.env?.length) {
|
|
3018
|
+
throw new Error("--env is only supported for stdio MCP servers");
|
|
3019
|
+
}
|
|
3020
|
+
if (args?.length) {
|
|
3021
|
+
throw new Error(
|
|
3022
|
+
"Unexpected arguments. URL-based MCP servers do not accept command args."
|
|
3023
|
+
);
|
|
3024
|
+
}
|
|
3025
|
+
const headers = parseMcpHeaders(options.header);
|
|
3026
|
+
addMcpServer(
|
|
3027
|
+
name,
|
|
3028
|
+
{
|
|
3029
|
+
type: transportInfo.transport,
|
|
3030
|
+
url: commandOrUrl,
|
|
3031
|
+
...headers ? { headers } : {}
|
|
3032
|
+
},
|
|
3033
|
+
scopeInfo.scope
|
|
3034
|
+
);
|
|
3035
|
+
const kind = transportInfo.transport.toUpperCase();
|
|
3036
|
+
console.log(
|
|
3037
|
+
`Added ${kind} MCP server ${name} with URL: ${commandOrUrl} to ${scopeInfo.display} config`
|
|
3038
|
+
);
|
|
3039
|
+
if (headers) {
|
|
3040
|
+
console.log(`Headers: ${JSON.stringify(headers, null, 2)}`);
|
|
3041
|
+
}
|
|
3042
|
+
}
|
|
3043
|
+
} else {
|
|
3044
|
+
console.error(
|
|
3045
|
+
"Error: Missing required arguments. Either provide no arguments for interactive mode or specify name and command/URL."
|
|
3046
|
+
);
|
|
3047
|
+
process.exit(1);
|
|
3048
|
+
}
|
|
3049
|
+
process.exit(0);
|
|
3050
|
+
} catch (error) {
|
|
3051
|
+
console.error(error.message);
|
|
3052
|
+
process.exit(1);
|
|
3053
|
+
}
|
|
3054
|
+
});
|
|
3055
|
+
mcp.command("remove <name>").description("Remove an MCP server").option(
|
|
3056
|
+
"-s, --scope <scope>",
|
|
3057
|
+
"Configuration scope (local, user, or project)"
|
|
3058
|
+
).action(async (name, options) => {
|
|
3059
|
+
try {
|
|
3060
|
+
if (options.scope) {
|
|
3061
|
+
const scopeInfo = normalizeMcpScopeForCli(options.scope);
|
|
3062
|
+
removeMcpServer(name, scopeInfo.scope);
|
|
3063
|
+
console.log(
|
|
3064
|
+
`Removed MCP server ${name} from ${scopeInfo.display} config`
|
|
3065
|
+
);
|
|
3066
|
+
process.exit(0);
|
|
3067
|
+
}
|
|
3068
|
+
const matches = [];
|
|
3069
|
+
const projectConfig = getCurrentProjectConfig();
|
|
3070
|
+
if (projectConfig.mcpServers?.[name]) {
|
|
3071
|
+
matches.push({
|
|
3072
|
+
scope: ensureConfigScope("project"),
|
|
3073
|
+
display: "local"
|
|
3074
|
+
});
|
|
3075
|
+
}
|
|
3076
|
+
const globalConfig = getGlobalConfig();
|
|
3077
|
+
if (globalConfig.mcpServers?.[name]) {
|
|
3078
|
+
matches.push({ scope: ensureConfigScope("global"), display: "user" });
|
|
3079
|
+
}
|
|
3080
|
+
const projectFileDefinitions = getProjectMcpServerDefinitions();
|
|
3081
|
+
if (projectFileDefinitions.servers[name]) {
|
|
3082
|
+
const source = projectFileDefinitions.sources[name];
|
|
3083
|
+
if (source === ".mcp.json") {
|
|
3084
|
+
matches.push({
|
|
3085
|
+
scope: ensureConfigScope("mcpjson"),
|
|
3086
|
+
display: "project"
|
|
3087
|
+
});
|
|
3088
|
+
} else {
|
|
3089
|
+
matches.push({
|
|
3090
|
+
scope: ensureConfigScope("mcprc"),
|
|
3091
|
+
display: "mcprc"
|
|
3092
|
+
});
|
|
3093
|
+
}
|
|
3094
|
+
}
|
|
3095
|
+
if (matches.length === 0) {
|
|
3096
|
+
throw new Error(`No MCP server found with name: ${name}`);
|
|
3097
|
+
}
|
|
3098
|
+
if (matches.length > 1) {
|
|
3099
|
+
console.error(
|
|
3100
|
+
`MCP server "${name}" exists in multiple scopes: ${matches.map((m) => m.display).join(", ")}`
|
|
3101
|
+
);
|
|
3102
|
+
console.error("Please specify which scope to remove from:");
|
|
3103
|
+
for (const match2 of matches) {
|
|
3104
|
+
console.error(
|
|
3105
|
+
` ${PRODUCT_COMMAND} mcp remove ${name} --scope ${match2.display}`
|
|
3106
|
+
);
|
|
3107
|
+
}
|
|
3108
|
+
process.exit(1);
|
|
3109
|
+
}
|
|
3110
|
+
const match = matches[0];
|
|
3111
|
+
removeMcpServer(name, match.scope);
|
|
3112
|
+
console.log(`Removed MCP server ${name} from ${match.display} config`);
|
|
3113
|
+
process.exit(0);
|
|
3114
|
+
} catch (error) {
|
|
3115
|
+
console.error(error.message);
|
|
3116
|
+
process.exit(1);
|
|
3117
|
+
}
|
|
3118
|
+
});
|
|
3119
|
+
mcp.command("list").description("List configured MCP servers").action(async () => {
|
|
3120
|
+
try {
|
|
3121
|
+
const servers = listMCPServers();
|
|
3122
|
+
if (Object.keys(servers).length === 0) {
|
|
3123
|
+
console.log(
|
|
3124
|
+
`No MCP servers configured. Use \`${PRODUCT_COMMAND} mcp add\` to add a server.`
|
|
3125
|
+
);
|
|
3126
|
+
process.exit(0);
|
|
3127
|
+
}
|
|
3128
|
+
const projectFileServers = getProjectMcpServerDefinitions();
|
|
3129
|
+
const clients = await getClients();
|
|
3130
|
+
const clientByName = /* @__PURE__ */ new Map();
|
|
3131
|
+
for (const client of clients) {
|
|
3132
|
+
clientByName.set(client.name, client);
|
|
3133
|
+
}
|
|
3134
|
+
const names = Object.keys(servers).sort((a, b) => a.localeCompare(b));
|
|
3135
|
+
for (const name of names) {
|
|
3136
|
+
const server = servers[name];
|
|
3137
|
+
const client = clientByName.get(name);
|
|
3138
|
+
const status = client?.type === "connected" ? "connected" : client?.type === "failed" ? "failed" : projectFileServers.servers[name] ? (() => {
|
|
3139
|
+
const approval = getMcprcServerStatus(name);
|
|
3140
|
+
if (approval === "pending") return "pending";
|
|
3141
|
+
if (approval === "rejected") return "rejected";
|
|
3142
|
+
return "disconnected";
|
|
3143
|
+
})() : "disconnected";
|
|
3144
|
+
const summary = (() => {
|
|
3145
|
+
switch (server.type) {
|
|
3146
|
+
case "http":
|
|
3147
|
+
return `${server.url} (http)`;
|
|
3148
|
+
case "sse":
|
|
3149
|
+
return `${server.url} (sse)`;
|
|
3150
|
+
case "sse-ide":
|
|
3151
|
+
return `${server.url} (sse-ide)`;
|
|
3152
|
+
case "ws":
|
|
3153
|
+
return `${server.url} (ws)`;
|
|
3154
|
+
case "ws-ide":
|
|
3155
|
+
return `${server.url} (ws-ide)`;
|
|
3156
|
+
case "stdio":
|
|
3157
|
+
default:
|
|
3158
|
+
return `${server.command} ${(server.args || []).join(" ")} (stdio)`;
|
|
3159
|
+
}
|
|
3160
|
+
})();
|
|
3161
|
+
console.log(`${name}: ${summary} [${status}]`);
|
|
3162
|
+
}
|
|
3163
|
+
process.exit(0);
|
|
3164
|
+
} catch (error) {
|
|
3165
|
+
console.error(error.message);
|
|
3166
|
+
process.exit(1);
|
|
3167
|
+
}
|
|
3168
|
+
});
|
|
3169
|
+
mcp.command("add-json <name> <json>").description("Add an MCP server with a JSON string").option(
|
|
3170
|
+
"-s, --scope <scope>",
|
|
3171
|
+
"Configuration scope (project, global, or mcprc)",
|
|
3172
|
+
"project"
|
|
3173
|
+
).action(async (name, jsonStr, options) => {
|
|
3174
|
+
try {
|
|
3175
|
+
const scope = ensureConfigScope(options.scope);
|
|
3176
|
+
let serverConfig;
|
|
3177
|
+
try {
|
|
3178
|
+
serverConfig = JSON.parse(jsonStr);
|
|
3179
|
+
} catch (e) {
|
|
3180
|
+
console.error("Error: Invalid JSON string");
|
|
3181
|
+
process.exit(1);
|
|
3182
|
+
}
|
|
3183
|
+
if (!serverConfig.type || !["stdio", "sse", "http", "ws", "sse-ide", "ws-ide"].includes(
|
|
3184
|
+
serverConfig.type
|
|
3185
|
+
)) {
|
|
3186
|
+
console.error(
|
|
3187
|
+
'Error: Server type must be one of: "stdio", "http", "sse", "ws", "sse-ide", "ws-ide"'
|
|
3188
|
+
);
|
|
3189
|
+
process.exit(1);
|
|
3190
|
+
}
|
|
3191
|
+
if (["sse", "http", "ws", "sse-ide", "ws-ide"].includes(
|
|
3192
|
+
serverConfig.type
|
|
3193
|
+
) && !serverConfig.url) {
|
|
3194
|
+
console.error("Error: URL-based MCP servers must have a URL");
|
|
3195
|
+
process.exit(1);
|
|
3196
|
+
}
|
|
3197
|
+
if (serverConfig.type === "stdio" && !serverConfig.command) {
|
|
3198
|
+
console.error("Error: stdio server must have a command");
|
|
3199
|
+
process.exit(1);
|
|
3200
|
+
}
|
|
3201
|
+
if (["sse-ide", "ws-ide"].includes(serverConfig.type) && !serverConfig.ideName) {
|
|
3202
|
+
console.error("Error: IDE MCP servers must include ideName");
|
|
3203
|
+
process.exit(1);
|
|
3204
|
+
}
|
|
3205
|
+
addMcpServer(name, serverConfig, scope);
|
|
3206
|
+
switch (serverConfig.type) {
|
|
3207
|
+
case "http":
|
|
3208
|
+
console.log(
|
|
3209
|
+
`Added HTTP MCP server ${name} with URL ${serverConfig.url} to ${scope} config`
|
|
3210
|
+
);
|
|
3211
|
+
break;
|
|
3212
|
+
case "sse":
|
|
3213
|
+
console.log(
|
|
3214
|
+
`Added SSE MCP server ${name} with URL ${serverConfig.url} to ${scope} config`
|
|
3215
|
+
);
|
|
3216
|
+
break;
|
|
3217
|
+
case "sse-ide":
|
|
3218
|
+
console.log(
|
|
3219
|
+
`Added SSE-IDE MCP server ${name} with URL ${serverConfig.url} to ${scope} config`
|
|
3220
|
+
);
|
|
3221
|
+
break;
|
|
3222
|
+
case "ws":
|
|
3223
|
+
console.log(
|
|
3224
|
+
`Added WS MCP server ${name} with URL ${serverConfig.url} to ${scope} config`
|
|
3225
|
+
);
|
|
3226
|
+
break;
|
|
3227
|
+
case "ws-ide":
|
|
3228
|
+
console.log(
|
|
3229
|
+
`Added WS-IDE MCP server ${name} with URL ${serverConfig.url} to ${scope} config`
|
|
3230
|
+
);
|
|
3231
|
+
break;
|
|
3232
|
+
case "stdio":
|
|
3233
|
+
default:
|
|
3234
|
+
console.log(
|
|
3235
|
+
`Added stdio MCP server ${name} with command: ${serverConfig.command} ${(serverConfig.args || []).join(" ")} to ${scope} config`
|
|
3236
|
+
);
|
|
3237
|
+
break;
|
|
3238
|
+
}
|
|
3239
|
+
process.exit(0);
|
|
3240
|
+
} catch (error) {
|
|
3241
|
+
console.error(error.message);
|
|
3242
|
+
process.exit(1);
|
|
3243
|
+
}
|
|
3244
|
+
});
|
|
3245
|
+
mcp.command("get <name>").description("Get details about an MCP server").action(async (name) => {
|
|
3246
|
+
try {
|
|
3247
|
+
const server = getMcpServer(name);
|
|
3248
|
+
if (!server) {
|
|
3249
|
+
console.error(`No MCP server found with name: ${name}`);
|
|
3250
|
+
process.exit(1);
|
|
3251
|
+
}
|
|
3252
|
+
const projectFileServers = getProjectMcpServerDefinitions();
|
|
3253
|
+
const clients = await getClients();
|
|
3254
|
+
const client = clients.find((c) => c.name === name);
|
|
3255
|
+
const status = client?.type === "connected" ? "connected" : client?.type === "failed" ? "failed" : projectFileServers.servers[name] ? (() => {
|
|
3256
|
+
const approval = getMcprcServerStatus(name);
|
|
3257
|
+
if (approval === "pending") return "pending";
|
|
3258
|
+
if (approval === "rejected") return "rejected";
|
|
3259
|
+
return "disconnected";
|
|
3260
|
+
})() : "disconnected";
|
|
3261
|
+
const scopeDisplay = (() => {
|
|
3262
|
+
switch (server.scope) {
|
|
3263
|
+
case "project":
|
|
3264
|
+
return "local";
|
|
3265
|
+
case "global":
|
|
3266
|
+
return "user";
|
|
3267
|
+
case "mcpjson":
|
|
3268
|
+
return "project";
|
|
3269
|
+
case "mcprc":
|
|
3270
|
+
return "mcprc";
|
|
3271
|
+
default:
|
|
3272
|
+
return server.scope;
|
|
3273
|
+
}
|
|
3274
|
+
})();
|
|
3275
|
+
console.log(`${name}:`);
|
|
3276
|
+
console.log(` Status: ${status}`);
|
|
3277
|
+
console.log(` Scope: ${scopeDisplay}`);
|
|
3278
|
+
const printHeaders = (headers) => {
|
|
3279
|
+
if (!headers || Object.keys(headers).length === 0) return;
|
|
3280
|
+
console.log(" Headers:");
|
|
3281
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
3282
|
+
console.log(` ${key}: ${value}`);
|
|
3283
|
+
}
|
|
3284
|
+
};
|
|
3285
|
+
switch (server.type) {
|
|
3286
|
+
case "http":
|
|
3287
|
+
console.log(` Type: http`);
|
|
3288
|
+
console.log(` URL: ${server.url}`);
|
|
3289
|
+
printHeaders(server.headers);
|
|
3290
|
+
break;
|
|
3291
|
+
case "sse":
|
|
3292
|
+
console.log(` Type: sse`);
|
|
3293
|
+
console.log(` URL: ${server.url}`);
|
|
3294
|
+
printHeaders(server.headers);
|
|
3295
|
+
break;
|
|
3296
|
+
case "sse-ide":
|
|
3297
|
+
console.log(` Type: sse-ide`);
|
|
3298
|
+
console.log(` URL: ${server.url}`);
|
|
3299
|
+
console.log(` IDE: ${server.ideName}`);
|
|
3300
|
+
printHeaders(server.headers);
|
|
3301
|
+
break;
|
|
3302
|
+
case "ws":
|
|
3303
|
+
console.log(` Type: ws`);
|
|
3304
|
+
console.log(` URL: ${server.url}`);
|
|
3305
|
+
break;
|
|
3306
|
+
case "ws-ide":
|
|
3307
|
+
console.log(` Type: ws-ide`);
|
|
3308
|
+
console.log(` URL: ${server.url}`);
|
|
3309
|
+
console.log(` IDE: ${server.ideName}`);
|
|
3310
|
+
break;
|
|
3311
|
+
case "stdio":
|
|
3312
|
+
default:
|
|
3313
|
+
console.log(` Type: stdio`);
|
|
3314
|
+
console.log(` Command: ${server.command}`);
|
|
3315
|
+
console.log(` Args: ${(server.args || []).join(" ")}`);
|
|
3316
|
+
if (server.env) {
|
|
3317
|
+
console.log(" Environment:");
|
|
3318
|
+
for (const [key, value] of Object.entries(server.env)) {
|
|
3319
|
+
console.log(` ${key}=${value}`);
|
|
3320
|
+
}
|
|
3321
|
+
}
|
|
3322
|
+
break;
|
|
3323
|
+
}
|
|
3324
|
+
process.exit(0);
|
|
3325
|
+
} catch (error) {
|
|
3326
|
+
console.error(error.message);
|
|
3327
|
+
process.exit(1);
|
|
3328
|
+
}
|
|
3329
|
+
});
|
|
3330
|
+
mcp.command("add-from-claude-desktop").description(
|
|
3331
|
+
"Import MCP servers from a desktop MCP host config (macOS, Windows and WSL)"
|
|
3332
|
+
).option(
|
|
3333
|
+
"-s, --scope <scope>",
|
|
3334
|
+
"Configuration scope (project, global, or mcprc)",
|
|
3335
|
+
"project"
|
|
3336
|
+
).action(async (options) => {
|
|
3337
|
+
try {
|
|
3338
|
+
const scope = ensureConfigScope(options.scope);
|
|
3339
|
+
const platform = process.platform;
|
|
3340
|
+
const { existsSync: existsSync2, readFileSync: readFileSync2 } = await import("fs");
|
|
3341
|
+
const { join: join2 } = await import("path");
|
|
3342
|
+
const { exec } = await import("child_process");
|
|
3343
|
+
const isWSL = platform === "linux" && existsSync2("/proc/version") && readFileSync2("/proc/version", "utf-8").toLowerCase().includes("microsoft");
|
|
3344
|
+
if (platform !== "darwin" && platform !== "win32" && !isWSL) {
|
|
3345
|
+
console.error(
|
|
3346
|
+
"Error: This command is only supported on macOS, Windows, and WSL"
|
|
3347
|
+
);
|
|
3348
|
+
process.exit(1);
|
|
3349
|
+
}
|
|
3350
|
+
let configPath;
|
|
3351
|
+
if (platform === "darwin") {
|
|
3352
|
+
configPath = join2(
|
|
3353
|
+
process.env.HOME || "~",
|
|
3354
|
+
"Library/Application Support/Claude/claude_desktop_config.json"
|
|
3355
|
+
);
|
|
3356
|
+
} else if (platform === "win32") {
|
|
3357
|
+
configPath = join2(
|
|
3358
|
+
process.env.APPDATA || "",
|
|
3359
|
+
"Claude/claude_desktop_config.json"
|
|
3360
|
+
);
|
|
3361
|
+
} else if (isWSL) {
|
|
3362
|
+
const whoamiCommand = await new Promise((resolve, reject) => {
|
|
3363
|
+
exec(
|
|
3364
|
+
'powershell.exe -Command "whoami"',
|
|
3365
|
+
(err, stdout) => {
|
|
3366
|
+
if (err) reject(err);
|
|
3367
|
+
else resolve(stdout.trim().split("\\").pop() || "");
|
|
3368
|
+
}
|
|
3369
|
+
);
|
|
3370
|
+
});
|
|
3371
|
+
configPath = `/mnt/c/Users/${whoamiCommand}/AppData/Roaming/Claude/claude_desktop_config.json`;
|
|
3372
|
+
}
|
|
3373
|
+
if (!existsSync2(configPath)) {
|
|
3374
|
+
console.error(`Error: Config file not found at ${configPath}`);
|
|
3375
|
+
process.exit(1);
|
|
3376
|
+
}
|
|
3377
|
+
let config2;
|
|
3378
|
+
try {
|
|
3379
|
+
const configContent = readFileSync2(configPath, "utf-8");
|
|
3380
|
+
config2 = JSON.parse(configContent);
|
|
3381
|
+
} catch (err) {
|
|
3382
|
+
console.error(`Error reading config file: ${err}`);
|
|
3383
|
+
process.exit(1);
|
|
3384
|
+
}
|
|
3385
|
+
const mcpServers = config2.mcpServers || {};
|
|
3386
|
+
const serverNames = Object.keys(mcpServers);
|
|
3387
|
+
const numServers = serverNames.length;
|
|
3388
|
+
if (numServers === 0) {
|
|
3389
|
+
console.log("No MCP servers found in the desktop config");
|
|
3390
|
+
process.exit(0);
|
|
3391
|
+
}
|
|
3392
|
+
const serversInfo = serverNames.map((name) => {
|
|
3393
|
+
const server = mcpServers[name];
|
|
3394
|
+
let description = "";
|
|
3395
|
+
switch (server.type) {
|
|
3396
|
+
case "http":
|
|
3397
|
+
description = `HTTP: ${server.url}`;
|
|
3398
|
+
break;
|
|
3399
|
+
case "sse":
|
|
3400
|
+
description = `SSE: ${server.url}`;
|
|
3401
|
+
break;
|
|
3402
|
+
case "sse-ide":
|
|
3403
|
+
description = `SSE-IDE (${server.ideName}): ${server.url}`;
|
|
3404
|
+
break;
|
|
3405
|
+
case "ws":
|
|
3406
|
+
description = `WS: ${server.url}`;
|
|
3407
|
+
break;
|
|
3408
|
+
case "ws-ide":
|
|
3409
|
+
description = `WS-IDE (${server.ideName}): ${server.url}`;
|
|
3410
|
+
break;
|
|
3411
|
+
case "stdio":
|
|
3412
|
+
default:
|
|
3413
|
+
description = `stdio: ${server.command} ${(server.args || []).join(" ")}`;
|
|
3414
|
+
break;
|
|
3415
|
+
}
|
|
3416
|
+
return { name, description, server };
|
|
3417
|
+
});
|
|
3418
|
+
const ink = await import("ink");
|
|
3419
|
+
const reactModule = await import("react");
|
|
3420
|
+
const inkjsui = await import("@inkjs/ui");
|
|
3421
|
+
const utilsTheme = await import("./theme-7S2QN2FO.js");
|
|
3422
|
+
const { render: render3 } = ink;
|
|
3423
|
+
const React11 = reactModule;
|
|
3424
|
+
const { MultiSelect: MultiSelect2 } = inkjsui;
|
|
3425
|
+
const { Box: Box6, Text: Text7 } = ink;
|
|
3426
|
+
const { getTheme: getTheme2 } = utilsTheme;
|
|
3427
|
+
await new Promise((resolve) => {
|
|
3428
|
+
function ClaudeDesktopImport() {
|
|
3429
|
+
const { useState: useState2 } = reactModule;
|
|
3430
|
+
const [isFinished, setIsFinished] = useState2(false);
|
|
3431
|
+
const [importResults, setImportResults] = useState2(
|
|
3432
|
+
[]
|
|
3433
|
+
);
|
|
3434
|
+
const [isImporting, setIsImporting] = useState2(false);
|
|
3435
|
+
const theme = getTheme2();
|
|
3436
|
+
const importServers = async (selectedServers) => {
|
|
3437
|
+
setIsImporting(true);
|
|
3438
|
+
const results = [];
|
|
3439
|
+
for (const name of selectedServers) {
|
|
3440
|
+
try {
|
|
3441
|
+
const server = mcpServers[name];
|
|
3442
|
+
const existingServer = getMcpServer(name);
|
|
3443
|
+
if (existingServer) {
|
|
3444
|
+
continue;
|
|
3445
|
+
}
|
|
3446
|
+
addMcpServer(name, server, scope);
|
|
3447
|
+
results.push({ name, success: true });
|
|
3448
|
+
} catch (err) {
|
|
3449
|
+
results.push({ name, success: false });
|
|
3450
|
+
}
|
|
3451
|
+
}
|
|
3452
|
+
setImportResults(results);
|
|
3453
|
+
setIsImporting(false);
|
|
3454
|
+
setIsFinished(true);
|
|
3455
|
+
setTimeout(() => {
|
|
3456
|
+
resolve();
|
|
3457
|
+
}, 1e3);
|
|
3458
|
+
};
|
|
3459
|
+
const handleConfirm = async (selectedServers) => {
|
|
3460
|
+
const existingServers = selectedServers.filter(
|
|
3461
|
+
(name) => getMcpServer(name)
|
|
3462
|
+
);
|
|
3463
|
+
if (existingServers.length > 0) {
|
|
3464
|
+
const results = [];
|
|
3465
|
+
const newServers = selectedServers.filter(
|
|
3466
|
+
(name) => !getMcpServer(name)
|
|
3467
|
+
);
|
|
3468
|
+
for (const name of newServers) {
|
|
3469
|
+
try {
|
|
3470
|
+
const server = mcpServers[name];
|
|
3471
|
+
addMcpServer(name, server, scope);
|
|
3472
|
+
results.push({ name, success: true });
|
|
3473
|
+
} catch (err) {
|
|
3474
|
+
results.push({ name, success: false });
|
|
3475
|
+
}
|
|
3476
|
+
}
|
|
3477
|
+
for (const name of existingServers) {
|
|
3478
|
+
try {
|
|
3479
|
+
const server = mcpServers[name];
|
|
3480
|
+
addMcpServer(name, server, scope);
|
|
3481
|
+
results.push({ name, success: true });
|
|
3482
|
+
} catch (err) {
|
|
3483
|
+
results.push({ name, success: false });
|
|
3484
|
+
}
|
|
3485
|
+
}
|
|
3486
|
+
setImportResults(results);
|
|
3487
|
+
setIsImporting(false);
|
|
3488
|
+
setIsFinished(true);
|
|
3489
|
+
setTimeout(() => {
|
|
3490
|
+
resolve();
|
|
3491
|
+
}, 1e3);
|
|
3492
|
+
} else {
|
|
3493
|
+
await importServers(selectedServers);
|
|
3494
|
+
}
|
|
3495
|
+
};
|
|
3496
|
+
return /* @__PURE__ */ React11.createElement(Box6, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React11.createElement(
|
|
3497
|
+
Box6,
|
|
3498
|
+
{
|
|
3499
|
+
flexDirection: "column",
|
|
3500
|
+
borderStyle: "round",
|
|
3501
|
+
borderColor: theme.kode,
|
|
3502
|
+
padding: 1,
|
|
3503
|
+
width: "100%"
|
|
3504
|
+
},
|
|
3505
|
+
/* @__PURE__ */ React11.createElement(Text7, { bold: true, color: theme.kode }, "Import MCP Servers from Desktop Config"),
|
|
3506
|
+
/* @__PURE__ */ React11.createElement(Box6, { marginY: 1 }, /* @__PURE__ */ React11.createElement(Text7, null, "Found ", numServers, " MCP servers in the desktop config.")),
|
|
3507
|
+
/* @__PURE__ */ React11.createElement(Text7, null, "Please select the servers you want to import:"),
|
|
3508
|
+
/* @__PURE__ */ React11.createElement(Box6, { marginTop: 1 }, /* @__PURE__ */ React11.createElement(
|
|
3509
|
+
MultiSelect2,
|
|
3510
|
+
{
|
|
3511
|
+
options: serverNames.map((name) => ({
|
|
3512
|
+
label: name,
|
|
3513
|
+
value: name
|
|
3514
|
+
})),
|
|
3515
|
+
defaultValue: serverNames,
|
|
3516
|
+
onSubmit: handleConfirm
|
|
3517
|
+
}
|
|
3518
|
+
))
|
|
3519
|
+
), /* @__PURE__ */ React11.createElement(Box6, { marginTop: 0, marginLeft: 3 }, /* @__PURE__ */ React11.createElement(Text7, { dimColor: true }, "Space to select \xB7 Enter to confirm \xB7 Esc to cancel")), isFinished && /* @__PURE__ */ React11.createElement(Box6, { marginTop: 1 }, /* @__PURE__ */ React11.createElement(Text7, { color: theme.success }, "Successfully imported", " ", importResults.filter((r) => r.success).length, " MCP server to local config.")));
|
|
3520
|
+
}
|
|
3521
|
+
const { unmount } = render3(/* @__PURE__ */ React11.createElement(ClaudeDesktopImport, null));
|
|
3522
|
+
setTimeout(() => {
|
|
3523
|
+
unmount();
|
|
3524
|
+
resolve();
|
|
3525
|
+
}, 3e4);
|
|
3526
|
+
});
|
|
3527
|
+
process.exit(0);
|
|
3528
|
+
} catch (error) {
|
|
3529
|
+
console.error(`Error: ${error.message}`);
|
|
3530
|
+
process.exit(1);
|
|
3531
|
+
}
|
|
3532
|
+
});
|
|
3533
|
+
const resetMcpChoices = () => {
|
|
3534
|
+
const config2 = getCurrentProjectConfig();
|
|
3535
|
+
saveCurrentProjectConfig({
|
|
3536
|
+
...config2,
|
|
3537
|
+
approvedMcprcServers: [],
|
|
3538
|
+
rejectedMcprcServers: []
|
|
3539
|
+
});
|
|
3540
|
+
console.log(
|
|
3541
|
+
"All project-file MCP server approvals/rejections (.mcp.json/.mcprc) have been reset."
|
|
3542
|
+
);
|
|
3543
|
+
console.log(
|
|
3544
|
+
`You will be prompted for approval next time you start ${PRODUCT_NAME}.`
|
|
3545
|
+
);
|
|
3546
|
+
process.exit(0);
|
|
3547
|
+
};
|
|
3548
|
+
mcp.command("reset-project-choices").description(
|
|
3549
|
+
"Reset approvals for project-file MCP servers (.mcp.json/.mcprc) in this project"
|
|
3550
|
+
).action(() => {
|
|
3551
|
+
resetMcpChoices();
|
|
3552
|
+
});
|
|
3553
|
+
mcp.command("reset-mcprc-choices").description(
|
|
3554
|
+
"Reset approvals for project-file MCP servers (.mcp.json/.mcprc) in this project"
|
|
3555
|
+
).action(() => {
|
|
3556
|
+
resetMcpChoices();
|
|
3557
|
+
});
|
|
3558
|
+
program.command("doctor").description(`Check the health of your ${PRODUCT_NAME} installation`).action(async () => {
|
|
3559
|
+
await new Promise((resolve) => {
|
|
3560
|
+
;
|
|
3561
|
+
(async () => {
|
|
3562
|
+
const { render: render3 } = await import("ink");
|
|
3563
|
+
render3(/* @__PURE__ */ React10.createElement(Doctor, { onDone: () => resolve(), doctorMode: true }));
|
|
3564
|
+
})();
|
|
3565
|
+
});
|
|
3566
|
+
process.exit(0);
|
|
3567
|
+
});
|
|
3568
|
+
program.command("update").description("Show manual upgrade commands (no auto-install)").action(async () => {
|
|
3569
|
+
console.log(`Current version: ${MACRO.VERSION}`);
|
|
3570
|
+
console.log("Checking for updates...");
|
|
3571
|
+
const { getLatestVersion, getUpdateCommandSuggestions } = await import("./autoUpdater-DNRMJWFQ.js");
|
|
3572
|
+
const latestVersion = await getLatestVersion();
|
|
3573
|
+
if (!latestVersion) {
|
|
3574
|
+
console.error("Failed to check for updates");
|
|
3575
|
+
process.exit(1);
|
|
3576
|
+
}
|
|
3577
|
+
if (latestVersion === MACRO.VERSION) {
|
|
3578
|
+
console.log(`${PRODUCT_NAME} is up to date`);
|
|
3579
|
+
process.exit(0);
|
|
3580
|
+
}
|
|
3581
|
+
console.log(`New version available: ${latestVersion}`);
|
|
3582
|
+
const cmds = await getUpdateCommandSuggestions();
|
|
3583
|
+
console.log("\nRun one of the following commands to update:");
|
|
3584
|
+
for (const c of cmds) console.log(` ${c}`);
|
|
3585
|
+
if (process.platform !== "win32") {
|
|
3586
|
+
console.log(
|
|
3587
|
+
'\nNote: you may need to prefix with "sudo" on macOS/Linux.'
|
|
3588
|
+
);
|
|
3589
|
+
}
|
|
3590
|
+
process.exit(0);
|
|
3591
|
+
});
|
|
3592
|
+
program.command("log").description("Manage conversation logs.").argument(
|
|
3593
|
+
"[number]",
|
|
3594
|
+
"A number (0, 1, 2, etc.) to display a specific log",
|
|
3595
|
+
parseInt
|
|
3596
|
+
).option("--cwd <cwd>", "The current working directory", String, cwd()).action(async (number, { cwd: cwd2 }) => {
|
|
3597
|
+
await setup(cwd2, false);
|
|
3598
|
+
const context2 = {};
|
|
3599
|
+
(async () => {
|
|
3600
|
+
const { render: render3 } = await import("ink");
|
|
3601
|
+
const { unmount } = render3(
|
|
3602
|
+
/* @__PURE__ */ React10.createElement(LogList, { context: context2, type: "messages", logNumber: number }),
|
|
3603
|
+
renderContextWithExitOnCtrlC
|
|
3604
|
+
);
|
|
3605
|
+
context2.unmount = unmount;
|
|
3606
|
+
})();
|
|
3607
|
+
});
|
|
3608
|
+
program.command("resume").description(
|
|
3609
|
+
"Resume a previous conversation. Optionally provide a session ID or session name (legacy: log index or file path)."
|
|
3610
|
+
).argument(
|
|
3611
|
+
"[identifier]",
|
|
3612
|
+
"A session ID or session name (legacy: log index or file path)"
|
|
3613
|
+
).option("--cwd <cwd>", "The current working directory", String, cwd()).option("-e, --enable-architect", "Enable the Architect tool", () => true).option("-v, --verbose", "Do not truncate message output", () => true).option(
|
|
3614
|
+
"--safe",
|
|
3615
|
+
"Enable strict permission checking mode (default is permissive)",
|
|
3616
|
+
() => true
|
|
3617
|
+
).option(
|
|
3618
|
+
"--disable-slash-commands",
|
|
3619
|
+
"Disable slash commands (treat /... as plain text)",
|
|
3620
|
+
() => true
|
|
3621
|
+
).action(
|
|
3622
|
+
async (identifier, { cwd: cwd2, enableArchitect, safe, verbose, disableSlashCommands }) => {
|
|
3623
|
+
await setup(cwd2, safe);
|
|
3624
|
+
assertMinVersion();
|
|
3625
|
+
const [{ getTools }, { getCommands }] = await Promise.all([
|
|
3626
|
+
import("./tools-FZU2FZBD.js"),
|
|
3627
|
+
import("./commands-TWH6PGVG.js")
|
|
3628
|
+
]);
|
|
3629
|
+
const [allTools, commands, mcpClients] = await Promise.all([
|
|
3630
|
+
getTools(
|
|
3631
|
+
enableArchitect ?? getCurrentProjectConfig().enableArchitectTool
|
|
3632
|
+
),
|
|
3633
|
+
getCommands(),
|
|
3634
|
+
getClients()
|
|
3635
|
+
]);
|
|
3636
|
+
const tools = disableSlashCommands === true ? allTools.filter((t) => t.name !== "SlashCommand") : allTools;
|
|
3637
|
+
if (identifier !== void 0) {
|
|
3638
|
+
const { loadKodeAgentSessionMessages } = await import("./kodeAgentSessionLoad-6N27AC5K.js");
|
|
3639
|
+
const { resolveResumeSessionIdentifier } = await import("./kodeAgentSessionResume-HUSAEO24.js");
|
|
3640
|
+
const { setKodeAgentSessionId } = await import("./kodeAgentSessionId-X6XWQW7B.js");
|
|
3641
|
+
const rawIdentifier = String(identifier).trim();
|
|
3642
|
+
const isLegacyNumber = /^-?\\d+$/.test(rawIdentifier);
|
|
3643
|
+
const isLegacyPath = !isLegacyNumber && existsSync(rawIdentifier);
|
|
3644
|
+
let messages;
|
|
3645
|
+
let messageLogName = dateToFilename(/* @__PURE__ */ new Date());
|
|
3646
|
+
let initialForkNumber = void 0;
|
|
3647
|
+
try {
|
|
3648
|
+
if (isLegacyNumber || isLegacyPath) {
|
|
3649
|
+
const logs = await loadLogList(CACHE_PATHS.messages());
|
|
3650
|
+
if (isLegacyNumber) {
|
|
3651
|
+
const number = Math.abs(parseInt(rawIdentifier, 10));
|
|
3652
|
+
const log = logs[number];
|
|
3653
|
+
if (!log) {
|
|
3654
|
+
console.error("No conversation found at index", number);
|
|
3655
|
+
process.exit(1);
|
|
3656
|
+
}
|
|
3657
|
+
messages = await loadMessagesFromLog(log.fullPath, tools);
|
|
3658
|
+
messageLogName = log.date;
|
|
3659
|
+
initialForkNumber = getNextAvailableLogForkNumber(
|
|
3660
|
+
log.date,
|
|
3661
|
+
log.forkNumber ?? 1,
|
|
3662
|
+
0
|
|
3663
|
+
);
|
|
3664
|
+
} else {
|
|
3665
|
+
messages = await loadMessagesFromLog(rawIdentifier, tools);
|
|
3666
|
+
const pathSegments = rawIdentifier.split("/");
|
|
3667
|
+
const filename = pathSegments[pathSegments.length - 1] ?? "unknown";
|
|
3668
|
+
const { date, forkNumber } = parseLogFilename(filename);
|
|
3669
|
+
messageLogName = date;
|
|
3670
|
+
initialForkNumber = getNextAvailableLogForkNumber(
|
|
3671
|
+
date,
|
|
3672
|
+
forkNumber ?? 1,
|
|
3673
|
+
0
|
|
3674
|
+
);
|
|
3675
|
+
}
|
|
3676
|
+
} else {
|
|
3677
|
+
const resolved = resolveResumeSessionIdentifier({
|
|
3678
|
+
cwd: cwd2,
|
|
3679
|
+
identifier: rawIdentifier
|
|
3680
|
+
});
|
|
3681
|
+
if (resolved.kind === "ok") {
|
|
3682
|
+
setKodeAgentSessionId(resolved.sessionId);
|
|
3683
|
+
messages = loadKodeAgentSessionMessages({
|
|
3684
|
+
cwd: cwd2,
|
|
3685
|
+
sessionId: resolved.sessionId
|
|
3686
|
+
});
|
|
3687
|
+
} else if (resolved.kind === "different_directory") {
|
|
3688
|
+
console.error(
|
|
3689
|
+
resolved.otherCwd ? `Error: That session belongs to a different directory: ${resolved.otherCwd}` : `Error: That session belongs to a different directory.`
|
|
3690
|
+
);
|
|
3691
|
+
process.exit(1);
|
|
3692
|
+
} else if (resolved.kind === "ambiguous") {
|
|
3693
|
+
console.error(
|
|
3694
|
+
`Error: Multiple sessions match "${rawIdentifier}": ${resolved.matchingSessionIds.join(
|
|
3695
|
+
", "
|
|
3696
|
+
)}`
|
|
3697
|
+
);
|
|
3698
|
+
process.exit(1);
|
|
3699
|
+
} else {
|
|
3700
|
+
console.error(
|
|
3701
|
+
`No conversation found with session ID or name: ${rawIdentifier}`
|
|
3702
|
+
);
|
|
3703
|
+
process.exit(1);
|
|
3704
|
+
}
|
|
3705
|
+
}
|
|
3706
|
+
const isDefaultModel = await isDefaultSlowAndCapableModel();
|
|
3707
|
+
{
|
|
3708
|
+
const { render: render3 } = await import("ink");
|
|
3709
|
+
const { REPL } = await import("./REPL-GIU4ZIXM.js");
|
|
3710
|
+
render3(
|
|
3711
|
+
/* @__PURE__ */ React10.createElement(
|
|
3712
|
+
REPL,
|
|
3713
|
+
{
|
|
3714
|
+
initialPrompt: "",
|
|
3715
|
+
messageLogName,
|
|
3716
|
+
initialForkNumber,
|
|
3717
|
+
shouldShowPromptInput: true,
|
|
3718
|
+
verbose,
|
|
3719
|
+
commands,
|
|
3720
|
+
disableSlashCommands: disableSlashCommands === true,
|
|
3721
|
+
tools,
|
|
3722
|
+
safeMode: safe,
|
|
3723
|
+
initialMessages: messages,
|
|
3724
|
+
mcpClients,
|
|
3725
|
+
isDefaultModel
|
|
3726
|
+
}
|
|
3727
|
+
),
|
|
3728
|
+
{ exitOnCtrlC: false }
|
|
3729
|
+
);
|
|
3730
|
+
}
|
|
3731
|
+
} catch (error) {
|
|
3732
|
+
logError(`Failed to load conversation: ${error}`);
|
|
3733
|
+
process.exit(1);
|
|
3734
|
+
}
|
|
3735
|
+
} else {
|
|
3736
|
+
const { listKodeAgentSessions } = await import("./kodeAgentSessionResume-HUSAEO24.js");
|
|
3737
|
+
const sessions = listKodeAgentSessions({ cwd: cwd2 });
|
|
3738
|
+
if (sessions.length === 0) {
|
|
3739
|
+
console.error("No conversation found to resume");
|
|
3740
|
+
process.exit(1);
|
|
3741
|
+
}
|
|
3742
|
+
const context2 = {};
|
|
3743
|
+
(async () => {
|
|
3744
|
+
const { render: render3 } = await import("ink");
|
|
3745
|
+
const { unmount } = render3(
|
|
3746
|
+
/* @__PURE__ */ React10.createElement(
|
|
3747
|
+
ResumeConversation,
|
|
3748
|
+
{
|
|
3749
|
+
cwd: cwd2,
|
|
3750
|
+
context: context2,
|
|
3751
|
+
commands,
|
|
3752
|
+
sessions,
|
|
3753
|
+
tools,
|
|
3754
|
+
verbose,
|
|
3755
|
+
safeMode: safe,
|
|
3756
|
+
disableSlashCommands: disableSlashCommands === true,
|
|
3757
|
+
mcpClients,
|
|
3758
|
+
initialPrompt: ""
|
|
3759
|
+
}
|
|
3760
|
+
),
|
|
3761
|
+
renderContextWithExitOnCtrlC
|
|
3762
|
+
);
|
|
3763
|
+
context2.unmount = unmount;
|
|
3764
|
+
})();
|
|
3765
|
+
}
|
|
3766
|
+
}
|
|
3767
|
+
);
|
|
3768
|
+
program.command("error").description(
|
|
3769
|
+
"View error logs. Optionally provide a number (0, -1, -2, etc.) to display a specific log."
|
|
3770
|
+
).argument(
|
|
3771
|
+
"[number]",
|
|
3772
|
+
"A number (0, 1, 2, etc.) to display a specific log",
|
|
3773
|
+
parseInt
|
|
3774
|
+
).option("--cwd <cwd>", "The current working directory", String, cwd()).action(async (number, { cwd: cwd2 }) => {
|
|
3775
|
+
await setup(cwd2, false);
|
|
3776
|
+
const context2 = {};
|
|
3777
|
+
(async () => {
|
|
3778
|
+
const { render: render3 } = await import("ink");
|
|
3779
|
+
const { unmount } = render3(
|
|
3780
|
+
/* @__PURE__ */ React10.createElement(LogList, { context: context2, type: "errors", logNumber: number }),
|
|
3781
|
+
renderContextWithExitOnCtrlC
|
|
3782
|
+
);
|
|
3783
|
+
context2.unmount = unmount;
|
|
3784
|
+
})();
|
|
3785
|
+
});
|
|
3786
|
+
const context = program.command("context").description(
|
|
3787
|
+
`Set static context (eg. ${PRODUCT_COMMAND} context add-file ./src/*.py)`
|
|
3788
|
+
);
|
|
3789
|
+
context.command("get <key>").option("--cwd <cwd>", "The current working directory", String, cwd()).description("Get a value from context").action(async (key, { cwd: cwd2 }) => {
|
|
3790
|
+
await setup(cwd2, false);
|
|
3791
|
+
const context2 = omitKeys(
|
|
3792
|
+
await getContext(),
|
|
3793
|
+
"codeStyle",
|
|
3794
|
+
"directoryStructure"
|
|
3795
|
+
);
|
|
3796
|
+
console.log(context2[key]);
|
|
3797
|
+
process.exit(0);
|
|
3798
|
+
});
|
|
3799
|
+
context.command("set <key> <value>").description("Set a value in context").option("--cwd <cwd>", "The current working directory", String, cwd()).action(async (key, value, { cwd: cwd2 }) => {
|
|
3800
|
+
await setup(cwd2, false);
|
|
3801
|
+
setContext(key, value);
|
|
3802
|
+
console.log(`Set context.${key} to "${value}"`);
|
|
3803
|
+
process.exit(0);
|
|
3804
|
+
});
|
|
3805
|
+
context.command("list").description("List all context values").option("--cwd <cwd>", "The current working directory", String, cwd()).action(async ({ cwd: cwd2 }) => {
|
|
3806
|
+
await setup(cwd2, false);
|
|
3807
|
+
const context2 = omitKeys(
|
|
3808
|
+
await getContext(),
|
|
3809
|
+
"codeStyle",
|
|
3810
|
+
"directoryStructure",
|
|
3811
|
+
"gitStatus"
|
|
3812
|
+
);
|
|
3813
|
+
console.log(JSON.stringify(context2, null, 2));
|
|
3814
|
+
process.exit(0);
|
|
3815
|
+
});
|
|
3816
|
+
context.command("remove <key>").description("Remove a value from context").option("--cwd <cwd>", "The current working directory", String, cwd()).action(async (key, { cwd: cwd2 }) => {
|
|
3817
|
+
await setup(cwd2, false);
|
|
3818
|
+
removeContext(key);
|
|
3819
|
+
console.log(`Removed context.${key}`);
|
|
3820
|
+
process.exit(0);
|
|
3821
|
+
});
|
|
3822
|
+
await program.parseAsync(process.argv);
|
|
3823
|
+
return program;
|
|
3824
|
+
}
|
|
3825
|
+
async function stdin() {
|
|
3826
|
+
if (process.stdin.isTTY) {
|
|
3827
|
+
return "";
|
|
3828
|
+
}
|
|
3829
|
+
let data = "";
|
|
3830
|
+
for await (const chunk of process.stdin) data += chunk;
|
|
3831
|
+
return data;
|
|
3832
|
+
}
|
|
3833
|
+
var isGracefulExitInProgress = false;
|
|
3834
|
+
async function gracefulExit(code = 0) {
|
|
3835
|
+
if (isGracefulExitInProgress) {
|
|
3836
|
+
process.exit(code);
|
|
3837
|
+
return;
|
|
3838
|
+
}
|
|
3839
|
+
isGracefulExitInProgress = true;
|
|
3840
|
+
try {
|
|
3841
|
+
const { runSessionEndHooks } = await import("./kodeHooks-TDMXFWSO.js");
|
|
3842
|
+
const { getKodeAgentSessionId } = await import("./kodeAgentSessionId-X6XWQW7B.js");
|
|
3843
|
+
const { tmpdir } = await import("os");
|
|
3844
|
+
const { join: join2 } = await import("path");
|
|
3845
|
+
const sessionId = getKodeAgentSessionId();
|
|
3846
|
+
const transcriptPath = join2(
|
|
3847
|
+
tmpdir(),
|
|
3848
|
+
"kode-hooks-transcripts",
|
|
3849
|
+
`${sessionId}.transcript.txt`
|
|
3850
|
+
);
|
|
3851
|
+
const { signal, cleanup } = (() => {
|
|
3852
|
+
if (typeof AbortSignal !== "undefined" && typeof AbortSignal.timeout === "function") {
|
|
3853
|
+
return {
|
|
3854
|
+
signal: AbortSignal.timeout(5e3),
|
|
3855
|
+
cleanup: () => {
|
|
3856
|
+
}
|
|
3857
|
+
};
|
|
3858
|
+
}
|
|
3859
|
+
const controller = new AbortController();
|
|
3860
|
+
const timer = setTimeout(() => controller.abort(), 5e3);
|
|
3861
|
+
return { signal: controller.signal, cleanup: () => clearTimeout(timer) };
|
|
3862
|
+
})();
|
|
3863
|
+
try {
|
|
3864
|
+
await runSessionEndHooks({
|
|
3865
|
+
reason: "exit",
|
|
3866
|
+
cwd: cwd(),
|
|
3867
|
+
transcriptPath,
|
|
3868
|
+
signal
|
|
3869
|
+
});
|
|
3870
|
+
} finally {
|
|
3871
|
+
cleanup();
|
|
3872
|
+
}
|
|
3873
|
+
} catch {
|
|
3874
|
+
}
|
|
3875
|
+
try {
|
|
3876
|
+
resetCursor();
|
|
3877
|
+
} catch {
|
|
3878
|
+
}
|
|
3879
|
+
try {
|
|
3880
|
+
BunShell.getInstance().close();
|
|
3881
|
+
} catch {
|
|
3882
|
+
}
|
|
3883
|
+
process.exit(code);
|
|
3884
|
+
}
|
|
3885
|
+
var didInstallProcessHandlers = false;
|
|
3886
|
+
function installProcessHandlers() {
|
|
3887
|
+
if (didInstallProcessHandlers) return;
|
|
3888
|
+
didInstallProcessHandlers = true;
|
|
3889
|
+
process.on("exit", () => {
|
|
3890
|
+
resetCursor();
|
|
3891
|
+
BunShell.getInstance().close();
|
|
3892
|
+
});
|
|
3893
|
+
process.on("SIGINT", () => void gracefulExit(0));
|
|
3894
|
+
process.on("SIGTERM", () => void gracefulExit(0));
|
|
3895
|
+
process.on("SIGBREAK", () => void gracefulExit(0));
|
|
3896
|
+
process.on("unhandledRejection", (err) => {
|
|
3897
|
+
console.error("Unhandled rejection:", err);
|
|
3898
|
+
void gracefulExit(1);
|
|
3899
|
+
});
|
|
3900
|
+
process.on("uncaughtException", (err) => {
|
|
3901
|
+
console.error("Uncaught exception:", err);
|
|
3902
|
+
void gracefulExit(1);
|
|
3903
|
+
});
|
|
3904
|
+
}
|
|
3905
|
+
function resetCursor() {
|
|
3906
|
+
const terminal = process.stderr.isTTY ? process.stderr : process.stdout.isTTY ? process.stdout : void 0;
|
|
3907
|
+
terminal?.write(`\x1B[?25h${cursorShow}`);
|
|
3908
|
+
}
|
|
3909
|
+
|
|
3910
|
+
// src/entrypoints/cli.tsx
|
|
3911
|
+
import * as dontcare from "@anthropic-ai/sdk/shims/node";
|
|
3912
|
+
initSentry();
|
|
3913
|
+
ensurePackagedRuntimeEnv();
|
|
3914
|
+
ensureYogaWasmPath(import.meta.url);
|
|
3915
|
+
Object.keys(dontcare);
|
|
3916
|
+
installProcessHandlers();
|
|
3917
|
+
void runCli();
|