ai-engineering-init 1.2.8 → 1.2.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/bin/index.js +48 -8
  2. package/package.json +1 -1
package/bin/index.js CHANGED
@@ -205,15 +205,14 @@ const GLOBAL_RULES = {
205
205
  label: 'Cursor',
206
206
  targetDir: path.join(HOME_DIR, '.cursor'),
207
207
  files: [
208
- { src: '.cursor/skills', dest: 'skills', label: 'Skills(全局技能库)', isDir: true },
209
- { src: '.cursor/agents', dest: 'agents', label: 'Agents(全局子代理)', isDir: true },
210
- { src: '.cursor/hooks', dest: 'hooks', label: 'Hooks(全局钩子)', isDir: true },
208
+ { src: '.cursor/skills', dest: 'skills', label: 'Skills(全局技能库)', isDir: true },
209
+ { src: '.cursor/agents', dest: 'agents', label: 'Agents(全局子代理)', isDir: true },
210
+ { src: '.cursor/hooks', dest: 'hooks', label: 'Hooks(全局钩子脚本)', isDir: true },
211
+ { src: '.cursor/hooks.json', dest: 'hooks.json', label: 'hooks.json(Hooks 触发配置)' },
212
+ { src: '.cursor/mcp.json', dest: 'mcp.json', label: 'mcp.json(MCP 服务器配置)', merge: true },
211
213
  ],
212
- preserve: [
213
- { dest: 'mcp.json', reason: '包含用户 MCP 服务器配置' },
214
- { dest: 'hooks.json', reason: '包含用户 Hooks 配置(项目级优先)' },
215
- ],
216
- note: `Skills/Hooks 已安装到 ~/.cursor,重启 Cursor 后在全局规则中生效`,
214
+ preserve: [],
215
+ note: `Skills/Hooks/MCP 已安装到 ~/.cursor,重启 Cursor 后生效`,
217
216
  },
218
217
  codex: {
219
218
  label: 'OpenAI Codex',
@@ -226,6 +225,39 @@ const GLOBAL_RULES = {
226
225
  },
227
226
  };
228
227
 
228
+ /** 合并 JSON 文件:将 src 的键补充到 dest,已有的键保留不覆盖 */
229
+ function mergeJsonFile(srcPath, destPath, label) {
230
+ try {
231
+ const srcData = JSON.parse(fs.readFileSync(srcPath, 'utf8'));
232
+ let destData = {};
233
+ if (fs.existsSync(destPath)) {
234
+ try { destData = JSON.parse(fs.readFileSync(destPath, 'utf8')); } catch { destData = {}; }
235
+ }
236
+ // 深度合并第一层对象键(如 mcpServers),已有的不覆盖
237
+ let added = 0;
238
+ for (const [key, value] of Object.entries(srcData)) {
239
+ if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
240
+ if (!destData[key]) destData[key] = {};
241
+ for (const [subKey, subValue] of Object.entries(value)) {
242
+ if (!(subKey in destData[key])) {
243
+ destData[key][subKey] = subValue;
244
+ added++;
245
+ }
246
+ }
247
+ } else if (!(key in destData)) {
248
+ destData[key] = value;
249
+ added++;
250
+ }
251
+ }
252
+ fs.writeFileSync(destPath, JSON.stringify(destData, null, 2) + '\n');
253
+ console.log(` ${fmt('green', '✓')} ${label} ${fmt('magenta', `(合并 +${added} 项,已有配置保留)`)}`);
254
+ return added > 0 ? 1 : 0;
255
+ } catch (e) {
256
+ console.log(` ${fmt('red', '✗')} ${label} 合并失败: ${e.message}`);
257
+ return -1;
258
+ }
259
+ }
260
+
229
261
  /** 全局安装单个工具 */
230
262
  function globalInstallTool(toolKey) {
231
263
  const rule = GLOBAL_RULES[toolKey];
@@ -244,6 +276,14 @@ function globalInstallTool(toolKey) {
244
276
  console.log(` ${fmt('yellow', '⚠')} ${item.label} 源文件不存在,跳过`);
245
277
  continue;
246
278
  }
279
+
280
+ // merge 模式:合并 JSON 而非覆盖(保留用户已有配置)
281
+ if (item.merge) {
282
+ const result = mergeJsonFile(srcPath, destPath, item.label);
283
+ if (result >= 0) installed++; else failed++;
284
+ continue;
285
+ }
286
+
247
287
  if (fs.existsSync(destPath) && !force) {
248
288
  console.log(` ${fmt('yellow', '⚠')} ${item.label} 已存在,跳过(--force 可强制覆盖)`);
249
289
  continue;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-engineering-init",
3
- "version": "1.2.8",
3
+ "version": "1.2.9",
4
4
  "description": "AI 工程化配置初始化工具 — 一键为 Claude Code、OpenAI Codex 等 AI 工具初始化 Skills 和项目规范",
5
5
  "keywords": [
6
6
  "claude-code",