@within-7/minto 0.4.0 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (391) hide show
  1. package/dist/Tool.js +7 -0
  2. package/dist/Tool.js.map +2 -2
  3. package/dist/commands/agents/AgentsCommand.js +1 -1
  4. package/dist/commands/agents/AgentsCommand.js.map +2 -2
  5. package/dist/commands/agents/constants.js +2 -2
  6. package/dist/commands/agents/constants.js.map +2 -2
  7. package/dist/commands/clear.js +4 -3
  8. package/dist/commands/clear.js.map +2 -2
  9. package/dist/commands/compact.js +2 -2
  10. package/dist/commands/compact.js.map +1 -1
  11. package/dist/commands/context.js +3 -1
  12. package/dist/commands/context.js.map +2 -2
  13. package/dist/commands/login.js +128 -0
  14. package/dist/commands/login.js.map +7 -0
  15. package/dist/commands/memory.js +33 -82
  16. package/dist/commands/memory.js.map +2 -2
  17. package/dist/commands/quit.js +3 -1
  18. package/dist/commands/quit.js.map +2 -2
  19. package/dist/commands/resume.js +39 -239
  20. package/dist/commands/resume.js.map +2 -2
  21. package/dist/commands/tasks.js +1 -1
  22. package/dist/commands/tasks.js.map +2 -2
  23. package/dist/commands/terminalSetup.js +6 -2
  24. package/dist/commands/terminalSetup.js.map +2 -2
  25. package/dist/commands.js +2 -0
  26. package/dist/commands.js.map +2 -2
  27. package/dist/components/AgentDetailView.js +126 -0
  28. package/dist/components/AgentDetailView.js.map +7 -0
  29. package/dist/components/AgentThinkingBlock.js +1 -1
  30. package/dist/components/AgentThinkingBlock.js.map +2 -2
  31. package/dist/components/AgentViewBanner.js +22 -0
  32. package/dist/components/AgentViewBanner.js.map +7 -0
  33. package/dist/components/HeaderBar.js +1 -1
  34. package/dist/components/HeaderBar.js.map +2 -2
  35. package/dist/components/Help.js +8 -1
  36. package/dist/components/Help.js.map +2 -2
  37. package/dist/components/HotkeyHelpPanel.js +26 -8
  38. package/dist/components/HotkeyHelpPanel.js.map +2 -2
  39. package/dist/components/IdleNotificationBar.js +10 -0
  40. package/dist/components/IdleNotificationBar.js.map +7 -0
  41. package/dist/components/ModelSelector/ModelSelector.js +55 -20
  42. package/dist/components/ModelSelector/ModelSelector.js.map +2 -2
  43. package/dist/components/PromptInput.js +186 -115
  44. package/dist/components/PromptInput.js.map +2 -2
  45. package/dist/components/RewindPanel.js +272 -0
  46. package/dist/components/RewindPanel.js.map +7 -0
  47. package/dist/components/Spinner.js +10 -21
  48. package/dist/components/Spinner.js.map +2 -2
  49. package/dist/components/StreamingTextPreview.js +29 -0
  50. package/dist/components/StreamingTextPreview.js.map +7 -0
  51. package/dist/components/SubagentBlock.js +3 -2
  52. package/dist/components/SubagentBlock.js.map +2 -2
  53. package/dist/components/SubagentProgress.js +4 -4
  54. package/dist/components/SubagentProgress.js.map +2 -2
  55. package/dist/components/TabbedListView/SearchInput.js +1 -1
  56. package/dist/components/TabbedListView/SearchInput.js.map +2 -2
  57. package/dist/components/TabbedListView/TabbedListView.js +87 -41
  58. package/dist/components/TabbedListView/TabbedListView.js.map +2 -2
  59. package/dist/components/TaskCard.js +4 -4
  60. package/dist/components/TaskCard.js.map +2 -2
  61. package/dist/components/TeamMemberPanel.js +107 -0
  62. package/dist/components/TeamMemberPanel.js.map +7 -0
  63. package/dist/components/ThinkingSelector.js +84 -0
  64. package/dist/components/ThinkingSelector.js.map +7 -0
  65. package/dist/components/TitledDivider.js +26 -0
  66. package/dist/components/TitledDivider.js.map +7 -0
  67. package/dist/components/TodoPanel.js +31 -30
  68. package/dist/components/TodoPanel.js.map +2 -2
  69. package/dist/components/TokenWarning.js +28 -7
  70. package/dist/components/TokenWarning.js.map +2 -2
  71. package/dist/components/messages/AssistantTextMessage.js +5 -2
  72. package/dist/components/messages/AssistantTextMessage.js.map +2 -2
  73. package/dist/components/messages/AssistantToolUseMessage.js +9 -1
  74. package/dist/components/messages/AssistantToolUseMessage.js.map +2 -2
  75. package/dist/components/messages/DefaultToolResultFallback.js +11 -0
  76. package/dist/components/messages/DefaultToolResultFallback.js.map +7 -0
  77. package/dist/components/messages/ParallelTasksGroupView.js +14 -6
  78. package/dist/components/messages/ParallelTasksGroupView.js.map +2 -2
  79. package/dist/components/messages/TaskInModuleView.js +27 -27
  80. package/dist/components/messages/TaskInModuleView.js.map +2 -2
  81. package/dist/components/messages/UserGuidanceMessage.js +26 -0
  82. package/dist/components/messages/UserGuidanceMessage.js.map +7 -0
  83. package/dist/components/messages/UserPromptMessage.js +2 -1
  84. package/dist/components/messages/UserPromptMessage.js.map +2 -2
  85. package/dist/components/messages/UserTeamNotificationMessage.js +91 -0
  86. package/dist/components/messages/UserTeamNotificationMessage.js.map +7 -0
  87. package/dist/components/messages/UserTextMessage.js +8 -0
  88. package/dist/components/messages/UserTextMessage.js.map +2 -2
  89. package/dist/components/messages/UserToolResultMessage/UserToolRejectMessage.js +4 -2
  90. package/dist/components/messages/UserToolResultMessage/UserToolRejectMessage.js.map +2 -2
  91. package/dist/components/messages/UserToolResultMessage/UserToolResultMessage.js +18 -1
  92. package/dist/components/messages/UserToolResultMessage/UserToolResultMessage.js.map +2 -2
  93. package/dist/components/messages/UserToolResultMessage/UserToolSuccessMessage.js +12 -1
  94. package/dist/components/messages/UserToolResultMessage/UserToolSuccessMessage.js.map +2 -2
  95. package/dist/components/permissions/PermissionRequest.js +4 -0
  96. package/dist/components/permissions/PermissionRequest.js.map +2 -2
  97. package/dist/components/permissions/PlanApprovalRequest.js +164 -0
  98. package/dist/components/permissions/PlanApprovalRequest.js.map +7 -0
  99. package/dist/constants/agentTeams.js +17 -0
  100. package/dist/constants/agentTeams.js.map +7 -0
  101. package/dist/constants/macros.js +2 -1
  102. package/dist/constants/macros.js.map +2 -2
  103. package/dist/constants/prompts/agentPrompt.js +1 -0
  104. package/dist/constants/prompts/agentPrompt.js.map +2 -2
  105. package/dist/constants/prompts/autoMemory.js +39 -0
  106. package/dist/constants/prompts/autoMemory.js.map +7 -0
  107. package/dist/constants/prompts/codeConventions.js +1 -13
  108. package/dist/constants/prompts/codeConventions.js.map +2 -2
  109. package/dist/constants/prompts/doingTasks.js +21 -2
  110. package/dist/constants/prompts/doingTasks.js.map +2 -2
  111. package/dist/constants/prompts/envInfo.js +6 -7
  112. package/dist/constants/prompts/envInfo.js.map +2 -2
  113. package/dist/constants/prompts/index.js +27 -5
  114. package/dist/constants/prompts/index.js.map +2 -2
  115. package/dist/constants/prompts/taskManagement.js +2 -43
  116. package/dist/constants/prompts/taskManagement.js.map +2 -2
  117. package/dist/constants/prompts/teamOverlays.js +50 -0
  118. package/dist/constants/prompts/teamOverlays.js.map +7 -0
  119. package/dist/constants/prompts/toneAndStyle.js +4 -29
  120. package/dist/constants/prompts/toneAndStyle.js.map +2 -2
  121. package/dist/constants/prompts/toolUsagePolicy.js +7 -22
  122. package/dist/constants/prompts/toolUsagePolicy.js.map +2 -2
  123. package/dist/constants/toolInputExamples.js +2 -2
  124. package/dist/constants/toolInputExamples.js.map +2 -2
  125. package/dist/context.js +39 -6
  126. package/dist/context.js.map +2 -2
  127. package/dist/core/backupManager.js +1 -1
  128. package/dist/core/backupManager.js.map +2 -2
  129. package/dist/core/permissions/rules/planModeRule.js +1 -1
  130. package/dist/core/permissions/rules/planModeRule.js.map +1 -1
  131. package/dist/core/permissions/rules/safeModeRule.js +1 -1
  132. package/dist/core/permissions/rules/safeModeRule.js.map +1 -1
  133. package/dist/engine/AgentEngine.js +902 -0
  134. package/dist/engine/AgentEngine.js.map +7 -0
  135. package/dist/engine/EngineRegistry.js +89 -0
  136. package/dist/engine/EngineRegistry.js.map +7 -0
  137. package/dist/engine/foregroundAdapter.js +191 -0
  138. package/dist/engine/foregroundAdapter.js.map +7 -0
  139. package/dist/engine/index.js +15 -0
  140. package/dist/engine/index.js.map +7 -0
  141. package/dist/engine/types.js +1 -0
  142. package/dist/engine/types.js.map +7 -0
  143. package/dist/entrypoints/cli.js +410 -79
  144. package/dist/entrypoints/cli.js.map +3 -3
  145. package/dist/hooks/useAgentEngine.js +129 -0
  146. package/dist/hooks/useAgentEngine.js.map +7 -0
  147. package/dist/hooks/useAgentTokenStats.js +0 -16
  148. package/dist/hooks/useAgentTokenStats.js.map +2 -2
  149. package/dist/hooks/useCanUseTool.js +47 -2
  150. package/dist/hooks/useCanUseTool.js.map +2 -2
  151. package/dist/hooks/useDeferredLoading.js +4 -1
  152. package/dist/hooks/useDeferredLoading.js.map +2 -2
  153. package/dist/hooks/useIdleNotifications.js +66 -0
  154. package/dist/hooks/useIdleNotifications.js.map +7 -0
  155. package/dist/hooks/useSessionTracking.js +9 -7
  156. package/dist/hooks/useSessionTracking.js.map +2 -2
  157. package/dist/hooks/useTeamMembers.js +51 -0
  158. package/dist/hooks/useTeamMembers.js.map +7 -0
  159. package/dist/i18n/locales/en.js +77 -12
  160. package/dist/i18n/locales/en.js.map +2 -2
  161. package/dist/i18n/locales/zh-CN.js +77 -12
  162. package/dist/i18n/locales/zh-CN.js.map +2 -2
  163. package/dist/i18n/types.js.map +1 -1
  164. package/dist/messages.js.map +2 -2
  165. package/dist/permissions.js +113 -7
  166. package/dist/permissions.js.map +2 -2
  167. package/dist/query.js +135 -37
  168. package/dist/query.js.map +2 -2
  169. package/dist/screens/REPL.js +504 -361
  170. package/dist/screens/REPL.js.map +3 -3
  171. package/dist/screens/ResumeConversation.js +199 -14
  172. package/dist/screens/ResumeConversation.js.map +2 -2
  173. package/dist/services/adapters/base.js.map +1 -1
  174. package/dist/services/agentTeams/backends/headless.js +108 -0
  175. package/dist/services/agentTeams/backends/headless.js.map +7 -0
  176. package/dist/services/agentTeams/backends/inProcess.js +102 -0
  177. package/dist/services/agentTeams/backends/inProcess.js.map +7 -0
  178. package/dist/services/agentTeams/backends/resolver.js +18 -0
  179. package/dist/services/agentTeams/backends/resolver.js.map +7 -0
  180. package/dist/services/agentTeams/backends/tmux.js +168 -0
  181. package/dist/services/agentTeams/backends/tmux.js.map +7 -0
  182. package/dist/services/agentTeams/backends/types.js +1 -0
  183. package/dist/services/agentTeams/backends/types.js.map +7 -0
  184. package/dist/services/agentTeams/heartbeat.js +88 -0
  185. package/dist/services/agentTeams/heartbeat.js.map +7 -0
  186. package/dist/services/agentTeams/index.js +42 -2
  187. package/dist/services/agentTeams/index.js.map +2 -2
  188. package/dist/services/agentTeams/injectionChannel.js +105 -0
  189. package/dist/services/agentTeams/injectionChannel.js.map +7 -0
  190. package/dist/services/agentTeams/mailbox.js +410 -30
  191. package/dist/services/agentTeams/mailbox.js.map +2 -2
  192. package/dist/services/agentTeams/messageFormatter.js +80 -0
  193. package/dist/services/agentTeams/messageFormatter.js.map +7 -0
  194. package/dist/services/agentTeams/permissionDelegation.js +71 -0
  195. package/dist/services/agentTeams/permissionDelegation.js.map +7 -0
  196. package/dist/services/agentTeams/teamEvents.js +45 -0
  197. package/dist/services/agentTeams/teamEvents.js.map +7 -0
  198. package/dist/services/agentTeams/teamManager.js +251 -34
  199. package/dist/services/agentTeams/teamManager.js.map +2 -2
  200. package/dist/services/agentTeams/teamTaskStore.js +290 -61
  201. package/dist/services/agentTeams/teamTaskStore.js.map +2 -2
  202. package/dist/services/agentTeams/teammateSpawner.js +99 -18
  203. package/dist/services/agentTeams/teammateSpawner.js.map +2 -2
  204. package/dist/services/hookExecutor.js +51 -8
  205. package/dist/services/hookExecutor.js.map +2 -2
  206. package/dist/services/llm/anthropicProvider.js +56 -59
  207. package/dist/services/llm/anthropicProvider.js.map +2 -2
  208. package/dist/services/llm/dispatch.js +24 -5
  209. package/dist/services/llm/dispatch.js.map +2 -2
  210. package/dist/services/llm/openaiProvider.js +115 -136
  211. package/dist/services/llm/openaiProvider.js.map +3 -3
  212. package/dist/services/llm/types.js +89 -15
  213. package/dist/services/llm/types.js.map +2 -2
  214. package/dist/services/mcpClient.js +80 -4
  215. package/dist/services/mcpClient.js.map +2 -2
  216. package/dist/services/mintoAuth.js +299 -0
  217. package/dist/services/mintoAuth.js.map +7 -0
  218. package/dist/services/oauth.js +3 -3
  219. package/dist/services/oauth.js.map +2 -2
  220. package/dist/services/openai.js +91 -20
  221. package/dist/services/openai.js.map +2 -2
  222. package/dist/services/plugins/pluginRuntime.js +11 -5
  223. package/dist/services/plugins/pluginRuntime.js.map +2 -2
  224. package/dist/services/plugins/pluginValidation.js +4 -2
  225. package/dist/services/plugins/pluginValidation.js.map +2 -2
  226. package/dist/services/sandbox/sandboxController.js +11 -3
  227. package/dist/services/sandbox/sandboxController.js.map +2 -2
  228. package/dist/services/sessionMemoryInjector.js +77 -0
  229. package/dist/services/sessionMemoryInjector.js.map +7 -0
  230. package/dist/services/systemReminder.js +130 -8
  231. package/dist/services/systemReminder.js.map +2 -2
  232. package/dist/services/taskStore.js +199 -8
  233. package/dist/services/taskStore.js.map +3 -3
  234. package/dist/services/topicDetector.js +169 -0
  235. package/dist/services/topicDetector.js.map +7 -0
  236. package/dist/tools/AskExpertModelTool/AskExpertModelTool.js +0 -13
  237. package/dist/tools/AskExpertModelTool/AskExpertModelTool.js.map +2 -2
  238. package/dist/tools/BashTool/BashTool.js +51 -28
  239. package/dist/tools/BashTool/BashTool.js.map +2 -2
  240. package/dist/tools/BashTool/prompt.js +95 -118
  241. package/dist/tools/BashTool/prompt.js.map +2 -2
  242. package/dist/tools/BashTool/utils.js +39 -1
  243. package/dist/tools/BashTool/utils.js.map +2 -2
  244. package/dist/tools/EnterWorktreeTool/EnterWorktreeTool.js +121 -0
  245. package/dist/tools/EnterWorktreeTool/EnterWorktreeTool.js.map +7 -0
  246. package/dist/tools/EnterWorktreeTool/prompt.js +22 -0
  247. package/dist/tools/EnterWorktreeTool/prompt.js.map +7 -0
  248. package/dist/tools/FileEditTool/FileEditTool.js +9 -4
  249. package/dist/tools/FileEditTool/FileEditTool.js.map +2 -2
  250. package/dist/tools/FileEditTool/prompt.js +3 -7
  251. package/dist/tools/FileEditTool/prompt.js.map +2 -2
  252. package/dist/tools/FileReadTool/FileReadTool.js +125 -3
  253. package/dist/tools/FileReadTool/FileReadTool.js.map +2 -2
  254. package/dist/tools/FileReadTool/prompt.js +1 -2
  255. package/dist/tools/FileReadTool/prompt.js.map +2 -2
  256. package/dist/tools/FileWriteTool/prompt.js +3 -5
  257. package/dist/tools/FileWriteTool/prompt.js.map +2 -2
  258. package/dist/tools/GlobTool/GlobTool.js +3 -2
  259. package/dist/tools/GlobTool/GlobTool.js.map +2 -2
  260. package/dist/tools/GrepTool/GrepTool.js +16 -5
  261. package/dist/tools/GrepTool/GrepTool.js.map +2 -2
  262. package/dist/tools/ListMcpResourcesTool/ListMcpResourcesTool.js.map +2 -2
  263. package/dist/tools/MCPSearchTool/MCPSearchTool.js +172 -0
  264. package/dist/tools/MCPSearchTool/MCPSearchTool.js.map +7 -0
  265. package/dist/tools/MCPSearchTool/prompt.js +77 -0
  266. package/dist/tools/MCPSearchTool/prompt.js.map +7 -0
  267. package/dist/tools/MultiEditTool/prompt.js +4 -7
  268. package/dist/tools/MultiEditTool/prompt.js.map +2 -2
  269. package/dist/tools/PlanModeTool/EnterPlanModeTool.js +12 -8
  270. package/dist/tools/PlanModeTool/EnterPlanModeTool.js.map +2 -2
  271. package/dist/tools/PlanModeTool/ExitPlanModeTool.js +54 -1
  272. package/dist/tools/PlanModeTool/ExitPlanModeTool.js.map +2 -2
  273. package/dist/tools/PlanModeTool/prompt.js +23 -74
  274. package/dist/tools/PlanModeTool/prompt.js.map +2 -2
  275. package/dist/tools/SendMessageTool/SendMessageTool.js +341 -0
  276. package/dist/tools/SendMessageTool/SendMessageTool.js.map +7 -0
  277. package/dist/tools/SendMessageTool/prompt.js +44 -0
  278. package/dist/tools/SendMessageTool/prompt.js.map +7 -0
  279. package/dist/tools/TaskCreateTool/prompt.js +15 -4
  280. package/dist/tools/TaskCreateTool/prompt.js.map +2 -2
  281. package/dist/tools/TaskListTool/prompt.js +18 -3
  282. package/dist/tools/TaskListTool/prompt.js.map +2 -2
  283. package/dist/tools/TaskOutputTool/prompt.js +4 -3
  284. package/dist/tools/TaskOutputTool/prompt.js.map +2 -2
  285. package/dist/tools/TaskTool/TaskTool.js +762 -98
  286. package/dist/tools/TaskTool/TaskTool.js.map +3 -3
  287. package/dist/tools/TaskTool/constants.js +8 -2
  288. package/dist/tools/TaskTool/constants.js.map +2 -2
  289. package/dist/tools/TaskTool/prompt.js +74 -70
  290. package/dist/tools/TaskTool/prompt.js.map +2 -2
  291. package/dist/tools/TaskUpdateTool/TaskUpdateTool.js +15 -1
  292. package/dist/tools/TaskUpdateTool/TaskUpdateTool.js.map +2 -2
  293. package/dist/tools/TeamCreateTool/TeamCreateTool.js +129 -0
  294. package/dist/tools/TeamCreateTool/TeamCreateTool.js.map +7 -0
  295. package/dist/tools/TeamCreateTool/prompt.js +58 -0
  296. package/dist/tools/TeamCreateTool/prompt.js.map +7 -0
  297. package/dist/tools/TeamDeleteTool/TeamDeleteTool.js +151 -0
  298. package/dist/tools/TeamDeleteTool/TeamDeleteTool.js.map +7 -0
  299. package/dist/tools/TeamDeleteTool/prompt.js +16 -0
  300. package/dist/tools/TeamDeleteTool/prompt.js.map +7 -0
  301. package/dist/tools/URLFetcherTool/URLFetcherTool.js +106 -15
  302. package/dist/tools/URLFetcherTool/URLFetcherTool.js.map +2 -2
  303. package/dist/tools/URLFetcherTool/prompt.js +3 -2
  304. package/dist/tools/URLFetcherTool/prompt.js.map +2 -2
  305. package/dist/tools/WebSearchTool/WebSearchTool.js +2 -1
  306. package/dist/tools/WebSearchTool/WebSearchTool.js.map +2 -2
  307. package/dist/tools/WebSearchTool/prompt.js +5 -4
  308. package/dist/tools/WebSearchTool/prompt.js.map +2 -2
  309. package/dist/tools.js +100 -20
  310. package/dist/tools.js.map +2 -2
  311. package/dist/types/PermissionMode.js +35 -6
  312. package/dist/types/PermissionMode.js.map +2 -2
  313. package/dist/types/hooks.js +2 -0
  314. package/dist/types/hooks.js.map +2 -2
  315. package/dist/types/plugin.js +2 -0
  316. package/dist/types/plugin.js.map +3 -3
  317. package/dist/utils/CircuitBreaker.js +15 -9
  318. package/dist/utils/CircuitBreaker.js.map +2 -2
  319. package/dist/utils/agentLoader.js +249 -112
  320. package/dist/utils/agentLoader.js.map +2 -2
  321. package/dist/utils/animationManager.js +40 -3
  322. package/dist/utils/animationManager.js.map +2 -2
  323. package/dist/utils/ask.js +7 -6
  324. package/dist/utils/ask.js.map +2 -2
  325. package/dist/utils/atomicWrite.js +23 -0
  326. package/dist/utils/atomicWrite.js.map +7 -0
  327. package/dist/utils/autoCompactCore.js +73 -56
  328. package/dist/utils/autoCompactCore.js.map +2 -2
  329. package/dist/utils/autoMemoryPaths.js +89 -0
  330. package/dist/utils/autoMemoryPaths.js.map +7 -0
  331. package/dist/utils/config.js +63 -38
  332. package/dist/utils/config.js.map +2 -2
  333. package/dist/utils/configSchema.js +13 -8
  334. package/dist/utils/configSchema.js.map +2 -2
  335. package/dist/utils/credentials/index.js +14 -0
  336. package/dist/utils/credentials/index.js.map +2 -2
  337. package/dist/utils/dualPath.js +24 -0
  338. package/dist/utils/dualPath.js.map +7 -0
  339. package/dist/utils/exit.js +66 -7
  340. package/dist/utils/exit.js.map +2 -2
  341. package/dist/utils/externalEditor.js +155 -0
  342. package/dist/utils/externalEditor.js.map +7 -0
  343. package/dist/utils/fileLock.js +67 -0
  344. package/dist/utils/fileLock.js.map +7 -0
  345. package/dist/utils/format.js +24 -14
  346. package/dist/utils/format.js.map +2 -2
  347. package/dist/utils/globalErrorHandler.js +5 -96
  348. package/dist/utils/globalErrorHandler.js.map +3 -3
  349. package/dist/utils/groupHandlers/parallelTasksHandler.js +5 -3
  350. package/dist/utils/groupHandlers/parallelTasksHandler.js.map +2 -2
  351. package/dist/utils/groupHandlers/taskHandler.js +2 -2
  352. package/dist/utils/groupHandlers/taskHandler.js.map +2 -2
  353. package/dist/utils/hookManager.js +64 -6
  354. package/dist/utils/hookManager.js.map +2 -2
  355. package/dist/utils/log.js +6 -2
  356. package/dist/utils/log.js.map +2 -2
  357. package/dist/utils/markdown.js +237 -19
  358. package/dist/utils/markdown.js.map +2 -2
  359. package/dist/utils/messageContextManager.js +18 -5
  360. package/dist/utils/messageContextManager.js.map +2 -2
  361. package/dist/utils/messageGroupManager.js +1 -1
  362. package/dist/utils/messageGroupManager.js.map +2 -2
  363. package/dist/utils/messages.js +104 -46
  364. package/dist/utils/messages.js.map +2 -2
  365. package/dist/utils/model.js +2 -2
  366. package/dist/utils/model.js.map +2 -2
  367. package/dist/utils/pasteCache.js +8 -4
  368. package/dist/utils/pasteCache.js.map +2 -2
  369. package/dist/utils/pluginLoader.js +18 -0
  370. package/dist/utils/pluginLoader.js.map +2 -2
  371. package/dist/utils/secureKeyStorage.js +36 -7
  372. package/dist/utils/secureKeyStorage.js.map +2 -2
  373. package/dist/utils/simpleMode.js +7 -0
  374. package/dist/utils/simpleMode.js.map +7 -0
  375. package/dist/utils/streamingState.js +11 -1
  376. package/dist/utils/streamingState.js.map +2 -2
  377. package/dist/utils/taskDisplayUtils.js +2 -1
  378. package/dist/utils/taskDisplayUtils.js.map +2 -2
  379. package/dist/utils/teamConfig.js +2 -2
  380. package/dist/utils/teamConfig.js.map +2 -2
  381. package/dist/utils/thinking.js +6 -2
  382. package/dist/utils/thinking.js.map +3 -3
  383. package/dist/utils/tokenProgress.js +55 -0
  384. package/dist/utils/tokenProgress.js.map +7 -0
  385. package/dist/utils/toolRiskClassification.js +26 -17
  386. package/dist/utils/toolRiskClassification.js.map +2 -2
  387. package/dist/utils/tooling/toolError.js +12 -0
  388. package/dist/utils/tooling/toolError.js.map +7 -0
  389. package/dist/version.js +2 -2
  390. package/dist/version.js.map +1 -1
  391. package/package.json +10 -8
