@within-7/minto 0.1.7 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (601) hide show
  1. package/cli.js +155 -37
  2. package/dist/Tool.js +38 -0
  3. package/dist/Tool.js.map +3 -3
  4. package/dist/commands/agents/AgentsCommand.js +73 -49
  5. package/dist/commands/agents/AgentsCommand.js.map +2 -2
  6. package/dist/commands/agents/constants.js +1 -1
  7. package/dist/commands/agents/constants.js.map +1 -1
  8. package/dist/commands/agents/index.js +1 -1
  9. package/dist/commands/bug.js +74 -7
  10. package/dist/commands/bug.js.map +3 -3
  11. package/dist/commands/clear.js +3 -0
  12. package/dist/commands/clear.js.map +2 -2
  13. package/dist/commands/compact.js +37 -0
  14. package/dist/commands/compact.js.map +2 -2
  15. package/dist/commands/context.js +85 -0
  16. package/dist/commands/context.js.map +7 -0
  17. package/dist/commands/ctx_viz.js +18 -10
  18. package/dist/commands/ctx_viz.js.map +2 -2
  19. package/dist/commands/doctor.js +158 -12
  20. package/dist/commands/doctor.js.map +2 -2
  21. package/dist/commands/export.js +157 -0
  22. package/dist/commands/export.js.map +7 -0
  23. package/dist/commands/mcp-interactive.js +28 -18
  24. package/dist/commands/mcp-interactive.js.map +2 -2
  25. package/dist/commands/model.js +9 -7
  26. package/dist/commands/model.js.map +2 -2
  27. package/dist/commands/permissions.js +87 -0
  28. package/dist/commands/permissions.js.map +7 -0
  29. package/dist/commands/plugin/AddMarketplaceForm.js +3 -2
  30. package/dist/commands/plugin/AddMarketplaceForm.js.map +2 -2
  31. package/dist/commands/plugin/ConfirmDialog.js +2 -1
  32. package/dist/commands/plugin/ConfirmDialog.js.map +2 -2
  33. package/dist/commands/plugin/ErrorView.js +2 -1
  34. package/dist/commands/plugin/ErrorView.js.map +2 -2
  35. package/dist/commands/plugin/InstalledPluginsByMarketplace.js +5 -4
  36. package/dist/commands/plugin/InstalledPluginsByMarketplace.js.map +2 -2
  37. package/dist/commands/plugin/InstalledPluginsManager.js +5 -4
  38. package/dist/commands/plugin/InstalledPluginsManager.js.map +2 -2
  39. package/dist/commands/plugin/MainMenu.js +2 -1
  40. package/dist/commands/plugin/MainMenu.js.map +2 -2
  41. package/dist/commands/plugin/MarketplaceManager.js +5 -4
  42. package/dist/commands/plugin/MarketplaceManager.js.map +2 -2
  43. package/dist/commands/plugin/MarketplaceSelector.js +4 -3
  44. package/dist/commands/plugin/MarketplaceSelector.js.map +2 -2
  45. package/dist/commands/plugin/PlaceholderScreen.js +3 -2
  46. package/dist/commands/plugin/PlaceholderScreen.js.map +2 -2
  47. package/dist/commands/plugin/PluginBrowser.js +6 -5
  48. package/dist/commands/plugin/PluginBrowser.js.map +2 -2
  49. package/dist/commands/plugin/PluginDetailsInstall.js +5 -4
  50. package/dist/commands/plugin/PluginDetailsInstall.js.map +2 -2
  51. package/dist/commands/plugin/PluginDetailsManage.js +4 -3
  52. package/dist/commands/plugin/PluginDetailsManage.js.map +2 -2
  53. package/dist/commands/plugin.js +16 -15
  54. package/dist/commands/plugin.js.map +2 -2
  55. package/dist/commands/quit.js +3 -1
  56. package/dist/commands/quit.js.map +2 -2
  57. package/dist/commands/sandbox.js +105 -0
  58. package/dist/commands/sandbox.js.map +7 -0
  59. package/dist/commands/setup.js +2 -1
  60. package/dist/commands/setup.js.map +2 -2
  61. package/dist/commands/status.js +59 -0
  62. package/dist/commands/status.js.map +7 -0
  63. package/dist/commands/tasks.js +108 -0
  64. package/dist/commands/tasks.js.map +7 -0
  65. package/dist/commands/todos.js +123 -0
  66. package/dist/commands/todos.js.map +7 -0
  67. package/dist/commands/undo.js +245 -0
  68. package/dist/commands/undo.js.map +7 -0
  69. package/dist/commands.js +22 -2
  70. package/dist/commands.js.map +2 -2
  71. package/dist/components/AgentThinkingBlock.js +10 -18
  72. package/dist/components/AgentThinkingBlock.js.map +2 -2
  73. package/dist/components/AsciiLogo.js +7 -8
  74. package/dist/components/AsciiLogo.js.map +2 -2
  75. package/dist/components/AskUserQuestionDialog/AskUserQuestionDialog.js +3 -2
  76. package/dist/components/AskUserQuestionDialog/AskUserQuestionDialog.js.map +2 -2
  77. package/dist/components/AskUserQuestionDialog/QuestionView.js +2 -1
  78. package/dist/components/AskUserQuestionDialog/QuestionView.js.map +2 -2
  79. package/dist/components/BackgroundTasksPanel.js +78 -29
  80. package/dist/components/BackgroundTasksPanel.js.map +2 -2
  81. package/dist/components/BashStreamingProgress.js +24 -0
  82. package/dist/components/BashStreamingProgress.js.map +7 -0
  83. package/dist/components/CollapsibleHint.js +15 -0
  84. package/dist/components/CollapsibleHint.js.map +7 -0
  85. package/dist/components/Config.js +3 -2
  86. package/dist/components/Config.js.map +2 -2
  87. package/dist/components/ConsoleOAuthFlow.js +2 -1
  88. package/dist/components/ConsoleOAuthFlow.js.map +2 -2
  89. package/dist/components/Cost.js +2 -1
  90. package/dist/components/Cost.js.map +2 -2
  91. package/dist/components/FileEditToolUpdatedMessage.js +1 -1
  92. package/dist/components/FileEditToolUpdatedMessage.js.map +2 -2
  93. package/dist/components/HeaderBar.js +13 -8
  94. package/dist/components/HeaderBar.js.map +2 -2
  95. package/dist/components/HistorySearchOverlay.js +4 -3
  96. package/dist/components/HistorySearchOverlay.js.map +2 -2
  97. package/dist/components/HotkeyHelpPanel.js +134 -0
  98. package/dist/components/HotkeyHelpPanel.js.map +7 -0
  99. package/dist/components/InvalidConfigDialog.js +2 -1
  100. package/dist/components/InvalidConfigDialog.js.map +2 -2
  101. package/dist/components/Logo.js +24 -68
  102. package/dist/components/Logo.js.map +2 -2
  103. package/dist/components/MCPServerApprovalDialog.js +2 -1
  104. package/dist/components/MCPServerApprovalDialog.js.map +2 -2
  105. package/dist/components/MCPServerDialogCopy.js +2 -1
  106. package/dist/components/MCPServerDialogCopy.js.map +2 -2
  107. package/dist/components/MCPServerMultiselectDialog.js +2 -1
  108. package/dist/components/MCPServerMultiselectDialog.js.map +2 -2
  109. package/dist/components/Message.js +23 -7
  110. package/dist/components/Message.js.map +3 -3
  111. package/dist/components/MessageSelector.js +4 -3
  112. package/dist/components/MessageSelector.js.map +2 -2
  113. package/dist/components/ModeIndicator.js +2 -1
  114. package/dist/components/ModeIndicator.js.map +2 -2
  115. package/dist/components/ModelConfig.js +20 -6
  116. package/dist/components/ModelConfig.js.map +2 -2
  117. package/dist/components/ModelListManager.js +7 -6
  118. package/dist/components/ModelListManager.js.map +2 -2
  119. package/dist/components/ModelSelector/ModelSelector.js +27 -14
  120. package/dist/components/ModelSelector/ModelSelector.js.map +2 -2
  121. package/dist/components/Onboarding.js +22 -16
  122. package/dist/components/Onboarding.js.map +2 -2
  123. package/dist/components/OperationSummary.js +130 -0
  124. package/dist/components/OperationSummary.js.map +7 -0
  125. package/dist/components/ProgressBar.js +74 -0
  126. package/dist/components/ProgressBar.js.map +7 -0
  127. package/dist/components/PromptInput.js +210 -87
  128. package/dist/components/PromptInput.js.map +2 -2
  129. package/dist/components/RequestStatusIndicator.js +194 -0
  130. package/dist/components/RequestStatusIndicator.js.map +7 -0
  131. package/dist/components/SensitiveFileWarning.js +31 -0
  132. package/dist/components/SensitiveFileWarning.js.map +7 -0
  133. package/dist/components/Spinner.js +141 -27
  134. package/dist/components/Spinner.js.map +2 -2
  135. package/dist/components/SpinnerSymbol.js +21 -27
  136. package/dist/components/SpinnerSymbol.js.map +2 -2
  137. package/dist/components/StreamingBashOutput.js +9 -8
  138. package/dist/components/StreamingBashOutput.js.map +2 -2
  139. package/dist/components/StructuredDiff.js +6 -8
  140. package/dist/components/StructuredDiff.js.map +2 -2
  141. package/dist/components/SubagentBlock.js +5 -3
  142. package/dist/components/SubagentBlock.js.map +2 -2
  143. package/dist/components/SubagentProgress.js +17 -15
  144. package/dist/components/SubagentProgress.js.map +2 -2
  145. package/dist/components/TaskCard.js +30 -24
  146. package/dist/components/TaskCard.js.map +2 -2
  147. package/dist/components/TextInput.js +9 -1
  148. package/dist/components/TextInput.js.map +2 -2
  149. package/dist/components/TodoChangeBlock.js +1 -1
  150. package/dist/components/TodoChangeBlock.js.map +2 -2
  151. package/dist/components/TodoPanel.js +140 -31
  152. package/dist/components/TodoPanel.js.map +3 -3
  153. package/dist/components/TokenCounter.js +74 -0
  154. package/dist/components/TokenCounter.js.map +7 -0
  155. package/dist/components/TokenWarning.js +2 -1
  156. package/dist/components/TokenWarning.js.map +2 -2
  157. package/dist/components/ToolUseLoader.js +2 -2
  158. package/dist/components/ToolUseLoader.js.map +2 -2
  159. package/dist/components/TreeConnector.js +26 -0
  160. package/dist/components/TreeConnector.js.map +7 -0
  161. package/dist/components/TrustDialog.js +2 -1
  162. package/dist/components/TrustDialog.js.map +2 -2
  163. package/dist/components/TurnCompletionIndicator.js +18 -0
  164. package/dist/components/TurnCompletionIndicator.js.map +7 -0
  165. package/dist/components/binary-feedback/BinaryFeedbackView.js +2 -1
  166. package/dist/components/binary-feedback/BinaryFeedbackView.js.map +2 -2
  167. package/dist/components/messages/AssistantTextMessage.js +20 -9
  168. package/dist/components/messages/AssistantTextMessage.js.map +2 -2
  169. package/dist/components/messages/AssistantThinkingMessage.js +18 -3
  170. package/dist/components/messages/AssistantThinkingMessage.js.map +2 -2
  171. package/dist/components/messages/AssistantToolUseMessage.js +17 -10
  172. package/dist/components/messages/AssistantToolUseMessage.js.map +2 -2
  173. package/dist/components/messages/GroupRenderer.js +54 -0
  174. package/dist/components/messages/GroupRenderer.js.map +7 -0
  175. package/dist/components/messages/NestedTasksPreview.js +24 -0
  176. package/dist/components/messages/NestedTasksPreview.js.map +7 -0
  177. package/dist/components/messages/ParallelTasksGroupView.js +93 -0
  178. package/dist/components/messages/ParallelTasksGroupView.js.map +7 -0
  179. package/dist/components/messages/TaskInModuleView.js +218 -0
  180. package/dist/components/messages/TaskInModuleView.js.map +7 -0
  181. package/dist/components/messages/TaskOutputContent.js +56 -0
  182. package/dist/components/messages/TaskOutputContent.js.map +7 -0
  183. package/dist/components/messages/UserPromptMessage.js +2 -2
  184. package/dist/components/messages/UserPromptMessage.js.map +2 -2
  185. package/dist/components/messages/UserToolResultMessage/UserToolSuccessMessage.js +2 -3
  186. package/dist/components/messages/UserToolResultMessage/UserToolSuccessMessage.js.map +2 -2
  187. package/dist/components/permissions/FallbackPermissionRequest.js +4 -4
  188. package/dist/components/permissions/FallbackPermissionRequest.js.map +2 -2
  189. package/dist/components/permissions/FilesystemPermissionRequest/FilesystemPermissionRequest.js +4 -4
  190. package/dist/components/permissions/FilesystemPermissionRequest/FilesystemPermissionRequest.js.map +2 -2
  191. package/dist/constants/colors.js +120 -54
  192. package/dist/constants/colors.js.map +2 -2
  193. package/dist/constants/formatRules.js +102 -0
  194. package/dist/constants/formatRules.js.map +7 -0
  195. package/dist/constants/prompts.js +12 -34
  196. package/dist/constants/prompts.js.map +2 -2
  197. package/dist/constants/symbols.js +64 -6
  198. package/dist/constants/symbols.js.map +2 -2
  199. package/dist/constants/timing.js +5 -0
  200. package/dist/constants/timing.js.map +2 -2
  201. package/dist/constants/toolInputExamples.js +84 -0
  202. package/dist/constants/toolInputExamples.js.map +7 -0
  203. package/dist/core/backupManager.js +321 -0
  204. package/dist/core/backupManager.js.map +7 -0
  205. package/dist/core/config/defaults.js +84 -0
  206. package/dist/core/config/defaults.js.map +7 -0
  207. package/dist/core/config/index.js +111 -0
  208. package/dist/core/config/index.js.map +7 -0
  209. package/dist/core/config/loader.js +221 -0
  210. package/dist/core/config/loader.js.map +7 -0
  211. package/dist/core/config/migrations.js +128 -0
  212. package/dist/core/config/migrations.js.map +7 -0
  213. package/dist/core/config/schema.js +178 -0
  214. package/dist/core/config/schema.js.map +7 -0
  215. package/dist/core/costTracker.js +129 -0
  216. package/dist/core/costTracker.js.map +7 -0
  217. package/dist/core/gitAutoCommit.js +287 -0
  218. package/dist/core/gitAutoCommit.js.map +7 -0
  219. package/dist/core/index.js +8 -0
  220. package/dist/core/index.js.map +7 -0
  221. package/dist/core/operationTracker.js +212 -0
  222. package/dist/core/operationTracker.js.map +7 -0
  223. package/dist/core/permissions/auditLog.js +204 -0
  224. package/dist/core/permissions/auditLog.js.map +7 -0
  225. package/dist/core/permissions/engine/index.js +3 -0
  226. package/dist/core/permissions/engine/index.js.map +7 -0
  227. package/dist/core/permissions/engine/permissionEngine.js +106 -0
  228. package/dist/core/permissions/engine/permissionEngine.js.map +7 -0
  229. package/dist/core/permissions/engine/types.js +1 -0
  230. package/dist/core/permissions/engine/types.js.map +7 -0
  231. package/dist/core/permissions/index.js +84 -0
  232. package/dist/core/permissions/index.js.map +7 -0
  233. package/dist/core/permissions/ruleEngine.js +259 -0
  234. package/dist/core/permissions/ruleEngine.js.map +7 -0
  235. package/dist/core/permissions/rules/allowedToolsRule.js +62 -0
  236. package/dist/core/permissions/rules/allowedToolsRule.js.map +7 -0
  237. package/dist/core/permissions/rules/autoEscalationRule.js +296 -0
  238. package/dist/core/permissions/rules/autoEscalationRule.js.map +7 -0
  239. package/dist/core/permissions/rules/index.js +46 -0
  240. package/dist/core/permissions/rules/index.js.map +7 -0
  241. package/dist/core/permissions/rules/planModeRule.js +55 -0
  242. package/dist/core/permissions/rules/planModeRule.js.map +7 -0
  243. package/dist/core/permissions/rules/projectBoundaryRule.js +173 -0
  244. package/dist/core/permissions/rules/projectBoundaryRule.js.map +7 -0
  245. package/dist/core/permissions/rules/safeModeRule.js +65 -0
  246. package/dist/core/permissions/rules/safeModeRule.js.map +7 -0
  247. package/dist/core/permissions/rules/sensitivePathsRule.js +345 -0
  248. package/dist/core/permissions/rules/sensitivePathsRule.js.map +7 -0
  249. package/dist/core/permissions/types.js +127 -0
  250. package/dist/core/permissions/types.js.map +7 -0
  251. package/dist/core/tokenStats.js +9 -0
  252. package/dist/core/tokenStats.js.map +7 -0
  253. package/dist/core/tokenStatsManager.js +331 -0
  254. package/dist/core/tokenStatsManager.js.map +7 -0
  255. package/dist/core/tools/executor.js +143 -0
  256. package/dist/core/tools/executor.js.map +7 -0
  257. package/dist/core/tools/index.js +15 -0
  258. package/dist/core/tools/index.js.map +7 -0
  259. package/dist/core/tools/registry.js +183 -0
  260. package/dist/core/tools/registry.js.map +7 -0
  261. package/dist/core/tools/types.js +1 -0
  262. package/dist/core/tools/types.js.map +7 -0
  263. package/dist/cost-tracker.js +23 -15
  264. package/dist/cost-tracker.js.map +2 -2
  265. package/dist/entrypoints/cli.js +158 -130
  266. package/dist/entrypoints/cli.js.map +2 -2
  267. package/dist/entrypoints/mcp.js +12 -4
  268. package/dist/entrypoints/mcp.js.map +2 -2
  269. package/dist/history.js +14 -3
  270. package/dist/history.js.map +2 -2
  271. package/dist/hooks/useAgentTokenStats.js +72 -0
  272. package/dist/hooks/useAgentTokenStats.js.map +7 -0
  273. package/dist/hooks/useAgentTranscripts.js +140 -0
  274. package/dist/hooks/useAgentTranscripts.js.map +7 -0
  275. package/dist/hooks/useAnimationSync.js +53 -0
  276. package/dist/hooks/useAnimationSync.js.map +7 -0
  277. package/dist/hooks/useArrowKeyHistory.js +4 -2
  278. package/dist/hooks/useArrowKeyHistory.js.map +2 -2
  279. package/dist/hooks/useCanUseTool.js +3 -1
  280. package/dist/hooks/useCanUseTool.js.map +2 -2
  281. package/dist/hooks/useExitOnCtrlCD.js +9 -5
  282. package/dist/hooks/useExitOnCtrlCD.js.map +2 -2
  283. package/dist/hooks/useHookStatus.js +40 -0
  284. package/dist/hooks/useHookStatus.js.map +7 -0
  285. package/dist/hooks/useLogMessages.js +29 -2
  286. package/dist/hooks/useLogMessages.js.map +2 -2
  287. package/dist/hooks/useMessageGroups.js +43 -0
  288. package/dist/hooks/useMessageGroups.js.map +7 -0
  289. package/dist/hooks/useTerminalSize.js +62 -6
  290. package/dist/hooks/useTerminalSize.js.map +2 -2
  291. package/dist/hooks/useUnifiedCompletion.js +69 -0
  292. package/dist/hooks/useUnifiedCompletion.js.map +2 -2
  293. package/dist/i18n/index.js +109 -0
  294. package/dist/i18n/index.js.map +7 -0
  295. package/dist/i18n/locales/en.js +348 -0
  296. package/dist/i18n/locales/en.js.map +7 -0
  297. package/dist/i18n/locales/index.js +7 -0
  298. package/dist/i18n/locales/index.js.map +7 -0
  299. package/dist/i18n/locales/zh-CN.js +348 -0
  300. package/dist/i18n/locales/zh-CN.js.map +7 -0
  301. package/dist/i18n/types.js +8 -0
  302. package/dist/i18n/types.js.map +7 -0
  303. package/dist/permissions.js +28 -1
  304. package/dist/permissions.js.map +2 -2
  305. package/dist/query.js +253 -21
  306. package/dist/query.js.map +3 -3
  307. package/dist/screens/REPL.js +523 -194
  308. package/dist/screens/REPL.js.map +3 -3
  309. package/dist/services/adapters/chatCompletions.js +3 -1
  310. package/dist/services/adapters/chatCompletions.js.map +2 -2
  311. package/dist/services/adapters/messageNormalizer.js +354 -0
  312. package/dist/services/adapters/messageNormalizer.js.map +7 -0
  313. package/dist/services/adapters/responsesAPI.js +6 -3
  314. package/dist/services/adapters/responsesAPI.js.map +2 -2
  315. package/dist/services/checkpointManager.js +386 -0
  316. package/dist/services/checkpointManager.js.map +7 -0
  317. package/dist/services/claude.js +192 -14
  318. package/dist/services/claude.js.map +3 -3
  319. package/dist/services/compressionService.js +50 -1
  320. package/dist/services/compressionService.js.map +2 -2
  321. package/dist/services/contextMonitor.js +162 -0
  322. package/dist/services/contextMonitor.js.map +7 -0
  323. package/dist/services/customCommands.js +60 -41
  324. package/dist/services/customCommands.js.map +2 -2
  325. package/dist/services/hookExecutor.js +173 -1
  326. package/dist/services/hookExecutor.js.map +2 -2
  327. package/dist/services/intelligentCompactor.js +281 -0
  328. package/dist/services/intelligentCompactor.js.map +7 -0
  329. package/dist/services/lspConfig.js +109 -0
  330. package/dist/services/lspConfig.js.map +7 -0
  331. package/dist/services/mcpClient.js +338 -43
  332. package/dist/services/mcpClient.js.map +2 -2
  333. package/dist/services/modelOrchestrator.js +310 -0
  334. package/dist/services/modelOrchestrator.js.map +7 -0
  335. package/dist/services/openai.js +8 -1
  336. package/dist/services/openai.js.map +2 -2
  337. package/dist/services/outputStyles.js +138 -0
  338. package/dist/services/outputStyles.js.map +7 -0
  339. package/dist/services/plugins/index.js +5 -0
  340. package/dist/services/plugins/index.js.map +7 -0
  341. package/dist/services/plugins/lspServers.js +188 -0
  342. package/dist/services/plugins/lspServers.js.map +7 -0
  343. package/dist/services/plugins/pluginRuntime.js +229 -0
  344. package/dist/services/plugins/pluginRuntime.js.map +7 -0
  345. package/dist/services/plugins/pluginValidation.js +219 -0
  346. package/dist/services/plugins/pluginValidation.js.map +7 -0
  347. package/dist/services/plugins/skillMarketplace.js +556 -0
  348. package/dist/services/plugins/skillMarketplace.js.map +7 -0
  349. package/dist/services/responseStateManager.js +37 -3
  350. package/dist/services/responseStateManager.js.map +2 -2
  351. package/dist/services/sandbox/filesystemBoundary.js +341 -0
  352. package/dist/services/sandbox/filesystemBoundary.js.map +7 -0
  353. package/dist/services/sandbox/index.js +14 -0
  354. package/dist/services/sandbox/index.js.map +7 -0
  355. package/dist/services/sandbox/networkProxy.js +293 -0
  356. package/dist/services/sandbox/networkProxy.js.map +7 -0
  357. package/dist/services/sandbox/sandboxController.js +574 -0
  358. package/dist/services/sandbox/sandboxController.js.map +7 -0
  359. package/dist/services/sandbox/types.js +50 -0
  360. package/dist/services/sandbox/types.js.map +7 -0
  361. package/dist/services/sessionMemory.js +266 -0
  362. package/dist/services/sessionMemory.js.map +7 -0
  363. package/dist/services/taskRouter.js +324 -0
  364. package/dist/services/taskRouter.js.map +7 -0
  365. package/dist/tools/ArchitectTool/ArchitectTool.js +7 -1
  366. package/dist/tools/ArchitectTool/ArchitectTool.js.map +2 -2
  367. package/dist/tools/AskExpertModelTool/AskExpertModelTool.js +6 -2
  368. package/dist/tools/AskExpertModelTool/AskExpertModelTool.js.map +2 -2
  369. package/dist/tools/AskUserQuestionTool/AskUserQuestionTool.js +2 -1
  370. package/dist/tools/AskUserQuestionTool/AskUserQuestionTool.js.map +2 -2
  371. package/dist/tools/BaseTool.js +72 -0
  372. package/dist/tools/BaseTool.js.map +7 -0
  373. package/dist/tools/BashOutputTool/BashOutputToolResultMessage.js +3 -0
  374. package/dist/tools/BashOutputTool/BashOutputToolResultMessage.js.map +2 -2
  375. package/dist/tools/BashTool/BashTool.js +79 -3
  376. package/dist/tools/BashTool/BashTool.js.map +2 -2
  377. package/dist/tools/BashTool/BashToolResultMessage.js +3 -0
  378. package/dist/tools/BashTool/BashToolResultMessage.js.map +2 -2
  379. package/dist/tools/BashTool/OutputLine.js +54 -0
  380. package/dist/tools/BashTool/OutputLine.js.map +2 -2
  381. package/dist/tools/BashTool/prompt.js +336 -3
  382. package/dist/tools/BashTool/prompt.js.map +2 -2
  383. package/dist/tools/FileEditTool/FileEditTool.js +29 -4
  384. package/dist/tools/FileEditTool/FileEditTool.js.map +2 -2
  385. package/dist/tools/FileEditTool/prompt.js +6 -3
  386. package/dist/tools/FileEditTool/prompt.js.map +2 -2
  387. package/dist/tools/FileWriteTool/FileWriteTool.js +5 -5
  388. package/dist/tools/FileWriteTool/FileWriteTool.js.map +2 -2
  389. package/dist/tools/FileWriteTool/prompt.js +4 -2
  390. package/dist/tools/FileWriteTool/prompt.js.map +2 -2
  391. package/dist/tools/GlobTool/GlobTool.js +4 -2
  392. package/dist/tools/GlobTool/GlobTool.js.map +2 -2
  393. package/dist/tools/GrepTool/GrepTool.js +36 -7
  394. package/dist/tools/GrepTool/GrepTool.js.map +2 -2
  395. package/dist/tools/KillShellTool/KillShellToolResultMessage.js +3 -0
  396. package/dist/tools/KillShellTool/KillShellToolResultMessage.js.map +2 -2
  397. package/dist/tools/ListMcpResourcesTool/ListMcpResourcesTool.js +109 -0
  398. package/dist/tools/ListMcpResourcesTool/ListMcpResourcesTool.js.map +7 -0
  399. package/dist/tools/ListMcpResourcesTool/prompt.js +19 -0
  400. package/dist/tools/ListMcpResourcesTool/prompt.js.map +7 -0
  401. package/dist/tools/LspTool/LspTool.js +664 -0
  402. package/dist/tools/LspTool/LspTool.js.map +7 -0
  403. package/dist/tools/LspTool/prompt.js +27 -0
  404. package/dist/tools/LspTool/prompt.js.map +7 -0
  405. package/dist/tools/MCPTool/MCPTool.js +9 -1
  406. package/dist/tools/MCPTool/MCPTool.js.map +2 -2
  407. package/dist/tools/MemoryReadTool/MemoryReadTool.js +19 -6
  408. package/dist/tools/MemoryReadTool/MemoryReadTool.js.map +2 -2
  409. package/dist/tools/MemoryWriteTool/MemoryWriteTool.js +6 -6
  410. package/dist/tools/MemoryWriteTool/MemoryWriteTool.js.map +2 -2
  411. package/dist/tools/MultiEditTool/MultiEditTool.js +19 -2
  412. package/dist/tools/MultiEditTool/MultiEditTool.js.map +2 -2
  413. package/dist/tools/MultiEditTool/prompt.js +5 -3
  414. package/dist/tools/MultiEditTool/prompt.js.map +2 -2
  415. package/dist/tools/NotebookEditTool/NotebookEditTool.js +7 -2
  416. package/dist/tools/NotebookEditTool/NotebookEditTool.js.map +2 -2
  417. package/dist/tools/NotebookReadTool/NotebookReadTool.js.map +2 -2
  418. package/dist/tools/PlanModeTool/EnterPlanModeTool.js +75 -0
  419. package/dist/tools/PlanModeTool/EnterPlanModeTool.js.map +7 -0
  420. package/dist/tools/PlanModeTool/ExitPlanModeTool.js +109 -0
  421. package/dist/tools/PlanModeTool/ExitPlanModeTool.js.map +7 -0
  422. package/dist/tools/PlanModeTool/prompt.js +94 -0
  423. package/dist/tools/PlanModeTool/prompt.js.map +7 -0
  424. package/dist/tools/ReadMcpResourceTool/ReadMcpResourceTool.js +130 -0
  425. package/dist/tools/ReadMcpResourceTool/ReadMcpResourceTool.js.map +7 -0
  426. package/dist/tools/ReadMcpResourceTool/prompt.js +17 -0
  427. package/dist/tools/ReadMcpResourceTool/prompt.js.map +7 -0
  428. package/dist/tools/SkillTool/SkillTool.js +10 -4
  429. package/dist/tools/SkillTool/SkillTool.js.map +2 -2
  430. package/dist/tools/SkillTool/prompt.js +1 -1
  431. package/dist/tools/SkillTool/prompt.js.map +1 -1
  432. package/dist/tools/SlashCommandTool/SlashCommandTool.js +260 -0
  433. package/dist/tools/SlashCommandTool/SlashCommandTool.js.map +7 -0
  434. package/dist/tools/SlashCommandTool/prompt.js +35 -0
  435. package/dist/tools/SlashCommandTool/prompt.js.map +7 -0
  436. package/dist/tools/TaskOutputTool/TaskOutputTool.js +190 -0
  437. package/dist/tools/TaskOutputTool/TaskOutputTool.js.map +7 -0
  438. package/dist/tools/TaskOutputTool/prompt.js +15 -0
  439. package/dist/tools/TaskOutputTool/prompt.js.map +7 -0
  440. package/dist/tools/TaskTool/TaskTool.js +310 -104
  441. package/dist/tools/TaskTool/TaskTool.js.map +2 -2
  442. package/dist/tools/TaskTool/prompt.js.map +2 -2
  443. package/dist/tools/TodoWriteTool/TodoWriteTool.js +42 -77
  444. package/dist/tools/TodoWriteTool/TodoWriteTool.js.map +2 -2
  445. package/dist/tools/URLFetcherTool/URLFetcherTool.js +4 -1
  446. package/dist/tools/URLFetcherTool/URLFetcherTool.js.map +2 -2
  447. package/dist/tools/URLFetcherTool/cache.js +55 -8
  448. package/dist/tools/URLFetcherTool/cache.js.map +2 -2
  449. package/dist/tools.js +31 -2
  450. package/dist/tools.js.map +2 -2
  451. package/dist/types/hooks.js +4 -0
  452. package/dist/types/hooks.js.map +2 -2
  453. package/dist/types/marketplace.js.map +2 -2
  454. package/dist/types/messageGroup.js +36 -0
  455. package/dist/types/messageGroup.js.map +7 -0
  456. package/dist/types/plugin.js.map +2 -2
  457. package/dist/types/thinking.js +1 -0
  458. package/dist/types/thinking.js.map +7 -0
  459. package/dist/utils/BackgroundShellManager.js +136 -39
  460. package/dist/utils/BackgroundShellManager.js.map +2 -2
  461. package/dist/utils/CircuitBreaker.js +242 -0
  462. package/dist/utils/CircuitBreaker.js.map +7 -0
  463. package/dist/utils/MessageBatchBuffer.js +102 -0
  464. package/dist/utils/MessageBatchBuffer.js.map +7 -0
  465. package/dist/utils/PersistentShell.js +151 -1
  466. package/dist/utils/PersistentShell.js.map +2 -2
  467. package/dist/utils/agentLoader.js +1 -23
  468. package/dist/utils/agentLoader.js.map +2 -2
  469. package/dist/utils/agentTranscripts.js +641 -0
  470. package/dist/utils/agentTranscripts.js.map +7 -0
  471. package/dist/utils/animationManager.js +213 -0
  472. package/dist/utils/animationManager.js.map +7 -0
  473. package/dist/utils/animationSync.js +110 -0
  474. package/dist/utils/animationSync.js.map +7 -0
  475. package/dist/utils/ask.js +2 -0
  476. package/dist/utils/ask.js.map +2 -2
  477. package/dist/utils/asyncFile.js +215 -0
  478. package/dist/utils/asyncFile.js.map +7 -0
  479. package/dist/utils/backgroundAgentManager.js +231 -0
  480. package/dist/utils/backgroundAgentManager.js.map +7 -0
  481. package/dist/utils/config.js +108 -10
  482. package/dist/utils/config.js.map +2 -2
  483. package/dist/utils/conversationRecovery.js +19 -0
  484. package/dist/utils/conversationRecovery.js.map +2 -2
  485. package/dist/utils/credentials/CredentialStore.js +1 -0
  486. package/dist/utils/credentials/CredentialStore.js.map +7 -0
  487. package/dist/utils/credentials/EncryptedFileStore.js +157 -0
  488. package/dist/utils/credentials/EncryptedFileStore.js.map +7 -0
  489. package/dist/utils/credentials/index.js +37 -0
  490. package/dist/utils/credentials/index.js.map +7 -0
  491. package/dist/utils/credentials/migration.js +82 -0
  492. package/dist/utils/credentials/migration.js.map +7 -0
  493. package/dist/utils/exit.js +73 -0
  494. package/dist/utils/exit.js.map +7 -0
  495. package/dist/utils/format.js +73 -5
  496. package/dist/utils/format.js.map +2 -2
  497. package/dist/utils/generators.js +76 -6
  498. package/dist/utils/generators.js.map +2 -2
  499. package/dist/utils/globalErrorHandler.js +149 -0
  500. package/dist/utils/globalErrorHandler.js.map +7 -0
  501. package/dist/utils/groupHandlers/index.js +8 -0
  502. package/dist/utils/groupHandlers/index.js.map +7 -0
  503. package/dist/utils/groupHandlers/parallelTasksHandler.js +140 -0
  504. package/dist/utils/groupHandlers/parallelTasksHandler.js.map +7 -0
  505. package/dist/utils/groupHandlers/taskHandler.js +104 -0
  506. package/dist/utils/groupHandlers/taskHandler.js.map +7 -0
  507. package/dist/utils/groupHandlers/types.js +1 -0
  508. package/dist/utils/groupHandlers/types.js.map +7 -0
  509. package/dist/utils/logRotation.js +224 -0
  510. package/dist/utils/logRotation.js.map +7 -0
  511. package/dist/utils/markdown.js +13 -1
  512. package/dist/utils/markdown.js.map +2 -2
  513. package/dist/utils/marketplaceManager.js +3 -5
  514. package/dist/utils/marketplaceManager.js.map +2 -2
  515. package/dist/utils/memSafety.js +264 -0
  516. package/dist/utils/memSafety.js.map +7 -0
  517. package/dist/utils/messageGroupManager.js +274 -0
  518. package/dist/utils/messageGroupManager.js.map +7 -0
  519. package/dist/utils/messages.js +13 -4
  520. package/dist/utils/messages.js.map +2 -2
  521. package/dist/utils/model.js +119 -15
  522. package/dist/utils/model.js.map +3 -3
  523. package/dist/utils/permissions/filesystem.js +162 -6
  524. package/dist/utils/permissions/filesystem.js.map +2 -2
  525. package/dist/utils/plan/planMode.js +143 -0
  526. package/dist/utils/plan/planMode.js.map +7 -0
  527. package/dist/utils/pluginLoader.js +17 -21
  528. package/dist/utils/pluginLoader.js.map +2 -2
  529. package/dist/utils/ripgrep.js +55 -2
  530. package/dist/utils/ripgrep.js.map +2 -2
  531. package/dist/utils/safePath.js +132 -0
  532. package/dist/utils/safePath.js.map +7 -0
  533. package/dist/utils/sanitizeInput.js +32 -0
  534. package/dist/utils/sanitizeInput.js.map +7 -0
  535. package/dist/utils/secureKeyStorage.js +312 -0
  536. package/dist/utils/secureKeyStorage.js.map +7 -0
  537. package/dist/utils/sensitiveFiles.js +125 -0
  538. package/dist/utils/sensitiveFiles.js.map +7 -0
  539. package/dist/utils/session/sessionPlugins.js +67 -0
  540. package/dist/utils/session/sessionPlugins.js.map +7 -0
  541. package/dist/utils/taskDisplayUtils.js +257 -0
  542. package/dist/utils/taskDisplayUtils.js.map +7 -0
  543. package/dist/utils/teamConfig.js +2 -1
  544. package/dist/utils/teamConfig.js.map +2 -2
  545. package/dist/utils/theme.js +6 -6
  546. package/dist/utils/theme.js.map +1 -1
  547. package/dist/utils/todoStorage.js +92 -2
  548. package/dist/utils/todoStorage.js.map +2 -2
  549. package/dist/utils/toolRiskClassification.js +207 -0
  550. package/dist/utils/toolRiskClassification.js.map +7 -0
  551. package/dist/utils/toolTimeout.js +136 -0
  552. package/dist/utils/toolTimeout.js.map +7 -0
  553. package/dist/utils/tooling/safeRender.js +116 -0
  554. package/dist/utils/tooling/safeRender.js.map +7 -0
  555. package/dist/utils/userFriendlyError.js +346 -0
  556. package/dist/utils/userFriendlyError.js.map +7 -0
  557. package/dist/utils/vendor/ripgrep/arm64-darwin/rg +0 -0
  558. package/dist/version.js +2 -2
  559. package/dist/version.js.map +1 -1
  560. package/package.json +17 -5
  561. package/scripts/postinstall.js +128 -38
  562. package/dist/commands/agents.js +0 -2086
  563. package/dist/commands/agents.js.map +0 -7
  564. package/dist/commands/build.js +0 -74
  565. package/dist/commands/build.js.map +0 -7
  566. package/dist/commands/compression.js +0 -57
  567. package/dist/commands/compression.js.map +0 -7
  568. package/dist/commands/listen.js +0 -37
  569. package/dist/commands/listen.js.map +0 -7
  570. package/dist/commands/login.js +0 -37
  571. package/dist/commands/login.js.map +0 -7
  572. package/dist/commands/logout.js +0 -33
  573. package/dist/commands/logout.js.map +0 -7
  574. package/dist/commands/mcp.js +0 -40
  575. package/dist/commands/mcp.js.map +0 -7
  576. package/dist/commands/mcp_refresh.js +0 -40
  577. package/dist/commands/mcp_refresh.js.map +0 -7
  578. package/dist/commands/modelstatus.js +0 -21
  579. package/dist/commands/modelstatus.js.map +0 -7
  580. package/dist/commands/onboarding.js +0 -36
  581. package/dist/commands/onboarding.js.map +0 -7
  582. package/dist/commands/plugin-interactive.js +0 -446
  583. package/dist/commands/plugin-interactive.js.map +0 -7
  584. package/dist/commands/pr_comments.js +0 -61
  585. package/dist/commands/pr_comments.js.map +0 -7
  586. package/dist/commands/release-notes.js +0 -30
  587. package/dist/commands/release-notes.js.map +0 -7
  588. package/dist/commands/review.js +0 -51
  589. package/dist/commands/review.js.map +0 -7
  590. package/dist/components/Bug.js +0 -147
  591. package/dist/components/Bug.js.map +0 -7
  592. package/dist/components/ModelSelector.js +0 -2062
  593. package/dist/components/ModelSelector.js.map +0 -7
  594. package/dist/components/ModelStatusDisplay.js +0 -87
  595. package/dist/components/ModelStatusDisplay.js.map +0 -7
  596. package/dist/entrypoints/cli-wrapper.js +0 -61
  597. package/dist/entrypoints/cli-wrapper.js.map +0 -7
  598. package/dist/hooks/useCancelRequest.js +0 -28
  599. package/dist/hooks/useCancelRequest.js.map +0 -7
  600. package/dist/screens/Doctor.js +0 -22
  601. package/dist/screens/Doctor.js.map +0 -7
