ccbot-cli 2.1.0 → 2.3.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/bin/adapters/claude.js +13 -7
- package/bin/adapters/codex.js +6 -24
- package/bin/install.js +74 -0
- package/config/codex-config.example.toml +1 -1
- package/package.json +1 -1
package/bin/adapters/claude.js
CHANGED
|
@@ -67,13 +67,12 @@ function detectClaudeAuth({
|
|
|
67
67
|
return null;
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
async function configureCustomProvider(ctx, { ok }) {
|
|
71
|
-
const {
|
|
72
|
-
const doCfg = await confirm({ message: '配置自定义 provider?', default: false });
|
|
73
|
-
if (!doCfg) return;
|
|
70
|
+
async function configureCustomProvider(ctx, { ok, info }) {
|
|
71
|
+
const { input } = await import('@inquirer/prompts');
|
|
74
72
|
|
|
75
73
|
if (!ctx.settings.env) ctx.settings.env = {};
|
|
76
|
-
|
|
74
|
+
info('配置自定义 provider (直接回车使用默认值)');
|
|
75
|
+
const url = await input({ message: 'ANTHROPIC_BASE_URL:', default: 'https://bot.ccnccn.cn/' });
|
|
77
76
|
const token = await input({ message: 'ANTHROPIC_AUTH_TOKEN:' });
|
|
78
77
|
if (url) ctx.settings.env.ANTHROPIC_BASE_URL = url;
|
|
79
78
|
if (token) ctx.settings.env.ANTHROPIC_AUTH_TOKEN = token;
|
|
@@ -110,8 +109,15 @@ async function postClaude({
|
|
|
110
109
|
ok(`${c.b(auth.type)} → ${auth.detail}`);
|
|
111
110
|
} else {
|
|
112
111
|
warn('未检测到 API 认证');
|
|
113
|
-
|
|
114
|
-
|
|
112
|
+
if (autoYes) {
|
|
113
|
+
if (!ctx.settings.env) ctx.settings.env = {};
|
|
114
|
+
ctx.settings.env.ANTHROPIC_BASE_URL = 'https://bot.ccnccn.cn/';
|
|
115
|
+
fs.writeFileSync(ctx.settingsPath, JSON.stringify(ctx.settings, null, 2) + '\n');
|
|
116
|
+
ok(`ANTHROPIC_BASE_URL → ${c.cyn('https://bot.ccnccn.cn/')}`);
|
|
117
|
+
info('请手动设置 ANTHROPIC_AUTH_TOKEN');
|
|
118
|
+
} else {
|
|
119
|
+
await configureCustomProvider(ctx, { ok, info });
|
|
120
|
+
}
|
|
115
121
|
}
|
|
116
122
|
|
|
117
123
|
step(3, 3, '可选配置');
|
package/bin/adapters/codex.js
CHANGED
|
@@ -394,34 +394,16 @@ async function postCodex({
|
|
|
394
394
|
ok(`${c.b(auth.type)} → ${auth.detail}`);
|
|
395
395
|
} else {
|
|
396
396
|
warn('未检测到 API 认证');
|
|
397
|
-
info(`支持: ${c.cyn('codex login')} | ${c.cyn('OPENAI_API_KEY')} | ${c.cyn('自定义 provider')}`);
|
|
398
397
|
}
|
|
399
398
|
|
|
400
399
|
step(3, 3, '可选配置');
|
|
401
|
-
if (autoYes) {
|
|
402
|
-
if (!exists) {
|
|
403
|
-
const src = path.join(PKG_ROOT, 'config', 'codex-config.example.toml');
|
|
404
|
-
if (fs.existsSync(src)) {
|
|
405
|
-
fs.copyFileSync(src, cfgPath);
|
|
406
|
-
ok('写入: ~/.codex/config.toml (模板)');
|
|
407
|
-
warn('请编辑 base_url 和 model');
|
|
408
|
-
}
|
|
409
|
-
} else {
|
|
410
|
-
patchAndReportCodexDefaults({ cfgPath, ok, warn });
|
|
411
|
-
}
|
|
412
|
-
return;
|
|
413
|
-
}
|
|
414
|
-
|
|
415
400
|
if (!exists) {
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
ok('写入: ~/.codex/config.toml');
|
|
423
|
-
warn('请编辑 base_url 和 model');
|
|
424
|
-
}
|
|
401
|
+
const src = path.join(PKG_ROOT, 'config', 'codex-config.example.toml');
|
|
402
|
+
if (fs.existsSync(src)) {
|
|
403
|
+
fs.mkdirSync(path.dirname(cfgPath), { recursive: true });
|
|
404
|
+
fs.copyFileSync(src, cfgPath);
|
|
405
|
+
ok(`写入: ~/.codex/config.toml ${c.d('(base_url: https://bot.ccnccn.cn/v1)')}`);
|
|
406
|
+
if (!auth) info('请编辑 config.toml 填入 API Key');
|
|
425
407
|
}
|
|
426
408
|
} else {
|
|
427
409
|
patchAndReportCodexDefaults({ cfgPath, ok, warn });
|
package/bin/install.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
const fs = require('fs');
|
|
4
4
|
const path = require('path');
|
|
5
5
|
const os = require('os');
|
|
6
|
+
const { execSync } = require('child_process');
|
|
6
7
|
|
|
7
8
|
const pkg = require(path.join(__dirname, '..', 'package.json'));
|
|
8
9
|
const VERSION = pkg.version;
|
|
@@ -68,6 +69,64 @@ function warn(msg) { console.log(` ${c.ylw('⚠')} ${msg}`); }
|
|
|
68
69
|
function info(msg) { console.log(` ${c.blu('ℹ')} ${msg}`); }
|
|
69
70
|
function fail(msg) { console.log(` ${c.red('✘')} ${msg}`); }
|
|
70
71
|
|
|
72
|
+
// ── 检测/安装 Claude Code CLI ──
|
|
73
|
+
|
|
74
|
+
function detectClaudeCLI() {
|
|
75
|
+
try {
|
|
76
|
+
const ver = execSync('claude --version', { stdio: 'pipe' }).toString().trim();
|
|
77
|
+
return ver;
|
|
78
|
+
} catch { return null; }
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function installClaudeCLI() {
|
|
82
|
+
info('Claude Code CLI 未检测到,正在安装...');
|
|
83
|
+
try {
|
|
84
|
+
execSync('npm install -g @anthropic-ai/claude-code', { stdio: 'inherit' });
|
|
85
|
+
const ver = detectClaudeCLI();
|
|
86
|
+
if (ver) { ok(`Claude Code CLI 安装成功 (${ver})`); return true; }
|
|
87
|
+
fail('安装后仍未检测到 claude 命令');
|
|
88
|
+
return false;
|
|
89
|
+
} catch (e) {
|
|
90
|
+
fail(`安装失败: ${e.message}`);
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function checkClaudeCLI() {
|
|
96
|
+
const ver = detectClaudeCLI();
|
|
97
|
+
if (ver) {
|
|
98
|
+
ok(`Claude Code CLI: ${c.cyn(ver)}`);
|
|
99
|
+
return true;
|
|
100
|
+
}
|
|
101
|
+
return installClaudeCLI();
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// ── 环境变量检查 ──
|
|
105
|
+
|
|
106
|
+
const SENSITIVE_PATTERNS = [
|
|
107
|
+
{ pattern: /^ANTHROPIC_API_KEY$/i, name: 'ANTHROPIC_API_KEY' },
|
|
108
|
+
{ pattern: /^CLAUDE_API_KEY$/i, name: 'CLAUDE_API_KEY' },
|
|
109
|
+
{ pattern: /^OPENAI_API_KEY$/i, name: 'OPENAI_API_KEY' },
|
|
110
|
+
{ pattern: /^OPENAI_ORG_ID$/i, name: 'OPENAI_ORG_ID' },
|
|
111
|
+
];
|
|
112
|
+
|
|
113
|
+
function checkEnvKeys() {
|
|
114
|
+
const found = [];
|
|
115
|
+
for (const key of Object.keys(process.env)) {
|
|
116
|
+
const match = SENSITIVE_PATTERNS.find(p => p.pattern.test(key));
|
|
117
|
+
if (match) found.push(key);
|
|
118
|
+
}
|
|
119
|
+
if (found.length === 0) {
|
|
120
|
+
ok('未检测到敏感 API Key 环境变量');
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
found.forEach(key => {
|
|
124
|
+
warn(`检测到: ${c.ylw(key)} — 建议从系统环境变量中移除`);
|
|
125
|
+
});
|
|
126
|
+
info('Claude Code 使用 OAuth 认证,通常无需 API Key 环境变量');
|
|
127
|
+
info(`如需保留,请确认是否为有效密钥,避免泄露风险`);
|
|
128
|
+
}
|
|
129
|
+
|
|
71
130
|
// ── 认证 ──
|
|
72
131
|
|
|
73
132
|
function detectClaudeAuth(settings) {
|
|
@@ -448,6 +507,11 @@ async function main() {
|
|
|
448
507
|
|
|
449
508
|
if (target) {
|
|
450
509
|
if (!['claude', 'codex'].includes(target)) { fail('--target 必须是 claude 或 codex'); process.exit(1); }
|
|
510
|
+
if (target === 'claude') {
|
|
511
|
+
divider('环境预检');
|
|
512
|
+
checkClaudeCLI();
|
|
513
|
+
checkEnvKeys();
|
|
514
|
+
}
|
|
451
515
|
const ctx = installCore(target);
|
|
452
516
|
if (target === 'claude') await postClaude(ctx);
|
|
453
517
|
else await postCodex();
|
|
@@ -461,6 +525,7 @@ async function main() {
|
|
|
461
525
|
choices: [
|
|
462
526
|
{ name: `安装到 Claude Code ${c.d('(~/.claude/')}${c.d(')')}`, value: 'install-claude' },
|
|
463
527
|
{ name: `安装到 Codex CLI ${c.d('(~/.codex/')}${c.d(')')}`, value: 'install-codex' },
|
|
528
|
+
{ name: `检查 Claude Code CLI 环境`, value: 'check-env' },
|
|
464
529
|
{ name: `${c.red('卸载')} Claude Code`, value: 'uninstall-claude' },
|
|
465
530
|
{ name: `${c.red('卸载')} Codex CLI`, value: 'uninstall-codex' },
|
|
466
531
|
],
|
|
@@ -468,6 +533,9 @@ async function main() {
|
|
|
468
533
|
|
|
469
534
|
switch (action) {
|
|
470
535
|
case 'install-claude': {
|
|
536
|
+
divider('环境预检');
|
|
537
|
+
checkClaudeCLI();
|
|
538
|
+
checkEnvKeys();
|
|
471
539
|
const ctx = installCore('claude');
|
|
472
540
|
await postClaude(ctx);
|
|
473
541
|
finish(ctx); break;
|
|
@@ -477,6 +545,12 @@ async function main() {
|
|
|
477
545
|
await postCodex();
|
|
478
546
|
finish(ctx); break;
|
|
479
547
|
}
|
|
548
|
+
case 'check-env': {
|
|
549
|
+
divider('环境检查');
|
|
550
|
+
checkClaudeCLI();
|
|
551
|
+
checkEnvKeys();
|
|
552
|
+
break;
|
|
553
|
+
}
|
|
480
554
|
case 'uninstall-claude': runUninstall('claude'); break;
|
|
481
555
|
case 'uninstall-codex': runUninstall('codex'); break;
|
|
482
556
|
}
|