@within-7/minto 0.4.1 → 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
@@ -0,0 +1,155 @@
1
+ import {
2
+ writeFileSync,
3
+ readFileSync,
4
+ unlinkSync,
5
+ openSync,
6
+ closeSync
7
+ } from "fs";
8
+ import { join } from "path";
9
+ import { tmpdir } from "os";
10
+ import { platform as osPlatform } from "os";
11
+ import { spawnSync } from "child_process";
12
+ import { randomBytes } from "crypto";
13
+ const TERMINAL_EDITORS = /^(vi|vim|nvim|nano|emacs|pico|ed|micro|helix|hx|kak)$/i;
14
+ function getPlatformDefaultEditor() {
15
+ if (osPlatform() === "win32") return "notepad";
16
+ return "vi";
17
+ }
18
+ function resolveEditor() {
19
+ const envEditor = process.env.VISUAL || process.env.EDITOR;
20
+ const editor = envEditor || getPlatformDefaultEditor();
21
+ const name = editor.split("/").pop() || editor;
22
+ return { bin: editor, name };
23
+ }
24
+ function isTerminalEditor(editorName) {
25
+ return TERMINAL_EDITORS.test(editorName);
26
+ }
27
+ function createTempFile(content) {
28
+ const id = randomBytes(6).toString("hex");
29
+ const tempPath = join(tmpdir(), `minto-prompt-${id}.md`);
30
+ writeFileSync(tempPath, content, "utf-8");
31
+ return tempPath;
32
+ }
33
+ function openInExternalEditor(content) {
34
+ const { bin: editor, name: editorName } = resolveEditor();
35
+ const tempPath = createTempFile(content);
36
+ try {
37
+ if (isTerminalEditor(editorName)) {
38
+ return openInTerminalEditor(editor, tempPath, content);
39
+ } else {
40
+ return openInGuiEditor(editor, tempPath, content);
41
+ }
42
+ } finally {
43
+ try {
44
+ unlinkSync(tempPath);
45
+ } catch {
46
+ }
47
+ }
48
+ }
49
+ function openFileInTerminalEditor(editor, filePath) {
50
+ let ttyFd;
51
+ try {
52
+ ttyFd = openSync("/dev/tty", "r");
53
+ } catch {
54
+ ttyFd = void 0;
55
+ }
56
+ if (typeof process.stdin.setRawMode === "function") {
57
+ process.stdin.setRawMode(false);
58
+ }
59
+ process.stdin.pause();
60
+ try {
61
+ const result = spawnSync(editor, [filePath], {
62
+ stdio: [ttyFd ?? "inherit", "inherit", "inherit"],
63
+ shell: false
64
+ });
65
+ if (result.error) {
66
+ throw new Error(`Failed to open editor: ${result.error.message}`);
67
+ }
68
+ } finally {
69
+ if (ttyFd !== void 0) {
70
+ try {
71
+ closeSync(ttyFd);
72
+ } catch {
73
+ }
74
+ }
75
+ process.stdin.resume();
76
+ if (typeof process.stdin.setRawMode === "function") {
77
+ process.stdin.setRawMode(true);
78
+ }
79
+ process.stdout.emit("resize");
80
+ }
81
+ }
82
+ function openInTerminalEditor(editor, filePath, originalContent) {
83
+ let ttyFd;
84
+ try {
85
+ ttyFd = openSync("/dev/tty", "r");
86
+ } catch {
87
+ ttyFd = void 0;
88
+ }
89
+ if (typeof process.stdin.setRawMode === "function") {
90
+ process.stdin.setRawMode(false);
91
+ }
92
+ process.stdin.pause();
93
+ try {
94
+ const result = spawnSync(editor, [filePath], {
95
+ stdio: [ttyFd ?? "inherit", "inherit", "inherit"],
96
+ shell: false
97
+ });
98
+ if (result.error) {
99
+ return null;
100
+ }
101
+ if (result.status !== 0) {
102
+ return null;
103
+ }
104
+ const edited = readFileSync(filePath, "utf-8");
105
+ if (edited === originalContent) {
106
+ return null;
107
+ }
108
+ return edited;
109
+ } catch {
110
+ return null;
111
+ } finally {
112
+ if (ttyFd !== void 0) {
113
+ try {
114
+ closeSync(ttyFd);
115
+ } catch {
116
+ }
117
+ }
118
+ process.stdin.resume();
119
+ if (typeof process.stdin.setRawMode === "function") {
120
+ process.stdin.setRawMode(true);
121
+ }
122
+ process.stdout.emit("resize");
123
+ }
124
+ }
125
+ function openInGuiEditor(editor, filePath, originalContent) {
126
+ try {
127
+ const result = spawnSync(editor, ["--wait", filePath], {
128
+ stdio: "ignore",
129
+ shell: false
130
+ });
131
+ if (result.error || result.status !== 0) {
132
+ const fallbackResult = spawnSync(editor, [filePath], {
133
+ stdio: "ignore",
134
+ shell: false
135
+ });
136
+ if (fallbackResult.error) {
137
+ return null;
138
+ }
139
+ }
140
+ const edited = readFileSync(filePath, "utf-8");
141
+ if (edited === originalContent) {
142
+ return null;
143
+ }
144
+ return edited;
145
+ } catch {
146
+ return null;
147
+ }
148
+ }
149
+ export {
150
+ isTerminalEditor,
151
+ openFileInTerminalEditor,
152
+ openInExternalEditor,
153
+ resolveEditor
154
+ };
155
+ //# sourceMappingURL=externalEditor.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/utils/externalEditor.ts"],
4
+ "sourcesContent": ["/**\n * External Editor Integration\n *\n * Opens user's preferred editor for composing/editing prompt text.\n * Triggered by Ctrl+G in PromptInput (mirrors Claude Code behavior).\n *\n * Editor selection priority:\n * 1. $VISUAL (standard for GUI-capable editors)\n * 2. $EDITOR (standard fallback)\n * 3. Platform default \u2014 vi (macOS/Linux), notepad (Windows)\n *\n * For terminal editors (vim/nano/emacs), properly releases Ink's TTY\n * and restores it after the editor exits. Extracted from commands/memory.ts.\n */\n\nimport {\n writeFileSync,\n readFileSync,\n unlinkSync,\n openSync,\n closeSync,\n} from 'fs'\nimport { join } from 'path'\nimport { tmpdir } from 'os'\nimport { platform as osPlatform } from 'os'\nimport { spawnSync } from 'child_process'\nimport { randomBytes } from 'crypto'\n\n// Terminal-based editors that need TTY management\nconst TERMINAL_EDITORS =\n /^(vi|vim|nvim|nano|emacs|pico|ed|micro|helix|hx|kak)$/i\n\n/**\n * Get platform default editor.\n */\nfunction getPlatformDefaultEditor(): string {\n if (osPlatform() === 'win32') return 'notepad'\n return 'vi'\n}\n\n/**\n * Resolve which editor binary to use.\n * Priority: $VISUAL \u2192 $EDITOR \u2192 platform default\n */\nexport function resolveEditor(): { bin: string; name: string } {\n const envEditor = process.env.VISUAL || process.env.EDITOR\n const editor = envEditor || getPlatformDefaultEditor()\n const name = editor.split('/').pop() || editor\n return { bin: editor, name }\n}\n\n/**\n * Check if the resolved editor is a terminal editor (needs TTY management).\n */\nexport function isTerminalEditor(editorName: string): boolean {\n return TERMINAL_EDITORS.test(editorName)\n}\n\n/**\n * Create a unique temporary file for editing.\n * Uses .md extension so editors can provide syntax highlighting.\n */\nfunction createTempFile(content: string): string {\n const id = randomBytes(6).toString('hex')\n const tempPath = join(tmpdir(), `minto-prompt-${id}.md`)\n writeFileSync(tempPath, content, 'utf-8')\n return tempPath\n}\n\n/**\n * Open content in the user's external editor and return the edited result.\n *\n * Flow:\n * 1. Write current content to a temp file\n * 2. Release Ink's raw mode (for terminal editors)\n * 3. Spawn editor synchronously, blocking until exit\n * 4. Read back the edited content\n * 5. Restore Ink state\n * 6. Clean up temp file\n *\n * Returns the edited text, or null if:\n * - The editor exited with non-zero status\n * - The content is unchanged\n * - An error occurred\n */\nexport function openInExternalEditor(content: string): string | null {\n const { bin: editor, name: editorName } = resolveEditor()\n const tempPath = createTempFile(content)\n\n try {\n if (isTerminalEditor(editorName)) {\n return openInTerminalEditor(editor, tempPath, content)\n } else {\n return openInGuiEditor(editor, tempPath, content)\n }\n } finally {\n // Clean up temp file\n try {\n unlinkSync(tempPath)\n } catch {\n // Ignore cleanup errors\n }\n }\n}\n\n/**\n * Open an existing file in a terminal editor with proper TTY management.\n * Used by /memory command and other file-editing commands.\n * Does NOT read back content \u2014 caller is responsible for that.\n */\nexport function openFileInTerminalEditor(\n editor: string,\n filePath: string,\n): void {\n let ttyFd: number | undefined\n try {\n ttyFd = openSync('/dev/tty', 'r')\n } catch {\n ttyFd = undefined\n }\n\n if (typeof process.stdin.setRawMode === 'function') {\n process.stdin.setRawMode(false)\n }\n process.stdin.pause()\n\n try {\n const result = spawnSync(editor, [filePath], {\n stdio: [ttyFd ?? 'inherit', 'inherit', 'inherit'],\n shell: false,\n })\n if (result.error) {\n throw new Error(`Failed to open editor: ${result.error.message}`)\n }\n } finally {\n if (ttyFd !== undefined) {\n try {\n closeSync(ttyFd)\n } catch {\n // Ignore\n }\n }\n process.stdin.resume()\n if (typeof process.stdin.setRawMode === 'function') {\n process.stdin.setRawMode(true)\n }\n process.stdout.emit('resize')\n }\n}\n\n/**\n * Open in a terminal editor with proper TTY management.\n * Releases Ink's raw mode, blocks until editor exits, restores state.\n * Returns edited content or null if unchanged/error.\n */\nfunction openInTerminalEditor(\n editor: string,\n filePath: string,\n originalContent: string,\n): string | null {\n // Open /dev/tty for keyboard input (bypasses Ink's stdin)\n let ttyFd: number | undefined\n try {\n ttyFd = openSync('/dev/tty', 'r')\n } catch {\n ttyFd = undefined\n }\n\n // Release Ink's raw mode\n if (typeof process.stdin.setRawMode === 'function') {\n process.stdin.setRawMode(false)\n }\n process.stdin.pause()\n\n try {\n const result = spawnSync(editor, [filePath], {\n stdio: [ttyFd ?? 'inherit', 'inherit', 'inherit'],\n shell: false,\n })\n\n if (result.error) {\n return null\n }\n\n if (result.status !== 0) {\n return null\n }\n\n // Read back edited content\n const edited = readFileSync(filePath, 'utf-8')\n\n // Return null if content is unchanged\n if (edited === originalContent) {\n return null\n }\n\n return edited\n } catch {\n return null\n } finally {\n if (ttyFd !== undefined) {\n try {\n closeSync(ttyFd)\n } catch {\n // Ignore\n }\n }\n // Restore Ink state\n process.stdin.resume()\n if (typeof process.stdin.setRawMode === 'function') {\n process.stdin.setRawMode(true)\n }\n // Trigger Ink re-render by emitting resize\n process.stdout.emit('resize')\n }\n}\n\n/**\n * Open in a GUI editor. Blocks synchronously until the process exits.\n * GUI editors like VSCode with --wait flag will block appropriately.\n */\nfunction openInGuiEditor(\n editor: string,\n filePath: string,\n originalContent: string,\n): string | null {\n try {\n const result = spawnSync(editor, ['--wait', filePath], {\n stdio: 'ignore',\n shell: false,\n })\n\n if (result.error || result.status !== 0) {\n // Fallback: try without --wait (editor may not support it)\n const fallbackResult = spawnSync(editor, [filePath], {\n stdio: 'ignore',\n shell: false,\n })\n if (fallbackResult.error) {\n return null\n }\n }\n\n const edited = readFileSync(filePath, 'utf-8')\n\n if (edited === originalContent) {\n return null\n }\n\n return edited\n } catch {\n return null\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,67 @@
1
+ import {
2
+ existsSync,
3
+ readFileSync,
4
+ writeFileSync,
5
+ mkdirSync,
6
+ unlinkSync
7
+ } from "fs";
8
+ import { join } from "path";
9
+ function acquireFileLock(lockPath, timeoutMs = 5e3) {
10
+ const deadline = Date.now() + timeoutMs;
11
+ const pid = process.pid.toString();
12
+ const dir = join(lockPath, "..");
13
+ if (!existsSync(dir)) {
14
+ mkdirSync(dir, { recursive: true });
15
+ }
16
+ while (Date.now() < deadline) {
17
+ try {
18
+ writeFileSync(lockPath, pid, { flag: "wx" });
19
+ return true;
20
+ } catch (err) {
21
+ if (err?.code === "EEXIST") {
22
+ try {
23
+ const holdingPid = parseInt(readFileSync(lockPath, "utf-8"), 10);
24
+ if (holdingPid && holdingPid !== process.pid) {
25
+ try {
26
+ process.kill(holdingPid, 0);
27
+ } catch {
28
+ try {
29
+ unlinkSync(lockPath);
30
+ } catch {
31
+ }
32
+ continue;
33
+ }
34
+ }
35
+ } catch {
36
+ try {
37
+ unlinkSync(lockPath);
38
+ } catch {
39
+ }
40
+ continue;
41
+ }
42
+ try {
43
+ const waitMs = 10 + Math.floor(Math.random() * 40);
44
+ Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, waitMs);
45
+ } catch {
46
+ const waitUntil = Date.now() + 10 + Math.floor(Math.random() * 40);
47
+ while (Date.now() < waitUntil) {
48
+ }
49
+ }
50
+ } else {
51
+ return false;
52
+ }
53
+ }
54
+ }
55
+ return false;
56
+ }
57
+ function releaseFileLock(lockPath) {
58
+ try {
59
+ unlinkSync(lockPath);
60
+ } catch {
61
+ }
62
+ }
63
+ export {
64
+ acquireFileLock,
65
+ releaseFileLock
66
+ };
67
+ //# sourceMappingURL=fileLock.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/utils/fileLock.ts"],
4
+ "sourcesContent": ["/**\n * Simple file-based lock for cross-process synchronization.\n * Uses exclusive file creation (O_CREAT | O_EXCL) for atomicity.\n * Includes stale lock detection: if the lock file contains a PID\n * that is no longer running, the lock is considered stale and reclaimed.\n *\n * Extracted from teamTaskStore.ts for reuse across mailbox, task store, etc.\n */\n\nimport {\n existsSync,\n readFileSync,\n writeFileSync,\n mkdirSync,\n unlinkSync,\n} from 'fs'\nimport { join } from 'path'\n\nexport function acquireFileLock(\n lockPath: string,\n timeoutMs: number = 5000,\n): boolean {\n const deadline = Date.now() + timeoutMs\n const pid = process.pid.toString()\n\n // Ensure parent directory exists\n const dir = join(lockPath, '..')\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true })\n }\n\n while (Date.now() < deadline) {\n try {\n writeFileSync(lockPath, pid, { flag: 'wx' })\n return true\n } catch (err: any) {\n if (err?.code === 'EEXIST') {\n // Lock file exists -- check if stale\n try {\n const holdingPid = parseInt(readFileSync(lockPath, 'utf-8'), 10)\n if (holdingPid && holdingPid !== process.pid) {\n try {\n process.kill(holdingPid, 0) // Check if process exists\n } catch {\n // Process doesn't exist -- stale lock, reclaim\n try {\n unlinkSync(lockPath)\n } catch {\n /* race -- another process may have reclaimed */\n }\n continue // Retry immediately\n }\n }\n } catch {\n // Can't read lock file -- try to remove and retry\n try {\n unlinkSync(lockPath)\n } catch {\n /* ignore */\n }\n continue\n }\n // Lock is held by a live process -- yield with Atomics.wait\n try {\n const waitMs = 10 + Math.floor(Math.random() * 40)\n Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, waitMs)\n } catch {\n // Atomics.wait may not be available in all environments\n const waitUntil = Date.now() + 10 + Math.floor(Math.random() * 40)\n while (Date.now() < waitUntil) {\n /* brief yield fallback */\n }\n }\n } else {\n // Non-EEXIST error (e.g., ENOENT for parent dir) -- bail\n return false\n }\n }\n }\n return false\n}\n\nexport function releaseFileLock(lockPath: string): void {\n try {\n unlinkSync(lockPath)\n } catch {\n // Lock already released or doesn't exist\n }\n}\n"],
5
+ "mappings": "AASA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,YAAY;AAEd,SAAS,gBACd,UACA,YAAoB,KACX;AACT,QAAM,WAAW,KAAK,IAAI,IAAI;AAC9B,QAAM,MAAM,QAAQ,IAAI,SAAS;AAGjC,QAAM,MAAM,KAAK,UAAU,IAAI;AAC/B,MAAI,CAAC,WAAW,GAAG,GAAG;AACpB,cAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AAAA,EACpC;AAEA,SAAO,KAAK,IAAI,IAAI,UAAU;AAC5B,QAAI;AACF,oBAAc,UAAU,KAAK,EAAE,MAAM,KAAK,CAAC;AAC3C,aAAO;AAAA,IACT,SAAS,KAAU;AACjB,UAAI,KAAK,SAAS,UAAU;AAE1B,YAAI;AACF,gBAAM,aAAa,SAAS,aAAa,UAAU,OAAO,GAAG,EAAE;AAC/D,cAAI,cAAc,eAAe,QAAQ,KAAK;AAC5C,gBAAI;AACF,sBAAQ,KAAK,YAAY,CAAC;AAAA,YAC5B,QAAQ;AAEN,kBAAI;AACF,2BAAW,QAAQ;AAAA,cACrB,QAAQ;AAAA,cAER;AACA;AAAA,YACF;AAAA,UACF;AAAA,QACF,QAAQ;AAEN,cAAI;AACF,uBAAW,QAAQ;AAAA,UACrB,QAAQ;AAAA,UAER;AACA;AAAA,QACF;AAEA,YAAI;AACF,gBAAM,SAAS,KAAK,KAAK,MAAM,KAAK,OAAO,IAAI,EAAE;AACjD,kBAAQ,KAAK,IAAI,WAAW,IAAI,kBAAkB,CAAC,CAAC,GAAG,GAAG,GAAG,MAAM;AAAA,QACrE,QAAQ;AAEN,gBAAM,YAAY,KAAK,IAAI,IAAI,KAAK,KAAK,MAAM,KAAK,OAAO,IAAI,EAAE;AACjE,iBAAO,KAAK,IAAI,IAAI,WAAW;AAAA,UAE/B;AAAA,QACF;AAAA,MACF,OAAO;AAEL,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEO,SAAS,gBAAgB,UAAwB;AACtD,MAAI;AACF,eAAW,QAAQ;AAAA,EACrB,QAAQ;AAAA,EAER;AACF;",
6
+ "names": []
7
+ }
@@ -1,12 +1,24 @@
1
1
  function wrapText(text, width) {
2
2
  const lines = [];
3
3
  let currentLine = "";
4
- for (const char of text) {
5
- if ([...currentLine].length < width) {
6
- currentLine += char;
4
+ const words = text.split(/(\s+)/);
5
+ for (const word of words) {
6
+ const currentLen = [...currentLine].length;
7
+ const wordLen = [...word].length;
8
+ if (currentLen + wordLen <= width) {
9
+ currentLine += word;
10
+ } else if (currentLen === 0) {
11
+ for (const char of word) {
12
+ if ([...currentLine].length < width) {
13
+ currentLine += char;
14
+ } else {
15
+ lines.push(currentLine);
16
+ currentLine = char;
17
+ }
18
+ }
7
19
  } else {
8
20
  lines.push(currentLine);
9
- currentLine = char;
21
+ currentLine = /^\s+$/.test(word) ? "" : word;
10
22
  }
11
23
  }
12
24
  if (currentLine) lines.push(currentLine);
@@ -41,7 +53,7 @@ function formatTokens(tokens) {
41
53
  return `${formatNumber(tokens)} tokens`;
42
54
  }
43
55
  function formatContextUsage(usedTokens, maxTokens) {
44
- const percentage = usedTokens / maxTokens * 100;
56
+ const percentage = maxTokens > 0 ? usedTokens / maxTokens * 100 : 0;
45
57
  const formatted = formatNumber(usedTokens);
46
58
  if (percentage <= 50) {
47
59
  return `${formatted}/${formatNumber(maxTokens)} (${percentage.toFixed(0)}%)`;
@@ -85,17 +97,15 @@ function truncateText(text, maxLength = 80) {
85
97
  if (trimmed.length <= maxLength) return trimmed;
86
98
  return trimmed.slice(0, maxLength - 3) + "...";
87
99
  }
88
- function formatTokenUsage(inputTokens, outputTokens) {
89
- const parts = [];
90
- if (inputTokens != null && inputTokens > 0) {
91
- parts.push(`\u2191 ${formatNumber(inputTokens)}`);
92
- }
93
- if (outputTokens != null && outputTokens > 0) {
94
- parts.push(`\u2193 ${formatNumber(outputTokens)}`);
95
- }
96
- return parts.join(" \xB7 ");
100
+ function formatBidirectionalTokens(_inputTokens, outputTokens) {
101
+ if (outputTokens <= 0) return "";
102
+ return `\u2193 ${formatNumber(outputTokens)} tokens`;
103
+ }
104
+ function formatTokenUsage(_inputTokens, outputTokens) {
105
+ return formatBidirectionalTokens(0, outputTokens ?? 0);
97
106
  }
98
107
  export {
108
+ formatBidirectionalTokens,
99
109
  formatContextUsage,
100
110
  formatDuration,
101
111
  formatNumber,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/utils/format.tsx"],
4
- "sourcesContent": ["export function wrapText(text: string, width: number): string[] {\n const lines: string[] = []\n let currentLine = ''\n\n for (const char of text) {\n // Important: we need the spread to properly count multi-plane UTF-8 characters (eg. \uD805\uDE96)\n if ([...currentLine].length < width) {\n currentLine += char\n } else {\n lines.push(currentLine)\n currentLine = char\n }\n }\n\n if (currentLine) lines.push(currentLine)\n return lines\n}\n\nexport function formatDuration(ms: number): string {\n const totalSeconds = Math.floor(ms / 1000)\n\n if (totalSeconds < 60) {\n return `${totalSeconds}s`\n }\n\n const hours = Math.floor(totalSeconds / 3600)\n const minutes = Math.floor((totalSeconds % 3600) / 60)\n const seconds = totalSeconds % 60\n\n if (hours > 0) {\n return `${hours}h ${minutes}m ${seconds}s`\n }\n if (minutes > 0) {\n return `${minutes}m ${seconds}s`\n }\n return `${seconds}s`\n}\n\nexport function formatNumber(number: number): string {\n return new Intl.NumberFormat('en', {\n notation: 'compact',\n maximumFractionDigits: 1,\n })\n .format(number) // eg. \"1321\" => \"1.3K\"\n .toLowerCase() // eg. \"1.3K\" => \"1.3k\"\n}\n\n/**\n * Format token count for display (e.g., 42000 -> \"42k tokens\")\n * More descriptive than formatNumber for token-specific contexts\n */\nexport function formatTokens(tokens: number): string {\n if (tokens < 1000) {\n return `${tokens} tokens`\n }\n return `${formatNumber(tokens)} tokens`\n}\n\n/**\n * Format context usage as percentage with visual indicator\n */\nexport function formatContextUsage(\n usedTokens: number,\n maxTokens: number,\n): string {\n const percentage = (usedTokens / maxTokens) * 100\n const formatted = formatNumber(usedTokens)\n\n if (percentage <= 50) {\n return `${formatted}/${formatNumber(maxTokens)} (${percentage.toFixed(0)}%)`\n } else if (percentage <= 80) {\n return `${formatted}/${formatNumber(maxTokens)} (${percentage.toFixed(0)}% \u26A0\uFE0F)`\n } else {\n return `${formatted}/${formatNumber(maxTokens)} (${percentage.toFixed(0)}% \uD83D\uDD34)`\n }\n}\n\n/**\n * Format timestamp for display (e.g., \"12:20 AM\")\n * Uses 12-hour format with AM/PM indicator like Claude Code\n */\nexport function formatTimestamp(timestamp: number | Date): string {\n const date = typeof timestamp === 'number' ? new Date(timestamp) : timestamp\n return date.toLocaleTimeString('en-US', {\n hour: 'numeric',\n minute: '2-digit',\n hour12: true,\n })\n}\n\n/**\n * Format URL for display\n * - Decodes URL-encoded characters for readability\n * - Truncates to max length with ellipsis\n * - Shows host + path truncated\n */\nexport function formatUrl(url: string, maxLength: number = 60): string {\n try {\n // Decode URL-encoded characters\n const decoded = decodeURIComponent(url)\n\n // Truncate if too long\n if (decoded.length <= maxLength) {\n return decoded\n }\n\n // Try to preserve host and beginning of path\n const urlObj = new URL(decoded)\n const host = urlObj.host\n const pathStart = urlObj.pathname.slice(0, 20)\n\n // Format: host/path.../end\n const remaining = maxLength - host.length - pathStart.length - 6 // \"...\" x2\n if (remaining > 10) {\n const pathEnd = urlObj.pathname.slice(-remaining)\n return `${host}${pathStart}...${pathEnd}`\n }\n\n // Fallback: simple truncation\n return decoded.slice(0, maxLength - 3) + '...'\n } catch {\n // If URL parsing fails, just truncate\n if (url.length <= maxLength) return url\n return url.slice(0, maxLength - 3) + '...'\n }\n}\n\n/**\n * Truncate text to a maximum length with ellipsis\n */\nexport function truncateText(text: string, maxLength: number = 80): string {\n if (!text) return ''\n const trimmed = text.trim().replace(/\\n+/g, ' ').replace(/\\s+/g, ' ')\n if (trimmed.length <= maxLength) return trimmed\n return trimmed.slice(0, maxLength - 3) + '...'\n}\n\n/**\n * Format token usage with up/down arrows for input/output\n * e.g., \"\u2191 8.2k \u00B7 \u2193 1.2k\"\n */\nexport function formatTokenUsage(\n inputTokens?: number,\n outputTokens?: number,\n): string {\n const parts: string[] = []\n if (inputTokens != null && inputTokens > 0) {\n parts.push(`\u2191 ${formatNumber(inputTokens)}`)\n }\n if (outputTokens != null && outputTokens > 0) {\n parts.push(`\u2193 ${formatNumber(outputTokens)}`)\n }\n return parts.join(' \u00B7 ')\n}\n"],
5
- "mappings": "AAAO,SAAS,SAAS,MAAc,OAAyB;AAC9D,QAAM,QAAkB,CAAC;AACzB,MAAI,cAAc;AAElB,aAAW,QAAQ,MAAM;AAEvB,QAAI,CAAC,GAAG,WAAW,EAAE,SAAS,OAAO;AACnC,qBAAe;AAAA,IACjB,OAAO;AACL,YAAM,KAAK,WAAW;AACtB,oBAAc;AAAA,IAChB;AAAA,EACF;AAEA,MAAI,YAAa,OAAM,KAAK,WAAW;AACvC,SAAO;AACT;AAEO,SAAS,eAAe,IAAoB;AACjD,QAAM,eAAe,KAAK,MAAM,KAAK,GAAI;AAEzC,MAAI,eAAe,IAAI;AACrB,WAAO,GAAG,YAAY;AAAA,EACxB;AAEA,QAAM,QAAQ,KAAK,MAAM,eAAe,IAAI;AAC5C,QAAM,UAAU,KAAK,MAAO,eAAe,OAAQ,EAAE;AACrD,QAAM,UAAU,eAAe;AAE/B,MAAI,QAAQ,GAAG;AACb,WAAO,GAAG,KAAK,KAAK,OAAO,KAAK,OAAO;AAAA,EACzC;AACA,MAAI,UAAU,GAAG;AACf,WAAO,GAAG,OAAO,KAAK,OAAO;AAAA,EAC/B;AACA,SAAO,GAAG,OAAO;AACnB;AAEO,SAAS,aAAa,QAAwB;AACnD,SAAO,IAAI,KAAK,aAAa,MAAM;AAAA,IACjC,UAAU;AAAA,IACV,uBAAuB;AAAA,EACzB,CAAC,EACE,OAAO,MAAM,EACb,YAAY;AACjB;AAMO,SAAS,aAAa,QAAwB;AACnD,MAAI,SAAS,KAAM;AACjB,WAAO,GAAG,MAAM;AAAA,EAClB;AACA,SAAO,GAAG,aAAa,MAAM,CAAC;AAChC;AAKO,SAAS,mBACd,YACA,WACQ;AACR,QAAM,aAAc,aAAa,YAAa;AAC9C,QAAM,YAAY,aAAa,UAAU;AAEzC,MAAI,cAAc,IAAI;AACpB,WAAO,GAAG,SAAS,IAAI,aAAa,SAAS,CAAC,KAAK,WAAW,QAAQ,CAAC,CAAC;AAAA,EAC1E,WAAW,cAAc,IAAI;AAC3B,WAAO,GAAG,SAAS,IAAI,aAAa,SAAS,CAAC,KAAK,WAAW,QAAQ,CAAC,CAAC;AAAA,EAC1E,OAAO;AACL,WAAO,GAAG,SAAS,IAAI,aAAa,SAAS,CAAC,KAAK,WAAW,QAAQ,CAAC,CAAC;AAAA,EAC1E;AACF;AAMO,SAAS,gBAAgB,WAAkC;AAChE,QAAM,OAAO,OAAO,cAAc,WAAW,IAAI,KAAK,SAAS,IAAI;AACnE,SAAO,KAAK,mBAAmB,SAAS;AAAA,IACtC,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,QAAQ;AAAA,EACV,CAAC;AACH;AAQO,SAAS,UAAU,KAAa,YAAoB,IAAY;AACrE,MAAI;AAEF,UAAM,UAAU,mBAAmB,GAAG;AAGtC,QAAI,QAAQ,UAAU,WAAW;AAC/B,aAAO;AAAA,IACT;AAGA,UAAM,SAAS,IAAI,IAAI,OAAO;AAC9B,UAAM,OAAO,OAAO;AACpB,UAAM,YAAY,OAAO,SAAS,MAAM,GAAG,EAAE;AAG7C,UAAM,YAAY,YAAY,KAAK,SAAS,UAAU,SAAS;AAC/D,QAAI,YAAY,IAAI;AAClB,YAAM,UAAU,OAAO,SAAS,MAAM,CAAC,SAAS;AAChD,aAAO,GAAG,IAAI,GAAG,SAAS,MAAM,OAAO;AAAA,IACzC;AAGA,WAAO,QAAQ,MAAM,GAAG,YAAY,CAAC,IAAI;AAAA,EAC3C,QAAQ;AAEN,QAAI,IAAI,UAAU,UAAW,QAAO;AACpC,WAAO,IAAI,MAAM,GAAG,YAAY,CAAC,IAAI;AAAA,EACvC;AACF;AAKO,SAAS,aAAa,MAAc,YAAoB,IAAY;AACzE,MAAI,CAAC,KAAM,QAAO;AAClB,QAAM,UAAU,KAAK,KAAK,EAAE,QAAQ,QAAQ,GAAG,EAAE,QAAQ,QAAQ,GAAG;AACpE,MAAI,QAAQ,UAAU,UAAW,QAAO;AACxC,SAAO,QAAQ,MAAM,GAAG,YAAY,CAAC,IAAI;AAC3C;AAMO,SAAS,iBACd,aACA,cACQ;AACR,QAAM,QAAkB,CAAC;AACzB,MAAI,eAAe,QAAQ,cAAc,GAAG;AAC1C,UAAM,KAAK,UAAK,aAAa,WAAW,CAAC,EAAE;AAAA,EAC7C;AACA,MAAI,gBAAgB,QAAQ,eAAe,GAAG;AAC5C,UAAM,KAAK,UAAK,aAAa,YAAY,CAAC,EAAE;AAAA,EAC9C;AACA,SAAO,MAAM,KAAK,QAAK;AACzB;",
4
+ "sourcesContent": ["export function wrapText(text: string, width: number): string[] {\n const lines: string[] = []\n let currentLine = ''\n\n const words = text.split(/(\\s+)/)\n for (const word of words) {\n const currentLen = [...currentLine].length\n const wordLen = [...word].length\n\n if (currentLen + wordLen <= width) {\n currentLine += word\n } else if (currentLen === 0) {\n // Word is longer than width \u2014 break by character\n for (const char of word) {\n if ([...currentLine].length < width) {\n currentLine += char\n } else {\n lines.push(currentLine)\n currentLine = char\n }\n }\n } else {\n lines.push(currentLine)\n // Don't start a new line with whitespace\n currentLine = /^\\s+$/.test(word) ? '' : word\n }\n }\n\n if (currentLine) lines.push(currentLine)\n return lines\n}\n\nexport function formatDuration(ms: number): string {\n const totalSeconds = Math.floor(ms / 1000)\n\n if (totalSeconds < 60) {\n return `${totalSeconds}s`\n }\n\n const hours = Math.floor(totalSeconds / 3600)\n const minutes = Math.floor((totalSeconds % 3600) / 60)\n const seconds = totalSeconds % 60\n\n if (hours > 0) {\n return `${hours}h ${minutes}m ${seconds}s`\n }\n if (minutes > 0) {\n return `${minutes}m ${seconds}s`\n }\n return `${seconds}s`\n}\n\nexport function formatNumber(number: number): string {\n return new Intl.NumberFormat('en', {\n notation: 'compact',\n maximumFractionDigits: 1,\n })\n .format(number) // eg. \"1321\" => \"1.3K\"\n .toLowerCase() // eg. \"1.3K\" => \"1.3k\"\n}\n\n/**\n * Format token count for display (e.g., 42000 -> \"42k tokens\")\n * More descriptive than formatNumber for token-specific contexts\n */\nexport function formatTokens(tokens: number): string {\n if (tokens < 1000) {\n return `${tokens} tokens`\n }\n return `${formatNumber(tokens)} tokens`\n}\n\n/**\n * Format context usage as percentage with visual indicator\n */\nexport function formatContextUsage(\n usedTokens: number,\n maxTokens: number,\n): string {\n const percentage = maxTokens > 0 ? (usedTokens / maxTokens) * 100 : 0\n const formatted = formatNumber(usedTokens)\n\n if (percentage <= 50) {\n return `${formatted}/${formatNumber(maxTokens)} (${percentage.toFixed(0)}%)`\n } else if (percentage <= 80) {\n return `${formatted}/${formatNumber(maxTokens)} (${percentage.toFixed(0)}% \u26A0\uFE0F)`\n } else {\n return `${formatted}/${formatNumber(maxTokens)} (${percentage.toFixed(0)}% \uD83D\uDD34)`\n }\n}\n\n/**\n * Format timestamp for display (e.g., \"12:20 AM\")\n * Uses 12-hour format with AM/PM indicator like Claude Code\n */\nexport function formatTimestamp(timestamp: number | Date): string {\n const date = typeof timestamp === 'number' ? new Date(timestamp) : timestamp\n return date.toLocaleTimeString('en-US', {\n hour: 'numeric',\n minute: '2-digit',\n hour12: true,\n })\n}\n\n/**\n * Format URL for display\n * - Decodes URL-encoded characters for readability\n * - Truncates to max length with ellipsis\n * - Shows host + path truncated\n */\nexport function formatUrl(url: string, maxLength: number = 60): string {\n try {\n // Decode URL-encoded characters\n const decoded = decodeURIComponent(url)\n\n // Truncate if too long\n if (decoded.length <= maxLength) {\n return decoded\n }\n\n // Try to preserve host and beginning of path\n const urlObj = new URL(decoded)\n const host = urlObj.host\n const pathStart = urlObj.pathname.slice(0, 20)\n\n // Format: host/path.../end\n const remaining = maxLength - host.length - pathStart.length - 6 // \"...\" x2\n if (remaining > 10) {\n const pathEnd = urlObj.pathname.slice(-remaining)\n return `${host}${pathStart}...${pathEnd}`\n }\n\n // Fallback: simple truncation\n return decoded.slice(0, maxLength - 3) + '...'\n } catch {\n // If URL parsing fails, just truncate\n if (url.length <= maxLength) return url\n return url.slice(0, maxLength - 3) + '...'\n }\n}\n\n/**\n * Truncate text to a maximum length with ellipsis\n */\nexport function truncateText(text: string, maxLength: number = 80): string {\n if (!text) return ''\n const trimmed = text.trim().replace(/\\n+/g, ' ').replace(/\\s+/g, ' ')\n if (trimmed.length <= maxLength) return trimmed\n return trimmed.slice(0, maxLength - 3) + '...'\n}\n\n/**\n * Format token display aligned with Claude Code: \u2193 X tokens (output only)\n * e.g., \"\u2193 3.5k tokens\"\n */\nexport function formatBidirectionalTokens(\n _inputTokens: number,\n outputTokens: number,\n): string {\n if (outputTokens <= 0) return ''\n return `\u2193 ${formatNumber(outputTokens)} tokens`\n}\n\n/**\n * Format token usage aligned with Claude Code: \u2193 X tokens (output only)\n */\nexport function formatTokenUsage(\n _inputTokens?: number,\n outputTokens?: number,\n): string {\n return formatBidirectionalTokens(0, outputTokens ?? 0)\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,79 +1,5 @@
1
- import { captureException } from "../services/sentry.js";
2
- import { logError } from "./log.js";
1
+ import { gracefulExit } from "./exit.js";
3
2
  let isInitialized = false;
4
- let isShuttingDown = false;
5
- var ErrorSeverity = /* @__PURE__ */ ((ErrorSeverity2) => {
6
- ErrorSeverity2["LOW"] = "low";
7
- ErrorSeverity2["MEDIUM"] = "medium";
8
- ErrorSeverity2["HIGH"] = "high";
9
- ErrorSeverity2["CRITICAL"] = "critical";
10
- return ErrorSeverity2;
11
- })(ErrorSeverity || {});
12
- function categorizeError(error) {
13
- if (error instanceof Error) {
14
- const message = error.message.toLowerCase();
15
- if (message.includes("out of memory") || message.includes("heap") || message.includes("stack overflow") || error.name === "RangeError") {
16
- return "critical" /* CRITICAL */;
17
- }
18
- if (message.includes("api") || message.includes("network") || message.includes("econnrefused") || message.includes("timeout")) {
19
- return "high" /* HIGH */;
20
- }
21
- if (error.name === "TypeError" || error.name === "ReferenceError" || message.includes("undefined") || message.includes("null")) {
22
- return "medium" /* MEDIUM */;
23
- }
24
- }
25
- return "low" /* LOW */;
26
- }
27
- function formatError(error) {
28
- if (error instanceof Error) {
29
- return `${error.name}: ${error.message}
30
- ${error.stack || ""}`;
31
- }
32
- return String(error);
33
- }
34
- function handleUnhandledRejection(reason, promise) {
35
- if (isShuttingDown) return;
36
- const severity = categorizeError(reason);
37
- const formattedError = formatError(reason);
38
- console.error(`
39
- [${severity.toUpperCase()}] Unhandled Promise Rejection:`);
40
- console.error(formattedError);
41
- try {
42
- logError(reason instanceof Error ? reason : new Error(String(reason)));
43
- } catch {
44
- }
45
- try {
46
- captureException(
47
- reason instanceof Error ? reason : new Error(String(reason))
48
- );
49
- } catch {
50
- }
51
- if (severity === "critical" /* CRITICAL */) {
52
- console.error("\n\u26A0\uFE0F Critical error detected. Consider restarting.");
53
- }
54
- }
55
- function handleUncaughtException(error, origin) {
56
- if (isShuttingDown) return;
57
- const severity = categorizeError(error);
58
- const formattedError = formatError(error);
59
- console.error(`
60
- [${severity.toUpperCase()}] Uncaught Exception (${origin}):`);
61
- console.error(formattedError);
62
- try {
63
- logError(error);
64
- } catch {
65
- }
66
- try {
67
- captureException(error);
68
- } catch {
69
- }
70
- if (severity === "critical" /* CRITICAL */) {
71
- console.error(
72
- "\n\u{1F4A5} Critical uncaught exception. Shutting down gracefully..."
73
- );
74
- gracefulShutdown(1);
75
- }
76
- }
77
3
  function handleWarning(warning) {
78
4
  if (process.env.VERBOSE === "true" || warning.name === "DeprecationWarning" || warning.name === "ExperimentalWarning") {
79
5
  console.warn(`
@@ -90,10 +16,7 @@ function unregisterCleanupHandler(handler) {
90
16
  cleanupHandlers.splice(index, 1);
91
17
  }
92
18
  }
93
- async function gracefulShutdown(exitCode = 0) {
94
- if (isShuttingDown) return;
95
- isShuttingDown = true;
96
- console.error("\n\u{1F504} Running cleanup handlers...");
19
+ async function runCleanupHandlers() {
97
20
  for (const handler of cleanupHandlers) {
98
21
  try {
99
22
  await handler();
@@ -101,24 +24,14 @@ async function gracefulShutdown(exitCode = 0) {
101
24
  console.error("Cleanup handler error:", error);
102
25
  }
103
26
  }
104
- console.error("\u2705 Cleanup complete.");
105
- process.exit(exitCode);
106
27
  }
107
28
  function initGlobalErrorHandlers() {
108
29
  if (isInitialized) return;
109
30
  isInitialized = true;
110
- process.on("unhandledRejection", handleUnhandledRejection);
111
- process.on("uncaughtException", handleUncaughtException);
112
31
  process.on("warning", handleWarning);
113
- process.on("SIGTERM", () => {
114
- console.error("\nReceived SIGTERM signal.");
115
- gracefulShutdown(0);
116
- });
117
- process.on("SIGINT", () => {
118
- });
119
32
  process.on("beforeExit", (code) => {
120
- if (!isShuttingDown && cleanupHandlers.length > 0) {
121
- gracefulShutdown(code);
33
+ if (cleanupHandlers.length > 0) {
34
+ gracefulExit(code);
122
35
  }
123
36
  });
124
37
  }
@@ -129,21 +42,17 @@ function resetGlobalErrorHandlers() {
129
42
  if (process.env.NODE_ENV !== "test") {
130
43
  throw new Error("resetGlobalErrorHandlers can only be called in tests");
131
44
  }
132
- process.removeAllListeners("unhandledRejection");
133
- process.removeAllListeners("uncaughtException");
134
45
  process.removeAllListeners("warning");
135
- process.removeAllListeners("SIGTERM");
136
46
  process.removeAllListeners("beforeExit");
137
47
  isInitialized = false;
138
- isShuttingDown = false;
139
48
  cleanupHandlers.length = 0;
140
49
  }
141
50
  export {
142
- ErrorSeverity,
143
51
  initGlobalErrorHandlers,
144
52
  isGlobalErrorHandlersInitialized,
145
53
  registerCleanupHandler,
146
54
  resetGlobalErrorHandlers,
55
+ runCleanupHandlers,
147
56
  unregisterCleanupHandler
148
57
  };
149
58
  //# sourceMappingURL=globalErrorHandler.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/utils/globalErrorHandler.ts"],
4
- "sourcesContent": ["/**\n * Global Error Handler\n *\n * Handles unhandled promise rejections and uncaught exceptions\n * to prevent silent crashes and ensure proper cleanup.\n */\n\nimport { captureException } from '@services/sentry'\nimport { logError } from './log'\n\nlet isInitialized = false\nlet isShuttingDown = false\n\n/**\n * Error severity levels\n */\nexport enum ErrorSeverity {\n LOW = 'low',\n MEDIUM = 'medium',\n HIGH = 'high',\n CRITICAL = 'critical',\n}\n\n/**\n * Categorize error severity based on error type\n */\nfunction categorizeError(error: unknown): ErrorSeverity {\n if (error instanceof Error) {\n const message = error.message.toLowerCase()\n\n // Critical: System-level failures\n if (\n message.includes('out of memory') ||\n message.includes('heap') ||\n message.includes('stack overflow') ||\n error.name === 'RangeError'\n ) {\n return ErrorSeverity.CRITICAL\n }\n\n // High: API and network failures\n if (\n message.includes('api') ||\n message.includes('network') ||\n message.includes('econnrefused') ||\n message.includes('timeout')\n ) {\n return ErrorSeverity.HIGH\n }\n\n // Medium: Logic errors\n if (\n error.name === 'TypeError' ||\n error.name === 'ReferenceError' ||\n message.includes('undefined') ||\n message.includes('null')\n ) {\n return ErrorSeverity.MEDIUM\n }\n }\n\n return ErrorSeverity.LOW\n}\n\n/**\n * Format error for logging\n */\nfunction formatError(error: unknown): string {\n if (error instanceof Error) {\n return `${error.name}: ${error.message}\\n${error.stack || ''}`\n }\n return String(error)\n}\n\n/**\n * Handle unhandled promise rejection\n */\nfunction handleUnhandledRejection(\n reason: unknown,\n promise: Promise<unknown>,\n): void {\n if (isShuttingDown) return\n\n const severity = categorizeError(reason)\n const formattedError = formatError(reason)\n\n // Log to console with severity indicator\n console.error(`\\n[${severity.toUpperCase()}] Unhandled Promise Rejection:`)\n console.error(formattedError)\n\n // Log to file\n try {\n logError(reason instanceof Error ? reason : new Error(String(reason)))\n } catch {\n // Ignore logging errors during error handling\n }\n\n // Report to Sentry\n try {\n captureException(\n reason instanceof Error ? reason : new Error(String(reason)),\n )\n } catch {\n // Ignore Sentry errors\n }\n\n // For critical errors, consider graceful shutdown\n if (severity === ErrorSeverity.CRITICAL) {\n console.error('\\n\u26A0\uFE0F Critical error detected. Consider restarting.')\n }\n}\n\n/**\n * Handle uncaught exception\n */\nfunction handleUncaughtException(error: Error, origin: string): void {\n if (isShuttingDown) return\n\n const severity = categorizeError(error)\n const formattedError = formatError(error)\n\n // Log to console\n console.error(`\\n[${severity.toUpperCase()}] Uncaught Exception (${origin}):`)\n console.error(formattedError)\n\n // Log to file\n try {\n logError(error)\n } catch {\n // Ignore logging errors during error handling\n }\n\n // Report to Sentry\n try {\n captureException(error)\n } catch {\n // Ignore Sentry errors\n }\n\n // For uncaught exceptions, we should exit gracefully\n if (severity === ErrorSeverity.CRITICAL) {\n console.error(\n '\\n\uD83D\uDCA5 Critical uncaught exception. Shutting down gracefully...',\n )\n gracefulShutdown(1)\n }\n}\n\n/**\n * Handle process warnings\n */\nfunction handleWarning(warning: Error): void {\n // Only log in verbose mode or for specific warning types\n if (\n process.env.VERBOSE === 'true' ||\n warning.name === 'DeprecationWarning' ||\n warning.name === 'ExperimentalWarning'\n ) {\n console.warn(`\\n\u26A0\uFE0F Warning [${warning.name}]: ${warning.message}`)\n }\n}\n\n/**\n * Cleanup handlers for graceful shutdown\n */\nconst cleanupHandlers: Array<() => void | Promise<void>> = []\n\n/**\n * Register a cleanup handler to be called during shutdown\n */\nexport function registerCleanupHandler(\n handler: () => void | Promise<void>,\n): void {\n cleanupHandlers.push(handler)\n}\n\n/**\n * Unregister a cleanup handler\n */\nexport function unregisterCleanupHandler(\n handler: () => void | Promise<void>,\n): void {\n const index = cleanupHandlers.indexOf(handler)\n if (index > -1) {\n cleanupHandlers.splice(index, 1)\n }\n}\n\n/**\n * Perform graceful shutdown\n */\nasync function gracefulShutdown(exitCode: number = 0): Promise<void> {\n if (isShuttingDown) return\n isShuttingDown = true\n\n console.error('\\n\uD83D\uDD04 Running cleanup handlers...')\n\n // Run all cleanup handlers\n for (const handler of cleanupHandlers) {\n try {\n await handler()\n } catch (error) {\n console.error('Cleanup handler error:', error)\n }\n }\n\n // Note: Sentry flush is handled by the sentry service if needed\n\n console.error('\u2705 Cleanup complete.')\n process.exit(exitCode)\n}\n\n/**\n * Initialize global error handlers\n * Should be called early in the application lifecycle\n */\nexport function initGlobalErrorHandlers(): void {\n if (isInitialized) return\n isInitialized = true\n\n // Handle unhandled promise rejections\n process.on('unhandledRejection', handleUnhandledRejection)\n\n // Handle uncaught exceptions\n process.on('uncaughtException', handleUncaughtException)\n\n // Handle warnings\n process.on('warning', handleWarning)\n\n // Handle graceful shutdown signals\n process.on('SIGTERM', () => {\n console.error('\\nReceived SIGTERM signal.')\n gracefulShutdown(0)\n })\n\n process.on('SIGINT', () => {\n // Let the application handle SIGINT (Ctrl-C) normally\n // Only intervene if pressed multiple times\n })\n\n // Handle beforeExit for cleanup\n process.on('beforeExit', code => {\n if (!isShuttingDown && cleanupHandlers.length > 0) {\n gracefulShutdown(code)\n }\n })\n}\n\n/**\n * Check if global error handlers are initialized\n */\nexport function isGlobalErrorHandlersInitialized(): boolean {\n return isInitialized\n}\n\n/**\n * Reset global error handlers (for testing)\n */\nexport function resetGlobalErrorHandlers(): void {\n if (process.env.NODE_ENV !== 'test') {\n throw new Error('resetGlobalErrorHandlers can only be called in tests')\n }\n\n process.removeAllListeners('unhandledRejection')\n process.removeAllListeners('uncaughtException')\n process.removeAllListeners('warning')\n process.removeAllListeners('SIGTERM')\n process.removeAllListeners('beforeExit')\n\n isInitialized = false\n isShuttingDown = false\n cleanupHandlers.length = 0\n}\n"],
5
- "mappings": "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",
6
- "names": ["ErrorSeverity"]
4
+ "sourcesContent": ["/**\n * Global Error Handler\n *\n * Handles process warnings, cleanup handler orchestration, and\n * delegates shutdown to exit.ts's gracefulExit() to avoid dual\n * shutdown paths.\n *\n * NOTE: Signal handlers (SIGINT, SIGTERM, SIGBREAK) and process lifecycle\n * handlers (exit, unhandledRejection, uncaughtException) are managed by\n * setupExitHandlers() in exit.ts to avoid duplicate registrations.\n */\n\nimport { gracefulExit } from './exit'\n\nlet isInitialized = false\n\n/**\n * Handle process warnings\n */\nfunction handleWarning(warning: Error): void {\n // Only log in verbose mode or for specific warning types\n if (\n process.env.VERBOSE === 'true' ||\n warning.name === 'DeprecationWarning' ||\n warning.name === 'ExperimentalWarning'\n ) {\n console.warn(`\\n\u26A0\uFE0F Warning [${warning.name}]: ${warning.message}`)\n }\n}\n\n/**\n * Cleanup handlers for graceful shutdown.\n * These are run by exit.ts's gracefulExit() via runCleanupHandlers().\n */\nconst cleanupHandlers: Array<() => void | Promise<void>> = []\n\n/**\n * Register a cleanup handler to be called during shutdown\n */\nexport function registerCleanupHandler(\n handler: () => void | Promise<void>,\n): void {\n cleanupHandlers.push(handler)\n}\n\n/**\n * Unregister a cleanup handler\n */\nexport function unregisterCleanupHandler(\n handler: () => void | Promise<void>,\n): void {\n const index = cleanupHandlers.indexOf(handler)\n if (index > -1) {\n cleanupHandlers.splice(index, 1)\n }\n}\n\n/**\n * Run all registered cleanup handlers.\n * Called by exit.ts's gracefulExit() to integrate cleanup into\n * the single shutdown path.\n */\nexport async function runCleanupHandlers(): Promise<void> {\n for (const handler of cleanupHandlers) {\n try {\n await handler()\n } catch (error) {\n console.error('Cleanup handler error:', error)\n }\n }\n}\n\n/**\n * Initialize global error handlers\n * Should be called early in the application lifecycle.\n *\n * NOTE: Signal handlers (SIGINT, SIGTERM, SIGBREAK) and process lifecycle\n * handlers (exit, unhandledRejection, uncaughtException) are managed by\n * setupExitHandlers() in exit.ts to avoid duplicate registrations.\n * This module focuses on warning handling and cleanup handler orchestration.\n */\nexport function initGlobalErrorHandlers(): void {\n if (isInitialized) return\n isInitialized = true\n\n // Handle warnings (unique to this module \u2014 exit.ts does not handle warnings)\n process.on('warning', handleWarning)\n\n // Handle beforeExit for cleanup \u2014 delegate to exit.ts's unified shutdown\n process.on('beforeExit', code => {\n if (cleanupHandlers.length > 0) {\n gracefulExit(code)\n }\n })\n}\n\n/**\n * Check if global error handlers are initialized\n */\nexport function isGlobalErrorHandlersInitialized(): boolean {\n return isInitialized\n}\n\n/**\n * Reset global error handlers (for testing)\n */\nexport function resetGlobalErrorHandlers(): void {\n if (process.env.NODE_ENV !== 'test') {\n throw new Error('resetGlobalErrorHandlers can only be called in tests')\n }\n\n process.removeAllListeners('warning')\n process.removeAllListeners('beforeExit')\n\n isInitialized = false\n cleanupHandlers.length = 0\n}\n"],
5
+ "mappings": "AAYA,SAAS,oBAAoB;AAE7B,IAAI,gBAAgB;AAKpB,SAAS,cAAc,SAAsB;AAE3C,MACE,QAAQ,IAAI,YAAY,UACxB,QAAQ,SAAS,wBACjB,QAAQ,SAAS,uBACjB;AACA,YAAQ,KAAK;AAAA,yBAAkB,QAAQ,IAAI,MAAM,QAAQ,OAAO,EAAE;AAAA,EACpE;AACF;AAMA,MAAM,kBAAqD,CAAC;AAKrD,SAAS,uBACd,SACM;AACN,kBAAgB,KAAK,OAAO;AAC9B;AAKO,SAAS,yBACd,SACM;AACN,QAAM,QAAQ,gBAAgB,QAAQ,OAAO;AAC7C,MAAI,QAAQ,IAAI;AACd,oBAAgB,OAAO,OAAO,CAAC;AAAA,EACjC;AACF;AAOA,eAAsB,qBAAoC;AACxD,aAAW,WAAW,iBAAiB;AACrC,QAAI;AACF,YAAM,QAAQ;AAAA,IAChB,SAAS,OAAO;AACd,cAAQ,MAAM,0BAA0B,KAAK;AAAA,IAC/C;AAAA,EACF;AACF;AAWO,SAAS,0BAAgC;AAC9C,MAAI,cAAe;AACnB,kBAAgB;AAGhB,UAAQ,GAAG,WAAW,aAAa;AAGnC,UAAQ,GAAG,cAAc,UAAQ;AAC/B,QAAI,gBAAgB,SAAS,GAAG;AAC9B,mBAAa,IAAI;AAAA,IACnB;AAAA,EACF,CAAC;AACH;AAKO,SAAS,mCAA4C;AAC1D,SAAO;AACT;AAKO,SAAS,2BAAiC;AAC/C,MAAI,QAAQ,IAAI,aAAa,QAAQ;AACnC,UAAM,IAAI,MAAM,sDAAsD;AAAA,EACxE;AAEA,UAAQ,mBAAmB,SAAS;AACpC,UAAQ,mBAAmB,YAAY;AAEvC,kBAAgB;AAChB,kBAAgB,SAAS;AAC3B;",
6
+ "names": []
7
7
  }
@@ -10,7 +10,7 @@ class ParallelTasksHandler {
10
10
  if (!Array.isArray(msg.message.content)) continue;
11
11
  const originalUuid = msg.originalUuid || msg.uuid;
12
12
  const toolUse = msg.message.content.find(
13
- (block) => block.type === "tool_use" && block.name === "Task"
13
+ (block) => block.type === "tool_use" && (block.name === "Agent" || block.name === "Task")
14
14
  );
15
15
  if (toolUse) {
16
16
  if (!tasksByOriginalUuid.has(originalUuid)) {
@@ -64,7 +64,7 @@ class ParallelTasksHandler {
64
64
  const toolUse = content.find(
65
65
  (block) => block.type === "tool_use" && block.id === toolUseId
66
66
  );
67
- if (toolUse && toolUse.name === "Task") {
67
+ if (toolUse && (toolUse.name === "Agent" || toolUse.name === "Task")) {
68
68
  taskToolUseIds.push(toolUseId);
69
69
  messageUuids.add(assistantMsg.uuid);
70
70
  }
@@ -127,7 +127,9 @@ class ParallelTasksHandler {
127
127
  toolUseId,
128
128
  agentId: getAgentIdByToolUseId(toolUseId),
129
129
  description: input.description || "Task",
130
- agentType: input.subagent_type || "general-purpose"
130
+ agentType: input.subagent_type || "general-purpose",
131
+ teamName: input.team_name,
132
+ teammateName: input.name
131
133
  });
132
134
  }
133
135
  }