clawt 3.9.13 → 3.10.1

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 (106) hide show
  1. package/README.md +80 -1
  2. package/README.zh-CN.md +81 -0
  3. package/dist/index.js +1935 -592
  4. package/dist/postinstall.js +1626 -283
  5. package/docs/config-file.md +2 -0
  6. package/docs/config.md +2 -1
  7. package/docs/init.md +3 -2
  8. package/docs/project-config.md +10 -1
  9. package/docs/spec.md +69 -2
  10. package/package.json +1 -1
  11. package/src/commands/alias.ts +5 -4
  12. package/src/commands/completion.ts +2 -1
  13. package/src/commands/config.ts +25 -7
  14. package/src/commands/cover-validate.ts +3 -2
  15. package/src/commands/create.ts +8 -7
  16. package/src/commands/home.ts +2 -1
  17. package/src/commands/init.ts +13 -6
  18. package/src/commands/list.ts +6 -4
  19. package/src/commands/merge.ts +8 -7
  20. package/src/commands/projects.ts +5 -3
  21. package/src/commands/remove.ts +7 -6
  22. package/src/commands/reset.ts +3 -2
  23. package/src/commands/resume.ts +10 -7
  24. package/src/commands/run.ts +8 -7
  25. package/src/commands/status.ts +16 -11
  26. package/src/commands/sync.ts +4 -3
  27. package/src/commands/tasks.ts +8 -6
  28. package/src/commands/validate.ts +7 -6
  29. package/src/constants/ai-prompts.ts +11 -11
  30. package/src/constants/config.ts +30 -0
  31. package/src/constants/index.ts +3 -2
  32. package/src/constants/messages/alias.ts +44 -14
  33. package/src/constants/messages/cli-descriptions.ts +91 -0
  34. package/src/constants/messages/common.ts +221 -36
  35. package/src/constants/messages/completion.ts +43 -14
  36. package/src/constants/messages/config.ts +61 -18
  37. package/src/constants/messages/cover-validate.ts +43 -14
  38. package/src/constants/messages/create.ts +16 -5
  39. package/src/constants/messages/home.ts +19 -6
  40. package/src/constants/messages/index.ts +2 -0
  41. package/src/constants/messages/init.ts +45 -14
  42. package/src/constants/messages/interactive-panel.ts +183 -29
  43. package/src/constants/messages/merge.ts +140 -38
  44. package/src/constants/messages/post-create.ts +59 -19
  45. package/src/constants/messages/projects.ts +51 -14
  46. package/src/constants/messages/remove.ts +50 -15
  47. package/src/constants/messages/reset.ts +14 -4
  48. package/src/constants/messages/resume.ts +116 -19
  49. package/src/constants/messages/run.ts +165 -35
  50. package/src/constants/messages/status.ts +84 -23
  51. package/src/constants/messages/sync.ts +54 -17
  52. package/src/constants/messages/tasks.ts +21 -7
  53. package/src/constants/messages/update.ts +35 -11
  54. package/src/constants/messages/validate.ts +218 -57
  55. package/src/constants/progress.ts +17 -6
  56. package/src/constants/project-config.ts +17 -0
  57. package/src/constants/prompt.ts +18 -2
  58. package/src/constants/tasks-template.ts +56 -2
  59. package/src/hooks/post-create.ts +5 -2
  60. package/src/index.ts +6 -5
  61. package/src/types/config.ts +2 -0
  62. package/src/utils/alias.ts +2 -1
  63. package/src/utils/claude.ts +10 -9
  64. package/src/utils/config-strategy.ts +3 -3
  65. package/src/utils/dry-run.ts +2 -2
  66. package/src/utils/formatter.ts +18 -11
  67. package/src/utils/i18n.ts +63 -0
  68. package/src/utils/index.ts +2 -0
  69. package/src/utils/interactive-panel-render.ts +6 -3
  70. package/src/utils/progress-render.ts +11 -9
  71. package/src/utils/prompt.ts +2 -1
  72. package/src/utils/task-executor.ts +10 -7
  73. package/src/utils/task-file.ts +2 -1
  74. package/src/utils/terminal.ts +9 -9
  75. package/src/utils/ui-prompts.ts +4 -3
  76. package/src/utils/update-checker.ts +1 -1
  77. package/src/utils/validate-branch.ts +16 -9
  78. package/src/utils/validate-core.ts +2 -1
  79. package/src/utils/validate-runner.ts +2 -2
  80. package/src/utils/worktree-matcher.ts +9 -7
  81. package/tests/unit/commands/alias.test.ts +4 -0
  82. package/tests/unit/commands/completion.test.ts +14 -0
  83. package/tests/unit/commands/config.test.ts +61 -28
  84. package/tests/unit/commands/cover-validate.test.ts +13 -2
  85. package/tests/unit/commands/init.test.ts +6 -2
  86. package/tests/unit/commands/merge.test.ts +14 -0
  87. package/tests/unit/commands/run.test.ts +17 -0
  88. package/tests/unit/commands/tasks.test.ts +39 -9
  89. package/tests/unit/constants/config.test.ts +16 -1
  90. package/tests/unit/constants/messages-post-create.test.ts +93 -1
  91. package/tests/unit/constants/messages.test.ts +85 -1
  92. package/tests/unit/hooks/post-create.test.ts +32 -0
  93. package/tests/unit/utils/alias.test.ts +14 -0
  94. package/tests/unit/utils/claude.test.ts +24 -4
  95. package/tests/unit/utils/config-strategy.test.ts +21 -0
  96. package/tests/unit/utils/conflict-resolver.test.ts +24 -4
  97. package/tests/unit/utils/formatter.test.ts +21 -0
  98. package/tests/unit/utils/i18n.test.ts +91 -0
  99. package/tests/unit/utils/progress.test.ts +39 -18
  100. package/tests/unit/utils/prompt.test.ts +25 -2
  101. package/tests/unit/utils/task-file.test.ts +73 -10
  102. package/tests/unit/utils/terminal-cmux.test.ts +19 -4
  103. package/tests/unit/utils/update-checker.test.ts +2 -0
  104. package/tests/unit/utils/validate-branch.test.ts +26 -1
  105. package/tests/unit/utils/validation.test.ts +2 -2
  106. package/tests/unit/utils/worktree-matcher.test.ts +2 -0
