momo-ai 1.0.4 → 1.0.6
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/.momo/advanced/refer.json +50 -0
- package/README.md +51 -35
- package/package.json +1 -1
- package/src/_agent/trae/momo-datamodel.json +5 -0
- package/src/_agent/trae/momo-module-req.json +5 -0
- package/src/_agent/trae/momo-system-req.json +5 -0
- package/src/_agent/trae/momo-task.json +5 -0
- package/src/_template/MCP/.gitkeep +0 -0
- package/src/_template/PROMPT/plan.md.ejs +1 -1
- package/src/_template/PROMPT/trae/momo-datamodel.ejs +8 -0
- package/src/_template/PROMPT/trae/momo-module-req.ejs +11 -0
- package/src/_template/PROMPT/trae/momo-system-req.ejs +9 -0
- package/src/_template/PROMPT/trae/momo-task.ejs +11 -0
- package/src/commander/agent.json +12 -0
- package/src/commander/agentcfg.json +5 -0
- package/src/commander/project.json +12 -0
- package/src/epic/momo.fn.out.js +10 -3
- package/src/executor/executeAdd.js +6 -16
- package/src/executor/executeAgent.js +214 -0
- package/src/executor/executeAgentCfg.js +195 -0
- package/src/executor/executeInit.js +5 -1
- package/src/executor/executeOpen.js +22 -21
- package/src/executor/executePlan.js +3 -16
- package/src/executor/executeProject.js +296 -0
- package/src/executor/executeRun.js +3 -29
- package/src/executor/executeTasks.js +3 -29
- package/src/executor/index.js +8 -1
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"maven": {
|
|
3
|
+
"file": "pom.xml",
|
|
4
|
+
"target": "reference/maven"
|
|
5
|
+
},
|
|
6
|
+
"gradle": {
|
|
7
|
+
"file": "build.gradle",
|
|
8
|
+
"target": "reference/gradle"
|
|
9
|
+
},
|
|
10
|
+
"npm": {
|
|
11
|
+
"file": "package.json",
|
|
12
|
+
"target": "reference/npm"
|
|
13
|
+
},
|
|
14
|
+
"rust": {
|
|
15
|
+
"file": "Cargo.toml",
|
|
16
|
+
"target": "reference/rust"
|
|
17
|
+
},
|
|
18
|
+
"go": {
|
|
19
|
+
"file": "go.mod",
|
|
20
|
+
"target": "reference/go"
|
|
21
|
+
},
|
|
22
|
+
"ruby": {
|
|
23
|
+
"file": "Gemfile",
|
|
24
|
+
"target": "reference/ruby"
|
|
25
|
+
},
|
|
26
|
+
"python": {
|
|
27
|
+
"file": "requirements.txt",
|
|
28
|
+
"target": "reference/python"
|
|
29
|
+
},
|
|
30
|
+
"php": {
|
|
31
|
+
"file": "composer.json",
|
|
32
|
+
"target": "reference/php"
|
|
33
|
+
},
|
|
34
|
+
"dotnet": {
|
|
35
|
+
"file": "project.csproj",
|
|
36
|
+
"target": "reference/dotnet"
|
|
37
|
+
},
|
|
38
|
+
"java": {
|
|
39
|
+
"file": "pom.xml",
|
|
40
|
+
"target": "reference/java"
|
|
41
|
+
},
|
|
42
|
+
"cmake": {
|
|
43
|
+
"file": "CMakeLists.txt",
|
|
44
|
+
"target": "reference/cmake"
|
|
45
|
+
},
|
|
46
|
+
"make": {
|
|
47
|
+
"file": "Makefile",
|
|
48
|
+
"target": "reference/make"
|
|
49
|
+
}
|
|
50
|
+
}
|
package/README.md
CHANGED
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
|
|
6
6
|
## 1. 介绍
|
|
7
7
|
|
|
8
|
+
### 1.1. 功能说明
|
|
9
|
+
|
|
8
10
|
当前工具会在操作系统中安装 `momo` 命令,使用它进行 `SDD - Spec Driven Development` 开发:
|
|
9
11
|
|
|
10
12
|
1. 参考:`OpenSpec / Spec-Kit / Kiro`
|
|
@@ -22,6 +24,30 @@
|
|
|
22
24
|
|
|
23
25
|
> 除开 `momo` 命令后续会提供和模型直接交互的 `lain` 命令,近似 `iFlow / openspec` 的功能。
|
|
24
26
|
|
|
27
|
+
### 1.2. 开始步骤
|
|
28
|
+
|
|
29
|
+
1. 使用 `momo init` 初始化协同工程项目(运行之前可使用 `momo env` 检查环境)。
|
|
30
|
+
2. 使用 `momo repo` 添加项目代码库以及工程实例(有多少个 `Agent` 工作就添加多少工程实例),添加完成后可使用 `momo open`
|
|
31
|
+
直接打开工程。
|
|
32
|
+
3. 更新 `project.md / project-model.md / requirement.md` 的细节文档(可用AI帮助拆分和书写)
|
|
33
|
+
4. 使用 `momo add -n 需求名称` 添加细节需求(可用AI帮助拆分和书写:`momo plan -n 需求名称`)
|
|
34
|
+
5. 使用 `momo tasks` 列出所有任务,并且使用 `momo run` 运行任务得到任务提示词
|
|
35
|
+
|
|
36
|
+
> 带 (CV) 📋️ 标记的命令——运行成功后可直接“Ctrl + V”粘贴到 TRAE / Lingma / Cursor / Kiro 中执行。
|
|
37
|
+
|
|
38
|
+
### 1.3. 项目计划
|
|
39
|
+
|
|
40
|
+
1. 使用 `momo project` 将后端项目拷贝到 `reference` 目录中(主要是提供数据模型)。
|
|
41
|
+
2. (唯一的人工处理)更新 `project.md` 中的所有信息,核心包括:
|
|
42
|
+
- 功能描述
|
|
43
|
+
- 场景描述等
|
|
44
|
+
- 风格
|
|
45
|
+
- 技术栈
|
|
46
|
+
3. 使用 `momo agentcfg` 给 TRAE 工具配置智能体,主要是导入部分已经定制好的智能体。
|
|
47
|
+
4. 使用 `momo agent -a "智能体名称"` 调用智能体进行开发之前的准备工作,目前支持的智能体可直接使用 `momo agentcfg` 查看。
|
|
48
|
+
|
|
49
|
+
<hr/>
|
|
50
|
+
|
|
25
51
|
## 2. 工具使用
|
|
26
52
|
|
|
27
53
|
### 2.1. 安装
|
|
@@ -32,67 +58,55 @@ npm install -g momo-ai
|
|
|
32
58
|
momo help
|
|
33
59
|
```
|
|
34
60
|
|
|
35
|
-
### 2.2. 操作步骤
|
|
36
|
-
|
|
37
|
-
1. 使用 `momo init` 初始化协同工程项目(运行之前可使用 `momo env` 检查环境)。
|
|
38
|
-
2. 使用 `momo repo` 添加项目代码库以及工程实例(有多少个 `Agent` 工作就添加多少工程实例),添加完成后可使用 `momo open`
|
|
39
|
-
直接打开工程。
|
|
40
|
-
3. 更新 `project.md / project-model.md / requirement.md` 的细节文档(可用AI帮助拆分和书写)
|
|
41
|
-
4. 使用 `momo add -n 需求名称` 添加细节需求(可用AI帮助拆分和书写:`momo plan -n 需求名称`)
|
|
42
|
-
5. 使用 `momo tasks` 列出所有任务,并且使用 `momo run` 运行任务得到任务提示词
|
|
43
|
-
|
|
44
|
-
> 带 (CV) 标记的命令运行成功后可直接“Ctrl + V”粘贴到 TRAE / Lingma / Cursor / Kiro 中执行。
|
|
45
|
-
|
|
46
61
|
### 2.3. 命令:不定模型
|
|
47
62
|
|
|
48
63
|
```bash
|
|
49
64
|
# ------------ 工程初始化 -----------------
|
|
50
|
-
#
|
|
51
|
-
momo env
|
|
65
|
+
# 🌷 环境检查、工程和代码初始化、工具启动等
|
|
66
|
+
momo env # 环境检查
|
|
52
67
|
|
|
53
|
-
#
|
|
54
|
-
momo init
|
|
55
|
-
momo init # 初始化当前项目
|
|
68
|
+
momo init -d app-fly # 初始化 directory = app-fly 的项目
|
|
69
|
+
momo init # 初始化当前项目
|
|
56
70
|
|
|
57
|
-
# momo repo
|
|
58
71
|
momo repo -a https://xxx/repo.git # 克隆远程代码库 -> source/repo/develop-01(名称靠解析) -> git submodule
|
|
59
72
|
momo repo -a xxx -i 10 # 克隆远程代码库(10个副本)
|
|
60
73
|
|
|
61
74
|
momo open # 交互式使用 TRAE / Lingma / Cursor / Kiro 打开当前项目
|
|
62
75
|
|
|
63
|
-
#
|
|
64
|
-
|
|
65
|
-
momo
|
|
66
|
-
momo
|
|
76
|
+
momo project -s "项目路径" # 将路径中的显示拷贝到当前项目的 reference 目录下,若不提供 -s 则直接列举所有支持的项目类型
|
|
77
|
+
|
|
78
|
+
momo agentcfg # 列出所有智能体,并且打开浏览器配置
|
|
79
|
+
momo agent -a "智能体名称" # 📋️ 调用智能体 -> prompt 得到提示词到剪切板
|
|
67
80
|
|
|
68
|
-
#
|
|
69
|
-
|
|
81
|
+
# ------------ 需求相关 -----------------
|
|
82
|
+
# 🌷 需求管理:添加、归档、校验、列出、显示
|
|
83
|
+
momo add -n "需求名称" # 📋️ 添加新需求 -> changes 下追加新内容 -> 包括任务
|
|
84
|
+
momo add -n "需求(MD)文档路径" # 📋️ 添加需求文档 -> changes 下追加新内容 -> 包括任务,如果带后缀直接用文件名做需求名称
|
|
70
85
|
|
|
71
|
-
# momo archive
|
|
72
86
|
momo archive -n "需求名称" # 需求归档 -> archive 下追加新内容,删除 changes 下内容
|
|
73
87
|
|
|
74
|
-
# momo show
|
|
75
88
|
momo show -n "需求名称" # 显示需求 -> 显示 changes 下内容
|
|
76
89
|
|
|
77
|
-
# momo validate
|
|
78
90
|
momo validate -n "需求名称" # 需求校验 -> 校验 changes 下内容
|
|
79
91
|
|
|
80
|
-
# momo list
|
|
81
92
|
momo list # 列出所有需求 -> changes 下内容
|
|
82
93
|
|
|
83
|
-
# ------------ 任务执行 -----------------
|
|
84
|
-
# momo tasks
|
|
85
|
-
momo tasks # 显示任务 -> 需求 / 任务 / 状态 -> 状态 = 待办 / 进行中 / 已完成
|
|
86
94
|
|
|
87
|
-
#
|
|
95
|
+
# 🌷 需求分析:计划、执行、拆分
|
|
96
|
+
momo plan -n "需求名称" # 📋️ 生成需求的整体开发计划 -> prompt 剪切板
|
|
97
|
+
|
|
98
|
+
# ------------ 任务执行 -----------------
|
|
99
|
+
# 🌷 任务执行:定义角色、执行任务
|
|
88
100
|
momo actors # 列出所有角色
|
|
89
101
|
|
|
90
|
-
# momo actor
|
|
91
102
|
momo actor -a "角色名称" # 添加新角色 -> 交互式命令,每个角色可以指定不同的大模型
|
|
92
103
|
|
|
93
|
-
|
|
94
|
-
momo
|
|
95
|
-
|
|
104
|
+
|
|
105
|
+
momo tasks # 📋️ 显示任务 -> 需求 / 任务 / 状态 -> 状态 = 待办 / 进行中 / 已完成
|
|
106
|
+
|
|
107
|
+
momo run -a {actor} -t {task} # 📋️ 将任务分配给角色,检查执行目录看哪些任务正在执行
|
|
108
|
+
momo run # 📋️ 从菜单中选择任务
|
|
109
|
+
|
|
96
110
|
momo unlock # 解锁任务 -> 任务状态 = 待办
|
|
97
111
|
```
|
|
98
112
|
|
|
@@ -100,6 +114,8 @@ momo unlock # 解锁任务 -> 任务状态 = 待办
|
|
|
100
114
|
|
|
101
115
|
> 控制台开发中(Lain 模式)
|
|
102
116
|
|
|
117
|
+
<hr/>
|
|
118
|
+
|
|
103
119
|
## 3. 参考链接
|
|
104
120
|
|
|
105
121
|
### 3.1. 旧版
|
package/package.json
CHANGED
|
File without changes
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# 需求计划提示词
|
|
2
2
|
|
|
3
3
|
<!-- BEGIN -->
|
|
4
4
|
阅读 specification/project.md 中的基本需求信息,根据 <%= NAME %> 的描述信息,重新制定需求的开发计划,更改掉 specification/changes/<%= NAME %>/ 目录中的需求说明,重新制定任务清单并且更新(子任务清单在specification/changes/<%= NAME %>/tasks/目录下),项目本身的技术栈和数据模型可参考 specification/project-model.md 文件。
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# 模块需求提示词
|
|
2
|
+
|
|
3
|
+
<!-- BEGIN -->
|
|
4
|
+
详细解读 specification/requirement.md 需求文档中的模块和每个模块的功能列表,在 specification/changes/ 目录之下创建模块的核心文档,每个模块用 MXX- 前缀,其中 XX 是模块编号。
|
|
5
|
+
|
|
6
|
+
1. 每个模块中包括 tasks/ 目录、任务明细文档存放位置。
|
|
7
|
+
2. 每个模块中包括 proposal.md,此文档中用来存放模块的详细需求。
|
|
8
|
+
3. 每个模块中包括 tasks.md,此文档中是描述所有任务的总清单。
|
|
9
|
+
4. 模块所需的数据模型可参考 specification/project-model.md 文档。
|
|
10
|
+
5. 有多少模块在于你的模块的整体设计,记得模块内部业务要形成完整闭环。
|
|
11
|
+
<!-- END -->
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# 系统需求提示词
|
|
2
|
+
|
|
3
|
+
<!-- BEGIN -->
|
|
4
|
+
根据人工提供的 specification/project.md 的详细需求描述进行核心分析,生成一份当前项目的比较规范的需求描述文档,用文档更新 specification/requirement.md 文档,这份需求文档的读者是前端架构师和前端工程师,所以一定要阐述清楚整个系统实现想要达到的效果和功能
|
|
5
|
+
|
|
6
|
+
1. 数据模型可以参考 specification/project-model.md 文档。
|
|
7
|
+
2. 技术栈信息可以直接从 specification/project.md 需求文档中提取。
|
|
8
|
+
3. 输出文档中一定要输出的核心内容:模块清单、模块中的功能列表。
|
|
9
|
+
<!-- END -->
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# 领域建模提示词
|
|
2
|
+
|
|
3
|
+
<!-- BEGIN -->
|
|
4
|
+
解读 specification/changes/ 下的所有模块(必须是 MXX- 开头的目录)对应的变更内容,并生成领域模型,根据每个目录中的 tasks.md 生成对应的任务并且更新 tasks.md 文件:
|
|
5
|
+
|
|
6
|
+
1. 每个模块的详细需求位于 specification/changes/MXX-模块/proposal.md 文件中。
|
|
7
|
+
2. 每个任务存放在 specification/changes/MXX-模块/tasks/ 目录下。
|
|
8
|
+
3. 任务文件名统一成 MXX-TNNN.md,其中 NN 是任务编号,NNN 是任务编号,编号长度不足用 0 填充。
|
|
9
|
+
4. 每个任务文件中要写出任务实施过程的详细步骤。
|
|
10
|
+
5. 系统相关的数据模型参考 specification/data-model.md 文件。
|
|
11
|
+
<!-- END -->
|
package/src/epic/momo.fn.out.js
CHANGED
|
@@ -22,6 +22,8 @@ const outString = (paths, content, sync = false) => __FX.fxContinue(!!content, (
|
|
|
22
22
|
const outCopy = (data) => new Promise(function (resolve, reject) {
|
|
23
23
|
const platform = os.platform();
|
|
24
24
|
let cmd = '';
|
|
25
|
+
let args = [];
|
|
26
|
+
|
|
25
27
|
if (platform === 'win32') {
|
|
26
28
|
cmd = 'clip';
|
|
27
29
|
} else if (platform === 'darwin') {
|
|
@@ -29,14 +31,19 @@ const outCopy = (data) => new Promise(function (resolve, reject) {
|
|
|
29
31
|
} else {
|
|
30
32
|
// 对于Linux和其他Unix-like系统,尝试使用xclip
|
|
31
33
|
cmd = 'xclip';
|
|
34
|
+
args = ['-selection', 'clipboard'];
|
|
32
35
|
}
|
|
33
36
|
|
|
34
|
-
const proc = require('child_process').spawn(cmd,
|
|
37
|
+
const proc = require('child_process').spawn(cmd, args);
|
|
35
38
|
proc.on('error', function (err) {
|
|
36
39
|
reject(err);
|
|
37
40
|
});
|
|
38
|
-
proc.on('close', function (
|
|
39
|
-
|
|
41
|
+
proc.on('close', function (code) {
|
|
42
|
+
if (code === 0) {
|
|
43
|
+
resolve();
|
|
44
|
+
} else {
|
|
45
|
+
reject(new Error(`剪贴板进程退出码: ${code}`));
|
|
46
|
+
}
|
|
40
47
|
});
|
|
41
48
|
proc.stdin.write(data);
|
|
42
49
|
proc.stdin.end();
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
2
|
const path = require('path');
|
|
3
3
|
const util = require('util');
|
|
4
|
-
const { spawn } = require('child_process');
|
|
5
4
|
const Ec = require('../epic');
|
|
6
5
|
const fsAsync = require('fs').promises;
|
|
6
|
+
const { outCopy } = require('../epic/momo.fn.out');
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* 读取模板文件并提取 <!-- BEGIN --> 到 <!-- END --> 之间的内容
|
|
@@ -174,27 +174,17 @@ const _copyToClipboard = async (content) => {
|
|
|
174
174
|
// 去除换行符,将内容合并为一行
|
|
175
175
|
const contentWithoutNewlines = content.replace(/\r?\n|\r/g, ' ');
|
|
176
176
|
|
|
177
|
-
//
|
|
178
|
-
|
|
179
|
-
if (process.platform === 'darwin') {
|
|
180
|
-
// macOS
|
|
181
|
-
proc = spawn('pbcopy', { stdio: 'pipe' });
|
|
182
|
-
} else if (process.platform === 'win32') {
|
|
183
|
-
// Windows
|
|
184
|
-
proc = spawn('clip', { stdio: 'pipe' });
|
|
185
|
-
} else {
|
|
186
|
-
// Linux/其他系统,尝试使用xclip
|
|
187
|
-
proc = spawn('xclip', ['-selection', 'clipboard'], { stdio: 'pipe' });
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
proc.stdin.write(contentWithoutNewlines);
|
|
191
|
-
proc.stdin.end();
|
|
177
|
+
// 使用统一的剪贴板函数
|
|
178
|
+
await outCopy(contentWithoutNewlines);
|
|
192
179
|
Ec.waiting('✅ 提示词已复制到剪贴板');
|
|
193
180
|
} catch (error) {
|
|
194
181
|
Ec.waiting(`复制到剪贴板失败: ${error.message}`);
|
|
195
182
|
// 提供备选方案
|
|
196
183
|
Ec.waiting('提示词内容:');
|
|
197
184
|
console.log(content);
|
|
185
|
+
if (process.platform === 'win32') {
|
|
186
|
+
Ec.waiting('💡 Windows 用户提示: 请确保您在具有足够权限的命令行中运行此命令');
|
|
187
|
+
}
|
|
198
188
|
}
|
|
199
189
|
};
|
|
200
190
|
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const util = require('util');
|
|
4
|
+
const Ec = require('../epic');
|
|
5
|
+
|
|
6
|
+
// 将 fs 方法转换为 Promise 版本
|
|
7
|
+
const fsAsync = {
|
|
8
|
+
readFile: util.promisify(fs.readFile),
|
|
9
|
+
readdir: util.promisify(fs.readdir),
|
|
10
|
+
stat: util.promisify(fs.stat)
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* 获取所有 agents 信息
|
|
15
|
+
* @returns {Array} agents 信息数组
|
|
16
|
+
*/
|
|
17
|
+
const _getAgents = () => {
|
|
18
|
+
const agentsDir = path.resolve(__dirname, '../_agent');
|
|
19
|
+
const agents = [];
|
|
20
|
+
|
|
21
|
+
if (!fs.existsSync(agentsDir)) {
|
|
22
|
+
return agents;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// 遍历 _agent 目录下的所有子目录
|
|
26
|
+
const types = fs.readdirSync(agentsDir).filter(file =>
|
|
27
|
+
fs.statSync(path.join(agentsDir, file)).isDirectory()
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
// 遍历每个类型目录
|
|
31
|
+
types.forEach(type => {
|
|
32
|
+
const typeDir = path.join(agentsDir, type);
|
|
33
|
+
const files = fs.readdirSync(typeDir).filter(file => file.endsWith('.json'));
|
|
34
|
+
|
|
35
|
+
// 遍历每个 json 文件
|
|
36
|
+
files.forEach(file => {
|
|
37
|
+
try {
|
|
38
|
+
const filePath = path.join(typeDir, file);
|
|
39
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
40
|
+
const agentInfo = JSON.parse(content);
|
|
41
|
+
|
|
42
|
+
agents.push({
|
|
43
|
+
argName: file.replace('momo-', '').replace('.json', ''),
|
|
44
|
+
type: type,
|
|
45
|
+
id: agentInfo.id,
|
|
46
|
+
name: agentInfo.name,
|
|
47
|
+
uri: agentInfo.uri,
|
|
48
|
+
filePath: filePath
|
|
49
|
+
});
|
|
50
|
+
} catch (error) {
|
|
51
|
+
Ec.waiting(`⚠️ 无法解析文件: ${file} - ${error.message}`);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
return agents;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* 从 EJS 模板中提取内容
|
|
61
|
+
* @param {string} templatePath 模板路径
|
|
62
|
+
* @returns {Promise<string>} 提取的模板内容
|
|
63
|
+
*/
|
|
64
|
+
const _extractTemplateContent = async (templatePath) => {
|
|
65
|
+
try {
|
|
66
|
+
const content = await fsAsync.readFile(templatePath, 'utf8');
|
|
67
|
+
const lines = content.split('\n');
|
|
68
|
+
let beginIndex = -1;
|
|
69
|
+
let endIndex = -1;
|
|
70
|
+
|
|
71
|
+
for (let i = 0; i < lines.length; i++) {
|
|
72
|
+
if (lines[i].includes('<!-- BEGIN -->')) {
|
|
73
|
+
beginIndex = i;
|
|
74
|
+
} else if (lines[i].includes('<!-- END -->')) {
|
|
75
|
+
endIndex = i;
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (beginIndex !== -1 && endIndex !== -1) {
|
|
81
|
+
// 提取 BEGIN 和 END 之间的内容(不包括 BEGIN 和 END 行)
|
|
82
|
+
return lines.slice(beginIndex + 1, endIndex).join('\n');
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return content;
|
|
86
|
+
} catch (error) {
|
|
87
|
+
throw new Error(`无法读取模板文件: ${error.message}`);
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* 将内容复制到剪贴板
|
|
93
|
+
* @param {string} content 要复制的内容
|
|
94
|
+
*/
|
|
95
|
+
const _copyToClipboard = async (content) => {
|
|
96
|
+
const { outCopy } = require('../epic/momo.fn.out');
|
|
97
|
+
try {
|
|
98
|
+
// 先打印内容,按行打印并保留前缀
|
|
99
|
+
Ec.waiting('📄 提示词内容:');
|
|
100
|
+
Ec.waiting('----------------------------------------');
|
|
101
|
+
const lines = content.split('\n');
|
|
102
|
+
lines.forEach(line => {
|
|
103
|
+
Ec.waiting(line);
|
|
104
|
+
});
|
|
105
|
+
Ec.waiting('----------------------------------------');
|
|
106
|
+
|
|
107
|
+
// 再复制到剪贴板
|
|
108
|
+
await outCopy(content);
|
|
109
|
+
Ec.waiting('✅ 提示词已复制到剪贴板');
|
|
110
|
+
} catch (error) {
|
|
111
|
+
Ec.waiting(`复制到剪贴板失败: ${error.message}`);
|
|
112
|
+
// 提供备选方案
|
|
113
|
+
Ec.waiting('提示词内容:');
|
|
114
|
+
const lines = content.split('\n');
|
|
115
|
+
lines.forEach(line => {
|
|
116
|
+
Ec.waiting(line);
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
module.exports = async (options) => {
|
|
122
|
+
// 参数提取
|
|
123
|
+
const parsed = Ec.parseArgument(options);
|
|
124
|
+
const agentName = parsed.agent || parsed.a;
|
|
125
|
+
|
|
126
|
+
try {
|
|
127
|
+
// 获取所有 agents
|
|
128
|
+
const agents = _getAgents();
|
|
129
|
+
|
|
130
|
+
if (agents.length === 0) {
|
|
131
|
+
Ec.error("❌ 未找到任何 agents");
|
|
132
|
+
Ec.askClose();
|
|
133
|
+
process.exit(1);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// 如果没有提供 agent 参数,显示可用的 agents 并让用户选择
|
|
137
|
+
if (!agentName) {
|
|
138
|
+
Ec.waiting('可用的 Agents:');
|
|
139
|
+
agents.forEach((agent, index) => {
|
|
140
|
+
Ec.waiting(`${index + 1}. ${agent.argName.red.bold} (${agent.name}), id = ${agent.id}, uri = ${agent.uri}`);
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
// 获取用户选择
|
|
144
|
+
const answer = await Ec.ask('请选择要使用的 Agent (输入编号): ');
|
|
145
|
+
const selectedIndex = parseInt(answer) - 1;
|
|
146
|
+
|
|
147
|
+
// 验证选择
|
|
148
|
+
if (isNaN(selectedIndex) || selectedIndex < 0 || selectedIndex >= agents.length) {
|
|
149
|
+
Ec.error("❌ 无效的选择");
|
|
150
|
+
Ec.askClose();
|
|
151
|
+
process.exit(1);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// 使用选择的 agent
|
|
155
|
+
const selectedAgent = agents[selectedIndex];
|
|
156
|
+
return await _processAgent(selectedAgent);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// 查找指定的 agent
|
|
160
|
+
const agent = agents.find(a => a.argName === agentName);
|
|
161
|
+
if (!agent) {
|
|
162
|
+
Ec.error(`❌ 未找到名为 "${agentName}" 的 Agent`);
|
|
163
|
+
Ec.waiting('可用的 Agents:');
|
|
164
|
+
agents.forEach((a, index) => {
|
|
165
|
+
Ec.waiting(`${index + 1}. ${a.argName.red.bold} (${a.name}), id = ${a.id}, uri = ${a.uri}`);
|
|
166
|
+
});
|
|
167
|
+
Ec.askClose();
|
|
168
|
+
process.exit(1);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// 处理选中的 agent
|
|
172
|
+
await _processAgent(agent);
|
|
173
|
+
|
|
174
|
+
} catch (error) {
|
|
175
|
+
Ec.error(`❌ 执行过程中发生错误: ${error.message}`);
|
|
176
|
+
Ec.askClose();
|
|
177
|
+
process.exit(1);
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* 处理选中的 agent
|
|
183
|
+
* @param {Object} agent 选中的 agent 对象
|
|
184
|
+
*/
|
|
185
|
+
const _processAgent = async (agent) => {
|
|
186
|
+
try {
|
|
187
|
+
// 构建模板路径
|
|
188
|
+
const templatePath = path.resolve(__dirname, `../_template/PROMPT/${agent.type}/${agent.id}.ejs`);
|
|
189
|
+
|
|
190
|
+
// 检查模板文件是否存在
|
|
191
|
+
if (!fs.existsSync(templatePath)) {
|
|
192
|
+
Ec.error(`❌ 未找到模板文件: ${templatePath}`);
|
|
193
|
+
Ec.askClose();
|
|
194
|
+
process.exit(1);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// 提取模板内容
|
|
198
|
+
const content = await _extractTemplateContent(templatePath);
|
|
199
|
+
|
|
200
|
+
// 复制到剪贴板
|
|
201
|
+
await _copyToClipboard(content);
|
|
202
|
+
|
|
203
|
+
// 显示警告提示
|
|
204
|
+
Ec.waiting('');
|
|
205
|
+
Ec.warn('⚠️ 为了获得最佳效果,请在您的 IDE 工具窗口中选择对应的 Agent 来配合使用此提示词');
|
|
206
|
+
|
|
207
|
+
Ec.askClose();
|
|
208
|
+
process.exit(0);
|
|
209
|
+
} catch (error) {
|
|
210
|
+
Ec.error(`❌ 处理 Agent 时发生错误: ${error.message}`);
|
|
211
|
+
Ec.askClose();
|
|
212
|
+
process.exit(1);
|
|
213
|
+
}
|
|
214
|
+
};
|