wangchuan 3.0.0 → 3.1.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.
Files changed (56) hide show
  1. package/README.md +146 -174
  2. package/README.zh-CN.md +254 -0
  3. package/dist/bin/wangchuan.d.ts +1 -1
  4. package/dist/bin/wangchuan.js +2 -2
  5. package/dist/src/agents/codex.d.ts +9 -0
  6. package/dist/src/agents/codex.d.ts.map +1 -0
  7. package/dist/src/agents/codex.js +20 -0
  8. package/dist/src/agents/codex.js.map +1 -0
  9. package/dist/src/agents/index.d.ts.map +1 -1
  10. package/dist/src/agents/index.js +2 -0
  11. package/dist/src/agents/index.js.map +1 -1
  12. package/dist/src/commands/completions.js +2 -2
  13. package/dist/src/commands/completions.js.map +1 -1
  14. package/dist/src/commands/list.d.ts.map +1 -1
  15. package/dist/src/commands/list.js +1 -0
  16. package/dist/src/commands/list.js.map +1 -1
  17. package/dist/src/commands/template.js +1 -1
  18. package/dist/src/commands/template.js.map +1 -1
  19. package/dist/src/core/config.d.ts +9 -9
  20. package/dist/src/core/config.d.ts.map +1 -1
  21. package/dist/src/core/config.js +11 -11
  22. package/dist/src/core/config.js.map +1 -1
  23. package/dist/src/core/crypto.d.ts +10 -10
  24. package/dist/src/core/crypto.d.ts.map +1 -1
  25. package/dist/src/core/crypto.js +19 -19
  26. package/dist/src/core/crypto.js.map +1 -1
  27. package/dist/src/core/git.d.ts +2 -2
  28. package/dist/src/core/git.js +9 -9
  29. package/dist/src/core/git.js.map +1 -1
  30. package/dist/src/core/json-field.d.ts +5 -5
  31. package/dist/src/core/json-field.d.ts.map +1 -1
  32. package/dist/src/core/json-field.js +5 -5
  33. package/dist/src/core/json-field.js.map +1 -1
  34. package/dist/src/core/sync.d.ts +9 -9
  35. package/dist/src/core/sync.js +47 -47
  36. package/dist/src/core/sync.js.map +1 -1
  37. package/dist/src/i18n.js +2 -2
  38. package/dist/src/i18n.js.map +1 -1
  39. package/dist/src/types.d.ts +24 -23
  40. package/dist/src/types.d.ts.map +1 -1
  41. package/dist/src/types.js +3 -3
  42. package/dist/src/types.js.map +1 -1
  43. package/dist/src/utils/linediff.d.ts +6 -5
  44. package/dist/src/utils/linediff.d.ts.map +1 -1
  45. package/dist/src/utils/linediff.js +10 -9
  46. package/dist/src/utils/linediff.js.map +1 -1
  47. package/dist/test/crypto.test.d.ts +1 -1
  48. package/dist/test/crypto.test.js +16 -16
  49. package/dist/test/crypto.test.js.map +1 -1
  50. package/dist/test/json-field.test.d.ts +1 -1
  51. package/dist/test/json-field.test.js +13 -13
  52. package/dist/test/json-field.test.js.map +1 -1
  53. package/dist/test/sync.test.d.ts +8 -8
  54. package/dist/test/sync.test.js +122 -113
  55. package/dist/test/sync.test.js.map +1 -1
  56. package/package.json +1 -1
@@ -1,8 +1,8 @@
1
1
  /**
2
- * crypto.ts — AES-256-GCM 加解密模块
2
+ * crypto.ts — AES-256-GCM encryption/decryption module
3
3
  *
4
- * 密钥文件格式:32 字节随机数据,以十六进制字符串存储(64 chars
5
- * 密文文件格式:IV(12B) | AuthTag(16B) | CipherText → Base64 写入 .enc 文件
4
+ * Key file format: 32 bytes of random data, stored as hex string (64 chars)
5
+ * Ciphertext format: IV(12B) | AuthTag(16B) | CipherText → Base64 written to .enc file
6
6
  */
7
7
  import crypto from 'crypto';
8
8
  import fs from 'fs';
@@ -10,20 +10,20 @@ import path from 'path';
10
10
  import { logger } from '../utils/logger.js';
11
11
  const ALGO = 'aes-256-gcm';
12
12
  const KEY_BYTES = 32; // 256 bit
13
- const IV_BYTES = 12; // 96 bit (GCM 推荐)
13
+ const IV_BYTES = 12; // 96 bit (GCM recommended)
14
14
  const TAG_BYTES = 16; // 128 bit auth tag
