@within-7/minto 0.3.6 → 0.3.10

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 (238) hide show
  1. package/{cli.js → cli.cjs} +25 -23
  2. package/dist/commands/agents/AgentsCommand.js +459 -655
  3. package/dist/commands/agents/AgentsCommand.js.map +2 -2
  4. package/dist/commands/agents/types.js +1 -0
  5. package/dist/commands/agents/types.js.map +2 -2
  6. package/dist/commands/agents/utils/fileOperations.js +96 -36
  7. package/dist/commands/agents/utils/fileOperations.js.map +3 -3
  8. package/dist/commands/agents/utils/index.js +3 -1
  9. package/dist/commands/agents/utils/index.js.map +2 -2
  10. package/dist/commands/context.js +54 -23
  11. package/dist/commands/context.js.map +2 -2
  12. package/dist/commands/export.js +673 -93
  13. package/dist/commands/export.js.map +2 -2
  14. package/dist/commands/language.js +110 -0
  15. package/dist/commands/language.js.map +7 -0
  16. package/dist/commands/mcp-interactive.js +419 -217
  17. package/dist/commands/mcp-interactive.js.map +2 -2
  18. package/dist/commands/model.js +415 -66
  19. package/dist/commands/model.js.map +2 -2
  20. package/dist/commands/new.js +56 -0
  21. package/dist/commands/new.js.map +7 -0
  22. package/dist/commands/permissions.js +75 -49
  23. package/dist/commands/permissions.js.map +2 -2
  24. package/dist/commands/plugin.js +882 -185
  25. package/dist/commands/plugin.js.map +3 -3
  26. package/dist/commands/resume.js +251 -16
  27. package/dist/commands/resume.js.map +2 -2
  28. package/dist/commands/sandbox.js +168 -70
  29. package/dist/commands/sandbox.js.map +2 -2
  30. package/dist/commands/sessions.js +224 -0
  31. package/dist/commands/sessions.js.map +7 -0
  32. package/dist/commands/setup.js +596 -109
  33. package/dist/commands/setup.js.map +2 -2
  34. package/dist/commands/stats.js +292 -0
  35. package/dist/commands/stats.js.map +7 -0
  36. package/dist/commands/status.js +75 -7
  37. package/dist/commands/status.js.map +2 -2
  38. package/dist/commands/undo.js +154 -180
  39. package/dist/commands/undo.js.map +2 -2
  40. package/dist/commands.js +6 -0
  41. package/dist/commands.js.map +2 -2
  42. package/dist/components/AskUserQuestionDialog/AskUserQuestionDialog.js +3 -2
  43. package/dist/components/AskUserQuestionDialog/AskUserQuestionDialog.js.map +2 -2
  44. package/dist/components/Config.js +9 -8
  45. package/dist/components/Config.js.map +2 -2
  46. package/dist/components/HeaderBar.js +2 -1
  47. package/dist/components/HeaderBar.js.map +2 -2
  48. package/dist/components/Help.js +166 -32
  49. package/dist/components/Help.js.map +2 -2
  50. package/dist/components/HotkeyHelpPanel.js +46 -44
  51. package/dist/components/HotkeyHelpPanel.js.map +2 -2
  52. package/dist/components/InfoPanel/InfoPanel.js +123 -0
  53. package/dist/components/InfoPanel/InfoPanel.js.map +7 -0
  54. package/dist/components/InfoPanel/index.js +5 -0
  55. package/dist/components/InfoPanel/index.js.map +7 -0
  56. package/dist/components/InfoPanel/types.js +1 -0
  57. package/dist/components/InfoPanel/types.js.map +7 -0
  58. package/dist/components/Logo.js +5 -2
  59. package/dist/components/Logo.js.map +2 -2
  60. package/dist/components/MCPServerApprovalDialog.js +6 -5
  61. package/dist/components/MCPServerApprovalDialog.js.map +2 -2
  62. package/dist/components/MCPServerMultiselectDialog.js +5 -4
  63. package/dist/components/MCPServerMultiselectDialog.js.map +2 -2
  64. package/dist/components/MessageSelector.js +4 -3
  65. package/dist/components/MessageSelector.js.map +2 -2
  66. package/dist/components/ModelConfig.js +13 -12
  67. package/dist/components/ModelConfig.js.map +2 -2
  68. package/dist/components/ModelListManager.js +4 -3
  69. package/dist/components/ModelListManager.js.map +2 -2
  70. package/dist/components/ModelSelector/BrandTextInput.js +43 -0
  71. package/dist/components/ModelSelector/BrandTextInput.js.map +7 -0
  72. package/dist/components/ModelSelector/ModelSelector.js +419 -501
  73. package/dist/components/ModelSelector/ModelSelector.js.map +2 -2
  74. package/dist/components/ModelSelector/WizardContainer.js +45 -0
  75. package/dist/components/ModelSelector/WizardContainer.js.map +7 -0
  76. package/dist/components/ModelSelector/index.js +1 -3
  77. package/dist/components/ModelSelector/index.js.map +2 -2
  78. package/dist/components/PromptInput.js +77 -44
  79. package/dist/components/PromptInput.js.map +2 -2
  80. package/dist/components/SensitiveFileWarning.js +12 -8
  81. package/dist/components/SensitiveFileWarning.js.map +2 -2
  82. package/dist/components/SimpleSelector/SimpleSelector.js +154 -0
  83. package/dist/components/SimpleSelector/SimpleSelector.js.map +7 -0
  84. package/dist/components/SimpleSelector/index.js +5 -0
  85. package/dist/components/SimpleSelector/index.js.map +7 -0
  86. package/dist/components/SimpleSelector/types.js +1 -0
  87. package/dist/components/SimpleSelector/types.js.map +7 -0
  88. package/dist/components/StatusOverlayContent.js +21 -0
  89. package/dist/components/StatusOverlayContent.js.map +7 -0
  90. package/dist/components/TabbedListView/ScrollableList.js +117 -0
  91. package/dist/components/TabbedListView/ScrollableList.js.map +7 -0
  92. package/dist/components/TabbedListView/SearchInput.js +23 -0
  93. package/dist/components/TabbedListView/SearchInput.js.map +7 -0
  94. package/dist/components/TabbedListView/TabBar.js +20 -0
  95. package/dist/components/TabbedListView/TabBar.js.map +7 -0
  96. package/dist/components/TabbedListView/TabbedListView.js +246 -0
  97. package/dist/components/TabbedListView/TabbedListView.js.map +7 -0
  98. package/dist/components/TabbedListView/index.js +11 -0
  99. package/dist/components/TabbedListView/index.js.map +7 -0
  100. package/dist/components/TabbedListView/types.js +1 -0
  101. package/dist/components/TabbedListView/types.js.map +7 -0
  102. package/dist/components/TodoChangeBlock.js +6 -5
  103. package/dist/components/TodoChangeBlock.js.map +3 -3
  104. package/dist/components/TodoPanel.js +6 -3
  105. package/dist/components/TodoPanel.js.map +3 -3
  106. package/dist/components/TrustDialog.js +6 -5
  107. package/dist/components/TrustDialog.js.map +2 -2
  108. package/dist/components/messages/UserToolResultMessage/UserToolCanceledMessage.js +2 -1
  109. package/dist/components/messages/UserToolResultMessage/UserToolCanceledMessage.js.map +2 -2
  110. package/dist/constants/macros.js +1 -1
  111. package/dist/constants/macros.js.map +1 -1
  112. package/dist/constants/product.js +2 -2
  113. package/dist/constants/product.js.map +1 -1
  114. package/dist/constants/prompts.js +17 -0
  115. package/dist/constants/prompts.js.map +2 -2
  116. package/dist/constants/toolInputExamples.js +5 -1
  117. package/dist/constants/toolInputExamples.js.map +2 -2
  118. package/dist/core/backupHook.js +29 -0
  119. package/dist/core/backupHook.js.map +7 -0
  120. package/dist/core/config/defaults.js +8 -2
  121. package/dist/core/config/defaults.js.map +2 -2
  122. package/dist/core/config/schema.js +14 -2
  123. package/dist/core/config/schema.js.map +2 -2
  124. package/dist/core/costTracker.js +0 -16
  125. package/dist/core/costTracker.js.map +2 -2
  126. package/dist/core/tokenStatsManager.js +5 -0
  127. package/dist/core/tokenStatsManager.js.map +2 -2
  128. package/dist/cost-tracker.js +0 -16
  129. package/dist/cost-tracker.js.map +2 -2
  130. package/dist/entrypoints/bootstrap.js +56 -0
  131. package/dist/entrypoints/bootstrap.js.map +7 -0
  132. package/dist/entrypoints/cli.js +164 -23
  133. package/dist/entrypoints/cli.js.map +3 -3
  134. package/dist/history.js +75 -15
  135. package/dist/history.js.map +2 -2
  136. package/dist/i18n/index.js +2 -2
  137. package/dist/i18n/index.js.map +2 -2
  138. package/dist/i18n/locales/en.js +582 -1
  139. package/dist/i18n/locales/en.js.map +2 -2
  140. package/dist/i18n/locales/zh-CN.js +582 -1
  141. package/dist/i18n/locales/zh-CN.js.map +2 -2
  142. package/dist/i18n/types.js.map +1 -1
  143. package/dist/index.js +1 -1
  144. package/dist/index.js.map +2 -2
  145. package/dist/messages.js +11 -0
  146. package/dist/messages.js.map +2 -2
  147. package/dist/permissions.js.map +2 -2
  148. package/dist/query.js +9 -0
  149. package/dist/query.js.map +2 -2
  150. package/dist/screens/REPL.js +45 -7
  151. package/dist/screens/REPL.js.map +2 -2
  152. package/dist/services/customCommands.js +44 -16
  153. package/dist/services/customCommands.js.map +2 -2
  154. package/dist/services/plugins/lspServers.js +1 -1
  155. package/dist/services/plugins/lspServers.js.map +2 -2
  156. package/dist/services/plugins/pluginRuntime.js +2 -1
  157. package/dist/services/plugins/pluginRuntime.js.map +2 -2
  158. package/dist/services/plugins/pluginValidation.js +10 -3
  159. package/dist/services/plugins/pluginValidation.js.map +2 -2
  160. package/dist/services/plugins/skillMarketplace.js +16 -8
  161. package/dist/services/plugins/skillMarketplace.js.map +2 -2
  162. package/dist/services/systemReminder.js +17 -6
  163. package/dist/services/systemReminder.js.map +2 -2
  164. package/dist/tools/FileEditTool/FileEditTool.js +7 -0
  165. package/dist/tools/FileEditTool/FileEditTool.js.map +2 -2
  166. package/dist/tools/FileWriteTool/FileWriteTool.js +7 -0
  167. package/dist/tools/FileWriteTool/FileWriteTool.js.map +2 -2
  168. package/dist/tools/MultiEditTool/MultiEditTool.js +7 -0
  169. package/dist/tools/MultiEditTool/MultiEditTool.js.map +2 -2
  170. package/dist/tools/NotebookEditTool/NotebookEditTool.js +2 -0
  171. package/dist/tools/NotebookEditTool/NotebookEditTool.js.map +2 -2
  172. package/dist/tools/TaskTool/TaskTool.js +179 -1
  173. package/dist/tools/TaskTool/TaskTool.js.map +2 -2
  174. package/dist/tools/TodoWriteTool/prompt.js +21 -0
  175. package/dist/tools/TodoWriteTool/prompt.js.map +2 -2
  176. package/dist/tools/URLFetcherTool/prompt.js +14 -9
  177. package/dist/tools/URLFetcherTool/prompt.js.map +2 -2
  178. package/dist/tools/WebSearchTool/prompt.js +12 -6
  179. package/dist/tools/WebSearchTool/prompt.js.map +2 -2
  180. package/dist/types/PermissionMode.js +30 -1
  181. package/dist/types/PermissionMode.js.map +2 -2
  182. package/dist/types/plugin.js +2 -4
  183. package/dist/types/plugin.js.map +2 -2
  184. package/dist/utils/agentHookExecutor.js +103 -0
  185. package/dist/utils/agentHookExecutor.js.map +7 -0
  186. package/dist/utils/agentLoader.js +272 -32
  187. package/dist/utils/agentLoader.js.map +2 -2
  188. package/dist/utils/agentMemory.js +134 -0
  189. package/dist/utils/agentMemory.js.map +7 -0
  190. package/dist/utils/claudeCodeSync.js +439 -0
  191. package/dist/utils/claudeCodeSync.js.map +7 -0
  192. package/dist/utils/config.js +52 -24
  193. package/dist/utils/config.js.map +2 -2
  194. package/dist/utils/configPaths.js +199 -0
  195. package/dist/utils/configPaths.js.map +7 -0
  196. package/dist/utils/execFileNoThrow.js +2 -1
  197. package/dist/utils/execFileNoThrow.js.map +2 -2
  198. package/dist/utils/historyManager.js +234 -0
  199. package/dist/utils/historyManager.js.map +7 -0
  200. package/dist/utils/marketplaceManager.js +80 -43
  201. package/dist/utils/marketplaceManager.js.map +2 -2
  202. package/dist/utils/messages.js +13 -8
  203. package/dist/utils/messages.js.map +2 -2
  204. package/dist/utils/migration/index.js +37 -0
  205. package/dist/utils/migration/index.js.map +7 -0
  206. package/dist/utils/migration/migrateHistory.js +273 -0
  207. package/dist/utils/migration/migrateHistory.js.map +7 -0
  208. package/dist/utils/migration/migrateTodos.js +323 -0
  209. package/dist/utils/migration/migrateTodos.js.map +7 -0
  210. package/dist/utils/pasteCache.js +309 -0
  211. package/dist/utils/pasteCache.js.map +7 -0
  212. package/dist/utils/pluginInstaller.js +34 -24
  213. package/dist/utils/pluginInstaller.js.map +2 -2
  214. package/dist/utils/pluginLoader.js +54 -28
  215. package/dist/utils/pluginLoader.js.map +2 -2
  216. package/dist/utils/repoFetcher.js +110 -0
  217. package/dist/utils/repoFetcher.js.map +7 -0
  218. package/dist/utils/sessionIndex.js +192 -0
  219. package/dist/utils/sessionIndex.js.map +7 -0
  220. package/dist/utils/sessionTracker.js +170 -0
  221. package/dist/utils/sessionTracker.js.map +7 -0
  222. package/dist/utils/skillLoader.js +103 -5
  223. package/dist/utils/skillLoader.js.map +2 -2
  224. package/dist/utils/stats.js +417 -0
  225. package/dist/utils/stats.js.map +7 -0
  226. package/dist/utils/stringSubstitution.js +106 -0
  227. package/dist/utils/stringSubstitution.js.map +7 -0
  228. package/dist/utils/teamConfig.js +156 -14
  229. package/dist/utils/teamConfig.js.map +2 -2
  230. package/dist/utils/terminal.js +1 -1
  231. package/dist/utils/terminal.js.map +2 -2
  232. package/dist/utils/todoStorage.js +51 -19
  233. package/dist/utils/todoStorage.js.map +2 -2
  234. package/dist/utils/tooling/safeRender.js.map +2 -2
  235. package/dist/version.js +2 -2
  236. package/dist/version.js.map +1 -1
  237. package/package.json +71 -28
  238. package/scripts/{postinstall.js → postinstall.cjs} +1 -1
