momo-ai 1.0.18 → 1.0.20
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.
- package/package.json +1 -1
- package/src/_agent/trae/momo-datamodel.json +2 -1
- package/src/_agent/trae/momo-module-req.json +2 -1
- package/src/_agent/trae/momo-system-req.json +2 -1
- package/src/_agent/trae/momo-task.json +2 -1
- package/src/_agent/trae/momo-taskplan.json +2 -1
- package/src/_template/LAIN/.momo/advanced/refer.json +0 -4
- package/src/_template/PROMPT/trae/momo-module-req.ejs +1 -1
- package/src/_template/PROMPT/trae/momo-task.ejs +1 -0
- package/src/executor/executeAgent.js +78 -3
- package/src/executor/executeAgentCfg.js +32 -17
- package/src/executor/executeList.js +32 -10
- package/src/executor/executeProject.js +6 -5
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
详细解读 specification/requirement.md 需求文档中的模块和每个模块的功能列表,在 specification/changes/ 目录之下创建模块的核心文档,每个模块用 MXX- 前缀,其中 XX 是模块编号。
|
|
5
5
|
|
|
6
6
|
1. 每个模块中包括 tasks/ 目录、任务明细文档存放位置。
|
|
7
|
-
2. 每个模块中包括 proposal.md
|
|
7
|
+
2. 每个模块中包括 proposal.md,此文档中用来存放模块的详细需求,记得头部使用带有需求编号的注释:`<!-- CODE: XXX -->`。
|
|
8
8
|
3. 每个模块中包括 tasks.md,此文档中是描述所有任务的总清单。
|
|
9
9
|
4. 模块所需的数据模型可参考 specification/project-model.md 文档。
|
|
10
10
|
5. 有多少模块在于你的模块的整体设计,记得模块内部业务要形成完整闭环。
|
|
@@ -45,6 +45,7 @@ const _getAgents = () => {
|
|
|
45
45
|
id: agentInfo.id,
|
|
46
46
|
name: agentInfo.name,
|
|
47
47
|
uri: agentInfo.uri,
|
|
48
|
+
uriCn: agentInfo['uri-cn'], // 添加CN链接
|
|
48
49
|
filePath: filePath
|
|
49
50
|
});
|
|
50
51
|
} catch (error) {
|
|
@@ -137,9 +138,45 @@ module.exports = async (options) => {
|
|
|
137
138
|
if (!agentName) {
|
|
138
139
|
while (true) {
|
|
139
140
|
Ec.waiting('可用的 Agents:');
|
|
141
|
+
|
|
142
|
+
// 计算列宽以适应内容
|
|
143
|
+
const typeColumnWidth = 12;
|
|
144
|
+
const idColumnWidth = 20;
|
|
145
|
+
const uriColumnWidth = 35;
|
|
146
|
+
const uriCnColumnWidth = 35;
|
|
147
|
+
const nameColumnWidth = 35;
|
|
148
|
+
|
|
149
|
+
// 表头
|
|
150
|
+
const header = "编号".padEnd(6) +
|
|
151
|
+
"Type".padEnd(typeColumnWidth) +
|
|
152
|
+
"ID".padEnd(idColumnWidth) +
|
|
153
|
+
"URI".padEnd(uriColumnWidth) +
|
|
154
|
+
"URI-CN".padEnd(uriCnColumnWidth) +
|
|
155
|
+
"Name".padEnd(nameColumnWidth);
|
|
156
|
+
Ec.waiting(header);
|
|
157
|
+
|
|
158
|
+
// 分隔线
|
|
159
|
+
const separator = "-".repeat(5) + " " +
|
|
160
|
+
"-".repeat(typeColumnWidth - 1) + " " +
|
|
161
|
+
"-".repeat(idColumnWidth - 1) + " " +
|
|
162
|
+
"-".repeat(uriColumnWidth - 1) + " " +
|
|
163
|
+
"-".repeat(uriCnColumnWidth - 1) + " " +
|
|
164
|
+
"-".repeat(nameColumnWidth - 1);
|
|
165
|
+
Ec.waiting(separator);
|
|
166
|
+
|
|
167
|
+
// 数据行
|
|
140
168
|
agents.forEach((agent, index) => {
|
|
141
|
-
|
|
169
|
+
const name = `${agent.argName} (${agent.name})`;
|
|
170
|
+
const row = `${(index + 1).toString().padEnd(6)}` +
|
|
171
|
+
`${agent.type.padEnd(typeColumnWidth)}` +
|
|
172
|
+
`${agent.id.padEnd(idColumnWidth).red.bold}` +
|
|
173
|
+
`${(agent.uri || '').padEnd(uriColumnWidth)}` +
|
|
174
|
+
`${(agent.uriCn || '').padEnd(uriCnColumnWidth)}` +
|
|
175
|
+
name.padEnd(nameColumnWidth);
|
|
176
|
+
Ec.waiting(row);
|
|
142
177
|
});
|
|
178
|
+
|
|
179
|
+
Ec.waiting(separator);
|
|
143
180
|
Ec.waiting(`${agents.length + 1}. 退出`);
|
|
144
181
|
|
|
145
182
|
// 获取用户选择
|
|
@@ -169,10 +206,48 @@ module.exports = async (options) => {
|
|
|
169
206
|
const agent = agents.find(a => a.argName === agentName);
|
|
170
207
|
if (!agent) {
|
|
171
208
|
Ec.error(`❌ 未找到名为 "${agentName}" 的 Agent`);
|
|
209
|
+
|
|
210
|
+
// 显示所有 agents(表格形式)
|
|
172
211
|
Ec.waiting('可用的 Agents:');
|
|
173
|
-
|
|
174
|
-
|
|
212
|
+
|
|
213
|
+
// 计算列宽以适应内容
|
|
214
|
+
const typeColumnWidth = 12;
|
|
215
|
+
const idColumnWidth = 20;
|
|
216
|
+
const uriColumnWidth = 35;
|
|
217
|
+
const uriCnColumnWidth = 35;
|
|
218
|
+
const nameColumnWidth = 35;
|
|
219
|
+
|
|
220
|
+
// 表头
|
|
221
|
+
const header = "编号".padEnd(6) +
|
|
222
|
+
"Type".padEnd(typeColumnWidth) +
|
|
223
|
+
"ID".padEnd(idColumnWidth) +
|
|
224
|
+
"URI".padEnd(uriColumnWidth) +
|
|
225
|
+
"URI-CN".padEnd(uriCnColumnWidth) +
|
|
226
|
+
"Name".padEnd(nameColumnWidth);
|
|
227
|
+
Ec.waiting(header);
|
|
228
|
+
|
|
229
|
+
// 分隔线
|
|
230
|
+
const separator = "-".repeat(5) + " " +
|
|
231
|
+
"-".repeat(typeColumnWidth - 1) + " " +
|
|
232
|
+
"-".repeat(idColumnWidth - 1) + " " +
|
|
233
|
+
"-".repeat(uriColumnWidth - 1) + " " +
|
|
234
|
+
"-".repeat(uriCnColumnWidth - 1) + " " +
|
|
235
|
+
"-".repeat(nameColumnWidth - 1);
|
|
236
|
+
Ec.waiting(separator);
|
|
237
|
+
|
|
238
|
+
// 数据行
|
|
239
|
+
agents.forEach((agent, index) => {
|
|
240
|
+
const name = `${agent.argName} (${agent.name})`;
|
|
241
|
+
const row = `${(index + 1).toString().padEnd(6)}` +
|
|
242
|
+
`${agent.type.padEnd(typeColumnWidth)}` +
|
|
243
|
+
`${agent.id.padEnd(idColumnWidth).red.bold}` +
|
|
244
|
+
`${(agent.uri || '').padEnd(uriColumnWidth)}` +
|
|
245
|
+
`${(agent.uriCn || '').padEnd(uriCnColumnWidth)}` +
|
|
246
|
+
name.padEnd(nameColumnWidth);
|
|
247
|
+
Ec.waiting(row);
|
|
175
248
|
});
|
|
249
|
+
|
|
250
|
+
Ec.waiting(separator);
|
|
176
251
|
Ec.waiting(`${agents.length + 1}. 退出`);
|
|
177
252
|
Ec.askClose();
|
|
178
253
|
process.exit(1);
|
|
@@ -38,6 +38,7 @@ const _getAgents = () => {
|
|
|
38
38
|
name: agentInfo.name,
|
|
39
39
|
id: agentInfo.id,
|
|
40
40
|
uri: agentInfo.uri,
|
|
41
|
+
uriCn: agentInfo['uri-cn'], // 添加CN链接
|
|
41
42
|
filePath: filePath
|
|
42
43
|
});
|
|
43
44
|
} catch (error) {
|
|
@@ -60,35 +61,39 @@ const _showAgents = (agents) => {
|
|
|
60
61
|
}
|
|
61
62
|
|
|
62
63
|
// 计算列宽
|
|
63
|
-
const
|
|
64
|
-
const
|
|
64
|
+
const typeColumnWidth = 12;
|
|
65
|
+
const idColumnWidth = 20;
|
|
66
|
+
const uriColumnWidth = 35;
|
|
67
|
+
const uriCnColumnWidth = 35;
|
|
68
|
+
const nameColumnWidth = 35;
|
|
65
69
|
|
|
66
70
|
// 表头
|
|
67
71
|
const header = "编号".padEnd(6) +
|
|
68
|
-
"
|
|
69
|
-
"
|
|
70
|
-
"ID".padEnd(columnWidth) +
|
|
72
|
+
"Type".padEnd(typeColumnWidth) +
|
|
73
|
+
"ID".padEnd(idColumnWidth) +
|
|
71
74
|
"URI".padEnd(uriColumnWidth) +
|
|
72
|
-
"
|
|
75
|
+
"URI-CN".padEnd(uriCnColumnWidth) +
|
|
76
|
+
"Name".padEnd(nameColumnWidth);
|
|
73
77
|
Ec.waiting(header);
|
|
74
78
|
|
|
75
79
|
// 分隔线
|
|
76
80
|
const separator = "-".repeat(5) + " " +
|
|
77
|
-
"-".repeat(
|
|
78
|
-
"-".repeat(
|
|
79
|
-
"-".repeat(columnWidth - 1) + " " +
|
|
81
|
+
"-".repeat(typeColumnWidth - 1) + " " +
|
|
82
|
+
"-".repeat(idColumnWidth - 1) + " " +
|
|
80
83
|
"-".repeat(uriColumnWidth - 1) + " " +
|
|
81
|
-
"-".repeat(
|
|
84
|
+
"-".repeat(uriCnColumnWidth - 1) + " " +
|
|
85
|
+
"-".repeat(nameColumnWidth - 1);
|
|
82
86
|
Ec.waiting(separator);
|
|
83
87
|
|
|
84
88
|
// 数据行
|
|
85
89
|
agents.forEach((agent, index) => {
|
|
90
|
+
const name = `${agent.argName} (${agent.name})`;
|
|
86
91
|
const row = `${(index + 1).toString().padEnd(6)}` +
|
|
87
|
-
`${agent.
|
|
88
|
-
`${agent.
|
|
89
|
-
`${agent.
|
|
90
|
-
`${agent.
|
|
91
|
-
|
|
92
|
+
`${agent.type.padEnd(typeColumnWidth)}` +
|
|
93
|
+
`${agent.id.padEnd(idColumnWidth).red.bold}` +
|
|
94
|
+
`${(agent.uri || '').padEnd(uriColumnWidth)}` +
|
|
95
|
+
`${(agent.uriCn || '').padEnd(uriCnColumnWidth)}` +
|
|
96
|
+
name.padEnd(nameColumnWidth);
|
|
92
97
|
Ec.waiting(row);
|
|
93
98
|
});
|
|
94
99
|
|
|
@@ -157,9 +162,19 @@ const _interactiveSelect = async (agents) => {
|
|
|
157
162
|
continue;
|
|
158
163
|
}
|
|
159
164
|
|
|
160
|
-
//
|
|
165
|
+
// 让用户选择打开国际版还是中文版链接
|
|
161
166
|
const selectedAgent = agents[selectedIndex];
|
|
162
|
-
|
|
167
|
+
let uriToOpen = selectedAgent.uri;
|
|
168
|
+
|
|
169
|
+
if (selectedAgent.uriCn) {
|
|
170
|
+
const choice = await Ec.ask('选择打开链接版本: 1. 国际版 2. 中文版 (默认国际版): ');
|
|
171
|
+
if (choice === '2') {
|
|
172
|
+
uriToOpen = selectedAgent.uriCn;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// 打开选中的 agent
|
|
177
|
+
_openInBrowser(uriToOpen, selectedAgent.type);
|
|
163
178
|
|
|
164
179
|
// 等待一段时间让用户看到结果
|
|
165
180
|
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
@@ -5,10 +5,17 @@ const Ec = require('../epic');
|
|
|
5
5
|
/**
|
|
6
6
|
* 从 Markdown 文件中提取编号信息
|
|
7
7
|
* @param {string} filePath 文件路径
|
|
8
|
+
* @param {string} dirName 目录名(用于从目录名中提取编号)
|
|
8
9
|
* @returns {string} 编号信息或 'N/A'
|
|
9
10
|
*/
|
|
10
|
-
const _extractId = (filePath) => {
|
|
11
|
+
const _extractId = (filePath, dirName) => {
|
|
11
12
|
try {
|
|
13
|
+
// 首先尝试从目录名中提取编号(MXX格式)
|
|
14
|
+
const dirMatch = dirName.match(/^M\d{2}/);
|
|
15
|
+
if (dirMatch) {
|
|
16
|
+
return dirMatch[0];
|
|
17
|
+
}
|
|
18
|
+
|
|
12
19
|
if (!fs.existsSync(filePath)) {
|
|
13
20
|
return 'N/A';
|
|
14
21
|
}
|
|
@@ -21,8 +28,17 @@ const _extractId = (filePath) => {
|
|
|
21
28
|
return codeMatch[1].trim();
|
|
22
29
|
}
|
|
23
30
|
|
|
24
|
-
//
|
|
31
|
+
// 然后尝试从文件内容的标题中提取编号(MXX格式)
|
|
25
32
|
const lines = content.split('\n');
|
|
33
|
+
for (const line of lines) {
|
|
34
|
+
// 匹配 # MXX 格式的标题(M后跟两位数字)
|
|
35
|
+
const titleMatch = line.match(/^#\s+(M\d{2})/);
|
|
36
|
+
if (titleMatch) {
|
|
37
|
+
return titleMatch[1];
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// 如果没有找到CODE格式,尝试查找 "- 编号:" 格式
|
|
26
42
|
for (const line of lines) {
|
|
27
43
|
const idMatch = line.match(/-\s*编号[::]\s*(.+)/);
|
|
28
44
|
if (idMatch) {
|
|
@@ -51,10 +67,11 @@ const _countTasks = (tasksFile) => {
|
|
|
51
67
|
const lines = content.split('\n');
|
|
52
68
|
let count = 0;
|
|
53
69
|
|
|
54
|
-
//
|
|
70
|
+
// 匹配任务列表格式:
|
|
71
|
+
// - [ ] 任务描述
|
|
72
|
+
// - [xxx] 任务描述
|
|
55
73
|
for (const line of lines) {
|
|
56
|
-
|
|
57
|
-
if (line.trim().startsWith('- [') && line.includes('] [') && line.includes('](') && line.includes('tasks/')) {
|
|
74
|
+
if (line.trim().match(/^-\s*\[.*\]/)) {
|
|
58
75
|
count++;
|
|
59
76
|
}
|
|
60
77
|
}
|
|
@@ -89,17 +106,22 @@ module.exports = (options) => {
|
|
|
89
106
|
process.exit(0);
|
|
90
107
|
}
|
|
91
108
|
|
|
92
|
-
//
|
|
93
|
-
|
|
94
|
-
Ec.waiting(
|
|
109
|
+
// 显示表头(调整列宽和间距)
|
|
110
|
+
const header = '编号'.padEnd(12) + '名称'.padEnd(32) + '任务数量';
|
|
111
|
+
Ec.waiting(header);
|
|
112
|
+
|
|
113
|
+
// 显示分隔线
|
|
114
|
+
const separator = '-'.repeat(10) + ' ' + '-'.repeat(30) + ' ' + '-'.repeat(8);
|
|
115
|
+
Ec.waiting(separator);
|
|
95
116
|
|
|
96
117
|
// 显示需求列表
|
|
97
118
|
requirements.forEach((requirement) => {
|
|
98
119
|
const proposalFile = path.join(changesDir, requirement, 'proposal.md');
|
|
99
120
|
const tasksFile = path.join(changesDir, requirement, 'tasks.md');
|
|
100
|
-
const id = _extractId(proposalFile);
|
|
121
|
+
const id = _extractId(proposalFile, requirement);
|
|
101
122
|
const taskCount = _countTasks(tasksFile);
|
|
102
|
-
|
|
123
|
+
const line = id.padEnd(12) + requirement.padEnd(32) + String(taskCount);
|
|
124
|
+
Ec.waiting(line);
|
|
103
125
|
});
|
|
104
126
|
|
|
105
127
|
Ec.info(`✅ 共找到 ${requirements.length} 个需求`);
|
|
@@ -80,10 +80,6 @@ const _getDefaultReferConfig = () => {
|
|
|
80
80
|
file: 'project.csproj',
|
|
81
81
|
target: 'reference/dotnet'
|
|
82
82
|
},
|
|
83
|
-
java: {
|
|
84
|
-
file: 'pom.xml',
|
|
85
|
-
target: 'reference/java'
|
|
86
|
-
},
|
|
87
83
|
cmake: {
|
|
88
84
|
file: 'CMakeLists.txt',
|
|
89
85
|
target: 'reference/cmake'
|
|
@@ -242,8 +238,13 @@ const _processProjectReference = async (sourcePath, referConfig, baseDir) => {
|
|
|
242
238
|
|
|
243
239
|
Ec.waiting(`检查项目: ${sourcePath}`);
|
|
244
240
|
|
|
245
|
-
//
|
|
241
|
+
// 遍历配置中的每种项目类型,但排除java类型
|
|
246
242
|
for (const [type, config] of Object.entries(referConfig)) {
|
|
243
|
+
// 跳过java类型处理
|
|
244
|
+
if (type === 'java') {
|
|
245
|
+
continue;
|
|
246
|
+
}
|
|
247
|
+
|
|
247
248
|
const { file, target } = config;
|
|
248
249
|
|
|
249
250
|
// 检查源目录中是否存在指定文件
|