@within-7/minto 0.1.7 → 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 (481) 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 +7 -1
  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.map +2 -2
  283. package/dist/tools/BaseTool.js +72 -0
  284. package/dist/tools/BaseTool.js.map +7 -0
  285. package/dist/tools/BashOutputTool/BashOutputToolResultMessage.js +3 -0
  286. package/dist/tools/BashOutputTool/BashOutputToolResultMessage.js.map +2 -2
  287. package/dist/tools/BashTool/BashTool.js +60 -3
  288. package/dist/tools/BashTool/BashTool.js.map +2 -2
  289. package/dist/tools/BashTool/BashToolResultMessage.js +3 -0
  290. package/dist/tools/BashTool/BashToolResultMessage.js.map +2 -2
  291. package/dist/tools/BashTool/OutputLine.js +54 -0
  292. package/dist/tools/BashTool/OutputLine.js.map +2 -2
  293. package/dist/tools/BashTool/prompt.js +192 -3
  294. package/dist/tools/BashTool/prompt.js.map +2 -2
  295. package/dist/tools/FileEditTool/FileEditTool.js +29 -4
  296. package/dist/tools/FileEditTool/FileEditTool.js.map +2 -2
  297. package/dist/tools/FileWriteTool/FileWriteTool.js +5 -5
  298. package/dist/tools/FileWriteTool/FileWriteTool.js.map +2 -2
  299. package/dist/tools/GlobTool/GlobTool.js +4 -2
  300. package/dist/tools/GlobTool/GlobTool.js.map +2 -2
  301. package/dist/tools/GrepTool/GrepTool.js +36 -7
  302. package/dist/tools/GrepTool/GrepTool.js.map +2 -2
  303. package/dist/tools/KillShellTool/KillShellToolResultMessage.js +3 -0
  304. package/dist/tools/KillShellTool/KillShellToolResultMessage.js.map +2 -2
  305. package/dist/tools/ListMcpResourcesTool/ListMcpResourcesTool.js +109 -0
  306. package/dist/tools/ListMcpResourcesTool/ListMcpResourcesTool.js.map +7 -0
  307. package/dist/tools/ListMcpResourcesTool/prompt.js +19 -0
  308. package/dist/tools/ListMcpResourcesTool/prompt.js.map +7 -0
  309. package/dist/tools/LspTool/LspTool.js +664 -0
  310. package/dist/tools/LspTool/LspTool.js.map +7 -0
  311. package/dist/tools/LspTool/prompt.js +27 -0
  312. package/dist/tools/LspTool/prompt.js.map +7 -0
  313. package/dist/tools/MCPTool/MCPTool.js +9 -1
  314. package/dist/tools/MCPTool/MCPTool.js.map +2 -2
  315. package/dist/tools/MemoryReadTool/MemoryReadTool.js +19 -6
  316. package/dist/tools/MemoryReadTool/MemoryReadTool.js.map +2 -2
  317. package/dist/tools/MemoryWriteTool/MemoryWriteTool.js +6 -6
  318. package/dist/tools/MemoryWriteTool/MemoryWriteTool.js.map +2 -2
  319. package/dist/tools/MultiEditTool/MultiEditTool.js +19 -2
  320. package/dist/tools/MultiEditTool/MultiEditTool.js.map +2 -2
  321. package/dist/tools/NotebookEditTool/NotebookEditTool.js +5 -1
  322. package/dist/tools/NotebookEditTool/NotebookEditTool.js.map +2 -2
  323. package/dist/tools/NotebookReadTool/NotebookReadTool.js.map +2 -2
  324. package/dist/tools/PlanModeTool/EnterPlanModeTool.js +74 -0
  325. package/dist/tools/PlanModeTool/EnterPlanModeTool.js.map +7 -0
  326. package/dist/tools/PlanModeTool/ExitPlanModeTool.js +108 -0
  327. package/dist/tools/PlanModeTool/ExitPlanModeTool.js.map +7 -0
  328. package/dist/tools/PlanModeTool/prompt.js +94 -0
  329. package/dist/tools/PlanModeTool/prompt.js.map +7 -0
  330. package/dist/tools/ReadMcpResourceTool/ReadMcpResourceTool.js +130 -0
  331. package/dist/tools/ReadMcpResourceTool/ReadMcpResourceTool.js.map +7 -0
  332. package/dist/tools/ReadMcpResourceTool/prompt.js +17 -0
  333. package/dist/tools/ReadMcpResourceTool/prompt.js.map +7 -0
  334. package/dist/tools/SkillTool/SkillTool.js +6 -1
  335. package/dist/tools/SkillTool/SkillTool.js.map +2 -2
  336. package/dist/tools/SlashCommandTool/SlashCommandTool.js +260 -0
  337. package/dist/tools/SlashCommandTool/SlashCommandTool.js.map +7 -0
  338. package/dist/tools/SlashCommandTool/prompt.js +35 -0
  339. package/dist/tools/SlashCommandTool/prompt.js.map +7 -0
  340. package/dist/tools/TaskOutputTool/TaskOutputTool.js +189 -0
  341. package/dist/tools/TaskOutputTool/TaskOutputTool.js.map +7 -0
  342. package/dist/tools/TaskOutputTool/prompt.js +15 -0
  343. package/dist/tools/TaskOutputTool/prompt.js.map +7 -0
  344. package/dist/tools/TaskTool/TaskTool.js +302 -104
  345. package/dist/tools/TaskTool/TaskTool.js.map +2 -2
  346. package/dist/tools/TaskTool/prompt.js.map +2 -2
  347. package/dist/tools/TodoWriteTool/TodoWriteTool.js +42 -77
  348. package/dist/tools/TodoWriteTool/TodoWriteTool.js.map +2 -2
  349. package/dist/tools/URLFetcherTool/URLFetcherTool.js +4 -1
  350. package/dist/tools/URLFetcherTool/URLFetcherTool.js.map +2 -2
  351. package/dist/tools/URLFetcherTool/cache.js +55 -8
  352. package/dist/tools/URLFetcherTool/cache.js.map +2 -2
  353. package/dist/tools.js +31 -2
  354. package/dist/tools.js.map +2 -2
  355. package/dist/types/hooks.js +4 -0
  356. package/dist/types/hooks.js.map +2 -2
  357. package/dist/types/marketplace.js.map +2 -2
  358. package/dist/types/messageGroup.js +36 -0
  359. package/dist/types/messageGroup.js.map +7 -0
  360. package/dist/types/plugin.js.map +2 -2
  361. package/dist/types/thinking.js +1 -0
  362. package/dist/types/thinking.js.map +7 -0
  363. package/dist/utils/BackgroundShellManager.js +136 -39
  364. package/dist/utils/BackgroundShellManager.js.map +2 -2
  365. package/dist/utils/MessageBatchBuffer.js +102 -0
  366. package/dist/utils/MessageBatchBuffer.js.map +7 -0
  367. package/dist/utils/PersistentShell.js +151 -1
  368. package/dist/utils/PersistentShell.js.map +2 -2
  369. package/dist/utils/agentLoader.js +1 -23
  370. package/dist/utils/agentLoader.js.map +2 -2
  371. package/dist/utils/agentTranscripts.js +641 -0
  372. package/dist/utils/agentTranscripts.js.map +7 -0
  373. package/dist/utils/animationManager.js +213 -0
  374. package/dist/utils/animationManager.js.map +7 -0
  375. package/dist/utils/animationSync.js +110 -0
  376. package/dist/utils/animationSync.js.map +7 -0
  377. package/dist/utils/asyncFile.js +215 -0
  378. package/dist/utils/asyncFile.js.map +7 -0
  379. package/dist/utils/backgroundAgentManager.js +231 -0
  380. package/dist/utils/backgroundAgentManager.js.map +7 -0
  381. package/dist/utils/config.js +63 -7
  382. package/dist/utils/config.js.map +2 -2
  383. package/dist/utils/conversationRecovery.js +19 -0
  384. package/dist/utils/conversationRecovery.js.map +2 -2
  385. package/dist/utils/exit.js +73 -0
  386. package/dist/utils/exit.js.map +7 -0
  387. package/dist/utils/format.js +73 -5
  388. package/dist/utils/format.js.map +2 -2
  389. package/dist/utils/generators.js +76 -6
  390. package/dist/utils/generators.js.map +2 -2
  391. package/dist/utils/globalErrorHandler.js +149 -0
  392. package/dist/utils/globalErrorHandler.js.map +7 -0
  393. package/dist/utils/groupHandlers/index.js +8 -0
  394. package/dist/utils/groupHandlers/index.js.map +7 -0
  395. package/dist/utils/groupHandlers/parallelTasksHandler.js +140 -0
  396. package/dist/utils/groupHandlers/parallelTasksHandler.js.map +7 -0
  397. package/dist/utils/groupHandlers/taskHandler.js +104 -0
  398. package/dist/utils/groupHandlers/taskHandler.js.map +7 -0
  399. package/dist/utils/groupHandlers/types.js +1 -0
  400. package/dist/utils/groupHandlers/types.js.map +7 -0
  401. package/dist/utils/logRotation.js +224 -0
  402. package/dist/utils/logRotation.js.map +7 -0
  403. package/dist/utils/marketplaceManager.js +3 -5
  404. package/dist/utils/marketplaceManager.js.map +2 -2
  405. package/dist/utils/memSafety.js +264 -0
  406. package/dist/utils/memSafety.js.map +7 -0
  407. package/dist/utils/messageGroupManager.js +274 -0
  408. package/dist/utils/messageGroupManager.js.map +7 -0
  409. package/dist/utils/messages.js +13 -4
  410. package/dist/utils/messages.js.map +2 -2
  411. package/dist/utils/model.js +119 -15
  412. package/dist/utils/model.js.map +3 -3
  413. package/dist/utils/permissions/filesystem.js +157 -5
  414. package/dist/utils/permissions/filesystem.js.map +2 -2
  415. package/dist/utils/plan/planMode.js +143 -0
  416. package/dist/utils/plan/planMode.js.map +7 -0
  417. package/dist/utils/pluginLoader.js +17 -21
  418. package/dist/utils/pluginLoader.js.map +2 -2
  419. package/dist/utils/ripgrep.js +55 -2
  420. package/dist/utils/ripgrep.js.map +2 -2
  421. package/dist/utils/sanitizeInput.js +32 -0
  422. package/dist/utils/sanitizeInput.js.map +7 -0
  423. package/dist/utils/secureKeyStorage.js +312 -0
  424. package/dist/utils/secureKeyStorage.js.map +7 -0
  425. package/dist/utils/session/sessionPlugins.js +67 -0
  426. package/dist/utils/session/sessionPlugins.js.map +7 -0
  427. package/dist/utils/taskDisplayUtils.js +257 -0
  428. package/dist/utils/taskDisplayUtils.js.map +7 -0
  429. package/dist/utils/teamConfig.js +2 -1
  430. package/dist/utils/teamConfig.js.map +2 -2
  431. package/dist/utils/todoStorage.js +92 -2
  432. package/dist/utils/todoStorage.js.map +2 -2
  433. package/dist/utils/toolTimeout.js +136 -0
  434. package/dist/utils/toolTimeout.js.map +7 -0
  435. package/dist/utils/tooling/safeRender.js +115 -0
  436. package/dist/utils/tooling/safeRender.js.map +7 -0
  437. package/dist/utils/userFriendlyError.js +346 -0
  438. package/dist/utils/userFriendlyError.js.map +7 -0
  439. package/dist/utils/vendor/ripgrep/arm64-darwin/rg +0 -0
  440. package/dist/version.js +2 -2
  441. package/dist/version.js.map +1 -1
  442. package/package.json +14 -4
  443. package/scripts/postinstall.js +128 -38
  444. package/dist/commands/agents.js +0 -2086
  445. package/dist/commands/agents.js.map +0 -7
  446. package/dist/commands/build.js +0 -74
  447. package/dist/commands/build.js.map +0 -7
  448. package/dist/commands/compression.js +0 -57
  449. package/dist/commands/compression.js.map +0 -7
  450. package/dist/commands/listen.js +0 -37
  451. package/dist/commands/listen.js.map +0 -7
  452. package/dist/commands/login.js +0 -37
  453. package/dist/commands/login.js.map +0 -7
  454. package/dist/commands/logout.js +0 -33
  455. package/dist/commands/logout.js.map +0 -7
  456. package/dist/commands/mcp.js +0 -40
  457. package/dist/commands/mcp.js.map +0 -7
  458. package/dist/commands/mcp_refresh.js +0 -40
  459. package/dist/commands/mcp_refresh.js.map +0 -7
  460. package/dist/commands/modelstatus.js +0 -21
  461. package/dist/commands/modelstatus.js.map +0 -7
  462. package/dist/commands/onboarding.js +0 -36
  463. package/dist/commands/onboarding.js.map +0 -7
  464. package/dist/commands/plugin-interactive.js +0 -446
  465. package/dist/commands/plugin-interactive.js.map +0 -7
  466. package/dist/commands/pr_comments.js +0 -61
  467. package/dist/commands/pr_comments.js.map +0 -7
  468. package/dist/commands/release-notes.js +0 -30
  469. package/dist/commands/release-notes.js.map +0 -7
  470. package/dist/commands/review.js +0 -51
  471. package/dist/commands/review.js.map +0 -7
  472. package/dist/components/Bug.js +0 -147
  473. package/dist/components/Bug.js.map +0 -7
  474. package/dist/components/ModelSelector.js +0 -2062
  475. package/dist/components/ModelSelector.js.map +0 -7
  476. package/dist/components/ModelStatusDisplay.js +0 -87
  477. package/dist/components/ModelStatusDisplay.js.map +0 -7
  478. package/dist/entrypoints/cli-wrapper.js +0 -61
  479. package/dist/entrypoints/cli-wrapper.js.map +0 -7
  480. package/dist/screens/Doctor.js +0 -22
  481. package/dist/screens/Doctor.js.map +0 -7
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/components/SubagentProgress.tsx"],
4
- "sourcesContent": ["import React, { useState, useEffect } from 'react'\nimport { Box, Text } from 'ink'\nimport { getTheme } from '@utils/theme'\nimport { formatNumber, formatDuration } from '@utils/format'\nimport { SYMBOLS } from '@constants/symbols'\nimport { getAgentColor } from '@constants/colors'\nimport { SpinnerSymbol } from './SpinnerSymbol'\nimport type { SubagentState } from '@minto-types/subagent'\nimport { Message } from './Message'\nimport type { Tool } from '@tool'\n\ninterface SubagentProgressProps {\n subagent: SubagentState\n isExpanded: boolean\n tools?: Tool[]\n verbose?: boolean\n debug?: boolean\n}\n\n/**\n * \u5355\u4E2A Subagent \u7684\u8FDB\u5EA6\u663E\u793A\u7EC4\u4EF6\n *\n * \u7EDF\u4E00\u663E\u793A\u683C\u5F0F\uFF1A\n * - \u7B2C1\u884C\uFF1ASpinner + Task\u540D\u79F0 + Agent\u7C7B\u578B + Status + Metrics\u6458\u8981\n * - Ctrl+O\u5C55\u5F00\u540E\uFF1A\u663E\u793A\u8BE6\u7EC6\u7684\u6D88\u606F\u6D41\n */\nexport function SubagentProgress({\n subagent,\n isExpanded,\n tools = [],\n verbose = false,\n debug = false,\n}: SubagentProgressProps) {\n const theme = getTheme()\n const { metrics, taskName, status, messages, agentType, agentColor } =\n subagent\n\n // \u83B7\u53D6 agent \u989C\u8272\n const color = getAgentColor(agentColor, theme)\n\n // \u5224\u65AD\u662F\u5426\u6B63\u5728\u8FD0\u884C\uFF08\u51B3\u5B9A\u662F\u5426\u95EA\u70C1\uFF09\n const isRunning =\n status === 'initializing' || status === 'running' || status === 'queued'\n\n // \u5B9E\u65F6\u66F4\u65B0\u65F6\u95F4\uFF1A\u6BCF\u79D2\u5F3A\u5236\u91CD\u65B0\u6E32\u67D3\n const [, setTick] = useState(0)\n useEffect(() => {\n if (isRunning) {\n // \u53EA\u5728\u4EFB\u52A1\u8FD0\u884C\u65F6\u542F\u52A8\u5B9A\u65F6\u5668\n const timer = setInterval(() => {\n setTick(prev => prev + 1)\n }, 1000) // \u6BCF\u79D2\u66F4\u65B0\u4E00\u6B21\n\n return () => clearInterval(timer)\n }\n }, [isRunning])\n\n // \u8BA1\u7B97\u6301\u7EED\u65F6\u95F4\uFF08\u5728\u6BCF\u6B21\u6E32\u67D3\u65F6\u91CD\u65B0\u8BA1\u7B97\uFF09\n const duration = metrics.endTime\n ? metrics.endTime - metrics.startTime\n : Date.now() - metrics.startTime\n\n // \u72B6\u6001\u6587\u672C\n const statusText = getStatusText(status)\n\n return (\n <Box flexDirection=\"column\" marginY={0}>\n {/* \u7B2C1\u884C\uFF1A\u4EFB\u52A1\u540D\u79F0 */}\n <Box flexDirection=\"row\">\n <SpinnerSymbol isRunning={isRunning} color={agentColor} />\n <Text> Task({taskName})</Text>\n </Box>\n\n {/* \u7B2C2\u884C\uFF1A\u8BE6\u7EC6\u4FE1\u606F\uFF08\u72B6\u6001\u3001\u6307\u6807\uFF09 - Claude Code CLI \u6807\u51C6\u683C\u5F0F */}\n <Box flexDirection=\"row\">\n <Text color={theme.dim}> \u23BFS1 </Text>\n <Text color={getStatusColor(status, theme)}>{statusText}</Text>\n <Text color={theme.secondaryText}> \u00B7 </Text>\n <Text color={theme.secondaryText}>\n {metrics.toolUseCount} tool use{metrics.toolUseCount !== 1 ? 's' : ''}\n </Text>\n <Text color={theme.secondaryText}> \u00B7 </Text>\n <Text color={theme.secondaryText}>\n {formatNumber(metrics.tokenCount)} tokens\n </Text>\n <Text color={theme.secondaryText}> \u00B7 </Text>\n <Text color={theme.secondaryText}>{formatDuration(duration)}</Text>\n {!isExpanded && <Text color={theme.dim}> \u00B7 (ctrl-o to expand)</Text>}\n </Box>\n\n {/* Ctrl+O \u5C55\u5F00\u540E\u663E\u793A\u8BE6\u7EC6\u6D88\u606F\u6D41 - Claude Code CLI \u6807\u51C6\u683C\u5F0F */}\n {isExpanded && (\n <Box flexDirection=\"column\" marginTop={0}>\n {renderExpandedView(subagent, theme, tools, verbose)}\n </Box>\n )}\n </Box>\n )\n}\n\n/**\n * \u6E32\u67D3\u5C55\u5F00\u89C6\u56FE - Claude Code CLI \u6807\u51C6\u683C\u5F0F\n */\nfunction renderExpandedView(\n subagent: SubagentState,\n theme: ReturnType<typeof getTheme>,\n tools: Tool[],\n verbose: boolean,\n) {\n const { prompt, messages, status, metrics } = subagent\n const duration = metrics.endTime\n ? metrics.endTime - metrics.startTime\n : Date.now() - metrics.startTime\n\n return (\n <Box flexDirection=\"column\">\n {/* Prompt \u90E8\u5206 */}\n {prompt && (\n <Box flexDirection=\"column\">\n <Box flexDirection=\"row\">\n <Text color={theme.dim}> \u23BFS2 </Text>\n <Text>Prompt:</Text>\n </Box>\n <Box flexDirection=\"column\" marginLeft={7}>\n <Text>{prompt}</Text>\n </Box>\n </Box>\n )}\n\n {/* \u5DE5\u5177\u8C03\u7528\u3001\u7ED3\u679C\u548C\u54CD\u5E94 */}\n {messages\n .map((msg, idx) => {\n if (msg.type === 'assistant') {\n return msg.message.content\n .map((content, contentIdx) => {\n if (content.type === 'tool_use') {\n const tool = tools.find(t => t.name === content.name)\n const toolName =\n (tool?.userFacingName &&\n typeof tool.userFacingName === 'function'\n ? tool.userFacingName()\n : undefined) || content.name\n return (\n <Box key={`${idx}-${contentIdx}`} flexDirection=\"row\">\n <Text color={theme.dim}> \u23BFS3 </Text>\n <Text>{toolName}</Text>\n </Box>\n )\n } else if (content.type === 'text' && content.text.trim()) {\n // \u663E\u793A Response \u6587\u672C\n const lines = content.text.trim().split('\\n')\n return (\n <Box key={`${idx}-${contentIdx}`} flexDirection=\"column\">\n <Box flexDirection=\"row\">\n <Text color={theme.dim}> \u23BFS4 </Text>\n <Text>Response:</Text>\n </Box>\n <Box flexDirection=\"column\" marginLeft={7}>\n {lines.map((line, lineIdx) => (\n <Text>{line}</Text>\n ))}\n </Box>\n </Box>\n )\n }\n return null\n })\n .filter(item => item !== null)\n } else if (msg.type === 'user') {\n // \u5DE5\u5177\u7ED3\u679C\n return msg.message.content\n .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 > 3\n ? lines.slice(0, 3).join('\\n') + '\\n...'\n : resultContent.trim()\n return (\n <Box key={`${idx}-${contentIdx}`} flexDirection=\"column\">\n <Box flexDirection=\"row\">\n <Text color={theme.dim}> \u23BFS5 </Text>\n <Text color={theme.secondaryText}>\n {preview.split('\\n')[0]}\n </Text>\n </Box>\n {preview\n .split('\\n')\n .slice(1)\n .map((line, lineIdx) => (\n <Box key={lineIdx} marginLeft={7}>\n <Text color={theme.secondaryText}>{line}</Text>\n </Box>\n ))}\n </Box>\n )\n }\n }\n return null\n })\n .filter(item => item !== null)\n }\n return null\n })\n .flat()\n .filter(item => item !== null)}\n\n {/* Done \u72B6\u6001\uFF08\u4EC5\u5728\u5B8C\u6210\u65F6\u663E\u793A\uFF09 */}\n {status === 'completed' && (\n <Box flexDirection=\"row\">\n <Text color={theme.dim}> \u23BFS6 </Text>\n <Text color={theme.success}>Done</Text>\n <Text color={theme.secondaryText}>\n {' '}\n ({metrics.toolUseCount} tool use\n {metrics.toolUseCount !== 1 ? 's' : ''} \u00B7{' '}\n {formatNumber(metrics.tokenCount)} tokens \u00B7{' '}\n {formatDuration(duration)})\n </Text>\n </Box>\n )}\n </Box>\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 'Initialize\u2026'\n case 'queued':\n return 'Queued\u2026'\n case 'running':\n return 'In progress\u2026'\n case 'completed':\n return 'Completed'\n case 'error':\n return 'Error'\n }\n}\n\n/**\n * \u83B7\u53D6\u72B6\u6001\u989C\u8272\n */\nfunction getStatusColor(\n status: SubagentState['status'],\n theme: ReturnType<typeof getTheme>,\n): string {\n switch (status) {\n case 'initializing':\n return theme.secondaryText\n case 'queued':\n return theme.secondaryText\n case 'running':\n return theme.minto\n case 'completed':\n return theme.success\n case 'error':\n return theme.error\n }\n}\n\n/**\n * \u6E32\u67D3\u6D88\u606F\u9884\u89C8 - \u4F7F\u7528\u5B8C\u6574\u7684 Message \u7EC4\u4EF6\u6765\u663E\u793A\u5DE5\u5177\u8C03\u7528\u548C\u7ED3\u679C\n */\nfunction renderMessagePreview(\n message: any,\n theme: ReturnType<typeof getTheme>,\n tools: Tool[],\n verbose: boolean,\n) {\n // \u4F7F\u7528 Message \u7EC4\u4EF6\u6765\u6E32\u67D3\uFF0C\u8FD9\u6837\u53EF\u4EE5\u663E\u793A\u5B8C\u6574\u7684\u5DE5\u5177\u8C03\u7528\u548C\u7ED3\u679C\n return (\n <Box flexDirection=\"column\" marginLeft={2}>\n <Message\n message={message}\n messages={[message]}\n addMargin={false}\n tools={tools}\n verbose={verbose}\n debug={false}\n erroredToolUseIDs={new Set()}\n inProgressToolUseIDs={new Set()}\n unresolvedToolUseIDs={new Set()}\n shouldAnimate={false}\n shouldShowDot={false}\n />\n </Box>\n )\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import React, { useRef } from 'react'\nimport { Box, Text } from 'ink'\nimport { getTheme } from '@utils/theme'\nimport { formatNumber, formatDuration } from '@utils/format'\nimport { SYMBOLS } from '@constants/symbols'\nimport { getAgentColor } from '@constants/colors'\nimport { SpinnerSymbol } from './SpinnerSymbol'\nimport type { SubagentState } from '@minto-types/subagent'\nimport { Message } from './Message'\nimport type { Tool } from '@tool'\nimport { useUnifiedAnimation } from '@utils/animationManager'\n\ninterface SubagentProgressProps {\n subagent: SubagentState\n isExpanded: boolean\n tools?: Tool[]\n verbose?: boolean\n debug?: boolean\n}\n\n/**\n * \u5355\u4E2A Subagent \u7684\u8FDB\u5EA6\u663E\u793A\u7EC4\u4EF6\n *\n * \u7EDF\u4E00\u663E\u793A\u683C\u5F0F\uFF1A\n * - \u7B2C1\u884C\uFF1ASpinner + Task\u540D\u79F0 + Agent\u7C7B\u578B + Status + Metrics\u6458\u8981\n * - Ctrl+O\u5C55\u5F00\u540E\uFF1A\u663E\u793A\u8BE6\u7EC6\u7684\u6D88\u606F\u6D41\n *\n * \u4F7F\u7528\u7EDF\u4E00\u52A8\u753B\u7BA1\u7406\u5668\u4EE3\u66FF setInterval\uFF0C\u51CF\u5C11\u5C4F\u5E55\u95EA\u70C1\n */\nexport function SubagentProgress({\n subagent,\n isExpanded,\n tools = [],\n verbose = false,\n debug = false,\n}: SubagentProgressProps) {\n const theme = getTheme()\n const { metrics, taskName, status, messages, agentType, agentColor } =\n subagent\n\n // \u83B7\u53D6 agent \u989C\u8272\n const color = getAgentColor(agentColor, theme)\n\n // \u5224\u65AD\u662F\u5426\u6B63\u5728\u8FD0\u884C\uFF08\u51B3\u5B9A\u662F\u5426\u95EA\u70C1\uFF09\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: `subagent-${subagent.id}`,\n })\n\n // \u8BA1\u7B97\u6301\u7EED\u65F6\u95F4\uFF08\u5728\u6BCF\u6B21\u6E32\u67D3\u65F6\u91CD\u65B0\u8BA1\u7B97\uFF09\n const duration = metrics.endTime\n ? metrics.endTime - metrics.startTime\n : Date.now() - metrics.startTime\n\n // \u72B6\u6001\u6587\u672C\n const statusText = getStatusText(status)\n\n return (\n <Box flexDirection=\"column\" marginY={0}>\n {/* \u7B2C1\u884C\uFF1A\u4EFB\u52A1\u540D\u79F0 */}\n <Box flexDirection=\"row\">\n <SpinnerSymbol isRunning={isRunning} color={agentColor} />\n <Text> Task({taskName})</Text>\n </Box>\n\n {/* \u7B2C2\u884C\uFF1A\u8BE6\u7EC6\u4FE1\u606F\uFF08\u72B6\u6001\u3001\u6307\u6807\uFF09 - Claude Code CLI \u6807\u51C6\u683C\u5F0F */}\n <Box flexDirection=\"row\">\n <Text color={theme.dim}> \u23BFS1 </Text>\n <Text color={getStatusColor(status, theme)}>{statusText}</Text>\n <Text color={theme.secondaryText}> \u00B7 </Text>\n <Text color={theme.secondaryText}>\n {metrics.toolUseCount} tool use{metrics.toolUseCount !== 1 ? 's' : ''}\n </Text>\n <Text color={theme.secondaryText}> \u00B7 </Text>\n <Text color={theme.secondaryText}>\n {formatNumber(metrics.tokenCount)} tokens\n </Text>\n <Text color={theme.secondaryText}> \u00B7 </Text>\n <Text color={theme.secondaryText}>{formatDuration(duration)}</Text>\n {!isExpanded && <Text color={theme.dim}> \u00B7 (ctrl-o to expand)</Text>}\n </Box>\n\n {/* Ctrl+O \u5C55\u5F00\u540E\u663E\u793A\u8BE6\u7EC6\u6D88\u606F\u6D41 - Claude Code CLI \u6807\u51C6\u683C\u5F0F */}\n {isExpanded && (\n <Box flexDirection=\"column\" marginTop={0}>\n {renderExpandedView(subagent, theme, tools, verbose)}\n </Box>\n )}\n </Box>\n )\n}\n\n/**\n * \u6E32\u67D3\u5C55\u5F00\u89C6\u56FE - Claude Code CLI \u6807\u51C6\u683C\u5F0F\n */\nfunction renderExpandedView(\n subagent: SubagentState,\n theme: ReturnType<typeof getTheme>,\n tools: Tool[],\n verbose: boolean,\n) {\n const { prompt, messages, status, metrics } = subagent\n const duration = metrics.endTime\n ? metrics.endTime - metrics.startTime\n : Date.now() - metrics.startTime\n\n return (\n <Box flexDirection=\"column\">\n {/* Prompt \u90E8\u5206 */}\n {prompt && (\n <Box flexDirection=\"column\">\n <Box flexDirection=\"row\">\n <Text color={theme.dim}> \u23BFS2 </Text>\n <Text>Prompt:</Text>\n </Box>\n <Box flexDirection=\"column\" marginLeft={7}>\n <Text>{prompt}</Text>\n </Box>\n </Box>\n )}\n\n {/* \u5DE5\u5177\u8C03\u7528\u3001\u7ED3\u679C\u548C\u54CD\u5E94 */}\n {messages\n .map((msg, idx) => {\n if (msg.type === 'assistant') {\n return msg.message.content\n .map((content, contentIdx) => {\n if (content.type === 'tool_use') {\n const tool = tools.find(t => t.name === content.name)\n const toolName =\n (tool?.userFacingName &&\n typeof tool.userFacingName === 'function'\n ? tool.userFacingName()\n : undefined) || content.name\n return (\n <Box key={`${idx}-${contentIdx}`} flexDirection=\"row\">\n <Text color={theme.dim}> \u23BFS3 </Text>\n <Text>{toolName}</Text>\n </Box>\n )\n } else if (content.type === 'text' && content.text.trim()) {\n // \u663E\u793A Response \u6587\u672C\n const lines = content.text.trim().split('\\n')\n return (\n <Box key={`${idx}-${contentIdx}`} flexDirection=\"column\">\n <Box flexDirection=\"row\">\n <Text color={theme.dim}> \u23BFS4 </Text>\n <Text>Response:</Text>\n </Box>\n <Box flexDirection=\"column\" marginLeft={7}>\n {lines.map((line, lineIdx) => (\n <Text>{line}</Text>\n ))}\n </Box>\n </Box>\n )\n }\n return null\n })\n .filter(item => item !== null)\n } else if (msg.type === 'user') {\n // \u5DE5\u5177\u7ED3\u679C\n return msg.message.content\n .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 > 3\n ? lines.slice(0, 3).join('\\n') + '\\n...'\n : resultContent.trim()\n return (\n <Box key={`${idx}-${contentIdx}`} flexDirection=\"column\">\n <Box flexDirection=\"row\">\n <Text color={theme.dim}> \u23BFS5 </Text>\n <Text color={theme.secondaryText}>\n {preview.split('\\n')[0]}\n </Text>\n </Box>\n {preview\n .split('\\n')\n .slice(1)\n .map((line, lineIdx) => (\n <Box key={lineIdx} marginLeft={7}>\n <Text color={theme.secondaryText}>{line}</Text>\n </Box>\n ))}\n </Box>\n )\n }\n }\n return null\n })\n .filter(item => item !== null)\n }\n return null\n })\n .flat()\n .filter(item => item !== null)}\n\n {/* Done \u72B6\u6001\uFF08\u4EC5\u5728\u5B8C\u6210\u65F6\u663E\u793A\uFF09 */}\n {status === 'completed' && (\n <Box flexDirection=\"row\">\n <Text color={theme.dim}> \u23BFS6 </Text>\n <Text color={theme.success}>Done</Text>\n <Text color={theme.secondaryText}>\n {' '}\n ({metrics.toolUseCount} tool use\n {metrics.toolUseCount !== 1 ? 's' : ''} \u00B7{' '}\n {formatNumber(metrics.tokenCount)} tokens \u00B7{' '}\n {formatDuration(duration)})\n </Text>\n </Box>\n )}\n </Box>\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 'Initialize\u2026'\n case 'queued':\n return 'Queued\u2026'\n case 'running':\n return 'In progress\u2026'\n case 'completed':\n return 'Done'\n case 'error':\n return 'Error'\n }\n}\n\n/**\n * \u83B7\u53D6\u72B6\u6001\u989C\u8272\n */\nfunction getStatusColor(\n status: SubagentState['status'],\n theme: ReturnType<typeof getTheme>,\n): string {\n switch (status) {\n case 'initializing':\n return theme.secondaryText\n case 'queued':\n return theme.secondaryText\n case 'running':\n return theme.minto\n case 'completed':\n return theme.success\n case 'error':\n return theme.error\n }\n}\n\n/**\n * \u6E32\u67D3\u6D88\u606F\u9884\u89C8 - \u4F7F\u7528\u5B8C\u6574\u7684 Message \u7EC4\u4EF6\u6765\u663E\u793A\u5DE5\u5177\u8C03\u7528\u548C\u7ED3\u679C\n */\nfunction renderMessagePreview(\n message: any,\n theme: ReturnType<typeof getTheme>,\n tools: Tool[],\n verbose: boolean,\n) {\n // \u4F7F\u7528 Message \u7EC4\u4EF6\u6765\u6E32\u67D3\uFF0C\u8FD9\u6837\u53EF\u4EE5\u663E\u793A\u5B8C\u6574\u7684\u5DE5\u5177\u8C03\u7528\u548C\u7ED3\u679C\n return (\n <Box flexDirection=\"column\" marginLeft={2}>\n <Message\n message={message}\n messages={[message]}\n addMargin={false}\n tools={tools}\n verbose={verbose}\n debug={false}\n erroredToolUseIDs={new Set()}\n inProgressToolUseIDs={new Set()}\n unresolvedToolUseIDs={new Set()}\n shouldAnimate={false}\n shouldShowDot={false}\n />\n </Box>\n )\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,8 +1,9 @@
1
- import React, { useState, useEffect } from "react";
1
+ import React, { useRef } from "react";
2
2
  import { Box, Text } from "ink";
3
3
  import { getTheme } from "../utils/theme.js";
4
4
  import { formatNumber, formatDuration } from "../utils/format.js";
5
5
  import { getAgentColor } from "../constants/colors.js";
6
+ import { useUnifiedAnimation } from "../utils/animationManager.js";
6
7
  function TaskCard({
7
8
  subagent,
8
9
  isExpanded = false,
@@ -16,15 +17,13 @@ function TaskCard({
16
17
  const { metrics, taskName, status, messages, agentType, agentColor } = subagent;
17
18
  const color = getAgentColor(agentColor, theme);
18
19
  const isRunning = status === "initializing" || status === "running" || status === "queued";
19
- const [, setTick] = useState(0);
20
- useEffect(() => {
21
- if (isRunning) {
22
- const timer = setInterval(() => {
23
- setTick((prev) => prev + 1);
24
- }, 1e3);
25
- return () => clearInterval(timer);
26
- }
27
- }, [isRunning]);
20
+ const startTimeRef = useRef(metrics.startTime);
21
+ const { elapsedTime } = useUnifiedAnimation({
22
+ enabled: isRunning,
23
+ startTime: startTimeRef.current,
24
+ spinnerFrameCount: 1,
25
+ componentId: `task-card-${subagent.id}`
26
+ });
28
27
  const duration = metrics.endTime ? metrics.endTime - metrics.startTime : Date.now() - metrics.startTime;
29
28
  const statusIcon = getStatusIcon(status, isRunning);
30
29
  const statusText = getStatusText(status);
@@ -48,8 +47,12 @@ function TaskCard({
48
47
  }
49
48
  } else if (msg.type === "progress") {
50
49
  prefix = "\u2699 ";
51
- const blocks = msg.content.message.content;
52
- content = blocks.filter((block) => block.type === "text").map((block) => block.text).join(" ");
50
+ if ("type" in msg.content && msg.content.type === "streaming") {
51
+ content = msg.content.stdout || msg.content.stderr || "(streaming...)";
52
+ } else if ("message" in msg.content) {
53
+ const blocks = msg.content.message.content;
54
+ content = blocks.filter((block) => block.type === "text").map((block) => block.text).join(" ");
55
+ }
53
56
  }
54
57
  if (!content || content.trim().length === 0) {
55
58
  return null;
@@ -83,7 +86,7 @@ function getStatusText(status) {
83
86
  case "running":
84
87
  return "Running";
85
88
  case "completed":
86
- return "Completed";
89
+ return "Done";
87
90
  case "error":
88
91
  return "Error";
89
92
  }
@@ -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 */\n\nimport React, { useState, useEffect } from 'react'\nimport { Box, Text } from 'ink'\nimport { getTheme } from '@utils/theme'\nimport { formatNumber, formatDuration } from '@utils/format'\nimport { getAgentColor } from '@constants/colors'\nimport type { SubagentState } from '@minto-types/subagent'\nimport type { Tool } from '@tool'\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 // \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 // \u5B9E\u65F6\u66F4\u65B0\u65F6\u95F4\n const [, setTick] = useState(0)\n useEffect(() => {\n if (isRunning) {\n const timer = setInterval(() => {\n setTick(prev => prev + 1)\n }, 1000)\n return () => clearInterval(timer)\n }\n }, [isRunning])\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(metrics.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 const blocks = msg.content.message.content\n content = blocks\n .filter((block: any) => block.type === 'text')\n .map((block: any) => block.text)\n .join(' ')\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(metrics.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={theme.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 'Completed'\n case 'error':\n return 'Error'\n }\n}\n\n/**\n * \u83B7\u53D6\u72B6\u6001\u989C\u8272 (\u4F7F\u7528 Claude Code CLI \u914D\u8272)\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 '#ADD8E6' // Pending Task (\u6D45\u84DD)\n case 'running':\n return theme.brand // #D4BBFF (\u54C1\u724C\u8272\uFF0C\u8868\u793A\u6D3B\u8DC3)\n case 'completed':\n return theme.success // #3DDC84 (\u9C9C\u7EFF)\n case 'error':\n return theme.error // #FF5555 (\u9C9C\u7EA2)\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 } from '@constants/colors'\nimport type { SubagentState } from '@minto-types/subagent'\nimport type { Tool } from '@tool'\nimport { useUnifiedAnimation } from '@utils/animationManager'\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 // \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(metrics.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(metrics.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={theme.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 Claude Code CLI \u914D\u8272)\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 '#ADD8E6' // Pending Task (\u6D45\u84DD)\n case 'running':\n return theme.brand // #D4BBFF (\u54C1\u724C\u8272\uFF0C\u8868\u793A\u6D3B\u8DC3)\n case 'completed':\n return theme.success // #3DDC84 (\u9C9C\u7EFF)\n case 'error':\n return theme.error // #FF5555 (\u9C9C\u7EA2)\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
  }
@@ -20,7 +20,7 @@ function TodoChangeBlock({
20
20
  marginLeft: 2,
21
21
  marginTop: changes.length > 0 ? 1 : 0
22
22
  },
23
- /* @__PURE__ */ React.createElement(Text, { color: theme.dim }, stats.pending, " pending \xB7 ", stats.inProgress, " in progress \xB7", " ", stats.completed, " completed")
23
+ /* @__PURE__ */ React.createElement(Text, { color: theme.dim }, stats.pending, " pending \xB7 ", stats.inProgress, " in progress \xB7", " ", stats.completed, " done")
24
24
  ));
25
25
  }
26
26
  export {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/components/TodoChangeBlock.tsx"],
4
- "sourcesContent": ["/**\n * TodoChangeBlock - Renders Todo changes in the conversation flow\n *\n * Displays:\n * - Tool call header \"\uD83D\uDD27 Updated task list\"\n * - Individual changes via TodoChangeLine\n * - Summary statistics (pending/in_progress/completed)\n *\n * When TodoWriteTool is called, this component shows what changed\n * in the conversation timeline, separate from the TodoPanel.\n */\n\nimport { Box, Text } from 'ink'\nimport React from 'react'\nimport type { TodoChange } from '@utils/todoChangeCalculator'\nimport type { TodoItem } from '@utils/todoStorage'\nimport { TodoChangeLine } from './TodoChangeLine'\nimport { getTheme } from '@utils/theme'\n\ninterface TodoChangeBlockProps {\n /** List of changes to display */\n changes: TodoChange[]\n /** Current complete todo list (for statistics) */\n todos: TodoItem[]\n /** Indentation level (default: 1) */\n indent?: number\n}\n\nexport function TodoChangeBlock({\n changes,\n todos,\n indent = 1,\n}: TodoChangeBlockProps) {\n const theme = getTheme()\n\n // Calculate statistics\n const stats = {\n pending: todos.filter(t => t.status === 'pending').length,\n inProgress: todos.filter(t => t.status === 'in_progress').length,\n completed: todos.filter(t => t.status === 'completed').length,\n }\n\n return (\n <Box flexDirection=\"column\" marginLeft={indent * 2}>\n {/* Tool call header */}\n <Box flexDirection=\"row\">\n <Text color={theme.brand}>\uD83D\uDD27 </Text>\n <Text>Updated task list</Text>\n </Box>\n\n {/* Changes display */}\n {changes.length > 0 && (\n <Box flexDirection=\"column\" marginLeft={2}>\n {changes.map((change, idx) => (\n <Box key={`${change.todoId}-${idx}`}>\n <TodoChangeLine change={change} />\n </Box>\n ))}\n </Box>\n )}\n\n {/* Summary statistics */}\n <Box\n flexDirection=\"row\"\n marginLeft={2}\n marginTop={changes.length > 0 ? 1 : 0}\n >\n <Text color={theme.dim}>\n {stats.pending} pending \u00B7 {stats.inProgress} in progress \u00B7{' '}\n {stats.completed} completed\n </Text>\n </Box>\n </Box>\n )\n}\n"],
5
- "mappings": "AAYA,SAAS,KAAK,YAAY;AAC1B,OAAO,WAAW;AAGlB,SAAS,sBAAsB;AAC/B,SAAS,gBAAgB;AAWlB,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA,SAAS;AACX,GAAyB;AACvB,QAAM,QAAQ,SAAS;AAGvB,QAAM,QAAQ;AAAA,IACZ,SAAS,MAAM,OAAO,OAAK,EAAE,WAAW,SAAS,EAAE;AAAA,IACnD,YAAY,MAAM,OAAO,OAAK,EAAE,WAAW,aAAa,EAAE;AAAA,IAC1D,WAAW,MAAM,OAAO,OAAK,EAAE,WAAW,WAAW,EAAE;AAAA,EACzD;AAEA,SACE,oCAAC,OAAI,eAAc,UAAS,YAAY,SAAS,KAE/C,oCAAC,OAAI,eAAc,SACjB,oCAAC,QAAK,OAAO,MAAM,SAAO,YAAG,GAC7B,oCAAC,YAAK,mBAAiB,CACzB,GAGC,QAAQ,SAAS,KAChB,oCAAC,OAAI,eAAc,UAAS,YAAY,KACrC,QAAQ,IAAI,CAAC,QAAQ,QACpB,oCAAC,OAAI,KAAK,GAAG,OAAO,MAAM,IAAI,GAAG,MAC/B,oCAAC,kBAAe,QAAgB,CAClC,CACD,CACH,GAIF;AAAA,IAAC;AAAA;AAAA,MACC,eAAc;AAAA,MACd,YAAY;AAAA,MACZ,WAAW,QAAQ,SAAS,IAAI,IAAI;AAAA;AAAA,IAEpC,oCAAC,QAAK,OAAO,MAAM,OAChB,MAAM,SAAQ,kBAAY,MAAM,YAAW,qBAAe,KAC1D,MAAM,WAAU,YACnB;AAAA,EACF,CACF;AAEJ;",
4
+ "sourcesContent": ["/**\n * TodoChangeBlock - Renders Todo changes in the conversation flow\n *\n * Displays:\n * - Tool call header \"\uD83D\uDD27 Updated task list\"\n * - Individual changes via TodoChangeLine\n * - Summary statistics (pending/in_progress/completed)\n *\n * When TodoWriteTool is called, this component shows what changed\n * in the conversation timeline, separate from the TodoPanel.\n */\n\nimport { Box, Text } from 'ink'\nimport React from 'react'\nimport type { TodoChange } from '@utils/todoChangeCalculator'\nimport type { TodoItem } from '@utils/todoStorage'\nimport { TodoChangeLine } from './TodoChangeLine'\nimport { getTheme } from '@utils/theme'\n\ninterface TodoChangeBlockProps {\n /** List of changes to display */\n changes: TodoChange[]\n /** Current complete todo list (for statistics) */\n todos: TodoItem[]\n /** Indentation level (default: 1) */\n indent?: number\n}\n\nexport function TodoChangeBlock({\n changes,\n todos,\n indent = 1,\n}: TodoChangeBlockProps) {\n const theme = getTheme()\n\n // Calculate statistics\n const stats = {\n pending: todos.filter(t => t.status === 'pending').length,\n inProgress: todos.filter(t => t.status === 'in_progress').length,\n completed: todos.filter(t => t.status === 'completed').length,\n }\n\n return (\n <Box flexDirection=\"column\" marginLeft={indent * 2}>\n {/* Tool call header */}\n <Box flexDirection=\"row\">\n <Text color={theme.brand}>\uD83D\uDD27 </Text>\n <Text>Updated task list</Text>\n </Box>\n\n {/* Changes display */}\n {changes.length > 0 && (\n <Box flexDirection=\"column\" marginLeft={2}>\n {changes.map((change, idx) => (\n <Box key={`${change.todoId}-${idx}`}>\n <TodoChangeLine change={change} />\n </Box>\n ))}\n </Box>\n )}\n\n {/* Summary statistics */}\n <Box\n flexDirection=\"row\"\n marginLeft={2}\n marginTop={changes.length > 0 ? 1 : 0}\n >\n <Text color={theme.dim}>\n {stats.pending} pending \u00B7 {stats.inProgress} in progress \u00B7{' '}\n {stats.completed} done\n </Text>\n </Box>\n </Box>\n )\n}\n"],
5
+ "mappings": "AAYA,SAAS,KAAK,YAAY;AAC1B,OAAO,WAAW;AAGlB,SAAS,sBAAsB;AAC/B,SAAS,gBAAgB;AAWlB,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA,SAAS;AACX,GAAyB;AACvB,QAAM,QAAQ,SAAS;AAGvB,QAAM,QAAQ;AAAA,IACZ,SAAS,MAAM,OAAO,OAAK,EAAE,WAAW,SAAS,EAAE;AAAA,IACnD,YAAY,MAAM,OAAO,OAAK,EAAE,WAAW,aAAa,EAAE;AAAA,IAC1D,WAAW,MAAM,OAAO,OAAK,EAAE,WAAW,WAAW,EAAE;AAAA,EACzD;AAEA,SACE,oCAAC,OAAI,eAAc,UAAS,YAAY,SAAS,KAE/C,oCAAC,OAAI,eAAc,SACjB,oCAAC,QAAK,OAAO,MAAM,SAAO,YAAG,GAC7B,oCAAC,YAAK,mBAAiB,CACzB,GAGC,QAAQ,SAAS,KAChB,oCAAC,OAAI,eAAc,UAAS,YAAY,KACrC,QAAQ,IAAI,CAAC,QAAQ,QACpB,oCAAC,OAAI,KAAK,GAAG,OAAO,MAAM,IAAI,GAAG,MAC/B,oCAAC,kBAAe,QAAgB,CAClC,CACD,CACH,GAIF;AAAA,IAAC;AAAA;AAAA,MACC,eAAc;AAAA,MACd,YAAY;AAAA,MACZ,WAAW,QAAQ,SAAS,IAAI,IAAI;AAAA;AAAA,IAEpC,oCAAC,QAAK,OAAO,MAAM,OAChB,MAAM,SAAQ,kBAAY,MAAM,YAAW,qBAAe,KAC1D,MAAM,WAAU,OACnB;AAAA,EACF,CACF;AAEJ;",
6
6
  "names": []
7
7
  }
@@ -1,43 +1,134 @@
1
- import React, { useState, useEffect } from "react";
1
+ import React, {
2
+ useRef,
3
+ useMemo,
4
+ memo
5
+ } from "react";
2
6
  import { Box, Text } from "ink";
3
7
  import { getTheme } from "../utils/theme.js";
4
8
  import { SYMBOLS, getTodoStatusSymbol } from "../constants/symbols.js";
5
- import { formatNumber } from "../utils/format.js";
6
- function TodoPanel({
9
+ import { formatNumber, formatTokenUsage } from "../utils/format.js";
10
+ import { sample } from "lodash-es";
11
+ import { getStreamingState } from "./Spinner.js";
12
+ import { getSessionState } from "../utils/sessionState.js";
13
+ import { useUnifiedAnimation } from "../utils/animationManager.js";
14
+ import { getIndent } from "../constants/formatRules.js";
15
+ const SpinnerLine = memo(function SpinnerLine2({
16
+ currentTaskActiveForm,
17
+ todos,
18
+ shouldShowTodos,
19
+ fallbackMessage
20
+ }) {
21
+ const theme = getTheme();
22
+ const startTimeRef = useRef(Date.now());
23
+ const { spinnerFrame, elapsedTime } = useUnifiedAnimation({
24
+ enabled: true,
25
+ startTime: startTimeRef.current,
26
+ spinnerFrameCount: SYMBOLS.THINKING_FRAMES.length,
27
+ componentId: "todo-panel-spinner"
28
+ });
29
+ const streamState = useMemo(() => getStreamingState(), [spinnerFrame]);
30
+ const getCurrentTaskDisplay = () => {
31
+ if (currentTaskActiveForm) {
32
+ return currentTaskActiveForm;
33
+ }
34
+ const inProgressTodo = todos.find((t) => t.status === "in_progress");
35
+ if (inProgressTodo?.activeForm) {
36
+ return inProgressTodo.activeForm;
37
+ }
38
+ switch (streamState.phase) {
39
+ case "tool_use":
40
+ return streamState.toolName ? `Using ${streamState.toolName}` : "Executing tool";
41
+ case "generating":
42
+ return "Generating response";
43
+ case "waiting":
44
+ return "Waiting for response";
45
+ case "thinking":
46
+ default:
47
+ return fallbackMessage || "Thinking";
48
+ }
49
+ };
50
+ const formatTime = (seconds) => {
51
+ if (seconds < 60) return `${seconds}s`;
52
+ const mins = Math.floor(seconds / 60);
53
+ const secs = seconds % 60;
54
+ return secs > 0 ? `${mins}m ${secs}s` : `${mins}m`;
55
+ };
56
+ const phaseColors = {
57
+ thinking: theme.minto,
58
+ deep_thinking: theme.minto,
59
+ generating: theme.success,
60
+ tool_use: theme.warning,
61
+ waiting: theme.secondaryText,
62
+ retrying: theme.error,
63
+ permission: theme.info,
64
+ compacting: theme.info,
65
+ concurrent: theme.success
66
+ };
67
+ const spinnerColor = phaseColors[streamState.phase];
68
+ const getTokenDisplay = () => {
69
+ if (streamState.inputTokens || streamState.outputTokens) {
70
+ return formatTokenUsage(streamState.inputTokens, streamState.outputTokens);
71
+ }
72
+ if (streamState.receivedChars && streamState.receivedChars > 0) {
73
+ const approxTokens = Math.round(streamState.receivedChars / 3);
74
+ return `\u2193 ~${formatNumber(approxTokens)}`;
75
+ }
76
+ return "";
77
+ };
78
+ const tokenUsage = getTokenDisplay();
79
+ const thinkingDuration = streamState.thinkingDurationMs ? Math.floor(streamState.thinkingDurationMs / 1e3) : null;
80
+ return /* @__PURE__ */ React.createElement(Box, { flexDirection: "row" }, /* @__PURE__ */ React.createElement(Text, { color: spinnerColor }, SYMBOLS.THINKING_FRAMES[spinnerFrame], " "), /* @__PURE__ */ React.createElement(Text, { color: spinnerColor }, getCurrentTaskDisplay()), /* @__PURE__ */ React.createElement(Text, { color: spinnerColor }, "\u2026 "), /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, "(", /* @__PURE__ */ React.createElement(Text, { bold: true }, "esc"), " to interrupt \xB7 ", formatTime(elapsedTime), tokenUsage && /* @__PURE__ */ React.createElement(Text, null, " \xB7 ", tokenUsage, " tokens"), thinkingDuration !== null && thinkingDuration > 0 && /* @__PURE__ */ React.createElement(Text, null, " \xB7 thought for ", thinkingDuration, "s"), shouldShowTodos && /* @__PURE__ */ React.createElement(Text, null, " ", "\xB7 ", /* @__PURE__ */ React.createElement(Text, { bold: true }, "ctrl+t"), " to hide todos"), ")"), getSessionState("currentError") && /* @__PURE__ */ React.createElement(Text, { color: theme.error }, " \xB7 ", getSessionState("currentError")));
81
+ });
82
+ const SPINNER_MESSAGES = [
83
+ "Thinking",
84
+ "Processing",
85
+ "Working",
86
+ "Computing",
87
+ "Analyzing",
88
+ "Generating",
89
+ "Executing",
90
+ "Preparing"
91
+ ];
92
+ const TodoPanel = memo(function TodoPanel2({
7
93
  todos,
8
94
  isVisible,
9
95
  currentTaskActiveForm,
10
- elapsedTime = 0,
11
- tokenCount = 0,
12
- isLoading = true
96
+ elapsedTime: initialElapsedTime = 0,
97
+ isLoading = true,
98
+ showTodoList = true
13
99
  }) {
14
100
  const theme = getTheme();
15
- const [frameIndex, setFrameIndex] = useState(0);
16
- useEffect(() => {
17
- if (!isLoading) {
18
- return;
19
- }
20
- const timer = setInterval(() => {
21
- setFrameIndex((i) => (i + 1) % SYMBOLS.THINKING_FRAMES.length);
22
- }, 150);
23
- return () => clearInterval(timer);
24
- }, [isLoading]);
101
+ const fallbackMessage = useRef(sample(SPINNER_MESSAGES) || "Thinking");
102
+ const hasTodos = todos.length > 0;
25
103
  const hasIncompleteTasks = todos.some((t) => t.status !== "completed");
26
- if (!isVisible || todos.length === 0 || !hasIncompleteTasks) {
104
+ const shouldShowTodos = hasTodos && hasIncompleteTasks && isVisible && showTodoList;
105
+ if (!isLoading) {
106
+ if (shouldShowTodos) {
107
+ return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React.createElement(Box, { flexDirection: "row" }, /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, "\u25CB "), /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, hasIncompleteTasks ? `${todos.filter((t) => t.status !== "completed").length} task(s) remaining` : "All tasks finished")), /* @__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(
108
+ TodoItemClaudeStyle,
109
+ {
110
+ todo,
111
+ theme,
112
+ isFirst: idx === 0
113
+ }
114
+ )))));
115
+ }
27
116
  return null;
28
117
  }
29
- const visibleTodos = todos;
30
- const currentTask = currentTaskActiveForm || todos.find((t) => t.status === "in_progress")?.activeForm || "Executing tasks";
31
- return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React.createElement(Box, { flexDirection: "row" }, /* @__PURE__ */ React.createElement(Box, { width: 2, flexShrink: 0 }, /* @__PURE__ */ React.createElement(Text, null, SYMBOLS.THINKING_FRAMES[frameIndex])), /* @__PURE__ */ React.createElement(Text, null, currentTask), /* @__PURE__ */ React.createElement(Text, null, "\u2026 "), /* @__PURE__ */ React.createElement(Text, { color: theme.dim }, "(esc to interrupt \xB7 ctrl+t to hide todos \xB7 ", elapsedTime, "s \xB7 \u2193", " ", formatNumber(tokenCount), " tokens)")), /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, visibleTodos.map((todo, idx) => /* @__PURE__ */ React.createElement(React.Fragment, { key: `todo-${idx}-${todo.content.slice(0, 20)}` }, /* @__PURE__ */ React.createElement(
32
- TodoItemClaudeStyle,
118
+ return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React.createElement(
119
+ SpinnerLine,
33
120
  {
34
- todo,
35
- theme,
36
- isFirst: idx === 0
121
+ currentTaskActiveForm,
122
+ todos,
123
+ shouldShowTodos,
124
+ fallbackMessage: fallbackMessage.current
37
125
  }
38
- )))));
39
- }
40
- function TodoItemClaudeStyle({
126
+ ), shouldShowTodos && /* @__PURE__ */ React.createElement(TodoList, { todos, theme }));
127
+ });
128
+ const TodoList = memo(function TodoList2({ todos, theme }) {
129
+ 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 }))));
130
+ });
131
+ const TodoItemClaudeStyle = memo(function TodoItemClaudeStyle2({
41
132
  todo,
42
133
  theme,
43
134
  isFirst
@@ -45,9 +136,9 @@ function TodoItemClaudeStyle({
45
136
  const isCompleted = todo.status === "completed";
46
137
  const symbol = getTodoStatusSymbol(todo.status);
47
138
  const color = isCompleted ? theme.dim : void 0;
48
- const indent = isFirst ? " \u23BF " : " ";
139
+ const indent = isFirst ? `${getIndent("L1")}${SYMBOLS.CHILD_OUTPUT} ` : `${getIndent("L1")} `;
49
140
  return /* @__PURE__ */ React.createElement(Box, { flexDirection: "row" }, /* @__PURE__ */ React.createElement(Text, { color: theme.dim }, indent), /* @__PURE__ */ React.createElement(Text, { color }, symbol, " "), /* @__PURE__ */ React.createElement(Text, { color, strikethrough: isCompleted }, todo.content));
50
- }
141
+ });
51
142
  export {
52
143
  TodoPanel
53
144
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/components/TodoPanel.tsx"],
4
- "sourcesContent": ["import React, { useState, useEffect } from 'react'\nimport { Box, Text } from 'ink'\nimport { TodoItem } from './TodoItem'\nimport { getTheme } from '@utils/theme'\nimport { SYMBOLS, getTodoStatusSymbol } from '@constants/symbols'\nimport { formatNumber } from '@utils/format'\nimport type { TodoItem as TodoItemType } from '@utils/todoStorage'\n\ninterface TodoPanelProps {\n /** TODO \u5217\u8868 */\n todos: TodoItemType[]\n /** \u662F\u5426\u663E\u793A\u9762\u677F\uFF08\u7531 Ctrl+T \u63A7\u5236\uFF09 */\n isVisible: boolean\n /** \u5F53\u524D\u4E3B\u4EFB\u52A1\u7684 activeForm\uFF08\u8FDB\u884C\u4E2D\u7684\u4EFB\u52A1\u63CF\u8FF0\uFF09 */\n currentTaskActiveForm?: string\n /** \u8FD0\u884C\u65F6\u95F4\uFF08\u79D2\uFF09 */\n elapsedTime?: number\n /** Token \u8BA1\u6570 */\n tokenCount?: number\n /** \u662F\u5426\u6B63\u5728\u52A0\u8F7D\uFF08\u63A7\u5236\u52A8\u753B\uFF09 */\n isLoading?: boolean\n}\n\n/**\n * TODO \u9762\u677F\u7EC4\u4EF6 - Claude Code CLI \u98CE\u683C\n *\n * \u89C6\u89C9\u683C\u5F0F\uFF1A\n * ```\n * \u273D \u4F18\u5316\u5E76\u884C\u4EFB\u52A1\u8FDB\u5EA6\u5C55\u793A\u2026 (esc to interrupt \u00B7 ctrl+t to hide todos \u00B7 252s \u00B7 \u2193 5.8k tokens)\n * \u23BF \u2612 \u5DF2\u5B8C\u6210\u4EFB\u52A1 (\u7070\u8272 + \u5220\u9664\u7EBF)\n * \u2610 \u5F85\u5B8C\u6210\u4EFB\u52A1\n * ```\n */\nexport function TodoPanel({\n todos,\n isVisible,\n currentTaskActiveForm,\n elapsedTime = 0,\n tokenCount = 0,\n isLoading = true,\n}: TodoPanelProps) {\n const theme = getTheme()\n\n // Claude Code \u98CE\u683C\uFF1A\u52A8\u6001\u52A8\u753B\u7B26\u53F7 (6\u5E27\u5FAA\u73AF)\n const [frameIndex, setFrameIndex] = useState(0)\n useEffect(() => {\n // \u53EA\u5728 isLoading \u4E3A true \u65F6\u8FD0\u884C\u52A8\u753B\n if (!isLoading) {\n return\n }\n\n const timer = setInterval(() => {\n setFrameIndex(i => (i + 1) % SYMBOLS.THINKING_FRAMES.length)\n }, 150)\n return () => clearInterval(timer)\n }, [isLoading])\n\n // Claude Code \u98CE\u683C\uFF1A\u6240\u6709\u4EFB\u52A1\u5B8C\u6210\u540E\u9690\u85CF\u9762\u677F\n const hasIncompleteTasks = todos.some(t => t.status !== 'completed')\n\n // \u5982\u679C\u4E0D\u53EF\u89C1\u3001\u6CA1\u6709 TODO\u3001\u6216\u6240\u6709\u4EFB\u52A1\u90FD\u5DF2\u5B8C\u6210\uFF0C\u4E0D\u6E32\u67D3\n if (!isVisible || todos.length === 0 || !hasIncompleteTasks) {\n return null\n }\n\n // Claude Code \u98CE\u683C\uFF1A\u663E\u793A\u6240\u6709 TODO\uFF08\u5305\u62EC\u5DF2\u5B8C\u6210\u7684\uFF09\n const visibleTodos = todos\n\n // \u83B7\u53D6\u5F53\u524D\u8FDB\u884C\u4E2D\u7684\u4EFB\u52A1\u63CF\u8FF0\n const currentTask =\n currentTaskActiveForm ||\n todos.find(t => t.status === 'in_progress')?.activeForm ||\n 'Executing tasks'\n\n return (\n <Box flexDirection=\"column\" marginY={1}>\n {/* \u7B2C\u4E00\u884C\uFF1A\u52A8\u753B + \u5F53\u524D\u4EFB\u52A1 + \u7EDF\u8BA1\u4FE1\u606F */}\n <Box flexDirection=\"row\">\n {/* \u52A8\u753B\u7B26\u53F7 - \u4F7F\u7528\u56FA\u5B9A\u5BBD\u5EA6\u907F\u514D\u6296\u52A8 */}\n <Box width={2} flexShrink={0}>\n <Text>{SYMBOLS.THINKING_FRAMES[frameIndex]}</Text>\n </Box>\n\n {/* \u5F53\u524D\u4EFB\u52A1\u63CF\u8FF0 */}\n <Text>{currentTask}</Text>\n\n {/* \u7701\u7565\u7B26\u53F7 */}\n <Text>\u2026 </Text>\n\n {/* \u7EDF\u8BA1\u4FE1\u606F\u548C\u63D0\u793A */}\n <Text color={theme.dim}>\n (esc to interrupt \u00B7 ctrl+t to hide todos \u00B7 {elapsedTime}s \u00B7 \u2193{' '}\n {formatNumber(tokenCount)} tokens)\n </Text>\n </Box>\n\n {/* TODO \u5217\u8868 */}\n <Box flexDirection=\"column\">\n {visibleTodos.map((todo, idx) => (\n <React.Fragment key={`todo-${idx}-${todo.content.slice(0, 20)}`}>\n <TodoItemClaudeStyle\n todo={todo}\n theme={theme}\n isFirst={idx === 0}\n />\n </React.Fragment>\n ))}\n </Box>\n </Box>\n )\n}\n\n/**\n * Claude Code \u98CE\u683C\u7684 TODO \u9879\n *\n * \u683C\u5F0F\uFF1A\n * ```\n * \u23BF \u2612 \u5DF2\u5B8C\u6210\u4EFB\u52A1 (\u7070\u8272 + \u5220\u9664\u7EBF)\n * \u2610 \u5F85\u5B8C\u6210\u4EFB\u52A1\n * ```\n */\ninterface TodoItemClaudeStyleProps {\n todo: TodoItemType\n theme: ReturnType<typeof getTheme>\n isFirst: boolean\n}\n\nfunction TodoItemClaudeStyle({\n todo,\n theme,\n isFirst,\n}: TodoItemClaudeStyleProps) {\n const isCompleted = todo.status === 'completed'\n\n // \u7B26\u53F7\uFF1A\u2610 \u672A\u5B8C\u6210 / \u2612 \u5DF2\u5B8C\u6210\n const symbol = getTodoStatusSymbol(todo.status)\n\n // \u989C\u8272\uFF1A\u5DF2\u5B8C\u6210\u7528\u7070\u8272\uFF0C\u5176\u4ED6\u6B63\u5E38\n const color = isCompleted ? theme.dim : undefined\n\n // \u7F29\u8FDB\uFF1A\u7B2C\u4E00\u4E2A\u7528 \" \u23BF \"\uFF0C\u5176\u4ED6\u7528 \" \" (5\u4E2A\u7A7A\u683C\u5BF9\u9F50)\n const indent = isFirst ? ' \u23BF ' : ' '\n\n return (\n <Box flexDirection=\"row\">\n {/* \u7F29\u8FDB */}\n <Text color={theme.dim}>{indent}</Text>\n\n {/* \u72B6\u6001\u7B26\u53F7 */}\n <Text color={color}>{symbol} </Text>\n\n {/* \u4EFB\u52A1\u63CF\u8FF0 */}\n <Text color={color} strikethrough={isCompleted}>\n {todo.content}\n </Text>\n </Box>\n )\n}\n"],
5
- "mappings": "AAAA,OAAO,SAAS,UAAU,iBAAiB;AAC3C,SAAS,KAAK,YAAY;AAE1B,SAAS,gBAAgB;AACzB,SAAS,SAAS,2BAA2B;AAC7C,SAAS,oBAAoB;AA4BtB,SAAS,UAAU;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd,aAAa;AAAA,EACb,YAAY;AACd,GAAmB;AACjB,QAAM,QAAQ,SAAS;AAGvB,QAAM,CAAC,YAAY,aAAa,IAAI,SAAS,CAAC;AAC9C,YAAU,MAAM;AAEd,QAAI,CAAC,WAAW;AACd;AAAA,IACF;AAEA,UAAM,QAAQ,YAAY,MAAM;AAC9B,oBAAc,QAAM,IAAI,KAAK,QAAQ,gBAAgB,MAAM;AAAA,IAC7D,GAAG,GAAG;AACN,WAAO,MAAM,cAAc,KAAK;AAAA,EAClC,GAAG,CAAC,SAAS,CAAC;AAGd,QAAM,qBAAqB,MAAM,KAAK,OAAK,EAAE,WAAW,WAAW;AAGnE,MAAI,CAAC,aAAa,MAAM,WAAW,KAAK,CAAC,oBAAoB;AAC3D,WAAO;AAAA,EACT;AAGA,QAAM,eAAe;AAGrB,QAAM,cACJ,yBACA,MAAM,KAAK,OAAK,EAAE,WAAW,aAAa,GAAG,cAC7C;AAEF,SACE,oCAAC,OAAI,eAAc,UAAS,SAAS,KAEnC,oCAAC,OAAI,eAAc,SAEjB,oCAAC,OAAI,OAAO,GAAG,YAAY,KACzB,oCAAC,YAAM,QAAQ,gBAAgB,UAAU,CAAE,CAC7C,GAGA,oCAAC,YAAM,WAAY,GAGnB,oCAAC,YAAK,SAAE,GAGR,oCAAC,QAAK,OAAO,MAAM,OAAK,qDACsB,aAAY,iBAAM,KAC7D,aAAa,UAAU,GAAE,UAC5B,CACF,GAGA,oCAAC,OAAI,eAAc,YAChB,aAAa,IAAI,CAAC,MAAM,QACvB,oCAAC,MAAM,UAAN,EAAe,KAAK,QAAQ,GAAG,IAAI,KAAK,QAAQ,MAAM,GAAG,EAAE,CAAC,MAC3D;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA,SAAS,QAAQ;AAAA;AAAA,EACnB,CACF,CACD,CACH,CACF;AAEJ;AAiBA,SAAS,oBAAoB;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AACF,GAA6B;AAC3B,QAAM,cAAc,KAAK,WAAW;AAGpC,QAAM,SAAS,oBAAoB,KAAK,MAAM;AAG9C,QAAM,QAAQ,cAAc,MAAM,MAAM;AAGxC,QAAM,SAAS,UAAU,eAAU;AAEnC,SACE,oCAAC,OAAI,eAAc,SAEjB,oCAAC,QAAK,OAAO,MAAM,OAAM,MAAO,GAGhC,oCAAC,QAAK,SAAe,QAAO,GAAC,GAG7B,oCAAC,QAAK,OAAc,eAAe,eAChC,KAAK,OACR,CACF;AAEJ;",
6
- "names": []
4
+ "sourcesContent": ["import React, {\n useState,\n useEffect,\n useRef,\n useMemo,\n memo,\n useCallback,\n} from 'react'\nimport { Box, Text } from 'ink'\nimport { TodoItem } from './TodoItem'\nimport { getTheme } from '@utils/theme'\nimport { SYMBOLS, getTodoStatusSymbol } from '@constants/symbols'\nimport { formatNumber, formatTokenUsage } from '@utils/format'\nimport type { TodoItem as TodoItemType } from '@utils/todoStorage'\nimport { sample } from 'lodash-es'\nimport { getStreamingState, type StreamingPhase } from './Spinner'\nimport { getSessionState } from '@utils/sessionState'\nimport { useUnifiedAnimation } from '@utils/animationManager'\nimport { SEMANTIC_COLORS, STATUS_COLORS } from '@constants/colors'\nimport { INDENT_LEVELS, getIndent } from '@constants/formatRules'\n\n/**\n * Isolated Spinner component to prevent animation updates from re-rendering the entire panel\n * This component handles all animation state internally\n */\ninterface SpinnerLineProps {\n currentTaskActiveForm?: string\n todos: TodoItemType[]\n shouldShowTodos: boolean\n fallbackMessage: string\n}\n\nconst SpinnerLine = memo(function SpinnerLine({\n currentTaskActiveForm,\n todos,\n shouldShowTodos,\n fallbackMessage,\n}: SpinnerLineProps) {\n const theme = getTheme()\n const startTimeRef = useRef(Date.now())\n\n // Animation state is isolated in this component\n const { spinnerFrame, elapsedTime } = useUnifiedAnimation({\n enabled: true,\n startTime: startTimeRef.current,\n spinnerFrameCount: SYMBOLS.THINKING_FRAMES.length,\n componentId: 'todo-panel-spinner',\n })\n\n // Get streaming state - only updates when this component re-renders\n const streamState = useMemo(() => getStreamingState(), [spinnerFrame])\n\n // Get current task display\n const getCurrentTaskDisplay = (): string => {\n if (currentTaskActiveForm) {\n return currentTaskActiveForm\n }\n const inProgressTodo = todos.find(t => t.status === 'in_progress')\n if (inProgressTodo?.activeForm) {\n return inProgressTodo.activeForm\n }\n switch (streamState.phase) {\n case 'tool_use':\n return streamState.toolName\n ? `Using ${streamState.toolName}`\n : 'Executing tool'\n case 'generating':\n return 'Generating response'\n case 'waiting':\n return 'Waiting for response'\n case 'thinking':\n default:\n return fallbackMessage || 'Thinking'\n }\n }\n\n // Format time display\n const formatTime = (seconds: number): string => {\n if (seconds < 60) return `${seconds}s`\n const mins = Math.floor(seconds / 60)\n const secs = seconds % 60\n return secs > 0 ? `${mins}m ${secs}s` : `${mins}m`\n }\n\n // Phase colors\n const phaseColors: Record<StreamingPhase, string> = {\n thinking: theme.minto,\n deep_thinking: theme.minto,\n generating: theme.success,\n tool_use: theme.warning,\n waiting: theme.secondaryText,\n retrying: theme.error,\n permission: theme.info,\n compacting: theme.info,\n concurrent: theme.success,\n }\n\n const spinnerColor = phaseColors[streamState.phase]\n\n // Get token usage from streaming state (API values or approximate from chars)\n const getTokenDisplay = () => {\n // Prefer API-provided token counts\n if (streamState.inputTokens || streamState.outputTokens) {\n return formatTokenUsage(streamState.inputTokens, streamState.outputTokens)\n }\n // Fallback: approximate from received characters (~3 chars per token for mixed content)\n if (streamState.receivedChars && streamState.receivedChars > 0) {\n const approxTokens = Math.round(streamState.receivedChars / 3)\n return `\u2193 ~${formatNumber(approxTokens)}`\n }\n return ''\n }\n\n const tokenUsage = getTokenDisplay()\n\n // Get thinking duration if available\n const thinkingDuration = streamState.thinkingDurationMs\n ? Math.floor(streamState.thinkingDurationMs / 1000)\n : null\n\n return (\n <Box flexDirection=\"row\">\n <Text color={spinnerColor}>{SYMBOLS.THINKING_FRAMES[spinnerFrame]} </Text>\n <Text color={spinnerColor}>{getCurrentTaskDisplay()}</Text>\n <Text color={spinnerColor}>\u2026 </Text>\n <Text color={theme.secondaryText}>\n (<Text bold>esc</Text> to interrupt \u00B7 {formatTime(elapsedTime)}\n {tokenUsage && <Text> \u00B7 {tokenUsage} tokens</Text>}\n {thinkingDuration !== null && thinkingDuration > 0 && (\n <Text> \u00B7 thought for {thinkingDuration}s</Text>\n )}\n {shouldShowTodos && (\n <Text>\n {' '}\n \u00B7 <Text bold>ctrl+t</Text> to hide todos\n </Text>\n )}\n )\n </Text>\n {getSessionState('currentError') && (\n <Text color={theme.error}> \u00B7 {getSessionState('currentError')}</Text>\n )}\n </Box>\n )\n})\n\n// Spinner messages for fallback when no todos\nconst SPINNER_MESSAGES = [\n 'Thinking',\n 'Processing',\n 'Working',\n 'Computing',\n 'Analyzing',\n 'Generating',\n 'Executing',\n 'Preparing',\n]\n\ninterface TodoPanelProps {\n /** TODO \u5217\u8868 */\n todos: TodoItemType[]\n /** \u662F\u5426\u663E\u793A\u9762\u677F\uFF08\u7531 Ctrl+T \u63A7\u5236\uFF09 */\n isVisible: boolean\n /** \u5F53\u524D\u4E3B\u4EFB\u52A1\u7684 activeForm\uFF08\u8FDB\u884C\u4E2D\u7684\u4EFB\u52A1\u63CF\u8FF0\uFF09 */\n currentTaskActiveForm?: string\n /** \u8FD0\u884C\u65F6\u95F4\uFF08\u79D2\uFF09 */\n elapsedTime?: number\n /** \u662F\u5426\u6B63\u5728\u52A0\u8F7D\uFF08\u63A7\u5236\u52A8\u753B\uFF09 */\n isLoading?: boolean\n /** \u662F\u5426\u663E\u793A\u4EFB\u52A1\u5217\u8868\u8BE6\u60C5 */\n showTodoList?: boolean\n}\n\n/**\n * \u7EDF\u4E00\u7684 Spinner + TODO \u9762\u677F\u7EC4\u4EF6 - Claude Code CLI \u98CE\u683C\n *\n * \u5F53\u6709 TODO \u65F6\u663E\u793A\uFF1A\n * ```\n * \u273D Fixing async tool description bug\u2026 (esc to interrupt \u00B7 ctrl+t to hide todos \u00B7 2m 52s \u00B7 \u2191 5.1k tokens)\n * \u23BF \u2610 Phase 1.1: Fix async tool description bug\n * \u2610 Phase 1.2: Add memory safety fixes\n * ```\n *\n * \u65E0 TODO \u65F6\u663E\u793A\u666E\u901A Spinner\uFF1A\n * ```\n * \u273D Thinking\u2026 (3s \u00B7 esc to interrupt)\n * ```\n *\n * Performance optimization: Animation is isolated in SpinnerLine component\n * to prevent the entire panel from re-rendering on each animation frame.\n */\nexport const TodoPanel = memo(function TodoPanel({\n todos,\n isVisible,\n currentTaskActiveForm,\n elapsedTime: initialElapsedTime = 0,\n isLoading = true,\n showTodoList = true,\n}: TodoPanelProps) {\n const theme = getTheme()\n const fallbackMessage = useRef(sample(SPINNER_MESSAGES) || 'Thinking')\n\n // \u5224\u65AD\u662F\u5426\u6709\u5F85\u529E\u4E8B\u9879\n const hasTodos = todos.length > 0\n const hasIncompleteTasks = todos.some(t => t.status !== 'completed')\n const shouldShowTodos =\n hasTodos && hasIncompleteTasks && isVisible && showTodoList\n\n // \u5982\u679C\u4E0D\u5728\u52A0\u8F7D\u72B6\u6001\uFF0C\u53EA\u663E\u793A todo \u5217\u8868\uFF08\u5982\u679C\u6709\u672A\u5B8C\u6210\u4EFB\u52A1\uFF09\n if (!isLoading) {\n // \u5373\u4F7F\u4E0D\u5728\u52A0\u8F7D\u4E2D\uFF0C\u5982\u679C\u6709\u672A\u5B8C\u6210\u7684\u4EFB\u52A1\u4E5F\u663E\u793A\u5217\u8868\n if (shouldShowTodos) {\n return (\n <Box flexDirection=\"column\" marginTop={1}>\n {/* \u9759\u6001\u6807\u9898 - \u663E\u793A\u8FD8\u6709\u672A\u5B8C\u6210\u4EFB\u52A1 */}\n <Box flexDirection=\"row\">\n <Text color={theme.secondaryText}>\u25CB </Text>\n <Text color={theme.secondaryText}>\n {hasIncompleteTasks\n ? `${todos.filter(t => t.status !== 'completed').length} task(s) remaining`\n : 'All tasks finished'}\n </Text>\n </Box>\n {/* TODO \u5217\u8868 */}\n <Box flexDirection=\"column\">\n {todos.map((todo, idx) => (\n <React.Fragment key={`todo-${idx}-${todo.content.slice(0, 20)}`}>\n <TodoItemClaudeStyle\n todo={todo}\n theme={theme}\n isFirst={idx === 0}\n />\n </React.Fragment>\n ))}\n </Box>\n </Box>\n )\n }\n return null\n }\n\n return (\n <Box flexDirection=\"column\" marginTop={1}>\n {/* \u7B2C\u4E00\u884C\uFF1A\u52A8\u753B + \u5F53\u524D\u4EFB\u52A1 + \u7EDF\u8BA1\u4FE1\u606F - \u9694\u79BB\u5728 SpinnerLine \u7EC4\u4EF6\u4E2D */}\n <SpinnerLine\n currentTaskActiveForm={currentTaskActiveForm}\n todos={todos}\n shouldShowTodos={shouldShowTodos}\n fallbackMessage={fallbackMessage.current}\n />\n\n {/* TODO \u5217\u8868 - \u4EC5\u5F53\u53EF\u89C1\u4E14\u6709\u672A\u5B8C\u6210\u4EFB\u52A1\u65F6\u663E\u793A */}\n {shouldShowTodos && <TodoList todos={todos} theme={theme} />}\n </Box>\n )\n})\n\n/**\n * Memoized TODO list to prevent re-rendering when only the spinner updates\n */\ninterface TodoListProps {\n todos: TodoItemType[]\n theme: ReturnType<typeof getTheme>\n}\n\nconst TodoList = memo(function TodoList({ todos, theme }: TodoListProps) {\n return (\n <Box flexDirection=\"column\">\n {todos.map((todo, idx) => (\n <React.Fragment key={`todo-${idx}-${todo.content.slice(0, 20)}`}>\n <TodoItemClaudeStyle todo={todo} theme={theme} isFirst={idx === 0} />\n </React.Fragment>\n ))}\n </Box>\n )\n})\n\n/**\n * Claude Code \u98CE\u683C\u7684 TODO \u9879\n *\n * \u683C\u5F0F\uFF1A\n * ```\n * \u23BF \u2612 \u5DF2\u5B8C\u6210\u4EFB\u52A1 (\u7070\u8272 + \u5220\u9664\u7EBF)\n * \u2610 \u5F85\u5B8C\u6210\u4EFB\u52A1\n * ```\n */\ninterface TodoItemClaudeStyleProps {\n todo: TodoItemType\n theme: ReturnType<typeof getTheme>\n isFirst: boolean\n}\n\n/**\n * Memoized TODO item component\n */\nconst TodoItemClaudeStyle = memo(function TodoItemClaudeStyle({\n todo,\n theme,\n isFirst,\n}: TodoItemClaudeStyleProps) {\n const isCompleted = todo.status === 'completed'\n\n // \u7B26\u53F7\uFF1A\u2610 \u672A\u5B8C\u6210 / \u2612 \u5DF2\u5B8C\u6210\n const symbol = getTodoStatusSymbol(todo.status)\n\n // \u989C\u8272\uFF1A\u5DF2\u5B8C\u6210\u7528\u7070\u8272\uFF0C\u5176\u4ED6\u6B63\u5E38\n const color = isCompleted ? theme.dim : undefined\n\n // \u4F7F\u7528 REPL \u89C4\u8303\u5B9A\u4E49\u7684\u7ED3\u6784\u7B26\u53F7\uFF1A\u7B2C\u4E00\u4E2A\u7528 \" \u23BF \"\uFF0C\u5176\u4ED6\u7528\u7F29\u8FDB\u5BF9\u9F50\n const indent = isFirst\n ? `${getIndent('L1')}${SYMBOLS.CHILD_OUTPUT} `\n : `${getIndent('L1')} `\n\n return (\n <Box flexDirection=\"row\">\n {/* \u7F29\u8FDB */}\n <Text color={theme.dim}>{indent}</Text>\n\n {/* \u72B6\u6001\u7B26\u53F7 */}\n <Text color={color}>{symbol} </Text>\n\n {/* \u4EFB\u52A1\u63CF\u8FF0 */}\n <Text color={color} strikethrough={isCompleted}>\n {todo.content}\n </Text>\n </Box>\n )\n})\n"],
5
+ "mappings": "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",
6
+ "names": ["SpinnerLine", "TodoPanel", "TodoList", "TodoItemClaudeStyle"]
7
7
  }