@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/pluginLoader.ts"],
4
- "sourcesContent": ["/**\n * Plugin Loader\n *\n * Discovers and loads plugins from Minto plugin directories.\n *\n * Directory Priority (later overrides earlier):\n * 1. ~/.minto/plugins/ (user global)\n * 2. ./.minto/plugins/ (project - highest priority)\n */\n\nimport {\n existsSync,\n readFileSync,\n readdirSync,\n statSync,\n writeFileSync,\n mkdirSync,\n} from 'fs'\nimport { debug as debugLogger } from '@utils/debugLogger'\nimport { join, resolve, basename } from 'path'\nimport { homedir } from 'os'\nimport matter from 'gray-matter'\nimport { validatePluginDirectory } from '@services/plugins/pluginValidation'\nimport {\n PluginManifest,\n PluginManifestSchema,\n LoadedPlugin,\n LoadedAgent,\n LoadedCommand,\n LoadedSkill,\n LoadedHook,\n LoadedMCPServer,\n LoadedLSPServer,\n PluginError,\n PluginErrorCode,\n PluginSource,\n} from '../types/plugin'\nimport { getCwd } from './state'\n\n/**\n * Extra plugin directories added via --plugin-dir CLI flag\n */\nlet extraPluginDirs: string[] = []\n\n/**\n * Add extra plugin directories (from --plugin-dir CLI flag)\n * These are merged with default directories, not replacing them.\n */\nexport function addExtraPluginDir(dir: string): void {\n const resolved = resolve(dir)\n if (!extraPluginDirs.includes(resolved)) {\n extraPluginDirs.push(resolved)\n }\n}\n\n/**\n * Get managed plugins directory (read-only, enterprise)\n */\nfunction getManagedPluginsDir(): string {\n if (process.platform === 'darwin') {\n return '/Library/Application Support/Minto/managed-plugins'\n }\n return '/etc/minto/managed-plugins'\n}\n\n/**\n * Plugin discovery directories in priority order\n */\nfunction getPluginDirectories(): string[] {\n const cwd = getCwd()\n const home = homedir()\n\n return [\n getManagedPluginsDir(), // Managed (enterprise, read-only, lowest)\n join(home, '.claude', 'plugins'), // User global (legacy)\n join(home, '.minto', 'plugins'), // User global\n join(cwd, '.claude', 'plugins'), // Project (legacy)\n join(cwd, '.minto', 'plugins'), // Project\n join(cwd, '.minto', 'plugins.local'), // Project local (gitignored)\n ...extraPluginDirs, // CLI --plugin-dir (highest priority)\n ]\n}\n\n/**\n * Find all plugin directories across all sources\n */\nfunction discoverPluginPaths(): Map<string, string> {\n const pluginPaths = new Map<string, string>() // name -> path\n const directories = getPluginDirectories()\n\n for (const dir of directories) {\n if (!existsSync(dir)) continue\n\n try {\n const entries = readdirSync(dir)\n\n for (const entry of entries) {\n const pluginPath = join(dir, entry)\n\n // Must be a directory\n if (!statSync(pluginPath).isDirectory()) continue\n\n // Must have plugin.json in .minto-plugin/, .claude-plugin/, or root\n const mintoManifestPath = join(\n pluginPath,\n '.minto-plugin',\n 'plugin.json',\n )\n const claudeManifestPath = join(\n pluginPath,\n '.claude-plugin',\n 'plugin.json',\n )\n const rootManifestPath = join(pluginPath, 'plugin.json')\n if (\n !existsSync(mintoManifestPath) &&\n !existsSync(claudeManifestPath) &&\n !existsSync(rootManifestPath)\n )\n continue\n\n // Later directories override earlier ones\n pluginPaths.set(entry, pluginPath)\n }\n } catch (error) {\n // Silently ignore errors\n }\n }\n\n return pluginPaths\n}\n\n/**\n * Load and validate plugin manifest\n *\n * Manifest locations (priority order):\n * 1. .minto-plugin/plugin.json\n * 2. plugin.json (root fallback)\n */\nfunction loadManifest(pluginPath: string): PluginManifest {\n const candidates = [\n join(pluginPath, '.minto-plugin', 'plugin.json'),\n join(pluginPath, '.claude-plugin', 'plugin.json'),\n join(pluginPath, 'plugin.json'),\n ]\n\n const existing = candidates.filter(p => existsSync(p))\n\n if (existing.length === 0) {\n throw new PluginError(\n `Plugin manifest not found. Tried:\\n${candidates.map(p => ` - ${p}`).join('\\n')}`,\n PluginErrorCode.MANIFEST_NOT_FOUND,\n )\n }\n\n let lastError: unknown = null\n\n // Try each candidate in priority order; fall through on validation failure\n for (const manifestPath of existing) {\n try {\n const manifestContent = readFileSync(manifestPath, 'utf-8')\n const manifestData = JSON.parse(manifestContent)\n return PluginManifestSchema.parse(manifestData)\n } catch (error) {\n lastError = error\n // Continue to next candidate\n }\n }\n\n // All candidates failed\n throw new PluginError(\n `Invalid plugin manifest at ${existing[0]}: ${lastError instanceof Error ? lastError.message : String(lastError)}`,\n PluginErrorCode.MANIFEST_INVALID,\n undefined,\n lastError,\n )\n}\n\n/**\n * Load agents from plugin\n */\nfunction loadAgents(\n pluginPath: string,\n manifest: PluginManifest,\n): LoadedAgent[] {\n const agents: LoadedAgent[] = []\n const agentsDir = join(pluginPath, 'agents')\n\n // Load agents listed in manifest\n for (const agentPath of manifest.agents || []) {\n const fullPath = join(pluginPath, agentPath)\n\n if (!existsSync(fullPath)) {\n debugLogger.warn('PLUGIN_LOADER', `Agent file not found: ${fullPath}`)\n continue\n }\n\n try {\n const content = readFileSync(fullPath, 'utf-8')\n const { data, content: promptContent } = matter(content)\n\n agents.push({\n name: data.name || basename(agentPath, '.md'),\n filePath: fullPath,\n config: {\n name: data.name || basename(agentPath, '.md'),\n description: data.description || '',\n tools: data.tools,\n model: data.model,\n content: promptContent.trim(),\n },\n pluginName: manifest.name,\n })\n } catch (error) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Error loading agent ${agentPath}: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n }\n\n // Also scan agents/ directory if it exists\n if (existsSync(agentsDir) && statSync(agentsDir).isDirectory()) {\n const agentFiles = readdirSync(agentsDir).filter(f => f.endsWith('.md'))\n\n for (const file of agentFiles) {\n const fullPath = join(agentsDir, file)\n\n // Skip if already loaded from manifest\n if (agents.some(a => a.filePath === fullPath)) continue\n\n try {\n const content = readFileSync(fullPath, 'utf-8')\n const { data, content: promptContent } = matter(content)\n\n agents.push({\n name: data.name || basename(file, '.md'),\n filePath: fullPath,\n config: {\n name: data.name || basename(file, '.md'),\n description: data.description || '',\n tools: data.tools,\n model: data.model,\n content: promptContent.trim(),\n },\n pluginName: manifest.name,\n })\n } catch (error) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Error loading agent ${file}: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n }\n }\n\n return agents\n}\n\n/**\n * Load commands from plugin\n */\nfunction loadCommands(\n pluginPath: string,\n manifest: PluginManifest,\n): LoadedCommand[] {\n const commands: LoadedCommand[] = []\n const commandsDir = join(pluginPath, 'commands')\n\n // Load commands listed in manifest\n for (const commandPath of manifest.commands || []) {\n const fullPath = join(pluginPath, commandPath)\n\n if (!existsSync(fullPath)) {\n debugLogger.warn('PLUGIN_LOADER', `Command file not found: ${fullPath}`)\n continue\n }\n\n try {\n const content = readFileSync(fullPath, 'utf-8')\n const { data, content: commandContent } = matter(content)\n\n commands.push({\n name: data.name || basename(commandPath, '.md'),\n filePath: fullPath,\n config: {\n name: data.name || basename(commandPath, '.md'),\n description: data.description,\n aliases: data.aliases,\n enabled: data.enabled !== false,\n hidden: data.hidden === true,\n progressMessage: data.progressMessage,\n argNames: data.argNames,\n 'allowed-tools': data['allowed-tools'],\n content: commandContent.trim(),\n },\n pluginName: manifest.name,\n })\n } catch (error) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Error loading command ${commandPath}: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n }\n\n // Also scan commands/ directory if it exists\n if (existsSync(commandsDir) && statSync(commandsDir).isDirectory()) {\n const commandFiles = readdirSync(commandsDir).filter(f => f.endsWith('.md'))\n\n for (const file of commandFiles) {\n const fullPath = join(commandsDir, file)\n\n // Skip if already loaded from manifest\n if (commands.some(c => c.filePath === fullPath)) continue\n\n try {\n const content = readFileSync(fullPath, 'utf-8')\n const { data, content: commandContent } = matter(content)\n\n commands.push({\n name: data.name || basename(file, '.md'),\n filePath: fullPath,\n config: {\n name: data.name || basename(file, '.md'),\n description: data.description,\n aliases: data.aliases,\n enabled: data.enabled !== false,\n hidden: data.hidden === true,\n progressMessage: data.progressMessage,\n argNames: data.argNames,\n 'allowed-tools': data['allowed-tools'],\n content: commandContent.trim(),\n },\n pluginName: manifest.name,\n })\n } catch (error) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Error loading command ${file}: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n }\n }\n\n return commands\n}\n\n/**\n * Load skills from plugin\n *\n * Supports two patterns:\n * - Subdirectory: skills/skill-name/SKILL.md\n * - Flat: skills/skill-name.md\n */\nfunction loadSkills(\n pluginPath: string,\n manifest: PluginManifest,\n): LoadedSkill[] {\n const skills: LoadedSkill[] = []\n const skillsDir = join(pluginPath, 'skills')\n\n // Load skills listed in manifest\n for (const skillPath of manifest.skills || []) {\n const fullPath = join(pluginPath, skillPath)\n\n if (!existsSync(fullPath)) {\n debugLogger.warn('PLUGIN_LOADER', `Skill file not found: ${fullPath}`)\n continue\n }\n\n try {\n const content = readFileSync(fullPath, 'utf-8')\n const { data, content: skillContent } = matter(content)\n\n skills.push({\n name: data.name || basename(skillPath, '.md'),\n filePath: fullPath,\n config: {\n name: data.name || basename(skillPath, '.md'),\n description: data.description || '',\n content: skillContent.trim(),\n },\n pluginName: manifest.name,\n source: 'plugin',\n })\n } catch (error) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Error loading skill ${skillPath}: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n }\n\n // Auto-discover skills from skills/ directory if it exists\n if (existsSync(skillsDir) && statSync(skillsDir).isDirectory()) {\n const entries = readdirSync(skillsDir, { withFileTypes: true })\n\n for (const entry of entries) {\n // Subdirectory pattern: skill-name/SKILL.md\n if (entry.isDirectory()) {\n const skillMdPath = join(skillsDir, entry.name, 'SKILL.md')\n\n if (existsSync(skillMdPath)) {\n // Skip if already loaded from manifest\n if (skills.some(s => s.filePath === skillMdPath)) continue\n\n try {\n const content = readFileSync(skillMdPath, 'utf-8')\n const { data, content: skillContent } = matter(content)\n\n skills.push({\n name: data.name || entry.name,\n filePath: skillMdPath,\n config: {\n name: data.name || entry.name,\n description: data.description || '',\n content: skillContent.trim(),\n },\n pluginName: manifest.name,\n source: 'plugin',\n })\n } catch (error) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Error loading skill from ${skillMdPath}: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n }\n }\n // Flat pattern: .md files directly in skills/\n else if (entry.isFile() && entry.name.endsWith('.md')) {\n const fullPath = join(skillsDir, entry.name)\n\n // Skip if already loaded from manifest\n if (skills.some(s => s.filePath === fullPath)) continue\n\n try {\n const content = readFileSync(fullPath, 'utf-8')\n const { data, content: skillContent } = matter(content)\n\n skills.push({\n name: data.name || basename(entry.name, '.md'),\n filePath: fullPath,\n config: {\n name: data.name || basename(entry.name, '.md'),\n description: data.description || '',\n content: skillContent.trim(),\n },\n pluginName: manifest.name,\n source: 'plugin',\n })\n } catch (error) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Error loading skill ${entry.name}: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n }\n }\n }\n\n return skills\n}\n\n/**\n * Load hooks from plugin\n *\n * Uses hooks/hooks.json format\n */\nfunction loadHooks(pluginPath: string, manifest: PluginManifest): LoadedHook[] {\n const hooks: LoadedHook[] = []\n const hooksDir = join(pluginPath, 'hooks')\n const hooksJsonPath = join(hooksDir, 'hooks.json')\n\n // Check if hooks.json exists\n if (!existsSync(hooksJsonPath)) {\n return hooks\n }\n\n try {\n const content = readFileSync(hooksJsonPath, 'utf-8')\n const hooksConfig = JSON.parse(content)\n\n // Validate structure (basic validation, full validation in hook executor)\n if (!hooksConfig.hooks || typeof hooksConfig.hooks !== 'object') {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Invalid hooks.json in ${pluginPath}: missing \"hooks\" field`,\n )\n return hooks\n }\n\n // Process each hook event\n for (const [eventName, matchers] of Object.entries(\n hooksConfig.hooks as Record<string, any[]>,\n )) {\n if (!Array.isArray(matchers)) continue\n\n for (const matcher of matchers) {\n if (!matcher.hooks || !Array.isArray(matcher.hooks)) continue\n\n for (const hookDef of matcher.hooks) {\n hooks.push({\n name: `${manifest.name}:${eventName}:${hooks.length}`,\n filePath: hooksJsonPath,\n config: {\n event: eventName as any,\n matcher: matcher.matcher,\n type: hookDef.type || 'command',\n command: hookDef.command,\n prompt: hookDef.prompt,\n blocking: hookDef.type === 'prompt',\n timeout: hookDef.timeout || 60,\n },\n pluginName: manifest.name,\n event: eventName as any,\n matcher: matcher.matcher,\n })\n }\n }\n }\n } catch (error) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Error loading hooks from ${hooksJsonPath}: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n\n return hooks\n}\n\n/**\n * Expand environment variables in a string\n * Supports:\n * - ${VAR} - expands to environment variable VAR\n * - ${VAR:-default} - expands to VAR or default if not set\n * - ${MINTO_PLUGIN_ROOT} - expands to plugin directory path\n */\nfunction expandEnvVars(value: string, pluginPath: string): string {\n // Replace ${MINTO_PLUGIN_ROOT} with plugin path\n let expanded = value.replace(/\\$\\{MINTO_PLUGIN_ROOT\\}/g, pluginPath)\n\n // Also support $MINTO_PLUGIN_ROOT without braces\n expanded = expanded.replace(/\\$MINTO_PLUGIN_ROOT(?![A-Za-z_])/g, pluginPath)\n\n // Support ${CLAUDE_PLUGIN_ROOT} for CC-synced plugins\n expanded = expanded.replace(/\\$\\{CLAUDE_PLUGIN_ROOT\\}/g, pluginPath)\n expanded = expanded.replace(/\\$CLAUDE_PLUGIN_ROOT(?![A-Za-z_])/g, pluginPath)\n\n // Replace ${VAR} or ${VAR:-default} for other environment variables\n expanded = expanded.replace(\n /\\$\\{([^}:]+)(?::-([^}]*))?\\}/g,\n (match, varName, defaultValue) => {\n // Skip already processed plugin root variables\n if (varName === 'MINTO_PLUGIN_ROOT' || varName === 'CLAUDE_PLUGIN_ROOT') {\n return match\n }\n return process.env[varName] || defaultValue || ''\n },\n )\n\n return expanded\n}\n\n/**\n * Expand environment variables in MCP server configuration\n */\nfunction expandServerConfig(config: any, pluginPath: string): any {\n const expanded: any = { ...config }\n\n // Expand string fields\n if (expanded.command) {\n expanded.command = expandEnvVars(expanded.command, pluginPath)\n }\n\n if (expanded.url) {\n expanded.url = expandEnvVars(expanded.url, pluginPath)\n }\n\n // Expand args array\n if (expanded.args && Array.isArray(expanded.args)) {\n expanded.args = expanded.args.map((arg: string) =>\n expandEnvVars(arg, pluginPath),\n )\n }\n\n // Expand env object\n if (expanded.env && typeof expanded.env === 'object') {\n expanded.env = Object.fromEntries(\n Object.entries(expanded.env).map(([k, v]) => [\n k,\n expandEnvVars(String(v), pluginPath),\n ]),\n )\n }\n\n // Expand headers object\n if (expanded.headers && typeof expanded.headers === 'object') {\n expanded.headers = Object.fromEntries(\n Object.entries(expanded.headers).map(([k, v]) => [\n k,\n expandEnvVars(String(v), pluginPath),\n ]),\n )\n }\n\n return expanded\n}\n\n/**\n * Load MCP servers from plugin\n *\n * Two configuration methods:\n * 1. .mcp.json file at plugin root\n * 2. Inline mcpServers in plugin.json manifest\n *\n * Inline configurations override .mcp.json for same server name.\n */\nfunction loadMCPServers(\n pluginPath: string,\n manifest: PluginManifest,\n): LoadedMCPServer[] {\n const mcpServers: LoadedMCPServer[] = []\n\n // Step 1: Load .mcp.json if it exists\n const mcpJsonPath = join(pluginPath, '.mcp.json')\n let mcpJsonServers: Record<string, any> = {}\n\n if (existsSync(mcpJsonPath)) {\n try {\n const content = readFileSync(mcpJsonPath, 'utf-8')\n const parsed = JSON.parse(content)\n\n if (parsed.mcpServers && typeof parsed.mcpServers === 'object') {\n mcpJsonServers = parsed.mcpServers\n }\n } catch (error) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Error loading .mcp.json from ${pluginPath}: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n }\n\n // Step 2: Get inline MCP servers from manifest\n let inlineServers: Record<string, any> = {}\n\n if (\n manifest.mcpServers &&\n typeof manifest.mcpServers === 'object' &&\n !Array.isArray(manifest.mcpServers)\n ) {\n inlineServers = manifest.mcpServers as Record<string, any>\n }\n\n // Step 3: Merge (inline overrides .mcp.json)\n const allServers = { ...mcpJsonServers, ...inlineServers }\n\n // Step 4: Convert to LoadedMCPServer format\n for (const [name, config] of Object.entries(allServers)) {\n try {\n // Expand environment variables\n const expandedConfig = expandServerConfig(config, pluginPath)\n\n // Validate required fields based on server type\n const serverType = expandedConfig.type || 'stdio'\n\n if (serverType === 'stdio' && !expandedConfig.command) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `MCP server \"${name}\" in ${manifest.name} is missing required \"command\" field for stdio type`,\n )\n continue\n }\n\n if (\n (serverType === 'http' || serverType === 'sse') &&\n !expandedConfig.url\n ) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `MCP server \"${name}\" in ${manifest.name} is missing required \"url\" field for ${serverType} type`,\n )\n continue\n }\n\n mcpServers.push({\n name,\n filePath: existsSync(mcpJsonPath)\n ? mcpJsonPath\n : join(pluginPath, 'plugin.json'),\n config: {\n command: expandedConfig.command || '',\n args: expandedConfig.args || [],\n env: expandedConfig.env || {},\n timeout: expandedConfig.timeout,\n },\n pluginName: manifest.name,\n })\n } catch (error) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Error loading MCP server \"${name}\" from ${manifest.name}: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n }\n\n return mcpServers\n}\n\n/**\n * Load LSP servers from plugin\n *\n * Two configuration methods:\n * 1. .lsp.json file at plugin root\n * 2. Inline lspServers in plugin.json manifest\n *\n * ${CLAUDE_PLUGIN_ROOT} / ${MINTO_PLUGIN_ROOT} is expanded in config values.\n */\nfunction loadLSPServers(\n pluginPath: string,\n manifest: PluginManifest,\n): LoadedLSPServer[] {\n const lspServers: LoadedLSPServer[] = []\n\n // Step 1: Load .lsp.json if it exists\n const lspJsonPath = join(pluginPath, '.lsp.json')\n let lspJsonServers: Record<string, any> = {}\n\n if (existsSync(lspJsonPath)) {\n try {\n const content = readFileSync(lspJsonPath, 'utf-8')\n const parsed = JSON.parse(content)\n\n if (parsed.lspServers && typeof parsed.lspServers === 'object') {\n lspJsonServers = parsed.lspServers\n } else if (typeof parsed === 'object' && !Array.isArray(parsed)) {\n // Support flat format: { \"server-name\": { command: \"...\" } }\n lspJsonServers = parsed\n }\n } catch (error) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Error loading .lsp.json from ${pluginPath}: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n }\n\n // Step 2: Get inline LSP servers from manifest (if any)\n const manifestData = manifest as any\n let inlineServers: Record<string, any> = {}\n\n if (\n manifestData.lspServers &&\n typeof manifestData.lspServers === 'object' &&\n !Array.isArray(manifestData.lspServers)\n ) {\n inlineServers = manifestData.lspServers\n }\n\n // Step 3: Merge (inline overrides .lsp.json)\n const allServers = { ...lspJsonServers, ...inlineServers }\n\n // Step 4: Convert to LoadedLSPServer format\n for (const [name, config] of Object.entries(allServers)) {\n try {\n const expandedConfig = expandServerConfig(config, pluginPath)\n\n if (!expandedConfig.command) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `LSP server \"${name}\" in ${manifest.name} is missing required \"command\" field`,\n )\n continue\n }\n\n lspServers.push({\n name,\n filePath: existsSync(lspJsonPath)\n ? lspJsonPath\n : join(pluginPath, 'plugin.json'),\n config: {\n command: expandedConfig.command,\n args: expandedConfig.args || [],\n env: expandedConfig.env || {},\n filePatterns: expandedConfig.filePatterns,\n languages: expandedConfig.languages,\n initializationOptions: expandedConfig.initializationOptions,\n },\n pluginName: manifest.name,\n })\n } catch (error) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Error loading LSP server \"${name}\" from ${manifest.name}: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n }\n\n return lspServers\n}\n\n/**\n * Determine plugin source from path\n * Checks for marketplace metadata file to identify marketplace-installed plugins\n */\nfunction determinePluginSource(pluginPath: string): PluginSource {\n const home = homedir()\n const cwd = getCwd()\n\n // Check for CC sync metadata (Claude Code synced plugins)\n const ccSyncPath = join(pluginPath, '.cc-sync.json')\n if (existsSync(ccSyncPath)) {\n try {\n const ccMeta = JSON.parse(readFileSync(ccSyncPath, 'utf-8'))\n return {\n type: 'claude-code',\n marketplace: ccMeta.marketplace || '',\n name: ccMeta.name || basename(pluginPath),\n }\n } catch {\n // Fall through to other detection methods\n }\n }\n\n // Check for marketplace metadata file\n const marketplaceMetaPath = join(pluginPath, '.marketplace-meta.json')\n if (existsSync(marketplaceMetaPath)) {\n try {\n const metaContent = readFileSync(marketplaceMetaPath, 'utf-8')\n const meta = JSON.parse(metaContent)\n if (meta.marketplace && meta.plugin) {\n return {\n type: 'marketplace',\n marketplace: meta.marketplace,\n name: meta.plugin,\n }\n }\n } catch (error) {\n // If metadata file is corrupted, fall through to local detection\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Failed to read marketplace metadata from ${marketplaceMetaPath}: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n }\n\n // Determine local source based on path\n const managedDir = getManagedPluginsDir()\n if (pluginPath.startsWith(managedDir)) {\n return { type: 'local', path: 'managed' }\n } else if (pluginPath.startsWith(join(home, '.minto', 'plugins'))) {\n return { type: 'local', path: 'user-global' }\n } else if (pluginPath.startsWith(join(cwd, '.minto', 'plugins.local'))) {\n return { type: 'local', path: 'local' }\n } else if (pluginPath.startsWith(join(cwd, '.minto', 'plugins'))) {\n return { type: 'local', path: 'project' }\n } else {\n return { type: 'local', path: pluginPath }\n }\n}\n\n/**\n * Load plugin settings.json (CC agent settings format)\n *\n * CC format: { \"agent\": { \"defaultAgent\": \"...\", \"maxTurns\": 20 } }\n * Only agent-related settings fields are applied.\n *\n * Priority: plugin settings < user settings < project settings\n */\nexport function loadPluginSettings(\n pluginPath: string,\n): Record<string, any> | null {\n const settingsPaths = [\n join(pluginPath, '.minto-plugin', 'settings.json'),\n join(pluginPath, '.claude-plugin', 'settings.json'),\n join(pluginPath, 'settings.json'),\n ]\n\n for (const settingsPath of settingsPaths) {\n if (!existsSync(settingsPath)) continue\n\n try {\n const content = readFileSync(settingsPath, 'utf-8')\n const parsed = JSON.parse(content)\n\n // Only return agent-related settings (CC format)\n if (parsed.agent && typeof parsed.agent === 'object') {\n return parsed.agent\n }\n\n return parsed\n } catch (error) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Failed to parse plugin settings from ${settingsPath}: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n }\n\n return null\n}\n\n/**\n * Load a single plugin from a directory\n */\nexport function loadPlugin(pluginPath: string): LoadedPlugin {\n const manifest = loadManifest(pluginPath)\n\n // Run directory validation for warnings (non-blocking)\n try {\n const validation = validatePluginDirectory(pluginPath)\n if (validation.warnings.length > 0) {\n for (const warning of validation.warnings) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Plugin \"${manifest.name}\": ${warning}`,\n )\n }\n }\n } catch {\n // Validation failed, continue with loading\n }\n\n const source = determinePluginSource(pluginPath)\n const pluginConfig = loadPluginConfig(pluginPath)\n\n const agents = loadAgents(pluginPath, manifest)\n const commands = loadCommands(pluginPath, manifest)\n const skills = loadSkills(pluginPath, manifest)\n const hooks = loadHooks(pluginPath, manifest)\n const mcpServers = loadMCPServers(pluginPath, manifest)\n const lspServers = loadLSPServers(pluginPath, manifest)\n const settings = loadPluginSettings(pluginPath)\n\n return {\n manifest,\n name: manifest.name,\n location: pluginPath,\n source,\n agents,\n commands,\n skills,\n hooks,\n mcpServers,\n lspServers,\n enabled: pluginConfig.enabled,\n config: pluginConfig.config,\n settings,\n }\n}\n\n/**\n * Load all plugins from all discovery directories\n */\nexport function loadAllPlugins(): LoadedPlugin[] {\n const pluginPaths = discoverPluginPaths()\n const plugins: LoadedPlugin[] = []\n\n for (const [name, path] of pluginPaths) {\n try {\n const plugin = loadPlugin(path)\n plugins.push(plugin)\n } catch (error) {\n if (error instanceof PluginError) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Error loading plugin ${name}: ${error.message}`,\n )\n } else {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Unexpected error loading plugin ${name}: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n }\n }\n\n return plugins\n}\n\n/**\n * Get plugin by name\n */\nexport function getPlugin(name: string): LoadedPlugin | undefined {\n const pluginPaths = discoverPluginPaths()\n const pluginPath = pluginPaths.get(name)\n\n if (!pluginPath) return undefined\n\n try {\n return loadPlugin(pluginPath)\n } catch (error) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Error loading plugin ${name}: ${error instanceof Error ? error.message : String(error)}`,\n )\n return undefined\n }\n}\n\n/**\n * List all installed plugins\n */\nexport function listPlugins(): Array<{\n name: string\n path: string\n manifest?: PluginManifest\n}> {\n const pluginPaths = discoverPluginPaths()\n const plugins: Array<{\n name: string\n path: string\n manifest?: PluginManifest\n }> = []\n\n for (const [name, path] of pluginPaths) {\n try {\n const manifest = loadManifest(path)\n plugins.push({ name, path, manifest })\n } catch (error) {\n plugins.push({ name, path })\n }\n }\n\n return plugins\n}\n\n/**\n * Get plugin config file path\n */\nfunction getPluginConfigPath(pluginPath: string): string {\n return join(pluginPath, '.plugin-config.json')\n}\n\n/**\n * Load plugin configuration\n */\nfunction loadPluginConfig(pluginPath: string): {\n enabled: boolean\n config: Record<string, any>\n} {\n const configPath = getPluginConfigPath(pluginPath)\n\n if (!existsSync(configPath)) {\n return { enabled: true, config: {} }\n }\n\n try {\n const content = readFileSync(configPath, 'utf-8')\n const data = JSON.parse(content)\n return {\n enabled: data.enabled !== false,\n config: data.config || {},\n }\n } catch (error) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Error loading plugin config from ${configPath}: ${error instanceof Error ? error.message : String(error)}`,\n )\n return { enabled: true, config: {} }\n }\n}\n\n/**\n * Save plugin configuration\n */\nfunction savePluginConfig(\n pluginPath: string,\n enabled: boolean,\n config: Record<string, any>,\n): void {\n const configPath = getPluginConfigPath(pluginPath)\n\n try {\n const data = { enabled, config }\n writeFileSync(configPath, JSON.stringify(data, null, 2), 'utf-8')\n } catch (error) {\n throw new PluginError(\n `Failed to save plugin config: ${error instanceof Error ? error.message : String(error)}`,\n PluginErrorCode.PERMISSION_DENIED,\n undefined,\n error,\n )\n }\n}\n\n/**\n * Enable a plugin\n */\nexport function enablePlugin(pluginName: string): void {\n const plugin = getPlugin(pluginName)\n\n if (!plugin) {\n throw new PluginError(\n `Plugin \"${pluginName}\" not found`,\n PluginErrorCode.NOT_INSTALLED,\n pluginName,\n )\n }\n\n savePluginConfig(plugin.location, true, plugin.config || {})\n}\n\n/**\n * Disable a plugin\n */\nexport function disablePlugin(pluginName: string): void {\n const plugin = getPlugin(pluginName)\n\n if (!plugin) {\n throw new PluginError(\n `Plugin \"${pluginName}\" not found`,\n PluginErrorCode.NOT_INSTALLED,\n pluginName,\n )\n }\n\n savePluginConfig(plugin.location, false, plugin.config || {})\n}\n\n/**\n * Toggle plugin enabled state\n */\nexport function togglePluginEnabled(pluginName: string): boolean {\n const plugin = getPlugin(pluginName)\n\n if (!plugin) {\n throw new PluginError(\n `Plugin \"${pluginName}\" not found`,\n PluginErrorCode.NOT_INSTALLED,\n pluginName,\n )\n }\n\n const newState = !plugin.enabled\n savePluginConfig(plugin.location, newState, plugin.config || {})\n return newState\n}\n\n/**\n * Update plugin configuration\n */\nexport function updatePluginConfig(\n pluginName: string,\n config: Record<string, any>,\n): void {\n const plugin = getPlugin(pluginName)\n\n if (!plugin) {\n throw new PluginError(\n `Plugin \"${pluginName}\" not found`,\n PluginErrorCode.NOT_INSTALLED,\n pluginName,\n )\n }\n\n savePluginConfig(plugin.location, plugin.enabled, config)\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * Plugin Loader\n *\n * Discovers and loads plugins from Minto plugin directories.\n *\n * Directory Priority (later overrides earlier):\n * 1. ~/.minto/plugins/ (user global)\n * 2. ./.minto/plugins/ (project - highest priority)\n */\n\nimport {\n existsSync,\n readFileSync,\n readdirSync,\n statSync,\n writeFileSync,\n mkdirSync,\n} from 'fs'\nimport { debug as debugLogger } from '@utils/debugLogger'\nimport { join, resolve, basename } from 'path'\nimport { homedir } from 'os'\nimport matter from 'gray-matter'\nimport { validatePluginDirectory } from '@services/plugins/pluginValidation'\nimport {\n PluginManifest,\n PluginManifestSchema,\n LoadedPlugin,\n LoadedAgent,\n LoadedCommand,\n LoadedSkill,\n LoadedHook,\n LoadedMCPServer,\n LoadedLSPServer,\n PluginError,\n PluginErrorCode,\n PluginSource,\n} from '../types/plugin'\nimport { getCwd } from './state'\n\n/**\n * Extra plugin directories added via --plugin-dir CLI flag\n */\nlet extraPluginDirs: string[] = []\n\n/**\n * Add extra plugin directories (from --plugin-dir CLI flag)\n * These are merged with default directories, not replacing them.\n */\nexport function addExtraPluginDir(dir: string): void {\n const resolved = resolve(dir)\n if (!extraPluginDirs.includes(resolved)) {\n extraPluginDirs.push(resolved)\n }\n}\n\n/**\n * Get managed plugins directory (read-only, enterprise)\n */\nfunction getManagedPluginsDir(): string {\n if (process.platform === 'darwin') {\n return '/Library/Application Support/Minto/managed-plugins'\n }\n return '/etc/minto/managed-plugins'\n}\n\n/**\n * Plugin discovery directories in priority order\n */\nfunction getPluginDirectories(): string[] {\n const cwd = getCwd()\n const home = homedir()\n\n return [\n getManagedPluginsDir(), // Managed (enterprise, read-only, lowest)\n join(home, '.claude', 'plugins'), // User global (legacy)\n join(home, '.minto', 'plugins'), // User global\n join(cwd, '.claude', 'plugins'), // Project (legacy)\n join(cwd, '.minto', 'plugins'), // Project\n join(cwd, '.minto', 'plugins.local'), // Project local (gitignored)\n ...extraPluginDirs, // CLI --plugin-dir (highest priority)\n ]\n}\n\n/**\n * Find all plugin directories across all sources\n */\nfunction discoverPluginPaths(): Map<string, string> {\n const pluginPaths = new Map<string, string>() // name -> path\n const directories = getPluginDirectories()\n\n for (const dir of directories) {\n if (!existsSync(dir)) continue\n\n try {\n const entries = readdirSync(dir)\n\n for (const entry of entries) {\n const pluginPath = join(dir, entry)\n\n // Must be a directory\n if (!statSync(pluginPath).isDirectory()) continue\n\n // Must have plugin.json in .minto-plugin/, .claude-plugin/, or root\n const mintoManifestPath = join(\n pluginPath,\n '.minto-plugin',\n 'plugin.json',\n )\n const claudeManifestPath = join(\n pluginPath,\n '.claude-plugin',\n 'plugin.json',\n )\n const rootManifestPath = join(pluginPath, 'plugin.json')\n if (\n !existsSync(mintoManifestPath) &&\n !existsSync(claudeManifestPath) &&\n !existsSync(rootManifestPath)\n )\n continue\n\n // Later directories override earlier ones\n pluginPaths.set(entry, pluginPath)\n }\n } catch (error) {\n // Silently ignore errors\n }\n }\n\n return pluginPaths\n}\n\n/**\n * Load and validate plugin manifest\n *\n * Manifest locations (priority order):\n * 1. .minto-plugin/plugin.json\n * 2. plugin.json (root fallback)\n */\nfunction loadManifest(pluginPath: string): PluginManifest {\n const candidates = [\n join(pluginPath, '.minto-plugin', 'plugin.json'),\n join(pluginPath, '.claude-plugin', 'plugin.json'),\n join(pluginPath, 'plugin.json'),\n ]\n\n const existing = candidates.filter(p => existsSync(p))\n\n if (existing.length === 0) {\n throw new PluginError(\n `Plugin manifest not found. Tried:\\n${candidates.map(p => ` - ${p}`).join('\\n')}`,\n PluginErrorCode.MANIFEST_NOT_FOUND,\n )\n }\n\n let lastError: unknown = null\n\n // Try each candidate in priority order; fall through on validation failure\n for (const manifestPath of existing) {\n try {\n const manifestContent = readFileSync(manifestPath, 'utf-8')\n const manifestData = JSON.parse(manifestContent)\n return PluginManifestSchema.parse(manifestData)\n } catch (error) {\n lastError = error\n // Continue to next candidate\n }\n }\n\n // All candidates failed\n throw new PluginError(\n `Invalid plugin manifest at ${existing[0]}: ${lastError instanceof Error ? lastError.message : String(lastError)}`,\n PluginErrorCode.MANIFEST_INVALID,\n undefined,\n lastError,\n )\n}\n\n/**\n * Load agents from plugin\n */\nfunction loadAgents(\n pluginPath: string,\n manifest: PluginManifest,\n): LoadedAgent[] {\n const agents: LoadedAgent[] = []\n const agentsDir = join(pluginPath, 'agents')\n\n // Load agents listed in manifest\n for (const agentPath of manifest.agents || []) {\n const fullPath = join(pluginPath, agentPath)\n\n if (!existsSync(fullPath)) {\n debugLogger.warn('PLUGIN_LOADER', `Agent file not found: ${fullPath}`)\n continue\n }\n\n try {\n const content = readFileSync(fullPath, 'utf-8')\n const { data, content: promptContent } = matter(content)\n\n agents.push({\n name: data.name || basename(agentPath, '.md'),\n filePath: fullPath,\n config: {\n name: data.name || basename(agentPath, '.md'),\n description: data.description || '',\n tools: data.tools,\n model: data.model,\n content: promptContent.trim(),\n },\n pluginName: manifest.name,\n })\n } catch (error) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Error loading agent ${agentPath}: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n }\n\n // Also scan agents/ directory if it exists\n if (existsSync(agentsDir) && statSync(agentsDir).isDirectory()) {\n const agentFiles = readdirSync(agentsDir).filter(f => f.endsWith('.md'))\n\n for (const file of agentFiles) {\n const fullPath = join(agentsDir, file)\n\n // Skip if already loaded from manifest\n if (agents.some(a => a.filePath === fullPath)) continue\n\n try {\n const content = readFileSync(fullPath, 'utf-8')\n const { data, content: promptContent } = matter(content)\n\n agents.push({\n name: data.name || basename(file, '.md'),\n filePath: fullPath,\n config: {\n name: data.name || basename(file, '.md'),\n description: data.description || '',\n tools: data.tools,\n model: data.model,\n content: promptContent.trim(),\n },\n pluginName: manifest.name,\n })\n } catch (error) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Error loading agent ${file}: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n }\n }\n\n return agents\n}\n\n/**\n * Load commands from plugin\n */\nfunction loadCommands(\n pluginPath: string,\n manifest: PluginManifest,\n): LoadedCommand[] {\n const commands: LoadedCommand[] = []\n const commandsDir = join(pluginPath, 'commands')\n\n // Load commands listed in manifest\n for (const commandPath of manifest.commands || []) {\n const fullPath = join(pluginPath, commandPath)\n\n if (!existsSync(fullPath)) {\n debugLogger.warn('PLUGIN_LOADER', `Command file not found: ${fullPath}`)\n continue\n }\n\n try {\n const content = readFileSync(fullPath, 'utf-8')\n const { data, content: commandContent } = matter(content)\n\n commands.push({\n name: data.name || basename(commandPath, '.md'),\n filePath: fullPath,\n config: {\n name: data.name || basename(commandPath, '.md'),\n description: data.description,\n aliases: data.aliases,\n enabled: data.enabled !== false,\n hidden: data.hidden === true,\n progressMessage: data.progressMessage,\n argNames: data.argNames,\n 'allowed-tools': data['allowed-tools'],\n content: commandContent.trim(),\n },\n pluginName: manifest.name,\n })\n } catch (error) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Error loading command ${commandPath}: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n }\n\n // Also scan commands/ directory if it exists\n if (existsSync(commandsDir) && statSync(commandsDir).isDirectory()) {\n const commandFiles = readdirSync(commandsDir).filter(f => f.endsWith('.md'))\n\n for (const file of commandFiles) {\n const fullPath = join(commandsDir, file)\n\n // Skip if already loaded from manifest\n if (commands.some(c => c.filePath === fullPath)) continue\n\n try {\n const content = readFileSync(fullPath, 'utf-8')\n const { data, content: commandContent } = matter(content)\n\n commands.push({\n name: data.name || basename(file, '.md'),\n filePath: fullPath,\n config: {\n name: data.name || basename(file, '.md'),\n description: data.description,\n aliases: data.aliases,\n enabled: data.enabled !== false,\n hidden: data.hidden === true,\n progressMessage: data.progressMessage,\n argNames: data.argNames,\n 'allowed-tools': data['allowed-tools'],\n content: commandContent.trim(),\n },\n pluginName: manifest.name,\n })\n } catch (error) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Error loading command ${file}: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n }\n }\n\n return commands\n}\n\n/**\n * Load skills from plugin\n *\n * Supports two patterns:\n * - Subdirectory: skills/skill-name/SKILL.md\n * - Flat: skills/skill-name.md\n */\nfunction loadSkills(\n pluginPath: string,\n manifest: PluginManifest,\n): LoadedSkill[] {\n const skills: LoadedSkill[] = []\n const skillsDir = join(pluginPath, 'skills')\n\n // Load skills listed in manifest\n for (const skillPath of manifest.skills || []) {\n const fullPath = join(pluginPath, skillPath)\n\n if (!existsSync(fullPath)) {\n debugLogger.warn('PLUGIN_LOADER', `Skill file not found: ${fullPath}`)\n continue\n }\n\n try {\n const content = readFileSync(fullPath, 'utf-8')\n const { data, content: skillContent } = matter(content)\n\n skills.push({\n name: data.name || basename(skillPath, '.md'),\n filePath: fullPath,\n config: {\n name: data.name || basename(skillPath, '.md'),\n description: data.description || '',\n content: skillContent.trim(),\n },\n pluginName: manifest.name,\n source: 'plugin',\n })\n } catch (error) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Error loading skill ${skillPath}: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n }\n\n // Auto-discover skills from skills/ directory if it exists\n if (existsSync(skillsDir) && statSync(skillsDir).isDirectory()) {\n const entries = readdirSync(skillsDir, { withFileTypes: true })\n\n for (const entry of entries) {\n // Subdirectory pattern: skill-name/SKILL.md\n if (entry.isDirectory()) {\n const skillMdPath = join(skillsDir, entry.name, 'SKILL.md')\n\n if (existsSync(skillMdPath)) {\n // Skip if already loaded from manifest\n if (skills.some(s => s.filePath === skillMdPath)) continue\n\n try {\n const content = readFileSync(skillMdPath, 'utf-8')\n const { data, content: skillContent } = matter(content)\n\n skills.push({\n name: data.name || entry.name,\n filePath: skillMdPath,\n config: {\n name: data.name || entry.name,\n description: data.description || '',\n content: skillContent.trim(),\n },\n pluginName: manifest.name,\n source: 'plugin',\n })\n } catch (error) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Error loading skill from ${skillMdPath}: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n }\n }\n // Flat pattern: .md files directly in skills/\n else if (entry.isFile() && entry.name.endsWith('.md')) {\n const fullPath = join(skillsDir, entry.name)\n\n // Skip if already loaded from manifest\n if (skills.some(s => s.filePath === fullPath)) continue\n\n try {\n const content = readFileSync(fullPath, 'utf-8')\n const { data, content: skillContent } = matter(content)\n\n skills.push({\n name: data.name || basename(entry.name, '.md'),\n filePath: fullPath,\n config: {\n name: data.name || basename(entry.name, '.md'),\n description: data.description || '',\n content: skillContent.trim(),\n },\n pluginName: manifest.name,\n source: 'plugin',\n })\n } catch (error) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Error loading skill ${entry.name}: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n }\n }\n }\n\n return skills\n}\n\n/**\n * Load hooks from plugin\n *\n * Uses hooks/hooks.json format\n */\nfunction loadHooks(pluginPath: string, manifest: PluginManifest): LoadedHook[] {\n const hooks: LoadedHook[] = []\n const hooksDir = join(pluginPath, 'hooks')\n const hooksJsonPath = join(hooksDir, 'hooks.json')\n\n // Check if hooks.json exists\n if (!existsSync(hooksJsonPath)) {\n return hooks\n }\n\n try {\n const content = readFileSync(hooksJsonPath, 'utf-8')\n const hooksConfig = JSON.parse(content)\n\n // Validate structure (basic validation, full validation in hook executor)\n if (!hooksConfig.hooks || typeof hooksConfig.hooks !== 'object') {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Invalid hooks.json in ${pluginPath}: missing \"hooks\" field`,\n )\n return hooks\n }\n\n // Process each hook event\n for (const [eventName, matchers] of Object.entries(\n hooksConfig.hooks as Record<string, any[]>,\n )) {\n if (!Array.isArray(matchers)) continue\n\n for (const matcher of matchers) {\n if (!matcher.hooks || !Array.isArray(matcher.hooks)) continue\n\n for (const hookDef of matcher.hooks) {\n hooks.push({\n name: `${manifest.name}:${eventName}:${hooks.length}`,\n filePath: hooksJsonPath,\n config: {\n event: eventName as any,\n matcher: matcher.matcher,\n type: hookDef.type || 'command',\n command: hookDef.command,\n prompt: hookDef.prompt,\n blocking: hookDef.type === 'prompt',\n timeout: hookDef.timeout || 60,\n },\n pluginName: manifest.name,\n event: eventName as any,\n matcher: matcher.matcher,\n })\n }\n }\n }\n } catch (error) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Error loading hooks from ${hooksJsonPath}: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n\n return hooks\n}\n\n/**\n * Expand environment variables in a string\n * Supports:\n * - ${VAR} - expands to environment variable VAR\n * - ${VAR:-default} - expands to VAR or default if not set\n * - ${MINTO_PLUGIN_ROOT} - expands to plugin directory path\n */\nfunction expandEnvVars(value: string, pluginPath: string): string {\n // Replace ${MINTO_PLUGIN_ROOT} with plugin path\n let expanded = value.replace(/\\$\\{MINTO_PLUGIN_ROOT\\}/g, pluginPath)\n\n // Also support $MINTO_PLUGIN_ROOT without braces\n expanded = expanded.replace(/\\$MINTO_PLUGIN_ROOT(?![A-Za-z_])/g, pluginPath)\n\n // Support ${CLAUDE_PLUGIN_ROOT} for CC-synced plugins\n expanded = expanded.replace(/\\$\\{CLAUDE_PLUGIN_ROOT\\}/g, pluginPath)\n expanded = expanded.replace(/\\$CLAUDE_PLUGIN_ROOT(?![A-Za-z_])/g, pluginPath)\n\n // Replace ${VAR} or ${VAR:-default} for other environment variables\n expanded = expanded.replace(\n /\\$\\{([^}:]+)(?::-([^}]*))?\\}/g,\n (match, varName, defaultValue) => {\n // Skip already processed plugin root variables\n if (varName === 'MINTO_PLUGIN_ROOT' || varName === 'CLAUDE_PLUGIN_ROOT') {\n return match\n }\n return process.env[varName] || defaultValue || ''\n },\n )\n\n return expanded\n}\n\n/**\n * Expand environment variables in MCP server configuration\n */\nfunction expandServerConfig(config: any, pluginPath: string): any {\n const expanded: any = { ...config }\n\n // Expand string fields\n if (expanded.command) {\n expanded.command = expandEnvVars(expanded.command, pluginPath)\n }\n\n if (expanded.url) {\n expanded.url = expandEnvVars(expanded.url, pluginPath)\n }\n\n // Expand args array\n if (expanded.args && Array.isArray(expanded.args)) {\n expanded.args = expanded.args.map((arg: string) =>\n expandEnvVars(arg, pluginPath),\n )\n }\n\n // Expand env object\n if (expanded.env && typeof expanded.env === 'object') {\n expanded.env = Object.fromEntries(\n Object.entries(expanded.env).map(([k, v]) => [\n k,\n expandEnvVars(String(v), pluginPath),\n ]),\n )\n }\n\n // Expand headers object\n if (expanded.headers && typeof expanded.headers === 'object') {\n expanded.headers = Object.fromEntries(\n Object.entries(expanded.headers).map(([k, v]) => [\n k,\n expandEnvVars(String(v), pluginPath),\n ]),\n )\n }\n\n return expanded\n}\n\n/**\n * Load MCP servers from plugin\n *\n * Two configuration methods:\n * 1. .mcp.json file at plugin root\n * 2. Inline mcpServers in plugin.json manifest\n *\n * Inline configurations override .mcp.json for same server name.\n */\nfunction loadMCPServers(\n pluginPath: string,\n manifest: PluginManifest,\n): LoadedMCPServer[] {\n const mcpServers: LoadedMCPServer[] = []\n\n // Step 1: Load .mcp.json if it exists\n const mcpJsonPath = join(pluginPath, '.mcp.json')\n let mcpJsonServers: Record<string, any> = {}\n\n if (existsSync(mcpJsonPath)) {\n try {\n const content = readFileSync(mcpJsonPath, 'utf-8')\n const parsed = JSON.parse(content)\n\n if (parsed.mcpServers && typeof parsed.mcpServers === 'object') {\n mcpJsonServers = parsed.mcpServers\n }\n } catch (error) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Error loading .mcp.json from ${pluginPath}: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n }\n\n // Step 2: Get inline MCP servers from manifest\n let inlineServers: Record<string, any> = {}\n\n if (\n manifest.mcpServers &&\n typeof manifest.mcpServers === 'object' &&\n !Array.isArray(manifest.mcpServers)\n ) {\n inlineServers = manifest.mcpServers as Record<string, any>\n }\n\n // Step 3: Merge (inline overrides .mcp.json)\n const allServers = { ...mcpJsonServers, ...inlineServers }\n\n // Step 4: Convert to LoadedMCPServer format\n for (const [name, config] of Object.entries(allServers)) {\n try {\n // Expand environment variables\n const expandedConfig = expandServerConfig(config, pluginPath)\n\n // Validate required fields based on server type\n const serverType = expandedConfig.type || 'stdio'\n\n if (serverType === 'stdio' && !expandedConfig.command) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `MCP server \"${name}\" in ${manifest.name} is missing required \"command\" field for stdio type`,\n )\n continue\n }\n\n if (\n (serverType === 'http' || serverType === 'sse') &&\n !expandedConfig.url\n ) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `MCP server \"${name}\" in ${manifest.name} is missing required \"url\" field for ${serverType} type`,\n )\n continue\n }\n\n mcpServers.push({\n name,\n filePath: existsSync(mcpJsonPath)\n ? mcpJsonPath\n : join(pluginPath, 'plugin.json'),\n config: {\n command: expandedConfig.command || '',\n args: expandedConfig.args || [],\n env: expandedConfig.env || {},\n timeout: expandedConfig.timeout,\n },\n pluginName: manifest.name,\n })\n } catch (error) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Error loading MCP server \"${name}\" from ${manifest.name}: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n }\n\n return mcpServers\n}\n\n/**\n * Load LSP servers from plugin\n *\n * Two configuration methods:\n * 1. .lsp.json file at plugin root\n * 2. Inline lspServers in plugin.json manifest\n *\n * ${CLAUDE_PLUGIN_ROOT} / ${MINTO_PLUGIN_ROOT} is expanded in config values.\n */\nfunction loadLSPServers(\n pluginPath: string,\n manifest: PluginManifest,\n): LoadedLSPServer[] {\n const lspServers: LoadedLSPServer[] = []\n\n // Step 1: Load .lsp.json if it exists\n const lspJsonPath = join(pluginPath, '.lsp.json')\n let lspJsonServers: Record<string, any> = {}\n\n if (existsSync(lspJsonPath)) {\n try {\n const content = readFileSync(lspJsonPath, 'utf-8')\n const parsed = JSON.parse(content)\n\n if (parsed.lspServers && typeof parsed.lspServers === 'object') {\n lspJsonServers = parsed.lspServers\n } else if (typeof parsed === 'object' && !Array.isArray(parsed)) {\n // Support flat format: { \"server-name\": { command: \"...\" } }\n lspJsonServers = parsed\n }\n } catch (error) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Error loading .lsp.json from ${pluginPath}: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n }\n\n // Step 2: Get inline LSP servers from manifest (if any)\n const manifestData = manifest as any\n let inlineServers: Record<string, any> = {}\n\n if (\n manifestData.lspServers &&\n typeof manifestData.lspServers === 'object' &&\n !Array.isArray(manifestData.lspServers)\n ) {\n inlineServers = manifestData.lspServers\n }\n\n // Step 3: Merge (inline overrides .lsp.json)\n const allServers = { ...lspJsonServers, ...inlineServers }\n\n // Step 4: Convert to LoadedLSPServer format\n for (const [name, config] of Object.entries(allServers)) {\n try {\n const expandedConfig = expandServerConfig(config, pluginPath)\n\n if (!expandedConfig.command) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `LSP server \"${name}\" in ${manifest.name} is missing required \"command\" field`,\n )\n continue\n }\n\n lspServers.push({\n name,\n filePath: existsSync(lspJsonPath)\n ? lspJsonPath\n : join(pluginPath, 'plugin.json'),\n config: {\n command: expandedConfig.command,\n args: expandedConfig.args || [],\n env: expandedConfig.env || {},\n filePatterns: expandedConfig.filePatterns,\n languages: expandedConfig.languages,\n initializationOptions: expandedConfig.initializationOptions,\n },\n pluginName: manifest.name,\n })\n } catch (error) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Error loading LSP server \"${name}\" from ${manifest.name}: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n }\n\n return lspServers\n}\n\n/**\n * Determine plugin source from path\n * Checks for marketplace metadata file to identify marketplace-installed plugins\n */\nfunction determinePluginSource(pluginPath: string): PluginSource {\n const home = homedir()\n const cwd = getCwd()\n\n // Check for CC sync metadata (Claude Code synced plugins)\n const ccSyncPath = join(pluginPath, '.cc-sync.json')\n if (existsSync(ccSyncPath)) {\n try {\n const ccMeta = JSON.parse(readFileSync(ccSyncPath, 'utf-8'))\n return {\n type: 'claude-code',\n marketplace: ccMeta.marketplace || '',\n name: ccMeta.name || basename(pluginPath),\n }\n } catch {\n // Fall through to other detection methods\n }\n }\n\n // Check for marketplace metadata file\n const marketplaceMetaPath = join(pluginPath, '.marketplace-meta.json')\n if (existsSync(marketplaceMetaPath)) {\n try {\n const metaContent = readFileSync(marketplaceMetaPath, 'utf-8')\n const meta = JSON.parse(metaContent)\n if (meta.marketplace && meta.plugin) {\n return {\n type: 'marketplace',\n marketplace: meta.marketplace,\n name: meta.plugin,\n }\n }\n } catch (error) {\n // If metadata file is corrupted, fall through to local detection\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Failed to read marketplace metadata from ${marketplaceMetaPath}: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n }\n\n // Determine local source based on path\n const managedDir = getManagedPluginsDir()\n if (pluginPath.startsWith(managedDir)) {\n return { type: 'local', path: 'managed' }\n } else if (pluginPath.startsWith(join(home, '.minto', 'plugins'))) {\n return { type: 'local', path: 'user-global' }\n } else if (pluginPath.startsWith(join(cwd, '.minto', 'plugins.local'))) {\n return { type: 'local', path: 'local' }\n } else if (pluginPath.startsWith(join(cwd, '.minto', 'plugins'))) {\n return { type: 'local', path: 'project' }\n } else {\n return { type: 'local', path: pluginPath }\n }\n}\n\n/**\n * Load plugin settings.json (CC agent settings format)\n *\n * CC format: { \"agent\": { \"defaultAgent\": \"...\", \"maxTurns\": 20 } }\n * Only agent-related settings fields are applied.\n *\n * Priority: plugin settings < user settings < project settings\n */\nexport function loadPluginSettings(\n pluginPath: string,\n): Record<string, any> | null {\n const settingsPaths = [\n join(pluginPath, '.minto-plugin', 'settings.json'),\n join(pluginPath, '.claude-plugin', 'settings.json'),\n join(pluginPath, 'settings.json'),\n ]\n\n for (const settingsPath of settingsPaths) {\n if (!existsSync(settingsPath)) continue\n\n try {\n const content = readFileSync(settingsPath, 'utf-8')\n const parsed = JSON.parse(content)\n\n // Only return agent-related settings (CC format)\n if (parsed.agent && typeof parsed.agent === 'object') {\n return parsed.agent\n }\n\n return parsed\n } catch (error) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Failed to parse plugin settings from ${settingsPath}: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n }\n\n return null\n}\n\n/**\n * Load a single plugin from a directory\n */\nexport function loadPlugin(pluginPath: string): LoadedPlugin {\n const manifest = loadManifest(pluginPath)\n\n // Run directory validation for warnings (non-blocking)\n try {\n const validation = validatePluginDirectory(pluginPath)\n if (validation.warnings.length > 0) {\n for (const warning of validation.warnings) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Plugin \"${manifest.name}\": ${warning}`,\n )\n }\n }\n } catch {\n // Validation failed, continue with loading\n }\n\n const source = determinePluginSource(pluginPath)\n const pluginConfig = loadPluginConfig(pluginPath)\n\n const agents = loadAgents(pluginPath, manifest)\n const commands = loadCommands(pluginPath, manifest)\n const skills = loadSkills(pluginPath, manifest)\n const hooks = loadHooks(pluginPath, manifest)\n const mcpServers = loadMCPServers(pluginPath, manifest)\n const lspServers = loadLSPServers(pluginPath, manifest)\n const settings = loadPluginSettings(pluginPath)\n\n return {\n manifest,\n name: manifest.name,\n location: pluginPath,\n source,\n agents,\n commands,\n skills,\n hooks,\n mcpServers,\n lspServers,\n enabled: pluginConfig.enabled,\n config: pluginConfig.config,\n settings,\n }\n}\n\n/**\n * Plugin cache with TTL to avoid re-scanning directories on every call.\n * Invalidated by enablePlugin/disablePlugin/togglePluginEnabled/updatePluginConfig,\n * or manually via invalidatePluginCache().\n */\nlet _pluginCache: LoadedPlugin[] | null = null\nlet _pluginCacheTime = 0\nconst PLUGIN_CACHE_TTL_MS = 30_000\n\n/**\n * Invalidate the plugin cache.\n * Call after plugin install/remove/enable/disable/config changes.\n */\nexport function invalidatePluginCache(): void {\n _pluginCache = null\n _pluginCacheTime = 0\n}\n\n/**\n * Load all plugins from all discovery directories\n */\nexport function loadAllPlugins(): LoadedPlugin[] {\n const now = Date.now()\n if (_pluginCache && now - _pluginCacheTime < PLUGIN_CACHE_TTL_MS) {\n return _pluginCache\n }\n\n const pluginPaths = discoverPluginPaths()\n const plugins: LoadedPlugin[] = []\n\n for (const [name, path] of pluginPaths) {\n try {\n const plugin = loadPlugin(path)\n plugins.push(plugin)\n } catch (error) {\n if (error instanceof PluginError) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Error loading plugin ${name}: ${error.message}`,\n )\n } else {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Unexpected error loading plugin ${name}: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n }\n }\n\n _pluginCache = plugins\n _pluginCacheTime = now\n return plugins\n}\n\n/**\n * Get plugin by name\n */\nexport function getPlugin(name: string): LoadedPlugin | undefined {\n const pluginPaths = discoverPluginPaths()\n const pluginPath = pluginPaths.get(name)\n\n if (!pluginPath) return undefined\n\n try {\n return loadPlugin(pluginPath)\n } catch (error) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Error loading plugin ${name}: ${error instanceof Error ? error.message : String(error)}`,\n )\n return undefined\n }\n}\n\n/**\n * List all installed plugins\n */\nexport function listPlugins(): Array<{\n name: string\n path: string\n manifest?: PluginManifest\n}> {\n const pluginPaths = discoverPluginPaths()\n const plugins: Array<{\n name: string\n path: string\n manifest?: PluginManifest\n }> = []\n\n for (const [name, path] of pluginPaths) {\n try {\n const manifest = loadManifest(path)\n plugins.push({ name, path, manifest })\n } catch (error) {\n plugins.push({ name, path })\n }\n }\n\n return plugins\n}\n\n/**\n * Get plugin config file path\n */\nfunction getPluginConfigPath(pluginPath: string): string {\n return join(pluginPath, '.plugin-config.json')\n}\n\n/**\n * Load plugin configuration\n */\nfunction loadPluginConfig(pluginPath: string): {\n enabled: boolean\n config: Record<string, any>\n} {\n const configPath = getPluginConfigPath(pluginPath)\n\n if (!existsSync(configPath)) {\n return { enabled: true, config: {} }\n }\n\n try {\n const content = readFileSync(configPath, 'utf-8')\n const data = JSON.parse(content)\n return {\n enabled: data.enabled !== false,\n config: data.config || {},\n }\n } catch (error) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Error loading plugin config from ${configPath}: ${error instanceof Error ? error.message : String(error)}`,\n )\n return { enabled: true, config: {} }\n }\n}\n\n/**\n * Save plugin configuration\n */\nfunction savePluginConfig(\n pluginPath: string,\n enabled: boolean,\n config: Record<string, any>,\n): void {\n const configPath = getPluginConfigPath(pluginPath)\n\n try {\n const data = { enabled, config }\n writeFileSync(configPath, JSON.stringify(data, null, 2), 'utf-8')\n } catch (error) {\n throw new PluginError(\n `Failed to save plugin config: ${error instanceof Error ? error.message : String(error)}`,\n PluginErrorCode.PERMISSION_DENIED,\n undefined,\n error,\n )\n }\n}\n\n/**\n * Enable a plugin\n */\nexport function enablePlugin(pluginName: string): void {\n const plugin = getPlugin(pluginName)\n\n if (!plugin) {\n throw new PluginError(\n `Plugin \"${pluginName}\" not found`,\n PluginErrorCode.NOT_INSTALLED,\n pluginName,\n )\n }\n\n savePluginConfig(plugin.location, true, plugin.config || {})\n invalidatePluginCache()\n}\n\n/**\n * Disable a plugin\n */\nexport function disablePlugin(pluginName: string): void {\n const plugin = getPlugin(pluginName)\n\n if (!plugin) {\n throw new PluginError(\n `Plugin \"${pluginName}\" not found`,\n PluginErrorCode.NOT_INSTALLED,\n pluginName,\n )\n }\n\n savePluginConfig(plugin.location, false, plugin.config || {})\n invalidatePluginCache()\n}\n\n/**\n * Toggle plugin enabled state\n */\nexport function togglePluginEnabled(pluginName: string): boolean {\n const plugin = getPlugin(pluginName)\n\n if (!plugin) {\n throw new PluginError(\n `Plugin \"${pluginName}\" not found`,\n PluginErrorCode.NOT_INSTALLED,\n pluginName,\n )\n }\n\n const newState = !plugin.enabled\n savePluginConfig(plugin.location, newState, plugin.config || {})\n invalidatePluginCache()\n return newState\n}\n\n/**\n * Update plugin configuration\n */\nexport function updatePluginConfig(\n pluginName: string,\n config: Record<string, any>,\n): void {\n const plugin = getPlugin(pluginName)\n\n if (!plugin) {\n throw new PluginError(\n `Plugin \"${pluginName}\" not found`,\n PluginErrorCode.NOT_INSTALLED,\n pluginName,\n )\n }\n\n savePluginConfig(plugin.location, plugin.enabled, config)\n invalidatePluginCache()\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -15,6 +15,7 @@ import {
15
15
  scryptSync,
16
16
  createHash
17
17
  } from "crypto";
