yymaxapi 1.0.63 → 1.0.65

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 +39 -16
  2. package/package.json +1 -1
package/bin/yymaxapi.js CHANGED
@@ -716,32 +716,49 @@ function writeCodexConfig(baseUrl, apiKey) {
716
716
  } catch { /* 非关键,静默失败 */ }
717
717
  }
718
718
 
719
- function writeOpencodeConfig(baseUrl, apiKey, modelId) {
719
+ function writeOpencodeConfig(claudeBaseUrl, codexBaseUrl, apiKey, modelId) {
720
720
  const home = os.homedir();
721
721
  const configDir = process.platform === 'win32'
722
722
  ? path.join(process.env.APPDATA || path.join(home, 'AppData', 'Roaming'), 'opencode')
723
723
  : path.join(home, '.config', 'opencode');
724
- const configPath = path.join(configDir, 'config.json');
724
+ const configPath = path.join(configDir, 'opencode.json');
725
725
  try {
726
726
  if (!fs.existsSync(configDir)) fs.mkdirSync(configDir, { recursive: true });
727
- const cleanUrl = baseUrl.replace(/\/+$/, '');
728
- const config = {
729
- provider: {
730
- anthropic: {
727
+ let existing = {};
728
+ if (fs.existsSync(configPath)) {
729
+ try { existing = JSON.parse(fs.readFileSync(configPath, 'utf8')); } catch { existing = {}; }
730
+ }
731
+ const cleanClaudeUrl = claudeBaseUrl.replace(/\/+$/, '');
732
+ let cleanCodexUrl = (codexBaseUrl || '').replace(/\/+$/, '');
733
+ if (cleanCodexUrl && !cleanCodexUrl.endsWith('/v1')) cleanCodexUrl += '/v1';
734
+ if (!existing.provider) existing.provider = {};
735
+ existing.provider.anthropic = {
736
+ options: {
737
+ apiKey: apiKey,
738
+ baseURL: cleanClaudeUrl
739
+ }
740
+ };
741
+ if (cleanCodexUrl) {
742
+ existing.provider.openai = {
743
+ options: {
731
744
  apiKey: apiKey,
732
- baseURL: cleanUrl
745
+ baseURL: cleanCodexUrl
733
746
  }
734
- },
735
- model: modelId || 'claude-sonnet-4-6'
736
- };
737
- fs.writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf8');
747
+ };
748
+ }
749
+ const rawModelId = modelId || 'claude-sonnet-4-6';
750
+ existing.model = rawModelId.startsWith('anthropic/') || rawModelId.startsWith('openai/')
751
+ ? rawModelId
752
+ : `anthropic/${rawModelId}`;
753
+ if (!existing.$schema) existing.$schema = 'https://opencode.ai/config.json';
754
+ fs.writeFileSync(configPath, JSON.stringify(existing, null, 2), 'utf8');
738
755
  return configPath;
739
756
  } catch {
740
757
  return null;
741
758
  }
742
759
  }
743
760
 
744
- function syncExternalTools(type, baseUrl, apiKey) {
761
+ function syncExternalTools(type, baseUrl, apiKey, extra = {}) {
745
762
  const synced = [];
746
763
  try {
747
764
  if (type === 'claude') {
@@ -751,6 +768,10 @@ function syncExternalTools(type, baseUrl, apiKey) {
751
768
  writeCodexConfig(baseUrl, apiKey);
752
769
  synced.push('Codex CLI config');
753
770
  }
771
+ if (type === 'claude' && extra.codexBaseUrl) {
772
+ writeOpencodeConfig(baseUrl, extra.codexBaseUrl, apiKey);
773
+ synced.push('Opencode config');
774
+ }
754
775
  } catch { /* ignore */ }
755
776
  return synced;
756
777
  }
@@ -2745,7 +2766,7 @@ async function autoActivate(paths, args = {}) {
2745
2766
  updateAuthProfiles(paths.authProfiles, claudeProviderName, apiKey);
2746
2767
  updateAuthProfiles(paths.authProfiles, codexProviderName, apiKey);
2747
2768
  const extSynced = [];
2748
- try { syncExternalTools('claude', claudeBaseUrl, apiKey); extSynced.push('Claude Code settings'); } catch { /* ignore */ }
2769
+ try { syncExternalTools('claude', claudeBaseUrl, apiKey, { codexBaseUrl }); extSynced.push('Claude Code settings'); } catch { /* ignore */ }
2749
2770
  try { syncExternalTools('codex', codexBaseUrl, apiKey); extSynced.push('Codex CLI config'); } catch { /* ignore */ }
2750
2771
  writeSpinner.succeed('配置写入完成');
2751
2772
 
@@ -2927,13 +2948,15 @@ async function activateOpencode(paths, args = {}) {
2927
2948
 
2928
2949
  // ---- 写入配置 ----
2929
2950
  const claudeBaseUrl = buildFullUrl(selectedEndpoint.url, 'claude');
2951
+ const codexBaseUrl = buildFullUrl(selectedEndpoint.url, 'codex');
2930
2952
  const modelId = 'claude-sonnet-4-6';
2931
2953
  const writeSpinner = ora({ text: '正在写入 Opencode 配置...', spinner: 'dots' }).start();
2932
- const configPath = writeOpencodeConfig(claudeBaseUrl, apiKey, modelId);
2954
+ const configPath = writeOpencodeConfig(claudeBaseUrl, codexBaseUrl, apiKey, modelId);
2933
2955
  writeSpinner.succeed('Opencode 配置写入完成');
2934
2956
 
2935
2957
  console.log(chalk.green('\n✅ Opencode 配置完成!'));
2936
- console.log(chalk.cyan(` Base URL: ${claudeBaseUrl}`));
2958
+ console.log(chalk.cyan(` Claude: ${claudeBaseUrl}`));
2959
+ console.log(chalk.cyan(` Codex: ${codexBaseUrl}`));
2937
2960
  console.log(chalk.gray(` 模型: ${modelId}`));
2938
2961
  console.log(chalk.gray(' API Key: 已设置'));
2939
2962
  if (configPath) {
@@ -3083,7 +3106,7 @@ async function yycodeQuickSetup(paths) {
3083
3106
  writeConfigWithSync(paths, config);
3084
3107
  updateAuthProfiles(paths.authProfiles, claudeProviderName, apiKey);
3085
3108
  updateAuthProfiles(paths.authProfiles, codexProviderName, apiKey);
3086
- try { syncExternalTools('claude', claudeBaseUrl, apiKey); } catch { /* ignore */ }
3109
+ try { syncExternalTools('claude', claudeBaseUrl, apiKey, { codexBaseUrl }); } catch { /* ignore */ }
3087
3110
  try { syncExternalTools('codex', codexBaseUrl, apiKey); } catch { /* ignore */ }
3088
3111
  writeSpinner.succeed('配置写入完成');
3089
3112
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yymaxapi",
3
- "version": "1.0.63",
3
+ "version": "1.0.65",
4
4
  "description": "跨平台 OpenClaw/Clawdbot 配置管理工具 - 管理中转地址、模型切换、API Keys、测速优化",
5
5
  "main": "bin/yymaxapi.js",
6
6
  "bin": {