yymaxapi 1.0.92 → 1.0.94

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.
Files changed (2) hide show
  1. package/bin/yymaxapi.js +114 -43
  2. package/package.json +1 -1
package/bin/yymaxapi.js CHANGED
@@ -1478,6 +1478,22 @@ const YUNYI_PROVIDER_ALIASES = {
1478
1478
  codex: new Set(['yunyi', 'yunyi-codex', 'codex-yunyi', 'codex_yunyi'])
1479
1479
  };
1480
1480
 
1481
+ function getCanonicalYunyiProviderName(type) {
1482
+ return String(API_CONFIG?.[type]?.providerName || (type === 'claude' ? 'yunyi-claude' : 'yunyi')).trim();
1483
+ }
1484
+
1485
+ function getLegacyYunyiProviderAliases(type = '') {
1486
+ const types = type ? [type] : ['claude', 'codex'];
1487
+ const aliases = [];
1488
+ for (const currentType of types) {
1489
+ const canonical = getCanonicalYunyiProviderName(currentType);
1490
+ for (const alias of YUNYI_PROVIDER_ALIASES[currentType] || []) {
1491
+ if (alias && alias !== canonical) aliases.push(alias);
1492
+ }
1493
+ }
1494
+ return [...new Set(aliases)];
1495
+ }
1496
+
1481
1497
  function looksLikeApiKey(value) {
1482
1498
  const text = String(value || '').trim();
1483
1499
  if (!text || text.includes('/') || text.includes(' ')) return false;
@@ -1555,6 +1571,27 @@ function renameProviderReferencesInConfig(config, oldName, newName) {
1555
1571
  if (!oldName || !newName || oldName === newName) return false;
1556
1572
  let changed = false;
1557
1573
 
1574
+ const renameModelSelection = (modelState) => {
1575
+ if (!modelState || typeof modelState !== 'object') return false;
1576
+ let localChanged = false;
1577
+ if (typeof modelState.primary === 'string' && modelState.primary.startsWith(`${oldName}/`)) {
1578
+ modelState.primary = `${newName}/${modelState.primary.slice(oldName.length + 1)}`;
1579
+ localChanged = true;
1580
+ }
1581
+ if (Array.isArray(modelState.fallbacks)) {
1582
+ const nextFallbacks = modelState.fallbacks.map(modelKey => (
1583
+ typeof modelKey === 'string' && modelKey.startsWith(`${oldName}/`)
1584
+ ? `${newName}/${modelKey.slice(oldName.length + 1)}`
1585
+ : modelKey
1586
+ ));
1587
+ if (JSON.stringify(nextFallbacks) !== JSON.stringify(modelState.fallbacks)) {
1588
+ modelState.fallbacks = nextFallbacks;
1589
+ localChanged = true;
1590
+ }
1591
+ }
1592
+ return localChanged;
1593
+ };
1594
+
1558
1595
  if (config?.agents?.defaults?.models) {
1559
1596
  for (const key of Object.keys(config.agents.defaults.models)) {
1560
1597
  if (!key.startsWith(`${oldName}/`)) continue;
@@ -1570,22 +1607,11 @@ function renameProviderReferencesInConfig(config, oldName, newName) {
1570
1607
  }
1571
1608
 
1572
1609
  if (config?.agents?.defaults?.model) {
1573
- const modelState = config.agents.defaults.model;
1574
- if (typeof modelState.primary === 'string' && modelState.primary.startsWith(`${oldName}/`)) {
1575
- modelState.primary = `${newName}/${modelState.primary.slice(oldName.length + 1)}`;
1576
- changed = true;
1577
- }
1578
- if (Array.isArray(modelState.fallbacks)) {
1579
- const nextFallbacks = modelState.fallbacks.map(modelKey => (
1580
- typeof modelKey === 'string' && modelKey.startsWith(`${oldName}/`)
1581
- ? `${newName}/${modelKey.slice(oldName.length + 1)}`
1582
- : modelKey
1583
- ));
1584
- if (JSON.stringify(nextFallbacks) !== JSON.stringify(modelState.fallbacks)) {
1585
- modelState.fallbacks = nextFallbacks;
1586
- changed = true;
1587
- }
1588
- }
1610
+ if (renameModelSelection(config.agents.defaults.model)) changed = true;
1611
+ }
1612
+
1613
+ if (config?.agents?.defaults?.imageModel) {
1614
+ if (renameModelSelection(config.agents.defaults.imageModel)) changed = true;
1589
1615
  }
1590
1616
 
1591
1617
  if (config?.auth?.profiles) {
@@ -1604,21 +1630,7 @@ function renameProviderReferencesInConfig(config, oldName, newName) {
1604
1630
  if (Array.isArray(config?.agents?.list)) {
1605
1631
  for (const agent of config.agents.list) {
1606
1632
  if (!agent || typeof agent !== 'object' || !agent.model || typeof agent.model !== 'object') continue;
1607
- if (typeof agent.model.primary === 'string' && agent.model.primary.startsWith(`${oldName}/`)) {
1608
- agent.model.primary = `${newName}/${agent.model.primary.slice(oldName.length + 1)}`;
1609
- changed = true;
1610
- }
1611
- if (Array.isArray(agent.model.fallbacks)) {
1612
- const nextFallbacks = agent.model.fallbacks.map(modelKey => (
1613
- typeof modelKey === 'string' && modelKey.startsWith(`${oldName}/`)
1614
- ? `${newName}/${modelKey.slice(oldName.length + 1)}`
1615
- : modelKey
1616
- ));
1617
- if (JSON.stringify(nextFallbacks) !== JSON.stringify(agent.model.fallbacks)) {
1618
- agent.model.fallbacks = nextFallbacks;
1619
- changed = true;
1620
- }
1621
- }
1633
+ if (renameModelSelection(agent.model)) changed = true;
1622
1634
  }
1623
1635
  }
1624
1636
 
@@ -1930,6 +1942,7 @@ const YYMAXAPI_OPENCLAW_GPT_PROVIDER = 'yunyi';
1930
1942
  const YYMAXAPI_OPENCLAW_MAIN_AGENT_ID = 'main';
1931
1943
  const YYMAXAPI_OPENCLAW_ALT_CLAUDE_AGENT_ID = 'yunyi-claude';
1932
1944
  const YYMAXAPI_OPENCLAW_GPT_AGENT_ID = 'yunyi-gpt';
1945
+ const YYMAXAPI_OPENCLAW_LEGACY_GPT_AGENT_IDS = ['gpt'];
1933
1946
  const YYMAXAPI_OPENCLAW_CLAUDE_PRIMARY = `${YYMAXAPI_OPENCLAW_CLAUDE_PROVIDER}/claude-sonnet-4-6`;
1934
1947
  const YYMAXAPI_OPENCLAW_CLAUDE_FALLBACK = `${YYMAXAPI_OPENCLAW_CLAUDE_PROVIDER}/claude-opus-4-6`;
1935
1948
  const YYMAXAPI_OPENCLAW_GPT_PRIMARY = `${YYMAXAPI_OPENCLAW_GPT_PROVIDER}/gpt-5.4`;
@@ -2394,6 +2407,25 @@ function removeManagedAgent(agentList, agentId, shouldManage) {
2394
2407
  return true;
2395
2408
  }
2396
2409
 
2410
+ function pruneLegacyYunyiAliasesInConfig(config) {
2411
+ if (!config || typeof config !== 'object') return false;
2412
+ let changed = false;
2413
+ const providers = config?.models?.providers || {};
2414
+
2415
+ for (const type of ['claude', 'codex']) {
2416
+ const canonical = type === 'claude' ? YYMAXAPI_OPENCLAW_CLAUDE_PROVIDER : YYMAXAPI_OPENCLAW_GPT_PROVIDER;
2417
+ for (const alias of getLegacyYunyiProviderAliases(type)) {
2418
+ if (renameProviderReferencesInConfig(config, alias, canonical)) changed = true;
2419
+ if (providers[alias]) {
2420
+ delete providers[alias];
2421
+ changed = true;
2422
+ }
2423
+ }
2424
+ }
2425
+
2426
+ return changed;
2427
+ }
2428
+
2397
2429
  function shouldManageYunyiDefaults(config) {
2398
2430
  const modelState = config?.agents?.defaults?.model || {};
2399
2431
  const primary = typeof modelState.primary === 'string' ? modelState.primary.trim() : '';
@@ -2436,6 +2468,35 @@ function normalizeManagedYunyiImageModel(modelState = {}, options = {}) {
2436
2468
  return { primary, fallbacks };
2437
2469
  }
2438
2470
 
2471
+ function pruneLegacyYunyiAuthProfilesWithSync(paths) {
2472
+ if (!paths?.authProfiles) return [];
2473
+ const legacyProviders = new Set(getLegacyYunyiProviderAliases());
2474
+ const store = readAuthStore(paths.authProfiles);
2475
+ const removed = [];
2476
+
2477
+ for (const key of Object.keys(store.profiles || {})) {
2478
+ const provider = key.split(':')[0];
2479
+ if (!legacyProviders.has(provider)) continue;
2480
+ delete store.profiles[key];
2481
+ removed.push(provider);
2482
+ }
2483
+
2484
+ if (removed.length > 0) {
2485
+ writeAuthStore(paths.authProfiles, store);
2486
+ syncMirroredAuthStores(paths);
2487
+ }
2488
+
2489
+ return [...new Set(removed)];
2490
+ }
2491
+
2492
+ function syncManagedYunyiAuthProfiles(paths, config) {
2493
+ const managedClaudeKey = String(config?.models?.providers?.[YYMAXAPI_OPENCLAW_CLAUDE_PROVIDER]?.apiKey || '').trim();
2494
+ const managedGptKey = String(config?.models?.providers?.[YYMAXAPI_OPENCLAW_GPT_PROVIDER]?.apiKey || '').trim();
2495
+ if (managedClaudeKey) updateAuthProfilesWithSync(paths, YYMAXAPI_OPENCLAW_CLAUDE_PROVIDER, managedClaudeKey);
2496
+ if (managedGptKey) updateAuthProfilesWithSync(paths, YYMAXAPI_OPENCLAW_GPT_PROVIDER, managedGptKey);
2497
+ pruneLegacyYunyiAuthProfilesWithSync(paths);
2498
+ }
2499
+
2439
2500
  function applyManagedYunyiOpenClawLayout(config, options = {}) {
2440
2501
  if (!isYymaxapiOpenClawBuild()) {
2441
2502
  return { changed: false, applied: false, claudeAgentId: null, preservedMain: false };
@@ -2529,6 +2590,10 @@ function applyManagedYunyiOpenClawLayout(config, options = {}) {
2529
2590
  model: normalizeManagedYunyiModelState('codex', currentGptAgentState, options)
2530
2591
  }, isManagedGptAgent);
2531
2592
  if (gptAgentResult.changed) changed = true;
2593
+ for (const legacyAgentId of YYMAXAPI_OPENCLAW_LEGACY_GPT_AGENT_IDS) {
2594
+ if (legacyAgentId === YYMAXAPI_OPENCLAW_GPT_AGENT_ID) continue;
2595
+ if (removeManagedAgent(agentList, legacyAgentId, isManagedGptAgent)) changed = true;
2596
+ }
2532
2597
 
2533
2598
  if (shouldManageYunyiDefaults(config)) {
2534
2599
  const nextDefaultsModel = normalizeManagedYunyiDefaultsModel(config.agents.defaults.model, options);
@@ -2547,6 +2612,10 @@ function applyManagedYunyiOpenClawLayout(config, options = {}) {
2547
2612
  }
2548
2613
  }
2549
2614
 
2615
+ if (pruneLegacyYunyiAliasesInConfig(config)) {
2616
+ changed = true;
2617
+ }
2618
+
2550
2619
  return { changed, applied: true, claudeAgentId, preservedMain };
2551
2620
  }
2552
2621
 
@@ -3409,10 +3478,7 @@ function autoFixConfig(paths) {
3409
3478
 
3410
3479
  if (changed) {
3411
3480
  writeConfigWithSync(paths, config);
3412
- const managedClaudeKey = String(config.models.providers?.[YYMAXAPI_OPENCLAW_CLAUDE_PROVIDER]?.apiKey || '').trim();
3413
- const managedGptKey = String(config.models.providers?.[YYMAXAPI_OPENCLAW_GPT_PROVIDER]?.apiKey || '').trim();
3414
- if (managedClaudeKey) updateAuthProfilesWithSync(paths, YYMAXAPI_OPENCLAW_CLAUDE_PROVIDER, managedClaudeKey);
3415
- if (managedGptKey) updateAuthProfilesWithSync(paths, YYMAXAPI_OPENCLAW_GPT_PROVIDER, managedGptKey);
3481
+ syncManagedYunyiAuthProfiles(paths, config);
3416
3482
  console.log(chalk.green('✓ 已自动修复配置(Yunyi providers / agents / API 协议)'));
3417
3483
  }
3418
3484
  } catch { /* ignore */ }
@@ -4126,8 +4192,7 @@ async function presetClaude(paths, args = {}) {
4126
4192
  writeConfigWithSync(paths, config);
4127
4193
  updateAuthProfilesWithSync(paths, providerName, apiKey);
4128
4194
  if (yunyiLayoutResult.applied) {
4129
- updateAuthProfilesWithSync(paths, YYMAXAPI_OPENCLAW_CLAUDE_PROVIDER, apiKey);
4130
- updateAuthProfilesWithSync(paths, YYMAXAPI_OPENCLAW_GPT_PROVIDER, apiKey);
4195
+ syncManagedYunyiAuthProfiles(paths, config);
4131
4196
  }
4132
4197
  syncExternalTools('claude', baseUrl, apiKey, { claudeModelId: modelId, opencodeDefaultModelKey: `yunyi-claude/${modelId}` });
4133
4198
  writeSpinner.succeed('配置写入完成');
@@ -4309,8 +4374,7 @@ async function presetCodex(paths, args = {}) {
4309
4374
  writeConfigWithSync(paths, config);
4310
4375
  updateAuthProfilesWithSync(paths, providerName, apiKey);
4311
4376
  if (yunyiLayoutResult.applied) {
4312
- updateAuthProfilesWithSync(paths, YYMAXAPI_OPENCLAW_CLAUDE_PROVIDER, apiKey);
4313
- updateAuthProfilesWithSync(paths, YYMAXAPI_OPENCLAW_GPT_PROVIDER, apiKey);
4377
+ syncManagedYunyiAuthProfiles(paths, config);
4314
4378
  }
4315
4379
  syncExternalTools('codex', baseUrl, apiKey, { modelId });
4316
4380
  writeSpinner2.succeed('配置写入完成');
@@ -4494,6 +4558,7 @@ async function autoActivate(paths, args = {}) {
4494
4558
  endpointUrl: selectedEndpoint.url,
4495
4559
  apiKey
4496
4560
  });
4561
+ applyManagedYunyiModelSelection(config, primaryModelKey);
4497
4562
 
4498
4563
  // ---- 写入配置 ----
4499
4564
  const writeSpinner = ora({ text: '正在写入配置...', spinner: 'dots' }).start();
@@ -4503,6 +4568,9 @@ async function autoActivate(paths, args = {}) {
4503
4568
  writeConfigWithSync(paths, config);
4504
4569
  updateAuthProfilesWithSync(paths, claudeProviderName, apiKey);
4505
4570
  updateAuthProfilesWithSync(paths, codexProviderName, apiKey);
4571
+ if (yunyiLayoutResult.applied) {
4572
+ syncManagedYunyiAuthProfiles(paths, config);
4573
+ }
4506
4574
  const opencodeDefaultModelKey = isClaudePrimary ? `yunyi-claude/${claudeModelId}` : `yunyi-codex/${codexModelId}`;
4507
4575
  try { syncExternalTools('claude', claudeBaseUrl, apiKey, { codexBaseUrl, claudeModelId, opencodeDefaultModelKey }); } catch { /* ignore */ }
4508
4576
  try { syncExternalTools('codex', codexBaseUrl, apiKey, { modelId: codexModelId }); } catch { /* ignore */ }
@@ -4950,6 +5018,9 @@ async function yycodeQuickSetup(paths) {
4950
5018
  writeConfigWithSync(paths, config);
4951
5019
  updateAuthProfilesWithSync(paths, claudeProviderName, apiKey);
4952
5020
  updateAuthProfilesWithSync(paths, codexProviderName, apiKey);
5021
+ if (yunyiLayoutResult.applied) {
5022
+ syncManagedYunyiAuthProfiles(paths, config);
5023
+ }
4953
5024
  try { syncExternalTools('claude', claudeBaseUrl, apiKey, { codexBaseUrl, claudeModelId, opencodeDefaultModelKey: `yunyi-codex/${codexModelId}` }); } catch { /* ignore */ }
4954
5025
  try { syncExternalTools('codex', codexBaseUrl, apiKey, { modelId: codexModelId }); } catch { /* ignore */ }
4955
5026
  writeSpinner.succeed('配置写入完成');
@@ -5228,10 +5299,7 @@ async function selectNode(paths, type) {
5228
5299
 
5229
5300
  ensureGatewaySettings(config);
5230
5301
  writeConfigWithSync(paths, config);
5231
- const managedClaudeKey = String(config.models.providers?.[YYMAXAPI_OPENCLAW_CLAUDE_PROVIDER]?.apiKey || '').trim();
5232
- const managedGptKey = String(config.models.providers?.[YYMAXAPI_OPENCLAW_GPT_PROVIDER]?.apiKey || '').trim();
5233
- if (managedClaudeKey) updateAuthProfilesWithSync(paths, YYMAXAPI_OPENCLAW_CLAUDE_PROVIDER, managedClaudeKey);
5234
- if (managedGptKey) updateAuthProfilesWithSync(paths, YYMAXAPI_OPENCLAW_GPT_PROVIDER, managedGptKey);
5302
+ syncManagedYunyiAuthProfiles(paths, config);
5235
5303
 
5236
5304
  console.log(chalk.green(`\n✅ ${typeLabel} 节点配置完成!`));
5237
5305
  console.log(chalk.cyan(` ${typeLabel}: ${modelConfig.name}`));
@@ -5287,6 +5355,9 @@ async function activate(paths, type) {
5287
5355
  authStore.profiles[`${YYMAXAPI_OPENCLAW_GPT_PROVIDER}:default`] = { type: 'api_key', key: apiKey.trim(), provider: YYMAXAPI_OPENCLAW_GPT_PROVIDER };
5288
5356
  }
5289
5357
  writeAuthStore(paths.authProfiles, authStore);
5358
+ if (yunyiLayoutResult.applied) {
5359
+ pruneLegacyYunyiAuthProfilesWithSync(paths);
5360
+ }
5290
5361
 
5291
5362
  console.log(chalk.green(`\n✅ 已激活 ${typeLabel}`));
5292
5363
  console.log(chalk.cyan(` ${typeLabel}: ${modelConfig.name}`));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yymaxapi",
3
- "version": "1.0.92",
3
+ "version": "1.0.94",
4
4
  "description": "跨平台 OpenClaw/Clawdbot 配置管理工具 - 管理中转地址、模型切换、API Keys、测速优化",
5
5
  "main": "bin/yymaxapi.js",
6
6
  "bin": {