18
+ import { debug as debugLogger } from "./debugLogger.js";
18
19
  const SERVICE_NAME = "com.minto.cli";
19
20
  const ENCRYPTED_KEYS_DIR = join(homedir(), ".minto", "secure");
20
21
  const ENCRYPTED_KEYS_FILE = join(ENCRYPTED_KEYS_DIR, "keys.enc");
@@ -55,7 +56,11 @@ function getMachineId() {
55
56
  );
56
57
  if (match) return match[1];
57
58
  }
58
- } catch {
59
+ } catch (e) {
60
+ debugLogger.trace("SECURE_KEY_STORAGE_ERROR", {
61
+ phase: "getMachineId.darwin",
62
+ error: e
63
+ });
59
64
  }
60
65
  }
61
66
  return null;
@@ -70,7 +75,11 @@ function getMachineId() {
70
75
  if (existsSync("/var/lib/dbus/machine-id")) {
71
76
  return readFileSync("/var/lib/dbus/machine-id", "utf-8").trim();
72
77
  }
73
- } catch {
78
+ } catch (e) {
79
+ debugLogger.trace("SECURE_KEY_STORAGE_ERROR", {
80
+ phase: "getMachineId.linux",
81
+ error: e
82
+ });
74
83
  }
75
84
  }
76
85
  return null;
