yymaxapi 1.0.91 → 1.0.93

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 +115 -46
  2. package/package.json +1 -1
package/bin/yymaxapi.js CHANGED
@@ -822,7 +822,7 @@ function writeClaudeCodeSettings(baseUrl, apiKey, modelId = getDefaultClaudeMode
822
822
  try {
823
823
  const cleanUrl = baseUrl.replace(/\/+$/, '');
824
824
  execSync(
825
- `powershell -NoProfile -Command "[Environment]::SetEnvironmentVariable('ANTHROPIC_BASE_URL','${cleanUrl}','User'); [Environment]::SetEnvironmentVariable('ANTHROPIC_AUTH_TOKEN','${apiKey}','User'); [Environment]::SetEnvironmentVariable('ANTHROPIC_MODEL','${modelId}','User'); [Environment]::SetEnvironmentVariable('NODE_TLS_REJECT_UNAUTHORIZED','0','User')"`,
825
+ `powershell -NoProfile -Command "[Environment]::SetEnvironmentVariable('ANTHROPIC_BASE_URL','${cleanUrl}','User'); [Environment]::SetEnvironmentVariable('ANTHROPIC_AUTH_TOKEN','${apiKey}','User'); [Environment]::SetEnvironmentVariable('ANTHROPIC_MODEL','${modelId}','User')"`,
826
826
  { stdio: 'pipe' }
827
827
  );
828
828
  } catch { /* best-effort */ }
@@ -830,13 +830,12 @@ function writeClaudeCodeSettings(baseUrl, apiKey, modelId = getDefaultClaudeMode
830
830
  const marker = '# >>> yymaxapi claude >>>';
831
831
  const markerEnd = '# <<< yymaxapi claude <<<';
832
832
  const cleanUrl = baseUrl.replace(/\/+$/, '');
833
+ // 只持久化工具本身需要的 Claude 变量,TLS 放宽只能留在进程内临时使用。
833
834
  const block = [
834
835
  marker,
835
836
  `export ANTHROPIC_BASE_URL="${cleanUrl}"`,
836
837
  `export ANTHROPIC_AUTH_TOKEN="${apiKey}"`,
837
838
  `export ANTHROPIC_MODEL="${modelId}"`,
838
- '# 中转站证书校验放宽,避免 unknown certificate verification error',
839
- 'export NODE_TLS_REJECT_UNAUTHORIZED=0',
840
839
  markerEnd
841
840
  ].join('\n');
842
841
 
@@ -1479,6 +1478,22 @@ const YUNYI_PROVIDER_ALIASES = {
1479
1478
  codex: new Set(['yunyi', 'yunyi-codex', 'codex-yunyi', 'codex_yunyi'])
1480
1479
  };
1481
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
+
1482
1497
  function looksLikeApiKey(value) {
1483
1498
  const text = String(value || '').trim();
1484
1499
  if (!text || text.includes('/') || text.includes(' ')) return false;
@@ -1556,6 +1571,27 @@ function renameProviderReferencesInConfig(config, oldName, newName) {
1556
1571
  if (!oldName || !newName || oldName === newName) return false;
1557
1572
  let changed = false;
1558
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
+
1559
1595
  if (config?.agents?.defaults?.models) {
1560
1596
  for (const key of Object.keys(config.agents.defaults.models)) {
1561
1597
  if (!key.startsWith(`${oldName}/`)) continue;
@@ -1571,22 +1607,11 @@ function renameProviderReferencesInConfig(config, oldName, newName) {
1571
1607
  }
1572
1608
 
1573
1609
  if (config?.agents?.defaults?.model) {
1574
- const modelState = config.agents.defaults.model;
1575
- if (typeof modelState.primary === 'string' && modelState.primary.startsWith(`${oldName}/`)) {
1576
- modelState.primary = `${newName}/${modelState.primary.slice(oldName.length + 1)}`;
1577
- changed = true;
1578
- }
1579
- if (Array.isArray(modelState.fallbacks)) {
1580
- const nextFallbacks = modelState.fallbacks.map(modelKey => (
1581
- typeof modelKey === 'string' && modelKey.startsWith(`${oldName}/`)
1582
- ? `${newName}/${modelKey.slice(oldName.length + 1)}`
1583
- : modelKey
1584
- ));
1585
- if (JSON.stringify(nextFallbacks) !== JSON.stringify(modelState.fallbacks)) {
1586
- modelState.fallbacks = nextFallbacks;
1587
- changed = true;
1588
- }
1589
- }
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;
1590
1615
  }
1591
1616
 
1592
1617
  if (config?.auth?.profiles) {
@@ -1605,21 +1630,7 @@ function renameProviderReferencesInConfig(config, oldName, newName) {
1605
1630
  if (Array.isArray(config?.agents?.list)) {
1606
1631
  for (const agent of config.agents.list) {
1607
1632
  if (!agent || typeof agent !== 'object' || !agent.model || typeof agent.model !== 'object') continue;
1608
- if (typeof agent.model.primary === 'string' && agent.model.primary.startsWith(`${oldName}/`)) {
1609
- agent.model.primary = `${newName}/${agent.model.primary.slice(oldName.length + 1)}`;
1610
- changed = true;
1611
- }
1612
- if (Array.isArray(agent.model.fallbacks)) {
1613
- const nextFallbacks = agent.model.fallbacks.map(modelKey => (
1614
- typeof modelKey === 'string' && modelKey.startsWith(`${oldName}/`)
1615
- ? `${newName}/${modelKey.slice(oldName.length + 1)}`
1616
- : modelKey
1617
- ));
1618
- if (JSON.stringify(nextFallbacks) !== JSON.stringify(agent.model.fallbacks)) {
1619
- agent.model.fallbacks = nextFallbacks;
1620
- changed = true;
1621
- }
1622
- }
1633
+ if (renameModelSelection(agent.model)) changed = true;
1623
1634
  }
1624
1635
  }
1625
1636
 
@@ -1931,6 +1942,7 @@ const YYMAXAPI_OPENCLAW_GPT_PROVIDER = 'yunyi';
1931
1942
  const YYMAXAPI_OPENCLAW_MAIN_AGENT_ID = 'main';
1932
1943
  const YYMAXAPI_OPENCLAW_ALT_CLAUDE_AGENT_ID = 'yunyi-claude';
1933
1944
  const YYMAXAPI_OPENCLAW_GPT_AGENT_ID = 'yunyi-gpt';
1945
+ const YYMAXAPI_OPENCLAW_LEGACY_GPT_AGENT_IDS = ['gpt'];
1934
1946
  const YYMAXAPI_OPENCLAW_CLAUDE_PRIMARY = `${YYMAXAPI_OPENCLAW_CLAUDE_PROVIDER}/claude-sonnet-4-6`;
1935
1947
  const YYMAXAPI_OPENCLAW_CLAUDE_FALLBACK = `${YYMAXAPI_OPENCLAW_CLAUDE_PROVIDER}/claude-opus-4-6`;
1936
1948
  const YYMAXAPI_OPENCLAW_GPT_PRIMARY = `${YYMAXAPI_OPENCLAW_GPT_PROVIDER}/gpt-5.4`;
@@ -2395,6 +2407,25 @@ function removeManagedAgent(agentList, agentId, shouldManage) {
2395
2407
  return true;
2396
2408
  }
2397
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
+
2398
2429
  function shouldManageYunyiDefaults(config) {
2399
2430
  const modelState = config?.agents?.defaults?.model || {};
2400
2431
  const primary = typeof modelState.primary === 'string' ? modelState.primary.trim() : '';
@@ -2437,6 +2468,35 @@ function normalizeManagedYunyiImageModel(modelState = {}, options = {}) {
2437
2468
  return { primary, fallbacks };
2438
2469
  }
2439
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
+
2440
2500
  function applyManagedYunyiOpenClawLayout(config, options = {}) {
2441
2501
  if (!isYymaxapiOpenClawBuild()) {
2442
2502
  return { changed: false, applied: false, claudeAgentId: null, preservedMain: false };
@@ -2530,6 +2590,10 @@ function applyManagedYunyiOpenClawLayout(config, options = {}) {
2530
2590
  model: normalizeManagedYunyiModelState('codex', currentGptAgentState, options)
2531
2591
  }, isManagedGptAgent);
2532
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
+ }
2533
2597
 
2534
2598
  if (shouldManageYunyiDefaults(config)) {
2535
2599
  const nextDefaultsModel = normalizeManagedYunyiDefaultsModel(config.agents.defaults.model, options);
@@ -2548,6 +2612,10 @@ function applyManagedYunyiOpenClawLayout(config, options = {}) {
2548
2612
  }
2549
2613
  }
2550
2614
 
2615
+ if (pruneLegacyYunyiAliasesInConfig(config)) {
2616
+ changed = true;
2617
+ }
2618
+
2551
2619
  return { changed, applied: true, claudeAgentId, preservedMain };
2552
2620
  }
2553
2621
 
@@ -3410,10 +3478,7 @@ function autoFixConfig(paths) {
3410
3478
 
3411
3479
  if (changed) {
3412
3480
  writeConfigWithSync(paths, config);
3413
- const managedClaudeKey = String(config.models.providers?.[YYMAXAPI_OPENCLAW_CLAUDE_PROVIDER]?.apiKey || '').trim();
3414
- const managedGptKey = String(config.models.providers?.[YYMAXAPI_OPENCLAW_GPT_PROVIDER]?.apiKey || '').trim();
3415
- if (managedClaudeKey) updateAuthProfilesWithSync(paths, YYMAXAPI_OPENCLAW_CLAUDE_PROVIDER, managedClaudeKey);
3416
- if (managedGptKey) updateAuthProfilesWithSync(paths, YYMAXAPI_OPENCLAW_GPT_PROVIDER, managedGptKey);
3481
+ syncManagedYunyiAuthProfiles(paths, config);
3417
3482
  console.log(chalk.green('✓ 已自动修复配置(Yunyi providers / agents / API 协议)'));
3418
3483
  }
3419
3484
  } catch { /* ignore */ }
@@ -4127,8 +4192,7 @@ async function presetClaude(paths, args = {}) {
4127
4192
  writeConfigWithSync(paths, config);
4128
4193
  updateAuthProfilesWithSync(paths, providerName, apiKey);
4129
4194
  if (yunyiLayoutResult.applied) {
4130
- updateAuthProfilesWithSync(paths, YYMAXAPI_OPENCLAW_CLAUDE_PROVIDER, apiKey);
4131
- updateAuthProfilesWithSync(paths, YYMAXAPI_OPENCLAW_GPT_PROVIDER, apiKey);
4195
+ syncManagedYunyiAuthProfiles(paths, config);
4132
4196
  }
4133
4197
  syncExternalTools('claude', baseUrl, apiKey, { claudeModelId: modelId, opencodeDefaultModelKey: `yunyi-claude/${modelId}` });
4134
4198
  writeSpinner.succeed('配置写入完成');
@@ -4310,8 +4374,7 @@ async function presetCodex(paths, args = {}) {
4310
4374
  writeConfigWithSync(paths, config);
4311
4375
  updateAuthProfilesWithSync(paths, providerName, apiKey);
4312
4376
  if (yunyiLayoutResult.applied) {
4313
- updateAuthProfilesWithSync(paths, YYMAXAPI_OPENCLAW_CLAUDE_PROVIDER, apiKey);
4314
- updateAuthProfilesWithSync(paths, YYMAXAPI_OPENCLAW_GPT_PROVIDER, apiKey);
4377
+ syncManagedYunyiAuthProfiles(paths, config);
4315
4378
  }
4316
4379
  syncExternalTools('codex', baseUrl, apiKey, { modelId });
4317
4380
  writeSpinner2.succeed('配置写入完成');
@@ -4504,6 +4567,9 @@ async function autoActivate(paths, args = {}) {
4504
4567
  writeConfigWithSync(paths, config);
4505
4568
  updateAuthProfilesWithSync(paths, claudeProviderName, apiKey);
4506
4569
  updateAuthProfilesWithSync(paths, codexProviderName, apiKey);
4570
+ if (yunyiLayoutResult.applied) {
4571
+ syncManagedYunyiAuthProfiles(paths, config);
4572
+ }
4507
4573
  const opencodeDefaultModelKey = isClaudePrimary ? `yunyi-claude/${claudeModelId}` : `yunyi-codex/${codexModelId}`;
4508
4574
  try { syncExternalTools('claude', claudeBaseUrl, apiKey, { codexBaseUrl, claudeModelId, opencodeDefaultModelKey }); } catch { /* ignore */ }
4509
4575
  try { syncExternalTools('codex', codexBaseUrl, apiKey, { modelId: codexModelId }); } catch { /* ignore */ }
@@ -4951,6 +5017,9 @@ async function yycodeQuickSetup(paths) {
4951
5017
  writeConfigWithSync(paths, config);
4952
5018
  updateAuthProfilesWithSync(paths, claudeProviderName, apiKey);
4953
5019
  updateAuthProfilesWithSync(paths, codexProviderName, apiKey);
5020
+ if (yunyiLayoutResult.applied) {
5021
+ syncManagedYunyiAuthProfiles(paths, config);
5022
+ }
4954
5023
  try { syncExternalTools('claude', claudeBaseUrl, apiKey, { codexBaseUrl, claudeModelId, opencodeDefaultModelKey: `yunyi-codex/${codexModelId}` }); } catch { /* ignore */ }
4955
5024
  try { syncExternalTools('codex', codexBaseUrl, apiKey, { modelId: codexModelId }); } catch { /* ignore */ }
4956
5025
  writeSpinner.succeed('配置写入完成');
@@ -5229,10 +5298,7 @@ async function selectNode(paths, type) {
5229
5298
 
5230
5299
  ensureGatewaySettings(config);
5231
5300
  writeConfigWithSync(paths, config);
5232
- const managedClaudeKey = String(config.models.providers?.[YYMAXAPI_OPENCLAW_CLAUDE_PROVIDER]?.apiKey || '').trim();
5233
- const managedGptKey = String(config.models.providers?.[YYMAXAPI_OPENCLAW_GPT_PROVIDER]?.apiKey || '').trim();
5234
- if (managedClaudeKey) updateAuthProfilesWithSync(paths, YYMAXAPI_OPENCLAW_CLAUDE_PROVIDER, managedClaudeKey);
5235
- if (managedGptKey) updateAuthProfilesWithSync(paths, YYMAXAPI_OPENCLAW_GPT_PROVIDER, managedGptKey);
5301
+ syncManagedYunyiAuthProfiles(paths, config);
5236
5302
 
5237
5303
  console.log(chalk.green(`\n✅ ${typeLabel} 节点配置完成!`));
5238
5304
  console.log(chalk.cyan(` ${typeLabel}: ${modelConfig.name}`));
@@ -5288,6 +5354,9 @@ async function activate(paths, type) {
5288
5354
  authStore.profiles[`${YYMAXAPI_OPENCLAW_GPT_PROVIDER}:default`] = { type: 'api_key', key: apiKey.trim(), provider: YYMAXAPI_OPENCLAW_GPT_PROVIDER };
5289
5355
  }
5290
5356
  writeAuthStore(paths.authProfiles, authStore);
5357
+ if (yunyiLayoutResult.applied) {
5358
+ pruneLegacyYunyiAuthProfilesWithSync(paths);
5359
+ }
5291
5360
 
5292
5361
  console.log(chalk.green(`\n✅ 已激活 ${typeLabel}`));
5293
5362
  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.91",
3
+ "version": "1.0.93",
4
4
  "description": "跨平台 OpenClaw/Clawdbot 配置管理工具 - 管理中转地址、模型切换、API Keys、测速优化",
5
5
  "main": "bin/yymaxapi.js",
6
6
  "bin": {