@within-7/minto 0.4.0 → 0.4.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.
Files changed (391) hide show
  1. package/dist/Tool.js +7 -0
  2. package/dist/Tool.js.map +2 -2
  3. package/dist/commands/agents/AgentsCommand.js +1 -1
  4. package/dist/commands/agents/AgentsCommand.js.map +2 -2
  5. package/dist/commands/agents/constants.js +2 -2
  6. package/dist/commands/agents/constants.js.map +2 -2
  7. package/dist/commands/clear.js +4 -3
  8. package/dist/commands/clear.js.map +2 -2
  9. package/dist/commands/compact.js +2 -2
  10. package/dist/commands/compact.js.map +1 -1
  11. package/dist/commands/context.js +3 -1
  12. package/dist/commands/context.js.map +2 -2
  13. package/dist/commands/login.js +128 -0
  14. package/dist/commands/login.js.map +7 -0
  15. package/dist/commands/memory.js +33 -82
  16. package/dist/commands/memory.js.map +2 -2
  17. package/dist/commands/quit.js +3 -1
  18. package/dist/commands/quit.js.map +2 -2
  19. package/dist/commands/resume.js +39 -239
  20. package/dist/commands/resume.js.map +2 -2
  21. package/dist/commands/tasks.js +1 -1
  22. package/dist/commands/tasks.js.map +2 -2
  23. package/dist/commands/terminalSetup.js +6 -2
  24. package/dist/commands/terminalSetup.js.map +2 -2
  25. package/dist/commands.js +2 -0
  26. package/dist/commands.js.map +2 -2
  27. package/dist/components/AgentDetailView.js +126 -0
  28. package/dist/components/AgentDetailView.js.map +7 -0
  29. package/dist/components/AgentThinkingBlock.js +1 -1
  30. package/dist/components/AgentThinkingBlock.js.map +2 -2
  31. package/dist/components/AgentViewBanner.js +22 -0
  32. package/dist/components/AgentViewBanner.js.map +7 -0
  33. package/dist/components/HeaderBar.js +1 -1
  34. package/dist/components/HeaderBar.js.map +2 -2
  35. package/dist/components/Help.js +8 -1
  36. package/dist/components/Help.js.map +2 -2
  37. package/dist/components/HotkeyHelpPanel.js +26 -8
  38. package/dist/components/HotkeyHelpPanel.js.map +2 -2
  39. package/dist/components/IdleNotificationBar.js +10 -0
  40. package/dist/components/IdleNotificationBar.js.map +7 -0
  41. package/dist/components/ModelSelector/ModelSelector.js +55 -20
  42. package/dist/components/ModelSelector/ModelSelector.js.map +2 -2
  43. package/dist/components/PromptInput.js +186 -115
  44. package/dist/components/PromptInput.js.map +2 -2
  45. package/dist/components/RewindPanel.js +272 -0
  46. package/dist/components/RewindPanel.js.map +7 -0
  47. package/dist/components/Spinner.js +10 -21
  48. package/dist/components/Spinner.js.map +2 -2
  49. package/dist/components/StreamingTextPreview.js +29 -0
  50. package/dist/components/StreamingTextPreview.js.map +7 -0
  51. package/dist/components/SubagentBlock.js +3 -2
  52. package/dist/components/SubagentBlock.js.map +2 -2
  53. package/dist/components/SubagentProgress.js +4 -4
  54. package/dist/components/SubagentProgress.js.map +2 -2
  55. package/dist/components/TabbedListView/SearchInput.js +1 -1
  56. package/dist/components/TabbedListView/SearchInput.js.map +2 -2
  57. package/dist/components/TabbedListView/TabbedListView.js +87 -41
  58. package/dist/components/TabbedListView/TabbedListView.js.map +2 -2
  59. package/dist/components/TaskCard.js +4 -4
  60. package/dist/components/TaskCard.js.map +2 -2
  61. package/dist/components/TeamMemberPanel.js +107 -0
  62. package/dist/components/TeamMemberPanel.js.map +7 -0
  63. package/dist/components/ThinkingSelector.js +84 -0
  64. package/dist/components/ThinkingSelector.js.map +7 -0
  65. package/dist/components/TitledDivider.js +26 -0
  66. package/dist/components/TitledDivider.js.map +7 -0
  67. package/dist/components/TodoPanel.js +31 -30
  68. package/dist/components/TodoPanel.js.map +2 -2
  69. package/dist/components/TokenWarning.js +28 -7
  70. package/dist/components/TokenWarning.js.map +2 -2
  71. package/dist/components/messages/AssistantTextMessage.js +5 -2
  72. package/dist/components/messages/AssistantTextMessage.js.map +2 -2
  73. package/dist/components/messages/AssistantToolUseMessage.js +9 -1
  74. package/dist/components/messages/AssistantToolUseMessage.js.map +2 -2
  75. package/dist/components/messages/DefaultToolResultFallback.js +11 -0
  76. package/dist/components/messages/DefaultToolResultFallback.js.map +7 -0
  77. package/dist/components/messages/ParallelTasksGroupView.js +14 -6
  78. package/dist/components/messages/ParallelTasksGroupView.js.map +2 -2
  79. package/dist/components/messages/TaskInModuleView.js +27 -27
  80. package/dist/components/messages/TaskInModuleView.js.map +2 -2
  81. package/dist/components/messages/UserGuidanceMessage.js +26 -0
  82. package/dist/components/messages/UserGuidanceMessage.js.map +7 -0
  83. package/dist/components/messages/UserPromptMessage.js +2 -1
  84. package/dist/components/messages/UserPromptMessage.js.map +2 -2
  85. package/dist/components/messages/UserTeamNotificationMessage.js +91 -0
  86. package/dist/components/messages/UserTeamNotificationMessage.js.map +7 -0
  87. package/dist/components/messages/UserTextMessage.js +8 -0
  88. package/dist/components/messages/UserTextMessage.js.map +2 -2
  89. package/dist/components/messages/UserToolResultMessage/UserToolRejectMessage.js +4 -2
  90. package/dist/components/messages/UserToolResultMessage/UserToolRejectMessage.js.map +2 -2
  91. package/dist/components/messages/UserToolResultMessage/UserToolResultMessage.js +18 -1
  92. package/dist/components/messages/UserToolResultMessage/UserToolResultMessage.js.map +2 -2
  93. package/dist/components/messages/UserToolResultMessage/UserToolSuccessMessage.js +12 -1
  94. package/dist/components/messages/UserToolResultMessage/UserToolSuccessMessage.js.map +2 -2
  95. package/dist/components/permissions/PermissionRequest.js +4 -0
  96. package/dist/components/permissions/PermissionRequest.js.map +2 -2
  97. package/dist/components/permissions/PlanApprovalRequest.js +164 -0
  98. package/dist/components/permissions/PlanApprovalRequest.js.map +7 -0
  99. package/dist/constants/agentTeams.js +17 -0
  100. package/dist/constants/agentTeams.js.map +7 -0
  101. package/dist/constants/macros.js +2 -1
  102. package/dist/constants/macros.js.map +2 -2
  103. package/dist/constants/prompts/agentPrompt.js +1 -0
  104. package/dist/constants/prompts/agentPrompt.js.map +2 -2
  105. package/dist/constants/prompts/autoMemory.js +39 -0
  106. package/dist/constants/prompts/autoMemory.js.map +7 -0
  107. package/dist/constants/prompts/codeConventions.js +1 -13
  108. package/dist/constants/prompts/codeConventions.js.map +2 -2
  109. package/dist/constants/prompts/doingTasks.js +21 -2
  110. package/dist/constants/prompts/doingTasks.js.map +2 -2
  111. package/dist/constants/prompts/envInfo.js +6 -7
  112. package/dist/constants/prompts/envInfo.js.map +2 -2
  113. package/dist/constants/prompts/index.js +27 -5
  114. package/dist/constants/prompts/index.js.map +2 -2
  115. package/dist/constants/prompts/taskManagement.js +2 -43
  116. package/dist/constants/prompts/taskManagement.js.map +2 -2
  117. package/dist/constants/prompts/teamOverlays.js +50 -0
  118. package/dist/constants/prompts/teamOverlays.js.map +7 -0
  119. package/dist/constants/prompts/toneAndStyle.js +4 -29
  120. package/dist/constants/prompts/toneAndStyle.js.map +2 -2
  121. package/dist/constants/prompts/toolUsagePolicy.js +7 -22
  122. package/dist/constants/prompts/toolUsagePolicy.js.map +2 -2
  123. package/dist/constants/toolInputExamples.js +2 -2
  124. package/dist/constants/toolInputExamples.js.map +2 -2
  125. package/dist/context.js +39 -6
  126. package/dist/context.js.map +2 -2
  127. package/dist/core/backupManager.js +1 -1
  128. package/dist/core/backupManager.js.map +2 -2
  129. package/dist/core/permissions/rules/planModeRule.js +1 -1
  130. package/dist/core/permissions/rules/planModeRule.js.map +1 -1
  131. package/dist/core/permissions/rules/safeModeRule.js +1 -1
  132. package/dist/core/permissions/rules/safeModeRule.js.map +1 -1
  133. package/dist/engine/AgentEngine.js +902 -0
  134. package/dist/engine/AgentEngine.js.map +7 -0
  135. package/dist/engine/EngineRegistry.js +89 -0
  136. package/dist/engine/EngineRegistry.js.map +7 -0
  137. package/dist/engine/foregroundAdapter.js +191 -0
  138. package/dist/engine/foregroundAdapter.js.map +7 -0
  139. package/dist/engine/index.js +15 -0
  140. package/dist/engine/index.js.map +7 -0
  141. package/dist/engine/types.js +1 -0
  142. package/dist/engine/types.js.map +7 -0
  143. package/dist/entrypoints/cli.js +410 -79
  144. package/dist/entrypoints/cli.js.map +3 -3
  145. package/dist/hooks/useAgentEngine.js +129 -0
  146. package/dist/hooks/useAgentEngine.js.map +7 -0
  147. package/dist/hooks/useAgentTokenStats.js +0 -16
  148. package/dist/hooks/useAgentTokenStats.js.map +2 -2
  149. package/dist/hooks/useCanUseTool.js +47 -2
  150. package/dist/hooks/useCanUseTool.js.map +2 -2
  151. package/dist/hooks/useDeferredLoading.js +4 -1
  152. package/dist/hooks/useDeferredLoading.js.map +2 -2
  153. package/dist/hooks/useIdleNotifications.js +66 -0
  154. package/dist/hooks/useIdleNotifications.js.map +7 -0
  155. package/dist/hooks/useSessionTracking.js +9 -7
  156. package/dist/hooks/useSessionTracking.js.map +2 -2
  157. package/dist/hooks/useTeamMembers.js +51 -0
  158. package/dist/hooks/useTeamMembers.js.map +7 -0
  159. package/dist/i18n/locales/en.js +77 -12
  160. package/dist/i18n/locales/en.js.map +2 -2
  161. package/dist/i18n/locales/zh-CN.js +77 -12
  162. package/dist/i18n/locales/zh-CN.js.map +2 -2
  163. package/dist/i18n/types.js.map +1 -1
  164. package/dist/messages.js.map +2 -2
  165. package/dist/permissions.js +113 -7
  166. package/dist/permissions.js.map +2 -2
  167. package/dist/query.js +135 -37
  168. package/dist/query.js.map +2 -2
  169. package/dist/screens/REPL.js +504 -361
  170. package/dist/screens/REPL.js.map +3 -3
  171. package/dist/screens/ResumeConversation.js +199 -14
  172. package/dist/screens/ResumeConversation.js.map +2 -2
  173. package/dist/services/adapters/base.js.map +1 -1
  174. package/dist/services/agentTeams/backends/headless.js +108 -0
  175. package/dist/services/agentTeams/backends/headless.js.map +7 -0
  176. package/dist/services/agentTeams/backends/inProcess.js +102 -0
  177. package/dist/services/agentTeams/backends/inProcess.js.map +7 -0
  178. package/dist/services/agentTeams/backends/resolver.js +18 -0
  179. package/dist/services/agentTeams/backends/resolver.js.map +7 -0
  180. package/dist/services/agentTeams/backends/tmux.js +168 -0
  181. package/dist/services/agentTeams/backends/tmux.js.map +7 -0
  182. package/dist/services/agentTeams/backends/types.js +1 -0
  183. package/dist/services/agentTeams/backends/types.js.map +7 -0
  184. package/dist/services/agentTeams/heartbeat.js +88 -0
  185. package/dist/services/agentTeams/heartbeat.js.map +7 -0
  186. package/dist/services/agentTeams/index.js +42 -2
  187. package/dist/services/agentTeams/index.js.map +2 -2
  188. package/dist/services/agentTeams/injectionChannel.js +105 -0
  189. package/dist/services/agentTeams/injectionChannel.js.map +7 -0
  190. package/dist/services/agentTeams/mailbox.js +410 -30
  191. package/dist/services/agentTeams/mailbox.js.map +2 -2
  192. package/dist/services/agentTeams/messageFormatter.js +80 -0
  193. package/dist/services/agentTeams/messageFormatter.js.map +7 -0
  194. package/dist/services/agentTeams/permissionDelegation.js +71 -0
  195. package/dist/services/agentTeams/permissionDelegation.js.map +7 -0
  196. package/dist/services/agentTeams/teamEvents.js +45 -0
  197. package/dist/services/agentTeams/teamEvents.js.map +7 -0
  198. package/dist/services/agentTeams/teamManager.js +251 -34
  199. package/dist/services/agentTeams/teamManager.js.map +2 -2
  200. package/dist/services/agentTeams/teamTaskStore.js +290 -61
  201. package/dist/services/agentTeams/teamTaskStore.js.map +2 -2
  202. package/dist/services/agentTeams/teammateSpawner.js +99 -18
  203. package/dist/services/agentTeams/teammateSpawner.js.map +2 -2
  204. package/dist/services/hookExecutor.js +51 -8
  205. package/dist/services/hookExecutor.js.map +2 -2
  206. package/dist/services/llm/anthropicProvider.js +56 -59
  207. package/dist/services/llm/anthropicProvider.js.map +2 -2
  208. package/dist/services/llm/dispatch.js +24 -5
  209. package/dist/services/llm/dispatch.js.map +2 -2
  210. package/dist/services/llm/openaiProvider.js +115 -136
  211. package/dist/services/llm/openaiProvider.js.map +3 -3
  212. package/dist/services/llm/types.js +89 -15
  213. package/dist/services/llm/types.js.map +2 -2
  214. package/dist/services/mcpClient.js +80 -4
  215. package/dist/services/mcpClient.js.map +2 -2
  216. package/dist/services/mintoAuth.js +299 -0
  217. package/dist/services/mintoAuth.js.map +7 -0
  218. package/dist/services/oauth.js +3 -3
  219. package/dist/services/oauth.js.map +2 -2
  220. package/dist/services/openai.js +91 -20
  221. package/dist/services/openai.js.map +2 -2
  222. package/dist/services/plugins/pluginRuntime.js +11 -5
  223. package/dist/services/plugins/pluginRuntime.js.map +2 -2
  224. package/dist/services/plugins/pluginValidation.js +4 -2
  225. package/dist/services/plugins/pluginValidation.js.map +2 -2
  226. package/dist/services/sandbox/sandboxController.js +11 -3
  227. package/dist/services/sandbox/sandboxController.js.map +2 -2
  228. package/dist/services/sessionMemoryInjector.js +77 -0
  229. package/dist/services/sessionMemoryInjector.js.map +7 -0
  230. package/dist/services/systemReminder.js +130 -8
  231. package/dist/services/systemReminder.js.map +2 -2
  232. package/dist/services/taskStore.js +199 -8
  233. package/dist/services/taskStore.js.map +3 -3
  234. package/dist/services/topicDetector.js +169 -0
  235. package/dist/services/topicDetector.js.map +7 -0
  236. package/dist/tools/AskExpertModelTool/AskExpertModelTool.js +0 -13
  237. package/dist/tools/AskExpertModelTool/AskExpertModelTool.js.map +2 -2
  238. package/dist/tools/BashTool/BashTool.js +51 -28
  239. package/dist/tools/BashTool/BashTool.js.map +2 -2
  240. package/dist/tools/BashTool/prompt.js +95 -118
  241. package/dist/tools/BashTool/prompt.js.map +2 -2
  242. package/dist/tools/BashTool/utils.js +39 -1
  243. package/dist/tools/BashTool/utils.js.map +2 -2
  244. package/dist/tools/EnterWorktreeTool/EnterWorktreeTool.js +121 -0
  245. package/dist/tools/EnterWorktreeTool/EnterWorktreeTool.js.map +7 -0
  246. package/dist/tools/EnterWorktreeTool/prompt.js +22 -0
  247. package/dist/tools/EnterWorktreeTool/prompt.js.map +7 -0
  248. package/dist/tools/FileEditTool/FileEditTool.js +9 -4
  249. package/dist/tools/FileEditTool/FileEditTool.js.map +2 -2
  250. package/dist/tools/FileEditTool/prompt.js +3 -7
  251. package/dist/tools/FileEditTool/prompt.js.map +2 -2
  252. package/dist/tools/FileReadTool/FileReadTool.js +125 -3
  253. package/dist/tools/FileReadTool/FileReadTool.js.map +2 -2
  254. package/dist/tools/FileReadTool/prompt.js +1 -2
  255. package/dist/tools/FileReadTool/prompt.js.map +2 -2
  256. package/dist/tools/FileWriteTool/prompt.js +3 -5
  257. package/dist/tools/FileWriteTool/prompt.js.map +2 -2
  258. package/dist/tools/GlobTool/GlobTool.js +3 -2
  259. package/dist/tools/GlobTool/GlobTool.js.map +2 -2
  260. package/dist/tools/GrepTool/GrepTool.js +16 -5
  261. package/dist/tools/GrepTool/GrepTool.js.map +2 -2
  262. package/dist/tools/ListMcpResourcesTool/ListMcpResourcesTool.js.map +2 -2
  263. package/dist/tools/MCPSearchTool/MCPSearchTool.js +172 -0
  264. package/dist/tools/MCPSearchTool/MCPSearchTool.js.map +7 -0
  265. package/dist/tools/MCPSearchTool/prompt.js +77 -0
  266. package/dist/tools/MCPSearchTool/prompt.js.map +7 -0
  267. package/dist/tools/MultiEditTool/prompt.js +4 -7
  268. package/dist/tools/MultiEditTool/prompt.js.map +2 -2
  269. package/dist/tools/PlanModeTool/EnterPlanModeTool.js +12 -8
  270. package/dist/tools/PlanModeTool/EnterPlanModeTool.js.map +2 -2
  271. package/dist/tools/PlanModeTool/ExitPlanModeTool.js +54 -1
  272. package/dist/tools/PlanModeTool/ExitPlanModeTool.js.map +2 -2
  273. package/dist/tools/PlanModeTool/prompt.js +23 -74
  274. package/dist/tools/PlanModeTool/prompt.js.map +2 -2
  275. package/dist/tools/SendMessageTool/SendMessageTool.js +341 -0
  276. package/dist/tools/SendMessageTool/SendMessageTool.js.map +7 -0
  277. package/dist/tools/SendMessageTool/prompt.js +44 -0
  278. package/dist/tools/SendMessageTool/prompt.js.map +7 -0
  279. package/dist/tools/TaskCreateTool/prompt.js +15 -4
  280. package/dist/tools/TaskCreateTool/prompt.js.map +2 -2
  281. package/dist/tools/TaskListTool/prompt.js +18 -3
  282. package/dist/tools/TaskListTool/prompt.js.map +2 -2
  283. package/dist/tools/TaskOutputTool/prompt.js +4 -3
  284. package/dist/tools/TaskOutputTool/prompt.js.map +2 -2
  285. package/dist/tools/TaskTool/TaskTool.js +762 -98
  286. package/dist/tools/TaskTool/TaskTool.js.map +3 -3
  287. package/dist/tools/TaskTool/constants.js +8 -2
  288. package/dist/tools/TaskTool/constants.js.map +2 -2
  289. package/dist/tools/TaskTool/prompt.js +74 -70
  290. package/dist/tools/TaskTool/prompt.js.map +2 -2
  291. package/dist/tools/TaskUpdateTool/TaskUpdateTool.js +15 -1
  292. package/dist/tools/TaskUpdateTool/TaskUpdateTool.js.map +2 -2
  293. package/dist/tools/TeamCreateTool/TeamCreateTool.js +129 -0
  294. package/dist/tools/TeamCreateTool/TeamCreateTool.js.map +7 -0
  295. package/dist/tools/TeamCreateTool/prompt.js +58 -0
  296. package/dist/tools/TeamCreateTool/prompt.js.map +7 -0
  297. package/dist/tools/TeamDeleteTool/TeamDeleteTool.js +151 -0
  298. package/dist/tools/TeamDeleteTool/TeamDeleteTool.js.map +7 -0
  299. package/dist/tools/TeamDeleteTool/prompt.js +16 -0
  300. package/dist/tools/TeamDeleteTool/prompt.js.map +7 -0
  301. package/dist/tools/URLFetcherTool/URLFetcherTool.js +106 -15
  302. package/dist/tools/URLFetcherTool/URLFetcherTool.js.map +2 -2
  303. package/dist/tools/URLFetcherTool/prompt.js +3 -2
  304. package/dist/tools/URLFetcherTool/prompt.js.map +2 -2
  305. package/dist/tools/WebSearchTool/WebSearchTool.js +2 -1
  306. package/dist/tools/WebSearchTool/WebSearchTool.js.map +2 -2
  307. package/dist/tools/WebSearchTool/prompt.js +5 -4
  308. package/dist/tools/WebSearchTool/prompt.js.map +2 -2
  309. package/dist/tools.js +100 -20
  310. package/dist/tools.js.map +2 -2
  311. package/dist/types/PermissionMode.js +35 -6
  312. package/dist/types/PermissionMode.js.map +2 -2
  313. package/dist/types/hooks.js +2 -0
  314. package/dist/types/hooks.js.map +2 -2
  315. package/dist/types/plugin.js +2 -0
  316. package/dist/types/plugin.js.map +3 -3
  317. package/dist/utils/CircuitBreaker.js +15 -9
  318. package/dist/utils/CircuitBreaker.js.map +2 -2
  319. package/dist/utils/agentLoader.js +249 -112
  320. package/dist/utils/agentLoader.js.map +2 -2
  321. package/dist/utils/animationManager.js +40 -3
  322. package/dist/utils/animationManager.js.map +2 -2
  323. package/dist/utils/ask.js +7 -6
  324. package/dist/utils/ask.js.map +2 -2
  325. package/dist/utils/atomicWrite.js +23 -0
  326. package/dist/utils/atomicWrite.js.map +7 -0
  327. package/dist/utils/autoCompactCore.js +73 -56
  328. package/dist/utils/autoCompactCore.js.map +2 -2
  329. package/dist/utils/autoMemoryPaths.js +89 -0
  330. package/dist/utils/autoMemoryPaths.js.map +7 -0
  331. package/dist/utils/config.js +63 -38
  332. package/dist/utils/config.js.map +2 -2
  333. package/dist/utils/configSchema.js +13 -8
  334. package/dist/utils/configSchema.js.map +2 -2
  335. package/dist/utils/credentials/index.js +14 -0
  336. package/dist/utils/credentials/index.js.map +2 -2
  337. package/dist/utils/dualPath.js +24 -0
  338. package/dist/utils/dualPath.js.map +7 -0
  339. package/dist/utils/exit.js +66 -7
  340. package/dist/utils/exit.js.map +2 -2
  341. package/dist/utils/externalEditor.js +155 -0
  342. package/dist/utils/externalEditor.js.map +7 -0
  343. package/dist/utils/fileLock.js +67 -0
  344. package/dist/utils/fileLock.js.map +7 -0
  345. package/dist/utils/format.js +24 -14
  346. package/dist/utils/format.js.map +2 -2
  347. package/dist/utils/globalErrorHandler.js +5 -96
  348. package/dist/utils/globalErrorHandler.js.map +3 -3
  349. package/dist/utils/groupHandlers/parallelTasksHandler.js +5 -3
  350. package/dist/utils/groupHandlers/parallelTasksHandler.js.map +2 -2
  351. package/dist/utils/groupHandlers/taskHandler.js +2 -2
  352. package/dist/utils/groupHandlers/taskHandler.js.map +2 -2
  353. package/dist/utils/hookManager.js +64 -6
  354. package/dist/utils/hookManager.js.map +2 -2
  355. package/dist/utils/log.js +6 -2
  356. package/dist/utils/log.js.map +2 -2
  357. package/dist/utils/markdown.js +237 -19
  358. package/dist/utils/markdown.js.map +2 -2
  359. package/dist/utils/messageContextManager.js +18 -5
  360. package/dist/utils/messageContextManager.js.map +2 -2
  361. package/dist/utils/messageGroupManager.js +1 -1
  362. package/dist/utils/messageGroupManager.js.map +2 -2
  363. package/dist/utils/messages.js +104 -46
  364. package/dist/utils/messages.js.map +2 -2
  365. package/dist/utils/model.js +2 -2
  366. package/dist/utils/model.js.map +2 -2
  367. package/dist/utils/pasteCache.js +8 -4
  368. package/dist/utils/pasteCache.js.map +2 -2
  369. package/dist/utils/pluginLoader.js +18 -0
  370. package/dist/utils/pluginLoader.js.map +2 -2
  371. package/dist/utils/secureKeyStorage.js +36 -7
  372. package/dist/utils/secureKeyStorage.js.map +2 -2
  373. package/dist/utils/simpleMode.js +7 -0
  374. package/dist/utils/simpleMode.js.map +7 -0
  375. package/dist/utils/streamingState.js +11 -1
  376. package/dist/utils/streamingState.js.map +2 -2
  377. package/dist/utils/taskDisplayUtils.js +2 -1
  378. package/dist/utils/taskDisplayUtils.js.map +2 -2
  379. package/dist/utils/teamConfig.js +2 -2
  380. package/dist/utils/teamConfig.js.map +2 -2
  381. package/dist/utils/thinking.js +6 -2
  382. package/dist/utils/thinking.js.map +3 -3
  383. package/dist/utils/tokenProgress.js +55 -0
  384. package/dist/utils/tokenProgress.js.map +7 -0
  385. package/dist/utils/toolRiskClassification.js +26 -17
  386. package/dist/utils/toolRiskClassification.js.map +2 -2
  387. package/dist/utils/tooling/toolError.js +12 -0
  388. package/dist/utils/tooling/toolError.js.map +7 -0
  389. package/dist/version.js +2 -2
  390. package/dist/version.js.map +1 -1
  391. package/package.json +10 -8
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/utils/config.ts"],
4
- "sourcesContent": ["import { existsSync, readFileSync, writeFileSync, renameSync, rmSync } from 'fs'\nimport { resolve, join, dirname } from 'path'\nimport { cloneDeep, memoize, pick } from 'lodash-es'\nimport { homedir } from 'os'\nimport { GLOBAL_CONFIG_FILE } from './env'\nimport { getCwd } from './state'\nimport { randomBytes } from 'crypto'\nimport { safeParseJSON } from './json'\nimport { ConfigParseError } from './errors'\nimport type { ThemeNames } from './theme'\nimport { debug as debugLogger } from './debugLogger'\nimport { safeValidateGlobalConfig } from './configSchema'\n\n// Re-export canonical types derived from Zod schemas (single source of truth)\nexport type {\n McpStdioServerConfig,\n McpSSEServerConfig,\n McpHTTPServerConfig,\n McpServerConfig,\n AutoUpdaterStatus,\n NotificationChannel,\n ProviderType,\n UILanguage,\n SafetyMode,\n ReasoningEffort,\n ModelProfile,\n ModelPointerType,\n ModelPointers,\n AccountInfo,\n SandboxConfigData,\n CompressionMode,\n} from './configSchema'\n\n// Import types locally for use in this file\nimport type {\n McpServerConfig,\n AutoUpdaterStatus,\n NotificationChannel,\n ProviderType,\n UILanguage,\n SafetyMode,\n ModelProfile,\n ModelPointerType,\n ModelPointers,\n AccountInfo,\n SandboxConfigData,\n CompressionMode,\n} from './configSchema'\nimport { getSessionState, setSessionState } from './sessionState'\n// CompressionMode now re-exported from configSchema.ts\n\n// Types McpStdioServerConfig, McpSSEServerConfig, McpHTTPServerConfig,\n// McpServerConfig, SandboxConfigData are now derived from Zod schemas\n// and re-exported from configSchema.ts above.\n\n// ProjectConfig uses Zod-derived sub-types but keeps manual definition\n// due to .passthrough() in Zod schema generating incompatible index signatures.\nexport type ProjectConfig = {\n allowedTools: string[]\n context: Record<string, string>\n contextFiles?: string[]\n history: string[]\n dontCrawlDirectory?: boolean\n enableArchitectTool?: boolean\n mcpContextUris: string[]\n mcpServers?: Record<string, McpServerConfig>\n approvedMcprcServers?: string[]\n rejectedMcprcServers?: string[]\n lastAPIDuration?: number\n lastCost?: number\n lastDuration?: number\n lastSessionId?: string\n exampleFiles?: string[]\n exampleFilesGeneratedAt?: number\n hasTrustDialogAccepted?: boolean\n hasCompletedProjectOnboarding?: boolean\n sandbox?: SandboxConfigData\n [key: string]: unknown\n}\n\nconst DEFAULT_PROJECT_CONFIG: ProjectConfig = {\n allowedTools: [],\n context: {},\n history: [],\n dontCrawlDirectory: false,\n enableArchitectTool: false,\n mcpContextUris: [],\n mcpServers: {},\n approvedMcprcServers: [],\n rejectedMcprcServers: [],\n hasTrustDialogAccepted: false,\n}\n\nfunction defaultConfigForProject(projectPath: string): ProjectConfig {\n const config = { ...DEFAULT_PROJECT_CONFIG }\n if (projectPath === homedir()) {\n config.dontCrawlDirectory = true\n }\n return config\n}\n\n// AutoUpdaterStatus now derived from Zod schema in configSchema.ts\n\nexport function isAutoUpdaterStatus(value: string): value is AutoUpdaterStatus {\n return ['disabled', 'enabled', 'no_permissions', 'not_configured'].includes(\n value as AutoUpdaterStatus,\n )\n}\n\n// NotificationChannel now derived from Zod schema in configSchema.ts\n\n/**\n * @deprecated Use verbose boolean instead. Kept for backward compatibility migration.\n */\nexport type DisplayMode = 'minimal' | 'compact' | 'detailed'\n\n// UILanguage now derived from Zod schema in configSchema.ts\n\n// SafetyMode now derived from Zod schema in configSchema.ts\n\n/**\n * Get verbose mode label (uses i18n)\n * Import dynamically to avoid circular dependency\n */\nexport function getVerboseLabel(verbose: boolean): string {\n // Dynamic import to avoid circular dependency at module load time\n try {\n const { t } = require('../i18n')\n return verbose ? t('ui.verbose.on') : t('ui.verbose.off')\n } catch {\n // Fallback if i18n not loaded yet\n return verbose ? 'Verbose: On' : 'Verbose: Off'\n }\n}\n\n// ProviderType now derived from Zod schema in configSchema.ts\n\n// ModelProfile now derived from Zod schema in configSchema.ts\n\n// Legacy type for config migration - includes deprecated 'id' field\ntype LegacyModelProfile = ModelProfile & {\n id?: string\n}\n\n// Legacy global config fields for migration\ntype LegacyGlobalConfigFields = {\n defaultModelId?: string\n defaultModelName?: string\n currentSelectedModelId?: string\n mainAgentModelId?: string\n taskToolModelId?: string\n}\n\n// ModelPointerType, ModelPointers, AccountInfo now derived from Zod schema in configSchema.ts\n\nexport type GlobalConfig = {\n projects?: Record<string, ProjectConfig>\n numStartups: number\n autoUpdaterStatus?: AutoUpdaterStatus\n userID?: string\n theme: ThemeNames\n hasCompletedOnboarding?: boolean\n // Tracks the last version that reset onboarding, used with MIN_VERSION_REQUIRING_ONBOARDING_RESET\n lastOnboardingVersion?: string\n // Tracks the last version for which release notes were seen, used for managing release notes\n lastReleaseNotesSeen?: string\n mcpServers?: Record<string, McpServerConfig>\n preferredNotifChannel: NotificationChannel\n /**\n * Verbose mode: shows full parameters and complete outputs when enabled\n * - false: Concise output (default)\n * - true: Detailed/verbose output\n */\n verbose: boolean\n /**\n * @deprecated Use verbose boolean instead. Kept for backward compatibility migration.\n */\n displayMode?: DisplayMode\n customApiKeyResponses?: {\n approved?: string[]\n rejected?: string[]\n }\n primaryProvider?: ProviderType\n maxTokens?: number\n hasAcknowledgedCostThreshold?: boolean\n oauthAccount?: AccountInfo\n iterm2KeyBindingInstalled?: boolean // Legacy - keeping for backward compatibility\n shiftEnterKeyBindingInstalled?: boolean\n proxy?: string\n stream?: boolean\n\n // New model system\n modelProfiles?: ModelProfile[] // Model configuration list\n modelPointers?: ModelPointers // Model pointer system\n defaultModelName?: string // Default model\n // Update notifications\n lastDismissedUpdateVersion?: string\n // Compression mode\n compressionMode?: CompressionMode // Compression algorithm mode ('business' or 'code')\n // Thinking mode (Phase 4.2)\n thinking?: boolean // Whether thinking/extended reasoning mode is enabled\n // UI Language\n language?: UILanguage // UI language ('en' or 'zh-CN')\n /**\n * @deprecated Use safetyMode instead. Kept for backward compatibility.\n * Safe mode: when enabled, requires user confirmation for all tool executions\n */\n safeMode?: boolean\n /**\n * Safety mode for tool execution (4-tier system):\n * - 'yolo': All tools allowed without confirmation (default for non-technical users)\n * - 'smart': Safe/monitored tools auto-allowed, dangerous tools need confirmation\n * - 'strict': Only safe tools auto-allowed, all others need confirmation\n * - 'free': Project directory operations auto-allowed, outside requires confirmation\n */\n safetyMode?: SafetyMode\n // Claude Code plugin auto-sync\n autoSyncClaudeCode?: boolean\n // Enable experimental memory tools (read/write persistent agent memory)\n enableMemoryTools?: boolean\n // Output style selection (CC compat)\n outputStyle?: string\n // Auto-memory: extract key decisions during auto-compact\n autoMemory?: boolean\n // File backup for /undo\n backupEnabled?: boolean\n}\n\nexport const DEFAULT_GLOBAL_CONFIG: GlobalConfig = {\n numStartups: 0,\n autoUpdaterStatus: 'not_configured',\n theme: 'dark',\n preferredNotifChannel: 'iterm2',\n verbose: false,\n primaryProvider: 'anthropic',\n customApiKeyResponses: {\n approved: [],\n rejected: [],\n },\n stream: true,\n\n // New model system defaults\n modelProfiles: [],\n modelPointers: {\n main: '',\n task: '',\n reasoning: '',\n quick: '',\n compact: '',\n },\n lastDismissedUpdateVersion: undefined,\n compressionMode: 'business', // Default to business consulting compression\n thinking: false, // Default to thinking mode off (Phase 4.2)\n language: 'en', // Default to English\n safeMode: false, // Deprecated: use safetyMode instead\n safetyMode: 'smart', // Default to smart mode \u2014 safe tools auto-allowed, dangerous tools need confirmation\n}\n\nexport const GLOBAL_CONFIG_KEYS = [\n 'autoUpdaterStatus',\n 'theme',\n 'hasCompletedOnboarding',\n 'lastOnboardingVersion',\n 'lastReleaseNotesSeen',\n 'verbose',\n 'customApiKeyResponses',\n 'primaryProvider',\n 'preferredNotifChannel',\n 'shiftEnterKeyBindingInstalled',\n 'maxTokens',\n 'compressionMode',\n 'language',\n 'safetyMode',\n 'enableMemoryTools',\n 'outputStyle',\n 'autoMemory',\n] as const\n\nexport type GlobalConfigKey = (typeof GLOBAL_CONFIG_KEYS)[number]\n\nexport function isGlobalConfigKey(key: string): key is GlobalConfigKey {\n return GLOBAL_CONFIG_KEYS.includes(key as GlobalConfigKey)\n}\n\nexport const PROJECT_CONFIG_KEYS = [\n 'dontCrawlDirectory',\n 'enableArchitectTool',\n 'hasTrustDialogAccepted',\n 'hasCompletedProjectOnboarding',\n] as const\n\nexport type ProjectConfigKey = (typeof PROJECT_CONFIG_KEYS)[number]\n\nexport function checkHasTrustDialogAccepted(): boolean {\n let currentPath = getCwd()\n const config = getConfig(GLOBAL_CONFIG_FILE, DEFAULT_GLOBAL_CONFIG)\n\n while (true) {\n const projectConfig = config.projects?.[currentPath]\n if (projectConfig?.hasTrustDialogAccepted) {\n return true\n }\n const parentPath = resolve(currentPath, '..')\n // Stop if we've reached the root (when parent is same as current)\n if (parentPath === currentPath) {\n break\n }\n currentPath = parentPath\n }\n\n return false\n}\n\n// We have to put this test code here because Jest doesn't support mocking ES modules :O\nconst TEST_GLOBAL_CONFIG_FOR_TESTING: GlobalConfig = {\n ...DEFAULT_GLOBAL_CONFIG,\n autoUpdaterStatus: 'disabled',\n}\nconst TEST_PROJECT_CONFIG_FOR_TESTING: ProjectConfig = {\n ...DEFAULT_PROJECT_CONFIG,\n}\n\nexport function isProjectConfigKey(key: string): key is ProjectConfigKey {\n return PROJECT_CONFIG_KEYS.includes(key as ProjectConfigKey)\n}\n\nexport function saveGlobalConfig(config: GlobalConfig): void {\n if (process.env.NODE_ENV === 'test') {\n for (const key in config) {\n ;(TEST_GLOBAL_CONFIG_FOR_TESTING as Record<string, unknown>)[key] = (\n config as Record<string, unknown>\n )[key]\n }\n return\n }\n\n // \u76F4\u63A5\u4FDD\u5B58\u914D\u7F6E\uFF08\u65E0\u9700\u6E05\u9664\u7F13\u5B58\uFF0C\u56E0\u4E3A\u5DF2\u79FB\u9664\u7F13\u5B58\uFF09\n saveConfig(\n GLOBAL_CONFIG_FILE,\n {\n ...config,\n projects: getConfig(GLOBAL_CONFIG_FILE, DEFAULT_GLOBAL_CONFIG).projects,\n },\n DEFAULT_GLOBAL_CONFIG,\n )\n}\n\n/**\n * Migrate legacy displayMode to verbose boolean\n */\nfunction migrateDisplayModeToVerbose(config: GlobalConfig): GlobalConfig {\n // If verbose is already set, no migration needed\n if (config.verbose !== undefined) {\n return config\n }\n\n // Check for legacy displayMode field\n const legacyConfig = config as GlobalConfig & { displayMode?: DisplayMode }\n if (legacyConfig.displayMode !== undefined) {\n const migratedConfig: GlobalConfig = {\n ...config,\n verbose: legacyConfig.displayMode === 'detailed',\n }\n // Remove legacy field\n delete (migratedConfig as Record<string, unknown>).displayMode\n return migratedConfig\n }\n\n // Default to false if no verbose or displayMode\n return {\n ...config,\n verbose: false,\n }\n}\n\n// \u4E34\u65F6\u79FB\u9664\u7F13\u5B58\uFF0C\u786E\u4FDD\u603B\u662F\u83B7\u53D6\u6700\u65B0\u914D\u7F6E\nexport function getGlobalConfig(): GlobalConfig {\n if (process.env.NODE_ENV === 'test') {\n return TEST_GLOBAL_CONFIG_FOR_TESTING\n }\n const config = getConfig(GLOBAL_CONFIG_FILE, DEFAULT_GLOBAL_CONFIG)\n const migratedConfig = migrateModelProfilesRemoveId(config)\n const displayMigratedConfig = migrateDisplayModeToVerbose(migratedConfig)\n\n // Apply model profile deduplication\n if (\n displayMigratedConfig.modelProfiles &&\n displayMigratedConfig.modelProfiles.length > 0\n ) {\n const originalCount = displayMigratedConfig.modelProfiles.length\n const deduplicatedProfiles = deduplicateModelProfiles(\n displayMigratedConfig.modelProfiles,\n )\n const deduplicatedCount = deduplicatedProfiles.length\n\n // If duplicates were found and removed, auto-save the deduplicated config\n if (deduplicatedCount < originalCount) {\n debugLogger.state('CONFIG_DEDUPLICATE_PROFILES', {\n originalCount: String(originalCount),\n deduplicatedCount: String(deduplicatedCount),\n removedCount: String(originalCount - deduplicatedCount),\n })\n const configToSave = {\n ...displayMigratedConfig,\n modelProfiles: deduplicatedProfiles,\n }\n // Save the deduplicated config (avoid recursion by using saveConfig directly)\n saveConfig(\n GLOBAL_CONFIG_FILE,\n {\n ...configToSave,\n projects: config.projects,\n },\n DEFAULT_GLOBAL_CONFIG,\n )\n return configToSave\n }\n\n return {\n ...displayMigratedConfig,\n modelProfiles: deduplicatedProfiles,\n }\n }\n\n return displayMigratedConfig\n}\n\nexport function getAnthropicApiKey(): null | string {\n return process.env.ANTHROPIC_API_KEY || null\n}\n\nexport function normalizeApiKeyForConfig(apiKey: string): string {\n return apiKey?.slice(-20) ?? ''\n}\n\nexport function getCustomApiKeyStatus(\n truncatedApiKey: string,\n): 'approved' | 'rejected' | 'new' {\n const config = getGlobalConfig()\n if (config.customApiKeyResponses?.approved?.includes(truncatedApiKey)) {\n return 'approved'\n }\n if (config.customApiKeyResponses?.rejected?.includes(truncatedApiKey)) {\n return 'rejected'\n }\n return 'new'\n}\n\n/**\n * Atomically write content to a file using temp file + rename pattern.\n * This prevents data corruption if writes are interrupted or multiple processes\n * attempt to write concurrently.\n *\n * @param filePath - The target file path to write to\n * @param content - The content to write\n * @throws {Error} If write or rename operation fails\n */\nfunction atomicWriteFileSync(filePath: string, content: string): void {\n const dir = dirname(filePath)\n const tempPath = join(\n dir,\n `.${Date.now()}-${Math.random().toString(36).slice(2)}.tmp`,\n )\n\n try {\n // Write to temporary file\n writeFileSync(tempPath, content, 'utf-8')\n // Atomically rename temp to target (atomic on most filesystems)\n renameSync(tempPath, filePath)\n } catch (error) {\n // Clean up temporary file on failure\n try {\n rmSync(tempPath, { force: true })\n } catch {\n // Ignore cleanup errors\n }\n throw error\n }\n}\n\nfunction saveConfig<A extends object>(\n file: string,\n config: A,\n defaultConfig: A,\n): void {\n // Filter out any values that match the defaults\n const filteredConfig = Object.fromEntries(\n Object.entries(config).filter(\n ([key, value]) =>\n JSON.stringify(value) !== JSON.stringify(defaultConfig[key as keyof A]),\n ),\n )\n try {\n atomicWriteFileSync(file, JSON.stringify(filteredConfig, null, 2))\n } catch (error) {\n const err = error as NodeJS.ErrnoException\n if (\n err?.code === 'EACCES' ||\n err?.code === 'EPERM' ||\n err?.code === 'EROFS'\n ) {\n debugLogger.state('CONFIG_SAVE_SKIPPED', {\n file,\n reason: String(err.code),\n })\n return\n }\n throw error\n }\n}\n\n// Flag to track if config reading is allowed\nlet configReadingAllowed = false\n\nexport function enableConfigs(): void {\n // Any reads to configuration before this flag is set show an console warning\n // to prevent us from adding config reading during module initialization\n configReadingAllowed = true\n // We only check the global config because currently all the configs share a file\n getConfig(\n GLOBAL_CONFIG_FILE,\n DEFAULT_GLOBAL_CONFIG,\n true /* throw on invalid */,\n )\n}\n\nfunction getConfig<A>(\n file: string,\n defaultConfig: A,\n throwOnInvalid?: boolean,\n): A {\n // \u7B80\u5316\u914D\u7F6E\u8BBF\u95EE\u903B\u8F91\uFF0C\u79FB\u9664\u590D\u6742\u7684\u65F6\u5E8F\u68C0\u67E5\n\n debugLogger.state('CONFIG_LOAD_START', {\n file,\n fileExists: String(existsSync(file)),\n throwOnInvalid: String(!!throwOnInvalid),\n })\n\n if (!existsSync(file)) {\n debugLogger.state('CONFIG_LOAD_DEFAULT', {\n file,\n reason: 'file_not_exists',\n defaultConfigKeys: Object.keys(defaultConfig as object).join(', '),\n })\n return cloneDeep(defaultConfig)\n }\n\n try {\n const fileContent = readFileSync(file, 'utf-8')\n debugLogger.state('CONFIG_FILE_READ', {\n file,\n contentLength: String(fileContent.length),\n contentPreview:\n fileContent.substring(0, 100) + (fileContent.length > 100 ? '...' : ''),\n })\n\n try {\n const parsedConfig = JSON.parse(fileContent)\n debugLogger.state('CONFIG_JSON_PARSED', {\n file,\n parsedKeys: Object.keys(parsedConfig).join(', '),\n })\n\n // Zod validation \u2014 monitor mode (log only, never reject)\n if (file === GLOBAL_CONFIG_FILE) {\n const validation = safeValidateGlobalConfig(parsedConfig)\n if (!validation.success && validation.errors) {\n debugLogger.warn('CONFIG_VALIDATION', {\n file,\n issues: validation.errors.issues\n .map(i => `${i.path.join('.')}: ${i.message}`)\n .join('; '),\n })\n }\n }\n\n // Handle backward compatibility - remove logic for deleted fields\n const finalConfig = {\n ...cloneDeep(defaultConfig),\n ...parsedConfig,\n }\n\n debugLogger.state('CONFIG_LOAD_SUCCESS', {\n file,\n finalConfigKeys: Object.keys(finalConfig as object).join(', '),\n })\n\n return finalConfig\n } catch (error) {\n // Throw a ConfigParseError with the file path and default config\n const errorMessage =\n error instanceof Error ? error.message : String(error)\n\n debugLogger.error('CONFIG_JSON_PARSE_ERROR', {\n file,\n errorMessage,\n errorType:\n error instanceof Error ? error.constructor.name : typeof error,\n contentLength: String(fileContent.length),\n })\n\n throw new ConfigParseError(errorMessage, file, defaultConfig)\n }\n } catch (error: unknown) {\n // Re-throw ConfigParseError if throwOnInvalid is true\n if (error instanceof ConfigParseError && throwOnInvalid) {\n debugLogger.error('CONFIG_PARSE_ERROR_RETHROWN', {\n file,\n throwOnInvalid: String(throwOnInvalid),\n errorMessage: error.message,\n })\n throw error\n }\n\n debugLogger.warn('CONFIG_FALLBACK_TO_DEFAULT', {\n file,\n errorType: error instanceof Error ? error.constructor.name : typeof error,\n errorMessage: error instanceof Error ? error.message : String(error),\n action: 'using_default_config',\n })\n\n return cloneDeep(defaultConfig)\n }\n}\n\nexport function getCurrentProjectConfig(): ProjectConfig {\n if (process.env.NODE_ENV === 'test') {\n return TEST_PROJECT_CONFIG_FOR_TESTING\n }\n\n const absolutePath = resolve(getCwd())\n const config = getConfig(GLOBAL_CONFIG_FILE, DEFAULT_GLOBAL_CONFIG)\n\n if (!config.projects) {\n return defaultConfigForProject(absolutePath)\n }\n\n const projectConfig =\n config.projects[absolutePath] ?? defaultConfigForProject(absolutePath)\n // Guard: allowedTools may be serialized as a JSON string in some config paths\n if (typeof projectConfig.allowedTools === 'string') {\n projectConfig.allowedTools =\n (safeParseJSON(projectConfig.allowedTools) as string[]) ?? []\n }\n return projectConfig\n}\n\nexport function saveCurrentProjectConfig(projectConfig: ProjectConfig): void {\n if (process.env.NODE_ENV === 'test') {\n for (const key in projectConfig) {\n TEST_PROJECT_CONFIG_FOR_TESTING[key] = projectConfig[key]\n }\n return\n }\n const config = getConfig(GLOBAL_CONFIG_FILE, DEFAULT_GLOBAL_CONFIG)\n saveConfig(\n GLOBAL_CONFIG_FILE,\n {\n ...config,\n projects: {\n ...config.projects,\n [resolve(getCwd())]: projectConfig,\n },\n },\n DEFAULT_GLOBAL_CONFIG,\n )\n}\n\nexport async function isAutoUpdaterDisabled(): Promise<boolean> {\n return getGlobalConfig().autoUpdaterStatus === 'disabled'\n}\n\nexport const TEST_MCPRC_CONFIG_FOR_TESTING: Record<string, McpServerConfig> = {}\n\nexport function clearMcprcConfigForTesting(): void {\n if (process.env.NODE_ENV === 'test') {\n Object.keys(TEST_MCPRC_CONFIG_FOR_TESTING).forEach(key => {\n delete TEST_MCPRC_CONFIG_FOR_TESTING[key]\n })\n }\n}\n\nexport function addMcprcServerForTesting(\n name: string,\n server: McpServerConfig,\n): void {\n if (process.env.NODE_ENV === 'test') {\n TEST_MCPRC_CONFIG_FOR_TESTING[name] = server\n }\n}\n\nexport function removeMcprcServerForTesting(name: string): void {\n if (process.env.NODE_ENV === 'test') {\n if (!TEST_MCPRC_CONFIG_FOR_TESTING[name]) {\n throw new Error(`No MCP server found with name: ${name} in .mcprc`)\n }\n delete TEST_MCPRC_CONFIG_FOR_TESTING[name]\n }\n}\n\nexport const getMcprcConfig = memoize(\n (): Record<string, McpServerConfig> => {\n if (process.env.NODE_ENV === 'test') {\n return TEST_MCPRC_CONFIG_FOR_TESTING\n }\n\n const mcprcPath = join(getCwd(), '.mcprc')\n if (!existsSync(mcprcPath)) {\n return {}\n }\n\n try {\n const mcprcContent = readFileSync(mcprcPath, 'utf-8')\n const config = safeParseJSON(mcprcContent)\n if (config && typeof config === 'object') {\n // Logging removed\n return config as Record<string, McpServerConfig>\n }\n } catch {\n // Ignore errors reading/parsing .mcprc (they're logged in safeParseJSON)\n }\n return {}\n },\n // This function returns the same value as long as the cwd and mcprc file content remain the same\n () => {\n const cwd = getCwd()\n const mcprcPath = join(cwd, '.mcprc')\n if (existsSync(mcprcPath)) {\n try {\n const stat = readFileSync(mcprcPath, 'utf-8')\n return `${cwd}:${stat}`\n } catch {\n return cwd\n }\n }\n return cwd\n },\n)\n\nexport function getOrCreateUserID(): string {\n const config = getGlobalConfig()\n if (config.userID) {\n return config.userID\n }\n\n const userID = randomBytes(32).toString('hex')\n saveGlobalConfig({ ...config, userID })\n return userID\n}\n\nexport function getConfigForCLI(key: string, global: boolean): unknown {\n if (global) {\n if (!isGlobalConfigKey(key)) {\n console.error(\n `Error: '${key}' is not a valid config key. Valid keys are: ${GLOBAL_CONFIG_KEYS.join(', ')}`,\n )\n process.exit(1)\n }\n return getGlobalConfig()[key]\n } else {\n if (!isProjectConfigKey(key)) {\n console.error(\n `Error: '${key}' is not a valid config key. Valid keys are: ${PROJECT_CONFIG_KEYS.join(', ')}`,\n )\n process.exit(1)\n }\n return getCurrentProjectConfig()[key]\n }\n}\n\nexport function setConfigForCLI(\n key: string,\n value: unknown,\n global: boolean,\n): void {\n if (global) {\n if (!isGlobalConfigKey(key)) {\n console.error(\n `Error: Cannot set '${key}'. Only these keys can be modified: ${GLOBAL_CONFIG_KEYS.join(', ')}`,\n )\n process.exit(1)\n }\n\n if (key === 'autoUpdaterStatus' && !isAutoUpdaterStatus(value as string)) {\n console.error(\n `Error: Invalid value for autoUpdaterStatus. Must be one of: disabled, enabled, no_permissions, not_configured`,\n )\n process.exit(1)\n }\n\n const currentConfig = getGlobalConfig()\n saveGlobalConfig({\n ...currentConfig,\n [key]: value,\n })\n } else {\n if (!isProjectConfigKey(key)) {\n console.error(\n `Error: Cannot set '${key}'. Only these keys can be modified: ${PROJECT_CONFIG_KEYS.join(', ')}. Did you mean --global?`,\n )\n process.exit(1)\n }\n const currentConfig = getCurrentProjectConfig()\n saveCurrentProjectConfig({\n ...currentConfig,\n [key]: value,\n })\n }\n // Wait for the output to be flushed, to avoid clearing the screen.\n setTimeout(() => {\n // Without this we hang indefinitely.\n process.exit(0)\n }, 100)\n}\n\nexport function deleteConfigForCLI(key: string, global: boolean): void {\n if (global) {\n if (!isGlobalConfigKey(key)) {\n console.error(\n `Error: Cannot delete '${key}'. Only these keys can be modified: ${GLOBAL_CONFIG_KEYS.join(', ')}`,\n )\n process.exit(1)\n }\n const currentConfig = getGlobalConfig()\n delete currentConfig[key]\n saveGlobalConfig(currentConfig)\n } else {\n if (!isProjectConfigKey(key)) {\n console.error(\n `Error: Cannot delete '${key}'. Only these keys can be modified: ${PROJECT_CONFIG_KEYS.join(', ')}. Did you mean --global?`,\n )\n process.exit(1)\n }\n const currentConfig = getCurrentProjectConfig()\n delete currentConfig[key]\n saveCurrentProjectConfig(currentConfig)\n }\n}\n\nexport function listConfigForCLI(global: true): GlobalConfig\nexport function listConfigForCLI(global: false): ProjectConfig\nexport function listConfigForCLI(global: boolean): object {\n if (global) {\n const currentConfig = pick(getGlobalConfig(), GLOBAL_CONFIG_KEYS)\n return currentConfig\n } else {\n return pick(getCurrentProjectConfig(), PROJECT_CONFIG_KEYS)\n }\n}\n\nexport function getOpenAIApiKey(): string | undefined {\n return process.env.OPENAI_API_KEY\n}\n\n// Configuration migration utility functions\nfunction migrateModelProfilesRemoveId(config: GlobalConfig): GlobalConfig {\n if (!config.modelProfiles) return config\n\n // Cast to legacy type for migration - config may have old fields\n const legacyConfig = config as GlobalConfig & LegacyGlobalConfigFields\n\n // 1. Remove id field from ModelProfile objects and build ID to modelName mapping\n const idToModelNameMap = new Map<string, string>()\n const migratedProfiles = config.modelProfiles.map(profile => {\n // Cast to legacy type that includes optional id field\n const legacyProfile = profile as LegacyModelProfile\n // Build mapping before removing id field\n if (legacyProfile.id && profile.modelName) {\n idToModelNameMap.set(legacyProfile.id, profile.modelName)\n }\n\n // Remove id field, keep everything else\n const { id, ...profileWithoutId } = legacyProfile\n return profileWithoutId as ModelProfile\n })\n\n // 2. Migrate ModelPointers from IDs to modelNames\n const migratedPointers: ModelPointers = {\n main: '',\n task: '',\n reasoning: '',\n quick: '',\n compact: '',\n }\n\n if (config.modelPointers) {\n Object.entries(config.modelPointers).forEach(([pointer, value]) => {\n if (value) {\n // If value looks like an old ID (model_xxx), map it to modelName\n const modelName = idToModelNameMap.get(value) || value\n migratedPointers[pointer as ModelPointerType] = modelName\n }\n })\n }\n\n // 3. Migrate legacy config fields\n let defaultModelName: string | undefined\n if (legacyConfig.defaultModelId) {\n defaultModelName =\n idToModelNameMap.get(legacyConfig.defaultModelId) ||\n legacyConfig.defaultModelId\n } else if (legacyConfig.defaultModelName) {\n defaultModelName = legacyConfig.defaultModelName\n }\n\n // 4. Remove legacy fields and return migrated config\n const migratedConfig: GlobalConfig & Partial<LegacyGlobalConfigFields> = {\n ...config,\n }\n delete migratedConfig.defaultModelId\n delete migratedConfig.currentSelectedModelId\n delete migratedConfig.mainAgentModelId\n delete migratedConfig.taskToolModelId\n\n return {\n ...migratedConfig,\n modelProfiles: migratedProfiles,\n modelPointers: migratedPointers,\n defaultModelName,\n }\n}\n\n// New model system utility functions\n\n/**\n * Deduplicate model profiles by modelName, keeping the one with the latest createdAt timestamp.\n *\n * @param profiles - Array of model profiles to deduplicate\n * @returns Deduplicated array of model profiles\n */\nexport function deduplicateModelProfiles(\n profiles: ModelProfile[],\n): ModelProfile[] {\n if (!profiles || profiles.length === 0) {\n return []\n }\n\n // Use Map to track the latest profile for each modelName\n const profileMap = new Map<string, ModelProfile>()\n\n for (const profile of profiles) {\n const existing = profileMap.get(profile.modelName)\n\n if (!existing) {\n // First occurrence of this modelName\n profileMap.set(profile.modelName, profile)\n } else {\n // Keep the one with the latest createdAt timestamp\n if (profile.createdAt > existing.createdAt) {\n profileMap.set(profile.modelName, profile)\n }\n }\n }\n\n // Return as array, preserving insertion order (which follows original array order for first occurrences)\n return Array.from(profileMap.values())\n}\n\nexport function setAllPointersToModel(modelName: string): void {\n const config = getGlobalConfig()\n const updatedConfig = {\n ...config,\n modelPointers: {\n main: modelName,\n task: modelName,\n reasoning: modelName,\n quick: modelName,\n compact: modelName,\n },\n defaultModelName: modelName,\n }\n saveGlobalConfig(updatedConfig)\n}\n\nexport function setModelPointer(\n pointer: ModelPointerType,\n modelName: string,\n): void {\n const config = getGlobalConfig()\n const updatedConfig = {\n ...config,\n modelPointers: {\n ...config.modelPointers,\n [pointer]: modelName,\n },\n }\n saveGlobalConfig(updatedConfig)\n\n // \uD83D\uDD27 Fix: Force ModelManager reload after config change\n // Import here to avoid circular dependency\n import('./model').then(({ reloadModelManager }) => {\n reloadModelManager()\n })\n}\n\n// Credential resolution functions for secure API key management\n\n/**\n * Resolve an API key for a ModelProfile.\n * Supports both plaintext keys (backward compatibility) and encrypted references.\n *\n * For plaintext keys (legacy):\n * Returns the key directly from the profile\n *\n * For encrypted references (encrypted:modelName):\n * Retrieves the key from the encrypted credential store\n *\n * @param profile The model profile to resolve the API key for\n * @returns The resolved API key, or null if not found\n * @throws Error if credential store access fails\n */\nexport async function resolveApiKey(\n profile: ModelProfile,\n): Promise<string | null> {\n if (!profile.apiKey) {\n return null\n }\n\n // Check if this is an encrypted reference\n if (profile.apiKey.startsWith('encrypted:')) {\n // Extract model name from the encrypted reference\n const modelName = profile.apiKey.slice('encrypted:'.length)\n\n // Import dynamically to avoid circular dependencies\n try {\n const { getApiKey } = await import('./credentials')\n return getApiKey(modelName)\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error)\n debugLogger.warn(\n 'CREDENTIAL_RESOLVE',\n `Failed to resolve encrypted API key for ${modelName}: ${errorMsg}`,\n )\n return null\n }\n }\n\n // Return plaintext key for backward compatibility\n return profile.apiKey\n}\n\n// GPT-5 functions extracted to src/utils/gpt5.ts \u2014 re-exported for backward compatibility\nexport {\n isGPT5ModelName,\n validateAndRepairGPT5Profile,\n validateAndRepairAllGPT5Profiles,\n getGPT5ConfigRecommendations,\n createGPT5ModelProfile,\n} from './gpt5'\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { existsSync, readFileSync, statSync } from 'fs'\nimport { resolve, join } from 'path'\nimport { cloneDeep, memoize, pick } from 'lodash-es'\nimport { homedir } from 'os'\nimport { GLOBAL_CONFIG_FILE } from './env'\nimport { getCwd } from './state'\nimport { randomBytes } from 'crypto'\nimport { safeParseJSON } from './json'\nimport { ConfigParseError } from './errors'\nimport type { ThemeNames } from './theme'\nimport { debug as debugLogger } from './debugLogger'\nimport { safeValidateGlobalConfig } from './configSchema'\nimport type { GlobalConfig as ZodGlobalConfig } from './configSchema'\n\n// Re-export canonical types derived from Zod schemas (single source of truth)\nexport type {\n McpStdioServerConfig,\n McpSSEServerConfig,\n McpHTTPServerConfig,\n McpServerConfig,\n AutoUpdaterStatus,\n NotificationChannel,\n ProviderType,\n UILanguage,\n SafetyMode,\n ReasoningEffort,\n ModelProfile,\n ModelPointerType,\n ModelPointers,\n AccountInfo,\n SandboxConfigData,\n CompressionMode,\n} from './configSchema'\n\n// Import types locally for use in this file\nimport type {\n McpServerConfig,\n AutoUpdaterStatus,\n NotificationChannel,\n ProviderType,\n UILanguage,\n SafetyMode,\n ModelProfile,\n ModelPointerType,\n ModelPointers,\n AccountInfo,\n SandboxConfigData,\n CompressionMode,\n} from './configSchema'\nimport { getSessionState, setSessionState } from './sessionState'\n// CompressionMode now re-exported from configSchema.ts\n\n// Types McpStdioServerConfig, McpSSEServerConfig, McpHTTPServerConfig,\n// McpServerConfig, SandboxConfigData are now derived from Zod schemas\n// and re-exported from configSchema.ts above.\n\n// ProjectConfig uses Zod-derived sub-types but keeps manual definition\n// due to .passthrough() in Zod schema generating incompatible index signatures.\nexport type ProjectConfig = {\n allowedTools: string[]\n context: Record<string, string>\n contextFiles?: string[]\n history: string[]\n dontCrawlDirectory?: boolean\n enableArchitectTool?: boolean\n mcpContextUris: string[]\n mcpServers?: Record<string, McpServerConfig>\n approvedMcprcServers?: string[]\n rejectedMcprcServers?: string[]\n lastAPIDuration?: number\n lastCost?: number\n lastDuration?: number\n lastSessionId?: string\n exampleFiles?: string[]\n exampleFilesGeneratedAt?: number\n hasTrustDialogAccepted?: boolean\n hasCompletedProjectOnboarding?: boolean\n sandbox?: SandboxConfigData\n [key: string]: unknown\n}\n\nconst DEFAULT_PROJECT_CONFIG: ProjectConfig = {\n allowedTools: [],\n context: {},\n history: [],\n dontCrawlDirectory: false,\n enableArchitectTool: false,\n mcpContextUris: [],\n mcpServers: {},\n approvedMcprcServers: [],\n rejectedMcprcServers: [],\n hasTrustDialogAccepted: false,\n}\n\nfunction defaultConfigForProject(projectPath: string): ProjectConfig {\n const config = { ...DEFAULT_PROJECT_CONFIG }\n if (projectPath === homedir()) {\n config.dontCrawlDirectory = true\n }\n return config\n}\n\n// AutoUpdaterStatus now derived from Zod schema in configSchema.ts\n\nexport function isAutoUpdaterStatus(value: string): value is AutoUpdaterStatus {\n return ['disabled', 'enabled', 'no_permissions', 'not_configured'].includes(\n value as AutoUpdaterStatus,\n )\n}\n\n// NotificationChannel now derived from Zod schema in configSchema.ts\n\n/**\n * @deprecated Use verbose boolean instead. Kept for backward compatibility migration.\n */\nexport type DisplayMode = 'minimal' | 'compact' | 'detailed'\n\n// UILanguage now derived from Zod schema in configSchema.ts\n\n// SafetyMode now derived from Zod schema in configSchema.ts\n\n/**\n * Get verbose mode label (uses i18n)\n * Import dynamically to avoid circular dependency\n */\nexport function getVerboseLabel(verbose: boolean): string {\n // Dynamic import to avoid circular dependency at module load time\n try {\n const { t } = require('../i18n')\n return verbose ? t('ui.verbose.on') : t('ui.verbose.off')\n } catch {\n // Fallback if i18n not loaded yet\n return verbose ? 'Verbose: On' : 'Verbose: Off'\n }\n}\n\n// ProviderType now derived from Zod schema in configSchema.ts\n\n// ModelProfile now derived from Zod schema in configSchema.ts\n\n// Legacy type for config migration - includes deprecated 'id' field\ntype LegacyModelProfile = ModelProfile & {\n id?: string\n}\n\n// Legacy global config fields for migration\ntype LegacyGlobalConfigFields = {\n defaultModelId?: string\n defaultModelName?: string\n currentSelectedModelId?: string\n mainAgentModelId?: string\n taskToolModelId?: string\n}\n\n// ModelPointerType, ModelPointers, AccountInfo now derived from Zod schema in configSchema.ts\n\n// GlobalConfig: Manual type definition kept because Zod's .passthrough() generates\n// `& { [k: string]: unknown }` via z.infer<>, which is incompatible with strict\n// ProjectConfig intersections (e.g., Record<string, ProjectConfig> vs Record<string, ProjectConfig & {[k:string]:unknown}>).\n// We cannot simply use `z.infer<typeof GlobalConfigSchema>` here.\n// This must stay in sync with GlobalConfigSchema in configSchema.ts. SYNC: configSchema.ts:GlobalConfigSchema\n//\n// Compile-time check: ensure manual GlobalConfig stays aligned with Zod schema.\n// If this line errors, the two definitions have drifted apart.\nexport type GlobalConfig = {\n projects?: Record<string, ProjectConfig>\n numStartups: number\n autoUpdaterStatus?: AutoUpdaterStatus\n userID?: string\n theme: ThemeNames\n hasCompletedOnboarding?: boolean\n lastOnboardingVersion?: string\n lastReleaseNotesSeen?: string\n mcpServers?: Record<string, McpServerConfig>\n preferredNotifChannel: NotificationChannel\n verbose: boolean\n /** @deprecated Use verbose boolean instead. */\n displayMode?: DisplayMode\n customApiKeyResponses?: {\n approved?: string[]\n rejected?: string[]\n }\n primaryProvider?: ProviderType\n maxTokens?: number\n hasAcknowledgedCostThreshold?: boolean\n oauthAccount?: AccountInfo\n iterm2KeyBindingInstalled?: boolean\n shiftEnterKeyBindingInstalled?: boolean\n proxy?: string\n stream?: boolean\n modelProfiles?: ModelProfile[]\n modelPointers?: ModelPointers\n defaultModelName?: string\n lastDismissedUpdateVersion?: string\n compressionMode?: CompressionMode\n thinking?: boolean\n language?: UILanguage\n /** @deprecated Use safetyMode instead. */\n safeMode?: boolean\n safetyMode?: SafetyMode\n autoSyncClaudeCode?: boolean\n enableMemoryTools?: boolean\n outputStyle?: string\n autoMemory?: boolean\n backupEnabled?: boolean\n enableAgentTeams?: boolean\n teammateMode?: 'auto' | 'in-process' | 'tmux'\n bashOutputSummarization?: boolean\n enableSessionMemory?: boolean\n enableTopicDetection?: boolean\n configVersion?: number\n sandbox?: SandboxConfigData\n}\n\n// Compile-time alignment check: ensure manual GlobalConfig stays in sync with Zod schema.\n// If this errors, the two definitions have drifted \u2014 add the missing field to whichever side is behind.\n// Bidirectional check: Forward catches fields missing from Zod, Reverse catches fields missing from config.ts.\n// Note: We strip the index signature from ZodGlobalConfig (due to .passthrough()) using a mapped type.\ntype StripIndexSignature<T> = {\n [K in keyof T as string extends K\n ? never\n : number extends K\n ? never\n : K]: T[K]\n}\nfunction _assertGlobalConfigAlignment() {\n // Forward: manual GlobalConfig assignable to Zod GlobalConfig\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const _check1: ZodGlobalConfig = {} as GlobalConfig\n // Reverse: Zod GlobalConfig (without index sig) assignable to manual GlobalConfig\n // Catches fields added to configSchema.ts but missing from config.ts GlobalConfig.\n // @ts-expect-error \u2014 Known incompatibility: Zod .passthrough() on ProjectConfigSchema\n // makes nested ProjectConfig fields optional in z.infer<>, while the manual ProjectConfig\n // type above (line 59) defines allowedTools/context/history/mcpContextUris as required.\n // This is intentional \u2014 see comment at line 157. The forward check (_check1) is the\n // primary drift guard; this reverse check is kept for documentation.\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const _check2: GlobalConfig = {} as StripIndexSignature<ZodGlobalConfig>\n}\n\nexport const DEFAULT_GLOBAL_CONFIG: GlobalConfig = {\n numStartups: 0,\n autoUpdaterStatus: 'not_configured',\n theme: 'dark',\n preferredNotifChannel: 'iterm2',\n verbose: false,\n primaryProvider: 'anthropic',\n customApiKeyResponses: {\n approved: [],\n rejected: [],\n },\n stream: true,\n\n // New model system defaults\n modelProfiles: [],\n modelPointers: {\n main: '',\n task: '',\n reasoning: '',\n quick: '',\n compact: '',\n },\n lastDismissedUpdateVersion: undefined,\n compressionMode: 'business', // Default to business consulting compression\n thinking: false, // Default to thinking mode off (Phase 4.2)\n language: 'en', // Default to English\n safeMode: false, // Deprecated: use safetyMode instead\n safetyMode: 'smart', // Default to smart mode \u2014 safe tools auto-allowed, dangerous tools need confirmation\n}\n\nexport const GLOBAL_CONFIG_KEYS = [\n 'autoUpdaterStatus',\n 'theme',\n 'hasCompletedOnboarding',\n 'lastOnboardingVersion',\n 'lastReleaseNotesSeen',\n 'verbose',\n 'customApiKeyResponses',\n 'primaryProvider',\n 'preferredNotifChannel',\n 'shiftEnterKeyBindingInstalled',\n 'maxTokens',\n 'proxy',\n 'stream',\n 'thinking',\n 'backupEnabled',\n 'compressionMode',\n 'language',\n 'safetyMode',\n 'enableMemoryTools',\n 'outputStyle',\n 'autoMemory',\n 'enableAgentTeams',\n 'teammateMode',\n 'bashOutputSummarization',\n 'enableSessionMemory',\n 'enableTopicDetection',\n] as const\n\nexport type GlobalConfigKey = (typeof GLOBAL_CONFIG_KEYS)[number]\n\nexport function isGlobalConfigKey(key: string): key is GlobalConfigKey {\n return GLOBAL_CONFIG_KEYS.includes(key as GlobalConfigKey)\n}\n\nexport const PROJECT_CONFIG_KEYS = [\n 'dontCrawlDirectory',\n 'enableArchitectTool',\n 'hasTrustDialogAccepted',\n 'hasCompletedProjectOnboarding',\n] as const\n\nexport type ProjectConfigKey = (typeof PROJECT_CONFIG_KEYS)[number]\n\nexport function checkHasTrustDialogAccepted(): boolean {\n let currentPath = getCwd()\n const config = getConfig(GLOBAL_CONFIG_FILE, DEFAULT_GLOBAL_CONFIG)\n\n while (true) {\n const projectConfig = config.projects?.[currentPath]\n if (projectConfig?.hasTrustDialogAccepted) {\n return true\n }\n const parentPath = resolve(currentPath, '..')\n // Stop if we've reached the root (when parent is same as current)\n if (parentPath === currentPath) {\n break\n }\n currentPath = parentPath\n }\n\n return false\n}\n\n// We have to put this test code here because Jest doesn't support mocking ES modules :O\nconst TEST_GLOBAL_CONFIG_FOR_TESTING: GlobalConfig = {\n ...DEFAULT_GLOBAL_CONFIG,\n autoUpdaterStatus: 'disabled',\n}\nconst TEST_PROJECT_CONFIG_FOR_TESTING: ProjectConfig = {\n ...DEFAULT_PROJECT_CONFIG,\n}\n\nexport function isProjectConfigKey(key: string): key is ProjectConfigKey {\n return PROJECT_CONFIG_KEYS.includes(key as ProjectConfigKey)\n}\n\nexport function saveGlobalConfig(config: GlobalConfig): void {\n if (process.env.NODE_ENV === 'test') {\n for (const key in config) {\n ;(TEST_GLOBAL_CONFIG_FOR_TESTING as Record<string, unknown>)[key] = (\n config as Record<string, unknown>\n )[key]\n }\n return\n }\n\n // Invalidate mtime cache so next getGlobalConfig() re-reads from disk\n _cachedGlobalConfig = null\n _cachedMtimeMs = 0\n saveConfig(\n GLOBAL_CONFIG_FILE,\n {\n ...config,\n projects: getConfig(GLOBAL_CONFIG_FILE, DEFAULT_GLOBAL_CONFIG).projects,\n },\n DEFAULT_GLOBAL_CONFIG,\n )\n}\n\n/**\n * Migrate legacy displayMode to verbose boolean\n */\nfunction migrateDisplayModeToVerbose(config: GlobalConfig): GlobalConfig {\n // If verbose is already set, no migration needed\n if (config.verbose !== undefined) {\n return config\n }\n\n // Check for legacy displayMode field\n const legacyConfig = config as GlobalConfig & { displayMode?: DisplayMode }\n if (legacyConfig.displayMode !== undefined) {\n const migratedConfig: GlobalConfig = {\n ...config,\n verbose: legacyConfig.displayMode === 'detailed',\n }\n // Remove legacy field\n delete (migratedConfig as Record<string, unknown>).displayMode\n return migratedConfig\n }\n\n // Default to false if no verbose or displayMode\n return {\n ...config,\n verbose: false,\n }\n}\n\n/**\n * Deep-freeze an object so it cannot be mutated.\n * Callers that need to mutate should clone first: `structuredClone(getGlobalConfig())`.\n */\nfunction deepFreeze<T extends object>(obj: T): Readonly<T> {\n Object.freeze(obj)\n for (const value of Object.values(obj)) {\n if (value && typeof value === 'object' && !Object.isFrozen(value)) {\n deepFreeze(value as object)\n }\n }\n return obj\n}\n\n// mtime-based cache for getGlobalConfig()\nlet _cachedGlobalConfig: Readonly<GlobalConfig> | null = null\nlet _cachedMtimeMs: number = 0\n\n/**\n * Returns a mutable clone of the global config for callers that need to modify and save it.\n * Pattern: `const config = getMutableGlobalConfig(); config.foo = bar; saveGlobalConfig(config);`\n */\nexport function getMutableGlobalConfig(): GlobalConfig {\n return structuredClone(getGlobalConfig()) as GlobalConfig\n}\n\nexport function getGlobalConfig(): Readonly<GlobalConfig> {\n if (process.env.NODE_ENV === 'test') {\n return TEST_GLOBAL_CONFIG_FOR_TESTING\n }\n\n // Check file mtime \u2014 if unchanged, return frozen cached reference directly\n const stat = statSync(GLOBAL_CONFIG_FILE, { throwIfNoEntry: false })\n const currentMtime = stat?.mtimeMs ?? 0\n if (_cachedGlobalConfig && currentMtime === _cachedMtimeMs) {\n return _cachedGlobalConfig\n }\n\n const config = getConfig(GLOBAL_CONFIG_FILE, DEFAULT_GLOBAL_CONFIG)\n\n // Apply migrations on every cache miss\n let migratedConfig = migrateModelProfilesRemoveId(config)\n let displayMigratedConfig = migrateDisplayModeToVerbose(migratedConfig)\n\n // Apply model profile deduplication\n if (\n displayMigratedConfig.modelProfiles &&\n displayMigratedConfig.modelProfiles.length > 0\n ) {\n const originalCount = displayMigratedConfig.modelProfiles.length\n const deduplicatedProfiles = deduplicateModelProfiles(\n displayMigratedConfig.modelProfiles,\n )\n const deduplicatedCount = deduplicatedProfiles.length\n\n // If duplicates were found and removed, auto-save the deduplicated config\n if (deduplicatedCount < originalCount) {\n debugLogger.state('CONFIG_DEDUPLICATE_PROFILES', {\n originalCount: String(originalCount),\n deduplicatedCount: String(deduplicatedCount),\n removedCount: String(originalCount - deduplicatedCount),\n })\n const configToSave = {\n ...displayMigratedConfig,\n modelProfiles: deduplicatedProfiles,\n }\n // Save the deduplicated config (avoid recursion by using saveConfig directly)\n saveConfig(\n GLOBAL_CONFIG_FILE,\n {\n ...configToSave,\n projects: config.projects,\n },\n DEFAULT_GLOBAL_CONFIG,\n )\n _cachedGlobalConfig = deepFreeze(configToSave)\n _cachedMtimeMs =\n statSync(GLOBAL_CONFIG_FILE, { throwIfNoEntry: false })?.mtimeMs ?? 0\n return _cachedGlobalConfig\n }\n\n displayMigratedConfig = {\n ...displayMigratedConfig,\n modelProfiles: deduplicatedProfiles,\n }\n }\n\n // Update cache \u2014 freeze once, return the same reference on subsequent calls\n _cachedGlobalConfig = deepFreeze(displayMigratedConfig)\n _cachedMtimeMs = currentMtime\n return _cachedGlobalConfig\n}\n\nexport function getAnthropicApiKey(): null | string {\n return process.env.ANTHROPIC_API_KEY || null\n}\n\nexport function normalizeApiKeyForConfig(apiKey: string): string {\n return apiKey?.slice(-20) ?? ''\n}\n\nexport function getCustomApiKeyStatus(\n truncatedApiKey: string,\n): 'approved' | 'rejected' | 'new' {\n const config = getGlobalConfig()\n if (config.customApiKeyResponses?.approved?.includes(truncatedApiKey)) {\n return 'approved'\n }\n if (config.customApiKeyResponses?.rejected?.includes(truncatedApiKey)) {\n return 'rejected'\n }\n return 'new'\n}\n\n// atomicWriteFileSync extracted to src/utils/atomicWrite.ts\nimport { atomicWriteFileSync } from './atomicWrite'\n\nfunction saveConfig<A extends object>(\n file: string,\n config: A,\n defaultConfig: A,\n): void {\n // Filter out any values that match the defaults\n const filteredConfig = Object.fromEntries(\n Object.entries(config).filter(\n ([key, value]) =>\n JSON.stringify(value) !== JSON.stringify(defaultConfig[key as keyof A]),\n ),\n )\n try {\n atomicWriteFileSync(file, JSON.stringify(filteredConfig, null, 2))\n } catch (error) {\n const err = error as NodeJS.ErrnoException\n if (\n err?.code === 'EACCES' ||\n err?.code === 'EPERM' ||\n err?.code === 'EROFS'\n ) {\n debugLogger.state('CONFIG_SAVE_SKIPPED', {\n file,\n reason: String(err.code),\n })\n return\n }\n throw error\n }\n}\n\n// Flag to track if config reading is allowed\nlet configReadingAllowed = false\n\nexport function enableConfigs(): void {\n // Any reads to configuration before this flag is set show an console warning\n // to prevent us from adding config reading during module initialization\n configReadingAllowed = true\n // We only check the global config because currently all the configs share a file\n getConfig(\n GLOBAL_CONFIG_FILE,\n DEFAULT_GLOBAL_CONFIG,\n true /* throw on invalid */,\n )\n}\n\nfunction getConfig<A>(\n file: string,\n defaultConfig: A,\n throwOnInvalid?: boolean,\n): A {\n // \u7B80\u5316\u914D\u7F6E\u8BBF\u95EE\u903B\u8F91\uFF0C\u79FB\u9664\u590D\u6742\u7684\u65F6\u5E8F\u68C0\u67E5\n\n debugLogger.state('CONFIG_LOAD_START', {\n file,\n fileExists: String(existsSync(file)),\n throwOnInvalid: String(!!throwOnInvalid),\n })\n\n if (!existsSync(file)) {\n debugLogger.state('CONFIG_LOAD_DEFAULT', {\n file,\n reason: 'file_not_exists',\n defaultConfigKeys: Object.keys(defaultConfig as object).join(', '),\n })\n return cloneDeep(defaultConfig)\n }\n\n try {\n const fileContent = readFileSync(file, 'utf-8')\n debugLogger.state('CONFIG_FILE_READ', {\n file,\n contentLength: String(fileContent.length),\n contentPreview:\n fileContent.substring(0, 100) + (fileContent.length > 100 ? '...' : ''),\n })\n\n try {\n const parsedConfig = JSON.parse(fileContent)\n debugLogger.state('CONFIG_JSON_PARSED', {\n file,\n parsedKeys: Object.keys(parsedConfig).join(', '),\n })\n\n // Zod validation \u2014 monitor mode (log errors, never reject \u2014 backward compatibility)\n let validationWarnings: string[] | undefined\n if (file === GLOBAL_CONFIG_FILE) {\n const validation = safeValidateGlobalConfig(parsedConfig)\n if (!validation.success && validation.errors) {\n const issues = validation.errors.issues.map(\n i => `${i.path.join('.')}: ${i.message}`,\n )\n validationWarnings = issues\n debugLogger.error('CONFIG_VALIDATION', {\n file,\n issues: issues.join('; '),\n })\n }\n }\n\n // Handle backward compatibility - remove logic for deleted fields\n const finalConfig = {\n ...cloneDeep(defaultConfig),\n ...parsedConfig,\n }\n\n // Attach validation warnings so callers can inspect them if needed\n if (validationWarnings) {\n ;(finalConfig as Record<string, unknown>)._validationWarnings =\n validationWarnings\n }\n\n debugLogger.state('CONFIG_LOAD_SUCCESS', {\n file,\n finalConfigKeys: Object.keys(finalConfig as object).join(', '),\n })\n\n return finalConfig\n } catch (error) {\n // Throw a ConfigParseError with the file path and default config\n const errorMessage =\n error instanceof Error ? error.message : String(error)\n\n debugLogger.error('CONFIG_JSON_PARSE_ERROR', {\n file,\n errorMessage,\n errorType:\n error instanceof Error ? error.constructor.name : typeof error,\n contentLength: String(fileContent.length),\n })\n\n throw new ConfigParseError(errorMessage, file, defaultConfig)\n }\n } catch (error: unknown) {\n // Re-throw ConfigParseError if throwOnInvalid is true\n if (error instanceof ConfigParseError && throwOnInvalid) {\n debugLogger.error('CONFIG_PARSE_ERROR_RETHROWN', {\n file,\n throwOnInvalid: String(throwOnInvalid),\n errorMessage: error.message,\n })\n throw error\n }\n\n debugLogger.warn('CONFIG_FALLBACK_TO_DEFAULT', {\n file,\n errorType: error instanceof Error ? error.constructor.name : typeof error,\n errorMessage: error instanceof Error ? error.message : String(error),\n action: 'using_default_config',\n })\n\n return cloneDeep(defaultConfig)\n }\n}\n\nexport function getCurrentProjectConfig(): ProjectConfig {\n if (process.env.NODE_ENV === 'test') {\n return TEST_PROJECT_CONFIG_FOR_TESTING\n }\n\n const absolutePath = resolve(getCwd())\n const config = getConfig(GLOBAL_CONFIG_FILE, DEFAULT_GLOBAL_CONFIG)\n\n if (!config.projects) {\n return defaultConfigForProject(absolutePath)\n }\n\n const projectConfig =\n config.projects[absolutePath] ?? defaultConfigForProject(absolutePath)\n // Guard: allowedTools may be serialized as a JSON string in some config paths\n if (typeof projectConfig.allowedTools === 'string') {\n projectConfig.allowedTools =\n (safeParseJSON(projectConfig.allowedTools) as string[]) ?? []\n }\n return projectConfig\n}\n\nexport function saveCurrentProjectConfig(projectConfig: ProjectConfig): void {\n if (process.env.NODE_ENV === 'test') {\n for (const key in projectConfig) {\n TEST_PROJECT_CONFIG_FOR_TESTING[key] = projectConfig[key]\n }\n return\n }\n const config = getConfig(GLOBAL_CONFIG_FILE, DEFAULT_GLOBAL_CONFIG)\n saveConfig(\n GLOBAL_CONFIG_FILE,\n {\n ...config,\n projects: {\n ...config.projects,\n [resolve(getCwd())]: projectConfig,\n },\n },\n DEFAULT_GLOBAL_CONFIG,\n )\n}\n\nexport async function isAutoUpdaterDisabled(): Promise<boolean> {\n return getGlobalConfig().autoUpdaterStatus === 'disabled'\n}\n\nexport const TEST_MCPRC_CONFIG_FOR_TESTING: Record<string, McpServerConfig> = {}\n\nexport function clearMcprcConfigForTesting(): void {\n if (process.env.NODE_ENV === 'test') {\n Object.keys(TEST_MCPRC_CONFIG_FOR_TESTING).forEach(key => {\n delete TEST_MCPRC_CONFIG_FOR_TESTING[key]\n })\n }\n}\n\nexport function addMcprcServerForTesting(\n name: string,\n server: McpServerConfig,\n): void {\n if (process.env.NODE_ENV === 'test') {\n TEST_MCPRC_CONFIG_FOR_TESTING[name] = server\n }\n}\n\nexport function removeMcprcServerForTesting(name: string): void {\n if (process.env.NODE_ENV === 'test') {\n if (!TEST_MCPRC_CONFIG_FOR_TESTING[name]) {\n throw new Error(`No MCP server found with name: ${name} in .mcprc`)\n }\n delete TEST_MCPRC_CONFIG_FOR_TESTING[name]\n }\n}\n\nexport const getMcprcConfig = memoize(\n (): Record<string, McpServerConfig> => {\n if (process.env.NODE_ENV === 'test') {\n return TEST_MCPRC_CONFIG_FOR_TESTING\n }\n\n const mcprcPath = join(getCwd(), '.mcprc')\n if (!existsSync(mcprcPath)) {\n return {}\n }\n\n try {\n const mcprcContent = readFileSync(mcprcPath, 'utf-8')\n const config = safeParseJSON(mcprcContent)\n if (config && typeof config === 'object') {\n // Logging removed\n return config as Record<string, McpServerConfig>\n }\n } catch {\n // Ignore errors reading/parsing .mcprc (they're logged in safeParseJSON)\n }\n return {}\n },\n // Cache key uses mtime instead of reading file content (avoids full I/O on every call)\n () => {\n const cwd = getCwd()\n const mcprcPath = join(cwd, '.mcprc')\n const mtime = statSync(mcprcPath, { throwIfNoEntry: false })?.mtimeMs\n return mtime != null ? `${cwd}:${mtime}` : cwd\n },\n)\n\nexport function getOrCreateUserID(): string {\n const config = getGlobalConfig()\n if (config.userID) {\n return config.userID\n }\n\n const userID = randomBytes(32).toString('hex')\n saveGlobalConfig({ ...config, userID })\n return userID\n}\n\nexport function getConfigForCLI(key: string, global: boolean): unknown {\n if (global) {\n if (!isGlobalConfigKey(key)) {\n console.error(\n `Error: '${key}' is not a valid config key. Valid keys are: ${GLOBAL_CONFIG_KEYS.join(', ')}`,\n )\n process.exit(1)\n }\n return getGlobalConfig()[key]\n } else {\n if (!isProjectConfigKey(key)) {\n console.error(\n `Error: '${key}' is not a valid config key. Valid keys are: ${PROJECT_CONFIG_KEYS.join(', ')}`,\n )\n process.exit(1)\n }\n return getCurrentProjectConfig()[key]\n }\n}\n\nexport function setConfigForCLI(\n key: string,\n value: unknown,\n global: boolean,\n): void {\n if (global) {\n if (!isGlobalConfigKey(key)) {\n console.error(\n `Error: Cannot set '${key}'. Only these keys can be modified: ${GLOBAL_CONFIG_KEYS.join(', ')}`,\n )\n process.exit(1)\n }\n\n if (key === 'autoUpdaterStatus' && !isAutoUpdaterStatus(value as string)) {\n console.error(\n `Error: Invalid value for autoUpdaterStatus. Must be one of: disabled, enabled, no_permissions, not_configured`,\n )\n process.exit(1)\n }\n\n const currentConfig = getGlobalConfig()\n saveGlobalConfig({\n ...currentConfig,\n [key]: value,\n })\n } else {\n if (!isProjectConfigKey(key)) {\n console.error(\n `Error: Cannot set '${key}'. Only these keys can be modified: ${PROJECT_CONFIG_KEYS.join(', ')}. Did you mean --global?`,\n )\n process.exit(1)\n }\n const currentConfig = getCurrentProjectConfig()\n saveCurrentProjectConfig({\n ...currentConfig,\n [key]: value,\n })\n }\n // Wait for the output to be flushed, to avoid clearing the screen.\n setTimeout(() => {\n // Without this we hang indefinitely.\n process.exit(0)\n }, 100)\n}\n\nexport function deleteConfigForCLI(key: string, global: boolean): void {\n if (global) {\n if (!isGlobalConfigKey(key)) {\n console.error(\n `Error: Cannot delete '${key}'. Only these keys can be modified: ${GLOBAL_CONFIG_KEYS.join(', ')}`,\n )\n process.exit(1)\n }\n const currentConfig = structuredClone(getGlobalConfig()) as GlobalConfig\n delete currentConfig[key]\n saveGlobalConfig(currentConfig)\n } else {\n if (!isProjectConfigKey(key)) {\n console.error(\n `Error: Cannot delete '${key}'. Only these keys can be modified: ${PROJECT_CONFIG_KEYS.join(', ')}. Did you mean --global?`,\n )\n process.exit(1)\n }\n const currentConfig = getCurrentProjectConfig()\n delete currentConfig[key]\n saveCurrentProjectConfig(currentConfig)\n }\n}\n\nexport function listConfigForCLI(global: true): GlobalConfig\nexport function listConfigForCLI(global: false): ProjectConfig\nexport function listConfigForCLI(global: boolean): object {\n if (global) {\n const currentConfig = pick(getGlobalConfig(), GLOBAL_CONFIG_KEYS)\n return currentConfig\n } else {\n return pick(getCurrentProjectConfig(), PROJECT_CONFIG_KEYS)\n }\n}\n\nexport function getOpenAIApiKey(): string | undefined {\n return process.env.OPENAI_API_KEY\n}\n\n// Configuration migration utility functions\nfunction migrateModelProfilesRemoveId(config: GlobalConfig): GlobalConfig {\n if (!config.modelProfiles) return config\n\n // Cast to legacy type for migration - config may have old fields\n const legacyConfig = config as GlobalConfig & LegacyGlobalConfigFields\n\n // 1. Remove id field from ModelProfile objects and build ID to modelName mapping\n const idToModelNameMap = new Map<string, string>()\n const migratedProfiles = config.modelProfiles.map(profile => {\n // Cast to legacy type that includes optional id field\n const legacyProfile = profile as LegacyModelProfile\n // Build mapping before removing id field\n if (legacyProfile.id && profile.modelName) {\n idToModelNameMap.set(legacyProfile.id, profile.modelName)\n }\n\n // Remove id field, keep everything else\n const { id, ...profileWithoutId } = legacyProfile\n return profileWithoutId as ModelProfile\n })\n\n // 2. Migrate ModelPointers from IDs to modelNames\n const migratedPointers: ModelPointers = {\n main: '',\n task: '',\n reasoning: '',\n quick: '',\n compact: '',\n }\n\n if (config.modelPointers) {\n Object.entries(config.modelPointers).forEach(([pointer, value]) => {\n if (value) {\n // If value looks like an old ID (model_xxx), map it to modelName\n const modelName = idToModelNameMap.get(value) || value\n migratedPointers[pointer as ModelPointerType] = modelName\n }\n })\n }\n\n // 3. Migrate legacy config fields\n let defaultModelName: string | undefined\n if (legacyConfig.defaultModelId) {\n defaultModelName =\n idToModelNameMap.get(legacyConfig.defaultModelId) ||\n legacyConfig.defaultModelId\n } else if (legacyConfig.defaultModelName) {\n defaultModelName = legacyConfig.defaultModelName\n }\n\n // 4. Remove legacy fields and return migrated config\n const migratedConfig: GlobalConfig & Partial<LegacyGlobalConfigFields> = {\n ...config,\n }\n delete migratedConfig.defaultModelId\n delete migratedConfig.currentSelectedModelId\n delete migratedConfig.mainAgentModelId\n delete migratedConfig.taskToolModelId\n\n return {\n ...migratedConfig,\n modelProfiles: migratedProfiles,\n modelPointers: migratedPointers,\n defaultModelName,\n }\n}\n\n// New model system utility functions\n\n/**\n * Deduplicate model profiles by modelName, keeping the one with the latest createdAt timestamp.\n *\n * @param profiles - Array of model profiles to deduplicate\n * @returns Deduplicated array of model profiles\n */\nexport function deduplicateModelProfiles(\n profiles: ModelProfile[],\n): ModelProfile[] {\n if (!profiles || profiles.length === 0) {\n return []\n }\n\n // Use Map to track the latest profile for each modelName\n const profileMap = new Map<string, ModelProfile>()\n\n for (const profile of profiles) {\n const existing = profileMap.get(profile.modelName)\n\n if (!existing) {\n // First occurrence of this modelName\n profileMap.set(profile.modelName, profile)\n } else {\n // Keep the one with the latest createdAt timestamp\n if (profile.createdAt > existing.createdAt) {\n profileMap.set(profile.modelName, profile)\n }\n }\n }\n\n // Return as array, preserving insertion order (which follows original array order for first occurrences)\n return Array.from(profileMap.values())\n}\n\nexport function setAllPointersToModel(modelName: string): void {\n const config = getGlobalConfig()\n const updatedConfig = {\n ...config,\n modelPointers: {\n main: modelName,\n task: modelName,\n reasoning: modelName,\n quick: modelName,\n compact: modelName,\n },\n defaultModelName: modelName,\n }\n saveGlobalConfig(updatedConfig)\n}\n\nexport function setModelPointer(\n pointer: ModelPointerType,\n modelName: string,\n): void {\n const config = getGlobalConfig()\n const updatedConfig = {\n ...config,\n modelPointers: {\n ...config.modelPointers,\n [pointer]: modelName,\n },\n }\n saveGlobalConfig(updatedConfig)\n\n // \uD83D\uDD27 Fix: Force ModelManager reload after config change\n // Import here to avoid circular dependency\n import('./model').then(({ reloadModelManager }) => {\n reloadModelManager()\n })\n}\n\n// Credential resolution functions for secure API key management\n\n/**\n * Resolve an API key for a ModelProfile.\n * Supports both plaintext keys (backward compatibility) and encrypted references.\n *\n * For plaintext keys (legacy):\n * Returns the key directly from the profile\n *\n * For encrypted references (encrypted:modelName):\n * Retrieves the key from the encrypted credential store\n *\n * @param profile The model profile to resolve the API key for\n * @returns The resolved API key, or null if not found\n * @throws Error if credential store access fails\n */\nexport async function resolveApiKey(\n profile: ModelProfile,\n): Promise<string | null> {\n if (!profile.apiKey) {\n return null\n }\n\n // Check if this is an encrypted reference\n if (profile.apiKey.startsWith('encrypted:')) {\n // Extract model name from the encrypted reference\n const modelName = profile.apiKey.slice('encrypted:'.length)\n\n // Import dynamically to avoid circular dependencies\n try {\n const { getApiKey } = await import('./credentials')\n return getApiKey(modelName)\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error)\n debugLogger.warn(\n 'CREDENTIAL_RESOLVE',\n `Failed to resolve encrypted API key for ${modelName}: ${errorMsg}`,\n )\n return null\n }\n }\n\n // Return plaintext key for backward compatibility\n return profile.apiKey\n}\n\n// GPT-5 functions extracted to src/utils/gpt5.ts \u2014 re-exported for backward compatibility\nexport {\n isGPT5ModelName,\n validateAndRepairGPT5Profile,\n validateAndRepairAllGPT5Profiles,\n getGPT5ConfigRecommendations,\n createGPT5ModelProfile,\n} from './gpt5'\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -92,7 +92,7 @@ const ModelProfileSchema = z.object({
92
92
  provider: ProviderTypeSchema,
93
93
  modelName: z.string(),
94
94
  baseURL: z.string().optional(),
95
- apiKey: z.string(),
95
+ apiKey: z.string().optional().default(""),
96
96
  maxTokens: z.number(),
97
97
  contextLength: z.number(),
98
98
  reasoningEffort: ReasoningEffortSchema.optional(),
@@ -191,16 +191,22 @@ const GlobalConfigSchema = z.object({
191
191
  // Auto-memory: extract key decisions during auto-compact
192
192
  autoMemory: z.boolean().optional(),
193
193
  // Sandbox config
194
- sandbox: SandboxConfigDataSchema.optional()
194
+ sandbox: SandboxConfigDataSchema.optional(),
195
+ // Agent Teams (experimental multi-agent collaboration)
196
+ enableAgentTeams: z.boolean().optional(),
197
+ // Teammate display mode: auto-detect, in-process, or tmux
198
+ teammateMode: z.enum(["auto", "in-process", "tmux"]).optional(),
199
+ // Bash output summarization: use quick model to summarize large outputs
200
+ bashOutputSummarization: z.boolean().optional(),
201
+ // Session memory: inject previous session summaries into new sessions
202
+ enableSessionMemory: z.boolean().optional(),
203
+ // Topic detection: pre-flight check to detect conversation topic changes
204
+ enableTopicDetection: z.boolean().optional()
195
205
  }).passthrough();
196
206
  function safeValidateGlobalConfig(config) {
197
207
  const result = GlobalConfigSchema.safeParse(config);
198
208
  return result.success ? { success: true, data: result.data } : { success: false, errors: result.error };
199
209
  }
200
- function safeValidateProjectConfig(config) {
201
- const result = ProjectConfigSchema.safeParse(config);
202
- return result.success ? { success: true, data: result.data } : { success: false, errors: result.error };
203
- }
204
210
  export {
205
211
  AccountInfoSchema,
206
212
  AutoUpdaterStatusSchema,
@@ -221,7 +227,6 @@ export {
221
227
  SandboxConfigDataSchema,
222
228
  ThemeNamesSchema,
223
229
  UILanguageSchema,
224
- safeValidateGlobalConfig,
225
- safeValidateProjectConfig
230
+ safeValidateGlobalConfig
226
231
  };
227
232
  //# sourceMappingURL=configSchema.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/utils/configSchema.ts"],
4
- "sourcesContent": ["/**\n * Configuration Schema Definitions (Zod)\n *\n * Preserved from src/core/config/schema.ts for future Zod validation integration.\n * These schemas define the canonical shape of Minto configuration.\n * Used by Phase 3 config hardening to add runtime validation.\n */\n\nimport { z } from 'zod'\n\n// Theme Names (matches src/utils/theme.ts)\nexport const ThemeNamesSchema = z.enum([\n 'dark',\n 'light',\n 'light-daltonized',\n 'dark-daltonized',\n])\n\n// MCP Server Configurations\nexport const McpStdioServerConfigSchema = z.object({\n type: z.literal('stdio').optional().default('stdio'),\n command: z.string(),\n args: z.array(z.string()),\n env: z.record(z.string()).optional(),\n enabled: z.boolean().optional(),\n})\n\nexport const McpSSEServerConfigSchema = z.object({\n type: z.literal('sse'),\n url: z.string(),\n enabled: z.boolean().optional(),\n})\n\nexport const McpHTTPServerConfigSchema = z.object({\n type: z.literal('http'),\n url: z.string(),\n headers: z.record(z.string()).optional(),\n enabled: z.boolean().optional(),\n})\n\nexport const McpServerConfigSchema = z.union([\n McpStdioServerConfigSchema,\n McpSSEServerConfigSchema,\n McpHTTPServerConfigSchema,\n])\n\n// Auto Updater Status\nexport const AutoUpdaterStatusSchema = z.enum([\n 'disabled',\n 'enabled',\n 'no_permissions',\n 'not_configured',\n])\n\n// Notification Channel\nexport const NotificationChannelSchema = z.enum([\n 'iterm2',\n 'terminal_bell',\n 'iterm2_with_bell',\n 'notifications_disabled',\n])\n\n// Provider Types\nexport const ProviderTypeSchema = z.enum([\n 'anthropic',\n 'openai',\n 'mistral',\n 'deepseek',\n 'kimi',\n 'qwen',\n 'glm',\n 'minimax',\n 'baidu-qianfan',\n 'siliconflow',\n 'bigdream',\n 'opendev',\n 'xai',\n 'groq',\n 'gemini',\n 'ollama',\n 'azure',\n 'custom',\n 'custom-openai',\n])\n\n// Compression Mode\nexport const CompressionModeSchema = z.enum(['business', 'code'])\n\n// UI Language\nexport const UILanguageSchema = z.enum(['en', 'zh-CN'])\n\n// Safety Mode\nexport const SafetyModeSchema = z.enum(['yolo', 'smart', 'strict', 'free'])\n\n// Reasoning Effort\nexport const ReasoningEffortSchema = z.enum([\n 'minimal',\n 'low',\n 'medium',\n 'high',\n])\n\n// Sandbox Config (matches SandboxConfigData in config.ts)\nexport const SandboxConfigDataSchema = z.object({\n enabled: z.boolean(),\n filesystem: z\n .object({\n writeAllowed: z.array(z.string()).optional(),\n readAllowed: z.array(z.string()).optional(),\n denied: z.array(z.string()).optional(),\n })\n .optional(),\n network: z\n .object({\n allowedDomains: z.array(z.string()).optional(),\n promptForNewDomains: z.boolean().optional(),\n blockAll: z.boolean().optional(),\n })\n .optional(),\n process: z\n .object({\n excludedCommands: z.array(z.string()).optional(),\n maxExecutionTime: z.number().optional(),\n })\n .optional(),\n})\n\n// Model Profile\nexport const ModelProfileSchema = z.object({\n name: z.string(),\n provider: ProviderTypeSchema,\n modelName: z.string(),\n baseURL: z.string().optional(),\n apiKey: z.string(),\n maxTokens: z.number(),\n contextLength: z.number(),\n reasoningEffort: ReasoningEffortSchema.optional(),\n isActive: z.boolean(),\n createdAt: z.number(),\n lastUsed: z.number().optional(),\n isGPT5: z.boolean().optional(),\n validationStatus: z\n .enum(['valid', 'needs_repair', 'auto_repaired'])\n .optional(),\n lastValidation: z.number().optional(),\n})\n\n// Model Pointer Type\nexport const ModelPointerTypeSchema = z.enum([\n 'main',\n 'task',\n 'reasoning',\n 'quick',\n 'compact',\n])\n\n// Model Pointers\nexport const ModelPointersSchema = z.object({\n main: z.string(),\n task: z.string(),\n reasoning: z.string(),\n quick: z.string(),\n compact: z.string(),\n})\n\n// Account Info\nexport const AccountInfoSchema = z.object({\n accountUuid: z.string(),\n emailAddress: z.string(),\n organizationUuid: z.string().optional(),\n})\n\n// Project Configuration \u2014 passthrough to never reject unknown fields\nexport const ProjectConfigSchema = z\n .object({\n allowedTools: z.array(z.string()),\n context: z.record(z.string()),\n contextFiles: z.array(z.string()).optional(),\n history: z.array(z.string()),\n dontCrawlDirectory: z.boolean().optional(),\n enableArchitectTool: z.boolean().optional(),\n mcpContextUris: z.array(z.string()),\n mcpServers: z.record(McpServerConfigSchema).optional(),\n approvedMcprcServers: z.array(z.string()).optional(),\n rejectedMcprcServers: z.array(z.string()).optional(),\n lastAPIDuration: z.number().optional(),\n lastCost: z.number().optional(),\n lastDuration: z.number().optional(),\n lastSessionId: z.string().optional(),\n exampleFiles: z.array(z.string()).optional(),\n exampleFilesGeneratedAt: z.number().optional(),\n hasTrustDialogAccepted: z.boolean().optional(),\n hasCompletedProjectOnboarding: z.boolean().optional(),\n sandbox: SandboxConfigDataSchema.optional(),\n })\n .passthrough()\n\n// Global Configuration \u2014 passthrough to never reject unknown fields\nexport const GlobalConfigSchema = z\n .object({\n projects: z.record(ProjectConfigSchema).optional(),\n numStartups: z.number(),\n autoUpdaterStatus: AutoUpdaterStatusSchema.optional(),\n userID: z.string().optional(),\n theme: ThemeNamesSchema,\n hasCompletedOnboarding: z.boolean().optional(),\n lastOnboardingVersion: z.string().optional(),\n lastReleaseNotesSeen: z.string().optional(),\n mcpServers: z.record(McpServerConfigSchema).optional(),\n preferredNotifChannel: NotificationChannelSchema,\n verbose: z.boolean(),\n customApiKeyResponses: z\n .object({\n approved: z.array(z.string()).optional(),\n rejected: z.array(z.string()).optional(),\n })\n .optional(),\n primaryProvider: ProviderTypeSchema.optional(),\n maxTokens: z.number().optional(),\n hasAcknowledgedCostThreshold: z.boolean().optional(),\n oauthAccount: AccountInfoSchema.optional(),\n iterm2KeyBindingInstalled: z.boolean().optional(),\n shiftEnterKeyBindingInstalled: z.boolean().optional(),\n proxy: z.string().optional(),\n stream: z.boolean().optional(),\n modelProfiles: z.array(ModelProfileSchema).optional(),\n modelPointers: ModelPointersSchema.optional(),\n defaultModelName: z.string().optional(),\n lastDismissedUpdateVersion: z.string().optional(),\n compressionMode: CompressionModeSchema.optional(),\n thinking: z.boolean().optional(),\n language: UILanguageSchema.optional(),\n safetyMode: SafetyModeSchema.optional(),\n // Deprecated fields \u2014 accepted but not used\n safeMode: z.boolean().optional(),\n displayMode: z.enum(['minimal', 'compact', 'detailed']).optional(),\n // Claude Code sync\n autoSyncClaudeCode: z.boolean().optional(),\n // File backup for /undo\n backupEnabled: z.boolean().optional(),\n // Config version for migrations\n configVersion: z.number().optional(),\n // Enable experimental memory tools\n enableMemoryTools: z.boolean().optional(),\n // Output style selection\n outputStyle: z.string().optional(),\n // Auto-memory: extract key decisions during auto-compact\n autoMemory: z.boolean().optional(),\n // Sandbox config\n sandbox: SandboxConfigDataSchema.optional(),\n })\n .passthrough()\n\n// Type exports\nexport type McpStdioServerConfig = z.infer<typeof McpStdioServerConfigSchema>\nexport type McpSSEServerConfig = z.infer<typeof McpSSEServerConfigSchema>\nexport type McpHTTPServerConfig = z.infer<typeof McpHTTPServerConfigSchema>\nexport type McpServerConfig = z.infer<typeof McpServerConfigSchema>\nexport type AutoUpdaterStatus = z.infer<typeof AutoUpdaterStatusSchema>\nexport type NotificationChannel = z.infer<typeof NotificationChannelSchema>\nexport type ProviderType = z.infer<typeof ProviderTypeSchema>\nexport type CompressionMode = z.infer<typeof CompressionModeSchema>\nexport type UILanguage = z.infer<typeof UILanguageSchema>\nexport type SafetyMode = z.infer<typeof SafetyModeSchema>\nexport type ReasoningEffort = z.infer<typeof ReasoningEffortSchema>\nexport type SandboxConfigData = z.infer<typeof SandboxConfigDataSchema>\nexport type ModelProfile = z.infer<typeof ModelProfileSchema>\nexport type ModelPointerType = z.infer<typeof ModelPointerTypeSchema>\nexport type ModelPointers = z.infer<typeof ModelPointersSchema>\nexport type AccountInfo = z.infer<typeof AccountInfoSchema>\nexport type ProjectConfig = z.infer<typeof ProjectConfigSchema>\nexport type GlobalConfig = z.infer<typeof GlobalConfigSchema>\n\n// Validation utilities\nexport function safeValidateGlobalConfig(config: unknown): {\n success: boolean\n data?: GlobalConfig\n errors?: z.ZodError\n} {\n const result = GlobalConfigSchema.safeParse(config)\n return result.success\n ? { success: true, data: result.data }\n : { success: false, errors: result.error }\n}\n\nexport function safeValidateProjectConfig(config: unknown): {\n success: boolean\n data?: ProjectConfig\n errors?: z.ZodError\n} {\n const result = ProjectConfigSchema.safeParse(config)\n return result.success\n ? { success: true, data: result.data }\n : { success: false, errors: result.error }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * Configuration Schema Definitions (Zod)\n *\n * Preserved from src/core/config/schema.ts for future Zod validation integration.\n * These schemas define the canonical shape of Minto configuration.\n * Used by Phase 3 config hardening to add runtime validation.\n */\n\nimport { z } from 'zod'\n\n// Theme Names (matches src/utils/theme.ts)\nexport const ThemeNamesSchema = z.enum([\n 'dark',\n 'light',\n 'light-daltonized',\n 'dark-daltonized',\n])\n\n// MCP Server Configurations\nexport const McpStdioServerConfigSchema = z.object({\n type: z.literal('stdio').optional().default('stdio'),\n command: z.string(),\n args: z.array(z.string()),\n env: z.record(z.string()).optional(),\n enabled: z.boolean().optional(),\n})\n\nexport const McpSSEServerConfigSchema = z.object({\n type: z.literal('sse'),\n url: z.string(),\n enabled: z.boolean().optional(),\n})\n\nexport const McpHTTPServerConfigSchema = z.object({\n type: z.literal('http'),\n url: z.string(),\n headers: z.record(z.string()).optional(),\n enabled: z.boolean().optional(),\n})\n\nexport const McpServerConfigSchema = z.union([\n McpStdioServerConfigSchema,\n McpSSEServerConfigSchema,\n McpHTTPServerConfigSchema,\n])\n\n// Auto Updater Status\nexport const AutoUpdaterStatusSchema = z.enum([\n 'disabled',\n 'enabled',\n 'no_permissions',\n 'not_configured',\n])\n\n// Notification Channel\nexport const NotificationChannelSchema = z.enum([\n 'iterm2',\n 'terminal_bell',\n 'iterm2_with_bell',\n 'notifications_disabled',\n])\n\n// Provider Types\nexport const ProviderTypeSchema = z.enum([\n 'anthropic',\n 'openai',\n 'mistral',\n 'deepseek',\n 'kimi',\n 'qwen',\n 'glm',\n 'minimax',\n 'baidu-qianfan',\n 'siliconflow',\n 'bigdream',\n 'opendev',\n 'xai',\n 'groq',\n 'gemini',\n 'ollama',\n 'azure',\n 'custom',\n 'custom-openai',\n])\n\n// Compression Mode\nexport const CompressionModeSchema = z.enum(['business', 'code'])\n\n// UI Language\nexport const UILanguageSchema = z.enum(['en', 'zh-CN'])\n\n// Safety Mode\nexport const SafetyModeSchema = z.enum(['yolo', 'smart', 'strict', 'free'])\n\n// Reasoning Effort\nexport const ReasoningEffortSchema = z.enum([\n 'minimal',\n 'low',\n 'medium',\n 'high',\n])\n\n// Sandbox Config (matches SandboxConfigData in config.ts)\nexport const SandboxConfigDataSchema = z.object({\n enabled: z.boolean(),\n filesystem: z\n .object({\n writeAllowed: z.array(z.string()).optional(),\n readAllowed: z.array(z.string()).optional(),\n denied: z.array(z.string()).optional(),\n })\n .optional(),\n network: z\n .object({\n allowedDomains: z.array(z.string()).optional(),\n promptForNewDomains: z.boolean().optional(),\n blockAll: z.boolean().optional(),\n })\n .optional(),\n process: z\n .object({\n excludedCommands: z.array(z.string()).optional(),\n maxExecutionTime: z.number().optional(),\n })\n .optional(),\n})\n\n// Model Profile\nexport const ModelProfileSchema = z.object({\n name: z.string(),\n provider: ProviderTypeSchema,\n modelName: z.string(),\n baseURL: z.string().optional(),\n apiKey: z.string().optional().default(''),\n maxTokens: z.number(),\n contextLength: z.number(),\n reasoningEffort: ReasoningEffortSchema.optional(),\n isActive: z.boolean(),\n createdAt: z.number(),\n lastUsed: z.number().optional(),\n isGPT5: z.boolean().optional(),\n validationStatus: z\n .enum(['valid', 'needs_repair', 'auto_repaired'])\n .optional(),\n lastValidation: z.number().optional(),\n})\n\n// Model Pointer Type\nexport const ModelPointerTypeSchema = z.enum([\n 'main',\n 'task',\n 'reasoning',\n 'quick',\n 'compact',\n])\n\n// Model Pointers\nexport const ModelPointersSchema = z.object({\n main: z.string(),\n task: z.string(),\n reasoning: z.string(),\n quick: z.string(),\n compact: z.string(),\n})\n\n// Account Info\nexport const AccountInfoSchema = z.object({\n accountUuid: z.string(),\n emailAddress: z.string(),\n organizationUuid: z.string().optional(),\n})\n\n// Project Configuration \u2014 passthrough to never reject unknown fields\nexport const ProjectConfigSchema = z\n .object({\n allowedTools: z.array(z.string()),\n context: z.record(z.string()),\n contextFiles: z.array(z.string()).optional(),\n history: z.array(z.string()),\n dontCrawlDirectory: z.boolean().optional(),\n enableArchitectTool: z.boolean().optional(),\n mcpContextUris: z.array(z.string()),\n mcpServers: z.record(McpServerConfigSchema).optional(),\n approvedMcprcServers: z.array(z.string()).optional(),\n rejectedMcprcServers: z.array(z.string()).optional(),\n lastAPIDuration: z.number().optional(),\n lastCost: z.number().optional(),\n lastDuration: z.number().optional(),\n lastSessionId: z.string().optional(),\n exampleFiles: z.array(z.string()).optional(),\n exampleFilesGeneratedAt: z.number().optional(),\n hasTrustDialogAccepted: z.boolean().optional(),\n hasCompletedProjectOnboarding: z.boolean().optional(),\n sandbox: SandboxConfigDataSchema.optional(),\n })\n .passthrough()\n\n// Global Configuration \u2014 passthrough to never reject unknown fields\nexport const GlobalConfigSchema = z\n .object({\n projects: z.record(ProjectConfigSchema).optional(),\n numStartups: z.number(),\n autoUpdaterStatus: AutoUpdaterStatusSchema.optional(),\n userID: z.string().optional(),\n theme: ThemeNamesSchema,\n hasCompletedOnboarding: z.boolean().optional(),\n lastOnboardingVersion: z.string().optional(),\n lastReleaseNotesSeen: z.string().optional(),\n mcpServers: z.record(McpServerConfigSchema).optional(),\n preferredNotifChannel: NotificationChannelSchema,\n verbose: z.boolean(),\n customApiKeyResponses: z\n .object({\n approved: z.array(z.string()).optional(),\n rejected: z.array(z.string()).optional(),\n })\n .optional(),\n primaryProvider: ProviderTypeSchema.optional(),\n maxTokens: z.number().optional(),\n hasAcknowledgedCostThreshold: z.boolean().optional(),\n oauthAccount: AccountInfoSchema.optional(),\n iterm2KeyBindingInstalled: z.boolean().optional(),\n shiftEnterKeyBindingInstalled: z.boolean().optional(),\n proxy: z.string().optional(),\n stream: z.boolean().optional(),\n modelProfiles: z.array(ModelProfileSchema).optional(),\n modelPointers: ModelPointersSchema.optional(),\n defaultModelName: z.string().optional(),\n lastDismissedUpdateVersion: z.string().optional(),\n compressionMode: CompressionModeSchema.optional(),\n thinking: z.boolean().optional(),\n language: UILanguageSchema.optional(),\n safetyMode: SafetyModeSchema.optional(),\n // Deprecated fields \u2014 accepted but not used\n safeMode: z.boolean().optional(),\n displayMode: z.enum(['minimal', 'compact', 'detailed']).optional(),\n // Claude Code sync\n autoSyncClaudeCode: z.boolean().optional(),\n // File backup for /undo\n backupEnabled: z.boolean().optional(),\n // Config version for migrations\n configVersion: z.number().optional(),\n // Enable experimental memory tools\n enableMemoryTools: z.boolean().optional(),\n // Output style selection\n outputStyle: z.string().optional(),\n // Auto-memory: extract key decisions during auto-compact\n autoMemory: z.boolean().optional(),\n // Sandbox config\n sandbox: SandboxConfigDataSchema.optional(),\n // Agent Teams (experimental multi-agent collaboration)\n enableAgentTeams: z.boolean().optional(),\n // Teammate display mode: auto-detect, in-process, or tmux\n teammateMode: z.enum(['auto', 'in-process', 'tmux']).optional(),\n // Bash output summarization: use quick model to summarize large outputs\n bashOutputSummarization: z.boolean().optional(),\n // Session memory: inject previous session summaries into new sessions\n enableSessionMemory: z.boolean().optional(),\n // Topic detection: pre-flight check to detect conversation topic changes\n enableTopicDetection: z.boolean().optional(),\n })\n .passthrough()\n\n// Type exports\nexport type McpStdioServerConfig = z.infer<typeof McpStdioServerConfigSchema>\nexport type McpSSEServerConfig = z.infer<typeof McpSSEServerConfigSchema>\nexport type McpHTTPServerConfig = z.infer<typeof McpHTTPServerConfigSchema>\nexport type McpServerConfig = z.infer<typeof McpServerConfigSchema>\nexport type AutoUpdaterStatus = z.infer<typeof AutoUpdaterStatusSchema>\nexport type NotificationChannel = z.infer<typeof NotificationChannelSchema>\nexport type ProviderType = z.infer<typeof ProviderTypeSchema>\nexport type CompressionMode = z.infer<typeof CompressionModeSchema>\nexport type UILanguage = z.infer<typeof UILanguageSchema>\nexport type SafetyMode = z.infer<typeof SafetyModeSchema>\nexport type ReasoningEffort = z.infer<typeof ReasoningEffortSchema>\nexport type SandboxConfigData = z.infer<typeof SandboxConfigDataSchema>\nexport type ModelProfile = z.infer<typeof ModelProfileSchema>\nexport type ModelPointerType = z.infer<typeof ModelPointerTypeSchema>\nexport type ModelPointers = z.infer<typeof ModelPointersSchema>\nexport type AccountInfo = z.infer<typeof AccountInfoSchema>\nexport type ProjectConfig = z.infer<typeof ProjectConfigSchema>\nexport type GlobalConfig = z.infer<typeof GlobalConfigSchema>\n\n// Validation utilities\nexport function safeValidateGlobalConfig(config: unknown): {\n success: boolean\n data?: GlobalConfig\n errors?: z.ZodError\n} {\n const result = GlobalConfigSchema.safeParse(config)\n return result.success\n ? { success: true, data: result.data }\n : { success: false, errors: result.error }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,4 +1,5 @@
1
1
  import { EncryptedFileStore } from "./EncryptedFileStore.js";
2
+ import * as secureKeyStorage from "../secureKeyStorage.js";
2
3
  let store = null;
3
4
  const SERVICE_NAME = "minto-api";
4
5
  function getCredentialStore() {
@@ -11,12 +12,25 @@ function resetCredentialStore() {
11
12
  store = null;
12
13
  }
13
14
  async function getApiKey(modelName) {
15
+ try {
16
+ const key = secureKeyStorage.getApiKey(`${SERVICE_NAME}:${modelName}`);
17
+ if (key) return key;
18
+ } catch {
19
+ }
14
20
  return getCredentialStore().get(SERVICE_NAME, modelName);
15
21
  }
16
22
  async function setApiKey(modelName, apiKey) {
23
+ try {
24
+ secureKeyStorage.storeApiKey(`${SERVICE_NAME}:${modelName}`, apiKey);
25
+ } catch {
26
+ }
17
27
  return getCredentialStore().set(SERVICE_NAME, modelName, apiKey);
18
28
  }
19
29
  async function deleteApiKey(modelName) {
30
+ try {
31
+ secureKeyStorage.deleteApiKey(`${SERVICE_NAME}:${modelName}`);
32
+ } catch {
33
+ }
20
34
  return getCredentialStore().delete(SERVICE_NAME, modelName);
21
35
  }
22
36
  async function findAllApiKeys() {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/utils/credentials/index.ts"],
4
- "sourcesContent": ["import { EncryptedFileStore } from './EncryptedFileStore'\nimport type { CredentialStore } from './CredentialStore'\n\n// Current credential store implementation (using encrypted files)\n// In Phase 2, this can be extended to support keytar for native OS keychains\nlet store: CredentialStore | null = null\n\nconst SERVICE_NAME = 'minto-api'\n\n/**\n * Get the current credential store instance\n * Currently uses encrypted file storage; will be extended to support keytar in Phase 2\n */\nexport function getCredentialStore(): CredentialStore {\n if (!store) {\n store = new EncryptedFileStore()\n }\n return store\n}\n\n/**\n * Reset the credential store (primarily for testing)\n */\nexport function resetCredentialStore(): void {\n store = null\n}\n\n/**\n * Retrieve an API key for a specific model from the credential store.\n * Returns null if the key is not found.\n *\n * @param modelName The name of the model to retrieve the API key for\n * @returns The API key or null if not stored in credential store\n */\nexport async function getApiKey(modelName: string): Promise<string | null> {\n return getCredentialStore().get(SERVICE_NAME, modelName)\n}\n\n/**\n * Store an API key for a specific model in the credential store.\n * This stores the key securely in encrypted storage.\n *\n * @param modelName The name of the model\n * @param apiKey The API key to store\n */\nexport async function setApiKey(\n modelName: string,\n apiKey: string,\n): Promise<void> {\n return getCredentialStore().set(SERVICE_NAME, modelName, apiKey)\n}\n\n/**\n * Delete an API key for a specific model from the credential store.\n *\n * @param modelName The name of the model\n */\nexport async function deleteApiKey(modelName: string): Promise<void> {\n return getCredentialStore().delete(SERVICE_NAME, modelName)\n}\n\n/**\n * Find all stored API keys for the service\n *\n * @returns Array of model names and their API keys\n */\nexport async function findAllApiKeys(): Promise<\n { modelName: string; apiKey: string }[]\n> {\n const credentials = await getCredentialStore().findCredentials(SERVICE_NAME)\n return credentials.map(({ account, password }) => ({\n modelName: account,\n apiKey: password,\n }))\n}\n"],
5
- "mappings": "AAAA,SAAS,0BAA0B;AAKnC,IAAI,QAAgC;AAEpC,MAAM,eAAe;AAMd,SAAS,qBAAsC;AACpD,MAAI,CAAC,OAAO;AACV,YAAQ,IAAI,mBAAmB;AAAA,EACjC;AACA,SAAO;AACT;AAKO,SAAS,uBAA6B;AAC3C,UAAQ;AACV;AASA,eAAsB,UAAU,WAA2C;AACzE,SAAO,mBAAmB,EAAE,IAAI,cAAc,SAAS;AACzD;AASA,eAAsB,UACpB,WACA,QACe;AACf,SAAO,mBAAmB,EAAE,IAAI,cAAc,WAAW,MAAM;AACjE;AAOA,eAAsB,aAAa,WAAkC;AACnE,SAAO,mBAAmB,EAAE,OAAO,cAAc,SAAS;AAC5D;AAOA,eAAsB,iBAEpB;AACA,QAAM,cAAc,MAAM,mBAAmB,EAAE,gBAAgB,YAAY;AAC3E,SAAO,YAAY,IAAI,CAAC,EAAE,SAAS,SAAS,OAAO;AAAA,IACjD,WAAW;AAAA,IACX,QAAQ;AAAA,EACV,EAAE;AACJ;",
4
+ "sourcesContent": ["import { EncryptedFileStore } from './EncryptedFileStore'\nimport type { CredentialStore } from './CredentialStore'\nimport * as secureKeyStorage from '../secureKeyStorage'\n\n// Credential store with keychain support on macOS.\n// Uses secureKeyStorage (keychain + encrypted file fallback) as primary,\n// with EncryptedFileStore as the secondary implementation for the CredentialStore interface.\nlet store: CredentialStore | null = null\n\nconst SERVICE_NAME = 'minto-api'\n\n/**\n * Get the current credential store instance.\n * Uses EncryptedFileStore for the CredentialStore interface.\n */\nexport function getCredentialStore(): CredentialStore {\n if (!store) {\n store = new EncryptedFileStore()\n }\n return store\n}\n\n/**\n * Reset the credential store (primarily for testing)\n */\nexport function resetCredentialStore(): void {\n store = null\n}\n\n/**\n * Retrieve an API key for a specific model.\n * Tries secureKeyStorage (keychain on macOS) first, falls back to EncryptedFileStore.\n *\n * @param modelName The name of the model to retrieve the API key for\n * @returns The API key or null if not found\n */\nexport async function getApiKey(modelName: string): Promise<string | null> {\n // Try secureKeyStorage first (uses keychain on macOS, encrypted file fallback)\n try {\n const key = secureKeyStorage.getApiKey(`${SERVICE_NAME}:${modelName}`)\n if (key) return key\n } catch {\n // Keychain unavailable, fall through to EncryptedFileStore\n }\n return getCredentialStore().get(SERVICE_NAME, modelName)\n}\n\n/**\n * Store an API key for a specific model.\n * Stores in both secureKeyStorage and EncryptedFileStore for redundancy.\n *\n * @param modelName The name of the model\n * @param apiKey The API key to store\n */\nexport async function setApiKey(\n modelName: string,\n apiKey: string,\n): Promise<void> {\n // Store in secureKeyStorage (keychain on macOS, encrypted file fallback)\n try {\n secureKeyStorage.storeApiKey(`${SERVICE_NAME}:${modelName}`, apiKey)\n } catch {\n // Best-effort \u2014 fall through to EncryptedFileStore\n }\n return getCredentialStore().set(SERVICE_NAME, modelName, apiKey)\n}\n\n/**\n * Delete an API key for a specific model from all stores.\n *\n * @param modelName The name of the model\n */\nexport async function deleteApiKey(modelName: string): Promise<void> {\n // Remove from secureKeyStorage\n try {\n secureKeyStorage.deleteApiKey(`${SERVICE_NAME}:${modelName}`)\n } catch {\n // Best-effort\n }\n return getCredentialStore().delete(SERVICE_NAME, modelName)\n}\n\n/**\n * Find all stored API keys for the service\n *\n * @returns Array of model names and their API keys\n */\nexport async function findAllApiKeys(): Promise<\n { modelName: string; apiKey: string }[]\n> {\n const credentials = await getCredentialStore().findCredentials(SERVICE_NAME)\n return credentials.map(({ account, password }) => ({\n modelName: account,\n apiKey: password,\n }))\n}\n"],
5
+ "mappings": "AAAA,SAAS,0BAA0B;AAEnC,YAAY,sBAAsB;AAKlC,IAAI,QAAgC;AAEpC,MAAM,eAAe;AAMd,SAAS,qBAAsC;AACpD,MAAI,CAAC,OAAO;AACV,YAAQ,IAAI,mBAAmB;AAAA,EACjC;AACA,SAAO;AACT;AAKO,SAAS,uBAA6B;AAC3C,UAAQ;AACV;AASA,eAAsB,UAAU,WAA2C;AAEzE,MAAI;AACF,UAAM,MAAM,iBAAiB,UAAU,GAAG,YAAY,IAAI,SAAS,EAAE;AACrE,QAAI,IAAK,QAAO;AAAA,EAClB,QAAQ;AAAA,EAER;AACA,SAAO,mBAAmB,EAAE,IAAI,cAAc,SAAS;AACzD;AASA,eAAsB,UACpB,WACA,QACe;AAEf,MAAI;AACF,qBAAiB,YAAY,GAAG,YAAY,IAAI,SAAS,IAAI,MAAM;AAAA,EACrE,QAAQ;AAAA,EAER;AACA,SAAO,mBAAmB,EAAE,IAAI,cAAc,WAAW,MAAM;AACjE;AAOA,eAAsB,aAAa,WAAkC;AAEnE,MAAI;AACF,qBAAiB,aAAa,GAAG,YAAY,IAAI,SAAS,EAAE;AAAA,EAC9D,QAAQ;AAAA,EAER;AACA,SAAO,mBAAmB,EAAE,OAAO,cAAc,SAAS;AAC5D;AAOA,eAAsB,iBAEpB;AACA,QAAM,cAAc,MAAM,mBAAmB,EAAE,gBAAgB,YAAY;AAC3E,SAAO,YAAY,IAAI,CAAC,EAAE,SAAS,SAAS,OAAO;AAAA,IACjD,WAAW;AAAA,IACX,QAAQ;AAAA,EACV,EAAE;AACJ;",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,24 @@
1
+ import { existsSync } from "fs";
2
+ import { join } from "path";
3
+ function resolveDualPaths(baseDirs, subpath) {
4
+ const results = [];
5
+ for (const baseDir of baseDirs) {
6
+ const mintoPath = join(baseDir, ".minto", subpath);
7
+ const claudePath = join(baseDir, ".claude", subpath);
8
+ if (existsSync(claudePath)) results.unshift(claudePath);
9
+ if (existsSync(mintoPath)) results.unshift(mintoPath);
10
+ }
11
+ return results;
12
+ }
13
+ function resolveFirstDualPath(baseDir, subpath) {
14
+ const mintoPath = join(baseDir, ".minto", subpath);
15
+ if (existsSync(mintoPath)) return mintoPath;
16
+ const claudePath = join(baseDir, ".claude", subpath);
17
+ if (existsSync(claudePath)) return claudePath;
18
+ return null;
19
+ }
20
+ export {
21
+ resolveDualPaths,
22
+ resolveFirstDualPath
23
+ };
24
+ //# sourceMappingURL=dualPath.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/utils/dualPath.ts"],
4
+ "sourcesContent": ["import { existsSync } from 'fs'\nimport { join } from 'path'\n\n/**\n * Resolve paths across .minto (primary) and .claude (fallback) directories.\n * Returns all existing paths in priority order (highest first).\n */\nexport function resolveDualPaths(\n baseDirs: string[],\n subpath: string,\n): string[] {\n const results: string[] = []\n // Process in reverse so higher-priority dirs are checked last and appear first\n for (const baseDir of baseDirs) {\n const mintoPath = join(baseDir, '.minto', subpath)\n const claudePath = join(baseDir, '.claude', subpath)\n if (existsSync(claudePath)) results.unshift(claudePath)\n if (existsSync(mintoPath)) results.unshift(mintoPath)\n }\n return results\n}\n\n/**\n * Resolve the first existing path, checking .minto before .claude.\n */\nexport function resolveFirstDualPath(\n baseDir: string,\n subpath: string,\n): string | null {\n const mintoPath = join(baseDir, '.minto', subpath)\n if (existsSync(mintoPath)) return mintoPath\n const claudePath = join(baseDir, '.claude', subpath)\n if (existsSync(claudePath)) return claudePath\n return null\n}\n"],
5
+ "mappings": "AAAA,SAAS,kBAAkB;AAC3B,SAAS,YAAY;AAMd,SAAS,iBACd,UACA,SACU;AACV,QAAM,UAAoB,CAAC;AAE3B,aAAW,WAAW,UAAU;AAC9B,UAAM,YAAY,KAAK,SAAS,UAAU,OAAO;AACjD,UAAM,aAAa,KAAK,SAAS,WAAW,OAAO;AACnD,QAAI,WAAW,UAAU,EAAG,SAAQ,QAAQ,UAAU;AACtD,QAAI,WAAW,SAAS,EAAG,SAAQ,QAAQ,SAAS;AAAA,EACtD;AACA,SAAO;AACT;AAKO,SAAS,qBACd,SACA,SACe;AACf,QAAM,YAAY,KAAK,SAAS,UAAU,OAAO;AACjD,MAAI,WAAW,SAAS,EAAG,QAAO;AAClC,QAAM,aAAa,KAAK,SAAS,WAAW,OAAO;AACnD,MAAI,WAAW,UAAU,EAAG,QAAO;AACnC,SAAO;AACT;",
6
+ "names": []
7
+ }
@@ -1,6 +1,25 @@
1
1
  import { PersistentShell } from "./PersistentShell.js";
2
2
  import { shutdownMCPClients } from "../services/mcpClient.js";
3
+ import { disbandAllTeams } from "../services/agentTeams/teamManager.js";
4
+ import { debug as debugLogger } from "./debugLogger.js";
5
+ import { runCleanupHandlers } from "./globalErrorHandler.js";
3
6
  let isShuttingDown = false;
7
+ const trackedChildPids = /* @__PURE__ */ new Set();
8
+ function registerChildPid(pid) {
9
+ trackedChildPids.add(pid);
10
+ }
11
+ function unregisterChildPid(pid) {
12
+ trackedChildPids.delete(pid);
13
+ }
14
+ function killTrackedChildren() {
15
+ for (const pid of trackedChildPids) {
16
+ try {
17
+ process.kill(pid, "SIGTERM");
18
+ } catch {
19
+ }
20
+ }
21
+ trackedChildPids.clear();
22
+ }
4
23
  function resetCursor() {
5
24
  const cursorShow = "\x1B[?25h";
6
25
  const terminal = process.stderr.isTTY ? process.stderr : process.stdout.isTTY ? process.stdout : void 0;
@@ -13,16 +32,45 @@ async function gracefulExit(code = 0) {
13
32
  isShuttingDown = true;
14
33
  try {
15
34
  resetCursor();
16
- } catch {
35
+ } catch (e) {
36
+ debugLogger.trace("EXIT_CLEANUP_ERROR", { phase: "resetCursor", error: e });
17
37
  }
18
38
  try {
19
39
  PersistentShell.getInstance().close();
20
- } catch {
40
+ } catch (e) {
41
+ debugLogger.trace("EXIT_CLEANUP_ERROR", {
42
+ phase: "PersistentShell.close",
43
+ error: e
44
+ });
21
45
  }
22
46
  try {
23
- await shutdownMCPClients();
24
- } catch {
47
+ await runCleanupHandlers();
48
+ } catch (e) {
49
+ debugLogger.trace("EXIT_CLEANUP_ERROR", {
50
+ phase: "runCleanupHandlers",
51
+ error: e
52
+ });
25
53
  }
54
+ try {
55
+ disbandAllTeams();
56
+ } catch (e) {
57
+ debugLogger.trace("EXIT_CLEANUP_ERROR", {
58
+ phase: "disbandAllTeams",
59
+ error: e
60
+ });
61
+ }
62
+ try {
63
+ await Promise.race([
64
+ shutdownMCPClients(),
65
+ new Promise((resolve) => setTimeout(resolve, 5e3))
66
+ ]);
67
+ } catch (e) {
68
+ debugLogger.trace("EXIT_CLEANUP_ERROR", {
69
+ phase: "shutdownMCPClients",
70
+ error: e
71
+ });
72
+ }
73
+ killTrackedChildren();
26
74
  process.exit(code);
27
75
  }
28
76
  function setupExitHandlers() {
@@ -38,12 +86,21 @@ function setupExitHandlers() {
38
86
  process.on("exit", () => {
39
87
  try {
40
88
  resetCursor();
41
- } catch {
89
+ } catch (e) {
90
+ debugLogger.trace("EXIT_CLEANUP_ERROR", {
91
+ phase: "onExit.resetCursor",
92
+ error: e
93
+ });
42
94
  }
43
95
  try {
44
96
  PersistentShell.getInstance().close();
45
- } catch {
97
+ } catch (e) {
98
+ debugLogger.trace("EXIT_CLEANUP_ERROR", {
99
+ phase: "onExit.PersistentShell.close",
100
+ error: e
101
+ });
46
102
  }
103
+ killTrackedChildren();
47
104
  });
48
105
  process.on("unhandledRejection", (err) => {
49
106
  const isTimeoutError = err instanceof Error && (err.name === "TimeoutError" || err.message?.includes("timed out") || err.message?.includes("timeout"));
@@ -68,6 +125,8 @@ function setupExitHandlers() {
68
125
  }
69
126
  export {
70
127
  gracefulExit,
71
- setupExitHandlers
128
+ registerChildPid,
129
+ setupExitHandlers,
130
+ unregisterChildPid
72
131
  };
73
132
  //# sourceMappingURL=exit.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/utils/exit.ts"],
4
- "sourcesContent": ["/**\n * Graceful exit utilities\n *\n * Provides a centralized way to exit the application gracefully,\n * ensuring resources are cleaned up properly.\n *\n * NOTE: Cost summary is now handled by useCostSummary() in cost-tracker.ts\n * which matches Kode-cli's implementation exactly.\n */\n\nimport { PersistentShell } from './PersistentShell'\nimport { shutdownMCPClients } from '../services/mcpClient'\n\n// Track if we're already shutting down to prevent multiple cleanup attempts\nlet isShuttingDown = false\n\n/**\n * Reset cursor visibility\n */\nfunction resetCursor() {\n const cursorShow = '\\x1B[?25h'\n const terminal = process.stderr.isTTY\n ? process.stderr\n : process.stdout.isTTY\n ? process.stdout\n : undefined\n terminal?.write(`\\u001B[?25h${cursorShow}`)\n}\n\n/**\n * Exit gracefully with proper cleanup\n *\n * NOTE: Cost summary is NOT printed here. It's handled by useCostSummary()\n * hook's process.on('exit') handler, matching Kode-cli's pattern.\n *\n * @param code Exit code (default: 0)\n */\nexport async function gracefulExit(code = 0): Promise<void> {\n if (isShuttingDown) {\n return\n }\n isShuttingDown = true\n\n try {\n resetCursor()\n } catch {}\n\n try {\n PersistentShell.getInstance().close()\n } catch {}\n\n try {\n await shutdownMCPClients()\n } catch {}\n\n process.exit(code)\n}\n\n/**\n * Setup exit handlers for various signals and events\n * Should be called once during application initialization\n *\n * NOTE: Cost summary output is handled by useCostSummary() in cost-tracker.ts,\n * NOT here. This matches Kode-cli's architecture.\n */\nexport function setupExitHandlers(): void {\n // Handle graceful shutdown signals\n process.on('SIGINT', () => {\n gracefulExit(0)\n })\n\n process.on('SIGTERM', () => {\n gracefulExit(0)\n })\n\n // Windows CTRL+BREAK\n process.on('SIGBREAK', () => {\n gracefulExit(0)\n })\n\n // Final cleanup on exit (cost summary handled by useCostSummary)\n process.on('exit', () => {\n try {\n resetCursor()\n } catch {}\n try {\n PersistentShell.getInstance().close()\n } catch {}\n })\n\n // Handle unhandled rejections\n process.on('unhandledRejection', err => {\n // Check if this is a timeout error that we can handle gracefully\n const isTimeoutError =\n err instanceof Error &&\n (err.name === 'TimeoutError' ||\n err.message?.includes('timed out') ||\n err.message?.includes('timeout'))\n\n const isDOMTimeoutError =\n err &&\n typeof err === 'object' &&\n 'name' in err &&\n (err as { name: string }).name === 'TimeoutError'\n\n if (isTimeoutError || isDOMTimeoutError) {\n // Log timeout errors but don't exit - they're often recoverable\n console.error(\n '\u26A0\uFE0F Operation timed out:',\n err instanceof Error ? err.message : err,\n )\n console.error(\n ' The operation will be retried or skipped. You can continue working.',\n )\n return\n }\n\n // For other unhandled rejections, log and exit\n console.error('Unhandled rejection:', err)\n gracefulExit(1)\n })\n\n // Handle uncaught exceptions\n process.on('uncaughtException', err => {\n console.error('Uncaught exception:', err)\n gracefulExit(1)\n })\n}\n"],
5
- "mappings": "AAUA,SAAS,uBAAuB;AAChC,SAAS,0BAA0B;AAGnC,IAAI,iBAAiB;AAKrB,SAAS,cAAc;AACrB,QAAM,aAAa;AACnB,QAAM,WAAW,QAAQ,OAAO,QAC5B,QAAQ,SACR,QAAQ,OAAO,QACb,QAAQ,SACR;AACN,YAAU,MAAM,YAAc,UAAU,EAAE;AAC5C;AAUA,eAAsB,aAAa,OAAO,GAAkB;AAC1D,MAAI,gBAAgB;AAClB;AAAA,EACF;AACA,mBAAiB;AAEjB,MAAI;AACF,gBAAY;AAAA,EACd,QAAQ;AAAA,EAAC;AAET,MAAI;AACF,oBAAgB,YAAY,EAAE,MAAM;AAAA,EACtC,QAAQ;AAAA,EAAC;AAET,MAAI;AACF,UAAM,mBAAmB;AAAA,EAC3B,QAAQ;AAAA,EAAC;AAET,UAAQ,KAAK,IAAI;AACnB;AASO,SAAS,oBAA0B;AAExC,UAAQ,GAAG,UAAU,MAAM;AACzB,iBAAa,CAAC;AAAA,EAChB,CAAC;AAED,UAAQ,GAAG,WAAW,MAAM;AAC1B,iBAAa,CAAC;AAAA,EAChB,CAAC;AAGD,UAAQ,GAAG,YAAY,MAAM;AAC3B,iBAAa,CAAC;AAAA,EAChB,CAAC;AAGD,UAAQ,GAAG,QAAQ,MAAM;AACvB,QAAI;AACF,kBAAY;AAAA,IACd,QAAQ;AAAA,IAAC;AACT,QAAI;AACF,sBAAgB,YAAY,EAAE,MAAM;AAAA,IACtC,QAAQ;AAAA,IAAC;AAAA,EACX,CAAC;AAGD,UAAQ,GAAG,sBAAsB,SAAO;AAEtC,UAAM,iBACJ,eAAe,UACd,IAAI,SAAS,kBACZ,IAAI,SAAS,SAAS,WAAW,KACjC,IAAI,SAAS,SAAS,SAAS;AAEnC,UAAM,oBACJ,OACA,OAAO,QAAQ,YACf,UAAU,OACT,IAAyB,SAAS;AAErC,QAAI,kBAAkB,mBAAmB;AAEvC,cAAQ;AAAA,QACN;AAAA,QACA,eAAe,QAAQ,IAAI,UAAU;AAAA,MACvC;AACA,cAAQ;AAAA,QACN;AAAA,MACF;AACA;AAAA,IACF;AAGA,YAAQ,MAAM,wBAAwB,GAAG;AACzC,iBAAa,CAAC;AAAA,EAChB,CAAC;AAGD,UAAQ,GAAG,qBAAqB,SAAO;AACrC,YAAQ,MAAM,uBAAuB,GAAG;AACxC,iBAAa,CAAC;AAAA,EAChB,CAAC;AACH;",
4
+ "sourcesContent": ["/**\n * Graceful exit utilities\n *\n * Provides a centralized way to exit the application gracefully,\n * ensuring resources are cleaned up properly.\n *\n * NOTE: Cost summary is now handled by useCostSummary() in cost-tracker.ts\n * which matches Kode-cli's implementation exactly.\n */\n\nimport { PersistentShell } from './PersistentShell'\nimport { shutdownMCPClients } from '../services/mcpClient'\nimport { disbandAllTeams } from '../services/agentTeams/teamManager'\nimport { debug as debugLogger } from './debugLogger'\nimport { runCleanupHandlers } from './globalErrorHandler'\n\n// Track if we're already shutting down to prevent multiple cleanup attempts\nlet isShuttingDown = false\n\n/**\n * Track child process PIDs for synchronous cleanup on exit.\n * MCP servers and other child processes register here so they\n * can be force-killed if the process exits without graceful shutdown.\n */\nconst trackedChildPids = new Set<number>()\n\n/**\n * Register a child process PID for cleanup on exit.\n * Call this after spawning any long-lived child process (MCP servers, etc.)\n */\nexport function registerChildPid(pid: number): void {\n trackedChildPids.add(pid)\n}\n\n/**\n * Unregister a child process PID (e.g., after it exits normally).\n */\nexport function unregisterChildPid(pid: number): void {\n trackedChildPids.delete(pid)\n}\n\n/**\n * Synchronously kill all tracked child processes.\n * Safe to call from the synchronous `process.on('exit')` handler.\n */\nfunction killTrackedChildren(): void {\n for (const pid of trackedChildPids) {\n try {\n process.kill(pid, 'SIGTERM')\n } catch {\n // Process may have already exited \u2014 ignore\n }\n }\n trackedChildPids.clear()\n}\n\n/**\n * Reset cursor visibility\n */\nfunction resetCursor() {\n const cursorShow = '\\x1B[?25h'\n const terminal = process.stderr.isTTY\n ? process.stderr\n : process.stdout.isTTY\n ? process.stdout\n : undefined\n terminal?.write(`\\u001B[?25h${cursorShow}`)\n}\n\n/**\n * Exit gracefully with proper cleanup\n *\n * NOTE: Cost summary is NOT printed here. It's handled by useCostSummary()\n * hook's process.on('exit') handler, matching Kode-cli's pattern.\n *\n * @param code Exit code (default: 0)\n */\nexport async function gracefulExit(code = 0): Promise<void> {\n if (isShuttingDown) {\n return\n }\n isShuttingDown = true\n\n try {\n resetCursor()\n } catch (e) {\n debugLogger.trace('EXIT_CLEANUP_ERROR', { phase: 'resetCursor', error: e })\n }\n\n try {\n PersistentShell.getInstance().close()\n } catch (e) {\n debugLogger.trace('EXIT_CLEANUP_ERROR', {\n phase: 'PersistentShell.close',\n error: e,\n })\n }\n\n // Run registered cleanup handlers (from globalErrorHandler)\n try {\n await runCleanupHandlers()\n } catch (e) {\n debugLogger.trace('EXIT_CLEANUP_ERROR', {\n phase: 'runCleanupHandlers',\n error: e,\n })\n }\n\n // Disband all active agent teams (aborts running agent query loops)\n try {\n disbandAllTeams()\n } catch (e) {\n debugLogger.trace('EXIT_CLEANUP_ERROR', {\n phase: 'disbandAllTeams',\n error: e,\n })\n }\n\n try {\n await Promise.race([\n shutdownMCPClients(),\n new Promise<void>(resolve => setTimeout(resolve, 5000)),\n ])\n } catch (e) {\n debugLogger.trace('EXIT_CLEANUP_ERROR', {\n phase: 'shutdownMCPClients',\n error: e,\n })\n }\n\n // Kill any remaining tracked child processes (safety net)\n killTrackedChildren()\n\n process.exit(code)\n}\n\n/**\n * Setup exit handlers for various signals and events\n * Should be called once during application initialization\n *\n * NOTE: Cost summary output is handled by useCostSummary() in cost-tracker.ts,\n * NOT here. This matches Kode-cli's architecture.\n */\nexport function setupExitHandlers(): void {\n // Handle graceful shutdown signals\n process.on('SIGINT', () => {\n gracefulExit(0)\n })\n\n process.on('SIGTERM', () => {\n gracefulExit(0)\n })\n\n // Windows CTRL+BREAK\n process.on('SIGBREAK', () => {\n gracefulExit(0)\n })\n\n // Final synchronous cleanup on exit.\n // This runs AFTER process.exit() is called \u2014 only sync code works here.\n // Handles the case where process.exit() was called without going through gracefulExit().\n process.on('exit', () => {\n try {\n resetCursor()\n } catch (e) {\n debugLogger.trace('EXIT_CLEANUP_ERROR', {\n phase: 'onExit.resetCursor',\n error: e,\n })\n }\n try {\n PersistentShell.getInstance().close()\n } catch (e) {\n debugLogger.trace('EXIT_CLEANUP_ERROR', {\n phase: 'onExit.PersistentShell.close',\n error: e,\n })\n }\n // Kill any remaining child processes (MCP servers, etc.)\n killTrackedChildren()\n })\n\n // Handle unhandled rejections\n process.on('unhandledRejection', err => {\n // Check if this is a timeout error that we can handle gracefully\n const isTimeoutError =\n err instanceof Error &&\n (err.name === 'TimeoutError' ||\n err.message?.includes('timed out') ||\n err.message?.includes('timeout'))\n\n const isDOMTimeoutError =\n err &&\n typeof err === 'object' &&\n 'name' in err &&\n (err as { name: string }).name === 'TimeoutError'\n\n if (isTimeoutError || isDOMTimeoutError) {\n // Log timeout errors but don't exit - they're often recoverable\n console.error(\n '\u26A0\uFE0F Operation timed out:',\n err instanceof Error ? err.message : err,\n )\n console.error(\n ' The operation will be retried or skipped. You can continue working.',\n )\n return\n }\n\n // For other unhandled rejections, log and exit\n console.error('Unhandled rejection:', err)\n gracefulExit(1)\n })\n\n // Handle uncaught exceptions\n process.on('uncaughtException', err => {\n console.error('Uncaught exception:', err)\n gracefulExit(1)\n })\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }