yymaxapi 1.0.123 → 1.0.125

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 +68 -23
  2. package/package.json +1 -1
package/bin/yymaxapi.js CHANGED
@@ -1248,13 +1248,39 @@ function writeCodexConfig(baseUrl, apiKey, modelId = 'gpt-5.5') {
1248
1248
  } catch { /* 非关键,静默失败 */ }
1249
1249
  }
1250
1250
 
1251
- function writeOpencodeConfig(claudeBaseUrl, codexBaseUrl, apiKey, defaultModelKey = getExternalModelKey('claude', getDefaultClaudeModel().id)) {
1251
+ function extractTomlProviderBearerToken(content, providerKey) {
1252
+ const escapedProviderKey = escapeRegExp(providerKey);
1253
+ const match = String(content || '').match(new RegExp(`\\[model_providers\\.${escapedProviderKey}\\][\\s\\S]*?experimental_bearer_token\\s*=\\s*"([^"]*)"`, 'm'));
1254
+ return String(match?.[1] || '').trim();
1255
+ }
1256
+
1257
+ function readOpenClawProviderApiKey(providerKey) {
1258
+ try {
1259
+ const paths = getConfigPath();
1260
+ const config = readConfig(paths.openclawConfig);
1261
+ return String(config?.models?.providers?.[providerKey]?.apiKey || '').trim();
1262
+ } catch {
1263
+ return '';
1264
+ }
1265
+ }
1266
+
1267
+ function writeOpencodeConfig(claudeBaseUrl, codexBaseUrl, apiKey, defaultModelKey = getExternalModelKey('claude', getDefaultClaudeModel().id), options = {}) {
1252
1268
  const home = os.homedir();
1253
1269
  const claudeUrl = claudeBaseUrl.replace(/\/+$/, '');
1254
1270
  const codexUrl = (codexBaseUrl || '').replace(/\/+$/, '');
1271
+ const claudeApiKey = String(apiKey || '').trim();
1255
1272
  const claudeProviderKey = getExternalClaudeProviderKey();
1256
1273
  const codexProviderKey = getExternalCodexProviderKey();
1274
+ const openClawCodexProviderKey = String(API_CONFIG?.codex?.providerName || codexProviderKey).trim() || codexProviderKey;
1257
1275
  const brandPrefix = getProviderBrandPrefix();
1276
+ const codexDir = path.join(home, '.codex');
1277
+ const codexConfigPath = path.join(codexDir, 'config.toml');
1278
+ const codexAuthPath = path.join(codexDir, 'auth.json');
1279
+ const existingCodexToml = readTextIfExists(codexConfigPath);
1280
+ let existingCodexAuth = {};
1281
+ if (fs.existsSync(codexAuthPath)) {
1282
+ try { existingCodexAuth = JSON.parse(fs.readFileSync(codexAuthPath, 'utf8')); } catch { existingCodexAuth = {}; }
1283
+ }
1258
1284
 
1259
1285
  // ---- 1. opencode.json (CLI + 桌面版) ----
1260
1286
  const configDir = process.platform === 'win32'
@@ -1268,13 +1294,21 @@ function writeOpencodeConfig(claudeBaseUrl, codexBaseUrl, apiKey, defaultModelKe
1268
1294
  try { existing = JSON.parse(fs.readFileSync(configPath, 'utf8')); } catch { existing = {}; }
1269
1295
  }
1270
1296
  if (!existing.provider) existing.provider = {};
1297
+ const codexApiKey = String(
1298
+ options.codexApiKey || options.codexKey || options.gptApiKey || options.gptKey || ''
1299
+ ).trim()
1300
+ || readOpenClawProviderApiKey(openClawCodexProviderKey)
1301
+ || extractTomlProviderBearerToken(existingCodexToml, codexProviderKey)
1302
+ || String(existingCodexAuth.OPENAI_API_KEY || '').trim()
1303
+ || String(existing.provider?.[codexProviderKey]?.options?.apiKey || '').trim()
1304
+ || claudeApiKey;
1271
1305
 
1272
1306
  // Claude provider (@ai-sdk/anthropic)
1273
1307
  existing.provider[claudeProviderKey] = {
1274
1308
  name: `${brandPrefix} Claude`,
1275
1309
  npm: '@ai-sdk/anthropic',
1276
1310
  models: buildProviderModelMap(CLAUDE_MODELS),
1277
- options: { apiKey, baseURL: `${claudeUrl}/v1` }
1311
+ options: { apiKey: claudeApiKey, baseURL: `${claudeUrl}/v1` }
1278
1312
  };
1279
1313
 
1280
1314
  // Codex provider (@ai-sdk/openai)
@@ -1283,7 +1317,7 @@ function writeOpencodeConfig(claudeBaseUrl, codexBaseUrl, apiKey, defaultModelKe
1283
1317
  name: `${brandPrefix} Codex`,
1284
1318
  npm: '@ai-sdk/openai',
1285
1319
  models: buildProviderModelMap(CODEX_MODELS),
1286
- options: { apiKey, baseURL: codexUrl }
1320
+ options: { apiKey: codexApiKey, baseURL: codexUrl }
1287
1321
  };
1288
1322
  }
1289
1323
 
@@ -1308,15 +1342,21 @@ function writeOpencodeConfig(claudeBaseUrl, codexBaseUrl, apiKey, defaultModelKe
1308
1342
  } catch { /* 非关键,静默失败 */ }
1309
1343
 
1310
1344
  // ---- 2. ~/.codex/config.toml (opencode 也读此格式) ----
1311
- const codexDir = path.join(home, '.codex');
1312
- const codexConfigPath = path.join(codexDir, 'config.toml');
1313
1345
  try {
1314
1346
  if (!fs.existsSync(codexDir)) fs.mkdirSync(codexDir, { recursive: true });
1315
1347
 
1316
- let content = '';
1317
- if (fs.existsSync(codexConfigPath)) {
1318
- content = fs.readFileSync(codexConfigPath, 'utf8');
1319
- }
1348
+ let content = existingCodexToml;
1349
+ const existingOpencodeConfig = fs.existsSync(configPath)
1350
+ ? (() => { try { return JSON.parse(fs.readFileSync(configPath, 'utf8')); } catch { return {}; } })()
1351
+ : {};
1352
+ const codexApiKey = String(
1353
+ options.codexApiKey || options.codexKey || options.gptApiKey || options.gptKey || ''
1354
+ ).trim()
1355
+ || readOpenClawProviderApiKey(openClawCodexProviderKey)
1356
+ || extractTomlProviderBearerToken(existingCodexToml, codexProviderKey)
1357
+ || String(existingCodexAuth.OPENAI_API_KEY || '').trim()
1358
+ || String(existingOpencodeConfig.provider?.[codexProviderKey]?.options?.apiKey || '').trim()
1359
+ || claudeApiKey;
1320
1360
 
1321
1361
  // 移除旧标记块(仅移除 opencode 自己写入的兼容 provider)
1322
1362
  content = content.replace(/# >>> yunyi opencode >>>[\s\S]*?# <<< yunyi opencode <<<\n?/g, '');
@@ -1352,14 +1392,14 @@ function writeOpencodeConfig(claudeBaseUrl, codexBaseUrl, apiKey, defaultModelKe
1352
1392
  `name = "${brandPrefix} Claude"`,
1353
1393
  `base_url = "${claudeUrl}/v1"`,
1354
1394
  `wire_api = "anthropic"`,
1355
- `experimental_bearer_token = "${apiKey}"`,
1395
+ `experimental_bearer_token = "${claudeApiKey}"`,
1356
1396
  ...(normalizedCodexTomlUrl ? [
1357
1397
  '',
1358
1398
  `[model_providers.${codexProviderKey}]`,
1359
1399
  `name = "${brandPrefix} Codex"`,
1360
1400
  `base_url = "${normalizedCodexTomlUrl}"`,
1361
1401
  `wire_api = "responses"`,
1362
- `experimental_bearer_token = "${apiKey}"`
1402
+ `experimental_bearer_token = "${codexApiKey}"`
1363
1403
  ] : []),
1364
1404
  markerEnd
1365
1405
  ].join('\n');
@@ -1368,14 +1408,10 @@ function writeOpencodeConfig(claudeBaseUrl, codexBaseUrl, apiKey, defaultModelKe
1368
1408
  fs.writeFileSync(codexConfigPath, nextContent, 'utf8');
1369
1409
 
1370
1410
  // ---- 3. ~/.codex/auth.json ----
1371
- const authPath = path.join(codexDir, 'auth.json');
1372
- let auth = {};
1373
- if (fs.existsSync(authPath)) {
1374
- try { auth = JSON.parse(fs.readFileSync(authPath, 'utf8')); } catch { auth = {}; }
1375
- }
1376
- auth.ANTHROPIC_API_KEY = apiKey;
1377
- auth.OPENAI_API_KEY = apiKey;
1378
- fs.writeFileSync(authPath, JSON.stringify(auth, null, 2), 'utf8');
1411
+ const auth = { ...existingCodexAuth };
1412
+ auth.ANTHROPIC_API_KEY = claudeApiKey;
1413
+ auth.OPENAI_API_KEY = codexApiKey;
1414
+ fs.writeFileSync(codexAuthPath, JSON.stringify(auth, null, 2), 'utf8');
1379
1415
  } catch { /* 非关键,静默失败 */ }
1380
1416
 
1381
1417
  return configPath;
@@ -3070,21 +3106,30 @@ function applyManagedYunyiOpenClawLayout(config, options = {}) {
3070
3106
  ensureConfigStructure(config);
3071
3107
 
3072
3108
  const endpointUrl = inferManagedYunyiEndpointUrl(config, options.endpointUrl);
3073
- const apiKey = inferManagedYunyiApiKey(config, options.apiKey);
3109
+ const sharedApiKey = String(options.apiKey || '').trim();
3110
+ const fallbackApiKey = inferManagedYunyiApiKey(config, sharedApiKey);
3074
3111
  if (!endpointUrl) {
3075
3112
  return { changed: false, applied: false, claudeAgentId: null, preservedMain: false };
3076
3113
  }
3077
3114
 
3078
3115
  let changed = false;
3079
3116
  const providers = config.models.providers;
3080
-
3081
- const nextClaudeProvider = buildManagedYunyiProviderConfig('claude', endpointUrl, apiKey, providers[YYMAXAPI_OPENCLAW_CLAUDE_PROVIDER] || {});
3117
+ const claudeApiKey = sharedApiKey
3118
+ || String(options.claudeApiKey || options.claudeKey || '').trim()
3119
+ || String(providers[YYMAXAPI_OPENCLAW_CLAUDE_PROVIDER]?.apiKey || '').trim()
3120
+ || fallbackApiKey;
3121
+ const gptApiKey = sharedApiKey
3122
+ || String(options.codexApiKey || options.codexKey || options.gptApiKey || options.gptKey || '').trim()
3123
+ || String(providers[YYMAXAPI_OPENCLAW_GPT_PROVIDER]?.apiKey || '').trim()
3124
+ || fallbackApiKey;
3125
+
3126
+ const nextClaudeProvider = buildManagedYunyiProviderConfig('claude', endpointUrl, claudeApiKey, providers[YYMAXAPI_OPENCLAW_CLAUDE_PROVIDER] || {});
3082
3127
  if (JSON.stringify(nextClaudeProvider) !== JSON.stringify(providers[YYMAXAPI_OPENCLAW_CLAUDE_PROVIDER] || {})) {
3083
3128
  providers[YYMAXAPI_OPENCLAW_CLAUDE_PROVIDER] = nextClaudeProvider;
3084
3129
  changed = true;
3085
3130
  }
3086
3131
 
3087
- const nextGptProvider = buildManagedYunyiProviderConfig('codex', endpointUrl, apiKey, providers[YYMAXAPI_OPENCLAW_GPT_PROVIDER] || {});
3132
+ const nextGptProvider = buildManagedYunyiProviderConfig('codex', endpointUrl, gptApiKey, providers[YYMAXAPI_OPENCLAW_GPT_PROVIDER] || {});
3088
3133
  if (JSON.stringify(nextGptProvider) !== JSON.stringify(providers[YYMAXAPI_OPENCLAW_GPT_PROVIDER] || {})) {
3089
3134
  providers[YYMAXAPI_OPENCLAW_GPT_PROVIDER] = nextGptProvider;
3090
3135
  changed = true;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yymaxapi",
3
- "version": "1.0.123",
3
+ "version": "1.0.125",
4
4
  "description": "跨平台 OpenClaw/Clawdbot 配置管理工具 - 管理中转地址、模型切换、API Keys、测速优化",
5
5
  "main": "bin/yymaxapi.js",
6
6
  "bin": {