ccg-ros2-workflow 1.0.9 → 1.2.0
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/README.md +51 -12
- package/bin/cli.js +567 -127
- package/package.json +6 -2
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
ROS2 多模型协作开发工具 - 基于 Claude Code CLI
|
|
7
7
|
|
|
8
|
-
> **v1.0
|
|
8
|
+
> **v1.2.0** - 全新交互式菜单体验,支持更新检查
|
|
9
9
|
|
|
10
10
|
## 特性
|
|
11
11
|
|
|
@@ -29,10 +29,13 @@ ccg-ros2-workflow
|
|
|
29
29
|
```
|
|
30
30
|
|
|
31
31
|
安装程序提供以下选项:
|
|
32
|
-
1.
|
|
33
|
-
2.
|
|
32
|
+
1. 安装/重装工作流
|
|
33
|
+
2. 更新工作流
|
|
34
34
|
3. 配置 ace-tool MCP
|
|
35
|
-
4.
|
|
35
|
+
4. 配置 API 密钥
|
|
36
|
+
5. 帮助
|
|
37
|
+
6. 卸载工作流
|
|
38
|
+
7. 退出
|
|
36
39
|
|
|
37
40
|
## 前置依赖
|
|
38
41
|
|
|
@@ -167,6 +170,10 @@ npm install -g @google/gemini-cli
|
|
|
167
170
|
│ ├── gemini/ # analyzer, architect, reviewer, debugger, optimizer, tester, frontend
|
|
168
171
|
│ └── claude/ # analyzer, architect, reviewer, debugger, optimizer, tester
|
|
169
172
|
├── commands/ccg/ # 17 个命令文件
|
|
173
|
+
├── agents/ccg/ # 3 个 agent 文件
|
|
174
|
+
│ ├── system-integrator.md # ROS2 系统集成设计
|
|
175
|
+
│ ├── planner.md # WBS 任务规划
|
|
176
|
+
│ └── get-current-datetime.md
|
|
170
177
|
├── mcp_servers.json # MCP 配置 (ace-tool)
|
|
171
178
|
└── bin/
|
|
172
179
|
└── codeagent-wrapper # 模型调用脚本
|
|
@@ -176,22 +183,35 @@ npm install -g @google/gemini-cli
|
|
|
176
183
|
|
|
177
184
|
ace-tool 是 Augment Code 的代码上下文引擎,让 AI 自动理解项目结构。
|
|
178
185
|
|
|
179
|
-
|
|
186
|
+
### 安装方式
|
|
187
|
+
|
|
188
|
+
运行安装程序,选择「配置 ace-tool MCP」:
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
npx ccg-ros2-workflow
|
|
192
|
+
# 选择 3. 配置 ace-tool MCP
|
|
193
|
+
# 选择版本:ace-tool (Node.js) 或 ace-tool-rs (Rust,推荐)
|
|
194
|
+
# 输入 Token(从 augmentcode.com 或中转服务获取)
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### 配置示例
|
|
180
198
|
|
|
181
199
|
```json
|
|
182
200
|
{
|
|
183
201
|
"ace-tool": {
|
|
184
|
-
"command": "
|
|
185
|
-
"args": ["mcp"],
|
|
186
|
-
"env": {}
|
|
202
|
+
"command": "npx",
|
|
203
|
+
"args": ["ace-tool-rs", "mcp", "--token", "your-token"],
|
|
204
|
+
"env": { "RUST_LOG": "info" }
|
|
187
205
|
}
|
|
188
206
|
}
|
|
189
207
|
```
|
|
190
208
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
209
|
+
### Token 获取
|
|
210
|
+
|
|
211
|
+
- **官方服务**: https://augmentcode.com/ 注册获取
|
|
212
|
+
- **中转服务**: 使用第三方中转(需要配置 Base URL)
|
|
213
|
+
|
|
214
|
+
配置完成后重启 Claude Code 即可使用。
|
|
195
215
|
|
|
196
216
|
## 语言配置
|
|
197
217
|
|
|
@@ -222,6 +242,25 @@ MIT
|
|
|
222
242
|
|
|
223
243
|
## 更新日志
|
|
224
244
|
|
|
245
|
+
### v1.2.0
|
|
246
|
+
- 全新交互式菜单 (inquirer + chalk)
|
|
247
|
+
- 添加更新检查功能,支持 npm 版本对比
|
|
248
|
+
- 新增 agents 目录,包含 3 个 agent 文件
|
|
249
|
+
- 改进卸载流程,显示详细文件统计
|
|
250
|
+
- 新增帮助命令,展示所有可用 /ccg: 命令
|
|
251
|
+
- 优化安装流程,显示安装摘要
|
|
252
|
+
|
|
253
|
+
### v1.1.0
|
|
254
|
+
- 支持直接安装 ace-tool,无需手动安装 CLI
|
|
255
|
+
- 支持 ace-tool (Node.js) 和 ace-tool-rs (Rust) 两种版本
|
|
256
|
+
- 支持配置 Token 和 Base URL(中转服务)
|
|
257
|
+
- 使用 npx 自动下载运行,首次使用自动安装
|
|
258
|
+
|
|
259
|
+
### v1.0.9
|
|
260
|
+
- 提示词文件统一使用英文
|
|
261
|
+
- 保留 "Code comments in Chinese" 指令
|
|
262
|
+
- 语言规范:提示词(英文) / 交互(中文) / 注释(中文)
|
|
263
|
+
|
|
225
264
|
### v1.0.8
|
|
226
265
|
- 基于 Codex+Gemini 双模型交叉验证分析优化
|
|
227
266
|
- `gemini/architect.md`: 增加 QoS 策略设计 + Node Composition
|
package/bin/cli.js
CHANGED
|
@@ -2,24 +2,37 @@
|
|
|
2
2
|
|
|
3
3
|
const fs = require('fs');
|
|
4
4
|
const path = require('path');
|
|
5
|
-
const readline = require('readline');
|
|
6
5
|
const { execSync } = require('child_process');
|
|
7
6
|
|
|
7
|
+
// 延迟加载依赖,避免首次运行时报错
|
|
8
|
+
let inquirer, chalk;
|
|
9
|
+
async function loadDependencies() {
|
|
10
|
+
try {
|
|
11
|
+
inquirer = require('inquirer');
|
|
12
|
+
chalk = require('chalk');
|
|
13
|
+
} catch {
|
|
14
|
+
console.log('正在安装依赖...');
|
|
15
|
+
execSync('npm install inquirer@8.2.6 chalk@4.1.2', { stdio: 'inherit' });
|
|
16
|
+
inquirer = require('inquirer');
|
|
17
|
+
chalk = require('chalk');
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// 路径常量
|
|
8
22
|
const CLAUDE_DIR = path.join(process.env.HOME, '.claude');
|
|
9
23
|
const CCG_DIR = path.join(CLAUDE_DIR, '.ccg');
|
|
10
24
|
const COMMANDS_DIR = path.join(CLAUDE_DIR, 'commands', 'ccg');
|
|
25
|
+
const AGENTS_DIR = path.join(CLAUDE_DIR, 'agents', 'ccg');
|
|
11
26
|
const BIN_DIR = path.join(CLAUDE_DIR, 'bin');
|
|
12
27
|
const MCP_CONFIG_PATH = path.join(CLAUDE_DIR, 'mcp_servers.json');
|
|
13
28
|
const SRC_DIR = path.join(__dirname, '..', 'src');
|
|
29
|
+
const PACKAGE_NAME = 'ccg-ros2-workflow';
|
|
14
30
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
});
|
|
31
|
+
// 版本信息
|
|
32
|
+
const PACKAGE_JSON = require('../package.json');
|
|
33
|
+
const VERSION = PACKAGE_JSON.version;
|
|
19
34
|
|
|
20
|
-
|
|
21
|
-
return new Promise(resolve => rl.question(prompt, resolve));
|
|
22
|
-
}
|
|
35
|
+
// ==================== 工具函数 ====================
|
|
23
36
|
|
|
24
37
|
function copyRecursive(src, dest) {
|
|
25
38
|
if (!fs.existsSync(src)) return;
|
|
@@ -44,182 +57,520 @@ function replaceInFile(filePath, replacements) {
|
|
|
44
57
|
fs.writeFileSync(filePath, content);
|
|
45
58
|
}
|
|
46
59
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
console.log('Codex (底层) + Gemini (上层) + Claude (编排)\n');
|
|
60
|
+
function isInstalled() {
|
|
61
|
+
return fs.existsSync(path.join(CCG_DIR, 'config.toml')) ||
|
|
62
|
+
fs.existsSync(COMMANDS_DIR);
|
|
63
|
+
}
|
|
52
64
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
65
|
+
function getInstalledVersion() {
|
|
66
|
+
const configPath = path.join(CCG_DIR, 'config.toml');
|
|
67
|
+
if (fs.existsSync(configPath)) {
|
|
68
|
+
const content = fs.readFileSync(configPath, 'utf8');
|
|
69
|
+
const match = content.match(/version\s*=\s*"([^"]+)"/);
|
|
70
|
+
if (match) return match[1];
|
|
61
71
|
}
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
62
74
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
75
|
+
async function checkLatestVersion() {
|
|
76
|
+
try {
|
|
77
|
+
const result = execSync(`npm view ${PACKAGE_NAME} version`, { encoding: 'utf8', timeout: 10000 });
|
|
78
|
+
return result.trim();
|
|
79
|
+
} catch {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function countFiles(dir, ext = '.md') {
|
|
85
|
+
if (!fs.existsSync(dir)) return 0;
|
|
86
|
+
return fs.readdirSync(dir).filter(f => f.endsWith(ext)).length;
|
|
87
|
+
}
|
|
70
88
|
|
|
71
|
-
|
|
89
|
+
// ==================== 主菜单 ====================
|
|
72
90
|
|
|
73
|
-
|
|
74
|
-
|
|
91
|
+
async function showMainMenu() {
|
|
92
|
+
console.log('\n' + chalk.cyan.bold('🤖 CCG-ROS2-Workflow'));
|
|
93
|
+
console.log(chalk.gray('━'.repeat(40)));
|
|
94
|
+
console.log(chalk.white('ROS2 多模型协作开发工具'));
|
|
95
|
+
console.log(chalk.gray(`Codex (底层控制) + Gemini (上层集成) + Claude (编排)`));
|
|
96
|
+
console.log(chalk.gray(`版本: ${VERSION}`));
|
|
97
|
+
console.log(chalk.gray('━'.repeat(40)) + '\n');
|
|
98
|
+
|
|
99
|
+
// 检查安装状态
|
|
100
|
+
const installed = isInstalled();
|
|
101
|
+
const installedVersion = getInstalledVersion();
|
|
102
|
+
|
|
103
|
+
if (installed) {
|
|
104
|
+
console.log(chalk.green(`✓ 已安装`) + (installedVersion ? chalk.gray(` (v${installedVersion})`) : ''));
|
|
105
|
+
} else {
|
|
106
|
+
console.log(chalk.yellow(`○ 未安装`));
|
|
107
|
+
}
|
|
108
|
+
console.log('');
|
|
109
|
+
|
|
110
|
+
const choices = [
|
|
111
|
+
{ name: chalk.green('1.') + ' 安装/重装工作流', value: 'install' },
|
|
112
|
+
{ name: chalk.blue('2.') + ' 更新工作流', value: 'update' },
|
|
113
|
+
{ name: chalk.cyan('3.') + ' 配置 ace-tool MCP', value: 'mcp' },
|
|
114
|
+
{ name: chalk.magenta('4.') + ' 配置 API 密钥', value: 'api' },
|
|
115
|
+
{ name: chalk.yellow('5.') + ' 帮助', value: 'help' },
|
|
116
|
+
{ name: chalk.red('6.') + ' 卸载工作流', value: 'uninstall' },
|
|
117
|
+
{ name: chalk.gray('7.') + ' 退出', value: 'exit' },
|
|
118
|
+
];
|
|
119
|
+
|
|
120
|
+
const { action } = await inquirer.prompt([
|
|
121
|
+
{
|
|
122
|
+
type: 'list',
|
|
123
|
+
name: 'action',
|
|
124
|
+
message: '请选择操作:',
|
|
125
|
+
choices,
|
|
126
|
+
}
|
|
127
|
+
]);
|
|
128
|
+
|
|
129
|
+
switch (action) {
|
|
130
|
+
case 'install':
|
|
75
131
|
await install();
|
|
76
132
|
break;
|
|
77
|
-
case '
|
|
78
|
-
await
|
|
133
|
+
case 'update':
|
|
134
|
+
await update();
|
|
79
135
|
break;
|
|
80
|
-
case '
|
|
136
|
+
case 'mcp':
|
|
81
137
|
await configureMCP();
|
|
82
138
|
break;
|
|
83
|
-
case '
|
|
139
|
+
case 'api':
|
|
140
|
+
await configureApiKeys();
|
|
141
|
+
break;
|
|
142
|
+
case 'help':
|
|
143
|
+
showHelp();
|
|
144
|
+
break;
|
|
145
|
+
case 'uninstall':
|
|
84
146
|
await uninstall();
|
|
85
147
|
break;
|
|
86
|
-
|
|
87
|
-
console.log('
|
|
148
|
+
case 'exit':
|
|
149
|
+
console.log(chalk.gray('再见!'));
|
|
150
|
+
process.exit(0);
|
|
88
151
|
}
|
|
89
152
|
|
|
90
|
-
|
|
153
|
+
// 返回主菜单
|
|
154
|
+
await showMainMenu();
|
|
91
155
|
}
|
|
92
156
|
|
|
157
|
+
// ==================== 安装功能 ====================
|
|
158
|
+
|
|
93
159
|
async function install() {
|
|
94
|
-
console.log('\n📦
|
|
160
|
+
console.log('\n' + chalk.cyan.bold('📦 安装工作流'));
|
|
161
|
+
console.log(chalk.gray('━'.repeat(40)) + '\n');
|
|
95
162
|
|
|
96
|
-
//
|
|
97
|
-
|
|
163
|
+
// 检查是否已安装
|
|
164
|
+
if (isInstalled()) {
|
|
165
|
+
const { confirm } = await inquirer.prompt([
|
|
166
|
+
{
|
|
167
|
+
type: 'confirm',
|
|
168
|
+
name: 'confirm',
|
|
169
|
+
message: chalk.yellow('检测到已有安装,是否覆盖?'),
|
|
170
|
+
default: false
|
|
171
|
+
}
|
|
172
|
+
]);
|
|
173
|
+
if (!confirm) {
|
|
174
|
+
console.log(chalk.gray('取消安装'));
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
console.log(chalk.blue('→') + ' 创建目录结构...');
|
|
180
|
+
[CCG_DIR, COMMANDS_DIR, AGENTS_DIR, BIN_DIR].forEach(dir => {
|
|
98
181
|
fs.mkdirSync(dir, { recursive: true });
|
|
99
182
|
});
|
|
100
183
|
|
|
101
|
-
|
|
102
|
-
console.log('复制配置文件...');
|
|
184
|
+
console.log(chalk.blue('→') + ' 复制提示词文件...');
|
|
103
185
|
copyRecursive(path.join(SRC_DIR, 'prompts'), path.join(CCG_DIR, 'prompts'));
|
|
186
|
+
const promptCount = countFiles(path.join(CCG_DIR, 'prompts', 'codex')) +
|
|
187
|
+
countFiles(path.join(CCG_DIR, 'prompts', 'gemini')) +
|
|
188
|
+
countFiles(path.join(CCG_DIR, 'prompts', 'claude'));
|
|
189
|
+
console.log(chalk.gray(` 已复制 ${promptCount} 个提示词文件`));
|
|
104
190
|
|
|
105
|
-
console.log('复制命令文件...');
|
|
191
|
+
console.log(chalk.blue('→') + ' 复制命令文件...');
|
|
106
192
|
copyRecursive(path.join(SRC_DIR, 'commands', 'ccg'), COMMANDS_DIR);
|
|
193
|
+
const commandCount = countFiles(COMMANDS_DIR);
|
|
194
|
+
console.log(chalk.gray(` 已复制 ${commandCount} 个命令文件`));
|
|
195
|
+
|
|
196
|
+
console.log(chalk.blue('→') + ' 创建 agents 目录...');
|
|
197
|
+
// 创建 agents 文件
|
|
198
|
+
createAgentFiles();
|
|
199
|
+
const agentCount = countFiles(AGENTS_DIR);
|
|
200
|
+
console.log(chalk.gray(` 已创建 ${agentCount} 个 agent 文件`));
|
|
201
|
+
|
|
202
|
+
console.log(chalk.blue('→') + ' 复制配置文件...');
|
|
203
|
+
const configSrc = path.join(SRC_DIR, 'config.toml');
|
|
204
|
+
const configDest = path.join(CCG_DIR, 'config.toml');
|
|
205
|
+
if (fs.existsSync(configSrc)) {
|
|
206
|
+
let configContent = fs.readFileSync(configSrc, 'utf8');
|
|
207
|
+
// 添加版本信息
|
|
208
|
+
if (!configContent.includes('version')) {
|
|
209
|
+
configContent = `version = "${VERSION}"\n` + configContent;
|
|
210
|
+
}
|
|
211
|
+
fs.writeFileSync(configDest, configContent);
|
|
212
|
+
} else {
|
|
213
|
+
// 创建默认配置
|
|
214
|
+
fs.writeFileSync(configDest, `version = "${VERSION}"\nlanguage = "zh-CN"\n`);
|
|
215
|
+
}
|
|
107
216
|
|
|
108
|
-
console.log('
|
|
109
|
-
fs.copyFileSync(
|
|
110
|
-
path.join(SRC_DIR, 'config.toml'),
|
|
111
|
-
path.join(CCG_DIR, 'config.toml')
|
|
112
|
-
);
|
|
113
|
-
|
|
114
|
-
// 复制 codeagent-wrapper 脚本
|
|
115
|
-
console.log('安装 codeagent-wrapper...');
|
|
217
|
+
console.log(chalk.blue('→') + ' 安装 codeagent-wrapper...');
|
|
116
218
|
const wrapperSrc = path.join(SRC_DIR, 'codeagent-wrapper.sh');
|
|
117
219
|
const wrapperDest = path.join(BIN_DIR, 'codeagent-wrapper');
|
|
118
|
-
fs.
|
|
119
|
-
|
|
220
|
+
if (fs.existsSync(wrapperSrc)) {
|
|
221
|
+
fs.copyFileSync(wrapperSrc, wrapperDest);
|
|
222
|
+
fs.chmodSync(wrapperDest, '755');
|
|
223
|
+
}
|
|
120
224
|
|
|
121
|
-
|
|
225
|
+
console.log(chalk.blue('→') + ' 处理路径变量...');
|
|
122
226
|
const homeDir = process.env.HOME;
|
|
123
227
|
const filesToUpdate = [
|
|
124
|
-
|
|
228
|
+
configDest,
|
|
125
229
|
...fs.readdirSync(COMMANDS_DIR)
|
|
126
230
|
.filter(f => f.endsWith('.md'))
|
|
127
231
|
.map(f => path.join(COMMANDS_DIR, f))
|
|
128
232
|
];
|
|
129
|
-
|
|
130
233
|
filesToUpdate.forEach(file => {
|
|
131
|
-
replaceInFile(file, {
|
|
132
|
-
'\\$HOME': homeDir
|
|
133
|
-
});
|
|
234
|
+
replaceInFile(file, { '\\$HOME': homeDir });
|
|
134
235
|
});
|
|
135
236
|
|
|
136
|
-
console.log('\n✅
|
|
237
|
+
console.log('\n' + chalk.green.bold('✅ 工作流安装完成!') + '\n');
|
|
238
|
+
|
|
239
|
+
// 显示安装摘要
|
|
240
|
+
console.log(chalk.white('安装摘要:'));
|
|
241
|
+
console.log(chalk.gray(` • 命令: ${commandCount} 个`));
|
|
242
|
+
console.log(chalk.gray(` • 提示词: ${promptCount} 个`));
|
|
243
|
+
console.log(chalk.gray(` • Agents: ${agentCount} 个`));
|
|
244
|
+
console.log(chalk.gray(` • 配置: ~/.claude/.ccg/config.toml`));
|
|
245
|
+
console.log('');
|
|
137
246
|
|
|
138
247
|
// 询问是否配置 MCP
|
|
139
|
-
const configMcp = await
|
|
140
|
-
|
|
248
|
+
const { configMcp } = await inquirer.prompt([
|
|
249
|
+
{
|
|
250
|
+
type: 'confirm',
|
|
251
|
+
name: 'configMcp',
|
|
252
|
+
message: '是否配置 ace-tool MCP?' + chalk.gray('(推荐,提供代码上下文)'),
|
|
253
|
+
default: true
|
|
254
|
+
}
|
|
255
|
+
]);
|
|
256
|
+
if (configMcp) {
|
|
141
257
|
await configureMCP();
|
|
142
258
|
}
|
|
143
259
|
|
|
144
260
|
// 询问是否配置 API
|
|
145
|
-
const configApi = await
|
|
146
|
-
|
|
261
|
+
const { configApi } = await inquirer.prompt([
|
|
262
|
+
{
|
|
263
|
+
type: 'confirm',
|
|
264
|
+
name: 'configApi',
|
|
265
|
+
message: '是否配置 API 密钥?',
|
|
266
|
+
default: false
|
|
267
|
+
}
|
|
268
|
+
]);
|
|
269
|
+
if (configApi) {
|
|
147
270
|
await configureApiKeys();
|
|
148
271
|
}
|
|
149
272
|
|
|
150
|
-
console.log('\n📖
|
|
151
|
-
console.log(' 在 Claude Code 中使用 /ccg:workflow <任务描述>');
|
|
152
|
-
console.log('
|
|
153
|
-
console.log('\n⚠️
|
|
273
|
+
console.log('\n' + chalk.cyan('📖 使用方法:'));
|
|
274
|
+
console.log(chalk.white(' 在 Claude Code 中使用 /ccg:workflow <任务描述>'));
|
|
275
|
+
console.log(chalk.white(' 查看所有命令: /ccg:<Tab>'));
|
|
276
|
+
console.log('\n' + chalk.yellow('⚠️ 请重启 Claude Code 使配置生效'));
|
|
154
277
|
}
|
|
155
278
|
|
|
156
|
-
|
|
157
|
-
console.log('\n🔧 配置 ace-tool MCP\n');
|
|
158
|
-
console.log('ace-tool 是 Augment Code 的代码上下文引擎');
|
|
159
|
-
console.log('它能让 AI 自动理解你的项目结构和代码\n');
|
|
279
|
+
// ==================== 创建 Agent 文件 ====================
|
|
160
280
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
281
|
+
function createAgentFiles() {
|
|
282
|
+
const agents = {
|
|
283
|
+
'system-integrator.md': `---
|
|
284
|
+
description: '系统集成设计师 - 为 ROS2 功能生成系统架构、节点交互和 Launch 配置设计'
|
|
285
|
+
---
|
|
286
|
+
|
|
287
|
+
# System Integrator - ROS2 系统集成设计
|
|
288
|
+
|
|
289
|
+
## 角色
|
|
290
|
+
|
|
291
|
+
你是 ROS2 系统集成设计师,负责设计上层应用架构。
|
|
292
|
+
|
|
293
|
+
## 职责
|
|
294
|
+
|
|
295
|
+
- 设计节点间通信架构
|
|
296
|
+
- 规划 Launch 文件结构
|
|
297
|
+
- 配置参数管理方案
|
|
298
|
+
- 设计 RViz 可视化配置
|
|
299
|
+
|
|
300
|
+
## 输出格式
|
|
301
|
+
|
|
302
|
+
\`\`\`markdown
|
|
303
|
+
## 系统集成设计
|
|
304
|
+
|
|
305
|
+
### 节点架构
|
|
306
|
+
### Launch 结构
|
|
307
|
+
### 参数配置
|
|
308
|
+
### 可视化配置
|
|
309
|
+
\`\`\`
|
|
310
|
+
`,
|
|
311
|
+
'planner.md': `---
|
|
312
|
+
description: '任务规划师 - 使用 WBS 方法论分解功能需求为可执行任务'
|
|
313
|
+
---
|
|
314
|
+
|
|
315
|
+
# Planner - 任务规划
|
|
316
|
+
|
|
317
|
+
## 角色
|
|
318
|
+
|
|
319
|
+
你是任务规划师,使用 WBS 方法分解需求。
|
|
320
|
+
|
|
321
|
+
## 职责
|
|
322
|
+
|
|
323
|
+
- 分解功能需求为子任务
|
|
324
|
+
- 确定任务依赖关系
|
|
325
|
+
- 估算任务复杂度
|
|
326
|
+
- 生成实施计划
|
|
327
|
+
|
|
328
|
+
## 输出格式
|
|
329
|
+
|
|
330
|
+
\`\`\`markdown
|
|
331
|
+
## 实施计划
|
|
332
|
+
|
|
333
|
+
### 任务分解
|
|
334
|
+
### 依赖关系
|
|
335
|
+
### 优先级排序
|
|
336
|
+
### 验收标准
|
|
337
|
+
\`\`\`
|
|
338
|
+
`,
|
|
339
|
+
'get-current-datetime.md': `---
|
|
340
|
+
description: '获取当前日期时间'
|
|
341
|
+
---
|
|
342
|
+
|
|
343
|
+
# Get Current Datetime
|
|
344
|
+
|
|
345
|
+
执行日期命令并返回当前时间。
|
|
346
|
+
`
|
|
347
|
+
};
|
|
348
|
+
|
|
349
|
+
for (const [filename, content] of Object.entries(agents)) {
|
|
350
|
+
fs.writeFileSync(path.join(AGENTS_DIR, filename), content);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
// ==================== 更新功能 ====================
|
|
355
|
+
|
|
356
|
+
async function update() {
|
|
357
|
+
console.log('\n' + chalk.blue.bold('🔄 检查更新'));
|
|
358
|
+
console.log(chalk.gray('━'.repeat(40)) + '\n');
|
|
359
|
+
|
|
360
|
+
if (!isInstalled()) {
|
|
361
|
+
console.log(chalk.yellow('未检测到安装,请先安装工作流'));
|
|
362
|
+
return;
|
|
169
363
|
}
|
|
170
364
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
365
|
+
const installedVersion = getInstalledVersion() || '未知';
|
|
366
|
+
console.log(chalk.gray(`当前版本: v${installedVersion}`));
|
|
367
|
+
console.log(chalk.gray(`包版本: v${VERSION}`));
|
|
368
|
+
|
|
369
|
+
console.log(chalk.blue('→') + ' 检查 npm 最新版本...');
|
|
370
|
+
const latestVersion = await checkLatestVersion();
|
|
175
371
|
|
|
176
|
-
|
|
177
|
-
|
|
372
|
+
if (latestVersion) {
|
|
373
|
+
console.log(chalk.gray(`最新版本: v${latestVersion}`));
|
|
374
|
+
|
|
375
|
+
if (latestVersion !== VERSION) {
|
|
376
|
+
console.log('\n' + chalk.yellow(`发现新版本 v${latestVersion}`));
|
|
377
|
+
console.log(chalk.gray('运行以下命令更新:'));
|
|
378
|
+
console.log(chalk.cyan(` npx ${PACKAGE_NAME}@latest`));
|
|
178
379
|
return;
|
|
179
380
|
}
|
|
180
381
|
}
|
|
181
382
|
|
|
383
|
+
if (installedVersion === VERSION) {
|
|
384
|
+
console.log('\n' + chalk.green('✓ 已是最新版本'));
|
|
385
|
+
|
|
386
|
+
const { reinstall } = await inquirer.prompt([
|
|
387
|
+
{
|
|
388
|
+
type: 'confirm',
|
|
389
|
+
name: 'reinstall',
|
|
390
|
+
message: '是否重新安装工作流文件?',
|
|
391
|
+
default: false
|
|
392
|
+
}
|
|
393
|
+
]);
|
|
394
|
+
|
|
395
|
+
if (reinstall) {
|
|
396
|
+
await install();
|
|
397
|
+
}
|
|
398
|
+
} else {
|
|
399
|
+
console.log('\n' + chalk.blue('→') + ' 更新工作流文件...');
|
|
400
|
+
await install();
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
// ==================== MCP 配置 ====================
|
|
405
|
+
|
|
406
|
+
async function configureMCP() {
|
|
407
|
+
console.log('\n' + chalk.cyan.bold('🔧 配置 ace-tool MCP'));
|
|
408
|
+
console.log(chalk.gray('━'.repeat(40)));
|
|
409
|
+
console.log(chalk.white('ace-tool 是 Augment Code 的代码上下文引擎'));
|
|
410
|
+
console.log(chalk.gray('它能让 AI 自动理解你的项目结构和代码') + '\n');
|
|
411
|
+
|
|
412
|
+
const { action } = await inquirer.prompt([
|
|
413
|
+
{
|
|
414
|
+
type: 'list',
|
|
415
|
+
name: 'action',
|
|
416
|
+
message: '请选择操作:',
|
|
417
|
+
choices: [
|
|
418
|
+
{ name: chalk.green('安装/更新 ace-tool') + chalk.gray(' (Node.js 版本)'), value: 'ace-tool' },
|
|
419
|
+
{ name: chalk.green('安装/更新 ace-tool-rs') + chalk.gray(' (Rust 版本,推荐)'), value: 'ace-tool-rs' },
|
|
420
|
+
{ name: chalk.red('卸载 ace-tool MCP 配置'), value: 'uninstall' },
|
|
421
|
+
{ name: chalk.gray('返回'), value: 'back' },
|
|
422
|
+
]
|
|
423
|
+
}
|
|
424
|
+
]);
|
|
425
|
+
|
|
426
|
+
if (action === 'back') return;
|
|
427
|
+
|
|
428
|
+
if (action === 'uninstall') {
|
|
429
|
+
await uninstallMCP();
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
const pkg = action;
|
|
434
|
+
const pkgName = pkg === 'ace-tool-rs' ? 'ace-tool-rs (Rust)' : 'ace-tool (Node.js)';
|
|
435
|
+
|
|
436
|
+
console.log('\n' + chalk.blue(`📦 配置 ${pkgName}`) + '\n');
|
|
437
|
+
|
|
438
|
+
console.log(chalk.white('获取 Token 的方式:'));
|
|
439
|
+
console.log(chalk.gray(' • 官方服务: https://augmentcode.com/ 注册获取'));
|
|
440
|
+
console.log(chalk.gray(' • 中转服务: 使用第三方中转(需要 Base URL)') + '\n');
|
|
441
|
+
|
|
442
|
+
const { baseUrl, token } = await inquirer.prompt([
|
|
443
|
+
{
|
|
444
|
+
type: 'input',
|
|
445
|
+
name: 'baseUrl',
|
|
446
|
+
message: 'Base URL' + chalk.gray(' (使用官方服务请留空):'),
|
|
447
|
+
default: ''
|
|
448
|
+
},
|
|
449
|
+
{
|
|
450
|
+
type: 'password',
|
|
451
|
+
name: 'token',
|
|
452
|
+
message: 'Token' + chalk.red(' (必填):'),
|
|
453
|
+
mask: '*',
|
|
454
|
+
validate: input => input.trim() ? true : 'Token 不能为空'
|
|
455
|
+
}
|
|
456
|
+
]);
|
|
457
|
+
|
|
458
|
+
// 构建 MCP 配置
|
|
459
|
+
const args = [pkg, 'mcp'];
|
|
460
|
+
if (baseUrl.trim()) {
|
|
461
|
+
args.push('--base-url', baseUrl.trim());
|
|
462
|
+
}
|
|
463
|
+
args.push('--token', token.trim());
|
|
464
|
+
|
|
465
|
+
const mcpServerConfig = {
|
|
466
|
+
command: 'npx',
|
|
467
|
+
args: args,
|
|
468
|
+
env: pkg === 'ace-tool-rs' ? { RUST_LOG: 'info' } : {}
|
|
469
|
+
};
|
|
470
|
+
|
|
182
471
|
// 读取或创建 MCP 配置
|
|
183
472
|
let mcpConfig = {};
|
|
184
473
|
if (fs.existsSync(MCP_CONFIG_PATH)) {
|
|
185
474
|
try {
|
|
186
475
|
mcpConfig = JSON.parse(fs.readFileSync(MCP_CONFIG_PATH, 'utf8'));
|
|
187
|
-
|
|
476
|
+
|
|
477
|
+
// 备份现有配置
|
|
478
|
+
const backupDir = path.join(CLAUDE_DIR, 'backup');
|
|
479
|
+
fs.mkdirSync(backupDir, { recursive: true });
|
|
480
|
+
const backupPath = path.join(backupDir, `mcp_servers_${Date.now()}.json`);
|
|
481
|
+
fs.writeFileSync(backupPath, JSON.stringify(mcpConfig, null, 2));
|
|
482
|
+
console.log(chalk.gray(`已备份配置到: ${backupPath}`));
|
|
188
483
|
} catch {
|
|
189
484
|
mcpConfig = {};
|
|
190
485
|
}
|
|
191
486
|
}
|
|
192
487
|
|
|
193
488
|
// 添加 ace-tool 配置
|
|
194
|
-
mcpConfig['ace-tool'] =
|
|
195
|
-
command: 'ace-tool',
|
|
196
|
-
args: ['mcp'],
|
|
197
|
-
env: {}
|
|
198
|
-
};
|
|
489
|
+
mcpConfig['ace-tool'] = mcpServerConfig;
|
|
199
490
|
|
|
200
491
|
// 写入配置
|
|
201
492
|
fs.mkdirSync(CLAUDE_DIR, { recursive: true });
|
|
202
493
|
fs.writeFileSync(MCP_CONFIG_PATH, JSON.stringify(mcpConfig, null, 2));
|
|
203
494
|
|
|
204
|
-
console.log('✅ MCP
|
|
205
|
-
console.log('
|
|
206
|
-
console.log(
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
console.log('
|
|
210
|
-
console.log(
|
|
211
|
-
console.log('
|
|
212
|
-
console.log('
|
|
213
|
-
console.log(' 在 workflow 中自动调用 mcp__ace-tool__search_context');
|
|
214
|
-
console.log(' 或手动调用 mcp__ace-tool__enhance_prompt');
|
|
495
|
+
console.log('\n' + chalk.green.bold('✅ MCP 配置已写入') + '\n');
|
|
496
|
+
console.log(chalk.white('配置文件: ~/.claude/mcp_servers.json'));
|
|
497
|
+
console.log(chalk.gray('配置内容:'));
|
|
498
|
+
console.log(chalk.gray(JSON.stringify(mcpServerConfig, null, 2)));
|
|
499
|
+
|
|
500
|
+
console.log('\n' + chalk.cyan('📌 说明:'));
|
|
501
|
+
console.log(chalk.white(` • 使用 npx ${pkg} 自动下载运行`));
|
|
502
|
+
console.log(chalk.white(' • 首次运行会自动下载包'));
|
|
503
|
+
console.log(chalk.white(' • 重启 Claude Code 使 MCP 生效'));
|
|
215
504
|
}
|
|
216
505
|
|
|
217
|
-
async function
|
|
218
|
-
|
|
506
|
+
async function uninstallMCP() {
|
|
507
|
+
if (!fs.existsSync(MCP_CONFIG_PATH)) {
|
|
508
|
+
console.log(chalk.yellow('未找到 MCP 配置文件'));
|
|
509
|
+
return;
|
|
510
|
+
}
|
|
219
511
|
|
|
220
|
-
const
|
|
221
|
-
|
|
222
|
-
|
|
512
|
+
const { confirm } = await inquirer.prompt([
|
|
513
|
+
{
|
|
514
|
+
type: 'confirm',
|
|
515
|
+
name: 'confirm',
|
|
516
|
+
message: chalk.red('确定要移除 ace-tool MCP 配置吗?'),
|
|
517
|
+
default: false
|
|
518
|
+
}
|
|
519
|
+
]);
|
|
520
|
+
|
|
521
|
+
if (!confirm) {
|
|
522
|
+
console.log(chalk.gray('取消卸载'));
|
|
523
|
+
return;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
try {
|
|
527
|
+
let mcpConfig = JSON.parse(fs.readFileSync(MCP_CONFIG_PATH, 'utf8'));
|
|
528
|
+
|
|
529
|
+
if (!mcpConfig['ace-tool']) {
|
|
530
|
+
console.log(chalk.yellow('MCP 配置中没有 ace-tool'));
|
|
531
|
+
return;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
delete mcpConfig['ace-tool'];
|
|
535
|
+
|
|
536
|
+
if (Object.keys(mcpConfig).length === 0) {
|
|
537
|
+
fs.unlinkSync(MCP_CONFIG_PATH);
|
|
538
|
+
console.log(chalk.green('✅ 已删除: ~/.claude/mcp_servers.json'));
|
|
539
|
+
} else {
|
|
540
|
+
fs.writeFileSync(MCP_CONFIG_PATH, JSON.stringify(mcpConfig, null, 2));
|
|
541
|
+
console.log(chalk.green('✅ 已从 MCP 配置中移除 ace-tool'));
|
|
542
|
+
}
|
|
543
|
+
} catch (e) {
|
|
544
|
+
console.log(chalk.red('❌ 移除失败:'), e.message);
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
// ==================== API 密钥配置 ====================
|
|
549
|
+
|
|
550
|
+
async function configureApiKeys() {
|
|
551
|
+
console.log('\n' + chalk.magenta.bold('🔑 配置 API 密钥'));
|
|
552
|
+
console.log(chalk.gray('━'.repeat(40)) + '\n');
|
|
553
|
+
|
|
554
|
+
const { geminiKey, geminiBaseUrl, codexKey } = await inquirer.prompt([
|
|
555
|
+
{
|
|
556
|
+
type: 'password',
|
|
557
|
+
name: 'geminiKey',
|
|
558
|
+
message: 'Gemini API Key' + chalk.gray(' (留空跳过):'),
|
|
559
|
+
mask: '*'
|
|
560
|
+
},
|
|
561
|
+
{
|
|
562
|
+
type: 'input',
|
|
563
|
+
name: 'geminiBaseUrl',
|
|
564
|
+
message: 'Gemini Base URL' + chalk.gray(' (留空使用官方):'),
|
|
565
|
+
when: answers => answers.geminiKey
|
|
566
|
+
},
|
|
567
|
+
{
|
|
568
|
+
type: 'password',
|
|
569
|
+
name: 'codexKey',
|
|
570
|
+
message: 'Codex API Key' + chalk.gray(' (留空跳过):'),
|
|
571
|
+
mask: '*'
|
|
572
|
+
}
|
|
573
|
+
]);
|
|
223
574
|
|
|
224
575
|
// 检测 shell 配置文件
|
|
225
576
|
const shellRc = fs.existsSync(path.join(process.env.HOME, '.zshrc'))
|
|
@@ -238,6 +589,7 @@ async function configureApiKeys() {
|
|
|
238
589
|
}
|
|
239
590
|
if (codexKey) {
|
|
240
591
|
envVars.push(`export CODEX_API_KEY="${codexKey}"`);
|
|
592
|
+
envVars.push(`export OPENAI_API_KEY="${codexKey}"`);
|
|
241
593
|
}
|
|
242
594
|
|
|
243
595
|
if (envVars.length > 0) {
|
|
@@ -245,51 +597,129 @@ async function configureApiKeys() {
|
|
|
245
597
|
if (!rcContent.includes(marker)) {
|
|
246
598
|
rcContent += `\n${marker}\n${envVars.join('\n')}\n`;
|
|
247
599
|
fs.writeFileSync(rcPath, rcContent);
|
|
248
|
-
console.log(
|
|
249
|
-
console.log(` 请运行: source ~/${shellRc}`);
|
|
600
|
+
console.log('\n' + chalk.green(`✅ 已添加到 ~/${shellRc}`));
|
|
601
|
+
console.log(chalk.yellow(` 请运行: source ~/${shellRc}`));
|
|
250
602
|
} else {
|
|
251
|
-
console.log(
|
|
603
|
+
console.log('\n' + chalk.yellow(`⚠️ ~/${shellRc} 中已存在配置,请手动更新`));
|
|
252
604
|
}
|
|
605
|
+
} else {
|
|
606
|
+
console.log(chalk.gray('未配置任何密钥'));
|
|
253
607
|
}
|
|
254
608
|
}
|
|
255
609
|
|
|
610
|
+
// ==================== 帮助 ====================
|
|
611
|
+
|
|
612
|
+
function showHelp() {
|
|
613
|
+
console.log('\n' + chalk.yellow.bold('📖 帮助'));
|
|
614
|
+
console.log(chalk.gray('━'.repeat(40)) + '\n');
|
|
615
|
+
|
|
616
|
+
console.log(chalk.white.bold('可用命令:'));
|
|
617
|
+
console.log(chalk.cyan(' /ccg:workflow') + chalk.gray(' - 完整 7 阶段开发工作流'));
|
|
618
|
+
console.log(chalk.cyan(' /ccg:plan') + chalk.gray(' - 多模型协作规划'));
|
|
619
|
+
console.log(chalk.cyan(' /ccg:execute') + chalk.gray(' - 执行实施计划'));
|
|
620
|
+
console.log(chalk.cyan(' /ccg:feat') + chalk.gray(' - 智能功能开发'));
|
|
621
|
+
console.log(chalk.cyan(' /ccg:frontend') + chalk.gray(' - 上层应用开发 (Gemini 主导)'));
|
|
622
|
+
console.log(chalk.cyan(' /ccg:backend') + chalk.gray(' - 底层控制开发 (Codex 主导)'));
|
|
623
|
+
console.log(chalk.cyan(' /ccg:analyze') + chalk.gray(' - 多模型技术分析'));
|
|
624
|
+
console.log(chalk.cyan(' /ccg:review') + chalk.gray(' - 多模型代码审查'));
|
|
625
|
+
console.log(chalk.cyan(' /ccg:test') + chalk.gray(' - 测试生成'));
|
|
626
|
+
console.log(chalk.cyan(' /ccg:debug') + chalk.gray(' - 问题诊断'));
|
|
627
|
+
console.log(chalk.cyan(' /ccg:optimize') + chalk.gray(' - 性能优化'));
|
|
628
|
+
console.log(chalk.cyan(' /ccg:commit') + chalk.gray(' - 智能 Git 提交'));
|
|
629
|
+
console.log(chalk.cyan(' /ccg:rollback') + chalk.gray(' - Git 回滚'));
|
|
630
|
+
|
|
631
|
+
console.log('\n' + chalk.white.bold('智能路由:'));
|
|
632
|
+
console.log(chalk.gray(' • 控制算法、C++、硬件驱动 → Codex'));
|
|
633
|
+
console.log(chalk.gray(' • Launch、Python、RViz、配置 → Gemini'));
|
|
634
|
+
|
|
635
|
+
console.log('\n' + chalk.white.bold('更多信息:'));
|
|
636
|
+
console.log(chalk.gray(' https://github.com/GuYu-001/ccg-ros2-workflow'));
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
// ==================== 卸载功能 ====================
|
|
640
|
+
|
|
256
641
|
async function uninstall() {
|
|
257
|
-
console.log('\n🗑️
|
|
642
|
+
console.log('\n' + chalk.red.bold('🗑️ 卸载工作流'));
|
|
643
|
+
console.log(chalk.gray('━'.repeat(40)) + '\n');
|
|
258
644
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
645
|
+
if (!isInstalled()) {
|
|
646
|
+
console.log(chalk.yellow('未检测到安装'));
|
|
647
|
+
return;
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
// 显示将要删除的内容
|
|
651
|
+
console.log(chalk.white('将要删除:'));
|
|
652
|
+
|
|
653
|
+
const commandCount = countFiles(COMMANDS_DIR);
|
|
654
|
+
const agentCount = countFiles(AGENTS_DIR);
|
|
655
|
+
const promptCount = fs.existsSync(path.join(CCG_DIR, 'prompts'))
|
|
656
|
+
? countFiles(path.join(CCG_DIR, 'prompts', 'codex')) +
|
|
657
|
+
countFiles(path.join(CCG_DIR, 'prompts', 'gemini')) +
|
|
658
|
+
countFiles(path.join(CCG_DIR, 'prompts', 'claude'))
|
|
659
|
+
: 0;
|
|
660
|
+
|
|
661
|
+
console.log(chalk.gray(` • ${commandCount} 个命令文件`));
|
|
662
|
+
console.log(chalk.gray(` • ${agentCount} 个 agent 文件`));
|
|
663
|
+
console.log(chalk.gray(` • ${promptCount} 个提示词文件`));
|
|
664
|
+
console.log(chalk.gray(` • 配置文件`));
|
|
665
|
+
console.log(chalk.gray(` • codeagent-wrapper`));
|
|
666
|
+
console.log('');
|
|
667
|
+
|
|
668
|
+
const { confirm } = await inquirer.prompt([
|
|
669
|
+
{
|
|
670
|
+
type: 'confirm',
|
|
671
|
+
name: 'confirm',
|
|
672
|
+
message: chalk.red('确定要卸载吗?这将删除所有配置文件'),
|
|
673
|
+
default: false
|
|
674
|
+
}
|
|
675
|
+
]);
|
|
676
|
+
|
|
677
|
+
if (!confirm) {
|
|
678
|
+
console.log(chalk.gray('取消卸载'));
|
|
262
679
|
return;
|
|
263
680
|
}
|
|
264
681
|
|
|
265
682
|
// 删除目录
|
|
266
|
-
[CCG_DIR, COMMANDS_DIR]
|
|
683
|
+
const dirsToDelete = [CCG_DIR, COMMANDS_DIR, AGENTS_DIR];
|
|
684
|
+
let deletedCount = 0;
|
|
685
|
+
|
|
686
|
+
for (const dir of dirsToDelete) {
|
|
267
687
|
if (fs.existsSync(dir)) {
|
|
268
688
|
fs.rmSync(dir, { recursive: true });
|
|
269
|
-
console.log(`已删除: ${dir}`);
|
|
689
|
+
console.log(chalk.gray(`已删除: ${dir}`));
|
|
690
|
+
deletedCount++;
|
|
270
691
|
}
|
|
271
|
-
}
|
|
692
|
+
}
|
|
272
693
|
|
|
273
694
|
// 删除 codeagent-wrapper
|
|
274
695
|
const wrapperPath = path.join(BIN_DIR, 'codeagent-wrapper');
|
|
275
696
|
if (fs.existsSync(wrapperPath)) {
|
|
276
697
|
fs.unlinkSync(wrapperPath);
|
|
277
|
-
console.log(`已删除: ${wrapperPath}`);
|
|
698
|
+
console.log(chalk.gray(`已删除: ${wrapperPath}`));
|
|
699
|
+
deletedCount++;
|
|
278
700
|
}
|
|
279
701
|
|
|
280
702
|
// 询问是否删除 MCP 配置
|
|
281
703
|
if (fs.existsSync(MCP_CONFIG_PATH)) {
|
|
282
|
-
const removeMcp = await
|
|
283
|
-
|
|
704
|
+
const { removeMcp } = await inquirer.prompt([
|
|
705
|
+
{
|
|
706
|
+
type: 'confirm',
|
|
707
|
+
name: 'removeMcp',
|
|
708
|
+
message: '是否同时删除 ace-tool MCP 配置?',
|
|
709
|
+
default: false
|
|
710
|
+
}
|
|
711
|
+
]);
|
|
712
|
+
|
|
713
|
+
if (removeMcp) {
|
|
284
714
|
try {
|
|
285
715
|
let mcpConfig = JSON.parse(fs.readFileSync(MCP_CONFIG_PATH, 'utf8'));
|
|
286
716
|
delete mcpConfig['ace-tool'];
|
|
287
717
|
if (Object.keys(mcpConfig).length === 0) {
|
|
288
718
|
fs.unlinkSync(MCP_CONFIG_PATH);
|
|
289
|
-
console.log('已删除: ~/.claude/mcp_servers.json');
|
|
719
|
+
console.log(chalk.gray('已删除: ~/.claude/mcp_servers.json'));
|
|
290
720
|
} else {
|
|
291
721
|
fs.writeFileSync(MCP_CONFIG_PATH, JSON.stringify(mcpConfig, null, 2));
|
|
292
|
-
console.log('已从 MCP 配置中移除 ace-tool');
|
|
722
|
+
console.log(chalk.gray('已从 MCP 配置中移除 ace-tool'));
|
|
293
723
|
}
|
|
294
724
|
} catch {
|
|
295
725
|
// ignore
|
|
@@ -297,8 +727,18 @@ async function uninstall() {
|
|
|
297
727
|
}
|
|
298
728
|
}
|
|
299
729
|
|
|
300
|
-
console.log('\n✅ 卸载完成');
|
|
301
|
-
console.log('注意: 环境变量需要手动从 ~/.zshrc 或 ~/.bashrc 中删除');
|
|
730
|
+
console.log('\n' + chalk.green.bold('✅ 卸载完成'));
|
|
731
|
+
console.log(chalk.yellow('注意: 环境变量需要手动从 ~/.zshrc 或 ~/.bashrc 中删除'));
|
|
302
732
|
}
|
|
303
733
|
|
|
304
|
-
|
|
734
|
+
// ==================== 主程序 ====================
|
|
735
|
+
|
|
736
|
+
async function main() {
|
|
737
|
+
await loadDependencies();
|
|
738
|
+
await showMainMenu();
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
main().catch(err => {
|
|
742
|
+
console.error(chalk.red('错误:'), err.message);
|
|
743
|
+
process.exit(1);
|
|
744
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ccg-ros2-workflow",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "ROS2 Multi-model Collaborative Development Workflow - Codex (Low-level) + Gemini (High-level) + Claude (Orchestration)",
|
|
5
5
|
"main": "bin/cli.js",
|
|
6
6
|
"bin": {
|
|
@@ -31,5 +31,9 @@
|
|
|
31
31
|
"files": [
|
|
32
32
|
"bin/",
|
|
33
33
|
"src/"
|
|
34
|
-
]
|
|
34
|
+
],
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"inquirer": "^8.2.6",
|
|
37
|
+
"chalk": "^4.1.2"
|
|
38
|
+
}
|
|
35
39
|
}
|