@@ -220,7 +229,11 @@ function storeApiKey(keyName, value) {
220
229
  keys[keyName] = value;
221
230
  saveEncryptedKeys(keys);
222
231
  return true;
223
- } catch {
232
+ } catch (e) {
233
+ debugLogger.trace("SECURE_KEY_STORAGE_ERROR", {
234
+ phase: "storeApiKey",
235
+ error: e
236
+ });
224
237
  return false;
225
238
  }
226
239
  }
@@ -237,7 +250,11 @@ function getApiKey(keyName) {
237
250
  try {
238
251
  const keys = loadEncryptedKeys();
239
252
  return keys[keyName] || null;
240
- } catch {
253
+ } catch (e) {
254
+ debugLogger.trace("SECURE_KEY_STORAGE_ERROR", {
255
+ phase: "getApiKey",
256
+ error: e
257
+ });
241
258
  return null;
242
259
  }
243
260
  }
@@ -258,7 +275,11 @@ function deleteApiKey(keyName) {
258
275
  saveEncryptedKeys(keys);
259
276
  success = true;
260
277
  }
261
- } catch {
278
+ } catch (e) {
279
+ debugLogger.trace("SECURE_KEY_STORAGE_ERROR", {
280
+ phase: "deleteApiKey",
281
+ error: e
282
+ });
262
283
  }