15
- /** 从文件加载并验证主密钥 */
15
+ /** Load and validate the master key from file */
16
16
  function loadKey(keyPath) {
17
17
  if (!fs.existsSync(keyPath)) {
18
- throw new Error(`密钥文件不存在: ${keyPath}\n请先运行 wangchuan init 生成密钥。`);
18
+ throw new Error(`Key file not found: ${keyPath}\nPlease run wangchuan init to generate a key.`);
19
19
  }
20
20
  const hex = fs.readFileSync(keyPath, 'utf-8').trim();
21
21
  if (hex.length !== KEY_BYTES * 2) {
22
- throw new Error(`密钥文件格式无效,期望 ${KEY_BYTES * 2} 个十六进制字符`);
22
+ throw new Error(`Invalid key file format, expected ${KEY_BYTES * 2} hex characters`);
23
23
  }
24
24
  return Buffer.from(hex, 'hex');
25
25
  }
26
- /** 加密 Buffer → Base64 字符串(格式:IV + AuthTag + CipherText */
26
+ /** Encrypt Buffer → Base64 string (format: IV + AuthTag + CipherText) */
27
27
  function encryptBuffer(plaintext, key) {
28
28
  const iv = crypto.randomBytes(IV_BYTES);
29
29
  const cipher = crypto.createCipheriv(ALGO, key, iv);
@@ -31,7 +31,7 @@ function encryptBuffer(plaintext, key) {
31
31
  const tag = cipher.getAuthTag();
32
32
  return Buffer.concat([iv, tag, enc]).toString('base64');
33
33
  }
34
- /** Base64 密文原始 Buffer */
34
+ /** Base64 ciphertextoriginal Buffer */
35
35
  function decryptBuffer(b64, key) {
36
36
  const data = Buffer.from(b64, 'base64');
37
37
  const iv = data.subarray(0, IV_BYTES);
@@ -43,44 +43,44 @@ function decryptBuffer(b64, key) {
43
43
  }
44
44
  export const cryptoEngine = {
45
45
  /**
46
- * 生成新主密钥并写入文件(mode 0o600
47
- * 返回原始 32 字节 Buffer,供测试断言使用
46
+ * Generate a new master key and write to file (mode 0o600).
47
+ * Returns the raw 32-byte Buffer for test assertions.
48
48
  */
49
49
  generateKey(keyPath) {
50
50
  fs.mkdirSync(path.dirname(keyPath), { recursive: true });
51
51
  const key = crypto.randomBytes(KEY_BYTES);
52
52
  fs.writeFileSync(keyPath, key.toString('hex'), { mode: 0o600, encoding: 'utf-8' });
53
- logger.ok(`主密钥已生成: ${keyPath}`);
53
+ logger.ok(`Master key generated: ${keyPath}`);
54
54
  return key;
55
55
  },
56
- /** 密钥文件是否存在 */
56
+ /** Check if key file exists */
57
57
  hasKey(keyPath) {
58
58
  return fs.existsSync(keyPath);
59
59
  },
60
- /** 加密源文件,密文写入 destPath(通常以 .enc 结尾) */
60
+ /** Encrypt source file, write ciphertext to destPath (typically ending in .enc) */
61
61
  encryptFile(srcPath, destPath, keyPath) {
62
62
  const key = loadKey(keyPath);
63
63
  const plaintext = fs.readFileSync(srcPath);
64
64
  const encrypted = encryptBuffer(plaintext, key);
65
65
  fs.mkdirSync(path.dirname(destPath), { recursive: true });
66
66
  fs.writeFileSync(destPath, encrypted, 'utf-8');
67
- logger.debug(`已加密: ${srcPath} → ${destPath}`);
67
+ logger.debug(`Encrypted: ${srcPath} → ${destPath}`);
68
68
  },
69
- /** 解密 .enc 文件,明文写入 destPath */
69
+ /** Decrypt .enc file, write plaintext to destPath */
70
70
  decryptFile(srcPath, destPath, keyPath) {
71
71
  const key = loadKey(keyPath);
72
72
  const encrypted = fs.readFileSync(srcPath, 'utf-8').trim();
73
73
  const plaintext = decryptBuffer(encrypted, key);
74
74
  fs.mkdirSync(path.dirname(destPath), { recursive: true });
75
75
  fs.writeFileSync(destPath, plaintext);
76
- logger.debug(`已解密: ${srcPath} → ${destPath}`);
76
+ logger.debug(`Decrypted: ${srcPath} → ${destPath}`);
77
77
  },
78
- /** 加密任意字符串,返回 Base64 密文 */
78
+ /** Encrypt an arbitrary string, return Base64 ciphertext */
79
79
  encryptString(plaintext, keyPath) {
80
80
  const key = loadKey(keyPath);
81
81
  return encryptBuffer(Buffer.from(plaintext, 'utf-8'), key);
82
82
  },
83
- /** 解密 Base64 密文,返回原始字符串 */
83
+ /** Decrypt Base64 ciphertext, return original string */
84
84
  decryptString(b64, keyPath) {
85
85
  const key = loadKey(keyPath);
86
86
  return decryptBuffer(b64, key).toString('utf-8');
@@ -1 +1 @@
1
- {"version":3,"file":"crypto.js","sourceRoot":"","sources":["../../../src/core/crypto.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"crypto.js","sourceRoot":"","sources":["../../../src/core/crypto.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  /**
2
- * git.ts — simple-git 封装,提供幂等的 Git 操作
2
+ * git.ts — simple-git wrapper providing idempotent Git operations
3
3
  *
4
- * simple-git v3 ESM 下必须使用具名导入 { simpleGit } 而非默认导入。
4
+ * simple-git v3 requires named import { simpleGit } under ESM (not default import).
5
5
  */
6
6
  import type { DefaultLogFields } from 'simple-git';
7
7
  import type { CommitResult } from '../types.js';
@@ -1,7 +1,7 @@
1
1
  /**
2
- * git.ts — simple-git 封装,提供幂等的 Git 操作
2
+ * git.ts — simple-git wrapper providing idempotent Git operations
3
3
  *
4
- * simple-git v3 ESM 下必须使用具名导入 { simpleGit } 而非默认导入。
4
+ * simple-git v3 requires named import { simpleGit } under ESM (not default import).
5
5
  */
6
6
  import { simpleGit } from 'simple-git';
7
7
  import fs from 'fs';
@@ -16,13 +16,13 @@ function createGit(repoPath) {
16
16
  export const gitEngine = {
17
17
  async cloneOrFetch(remoteUrl, localPath, branch = 'main') {
18
18
  if (fs.existsSync(path.join(localPath, '.git'))) {
19
- logger.debug(`仓库已存在,执行 fetch: ${localPath}`);
19
+ logger.debug(`Repo exists, running fetch: ${localPath}`);
20
20
  const git = createGit(localPath);
21
21
  await git.fetch('origin', branch);
22
22
  await git.reset(['--hard', `origin/${branch}`]);
23
23
  }
24
24
  else {
25
- logger.debug(`克隆仓库: ${remoteUrl} → ${localPath}`);
25
+ logger.debug(`Cloning repo: ${remoteUrl} → ${localPath}`);
26
26
  fs.mkdirSync(localPath, { recursive: true });
27
27
  await simpleGit().clone(remoteUrl, localPath, ['--branch', branch, '--single-branch']);
28
28
  }
@@ -38,14 +38,14 @@ export const gitEngine = {
38
38
  await git.add('.');
39
39
  const status = await git.status();
40
40
  if (status.isClean()) {
41
- logger.info('没有新的变更需要提交');
41
+ logger.info('No new changes to commit');
42
42
  return { committed: false, pushed: false };
43
43
  }
44
- logger.debug(`暂存文件: ${status.staged.join(', ')}`);
44
+ logger.debug(`Staged files: ${status.staged.join(', ')}`);
45
45
  const commitResult = await git.commit(message);
46
46
  logger.debug(`commit: ${commitResult.commit}`);
47
47
  await git.push('origin', branch);
48
- logger.debug(`已推送到 origin/${branch}`);
48
+ logger.debug(`Pushed to origin/${branch}`);
49
49
  return { committed: true, pushed: true, sha: commitResult.commit };
50
50
  },
51
51
  async status(localPath) {
@@ -62,9 +62,9 @@ export const gitEngine = {
62
62
  return remotes.find(r => r.name === 'origin')?.refs?.fetch ?? null;
63
63
  },
64
64
  async rollback(localPath) {
65
- logger.warn('正在回滚最近一次 commit');
65
+ logger.warn('Rolling back the last commit...');
66
66
  await createGit(localPath).reset(['--soft', 'HEAD~1']);
67
- logger.warn('回滚完成,本地变更已保留在暂存区');
67
+ logger.warn('Rollback complete, local changes preserved in staging area');
68
68
  },
69
69
  /**
70
70
  * Fetch from remote and check if remote branch is ahead of local.
@@ -1 +1 @@
1
- {"version":3,"file":"git.js","sourceRoot":"","sources":["../../../src/core/git.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"git.js","sourceRoot":"","sources":["../../../src/core/git.ts"],"names":[],"mappings":"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"}
@@ -1,13 +1,13 @@
1
1
  /**
2
- * json-field.ts — JSON 字段级提取与合并
2
+ * json-field.ts — JSON field-level extraction and merge
3
3
  *
4
- * 支持从大 JSON 文件中 pick 指定顶层字段进行同步,
5
- * pull merge 回目标 JSON(不破坏其他字段)。
4
+ * Supports picking specified top-level fields from large JSON files for sync;
5
+ * merges fields back into target JSON on pull (without destroying other fields).
6
6
  */
7
7
  type JsonObject = Record<string, unknown>;
8
- /** 从对象中提取指定顶层字段 */
8
+ /** Extract specified top-level fields from an object */
9
9
  export declare function extractFields(obj: JsonObject, fields: readonly string[]): JsonObject;
10
- /** 将提取的字段 shallow merge 回目标对象(仅覆盖提取字段,保留其余) */
10
+ /** Shallow merge extracted fields back into target object (only overwrites extracted fields, preserves the rest) */
11
11
  export declare function mergeFields(target: JsonObject, partial: JsonObject): JsonObject;
12
12
  export declare const jsonField: {
13
13
  readonly extractFields: typeof extractFields;
@@ -1 +1 @@
1
- {"version":3,"file":"json-field.d.ts","sourceRoot":"","sources":["../../../src/core/json-field.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,KAAK,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAE1C,mBAAmB;AACnB,wBAAgB,aAAa,CAAC,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,UAAU,CAMpF;AAED,+CAA+C;AAC/C,wBAAgB,WAAW,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,GAAG,UAAU,CAE/E;AAED,eAAO,MAAM,SAAS;;;CAA0C,CAAC"}
1
+ {"version":3,"file":"json-field.d.ts","sourceRoot":"","sources":["../../../src/core/json-field.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,KAAK,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAE1C,wDAAwD;AACxD,wBAAgB,aAAa,CAAC,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,UAAU,CAMpF;AAED,oHAAoH;AACpH,wBAAgB,WAAW,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,GAAG,UAAU,CAE/E;AAED,eAAO,MAAM,SAAS;;;CAA0C,CAAC"}
@@ -1,10 +1,10 @@
1
1
  /**
2
- * json-field.ts — JSON 字段级提取与合并
2
+ * json-field.ts — JSON field-level extraction and merge
3
3
  *
4
- * 支持从大 JSON 文件中 pick 指定顶层字段进行同步,
5
- * pull merge 回目标 JSON(不破坏其他字段)。
4
+ * Supports picking specified top-level fields from large JSON files for sync;
5
+ * merges fields back into target JSON on pull (without destroying other fields).
6
6
  */
7
- /** 从对象中提取指定顶层字段 */
7
+ /** Extract specified top-level fields from an object */
8
8
  export function extractFields(obj, fields) {
9
9
  const result = {};
10
10
  for (const f of fields) {
@@ -13,7 +13,7 @@ export function extractFields(obj, fields) {
13
13
  }
14
14
  return result;
15
15
  }
16
- /** 将提取的字段 shallow merge 回目标对象(仅覆盖提取字段,保留其余) */
16
+ /** Shallow merge extracted fields back into target object (only overwrites extracted fields, preserves the rest) */
17
17
  export function mergeFields(target, partial) {
18
18
  return { ...target, ...partial };
19
19
  }
@@ -1 +1 @@
1
- {"version":3,"file":"json-field.js","sourceRoot":"","sources":["../../../src/core/json-field.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,mBAAmB;AACnB,MAAM,UAAU,aAAa,CAAC,GAAe,EAAE,MAAyB;IACtE,MAAM,MAAM,GAAe,EAAE,CAAC;IAC9B,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,IAAI,CAAC,IAAI,GAAG;YAAE,MAAM,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;IACnC,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,+CAA+C;AAC/C,MAAM,UAAU,WAAW,CAAC,MAAkB,EAAE,OAAmB;IACjE,OAAO,EAAE,GAAG,MAAM,EAAE,GAAG,OAAO,EAAE,CAAC;AACnC,CAAC;AAED,MAAM,CAAC,MAAM,SAAS,GAAG,EAAE,aAAa,EAAE,WAAW,EAAW,CAAC"}
1
+ {"version":3,"file":"json-field.js","sourceRoot":"","sources":["../../../src/core/json-field.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,wDAAwD;AACxD,MAAM,UAAU,aAAa,CAAC,GAAe,EAAE,MAAyB;IACtE,MAAM,MAAM,GAAe,EAAE,CAAC;IAC9B,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,IAAI,CAAC,IAAI,GAAG;YAAE,MAAM,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;IACnC,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,oHAAoH;AACpH,MAAM,UAAU,WAAW,CAAC,MAAkB,EAAE,OAAmB;IACjE,OAAO,EAAE,GAAG,MAAM,EAAE,GAAG,OAAO,EAAE,CAAC;AACnC,CAAC;AAED,MAAM,CAAC,MAAM,SAAS,GAAG,EAAE,aAAa,EAAE,WAAW,EAAW,CAAC"}
@@ -1,16 +1,16 @@
1
1
  /**
2
- * sync.ts — 同步引擎核心
2
+ * sync.ts — Core sync engine
3
3
  *
4
- * 三个方向:
5
- * stageToRepo 工作区本地仓库目录(推送前准备)
6
- * restoreFromRepo 本地仓库目录工作区(拉取后还原)
7
- * diff 对比两侧,返回差异摘要
4
+ * Three directions:
5
+ * stageToRepo workspacelocal repo directory (pre-push staging)
6
+ * restoreFromRepo local repo directory workspace (post-pull restore)
7
+ * diff compare both sides, return diff summary
8
8
  *
9
- * 支持三层同步:
10
- * shared — agent 共享(skillsMCP 模板、共享记忆)
11
- * agents/* — per-agent 跨环境同步
9
+ * Supports two-tier sync:
10
+ * shared — cross-agent sharing (skills, MCP templates, shared memory)
11
+ * agents/* — per-agent cross-environment sync
12
12
  *
13
- * 所有方法支持可选的 agent 过滤参数,只操作指定智能体的文件。
13
+ * All methods accept an optional agent filter parameter to operate on a specific agent's files only.
14
14
  */
15
15
  import type { WangchuanConfig, FileEntry, StageResult, RestoreResult, DiffResult, AgentName, FilterOptions } from '../types.js';
16
16
  export declare function expandHome(p: string): string;
@@ -1,16 +1,16 @@
1
1
  /**
2
- * sync.ts — 同步引擎核心
2
+ * sync.ts — Core sync engine
3
3
  *
4
- * 三个方向:
5
- * stageToRepo 工作区本地仓库目录(推送前准备)
6
- * restoreFromRepo 本地仓库目录工作区(拉取后还原)
7
- * diff 对比两侧,返回差异摘要
4
+ * Three directions:
5
+ * stageToRepo workspacelocal repo directory (pre-push staging)
6
+ * restoreFromRepo local repo directory workspace (post-pull restore)
7
+ * diff compare both sides, return diff summary
8
8
  *
9
- * 支持三层同步:
10
- * shared — agent 共享(skillsMCP 模板、共享记忆)
11
- * agents/* — per-agent 跨环境同步
9
+ * Supports two-tier sync:
10
+ * shared — cross-agent sharing (skills, MCP templates, shared memory)
11
+ * agents/* — per-agent cross-environment sync
12
12
  *
13
- * 所有方法支持可选的 agent 过滤参数,只操作指定智能体的文件。
13
+ * All methods accept an optional agent filter parameter to operate on a specific agent's files only.
14
14
  */
15
15
  import fs from 'fs';
16
16
  import path from 'path';
@@ -136,7 +136,7 @@ function walkDir(dirAbs) {
136
136
  fs.readdirSync(dirAbs).forEach(f => walk(f));
137
137
  return results;
138
138
  }
139
- /** repoRel 去重,保留第一个出现的条目 */
139
+ /** Deduplicate by repoRel, keeping the first occurrence */
140
140
  function deduplicateEntries(entries) {
141
141
  const seen = new Set();
142
142
  return entries.filter(e => {
@@ -159,7 +159,7 @@ function logProgress(index, total, tag, filePath) {
159
159
  logger.info(` ${counter} ${coloredTag} ${chalk.white(filePath)}`);
160
160
  }
161
161
  /**
162
- * 为指定 agent profile 生成 syncFiles + syncDirs + jsonFields 条目
162
+ * Build syncFiles + syncDirs + jsonFields entries for a given agent profile.
163
163
  */
164
164
  function buildAgentEntries(name, profile, repoDirBase) {
165
165
  const entries = [];
@@ -195,7 +195,7 @@ function buildAgentEntries(name, profile, repoDirBase) {
195
195
  });
196
196
  }
197
197
  }
198
- // jsonFields — 字段级 JSON 提取
198
+ // jsonFields — field-level JSON extraction
199
199
  for (const jf of (profile.jsonFields ?? [])) {
200
200
  const suffix = jf.encrypt ? '.enc' : '';
201
201
  entries.push({
@@ -213,7 +213,7 @@ function buildAgentEntries(name, profile, repoDirBase) {
213
213
  return entries;
214
214
  }
215
215
  /**
216
- * 构建 shared tier 条目(skillsMCP 模板、共享文件)
216
+ * Build shared tier entries (skills, MCP templates, shared files).
217
217
  */
218
218
  function buildSharedEntries(cfg, repoDirBase) {
219
219
  const entries = [];
@@ -221,7 +221,7 @@ function buildSharedEntries(cfg, repoDirBase) {
221
221
  if (!shared)
222
222
  return entries;
223
223
  const profiles = cfg.profiles.default;
224
- // ── shared skills:多源汇聚 ────────────────────────────────
224
+ // ── shared skills: multi-source aggregation ────────────────
225
225
  for (const source of shared.skills.sources) {
226
226
  const p = profiles[source.agent];
227
227
  if (!p.enabled)
@@ -233,7 +233,7 @@ function buildSharedEntries(cfg, repoDirBase) {
233
233
  if (!fs.existsSync(scanBase))
234
234
  continue;
235
235
  for (const relFile of walkDir(scanBase)) {
236
- // 跳过 .DS_Store 等系统文件
236
+ // Skip system files like .DS_Store
237
237
  if (path.basename(relFile).startsWith('.'))
238
238
  continue;
239
239
  entries.push({
@@ -245,7 +245,7 @@ function buildSharedEntries(cfg, repoDirBase) {
245
245
  });
246
246
  }
247
247
  }
248
- // ── shared MCP:从各 agent JSON 中提取 mcpServers ──────
248
+ // ── shared MCP: extract mcpServers from each agent's JSON ──
249
249
  for (const source of shared.mcp.sources) {
250
250
  const p = profiles[source.agent];
251
251
  if (!p.enabled)
@@ -308,30 +308,30 @@ function applyFilter(entries, filter) {
308
308
  export function buildFileEntries(cfg, repoDirBase, agent, filter) {
309
309
  const entries = [];
310
310
  const profiles = cfg.profiles.default;
311
- // per-agent 条目
311
+ // per-agent entries
312
312
  for (const name of AGENT_NAMES) {
313
313
  const p = profiles[name];
314
314
  if (!p.enabled || (agent && agent !== name))
315
315
  continue;
316
316
  entries.push(...buildAgentEntries(name, p, repoDirBase));
317
317
  }
318
- // shared 条目(--agent 过滤时不包含 shared,因为 shared 不属于任何单一 agent
318
+ // shared entries (excluded when --agent filter is active, since shared belongs to no single agent)
319
319
  if (!agent) {
320
320
  entries.push(...buildSharedEntries(cfg, repoDirBase));
321
321
  }
322
322
  return applyFilter(deduplicateEntries(entries), filter);
323
323
  }
324
324
  /**
325
- * shared 内容(skillsMCP 配置)分发到各 agent 的本地目录。
326
- * push 前调用,确保各 agent 在推送前已获得最新共享资源。
325
+ * Distribute shared content (skills, MCP configs) to each agent's local directory.
326
+ * Called before push to ensure all agents have the latest shared resources.
327
327
  */
328
328
  function distributeShared(cfg) {
329
329
  const shared = cfg.shared;
330
330
  if (!shared)
331
331
  return;
332
332
  const profiles = cfg.profiles.default;
333
- // ── 分发 skills:从每个 source 收集,只添加对方完全没有的新 skill ──
334
- // 收集各 agent 当前拥有的 skill 集合
333
+ // ── Distribute skills: collect from each source, only add skills the target is missing ──
334
+ // Collect each agent's current skill set
335
335
  const agentSkills = new Map(); // agent → relPath → absPath
336
336
  for (const source of shared.skills.sources) {
337
337
  const p = profiles[source.agent];
@@ -348,7 +348,7 @@ function distributeShared(cfg) {
348
348
  }
349
349
  agentSkills.set(source.agent, skills);
350
350
  }
351
- // 合并所有 agent skill(去重,先出现者优先)
351
+ // Merge all agents' skills (deduplicate, first occurrence wins)
352
352
  const allSkills = new Map();
353
353
  for (const skills of agentSkills.values()) {
354
354
  for (const [rel, abs] of skills) {
@@ -356,7 +356,7 @@ function distributeShared(cfg) {
356
356
  allSkills.set(rel, abs);
357
357
  }
358
358
  }
359
- // 分发:只把某 agent 缺少的 skill 复制过去(skill 存在于全局集合中)
359
+ // Distribute: only copy skills that a given agent is missing (present in global set)
360
360
  for (const source of shared.skills.sources) {
361
361
  const p = profiles[source.agent];
362
362
  if (!p.enabled)
@@ -365,14 +365,14 @@ function distributeShared(cfg) {
365
365
  const skillsDir = path.join(expandHome(p.workspacePath), source.dir);
366
366
  for (const [relFile, srcAbs] of allSkills) {
367
367
  if (mySkills.has(relFile))
368
- continue; // 已有,不覆盖
368
+ continue; // already exists, do not overwrite
369
369
  const dest = path.join(skillsDir, relFile);
370
370
  fs.mkdirSync(path.dirname(dest), { recursive: true });
371
371
  fs.copyFileSync(srcAbs, dest);
372
372
  logger.debug(` ${t('sync.distributeSkill', { file: relFile, agent: source.agent })}`);
373
373
  }
374
374
  }
375
- // ── 分发 MCP 配置:从每个 source 提取,merge 到其他 agent ──
375
+ // ── Distribute MCP configs: extract from each source, merge into other agents ──
376
376
  const mergedMcp = {};
377
377
  for (const source of shared.mcp.sources) {
378
378
  const p = profiles[source.agent];
@@ -388,9 +388,9 @@ function distributeShared(cfg) {
388
388
  Object.assign(mergedMcp, mcpField);
389
389
  }
390
390
  }
391
- catch { /* 忽略解析失败 */ }
391
+ catch { /* ignore parse failures */ }
392
392
  }
393
- // 写回到每个 source agent MCP 配置(文件不存在时创建)
393
+ // Write back to each source agent's MCP config (create file if missing)
394
394
  if (Object.keys(mergedMcp).length > 0) {
395
395
  for (const source of shared.mcp.sources) {
396
396
  const p = profiles[source.agent];
@@ -403,7 +403,7 @@ function distributeShared(cfg) {
403
403
  json = JSON.parse(fs.readFileSync(srcPath, 'utf-8'));
404
404
  }
405
405
  const currentMcp = (json[source.field] ?? {});
406
- // 只添加本地没有的 MCP server,不覆盖已有配置
406
+ // Only add MCP servers not present locally; do not overwrite existing configs
407
407
  let changed = false;
408
408
  for (const [key, val] of Object.entries(mergedMcp)) {
409
409
  if (!(key in currentMcp)) {
@@ -418,13 +418,13 @@ function distributeShared(cfg) {
418
418
  logger.debug(` ${t('sync.distributeMcp', { agent: source.agent })}`);
419
419
  }
420
420
  }
421
- catch { /* 忽略 */ }
421
+ catch { /* ignore */ }
422
422
  }
423
423
  }
424
424
  }
425
425
  /**
426
- * 清理 repo 中的过期文件 — repo 有但当前 entries 中不包含的条目删除。
427
- * 仅清理 agents/ shared/ 目录下的文件(不删 .git 等)。
426
+ * Prune stale files from repo — delete entries present in repo but absent from current entries.
427
+ * Only prunes files under agents/ and shared/ directories (does not touch .git etc.).
428
428
  */
429
429
  function pruneRepoStaleFiles(repoPath, entries) {
430
430
  const activeRepoRels = new Set(entries.map(e => e.repoRel));
@@ -442,7 +442,7 @@ function pruneRepoStaleFiles(repoPath, entries) {
442
442
  fs.unlinkSync(abs);
443
443
  deleted.push(repoRel);
444
444
  logger.debug(` ${t('sync.pruneStale', { file: repoRel })}`);
445
- // 清理空目录
445
+ // Clean up empty directories
446
446
  let dir = path.dirname(abs);
447
447
  while (dir !== scanRoot && dir.startsWith(scanRoot)) {
448
448
  const remaining = fs.readdirSync(dir);
@@ -698,8 +698,8 @@ export const syncEngine = {
698
698
  }
699
699
  result.synced.push(entry.repoRel);
700
700
  }
701
- // ── 清理 repo 中的过期文件(全量 push 时) ──────────────────
702
- // 只用实际写入 repo 的条目做 prune,排除本地不存在的 skipped 条目
701
+ // ── Prune stale files from repo (full push only) ──────────────
702
+ // Only prune using entries actually written to repo, excluding skipped entries with missing local files
703
703
  if (!agent) {
704
704
  const syncedEntries = entries.filter(e => fs.existsSync(e.srcAbs));
705
705
  const pruned = pruneRepoStaleFiles(repoPath, syncedEntries);
@@ -729,8 +729,8 @@ export const syncEngine = {
729
729
  for (const entry of entries) {
730
730
  const srcRepo = path.join(repoPath, entry.repoRel);
731
731
  if (!fs.existsSync(srcRepo)) {
732
- // repo 没有但本地有记录为 localOnly
733
- // jsonFields 条目:srcAbs 是完整 JSON(总是存在),需检查提取字段是否非空
732
+ // Not in repo but exists locally mark as localOnly
733
+ // jsonFields entries: srcAbs is the full JSON (always exists), check if extracted fields are non-empty
734
734
  if (entry.jsonExtract) {
735
735
  try {
736
736
  const fullJson = JSON.parse(fs.readFileSync(entry.srcAbs, 'utf-8'));
@@ -739,7 +739,7 @@ export const syncEngine = {
739
739
  result.localOnly.push(entry.repoRel);
740
740
  }
741
741
  }
742
- catch { /* JSON 解析失败则忽略 */ }
742
+ catch { /* ignore JSON parse failures */ }
743
743
  }
744
744
  else if (fs.existsSync(entry.srcAbs)) {
745
745
  result.localOnly.push(entry.repoRel);
@@ -748,7 +748,7 @@ export const syncEngine = {
748
748
  result.skipped.push(entry.repoRel);
749
749
  continue;
750
750
  }
751
- // ── JSON 字段级 merge-back ────────────────────────────────
751
+ // ── JSON field-level merge-back ────────────────────────────
752
752
  if (entry.jsonExtract) {
753
753
  let partialContent;
754
754
  if (entry.encrypt) {
@@ -758,7 +758,7 @@ export const syncEngine = {
758
758
  partialContent = fs.readFileSync(srcRepo, 'utf-8');
759
759
  }
760
760
  const partial = JSON.parse(partialContent);
761
- // 读取本地完整 JSONmerge 进去(不破坏其他字段)
761
+ // Read local full JSON, merge into it (without destroying other fields)
762
762
  const targetPath = entry.jsonExtract.originalPath;
763
763
  let fullJson = {};
764
764
  if (fs.existsSync(targetPath)) {
@@ -767,7 +767,7 @@ export const syncEngine = {
767
767
  const merged = jsonField.mergeFields(fullJson, partial);
768
768
  fs.mkdirSync(path.dirname(targetPath), { recursive: true });
769
769
  fs.writeFileSync(targetPath, JSON.stringify(merged, null, 2), 'utf-8');
770
- // shared MCP 条目:同时分发到所有其他 agent
770
+ // shared MCP entry: also distribute to all other agents
771
771
  if (entry.agentName === 'shared' && cfg.shared) {
772
772
  for (const source of cfg.shared.mcp.sources) {
773
773
  const p = cfg.profiles.default[source.agent];
@@ -775,7 +775,7 @@ export const syncEngine = {
775
775
  continue;
776
776
  const otherPath = path.join(expandHome(p.workspacePath), source.src);
777
777
  if (otherPath === targetPath)
778
- continue; // 已处理
778
+ continue; // already handled
779
779
  let otherJson = {};
780
780
  if (fs.existsSync(otherPath)) {
781
781
  try {
@@ -795,7 +795,7 @@ export const syncEngine = {
795
795
  logProgress(restoreIdx, restoreTotal, entry.encrypt ? 'decrypted' : 'field', entry.repoRel);
796
796
  continue;
797
797
  }
798
- // ── shared skills 分发到各 agent ──────────────────────────
798
+ // ── Distribute shared skills to all agents ─────────────────
799
799
  if (entry.agentName === 'shared' && entry.repoRel.startsWith('shared/skills/')) {
800
800
  const relInSkills = entry.repoRel.slice('shared/skills/'.length);
801
801
  const shared = cfg.shared;
@@ -814,7 +814,7 @@ export const syncEngine = {
814
814
  logProgress(restoreIdx, restoreTotal, 'copy', entry.repoRel);
815
815
  continue;
816
816
  }
817
- // ── 冲突检测(整文件同步) ────────────────────────────────
817
+ // ── Conflict detection (whole-file sync) ──────────────────
818
818
  if (fs.existsSync(entry.srcAbs)) {
819
819
  let isDiff = false;
820
820
  const localBuf = fs.readFileSync(entry.srcAbs);
@@ -906,7 +906,7 @@ export const syncEngine = {
906
906
  }
907
907
  }
908
908
  }
909
- // ── 写入文件 ──────────────────────────────────────────────
909
+ // ── Write file ───────────────────────────────────────────
910
910
  fs.mkdirSync(path.dirname(entry.srcAbs), { recursive: true });
911
911
  if (entry.encrypt) {
912
912
  cryptoEngine.decryptFile(srcRepo, entry.srcAbs, keyPath);
@@ -953,7 +953,7 @@ export const syncEngine = {
953
953
  diff.missing.push(entry.repoRel);
954
954
  continue;
955
955
  }
956
- // JSON 字段提取时,比较提取后的内容
956
+ // For JSON field extraction, compare the extracted content
957
957
  if (entry.jsonExtract) {
958
958
  try {
959
959
  const fullJson = JSON.parse(fs.readFileSync(entry.srcAbs, 'utf-8'));
@@ -974,7 +974,7 @@ export const syncEngine = {
974
974
  }
975
975
  continue;
976
976
  }
977
- // 整文件比较
977
+ // Whole-file comparison
978
978
  const srcBuf = fs.readFileSync(entry.srcAbs);
979
979
  const repoBuf = fs.readFileSync(path.join(repoPath, entry.repoRel));
980
980
  if (entry.encrypt) {