@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
@@ -0,0 +1,123 @@
1
+ import {
2
+ getTodos,
3
+ getTodoStatistics,
4
+ getTodosByStatus,
5
+ clearTodos
6
+ } from "../utils/todoStorage.js";
7
+ function formatTodoItem(todo, index) {
8
+ const statusIcon = todo.status === "completed" ? "\u2713" : todo.status === "in_progress" ? "\u25B6" : "\u25CB";
9
+ const priorityIcon = todo.priority === "high" ? "!!!" : todo.priority === "medium" ? "!!" : "!";
10
+ return ` ${statusIcon} [${index + 1}] ${todo.content} (${priorityIcon})`;
11
+ }
12
+ function formatTodos(todos2, title) {
13
+ if (todos2.length === 0) {
14
+ return `${title}: (none)`;
15
+ }
16
+ const lines = [title];
17
+ todos2.forEach((todo, i) => {
18
+ lines.push(formatTodoItem(todo, i));
19
+ });
20
+ return lines.join("\n");
21
+ }
22
+ function parseArgs(args) {
23
+ const trimmed = args.trim().toLowerCase();
24
+ if (trimmed === "clear" || trimmed === "clean") {
25
+ return { action: "clear" };
26
+ }
27
+ if (trimmed === "stats" || trimmed === "statistics") {
28
+ return { action: "stats" };
29
+ }
30
+ if (trimmed === "pending" || trimmed === "todo") {
31
+ return { filter: "pending" };
32
+ }
33
+ if (trimmed === "in_progress" || trimmed === "active" || trimmed === "doing") {
34
+ return { filter: "in_progress" };
35
+ }
36
+ if (trimmed === "completed" || trimmed === "done") {
37
+ return { filter: "completed" };
38
+ }
39
+ return { filter: "all" };
40
+ }
41
+ async function executeTodosCommand(args) {
42
+ const { filter, action } = parseArgs(args);
43
+ if (action === "clear") {
44
+ const completed = getTodosByStatus("completed");
45
+ if (completed.length === 0) {
46
+ return "No completed todos to clear";
47
+ }
48
+ const remaining = getTodos().filter((t) => t.status !== "completed");
49
+ clearTodos();
50
+ const { setTodos } = await import("../utils/todoStorage.js");
51
+ setTodos(remaining);
52
+ return `Cleared ${completed.length} completed todo(s)`;
53
+ }
54
+ if (action === "stats") {
55
+ const stats = getTodoStatistics();
56
+ const completionRate = stats.total > 0 ? stats.byStatus.completed / stats.total : 0;
57
+ const lines2 = [
58
+ "=== Todo Statistics ===",
59
+ "",
60
+ `Total: ${stats.total}`,
61
+ ` Pending: ${stats.byStatus.pending}`,
62
+ ` In Progress: ${stats.byStatus.in_progress}`,
63
+ ` Completed: ${stats.byStatus.completed}`,
64
+ "",
65
+ `By Priority:`,
66
+ ` High: ${stats.byPriority.high}`,
67
+ ` Medium: ${stats.byPriority.medium}`,
68
+ ` Low: ${stats.byPriority.low}`
69
+ ];
70
+ if (stats.total > 0) {
71
+ lines2.push("");
72
+ lines2.push(`Completion Rate: ${(completionRate * 100).toFixed(1)}%`);
73
+ }
74
+ return lines2.join("\n");
75
+ }
76
+ const lines = [];
77
+ lines.push("=== Todo List ===\n");
78
+ if (filter === "all" || !filter) {
79
+ const inProgress = getTodosByStatus("in_progress");
80
+ const pending = getTodosByStatus("pending");
81
+ const completed = getTodosByStatus("completed");
82
+ if (inProgress.length > 0) {
83
+ lines.push(formatTodos(inProgress, "## In Progress"));
84
+ lines.push("");
85
+ }
86
+ if (pending.length > 0) {
87
+ lines.push(formatTodos(pending, "## Pending"));
88
+ lines.push("");
89
+ }
90
+ if (completed.length > 0) {
91
+ lines.push(formatTodos(completed, "## Completed"));
92
+ lines.push("");
93
+ }
94
+ if (inProgress.length === 0 && pending.length === 0 && completed.length === 0) {
95
+ lines.push("No todos");
96
+ }
97
+ } else {
98
+ const todos2 = getTodosByStatus(filter);
99
+ const title = filter === "pending" ? "## Pending" : filter === "in_progress" ? "## In Progress" : "## Completed";
100
+ lines.push(formatTodos(todos2, title));
101
+ }
102
+ lines.push("");
103
+ lines.push("Usage: /todos [pending|active|done|stats|clear]");
104
+ return lines.join("\n");
105
+ }
106
+ const todos = {
107
+ type: "local",
108
+ name: "todos",
109
+ description: "List and manage todos",
110
+ isEnabled: true,
111
+ isHidden: false,
112
+ async call(args) {
113
+ return executeTodosCommand(args);
114
+ },
115
+ userFacingName() {
116
+ return "todos";
117
+ }
118
+ };
119
+ var todos_default = todos;
120
+ export {
121
+ todos_default as default
122
+ };
123
+ //# sourceMappingURL=todos.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/commands/todos.ts"],
4
+ "sourcesContent": ["import type { Command } from '@commands'\nimport {\n getTodos,\n getTodoStatistics,\n getTodosByStatus,\n clearTodos,\n type TodoItem,\n} from '@utils/todoStorage'\n\n/**\n * Todo list command\n * Lists, filters, and manages todos\n */\n\nfunction formatTodoItem(todo: TodoItem, index: number): string {\n const statusIcon =\n todo.status === 'completed'\n ? '\u2713'\n : todo.status === 'in_progress'\n ? '\u25B6'\n : '\u25CB'\n\n const priorityIcon =\n todo.priority === 'high' ? '!!!' : todo.priority === 'medium' ? '!!' : '!'\n\n return ` ${statusIcon} [${index + 1}] ${todo.content} (${priorityIcon})`\n}\n\nfunction formatTodos(todos: TodoItem[], title: string): string {\n if (todos.length === 0) {\n return `${title}: (none)`\n }\n\n const lines = [title]\n todos.forEach((todo, i) => {\n lines.push(formatTodoItem(todo, i))\n })\n return lines.join('\\n')\n}\n\nfunction parseArgs(args: string): {\n filter?: 'pending' | 'in_progress' | 'completed' | 'all'\n action?: 'clear' | 'stats'\n} {\n const trimmed = args.trim().toLowerCase()\n\n if (trimmed === 'clear' || trimmed === 'clean') {\n return { action: 'clear' }\n }\n\n if (trimmed === 'stats' || trimmed === 'statistics') {\n return { action: 'stats' }\n }\n\n if (trimmed === 'pending' || trimmed === 'todo') {\n return { filter: 'pending' }\n }\n\n if (\n trimmed === 'in_progress' ||\n trimmed === 'active' ||\n trimmed === 'doing'\n ) {\n return { filter: 'in_progress' }\n }\n\n if (trimmed === 'completed' || trimmed === 'done') {\n return { filter: 'completed' }\n }\n\n return { filter: 'all' }\n}\n\nasync function executeTodosCommand(args: string): Promise<string> {\n const { filter, action } = parseArgs(args)\n\n // Handle actions\n if (action === 'clear') {\n const completed = getTodosByStatus('completed')\n if (completed.length === 0) {\n return 'No completed todos to clear'\n }\n\n // Remove completed todos by setting new todo list without them\n const remaining = getTodos().filter(t => t.status !== 'completed')\n clearTodos()\n\n // Re-add non-completed todos\n const { setTodos } = await import('@utils/todoStorage')\n setTodos(remaining)\n\n return `Cleared ${completed.length} completed todo(s)`\n }\n\n if (action === 'stats') {\n const stats = getTodoStatistics()\n const completionRate =\n stats.total > 0 ? stats.byStatus.completed / stats.total : 0\n\n const lines = [\n '=== Todo Statistics ===',\n '',\n `Total: ${stats.total}`,\n ` Pending: ${stats.byStatus.pending}`,\n ` In Progress: ${stats.byStatus.in_progress}`,\n ` Completed: ${stats.byStatus.completed}`,\n '',\n `By Priority:`,\n ` High: ${stats.byPriority.high}`,\n ` Medium: ${stats.byPriority.medium}`,\n ` Low: ${stats.byPriority.low}`,\n ]\n\n if (stats.total > 0) {\n lines.push('')\n lines.push(`Completion Rate: ${(completionRate * 100).toFixed(1)}%`)\n }\n\n return lines.join('\\n')\n }\n\n // Handle filtering\n const lines: string[] = []\n lines.push('=== Todo List ===\\n')\n\n if (filter === 'all' || !filter) {\n const inProgress = getTodosByStatus('in_progress')\n const pending = getTodosByStatus('pending')\n const completed = getTodosByStatus('completed')\n\n if (inProgress.length > 0) {\n lines.push(formatTodos(inProgress, '## In Progress'))\n lines.push('')\n }\n\n if (pending.length > 0) {\n lines.push(formatTodos(pending, '## Pending'))\n lines.push('')\n }\n\n if (completed.length > 0) {\n lines.push(formatTodos(completed, '## Completed'))\n lines.push('')\n }\n\n if (\n inProgress.length === 0 &&\n pending.length === 0 &&\n completed.length === 0\n ) {\n lines.push('No todos')\n }\n } else {\n const todos = getTodosByStatus(filter)\n const title =\n filter === 'pending'\n ? '## Pending'\n : filter === 'in_progress'\n ? '## In Progress'\n : '## Completed'\n\n lines.push(formatTodos(todos, title))\n }\n\n lines.push('')\n lines.push('Usage: /todos [pending|active|done|stats|clear]')\n\n return lines.join('\\n')\n}\n\nconst todos = {\n type: 'local',\n name: 'todos',\n description: 'List and manage todos',\n isEnabled: true,\n isHidden: false,\n async call(args: string) {\n return executeTodosCommand(args)\n },\n userFacingName() {\n return 'todos'\n },\n} satisfies Command\n\nexport default todos\n"],
5
+ "mappings": "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",
6
+ "names": ["todos", "lines"]
7
+ }
package/dist/commands.js CHANGED
@@ -1,19 +1,28 @@
1
1
  import clear from "./commands/clear.js";
