@within-7/minto 0.2.0 → 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 (254) hide show
  1. package/dist/commands/agents/AgentsCommand.js +22 -24
  2. package/dist/commands/agents/AgentsCommand.js.map +2 -2
  3. package/dist/commands/context.js +2 -1
  4. package/dist/commands/context.js.map +2 -2
  5. package/dist/commands/export.js +2 -1
  6. package/dist/commands/export.js.map +2 -2
  7. package/dist/commands/mcp-interactive.js +7 -6
  8. package/dist/commands/mcp-interactive.js.map +2 -2
  9. package/dist/commands/model.js +3 -2
  10. package/dist/commands/model.js.map +2 -2
  11. package/dist/commands/permissions.js +4 -3
  12. package/dist/commands/permissions.js.map +2 -2
  13. package/dist/commands/plugin/AddMarketplaceForm.js +3 -2
  14. package/dist/commands/plugin/AddMarketplaceForm.js.map +2 -2
  15. package/dist/commands/plugin/ConfirmDialog.js +2 -1
  16. package/dist/commands/plugin/ConfirmDialog.js.map +2 -2
  17. package/dist/commands/plugin/ErrorView.js +2 -1
  18. package/dist/commands/plugin/ErrorView.js.map +2 -2
  19. package/dist/commands/plugin/InstalledPluginsByMarketplace.js +5 -4
  20. package/dist/commands/plugin/InstalledPluginsByMarketplace.js.map +2 -2
  21. package/dist/commands/plugin/InstalledPluginsManager.js +5 -4
  22. package/dist/commands/plugin/InstalledPluginsManager.js.map +2 -2
  23. package/dist/commands/plugin/MainMenu.js +2 -1
  24. package/dist/commands/plugin/MainMenu.js.map +2 -2
  25. package/dist/commands/plugin/MarketplaceManager.js +5 -4
  26. package/dist/commands/plugin/MarketplaceManager.js.map +2 -2
  27. package/dist/commands/plugin/MarketplaceSelector.js +4 -3
  28. package/dist/commands/plugin/MarketplaceSelector.js.map +2 -2
  29. package/dist/commands/plugin/PlaceholderScreen.js +3 -2
  30. package/dist/commands/plugin/PlaceholderScreen.js.map +2 -2
  31. package/dist/commands/plugin/PluginBrowser.js +6 -5
  32. package/dist/commands/plugin/PluginBrowser.js.map +2 -2
  33. package/dist/commands/plugin/PluginDetailsInstall.js +5 -4
  34. package/dist/commands/plugin/PluginDetailsInstall.js.map +2 -2
  35. package/dist/commands/plugin/PluginDetailsManage.js +4 -3
  36. package/dist/commands/plugin/PluginDetailsManage.js.map +2 -2
  37. package/dist/commands/plugin.js +16 -15
  38. package/dist/commands/plugin.js.map +2 -2
  39. package/dist/commands/sandbox.js +4 -3
  40. package/dist/commands/sandbox.js.map +2 -2
  41. package/dist/commands/setup.js +2 -1
  42. package/dist/commands/setup.js.map +2 -2
  43. package/dist/commands/status.js +2 -1
  44. package/dist/commands/status.js.map +2 -2
  45. package/dist/commands/undo.js +245 -0
  46. package/dist/commands/undo.js.map +7 -0
  47. package/dist/commands.js +2 -0
  48. package/dist/commands.js.map +2 -2
  49. package/dist/components/AgentThinkingBlock.js +1 -1
  50. package/dist/components/AgentThinkingBlock.js.map +2 -2
  51. package/dist/components/AsciiLogo.js +7 -8
  52. package/dist/components/AsciiLogo.js.map +2 -2
  53. package/dist/components/AskUserQuestionDialog/AskUserQuestionDialog.js +3 -2
  54. package/dist/components/AskUserQuestionDialog/AskUserQuestionDialog.js.map +2 -2
  55. package/dist/components/AskUserQuestionDialog/QuestionView.js +2 -1
  56. package/dist/components/AskUserQuestionDialog/QuestionView.js.map +2 -2
  57. package/dist/components/CollapsibleHint.js +2 -1
  58. package/dist/components/CollapsibleHint.js.map +2 -2
  59. package/dist/components/Config.js +3 -2
  60. package/dist/components/Config.js.map +2 -2
  61. package/dist/components/ConsoleOAuthFlow.js +2 -1
  62. package/dist/components/ConsoleOAuthFlow.js.map +2 -2
  63. package/dist/components/Cost.js +2 -1
  64. package/dist/components/Cost.js.map +2 -2
  65. package/dist/components/HeaderBar.js +13 -8
  66. package/dist/components/HeaderBar.js.map +2 -2
  67. package/dist/components/HistorySearchOverlay.js +4 -3
  68. package/dist/components/HistorySearchOverlay.js.map +2 -2
  69. package/dist/components/HotkeyHelpPanel.js +8 -11
  70. package/dist/components/HotkeyHelpPanel.js.map +2 -2
  71. package/dist/components/InvalidConfigDialog.js +2 -1
  72. package/dist/components/InvalidConfigDialog.js.map +2 -2
  73. package/dist/components/Logo.js +23 -67
  74. package/dist/components/Logo.js.map +2 -2
  75. package/dist/components/MCPServerApprovalDialog.js +2 -1
  76. package/dist/components/MCPServerApprovalDialog.js.map +2 -2
  77. package/dist/components/MCPServerDialogCopy.js +2 -1
  78. package/dist/components/MCPServerDialogCopy.js.map +2 -2
  79. package/dist/components/MCPServerMultiselectDialog.js +2 -1
  80. package/dist/components/MCPServerMultiselectDialog.js.map +2 -2
  81. package/dist/components/MessageSelector.js +4 -3
  82. package/dist/components/MessageSelector.js.map +2 -2
  83. package/dist/components/ModeIndicator.js +2 -1
  84. package/dist/components/ModeIndicator.js.map +2 -2
  85. package/dist/components/ModelConfig.js +4 -3
  86. package/dist/components/ModelConfig.js.map +2 -2
  87. package/dist/components/ModelListManager.js +4 -3
  88. package/dist/components/ModelListManager.js.map +2 -2
  89. package/dist/components/ModelSelector/ModelSelector.js +26 -13
  90. package/dist/components/ModelSelector/ModelSelector.js.map +2 -2
  91. package/dist/components/Onboarding.js +3 -2
  92. package/dist/components/Onboarding.js.map +2 -2
  93. package/dist/components/OperationSummary.js +130 -0
  94. package/dist/components/OperationSummary.js.map +7 -0
  95. package/dist/components/PromptInput.js +88 -75
  96. package/dist/components/PromptInput.js.map +2 -2
  97. package/dist/components/SensitiveFileWarning.js +31 -0
  98. package/dist/components/SensitiveFileWarning.js.map +7 -0
  99. package/dist/components/Spinner.js +71 -22
  100. package/dist/components/Spinner.js.map +2 -2
  101. package/dist/components/StructuredDiff.js +6 -8
  102. package/dist/components/StructuredDiff.js.map +2 -2
  103. package/dist/components/SubagentBlock.js +4 -2
  104. package/dist/components/SubagentBlock.js.map +2 -2
  105. package/dist/components/SubagentProgress.js +7 -4
  106. package/dist/components/SubagentProgress.js.map +2 -2
  107. package/dist/components/TaskCard.js +14 -11
  108. package/dist/components/TaskCard.js.map +2 -2
  109. package/dist/components/TextInput.js +9 -1
  110. package/dist/components/TextInput.js.map +2 -2
  111. package/dist/components/TodoPanel.js +44 -26
  112. package/dist/components/TodoPanel.js.map +2 -2
  113. package/dist/components/ToolUseLoader.js +2 -2
  114. package/dist/components/ToolUseLoader.js.map +2 -2
  115. package/dist/components/TreeConnector.js +4 -3
  116. package/dist/components/TreeConnector.js.map +2 -2
  117. package/dist/components/TrustDialog.js +2 -1
  118. package/dist/components/TrustDialog.js.map +2 -2
  119. package/dist/components/binary-feedback/BinaryFeedbackView.js +2 -1
  120. package/dist/components/binary-feedback/BinaryFeedbackView.js.map +2 -2
  121. package/dist/components/messages/AssistantTextMessage.js +17 -9
  122. package/dist/components/messages/AssistantTextMessage.js.map +2 -2
  123. package/dist/components/messages/AssistantToolUseMessage.js +8 -4
  124. package/dist/components/messages/AssistantToolUseMessage.js.map +2 -2
  125. package/dist/components/messages/GroupRenderer.js +2 -1
  126. package/dist/components/messages/GroupRenderer.js.map +2 -2
  127. package/dist/components/messages/NestedTasksPreview.js +13 -1
  128. package/dist/components/messages/NestedTasksPreview.js.map +2 -2
  129. package/dist/components/messages/ParallelTasksGroupView.js +4 -3
  130. package/dist/components/messages/ParallelTasksGroupView.js.map +2 -2
  131. package/dist/components/messages/TaskInModuleView.js +35 -15
  132. package/dist/components/messages/TaskInModuleView.js.map +2 -2
  133. package/dist/components/messages/TaskOutputContent.js +9 -6
  134. package/dist/components/messages/TaskOutputContent.js.map +2 -2
  135. package/dist/components/messages/UserPromptMessage.js +2 -2
  136. package/dist/components/messages/UserPromptMessage.js.map +2 -2
  137. package/dist/constants/colors.js +90 -72
  138. package/dist/constants/colors.js.map +2 -2
  139. package/dist/constants/toolInputExamples.js +84 -0
  140. package/dist/constants/toolInputExamples.js.map +7 -0
  141. package/dist/core/backupManager.js +321 -0
  142. package/dist/core/backupManager.js.map +7 -0
  143. package/dist/core/costTracker.js +9 -18
  144. package/dist/core/costTracker.js.map +2 -2
  145. package/dist/core/gitAutoCommit.js +287 -0
  146. package/dist/core/gitAutoCommit.js.map +7 -0
  147. package/dist/core/index.js +3 -0
  148. package/dist/core/index.js.map +2 -2
  149. package/dist/core/operationTracker.js +212 -0
  150. package/dist/core/operationTracker.js.map +7 -0
  151. package/dist/core/permissions/rules/allowedToolsRule.js +1 -1
  152. package/dist/core/permissions/rules/allowedToolsRule.js.map +2 -2
  153. package/dist/core/permissions/rules/autoEscalationRule.js +5 -0
  154. package/dist/core/permissions/rules/autoEscalationRule.js.map +2 -2
  155. package/dist/core/permissions/rules/projectBoundaryRule.js +5 -0
  156. package/dist/core/permissions/rules/projectBoundaryRule.js.map +2 -2
  157. package/dist/core/permissions/rules/sensitivePathsRule.js +5 -0
  158. package/dist/core/permissions/rules/sensitivePathsRule.js.map +2 -2
  159. package/dist/core/tokenStats.js +9 -0
  160. package/dist/core/tokenStats.js.map +7 -0
  161. package/dist/core/tokenStatsManager.js +331 -0
  162. package/dist/core/tokenStatsManager.js.map +7 -0
  163. package/dist/entrypoints/cli.js +115 -87
  164. package/dist/entrypoints/cli.js.map +2 -2
  165. package/dist/hooks/useAgentTokenStats.js +72 -0
  166. package/dist/hooks/useAgentTokenStats.js.map +7 -0
  167. package/dist/hooks/useAgentTranscripts.js +30 -6
  168. package/dist/hooks/useAgentTranscripts.js.map +2 -2
  169. package/dist/hooks/useLogMessages.js +12 -1
  170. package/dist/hooks/useLogMessages.js.map +2 -2
  171. package/dist/i18n/locales/en.js +6 -5
  172. package/dist/i18n/locales/en.js.map +2 -2
  173. package/dist/i18n/locales/zh-CN.js +6 -5
  174. package/dist/i18n/locales/zh-CN.js.map +2 -2
  175. package/dist/i18n/types.js.map +1 -1
  176. package/dist/permissions.js +28 -1
  177. package/dist/permissions.js.map +2 -2
  178. package/dist/query.js +78 -4
  179. package/dist/query.js.map +3 -3
  180. package/dist/screens/REPL.js +23 -3
  181. package/dist/screens/REPL.js.map +2 -2
  182. package/dist/services/claude.js +54 -3
  183. package/dist/services/claude.js.map +2 -2
  184. package/dist/services/intelligentCompactor.js +1 -1
  185. package/dist/services/intelligentCompactor.js.map +2 -2
  186. package/dist/services/mcpClient.js +81 -25
  187. package/dist/services/mcpClient.js.map +2 -2
  188. package/dist/services/sandbox/filesystemBoundary.js +58 -17
  189. package/dist/services/sandbox/filesystemBoundary.js.map +2 -2
  190. package/dist/tools/AskExpertModelTool/AskExpertModelTool.js +3 -2
  191. package/dist/tools/AskExpertModelTool/AskExpertModelTool.js.map +2 -2
  192. package/dist/tools/AskUserQuestionTool/AskUserQuestionTool.js +2 -1
  193. package/dist/tools/AskUserQuestionTool/AskUserQuestionTool.js.map +2 -2
  194. package/dist/tools/BashTool/BashTool.js +22 -3
  195. package/dist/tools/BashTool/BashTool.js.map +2 -2
  196. package/dist/tools/BashTool/prompt.js +178 -34
  197. package/dist/tools/BashTool/prompt.js.map +2 -2
  198. package/dist/tools/FileEditTool/prompt.js +6 -3
  199. package/dist/tools/FileEditTool/prompt.js.map +2 -2
  200. package/dist/tools/FileWriteTool/prompt.js +4 -2
  201. package/dist/tools/FileWriteTool/prompt.js.map +2 -2
  202. package/dist/tools/MultiEditTool/prompt.js +5 -3
  203. package/dist/tools/MultiEditTool/prompt.js.map +2 -2
  204. package/dist/tools/NotebookEditTool/NotebookEditTool.js +2 -1
  205. package/dist/tools/NotebookEditTool/NotebookEditTool.js.map +2 -2
  206. package/dist/tools/PlanModeTool/EnterPlanModeTool.js +3 -2
  207. package/dist/tools/PlanModeTool/EnterPlanModeTool.js.map +2 -2
  208. package/dist/tools/PlanModeTool/ExitPlanModeTool.js +3 -2
  209. package/dist/tools/PlanModeTool/ExitPlanModeTool.js.map +2 -2
  210. package/dist/tools/PlanModeTool/prompt.js +1 -1
  211. package/dist/tools/PlanModeTool/prompt.js.map +1 -1
  212. package/dist/tools/SkillTool/SkillTool.js +4 -3
  213. package/dist/tools/SkillTool/SkillTool.js.map +2 -2
  214. package/dist/tools/SkillTool/prompt.js +1 -1
  215. package/dist/tools/SkillTool/prompt.js.map +1 -1
  216. package/dist/tools/TaskOutputTool/TaskOutputTool.js +3 -2
  217. package/dist/tools/TaskOutputTool/TaskOutputTool.js.map +2 -2
  218. package/dist/tools/TaskTool/TaskTool.js +8 -0
  219. package/dist/tools/TaskTool/TaskTool.js.map +2 -2
  220. package/dist/utils/CircuitBreaker.js +242 -0
  221. package/dist/utils/CircuitBreaker.js.map +7 -0
  222. package/dist/utils/ask.js +2 -0
  223. package/dist/utils/ask.js.map +2 -2
  224. package/dist/utils/config.js +47 -5
  225. package/dist/utils/config.js.map +2 -2
  226. package/dist/utils/credentials/CredentialStore.js +1 -0
  227. package/dist/utils/credentials/CredentialStore.js.map +7 -0
  228. package/dist/utils/credentials/EncryptedFileStore.js +157 -0
  229. package/dist/utils/credentials/EncryptedFileStore.js.map +7 -0
  230. package/dist/utils/credentials/index.js +37 -0
  231. package/dist/utils/credentials/index.js.map +7 -0
  232. package/dist/utils/credentials/migration.js +82 -0
  233. package/dist/utils/credentials/migration.js.map +7 -0
  234. package/dist/utils/markdown.js +13 -1
  235. package/dist/utils/markdown.js.map +2 -2
  236. package/dist/utils/permissions/filesystem.js +5 -1
  237. package/dist/utils/permissions/filesystem.js.map +2 -2
  238. package/dist/utils/safePath.js +132 -0
  239. package/dist/utils/safePath.js.map +7 -0
  240. package/dist/utils/sensitiveFiles.js +125 -0
  241. package/dist/utils/sensitiveFiles.js.map +7 -0
  242. package/dist/utils/taskDisplayUtils.js +9 -9
  243. package/dist/utils/taskDisplayUtils.js.map +2 -2
  244. package/dist/utils/theme.js +6 -6
  245. package/dist/utils/theme.js.map +1 -1
  246. package/dist/utils/toolRiskClassification.js +207 -0
  247. package/dist/utils/toolRiskClassification.js.map +7 -0
  248. package/dist/utils/tooling/safeRender.js +5 -4
  249. package/dist/utils/tooling/safeRender.js.map +2 -2
  250. package/dist/version.js +2 -2
  251. package/dist/version.js.map +1 -1
  252. package/package.json +9 -7
  253. package/dist/hooks/useCancelRequest.js +0 -31
  254. package/dist/hooks/useCancelRequest.js.map +0 -7
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/commands/status.tsx"],
4
- "sourcesContent": ["/**\n * Status Command\n *\n * Shows version information, connection status, and system health.\n */\n\nimport React from 'react'\nimport { Box, Text } from 'ink'\nimport type { Command } from '@commands'\nimport { getModelManager } from '@utils/model'\nimport { getCwd } from '@utils/state'\nimport { MACRO } from '@constants/macros'\n\ninterface StatusInfo {\n version: string\n nodeVersion: string\n bunVersion: string | null\n platform: string\n cwd: string\n modelInfo: {\n name: string\n provider: string\n contextLength: number\n } | null\n apiConnected: boolean\n}\n\nconst StatusDisplay = ({ status }: { status: StatusInfo }) => {\n return (\n <Box flexDirection=\"column\" marginY={1}>\n {/* Header */}\n <Box marginBottom={1}>\n <Text bold color=\"cyan\">\n Minto Status\n </Text>\n </Box>\n\n {/* Version info */}\n <Box flexDirection=\"column\" marginBottom={1}>\n <Text bold>Version Info</Text>\n <Box paddingLeft={2} flexDirection=\"column\">\n <Text>\n <Text dimColor>Minto: </Text>\n <Text color=\"green\">v{status.version}</Text>\n </Text>\n <Text>\n <Text dimColor>Node.js: </Text>\n <Text>{status.nodeVersion}</Text>\n </Text>\n {status.bunVersion && (\n <Text>\n <Text dimColor>Bun: </Text>\n <Text>{status.bunVersion}</Text>\n </Text>\n )}\n <Text>\n <Text dimColor>Platform: </Text>\n <Text>{status.platform}</Text>\n </Text>\n </Box>\n </Box>\n\n {/* Environment */}\n <Box flexDirection=\"column\" marginBottom={1}>\n <Text bold>Environment</Text>\n <Box paddingLeft={2} flexDirection=\"column\">\n <Text>\n <Text dimColor>CWD: </Text>\n <Text>{status.cwd}</Text>\n </Text>\n </Box>\n </Box>\n\n {/* Model info */}\n <Box flexDirection=\"column\" marginBottom={1}>\n <Text bold>Model Configuration</Text>\n <Box paddingLeft={2} flexDirection=\"column\">\n {status.modelInfo ? (\n <>\n <Text>\n <Text dimColor>Model: </Text>\n <Text color=\"cyan\">{status.modelInfo.name}</Text>\n </Text>\n <Text>\n <Text dimColor>Provider: </Text>\n <Text>{status.modelInfo.provider}</Text>\n </Text>\n <Text>\n <Text dimColor>Context: </Text>\n <Text>\n {(status.modelInfo.contextLength / 1000).toFixed(0)}k tokens\n </Text>\n </Text>\n </>\n ) : (\n <Text color=\"yellow\">No model configured</Text>\n )}\n </Box>\n </Box>\n\n {/* API Status */}\n <Box flexDirection=\"column\">\n <Text bold>API Connection</Text>\n <Box paddingLeft={2}>\n <Text>\n <Text dimColor>Status: </Text>\n {status.apiConnected ? (\n <Text color=\"green\">\u25CF Connected</Text>\n ) : (\n <Text color=\"red\">\u25CB Not connected</Text>\n )}\n </Text>\n </Box>\n </Box>\n </Box>\n )\n}\n\nasync function getStatusInfo(): Promise<StatusInfo> {\n let modelInfo: StatusInfo['modelInfo'] = null\n let apiConnected = false\n\n try {\n const modelManager = getModelManager()\n const profile = modelManager.resolveModel('main')\n if (profile) {\n modelInfo = {\n name: profile.name || profile.modelName,\n provider: profile.provider || 'anthropic',\n contextLength: profile.contextLength || 200_000,\n }\n apiConnected = true // If we can resolve model, API is configured\n }\n } catch {\n // Model not configured\n }\n\n // Check for Bun\n let bunVersion: string | null = null\n if (typeof Bun !== 'undefined') {\n bunVersion = Bun.version\n }\n\n return {\n version: MACRO.VERSION,\n nodeVersion: process.version,\n bunVersion,\n platform: `${process.platform} (${process.arch})`,\n cwd: getCwd(),\n modelInfo,\n apiConnected,\n }\n}\n\nconst command: Command = {\n name: 'status',\n description: 'Display version and connection information',\n isEnabled: true,\n isHidden: false,\n type: 'local-jsx',\n\n userFacingName() {\n return this.name\n },\n\n async call(onDone) {\n const status = await getStatusInfo()\n\n setTimeout(() => onDone(), 100)\n\n return <StatusDisplay status={status} />\n },\n}\n\nexport default command\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * Status Command\n *\n * Shows version information, connection status, and system health.\n */\n\nimport React from 'react'\nimport { Box, Text } from 'ink'\nimport type { Command } from '@commands'\nimport { getModelManager } from '@utils/model'\nimport { getCwd } from '@utils/state'\nimport { MACRO } from '@constants/macros'\nimport { SEMANTIC_COLORS } from '@constants/colors'\n\ninterface StatusInfo {\n version: string\n nodeVersion: string\n bunVersion: string | null\n platform: string\n cwd: string\n modelInfo: {\n name: string\n provider: string\n contextLength: number\n } | null\n apiConnected: boolean\n}\n\nconst StatusDisplay = ({ status }: { status: StatusInfo }) => {\n return (\n <Box flexDirection=\"column\" marginY={1}>\n {/* Header */}\n <Box marginBottom={1}>\n <Text bold color=\"cyan\">\n Minto Status\n </Text>\n </Box>\n\n {/* Version info */}\n <Box flexDirection=\"column\" marginBottom={1}>\n <Text bold>Version Info</Text>\n <Box paddingLeft={2} flexDirection=\"column\">\n <Text>\n <Text color={SEMANTIC_COLORS.dim}>Minto: </Text>\n <Text color=\"green\">v{status.version}</Text>\n </Text>\n <Text>\n <Text color={SEMANTIC_COLORS.dim}>Node.js: </Text>\n <Text>{status.nodeVersion}</Text>\n </Text>\n {status.bunVersion && (\n <Text>\n <Text color={SEMANTIC_COLORS.dim}>Bun: </Text>\n <Text>{status.bunVersion}</Text>\n </Text>\n )}\n <Text>\n <Text color={SEMANTIC_COLORS.dim}>Platform: </Text>\n <Text>{status.platform}</Text>\n </Text>\n </Box>\n </Box>\n\n {/* Environment */}\n <Box flexDirection=\"column\" marginBottom={1}>\n <Text bold>Environment</Text>\n <Box paddingLeft={2} flexDirection=\"column\">\n <Text>\n <Text color={SEMANTIC_COLORS.dim}>CWD: </Text>\n <Text>{status.cwd}</Text>\n </Text>\n </Box>\n </Box>\n\n {/* Model info */}\n <Box flexDirection=\"column\" marginBottom={1}>\n <Text bold>Model Configuration</Text>\n <Box paddingLeft={2} flexDirection=\"column\">\n {status.modelInfo ? (\n <>\n <Text>\n <Text color={SEMANTIC_COLORS.dim}>Model: </Text>\n <Text color=\"cyan\">{status.modelInfo.name}</Text>\n </Text>\n <Text>\n <Text color={SEMANTIC_COLORS.dim}>Provider: </Text>\n <Text>{status.modelInfo.provider}</Text>\n </Text>\n <Text>\n <Text color={SEMANTIC_COLORS.dim}>Context: </Text>\n <Text>\n {(status.modelInfo.contextLength / 1000).toFixed(0)}k tokens\n </Text>\n </Text>\n </>\n ) : (\n <Text color=\"yellow\">No model configured</Text>\n )}\n </Box>\n </Box>\n\n {/* API Status */}\n <Box flexDirection=\"column\">\n <Text bold>API Connection</Text>\n <Box paddingLeft={2}>\n <Text>\n <Text color={SEMANTIC_COLORS.dim}>Status: </Text>\n {status.apiConnected ? (\n <Text color=\"green\">\u25CF Connected</Text>\n ) : (\n <Text color=\"red\">\u25CB Not connected</Text>\n )}\n </Text>\n </Box>\n </Box>\n </Box>\n )\n}\n\nasync function getStatusInfo(): Promise<StatusInfo> {\n let modelInfo: StatusInfo['modelInfo'] = null\n let apiConnected = false\n\n try {\n const modelManager = getModelManager()\n const profile = modelManager.resolveModel('main')\n if (profile) {\n modelInfo = {\n name: profile.name || profile.modelName,\n provider: profile.provider || 'anthropic',\n contextLength: profile.contextLength || 200_000,\n }\n apiConnected = true // If we can resolve model, API is configured\n }\n } catch {\n // Model not configured\n }\n\n // Check for Bun\n let bunVersion: string | null = null\n if (typeof Bun !== 'undefined') {\n bunVersion = Bun.version\n }\n\n return {\n version: MACRO.VERSION,\n nodeVersion: process.version,\n bunVersion,\n platform: `${process.platform} (${process.arch})`,\n cwd: getCwd(),\n modelInfo,\n apiConnected,\n }\n}\n\nconst command: Command = {\n name: 'status',\n description: 'Display version and connection information',\n isEnabled: true,\n isHidden: false,\n type: 'local-jsx',\n\n userFacingName() {\n return this.name\n },\n\n async call(onDone) {\n const status = await getStatusInfo()\n\n setTimeout(() => onDone(), 100)\n\n return <StatusDisplay status={status} />\n },\n}\n\nexport default command\n"],
5
+ "mappings": "AAMA,OAAO,WAAW;AAClB,SAAS,KAAK,YAAY;AAE1B,SAAS,uBAAuB;AAChC,SAAS,cAAc;AACvB,SAAS,aAAa;AACtB,SAAS,uBAAuB;AAgBhC,MAAM,gBAAgB,CAAC,EAAE,OAAO,MAA8B;AAC5D,SACE,oCAAC,OAAI,eAAc,UAAS,SAAS,KAEnC,oCAAC,OAAI,cAAc,KACjB,oCAAC,QAAK,MAAI,MAAC,OAAM,UAAO,cAExB,CACF,GAGA,oCAAC,OAAI,eAAc,UAAS,cAAc,KACxC,oCAAC,QAAK,MAAI,QAAC,cAAY,GACvB,oCAAC,OAAI,aAAa,GAAG,eAAc,YACjC,oCAAC,YACC,oCAAC,QAAK,OAAO,gBAAgB,OAAK,SAAO,GACzC,oCAAC,QAAK,OAAM,WAAQ,KAAE,OAAO,OAAQ,CACvC,GACA,oCAAC,YACC,oCAAC,QAAK,OAAO,gBAAgB,OAAK,WAAS,GAC3C,oCAAC,YAAM,OAAO,WAAY,CAC5B,GACC,OAAO,cACN,oCAAC,YACC,oCAAC,QAAK,OAAO,gBAAgB,OAAK,OAAK,GACvC,oCAAC,YAAM,OAAO,UAAW,CAC3B,GAEF,oCAAC,YACC,oCAAC,QAAK,OAAO,gBAAgB,OAAK,YAAU,GAC5C,oCAAC,YAAM,OAAO,QAAS,CACzB,CACF,CACF,GAGA,oCAAC,OAAI,eAAc,UAAS,cAAc,KACxC,oCAAC,QAAK,MAAI,QAAC,aAAW,GACtB,oCAAC,OAAI,aAAa,GAAG,eAAc,YACjC,oCAAC,YACC,oCAAC,QAAK,OAAO,gBAAgB,OAAK,OAAK,GACvC,oCAAC,YAAM,OAAO,GAAI,CACpB,CACF,CACF,GAGA,oCAAC,OAAI,eAAc,UAAS,cAAc,KACxC,oCAAC,QAAK,MAAI,QAAC,qBAAmB,GAC9B,oCAAC,OAAI,aAAa,GAAG,eAAc,YAChC,OAAO,YACN,0DACE,oCAAC,YACC,oCAAC,QAAK,OAAO,gBAAgB,OAAK,SAAO,GACzC,oCAAC,QAAK,OAAM,UAAQ,OAAO,UAAU,IAAK,CAC5C,GACA,oCAAC,YACC,oCAAC,QAAK,OAAO,gBAAgB,OAAK,YAAU,GAC5C,oCAAC,YAAM,OAAO,UAAU,QAAS,CACnC,GACA,oCAAC,YACC,oCAAC,QAAK,OAAO,gBAAgB,OAAK,WAAS,GAC3C,oCAAC,aACG,OAAO,UAAU,gBAAgB,KAAM,QAAQ,CAAC,GAAE,UACtD,CACF,CACF,IAEA,oCAAC,QAAK,OAAM,YAAS,qBAAmB,CAE5C,CACF,GAGA,oCAAC,OAAI,eAAc,YACjB,oCAAC,QAAK,MAAI,QAAC,gBAAc,GACzB,oCAAC,OAAI,aAAa,KAChB,oCAAC,YACC,oCAAC,QAAK,OAAO,gBAAgB,OAAK,UAAQ,GACzC,OAAO,eACN,oCAAC,QAAK,OAAM,WAAQ,kBAAW,IAE/B,oCAAC,QAAK,OAAM,SAAM,sBAAe,CAErC,CACF,CACF,CACF;AAEJ;AAEA,eAAe,gBAAqC;AAClD,MAAI,YAAqC;AACzC,MAAI,eAAe;AAEnB,MAAI;AACF,UAAM,eAAe,gBAAgB;AACrC,UAAM,UAAU,aAAa,aAAa,MAAM;AAChD,QAAI,SAAS;AACX,kBAAY;AAAA,QACV,MAAM,QAAQ,QAAQ,QAAQ;AAAA,QAC9B,UAAU,QAAQ,YAAY;AAAA,QAC9B,eAAe,QAAQ,iBAAiB;AAAA,MAC1C;AACA,qBAAe;AAAA,IACjB;AAAA,EACF,QAAQ;AAAA,EAER;AAGA,MAAI,aAA4B;AAChC,MAAI,OAAO,QAAQ,aAAa;AAC9B,iBAAa,IAAI;AAAA,EACnB;AAEA,SAAO;AAAA,IACL,SAAS,MAAM;AAAA,IACf,aAAa,QAAQ;AAAA,IACrB;AAAA,IACA,UAAU,GAAG,QAAQ,QAAQ,KAAK,QAAQ,IAAI;AAAA,IAC9C,KAAK,OAAO;AAAA,IACZ;AAAA,IACA;AAAA,EACF;AACF;AAEA,MAAM,UAAmB;AAAA,EACvB,MAAM;AAAA,EACN,aAAa;AAAA,EACb,WAAW;AAAA,EACX,UAAU;AAAA,EACV,MAAM;AAAA,EAEN,iBAAiB;AACf,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,KAAK,QAAQ;AACjB,UAAM,SAAS,MAAM,cAAc;AAEnC,eAAW,MAAM,OAAO,GAAG,GAAG;AAE9B,WAAO,oCAAC,iBAAc,QAAgB;AAAA,EACxC;AACF;AAEA,IAAO,iBAAQ;",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,245 @@
1
+ import React, { useState, useEffect } from "react";
2
+ import { Box, Text, useInput } from "ink";
3
+ import { SEMANTIC_COLORS } from "../constants/colors.js";
4
+ import { getCwd } from "../utils/state.js";
5
+ import {
6
+ listBackedUpFiles,
7
+ getBackupVersions,
8
+ restoreBackup
9
+ } from "../core/backupManager.js";
10
+ function formatTimestamp(timestamp) {
11
+ const date = new Date(timestamp);
12
+ const now = /* @__PURE__ */ new Date();
13
+ const diff = now.getTime() - timestamp;
14
+ if (diff < 60 * 60 * 1e3) {
15
+ const minutes = Math.floor(diff / (60 * 1e3));
16
+ return minutes <= 1 ? "\u521A\u521A" : `${minutes} \u5206\u949F\u524D`;
17
+ }
18
+ if (date.getDate() === now.getDate() && date.getMonth() === now.getMonth() && date.getFullYear() === now.getFullYear()) {
19
+ return `\u4ECA\u5929 ${date.getHours().toString().padStart(2, "0")}:${date.getMinutes().toString().padStart(2, "0")}`;
20
+ }
21
+ if (diff < 7 * 24 * 60 * 60 * 1e3) {
22
+ const days = ["\u65E5", "\u4E00", "\u4E8C", "\u4E09", "\u56DB", "\u4E94", "\u516D"];
23
+ return `\u5468${days[date.getDay()]} ${date.getHours().toString().padStart(2, "0")}:${date.getMinutes().toString().padStart(2, "0")}`;
24
+ }
25
+ return `${date.getMonth() + 1}/${date.getDate()} ${date.getHours().toString().padStart(2, "0")}:${date.getMinutes().toString().padStart(2, "0")}`;
26
+ }
27
+ function getRelativePath(filePath) {
28
+ const cwd = getCwd();
29
+ if (filePath.startsWith(cwd)) {
30
+ const relative = filePath.slice(cwd.length);
31
+ return relative.startsWith("/") ? relative.slice(1) : relative;
32
+ }
33
+ return filePath;
34
+ }
35
+ const FileListView = ({ files, selectedIndex, onSelect, onClose }) => {
36
+ useInput((input, key) => {
37
+ if (key.escape || input === "q") {
38
+ onClose();
39
+ } else if (key.return) {
40
+ if (files.length > 0 && files[selectedIndex]) {
41
+ onSelect(files[selectedIndex]);
42
+ }
43
+ }
44
+ });
45
+ if (files.length === 0) {
46
+ return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React.createElement(Box, { marginBottom: 1 }, /* @__PURE__ */ React.createElement(Text, { bold: true, color: SEMANTIC_COLORS.brand }, "\u64A4\u9500\u6587\u4EF6\u4FEE\u6539")), /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", paddingLeft: 1 }, /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.dim }, "\u6682\u65E0\u53EF\u64A4\u9500\u7684\u6587\u4EF6\u4FEE\u6539\u3002"), /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.muted }, " "), /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.dim }, "\u63D0\u793A\uFF1A\u4F7F\u7528 ", /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.info }, "--smart"), " ", "\u6A21\u5F0F\u542F\u52A8 Minto \u4EE5\u542F\u7528\u81EA\u52A8\u5907\u4EFD\u529F\u80FD\uFF1A"), /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.muted }, " minto --smart")), /* @__PURE__ */ React.createElement(Box, { marginTop: 2 }, /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.muted }, "\u6309 q \u6216 Esc \u9000\u51FA")));
47
+ }
48
+ return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React.createElement(Box, { marginBottom: 1 }, /* @__PURE__ */ React.createElement(Text, { bold: true, color: SEMANTIC_COLORS.brand }, "\u64A4\u9500\u6587\u4EF6\u4FEE\u6539"), /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.dim }, " - \u9009\u62E9\u8981\u6062\u590D\u7684\u6587\u4EF6")), /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, files.map((file, index) => {
49
+ const isSelected = index === selectedIndex;
50
+ const relativePath = getRelativePath(file.filePath);
51
+ return /* @__PURE__ */ React.createElement(Box, { key: file.filePath, paddingLeft: 1 }, /* @__PURE__ */ React.createElement(Text, { color: isSelected ? SEMANTIC_COLORS.info : void 0 }, isSelected ? "\u25B6 " : " ", /* @__PURE__ */ React.createElement(
52
+ Text,
53
+ {
54
+ color: isSelected ? SEMANTIC_COLORS.primary : SEMANTIC_COLORS.secondary
55
+ },
56
+ relativePath
57
+ ), /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.dim }, " ", "(", file.versionCount, " \u4E2A\u7248\u672C)")));
58
+ })), /* @__PURE__ */ React.createElement(Box, { marginTop: 2 }, /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.muted }, "\u2191/\u2193: \u9009\u62E9 | Enter: \u67E5\u770B\u7248\u672C | q/Esc: \u9000\u51FA")));
59
+ };
60
+ const VersionListView = ({ file, versions, selectedIndex, onSelect, onBack }) => {
61
+ useInput((input, key) => {
62
+ if (key.escape || input === "q") {
63
+ onBack();
64
+ } else if (key.return) {
65
+ if (versions.length > 0 && versions[selectedIndex]) {
66
+ onSelect(versions[selectedIndex]);
67
+ }
68
+ }
69
+ });
70
+ const relativePath = getRelativePath(file.filePath);
71
+ return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React.createElement(Box, { marginBottom: 1 }, /* @__PURE__ */ React.createElement(Text, { bold: true, color: SEMANTIC_COLORS.brand }, "\u9009\u62E9\u8981\u6062\u590D\u7684\u7248\u672C")), /* @__PURE__ */ React.createElement(Box, { marginBottom: 1, paddingLeft: 1 }, /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.dim }, "\u6587\u4EF6: "), /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.secondary }, relativePath)), /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, versions.map((version, index) => {
72
+ const isSelected = index === selectedIndex;
73
+ return /* @__PURE__ */ React.createElement(Box, { key: version.version, paddingLeft: 1 }, /* @__PURE__ */ React.createElement(Text, { color: isSelected ? SEMANTIC_COLORS.info : void 0 }, isSelected ? "\u25B6 " : " ", /* @__PURE__ */ React.createElement(
74
+ Text,
75
+ {
76
+ color: isSelected ? SEMANTIC_COLORS.primary : SEMANTIC_COLORS.secondary
77
+ },
78
+ "v",
79
+ version.version
80
+ ), /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.dim }, ": ", version.operation, " - ", formatTimestamp(version.timestamp))));
81
+ })), /* @__PURE__ */ React.createElement(Box, { marginTop: 2 }, /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.muted }, "\u2191/\u2193: \u9009\u62E9 | Enter: \u6062\u590D\u6B64\u7248\u672C | Esc: \u8FD4\u56DE")));
82
+ };
83
+ const SuccessView = ({ file, version, onClose }) => {
84
+ useInput((input, key) => {
85
+ if (key.escape || input === "q" || key.return) {
86
+ onClose();
87
+ }
88
+ });
89
+ const relativePath = getRelativePath(file.filePath);
90
+ return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React.createElement(Box, { marginBottom: 1 }, /* @__PURE__ */ React.createElement(Text, { bold: true, color: SEMANTIC_COLORS.success }, "\u2713 \u6587\u4EF6\u5DF2\u6062\u590D")), /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", paddingLeft: 1 }, /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.dim }, "\u6587\u4EF6: "), /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.secondary }, relativePath)), /* @__PURE__ */ React.createElement(Box, { paddingLeft: 1, marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.dim }, "\u5DF2\u6062\u590D\u5230: ", version.operation, " (", formatTimestamp(version.timestamp), ")")), /* @__PURE__ */ React.createElement(Box, { marginTop: 2 }, /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.muted }, "\u6309\u4EFB\u610F\u952E\u9000\u51FA")));
91
+ };
92
+ const UndoCommand = ({ onClose }) => {
93
+ const [view, setView] = useState("file-list");
94
+ const [files, setFiles] = useState([]);
95
+ const [selectedFileIndex, setSelectedFileIndex] = useState(0);
96
+ const [selectedFile, setSelectedFile] = useState(
97
+ null
98
+ );
99
+ const [versions, setVersions] = useState([]);
100
+ const [selectedVersionIndex, setSelectedVersionIndex] = useState(0);
101
+ const [restoredVersion, setRestoredVersion] = useState(
102
+ null
103
+ );
104
+ const [error, setError] = useState(null);
105
+ const [isLoading, setIsLoading] = useState(true);
106
+ useEffect(() => {
107
+ const loadFiles = async () => {
108
+ try {
109
+ const backupFiles = await listBackedUpFiles();
110
+ setFiles(backupFiles);
111
+ } catch (err) {
112
+ setError(err instanceof Error ? err.message : String(err));
113
+ } finally {
114
+ setIsLoading(false);
115
+ }
116
+ };
117
+ loadFiles();
118
+ }, []);
119
+ useInput(
120
+ (input, key) => {
121
+ if (view === "file-list" && files.length > 0) {
122
+ if (key.upArrow) {
123
+ setSelectedFileIndex((prev) => Math.max(0, prev - 1));
124
+ } else if (key.downArrow) {
125
+ setSelectedFileIndex((prev) => Math.min(files.length - 1, prev + 1));
126
+ }
127
+ }
128
+ },
129
+ { isActive: view === "file-list" }
130
+ );
131
+ useInput(
132
+ (input, key) => {
133
+ if (view === "version-list" && versions.length > 0) {
134
+ if (key.upArrow) {
135
+ setSelectedVersionIndex((prev) => Math.max(0, prev - 1));
136
+ } else if (key.downArrow) {
137
+ setSelectedVersionIndex(
138
+ (prev) => Math.min(versions.length - 1, prev + 1)
139
+ );
140
+ }
141
+ }
142
+ },
143
+ { isActive: view === "version-list" }
144
+ );
145
+ const handleFileSelect = async (file) => {
146
+ setSelectedFile(file);
147
+ try {
148
+ const fileVersions = await getBackupVersions(file.filePath);
149
+ setVersions(fileVersions);
150
+ setSelectedVersionIndex(0);
151
+ setView("version-list");
152
+ } catch (err) {
153
+ setError(err instanceof Error ? err.message : String(err));
154
+ }
155
+ };
156
+ const handleVersionSelect = async (version) => {
157
+ if (!selectedFile) return;
158
+ try {
159
+ const success = await restoreBackup(
160
+ selectedFile.filePath,
161
+ version.version
162
+ );
163
+ if (success) {
164
+ setRestoredVersion(version);
165
+ setView("success");
166
+ } else {
167
+ setError("\u6062\u590D\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002");
168
+ }
169
+ } catch (err) {
170
+ setError(err instanceof Error ? err.message : String(err));
171
+ }
172
+ };
173
+ const handleBack = () => {
174
+ setView("file-list");
175
+ setSelectedFile(null);
176
+ setVersions([]);
177
+ setSelectedVersionIndex(0);
178
+ };
179
+ if (isLoading) {
180
+ return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.dim }, "\u52A0\u8F7D\u5907\u4EFD\u4FE1\u606F..."));
181
+ }
182
+ if (error) {
183
+ return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React.createElement(Box, { marginBottom: 1 }, /* @__PURE__ */ React.createElement(Text, { bold: true, color: SEMANTIC_COLORS.error }, "\u9519\u8BEF")), /* @__PURE__ */ React.createElement(Box, { paddingLeft: 1 }, /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.dim }, error)), /* @__PURE__ */ React.createElement(Box, { marginTop: 2 }, /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.muted }, "\u6309\u4EFB\u610F\u952E\u9000\u51FA")));
184
+ }
185
+ switch (view) {
186
+ case "file-list":
187
+ return /* @__PURE__ */ React.createElement(
188
+ FileListView,
189
+ {
190
+ files,
191
+ selectedIndex: selectedFileIndex,
192
+ onSelect: handleFileSelect,
193
+ onClose
194
+ }
195
+ );
196
+ case "version-list":
197
+ if (!selectedFile) {
198
+ handleBack();
199
+ return null;
200
+ }
201
+ return /* @__PURE__ */ React.createElement(
202
+ VersionListView,
203
+ {
204
+ file: selectedFile,
205
+ versions,
206
+ selectedIndex: selectedVersionIndex,
207
+ onSelect: handleVersionSelect,
208
+ onBack: handleBack
209
+ }
210
+ );
211
+ case "success":
212
+ if (!selectedFile || !restoredVersion) {
213
+ onClose();
214
+ return null;
215
+ }
216
+ return /* @__PURE__ */ React.createElement(
217
+ SuccessView,
218
+ {
219
+ file: selectedFile,
220
+ version: restoredVersion,
221
+ onClose
222
+ }
223
+ );
224
+ default:
225
+ return null;
226
+ }
227
+ };
228
+ const command = {
229
+ name: "undo",
230
+ description: "\u64A4\u9500\u6587\u4EF6\u4FEE\u6539\uFF08\u9700\u8981 --smart \u6A21\u5F0F\uFF09",
231
+ type: "local-jsx",
232
+ isEnabled: true,
233
+ isHidden: false,
234
+ userFacingName() {
235
+ return "undo";
236
+ },
237
+ async call(onDone) {
238
+ return /* @__PURE__ */ React.createElement(UndoCommand, { onClose: onDone });
239
+ }
240
+ };
241
+ var undo_default = command;
242
+ export {
243
+ undo_default as default
244
+ };
245
+ //# sourceMappingURL=undo.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/commands/undo.tsx"],
4
+ "sourcesContent": ["/**\n * Undo Command\n *\n * Interactive command to restore file versions from backups.\n * Requires --smart mode to have backups available.\n */\n\nimport React, { useState, useEffect } from 'react'\nimport { Box, Text, useInput } from 'ink'\nimport type { Command } from '@commands'\nimport { SEMANTIC_COLORS } from '@constants/colors'\nimport { getCwd } from '@utils/state'\nimport {\n listBackedUpFiles,\n getBackupVersions,\n restoreBackup,\n type BackupFileSummary,\n type BackupMetadata,\n} from '../core/backupManager'\n\ntype ViewState = 'file-list' | 'version-list' | 'success'\n\ninterface UndoCommandProps {\n onClose: () => void\n}\n\n/**\n * Format a timestamp as a human-readable string\n */\nfunction formatTimestamp(timestamp: number): string {\n const date = new Date(timestamp)\n const now = new Date()\n const diff = now.getTime() - timestamp\n\n // Within last hour - show minutes\n if (diff < 60 * 60 * 1000) {\n const minutes = Math.floor(diff / (60 * 1000))\n return minutes <= 1 ? '\u521A\u521A' : `${minutes} \u5206\u949F\u524D`\n }\n\n // Within today - show time\n if (\n date.getDate() === now.getDate() &&\n date.getMonth() === now.getMonth() &&\n date.getFullYear() === now.getFullYear()\n ) {\n return `\u4ECA\u5929 ${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`\n }\n\n // Within this week - show day and time\n if (diff < 7 * 24 * 60 * 60 * 1000) {\n const days = ['\u65E5', '\u4E00', '\u4E8C', '\u4E09', '\u56DB', '\u4E94', '\u516D']\n return `\u5468${days[date.getDay()]} ${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`\n }\n\n // Otherwise - show date\n return `${date.getMonth() + 1}/${date.getDate()} ${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`\n}\n\n/**\n * Get relative path from cwd\n */\nfunction getRelativePath(filePath: string): string {\n const cwd = getCwd()\n if (filePath.startsWith(cwd)) {\n const relative = filePath.slice(cwd.length)\n return relative.startsWith('/') ? relative.slice(1) : relative\n }\n return filePath\n}\n\n/**\n * File List View - shows all files with backups\n */\nconst FileListView: React.FC<{\n files: BackupFileSummary[]\n selectedIndex: number\n onSelect: (file: BackupFileSummary) => void\n onClose: () => void\n}> = ({ files, selectedIndex, onSelect, onClose }) => {\n useInput((input, key) => {\n if (key.escape || input === 'q') {\n onClose()\n } else if (key.return) {\n if (files.length > 0 && files[selectedIndex]) {\n onSelect(files[selectedIndex])\n }\n }\n })\n\n if (files.length === 0) {\n return (\n <Box flexDirection=\"column\" marginY={1}>\n <Box marginBottom={1}>\n <Text bold color={SEMANTIC_COLORS.brand}>\n \u64A4\u9500\u6587\u4EF6\u4FEE\u6539\n </Text>\n </Box>\n\n <Box flexDirection=\"column\" paddingLeft={1}>\n <Text color={SEMANTIC_COLORS.dim}>\u6682\u65E0\u53EF\u64A4\u9500\u7684\u6587\u4EF6\u4FEE\u6539\u3002</Text>\n <Text color={SEMANTIC_COLORS.muted}> </Text>\n <Text color={SEMANTIC_COLORS.dim}>\n \u63D0\u793A\uFF1A\u4F7F\u7528 <Text color={SEMANTIC_COLORS.info}>--smart</Text>{' '}\n \u6A21\u5F0F\u542F\u52A8 Minto \u4EE5\u542F\u7528\u81EA\u52A8\u5907\u4EFD\u529F\u80FD\uFF1A\n </Text>\n <Text color={SEMANTIC_COLORS.muted}> minto --smart</Text>\n </Box>\n\n <Box marginTop={2}>\n <Text color={SEMANTIC_COLORS.muted}>\u6309 q \u6216 Esc \u9000\u51FA</Text>\n </Box>\n </Box>\n )\n }\n\n return (\n <Box flexDirection=\"column\" marginY={1}>\n <Box marginBottom={1}>\n <Text bold color={SEMANTIC_COLORS.brand}>\n \u64A4\u9500\u6587\u4EF6\u4FEE\u6539\n </Text>\n <Text color={SEMANTIC_COLORS.dim}> - \u9009\u62E9\u8981\u6062\u590D\u7684\u6587\u4EF6</Text>\n </Box>\n\n <Box flexDirection=\"column\">\n {files.map((file, index) => {\n const isSelected = index === selectedIndex\n const relativePath = getRelativePath(file.filePath)\n\n return (\n <Box key={file.filePath} paddingLeft={1}>\n <Text color={isSelected ? SEMANTIC_COLORS.info : undefined}>\n {isSelected ? '\u25B6 ' : ' '}\n <Text\n color={\n isSelected\n ? SEMANTIC_COLORS.primary\n : SEMANTIC_COLORS.secondary\n }\n >\n {relativePath}\n </Text>\n <Text color={SEMANTIC_COLORS.dim}>\n {' '}\n ({file.versionCount} \u4E2A\u7248\u672C)\n </Text>\n </Text>\n </Box>\n )\n })}\n </Box>\n\n <Box marginTop={2}>\n <Text color={SEMANTIC_COLORS.muted}>\n \u2191/\u2193: \u9009\u62E9 | Enter: \u67E5\u770B\u7248\u672C | q/Esc: \u9000\u51FA\n </Text>\n </Box>\n </Box>\n )\n}\n\n/**\n * Version List View - shows all versions for a selected file\n */\nconst VersionListView: React.FC<{\n file: BackupFileSummary\n versions: BackupMetadata[]\n selectedIndex: number\n onSelect: (version: BackupMetadata) => void\n onBack: () => void\n}> = ({ file, versions, selectedIndex, onSelect, onBack }) => {\n useInput((input, key) => {\n if (key.escape || input === 'q') {\n onBack()\n } else if (key.return) {\n if (versions.length > 0 && versions[selectedIndex]) {\n onSelect(versions[selectedIndex])\n }\n }\n })\n\n const relativePath = getRelativePath(file.filePath)\n\n return (\n <Box flexDirection=\"column\" marginY={1}>\n <Box marginBottom={1}>\n <Text bold color={SEMANTIC_COLORS.brand}>\n \u9009\u62E9\u8981\u6062\u590D\u7684\u7248\u672C\n </Text>\n </Box>\n\n <Box marginBottom={1} paddingLeft={1}>\n <Text color={SEMANTIC_COLORS.dim}>\u6587\u4EF6: </Text>\n <Text color={SEMANTIC_COLORS.secondary}>{relativePath}</Text>\n </Box>\n\n <Box flexDirection=\"column\">\n {versions.map((version, index) => {\n const isSelected = index === selectedIndex\n\n return (\n <Box key={version.version} paddingLeft={1}>\n <Text color={isSelected ? SEMANTIC_COLORS.info : undefined}>\n {isSelected ? '\u25B6 ' : ' '}\n <Text\n color={\n isSelected\n ? SEMANTIC_COLORS.primary\n : SEMANTIC_COLORS.secondary\n }\n >\n v{version.version}\n </Text>\n <Text color={SEMANTIC_COLORS.dim}>\n : {version.operation} - {formatTimestamp(version.timestamp)}\n </Text>\n </Text>\n </Box>\n )\n })}\n </Box>\n\n <Box marginTop={2}>\n <Text color={SEMANTIC_COLORS.muted}>\n \u2191/\u2193: \u9009\u62E9 | Enter: \u6062\u590D\u6B64\u7248\u672C | Esc: \u8FD4\u56DE\n </Text>\n </Box>\n </Box>\n )\n}\n\n/**\n * Success View - shows restoration confirmation\n */\nconst SuccessView: React.FC<{\n file: BackupFileSummary\n version: BackupMetadata\n onClose: () => void\n}> = ({ file, version, onClose }) => {\n useInput((input, key) => {\n if (key.escape || input === 'q' || key.return) {\n onClose()\n }\n })\n\n const relativePath = getRelativePath(file.filePath)\n\n return (\n <Box flexDirection=\"column\" marginY={1}>\n <Box marginBottom={1}>\n <Text bold color={SEMANTIC_COLORS.success}>\n \u2713 \u6587\u4EF6\u5DF2\u6062\u590D\n </Text>\n </Box>\n\n <Box flexDirection=\"column\" paddingLeft={1}>\n <Text color={SEMANTIC_COLORS.dim}>\u6587\u4EF6: </Text>\n <Text color={SEMANTIC_COLORS.secondary}>{relativePath}</Text>\n </Box>\n\n <Box paddingLeft={1} marginTop={1}>\n <Text color={SEMANTIC_COLORS.dim}>\n \u5DF2\u6062\u590D\u5230: {version.operation} ({formatTimestamp(version.timestamp)})\n </Text>\n </Box>\n\n <Box marginTop={2}>\n <Text color={SEMANTIC_COLORS.muted}>\u6309\u4EFB\u610F\u952E\u9000\u51FA</Text>\n </Box>\n </Box>\n )\n}\n\n/**\n * Main Undo Command Component\n */\nconst UndoCommand: React.FC<UndoCommandProps> = ({ onClose }) => {\n const [view, setView] = useState<ViewState>('file-list')\n const [files, setFiles] = useState<BackupFileSummary[]>([])\n const [selectedFileIndex, setSelectedFileIndex] = useState(0)\n const [selectedFile, setSelectedFile] = useState<BackupFileSummary | null>(\n null,\n )\n const [versions, setVersions] = useState<BackupMetadata[]>([])\n const [selectedVersionIndex, setSelectedVersionIndex] = useState(0)\n const [restoredVersion, setRestoredVersion] = useState<BackupMetadata | null>(\n null,\n )\n const [error, setError] = useState<string | null>(null)\n const [isLoading, setIsLoading] = useState(true)\n\n // Load files with backups on mount\n useEffect(() => {\n const loadFiles = async () => {\n try {\n const backupFiles = await listBackedUpFiles()\n // Already sorted by most recent in listBackedUpFiles\n setFiles(backupFiles)\n } catch (err) {\n setError(err instanceof Error ? err.message : String(err))\n } finally {\n setIsLoading(false)\n }\n }\n loadFiles()\n }, [])\n\n // Handle keyboard navigation for file list\n useInput(\n (input, key) => {\n if (view === 'file-list' && files.length > 0) {\n if (key.upArrow) {\n setSelectedFileIndex(prev => Math.max(0, prev - 1))\n } else if (key.downArrow) {\n setSelectedFileIndex(prev => Math.min(files.length - 1, prev + 1))\n }\n }\n },\n { isActive: view === 'file-list' },\n )\n\n // Handle keyboard navigation for version list\n useInput(\n (input, key) => {\n if (view === 'version-list' && versions.length > 0) {\n if (key.upArrow) {\n setSelectedVersionIndex(prev => Math.max(0, prev - 1))\n } else if (key.downArrow) {\n setSelectedVersionIndex(prev =>\n Math.min(versions.length - 1, prev + 1),\n )\n }\n }\n },\n { isActive: view === 'version-list' },\n )\n\n // Handle file selection\n const handleFileSelect = async (file: BackupFileSummary) => {\n setSelectedFile(file)\n try {\n const fileVersions = await getBackupVersions(file.filePath)\n // Already sorted by newest first in getBackupVersions\n setVersions(fileVersions)\n setSelectedVersionIndex(0)\n setView('version-list')\n } catch (err) {\n setError(err instanceof Error ? err.message : String(err))\n }\n }\n\n // Handle version selection and restore\n const handleVersionSelect = async (version: BackupMetadata) => {\n if (!selectedFile) return\n\n try {\n const success = await restoreBackup(\n selectedFile.filePath,\n version.version,\n )\n if (success) {\n setRestoredVersion(version)\n setView('success')\n } else {\n setError('\u6062\u590D\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002')\n }\n } catch (err) {\n setError(err instanceof Error ? err.message : String(err))\n }\n }\n\n // Handle back navigation\n const handleBack = () => {\n setView('file-list')\n setSelectedFile(null)\n setVersions([])\n setSelectedVersionIndex(0)\n }\n\n // Loading state\n if (isLoading) {\n return (\n <Box flexDirection=\"column\" marginY={1}>\n <Text color={SEMANTIC_COLORS.dim}>\u52A0\u8F7D\u5907\u4EFD\u4FE1\u606F...</Text>\n </Box>\n )\n }\n\n // Error display\n if (error) {\n return (\n <Box flexDirection=\"column\" marginY={1}>\n <Box marginBottom={1}>\n <Text bold color={SEMANTIC_COLORS.error}>\n \u9519\u8BEF\n </Text>\n </Box>\n <Box paddingLeft={1}>\n <Text color={SEMANTIC_COLORS.dim}>{error}</Text>\n </Box>\n <Box marginTop={2}>\n <Text color={SEMANTIC_COLORS.muted}>\u6309\u4EFB\u610F\u952E\u9000\u51FA</Text>\n </Box>\n </Box>\n )\n }\n\n // Render current view\n switch (view) {\n case 'file-list':\n return (\n <FileListView\n files={files}\n selectedIndex={selectedFileIndex}\n onSelect={handleFileSelect}\n onClose={onClose}\n />\n )\n\n case 'version-list':\n if (!selectedFile) {\n handleBack()\n return null\n }\n return (\n <VersionListView\n file={selectedFile}\n versions={versions}\n selectedIndex={selectedVersionIndex}\n onSelect={handleVersionSelect}\n onBack={handleBack}\n />\n )\n\n case 'success':\n if (!selectedFile || !restoredVersion) {\n onClose()\n return null\n }\n return (\n <SuccessView\n file={selectedFile}\n version={restoredVersion}\n onClose={onClose}\n />\n )\n\n default:\n return null\n }\n}\n\n/**\n * Undo Command Export\n */\nconst command: Command = {\n name: 'undo',\n description: '\u64A4\u9500\u6587\u4EF6\u4FEE\u6539\uFF08\u9700\u8981 --smart \u6A21\u5F0F\uFF09',\n type: 'local-jsx' as const,\n isEnabled: true,\n isHidden: false,\n\n userFacingName() {\n return 'undo'\n },\n\n async call(onDone: (result?: string) => void) {\n return <UndoCommand onClose={onDone} />\n },\n}\n\nexport default command\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
package/dist/commands.js CHANGED
@@ -18,6 +18,7 @@ import terminalSetup from "./commands/terminalSetup.js";
18
18
  import resume from "./commands/resume.js";
19
19
  import agents from "./commands/agents/index.js";
20
20
  import plugin from "./commands/plugin.js";
21
+ import undo from "./commands/undo.js";
21
22
  import { quit } from "./commands/quit.js";
22
23
  import doctor from "./commands/doctor.js";
23
24
  import bug from "./commands/bug.js";
@@ -53,6 +54,7 @@ const COMMANDS = memoize(() => [
53
54
  status,
54
55
  tasks,
55
56
  todos,
57
+ undo,
56
58
  ...HIDDEN_COMMANDS
57
59
  ]);
58
60
  const getCommands = memoize(async () => {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/commands.ts"],
4
- "sourcesContent": ["import React from 'react'\nimport clear from './commands/clear'\nimport compact from './commands/compact'\nimport config from './commands/config'\nimport context from './commands/context'\nimport cost from './commands/cost'\nimport ctx_viz from './commands/ctx_viz'\nimport exportCmd from './commands/export'\nimport help from './commands/help'\nimport init from './commands/init'\nimport mcp from './commands/mcp-interactive'\nimport model from './commands/model'\nimport permissions from './commands/permissions'\nimport refreshCommands from './commands/refreshCommands'\nimport sandbox from './commands/sandbox'\nimport setup from './commands/setup'\nimport status from './commands/status'\nimport terminalSetup from './commands/terminalSetup'\nimport { Tool, ToolUseContext } from './Tool'\nimport resume from './commands/resume'\nimport agents from './commands/agents'\nimport plugin from './commands/plugin'\nimport { quit } from './commands/quit'\n// Phase 4: Diagnostic and task management commands\nimport doctor from './commands/doctor'\nimport bug from './commands/bug'\nimport tasks from './commands/tasks'\nimport todos from './commands/todos'\nimport { getMCPCommands } from './services/mcpClient'\nimport {\n loadCustomCommands,\n loadPluginCommands,\n} from './services/customCommands'\nimport type { MessageParam } from '@anthropic-ai/sdk/resources/index.mjs'\nimport { memoize } from 'lodash-es'\nimport type { Message } from './query'\n\ntype PromptCommand = {\n type: 'prompt'\n progressMessage: string\n argNames?: string[]\n getPromptForCommand(args: string): Promise<MessageParam[]>\n}\n\ntype LocalCommand = {\n type: 'local'\n call(\n args: string,\n context: {\n options: {\n commands: Command[]\n tools: Tool[]\n slowAndCapableModel: string\n }\n abortController: AbortController\n setForkConvoWithMessagesOnTheNextRender: (\n forkConvoWithMessages: Message[],\n ) => void\n },\n ): Promise<string>\n}\n\ntype LocalJSXCommand = {\n type: 'local-jsx'\n call(\n onDone: (result?: string) => void,\n context: ToolUseContext & {\n setForkConvoWithMessagesOnTheNextRender: (\n forkConvoWithMessages: Message[],\n ) => void\n },\n ): Promise<React.ReactNode>\n}\n\nexport type Command = {\n description: string\n isEnabled: boolean\n isHidden: boolean\n name: string\n aliases?: string[]\n userFacingName(): string\n} & (PromptCommand | LocalCommand | LocalJSXCommand)\n\n// Hidden developer commands (not shown in /help but still accessible)\nconst HIDDEN_COMMANDS = [ctx_viz, refreshCommands, terminalSetup]\n\n// Declared as a function so that we don't run this until getCommands is called,\n// since underlying functions read from config, which can't be read at module initialization time\nconst COMMANDS = memoize((): Command[] => [\n agents,\n bug,\n clear,\n compact,\n config,\n context,\n cost,\n doctor,\n exportCmd,\n help,\n init,\n mcp,\n model,\n permissions,\n plugin,\n quit,\n resume,\n sandbox,\n setup,\n status,\n tasks,\n todos,\n ...HIDDEN_COMMANDS,\n])\n\nexport const getCommands = memoize(async (): Promise<Command[]> => {\n const [mcpCommands, customCommands, pluginCommands] = await Promise.all([\n getMCPCommands(),\n loadCustomCommands(),\n loadPluginCommands(),\n ])\n\n // Get built-in commands\n const builtInCommands = COMMANDS()\n\n // Sort built-in commands alphabetically by name\n const sortedBuiltIn = [...builtInCommands].sort((a, b) =>\n a.userFacingName().localeCompare(b.userFacingName()),\n )\n\n // Sort MCP commands alphabetically by name\n const sortedMCP = [...mcpCommands].sort((a, b) =>\n a.userFacingName().localeCompare(b.userFacingName()),\n )\n\n // Sort plugin commands alphabetically by name\n const sortedPlugin = [...pluginCommands].sort((a, b) =>\n a.userFacingName().localeCompare(b.userFacingName()),\n )\n\n // Sort custom commands alphabetically by name\n const sortedCustom = [...customCommands].sort((a, b) =>\n a.userFacingName().localeCompare(b.userFacingName()),\n )\n\n // Command priority (later overrides earlier):\n // 1. MCP commands (lowest priority) - sorted alphabetically\n // 2. Plugin commands - sorted alphabetically\n // 3. Custom commands (user/project) - sorted alphabetically\n // 4. Built-in commands (highest priority) - sorted alphabetically\n // Display order: Built-in first, then custom/plugin/MCP\n return [\n ...sortedBuiltIn,\n ...sortedCustom,\n ...sortedPlugin,\n ...sortedMCP,\n ].filter(_ => _.isEnabled)\n})\n\nexport function hasCommand(commandName: string, commands: Command[]): boolean {\n return commands.some(\n _ => _.userFacingName() === commandName || _.aliases?.includes(commandName),\n )\n}\n\nexport function getCommand(commandName: string, commands: Command[]): Command {\n const command = commands.find(\n _ => _.userFacingName() === commandName || _.aliases?.includes(commandName),\n ) as Command | undefined\n if (!command) {\n throw ReferenceError(\n `Command ${commandName} not found. Available commands: ${commands\n .map(_ => {\n const name = _.userFacingName()\n return _.aliases ? `${name} (aliases: ${_.aliases.join(', ')})` : name\n })\n .join(', ')}`,\n )\n }\n\n return command\n}\n"],
5
- "mappings": "AACA,OAAO,WAAW;AAClB,OAAO,aAAa;AACpB,OAAO,YAAY;AACnB,OAAO,aAAa;AACpB,OAAO,UAAU;AACjB,OAAO,aAAa;AACpB,OAAO,eAAe;AACtB,OAAO,UAAU;AACjB,OAAO,UAAU;AACjB,OAAO,SAAS;AAChB,OAAO,WAAW;AAClB,OAAO,iBAAiB;AACxB,OAAO,qBAAqB;AAC5B,OAAO,aAAa;AACpB,OAAO,WAAW;AAClB,OAAO,YAAY;AACnB,OAAO,mBAAmB;AAE1B,OAAO,YAAY;AACnB,OAAO,YAAY;AACnB,OAAO,YAAY;AACnB,SAAS,YAAY;AAErB,OAAO,YAAY;AACnB,OAAO,SAAS;AAChB,OAAO,WAAW;AAClB,OAAO,WAAW;AAClB,SAAS,sBAAsB;AAC/B;AAAA,EACE;AAAA,EACA;AAAA,OACK;AAEP,SAAS,eAAe;AAkDxB,MAAM,kBAAkB,CAAC,SAAS,iBAAiB,aAAa;AAIhE,MAAM,WAAW,QAAQ,MAAiB;AAAA,EACxC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,CAAC;AAEM,MAAM,cAAc,QAAQ,YAAgC;AACjE,QAAM,CAAC,aAAa,gBAAgB,cAAc,IAAI,MAAM,QAAQ,IAAI;AAAA,IACtE,eAAe;AAAA,IACf,mBAAmB;AAAA,IACnB,mBAAmB;AAAA,EACrB,CAAC;AAGD,QAAM,kBAAkB,SAAS;AAGjC,QAAM,gBAAgB,CAAC,GAAG,eAAe,EAAE;AAAA,IAAK,CAAC,GAAG,MAClD,EAAE,eAAe,EAAE,cAAc,EAAE,eAAe,CAAC;AAAA,EACrD;AAGA,QAAM,YAAY,CAAC,GAAG,WAAW,EAAE;AAAA,IAAK,CAAC,GAAG,MAC1C,EAAE,eAAe,EAAE,cAAc,EAAE,eAAe,CAAC;AAAA,EACrD;AAGA,QAAM,eAAe,CAAC,GAAG,cAAc,EAAE;AAAA,IAAK,CAAC,GAAG,MAChD,EAAE,eAAe,EAAE,cAAc,EAAE,eAAe,CAAC;AAAA,EACrD;AAGA,QAAM,eAAe,CAAC,GAAG,cAAc,EAAE;AAAA,IAAK,CAAC,GAAG,MAChD,EAAE,eAAe,EAAE,cAAc,EAAE,eAAe,CAAC;AAAA,EACrD;AAQA,SAAO;AAAA,IACL,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,EACL,EAAE,OAAO,OAAK,EAAE,SAAS;AAC3B,CAAC;AAEM,SAAS,WAAW,aAAqB,UAA8B;AAC5E,SAAO,SAAS;AAAA,IACd,OAAK,EAAE,eAAe,MAAM,eAAe,EAAE,SAAS,SAAS,WAAW;AAAA,EAC5E;AACF;AAEO,SAAS,WAAW,aAAqB,UAA8B;AAC5E,QAAM,UAAU,SAAS;AAAA,IACvB,OAAK,EAAE,eAAe,MAAM,eAAe,EAAE,SAAS,SAAS,WAAW;AAAA,EAC5E;AACA,MAAI,CAAC,SAAS;AACZ,UAAM;AAAA,MACJ,WAAW,WAAW,mCAAmC,SACtD,IAAI,OAAK;AACR,cAAM,OAAO,EAAE,eAAe;AAC9B,eAAO,EAAE,UAAU,GAAG,IAAI,cAAc,EAAE,QAAQ,KAAK,IAAI,CAAC,MAAM;AAAA,MACpE,CAAC,EACA,KAAK,IAAI,CAAC;AAAA,IACf;AAAA,EACF;AAEA,SAAO;AACT;",
4
+ "sourcesContent": ["import React from 'react'\nimport clear from './commands/clear'\nimport compact from './commands/compact'\nimport config from './commands/config'\nimport context from './commands/context'\nimport cost from './commands/cost'\nimport ctx_viz from './commands/ctx_viz'\nimport exportCmd from './commands/export'\nimport help from './commands/help'\nimport init from './commands/init'\nimport mcp from './commands/mcp-interactive'\nimport model from './commands/model'\nimport permissions from './commands/permissions'\nimport refreshCommands from './commands/refreshCommands'\nimport sandbox from './commands/sandbox'\nimport setup from './commands/setup'\nimport status from './commands/status'\nimport terminalSetup from './commands/terminalSetup'\nimport { Tool, ToolUseContext } from './Tool'\nimport resume from './commands/resume'\nimport agents from './commands/agents'\nimport plugin from './commands/plugin'\nimport undo from './commands/undo'\nimport { quit } from './commands/quit'\n// Phase 4: Diagnostic and task management commands\nimport doctor from './commands/doctor'\nimport bug from './commands/bug'\nimport tasks from './commands/tasks'\nimport todos from './commands/todos'\nimport { getMCPCommands } from './services/mcpClient'\nimport {\n loadCustomCommands,\n loadPluginCommands,\n} from './services/customCommands'\nimport type { MessageParam } from '@anthropic-ai/sdk/resources/index.mjs'\nimport { memoize } from 'lodash-es'\nimport type { Message } from './query'\n\ntype PromptCommand = {\n type: 'prompt'\n progressMessage: string\n argNames?: string[]\n getPromptForCommand(args: string): Promise<MessageParam[]>\n}\n\ntype LocalCommand = {\n type: 'local'\n call(\n args: string,\n context: {\n options: {\n commands: Command[]\n tools: Tool[]\n slowAndCapableModel: string\n }\n abortController: AbortController\n setForkConvoWithMessagesOnTheNextRender: (\n forkConvoWithMessages: Message[],\n ) => void\n },\n ): Promise<string>\n}\n\ntype LocalJSXCommand = {\n type: 'local-jsx'\n call(\n onDone: (result?: string) => void,\n context: ToolUseContext & {\n setForkConvoWithMessagesOnTheNextRender: (\n forkConvoWithMessages: Message[],\n ) => void\n },\n ): Promise<React.ReactNode>\n}\n\nexport type Command = {\n description: string\n isEnabled: boolean\n isHidden: boolean\n name: string\n aliases?: string[]\n userFacingName(): string\n} & (PromptCommand | LocalCommand | LocalJSXCommand)\n\n// Hidden developer commands (not shown in /help but still accessible)\nconst HIDDEN_COMMANDS = [ctx_viz, refreshCommands, terminalSetup]\n\n// Declared as a function so that we don't run this until getCommands is called,\n// since underlying functions read from config, which can't be read at module initialization time\nconst COMMANDS = memoize((): Command[] => [\n agents,\n bug,\n clear,\n compact,\n config,\n context,\n cost,\n doctor,\n exportCmd,\n help,\n init,\n mcp,\n model,\n permissions,\n plugin,\n quit,\n resume,\n sandbox,\n setup,\n status,\n tasks,\n todos,\n undo,\n ...HIDDEN_COMMANDS,\n])\n\nexport const getCommands = memoize(async (): Promise<Command[]> => {\n const [mcpCommands, customCommands, pluginCommands] = await Promise.all([\n getMCPCommands(),\n loadCustomCommands(),\n loadPluginCommands(),\n ])\n\n // Get built-in commands\n const builtInCommands = COMMANDS()\n\n // Sort built-in commands alphabetically by name\n const sortedBuiltIn = [...builtInCommands].sort((a, b) =>\n a.userFacingName().localeCompare(b.userFacingName()),\n )\n\n // Sort MCP commands alphabetically by name\n const sortedMCP = [...mcpCommands].sort((a, b) =>\n a.userFacingName().localeCompare(b.userFacingName()),\n )\n\n // Sort plugin commands alphabetically by name\n const sortedPlugin = [...pluginCommands].sort((a, b) =>\n a.userFacingName().localeCompare(b.userFacingName()),\n )\n\n // Sort custom commands alphabetically by name\n const sortedCustom = [...customCommands].sort((a, b) =>\n a.userFacingName().localeCompare(b.userFacingName()),\n )\n\n // Command priority (later overrides earlier):\n // 1. MCP commands (lowest priority) - sorted alphabetically\n // 2. Plugin commands - sorted alphabetically\n // 3. Custom commands (user/project) - sorted alphabetically\n // 4. Built-in commands (highest priority) - sorted alphabetically\n // Display order: Built-in first, then custom/plugin/MCP\n return [\n ...sortedBuiltIn,\n ...sortedCustom,\n ...sortedPlugin,\n ...sortedMCP,\n ].filter(_ => _.isEnabled)\n})\n\nexport function hasCommand(commandName: string, commands: Command[]): boolean {\n return commands.some(\n _ => _.userFacingName() === commandName || _.aliases?.includes(commandName),\n )\n}\n\nexport function getCommand(commandName: string, commands: Command[]): Command {\n const command = commands.find(\n _ => _.userFacingName() === commandName || _.aliases?.includes(commandName),\n ) as Command | undefined\n if (!command) {\n throw ReferenceError(\n `Command ${commandName} not found. Available commands: ${commands\n .map(_ => {\n const name = _.userFacingName()\n return _.aliases ? `${name} (aliases: ${_.aliases.join(', ')})` : name\n })\n .join(', ')}`,\n )\n }\n\n return command\n}\n"],
5
+ "mappings": "AACA,OAAO,WAAW;AAClB,OAAO,aAAa;AACpB,OAAO,YAAY;AACnB,OAAO,aAAa;AACpB,OAAO,UAAU;AACjB,OAAO,aAAa;AACpB,OAAO,eAAe;AACtB,OAAO,UAAU;AACjB,OAAO,UAAU;AACjB,OAAO,SAAS;AAChB,OAAO,WAAW;AAClB,OAAO,iBAAiB;AACxB,OAAO,qBAAqB;AAC5B,OAAO,aAAa;AACpB,OAAO,WAAW;AAClB,OAAO,YAAY;AACnB,OAAO,mBAAmB;AAE1B,OAAO,YAAY;AACnB,OAAO,YAAY;AACnB,OAAO,YAAY;AACnB,OAAO,UAAU;AACjB,SAAS,YAAY;AAErB,OAAO,YAAY;AACnB,OAAO,SAAS;AAChB,OAAO,WAAW;AAClB,OAAO,WAAW;AAClB,SAAS,sBAAsB;AAC/B;AAAA,EACE;AAAA,EACA;AAAA,OACK;AAEP,SAAS,eAAe;AAkDxB,MAAM,kBAAkB,CAAC,SAAS,iBAAiB,aAAa;AAIhE,MAAM,WAAW,QAAQ,MAAiB;AAAA,EACxC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,CAAC;AAEM,MAAM,cAAc,QAAQ,YAAgC;AACjE,QAAM,CAAC,aAAa,gBAAgB,cAAc,IAAI,MAAM,QAAQ,IAAI;AAAA,IACtE,eAAe;AAAA,IACf,mBAAmB;AAAA,IACnB,mBAAmB;AAAA,EACrB,CAAC;AAGD,QAAM,kBAAkB,SAAS;AAGjC,QAAM,gBAAgB,CAAC,GAAG,eAAe,EAAE;AAAA,IAAK,CAAC,GAAG,MAClD,EAAE,eAAe,EAAE,cAAc,EAAE,eAAe,CAAC;AAAA,EACrD;AAGA,QAAM,YAAY,CAAC,GAAG,WAAW,EAAE;AAAA,IAAK,CAAC,GAAG,MAC1C,EAAE,eAAe,EAAE,cAAc,EAAE,eAAe,CAAC;AAAA,EACrD;AAGA,QAAM,eAAe,CAAC,GAAG,cAAc,EAAE;AAAA,IAAK,CAAC,GAAG,MAChD,EAAE,eAAe,EAAE,cAAc,EAAE,eAAe,CAAC;AAAA,EACrD;AAGA,QAAM,eAAe,CAAC,GAAG,cAAc,EAAE;AAAA,IAAK,CAAC,GAAG,MAChD,EAAE,eAAe,EAAE,cAAc,EAAE,eAAe,CAAC;AAAA,EACrD;AAQA,SAAO;AAAA,IACL,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,EACL,EAAE,OAAO,OAAK,EAAE,SAAS;AAC3B,CAAC;AAEM,SAAS,WAAW,aAAqB,UAA8B;AAC5E,SAAO,SAAS;AAAA,IACd,OAAK,EAAE,eAAe,MAAM,eAAe,EAAE,SAAS,SAAS,WAAW;AAAA,EAC5E;AACF;AAEO,SAAS,WAAW,aAAqB,UAA8B;AAC5E,QAAM,UAAU,SAAS;AAAA,IACvB,OAAK,EAAE,eAAe,MAAM,eAAe,EAAE,SAAS,SAAS,WAAW;AAAA,EAC5E;AACA,MAAI,CAAC,SAAS;AACZ,UAAM;AAAA,MACJ,WAAW,WAAW,mCAAmC,SACtD,IAAI,OAAK;AACR,cAAM,OAAO,EAAE,eAAe;AAC9B,eAAO,EAAE,UAAU,GAAG,IAAI,cAAc,EAAE,QAAQ,KAAK,IAAI,CAAC,MAAM;AAAA,MACpE,CAAC,EACA,KAAK,IAAI,CAAC;AAAA,IACf;AAAA,EACF;AAEA,SAAO;AACT;",
6
6
  "names": []
7
7
  }
@@ -18,7 +18,7 @@ function AgentThinkingBlock({
18
18
  spinnerFrameCount: frames.length,
19
19
  componentId: "agent-thinking-block"
20
20
  });
21
- return /* @__PURE__ */ React.createElement(Box, { flexDirection: "row", marginTop: 1 }, showSpinner && /* @__PURE__ */ React.createElement(Box, { flexWrap: "nowrap", height: 1, width: 2 }, /* @__PURE__ */ React.createElement(Text, { color: theme.dimmedText }, frames[spinnerFrame])), /* @__PURE__ */ React.createElement(Text, { color: theme.dimmedText }, message, showSpinner && "\u2026"), showElapsedTime && /* @__PURE__ */ React.createElement(Text, { color: theme.mutedText }, " ", "(", elapsedTime, "s \xB7 ", /* @__PURE__ */ React.createElement(Text, { bold: true }, "esc"), " to interrupt)"));
21
+ return /* @__PURE__ */ React.createElement(Box, { flexDirection: "row", marginTop: 1 }, showSpinner && /* @__PURE__ */ React.createElement(Box, { flexWrap: "nowrap", height: 1, width: 2 }, /* @__PURE__ */ React.createElement(Text, { color: theme.dimmedText }, frames[spinnerFrame])), /* @__PURE__ */ React.createElement(Text, { color: theme.dimmedText }, message, showSpinner && "\u2026"), showElapsedTime && /* @__PURE__ */ React.createElement(Text, { color: theme.mutedText }, " ", "(", elapsedTime, "s \xB7 ", /* @__PURE__ */ React.createElement(Text, { bold: true }, "esc esc"), " to interrupt)"));
22
22
  }
23
23
  function ThinkingIndicator({
24
24
  message
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/components/AgentThinkingBlock.tsx"],
4
- "sourcesContent": ["/**\n * AgentThinkingBlock - Claude Code CLI \u98CE\u683C\u7684\u601D\u8003\u8FC7\u7A0B\u7EC4\u4EF6\n *\n * \u6838\u5FC3\u7279\u6027\uFF1A\n * 1. **\u539F\u5730\u66F4\u65B0** - \u540C\u4E00\u4E2A\u7EC4\u4EF6\u5B9E\u4F8B\uFF0C\u901A\u8FC7 props \u66F4\u65B0\u5185\u5BB9\n * 2. **\u6697\u6DE1\u914D\u8272** - \u4F7F\u7528 dimmedText \u8868\u793A\u8FC7\u6E21\u72B6\u6001\n * 3. **\u52A8\u753B Spinner** - \u6301\u7EED\u65CB\u8F6C\uFF0C\u8868\u793A\u6D3B\u8DC3\u72B6\u6001\n * 4. **\u6D41\u7545\u8FC7\u6E21** - \u6D88\u606F\u53D8\u5316\u65F6\u5E73\u6ED1\u66FF\u6362\uFF0C\u4E0D\u4EA7\u751F\u6EDA\u52A8\n *\n * \u8FD9\u662F\u5B9E\u73B0\"\u6D41\u52A8\u6027\"\u7684\u5173\u952E\u7EC4\u4EF6\n * \u4F7F\u7528\u7EDF\u4E00\u52A8\u753B\u7BA1\u7406\u5668\u4EE3\u66FF\u591A\u4E2A setInterval\uFF0C\u51CF\u5C11\u5C4F\u5E55\u95EA\u70C1\n */\n\nimport React, { useRef } from 'react'\nimport { Box, Text } from 'ink'\nimport { getTheme } from '@utils/theme'\nimport { SYMBOLS } from '@constants/symbols'\nimport { useUnifiedAnimation } from '@utils/animationManager'\n\ninterface Props {\n /** \u5F53\u524D\u601D\u8003\u9636\u6BB5\u7684\u6D88\u606F */\n message: string\n\n /** \u662F\u5426\u663E\u793A Spinner \u52A8\u753B */\n showSpinner?: boolean\n\n /** \u662F\u5426\u663E\u793A\u7ECF\u8FC7\u65F6\u95F4 */\n showElapsedTime?: boolean\n\n /** \u8D77\u59CB\u65F6\u95F4 (\u7528\u4E8E\u8BA1\u7B97\u7ECF\u8FC7\u65F6\u95F4) */\n startTime?: number\n}\n\n/**\n * AgentThinkingBlock - \u539F\u5730\u66F4\u65B0\u7684\u601D\u8003\u8FC7\u7A0B\u7EC4\u4EF6\n *\n * \u7528\u6CD5\u793A\u4F8B\uFF1A\n * ```tsx\n * // \u521D\u59CB\u6E32\u67D3\n * <AgentThinkingBlock message=\"Reading file...\" />\n *\n * // \u66F4\u65B0\u6D88\u606F (\u540C\u4E00\u4E2A\u7EC4\u4EF6\u5B9E\u4F8B\uFF0Cprops \u53D8\u5316)\n * <AgentThinkingBlock message=\"Analyzing code...\" />\n *\n * // \u518D\u6B21\u66F4\u65B0\n * <AgentThinkingBlock message=\"Generating response...\" />\n * ```\n *\n * \u7528\u6237\u770B\u5230\u7684\u6548\u679C\uFF1A\n * ```\n * \u00B7 Reading file... \u2190 \u663E\u793A\n * \u2722 Analyzing code... \u2190 \u66FF\u6362 (\u4E0D\u662F\u65B0\u884C)\n * \u2733 Generating response... \u2190 \u518D\u6B21\u66FF\u6362\n * ```\n */\nexport function AgentThinkingBlock({\n message,\n showSpinner = true,\n showElapsedTime = true,\n startTime = Date.now(),\n}: Props): React.ReactNode {\n const theme = getTheme()\n const startTimeRef = useRef(startTime)\n\n // Claude Code \u98CE\u683C\u7684\u601D\u8003\u52A8\u753B - 6\u5E27\u5FAA\u73AF\n const frames = SYMBOLS.THINKING_FRAMES\n\n // Use unified animation manager instead of separate setInterval timers\n const { spinnerFrame, elapsedTime } = useUnifiedAnimation({\n enabled: showSpinner || showElapsedTime,\n startTime: startTimeRef.current,\n spinnerFrameCount: frames.length,\n componentId: 'agent-thinking-block',\n })\n\n return (\n <Box flexDirection=\"row\" marginTop={1}>\n {/* Spinner \u52A8\u753B */}\n {showSpinner && (\n <Box flexWrap=\"nowrap\" height={1} width={2}>\n {/* \u4F7F\u7528\u6697\u6DE1\u8272 - \u5173\u952E\uFF1A\u8FC7\u6E21\u72B6\u6001\u5E94\u8BE5\u4E0D\u663E\u773C */}\n <Text color={theme.dimmedText}>{frames[spinnerFrame]}</Text>\n </Box>\n )}\n\n {/* \u601D\u8003\u6D88\u606F - \u4F7F\u7528\u6697\u6DE1\u8272\uFF0C\u7B26\u5408 Claude Code CLI \u89C4\u8303 */}\n <Text color={theme.dimmedText}>\n {message}\n {showSpinner && '\u2026'}\n </Text>\n\n {/* \u7ECF\u8FC7\u65F6\u95F4\u548C\u63D0\u793A */}\n {showElapsedTime && (\n <Text color={theme.mutedText}>\n {' '}\n ({elapsedTime}s \u00B7 <Text bold>esc</Text> to interrupt)\n </Text>\n )}\n </Box>\n )\n}\n\n/**\n * \u8F7B\u91CF\u7EA7\u7684 Thinking Indicator (\u7528\u4E8E\u7D27\u51D1\u5E03\u5C40)\n */\nexport function ThinkingIndicator({\n message,\n}: {\n message: string\n}): React.ReactNode {\n return <AgentThinkingBlock message={message} showElapsedTime={false} />\n}\n"],
5
- "mappings": "AAaA,OAAO,SAAS,cAAc;AAC9B,SAAS,KAAK,YAAY;AAC1B,SAAS,gBAAgB;AACzB,SAAS,eAAe;AACxB,SAAS,2BAA2B;AAsC7B,SAAS,mBAAmB;AAAA,EACjC;AAAA,EACA,cAAc;AAAA,EACd,kBAAkB;AAAA,EAClB,YAAY,KAAK,IAAI;AACvB,GAA2B;AACzB,QAAM,QAAQ,SAAS;AACvB,QAAM,eAAe,OAAO,SAAS;AAGrC,QAAM,SAAS,QAAQ;AAGvB,QAAM,EAAE,cAAc,YAAY,IAAI,oBAAoB;AAAA,IACxD,SAAS,eAAe;AAAA,IACxB,WAAW,aAAa;AAAA,IACxB,mBAAmB,OAAO;AAAA,IAC1B,aAAa;AAAA,EACf,CAAC;AAED,SACE,oCAAC,OAAI,eAAc,OAAM,WAAW,KAEjC,eACC,oCAAC,OAAI,UAAS,UAAS,QAAQ,GAAG,OAAO,KAEvC,oCAAC,QAAK,OAAO,MAAM,cAAa,OAAO,YAAY,CAAE,CACvD,GAIF,oCAAC,QAAK,OAAO,MAAM,cAChB,SACA,eAAe,QAClB,GAGC,mBACC,oCAAC,QAAK,OAAO,MAAM,aAChB,KAAI,KACH,aAAY,WAAI,oCAAC,QAAK,MAAI,QAAC,KAAG,GAAO,gBACzC,CAEJ;AAEJ;AAKO,SAAS,kBAAkB;AAAA,EAChC;AACF,GAEoB;AAClB,SAAO,oCAAC,sBAAmB,SAAkB,iBAAiB,OAAO;AACvE;",
4
+ "sourcesContent": ["/**\n * AgentThinkingBlock - Claude Code CLI \u98CE\u683C\u7684\u601D\u8003\u8FC7\u7A0B\u7EC4\u4EF6\n *\n * \u6838\u5FC3\u7279\u6027\uFF1A\n * 1. **\u539F\u5730\u66F4\u65B0** - \u540C\u4E00\u4E2A\u7EC4\u4EF6\u5B9E\u4F8B\uFF0C\u901A\u8FC7 props \u66F4\u65B0\u5185\u5BB9\n * 2. **\u6697\u6DE1\u914D\u8272** - \u4F7F\u7528 dimmedText \u8868\u793A\u8FC7\u6E21\u72B6\u6001\n * 3. **\u52A8\u753B Spinner** - \u6301\u7EED\u65CB\u8F6C\uFF0C\u8868\u793A\u6D3B\u8DC3\u72B6\u6001\n * 4. **\u6D41\u7545\u8FC7\u6E21** - \u6D88\u606F\u53D8\u5316\u65F6\u5E73\u6ED1\u66FF\u6362\uFF0C\u4E0D\u4EA7\u751F\u6EDA\u52A8\n *\n * \u8FD9\u662F\u5B9E\u73B0\"\u6D41\u52A8\u6027\"\u7684\u5173\u952E\u7EC4\u4EF6\n * \u4F7F\u7528\u7EDF\u4E00\u52A8\u753B\u7BA1\u7406\u5668\u4EE3\u66FF\u591A\u4E2A setInterval\uFF0C\u51CF\u5C11\u5C4F\u5E55\u95EA\u70C1\n */\n\nimport React, { useRef } from 'react'\nimport { Box, Text } from 'ink'\nimport { getTheme } from '@utils/theme'\nimport { SYMBOLS } from '@constants/symbols'\nimport { useUnifiedAnimation } from '@utils/animationManager'\n\ninterface Props {\n /** \u5F53\u524D\u601D\u8003\u9636\u6BB5\u7684\u6D88\u606F */\n message: string\n\n /** \u662F\u5426\u663E\u793A Spinner \u52A8\u753B */\n showSpinner?: boolean\n\n /** \u662F\u5426\u663E\u793A\u7ECF\u8FC7\u65F6\u95F4 */\n showElapsedTime?: boolean\n\n /** \u8D77\u59CB\u65F6\u95F4 (\u7528\u4E8E\u8BA1\u7B97\u7ECF\u8FC7\u65F6\u95F4) */\n startTime?: number\n}\n\n/**\n * AgentThinkingBlock - \u539F\u5730\u66F4\u65B0\u7684\u601D\u8003\u8FC7\u7A0B\u7EC4\u4EF6\n *\n * \u7528\u6CD5\u793A\u4F8B\uFF1A\n * ```tsx\n * // \u521D\u59CB\u6E32\u67D3\n * <AgentThinkingBlock message=\"Reading file...\" />\n *\n * // \u66F4\u65B0\u6D88\u606F (\u540C\u4E00\u4E2A\u7EC4\u4EF6\u5B9E\u4F8B\uFF0Cprops \u53D8\u5316)\n * <AgentThinkingBlock message=\"Analyzing code...\" />\n *\n * // \u518D\u6B21\u66F4\u65B0\n * <AgentThinkingBlock message=\"Generating response...\" />\n * ```\n *\n * \u7528\u6237\u770B\u5230\u7684\u6548\u679C\uFF1A\n * ```\n * \u00B7 Reading file... \u2190 \u663E\u793A\n * \u2722 Analyzing code... \u2190 \u66FF\u6362 (\u4E0D\u662F\u65B0\u884C)\n * \u2733 Generating response... \u2190 \u518D\u6B21\u66FF\u6362\n * ```\n */\nexport function AgentThinkingBlock({\n message,\n showSpinner = true,\n showElapsedTime = true,\n startTime = Date.now(),\n}: Props): React.ReactNode {\n const theme = getTheme()\n const startTimeRef = useRef(startTime)\n\n // Claude Code \u98CE\u683C\u7684\u601D\u8003\u52A8\u753B - 6\u5E27\u5FAA\u73AF\n const frames = SYMBOLS.THINKING_FRAMES\n\n // Use unified animation manager instead of separate setInterval timers\n const { spinnerFrame, elapsedTime } = useUnifiedAnimation({\n enabled: showSpinner || showElapsedTime,\n startTime: startTimeRef.current,\n spinnerFrameCount: frames.length,\n componentId: 'agent-thinking-block',\n })\n\n return (\n <Box flexDirection=\"row\" marginTop={1}>\n {/* Spinner \u52A8\u753B */}\n {showSpinner && (\n <Box flexWrap=\"nowrap\" height={1} width={2}>\n {/* \u4F7F\u7528\u6697\u6DE1\u8272 - \u5173\u952E\uFF1A\u8FC7\u6E21\u72B6\u6001\u5E94\u8BE5\u4E0D\u663E\u773C */}\n <Text color={theme.dimmedText}>{frames[spinnerFrame]}</Text>\n </Box>\n )}\n\n {/* \u601D\u8003\u6D88\u606F - \u4F7F\u7528\u6697\u6DE1\u8272\uFF0C\u7B26\u5408 Claude Code CLI \u89C4\u8303 */}\n <Text color={theme.dimmedText}>\n {message}\n {showSpinner && '\u2026'}\n </Text>\n\n {/* \u7ECF\u8FC7\u65F6\u95F4\u548C\u63D0\u793A */}\n {showElapsedTime && (\n <Text color={theme.mutedText}>\n {' '}\n ({elapsedTime}s \u00B7 <Text bold>esc esc</Text> to interrupt)\n </Text>\n )}\n </Box>\n )\n}\n\n/**\n * \u8F7B\u91CF\u7EA7\u7684 Thinking Indicator (\u7528\u4E8E\u7D27\u51D1\u5E03\u5C40)\n */\nexport function ThinkingIndicator({\n message,\n}: {\n message: string\n}): React.ReactNode {\n return <AgentThinkingBlock message={message} showElapsedTime={false} />\n}\n"],
5
+ "mappings": "AAaA,OAAO,SAAS,cAAc;AAC9B,SAAS,KAAK,YAAY;AAC1B,SAAS,gBAAgB;AACzB,SAAS,eAAe;AACxB,SAAS,2BAA2B;AAsC7B,SAAS,mBAAmB;AAAA,EACjC;AAAA,EACA,cAAc;AAAA,EACd,kBAAkB;AAAA,EAClB,YAAY,KAAK,IAAI;AACvB,GAA2B;AACzB,QAAM,QAAQ,SAAS;AACvB,QAAM,eAAe,OAAO,SAAS;AAGrC,QAAM,SAAS,QAAQ;AAGvB,QAAM,EAAE,cAAc,YAAY,IAAI,oBAAoB;AAAA,IACxD,SAAS,eAAe;AAAA,IACxB,WAAW,aAAa;AAAA,IACxB,mBAAmB,OAAO;AAAA,IAC1B,aAAa;AAAA,EACf,CAAC;AAED,SACE,oCAAC,OAAI,eAAc,OAAM,WAAW,KAEjC,eACC,oCAAC,OAAI,UAAS,UAAS,QAAQ,GAAG,OAAO,KAEvC,oCAAC,QAAK,OAAO,MAAM,cAAa,OAAO,YAAY,CAAE,CACvD,GAIF,oCAAC,QAAK,OAAO,MAAM,cAChB,SACA,eAAe,QAClB,GAGC,mBACC,oCAAC,QAAK,OAAO,MAAM,aAChB,KAAI,KACH,aAAY,WAAI,oCAAC,QAAK,MAAI,QAAC,SAAO,GAAO,gBAC7C,CAEJ;AAEJ;AAKO,SAAS,kBAAkB;AAAA,EAChC;AACF,GAEoB;AAClB,SAAO,oCAAC,sBAAmB,SAAkB,iBAAiB,OAAO;AACvE;",
6
6
  "names": []
7
7
  }
@@ -3,15 +3,14 @@ import React from "react";
3
3
  import { getTheme } from "../utils/theme.js";
4
4
  function AsciiLogo() {
5
5
  const theme = getTheme();
6
- const logoLines = [
7
- "\u2588\u2588\u2588\u2557\u2591\u2591\u2591\u2588\u2588\u2588\u2557\u2588\u2588\u2557\u2588\u2588\u2588\u2557\u2591\u2591\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2591\u2588\u2588\u2588\u2588\u2588\u2557\u2591",
8
- "\u2588\u2588\u2588\u2588\u2557\u2591\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2557\u2591\u2588\u2588\u2551\u255A\u2550\u2550\u2588\u2588\u2554\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557",
9
- "\u2588\u2588\u2554\u2588\u2588\u2588\u2588\u2554\u2588\u2588\u2551\u2588\u2588\u2551\u2588\u2588\u2554\u2588\u2588\u2557\u2588\u2588\u2551\u2591\u2591\u2591\u2588\u2588\u2551\u2591\u2591\u2591\u2588\u2588\u2551\u2591\u2591\u2588\u2588\u2551",
10
- "\u2588\u2588\u2551\u255A\u2588\u2588\u2554\u255D\u2588\u2588\u2551\u2588\u2588\u2551\u2588\u2588\u2551\u255A\u2588\u2588\u2588\u2588\u2551\u2591\u2591\u2591\u2588\u2588\u2551\u2591\u2591\u2591\u2588\u2588\u2551\u2591\u2591\u2588\u2588\u2551",
11
- "\u2588\u2588\u2551\u2591\u255A\u2550\u255D\u2591\u2588\u2588\u2551\u2588\u2588\u2551\u2588\u2588\u2551\u2591\u255A\u2588\u2588\u2588\u2551\u2591\u2591\u2591\u2588\u2588\u2551\u2591\u2591\u2591\u255A\u2588\u2588\u2588\u2588\u2588\u2554\u255D",
12
- "\u255A\u2550\u255D\u2591\u2591\u2591\u2591\u2591\u255A\u2550\u255D\u255A\u2550\u255D\u255A\u2550\u255D\u2591\u2591\u255A\u2550\u2550\u255D\u2591\u2591\u2591\u255A\u2550\u255D\u2591\u2591\u2591\u2591\u255A\u2550\u2550\u2550\u2550\u255D\u2591"
6
+ const logoLines = ["\u2588\u2580\u2584\u2580\u2588 \u2588 \u2588\u2584 \u2588 \u2580\u2588\u2580 \u2588\u2580\u2588", "\u2588 \u2580 \u2588 \u2588 \u2588 \u2580\u2588 \u2588 \u2588\u2584\u2588"];
7
+ const gradientColors = [
8
+ "#667EEA",
9
+ // Purple-Blue
10
+ "#F5576C"
11
+ // Coral Red
13
12
  ];
14
- return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", alignItems: "flex-start" }, /* @__PURE__ */ React.createElement(Text, { color: "cyan" }, logoLines[0]), /* @__PURE__ */ React.createElement(Text, { color: "blue" }, logoLines[1]), /* @__PURE__ */ React.createElement(Text, { color: "magenta" }, logoLines[2]), /* @__PURE__ */ React.createElement(Text, { color: "magenta" }, logoLines[3]), /* @__PURE__ */ React.createElement(Text, { color: "cyan" }, logoLines[4]), /* @__PURE__ */ React.createElement(Text, { color: "blue" }, logoLines[5]));
13
+ return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", alignItems: "center" }, /* @__PURE__ */ React.createElement(Text, { color: gradientColors[0] }, "\u25C6"), /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", alignItems: "center", marginY: 1 }, /* @__PURE__ */ React.createElement(Text, { color: gradientColors[0], bold: true }, logoLines[0]), /* @__PURE__ */ React.createElement(Text, { color: gradientColors[1], bold: true }, logoLines[1])), /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, /* @__PURE__ */ React.createElement(Text, { color: gradientColors[0] }, "Strategic AI"), /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, " \xB7 "), /* @__PURE__ */ React.createElement(Text, { color: gradientColors[1] }, "Global Excellence")));
15
14
  }
