@within-7/minto 0.4.0 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (391) hide show
  1. package/dist/Tool.js +7 -0
  2. package/dist/Tool.js.map +2 -2
  3. package/dist/commands/agents/AgentsCommand.js +1 -1
  4. package/dist/commands/agents/AgentsCommand.js.map +2 -2
  5. package/dist/commands/agents/constants.js +2 -2
  6. package/dist/commands/agents/constants.js.map +2 -2
  7. package/dist/commands/clear.js +4 -3
  8. package/dist/commands/clear.js.map +2 -2
  9. package/dist/commands/compact.js +2 -2
  10. package/dist/commands/compact.js.map +1 -1
  11. package/dist/commands/context.js +3 -1
  12. package/dist/commands/context.js.map +2 -2
  13. package/dist/commands/login.js +128 -0
  14. package/dist/commands/login.js.map +7 -0
  15. package/dist/commands/memory.js +33 -82
  16. package/dist/commands/memory.js.map +2 -2
  17. package/dist/commands/quit.js +3 -1
  18. package/dist/commands/quit.js.map +2 -2
  19. package/dist/commands/resume.js +39 -239
  20. package/dist/commands/resume.js.map +2 -2
  21. package/dist/commands/tasks.js +1 -1
  22. package/dist/commands/tasks.js.map +2 -2
  23. package/dist/commands/terminalSetup.js +6 -2
  24. package/dist/commands/terminalSetup.js.map +2 -2
  25. package/dist/commands.js +2 -0
  26. package/dist/commands.js.map +2 -2
  27. package/dist/components/AgentDetailView.js +126 -0
  28. package/dist/components/AgentDetailView.js.map +7 -0
  29. package/dist/components/AgentThinkingBlock.js +1 -1
  30. package/dist/components/AgentThinkingBlock.js.map +2 -2
  31. package/dist/components/AgentViewBanner.js +22 -0
  32. package/dist/components/AgentViewBanner.js.map +7 -0
  33. package/dist/components/HeaderBar.js +1 -1
  34. package/dist/components/HeaderBar.js.map +2 -2
  35. package/dist/components/Help.js +8 -1
  36. package/dist/components/Help.js.map +2 -2
  37. package/dist/components/HotkeyHelpPanel.js +26 -8
  38. package/dist/components/HotkeyHelpPanel.js.map +2 -2
  39. package/dist/components/IdleNotificationBar.js +10 -0
  40. package/dist/components/IdleNotificationBar.js.map +7 -0
  41. package/dist/components/ModelSelector/ModelSelector.js +55 -20
  42. package/dist/components/ModelSelector/ModelSelector.js.map +2 -2
  43. package/dist/components/PromptInput.js +186 -115
  44. package/dist/components/PromptInput.js.map +2 -2
  45. package/dist/components/RewindPanel.js +272 -0
  46. package/dist/components/RewindPanel.js.map +7 -0
  47. package/dist/components/Spinner.js +10 -21
  48. package/dist/components/Spinner.js.map +2 -2
  49. package/dist/components/StreamingTextPreview.js +29 -0
  50. package/dist/components/StreamingTextPreview.js.map +7 -0
  51. package/dist/components/SubagentBlock.js +3 -2
  52. package/dist/components/SubagentBlock.js.map +2 -2
  53. package/dist/components/SubagentProgress.js +4 -4
  54. package/dist/components/SubagentProgress.js.map +2 -2
  55. package/dist/components/TabbedListView/SearchInput.js +1 -1
  56. package/dist/components/TabbedListView/SearchInput.js.map +2 -2
  57. package/dist/components/TabbedListView/TabbedListView.js +87 -41
  58. package/dist/components/TabbedListView/TabbedListView.js.map +2 -2
  59. package/dist/components/TaskCard.js +4 -4
  60. package/dist/components/TaskCard.js.map +2 -2
  61. package/dist/components/TeamMemberPanel.js +107 -0
  62. package/dist/components/TeamMemberPanel.js.map +7 -0
  63. package/dist/components/ThinkingSelector.js +84 -0
  64. package/dist/components/ThinkingSelector.js.map +7 -0
  65. package/dist/components/TitledDivider.js +26 -0
  66. package/dist/components/TitledDivider.js.map +7 -0
  67. package/dist/components/TodoPanel.js +31 -30
  68. package/dist/components/TodoPanel.js.map +2 -2
  69. package/dist/components/TokenWarning.js +28 -7
  70. package/dist/components/TokenWarning.js.map +2 -2
  71. package/dist/components/messages/AssistantTextMessage.js +5 -2
  72. package/dist/components/messages/AssistantTextMessage.js.map +2 -2
  73. package/dist/components/messages/AssistantToolUseMessage.js +9 -1
  74. package/dist/components/messages/AssistantToolUseMessage.js.map +2 -2
  75. package/dist/components/messages/DefaultToolResultFallback.js +11 -0
  76. package/dist/components/messages/DefaultToolResultFallback.js.map +7 -0
  77. package/dist/components/messages/ParallelTasksGroupView.js +14 -6
  78. package/dist/components/messages/ParallelTasksGroupView.js.map +2 -2
  79. package/dist/components/messages/TaskInModuleView.js +27 -27
  80. package/dist/components/messages/TaskInModuleView.js.map +2 -2
  81. package/dist/components/messages/UserGuidanceMessage.js +26 -0
  82. package/dist/components/messages/UserGuidanceMessage.js.map +7 -0
  83. package/dist/components/messages/UserPromptMessage.js +2 -1
  84. package/dist/components/messages/UserPromptMessage.js.map +2 -2
  85. package/dist/components/messages/UserTeamNotificationMessage.js +91 -0
  86. package/dist/components/messages/UserTeamNotificationMessage.js.map +7 -0
  87. package/dist/components/messages/UserTextMessage.js +8 -0
  88. package/dist/components/messages/UserTextMessage.js.map +2 -2
  89. package/dist/components/messages/UserToolResultMessage/UserToolRejectMessage.js +4 -2
  90. package/dist/components/messages/UserToolResultMessage/UserToolRejectMessage.js.map +2 -2
  91. package/dist/components/messages/UserToolResultMessage/UserToolResultMessage.js +18 -1
  92. package/dist/components/messages/UserToolResultMessage/UserToolResultMessage.js.map +2 -2
  93. package/dist/components/messages/UserToolResultMessage/UserToolSuccessMessage.js +12 -1
  94. package/dist/components/messages/UserToolResultMessage/UserToolSuccessMessage.js.map +2 -2
  95. package/dist/components/permissions/PermissionRequest.js +4 -0
  96. package/dist/components/permissions/PermissionRequest.js.map +2 -2
  97. package/dist/components/permissions/PlanApprovalRequest.js +164 -0
  98. package/dist/components/permissions/PlanApprovalRequest.js.map +7 -0
  99. package/dist/constants/agentTeams.js +17 -0
  100. package/dist/constants/agentTeams.js.map +7 -0
  101. package/dist/constants/macros.js +2 -1
  102. package/dist/constants/macros.js.map +2 -2
  103. package/dist/constants/prompts/agentPrompt.js +1 -0
  104. package/dist/constants/prompts/agentPrompt.js.map +2 -2
  105. package/dist/constants/prompts/autoMemory.js +39 -0
  106. package/dist/constants/prompts/autoMemory.js.map +7 -0
  107. package/dist/constants/prompts/codeConventions.js +1 -13
  108. package/dist/constants/prompts/codeConventions.js.map +2 -2
  109. package/dist/constants/prompts/doingTasks.js +21 -2
  110. package/dist/constants/prompts/doingTasks.js.map +2 -2
  111. package/dist/constants/prompts/envInfo.js +6 -7
  112. package/dist/constants/prompts/envInfo.js.map +2 -2
  113. package/dist/constants/prompts/index.js +27 -5
  114. package/dist/constants/prompts/index.js.map +2 -2
  115. package/dist/constants/prompts/taskManagement.js +2 -43
  116. package/dist/constants/prompts/taskManagement.js.map +2 -2
  117. package/dist/constants/prompts/teamOverlays.js +50 -0
  118. package/dist/constants/prompts/teamOverlays.js.map +7 -0
  119. package/dist/constants/prompts/toneAndStyle.js +4 -29
  120. package/dist/constants/prompts/toneAndStyle.js.map +2 -2
  121. package/dist/constants/prompts/toolUsagePolicy.js +7 -22
  122. package/dist/constants/prompts/toolUsagePolicy.js.map +2 -2
  123. package/dist/constants/toolInputExamples.js +2 -2
  124. package/dist/constants/toolInputExamples.js.map +2 -2
  125. package/dist/context.js +39 -6
  126. package/dist/context.js.map +2 -2
  127. package/dist/core/backupManager.js +1 -1
  128. package/dist/core/backupManager.js.map +2 -2
  129. package/dist/core/permissions/rules/planModeRule.js +1 -1
  130. package/dist/core/permissions/rules/planModeRule.js.map +1 -1
  131. package/dist/core/permissions/rules/safeModeRule.js +1 -1
  132. package/dist/core/permissions/rules/safeModeRule.js.map +1 -1
  133. package/dist/engine/AgentEngine.js +902 -0
  134. package/dist/engine/AgentEngine.js.map +7 -0
  135. package/dist/engine/EngineRegistry.js +89 -0
  136. package/dist/engine/EngineRegistry.js.map +7 -0
  137. package/dist/engine/foregroundAdapter.js +191 -0
  138. package/dist/engine/foregroundAdapter.js.map +7 -0
  139. package/dist/engine/index.js +15 -0
  140. package/dist/engine/index.js.map +7 -0
  141. package/dist/engine/types.js +1 -0
  142. package/dist/engine/types.js.map +7 -0
  143. package/dist/entrypoints/cli.js +410 -79
  144. package/dist/entrypoints/cli.js.map +3 -3
  145. package/dist/hooks/useAgentEngine.js +129 -0
  146. package/dist/hooks/useAgentEngine.js.map +7 -0
  147. package/dist/hooks/useAgentTokenStats.js +0 -16
  148. package/dist/hooks/useAgentTokenStats.js.map +2 -2
  149. package/dist/hooks/useCanUseTool.js +47 -2
  150. package/dist/hooks/useCanUseTool.js.map +2 -2
  151. package/dist/hooks/useDeferredLoading.js +4 -1
  152. package/dist/hooks/useDeferredLoading.js.map +2 -2
  153. package/dist/hooks/useIdleNotifications.js +66 -0
  154. package/dist/hooks/useIdleNotifications.js.map +7 -0
  155. package/dist/hooks/useSessionTracking.js +9 -7
  156. package/dist/hooks/useSessionTracking.js.map +2 -2
  157. package/dist/hooks/useTeamMembers.js +51 -0
  158. package/dist/hooks/useTeamMembers.js.map +7 -0
  159. package/dist/i18n/locales/en.js +77 -12
  160. package/dist/i18n/locales/en.js.map +2 -2
  161. package/dist/i18n/locales/zh-CN.js +77 -12
  162. package/dist/i18n/locales/zh-CN.js.map +2 -2
  163. package/dist/i18n/types.js.map +1 -1
  164. package/dist/messages.js.map +2 -2
  165. package/dist/permissions.js +113 -7
  166. package/dist/permissions.js.map +2 -2
  167. package/dist/query.js +135 -37
  168. package/dist/query.js.map +2 -2
  169. package/dist/screens/REPL.js +504 -361
  170. package/dist/screens/REPL.js.map +3 -3
  171. package/dist/screens/ResumeConversation.js +199 -14
  172. package/dist/screens/ResumeConversation.js.map +2 -2
  173. package/dist/services/adapters/base.js.map +1 -1
  174. package/dist/services/agentTeams/backends/headless.js +108 -0
  175. package/dist/services/agentTeams/backends/headless.js.map +7 -0
  176. package/dist/services/agentTeams/backends/inProcess.js +102 -0
  177. package/dist/services/agentTeams/backends/inProcess.js.map +7 -0
  178. package/dist/services/agentTeams/backends/resolver.js +18 -0
  179. package/dist/services/agentTeams/backends/resolver.js.map +7 -0
  180. package/dist/services/agentTeams/backends/tmux.js +168 -0
  181. package/dist/services/agentTeams/backends/tmux.js.map +7 -0
  182. package/dist/services/agentTeams/backends/types.js +1 -0
  183. package/dist/services/agentTeams/backends/types.js.map +7 -0
  184. package/dist/services/agentTeams/heartbeat.js +88 -0
  185. package/dist/services/agentTeams/heartbeat.js.map +7 -0
  186. package/dist/services/agentTeams/index.js +42 -2
  187. package/dist/services/agentTeams/index.js.map +2 -2
  188. package/dist/services/agentTeams/injectionChannel.js +105 -0
  189. package/dist/services/agentTeams/injectionChannel.js.map +7 -0
  190. package/dist/services/agentTeams/mailbox.js +410 -30
  191. package/dist/services/agentTeams/mailbox.js.map +2 -2
  192. package/dist/services/agentTeams/messageFormatter.js +80 -0
  193. package/dist/services/agentTeams/messageFormatter.js.map +7 -0
  194. package/dist/services/agentTeams/permissionDelegation.js +71 -0
  195. package/dist/services/agentTeams/permissionDelegation.js.map +7 -0
  196. package/dist/services/agentTeams/teamEvents.js +45 -0
  197. package/dist/services/agentTeams/teamEvents.js.map +7 -0
  198. package/dist/services/agentTeams/teamManager.js +251 -34
  199. package/dist/services/agentTeams/teamManager.js.map +2 -2
  200. package/dist/services/agentTeams/teamTaskStore.js +290 -61
  201. package/dist/services/agentTeams/teamTaskStore.js.map +2 -2
  202. package/dist/services/agentTeams/teammateSpawner.js +99 -18
  203. package/dist/services/agentTeams/teammateSpawner.js.map +2 -2
  204. package/dist/services/hookExecutor.js +51 -8
  205. package/dist/services/hookExecutor.js.map +2 -2
  206. package/dist/services/llm/anthropicProvider.js +56 -59
  207. package/dist/services/llm/anthropicProvider.js.map +2 -2
  208. package/dist/services/llm/dispatch.js +24 -5
  209. package/dist/services/llm/dispatch.js.map +2 -2
  210. package/dist/services/llm/openaiProvider.js +115 -136
  211. package/dist/services/llm/openaiProvider.js.map +3 -3
  212. package/dist/services/llm/types.js +89 -15
  213. package/dist/services/llm/types.js.map +2 -2
  214. package/dist/services/mcpClient.js +80 -4
  215. package/dist/services/mcpClient.js.map +2 -2
  216. package/dist/services/mintoAuth.js +299 -0
  217. package/dist/services/mintoAuth.js.map +7 -0
  218. package/dist/services/oauth.js +3 -3
  219. package/dist/services/oauth.js.map +2 -2
  220. package/dist/services/openai.js +91 -20
  221. package/dist/services/openai.js.map +2 -2
  222. package/dist/services/plugins/pluginRuntime.js +11 -5
  223. package/dist/services/plugins/pluginRuntime.js.map +2 -2
  224. package/dist/services/plugins/pluginValidation.js +4 -2
  225. package/dist/services/plugins/pluginValidation.js.map +2 -2
  226. package/dist/services/sandbox/sandboxController.js +11 -3
  227. package/dist/services/sandbox/sandboxController.js.map +2 -2
  228. package/dist/services/sessionMemoryInjector.js +77 -0
  229. package/dist/services/sessionMemoryInjector.js.map +7 -0
  230. package/dist/services/systemReminder.js +130 -8
  231. package/dist/services/systemReminder.js.map +2 -2
  232. package/dist/services/taskStore.js +199 -8
  233. package/dist/services/taskStore.js.map +3 -3
  234. package/dist/services/topicDetector.js +169 -0
  235. package/dist/services/topicDetector.js.map +7 -0
  236. package/dist/tools/AskExpertModelTool/AskExpertModelTool.js +0 -13
  237. package/dist/tools/AskExpertModelTool/AskExpertModelTool.js.map +2 -2
  238. package/dist/tools/BashTool/BashTool.js +51 -28
  239. package/dist/tools/BashTool/BashTool.js.map +2 -2
  240. package/dist/tools/BashTool/prompt.js +95 -118
  241. package/dist/tools/BashTool/prompt.js.map +2 -2
  242. package/dist/tools/BashTool/utils.js +39 -1
  243. package/dist/tools/BashTool/utils.js.map +2 -2
  244. package/dist/tools/EnterWorktreeTool/EnterWorktreeTool.js +121 -0
  245. package/dist/tools/EnterWorktreeTool/EnterWorktreeTool.js.map +7 -0
  246. package/dist/tools/EnterWorktreeTool/prompt.js +22 -0
  247. package/dist/tools/EnterWorktreeTool/prompt.js.map +7 -0
  248. package/dist/tools/FileEditTool/FileEditTool.js +9 -4
  249. package/dist/tools/FileEditTool/FileEditTool.js.map +2 -2
  250. package/dist/tools/FileEditTool/prompt.js +3 -7
  251. package/dist/tools/FileEditTool/prompt.js.map +2 -2
  252. package/dist/tools/FileReadTool/FileReadTool.js +125 -3
  253. package/dist/tools/FileReadTool/FileReadTool.js.map +2 -2
  254. package/dist/tools/FileReadTool/prompt.js +1 -2
  255. package/dist/tools/FileReadTool/prompt.js.map +2 -2
  256. package/dist/tools/FileWriteTool/prompt.js +3 -5
  257. package/dist/tools/FileWriteTool/prompt.js.map +2 -2
  258. package/dist/tools/GlobTool/GlobTool.js +3 -2
  259. package/dist/tools/GlobTool/GlobTool.js.map +2 -2
  260. package/dist/tools/GrepTool/GrepTool.js +16 -5
  261. package/dist/tools/GrepTool/GrepTool.js.map +2 -2
  262. package/dist/tools/ListMcpResourcesTool/ListMcpResourcesTool.js.map +2 -2
  263. package/dist/tools/MCPSearchTool/MCPSearchTool.js +172 -0
  264. package/dist/tools/MCPSearchTool/MCPSearchTool.js.map +7 -0
  265. package/dist/tools/MCPSearchTool/prompt.js +77 -0
  266. package/dist/tools/MCPSearchTool/prompt.js.map +7 -0
  267. package/dist/tools/MultiEditTool/prompt.js +4 -7
  268. package/dist/tools/MultiEditTool/prompt.js.map +2 -2
  269. package/dist/tools/PlanModeTool/EnterPlanModeTool.js +12 -8
  270. package/dist/tools/PlanModeTool/EnterPlanModeTool.js.map +2 -2
  271. package/dist/tools/PlanModeTool/ExitPlanModeTool.js +54 -1
  272. package/dist/tools/PlanModeTool/ExitPlanModeTool.js.map +2 -2
  273. package/dist/tools/PlanModeTool/prompt.js +23 -74
  274. package/dist/tools/PlanModeTool/prompt.js.map +2 -2
  275. package/dist/tools/SendMessageTool/SendMessageTool.js +341 -0
  276. package/dist/tools/SendMessageTool/SendMessageTool.js.map +7 -0
  277. package/dist/tools/SendMessageTool/prompt.js +44 -0
  278. package/dist/tools/SendMessageTool/prompt.js.map +7 -0
  279. package/dist/tools/TaskCreateTool/prompt.js +15 -4
  280. package/dist/tools/TaskCreateTool/prompt.js.map +2 -2
  281. package/dist/tools/TaskListTool/prompt.js +18 -3
  282. package/dist/tools/TaskListTool/prompt.js.map +2 -2
  283. package/dist/tools/TaskOutputTool/prompt.js +4 -3
  284. package/dist/tools/TaskOutputTool/prompt.js.map +2 -2
  285. package/dist/tools/TaskTool/TaskTool.js +762 -98
  286. package/dist/tools/TaskTool/TaskTool.js.map +3 -3
  287. package/dist/tools/TaskTool/constants.js +8 -2
  288. package/dist/tools/TaskTool/constants.js.map +2 -2
  289. package/dist/tools/TaskTool/prompt.js +74 -70
  290. package/dist/tools/TaskTool/prompt.js.map +2 -2
  291. package/dist/tools/TaskUpdateTool/TaskUpdateTool.js +15 -1
  292. package/dist/tools/TaskUpdateTool/TaskUpdateTool.js.map +2 -2
  293. package/dist/tools/TeamCreateTool/TeamCreateTool.js +129 -0
  294. package/dist/tools/TeamCreateTool/TeamCreateTool.js.map +7 -0
  295. package/dist/tools/TeamCreateTool/prompt.js +58 -0
  296. package/dist/tools/TeamCreateTool/prompt.js.map +7 -0
  297. package/dist/tools/TeamDeleteTool/TeamDeleteTool.js +151 -0
  298. package/dist/tools/TeamDeleteTool/TeamDeleteTool.js.map +7 -0
  299. package/dist/tools/TeamDeleteTool/prompt.js +16 -0
  300. package/dist/tools/TeamDeleteTool/prompt.js.map +7 -0
  301. package/dist/tools/URLFetcherTool/URLFetcherTool.js +106 -15
  302. package/dist/tools/URLFetcherTool/URLFetcherTool.js.map +2 -2
  303. package/dist/tools/URLFetcherTool/prompt.js +3 -2
  304. package/dist/tools/URLFetcherTool/prompt.js.map +2 -2
  305. package/dist/tools/WebSearchTool/WebSearchTool.js +2 -1
  306. package/dist/tools/WebSearchTool/WebSearchTool.js.map +2 -2
  307. package/dist/tools/WebSearchTool/prompt.js +5 -4
  308. package/dist/tools/WebSearchTool/prompt.js.map +2 -2
  309. package/dist/tools.js +100 -20
  310. package/dist/tools.js.map +2 -2
  311. package/dist/types/PermissionMode.js +35 -6
  312. package/dist/types/PermissionMode.js.map +2 -2
  313. package/dist/types/hooks.js +2 -0
  314. package/dist/types/hooks.js.map +2 -2
  315. package/dist/types/plugin.js +2 -0
  316. package/dist/types/plugin.js.map +3 -3
  317. package/dist/utils/CircuitBreaker.js +15 -9
  318. package/dist/utils/CircuitBreaker.js.map +2 -2
  319. package/dist/utils/agentLoader.js +249 -112
  320. package/dist/utils/agentLoader.js.map +2 -2
  321. package/dist/utils/animationManager.js +40 -3
  322. package/dist/utils/animationManager.js.map +2 -2
  323. package/dist/utils/ask.js +7 -6
  324. package/dist/utils/ask.js.map +2 -2
  325. package/dist/utils/atomicWrite.js +23 -0
  326. package/dist/utils/atomicWrite.js.map +7 -0
  327. package/dist/utils/autoCompactCore.js +73 -56
  328. package/dist/utils/autoCompactCore.js.map +2 -2
  329. package/dist/utils/autoMemoryPaths.js +89 -0
  330. package/dist/utils/autoMemoryPaths.js.map +7 -0
  331. package/dist/utils/config.js +63 -38
  332. package/dist/utils/config.js.map +2 -2
  333. package/dist/utils/configSchema.js +13 -8
  334. package/dist/utils/configSchema.js.map +2 -2
  335. package/dist/utils/credentials/index.js +14 -0
  336. package/dist/utils/credentials/index.js.map +2 -2
  337. package/dist/utils/dualPath.js +24 -0
  338. package/dist/utils/dualPath.js.map +7 -0
  339. package/dist/utils/exit.js +66 -7
  340. package/dist/utils/exit.js.map +2 -2
  341. package/dist/utils/externalEditor.js +155 -0
  342. package/dist/utils/externalEditor.js.map +7 -0
  343. package/dist/utils/fileLock.js +67 -0
  344. package/dist/utils/fileLock.js.map +7 -0
  345. package/dist/utils/format.js +24 -14
  346. package/dist/utils/format.js.map +2 -2
  347. package/dist/utils/globalErrorHandler.js +5 -96
  348. package/dist/utils/globalErrorHandler.js.map +3 -3
  349. package/dist/utils/groupHandlers/parallelTasksHandler.js +5 -3
  350. package/dist/utils/groupHandlers/parallelTasksHandler.js.map +2 -2
  351. package/dist/utils/groupHandlers/taskHandler.js +2 -2
  352. package/dist/utils/groupHandlers/taskHandler.js.map +2 -2
  353. package/dist/utils/hookManager.js +64 -6
  354. package/dist/utils/hookManager.js.map +2 -2
  355. package/dist/utils/log.js +6 -2
  356. package/dist/utils/log.js.map +2 -2
  357. package/dist/utils/markdown.js +237 -19
  358. package/dist/utils/markdown.js.map +2 -2
  359. package/dist/utils/messageContextManager.js +18 -5
  360. package/dist/utils/messageContextManager.js.map +2 -2
  361. package/dist/utils/messageGroupManager.js +1 -1
  362. package/dist/utils/messageGroupManager.js.map +2 -2
  363. package/dist/utils/messages.js +104 -46
  364. package/dist/utils/messages.js.map +2 -2
  365. package/dist/utils/model.js +2 -2
  366. package/dist/utils/model.js.map +2 -2
  367. package/dist/utils/pasteCache.js +8 -4
  368. package/dist/utils/pasteCache.js.map +2 -2
  369. package/dist/utils/pluginLoader.js +18 -0
  370. package/dist/utils/pluginLoader.js.map +2 -2
  371. package/dist/utils/secureKeyStorage.js +36 -7
  372. package/dist/utils/secureKeyStorage.js.map +2 -2
  373. package/dist/utils/simpleMode.js +7 -0
  374. package/dist/utils/simpleMode.js.map +7 -0
  375. package/dist/utils/streamingState.js +11 -1
  376. package/dist/utils/streamingState.js.map +2 -2
  377. package/dist/utils/taskDisplayUtils.js +2 -1
  378. package/dist/utils/taskDisplayUtils.js.map +2 -2
  379. package/dist/utils/teamConfig.js +2 -2
  380. package/dist/utils/teamConfig.js.map +2 -2
  381. package/dist/utils/thinking.js +6 -2
  382. package/dist/utils/thinking.js.map +3 -3
  383. package/dist/utils/tokenProgress.js +55 -0
  384. package/dist/utils/tokenProgress.js.map +7 -0
  385. package/dist/utils/toolRiskClassification.js +26 -17
  386. package/dist/utils/toolRiskClassification.js.map +2 -2
  387. package/dist/utils/tooling/toolError.js +12 -0
  388. package/dist/utils/tooling/toolError.js.map +7 -0
  389. package/dist/version.js +2 -2
  390. package/dist/version.js.map +1 -1
  391. package/package.json +10 -8
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/components/SubagentBlock.tsx"],
4
- "sourcesContent": ["/**\n * SubagentBlock - Embedded subagent execution display\n *\n * Renders a complete subagent execution hierarchically with:\n * - Header (task name, agent type, status)\n * - Optional: Subtasks (if subagent has todos)\n * - Optional: Thinking phase\n * - Optional: Tool executions\n * - Optional: Response\n * - Footer (completion status)\n *\n * Supports collapsible internal content\n */\n\nimport React, { useState } from 'react'\nimport { Box, Text } from 'ink'\nimport { getTheme } from '@utils/theme'\nimport { SYMBOLS, getTodoStatusSymbol } from '@constants/symbols'\nimport { AgentThinkingBlock } from './AgentThinkingBlock'\nimport { ToolExecutionBlock } from './ToolExecutionBlock'\nimport { AgentResponseBlock } from './AgentResponseBlock'\nimport { useAgentTokenStats, formatTokenCount } from '@hooks/useAgentTokenStats'\nimport type { SubagentState } from '@minto-types/subagent'\nimport type { TodoItem } from '@utils/todoStorage'\nimport type { AssistantMessage } from '@minto-types/conversation'\nimport type { TextBlockParam } from '@anthropic-ai/sdk/resources/index.mjs'\n\ninterface Props {\n subagent: SubagentState\n indent?: number\n isExpanded?: boolean\n}\n\n/**\n * SubagentBlock - Hierarchical embedded subagent display\n *\n * Visual format (indent=1):\n * ```\n * \uD83E\uDD16 Launching subagent: backend-architect\n * \u251C\u2500 Task: Design authentication system\n * \u2502\n * \u2502 \uD83E\uDD14 Analyzing requirements... (300ms)\n * \u2502\n * \u2502 \uD83D\uDD27 Tool: Read package.json\n * \u2502 \u2514\u2500 \u2713 Read 50 lines (80ms)\n * \u2502\n * \u2502 \uD83D\uDCAC I recommend using JWT...\n * \u2502\n * \u2514\u2500 \u2713 Completed (2.5s, 1200 tokens)\n * ```\n */\nexport function SubagentBlock({\n subagent,\n indent = 0,\n isExpanded = false,\n}: Props): React.ReactNode {\n const theme = getTheme()\n const [expanded, setExpanded] = useState(isExpanded)\n const marginLeft = indent * 2\n\n // Get real-time token stats from unified TokenStatsManager\n const tokenStats = useAgentTokenStats(subagent.id)\n\n // Extract todos if present (from subagent execution)\n const todos = extractSubagentTodos(subagent)\n const thinking = extractThinkingMessage(subagent)\n const toolExecutions = extractToolExecutions(subagent)\n const response = extractResponse(subagent)\n\n // Calculate metrics\n const duration = subagent.metrics.endTime\n ? ((subagent.metrics.endTime - subagent.metrics.startTime) / 1000).toFixed(\n 1,\n )\n : '...'\n // Use token stats from TokenStatsManager (single source of truth)\n const tokenCount = tokenStats?.grandTotalTokens ?? 0\n\n // Status indicator\n const statusIndicator = getStatusIndicator(subagent.status)\n const statusColor = getStatusColor(subagent.status, theme)\n\n return (\n <Box flexDirection=\"column\" marginLeft={marginLeft} marginTop={1}>\n {/* Subagent Header */}\n <Box flexDirection=\"row\">\n <Text color={theme.brand}>\uD83E\uDD16 </Text>\n <Text>\n Launching subagent: <Text bold>{subagent.agentType}</Text>\n </Text>\n </Box>\n\n {/* Task description */}\n <Box flexDirection=\"row\" marginLeft={2}>\n <Text color={theme.dimmedText}>\u251C\u2500 </Text>\n <Text>Task: {subagent.taskName}</Text>\n </Box>\n\n {/* Collapsible internal content */}\n {expanded && (\n <Box flexDirection=\"column\" marginLeft={2}>\n <Text color={theme.dimmedText}>\u2502</Text>\n\n {/* Subagent subtasks (if present) */}\n {todos && todos.length > 0 && (\n <SubagentTodosSection todos={todos} theme={theme} />\n )}\n\n {/* Subagent thinking */}\n {thinking && (\n <Box flexDirection=\"column\" marginLeft={1}>\n <Text color={theme.dimmedText}>\u2502 </Text>\n <AgentThinkingBlock\n message={thinking.message}\n startTime={thinking.startTime}\n showSpinner={subagent.status === 'running'}\n showElapsedTime={false}\n />\n </Box>\n )}\n\n {/* Subagent tool executions */}\n {toolExecutions.map((tool, idx) => (\n <Box key={idx} flexDirection=\"column\" marginLeft={1}>\n <Text color={theme.dimmedText}>\u2502 </Text>\n <ToolExecutionBlock tool={tool} indent={0} />\n </Box>\n ))}\n\n {/* Subagent response */}\n {response && (\n <Box flexDirection=\"column\" marginLeft={1}>\n <Text color={theme.dimmedText}>\u2502 </Text>\n <AgentResponseBlock\n message={response}\n indent={0}\n isSubagent={true}\n />\n </Box>\n )}\n\n <Text color={theme.dimmedText}>\u2502</Text>\n </Box>\n )}\n\n {/* Subagent Footer (completion status) */}\n <Box flexDirection=\"row\" marginLeft={2}>\n <Text color={theme.dimmedText}>\u2514\u2500 </Text>\n <Text color={statusColor}>\n {statusIndicator} {getStatusLabel(subagent.status)}\n </Text>\n {subagent.status === 'completed' && (\n <Text color={theme.mutedText}>\n {' '}\n ({duration}s, {formatTokenCount(tokenCount)} tokens)\n </Text>\n )}\n </Box>\n\n {/* Expand/collapse hint (only when collapsed) */}\n {!expanded && (\n <Box flexDirection=\"row\" marginLeft={4}>\n <Text color={theme.mutedText}>\n Press <Text bold>Ctrl+O</Text> to expand details\n </Text>\n </Box>\n )}\n </Box>\n )\n}\n\n/**\n * SubagentTodosSection - Renders subagent's subtasks\n */\nfunction SubagentTodosSection({\n todos,\n theme,\n}: {\n todos: TodoItem[]\n theme: ReturnType<typeof getTheme>\n}) {\n return (\n <Box flexDirection=\"column\" marginLeft={1} marginY={1}>\n <Box flexDirection=\"row\">\n <Text color={theme.dimmedText}>\u2502 </Text>\n <Text color={theme.dimmedText}>Subtasks:</Text>\n </Box>\n {todos.map((todo, idx) => (\n <Box key={idx} flexDirection=\"row\" marginLeft={1}>\n <Text color={theme.dimmedText}>\u2502 </Text>\n <Text>{getTodoStatusSymbol(todo.status)} </Text>\n <Text\n color={todo.status === 'completed' ? theme.dim : undefined}\n strikethrough={todo.status === 'completed'}\n >\n {todo.content}\n </Text>\n </Box>\n ))}\n </Box>\n )\n}\n\n/**\n * Helper: Extract todos from subagent messages\n * (This would be populated from TodoWriteTool calls within the subagent)\n */\nfunction extractSubagentTodos(subagent: SubagentState): TodoItem[] | null {\n // Extract todos from TodoWrite tool_use blocks in subagent messages\n let latestTodos: TodoItem[] | null = null\n\n for (const msg of subagent.messages) {\n if (msg.type === 'assistant' && 'message' in msg) {\n const todoBlocks = msg.message.content.filter(\n (block: any) => block.type === 'tool_use' && block.name === 'TodoWrite',\n )\n for (const block of todoBlocks) {\n if ('input' in block && block.input?.todos) {\n // Each TodoWrite call replaces the full list\n latestTodos = (block.input.todos as any[]).map((t, i) => ({\n id: t.id ?? String(i),\n content: t.content ?? '',\n status: t.status ?? 'pending',\n priority: t.priority ?? 'medium',\n }))\n }\n }\n }\n }\n\n return latestTodos\n}\n\n/**\n * Helper: Extract thinking message from subagent\n */\nfunction extractThinkingMessage(\n subagent: SubagentState,\n): { message: string; startTime: number } | null {\n // Find thinking blocks in messages\n for (const msg of subagent.messages) {\n if (msg.type === 'assistant' && 'message' in msg) {\n const thinkingBlock = msg.message.content.find(\n (block: any) => block.type === 'thinking',\n )\n if (thinkingBlock && 'thinking' in thinkingBlock) {\n return {\n message: thinkingBlock.thinking || 'Thinking...',\n startTime: subagent.metrics.startTime,\n }\n }\n }\n }\n return null\n}\n\n/**\n * Helper: Extract tool executions from subagent\n */\nfunction extractToolExecutions(subagent: SubagentState): Array<{\n id: string\n name: string\n input: any\n status: 'pending' | 'running' | 'completed' | 'error'\n startTime: number\n durationMs?: number\n}> {\n const tools: Array<any> = []\n\n // Extract tool_use blocks from messages, pair with tool_result for duration\n const toolResultTimes = new Map<string, number>()\n let msgIndex = 0\n\n for (const msg of subagent.messages) {\n if (msg.type === 'user' && 'message' in msg) {\n const resultBlocks = (\n Array.isArray(msg.message.content) ? msg.message.content : []\n ).filter((block: any) => block.type === 'tool_result')\n for (const rb of resultBlocks) {\n if ('tool_use_id' in rb) {\n toolResultTimes.set(rb.tool_use_id as string, msgIndex)\n }\n }\n }\n msgIndex++\n }\n\n let toolIndex = 0\n for (const msg of subagent.messages) {\n if (msg.type === 'assistant' && 'message' in msg) {\n const toolBlocks = msg.message.content.filter(\n (block: any) => block.type === 'tool_use',\n )\n for (const toolBlock of toolBlocks) {\n if ('name' in toolBlock && 'id' in toolBlock) {\n // Estimate duration: spread evenly across total subagent time\n const totalDuration =\n (subagent.metrics.endTime || Date.now()) -\n subagent.metrics.startTime\n const toolCount = subagent.metrics.toolUseCount || tools.length + 1\n const estimatedDuration = Math.max(\n 1,\n Math.round(totalDuration / toolCount),\n )\n\n tools.push({\n id: toolBlock.id,\n name: toolBlock.name,\n input: toolBlock.input,\n status: toolResultTimes.has(toolBlock.id) ? 'completed' : 'running',\n startTime:\n subagent.metrics.startTime + toolIndex * estimatedDuration,\n durationMs: estimatedDuration,\n })\n toolIndex++\n }\n }\n }\n }\n\n return tools\n}\n\n/**\n * Helper: Extract response message from subagent\n */\nfunction extractResponse(subagent: SubagentState): AssistantMessage | null {\n // Find last assistant message with text content\n for (let i = subagent.messages.length - 1; i >= 0; i--) {\n const msg = subagent.messages[i]\n if (msg.type === 'assistant' && 'message' in msg) {\n const hasText = msg.message.content.some(\n (block: any) => block.type === 'text' && block.text.trim(),\n )\n if (hasText) {\n return msg as AssistantMessage\n }\n }\n }\n return null\n}\n\n/**\n * Helper: Get status indicator symbol\n */\nfunction getStatusIndicator(status: SubagentState['status']): string {\n switch (status) {\n case 'initializing':\n return '\u25CB'\n case 'queued':\n return '\u2139'\n case 'running':\n return '\u22EF'\n case 'completed':\n return '\u2713'\n case 'error':\n return '\u2716'\n }\n}\n\n/**\n * Helper: Get status color\n */\nfunction getStatusColor(\n status: SubagentState['status'],\n theme: ReturnType<typeof getTheme>,\n): string {\n switch (status) {\n case 'completed':\n return theme.success\n case 'error':\n return theme.error\n case 'running':\n return theme.brand\n default:\n return theme.dimmedText\n }\n}\n\n/**\n * Helper: Get status label\n */\nfunction getStatusLabel(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"],
5
- "mappings": "AAcA,OAAO,SAAS,gBAAgB;AAChC,SAAS,KAAK,YAAY;AAC1B,SAAS,gBAAgB;AACzB,SAAkB,2BAA2B;AAC7C,SAAS,0BAA0B;AACnC,SAAS,0BAA0B;AACnC,SAAS,0BAA0B;AACnC,SAAS,oBAAoB,wBAAwB;AA8B9C,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA,SAAS;AAAA,EACT,aAAa;AACf,GAA2B;AACzB,QAAM,QAAQ,SAAS;AACvB,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,UAAU;AACnD,QAAM,aAAa,SAAS;AAG5B,QAAM,aAAa,mBAAmB,SAAS,EAAE;AAGjD,QAAM,QAAQ,qBAAqB,QAAQ;AAC3C,QAAM,WAAW,uBAAuB,QAAQ;AAChD,QAAM,iBAAiB,sBAAsB,QAAQ;AACrD,QAAM,WAAW,gBAAgB,QAAQ;AAGzC,QAAM,WAAW,SAAS,QAAQ,YAC5B,SAAS,QAAQ,UAAU,SAAS,QAAQ,aAAa,KAAM;AAAA,IAC/D;AAAA,EACF,IACA;AAEJ,QAAM,aAAa,YAAY,oBAAoB;AAGnD,QAAM,kBAAkB,mBAAmB,SAAS,MAAM;AAC1D,QAAM,cAAc,eAAe,SAAS,QAAQ,KAAK;AAEzD,SACE,oCAAC,OAAI,eAAc,UAAS,YAAwB,WAAW,KAE7D,oCAAC,OAAI,eAAc,SACjB,oCAAC,QAAK,OAAO,MAAM,SAAO,YAAG,GAC7B,oCAAC,YAAK,wBACgB,oCAAC,QAAK,MAAI,QAAE,SAAS,SAAU,CACrD,CACF,GAGA,oCAAC,OAAI,eAAc,OAAM,YAAY,KACnC,oCAAC,QAAK,OAAO,MAAM,cAAY,eAAG,GAClC,oCAAC,YAAK,UAAO,SAAS,QAAS,CACjC,GAGC,YACC,oCAAC,OAAI,eAAc,UAAS,YAAY,KACtC,oCAAC,QAAK,OAAO,MAAM,cAAY,QAAC,GAG/B,SAAS,MAAM,SAAS,KACvB,oCAAC,wBAAqB,OAAc,OAAc,GAInD,YACC,oCAAC,OAAI,eAAc,UAAS,YAAY,KACtC,oCAAC,QAAK,OAAO,MAAM,cAAY,SAAE,GACjC;AAAA,IAAC;AAAA;AAAA,MACC,SAAS,SAAS;AAAA,MAClB,WAAW,SAAS;AAAA,MACpB,aAAa,SAAS,WAAW;AAAA,MACjC,iBAAiB;AAAA;AAAA,EACnB,CACF,GAID,eAAe,IAAI,CAAC,MAAM,QACzB,oCAAC,OAAI,KAAK,KAAK,eAAc,UAAS,YAAY,KAChD,oCAAC,QAAK,OAAO,MAAM,cAAY,SAAE,GACjC,oCAAC,sBAAmB,MAAY,QAAQ,GAAG,CAC7C,CACD,GAGA,YACC,oCAAC,OAAI,eAAc,UAAS,YAAY,KACtC,oCAAC,QAAK,OAAO,MAAM,cAAY,SAAE,GACjC;AAAA,IAAC;AAAA;AAAA,MACC,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,YAAY;AAAA;AAAA,EACd,CACF,GAGF,oCAAC,QAAK,OAAO,MAAM,cAAY,QAAC,CAClC,GAIF,oCAAC,OAAI,eAAc,OAAM,YAAY,KACnC,oCAAC,QAAK,OAAO,MAAM,cAAY,eAAG,GAClC,oCAAC,QAAK,OAAO,eACV,iBAAgB,KAAE,eAAe,SAAS,MAAM,CACnD,GACC,SAAS,WAAW,eACnB,oCAAC,QAAK,OAAO,MAAM,aAChB,KAAI,KACH,UAAS,OAAI,iBAAiB,UAAU,GAAE,UAC9C,CAEJ,GAGC,CAAC,YACA,oCAAC,OAAI,eAAc,OAAM,YAAY,KACnC,oCAAC,QAAK,OAAO,MAAM,aAAW,UACtB,oCAAC,QAAK,MAAI,QAAC,QAAM,GAAO,oBAChC,CACF,CAEJ;AAEJ;AAKA,SAAS,qBAAqB;AAAA,EAC5B;AAAA,EACA;AACF,GAGG;AACD,SACE,oCAAC,OAAI,eAAc,UAAS,YAAY,GAAG,SAAS,KAClD,oCAAC,OAAI,eAAc,SACjB,oCAAC,QAAK,OAAO,MAAM,cAAY,SAAE,GACjC,oCAAC,QAAK,OAAO,MAAM,cAAY,WAAS,CAC1C,GACC,MAAM,IAAI,CAAC,MAAM,QAChB,oCAAC,OAAI,KAAK,KAAK,eAAc,OAAM,YAAY,KAC7C,oCAAC,QAAK,OAAO,MAAM,cAAY,SAAE,GACjC,oCAAC,YAAM,oBAAoB,KAAK,MAAM,GAAE,GAAC,GACzC;AAAA,IAAC;AAAA;AAAA,MACC,OAAO,KAAK,WAAW,cAAc,MAAM,MAAM;AAAA,MACjD,eAAe,KAAK,WAAW;AAAA;AAAA,IAE9B,KAAK;AAAA,EACR,CACF,CACD,CACH;AAEJ;AAMA,SAAS,qBAAqB,UAA4C;AAExE,MAAI,cAAiC;AAErC,aAAW,OAAO,SAAS,UAAU;AACnC,QAAI,IAAI,SAAS,eAAe,aAAa,KAAK;AAChD,YAAM,aAAa,IAAI,QAAQ,QAAQ;AAAA,QACrC,CAAC,UAAe,MAAM,SAAS,cAAc,MAAM,SAAS;AAAA,MAC9D;AACA,iBAAW,SAAS,YAAY;AAC9B,YAAI,WAAW,SAAS,MAAM,OAAO,OAAO;AAE1C,wBAAe,MAAM,MAAM,MAAgB,IAAI,CAAC,GAAG,OAAO;AAAA,YACxD,IAAI,EAAE,MAAM,OAAO,CAAC;AAAA,YACpB,SAAS,EAAE,WAAW;AAAA,YACtB,QAAQ,EAAE,UAAU;AAAA,YACpB,UAAU,EAAE,YAAY;AAAA,UAC1B,EAAE;AAAA,QACJ;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAKA,SAAS,uBACP,UAC+C;AAE/C,aAAW,OAAO,SAAS,UAAU;AACnC,QAAI,IAAI,SAAS,eAAe,aAAa,KAAK;AAChD,YAAM,gBAAgB,IAAI,QAAQ,QAAQ;AAAA,QACxC,CAAC,UAAe,MAAM,SAAS;AAAA,MACjC;AACA,UAAI,iBAAiB,cAAc,eAAe;AAChD,eAAO;AAAA,UACL,SAAS,cAAc,YAAY;AAAA,UACnC,WAAW,SAAS,QAAQ;AAAA,QAC9B;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAKA,SAAS,sBAAsB,UAO5B;AACD,QAAM,QAAoB,CAAC;AAG3B,QAAM,kBAAkB,oBAAI,IAAoB;AAChD,MAAI,WAAW;AAEf,aAAW,OAAO,SAAS,UAAU;AACnC,QAAI,IAAI,SAAS,UAAU,aAAa,KAAK;AAC3C,YAAM,gBACJ,MAAM,QAAQ,IAAI,QAAQ,OAAO,IAAI,IAAI,QAAQ,UAAU,CAAC,GAC5D,OAAO,CAAC,UAAe,MAAM,SAAS,aAAa;AACrD,iBAAW,MAAM,cAAc;AAC7B,YAAI,iBAAiB,IAAI;AACvB,0BAAgB,IAAI,GAAG,aAAuB,QAAQ;AAAA,QACxD;AAAA,MACF;AAAA,IACF;AACA;AAAA,EACF;AAEA,MAAI,YAAY;AAChB,aAAW,OAAO,SAAS,UAAU;AACnC,QAAI,IAAI,SAAS,eAAe,aAAa,KAAK;AAChD,YAAM,aAAa,IAAI,QAAQ,QAAQ;AAAA,QACrC,CAAC,UAAe,MAAM,SAAS;AAAA,MACjC;AACA,iBAAW,aAAa,YAAY;AAClC,YAAI,UAAU,aAAa,QAAQ,WAAW;AAE5C,gBAAM,iBACH,SAAS,QAAQ,WAAW,KAAK,IAAI,KACtC,SAAS,QAAQ;AACnB,gBAAM,YAAY,SAAS,QAAQ,gBAAgB,MAAM,SAAS;AAClE,gBAAM,oBAAoB,KAAK;AAAA,YAC7B;AAAA,YACA,KAAK,MAAM,gBAAgB,SAAS;AAAA,UACtC;AAEA,gBAAM,KAAK;AAAA,YACT,IAAI,UAAU;AAAA,YACd,MAAM,UAAU;AAAA,YAChB,OAAO,UAAU;AAAA,YACjB,QAAQ,gBAAgB,IAAI,UAAU,EAAE,IAAI,cAAc;AAAA,YAC1D,WACE,SAAS,QAAQ,YAAY,YAAY;AAAA,YAC3C,YAAY;AAAA,UACd,CAAC;AACD;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAKA,SAAS,gBAAgB,UAAkD;AAEzE,WAAS,IAAI,SAAS,SAAS,SAAS,GAAG,KAAK,GAAG,KAAK;AACtD,UAAM,MAAM,SAAS,SAAS,CAAC;AAC/B,QAAI,IAAI,SAAS,eAAe,aAAa,KAAK;AAChD,YAAM,UAAU,IAAI,QAAQ,QAAQ;AAAA,QAClC,CAAC,UAAe,MAAM,SAAS,UAAU,MAAM,KAAK,KAAK;AAAA,MAC3D;AACA,UAAI,SAAS;AACX,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAKA,SAAS,mBAAmB,QAAyC;AACnE,UAAQ,QAAQ;AAAA,IACd,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,EACX;AACF;AAKA,SAAS,eACP,QACA,OACQ;AACR,UAAQ,QAAQ;AAAA,IACd,KAAK;AACH,aAAO,MAAM;AAAA,IACf,KAAK;AACH,aAAO,MAAM;AAAA,IACf,KAAK;AACH,aAAO,MAAM;AAAA,IACf;AACE,aAAO,MAAM;AAAA,EACjB;AACF;AAKA,SAAS,eAAe,QAAyC;AAC/D,UAAQ,QAAQ;AAAA,IACd,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,EACX;AACF;",
4
+ "sourcesContent": ["/**\n * SubagentBlock - Embedded subagent execution display\n *\n * Renders a complete subagent execution hierarchically with:\n * - Header (task name, agent type, status)\n * - Optional: Subtasks (if subagent has todos)\n * - Optional: Thinking phase\n * - Optional: Tool executions\n * - Optional: Response\n * - Footer (completion status)\n *\n * Supports collapsible internal content\n */\n\nimport React, { useState } from 'react'\nimport { Box, Text } from 'ink'\nimport { getTheme } from '@utils/theme'\nimport { formatNumber } from '@utils/format'\nimport { SYMBOLS, getTodoStatusSymbol } from '@constants/symbols'\nimport { AgentThinkingBlock } from './AgentThinkingBlock'\nimport { ToolExecutionBlock } from './ToolExecutionBlock'\nimport { AgentResponseBlock } from './AgentResponseBlock'\nimport { useAgentTokenStats } from '@hooks/useAgentTokenStats'\nimport type { SubagentState } from '@minto-types/subagent'\nimport type { TodoItem } from '@utils/todoStorage'\nimport type { AssistantMessage } from '@minto-types/conversation'\nimport type { TextBlockParam } from '@anthropic-ai/sdk/resources/index.mjs'\n\ninterface Props {\n subagent: SubagentState\n indent?: number\n isExpanded?: boolean\n}\n\n/**\n * SubagentBlock - Hierarchical embedded subagent display\n *\n * Visual format (indent=1):\n * ```\n * \uD83E\uDD16 Launching subagent: backend-architect\n * \u251C\u2500 Task: Design authentication system\n * \u2502\n * \u2502 \uD83E\uDD14 Analyzing requirements... (300ms)\n * \u2502\n * \u2502 \uD83D\uDD27 Tool: Read package.json\n * \u2502 \u2514\u2500 \u2713 Read 50 lines (80ms)\n * \u2502\n * \u2502 \uD83D\uDCAC I recommend using JWT...\n * \u2502\n * \u2514\u2500 \u2713 Completed (2.5s, 1200 tokens)\n * ```\n */\nexport function SubagentBlock({\n subagent,\n indent = 0,\n isExpanded = false,\n}: Props): React.ReactNode {\n const theme = getTheme()\n const [expanded, setExpanded] = useState(isExpanded)\n const marginLeft = indent * 2\n\n // Get real-time token stats from unified TokenStatsManager\n const tokenStats = useAgentTokenStats(subagent.id)\n\n // Extract todos if present (from subagent execution)\n const todos = extractSubagentTodos(subagent)\n const thinking = extractThinkingMessage(subagent)\n const toolExecutions = extractToolExecutions(subagent)\n const response = extractResponse(subagent)\n\n // Calculate metrics\n const duration = subagent.metrics.endTime\n ? ((subagent.metrics.endTime - subagent.metrics.startTime) / 1000).toFixed(\n 1,\n )\n : '...'\n // Use token stats from TokenStatsManager (single source of truth)\n const tokenCount = tokenStats?.grandTotalTokens ?? 0\n\n // Status indicator\n const statusIndicator = getStatusIndicator(subagent.status)\n const statusColor = getStatusColor(subagent.status, theme)\n\n return (\n <Box flexDirection=\"column\" marginLeft={marginLeft} marginTop={1}>\n {/* Subagent Header */}\n <Box flexDirection=\"row\">\n <Text color={theme.brand}>\uD83E\uDD16 </Text>\n <Text>\n Launching subagent: <Text bold>{subagent.agentType}</Text>\n </Text>\n </Box>\n\n {/* Task description */}\n <Box flexDirection=\"row\" marginLeft={2}>\n <Text color={theme.dimmedText}>\u251C\u2500 </Text>\n <Text>Task: {subagent.taskName}</Text>\n </Box>\n\n {/* Collapsible internal content */}\n {expanded && (\n <Box flexDirection=\"column\" marginLeft={2}>\n <Text color={theme.dimmedText}>\u2502</Text>\n\n {/* Subagent subtasks (if present) */}\n {todos && todos.length > 0 && (\n <SubagentTodosSection todos={todos} theme={theme} />\n )}\n\n {/* Subagent thinking */}\n {thinking && (\n <Box flexDirection=\"column\" marginLeft={1}>\n <Text color={theme.dimmedText}>\u2502 </Text>\n <AgentThinkingBlock\n message={thinking.message}\n startTime={thinking.startTime}\n showSpinner={subagent.status === 'running'}\n showElapsedTime={false}\n />\n </Box>\n )}\n\n {/* Subagent tool executions */}\n {toolExecutions.map((tool, idx) => (\n <Box key={idx} flexDirection=\"column\" marginLeft={1}>\n <Text color={theme.dimmedText}>\u2502 </Text>\n <ToolExecutionBlock tool={tool} indent={0} />\n </Box>\n ))}\n\n {/* Subagent response */}\n {response && (\n <Box flexDirection=\"column\" marginLeft={1}>\n <Text color={theme.dimmedText}>\u2502 </Text>\n <AgentResponseBlock\n message={response}\n indent={0}\n isSubagent={true}\n />\n </Box>\n )}\n\n <Text color={theme.dimmedText}>\u2502</Text>\n </Box>\n )}\n\n {/* Subagent Footer (completion status) */}\n <Box flexDirection=\"row\" marginLeft={2}>\n <Text color={theme.dimmedText}>\u2514\u2500 </Text>\n <Text color={statusColor}>\n {statusIndicator} {getStatusLabel(subagent.status)}\n </Text>\n {subagent.status === 'completed' && (\n <Text color={theme.mutedText}>\n {' '}\n ({duration}s, {formatNumber(tokenCount)} tokens)\n </Text>\n )}\n </Box>\n\n {/* Expand/collapse hint (only when collapsed) */}\n {!expanded && (\n <Box flexDirection=\"row\" marginLeft={4}>\n <Text color={theme.mutedText}>\n Press <Text bold>Ctrl+O</Text> to expand details\n </Text>\n </Box>\n )}\n </Box>\n )\n}\n\n/**\n * SubagentTodosSection - Renders subagent's subtasks\n */\nfunction SubagentTodosSection({\n todos,\n theme,\n}: {\n todos: TodoItem[]\n theme: ReturnType<typeof getTheme>\n}) {\n return (\n <Box flexDirection=\"column\" marginLeft={1} marginY={1}>\n <Box flexDirection=\"row\">\n <Text color={theme.dimmedText}>\u2502 </Text>\n <Text color={theme.dimmedText}>Subtasks:</Text>\n </Box>\n {todos.map((todo, idx) => (\n <Box key={idx} flexDirection=\"row\" marginLeft={1}>\n <Text color={theme.dimmedText}>\u2502 </Text>\n <Text>{getTodoStatusSymbol(todo.status)} </Text>\n <Text\n color={todo.status === 'completed' ? theme.dim : undefined}\n strikethrough={todo.status === 'completed'}\n >\n {todo.content}\n </Text>\n </Box>\n ))}\n </Box>\n )\n}\n\n/**\n * Helper: Extract todos from subagent messages\n * (This would be populated from TodoWriteTool calls within the subagent)\n */\nfunction extractSubagentTodos(subagent: SubagentState): TodoItem[] | null {\n // Extract todos from TodoWrite tool_use blocks in subagent messages\n let latestTodos: TodoItem[] | null = null\n\n for (const msg of subagent.messages) {\n if (msg.type === 'assistant' && 'message' in msg) {\n const todoBlocks = msg.message.content.filter(\n (block: any) => block.type === 'tool_use' && block.name === 'TodoWrite',\n )\n for (const block of todoBlocks) {\n if ('input' in block && block.input?.todos) {\n // Each TodoWrite call replaces the full list\n latestTodos = (block.input.todos as any[]).map((t, i) => ({\n id: t.id ?? String(i),\n content: t.content ?? '',\n status: t.status ?? 'pending',\n priority: t.priority ?? 'medium',\n }))\n }\n }\n }\n }\n\n return latestTodos\n}\n\n/**\n * Helper: Extract thinking message from subagent\n */\nfunction extractThinkingMessage(\n subagent: SubagentState,\n): { message: string; startTime: number } | null {\n // Find thinking blocks in messages\n for (const msg of subagent.messages) {\n if (msg.type === 'assistant' && 'message' in msg) {\n const thinkingBlock = msg.message.content.find(\n (block: any) => block.type === 'thinking',\n )\n if (thinkingBlock && 'thinking' in thinkingBlock) {\n return {\n message: thinkingBlock.thinking || 'Thinking...',\n startTime: subagent.metrics.startTime,\n }\n }\n }\n }\n return null\n}\n\n/**\n * Helper: Extract tool executions from subagent\n */\nfunction extractToolExecutions(subagent: SubagentState): Array<{\n id: string\n name: string\n input: any\n status: 'pending' | 'running' | 'completed' | 'error'\n startTime: number\n durationMs?: number\n}> {\n const tools: Array<any> = []\n\n // Extract tool_use blocks from messages, pair with tool_result for duration\n const toolResultTimes = new Map<string, number>()\n let msgIndex = 0\n\n for (const msg of subagent.messages) {\n if (msg.type === 'user' && 'message' in msg) {\n const resultBlocks = (\n Array.isArray(msg.message.content) ? msg.message.content : []\n ).filter((block: any) => block.type === 'tool_result')\n for (const rb of resultBlocks) {\n if ('tool_use_id' in rb) {\n toolResultTimes.set(rb.tool_use_id as string, msgIndex)\n }\n }\n }\n msgIndex++\n }\n\n let toolIndex = 0\n for (const msg of subagent.messages) {\n if (msg.type === 'assistant' && 'message' in msg) {\n const toolBlocks = msg.message.content.filter(\n (block: any) => block.type === 'tool_use',\n )\n for (const toolBlock of toolBlocks) {\n if ('name' in toolBlock && 'id' in toolBlock) {\n // Estimate duration: spread evenly across total subagent time\n const totalDuration =\n (subagent.metrics.endTime || Date.now()) -\n subagent.metrics.startTime\n const toolCount = subagent.metrics.toolUseCount || tools.length + 1\n const estimatedDuration = Math.max(\n 1,\n Math.round(totalDuration / toolCount),\n )\n\n tools.push({\n id: toolBlock.id,\n name: toolBlock.name,\n input: toolBlock.input,\n status: toolResultTimes.has(toolBlock.id) ? 'completed' : 'running',\n startTime:\n subagent.metrics.startTime + toolIndex * estimatedDuration,\n durationMs: estimatedDuration,\n })\n toolIndex++\n }\n }\n }\n }\n\n return tools\n}\n\n/**\n * Helper: Extract response message from subagent\n */\nfunction extractResponse(subagent: SubagentState): AssistantMessage | null {\n // Find last assistant message with text content\n for (let i = subagent.messages.length - 1; i >= 0; i--) {\n const msg = subagent.messages[i]\n if (msg.type === 'assistant' && 'message' in msg) {\n const hasText = msg.message.content.some(\n (block: any) => block.type === 'text' && block.text.trim(),\n )\n if (hasText) {\n return msg as AssistantMessage\n }\n }\n }\n return null\n}\n\n/**\n * Helper: Get status indicator symbol\n */\nfunction getStatusIndicator(status: SubagentState['status']): string {\n switch (status) {\n case 'initializing':\n return '\u25CB'\n case 'queued':\n return '\u2139'\n case 'running':\n return '\u22EF'\n case 'completed':\n return '\u2713'\n case 'error':\n return '\u2716'\n }\n}\n\n/**\n * Helper: Get status color\n */\nfunction getStatusColor(\n status: SubagentState['status'],\n theme: ReturnType<typeof getTheme>,\n): string {\n switch (status) {\n case 'completed':\n return theme.success\n case 'error':\n return theme.error\n case 'running':\n return theme.brand\n default:\n return theme.dimmedText\n }\n}\n\n/**\n * Helper: Get status label\n */\nfunction getStatusLabel(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"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,12 +1,12 @@
1
1
  import React, { useRef } from "react";
2
2
  import { Box, Text } from "ink";
3
3
  import { getTheme } from "../utils/theme.js";
4
- import { formatDuration } from "../utils/format.js";
4
+ import { formatNumber, formatDuration } from "../utils/format.js";
5
5
  import { getAgentColor } from "../constants/colors.js";
6
6
  import { SpinnerSymbol } from "./SpinnerSymbol.js";
7
7
  import { Message } from "./Message.js";
8
8
  import { useUnifiedAnimation } from "../utils/animationManager.js";
9
- import { useAgentTokenStats, formatTokenCount } from "../hooks/useAgentTokenStats.js";
9
+ import { useAgentTokenStats } from "../hooks/useAgentTokenStats.js";
10
10
  function SubagentProgress({
11
11
  subagent,
12
12
  isExpanded,
@@ -29,7 +29,7 @@ function SubagentProgress({
29
29
  });
30
30
  const duration = metrics.endTime ? metrics.endTime - metrics.startTime : Date.now() - metrics.startTime;
31
31
  const statusText = getStatusText(status);
32
- return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", marginY: 0 }, /* @__PURE__ */ React.createElement(Box, { flexDirection: "row" }, /* @__PURE__ */ React.createElement(SpinnerSymbol, { isRunning, color: agentColor }), /* @__PURE__ */ React.createElement(Text, null, " Task(", taskName, ")")), /* @__PURE__ */ React.createElement(Box, { flexDirection: "row" }, /* @__PURE__ */ React.createElement(Text, { color: theme.dim }, " \u23BFS1 "), /* @__PURE__ */ React.createElement(Text, { color: getStatusColor(status, theme) }, statusText), /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, " \xB7 "), /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, metrics.toolUseCount, " tool use", metrics.toolUseCount !== 1 ? "s" : ""), /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, " \xB7 "), /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, formatTokenCount(tokenCount), " tokens"), /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, " \xB7 "), /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, formatDuration(duration)), !isExpanded && /* @__PURE__ */ React.createElement(Text, { color: theme.dim }, " \xB7 (ctrl-o to expand)")), isExpanded && /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", marginTop: 0 }, renderExpandedView(subagent, theme, tools, verbose, tokenCount)));
32
+ return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", marginY: 0 }, /* @__PURE__ */ React.createElement(Box, { flexDirection: "row" }, /* @__PURE__ */ React.createElement(SpinnerSymbol, { isRunning, color: agentColor }), /* @__PURE__ */ React.createElement(Text, null, " Task(", taskName, ")")), /* @__PURE__ */ React.createElement(Box, { flexDirection: "row" }, /* @__PURE__ */ React.createElement(Text, { color: theme.dim }, " \u23BFS1 "), /* @__PURE__ */ React.createElement(Text, { color: getStatusColor(status, theme) }, statusText), /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, " \xB7 "), /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, metrics.toolUseCount, " tool use", metrics.toolUseCount !== 1 ? "s" : ""), /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, " \xB7 "), /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, formatNumber(tokenCount), " tokens"), /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, " \xB7 "), /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, formatDuration(duration)), !isExpanded && /* @__PURE__ */ React.createElement(Text, { color: theme.dim }, " \xB7 (ctrl-o to expand)")), isExpanded && /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", marginTop: 0 }, renderExpandedView(subagent, theme, tools, verbose, tokenCount)));
33
33
  }