@@ -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'\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": "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",
4
+ "sourcesContent": ["/**\n * Status Command\n *\n * Shows version information, connection status, and system health.\n * Uses InfoPanel for consistent UI.\n */\n\nimport React from 'react'\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'\nimport { InfoPanel } from '@components/InfoPanel'\nimport type { InfoSection } from '@components/InfoPanel'\nimport { t } from '@i18n'\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\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\n }\n } catch {\n // Model not configured\n }\n\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\nfunction buildSections(status: StatusInfo): InfoSection[] {\n const sections: InfoSection[] = []\n\n // Version Info\n const versionItems = [\n {\n label: 'Minto',\n value: `v${status.version}`,\n valueColor: SEMANTIC_COLORS.success,\n },\n { label: 'Node.js', value: status.nodeVersion },\n ]\n if (status.bunVersion) {\n versionItems.push({ label: 'Bun', value: status.bunVersion })\n }\n versionItems.push({ label: 'Platform', value: status.platform })\n sections.push({\n title: t('commands.status.versionInfo'),\n items: versionItems,\n })\n\n // Environment\n sections.push({\n title: t('commands.status.environment'),\n items: [{ label: 'CWD', value: status.cwd }],\n })\n\n // Model Configuration\n if (status.modelInfo) {\n sections.push({\n title: t('commands.status.modelConfiguration'),\n items: [\n {\n label: 'Model',\n value: status.modelInfo.name,\n valueColor: SEMANTIC_COLORS.info,\n },\n { label: 'Provider', value: status.modelInfo.provider },\n {\n label: 'Context',\n value: `${(status.modelInfo.contextLength / 1000).toFixed(0)}k tokens`,\n },\n ],\n })\n } else {\n sections.push({\n title: t('commands.status.modelConfiguration'),\n items: [\n {\n label: 'Status',\n value: t('commands.status.notConfigured'),\n valueColor: '#FFB86C',\n },\n ],\n })\n }\n\n // API Connection\n sections.push({\n title: t('commands.status.apiConnection'),\n items: [\n {\n label: 'Status',\n value: status.apiConnected\n ? `\\u25CF ${t('commands.status.connected')}`\n : `\\u25CB ${t('commands.status.notConnected')}`,\n valueColor: status.apiConnected\n ? SEMANTIC_COLORS.success\n : SEMANTIC_COLORS.error,\n },\n ],\n })\n\n return sections\n}\n\nconst command: Command = {\n name: 'status',\n description: t('commands.status.description'),\n isEnabled: true,\n isHidden: false,\n hidePromptInput: true,\n type: 'local-jsx',\n\n userFacingName() {\n return this.name\n },\n\n async call(onDone) {\n const status = await getStatusInfo()\n const sections = buildSections(status)\n\n return (\n <InfoPanel\n title={t('commands.status.title')}\n sections={sections}\n onClose={onDone}\n />\n )\n },\n}\n\nexport default command\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,28 +1,37 @@
1
- import React, { useState, useEffect } from "react";
2
- import { Box, Text, useInput } from "ink";
3
- import { SEMANTIC_COLORS } from "../constants/colors.js";
1
+ import React, { useState, useEffect, useCallback, useMemo } from "react";
4
2
  import { getCwd } from "../utils/state.js";
5
3
  import {
6
4
  listBackedUpFiles,
7
5
  getBackupVersions,
8
6
  restoreBackup
9
7
  } from "../core/backupManager.js";
8
+ import { TabbedListView } from "../components/TabbedListView/TabbedListView.js";
9
+ import { t } from "../i18n/index.js";
10
10
  function formatTimestamp(timestamp) {
11
11
  const date = new Date(timestamp);
12
12
  const now = /* @__PURE__ */ new Date();
13
13
  const diff = now.getTime() - timestamp;
14
+ const timeStr = `${date.getHours().toString().padStart(2, "0")}:${date.getMinutes().toString().padStart(2, "0")}`;
14
15
  if (diff < 60 * 60 * 1e3) {
15
16
  const minutes = Math.floor(diff / (60 * 1e3));
16
- return minutes <= 1 ? "\u521A\u521A" : `${minutes} \u5206\u949F\u524D`;
17
+ return minutes <= 1 ? t("commands.undo.justNow") : t("commands.undo.minutesAgo", { count: minutes });
17
18
  }
18
19
  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
+ return `${t("commands.undo.today")} ${timeStr}`;
20
21
  }
21
22
  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")}`;
23
+ const weekdayKeys = [
24
+ "commands.undo.weekday.sun",
25
+ "commands.undo.weekday.mon",
26
+ "commands.undo.weekday.tue",
27
+ "commands.undo.weekday.wed",
28
+ "commands.undo.weekday.thu",
29
+ "commands.undo.weekday.fri",
30
+ "commands.undo.weekday.sat"
31
+ ];
32
+ return `${t(weekdayKeys[date.getDay()])} ${timeStr}`;
24
33
  }