16
15
  export {
17
16
  AsciiLogo
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/components/AsciiLogo.tsx"],
4
- "sourcesContent": ["import { Box, Text } from 'ink'\nimport React from 'react'\nimport { getTheme } from '@utils/theme'\n\nexport function AsciiLogo(): React.ReactNode {\n const theme = getTheme()\n\n // ASCII Logo lines with gradient colors\n const logoLines = [\n '\u2588\u2588\u2588\u2557\u2591\u2591\u2591\u2588\u2588\u2588\u2557\u2588\u2588\u2557\u2588\u2588\u2588\u2557\u2591\u2591\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2591\u2588\u2588\u2588\u2588\u2588\u2557\u2591',\n '\u2588\u2588\u2588\u2588\u2557\u2591\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2557\u2591\u2588\u2588\u2551\u255A\u2550\u2550\u2588\u2588\u2554\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557',\n '\u2588\u2588\u2554\u2588\u2588\u2588\u2588\u2554\u2588\u2588\u2551\u2588\u2588\u2551\u2588\u2588\u2554\u2588\u2588\u2557\u2588\u2588\u2551\u2591\u2591\u2591\u2588\u2588\u2551\u2591\u2591\u2591\u2588\u2588\u2551\u2591\u2591\u2588\u2588\u2551',\n '\u2588\u2588\u2551\u255A\u2588\u2588\u2554\u255D\u2588\u2588\u2551\u2588\u2588\u2551\u2588\u2588\u2551\u255A\u2588\u2588\u2588\u2588\u2551\u2591\u2591\u2591\u2588\u2588\u2551\u2591\u2591\u2591\u2588\u2588\u2551\u2591\u2591\u2588\u2588\u2551',\n '\u2588\u2588\u2551\u2591\u255A\u2550\u255D\u2591\u2588\u2588\u2551\u2588\u2588\u2551\u2588\u2588\u2551\u2591\u255A\u2588\u2588\u2588\u2551\u2591\u2591\u2591\u2588\u2588\u2551\u2591\u2591\u2591\u255A\u2588\u2588\u2588\u2588\u2588\u2554\u255D',\n '\u255A\u2550\u255D\u2591\u2591\u2591\u2591\u2591\u255A\u2550\u255D\u255A\u2550\u255D\u255A\u2550\u255D\u2591\u2591\u255A\u2550\u2550\u255D\u2591\u2591\u2591\u255A\u2550\u255D\u2591\u2591\u2591\u2591\u255A\u2550\u2550\u2550\u2550\u255D\u2591',\n ]\n\n return (\n <Box flexDirection=\"column\" alignItems=\"flex-start\">\n <Text color=\"cyan\">{logoLines[0]}</Text>\n <Text color=\"blue\">{logoLines[1]}</Text>\n <Text color=\"magenta\">{logoLines[2]}</Text>\n <Text color=\"magenta\">{logoLines[3]}</Text>\n <Text color=\"cyan\">{logoLines[4]}</Text>\n <Text color=\"blue\">{logoLines[5]}</Text>\n </Box>\n )\n}\n"],
5
- "mappings": "AAAA,SAAS,KAAK,YAAY;AAC1B,OAAO,WAAW;AAClB,SAAS,gBAAgB;AAElB,SAAS,YAA6B;AAC3C,QAAM,QAAQ,SAAS;AAGvB,QAAM,YAAY;AAAA,IAChB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,SACE,oCAAC,OAAI,eAAc,UAAS,YAAW,gBACrC,oCAAC,QAAK,OAAM,UAAQ,UAAU,CAAC,CAAE,GACjC,oCAAC,QAAK,OAAM,UAAQ,UAAU,CAAC,CAAE,GACjC,oCAAC,QAAK,OAAM,aAAW,UAAU,CAAC,CAAE,GACpC,oCAAC,QAAK,OAAM,aAAW,UAAU,CAAC,CAAE,GACpC,oCAAC,QAAK,OAAM,UAAQ,UAAU,CAAC,CAAE,GACjC,oCAAC,QAAK,OAAM,UAAQ,UAAU,CAAC,CAAE,CACnC;AAEJ;",
4
+ "sourcesContent": ["import { Box, Text } from 'ink'\nimport React from 'react'\nimport { getTheme } from '@utils/theme'\n\nexport function AsciiLogo(): React.ReactNode {\n const theme = getTheme()\n\n // Bold modern ASCII font - powerful yet refined\n // Uses half-block characters for a contemporary, impactful look\n const logoLines = ['\u2588\u2580\u2584\u2580\u2588 \u2588 \u2588\u2584 \u2588 \u2580\u2588\u2580 \u2588\u2580\u2588', '\u2588 \u2580 \u2588 \u2588 \u2588 \u2580\u2588 \u2588 \u2588\u2584\u2588']\n\n // Sunset gradient: Purple-Blue \u2192 Coral\n const gradientColors = [\n '#667EEA', // Purple-Blue\n '#F5576C', // Coral Red\n ]\n\n return (\n <Box flexDirection=\"column\" alignItems=\"center\">\n {/* Decorative diamond */}\n <Text color={gradientColors[0]}>{'\u25C6'}</Text>\n\n {/* Main MINTO text with gradient */}\n <Box flexDirection=\"column\" alignItems=\"center\" marginY={1}>\n <Text color={gradientColors[0]} bold>\n {logoLines[0]}\n </Text>\n <Text color={gradientColors[1]} bold>\n {logoLines[1]}\n </Text>\n </Box>\n\n {/* Tagline */}\n <Text color={theme.secondaryText}>\n <Text color={gradientColors[0]}>Strategic AI</Text>\n <Text color={theme.secondaryText}>{' \u00B7 '}</Text>\n <Text color={gradientColors[1]}>Global Excellence</Text>\n </Text>\n </Box>\n )\n}\n"],
5
+ "mappings": "AAAA,SAAS,KAAK,YAAY;AAC1B,OAAO,WAAW;AAClB,SAAS,gBAAgB;AAElB,SAAS,YAA6B;AAC3C,QAAM,QAAQ,SAAS;AAIvB,QAAM,YAAY,CAAC,mGAAwB,6EAAsB;AAGjE,QAAM,iBAAiB;AAAA,IACrB;AAAA;AAAA,IACA;AAAA;AAAA,EACF;AAEA,SACE,oCAAC,OAAI,eAAc,UAAS,YAAW,YAErC,oCAAC,QAAK,OAAO,eAAe,CAAC,KAAI,QAAI,GAGrC,oCAAC,OAAI,eAAc,UAAS,YAAW,UAAS,SAAS,KACvD,oCAAC,QAAK,OAAO,eAAe,CAAC,GAAG,MAAI,QACjC,UAAU,CAAC,CACd,GACA,oCAAC,QAAK,OAAO,eAAe,CAAC,GAAG,MAAI,QACjC,UAAU,CAAC,CACd,CACF,GAGA,oCAAC,QAAK,OAAO,MAAM,iBACjB,oCAAC,QAAK,OAAO,eAAe,CAAC,KAAG,cAAY,GAC5C,oCAAC,QAAK,OAAO,MAAM,iBAAgB,QAAM,GACzC,oCAAC,QAAK,OAAO,eAAe,CAAC,KAAG,mBAAiB,CACnD,CACF;AAEJ;",
6
6
  "names": []
7
7
  }
