yymaxapi 1.0.55 → 1.0.57
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/yymaxapi.js +85 -45
- package/package.json +1 -1
package/bin/yymaxapi.js
CHANGED
|
@@ -3397,62 +3397,77 @@ async function switchModel(paths) {
|
|
|
3397
3397
|
return;
|
|
3398
3398
|
}
|
|
3399
3399
|
|
|
3400
|
-
const
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
|
|
3400
|
+
const PROVIDER_LABELS = {
|
|
3401
|
+
'claude-yunyi': '云翼 Claude (包月)',
|
|
3402
|
+
'yunyi': '云翼 Codex (包月)',
|
|
3403
|
+
'heibai': 'MAXAPI (按量)',
|
|
3404
|
+
};
|
|
3405
|
+
|
|
3406
|
+
const claudeProviderName = API_CONFIG.claude.providerName;
|
|
3407
|
+
const codexProviderName = API_CONFIG.codex.providerName;
|
|
3404
3408
|
|
|
3405
|
-
//
|
|
3409
|
+
// 预设模型列表
|
|
3406
3410
|
const choices = [];
|
|
3407
|
-
const
|
|
3411
|
+
const presetKeys = new Set();
|
|
3408
3412
|
|
|
3409
3413
|
if (CLAUDE_MODELS.length > 0) {
|
|
3410
3414
|
choices.push(new inquirer.Separator(' -- Claude --'));
|
|
3411
3415
|
for (const m of CLAUDE_MODELS) {
|
|
3412
|
-
const
|
|
3413
|
-
const modelKey = `${
|
|
3416
|
+
const pName = providers[claudeProviderName] ? claudeProviderName : Object.keys(providers)[0];
|
|
3417
|
+
const modelKey = `${pName}/${m.id}`;
|
|
3414
3418
|
const isCurrent = modelKey === primary;
|
|
3415
3419
|
choices.push({
|
|
3416
3420
|
name: isCurrent ? `${m.name} (当前)` : m.name,
|
|
3417
3421
|
value: modelKey,
|
|
3418
3422
|
});
|
|
3419
|
-
|
|
3423
|
+
presetKeys.add(modelKey);
|
|
3420
3424
|
}
|
|
3421
3425
|
}
|
|
3422
3426
|
|
|
3423
3427
|
if (CODEX_MODELS.length > 0) {
|
|
3424
3428
|
choices.push(new inquirer.Separator(' -- GPT --'));
|
|
3425
3429
|
for (const m of CODEX_MODELS) {
|
|
3426
|
-
const
|
|
3427
|
-
const modelKey = `${
|
|
3430
|
+
const pName = providers[codexProviderName] ? codexProviderName : Object.keys(providers)[0];
|
|
3431
|
+
const modelKey = `${pName}/${m.id}`;
|
|
3428
3432
|
const isCurrent = modelKey === primary;
|
|
3429
3433
|
choices.push({
|
|
3430
3434
|
name: isCurrent ? `${m.name} (当前)` : m.name,
|
|
3431
3435
|
value: modelKey,
|
|
3432
3436
|
});
|
|
3433
|
-
|
|
3437
|
+
presetKeys.add(modelKey);
|
|
3434
3438
|
}
|
|
3435
3439
|
}
|
|
3436
3440
|
|
|
3437
|
-
//
|
|
3441
|
+
// 收集用户配置中的其他模型(不在预设列表里的)
|
|
3442
|
+
const otherModels = [];
|
|
3438
3443
|
for (const [providerName, providerConfig] of Object.entries(providers)) {
|
|
3439
3444
|
for (const m of (providerConfig.models || [])) {
|
|
3440
3445
|
const modelKey = `${providerName}/${m.id}`;
|
|
3441
|
-
if (
|
|
3442
|
-
|
|
3443
|
-
|
|
3444
|
-
name: isCurrent ? `${m.name || m.id} (当前)` : (m.name || m.id),
|
|
3445
|
-
value: modelKey,
|
|
3446
|
-
});
|
|
3447
|
-
listedKeys.add(modelKey);
|
|
3446
|
+
if (!presetKeys.has(modelKey)) {
|
|
3447
|
+
otherModels.push({ modelKey, name: m.name || m.id, providerName });
|
|
3448
|
+
}
|
|
3448
3449
|
}
|
|
3449
3450
|
}
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
3451
|
+
const registeredKeys = Object.keys(config.agents?.defaults?.models || {});
|
|
3452
|
+
for (const modelKey of registeredKeys) {
|
|
3453
|
+
if (presetKeys.has(modelKey) || otherModels.some(o => o.modelKey === modelKey)) continue;
|
|
3454
|
+
const [pName, mId] = modelKey.split('/');
|
|
3455
|
+
if (!pName || !mId) continue;
|
|
3456
|
+
otherModels.push({ modelKey, name: `${PROVIDER_LABELS[pName] || pName} / ${mId}`, providerName: pName });
|
|
3454
3457
|
}
|
|
3455
3458
|
|
|
3459
|
+
// 当前主模型不在预设列表中时,标注在"其他"入口上
|
|
3460
|
+
const primaryInPreset = presetKeys.has(primary);
|
|
3461
|
+
const otherLabel = otherModels.length > 0
|
|
3462
|
+
? `切换其他模型 (${otherModels.length} 个)`
|
|
3463
|
+
: '切换其他模型';
|
|
3464
|
+
|
|
3465
|
+
choices.push(new inquirer.Separator(''));
|
|
3466
|
+
choices.push({
|
|
3467
|
+
name: !primaryInPreset && primary ? `${otherLabel} ← 当前在此` : otherLabel,
|
|
3468
|
+
value: '__other__',
|
|
3469
|
+
});
|
|
3470
|
+
|
|
3456
3471
|
const currentProvider = primary.split('/')[0] || '';
|
|
3457
3472
|
const currentProviderConfig = providers[currentProvider];
|
|
3458
3473
|
console.log(chalk.gray(`当前模型: ${primary || '未设置'}`));
|
|
@@ -3465,25 +3480,51 @@ async function switchModel(paths) {
|
|
|
3465
3480
|
type: 'list',
|
|
3466
3481
|
name: 'selected',
|
|
3467
3482
|
message: '选择模型:',
|
|
3468
|
-
default: primary,
|
|
3483
|
+
default: primaryInPreset ? primary : undefined,
|
|
3469
3484
|
pageSize: 15,
|
|
3470
3485
|
choices,
|
|
3471
3486
|
}]);
|
|
3472
3487
|
|
|
3473
|
-
|
|
3488
|
+
let finalSelected = selected;
|
|
3489
|
+
|
|
3490
|
+
if (selected === '__other__') {
|
|
3491
|
+
if (otherModels.length === 0) {
|
|
3492
|
+
console.log(chalk.gray('\n当前配置中没有其他模型,仅有预设模型可用'));
|
|
3493
|
+
return;
|
|
3494
|
+
}
|
|
3495
|
+
const otherChoices = otherModels.map(o => {
|
|
3496
|
+
const label = PROVIDER_LABELS[o.providerName] || o.providerName;
|
|
3497
|
+
const isCurrent = o.modelKey === primary;
|
|
3498
|
+
return {
|
|
3499
|
+
name: isCurrent ? `${o.name} [${label}] (当前)` : `${o.name} [${label}]`,
|
|
3500
|
+
value: o.modelKey,
|
|
3501
|
+
};
|
|
3502
|
+
});
|
|
3503
|
+
const { pickedOther } = await inquirer.prompt([{
|
|
3504
|
+
type: 'list',
|
|
3505
|
+
name: 'pickedOther',
|
|
3506
|
+
message: '选择其他模型:',
|
|
3507
|
+
default: !primaryInPreset ? primary : undefined,
|
|
3508
|
+
pageSize: 15,
|
|
3509
|
+
choices: otherChoices,
|
|
3510
|
+
}]);
|
|
3511
|
+
finalSelected = pickedOther;
|
|
3512
|
+
}
|
|
3513
|
+
|
|
3514
|
+
if (finalSelected === primary) {
|
|
3474
3515
|
console.log(chalk.gray('\n模型未变更'));
|
|
3475
3516
|
return;
|
|
3476
3517
|
}
|
|
3477
3518
|
|
|
3478
|
-
const
|
|
3479
|
-
const selectedModelId =
|
|
3480
|
-
config.agents.defaults.model.primary =
|
|
3481
|
-
if (!config.agents.defaults.models[
|
|
3482
|
-
config.agents.defaults.models[
|
|
3519
|
+
const selectedProviderKey = finalSelected.split('/')[0];
|
|
3520
|
+
const selectedModelId = finalSelected.split('/')[1];
|
|
3521
|
+
config.agents.defaults.model.primary = finalSelected;
|
|
3522
|
+
if (!config.agents.defaults.models[finalSelected]) {
|
|
3523
|
+
config.agents.defaults.models[finalSelected] = { alias: selectedProviderKey };
|
|
3483
3524
|
}
|
|
3484
3525
|
|
|
3485
|
-
// 同步更新 provider.models
|
|
3486
|
-
const providerConfig = providers[
|
|
3526
|
+
// 同步更新 provider.models
|
|
3527
|
+
const providerConfig = providers[selectedProviderKey];
|
|
3487
3528
|
if (providerConfig && selectedModelId) {
|
|
3488
3529
|
const existingModel = (providerConfig.models || []).find(m => m.id === selectedModelId);
|
|
3489
3530
|
if (!existingModel) {
|
|
@@ -3504,16 +3545,16 @@ async function switchModel(paths) {
|
|
|
3504
3545
|
}
|
|
3505
3546
|
}
|
|
3506
3547
|
|
|
3507
|
-
config.agents.defaults.model.fallbacks = (config.agents.defaults.model.fallbacks || []).filter(k => k !==
|
|
3508
|
-
if (primary && primary !==
|
|
3548
|
+
config.agents.defaults.model.fallbacks = (config.agents.defaults.model.fallbacks || []).filter(k => k !== finalSelected);
|
|
3549
|
+
if (primary && primary !== finalSelected && !config.agents.defaults.model.fallbacks.includes(primary)) {
|
|
3509
3550
|
config.agents.defaults.model.fallbacks.push(primary);
|
|
3510
3551
|
}
|
|
3511
3552
|
ensureGatewaySettings(config);
|
|
3512
3553
|
writeConfigWithSync(paths, config);
|
|
3513
3554
|
|
|
3514
|
-
const selectedProviderConfig = providers[
|
|
3515
|
-
const selectedLabel = PROVIDER_LABELS[
|
|
3516
|
-
console.log(chalk.green(`\n✅ 已切换到 ${
|
|
3555
|
+
const selectedProviderConfig = providers[selectedProviderKey];
|
|
3556
|
+
const selectedLabel = PROVIDER_LABELS[selectedProviderKey] || selectedProviderKey;
|
|
3557
|
+
console.log(chalk.green(`\n✅ 已切换到 ${finalSelected}`));
|
|
3517
3558
|
console.log(chalk.gray(` 来源: ${selectedLabel}`));
|
|
3518
3559
|
if (selectedProviderConfig) {
|
|
3519
3560
|
console.log(chalk.gray(` 节点: ${selectedProviderConfig.baseUrl}`));
|
|
@@ -3522,7 +3563,6 @@ async function switchModel(paths) {
|
|
|
3522
3563
|
const gwPort = config.gateway?.port || 18789;
|
|
3523
3564
|
const gwToken = config.gateway?.auth?.token;
|
|
3524
3565
|
|
|
3525
|
-
// 自动重启 Gateway 使切换立即生效
|
|
3526
3566
|
if (await isPortOpen(gwPort)) {
|
|
3527
3567
|
const gwSpinner = ora({ text: '重启 Gateway 使模型切换生效...', spinner: 'dots' }).start();
|
|
3528
3568
|
const ok = await restartGateway({ silent: true });
|
|
@@ -3794,14 +3834,14 @@ async function testConnection(paths, args = {}) {
|
|
|
3794
3834
|
let result = await testGatewayApi(gatewayPort, gatewayToken, primary);
|
|
3795
3835
|
const latency = Date.now() - startTime;
|
|
3796
3836
|
|
|
3797
|
-
// /v1/responses 返回 405 时,回退测试 /v1/chat/completions
|
|
3798
|
-
if (!result.success && result.reachable && result.status
|
|
3837
|
+
// /v1/responses 返回 404/405 时,回退测试 /v1/chat/completions
|
|
3838
|
+
if (!result.success && result.reachable && [404, 405].includes(result.status)) {
|
|
3799
3839
|
console.log(chalk.gray(' /v1/responses 不支持,回退测试 /v1/chat/completions...'));
|
|
3800
3840
|
result = await testGatewayApi(gatewayPort, gatewayToken, primary, '/v1/chat/completions');
|
|
3801
3841
|
}
|
|
3802
3842
|
|
|
3803
|
-
// CLI 对话已成功 + Gateway 可达(405)= Dashboard 通过 WebSocket 工作,视为通过
|
|
3804
|
-
if (!result.success && cliPassed && result.reachable && result.status
|
|
3843
|
+
// CLI 对话已成功 + Gateway 可达(404/405)= Dashboard 通过 WebSocket 工作,视为通过
|
|
3844
|
+
if (!result.success && cliPassed && result.reachable && [404, 405].includes(result.status)) {
|
|
3805
3845
|
console.log(chalk.green(`\n✅ Gateway 测试通过`));
|
|
3806
3846
|
console.log(chalk.cyan(` CLI 对话正常,Gateway 可达`));
|
|
3807
3847
|
console.log(chalk.gray(` 注: Gateway Dashboard 通过 WebSocket 通信,REST 端点返回 405 属正常现象`));
|
|
@@ -3836,8 +3876,8 @@ async function testConnection(paths, args = {}) {
|
|
|
3836
3876
|
console.log(chalk.gray(` 3) 若仍 401,检查是否存在多个配置目录(.openclaw 与 .clawdbot)`));
|
|
3837
3877
|
}
|
|
3838
3878
|
|
|
3839
|
-
if (cliPassed && /\
|
|
3840
|
-
console.log(chalk.yellow(`\n⚠️ 已定位:Gateway
|
|
3879
|
+
if (cliPassed && /\b(404|405)\b/.test(String(result.error || ''))) {
|
|
3880
|
+
console.log(chalk.yellow(`\n⚠️ 已定位:Gateway 可达,Web REST 端点返回 ${result.status || '404/405'}`));
|
|
3841
3881
|
console.log(chalk.gray(` CLI 对话正常,Web Dashboard 应可正常使用。`));
|
|
3842
3882
|
console.log(chalk.gray(` 如遇问题,尝试更新 Gateway: npm install -g openclaw@latest && openclaw gateway restart`));
|
|
3843
3883
|
}
|