momo-ai 1.0.20 → 1.0.22

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 (162) hide show
  1. package/.claude/skills/algorithmic-art/LICENSE.txt +202 -0
  2. package/.claude/skills/algorithmic-art/SKILL.md +405 -0
  3. package/.claude/skills/algorithmic-art/templates/generator_template.js +223 -0
  4. package/.claude/skills/algorithmic-art/templates/viewer.html +599 -0
  5. package/.claude/skills/r2mo-rad-lain/SKILL.md +101 -0
  6. package/.cursor/mcp.json +17 -0
  7. package/.obsidian/app.json +1 -0
  8. package/.obsidian/appearance.json +4 -0
  9. package/.obsidian/community-plugins.json +4 -0
  10. package/.obsidian/core-plugins.json +33 -0
  11. package/.obsidian/plugins/ai-agent/main.js +98495 -0
  12. package/.obsidian/plugins/ai-agent/manifest.json +11 -0
  13. package/.obsidian/plugins/ai-agent/styles.css +806 -0
  14. package/.obsidian/plugins/dataview/main.js +20876 -0
  15. package/.obsidian/plugins/dataview/manifest.json +11 -0
  16. package/.obsidian/plugins/dataview/styles.css +141 -0
  17. package/.obsidian/plugins/obsidian-excalidraw-plugin/main.js +10 -0
  18. package/.obsidian/plugins/obsidian-excalidraw-plugin/manifest.json +12 -0
  19. package/.obsidian/plugins/obsidian-excalidraw-plugin/styles.css +1 -0
  20. package/.obsidian/plugins/templater-obsidian/main.js +45 -0
  21. package/.obsidian/plugins/templater-obsidian/manifest.json +11 -0
  22. package/.obsidian/plugins/templater-obsidian/styles.css +226 -0
  23. package/.obsidian/plugins/terminal/main.js +200 -0
  24. package/.obsidian/plugins/terminal/manifest.json +14 -0
  25. package/.obsidian/plugins/terminal/styles.css +32 -0
  26. package/.obsidian/themes/AnuPpuccin/manifest.json +7 -0
  27. package/.obsidian/themes/AnuPpuccin/theme.css +9080 -0
  28. package/.obsidian/themes/Things/manifest.json +7 -0
  29. package/.obsidian/themes/Things/theme.css +1628 -0
  30. package/.obsidian/workspace.json +196 -0
  31. package/.trae/skills/algorithmic-art/LICENSE.txt +202 -0
  32. package/.trae/skills/algorithmic-art/SKILL.md +405 -0
  33. package/.trae/skills/algorithmic-art/templates/generator_template.js +223 -0
  34. package/.trae/skills/algorithmic-art/templates/viewer.html +599 -0
  35. package/.trae/skills/doc-coauthoring/SKILL.md +375 -0
  36. package/.trae/skills/frontend-design/LICENSE.txt +177 -0
  37. package/.trae/skills/frontend-design/SKILL.md +42 -0
  38. package/.trae/skills/r2mo-rad-lain/SKILL.md +101 -0
  39. package/README.md +12 -148
  40. package/docs/images/logo.jpeg +0 -0
  41. package/docs/images/r2mo-lain.png +0 -0
  42. package/install.sh +1 -0
  43. package/package.json +15 -11
  44. package/skills/r2mo-rad-domain/SKILL.md +70 -0
  45. package/skills/r2mo-rad-lain/SKILL.md +101 -0
  46. package/src/_mcp/skills-server.mjs +70 -0
  47. package/src/_skill/repositories.json +22 -0
  48. package/src/_template/LAIN/.obsidian/app.json +1 -0
  49. package/src/_template/LAIN/.obsidian/appearance.json +10 -0
  50. package/src/_template/LAIN/.obsidian/community-plugins.json +7 -0
  51. package/src/_template/LAIN/.obsidian/core-plugins.json +33 -0
  52. package/src/_template/LAIN/.obsidian/plugins/dataview/main.js +20876 -0
  53. package/src/_template/LAIN/.obsidian/plugins/dataview/manifest.json +11 -0
  54. package/src/_template/LAIN/.obsidian/plugins/dataview/styles.css +141 -0
  55. package/src/_template/LAIN/.obsidian/plugins/obsidian-excalidraw-plugin/data.json +815 -0
  56. package/src/_template/LAIN/.obsidian/plugins/obsidian-excalidraw-plugin/main.js +10 -0
  57. package/src/_template/LAIN/.obsidian/plugins/obsidian-excalidraw-plugin/manifest.json +12 -0
  58. package/src/_template/LAIN/.obsidian/plugins/obsidian-excalidraw-plugin/styles.css +1 -0
  59. package/src/_template/LAIN/.obsidian/plugins/obsidian-kanban/main.js +153 -0
  60. package/src/_template/LAIN/.obsidian/plugins/obsidian-kanban/manifest.json +11 -0
  61. package/src/_template/LAIN/.obsidian/plugins/obsidian-kanban/styles.css +1 -0
  62. package/src/_template/LAIN/.obsidian/plugins/obsidian-plantuml/main.js +7732 -0
  63. package/src/_template/LAIN/.obsidian/plugins/obsidian-plantuml/manifest.json +10 -0
  64. package/src/_template/LAIN/.obsidian/plugins/obsidian-plantuml/styles.css +38 -0
  65. package/src/_template/LAIN/.obsidian/plugins/obsidian-tasks-plugin/main.js +504 -0
  66. package/src/_template/LAIN/.obsidian/plugins/obsidian-tasks-plugin/manifest.json +12 -0
  67. package/src/_template/LAIN/.obsidian/plugins/obsidian-tasks-plugin/styles.css +1 -0
  68. package/src/_template/LAIN/.obsidian/snippets/body-font.css +27 -0
  69. package/src/_template/LAIN/.obsidian/themes/Primary/manifest.json +9 -0
  70. package/src/_template/LAIN/.obsidian/themes/Primary/theme.css +3878 -0
  71. package/src/_template/LAIN/.obsidian/themes/Retro Windows/manifest.json +7 -0
  72. package/src/_template/LAIN/.obsidian/themes/Retro Windows/theme.css +582 -0
  73. package/src/_template/LAIN/.obsidian/themes/RetroOS 98/manifest.json +9 -0
  74. package/src/_template/LAIN/.obsidian/themes/RetroOS 98/theme.css +2566 -0
  75. package/src/_template/LAIN/.obsidian/types.json +28 -0
  76. package/src/_template/LAIN/.obsidian/workspace.json +184 -0
  77. package/src/_template/LAIN/AGENTS.md +170 -16
  78. package/src/_template/R2MO/domain-enhance.md +10 -0
  79. package/src/commander/app.json +13 -0
  80. package/src/commander/apply.json +13 -0
  81. package/src/commander/ask.json +6 -0
  82. package/src/commander/docs.json +13 -0
  83. package/src/commander/domain.json +19 -0
  84. package/src/commander/help.json +5 -0
  85. package/src/commander/init.json +1 -1
  86. package/src/commander/mcp.json +13 -0
  87. package/src/commander/mmr0.json +6 -0
  88. package/src/commander/mmr2.json +6 -0
  89. package/src/commander/open.json +8 -2
  90. package/src/executor/executeApp.js +133 -0
  91. package/src/executor/executeApply.js +611 -0
  92. package/src/executor/executeAsk.js +274 -0
  93. package/src/executor/executeDocs.js +498 -0
  94. package/src/executor/executeDomain.js +293 -0
  95. package/src/executor/executeEnv.js +48 -38
  96. package/src/executor/executeHelp.js +77 -16
  97. package/src/executor/executeInit.js +176 -346
  98. package/src/executor/executeMcp.js +363 -0
  99. package/src/executor/executeMmr0.js +488 -0
  100. package/src/executor/executeMmr2.js +880 -0
  101. package/src/executor/executeOpen.js +144 -125
  102. package/src/executor/index.js +17 -39
  103. package/src/momo.js +2 -1
  104. package/src/python/r2mo_proto.py +418 -0
  105. package/src/python/r2mo_proto_database.py +369 -0
  106. package/src/python/r2mo_proto_domain.py +458 -0
  107. package/src/utils/momo-args.js +39 -0
  108. package/src/utils/momo-file-utils.js +75 -0
  109. package/src/utils/momo-menu.js +84 -0
  110. package/src/_template/LAIN/.momo/advanced/actor.md +0 -42
  111. package/src/_template/LAIN/.momo/advanced/refer.json +0 -46
  112. package/src/_template/LAIN/.momo/scripts/submodule-clean.sh +0 -56
  113. package/src/_template/LAIN/changes/proposal.md +0 -39
  114. package/src/_template/LAIN/changes/tasks/task-detail.md +0 -45
  115. package/src/_template/LAIN/changes/tasks.md +0 -49
  116. package/src/_template/LAIN/execute/admin-n-f-dashboard.md +0 -53
  117. package/src/_template/LAIN/execute/admin-n-f-form.md +0 -51
  118. package/src/_template/LAIN/execute/admin-n-f-home.md +0 -49
  119. package/src/_template/LAIN/execute/admin-n-f-list.md +0 -52
  120. package/src/_template/LAIN/execute/admin-n-f-login.md +0 -56
  121. package/src/_template/LAIN/specification/project-model.md +0 -13
  122. package/src/_template/LAIN/specification/project.md +0 -73
  123. package/src/_template/LAIN/specification/requirement.md +0 -25
  124. package/src/commander/actor.json +0 -12
  125. package/src/commander/actors.json +0 -6
  126. package/src/commander/add.json +0 -12
  127. package/src/commander/agent.json +0 -12
  128. package/src/commander/agentcfg.json +0 -5
  129. package/src/commander/archive.json +0 -12
  130. package/src/commander/commit.json +0 -12
  131. package/src/commander/console.json +0 -7
  132. package/src/commander/lain.json +0 -7
  133. package/src/commander/list.json +0 -7
  134. package/src/commander/plan.json +0 -12
  135. package/src/commander/project.json +0 -12
  136. package/src/commander/pull.json +0 -6
  137. package/src/commander/push.json +0 -6
  138. package/src/commander/repo.json +0 -18
  139. package/src/commander/run.json +0 -18
  140. package/src/commander/show.json +0 -12
  141. package/src/commander/tasks.json +0 -18
  142. package/src/commander/unlock.json +0 -6
  143. package/src/commander/validate.json +0 -12
  144. package/src/executor/executeActor.js +0 -133
  145. package/src/executor/executeActors.js +0 -58
  146. package/src/executor/executeAdd.js +0 -307
  147. package/src/executor/executeAgent.js +0 -299
  148. package/src/executor/executeAgentCfg.js +0 -210
  149. package/src/executor/executeArchive.js +0 -124
  150. package/src/executor/executeCommit.js +0 -202
  151. package/src/executor/executeConsole.js +0 -142
  152. package/src/executor/executeList.js +0 -133
  153. package/src/executor/executePlan.js +0 -164
  154. package/src/executor/executeProject.js +0 -313
  155. package/src/executor/executePull.js +0 -127
  156. package/src/executor/executePush.js +0 -243
  157. package/src/executor/executeRepo.js +0 -238
  158. package/src/executor/executeRun.js +0 -644
  159. package/src/executor/executeShow.js +0 -164
  160. package/src/executor/executeTasks.js +0 -384
  161. package/src/executor/executeUnlock.js +0 -110
  162. package/src/executor/executeValidate.js +0 -210