@@ -1,10 +1,10 @@
1
1
  import React, { useRef } from "react";
2
2
  import { Box, Text } from "ink";
3
3
  import { getTheme } from "../utils/theme.js";
4
- import { formatDuration } from "../utils/format.js";
4
+ import { formatNumber, formatDuration } from "../utils/format.js";
5
5
  import { getAgentColor, SYMBOL_COLORS } from "../constants/colors.js";
6
6
  import { useUnifiedAnimation } from "../utils/animationManager.js";
7
- import { useAgentTokenStats, formatTokenCount } from "../hooks/useAgentTokenStats.js";
7
+ import { useAgentTokenStats } from "../hooks/useAgentTokenStats.js";
8
8
  function TaskCard({
9
9
  subagent,
10
10
  isExpanded = false,
@@ -34,7 +34,7 @@ function TaskCard({
34
34
  const latestMessage = getLatestMessage(messages);
35
35
  const cardBgColor = isHighlighted ? theme.selectionBg : "#6A7B8E";
36
36
  const isCompleted = status === "completed" || status === "error";
37
- return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", marginY: 0 }, !isCompleted && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Box, { flexDirection: "row" }, /* @__PURE__ */ React.createElement(Text, { color }, statusIcon, " "), /* @__PURE__ */ React.createElement(Text, { bold: true }, taskName), /* @__PURE__ */ React.createElement(Text, { color: theme.dimmedText }, " \xB7 ", agentType)), /* @__PURE__ */ React.createElement(Box, { flexDirection: "row", marginLeft: 2 }, /* @__PURE__ */ React.createElement(Text, { color: theme.dimmedText }, "\u251C\u2500 "), /* @__PURE__ */ React.createElement(Text, { color: statusColor }, statusText), /* @__PURE__ */ React.createElement(Text, { color: theme.mutedText }, " \xB7 "), /* @__PURE__ */ React.createElement(Text, { color: theme.mutedText }, metrics.toolUseCount, " tool", metrics.toolUseCount !== 1 ? "s" : ""), /* @__PURE__ */ React.createElement(Text, { color: theme.mutedText }, " \xB7 "), /* @__PURE__ */ React.createElement(Text, { color: theme.mutedText }, formatTokenCount(tokenCount), " tokens"), /* @__PURE__ */ React.createElement(Text, { color: theme.mutedText }, " \xB7 "), /* @__PURE__ */ React.createElement(Text, { color: theme.mutedText }, formatDuration(duration))), latestMessage && /* @__PURE__ */ React.createElement(Box, { flexDirection: "row", marginLeft: 2 }, /* @__PURE__ */ React.createElement(Text, { color: theme.dimmedText }, "\u2514\u2500 "), /* @__PURE__ */ React.createElement(Text, { color: theme.dimmedText }, latestMessage)), messages.length > 0 && messages.map((msg, idx) => {
37
+ return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", marginY: 0 }, !isCompleted && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Box, { flexDirection: "row" }, /* @__PURE__ */ React.createElement(Text, { color }, statusIcon, " "), /* @__PURE__ */ React.createElement(Text, { bold: true }, taskName), /* @__PURE__ */ React.createElement(Text, { color: theme.dimmedText }, " \xB7 ", agentType)), /* @__PURE__ */ React.createElement(Box, { flexDirection: "row", marginLeft: 2 }, /* @__PURE__ */ React.createElement(Text, { color: theme.dimmedText }, "\u251C\u2500 "), /* @__PURE__ */ React.createElement(Text, { color: statusColor }, statusText), /* @__PURE__ */ React.createElement(Text, { color: theme.mutedText }, " \xB7 "), /* @__PURE__ */ React.createElement(Text, { color: theme.mutedText }, metrics.toolUseCount, " tool", metrics.toolUseCount !== 1 ? "s" : ""), /* @__PURE__ */ React.createElement(Text, { color: theme.mutedText }, " \xB7 "), /* @__PURE__ */ React.createElement(Text, { color: theme.mutedText }, formatNumber(tokenCount), " tokens"), /* @__PURE__ */ React.createElement(Text, { color: theme.mutedText }, " \xB7 "), /* @__PURE__ */ React.createElement(Text, { color: theme.mutedText }, formatDuration(duration))), latestMessage && /* @__PURE__ */ React.createElement(Box, { flexDirection: "row", marginLeft: 2 }, /* @__PURE__ */ React.createElement(Text, { color: theme.dimmedText }, "\u2514\u2500 "), /* @__PURE__ */ React.createElement(Text, { color: theme.dimmedText }, latestMessage)), messages.length > 0 && messages.map((msg, idx) => {
38
38
  let content = "";
39
39
  let prefix = "\u2190 ";
40
40
  if (msg.type === "assistant") {
@@ -61,7 +61,7 @@ function TaskCard({
61
61
  return null;
62
62
  }
63
63
  return /* @__PURE__ */ React.createElement(Box, { key: idx, flexDirection: "row", marginLeft: 4 }, /* @__PURE__ */ React.createElement(Text, { color: theme.dimmedText }, prefix), /* @__PURE__ */ React.createElement(Text, { color: theme.mutedText }, content.substring(0, 80), content.length > 80 ? "..." : ""));
64
- }).filter(Boolean)), isCompleted && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Box, { flexDirection: "row" }, /* @__PURE__ */ React.createElement(Text, { color }, statusIcon, " "), /* @__PURE__ */ React.createElement(Text, { bold: true }, taskName), /* @__PURE__ */ React.createElement(Text, { color: theme.dimmedText }, " \xB7 ", agentType)), /* @__PURE__ */ React.createElement(Box, { flexDirection: "row", marginLeft: 2 }, /* @__PURE__ */ React.createElement(Text, { color: theme.dimmedText }, "\u2514\u2500 "), /* @__PURE__ */ React.createElement(Text, { color: statusColor }, statusText), /* @__PURE__ */ React.createElement(Text, { color: theme.mutedText }, " \xB7 "), /* @__PURE__ */ React.createElement(Text, { color: theme.mutedText }, metrics.toolUseCount, " tool", metrics.toolUseCount !== 1 ? "s" : ""), /* @__PURE__ */ React.createElement(Text, { color: theme.mutedText }, " \xB7 "), /* @__PURE__ */ React.createElement(Text, { color: theme.mutedText }, formatTokenCount(tokenCount), " tokens"), /* @__PURE__ */ React.createElement(Text, { color: theme.mutedText }, " \xB7 "), /* @__PURE__ */ React.createElement(Text, { color: theme.mutedText }, formatDuration(duration)), /* @__PURE__ */ React.createElement(Text, { color: theme.dimmedText }, " (Ctrl+O to expand)")), isExpanded && messages.length > 0 && /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", marginLeft: 4, marginTop: 1 }, renderTaskOutputLog(subagent, theme, tools, verbose))), debug && /* @__PURE__ */ React.createElement(Box, { flexDirection: "row", marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, { color: theme.info }, "[View Details]"), /* @__PURE__ */ React.createElement(Text, null, " "), isRunning && /* @__PURE__ */ React.createElement(Text, { color: SYMBOL_COLORS.error }, "[Cancel]")));
64
+ }).filter(Boolean)), isCompleted && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Box, { flexDirection: "row" }, /* @__PURE__ */ React.createElement(Text, { color }, statusIcon, " "), /* @__PURE__ */ React.createElement(Text, { bold: true }, taskName), /* @__PURE__ */ React.createElement(Text, { color: theme.dimmedText }, " \xB7 ", agentType)), /* @__PURE__ */ React.createElement(Box, { flexDirection: "row", marginLeft: 2 }, /* @__PURE__ */ React.createElement(Text, { color: theme.dimmedText }, "\u2514\u2500 "), /* @__PURE__ */ React.createElement(Text, { color: statusColor }, statusText), /* @__PURE__ */ React.createElement(Text, { color: theme.mutedText }, " \xB7 "), /* @__PURE__ */ React.createElement(Text, { color: theme.mutedText }, metrics.toolUseCount, " tool", metrics.toolUseCount !== 1 ? "s" : ""), /* @__PURE__ */ React.createElement(Text, { color: theme.mutedText }, " \xB7 "), /* @__PURE__ */ React.createElement(Text, { color: theme.mutedText }, formatNumber(tokenCount), " tokens"), /* @__PURE__ */ React.createElement(Text, { color: theme.mutedText }, " \xB7 "), /* @__PURE__ */ React.createElement(Text, { color: theme.mutedText }, formatDuration(duration)), /* @__PURE__ */ React.createElement(Text, { color: theme.dimmedText }, " (Ctrl+O to expand)")), isExpanded && messages.length > 0 && /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", marginLeft: 4, marginTop: 1 }, renderTaskOutputLog(subagent, theme, tools, verbose))), debug && /* @__PURE__ */ React.createElement(Box, { flexDirection: "row", marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, { color: theme.info }, "[View Details]"), /* @__PURE__ */ React.createElement(Text, null, " "), isRunning && /* @__PURE__ */ React.createElement(Text, { color: SYMBOL_COLORS.error }, "[Cancel]")));
65
65
  }
