@within-7/minto 0.1.7 → 0.3.0

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 (601) hide show
  1. package/cli.js +155 -37
  2. package/dist/Tool.js +38 -0
  3. package/dist/Tool.js.map +3 -3
  4. package/dist/commands/agents/AgentsCommand.js +73 -49
  5. package/dist/commands/agents/AgentsCommand.js.map +2 -2
  6. package/dist/commands/agents/constants.js +1 -1
  7. package/dist/commands/agents/constants.js.map +1 -1
  8. package/dist/commands/agents/index.js +1 -1
  9. package/dist/commands/bug.js +74 -7
  10. package/dist/commands/bug.js.map +3 -3
  11. package/dist/commands/clear.js +3 -0
  12. package/dist/commands/clear.js.map +2 -2
  13. package/dist/commands/compact.js +37 -0
  14. package/dist/commands/compact.js.map +2 -2
  15. package/dist/commands/context.js +85 -0
  16. package/dist/commands/context.js.map +7 -0
  17. package/dist/commands/ctx_viz.js +18 -10
  18. package/dist/commands/ctx_viz.js.map +2 -2
  19. package/dist/commands/doctor.js +158 -12
  20. package/dist/commands/doctor.js.map +2 -2
  21. package/dist/commands/export.js +157 -0
  22. package/dist/commands/export.js.map +7 -0
  23. package/dist/commands/mcp-interactive.js +28 -18
  24. package/dist/commands/mcp-interactive.js.map +2 -2
  25. package/dist/commands/model.js +9 -7
  26. package/dist/commands/model.js.map +2 -2
  27. package/dist/commands/permissions.js +87 -0
  28. package/dist/commands/permissions.js.map +7 -0
  29. package/dist/commands/plugin/AddMarketplaceForm.js +3 -2
  30. package/dist/commands/plugin/AddMarketplaceForm.js.map +2 -2
  31. package/dist/commands/plugin/ConfirmDialog.js +2 -1
  32. package/dist/commands/plugin/ConfirmDialog.js.map +2 -2
  33. package/dist/commands/plugin/ErrorView.js +2 -1
  34. package/dist/commands/plugin/ErrorView.js.map +2 -2
  35. package/dist/commands/plugin/InstalledPluginsByMarketplace.js +5 -4
  36. package/dist/commands/plugin/InstalledPluginsByMarketplace.js.map +2 -2
  37. package/dist/commands/plugin/InstalledPluginsManager.js +5 -4
  38. package/dist/commands/plugin/InstalledPluginsManager.js.map +2 -2
  39. package/dist/commands/plugin/MainMenu.js +2 -1
  40. package/dist/commands/plugin/MainMenu.js.map +2 -2
  41. package/dist/commands/plugin/MarketplaceManager.js +5 -4
  42. package/dist/commands/plugin/MarketplaceManager.js.map +2 -2
  43. package/dist/commands/plugin/MarketplaceSelector.js +4 -3
  44. package/dist/commands/plugin/MarketplaceSelector.js.map +2 -2
  45. package/dist/commands/plugin/PlaceholderScreen.js +3 -2
  46. package/dist/commands/plugin/PlaceholderScreen.js.map +2 -2
  47. package/dist/commands/plugin/PluginBrowser.js +6 -5
  48. package/dist/commands/plugin/PluginBrowser.js.map +2 -2
  49. package/dist/commands/plugin/PluginDetailsInstall.js +5 -4
  50. package/dist/commands/plugin/PluginDetailsInstall.js.map +2 -2
  51. package/dist/commands/plugin/PluginDetailsManage.js +4 -3
  52. package/dist/commands/plugin/PluginDetailsManage.js.map +2 -2
  53. package/dist/commands/plugin.js +16 -15
  54. package/dist/commands/plugin.js.map +2 -2
  55. package/dist/commands/quit.js +3 -1
  56. package/dist/commands/quit.js.map +2 -2
  57. package/dist/commands/sandbox.js +105 -0
  58. package/dist/commands/sandbox.js.map +7 -0
  59. package/dist/commands/setup.js +2 -1
  60. package/dist/commands/setup.js.map +2 -2
  61. package/dist/commands/status.js +59 -0
  62. package/dist/commands/status.js.map +7 -0
  63. package/dist/commands/tasks.js +108 -0
  64. package/dist/commands/tasks.js.map +7 -0
  65. package/dist/commands/todos.js +123 -0
  66. package/dist/commands/todos.js.map +7 -0
  67. package/dist/commands/undo.js +245 -0
  68. package/dist/commands/undo.js.map +7 -0
  69. package/dist/commands.js +22 -2
  70. package/dist/commands.js.map +2 -2
  71. package/dist/components/AgentThinkingBlock.js +10 -18
  72. package/dist/components/AgentThinkingBlock.js.map +2 -2
  73. package/dist/components/AsciiLogo.js +7 -8
  74. package/dist/components/AsciiLogo.js.map +2 -2
  75. package/dist/components/AskUserQuestionDialog/AskUserQuestionDialog.js +3 -2
  76. package/dist/components/AskUserQuestionDialog/AskUserQuestionDialog.js.map +2 -2
  77. package/dist/components/AskUserQuestionDialog/QuestionView.js +2 -1
  78. package/dist/components/AskUserQuestionDialog/QuestionView.js.map +2 -2
  79. package/dist/components/BackgroundTasksPanel.js +78 -29
  80. package/dist/components/BackgroundTasksPanel.js.map +2 -2
  81. package/dist/components/BashStreamingProgress.js +24 -0
  82. package/dist/components/BashStreamingProgress.js.map +7 -0
  83. package/dist/components/CollapsibleHint.js +15 -0
  84. package/dist/components/CollapsibleHint.js.map +7 -0
  85. package/dist/components/Config.js +3 -2
  86. package/dist/components/Config.js.map +2 -2
  87. package/dist/components/ConsoleOAuthFlow.js +2 -1
  88. package/dist/components/ConsoleOAuthFlow.js.map +2 -2
  89. package/dist/components/Cost.js +2 -1
  90. package/dist/components/Cost.js.map +2 -2
  91. package/dist/components/FileEditToolUpdatedMessage.js +1 -1
  92. package/dist/components/FileEditToolUpdatedMessage.js.map +2 -2
  93. package/dist/components/HeaderBar.js +13 -8
  94. package/dist/components/HeaderBar.js.map +2 -2
  95. package/dist/components/HistorySearchOverlay.js +4 -3
  96. package/dist/components/HistorySearchOverlay.js.map +2 -2
  97. package/dist/components/HotkeyHelpPanel.js +134 -0
  98. package/dist/components/HotkeyHelpPanel.js.map +7 -0
  99. package/dist/components/InvalidConfigDialog.js +2 -1
  100. package/dist/components/InvalidConfigDialog.js.map +2 -2
  101. package/dist/components/Logo.js +24 -68
  102. package/dist/components/Logo.js.map +2 -2
  103. package/dist/components/MCPServerApprovalDialog.js +2 -1
  104. package/dist/components/MCPServerApprovalDialog.js.map +2 -2
  105. package/dist/components/MCPServerDialogCopy.js +2 -1
  106. package/dist/components/MCPServerDialogCopy.js.map +2 -2
  107. package/dist/components/MCPServerMultiselectDialog.js +2 -1
  108. package/dist/components/MCPServerMultiselectDialog.js.map +2 -2
  109. package/dist/components/Message.js +23 -7
  110. package/dist/components/Message.js.map +3 -3
  111. package/dist/components/MessageSelector.js +4 -3
  112. package/dist/components/MessageSelector.js.map +2 -2
  113. package/dist/components/ModeIndicator.js +2 -1
  114. package/dist/components/ModeIndicator.js.map +2 -2
  115. package/dist/components/ModelConfig.js +20 -6
  116. package/dist/components/ModelConfig.js.map +2 -2
  117. package/dist/components/ModelListManager.js +7 -6
  118. package/dist/components/ModelListManager.js.map +2 -2
  119. package/dist/components/ModelSelector/ModelSelector.js +27 -14
  120. package/dist/components/ModelSelector/ModelSelector.js.map +2 -2
  121. package/dist/components/Onboarding.js +22 -16
  122. package/dist/components/Onboarding.js.map +2 -2
  123. package/dist/components/OperationSummary.js +130 -0
  124. package/dist/components/OperationSummary.js.map +7 -0
  125. package/dist/components/ProgressBar.js +74 -0
  126. package/dist/components/ProgressBar.js.map +7 -0
  127. package/dist/components/PromptInput.js +210 -87
  128. package/dist/components/PromptInput.js.map +2 -2
  129. package/dist/components/RequestStatusIndicator.js +194 -0
  130. package/dist/components/RequestStatusIndicator.js.map +7 -0
  131. package/dist/components/SensitiveFileWarning.js +31 -0
  132. package/dist/components/SensitiveFileWarning.js.map +7 -0
  133. package/dist/components/Spinner.js +141 -27
  134. package/dist/components/Spinner.js.map +2 -2
  135. package/dist/components/SpinnerSymbol.js +21 -27
  136. package/dist/components/SpinnerSymbol.js.map +2 -2
  137. package/dist/components/StreamingBashOutput.js +9 -8
  138. package/dist/components/StreamingBashOutput.js.map +2 -2
  139. package/dist/components/StructuredDiff.js +6 -8
  140. package/dist/components/StructuredDiff.js.map +2 -2
  141. package/dist/components/SubagentBlock.js +5 -3
  142. package/dist/components/SubagentBlock.js.map +2 -2
  143. package/dist/components/SubagentProgress.js +17 -15
  144. package/dist/components/SubagentProgress.js.map +2 -2
  145. package/dist/components/TaskCard.js +30 -24
  146. package/dist/components/TaskCard.js.map +2 -2
  147. package/dist/components/TextInput.js +9 -1
  148. package/dist/components/TextInput.js.map +2 -2
  149. package/dist/components/TodoChangeBlock.js +1 -1
  150. package/dist/components/TodoChangeBlock.js.map +2 -2
  151. package/dist/components/TodoPanel.js +140 -31
  152. package/dist/components/TodoPanel.js.map +3 -3
  153. package/dist/components/TokenCounter.js +74 -0
  154. package/dist/components/TokenCounter.js.map +7 -0
  155. package/dist/components/TokenWarning.js +2 -1
  156. package/dist/components/TokenWarning.js.map +2 -2
  157. package/dist/components/ToolUseLoader.js +2 -2
  158. package/dist/components/ToolUseLoader.js.map +2 -2
  159. package/dist/components/TreeConnector.js +26 -0
  160. package/dist/components/TreeConnector.js.map +7 -0
  161. package/dist/components/TrustDialog.js +2 -1
  162. package/dist/components/TrustDialog.js.map +2 -2
  163. package/dist/components/TurnCompletionIndicator.js +18 -0
  164. package/dist/components/TurnCompletionIndicator.js.map +7 -0
  165. package/dist/components/binary-feedback/BinaryFeedbackView.js +2 -1
  166. package/dist/components/binary-feedback/BinaryFeedbackView.js.map +2 -2
  167. package/dist/components/messages/AssistantTextMessage.js +20 -9
  168. package/dist/components/messages/AssistantTextMessage.js.map +2 -2
  169. package/dist/components/messages/AssistantThinkingMessage.js +18 -3
  170. package/dist/components/messages/AssistantThinkingMessage.js.map +2 -2
  171. package/dist/components/messages/AssistantToolUseMessage.js +17 -10
  172. package/dist/components/messages/AssistantToolUseMessage.js.map +2 -2
  173. package/dist/components/messages/GroupRenderer.js +54 -0
  174. package/dist/components/messages/GroupRenderer.js.map +7 -0
  175. package/dist/components/messages/NestedTasksPreview.js +24 -0
  176. package/dist/components/messages/NestedTasksPreview.js.map +7 -0
  177. package/dist/components/messages/ParallelTasksGroupView.js +93 -0
  178. package/dist/components/messages/ParallelTasksGroupView.js.map +7 -0
  179. package/dist/components/messages/TaskInModuleView.js +218 -0
  180. package/dist/components/messages/TaskInModuleView.js.map +7 -0
  181. package/dist/components/messages/TaskOutputContent.js +56 -0
  182. package/dist/components/messages/TaskOutputContent.js.map +7 -0
  183. package/dist/components/messages/UserPromptMessage.js +2 -2
  184. package/dist/components/messages/UserPromptMessage.js.map +2 -2
  185. package/dist/components/messages/UserToolResultMessage/UserToolSuccessMessage.js +2 -3
  186. package/dist/components/messages/UserToolResultMessage/UserToolSuccessMessage.js.map +2 -2
  187. package/dist/components/permissions/FallbackPermissionRequest.js +4 -4
  188. package/dist/components/permissions/FallbackPermissionRequest.js.map +2 -2
  189. package/dist/components/permissions/FilesystemPermissionRequest/FilesystemPermissionRequest.js +4 -4
  190. package/dist/components/permissions/FilesystemPermissionRequest/FilesystemPermissionRequest.js.map +2 -2
  191. package/dist/constants/colors.js +120 -54
  192. package/dist/constants/colors.js.map +2 -2
  193. package/dist/constants/formatRules.js +102 -0
  194. package/dist/constants/formatRules.js.map +7 -0
  195. package/dist/constants/prompts.js +12 -34
  196. package/dist/constants/prompts.js.map +2 -2
  197. package/dist/constants/symbols.js +64 -6
  198. package/dist/constants/symbols.js.map +2 -2
  199. package/dist/constants/timing.js +5 -0
  200. package/dist/constants/timing.js.map +2 -2
  201. package/dist/constants/toolInputExamples.js +84 -0
  202. package/dist/constants/toolInputExamples.js.map +7 -0
  203. package/dist/core/backupManager.js +321 -0
  204. package/dist/core/backupManager.js.map +7 -0
  205. package/dist/core/config/defaults.js +84 -0
  206. package/dist/core/config/defaults.js.map +7 -0
  207. package/dist/core/config/index.js +111 -0
  208. package/dist/core/config/index.js.map +7 -0
  209. package/dist/core/config/loader.js +221 -0
  210. package/dist/core/config/loader.js.map +7 -0
  211. package/dist/core/config/migrations.js +128 -0
  212. package/dist/core/config/migrations.js.map +7 -0
  213. package/dist/core/config/schema.js +178 -0
  214. package/dist/core/config/schema.js.map +7 -0
  215. package/dist/core/costTracker.js +129 -0
  216. package/dist/core/costTracker.js.map +7 -0
  217. package/dist/core/gitAutoCommit.js +287 -0
  218. package/dist/core/gitAutoCommit.js.map +7 -0
  219. package/dist/core/index.js +8 -0
  220. package/dist/core/index.js.map +7 -0
  221. package/dist/core/operationTracker.js +212 -0
  222. package/dist/core/operationTracker.js.map +7 -0
  223. package/dist/core/permissions/auditLog.js +204 -0
  224. package/dist/core/permissions/auditLog.js.map +7 -0
  225. package/dist/core/permissions/engine/index.js +3 -0
  226. package/dist/core/permissions/engine/index.js.map +7 -0
  227. package/dist/core/permissions/engine/permissionEngine.js +106 -0
  228. package/dist/core/permissions/engine/permissionEngine.js.map +7 -0
  229. package/dist/core/permissions/engine/types.js +1 -0
  230. package/dist/core/permissions/engine/types.js.map +7 -0
  231. package/dist/core/permissions/index.js +84 -0
  232. package/dist/core/permissions/index.js.map +7 -0
  233. package/dist/core/permissions/ruleEngine.js +259 -0
  234. package/dist/core/permissions/ruleEngine.js.map +7 -0
  235. package/dist/core/permissions/rules/allowedToolsRule.js +62 -0
  236. package/dist/core/permissions/rules/allowedToolsRule.js.map +7 -0
  237. package/dist/core/permissions/rules/autoEscalationRule.js +296 -0
  238. package/dist/core/permissions/rules/autoEscalationRule.js.map +7 -0
  239. package/dist/core/permissions/rules/index.js +46 -0
  240. package/dist/core/permissions/rules/index.js.map +7 -0
  241. package/dist/core/permissions/rules/planModeRule.js +55 -0
  242. package/dist/core/permissions/rules/planModeRule.js.map +7 -0
  243. package/dist/core/permissions/rules/projectBoundaryRule.js +173 -0
  244. package/dist/core/permissions/rules/projectBoundaryRule.js.map +7 -0
  245. package/dist/core/permissions/rules/safeModeRule.js +65 -0
  246. package/dist/core/permissions/rules/safeModeRule.js.map +7 -0
  247. package/dist/core/permissions/rules/sensitivePathsRule.js +345 -0
  248. package/dist/core/permissions/rules/sensitivePathsRule.js.map +7 -0
  249. package/dist/core/permissions/types.js +127 -0
  250. package/dist/core/permissions/types.js.map +7 -0
  251. package/dist/core/tokenStats.js +9 -0
  252. package/dist/core/tokenStats.js.map +7 -0
  253. package/dist/core/tokenStatsManager.js +331 -0
  254. package/dist/core/tokenStatsManager.js.map +7 -0
  255. package/dist/core/tools/executor.js +143 -0
  256. package/dist/core/tools/executor.js.map +7 -0
  257. package/dist/core/tools/index.js +15 -0
  258. package/dist/core/tools/index.js.map +7 -0
  259. package/dist/core/tools/registry.js +183 -0
  260. package/dist/core/tools/registry.js.map +7 -0
  261. package/dist/core/tools/types.js +1 -0
  262. package/dist/core/tools/types.js.map +7 -0
  263. package/dist/cost-tracker.js +23 -15
  264. package/dist/cost-tracker.js.map +2 -2
  265. package/dist/entrypoints/cli.js +158 -130
  266. package/dist/entrypoints/cli.js.map +2 -2
  267. package/dist/entrypoints/mcp.js +12 -4
  268. package/dist/entrypoints/mcp.js.map +2 -2
  269. package/dist/history.js +14 -3
  270. package/dist/history.js.map +2 -2
  271. package/dist/hooks/useAgentTokenStats.js +72 -0
  272. package/dist/hooks/useAgentTokenStats.js.map +7 -0
  273. package/dist/hooks/useAgentTranscripts.js +140 -0
  274. package/dist/hooks/useAgentTranscripts.js.map +7 -0
  275. package/dist/hooks/useAnimationSync.js +53 -0
  276. package/dist/hooks/useAnimationSync.js.map +7 -0
  277. package/dist/hooks/useArrowKeyHistory.js +4 -2
  278. package/dist/hooks/useArrowKeyHistory.js.map +2 -2
  279. package/dist/hooks/useCanUseTool.js +3 -1
  280. package/dist/hooks/useCanUseTool.js.map +2 -2
  281. package/dist/hooks/useExitOnCtrlCD.js +9 -5
  282. package/dist/hooks/useExitOnCtrlCD.js.map +2 -2
  283. package/dist/hooks/useHookStatus.js +40 -0
  284. package/dist/hooks/useHookStatus.js.map +7 -0
  285. package/dist/hooks/useLogMessages.js +29 -2
  286. package/dist/hooks/useLogMessages.js.map +2 -2
  287. package/dist/hooks/useMessageGroups.js +43 -0
  288. package/dist/hooks/useMessageGroups.js.map +7 -0
  289. package/dist/hooks/useTerminalSize.js +62 -6
  290. package/dist/hooks/useTerminalSize.js.map +2 -2
  291. package/dist/hooks/useUnifiedCompletion.js +69 -0
  292. package/dist/hooks/useUnifiedCompletion.js.map +2 -2
  293. package/dist/i18n/index.js +109 -0
  294. package/dist/i18n/index.js.map +7 -0
  295. package/dist/i18n/locales/en.js +348 -0
  296. package/dist/i18n/locales/en.js.map +7 -0
  297. package/dist/i18n/locales/index.js +7 -0
  298. package/dist/i18n/locales/index.js.map +7 -0
  299. package/dist/i18n/locales/zh-CN.js +348 -0
  300. package/dist/i18n/locales/zh-CN.js.map +7 -0
  301. package/dist/i18n/types.js +8 -0
  302. package/dist/i18n/types.js.map +7 -0
  303. package/dist/permissions.js +28 -1
  304. package/dist/permissions.js.map +2 -2
  305. package/dist/query.js +253 -21
  306. package/dist/query.js.map +3 -3
  307. package/dist/screens/REPL.js +523 -194
  308. package/dist/screens/REPL.js.map +3 -3
  309. package/dist/services/adapters/chatCompletions.js +3 -1
  310. package/dist/services/adapters/chatCompletions.js.map +2 -2
  311. package/dist/services/adapters/messageNormalizer.js +354 -0
  312. package/dist/services/adapters/messageNormalizer.js.map +7 -0
  313. package/dist/services/adapters/responsesAPI.js +6 -3
  314. package/dist/services/adapters/responsesAPI.js.map +2 -2
  315. package/dist/services/checkpointManager.js +386 -0
  316. package/dist/services/checkpointManager.js.map +7 -0
  317. package/dist/services/claude.js +192 -14
  318. package/dist/services/claude.js.map +3 -3
  319. package/dist/services/compressionService.js +50 -1
  320. package/dist/services/compressionService.js.map +2 -2
  321. package/dist/services/contextMonitor.js +162 -0
  322. package/dist/services/contextMonitor.js.map +7 -0
  323. package/dist/services/customCommands.js +60 -41
  324. package/dist/services/customCommands.js.map +2 -2
  325. package/dist/services/hookExecutor.js +173 -1
  326. package/dist/services/hookExecutor.js.map +2 -2
  327. package/dist/services/intelligentCompactor.js +281 -0
  328. package/dist/services/intelligentCompactor.js.map +7 -0
  329. package/dist/services/lspConfig.js +109 -0
  330. package/dist/services/lspConfig.js.map +7 -0
  331. package/dist/services/mcpClient.js +338 -43
  332. package/dist/services/mcpClient.js.map +2 -2
  333. package/dist/services/modelOrchestrator.js +310 -0
  334. package/dist/services/modelOrchestrator.js.map +7 -0
  335. package/dist/services/openai.js +8 -1
  336. package/dist/services/openai.js.map +2 -2
  337. package/dist/services/outputStyles.js +138 -0
  338. package/dist/services/outputStyles.js.map +7 -0
  339. package/dist/services/plugins/index.js +5 -0
  340. package/dist/services/plugins/index.js.map +7 -0
  341. package/dist/services/plugins/lspServers.js +188 -0
  342. package/dist/services/plugins/lspServers.js.map +7 -0
  343. package/dist/services/plugins/pluginRuntime.js +229 -0
  344. package/dist/services/plugins/pluginRuntime.js.map +7 -0
  345. package/dist/services/plugins/pluginValidation.js +219 -0
  346. package/dist/services/plugins/pluginValidation.js.map +7 -0
  347. package/dist/services/plugins/skillMarketplace.js +556 -0
  348. package/dist/services/plugins/skillMarketplace.js.map +7 -0
  349. package/dist/services/responseStateManager.js +37 -3
  350. package/dist/services/responseStateManager.js.map +2 -2
  351. package/dist/services/sandbox/filesystemBoundary.js +341 -0
  352. package/dist/services/sandbox/filesystemBoundary.js.map +7 -0
  353. package/dist/services/sandbox/index.js +14 -0
  354. package/dist/services/sandbox/index.js.map +7 -0
  355. package/dist/services/sandbox/networkProxy.js +293 -0
  356. package/dist/services/sandbox/networkProxy.js.map +7 -0
  357. package/dist/services/sandbox/sandboxController.js +574 -0
  358. package/dist/services/sandbox/sandboxController.js.map +7 -0
  359. package/dist/services/sandbox/types.js +50 -0
  360. package/dist/services/sandbox/types.js.map +7 -0
  361. package/dist/services/sessionMemory.js +266 -0
  362. package/dist/services/sessionMemory.js.map +7 -0
  363. package/dist/services/taskRouter.js +324 -0
  364. package/dist/services/taskRouter.js.map +7 -0
  365. package/dist/tools/ArchitectTool/ArchitectTool.js +7 -1
  366. package/dist/tools/ArchitectTool/ArchitectTool.js.map +2 -2
  367. package/dist/tools/AskExpertModelTool/AskExpertModelTool.js +6 -2
  368. package/dist/tools/AskExpertModelTool/AskExpertModelTool.js.map +2 -2
  369. package/dist/tools/AskUserQuestionTool/AskUserQuestionTool.js +2 -1
  370. package/dist/tools/AskUserQuestionTool/AskUserQuestionTool.js.map +2 -2
  371. package/dist/tools/BaseTool.js +72 -0
  372. package/dist/tools/BaseTool.js.map +7 -0
  373. package/dist/tools/BashOutputTool/BashOutputToolResultMessage.js +3 -0
  374. package/dist/tools/BashOutputTool/BashOutputToolResultMessage.js.map +2 -2
  375. package/dist/tools/BashTool/BashTool.js +79 -3
  376. package/dist/tools/BashTool/BashTool.js.map +2 -2
  377. package/dist/tools/BashTool/BashToolResultMessage.js +3 -0
  378. package/dist/tools/BashTool/BashToolResultMessage.js.map +2 -2
  379. package/dist/tools/BashTool/OutputLine.js +54 -0
  380. package/dist/tools/BashTool/OutputLine.js.map +2 -2
  381. package/dist/tools/BashTool/prompt.js +336 -3
  382. package/dist/tools/BashTool/prompt.js.map +2 -2
  383. package/dist/tools/FileEditTool/FileEditTool.js +29 -4
  384. package/dist/tools/FileEditTool/FileEditTool.js.map +2 -2
  385. package/dist/tools/FileEditTool/prompt.js +6 -3
  386. package/dist/tools/FileEditTool/prompt.js.map +2 -2
  387. package/dist/tools/FileWriteTool/FileWriteTool.js +5 -5
  388. package/dist/tools/FileWriteTool/FileWriteTool.js.map +2 -2
  389. package/dist/tools/FileWriteTool/prompt.js +4 -2
  390. package/dist/tools/FileWriteTool/prompt.js.map +2 -2
  391. package/dist/tools/GlobTool/GlobTool.js +4 -2
  392. package/dist/tools/GlobTool/GlobTool.js.map +2 -2
  393. package/dist/tools/GrepTool/GrepTool.js +36 -7
  394. package/dist/tools/GrepTool/GrepTool.js.map +2 -2
  395. package/dist/tools/KillShellTool/KillShellToolResultMessage.js +3 -0
  396. package/dist/tools/KillShellTool/KillShellToolResultMessage.js.map +2 -2
  397. package/dist/tools/ListMcpResourcesTool/ListMcpResourcesTool.js +109 -0
  398. package/dist/tools/ListMcpResourcesTool/ListMcpResourcesTool.js.map +7 -0
  399. package/dist/tools/ListMcpResourcesTool/prompt.js +19 -0
  400. package/dist/tools/ListMcpResourcesTool/prompt.js.map +7 -0
  401. package/dist/tools/LspTool/LspTool.js +664 -0
  402. package/dist/tools/LspTool/LspTool.js.map +7 -0
  403. package/dist/tools/LspTool/prompt.js +27 -0
  404. package/dist/tools/LspTool/prompt.js.map +7 -0
  405. package/dist/tools/MCPTool/MCPTool.js +9 -1
  406. package/dist/tools/MCPTool/MCPTool.js.map +2 -2
  407. package/dist/tools/MemoryReadTool/MemoryReadTool.js +19 -6
  408. package/dist/tools/MemoryReadTool/MemoryReadTool.js.map +2 -2
  409. package/dist/tools/MemoryWriteTool/MemoryWriteTool.js +6 -6
  410. package/dist/tools/MemoryWriteTool/MemoryWriteTool.js.map +2 -2
  411. package/dist/tools/MultiEditTool/MultiEditTool.js +19 -2
  412. package/dist/tools/MultiEditTool/MultiEditTool.js.map +2 -2
  413. package/dist/tools/MultiEditTool/prompt.js +5 -3
  414. package/dist/tools/MultiEditTool/prompt.js.map +2 -2
  415. package/dist/tools/NotebookEditTool/NotebookEditTool.js +7 -2
  416. package/dist/tools/NotebookEditTool/NotebookEditTool.js.map +2 -2
  417. package/dist/tools/NotebookReadTool/NotebookReadTool.js.map +2 -2
  418. package/dist/tools/PlanModeTool/EnterPlanModeTool.js +75 -0
  419. package/dist/tools/PlanModeTool/EnterPlanModeTool.js.map +7 -0
  420. package/dist/tools/PlanModeTool/ExitPlanModeTool.js +109 -0
  421. package/dist/tools/PlanModeTool/ExitPlanModeTool.js.map +7 -0
  422. package/dist/tools/PlanModeTool/prompt.js +94 -0
  423. package/dist/tools/PlanModeTool/prompt.js.map +7 -0
  424. package/dist/tools/ReadMcpResourceTool/ReadMcpResourceTool.js +130 -0
  425. package/dist/tools/ReadMcpResourceTool/ReadMcpResourceTool.js.map +7 -0
  426. package/dist/tools/ReadMcpResourceTool/prompt.js +17 -0
  427. package/dist/tools/ReadMcpResourceTool/prompt.js.map +7 -0
  428. package/dist/tools/SkillTool/SkillTool.js +10 -4
  429. package/dist/tools/SkillTool/SkillTool.js.map +2 -2
  430. package/dist/tools/SkillTool/prompt.js +1 -1
  431. package/dist/tools/SkillTool/prompt.js.map +1 -1
  432. package/dist/tools/SlashCommandTool/SlashCommandTool.js +260 -0
  433. package/dist/tools/SlashCommandTool/SlashCommandTool.js.map +7 -0
  434. package/dist/tools/SlashCommandTool/prompt.js +35 -0
  435. package/dist/tools/SlashCommandTool/prompt.js.map +7 -0
  436. package/dist/tools/TaskOutputTool/TaskOutputTool.js +190 -0
  437. package/dist/tools/TaskOutputTool/TaskOutputTool.js.map +7 -0
  438. package/dist/tools/TaskOutputTool/prompt.js +15 -0
  439. package/dist/tools/TaskOutputTool/prompt.js.map +7 -0
  440. package/dist/tools/TaskTool/TaskTool.js +310 -104
  441. package/dist/tools/TaskTool/TaskTool.js.map +2 -2
  442. package/dist/tools/TaskTool/prompt.js.map +2 -2
  443. package/dist/tools/TodoWriteTool/TodoWriteTool.js +42 -77
  444. package/dist/tools/TodoWriteTool/TodoWriteTool.js.map +2 -2
  445. package/dist/tools/URLFetcherTool/URLFetcherTool.js +4 -1
  446. package/dist/tools/URLFetcherTool/URLFetcherTool.js.map +2 -2
  447. package/dist/tools/URLFetcherTool/cache.js +55 -8
  448. package/dist/tools/URLFetcherTool/cache.js.map +2 -2
  449. package/dist/tools.js +31 -2
  450. package/dist/tools.js.map +2 -2
  451. package/dist/types/hooks.js +4 -0
  452. package/dist/types/hooks.js.map +2 -2
  453. package/dist/types/marketplace.js.map +2 -2
  454. package/dist/types/messageGroup.js +36 -0
  455. package/dist/types/messageGroup.js.map +7 -0
  456. package/dist/types/plugin.js.map +2 -2
  457. package/dist/types/thinking.js +1 -0
  458. package/dist/types/thinking.js.map +7 -0
  459. package/dist/utils/BackgroundShellManager.js +136 -39
  460. package/dist/utils/BackgroundShellManager.js.map +2 -2
  461. package/dist/utils/CircuitBreaker.js +242 -0
  462. package/dist/utils/CircuitBreaker.js.map +7 -0
  463. package/dist/utils/MessageBatchBuffer.js +102 -0
  464. package/dist/utils/MessageBatchBuffer.js.map +7 -0
  465. package/dist/utils/PersistentShell.js +151 -1
  466. package/dist/utils/PersistentShell.js.map +2 -2
  467. package/dist/utils/agentLoader.js +1 -23
  468. package/dist/utils/agentLoader.js.map +2 -2
  469. package/dist/utils/agentTranscripts.js +641 -0
  470. package/dist/utils/agentTranscripts.js.map +7 -0
  471. package/dist/utils/animationManager.js +213 -0
  472. package/dist/utils/animationManager.js.map +7 -0
  473. package/dist/utils/animationSync.js +110 -0
  474. package/dist/utils/animationSync.js.map +7 -0
  475. package/dist/utils/ask.js +2 -0
  476. package/dist/utils/ask.js.map +2 -2
  477. package/dist/utils/asyncFile.js +215 -0
  478. package/dist/utils/asyncFile.js.map +7 -0
  479. package/dist/utils/backgroundAgentManager.js +231 -0
  480. package/dist/utils/backgroundAgentManager.js.map +7 -0
  481. package/dist/utils/config.js +108 -10
  482. package/dist/utils/config.js.map +2 -2
  483. package/dist/utils/conversationRecovery.js +19 -0
  484. package/dist/utils/conversationRecovery.js.map +2 -2
  485. package/dist/utils/credentials/CredentialStore.js +1 -0
  486. package/dist/utils/credentials/CredentialStore.js.map +7 -0
  487. package/dist/utils/credentials/EncryptedFileStore.js +157 -0
  488. package/dist/utils/credentials/EncryptedFileStore.js.map +7 -0
  489. package/dist/utils/credentials/index.js +37 -0
  490. package/dist/utils/credentials/index.js.map +7 -0
  491. package/dist/utils/credentials/migration.js +82 -0
  492. package/dist/utils/credentials/migration.js.map +7 -0
  493. package/dist/utils/exit.js +73 -0
  494. package/dist/utils/exit.js.map +7 -0
  495. package/dist/utils/format.js +73 -5
  496. package/dist/utils/format.js.map +2 -2
  497. package/dist/utils/generators.js +76 -6
  498. package/dist/utils/generators.js.map +2 -2
  499. package/dist/utils/globalErrorHandler.js +149 -0
  500. package/dist/utils/globalErrorHandler.js.map +7 -0
  501. package/dist/utils/groupHandlers/index.js +8 -0
  502. package/dist/utils/groupHandlers/index.js.map +7 -0
  503. package/dist/utils/groupHandlers/parallelTasksHandler.js +140 -0
  504. package/dist/utils/groupHandlers/parallelTasksHandler.js.map +7 -0
  505. package/dist/utils/groupHandlers/taskHandler.js +104 -0
  506. package/dist/utils/groupHandlers/taskHandler.js.map +7 -0
  507. package/dist/utils/groupHandlers/types.js +1 -0
  508. package/dist/utils/groupHandlers/types.js.map +7 -0
  509. package/dist/utils/logRotation.js +224 -0
  510. package/dist/utils/logRotation.js.map +7 -0
  511. package/dist/utils/markdown.js +13 -1
  512. package/dist/utils/markdown.js.map +2 -2
  513. package/dist/utils/marketplaceManager.js +3 -5
  514. package/dist/utils/marketplaceManager.js.map +2 -2
  515. package/dist/utils/memSafety.js +264 -0
  516. package/dist/utils/memSafety.js.map +7 -0
  517. package/dist/utils/messageGroupManager.js +274 -0
  518. package/dist/utils/messageGroupManager.js.map +7 -0
  519. package/dist/utils/messages.js +13 -4
  520. package/dist/utils/messages.js.map +2 -2
  521. package/dist/utils/model.js +119 -15
  522. package/dist/utils/model.js.map +3 -3
  523. package/dist/utils/permissions/filesystem.js +162 -6
  524. package/dist/utils/permissions/filesystem.js.map +2 -2
  525. package/dist/utils/plan/planMode.js +143 -0
  526. package/dist/utils/plan/planMode.js.map +7 -0
  527. package/dist/utils/pluginLoader.js +17 -21
  528. package/dist/utils/pluginLoader.js.map +2 -2
  529. package/dist/utils/ripgrep.js +55 -2
  530. package/dist/utils/ripgrep.js.map +2 -2
  531. package/dist/utils/safePath.js +132 -0
  532. package/dist/utils/safePath.js.map +7 -0
  533. package/dist/utils/sanitizeInput.js +32 -0
  534. package/dist/utils/sanitizeInput.js.map +7 -0
  535. package/dist/utils/secureKeyStorage.js +312 -0
  536. package/dist/utils/secureKeyStorage.js.map +7 -0
  537. package/dist/utils/sensitiveFiles.js +125 -0
  538. package/dist/utils/sensitiveFiles.js.map +7 -0
  539. package/dist/utils/session/sessionPlugins.js +67 -0
  540. package/dist/utils/session/sessionPlugins.js.map +7 -0
  541. package/dist/utils/taskDisplayUtils.js +257 -0
  542. package/dist/utils/taskDisplayUtils.js.map +7 -0
  543. package/dist/utils/teamConfig.js +2 -1
  544. package/dist/utils/teamConfig.js.map +2 -2
  545. package/dist/utils/theme.js +6 -6
  546. package/dist/utils/theme.js.map +1 -1
  547. package/dist/utils/todoStorage.js +92 -2
  548. package/dist/utils/todoStorage.js.map +2 -2
  549. package/dist/utils/toolRiskClassification.js +207 -0
  550. package/dist/utils/toolRiskClassification.js.map +7 -0
  551. package/dist/utils/toolTimeout.js +136 -0
  552. package/dist/utils/toolTimeout.js.map +7 -0
  553. package/dist/utils/tooling/safeRender.js +116 -0
  554. package/dist/utils/tooling/safeRender.js.map +7 -0
  555. package/dist/utils/userFriendlyError.js +346 -0
  556. package/dist/utils/userFriendlyError.js.map +7 -0
  557. package/dist/utils/vendor/ripgrep/arm64-darwin/rg +0 -0
  558. package/dist/version.js +2 -2
  559. package/dist/version.js.map +1 -1
  560. package/package.json +17 -5
  561. package/scripts/postinstall.js +128 -38
  562. package/dist/commands/agents.js +0 -2086
  563. package/dist/commands/agents.js.map +0 -7
  564. package/dist/commands/build.js +0 -74
  565. package/dist/commands/build.js.map +0 -7
  566. package/dist/commands/compression.js +0 -57
  567. package/dist/commands/compression.js.map +0 -7
  568. package/dist/commands/listen.js +0 -37
  569. package/dist/commands/listen.js.map +0 -7
  570. package/dist/commands/login.js +0 -37
  571. package/dist/commands/login.js.map +0 -7
  572. package/dist/commands/logout.js +0 -33
  573. package/dist/commands/logout.js.map +0 -7
  574. package/dist/commands/mcp.js +0 -40
  575. package/dist/commands/mcp.js.map +0 -7
  576. package/dist/commands/mcp_refresh.js +0 -40
  577. package/dist/commands/mcp_refresh.js.map +0 -7
  578. package/dist/commands/modelstatus.js +0 -21
  579. package/dist/commands/modelstatus.js.map +0 -7
  580. package/dist/commands/onboarding.js +0 -36
  581. package/dist/commands/onboarding.js.map +0 -7
  582. package/dist/commands/plugin-interactive.js +0 -446
  583. package/dist/commands/plugin-interactive.js.map +0 -7
  584. package/dist/commands/pr_comments.js +0 -61
  585. package/dist/commands/pr_comments.js.map +0 -7
  586. package/dist/commands/release-notes.js +0 -30
  587. package/dist/commands/release-notes.js.map +0 -7
  588. package/dist/commands/review.js +0 -51
  589. package/dist/commands/review.js.map +0 -7
  590. package/dist/components/Bug.js +0 -147
  591. package/dist/components/Bug.js.map +0 -7
  592. package/dist/components/ModelSelector.js +0 -2062
  593. package/dist/components/ModelSelector.js.map +0 -7
  594. package/dist/components/ModelStatusDisplay.js +0 -87
  595. package/dist/components/ModelStatusDisplay.js.map +0 -7
  596. package/dist/entrypoints/cli-wrapper.js +0 -61
  597. package/dist/entrypoints/cli-wrapper.js.map +0 -7
  598. package/dist/hooks/useCancelRequest.js +0 -28
  599. package/dist/hooks/useCancelRequest.js.map +0 -7
  600. package/dist/screens/Doctor.js +0 -22
  601. package/dist/screens/Doctor.js.map +0 -7
