coding-tool-x 3.4.3 → 3.4.4
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/web/assets/{Analytics-CbGxotgz.js → Analytics-_Byi9M6y.js} +1 -1
- package/dist/web/assets/{ConfigTemplates-oP6nrFEb.js → ConfigTemplates-DIwosdtG.js} +1 -1
- package/dist/web/assets/{Home-DMntmEvh.js → Home-DdNMuQ9c.js} +1 -1
- package/dist/web/assets/{PluginManager-BUC_c7nH.js → PluginManager-iuY24cnW.js} +1 -1
- package/dist/web/assets/{ProjectList-oJIyIRkP.css → ProjectList-DL4JK6ci.css} +1 -1
- package/dist/web/assets/{ProjectList-CW8J49n7.js → ProjectList-DSkMulzL.js} +1 -1
- package/dist/web/assets/{SessionList-7lYnF92v.js → SessionList-B6pGquIr.js} +1 -1
- package/dist/web/assets/{SkillManager-Cs08216i.js → SkillManager-CHtQX5r8.js} +1 -1
- package/dist/web/assets/{WorkspaceManager-CY-oGtyB.js → WorkspaceManager-gNPs-VaI.js} +1 -1
- package/dist/web/assets/index-DGjGCo37.js +2 -0
- package/dist/web/assets/{index-5qy5NMIP.css → index-pMqqe9ei.css} +1 -1
- package/dist/web/index.html +2 -2
- package/package.json +1 -1
- package/src/commands/channels.js +13 -13
- package/src/commands/cli-type.js +5 -5
- package/src/commands/daemon.js +31 -31
- package/src/commands/doctor.js +14 -14
- package/src/commands/export-config.js +23 -23
- package/src/commands/list.js +4 -4
- package/src/commands/logs.js +19 -19
- package/src/commands/plugin.js +62 -62
- package/src/commands/port-config.js +4 -4
- package/src/commands/proxy-control.js +35 -35
- package/src/commands/proxy.js +28 -28
- package/src/commands/resume.js +4 -4
- package/src/commands/search.js +9 -9
- package/src/commands/security.js +5 -5
- package/src/commands/stats.js +18 -18
- package/src/commands/switch.js +1 -1
- package/src/commands/toggle-proxy.js +18 -18
- package/src/commands/ui.js +11 -11
- package/src/commands/update.js +9 -9
- package/src/commands/workspace.js +11 -11
- package/src/index.js +24 -24
- package/src/plugins/plugin-installer.js +1 -1
- package/src/reset-config.js +9 -9
- package/src/server/api/channels.js +1 -1
- package/src/server/api/claude-hooks.js +2 -2
- package/src/server/api/plugins.js +4 -0
- package/src/server/api/pm2-autostart.js +2 -2
- package/src/server/api/proxy.js +6 -6
- package/src/server/api/skills.js +4 -0
- package/src/server/dev-server.js +2 -2
- package/src/server/index.js +37 -37
- package/src/server/proxy-server.js +4 -4
- package/src/server/services/config-export-service.js +1 -1
- package/src/server/services/mcp-service.js +2 -1
- package/src/server/services/model-detector.js +2 -2
- package/src/server/services/native-keychain.js +1 -0
- package/src/server/services/plugins-service.js +7 -27
- package/src/server/services/settings-manager.js +3 -3
- package/src/server/services/skill-service.js +4 -12
- package/src/server/websocket-server.js +8 -8
- package/src/ui/menu.js +2 -2
- package/src/ui/prompts.js +5 -5
- package/dist/web/assets/index-ClCqKpvX.js +0 -2
package/dist/web/index.html
CHANGED
|
@@ -5,14 +5,14 @@
|
|
|
5
5
|
<link rel="icon" href="/favicon.ico">
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
7
7
|
<title>CC-TOOL - ClaudeCode增强工作助手</title>
|
|
8
|
-
<script type="module" crossorigin src="/assets/index-
|
|
8
|
+
<script type="module" crossorigin src="/assets/index-DGjGCo37.js"></script>
|
|
9
9
|
<link rel="modulepreload" crossorigin href="/assets/markdown-DyTJGI4N.js">
|
|
10
10
|
<link rel="modulepreload" crossorigin href="/assets/vue-vendor-3bf-fPGP.js">
|
|
11
11
|
<link rel="modulepreload" crossorigin href="/assets/vendors-CKPV1OAU.js">
|
|
12
12
|
<link rel="modulepreload" crossorigin href="/assets/naive-ui-Bdxp09n2.js">
|
|
13
13
|
<link rel="modulepreload" crossorigin href="/assets/icons-B5Pl4lrD.js">
|
|
14
14
|
<link rel="stylesheet" crossorigin href="/assets/markdown-BfC0goYb.css">
|
|
15
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
15
|
+
<link rel="stylesheet" crossorigin href="/assets/index-pMqqe9ei.css">
|
|
16
16
|
</head>
|
|
17
17
|
<body>
|
|
18
18
|
<div id="app"></div>
|
package/package.json
CHANGED
package/src/commands/channels.js
CHANGED
|
@@ -71,9 +71,9 @@ function getChannelServices(cliType) {
|
|
|
71
71
|
*/
|
|
72
72
|
async function handleChannelManagement() {
|
|
73
73
|
console.clear();
|
|
74
|
-
console.log(chalk.bold.cyan('\n
|
|
74
|
+
console.log(chalk.bold.cyan('\n╔=======================================╗'));
|
|
75
75
|
console.log(chalk.bold.cyan('║ 渠道管理 ║'));
|
|
76
|
-
console.log(chalk.bold.cyan('
|
|
76
|
+
console.log(chalk.bold.cyan('╚=======================================╝\n'));
|
|
77
77
|
|
|
78
78
|
const config = loadConfig();
|
|
79
79
|
const cliType = config.currentCliType || 'claude';
|
|
@@ -124,9 +124,9 @@ async function handleChannelManagement() {
|
|
|
124
124
|
*/
|
|
125
125
|
async function handleAddChannel() {
|
|
126
126
|
console.clear();
|
|
127
|
-
console.log(chalk.bold.cyan('\n
|
|
127
|
+
console.log(chalk.bold.cyan('\n╔=======================================╗'));
|
|
128
128
|
console.log(chalk.bold.cyan('║ 添加渠道 ║'));
|
|
129
|
-
console.log(chalk.bold.cyan('
|
|
129
|
+
console.log(chalk.bold.cyan('╚=======================================╝\n'));
|
|
130
130
|
|
|
131
131
|
const config = loadConfig();
|
|
132
132
|
const cliType = config.currentCliType || 'claude';
|
|
@@ -248,7 +248,7 @@ async function handleAddChannel() {
|
|
|
248
248
|
);
|
|
249
249
|
}
|
|
250
250
|
|
|
251
|
-
console.log(chalk.green(`\n
|
|
251
|
+
console.log(chalk.green(`\n[OK] 渠道添加成功: ${channel.name}\n`));
|
|
252
252
|
console.log(chalk.gray('提示: 使用"渠道管理"功能来启用此渠道\n'));
|
|
253
253
|
broadcastSchedulerSnapshot(cliType);
|
|
254
254
|
|
|
@@ -260,7 +260,7 @@ async function handleAddChannel() {
|
|
|
260
260
|
},
|
|
261
261
|
]);
|
|
262
262
|
} catch (error) {
|
|
263
|
-
console.log(chalk.red(`\n
|
|
263
|
+
console.log(chalk.red(`\n[ERROR] 添加失败: ${error.message}\n`));
|
|
264
264
|
|
|
265
265
|
await inquirer.prompt([
|
|
266
266
|
{
|
|
@@ -274,9 +274,9 @@ async function handleAddChannel() {
|
|
|
274
274
|
|
|
275
275
|
async function handleChannelStatus() {
|
|
276
276
|
console.clear();
|
|
277
|
-
console.log(chalk.bold.cyan('\n
|
|
277
|
+
console.log(chalk.bold.cyan('\n╔=======================================╗'));
|
|
278
278
|
console.log(chalk.bold.cyan('║ 调度状态查看 ║'));
|
|
279
|
-
console.log(chalk.bold.cyan('
|
|
279
|
+
console.log(chalk.bold.cyan('╚=======================================╝\n'));
|
|
280
280
|
|
|
281
281
|
try {
|
|
282
282
|
const { getSchedulerState } = require('../server/services/channel-scheduler');
|
|
@@ -370,7 +370,7 @@ async function handleChannelToggle(channels, services, cliType) {
|
|
|
370
370
|
]);
|
|
371
371
|
|
|
372
372
|
if (!selectedIds.length) {
|
|
373
|
-
console.log(chalk.red('\n
|
|
373
|
+
console.log(chalk.red('\n[ERROR] 至少需要启用一个渠道。\n'));
|
|
374
374
|
await inquirer.prompt([{ type: 'input', name: 'continue', message: '按回车返回...' }]);
|
|
375
375
|
return;
|
|
376
376
|
}
|
|
@@ -382,7 +382,7 @@ async function handleChannelToggle(channels, services, cliType) {
|
|
|
382
382
|
if (shouldEnable !== currentEnabled) {
|
|
383
383
|
await services.updateChannel(channel.id, { enabled: shouldEnable });
|
|
384
384
|
console.log(
|
|
385
|
-
`${shouldEnable ? chalk.green('
|
|
385
|
+
`${shouldEnable ? chalk.green('[OK] 启用') : chalk.yellow('[PAUSE] 停用')} ${chalk.bold(channel.name)}`
|
|
386
386
|
);
|
|
387
387
|
hasChanged = true;
|
|
388
388
|
}
|
|
@@ -524,7 +524,7 @@ async function handleLegacySwitch(channels, services) {
|
|
|
524
524
|
});
|
|
525
525
|
|
|
526
526
|
choices.push(new inquirer.Separator(chalk.gray('─'.repeat(14))));
|
|
527
|
-
choices.push({ name: chalk.blue('
|
|
527
|
+
choices.push({ name: chalk.blue('[<-] 返回主菜单'), value: 'back' });
|
|
528
528
|
|
|
529
529
|
const { channelId } = await inquirer.prompt([
|
|
530
530
|
{
|
|
@@ -542,9 +542,9 @@ async function handleLegacySwitch(channels, services) {
|
|
|
542
542
|
|
|
543
543
|
try {
|
|
544
544
|
await services.activateChannel(channelId);
|
|
545
|
-
console.log(chalk.green('\n
|
|
545
|
+
console.log(chalk.green('\n[OK] 渠道已切换\n'));
|
|
546
546
|
} catch (error) {
|
|
547
|
-
console.log(chalk.red(`\n
|
|
547
|
+
console.log(chalk.red(`\n[ERROR] 操作失败: ${error.message}\n`));
|
|
548
548
|
}
|
|
549
549
|
|
|
550
550
|
await inquirer.prompt([{ type: 'input', name: 'continue', message: '按回车返回...' }]);
|
package/src/commands/cli-type.js
CHANGED
|
@@ -15,9 +15,9 @@ const CLI_TYPES = {
|
|
|
15
15
|
*/
|
|
16
16
|
async function handleSwitchCliType() {
|
|
17
17
|
console.clear();
|
|
18
|
-
console.log(chalk.bold.cyan('\n
|
|
18
|
+
console.log(chalk.bold.cyan('\n╔=======================================╗'));
|
|
19
19
|
console.log(chalk.bold.cyan('║ 切换 CLI 类型 ║'));
|
|
20
|
-
console.log(chalk.bold.cyan('
|
|
20
|
+
console.log(chalk.bold.cyan('╚=======================================╝\n'));
|
|
21
21
|
|
|
22
22
|
const config = loadConfig();
|
|
23
23
|
const currentType = config.currentCliType || 'claude';
|
|
@@ -29,9 +29,9 @@ async function handleSwitchCliType() {
|
|
|
29
29
|
const choices = Object.entries(CLI_TYPES).map(([type, info]) => {
|
|
30
30
|
let name = '';
|
|
31
31
|
|
|
32
|
-
//
|
|
32
|
+
// 如果是当前类型,添加[v]标记
|
|
33
33
|
if (type === currentType) {
|
|
34
|
-
name += chalk.green('
|
|
34
|
+
name += chalk.green('[v] ');
|
|
35
35
|
} else {
|
|
36
36
|
name += ' ';
|
|
37
37
|
}
|
|
@@ -81,7 +81,7 @@ async function handleSwitchCliType() {
|
|
|
81
81
|
config.currentCliType = selectedType;
|
|
82
82
|
saveConfig(config);
|
|
83
83
|
|
|
84
|
-
console.log(chalk.green(`\n
|
|
84
|
+
console.log(chalk.green(`\n[OK] 已切换到 ${CLI_TYPES[selectedType].name}\n`));
|
|
85
85
|
console.log(chalk.gray('下次启动时将使用新的类型\n'));
|
|
86
86
|
|
|
87
87
|
await inquirer.prompt([
|
package/src/commands/daemon.js
CHANGED
|
@@ -73,7 +73,7 @@ function printPortToolIssue(issue = getPortToolIssue()) {
|
|
|
73
73
|
return;
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
-
console.log(chalk.yellow(`\n
|
|
76
|
+
console.log(chalk.yellow(`\n[WARN] ${lines[0]}`));
|
|
77
77
|
lines.slice(1).forEach((line) => {
|
|
78
78
|
console.log(chalk.gray(` ${line}`));
|
|
79
79
|
});
|
|
@@ -135,7 +135,7 @@ async function handleStart() {
|
|
|
135
135
|
// 检查是否已经在运行
|
|
136
136
|
const existing = await getCCToolProcess();
|
|
137
137
|
if (existing && existing.pm2_env.status === 'online') {
|
|
138
|
-
console.log(chalk.yellow('\n
|
|
138
|
+
console.log(chalk.yellow('\n[WARN] 服务已在运行中\n'));
|
|
139
139
|
console.log(chalk.gray(`进程 ID: ${existing.pid}`));
|
|
140
140
|
console.log(chalk.gray(`运行时长: ${formatUptime(existing.pm2_env.pm_uptime)}`));
|
|
141
141
|
console.log(chalk.gray('\n使用 ') + chalk.cyan('ctx status') + chalk.gray(' 查看详细状态'));
|
|
@@ -168,12 +168,12 @@ async function handleStart() {
|
|
|
168
168
|
CC_TOOL_PORT: port
|
|
169
169
|
},
|
|
170
170
|
output: path.join(PATHS.logs, 'cc-tool-out.log'),
|
|
171
|
-
error: path.join(PATHS.logs, 'cc-tool-
|
|
171
|
+
error: path.join(PATHS.logs, 'cc-tool-out.log'),
|
|
172
172
|
merge_logs: true,
|
|
173
173
|
log_date_format: 'YYYY-MM-DD HH:mm:ss'
|
|
174
174
|
}, async (err) => {
|
|
175
175
|
if (err) {
|
|
176
|
-
console.error(chalk.red('\n
|
|
176
|
+
console.error(chalk.red('\n[ERROR] 启动服务失败:'), err.message);
|
|
177
177
|
disconnectPM2();
|
|
178
178
|
process.exit(1);
|
|
179
179
|
}
|
|
@@ -183,10 +183,10 @@ async function handleStart() {
|
|
|
183
183
|
readyState = await waitForServiceReady(port);
|
|
184
184
|
if (!readyState.ready) {
|
|
185
185
|
const statusText = readyState.process?.pm2_env?.status || 'unknown';
|
|
186
|
-
console.error(chalk.red('\n
|
|
186
|
+
console.error(chalk.red('\n[ERROR] Coding-Tool 服务启动失败,进程未就绪\n'));
|
|
187
187
|
console.error(chalk.gray(`PM2 状态: ${statusText}`));
|
|
188
188
|
printPortToolIssue(readyState.degradedPortCheckIssue);
|
|
189
|
-
console.error(chalk.yellow('
|
|
189
|
+
console.error(chalk.yellow('[TIP] 请使用 ctx logs ui 查看详细日志\n'));
|
|
190
190
|
|
|
191
191
|
pm2.delete(PM2_APP_NAME, () => {
|
|
192
192
|
pm2.dump(() => {
|
|
@@ -197,16 +197,16 @@ async function handleStart() {
|
|
|
197
197
|
return;
|
|
198
198
|
}
|
|
199
199
|
} catch (checkError) {
|
|
200
|
-
console.error(chalk.red('\n
|
|
200
|
+
console.error(chalk.red('\n[ERROR] 启动后健康检查失败:'), checkError.message);
|
|
201
201
|
disconnectPM2();
|
|
202
202
|
process.exit(1);
|
|
203
203
|
}
|
|
204
204
|
|
|
205
|
-
console.log(chalk.green('\n
|
|
205
|
+
console.log(chalk.green('\n[OK] Coding-Tool 服务已启动(后台运行)\n'));
|
|
206
206
|
console.log(chalk.gray(`Web UI: http://localhost:${port}`));
|
|
207
207
|
printPortToolIssue(readyState.degradedPortCheckIssue);
|
|
208
208
|
if (enableHost) {
|
|
209
|
-
console.log(chalk.yellow(
|
|
209
|
+
console.log(chalk.yellow(`[WARN] LAN 访问已启用 (http://<your-ip>:${port})`));
|
|
210
210
|
}
|
|
211
211
|
console.log(chalk.gray('\n可以安全关闭此终端窗口'));
|
|
212
212
|
console.log(chalk.gray('\n常用命令:'));
|
|
@@ -235,14 +235,14 @@ async function handleStop() {
|
|
|
235
235
|
|
|
236
236
|
const existing = await getCCToolProcess();
|
|
237
237
|
if (!existing) {
|
|
238
|
-
console.log(chalk.yellow('\n
|
|
238
|
+
console.log(chalk.yellow('\n[WARN] 服务未在运行\n'));
|
|
239
239
|
disconnectPM2();
|
|
240
240
|
return;
|
|
241
241
|
}
|
|
242
242
|
|
|
243
243
|
pm2.stop(PM2_APP_NAME, (err) => {
|
|
244
244
|
if (err) {
|
|
245
|
-
console.error(chalk.red('\n
|
|
245
|
+
console.error(chalk.red('\n[ERROR] 停止服务失败:'), err.message);
|
|
246
246
|
disconnectPM2();
|
|
247
247
|
process.exit(1);
|
|
248
248
|
}
|
|
@@ -252,7 +252,7 @@ async function handleStop() {
|
|
|
252
252
|
if (err) {
|
|
253
253
|
console.error(chalk.red('删除进程失败:'), err.message);
|
|
254
254
|
} else {
|
|
255
|
-
console.log(chalk.green('\n
|
|
255
|
+
console.log(chalk.green('\n[OK] Coding-Tool 服务已停止\n'));
|
|
256
256
|
}
|
|
257
257
|
|
|
258
258
|
pm2.dump((err) => {
|
|
@@ -276,19 +276,19 @@ async function handleRestart() {
|
|
|
276
276
|
|
|
277
277
|
const existing = await getCCToolProcess();
|
|
278
278
|
if (!existing) {
|
|
279
|
-
console.log(chalk.yellow('\n
|
|
279
|
+
console.log(chalk.yellow('\n[WARN] 服务未在运行,请使用 ') + chalk.cyan('ctx start') + chalk.yellow(' 启动\n'));
|
|
280
280
|
disconnectPM2();
|
|
281
281
|
return;
|
|
282
282
|
}
|
|
283
283
|
|
|
284
284
|
pm2.restart(PM2_APP_NAME, (err) => {
|
|
285
285
|
if (err) {
|
|
286
|
-
console.error(chalk.red('\n
|
|
286
|
+
console.error(chalk.red('\n[ERROR] 重启服务失败:'), err.message);
|
|
287
287
|
disconnectPM2();
|
|
288
288
|
process.exit(1);
|
|
289
289
|
}
|
|
290
290
|
|
|
291
|
-
console.log(chalk.green('\n
|
|
291
|
+
console.log(chalk.green('\n[OK] Coding-Tool 服务已重启\n'));
|
|
292
292
|
|
|
293
293
|
pm2.dump((err) => {
|
|
294
294
|
disconnectPM2();
|
|
@@ -311,21 +311,21 @@ async function handleStatus() {
|
|
|
311
311
|
const existing = await getCCToolProcess();
|
|
312
312
|
const config = loadConfig();
|
|
313
313
|
|
|
314
|
-
console.log(chalk.bold.cyan('\n
|
|
314
|
+
console.log(chalk.bold.cyan('\n╔======================================╗'));
|
|
315
315
|
console.log(chalk.bold.cyan('║ Coding-Tool 服务状态 ║'));
|
|
316
|
-
console.log(chalk.bold.cyan('
|
|
316
|
+
console.log(chalk.bold.cyan('╚======================================╝\n'));
|
|
317
317
|
|
|
318
318
|
// UI 服务状态
|
|
319
|
-
console.log(chalk.bold('
|
|
319
|
+
console.log(chalk.bold('[UI] Web UI 服务:'));
|
|
320
320
|
if (existing && existing.pm2_env.status === 'online') {
|
|
321
|
-
console.log(chalk.green('
|
|
322
|
-
console.log(chalk.gray(`
|
|
323
|
-
console.log(chalk.gray(`
|
|
324
|
-
console.log(chalk.gray(`
|
|
325
|
-
console.log(chalk.gray(`
|
|
326
|
-
console.log(chalk.gray(`
|
|
321
|
+
console.log(chalk.green(' [OK] 状态: 运行中'));
|
|
322
|
+
console.log(chalk.gray(` [NET] 地址: http://localhost:${config.ports?.webUI || 19999}`));
|
|
323
|
+
console.log(chalk.gray(` [KEY] 进程 ID: ${existing.pid}`));
|
|
324
|
+
console.log(chalk.gray(` [TIMER] 运行时长: ${formatUptime(existing.pm2_env.pm_uptime)}`));
|
|
325
|
+
console.log(chalk.gray(` [SAVE] 内存使用: ${formatMemory(existing.monit?.memory)}`));
|
|
326
|
+
console.log(chalk.gray(` [SYNC] 重启次数: ${existing.pm2_env.restart_time}`));
|
|
327
327
|
} else {
|
|
328
|
-
console.log(chalk.gray('
|
|
328
|
+
console.log(chalk.gray(' [ERROR] 状态: 未运行'));
|
|
329
329
|
}
|
|
330
330
|
|
|
331
331
|
// 代理服务状态(从运行时文件检测)
|
|
@@ -336,21 +336,21 @@ async function handleStatus() {
|
|
|
336
336
|
const geminiActive = fs.existsSync(PATHS.activeChannel.gemini);
|
|
337
337
|
const opencodeActive = fs.existsSync(PATHS.activeChannel.opencode);
|
|
338
338
|
|
|
339
|
-
console.log(chalk.bold('\n
|
|
339
|
+
console.log(chalk.bold('\n[PROXY] 代理服务:'));
|
|
340
340
|
|
|
341
|
-
console.log(chalk.gray(' Claude: ') + (claudeActive ? chalk.green('
|
|
341
|
+
console.log(chalk.gray(' Claude: ') + (claudeActive ? chalk.green('[OK] 运行中') : chalk.gray('[STOP] 未启动')) +
|
|
342
342
|
chalk.gray(` (http://localhost:${config.ports?.proxy || 20088})`));
|
|
343
343
|
|
|
344
|
-
console.log(chalk.gray(' Codex: ') + (codexActive ? chalk.green('
|
|
344
|
+
console.log(chalk.gray(' Codex: ') + (codexActive ? chalk.green('[OK] 运行中') : chalk.gray('[STOP] 未启动')) +
|
|
345
345
|
chalk.gray(` (http://localhost:${config.ports?.codexProxy || 20089})`));
|
|
346
346
|
|
|
347
|
-
console.log(chalk.gray(' Gemini: ') + (geminiActive ? chalk.green('
|
|
347
|
+
console.log(chalk.gray(' Gemini: ') + (geminiActive ? chalk.green('[OK] 运行中') : chalk.gray('[STOP] 未启动')) +
|
|
348
348
|
chalk.gray(` (http://localhost:${config.ports?.geminiProxy || 20090})`));
|
|
349
349
|
|
|
350
|
-
console.log(chalk.gray(' OpenCode:') + (opencodeActive ? chalk.green('
|
|
350
|
+
console.log(chalk.gray(' OpenCode:') + (opencodeActive ? chalk.green('[OK] 运行中') : chalk.gray('[STOP] 未启动')) +
|
|
351
351
|
chalk.gray(` (http://localhost:${config.ports?.opencodeProxy || 20091})`));
|
|
352
352
|
|
|
353
|
-
console.log(chalk.bold('\n
|
|
353
|
+
console.log(chalk.bold('\n[TIP] 提示:'));
|
|
354
354
|
console.log(chalk.gray(' • 代理服务通过 Web UI 界面控制'));
|
|
355
355
|
console.log(chalk.gray(' • 使用 ') + chalk.cyan('ctx logs [type]') + chalk.gray(' 查看日志'));
|
|
356
356
|
console.log(chalk.gray(' • 使用 ') + chalk.cyan('ctx stats [type]') + chalk.gray(' 查看统计信息\n'));
|
package/src/commands/doctor.js
CHANGED
|
@@ -13,9 +13,9 @@ const execAsync = promisify(exec);
|
|
|
13
13
|
* 诊断系统
|
|
14
14
|
*/
|
|
15
15
|
async function handleDoctor() {
|
|
16
|
-
console.log(chalk.bold.cyan('\n
|
|
16
|
+
console.log(chalk.bold.cyan('\n╔======================================╗'));
|
|
17
17
|
console.log(chalk.bold.cyan('║ Coding-Tool 系统诊断 ║'));
|
|
18
|
-
console.log(chalk.bold.cyan('
|
|
18
|
+
console.log(chalk.bold.cyan('╚======================================╝\n'));
|
|
19
19
|
|
|
20
20
|
const checks = [];
|
|
21
21
|
|
|
@@ -41,23 +41,23 @@ async function handleDoctor() {
|
|
|
41
41
|
checks.push(await checkDiskSpace());
|
|
42
42
|
|
|
43
43
|
// 显示结果
|
|
44
|
-
console.log(chalk.bold('\n
|
|
44
|
+
console.log(chalk.bold('\n[LOG] 诊断结果:\n'));
|
|
45
45
|
|
|
46
46
|
let passedCount = 0;
|
|
47
47
|
let warningCount = 0;
|
|
48
48
|
let failedCount = 0;
|
|
49
49
|
|
|
50
50
|
checks.forEach(check => {
|
|
51
|
-
const icon = check.status === 'pass' ? chalk.green('
|
|
52
|
-
check.status === 'warning' ? chalk.yellow('
|
|
53
|
-
chalk.red('
|
|
51
|
+
const icon = check.status === 'pass' ? chalk.green('[OK]') :
|
|
52
|
+
check.status === 'warning' ? chalk.yellow('[WARN]') :
|
|
53
|
+
chalk.red('[ERROR]');
|
|
54
54
|
|
|
55
55
|
console.log(`${icon} ${check.name}`);
|
|
56
56
|
if (check.message) {
|
|
57
57
|
console.log(chalk.gray(` ${check.message}`));
|
|
58
58
|
}
|
|
59
59
|
if (check.suggestion) {
|
|
60
|
-
console.log(chalk.cyan(`
|
|
60
|
+
console.log(chalk.cyan(` [TIP] ${check.suggestion}`));
|
|
61
61
|
}
|
|
62
62
|
console.log('');
|
|
63
63
|
|
|
@@ -67,23 +67,23 @@ async function handleDoctor() {
|
|
|
67
67
|
});
|
|
68
68
|
|
|
69
69
|
// 总结
|
|
70
|
-
console.log(chalk.bold('
|
|
71
|
-
console.log(chalk.green(`
|
|
70
|
+
console.log(chalk.bold('[STATS] 总结:'));
|
|
71
|
+
console.log(chalk.green(` [OK] 通过: ${passedCount}`));
|
|
72
72
|
if (warningCount > 0) {
|
|
73
|
-
console.log(chalk.yellow(`
|
|
73
|
+
console.log(chalk.yellow(` [WARN] 警告: ${warningCount}`));
|
|
74
74
|
}
|
|
75
75
|
if (failedCount > 0) {
|
|
76
|
-
console.log(chalk.red(`
|
|
76
|
+
console.log(chalk.red(` [ERROR] 失败: ${failedCount}`));
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
console.log('');
|
|
80
80
|
|
|
81
81
|
if (failedCount > 0) {
|
|
82
|
-
console.log(chalk.red('
|
|
82
|
+
console.log(chalk.red('[WARN] 发现问题,请根据上述建议进行修复\n'));
|
|
83
83
|
} else if (warningCount > 0) {
|
|
84
|
-
console.log(chalk.yellow('
|
|
84
|
+
console.log(chalk.yellow('[WARN] 发现一些警告,建议查看并处理\n'));
|
|
85
85
|
} else {
|
|
86
|
-
console.log(chalk.green('
|
|
86
|
+
console.log(chalk.green('[OK] 系统运行正常!\n'));
|
|
87
87
|
}
|
|
88
88
|
}
|
|
89
89
|
|
|
@@ -12,7 +12,7 @@ async function exportConfig(options = {}) {
|
|
|
12
12
|
const { output = 'claude-config.zip', includeProjects = true } = options;
|
|
13
13
|
|
|
14
14
|
try {
|
|
15
|
-
console.log(chalk.blue('
|
|
15
|
+
console.log(chalk.blue('[START] 开始导出 Claude Code 配置...'));
|
|
16
16
|
|
|
17
17
|
const homeDir = HOME_DIR;
|
|
18
18
|
const claudeDir = path.join(homeDir, '.claude');
|
|
@@ -20,7 +20,7 @@ async function exportConfig(options = {}) {
|
|
|
20
20
|
|
|
21
21
|
// 检查 .claude 目录是否存在
|
|
22
22
|
if (!fs.existsSync(claudeDir)) {
|
|
23
|
-
console.log(chalk.red('
|
|
23
|
+
console.log(chalk.red('[ERROR] 未找到 .claude 配置目录'));
|
|
24
24
|
return;
|
|
25
25
|
}
|
|
26
26
|
|
|
@@ -36,7 +36,7 @@ async function exportConfig(options = {}) {
|
|
|
36
36
|
|
|
37
37
|
// 监听完成
|
|
38
38
|
archive.on('end', () => {
|
|
39
|
-
console.log(chalk.green(`\n
|
|
39
|
+
console.log(chalk.green(`\n[OK] 配置导出成功!`));
|
|
40
40
|
console.log(chalk.gray(` 文件位置: ${outputPath}`));
|
|
41
41
|
console.log(chalk.gray(` 文件大小: ${(archive.pointer() / 1024 / 1024).toFixed(2)} MB`));
|
|
42
42
|
});
|
|
@@ -59,7 +59,7 @@ async function exportConfig(options = {}) {
|
|
|
59
59
|
archive.file(globalClaudeMd, { name: 'global/CLAUDE.md' });
|
|
60
60
|
manifest.globalConfig.claudeMd = true;
|
|
61
61
|
manifest.enabledConfigs.push('global/CLAUDE.md');
|
|
62
|
-
console.log(chalk.gray('
|
|
62
|
+
console.log(chalk.gray(' [v] 全局 CLAUDE.md'));
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
// 2. 导出 settings.json
|
|
@@ -68,7 +68,7 @@ async function exportConfig(options = {}) {
|
|
|
68
68
|
archive.file(settingsJson, { name: 'global/settings.json' });
|
|
69
69
|
manifest.globalConfig.settings = true;
|
|
70
70
|
manifest.enabledConfigs.push('global/settings.json');
|
|
71
|
-
console.log(chalk.gray('
|
|
71
|
+
console.log(chalk.gray(' [v] settings.json'));
|
|
72
72
|
|
|
73
73
|
// 解析 MCP 服务器配置
|
|
74
74
|
try {
|
|
@@ -84,7 +84,7 @@ async function exportConfig(options = {}) {
|
|
|
84
84
|
manifest.globalConfig.statusLine = true;
|
|
85
85
|
}
|
|
86
86
|
} catch (e) {
|
|
87
|
-
console.log(chalk.yellow('
|
|
87
|
+
console.log(chalk.yellow(' [!] settings.json 解析失败'));
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
90
|
|
|
@@ -96,7 +96,7 @@ async function exportConfig(options = {}) {
|
|
|
96
96
|
archive.directory(skillsDir, 'global/skills');
|
|
97
97
|
manifest.globalConfig.skills = skills;
|
|
98
98
|
manifest.enabledConfigs.push('global/skills');
|
|
99
|
-
console.log(chalk.gray(`
|
|
99
|
+
console.log(chalk.gray(` [v] Skills (${skills.length} 个)`));
|
|
100
100
|
}
|
|
101
101
|
}
|
|
102
102
|
|
|
@@ -108,7 +108,7 @@ async function exportConfig(options = {}) {
|
|
|
108
108
|
archive.file(projectClaudeMd, { name: 'project/CLAUDE.md' });
|
|
109
109
|
manifest.projectConfig.claudeMd = true;
|
|
110
110
|
manifest.enabledConfigs.push('project/CLAUDE.md');
|
|
111
|
-
console.log(chalk.gray('
|
|
111
|
+
console.log(chalk.gray(' [v] 项目 CLAUDE.md'));
|
|
112
112
|
}
|
|
113
113
|
|
|
114
114
|
// 项目级 settings.local.json
|
|
@@ -117,7 +117,7 @@ async function exportConfig(options = {}) {
|
|
|
117
117
|
archive.file(projectSettings, { name: 'project/.claude/settings.local.json' });
|
|
118
118
|
manifest.projectConfig.settingsLocal = true;
|
|
119
119
|
manifest.enabledConfigs.push('project/.claude/settings.local.json');
|
|
120
|
-
console.log(chalk.gray('
|
|
120
|
+
console.log(chalk.gray(' [v] 项目 settings.local.json'));
|
|
121
121
|
}
|
|
122
122
|
|
|
123
123
|
// 项目级 workspace CLAUDE.md
|
|
@@ -126,24 +126,24 @@ async function exportConfig(options = {}) {
|
|
|
126
126
|
archive.file(workspaceClaudeMd, { name: 'workspace/CLAUDE.md' });
|
|
127
127
|
manifest.projectConfig.workspaceClaudeMd = true;
|
|
128
128
|
manifest.enabledConfigs.push('workspace/CLAUDE.md');
|
|
129
|
-
console.log(chalk.gray('
|
|
129
|
+
console.log(chalk.gray(' [v] workspace CLAUDE.md'));
|
|
130
130
|
}
|
|
131
131
|
}
|
|
132
132
|
|
|
133
133
|
// 5. 添加配置清单
|
|
134
134
|
archive.append(JSON.stringify(manifest, null, 2), { name: 'manifest.json' });
|
|
135
|
-
console.log(chalk.gray('
|
|
135
|
+
console.log(chalk.gray(' [v] manifest.json'));
|
|
136
136
|
|
|
137
137
|
// 6. 添加 README
|
|
138
138
|
const readme = generateReadme(manifest);
|
|
139
139
|
archive.append(readme, { name: 'README.md' });
|
|
140
|
-
console.log(chalk.gray('
|
|
140
|
+
console.log(chalk.gray(' [v] README.md'));
|
|
141
141
|
|
|
142
142
|
// 完成打包
|
|
143
143
|
await archive.finalize();
|
|
144
144
|
|
|
145
145
|
} catch (error) {
|
|
146
|
-
console.error(chalk.red('
|
|
146
|
+
console.error(chalk.red('[ERROR] 导出失败:'), error.message);
|
|
147
147
|
throw error;
|
|
148
148
|
}
|
|
149
149
|
}
|
|
@@ -157,21 +157,21 @@ function generateReadme(manifest) {
|
|
|
157
157
|
导出时间: ${new Date(manifest.exportTime).toLocaleString('zh-CN')}
|
|
158
158
|
版本: ${manifest.version}
|
|
159
159
|
|
|
160
|
-
##
|
|
160
|
+
## [PKG] 包含内容
|
|
161
161
|
|
|
162
162
|
### 全局配置
|
|
163
|
-
${manifest.globalConfig.claudeMd ? '-
|
|
164
|
-
${manifest.globalConfig.settings ? '-
|
|
163
|
+
${manifest.globalConfig.claudeMd ? '- [OK] 全局 CLAUDE.md(AI 行为指令)' : ''}
|
|
164
|
+
${manifest.globalConfig.settings ? '- [OK] settings.json(包含 MCP 服务器、Hooks 等)' : ''}
|
|
165
165
|
${manifest.globalConfig.mcpServers ? ` - MCP 服务器: ${manifest.globalConfig.mcpServers.join(', ')}` : ''}
|
|
166
166
|
${manifest.globalConfig.hooks ? ` - Hooks: ${manifest.globalConfig.hooks.join(', ')}` : ''}
|
|
167
|
-
${manifest.globalConfig.skills ? `-
|
|
167
|
+
${manifest.globalConfig.skills ? `- [OK] Skills (${manifest.globalConfig.skills.length} 个): ${manifest.globalConfig.skills.join(', ')}` : ''}
|
|
168
168
|
|
|
169
169
|
### 项目配置
|
|
170
|
-
${manifest.projectConfig.claudeMd ? '-
|
|
171
|
-
${manifest.projectConfig.settingsLocal ? '-
|
|
172
|
-
${manifest.projectConfig.workspaceClaudeMd ? '-
|
|
170
|
+
${manifest.projectConfig.claudeMd ? '- [OK] 项目 CLAUDE.md' : ''}
|
|
171
|
+
${manifest.projectConfig.settingsLocal ? '- [OK] 项目 settings.local.json' : ''}
|
|
172
|
+
${manifest.projectConfig.workspaceClaudeMd ? '- [OK] workspace CLAUDE.md' : ''}
|
|
173
173
|
|
|
174
|
-
##
|
|
174
|
+
## [IMPORT] 如何导入
|
|
175
175
|
|
|
176
176
|
### 方法 1:手动导入
|
|
177
177
|
1. 解压此 ZIP 文件
|
|
@@ -184,14 +184,14 @@ ${manifest.projectConfig.workspaceClaudeMd ? '- ✅ workspace CLAUDE.md' : ''}
|
|
|
184
184
|
ctx import-config claude-config.zip
|
|
185
185
|
\`\`\`
|
|
186
186
|
|
|
187
|
-
##
|
|
187
|
+
## [WARN] 注意事项
|
|
188
188
|
|
|
189
189
|
1. **备份现有配置**:导入前请备份现有的 \`.claude\` 目录
|
|
190
190
|
2. **敏感信息**:此配置包可能包含 API Keys、代理配置等敏感信息,请妥善保管
|
|
191
191
|
3. **路径适配**:某些路径可能需要根据你的系统调整(如 hooks 中的脚本路径)
|
|
192
192
|
4. **MCP 服务器**:需要确保目标环境已安装对应的 MCP 服务器
|
|
193
193
|
|
|
194
|
-
##
|
|
194
|
+
## [NOTE] 配置清单
|
|
195
195
|
|
|
196
196
|
已启用的配置项:
|
|
197
197
|
${manifest.enabledConfigs.map(c => `- ${c}`).join('\n')}
|
package/src/commands/list.js
CHANGED
|
@@ -77,7 +77,7 @@ async function listSessions(config, limit = null) {
|
|
|
77
77
|
|
|
78
78
|
// 清屏并重新显示,避免之前的输出干扰
|
|
79
79
|
console.clear();
|
|
80
|
-
console.log(chalk.green(`\n
|
|
80
|
+
console.log(chalk.green(`\n[NEW] 找到 ${sessions.length} 个会话\n`));
|
|
81
81
|
|
|
82
82
|
return choices;
|
|
83
83
|
}
|
|
@@ -150,7 +150,7 @@ async function listRecentSessionsAcrossProjects(config, limit = null) {
|
|
|
150
150
|
|
|
151
151
|
// 清屏并重新显示,避免之前的输出干扰
|
|
152
152
|
console.clear();
|
|
153
|
-
console.log(chalk.green(`\n
|
|
153
|
+
console.log(chalk.green(`\n[NEW] 找到 ${sessions.length} 个最新对话(跨所有项目)\n`));
|
|
154
154
|
|
|
155
155
|
return choices;
|
|
156
156
|
}
|
|
@@ -171,11 +171,11 @@ async function handleList(config, switchProjectCallback, crossProject = false) {
|
|
|
171
171
|
|
|
172
172
|
// 添加操作选项
|
|
173
173
|
choices.push(new inquirer.Separator(chalk.gray('─'.repeat(50))));
|
|
174
|
-
choices.push({ name: chalk.blue('
|
|
174
|
+
choices.push({ name: chalk.blue('[<-] 返回主菜单'), value: 'back' });
|
|
175
175
|
|
|
176
176
|
// 跨项目模式不显示切换项目选项(因为已经是跨所有项目了)
|
|
177
177
|
if (!crossProject) {
|
|
178
|
-
choices.push({ name: chalk.magenta('
|
|
178
|
+
choices.push({ name: chalk.magenta('[SWITCH] 切换项目'), value: 'switch' });
|
|
179
179
|
}
|
|
180
180
|
|
|
181
181
|
const selected = await promptSelectSession(choices);
|