yymaxapi 1.0.87 → 1.0.89

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 +223 -84
  2. package/package.json +1 -1
package/bin/yymaxapi.js CHANGED
@@ -56,6 +56,20 @@ function safeExec(cmd, options = {}) {
56
56
  }
57
57
  }
58
58
 
59
+ function shouldSuppressProcessWarning(warning) {
60
+ const message = typeof warning === 'string' ? warning : String(warning?.message || '');
61
+ return message.includes("Setting the NODE_TLS_REJECT_UNAUTHORIZED environment variable to '0'");
62
+ }
63
+
64
+ if (!process.__yymaxapiWarningFilterInstalled && typeof process.emitWarning === 'function') {
65
+ const originalEmitWarning = process.emitWarning.bind(process);
66
+ process.emitWarning = function patchedEmitWarning(warning, ...args) {
67
+ if (shouldSuppressProcessWarning(warning)) return;
68
+ return originalEmitWarning(warning, ...args);
69
+ };
70
+ process.__yymaxapiWarningFilterInstalled = true;
71
+ }
72
+
59
73
  // ============ 预设 (由 build.js 从 provider config 生成) ============
60
74
  const DEFAULT_ENDPOINTS = [
61
75
  {
@@ -493,41 +507,8 @@ async function validateApiKey(nodeUrl, apiKey) {
493
507
  try {
494
508
  const res = await httpGetJson(verifyUrl, { Authorization: `Bearer ${apiKey}` });
495
509
  if (res.status === 200 && res.data) {
496
- spinner.succeed('API Key 验证成功');
497
- const d = res.data;
498
- // 基本信息
499
- if (d.service_type) console.log(chalk.gray(` 服务类型: ${d.service_type}`));
500
- if (d.billing_mode) console.log(chalk.gray(` 计费模式: ${d.billing_mode}`));
501
- if (d.status && d.status !== 'active') console.log(chalk.yellow(` ⚠ 状态: ${d.status}`));
502
- // 配额信息
503
- if (d.total_quota !== undefined || d.remaining_quota !== undefined) {
504
- const total = d.total_quota || 0;
505
- const remaining = d.remaining_quota !== undefined ? d.remaining_quota : total;
506
- const used = total - remaining;
507
- const pct = total > 0 ? Math.round((used / total) * 100) : 0;
508
- const barLen = 20;
509
- const filled = Math.round(barLen * pct / 100);
510
- const bar = chalk.green('█'.repeat(filled)) + chalk.gray('░'.repeat(barLen - filled));
511
- console.log(chalk.gray(` 总配额: ${total}`) + (d.max_requests ? chalk.gray(` | 最大请求: ${d.max_requests}`) : ''));
512
- console.log(chalk.gray(` 已用/剩余: ${used} / ${remaining}`));
513
- console.log(` [${bar}] ${pct}%`);
514
- }
515
- // 每日配额
516
- if (d.daily_quota !== undefined || d.daily_remaining !== undefined) {
517
- const dTotal = d.daily_quota || 0;
518
- const dRemain = d.daily_remaining !== undefined ? d.daily_remaining : dTotal;
519
- const dUsed = d.daily_used !== undefined ? d.daily_used : (dTotal - dRemain);
520
- console.log(chalk.gray(` 今日配额: ${dTotal} | 已用: ${dUsed} | 剩余: ${dRemain}`));
521
- }
522
- // 有效期
523
- if (d.activated_at) console.log(chalk.gray(` 激活时间: ${new Date(d.activated_at).toLocaleDateString()}`));
524
- if (d.expires_at) {
525
- const exp = new Date(d.expires_at);
526
- const daysLeft = Math.ceil((exp - Date.now()) / 86400000);
527
- const expColor = daysLeft <= 7 ? chalk.red : daysLeft <= 30 ? chalk.yellow : chalk.gray;
528
- console.log(expColor(` 有效期至: ${exp.toLocaleDateString()} (${daysLeft > 0 ? `剩余 ${daysLeft} 天` : '已过期'})`));
529
- }
530
- return { valid: true, data: d };
510
+ spinner.succeed('API Key 可用');
511
+ return { valid: true, data: res.data };
531
512
  } else {
532
513
  spinner.fail('API Key 验证失败');
533
514
  console.log(chalk.red(` HTTP ${res.status}`));
@@ -2030,6 +2011,150 @@ function findAgentById(config, agentId) {
2030
2011
  return config.agents.list.find(agent => agent && typeof agent === 'object' && agent.id === agentId) || null;
2031
2012
  }
2032
2013
 
2014
+ function canonicalizeManagedYunyiModelKey(modelKey, preferredType = '') {
2015
+ const text = String(modelKey || '').trim();
2016
+ if (!text.includes('/')) return text;
2017
+ const [, modelId = ''] = text.split('/');
2018
+ if (!modelId) return text;
2019
+ if (preferredType === 'claude' || (!preferredType && isManagedYunyiClaudeModelKey(text))) {
2020
+ return `${YYMAXAPI_OPENCLAW_CLAUDE_PROVIDER}/${modelId}`;
2021
+ }
2022
+ if (preferredType === 'codex' || preferredType === 'gpt' || (!preferredType && isManagedYunyiGptModelKey(text))) {
2023
+ return `${YYMAXAPI_OPENCLAW_GPT_PROVIDER}/${modelId}`;
2024
+ }
2025
+ return text;
2026
+ }
2027
+
2028
+ function getManagedYunyiKnownModelKeys(type) {
2029
+ return type === 'claude'
2030
+ ? [YYMAXAPI_OPENCLAW_CLAUDE_PRIMARY, YYMAXAPI_OPENCLAW_CLAUDE_FALLBACK]
2031
+ : [YYMAXAPI_OPENCLAW_GPT_PRIMARY, YYMAXAPI_OPENCLAW_GPT_FALLBACK];
2032
+ }
2033
+
2034
+ function normalizeManagedYunyiModelState(type, modelState = {}, options = {}) {
2035
+ const knownKeys = getManagedYunyiKnownModelKeys(type);
2036
+ const fallbackPrimary = knownKeys[0];
2037
+ const currentPrimary = canonicalizeManagedYunyiModelKey(modelState.primary || '', type);
2038
+ const canPreserve = !options.force && currentPrimary && knownKeys.includes(currentPrimary);
2039
+ const primary = canPreserve ? currentPrimary : fallbackPrimary;
2040
+
2041
+ let fallbacks = Array.isArray(modelState.fallbacks) ? modelState.fallbacks : [];
2042
+ fallbacks = [...new Set(
2043
+ fallbacks
2044
+ .map(item => canonicalizeManagedYunyiModelKey(item, type))
2045
+ .filter(item => item && item !== primary && knownKeys.includes(item))
2046
+ )];
2047
+
2048
+ if (fallbacks.length === 0) {
2049
+ fallbacks = knownKeys.filter(item => item !== primary);
2050
+ }
2051
+
2052
+ return { primary, fallbacks };
2053
+ }
2054
+
2055
+ function normalizeManagedYunyiDefaultsModel(modelState = {}, options = {}) {
2056
+ const currentPrimary = String(modelState.primary || '').trim();
2057
+ const canPreserve = !options.force && currentPrimary && isManagedYunyiModelKey(currentPrimary);
2058
+ const primary = canPreserve
2059
+ ? canonicalizeManagedYunyiModelKey(currentPrimary)
2060
+ : YYMAXAPI_OPENCLAW_CLAUDE_PRIMARY;
2061
+
2062
+ let fallbacks = Array.isArray(modelState.fallbacks) ? modelState.fallbacks : [];
2063
+ fallbacks = [...new Set(
2064
+ fallbacks
2065
+ .map(item => {
2066
+ const text = String(item || '').trim();
2067
+ return isManagedYunyiModelKey(text) ? canonicalizeManagedYunyiModelKey(text) : text;
2068
+ })
2069
+ .filter(item => item && item !== primary)
2070
+ )];
2071
+
2072
+ if (fallbacks.length === 0) {
2073
+ fallbacks = [isManagedYunyiClaudeModelKey(primary) ? YYMAXAPI_OPENCLAW_GPT_PRIMARY : YYMAXAPI_OPENCLAW_CLAUDE_PRIMARY];
2074
+ }
2075
+
2076
+ return { primary, fallbacks };
2077
+ }
2078
+
2079
+ function getManagedClaudeAgentId(config) {
2080
+ const mainAgent = findAgentById(config, YYMAXAPI_OPENCLAW_MAIN_AGENT_ID);
2081
+ if (mainAgent && isManagedMainAgent(mainAgent)) {
2082
+ return YYMAXAPI_OPENCLAW_MAIN_AGENT_ID;
2083
+ }
2084
+
2085
+ const sideAgent = findAgentById(config, YYMAXAPI_OPENCLAW_ALT_CLAUDE_AGENT_ID);
2086
+ if (sideAgent && isManagedClaudeSideAgent(sideAgent)) {
2087
+ return YYMAXAPI_OPENCLAW_ALT_CLAUDE_AGENT_ID;
2088
+ }
2089
+
2090
+ return mainAgent ? YYMAXAPI_OPENCLAW_MAIN_AGENT_ID : (sideAgent ? YYMAXAPI_OPENCLAW_ALT_CLAUDE_AGENT_ID : null);
2091
+ }
2092
+
2093
+ function inferManagedYunyiAgentIdForModelKey(config, modelKey) {
2094
+ if (isManagedYunyiGptModelKey(modelKey)) return YYMAXAPI_OPENCLAW_GPT_AGENT_ID;
2095
+ if (isManagedYunyiClaudeModelKey(modelKey)) return getManagedClaudeAgentId(config);
2096
+ return null;
2097
+ }
2098
+
2099
+ function applyManagedYunyiModelSelection(config, selectedModelKey) {
2100
+ ensureConfigStructure(config);
2101
+
2102
+ const normalizedSelected = canonicalizeManagedYunyiModelKey(selectedModelKey);
2103
+ const selectedType = isManagedYunyiClaudeModelKey(normalizedSelected)
2104
+ ? 'claude'
2105
+ : (isManagedYunyiGptModelKey(normalizedSelected) ? 'codex' : '');
2106
+
2107
+ if (!selectedType) {
2108
+ return { changed: false, selectedModelKey: normalizedSelected, agentId: null };
2109
+ }
2110
+
2111
+ let changed = false;
2112
+ const previousPrimary = String(config.agents?.defaults?.model?.primary || '').trim();
2113
+ const previousCanonical = isManagedYunyiModelKey(previousPrimary)
2114
+ ? canonicalizeManagedYunyiModelKey(previousPrimary)
2115
+ : previousPrimary;
2116
+ const nextDefaultsModel = {
2117
+ primary: normalizedSelected,
2118
+ fallbacks: previousCanonical && previousCanonical !== normalizedSelected ? [previousCanonical] : []
2119
+ };
2120
+
2121
+ if (JSON.stringify(config.agents.defaults.model) !== JSON.stringify(nextDefaultsModel)) {
2122
+ config.agents.defaults.model = nextDefaultsModel;
2123
+ changed = true;
2124
+ }
2125
+
2126
+ const managedModelAliases = {
2127
+ [YYMAXAPI_OPENCLAW_CLAUDE_PRIMARY]: YYMAXAPI_OPENCLAW_CLAUDE_PROVIDER,
2128
+ [YYMAXAPI_OPENCLAW_CLAUDE_FALLBACK]: YYMAXAPI_OPENCLAW_CLAUDE_PROVIDER,
2129
+ [YYMAXAPI_OPENCLAW_GPT_PRIMARY]: YYMAXAPI_OPENCLAW_GPT_PROVIDER,
2130
+ [YYMAXAPI_OPENCLAW_GPT_FALLBACK]: YYMAXAPI_OPENCLAW_GPT_PROVIDER
2131
+ };
2132
+ for (const [modelKey, alias] of Object.entries(managedModelAliases)) {
2133
+ const nextEntry = { alias };
2134
+ if (JSON.stringify(config.agents.defaults.models[modelKey] || {}) !== JSON.stringify(nextEntry)) {
2135
+ config.agents.defaults.models[modelKey] = nextEntry;
2136
+ changed = true;
2137
+ }
2138
+ }
2139
+
2140
+ const agentId = inferManagedYunyiAgentIdForModelKey(config, normalizedSelected)
2141
+ || (selectedType === 'codex' ? YYMAXAPI_OPENCLAW_GPT_AGENT_ID : YYMAXAPI_OPENCLAW_ALT_CLAUDE_AGENT_ID);
2142
+ const agentList = ensureAgentList(config);
2143
+ const nextAgent = {
2144
+ id: agentId,
2145
+ default: agentId === YYMAXAPI_OPENCLAW_MAIN_AGENT_ID,
2146
+ name: selectedType === 'codex' ? 'yunyi-gpt' : 'yunyi-claude',
2147
+ model: normalizeManagedYunyiModelState(selectedType, { primary: normalizedSelected })
2148
+ };
2149
+ const shouldManage = selectedType === 'codex'
2150
+ ? isManagedGptAgent
2151
+ : (agentId === YYMAXAPI_OPENCLAW_MAIN_AGENT_ID ? isManagedMainAgent : isManagedClaudeSideAgent);
2152
+ const updateResult = upsertManagedAgent(agentList, nextAgent, shouldManage);
2153
+ if (updateResult.changed) changed = true;
2154
+
2155
+ return { changed, selectedModelKey: normalizedSelected, agentId };
2156
+ }
2157
+
2033
2158
  function resolveOpenClawTestTarget(config, args = {}) {
2034
2159
  const requestedAgentId = String(args.agent || args['agent-id'] || '').trim();
2035
2160
  const requestedAgent = requestedAgentId ? findAgentById(config, requestedAgentId) : null;
@@ -2046,11 +2171,23 @@ function resolveOpenClawTestTarget(config, args = {}) {
2046
2171
  if (requestedAgent) {
2047
2172
  const agentState = getAgentModelState(requestedAgent);
2048
2173
  if (agentState.primary) {
2049
- primary = agentState.primary;
2174
+ primary = canonicalizeManagedYunyiModelKey(agentState.primary);
2050
2175
  fallbacks = agentState.fallbacks;
2051
2176
  agentId = requestedAgent.id;
2052
2177
  agentName = String(requestedAgent.name || '').trim();
2053
2178
  }
2179
+ } else {
2180
+ const inferredAgentId = inferManagedYunyiAgentIdForModelKey(config, primary);
2181
+ const inferredAgent = inferredAgentId ? findAgentById(config, inferredAgentId) : null;
2182
+ if (inferredAgent) {
2183
+ const agentState = getAgentModelState(inferredAgent);
2184
+ if (agentState.primary) {
2185
+ primary = canonicalizeManagedYunyiModelKey(agentState.primary);
2186
+ fallbacks = agentState.fallbacks.map(item => isManagedYunyiModelKey(item) ? canonicalizeManagedYunyiModelKey(item) : item);
2187
+ }
2188
+ agentId = inferredAgent.id;
2189
+ agentName = String(inferredAgent.name || '').trim();
2190
+ }
2054
2191
  }
2055
2192
 
2056
2193
  const providerName = primary.includes('/') ? primary.split('/')[0] : '';
@@ -2312,28 +2449,24 @@ function applyManagedYunyiOpenClawLayout(config, options = {}) {
2312
2449
  }
2313
2450
 
2314
2451
  const agentList = ensureAgentList(config);
2452
+ const currentMainAgentState = getAgentModelState(findAgentById(config, YYMAXAPI_OPENCLAW_MAIN_AGENT_ID));
2315
2453
  const mainAgentResult = upsertManagedAgent(agentList, {
2316
2454
  id: YYMAXAPI_OPENCLAW_MAIN_AGENT_ID,
2317
2455
  default: true,
2318
2456
  name: 'yunyi-claude',
2319
- model: {
2320
- primary: YYMAXAPI_OPENCLAW_CLAUDE_PRIMARY,
2321
- fallbacks: [YYMAXAPI_OPENCLAW_CLAUDE_FALLBACK]
2322
- }
2457
+ model: normalizeManagedYunyiModelState('claude', currentMainAgentState, options)
2323
2458
  }, isManagedMainAgent);
2324
2459
  if (mainAgentResult.changed) changed = true;
2325
2460
 
2326
2461
  let claudeAgentId = YYMAXAPI_OPENCLAW_MAIN_AGENT_ID;
2327
2462
  let preservedMain = !mainAgentResult.managed;
2328
2463
  if (!mainAgentResult.managed) {
2464
+ const currentClaudeSideState = getAgentModelState(findAgentById(config, YYMAXAPI_OPENCLAW_ALT_CLAUDE_AGENT_ID));
2329
2465
  const fallbackClaudeAgentResult = upsertManagedAgent(agentList, {
2330
2466
  id: YYMAXAPI_OPENCLAW_ALT_CLAUDE_AGENT_ID,
2331
2467
  default: false,
2332
2468
  name: 'yunyi-claude',
2333
- model: {
2334
- primary: YYMAXAPI_OPENCLAW_CLAUDE_PRIMARY,
2335
- fallbacks: [YYMAXAPI_OPENCLAW_CLAUDE_FALLBACK]
2336
- }
2469
+ model: normalizeManagedYunyiModelState('claude', currentClaudeSideState, options)
2337
2470
  }, isManagedClaudeSideAgent);
2338
2471
  if (fallbackClaudeAgentResult.changed) changed = true;
2339
2472
  claudeAgentId = fallbackClaudeAgentResult.managed ? YYMAXAPI_OPENCLAW_ALT_CLAUDE_AGENT_ID : null;
@@ -2341,22 +2474,17 @@ function applyManagedYunyiOpenClawLayout(config, options = {}) {
2341
2474
  changed = true;
2342
2475
  }
2343
2476
 
2477
+ const currentGptAgentState = getAgentModelState(findAgentById(config, YYMAXAPI_OPENCLAW_GPT_AGENT_ID));
2344
2478
  const gptAgentResult = upsertManagedAgent(agentList, {
2345
2479
  id: YYMAXAPI_OPENCLAW_GPT_AGENT_ID,
2346
2480
  default: false,
2347
2481
  name: 'yunyi-gpt',
2348
- model: {
2349
- primary: YYMAXAPI_OPENCLAW_GPT_PRIMARY,
2350
- fallbacks: [YYMAXAPI_OPENCLAW_GPT_FALLBACK]
2351
- }
2482
+ model: normalizeManagedYunyiModelState('codex', currentGptAgentState, options)
2352
2483
  }, isManagedGptAgent);
2353
2484
  if (gptAgentResult.changed) changed = true;
2354
2485
 
2355
2486
  if (shouldManageYunyiDefaults(config)) {
2356
- const nextDefaultsModel = {
2357
- primary: YYMAXAPI_OPENCLAW_CLAUDE_PRIMARY,
2358
- fallbacks: [YYMAXAPI_OPENCLAW_GPT_PRIMARY]
2359
- };
2487
+ const nextDefaultsModel = normalizeManagedYunyiDefaultsModel(config.agents.defaults.model, options);
2360
2488
  if (JSON.stringify(config.agents.defaults.model) !== JSON.stringify(nextDefaultsModel)) {
2361
2489
  config.agents.defaults.model = nextDefaultsModel;
2362
2490
  changed = true;
@@ -5116,7 +5244,8 @@ async function switchModel(paths) {
5116
5244
 
5117
5245
  const config = ensureConfigStructure(readConfig(paths.openclawConfig) || {});
5118
5246
  applyConfigRepairsWithSync(config, paths);
5119
- const primary = config.agents?.defaults?.model?.primary || '';
5247
+ applyManagedYunyiOpenClawLayout(config);
5248
+ let primary = config.agents?.defaults?.model?.primary || '';
5120
5249
  const providers = config.models?.providers || {};
5121
5250
 
5122
5251
  if (Object.keys(providers).length === 0) {
@@ -5214,6 +5343,7 @@ async function switchModel(paths) {
5214
5343
  }]);
5215
5344
 
5216
5345
  let finalSelected = selected;
5346
+ let selectedAgentId = '';
5217
5347
 
5218
5348
  if (selected === '__other__') {
5219
5349
  if (otherModels.length === 0) {
@@ -5244,42 +5374,51 @@ async function switchModel(paths) {
5244
5374
  return;
5245
5375
  }
5246
5376
 
5247
- const selectedProviderKey = finalSelected.split('/')[0];
5248
- const selectedModelId = finalSelected.split('/')[1];
5249
- config.agents.defaults.model.primary = finalSelected;
5250
- if (!config.agents.defaults.models[finalSelected]) {
5251
- config.agents.defaults.models[finalSelected] = { alias: selectedProviderKey };
5252
- }
5253
-
5254
- // 同步更新 provider.models
5255
- const providerConfig = providers[selectedProviderKey];
5256
- if (providerConfig && selectedModelId) {
5257
- const existingModel = (providerConfig.models || []).find(m => m.id === selectedModelId);
5258
- if (!existingModel) {
5259
- const allModels = [...CLAUDE_MODELS, ...CODEX_MODELS];
5260
- const knownModel = allModels.find(m => m.id === selectedModelId);
5261
- const apiType = providerConfig.api || '';
5262
- const isAnthropic = apiType.startsWith('anthropic');
5263
- const defaultCtx = isAnthropic ? (API_CONFIG.claude?.contextWindow || 200000) : (API_CONFIG.codex?.contextWindow || 200000);
5264
- const defaultMax = isAnthropic ? (API_CONFIG.claude?.maxTokens || 8192) : (API_CONFIG.codex?.maxTokens || 8192);
5265
- providerConfig.models = [{
5266
- id: selectedModelId,
5267
- name: knownModel ? knownModel.name : selectedModelId,
5268
- contextWindow: defaultCtx,
5269
- maxTokens: defaultMax
5270
- }];
5271
- } else {
5272
- providerConfig.models = [existingModel];
5377
+ if (isManagedYunyiModelKey(finalSelected)) {
5378
+ const selectionResult = applyManagedYunyiModelSelection(config, finalSelected);
5379
+ finalSelected = selectionResult.selectedModelKey;
5380
+ selectedAgentId = selectionResult.agentId || '';
5381
+ } else {
5382
+ const selectedProviderKey = finalSelected.split('/')[0];
5383
+ const selectedModelId = finalSelected.split('/')[1];
5384
+ config.agents.defaults.model.primary = finalSelected;
5385
+ if (!config.agents.defaults.models[finalSelected]) {
5386
+ config.agents.defaults.models[finalSelected] = { alias: selectedProviderKey };
5387
+ }
5388
+
5389
+ // 同步更新 provider.models
5390
+ const providerConfig = providers[selectedProviderKey];
5391
+ if (providerConfig && selectedModelId) {
5392
+ const existingModel = (providerConfig.models || []).find(m => m.id === selectedModelId);
5393
+ if (!existingModel) {
5394
+ const allModels = [...CLAUDE_MODELS, ...CODEX_MODELS];
5395
+ const knownModel = allModels.find(m => m.id === selectedModelId);
5396
+ const apiType = providerConfig.api || '';
5397
+ const isAnthropic = apiType.startsWith('anthropic');
5398
+ const defaultCtx = isAnthropic ? (API_CONFIG.claude?.contextWindow || 200000) : (API_CONFIG.codex?.contextWindow || 200000);
5399
+ const defaultMax = isAnthropic ? (API_CONFIG.claude?.maxTokens || 8192) : (API_CONFIG.codex?.maxTokens || 8192);
5400
+ providerConfig.models = [{
5401
+ id: selectedModelId,
5402
+ name: knownModel ? knownModel.name : selectedModelId,
5403
+ contextWindow: defaultCtx,
5404
+ maxTokens: defaultMax
5405
+ }];
5406
+ } else {
5407
+ providerConfig.models = [existingModel];
5408
+ }
5273
5409
  }
5274
- }
5275
5410
 
5276
- config.agents.defaults.model.fallbacks = (config.agents.defaults.model.fallbacks || []).filter(k => k !== finalSelected);
5277
- if (primary && primary !== finalSelected && !config.agents.defaults.model.fallbacks.includes(primary)) {
5278
- config.agents.defaults.model.fallbacks.push(primary);
5411
+ config.agents.defaults.model.fallbacks = (config.agents.defaults.model.fallbacks || []).filter(k => k !== finalSelected);
5412
+ if (primary && primary !== finalSelected && !config.agents.defaults.model.fallbacks.includes(primary)) {
5413
+ config.agents.defaults.model.fallbacks.push(primary);
5414
+ }
5279
5415
  }
5416
+
5417
+ primary = finalSelected;
5280
5418
  ensureGatewaySettings(config);
5281
5419
  writeConfigWithSync(paths, config);
5282
5420
 
5421
+ const selectedProviderKey = finalSelected.split('/')[0];
5283
5422
  const selectedProviderConfig = providers[selectedProviderKey];
5284
5423
  const selectedLabel = PROVIDER_LABELS[selectedProviderKey] || selectedProviderKey;
5285
5424
  console.log(chalk.green(`\n✅ 已切换到 ${finalSelected}`));
@@ -5305,7 +5444,7 @@ async function switchModel(paths) {
5305
5444
 
5306
5445
  // 重启后直接测试连接
5307
5446
  console.log('');
5308
- await testConnection(paths, {});
5447
+ await testConnection(paths, selectedAgentId ? { agent: selectedAgentId } : {});
5309
5448
  }
5310
5449
  // ============ 权限管理 (tools.profile) ============
5311
5450
  const TOOLS_PROFILES = [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yymaxapi",
3
- "version": "1.0.87",
3
+ "version": "1.0.89",
4
4
  "description": "跨平台 OpenClaw/Clawdbot 配置管理工具 - 管理中转地址、模型切换、API Keys、测速优化",
5
5
  "main": "bin/yymaxapi.js",
6
6
  "bin": {