25
- return `${date.getMonth() + 1}/${date.getDate()} ${date.getHours().toString().padStart(2, "0")}:${date.getMinutes().toString().padStart(2, "0")}`;
34
+ return `${date.getMonth() + 1}/${date.getDate()} ${timeStr}`;
26
35
  }
27
36
  function getRelativePath(filePath) {
28
37
  const cwd = getCwd();
@@ -32,205 +41,170 @@ function getRelativePath(filePath) {
32
41
  }
33
42
  return filePath;
34
43
  }
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
44
  const UndoCommand = ({ onClose }) => {
93
- const [view, setView] = useState("file-list");
45
+ const [phase, setPhase] = useState({ type: "file-list" });
94
46
  const [files, setFiles] = useState([]);
95
- const [selectedFileIndex, setSelectedFileIndex] = useState(0);
96
- const [selectedFile, setSelectedFile] = useState(
97
- null
98
- );
99
47
  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);
48
+ const [loading, setLoading] = useState(true);
49
+ const [statusOverlay, setStatusOverlay] = useState(null);
106
50
  useEffect(() => {
107
51
  const loadFiles = async () => {
108
52
  try {
109
53
  const backupFiles = await listBackedUpFiles();
110
54
  setFiles(backupFiles);
111
- } catch (err) {
112
- setError(err instanceof Error ? err.message : String(err));
55
+ } catch {
56
+ setFiles([]);
113
57
  } finally {
114
- setIsLoading(false);
58
+ setLoading(false);
115
59
  }
116
60
  };
117
61
  loadFiles();
118
62
  }, []);
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));
63
+ useEffect(() => {
64
+ if (phase.type === "version-list") {
65
+ const loadVersions = async () => {
66
+ setLoading(true);
67
+ try {
68
+ const fileVersions = await getBackupVersions(phase.file.filePath);
69
+ setVersions(fileVersions);
70
+ } catch {
71
+ setVersions([]);
72
+ } finally {
73
+ setLoading(false);
126
74
  }
75
+ };
76
+ loadVersions();
77
+ }
78
+ }, [phase]);
79
+ const { tabs, items, title, footerHint, emptyText } = useMemo(() => {
80
+ switch (phase.type) {
81
+ case "file-list": {
82
+ const fileTabs = [
83
+ { id: "files", label: t("commands.undo.tabFiles") }
84
+ ];
85
+ const fileItems = files.map((file) => ({
86
+ id: file.filePath,
87
+ label: getRelativePath(file.filePath),
88
+ description: t("commands.undo.versions", {
89
+ count: file.versionCount
90
+ }),
91
+ data: { file }
92
+ }));
93
+ return {
94
+ tabs: fileTabs,
95
+ items: fileItems,
96
+ title: t("commands.undo.title"),
97
+ footerHint: "\u2191\u2193 Navigate \xB7 Enter Select \xB7 Esc Close",
98
+ emptyText: t("commands.undo.noBackups")
99
+ };
127
100
  }
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
- }
101
+ case "version-list": {
102
+ const versionTabs = [
103
+ { id: "versions", label: t("commands.undo.tabVersions") }
104
+ ];
105
+ const versionItems = versions.map((version) => ({
106
+ id: String(version.version),
107
+ label: `v${version.version}: ${version.operation}`,
108
+ description: formatTimestamp(version.timestamp),
109
+ data: { version }
110
+ }));
111
+ return {
112
+ tabs: versionTabs,
113
+ items: versionItems,
114
+ title: getRelativePath(phase.file.filePath),
115
+ footerHint: "\u2191\u2193 Navigate \xB7 Enter Restore \xB7 Esc Back",
116
+ emptyText: "No versions found"
117
+ };
141
118
  }
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
119
  }
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));
120
+ }, [phase, files, versions]);
121
+ const handleStatusDismiss = useCallback(() => {
122
+ setStatusOverlay(null);
123
+ onClose();
124
+ }, [onClose]);
125
+ const handleBack = useCallback(() => {
126
+ if (statusOverlay && statusOverlay.type !== "loading") {
127
+ handleStatusDismiss();
128
+ return;
171
129
  }
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
130
+ if (phase.type === "file-list") {
131
+ onClose();
132
+ } else {
133
+ setPhase({ type: "file-list" });
134
+ }
135
+ }, [phase, statusOverlay, onClose, handleStatusDismiss]);
136
+ const handleClose = handleBack;
137
+ const handleTabChange = useCallback(() => {
138
+ }, []);
139
+ const handleSelect = useCallback(
140
+ async (item) => {
141
+ switch (phase.type) {
142
+ case "file-list": {
143
+ const data = item.data;
144
+ setPhase({ type: "version-list", file: data.file });
145
+ break;
194
146
  }
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
147
+ case "version-list": {
148
+ const data = item.data;
149
+ setStatusOverlay({
150
+ type: "loading",
151
+ message: "Restoring file..."
152
+ });
153
+ try {
154
+ const success = await restoreBackup(
155
+ phase.file.filePath,
156
+ data.version.version
157
+ );
158
+ if (success) {
159
+ setStatusOverlay({
160
+ type: "success",
161
+ message: `${t("commands.undo.fileRestored")}: v${data.version.version}`
162
+ });
163
+ } else {
164
+ setStatusOverlay({
165
+ type: "error",
166
+ message: t("commands.undo.restoreFailed")
167
+ });
168
+ }
169
+ } catch (err) {
170
+ const msg = err instanceof Error ? err.message : String(err);
171
+ setStatusOverlay({ type: "error", message: msg });
172
+ }
173
+ break;
209
174
  }
210
- );
211
- case "success":
212
- if (!selectedFile || !restoredVersion) {
213
- onClose();
214
- return null;
215
175
  }
216
- return /* @__PURE__ */ React.createElement(
217
- SuccessView,
218
- {
219
- file: selectedFile,
220
- version: restoredVersion,
221
- onClose
222
- }
223
- );
224
- default:
225
- return null;
226
- }
176
+ },
177
+ [phase]
178
+ );
179
+ const currentTab = phase.type === "file-list" ? "files" : "versions";
180
+ return /* @__PURE__ */ React.createElement(
181
+ TabbedListView,
182
+ {
183
+ title,
184
+ tabs,
185
+ activeTab: currentTab,
186
+ onTabChange: handleTabChange,
187
+ items,
188
+ searchEnabled: false,
189
+ onSelect: handleSelect,
190
+ onClose: handleClose,
191
+ onBack: handleBack,
192
+ statusOverlay,
193
+ footerHint,
194
+ isLoading: loading,
195
+ loadingText: t("commands.undo.loading"),
196
+ emptyText,
197
+ statusDismissHint: "Enter Close"
198
+ }
199
+ );
227
200
  };
