momo-ai 1.0.21 → 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 (94) hide show
  1. package/.claude/skills/r2mo-rad-lain/SKILL.md +63 -374
  2. package/.trae/skills/algorithmic-art/LICENSE.txt +202 -0
  3. package/.trae/skills/algorithmic-art/SKILL.md +405 -0
  4. package/.trae/skills/algorithmic-art/templates/generator_template.js +223 -0
  5. package/.trae/skills/algorithmic-art/templates/viewer.html +599 -0
  6. package/.trae/skills/doc-coauthoring/SKILL.md +375 -0
  7. package/.trae/skills/frontend-design/LICENSE.txt +177 -0
  8. package/.trae/skills/frontend-design/SKILL.md +42 -0
  9. package/.trae/skills/r2mo-rad-lain/SKILL.md +101 -0
  10. package/README.md +9 -32
  11. package/docs/images/r2mo-lain.png +0 -0
  12. package/package.json +11 -11
  13. package/skills/r2mo-rad-domain/SKILL.md +70 -0
  14. package/src/_skill/repositories.json +9 -3
  15. package/src/_template/LAIN/.obsidian/app.json +1 -0
  16. package/src/_template/LAIN/.obsidian/appearance.json +10 -0
  17. package/src/_template/LAIN/.obsidian/community-plugins.json +7 -0
  18. package/src/_template/LAIN/.obsidian/core-plugins.json +33 -0
  19. package/src/_template/LAIN/.obsidian/plugins/dataview/main.js +20876 -0
  20. package/src/_template/LAIN/.obsidian/plugins/dataview/manifest.json +11 -0
  21. package/src/_template/LAIN/.obsidian/plugins/dataview/styles.css +141 -0
  22. package/src/_template/LAIN/.obsidian/plugins/obsidian-excalidraw-plugin/data.json +815 -0
  23. package/src/_template/LAIN/.obsidian/plugins/obsidian-excalidraw-plugin/main.js +10 -0
  24. package/src/_template/LAIN/.obsidian/plugins/obsidian-excalidraw-plugin/manifest.json +12 -0
  25. package/src/_template/LAIN/.obsidian/plugins/obsidian-excalidraw-plugin/styles.css +1 -0
  26. package/src/_template/LAIN/.obsidian/plugins/obsidian-kanban/main.js +153 -0
  27. package/src/_template/LAIN/.obsidian/plugins/obsidian-kanban/manifest.json +11 -0
  28. package/src/_template/LAIN/.obsidian/plugins/obsidian-kanban/styles.css +1 -0
  29. package/src/_template/LAIN/.obsidian/plugins/obsidian-plantuml/main.js +7732 -0
  30. package/src/_template/LAIN/.obsidian/plugins/obsidian-plantuml/manifest.json +10 -0
  31. package/src/_template/LAIN/.obsidian/plugins/obsidian-plantuml/styles.css +38 -0
  32. package/src/_template/LAIN/.obsidian/plugins/obsidian-tasks-plugin/main.js +504 -0
  33. package/src/_template/LAIN/.obsidian/plugins/obsidian-tasks-plugin/manifest.json +12 -0
  34. package/src/_template/LAIN/.obsidian/plugins/obsidian-tasks-plugin/styles.css +1 -0
  35. package/src/_template/LAIN/.obsidian/snippets/body-font.css +27 -0
  36. package/src/_template/LAIN/.obsidian/themes/Primary/manifest.json +9 -0
  37. package/src/_template/LAIN/.obsidian/themes/Primary/theme.css +3878 -0
  38. package/src/_template/LAIN/.obsidian/themes/Retro Windows/manifest.json +7 -0
  39. package/src/_template/LAIN/.obsidian/themes/Retro Windows/theme.css +582 -0
  40. package/src/_template/LAIN/.obsidian/themes/RetroOS 98/manifest.json +9 -0
  41. package/src/_template/LAIN/.obsidian/themes/RetroOS 98/theme.css +2566 -0
  42. package/src/_template/LAIN/.obsidian/types.json +28 -0
  43. package/src/_template/LAIN/.obsidian/workspace.json +184 -0
  44. package/src/_template/LAIN/AGENTS.md +170 -16
  45. package/src/_template/R2MO/domain-enhance.md +10 -0
  46. package/src/commander/app.json +13 -0
  47. package/src/commander/apply.json +13 -0
  48. package/src/commander/ask.json +6 -0
  49. package/src/commander/docs.json +13 -0
  50. package/src/commander/domain.json +19 -0
  51. package/src/commander/init.json +1 -1
  52. package/src/commander/mmr0.json +6 -0
  53. package/src/commander/mmr2.json +6 -0
  54. package/src/executor/executeApp.js +133 -0
  55. package/src/executor/{executeSkills.js → executeApply.js} +166 -302
  56. package/src/executor/executeAsk.js +274 -0
  57. package/src/executor/executeDocs.js +498 -0
  58. package/src/executor/executeDomain.js +293 -0
  59. package/src/executor/executeInit.js +159 -383
  60. package/src/executor/executeMcp.js +74 -1
  61. package/src/executor/executeMmr0.js +488 -0
  62. package/src/executor/executeMmr2.js +880 -0
  63. package/src/executor/index.js +15 -3
  64. package/src/python/r2mo_proto.py +418 -0
  65. package/src/python/r2mo_proto_database.py +369 -0
  66. package/src/python/r2mo_proto_domain.py +458 -0
  67. package/src/utils/momo-menu.js +43 -13
  68. package/.claude/skills/r2mo-rad-lain/PROMPT.md +0 -281
  69. package/.claude/skills/r2mo-rad-lain/README.md +0 -192
  70. package/.claude/skills/r2mo-rad-lain/examples/argument-parsing.js +0 -154
  71. package/.claude/skills/r2mo-rad-lain/examples/file-operations.js +0 -182
  72. package/.claude/skills/r2mo-rad-lain/file-utils-api.md +0 -281
  73. package/.claude/skills/r2mo-rad-lain/menu-api.md +0 -187
  74. package/.claude/skills/r2mo-rad-lain/scripts/file-utils.js +0 -223
  75. package/.claude/skills/r2mo-rad-lain/scripts/menu.js +0 -289
  76. package/.claude/skills/r2mo-rad-lain/scripts/yaml-parser.js +0 -209
  77. package/.claude/skills/r2mo-rad-lain/templates/command.json.template +0 -13
  78. package/.claude/skills/r2mo-rad-lain/templates/executor.js.template +0 -32
  79. package/.claude/skills/r2mo-rad-lain/templates/interactive-menu.js.template +0 -221
  80. package/src/_template/LAIN/.momo/advanced/actor.md +0 -42
  81. package/src/_template/LAIN/.momo/advanced/refer.json +0 -46
  82. package/src/_template/LAIN/.momo/scripts/submodule-clean.sh +0 -56
  83. package/src/_template/LAIN/changes/proposal.md +0 -39
  84. package/src/_template/LAIN/changes/tasks/task-detail.md +0 -45
  85. package/src/_template/LAIN/changes/tasks.md +0 -49
  86. package/src/_template/LAIN/execute/admin-n-f-dashboard.md +0 -53
  87. package/src/_template/LAIN/execute/admin-n-f-form.md +0 -51
  88. package/src/_template/LAIN/execute/admin-n-f-home.md +0 -49
  89. package/src/_template/LAIN/execute/admin-n-f-list.md +0 -52
  90. package/src/_template/LAIN/execute/admin-n-f-login.md +0 -56
  91. package/src/_template/LAIN/specification/project-model.md +0 -13
  92. package/src/_template/LAIN/specification/project.md +0 -73
  93. package/src/_template/LAIN/specification/requirement.md +0 -25
  94. package/src/commander/skills.json +0 -20
@@ -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
+ };