2
2
  import compact from "./commands/compact.js";
3
3
  import config from "./commands/config.js";
4
+ import context from "./commands/context.js";
4
5
  import cost from "./commands/cost.js";
5
6
  import ctx_viz from "./commands/ctx_viz.js";
7
+ import exportCmd from "./commands/export.js";
6
8
  import help from "./commands/help.js";
7
9
  import init from "./commands/init.js";
8
10
  import mcp from "./commands/mcp-interactive.js";
9
11
  import model from "./commands/model.js";
12
+ import permissions from "./commands/permissions.js";
10
13
  import refreshCommands from "./commands/refreshCommands.js";
14
+ import sandbox from "./commands/sandbox.js";
11
15
  import setup from "./commands/setup.js";
16
+ import status from "./commands/status.js";
12
17
  import terminalSetup from "./commands/terminalSetup.js";
13
18
  import resume from "./commands/resume.js";
14
- import agents from "./commands/agents.js";
19
+ import agents from "./commands/agents/index.js";
15
20
  import plugin from "./commands/plugin.js";
16
21
  import { quit } from "./commands/quit.js";
22
+ import doctor from "./commands/doctor.js";
23
+ import bug from "./commands/bug.js";
24
+ import tasks from "./commands/tasks.js";
25
+ import todos from "./commands/todos.js";
17
26
  import { getMCPCommands } from "./services/mcpClient.js";