@@ -0,0 +1,293 @@
1
+ const { spawn } = require('child_process');
2
+ const fs = require('fs');
3
+ const path = require('path');
4
+ const Ec = require('../epic');
5
+ const { parseOptional } = require('../utils/momo-args');
6
+
7
+ // 脚本路径(相对于项目根目录)
8
+ const SCRIPT_PATH_DOMAIN = 'src/python/r2mo_proto_domain.py';
9
+ const SCRIPT_PATH_DATABASE = 'src/python/r2mo_proto_database.py';
10
+
11
+ /**
12
+ * 检查命令是否可用
13
+ * @param {string} command 命令名称
14
+ * @returns {Promise<boolean>}
15
+ */
16
+ const _isCommandAvailable = async (command) => {
17
+ return new Promise((resolve) => {
18
+ const whereCmd = process.platform === 'win32' ? 'where' : 'which';
19
+ const childProcess = spawn(whereCmd, [command], { stdio: 'pipe' });
20
+ childProcess.on('close', (code) => {
21
+ resolve(code === 0);
22
+ });
23
+ childProcess.on('error', () => {
24
+ resolve(false);
25
+ });
26
+ });
27
+ };
28
+
29
+ /**
30
+ * 解析 pom.xml 提取 artifactId(排除 parent 节点)
31
+ * @param {string} pomPath pom.xml 文件路径
32
+ * @returns {string|null} artifactId,如果解析失败返回 null
33
+ */
34
+ const _parsePomXml = (pomPath) => {
35
+ try {
36
+ const content = fs.readFileSync(pomPath, 'utf8');
37
+
38
+ // 移除 <parent>...</parent> 节点,避免提取 parent 的 artifactId
39
+ const withoutParent = content.replace(/<parent>[\s\S]*?<\/parent>/gi, '');
40
+
41
+ // 在剩余内容中查找 artifactId
42
+ const match = withoutParent.match(/<artifactId>([^<]+)<\/artifactId>/);
43
+ if (match && match[1]) {
44
+ return match[1].trim();
45
+ }
46
+ return null;
47
+ } catch (error) {
48
+ return null;
49
+ }
50
+ };
51
+
52
+ /**
53
+ * 验证 Maven 项目结构
54
+ * @param {string} targetDir 目标目录
55
+ * @returns {Object} { isValid: boolean, artifactId: string|null, missing: string[] }
56
+ */
57
+ const _validateMavenProject = (targetDir) => {
58
+ const pomPath = path.join(targetDir, 'pom.xml');
59
+
60
+ // 1. 检查 pom.xml 是否存在
61
+ if (!fs.existsSync(pomPath)) {
62
+ return {
63
+ isValid: false,
64
+ artifactId: null,
65
+ missing: ['pom.xml'],
66
+ error: '目录中未找到 pom.xml 文件'
67
+ };
68
+ }
69
+
70
+ // 2. 解析 pom.xml 提取 artifactId
71
+ const artifactId = _parsePomXml(pomPath);
72
+ if (!artifactId) {
73
+ return {
74
+ isValid: false,
75
+ artifactId: null,
76
+ missing: ['artifactId'],
77
+ error: '无法从 pom.xml 中提取 artifactId'
78
+ };
79
+ }
80
+
81
+ // 3. 检查 -domain 模块是否存在
82
+ const missing = [];
83
+ const domainPath = path.join(targetDir, `${artifactId}-domain`);
84
+
85
+ // 检查同级目录
86
+ if (!fs.existsSync(domainPath)) {
87
+ missing.push(`${artifactId}-domain`);
88
+ }
89
+
90
+ return {
91
+ isValid: missing.length === 0,
92
+ artifactId: artifactId,
93
+ missing: missing,
94
+ error: missing.length > 0 ? `缺少必需的模块: ${missing.join(', ')}` : null
95
+ };
96
+ };
97
+
98
+ /**
99
+ * 检查目录中是否存在 Flyway 目录(仅考虑 src/main/resources 下)
100
+ * @param {string} targetDir 目标目录
101
+ * @returns {boolean}
102
+ */
103
+ const _checkFlywayDirectory = (targetDir) => {
104
+ try {
105
+ const resourcesDir = path.join(targetDir, 'src', 'main', 'resources');
106
+ if (!fs.existsSync(resourcesDir) || !fs.statSync(resourcesDir).isDirectory()) {
107
+ return false;
108
+ }
109
+ const checkDir = (dir, depth = 0) => {
110
+ if (depth > 8) return false;
111
+ const items = fs.readdirSync(dir);
112
+ for (const item of items) {
113
+ const fullPath = path.join(dir, item);
114
+ try {
115
+ const stat = fs.statSync(fullPath);
116
+ if (stat.isDirectory()) {
117
+ const lowerPath = fullPath.toLowerCase();
118
+ if (lowerPath.includes('flyway') && lowerPath.includes('mysql')) {
119
+ return true;
120
+ }
121
+ if (checkDir(fullPath, depth + 1)) return true;
122
+ }
123
+ } catch (e) {}
124
+ }
125
+ return false;
126
+ };
127
+ return checkDir(resourcesDir);
128
+ } catch (error) {
129
+ return false;
130
+ }
131
+ };
132
+
133
+ /**
134
+ * 执行 Python 脚本
135
+ * @param {string} targetDir 目标目录(工作目录)
136
+ * @param {string} scriptPath 脚本路径(绝对路径)
137
+ * @param {string[]} [args] 传给脚本的参数,如 ['-i', '.', '-o', '/path/to/out']
138
+ */
139
+ const _executePythonScript = async (targetDir, scriptPath, args = []) => {
140
+ return new Promise((resolve, reject) => {
141
+ Ec.waiting(`🚀 正在执行脚本: ${path.basename(scriptPath).cyan}...`);
142
+ Ec.waiting(`📁 工作目录: ${targetDir.cyan}`);
143
+
144
+ const child = spawn('python3', [scriptPath, ...args], {
145
+ cwd: targetDir,
146
+ stdio: 'inherit',
147
+ shell: false
148
+ });
149
+
150
+ child.on('close', (code) => {
151
+ if (code === 0) {
152
+ Ec.info(`✅ 脚本执行成功`);
153
+ resolve();
154
+ } else {
155
+ reject(new Error(`脚本执行失败,退出码: ${code}`));
156
+ }
157
+ });
158
+
159
+ child.on('error', (error) => {
160
+ reject(new Error(`执行脚本失败: ${error.message}`));
161
+ });
162
+ });
163
+ };
164
+
165
+ module.exports = async (options) => {
166
+ try {
167
+ // 1. 解析参数
168
+ const dirArg = parseOptional('dir', 'd');
169
+ const entityArg = parseOptional('entity', 'e');
170
+
171
+ const targetDir = dirArg.hasFlag && dirArg.value
172
+ ? path.resolve(dirArg.value)
173
+ : process.cwd();
174
+
175
+ // 默认从 Entity 生成(-e true 或不传参数)
176
+ const fromEntity = !entityArg.hasFlag || entityArg.value === 'true' || entityArg.value === true;
177
+
178
+ const mode = fromEntity ? 'Entity (Java Domain)' : 'Database (Flyway SQL)';
179
+ const scriptPath = fromEntity ? SCRIPT_PATH_DOMAIN : SCRIPT_PATH_DATABASE;
180
+
181
+ Ec.info(`📋 生成模式: ${mode.cyan}`);
182
+
183
+ // 2. 验证目录是否存在
184
+ if (!fs.existsSync(targetDir)) {
185
+ Ec.error(`❌ 目录不存在: ${targetDir}`);
186
+ process.exit(1);
187
+ }
188
+
189
+ if (!fs.statSync(targetDir).isDirectory()) {
190
+ Ec.error(`❌ 路径不是目录: ${targetDir}`);
191
+ process.exit(1);
192
+ }
193
+
194
+ // 3. 如果是 Entity 模式,验证 Maven 项目结构
195
+ if (fromEntity) {
196
+ Ec.waiting('正在验证 Maven 项目结构...');
197
+ const validation = _validateMavenProject(targetDir);
198
+
199
+ if (!validation.isValid) {
200
+ if (!validation.artifactId) {
201
+ Ec.error(`❌ ${validation.error}`);
202
+ if (validation.missing.includes('pom.xml')) {
203
+ Ec.waiting('请确保指定目录是包含 pom.xml 的 Maven 项目根目录');
204
+ } else {
205
+ Ec.waiting('请检查 pom.xml 文件格式是否正确');
206
+ }
207
+ console.log('');
208
+ process.exit(1);
209
+ } else {
210
+ Ec.error(`❌ ${validation.error}`);
211
+ console.log('');
212
+ Ec.waiting(`项目 ID: ${validation.artifactId.cyan}`);
213
+ Ec.waiting(`缺少的模块:`);
214
+ validation.missing.forEach(module => {
215
+ Ec.waiting(` - ${module.red}`);
216
+ });
217
+ console.log('');
218
+ Ec.waiting('请确保以下模块存在于项目根目录:');
219
+ Ec.waiting(` - ${validation.artifactId}-domain`.cyan);
220
+ console.log('');
221
+ process.exit(1);
222
+ }
223
+ }
224
+
225
+ Ec.info(`✓ Maven 项目验证通过`);
226
+ Ec.info(` 项目 ID: ${validation.artifactId.cyan}`);
227
+ Ec.info(` 找到模块: ${validation.artifactId}-domain`.green);
228
+ } else {
229
+ // Database 模式:检查是否有 flyway 目录
230
+ Ec.waiting('正在检查 Flyway SQL 文件...');
231
+ const hasFlywayDir = _checkFlywayDirectory(targetDir);
232
+ if (!hasFlywayDir) {
233
+ Ec.warn(`⚠ 未在目录中找到 flyway/MYSQL 目录`);
234
+ Ec.waiting('将尝试扫描所有 SQL 文件...');
235
+ } else {
236
+ Ec.info('✓ 找到 Flyway 目录');
237
+ }
238
+ }
239
+
240
+ // 4. 检查 python3 是否安装
241
+ Ec.waiting('正在检查 python3 命令...');
242
+ const python3Available = await _isCommandAvailable('python3');
243
+
244
+ if (!python3Available) {
245
+ Ec.error('❌ 未找到 python3 命令');
246
+ console.log('');
247
+ Ec.error('请先安装 Python 3:');
248
+ if (process.platform === 'darwin') {
249
+ console.log(' brew install python3'.cyan);
250
+ } else if (process.platform === 'win32') {
251
+ console.log(' 从 https://www.python.org/downloads/ 下载安装'.cyan);
252
+ } else {
253
+ console.log(' sudo apt-get install python3'.cyan);
254
+ }
255
+ console.log('');
256
+ process.exit(1);
257
+ }
258
+
259
+ Ec.info('✓ python3 已安装');
260
+
261
+ // 5. 检查脚本文件是否存在
262
+ const projectRoot = path.resolve(__dirname, '../..');
263
+ const fullScriptPath = path.join(projectRoot, scriptPath);
264
+
265
+ if (!fs.existsSync(fullScriptPath)) {
266
+ Ec.error(`❌ 脚本文件不存在: ${fullScriptPath}`);
267
+ Ec.waiting(`请确保 ${scriptPath} 文件存在`);
268
+ process.exit(1);
269
+ }
270
+
271
+ Ec.info(`✓ 找到脚本: ${scriptPath}`);
272
+
273
+ // 6. 执行 Python 脚本(Database 模式需指定输出到 -ui/.r2mo/domain,与 Domain 模式一致)
274
+ console.log('');
275
+ let scriptArgs = [];
276
+ if (!fromEntity) {
277
+ const rootDir = targetDir.endsWith('-domain') ? path.join(targetDir, '..') : targetDir;
278
+ const artifactId = _parsePomXml(path.join(rootDir, 'pom.xml'));
279
+ const outputDir = artifactId
280
+ ? path.join(rootDir, `${artifactId}-ui`, '.r2mo', 'domain')
281
+ : path.join(targetDir, 'proto');
282
+ scriptArgs = ['-i', targetDir, '-o', outputDir];
283
+ Ec.info(` 输出目录: ${outputDir.cyan}`);
284
+ }
285
+ await _executePythonScript(targetDir, fullScriptPath, scriptArgs);
286
+
287
+ process.exit(0);
288
+
289
+ } catch (error) {
290
+ Ec.error(`❌ 执行失败: ${error.message}`);
291
+ process.exit(1);
292
+ }
293
+ };
@@ -80,67 +80,77 @@ module.exports = async () => {
80
80
 
81
81
  Ec.waiting('------------------------------------------------------------');
82
82
 
83
+ // 检查操作系统信息
84
+ try {
85
+ const os = require('os');
86
+ const osType = os.type();
87
+ const displayOs = osType === 'Darwin' ? 'macOS' : osType;
88
+ Ec.waiting(`🖥️ OS 版本 : ${displayOs} ${os.release()} ${os.arch()}`);
89
+ } catch (error) {
90
+ Ec.waiting('⚠️ 无法获取 OS 系统信息');
91
+ }
92
+
93
+ // 检查 JDK 版本
94
+ try {
95
+ // java -version 输出通常在 stderr
96
+ const { stderr } = await execAsync('java -version');
97
+ const versionLine = stderr.split('\n')[0]; // 取第一行
98
+ // 尝试提取引号中的版本号
99
+ const versionMatch = versionLine.match(/"([^"]+)"/);
100
+ const version = versionMatch ? versionMatch[1] : versionLine;
101
+ Ec.waiting(`♨️ JDK 版本 : ${version}`);
102
+ } catch (error) {
103
+ Ec.waiting('⚠️ JDK 未安装或无法获取版本信息');
104
+ }
105
+
83
106
  // 检查额外的环境信息