@@ -2,6 +2,7 @@ import { Box, Text } from "ink";
2
2
  import * as React from "react";
3
3
  import { Select } from "../CustomSelect/select.js";
4
4
  import { getTheme } from "../../utils/theme.js";
5
+ import { SEMANTIC_COLORS } from "../../constants/colors.js";
5
6
  function QuestionView({
6
7
  question,
7
8
  questionIndex,
@@ -37,7 +38,7 @@ function QuestionView({
37
38
  }
38
39
  }
39
40
  }
40
- )), question.options && question.options.length > 0 && selectedOptionIndex >= 0 && selectedOptionIndex < question.options.length && /* @__PURE__ */ React.createElement(Box, { marginLeft: 2, marginBottom: 1 }, /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText, dimColor: true }, question.options[selectedOptionIndex]?.description || "")), /* @__PURE__ */ React.createElement(
41
+ )), question.options && question.options.length > 0 && selectedOptionIndex >= 0 && selectedOptionIndex < question.options.length && /* @__PURE__ */ React.createElement(Box, { marginLeft: 2, marginBottom: 1 }, /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.dim }, question.options[selectedOptionIndex]?.description || "")), /* @__PURE__ */ React.createElement(
41
42
  Box,
42
43
  {
43
44
  marginTop: 1,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/components/AskUserQuestionDialog/QuestionView.tsx"],
4
- "sourcesContent": ["import { Box, Text } from 'ink'\nimport * as React from 'react'\nimport { Select } from '@components/CustomSelect/select'\nimport {\n type UserQuestion,\n type QuestionOption,\n} from '@minto-types/askUserQuestion'\nimport { Option } from '@inkjs/ui'\nimport { getTheme } from '@utils/theme'\n\ninterface QuestionViewProps {\n question: UserQuestion\n questionIndex: number\n totalQuestions: number\n selectedOptionIndex: number\n onOptionChange: (optionIndex: number) => void\n}\n\nexport function QuestionView({\n question,\n questionIndex,\n totalQuestions,\n selectedOptionIndex,\n onOptionChange,\n}: QuestionViewProps): React.ReactElement {\n const theme = getTheme()\n\n // Build options for the Select component\n const options: Option[] = React.useMemo(() => {\n if (!question.options || question.options.length === 0) {\n return []\n }\n\n const selectOptions = question.options.map((opt, index) => ({\n label: opt.label,\n value: String(index),\n }))\n\n // Always add \"Other (custom input)\" option\n selectOptions.push({\n label: 'Other (custom input)',\n value: 'other',\n })\n\n return selectOptions\n }, [question.options])\n\n return (\n <Box flexDirection=\"column\" paddingX={2} paddingY={1}>\n {/* Header with question counter */}\n <Box marginBottom={1}>\n <Text color={theme.primary} bold>\n \uD83E\uDD14 AI needs your input\n </Text>\n {totalQuestions > 1 && (\n <Text color={theme.secondaryText}>\n {' '}\n (Question {questionIndex + 1} of {totalQuestions})\n </Text>\n )}\n </Box>\n\n {/* Question header tag */}\n {question.header && (\n <Box marginBottom={1}>\n <Text color={theme.minto}>[{question.header}]</Text>\n </Box>\n )}\n\n {/* Question text */}\n <Box marginBottom={1}>\n <Text bold>{question.question}</Text>\n </Box>\n\n {/* Options list */}\n {question.options && question.options.length > 0 && (\n <Box marginBottom={1}>\n <Select\n options={options}\n defaultValue={String(selectedOptionIndex)}\n onChange={value => {\n if (value === 'other') {\n onOptionChange(-1) // -1 indicates \"Other\"\n } else {\n onOptionChange(Number(value))\n }\n }}\n />\n </Box>\n )}\n\n {/* Show option descriptions */}\n {question.options &&\n question.options.length > 0 &&\n selectedOptionIndex >= 0 &&\n selectedOptionIndex < question.options.length && (\n <Box marginLeft={2} marginBottom={1}>\n <Text color={theme.secondaryText} dimColor>\n {question.options[selectedOptionIndex]?.description || ''}\n </Text>\n </Box>\n )}\n\n {/* Help text */}\n <Box\n marginTop={1}\n borderStyle=\"single\"\n borderColor={theme.secondaryBorder}\n paddingX={1}\n >\n <Text color={theme.secondaryText}>\n [\u2191/\u2193 Navigate] [Enter Confirm]\n {totalQuestions > 1 && ' [\u2190/\u2192 Switch Questions]'} [Esc Cancel]\n </Text>\n </Box>\n </Box>\n )\n}\n"],
5
- "mappings": "AAAA,SAAS,KAAK,YAAY;AAC1B,YAAY,WAAW;AACvB,SAAS,cAAc;AAMvB,SAAS,gBAAgB;AAUlB,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA0C;AACxC,QAAM,QAAQ,SAAS;AAGvB,QAAM,UAAoB,MAAM,QAAQ,MAAM;AAC5C,QAAI,CAAC,SAAS,WAAW,SAAS,QAAQ,WAAW,GAAG;AACtD,aAAO,CAAC;AAAA,IACV;AAEA,UAAM,gBAAgB,SAAS,QAAQ,IAAI,CAAC,KAAK,WAAW;AAAA,MAC1D,OAAO,IAAI;AAAA,MACX,OAAO,OAAO,KAAK;AAAA,IACrB,EAAE;AAGF,kBAAc,KAAK;AAAA,MACjB,OAAO;AAAA,MACP,OAAO;AAAA,IACT,CAAC;AAED,WAAO;AAAA,EACT,GAAG,CAAC,SAAS,OAAO,CAAC;AAErB,SACE,oCAAC,OAAI,eAAc,UAAS,UAAU,GAAG,UAAU,KAEjD,oCAAC,OAAI,cAAc,KACjB,oCAAC,QAAK,OAAO,MAAM,SAAS,MAAI,QAAC,+BAEjC,GACC,iBAAiB,KAChB,oCAAC,QAAK,OAAO,MAAM,iBAChB,KAAI,cACM,gBAAgB,GAAE,QAAK,gBAAe,GACnD,CAEJ,GAGC,SAAS,UACR,oCAAC,OAAI,cAAc,KACjB,oCAAC,QAAK,OAAO,MAAM,SAAO,KAAE,SAAS,QAAO,GAAC,CAC/C,GAIF,oCAAC,OAAI,cAAc,KACjB,oCAAC,QAAK,MAAI,QAAE,SAAS,QAAS,CAChC,GAGC,SAAS,WAAW,SAAS,QAAQ,SAAS,KAC7C,oCAAC,OAAI,cAAc,KACjB;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,cAAc,OAAO,mBAAmB;AAAA,MACxC,UAAU,WAAS;AACjB,YAAI,UAAU,SAAS;AACrB,yBAAe,EAAE;AAAA,QACnB,OAAO;AACL,yBAAe,OAAO,KAAK,CAAC;AAAA,QAC9B;AAAA,MACF;AAAA;AAAA,EACF,CACF,GAID,SAAS,WACR,SAAS,QAAQ,SAAS,KAC1B,uBAAuB,KACvB,sBAAsB,SAAS,QAAQ,UACrC,oCAAC,OAAI,YAAY,GAAG,cAAc,KAChC,oCAAC,QAAK,OAAO,MAAM,eAAe,UAAQ,QACvC,SAAS,QAAQ,mBAAmB,GAAG,eAAe,EACzD,CACF,GAIJ;AAAA,IAAC;AAAA;AAAA,MACC,WAAW;AAAA,MACX,aAAY;AAAA,MACZ,aAAa,MAAM;AAAA,MACnB,UAAU;AAAA;AAAA,IAEV,oCAAC,QAAK,OAAO,MAAM,iBAAe,4CAE/B,iBAAiB,KAAK,qCAA0B,eACnD;AAAA,EACF,CACF;AAEJ;",
4
+ "sourcesContent": ["import { Box, Text } from 'ink'\nimport * as React from 'react'\nimport { Select } from '@components/CustomSelect/select'\nimport {\n type UserQuestion,\n type QuestionOption,\n} from '@minto-types/askUserQuestion'\nimport { Option } from '@inkjs/ui'\nimport { getTheme } from '@utils/theme'\nimport { SEMANTIC_COLORS } from '@constants/colors'\n\ninterface QuestionViewProps {\n question: UserQuestion\n questionIndex: number\n totalQuestions: number\n selectedOptionIndex: number\n onOptionChange: (optionIndex: number) => void\n}\n\nexport function QuestionView({\n question,\n questionIndex,\n totalQuestions,\n selectedOptionIndex,\n onOptionChange,\n}: QuestionViewProps): React.ReactElement {\n const theme = getTheme()\n\n // Build options for the Select component\n const options: Option[] = React.useMemo(() => {\n if (!question.options || question.options.length === 0) {\n return []\n }\n\n const selectOptions = question.options.map((opt, index) => ({\n label: opt.label,\n value: String(index),\n }))\n\n // Always add \"Other (custom input)\" option\n selectOptions.push({\n label: 'Other (custom input)',\n value: 'other',\n })\n\n return selectOptions\n }, [question.options])\n\n return (\n <Box flexDirection=\"column\" paddingX={2} paddingY={1}>\n {/* Header with question counter */}\n <Box marginBottom={1}>\n <Text color={theme.primary} bold>\n \uD83E\uDD14 AI needs your input\n </Text>\n {totalQuestions > 1 && (\n <Text color={theme.secondaryText}>\n {' '}\n (Question {questionIndex + 1} of {totalQuestions})\n </Text>\n )}\n </Box>\n\n {/* Question header tag */}\n {question.header && (\n <Box marginBottom={1}>\n <Text color={theme.minto}>[{question.header}]</Text>\n </Box>\n )}\n\n {/* Question text */}\n <Box marginBottom={1}>\n <Text bold>{question.question}</Text>\n </Box>\n\n {/* Options list */}\n {question.options && question.options.length > 0 && (\n <Box marginBottom={1}>\n <Select\n options={options}\n defaultValue={String(selectedOptionIndex)}\n onChange={value => {\n if (value === 'other') {\n onOptionChange(-1) // -1 indicates \"Other\"\n } else {\n onOptionChange(Number(value))\n }\n }}\n />\n </Box>\n )}\n\n {/* Show option descriptions */}\n {question.options &&\n question.options.length > 0 &&\n selectedOptionIndex >= 0 &&\n selectedOptionIndex < question.options.length && (\n <Box marginLeft={2} marginBottom={1}>\n <Text color={SEMANTIC_COLORS.dim}>\n {question.options[selectedOptionIndex]?.description || ''}\n </Text>\n </Box>\n )}\n\n {/* Help text */}\n <Box\n marginTop={1}\n borderStyle=\"single\"\n borderColor={theme.secondaryBorder}\n paddingX={1}\n >\n <Text color={theme.secondaryText}>\n [\u2191/\u2193 Navigate] [Enter Confirm]\n {totalQuestions > 1 && ' [\u2190/\u2192 Switch Questions]'} [Esc Cancel]\n </Text>\n </Box>\n </Box>\n )\n}\n"],
5
+ "mappings": "AAAA,SAAS,KAAK,YAAY;AAC1B,YAAY,WAAW;AACvB,SAAS,cAAc;AAMvB,SAAS,gBAAgB;AACzB,SAAS,uBAAuB;AAUzB,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA0C;AACxC,QAAM,QAAQ,SAAS;AAGvB,QAAM,UAAoB,MAAM,QAAQ,MAAM;AAC5C,QAAI,CAAC,SAAS,WAAW,SAAS,QAAQ,WAAW,GAAG;AACtD,aAAO,CAAC;AAAA,IACV;AAEA,UAAM,gBAAgB,SAAS,QAAQ,IAAI,CAAC,KAAK,WAAW;AAAA,MAC1D,OAAO,IAAI;AAAA,MACX,OAAO,OAAO,KAAK;AAAA,IACrB,EAAE;AAGF,kBAAc,KAAK;AAAA,MACjB,OAAO;AAAA,MACP,OAAO;AAAA,IACT,CAAC;AAED,WAAO;AAAA,EACT,GAAG,CAAC,SAAS,OAAO,CAAC;AAErB,SACE,oCAAC,OAAI,eAAc,UAAS,UAAU,GAAG,UAAU,KAEjD,oCAAC,OAAI,cAAc,KACjB,oCAAC,QAAK,OAAO,MAAM,SAAS,MAAI,QAAC,+BAEjC,GACC,iBAAiB,KAChB,oCAAC,QAAK,OAAO,MAAM,iBAChB,KAAI,cACM,gBAAgB,GAAE,QAAK,gBAAe,GACnD,CAEJ,GAGC,SAAS,UACR,oCAAC,OAAI,cAAc,KACjB,oCAAC,QAAK,OAAO,MAAM,SAAO,KAAE,SAAS,QAAO,GAAC,CAC/C,GAIF,oCAAC,OAAI,cAAc,KACjB,oCAAC,QAAK,MAAI,QAAE,SAAS,QAAS,CAChC,GAGC,SAAS,WAAW,SAAS,QAAQ,SAAS,KAC7C,oCAAC,OAAI,cAAc,KACjB;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,cAAc,OAAO,mBAAmB;AAAA,MACxC,UAAU,WAAS;AACjB,YAAI,UAAU,SAAS;AACrB,yBAAe,EAAE;AAAA,QACnB,OAAO;AACL,yBAAe,OAAO,KAAK,CAAC;AAAA,QAC9B;AAAA,MACF;AAAA;AAAA,EACF,CACF,GAID,SAAS,WACR,SAAS,QAAQ,SAAS,KAC1B,uBAAuB,KACvB,sBAAsB,SAAS,QAAQ,UACrC,oCAAC,OAAI,YAAY,GAAG,cAAc,KAChC,oCAAC,QAAK,OAAO,gBAAgB,OAC1B,SAAS,QAAQ,mBAAmB,GAAG,eAAe,EACzD,CACF,GAIJ;AAAA,IAAC;AAAA;AAAA,MACC,WAAW;AAAA,MACX,aAAY;AAAA,MACZ,aAAa,MAAM;AAAA,MACnB,UAAU;AAAA;AAAA,IAEV,oCAAC,QAAK,OAAO,MAAM,iBAAe,4CAE/B,iBAAiB,KAAK,qCAA0B,eACnD;AAAA,EACF,CACF;AAEJ;",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,12 @@
1
1
  import { Box, Text, useInput } from "ink";
2
2
  import * as React from "react";
3
- import { useState, useEffect } from "react";
3
+ import { useState, useEffect, useCallback } from "react";
4
4
  import { getTheme } from "../utils/theme.js";
5
+ import {
6
+ getAllBackgroundAgents,
7
+ cancelBackgroundAgent,
8
+ backgroundAgentEvents
9
+ } from "../utils/backgroundAgentManager.js";
5
10
  function BackgroundTasksPanel({
6
11
  shells,
7
12
  isVisible,
@@ -10,38 +15,51 @@ function BackgroundTasksPanel({
10
15
  onClose
11
16
  }) {
12
17
  const [selectedIndex, setSelectedIndex] = useState(0);
18
+ const [agents, setAgents] = useState([]);
13
19
  const theme = getTheme();
14
20
  useEffect(() => {
15
- if (selectedIndex >= shells.length && shells.length > 0) {
16
- setSelectedIndex(shells.length - 1);
21
+ setAgents(getAllBackgroundAgents());
22
+ const unsubscribe = backgroundAgentEvents.onStatusChange(() => {
23
+ setAgents(getAllBackgroundAgents());
24
+ });
25
+ return unsubscribe;
26
+ }, []);
27
+ const tasks = [
28
+ ...shells.map((shell) => ({ type: "shell", data: shell })),
29
+ ...agents.map((agent) => ({ type: "agent", data: agent }))
30
+ ];
31
+ useEffect(() => {
32
+ if (selectedIndex >= tasks.length && tasks.length > 0) {
33
+ setSelectedIndex(tasks.length - 1);
34
+ }
35
+ }, [tasks.length, selectedIndex]);
36
+ const handleKillSelected = useCallback(() => {
37
+ const selected = tasks[selectedIndex];
38
+ if (!selected) return;
39
+ if (selected.type === "shell") {
40
+ onKill(selected.data);
41
+ } else if (selected.type === "agent") {
42
+ cancelBackgroundAgent(selected.data.agentId);
43
+ }
44
+ if (selectedIndex >= tasks.length - 1 && tasks.length > 1) {
45
+ setSelectedIndex(tasks.length - 2);
17
46
  }
18
- }, [shells.length, selectedIndex]);
47
+ }, [tasks, selectedIndex, onKill]);
19
48
  useInput(
20
49
  (input, key) => {
21
50
  if (key.upArrow) {
22
51
  setSelectedIndex((prev) => Math.max(0, prev - 1));
23
52
  } else if (key.downArrow) {
24
- setSelectedIndex((prev) => Math.min(shells.length - 1, prev + 1));
53
+ setSelectedIndex((prev) => Math.min(tasks.length - 1, prev + 1));
25
54
  } else if (key.return) {
26
- const selected = shells[selectedIndex];
27
- if (selected) onSelect(selected);
28
- } else if (input === "k" || input === "K") {
29
- const selected = shells[selectedIndex];
30
- if (selected) {
31
- console.log(
32
- "[BackgroundTasksPanel] Killing shell:",
33
- selected.id,
34
- selected.command
35
- );
36
- onKill(selected);
37
- if (selectedIndex >= shells.length - 1 && shells.length > 1) {
38
- setSelectedIndex(shells.length - 2);
39
- }
55
+ const selected = tasks[selectedIndex];
56
+ if (selected?.type === "shell") {
57
+ onSelect(selected.data);
40
58
  }
59
+ } else if (input === "k" || input === "K") {
60
+ handleKillSelected();
41
61
  } else if (key.escape) {
42
62
  onClose();
43
- } else {
44
- console.log("[BackgroundTasksPanel] Unhandled input:", { input, key });
45
63
  }
46
64
  },
47
65
  { isActive: isVisible }
@@ -73,15 +91,36 @@ function BackgroundTasksPanel({
73
91
  case "running":
74
92
  return "\u25B6";
75
93
  case "done":
94
+ case "completed":
76
95
  return "\u2713";
77
96
  case "killed":
97
+ case "cancelled":
78
98
  return "\u2717";
99
+ case "failed":
100
+ return "!";
79
101
  default:
80
102
  return "\u2022";
81
103
  }
82
104
  };
83
- const activeCount = shells.filter((s) => s.status === "running").length;
84
- const countText = activeCount === 1 ? "1 active shell" : `${activeCount} active shells`;
105
+ const getTypeIcon = (task) => {
106
+ return task.type === "shell" ? ">" : "\u2699";
107
+ };
108
+ const activeShellCount = shells.filter((s) => s.status === "running").length;
109
+ const activeAgentCount = agents.filter((a) => a.status === "running").length;
110
+ const totalActive = activeShellCount + activeAgentCount;
111
+ let countText = "";
112
+ if (totalActive === 0) {
113
+ countText = "No active tasks";
114
+ } else {
115
+ const parts = [];
116
+ if (activeShellCount > 0) {
117
+ parts.push(`${activeShellCount} shell${activeShellCount > 1 ? "s" : ""}`);
118
+ }
119
+ if (activeAgentCount > 0) {
120
+ parts.push(`${activeAgentCount} agent${activeAgentCount > 1 ? "s" : ""}`);
121
+ }
122
+ countText = parts.join(", ") + " running";
123
+ }
85
124
  return /* @__PURE__ */ React.createElement(
86
125
  Box,
87
126
  {
@@ -94,19 +133,24 @@ function BackgroundTasksPanel({
94
133
  /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { bold: true, color: theme.primary }, "Background tasks")),
95
134
  /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, countText)),
96
135
  /* @__PURE__ */ React.createElement(Box, { height: 1 }),
97
- shells.length === 0 ? /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, "(No background tasks)")) : shells.map((shell, index) => {
136
+ tasks.length === 0 ? /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, "(No background tasks)")) : tasks.map((task, index) => {
98
137
  const isSelected = index === selectedIndex;
99
138
  const bgColor = isSelected ? "cyan" : void 0;
100
- const duration = formatDuration(shell.startTime, shell.endTime);
101
- const summary = getSummary(shell);
102
- return /* @__PURE__ */ React.createElement(Box, { key: shell.id }, /* @__PURE__ */ React.createElement(
139
+ const status = task.type === "shell" ? task.data.status : task.data.status;
140
+ const startTime = task.data.startTime;
141
+ const endTime = task.type === "shell" ? task.data.endTime : task.data.endTime;
142
+ const id = task.type === "shell" ? task.data.id : task.data.agentId;
143
+ const duration = formatDuration(startTime, endTime);
144
+ const summary = task.type === "shell" ? getShellSummary(task.data) : getAgentSummary(task.data);
145
+ return /* @__PURE__ */ React.createElement(Box, { key: `${task.type}-${id}` }, /* @__PURE__ */ React.createElement(
103
146
  Text,
104
147
  {
105
148
  backgroundColor: bgColor,
106
149
  color: isSelected ? "black" : theme.primary
107
150
  },
108
151
  isSelected ? "\u276F " : " ",
109
- /* @__PURE__ */ React.createElement(Text, { color: getStatusColor(shell.status) }, getStatusIcon(shell.status), " "),
152
+ /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, getTypeIcon(task), " "),
153
+ /* @__PURE__ */ React.createElement(Text, { color: getStatusColor(status) }, getStatusIcon(status), " "),
110
154
  summary,
111
155
  /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, " [", duration, "]")
112
156
  ));
@@ -115,13 +159,18 @@ function BackgroundTasksPanel({
115
159
  /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, "\u2191/\u2193 to select \xB7 Enter to view \xB7 k to kill \xB7 Esc to close"))
116
160
  );
117
161
  }
118
- function getSummary(shell) {
162
+ function getShellSummary(shell) {
119
163
  const maxCmdLen = 40;
120
164
  const cmd = shell.command.length > maxCmdLen ? shell.command.slice(0, maxCmdLen) + "\u2026" : shell.command;
121
165
  const lastLine = shell.stdout[shell.stdout.length - 1] || "";
122
166
  const preview = lastLine.slice(0, 30);
123
167
  return preview ? `${cmd} ${preview}\u2026` : cmd;
124
168
  }
169
+ function getAgentSummary(agent) {
170
+ const maxLen = 50;
171
+ const desc = agent.description.length > maxLen ? agent.description.slice(0, maxLen) + "\u2026" : agent.description;
172
+ return `[${agent.agentType}] ${desc}`;
173
+ }
125
174
  export {
126
175
  BackgroundTasksPanel
127
176
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/components/BackgroundTasksPanel.tsx"],
4
- "sourcesContent": ["import { Box, Text, useInput } from 'ink'\nimport * as React from 'react'\nimport { useState, useEffect } from 'react'\nimport { getTheme } from '@utils/theme'\nimport type { BackgroundShell } from '@utils/BackgroundShellManager'\n\ntype Props = {\n shells: BackgroundShell[]\n isVisible: boolean\n onSelect: (shell: BackgroundShell) => void\n onKill: (shell: BackgroundShell) => void\n onClose: () => void\n}\n\nexport function BackgroundTasksPanel({\n shells,\n isVisible,\n onSelect,\n onKill,\n onClose,\n}: Props) {\n const [selectedIndex, setSelectedIndex] = useState(0)\n const theme = getTheme()\n\n // Reset selection when shells list changes\n useEffect(() => {\n if (selectedIndex >= shells.length && shells.length > 0) {\n setSelectedIndex(shells.length - 1)\n }\n }, [shells.length, selectedIndex])\n\n useInput(\n (input, key) => {\n if (key.upArrow) {\n setSelectedIndex(prev => Math.max(0, prev - 1))\n } else if (key.downArrow) {\n setSelectedIndex(prev => Math.min(shells.length - 1, prev + 1))\n } else if (key.return) {\n const selected = shells[selectedIndex]\n if (selected) onSelect(selected)\n } else if (input === 'k' || input === 'K') {\n const selected = shells[selectedIndex]\n if (selected) {\n console.log(\n '[BackgroundTasksPanel] Killing shell:',\n selected.id,\n selected.command,\n )\n onKill(selected)\n // Update selection if we killed the last item\n if (selectedIndex >= shells.length - 1 && shells.length > 1) {\n setSelectedIndex(shells.length - 2)\n }\n }\n } else if (key.escape) {\n onClose()\n } else {\n // Debug: log unhandled input\n console.log('[BackgroundTasksPanel] Unhandled input:', { input, key })\n }\n },\n { isActive: isVisible },\n )\n\n if (!isVisible) return null\n\n const formatDuration = (startTime: number, endTime?: number): string => {\n const duration = endTime ? endTime - startTime : Date.now() - startTime\n const seconds = Math.floor(duration / 1000)\n if (seconds < 60) return `${seconds}s`\n const minutes = Math.floor(seconds / 60)\n if (minutes < 60) return `${minutes}m ${seconds % 60}s`\n const hours = Math.floor(minutes / 60)\n return `${hours}h ${minutes % 60}m`\n }\n\n const getStatusColor = (status: string) => {\n switch (status) {\n case 'running':\n return theme.success\n case 'done':\n return theme.secondaryText\n case 'killed':\n return theme.error\n default:\n return theme.primary\n }\n }\n\n const getStatusIcon = (status: string) => {\n switch (status) {\n case 'running':\n return '\u25B6'\n case 'done':\n return '\u2713'\n case 'killed':\n return '\u2717'\n default:\n return '\u2022'\n }\n }\n\n const activeCount = shells.filter(s => s.status === 'running').length\n const countText =\n activeCount === 1 ? '1 active shell' : `${activeCount} active shells`\n\n return (\n <Box\n flexDirection=\"column\"\n borderStyle=\"single\"\n borderColor={theme.secondaryBorder}\n paddingX={1}\n marginBottom={1}\n >\n <Box>\n <Text bold color={theme.primary}>\n Background tasks\n </Text>\n </Box>\n <Box>\n <Text color={theme.secondaryText}>{countText}</Text>\n </Box>\n <Box height={1} />\n\n {shells.length === 0 ? (\n <Box>\n <Text color={theme.secondaryText}>(No background tasks)</Text>\n </Box>\n ) : (\n shells.map((shell, index) => {\n const isSelected = index === selectedIndex\n const bgColor = isSelected ? 'cyan' : undefined\n const duration = formatDuration(shell.startTime, shell.endTime)\n const summary = getSummary(shell)\n\n return (\n <Box key={shell.id}>\n <Text\n backgroundColor={bgColor}\n color={isSelected ? 'black' : theme.primary}\n >\n {isSelected ? '\u276F ' : ' '}\n <Text color={getStatusColor(shell.status)}>\n {getStatusIcon(shell.status)}{' '}\n </Text>\n {summary}\n <Text color={theme.secondaryText}> [{duration}]</Text>\n </Text>\n </Box>\n )\n })\n )}\n\n <Box height={1} />\n <Box>\n <Text color={theme.secondaryText}>\n \u2191/\u2193 to select \u00B7 Enter to view \u00B7 k to kill \u00B7 Esc to close\n </Text>\n </Box>\n </Box>\n )\n}\n\nfunction getSummary(shell: BackgroundShell): string {\n // Get command (truncate if too long)\n const maxCmdLen = 40\n const cmd =\n shell.command.length > maxCmdLen\n ? shell.command.slice(0, maxCmdLen) + '\u2026'\n : shell.command\n\n // Get last few lines of output for preview\n const lastLine = shell.stdout[shell.stdout.length - 1] || ''\n const preview = lastLine.slice(0, 30)\n\n return preview ? `${cmd} ${preview}\u2026` : cmd\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { Box, Text, useInput } from 'ink'\nimport * as React from 'react'\nimport { useState, useEffect, useCallback } from 'react'\nimport { getTheme } from '@utils/theme'\nimport type { BackgroundShell } from '@utils/BackgroundShellManager'\nimport {\n type BackgroundAgentInfo,\n getAllBackgroundAgents,\n cancelBackgroundAgent,\n backgroundAgentEvents,\n} from '@utils/backgroundAgentManager'\n\n/**\n * Unified background task type for both shells and agents\n */\nexport type BackgroundTask =\n | { type: 'shell'; data: BackgroundShell }\n | { type: 'agent'; data: BackgroundAgentInfo }\n\ntype Props = {\n shells: BackgroundShell[]\n isVisible: boolean\n onSelect: (shell: BackgroundShell) => void\n onKill: (shell: BackgroundShell) => void\n onClose: () => void\n}\n\nexport function BackgroundTasksPanel({\n shells,\n isVisible,\n onSelect,\n onKill,\n onClose,\n}: Props) {\n const [selectedIndex, setSelectedIndex] = useState(0)\n const [agents, setAgents] = useState<BackgroundAgentInfo[]>([])\n const theme = getTheme()\n\n // Subscribe to background agent events for real-time updates\n useEffect(() => {\n // Initialize with current agents\n setAgents(getAllBackgroundAgents())\n\n // Subscribe to status changes\n const unsubscribe = backgroundAgentEvents.onStatusChange(() => {\n setAgents(getAllBackgroundAgents())\n })\n\n return unsubscribe\n }, [])\n\n // Combine shells and agents into unified task list\n const tasks: BackgroundTask[] = [\n ...shells.map(shell => ({ type: 'shell' as const, data: shell })),\n ...agents.map(agent => ({ type: 'agent' as const, data: agent })),\n ]\n\n // Reset selection when task list changes\n useEffect(() => {\n if (selectedIndex >= tasks.length && tasks.length > 0) {\n setSelectedIndex(tasks.length - 1)\n }\n }, [tasks.length, selectedIndex])\n\n // Handle killing the selected task\n const handleKillSelected = useCallback(() => {\n const selected = tasks[selectedIndex]\n if (!selected) return\n\n if (selected.type === 'shell') {\n onKill(selected.data)\n } else if (selected.type === 'agent') {\n cancelBackgroundAgent(selected.data.agentId)\n }\n\n // Update selection if we killed the last item\n if (selectedIndex >= tasks.length - 1 && tasks.length > 1) {\n setSelectedIndex(tasks.length - 2)\n }\n }, [tasks, selectedIndex, onKill])\n\n useInput(\n (input, key) => {\n if (key.upArrow) {\n setSelectedIndex(prev => Math.max(0, prev - 1))\n } else if (key.downArrow) {\n setSelectedIndex(prev => Math.min(tasks.length - 1, prev + 1))\n } else if (key.return) {\n const selected = tasks[selectedIndex]\n if (selected?.type === 'shell') {\n onSelect(selected.data)\n }\n // Agent selection could be added later for viewing results\n } else if (input === 'k' || input === 'K') {\n handleKillSelected()\n } else if (key.escape) {\n onClose()\n }\n },\n { isActive: isVisible },\n )\n\n if (!isVisible) return null\n\n const formatDuration = (startTime: number, endTime?: number): string => {\n const duration = endTime ? endTime - startTime : Date.now() - startTime\n const seconds = Math.floor(duration / 1000)\n if (seconds < 60) return `${seconds}s`\n const minutes = Math.floor(seconds / 60)\n if (minutes < 60) return `${minutes}m ${seconds % 60}s`\n const hours = Math.floor(minutes / 60)\n return `${hours}h ${minutes % 60}m`\n }\n\n const getStatusColor = (status: string) => {\n switch (status) {\n case 'running':\n return theme.success\n case 'done':\n return theme.secondaryText\n case 'killed':\n return theme.error\n default:\n return theme.primary\n }\n }\n\n const getStatusIcon = (status: string) => {\n switch (status) {\n case 'running':\n return '\u25B6'\n case 'done':\n case 'completed':\n return '\u2713'\n case 'killed':\n case 'cancelled':\n return '\u2717'\n case 'failed':\n return '!'\n default:\n return '\u2022'\n }\n }\n\n // Get task type icon\n const getTypeIcon = (task: BackgroundTask) => {\n return task.type === 'shell' ? '>' : '\u2699'\n }\n\n // Count active tasks\n const activeShellCount = shells.filter(s => s.status === 'running').length\n const activeAgentCount = agents.filter(a => a.status === 'running').length\n const totalActive = activeShellCount + activeAgentCount\n\n // Build count text\n let countText = ''\n if (totalActive === 0) {\n countText = 'No active tasks'\n } else {\n const parts: string[] = []\n if (activeShellCount > 0) {\n parts.push(`${activeShellCount} shell${activeShellCount > 1 ? 's' : ''}`)\n }\n if (activeAgentCount > 0) {\n parts.push(`${activeAgentCount} agent${activeAgentCount > 1 ? 's' : ''}`)\n }\n countText = parts.join(', ') + ' running'\n }\n\n return (\n <Box\n flexDirection=\"column\"\n borderStyle=\"single\"\n borderColor={theme.secondaryBorder}\n paddingX={1}\n marginBottom={1}\n >\n <Box>\n <Text bold color={theme.primary}>\n Background tasks\n </Text>\n </Box>\n <Box>\n <Text color={theme.secondaryText}>{countText}</Text>\n </Box>\n <Box height={1} />\n\n {tasks.length === 0 ? (\n <Box>\n <Text color={theme.secondaryText}>(No background tasks)</Text>\n </Box>\n ) : (\n tasks.map((task, index) => {\n const isSelected = index === selectedIndex\n const bgColor = isSelected ? 'cyan' : undefined\n\n // Extract common properties based on task type\n const status =\n task.type === 'shell' ? task.data.status : task.data.status\n const startTime = task.data.startTime\n const endTime =\n task.type === 'shell' ? task.data.endTime : task.data.endTime\n const id = task.type === 'shell' ? task.data.id : task.data.agentId\n const duration = formatDuration(startTime, endTime)\n\n // Get summary based on task type\n const summary =\n task.type === 'shell'\n ? getShellSummary(task.data)\n : getAgentSummary(task.data)\n\n return (\n <Box key={`${task.type}-${id}`}>\n <Text\n backgroundColor={bgColor}\n color={isSelected ? 'black' : theme.primary}\n >\n {isSelected ? '\u276F ' : ' '}\n <Text color={theme.secondaryText}>{getTypeIcon(task)} </Text>\n <Text color={getStatusColor(status)}>\n {getStatusIcon(status)}{' '}\n </Text>\n {summary}\n <Text color={theme.secondaryText}> [{duration}]</Text>\n </Text>\n </Box>\n )\n })\n )}\n\n <Box height={1} />\n <Box>\n <Text color={theme.secondaryText}>\n \u2191/\u2193 to select \u00B7 Enter to view \u00B7 k to kill \u00B7 Esc to close\n </Text>\n </Box>\n </Box>\n )\n}\n\nfunction getShellSummary(shell: BackgroundShell): string {\n // Get command (truncate if too long)\n const maxCmdLen = 40\n const cmd =\n shell.command.length > maxCmdLen\n ? shell.command.slice(0, maxCmdLen) + '\u2026'\n : shell.command\n\n // Get last few lines of output for preview\n const lastLine = shell.stdout[shell.stdout.length - 1] || ''\n const preview = lastLine.slice(0, 30)\n\n return preview ? `${cmd} ${preview}\u2026` : cmd\n}\n\nfunction getAgentSummary(agent: BackgroundAgentInfo): string {\n // Get description (truncate if too long)\n const maxLen = 50\n const desc =\n agent.description.length > maxLen\n ? agent.description.slice(0, maxLen) + '\u2026'\n : agent.description\n\n return `[${agent.agentType}] ${desc}`\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,24 @@
1
+ import { Box, Text } from "ink";
2
+ import * as React from "react";
3
+ import { getTheme } from "../utils/theme.js";
4
+ const DEFAULT_MAX_LINES = 10;
5
+ function BashStreamingProgress({
6
+ stdout,
7
+ stderr,
8
+ isStreaming,
9
+ maxLines = DEFAULT_MAX_LINES
10
+ }) {
11
+ const theme = getTheme();
12
+ const stdoutLines = stdout ? stdout.split("\n").filter((line) => line.length > 0) : [];
13
+ const stderrLines = stderr ? stderr.split("\n").filter((line) => line.length > 0) : [];
14
+ const visibleStdoutLines = stdoutLines.slice(-maxLines);
15
+ const hiddenStdoutCount = Math.max(0, stdoutLines.length - maxLines);
16
+ const visibleStderrLines = stderrLines.slice(-maxLines);
17
+ const hiddenStderrCount = Math.max(0, stderrLines.length - maxLines);
18
+ const hasOutput = stdoutLines.length > 0 || stderrLines.length > 0;
19
+ return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, visibleStdoutLines.length > 0 && /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(Box, { flexDirection: "row" }, /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, "\xA0\xA0\u23BF "), hiddenStdoutCount > 0 && /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, "(", hiddenStdoutCount, " lines hidden)")), visibleStdoutLines.map((line, index) => /* @__PURE__ */ React.createElement(Box, { key: `stdout-${index}`, paddingLeft: 4 }, /* @__PURE__ */ React.createElement(Text, null, line)))), visibleStderrLines.length > 0 && /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(Box, { flexDirection: "row" }, /* @__PURE__ */ React.createElement(Text, { color: theme.error }, "\xA0\xA0\u23BF "), hiddenStderrCount > 0 && /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, "(", hiddenStderrCount, " error lines hidden)")), visibleStderrLines.map((line, index) => /* @__PURE__ */ React.createElement(Box, { key: `stderr-${index}`, paddingLeft: 4 }, /* @__PURE__ */ React.createElement(Text, { color: theme.error }, line)))), !hasOutput && isStreaming && /* @__PURE__ */ React.createElement(Box, { flexDirection: "row" }, /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, "\xA0\xA0\u23BF "), /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, "(waiting for output...)")), isStreaming && hasOutput && /* @__PURE__ */ React.createElement(Box, { flexDirection: "row", paddingLeft: 4 }, /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, "...")));
20
+ }
21
+ export {
22
+ BashStreamingProgress
23
+ };
24
+ //# sourceMappingURL=BashStreamingProgress.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/components/BashStreamingProgress.tsx"],
4
+ "sourcesContent": ["import { Box, Text } from 'ink'\nimport * as React from 'react'\nimport { getTheme } from '@utils/theme'\n\n/**\n * Props for BashStreamingProgress component\n * Displays real-time streaming output from Bash commands\n */\ntype Props = {\n stdout: string\n stderr: string\n isStreaming: boolean\n maxLines?: number\n}\n\nconst DEFAULT_MAX_LINES = 10\n\n/**\n * Component for displaying real-time streaming Bash output\n * Used during command execution to show progressive output\n */\nexport function BashStreamingProgress({\n stdout,\n stderr,\n isStreaming,\n maxLines = DEFAULT_MAX_LINES,\n}: Props) {\n const theme = getTheme()\n\n // Split output into lines and calculate visibility\n const stdoutLines = stdout\n ? stdout.split('\\n').filter(line => line.length > 0)\n : []\n const stderrLines = stderr\n ? stderr.split('\\n').filter(line => line.length > 0)\n : []\n\n // Calculate visible lines (show last N lines for tailing behavior)\n const visibleStdoutLines = stdoutLines.slice(-maxLines)\n const hiddenStdoutCount = Math.max(0, stdoutLines.length - maxLines)\n\n const visibleStderrLines = stderrLines.slice(-maxLines)\n const hiddenStderrCount = Math.max(0, stderrLines.length - maxLines)\n\n const hasOutput = stdoutLines.length > 0 || stderrLines.length > 0\n\n return (\n <Box flexDirection=\"column\">\n {/* Stdout output */}\n {visibleStdoutLines.length > 0 && (\n <Box flexDirection=\"column\">\n <Box flexDirection=\"row\">\n <Text color={theme.secondaryText}>&nbsp;&nbsp;\u23BF </Text>\n {hiddenStdoutCount > 0 && (\n <Text color={theme.secondaryText}>\n ({hiddenStdoutCount} lines hidden)\n </Text>\n )}\n </Box>\n {visibleStdoutLines.map((line, index) => (\n <Box key={`stdout-${index}`} paddingLeft={4}>\n <Text>{line}</Text>\n </Box>\n ))}\n </Box>\n )}\n\n {/* Stderr output */}\n {visibleStderrLines.length > 0 && (\n <Box flexDirection=\"column\">\n <Box flexDirection=\"row\">\n <Text color={theme.error}>&nbsp;&nbsp;\u23BF </Text>\n {hiddenStderrCount > 0 && (\n <Text color={theme.secondaryText}>\n ({hiddenStderrCount} error lines hidden)\n </Text>\n )}\n </Box>\n {visibleStderrLines.map((line, index) => (\n <Box key={`stderr-${index}`} paddingLeft={4}>\n <Text color={theme.error}>{line}</Text>\n </Box>\n ))}\n </Box>\n )}\n\n {/* Empty output indicator */}\n {!hasOutput && isStreaming && (\n <Box flexDirection=\"row\">\n <Text color={theme.secondaryText}>&nbsp;&nbsp;\u23BF </Text>\n <Text color={theme.secondaryText}>(waiting for output...)</Text>\n </Box>\n )}\n\n {/* Streaming indicator */}\n {isStreaming && hasOutput && (\n <Box flexDirection=\"row\" paddingLeft={4}>\n <Text color={theme.secondaryText}>...</Text>\n </Box>\n )}\n </Box>\n )\n}\n"],
5
+ "mappings": "AAAA,SAAS,KAAK,YAAY;AAC1B,YAAY,WAAW;AACvB,SAAS,gBAAgB;AAazB,MAAM,oBAAoB;AAMnB,SAAS,sBAAsB;AAAA,EACpC;AAAA,EACA;AAAA,EACA;AAAA,EACA,WAAW;AACb,GAAU;AACR,QAAM,QAAQ,SAAS;AAGvB,QAAM,cAAc,SAChB,OAAO,MAAM,IAAI,EAAE,OAAO,UAAQ,KAAK,SAAS,CAAC,IACjD,CAAC;AACL,QAAM,cAAc,SAChB,OAAO,MAAM,IAAI,EAAE,OAAO,UAAQ,KAAK,SAAS,CAAC,IACjD,CAAC;AAGL,QAAM,qBAAqB,YAAY,MAAM,CAAC,QAAQ;AACtD,QAAM,oBAAoB,KAAK,IAAI,GAAG,YAAY,SAAS,QAAQ;AAEnE,QAAM,qBAAqB,YAAY,MAAM,CAAC,QAAQ;AACtD,QAAM,oBAAoB,KAAK,IAAI,GAAG,YAAY,SAAS,QAAQ;AAEnE,QAAM,YAAY,YAAY,SAAS,KAAK,YAAY,SAAS;AAEjE,SACE,oCAAC,OAAI,eAAc,YAEhB,mBAAmB,SAAS,KAC3B,oCAAC,OAAI,eAAc,YACjB,oCAAC,OAAI,eAAc,SACjB,oCAAC,QAAK,OAAO,MAAM,iBAAe,iBAAc,GAC/C,oBAAoB,KACnB,oCAAC,QAAK,OAAO,MAAM,iBAAe,KAC9B,mBAAkB,gBACtB,CAEJ,GACC,mBAAmB,IAAI,CAAC,MAAM,UAC7B,oCAAC,OAAI,KAAK,UAAU,KAAK,IAAI,aAAa,KACxC,oCAAC,YAAM,IAAK,CACd,CACD,CACH,GAID,mBAAmB,SAAS,KAC3B,oCAAC,OAAI,eAAc,YACjB,oCAAC,OAAI,eAAc,SACjB,oCAAC,QAAK,OAAO,MAAM,SAAO,iBAAc,GACvC,oBAAoB,KACnB,oCAAC,QAAK,OAAO,MAAM,iBAAe,KAC9B,mBAAkB,sBACtB,CAEJ,GACC,mBAAmB,IAAI,CAAC,MAAM,UAC7B,oCAAC,OAAI,KAAK,UAAU,KAAK,IAAI,aAAa,KACxC,oCAAC,QAAK,OAAO,MAAM,SAAQ,IAAK,CAClC,CACD,CACH,GAID,CAAC,aAAa,eACb,oCAAC,OAAI,eAAc,SACjB,oCAAC,QAAK,OAAO,MAAM,iBAAe,iBAAc,GAChD,oCAAC,QAAK,OAAO,MAAM,iBAAe,yBAAuB,CAC3D,GAID,eAAe,aACd,oCAAC,OAAI,eAAc,OAAM,aAAa,KACpC,oCAAC,QAAK,OAAO,MAAM,iBAAe,KAAG,CACvC,CAEJ;AAEJ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,15 @@
1
+ import React from "react";
2
+ import { Text } from "ink";
3
+ import { SEMANTIC_COLORS } from "../constants/colors.js";
4
+ function CollapsibleHint({
5
+ canExpand,
6
+ shortcut = "ctrl+o",
7
+ action = "expand"
8
+ }) {
9
+ if (!canExpand) return null;
10
+ return /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.dim }, " ", "(", shortcut, " to ", action, ")");
11
+ }
12
+ export {
13
+ CollapsibleHint
14
+ };
15
+ //# sourceMappingURL=CollapsibleHint.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/components/CollapsibleHint.tsx"],
4
+ "sourcesContent": ["/**\n * Collapsible Hint Component\n *\n * Displays a keyboard shortcut hint for expandable content.\n * Shows \"(ctrl+o to expand)\" or similar hint when content can be expanded.\n */\n\nimport React from 'react'\nimport { Text } from 'ink'\nimport { SEMANTIC_COLORS } from '@constants/colors'\n\ninterface Props {\n /** Whether the content can be expanded */\n canExpand: boolean\n /** The keyboard shortcut text (default: \"ctrl+o\") */\n shortcut?: string\n /** The action text (default: \"expand\") */\n action?: string\n}\n\nexport function CollapsibleHint({\n canExpand,\n shortcut = 'ctrl+o',\n action = 'expand',\n}: Props): React.ReactNode {\n if (!canExpand) return null\n\n return (\n <Text color={SEMANTIC_COLORS.dim}>\n {' '}\n ({shortcut} to {action})\n </Text>\n )\n}\n"],
5
+ "mappings": "AAOA,OAAO,WAAW;AAClB,SAAS,YAAY;AACrB,SAAS,uBAAuB;AAWzB,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA,WAAW;AAAA,EACX,SAAS;AACX,GAA2B;AACzB,MAAI,CAAC,UAAW,QAAO;AAEvB,SACE,oCAAC,QAAK,OAAO,gBAAgB,OAC1B,KAAI,KACH,UAAS,QAAK,QAAO,GACzB;AAEJ;",
6
+ "names": []
7
+ }
@@ -7,6 +7,7 @@ import { saveGlobalConfig, getGlobalConfig } from "../utils/config.js";
7
7
  import { useExitOnCtrlCD } from "../hooks/useExitOnCtrlCD.js";