66
66
  function getStatusIcon(status, isRunning) {
67
67
  if (isRunning) {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/components/TaskCard.tsx"],
4
- "sourcesContent": ["/**\n * TaskCard - Claude Code CLI \u98CE\u683C\u7684\u4EFB\u52A1\u5361\u7247\u7EC4\u4EF6\n *\n * \u6838\u5FC3\u7279\u6027\uFF1A\n * 1. **\u5361\u7247\u5F0F\u8BBE\u8BA1** - \u72EC\u7ACB\u7684\u89C6\u89C9\u5355\u5143\uFF0C\u4E0E\u4E3B\u5BF9\u8BDD\u6D41\u533A\u5206\n * 2. **\u72B6\u6001\u6E05\u6670** - \u901A\u8FC7\u56FE\u6807\u548C\u989C\u8272\u660E\u786E\u4F20\u8FBE\u4EFB\u52A1\u72B6\u6001\n * 3. **\u53EF\u6298\u53E0** - \u8BE6\u7EC6\u65E5\u5FD7\u53EF\u6298\u53E0\uFF0C\u8282\u7701\u7A7A\u95F4\n * 4. **\u8FDB\u5EA6\u53EF\u89C6\u5316** - \u663E\u793A\u4EFB\u52A1\u8FDB\u5EA6\u767E\u5206\u6BD4\u548C\u6307\u6807\n * 5. **\u5E76\u53D1\u53CB\u597D** - \u591A\u4E2A\u5361\u7247\u5E76\u5217\u663E\u793A\u4E0D\u6DF7\u4E71\n *\n * \u57FA\u4E8E Claude Code CLI \u7684 TaskCardBlock \u89C4\u8303\n * \u4F7F\u7528\u7EDF\u4E00\u52A8\u753B\u7BA1\u7406\u5668\u4EE3\u66FF setInterval\uFF0C\u51CF\u5C11\u5C4F\u5E55\u95EA\u70C1\n */\n\nimport React, { useRef } from 'react'\nimport { Box, Text } from 'ink'\nimport { getTheme } from '@utils/theme'\nimport { formatNumber, formatDuration } from '@utils/format'\nimport { getAgentColor, SYMBOL_COLORS } from '@constants/colors'\nimport type { SubagentState } from '@minto-types/subagent'\nimport type { Tool } from '@tool'\nimport { useUnifiedAnimation } from '@utils/animationManager'\nimport { useAgentTokenStats, formatTokenCount } from '@hooks/useAgentTokenStats'\n\ninterface TaskCardProps {\n /** \u5B50\u4EFB\u52A1\u72B6\u6001 */\n subagent: SubagentState\n\n /** \u662F\u5426\u5C55\u5F00\u8BE6\u7EC6\u65E5\u5FD7 */\n isExpanded?: boolean\n\n /** \u662F\u5426\u9AD8\u4EAE\uFF08\u9700\u8981\u7528\u6237\u5173\u6CE8\uFF09 */\n isHighlighted?: boolean\n\n /** \u5DE5\u5177\u5217\u8868 */\n tools?: Tool[]\n\n /** \u662F\u5426\u663E\u793A\u8BE6\u7EC6\u4FE1\u606F */\n verbose?: boolean\n\n /** \u8C03\u8BD5\u6A21\u5F0F */\n debug?: boolean\n\n /** \u6298\u53E0/\u5C55\u5F00\u56DE\u8C03 */\n onToggleExpand?: () => void\n}\n\n/**\n * TaskCard - \u5355\u4E2A\u5B50\u4EFB\u52A1\u7684\u52A8\u6001\u5C55\u793A\uFF08\u65E0\u8FB9\u6846\uFF09\n *\n * \u8FD0\u884C\u4E2D\u5E03\u5C40\uFF08\u81EA\u52A8\u5C55\u5F00\uFF09:\n * ```\n * \u280B Feature Implementation \u00B7 backend-architect\n * \u251C\u2500 Running \u00B7 3 tools \u00B7 5.2k tokens \u00B7 12s\n * \u2514\u2500 Analyzing code structure...\n * \u2192 Tool call output message...\n * \u2190 Assistant response...\n * ```\n *\n * \u5B8C\u6210\u540E\u5E03\u5C40\uFF08\u81EA\u52A8\u6298\u53E0\uFF09:\n * ```\n * \u2713 Feature Implementation \u00B7 backend-architect\n * \u2514\u2500 Done \u00B7 5 tools \u00B7 8.3k tokens \u00B7 24s (Ctrl+O to expand)\n * ```\n *\n * \u5B8C\u6210\u540E\u5C55\u5F00\uFF08Ctrl+O\uFF09:\n * ```\n * \u2713 Feature Implementation \u00B7 backend-architect\n * \u2514\u2500 Done \u00B7 5 tools \u00B7 8.3k tokens \u00B7 24s (Ctrl+O to expand)\n * [\u8BE6\u7EC6\u7684\u6267\u884C\u8FC7\u7A0B\u65E5\u5FD7]\n * ```\n */\nexport function TaskCard({\n subagent,\n isExpanded = false,\n isHighlighted = false,\n tools = [],\n verbose = false,\n debug = false,\n onToggleExpand,\n}: TaskCardProps): React.ReactNode {\n const theme = getTheme()\n const { metrics, taskName, status, messages, agentType, agentColor } =\n subagent\n\n // Get real-time token stats from unified TokenStatsManager\n const tokenStats = useAgentTokenStats(subagent.id)\n const tokenCount = tokenStats?.grandTotalTokens ?? 0\n\n // \u83B7\u53D6 agent \u989C\u8272\n const color = getAgentColor(agentColor, theme)\n\n // \u5224\u65AD\u662F\u5426\u6B63\u5728\u8FD0\u884C\n const isRunning =\n status === 'initializing' || status === 'running' || status === 'queued'\n\n // Use unified animation manager for periodic time updates\n const startTimeRef = useRef(metrics.startTime)\n const { elapsedTime } = useUnifiedAnimation({\n enabled: isRunning,\n startTime: startTimeRef.current,\n spinnerFrameCount: 1,\n componentId: `task-card-${subagent.id}`,\n })\n\n // \u8BA1\u7B97\u6301\u7EED\u65F6\u95F4\n const duration = metrics.endTime\n ? metrics.endTime - metrics.startTime\n : Date.now() - metrics.startTime\n\n // \u72B6\u6001\u56FE\u6807\u548C\u6587\u672C\n const statusIcon = getStatusIcon(status, isRunning)\n const statusText = getStatusText(status)\n const statusColor = getStatusColor(status, theme)\n\n // \u83B7\u53D6\u6700\u65B0\u7684\u72B6\u6001\u6D88\u606F\n const latestMessage = getLatestMessage(messages)\n\n // \u5361\u7247\u80CC\u666F\u8272\uFF08\u6839\u636E\u72B6\u6001\u548C\u9AD8\u4EAE\uFF09\n const cardBgColor = isHighlighted\n ? theme.selectionBg // #3C3C3C\n : '#6A7B8E' // Task Card BG\n\n // \u5224\u65AD\u662F\u5426\u5DF2\u5B8C\u6210\uFF08completed \u6216 error\uFF09\n const isCompleted = status === 'completed' || status === 'error'\n\n return (\n <Box flexDirection=\"column\" marginY={0}>\n {/* \u8FD0\u884C\u4E2D\uFF1A\u5C55\u5F00\u663E\u793A\u6240\u6709\u5185\u5BB9 */}\n {!isCompleted && (\n <>\n {/* TaskHeader - \u4EFB\u52A1\u540D\u79F0\u548C Agent \u7C7B\u578B */}\n <Box flexDirection=\"row\">\n <Text color={color}>{statusIcon} </Text>\n <Text bold>{taskName}</Text>\n <Text color={theme.dimmedText}> \u00B7 {agentType}</Text>\n </Box>\n\n {/* TaskProgress - \u72B6\u6001\u548C\u6307\u6807 */}\n <Box flexDirection=\"row\" marginLeft={2}>\n <Text color={theme.dimmedText}>\u251C\u2500 </Text>\n <Text color={statusColor}>{statusText}</Text>\n <Text color={theme.mutedText}> \u00B7 </Text>\n <Text color={theme.mutedText}>\n {metrics.toolUseCount} tool{metrics.toolUseCount !== 1 ? 's' : ''}\n </Text>\n <Text color={theme.mutedText}> \u00B7 </Text>\n <Text color={theme.mutedText}>\n {formatTokenCount(tokenCount)} tokens\n </Text>\n <Text color={theme.mutedText}> \u00B7 </Text>\n <Text color={theme.mutedText}>{formatDuration(duration)}</Text>\n </Box>\n\n {/* TaskStatusMessage - \u5F53\u524D\u6B63\u5728\u505A\u4EC0\u4E48 */}\n {latestMessage && (\n <Box flexDirection=\"row\" marginLeft={2}>\n <Text color={theme.dimmedText}>\u2514\u2500 </Text>\n <Text color={theme.dimmedText}>{latestMessage}</Text>\n </Box>\n )}\n\n {/* Output messages - \u76F4\u63A5\u663E\u793A\u4E3A\u5B50\u5C42\u7EA7\uFF0C\u65E0 \"Output Log\" \u6807\u9898 */}\n {messages.length > 0 &&\n messages\n .map((msg, idx) => {\n // Extract text content based on message type\n let content = ''\n let prefix = '\u2190 '\n\n if (msg.type === 'assistant') {\n prefix = '\u2192 '\n const blocks = msg.message.content\n content = blocks\n .filter((block: any) => block.type === 'text')\n .map((block: any) => block.text)\n .join(' ')\n } else if (msg.type === 'user') {\n const msgParam = msg.message as any\n if (typeof msgParam.content === 'string') {\n content = msgParam.content\n } else if (Array.isArray(msgParam.content)) {\n content = msgParam.content\n .filter((block: any) => block.type === 'text')\n .map((block: any) => block.text)\n .join(' ')\n }\n } else if (msg.type === 'progress') {\n prefix = '\u2699 '\n // Handle both AssistantMessage and StreamingProgressContent\n if (\n 'type' in msg.content &&\n msg.content.type === 'streaming'\n ) {\n // StreamingProgressContent - show stdout/stderr preview\n content =\n msg.content.stdout ||\n msg.content.stderr ||\n '(streaming...)'\n } else if ('message' in msg.content) {\n // AssistantMessage\n const blocks = (msg.content as any).message.content\n content = blocks\n .filter((block: any) => block.type === 'text')\n .map((block: any) => block.text)\n .join(' ')\n }\n }\n\n if (!content || content.trim().length === 0) {\n return null\n }\n\n return (\n <Box key={idx} flexDirection=\"row\" marginLeft={4}>\n <Text color={theme.dimmedText}>{prefix}</Text>\n <Text color={theme.mutedText}>\n {content.substring(0, 80)}\n {content.length > 80 ? '...' : ''}\n </Text>\n </Box>\n )\n })\n .filter(Boolean)}\n </>\n )}\n\n {/* \u5DF2\u5B8C\u6210\uFF1A\u6298\u53E0\u6210\u4E00\u884C\uFF0C\u5E26\u5C55\u5F00\u63D0\u793A */}\n {isCompleted && (\n <>\n <Box flexDirection=\"row\">\n <Text color={color}>{statusIcon} </Text>\n <Text bold>{taskName}</Text>\n <Text color={theme.dimmedText}> \u00B7 {agentType}</Text>\n </Box>\n\n <Box flexDirection=\"row\" marginLeft={2}>\n <Text color={theme.dimmedText}>\u2514\u2500 </Text>\n <Text color={statusColor}>{statusText}</Text>\n <Text color={theme.mutedText}> \u00B7 </Text>\n <Text color={theme.mutedText}>\n {metrics.toolUseCount} tool{metrics.toolUseCount !== 1 ? 's' : ''}\n </Text>\n <Text color={theme.mutedText}> \u00B7 </Text>\n <Text color={theme.mutedText}>\n {formatTokenCount(tokenCount)} tokens\n </Text>\n <Text color={theme.mutedText}> \u00B7 </Text>\n <Text color={theme.mutedText}>{formatDuration(duration)}</Text>\n <Text color={theme.dimmedText}> (Ctrl+O to expand)</Text>\n </Box>\n\n {/* \u5C55\u5F00\u65F6\u663E\u793A\u8BE6\u7EC6\u8FC7\u7A0B */}\n {isExpanded && messages.length > 0 && (\n <Box flexDirection=\"column\" marginLeft={4} marginTop={1}>\n {renderTaskOutputLog(subagent, theme, tools, verbose)}\n </Box>\n )}\n </>\n )}\n\n {/* TaskActionButtons - \u64CD\u4F5C\u6309\u94AE (\u672A\u6765\u6269\u5C55) */}\n {debug && (\n <Box flexDirection=\"row\" marginTop={1}>\n <Text color={theme.info}>[View Details]</Text>\n <Text> </Text>\n {isRunning && <Text color={SYMBOL_COLORS.error}>[Cancel]</Text>}\n </Box>\n )}\n </Box>\n )\n}\n\n/**\n * \u83B7\u53D6\u72B6\u6001\u56FE\u6807\n */\nfunction getStatusIcon(\n status: SubagentState['status'],\n isRunning: boolean,\n): string {\n if (isRunning) {\n // \u4F7F\u7528 Spinner \u5B57\u7B26\u8F6E\u8F6C (\u7B80\u5316\u7248)\n const spinnerFrames = ['\u280B', '\u2819', '\u2839', '\u2838', '\u283C', '\u2834', '\u2826', '\u2827', '\u2807', '\u280F']\n const frame = Math.floor(Date.now() / 120) % spinnerFrames.length\n return spinnerFrames[frame] || '\u280B'\n }\n\n switch (status) {\n case 'completed':\n return '\u2713'\n case 'error':\n return '\u2715'\n case 'queued':\n return '\u2026'\n default:\n return '\u25E6'\n }\n}\n\n/**\n * \u83B7\u53D6\u72B6\u6001\u6587\u672C\n */\nfunction getStatusText(status: SubagentState['status']): string {\n switch (status) {\n case 'initializing':\n return 'Initializing'\n case 'queued':\n return 'Queued'\n case 'running':\n return 'Running'\n case 'completed':\n return 'Done'\n case 'error':\n return 'Error'\n }\n}\n\n/**\n * \u83B7\u53D6\u72B6\u6001\u989C\u8272 - \u4F7F\u7528 SYMBOL_COLORS \u4E0E Logo \u54C1\u724C\u914D\u8272\u4FDD\u6301\u4E00\u81F4\n */\nfunction getStatusColor(\n status: SubagentState['status'],\n theme: ReturnType<typeof getTheme>,\n): string {\n switch (status) {\n case 'initializing':\n case 'queued':\n return SYMBOL_COLORS.pending // \u7070\u8272 - \u7B49\u5F85\n case 'running':\n return SYMBOL_COLORS.running // \u7C89\u7D2B - \u8FDB\u884C\u4E2D\n case 'completed':\n return SYMBOL_COLORS.success // \u7D2B\u84DD - \u5B8C\u6210\n case 'error':\n return SYMBOL_COLORS.error // \u73CA\u745A\u7EA2 - \u9519\u8BEF\n }\n}\n\n/**\n * \u83B7\u53D6\u6700\u65B0\u7684\u72B6\u6001\u6D88\u606F\n */\nfunction getLatestMessage(messages: SubagentState['messages']): string | null {\n if (messages.length === 0) return null\n\n // \u5012\u5E8F\u67E5\u627E\u6700\u65B0\u7684\u6587\u672C\u6D88\u606F\n for (let i = messages.length - 1; i >= 0; i--) {\n const msg = messages[i]\n if (msg?.type === 'assistant' && msg.message?.content) {\n for (const content of msg.message.content) {\n if (content.type === 'text' && content.text.trim()) {\n // \u622A\u53D6\u524D 60 \u4E2A\u5B57\u7B26\n const text = content.text.trim()\n return text.length > 60 ? text.substring(0, 60) + '...' : text\n }\n if (content.type === 'tool_use') {\n return `Using ${content.name}...`\n }\n }\n }\n }\n\n return null\n}\n\n/**\n * \u6E32\u67D3\u8BE6\u7EC6\u7684\u8F93\u51FA\u65E5\u5FD7\n */\nfunction renderTaskOutputLog(\n subagent: SubagentState,\n theme: ReturnType<typeof getTheme>,\n tools: Tool[],\n verbose: boolean,\n): React.ReactNode {\n const { messages } = subagent\n\n return (\n <Box flexDirection=\"column\">\n {messages.map((msg, idx) => {\n if (msg.type === 'assistant') {\n return msg.message.content.map((content, contentIdx) => {\n if (content.type === 'tool_use') {\n const tool = tools.find(t => t.name === content.name)\n const toolName = tool?.userFacingName\n ? typeof tool.userFacingName === 'function'\n ? tool.userFacingName()\n : tool.userFacingName\n : content.name\n\n return (\n <Box key={`${idx}-${contentIdx}`} flexDirection=\"row\">\n <Text color={theme.info}>\uD83D\uDD27 {toolName}</Text>\n </Box>\n )\n } else if (content.type === 'text' && content.text.trim()) {\n const lines = content.text.trim().split('\\n')\n return (\n <Box key={`${idx}-${contentIdx}`} flexDirection=\"column\">\n {lines.map((line, lineIdx) => (\n <Text color={theme.secondaryText}>{line}</Text>\n ))}\n </Box>\n )\n }\n return null\n })\n } else if (msg.type === 'user') {\n return msg.message.content.map((content, contentIdx) => {\n if (content.type === 'tool_result') {\n const resultContent = Array.isArray(content.content)\n ? content.content.find(c => c.type === 'text')?.text\n : typeof content.content === 'string'\n ? content.content\n : ''\n\n if (resultContent && resultContent.trim()) {\n const lines = resultContent.trim().split('\\n')\n const preview =\n lines.length > 5\n ? lines.slice(0, 5).join('\\n') + '\\n...'\n : resultContent.trim()\n\n return (\n <Box key={`${idx}-${contentIdx}`} flexDirection=\"column\">\n {preview.split('\\n').map((line, lineIdx) => (\n <Text color={theme.mutedText}>{line}</Text>\n ))}\n </Box>\n )\n }\n }\n return null\n })\n }\n return null\n })}\n </Box>\n )\n}\n\n/**\n * \u7D27\u51D1\u7248 TaskCard (\u7528\u4E8E\u7A7A\u95F4\u53D7\u9650\u7684\u573A\u666F)\n */\nexport function CompactTaskCard({\n subagent,\n}: {\n subagent: SubagentState\n}): React.ReactNode {\n const theme = getTheme()\n const { taskName, status, agentColor } = subagent\n\n const color = getAgentColor(agentColor, theme)\n const isRunning =\n status === 'initializing' || status === 'running' || status === 'queued'\n const statusIcon = getStatusIcon(status, isRunning)\n\n return (\n <Box flexDirection=\"row\">\n <Text color={color}>\n {statusIcon} {taskName}\n </Text>\n <Text color={theme.dimmedText}> \u00B7 {getStatusText(status)}</Text>\n </Box>\n )\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * TaskCard - Claude Code CLI \u98CE\u683C\u7684\u4EFB\u52A1\u5361\u7247\u7EC4\u4EF6\n *\n * \u6838\u5FC3\u7279\u6027\uFF1A\n * 1. **\u5361\u7247\u5F0F\u8BBE\u8BA1** - \u72EC\u7ACB\u7684\u89C6\u89C9\u5355\u5143\uFF0C\u4E0E\u4E3B\u5BF9\u8BDD\u6D41\u533A\u5206\n * 2. **\u72B6\u6001\u6E05\u6670** - \u901A\u8FC7\u56FE\u6807\u548C\u989C\u8272\u660E\u786E\u4F20\u8FBE\u4EFB\u52A1\u72B6\u6001\n * 3. **\u53EF\u6298\u53E0** - \u8BE6\u7EC6\u65E5\u5FD7\u53EF\u6298\u53E0\uFF0C\u8282\u7701\u7A7A\u95F4\n * 4. **\u8FDB\u5EA6\u53EF\u89C6\u5316** - \u663E\u793A\u4EFB\u52A1\u8FDB\u5EA6\u767E\u5206\u6BD4\u548C\u6307\u6807\n * 5. **\u5E76\u53D1\u53CB\u597D** - \u591A\u4E2A\u5361\u7247\u5E76\u5217\u663E\u793A\u4E0D\u6DF7\u4E71\n *\n * \u57FA\u4E8E Claude Code CLI \u7684 TaskCardBlock \u89C4\u8303\n * \u4F7F\u7528\u7EDF\u4E00\u52A8\u753B\u7BA1\u7406\u5668\u4EE3\u66FF setInterval\uFF0C\u51CF\u5C11\u5C4F\u5E55\u95EA\u70C1\n */\n\nimport React, { useRef } from 'react'\nimport { Box, Text } from 'ink'\nimport { getTheme } from '@utils/theme'\nimport { formatNumber, formatDuration } from '@utils/format'\nimport { getAgentColor, SYMBOL_COLORS } from '@constants/colors'\nimport type { SubagentState } from '@minto-types/subagent'\nimport type { Tool } from '@tool'\nimport { useUnifiedAnimation } from '@utils/animationManager'\nimport { useAgentTokenStats } from '@hooks/useAgentTokenStats'\n\ninterface TaskCardProps {\n /** \u5B50\u4EFB\u52A1\u72B6\u6001 */\n subagent: SubagentState\n\n /** \u662F\u5426\u5C55\u5F00\u8BE6\u7EC6\u65E5\u5FD7 */\n isExpanded?: boolean\n\n /** \u662F\u5426\u9AD8\u4EAE\uFF08\u9700\u8981\u7528\u6237\u5173\u6CE8\uFF09 */\n isHighlighted?: boolean\n\n /** \u5DE5\u5177\u5217\u8868 */\n tools?: Tool[]\n\n /** \u662F\u5426\u663E\u793A\u8BE6\u7EC6\u4FE1\u606F */\n verbose?: boolean\n\n /** \u8C03\u8BD5\u6A21\u5F0F */\n debug?: boolean\n\n /** \u6298\u53E0/\u5C55\u5F00\u56DE\u8C03 */\n onToggleExpand?: () => void\n}\n\n/**\n * TaskCard - \u5355\u4E2A\u5B50\u4EFB\u52A1\u7684\u52A8\u6001\u5C55\u793A\uFF08\u65E0\u8FB9\u6846\uFF09\n *\n * \u8FD0\u884C\u4E2D\u5E03\u5C40\uFF08\u81EA\u52A8\u5C55\u5F00\uFF09:\n * ```\n * \u280B Feature Implementation \u00B7 backend-architect\n * \u251C\u2500 Running \u00B7 3 tools \u00B7 5.2k tokens \u00B7 12s\n * \u2514\u2500 Analyzing code structure...\n * \u2192 Tool call output message...\n * \u2190 Assistant response...\n * ```\n *\n * \u5B8C\u6210\u540E\u5E03\u5C40\uFF08\u81EA\u52A8\u6298\u53E0\uFF09:\n * ```\n * \u2713 Feature Implementation \u00B7 backend-architect\n * \u2514\u2500 Done \u00B7 5 tools \u00B7 8.3k tokens \u00B7 24s (Ctrl+O to expand)\n * ```\n *\n * \u5B8C\u6210\u540E\u5C55\u5F00\uFF08Ctrl+O\uFF09:\n * ```\n * \u2713 Feature Implementation \u00B7 backend-architect\n * \u2514\u2500 Done \u00B7 5 tools \u00B7 8.3k tokens \u00B7 24s (Ctrl+O to expand)\n * [\u8BE6\u7EC6\u7684\u6267\u884C\u8FC7\u7A0B\u65E5\u5FD7]\n * ```\n */\nexport function TaskCard({\n subagent,\n isExpanded = false,\n isHighlighted = false,\n tools = [],\n verbose = false,\n debug = false,\n onToggleExpand,\n}: TaskCardProps): React.ReactNode {\n const theme = getTheme()\n const { metrics, taskName, status, messages, agentType, agentColor } =\n subagent\n\n // Get real-time token stats from unified TokenStatsManager\n const tokenStats = useAgentTokenStats(subagent.id)\n const tokenCount = tokenStats?.grandTotalTokens ?? 0\n\n // \u83B7\u53D6 agent \u989C\u8272\n const color = getAgentColor(agentColor, theme)\n\n // \u5224\u65AD\u662F\u5426\u6B63\u5728\u8FD0\u884C\n const isRunning =\n status === 'initializing' || status === 'running' || status === 'queued'\n\n // Use unified animation manager for periodic time updates\n const startTimeRef = useRef(metrics.startTime)\n const { elapsedTime } = useUnifiedAnimation({\n enabled: isRunning,\n startTime: startTimeRef.current,\n spinnerFrameCount: 1,\n componentId: `task-card-${subagent.id}`,\n })\n\n // \u8BA1\u7B97\u6301\u7EED\u65F6\u95F4\n const duration = metrics.endTime\n ? metrics.endTime - metrics.startTime\n : Date.now() - metrics.startTime\n\n // \u72B6\u6001\u56FE\u6807\u548C\u6587\u672C\n const statusIcon = getStatusIcon(status, isRunning)\n const statusText = getStatusText(status)\n const statusColor = getStatusColor(status, theme)\n\n // \u83B7\u53D6\u6700\u65B0\u7684\u72B6\u6001\u6D88\u606F\n const latestMessage = getLatestMessage(messages)\n\n // \u5361\u7247\u80CC\u666F\u8272\uFF08\u6839\u636E\u72B6\u6001\u548C\u9AD8\u4EAE\uFF09\n const cardBgColor = isHighlighted\n ? theme.selectionBg // #3C3C3C\n : '#6A7B8E' // Task Card BG\n\n // \u5224\u65AD\u662F\u5426\u5DF2\u5B8C\u6210\uFF08completed \u6216 error\uFF09\n const isCompleted = status === 'completed' || status === 'error'\n\n return (\n <Box flexDirection=\"column\" marginY={0}>\n {/* \u8FD0\u884C\u4E2D\uFF1A\u5C55\u5F00\u663E\u793A\u6240\u6709\u5185\u5BB9 */}\n {!isCompleted && (\n <>\n {/* TaskHeader - \u4EFB\u52A1\u540D\u79F0\u548C Agent \u7C7B\u578B */}\n <Box flexDirection=\"row\">\n <Text color={color}>{statusIcon} </Text>\n <Text bold>{taskName}</Text>\n <Text color={theme.dimmedText}> \u00B7 {agentType}</Text>\n </Box>\n\n {/* TaskProgress - \u72B6\u6001\u548C\u6307\u6807 */}\n <Box flexDirection=\"row\" marginLeft={2}>\n <Text color={theme.dimmedText}>\u251C\u2500 </Text>\n <Text color={statusColor}>{statusText}</Text>\n <Text color={theme.mutedText}> \u00B7 </Text>\n <Text color={theme.mutedText}>\n {metrics.toolUseCount} tool{metrics.toolUseCount !== 1 ? 's' : ''}\n </Text>\n <Text color={theme.mutedText}> \u00B7 </Text>\n <Text color={theme.mutedText}>\n {formatNumber(tokenCount)} tokens\n </Text>\n <Text color={theme.mutedText}> \u00B7 </Text>\n <Text color={theme.mutedText}>{formatDuration(duration)}</Text>\n </Box>\n\n {/* TaskStatusMessage - \u5F53\u524D\u6B63\u5728\u505A\u4EC0\u4E48 */}\n {latestMessage && (\n <Box flexDirection=\"row\" marginLeft={2}>\n <Text color={theme.dimmedText}>\u2514\u2500 </Text>\n <Text color={theme.dimmedText}>{latestMessage}</Text>\n </Box>\n )}\n\n {/* Output messages - \u76F4\u63A5\u663E\u793A\u4E3A\u5B50\u5C42\u7EA7\uFF0C\u65E0 \"Output Log\" \u6807\u9898 */}\n {messages.length > 0 &&\n messages\n .map((msg, idx) => {\n // Extract text content based on message type\n let content = ''\n let prefix = '\u2190 '\n\n if (msg.type === 'assistant') {\n prefix = '\u2192 '\n const blocks = msg.message.content\n content = blocks\n .filter((block: any) => block.type === 'text')\n .map((block: any) => block.text)\n .join(' ')\n } else if (msg.type === 'user') {\n const msgParam = msg.message as any\n if (typeof msgParam.content === 'string') {\n content = msgParam.content\n } else if (Array.isArray(msgParam.content)) {\n content = msgParam.content\n .filter((block: any) => block.type === 'text')\n .map((block: any) => block.text)\n .join(' ')\n }\n } else if (msg.type === 'progress') {\n prefix = '\u2699 '\n // Handle both AssistantMessage and StreamingProgressContent\n if (\n 'type' in msg.content &&\n msg.content.type === 'streaming'\n ) {\n // StreamingProgressContent - show stdout/stderr preview\n content =\n msg.content.stdout ||\n msg.content.stderr ||\n '(streaming...)'\n } else if ('message' in msg.content) {\n // AssistantMessage\n const blocks = (msg.content as any).message.content\n content = blocks\n .filter((block: any) => block.type === 'text')\n .map((block: any) => block.text)\n .join(' ')\n }\n }\n\n if (!content || content.trim().length === 0) {\n return null\n }\n\n return (\n <Box key={idx} flexDirection=\"row\" marginLeft={4}>\n <Text color={theme.dimmedText}>{prefix}</Text>\n <Text color={theme.mutedText}>\n {content.substring(0, 80)}\n {content.length > 80 ? '...' : ''}\n </Text>\n </Box>\n )\n })\n .filter(Boolean)}\n </>\n )}\n\n {/* \u5DF2\u5B8C\u6210\uFF1A\u6298\u53E0\u6210\u4E00\u884C\uFF0C\u5E26\u5C55\u5F00\u63D0\u793A */}\n {isCompleted && (\n <>\n <Box flexDirection=\"row\">\n <Text color={color}>{statusIcon} </Text>\n <Text bold>{taskName}</Text>\n <Text color={theme.dimmedText}> \u00B7 {agentType}</Text>\n </Box>\n\n <Box flexDirection=\"row\" marginLeft={2}>\n <Text color={theme.dimmedText}>\u2514\u2500 </Text>\n <Text color={statusColor}>{statusText}</Text>\n <Text color={theme.mutedText}> \u00B7 </Text>\n <Text color={theme.mutedText}>\n {metrics.toolUseCount} tool{metrics.toolUseCount !== 1 ? 's' : ''}\n </Text>\n <Text color={theme.mutedText}> \u00B7 </Text>\n <Text color={theme.mutedText}>\n {formatNumber(tokenCount)} tokens\n </Text>\n <Text color={theme.mutedText}> \u00B7 </Text>\n <Text color={theme.mutedText}>{formatDuration(duration)}</Text>\n <Text color={theme.dimmedText}> (Ctrl+O to expand)</Text>\n </Box>\n\n {/* \u5C55\u5F00\u65F6\u663E\u793A\u8BE6\u7EC6\u8FC7\u7A0B */}\n {isExpanded && messages.length > 0 && (\n <Box flexDirection=\"column\" marginLeft={4} marginTop={1}>\n {renderTaskOutputLog(subagent, theme, tools, verbose)}\n </Box>\n )}\n </>\n )}\n\n {/* TaskActionButtons - \u64CD\u4F5C\u6309\u94AE (\u672A\u6765\u6269\u5C55) */}\n {debug && (\n <Box flexDirection=\"row\" marginTop={1}>\n <Text color={theme.info}>[View Details]</Text>\n <Text> </Text>\n {isRunning && <Text color={SYMBOL_COLORS.error}>[Cancel]</Text>}\n </Box>\n )}\n </Box>\n )\n}\n\n/**\n * \u83B7\u53D6\u72B6\u6001\u56FE\u6807\n */\nfunction getStatusIcon(\n status: SubagentState['status'],\n isRunning: boolean,\n): string {\n if (isRunning) {\n // \u4F7F\u7528 Spinner \u5B57\u7B26\u8F6E\u8F6C (\u7B80\u5316\u7248)\n const spinnerFrames = ['\u280B', '\u2819', '\u2839', '\u2838', '\u283C', '\u2834', '\u2826', '\u2827', '\u2807', '\u280F']\n const frame = Math.floor(Date.now() / 120) % spinnerFrames.length\n return spinnerFrames[frame] || '\u280B'\n }\n\n switch (status) {\n case 'completed':\n return '\u2713'\n case 'error':\n return '\u2715'\n case 'queued':\n return '\u2026'\n default:\n return '\u25E6'\n }\n}\n\n/**\n * \u83B7\u53D6\u72B6\u6001\u6587\u672C\n */\nfunction getStatusText(status: SubagentState['status']): string {\n switch (status) {\n case 'initializing':\n return 'Initializing'\n case 'queued':\n return 'Queued'\n case 'running':\n return 'Running'\n case 'completed':\n return 'Done'\n case 'error':\n return 'Error'\n }\n}\n\n/**\n * \u83B7\u53D6\u72B6\u6001\u989C\u8272 - \u4F7F\u7528 SYMBOL_COLORS \u4E0E Logo \u54C1\u724C\u914D\u8272\u4FDD\u6301\u4E00\u81F4\n */\nfunction getStatusColor(\n status: SubagentState['status'],\n theme: ReturnType<typeof getTheme>,\n): string {\n switch (status) {\n case 'initializing':\n case 'queued':\n return SYMBOL_COLORS.pending // \u7070\u8272 - \u7B49\u5F85\n case 'running':\n return SYMBOL_COLORS.running // \u7C89\u7D2B - \u8FDB\u884C\u4E2D\n case 'completed':\n return SYMBOL_COLORS.success // \u7D2B\u84DD - \u5B8C\u6210\n case 'error':\n return SYMBOL_COLORS.error // \u73CA\u745A\u7EA2 - \u9519\u8BEF\n }\n}\n\n/**\n * \u83B7\u53D6\u6700\u65B0\u7684\u72B6\u6001\u6D88\u606F\n */\nfunction getLatestMessage(messages: SubagentState['messages']): string | null {\n if (messages.length === 0) return null\n\n // \u5012\u5E8F\u67E5\u627E\u6700\u65B0\u7684\u6587\u672C\u6D88\u606F\n for (let i = messages.length - 1; i >= 0; i--) {\n const msg = messages[i]\n if (msg?.type === 'assistant' && msg.message?.content) {\n for (const content of msg.message.content) {\n if (content.type === 'text' && content.text.trim()) {\n // \u622A\u53D6\u524D 60 \u4E2A\u5B57\u7B26\n const text = content.text.trim()\n return text.length > 60 ? text.substring(0, 60) + '...' : text\n }\n if (content.type === 'tool_use') {\n return `Using ${content.name}...`\n }\n }\n }\n }\n\n return null\n}\n\n/**\n * \u6E32\u67D3\u8BE6\u7EC6\u7684\u8F93\u51FA\u65E5\u5FD7\n */\nfunction renderTaskOutputLog(\n subagent: SubagentState,\n theme: ReturnType<typeof getTheme>,\n tools: Tool[],\n verbose: boolean,\n): React.ReactNode {\n const { messages } = subagent\n\n return (\n <Box flexDirection=\"column\">\n {messages.map((msg, idx) => {\n if (msg.type === 'assistant') {\n return msg.message.content.map((content, contentIdx) => {\n if (content.type === 'tool_use') {\n const tool = tools.find(t => t.name === content.name)\n const toolName = tool?.userFacingName\n ? typeof tool.userFacingName === 'function'\n ? tool.userFacingName()\n : tool.userFacingName\n : content.name\n\n return (\n <Box key={`${idx}-${contentIdx}`} flexDirection=\"row\">\n <Text color={theme.info}>\uD83D\uDD27 {toolName}</Text>\n </Box>\n )\n } else if (content.type === 'text' && content.text.trim()) {\n const lines = content.text.trim().split('\\n')\n return (\n <Box key={`${idx}-${contentIdx}`} flexDirection=\"column\">\n {lines.map((line, lineIdx) => (\n <Text color={theme.secondaryText}>{line}</Text>\n ))}\n </Box>\n )\n }\n return null\n })\n } else if (msg.type === 'user') {\n return msg.message.content.map((content, contentIdx) => {\n if (content.type === 'tool_result') {\n const resultContent = Array.isArray(content.content)\n ? content.content.find(c => c.type === 'text')?.text\n : typeof content.content === 'string'\n ? content.content\n : ''\n\n if (resultContent && resultContent.trim()) {\n const lines = resultContent.trim().split('\\n')\n const preview =\n lines.length > 5\n ? lines.slice(0, 5).join('\\n') + '\\n...'\n : resultContent.trim()\n\n return (\n <Box key={`${idx}-${contentIdx}`} flexDirection=\"column\">\n {preview.split('\\n').map((line, lineIdx) => (\n <Text color={theme.mutedText}>{line}</Text>\n ))}\n </Box>\n )\n }\n }\n return null\n })\n }\n return null\n })}\n </Box>\n )\n}\n\n/**\n * \u7D27\u51D1\u7248 TaskCard (\u7528\u4E8E\u7A7A\u95F4\u53D7\u9650\u7684\u573A\u666F)\n */\nexport function CompactTaskCard({\n subagent,\n}: {\n subagent: SubagentState\n}): React.ReactNode {\n const theme = getTheme()\n const { taskName, status, agentColor } = subagent\n\n const color = getAgentColor(agentColor, theme)\n const isRunning =\n status === 'initializing' || status === 'running' || status === 'queued'\n const statusIcon = getStatusIcon(status, isRunning)\n\n return (\n <Box flexDirection=\"row\">\n <Text color={color}>\n {statusIcon} {taskName}\n </Text>\n <Text color={theme.dimmedText}> \u00B7 {getStatusText(status)}</Text>\n </Box>\n )\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,107 @@
1
+ import { Box, Text } from "ink";
2
+ import React, { useState, useMemo, useCallback } from "react";
3
+ import { TabbedListView } from "./TabbedListView/TabbedListView.js";
4
+ import { useTeamMembers } from "../hooks/useTeamMembers.js";
5
+ import { getTheme } from "../utils/theme.js";
6
+ const STATUS_ICONS = {
7
+ working: "\u25D0",
8
+ planning: "\u25D1",
9
+ idle: "\u25CB",
10
+ stopped: "\u25CC"
11
+ };
12
+ const STATUS_COLORS = {
13
+ working: "yellow",
14
+ planning: "cyan",
15
+ idle: "green",
16
+ stopped: "gray"
17
+ };
18
+ function mapStatusToListStatus(status) {
19
+ switch (status) {
20
+ case "working":
21
+ return "running";
22
+ case "planning":
23
+ return "running";
24
+ case "idle":
25
+ return "enabled";
26
+ case "stopped":
27
+ return "disabled";
28
+ default:
29
+ return "enabled";
30
+ }
31
+ }
32
+ function TeamMemberItem({
33
+ item,
34
+ isFocused
35
+ }) {
36
+ const theme = getTheme();
37
+ const member = item.data;
38
+ if (!member) return null;
39
+ const icon = STATUS_ICONS[member.status] || "?";
40
+ const color = STATUS_COLORS[member.status] || "white";
41
+ return /* @__PURE__ */ React.createElement(Box, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React.createElement(Text, { color: isFocused ? "cyan" : void 0 }, isFocused ? "\u25B8" : " "), /* @__PURE__ */ React.createElement(Text, { color }, icon), /* @__PURE__ */ React.createElement(Text, { bold: isFocused, color: isFocused ? "white" : void 0 }, member.name), /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, "(", member.agentType, ")"), member.currentTaskId ? /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, "#", member.currentTaskId) : null);
42
+ }
43
+ function TeamMemberPanel({ isVisible, onClose, onFocusAgent }) {
44
+ const { members, teamName, hasActiveTeam } = useTeamMembers();
45
+ const [activeTab, setActiveTab] = useState("all");
46
+ const tabs = useMemo(() => {
47
+ const working = members.filter(
48
+ (m) => m.status === "working" || m.status === "planning"
49
+ ).length;
50
+ const idle = members.filter((m) => m.status === "idle").length;
51
+ return [
52
+ { id: "all", label: "All", badge: members.length },
53
+ { id: "active", label: "Active", badge: working },
54
+ { id: "idle", label: "Idle", badge: idle }
55
+ ];
56
+ }, [members]);
57
+ const items = useMemo(() => {
58
+ const filtered = activeTab === "all" ? members : activeTab === "active" ? members.filter(
59
+ (m) => m.status === "working" || m.status === "planning"
60
+ ) : members.filter((m) => m.status === "idle" || m.status === "stopped");
61
+ return filtered.map((m) => ({
62
+ id: m.id,
63
+ label: m.name,
64
+ description: `${m.agentType} \u2022 ${m.status}`,
65
+ status: mapStatusToListStatus(m.status),
66
+ data: m
67
+ }));
68
+ }, [members, activeTab]);
69
+ const isTeamLeadMember = (id) => id === "team-lead" || id.startsWith("team-lead@");
70
+ const handleSelect = useCallback(
71
+ (item) => {
72
+ if (onFocusAgent) {
73
+ onFocusAgent(isTeamLeadMember(item.id) ? null : item.id);
74
+ }
75
+ },
76
+ [onFocusAgent]
77
+ );
78
+ if (!isVisible || !hasActiveTeam) return null;
79
+ return /* @__PURE__ */ React.createElement(
80
+ TabbedListView,
81
+ {
82
+ title: `Team: ${teamName}`,
83
+ tabs,
84
+ activeTab,
85
+ onTabChange: setActiveTab,
86
+ items,
87
+ showTabs: false,
88
+ searchEnabled: false,
89
+ onClose,
90
+ onSelect: handleSelect,
91
+ isActive: isVisible,
92
+ footerHint: "\u2191\u2193 Navigate \xB7 Enter Focus \xB7 Esc Close",
93
+ renderItem: (item, isFocused, isSelected) => /* @__PURE__ */ React.createElement(
94
+ TeamMemberItem,
95
+ {
96
+ item,
97
+ isFocused,
98
+ isSelected: isSelected ?? false
99
+ }
100
+ )
101
+ }
102
+ );
103
+ }
104
+ export {
105
+ TeamMemberPanel
106
+ };
107
+ //# sourceMappingURL=TeamMemberPanel.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/components/TeamMemberPanel.tsx"],
4
+ "sourcesContent": ["/**\n * TeamMemberPanel Component\n *\n * Displays active team members during an Agent Teams session.\n * Reuses the TabbedListView component for consistent UI.\n * Toggled with Shift+Up keybinding.\n *\n * Selecting a member (Enter) delegates to onFocusAgent callback\n * which switches the REPL to full-screen agent focus mode.\n */\n\nimport { Box, Text } from 'ink'\nimport React, { useState, useMemo, useCallback } from 'react'\nimport { TabbedListView } from './TabbedListView/TabbedListView'\nimport type { ListItem, TabDefinition } from './TabbedListView/types'\nimport { useTeamMembers, type TeamMemberInfo } from '@hooks/useTeamMembers'\nimport { getTheme } from '@utils/theme'\nimport type { TeammateStatus } from '@minto-types/agentTeams'\n\nconst STATUS_ICONS: Record<TeammateStatus, string> = {\n working: '\\u25D0',\n planning: '\\u25D1',\n idle: '\\u25CB',\n stopped: '\\u25CC',\n}\n\nconst STATUS_COLORS: Record<TeammateStatus, string> = {\n working: 'yellow',\n planning: 'cyan',\n idle: 'green',\n stopped: 'gray',\n}\n\nfunction mapStatusToListStatus(status: TeammateStatus): ListItem['status'] {\n switch (status) {\n case 'working':\n return 'running'\n case 'planning':\n return 'running'\n case 'idle':\n return 'enabled'\n case 'stopped':\n return 'disabled'\n default:\n return 'enabled'\n }\n}\n\nfunction TeamMemberItem({\n item,\n isFocused,\n}: {\n item: ListItem\n isFocused: boolean\n isSelected: boolean\n}): React.ReactNode {\n const theme = getTheme()\n const member = item.data as TeamMemberInfo | undefined\n if (!member) return null\n\n const icon = STATUS_ICONS[member.status] || '?'\n const color = STATUS_COLORS[member.status] || 'white'\n\n return (\n <Box flexDirection=\"row\" gap={1}>\n {/* Cursor indicator for focused item */}\n <Text color={isFocused ? 'cyan' : undefined}>\n {isFocused ? '\u25B8' : ' '}\n </Text>\n <Text color={color}>{icon}</Text>\n <Text bold={isFocused} color={isFocused ? 'white' : undefined}>\n {member.name}\n </Text>\n <Text color={theme.secondaryText}>({member.agentType})</Text>\n {member.currentTaskId ? (\n <Text color={theme.secondaryText}>#{member.currentTaskId}</Text>\n ) : null}\n </Box>\n )\n}\n\ntype Props = {\n isVisible: boolean\n onClose: () => void\n onFocusAgent?: (agentId: string | null) => void\n}\n\nexport function TeamMemberPanel({ isVisible, onClose, onFocusAgent }: Props) {\n const { members, teamName, hasActiveTeam } = useTeamMembers()\n const [activeTab, setActiveTab] = useState('all')\n\n const tabs: TabDefinition[] = useMemo(() => {\n const working = members.filter(\n m => m.status === 'working' || m.status === 'planning',\n ).length\n const idle = members.filter(m => m.status === 'idle').length\n return [\n { id: 'all', label: 'All', badge: members.length },\n { id: 'active', label: 'Active', badge: working },\n { id: 'idle', label: 'Idle', badge: idle },\n ]\n }, [members])\n\n const items: ListItem[] = useMemo(() => {\n const filtered =\n activeTab === 'all'\n ? members\n : activeTab === 'active'\n ? members.filter(\n m => m.status === 'working' || m.status === 'planning',\n )\n : members.filter(m => m.status === 'idle' || m.status === 'stopped')\n\n return filtered.map(m => ({\n id: m.id,\n label: m.name,\n description: `${m.agentType} \\u2022 ${m.status}`,\n status: mapStatusToListStatus(m.status),\n data: m,\n }))\n }, [members, activeTab])\n\n // Detect team-lead member by id pattern (registered as \"team-lead@<teamName>\")\n const isTeamLeadMember = (id: string) =>\n id === 'team-lead' || id.startsWith('team-lead@')\n\n const handleSelect = useCallback(\n (item: ListItem) => {\n if (onFocusAgent) {\n // Team-lead maps to null (return to main view), others pass the id\n onFocusAgent(isTeamLeadMember(item.id) ? null : item.id)\n }\n },\n [onFocusAgent],\n )\n\n if (!isVisible || !hasActiveTeam) return null\n\n return (\n <TabbedListView\n title={`Team: ${teamName}`}\n tabs={tabs}\n activeTab={activeTab}\n onTabChange={setActiveTab}\n items={items}\n showTabs={false}\n searchEnabled={false}\n onClose={onClose}\n onSelect={handleSelect}\n isActive={isVisible}\n footerHint=\"\u2191\u2193 Navigate \u00B7 Enter Focus \u00B7 Esc Close\"\n renderItem={(item, isFocused, isSelected) => (\n <TeamMemberItem\n item={item}\n isFocused={isFocused}\n isSelected={isSelected ?? false}\n />\n )}\n />\n )\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,84 @@
1
+ import React, { useState } from "react";
2
+ import { Box, Text, useInput } from "ink";
3
+ import figures from "figures";
4
+ import { BRAND_GRADIENT, SEMANTIC_COLORS } from "../constants/colors.js";
5
+ import { getGlobalConfig, saveGlobalConfig } from "../utils/config.js";
6
+ import { t } from "../i18n/index.js";
7
+ const OPTIONS = [
8
+ {
9
+ id: "enabled",
10
+ label: t("thinking.enabled"),
11
+ description: t("thinking.enabledDesc")
12
+ },
13
+ {
14
+ id: "disabled",
15
+ label: t("thinking.disabled"),
16
+ description: t("thinking.disabledDesc")
17
+ }
18
+ ];
19
+ function ThinkingSelector({ onClose }) {
20
+ const config = getGlobalConfig();
21
+ const currentEnabled = !!config.thinking;
22
+ const initialIndex = currentEnabled ? 0 : 1;
23
+ const [selectedIndex, setSelectedIndex] = useState(initialIndex);
24
+ useInput((input, key) => {
25
+ if (key.escape) {
26
+ onClose();
27
+ return;
28
+ }
29
+ if (key.downArrow) {
30
+ setSelectedIndex((prev) => Math.min(prev + 1, OPTIONS.length - 1));
31
+ return;
32
+ }
33
+ if (key.upArrow) {
34
+ setSelectedIndex((prev) => Math.max(prev - 1, 0));
35
+ return;
36
+ }
37
+ const num = Number(input);
38
+ if (num >= 1 && num <= OPTIONS.length) {
39
+ const option = OPTIONS[num - 1];
40
+ const newThinking = option.id === "enabled";
41
+ saveGlobalConfig({ ...getGlobalConfig(), thinking: newThinking });
42
+ onClose();
43
+ return;
44
+ }
45
+ if (key.return) {
46
+ const selected = OPTIONS[selectedIndex];
47
+ const newThinking = selected.id === "enabled";
48
+ saveGlobalConfig({ ...getGlobalConfig(), thinking: newThinking });
49
+ onClose();
50
+ return;
51
+ }
52
+ });
53
+ return /* @__PURE__ */ React.createElement(
54
+ Box,
55
+ {
56
+ flexDirection: "column",
57
+ borderStyle: "round",
58
+ borderColor: BRAND_GRADIENT.START,
59
+ paddingX: 1,
60
+ paddingY: 1
61
+ },
62
+ /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", marginBottom: 1 }, /* @__PURE__ */ React.createElement(Text, { bold: true, color: BRAND_GRADIENT.START }, t("thinking.title")), /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.secondary }, t("thinking.subtitle"))),
63
+ OPTIONS.map((option, index) => {
64
+ const isSelected = index === selectedIndex;
65
+ const isCurrent = option.id === "enabled" && currentEnabled || option.id === "disabled" && !currentEnabled;
66
+ return /* @__PURE__ */ React.createElement(Box, { key: option.id }, /* @__PURE__ */ React.createElement(
67
+ Text,
68
+ {
69
+ color: isSelected ? BRAND_GRADIENT.START : void 0,
70
+ bold: isSelected
71
+ },
72
+ isSelected ? `${figures.pointer} ` : " ",
73
+ index + 1,
74
+ ". ",
75
+ option.label
76
+ ), isCurrent && /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.success }, " \u2714"), /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.dim }, " ", option.description));
77
+ }),
78
+ /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.dim }, t("rewind.enterToContinue"), " \xB7 ", t("rewind.escToExit")))
79
+ );
80
+ }
81
+ export {
82
+ ThinkingSelector
83
+ };
84
+ //# sourceMappingURL=ThinkingSelector.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/components/ThinkingSelector.tsx"],
4
+ "sourcesContent": ["/**\n * ThinkingSelector \u2014 Toggle thinking mode overlay\n *\n * Matches RewindPanel visual style (round border, brand colors).\n * Activated via Option+T (\u2325T).\n */\n\nimport React, { useState } from 'react'\nimport { Box, Text, useInput } from 'ink'\nimport figures from 'figures'\nimport { BRAND_GRADIENT, SEMANTIC_COLORS } from '@constants/colors'\nimport { getGlobalConfig, saveGlobalConfig } from '@utils/config'\nimport { t } from '@i18n'\n\ninterface Props {\n onClose: () => void\n}\n\ninterface ThinkingOption {\n id: 'enabled' | 'disabled'\n label: string\n description: string\n}\n\nconst OPTIONS: ThinkingOption[] = [\n {\n id: 'enabled',\n label: t('thinking.enabled'),\n description: t('thinking.enabledDesc'),\n },\n {\n id: 'disabled',\n label: t('thinking.disabled'),\n description: t('thinking.disabledDesc'),\n },\n]\n\nexport function ThinkingSelector({ onClose }: Props): React.ReactNode {\n const config = getGlobalConfig()\n const currentEnabled = !!config.thinking\n const initialIndex = currentEnabled ? 0 : 1\n const [selectedIndex, setSelectedIndex] = useState(initialIndex)\n\n useInput((input, key) => {\n if (key.escape) {\n onClose()\n return\n }\n\n if (key.downArrow) {\n setSelectedIndex(prev => Math.min(prev + 1, OPTIONS.length - 1))\n return\n }\n\n if (key.upArrow) {\n setSelectedIndex(prev => Math.max(prev - 1, 0))\n return\n }\n\n // Number keys 1-2\n const num = Number(input)\n if (num >= 1 && num <= OPTIONS.length) {\n const option = OPTIONS[num - 1]\n const newThinking = option.id === 'enabled'\n saveGlobalConfig({ ...getGlobalConfig(), thinking: newThinking })\n onClose()\n return\n }\n\n if (key.return) {\n const selected = OPTIONS[selectedIndex]\n const newThinking = selected.id === 'enabled'\n saveGlobalConfig({ ...getGlobalConfig(), thinking: newThinking })\n onClose()\n return\n }\n })\n\n return (\n <Box\n flexDirection=\"column\"\n borderStyle=\"round\"\n borderColor={BRAND_GRADIENT.START}\n paddingX={1}\n paddingY={1}\n >\n {/* Header */}\n <Box flexDirection=\"column\" marginBottom={1}>\n <Text bold color={BRAND_GRADIENT.START}>\n {t('thinking.title')}\n </Text>\n <Text color={SEMANTIC_COLORS.secondary}>{t('thinking.subtitle')}</Text>\n </Box>\n\n {/* Options */}\n {OPTIONS.map((option, index) => {\n const isSelected = index === selectedIndex\n const isCurrent =\n (option.id === 'enabled' && currentEnabled) ||\n (option.id === 'disabled' && !currentEnabled)\n\n return (\n <Box key={option.id}>\n <Text\n color={isSelected ? BRAND_GRADIENT.START : undefined}\n bold={isSelected}\n >\n {isSelected ? `${figures.pointer} ` : ' '}\n {index + 1}. {option.label}\n </Text>\n {isCurrent && <Text color={SEMANTIC_COLORS.success}> \u2714</Text>}\n <Text color={SEMANTIC_COLORS.dim}> {option.description}</Text>\n </Box>\n )\n })}\n\n {/* Footer */}\n <Box marginTop={1}>\n <Text color={SEMANTIC_COLORS.dim}>\n {t('rewind.enterToContinue')} \u00B7 {t('rewind.escToExit')}\n </Text>\n </Box>\n </Box>\n )\n}\n"],
5
+ "mappings": "AAOA,OAAO,SAAS,gBAAgB;AAChC,SAAS,KAAK,MAAM,gBAAgB;AACpC,OAAO,aAAa;AACpB,SAAS,gBAAgB,uBAAuB;AAChD,SAAS,iBAAiB,wBAAwB;AAClD,SAAS,SAAS;AAYlB,MAAM,UAA4B;AAAA,EAChC;AAAA,IACE,IAAI;AAAA,IACJ,OAAO,EAAE,kBAAkB;AAAA,IAC3B,aAAa,EAAE,sBAAsB;AAAA,EACvC;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,OAAO,EAAE,mBAAmB;AAAA,IAC5B,aAAa,EAAE,uBAAuB;AAAA,EACxC;AACF;AAEO,SAAS,iBAAiB,EAAE,QAAQ,GAA2B;AACpE,QAAM,SAAS,gBAAgB;AAC/B,QAAM,iBAAiB,CAAC,CAAC,OAAO;AAChC,QAAM,eAAe,iBAAiB,IAAI;AAC1C,QAAM,CAAC,eAAe,gBAAgB,IAAI,SAAS,YAAY;AAE/D,WAAS,CAAC,OAAO,QAAQ;AACvB,QAAI,IAAI,QAAQ;AACd,cAAQ;AACR;AAAA,IACF;AAEA,QAAI,IAAI,WAAW;AACjB,uBAAiB,UAAQ,KAAK,IAAI,OAAO,GAAG,QAAQ,SAAS,CAAC,CAAC;AAC/D;AAAA,IACF;AAEA,QAAI,IAAI,SAAS;AACf,uBAAiB,UAAQ,KAAK,IAAI,OAAO,GAAG,CAAC,CAAC;AAC9C;AAAA,IACF;AAGA,UAAM,MAAM,OAAO,KAAK;AACxB,QAAI,OAAO,KAAK,OAAO,QAAQ,QAAQ;AACrC,YAAM,SAAS,QAAQ,MAAM,CAAC;AAC9B,YAAM,cAAc,OAAO,OAAO;AAClC,uBAAiB,EAAE,GAAG,gBAAgB,GAAG,UAAU,YAAY,CAAC;AAChE,cAAQ;AACR;AAAA,IACF;AAEA,QAAI,IAAI,QAAQ;AACd,YAAM,WAAW,QAAQ,aAAa;AACtC,YAAM,cAAc,SAAS,OAAO;AACpC,uBAAiB,EAAE,GAAG,gBAAgB,GAAG,UAAU,YAAY,CAAC;AAChE,cAAQ;AACR;AAAA,IACF;AAAA,EACF,CAAC;AAED,SACE;AAAA,IAAC;AAAA;AAAA,MACC,eAAc;AAAA,MACd,aAAY;AAAA,MACZ,aAAa,eAAe;AAAA,MAC5B,UAAU;AAAA,MACV,UAAU;AAAA;AAAA,IAGV,oCAAC,OAAI,eAAc,UAAS,cAAc,KACxC,oCAAC,QAAK,MAAI,MAAC,OAAO,eAAe,SAC9B,EAAE,gBAAgB,CACrB,GACA,oCAAC,QAAK,OAAO,gBAAgB,aAAY,EAAE,mBAAmB,CAAE,CAClE;AAAA,IAGC,QAAQ,IAAI,CAAC,QAAQ,UAAU;AAC9B,YAAM,aAAa,UAAU;AAC7B,YAAM,YACH,OAAO,OAAO,aAAa,kBAC3B,OAAO,OAAO,cAAc,CAAC;AAEhC,aACE,oCAAC,OAAI,KAAK,OAAO,MACf;AAAA,QAAC;AAAA;AAAA,UACC,OAAO,aAAa,eAAe,QAAQ;AAAA,UAC3C,MAAM;AAAA;AAAA,QAEL,aAAa,GAAG,QAAQ,OAAO,MAAM;AAAA,QACrC,QAAQ;AAAA,QAAE;AAAA,QAAG,OAAO;AAAA,MACvB,GACC,aAAa,oCAAC,QAAK,OAAO,gBAAgB,WAAS,SAAE,GACtD,oCAAC,QAAK,OAAO,gBAAgB,OAAK,KAAE,OAAO,WAAY,CACzD;AAAA,IAEJ,CAAC;AAAA,IAGD,oCAAC,OAAI,WAAW,KACd,oCAAC,QAAK,OAAO,gBAAgB,OAC1B,EAAE,wBAAwB,GAAE,UAAI,EAAE,kBAAkB,CACvD,CACF;AAAA,EACF;AAEJ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,26 @@
1
+ import { Box, Text } from "ink";
2
+ import * as React from "react";
3
+ import { useTerminalSize } from "../hooks/useTerminalSize.js";
4
+ import { SEMANTIC_COLORS } from "../constants/colors.js";
5
+ function TitledDivider({
6
+ title,
7
+ dividerChar = "\u2500",
8
+ titleColor = SEMANTIC_COLORS.secondary,
9
+ dividerColor = SEMANTIC_COLORS.dim,
10
+ width
11
+ }) {
12
+ const { columns } = useTerminalSize();
13
+ const effectiveWidth = width ?? columns;
14
+ if (!title) {
15
+ return /* @__PURE__ */ React.createElement(Text, { color: dividerColor }, dividerChar.repeat(Math.max(0, effectiveWidth)));
16
+ }
17
+ const titleWithPadding = ` ${title} `;
18
+ const remaining = effectiveWidth - titleWithPadding.length;
19
+ const leftLen = Math.floor(remaining / 2);
20
+ const rightLen = remaining - leftLen;
21
+ return /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { color: dividerColor }, dividerChar.repeat(Math.max(0, leftLen))), /* @__PURE__ */ React.createElement(Text, { color: titleColor }, titleWithPadding), /* @__PURE__ */ React.createElement(Text, { color: dividerColor }, dividerChar.repeat(Math.max(0, rightLen))));
22
+ }
23
+ export {
24
+ TitledDivider
25
+ };
26
+ //# sourceMappingURL=TitledDivider.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/components/TitledDivider.tsx"],
4
+ "sourcesContent": ["/**\n * TitledDivider Component\n *\n * Renders a horizontal divider line with an optional centered title.\n * Used for transcript mode indicators (Ctrl+E show/hide previous messages).\n *\n * Example output:\n * \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 ctrl+e to show 10 previous messages \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n */\n\nimport { Box, Text } from 'ink'\nimport * as React from 'react'\nimport { useTerminalSize } from '@hooks/useTerminalSize'\nimport { SEMANTIC_COLORS } from '@constants/colors'\n\ninterface TitledDividerProps {\n title?: string\n dividerChar?: string\n titleColor?: string\n dividerColor?: string\n width?: number\n}\n\nexport function TitledDivider({\n title,\n dividerChar = '\u2500',\n titleColor = SEMANTIC_COLORS.secondary,\n dividerColor = SEMANTIC_COLORS.dim,\n width,\n}: TitledDividerProps): React.ReactNode {\n const { columns } = useTerminalSize()\n const effectiveWidth = width ?? columns\n\n if (!title) {\n return (\n <Text color={dividerColor}>\n {dividerChar.repeat(Math.max(0, effectiveWidth))}\n </Text>\n )\n }\n\n const titleWithPadding = ` ${title} `\n const remaining = effectiveWidth - titleWithPadding.length\n const leftLen = Math.floor(remaining / 2)\n const rightLen = remaining - leftLen\n\n return (\n <Box>\n <Text color={dividerColor}>\n {dividerChar.repeat(Math.max(0, leftLen))}\n </Text>\n <Text color={titleColor}>{titleWithPadding}</Text>\n <Text color={dividerColor}>\n {dividerChar.repeat(Math.max(0, rightLen))}\n </Text>\n </Box>\n )\n}\n"],
5
+ "mappings": "AAUA,SAAS,KAAK,YAAY;AAC1B,YAAY,WAAW;AACvB,SAAS,uBAAuB;AAChC,SAAS,uBAAuB;AAUzB,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA,cAAc;AAAA,EACd,aAAa,gBAAgB;AAAA,EAC7B,eAAe,gBAAgB;AAAA,EAC/B;AACF,GAAwC;AACtC,QAAM,EAAE,QAAQ,IAAI,gBAAgB;AACpC,QAAM,iBAAiB,SAAS;AAEhC,MAAI,CAAC,OAAO;AACV,WACE,oCAAC,QAAK,OAAO,gBACV,YAAY,OAAO,KAAK,IAAI,GAAG,cAAc,CAAC,CACjD;AAAA,EAEJ;AAEA,QAAM,mBAAmB,IAAI,KAAK;AAClC,QAAM,YAAY,iBAAiB,iBAAiB;AACpD,QAAM,UAAU,KAAK,MAAM,YAAY,CAAC;AACxC,QAAM,WAAW,YAAY;AAE7B,SACE,oCAAC,WACC,oCAAC,QAAK,OAAO,gBACV,YAAY,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,CAC1C,GACA,oCAAC,QAAK,OAAO,cAAa,gBAAiB,GAC3C,oCAAC,QAAK,OAAO,gBACV,YAAY,OAAO,KAAK,IAAI,GAAG,QAAQ,CAAC,CAC3C,CACF;AAEJ;",
6
+ "names": []
7
+ }
@@ -2,9 +2,9 @@ import React, { useRef, useMemo, memo } from "react";
2
2
  import { Box, Text } from "ink";
