@within-7/minto 0.1.6 → 0.2.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 (487) 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 +52 -26
  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 +84 -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 +156 -0
  22. package/dist/commands/export.js.map +7 -0
  23. package/dist/commands/mcp-interactive.js +21 -12
  24. package/dist/commands/mcp-interactive.js.map +2 -2
  25. package/dist/commands/model.js +6 -5
  26. package/dist/commands/model.js.map +2 -2
  27. package/dist/commands/permissions.js +86 -0
  28. package/dist/commands/permissions.js.map +7 -0
  29. package/dist/commands/quit.js +3 -1
  30. package/dist/commands/quit.js.map +2 -2
  31. package/dist/commands/sandbox.js +104 -0
  32. package/dist/commands/sandbox.js.map +7 -0
  33. package/dist/commands/status.js +58 -0
  34. package/dist/commands/status.js.map +7 -0
  35. package/dist/commands/tasks.js +108 -0
  36. package/dist/commands/tasks.js.map +7 -0
  37. package/dist/commands/todos.js +123 -0
  38. package/dist/commands/todos.js.map +7 -0
  39. package/dist/commands.js +20 -2
  40. package/dist/commands.js.map +2 -2
  41. package/dist/components/AgentThinkingBlock.js +10 -18
  42. package/dist/components/AgentThinkingBlock.js.map +2 -2
  43. package/dist/components/BackgroundTasksPanel.js +78 -29
  44. package/dist/components/BackgroundTasksPanel.js.map +2 -2
  45. package/dist/components/BashStreamingProgress.js +24 -0
  46. package/dist/components/BashStreamingProgress.js.map +7 -0
  47. package/dist/components/CollapsibleHint.js +14 -0
  48. package/dist/components/CollapsibleHint.js.map +7 -0
  49. package/dist/components/FileEditToolUpdatedMessage.js +1 -1
  50. package/dist/components/FileEditToolUpdatedMessage.js.map +2 -2
  51. package/dist/components/HotkeyHelpPanel.js +137 -0
  52. package/dist/components/HotkeyHelpPanel.js.map +7 -0
  53. package/dist/components/Logo.js +5 -5
  54. package/dist/components/Logo.js.map +2 -2
  55. package/dist/components/Message.js +23 -7
  56. package/dist/components/Message.js.map +3 -3
  57. package/dist/components/ModelConfig.js +16 -3
  58. package/dist/components/ModelConfig.js.map +2 -2
  59. package/dist/components/ModelListManager.js +3 -3
  60. package/dist/components/ModelListManager.js.map +2 -2
  61. package/dist/components/ModelSelector/ModelSelector.js +1 -1
  62. package/dist/components/Onboarding.js +19 -14
  63. package/dist/components/Onboarding.js.map +2 -2
  64. package/dist/components/ProgressBar.js +74 -0
  65. package/dist/components/ProgressBar.js.map +7 -0
  66. package/dist/components/PromptInput.js +156 -46
  67. package/dist/components/PromptInput.js.map +2 -2
  68. package/dist/components/RequestStatusIndicator.js +194 -0
  69. package/dist/components/RequestStatusIndicator.js.map +7 -0
  70. package/dist/components/Spinner.js +92 -27
  71. package/dist/components/Spinner.js.map +2 -2
  72. package/dist/components/SpinnerSymbol.js +21 -27
  73. package/dist/components/SpinnerSymbol.js.map +2 -2
  74. package/dist/components/StreamingBashOutput.js +9 -8
  75. package/dist/components/StreamingBashOutput.js.map +2 -2
  76. package/dist/components/SubagentBlock.js +1 -1
  77. package/dist/components/SubagentBlock.js.map +1 -1
  78. package/dist/components/SubagentProgress.js +10 -11
  79. package/dist/components/SubagentProgress.js.map +2 -2
  80. package/dist/components/TaskCard.js +16 -13
  81. package/dist/components/TaskCard.js.map +2 -2
  82. package/dist/components/TodoChangeBlock.js +1 -1
  83. package/dist/components/TodoChangeBlock.js.map +2 -2
  84. package/dist/components/TodoPanel.js +120 -29
  85. package/dist/components/TodoPanel.js.map +3 -3
  86. package/dist/components/TokenCounter.js +74 -0
  87. package/dist/components/TokenCounter.js.map +7 -0
  88. package/dist/components/TokenWarning.js +2 -1
  89. package/dist/components/TokenWarning.js.map +2 -2
  90. package/dist/components/TreeConnector.js +25 -0
  91. package/dist/components/TreeConnector.js.map +7 -0
  92. package/dist/components/TurnCompletionIndicator.js +18 -0
  93. package/dist/components/TurnCompletionIndicator.js.map +7 -0
  94. package/dist/components/messages/AssistantTextMessage.js +5 -2
  95. package/dist/components/messages/AssistantTextMessage.js.map +2 -2
  96. package/dist/components/messages/AssistantThinkingMessage.js +18 -3
  97. package/dist/components/messages/AssistantThinkingMessage.js.map +2 -2
  98. package/dist/components/messages/AssistantToolUseMessage.js +11 -8
  99. package/dist/components/messages/AssistantToolUseMessage.js.map +2 -2
  100. package/dist/components/messages/GroupRenderer.js +53 -0
  101. package/dist/components/messages/GroupRenderer.js.map +7 -0
  102. package/dist/components/messages/NestedTasksPreview.js +12 -0
  103. package/dist/components/messages/NestedTasksPreview.js.map +7 -0
  104. package/dist/components/messages/ParallelTasksGroupView.js +92 -0
  105. package/dist/components/messages/ParallelTasksGroupView.js.map +7 -0
  106. package/dist/components/messages/TaskInModuleView.js +198 -0
  107. package/dist/components/messages/TaskInModuleView.js.map +7 -0
  108. package/dist/components/messages/TaskOutputContent.js +53 -0
  109. package/dist/components/messages/TaskOutputContent.js.map +7 -0
  110. package/dist/components/messages/UserPromptMessage.js +1 -1
  111. package/dist/components/messages/UserPromptMessage.js.map +2 -2
  112. package/dist/components/messages/UserToolResultMessage/UserToolSuccessMessage.js +2 -3
  113. package/dist/components/messages/UserToolResultMessage/UserToolSuccessMessage.js.map +2 -2
  114. package/dist/components/permissions/FallbackPermissionRequest.js +4 -4
  115. package/dist/components/permissions/FallbackPermissionRequest.js.map +2 -2
  116. package/dist/components/permissions/FilesystemPermissionRequest/FilesystemPermissionRequest.js +4 -4
  117. package/dist/components/permissions/FilesystemPermissionRequest/FilesystemPermissionRequest.js.map +2 -2
  118. package/dist/constants/colors.js +48 -0
  119. package/dist/constants/colors.js.map +2 -2
  120. package/dist/constants/formatRules.js +102 -0
  121. package/dist/constants/formatRules.js.map +7 -0
  122. package/dist/constants/prompts.js +12 -34
  123. package/dist/constants/prompts.js.map +2 -2
  124. package/dist/constants/symbols.js +64 -6
  125. package/dist/constants/symbols.js.map +2 -2
  126. package/dist/constants/timing.js +5 -0
  127. package/dist/constants/timing.js.map +2 -2
  128. package/dist/core/config/defaults.js +84 -0
  129. package/dist/core/config/defaults.js.map +7 -0
  130. package/dist/core/config/index.js +111 -0
  131. package/dist/core/config/index.js.map +7 -0
  132. package/dist/core/config/loader.js +221 -0
  133. package/dist/core/config/loader.js.map +7 -0
  134. package/dist/core/config/migrations.js +128 -0
  135. package/dist/core/config/migrations.js.map +7 -0
  136. package/dist/core/config/schema.js +178 -0
  137. package/dist/core/config/schema.js.map +7 -0
  138. package/dist/core/costTracker.js +138 -0
  139. package/dist/core/costTracker.js.map +7 -0
  140. package/dist/core/index.js +5 -0
  141. package/dist/core/index.js.map +7 -0
  142. package/dist/core/permissions/auditLog.js +204 -0
  143. package/dist/core/permissions/auditLog.js.map +7 -0
  144. package/dist/core/permissions/engine/index.js +3 -0
  145. package/dist/core/permissions/engine/index.js.map +7 -0
  146. package/dist/core/permissions/engine/permissionEngine.js +106 -0
  147. package/dist/core/permissions/engine/permissionEngine.js.map +7 -0
  148. package/dist/core/permissions/engine/types.js +1 -0
  149. package/dist/core/permissions/engine/types.js.map +7 -0
  150. package/dist/core/permissions/index.js +84 -0
  151. package/dist/core/permissions/index.js.map +7 -0
  152. package/dist/core/permissions/ruleEngine.js +259 -0
  153. package/dist/core/permissions/ruleEngine.js.map +7 -0
  154. package/dist/core/permissions/rules/allowedToolsRule.js +62 -0
  155. package/dist/core/permissions/rules/allowedToolsRule.js.map +7 -0
  156. package/dist/core/permissions/rules/autoEscalationRule.js +291 -0
  157. package/dist/core/permissions/rules/autoEscalationRule.js.map +7 -0
  158. package/dist/core/permissions/rules/index.js +46 -0
  159. package/dist/core/permissions/rules/index.js.map +7 -0
  160. package/dist/core/permissions/rules/planModeRule.js +55 -0
  161. package/dist/core/permissions/rules/planModeRule.js.map +7 -0
  162. package/dist/core/permissions/rules/projectBoundaryRule.js +168 -0
  163. package/dist/core/permissions/rules/projectBoundaryRule.js.map +7 -0
  164. package/dist/core/permissions/rules/safeModeRule.js +65 -0
  165. package/dist/core/permissions/rules/safeModeRule.js.map +7 -0
  166. package/dist/core/permissions/rules/sensitivePathsRule.js +340 -0
  167. package/dist/core/permissions/rules/sensitivePathsRule.js.map +7 -0
  168. package/dist/core/permissions/types.js +127 -0
  169. package/dist/core/permissions/types.js.map +7 -0
  170. package/dist/core/tools/executor.js +143 -0
  171. package/dist/core/tools/executor.js.map +7 -0
  172. package/dist/core/tools/index.js +15 -0
  173. package/dist/core/tools/index.js.map +7 -0
  174. package/dist/core/tools/registry.js +183 -0
  175. package/dist/core/tools/registry.js.map +7 -0
  176. package/dist/core/tools/types.js +1 -0
  177. package/dist/core/tools/types.js.map +7 -0
  178. package/dist/cost-tracker.js +23 -15
  179. package/dist/cost-tracker.js.map +2 -2
  180. package/dist/entrypoints/cli.js +43 -43
  181. package/dist/entrypoints/cli.js.map +2 -2
  182. package/dist/entrypoints/mcp.js +12 -4
  183. package/dist/entrypoints/mcp.js.map +2 -2
  184. package/dist/history.js +14 -3
  185. package/dist/history.js.map +2 -2
  186. package/dist/hooks/useAgentTranscripts.js +116 -0
  187. package/dist/hooks/useAgentTranscripts.js.map +7 -0
  188. package/dist/hooks/useAnimationSync.js +53 -0
  189. package/dist/hooks/useAnimationSync.js.map +7 -0
  190. package/dist/hooks/useArrowKeyHistory.js +4 -2
  191. package/dist/hooks/useArrowKeyHistory.js.map +2 -2
  192. package/dist/hooks/useCanUseTool.js +3 -1
  193. package/dist/hooks/useCanUseTool.js.map +2 -2
  194. package/dist/hooks/useCancelRequest.js +4 -1
  195. package/dist/hooks/useCancelRequest.js.map +2 -2
  196. package/dist/hooks/useExitOnCtrlCD.js +9 -5
  197. package/dist/hooks/useExitOnCtrlCD.js.map +2 -2
  198. package/dist/hooks/useHookStatus.js +40 -0
  199. package/dist/hooks/useHookStatus.js.map +7 -0
  200. package/dist/hooks/useLogMessages.js +17 -1
  201. package/dist/hooks/useLogMessages.js.map +2 -2
  202. package/dist/hooks/useMessageGroups.js +43 -0
  203. package/dist/hooks/useMessageGroups.js.map +7 -0
  204. package/dist/hooks/useTerminalSize.js +62 -6
  205. package/dist/hooks/useTerminalSize.js.map +2 -2
  206. package/dist/hooks/useUnifiedCompletion.js +69 -0
  207. package/dist/hooks/useUnifiedCompletion.js.map +2 -2
  208. package/dist/i18n/index.js +109 -0
  209. package/dist/i18n/index.js.map +7 -0
  210. package/dist/i18n/locales/en.js +347 -0
  211. package/dist/i18n/locales/en.js.map +7 -0
  212. package/dist/i18n/locales/index.js +7 -0
  213. package/dist/i18n/locales/index.js.map +7 -0
  214. package/dist/i18n/locales/zh-CN.js +347 -0
  215. package/dist/i18n/locales/zh-CN.js.map +7 -0
  216. package/dist/i18n/types.js +8 -0
  217. package/dist/i18n/types.js.map +7 -0
  218. package/dist/query.js +175 -17
  219. package/dist/query.js.map +3 -3
  220. package/dist/screens/REPL.js +501 -192
  221. package/dist/screens/REPL.js.map +3 -3
  222. package/dist/services/adapters/chatCompletions.js +3 -1
  223. package/dist/services/adapters/chatCompletions.js.map +2 -2
  224. package/dist/services/adapters/messageNormalizer.js +354 -0
  225. package/dist/services/adapters/messageNormalizer.js.map +7 -0
  226. package/dist/services/adapters/responsesAPI.js +6 -3
  227. package/dist/services/adapters/responsesAPI.js.map +2 -2
  228. package/dist/services/checkpointManager.js +386 -0
  229. package/dist/services/checkpointManager.js.map +7 -0
  230. package/dist/services/claude.js +138 -11
  231. package/dist/services/claude.js.map +3 -3
  232. package/dist/services/compressionService.js +50 -1
  233. package/dist/services/compressionService.js.map +2 -2
  234. package/dist/services/contextMonitor.js +162 -0
  235. package/dist/services/contextMonitor.js.map +7 -0
  236. package/dist/services/customCommands.js +60 -41
  237. package/dist/services/customCommands.js.map +2 -2
  238. package/dist/services/hookExecutor.js +173 -1
  239. package/dist/services/hookExecutor.js.map +2 -2
  240. package/dist/services/intelligentCompactor.js +281 -0
  241. package/dist/services/intelligentCompactor.js.map +7 -0
  242. package/dist/services/lspConfig.js +109 -0
  243. package/dist/services/lspConfig.js.map +7 -0
  244. package/dist/services/mcpClient.js +273 -34
  245. package/dist/services/mcpClient.js.map +2 -2
  246. package/dist/services/modelOrchestrator.js +310 -0
  247. package/dist/services/modelOrchestrator.js.map +7 -0
  248. package/dist/services/openai.js +8 -1
  249. package/dist/services/openai.js.map +2 -2
  250. package/dist/services/outputStyles.js +138 -0
  251. package/dist/services/outputStyles.js.map +7 -0
  252. package/dist/services/plugins/index.js +5 -0
  253. package/dist/services/plugins/index.js.map +7 -0
  254. package/dist/services/plugins/lspServers.js +188 -0
  255. package/dist/services/plugins/lspServers.js.map +7 -0
  256. package/dist/services/plugins/pluginRuntime.js +229 -0
  257. package/dist/services/plugins/pluginRuntime.js.map +7 -0
  258. package/dist/services/plugins/pluginValidation.js +219 -0
  259. package/dist/services/plugins/pluginValidation.js.map +7 -0
  260. package/dist/services/plugins/skillMarketplace.js +556 -0
  261. package/dist/services/plugins/skillMarketplace.js.map +7 -0
  262. package/dist/services/responseStateManager.js +37 -3
  263. package/dist/services/responseStateManager.js.map +2 -2
  264. package/dist/services/sandbox/filesystemBoundary.js +300 -0
  265. package/dist/services/sandbox/filesystemBoundary.js.map +7 -0
  266. package/dist/services/sandbox/index.js +14 -0
  267. package/dist/services/sandbox/index.js.map +7 -0
  268. package/dist/services/sandbox/networkProxy.js +293 -0
  269. package/dist/services/sandbox/networkProxy.js.map +7 -0
  270. package/dist/services/sandbox/sandboxController.js +574 -0
  271. package/dist/services/sandbox/sandboxController.js.map +7 -0
  272. package/dist/services/sandbox/types.js +50 -0
  273. package/dist/services/sandbox/types.js.map +7 -0
  274. package/dist/services/sessionMemory.js +266 -0
  275. package/dist/services/sessionMemory.js.map +7 -0
  276. package/dist/services/taskRouter.js +324 -0
  277. package/dist/services/taskRouter.js.map +7 -0
  278. package/dist/tools/ArchitectTool/ArchitectTool.js +10 -3
  279. package/dist/tools/ArchitectTool/ArchitectTool.js.map +2 -2
  280. package/dist/tools/AskExpertModelTool/AskExpertModelTool.js +3 -0
  281. package/dist/tools/AskExpertModelTool/AskExpertModelTool.js.map +2 -2
  282. package/dist/tools/AskUserQuestionTool/AskUserQuestionTool.js +8 -1
  283. package/dist/tools/AskUserQuestionTool/AskUserQuestionTool.js.map +2 -2
  284. package/dist/tools/BaseTool.js +72 -0
  285. package/dist/tools/BaseTool.js.map +7 -0
  286. package/dist/tools/BashOutputTool/BashOutputToolResultMessage.js +3 -0
  287. package/dist/tools/BashOutputTool/BashOutputToolResultMessage.js.map +2 -2
  288. package/dist/tools/BashTool/BashTool.js +60 -3
  289. package/dist/tools/BashTool/BashTool.js.map +2 -2
  290. package/dist/tools/BashTool/BashToolResultMessage.js +3 -0
  291. package/dist/tools/BashTool/BashToolResultMessage.js.map +2 -2
  292. package/dist/tools/BashTool/OutputLine.js +54 -0
  293. package/dist/tools/BashTool/OutputLine.js.map +2 -2
  294. package/dist/tools/BashTool/prompt.js +192 -3
  295. package/dist/tools/BashTool/prompt.js.map +2 -2
  296. package/dist/tools/FileEditTool/FileEditTool.js +29 -4
  297. package/dist/tools/FileEditTool/FileEditTool.js.map +2 -2
  298. package/dist/tools/FileReadTool/FileReadTool.js +23 -4
  299. package/dist/tools/FileReadTool/FileReadTool.js.map +2 -2
  300. package/dist/tools/FileWriteTool/FileWriteTool.js +5 -5
  301. package/dist/tools/FileWriteTool/FileWriteTool.js.map +2 -2
  302. package/dist/tools/GlobTool/GlobTool.js +14 -3
  303. package/dist/tools/GlobTool/GlobTool.js.map +2 -2
  304. package/dist/tools/GrepTool/GrepTool.js +41 -7
  305. package/dist/tools/GrepTool/GrepTool.js.map +2 -2
  306. package/dist/tools/KillShellTool/KillShellToolResultMessage.js +3 -0
  307. package/dist/tools/KillShellTool/KillShellToolResultMessage.js.map +2 -2
  308. package/dist/tools/ListMcpResourcesTool/ListMcpResourcesTool.js +109 -0
  309. package/dist/tools/ListMcpResourcesTool/ListMcpResourcesTool.js.map +7 -0
  310. package/dist/tools/ListMcpResourcesTool/prompt.js +19 -0
  311. package/dist/tools/ListMcpResourcesTool/prompt.js.map +7 -0
  312. package/dist/tools/LspTool/LspTool.js +664 -0
  313. package/dist/tools/LspTool/LspTool.js.map +7 -0
  314. package/dist/tools/LspTool/prompt.js +27 -0
  315. package/dist/tools/LspTool/prompt.js.map +7 -0
  316. package/dist/tools/MCPTool/MCPTool.js +11 -4
  317. package/dist/tools/MCPTool/MCPTool.js.map +2 -2
  318. package/dist/tools/MemoryReadTool/MemoryReadTool.js +19 -6
  319. package/dist/tools/MemoryReadTool/MemoryReadTool.js.map +2 -2
  320. package/dist/tools/MemoryWriteTool/MemoryWriteTool.js +6 -6
  321. package/dist/tools/MemoryWriteTool/MemoryWriteTool.js.map +2 -2
  322. package/dist/tools/MultiEditTool/MultiEditTool.js +19 -2
  323. package/dist/tools/MultiEditTool/MultiEditTool.js.map +2 -2
  324. package/dist/tools/NotebookEditTool/NotebookEditTool.js +5 -1
  325. package/dist/tools/NotebookEditTool/NotebookEditTool.js.map +2 -2
  326. package/dist/tools/NotebookReadTool/NotebookReadTool.js +8 -4
  327. package/dist/tools/NotebookReadTool/NotebookReadTool.js.map +2 -2
  328. package/dist/tools/PlanModeTool/EnterPlanModeTool.js +74 -0
  329. package/dist/tools/PlanModeTool/EnterPlanModeTool.js.map +7 -0
  330. package/dist/tools/PlanModeTool/ExitPlanModeTool.js +108 -0
  331. package/dist/tools/PlanModeTool/ExitPlanModeTool.js.map +7 -0
  332. package/dist/tools/PlanModeTool/prompt.js +94 -0
  333. package/dist/tools/PlanModeTool/prompt.js.map +7 -0
  334. package/dist/tools/ReadMcpResourceTool/ReadMcpResourceTool.js +130 -0
  335. package/dist/tools/ReadMcpResourceTool/ReadMcpResourceTool.js.map +7 -0
  336. package/dist/tools/ReadMcpResourceTool/prompt.js +17 -0
  337. package/dist/tools/ReadMcpResourceTool/prompt.js.map +7 -0
  338. package/dist/tools/SkillTool/SkillTool.js +14 -3
  339. package/dist/tools/SkillTool/SkillTool.js.map +2 -2
  340. package/dist/tools/SlashCommandTool/SlashCommandTool.js +260 -0
  341. package/dist/tools/SlashCommandTool/SlashCommandTool.js.map +7 -0
  342. package/dist/tools/SlashCommandTool/prompt.js +35 -0
  343. package/dist/tools/SlashCommandTool/prompt.js.map +7 -0
  344. package/dist/tools/TaskOutputTool/TaskOutputTool.js +189 -0
  345. package/dist/tools/TaskOutputTool/TaskOutputTool.js.map +7 -0
  346. package/dist/tools/TaskOutputTool/prompt.js +15 -0
  347. package/dist/tools/TaskOutputTool/prompt.js.map +7 -0
  348. package/dist/tools/TaskTool/TaskTool.js +321 -146
  349. package/dist/tools/TaskTool/TaskTool.js.map +2 -2
  350. package/dist/tools/TaskTool/prompt.js.map +2 -2
  351. package/dist/tools/TodoWriteTool/TodoWriteTool.js +42 -73
  352. package/dist/tools/TodoWriteTool/TodoWriteTool.js.map +2 -2
  353. package/dist/tools/URLFetcherTool/URLFetcherTool.js +7 -1
  354. package/dist/tools/URLFetcherTool/URLFetcherTool.js.map +2 -2
  355. package/dist/tools/URLFetcherTool/cache.js +55 -8
  356. package/dist/tools/URLFetcherTool/cache.js.map +2 -2
  357. package/dist/tools/WebSearchTool/WebSearchTool.js +6 -1
  358. package/dist/tools/WebSearchTool/WebSearchTool.js.map +2 -2
  359. package/dist/tools.js +31 -2
  360. package/dist/tools.js.map +2 -2
  361. package/dist/types/hooks.js +4 -0
  362. package/dist/types/hooks.js.map +2 -2
  363. package/dist/types/marketplace.js.map +2 -2
  364. package/dist/types/messageGroup.js +36 -0
  365. package/dist/types/messageGroup.js.map +7 -0
  366. package/dist/types/plugin.js.map +2 -2
  367. package/dist/types/thinking.js +1 -0
  368. package/dist/types/thinking.js.map +7 -0
  369. package/dist/utils/BackgroundShellManager.js +136 -39
  370. package/dist/utils/BackgroundShellManager.js.map +2 -2
  371. package/dist/utils/MessageBatchBuffer.js +102 -0
  372. package/dist/utils/MessageBatchBuffer.js.map +7 -0
  373. package/dist/utils/PersistentShell.js +151 -1
  374. package/dist/utils/PersistentShell.js.map +2 -2
  375. package/dist/utils/agentLoader.js +1 -23
  376. package/dist/utils/agentLoader.js.map +2 -2
  377. package/dist/utils/agentTranscripts.js +641 -0
  378. package/dist/utils/agentTranscripts.js.map +7 -0
  379. package/dist/utils/animationManager.js +213 -0
  380. package/dist/utils/animationManager.js.map +7 -0
  381. package/dist/utils/animationSync.js +110 -0
  382. package/dist/utils/animationSync.js.map +7 -0
  383. package/dist/utils/asyncFile.js +215 -0
  384. package/dist/utils/asyncFile.js.map +7 -0
  385. package/dist/utils/backgroundAgentManager.js +231 -0
  386. package/dist/utils/backgroundAgentManager.js.map +7 -0
  387. package/dist/utils/config.js +63 -7
  388. package/dist/utils/config.js.map +2 -2
  389. package/dist/utils/conversationRecovery.js +19 -0
  390. package/dist/utils/conversationRecovery.js.map +2 -2
  391. package/dist/utils/exit.js +73 -0
  392. package/dist/utils/exit.js.map +7 -0
  393. package/dist/utils/format.js +73 -5
  394. package/dist/utils/format.js.map +2 -2
  395. package/dist/utils/generators.js +76 -6
  396. package/dist/utils/generators.js.map +2 -2
  397. package/dist/utils/globalErrorHandler.js +149 -0
  398. package/dist/utils/globalErrorHandler.js.map +7 -0
  399. package/dist/utils/groupHandlers/index.js +8 -0
  400. package/dist/utils/groupHandlers/index.js.map +7 -0
  401. package/dist/utils/groupHandlers/parallelTasksHandler.js +140 -0
  402. package/dist/utils/groupHandlers/parallelTasksHandler.js.map +7 -0
  403. package/dist/utils/groupHandlers/taskHandler.js +104 -0
  404. package/dist/utils/groupHandlers/taskHandler.js.map +7 -0
  405. package/dist/utils/groupHandlers/types.js +1 -0
  406. package/dist/utils/groupHandlers/types.js.map +7 -0
  407. package/dist/utils/logRotation.js +224 -0
  408. package/dist/utils/logRotation.js.map +7 -0
  409. package/dist/utils/marketplaceManager.js +3 -5
  410. package/dist/utils/marketplaceManager.js.map +2 -2
  411. package/dist/utils/memSafety.js +264 -0
  412. package/dist/utils/memSafety.js.map +7 -0
  413. package/dist/utils/messageGroupManager.js +274 -0
  414. package/dist/utils/messageGroupManager.js.map +7 -0
  415. package/dist/utils/messages.js +13 -4
  416. package/dist/utils/messages.js.map +2 -2
  417. package/dist/utils/model.js +119 -15
  418. package/dist/utils/model.js.map +3 -3
  419. package/dist/utils/permissions/filesystem.js +157 -5
  420. package/dist/utils/permissions/filesystem.js.map +2 -2
  421. package/dist/utils/plan/planMode.js +143 -0
  422. package/dist/utils/plan/planMode.js.map +7 -0
  423. package/dist/utils/pluginLoader.js +17 -21
  424. package/dist/utils/pluginLoader.js.map +2 -2
  425. package/dist/utils/ripgrep.js +55 -2
  426. package/dist/utils/ripgrep.js.map +2 -2
  427. package/dist/utils/sanitizeInput.js +32 -0
  428. package/dist/utils/sanitizeInput.js.map +7 -0
  429. package/dist/utils/secureKeyStorage.js +312 -0
  430. package/dist/utils/secureKeyStorage.js.map +7 -0
  431. package/dist/utils/session/sessionPlugins.js +67 -0
  432. package/dist/utils/session/sessionPlugins.js.map +7 -0
  433. package/dist/utils/taskDisplayUtils.js +257 -0
  434. package/dist/utils/taskDisplayUtils.js.map +7 -0
  435. package/dist/utils/teamConfig.js +2 -1
  436. package/dist/utils/teamConfig.js.map +2 -2
  437. package/dist/utils/todoStorage.js +92 -2
  438. package/dist/utils/todoStorage.js.map +2 -2
  439. package/dist/utils/toolTimeout.js +136 -0
  440. package/dist/utils/toolTimeout.js.map +7 -0
  441. package/dist/utils/tooling/safeRender.js +115 -0
  442. package/dist/utils/tooling/safeRender.js.map +7 -0
  443. package/dist/utils/userFriendlyError.js +346 -0
  444. package/dist/utils/userFriendlyError.js.map +7 -0
  445. package/dist/utils/vendor/ripgrep/arm64-darwin/rg +0 -0
  446. package/dist/version.js +2 -2
  447. package/dist/version.js.map +1 -1
  448. package/package.json +14 -4
  449. package/scripts/postinstall.js +128 -38
  450. package/dist/commands/agents.js +0 -2086
  451. package/dist/commands/agents.js.map +0 -7
  452. package/dist/commands/build.js +0 -74
  453. package/dist/commands/build.js.map +0 -7
  454. package/dist/commands/compression.js +0 -57
  455. package/dist/commands/compression.js.map +0 -7
  456. package/dist/commands/listen.js +0 -37
  457. package/dist/commands/listen.js.map +0 -7
  458. package/dist/commands/login.js +0 -37
  459. package/dist/commands/login.js.map +0 -7
  460. package/dist/commands/logout.js +0 -33
  461. package/dist/commands/logout.js.map +0 -7
  462. package/dist/commands/mcp.js +0 -40
  463. package/dist/commands/mcp.js.map +0 -7
  464. package/dist/commands/mcp_refresh.js +0 -40
  465. package/dist/commands/mcp_refresh.js.map +0 -7
  466. package/dist/commands/modelstatus.js +0 -21
  467. package/dist/commands/modelstatus.js.map +0 -7
  468. package/dist/commands/onboarding.js +0 -36
  469. package/dist/commands/onboarding.js.map +0 -7
  470. package/dist/commands/plugin-interactive.js +0 -446
  471. package/dist/commands/plugin-interactive.js.map +0 -7
  472. package/dist/commands/pr_comments.js +0 -61
  473. package/dist/commands/pr_comments.js.map +0 -7
  474. package/dist/commands/release-notes.js +0 -30
  475. package/dist/commands/release-notes.js.map +0 -7
  476. package/dist/commands/review.js +0 -51
  477. package/dist/commands/review.js.map +0 -7
  478. package/dist/components/Bug.js +0 -147
  479. package/dist/components/Bug.js.map +0 -7
  480. package/dist/components/ModelSelector.js +0 -2062
  481. package/dist/components/ModelSelector.js.map +0 -7
  482. package/dist/components/ModelStatusDisplay.js +0 -87
  483. package/dist/components/ModelStatusDisplay.js.map +0 -7
  484. package/dist/entrypoints/cli-wrapper.js +0 -61
  485. package/dist/entrypoints/cli-wrapper.js.map +0 -7
  486. package/dist/screens/Doctor.js +0 -22
  487. package/dist/screens/Doctor.js.map +0 -7