18
27
  import {
19
28
  loadCustomCommands,
@@ -23,18 +32,27 @@ import { memoize } from "lodash-es";
23
32
  const HIDDEN_COMMANDS = [ctx_viz, refreshCommands, terminalSetup];
24
33
  const COMMANDS = memoize(() => [
25
34
  agents,
26
- plugin,
35
+ bug,
27
36
  clear,
28
37
  compact,
29
38
  config,
39
+ context,
30
40
  cost,
41
+ doctor,
42
+ exportCmd,
31
43
  help,
32
44
  init,
33
45
  mcp,
34
46
  model,
47
+ permissions,
48
+ plugin,
35
49
  quit,
36
50
  resume,
51
+ sandbox,
37
52
  setup,
53
+ status,
54
+ tasks,
55
+ todos,
38
56
  ...HIDDEN_COMMANDS
39
57
  ]);
40
58
  const getCommands = memoize(async () => {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/commands.ts"],
4
- "sourcesContent": ["import React from 'react'\nimport clear from './commands/clear'\nimport compact from './commands/compact'\nimport config from './commands/config'\nimport cost from './commands/cost'\nimport ctx_viz from './commands/ctx_viz'\nimport help from './commands/help'\nimport init from './commands/init'\nimport mcp from './commands/mcp-interactive'\nimport model from './commands/model'\nimport refreshCommands from './commands/refreshCommands'\nimport setup from './commands/setup'\nimport terminalSetup from './commands/terminalSetup'\nimport { Tool, ToolUseContext } from './Tool'\nimport resume from './commands/resume'\nimport agents from './commands/agents'\nimport plugin from './commands/plugin'\nimport { quit } from './commands/quit'\nimport { getMCPCommands } from './services/mcpClient'\nimport {\n loadCustomCommands,\n loadPluginCommands,\n} from './services/customCommands'\nimport type { MessageParam } from '@anthropic-ai/sdk/resources/index.mjs'\nimport { memoize } from 'lodash-es'\nimport type { Message } from './query'\n\ntype PromptCommand = {\n type: 'prompt'\n progressMessage: string\n argNames?: string[]\n getPromptForCommand(args: string): Promise<MessageParam[]>\n}\n\ntype LocalCommand = {\n type: 'local'\n call(\n args: string,\n context: {\n options: {\n commands: Command[]\n tools: Tool[]\n slowAndCapableModel: string\n }\n abortController: AbortController\n setForkConvoWithMessagesOnTheNextRender: (\n forkConvoWithMessages: Message[],\n ) => void\n },\n ): Promise<string>\n}\n\ntype LocalJSXCommand = {\n type: 'local-jsx'\n call(\n onDone: (result?: string) => void,\n context: ToolUseContext & {\n setForkConvoWithMessagesOnTheNextRender: (\n forkConvoWithMessages: Message[],\n ) => void\n },\n ): Promise<React.ReactNode>\n}\n\nexport type Command = {\n description: string\n isEnabled: boolean\n isHidden: boolean\n name: string\n aliases?: string[]\n userFacingName(): string\n} & (PromptCommand | LocalCommand | LocalJSXCommand)\n\n// Hidden developer commands (not shown in /help but still accessible)\nconst HIDDEN_COMMANDS = [ctx_viz, refreshCommands, terminalSetup]\n\n// Declared as a function so that we don't run this until getCommands is called,\n// since underlying functions read from config, which can't be read at module initialization time\nconst COMMANDS = memoize((): Command[] => [\n agents,\n plugin,\n clear,\n compact,\n config,\n cost,\n help,\n init,\n mcp,\n model,\n quit,\n resume,\n setup,\n ...HIDDEN_COMMANDS,\n])\n\nexport const getCommands = memoize(async (): Promise<Command[]> => {\n const [mcpCommands, customCommands, pluginCommands] = await Promise.all([\n getMCPCommands(),\n loadCustomCommands(),\n loadPluginCommands(),\n ])\n\n // Get built-in commands\n const builtInCommands = COMMANDS()\n\n // Sort built-in commands alphabetically by name\n const sortedBuiltIn = [...builtInCommands].sort((a, b) =>\n a.userFacingName().localeCompare(b.userFacingName()),\n )\n\n // Sort MCP commands alphabetically by name\n const sortedMCP = [...mcpCommands].sort((a, b) =>\n a.userFacingName().localeCompare(b.userFacingName()),\n )\n\n // Sort plugin commands alphabetically by name\n const sortedPlugin = [...pluginCommands].sort((a, b) =>\n a.userFacingName().localeCompare(b.userFacingName()),\n )\n\n // Sort custom commands alphabetically by name\n const sortedCustom = [...customCommands].sort((a, b) =>\n a.userFacingName().localeCompare(b.userFacingName()),\n )\n\n // Command priority (later overrides earlier):\n // 1. MCP commands (lowest priority) - sorted alphabetically\n // 2. Plugin commands - sorted alphabetically\n // 3. Custom commands (user/project) - sorted alphabetically\n // 4. Built-in commands (highest priority) - sorted alphabetically\n // Display order: Built-in first, then custom/plugin/MCP\n return [\n ...sortedBuiltIn,\n ...sortedCustom,\n ...sortedPlugin,\n ...sortedMCP,\n ].filter(_ => _.isEnabled)\n})\n\nexport function hasCommand(commandName: string, commands: Command[]): boolean {\n return commands.some(\n _ => _.userFacingName() === commandName || _.aliases?.includes(commandName),\n )\n}\n\nexport function getCommand(commandName: string, commands: Command[]): Command {\n const command = commands.find(\n _ => _.userFacingName() === commandName || _.aliases?.includes(commandName),\n ) as Command | undefined\n if (!command) {\n throw ReferenceError(\n `Command ${commandName} not found. Available commands: ${commands\n .map(_ => {\n const name = _.userFacingName()\n return _.aliases ? `${name} (aliases: ${_.aliases.join(', ')})` : name\n })\n .join(', ')}`,\n )\n }\n\n return command\n}\n"],
5
- "mappings": "AACA,OAAO,WAAW;AAClB,OAAO,aAAa;AACpB,OAAO,YAAY;AACnB,OAAO,UAAU;AACjB,OAAO,aAAa;AACpB,OAAO,UAAU;AACjB,OAAO,UAAU;AACjB,OAAO,SAAS;AAChB,OAAO,WAAW;AAClB,OAAO,qBAAqB;AAC5B,OAAO,WAAW;AAClB,OAAO,mBAAmB;AAE1B,OAAO,YAAY;AACnB,OAAO,YAAY;AACnB,OAAO,YAAY;AACnB,SAAS,YAAY;AACrB,SAAS,sBAAsB;AAC/B;AAAA,EACE;AAAA,EACA;AAAA,OACK;AAEP,SAAS,eAAe;AAkDxB,MAAM,kBAAkB,CAAC,SAAS,iBAAiB,aAAa;AAIhE,MAAM,WAAW,QAAQ,MAAiB;AAAA,EACxC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,CAAC;AAEM,MAAM,cAAc,QAAQ,YAAgC;AACjE,QAAM,CAAC,aAAa,gBAAgB,cAAc,IAAI,MAAM,QAAQ,IAAI;AAAA,IACtE,eAAe;AAAA,IACf,mBAAmB;AAAA,IACnB,mBAAmB;AAAA,EACrB,CAAC;AAGD,QAAM,kBAAkB,SAAS;AAGjC,QAAM,gBAAgB,CAAC,GAAG,eAAe,EAAE;AAAA,IAAK,CAAC,GAAG,MAClD,EAAE,eAAe,EAAE,cAAc,EAAE,eAAe,CAAC;AAAA,EACrD;AAGA,QAAM,YAAY,CAAC,GAAG,WAAW,EAAE;AAAA,IAAK,CAAC,GAAG,MAC1C,EAAE,eAAe,EAAE,cAAc,EAAE,eAAe,CAAC;AAAA,EACrD;AAGA,QAAM,eAAe,CAAC,GAAG,cAAc,EAAE;AAAA,IAAK,CAAC,GAAG,MAChD,EAAE,eAAe,EAAE,cAAc,EAAE,eAAe,CAAC;AAAA,EACrD;AAGA,QAAM,eAAe,CAAC,GAAG,cAAc,EAAE;AAAA,IAAK,CAAC,GAAG,MAChD,EAAE,eAAe,EAAE,cAAc,EAAE,eAAe,CAAC;AAAA,EACrD;AAQA,SAAO;AAAA,IACL,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,EACL,EAAE,OAAO,OAAK,EAAE,SAAS;AAC3B,CAAC;AAEM,SAAS,WAAW,aAAqB,UAA8B;AAC5E,SAAO,SAAS;AAAA,IACd,OAAK,EAAE,eAAe,MAAM,eAAe,EAAE,SAAS,SAAS,WAAW;AAAA,EAC5E;AACF;AAEO,SAAS,WAAW,aAAqB,UAA8B;AAC5E,QAAM,UAAU,SAAS;AAAA,IACvB,OAAK,EAAE,eAAe,MAAM,eAAe,EAAE,SAAS,SAAS,WAAW;AAAA,EAC5E;AACA,MAAI,CAAC,SAAS;AACZ,UAAM;AAAA,MACJ,WAAW,WAAW,mCAAmC,SACtD,IAAI,OAAK;AACR,cAAM,OAAO,EAAE,eAAe;AAC9B,eAAO,EAAE,UAAU,GAAG,IAAI,cAAc,EAAE,QAAQ,KAAK,IAAI,CAAC,MAAM;AAAA,MACpE,CAAC,EACA,KAAK,IAAI,CAAC;AAAA,IACf;AAAA,EACF;AAEA,SAAO;AACT;",
4
+ "sourcesContent": ["import React from 'react'\nimport clear from './commands/clear'\nimport compact from './commands/compact'\nimport config from './commands/config'\nimport context from './commands/context'\nimport cost from './commands/cost'\nimport ctx_viz from './commands/ctx_viz'\nimport exportCmd from './commands/export'\nimport help from './commands/help'\nimport init from './commands/init'\nimport mcp from './commands/mcp-interactive'\nimport model from './commands/model'\nimport permissions from './commands/permissions'\nimport refreshCommands from './commands/refreshCommands'\nimport sandbox from './commands/sandbox'\nimport setup from './commands/setup'\nimport status from './commands/status'\nimport terminalSetup from './commands/terminalSetup'\nimport { Tool, ToolUseContext } from './Tool'\nimport resume from './commands/resume'\nimport agents from './commands/agents'\nimport plugin from './commands/plugin'\nimport { quit } from './commands/quit'\n// Phase 4: Diagnostic and task management commands\nimport doctor from './commands/doctor'\nimport bug from './commands/bug'\nimport tasks from './commands/tasks'\nimport todos from './commands/todos'\nimport { getMCPCommands } from './services/mcpClient'\nimport {\n loadCustomCommands,\n loadPluginCommands,\n} from './services/customCommands'\nimport type { MessageParam } from '@anthropic-ai/sdk/resources/index.mjs'\nimport { memoize } from 'lodash-es'\nimport type { Message } from './query'\n\ntype PromptCommand = {\n type: 'prompt'\n progressMessage: string\n argNames?: string[]\n getPromptForCommand(args: string): Promise<MessageParam[]>\n}\n\ntype LocalCommand = {\n type: 'local'\n call(\n args: string,\n context: {\n options: {\n commands: Command[]\n tools: Tool[]\n slowAndCapableModel: string\n }\n abortController: AbortController\n setForkConvoWithMessagesOnTheNextRender: (\n forkConvoWithMessages: Message[],\n ) => void\n },\n ): Promise<string>\n}\n\ntype LocalJSXCommand = {\n type: 'local-jsx'\n call(\n onDone: (result?: string) => void,\n context: ToolUseContext & {\n setForkConvoWithMessagesOnTheNextRender: (\n forkConvoWithMessages: Message[],\n ) => void\n },\n ): Promise<React.ReactNode>\n}\n\nexport type Command = {\n description: string\n isEnabled: boolean\n isHidden: boolean\n name: string\n aliases?: string[]\n userFacingName(): string\n} & (PromptCommand | LocalCommand | LocalJSXCommand)\n\n// Hidden developer commands (not shown in /help but still accessible)\nconst HIDDEN_COMMANDS = [ctx_viz, refreshCommands, terminalSetup]\n\n// Declared as a function so that we don't run this until getCommands is called,\n// since underlying functions read from config, which can't be read at module initialization time\nconst COMMANDS = memoize((): Command[] => [\n agents,\n bug,\n clear,\n compact,\n config,\n context,\n cost,\n doctor,\n exportCmd,\n help,\n init,\n mcp,\n model,\n permissions,\n plugin,\n quit,\n resume,\n sandbox,\n setup,\n status,\n tasks,\n todos,\n ...HIDDEN_COMMANDS,\n])\n\nexport const getCommands = memoize(async (): Promise<Command[]> => {\n const [mcpCommands, customCommands, pluginCommands] = await Promise.all([\n getMCPCommands(),\n loadCustomCommands(),\n loadPluginCommands(),\n ])\n\n // Get built-in commands\n const builtInCommands = COMMANDS()\n\n // Sort built-in commands alphabetically by name\n const sortedBuiltIn = [...builtInCommands].sort((a, b) =>\n a.userFacingName().localeCompare(b.userFacingName()),\n )\n\n // Sort MCP commands alphabetically by name\n const sortedMCP = [...mcpCommands].sort((a, b) =>\n a.userFacingName().localeCompare(b.userFacingName()),\n )\n\n // Sort plugin commands alphabetically by name\n const sortedPlugin = [...pluginCommands].sort((a, b) =>\n a.userFacingName().localeCompare(b.userFacingName()),\n )\n\n // Sort custom commands alphabetically by name\n const sortedCustom = [...customCommands].sort((a, b) =>\n a.userFacingName().localeCompare(b.userFacingName()),\n )\n\n // Command priority (later overrides earlier):\n // 1. MCP commands (lowest priority) - sorted alphabetically\n // 2. Plugin commands - sorted alphabetically\n // 3. Custom commands (user/project) - sorted alphabetically\n // 4. Built-in commands (highest priority) - sorted alphabetically\n // Display order: Built-in first, then custom/plugin/MCP\n return [\n ...sortedBuiltIn,\n ...sortedCustom,\n ...sortedPlugin,\n ...sortedMCP,\n ].filter(_ => _.isEnabled)\n})\n\nexport function hasCommand(commandName: string, commands: Command[]): boolean {\n return commands.some(\n _ => _.userFacingName() === commandName || _.aliases?.includes(commandName),\n )\n}\n\nexport function getCommand(commandName: string, commands: Command[]): Command {\n const command = commands.find(\n _ => _.userFacingName() === commandName || _.aliases?.includes(commandName),\n ) as Command | undefined\n if (!command) {\n throw ReferenceError(\n `Command ${commandName} not found. Available commands: ${commands\n .map(_ => {\n const name = _.userFacingName()\n return _.aliases ? `${name} (aliases: ${_.aliases.join(', ')})` : name\n })\n .join(', ')}`,\n )\n }\n\n return command\n}\n"],
5
+ "mappings": "AACA,OAAO,WAAW;AAClB,OAAO,aAAa;AACpB,OAAO,YAAY;AACnB,OAAO,aAAa;AACpB,OAAO,UAAU;AACjB,OAAO,aAAa;AACpB,OAAO,eAAe;AACtB,OAAO,UAAU;AACjB,OAAO,UAAU;AACjB,OAAO,SAAS;AAChB,OAAO,WAAW;AAClB,OAAO,iBAAiB;AACxB,OAAO,qBAAqB;AAC5B,OAAO,aAAa;AACpB,OAAO,WAAW;AAClB,OAAO,YAAY;AACnB,OAAO,mBAAmB;AAE1B,OAAO,YAAY;AACnB,OAAO,YAAY;AACnB,OAAO,YAAY;AACnB,SAAS,YAAY;AAErB,OAAO,YAAY;AACnB,OAAO,SAAS;AAChB,OAAO,WAAW;AAClB,OAAO,WAAW;AAClB,SAAS,sBAAsB;AAC/B;AAAA,EACE;AAAA,EACA;AAAA,OACK;AAEP,SAAS,eAAe;AAkDxB,MAAM,kBAAkB,CAAC,SAAS,iBAAiB,aAAa;AAIhE,MAAM,WAAW,QAAQ,MAAiB;AAAA,EACxC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,CAAC;AAEM,MAAM,cAAc,QAAQ,YAAgC;AACjE,QAAM,CAAC,aAAa,gBAAgB,cAAc,IAAI,MAAM,QAAQ,IAAI;AAAA,IACtE,eAAe;AAAA,IACf,mBAAmB;AAAA,IACnB,mBAAmB;AAAA,EACrB,CAAC;AAGD,QAAM,kBAAkB,SAAS;AAGjC,QAAM,gBAAgB,CAAC,GAAG,eAAe,EAAE;AAAA,IAAK,CAAC,GAAG,MAClD,EAAE,eAAe,EAAE,cAAc,EAAE,eAAe,CAAC;AAAA,EACrD;AAGA,QAAM,YAAY,CAAC,GAAG,WAAW,EAAE;AAAA,IAAK,CAAC,GAAG,MAC1C,EAAE,eAAe,EAAE,cAAc,EAAE,eAAe,CAAC;AAAA,EACrD;AAGA,QAAM,eAAe,CAAC,GAAG,cAAc,EAAE;AAAA,IAAK,CAAC,GAAG,MAChD,EAAE,eAAe,EAAE,cAAc,EAAE,eAAe,CAAC;AAAA,EACrD;AAGA,QAAM,eAAe,CAAC,GAAG,cAAc,EAAE;AAAA,IAAK,CAAC,GAAG,MAChD,EAAE,eAAe,EAAE,cAAc,EAAE,eAAe,CAAC;AAAA,EACrD;AAQA,SAAO;AAAA,IACL,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,EACL,EAAE,OAAO,OAAK,EAAE,SAAS;AAC3B,CAAC;AAEM,SAAS,WAAW,aAAqB,UAA8B;AAC5E,SAAO,SAAS;AAAA,IACd,OAAK,EAAE,eAAe,MAAM,eAAe,EAAE,SAAS,SAAS,WAAW;AAAA,EAC5E;AACF;AAEO,SAAS,WAAW,aAAqB,UAA8B;AAC5E,QAAM,UAAU,SAAS;AAAA,IACvB,OAAK,EAAE,eAAe,MAAM,eAAe,EAAE,SAAS,SAAS,WAAW;AAAA,EAC5E;AACA,MAAI,CAAC,SAAS;AACZ,UAAM;AAAA,MACJ,WAAW,WAAW,mCAAmC,SACtD,IAAI,OAAK;AACR,cAAM,OAAO,EAAE,eAAe;AAC9B,eAAO,EAAE,UAAU,GAAG,IAAI,cAAc,EAAE,QAAQ,KAAK,IAAI,CAAC,MAAM;AAAA,MACpE,CAAC,EACA,KAAK,IAAI,CAAC;AAAA,IACf;AAAA,EACF;AAEA,SAAO;AACT;",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,8 @@
1
- import React, { useEffect, useState } 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 { SYMBOLS } from "../constants/symbols.js";
5
+ import { useUnifiedAnimation } from "../utils/animationManager.js";
5
6
  function AgentThinkingBlock({
6
7
  message,
7
8
  showSpinner = true,
@@ -9,24 +10,15 @@ function AgentThinkingBlock({
9
10
  startTime = Date.now()
10
11
  }) {
11
12
  const theme = getTheme();
13
+ const startTimeRef = useRef(startTime);
12
14
  const frames = SYMBOLS.THINKING_FRAMES;
13
- const [frame, setFrame] = useState(0);
14
- const [elapsedTime, setElapsedTime] = useState(0);
15
- useEffect(() => {
16
- if (!showSpinner) return;
17
- const timer = setInterval(() => {
18
- setFrame((f) => (f + 1) % frames.length);
19
- }, 150);
20
- return () => clearInterval(timer);
21
- }, [showSpinner, frames.length]);
22
- useEffect(() => {
23
- if (!showElapsedTime) return;
24
- const timer = setInterval(() => {
25
- setElapsedTime(Math.floor((Date.now() - startTime) / 1e3));
26
- }, 1e3);
27
- return () => clearInterval(timer);
28
- }, [showElapsedTime, startTime]);
29
- return /* @__PURE__ */ React.createElement(Box, { flexDirection: "row", marginTop: 1 }, showSpinner && /* @__PURE__ */ React.createElement(Box, { flexWrap: "nowrap", height: 1, width: 2 }, /* @__PURE__ */ React.createElement(Text, { color: theme.dimmedText }, frames[frame])), /* @__PURE__ */ React.createElement(Text, { color: theme.dimmedText }, message, showSpinner && "\u2026"), showElapsedTime && /* @__PURE__ */ React.createElement(Text, { color: theme.mutedText }, " ", "(", elapsedTime, "s \xB7 ", /* @__PURE__ */ React.createElement(Text, { bold: true }, "esc"), " to interrupt)"));
15
+ const { spinnerFrame, elapsedTime } = useUnifiedAnimation({
16
+ enabled: showSpinner || showElapsedTime,
17
+ startTime: startTimeRef.current,
18
+ spinnerFrameCount: frames.length,
19
+ componentId: "agent-thinking-block"
20
+ });
21
+ return /* @__PURE__ */ React.createElement(Box, { flexDirection: "row", marginTop: 1 }, showSpinner && /* @__PURE__ */ React.createElement(Box, { flexWrap: "nowrap", height: 1, width: 2 }, /* @__PURE__ */ React.createElement(Text, { color: theme.dimmedText }, frames[spinnerFrame])), /* @__PURE__ */ React.createElement(Text, { color: theme.dimmedText }, message, showSpinner && "\u2026"), showElapsedTime && /* @__PURE__ */ React.createElement(Text, { color: theme.mutedText }, " ", "(", elapsedTime, "s \xB7 ", /* @__PURE__ */ React.createElement(Text, { bold: true }, "esc"), " to interrupt)"));
30
22
  }
31
23
  function ThinkingIndicator({
32
24
  message
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/components/AgentThinkingBlock.tsx"],
4
- "sourcesContent": ["/**\n * AgentThinkingBlock - Claude Code CLI \u98CE\u683C\u7684\u601D\u8003\u8FC7\u7A0B\u7EC4\u4EF6\n *\n * \u6838\u5FC3\u7279\u6027\uFF1A\n * 1. **\u539F\u5730\u66F4\u65B0** - \u540C\u4E00\u4E2A\u7EC4\u4EF6\u5B9E\u4F8B\uFF0C\u901A\u8FC7 props \u66F4\u65B0\u5185\u5BB9\n * 2. **\u6697\u6DE1\u914D\u8272** - \u4F7F\u7528 dimmedText \u8868\u793A\u8FC7\u6E21\u72B6\u6001\n * 3. **\u52A8\u753B Spinner** - \u6301\u7EED\u65CB\u8F6C\uFF0C\u8868\u793A\u6D3B\u8DC3\u72B6\u6001\n * 4. **\u6D41\u7545\u8FC7\u6E21** - \u6D88\u606F\u53D8\u5316\u65F6\u5E73\u6ED1\u66FF\u6362\uFF0C\u4E0D\u4EA7\u751F\u6EDA\u52A8\n *\n * \u8FD9\u662F\u5B9E\u73B0\"\u6D41\u52A8\u6027\"\u7684\u5173\u952E\u7EC4\u4EF6\n */\n\nimport React, { useEffect, useState } from 'react'\nimport { Box, Text } from 'ink'\nimport { getTheme } from '@utils/theme'\nimport { SYMBOLS } from '@constants/symbols'\n\ninterface Props {\n /** \u5F53\u524D\u601D\u8003\u9636\u6BB5\u7684\u6D88\u606F */\n message: string\n\n /** \u662F\u5426\u663E\u793A Spinner \u52A8\u753B */\n showSpinner?: boolean\n\n /** \u662F\u5426\u663E\u793A\u7ECF\u8FC7\u65F6\u95F4 */\n showElapsedTime?: boolean\n\n /** \u8D77\u59CB\u65F6\u95F4 (\u7528\u4E8E\u8BA1\u7B97\u7ECF\u8FC7\u65F6\u95F4) */\n startTime?: number\n}\n\n/**\n * AgentThinkingBlock - \u539F\u5730\u66F4\u65B0\u7684\u601D\u8003\u8FC7\u7A0B\u7EC4\u4EF6\n *\n * \u7528\u6CD5\u793A\u4F8B\uFF1A\n * ```tsx\n * // \u521D\u59CB\u6E32\u67D3\n * <AgentThinkingBlock message=\"Reading file...\" />\n *\n * // \u66F4\u65B0\u6D88\u606F (\u540C\u4E00\u4E2A\u7EC4\u4EF6\u5B9E\u4F8B\uFF0Cprops \u53D8\u5316)\n * <AgentThinkingBlock message=\"Analyzing code...\" />\n *\n * // \u518D\u6B21\u66F4\u65B0\n * <AgentThinkingBlock message=\"Generating response...\" />\n * ```\n *\n * \u7528\u6237\u770B\u5230\u7684\u6548\u679C\uFF1A\n * ```\n * \u00B7 Reading file... \u2190 \u663E\u793A\n * \u2722 Analyzing code... \u2190 \u66FF\u6362 (\u4E0D\u662F\u65B0\u884C)\n * \u2733 Generating response... \u2190 \u518D\u6B21\u66FF\u6362\n * ```\n */\nexport function AgentThinkingBlock({\n message,\n showSpinner = true,\n showElapsedTime = true,\n startTime = Date.now(),\n}: Props): React.ReactNode {\n const theme = getTheme()\n\n // Claude Code \u98CE\u683C\u7684\u601D\u8003\u52A8\u753B - 6\u5E27\u5FAA\u73AF\n const frames = SYMBOLS.THINKING_FRAMES\n const [frame, setFrame] = useState(0)\n\n // \u7ECF\u8FC7\u65F6\u95F4\n const [elapsedTime, setElapsedTime] = useState(0)\n\n // Claude Code \u98CE\u683C\u52A8\u753B - 150ms \u95F4\u9694\n useEffect(() => {\n if (!showSpinner) return\n\n const timer = setInterval(() => {\n setFrame(f => (f + 1) % frames.length)\n }, 150)\n\n return () => clearInterval(timer)\n }, [showSpinner, frames.length])\n\n // \u7ECF\u8FC7\u65F6\u95F4\u8BA1\u65F6\u5668\n useEffect(() => {\n if (!showElapsedTime) return\n\n const timer = setInterval(() => {\n setElapsedTime(Math.floor((Date.now() - startTime) / 1000))\n }, 1000)\n\n return () => clearInterval(timer)\n }, [showElapsedTime, startTime])\n\n return (\n <Box flexDirection=\"row\" marginTop={1}>\n {/* Spinner \u52A8\u753B */}\n {showSpinner && (\n <Box flexWrap=\"nowrap\" height={1} width={2}>\n {/* \u4F7F\u7528\u6697\u6DE1\u8272 - \u5173\u952E\uFF1A\u8FC7\u6E21\u72B6\u6001\u5E94\u8BE5\u4E0D\u663E\u773C */}\n <Text color={theme.dimmedText}>{frames[frame]}</Text>\n </Box>\n )}\n\n {/* \u601D\u8003\u6D88\u606F - \u4F7F\u7528\u6697\u6DE1\u8272\uFF0C\u7B26\u5408 Claude Code CLI \u89C4\u8303 */}\n <Text color={theme.dimmedText}>\n {message}\n {showSpinner && '\u2026'}\n </Text>\n\n {/* \u7ECF\u8FC7\u65F6\u95F4\u548C\u63D0\u793A */}\n {showElapsedTime && (\n <Text color={theme.mutedText}>\n {' '}\n ({elapsedTime}s \u00B7 <Text bold>esc</Text> to interrupt)\n </Text>\n )}\n </Box>\n )\n}\n\n/**\n * \u8F7B\u91CF\u7EA7\u7684 Thinking Indicator (\u7528\u4E8E\u7D27\u51D1\u5E03\u5C40)\n */\nexport function ThinkingIndicator({\n message,\n}: {\n message: string\n}): React.ReactNode {\n return <AgentThinkingBlock message={message} showElapsedTime={false} />\n}\n"],
5
- "mappings": "AAYA,OAAO,SAAS,WAAW,gBAAgB;AAC3C,SAAS,KAAK,YAAY;AAC1B,SAAS,gBAAgB;AACzB,SAAS,eAAe;AAsCjB,SAAS,mBAAmB;AAAA,EACjC;AAAA,EACA,cAAc;AAAA,EACd,kBAAkB;AAAA,EAClB,YAAY,KAAK,IAAI;AACvB,GAA2B;AACzB,QAAM,QAAQ,SAAS;AAGvB,QAAM,SAAS,QAAQ;AACvB,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAS,CAAC;AAGpC,QAAM,CAAC,aAAa,cAAc,IAAI,SAAS,CAAC;AAGhD,YAAU,MAAM;AACd,QAAI,CAAC,YAAa;AAElB,UAAM,QAAQ,YAAY,MAAM;AAC9B,eAAS,QAAM,IAAI,KAAK,OAAO,MAAM;AAAA,IACvC,GAAG,GAAG;AAEN,WAAO,MAAM,cAAc,KAAK;AAAA,EAClC,GAAG,CAAC,aAAa,OAAO,MAAM,CAAC;AAG/B,YAAU,MAAM;AACd,QAAI,CAAC,gBAAiB;AAEtB,UAAM,QAAQ,YAAY,MAAM;AAC9B,qBAAe,KAAK,OAAO,KAAK,IAAI,IAAI,aAAa,GAAI,CAAC;AAAA,IAC5D,GAAG,GAAI;AAEP,WAAO,MAAM,cAAc,KAAK;AAAA,EAClC,GAAG,CAAC,iBAAiB,SAAS,CAAC;AAE/B,SACE,oCAAC,OAAI,eAAc,OAAM,WAAW,KAEjC,eACC,oCAAC,OAAI,UAAS,UAAS,QAAQ,GAAG,OAAO,KAEvC,oCAAC,QAAK,OAAO,MAAM,cAAa,OAAO,KAAK,CAAE,CAChD,GAIF,oCAAC,QAAK,OAAO,MAAM,cAChB,SACA,eAAe,QAClB,GAGC,mBACC,oCAAC,QAAK,OAAO,MAAM,aAChB,KAAI,KACH,aAAY,WAAI,oCAAC,QAAK,MAAI,QAAC,KAAG,GAAO,gBACzC,CAEJ;AAEJ;AAKO,SAAS,kBAAkB;AAAA,EAChC;AACF,GAEoB;AAClB,SAAO,oCAAC,sBAAmB,SAAkB,iBAAiB,OAAO;AACvE;",
4
+ "sourcesContent": ["/**\n * AgentThinkingBlock - Claude Code CLI \u98CE\u683C\u7684\u601D\u8003\u8FC7\u7A0B\u7EC4\u4EF6\n *\n * \u6838\u5FC3\u7279\u6027\uFF1A\n * 1. **\u539F\u5730\u66F4\u65B0** - \u540C\u4E00\u4E2A\u7EC4\u4EF6\u5B9E\u4F8B\uFF0C\u901A\u8FC7 props \u66F4\u65B0\u5185\u5BB9\n * 2. **\u6697\u6DE1\u914D\u8272** - \u4F7F\u7528 dimmedText \u8868\u793A\u8FC7\u6E21\u72B6\u6001\n * 3. **\u52A8\u753B Spinner** - \u6301\u7EED\u65CB\u8F6C\uFF0C\u8868\u793A\u6D3B\u8DC3\u72B6\u6001\n * 4. **\u6D41\u7545\u8FC7\u6E21** - \u6D88\u606F\u53D8\u5316\u65F6\u5E73\u6ED1\u66FF\u6362\uFF0C\u4E0D\u4EA7\u751F\u6EDA\u52A8\n *\n * \u8FD9\u662F\u5B9E\u73B0\"\u6D41\u52A8\u6027\"\u7684\u5173\u952E\u7EC4\u4EF6\n * \u4F7F\u7528\u7EDF\u4E00\u52A8\u753B\u7BA1\u7406\u5668\u4EE3\u66FF\u591A\u4E2A 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 { SYMBOLS } from '@constants/symbols'\nimport { useUnifiedAnimation } from '@utils/animationManager'\n\ninterface Props {\n /** \u5F53\u524D\u601D\u8003\u9636\u6BB5\u7684\u6D88\u606F */\n message: string\n\n /** \u662F\u5426\u663E\u793A Spinner \u52A8\u753B */\n showSpinner?: boolean\n\n /** \u662F\u5426\u663E\u793A\u7ECF\u8FC7\u65F6\u95F4 */\n showElapsedTime?: boolean\n\n /** \u8D77\u59CB\u65F6\u95F4 (\u7528\u4E8E\u8BA1\u7B97\u7ECF\u8FC7\u65F6\u95F4) */\n startTime?: number\n}\n\n/**\n * AgentThinkingBlock - \u539F\u5730\u66F4\u65B0\u7684\u601D\u8003\u8FC7\u7A0B\u7EC4\u4EF6\n *\n * \u7528\u6CD5\u793A\u4F8B\uFF1A\n * ```tsx\n * // \u521D\u59CB\u6E32\u67D3\n * <AgentThinkingBlock message=\"Reading file...\" />\n *\n * // \u66F4\u65B0\u6D88\u606F (\u540C\u4E00\u4E2A\u7EC4\u4EF6\u5B9E\u4F8B\uFF0Cprops \u53D8\u5316)\n * <AgentThinkingBlock message=\"Analyzing code...\" />\n *\n * // \u518D\u6B21\u66F4\u65B0\n * <AgentThinkingBlock message=\"Generating response...\" />\n * ```\n *\n * \u7528\u6237\u770B\u5230\u7684\u6548\u679C\uFF1A\n * ```\n * \u00B7 Reading file... \u2190 \u663E\u793A\n * \u2722 Analyzing code... \u2190 \u66FF\u6362 (\u4E0D\u662F\u65B0\u884C)\n * \u2733 Generating response... \u2190 \u518D\u6B21\u66FF\u6362\n * ```\n */\nexport function AgentThinkingBlock({\n message,\n showSpinner = true,\n showElapsedTime = true,\n startTime = Date.now(),\n}: Props): React.ReactNode {\n const theme = getTheme()\n const startTimeRef = useRef(startTime)\n\n // Claude Code \u98CE\u683C\u7684\u601D\u8003\u52A8\u753B - 6\u5E27\u5FAA\u73AF\n const frames = SYMBOLS.THINKING_FRAMES\n\n // Use unified animation manager instead of separate setInterval timers\n const { spinnerFrame, elapsedTime } = useUnifiedAnimation({\n enabled: showSpinner || showElapsedTime,\n startTime: startTimeRef.current,\n spinnerFrameCount: frames.length,\n componentId: 'agent-thinking-block',\n })\n\n return (\n <Box flexDirection=\"row\" marginTop={1}>\n {/* Spinner \u52A8\u753B */}\n {showSpinner && (\n <Box flexWrap=\"nowrap\" height={1} width={2}>\n {/* \u4F7F\u7528\u6697\u6DE1\u8272 - \u5173\u952E\uFF1A\u8FC7\u6E21\u72B6\u6001\u5E94\u8BE5\u4E0D\u663E\u773C */}\n <Text color={theme.dimmedText}>{frames[spinnerFrame]}</Text>\n </Box>\n )}\n\n {/* \u601D\u8003\u6D88\u606F - \u4F7F\u7528\u6697\u6DE1\u8272\uFF0C\u7B26\u5408 Claude Code CLI \u89C4\u8303 */}\n <Text color={theme.dimmedText}>\n {message}\n {showSpinner && '\u2026'}\n </Text>\n\n {/* \u7ECF\u8FC7\u65F6\u95F4\u548C\u63D0\u793A */}\n {showElapsedTime && (\n <Text color={theme.mutedText}>\n {' '}\n ({elapsedTime}s \u00B7 <Text bold>esc</Text> to interrupt)\n </Text>\n )}\n </Box>\n )\n}\n\n/**\n * \u8F7B\u91CF\u7EA7\u7684 Thinking Indicator (\u7528\u4E8E\u7D27\u51D1\u5E03\u5C40)\n */\nexport function ThinkingIndicator({\n message,\n}: {\n message: string\n}): React.ReactNode {\n return <AgentThinkingBlock message={message} showElapsedTime={false} />\n}\n"],
5
+ "mappings": "AAaA,OAAO,SAAS,cAAc;AAC9B,SAAS,KAAK,YAAY;AAC1B,SAAS,gBAAgB;AACzB,SAAS,eAAe;AACxB,SAAS,2BAA2B;AAsC7B,SAAS,mBAAmB;AAAA,EACjC;AAAA,EACA,cAAc;AAAA,EACd,kBAAkB;AAAA,EAClB,YAAY,KAAK,IAAI;AACvB,GAA2B;AACzB,QAAM,QAAQ,SAAS;AACvB,QAAM,eAAe,OAAO,SAAS;AAGrC,QAAM,SAAS,QAAQ;AAGvB,QAAM,EAAE,cAAc,YAAY,IAAI,oBAAoB;AAAA,IACxD,SAAS,eAAe;AAAA,IACxB,WAAW,aAAa;AAAA,IACxB,mBAAmB,OAAO;AAAA,IAC1B,aAAa;AAAA,EACf,CAAC;AAED,SACE,oCAAC,OAAI,eAAc,OAAM,WAAW,KAEjC,eACC,oCAAC,OAAI,UAAS,UAAS,QAAQ,GAAG,OAAO,KAEvC,oCAAC,QAAK,OAAO,MAAM,cAAa,OAAO,YAAY,CAAE,CACvD,GAIF,oCAAC,QAAK,OAAO,MAAM,cAChB,SACA,eAAe,QAClB,GAGC,mBACC,oCAAC,QAAK,OAAO,MAAM,aAChB,KAAI,KACH,aAAY,WAAI,oCAAC,QAAK,MAAI,QAAC,KAAG,GAAO,gBACzC,CAEJ;AAEJ;AAKO,SAAS,kBAAkB;AAAA,EAChC;AACF,GAEoB;AAClB,SAAO,oCAAC,sBAAmB,SAAkB,iBAAiB,OAAO;AACvE;",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,12 @@
1
1
  import { Box, Text, useInput } from "ink";
2
2
  import * as React from "react";
3
- import { useState, useEffect } from "react";
3
+ import { useState, useEffect, useCallback } from "react";
4
4
  import { getTheme } from "../utils/theme.js";
5
+ import {
6
+ getAllBackgroundAgents,
7
+ cancelBackgroundAgent,
8
+ backgroundAgentEvents
9
+ } from "../utils/backgroundAgentManager.js";
5
10
  function BackgroundTasksPanel({
6
11
  shells,
7
12
  isVisible,
@@ -10,38 +15,51 @@ function BackgroundTasksPanel({
10
15
  onClose
11
16
  }) {
12
17
  const [selectedIndex, setSelectedIndex] = useState(0);
18
+ const [agents, setAgents] = useState([]);
13
19
  const theme = getTheme();
14
20
  useEffect(() => {
15
- if (selectedIndex >= shells.length && shells.length > 0) {
16
- setSelectedIndex(shells.length - 1);
21
+ setAgents(getAllBackgroundAgents());
22
+ const unsubscribe = backgroundAgentEvents.onStatusChange(() => {
23
+ setAgents(getAllBackgroundAgents());
24
+ });
25
+ return unsubscribe;
26
+ }, []);
27
+ const tasks = [
28
+ ...shells.map((shell) => ({ type: "shell", data: shell })),
29
+ ...agents.map((agent) => ({ type: "agent", data: agent }))
30
+ ];
31
+ useEffect(() => {
32
+ if (selectedIndex >= tasks.length && tasks.length > 0) {
33
+ setSelectedIndex(tasks.length - 1);
34
+ }
35
+ }, [tasks.length, selectedIndex]);
36
+ const handleKillSelected = useCallback(() => {
37
+ const selected = tasks[selectedIndex];
38
+ if (!selected) return;
39
+ if (selected.type === "shell") {
40
+ onKill(selected.data);
41
+ } else if (selected.type === "agent") {
42
+ cancelBackgroundAgent(selected.data.agentId);
43
+ }
44
+ if (selectedIndex >= tasks.length - 1 && tasks.length > 1) {
45
+ setSelectedIndex(tasks.length - 2);
17
46
  }
18
- }, [shells.length, selectedIndex]);
47
+ }, [tasks, selectedIndex, onKill]);
19
48
  useInput(
20
49
  (input, key) => {
21
50
  if (key.upArrow) {
22
51
  setSelectedIndex((prev) => Math.max(0, prev - 1));
23
52
  } else if (key.downArrow) {
24
- setSelectedIndex((prev) => Math.min(shells.length - 1, prev + 1));
53
+ setSelectedIndex((prev) => Math.min(tasks.length - 1, prev + 1));
25
54
  } else if (key.return) {
26
- const selected = shells[selectedIndex];
27
- if (selected) onSelect(selected);
28
- } else if (input === "k" || input === "K") {
29
- const selected = shells[selectedIndex];
30
- if (selected) {
31
- console.log(
32
- "[BackgroundTasksPanel] Killing shell:",
33
- selected.id,
34
- selected.command
35
- );
36
- onKill(selected);
37
- if (selectedIndex >= shells.length - 1 && shells.length > 1) {
38
- setSelectedIndex(shells.length - 2);
39
- }
55
+ const selected = tasks[selectedIndex];
56
+ if (selected?.type === "shell") {
57
+ onSelect(selected.data);
40
58
  }
59
+ } else if (input === "k" || input === "K") {
60
+ handleKillSelected();
41
61
  } else if (key.escape) {
42
62
  onClose();
43
- } else {
44
- console.log("[BackgroundTasksPanel] Unhandled input:", { input, key });
45
63
  }
46
64
  },
47
65
  { isActive: isVisible }
@@ -73,15 +91,36 @@ function BackgroundTasksPanel({
73
91
  case "running":
74
92
  return "\u25B6";
75
93
  case "done":
94
+ case "completed":
76
95
  return "\u2713";
77
96
  case "killed":
97
+ case "cancelled":
78
98
  return "\u2717";
99
+ case "failed":
100
+ return "!";
79
101
  default:
80
102
  return "\u2022";
81
103
  }
82
104
  };
83
- const activeCount = shells.filter((s) => s.status === "running").length;
84
- const countText = activeCount === 1 ? "1 active shell" : `${activeCount} active shells`;
105
+ const getTypeIcon = (task) => {
106
+ return task.type === "shell" ? ">" : "\u2699";
107
+ };
108
+ const activeShellCount = shells.filter((s) => s.status === "running").length;
109
+ const activeAgentCount = agents.filter((a) => a.status === "running").length;
110
+ const totalActive = activeShellCount + activeAgentCount;
111
+ let countText = "";
112
+ if (totalActive === 0) {
113
+ countText = "No active tasks";
114
+ } else {
115
+ const parts = [];
116
+ if (activeShellCount > 0) {
117
+ parts.push(`${activeShellCount} shell${activeShellCount > 1 ? "s" : ""}`);
118
+ }
119
+ if (activeAgentCount > 0) {
120
+ parts.push(`${activeAgentCount} agent${activeAgentCount > 1 ? "s" : ""}`);
121
+ }
122
+ countText = parts.join(", ") + " running";
123
+ }
85
124
  return /* @__PURE__ */ React.createElement(
86
125
  Box,
87
126
  {
@@ -94,19 +133,24 @@ function BackgroundTasksPanel({
94
133
  /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { bold: true, color: theme.primary }, "Background tasks")),
95
134
  /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, countText)),
96
135
  /* @__PURE__ */ React.createElement(Box, { height: 1 }),
97
- shells.length === 0 ? /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, "(No background tasks)")) : shells.map((shell, index) => {
136
+ tasks.length === 0 ? /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, "(No background tasks)")) : tasks.map((task, index) => {
98
137
  const isSelected = index === selectedIndex;
99
138
  const bgColor = isSelected ? "cyan" : void 0;
100
- const duration = formatDuration(shell.startTime, shell.endTime);
101
- const summary = getSummary(shell);
102
- return /* @__PURE__ */ React.createElement(Box, { key: shell.id }, /* @__PURE__ */ React.createElement(
139
+ const status = task.type === "shell" ? task.data.status : task.data.status;
140
+ const startTime = task.data.startTime;
141
+ const endTime = task.type === "shell" ? task.data.endTime : task.data.endTime;
142
+ const id = task.type === "shell" ? task.data.id : task.data.agentId;
143
+ const duration = formatDuration(startTime, endTime);
144
+ const summary = task.type === "shell" ? getShellSummary(task.data) : getAgentSummary(task.data);
145
+ return /* @__PURE__ */ React.createElement(Box, { key: `${task.type}-${id}` }, /* @__PURE__ */ React.createElement(
103
146
  Text,
104
147
  {
105
148
  backgroundColor: bgColor,
106
149
  color: isSelected ? "black" : theme.primary
107
150
  },
108
151
  isSelected ? "\u276F " : " ",
109
- /* @__PURE__ */ React.createElement(Text, { color: getStatusColor(shell.status) }, getStatusIcon(shell.status), " "),
152
+ /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, getTypeIcon(task), " "),
153
+ /* @__PURE__ */ React.createElement(Text, { color: getStatusColor(status) }, getStatusIcon(status), " "),
110
154
  summary,
111
155
  /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, " [", duration, "]")
112
156
  ));
@@ -115,13 +159,18 @@ function BackgroundTasksPanel({
115
159
  /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, "\u2191/\u2193 to select \xB7 Enter to view \xB7 k to kill \xB7 Esc to close"))
116
160
  );
117
161
  }
118
- function getSummary(shell) {
162
+ function getShellSummary(shell) {
119
163
  const maxCmdLen = 40;
120
164
  const cmd = shell.command.length > maxCmdLen ? shell.command.slice(0, maxCmdLen) + "\u2026" : shell.command;
121
165
  const lastLine = shell.stdout[shell.stdout.length - 1] || "";
122
166
  const preview = lastLine.slice(0, 30);
123
167
  return preview ? `${cmd} ${preview}\u2026` : cmd;
124
168
  }
169
+ function getAgentSummary(agent) {
170
+ const maxLen = 50;
171
+ const desc = agent.description.length > maxLen ? agent.description.slice(0, maxLen) + "\u2026" : agent.description;
172
+ return `[${agent.agentType}] ${desc}`;
173
+ }
125
174
  export {
126
175
  BackgroundTasksPanel
127
176
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/components/BackgroundTasksPanel.tsx"],
4
- "sourcesContent": ["import { Box, Text, useInput } from 'ink'\nimport * as React from 'react'\nimport { useState, useEffect } from 'react'\nimport { getTheme } from '@utils/theme'\nimport type { BackgroundShell } from '@utils/BackgroundShellManager'\n\ntype Props = {\n shells: BackgroundShell[]\n isVisible: boolean\n onSelect: (shell: BackgroundShell) => void\n onKill: (shell: BackgroundShell) => void\n onClose: () => void\n}\n\nexport function BackgroundTasksPanel({\n shells,\n isVisible,\n onSelect,\n onKill,\n onClose,\n}: Props) {\n const [selectedIndex, setSelectedIndex] = useState(0)\n const theme = getTheme()\n\n // Reset selection when shells list changes\n useEffect(() => {\n if (selectedIndex >= shells.length && shells.length > 0) {\n setSelectedIndex(shells.length - 1)\n }\n }, [shells.length, selectedIndex])\n\n useInput(\n (input, key) => {\n if (key.upArrow) {\n setSelectedIndex(prev => Math.max(0, prev - 1))\n } else if (key.downArrow) {\n setSelectedIndex(prev => Math.min(shells.length - 1, prev + 1))\n } else if (key.return) {\n const selected = shells[selectedIndex]\n if (selected) onSelect(selected)\n } else if (input === 'k' || input === 'K') {\n const selected = shells[selectedIndex]\n if (selected) {\n console.log(\n '[BackgroundTasksPanel] Killing shell:',\n selected.id,\n selected.command,\n )\n onKill(selected)\n // Update selection if we killed the last item\n if (selectedIndex >= shells.length - 1 && shells.length > 1) {\n setSelectedIndex(shells.length - 2)\n }\n }\n } else if (key.escape) {\n onClose()\n } else {\n // Debug: log unhandled input\n console.log('[BackgroundTasksPanel] Unhandled input:', { input, key })\n }\n },\n { isActive: isVisible },\n )\n\n if (!isVisible) return null\n\n const formatDuration = (startTime: number, endTime?: number): string => {\n const duration = endTime ? endTime - startTime : Date.now() - startTime\n const seconds = Math.floor(duration / 1000)\n if (seconds < 60) return `${seconds}s`\n const minutes = Math.floor(seconds / 60)\n if (minutes < 60) return `${minutes}m ${seconds % 60}s`\n const hours = Math.floor(minutes / 60)\n return `${hours}h ${minutes % 60}m`\n }\n\n const getStatusColor = (status: string) => {\n switch (status) {\n case 'running':\n return theme.success\n case 'done':\n return theme.secondaryText\n case 'killed':\n return theme.error\n default:\n return theme.primary\n }\n }\n\n const getStatusIcon = (status: string) => {\n switch (status) {\n case 'running':\n return '\u25B6'\n case 'done':\n return '\u2713'\n case 'killed':\n return '\u2717'\n default:\n return '\u2022'\n }\n }\n\n const activeCount = shells.filter(s => s.status === 'running').length\n const countText =\n activeCount === 1 ? '1 active shell' : `${activeCount} active shells`\n\n return (\n <Box\n flexDirection=\"column\"\n borderStyle=\"single\"\n borderColor={theme.secondaryBorder}\n paddingX={1}\n marginBottom={1}\n >\n <Box>\n <Text bold color={theme.primary}>\n Background tasks\n </Text>\n </Box>\n <Box>\n <Text color={theme.secondaryText}>{countText}</Text>\n </Box>\n <Box height={1} />\n\n {shells.length === 0 ? (\n <Box>\n <Text color={theme.secondaryText}>(No background tasks)</Text>\n </Box>\n ) : (\n shells.map((shell, index) => {\n const isSelected = index === selectedIndex\n const bgColor = isSelected ? 'cyan' : undefined\n const duration = formatDuration(shell.startTime, shell.endTime)\n const summary = getSummary(shell)\n\n return (\n <Box key={shell.id}>\n <Text\n backgroundColor={bgColor}\n color={isSelected ? 'black' : theme.primary}\n >\n {isSelected ? '\u276F ' : ' '}\n <Text color={getStatusColor(shell.status)}>\n {getStatusIcon(shell.status)}{' '}\n </Text>\n {summary}\n <Text color={theme.secondaryText}> [{duration}]</Text>\n </Text>\n </Box>\n )\n })\n )}\n\n <Box height={1} />\n <Box>\n <Text color={theme.secondaryText}>\n \u2191/\u2193 to select \u00B7 Enter to view \u00B7 k to kill \u00B7 Esc to close\n </Text>\n </Box>\n </Box>\n )\n}\n\nfunction getSummary(shell: BackgroundShell): string {\n // Get command (truncate if too long)\n const maxCmdLen = 40\n const cmd =\n shell.command.length > maxCmdLen\n ? shell.command.slice(0, maxCmdLen) + '\u2026'\n : shell.command\n\n // Get last few lines of output for preview\n const lastLine = shell.stdout[shell.stdout.length - 1] || ''\n const preview = lastLine.slice(0, 30)\n\n return preview ? `${cmd} ${preview}\u2026` : cmd\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { Box, Text, useInput } from 'ink'\nimport * as React from 'react'\nimport { useState, useEffect, useCallback } from 'react'\nimport { getTheme } from '@utils/theme'\nimport type { BackgroundShell } from '@utils/BackgroundShellManager'\nimport {\n type BackgroundAgentInfo,\n getAllBackgroundAgents,\n cancelBackgroundAgent,\n backgroundAgentEvents,\n} from '@utils/backgroundAgentManager'\n\n/**\n * Unified background task type for both shells and agents\n */\nexport type BackgroundTask =\n | { type: 'shell'; data: BackgroundShell }\n | { type: 'agent'; data: BackgroundAgentInfo }\n\ntype Props = {\n shells: BackgroundShell[]\n isVisible: boolean\n onSelect: (shell: BackgroundShell) => void\n onKill: (shell: BackgroundShell) => void\n onClose: () => void\n}\n\nexport function BackgroundTasksPanel({\n shells,\n isVisible,\n onSelect,\n onKill,\n onClose,\n}: Props) {\n const [selectedIndex, setSelectedIndex] = useState(0)\n const [agents, setAgents] = useState<BackgroundAgentInfo[]>([])\n const theme = getTheme()\n\n // Subscribe to background agent events for real-time updates\n useEffect(() => {\n // Initialize with current agents\n setAgents(getAllBackgroundAgents())\n\n // Subscribe to status changes\n const unsubscribe = backgroundAgentEvents.onStatusChange(() => {\n setAgents(getAllBackgroundAgents())\n })\n\n return unsubscribe\n }, [])\n\n // Combine shells and agents into unified task list\n const tasks: BackgroundTask[] = [\n ...shells.map(shell => ({ type: 'shell' as const, data: shell })),\n ...agents.map(agent => ({ type: 'agent' as const, data: agent })),\n ]\n\n // Reset selection when task list changes\n useEffect(() => {\n if (selectedIndex >= tasks.length && tasks.length > 0) {\n setSelectedIndex(tasks.length - 1)\n }\n }, [tasks.length, selectedIndex])\n\n // Handle killing the selected task\n const handleKillSelected = useCallback(() => {\n const selected = tasks[selectedIndex]\n if (!selected) return\n\n if (selected.type === 'shell') {\n onKill(selected.data)\n } else if (selected.type === 'agent') {\n cancelBackgroundAgent(selected.data.agentId)\n }\n\n // Update selection if we killed the last item\n if (selectedIndex >= tasks.length - 1 && tasks.length > 1) {\n setSelectedIndex(tasks.length - 2)\n }\n }, [tasks, selectedIndex, onKill])\n\n useInput(\n (input, key) => {\n if (key.upArrow) {\n setSelectedIndex(prev => Math.max(0, prev - 1))\n } else if (key.downArrow) {\n setSelectedIndex(prev => Math.min(tasks.length - 1, prev + 1))\n } else if (key.return) {\n const selected = tasks[selectedIndex]\n if (selected?.type === 'shell') {\n onSelect(selected.data)\n }\n // Agent selection could be added later for viewing results\n } else if (input === 'k' || input === 'K') {\n handleKillSelected()\n } else if (key.escape) {\n onClose()\n }\n },\n { isActive: isVisible },\n )\n\n if (!isVisible) return null\n\n const formatDuration = (startTime: number, endTime?: number): string => {\n const duration = endTime ? endTime - startTime : Date.now() - startTime\n const seconds = Math.floor(duration / 1000)\n if (seconds < 60) return `${seconds}s`\n const minutes = Math.floor(seconds / 60)\n if (minutes < 60) return `${minutes}m ${seconds % 60}s`\n const hours = Math.floor(minutes / 60)\n return `${hours}h ${minutes % 60}m`\n }\n\n const getStatusColor = (status: string) => {\n switch (status) {\n case 'running':\n return theme.success\n case 'done':\n return theme.secondaryText\n case 'killed':\n return theme.error\n default:\n return theme.primary\n }\n }\n\n const getStatusIcon = (status: string) => {\n switch (status) {\n case 'running':\n return '\u25B6'\n case 'done':\n case 'completed':\n return '\u2713'\n case 'killed':\n case 'cancelled':\n return '\u2717'\n case 'failed':\n return '!'\n default:\n return '\u2022'\n }\n }\n\n // Get task type icon\n const getTypeIcon = (task: BackgroundTask) => {\n return task.type === 'shell' ? '>' : '\u2699'\n }\n\n // Count active tasks\n const activeShellCount = shells.filter(s => s.status === 'running').length\n const activeAgentCount = agents.filter(a => a.status === 'running').length\n const totalActive = activeShellCount + activeAgentCount\n\n // Build count text\n let countText = ''\n if (totalActive === 0) {\n countText = 'No active tasks'\n } else {\n const parts: string[] = []\n if (activeShellCount > 0) {\n parts.push(`${activeShellCount} shell${activeShellCount > 1 ? 's' : ''}`)\n }\n if (activeAgentCount > 0) {\n parts.push(`${activeAgentCount} agent${activeAgentCount > 1 ? 's' : ''}`)\n }\n countText = parts.join(', ') + ' running'\n }\n\n return (\n <Box\n flexDirection=\"column\"\n borderStyle=\"single\"\n borderColor={theme.secondaryBorder}\n paddingX={1}\n marginBottom={1}\n >\n <Box>\n <Text bold color={theme.primary}>\n Background tasks\n </Text>\n </Box>\n <Box>\n <Text color={theme.secondaryText}>{countText}</Text>\n </Box>\n <Box height={1} />\n\n {tasks.length === 0 ? (\n <Box>\n <Text color={theme.secondaryText}>(No background tasks)</Text>\n </Box>\n ) : (\n tasks.map((task, index) => {\n const isSelected = index === selectedIndex\n const bgColor = isSelected ? 'cyan' : undefined\n\n // Extract common properties based on task type\n const status =\n task.type === 'shell' ? task.data.status : task.data.status\n const startTime = task.data.startTime\n const endTime =\n task.type === 'shell' ? task.data.endTime : task.data.endTime\n const id = task.type === 'shell' ? task.data.id : task.data.agentId\n const duration = formatDuration(startTime, endTime)\n\n // Get summary based on task type\n const summary =\n task.type === 'shell'\n ? getShellSummary(task.data)\n : getAgentSummary(task.data)\n\n return (\n <Box key={`${task.type}-${id}`}>\n <Text\n backgroundColor={bgColor}\n color={isSelected ? 'black' : theme.primary}\n >\n {isSelected ? '\u276F ' : ' '}\n <Text color={theme.secondaryText}>{getTypeIcon(task)} </Text>\n <Text color={getStatusColor(status)}>\n {getStatusIcon(status)}{' '}\n </Text>\n {summary}\n <Text color={theme.secondaryText}> [{duration}]</Text>\n </Text>\n </Box>\n )\n })\n )}\n\n <Box height={1} />\n <Box>\n <Text color={theme.secondaryText}>\n \u2191/\u2193 to select \u00B7 Enter to view \u00B7 k to kill \u00B7 Esc to close\n </Text>\n </Box>\n </Box>\n )\n}\n\nfunction getShellSummary(shell: BackgroundShell): string {\n // Get command (truncate if too long)\n const maxCmdLen = 40\n const cmd =\n shell.command.length > maxCmdLen\n ? shell.command.slice(0, maxCmdLen) + '\u2026'\n : shell.command\n\n // Get last few lines of output for preview\n const lastLine = shell.stdout[shell.stdout.length - 1] || ''\n const preview = lastLine.slice(0, 30)\n\n return preview ? `${cmd} ${preview}\u2026` : cmd\n}\n\nfunction getAgentSummary(agent: BackgroundAgentInfo): string {\n // Get description (truncate if too long)\n const maxLen = 50\n const desc =\n agent.description.length > maxLen\n ? agent.description.slice(0, maxLen) + '\u2026'\n : agent.description\n\n return `[${agent.agentType}] ${desc}`\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,24 @@
1
+ import { Box, Text } from "ink";
2
+ import * as React from "react";
3
+ import { getTheme } from "../utils/theme.js";
4
+ const DEFAULT_MAX_LINES = 10;
5
+ function BashStreamingProgress({
6
+ stdout,
7
+ stderr,
8
+ isStreaming,
9
+ maxLines = DEFAULT_MAX_LINES
10
+ }) {
11
+ const theme = getTheme();
12
+ const stdoutLines = stdout ? stdout.split("\n").filter((line) => line.length > 0) : [];
13
+ const stderrLines = stderr ? stderr.split("\n").filter((line) => line.length > 0) : [];
14
+ const visibleStdoutLines = stdoutLines.slice(-maxLines);
15
+ const hiddenStdoutCount = Math.max(0, stdoutLines.length - maxLines);
16
+ const visibleStderrLines = stderrLines.slice(-maxLines);
17
+ const hiddenStderrCount = Math.max(0, stderrLines.length - maxLines);
18
+ const hasOutput = stdoutLines.length > 0 || stderrLines.length > 0;
19
+ return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, visibleStdoutLines.length > 0 && /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(Box, { flexDirection: "row" }, /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, "\xA0\xA0\u23BF "), hiddenStdoutCount > 0 && /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, "(", hiddenStdoutCount, " lines hidden)")), visibleStdoutLines.map((line, index) => /* @__PURE__ */ React.createElement(Box, { key: `stdout-${index}`, paddingLeft: 4 }, /* @__PURE__ */ React.createElement(Text, null, line)))), visibleStderrLines.length > 0 && /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(Box, { flexDirection: "row" }, /* @__PURE__ */ React.createElement(Text, { color: theme.error }, "\xA0\xA0\u23BF "), hiddenStderrCount > 0 && /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, "(", hiddenStderrCount, " error lines hidden)")), visibleStderrLines.map((line, index) => /* @__PURE__ */ React.createElement(Box, { key: `stderr-${index}`, paddingLeft: 4 }, /* @__PURE__ */ React.createElement(Text, { color: theme.error }, line)))), !hasOutput && isStreaming && /* @__PURE__ */ React.createElement(Box, { flexDirection: "row" }, /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, "\xA0\xA0\u23BF "), /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, "(waiting for output...)")), isStreaming && hasOutput && /* @__PURE__ */ React.createElement(Box, { flexDirection: "row", paddingLeft: 4 }, /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, "...")));
20
+ }
21
+ export {
22
+ BashStreamingProgress
23
+ };
24
+ //# sourceMappingURL=BashStreamingProgress.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/components/BashStreamingProgress.tsx"],
4
+ "sourcesContent": ["import { Box, Text } from 'ink'\nimport * as React from 'react'\nimport { getTheme } from '@utils/theme'\n\n/**\n * Props for BashStreamingProgress component\n * Displays real-time streaming output from Bash commands\n */\ntype Props = {\n stdout: string\n stderr: string\n isStreaming: boolean\n maxLines?: number\n}\n\nconst DEFAULT_MAX_LINES = 10\n\n/**\n * Component for displaying real-time streaming Bash output\n * Used during command execution to show progressive output\n */\nexport function BashStreamingProgress({\n stdout,\n stderr,\n isStreaming,\n maxLines = DEFAULT_MAX_LINES,\n}: Props) {\n const theme = getTheme()\n\n // Split output into lines and calculate visibility\n const stdoutLines = stdout\n ? stdout.split('\\n').filter(line => line.length > 0)\n : []\n const stderrLines = stderr\n ? stderr.split('\\n').filter(line => line.length > 0)\n : []\n\n // Calculate visible lines (show last N lines for tailing behavior)\n const visibleStdoutLines = stdoutLines.slice(-maxLines)\n const hiddenStdoutCount = Math.max(0, stdoutLines.length - maxLines)\n\n const visibleStderrLines = stderrLines.slice(-maxLines)\n const hiddenStderrCount = Math.max(0, stderrLines.length - maxLines)\n\n const hasOutput = stdoutLines.length > 0 || stderrLines.length > 0\n\n return (\n <Box flexDirection=\"column\">\n {/* Stdout output */}\n {visibleStdoutLines.length > 0 && (\n <Box flexDirection=\"column\">\n <Box flexDirection=\"row\">\n <Text color={theme.secondaryText}>&nbsp;&nbsp;\u23BF </Text>\n {hiddenStdoutCount > 0 && (\n <Text color={theme.secondaryText}>\n ({hiddenStdoutCount} lines hidden)\n </Text>\n )}\n </Box>\n {visibleStdoutLines.map((line, index) => (\n <Box key={`stdout-${index}`} paddingLeft={4}>\n <Text>{line}</Text>\n </Box>\n ))}\n </Box>\n )}\n\n {/* Stderr output */}\n {visibleStderrLines.length > 0 && (\n <Box flexDirection=\"column\">\n <Box flexDirection=\"row\">\n <Text color={theme.error}>&nbsp;&nbsp;\u23BF </Text>\n {hiddenStderrCount > 0 && (\n <Text color={theme.secondaryText}>\n ({hiddenStderrCount} error lines hidden)\n </Text>\n )}\n </Box>\n {visibleStderrLines.map((line, index) => (\n <Box key={`stderr-${index}`} paddingLeft={4}>\n <Text color={theme.error}>{line}</Text>\n </Box>\n ))}\n </Box>\n )}\n\n {/* Empty output indicator */}\n {!hasOutput && isStreaming && (\n <Box flexDirection=\"row\">\n <Text color={theme.secondaryText}>&nbsp;&nbsp;\u23BF </Text>\n <Text color={theme.secondaryText}>(waiting for output...)</Text>\n </Box>\n )}\n\n {/* Streaming indicator */}\n {isStreaming && hasOutput && (\n <Box flexDirection=\"row\" paddingLeft={4}>\n <Text color={theme.secondaryText}>...</Text>\n </Box>\n )}\n </Box>\n )\n}\n"],
5
+ "mappings": "AAAA,SAAS,KAAK,YAAY;AAC1B,YAAY,WAAW;AACvB,SAAS,gBAAgB;AAazB,MAAM,oBAAoB;AAMnB,SAAS,sBAAsB;AAAA,EACpC;AAAA,EACA;AAAA,EACA;AAAA,EACA,WAAW;AACb,GAAU;AACR,QAAM,QAAQ,SAAS;AAGvB,QAAM,cAAc,SAChB,OAAO,MAAM,IAAI,EAAE,OAAO,UAAQ,KAAK,SAAS,CAAC,IACjD,CAAC;AACL,QAAM,cAAc,SAChB,OAAO,MAAM,IAAI,EAAE,OAAO,UAAQ,KAAK,SAAS,CAAC,IACjD,CAAC;AAGL,QAAM,qBAAqB,YAAY,MAAM,CAAC,QAAQ;AACtD,QAAM,oBAAoB,KAAK,IAAI,GAAG,YAAY,SAAS,QAAQ;AAEnE,QAAM,qBAAqB,YAAY,MAAM,CAAC,QAAQ;AACtD,QAAM,oBAAoB,KAAK,IAAI,GAAG,YAAY,SAAS,QAAQ;AAEnE,QAAM,YAAY,YAAY,SAAS,KAAK,YAAY,SAAS;AAEjE,SACE,oCAAC,OAAI,eAAc,YAEhB,mBAAmB,SAAS,KAC3B,oCAAC,OAAI,eAAc,YACjB,oCAAC,OAAI,eAAc,SACjB,oCAAC,QAAK,OAAO,MAAM,iBAAe,iBAAc,GAC/C,oBAAoB,KACnB,oCAAC,QAAK,OAAO,MAAM,iBAAe,KAC9B,mBAAkB,gBACtB,CAEJ,GACC,mBAAmB,IAAI,CAAC,MAAM,UAC7B,oCAAC,OAAI,KAAK,UAAU,KAAK,IAAI,aAAa,KACxC,oCAAC,YAAM,IAAK,CACd,CACD,CACH,GAID,mBAAmB,SAAS,KAC3B,oCAAC,OAAI,eAAc,YACjB,oCAAC,OAAI,eAAc,SACjB,oCAAC,QAAK,OAAO,MAAM,SAAO,iBAAc,GACvC,oBAAoB,KACnB,oCAAC,QAAK,OAAO,MAAM,iBAAe,KAC9B,mBAAkB,sBACtB,CAEJ,GACC,mBAAmB,IAAI,CAAC,MAAM,UAC7B,oCAAC,OAAI,KAAK,UAAU,KAAK,IAAI,aAAa,KACxC,oCAAC,QAAK,OAAO,MAAM,SAAQ,IAAK,CAClC,CACD,CACH,GAID,CAAC,aAAa,eACb,oCAAC,OAAI,eAAc,SACjB,oCAAC,QAAK,OAAO,MAAM,iBAAe,iBAAc,GAChD,oCAAC,QAAK,OAAO,MAAM,iBAAe,yBAAuB,CAC3D,GAID,eAAe,aACd,oCAAC,OAAI,eAAc,OAAM,aAAa,KACpC,oCAAC,QAAK,OAAO,MAAM,iBAAe,KAAG,CACvC,CAEJ;AAEJ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,14 @@
1
+ import React from "react";
2
+ import { Text } from "ink";
3
+ function CollapsibleHint({
4
+ canExpand,
5
+ shortcut = "ctrl+o",
6
+ action = "expand"
7
+ }) {
8
+ if (!canExpand) return null;
9
+ return /* @__PURE__ */ React.createElement(Text, { dimColor: true }, " ", "(", shortcut, " to ", action, ")");
10
+ }
11
+ export {
12
+ CollapsibleHint
13
+ };
14
+ //# sourceMappingURL=CollapsibleHint.js.map