3
3
  import { getTheme } from "../utils/theme.js";
4
4
  import { SYMBOLS, getTodoStatusSymbol } from "../constants/symbols.js";
5
- import { formatNumber, formatTokenUsage } from "../utils/format.js";
5
+ import { getTokenDisplay } from "../utils/tokenProgress.js";
6
6
  import { sample } from "lodash-es";
7
- import { getMainStreamingState } from "../utils/streamingState.js";
7
+ import { getMainStreamingState, getStreamingState } from "../utils/streamingState.js";
8
8
  import { getSessionState } from "../utils/sessionState.js";
9
9
  import { useUnifiedAnimation } from "../utils/animationManager.js";
10
10
  import {
@@ -39,17 +39,30 @@ const SpinnerLine = memo(function SpinnerLine2({
39
39
  currentTaskActiveForm,
40
40
  todos,
41
41
  shouldShowTodos,
42
- fallbackMessage
42
+ fallbackMessage,
43
+ focusedAgentId
43
44
  }) {
44
45
  const theme = getTheme();
45
- const startTimeRef = useRef(Date.now());
46
- const { spinnerFrame, elapsedTime } = useUnifiedAnimation({
46
+ const fallbackStartRef = useRef(Date.now());
47
+ const tickRef = useRef(0);
48
+ const { spinnerFrame, dataTick } = useUnifiedAnimation({
47
49
  enabled: true,
48
- startTime: startTimeRef.current,
50
+ // startTime is updated below after reading streaming state
51
+ startTime: fallbackStartRef.current,
49
52
  spinnerFrameCount: SHIMMER_COLORS.length,
50
53
  componentId: "todo-panel-spinner"
51
54
  });
52
- const streamState = useMemo(() => getMainStreamingState(), [spinnerFrame]);
55
+ tickRef.current = spinnerFrame;
56
+ const latestStreamState = useMemo(
57
+ () => focusedAgentId ? getStreamingState(focusedAgentId) : getMainStreamingState(),
58
+ // eslint-disable-next-line react-hooks/exhaustive-deps
59
+ [focusedAgentId, dataTick]
60
+ );
61
+ const startTime = latestStreamState.turnStartedAt ?? fallbackStartRef.current;
62
+ const correctedElapsed = Math.max(
63
+ 0,
64
+ Math.floor((Date.now() - startTime) / 1e3)
65
+ );
53
66
  const getCurrentTaskDisplay = () => {
54
67
  if (currentTaskActiveForm) {
55
68
  return currentTaskActiveForm;
@@ -58,9 +71,9 @@ const SpinnerLine = memo(function SpinnerLine2({
58
71
  if (inProgressTodo?.activeForm) {
59
72
  return inProgressTodo.activeForm;
60
73
  }
61
- switch (streamState.phase) {
74
+ switch (latestStreamState.phase) {
62
75
  case "tool_use":
63
- return streamState.toolName ? `Using ${streamState.toolName}` : "Executing tool";
76
+ return latestStreamState.toolName ? `Using ${latestStreamState.toolName}` : "Executing tool";
64
77
  case "generating":
65
78
  return "Generating response";
66
79
  case "waiting":
@@ -78,23 +91,9 @@ const SpinnerLine = memo(function SpinnerLine2({
78
91
  };
79
92
  const shimmerColor = getShimmerColor(spinnerFrame);
80
93
  const spinnerIconFrame = spinnerFrame % SYMBOLS.THINKING_FRAMES.length;
81
- const getTokenDisplay = () => {
82
- if (streamState.inputTokens || streamState.outputTokens) {
83
- return formatTokenUsage(streamState.inputTokens, streamState.outputTokens);
84
- }
85
- if (streamState.receivedChars && streamState.receivedChars > 0) {
86
- const approxOutputTokens = Math.round(streamState.receivedChars / 3);
87
- if (streamState.sentChars && streamState.sentChars > 0) {
88
- const approxInputTokens = Math.round(streamState.sentChars / 3);
89
- return `\u2191 ~${formatNumber(approxInputTokens)} \xB7 \u2193 ~${formatNumber(approxOutputTokens)}`;
90
- }
91
- return `\u2193 ~${formatNumber(approxOutputTokens)}`;
92
- }
93
- return "";
94
- };
95
- const tokenUsage = getTokenDisplay();
96
- const thinkingDuration = streamState.thinkingDurationMs ? Math.floor(streamState.thinkingDurationMs / 1e3) : null;
97
- return /* @__PURE__ */ React.createElement(Box, { flexDirection: "row", flexWrap: "nowrap" }, /* @__PURE__ */ React.createElement(Text, { color: shimmerColor }, SYMBOLS.THINKING_FRAMES[spinnerIconFrame], " "), /* @__PURE__ */ React.createElement(Text, { color: shimmerColor, bold: true }, getCurrentTaskDisplay()), /* @__PURE__ */ React.createElement(Text, { color: shimmerColor }, "\u2026 "), /* @__PURE__ */ React.createElement(Text, { color: BRAND_GRADIENT.START }, "(", /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.secondary }, "esc esc"), " to cancel \xB7", " ", /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.secondary }, formatTime(elapsedTime)), tokenUsage && /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.secondary }, " \xB7 ", tokenUsage), thinkingDuration !== null && thinkingDuration > 0 && /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.secondary }, " ", "\xB7 thinking ", thinkingDuration, "s"), shouldShowTodos && /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.secondary }, " ", "\xB7 ", /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.secondary }, "ctrl+t"), " to hide"), ")"), getSessionState("currentError") && /* @__PURE__ */ React.createElement(Text, { color: SYMBOL_COLORS.error }, " ", "\xB7 ", getSessionState("currentError")));
94
+ const { formatted: tokenUsage } = getTokenDisplay(focusedAgentId);
95
+ const thinkingDuration = latestStreamState.thinkingDurationMs ? Math.floor(latestStreamState.thinkingDurationMs / 1e3) : null;
96
+ return /* @__PURE__ */ React.createElement(Box, { flexDirection: "row", flexWrap: "nowrap" }, /* @__PURE__ */ React.createElement(Text, { color: shimmerColor }, SYMBOLS.THINKING_FRAMES[spinnerIconFrame], " "), /* @__PURE__ */ React.createElement(Text, { color: shimmerColor, bold: true }, getCurrentTaskDisplay()), /* @__PURE__ */ React.createElement(Text, { color: shimmerColor }, "\u2026 "), /* @__PURE__ */ React.createElement(Text, { color: BRAND_GRADIENT.START }, "(", /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.secondary }, "esc"), " to cancel \xB7", " ", /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.secondary }, formatTime(correctedElapsed)), tokenUsage && /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.secondary }, " \xB7 ", tokenUsage), latestStreamState.phase === "thinking" && /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.secondary }, " \xB7 thinking"), thinkingDuration !== null && thinkingDuration > 0 && /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.secondary }, " ", "\xB7 thinking ", thinkingDuration, "s"), shouldShowTodos && /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.secondary }, " ", "\xB7 ", /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.secondary }, "ctrl+t"), " to hide"), ")"), getSessionState("currentError") && /* @__PURE__ */ React.createElement(Text, { color: SYMBOL_COLORS.error }, " ", "\xB7 ", getSessionState("currentError")));
98
97
  });