8
8
  import { getModelManager } from "../utils/model.js";
9
9
  import { getCompressionMode, setCompressionMode } from "../utils/compressionMode.js";
10
+ import { SEMANTIC_COLORS } from "../constants/colors.js";
10
11
  function Config({ onClose }) {
11
12
  const [globalConfig, setGlobalConfig] = useState(getGlobalConfig());
12
13
  const initialConfig = React.useRef(getGlobalConfig());
@@ -169,8 +170,8 @@ function Config({ onClose }) {
169
170
  color: setting.disabled ? theme.secondaryText : theme.suggestion
170
171
  },
171
172
  setting.type === "boolean" ? setting.value ? "enabled" : "disabled" : setting.type === "enum" ? setting.value : String(setting.value)
172
- )), index === selectedIndex && editingString && /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", marginLeft: 2 }, /* @__PURE__ */ React.createElement(Text, { color: theme.suggestion }, "Enter new value: ", currentInput), inputError && /* @__PURE__ */ React.createElement(Text, { color: "red" }, inputError))))),
173
- /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, editingString ? "Enter to save \xB7 Esc to cancel" : /* @__PURE__ */ React.createElement(React.Fragment, null, "\u2191/\u2193 to navigate \xB7 Enter to change \xB7 Esc to close", /* @__PURE__ */ React.createElement(Text, { color: theme.suggestion }, " ", "\xB7 Use /model for model config"))))
173
+ )), index === selectedIndex && editingString && /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", marginLeft: 2 }, /* @__PURE__ */ React.createElement(Text, { color: theme.suggestion }, "Enter new value: ", currentInput), inputError && /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.error }, inputError))))),
174
+ /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.dim }, editingString ? "Enter to save \xB7 Esc to cancel" : /* @__PURE__ */ React.createElement(React.Fragment, null, "\u2191/\u2193 to navigate \xB7 Enter to change \xB7 Esc to close", /* @__PURE__ */ React.createElement(Text, { color: theme.suggestion }, " ", "\xB7 Use /model for model config"))))
174
175
  ));
