yingclaw 1.4.0 → 1.5.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 +37 -11
- package/package.json +1 -1
package/bin/cli.js
CHANGED
|
@@ -114,7 +114,7 @@ program
|
|
|
114
114
|
if (!yes) return;
|
|
115
115
|
} catch {}
|
|
116
116
|
|
|
117
|
-
const network = await select({
|
|
117
|
+
const network = await select({ loop: false,
|
|
118
118
|
message: chalk.cyan('你的网络环境'),
|
|
119
119
|
choices: [
|
|
120
120
|
{ name: '有梯子 / 海外网络(走官方)', value: 'vpn' },
|
|
@@ -190,7 +190,7 @@ program
|
|
|
190
190
|
|
|
191
191
|
while (true) {
|
|
192
192
|
if (step === 'provider') {
|
|
193
|
-
providerKey = await select({
|
|
193
|
+
providerKey = await select({ loop: false,
|
|
194
194
|
message: chalk.cyan('选择 AI 厂商'),
|
|
195
195
|
choices: [
|
|
196
196
|
...Object.entries(PROVIDERS).map(([value, p]) => ({ name: p.name, value })),
|
|
@@ -221,7 +221,7 @@ program
|
|
|
221
221
|
modelChoices = provider.models;
|
|
222
222
|
}
|
|
223
223
|
|
|
224
|
-
const m = await select({
|
|
224
|
+
const m = await select({ loop: false,
|
|
225
225
|
message: chalk.cyan('选择模型'),
|
|
226
226
|
choices: [
|
|
227
227
|
...modelChoices,
|
|
@@ -282,7 +282,7 @@ program
|
|
|
282
282
|
return;
|
|
283
283
|
}
|
|
284
284
|
|
|
285
|
-
const providerKey = await select({
|
|
285
|
+
const providerKey = await select({ loop: false,
|
|
286
286
|
message: chalk.cyan('选择 AI 厂商'),
|
|
287
287
|
choices: [
|
|
288
288
|
...Object.entries(PROVIDERS).map(([value, p]) => ({ name: p.name, value })),
|
|
@@ -319,7 +319,7 @@ program
|
|
|
319
319
|
modelChoices = provider.models;
|
|
320
320
|
}
|
|
321
321
|
|
|
322
|
-
const model = await select({
|
|
322
|
+
const model = await select({ loop: false,
|
|
323
323
|
message: chalk.cyan('选择模型'),
|
|
324
324
|
choices: [
|
|
325
325
|
...modelChoices,
|
|
@@ -342,7 +342,7 @@ program
|
|
|
342
342
|
.description('查看当前配置和 Key 有效性')
|
|
343
343
|
.action(showStatus);
|
|
344
344
|
|
|
345
|
-
async function renderStatusBar() {
|
|
345
|
+
async function renderStatusBar(apiStatus) {
|
|
346
346
|
const chalk = (await import('chalk')).default;
|
|
347
347
|
const config = loadConfig();
|
|
348
348
|
const claudeInstalled = (() => {
|
|
@@ -355,7 +355,16 @@ async function renderStatusBar() {
|
|
|
355
355
|
let cfgPart;
|
|
356
356
|
if (config) {
|
|
357
357
|
const provName = PROVIDERS[config.provider]?.name || config.provider;
|
|
358
|
-
|
|
358
|
+
let dot;
|
|
359
|
+
if (apiStatus === true) dot = chalk.green('●');
|
|
360
|
+
else if (apiStatus === false) dot = chalk.red('●');
|
|
361
|
+
else if (apiStatus === null) dot = chalk.yellow('●');
|
|
362
|
+
else dot = chalk.dim('●'); // 未检测
|
|
363
|
+
const apiTag = apiStatus === true ? chalk.green(' API ✓')
|
|
364
|
+
: apiStatus === false ? chalk.red(' API ✘')
|
|
365
|
+
: apiStatus === null ? chalk.yellow(' 网络异常')
|
|
366
|
+
: '';
|
|
367
|
+
cfgPart = `${dot} ${chalk.white(provName)}${chalk.dim(' · ')}${chalk.yellow(config.model)}${apiTag}`;
|
|
359
368
|
} else {
|
|
360
369
|
cfgPart = chalk.red('●') + ' ' + chalk.dim('未配置');
|
|
361
370
|
}
|
|
@@ -365,15 +374,26 @@ async function renderStatusBar() {
|
|
|
365
374
|
|
|
366
375
|
async function runMenu() {
|
|
367
376
|
const chalk = (await import('chalk')).default;
|
|
377
|
+
const ora = (await import('ora')).default;
|
|
368
378
|
|
|
369
379
|
while (true) {
|
|
370
380
|
console.clear();
|
|
371
381
|
console.log(await getBanner());
|
|
372
|
-
console.log(await renderStatusBar());
|
|
373
|
-
console.log();
|
|
374
382
|
|
|
375
383
|
const config = loadConfig();
|
|
376
|
-
|
|
384
|
+
let apiStatus; // undefined = skipped, true/false/null = checked
|
|
385
|
+
if (config) {
|
|
386
|
+
const spinner = ora('正在检测 API 是否通畅...').start();
|
|
387
|
+
apiStatus = await validateKey(config);
|
|
388
|
+
if (apiStatus === true) spinner.succeed('API 连接正常');
|
|
389
|
+
else if (apiStatus === false) spinner.fail('API Key 无效或已过期');
|
|
390
|
+
else spinner.warn('网络异常,无法连接 API');
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
console.log(await renderStatusBar(apiStatus));
|
|
394
|
+
console.log();
|
|
395
|
+
|
|
396
|
+
const action = await select({ loop: false,
|
|
377
397
|
message: chalk.cyan('选择操作'),
|
|
378
398
|
choices: [
|
|
379
399
|
{ name: '🤖 启动 Claude Code', value: 'launch', disabled: !config && '需先完成配置' },
|
|
@@ -381,12 +401,18 @@ async function runMenu() {
|
|
|
381
401
|
{ name: config ? '⚙️ 重新配置(输入新的 API Key)' : '⚙️ 首次配置 API Key 和模型', value: 'setup' },
|
|
382
402
|
{ name: '🔄 切换厂商/模型(保留当前 Key)', value: 'switch', disabled: !config && '需先完成配置' },
|
|
383
403
|
{ name: '📊 查看当前配置', value: 'status', disabled: !config && '需先完成配置' },
|
|
404
|
+
{ name: '🔁 重新检测 API', value: 'recheck', disabled: !config && '需先完成配置' },
|
|
384
405
|
{ name: '退出', value: 'exit' },
|
|
385
406
|
],
|
|
386
407
|
});
|
|
387
408
|
|
|
388
409
|
if (action === 'exit') return;
|
|
389
410
|
|
|
411
|
+
if (action === 'recheck') {
|
|
412
|
+
// 仅刷新菜单,下次循环会重新检测
|
|
413
|
+
continue;
|
|
414
|
+
}
|
|
415
|
+
|
|
390
416
|
if (action === 'launch') {
|
|
391
417
|
const cfg = loadConfig();
|
|
392
418
|
if (!cfg) continue;
|
|
@@ -421,7 +447,7 @@ async function runMenu() {
|
|
|
421
447
|
|
|
422
448
|
// 操作结束,提示返回菜单
|
|
423
449
|
console.log();
|
|
424
|
-
const next = await select({
|
|
450
|
+
const next = await select({ loop: false,
|
|
425
451
|
message: chalk.cyan('下一步'),
|
|
426
452
|
choices: [
|
|
427
453
|
{ name: '↩ 返回主菜单', value: 'menu' },
|