cfix 1.0.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/.env.example +69 -0
- package/README.md +1590 -0
- package/bin/cfix +14 -0
- package/bin/cfix.cmd +6 -0
- package/cli/commands/config.js +58 -0
- package/cli/commands/doctor.js +240 -0
- package/cli/commands/fix.js +211 -0
- package/cli/commands/help.js +62 -0
- package/cli/commands/init.js +226 -0
- package/cli/commands/logs.js +161 -0
- package/cli/commands/monitor.js +151 -0
- package/cli/commands/project.js +331 -0
- package/cli/commands/service.js +133 -0
- package/cli/commands/status.js +115 -0
- package/cli/commands/task.js +412 -0
- package/cli/commands/version.js +19 -0
- package/cli/index.js +269 -0
- package/cli/lib/config-manager.js +612 -0
- package/cli/lib/formatter.js +224 -0
- package/cli/lib/process-manager.js +233 -0
- package/cli/lib/service-client.js +271 -0
- package/cli/scripts/install-completion.js +133 -0
- package/package.json +85 -0
- package/public/monitor.html +1096 -0
- package/scripts/completion.bash +87 -0
- package/scripts/completion.zsh +102 -0
- package/src/assets/README.md +32 -0
- package/src/assets/error.png +0 -0
- package/src/assets/icon.png +0 -0
- package/src/assets/success.png +0 -0
- package/src/claude-cli-service.js +216 -0
- package/src/config/index.js +69 -0
- package/src/database/manager.js +391 -0
- package/src/database/migration.js +252 -0
- package/src/git-service.js +1278 -0
- package/src/index.js +1658 -0
- package/src/logger.js +139 -0
- package/src/metrics/collector.js +184 -0
- package/src/middleware/auth.js +86 -0
- package/src/middleware/rate-limit.js +85 -0
- package/src/queue/integration-example.js +283 -0
- package/src/queue/task-queue.js +333 -0
- package/src/services/notification-limiter.js +48 -0
- package/src/services/notification-service.js +115 -0
- package/src/services/system-notifier.js +130 -0
- package/src/task-manager.js +289 -0
- package/src/utils/exec.js +87 -0
- package/src/utils/project-lock.js +246 -0
- package/src/utils/retry.js +110 -0
- package/src/utils/sanitizer.js +174 -0
- package/src/websocket/notifier.js +363 -0
- package/src/wechat-notifier.js +97 -0
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 任务管理命令
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const ServiceClient = require('../lib/service-client');
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* 列出任务
|
|
9
|
+
*/
|
|
10
|
+
async function list(options) {
|
|
11
|
+
console.log('📋 任务列表');
|
|
12
|
+
console.log('');
|
|
13
|
+
|
|
14
|
+
try {
|
|
15
|
+
const client = new ServiceClient();
|
|
16
|
+
|
|
17
|
+
// 构建查询参数
|
|
18
|
+
const params = {};
|
|
19
|
+
if (options.project) {
|
|
20
|
+
params.projectPath = options.project;
|
|
21
|
+
}
|
|
22
|
+
if (options.status) {
|
|
23
|
+
params.status = options.status;
|
|
24
|
+
}
|
|
25
|
+
if (options.all) {
|
|
26
|
+
// 不限制,显示所有
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const response = await client.getTasks(params);
|
|
30
|
+
|
|
31
|
+
// 服务端返回的数据结构: { success, pagination, stats, tasks }
|
|
32
|
+
const pagination = response.pagination || {};
|
|
33
|
+
const stats = response.stats || {};
|
|
34
|
+
const tasks = response.tasks || [];
|
|
35
|
+
|
|
36
|
+
console.log('======================================');
|
|
37
|
+
console.log(`总计: ${pagination.total || 0} 个任务`);
|
|
38
|
+
|
|
39
|
+
if (pagination.page) {
|
|
40
|
+
console.log(`页码: ${pagination.page} / ${pagination.totalPages || 1}`);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
console.log('======================================');
|
|
44
|
+
console.log('');
|
|
45
|
+
|
|
46
|
+
// 显示统计信息
|
|
47
|
+
if (stats.total > 0) {
|
|
48
|
+
console.log('统计:');
|
|
49
|
+
console.log(` 总计: ${stats.total}`);
|
|
50
|
+
console.log(` 等待中: ${stats.pending || 0}`);
|
|
51
|
+
console.log(` 运行中: ${stats.running || 0}`);
|
|
52
|
+
console.log(` 待审批: ${stats.waiting_approval || 0}`);
|
|
53
|
+
console.log(` 已完成: ${stats.completed || 0}`);
|
|
54
|
+
console.log(` 失败: ${stats.failed || 0}`);
|
|
55
|
+
console.log('');
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (tasks.length === 0) {
|
|
59
|
+
console.log('暂无任务');
|
|
60
|
+
} else {
|
|
61
|
+
tasks.forEach((task, index) => {
|
|
62
|
+
const statusIcon = getStatusIcon(task.status);
|
|
63
|
+
console.log(`${index + 1}. ${statusIcon} ${task.taskId}`);
|
|
64
|
+
console.log(` 需求: ${task.requirement}`);
|
|
65
|
+
console.log(` 项目: ${task.projectPath}`);
|
|
66
|
+
console.log(` 状态: ${task.status}`);
|
|
67
|
+
console.log(` 创建时间: ${new Date(task.createdAt).toLocaleString('zh-CN')}`);
|
|
68
|
+
console.log('');
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
console.log('======================================');
|
|
73
|
+
|
|
74
|
+
} catch (error) {
|
|
75
|
+
console.error(`❌ 获取任务列表失败: ${error.message}`);
|
|
76
|
+
process.exit(1);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* 显示任务详情
|
|
82
|
+
*/
|
|
83
|
+
async function show(taskId) {
|
|
84
|
+
console.log(`📄 任务详情: ${taskId}`);
|
|
85
|
+
console.log('');
|
|
86
|
+
|
|
87
|
+
try {
|
|
88
|
+
const client = new ServiceClient();
|
|
89
|
+
const task = await client.getTask(taskId);
|
|
90
|
+
|
|
91
|
+
console.log('======================================');
|
|
92
|
+
console.log(`状态: ${getStatusIcon(task.status)} ${task.status}`);
|
|
93
|
+
console.log('======================================');
|
|
94
|
+
console.log('');
|
|
95
|
+
|
|
96
|
+
console.log('基本信息:');
|
|
97
|
+
console.log(` 任务 ID: ${task.taskId}`);
|
|
98
|
+
console.log(` 需求: ${task.requirement}`);
|
|
99
|
+
console.log(` 项目: ${task.projectPath}`);
|
|
100
|
+
console.log(` 状态: ${task.status}`);
|
|
101
|
+
console.log(` 进度: ${task.progress || 0}%`);
|
|
102
|
+
console.log('');
|
|
103
|
+
|
|
104
|
+
console.log('时间信息:');
|
|
105
|
+
console.log(` 创建时间: ${new Date(task.createdAt).toLocaleString('zh-CN')}`);
|
|
106
|
+
console.log(` 更新时间: ${new Date(task.updatedAt).toLocaleString('zh-CN')}`);
|
|
107
|
+
if (task.completedAt) {
|
|
108
|
+
console.log(` 完成时间: ${new Date(task.completedAt).toLocaleString('zh-CN')}`);
|
|
109
|
+
}
|
|
110
|
+
console.log('');
|
|
111
|
+
|
|
112
|
+
// 如果有结果信息
|
|
113
|
+
if (task.result) {
|
|
114
|
+
console.log('执行结果:');
|
|
115
|
+
console.log(` 成功: ${task.result.success ? '是' : '否'}`);
|
|
116
|
+
if (task.result.message) {
|
|
117
|
+
console.log(` 消息: ${task.result.message}`);
|
|
118
|
+
}
|
|
119
|
+
if (task.result.files) {
|
|
120
|
+
console.log(` 修改文件: ${task.result.files.modified?.length || 0} 个`);
|
|
121
|
+
console.log(` 新增文件: ${task.result.files.added?.length || 0} 个`);
|
|
122
|
+
console.log(` 删除文件: ${task.result.files.deleted?.length || 0} 个`);
|
|
123
|
+
}
|
|
124
|
+
console.log('');
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// 如果有错误
|
|
128
|
+
if (task.error) {
|
|
129
|
+
console.log(`错误: ${task.error}`);
|
|
130
|
+
console.log('');
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// 根据状态显示操作提示
|
|
134
|
+
if (task.status === 'waiting_approval') {
|
|
135
|
+
console.log('可用操作:');
|
|
136
|
+
console.log(` cfix approve ${taskId} # 批准修改`);
|
|
137
|
+
console.log(` cfix reject ${taskId} # 拒绝修改`);
|
|
138
|
+
console.log(` cfix task ${taskId} # 查看修改内容`);
|
|
139
|
+
} else if (task.status === 'pending' || task.status === 'running') {
|
|
140
|
+
console.log('可用操作:');
|
|
141
|
+
console.log(` cfix cancel ${taskId} # 取消任务`);
|
|
142
|
+
console.log(` cfix wait ${taskId} # 等待完成`);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
} catch (error) {
|
|
146
|
+
console.error(`❌ 获取任务详情失败: ${error.message}`);
|
|
147
|
+
process.exit(1);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
console.log('======================================');
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* 批准任务
|
|
155
|
+
*/
|
|
156
|
+
async function approve(taskId, options = {}) {
|
|
157
|
+
console.log(`✅ 批准任务: ${taskId}`);
|
|
158
|
+
console.log('');
|
|
159
|
+
|
|
160
|
+
try {
|
|
161
|
+
const client = new ServiceClient();
|
|
162
|
+
|
|
163
|
+
// 获取任务详情
|
|
164
|
+
const task = await client.getTask(taskId);
|
|
165
|
+
|
|
166
|
+
// 显示修改内容
|
|
167
|
+
console.log('======================================');
|
|
168
|
+
console.log(`需求: ${task.requirement}`);
|
|
169
|
+
console.log(`项目: ${task.projectPath}`);
|
|
170
|
+
console.log('======================================');
|
|
171
|
+
console.log('');
|
|
172
|
+
|
|
173
|
+
if (task.changes) {
|
|
174
|
+
console.log('修改内容:');
|
|
175
|
+
if (task.changes.summary) {
|
|
176
|
+
console.log(` ${task.changes.summary}`);
|
|
177
|
+
}
|
|
178
|
+
if (task.changes.files && task.changes.files.length > 0) {
|
|
179
|
+
console.log('');
|
|
180
|
+
console.log(' 文件列表:');
|
|
181
|
+
task.changes.files.forEach((file, index) => {
|
|
182
|
+
console.log(` ${index + 1}. ${file}`);
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
console.log('');
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// 交互式确认(如果需要)
|
|
189
|
+
if (!options.yes && !options.autoConfirm) {
|
|
190
|
+
const inquirer = require('inquirer');
|
|
191
|
+
const { confirmed } = await inquirer.prompt([
|
|
192
|
+
{
|
|
193
|
+
type: 'confirm',
|
|
194
|
+
name: 'confirmed',
|
|
195
|
+
message: '确认批准这些修改?',
|
|
196
|
+
default: true
|
|
197
|
+
}
|
|
198
|
+
]);
|
|
199
|
+
|
|
200
|
+
if (!confirmed) {
|
|
201
|
+
console.log('❌ 已取消');
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const result = await client.approveTask(taskId);
|
|
207
|
+
|
|
208
|
+
console.log('======================================');
|
|
209
|
+
console.log('✅ 任务已批准');
|
|
210
|
+
console.log('======================================');
|
|
211
|
+
console.log('');
|
|
212
|
+
|
|
213
|
+
if (result.branch) {
|
|
214
|
+
console.log(`分支: ${result.branch}`);
|
|
215
|
+
console.log('');
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
if (result.message) {
|
|
219
|
+
console.log(`提示: ${result.message}`);
|
|
220
|
+
console.log('');
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
} catch (error) {
|
|
224
|
+
console.error(`❌ 批准任务失败: ${error.message}`);
|
|
225
|
+
process.exit(1);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* 拒绝任务
|
|
231
|
+
*/
|
|
232
|
+
async function reject(taskId, reason) {
|
|
233
|
+
console.log(`❌ 拒绝任务: ${taskId}`);
|
|
234
|
+
console.log('');
|
|
235
|
+
|
|
236
|
+
try {
|
|
237
|
+
const client = new ServiceClient();
|
|
238
|
+
const result = await client.rejectTask(taskId, reason);
|
|
239
|
+
|
|
240
|
+
console.log('======================================');
|
|
241
|
+
console.log('✅ 任务已拒绝');
|
|
242
|
+
console.log('======================================');
|
|
243
|
+
console.log('');
|
|
244
|
+
|
|
245
|
+
if (reason) {
|
|
246
|
+
console.log(`原因: ${reason}`);
|
|
247
|
+
console.log('');
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
if (result.message) {
|
|
251
|
+
console.log(`提示: ${result.message}`);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
} catch (error) {
|
|
255
|
+
console.error(`❌ 拒绝任务失败: ${error.message}`);
|
|
256
|
+
process.exit(1);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* 取消任务
|
|
262
|
+
*/
|
|
263
|
+
async function cancel(taskId) {
|
|
264
|
+
console.log(`🚫 取消任务: ${taskId}`);
|
|
265
|
+
console.log('');
|
|
266
|
+
|
|
267
|
+
try {
|
|
268
|
+
const client = new ServiceClient();
|
|
269
|
+
await client.cancelTask(taskId);
|
|
270
|
+
|
|
271
|
+
console.log('======================================');
|
|
272
|
+
console.log('✅ 任务已取消');
|
|
273
|
+
console.log('======================================');
|
|
274
|
+
|
|
275
|
+
} catch (error) {
|
|
276
|
+
console.error(`❌ 取消任务失败: ${error.message}`);
|
|
277
|
+
process.exit(1);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* 等待任务完成
|
|
283
|
+
*/
|
|
284
|
+
async function wait(taskId, options = {}) {
|
|
285
|
+
console.log(`⏳ 等待任务完成: ${taskId}`);
|
|
286
|
+
console.log('');
|
|
287
|
+
|
|
288
|
+
try {
|
|
289
|
+
const client = new ServiceClient();
|
|
290
|
+
|
|
291
|
+
// 首先获取任务状态
|
|
292
|
+
const initialTask = await client.getTask(taskId);
|
|
293
|
+
|
|
294
|
+
// 显示初始状态
|
|
295
|
+
console.log('======================================');
|
|
296
|
+
console.log(`当前状态: ${getStatusIcon(initialTask.status)} ${initialTask.status}`);
|
|
297
|
+
console.log(`需求: ${initialTask.requirement}`);
|
|
298
|
+
console.log('======================================');
|
|
299
|
+
console.log('');
|
|
300
|
+
|
|
301
|
+
// 如果已经完成
|
|
302
|
+
if (['completed', 'failed', 'cancelled'].includes(initialTask.status)) {
|
|
303
|
+
console.log('任务已经结束,无需等待');
|
|
304
|
+
console.log('');
|
|
305
|
+
|
|
306
|
+
// 显示结果
|
|
307
|
+
if (initialTask.status === 'completed' && initialTask.result) {
|
|
308
|
+
console.log('执行结果:');
|
|
309
|
+
console.log(` 修改文件: ${initialTask.result.files?.modified?.length || 0} 个`);
|
|
310
|
+
console.log(` 新增文件: ${initialTask.result.files?.added?.length || 0} 个`);
|
|
311
|
+
console.log(` 删除文件: ${initialTask.result.files?.deleted?.length || 0} 个`);
|
|
312
|
+
} else if (initialTask.status === 'failed' && initialTask.error) {
|
|
313
|
+
console.log(`错误: ${initialTask.error}`);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
return initialTask;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// 等待完成
|
|
320
|
+
const timeout = options.timeout || 1800000; // 默认 30 分钟
|
|
321
|
+
const interval = options.interval || 2000; // 默认 2 秒
|
|
322
|
+
|
|
323
|
+
console.log(`等待任务完成 (超时: ${Math.floor(timeout / 60000)} 分钟)...`);
|
|
324
|
+
console.log('');
|
|
325
|
+
|
|
326
|
+
const startTime = Date.now();
|
|
327
|
+
|
|
328
|
+
const finalTask = await client.waitForTask(taskId, {
|
|
329
|
+
timeout,
|
|
330
|
+
interval,
|
|
331
|
+
onProgress: (task) => {
|
|
332
|
+
const elapsed = Math.floor((Date.now() - startTime) / 1000);
|
|
333
|
+
const progressLine = `[${elapsed}s] ${getStatusIcon(task.status)} ${task.status}`;
|
|
334
|
+
|
|
335
|
+
if (task.progress) {
|
|
336
|
+
process.stdout.write(`\r${progressLine} - 进度: ${task.progress}%`);
|
|
337
|
+
} else {
|
|
338
|
+
process.stdout.write(`\r${progressLine}`);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
console.log('');
|
|
344
|
+
console.log('');
|
|
345
|
+
console.log('======================================');
|
|
346
|
+
console.log(`✅ 任务完成: ${getStatusIcon(finalTask.status)} ${finalTask.status}`);
|
|
347
|
+
console.log('======================================');
|
|
348
|
+
console.log('');
|
|
349
|
+
|
|
350
|
+
// 显示结果
|
|
351
|
+
if (finalTask.result) {
|
|
352
|
+
console.log('执行结果:');
|
|
353
|
+
console.log(` 成功: ${finalTask.result.success ? '是' : '否'}`);
|
|
354
|
+
if (finalTask.result.message) {
|
|
355
|
+
console.log(` 消息: ${finalTask.result.message}`);
|
|
356
|
+
}
|
|
357
|
+
if (finalTask.result.files) {
|
|
358
|
+
console.log(` 修改文件: ${finalTask.result.files.modified?.length || 0} 个`);
|
|
359
|
+
console.log(` 新增文件: ${finalTask.result.files.added?.length || 0} 个`);
|
|
360
|
+
console.log(` 删除文件: ${finalTask.result.files.deleted?.length || 0} 个`);
|
|
361
|
+
}
|
|
362
|
+
} else if (finalTask.error) {
|
|
363
|
+
console.log(`错误: ${finalTask.error}`);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// 如果需要确认
|
|
367
|
+
if (finalTask.status === 'waiting_approval') {
|
|
368
|
+
console.log('');
|
|
369
|
+
console.log('⚠️ 任务需要人工确认');
|
|
370
|
+
console.log('');
|
|
371
|
+
console.log('使用以下命令:');
|
|
372
|
+
console.log(` cfix task ${taskId} # 查看详情`);
|
|
373
|
+
console.log(` cfix approve ${taskId} # 批准修改`);
|
|
374
|
+
console.log(` cfix reject ${taskId} # 拒绝修改`);
|
|
375
|
+
|
|
376
|
+
// 自动确认
|
|
377
|
+
if (options.autoApprove) {
|
|
378
|
+
console.log('');
|
|
379
|
+
console.log('⚠️ 正在自动批准...');
|
|
380
|
+
|
|
381
|
+
await client.approveTask(taskId);
|
|
382
|
+
console.log('✅ 任务已自动批准');
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
return finalTask;
|
|
387
|
+
|
|
388
|
+
} catch (error) {
|
|
389
|
+
console.error('');
|
|
390
|
+
console.error('======================================');
|
|
391
|
+
console.error(`❌ 等待任务失败: ${error.message}`);
|
|
392
|
+
console.error('======================================');
|
|
393
|
+
process.exit(1);
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* 获取状态图标
|
|
399
|
+
*/
|
|
400
|
+
function getStatusIcon(status) {
|
|
401
|
+
const icons = {
|
|
402
|
+
pending: '⏳',
|
|
403
|
+
running: '🔄',
|
|
404
|
+
waiting_approval: '⏸️',
|
|
405
|
+
completed: '✅',
|
|
406
|
+
failed: '❌',
|
|
407
|
+
cancelled: '🚫'
|
|
408
|
+
};
|
|
409
|
+
return icons[status] || '❓';
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
module.exports = { list, show, approve, reject, cancel, wait };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 版本命令
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const pkg = require('../../package.json');
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* 显示版本信息
|
|
9
|
+
*/
|
|
10
|
+
async function handle() {
|
|
11
|
+
console.log(`
|
|
12
|
+
CodeFix CLI
|
|
13
|
+
版本: ${pkg.version}
|
|
14
|
+
Node.js: ${process.version}
|
|
15
|
+
系统: ${process.platform} ${process.arch}
|
|
16
|
+
`);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
module.exports = { handle };
|
package/cli/index.js
ADDED
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* CodeFix CLI 主入口
|
|
4
|
+
* 命令: cfix
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { program } = require('commander');
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const fs = require('fs');
|
|
10
|
+
|
|
11
|
+
// 设置根目录
|
|
12
|
+
const ROOT_DIR = process.env.CFIX_ROOT || path.resolve(__dirname, '..');
|
|
13
|
+
process.env.CFIX_ROOT = ROOT_DIR;
|
|
14
|
+
|
|
15
|
+
// 版本号
|
|
16
|
+
const VERSION = require('../package.json').version;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* 主程序
|
|
20
|
+
*/
|
|
21
|
+
async function main() {
|
|
22
|
+
// CLI 基本配置
|
|
23
|
+
program
|
|
24
|
+
.name('cfix')
|
|
25
|
+
.description('AI 自动代码修复 CLI 工具')
|
|
26
|
+
.version(VERSION);
|
|
27
|
+
|
|
28
|
+
// 核心命令
|
|
29
|
+
program.command('fix', { isDefault: true })
|
|
30
|
+
.description('创建修复任务')
|
|
31
|
+
.argument('[requirement]', '修复需求描述')
|
|
32
|
+
.option('-p, --project <path>', '项目路径')
|
|
33
|
+
.option('-o, --output <format>', '输出格式 (interactive|json|quiet)', 'interactive')
|
|
34
|
+
.option('-w, --wait', '等待任务完成')
|
|
35
|
+
.option('-y, --yes', '自动确认')
|
|
36
|
+
.action(async (requirement, options) => {
|
|
37
|
+
const cmd = require('./commands/fix');
|
|
38
|
+
await cmd.handle(requirement, options);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
// 服务管理命令
|
|
42
|
+
program.command('start')
|
|
43
|
+
.description('启动服务')
|
|
44
|
+
.option('-d, --daemon', '守护进程模式')
|
|
45
|
+
.option('-w, --wait', '等待服务就绪')
|
|
46
|
+
.action(async (options) => {
|
|
47
|
+
const cmd = require('./commands/service');
|
|
48
|
+
await cmd.start(options);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
program.command('stop')
|
|
52
|
+
.description('停止服务')
|
|
53
|
+
.option('-q, --quiet', '静默模式')
|
|
54
|
+
.action(async (options) => {
|
|
55
|
+
const cmd = require('./commands/service');
|
|
56
|
+
await cmd.stop(options);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
program.command('restart')
|
|
60
|
+
.description('重启服务')
|
|
61
|
+
.action(async () => {
|
|
62
|
+
const cmd = require('./commands/service');
|
|
63
|
+
await cmd.restart();
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// 状态和日志
|
|
67
|
+
program.command('status')
|
|
68
|
+
.description('查看服务状态')
|
|
69
|
+
.action(async () => {
|
|
70
|
+
const cmd = require('./commands/status');
|
|
71
|
+
await cmd.handle();
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
program.command('logs')
|
|
75
|
+
.description('查看日志')
|
|
76
|
+
.option('-f, --follow', '跟踪日志输出')
|
|
77
|
+
.option('-e, --errors', '仅显示错误日志')
|
|
78
|
+
.action(async (options) => {
|
|
79
|
+
const cmd = require('./commands/logs');
|
|
80
|
+
await cmd.handle(options);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
// 项目管理
|
|
84
|
+
program
|
|
85
|
+
.command('project')
|
|
86
|
+
.description('项目管理命令')
|
|
87
|
+
.addCommand(
|
|
88
|
+
new program.Command('add')
|
|
89
|
+
.argument('<path>')
|
|
90
|
+
.description('添加项目 (支持 Git URL 或本地路径)')
|
|
91
|
+
.option('-n, --name <name>', '项目名称')
|
|
92
|
+
.option('-a, --alias <alias>', '项目别名')
|
|
93
|
+
.option('-y, --yes', '自动确认 (克隆时跳过询问)')
|
|
94
|
+
.action(async (projectPath, options) => {
|
|
95
|
+
const cmd = require('./commands/project');
|
|
96
|
+
await cmd.add(projectPath, options);
|
|
97
|
+
})
|
|
98
|
+
)
|
|
99
|
+
.addCommand(
|
|
100
|
+
new program.Command('remove')
|
|
101
|
+
.argument('<path>')
|
|
102
|
+
.description('移除项目')
|
|
103
|
+
.action(async (projectPath) => {
|
|
104
|
+
const cmd = require('./commands/project');
|
|
105
|
+
await cmd.remove(projectPath);
|
|
106
|
+
})
|
|
107
|
+
)
|
|
108
|
+
.addCommand(
|
|
109
|
+
new program.Command('list')
|
|
110
|
+
.description('列出所有项目')
|
|
111
|
+
.action(async () => {
|
|
112
|
+
const cmd = require('./commands/project');
|
|
113
|
+
await cmd.list();
|
|
114
|
+
})
|
|
115
|
+
)
|
|
116
|
+
.addCommand(
|
|
117
|
+
new program.Command('info')
|
|
118
|
+
.argument('<path>')
|
|
119
|
+
.description('项目详情')
|
|
120
|
+
.action(async (projectPath) => {
|
|
121
|
+
const cmd = require('./commands/project');
|
|
122
|
+
await cmd.info(projectPath);
|
|
123
|
+
})
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
// 配置管理
|
|
127
|
+
program
|
|
128
|
+
.command('config')
|
|
129
|
+
.description('配置管理命令')
|
|
130
|
+
.addCommand(
|
|
131
|
+
new program.Command('get')
|
|
132
|
+
.argument('<key>')
|
|
133
|
+
.description('获取配置')
|
|
134
|
+
.action(async (key) => {
|
|
135
|
+
const cmd = require('./commands/config');
|
|
136
|
+
await cmd.get(key);
|
|
137
|
+
})
|
|
138
|
+
)
|
|
139
|
+
.addCommand(
|
|
140
|
+
new program.Command('set')
|
|
141
|
+
.argument('<key>')
|
|
142
|
+
.argument('<value>')
|
|
143
|
+
.description('设置配置')
|
|
144
|
+
.action(async (key, value) => {
|
|
145
|
+
const cmd = require('./commands/config');
|
|
146
|
+
await cmd.set(key, value);
|
|
147
|
+
})
|
|
148
|
+
)
|
|
149
|
+
.addCommand(
|
|
150
|
+
new program.Command('list')
|
|
151
|
+
.description('列出所有配置')
|
|
152
|
+
.action(async () => {
|
|
153
|
+
const cmd = require('./commands/config');
|
|
154
|
+
await cmd.list();
|
|
155
|
+
})
|
|
156
|
+
)
|
|
157
|
+
.addCommand(
|
|
158
|
+
new program.Command('edit')
|
|
159
|
+
.description('编辑配置文件')
|
|
160
|
+
.action(async () => {
|
|
161
|
+
const cmd = require('./commands/config');
|
|
162
|
+
await cmd.edit();
|
|
163
|
+
})
|
|
164
|
+
)
|
|
165
|
+
.addCommand(
|
|
166
|
+
new program.Command('reset')
|
|
167
|
+
.description('重置配置')
|
|
168
|
+
.action(async () => {
|
|
169
|
+
const cmd = require('./commands/config');
|
|
170
|
+
await cmd.reset();
|
|
171
|
+
})
|
|
172
|
+
);
|
|
173
|
+
|
|
174
|
+
// 任务管理
|
|
175
|
+
program.command('tasks')
|
|
176
|
+
.description('查看任务列表')
|
|
177
|
+
.option('-p, --project <path>', '筛选项目')
|
|
178
|
+
.option('-s, --status <status>', '筛选状态')
|
|
179
|
+
.option('--all', '显示所有项目')
|
|
180
|
+
.action(async (options) => {
|
|
181
|
+
const cmd = require('./commands/task');
|
|
182
|
+
await cmd.list(options);
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
program.command('task <taskId>')
|
|
186
|
+
.description('查看任务详情')
|
|
187
|
+
.action(async (taskId) => {
|
|
188
|
+
const cmd = require('./commands/task');
|
|
189
|
+
await cmd.show(taskId);
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
program.command('approve <taskId>')
|
|
193
|
+
.description('批准任务')
|
|
194
|
+
.option('-y, --yes', '跳过确认')
|
|
195
|
+
.action(async (taskId, options) => {
|
|
196
|
+
const cmd = require('./commands/task');
|
|
197
|
+
await cmd.approve(taskId, options);
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
program.command('reject <taskId>')
|
|
201
|
+
.description('拒绝任务')
|
|
202
|
+
.argument('[reason]', '拒绝原因')
|
|
203
|
+
.action(async (taskId, reason) => {
|
|
204
|
+
const cmd = require('./commands/task');
|
|
205
|
+
await cmd.reject(taskId, reason);
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
program.command('cancel <taskId>')
|
|
209
|
+
.description('取消任务')
|
|
210
|
+
.action(async (taskId) => {
|
|
211
|
+
const cmd = require('./commands/task');
|
|
212
|
+
await cmd.cancel(taskId);
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
program.command('wait <taskId>')
|
|
216
|
+
.description('等待任务完成')
|
|
217
|
+
.option('-t, --timeout <ms>', '超时时间(毫秒)', parseInt)
|
|
218
|
+
.option('-i, --interval <ms>', '检查间隔(毫秒)', parseInt)
|
|
219
|
+
.option('-y, --yes', '自动批准')
|
|
220
|
+
.action(async (taskId, options) => {
|
|
221
|
+
const cmd = require('./commands/task');
|
|
222
|
+
await cmd.wait(taskId, options);
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
// 工具命令
|
|
226
|
+
program.command('init [path]')
|
|
227
|
+
.description('初始化项目配置')
|
|
228
|
+
.action(async (projectPath) => {
|
|
229
|
+
const cmd = require('./commands/init');
|
|
230
|
+
await cmd.handle(projectPath);
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
program.command('monitor')
|
|
234
|
+
.description('打开监控面板')
|
|
235
|
+
.option('-f, --follow', '持续监控状态')
|
|
236
|
+
.option('--no-auto-start', '不自动启动服务')
|
|
237
|
+
.action(async (options) => {
|
|
238
|
+
const cmd = require('./commands/monitor');
|
|
239
|
+
await cmd.handle(options);
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
program.command('doctor')
|
|
243
|
+
.description('环境检查')
|
|
244
|
+
.action(async () => {
|
|
245
|
+
const cmd = require('./commands/doctor');
|
|
246
|
+
await cmd.handle();
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
// 解析参数
|
|
250
|
+
await program.parseAsync(process.argv);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* 运行 CLI
|
|
255
|
+
*/
|
|
256
|
+
function run() {
|
|
257
|
+
main().catch((error) => {
|
|
258
|
+
console.error('错误:', error.message);
|
|
259
|
+
process.exit(1);
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// 导出
|
|
264
|
+
module.exports = { run };
|
|
265
|
+
|
|
266
|
+
// 如果直接运行此文件
|
|
267
|
+
if (require.main === module) {
|
|
268
|
+
run();
|
|
269
|
+
}
|