ai-engineering-init 1.6.0 → 1.7.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/.claude/agents/code-reviewer.md +3 -130
- package/.claude/hooks/skill-forced-eval.js +2 -0
- package/.claude/hooks/stop.js +24 -1
- package/.claude/skills/codex-code-review/SKILL.md +327 -0
- package/.claude/skills/leniu-report-customization/SKILL.md +82 -2
- package/.claude/skills/leniu-report-standard-customization/SKILL.md +65 -2
- package/.claude/skills/loki-log-query/SKILL.md +400 -0
- package/.claude/skills/mysql-debug/SKILL.md +58 -22
- package/.claude/skills/skill-creator/LICENSE.txt +202 -0
- package/.claude/skills/skill-creator/SKILL.md +479 -0
- package/.claude/skills/skill-creator/agents/analyzer.md +274 -0
- package/.claude/skills/skill-creator/agents/comparator.md +202 -0
- package/.claude/skills/skill-creator/agents/grader.md +223 -0
- package/.claude/skills/skill-creator/assets/eval_review.html +146 -0
- package/.claude/skills/skill-creator/eval-viewer/generate_review.py +471 -0
- package/.claude/skills/skill-creator/eval-viewer/viewer.html +1325 -0
- package/.claude/skills/skill-creator/references/schemas.md +430 -0
- package/.claude/skills/skill-creator/scripts/__init__.py +0 -0
- package/.claude/skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
- package/.claude/skills/skill-creator/scripts/generate_report.py +326 -0
- package/.claude/skills/skill-creator/scripts/improve_description.py +248 -0
- package/.claude/skills/skill-creator/scripts/package_skill.py +136 -0
- package/.claude/skills/skill-creator/scripts/quick_validate.py +103 -0
- package/.claude/skills/skill-creator/scripts/run_eval.py +310 -0
- package/.claude/skills/skill-creator/scripts/run_loop.py +332 -0
- package/.claude/skills/skill-creator/scripts/utils.py +47 -0
- package/.claude/skills/sync-back-merge/SKILL.md +66 -0
- package/.claude/skills/yunxiao-task-management/SKILL.md +489 -0
- package/.codex/skills/leniu-report-customization/SKILL.md +82 -2
- package/.codex/skills/leniu-report-standard-customization/SKILL.md +65 -2
- package/.codex/skills/loki-log-query/SKILL.md +400 -0
- package/.codex/skills/loki-log-query/environments.json +45 -0
- package/.codex/skills/mysql-debug/SKILL.md +58 -22
- package/.codex/skills/skill-creator/LICENSE.txt +202 -0
- package/.codex/skills/skill-creator/SKILL.md +479 -0
- package/.codex/skills/skill-creator/agents/analyzer.md +274 -0
- package/.codex/skills/skill-creator/agents/comparator.md +202 -0
- package/.codex/skills/skill-creator/agents/grader.md +223 -0
- package/.codex/skills/skill-creator/assets/eval_review.html +146 -0
- package/.codex/skills/skill-creator/eval-viewer/generate_review.py +471 -0
- package/.codex/skills/skill-creator/eval-viewer/viewer.html +1325 -0
- package/.codex/skills/skill-creator/references/schemas.md +430 -0
- package/.codex/skills/skill-creator/scripts/__init__.py +0 -0
- package/.codex/skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
- package/.codex/skills/skill-creator/scripts/generate_report.py +326 -0
- package/.codex/skills/skill-creator/scripts/improve_description.py +248 -0
- package/.codex/skills/skill-creator/scripts/package_skill.py +136 -0
- package/.codex/skills/skill-creator/scripts/quick_validate.py +103 -0
- package/.codex/skills/skill-creator/scripts/run_eval.py +310 -0
- package/.codex/skills/skill-creator/scripts/run_loop.py +332 -0
- package/.codex/skills/skill-creator/scripts/utils.py +47 -0
- package/.codex/skills/sync-back-merge/SKILL.md +66 -0
- package/.codex/skills/yunxiao-task-management/SKILL.md +489 -0
- package/.cursor/hooks/stop.js +23 -1
- package/.cursor/skills/leniu-report-customization/SKILL.md +82 -2
- package/.cursor/skills/leniu-report-standard-customization/SKILL.md +65 -2
- package/.cursor/skills/loki-log-query/SKILL.md +400 -0
- package/.cursor/skills/loki-log-query/environments.json +45 -0
- package/.cursor/skills/mysql-debug/SKILL.md +58 -22
- package/.cursor/skills/skill-creator/LICENSE.txt +202 -0
- package/.cursor/skills/skill-creator/SKILL.md +479 -0
- package/.cursor/skills/skill-creator/agents/analyzer.md +274 -0
- package/.cursor/skills/skill-creator/agents/comparator.md +202 -0
- package/.cursor/skills/skill-creator/agents/grader.md +223 -0
- package/.cursor/skills/skill-creator/assets/eval_review.html +146 -0
- package/.cursor/skills/skill-creator/eval-viewer/generate_review.py +471 -0
- package/.cursor/skills/skill-creator/eval-viewer/viewer.html +1325 -0
- package/.cursor/skills/skill-creator/references/schemas.md +430 -0
- package/.cursor/skills/skill-creator/scripts/__init__.py +0 -0
- package/.cursor/skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
- package/.cursor/skills/skill-creator/scripts/generate_report.py +326 -0
- package/.cursor/skills/skill-creator/scripts/improve_description.py +248 -0
- package/.cursor/skills/skill-creator/scripts/package_skill.py +136 -0
- package/.cursor/skills/skill-creator/scripts/quick_validate.py +103 -0
- package/.cursor/skills/skill-creator/scripts/run_eval.py +310 -0
- package/.cursor/skills/skill-creator/scripts/run_loop.py +332 -0
- package/.cursor/skills/skill-creator/scripts/utils.py +47 -0
- package/.cursor/skills/sync-back-merge/SKILL.md +66 -0
- package/.cursor/skills/yunxiao-task-management/SKILL.md +489 -0
- package/bin/index.js +606 -24
- package/package.json +1 -1
- package/src/platform-map.json +4 -0
- package/src/skills/codex-code-review/SKILL.md +261 -69
- package/src/skills/leniu-report-customization/SKILL.md +82 -2
- package/src/skills/leniu-report-standard-customization/SKILL.md +65 -2
- package/src/skills/loki-log-query/SKILL.md +400 -0
- package/src/skills/loki-log-query/environments.json +45 -0
- package/src/skills/mysql-debug/SKILL.md +58 -22
- package/src/skills/skill-creator/LICENSE.txt +202 -0
- package/src/skills/skill-creator/SKILL.md +479 -0
- package/src/skills/skill-creator/agents/analyzer.md +274 -0
- package/src/skills/skill-creator/agents/comparator.md +202 -0
- package/src/skills/skill-creator/agents/grader.md +223 -0
- package/src/skills/skill-creator/assets/eval_review.html +146 -0
- package/src/skills/skill-creator/eval-viewer/generate_review.py +471 -0
- package/src/skills/skill-creator/eval-viewer/viewer.html +1325 -0
- package/src/skills/skill-creator/references/schemas.md +430 -0
- package/src/skills/skill-creator/scripts/__init__.py +0 -0
- package/src/skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
- package/src/skills/skill-creator/scripts/generate_report.py +326 -0
- package/src/skills/skill-creator/scripts/improve_description.py +248 -0
- package/src/skills/skill-creator/scripts/package_skill.py +136 -0
- package/src/skills/skill-creator/scripts/quick_validate.py +103 -0
- package/src/skills/skill-creator/scripts/run_eval.py +310 -0
- package/src/skills/skill-creator/scripts/run_loop.py +332 -0
- package/src/skills/skill-creator/scripts/utils.py +47 -0
- package/src/skills/sync-back-merge/SKILL.md +66 -0
- package/src/skills/yunxiao-task-management/SKILL.md +489 -0
package/bin/index.js
CHANGED
|
@@ -62,9 +62,18 @@ for (let i = 0; i < args.length; i++) {
|
|
|
62
62
|
case 'global':
|
|
63
63
|
command = 'global';
|
|
64
64
|
break;
|
|
65
|
+
case 'init':
|
|
66
|
+
command = 'init';
|
|
67
|
+
break;
|
|
65
68
|
case 'sync-back':
|
|
66
69
|
command = 'sync-back';
|
|
67
70
|
break;
|
|
71
|
+
case 'config':
|
|
72
|
+
command = 'config';
|
|
73
|
+
break;
|
|
74
|
+
case 'mcp':
|
|
75
|
+
command = 'mcp';
|
|
76
|
+
break;
|
|
68
77
|
case '--tool': case '-t':
|
|
69
78
|
if (i + 1 >= args.length || args[i + 1].startsWith('-')) {
|
|
70
79
|
console.error(fmt('red', `错误:${arg} 需要一个值(claude | cursor | codex | all)`));
|
|
@@ -109,10 +118,13 @@ for (let i = 0; i < args.length; i++) {
|
|
|
109
118
|
function printHelp() {
|
|
110
119
|
console.log(`用法: ${fmt('bold', 'npx ai-engineering-init')} [命令] [选项]\n`);
|
|
111
120
|
console.log('命令:');
|
|
112
|
-
console.log(` ${fmt('bold', '
|
|
121
|
+
console.log(` ${fmt('bold', 'init')} 交互式初始化(安装到当前项目目录)`);
|
|
113
122
|
console.log(` ${fmt('bold', 'update')} 更新已安装的框架文件(跳过用户自定义文件)`);
|
|
114
123
|
console.log(` ${fmt('bold', 'global')} 全局安装到 ~/.claude / ~/.cursor 等,对所有项目生效`);
|
|
115
|
-
console.log(` ${fmt('bold', 'sync-back')} 对比本地技能修改,生成 diff 或提交 GitHub Issue
|
|
124
|
+
console.log(` ${fmt('bold', 'sync-back')} 对比本地技能修改,生成 diff 或提交 GitHub Issue`);
|
|
125
|
+
console.log(` ${fmt('bold', 'config')} 初始化数据库配置文件(.claude/mysql-config.json)`);
|
|
126
|
+
console.log(` ${fmt('bold', 'mcp')} MCP 服务器管理(安装/卸载/状态检查)\n`);
|
|
127
|
+
console.log(`无命令时显示交互式主菜单。\n`);
|
|
116
128
|
console.log('选项:');
|
|
117
129
|
console.log(' --tool, -t <工具> 指定工具: claude | cursor | codex | all');
|
|
118
130
|
console.log(' --dir, -d <目录> 目标目录(默认:当前目录,仅 init/update 有效)');
|
|
@@ -1103,39 +1115,536 @@ function runSyncBack(selectedTool, selectedSkill, doSubmit) {
|
|
|
1103
1115
|
console.log('');
|
|
1104
1116
|
}
|
|
1105
1117
|
|
|
1106
|
-
// ──
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
}
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1118
|
+
// ── 数据库配置初始化 ──────────────────────────────────────────────────────
|
|
1119
|
+
function runConfig() {
|
|
1120
|
+
if (!process.stdin.isTTY) {
|
|
1121
|
+
console.error(fmt('red', '错误:config 命令需要交互式终端'));
|
|
1122
|
+
process.exit(1);
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1125
|
+
const configPath = path.join(targetDir, '.claude', 'mysql-config.json');
|
|
1126
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
1127
|
+
|
|
1128
|
+
const ask = (question) => new Promise((resolve) => {
|
|
1129
|
+
rl.question(question, (answer) => resolve(answer.trim()));
|
|
1130
|
+
});
|
|
1131
|
+
|
|
1132
|
+
const ENV_DEFAULTS = {
|
|
1133
|
+
local: { host: '127.0.0.1', user: 'root', desc: '本地开发环境' },
|
|
1134
|
+
dev: { host: '', user: '', desc: '开发测试环境' },
|
|
1135
|
+
test: { host: '', user: '', desc: '测试环境' },
|
|
1136
|
+
prod: { host: '', user: '', desc: '生产环境' },
|
|
1137
|
+
};
|
|
1138
|
+
|
|
1139
|
+
(async () => {
|
|
1140
|
+
try {
|
|
1141
|
+
// 1. 检测已有配置
|
|
1142
|
+
if (fs.existsSync(configPath)) {
|
|
1143
|
+
console.log(fmt('yellow', `⚠ 配置文件已存在:${configPath}`));
|
|
1144
|
+
const overwrite = await ask(fmt('bold', '是否重新配置?[y/N]: '));
|
|
1145
|
+
if (overwrite.toLowerCase() !== 'y') {
|
|
1146
|
+
console.log('已取消。');
|
|
1147
|
+
rl.close();
|
|
1148
|
+
return;
|
|
1149
|
+
}
|
|
1150
|
+
console.log('');
|
|
1151
|
+
}
|
|
1152
|
+
|
|
1153
|
+
// 2. 选择环境
|
|
1154
|
+
console.log(fmt('cyan', '请选择要配置的数据库环境(多选,用逗号分隔):'));
|
|
1155
|
+
console.log('');
|
|
1156
|
+
console.log(` ${fmt('bold', '1')}) local — 本地开发环境`);
|
|
1157
|
+
console.log(` ${fmt('bold', '2')}) dev — 开发测试环境`);
|
|
1158
|
+
console.log(` ${fmt('bold', '3')}) test — 测试环境`);
|
|
1159
|
+
console.log(` ${fmt('bold', '4')}) prod — 生产环境`);
|
|
1160
|
+
console.log('');
|
|
1161
|
+
const envAnswer = await ask(fmt('bold', '请输入选项(如 1,2 或 1-3): '));
|
|
1162
|
+
|
|
1163
|
+
// 解析选择
|
|
1164
|
+
const envNames = ['local', 'dev', 'test', 'prod'];
|
|
1165
|
+
const selected = new Set();
|
|
1166
|
+
for (const part of envAnswer.split(',')) {
|
|
1167
|
+
const trimmed = part.trim();
|
|
1168
|
+
const rangeMatch = trimmed.match(/^(\d)-(\d)$/);
|
|
1169
|
+
if (rangeMatch) {
|
|
1170
|
+
const start = parseInt(rangeMatch[1], 10);
|
|
1171
|
+
const end = parseInt(rangeMatch[2], 10);
|
|
1172
|
+
for (let n = start; n <= end; n++) {
|
|
1173
|
+
if (n >= 1 && n <= 4) selected.add(envNames[n - 1]);
|
|
1174
|
+
}
|
|
1175
|
+
} else {
|
|
1176
|
+
const n = parseInt(trimmed, 10);
|
|
1177
|
+
if (n >= 1 && n <= 4) selected.add(envNames[n - 1]);
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
|
|
1181
|
+
const selectedEnvs = [...selected];
|
|
1182
|
+
if (selectedEnvs.length === 0) {
|
|
1183
|
+
console.error(fmt('red', '未选择任何环境,退出。'));
|
|
1184
|
+
rl.close();
|
|
1185
|
+
process.exit(1);
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
console.log('');
|
|
1189
|
+
console.log(fmt('green', `已选择环境:${selectedEnvs.join(', ')}`));
|
|
1190
|
+
console.log('');
|
|
1191
|
+
|
|
1192
|
+
// 3. 收集每个环境的配置
|
|
1193
|
+
const environments = {};
|
|
1194
|
+
for (const env of selectedEnvs) {
|
|
1195
|
+
const defaults = ENV_DEFAULTS[env];
|
|
1196
|
+
console.log(fmt('cyan', `── ${env} 环境配置 ──`));
|
|
1197
|
+
|
|
1198
|
+
const host = await ask(` host [${defaults.host || '无默认'}]: `) || defaults.host;
|
|
1199
|
+
const port = await ask(' port [3306]: ') || '3306';
|
|
1200
|
+
const user = await ask(` user [${defaults.user || '无默认'}]: `) || defaults.user;
|
|
1201
|
+
const password = await ask(' password: ');
|
|
1202
|
+
const desc = await ask(` 描述 [${defaults.desc}]: `) || defaults.desc;
|
|
1203
|
+
console.log('');
|
|
1204
|
+
|
|
1205
|
+
if (!host) {
|
|
1206
|
+
console.error(fmt('red', `错误:${env} 环境的 host 不能为空`));
|
|
1207
|
+
rl.close();
|
|
1208
|
+
process.exit(1);
|
|
1209
|
+
}
|
|
1210
|
+
if (!user) {
|
|
1211
|
+
console.error(fmt('red', `错误:${env} 环境的 user 不能为空`));
|
|
1212
|
+
rl.close();
|
|
1213
|
+
process.exit(1);
|
|
1214
|
+
}
|
|
1215
|
+
|
|
1216
|
+
environments[env] = {
|
|
1217
|
+
host,
|
|
1218
|
+
port: parseInt(port, 10),
|
|
1219
|
+
user,
|
|
1220
|
+
password,
|
|
1221
|
+
description: desc,
|
|
1222
|
+
};
|
|
1223
|
+
}
|
|
1224
|
+
|
|
1225
|
+
// 4. 选择默认环境
|
|
1226
|
+
let defaultEnv = selectedEnvs[0];
|
|
1227
|
+
if (selectedEnvs.length > 1) {
|
|
1228
|
+
console.log(fmt('cyan', '请选择默认环境:'));
|
|
1229
|
+
selectedEnvs.forEach((env, i) => {
|
|
1230
|
+
console.log(` ${fmt('bold', String(i + 1))}) ${env}`);
|
|
1231
|
+
});
|
|
1232
|
+
const defaultAnswer = await ask(fmt('bold', `请输入选项 [1-${selectedEnvs.length}]: `));
|
|
1233
|
+
const idx = parseInt(defaultAnswer, 10) - 1;
|
|
1234
|
+
if (idx >= 0 && idx < selectedEnvs.length) {
|
|
1235
|
+
defaultEnv = selectedEnvs[idx];
|
|
1236
|
+
}
|
|
1237
|
+
console.log('');
|
|
1238
|
+
}
|
|
1239
|
+
|
|
1240
|
+
// 5. 写入配置文件
|
|
1241
|
+
const config = { defaultEnv, environments };
|
|
1242
|
+
const claudeDir = path.join(targetDir, '.claude');
|
|
1243
|
+
if (!fs.existsSync(claudeDir)) {
|
|
1244
|
+
fs.mkdirSync(claudeDir, { recursive: true });
|
|
1245
|
+
}
|
|
1246
|
+
fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n', 'utf-8');
|
|
1247
|
+
console.log(fmt('green', `✔ 配置已写入:${configPath}`));
|
|
1248
|
+
|
|
1249
|
+
// 6. 确保 .gitignore 包含该文件
|
|
1250
|
+
const gitignorePath = path.join(targetDir, '.gitignore');
|
|
1251
|
+
const ignoreEntry = '.claude/mysql-config.json';
|
|
1252
|
+
let needAppend = true;
|
|
1253
|
+
if (fs.existsSync(gitignorePath)) {
|
|
1254
|
+
const content = fs.readFileSync(gitignorePath, 'utf-8');
|
|
1255
|
+
if (content.split('\n').some(line => line.trim() === ignoreEntry)) {
|
|
1256
|
+
needAppend = false;
|
|
1257
|
+
}
|
|
1258
|
+
}
|
|
1259
|
+
if (needAppend) {
|
|
1260
|
+
const separator = fs.existsSync(gitignorePath) ? '\n' : '';
|
|
1261
|
+
fs.appendFileSync(gitignorePath, `${separator}${ignoreEntry}\n`, 'utf-8');
|
|
1262
|
+
console.log(fmt('green', `✔ 已添加 ${ignoreEntry} 到 .gitignore`));
|
|
1263
|
+
}
|
|
1264
|
+
|
|
1265
|
+
console.log('');
|
|
1266
|
+
console.log(fmt('green', '数据库配置初始化完成!'));
|
|
1267
|
+
console.log(`使用 ${fmt('bold', 'mysql-debug')} 技能时将自动读取此配置。`);
|
|
1268
|
+
} finally {
|
|
1269
|
+
rl.close();
|
|
1270
|
+
}
|
|
1271
|
+
})();
|
|
1272
|
+
}
|
|
1273
|
+
|
|
1274
|
+
// ── MCP 服务器管理 ──────────────────────────────────────────────────────────
|
|
1275
|
+
|
|
1276
|
+
const MCP_REGISTRY = [
|
|
1277
|
+
{
|
|
1278
|
+
name: 'sequential-thinking',
|
|
1279
|
+
package: '@modelcontextprotocol/server-sequential-thinking',
|
|
1280
|
+
description: '链式推理 — 深度分析、仔细思考、全面评估时使用',
|
|
1281
|
+
env: {},
|
|
1282
|
+
recommended: true,
|
|
1283
|
+
},
|
|
1284
|
+
{
|
|
1285
|
+
name: 'context7',
|
|
1286
|
+
package: '@upstash/context7-mcp',
|
|
1287
|
+
description: '官方文档查询 — 最佳实践、官方文档、标准写法时使用',
|
|
1288
|
+
env: {},
|
|
1289
|
+
recommended: true,
|
|
1290
|
+
},
|
|
1291
|
+
{
|
|
1292
|
+
name: 'github',
|
|
1293
|
+
package: '@modelcontextprotocol/server-github',
|
|
1294
|
+
description: 'GitHub 集成 — 查询 Issues、PR、仓库信息',
|
|
1295
|
+
env: { GITHUB_PERSONAL_ACCESS_TOKEN: '${GITHUB_TOKEN}' },
|
|
1296
|
+
recommended: true,
|
|
1297
|
+
},
|
|
1298
|
+
{
|
|
1299
|
+
name: 'filesystem',
|
|
1300
|
+
package: '@modelcontextprotocol/server-filesystem',
|
|
1301
|
+
description: '文件系统访问 — 读写项目外的文件',
|
|
1302
|
+
env: {},
|
|
1303
|
+
recommended: false,
|
|
1304
|
+
},
|
|
1305
|
+
{
|
|
1306
|
+
name: 'fetch',
|
|
1307
|
+
package: '@anthropic-ai/mcp-fetch',
|
|
1308
|
+
description: '网页抓取 — 获取网页内容',
|
|
1309
|
+
env: {},
|
|
1310
|
+
recommended: false,
|
|
1311
|
+
},
|
|
1312
|
+
{
|
|
1313
|
+
name: 'yunxiao',
|
|
1314
|
+
package: 'alibabacloud-devops-mcp-server',
|
|
1315
|
+
description: '阿里云效 — DevOps 项目管理、代码仓库、流水线集成',
|
|
1316
|
+
env: { YUNXIAO_ACCESS_TOKEN: '<YOUR_TOKEN>' },
|
|
1317
|
+
recommended: false,
|
|
1318
|
+
},
|
|
1319
|
+
{
|
|
1320
|
+
name: 'yuque',
|
|
1321
|
+
package: 'yuque-mcp',
|
|
1322
|
+
description: '语雀 — 知识库文档读写、搜索、团队协作',
|
|
1323
|
+
env: { YUQUE_TOKEN: '<YOUR_TOKEN>' },
|
|
1324
|
+
recommended: false,
|
|
1325
|
+
},
|
|
1326
|
+
];
|
|
1327
|
+
|
|
1328
|
+
/** MCP 配置文件路径映射 */
|
|
1329
|
+
const MCP_CONFIG_PATHS = {
|
|
1330
|
+
claude: { file: '.claude/settings.json', key: 'mcpServers' },
|
|
1331
|
+
cursor: { file: '.cursor/mcp.json', key: 'mcpServers' },
|
|
1332
|
+
};
|
|
1333
|
+
|
|
1334
|
+
/** 检测项目中已有的工具配置目录 */
|
|
1335
|
+
function detectMcpTools() {
|
|
1336
|
+
const tools = [];
|
|
1337
|
+
if (isRealDir(path.join(targetDir, '.claude'))) tools.push('claude');
|
|
1338
|
+
if (isRealDir(path.join(targetDir, '.cursor'))) tools.push('cursor');
|
|
1339
|
+
return tools;
|
|
1340
|
+
}
|
|
1341
|
+
|
|
1342
|
+
/** 读取指定工具的 MCP 已配置服务器 */
|
|
1343
|
+
function getMcpServers(toolName) {
|
|
1344
|
+
const config = MCP_CONFIG_PATHS[toolName];
|
|
1345
|
+
if (!config) return {};
|
|
1346
|
+
const filePath = path.join(targetDir, config.file);
|
|
1347
|
+
try {
|
|
1348
|
+
const data = JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
|
1349
|
+
return data[config.key] || {};
|
|
1350
|
+
} catch { return {}; }
|
|
1351
|
+
}
|
|
1352
|
+
|
|
1353
|
+
/** 写入指定工具的 MCP 配置(保留文件其他字段) */
|
|
1354
|
+
function setMcpServers(toolName, mcpServers) {
|
|
1355
|
+
const config = MCP_CONFIG_PATHS[toolName];
|
|
1356
|
+
if (!config) return;
|
|
1357
|
+
const filePath = path.join(targetDir, config.file);
|
|
1358
|
+
let data = {};
|
|
1359
|
+
try { data = JSON.parse(fs.readFileSync(filePath, 'utf8')); } catch { /* 新建 */ }
|
|
1360
|
+
data[config.key] = mcpServers;
|
|
1361
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
1362
|
+
fs.writeFileSync(filePath, JSON.stringify(data, null, 2) + '\n');
|
|
1363
|
+
}
|
|
1364
|
+
|
|
1365
|
+
/** 构建单个 MCP 服务器的配置对象 */
|
|
1366
|
+
function buildMcpServerConfig(entry) {
|
|
1367
|
+
const config = {
|
|
1368
|
+
command: 'npx',
|
|
1369
|
+
args: ['-y', entry.package],
|
|
1370
|
+
};
|
|
1371
|
+
if (Object.keys(entry.env).length > 0) {
|
|
1372
|
+
config.env = { ...entry.env };
|
|
1373
|
+
}
|
|
1374
|
+
return config;
|
|
1375
|
+
}
|
|
1376
|
+
|
|
1377
|
+
/** 获取所有工具中已安装的 MCP 服务器名称集合 */
|
|
1378
|
+
function getInstalledMcpNames(tools) {
|
|
1379
|
+
const names = new Set();
|
|
1380
|
+
for (const t of tools) {
|
|
1381
|
+
const servers = getMcpServers(t);
|
|
1382
|
+
for (const name of Object.keys(servers)) names.add(name);
|
|
1383
|
+
}
|
|
1384
|
+
return names;
|
|
1385
|
+
}
|
|
1386
|
+
|
|
1387
|
+
function runMcp() {
|
|
1388
|
+
if (!process.stdin.isTTY) {
|
|
1389
|
+
console.error(fmt('red', '错误:mcp 命令需要交互式终端'));
|
|
1390
|
+
process.exit(1);
|
|
1391
|
+
}
|
|
1392
|
+
|
|
1393
|
+
const tools = detectMcpTools();
|
|
1394
|
+
if (tools.length === 0) {
|
|
1395
|
+
console.log(fmt('yellow', '⚠ 当前目录未检测到 .claude/ 或 .cursor/ 配置目录。'));
|
|
1396
|
+
console.log(` 请先运行: ${fmt('bold', hintCmd('init --tool claude'))}`);
|
|
1397
|
+
console.log('');
|
|
1398
|
+
process.exit(1);
|
|
1399
|
+
}
|
|
1400
|
+
|
|
1401
|
+
console.log(` 检测到工具: ${fmt('bold', tools.join(', '))}`);
|
|
1402
|
+
console.log('');
|
|
1403
|
+
|
|
1404
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
1405
|
+
const ask = (question) => new Promise((resolve) => {
|
|
1406
|
+
rl.question(question, (answer) => resolve(answer.trim()));
|
|
1407
|
+
});
|
|
1408
|
+
|
|
1409
|
+
(async () => {
|
|
1410
|
+
try {
|
|
1411
|
+
console.log(fmt('cyan', '请选择 MCP 操作:'));
|
|
1412
|
+
console.log('');
|
|
1413
|
+
console.log(` ${fmt('bold', '1')}) ${fmt('green', '安装 MCP 服务器')} — 从预置列表选择并安装到配置`);
|
|
1414
|
+
console.log(` ${fmt('bold', '2')}) ${fmt('red', '卸载 MCP 服务器')} — 从已安装列表中移除`);
|
|
1415
|
+
console.log(` ${fmt('bold', '3')}) ${fmt('cyan', '查看状态')} — 检查已配置的 MCP 服务器`);
|
|
1416
|
+
console.log(` ${fmt('bold', '4')}) ${fmt('yellow', '一键推荐安装')} — 安装所有推荐的 MCP 服务器`);
|
|
1417
|
+
console.log('');
|
|
1418
|
+
const action = await ask(fmt('bold', '请输入选项 [1-4]: '));
|
|
1419
|
+
console.log('');
|
|
1420
|
+
|
|
1421
|
+
switch (action) {
|
|
1422
|
+
case '1': await mcpInstall(tools, ask); break;
|
|
1423
|
+
case '2': await mcpUninstall(tools, ask); break;
|
|
1424
|
+
case '3': mcpStatus(tools); break;
|
|
1425
|
+
case '4': await mcpRecommend(tools, ask); break;
|
|
1426
|
+
default:
|
|
1427
|
+
console.error(fmt('red', '无效选项,退出。'));
|
|
1428
|
+
process.exit(1);
|
|
1429
|
+
}
|
|
1430
|
+
} finally {
|
|
1431
|
+
rl.close();
|
|
1432
|
+
}
|
|
1433
|
+
})();
|
|
1434
|
+
}
|
|
1435
|
+
|
|
1436
|
+
/** 安装 MCP 服务器 */
|
|
1437
|
+
async function mcpInstall(tools, ask) {
|
|
1438
|
+
const installed = getInstalledMcpNames(tools);
|
|
1439
|
+
|
|
1440
|
+
console.log(fmt('cyan', '可用的 MCP 服务器:'));
|
|
1441
|
+
console.log('');
|
|
1442
|
+
for (let i = 0; i < MCP_REGISTRY.length; i++) {
|
|
1443
|
+
const entry = MCP_REGISTRY[i];
|
|
1444
|
+
const tags = [];
|
|
1445
|
+
if (installed.has(entry.name)) tags.push(fmt('green', '[已安装]'));
|
|
1446
|
+
if (entry.recommended) tags.push(fmt('yellow', '[推荐]'));
|
|
1447
|
+
const tagStr = tags.length > 0 ? ' ' + tags.join(' ') : '';
|
|
1448
|
+
console.log(` ${fmt('bold', String(i + 1))}) ${fmt('bold', entry.name)}${tagStr}`);
|
|
1449
|
+
console.log(` ${entry.description}`);
|
|
1450
|
+
}
|
|
1451
|
+
console.log('');
|
|
1452
|
+
const answer = await ask(fmt('bold', '请选择要安装的服务器(逗号分隔,如 1,2,3): '));
|
|
1453
|
+
const indices = answer.split(',').map(s => parseInt(s.trim(), 10) - 1).filter(i => i >= 0 && i < MCP_REGISTRY.length);
|
|
1454
|
+
|
|
1455
|
+
if (indices.length === 0) {
|
|
1456
|
+
console.log(fmt('yellow', '未选择任何服务器,退出。'));
|
|
1457
|
+
return;
|
|
1458
|
+
}
|
|
1459
|
+
|
|
1460
|
+
const selected = indices.map(i => MCP_REGISTRY[i]);
|
|
1461
|
+
console.log('');
|
|
1462
|
+
|
|
1463
|
+
// 处理需要 env 的服务器
|
|
1464
|
+
for (const entry of selected) {
|
|
1465
|
+
if (Object.keys(entry.env).length > 0) {
|
|
1466
|
+
console.log(fmt('cyan', `── ${entry.name} 环境变量配置 ──`));
|
|
1467
|
+
for (const [key, defaultVal] of Object.entries(entry.env)) {
|
|
1468
|
+
const val = await ask(` ${key} [${defaultVal}]: `);
|
|
1469
|
+
if (val) entry.env[key] = val;
|
|
1470
|
+
}
|
|
1471
|
+
console.log('');
|
|
1472
|
+
}
|
|
1473
|
+
}
|
|
1474
|
+
|
|
1475
|
+
// 写入所有检测到的工具配置
|
|
1476
|
+
for (const toolName of tools) {
|
|
1477
|
+
const servers = getMcpServers(toolName);
|
|
1478
|
+
for (const entry of selected) {
|
|
1479
|
+
servers[entry.name] = buildMcpServerConfig(entry);
|
|
1480
|
+
}
|
|
1481
|
+
setMcpServers(toolName, servers);
|
|
1482
|
+
console.log(` ${fmt('green', '✓')} ${toolName}: 已写入 ${selected.map(e => e.name).join(', ')}`);
|
|
1483
|
+
}
|
|
1484
|
+
|
|
1485
|
+
console.log('');
|
|
1486
|
+
console.log(fmt('green', fmt('bold', `✅ 已安装 ${selected.length} 个 MCP 服务器!`)));
|
|
1487
|
+
console.log('');
|
|
1488
|
+
}
|
|
1489
|
+
|
|
1490
|
+
/** 卸载 MCP 服务器 */
|
|
1491
|
+
async function mcpUninstall(tools, ask) {
|
|
1492
|
+
// 收集所有已安装的服务器(合并去重)
|
|
1493
|
+
const allServers = new Map(); // name → 出现在哪些工具中
|
|
1494
|
+
for (const toolName of tools) {
|
|
1495
|
+
const servers = getMcpServers(toolName);
|
|
1496
|
+
for (const name of Object.keys(servers)) {
|
|
1497
|
+
if (!allServers.has(name)) allServers.set(name, []);
|
|
1498
|
+
allServers.get(name).push(toolName);
|
|
1499
|
+
}
|
|
1500
|
+
}
|
|
1501
|
+
|
|
1502
|
+
if (allServers.size === 0) {
|
|
1503
|
+
console.log(fmt('yellow', ' 当前没有已安装的 MCP 服务器。'));
|
|
1504
|
+
console.log(` 运行 ${fmt('bold', hintCmd('mcp'))} 安装服务器。`);
|
|
1505
|
+
console.log('');
|
|
1506
|
+
return;
|
|
1507
|
+
}
|
|
1508
|
+
|
|
1509
|
+
const serverNames = [...allServers.keys()];
|
|
1510
|
+
console.log(fmt('cyan', '已安装的 MCP 服务器:'));
|
|
1511
|
+
console.log('');
|
|
1512
|
+
for (let i = 0; i < serverNames.length; i++) {
|
|
1513
|
+
const name = serverNames[i];
|
|
1514
|
+
const toolList = allServers.get(name).join(', ');
|
|
1515
|
+
console.log(` ${fmt('bold', String(i + 1))}) ${fmt('bold', name)} ${fmt('magenta', `(${toolList})`)}`);
|
|
1516
|
+
}
|
|
1517
|
+
console.log('');
|
|
1518
|
+
const answer = await ask(fmt('bold', '请选择要卸载的服务器(逗号分隔): '));
|
|
1519
|
+
const indices = answer.split(',').map(s => parseInt(s.trim(), 10) - 1).filter(i => i >= 0 && i < serverNames.length);
|
|
1520
|
+
|
|
1521
|
+
if (indices.length === 0) {
|
|
1522
|
+
console.log(fmt('yellow', '未选择任何服务器,退出。'));
|
|
1523
|
+
return;
|
|
1524
|
+
}
|
|
1525
|
+
|
|
1526
|
+
const toRemove = indices.map(i => serverNames[i]);
|
|
1527
|
+
console.log('');
|
|
1528
|
+
|
|
1529
|
+
for (const toolName of tools) {
|
|
1530
|
+
const servers = getMcpServers(toolName);
|
|
1531
|
+
let removed = 0;
|
|
1532
|
+
for (const name of toRemove) {
|
|
1533
|
+
if (name in servers) {
|
|
1534
|
+
delete servers[name];
|
|
1535
|
+
removed++;
|
|
1536
|
+
}
|
|
1537
|
+
}
|
|
1538
|
+
if (removed > 0) {
|
|
1539
|
+
setMcpServers(toolName, servers);
|
|
1540
|
+
console.log(` ${fmt('green', '✓')} ${toolName}: 已移除 ${toRemove.filter(n => !servers[n]).join(', ')}`);
|
|
1541
|
+
}
|
|
1542
|
+
}
|
|
1543
|
+
|
|
1544
|
+
console.log('');
|
|
1545
|
+
console.log(fmt('green', fmt('bold', `✅ 已卸载 ${toRemove.length} 个 MCP 服务器!`)));
|
|
1546
|
+
console.log('');
|
|
1547
|
+
}
|
|
1548
|
+
|
|
1549
|
+
/** 查看 MCP 状态 */
|
|
1550
|
+
function mcpStatus(tools) {
|
|
1551
|
+
let hasAny = false;
|
|
1552
|
+
|
|
1553
|
+
for (const toolName of tools) {
|
|
1554
|
+
const servers = getMcpServers(toolName);
|
|
1555
|
+
const names = Object.keys(servers);
|
|
1556
|
+
|
|
1557
|
+
console.log(fmt('cyan', `[${toolName}]`) + ` ${MCP_CONFIG_PATHS[toolName].file}`);
|
|
1558
|
+
|
|
1559
|
+
if (names.length === 0) {
|
|
1560
|
+
console.log(` ${fmt('yellow', '(无已安装的 MCP 服务器)')}`);
|
|
1561
|
+
} else {
|
|
1562
|
+
hasAny = true;
|
|
1563
|
+
for (const name of names) {
|
|
1564
|
+
const srv = servers[name];
|
|
1565
|
+
const pkg = (srv.args || []).find(a => a.startsWith('@')) || '—';
|
|
1566
|
+
const envKeys = srv.env ? Object.keys(srv.env).join(', ') : '—';
|
|
1567
|
+
console.log(` ${fmt('green', '●')} ${fmt('bold', name)}`);
|
|
1568
|
+
console.log(` 包: ${pkg} | 环境变量: ${envKeys}`);
|
|
1569
|
+
}
|
|
1570
|
+
}
|
|
1571
|
+
console.log('');
|
|
1572
|
+
}
|
|
1573
|
+
|
|
1574
|
+
if (!hasAny) {
|
|
1575
|
+
console.log(fmt('yellow', '💡 未安装任何 MCP 服务器。'));
|
|
1576
|
+
console.log(` 运行 ${fmt('bold', hintCmd('mcp'))} 开始安装。`);
|
|
1577
|
+
console.log('');
|
|
1578
|
+
}
|
|
1579
|
+
}
|
|
1580
|
+
|
|
1581
|
+
/** 一键推荐安装 */
|
|
1582
|
+
async function mcpRecommend(tools, ask) {
|
|
1583
|
+
const installed = getInstalledMcpNames(tools);
|
|
1584
|
+
const toInstall = MCP_REGISTRY.filter(e => e.recommended && !installed.has(e.name));
|
|
1585
|
+
|
|
1586
|
+
if (toInstall.length === 0) {
|
|
1587
|
+
console.log(fmt('green', ' ✓ 所有推荐的 MCP 服务器已安装!'));
|
|
1588
|
+
console.log('');
|
|
1589
|
+
mcpStatus(tools);
|
|
1590
|
+
return;
|
|
1591
|
+
}
|
|
1592
|
+
|
|
1593
|
+
console.log(fmt('cyan', '将安装以下推荐服务器:'));
|
|
1594
|
+
console.log('');
|
|
1595
|
+
for (const entry of toInstall) {
|
|
1596
|
+
console.log(` ${fmt('green', '●')} ${fmt('bold', entry.name)} — ${entry.description}`);
|
|
1597
|
+
}
|
|
1598
|
+
console.log('');
|
|
1599
|
+
|
|
1600
|
+
// 处理需要 env 的服务器
|
|
1601
|
+
for (const entry of toInstall) {
|
|
1602
|
+
if (Object.keys(entry.env).length > 0) {
|
|
1603
|
+
console.log(fmt('cyan', `── ${entry.name} 环境变量配置 ──`));
|
|
1604
|
+
for (const [key, defaultVal] of Object.entries(entry.env)) {
|
|
1605
|
+
const val = await ask(` ${key} [${defaultVal}]: `);
|
|
1606
|
+
if (val) entry.env[key] = val;
|
|
1607
|
+
}
|
|
1608
|
+
console.log('');
|
|
1609
|
+
}
|
|
1610
|
+
}
|
|
1611
|
+
|
|
1612
|
+
// 写入配置
|
|
1613
|
+
for (const toolName of tools) {
|
|
1614
|
+
const servers = getMcpServers(toolName);
|
|
1615
|
+
for (const entry of toInstall) {
|
|
1616
|
+
servers[entry.name] = buildMcpServerConfig(entry);
|
|
1617
|
+
}
|
|
1618
|
+
setMcpServers(toolName, servers);
|
|
1619
|
+
console.log(` ${fmt('green', '✓')} ${toolName}: 已写入 ${toInstall.map(e => e.name).join(', ')}`);
|
|
1620
|
+
}
|
|
1621
|
+
|
|
1622
|
+
console.log('');
|
|
1623
|
+
console.log(fmt('green', fmt('bold', `✅ 已安装 ${toInstall.length} 个推荐 MCP 服务器!`)));
|
|
1624
|
+
console.log('');
|
|
1625
|
+
}
|
|
1626
|
+
|
|
1627
|
+
// ── 工具选择菜单(init 用)─────────────────────────────────────────────────
|
|
1628
|
+
function showToolMenu() {
|
|
1117
1629
|
if (!process.stdin.isTTY) {
|
|
1118
1630
|
console.error(fmt('red', '错误:非交互环境下必须指定 --tool 参数'));
|
|
1119
|
-
console.error(` 示例: ${fmt('bold', hintCmd('--tool claude'))}`);
|
|
1631
|
+
console.error(` 示例: ${fmt('bold', hintCmd('init --tool claude'))}`);
|
|
1120
1632
|
process.exit(1);
|
|
1121
1633
|
}
|
|
1122
1634
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
1123
|
-
console.log(fmt('cyan', '
|
|
1635
|
+
console.log(fmt('cyan', '请选择要初始化的工具:'));
|
|
1124
1636
|
console.log('');
|
|
1125
|
-
console.log(` ${fmt('bold', '1')}) ${fmt('green', 'Claude Code')} —
|
|
1126
|
-
console.log(` ${fmt('bold', '2')}) ${fmt('cyan', 'Cursor')} —
|
|
1127
|
-
console.log(` ${fmt('bold', '3')}) ${fmt('yellow', 'OpenAI Codex')} —
|
|
1128
|
-
console.log(` ${fmt('bold', '4')}) ${fmt('blue', '全部工具')} — 同时初始化 Claude + Cursor + Codex
|
|
1129
|
-
console.log(` ${fmt('bold', '5')}) ${fmt('magenta', '全局安装')} — 安装到 ~/.claude / ~/.cursor,对所有项目生效`);
|
|
1637
|
+
console.log(` ${fmt('bold', '1')}) ${fmt('green', 'Claude Code')} — .claude/ + CLAUDE.md`);
|
|
1638
|
+
console.log(` ${fmt('bold', '2')}) ${fmt('cyan', 'Cursor')} — .cursor/(Skills + Agents)`);
|
|
1639
|
+
console.log(` ${fmt('bold', '3')}) ${fmt('yellow', 'OpenAI Codex')} — .codex/ + AGENTS.md`);
|
|
1640
|
+
console.log(` ${fmt('bold', '4')}) ${fmt('blue', '全部工具')} — 同时初始化 Claude + Cursor + Codex`);
|
|
1130
1641
|
console.log('');
|
|
1131
|
-
rl.question(fmt('bold', '请输入选项 [1-
|
|
1642
|
+
rl.question(fmt('bold', '请输入选项 [1-4]: '), (answer) => {
|
|
1132
1643
|
rl.close();
|
|
1133
1644
|
const map = { '1': 'claude', '2': 'cursor', '3': 'codex', '4': 'all' };
|
|
1134
1645
|
const selected = map[answer.trim()];
|
|
1135
1646
|
console.log('');
|
|
1136
|
-
if (
|
|
1137
|
-
runGlobal('all');
|
|
1138
|
-
} else if (selected) {
|
|
1647
|
+
if (selected) {
|
|
1139
1648
|
run(selected);
|
|
1140
1649
|
} else {
|
|
1141
1650
|
console.error(fmt('red', '无效选项,退出。'));
|
|
@@ -1143,3 +1652,76 @@ if (command === 'update') {
|
|
|
1143
1652
|
}
|
|
1144
1653
|
});
|
|
1145
1654
|
}
|
|
1655
|
+
|
|
1656
|
+
// ── 主菜单(无命令时展示)──────────────────────────────────────────────────
|
|
1657
|
+
function showMainMenu() {
|
|
1658
|
+
if (!process.stdin.isTTY) {
|
|
1659
|
+
console.error(fmt('red', '错误:非交互环境下必须指定命令'));
|
|
1660
|
+
console.error(` 示例: ${fmt('bold', hintCmd('init --tool claude'))}`);
|
|
1661
|
+
console.error(` 运行 ${fmt('bold', hintCmd('--help'))} 查看所有命令`);
|
|
1662
|
+
process.exit(1);
|
|
1663
|
+
}
|
|
1664
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
1665
|
+
console.log(fmt('cyan', '请选择操作:'));
|
|
1666
|
+
console.log('');
|
|
1667
|
+
console.log(` ${fmt('bold', '1')}) ${fmt('green', '初始化')} — 安装 AI 工具配置到当前项目`);
|
|
1668
|
+
console.log(` ${fmt('bold', '2')}) ${fmt('cyan', '更新')} — 更新已安装的框架文件`);
|
|
1669
|
+
console.log(` ${fmt('bold', '3')}) ${fmt('yellow', '全局安装')} — 安装到 ~/.claude 等,对所有项目生效`);
|
|
1670
|
+
console.log(` ${fmt('bold', '4')}) ${fmt('magenta', '技能同步反馈')} — 对比本地技能修改,生成 diff`);
|
|
1671
|
+
console.log(` ${fmt('bold', '5')}) ${fmt('blue', '数据库配置')} — 初始化 mysql-config.json(数据库连接信息)`);
|
|
1672
|
+
console.log(` ${fmt('bold', '6')}) ${fmt('green', 'MCP 管理')} — MCP 服务器安装/卸载/状态检查`);
|
|
1673
|
+
console.log('');
|
|
1674
|
+
rl.question(fmt('bold', '请输入选项 [1-6]: '), (answer) => {
|
|
1675
|
+
rl.close();
|
|
1676
|
+
console.log('');
|
|
1677
|
+
switch (answer.trim()) {
|
|
1678
|
+
case '1':
|
|
1679
|
+
showToolMenu();
|
|
1680
|
+
break;
|
|
1681
|
+
case '2':
|
|
1682
|
+
runUpdate(tool);
|
|
1683
|
+
break;
|
|
1684
|
+
case '3':
|
|
1685
|
+
runGlobal(tool || 'all');
|
|
1686
|
+
break;
|
|
1687
|
+
case '4':
|
|
1688
|
+
runSyncBack(tool, skillFilter, submitIssue);
|
|
1689
|
+
break;
|
|
1690
|
+
case '5':
|
|
1691
|
+
runConfig();
|
|
1692
|
+
break;
|
|
1693
|
+
case '6':
|
|
1694
|
+
runMcp();
|
|
1695
|
+
break;
|
|
1696
|
+
default:
|
|
1697
|
+
console.error(fmt('red', '无效选项,退出。'));
|
|
1698
|
+
process.exit(1);
|
|
1699
|
+
}
|
|
1700
|
+
});
|
|
1701
|
+
}
|
|
1702
|
+
|
|
1703
|
+
// ── 主入口 ────────────────────────────────────────────────────────────────
|
|
1704
|
+
if (command === 'init') {
|
|
1705
|
+
// 显式 init 子命令
|
|
1706
|
+
if (tool) {
|
|
1707
|
+
run(tool);
|
|
1708
|
+
} else {
|
|
1709
|
+
showToolMenu();
|
|
1710
|
+
}
|
|
1711
|
+
} else if (command === 'update') {
|
|
1712
|
+
runUpdate(tool);
|
|
1713
|
+
} else if (command === 'global') {
|
|
1714
|
+
runGlobal(tool);
|
|
1715
|
+
} else if (command === 'sync-back') {
|
|
1716
|
+
runSyncBack(tool, skillFilter, submitIssue);
|
|
1717
|
+
} else if (command === 'config') {
|
|
1718
|
+
runConfig();
|
|
1719
|
+
} else if (command === 'mcp') {
|
|
1720
|
+
runMcp();
|
|
1721
|
+
} else if (tool) {
|
|
1722
|
+
// 向后兼容:无 command 但有 --tool,当作 init 执行
|
|
1723
|
+
run(tool);
|
|
1724
|
+
} else {
|
|
1725
|
+
// 无命令无参数:显示主菜单
|
|
1726
|
+
showMainMenu();
|
|
1727
|
+
}
|
package/package.json
CHANGED
package/src/platform-map.json
CHANGED