@@ -1,27 +1,64 @@
1
- /** sync 命令专属提示消息 */
2
- export const SYNC_MESSAGES = {
1
+ import { createMessages } from '../../utils/i18n.js';
2
+
3
+ /** sync 命令专属提示消息(双语映射) */
4
+ const SYNC_MESSAGES_I18N = {
3
5
  /** sync 自动保存未提交变更 */
4
- SYNC_AUTO_COMMITTED: (branch: string) =>
5
- `已自动保存 ${branch} 分支的未提交变更`,
6
+ SYNC_AUTO_COMMITTED: {
7
+ en: (branch: string) =>
8
+ `Auto-saved uncommitted changes on branch ${branch}`,
9
+ 'zh-CN': (branch: string) =>
10
+ `已自动保存 ${branch} 分支的未提交变更`,
11
+ },
6
12
  /** sync 开始合并 */
7
- SYNC_MERGING: (targetBranch: string, mainBranch: string) =>
8
- `正在将 ${mainBranch} 合并到 ${targetBranch} ...`,
13
+ SYNC_MERGING: {
14
+ en: (targetBranch: string, mainBranch: string) =>
15
+ `Merging ${mainBranch} into ${targetBranch} ...`,
16
+ 'zh-CN': (targetBranch: string, mainBranch: string) =>
17
+ `正在将 ${mainBranch} 合并到 ${targetBranch} ...`,
18
+ },
9
19
  /** sync 成功 */
10
- SYNC_SUCCESS: (targetBranch: string, mainBranch: string) =>
11
- `✓ 已将 ${mainBranch} 的最新代码同步到 ${targetBranch}`,
20
+ SYNC_SUCCESS: {
21
+ en: (targetBranch: string, mainBranch: string) =>
22
+ `✓ Synced latest code from ${mainBranch} to ${targetBranch}`,
23
+ 'zh-CN': (targetBranch: string, mainBranch: string) =>
24
+ `✓ 已将 ${mainBranch} 的最新代码同步到 ${targetBranch}`,
25
+ },
12
26
  /** sync 冲突 */
13
- SYNC_CONFLICT: (worktreePath: string) =>
14
- `合并存在冲突,请进入目标 worktree 手动解决:\n cd ${worktreePath}\n 解决冲突后执行 git add . && git merge --continue\n clawt validate -b <branch> 验证变更`,
27
+ SYNC_CONFLICT: {
28
+ en: (worktreePath: string) =>
29
+ `Merge conflicts detected. Please resolve them in the target worktree:\n cd ${worktreePath}\n After resolving conflicts, run: git add . && git merge --continue\n Then validate changes with: clawt validate -b <branch>`,
30
+ 'zh-CN': (worktreePath: string) =>
31
+ `合并存在冲突,请进入目标 worktree 手动解决:\n cd ${worktreePath}\n 解决冲突后执行 git add . && git merge --continue\n clawt validate -b <branch> 验证变更`,
32
+ },
15
33
  /** sync 无可用 worktree */
16
- SYNC_NO_WORKTREES: '当前项目没有可用的 worktree,请先通过 clawt run 或 clawt create 创建',
34
+ SYNC_NO_WORKTREES: {
35
+ en: 'No worktrees available. Please create one with: clawt run or clawt create',
36
+ 'zh-CN': '当前项目没有可用的 worktree,请先通过 clawt run 或 clawt create 创建',
37
+ },
17
38
  /** sync 模糊匹配无结果,列出可用分支 */
18
- SYNC_NO_MATCH: (name: string, branches: string[]) =>
19
- `未找到与 "${name}" 匹配的分支\n 可用分支:\n${branches.map((b) => ` - ${b}`).join('\n')}`,
39
+ SYNC_NO_MATCH: {
40
+ en: (name: string, branches: string[]) =>
41
+ `No branches matching "${name}"\n Available branches:\n${branches.map((b) => ` - ${b}`).join('\n')}`,
42
+ 'zh-CN': (name: string, branches: string[]) =>
43
+ `未找到与 "${name}" 匹配的分支\n 可用分支:\n${branches.map((b) => ` - ${b}`).join('\n')}`,
44
+ },
20
45
  /** sync 交互选择提示 */
21
- SYNC_SELECT_BRANCH: '请选择要同步的分支',
46
+ SYNC_SELECT_BRANCH: {
47
+ en: 'Select branches to sync',
48
+ 'zh-CN': '请选择要同步的分支',
49
+ },
22
50
  /** sync 模糊匹配到多个结果提示 */
23
- SYNC_MULTIPLE_MATCHES: (name: string) => `"${name}" 匹配到多个分支,请选择:`,
51
+ SYNC_MULTIPLE_MATCHES: {
52
+ en: (name: string) => `"${name}" matched multiple branches, please select:`,
53
+ 'zh-CN': (name: string) => `"${name}" 匹配到多个分支,请选择:`,
54
+ },
24
55
  /** sync 后验证分支已重建提示 */
25
- SYNC_VALIDATE_BRANCH_REBUILT: (validateBranch: string) =>
26
- `验证分支 ${validateBranch} 已重建`,
56
+ SYNC_VALIDATE_BRANCH_REBUILT: {
57
+ en: (validateBranch: string) =>
58
+ `Validation branch ${validateBranch} has been rebuilt`,
59
+ 'zh-CN': (validateBranch: string) =>
60
+ `验证分支 ${validateBranch} 已重建`,
61
+ },
27
62
  } as const;
63
+
64
+ export const SYNC_MESSAGES = createMessages(SYNC_MESSAGES_I18N);
@@ -1,10 +1,24 @@
1
- /** tasks 命令相关提示消息 */
2
- export const TASKS_CMD_MESSAGES = {
1
+ import { createMessages } from '../../utils/i18n.js';
2
+
3
+ /** tasks 命令相关提示消息(双语映射) */
4
+ const TASKS_CMD_MESSAGES_I18N = {
3
5
  /** 任务模板文件已存在 */
4
- TASK_INIT_FILE_EXISTS: (path: string) => `文件已存在: ${path},如需覆盖请先删除`,
6
+ TASK_INIT_FILE_EXISTS: {
7
+ en: (path: string) => `File already exists: ${path}, delete it first to overwrite`,
8
+ 'zh-CN': (path: string) => `文件已存在: ${path},如需覆盖请先删除`,
9
+ },
5
10
  /** 任务模板生成成功 */
6
- TASK_INIT_SUCCESS: (path: string) => `✓ 任务模板已生成: ${path}`,
11
+ TASK_INIT_SUCCESS: {
12
+ en: (path: string) => `✓ Task template generated: ${path}`,
13
+ 'zh-CN': (path: string) => `✓ 任务模板已生成: ${path}`,
14
+ },
7
15
  /** 任务模板使用提示(分行列出 run 和 resume 两种用法) */
8
- TASK_INIT_HINT: (path: string) =>
9
- `执行任务:\n clawt run -f ${path} # 创建 worktree 并执行(分支名需不存在)\n clawt resume -f ${path} # 在已有 worktree 中追问(分支名需已存在)`,
10
- } as const;
16
+ TASK_INIT_HINT: {
17
+ en: (path: string) =>
18
+ `Run task:\n clawt run -f ${path} # Create worktree and execute (branch name must not exist)\n clawt resume -f ${path} # Resume in existing worktree (branch name must exist)`,
19
+ 'zh-CN': (path: string) =>
20
+ `执行任务:\n clawt run -f ${path} # 创建 worktree 并执行(分支名需不存在)\n clawt resume -f ${path} # 在已有 worktree 中追问(分支名需已存在)`,
21
+ },
22
+ };
23
+
24
+ export const TASKS_CMD_MESSAGES = createMessages(TASKS_CMD_MESSAGES_I18N);
@@ -1,15 +1,39 @@
1
+ import { createMessages } from '../../utils/i18n.js';
2
+
3
+ /** 各包管理器对应的全局安装命令(双语映射,命令本身不需要翻译) */
4
+ const UPDATE_COMMANDS_I18N = {
5
+ npm: {
6
+ en: 'npm i -g clawt',
7
+ 'zh-CN': 'npm i -g clawt',
8
+ },
9
+ pnpm: {
10
+ en: 'pnpm add -g clawt',
11
+ 'zh-CN': 'pnpm add -g clawt',
12
+ },
13
+ yarn: {
14
+ en: 'yarn global add clawt',
15
+ 'zh-CN': 'yarn global add clawt',
16
+ },
17
+ };
18
+
1
19
  /** 各包管理器对应的全局安装命令 */
2
- export const UPDATE_COMMANDS: Record<string, string> = {
3
- npm: 'npm i -g clawt',
4
- pnpm: 'pnpm add -g clawt',
5
- yarn: 'yarn global add clawt',
6
- } as const;
20
+ export const UPDATE_COMMANDS = createMessages(UPDATE_COMMANDS_I18N);
7
21
 
8
- /** 更新检查相关提示消息 */
9
- export const UPDATE_MESSAGES = {
22
+ /** 更新检查相关提示消息(双语映射) */
23
+ const UPDATE_MESSAGES_I18N = {
10
24
  /** 版本更新提示 */
11
- UPDATE_AVAILABLE: (currentVersion: string, latestVersion: string) =>
12
- `clawt 有新版本可用: ${currentVersion} ${latestVersion}`,
25
+ UPDATE_AVAILABLE: {
26
+ en: (currentVersion: string, latestVersion: string) =>
27
+ `clawt update available: ${currentVersion} → ${latestVersion}`,
28
+ 'zh-CN': (currentVersion: string, latestVersion: string) =>
29
+ `clawt 有新版本可用: ${currentVersion} → ${latestVersion}`,
30
+ },
13
31
  /** 更新操作提示 */
14
- UPDATE_HINT: (command: string) => `执行 ${command} 进行更新`,
15
- } as const;
32
+ UPDATE_HINT: {
33
+ en: (command: string) => `Run ${command} to update`,
34
+ 'zh-CN': (command: string) => `执行 ${command} 进行更新`,
35
+ },
36
+ };
37
+
38
+ /** 更新检查相关提示消息 */
39
+ export const UPDATE_MESSAGES = createMessages(UPDATE_MESSAGES_I18N);
@@ -1,89 +1,250 @@
1
- /** validate 命令专属提示消息 */
2
- export const VALIDATE_MESSAGES = {
1
+ import { createMessages } from '../../utils/i18n.js';
2
+
3
+ /** validate 命令专属提示消息(双语映射) */
4
+ const VALIDATE_MESSAGES_I18N = {
3
5
  /** validate 成功 */
4
- VALIDATE_SUCCESS: (branch: string) =>
5
- `✓ 已将分支 ${branch} 的变更应用到主 worktree\n 可以开始验证了`,
6
+ VALIDATE_SUCCESS: {
7
+ en: (branch: string) =>
8
+ `✓ Changes from branch ${branch} applied to main worktree\n Ready for validation`,
9
+ 'zh-CN': (branch: string) =>
10
+ `✓ 已将分支 ${branch} 的变更应用到主 worktree\n 可以开始验证了`,
11
+ },
6
12
  /** 增量 validate 成功提示 */
7
- INCREMENTAL_VALIDATE_SUCCESS: (branch: string) =>
8
- `✓ 已将分支 ${branch} 的最新变更应用到主 worktree(增量模式)\n 暂存区 = 上次快照,工作目录 = 最新变更`,
13
+ INCREMENTAL_VALIDATE_SUCCESS: {
14
+ en: (branch: string) =>
15
+ `✓ Latest changes from branch ${branch} applied to main worktree (incremental mode)\n Staging area = last snapshot, Working directory = latest changes`,
16
+ 'zh-CN': (branch: string) =>
17
+ `✓ 已将分支 ${branch} 的最新变更应用到主 worktree(增量模式)\n 暂存区 = 上次快照,工作目录 = 最新变更`,
18
+ },
9
19
  /** 增量 validate 降级为全量模式提示 */
10
- INCREMENTAL_VALIDATE_FALLBACK: '增量对比失败,已降级为全量模式',
20
+ INCREMENTAL_VALIDATE_FALLBACK: {
21
+ en: 'Incremental comparison failed, fell back to full mode',
22
+ 'zh-CN': '增量对比失败,已降级为全量模式',
23
+ },
11
24
  /** 增量 validate 检测到目标 worktree 无新变更 */
12
- INCREMENTAL_VALIDATE_NO_CHANGES: (branch: string) =>
13
- `分支 ${branch} 自上次 validate 以来没有新的变更,已恢复到上次验证状态`,
25
+ INCREMENTAL_VALIDATE_NO_CHANGES: {
26
+ en: (branch: string) =>
27
+ `Branch ${branch} has no new changes since last validate, restored to previous validation state`,
28
+ 'zh-CN': (branch: string) =>
29
+ `分支 ${branch} 自上次 validate 以来没有新的变更,已恢复到上次验证状态`,
30
+ },
14
31
  /** validate 状态已清理 */
15
- VALIDATE_CLEANED: (branch: string) => `✓ 分支 ${branch} 的 validate 状态已清理`,
32
+ VALIDATE_CLEANED: {
33
+ en: (branch: string) => `✓ Validate state for branch ${branch} cleaned`,
34
+ 'zh-CN': (branch: string) => `✓ 分支 ${branch} 的 validate 状态已清理`,
35
+ },
16
36
  /** validate patch apply 失败,提示用户同步主分支 */
17
- VALIDATE_PATCH_APPLY_FAILED: (branch: string) =>
18
- `变更迁移失败:目标分支与主分支差异过大\n 请先执行 clawt sync -b ${branch} 同步主分支后重试`,
37
+ VALIDATE_PATCH_APPLY_FAILED: {
38
+ en: (branch: string) =>
39
+ `Change migration failed: target branch has diverged too far from main\n Please run clawt sync -b ${branch} first, then retry`,
40
+ 'zh-CN': (branch: string) =>
41
+ `变更迁移失败:目标分支与主分支差异过大\n 请先执行 clawt sync -b ${branch} 同步主分支后重试`,
42
+ },
19
43
  /** validate 无可用 worktree */
20
- VALIDATE_NO_WORKTREES: '当前项目没有可用的 worktree,请先通过 clawt run 或 clawt create 创建',
44
+ VALIDATE_NO_WORKTREES: {
45
+ en: 'No worktrees available, please create one with clawt run or clawt create first',
46
+ 'zh-CN': '当前项目没有可用的 worktree,请先通过 clawt run 或 clawt create 创建',
47
+ },
21
48
  /** validate 模糊匹配无结果,列出可用分支 */
22
- VALIDATE_NO_MATCH: (name: string, branches: string[]) =>
23
- `未找到与 "${name}" 匹配的分支\n 可用分支:\n${branches.map((b) => ` - ${b}`).join('\n')}`,
49
+ VALIDATE_NO_MATCH: {
50
+ en: (name: string, branches: string[]) =>
51
+ `No branch matching "${name}"\n Available branches:\n${branches.map((b) => ` - ${b}`).join('\n')}`,
52
+ 'zh-CN': (name: string, branches: string[]) =>
53
+ `未找到与 "${name}" 匹配的分支\n 可用分支:\n${branches.map((b) => ` - ${b}`).join('\n')}`,
54
+ },
24
55
  /** validate 交互选择提示 */
25
- VALIDATE_SELECT_BRANCH: '请选择要验证的分支',
56
+ VALIDATE_SELECT_BRANCH: {
57
+ en: 'Select a branch to validate',
58
+ 'zh-CN': '请选择要验证的分支',
59
+ },
26
60
  /** validate 模糊匹配到多个结果提示 */
27
- VALIDATE_MULTIPLE_MATCHES: (name: string) => `"${name}" 匹配到多个分支,请选择:`,
61
+ VALIDATE_MULTIPLE_MATCHES: {
62
+ en: (name: string) => `"${name}" matched multiple branches, please select:`,
63
+ 'zh-CN': (name: string) => `"${name}" 匹配到多个分支,请选择:`,
64
+ },
28
65
  /** --run 命令开始执行提示 */
29
- VALIDATE_RUN_START: (command: string) => `正在主 worktree 中执行命令: ${command}`,
66
+ VALIDATE_RUN_START: {
67
+ en: (command: string) => `Running command in main worktree: ${command}`,
68
+ 'zh-CN': (command: string) => `正在主 worktree 中执行命令: ${command}`,
69
+ },
30
70
  /** --run 命令执行成功(退出码 0) */
31
- VALIDATE_RUN_SUCCESS: (command: string) => `✓ 命令执行完成: ${command},退出码: 0`,
71
+ VALIDATE_RUN_SUCCESS: {
72
+ en: (command: string) => `✓ Command completed: ${command}, exit code: 0`,
73
+ 'zh-CN': (command: string) => `✓ 命令执行完成: ${command},退出码: 0`,
74
+ },
32
75
  /** --run 命令执行失败(退出码非 0) */
33
- VALIDATE_RUN_FAILED: (command: string, exitCode: number) =>
34
- `✗ 命令执行完成: ${command},退出码: ${exitCode}`,
76
+ VALIDATE_RUN_FAILED: {
77
+ en: (command: string, exitCode: number) =>
78
+ `✗ Command completed: ${command}, exit code: ${exitCode}`,
79
+ 'zh-CN': (command: string, exitCode: number) =>
80
+ `✗ 命令执行完成: ${command},退出码: ${exitCode}`,
81
+ },
35
82
  /** --run 命令执行异常(进程启动失败等) */
36
- VALIDATE_RUN_ERROR: (command: string, errorMessage: string) =>
37
- `✗ 命令执行出错: ${errorMessage}`,
83
+ VALIDATE_RUN_ERROR: {
84
+ en: (command: string, errorMessage: string) =>
85
+ `✗ Command execution error: ${errorMessage}`,
86
+ 'zh-CN': (command: string, errorMessage: string) =>
87
+ `✗ 命令执行出错: ${errorMessage}`,
88
+ },
38
89
  /** 并行命令开始执行提示 */
39
- VALIDATE_PARALLEL_RUN_START: (count: number) =>
40
- `正在并行执行 ${count} 个命令...`,
90
+ VALIDATE_PARALLEL_RUN_START: {
91
+ en: (count: number) =>
92
+ `Running ${count} command(s) in parallel...`,
93
+ 'zh-CN': (count: number) =>
94
+ `正在并行执行 ${count} 个命令...`,
95
+ },
41
96
  /** 并行执行中单个命令开始提示(带序号) */
42
- VALIDATE_PARALLEL_CMD_START: (index: number, total: number, command: string) =>
43
- `[${index}/${total}] ${command}`,
97
+ VALIDATE_PARALLEL_CMD_START: {
98
+ en: (index: number, total: number, command: string) =>
99
+ `[${index}/${total}] ${command}`,
100
+ 'zh-CN': (index: number, total: number, command: string) =>
101
+ `[${index}/${total}] ${command}`,
102
+ },
44
103
  /** 并行执行全部成功汇总提示 */
45
- VALIDATE_PARALLEL_RUN_ALL_SUCCESS: (count: number) =>
46
- `✓ 全部 ${count} 个命令执行成功`,
104
+ VALIDATE_PARALLEL_RUN_ALL_SUCCESS: {
105
+ en: (count: number) =>
106
+ `✓ All ${count} command(s) completed successfully`,
107
+ 'zh-CN': (count: number) =>
108
+ `✓ 全部 ${count} 个命令执行成功`,
109
+ },
47
110
  /** 并行执行部分失败汇总提示 */
48
- VALIDATE_PARALLEL_RUN_SUMMARY: (successCount: number, failedCount: number) =>
49
- `共 ${successCount + failedCount} 个命令,${successCount} 个成功,${failedCount} 个失败`,
111
+ VALIDATE_PARALLEL_RUN_SUMMARY: {
112
+ en: (successCount: number, failedCount: number) =>
113
+ `${successCount + failedCount} command(s), ${successCount} succeeded, ${failedCount} failed`,
114
+ 'zh-CN': (successCount: number, failedCount: number) =>
115
+ `共 ${successCount + failedCount} 个命令,${successCount} 个成功,${failedCount} 个失败`,
116
+ },
50
117
  /** 并行执行中单个命令成功 */
51
- VALIDATE_PARALLEL_CMD_SUCCESS: (command: string) =>
52
- ` ✓ ${command}`,
118
+ VALIDATE_PARALLEL_CMD_SUCCESS: {
119
+ en: (command: string) =>
120
+ ` ✓ ${command}`,
121
+ 'zh-CN': (command: string) =>
122
+ ` ✓ ${command}`,
123
+ },
53
124
  /** 并行执行中单个命令失败 */
54
- VALIDATE_PARALLEL_CMD_FAILED: (command: string, exitCode: number) =>
55
- ` ✗ ${command}(退出码: ${exitCode})`,
125
+ VALIDATE_PARALLEL_CMD_FAILED: {
126
+ en: (command: string, exitCode: number) =>
127
+ ` ✗ ${command} (exit code: ${exitCode})`,
128
+ 'zh-CN': (command: string, exitCode: number) =>
129
+ ` ✗ ${command}(退出码: ${exitCode})`,
130
+ },
56
131
  /** 并行执行中单个命令启动失败 */
57
- VALIDATE_PARALLEL_CMD_ERROR: (command: string, errorMessage: string) =>
58
- ` ✗ ${command}(错误: ${errorMessage})`,
132
+ VALIDATE_PARALLEL_CMD_ERROR: {
133
+ en: (command: string, errorMessage: string) =>
134
+ ` ✗ ${command} (error: ${errorMessage})`,
135
+ 'zh-CN': (command: string, errorMessage: string) =>
136
+ ` ✗ ${command}(错误: ${errorMessage})`,
137
+ },
59
138
  /** patch apply 失败后询问用户是否执行 sync */
60
- VALIDATE_CONFIRM_AUTO_SYNC: (branch: string) =>
61
- `是否立即执行 sync 同步主分支到 ${branch}?`,
139
+ VALIDATE_CONFIRM_AUTO_SYNC: {
140
+ en: (branch: string) =>
141
+ `Run sync now to sync main branch to ${branch}?`,
142
+ 'zh-CN': (branch: string) =>
143
+ `是否立即执行 sync 同步主分支到 ${branch}?`,
144
+ },
62
145
  /** 自动 sync 开始提示 */
63
- VALIDATE_AUTO_SYNC_START: (branch: string) =>
64
- `正在自动同步主分支到 ${branch} ...`,
146
+ VALIDATE_AUTO_SYNC_START: {
147
+ en: (branch: string) =>
148
+ `Auto-syncing main branch to ${branch} ...`,
149
+ 'zh-CN': (branch: string) =>
150
+ `正在自动同步主分支到 ${branch} ...`,
151
+ },
65
152
  /** 用户拒绝自动 sync */
66
- VALIDATE_AUTO_SYNC_DECLINED: (branch: string) =>
67
- `请手动执行 clawt sync -b ${branch} 同步主分支后重试`,
153
+ VALIDATE_AUTO_SYNC_DECLINED: {
154
+ en: (branch: string) =>
155
+ `Please run clawt sync -b ${branch} manually, then retry`,
156
+ 'zh-CN': (branch: string) =>
157
+ `请手动执行 clawt sync -b ${branch} 同步主分支后重试`,
158
+ },
68
159
  /** 验证分支不存在 */
69
- VALIDATE_BRANCH_NOT_FOUND: (validateBranch: string, branch: string) =>
70
- `验证分支 ${validateBranch} 不存在,请先执行 clawt create 或 clawt run 创建分支 ${branch}`,
160
+ VALIDATE_BRANCH_NOT_FOUND: {
161
+ en: (validateBranch: string, branch: string) =>
162
+ `Validation branch ${validateBranch} does not exist, please run clawt create or clawt run to create branch ${branch} first`,
163
+ 'zh-CN': (validateBranch: string, branch: string) =>
164
+ `验证分支 ${validateBranch} 不存在,请先执行 clawt create 或 clawt run 创建分支 ${branch}`,
165
+ },
71
166
  /** validate 成功(含验证分支信息) */
72
- VALIDATE_SUCCESS_WITH_BRANCH: (branch: string, validateBranch: string) =>
73
- `✓ 已切换到验证分支 ${validateBranch} 并应用分支 ${branch} 的变更\n 可以开始验证了`,
167
+ VALIDATE_SUCCESS_WITH_BRANCH: {
168
+ en: (branch: string, validateBranch: string) =>
169
+ `✓ Switched to validation branch ${validateBranch} and applied changes from branch ${branch}\n Ready for validation`,
170
+ 'zh-CN': (branch: string, validateBranch: string) =>
171
+ `✓ 已切换到验证分支 ${validateBranch} 并应用分支 ${branch} 的变更\n 可以开始验证了`,
172
+ },
74
173
  /** 错误信息已复制到剪贴板提示 */
75
- VALIDATE_RUN_ERROR_COPIED: '✂ 错误信息已复制到剪贴板',
174
+ VALIDATE_RUN_ERROR_COPIED: {
175
+ en: '✂ Error information copied to clipboard',
176
+ 'zh-CN': '✂ 错误信息已复制到剪贴板',
177
+ },
76
178
  /** 剪贴板复制失败提示 */
77
- VALIDATE_RUN_ERROR_COPY_FAILED: '⚠ 错误信息复制到剪贴板失败',
179
+ VALIDATE_RUN_ERROR_COPY_FAILED: {
180
+ en: '⚠ Failed to copy error information to clipboard',
181
+ 'zh-CN': '⚠ 错误信息复制到剪贴板失败',
182
+ },
78
183
  /** 检测到外部软链接警告 */
79
- VALIDATE_EXTERNAL_SYMLINKS_FOUND: (count: number) =>
80
- `⚠ 检测到 ${count} 个指向 worktree 外部的软链接(可能由 AI Agent 创建),已自动移除`,
184
+ VALIDATE_EXTERNAL_SYMLINKS_FOUND: {
185
+ en: (count: number) =>
186
+ `⚠ Detected ${count} symlink(s) pointing outside the worktree (possibly created by AI Agent), auto-removed`,
187
+ 'zh-CN': (count: number) =>
188
+ `⚠ 检测到 ${count} 个指向 worktree 外部的软链接(可能由 AI Agent 创建),已自动移除`,
189
+ },
81
190
  /** 单命令(含 && 链)剪贴板错误格式 */
82
- VALIDATE_CLIPBOARD_SINGLE_ERROR: (command: string, stderr: string) =>
83
- `${command} 指令执行出错,错误信息:\n${stderr}`,
191
+ VALIDATE_CLIPBOARD_SINGLE_ERROR: {
192
+ en: (command: string, stderr: string) =>
193
+ `${command} command error:\n${stderr}`,
194
+ 'zh-CN': (command: string, stderr: string) =>
195
+ `${command} 指令执行出错,错误信息:\n${stderr}`,
196
+ },
84
197
  /** 并行命令中单个命令的剪贴板错误格式 */
85
- VALIDATE_CLIPBOARD_PARALLEL_ERROR: (command: string, stderr: string) =>
86
- `${command} 指令执行出错,错误信息:\n${stderr}`,
198
+ VALIDATE_CLIPBOARD_PARALLEL_ERROR: {
199
+ en: (command: string, stderr: string) =>
200
+ `${command} command error:\n${stderr}`,
201
+ 'zh-CN': (command: string, stderr: string) =>
202
+ `${command} 指令执行出错,错误信息:\n${stderr}`,
203
+ },
87
204
  /** 多个错误之间的分隔符 */
88
- VALIDATE_CLIPBOARD_SEPARATOR: '\n\n---\n\n',
89
- } as const;
205
+ VALIDATE_CLIPBOARD_SEPARATOR: {
206
+ en: '\n\n---\n\n',
207
+ 'zh-CN': '\n\n---\n\n',
208
+ },
209
+ // --- 从 validate-branch.ts 迁移 ---
210
+ /** 工作区仍然不干净 */
211
+ WORKSPACE_STILL_DIRTY: {
212
+ en: 'Workspace is still dirty, please resolve manually',
213
+ 'zh-CN': '工作区仍然不干净,请手动处理',
214
+ },
215
+ /** 当前分支有未提交的更改 */
216
+ UNCOMMITTED_CHANGES_ON_BRANCH: {
217
+ en: 'Current branch has uncommitted changes, please choose how to handle:\n',
218
+ 'zh-CN': '当前分支有未提交的更改,请选择处理方式:\n',
219
+ },
220
+ /** 选择处理方式 */
221
+ SELECT_ACTION: {
222
+ en: 'Select action',
223
+ 'zh-CN': '选择处理方式',
224
+ },
225
+ /** 是否继续执行? */
226
+ CONFIRM_CONTINUE_VALIDATE: {
227
+ en: 'Continue?',
228
+ 'zh-CN': '是否继续执行?',
229
+ },
230
+ /** 用户选择退出 */
231
+ USER_CHOSE_EXIT: {
232
+ en: 'User chose to exit, please resolve workspace changes manually and retry',
233
+ 'zh-CN': '用户选择退出,请手动处理工作区更改后重试',
234
+ },
235
+ // --- 从 validate-runner.ts 迁移 ---
236
+ /** 指令执行出错,退出码 */
237
+ COMMAND_EXEC_ERROR: {
238
+ en: (command: string, exitCode: number) =>
239
+ `${command} command error, exit code: ${exitCode}`,
240
+ 'zh-CN': (command: string, exitCode: number) =>
241
+ `${command} 指令执行出错,退出码: ${exitCode}`,
242
+ },
243
+ /** 退出码标签 */
244
+ EXIT_CODE_LABEL: {
245
+ en: (exitCode: number) => `Exit code: ${exitCode}`,
246
+ 'zh-CN': (exitCode: number) => `退出码: ${exitCode}`,
247
+ },
248
+ };
249
+
250
+ export const VALIDATE_MESSAGES = createMessages(VALIDATE_MESSAGES_I18N);
@@ -1,3 +1,5 @@
1
+ import { getCurrentLanguage } from '../utils/i18n.js';
2
+
1
3
  /** Braille spinner 帧序列 */
2
4
  export const SPINNER_FRAMES: readonly string[] = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
3
5
 
@@ -20,22 +22,31 @@ export const TASK_STATUS_ICONS = {
20
22
  FAILED: '✗',
21
23
  } as const;
22
24
 
23
- /** 任务状态标签 */
25
+ /** 任务状态标签(根据语言返回) */
26
+ export function getTaskStatusLabels() {
27
+ const lang = getCurrentLanguage();
28
+ return lang === 'en'
29
+ ? { PENDING: 'Pending', RUNNING: 'Running', DONE: 'Done', FAILED: 'Failed' }
30
+ : { PENDING: '排队中', RUNNING: '运行中', DONE: '完成', FAILED: '失败' };
31
+ }
32
+
33
+ /** 兼容旧代码:保留静态常量,默认中文(仅用于非动态场景) */
24
34
  export const TASK_STATUS_LABELS = {
25
- /** 排队中 */
26
35
  PENDING: '排队中',
27
- /** 运行中 */
28
36
  RUNNING: '运行中',
29
- /** 完成 */
30
37
  DONE: '完成',
31
- /** 失败 */
32
38
  FAILED: '失败',
33
39
  } as const;
34
40
 
35
41
  /** 活动描述文本的最大字符数 */
36
42
  export const ACTIVITY_TEXT_MAX_LENGTH = 30;
37
43
 
38
- /** 文本类型活动的前缀 */
44
+ /** 文本类型活动的前缀(根据语言返回) */
45
+ export function getTextActivityPrefix() {
46
+ return getCurrentLanguage() === 'en' ? 'Thinking' : '思考中';
47
+ }
48
+
49
+ /** 兼容旧代码:保留静态常量 */
39
50
  export const TEXT_ACTIVITY_PREFIX = '思考中';
40
51
 
41
52
  /** 结果预览文本的最大字符数 */
@@ -1,4 +1,5 @@
1
1
  import type { ProjectConfig, ProjectConfigDefinitions } from '../types/index.js';
2
+ import { getCurrentLanguage } from '../utils/i18n.js';
2
3
 
3
4
  /**
4
5
  * 项目级配置项完整定义(单一数据源)
@@ -52,3 +53,19 @@ export const PROJECT_DEFAULT_CONFIG: Required<ProjectConfig> = deriveDefaultConf
52
53
 
53
54
  /** 项目配置项描述映射 */
54
55
  export const PROJECT_CONFIG_DESCRIPTIONS: Record<keyof Required<ProjectConfig>, string> = deriveConfigDescriptions(PROJECT_CONFIG_DEFINITIONS);
56
+
57
+ /** 项目配置项英文描述映射 */
58
+ const PROJECT_CONFIG_DESCRIPTIONS_EN: Record<keyof Required<ProjectConfig>, string> = {
59
+ clawtMainWorkBranch: 'Main worktree branch name',
60
+ validateRunCommand: 'Command to auto-run after validate success (default for -r)',
61
+ postCreate: 'Command to auto-run after worktree creation (e.g. install dependencies)',
62
+ claudeCodeCommand: 'Claude Code CLI launch command (falls back to global config if unset)',
63
+ };
64
+
65
+ /**
66
+ * 获取国际化项目配置项描述映射
67
+ * @returns {Record<keyof Required<ProjectConfig>, string>} 当前语言的配置项描述映射
68
+ */
69
+ export function getI18nProjectConfigDescriptions(): Record<keyof Required<ProjectConfig>, string> {
70
+ return getCurrentLanguage() === 'en' ? PROJECT_CONFIG_DESCRIPTIONS_EN : PROJECT_CONFIG_DESCRIPTIONS;
71
+ }
@@ -1,4 +1,5 @@
1
1
  import chalk from 'chalk';
2
+ import { getCurrentLanguage } from '../utils/i18n.js';
2
3
 
3
4
  /** 多选列表中全选选项的标识名称 */
4
5
  export const SELECT_ALL_NAME = '__select_all__';
@@ -23,11 +24,26 @@ export const GROUP_SELECT_ALL_LABEL = (dateLabel: string): string => `[select-al
23
24
  * @param {string} relativeTime - 相对时间描述
24
25
  * @returns {string} 格式化的分隔线文本
25
26
  */
26
- export const GROUP_SEPARATOR_LABEL = (dateLabel: string, relativeTime: string): string =>
27
- `════ ${chalk.bold.hex('#FF8C00')(dateLabel)}(${chalk.hex('#FF8C00')(relativeTime)}) ════`;
27
+ export const GROUP_SEPARATOR_LABEL = (dateLabel: string, relativeTime: string): string => {
28
+ const lang = getCurrentLanguage();
29
+ const separator = lang === 'en' ? `════ ${chalk.bold.hex('#FF8C00')(dateLabel)} (${chalk.hex('#FF8C00')(relativeTime)}) ════` : `════ ${chalk.bold.hex('#FF8C00')(dateLabel)}(${chalk.hex('#FF8C00')(relativeTime)}) ════`;
30
+ return separator;
31
+ };
28
32
 
29
33
  /** 无法获取创建日期时的默认分组名称 */
34
+ export function getUnknownDateGroup(): string {
35
+ return getCurrentLanguage() === 'en' ? 'Unknown date' : '未知日期';
36
+ }
37
+
38
+ /** 兼容旧代码:保留静态常量 */
30
39
  export const UNKNOWN_DATE_GROUP = '未知日期';
31
40
 
32
41
  /** 未知日期分组的分隔线显示文本 */
42
+ export function getUnknownDateSeparatorLabel(): string {
43
+ const lang = getCurrentLanguage();
44
+ const label = lang === 'en' ? 'Unknown date' : '未知日期';
45
+ return `════ ${chalk.bold.hex('#FF8C00')(label)} ════`;
46
+ }
47
+
48
+ /** 兼容旧代码:保留静态常量 */
33
49
  export const UNKNOWN_DATE_SEPARATOR_LABEL = `════ ${chalk.bold.hex('#FF8C00')('未知日期')} ════`;
@@ -1,11 +1,41 @@
1
+ import { getCurrentLanguage } from '../utils/i18n.js';
2
+
1
3
  /** 任务模板默认输出目录 */
2
4
  export const TASK_TEMPLATE_OUTPUT_DIR = '.clawt/tasks';
3
5
 
4
6
  /** 任务模板文件名前缀 */
5
7
  export const TASK_TEMPLATE_FILENAME_PREFIX = 'clawt-tasks';
6
8
 
7
- /** 任务模板文件内容 */
8
- export const TASK_TEMPLATE_CONTENT = `# Clawt 任务文件
9
+ /**
10
+ * 获取任务模板文件内容(根据语言返回)
11
+ * @returns {string} 任务模板内容
12
+ */
13
+ export function getTaskTemplateContent(): string {
14
+ const lang = getCurrentLanguage();
15
+ if (lang === 'en') {
16
+ return `# Clawt Task File
17
+ #
18
+ # Usage: clawt run -f tasks.md
19
+ # Format: Text outside tags is ignored, each task is wrapped in START/END tags
20
+ #
21
+ # Rules:
22
+ # 1. Each task block is wrapped with <START> and <END> tags (see example below)
23
+ # 2. Use # branch: <branch-name> inside the block to declare branch name (can be omitted with -b)
24
+ # 3. Other lines inside the block are the task description (supports multi-line)
25
+
26
+ <!-- CLAWT-TASKS:START -->
27
+ # branch: feat-example-1
28
+ Write your first task description here
29
+ <!-- CLAWT-TASKS:END -->
30
+
31
+ <!-- CLAWT-TASKS:START -->
32
+ # branch: feat-example-2
33
+ Write your second task description here
34
+ Multi-line descriptions are supported
35
+ <!-- CLAWT-TASKS:END -->
36
+ `;
37
+ }
38
+ return `# Clawt 任务文件
9
39
  #
10
40
  # 使用方法: clawt run -f tasks.md
11
41
  # 格式说明: 标签外的文本会被忽略,每个任务用 START/END 标签包裹
@@ -26,3 +56,27 @@ export const TASK_TEMPLATE_CONTENT = `# Clawt 任务文件
26
56
  支持多行描述
27
57
  <!-- CLAWT-TASKS:END -->
28
58
  `;
59
+ }
60
+
61
+ /** 兼容旧代码:保留静态常量(默认中文) */
62
+ export const TASK_TEMPLATE_CONTENT = `# Clawt 任务文件
63
+ #
64
+ # 使用方法: clawt run -f tasks.md
65
+ # 格式说明: 标签外的文本会被忽略,每个任务用 START/END 标签包裹
66
+ #
67
+ # 规则:
68
+ # 1. 每个任务块用 <START> 和 <END> 标签包裹(实际标签见下方示例)
69
+ # 2. 块内 # branch: <分支名> 声明分支名(使用 -b 参数时可省略)
70
+ # 3. 块内其余行为任务描述(支持多行)
71
+
72
+ <!-- CLAWT-TASKS:START -->
73
+ # branch: feat-example-1
74
+ 在这里写第一个任务的描述
75
+ <!-- CLAWT-TASKS:END -->
76
+
77
+ <!-- CLAWT-TASKS:START -->
78
+ # branch: feat-example-2
79
+ 在这里写第二个任务的描述
80
+ 支持多行描述
81
+ <!-- CLAWT-TASKS:END -->
82
+ `;