263
284
  return success;
264
285
  }
@@ -272,7 +293,11 @@ function listApiKeyNames() {
272
293
  for (const name of Object.keys(keys)) {
273
294
  names.add(name);
274
295
  }
275
- } catch {
296
+ } catch (e) {
297
+ debugLogger.trace("SECURE_KEY_STORAGE_ERROR", {
298
+ phase: "listApiKeyNames",
299
+ error: e
300
+ });
276
301
  }
277
302
  return Array.from(names);
278
303
  }
@@ -295,7 +320,11 @@ function clearAllApiKeys() {
295
320
  if (existsSync(ENCRYPTED_KEYS_FILE)) {
296
321
  try {
297
322
  unlinkSync(ENCRYPTED_KEYS_FILE);
298
- } catch {
323
+ } catch (e) {
324
+ debugLogger.trace("SECURE_KEY_STORAGE_ERROR", {
325
+ phase: "clearAllApiKeys",
326
+ error: e
327
+ });
299
328
  }
300
329
  }
301
330
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/utils/secureKeyStorage.ts"],
4
- "sourcesContent": ["/**\n * Secure Key Storage\n *\n * Provides secure storage for API keys using system keychain on macOS\n * and encrypted file storage on other platforms.\n *\n * Security features:\n * - Uses macOS Keychain via `security` command when available\n * - Falls back to AES-256-GCM encrypted file storage\n * - Encryption key derived from machine-specific data\n * - Keys never stored in plain text in config files\n */\n\nimport { spawnSync } from 'child_process'\nimport {\n existsSync,\n readFileSync,\n writeFileSync,\n mkdirSync,\n unlinkSync,\n} from 'fs'\nimport { join } from 'path'\nimport { homedir, hostname, platform } from 'os'\nimport {\n createCipheriv,\n createDecipheriv,\n randomBytes,\n scryptSync,\n createHash,\n} from 'crypto'\n\nconst SERVICE_NAME = 'com.minto.cli'\nconst ENCRYPTED_KEYS_DIR = join(homedir(), '.minto', 'secure')\nconst ENCRYPTED_KEYS_FILE = join(ENCRYPTED_KEYS_DIR, 'keys.enc')\n\n/**\n * Check if we're running on macOS with Keychain available\n */\nfunction isMacOSWithKeychain(): boolean {\n if (platform() !== 'darwin') return false\n\n try {\n const result = spawnSync('security', ['help'], {\n encoding: 'utf-8',\n timeout: 5000,\n })\n return result.status === 0 || result.status === 1 // security help returns 1\n } catch {\n return false\n }\n}\n\n/**\n * Get machine-specific key for encryption\n * Combines hostname and a stable machine identifier\n */\nfunction getMachineKey(): Buffer {\n const machineId = getMachineId()\n const combined = `${hostname()}-${machineId}-minto-secure-storage`\n return createHash('sha256').update(combined).digest()\n}\n\n/**\n * Get a stable machine identifier using safe methods only\n */\nfunction getMachineId(): string {\n // Try to get machine ID from various sources\n const sources = [\n // macOS - use spawnSync instead of execSync for safety\n () => {\n if (platform() === 'darwin') {\n try {\n const result = spawnSync(\n 'ioreg',\n ['-rd1', '-c', 'IOPlatformExpertDevice'],\n {\n encoding: 'utf-8',\n timeout: 5000,\n },\n )\n if (result.status === 0 && result.stdout) {\n const match = result.stdout.match(\n /\"IOPlatformUUID\"\\s*=\\s*\"([^\"]+)\"/,\n )\n if (match) return match[1]\n }\n } catch {}\n }\n return null\n },\n // Linux - read from file directly (no shell needed)\n () => {\n if (platform() === 'linux') {\n try {\n if (existsSync('/etc/machine-id')) {\n return readFileSync('/etc/machine-id', 'utf-8').trim()\n }\n if (existsSync('/var/lib/dbus/machine-id')) {\n return readFileSync('/var/lib/dbus/machine-id', 'utf-8').trim()\n }\n } catch {}\n }\n return null\n },\n // Fallback: use hostname hash\n () => {\n return createHash('sha256').update(hostname()).digest('hex').slice(0, 32)\n },\n ]\n\n for (const source of sources) {\n const id = source()\n if (id) return id\n }\n\n // Should never reach here due to fallback\n return 'minto-default-machine-id'\n}\n\n/**\n * Encrypt data using AES-256-GCM\n */\nfunction encrypt(data: string, key: Buffer): string {\n const iv = randomBytes(16)\n const salt = randomBytes(32)\n const derivedKey = scryptSync(key, salt, 32)\n\n const cipher = createCipheriv('aes-256-gcm', derivedKey, iv)\n const encrypted = Buffer.concat([\n cipher.update(data, 'utf-8'),\n cipher.final(),\n ])\n const authTag = cipher.getAuthTag()\n\n // Format: salt:iv:authTag:encrypted (all base64)\n return [\n salt.toString('base64'),\n iv.toString('base64'),\n authTag.toString('base64'),\n encrypted.toString('base64'),\n ].join(':')\n}\n\n/**\n * Decrypt data using AES-256-GCM\n */\nfunction decrypt(encryptedData: string, key: Buffer): string {\n const parts = encryptedData.split(':')\n if (parts.length !== 4) {\n throw new Error('Invalid encrypted data format')\n }\n\n const [saltB64, ivB64, authTagB64, encryptedB64] = parts\n const salt = Buffer.from(saltB64, 'base64')\n const iv = Buffer.from(ivB64, 'base64')\n const authTag = Buffer.from(authTagB64, 'base64')\n const encrypted = Buffer.from(encryptedB64, 'base64')\n\n const derivedKey = scryptSync(key, salt, 32)\n const decipher = createDecipheriv('aes-256-gcm', derivedKey, iv)\n decipher.setAuthTag(authTag)\n\n return Buffer.concat([decipher.update(encrypted), decipher.final()]).toString(\n 'utf-8',\n )\n}\n\n/**\n * Store API key in macOS Keychain\n */\nfunction storeInKeychain(keyName: string, value: string): boolean {\n try {\n // First try to delete existing entry\n spawnSync(\n 'security',\n ['delete-generic-password', '-s', SERVICE_NAME, '-a', keyName],\n { timeout: 5000 },\n )\n\n // Add new entry\n const result = spawnSync(\n 'security',\n [\n 'add-generic-password',\n '-s',\n SERVICE_NAME,\n '-a',\n keyName,\n '-w',\n value,\n '-U', // Update if exists\n ],\n { timeout: 5000 },\n )\n\n return result.status === 0\n } catch {\n return false\n }\n}\n\n/**\n * Retrieve API key from macOS Keychain\n */\nfunction getFromKeychain(keyName: string): string | null {\n try {\n const result = spawnSync(\n 'security',\n [\n 'find-generic-password',\n '-s',\n SERVICE_NAME,\n '-a',\n keyName,\n '-w', // Output password only\n ],\n {\n encoding: 'utf-8',\n timeout: 5000,\n },\n )\n\n if (result.status === 0 && result.stdout) {\n return result.stdout.trim()\n }\n return null\n } catch {\n return null\n }\n}\n\n/**\n * Delete API key from macOS Keychain\n */\nfunction deleteFromKeychain(keyName: string): boolean {\n try {\n const result = spawnSync(\n 'security',\n ['delete-generic-password', '-s', SERVICE_NAME, '-a', keyName],\n { timeout: 5000 },\n )\n\n return result.status === 0\n } catch {\n return false\n }\n}\n\n/**\n * Load encrypted keys from file\n */\nfunction loadEncryptedKeys(): Record<string, string> {\n if (!existsSync(ENCRYPTED_KEYS_FILE)) {\n return {}\n }\n\n try {\n const encryptedContent = readFileSync(ENCRYPTED_KEYS_FILE, 'utf-8')\n const machineKey = getMachineKey()\n const decrypted = decrypt(encryptedContent, machineKey)\n return JSON.parse(decrypted)\n } catch {\n // If decryption fails (e.g., machine key changed), return empty\n return {}\n }\n}\n\n/**\n * Save encrypted keys to file\n */\nfunction saveEncryptedKeys(keys: Record<string, string>): void {\n // Ensure directory exists\n if (!existsSync(ENCRYPTED_KEYS_DIR)) {\n mkdirSync(ENCRYPTED_KEYS_DIR, { recursive: true, mode: 0o700 })\n }\n\n const machineKey = getMachineKey()\n const encrypted = encrypt(JSON.stringify(keys), machineKey)\n writeFileSync(ENCRYPTED_KEYS_FILE, encrypted, { mode: 0o600 })\n}\n\n/**\n * Store an API key securely\n */\nexport function storeApiKey(keyName: string, value: string): boolean {\n // Validate input\n if (!keyName || !value) {\n return false\n }\n\n // Try macOS Keychain first\n if (isMacOSWithKeychain()) {\n if (storeInKeychain(keyName, value)) {\n return true\n }\n }\n\n // Fall back to encrypted file storage\n try {\n const keys = loadEncryptedKeys()\n keys[keyName] = value\n saveEncryptedKeys(keys)\n return true\n } catch {\n return false\n }\n}\n\n/**\n * Retrieve an API key securely\n */\nexport function getApiKey(keyName: string): string | null {\n if (!keyName) {\n return null\n }\n\n // Try macOS Keychain first\n if (isMacOSWithKeychain()) {\n const value = getFromKeychain(keyName)\n if (value) {\n return value\n }\n }\n\n // Fall back to encrypted file storage\n try {\n const keys = loadEncryptedKeys()\n return keys[keyName] || null\n } catch {\n return null\n }\n}\n\n/**\n * Delete an API key\n */\nexport function deleteApiKey(keyName: string): boolean {\n if (!keyName) {\n return false\n }\n\n let success = false\n\n // Try macOS Keychain\n if (isMacOSWithKeychain()) {\n if (deleteFromKeychain(keyName)) {\n success = true\n }\n }\n\n // Also remove from encrypted file\n try {\n const keys = loadEncryptedKeys()\n if (keys[keyName]) {\n delete keys[keyName]\n saveEncryptedKeys(keys)\n success = true\n }\n } catch {}\n\n return success\n}\n\n/**\n * Check if an API key exists\n */\nexport function hasApiKey(keyName: string): boolean {\n return getApiKey(keyName) !== null\n}\n\n/**\n * List all stored API key names (not values)\n */\nexport function listApiKeyNames(): string[] {\n const names = new Set<string>()\n\n // From encrypted file\n try {\n const keys = loadEncryptedKeys()\n for (const name of Object.keys(keys)) {\n names.add(name)\n }\n } catch {}\n\n return Array.from(names)\n}\n\n/**\n * Migrate API key from plain text config to secure storage\n * Returns true if migration was successful or key was already secure\n */\nexport function migrateApiKeyToSecure(\n keyName: string,\n plainTextValue: string,\n): boolean {\n if (!plainTextValue) {\n return false\n }\n\n // Store in secure storage\n if (storeApiKey(keyName, plainTextValue)) {\n return true\n }\n\n return false\n}\n\n/**\n * Get storage backend info (for debugging)\n */\nexport function getStorageBackendInfo(): {\n backend: 'keychain' | 'encrypted-file'\n available: boolean\n} {\n if (isMacOSWithKeychain()) {\n return { backend: 'keychain', available: true }\n }\n return { backend: 'encrypted-file', available: true }\n}\n\n/**\n * Clear all stored API keys (use with caution)\n */\nexport function clearAllApiKeys(): void {\n // Clear encrypted file\n if (existsSync(ENCRYPTED_KEYS_FILE)) {\n try {\n unlinkSync(ENCRYPTED_KEYS_FILE)\n } catch {}\n }\n\n // Note: We don't clear Keychain entries automatically\n // as that could affect other applications\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * Secure Key Storage\n *\n * Provides secure storage for API keys using system keychain on macOS\n * and encrypted file storage on other platforms.\n *\n * Security features:\n * - Uses macOS Keychain via `security` command when available\n * - Falls back to AES-256-GCM encrypted file storage\n * - Encryption key derived from machine-specific data\n * - Keys never stored in plain text in config files\n */\n\nimport { spawnSync } from 'child_process'\nimport {\n existsSync,\n readFileSync,\n writeFileSync,\n mkdirSync,\n unlinkSync,\n} from 'fs'\nimport { join } from 'path'\nimport { homedir, hostname, platform } from 'os'\nimport {\n createCipheriv,\n createDecipheriv,\n randomBytes,\n scryptSync,\n createHash,\n} from 'crypto'\nimport { debug as debugLogger } from './debugLogger'\n\nconst SERVICE_NAME = 'com.minto.cli'\nconst ENCRYPTED_KEYS_DIR = join(homedir(), '.minto', 'secure')\nconst ENCRYPTED_KEYS_FILE = join(ENCRYPTED_KEYS_DIR, 'keys.enc')\n\n/**\n * Check if we're running on macOS with Keychain available\n */\nfunction isMacOSWithKeychain(): boolean {\n if (platform() !== 'darwin') return false\n\n try {\n const result = spawnSync('security', ['help'], {\n encoding: 'utf-8',\n timeout: 5000,\n })\n return result.status === 0 || result.status === 1 // security help returns 1\n } catch {\n return false\n }\n}\n\n/**\n * Get machine-specific key for encryption\n * Combines hostname and a stable machine identifier\n */\nfunction getMachineKey(): Buffer {\n const machineId = getMachineId()\n const combined = `${hostname()}-${machineId}-minto-secure-storage`\n return createHash('sha256').update(combined).digest()\n}\n\n/**\n * Get a stable machine identifier using safe methods only\n */\nfunction getMachineId(): string {\n // Try to get machine ID from various sources\n const sources = [\n // macOS - use spawnSync instead of execSync for safety\n () => {\n if (platform() === 'darwin') {\n try {\n const result = spawnSync(\n 'ioreg',\n ['-rd1', '-c', 'IOPlatformExpertDevice'],\n {\n encoding: 'utf-8',\n timeout: 5000,\n },\n )\n if (result.status === 0 && result.stdout) {\n const match = result.stdout.match(\n /\"IOPlatformUUID\"\\s*=\\s*\"([^\"]+)\"/,\n )\n if (match) return match[1]\n }\n } catch (e) {\n debugLogger.trace('SECURE_KEY_STORAGE_ERROR', {\n phase: 'getMachineId.darwin',\n error: e,\n })\n }\n }\n return null\n },\n // Linux - read from file directly (no shell needed)\n () => {\n if (platform() === 'linux') {\n try {\n if (existsSync('/etc/machine-id')) {\n return readFileSync('/etc/machine-id', 'utf-8').trim()\n }\n if (existsSync('/var/lib/dbus/machine-id')) {\n return readFileSync('/var/lib/dbus/machine-id', 'utf-8').trim()\n }\n } catch (e) {\n debugLogger.trace('SECURE_KEY_STORAGE_ERROR', {\n phase: 'getMachineId.linux',\n error: e,\n })\n }\n }\n return null\n },\n // Fallback: use hostname hash\n () => {\n return createHash('sha256').update(hostname()).digest('hex').slice(0, 32)\n },\n ]\n\n for (const source of sources) {\n const id = source()\n if (id) return id\n }\n\n // Should never reach here due to fallback\n return 'minto-default-machine-id'\n}\n\n/**\n * Encrypt data using AES-256-GCM\n */\nfunction encrypt(data: string, key: Buffer): string {\n const iv = randomBytes(16)\n const salt = randomBytes(32)\n const derivedKey = scryptSync(key, salt, 32)\n\n const cipher = createCipheriv('aes-256-gcm', derivedKey, iv)\n const encrypted = Buffer.concat([\n cipher.update(data, 'utf-8'),\n cipher.final(),\n ])\n const authTag = cipher.getAuthTag()\n\n // Format: salt:iv:authTag:encrypted (all base64)\n return [\n salt.toString('base64'),\n iv.toString('base64'),\n authTag.toString('base64'),\n encrypted.toString('base64'),\n ].join(':')\n}\n\n/**\n * Decrypt data using AES-256-GCM\n */\nfunction decrypt(encryptedData: string, key: Buffer): string {\n const parts = encryptedData.split(':')\n if (parts.length !== 4) {\n throw new Error('Invalid encrypted data format')\n }\n\n const [saltB64, ivB64, authTagB64, encryptedB64] = parts\n const salt = Buffer.from(saltB64, 'base64')\n const iv = Buffer.from(ivB64, 'base64')\n const authTag = Buffer.from(authTagB64, 'base64')\n const encrypted = Buffer.from(encryptedB64, 'base64')\n\n const derivedKey = scryptSync(key, salt, 32)\n const decipher = createDecipheriv('aes-256-gcm', derivedKey, iv)\n decipher.setAuthTag(authTag)\n\n return Buffer.concat([decipher.update(encrypted), decipher.final()]).toString(\n 'utf-8',\n )\n}\n\n/**\n * Store API key in macOS Keychain\n */\nfunction storeInKeychain(keyName: string, value: string): boolean {\n try {\n // First try to delete existing entry\n spawnSync(\n 'security',\n ['delete-generic-password', '-s', SERVICE_NAME, '-a', keyName],\n { timeout: 5000 },\n )\n\n // Add new entry\n const result = spawnSync(\n 'security',\n [\n 'add-generic-password',\n '-s',\n SERVICE_NAME,\n '-a',\n keyName,\n '-w',\n value,\n '-U', // Update if exists\n ],\n { timeout: 5000 },\n )\n\n return result.status === 0\n } catch {\n return false\n }\n}\n\n/**\n * Retrieve API key from macOS Keychain\n */\nfunction getFromKeychain(keyName: string): string | null {\n try {\n const result = spawnSync(\n 'security',\n [\n 'find-generic-password',\n '-s',\n SERVICE_NAME,\n '-a',\n keyName,\n '-w', // Output password only\n ],\n {\n encoding: 'utf-8',\n timeout: 5000,\n },\n )\n\n if (result.status === 0 && result.stdout) {\n return result.stdout.trim()\n }\n return null\n } catch {\n return null\n }\n}\n\n/**\n * Delete API key from macOS Keychain\n */\nfunction deleteFromKeychain(keyName: string): boolean {\n try {\n const result = spawnSync(\n 'security',\n ['delete-generic-password', '-s', SERVICE_NAME, '-a', keyName],\n { timeout: 5000 },\n )\n\n return result.status === 0\n } catch {\n return false\n }\n}\n\n/**\n * Load encrypted keys from file\n */\nfunction loadEncryptedKeys(): Record<string, string> {\n if (!existsSync(ENCRYPTED_KEYS_FILE)) {\n return {}\n }\n\n try {\n const encryptedContent = readFileSync(ENCRYPTED_KEYS_FILE, 'utf-8')\n const machineKey = getMachineKey()\n const decrypted = decrypt(encryptedContent, machineKey)\n return JSON.parse(decrypted)\n } catch {\n // If decryption fails (e.g., machine key changed), return empty\n return {}\n }\n}\n\n/**\n * Save encrypted keys to file\n */\nfunction saveEncryptedKeys(keys: Record<string, string>): void {\n // Ensure directory exists\n if (!existsSync(ENCRYPTED_KEYS_DIR)) {\n mkdirSync(ENCRYPTED_KEYS_DIR, { recursive: true, mode: 0o700 })\n }\n\n const machineKey = getMachineKey()\n const encrypted = encrypt(JSON.stringify(keys), machineKey)\n writeFileSync(ENCRYPTED_KEYS_FILE, encrypted, { mode: 0o600 })\n}\n\n/**\n * Store an API key securely\n */\nexport function storeApiKey(keyName: string, value: string): boolean {\n // Validate input\n if (!keyName || !value) {\n return false\n }\n\n // Try macOS Keychain first\n if (isMacOSWithKeychain()) {\n if (storeInKeychain(keyName, value)) {\n return true\n }\n }\n\n // Fall back to encrypted file storage\n try {\n const keys = loadEncryptedKeys()\n keys[keyName] = value\n saveEncryptedKeys(keys)\n return true\n } catch (e) {\n debugLogger.trace('SECURE_KEY_STORAGE_ERROR', {\n phase: 'storeApiKey',\n error: e,\n })\n return false\n }\n}\n\n/**\n * Retrieve an API key securely\n */\nexport function getApiKey(keyName: string): string | null {\n if (!keyName) {\n return null\n }\n\n // Try macOS Keychain first\n if (isMacOSWithKeychain()) {\n const value = getFromKeychain(keyName)\n if (value) {\n return value\n }\n }\n\n // Fall back to encrypted file storage\n try {\n const keys = loadEncryptedKeys()\n return keys[keyName] || null\n } catch (e) {\n debugLogger.trace('SECURE_KEY_STORAGE_ERROR', {\n phase: 'getApiKey',\n error: e,\n })\n return null\n }\n}\n\n/**\n * Delete an API key\n */\nexport function deleteApiKey(keyName: string): boolean {\n if (!keyName) {\n return false\n }\n\n let success = false\n\n // Try macOS Keychain\n if (isMacOSWithKeychain()) {\n if (deleteFromKeychain(keyName)) {\n success = true\n }\n }\n\n // Also remove from encrypted file\n try {\n const keys = loadEncryptedKeys()\n if (keys[keyName]) {\n delete keys[keyName]\n saveEncryptedKeys(keys)\n success = true\n }\n } catch (e) {\n debugLogger.trace('SECURE_KEY_STORAGE_ERROR', {\n phase: 'deleteApiKey',\n error: e,\n })\n }\n\n return success\n}\n\n/**\n * Check if an API key exists\n */\nexport function hasApiKey(keyName: string): boolean {\n return getApiKey(keyName) !== null\n}\n\n/**\n * List all stored API key names (not values)\n */\nexport function listApiKeyNames(): string[] {\n const names = new Set<string>()\n\n // From encrypted file\n try {\n const keys = loadEncryptedKeys()\n for (const name of Object.keys(keys)) {\n names.add(name)\n }\n } catch (e) {\n debugLogger.trace('SECURE_KEY_STORAGE_ERROR', {\n phase: 'listApiKeyNames',\n error: e,\n })\n }\n\n return Array.from(names)\n}\n\n/**\n * Migrate API key from plain text config to secure storage\n * Returns true if migration was successful or key was already secure\n */\nexport function migrateApiKeyToSecure(\n keyName: string,\n plainTextValue: string,\n): boolean {\n if (!plainTextValue) {\n return false\n }\n\n // Store in secure storage\n if (storeApiKey(keyName, plainTextValue)) {\n return true\n }\n\n return false\n}\n\n/**\n * Get storage backend info (for debugging)\n */\nexport function getStorageBackendInfo(): {\n backend: 'keychain' | 'encrypted-file'\n available: boolean\n} {\n if (isMacOSWithKeychain()) {\n return { backend: 'keychain', available: true }\n }\n return { backend: 'encrypted-file', available: true }\n}\n\n/**\n * Clear all stored API keys (use with caution)\n */\nexport function clearAllApiKeys(): void {\n // Clear encrypted file\n if (existsSync(ENCRYPTED_KEYS_FILE)) {\n try {\n unlinkSync(ENCRYPTED_KEYS_FILE)\n } catch (e) {\n debugLogger.trace('SECURE_KEY_STORAGE_ERROR', {\n phase: 'clearAllApiKeys',\n error: e,\n })\n }\n }\n\n // Note: We don't clear Keychain entries automatically\n // as that could affect other applications\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,7 @@
1
+ function isSimpleMode() {
2
+ return !!(process.env.MINTO_SIMPLE || process.env.CLAUDE_CODE_SIMPLE);
3
+ }
4
+ export {
5
+ isSimpleMode
6
+ };
7
+ //# sourceMappingURL=simpleMode.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/utils/simpleMode.ts"],
4
+ "sourcesContent": ["/**\n * Simple mode detection\n *\n * When MINTO_SIMPLE or CLAUDE_CODE_SIMPLE env var is set (any truthy value),\n * Minto runs in a minimal mode that disables:\n * - MCP servers and tool search\n * - Hooks (session lifecycle, pre/post tool hooks)\n * - CLAUDE.md / MINTO.md project doc loading\n * - Plugin loading\n *\n * This is useful for faster startup, CI environments, or when running\n * as a simple LLM interface without extensions.\n */\nexport function isSimpleMode(): boolean {\n return !!(process.env.MINTO_SIMPLE || process.env.CLAUDE_CODE_SIMPLE)\n}\n"],
5
+ "mappings": "AAaO,SAAS,eAAwB;AACtC,SAAO,CAAC,EAAE,QAAQ,IAAI,gBAAgB,QAAQ,IAAI;AACpD;",
6
+ "names": []
7
+ }
@@ -14,8 +14,18 @@ function pushAgentContext(agentId) {
14
14
  streamingStates.set(agentId, createDefaultState());
15
15
  }
16
16
  }