@@ -0,0 +1,74 @@
1
+ import { Box, Text } from "ink";
2
+ import * as React from "react";
3
+ import { useRef, useMemo } from "react";
4
+ import { getTheme } from "../utils/theme.js";
5
+ import { getTotalCost, getTotalAPIDuration } from "../cost-tracker.js";
6
+ import { useUnifiedAnimation } from "../utils/animationManager.js";
7
+ function TokenCounter({
8
+ mode = "compact",
9
+ showCost = true,
10
+ isActive = true
11
+ }) {
12
+ const theme = getTheme();
13
+ const startTimeRef = useRef(Date.now());
14
+ const { elapsedTime } = useUnifiedAnimation({
15
+ enabled: isActive,
16
+ startTime: startTimeRef.current,
17
+ spinnerFrameCount: 1,
18
+ componentId: "token-counter"
19
+ });
20
+ const stats = useMemo(
21
+ () => ({
22
+ totalCost: getTotalCost(),
23
+ apiDuration: getTotalAPIDuration()
24
+ }),
25
+ [elapsedTime]
26
+ );
27
+ const formatCost = (cost) => {
28
+ if (cost < 0.01) {
29
+ return `$${(cost * 100).toFixed(2)}\xA2`;
30
+ }
31
+ return `$${cost.toFixed(2)}`;
32
+ };
33
+ const formatDuration = (ms) => {
34
+ if (ms < 1e3) {
35
+ return `${ms}ms`;
36
+ }
37
+ return `${(ms / 1e3).toFixed(1)}s`;
38
+ };
39
+ if (mode === "minimal") {
40
+ return /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, formatCost(stats.totalCost));
41
+ }
42
+ if (mode === "compact") {
43
+ return /* @__PURE__ */ React.createElement(Box, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, "\u{1F4CA}"), showCost && stats.totalCost > 0 && /* @__PURE__ */ React.createElement(Text, { color: theme.warning }, formatCost(stats.totalCost)), stats.apiDuration > 0 && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, "\xB7"), /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, formatDuration(stats.apiDuration))));
44
+ }
45
+ return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(Box, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, "\u{1F4CA} Cost Summary:")), /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", marginLeft: 2 }, showCost && /* @__PURE__ */ React.createElement(Box, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React.createElement(Text, { color: theme.dimmedText }, "Total Cost:"), /* @__PURE__ */ React.createElement(Text, { color: theme.warning }, formatCost(stats.totalCost))), stats.apiDuration > 0 && /* @__PURE__ */ React.createElement(Box, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React.createElement(Text, { color: theme.dimmedText }, "API Duration:"), /* @__PURE__ */ React.createElement(Text, { color: theme.text }, formatDuration(stats.apiDuration)))));
46
+ }
47
+ function TokenBadge({
48
+ inputTokens,
49
+ outputTokens
50
+ }) {
51
+ const theme = getTheme();
52
+ const total = inputTokens + outputTokens;
53
+ const format = (n) => {
54
+ if (n >= 1e3) {
55
+ return `${(n / 1e3).toFixed(1)}k`;
56
+ }
57
+ return n.toString();
58
+ };
59
+ return /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, format(total), " tokens");
60
+ }
61
+ function CostBadge() {
62
+ const theme = getTheme();
63
+ const cost = getTotalCost();
64
+ if (cost < 1e-3) {
65
+ return /* @__PURE__ */ React.createElement(Text, { color: theme.dimmedText }, "$0.00");
66
+ }
67
+ return /* @__PURE__ */ React.createElement(Text, { color: theme.warning }, "$", cost.toFixed(2));
68
+ }
69
+ export {
70
+ CostBadge,
71
+ TokenBadge,
72
+ TokenCounter
73
+ };
74
+ //# sourceMappingURL=TokenCounter.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/components/TokenCounter.tsx"],
4
+ "sourcesContent": ["/**\n * TokenCounter - Real-time cost and duration display component\n *\n * Displays current session cost and API duration:\n *\n * \uD83D\uDCCA $0.42 \u00B7 15.3s\n *\n * Features:\n * - Real-time updates from cost tracker\n * - Compact and verbose display modes\n * - Cost and API duration display\n * - Uses unified animation manager to reduce screen flickering\n */\n\nimport { Box, Text } from 'ink'\nimport * as React from 'react'\nimport { useState, useRef, useMemo } from 'react'\nimport { getTheme } from '@utils/theme'\nimport { getTotalCost, getTotalAPIDuration } from '@costTracker'\nimport { useUnifiedAnimation } from '@utils/animationManager'\n\nexport interface TokenCounterProps {\n /** Display mode */\n mode?: 'compact' | 'verbose' | 'minimal'\n /** Show cost estimate */\n showCost?: boolean\n /** Update interval in ms (default: 1000) - no longer used, kept for API compat */\n updateInterval?: number\n /** Whether the counter should be active (updating) */\n isActive?: boolean\n}\n\ninterface TokenStats {\n totalCost: number\n apiDuration: number\n}\n\n/**\n * TokenCounter - Real-time cost and duration display\n *\n * Usage:\n * ```tsx\n * // Compact display\n * <TokenCounter mode=\"compact\" />\n *\n * // Full stats\n * <TokenCounter mode=\"verbose\" />\n *\n * // Minimal (just cost)\n * <TokenCounter mode=\"minimal\" />\n * ```\n */\nexport function TokenCounter({\n mode = 'compact',\n showCost = true,\n isActive = true,\n}: TokenCounterProps): React.ReactElement {\n const theme = getTheme()\n const startTimeRef = useRef(Date.now())\n\n // Use unified animation manager for periodic updates\n const { elapsedTime } = useUnifiedAnimation({\n enabled: isActive,\n startTime: startTimeRef.current,\n spinnerFrameCount: 1,\n componentId: 'token-counter',\n })\n\n // Get stats on each render (triggered by elapsedTime change)\n const stats = useMemo<TokenStats>(\n () => ({\n totalCost: getTotalCost(),\n apiDuration: getTotalAPIDuration(),\n }),\n [elapsedTime],\n )\n\n // Format cost\n const formatCost = (cost: number): string => {\n if (cost < 0.01) {\n return `$${(cost * 100).toFixed(2)}\u00A2`\n }\n return `$${cost.toFixed(2)}`\n }\n\n // Format duration\n const formatDuration = (ms: number): string => {\n if (ms < 1000) {\n return `${ms}ms`\n }\n return `${(ms / 1000).toFixed(1)}s`\n }\n\n if (mode === 'minimal') {\n return (\n <Text color={theme.secondaryText}>{formatCost(stats.totalCost)}</Text>\n )\n }\n\n if (mode === 'compact') {\n return (\n <Box flexDirection=\"row\" gap={1}>\n <Text color={theme.secondaryText}>\uD83D\uDCCA</Text>\n {showCost && stats.totalCost > 0 && (\n <Text color={theme.warning}>{formatCost(stats.totalCost)}</Text>\n )}\n {stats.apiDuration > 0 && (\n <>\n <Text color={theme.secondaryText}>\u00B7</Text>\n <Text color={theme.secondaryText}>\n {formatDuration(stats.apiDuration)}\n </Text>\n </>\n )}\n </Box>\n )\n }\n\n // Verbose mode\n return (\n <Box flexDirection=\"column\">\n <Box flexDirection=\"row\" gap={1}>\n <Text color={theme.secondaryText}>\uD83D\uDCCA Cost Summary:</Text>\n </Box>\n <Box flexDirection=\"column\" marginLeft={2}>\n {showCost && (\n <Box flexDirection=\"row\" gap={1}>\n <Text color={theme.dimmedText}>Total Cost:</Text>\n <Text color={theme.warning}>{formatCost(stats.totalCost)}</Text>\n </Box>\n )}\n {stats.apiDuration > 0 && (\n <Box flexDirection=\"row\" gap={1}>\n <Text color={theme.dimmedText}>API Duration:</Text>\n <Text color={theme.text}>{formatDuration(stats.apiDuration)}</Text>\n </Box>\n )}\n </Box>\n </Box>\n )\n}\n\n/**\n * Inline token badge for status bars\n */\nexport function TokenBadge({\n inputTokens,\n outputTokens,\n}: {\n inputTokens: number\n outputTokens: number\n}): React.ReactElement {\n const theme = getTheme()\n const total = inputTokens + outputTokens\n\n // Format with K suffix\n const format = (n: number): string => {\n if (n >= 1000) {\n return `${(n / 1000).toFixed(1)}k`\n }\n return n.toString()\n }\n\n return <Text color={theme.secondaryText}>{format(total)} tokens</Text>\n}\n\n/**\n * Cost badge for status bars\n */\nexport function CostBadge(): React.ReactElement {\n const theme = getTheme()\n const cost = getTotalCost()\n\n if (cost < 0.001) {\n return <Text color={theme.dimmedText}>$0.00</Text>\n }\n\n return <Text color={theme.warning}>${cost.toFixed(2)}</Text>\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -10,7 +10,8 @@ function TokenWarning({ tokenUsage }) {
10
10
  return null;
11
11
  }