228
201
  const command = {
229
202
  name: "undo",
230
- description: "\u64A4\u9500\u6587\u4EF6\u4FEE\u6539\uFF08\u9700\u8981 --smart \u6A21\u5F0F\uFF09",
203
+ description: t("commands.undo.description"),
231
204
  type: "local-jsx",
232
205
  isEnabled: true,
233
206
  isHidden: false,
207
+ hidePromptInput: true,
234
208
  userFacingName() {
235
209
  return "undo";
236
210
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
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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",
4
+ "sourcesContent": ["/**\n * Undo Command\n *\n * Interactive command to restore file versions from backups.\n * Uses TabbedListView with a phase state machine for consistent UI.\n */\n\nimport React, { useState, useEffect, useCallback, useMemo } from 'react'\nimport type { Command } from '@commands'\nimport { getCwd } from '@utils/state'\nimport {\n listBackedUpFiles,\n getBackupVersions,\n restoreBackup,\n type BackupFileSummary,\n type BackupMetadata,\n} from '../core/backupManager'\nimport { TabbedListView } from '@components/TabbedListView/TabbedListView'\nimport type {\n ListItem,\n TabDefinition,\n StatusOverlay,\n} from '@components/TabbedListView/types'\nimport { t } from '@i18n'\n\n// =============================================================================\n// Helpers\n// =============================================================================\n\nfunction formatTimestamp(timestamp: number): string {\n const date = new Date(timestamp)\n const now = new Date()\n const diff = now.getTime() - timestamp\n const timeStr = `${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`\n\n if (diff < 60 * 60 * 1000) {\n const minutes = Math.floor(diff / (60 * 1000))\n return minutes <= 1\n ? t('commands.undo.justNow')\n : t('commands.undo.minutesAgo', { count: minutes })\n }\n\n if (\n date.getDate() === now.getDate() &&\n date.getMonth() === now.getMonth() &&\n date.getFullYear() === now.getFullYear()\n ) {\n return `${t('commands.undo.today')} ${timeStr}`\n }\n\n if (diff < 7 * 24 * 60 * 60 * 1000) {\n const weekdayKeys = [\n 'commands.undo.weekday.sun',\n 'commands.undo.weekday.mon',\n 'commands.undo.weekday.tue',\n 'commands.undo.weekday.wed',\n 'commands.undo.weekday.thu',\n 'commands.undo.weekday.fri',\n 'commands.undo.weekday.sat',\n ] as const\n return `${t(weekdayKeys[date.getDay()])} ${timeStr}`\n }\n\n return `${date.getMonth() + 1}/${date.getDate()} ${timeStr}`\n}\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// Types\n// =============================================================================\n\ntype UndoPhase =\n | { type: 'file-list' }\n | { type: 'version-list'; file: BackupFileSummary }\n\n// =============================================================================\n// Main Component\n// =============================================================================\n\nconst UndoCommand: React.FC<{ onClose: () => void }> = ({ onClose }) => {\n const [phase, setPhase] = useState<UndoPhase>({ type: 'file-list' })\n const [files, setFiles] = useState<BackupFileSummary[]>([])\n const [versions, setVersions] = useState<BackupMetadata[]>([])\n const [loading, setLoading] = useState(true)\n const [statusOverlay, setStatusOverlay] = useState<StatusOverlay | null>(null)\n\n // Load files on mount\n useEffect(() => {\n const loadFiles = async () => {\n try {\n const backupFiles = await listBackedUpFiles()\n setFiles(backupFiles)\n } catch {\n setFiles([])\n } finally {\n setLoading(false)\n }\n }\n loadFiles()\n }, [])\n\n // Load versions when entering version-list phase\n useEffect(() => {\n if (phase.type === 'version-list') {\n const loadVersions = async () => {\n setLoading(true)\n try {\n const fileVersions = await getBackupVersions(phase.file.filePath)\n setVersions(fileVersions)\n } catch {\n setVersions([])\n } finally {\n setLoading(false)\n }\n }\n loadVersions()\n }\n }, [phase])\n\n // Build tabs, items, title based on phase\n const { tabs, items, title, footerHint, emptyText } = useMemo(() => {\n switch (phase.type) {\n case 'file-list': {\n const fileTabs: TabDefinition[] = [\n { id: 'files', label: t('commands.undo.tabFiles') },\n ]\n\n const fileItems: ListItem[] = files.map(file => ({\n id: file.filePath,\n label: getRelativePath(file.filePath),\n description: t('commands.undo.versions', {\n count: file.versionCount,\n }),\n data: { file },\n }))\n\n return {\n tabs: fileTabs,\n items: fileItems,\n title: t('commands.undo.title'),\n footerHint: '\u2191\u2193 Navigate \u00B7 Enter Select \u00B7 Esc Close',\n emptyText: t('commands.undo.noBackups'),\n }\n }\n\n case 'version-list': {\n const versionTabs: TabDefinition[] = [\n { id: 'versions', label: t('commands.undo.tabVersions') },\n ]\n\n const versionItems: ListItem[] = versions.map(version => ({\n id: String(version.version),\n label: `v${version.version}: ${version.operation}`,\n description: formatTimestamp(version.timestamp),\n data: { version },\n }))\n\n return {\n tabs: versionTabs,\n items: versionItems,\n title: getRelativePath(phase.file.filePath),\n footerHint: '\u2191\u2193 Navigate \u00B7 Enter Restore \u00B7 Esc Back',\n emptyText: 'No versions found',\n }\n }\n }\n }, [phase, files, versions])\n\n // Handle status overlay dismiss\n const handleStatusDismiss = useCallback(() => {\n setStatusOverlay(null)\n onClose()\n }, [onClose])\n\n // Handle back / close\n const handleBack = useCallback(() => {\n if (statusOverlay && statusOverlay.type !== 'loading') {\n handleStatusDismiss()\n return\n }\n if (phase.type === 'file-list') {\n onClose()\n } else {\n setPhase({ type: 'file-list' })\n }\n }, [phase, statusOverlay, onClose, handleStatusDismiss])\n\n const handleClose = handleBack\n\n // Handle tab change (no-op, single tab per phase)\n const handleTabChange = useCallback(() => {}, [])\n\n // Handle item selection\n const handleSelect = useCallback(\n async (item: ListItem) => {\n switch (phase.type) {\n case 'file-list': {\n const data = item.data as { file: BackupFileSummary }\n setPhase({ type: 'version-list', file: data.file })\n break\n }\n\n case 'version-list': {\n const data = item.data as { version: BackupMetadata }\n setStatusOverlay({\n type: 'loading',\n message: 'Restoring file...',\n })\n\n try {\n const success = await restoreBackup(\n phase.file.filePath,\n data.version.version,\n )\n if (success) {\n setStatusOverlay({\n type: 'success',\n message: `${t('commands.undo.fileRestored')}: v${data.version.version}`,\n })\n } else {\n setStatusOverlay({\n type: 'error',\n message: t('commands.undo.restoreFailed'),\n })\n }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n setStatusOverlay({ type: 'error', message: msg })\n }\n break\n }\n }\n },\n [phase],\n )\n\n const currentTab = phase.type === 'file-list' ? 'files' : 'versions'\n\n return (\n <TabbedListView\n title={title}\n tabs={tabs}\n activeTab={currentTab}\n onTabChange={handleTabChange}\n items={items}\n searchEnabled={false}\n onSelect={handleSelect}\n onClose={handleClose}\n onBack={handleBack}\n statusOverlay={statusOverlay}\n footerHint={footerHint}\n isLoading={loading}\n loadingText={t('commands.undo.loading')}\n emptyText={emptyText}\n statusDismissHint=\"Enter Close\"\n />\n )\n}\n\n// =============================================================================\n// Command Export\n// =============================================================================\n\nconst command: Command = {\n name: 'undo',\n description: t('commands.undo.description'),\n type: 'local-jsx' as const,\n isEnabled: true,\n isHidden: false,\n hidePromptInput: true,\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
6
  "names": []
7
7
  }
package/dist/commands.js CHANGED
@@ -16,10 +16,13 @@ import setup from "./commands/setup.js";
16
16
  import status from "./commands/status.js";
17
17
  import terminalSetup from "./commands/terminalSetup.js";
18
18
  import resume from "./commands/resume.js";
19
+ import newCmd from "./commands/new.js";
19
20
  import agents from "./commands/agents/index.js";
20
21
  import plugin from "./commands/plugin.js";
21
22
  import undo from "./commands/undo.js";
23
+ import language from "./commands/language.js";
22
24
  import { quit } from "./commands/quit.js";
25
+ import stats from "./commands/stats.js";
23
26
  import doctor from "./commands/doctor.js";
24
27
  import bug from "./commands/bug.js";
25
28
  import tasks from "./commands/tasks.js";
@@ -43,14 +46,17 @@ const COMMANDS = memoize(() => [
43
46
  exportCmd,
44
47
  help,
45
48
  init,
49
+ language,
46
50
  mcp,
47
51
  model,
52
+ newCmd,
48
53
  permissions,
49
54
  plugin,
50
55
  quit,
51
56
  resume,
52
57
  sandbox,
53
58
  setup,
59
+ stats,
54
60
  status,
55
61
  tasks,
56
62
  todos,