yymaxapi 1.0.88 → 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.
- package/bin/yymaxapi.js +207 -49
- package/package.json +1 -1
package/bin/yymaxapi.js
CHANGED
|
@@ -2011,6 +2011,150 @@ function findAgentById(config, agentId) {
|
|
|
2011
2011
|
return config.agents.list.find(agent => agent && typeof agent === 'object' && agent.id === agentId) || null;
|
|
2012
2012
|
}
|
|
2013
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
|
+
|
|
2014
2158
|
function resolveOpenClawTestTarget(config, args = {}) {
|
|
2015
2159
|
const requestedAgentId = String(args.agent || args['agent-id'] || '').trim();
|
|
2016
2160
|
const requestedAgent = requestedAgentId ? findAgentById(config, requestedAgentId) : null;
|
|
@@ -2027,11 +2171,23 @@ function resolveOpenClawTestTarget(config, args = {}) {
|
|
|
2027
2171
|
if (requestedAgent) {
|
|
2028
2172
|
const agentState = getAgentModelState(requestedAgent);
|
|
2029
2173
|
if (agentState.primary) {
|
|
2030
|
-
primary = agentState.primary;
|
|
2174
|
+
primary = canonicalizeManagedYunyiModelKey(agentState.primary);
|
|
2031
2175
|
fallbacks = agentState.fallbacks;
|
|
2032
2176
|
agentId = requestedAgent.id;
|
|
2033
2177
|
agentName = String(requestedAgent.name || '').trim();
|
|
2034
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
|
+
}
|
|
2035
2191
|
}
|
|
2036
2192
|
|
|
2037
2193
|
const providerName = primary.includes('/') ? primary.split('/')[0] : '';
|
|
@@ -2293,28 +2449,24 @@ function applyManagedYunyiOpenClawLayout(config, options = {}) {
|
|
|
2293
2449
|
}
|
|
2294
2450
|
|
|
2295
2451
|
const agentList = ensureAgentList(config);
|
|
2452
|
+
const currentMainAgentState = getAgentModelState(findAgentById(config, YYMAXAPI_OPENCLAW_MAIN_AGENT_ID));
|
|
2296
2453
|
const mainAgentResult = upsertManagedAgent(agentList, {
|
|
2297
2454
|
id: YYMAXAPI_OPENCLAW_MAIN_AGENT_ID,
|
|
2298
2455
|
default: true,
|
|
2299
2456
|
name: 'yunyi-claude',
|
|
2300
|
-
model:
|
|
2301
|
-
primary: YYMAXAPI_OPENCLAW_CLAUDE_PRIMARY,
|
|
2302
|
-
fallbacks: [YYMAXAPI_OPENCLAW_CLAUDE_FALLBACK]
|
|
2303
|
-
}
|
|
2457
|
+
model: normalizeManagedYunyiModelState('claude', currentMainAgentState, options)
|
|
2304
2458
|
}, isManagedMainAgent);
|
|
2305
2459
|
if (mainAgentResult.changed) changed = true;
|
|
2306
2460
|
|
|
2307
2461
|
let claudeAgentId = YYMAXAPI_OPENCLAW_MAIN_AGENT_ID;
|
|
2308
2462
|
let preservedMain = !mainAgentResult.managed;
|
|
2309
2463
|
if (!mainAgentResult.managed) {
|
|
2464
|
+
const currentClaudeSideState = getAgentModelState(findAgentById(config, YYMAXAPI_OPENCLAW_ALT_CLAUDE_AGENT_ID));
|
|
2310
2465
|
const fallbackClaudeAgentResult = upsertManagedAgent(agentList, {
|
|
2311
2466
|
id: YYMAXAPI_OPENCLAW_ALT_CLAUDE_AGENT_ID,
|
|
2312
2467
|
default: false,
|
|
2313
2468
|
name: 'yunyi-claude',
|
|
2314
|
-
model:
|
|
2315
|
-
primary: YYMAXAPI_OPENCLAW_CLAUDE_PRIMARY,
|
|
2316
|
-
fallbacks: [YYMAXAPI_OPENCLAW_CLAUDE_FALLBACK]
|
|
2317
|
-
}
|
|
2469
|
+
model: normalizeManagedYunyiModelState('claude', currentClaudeSideState, options)
|
|
2318
2470
|
}, isManagedClaudeSideAgent);
|
|
2319
2471
|
if (fallbackClaudeAgentResult.changed) changed = true;
|
|
2320
2472
|
claudeAgentId = fallbackClaudeAgentResult.managed ? YYMAXAPI_OPENCLAW_ALT_CLAUDE_AGENT_ID : null;
|
|
@@ -2322,22 +2474,17 @@ function applyManagedYunyiOpenClawLayout(config, options = {}) {
|
|
|
2322
2474
|
changed = true;
|
|
2323
2475
|
}
|
|
2324
2476
|
|
|
2477
|
+
const currentGptAgentState = getAgentModelState(findAgentById(config, YYMAXAPI_OPENCLAW_GPT_AGENT_ID));
|
|
2325
2478
|
const gptAgentResult = upsertManagedAgent(agentList, {
|
|
2326
2479
|
id: YYMAXAPI_OPENCLAW_GPT_AGENT_ID,
|
|
2327
2480
|
default: false,
|
|
2328
2481
|
name: 'yunyi-gpt',
|
|
2329
|
-
model:
|
|
2330
|
-
primary: YYMAXAPI_OPENCLAW_GPT_PRIMARY,
|
|
2331
|
-
fallbacks: [YYMAXAPI_OPENCLAW_GPT_FALLBACK]
|
|
2332
|
-
}
|
|
2482
|
+
model: normalizeManagedYunyiModelState('codex', currentGptAgentState, options)
|
|
2333
2483
|
}, isManagedGptAgent);
|
|
2334
2484
|
if (gptAgentResult.changed) changed = true;
|
|
2335
2485
|
|
|
2336
2486
|
if (shouldManageYunyiDefaults(config)) {
|
|
2337
|
-
const nextDefaultsModel =
|
|
2338
|
-
primary: YYMAXAPI_OPENCLAW_CLAUDE_PRIMARY,
|
|
2339
|
-
fallbacks: [YYMAXAPI_OPENCLAW_GPT_PRIMARY]
|
|
2340
|
-
};
|
|
2487
|
+
const nextDefaultsModel = normalizeManagedYunyiDefaultsModel(config.agents.defaults.model, options);
|
|
2341
2488
|
if (JSON.stringify(config.agents.defaults.model) !== JSON.stringify(nextDefaultsModel)) {
|
|
2342
2489
|
config.agents.defaults.model = nextDefaultsModel;
|
|
2343
2490
|
changed = true;
|
|
@@ -5097,7 +5244,8 @@ async function switchModel(paths) {
|
|
|
5097
5244
|
|
|
5098
5245
|
const config = ensureConfigStructure(readConfig(paths.openclawConfig) || {});
|
|
5099
5246
|
applyConfigRepairsWithSync(config, paths);
|
|
5100
|
-
|
|
5247
|
+
applyManagedYunyiOpenClawLayout(config);
|
|
5248
|
+
let primary = config.agents?.defaults?.model?.primary || '';
|
|
5101
5249
|
const providers = config.models?.providers || {};
|
|
5102
5250
|
|
|
5103
5251
|
if (Object.keys(providers).length === 0) {
|
|
@@ -5195,6 +5343,7 @@ async function switchModel(paths) {
|
|
|
5195
5343
|
}]);
|
|
5196
5344
|
|
|
5197
5345
|
let finalSelected = selected;
|
|
5346
|
+
let selectedAgentId = '';
|
|
5198
5347
|
|
|
5199
5348
|
if (selected === '__other__') {
|
|
5200
5349
|
if (otherModels.length === 0) {
|
|
@@ -5225,42 +5374,51 @@ async function switchModel(paths) {
|
|
|
5225
5374
|
return;
|
|
5226
5375
|
}
|
|
5227
5376
|
|
|
5228
|
-
|
|
5229
|
-
|
|
5230
|
-
|
|
5231
|
-
|
|
5232
|
-
|
|
5233
|
-
|
|
5234
|
-
|
|
5235
|
-
|
|
5236
|
-
|
|
5237
|
-
|
|
5238
|
-
|
|
5239
|
-
|
|
5240
|
-
|
|
5241
|
-
|
|
5242
|
-
|
|
5243
|
-
const
|
|
5244
|
-
|
|
5245
|
-
|
|
5246
|
-
|
|
5247
|
-
|
|
5248
|
-
|
|
5249
|
-
contextWindow:
|
|
5250
|
-
maxTokens:
|
|
5251
|
-
|
|
5252
|
-
|
|
5253
|
-
|
|
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
|
+
}
|
|
5254
5409
|
}
|
|
5255
|
-
}
|
|
5256
5410
|
|
|
5257
|
-
|
|
5258
|
-
|
|
5259
|
-
|
|
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
|
+
}
|
|
5260
5415
|
}
|
|
5416
|
+
|
|
5417
|
+
primary = finalSelected;
|
|
5261
5418
|
ensureGatewaySettings(config);
|
|
5262
5419
|
writeConfigWithSync(paths, config);
|
|
5263
5420
|
|
|
5421
|
+
const selectedProviderKey = finalSelected.split('/')[0];
|
|
5264
5422
|
const selectedProviderConfig = providers[selectedProviderKey];
|
|
5265
5423
|
const selectedLabel = PROVIDER_LABELS[selectedProviderKey] || selectedProviderKey;
|
|
5266
5424
|
console.log(chalk.green(`\n✅ 已切换到 ${finalSelected}`));
|
|
@@ -5286,7 +5444,7 @@ async function switchModel(paths) {
|
|
|
5286
5444
|
|
|
5287
5445
|
// 重启后直接测试连接
|
|
5288
5446
|
console.log('');
|
|
5289
|
-
await testConnection(paths, {});
|
|
5447
|
+
await testConnection(paths, selectedAgentId ? { agent: selectedAgentId } : {});
|
|
5290
5448
|
}
|
|
5291
5449
|
// ============ 权限管理 (tools.profile) ============
|
|
5292
5450
|
const TOOLS_PROFILES = [
|