@@ -0,0 +1,264 @@
1
+ class TokenCounter {
2
+ inputTokens = 0;
3
+ outputTokens = 0;
4
+ cacheReadTokens = 0;
5
+ cacheCreationTokens = 0;
6
+ reasoningTokens = 0;
7
+ /**
8
+ * Add token usage from a streaming chunk or response.
9
+ * Thread-safe accumulation.
10
+ */
11
+ add(usage) {
12
+ if (usage.input_tokens !== void 0) {
13
+ this.inputTokens += usage.input_tokens;
14
+ }
15
+ if (usage.output_tokens !== void 0) {
16
+ this.outputTokens += usage.output_tokens;
17
+ }
18
+ if (usage.cache_read_input_tokens !== void 0) {
19
+ this.cacheReadTokens += usage.cache_read_input_tokens;
20
+ }
21
+ if (usage.cache_creation_input_tokens !== void 0) {
22
+ this.cacheCreationTokens += usage.cache_creation_input_tokens;
23
+ }
24
+ if (usage.reasoning_tokens !== void 0) {
25
+ this.reasoningTokens += usage.reasoning_tokens;
26
+ }
27
+ if (usage.prompt_tokens !== void 0 && usage.input_tokens === void 0) {
28
+ this.inputTokens += usage.prompt_tokens;
29
+ }
30
+ if (usage.completion_tokens !== void 0 && usage.output_tokens === void 0) {
31
+ this.outputTokens += usage.completion_tokens;
32
+ }
33
+ }
34
+ /**
35
+ * Get accumulated totals.
36
+ */
37
+ getTotal() {
38
+ return {
39
+ input_tokens: this.inputTokens,
40
+ output_tokens: this.outputTokens,
41
+ cache_read_input_tokens: this.cacheReadTokens,
42
+ cache_creation_input_tokens: this.cacheCreationTokens,
43
+ reasoning_tokens: this.reasoningTokens
44
+ };
45
+ }
46
+ /**
47
+ * Reset counters (useful for reusing counter instances).
48
+ */
49
+ reset() {
50
+ this.inputTokens = 0;
51
+ this.outputTokens = 0;
52
+ this.cacheReadTokens = 0;
53
+ this.cacheCreationTokens = 0;
54
+ this.reasoningTokens = 0;
55
+ }
56
+ }
57
+ function safeParseResponse(response) {
58
+ if (response === null || response === void 0) {
59
+ return {
60
+ success: false,
61
+ data: null,
62
+ error: "Response is null or undefined"
63
+ };
64
+ }
65
+ if (typeof response !== "object") {
66
+ return {
67
+ success: false,
68
+ data: null,
69
+ error: `Invalid response type: ${typeof response}`
70
+ };
71
+ }
72
+ const res = response;
73
+ let content = [];
74
+ if (res.content !== void 0) {
75
+ if (!Array.isArray(res.content)) {
76
+ if (typeof res.content === "string") {
77
+ content = [{ type: "text", text: res.content }];
78
+ } else {
79
+ return {
80
+ success: false,
81
+ data: null,
82
+ error: "Content is not an array or string"
83
+ };
84
+ }
85
+ } else {
86
+ content = res.content.map((block) => {
87
+ if (block === null || block === void 0) {
88
+ return { type: "text", text: "" };
89
+ }
90
+ if (typeof block !== "object") {
91
+ return { type: "text", text: String(block) };
92
+ }
93
+ return block;
94
+ });
95
+ }
96
+ }
97
+ const rawUsage = res.usage || {};
98
+ const usage = {
99
+ input_tokens: safeNumber(rawUsage.input_tokens, 0),
100
+ output_tokens: safeNumber(rawUsage.output_tokens, 0),
101
+ cache_read_input_tokens: safeNumber(rawUsage.cache_read_input_tokens),
102
+ cache_creation_input_tokens: safeNumber(
103
+ rawUsage.cache_creation_input_tokens
104
+ )
105
+ };
106
+ return {
107
+ success: true,
108
+ data: {
109
+ content,
110
+ usage,
111
+ stop_reason: safeString(res.stop_reason),
112
+ id: safeString(res.id),
113
+ model: safeString(res.model)
114
+ },
115
+ error: null
116
+ };
117
+ }
118
+ function safeParseOpenAIResponse(response) {
119
+ if (response === null || response === void 0) {
120
+ return {
121
+ success: false,
122
+ data: null,
123
+ error: "Response is null or undefined"
124
+ };
125
+ }
126
+ if (typeof response !== "object") {
127
+ return {
128
+ success: false,
129
+ data: null,
130
+ error: `Invalid response type: ${typeof response}`
131
+ };
132
+ }
133
+ const res = response;
134
+ const choices = res.choices;
135
+ const firstChoice = choices?.[0];
136
+ const message = firstChoice?.message || {};
137
+ const rawToolCalls = message.tool_calls;
138
+ const tool_calls = (rawToolCalls || []).map((tc) => {
139
+ if (!tc || typeof tc !== "object") return null;
140
+ const func = tc.function;
141
+ return {
142
+ id: safeString(tc.id) || "",
143
+ type: safeString(tc.type) || "function",
144
+ function: {
145
+ name: safeString(func?.name) || "",
146
+ arguments: safeString(func?.arguments) || "{}"
147
+ }
148
+ };
149
+ }).filter((tc) => tc !== null);
150
+ const rawUsage = res.usage || {};
151
+ const usage = {
152
+ prompt_tokens: safeNumber(rawUsage.prompt_tokens, 0),
153
+ completion_tokens: safeNumber(rawUsage.completion_tokens, 0),
154
+ total_tokens: safeNumber(rawUsage.total_tokens, 0)
155
+ };
156
+ return {
157
+ success: true,
158
+ data: {
159
+ content: safeString(message.content) || "",
160
+ tool_calls,
161
+ usage,
162
+ finish_reason: safeString(firstChoice?.finish_reason),
163
+ id: safeString(res.id),
164
+ model: safeString(res.model)
165
+ },
166
+ error: null
167
+ };
168
+ }
169
+ function safeNumber(value, defaultValue) {
170
+ if (typeof value === "number" && !isNaN(value)) {
171
+ return value;
172
+ }
173
+ if (typeof value === "string") {
174
+ const parsed = parseFloat(value);
175
+ if (!isNaN(parsed)) {
176
+ return parsed;
177
+ }
178
+ }
179
+ return defaultValue ?? 0;
180
+ }
181
+ function safeString(value) {
182
+ if (typeof value === "string") {
183
+ return value;
184
+ }
185
+ if (value !== null && value !== void 0) {
186
+ return String(value);
187
+ }
188
+ return void 0;
189
+ }
190
+ function linkAbortSignal(externalSignal, controller) {
191
+ if (!externalSignal) {
192
+ return () => {
193
+ };
194
+ }
195
+ const onAbort = () => {
196
+ controller.abort();
197
+ };
198
+ externalSignal.addEventListener("abort", onAbort);
199
+ return () => {
200
+ externalSignal.removeEventListener("abort", onAbort);
201
+ };
202
+ }
203
+ function createLinkedAbortController(externalSignal) {
204
+ const controller = new AbortController();
205
+ if (externalSignal?.aborted) {
206
+ controller.abort();
207
+ return { controller, cleanup: () => {
208
+ } };
209
+ }
210
+ const cleanup = linkAbortSignal(externalSignal, controller);
211
+ return { controller, cleanup };
212
+ }
213
+ async function* safeStreamIterate(stream, signal) {
214
+ if (signal?.aborted) {
215
+ return;
216
+ }
217
+ const iterator = stream[Symbol.asyncIterator]();
218
+ try {
219
+ while (true) {
220
+ if (signal?.aborted) {
221
+ break;
222
+ }
223
+ const result = await iterator.next();
224
+ if (result.done) {
225
+ break;
226
+ }
227
+ if (signal?.aborted) {
228
+ break;
229
+ }
230
+ yield result.value;
231
+ }
232
+ } finally {
233
+ if (iterator.return) {
234
+ await iterator.return();
235
+ }
236
+ }
237
+ }
238
+ function extractTextContent(content) {
239
+ if (!Array.isArray(content)) {
240
+ return "";
241
+ }
242
+ return content.filter((block) => block?.type === "text" && typeof block.text === "string").map((block) => block.text).join("\n");
243
+ }
244
+ function extractToolUses(content) {
245
+ if (!Array.isArray(content)) {
246
+ return [];
247
+ }
248
+ return content.filter((block) => block?.type === "tool_use").map((block) => ({
249
+ id: block.id || "",
250
+ name: block.name || "",
251
+ input: block.input || {}
252
+ }));
253
+ }
254
+ export {
255
+ TokenCounter,
256
+ createLinkedAbortController,
257
+ extractTextContent,
258
+ extractToolUses,
259
+ linkAbortSignal,
260
+ safeParseOpenAIResponse,
261
+ safeParseResponse,
262
+ safeStreamIterate
263
+ };
264
+ //# sourceMappingURL=memSafety.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/utils/memSafety.ts"],
4
+ "sourcesContent": ["/**\n * Memory Safety Utilities for Minto\n *\n * Provides thread-safe token counting, response parsing with null guards,\n * and stream abort signal handling to prevent race conditions and memory leaks.\n *\n * Part of Phase 1.2: Memory Safety Fixes\n */\n\n/**\n * Thread-safe token counter for accumulating usage across streaming chunks.\n * Prevents race conditions when multiple chunks arrive concurrently.\n */\nexport class TokenCounter {\n private inputTokens = 0\n private outputTokens = 0\n private cacheReadTokens = 0\n private cacheCreationTokens = 0\n private reasoningTokens = 0\n\n /**\n * Add token usage from a streaming chunk or response.\n * Thread-safe accumulation.\n */\n add(usage: {\n input_tokens?: number\n output_tokens?: number\n cache_read_input_tokens?: number\n cache_creation_input_tokens?: number\n reasoning_tokens?: number\n // OpenAI format\n prompt_tokens?: number\n completion_tokens?: number\n }): void {\n // Anthropic format\n if (usage.input_tokens !== undefined) {\n this.inputTokens += usage.input_tokens\n }\n if (usage.output_tokens !== undefined) {\n this.outputTokens += usage.output_tokens\n }\n if (usage.cache_read_input_tokens !== undefined) {\n this.cacheReadTokens += usage.cache_read_input_tokens\n }\n if (usage.cache_creation_input_tokens !== undefined) {\n this.cacheCreationTokens += usage.cache_creation_input_tokens\n }\n if (usage.reasoning_tokens !== undefined) {\n this.reasoningTokens += usage.reasoning_tokens\n }\n\n // OpenAI format (fallback)\n if (usage.prompt_tokens !== undefined && usage.input_tokens === undefined) {\n this.inputTokens += usage.prompt_tokens\n }\n if (\n usage.completion_tokens !== undefined &&\n usage.output_tokens === undefined\n ) {\n this.outputTokens += usage.completion_tokens\n }\n }\n\n /**\n * Get accumulated totals.\n */\n getTotal(): {\n input_tokens: number\n output_tokens: number\n cache_read_input_tokens: number\n cache_creation_input_tokens: number\n reasoning_tokens: number\n } {\n return {\n input_tokens: this.inputTokens,\n output_tokens: this.outputTokens,\n cache_read_input_tokens: this.cacheReadTokens,\n cache_creation_input_tokens: this.cacheCreationTokens,\n reasoning_tokens: this.reasoningTokens,\n }\n }\n\n /**\n * Reset counters (useful for reusing counter instances).\n */\n reset(): void {\n this.inputTokens = 0\n this.outputTokens = 0\n this.cacheReadTokens = 0\n this.cacheCreationTokens = 0\n this.reasoningTokens = 0\n }\n}\n\n/**\n * Result type for safe response parsing.\n */\nexport interface ParsedResponse<T = unknown> {\n success: boolean\n data: T | null\n error: string | null\n}\n\n/**\n * Safe content block type.\n */\nexport interface ContentBlock {\n type: string\n text?: string\n id?: string\n name?: string\n input?: unknown\n thinking?: string\n signature?: string\n}\n\n/**\n * Safely parse an API response with comprehensive null checks.\n * Prevents crashes from malformed or empty responses.\n */\nexport function safeParseResponse(response: unknown): ParsedResponse<{\n content: ContentBlock[]\n usage: {\n input_tokens: number\n output_tokens: number\n cache_read_input_tokens?: number\n cache_creation_input_tokens?: number\n }\n stop_reason?: string\n id?: string\n model?: string\n}> {\n // Null/undefined check\n if (response === null || response === undefined) {\n return {\n success: false,\n data: null,\n error: 'Response is null or undefined',\n }\n }\n\n // Type check\n if (typeof response !== 'object') {\n return {\n success: false,\n data: null,\n error: `Invalid response type: ${typeof response}`,\n }\n }\n\n const res = response as Record<string, unknown>\n\n // Content array check\n let content: ContentBlock[] = []\n if (res.content !== undefined) {\n if (!Array.isArray(res.content)) {\n // Some APIs return content as string\n if (typeof res.content === 'string') {\n content = [{ type: 'text', text: res.content }]\n } else {\n return {\n success: false,\n data: null,\n error: 'Content is not an array or string',\n }\n }\n } else {\n content = res.content.map((block: unknown) => {\n if (block === null || block === undefined) {\n return { type: 'text', text: '' }\n }\n if (typeof block !== 'object') {\n return { type: 'text', text: String(block) }\n }\n return block as ContentBlock\n })\n }\n }\n\n // Usage parsing with defaults\n const rawUsage = (res.usage as Record<string, unknown>) || {}\n const usage = {\n input_tokens: safeNumber(rawUsage.input_tokens, 0),\n output_tokens: safeNumber(rawUsage.output_tokens, 0),\n cache_read_input_tokens: safeNumber(rawUsage.cache_read_input_tokens),\n cache_creation_input_tokens: safeNumber(\n rawUsage.cache_creation_input_tokens,\n ),\n }\n\n return {\n success: true,\n data: {\n content,\n usage,\n stop_reason: safeString(res.stop_reason),\n id: safeString(res.id),\n model: safeString(res.model),\n },\n error: null,\n }\n}\n\n/**\n * Safely parse OpenAI format response.\n */\nexport function safeParseOpenAIResponse(response: unknown): ParsedResponse<{\n content: string\n tool_calls: Array<{\n id: string\n type: string\n function: { name: string; arguments: string }\n }>\n usage: {\n prompt_tokens: number\n completion_tokens: number\n total_tokens: number\n }\n finish_reason?: string\n id?: string\n model?: string\n}> {\n if (response === null || response === undefined) {\n return {\n success: false,\n data: null,\n error: 'Response is null or undefined',\n }\n }\n\n if (typeof response !== 'object') {\n return {\n success: false,\n data: null,\n error: `Invalid response type: ${typeof response}`,\n }\n }\n\n const res = response as Record<string, unknown>\n\n // Get first choice\n const choices = res.choices as Array<Record<string, unknown>> | undefined\n const firstChoice = choices?.[0]\n const message = (firstChoice?.message as Record<string, unknown>) || {}\n\n // Parse tool calls\n const rawToolCalls = message.tool_calls as\n | Array<Record<string, unknown>>\n | undefined\n const tool_calls = (rawToolCalls || [])\n .map(tc => {\n if (!tc || typeof tc !== 'object') return null\n const func = tc.function as Record<string, unknown> | undefined\n return {\n id: safeString(tc.id) || '',\n type: safeString(tc.type) || 'function',\n function: {\n name: safeString(func?.name) || '',\n arguments: safeString(func?.arguments) || '{}',\n },\n }\n })\n .filter((tc): tc is NonNullable<typeof tc> => tc !== null)\n\n // Usage parsing\n const rawUsage = (res.usage as Record<string, unknown>) || {}\n const usage = {\n prompt_tokens: safeNumber(rawUsage.prompt_tokens, 0),\n completion_tokens: safeNumber(rawUsage.completion_tokens, 0),\n total_tokens: safeNumber(rawUsage.total_tokens, 0),\n }\n\n return {\n success: true,\n data: {\n content: safeString(message.content) || '',\n tool_calls,\n usage,\n finish_reason: safeString(firstChoice?.finish_reason),\n id: safeString(res.id),\n model: safeString(res.model),\n },\n error: null,\n }\n}\n\n/**\n * Safe number extraction with default value.\n */\nfunction safeNumber(value: unknown, defaultValue?: number): number {\n if (typeof value === 'number' && !isNaN(value)) {\n return value\n }\n if (typeof value === 'string') {\n const parsed = parseFloat(value)\n if (!isNaN(parsed)) {\n return parsed\n }\n }\n return defaultValue ?? 0\n}\n\n/**\n * Safe string extraction.\n */\nfunction safeString(value: unknown): string | undefined {\n if (typeof value === 'string') {\n return value\n }\n if (value !== null && value !== undefined) {\n return String(value)\n }\n return undefined\n}\n\n/**\n * Link an external AbortSignal to an AbortController.\n * Ensures proper cleanup when the external signal is aborted.\n */\nexport function linkAbortSignal(\n externalSignal: AbortSignal | undefined,\n controller: AbortController,\n): () => void {\n if (!externalSignal) {\n return () => {}\n }\n\n const onAbort = () => {\n controller.abort()\n }\n\n externalSignal.addEventListener('abort', onAbort)\n\n // Return cleanup function\n return () => {\n externalSignal.removeEventListener('abort', onAbort)\n }\n}\n\n/**\n * Create a linked abort controller that follows an external signal.\n */\nexport function createLinkedAbortController(externalSignal?: AbortSignal): {\n controller: AbortController\n cleanup: () => void\n} {\n const controller = new AbortController()\n\n // If already aborted, abort immediately\n if (externalSignal?.aborted) {\n controller.abort()\n return { controller, cleanup: () => {} }\n }\n\n const cleanup = linkAbortSignal(externalSignal, controller)\n\n return { controller, cleanup }\n}\n\n/**\n * Safe stream iteration with proper abort handling.\n * Ensures resources are cleaned up even if iteration is interrupted.\n */\nexport async function* safeStreamIterate<T>(\n stream: AsyncIterable<T>,\n signal?: AbortSignal,\n): AsyncGenerator<T, void, unknown> {\n // Check if already aborted before starting\n if (signal?.aborted) {\n return\n }\n\n const iterator = stream[Symbol.asyncIterator]()\n\n try {\n while (true) {\n // Check abort status before each iteration\n if (signal?.aborted) {\n break\n }\n\n const result = await iterator.next()\n\n if (result.done) {\n break\n }\n\n // Check abort status after receiving value\n if (signal?.aborted) {\n break\n }\n\n yield result.value\n }\n } finally {\n // Ensure cleanup by calling return on iterator if it exists\n if (iterator.return) {\n await iterator.return()\n }\n }\n}\n\n/**\n * Safely extract text content from content blocks.\n */\nexport function extractTextContent(content: ContentBlock[]): string {\n if (!Array.isArray(content)) {\n return ''\n }\n\n return content\n .filter(block => block?.type === 'text' && typeof block.text === 'string')\n .map(block => block.text)\n .join('\\n')\n}\n\n/**\n * Safely extract tool use blocks from content.\n */\nexport function extractToolUses(content: ContentBlock[]): Array<{\n id: string\n name: string\n input: unknown\n}> {\n if (!Array.isArray(content)) {\n return []\n }\n\n return content\n .filter(block => block?.type === 'tool_use')\n .map(block => ({\n id: block.id || '',\n name: block.name || '',\n input: block.input || {},\n }))\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,274 @@
1
+ import { TaskGroupHandler } from "./groupHandlers/taskHandler.js";
2
+ import { ParallelTasksHandler } from "./groupHandlers/parallelTasksHandler.js";
3
+ import { getAgentIdByToolUseId, getAgentTranscript } from "./agentTranscripts.js";
4
+ class MessageGroupManager {
5
+ groups = /* @__PURE__ */ new Map();
6
+ toolUseToGroup = /* @__PURE__ */ new Map();
7
+ messageToGroup = /* @__PURE__ */ new Map();
8
+ typeHandlers = /* @__PURE__ */ new Map();
9
+ messageIndexMap = /* @__PURE__ */ new Map();
10
+ idCounter = 0;
11
+ constructor() {
12
+ this.registerHandler(new TaskGroupHandler());
13
+ this.registerHandler(new ParallelTasksHandler());
14
+ }
15
+ /**
16
+ * Register a group type handler (supports custom extensions)
17
+ */
18
+ registerHandler(handler) {
19
+ this.typeHandlers.set(handler.type, handler);
20
+ }
21
+ /**
22
+ * Identify all groups from message list
23
+ */
24
+ identifyGroups(messages) {
25
+ this.reset();
26
+ messages.forEach((msg, idx) => {
27
+ this.messageIndexMap.set(msg.uuid, idx);
28
+ });
29
+ const processingOrder = ["parallel-tasks", "task"];
30
+ const parallelGroupUuids = /* @__PURE__ */ new Set();
31
+ for (const type of processingOrder) {
32
+ const handler = this.typeHandlers.get(type);
33
+ if (!handler) continue;
34
+ const identified = handler.identify(messages);
35
+ for (const identifiedGroup of identified) {
36
+ if (type === "task") {
37
+ const msgUuid = identifiedGroup.messageUuids[0];
38
+ if (parallelGroupUuids.has(msgUuid)) {
39
+ continue;
40
+ }
41
+ }
42
+ if (type === "parallel-tasks") {
43
+ for (const uuid of identifiedGroup.messageUuids) {
44
+ parallelGroupUuids.add(uuid);
45
+ }
46
+ }
47
+ this.createGroup(identifiedGroup, handler, messages);
48
+ }
49
+ }
50
+ }
51
+ /**
52
+ * Create a group and compute initial state
53
+ */
54
+ createGroup(identified, handler, messages) {
55
+ const groupId = this.generateGroupId(identified.type);
56
+ const group = {
57
+ id: groupId,
58
+ type: identified.type,
59
+ childIds: identified.childIds || [],
60
+ messageUuids: identified.messageUuids,
61
+ status: "pending",
62
+ metadata: identified.metadata,
63
+ // V1+ new fields: will be computed
64
+ anchor: { anchorMessageUuid: "", anchorStrategy: "first" },
65
+ resolution: {
66
+ isSelfResolved: false,
67
+ isNestedResolved: true,
68
+ isFullyResolved: false,
69
+ unresolvedToolUseIds: []
70
+ }
71
+ };
72
+ group.anchor = handler.computeAnchor(group, messages);
73
+ this.groups.set(group.id, group);
74
+ for (const uuid of group.messageUuids) {
75
+ this.messageToGroup.set(uuid, group.id);
76
+ }
77
+ if (identified.metadata.toolUseId) {
78
+ this.toolUseToGroup.set(identified.metadata.toolUseId, group.id);
79
+ }
80
+ if (identified.metadata.siblingToolUseIds) {
81
+ for (const toolUseId of identified.metadata.siblingToolUseIds) {
82
+ this.toolUseToGroup.set(toolUseId, group.id);
83
+ }
84
+ }
85
+ return group;
86
+ }
87
+ /**
88
+ * Update resolution states for all groups
89
+ * This is the generalized version of V3's nested checking
90
+ */
91
+ updateResolutionStates(unresolvedToolUseIDs, inProgressToolUseIDs) {
92
+ for (const group of this.groups.values()) {
93
+ const handler = this.typeHandlers.get(group.type);
94
+ if (handler) {
95
+ group.resolution = handler.computeResolution(
96
+ group,
97
+ unresolvedToolUseIDs
98
+ );
99
+ }
100
+ }
101
+ for (const group of this.groups.values()) {
102
+ if (group.type === "parallel-tasks") {
103
+ this.updateParallelGroupResolution(group, unresolvedToolUseIDs);
104
+ }
105
+ }
106
+ for (const group of this.groups.values()) {
107
+ group.status = this.computeGroupStatus(group, inProgressToolUseIDs);
108
+ }
109
+ }
110
+ /**
111
+ * Update parallel group resolution by checking all member tasks
112
+ */
113
+ updateParallelGroupResolution(group, unresolvedToolUseIDs) {
114
+ const memberIds = group.metadata.siblingToolUseIds || [];
115
+ let allNestedResolved = true;
116
+ const allUnresolvedIds = [
117
+ ...group.resolution.unresolvedToolUseIds
118
+ ];
119
+ for (const toolUseId of memberIds) {
120
+ const agentId = getAgentIdByToolUseId(toolUseId);
121
+ if (agentId) {
122
+ const nestedResult = this.checkNestedTasksResolution(
123
+ agentId,
124
+ unresolvedToolUseIDs
125
+ );
126
+ if (nestedResult.hasUnresolved) {
127
+ allNestedResolved = false;
128
+ allUnresolvedIds.push(...nestedResult.unresolvedIds);
129
+ }
130
+ }
131
+ }
132
+ group.resolution.isNestedResolved = allNestedResolved;
133
+ group.resolution.isFullyResolved = group.resolution.isSelfResolved && allNestedResolved;
134
+ group.resolution.unresolvedToolUseIds = allUnresolvedIds;
135
+ }
136
+ /**
137
+ * Recursively check if all nested tasks are resolved
138
+ */
139
+ checkNestedTasksResolution(agentId, unresolvedToolUseIDs) {
140
+ const transcript = getAgentTranscript(agentId);
141
+ if (!transcript) {
142
+ return { hasUnresolved: false, unresolvedIds: [] };
143
+ }
144
+ const unresolvedIds = [];
145
+ for (const message of transcript.messages) {
146
+ if (message.type === "assistant") {
147
+ const content = message.message.content;
148
+ if (!content || !Array.isArray(content)) continue;
149
+ for (const block of content) {
150
+ if (block.type === "tool_use" && block.name === "Task") {
151
+ if (unresolvedToolUseIDs.has(block.id)) {
152
+ unresolvedIds.push(block.id);
153
+ }
154
+ const nestedAgentId = getAgentIdByToolUseId(block.id);
155
+ if (nestedAgentId) {
156
+ const nested = this.checkNestedTasksResolution(
157
+ nestedAgentId,
158
+ unresolvedToolUseIDs
159
+ );
160
+ unresolvedIds.push(...nested.unresolvedIds);
161
+ }
162
+ }
163
+ }
164
+ }
165
+ }
166
+ return {
167
+ hasUnresolved: unresolvedIds.length > 0,
168
+ unresolvedIds
169
+ };
170
+ }
171
+ /**
172
+ * Check if a group should be rendered as Static
173
+ * V1+ core: only fully resolved groups can be Static
174
+ */
175
+ shouldGroupBeStatic(group) {
176
+ return group.resolution.isFullyResolved;
177
+ }
178
+ /**
179
+ * Get ordered root groups (groups without parent)
180
+ * Sorted by anchor message position
181
+ */
182
+ getOrderedRootGroups() {
183
+ const roots = Array.from(this.groups.values()).filter((g) => !g.parentId);
184
+ return roots.sort((a, b) => {
185
+ const aIndex = this.messageIndexMap.get(a.anchor.anchorMessageUuid) ?? 0;
186
+ const bIndex = this.messageIndexMap.get(b.anchor.anchorMessageUuid) ?? 0;
187
+ return aIndex - bIndex;
188
+ });
189
+ }
190
+ /**
191
+ * Get all tool use IDs associated with a group
192
+ */
193
+ getGroupToolUseIds(group) {
194
+ const ids = [];
195
+ if (group.metadata.toolUseId) {
196
+ ids.push(group.metadata.toolUseId);
197
+ }
198
+ if (group.metadata.siblingToolUseIds) {
199
+ ids.push(...group.metadata.siblingToolUseIds);
200
+ }
201
+ return ids;
202
+ }
203
+ /**
204
+ * Compute group status based on resolution and progress
205
+ *
206
+ * IMPORTANT: For parallel tasks, we must check inProgressToolUseIDs BEFORE
207
+ * checking isFullyResolved, because tool uses may still be running even if
208
+ * they haven't received results yet. The resolution check only tells us if
209
+ * tool_results exist, not if agents are still running.
210
+ */
211
+ computeGroupStatus(group, inProgressToolUseIDs) {
212
+ const toolUseIds = this.getGroupToolUseIds(group);
213
+ if (toolUseIds.some((id) => inProgressToolUseIDs.has(id))) {
214
+ return "running";
215
+ }
216
+ if (group.resolution.isFullyResolved) {
217
+ return "completed";
218
+ }
219
+ return "pending";
220
+ }
221
+ generateGroupId(type) {
222
+ this.idCounter++;
223
+ return `${type}-${Date.now()}-${this.idCounter}`;
224
+ }
225
+ reset() {
226
+ this.groups.clear();
227
+ this.toolUseToGroup.clear();
228
+ this.messageToGroup.clear();
229
+ this.messageIndexMap.clear();
230
+ this.idCounter = 0;
231
+ }
232
+ getGroup(id) {
233
+ return this.groups.get(id);
234
+ }
235
+ getGroupByToolUseId(toolUseId) {
236
+ const groupId = this.toolUseToGroup.get(toolUseId);
237
+ return groupId ? this.groups.get(groupId) : void 0;
238
+ }
239
+ getGroupByMessageUuid(uuid) {
240
+ const groupId = this.messageToGroup.get(uuid);
241
+ return groupId ? this.groups.get(groupId) : void 0;
242
+ }
243
+ getAllGroups() {
244
+ return Array.from(this.groups.values());
245
+ }
246
+ /**
247
+ * Check if a toolUseId is the anchor of its group
248
+ */
249
+ isGroupAnchor(toolUseId) {
250
+ const group = this.getGroupByToolUseId(toolUseId);
251
+ if (!group) return false;
252
+ if (group.type === "parallel-tasks") {
253
+ const siblings = group.metadata.siblingToolUseIds;
254
+ return siblings?.[0] === toolUseId;
255
+ }
256
+ return group.metadata.toolUseId === toolUseId;
257
+ }
258
+ }
259
+ let globalManager = null;
260
+ function getMessageGroupManager() {
261
+ if (!globalManager) {
262
+ globalManager = new MessageGroupManager();
263
+ }
264
+ return globalManager;
265
+ }
266
+ function resetMessageGroupManager() {
267
+ globalManager = null;
268
+ }
269
+ export {
270
+ MessageGroupManager,
271
+ getMessageGroupManager,
272
+ resetMessageGroupManager
273
+ };
274
+ //# sourceMappingURL=messageGroupManager.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/utils/messageGroupManager.ts"],
4
+ "sourcesContent": ["/**\n * V1+ Message Group Manager\n *\n * Unified manager combining V1's generality with V3's concrete solutions:\n * 1. Plugin-based type handlers for extensibility\n * 2. Unified recursive state computation\n * 3. Position anchoring mechanism\n */\n\nimport type { NormalizedMessage } from '@utils/messages'\nimport type {\n MessageGroup,\n MessageGroupType,\n IdentifiedGroup,\n PositionAnchor,\n ResolutionState,\n} from '@minto-types/messageGroup'\nimport type { GroupTypeHandler } from './groupHandlers/types'\nimport { TaskGroupHandler } from './groupHandlers/taskHandler'\nimport { ParallelTasksHandler } from './groupHandlers/parallelTasksHandler'\nimport { getAgentIdByToolUseId, getAgentTranscript } from './agentTranscripts'\n\n/**\n * V1+ Message Group Manager\n *\n * Features:\n * 1. Plugin-based type handlers\n * 2. Unified recursive state computation\n * 3. Position anchoring mechanism\n */\nexport class MessageGroupManager {\n private groups: Map<string, MessageGroup> = new Map()\n private toolUseToGroup: Map<string, string> = new Map()\n private messageToGroup: Map<string, string> = new Map()\n private typeHandlers: Map<MessageGroupType, GroupTypeHandler> = new Map()\n private messageIndexMap: Map<string, number> = new Map()\n private idCounter = 0\n\n constructor() {\n // Register built-in type handlers\n this.registerHandler(new TaskGroupHandler())\n this.registerHandler(new ParallelTasksHandler())\n }\n\n /**\n * Register a group type handler (supports custom extensions)\n */\n registerHandler(handler: GroupTypeHandler): void {\n this.typeHandlers.set(handler.type, handler)\n }\n\n /**\n * Identify all groups from message list\n */\n identifyGroups(messages: NormalizedMessage[]): void {\n this.reset()\n\n // Build message index map for sorting\n messages.forEach((msg, idx) => {\n this.messageIndexMap.set(msg.uuid, idx)\n })\n\n // Process in dependency order: parallel-tasks first (to exclude from task handler)\n // Then task handler for remaining single tasks\n const processingOrder: MessageGroupType[] = ['parallel-tasks', 'task']\n\n // Track UUIDs that are part of parallel groups\n const parallelGroupUuids = new Set<string>()\n\n for (const type of processingOrder) {\n const handler = this.typeHandlers.get(type)\n if (!handler) continue\n\n const identified = handler.identify(messages)\n\n for (const identifiedGroup of identified) {\n // For task groups, skip if the message is already in a parallel group\n if (type === 'task') {\n const msgUuid = identifiedGroup.messageUuids[0]\n if (parallelGroupUuids.has(msgUuid)) {\n continue\n }\n }\n\n // Track parallel group UUIDs\n if (type === 'parallel-tasks') {\n for (const uuid of identifiedGroup.messageUuids) {\n parallelGroupUuids.add(uuid)\n }\n }\n\n this.createGroup(identifiedGroup, handler, messages)\n }\n }\n }\n\n /**\n * Create a group and compute initial state\n */\n private createGroup(\n identified: IdentifiedGroup,\n handler: GroupTypeHandler,\n messages: NormalizedMessage[],\n ): MessageGroup {\n const groupId = this.generateGroupId(identified.type)\n\n const group: MessageGroup = {\n id: groupId,\n type: identified.type,\n childIds: identified.childIds || [],\n messageUuids: identified.messageUuids,\n status: 'pending',\n metadata: identified.metadata,\n // V1+ new fields: will be computed\n anchor: { anchorMessageUuid: '', anchorStrategy: 'first' },\n resolution: {\n isSelfResolved: false,\n isNestedResolved: true,\n isFullyResolved: false,\n unresolvedToolUseIds: [],\n },\n }\n\n // Compute anchor\n group.anchor = handler.computeAnchor(group, messages)\n\n // Register mappings\n this.groups.set(group.id, group)\n for (const uuid of group.messageUuids) {\n this.messageToGroup.set(uuid, group.id)\n }\n if (identified.metadata.toolUseId) {\n this.toolUseToGroup.set(identified.metadata.toolUseId, group.id)\n }\n // Also register sibling tool use IDs for parallel groups\n if (identified.metadata.siblingToolUseIds) {\n for (const toolUseId of identified.metadata.siblingToolUseIds) {\n this.toolUseToGroup.set(toolUseId, group.id)\n }\n }\n\n return group\n }\n\n /**\n * Update resolution states for all groups\n * This is the generalized version of V3's nested checking\n */\n updateResolutionStates(\n unresolvedToolUseIDs: Set<string>,\n inProgressToolUseIDs: Set<string>,\n ): void {\n // First pass: update all groups' resolution using their handlers\n for (const group of this.groups.values()) {\n const handler = this.typeHandlers.get(group.type)\n if (handler) {\n group.resolution = handler.computeResolution(\n group,\n unresolvedToolUseIDs,\n )\n }\n }\n\n // Second pass: for parallel groups, aggregate child resolutions\n for (const group of this.groups.values()) {\n if (group.type === 'parallel-tasks') {\n this.updateParallelGroupResolution(group, unresolvedToolUseIDs)\n }\n }\n\n // Third pass: update status based on resolution\n for (const group of this.groups.values()) {\n group.status = this.computeGroupStatus(group, inProgressToolUseIDs)\n }\n }\n\n /**\n * Update parallel group resolution by checking all member tasks\n */\n private updateParallelGroupResolution(\n group: MessageGroup,\n unresolvedToolUseIDs: Set<string>,\n ): void {\n const memberIds = (group.metadata.siblingToolUseIds as string[]) || []\n\n // Check each member's nested resolution\n let allNestedResolved = true\n const allUnresolvedIds: string[] = [\n ...group.resolution.unresolvedToolUseIds,\n ]\n\n for (const toolUseId of memberIds) {\n const agentId = getAgentIdByToolUseId(toolUseId)\n if (agentId) {\n const nestedResult = this.checkNestedTasksResolution(\n agentId,\n unresolvedToolUseIDs,\n )\n if (nestedResult.hasUnresolved) {\n allNestedResolved = false\n allUnresolvedIds.push(...nestedResult.unresolvedIds)\n }\n }\n }\n\n group.resolution.isNestedResolved = allNestedResolved\n group.resolution.isFullyResolved =\n group.resolution.isSelfResolved && allNestedResolved\n group.resolution.unresolvedToolUseIds = allUnresolvedIds\n }\n\n /**\n * Recursively check if all nested tasks are resolved\n */\n private checkNestedTasksResolution(\n agentId: string,\n unresolvedToolUseIDs: Set<string>,\n ): { hasUnresolved: boolean; unresolvedIds: string[] } {\n const transcript = getAgentTranscript(agentId)\n if (!transcript) {\n return { hasUnresolved: false, unresolvedIds: [] }\n }\n\n const unresolvedIds: string[] = []\n\n for (const message of transcript.messages) {\n if (message.type === 'assistant') {\n const content = message.message.content\n if (!content || !Array.isArray(content)) continue\n\n for (const block of content) {\n if (block.type === 'tool_use' && block.name === 'Task') {\n if (unresolvedToolUseIDs.has(block.id)) {\n unresolvedIds.push(block.id)\n }\n\n const nestedAgentId = getAgentIdByToolUseId(block.id)\n if (nestedAgentId) {\n const nested = this.checkNestedTasksResolution(\n nestedAgentId,\n unresolvedToolUseIDs,\n )\n unresolvedIds.push(...nested.unresolvedIds)\n }\n }\n }\n }\n }\n\n return {\n hasUnresolved: unresolvedIds.length > 0,\n unresolvedIds,\n }\n }\n\n /**\n * Check if a group should be rendered as Static\n * V1+ core: only fully resolved groups can be Static\n */\n shouldGroupBeStatic(group: MessageGroup): boolean {\n return group.resolution.isFullyResolved\n }\n\n /**\n * Get ordered root groups (groups without parent)\n * Sorted by anchor message position\n */\n getOrderedRootGroups(): MessageGroup[] {\n const roots = Array.from(this.groups.values()).filter(g => !g.parentId)\n return roots.sort((a, b) => {\n const aIndex = this.messageIndexMap.get(a.anchor.anchorMessageUuid) ?? 0\n const bIndex = this.messageIndexMap.get(b.anchor.anchorMessageUuid) ?? 0\n return aIndex - bIndex\n })\n }\n\n /**\n * Get all tool use IDs associated with a group\n */\n getGroupToolUseIds(group: MessageGroup): string[] {\n const ids: string[] = []\n if (group.metadata.toolUseId) {\n ids.push(group.metadata.toolUseId)\n }\n if (group.metadata.siblingToolUseIds) {\n ids.push(...group.metadata.siblingToolUseIds)\n }\n return ids\n }\n\n /**\n * Compute group status based on resolution and progress\n *\n * IMPORTANT: For parallel tasks, we must check inProgressToolUseIDs BEFORE\n * checking isFullyResolved, because tool uses may still be running even if\n * they haven't received results yet. The resolution check only tells us if\n * tool_results exist, not if agents are still running.\n */\n private computeGroupStatus(\n group: MessageGroup,\n inProgressToolUseIDs: Set<string>,\n ): 'pending' | 'running' | 'completed' | 'failed' {\n const toolUseIds = this.getGroupToolUseIds(group)\n\n // Check running status FIRST - if any toolUseId is in progress, the group is running\n // This is critical for parallel tasks where agents may still be running\n if (toolUseIds.some(id => inProgressToolUseIDs.has(id))) {\n return 'running'\n }\n\n // Only after confirming nothing is running, check resolution\n if (group.resolution.isFullyResolved) {\n return 'completed'\n }\n\n return 'pending'\n }\n\n private generateGroupId(type: MessageGroupType): string {\n this.idCounter++\n return `${type}-${Date.now()}-${this.idCounter}`\n }\n\n reset(): void {\n this.groups.clear()\n this.toolUseToGroup.clear()\n this.messageToGroup.clear()\n this.messageIndexMap.clear()\n this.idCounter = 0\n }\n\n getGroup(id: string): MessageGroup | undefined {\n return this.groups.get(id)\n }\n\n getGroupByToolUseId(toolUseId: string): MessageGroup | undefined {\n const groupId = this.toolUseToGroup.get(toolUseId)\n return groupId ? this.groups.get(groupId) : undefined\n }\n\n getGroupByMessageUuid(uuid: string): MessageGroup | undefined {\n const groupId = this.messageToGroup.get(uuid)\n return groupId ? this.groups.get(groupId) : undefined\n }\n\n getAllGroups(): MessageGroup[] {\n return Array.from(this.groups.values())\n }\n\n /**\n * Check if a toolUseId is the anchor of its group\n */\n isGroupAnchor(toolUseId: string): boolean {\n const group = this.getGroupByToolUseId(toolUseId)\n if (!group) return false\n\n // For parallel groups, check if this is the first sibling\n if (group.type === 'parallel-tasks') {\n const siblings = group.metadata.siblingToolUseIds as string[] | undefined\n return siblings?.[0] === toolUseId\n }\n\n // For single task groups, the toolUseId is always the anchor\n return group.metadata.toolUseId === toolUseId\n }\n}\n\n// Singleton instance for global access\nlet globalManager: MessageGroupManager | null = null\n\nexport function getMessageGroupManager(): MessageGroupManager {\n if (!globalManager) {\n globalManager = new MessageGroupManager()\n }\n return globalManager\n}\n\nexport function resetMessageGroupManager(): void {\n globalManager = null\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -1,4 +1,4 @@
1
- import { randomUUID } from "crypto";
1
+ import { createHash, randomUUID } from "crypto";
2
2
  import { getCommand, hasCommand } from "../commands.js";
3
3
  import { MalformedCommandError } from "./errors.js";
4
4
  import { logError } from "./log.js";
@@ -413,20 +413,29 @@ function isNotEmptyMessage(message) {
413
413
  }
414
414
  return message.message.content[0].text.trim().length > 0 && message.message.content[0].text !== NO_CONTENT_MESSAGE && message.message.content[0].text !== INTERRUPT_MESSAGE_FOR_TOOL_USE;
415
415
  }
416
+ function deterministicUUID(seed) {
417
+ const hash = createHash("sha256").update(seed).digest("hex");
418
+ return `${hash.slice(0, 8)}-${hash.slice(8, 12)}-4${hash.slice(13, 16)}-${(parseInt(hash.slice(16, 17), 16) & 3 | 8).toString(16)}${hash.slice(17, 20)}-${hash.slice(20, 32)}`;
419
+ }
416
420
  function normalizeMessages(messages) {
417
- return messages.flatMap((message) => {
421
+ return messages.flatMap((message, messageIndex) => {
418
422
  if (message.type === "progress") {
419
423
  return [message];
420
424
  }
421
425
  if (typeof message.message.content === "string") {
422
426
  return [message];
423
427
  }
424
- return message.message.content.map((_) => {
428
+ return message.message.content.map((_, contentIndex) => {
425
429
  switch (message.type) {
426
430
  case "assistant":
431
+ const baseUuid = message.uuid || `msg-${messageIndex}`;
432
+ const contentId = _.type === "tool_use" ? _.id || contentIndex : contentIndex;
433
+ const stableUuid = deterministicUUID(`${baseUuid}-${contentId}`);
427
434
  return {
428
435
  type: "assistant",
429
- uuid: randomUUID(),
436
+ uuid: stableUuid,
437
+ // Preserve original UUID for identifying parallel tool calls from same message
438
+ originalUuid: message.uuid,
430
439
  message: {
431
440
  ...message.message,
432
441
  content: [_]