17
- function popAgentContext() {
17
+ function popAgentContext(expectedId) {
18
18
  if (agentContextStack.length > 1) {
19
+ const top = agentContextStack[agentContextStack.length - 1];
20
+ if (expectedId && top !== expectedId) {
21
+ import("./debugLogger.js").then(({ debug }) => {
22
+ debug.warn("AGENT_CONTEXT_MISMATCH", {
23
+ expected: expectedId,
24
+ actual: top
25
+ });
26
+ }).catch(() => {
27
+ });
28
+ }
19
29
  return agentContextStack.pop();
20
30
  }
21
31
  return void 0;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/utils/streamingState.ts"],
4
- "sourcesContent": ["/**\n * Streaming State Management\n *\n * Extracted from Spinner.tsx to break the layer violation where\n * service-layer code (claude.ts, query.ts) imported from a UI component.\n *\n * Provides per-agent streaming state tracking with hierarchical context support.\n */\n\n// Streaming phases for better UX feedback\nexport type StreamingPhase =\n | 'thinking' // Initial thinking phase\n | 'generating' // Generating response content\n | 'tool_use' // Executing a tool\n | 'waiting' // Waiting for API response\n | 'deep_thinking' // Extended thinking mode (Claude thinking blocks)\n | 'retrying' // API retry in progress\n | 'permission' // Waiting for user permission\n | 'compacting' // Compacting conversation context\n | 'concurrent' // Running concurrent tasks\n\n// Streaming state type definition\nexport interface StreamingStateData {\n phase: StreamingPhase\n toolName?: string\n tokenCount?: number\n chunkCount?: number\n // New fields for enhanced feedback\n retryCount?: number\n maxRetries?: number\n errorName?: string\n concurrentCount?: number\n thinkingMaxTokens?: number\n // Token usage from API (real-time streaming)\n inputTokens?: number\n outputTokens?: number\n // Character counts for approximate token estimation\n sentChars?: number // Characters sent to API (input)\n receivedChars?: number // Characters received from API (output)\n // Thinking timing\n thinkingStartTime?: number\n thinkingDurationMs?: number\n}\n\n// Default state factory\nfunction createDefaultState(): StreamingStateData {\n return { phase: 'thinking' }\n}\n\n// Store streaming state per agent (agentId -> state)\n// '__main__' is used for the main/root agent\nconst streamingStates: Map<string, StreamingStateData> = new Map([\n ['__main__', createDefaultState()],\n])\n\n// Current active agent context (stack to support nesting)\nconst agentContextStack: string[] = ['__main__']\n\n/**\n * Get the current active agent ID\n */\nexport function getCurrentAgentContext(): string {\n return agentContextStack[agentContextStack.length - 1] ?? '__main__'\n}\n\n/**\n * Push a new agent context (when entering a subagent)\n */\nexport function pushAgentContext(agentId: string): void {\n agentContextStack.push(agentId)\n if (!streamingStates.has(agentId)) {\n streamingStates.set(agentId, createDefaultState())\n }\n}\n\n/**\n * Pop the current agent context (when exiting a subagent)\n */\nexport function popAgentContext(): string | undefined {\n if (agentContextStack.length > 1) {\n return agentContextStack.pop()\n }\n return undefined\n}\n\n/**\n * Set streaming state for a specific agent (or current context if not specified)\n */\nexport function setStreamingState(\n state: Partial<StreamingStateData>,\n agentId?: string,\n): void {\n const targetId = agentId ?? getCurrentAgentContext()\n const current = streamingStates.get(targetId) ?? createDefaultState()\n streamingStates.set(targetId, { ...current, ...state })\n}\n\n/**\n * Reset streaming state for a specific agent (or current context if not specified)\n */\nexport function resetStreamingState(agentId?: string): void {\n const targetId = agentId ?? getCurrentAgentContext()\n streamingStates.set(targetId, createDefaultState())\n}\n\n/**\n * Get streaming state for a specific agent (or current context if not specified)\n */\nexport function getStreamingState(agentId?: string): StreamingStateData {\n const targetId = agentId ?? getCurrentAgentContext()\n return streamingStates.get(targetId) ?? createDefaultState()\n}\n\n/**\n * Get streaming state for the main/root agent (used by main Spinner)\n */\nexport function getMainStreamingState(): StreamingStateData {\n return streamingStates.get('__main__') ?? createDefaultState()\n}\n\n/**\n * Clean up streaming state for a completed agent\n */\nexport function cleanupAgentStreamingState(agentId: string): void {\n streamingStates.delete(agentId)\n}\n"],
5
- "mappings": "AA6CA,SAAS,qBAAyC;AAChD,SAAO,EAAE,OAAO,WAAW;AAC7B;AAIA,MAAM,kBAAmD,oBAAI,IAAI;AAAA,EAC/D,CAAC,YAAY,mBAAmB,CAAC;AACnC,CAAC;AAGD,MAAM,oBAA8B,CAAC,UAAU;AAKxC,SAAS,yBAAiC;AAC/C,SAAO,kBAAkB,kBAAkB,SAAS,CAAC,KAAK;AAC5D;AAKO,SAAS,iBAAiB,SAAuB;AACtD,oBAAkB,KAAK,OAAO;AAC9B,MAAI,CAAC,gBAAgB,IAAI,OAAO,GAAG;AACjC,oBAAgB,IAAI,SAAS,mBAAmB,CAAC;AAAA,EACnD;AACF;AAKO,SAAS,kBAAsC;AACpD,MAAI,kBAAkB,SAAS,GAAG;AAChC,WAAO,kBAAkB,IAAI;AAAA,EAC/B;AACA,SAAO;AACT;AAKO,SAAS,kBACd,OACA,SACM;AACN,QAAM,WAAW,WAAW,uBAAuB;AACnD,QAAM,UAAU,gBAAgB,IAAI,QAAQ,KAAK,mBAAmB;AACpE,kBAAgB,IAAI,UAAU,EAAE,GAAG,SAAS,GAAG,MAAM,CAAC;AACxD;AAKO,SAAS,oBAAoB,SAAwB;AAC1D,QAAM,WAAW,WAAW,uBAAuB;AACnD,kBAAgB,IAAI,UAAU,mBAAmB,CAAC;AACpD;AAKO,SAAS,kBAAkB,SAAsC;AACtE,QAAM,WAAW,WAAW,uBAAuB;AACnD,SAAO,gBAAgB,IAAI,QAAQ,KAAK,mBAAmB;AAC7D;AAKO,SAAS,wBAA4C;AAC1D,SAAO,gBAAgB,IAAI,UAAU,KAAK,mBAAmB;AAC/D;AAKO,SAAS,2BAA2B,SAAuB;AAChE,kBAAgB,OAAO,OAAO;AAChC;",
4
+ "sourcesContent": ["/**\n * Streaming State Management\n *\n * Extracted from Spinner.tsx to break the layer violation where\n * service-layer code (claude.ts, query.ts) imported from a UI component.\n *\n * Provides per-agent streaming state tracking with hierarchical context support.\n */\n\n// Streaming phases for better UX feedback\nexport type StreamingPhase =\n | 'thinking' // Initial thinking phase\n | 'generating' // Generating response content\n | 'tool_use' // Executing a tool\n | 'waiting' // Waiting for API response\n | 'deep_thinking' // Extended thinking mode (Claude thinking blocks)\n | 'retrying' // API retry in progress\n | 'permission' // Waiting for user permission\n | 'compacting' // Compacting conversation context\n | 'concurrent' // Running concurrent tasks\n\n// Streaming state type definition\nexport interface StreamingStateData {\n phase: StreamingPhase\n toolName?: string\n tokenCount?: number\n chunkCount?: number\n // New fields for enhanced feedback\n retryCount?: number\n maxRetries?: number\n errorName?: string\n retryDelayMs?: number\n concurrentCount?: number\n thinkingMaxTokens?: number\n // Token usage from API (real-time streaming)\n inputTokens?: number\n outputTokens?: number\n // Character counts for approximate token estimation\n sentChars?: number // Characters sent to API (input)\n sentCharsSetAt?: number // Timestamp when sentChars was set (for UI count-up animation)\n receivedChars?: number // Characters received from API (output)\n // Thinking timing\n thinkingStartTime?: number\n thinkingDurationMs?: number\n // Turn timing: when the current turn started (survives component remounts)\n turnStartedAt?: number\n // Streaming text buffer: accumulates text chunks for typewriter preview\n streamingText?: string\n // Cumulative output tokens across API calls within a turn.\n // Prevents the display from resetting to 0 between tool-use and next API call.\n cumulativeOutputTokens?: number\n}\n\n// Default state factory\nfunction createDefaultState(): StreamingStateData {\n return { phase: 'thinking' }\n}\n\n// Store streaming state per agent (agentId -> state)\n// '__main__' is used for the main/root agent\nconst streamingStates: Map<string, StreamingStateData> = new Map([\n ['__main__', createDefaultState()],\n])\n\n// Current active agent context (stack to support nesting)\nconst agentContextStack: string[] = ['__main__']\n\n/**\n * Get the current active agent ID\n */\nexport function getCurrentAgentContext(): string {\n return agentContextStack[agentContextStack.length - 1] ?? '__main__'\n}\n\n/**\n * Push a new agent context (when entering a subagent)\n */\nexport function pushAgentContext(agentId: string): void {\n agentContextStack.push(agentId)\n if (!streamingStates.has(agentId)) {\n streamingStates.set(agentId, createDefaultState())\n }\n}\n\n/**\n * Pop the current agent context (when exiting a subagent)\n */\nexport function popAgentContext(expectedId?: string): string | undefined {\n if (agentContextStack.length > 1) {\n const top = agentContextStack[agentContextStack.length - 1]\n if (expectedId && top !== expectedId) {\n import('./debugLogger')\n .then(({ debug }) => {\n debug.warn('AGENT_CONTEXT_MISMATCH', {\n expected: expectedId,\n actual: top,\n })\n })\n .catch(() => {})\n }\n return agentContextStack.pop()\n }\n return undefined\n}\n\n/**\n * Set streaming state for a specific agent (or current context if not specified)\n */\nexport function setStreamingState(\n state: Partial<StreamingStateData>,\n agentId?: string,\n): void {\n const targetId = agentId ?? getCurrentAgentContext()\n const current = streamingStates.get(targetId) ?? createDefaultState()\n streamingStates.set(targetId, { ...current, ...state })\n}\n\n/**\n * Reset streaming state for a specific agent (or current context if not specified)\n */\nexport function resetStreamingState(agentId?: string): void {\n const targetId = agentId ?? getCurrentAgentContext()\n streamingStates.set(targetId, createDefaultState())\n}\n\n/**\n * Get streaming state for a specific agent (or current context if not specified)\n */\nexport function getStreamingState(agentId?: string): StreamingStateData {\n const targetId = agentId ?? getCurrentAgentContext()\n return streamingStates.get(targetId) ?? createDefaultState()\n}\n\n/**\n * Get streaming state for the main/root agent (used by main Spinner)\n */\nexport function getMainStreamingState(): StreamingStateData {\n return streamingStates.get('__main__') ?? createDefaultState()\n}\n\n/**\n * Clean up streaming state for a completed agent\n */\nexport function cleanupAgentStreamingState(agentId: string): void {\n streamingStates.delete(agentId)\n}\n"],
5
+ "mappings": "AAsDA,SAAS,qBAAyC;AAChD,SAAO,EAAE,OAAO,WAAW;AAC7B;AAIA,MAAM,kBAAmD,oBAAI,IAAI;AAAA,EAC/D,CAAC,YAAY,mBAAmB,CAAC;AACnC,CAAC;AAGD,MAAM,oBAA8B,CAAC,UAAU;AAKxC,SAAS,yBAAiC;AAC/C,SAAO,kBAAkB,kBAAkB,SAAS,CAAC,KAAK;AAC5D;AAKO,SAAS,iBAAiB,SAAuB;AACtD,oBAAkB,KAAK,OAAO;AAC9B,MAAI,CAAC,gBAAgB,IAAI,OAAO,GAAG;AACjC,oBAAgB,IAAI,SAAS,mBAAmB,CAAC;AAAA,EACnD;AACF;AAKO,SAAS,gBAAgB,YAAyC;AACvE,MAAI,kBAAkB,SAAS,GAAG;AAChC,UAAM,MAAM,kBAAkB,kBAAkB,SAAS,CAAC;AAC1D,QAAI,cAAc,QAAQ,YAAY;AACpC,aAAO,eAAe,EACnB,KAAK,CAAC,EAAE,MAAM,MAAM;AACnB,cAAM,KAAK,0BAA0B;AAAA,UACnC,UAAU;AAAA,UACV,QAAQ;AAAA,QACV,CAAC;AAAA,MACH,CAAC,EACA,MAAM,MAAM;AAAA,MAAC,CAAC;AAAA,IACnB;AACA,WAAO,kBAAkB,IAAI;AAAA,EAC/B;AACA,SAAO;AACT;AAKO,SAAS,kBACd,OACA,SACM;AACN,QAAM,WAAW,WAAW,uBAAuB;AACnD,QAAM,UAAU,gBAAgB,IAAI,QAAQ,KAAK,mBAAmB;AACpE,kBAAgB,IAAI,UAAU,EAAE,GAAG,SAAS,GAAG,MAAM,CAAC;AACxD;AAKO,SAAS,oBAAoB,SAAwB;AAC1D,QAAM,WAAW,WAAW,uBAAuB;AACnD,kBAAgB,IAAI,UAAU,mBAAmB,CAAC;AACpD;AAKO,SAAS,kBAAkB,SAAsC;AACtE,QAAM,WAAW,WAAW,uBAAuB;AACnD,SAAO,gBAAgB,IAAI,QAAQ,KAAK,mBAAmB;AAC7D;AAKO,SAAS,wBAA4C;AAC1D,SAAO,gBAAgB,IAAI,UAAU,KAAK,mBAAmB;AAC/D;AAKO,SAAS,2BAA2B,SAAuB;AAChE,kBAAgB,OAAO,OAAO;AAChC;",
6
6
  "names": []
7
7
  }
@@ -23,7 +23,7 @@ function getNestedTasks(transcript) {
23
23
  const content = msg.message.content;
24
24
  if (!content || !Array.isArray(content)) continue;
25
25
  for (const block of content) {
26
- if (block.type === "tool_use" && block.name === "Task") {
26
+ if (block.type === "tool_use" && (block.name === "Agent" || block.name === "Task")) {
27
27
  const toolUse = block;
28
28
  const nestedAgentId = getAgentIdByToolUseId(toolUse.id);
29
29
  if (nestedAgentId) {
@@ -210,6 +210,7 @@ function getToolUseDescription(toolUse) {
210
210
  return input.pattern ? `"${input.pattern}"` : "content";
211
211
  case "Bash":
212
212
  return input.command ? String(input.command).slice(0, 50) + (String(input.command).length > 50 ? "..." : "") : "command";
213
+ case "Agent":
213
214
  case "Task":
214
215
  return input.description ? String(input.description) : "sub-task";
215
216
  case "WebFetch":