84
107
  try {
85
108
  const {stdout: nodeVersion} = await execAsync('node --version');
86
- Ec.waiting(`💻 Node.js 版本: ${nodeVersion.trim()}`);
109
+ Ec.waiting(`💻 Node.js 版本 : ${nodeVersion.trim()}`);
87
110
  } catch (error) {
88
111
  Ec.waiting('⚠️ 无法获取 Node.js 版本信息');
89
112
  }
90
113
 
91
114
  try {
92
115
  const {stdout: npmVersion} = await execAsync('npm --version');
93
- Ec.waiting(`📦 NPM 版本: ${npmVersion.trim()}`);
116
+ Ec.waiting(`📦 NPM 版本 : ${npmVersion.trim()}`);
94
117
  } catch (error) {
95
118
  Ec.waiting('⚠️ 无法获取 NPM 版本信息');
96
119
  }
97
120
 
98
121
  try {
99
122
  const {stdout: gitVersion} = await execAsync('git --version');
100
- Ec.waiting(`🌱 Git 版本: ${gitVersion.trim()}`);
123
+ Ec.waiting(`🌱 Git 版本 : ${gitVersion.trim()}`);
101
124
  } catch (error) {
102
125
  Ec.waiting('⚠️ 无法获取 Git 版本信息');
103
126
  }