99
98
  const SPINNER_MESSAGES = [
100
99
  "Thinking",
@@ -112,7 +111,8 @@ const TodoPanel = memo(function TodoPanel2({
112
111
  currentTaskActiveForm,
113
112
  elapsedTime: initialElapsedTime = 0,
114
113
  isLoading = true,
115
- showTodoList = true
114
+ showTodoList = true,
115
+ focusedAgentId
116
116
  }) {
117
117
  const theme = getTheme();
118
118
  const fallbackMessage = useRef(sample(SPINNER_MESSAGES) || "Thinking");
@@ -123,7 +123,7 @@ const TodoPanel = memo(function TodoPanel2({
123
123
  if (shouldShowTodos) {
124
124
  return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React.createElement(Box, { flexDirection: "row" }, /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.dim }, "\u25CB "), /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.dim }, hasIncompleteTasks ? t("ui.todo.tasksRemaining", {
125
125
  count: todos.filter((todo) => todo.status !== "completed").length
126
- }) : t("ui.todo.allDone"))), /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, todos.map((todo, idx) => /* @__PURE__ */ React.createElement(React.Fragment, { key: `todo-${idx}-${todo.content.slice(0, 20)}` }, /* @__PURE__ */ React.createElement(
126
+ }) : t("ui.todo.allDone"))), /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, todos.map((todo, idx) => /* @__PURE__ */ React.createElement(React.Fragment, { key: todo.id }, /* @__PURE__ */ React.createElement(
127
127
  TodoItemClaudeStyle,
128
128
  {
129
129
  todo,
@@ -140,12 +140,13 @@ const TodoPanel = memo(function TodoPanel2({
140
140
  currentTaskActiveForm,
141
141
  todos,
142
142
  shouldShowTodos,
143
- fallbackMessage: fallbackMessage.current
143
+ fallbackMessage: fallbackMessage.current,
144
+ focusedAgentId
144
145
  }
145
146
  ), shouldShowTodos && /* @__PURE__ */ React.createElement(TodoList, { todos, theme }));
146
147
  });
147
148
  const TodoList = memo(function TodoList2({ todos, theme }) {
148
- return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, todos.map((todo, idx) => /* @__PURE__ */ React.createElement(React.Fragment, { key: `todo-${idx}-${todo.content.slice(0, 20)}` }, /* @__PURE__ */ React.createElement(TodoItemClaudeStyle, { todo, theme, isFirst: idx === 0 }))));
149
+ return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, todos.map((todo, idx) => /* @__PURE__ */ React.createElement(React.Fragment, { key: todo.id }, /* @__PURE__ */ React.createElement(TodoItemClaudeStyle, { todo, theme, isFirst: idx === 0 }))));
149
150
  });
150
151
  const TodoItemClaudeStyle = memo(function TodoItemClaudeStyle2({
151
152
  todo,