clawt 2.3.0 → 2.3.2

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/dist/index.js CHANGED
@@ -46,11 +46,10 @@ var MESSAGES = {
46
46
  VALIDATE_SUCCESS: (branch) => `\u2713 \u5DF2\u5C06\u5206\u652F ${branch} \u7684\u53D8\u66F4\u5E94\u7528\u5230\u4E3B worktree
47
47
  \u53EF\u4EE5\u5F00\u59CB\u9A8C\u8BC1\u4E86`,
48
48
  /** merge 成功 */
49
- MERGE_SUCCESS: (branch, message) => `\u2713 \u5206\u652F ${branch} \u5DF2\u6210\u529F\u5408\u5E76\u5230\u5F53\u524D\u5206\u652F
50
- \u63D0\u4EA4\u4FE1\u606F: ${message}
51
- \u5DF2\u63A8\u9001\u5230\u8FDC\u7A0B\u4ED3\u5E93`,
49
+ MERGE_SUCCESS: (branch, message, pushed) => `\u2713 \u5206\u652F ${branch} \u5DF2\u6210\u529F\u5408\u5E76\u5230\u5F53\u524D\u5206\u652F
50
+ \u63D0\u4EA4\u4FE1\u606F: ${message}${pushed ? "\n \u5DF2\u63A8\u9001\u5230\u8FDC\u7A0B\u4ED3\u5E93" : ""}`,
52
51
  /** merge 成功(无提交信息,目标 worktree 已提交过) */
53
- MERGE_SUCCESS_NO_MESSAGE: (branch) => `\u2713 \u5206\u652F ${branch} \u5DF2\u6210\u529F\u5408\u5E76\u5230\u5F53\u524D\u5206\u652F`,
52
+ MERGE_SUCCESS_NO_MESSAGE: (branch, pushed) => `\u2713 \u5206\u652F ${branch} \u5DF2\u6210\u529F\u5408\u5E76\u5230\u5F53\u524D\u5206\u652F${pushed ? "\n \u5DF2\u63A8\u9001\u5230\u8FDC\u7A0B\u4ED3\u5E93" : ""}`,
54
53
  /** merge 冲突 */
55
54
  MERGE_CONFLICT: "\u5408\u5E76\u5B58\u5728\u51B2\u7A81\uFF0C\u8BF7\u624B\u52A8\u5904\u7406",
56
55
  /** merge 后清理 worktree 和分支成功 */
@@ -115,7 +114,10 @@ var MESSAGES = {
115
114
  /** reset 成功 */
116
115
  RESET_SUCCESS: "\u2713 \u4E3B worktree \u5DE5\u4F5C\u533A\u548C\u6682\u5B58\u533A\u5DF2\u91CD\u7F6E",
117
116
  /** reset 时工作区和暂存区已干净 */
118
- RESET_ALREADY_CLEAN: "\u4E3B worktree \u5DE5\u4F5C\u533A\u548C\u6682\u5B58\u533A\u5DF2\u662F\u5E72\u51C0\u72B6\u6001\uFF0C\u65E0\u9700\u91CD\u7F6E"
117
+ RESET_ALREADY_CLEAN: "\u4E3B worktree \u5DE5\u4F5C\u533A\u548C\u6682\u5B58\u533A\u5DF2\u662F\u5E72\u51C0\u72B6\u6001\uFF0C\u65E0\u9700\u91CD\u7F6E",
118
+ /** 批量移除部分失败 */
119
+ REMOVE_PARTIAL_FAILURE: (failures) => `\u4EE5\u4E0B worktree \u79FB\u9664\u5931\u8D25\uFF1A
120
+ ${failures.map((f) => ` \u2717 ${f.path}: ${f.error}`).join("\n")}`
119
121
  };
120
122
 
121
123
  // src/constants/exitCodes.ts
@@ -759,6 +761,7 @@ async function handleRemove(options) {
759
761
  if (!autoDelete) {
760
762
  shouldDeleteBranch = await confirmAction("\u662F\u5426\u540C\u65F6\u5220\u9664\u5BF9\u5E94\u7684\u672C\u5730\u5206\u652F\uFF1F");
761
763
  }
764
+ const failures = [];
762
765
  for (const wt of worktreesToRemove) {
763
766
  try {
764
767
  removeWorktreeByPath(wt.path);
@@ -767,13 +770,20 @@ async function handleRemove(options) {
767
770
  }
768
771
  printSuccess(MESSAGES.WORKTREE_REMOVED(wt.path));
769
772
  } catch (error) {
773
+ const errorMessage = error instanceof Error ? error.message : String(error);
770
774
  logger.error(`\u79FB\u9664 worktree \u5931\u8D25: ${wt.path} - ${error}`);
771
- throw error;
775
+ failures.push({ path: wt.path, error: errorMessage });
772
776
  }
773
777
  }
774
778
  gitWorktreePrune();
775
779
  const projectDir = getProjectWorktreeDir();
776
780
  removeEmptyDir(projectDir);
781
+ if (failures.length > 0) {
782
+ printError(MESSAGES.REMOVE_PARTIAL_FAILURE(failures));
783
+ throw new ClawtError(
784
+ `${failures.length} \u4E2A worktree \u79FB\u9664\u5931\u8D25`
785
+ );
786
+ }
777
787
  }
778
788
 
779
789
  // src/commands/run.ts
@@ -1192,16 +1202,17 @@ async function handleMerge(options) {
1192
1202
  if (hasMergeConflict(mainWorktreePath)) {
1193
1203
  throw new ClawtError(MESSAGES.MERGE_CONFLICT);
1194
1204
  }
1195
- if (getConfigValue("autoPullPush")) {
1205
+ const autoPullPush = getConfigValue("autoPullPush");
1206
+ if (autoPullPush) {
1196
1207
  gitPull(mainWorktreePath);
1197
1208
  gitPush(mainWorktreePath);
1198
1209
  } else {
1199
1210
  printInfo("\u5DF2\u8DF3\u8FC7\u81EA\u52A8 pull/push\uFF0C\u8BF7\u624B\u52A8\u6267\u884C git pull && git push");
1200
1211
  }
1201
1212
  if (options.message) {
1202
- printSuccess(MESSAGES.MERGE_SUCCESS(options.branch, options.message));
1213
+ printSuccess(MESSAGES.MERGE_SUCCESS(options.branch, options.message, autoPullPush));
1203
1214
  } else {
1204
- printSuccess(MESSAGES.MERGE_SUCCESS_NO_MESSAGE(options.branch));
1215
+ printSuccess(MESSAGES.MERGE_SUCCESS_NO_MESSAGE(options.branch, autoPullPush));
1205
1216
  }
1206
1217
  if (shouldCleanup) {
1207
1218
  cleanupWorktreeAndBranch(targetWorktreePath, options.branch);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clawt",
3
- "version": "2.3.0",
3
+ "version": "2.3.2",
4
4
  "description": "本地并行执行多个Claude Code Agent任务,融合 Git Worktree 与 Claude Code CLI 的命令行工具",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -191,7 +191,8 @@ async function handleMerge(options: MergeOptions): Promise<void> {
191
191
  }
192
192
 
193
193
  // 步骤 7:根据配置决定是否自动 pull 和 push
194
- if (getConfigValue('autoPullPush')) {
194
+ const autoPullPush = getConfigValue('autoPullPush');
195
+ if (autoPullPush) {
195
196
  gitPull(mainWorktreePath);
196
197
  gitPush(mainWorktreePath);
197
198
  } else {
@@ -200,9 +201,9 @@ async function handleMerge(options: MergeOptions): Promise<void> {
200
201
 
201
202
  // 步骤 8:输出成功提示(根据是否有 message 选择对应模板)
202
203
  if (options.message) {
203
- printSuccess(MESSAGES.MERGE_SUCCESS(options.branch, options.message));
204
+ printSuccess(MESSAGES.MERGE_SUCCESS(options.branch, options.message, autoPullPush));
204
205
  } else {
205
- printSuccess(MESSAGES.MERGE_SUCCESS_NO_MESSAGE(options.branch));
206
+ printSuccess(MESSAGES.MERGE_SUCCESS_NO_MESSAGE(options.branch, autoPullPush));
206
207
  }
207
208
 
208
209
  // 步骤 9:merge 成功后清理 worktree 和分支
@@ -15,6 +15,7 @@ import {
15
15
  removeEmptyDir,
16
16
  printInfo,
17
17
  printSuccess,
18
+ printError,
18
19
  confirmAction,
19
20
  } from '../utils/index.js';
20
21
 
@@ -91,7 +92,8 @@ async function handleRemove(options: RemoveOptions): Promise<void> {
91
92
  shouldDeleteBranch = await confirmAction('是否同时删除对应的本地分支?');
92
93
  }
93
94
 
94
- // 执行移除
95
+ // 执行移除,收集失败项
96
+ const failures: Array<{ path: string; error: string }> = [];
95
97
  for (const wt of worktreesToRemove) {
96
98
  try {
97
99
  removeWorktreeByPath(wt.path);
@@ -100,8 +102,9 @@ async function handleRemove(options: RemoveOptions): Promise<void> {
100
102
  }
101
103
  printSuccess(MESSAGES.WORKTREE_REMOVED(wt.path));
102
104
  } catch (error) {
105
+ const errorMessage = error instanceof Error ? error.message : String(error);
103
106
  logger.error(`移除 worktree 失败: ${wt.path} - ${error}`);
104
- throw error;
107
+ failures.push({ path: wt.path, error: errorMessage });
105
108
  }
106
109
  }
107
110
 
@@ -109,4 +112,12 @@ async function handleRemove(options: RemoveOptions): Promise<void> {
109
112
  gitWorktreePrune();
110
113
  const projectDir = getProjectWorktreeDir();
111
114
  removeEmptyDir(projectDir);
115
+
116
+ // 汇总报告失败项
117
+ if (failures.length > 0) {
118
+ printError(MESSAGES.REMOVE_PARTIAL_FAILURE(failures));
119
+ throw new ClawtError(
120
+ `${failures.length} 个 worktree 移除失败`,
121
+ );
122
+ }
112
123
  }
@@ -27,11 +27,11 @@ export const MESSAGES = {
27
27
  VALIDATE_SUCCESS: (branch: string) =>
28
28
  `✓ 已将分支 ${branch} 的变更应用到主 worktree\n 可以开始验证了`,
29
29
  /** merge 成功 */
30
- MERGE_SUCCESS: (branch: string, message: string) =>
31
- `✓ 分支 ${branch} 已成功合并到当前分支\n 提交信息: ${message}\n 已推送到远程仓库`,
30
+ MERGE_SUCCESS: (branch: string, message: string, pushed: boolean) =>
31
+ `✓ 分支 ${branch} 已成功合并到当前分支\n 提交信息: ${message}${pushed ? '\n 已推送到远程仓库' : ''}`,
32
32
  /** merge 成功(无提交信息,目标 worktree 已提交过) */
33
- MERGE_SUCCESS_NO_MESSAGE: (branch: string) =>
34
- `✓ 分支 ${branch} 已成功合并到当前分支`,
33
+ MERGE_SUCCESS_NO_MESSAGE: (branch: string, pushed: boolean) =>
34
+ `✓ 分支 ${branch} 已成功合并到当前分支${pushed ? '\n 已推送到远程仓库' : ''}`,
35
35
  /** merge 冲突 */
36
36
  MERGE_CONFLICT: '合并存在冲突,请手动处理',
37
37
  /** merge 后清理 worktree 和分支成功 */
@@ -99,4 +99,7 @@ export const MESSAGES = {
99
99
  RESET_SUCCESS: '✓ 主 worktree 工作区和暂存区已重置',
100
100
  /** reset 时工作区和暂存区已干净 */
101
101
  RESET_ALREADY_CLEAN: '主 worktree 工作区和暂存区已是干净状态,无需重置',
102
+ /** 批量移除部分失败 */
103
+ REMOVE_PARTIAL_FAILURE: (failures: Array<{ path: string; error: string }>) =>
104
+ `以下 worktree 移除失败:\n${failures.map((f) => ` ✗ ${f.path}: ${f.error}`).join('\n')}`,
102
105
  } as const;