104
127
 
105
- // 检查 trae 版本(可选命令)
106
- try {
107
- const {stdout: traeVersion} = await execAsync('trae --version');
108
- const traeItems = (traeVersion.split("\n"));
109
- Ec.waiting(`----> 🎯 Trae 版本: ${traeItems[0].trim()}`);
110
- } catch (error) {
111
- Ec.waiting('⚠️ Trae 未安装或无法获取版本信息(可选工具)');
112
- }
113
-
114
- // 检查 lingma 版本(可选命令)
115
- try {
116
- const {stdout: lingmaVersion} = await execAsync('lingma --version');
117
- const lingmaItems = (lingmaVersion.split("\n"));
118
- Ec.waiting(`----> 🧠 Lingma 版本: ${lingmaItems[0].trim()}`);
119
- } catch (error) {
120
- Ec.waiting('⚠️ Lingma 未安装或无法获取版本信息(可选工具)');
121
- }
122
-
123
- // 检查 cursor 版本(可选命令)
124
- try {
125
- const {stdout: cursorVersion} = await execAsync('cursor --version');
126
- const cursorItems = (cursorVersion.split("\n"));
127
- Ec.waiting(`----> 🖱️ Cursor 版本: ${cursorItems[0].trim()}`);
128
- } catch (error) {
129
- Ec.waiting('⚠️ Cursor 未安装或无法获取版本信息(可选工具)');
130
- }
131
-
132
- // 检查 kiro 版本(可选命令)
133
- try {
134
- const {stdout: kiroVersion} = await execAsync('kiro --version');
135
- const kiroItems = (kiroVersion.split("\n"));
136
- Ec.waiting(`----> ⚡ Kiro 版本: ${kiroItems[0].trim()}`);
137
- } catch (error) {
138
- Ec.waiting('⚠️ Kiro 未安装或无法获取版本信息(可选工具)');
128
+ // 定义可选工具列表
129
+ const optionalTools = [
130
+ { cmd: 'trae', label: 'Trae 版本 ', emoji: '🎯' },
131
+ { cmd: 'lingma', label: 'Lingma 版本 ', emoji: '🧠' },
132
+ { cmd: 'cursor', label: 'Cursor 版本 ', emoji: '👾' },
133
+ { cmd: 'kiro', label: 'Kiro 版本 ', emoji: '🔮' },
134
+ { cmd: 'claude', label: 'Claude 版本 ', emoji: '🤖' },
135
+ { cmd: 'gemini', label: 'Gemini 版本 ', emoji: '🌟' },
136
+ { cmd: 'codex', label: 'Codex 版本 ', emoji: '💬' }
137
+ ];
138
+
139
+ for (const tool of optionalTools) {
140
+ try {
141
+ const {stdout} = await execAsync(`${tool.cmd} --version`);
142
+ const versionLines = stdout.split("\n");
143
+ const currentVersion = versionLines[0].trim();
144
+ Ec.waiting(`----> ${tool.emoji} ${tool.label}: ${currentVersion.cyan}`);
145
+ } catch (error) {
146
+ const name = tool.label.trim().replace(' 版本', '');
147
+ Ec.waiting(`⚠️ ${name} 未安装或无法获取版本信息(可选工具)`);
148
+ }
139
149
  }
140
150
 
141
151
  // 显示 Momo 版本
142
152
  const momoVersion = _getVersion();
143
- Ec.waiting(`🤖 Momo 版本: ${momoVersion}`);
153
+ Ec.waiting(`🤖 Momo 版本: ${momoVersion.red}`);
144
154
 
145
155
  // 总结(只检查必需命令)
146
156
  if (allCommandsAvailable) {
@@ -1,27 +1,88 @@
1
1
  const Ec = require('../epic');
2
- const os = require('os');
2
+
3
3
  module.exports = (options) => {
4
+ const parsed = Ec.parseArgument(options);
4
5
  const metadata = Ec.parseMetadata();
5
- metadata.forEach(runner => {
6
- Ec.waiting(`命令:` + `momo ${runner.command} [-options]`.green);
7
- // 检查描述中是否包含"CV",如果包含则在(CV)和说明之间添加红色高亮emoji
6
+
7
+ // 优先读取 options 中的 command,如果没有则尝试读取位置参数
8
+ const commandName = parsed.command ? parsed.command : (process.argv[3] && !process.argv[3].startsWith('-') ? process.argv[3] : null);
9
+
10
+ if (commandName) {
11
+ // ---------------------------------------------------------
12
+ // 单命令详细模式
13
+ // ---------------------------------------------------------
14
+ const runner = metadata.find(runner => runner.command === commandName);
15
+ if (!runner) {
16
+ Ec.error(`未找到命令 [ ${commandName} ] 的定义信息!`);
17
+ process.exit(1);
18
+ }
19
+
20
+ // 处理描述文字
8
21
  let description = runner.description;
9
22
  if (description.includes("(CV)")) {
10
23
  description = description.replace("(CV)", "(CV)📋️ ");
11
24
  }
12
- Ec.waiting(`说明`.yellow + `:${description}`);
13
- const options = runner.options || [];
14
- options.forEach(option => {
15
- if (option.hasOwnProperty('default')) {
16
- const str = option.default + '';
17
- Ec.waiting(`\t-${option.alias},--${option.name}`.red + `\t${option.description}, 默认值:\uD83C\uDF37 ` + str.blue);
18
- } else {
19
- Ec.waiting(`\t-${option.alias},--${option.name}`.red + `\t${option.description}`);
25
+
26
+ console.log(``);
27
+ console.log(`${description}`);
28
+ console.log(``);
29
+
30
+ console.log(`Usage:`);
31
+ console.log(`momo ${runner.command} [options]`);
32
+ console.log(``);
33
+
34
+ const opts = runner.options || [];
35
+ if (opts.length > 0) {
36
+ console.log(`Options:`);
37
+ opts.forEach(option => {
38
+ const flags = `[-${option.alias}|--${option.name}]`;
39
+ let desc = option.description;
40
+ if (option.hasOwnProperty('default')) {
41
+ desc += ` (默认: ${option.default})`.blue;
42
+ }
43
+
44
+ // 对齐设置
45
+ const minPadding = 25;
46
+ let paddingSpace = minPadding - flags.length;
47
+ if (paddingSpace < 2) paddingSpace = 2;
48
+
49
+ console.log(`${flags.yellow}${' '.repeat(paddingSpace)}${desc}`);
50
+ });
51
+ console.log(``);
52
+ }
53
+
54
+ } else {
55
+ // ---------------------------------------------------------
56
+ // 所有命令列表模式
57
+ // ---------------------------------------------------------
58
+ console.log(``);
59
+ console.log(`Usage:`);
60
+ console.log(`momo <command>`);
61
+ console.log(``);
62
+ console.log(`All commands:`);
63
+ console.log(``);
64
+
65
+ // 计算最大长度以对齐
66
+ let maxCmdLen = 0;
67
+ metadata.forEach(r => {
68
+ if (r.command.length > maxCmdLen) maxCmdLen = r.command.length;
69
+ });
70
+ const alignLen = maxCmdLen + 6;
71
+
72
+ metadata.forEach(runner => {
73
+ let description = runner.description;
74
+ if (description.includes("(CV)")) {
75
+ description = description.replace("(CV)", "📋️");
20
76
  }
21
- })
22
- Ec.waiting();
23
- });
24
- Ec.info("命令执行完成!");
77
+
78
+ const padding = ' '.repeat(alignLen - runner.command.length);
79
+ console.log(` ${runner.command.green}${padding}${description}`);
80
+ });
81
+
82
+ console.log(``);
83
+ console.log(`Run "momo help -c <command>" for more info`);
84
+ console.log(``);
85
+ }
25
86
 
26
87
  // 退出程序
27
88
  process.exit(0);