34
34
  function renderExpandedView(subagent, theme, tools, verbose, tokenCount) {
35
35
  const { prompt, messages, status, metrics } = subagent;
@@ -69,7 +69,7 @@ function renderExpandedView(subagent, theme, tools, verbose, tokenCount) {
69
69
  }).filter((item) => item !== null);
70
70
  }
71
71
  return null;
72
- }).flat().filter((item) => item !== null), status === "completed" && /* @__PURE__ */ React.createElement(Box, { flexDirection: "row" }, /* @__PURE__ */ React.createElement(Text, { color: theme.dim }, " \u23BFS6 "), /* @__PURE__ */ React.createElement(Text, { color: theme.success }, "Done"), /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, " ", "(", metrics.toolUseCount, " tool use", metrics.toolUseCount !== 1 ? "s" : "", " \xB7", " ", formatTokenCount(tokenCount), " tokens \xB7 ", formatDuration(duration), ")")));
72
+ }).flat().filter((item) => item !== null), status === "completed" && /* @__PURE__ */ React.createElement(Box, { flexDirection: "row" }, /* @__PURE__ */ React.createElement(Text, { color: theme.dim }, " \u23BFS6 "), /* @__PURE__ */ React.createElement(Text, { color: theme.success }, "Done"), /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, " ", "(", metrics.toolUseCount, " tool use", metrics.toolUseCount !== 1 ? "s" : "", " \xB7 ", formatNumber(tokenCount), " ", "tokens \xB7 ", formatDuration(duration), ")")));
73
73
  }
