@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/CircuitBreaker.ts"],
4
- "sourcesContent": ["/**\n * Circuit Breaker pattern implementation for handling failing services gracefully\n *\n * States:\n * - CLOSED: Service is healthy, requests pass through normally\n * - OPEN: Service is unhealthy, requests fail immediately\n * - HALF_OPEN: Testing if service has recovered, limited requests allowed\n *\n * Transitions:\n * - CLOSED \u2192 OPEN: When failure count exceeds threshold\n * - OPEN \u2192 HALF_OPEN: After cooldown timeout\n * - HALF_OPEN \u2192 CLOSED: When success count exceeds threshold\n * - HALF_OPEN \u2192 OPEN: When a request fails\n */\n\nexport interface CircuitBreakerConfig {\n /** Number of failures that trigger opening the circuit (default: 5) */\n failureThreshold: number\n /** Number of successful requests needed to close circuit from HALF_OPEN (default: 2) */\n successThreshold: number\n /** Time in ms before transitioning from OPEN to HALF_OPEN (default: 30000) */\n openTimeout: number\n /** Optional timeout in ms for operations (default: none) */\n halfOpenTimeout?: number\n}\n\nexport class CircuitOpenError extends Error {\n constructor(\n public readonly remainingCooldown: number,\n serverName?: string,\n ) {\n const message = serverName\n ? `Circuit breaker for \"${serverName}\" is open. Retry in ${Math.ceil(remainingCooldown / 1000)}s`\n : `Circuit breaker is open. Retry in ${Math.ceil(remainingCooldown / 1000)}s`\n super(message)\n this.name = 'CircuitOpenError'\n }\n}\n\nexport type CircuitBreakerState = 'closed' | 'open' | 'half-open'\n\nexport interface CircuitBreakerStats {\n state: CircuitBreakerState\n failureCount: number\n successCount: number\n lastFailureTime: number | null\n totalRequests: number\n totalFailures: number\n}\n\nexport type CircuitBreakerListener = (\n event: 'state-change' | 'failure' | 'success',\n details: {\n state?: CircuitBreakerState\n previousState?: CircuitBreakerState\n error?: Error\n },\n) => void\n\n/**\n * Circuit Breaker implementation for fault tolerance\n *\n * Prevents cascading failures by failing fast when a service is unhealthy,\n * while automatically attempting recovery when the service potentially recovers.\n */\nexport class CircuitBreaker<T = unknown> {\n private state: CircuitBreakerState = 'closed'\n private failureCount: number = 0\n private successCount: number = 0\n private lastFailureTime: number | null = null\n private readonly config: Required<CircuitBreakerConfig>\n private readonly listeners: Set<CircuitBreakerListener> = new Set()\n private readonly name: string\n private totalRequests: number = 0\n private totalFailures: number = 0\n\n constructor(\n name: string = 'default',\n config?: Partial<CircuitBreakerConfig>,\n ) {\n this.name = name\n this.config = {\n failureThreshold: config?.failureThreshold ?? 5,\n successThreshold: config?.successThreshold ?? 2,\n openTimeout: config?.openTimeout ?? 30000,\n halfOpenTimeout: config?.halfOpenTimeout ?? 30000,\n }\n }\n\n /**\n * Execute an operation through the circuit breaker\n * @throws {CircuitOpenError} If circuit is open\n * @throws {Error} If operation fails\n */\n async execute<R>(operation: () => Promise<R>): Promise<R> {\n this.totalRequests++\n\n // Check if we need to transition from OPEN to HALF_OPEN\n if (this.state === 'open') {\n const cooldownRemaining = this.getRemainingCooldown()\n if (cooldownRemaining <= 0) {\n this.transition('half-open')\n } else {\n const error = new CircuitOpenError(cooldownRemaining, this.name)\n this.notifyListeners('failure', { error })\n throw error\n }\n }\n\n // Execute the operation\n try {\n const result = await operation()\n this.onSuccess()\n return result\n } catch (error) {\n this.onFailure(error instanceof Error ? error : new Error(String(error)))\n throw error\n }\n }\n\n /**\n * Execute with timeout protection\n * @throws {CircuitOpenError} If circuit is open\n * @throws {Error} If operation times out or fails\n */\n async executeWithTimeout<R>(\n operation: () => Promise<R>,\n timeoutMs?: number,\n ): Promise<R> {\n const timeout = timeoutMs ?? this.config.halfOpenTimeout\n if (!timeout) {\n return this.execute(operation)\n }\n\n return Promise.race([\n this.execute(operation),\n new Promise<R>((_, reject) =>\n setTimeout(\n () => reject(new Error(`Operation timeout after ${timeout}ms`)),\n timeout,\n ),\n ),\n ])\n }\n\n /**\n * Get current circuit state\n */\n getState(): CircuitBreakerState {\n return this.state\n }\n\n /**\n * Get detailed statistics\n */\n getStats(): CircuitBreakerStats {\n return {\n state: this.state,\n failureCount: this.failureCount,\n successCount: this.successCount,\n lastFailureTime: this.lastFailureTime,\n totalRequests: this.totalRequests,\n totalFailures: this.totalFailures,\n }\n }\n\n /**\n * Get remaining cooldown time in milliseconds\n */\n getRemainingCooldown(): number {\n if (!this.lastFailureTime) {\n return 0\n }\n return Math.max(\n 0,\n this.config.openTimeout - (Date.now() - this.lastFailureTime),\n )\n }\n\n /**\n * Register a listener for state changes and events\n */\n on(listener: CircuitBreakerListener): () => void {\n this.listeners.add(listener)\n return () => {\n this.listeners.delete(listener)\n }\n }\n\n /**\n * Reset the circuit breaker to CLOSED state\n */\n reset(): void {\n const previousState = this.state\n this.state = 'closed'\n this.failureCount = 0\n this.successCount = 0\n this.lastFailureTime = null\n this.totalRequests = 0\n this.totalFailures = 0\n\n this.notifyListeners('state-change', {\n state: this.state,\n previousState,\n })\n }\n\n /**\n * Manually open the circuit (for testing or explicit fault injection)\n */\n forceOpen(): void {\n this.transition('open')\n }\n\n /**\n * Manually close the circuit (for recovery testing)\n */\n forceClosed(): void {\n this.transition('closed')\n }\n\n /**\n * Manually transition to half-open state (for testing)\n */\n forceHalfOpen(): void {\n this.transition('half-open')\n }\n\n // Private methods\n\n private transition(newState: CircuitBreakerState): void {\n if (newState === this.state) {\n return\n }\n\n const previousState = this.state\n this.state = newState\n\n // Reset counters on state transition\n if (newState === 'closed') {\n this.failureCount = 0\n this.successCount = 0\n } else if (newState === 'half-open') {\n this.successCount = 0\n this.failureCount = 0\n }\n\n this.notifyListeners('state-change', {\n state: newState,\n previousState,\n })\n }\n\n private onSuccess(): void {\n if (this.state === 'half-open') {\n this.successCount++\n if (this.successCount >= this.config.successThreshold) {\n this.transition('closed')\n }\n } else if (this.state === 'closed') {\n this.failureCount = 0\n }\n\n this.notifyListeners('success', {})\n }\n\n private onFailure(error: Error): void {\n this.failureCount++\n this.totalFailures++\n this.lastFailureTime = Date.now()\n\n if (this.state === 'closed') {\n if (this.failureCount >= this.config.failureThreshold) {\n this.transition('open')\n }\n } else if (this.state === 'half-open') {\n // Any failure in half-open state goes back to open\n this.transition('open')\n }\n\n this.notifyListeners('failure', { error })\n }\n\n private notifyListeners(\n event: 'state-change' | 'failure' | 'success',\n details: {\n state?: CircuitBreakerState\n previousState?: CircuitBreakerState\n error?: Error\n },\n ): void {\n for (const listener of this.listeners) {\n try {\n listener(event, details)\n } catch {\n // Ignore listener errors to prevent them from affecting the circuit\n }\n }\n }\n}\n\n/**\n * Create a simple factory for managing multiple circuit breakers\n */\nexport class CircuitBreakerRegistry {\n private readonly breakers = new Map<string, CircuitBreaker>()\n private readonly defaultConfig?: Partial<CircuitBreakerConfig>\n\n constructor(defaultConfig?: Partial<CircuitBreakerConfig>) {\n this.defaultConfig = defaultConfig\n }\n\n /**\n * Get or create a circuit breaker by name\n */\n getOrCreate(\n name: string,\n config?: Partial<CircuitBreakerConfig>,\n ): CircuitBreaker {\n if (!this.breakers.has(name)) {\n const mergedConfig = { ...this.defaultConfig, ...config }\n this.breakers.set(name, new CircuitBreaker(name, mergedConfig))\n }\n return this.breakers.get(name)!\n }\n\n /**\n * Get all registered circuit breakers\n */\n getAll(): Map<string, CircuitBreaker> {\n return new Map(this.breakers)\n }\n\n /**\n * Reset all circuit breakers\n */\n resetAll(): void {\n for (const breaker of this.breakers.values()) {\n breaker.reset()\n }\n }\n\n /**\n * Clear all circuit breakers\n */\n clear(): void {\n this.breakers.clear()\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * Circuit Breaker pattern implementation for handling failing services gracefully\n *\n * States:\n * - CLOSED: Service is healthy, requests pass through normally\n * - OPEN: Service is unhealthy, requests fail immediately\n * - HALF_OPEN: Testing if service has recovered, limited requests allowed\n *\n * Transitions:\n * - CLOSED \u2192 OPEN: When failure count exceeds threshold\n * - OPEN \u2192 HALF_OPEN: After cooldown timeout\n * - HALF_OPEN \u2192 CLOSED: When success count exceeds threshold\n * - HALF_OPEN \u2192 OPEN: When a request fails\n */\n\nexport interface CircuitBreakerConfig {\n /** Number of failures that trigger opening the circuit (default: 5) */\n failureThreshold: number\n /** Number of successful requests needed to close circuit from HALF_OPEN (default: 2) */\n successThreshold: number\n /** Time in ms before transitioning from OPEN to HALF_OPEN (default: 30000) */\n openTimeout: number\n /** Optional timeout in ms for operations (default: none) */\n halfOpenTimeout?: number\n}\n\nexport class CircuitOpenError extends Error {\n constructor(\n public readonly remainingCooldown: number,\n serverName?: string,\n ) {\n const message = serverName\n ? `Circuit breaker for \"${serverName}\" is open. Retry in ${Math.ceil(remainingCooldown / 1000)}s`\n : `Circuit breaker is open. Retry in ${Math.ceil(remainingCooldown / 1000)}s`\n super(message)\n this.name = 'CircuitOpenError'\n }\n}\n\nexport type CircuitBreakerState = 'closed' | 'open' | 'half-open'\n\nexport interface CircuitBreakerStats {\n state: CircuitBreakerState\n failureCount: number\n successCount: number\n lastFailureTime: number | null\n totalRequests: number\n totalFailures: number\n}\n\nexport type CircuitBreakerListener = (\n event: 'state-change' | 'failure' | 'success',\n details: {\n state?: CircuitBreakerState\n previousState?: CircuitBreakerState\n error?: Error\n },\n) => void\n\n/**\n * Circuit Breaker implementation for fault tolerance\n *\n * Prevents cascading failures by failing fast when a service is unhealthy,\n * while automatically attempting recovery when the service potentially recovers.\n */\nexport class CircuitBreaker<T = unknown> {\n private state: CircuitBreakerState = 'closed'\n private failureCount: number = 0\n private successCount: number = 0\n private lastFailureTime: number | null = null\n private readonly config: Required<CircuitBreakerConfig>\n private readonly listeners: Set<CircuitBreakerListener> = new Set()\n private readonly name: string\n private totalRequests: number = 0\n private totalFailures: number = 0\n\n constructor(\n name: string = 'default',\n config?: Partial<CircuitBreakerConfig>,\n ) {\n this.name = name\n this.config = {\n failureThreshold: config?.failureThreshold ?? 5,\n successThreshold: config?.successThreshold ?? 2,\n openTimeout: config?.openTimeout ?? 30000,\n halfOpenTimeout: config?.halfOpenTimeout ?? 30000,\n }\n }\n\n /**\n * Execute an operation through the circuit breaker\n * @throws {CircuitOpenError} If circuit is open\n * @throws {Error} If operation fails\n */\n async execute<R>(operation: () => Promise<R>): Promise<R> {\n this.totalRequests++\n\n // Check if we need to transition from OPEN to HALF_OPEN\n if (this.state === 'open') {\n const cooldownRemaining = this.getRemainingCooldown()\n if (cooldownRemaining <= 0) {\n this.transition('half-open')\n } else {\n const error = new CircuitOpenError(cooldownRemaining, this.name)\n this.notifyListeners('failure', { error })\n throw error\n }\n }\n\n // Execute the operation\n try {\n const result = await operation()\n this.onSuccess()\n return result\n } catch (error) {\n this.onFailure(error instanceof Error ? error : new Error(String(error)))\n throw error\n }\n }\n\n /**\n * Execute with timeout protection\n * @throws {CircuitOpenError} If circuit is open\n * @throws {Error} If operation times out or fails\n */\n async executeWithTimeout<R>(\n operation: () => Promise<R>,\n timeoutMs?: number,\n ): Promise<R> {\n const timeout = timeoutMs ?? this.config.halfOpenTimeout\n if (!timeout) {\n return this.execute(operation)\n }\n\n let timeoutId: ReturnType<typeof setTimeout> | undefined\n try {\n const result = await Promise.race([\n this.execute(operation),\n new Promise<R>((_, reject) => {\n timeoutId = setTimeout(\n () => reject(new Error(`Operation timeout after ${timeout}ms`)),\n timeout,\n )\n }),\n ])\n return result\n } finally {\n if (timeoutId !== undefined) clearTimeout(timeoutId)\n }\n }\n\n /**\n * Get current circuit state\n */\n getState(): CircuitBreakerState {\n return this.state\n }\n\n /**\n * Get detailed statistics\n */\n getStats(): CircuitBreakerStats {\n return {\n state: this.state,\n failureCount: this.failureCount,\n successCount: this.successCount,\n lastFailureTime: this.lastFailureTime,\n totalRequests: this.totalRequests,\n totalFailures: this.totalFailures,\n }\n }\n\n /**\n * Get remaining cooldown time in milliseconds\n */\n getRemainingCooldown(): number {\n if (!this.lastFailureTime) {\n return 0\n }\n return Math.max(\n 0,\n this.config.openTimeout - (Date.now() - this.lastFailureTime),\n )\n }\n\n /**\n * Register a listener for state changes and events\n */\n on(listener: CircuitBreakerListener): () => void {\n this.listeners.add(listener)\n return () => {\n this.listeners.delete(listener)\n }\n }\n\n /**\n * Reset the circuit breaker to CLOSED state\n */\n reset(): void {\n const previousState = this.state\n this.state = 'closed'\n this.failureCount = 0\n this.successCount = 0\n this.lastFailureTime = null\n this.totalRequests = 0\n this.totalFailures = 0\n\n this.notifyListeners('state-change', {\n state: this.state,\n previousState,\n })\n }\n\n /**\n * Manually open the circuit (for testing or explicit fault injection)\n */\n forceOpen(): void {\n this.transition('open')\n }\n\n /**\n * Manually close the circuit (for recovery testing)\n */\n forceClosed(): void {\n this.transition('closed')\n }\n\n /**\n * Manually transition to half-open state (for testing)\n */\n forceHalfOpen(): void {\n this.transition('half-open')\n }\n\n // Private methods\n\n private transition(newState: CircuitBreakerState): void {\n if (newState === this.state) {\n return\n }\n\n const previousState = this.state\n this.state = newState\n\n // Reset counters on state transition\n if (newState === 'closed') {\n this.failureCount = 0\n this.successCount = 0\n } else if (newState === 'half-open') {\n this.successCount = 0\n this.failureCount = 0\n }\n\n this.notifyListeners('state-change', {\n state: newState,\n previousState,\n })\n }\n\n private onSuccess(): void {\n if (this.state === 'half-open') {\n this.successCount++\n if (this.successCount >= this.config.successThreshold) {\n this.transition('closed')\n }\n } else if (this.state === 'closed') {\n this.failureCount = 0\n }\n\n this.notifyListeners('success', {})\n }\n\n private onFailure(error: Error): void {\n this.failureCount++\n this.totalFailures++\n this.lastFailureTime = Date.now()\n\n if (this.state === 'closed') {\n if (this.failureCount >= this.config.failureThreshold) {\n this.transition('open')\n }\n } else if (this.state === 'half-open') {\n // Any failure in half-open state goes back to open\n this.transition('open')\n }\n\n this.notifyListeners('failure', { error })\n }\n\n private notifyListeners(\n event: 'state-change' | 'failure' | 'success',\n details: {\n state?: CircuitBreakerState\n previousState?: CircuitBreakerState\n error?: Error\n },\n ): void {\n for (const listener of this.listeners) {\n try {\n listener(event, details)\n } catch {\n // Ignore listener errors to prevent them from affecting the circuit\n }\n }\n }\n}\n\n/**\n * Create a simple factory for managing multiple circuit breakers\n */\nexport class CircuitBreakerRegistry {\n private readonly breakers = new Map<string, CircuitBreaker>()\n private readonly defaultConfig?: Partial<CircuitBreakerConfig>\n\n constructor(defaultConfig?: Partial<CircuitBreakerConfig>) {\n this.defaultConfig = defaultConfig\n }\n\n /**\n * Get or create a circuit breaker by name\n */\n getOrCreate(\n name: string,\n config?: Partial<CircuitBreakerConfig>,\n ): CircuitBreaker {\n if (!this.breakers.has(name)) {\n const mergedConfig = { ...this.defaultConfig, ...config }\n this.breakers.set(name, new CircuitBreaker(name, mergedConfig))\n }\n return this.breakers.get(name)!\n }\n\n /**\n * Get all registered circuit breakers\n */\n getAll(): Map<string, CircuitBreaker> {\n return new Map(this.breakers)\n }\n\n /**\n * Reset all circuit breakers\n */\n resetAll(): void {\n for (const breaker of this.breakers.values()) {\n breaker.reset()\n }\n }\n\n /**\n * Clear all circuit breakers\n */\n clear(): void {\n this.breakers.clear()\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,16 +1,13 @@
1
- import {
2
- existsSync,
3
- readFileSync,
4
- readdirSync,
5
- statSync,
6
- watch
7
- } from "fs";
1
+ import { existsSync, readFileSync, watch } from "fs";
2
+ import { readdir, stat, readFile } from "fs/promises";
8
3
  import { join } from "path";
9
4
  import { homedir } from "os";
10
5
  import matter from "gray-matter";
11
6
  import { getCwd } from "./state.js";
12
7
  import { memoize } from "lodash-es";
8
+ import { LRUCache } from "lru-cache";
13
9
  import { loadAllPlugins } from "./pluginLoader.js";
10
+ import { debug as debugLog } from "./debugLogger.js";
14
11
  const warnedAgents = /* @__PURE__ */ new Set();
15
12
  const BUILTIN_AGENTS = [
16
13
  // general-purpose: Default agent for multi-step tasks
@@ -72,30 +69,89 @@ You are READ-ONLY. You cannot modify any files.`,
72
69
  // Inherit caller's model
73
70
  permissionMode: "plan",
74
71
  // Read-only mode
75
- systemPrompt: `You are a planning agent specialized in analyzing codebases and creating implementation plans.
72
+ systemPrompt: `You are a planning agent. Analyze the codebase and create an implementation plan.
73
+
74
+ Your output must include:
75
+ 1. Context \u2014 Problem being solved, motivation, intended outcome
76
+ 2. Critical file paths \u2014 All files to modify/create
77
+ 3. Recommended approach \u2014 Step-by-step plan referencing existing utilities and patterns
78
+ 4. Verification \u2014 Testing procedures for end-to-end validation
79
+
80
+ Guidelines:
81
+ - Read relevant files to understand current patterns before designing
82
+ - Identify reusable utilities and existing conventions
83
+ - Consider edge cases and dependencies
84
+ - Be specific and actionable \u2014 reference exact file paths and function names
85
+
86
+ You are READ-ONLY. You cannot modify any files. Focus on planning, not execution.`,
87
+ location: "built-in"
88
+ },
89
+ // output-style-setup: Agent for creating custom output styles
90
+ {
91
+ agentType: "output-style-setup",
92
+ whenToUse: "Agent for creating and customizing output display styles. Use this when you need to help the user configure how Minto formats and displays tool results, assistant responses, or status messages.",
93
+ tools: ["Read", "Write", "Edit", "Glob", "Grep"],
94
+ model_name: "main",
95
+ systemPrompt: `You are an output style configuration agent for Minto CLI.
76
96
 
77
97
  Your role:
78
- - Understand requirements and constraints
79
- - Analyze existing code patterns and architecture
80
- - Create detailed, step-by-step implementation plans
81
- - Identify potential issues and trade-offs
82
- - Recommend best approaches based on codebase conventions
98
+ - Help users create custom output styles for Minto's terminal display
99
+ - Modify style configuration files to adjust formatting, colors, and layout
100
+ - Read existing style files to understand current configuration
83
101
 
84
102
  Guidelines:
85
- - Read relevant files to understand current patterns
86
- - Identify all files that will need modification
87
- - Consider edge cases and error handling
88
- - Note any dependencies or prerequisites
89
- - Provide specific, actionable steps
103
+ - Check existing style files in .minto/ and src/utils/style.ts first
104
+ - Follow the existing code style pattern exactly
105
+ - Make minimal, focused changes
106
+ - Validate that style changes won't break existing functionality`,
107
+ location: "built-in"
108
+ },
109
+ // statusline-setup: Agent for configuring the status line
110
+ {
111
+ agentType: "statusline-setup",
112
+ whenToUse: "Agent for configuring the Minto CLI status line. Use this when the user wants to customize what information appears in the bottom status bar (model name, token count, costs, git branch, etc.).",
113
+ tools: ["Read", "Edit"],
114
+ model_name: "main",
115
+ systemPrompt: `You are a status line configuration agent for Minto CLI.
90
116
 
91
- Output format:
92
- 1. Summary of the task
93
- 2. Files to modify/create (with paths)
94
- 3. Step-by-step implementation plan
95
- 4. Potential challenges or considerations
96
- 5. Testing approach
117
+ Your role:
118
+ - Help users configure the status line (bottom bar) display
119
+ - Modify status line settings to show/hide specific information segments
120
+ - Adjust the layout and formatting of the status line
97
121
 
98
- You are READ-ONLY. You cannot modify any files. Focus on planning, not execution.`,
122
+ Guidelines:
123
+ - Read existing status line configuration first
124
+ - The status line is rendered by Ink components in src/screens/
125
+ - Make minimal changes to configuration values
126
+ - Preserve existing formatting patterns`,
127
+ location: "built-in"
128
+ },
129
+ // minto-guide: Agent for answering questions about Minto CLI features
130
+ {
131
+ agentType: "minto-guide",
132
+ whenToUse: "Knowledge agent for answering questions about Minto CLI features, configuration, and usage. Use this when the user asks how to use a feature, what commands are available, or needs help understanding Minto capabilities.",
133
+ tools: ["Glob", "Grep", "Read", "WebFetch", "WebSearch"],
134
+ disallowedTools: ["Edit", "Write", "Bash", "NotebookEdit"],
135
+ model_name: "quick",
136
+ permissionMode: "plan",
137
+ systemPrompt: `You are a Minto CLI guide and knowledge agent.
138
+
139
+ Your role:
140
+ - Answer questions about Minto CLI features and capabilities
141
+ - Explain how to configure models, agents, plugins, and hooks
142
+ - Help users understand available commands and slash commands
143
+ - Provide usage examples and best practices
144
+
145
+ Guidelines:
146
+ - Search the codebase to find accurate, up-to-date information
147
+ - Check CLAUDE.md and MINTO.md files for project documentation
148
+ - Look at src/commands/ for available commands
149
+ - Look at src/tools/ for available tools
150
+ - Look at src/utils/agentLoader.ts for agent configuration
151
+ - Provide specific file paths and code references when helpful
152
+ - Be concise but thorough in explanations
153
+
154
+ You are READ-ONLY. You cannot modify any files.`,
99
155
  location: "built-in"
100
156
  },
101
157
  // Bash: Shell command execution agent (Claude Code spec)
@@ -196,6 +252,7 @@ function parsePermissionMode(mode) {
196
252
  "acceptEdits",
197
253
  "dontAsk",
198
254
  "plan",
255
+ "delegate",
199
256
  "bypassPermissions"
200
257
  ];
201
258
  if (typeof mode === "string" && validModes.includes(mode)) {
@@ -209,76 +266,116 @@ async function scanAgentDirectory(dirPath, location) {
209
266
  }
210
267
  const agents = [];
211
268
  try {
212
- const files = readdirSync(dirPath);
213
- for (const file of files) {
214
- if (!file.endsWith(".md")) continue;
215
- const filePath = join(dirPath, file);
216
- const stat = statSync(filePath);
217
- if (!stat.isFile()) continue;
218
- try {
219
- const content = readFileSync(filePath, "utf-8");
220
- if (!content.trim()) continue;
221
- const { data: frontmatter, content: body } = matter(content);
222
- if (!frontmatter.name || !frontmatter.description) {
223
- const headingMatch = body.match(/^#\s+(.+)/m);
224
- const firstParagraph = body.split(/\n\n/).find((p) => p.trim() && !p.trim().startsWith("#"));
225
- if (headingMatch) {
226
- if (!frontmatter.name) {
227
- frontmatter.name = headingMatch[1].trim();
228
- }
229
- if (!frontmatter.description) {
230
- frontmatter.description = firstParagraph?.trim() || frontmatter.name;
269
+ const files = await readdir(dirPath);
270
+ const mdFiles = files.filter((f) => f.endsWith(".md"));
271
+ const fileResults = await Promise.all(
272
+ mdFiles.map(async (file) => {
273
+ const filePath = join(dirPath, file);
274
+ try {
275
+ const fileStat = await stat(filePath);
276
+ if (!fileStat.isFile()) return null;
277
+ const content = await readFile(filePath, "utf-8");
278
+ if (!content.trim()) return null;
279
+ const { data: frontmatter, content: body } = matter(content);
280
+ if (!frontmatter.name || !frontmatter.description) {
281
+ const headingMatch = body.match(/^#\s+(.+)/m);
282
+ const firstParagraph = body.split(/\n\n/).find((p) => p.trim() && !p.trim().startsWith("#"));
283
+ if (headingMatch) {
284
+ if (!frontmatter.name) {
285
+ frontmatter.name = headingMatch[1].trim();
286
+ }
287
+ if (!frontmatter.description) {
288
+ frontmatter.description = firstParagraph?.trim() || frontmatter.name;
289
+ }
290
+ } else {
291
+ debugLog.warn("AGENT_MISSING_FIELDS", {
292
+ filePath,
293
+ message: "missing required fields (name, description)"
294
+ });
295
+ return null;
231
296
  }
232
- } else {
233
- console.warn(
234
- `Skipping ${filePath}: missing required fields (name, description)`
235
- );
236
- continue;
237
297
  }
238
- }
239
- if (frontmatter.model && !frontmatter.model_name && !warnedAgents.has(frontmatter.name) && process.env.MINTO_DEBUG_AGENTS) {
240
- console.warn(
241
- `\u26A0\uFE0F Agent ${frontmatter.name}: 'model' field is deprecated and ignored. Use 'model_name' instead, or omit to use default 'task' model.`
298
+ if (frontmatter.model && !frontmatter.model_name && !warnedAgents.has(frontmatter.name) && process.env.MINTO_DEBUG_AGENTS) {
299
+ debugLog.warn("AGENT_DEPRECATED_MODEL_FIELD", {
300
+ agent: frontmatter.name,
301
+ message: "'model' field is deprecated and ignored. Use 'model_name' instead."
302
+ });
303
+ warnedAgents.add(frontmatter.name);
304
+ }
305
+ const disallowedTools = parseDisallowedTools(
306
+ frontmatter.disallowedTools
242
307
  );
243
- warnedAgents.add(frontmatter.name);
308
+ const skills = parseSkills(frontmatter.skills);
309
+ const memory = parseMemory(frontmatter.memory);
310
+ const permissionMode = parsePermissionMode(frontmatter.permissionMode);
311
+ const agent = {
312
+ agentType: frontmatter.name,
313
+ whenToUse: frontmatter.description.replace(/\\n/g, "\n"),
314
+ tools: parseTools(frontmatter.tools),
315
+ systemPrompt: body.trim(),
316
+ location,
317
+ sourcePath: filePath,
318
+ // Optional fields - only include if defined
319
+ ...frontmatter.color && { color: frontmatter.color },
320
+ ...frontmatter.model_name && {
321
+ model_name: frontmatter.model_name
322
+ },
323
+ ...disallowedTools && { disallowedTools },
324
+ ...permissionMode && { permissionMode },
325
+ ...skills && { skills },
326
+ ...memory && { memory },
327
+ ...frontmatter.maxThinkingTokens && {
328
+ maxThinkingTokens: Number(frontmatter.maxThinkingTokens)
329
+ },
330
+ ...frontmatter.hooks && {
331
+ hooks: frontmatter.hooks
332
+ },
333
+ ...frontmatter.isolation && { isolation: frontmatter.isolation },
334
+ ...frontmatter.background && {
335
+ background: frontmatter.background === true
336
+ },
337
+ ...frontmatter.mcpServers && {
338
+ mcpServers: frontmatter.mcpServers
339
+ },
340
+ ...frontmatter.maxTurns && {
341
+ maxTurns: Number(frontmatter.maxTurns)
342
+ }
343
+ };
344
+ const MAX_PROJECT_PERM_LEVEL = 2;
345
+ if (location === "project" && agent.permissionMode) {
346
+ const { PERMISSION_LEVELS } = await import("../types/PermissionMode.js");
347
+ const currentLevel = PERMISSION_LEVELS[agent.permissionMode] ?? 1;
348
+ if (currentLevel > MAX_PROJECT_PERM_LEVEL) {
349
+ if (!warnedAgents.has(agent.agentType + ":perm")) {
350
+ debugLog.warn("AGENT_PERMISSION_CAPPED", {
351
+ agent: agent.agentType,
352
+ requested: agent.permissionMode,
353
+ capped: "acceptEdits"
354
+ });
355
+ warnedAgents.add(agent.agentType + ":perm");
356
+ }
357
+ agent.permissionMode = "acceptEdits";
358
+ }
359
+ }
360
+ if (location === "project" && agent.mcpServers) {
361
+ debugLog.warn("AGENT_MCPSERVERS_STRIPPED", {
362
+ agent: agent.agentType,
363
+ message: "mcpServers from project agents are ignored for security. Move to ~/.minto/agents/ to enable."
364
+ });
365
+ delete agent.mcpServers;
366
+ }
367
+ return agent;
368
+ } catch (error) {
369
+ debugLog.warn("AGENT_PARSE_FAILED", { filePath, error });
370
+ return null;
244
371
  }
245
- const disallowedTools = parseDisallowedTools(
246
- frontmatter.disallowedTools
247
- );
248
- const skills = parseSkills(frontmatter.skills);
249
- const memory = parseMemory(frontmatter.memory);
250
- const permissionMode = parsePermissionMode(frontmatter.permissionMode);
251
- const agent = {
252
- agentType: frontmatter.name,
253
- whenToUse: frontmatter.description.replace(/\\n/g, "\n"),
254
- tools: parseTools(frontmatter.tools),
255
- systemPrompt: body.trim(),
256
- location,
257
- sourcePath: filePath,
258
- // Optional fields - only include if defined
259
- ...frontmatter.color && { color: frontmatter.color },
260
- ...frontmatter.model_name && { model_name: frontmatter.model_name },
261
- ...disallowedTools && { disallowedTools },
262
- ...permissionMode && { permissionMode },
263
- ...skills && { skills },
264
- ...memory && { memory },
265
- ...frontmatter.maxThinkingTokens && {
266
- maxThinkingTokens: Number(frontmatter.maxThinkingTokens)
267
- },
268
- ...frontmatter.hooks && { hooks: frontmatter.hooks },
269
- ...frontmatter.isolation && { isolation: frontmatter.isolation },
270
- ...frontmatter.background && {
271
- background: frontmatter.background === true
272
- },
273
- ...frontmatter.mcpServers && { mcpServers: frontmatter.mcpServers }
274
- };
275
- agents.push(agent);
276
- } catch (error) {
277
- console.warn(`Failed to parse agent file ${filePath}:`, error);
278
- }
372
+ })
373
+ );
374
+ for (const agent of fileResults) {
375
+ if (agent) agents.push(agent);
279
376
  }
280
377
  } catch (error) {
281
- console.warn(`Failed to scan directory ${dirPath}:`, error);
378
+ debugLog.warn("AGENT_SCAN_FAILED", { dirPath, error });
282
379
  }
283
380
  return agents;
284
381
  }
@@ -304,16 +401,19 @@ async function loadPluginAgents() {
304
401
  frontmatter.description = firstParagraph?.trim() || frontmatter.name;
305
402
  }
306
403
  } else {
307
- console.warn(
308
- `Skipping plugin agent ${pluginAgent.filePath}: missing required fields (name, description)`
309
- );
404
+ debugLog.warn("PLUGIN_AGENT_MISSING_FIELDS", {
405
+ filePath: pluginAgent.filePath,
406
+ message: "missing required fields (name, description)"
407
+ });
310
408
  continue;
311
409
  }
312
410
  }
313
411
  if (frontmatter.model && !frontmatter.model_name && !warnedAgents.has(frontmatter.name) && process.env.MINTO_DEBUG_AGENTS) {
314
- console.warn(
315
- `\u26A0\uFE0F Plugin agent ${frontmatter.name} (from ${plugin.manifest.name}): 'model' field is deprecated and ignored. Use 'model_name' instead, or omit to use default 'task' model.`
316
- );
412
+ debugLog.warn("PLUGIN_AGENT_DEPRECATED_MODEL_FIELD", {
413
+ agent: frontmatter.name,
414
+ plugin: plugin.manifest.name,
415
+ message: "'model' field is deprecated and ignored. Use 'model_name' instead."
416
+ });
317
417
  warnedAgents.add(frontmatter.name);
318
418
  }
319
419
  const disallowedTools = parseDisallowedTools(
@@ -353,17 +453,42 @@ async function loadPluginAgents() {
353
453
  mcpServers: frontmatter.mcpServers
354
454
  }
355
455
  };
456
+ const MAX_PLUGIN_PERM_LEVEL = 2;
457
+ if (agent.permissionMode) {
458
+ const { PERMISSION_LEVELS } = await import("../types/PermissionMode.js");
459
+ const currentLevel = PERMISSION_LEVELS[agent.permissionMode] ?? 1;
460
+ if (currentLevel > MAX_PLUGIN_PERM_LEVEL) {
461
+ if (!warnedAgents.has(agent.agentType + ":perm")) {
462
+ debugLog.warn("PLUGIN_AGENT_PERMISSION_CAPPED", {
463
+ agent: agent.agentType,
464
+ plugin: plugin.manifest.name,
465
+ requested: agent.permissionMode,
466
+ capped: "acceptEdits"
467
+ });
468
+ warnedAgents.add(agent.agentType + ":perm");
469
+ }
470
+ agent.permissionMode = "acceptEdits";
471
+ }
472
+ }
473
+ if (agent.mcpServers) {
474
+ debugLog.warn("AGENT_MCPSERVERS_STRIPPED", {
475
+ agent: agent.agentType,
476
+ message: "mcpServers from plugin agents are ignored for security. Move to ~/.minto/agents/ to enable."
477
+ });
478
+ delete agent.mcpServers;
479
+ }
356
480
  agents.push(agent);
357
481
  } catch (error) {
358
- console.warn(
359
- `Failed to load plugin agent ${pluginAgent.name} from ${plugin.manifest.name}:`,
482
+ debugLog.warn("PLUGIN_AGENT_LOAD_FAILED", {
483
+ agent: pluginAgent.name,
484
+ plugin: plugin.manifest.name,
360
485
  error
361
- );
486
+ });
362
487
  }
363
488
  }
364
489
  }
365
490
  } catch (error) {
366
- console.warn("Failed to load plugin agents:", error);
491
+ debugLog.warn("PLUGIN_AGENTS_LOAD_FAILED", { error });
367
492
  }
368
493
  return agents;
369
494
  }
@@ -434,27 +559,39 @@ const getAllAgents = memoize(async () => {
434
559
  const { allAgents } = await loadAllAgents();
435
560
  return allAgents;
436
561
  });
562
+ const _agentByTypeCache = new LRUCache({
563
+ max: 64,
564
+ ttl: 5 * 60 * 1e3,
565
+ // 5 min TTL
566
+ ttlAutopurge: false
567
+ });
437
568
  function clearAgentCache() {
438
569
  getActiveAgents.cache?.clear?.();
439
570
  getAllAgents.cache?.clear?.();
440
- getAgentByType.cache?.clear?.();
571
+ _agentByTypeCache.clear();
441
572
  getAvailableAgentTypes.cache?.clear?.();
442
573
  }
443
- const getAgentByType = memoize(
444
- async (agentType) => {
445
- const agents = await getActiveAgents();
446
- const direct = agents.find((agent) => agent.agentType === agentType);
447
- if (direct) return direct;
448
- if (!agentType.includes(":")) {
449
- for (const agent of agents) {
450
- if (agent.agentType.includes(":") && agent.agentType.split(":").pop() === agentType) {
451
- return agent;
452
- }
574
+ async function getAgentByType(agentType) {
575
+ const cached = _agentByTypeCache.get(agentType);
576
+ if (cached !== void 0) return cached;
577
+ if (_agentByTypeCache.has(agentType)) return void 0;
578
+ const agents = await getActiveAgents();
579
+ const direct = agents.find((agent) => agent.agentType === agentType);
580
+ if (direct) {
581
+ _agentByTypeCache.set(agentType, direct);
582
+ return direct;
583
+ }
584
+ if (!agentType.includes(":")) {
585
+ for (const agent of agents) {
586
+ if (agent.agentType.includes(":") && agent.agentType.split(":").pop() === agentType) {
587
+ _agentByTypeCache.set(agentType, agent);
588
+ return agent;
453
589
  }
454
590
  }
455
- return void 0;
456
591
  }
457
- );
592
+ _agentByTypeCache.set(agentType, void 0);
593
+ return void 0;
594
+ }
458
595
  const getAvailableAgentTypes = memoize(async () => {
459
596
  const agents = await getActiveAgents();
460
597
  return agents.map((agent) => agent.agentType);