@@ -5,6 +5,7 @@ import { QuestionView } from "./QuestionView.js";
5
5
  import { useNotifyAfterTimeout } from "../../hooks/useNotifyAfterTimeout.js";
6
6
  import { PRODUCT_NAME } from "../../constants/product.js";
7
7
  import TextInput from "ink-text-input";
8
+ import { BRAND_GRADIENT, SEMANTIC_COLORS } from "../../constants/colors.js";
8
9
  function AskUserQuestionDialog({
9
10
  context,
10
11
  onDone
@@ -113,14 +114,14 @@ function AskUserQuestionDialog({
113
114
  resolve
114
115
  ]
115
116
  );
116
- return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", paddingY: 1 }, isCustomInputMode ? /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", paddingX: 2 }, /* @__PURE__ */ React.createElement(Box, { marginBottom: 1 }, /* @__PURE__ */ React.createElement(Text, { bold: true }, "Enter your custom response:")), /* @__PURE__ */ React.createElement(Box, { marginBottom: 1 }, /* @__PURE__ */ React.createElement(Text, { color: "cyan" }, "> "), /* @__PURE__ */ React.createElement(
117
+ return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", paddingY: 1 }, isCustomInputMode ? /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", paddingX: 2 }, /* @__PURE__ */ React.createElement(Box, { marginBottom: 1 }, /* @__PURE__ */ React.createElement(Text, { bold: true }, "Enter your custom response:")), /* @__PURE__ */ React.createElement(Box, { marginBottom: 1 }, /* @__PURE__ */ React.createElement(Text, { color: BRAND_GRADIENT.START }, "> "), /* @__PURE__ */ React.createElement(
117
118
  TextInput,
118
119
  {
119
120
  value: customInput,
120
121
  onChange: setCustomInput,
121
122
  onSubmit: handleConfirm
122
123
  }
123
- )), /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, "[Enter to confirm] [Esc to cancel]"))) : (
124
+ )), /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.dim }, "[Enter to confirm] [Esc to cancel]"))) : (
124
125
  /* Normal question view */
125
126
  /* @__PURE__ */ React.createElement(
126
127
  QuestionView,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/components/AskUserQuestionDialog/AskUserQuestionDialog.tsx"],
4
- "sourcesContent": ["import { Box, Text, useInput } from 'ink'\nimport * as React from 'react'\nimport { useState, useCallback } from 'react'\nimport {\n type AskUserQuestionContext,\n type UserAnswer,\n} from '@minto-types/askUserQuestion'\nimport { QuestionView } from './QuestionView'\nimport { useNotifyAfterTimeout } from '@hooks/useNotifyAfterTimeout'\nimport { PRODUCT_NAME } from '@constants/product'\nimport TextInput from 'ink-text-input'\n\ninterface AskUserQuestionDialogProps {\n context: AskUserQuestionContext\n onDone: () => void\n}\n\nexport function AskUserQuestionDialog({\n context,\n onDone,\n}: AskUserQuestionDialogProps): React.ReactElement {\n const { questions, resolve, reject } = context\n\n // Current question index (for multi-question scenarios)\n const [currentQuestionIndex, setCurrentQuestionIndex] = useState(0)\n\n // Selected option indices for each question\n const [selectedOptions, setSelectedOptions] = useState<number[]>(\n questions.map(() => 0),\n )\n\n // Custom input mode for \"Other\" option\n const [isCustomInputMode, setIsCustomInputMode] = useState(false)\n const [customInput, setCustomInput] = useState('')\n\n // Notification after timeout\n useNotifyAfterTimeout(`${PRODUCT_NAME} needs your input to continue`)\n\n const currentQuestion = questions[currentQuestionIndex]!\n\n // Handle keyboard input\n useInput(\n (input, key) => {\n // Cancel with Escape or Ctrl+C\n if (key.escape || (key.ctrl && input === 'c')) {\n onDone()\n reject()\n return\n }\n\n // Don't handle other keys in custom input mode\n if (isCustomInputMode) {\n return\n }\n\n // Navigate between questions with left/right arrows\n if (key.leftArrow && currentQuestionIndex > 0) {\n setCurrentQuestionIndex(prev => prev - 1)\n return\n }\n\n if (key.rightArrow && currentQuestionIndex < questions.length - 1) {\n setCurrentQuestionIndex(prev => prev + 1)\n return\n }\n\n // Confirm with Enter\n if (key.return) {\n handleConfirm()\n return\n }\n\n // Press 'o' to enter custom input mode\n if (input === 'o' && currentQuestion.options) {\n setIsCustomInputMode(true)\n setCustomInput('')\n return\n }\n },\n { isActive: true },\n )\n\n // Handle option change\n const handleOptionChange = useCallback(\n (optionIndex: number) => {\n const newSelectedOptions = [...selectedOptions]\n newSelectedOptions[currentQuestionIndex] = optionIndex\n setSelectedOptions(newSelectedOptions)\n\n // If \"Other\" is selected (-1), enter custom input mode\n if (optionIndex === -1) {\n setIsCustomInputMode(true)\n setCustomInput('')\n }\n },\n [selectedOptions, currentQuestionIndex],\n )\n\n // Handle confirmation\n const handleConfirm = useCallback(() => {\n // If in custom input mode, save the custom input\n if (isCustomInputMode) {\n if (!customInput.trim()) {\n // Don't allow empty custom input\n return\n }\n\n // Save custom input and exit custom input mode\n setIsCustomInputMode(false)\n\n // If this is the last question, submit all answers\n if (currentQuestionIndex === questions.length - 1) {\n submitAnswers(customInput)\n } else {\n // Move to next question\n setCurrentQuestionIndex(prev => prev + 1)\n }\n return\n }\n\n // If this is the last question, submit all answers\n if (currentQuestionIndex === questions.length - 1) {\n submitAnswers()\n } else {\n // Move to next question\n setCurrentQuestionIndex(prev => prev + 1)\n }\n }, [isCustomInputMode, customInput, currentQuestionIndex, questions.length])\n\n // Submit all answers\n const submitAnswers = useCallback(\n (customInputOverride?: string) => {\n const answers: UserAnswer[] = questions.map((question, index) => {\n const selectedOptionIndex = selectedOptions[index]!\n\n // If it's the current question and we have custom input\n if (\n index === currentQuestionIndex &&\n (customInputOverride || isCustomInputMode)\n ) {\n return {\n questionIndex: index,\n customInput: customInputOverride || customInput,\n }\n }\n\n // If \"Other\" was selected (-1), use custom input\n if (selectedOptionIndex === -1) {\n return {\n questionIndex: index,\n customInput: customInput,\n }\n }\n\n // Regular option selection\n return {\n questionIndex: index,\n selectedOptions: [selectedOptionIndex],\n }\n })\n\n onDone()\n resolve(answers)\n },\n [\n questions,\n selectedOptions,\n currentQuestionIndex,\n isCustomInputMode,\n customInput,\n onDone,\n resolve,\n ],\n )\n\n return (\n <Box flexDirection=\"column\" paddingY={1}>\n {/* Custom input mode */}\n {isCustomInputMode ? (\n <Box flexDirection=\"column\" paddingX={2}>\n <Box marginBottom={1}>\n <Text bold>Enter your custom response:</Text>\n </Box>\n <Box marginBottom={1}>\n <Text color=\"cyan\">&gt; </Text>\n <TextInput\n value={customInput}\n onChange={setCustomInput}\n onSubmit={handleConfirm}\n />\n </Box>\n <Box>\n <Text dimColor>[Enter to confirm] [Esc to cancel]</Text>\n </Box>\n </Box>\n ) : (\n /* Normal question view */\n <QuestionView\n question={currentQuestion}\n questionIndex={currentQuestionIndex}\n totalQuestions={questions.length}\n selectedOptionIndex={selectedOptions[currentQuestionIndex]!}\n onOptionChange={handleOptionChange}\n />\n )}\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, useCallback } from 'react'\nimport {\n type AskUserQuestionContext,\n type UserAnswer,\n} from '@minto-types/askUserQuestion'\nimport { QuestionView } from './QuestionView'\nimport { useNotifyAfterTimeout } from '@hooks/useNotifyAfterTimeout'\nimport { PRODUCT_NAME } from '@constants/product'\nimport TextInput from 'ink-text-input'\nimport { BRAND_GRADIENT, SEMANTIC_COLORS } from '@constants/colors'\n\ninterface AskUserQuestionDialogProps {\n context: AskUserQuestionContext\n onDone: () => void\n}\n\nexport function AskUserQuestionDialog({\n context,\n onDone,\n}: AskUserQuestionDialogProps): React.ReactElement {\n const { questions, resolve, reject } = context\n\n // Current question index (for multi-question scenarios)\n const [currentQuestionIndex, setCurrentQuestionIndex] = useState(0)\n\n // Selected option indices for each question\n const [selectedOptions, setSelectedOptions] = useState<number[]>(\n questions.map(() => 0),\n )\n\n // Custom input mode for \"Other\" option\n const [isCustomInputMode, setIsCustomInputMode] = useState(false)\n const [customInput, setCustomInput] = useState('')\n\n // Notification after timeout\n useNotifyAfterTimeout(`${PRODUCT_NAME} needs your input to continue`)\n\n const currentQuestion = questions[currentQuestionIndex]!\n\n // Handle keyboard input\n useInput(\n (input, key) => {\n // Cancel with Escape or Ctrl+C\n if (key.escape || (key.ctrl && input === 'c')) {\n onDone()\n reject()\n return\n }\n\n // Don't handle other keys in custom input mode\n if (isCustomInputMode) {\n return\n }\n\n // Navigate between questions with left/right arrows\n if (key.leftArrow && currentQuestionIndex > 0) {\n setCurrentQuestionIndex(prev => prev - 1)\n return\n }\n\n if (key.rightArrow && currentQuestionIndex < questions.length - 1) {\n setCurrentQuestionIndex(prev => prev + 1)\n return\n }\n\n // Confirm with Enter\n if (key.return) {\n handleConfirm()\n return\n }\n\n // Press 'o' to enter custom input mode\n if (input === 'o' && currentQuestion.options) {\n setIsCustomInputMode(true)\n setCustomInput('')\n return\n }\n },\n { isActive: true },\n )\n\n // Handle option change\n const handleOptionChange = useCallback(\n (optionIndex: number) => {\n const newSelectedOptions = [...selectedOptions]\n newSelectedOptions[currentQuestionIndex] = optionIndex\n setSelectedOptions(newSelectedOptions)\n\n // If \"Other\" is selected (-1), enter custom input mode\n if (optionIndex === -1) {\n setIsCustomInputMode(true)\n setCustomInput('')\n }\n },\n [selectedOptions, currentQuestionIndex],\n )\n\n // Handle confirmation\n const handleConfirm = useCallback(() => {\n // If in custom input mode, save the custom input\n if (isCustomInputMode) {\n if (!customInput.trim()) {\n // Don't allow empty custom input\n return\n }\n\n // Save custom input and exit custom input mode\n setIsCustomInputMode(false)\n\n // If this is the last question, submit all answers\n if (currentQuestionIndex === questions.length - 1) {\n submitAnswers(customInput)\n } else {\n // Move to next question\n setCurrentQuestionIndex(prev => prev + 1)\n }\n return\n }\n\n // If this is the last question, submit all answers\n if (currentQuestionIndex === questions.length - 1) {\n submitAnswers()\n } else {\n // Move to next question\n setCurrentQuestionIndex(prev => prev + 1)\n }\n }, [isCustomInputMode, customInput, currentQuestionIndex, questions.length])\n\n // Submit all answers\n const submitAnswers = useCallback(\n (customInputOverride?: string) => {\n const answers: UserAnswer[] = questions.map((question, index) => {\n const selectedOptionIndex = selectedOptions[index]!\n\n // If it's the current question and we have custom input\n if (\n index === currentQuestionIndex &&\n (customInputOverride || isCustomInputMode)\n ) {\n return {\n questionIndex: index,\n customInput: customInputOverride || customInput,\n }\n }\n\n // If \"Other\" was selected (-1), use custom input\n if (selectedOptionIndex === -1) {\n return {\n questionIndex: index,\n customInput: customInput,\n }\n }\n\n // Regular option selection\n return {\n questionIndex: index,\n selectedOptions: [selectedOptionIndex],\n }\n })\n\n onDone()\n resolve(answers)\n },\n [\n questions,\n selectedOptions,\n currentQuestionIndex,\n isCustomInputMode,\n customInput,\n onDone,\n resolve,\n ],\n )\n\n return (\n <Box flexDirection=\"column\" paddingY={1}>\n {/* Custom input mode */}\n {isCustomInputMode ? (\n <Box flexDirection=\"column\" paddingX={2}>\n <Box marginBottom={1}>\n <Text bold>Enter your custom response:</Text>\n </Box>\n <Box marginBottom={1}>\n <Text color={BRAND_GRADIENT.START}>&gt; </Text>\n <TextInput\n value={customInput}\n onChange={setCustomInput}\n onSubmit={handleConfirm}\n />\n </Box>\n <Box>\n <Text color={SEMANTIC_COLORS.dim}>\n [Enter to confirm] [Esc to cancel]\n </Text>\n </Box>\n </Box>\n ) : (\n /* Normal question view */\n <QuestionView\n question={currentQuestion}\n questionIndex={currentQuestionIndex}\n totalQuestions={questions.length}\n selectedOptionIndex={selectedOptions[currentQuestionIndex]!}\n onOptionChange={handleOptionChange}\n />\n )}\n </Box>\n )\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
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,