175
176
  }
176
177
  export {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/components/Config.tsx"],
4
- "sourcesContent": ["import { Box, Text, useInput } from 'ink'\nimport * as React from 'react'\nimport { useState } from 'react'\nimport figures from 'figures'\nimport { getTheme } from '@utils/theme'\nimport { GlobalConfig, saveGlobalConfig, getGlobalConfig } from '@utils/config'\nimport chalk from 'chalk'\nimport { useExitOnCtrlCD } from '@hooks/useExitOnCtrlCD'\nimport { getModelManager } from '@utils/model'\nimport { getCompressionMode, setCompressionMode } from '@utils/compressionMode'\nimport type { CompressionMode } from '@constants/compressionPrompts'\n\ntype Props = {\n onClose: () => void\n}\n\ntype Setting =\n | {\n id: string\n label: string\n value: boolean\n onChange(value: boolean): void\n type: 'boolean'\n disabled?: boolean\n }\n | {\n id: string\n label: string\n value: string\n options: string[]\n onChange(value: string): void\n type: 'enum'\n disabled?: boolean\n }\n | {\n id: string\n label: string\n value: string\n onChange(value: string): void\n type: 'string'\n disabled?: boolean\n }\n | {\n id: string\n label: string\n value: number\n onChange(value: number): void\n type: 'number'\n disabled?: boolean\n }\n\nexport function Config({ onClose }: Props): React.ReactNode {\n const [globalConfig, setGlobalConfig] = useState(getGlobalConfig())\n const initialConfig = React.useRef(getGlobalConfig())\n const [selectedIndex, setSelectedIndex] = useState(0)\n const exitState = useExitOnCtrlCD(() => process.exit(0))\n const [editingString, setEditingString] = useState(false)\n const [currentInput, setCurrentInput] = useState('')\n const [inputError, setInputError] = useState<string | null>(null)\n\n const modelManager = getModelManager()\n const activeProfiles = modelManager.getAvailableModels()\n\n const settings: Setting[] = [\n // Global settings\n {\n id: 'theme',\n label: 'Theme',\n value: globalConfig.theme ?? 'dark',\n options: ['dark', 'light'],\n onChange(theme: string) {\n const config = { ...getGlobalConfig(), theme: theme as any }\n saveGlobalConfig(config)\n setGlobalConfig(config)\n },\n type: 'enum',\n },\n {\n id: 'verbose',\n label: 'Verbose mode',\n value: globalConfig.verbose ?? false,\n onChange(verbose: boolean) {\n const config = { ...getGlobalConfig(), verbose }\n saveGlobalConfig(config)\n setGlobalConfig(config)\n },\n type: 'boolean',\n },\n {\n id: 'stream',\n label: 'Stream responses',\n value: globalConfig.stream ?? true,\n onChange(stream: boolean) {\n const config = { ...getGlobalConfig(), stream }\n saveGlobalConfig(config)\n setGlobalConfig(config)\n },\n type: 'boolean',\n },\n {\n id: 'compressionMode',\n label: 'Compression mode (/compact)',\n value: getCompressionMode(),\n options: ['business', 'code'],\n onChange(mode: string) {\n setCompressionMode(mode as CompressionMode)\n const config = {\n ...getGlobalConfig(),\n compressionMode: mode as CompressionMode,\n }\n setGlobalConfig(config)\n },\n type: 'enum',\n },\n ]\n\n const theme = getTheme()\n\n useInput((input, key) => {\n if (editingString) {\n if (key.return) {\n const currentSetting = settings[selectedIndex]\n if (currentSetting?.type === 'string') {\n try {\n currentSetting.onChange(currentInput)\n setEditingString(false)\n setCurrentInput('')\n setInputError(null)\n } catch (error) {\n setInputError(\n error instanceof Error ? error.message : 'Invalid input',\n )\n }\n } else if (currentSetting?.type === 'number') {\n const numValue = parseFloat(currentInput)\n if (isNaN(numValue)) {\n setInputError('Please enter a valid number')\n } else {\n try {\n ;(currentSetting as any).onChange(numValue)\n setEditingString(false)\n setCurrentInput('')\n setInputError(null)\n } catch (error) {\n setInputError(\n error instanceof Error ? error.message : 'Invalid input',\n )\n }\n }\n }\n } else if (key.escape) {\n setEditingString(false)\n setCurrentInput('')\n setInputError(null)\n } else if (key.delete || key.backspace) {\n setCurrentInput(prev => prev.slice(0, -1))\n } else if (input) {\n setCurrentInput(prev => prev + input)\n }\n return\n }\n\n if (key.upArrow && !exitState.pending) {\n setSelectedIndex(prev => Math.max(0, prev - 1))\n } else if (key.downArrow && !exitState.pending) {\n setSelectedIndex(prev => Math.min(settings.length - 1, prev + 1))\n } else if (key.return && !exitState.pending) {\n const currentSetting = settings[selectedIndex]\n if (currentSetting?.disabled) return\n\n if (currentSetting?.type === 'boolean') {\n currentSetting.onChange(!currentSetting.value)\n } else if (currentSetting?.type === 'enum') {\n const currentIndex = currentSetting.options.indexOf(\n currentSetting.value,\n )\n const nextIndex = (currentIndex + 1) % currentSetting.options.length\n currentSetting.onChange(currentSetting.options[nextIndex])\n } else if (\n currentSetting?.type === 'string' ||\n currentSetting?.type === 'number'\n ) {\n setCurrentInput(String(currentSetting.value))\n setEditingString(true)\n setInputError(null)\n }\n } else if (key.escape && !exitState.pending) {\n // Check if config has changed\n const currentConfigString = JSON.stringify(getGlobalConfig())\n const initialConfigString = JSON.stringify(initialConfig.current)\n\n if (currentConfigString !== initialConfigString) {\n // Config has changed, save it\n saveGlobalConfig(getGlobalConfig())\n }\n\n onClose()\n }\n })\n\n return (\n <Box flexDirection=\"column\" gap={1}>\n <Box\n flexDirection=\"column\"\n borderStyle=\"round\"\n borderColor={theme.secondaryBorder}\n paddingX={2}\n paddingY={1}\n gap={1}\n >\n <Text bold>\n Configuration{' '}\n {exitState.pending\n ? `(press ${exitState.keyName} again to exit)`\n : ''}\n </Text>\n\n {/* Model Configuration Summary */}\n <Box flexDirection=\"column\" marginY={1}>\n <Text bold color={theme.success}>\n Model Configuration:\n </Text>\n {activeProfiles.length === 0 ? (\n <Text color={theme.secondaryText}>\n No models configured. Use /model to add models.\n </Text>\n ) : (\n <Box flexDirection=\"column\" marginLeft={2}>\n {activeProfiles.map(profile => (\n <React.Fragment key={profile.modelName}>\n <Text color={theme.secondaryText}>\n \u2022 {profile.name} ({profile.provider})\n </Text>\n </React.Fragment>\n ))}\n <Box marginTop={1}>\n <Text color={theme.suggestion}>\n Use /model to manage model configurations\n </Text>\n </Box>\n </Box>\n )}\n </Box>\n\n {/* Settings List */}\n <Box flexDirection=\"column\">\n {settings.map((setting, index) => (\n <Box key={setting.id} flexDirection=\"column\">\n <Box flexDirection=\"row\" gap={1}>\n <Text\n color={\n index === selectedIndex\n ? theme.success\n : setting.disabled\n ? theme.secondaryText\n : theme.text\n }\n >\n {index === selectedIndex ? figures.pointer : ' '}{' '}\n {setting.label}\n </Text>\n <Text\n color={\n setting.disabled ? theme.secondaryText : theme.suggestion\n }\n >\n {setting.type === 'boolean'\n ? setting.value\n ? 'enabled'\n : 'disabled'\n : setting.type === 'enum'\n ? setting.value\n : String(setting.value)}\n </Text>\n </Box>\n {index === selectedIndex && editingString && (\n <Box flexDirection=\"column\" marginLeft={2}>\n <Text color={theme.suggestion}>\n Enter new value: {currentInput}\n </Text>\n {inputError && <Text color=\"red\">{inputError}</Text>}\n </Box>\n )}\n </Box>\n ))}\n </Box>\n\n <Box marginTop={1}>\n <Text dimColor>\n {editingString ? (\n 'Enter to save \u00B7 Esc to cancel'\n ) : (\n <>\n \u2191/\u2193 to navigate \u00B7 Enter to change \u00B7 Esc to close\n <Text color={theme.suggestion}>\n {' '}\n \u00B7 Use /model for model config\n </Text>\n </>\n )}\n </Text>\n </Box>\n </Box>\n </Box>\n )\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { Box, Text, useInput } from 'ink'\nimport * as React from 'react'\nimport { useState } from 'react'\nimport figures from 'figures'\nimport { getTheme } from '@utils/theme'\nimport { GlobalConfig, saveGlobalConfig, getGlobalConfig } from '@utils/config'\nimport chalk from 'chalk'\nimport { useExitOnCtrlCD } from '@hooks/useExitOnCtrlCD'\nimport { getModelManager } from '@utils/model'\nimport { getCompressionMode, setCompressionMode } from '@utils/compressionMode'\nimport type { CompressionMode } from '@constants/compressionPrompts'\nimport { SEMANTIC_COLORS } from '@constants/colors'\n\ntype Props = {\n onClose: () => void\n}\n\ntype Setting =\n | {\n id: string\n label: string\n value: boolean\n onChange(value: boolean): void\n type: 'boolean'\n disabled?: boolean\n }\n | {\n id: string\n label: string\n value: string\n options: string[]\n onChange(value: string): void\n type: 'enum'\n disabled?: boolean\n }\n | {\n id: string\n label: string\n value: string\n onChange(value: string): void\n type: 'string'\n disabled?: boolean\n }\n | {\n id: string\n label: string\n value: number\n onChange(value: number): void\n type: 'number'\n disabled?: boolean\n }\n\nexport function Config({ onClose }: Props): React.ReactNode {\n const [globalConfig, setGlobalConfig] = useState(getGlobalConfig())\n const initialConfig = React.useRef(getGlobalConfig())\n const [selectedIndex, setSelectedIndex] = useState(0)\n const exitState = useExitOnCtrlCD(() => process.exit(0))\n const [editingString, setEditingString] = useState(false)\n const [currentInput, setCurrentInput] = useState('')\n const [inputError, setInputError] = useState<string | null>(null)\n\n const modelManager = getModelManager()\n const activeProfiles = modelManager.getAvailableModels()\n\n const settings: Setting[] = [\n // Global settings\n {\n id: 'theme',\n label: 'Theme',\n value: globalConfig.theme ?? 'dark',\n options: ['dark', 'light'],\n onChange(theme: string) {\n const config = { ...getGlobalConfig(), theme: theme as any }\n saveGlobalConfig(config)\n setGlobalConfig(config)\n },\n type: 'enum',\n },\n {\n id: 'verbose',\n label: 'Verbose mode',\n value: globalConfig.verbose ?? false,\n onChange(verbose: boolean) {\n const config = { ...getGlobalConfig(), verbose }\n saveGlobalConfig(config)\n setGlobalConfig(config)\n },\n type: 'boolean',\n },\n {\n id: 'stream',\n label: 'Stream responses',\n value: globalConfig.stream ?? true,\n onChange(stream: boolean) {\n const config = { ...getGlobalConfig(), stream }\n saveGlobalConfig(config)\n setGlobalConfig(config)\n },\n type: 'boolean',\n },\n {\n id: 'compressionMode',\n label: 'Compression mode (/compact)',\n value: getCompressionMode(),\n options: ['business', 'code'],\n onChange(mode: string) {\n setCompressionMode(mode as CompressionMode)\n const config = {\n ...getGlobalConfig(),\n compressionMode: mode as CompressionMode,\n }\n setGlobalConfig(config)\n },\n type: 'enum',\n },\n ]\n\n const theme = getTheme()\n\n useInput((input, key) => {\n if (editingString) {\n if (key.return) {\n const currentSetting = settings[selectedIndex]\n if (currentSetting?.type === 'string') {\n try {\n currentSetting.onChange(currentInput)\n setEditingString(false)\n setCurrentInput('')\n setInputError(null)\n } catch (error) {\n setInputError(\n error instanceof Error ? error.message : 'Invalid input',\n )\n }\n } else if (currentSetting?.type === 'number') {\n const numValue = parseFloat(currentInput)\n if (isNaN(numValue)) {\n setInputError('Please enter a valid number')\n } else {\n try {\n ;(currentSetting as any).onChange(numValue)\n setEditingString(false)\n setCurrentInput('')\n setInputError(null)\n } catch (error) {\n setInputError(\n error instanceof Error ? error.message : 'Invalid input',\n )\n }\n }\n }\n } else if (key.escape) {\n setEditingString(false)\n setCurrentInput('')\n setInputError(null)\n } else if (key.delete || key.backspace) {\n setCurrentInput(prev => prev.slice(0, -1))\n } else if (input) {\n setCurrentInput(prev => prev + input)\n }\n return\n }\n\n if (key.upArrow && !exitState.pending) {\n setSelectedIndex(prev => Math.max(0, prev - 1))\n } else if (key.downArrow && !exitState.pending) {\n setSelectedIndex(prev => Math.min(settings.length - 1, prev + 1))\n } else if (key.return && !exitState.pending) {\n const currentSetting = settings[selectedIndex]\n if (currentSetting?.disabled) return\n\n if (currentSetting?.type === 'boolean') {\n currentSetting.onChange(!currentSetting.value)\n } else if (currentSetting?.type === 'enum') {\n const currentIndex = currentSetting.options.indexOf(\n currentSetting.value,\n )\n const nextIndex = (currentIndex + 1) % currentSetting.options.length\n currentSetting.onChange(currentSetting.options[nextIndex])\n } else if (\n currentSetting?.type === 'string' ||\n currentSetting?.type === 'number'\n ) {\n setCurrentInput(String(currentSetting.value))\n setEditingString(true)\n setInputError(null)\n }\n } else if (key.escape && !exitState.pending) {\n // Check if config has changed\n const currentConfigString = JSON.stringify(getGlobalConfig())\n const initialConfigString = JSON.stringify(initialConfig.current)\n\n if (currentConfigString !== initialConfigString) {\n // Config has changed, save it\n saveGlobalConfig(getGlobalConfig())\n }\n\n onClose()\n }\n })\n\n return (\n <Box flexDirection=\"column\" gap={1}>\n <Box\n flexDirection=\"column\"\n borderStyle=\"round\"\n borderColor={theme.secondaryBorder}\n paddingX={2}\n paddingY={1}\n gap={1}\n >\n <Text bold>\n Configuration{' '}\n {exitState.pending\n ? `(press ${exitState.keyName} again to exit)`\n : ''}\n </Text>\n\n {/* Model Configuration Summary */}\n <Box flexDirection=\"column\" marginY={1}>\n <Text bold color={theme.success}>\n Model Configuration:\n </Text>\n {activeProfiles.length === 0 ? (\n <Text color={theme.secondaryText}>\n No models configured. Use /model to add models.\n </Text>\n ) : (\n <Box flexDirection=\"column\" marginLeft={2}>\n {activeProfiles.map(profile => (\n <React.Fragment key={profile.modelName}>\n <Text color={theme.secondaryText}>\n \u2022 {profile.name} ({profile.provider})\n </Text>\n </React.Fragment>\n ))}\n <Box marginTop={1}>\n <Text color={theme.suggestion}>\n Use /model to manage model configurations\n </Text>\n </Box>\n </Box>\n )}\n </Box>\n\n {/* Settings List */}\n <Box flexDirection=\"column\">\n {settings.map((setting, index) => (\n <Box key={setting.id} flexDirection=\"column\">\n <Box flexDirection=\"row\" gap={1}>\n <Text\n color={\n index === selectedIndex\n ? theme.success\n : setting.disabled\n ? theme.secondaryText\n : theme.text\n }\n >\n {index === selectedIndex ? figures.pointer : ' '}{' '}\n {setting.label}\n </Text>\n <Text\n color={\n setting.disabled ? theme.secondaryText : theme.suggestion\n }\n >\n {setting.type === 'boolean'\n ? setting.value\n ? 'enabled'\n : 'disabled'\n : setting.type === 'enum'\n ? setting.value\n : String(setting.value)}\n </Text>\n </Box>\n {index === selectedIndex && editingString && (\n <Box flexDirection=\"column\" marginLeft={2}>\n <Text color={theme.suggestion}>\n Enter new value: {currentInput}\n </Text>\n {inputError && (\n <Text color={SEMANTIC_COLORS.error}>{inputError}</Text>\n )}\n </Box>\n )}\n </Box>\n ))}\n </Box>\n\n <Box marginTop={1}>\n <Text color={SEMANTIC_COLORS.dim}>\n {editingString ? (\n 'Enter to save \u00B7 Esc to cancel'\n ) : (\n <>\n \u2191/\u2193 to navigate \u00B7 Enter to change \u00B7 Esc to close\n <Text color={theme.suggestion}>\n {' '}\n \u00B7 Use /model for model config\n </Text>\n </>\n )}\n </Text>\n </Box>\n </Box>\n </Box>\n )\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["theme"]
7
7
  }
@@ -11,6 +11,7 @@ import { SimpleSpinner } from "./Spinner.js";
11
11
  import { WelcomeBox } from "./Onboarding.js";
12
12
  import { PRODUCT_NAME } from "../constants/product.js";
13
13
  import { sendNotification } from "../services/notifier.js";
14
+ import { SEMANTIC_COLORS } from "../constants/colors.js";
14
15
  const PASTE_HERE_MSG = "Paste code here if prompted > ";
15
16
  function ConsoleOAuthFlow({ onDone }) {
16
17
  const [oauthStatus, setOAuthStatus] = useState({
@@ -162,7 +163,7 @@ function ConsoleOAuthFlow({ onDone }) {
162
163
  staticItems.header = /* @__PURE__ */ React.createElement(Box, { key: "header", flexDirection: "column", gap: 1 }, /* @__PURE__ */ React.createElement(WelcomeBox, null), /* @__PURE__ */ React.createElement(Box, { paddingBottom: 1, paddingLeft: 1 }, /* @__PURE__ */ React.createElement(AsciiLogo, null)));
163
164
  }
164
165
  if (oauthStatus.state === "waiting_for_login" && showPastePrompt) {
165
- staticItems.urlToCopy = /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", key: "urlToCopy", gap: 1, paddingBottom: 1 }, /* @__PURE__ */ React.createElement(Box, { paddingX: 1 }, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, "Browser didn't open? Use the url below to sign in:")), /* @__PURE__ */ React.createElement(Box, { width: 1e3 }, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, oauthStatus.url)));
166
+ staticItems.urlToCopy = /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", key: "urlToCopy", gap: 1, paddingBottom: 1 }, /* @__PURE__ */ React.createElement(Box, { paddingX: 1 }, /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.dim }, "Browser didn't open? Use the url below to sign in:")), /* @__PURE__ */ React.createElement(Box, { width: 1e3 }, /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.dim }, oauthStatus.url)));
166
167
  }
167
168
  return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", gap: 1 }, /* @__PURE__ */ React.createElement(
168
169
  Static,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/components/ConsoleOAuthFlow.tsx"],
4
- "sourcesContent": ["import React, { useEffect, useState, useCallback } from 'react'\nimport { Static, Box, Text, useInput } from 'ink'\nimport TextInput from './TextInput'\nimport { OAuthService, createAndStoreApiKey } from '@services/oauth'\nimport { getTheme } from '@utils/theme'\nimport { AsciiLogo } from './AsciiLogo'\nimport { useTerminalSize } from '@hooks/useTerminalSize'\nimport { logError } from '@utils/log'\nimport { clearTerminal } from '@utils/terminal'\nimport { SimpleSpinner } from './Spinner'\nimport { WelcomeBox } from './Onboarding'\nimport { PRODUCT_NAME } from '@constants/product'\nimport { sendNotification } from '@services/notifier'\n\ntype Props = {\n onDone(): void\n}\n\ntype OAuthStatus =\n | { state: 'idle' }\n | { state: 'ready_to_start' }\n | { state: 'waiting_for_login'; url: string }\n | { state: 'creating_api_key' }\n | { state: 'about_to_retry'; nextState: OAuthStatus }\n | { state: 'success'; apiKey: string }\n | {\n state: 'error'\n message: string\n toRetry?: OAuthStatus\n }\n\nconst PASTE_HERE_MSG = 'Paste code here if prompted > '\n\nexport function ConsoleOAuthFlow({ onDone }: Props): React.ReactNode {\n const [oauthStatus, setOAuthStatus] = useState<OAuthStatus>({\n state: 'idle',\n })\n const theme = getTheme()\n\n const [pastedCode, setPastedCode] = useState('')\n const [cursorOffset, setCursorOffset] = useState(0)\n const [oauthService] = useState(() => new OAuthService())\n // After a few seconds we suggest the user to copy/paste url if the\n // browser did not open automatically. In this flow we expect the user to\n // copy the code from the browser and paste it in the terminal\n const [showPastePrompt, setShowPastePrompt] = useState(false)\n // we need a special clearing state to correctly re-render Static elements\n const [isClearing, setIsClearing] = useState(false)\n\n const textInputColumns = useTerminalSize().columns - PASTE_HERE_MSG.length - 1\n\n useEffect(() => {\n if (isClearing) {\n clearTerminal()\n setIsClearing(false)\n }\n }, [isClearing])\n\n // Retry logic\n useEffect(() => {\n if (oauthStatus.state === 'about_to_retry') {\n setIsClearing(true)\n setTimeout(() => {\n setOAuthStatus(oauthStatus.nextState)\n }, 1000)\n }\n }, [oauthStatus])\n\n useInput(async (_, key) => {\n if (key.return) {\n if (oauthStatus.state === 'idle') {\n setOAuthStatus({ state: 'ready_to_start' })\n } else if (oauthStatus.state === 'success') {\n await clearTerminal() // needed to clear out Static components\n onDone()\n } else if (oauthStatus.state === 'error' && oauthStatus.toRetry) {\n setPastedCode('')\n setOAuthStatus({\n state: 'about_to_retry',\n nextState: oauthStatus.toRetry,\n })\n }\n }\n })\n\n async function handleSubmitCode(value: string, url: string) {\n try {\n // Expecting format \"authorizationCode#state\" from the authorization callback URL\n const [authorizationCode, state] = value.split('#')\n\n if (!authorizationCode || !state) {\n setOAuthStatus({\n state: 'error',\n message: 'Invalid code. Please make sure the full code was copied',\n toRetry: { state: 'waiting_for_login', url },\n })\n return\n }\n\n // Track which path the user is taking (manual code entry)\n\n oauthService.processCallback({\n authorizationCode,\n state,\n useManualRedirect: true,\n })\n } catch (err) {\n logError(err)\n setOAuthStatus({\n state: 'error',\n message: (err as Error).message,\n toRetry: { state: 'waiting_for_login', url },\n })\n }\n }\n\n const startOAuth = useCallback(async () => {\n try {\n const result = await oauthService\n .startOAuthFlow(async url => {\n setOAuthStatus({ state: 'waiting_for_login', url })\n setTimeout(() => setShowPastePrompt(true), 3000)\n })\n .catch(err => {\n // Handle token exchange errors specifically\n if (err.message.includes('Token exchange failed')) {\n setOAuthStatus({\n state: 'error',\n message:\n 'Failed to exchange authorization code for access token. Please try again.',\n toRetry: { state: 'ready_to_start' },\n })\n } else {\n // Handle other errors\n setOAuthStatus({\n state: 'error',\n message: err.message,\n toRetry: { state: 'ready_to_start' },\n })\n }\n throw err\n })\n\n setOAuthStatus({ state: 'creating_api_key' })\n\n const apiKey = await createAndStoreApiKey(result.accessToken).catch(\n err => {\n setOAuthStatus({\n state: 'error',\n message: 'Failed to create API key: ' + err.message,\n toRetry: { state: 'ready_to_start' },\n })\n\n throw err\n },\n )\n\n if (apiKey) {\n setOAuthStatus({ state: 'success', apiKey })\n sendNotification({ message: 'Minto login successful' })\n } else {\n setOAuthStatus({\n state: 'error',\n message:\n \"Unable to create API key. The server accepted the request but didn't return a key.\",\n toRetry: { state: 'ready_to_start' },\n })\n }\n } catch (err) {\n const errorMessage = (err as Error).message\n }\n }, [oauthService, setShowPastePrompt])\n\n useEffect(() => {\n if (oauthStatus.state === 'ready_to_start') {\n startOAuth()\n }\n }, [oauthStatus.state, startOAuth])\n\n // Helper function to render the appropriate status message\n function renderStatusMessage(): React.ReactNode {\n switch (oauthStatus.state) {\n case 'idle':\n return (\n <Box flexDirection=\"column\" gap={1}>\n <Text bold>\n {PRODUCT_NAME} is billed based on API usage through your Anthropic\n Console account.\n </Text>\n\n <Box>\n <Text>\n Pricing may evolve as we move towards general availability.\n </Text>\n </Box>\n\n <Box marginTop={1}>\n <Text color={theme.permission}>\n Press <Text bold>Enter</Text> to login to your Anthropic Console\n account\u2026\n </Text>\n </Box>\n </Box>\n )\n\n case 'waiting_for_login':\n return (\n <Box flexDirection=\"column\" gap={1}>\n {!showPastePrompt && (\n <Box>\n <SimpleSpinner />\n <Text>Opening browser to sign in\u2026</Text>\n </Box>\n )}\n\n {showPastePrompt && (\n <Box>\n <Text>{PASTE_HERE_MSG}</Text>\n <TextInput\n value={pastedCode}\n onChange={setPastedCode}\n onSubmit={(value: string) =>\n handleSubmitCode(value, oauthStatus.url)\n }\n cursorOffset={cursorOffset}\n onChangeCursorOffset={setCursorOffset}\n columns={textInputColumns}\n />\n </Box>\n )}\n </Box>\n )\n\n case 'creating_api_key':\n return (\n <Box flexDirection=\"column\" gap={1}>\n <Box>\n <SimpleSpinner />\n <Text>Creating API key for Minto\u2026</Text>\n </Box>\n </Box>\n )\n\n case 'about_to_retry':\n return (\n <Box flexDirection=\"column\" gap={1}>\n <Text color={theme.permission}>Retrying\u2026</Text>\n </Box>\n )\n\n case 'success':\n return (\n <Box flexDirection=\"column\" gap={1}>\n <Text color={theme.success}>\n Login successful. Press <Text bold>Enter</Text> to continue\u2026\n </Text>\n </Box>\n )\n\n case 'error':\n return (\n <Box flexDirection=\"column\" gap={1}>\n <Text color={theme.error}>OAuth error: {oauthStatus.message}</Text>\n\n {oauthStatus.toRetry && (\n <Box marginTop={1}>\n <Text color={theme.permission}>\n Press <Text bold>Enter</Text> to retry.\n </Text>\n </Box>\n )}\n </Box>\n )\n\n default:\n return null\n }\n }\n\n // We need to render the copy-able URL statically to prevent Ink <Text> from inserting\n // newlines in the middle of the URL (this breaks Safari). Because <Static> components are\n // only rendered once top-to-bottom, we also need to make everything above the URL static.\n const staticItems: Record<string, React.JSX.Element> = {}\n if (!isClearing) {\n staticItems.header = (\n <Box key=\"header\" flexDirection=\"column\" gap={1}>\n <WelcomeBox />\n <Box paddingBottom={1} paddingLeft={1}>\n <AsciiLogo />\n </Box>\n </Box>\n )\n }\n if (oauthStatus.state === 'waiting_for_login' && showPastePrompt) {\n staticItems.urlToCopy = (\n <Box flexDirection=\"column\" key=\"urlToCopy\" gap={1} paddingBottom={1}>\n <Box paddingX={1}>\n <Text dimColor>\n Browser didn&apos;t open? Use the url below to sign in:\n </Text>\n </Box>\n <Box width={1000}>\n <Text dimColor>{oauthStatus.url}</Text>\n </Box>\n </Box>\n )\n }\n return (\n <Box flexDirection=\"column\" gap={1}>\n <Static\n items={Object.keys(staticItems)}\n children={(item: string) => staticItems[item]}\n />\n <Box paddingLeft={1} flexDirection=\"column\" gap={1}>\n {renderStatusMessage()}\n </Box>\n </Box>\n )\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import React, { useEffect, useState, useCallback } from 'react'\nimport { Static, Box, Text, useInput } from 'ink'\nimport TextInput from './TextInput'\nimport { OAuthService, createAndStoreApiKey } from '@services/oauth'\nimport { getTheme } from '@utils/theme'\nimport { AsciiLogo } from './AsciiLogo'\nimport { useTerminalSize } from '@hooks/useTerminalSize'\nimport { logError } from '@utils/log'\nimport { clearTerminal } from '@utils/terminal'\nimport { SimpleSpinner } from './Spinner'\nimport { WelcomeBox } from './Onboarding'\nimport { PRODUCT_NAME } from '@constants/product'\nimport { sendNotification } from '@services/notifier'\nimport { SEMANTIC_COLORS } from '@constants/colors'\n\ntype Props = {\n onDone(): void\n}\n\ntype OAuthStatus =\n | { state: 'idle' }\n | { state: 'ready_to_start' }\n | { state: 'waiting_for_login'; url: string }\n | { state: 'creating_api_key' }\n | { state: 'about_to_retry'; nextState: OAuthStatus }\n | { state: 'success'; apiKey: string }\n | {\n state: 'error'\n message: string\n toRetry?: OAuthStatus\n }\n\nconst PASTE_HERE_MSG = 'Paste code here if prompted > '\n\nexport function ConsoleOAuthFlow({ onDone }: Props): React.ReactNode {\n const [oauthStatus, setOAuthStatus] = useState<OAuthStatus>({\n state: 'idle',\n })\n const theme = getTheme()\n\n const [pastedCode, setPastedCode] = useState('')\n const [cursorOffset, setCursorOffset] = useState(0)\n const [oauthService] = useState(() => new OAuthService())\n // After a few seconds we suggest the user to copy/paste url if the\n // browser did not open automatically. In this flow we expect the user to\n // copy the code from the browser and paste it in the terminal\n const [showPastePrompt, setShowPastePrompt] = useState(false)\n // we need a special clearing state to correctly re-render Static elements\n const [isClearing, setIsClearing] = useState(false)\n\n const textInputColumns = useTerminalSize().columns - PASTE_HERE_MSG.length - 1\n\n useEffect(() => {\n if (isClearing) {\n clearTerminal()\n setIsClearing(false)\n }\n }, [isClearing])\n\n // Retry logic\n useEffect(() => {\n if (oauthStatus.state === 'about_to_retry') {\n setIsClearing(true)\n setTimeout(() => {\n setOAuthStatus(oauthStatus.nextState)\n }, 1000)\n }\n }, [oauthStatus])\n\n useInput(async (_, key) => {\n if (key.return) {\n if (oauthStatus.state === 'idle') {\n setOAuthStatus({ state: 'ready_to_start' })\n } else if (oauthStatus.state === 'success') {\n await clearTerminal() // needed to clear out Static components\n onDone()\n } else if (oauthStatus.state === 'error' && oauthStatus.toRetry) {\n setPastedCode('')\n setOAuthStatus({\n state: 'about_to_retry',\n nextState: oauthStatus.toRetry,\n })\n }\n }\n })\n\n async function handleSubmitCode(value: string, url: string) {\n try {\n // Expecting format \"authorizationCode#state\" from the authorization callback URL\n const [authorizationCode, state] = value.split('#')\n\n if (!authorizationCode || !state) {\n setOAuthStatus({\n state: 'error',\n message: 'Invalid code. Please make sure the full code was copied',\n toRetry: { state: 'waiting_for_login', url },\n })\n return\n }\n\n // Track which path the user is taking (manual code entry)\n\n oauthService.processCallback({\n authorizationCode,\n state,\n useManualRedirect: true,\n })\n } catch (err) {\n logError(err)\n setOAuthStatus({\n state: 'error',\n message: (err as Error).message,\n toRetry: { state: 'waiting_for_login', url },\n })\n }\n }\n\n const startOAuth = useCallback(async () => {\n try {\n const result = await oauthService\n .startOAuthFlow(async url => {\n setOAuthStatus({ state: 'waiting_for_login', url })\n setTimeout(() => setShowPastePrompt(true), 3000)\n })\n .catch(err => {\n // Handle token exchange errors specifically\n if (err.message.includes('Token exchange failed')) {\n setOAuthStatus({\n state: 'error',\n message:\n 'Failed to exchange authorization code for access token. Please try again.',\n toRetry: { state: 'ready_to_start' },\n })\n } else {\n // Handle other errors\n setOAuthStatus({\n state: 'error',\n message: err.message,\n toRetry: { state: 'ready_to_start' },\n })\n }\n throw err\n })\n\n setOAuthStatus({ state: 'creating_api_key' })\n\n const apiKey = await createAndStoreApiKey(result.accessToken).catch(\n err => {\n setOAuthStatus({\n state: 'error',\n message: 'Failed to create API key: ' + err.message,\n toRetry: { state: 'ready_to_start' },\n })\n\n throw err\n },\n )\n\n if (apiKey) {\n setOAuthStatus({ state: 'success', apiKey })\n sendNotification({ message: 'Minto login successful' })\n } else {\n setOAuthStatus({\n state: 'error',\n message:\n \"Unable to create API key. The server accepted the request but didn't return a key.\",\n toRetry: { state: 'ready_to_start' },\n })\n }\n } catch (err) {\n const errorMessage = (err as Error).message\n }\n }, [oauthService, setShowPastePrompt])\n\n useEffect(() => {\n if (oauthStatus.state === 'ready_to_start') {\n startOAuth()\n }\n }, [oauthStatus.state, startOAuth])\n\n // Helper function to render the appropriate status message\n function renderStatusMessage(): React.ReactNode {\n switch (oauthStatus.state) {\n case 'idle':\n return (\n <Box flexDirection=\"column\" gap={1}>\n <Text bold>\n {PRODUCT_NAME} is billed based on API usage through your Anthropic\n Console account.\n </Text>\n\n <Box>\n <Text>\n Pricing may evolve as we move towards general availability.\n </Text>\n </Box>\n\n <Box marginTop={1}>\n <Text color={theme.permission}>\n Press <Text bold>Enter</Text> to login to your Anthropic Console\n account\u2026\n </Text>\n </Box>\n </Box>\n )\n\n case 'waiting_for_login':\n return (\n <Box flexDirection=\"column\" gap={1}>\n {!showPastePrompt && (\n <Box>\n <SimpleSpinner />\n <Text>Opening browser to sign in\u2026</Text>\n </Box>\n )}\n\n {showPastePrompt && (\n <Box>\n <Text>{PASTE_HERE_MSG}</Text>\n <TextInput\n value={pastedCode}\n onChange={setPastedCode}\n onSubmit={(value: string) =>\n handleSubmitCode(value, oauthStatus.url)\n }\n cursorOffset={cursorOffset}\n onChangeCursorOffset={setCursorOffset}\n columns={textInputColumns}\n />\n </Box>\n )}\n </Box>\n )\n\n case 'creating_api_key':\n return (\n <Box flexDirection=\"column\" gap={1}>\n <Box>\n <SimpleSpinner />\n <Text>Creating API key for Minto\u2026</Text>\n </Box>\n </Box>\n )\n\n case 'about_to_retry':\n return (\n <Box flexDirection=\"column\" gap={1}>\n <Text color={theme.permission}>Retrying\u2026</Text>\n </Box>\n )\n\n case 'success':\n return (\n <Box flexDirection=\"column\" gap={1}>\n <Text color={theme.success}>\n Login successful. Press <Text bold>Enter</Text> to continue\u2026\n </Text>\n </Box>\n )\n\n case 'error':\n return (\n <Box flexDirection=\"column\" gap={1}>\n <Text color={theme.error}>OAuth error: {oauthStatus.message}</Text>\n\n {oauthStatus.toRetry && (\n <Box marginTop={1}>\n <Text color={theme.permission}>\n Press <Text bold>Enter</Text> to retry.\n </Text>\n </Box>\n )}\n </Box>\n )\n\n default:\n return null\n }\n }\n\n // We need to render the copy-able URL statically to prevent Ink <Text> from inserting\n // newlines in the middle of the URL (this breaks Safari). Because <Static> components are\n // only rendered once top-to-bottom, we also need to make everything above the URL static.\n const staticItems: Record<string, React.JSX.Element> = {}\n if (!isClearing) {\n staticItems.header = (\n <Box key=\"header\" flexDirection=\"column\" gap={1}>\n <WelcomeBox />\n <Box paddingBottom={1} paddingLeft={1}>\n <AsciiLogo />\n </Box>\n </Box>\n )\n }\n if (oauthStatus.state === 'waiting_for_login' && showPastePrompt) {\n staticItems.urlToCopy = (\n <Box flexDirection=\"column\" key=\"urlToCopy\" gap={1} paddingBottom={1}>\n <Box paddingX={1}>\n <Text color={SEMANTIC_COLORS.dim}>\n Browser didn&apos;t open? Use the url below to sign in:\n </Text>\n </Box>\n <Box width={1000}>\n <Text color={SEMANTIC_COLORS.dim}>{oauthStatus.url}</Text>\n </Box>\n </Box>\n )\n }\n return (\n <Box flexDirection=\"column\" gap={1}>\n <Static\n items={Object.keys(staticItems)}\n children={(item: string) => staticItems[item]}\n />\n <Box paddingLeft={1} flexDirection=\"column\" gap={1}>\n {renderStatusMessage()}\n </Box>\n </Box>\n )\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,11 +1,12 @@
1
1
  import * as React from "react";
2
2
  import { Box, Text } from "ink";
3
+ import { SEMANTIC_COLORS } from "../constants/colors.js";
3
4
  function Cost({ costUSD, durationMs, debug }) {
4
5
  if (!debug) {
5
6
  return null;
6
7
  }
7
8
  const durationInSeconds = (durationMs / 1e3).toFixed(1);
8
- return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", minWidth: 23, width: 23 }, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, "Cost: $", costUSD.toFixed(4), " (", durationInSeconds, "s)"));
9
+ return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", minWidth: 23, width: 23 }, /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.dim }, "Cost: $", costUSD.toFixed(4), " (", durationInSeconds, "s)"));
9
10
  }
10
11
  export {
11
12
  Cost
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/components/Cost.tsx"],
4
- "sourcesContent": ["import * as React from 'react'\nimport { Box, Text } from 'ink'\n\ntype Props = {\n costUSD: number\n durationMs: number\n debug: boolean\n}\n\nexport function Cost({ costUSD, durationMs, debug }: Props): React.ReactNode {\n if (!debug) {\n return null\n }\n\n const durationInSeconds = (durationMs / 1000).toFixed(1)\n return (\n <Box flexDirection=\"column\" minWidth={23} width={23}>\n <Text dimColor>\n Cost: ${costUSD.toFixed(4)} ({durationInSeconds}s)\n </Text>\n </Box>\n )\n}\n"],
5
- "mappings": "AAAA,YAAY,WAAW;AACvB,SAAS,KAAK,YAAY;AAQnB,SAAS,KAAK,EAAE,SAAS,YAAY,MAAM,GAA2B;AAC3E,MAAI,CAAC,OAAO;AACV,WAAO;AAAA,EACT;AAEA,QAAM,qBAAqB,aAAa,KAAM,QAAQ,CAAC;AACvD,SACE,oCAAC,OAAI,eAAc,UAAS,UAAU,IAAI,OAAO,MAC/C,oCAAC,QAAK,UAAQ,QAAC,WACL,QAAQ,QAAQ,CAAC,GAAE,MAAG,mBAAkB,IAClD,CACF;AAEJ;",
4
+ "sourcesContent": ["import * as React from 'react'\nimport { Box, Text } from 'ink'\nimport { SEMANTIC_COLORS } from '@constants/colors'\n\ntype Props = {\n costUSD: number\n durationMs: number\n debug: boolean\n}\n\nexport function Cost({ costUSD, durationMs, debug }: Props): React.ReactNode {\n if (!debug) {\n return null\n }\n\n const durationInSeconds = (durationMs / 1000).toFixed(1)\n return (\n <Box flexDirection=\"column\" minWidth={23} width={23}>\n <Text color={SEMANTIC_COLORS.dim}>\n Cost: ${costUSD.toFixed(4)} ({durationInSeconds}s)\n </Text>\n </Box>\n )\n}\n"],
5
+ "mappings": "AAAA,YAAY,WAAW;AACvB,SAAS,KAAK,YAAY;AAC1B,SAAS,uBAAuB;AAQzB,SAAS,KAAK,EAAE,SAAS,YAAY,MAAM,GAA2B;AAC3E,MAAI,CAAC,OAAO;AACV,WAAO;AAAA,EACT;AAEA,QAAM,qBAAqB,aAAa,KAAM,QAAQ,CAAC;AACvD,SACE,oCAAC,OAAI,eAAc,UAAS,UAAU,IAAI,OAAO,MAC/C,oCAAC,QAAK,OAAO,gBAAgB,OAAK,WACxB,QAAQ,QAAQ,CAAC,GAAE,MAAG,mBAAkB,IAClD,CACF;AAEJ;",
6
6
  "names": []
7
7
  }