12
12
  const isError = tokenUsage >= ERROR_THRESHOLD;
13
- return /* @__PURE__ */ React.createElement(Box, { flexDirection: "row" }, /* @__PURE__ */ React.createElement(Text, { color: isError ? theme.error : theme.warning }, "Context low (", Math.max(0, 100 - Math.round(tokenUsage / MAX_TOKENS * 100)), "% remaining) \xB7 Run /compact to compact & continue"));
13
+ const emoji = isError ? "\u{1F534}" : "\u26A0\uFE0F";
14
+ return /* @__PURE__ */ React.createElement(Box, { flexDirection: "row" }, /* @__PURE__ */ React.createElement(Text, { color: isError ? theme.error : theme.warning }, emoji, " Context low (", Math.max(0, 100 - Math.round(tokenUsage / MAX_TOKENS * 100)), "% remaining) \xB7 Run /compact to compact & continue"));
14
15
  }
15
16
  export {
16
17
  TokenWarning,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/components/TokenWarning.tsx"],
4
- "sourcesContent": ["import { Box, Text } from 'ink'\nimport * as React from 'react'\nimport { getTheme } from '@utils/theme'\n\ntype Props = {\n tokenUsage: number\n}\n\nconst MAX_TOKENS = 190_000\nexport const WARNING_THRESHOLD = MAX_TOKENS * 0.6\nconst ERROR_THRESHOLD = MAX_TOKENS * 0.8\n\nexport function TokenWarning({ tokenUsage }: Props): React.ReactNode {\n const theme = getTheme()\n\n if (tokenUsage < WARNING_THRESHOLD) {\n return null\n }\n\n const isError = tokenUsage >= ERROR_THRESHOLD\n\n return (\n <Box flexDirection=\"row\">\n <Text color={isError ? theme.error : theme.warning}>\n Context low (\n {Math.max(0, 100 - Math.round((tokenUsage / MAX_TOKENS) * 100))}%\n remaining) &middot; Run /compact to compact & continue\n </Text>\n </Box>\n )\n}\n"],
5
- "mappings": "AAAA,SAAS,KAAK,YAAY;AAC1B,YAAY,WAAW;AACvB,SAAS,gBAAgB;AAMzB,MAAM,aAAa;AACZ,MAAM,oBAAoB,aAAa;AAC9C,MAAM,kBAAkB,aAAa;AAE9B,SAAS,aAAa,EAAE,WAAW,GAA2B;AACnE,QAAM,QAAQ,SAAS;AAEvB,MAAI,aAAa,mBAAmB;AAClC,WAAO;AAAA,EACT;AAEA,QAAM,UAAU,cAAc;AAE9B,SACE,oCAAC,OAAI,eAAc,SACjB,oCAAC,QAAK,OAAO,UAAU,MAAM,QAAQ,MAAM,WAAS,iBAEjD,KAAK,IAAI,GAAG,MAAM,KAAK,MAAO,aAAa,aAAc,GAAG,CAAC,GAAE,sDAElE,CACF;AAEJ;",
4
+ "sourcesContent": ["import { Box, Text } from 'ink'\nimport * as React from 'react'\nimport { getTheme } from '@utils/theme'\n\ntype Props = {\n tokenUsage: number\n}\n\nconst MAX_TOKENS = 190_000\nexport const WARNING_THRESHOLD = MAX_TOKENS * 0.6\nconst ERROR_THRESHOLD = MAX_TOKENS * 0.8\n\nexport function TokenWarning({ tokenUsage }: Props): React.ReactNode {\n const theme = getTheme()\n\n if (tokenUsage < WARNING_THRESHOLD) {\n return null\n }\n\n const isError = tokenUsage >= ERROR_THRESHOLD\n\n const emoji = isError ? '\uD83D\uDD34' : '\u26A0\uFE0F'\n\n return (\n <Box flexDirection=\"row\">\n <Text color={isError ? theme.error : theme.warning}>\n {emoji} Context low (\n {Math.max(0, 100 - Math.round((tokenUsage / MAX_TOKENS) * 100))}%\n remaining) \u00B7 Run /compact to compact & continue\n </Text>\n </Box>\n )\n}\n"],
5
+ "mappings": "AAAA,SAAS,KAAK,YAAY;AAC1B,YAAY,WAAW;AACvB,SAAS,gBAAgB;AAMzB,MAAM,aAAa;AACZ,MAAM,oBAAoB,aAAa;AAC9C,MAAM,kBAAkB,aAAa;AAE9B,SAAS,aAAa,EAAE,WAAW,GAA2B;AACnE,QAAM,QAAQ,SAAS;AAEvB,MAAI,aAAa,mBAAmB;AAClC,WAAO;AAAA,EACT;AAEA,QAAM,UAAU,cAAc;AAE9B,QAAM,QAAQ,UAAU,cAAO;AAE/B,SACE,oCAAC,OAAI,eAAc,SACjB,oCAAC,QAAK,OAAO,UAAU,MAAM,QAAQ,MAAM,WACxC,OAAM,kBACN,KAAK,IAAI,GAAG,MAAM,KAAK,MAAO,aAAa,aAAc,GAAG,CAAC,GAAE,sDAElE,CACF;AAEJ;",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,25 @@
1
+ import React from "react";
2
+ import { Box, Text } from "ink";
3
+ import { SYMBOLS } from "../constants/symbols.js";
4
+ function TreeConnector({
5
+ isLast,
6
+ variant = "default"
7
+ }) {
8
+ const branch = isLast ? `${SYMBOLS.TREE_LAST} ` : `${SYMBOLS.TREE_BRANCH} `;
9
+ if (variant === "compact") {
10
+ return /* @__PURE__ */ React.createElement(Text, { dimColor: true }, isLast ? "\u2514 " : "\u251C ");
11
+ }
12
+ return /* @__PURE__ */ React.createElement(Box, { minWidth: 3 }, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, branch));
13
+ }
14
+ function TreeContinuation({
15
+ parentIsLast,
16
+ width = 3
17
+ }) {
18
+ const line = parentIsLast ? `${SYMBOLS.TREE_SPACE} ` : `${SYMBOLS.TREE_VERTICAL} `;
19
+ return /* @__PURE__ */ React.createElement(Box, { minWidth: width }, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, line));
20
+ }
21
+ export {
22
+ TreeConnector,
23
+ TreeContinuation
24
+ };
25
+ //# sourceMappingURL=TreeConnector.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/components/TreeConnector.tsx"],
4
+ "sourcesContent": ["/**\n * Tree Connector Component\n *\n * Renders tree-style connection lines for hierarchical display.\n * Uses REPL \u663E\u793A\u89C4\u8303\u5B9A\u4E49\u7684\u7ED3\u6784\u7B26\u53F7\n */\n\nimport React from 'react'\nimport { Box, Text } from 'ink'\nimport { SYMBOLS } from '@constants/symbols'\n\ninterface Props {\n /** Whether this is the last child in the parent */\n isLast: boolean\n /** Connector style variant */\n variant?: 'default' | 'compact'\n}\n\nexport function TreeConnector({\n isLast,\n variant = 'default',\n}: Props): React.ReactNode {\n // \u4F7F\u7528 REPL \u89C4\u8303\u5B9A\u4E49\u7684\u7ED3\u6784\u7B26\u53F7\n const branch = isLast ? `${SYMBOLS.TREE_LAST} ` : `${SYMBOLS.TREE_BRANCH} `\n\n if (variant === 'compact') {\n return <Text dimColor>{isLast ? '\u2514 ' : '\u251C '}</Text>\n }\n\n return (\n <Box minWidth={3}>\n <Text dimColor>{branch}</Text>\n </Box>\n )\n}\n\n/**\n * Continuation line for nested content under a tree item\n * \u4F7F\u7528 REPL \u89C4\u8303\u5B9A\u4E49\u7684\u5782\u76F4\u8FDE\u63A5\u7B26\u53F7\n */\ninterface ContinuationProps {\n /** Whether parent was the last child */\n parentIsLast: boolean\n /** Width of the continuation line area */\n width?: number\n}\n\nexport function TreeContinuation({\n parentIsLast,\n width = 3,\n}: ContinuationProps): React.ReactNode {\n // \u6700\u540E\u4E00\u9879\u540E\u4F7F\u7528\u7A7A\u767D\uFF0C\u975E\u6700\u540E\u9879\u4F7F\u7528\u5782\u76F4\u7EBF\n const line = parentIsLast\n ? `${SYMBOLS.TREE_SPACE} `\n : `${SYMBOLS.TREE_VERTICAL} `\n\n return (\n <Box minWidth={width}>\n <Text dimColor>{line}</Text>\n </Box>\n )\n}\n"],
5
+ "mappings": "AAOA,OAAO,WAAW;AAClB,SAAS,KAAK,YAAY;AAC1B,SAAS,eAAe;AASjB,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA,UAAU;AACZ,GAA2B;AAEzB,QAAM,SAAS,SAAS,GAAG,QAAQ,SAAS,MAAM,GAAG,QAAQ,WAAW;AAExE,MAAI,YAAY,WAAW;AACzB,WAAO,oCAAC,QAAK,UAAQ,QAAE,SAAS,YAAO,SAAK;AAAA,EAC9C;AAEA,SACE,oCAAC,OAAI,UAAU,KACb,oCAAC,QAAK,UAAQ,QAAE,MAAO,CACzB;AAEJ;AAaO,SAAS,iBAAiB;AAAA,EAC/B;AAAA,EACA,QAAQ;AACV,GAAuC;AAErC,QAAM,OAAO,eACT,GAAG,QAAQ,UAAU,MACrB,GAAG,QAAQ,aAAa;AAE5B,SACE,oCAAC,OAAI,UAAU,SACb,oCAAC,QAAK,UAAQ,QAAE,IAAK,CACvB;AAEJ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,18 @@
1
+ import React from "react";
2
+ import { Box, Text } from "ink";
3
+ import { formatDuration } from "../utils/format.js";
4
+ import { getTheme } from "../utils/theme.js";
5
+ function TurnCompletionIndicator({
6
+ durationMs,
7
+ isVisible
8
+ }) {
9
+ if (!isVisible || durationMs === null || durationMs < 1e3) {
10
+ return null;
11
+ }
12
+ const theme = getTheme();
13
+ return /* @__PURE__ */ React.createElement(Box, { marginTop: 1, marginBottom: 1 }, /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, "\u273B Cogitated for ", formatDuration(durationMs)));
14
+ }
15
+ export {
16
+ TurnCompletionIndicator
17
+ };
18
+ //# sourceMappingURL=TurnCompletionIndicator.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/components/TurnCompletionIndicator.tsx"],
4
+ "sourcesContent": ["/**\n * Turn Completion Indicator\n *\n * Displays \"\u273B Cogitated for Xm Ys\" after an AI turn completes,\n * similar to Claude Code's turn duration display.\n */\n\nimport React from 'react'\nimport { Box, Text } from 'ink'\nimport { formatDuration } from '@utils/format'\nimport { getTheme } from '@utils/theme'\n\ninterface Props {\n /** Duration of the completed turn in milliseconds */\n durationMs: number | null\n /** Whether to show the indicator */\n isVisible: boolean\n}\n\n/**\n * Shows a completion indicator with elapsed time after an AI turn finishes.\n * Uses \"Cogitated\" as a more engaging word than \"Worked\" or \"Processed\".\n */\nexport function TurnCompletionIndicator({\n durationMs,\n isVisible,\n}: Props): React.ReactNode {\n if (!isVisible || durationMs === null || durationMs < 1000) {\n // Don't show for very short turns (< 1s)\n return null\n }\n\n const theme = getTheme()\n\n return (\n <Box marginTop={1} marginBottom={1}>\n <Text color={theme.secondaryText}>\n \u273B Cogitated for {formatDuration(durationMs)}\n </Text>\n </Box>\n )\n}\n"],
5
+ "mappings": "AAOA,OAAO,WAAW;AAClB,SAAS,KAAK,YAAY;AAC1B,SAAS,sBAAsB;AAC/B,SAAS,gBAAgB;AAalB,SAAS,wBAAwB;AAAA,EACtC;AAAA,EACA;AACF,GAA2B;AACzB,MAAI,CAAC,aAAa,eAAe,QAAQ,aAAa,KAAM;AAE1D,WAAO;AAAA,EACT;AAEA,QAAM,QAAQ,SAAS;AAEvB,SACE,oCAAC,OAAI,WAAW,GAAG,cAAc,KAC/B,oCAAC,QAAK,OAAO,MAAM,iBAAe,yBACf,eAAe,UAAU,CAC5C,CACF;AAEJ;",
6
+ "names": []
7
+ }
@@ -20,6 +20,7 @@ import {
20
20
  import { BLACK_CIRCLE } from "../../constants/figures.js";
21
21
  import { applyMarkdown } from "../../utils/markdown.js";
22
22
  import { useTerminalSize } from "../../hooks/useTerminalSize.js";
23
+ import { formatTimestamp } from "../../utils/format.js";
23
24
  function AssistantTextMessage({
24
25
  param: { text },
25
26
  costUSD,
@@ -27,7 +28,9 @@ function AssistantTextMessage({
27
28
  debug,
28
29
  addMargin,
29
30
  shouldShowDot,
30
- verbose
31
+ verbose,
32
+ timestamp,
33
+ modelId
31
34
  }) {
32
35
  const { columns } = useTerminalSize();
33
36
  if (isEmptyMessageText(text)) {
@@ -68,7 +71,7 @@ function AssistantTextMessage({
68
71
  width: "100%"
69
72
  },
70
73
  /* @__PURE__ */ React.createElement(Box, { flexDirection: "row" }, shouldShowDot && /* @__PURE__ */ React.createElement(Box, { minWidth: 2 }, /* @__PURE__ */ React.createElement(Text, { color: getTheme().text }, BLACK_CIRCLE)), /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", width: columns - 6 }, /* @__PURE__ */ React.createElement(Text, null, applyMarkdown(text)))),
71
- /* @__PURE__ */ React.createElement(Cost, { costUSD, durationMs, debug })
74
+ /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", alignItems: "flex-end" }, /* @__PURE__ */ React.createElement(Cost, { costUSD, durationMs, debug }), verbose && (timestamp || modelId) && /* @__PURE__ */ React.createElement(Text, { dimColor: true }, timestamp ? formatTimestamp(timestamp) : "", timestamp && modelId ? " " : "", modelId || ""))
72
75
  );
73
76
  }
74
77
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/components/messages/AssistantTextMessage.tsx"],
4
- "sourcesContent": ["import { TextBlockParam } from '@anthropic-ai/sdk/resources/index.mjs'\nimport React from 'react'\nimport { AssistantBashOutputMessage } from './AssistantBashOutputMessage'\nimport { AssistantLocalCommandOutputMessage } from './AssistantLocalCommandOutputMessage'\nimport { getTheme } from '@utils/theme'\nimport { Box, Text } from 'ink'\nimport { Cost } from '@components/Cost'\nimport {\n API_ERROR_MESSAGE_PREFIX,\n CREDIT_BALANCE_TOO_LOW_ERROR_MESSAGE,\n INVALID_API_KEY_ERROR_MESSAGE,\n PROMPT_TOO_LONG_ERROR_MESSAGE,\n} from '@services/claude'\nimport {\n CANCEL_MESSAGE,\n INTERRUPT_MESSAGE,\n INTERRUPT_MESSAGE_FOR_TOOL_USE,\n isEmptyMessageText,\n NO_RESPONSE_REQUESTED,\n} from '@utils/messages'\nimport { BLACK_CIRCLE } from '@constants/figures'\nimport { applyMarkdown } from '@utils/markdown'\nimport { useTerminalSize } from '@hooks/useTerminalSize'\n\ntype Props = {\n param: TextBlockParam\n costUSD: number\n durationMs: number\n debug: boolean\n addMargin: boolean\n shouldShowDot: boolean\n verbose?: boolean\n width?: number | string\n}\n\nexport function AssistantTextMessage({\n param: { text },\n costUSD,\n durationMs,\n debug,\n addMargin,\n shouldShowDot,\n verbose,\n}: Props): React.ReactNode {\n const { columns } = useTerminalSize()\n if (isEmptyMessageText(text)) {\n return null\n }\n\n // Show bash output\n if (text.startsWith('<bash-stdout') || text.startsWith('<bash-stderr')) {\n return <AssistantBashOutputMessage content={text} verbose={verbose} />\n }\n\n // Show command output\n if (\n text.startsWith('<local-command-stdout') ||\n text.startsWith('<local-command-stderr')\n ) {\n return <AssistantLocalCommandOutputMessage content={text} />\n }\n\n if (text.startsWith(API_ERROR_MESSAGE_PREFIX)) {\n return (\n <Text>\n &nbsp;&nbsp;\u23BF &nbsp;\n <Text color={getTheme().error}>\n {text === API_ERROR_MESSAGE_PREFIX\n ? `${API_ERROR_MESSAGE_PREFIX}: Please wait a moment and try again.`\n : text}\n </Text>\n </Text>\n )\n }\n\n switch (text) {\n // Local JSX commands don't need a response, but we still want the assistant to see them\n // Tool results render their own interrupt messages\n case NO_RESPONSE_REQUESTED:\n case INTERRUPT_MESSAGE_FOR_TOOL_USE:\n return null\n\n case INTERRUPT_MESSAGE:\n case CANCEL_MESSAGE:\n return (\n <Text>\n &nbsp;&nbsp;\u23BF &nbsp;\n <Text color={getTheme().error}>Interrupted by user</Text>\n </Text>\n )\n\n case PROMPT_TOO_LONG_ERROR_MESSAGE:\n return (\n <Text>\n &nbsp;&nbsp;\u23BF &nbsp;\n <Text color={getTheme().error}>\n Context low &middot; Run /compact to compact & continue\n </Text>\n </Text>\n )\n\n case CREDIT_BALANCE_TOO_LOW_ERROR_MESSAGE:\n return (\n <Text>\n &nbsp;&nbsp;\u23BF &nbsp;\n <Text color={getTheme().error}>\n Credit balance too low &middot; Add funds:\n https://console.anthropic.com/settings/billing\n </Text>\n </Text>\n )\n\n case INVALID_API_KEY_ERROR_MESSAGE:\n return (\n <Text>\n &nbsp;&nbsp;\u23BF &nbsp;\n <Text color={getTheme().error}>{INVALID_API_KEY_ERROR_MESSAGE}</Text>\n </Text>\n )\n\n default:\n return (\n <Box\n alignItems=\"flex-start\"\n flexDirection=\"row\"\n justifyContent=\"space-between\"\n marginTop={addMargin ? 1 : 0}\n width=\"100%\"\n >\n <Box flexDirection=\"row\">\n {shouldShowDot && (\n <Box minWidth={2}>\n <Text color={getTheme().text}>{BLACK_CIRCLE}</Text>\n </Box>\n )}\n <Box flexDirection=\"column\" width={columns - 6}>\n <Text>{applyMarkdown(text)}</Text>\n </Box>\n </Box>\n <Cost costUSD={costUSD} durationMs={durationMs} debug={debug} />\n </Box>\n )\n }\n}\n"],
5
- "mappings": "AACA,OAAO,WAAW;AAClB,SAAS,kCAAkC;AAC3C,SAAS,0CAA0C;AACnD,SAAS,gBAAgB;AACzB,SAAS,KAAK,YAAY;AAC1B,SAAS,YAAY;AACrB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,oBAAoB;AAC7B,SAAS,qBAAqB;AAC9B,SAAS,uBAAuB;AAazB,SAAS,qBAAqB;AAAA,EACnC,OAAO,EAAE,KAAK;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA2B;AACzB,QAAM,EAAE,QAAQ,IAAI,gBAAgB;AACpC,MAAI,mBAAmB,IAAI,GAAG;AAC5B,WAAO;AAAA,EACT;AAGA,MAAI,KAAK,WAAW,cAAc,KAAK,KAAK,WAAW,cAAc,GAAG;AACtE,WAAO,oCAAC,8BAA2B,SAAS,MAAM,SAAkB;AAAA,EACtE;AAGA,MACE,KAAK,WAAW,uBAAuB,KACvC,KAAK,WAAW,uBAAuB,GACvC;AACA,WAAO,oCAAC,sCAAmC,SAAS,MAAM;AAAA,EAC5D;AAEA,MAAI,KAAK,WAAW,wBAAwB,GAAG;AAC7C,WACE,oCAAC,YAAK,uBAEJ,oCAAC,QAAK,OAAO,SAAS,EAAE,SACrB,SAAS,2BACN,GAAG,wBAAwB,0CAC3B,IACN,CACF;AAAA,EAEJ;AAEA,UAAQ,MAAM;AAAA;AAAA;AAAA,IAGZ,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AAAA,IACL,KAAK;AACH,aACE,oCAAC,YAAK,uBAEJ,oCAAC,QAAK,OAAO,SAAS,EAAE,SAAO,qBAAmB,CACpD;AAAA,IAGJ,KAAK;AACH,aACE,oCAAC,YAAK,uBAEJ,oCAAC,QAAK,OAAO,SAAS,EAAE,SAAO,qDAE/B,CACF;AAAA,IAGJ,KAAK;AACH,aACE,oCAAC,YAAK,uBAEJ,oCAAC,QAAK,OAAO,SAAS,EAAE,SAAO,uFAG/B,CACF;AAAA,IAGJ,KAAK;AACH,aACE,oCAAC,YAAK,uBAEJ,oCAAC,QAAK,OAAO,SAAS,EAAE,SAAQ,6BAA8B,CAChE;AAAA,IAGJ;AACE,aACE;AAAA,QAAC;AAAA;AAAA,UACC,YAAW;AAAA,UACX,eAAc;AAAA,UACd,gBAAe;AAAA,UACf,WAAW,YAAY,IAAI;AAAA,UAC3B,OAAM;AAAA;AAAA,QAEN,oCAAC,OAAI,eAAc,SAChB,iBACC,oCAAC,OAAI,UAAU,KACb,oCAAC,QAAK,OAAO,SAAS,EAAE,QAAO,YAAa,CAC9C,GAEF,oCAAC,OAAI,eAAc,UAAS,OAAO,UAAU,KAC3C,oCAAC,YAAM,cAAc,IAAI,CAAE,CAC7B,CACF;AAAA,QACA,oCAAC,QAAK,SAAkB,YAAwB,OAAc;AAAA,MAChE;AAAA,EAEN;AACF;",
4
+ "sourcesContent": ["import { TextBlockParam } from '@anthropic-ai/sdk/resources/index.mjs'\nimport React from 'react'\nimport { AssistantBashOutputMessage } from './AssistantBashOutputMessage'\nimport { AssistantLocalCommandOutputMessage } from './AssistantLocalCommandOutputMessage'\nimport { getTheme } from '@utils/theme'\nimport { Box, Text } from 'ink'\nimport { Cost } from '@components/Cost'\nimport {\n API_ERROR_MESSAGE_PREFIX,\n CREDIT_BALANCE_TOO_LOW_ERROR_MESSAGE,\n INVALID_API_KEY_ERROR_MESSAGE,\n PROMPT_TOO_LONG_ERROR_MESSAGE,\n} from '@services/claude'\nimport {\n CANCEL_MESSAGE,\n INTERRUPT_MESSAGE,\n INTERRUPT_MESSAGE_FOR_TOOL_USE,\n isEmptyMessageText,\n NO_RESPONSE_REQUESTED,\n} from '@utils/messages'\nimport { BLACK_CIRCLE } from '@constants/figures'\nimport { applyMarkdown } from '@utils/markdown'\nimport { useTerminalSize } from '@hooks/useTerminalSize'\nimport { formatTimestamp } from '@utils/format'\n\ntype Props = {\n param: TextBlockParam\n costUSD: number\n durationMs: number\n debug: boolean\n addMargin: boolean\n shouldShowDot: boolean\n verbose?: boolean\n width?: number | string\n /** Timestamp for verbose mode display */\n timestamp?: number\n /** Model ID for verbose mode display */\n modelId?: string\n}\n\nexport function AssistantTextMessage({\n param: { text },\n costUSD,\n durationMs,\n debug,\n addMargin,\n shouldShowDot,\n verbose,\n timestamp,\n modelId,\n}: Props): React.ReactNode {\n const { columns } = useTerminalSize()\n if (isEmptyMessageText(text)) {\n return null\n }\n\n // Show bash output\n if (text.startsWith('<bash-stdout') || text.startsWith('<bash-stderr')) {\n return <AssistantBashOutputMessage content={text} verbose={verbose} />\n }\n\n // Show command output\n if (\n text.startsWith('<local-command-stdout') ||\n text.startsWith('<local-command-stderr')\n ) {\n return <AssistantLocalCommandOutputMessage content={text} />\n }\n\n if (text.startsWith(API_ERROR_MESSAGE_PREFIX)) {\n return (\n <Text>\n &nbsp;&nbsp;\u23BF &nbsp;\n <Text color={getTheme().error}>\n {text === API_ERROR_MESSAGE_PREFIX\n ? `${API_ERROR_MESSAGE_PREFIX}: Please wait a moment and try again.`\n : text}\n </Text>\n </Text>\n )\n }\n\n switch (text) {\n // Local JSX commands don't need a response, but we still want the assistant to see them\n // Tool results render their own interrupt messages\n case NO_RESPONSE_REQUESTED:\n case INTERRUPT_MESSAGE_FOR_TOOL_USE:\n return null\n\n case INTERRUPT_MESSAGE:\n case CANCEL_MESSAGE:\n return (\n <Text>\n &nbsp;&nbsp;\u23BF &nbsp;\n <Text color={getTheme().error}>Interrupted by user</Text>\n </Text>\n )\n\n case PROMPT_TOO_LONG_ERROR_MESSAGE:\n return (\n <Text>\n &nbsp;&nbsp;\u23BF &nbsp;\n <Text color={getTheme().error}>\n Context low &middot; Run /compact to compact & continue\n </Text>\n </Text>\n )\n\n case CREDIT_BALANCE_TOO_LOW_ERROR_MESSAGE:\n return (\n <Text>\n &nbsp;&nbsp;\u23BF &nbsp;\n <Text color={getTheme().error}>\n Credit balance too low &middot; Add funds:\n https://console.anthropic.com/settings/billing\n </Text>\n </Text>\n )\n\n case INVALID_API_KEY_ERROR_MESSAGE:\n return (\n <Text>\n &nbsp;&nbsp;\u23BF &nbsp;\n <Text color={getTheme().error}>{INVALID_API_KEY_ERROR_MESSAGE}</Text>\n </Text>\n )\n\n default:\n return (\n <Box\n alignItems=\"flex-start\"\n flexDirection=\"row\"\n justifyContent=\"space-between\"\n marginTop={addMargin ? 1 : 0}\n width=\"100%\"\n >\n <Box flexDirection=\"row\">\n {shouldShowDot && (\n <Box minWidth={2}>\n <Text color={getTheme().text}>{BLACK_CIRCLE}</Text>\n </Box>\n )}\n <Box flexDirection=\"column\" width={columns - 6}>\n <Text>{applyMarkdown(text)}</Text>\n </Box>\n </Box>\n <Box flexDirection=\"column\" alignItems=\"flex-end\">\n <Cost costUSD={costUSD} durationMs={durationMs} debug={debug} />\n {/* Verbose mode: show timestamp and model ID */}\n {verbose && (timestamp || modelId) && (\n <Text dimColor>\n {timestamp ? formatTimestamp(timestamp) : ''}\n {timestamp && modelId ? ' ' : ''}\n {modelId || ''}\n </Text>\n )}\n </Box>\n </Box>\n )\n }\n}\n"],
5
+ "mappings": "AACA,OAAO,WAAW;AAClB,SAAS,kCAAkC;AAC3C,SAAS,0CAA0C;AACnD,SAAS,gBAAgB;AACzB,SAAS,KAAK,YAAY;AAC1B,SAAS,YAAY;AACrB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,oBAAoB;AAC7B,SAAS,qBAAqB;AAC9B,SAAS,uBAAuB;AAChC,SAAS,uBAAuB;AAiBzB,SAAS,qBAAqB;AAAA,EACnC,OAAO,EAAE,KAAK;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA2B;AACzB,QAAM,EAAE,QAAQ,IAAI,gBAAgB;AACpC,MAAI,mBAAmB,IAAI,GAAG;AAC5B,WAAO;AAAA,EACT;AAGA,MAAI,KAAK,WAAW,cAAc,KAAK,KAAK,WAAW,cAAc,GAAG;AACtE,WAAO,oCAAC,8BAA2B,SAAS,MAAM,SAAkB;AAAA,EACtE;AAGA,MACE,KAAK,WAAW,uBAAuB,KACvC,KAAK,WAAW,uBAAuB,GACvC;AACA,WAAO,oCAAC,sCAAmC,SAAS,MAAM;AAAA,EAC5D;AAEA,MAAI,KAAK,WAAW,wBAAwB,GAAG;AAC7C,WACE,oCAAC,YAAK,uBAEJ,oCAAC,QAAK,OAAO,SAAS,EAAE,SACrB,SAAS,2BACN,GAAG,wBAAwB,0CAC3B,IACN,CACF;AAAA,EAEJ;AAEA,UAAQ,MAAM;AAAA;AAAA;AAAA,IAGZ,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AAAA,IACL,KAAK;AACH,aACE,oCAAC,YAAK,uBAEJ,oCAAC,QAAK,OAAO,SAAS,EAAE,SAAO,qBAAmB,CACpD;AAAA,IAGJ,KAAK;AACH,aACE,oCAAC,YAAK,uBAEJ,oCAAC,QAAK,OAAO,SAAS,EAAE,SAAO,qDAE/B,CACF;AAAA,IAGJ,KAAK;AACH,aACE,oCAAC,YAAK,uBAEJ,oCAAC,QAAK,OAAO,SAAS,EAAE,SAAO,uFAG/B,CACF;AAAA,IAGJ,KAAK;AACH,aACE,oCAAC,YAAK,uBAEJ,oCAAC,QAAK,OAAO,SAAS,EAAE,SAAQ,6BAA8B,CAChE;AAAA,IAGJ;AACE,aACE;AAAA,QAAC;AAAA;AAAA,UACC,YAAW;AAAA,UACX,eAAc;AAAA,UACd,gBAAe;AAAA,UACf,WAAW,YAAY,IAAI;AAAA,UAC3B,OAAM;AAAA;AAAA,QAEN,oCAAC,OAAI,eAAc,SAChB,iBACC,oCAAC,OAAI,UAAU,KACb,oCAAC,QAAK,OAAO,SAAS,EAAE,QAAO,YAAa,CAC9C,GAEF,oCAAC,OAAI,eAAc,UAAS,OAAO,UAAU,KAC3C,oCAAC,YAAM,cAAc,IAAI,CAAE,CAC7B,CACF;AAAA,QACA,oCAAC,OAAI,eAAc,UAAS,YAAW,cACrC,oCAAC,QAAK,SAAkB,YAAwB,OAAc,GAE7D,YAAY,aAAa,YACxB,oCAAC,QAAK,UAAQ,QACX,YAAY,gBAAgB,SAAS,IAAI,IACzC,aAAa,UAAU,OAAO,IAC9B,WAAW,EACd,CAEJ;AAAA,MACF;AAAA,EAEN;AACF;",
6
6
  "names": []
7
7
  }
@@ -2,13 +2,28 @@ import React from "react";
2
2
  import { Box, Text } from "ink";
3
3
  import { getTheme } from "../../utils/theme.js";
4
4
  import { applyMarkdown } from "../../utils/markdown.js";
5
+ import { formatDuration, formatNumber } from "../../utils/format.js";
6
+ function formatThinkingMeta(metadata) {
7
+ const parts = [];
8
+ if (metadata.durationMs > 0) {
9
+ parts.push(formatDuration(metadata.durationMs));
10
+ }
11
+ if (metadata.charCount > 0) {
12
+ parts.push(`${formatNumber(metadata.charCount)} chars`);
13
+ }
14
+ return parts.join(" \xB7 ");
15
+ }
5
16
  function AssistantThinkingMessage({
6
17
  param: { thinking },
7
- addMargin = false
18
+ addMargin = false,
19
+ metadata,
20
+ showMetaInfo = false
8
21
  }) {
9
22
  if (!thinking) {
10
23
  return null;
11
24
  }
25
+ const theme = getTheme();
26
+ const metaText = showMetaInfo && metadata ? formatThinkingMeta(metadata) : null;
12
27
  return /* @__PURE__ */ React.createElement(
13
28
  Box,
14
29
  {
@@ -17,8 +32,8 @@ function AssistantThinkingMessage({
17
32
  marginTop: addMargin ? 1 : 0,
18
33
  width: "100%"
19
34
  },
20
- /* @__PURE__ */ React.createElement(Text, { color: getTheme().secondaryText, italic: true }, "\u273B Thinking\u2026"),
21
- /* @__PURE__ */ React.createElement(Box, { paddingLeft: 2 }, /* @__PURE__ */ React.createElement(Text, { color: getTheme().secondaryText, italic: true }, applyMarkdown(thinking)))
35
+ /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText, italic: true }, "\u273B ", metadata?.isComplete ? "Thinking" : "Thinking\u2026"), metaText && /* @__PURE__ */ React.createElement(Text, { color: theme.mutedText }, " (", metaText, ")")),
36
+ /* @__PURE__ */ React.createElement(Box, { paddingLeft: 2 }, /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText, italic: true }, applyMarkdown(thinking)))
22
37
  );
23
38
  }
24
39
  export {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/components/messages/AssistantThinkingMessage.tsx"],
4
- "sourcesContent": ["import React from 'react'\nimport { Box, Text } from 'ink'\nimport { getTheme } from '@utils/theme'\nimport { applyMarkdown } from '@utils/markdown'\nimport {\n ThinkingBlock,\n ThinkingBlockParam,\n} from '@anthropic-ai/sdk/resources/index.mjs'\n\ntype Props = {\n param: ThinkingBlock | ThinkingBlockParam\n addMargin: boolean\n}\n\nexport function AssistantThinkingMessage({\n param: { thinking },\n addMargin = false,\n}: Props): React.ReactNode {\n if (!thinking) {\n return null\n }\n\n return (\n <Box\n flexDirection=\"column\"\n gap={1}\n marginTop={addMargin ? 1 : 0}\n width=\"100%\"\n >\n <Text color={getTheme().secondaryText} italic>\n \u273B Thinking\u2026\n </Text>\n <Box paddingLeft={2}>\n <Text color={getTheme().secondaryText} italic>\n {applyMarkdown(thinking)}\n </Text>\n </Box>\n </Box>\n )\n}\n"],
5
- "mappings": "AAAA,OAAO,WAAW;AAClB,SAAS,KAAK,YAAY;AAC1B,SAAS,gBAAgB;AACzB,SAAS,qBAAqB;AAWvB,SAAS,yBAAyB;AAAA,EACvC,OAAO,EAAE,SAAS;AAAA,EAClB,YAAY;AACd,GAA2B;AACzB,MAAI,CAAC,UAAU;AACb,WAAO;AAAA,EACT;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,eAAc;AAAA,MACd,KAAK;AAAA,MACL,WAAW,YAAY,IAAI;AAAA,MAC3B,OAAM;AAAA;AAAA,IAEN,oCAAC,QAAK,OAAO,SAAS,EAAE,eAAe,QAAM,QAAC,uBAE9C;AAAA,IACA,oCAAC,OAAI,aAAa,KAChB,oCAAC,QAAK,OAAO,SAAS,EAAE,eAAe,QAAM,QAC1C,cAAc,QAAQ,CACzB,CACF;AAAA,EACF;AAEJ;",
4
+ "sourcesContent": ["import React from 'react'\nimport { Box, Text } from 'ink'\nimport { getTheme } from '@utils/theme'\nimport { applyMarkdown } from '@utils/markdown'\nimport { formatDuration, formatNumber } from '@utils/format'\nimport {\n ThinkingBlock,\n ThinkingBlockParam,\n} from '@anthropic-ai/sdk/resources/index.mjs'\nimport type { ThinkingMetadata } from '@minto-types/thinking'\n\ntype Props = {\n param: ThinkingBlock | ThinkingBlockParam\n addMargin: boolean\n metadata?: ThinkingMetadata\n showMetaInfo?: boolean\n}\n\n/**\n * Format thinking metadata for display\n * e.g., \"15s \u00B7 4.2k chars\"\n */\nfunction formatThinkingMeta(metadata: ThinkingMetadata): string {\n const parts: string[] = []\n if (metadata.durationMs > 0) {\n parts.push(formatDuration(metadata.durationMs))\n }\n if (metadata.charCount > 0) {\n parts.push(`${formatNumber(metadata.charCount)} chars`)\n }\n return parts.join(' \u00B7 ')\n}\n\nexport function AssistantThinkingMessage({\n param: { thinking },\n addMargin = false,\n metadata,\n showMetaInfo = false,\n}: Props): React.ReactNode {\n if (!thinking) {\n return null\n }\n\n const theme = getTheme()\n\n // Format metadata for display\n const metaText =\n showMetaInfo && metadata ? formatThinkingMeta(metadata) : null\n\n return (\n <Box\n flexDirection=\"column\"\n gap={1}\n marginTop={addMargin ? 1 : 0}\n width=\"100%\"\n >\n <Box>\n <Text color={theme.secondaryText} italic>\n \u273B {metadata?.isComplete ? 'Thinking' : 'Thinking\u2026'}\n </Text>\n {metaText && <Text color={theme.mutedText}> ({metaText})</Text>}\n </Box>\n <Box paddingLeft={2}>\n <Text color={theme.secondaryText} italic>\n {applyMarkdown(thinking)}\n </Text>\n </Box>\n </Box>\n )\n}\n"],
5
+ "mappings": "AAAA,OAAO,WAAW;AAClB,SAAS,KAAK,YAAY;AAC1B,SAAS,gBAAgB;AACzB,SAAS,qBAAqB;AAC9B,SAAS,gBAAgB,oBAAoB;AAkB7C,SAAS,mBAAmB,UAAoC;AAC9D,QAAM,QAAkB,CAAC;AACzB,MAAI,SAAS,aAAa,GAAG;AAC3B,UAAM,KAAK,eAAe,SAAS,UAAU,CAAC;AAAA,EAChD;AACA,MAAI,SAAS,YAAY,GAAG;AAC1B,UAAM,KAAK,GAAG,aAAa,SAAS,SAAS,CAAC,QAAQ;AAAA,EACxD;AACA,SAAO,MAAM,KAAK,QAAK;AACzB;AAEO,SAAS,yBAAyB;AAAA,EACvC,OAAO,EAAE,SAAS;AAAA,EAClB,YAAY;AAAA,EACZ;AAAA,EACA,eAAe;AACjB,GAA2B;AACzB,MAAI,CAAC,UAAU;AACb,WAAO;AAAA,EACT;AAEA,QAAM,QAAQ,SAAS;AAGvB,QAAM,WACJ,gBAAgB,WAAW,mBAAmB,QAAQ,IAAI;AAE5D,SACE;AAAA,IAAC;AAAA;AAAA,MACC,eAAc;AAAA,MACd,KAAK;AAAA,MACL,WAAW,YAAY,IAAI;AAAA,MAC3B,OAAM;AAAA;AAAA,IAEN,oCAAC,WACC,oCAAC,QAAK,OAAO,MAAM,eAAe,QAAM,QAAC,WACpC,UAAU,aAAa,aAAa,gBACzC,GACC,YAAY,oCAAC,QAAK,OAAO,MAAM,aAAW,MAAG,UAAS,GAAC,CAC1D;AAAA,IACA,oCAAC,OAAI,aAAa,KAChB,oCAAC,QAAK,OAAO,MAAM,eAAe,QAAM,QACrC,cAAc,QAAQ,CACzB,CACF;AAAA,EACF;AAEJ;",
6
6
  "names": []
7
7
  }
@@ -8,6 +8,8 @@ import { BLACK_CIRCLE } from "../../constants/figures.js";
8
8
  import { ThinkTool } from "../../tools/ThinkTool/ThinkTool.js";
9
9
  import { AssistantThinkingMessage } from "./AssistantThinkingMessage.js";
10
10
  import { TaskToolMessage } from "./TaskToolMessage.js";
11
+ import { safeRenderToolUseMessage } from "../../utils/tooling/safeRender.js";
12
+ import { formatTimestamp } from "../../utils/format.js";
11
13
  function AssistantToolUseMessage({
12
14
  param,
13
15
  costUSD,
@@ -20,7 +22,8 @@ function AssistantToolUseMessage({
20
22
  inProgressToolUseIDs,
21
23
  unresolvedToolUseIDs,
22
24
  shouldAnimate,
23
- shouldShowDot
25
+ shouldShowDot,
26
+ modelId
24
27
  }) {
25
28
  const tool = tools.find((_) => _.name === param.name);
26
29
  if (!tool) {
@@ -73,18 +76,18 @@ function AssistantToolUseMessage({
73
76
  }
74
77
  ) : /* @__PURE__ */ React.createElement(Text, { color, bold: !isQueued }, userFacingToolName)
75
78
  ), /* @__PURE__ */ React.createElement(Box, { flexWrap: "nowrap" }, Object.keys(param.input).length > 0 && (() => {
76
- const toolMessage = tool.renderToolUseMessage(
77
- param.input,
78
- {
79
- verbose
80
- }
81
- );
79
+ const toolMessage = safeRenderToolUseMessage(tool, param.input, {
80
+ verbose
81
+ });
82
+ if (tool.name === "TodoWrite") {
83
+ return /* @__PURE__ */ React.createElement(Text, { color }, toolMessage);
84
+ }
82
85
  if (React.isValidElement(toolMessage)) {
83
86
  return /* @__PURE__ */ React.createElement(Box, { flexDirection: "row" }, /* @__PURE__ */ React.createElement(Text, { color }, "("), toolMessage, /* @__PURE__ */ React.createElement(Text, { color }, ")"));
84
87
  }
85
88
  return /* @__PURE__ */ React.createElement(Text, { color }, "(", toolMessage, ")");
86
89
  })(), /* @__PURE__ */ React.createElement(Text, { color }, "\u2026"))),
87
- /* @__PURE__ */ React.createElement(Cost, { costUSD, durationMs, debug })
90
+ /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", alignItems: "flex-end" }, /* @__PURE__ */ React.createElement(Cost, { costUSD, durationMs, debug }), verbose && /* @__PURE__ */ React.createElement(Text, { dimColor: true }, formatTimestamp(Date.now()), modelId ? ` ${modelId}` : "", durationMs > 0 ? ` ${(durationMs / 1e3).toFixed(1)}s` : ""))
88
91
  );
89
92
  }
90
93
  export {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/components/messages/AssistantToolUseMessage.tsx"],
4
- "sourcesContent": ["import { Box, Text } from 'ink'\nimport React from 'react'\nimport { logError } from '@utils/log'\nimport { ToolUseBlockParam } from '@anthropic-ai/sdk/resources/index.mjs'\nimport { Tool } from '@tool'\nimport { Cost } from '@components/Cost'\nimport { ToolUseLoader } from '@components/ToolUseLoader'\nimport { getTheme } from '@utils/theme'\nimport { BLACK_CIRCLE } from '@constants/figures'\nimport { ThinkTool } from '@tools/ThinkTool/ThinkTool'\nimport { AssistantThinkingMessage } from './AssistantThinkingMessage'\nimport { TaskToolMessage } from './TaskToolMessage'\n\ntype Props = {\n param: ToolUseBlockParam\n costUSD: number\n durationMs: number\n addMargin: boolean\n tools: Tool[]\n debug: boolean\n verbose: boolean\n erroredToolUseIDs: Set<string>\n inProgressToolUseIDs: Set<string>\n unresolvedToolUseIDs: Set<string>\n shouldAnimate: boolean\n shouldShowDot: boolean\n}\n\nexport function AssistantToolUseMessage({\n param,\n costUSD,\n durationMs,\n addMargin,\n tools,\n debug,\n verbose,\n erroredToolUseIDs,\n inProgressToolUseIDs,\n unresolvedToolUseIDs,\n shouldAnimate,\n shouldShowDot,\n}: Props): React.ReactNode {\n const tool = tools.find(_ => _.name === param.name)\n if (!tool) {\n logError(`Tool ${param.name} not found`)\n return null\n }\n const isQueued =\n !inProgressToolUseIDs.has(param.id) && unresolvedToolUseIDs.has(param.id)\n // Keeping color undefined makes the OS use the default color regardless of appearance\n const color = isQueued ? getTheme().secondaryText : undefined\n\n // Handle thinking tool with specialized rendering\n if (tool === ThinkTool) {\n const { thought } = ThinkTool.inputSchema.parse(param.input)\n return (\n <AssistantThinkingMessage\n param={{ thinking: thought, signature: '', type: 'thinking' }}\n addMargin={addMargin}\n />\n )\n }\n\n const userFacingToolName = tool.userFacingName\n ? tool.userFacingName()\n : tool.name\n return (\n <Box\n flexDirection=\"row\"\n justifyContent=\"space-between\"\n marginTop={addMargin ? 1 : 0}\n width=\"100%\"\n >\n <Box>\n <Box\n flexWrap=\"nowrap\"\n minWidth={userFacingToolName.length + (shouldShowDot ? 2 : 0)}\n >\n {shouldShowDot &&\n (isQueued ? (\n <Box minWidth={2}>\n <Text color={color}>{BLACK_CIRCLE}</Text>\n </Box>\n ) : (\n <ToolUseLoader\n shouldAnimate={shouldAnimate}\n isUnresolved={unresolvedToolUseIDs.has(param.id)}\n isError={erroredToolUseIDs.has(param.id)}\n />\n ))}\n {tool.name === 'Task' && param.input ? (\n <TaskToolMessage\n agentType={String(\n (param.input as any).subagent_type || 'general-purpose',\n )}\n bold={Boolean(!isQueued)}\n children={String(userFacingToolName || '')}\n />\n ) : (\n <Text color={color} bold={!isQueued}>\n {userFacingToolName}\n </Text>\n )}\n </Box>\n <Box flexWrap=\"nowrap\">\n {Object.keys(param.input as { [key: string]: unknown }).length > 0 &&\n (() => {\n const toolMessage = tool.renderToolUseMessage(\n param.input as never,\n {\n verbose,\n },\n )\n\n // If the tool returns a React component, render it directly\n if (React.isValidElement(toolMessage)) {\n return (\n <Box flexDirection=\"row\">\n <Text color={color}>(</Text>\n {toolMessage}\n <Text color={color}>)</Text>\n </Box>\n )\n }\n\n // If it's a string, wrap it in Text\n return <Text color={color}>({toolMessage})</Text>\n })()}\n <Text color={color}>\u2026</Text>\n </Box>\n </Box>\n <Cost costUSD={costUSD} durationMs={durationMs} debug={debug} />\n </Box>\n )\n}\n"],
5
- "mappings": "AAAA,SAAS,KAAK,YAAY;AAC1B,OAAO,WAAW;AAClB,SAAS,gBAAgB;AAGzB,SAAS,YAAY;AACrB,SAAS,qBAAqB;AAC9B,SAAS,gBAAgB;AACzB,SAAS,oBAAoB;AAC7B,SAAS,iBAAiB;AAC1B,SAAS,gCAAgC;AACzC,SAAS,uBAAuB;AAiBzB,SAAS,wBAAwB;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA2B;AACzB,QAAM,OAAO,MAAM,KAAK,OAAK,EAAE,SAAS,MAAM,IAAI;AAClD,MAAI,CAAC,MAAM;AACT,aAAS,QAAQ,MAAM,IAAI,YAAY;AACvC,WAAO;AAAA,EACT;AACA,QAAM,WACJ,CAAC,qBAAqB,IAAI,MAAM,EAAE,KAAK,qBAAqB,IAAI,MAAM,EAAE;AAE1E,QAAM,QAAQ,WAAW,SAAS,EAAE,gBAAgB;AAGpD,MAAI,SAAS,WAAW;AACtB,UAAM,EAAE,QAAQ,IAAI,UAAU,YAAY,MAAM,MAAM,KAAK;AAC3D,WACE;AAAA,MAAC;AAAA;AAAA,QACC,OAAO,EAAE,UAAU,SAAS,WAAW,IAAI,MAAM,WAAW;AAAA,QAC5D;AAAA;AAAA,IACF;AAAA,EAEJ;AAEA,QAAM,qBAAqB,KAAK,iBAC5B,KAAK,eAAe,IACpB,KAAK;AACT,SACE;AAAA,IAAC;AAAA;AAAA,MACC,eAAc;AAAA,MACd,gBAAe;AAAA,MACf,WAAW,YAAY,IAAI;AAAA,MAC3B,OAAM;AAAA;AAAA,IAEN,oCAAC,WACC;AAAA,MAAC;AAAA;AAAA,QACC,UAAS;AAAA,QACT,UAAU,mBAAmB,UAAU,gBAAgB,IAAI;AAAA;AAAA,MAE1D,kBACE,WACC,oCAAC,OAAI,UAAU,KACb,oCAAC,QAAK,SAAe,YAAa,CACpC,IAEA;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA,cAAc,qBAAqB,IAAI,MAAM,EAAE;AAAA,UAC/C,SAAS,kBAAkB,IAAI,MAAM,EAAE;AAAA;AAAA,MACzC;AAAA,MAEH,KAAK,SAAS,UAAU,MAAM,QAC7B;AAAA,QAAC;AAAA;AAAA,UACC,WAAW;AAAA,YACR,MAAM,MAAc,iBAAiB;AAAA,UACxC;AAAA,UACA,MAAM,QAAQ,CAAC,QAAQ;AAAA,UACvB,UAAU,OAAO,sBAAsB,EAAE;AAAA;AAAA,MAC3C,IAEA,oCAAC,QAAK,OAAc,MAAM,CAAC,YACxB,kBACH;AAAA,IAEJ,GACA,oCAAC,OAAI,UAAS,YACX,OAAO,KAAK,MAAM,KAAmC,EAAE,SAAS,MAC9D,MAAM;AACL,YAAM,cAAc,KAAK;AAAA,QACvB,MAAM;AAAA,QACN;AAAA,UACE;AAAA,QACF;AAAA,MACF;AAGA,UAAI,MAAM,eAAe,WAAW,GAAG;AACrC,eACE,oCAAC,OAAI,eAAc,SACjB,oCAAC,QAAK,SAAc,GAAC,GACpB,aACD,oCAAC,QAAK,SAAc,GAAC,CACvB;AAAA,MAEJ;AAGA,aAAO,oCAAC,QAAK,SAAc,KAAE,aAAY,GAAC;AAAA,IAC5C,GAAG,GACL,oCAAC,QAAK,SAAc,QAAC,CACvB,CACF;AAAA,IACA,oCAAC,QAAK,SAAkB,YAAwB,OAAc;AAAA,EAChE;AAEJ;",
4
+ "sourcesContent": ["import { Box, Text } from 'ink'\nimport React from 'react'\nimport { logError } from '@utils/log'\nimport { ToolUseBlockParam } from '@anthropic-ai/sdk/resources/index.mjs'\nimport { Tool } from '@tool'\nimport { Cost } from '@components/Cost'\nimport { ToolUseLoader } from '@components/ToolUseLoader'\nimport { getTheme } from '@utils/theme'\nimport { BLACK_CIRCLE } from '@constants/figures'\nimport { ThinkTool } from '@tools/ThinkTool/ThinkTool'\nimport { AssistantThinkingMessage } from './AssistantThinkingMessage'\nimport { TaskToolMessage } from './TaskToolMessage'\nimport { safeRenderToolUseMessage } from '@utils/tooling/safeRender'\nimport { formatTimestamp } from '@utils/format'\n\ntype Props = {\n param: ToolUseBlockParam\n costUSD: number\n durationMs: number\n addMargin: boolean\n tools: Tool[]\n debug: boolean\n verbose: boolean\n erroredToolUseIDs: Set<string>\n inProgressToolUseIDs: Set<string>\n unresolvedToolUseIDs: Set<string>\n shouldAnimate: boolean\n shouldShowDot: boolean\n /** Model ID for verbose mode display */\n modelId?: string\n}\n\nexport function AssistantToolUseMessage({\n param,\n costUSD,\n durationMs,\n addMargin,\n tools,\n debug,\n verbose,\n erroredToolUseIDs,\n inProgressToolUseIDs,\n unresolvedToolUseIDs,\n shouldAnimate,\n shouldShowDot,\n modelId,\n}: Props): React.ReactNode {\n const tool = tools.find(_ => _.name === param.name)\n if (!tool) {\n logError(`Tool ${param.name} not found`)\n return null\n }\n const isQueued =\n !inProgressToolUseIDs.has(param.id) && unresolvedToolUseIDs.has(param.id)\n // Keeping color undefined makes the OS use the default color regardless of appearance\n const color = isQueued ? getTheme().secondaryText : undefined\n\n // Handle thinking tool with specialized rendering\n if (tool === ThinkTool) {\n const { thought } = ThinkTool.inputSchema.parse(param.input)\n return (\n <AssistantThinkingMessage\n param={{ thinking: thought, signature: '', type: 'thinking' }}\n addMargin={addMargin}\n />\n )\n }\n\n const userFacingToolName = tool.userFacingName\n ? tool.userFacingName()\n : tool.name\n return (\n <Box\n flexDirection=\"row\"\n justifyContent=\"space-between\"\n marginTop={addMargin ? 1 : 0}\n width=\"100%\"\n >\n <Box>\n <Box\n flexWrap=\"nowrap\"\n minWidth={userFacingToolName.length + (shouldShowDot ? 2 : 0)}\n >\n {shouldShowDot &&\n (isQueued ? (\n <Box minWidth={2}>\n <Text color={color}>{BLACK_CIRCLE}</Text>\n </Box>\n ) : (\n <ToolUseLoader\n shouldAnimate={shouldAnimate}\n isUnresolved={unresolvedToolUseIDs.has(param.id)}\n isError={erroredToolUseIDs.has(param.id)}\n />\n ))}\n {tool.name === 'Task' && param.input ? (\n <TaskToolMessage\n agentType={String(\n (param.input as any).subagent_type || 'general-purpose',\n )}\n bold={Boolean(!isQueued)}\n children={String(userFacingToolName || '')}\n />\n ) : (\n <Text color={color} bold={!isQueued}>\n {userFacingToolName}\n </Text>\n )}\n </Box>\n <Box flexWrap=\"nowrap\">\n {Object.keys(param.input as { [key: string]: unknown }).length > 0 &&\n (() => {\n const toolMessage = safeRenderToolUseMessage(tool, param.input, {\n verbose,\n })\n\n // TodoWriteTool: Special formatting - message already includes parentheses and formatting\n // Format: \" (1 running, 2 pending): taskName\" (note leading space, parens around stats only)\n if (tool.name === 'TodoWrite') {\n return <Text color={color}>{toolMessage}</Text>\n }\n\n // If the tool returns a React component, render it directly\n if (React.isValidElement(toolMessage)) {\n return (\n <Box flexDirection=\"row\">\n <Text color={color}>(</Text>\n {toolMessage}\n <Text color={color}>)</Text>\n </Box>\n )\n }\n\n // If it's a string, wrap it in Text\n return <Text color={color}>({toolMessage})</Text>\n })()}\n <Text color={color}>\u2026</Text>\n </Box>\n </Box>\n <Box flexDirection=\"column\" alignItems=\"flex-end\">\n <Cost costUSD={costUSD} durationMs={durationMs} debug={debug} />\n {/* Verbose mode: show timestamp, model, and tool ID */}\n {verbose && (\n <Text dimColor>\n {formatTimestamp(Date.now())}\n {modelId ? ` ${modelId}` : ''}\n {durationMs > 0 ? ` ${(durationMs / 1000).toFixed(1)}s` : ''}\n </Text>\n )}\n </Box>\n </Box>\n )\n}\n"],
5
+ "mappings": "AAAA,SAAS,KAAK,YAAY;AAC1B,OAAO,WAAW;AAClB,SAAS,gBAAgB;AAGzB,SAAS,YAAY;AACrB,SAAS,qBAAqB;AAC9B,SAAS,gBAAgB;AACzB,SAAS,oBAAoB;AAC7B,SAAS,iBAAiB;AAC1B,SAAS,gCAAgC;AACzC,SAAS,uBAAuB;AAChC,SAAS,gCAAgC;AACzC,SAAS,uBAAuB;AAmBzB,SAAS,wBAAwB;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA2B;AACzB,QAAM,OAAO,MAAM,KAAK,OAAK,EAAE,SAAS,MAAM,IAAI;AAClD,MAAI,CAAC,MAAM;AACT,aAAS,QAAQ,MAAM,IAAI,YAAY;AACvC,WAAO;AAAA,EACT;AACA,QAAM,WACJ,CAAC,qBAAqB,IAAI,MAAM,EAAE,KAAK,qBAAqB,IAAI,MAAM,EAAE;AAE1E,QAAM,QAAQ,WAAW,SAAS,EAAE,gBAAgB;AAGpD,MAAI,SAAS,WAAW;AACtB,UAAM,EAAE,QAAQ,IAAI,UAAU,YAAY,MAAM,MAAM,KAAK;AAC3D,WACE;AAAA,MAAC;AAAA;AAAA,QACC,OAAO,EAAE,UAAU,SAAS,WAAW,IAAI,MAAM,WAAW;AAAA,QAC5D;AAAA;AAAA,IACF;AAAA,EAEJ;AAEA,QAAM,qBAAqB,KAAK,iBAC5B,KAAK,eAAe,IACpB,KAAK;AACT,SACE;AAAA,IAAC;AAAA;AAAA,MACC,eAAc;AAAA,MACd,gBAAe;AAAA,MACf,WAAW,YAAY,IAAI;AAAA,MAC3B,OAAM;AAAA;AAAA,IAEN,oCAAC,WACC;AAAA,MAAC;AAAA;AAAA,QACC,UAAS;AAAA,QACT,UAAU,mBAAmB,UAAU,gBAAgB,IAAI;AAAA;AAAA,MAE1D,kBACE,WACC,oCAAC,OAAI,UAAU,KACb,oCAAC,QAAK,SAAe,YAAa,CACpC,IAEA;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA,cAAc,qBAAqB,IAAI,MAAM,EAAE;AAAA,UAC/C,SAAS,kBAAkB,IAAI,MAAM,EAAE;AAAA;AAAA,MACzC;AAAA,MAEH,KAAK,SAAS,UAAU,MAAM,QAC7B;AAAA,QAAC;AAAA;AAAA,UACC,WAAW;AAAA,YACR,MAAM,MAAc,iBAAiB;AAAA,UACxC;AAAA,UACA,MAAM,QAAQ,CAAC,QAAQ;AAAA,UACvB,UAAU,OAAO,sBAAsB,EAAE;AAAA;AAAA,MAC3C,IAEA,oCAAC,QAAK,OAAc,MAAM,CAAC,YACxB,kBACH;AAAA,IAEJ,GACA,oCAAC,OAAI,UAAS,YACX,OAAO,KAAK,MAAM,KAAmC,EAAE,SAAS,MAC9D,MAAM;AACL,YAAM,cAAc,yBAAyB,MAAM,MAAM,OAAO;AAAA,QAC9D;AAAA,MACF,CAAC;AAID,UAAI,KAAK,SAAS,aAAa;AAC7B,eAAO,oCAAC,QAAK,SAAe,WAAY;AAAA,MAC1C;AAGA,UAAI,MAAM,eAAe,WAAW,GAAG;AACrC,eACE,oCAAC,OAAI,eAAc,SACjB,oCAAC,QAAK,SAAc,GAAC,GACpB,aACD,oCAAC,QAAK,SAAc,GAAC,CACvB;AAAA,MAEJ;AAGA,aAAO,oCAAC,QAAK,SAAc,KAAE,aAAY,GAAC;AAAA,IAC5C,GAAG,GACL,oCAAC,QAAK,SAAc,QAAC,CACvB,CACF;AAAA,IACA,oCAAC,OAAI,eAAc,UAAS,YAAW,cACrC,oCAAC,QAAK,SAAkB,YAAwB,OAAc,GAE7D,WACC,oCAAC,QAAK,UAAQ,QACX,gBAAgB,KAAK,IAAI,CAAC,GAC1B,UAAU,KAAK,OAAO,KAAK,IAC3B,aAAa,IAAI,MAAM,aAAa,KAAM,QAAQ,CAAC,CAAC,MAAM,EAC7D,CAEJ;AAAA,EACF;AAEJ;",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,53 @@
1
+ import React from "react";
2
+ import { Box, Text } from "ink";
3
+ import { ParallelTasksGroupView } from "./ParallelTasksGroupView.js";
4
+ import { TaskInModuleView } from "./TaskInModuleView.js";
5
+ function GroupRenderer({
6
+ group,
7
+ context,
8
+ messages,
9
+ transcripts,
10
+ outputs
11
+ }) {
12
+ const { displayConfig, shouldAnimate, getTranscript } = context;
13
+ switch (group.type) {
14
+ case "parallel-tasks":
15
+ return /* @__PURE__ */ React.createElement(
16
+ ParallelTasksGroupView,
17
+ {
18
+ group,
19
+ messages,
20
+ transcripts,
21
+ outputs,
22
+ displayConfig,
23
+ shouldAnimate,
24
+ getTranscript
25
+ }
26
+ );
27
+ case "task": {
28
+ const toolUseId = group.metadata.toolUseId;
29
+ const agentId = group.metadata.agentId;
30
+ const transcript = agentId ? getTranscript?.(agentId) ?? transcripts.get(agentId) ?? null : null;
31
+ const output = outputs.get(toolUseId);
32
+ return /* @__PURE__ */ React.createElement(
33
+ TaskInModuleView,
34
+ {
35
+ toolUseId,
36
+ description: group.metadata.description || "Task",
37
+ agentType: group.metadata.agentType || "general-purpose",
38
+ transcript,
39
+ output: output || null,
40
+ config: displayConfig,
41
+ shouldAnimate,
42
+ inModule: false
43
+ }
44
+ );
45
+ }
46
+ default:
47
+ return /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, "[Unknown group type: ", group.type, "]"));
48
+ }
49
+ }
50
+ export {
51
+ GroupRenderer
52
+ };
53
+ //# sourceMappingURL=GroupRenderer.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/components/messages/GroupRenderer.tsx"],
4
+ "sourcesContent": ["/**\n * Group Renderer Component\n *\n * Dispatches rendering to specialized components based on group type.\n * Entry point for the V1+ hierarchical message display system.\n */\n\nimport React from 'react'\nimport { Box, Text } from 'ink'\nimport type {\n ToolResultBlockParam,\n ToolUseBlockParam,\n} from '@anthropic-ai/sdk/resources/index.mjs'\nimport type { MessageGroup, GroupContext } from '@minto-types/messageGroup'\nimport type { AgentTranscript } from '@utils/agentTranscripts'\nimport type { NormalizedMessage } from '@utils/messages'\nimport { ParallelTasksGroupView } from './ParallelTasksGroupView'\nimport { TaskInModuleView } from './TaskInModuleView'\n\ninterface Props {\n /** The group to render */\n group: MessageGroup\n /** Group rendering context */\n context: GroupContext\n /** Normalized messages */\n messages: NormalizedMessage[]\n /** Transcripts by agentId */\n transcripts: Map<string, AgentTranscript>\n /** Outputs by toolUseId */\n outputs: Map<string, ToolResultBlockParam>\n}\n\nexport function GroupRenderer({\n group,\n context,\n messages,\n transcripts,\n outputs,\n}: Props): React.ReactNode {\n const { displayConfig, shouldAnimate, getTranscript } = context\n\n switch (group.type) {\n case 'parallel-tasks':\n return (\n <ParallelTasksGroupView\n group={group}\n messages={messages}\n transcripts={transcripts}\n outputs={outputs}\n displayConfig={displayConfig}\n shouldAnimate={shouldAnimate}\n getTranscript={getTranscript}\n />\n )\n\n case 'task': {\n const toolUseId = group.metadata.toolUseId as string\n const agentId = group.metadata.agentId as string | undefined\n // Use getTranscript for lazy loading from disk (essential for historical messages)\n const transcript = agentId\n ? (getTranscript?.(agentId) ?? transcripts.get(agentId) ?? null)\n : null\n const output = outputs.get(toolUseId)\n\n return (\n <TaskInModuleView\n toolUseId={toolUseId}\n description={group.metadata.description || 'Task'}\n agentType={group.metadata.agentType || 'general-purpose'}\n transcript={transcript}\n output={output || null}\n config={displayConfig}\n shouldAnimate={shouldAnimate}\n inModule={false}\n />\n )\n }\n\n default:\n // Unknown type: render a simple placeholder\n return (\n <Box>\n <Text dimColor>[Unknown group type: {group.type}]</Text>\n </Box>\n )\n }\n}\n"],
5
+ "mappings": "AAOA,OAAO,WAAW;AAClB,SAAS,KAAK,YAAY;AAQ1B,SAAS,8BAA8B;AACvC,SAAS,wBAAwB;AAe1B,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA2B;AACzB,QAAM,EAAE,eAAe,eAAe,cAAc,IAAI;AAExD,UAAQ,MAAM,MAAM;AAAA,IAClB,KAAK;AACH,aACE;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA;AAAA,MACF;AAAA,IAGJ,KAAK,QAAQ;AACX,YAAM,YAAY,MAAM,SAAS;AACjC,YAAM,UAAU,MAAM,SAAS;AAE/B,YAAM,aAAa,UACd,gBAAgB,OAAO,KAAK,YAAY,IAAI,OAAO,KAAK,OACzD;AACJ,YAAM,SAAS,QAAQ,IAAI,SAAS;AAEpC,aACE;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA,aAAa,MAAM,SAAS,eAAe;AAAA,UAC3C,WAAW,MAAM,SAAS,aAAa;AAAA,UACvC;AAAA,UACA,QAAQ,UAAU;AAAA,UAClB,QAAQ;AAAA,UACR;AAAA,UACA,UAAU;AAAA;AAAA,MACZ;AAAA,IAEJ;AAAA,IAEA;AAEE,aACE,oCAAC,WACC,oCAAC,QAAK,UAAQ,QAAC,yBAAsB,MAAM,MAAK,GAAC,CACnD;AAAA,EAEN;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,12 @@
1
+ import React from "react";
2
+ import { Box, Text } from "ink";
3
+ function NestedTasksPreview({
4
+ tasks,
5
+ hiddenCount
6
+ }) {
7
+ return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, hiddenCount > 0 && /* @__PURE__ */ React.createElement(Text, { dimColor: true }, "\xB7\xB7\xB7 ", hiddenCount, " earlier tasks hidden \xB7\xB7\xB7"), tasks.map((child, i) => /* @__PURE__ */ React.createElement(Box, { key: i, flexDirection: "column" }, /* @__PURE__ */ React.createElement(Text, null, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, child.status === "completed" ? "\u2713" : "\u22EF", " "), /* @__PURE__ */ React.createElement(Text, null, child.description)), child.content && /* @__PURE__ */ React.createElement(Box, { marginLeft: 2 }, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, child.content)))));
8
+ }
9
+ export {
10
+ NestedTasksPreview
11
+ };
12
+ //# sourceMappingURL=NestedTasksPreview.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/components/messages/NestedTasksPreview.tsx"],
4
+ "sourcesContent": ["/**\n * Nested Tasks Preview Component\n *\n * Displays a preview of nested/child tasks with status and content.\n * Used for intermediate state display during task execution.\n */\n\nimport React from 'react'\nimport { Box, Text } from 'ink'\n\ninterface NestedTaskChild {\n description: string\n status: string\n content: string\n}\n\ninterface Props {\n tasks: NestedTaskChild[]\n hiddenCount: number\n}\n\nexport function NestedTasksPreview({\n tasks,\n hiddenCount,\n}: Props): React.ReactNode {\n return (\n <Box flexDirection=\"column\">\n {/* Hidden tasks indicator */}\n {hiddenCount > 0 && (\n <Text dimColor>\u00B7\u00B7\u00B7 {hiddenCount} earlier tasks hidden \u00B7\u00B7\u00B7</Text>\n )}\n\n {/* Visible nested tasks */}\n {tasks.map((child, i) => (\n <Box key={i} flexDirection=\"column\">\n <Text>\n <Text dimColor>{child.status === 'completed' ? '\u2713' : '\u22EF'} </Text>\n <Text>{child.description}</Text>\n </Text>\n {child.content && (\n <Box marginLeft={2}>\n <Text dimColor>{child.content}</Text>\n </Box>\n )}\n </Box>\n ))}\n </Box>\n )\n}\n"],
5
+ "mappings": "AAOA,OAAO,WAAW;AAClB,SAAS,KAAK,YAAY;AAanB,SAAS,mBAAmB;AAAA,EACjC;AAAA,EACA;AACF,GAA2B;AACzB,SACE,oCAAC,OAAI,eAAc,YAEhB,cAAc,KACb,oCAAC,QAAK,UAAQ,QAAC,iBAAK,aAAY,oCAAyB,GAI1D,MAAM,IAAI,CAAC,OAAO,MACjB,oCAAC,OAAI,KAAK,GAAG,eAAc,YACzB,oCAAC,YACC,oCAAC,QAAK,UAAQ,QAAE,MAAM,WAAW,cAAc,WAAM,UAAI,GAAC,GAC1D,oCAAC,YAAM,MAAM,WAAY,CAC3B,GACC,MAAM,WACL,oCAAC,OAAI,YAAY,KACf,oCAAC,QAAK,UAAQ,QAAE,MAAM,OAAQ,CAChC,CAEJ,CACD,CACH;AAEJ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,92 @@
1
+ import React from "react";
2
+ import { Box, Text } from "ink";
3
+ import { TreeConnector } from "../TreeConnector.js";
4
+ import { CollapsibleHint } from "../CollapsibleHint.js";
5
+ import { TaskInModuleView } from "./TaskInModuleView.js";
6
+ import { ParallelTasksHandler } from "../../utils/groupHandlers/parallelTasksHandler.js";
7
+ import { MARGIN_BEFORE_MODULE, INDENT_LEVELS } from "../../constants/formatRules.js";
8
+ import { SYMBOLS } from "../../constants/symbols.js";
9
+ import {
10
+ SEMANTIC_COLORS,
11
+ VALUE_TIER_COLORS
12
+ } from "../../constants/colors.js";
13
+ import { formatMetaInfo } from "../../utils/taskDisplayUtils.js";
14
+ function ParallelTasksGroupView({
15
+ group,
16
+ messages,
17
+ transcripts,
18
+ outputs,
19
+ displayConfig,
20
+ shouldAnimate,
21
+ getTranscript
22
+ }) {
23
+ const memberIds = group.metadata.siblingToolUseIds || [];
24
+ const getTranscriptForAgent = (agentId) => {
25
+ return getTranscript?.(agentId) ?? transcripts.get(agentId) ?? null;
26
+ };
27
+ const memberInfos = ParallelTasksHandler.getMemberTaskInfo(group, messages);
28
+ const completedCount = memberInfos.filter((info) => {
29
+ const output = outputs.get(info.toolUseId);
30
+ if (output) return true;
31
+ if (!info.agentId) return false;
32
+ const transcript = getTranscriptForAgent(info.agentId);
33
+ return transcript?.status === "completed";
34
+ }).length;
35
+ const totalCount = memberInfos.length;
36
+ const isCompleted = completedCount === totalCount && totalCount > 0;
37
+ const statusColor = isCompleted ? SEMANTIC_COLORS.success : group.status === "running" ? SEMANTIC_COLORS.running : SEMANTIC_COLORS.dim;
38
+ const groupSymbol = isCompleted ? SYMBOLS.TOOL_SUCCESS : SYMBOLS.PARALLEL_GROUP;
39
+ const groupMetaInfo = (() => {
40
+ if (!isCompleted) return null;
41
+ const completedTranscripts = [];
42
+ for (const info of memberInfos) {
43
+ if (info.agentId) {
44
+ const transcript = getTranscriptForAgent(info.agentId);
45
+ if (transcript?.endTime) {
46
+ completedTranscripts.push(transcript);
47
+ }
48
+ }
49
+ }
50
+ if (completedTranscripts.length === 0) return null;
51
+ const startTimes = completedTranscripts.map((t) => t.startTime);
52
+ const endTimes = completedTranscripts.map((t) => t.endTime);
53
+ const earliestStart = Math.min(...startTimes);
54
+ const latestEnd = Math.max(...endTimes);
55
+ const totalDuration = latestEnd - earliestStart;
56
+ return {
57
+ duration: totalDuration,
58
+ timestamp: latestEnd
59
+ };
60
+ })();
61
+ return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", width: "100%", marginTop: MARGIN_BEFORE_MODULE }, /* @__PURE__ */ React.createElement(Box, { flexDirection: "row" }, /* @__PURE__ */ React.createElement(Text, { color: statusColor }, groupSymbol, " "), /* @__PURE__ */ React.createElement(Text, { bold: true, color: SEMANTIC_COLORS.secondary }, "Parallel Tasks"), /* @__PURE__ */ React.createElement(Text, null, " "), /* @__PURE__ */ React.createElement(Text, null, "("), /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.success }, completedCount), /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.dim }, "/", totalCount), /* @__PURE__ */ React.createElement(Text, null, " finished)"), displayConfig.showMetaInfo && groupMetaInfo && /* @__PURE__ */ React.createElement(Text, { color: VALUE_TIER_COLORS.meta }, " ", formatMetaInfo({
62
+ duration: groupMetaInfo.duration,
63
+ timestamp: groupMetaInfo.timestamp
64
+ })), /* @__PURE__ */ React.createElement(
65
+ CollapsibleHint,
66
+ {
67
+ canExpand: isCompleted && !displayConfig.showAllChildren
68
+ }
69
+ )), /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", marginLeft: INDENT_LEVELS.L1 }, memberInfos.map((info, index) => {
70
+ const isLast = index === memberInfos.length - 1;
71
+ const transcript = info.agentId ? getTranscriptForAgent(info.agentId) : null;
72
+ const output = outputs.get(info.toolUseId);
73
+ return /* @__PURE__ */ React.createElement(Box, { key: info.toolUseId, flexDirection: "row" }, /* @__PURE__ */ React.createElement(TreeConnector, { isLast }), /* @__PURE__ */ React.createElement(
74
+ TaskInModuleView,
75
+ {
76
+ toolUseId: info.toolUseId,
77
+ description: info.description,
78
+ agentType: info.agentType,
79
+ transcript,
80
+ output: output || null,
81
+ config: displayConfig,
82
+ shouldAnimate,
83
+ inModule: true,
84
+ isLastInModule: isLast
85
+ }
86
+ ));
87
+ })));
88
+ }
89
+ export {
90
+ ParallelTasksGroupView
91
+ };
92
+ //# sourceMappingURL=ParallelTasksGroupView.js.map