yymaxapi 1.0.50 → 1.0.51
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.
- package/bin/yymaxapi.js +96 -58
- package/package.json +1 -1
package/bin/yymaxapi.js
CHANGED
|
@@ -140,8 +140,6 @@ const DEFAULT_API_CONFIG = {
|
|
|
140
140
|
|
|
141
141
|
const SKIP_API_VALIDATION = false;
|
|
142
142
|
|
|
143
|
-
const SKIP_API_VALIDATION = false;
|
|
144
|
-
|
|
145
143
|
function normalizeEndpoints(raw, fallback) {
|
|
146
144
|
if (!Array.isArray(raw)) return fallback;
|
|
147
145
|
const normalized = raw
|
|
@@ -1184,8 +1182,23 @@ function coerceModelsRecord(value) {
|
|
|
1184
1182
|
return record;
|
|
1185
1183
|
}
|
|
1186
1184
|
|
|
1185
|
+
const OPENCLAW_KNOWN_ROOT_KEYS = new Set([
|
|
1186
|
+
'models', 'agents', 'auth', 'gateway', 'tools',
|
|
1187
|
+
'channels', 'mcpServers', 'globalShortcut', 'customModes',
|
|
1188
|
+
'permissions', 'proxy', 'env', 'hooks', 'storage',
|
|
1189
|
+
]);
|
|
1190
|
+
|
|
1191
|
+
function sanitizeRootKeys(config) {
|
|
1192
|
+
for (const key of Object.keys(config)) {
|
|
1193
|
+
if (!OPENCLAW_KNOWN_ROOT_KEYS.has(key)) {
|
|
1194
|
+
delete config[key];
|
|
1195
|
+
}
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
1198
|
+
|
|
1187
1199
|
function ensureConfigStructure(config) {
|
|
1188
1200
|
const next = config || {};
|
|
1201
|
+
sanitizeRootKeys(next);
|
|
1189
1202
|
if (!next.models) next.models = {};
|
|
1190
1203
|
if (!next.models.providers) next.models.providers = {};
|
|
1191
1204
|
if (!next.agents) next.agents = {};
|
|
@@ -2668,25 +2681,54 @@ async function autoActivate(paths, args = {}) {
|
|
|
2668
2681
|
// ---- 构建配置 ----
|
|
2669
2682
|
const config = ensureConfigStructure(readConfig(paths.openclawConfig) || {});
|
|
2670
2683
|
|
|
2671
|
-
// 增量写入: 只添加/更新云翼 provider,保留其他已有配置
|
|
2672
|
-
|
|
2673
|
-
// Claude 侧 — 让用户选模型
|
|
2674
2684
|
const claudeBaseUrl = buildFullUrl(selectedEndpoint.url, 'claude');
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
+
const codexBaseUrl = buildFullUrl(selectedEndpoint.url, 'codex');
|
|
2686
|
+
|
|
2687
|
+
// 检测单一模式:Claude 和 Codex 只有一个模型且 id 相同(如 maxapi 的 heibai)
|
|
2688
|
+
const isSingleMode = CLAUDE_MODELS.length === 1 && CODEX_MODELS.length === 1
|
|
2689
|
+
&& CLAUDE_MODELS[0].id === CODEX_MODELS[0].id;
|
|
2690
|
+
|
|
2691
|
+
let claudeModelId, codexModelId;
|
|
2692
|
+
|
|
2693
|
+
if (isSingleMode) {
|
|
2694
|
+
// 单一模式:固定模型,不选择,不分 Claude/Codex
|
|
2695
|
+
claudeModelId = CLAUDE_MODELS[0].id;
|
|
2696
|
+
codexModelId = CODEX_MODELS[0].id;
|
|
2697
|
+
} else {
|
|
2698
|
+
// 多模型模式:让用户选模型
|
|
2699
|
+
claudeModelId = (args['claude-model'] || '').toString().trim();
|
|
2700
|
+
if (!claudeModelId && CLAUDE_MODELS.length > 1) {
|
|
2701
|
+
const { picked } = await inquirer.prompt([{
|
|
2702
|
+
type: 'list',
|
|
2703
|
+
name: 'picked',
|
|
2704
|
+
message: '选择 Claude 模型:',
|
|
2705
|
+
choices: CLAUDE_MODELS.map(m => ({ name: m.name, value: m.id })),
|
|
2706
|
+
default: CLAUDE_MODELS[0].id
|
|
2707
|
+
}]);
|
|
2708
|
+
claudeModelId = picked;
|
|
2709
|
+
}
|
|
2710
|
+
if (!claudeModelId) claudeModelId = CLAUDE_MODELS[0]?.id || 'claude-sonnet-4-6';
|
|
2711
|
+
|
|
2712
|
+
codexModelId = (args['codex-model'] || '').toString().trim();
|
|
2713
|
+
if (!codexModelId && CODEX_MODELS.length > 1) {
|
|
2714
|
+
const { pickedCodex } = await inquirer.prompt([{
|
|
2715
|
+
type: 'list',
|
|
2716
|
+
name: 'pickedCodex',
|
|
2717
|
+
message: '选择 Codex 模型:',
|
|
2718
|
+
choices: CODEX_MODELS.map(m => ({ name: m.name, value: m.id })),
|
|
2719
|
+
default: CODEX_MODELS[0].id
|
|
2720
|
+
}]);
|
|
2721
|
+
codexModelId = pickedCodex;
|
|
2722
|
+
}
|
|
2723
|
+
if (!codexModelId) codexModelId = CODEX_MODELS[0]?.id || 'gpt-5.3-codex';
|
|
2685
2724
|
}
|
|
2686
|
-
|
|
2725
|
+
|
|
2687
2726
|
const claudeModel = CLAUDE_MODELS.find(m => m.id === claudeModelId) || { id: claudeModelId, name: claudeModelId };
|
|
2727
|
+
const codexModel = CODEX_MODELS.find(m => m.id === codexModelId) || { id: codexModelId, name: codexModelId };
|
|
2688
2728
|
const claudeModelKey = `${claudeProviderName}/${claudeModelId}`;
|
|
2729
|
+
const codexModelKey = `${codexProviderName}/${codexModelId}`;
|
|
2689
2730
|
|
|
2731
|
+
// 写入 Claude provider
|
|
2690
2732
|
config.models.providers[claudeProviderName] = {
|
|
2691
2733
|
baseUrl: claudeBaseUrl,
|
|
2692
2734
|
auth: DEFAULT_AUTH_MODE,
|
|
@@ -2704,23 +2746,7 @@ async function autoActivate(paths, args = {}) {
|
|
|
2704
2746
|
config.auth.profiles[`${claudeProviderName}:default`] = { provider: claudeProviderName, mode: 'api_key' };
|
|
2705
2747
|
config.agents.defaults.models[claudeModelKey] = { alias: claudeProviderName };
|
|
2706
2748
|
|
|
2707
|
-
// Codex
|
|
2708
|
-
const codexBaseUrl = buildFullUrl(selectedEndpoint.url, 'codex');
|
|
2709
|
-
let codexModelId = (args['codex-model'] || '').toString().trim();
|
|
2710
|
-
if (!codexModelId && CODEX_MODELS.length > 1) {
|
|
2711
|
-
const { pickedCodex } = await inquirer.prompt([{
|
|
2712
|
-
type: 'list',
|
|
2713
|
-
name: 'pickedCodex',
|
|
2714
|
-
message: '选择 Codex 模型:',
|
|
2715
|
-
choices: CODEX_MODELS.map(m => ({ name: m.name, value: m.id })),
|
|
2716
|
-
default: CODEX_MODELS[0].id
|
|
2717
|
-
}]);
|
|
2718
|
-
codexModelId = pickedCodex;
|
|
2719
|
-
}
|
|
2720
|
-
if (!codexModelId) codexModelId = CODEX_MODELS[0]?.id || 'gpt-5.3-codex';
|
|
2721
|
-
const codexModel = CODEX_MODELS.find(m => m.id === codexModelId) || { id: codexModelId, name: codexModelId };
|
|
2722
|
-
const codexModelKey = `${codexProviderName}/${codexModelId}`;
|
|
2723
|
-
|
|
2749
|
+
// 写入 Codex provider(单一模式下仍写入,保证配置完整)
|
|
2724
2750
|
config.models.providers[codexProviderName] = {
|
|
2725
2751
|
baseUrl: codexBaseUrl,
|
|
2726
2752
|
auth: DEFAULT_AUTH_MODE,
|
|
@@ -2739,27 +2765,34 @@ async function autoActivate(paths, args = {}) {
|
|
|
2739
2765
|
config.agents.defaults.models[codexModelKey] = { alias: codexProviderName };
|
|
2740
2766
|
|
|
2741
2767
|
// ---- 选择主力 ----
|
|
2742
|
-
let
|
|
2743
|
-
if (
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2768
|
+
let primaryModelKey, fallbackModelKey;
|
|
2769
|
+
if (isSingleMode) {
|
|
2770
|
+
// 单一模式:直接用 Claude provider 作为 primary,不需要用户选
|
|
2771
|
+
primaryModelKey = claudeModelKey;
|
|
2772
|
+
fallbackModelKey = codexModelKey;
|
|
2747
2773
|
} else {
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2774
|
+
let primaryType = 'claude';
|
|
2775
|
+
if (args.primary === 'claude') {
|
|
2776
|
+
primaryType = 'claude';
|
|
2777
|
+
} else if (args.primary === 'codex') {
|
|
2778
|
+
primaryType = 'codex';
|
|
2779
|
+
} else {
|
|
2780
|
+
const { picked } = await inquirer.prompt([{
|
|
2781
|
+
type: 'list',
|
|
2782
|
+
name: 'picked',
|
|
2783
|
+
message: '选择主力工具(默认启动哪个):',
|
|
2784
|
+
choices: [
|
|
2785
|
+
{ name: 'Claude Code', value: 'claude' },
|
|
2786
|
+
{ name: 'Codex (GPT)', value: 'codex' }
|
|
2787
|
+
]
|
|
2788
|
+
}]);
|
|
2789
|
+
primaryType = picked;
|
|
2790
|
+
}
|
|
2791
|
+
primaryModelKey = primaryType === 'claude' ? claudeModelKey : codexModelKey;
|
|
2792
|
+
fallbackModelKey = primaryType === 'claude' ? codexModelKey : claudeModelKey;
|
|
2758
2793
|
}
|
|
2759
2794
|
|
|
2760
|
-
const primaryModelKey = primaryType === 'claude' ? claudeModelKey : codexModelKey;
|
|
2761
2795
|
config.agents.defaults.model.primary = primaryModelKey;
|
|
2762
|
-
const fallbackModelKey = primaryType === 'claude' ? codexModelKey : claudeModelKey;
|
|
2763
2796
|
config.agents.defaults.model.fallbacks = [fallbackModelKey];
|
|
2764
2797
|
|
|
2765
2798
|
// ---- 写入配置 ----
|
|
@@ -2775,13 +2808,19 @@ async function autoActivate(paths, args = {}) {
|
|
|
2775
2808
|
writeSpinner.succeed('配置写入完成');
|
|
2776
2809
|
|
|
2777
2810
|
// ---- 输出结果 ----
|
|
2778
|
-
const primaryTag = primaryType === 'claude' ? ' (主)' : '';
|
|
2779
|
-
const codexTag = primaryType === 'codex' ? ' (主)' : '';
|
|
2780
2811
|
console.log(chalk.green('\n✅ 一键激活完成!'));
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2812
|
+
if (isSingleMode) {
|
|
2813
|
+
console.log(chalk.cyan(` 节点: ${selectedEndpoint.url}`));
|
|
2814
|
+
console.log(chalk.gray(` 模型: ${claudeModel.name}`));
|
|
2815
|
+
} else {
|
|
2816
|
+
const primaryType = primaryModelKey === claudeModelKey ? 'claude' : 'codex';
|
|
2817
|
+
const primaryTag = primaryType === 'claude' ? ' (主)' : '';
|
|
2818
|
+
const codexTag = primaryType === 'codex' ? ' (主)' : '';
|
|
2819
|
+
console.log(chalk.cyan(` Claude Code${primaryTag}: ${claudeBaseUrl}`));
|
|
2820
|
+
console.log(chalk.gray(` 模型: ${claudeModel.name}`));
|
|
2821
|
+
console.log(chalk.cyan(` Codex${codexTag}: ${codexBaseUrl}`));
|
|
2822
|
+
console.log(chalk.gray(` 模型: ${codexModel.name}`));
|
|
2823
|
+
}
|
|
2785
2824
|
console.log(chalk.gray(' API Key: 已设置'));
|
|
2786
2825
|
if (extSynced.length > 0) console.log(chalk.gray(` 同步: ${extSynced.join(', ')}`));
|
|
2787
2826
|
|
|
@@ -3665,8 +3704,7 @@ async function testConnection(paths, args = {}) {
|
|
|
3665
3704
|
console.log(chalk.yellow('⚠️ 请先设置主模型'));
|
|
3666
3705
|
return;
|
|
3667
3706
|
}
|
|
3668
|
-
|
|
3669
|
-
const preferOrder = ['claude-yunyi', 'yunyi', 'heibai'];
|
|
3707
|
+
const preferOrder = ['maxapi', 'heibai', 'claude-yunyi', 'yunyi', 'maxapi-codex'];
|
|
3670
3708
|
const preferred = preferOrder.find(n => providerNames.includes(n));
|
|
3671
3709
|
const firstP = preferred || providerNames.find(n => n.includes('claude')) || providerNames[0];
|
|
3672
3710
|
const firstModels = providers[firstP]?.models || [];
|