74
74
  function getStatusText(status) {
75
75
  switch (status) {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/components/SubagentProgress.tsx"],
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'\nimport { useAgentTokenStats, formatTokenCount } from '@hooks/useAgentTokenStats'\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 // Get real-time token stats from unified TokenStatsManager\n const tokenStats = useAgentTokenStats(subagent.id)\n const tokenCount = tokenStats?.grandTotalTokens ?? 0\n\n // \u83B7\u53D6 agent \u989C\u8272\n const color = getAgentColor(agentColor, theme)\n\n // \u5224\u65AD\u662F\u5426\u6B63\u5728\u8FD0\u884C\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 {formatTokenCount(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, tokenCount)}\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 tokenCount: number,\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 // Skip displaying raw JSON objects (e.g., tool data objects)\n // These look like { \"key\": \"value\", ... } and shouldn't be shown\n const trimmedContent = resultContent.trim()\n if (\n trimmedContent.startsWith('{') &&\n trimmedContent.endsWith('}')\n ) {\n try {\n // If it's valid JSON, skip it - it's internal tool data\n JSON.parse(trimmedContent)\n return null\n } catch {\n // Not valid JSON, show it\n }\n }\n\n const lines = trimmedContent.split('\\n')\n const preview =\n lines.length > 3\n ? lines.slice(0, 3).join('\\n') + '\\n...'\n : trimmedContent\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 {formatTokenCount(tokenCount)} tokens \u00B7 {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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",
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'\nimport { useAgentTokenStats } from '@hooks/useAgentTokenStats'\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 // Get real-time token stats from unified TokenStatsManager\n const tokenStats = useAgentTokenStats(subagent.id)\n const tokenCount = tokenStats?.grandTotalTokens ?? 0\n\n // \u83B7\u53D6 agent \u989C\u8272\n const color = getAgentColor(agentColor, theme)\n\n // \u5224\u65AD\u662F\u5426\u6B63\u5728\u8FD0\u884C\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(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, tokenCount)}\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 tokenCount: number,\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 // Skip displaying raw JSON objects (e.g., tool data objects)\n // These look like { \"key\": \"value\", ... } and shouldn't be shown\n const trimmedContent = resultContent.trim()\n if (\n trimmedContent.startsWith('{') &&\n trimmedContent.endsWith('}')\n ) {\n try {\n // If it's valid JSON, skip it - it's internal tool data\n JSON.parse(trimmedContent)\n return null\n } catch {\n // Not valid JSON, show it\n }\n }\n\n const lines = trimmedContent.split('\\n')\n const preview =\n lines.length > 3\n ? lines.slice(0, 3).join('\\n') + '\\n...'\n : trimmedContent\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 {formatNumber(tokenCount)}{' '}\n tokens \u00B7 {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
  }
@@ -8,7 +8,7 @@ function SearchInput({
8
8
  placeholder = "Search...",
9
9
  isActive
10
10
  }) {
11
- return /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { color: isActive ? BRAND_GRADIENT.START : SEMANTIC_COLORS.dim }, "/"), /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.dim }, " "), isActive ? /* @__PURE__ */ React.createElement(
11
+ return /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { color: isActive ? BRAND_GRADIENT.START : SEMANTIC_COLORS.dim }, "\u2315"), /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.dim }, " "), isActive ? /* @__PURE__ */ React.createElement(
12
12
  InkTextInput,
13
13
  {
14
14
  value,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/components/TabbedListView/SearchInput.tsx"],
4
- "sourcesContent": ["/**\n * SearchInput Component\n *\n * A styled search input with search icon.\n * Uses inline style matching the overall design.\n */\n\nimport React from 'react'\nimport { Box, Text } from 'ink'\nimport InkTextInput from 'ink-text-input'\nimport { BRAND_GRADIENT, SEMANTIC_COLORS } from '@constants/colors'\nimport type { SearchInputProps } from './types'\n\nexport function SearchInput({\n value,\n onChange,\n placeholder = 'Search...',\n isActive,\n}: SearchInputProps) {\n return (\n <Box>\n <Text color={isActive ? BRAND_GRADIENT.START : SEMANTIC_COLORS.dim}>\n /\n </Text>\n <Text color={SEMANTIC_COLORS.dim}> </Text>\n {isActive ? (\n <InkTextInput\n value={value}\n onChange={onChange}\n placeholder={placeholder}\n />\n ) : (\n <Text color={value ? SEMANTIC_COLORS.secondary : SEMANTIC_COLORS.dim}>\n {value || placeholder}\n </Text>\n )}\n </Box>\n )\n}\n"],
5
- "mappings": "AAOA,OAAO,WAAW;AAClB,SAAS,KAAK,YAAY;AAC1B,OAAO,kBAAkB;AACzB,SAAS,gBAAgB,uBAAuB;AAGzC,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd;AACF,GAAqB;AACnB,SACE,oCAAC,WACC,oCAAC,QAAK,OAAO,WAAW,eAAe,QAAQ,gBAAgB,OAAK,GAEpE,GACA,oCAAC,QAAK,OAAO,gBAAgB,OAAK,GAAC,GAClC,WACC;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA;AAAA,EACF,IAEA,oCAAC,QAAK,OAAO,QAAQ,gBAAgB,YAAY,gBAAgB,OAC9D,SAAS,WACZ,CAEJ;AAEJ;",
4
+ "sourcesContent": ["/**\n * SearchInput Component\n *\n * A styled search input with search icon.\n * Uses inline style matching the overall design.\n */\n\nimport React from 'react'\nimport { Box, Text } from 'ink'\nimport InkTextInput from 'ink-text-input'\nimport { BRAND_GRADIENT, SEMANTIC_COLORS } from '@constants/colors'\nimport type { SearchInputProps } from './types'\n\nexport function SearchInput({\n value,\n onChange,\n placeholder = 'Search...',\n isActive,\n}: SearchInputProps) {\n return (\n <Box>\n <Text color={isActive ? BRAND_GRADIENT.START : SEMANTIC_COLORS.dim}>\n \u2315\n </Text>\n <Text color={SEMANTIC_COLORS.dim}> </Text>\n {isActive ? (\n <InkTextInput\n value={value}\n onChange={onChange}\n placeholder={placeholder}\n />\n ) : (\n <Text color={value ? SEMANTIC_COLORS.secondary : SEMANTIC_COLORS.dim}>\n {value || placeholder}\n </Text>\n )}\n </Box>\n )\n}\n"],
5
+ "mappings": "AAOA,OAAO,WAAW;AAClB,SAAS,KAAK,YAAY;AAC1B,OAAO,kBAAkB;AACzB,SAAS,gBAAgB,uBAAuB;AAGzC,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd;AACF,GAAqB;AACnB,SACE,oCAAC,WACC,oCAAC,QAAK,OAAO,WAAW,eAAe,QAAQ,gBAAgB,OAAK,QAEpE,GACA,oCAAC,QAAK,OAAO,gBAAgB,OAAK,GAAC,GAClC,WACC;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA;AAAA,EACF,IAEA,oCAAC,QAAK,OAAO,QAAQ,gBAAgB,YAAY,gBAAgB,OAC9D,SAAS,WACZ,CAEJ;AAEJ;",
6
6
  "names": []
7
7
  }
@@ -8,7 +8,6 @@ import { SimpleSpinner } from "../Spinner.js";
8
8
  import { StatusOverlayContent } from "../StatusOverlayContent.js";
9
9
  import { useTerminalSize } from "../../hooks/useTerminalSize.js";
10
10
  const PROMPT_HEIGHT = 5;
11
- const CHROME_HEIGHT = 6;
12
11
  function TabbedListView({
13
12
  title,
14
13
  tabs,
@@ -32,6 +31,8 @@ function TabbedListView({
32
31
  statusOverlay,
33
32
  isActive = true,
34
33
  showItemCount = true,
34
+ showTabs,
35
+ showList,
35
36
  statusDismissHint,
36
37
  multiSelect,
37
38
  selectedIds,
@@ -40,13 +41,15 @@ function TabbedListView({
40
41
  multiSelectActionLabel
41
42
  }) {
42
43
  const { rows } = useTerminalSize();
44
+ const chromeHeight = 2 + // title + top border
45
+ (showTabs !== false ? 2 : 0) + // tab bar + margin
46
+ (searchEnabled ? 2 : 0) + // search + margin
47
+ 2;
43
48
  const visibleCount = Math.min(
44
49
  8,
45
- Math.max(3, rows - PROMPT_HEIGHT - CHROME_HEIGHT)
46
- );
47
- const [focusArea, setFocusArea] = useState(
48
- searchEnabled ? "search" : "list"
50
+ Math.max(3, rows - PROMPT_HEIGHT - chromeHeight)
49
51
  );
52
+ const [inputMode, setInputMode] = useState("normal");
50
53
  const [focusedIndex, setFocusedIndex] = useState(0);
51
54
  const filteredItems = useMemo(() => {
52
55
  if (!searchQuery.trim()) return items;
@@ -88,6 +91,37 @@ function TabbedListView({
88
91
  return;
89
92
  }
90
93
  if (statusOverlay) return;
94
+ if (inputMode === "search") {
95
+ if (key.escape) {
96
+ if (showList !== false) {
97
+ setInputMode("normal");
98
+ } else if (onBack) {
99
+ onBack();
100
+ } else {
101
+ onClose();
102
+ }
103
+ return;
104
+ }
105
+ if (key.downArrow && showList !== false) {
106
+ setInputMode("normal");
107
+ return;
108
+ }
109
+ if (key.return && onSearchSubmit) {
110
+ onSearchSubmit(searchQuery);
111
+ return;
112
+ }
113
+ if (showTabs !== false) {
114
+ if (key.leftArrow) {
115
+ cycleTab("left");
116
+ return;
117
+ }
118
+ if (key.rightArrow) {
119
+ cycleTab("right");
120
+ return;
121
+ }
122
+ }
123
+ return;
124
+ }
91
125
  if (key.escape) {
92
126
  if (onBack) {
93
127
  onBack();
@@ -96,11 +130,11 @@ function TabbedListView({
96
130
  }
97
131
  return;
98
132
  }
99
- if (key.tab) {
133
+ if (key.tab && showTabs !== false) {
100
134
  cycleTab(key.shift ? "left" : "right");
101
135
  return;
102
136
  }
103
- if (focusArea === "tabs" || focusArea === "search") {
137
+ if (showTabs !== false) {
104
138
  if (key.leftArrow) {
105
139
  cycleTab("left");
106
140
  return;
@@ -110,33 +144,21 @@ function TabbedListView({
110
144
  return;
111
145
  }
112
146
  }
113
- if (key.downArrow) {
114
- if (focusArea === "search") {
115
- setFocusArea("list");
116
- return;
117
- }
118
- if (focusArea === "list" && filteredItems.length > 0) {
119
- setFocusedIndex(
120
- (prev) => prev < filteredItems.length - 1 ? prev + 1 : prev
121
- );
122
- return;
123
- }
147
+ if (key.downArrow && showList !== false && filteredItems.length > 0) {
148
+ setFocusedIndex(
149
+ (prev) => prev < filteredItems.length - 1 ? prev + 1 : prev
150
+ );
151
+ return;
124
152
  }
125
- if (key.upArrow) {
126
- if (focusArea === "list") {
127
- if (focusedIndex > 0) {
128
- setFocusedIndex((prev) => prev - 1);
129
- } else if (searchEnabled) {
130
- setFocusArea("search");
131
- }
132
- return;
153
+ if (key.upArrow && showList !== false) {
154
+ if (focusedIndex > 0) {
155
+ setFocusedIndex((prev) => prev - 1);
156
+ } else if (searchEnabled) {
157
+ setInputMode("search");
133
158
  }
134
- }
135
- if (key.return && focusArea === "search" && onSearchSubmit) {
136
- onSearchSubmit(searchQuery);
137
159
  return;
138
160
  }
139
- if (input === " " && multiSelect && focusArea === "list" && filteredItems.length > 0) {
161
+ if (input === " " && multiSelect && showList !== false && filteredItems.length > 0) {
140
162
  const item = filteredItems[focusedIndex];
141
163
  if (item && onSelectionChange) {
142
164
  const isCurrentlySelected = selectedIds?.has(item.id) ?? false;
@@ -144,7 +166,7 @@ function TabbedListView({
144
166
  }
145
167
  return;
146
168
  }
147
- if (input === "a" && multiSelect && focusArea === "list" && filteredItems.length > 0) {
169
+ if (input === "a" && multiSelect && showList !== false && filteredItems.length > 0) {
148
170
  if (onSelectionChange) {
149
171
  const allSelected = filteredItems.every(
150
172
  (item) => selectedIds?.has(item.id)
@@ -155,7 +177,7 @@ function TabbedListView({
155
177
  }
156
178
  return;
157
179
  }
158
- if (key.return && focusArea === "list" && filteredItems.length > 0) {
180
+ if (key.return && showList !== false && filteredItems.length > 0) {
159
181
  if (multiSelect && selectedIds && selectedIds.size > 0 && onMultiSelect) {
160
182
  const selectedItems = filteredItems.filter(
161
183
  (item) => selectedIds.has(item.id)
@@ -165,19 +187,36 @@ function TabbedListView({
165
187
  return;
166
188
  }
167
189
  }
168
- handleSelect(filteredItems[focusedIndex]);
190
+ const selectedItem = filteredItems[Math.min(focusedIndex, filteredItems.length - 1)];
191
+ if (selectedItem) handleSelect(selectedItem);
169
192
  return;
170
193
  }
171
- if (input === "/" && searchEnabled && focusArea !== "search") {
172
- setFocusArea("search");
194
+ if (input === "/" && searchEnabled && inputMode !== "search") {
195
+ setInputMode("search");
173
196
  return;
174
197
  }
175
198
  },
176
199
  { isActive }
177
200
  );
178
- const defaultHint = "\u2191\u2193 Navigate \xB7 Enter Select \xB7 Tab/\u2190\u2192 Switch \xB7 Esc Close";
179
- const multiSelectHint = "\u2191\u2193 Navigate \xB7 Space Select \xB7 a All \xB7 Enter Action \xB7 Tab Switch \xB7 Esc Close";
180
- const displayHint = statusOverlay ? statusOverlay.type === "loading" ? "" : statusDismissHint || "Esc Close" : multiSelect ? selectedIds && selectedIds.size > 0 && multiSelectActionLabel ? `${multiSelectActionLabel} \xB7 ${footerHint || multiSelectHint}` : footerHint || multiSelectHint : footerHint || defaultHint;
201
+ const buildDefaultHint = () => {
202
+ const parts = [];
203
+ if (showList !== false) parts.push("\u2191\u2193 Navigate");
204
+ if (showList !== false) parts.push("Enter Select");
205
+ if (showTabs !== false) parts.push("Tab/\u2190\u2192 Switch");
206
+ parts.push("Esc Close");
207
+ return parts.join(" \xB7 ");
208
+ };
209
+ const buildMultiSelectHint = () => {
210
+ const parts = [];
211
+ if (showList !== false) parts.push("\u2191\u2193 Navigate");
212
+ parts.push("Space Select");
213
+ parts.push("a All");
214
+ parts.push("Enter Action");
215
+ if (showTabs !== false) parts.push("Tab Switch");
216
+ parts.push("Esc Close");
217
+ return parts.join(" \xB7 ");
218
+ };
219
+ const displayHint = statusOverlay ? statusOverlay.type === "loading" ? "" : statusDismissHint || "Esc Close" : multiSelect ? selectedIds && selectedIds.size > 0 && multiSelectActionLabel ? `${multiSelectActionLabel} \xB7 ${footerHint || buildMultiSelectHint()}` : footerHint || buildMultiSelectHint() : footerHint || buildDefaultHint();
181
220
  return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", width: "100%" }, /* @__PURE__ */ React.createElement(
182
221
  Box,
183
222
  {
@@ -192,7 +231,14 @@ function TabbedListView({
192
231
  flexDirection: "column"
193
232
  },
194
233
  /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { color: BRAND_GRADIENT.START }, "\u25C6"), /* @__PURE__ */ React.createElement(Text, { bold: true, color: SEMANTIC_COLORS.secondary }, " ", title), showItemCount && !statusOverlay && filteredItems.length > 0 && /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.dim }, " (", filteredItems.length, ")")),
195
- /* @__PURE__ */ React.createElement(Box, { marginTop: 1, flexShrink: 0 }, /* @__PURE__ */ React.createElement(TabBar, { tabs, activeTab, onTabChange }))
234
+ showTabs !== false && /* @__PURE__ */ React.createElement(Box, { marginTop: 1, flexShrink: 0 }, /* @__PURE__ */ React.createElement(
235
+ TabBar,
236
+ {
237
+ tabs,
238
+ activeTab,
239
+ onTabChange
240
+ }
241
+ ))
196
242
  ), /* @__PURE__ */ React.createElement(
197
243
  Box,
198
244
  {
@@ -214,10 +260,10 @@ function TabbedListView({
214
260
  onChange: onSearchChange || (() => {
215
261
  }),
216
262
  placeholder: searchPlaceholder,
217
- isActive: focusArea === "search"
263
+ isActive: inputMode === "search"
218
264
  }
219
265
  )),
220
- /* @__PURE__ */ React.createElement(Box, { key: `content-${activeTab}`, flexDirection: "column" }, statusOverlay ? /* @__PURE__ */ React.createElement(
266
+ showList !== false && /* @__PURE__ */ React.createElement(Box, { key: `content-${activeTab}`, flexDirection: "column" }, statusOverlay ? /* @__PURE__ */ React.createElement(
221
267
  StatusOverlayContent,
222
268
  {
223
269
  type: statusOverlay.type,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/components/TabbedListView/TabbedListView.tsx"],
4
- "sourcesContent": ["/**\n * TabbedListView Component\n *\n * A reusable component matching the /command suggestion UI pattern:\n * - Tab navigation (\u2190/\u2192 or Tab key)\n * - Search input (/ to focus)\n * - Scrollable list with \u25C6 selection indicator\n * - Brand gradient colors for selection\n * - Consistent height control (MAX_VISIBLE = 8)\n * - Status overlay for loading/success/error states (maintains frame)\n * - Back navigation support (onBack)\n *\n * Based on Claude Code CLI's /plugins UI pattern.\n */\n\nimport React, { useState, useCallback, useMemo } from 'react'\nimport { Box, Text, useInput } from 'ink'\nimport { BRAND_GRADIENT, SEMANTIC_COLORS } from '@constants/colors'\nimport { TabBar } from './TabBar'\nimport { SearchInput } from './SearchInput'\nimport { ScrollableList } from './ScrollableList'\nimport { SimpleSpinner } from '@components/Spinner'\nimport { StatusOverlayContent } from '@components/StatusOverlayContent'\nimport { useTerminalSize } from '@hooks/useTerminalSize'\nimport type { TabbedListViewProps, ListItem } from './types'\n\ntype FocusArea = 'tabs' | 'search' | 'list'\n\n// Heights for dynamic visible count calculation\nconst PROMPT_HEIGHT = 5 // PromptInput borders + input + hints\nconst CHROME_HEIGHT = 6 // title + tabs + search + footer + borders\n\nexport function TabbedListView({\n title,\n tabs,\n activeTab,\n onTabChange,\n items,\n searchEnabled = true,\n searchPlaceholder = 'Search...',\n searchQuery = '',\n onSearchChange,\n onSearchSubmit,\n onSelect,\n onClose,\n onBack,\n footerHint,\n isLoading = false,\n loadingText = 'Loading...',\n emptyText = 'No items found',\n groupByCategory = false,\n renderItem,\n statusOverlay,\n isActive = true,\n showItemCount = true,\n statusDismissHint,\n multiSelect,\n selectedIds,\n onSelectionChange,\n onMultiSelect,\n multiSelectActionLabel,\n}: TabbedListViewProps) {\n // Dynamic visible count based on terminal height\n const { rows } = useTerminalSize()\n const visibleCount = Math.min(\n 8,\n Math.max(3, rows - PROMPT_HEIGHT - CHROME_HEIGHT),\n )\n\n // Focus state: which area is currently active\n const [focusArea, setFocusArea] = useState<FocusArea>(\n searchEnabled ? 'search' : 'list',\n )\n\n // Index of focused item in the list\n const [focusedIndex, setFocusedIndex] = useState(0)\n\n // Filter items based on search query\n const filteredItems = useMemo(() => {\n if (!searchQuery.trim()) return items\n\n const query = searchQuery.toLowerCase()\n return items.filter(\n item =>\n item.label.toLowerCase().includes(query) ||\n item.description?.toLowerCase().includes(query) ||\n item.category?.toLowerCase().includes(query),\n )\n }, [items, searchQuery])\n\n // Reset focus index when items change\n React.useEffect(() => {\n setFocusedIndex(0)\n }, [filteredItems.length, activeTab])\n\n // Handle tab cycling\n const cycleTab = useCallback(\n (direction: 'left' | 'right') => {\n const currentIndex = tabs.findIndex(t => t.id === activeTab)\n let newIndex: number\n\n if (direction === 'right') {\n newIndex = (currentIndex + 1) % tabs.length\n } else {\n newIndex = currentIndex - 1 < 0 ? tabs.length - 1 : currentIndex - 1\n }\n\n onTabChange(tabs[newIndex].id)\n },\n [tabs, activeTab, onTabChange],\n )\n\n // Handle item selection\n const handleSelect = useCallback(\n (item: ListItem) => {\n if (onSelect) {\n onSelect(item)\n }\n },\n [onSelect],\n )\n\n // Keyboard input handling\n useInput(\n (input, key) => {\n // Status overlay: success/error \u2192 ESC/Enter closes\n if (statusOverlay && statusOverlay.type !== 'loading') {\n if (key.escape || key.return) {\n onClose()\n }\n return\n }\n\n // Status overlay: loading \u2192 ignore all input\n if (statusOverlay) return\n\n // Escape: onBack if provided, else onClose\n if (key.escape) {\n if (onBack) {\n onBack()\n } else {\n onClose()\n }\n return\n }\n\n // Tab key cycles through tabs\n if (key.tab) {\n cycleTab(key.shift ? 'left' : 'right')\n return\n }\n\n // Left/Right arrows for tab navigation when in tabs or search area\n if (focusArea === 'tabs' || focusArea === 'search') {\n if (key.leftArrow) {\n cycleTab('left')\n return\n }\n if (key.rightArrow) {\n cycleTab('right')\n return\n }\n }\n\n // Handle focus area navigation\n if (key.downArrow) {\n if (focusArea === 'search') {\n setFocusArea('list')\n return\n }\n if (focusArea === 'list' && filteredItems.length > 0) {\n setFocusedIndex(prev =>\n prev < filteredItems.length - 1 ? prev + 1 : prev,\n )\n return\n }\n }\n\n if (key.upArrow) {\n if (focusArea === 'list') {\n if (focusedIndex > 0) {\n setFocusedIndex(prev => prev - 1)\n } else if (searchEnabled) {\n setFocusArea('search')\n }\n return\n }\n }\n\n // Enter in search: submit if onSearchSubmit provided\n if (key.return && focusArea === 'search' && onSearchSubmit) {\n onSearchSubmit(searchQuery)\n return\n }\n\n // Space: toggle selection in multi-select mode\n if (\n input === ' ' &&\n multiSelect &&\n focusArea === 'list' &&\n filteredItems.length > 0\n ) {\n const item = filteredItems[focusedIndex]\n if (item && onSelectionChange) {\n const isCurrentlySelected = selectedIds?.has(item.id) ?? false\n onSelectionChange(item.id, !isCurrentlySelected)\n }\n return\n }\n\n // 'a': toggle select-all / deselect-all in multi-select mode\n if (\n input === 'a' &&\n multiSelect &&\n focusArea === 'list' &&\n filteredItems.length > 0\n ) {\n if (onSelectionChange) {\n const allSelected = filteredItems.every(item =>\n selectedIds?.has(item.id),\n )\n for (const item of filteredItems) {\n onSelectionChange(item.id, !allSelected)\n }\n }\n return\n }\n\n // Enter: batch action if multi-select has selections, otherwise single select\n if (key.return && focusArea === 'list' && filteredItems.length > 0) {\n if (\n multiSelect &&\n selectedIds &&\n selectedIds.size > 0 &&\n onMultiSelect\n ) {\n const selectedItems = filteredItems.filter(item =>\n selectedIds.has(item.id),\n )\n if (selectedItems.length > 0) {\n onMultiSelect(selectedItems)\n return\n }\n }\n handleSelect(filteredItems[focusedIndex])\n return\n }\n\n // '/' to focus search\n if (input === '/' && searchEnabled && focusArea !== 'search') {\n setFocusArea('search')\n return\n }\n },\n { isActive },\n )\n\n // Build footer hint based on current state\n const defaultHint = '\u2191\u2193 Navigate \u00B7 Enter Select \u00B7 Tab/\u2190\u2192 Switch \u00B7 Esc Close'\n const multiSelectHint =\n '\u2191\u2193 Navigate \u00B7 Space Select \u00B7 a All \u00B7 Enter Action \u00B7 Tab Switch \u00B7 Esc Close'\n const displayHint = statusOverlay\n ? statusOverlay.type === 'loading'\n ? ''\n : statusDismissHint || 'Esc Close'\n : multiSelect\n ? selectedIds && selectedIds.size > 0 && multiSelectActionLabel\n ? `${multiSelectActionLabel} \u00B7 ${footerHint || multiSelectHint}`\n : footerHint || multiSelectHint\n : footerHint || defaultHint\n\n return (\n <Box flexDirection=\"column\" width=\"100%\">\n {/* Header bar with top border - mimics PromptInput separator */}\n <Box\n borderTop={true}\n borderBottom={false}\n borderLeft={false}\n borderRight={false}\n borderColor={BRAND_GRADIENT.START}\n borderStyle=\"single\"\n width=\"100%\"\n paddingX={1}\n flexDirection=\"column\"\n >\n {/* Title with brand color */}\n <Box>\n <Text color={BRAND_GRADIENT.START}>\u25C6</Text>\n <Text bold color={SEMANTIC_COLORS.secondary}>\n {' '}\n {title}\n </Text>\n {showItemCount && !statusOverlay && filteredItems.length > 0 && (\n <Text color={SEMANTIC_COLORS.dim}> ({filteredItems.length})</Text>\n )}\n </Box>\n\n {/* Tab Bar - left aligned, flexShrink={0} prevents compression */}\n <Box marginTop={1} flexShrink={0}>\n <TabBar tabs={tabs} activeTab={activeTab} onTabChange={onTabChange} />\n </Box>\n </Box>\n\n {/* Content container with bottom border */}\n <Box\n flexDirection=\"column\"\n borderTop={false}\n borderBottom={true}\n borderLeft={false}\n borderRight={false}\n borderColor={BRAND_GRADIENT.START}\n borderStyle=\"single\"\n width=\"100%\"\n paddingX={1}\n paddingY={1}\n >\n {/* Search Input - hidden during status overlay */}\n {searchEnabled && !statusOverlay && (\n <Box marginBottom={1}>\n <SearchInput\n value={searchQuery}\n onChange={onSearchChange || (() => {})}\n placeholder={searchPlaceholder}\n isActive={focusArea === 'search'}\n />\n </Box>\n )}\n\n {/* Content Area - key forces re-render on tab change */}\n <Box key={`content-${activeTab}`} flexDirection=\"column\">\n {statusOverlay ? (\n <StatusOverlayContent\n type={statusOverlay.type}\n message={statusOverlay.message}\n />\n ) : isLoading ? (\n <Box>\n <SimpleSpinner />\n <Text color={SEMANTIC_COLORS.dim}> {loadingText}</Text>\n </Box>\n ) : filteredItems.length === 0 ? (\n <Box>\n <Text color={SEMANTIC_COLORS.dim}>{emptyText}</Text>\n </Box>\n ) : (\n <ScrollableList\n items={filteredItems}\n focusedIndex={focusedIndex}\n onFocusChange={setFocusedIndex}\n onSelect={handleSelect}\n visibleCount={visibleCount}\n groupByCategory={groupByCategory}\n renderItem={renderItem}\n multiSelect={multiSelect}\n selectedIds={selectedIds}\n />\n )}\n </Box>\n\n {/* Footer Hint - compact style */}\n {displayHint && (\n <Box marginTop={1}>\n <Text color={SEMANTIC_COLORS.muted}>{displayHint}</Text>\n </Box>\n )}\n </Box>\n </Box>\n )\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * TabbedListView Component\n *\n * A reusable component matching the /command suggestion UI pattern:\n * - Tab navigation (\u2190/\u2192 or Tab key)\n * - Search input (/ to focus)\n * - Scrollable list with \u25C6 selection indicator\n * - Brand gradient colors for selection\n * - Consistent height control (MAX_VISIBLE = 8)\n * - Status overlay for loading/success/error states (maintains frame)\n * - Back navigation support (onBack)\n *\n * Based on Claude Code CLI's /plugins UI pattern.\n */\n\nimport React, { useState, useCallback, useMemo } from 'react'\nimport { Box, Text, useInput } from 'ink'\nimport { BRAND_GRADIENT, SEMANTIC_COLORS } from '@constants/colors'\nimport { TabBar } from './TabBar'\nimport { SearchInput } from './SearchInput'\nimport { ScrollableList } from './ScrollableList'\nimport { SimpleSpinner } from '@components/Spinner'\nimport { StatusOverlayContent } from '@components/StatusOverlayContent'\nimport { useTerminalSize } from '@hooks/useTerminalSize'\nimport type { TabbedListViewProps, ListItem } from './types'\n\ntype InputMode = 'normal' | 'search'\n\n// Heights for dynamic visible count calculation\nconst PROMPT_HEIGHT = 5 // PromptInput borders + input + hints\n\nexport function TabbedListView({\n title,\n tabs,\n activeTab,\n onTabChange,\n items,\n searchEnabled = true,\n searchPlaceholder = 'Search...',\n searchQuery = '',\n onSearchChange,\n onSearchSubmit,\n onSelect,\n onClose,\n onBack,\n footerHint,\n isLoading = false,\n loadingText = 'Loading...',\n emptyText = 'No items found',\n groupByCategory = false,\n renderItem,\n statusOverlay,\n isActive = true,\n showItemCount = true,\n showTabs,\n showList,\n statusDismissHint,\n multiSelect,\n selectedIds,\n onSelectionChange,\n onMultiSelect,\n multiSelectActionLabel,\n}: TabbedListViewProps) {\n // Dynamic visible count based on terminal height and visible sections\n const { rows } = useTerminalSize()\n const chromeHeight =\n 2 + // title + top border\n (showTabs !== false ? 2 : 0) + // tab bar + margin\n (searchEnabled ? 2 : 0) + // search + margin\n 2 // footer + bottom border\n const visibleCount = Math.min(\n 8,\n Math.max(3, rows - PROMPT_HEIGHT - chromeHeight),\n )\n\n // Input mode: always start in 'normal' so list cursor is on first item\n const [inputMode, setInputMode] = useState<InputMode>('normal')\n\n // Index of focused item in the list\n const [focusedIndex, setFocusedIndex] = useState(0)\n\n // Filter items based on search query\n const filteredItems = useMemo(() => {\n if (!searchQuery.trim()) return items\n\n const query = searchQuery.toLowerCase()\n return items.filter(\n item =>\n item.label.toLowerCase().includes(query) ||\n item.description?.toLowerCase().includes(query) ||\n item.category?.toLowerCase().includes(query),\n )\n }, [items, searchQuery])\n\n // Reset focus index when items change\n React.useEffect(() => {\n setFocusedIndex(0)\n }, [filteredItems.length, activeTab])\n\n // Handle tab cycling\n const cycleTab = useCallback(\n (direction: 'left' | 'right') => {\n const currentIndex = tabs.findIndex(t => t.id === activeTab)\n let newIndex: number\n\n if (direction === 'right') {\n newIndex = (currentIndex + 1) % tabs.length\n } else {\n newIndex = currentIndex - 1 < 0 ? tabs.length - 1 : currentIndex - 1\n }\n\n onTabChange(tabs[newIndex].id)\n },\n [tabs, activeTab, onTabChange],\n )\n\n // Handle item selection\n const handleSelect = useCallback(\n (item: ListItem) => {\n if (onSelect) {\n onSelect(item)\n }\n },\n [onSelect],\n )\n\n // Keyboard input handling \u2014 dual-cursor model\n useInput(\n (input, key) => {\n // Status overlay: success/error \u2192 ESC/Enter closes\n if (statusOverlay && statusOverlay.type !== 'loading') {\n if (key.escape || key.return) {\n onClose()\n }\n return\n }\n\n // Status overlay: loading \u2192 ignore all input\n if (statusOverlay) return\n\n // --- Search mode: text input is active ---\n if (inputMode === 'search') {\n if (key.escape) {\n if (showList !== false) {\n setInputMode('normal')\n } else if (onBack) {\n onBack()\n } else {\n onClose()\n }\n return\n }\n if (key.downArrow && showList !== false) {\n setInputMode('normal')\n return\n }\n if (key.return && onSearchSubmit) {\n onSearchSubmit(searchQuery)\n return\n }\n // Left/Right: cycle tabs even in search mode (matches original behavior)\n if (showTabs !== false) {\n if (key.leftArrow) {\n cycleTab('left')\n return\n }\n if (key.rightArrow) {\n cycleTab('right')\n return\n }\n }\n // All other input passes through to InkTextInput\n return\n }\n\n // --- Normal mode: dual-cursor (L/R tabs, U/D list) ---\n\n // Escape: onBack if provided, else onClose\n if (key.escape) {\n if (onBack) {\n onBack()\n } else {\n onClose()\n }\n return\n }\n\n // Tab key cycles through tabs\n if (key.tab && showTabs !== false) {\n cycleTab(key.shift ? 'left' : 'right')\n return\n }\n\n // Left/Right arrows always cycle tabs in normal mode\n if (showTabs !== false) {\n if (key.leftArrow) {\n cycleTab('left')\n return\n }\n if (key.rightArrow) {\n cycleTab('right')\n return\n }\n }\n\n // Down arrow: navigate list down\n if (key.downArrow && showList !== false && filteredItems.length > 0) {\n setFocusedIndex(prev =>\n prev < filteredItems.length - 1 ? prev + 1 : prev,\n )\n return\n }\n\n // Up arrow: navigate list up; at index 0 \u2192 enter search if enabled\n if (key.upArrow && showList !== false) {\n if (focusedIndex > 0) {\n setFocusedIndex(prev => prev - 1)\n } else if (searchEnabled) {\n setInputMode('search')\n }\n return\n }\n\n // Space: toggle selection in multi-select mode\n if (\n input === ' ' &&\n multiSelect &&\n showList !== false &&\n filteredItems.length > 0\n ) {\n const item = filteredItems[focusedIndex]\n if (item && onSelectionChange) {\n const isCurrentlySelected = selectedIds?.has(item.id) ?? false\n onSelectionChange(item.id, !isCurrentlySelected)\n }\n return\n }\n\n // 'a': toggle select-all / deselect-all in multi-select mode\n if (\n input === 'a' &&\n multiSelect &&\n showList !== false &&\n filteredItems.length > 0\n ) {\n if (onSelectionChange) {\n const allSelected = filteredItems.every(item =>\n selectedIds?.has(item.id),\n )\n for (const item of filteredItems) {\n onSelectionChange(item.id, !allSelected)\n }\n }\n return\n }\n\n // Enter: batch action if multi-select has selections, otherwise single select\n if (key.return && showList !== false && filteredItems.length > 0) {\n if (\n multiSelect &&\n selectedIds &&\n selectedIds.size > 0 &&\n onMultiSelect\n ) {\n const selectedItems = filteredItems.filter(item =>\n selectedIds.has(item.id),\n )\n if (selectedItems.length > 0) {\n onMultiSelect(selectedItems)\n return\n }\n }\n const selectedItem =\n filteredItems[Math.min(focusedIndex, filteredItems.length - 1)]\n if (selectedItem) handleSelect(selectedItem)\n return\n }\n\n // '/' to focus search\n if (input === '/' && searchEnabled && inputMode !== 'search') {\n setInputMode('search')\n return\n }\n },\n { isActive },\n )\n\n // Build footer hint dynamically based on visible sections\n const buildDefaultHint = (): string => {\n const parts: string[] = []\n if (showList !== false) parts.push('\u2191\u2193 Navigate')\n if (showList !== false) parts.push('Enter Select')\n if (showTabs !== false) parts.push('Tab/\u2190\u2192 Switch')\n parts.push('Esc Close')\n return parts.join(' \u00B7 ')\n }\n const buildMultiSelectHint = (): string => {\n const parts: string[] = []\n if (showList !== false) parts.push('\u2191\u2193 Navigate')\n parts.push('Space Select')\n parts.push('a All')\n parts.push('Enter Action')\n if (showTabs !== false) parts.push('Tab Switch')\n parts.push('Esc Close')\n return parts.join(' \u00B7 ')\n }\n const displayHint = statusOverlay\n ? statusOverlay.type === 'loading'\n ? ''\n : statusDismissHint || 'Esc Close'\n : multiSelect\n ? selectedIds && selectedIds.size > 0 && multiSelectActionLabel\n ? `${multiSelectActionLabel} \u00B7 ${footerHint || buildMultiSelectHint()}`\n : footerHint || buildMultiSelectHint()\n : footerHint || buildDefaultHint()\n\n return (\n <Box flexDirection=\"column\" width=\"100%\">\n {/* Header bar with top border - mimics PromptInput separator */}\n <Box\n borderTop={true}\n borderBottom={false}\n borderLeft={false}\n borderRight={false}\n borderColor={BRAND_GRADIENT.START}\n borderStyle=\"single\"\n width=\"100%\"\n paddingX={1}\n flexDirection=\"column\"\n >\n {/* Title with brand color */}\n <Box>\n <Text color={BRAND_GRADIENT.START}>\u25C6</Text>\n <Text bold color={SEMANTIC_COLORS.secondary}>\n {' '}\n {title}\n </Text>\n {showItemCount && !statusOverlay && filteredItems.length > 0 && (\n <Text color={SEMANTIC_COLORS.dim}> ({filteredItems.length})</Text>\n )}\n </Box>\n\n {/* Tab Bar - only if showTabs */}\n {showTabs !== false && (\n <Box marginTop={1} flexShrink={0}>\n <TabBar\n tabs={tabs}\n activeTab={activeTab}\n onTabChange={onTabChange}\n />\n </Box>\n )}\n </Box>\n\n {/* Content container with bottom border */}\n <Box\n flexDirection=\"column\"\n borderTop={false}\n borderBottom={true}\n borderLeft={false}\n borderRight={false}\n borderColor={BRAND_GRADIENT.START}\n borderStyle=\"single\"\n width=\"100%\"\n paddingX={1}\n paddingY={1}\n >\n {/* Search Input - hidden during status overlay */}\n {searchEnabled && !statusOverlay && (\n <Box marginBottom={1}>\n <SearchInput\n value={searchQuery}\n onChange={onSearchChange || (() => {})}\n placeholder={searchPlaceholder}\n isActive={inputMode === 'search'}\n />\n </Box>\n )}\n\n {/* Content Area - only if showList */}\n {showList !== false && (\n <Box key={`content-${activeTab}`} flexDirection=\"column\">\n {statusOverlay ? (\n <StatusOverlayContent\n type={statusOverlay.type}\n message={statusOverlay.message}\n />\n ) : isLoading ? (\n <Box>\n <SimpleSpinner />\n <Text color={SEMANTIC_COLORS.dim}> {loadingText}</Text>\n </Box>\n ) : filteredItems.length === 0 ? (\n <Box>\n <Text color={SEMANTIC_COLORS.dim}>{emptyText}</Text>\n </Box>\n ) : (\n <ScrollableList\n items={filteredItems}\n focusedIndex={focusedIndex}\n onFocusChange={setFocusedIndex}\n onSelect={handleSelect}\n visibleCount={visibleCount}\n groupByCategory={groupByCategory}\n renderItem={renderItem}\n multiSelect={multiSelect}\n selectedIds={selectedIds}\n />\n )}\n </Box>\n )}\n\n {/* Footer Hint - compact style */}\n {displayHint && (\n <Box marginTop={1}>\n <Text color={SEMANTIC_COLORS.muted}>{displayHint}</Text>\n </Box>\n )}\n </Box>\n </Box>\n )\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }