yingclaw 1.6.0 → 1.6.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.
- package/bin/cli.js +32 -8
- package/index.js +4 -0
- package/lib/config.js +23 -1
- package/package.json +1 -1
package/bin/cli.js
CHANGED
|
@@ -8,6 +8,7 @@ const {
|
|
|
8
8
|
writeEnvToZshrc,
|
|
9
9
|
fetchModels,
|
|
10
10
|
resetConfig,
|
|
11
|
+
validateConfig,
|
|
11
12
|
resolveFastModel,
|
|
12
13
|
buildClaudeEnv,
|
|
13
14
|
classifyValidationStatus,
|
|
@@ -66,6 +67,11 @@ async function validateKey(config) {
|
|
|
66
67
|
});
|
|
67
68
|
}
|
|
68
69
|
|
|
70
|
+
function getConfigValidationMessage(config) {
|
|
71
|
+
const validation = validateConfig(config);
|
|
72
|
+
return validation.valid ? null : validation.message;
|
|
73
|
+
}
|
|
74
|
+
|
|
69
75
|
function isClaudeInstalled() {
|
|
70
76
|
try {
|
|
71
77
|
execSync('claude --version', { stdio: 'pipe' });
|
|
@@ -85,6 +91,12 @@ async function showStatus() {
|
|
|
85
91
|
console.log(chalk.red('\n未配置,请先运行: claw setup\n'));
|
|
86
92
|
return;
|
|
87
93
|
}
|
|
94
|
+
const configProblem = getConfigValidationMessage(config);
|
|
95
|
+
if (configProblem) {
|
|
96
|
+
console.log(chalk.red(`\n配置无效:${configProblem}`));
|
|
97
|
+
console.log(chalk.dim('请运行 claw setup 重新配置。\n'));
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
88
100
|
|
|
89
101
|
const spinner = ora('验证 API Key...').start();
|
|
90
102
|
const valid = await validateKey(config);
|
|
@@ -218,7 +230,7 @@ program
|
|
|
218
230
|
chalk.bold('当前配置\n\n') +
|
|
219
231
|
chalk.dim('厂商 ') + chalk.white(existingProvider?.name || existing.provider) + '\n' +
|
|
220
232
|
chalk.dim('模型 ') + chalk.yellow(existing.model) + '\n' +
|
|
221
|
-
chalk.dim('Key ') + chalk.dim(existing.apiKey
|
|
233
|
+
chalk.dim('Key ') + chalk.dim(existing.apiKey ? '已保存' : '缺失'),
|
|
222
234
|
{ padding: { top: 0, bottom: 0, left: 2, right: 2 }, borderStyle: 'round', borderColor: 'yellow', margin: { top: 1, bottom: 1 } }
|
|
223
235
|
));
|
|
224
236
|
const overwrite = await confirm({ message: '覆盖现有配置?', default: false });
|
|
@@ -291,7 +303,7 @@ program
|
|
|
291
303
|
console.log(boxen(
|
|
292
304
|
chalk.bold('配置完成!\n\n') +
|
|
293
305
|
chalk.dim('ANTHROPIC_BASE_URL ') + chalk.cyan(provider.baseUrl) + '\n' +
|
|
294
|
-
chalk.dim('ANTHROPIC_API_KEY ') + chalk.cyan(
|
|
306
|
+
chalk.dim('ANTHROPIC_API_KEY ') + chalk.cyan('已保存') + '\n\n' +
|
|
295
307
|
chalk.white('下次直接输入 ') + chalk.cyan.bold('claude') + chalk.white(' 即可使用'),
|
|
296
308
|
{ padding: { top: 0, bottom: 0, left: 2, right: 2 }, borderStyle: 'round', borderColor: 'green', margin: { top: 1, bottom: 1 } }
|
|
297
309
|
));
|
|
@@ -322,6 +334,12 @@ program
|
|
|
322
334
|
console.log(chalk.red('\n未配置,请先运行: claw setup\n'));
|
|
323
335
|
return;
|
|
324
336
|
}
|
|
337
|
+
const configProblem = getConfigValidationMessage(config);
|
|
338
|
+
if (configProblem) {
|
|
339
|
+
console.log(chalk.red(`\n配置无效:${configProblem}`));
|
|
340
|
+
console.log(chalk.dim('请运行 claw setup 重新配置。\n'));
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
325
343
|
|
|
326
344
|
const providerKey = await select({ loop: false,
|
|
327
345
|
message: chalk.cyan('选择 AI 厂商'),
|
|
@@ -464,7 +482,8 @@ async function runMenu() {
|
|
|
464
482
|
|
|
465
483
|
const config = loadConfig();
|
|
466
484
|
let apiStatus; // undefined = skipped, true/false/null = checked
|
|
467
|
-
|
|
485
|
+
const configProblem = config ? getConfigValidationMessage(config) : null;
|
|
486
|
+
if (config && !configProblem) {
|
|
468
487
|
const spinner = ora('正在检测 API 是否通畅...').start();
|
|
469
488
|
apiStatus = await validateKey(config);
|
|
470
489
|
if (apiStatus === true) spinner.succeed('API 连接正常');
|
|
@@ -472,18 +491,23 @@ async function runMenu() {
|
|
|
472
491
|
else spinner.warn('网络异常,无法连接 API');
|
|
473
492
|
}
|
|
474
493
|
|
|
475
|
-
|
|
494
|
+
if (configProblem) {
|
|
495
|
+
console.log(chalk.red(` ● 配置无效:${configProblem}`));
|
|
496
|
+
console.log(chalk.dim(' 请先选择“首次配置 API Key 和模型”重新配置'));
|
|
497
|
+
} else {
|
|
498
|
+
console.log(await renderStatusBar(apiStatus));
|
|
499
|
+
}
|
|
476
500
|
console.log();
|
|
477
501
|
|
|
478
502
|
const action = await select({ loop: false,
|
|
479
503
|
message: chalk.cyan('选择操作'),
|
|
480
504
|
choices: [
|
|
481
|
-
{ name: '🤖 启动 Claude Code', value: 'launch', disabled: !config && '需先完成配置' },
|
|
505
|
+
{ name: '🤖 启动 Claude Code', value: 'launch', disabled: (!config || configProblem) && '需先完成配置' },
|
|
482
506
|
{ name: '📦 安装 Claude Code', value: 'install' },
|
|
483
507
|
{ name: config ? '⚙️ 重新配置(输入新的 API Key)' : '⚙️ 首次配置 API Key 和模型', value: 'setup' },
|
|
484
|
-
{ name: '🔄 切换厂商或模型', value: 'switch', disabled: !config && '需先完成配置' },
|
|
508
|
+
{ name: '🔄 切换厂商或模型', value: 'switch', disabled: (!config || configProblem) && '需先完成配置' },
|
|
485
509
|
{ name: '📊 查看当前配置', value: 'status', disabled: !config && '需先完成配置' },
|
|
486
|
-
{ name: '🔁 重新检测 API', value: 'recheck', disabled: !config && '需先完成配置' },
|
|
510
|
+
{ name: '🔁 重新检测 API', value: 'recheck', disabled: (!config || configProblem) && '需先完成配置' },
|
|
487
511
|
{ name: '🗑 恢复默认(清除所有配置)', value: 'reset', disabled: !config && '没有可清除的配置' },
|
|
488
512
|
{ name: '退出', value: 'exit' },
|
|
489
513
|
],
|
|
@@ -498,7 +522,7 @@ async function runMenu() {
|
|
|
498
522
|
|
|
499
523
|
if (action === 'launch') {
|
|
500
524
|
const cfg = loadConfig();
|
|
501
|
-
if (!cfg) continue;
|
|
525
|
+
if (!cfg || getConfigValidationMessage(cfg)) continue;
|
|
502
526
|
// 启动 claude 后等它退出,然后回菜单
|
|
503
527
|
await new Promise((resolve) => {
|
|
504
528
|
const child = spawn('claude', [], {
|
package/index.js
ADDED
package/lib/config.js
CHANGED
|
@@ -106,6 +106,21 @@ function loadConfig() {
|
|
|
106
106
|
}
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
+
function validateConfig(config) {
|
|
110
|
+
if (!config || typeof config !== 'object') {
|
|
111
|
+
return { valid: false, message: '未找到配置' };
|
|
112
|
+
}
|
|
113
|
+
for (const key of ['provider', 'baseUrl', 'apiKey', 'model']) {
|
|
114
|
+
if (typeof config[key] !== 'string' || config[key].trim().length === 0) {
|
|
115
|
+
return { valid: false, message: `配置缺少 ${key}` };
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if (!PROVIDERS[config.provider]) {
|
|
119
|
+
return { valid: false, message: `未知厂商 ${config.provider}` };
|
|
120
|
+
}
|
|
121
|
+
return { valid: true };
|
|
122
|
+
}
|
|
123
|
+
|
|
109
124
|
function saveConfig(config) {
|
|
110
125
|
fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2));
|
|
111
126
|
try {
|
|
@@ -113,6 +128,10 @@ function saveConfig(config) {
|
|
|
113
128
|
} catch {}
|
|
114
129
|
}
|
|
115
130
|
|
|
131
|
+
function providerKeyFromBaseUrl(baseUrl) {
|
|
132
|
+
return Object.entries(PROVIDERS).find(([, provider]) => provider.baseUrl === baseUrl)?.[0];
|
|
133
|
+
}
|
|
134
|
+
|
|
116
135
|
function resolveFastModel(provider, model) {
|
|
117
136
|
if (/flash|turbo|haiku|air|lite/i.test(model)) return model;
|
|
118
137
|
return provider?.fastModel || model;
|
|
@@ -145,7 +164,8 @@ function shellQuote(value) {
|
|
|
145
164
|
|
|
146
165
|
// 构造完整的 clawai 环境变量块
|
|
147
166
|
function buildEnvBlock(baseUrl, apiKey, model, fastModel) {
|
|
148
|
-
const
|
|
167
|
+
const provider = providerKeyFromBaseUrl(baseUrl);
|
|
168
|
+
const env = buildClaudeEnv({ provider, baseUrl, apiKey, model, fastModel });
|
|
149
169
|
return [
|
|
150
170
|
'',
|
|
151
171
|
'# clawai-start',
|
|
@@ -224,7 +244,9 @@ module.exports = {
|
|
|
224
244
|
writeEnvToZshrc,
|
|
225
245
|
fetchModels,
|
|
226
246
|
resetConfig,
|
|
247
|
+
validateConfig,
|
|
227
248
|
resolveFastModel,
|
|
249
|
+
providerKeyFromBaseUrl,
|
|
228
250
|
buildClaudeEnv,
|
|
229
251
|
buildEnvBlock,
|
|
230
252
|
classifyValidationStatus,
|