yymaxapi 1.0.85 → 1.0.86

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 +92 -19
  2. package/package.json +1 -1
package/bin/yymaxapi.js CHANGED
@@ -2025,6 +2025,53 @@ function getAgentModelState(agent) {
2025
2025
  return { primary, fallbacks };
2026
2026
  }
2027
2027
 
2028
+ function findAgentById(config, agentId) {
2029
+ if (!Array.isArray(config?.agents?.list) || !agentId) return null;
2030
+ return config.agents.list.find(agent => agent && typeof agent === 'object' && agent.id === agentId) || null;
2031
+ }
2032
+
2033
+ function resolveOpenClawTestTarget(config, args = {}) {
2034
+ const requestedAgentId = String(args.agent || args['agent-id'] || '').trim();
2035
+ const requestedAgent = requestedAgentId ? findAgentById(config, requestedAgentId) : null;
2036
+ const defaultPrimary = String(config?.agents?.defaults?.model?.primary || '').trim();
2037
+ const defaultFallbacks = Array.isArray(config?.agents?.defaults?.model?.fallbacks)
2038
+ ? [...config.agents.defaults.model.fallbacks]
2039
+ : [];
2040
+
2041
+ let primary = defaultPrimary;
2042
+ let fallbacks = defaultFallbacks;
2043
+ let agentId = null;
2044
+ let agentName = '';
2045
+
2046
+ if (requestedAgent) {
2047
+ const agentState = getAgentModelState(requestedAgent);
2048
+ if (agentState.primary) {
2049
+ primary = agentState.primary;
2050
+ fallbacks = agentState.fallbacks;
2051
+ agentId = requestedAgent.id;
2052
+ agentName = String(requestedAgent.name || '').trim();
2053
+ }
2054
+ }
2055
+
2056
+ const providerName = primary.includes('/') ? primary.split('/')[0] : '';
2057
+ const provider = providerName ? (config.models?.providers?.[providerName] || null) : null;
2058
+ const apiType = provider?.api || '';
2059
+ const typeLabel = apiType.startsWith('anthropic')
2060
+ ? 'Claude'
2061
+ : (apiType.startsWith('openai') ? 'Codex' : '模型');
2062
+
2063
+ return {
2064
+ agentId,
2065
+ agentName,
2066
+ primary,
2067
+ fallbacks,
2068
+ providerName,
2069
+ provider,
2070
+ typeLabel,
2071
+ defaultPrimary
2072
+ };
2073
+ }
2074
+
2028
2075
  function hasManagedYunyiFootprint(config) {
2029
2076
  const providers = config?.models?.providers || {};
2030
2077
  if (Object.entries(providers).some(([name, provider]) => isYunyiProviderEntry(name, provider, 'claude') || isYunyiProviderEntry(name, provider, 'codex'))) {
@@ -2103,6 +2150,18 @@ function buildManagedYunyiProviderConfig(type, endpointUrl, apiKey, existingProv
2103
2150
  return next;
2104
2151
  }
2105
2152
 
2153
+ function buildGatewayAgentSubcommand({ sessionId, agentId, message = '请回复你的模型名称' }) {
2154
+ const agentArg = agentId ? ` --agent ${shellQuote(agentId)}` : '';
2155
+ return `agent${agentArg} --session-id ${shellQuote(sessionId)} --message ${shellQuote(message)} --json --timeout 120`;
2156
+ }
2157
+
2158
+ function buildGatewayAgentCliCommand({ cliBinary, nodeInfo, useNode, sessionId, agentId, message = '请回复你的模型名称' }) {
2159
+ const subcommand = buildGatewayAgentSubcommand({ sessionId, agentId, message });
2160
+ return useNode
2161
+ ? `${shellQuote(nodeInfo.path)} ${shellQuote(cliBinary)} ${subcommand}`
2162
+ : `${shellQuote(cliBinary)} ${subcommand}`;
2163
+ }
2164
+
2106
2165
  function ensureAgentList(config) {
2107
2166
  if (!config.agents) config.agents = {};
2108
2167
  if (!Array.isArray(config.agents.list)) config.agents.list = [];
@@ -4308,7 +4367,10 @@ async function autoActivate(paths, args = {}) {
4308
4367
  }]);
4309
4368
 
4310
4369
  if (nextAction === 'test') {
4311
- await testConnection(paths, args);
4370
+ const selectedOpenClawAgentId = isClaudePrimary
4371
+ ? (yunyiLayoutResult.claudeAgentId || YYMAXAPI_OPENCLAW_MAIN_AGENT_ID)
4372
+ : YYMAXAPI_OPENCLAW_GPT_AGENT_ID;
4373
+ await testConnection(paths, { ...args, agent: selectedOpenClawAgentId });
4312
4374
  } else {
4313
4375
  console.log(chalk.cyan('👋 再见!\n'));
4314
4376
  process.exit(0);
@@ -4866,7 +4928,9 @@ async function main() {
4866
4928
  // 获取当前配置状态摘要
4867
4929
  function getConfigStatusLine(paths) {
4868
4930
  try {
4869
- const config = readConfig(paths.openclawConfig);
4931
+ const config = ensureConfigStructure(readConfig(paths.openclawConfig) || {});
4932
+ applyConfigRepairsWithSync(config, paths);
4933
+ applyManagedYunyiOpenClawLayout(config);
4870
4934
  if (!config?.models?.providers) return null;
4871
4935
 
4872
4936
  const providers = Object.keys(config.models.providers);
@@ -5343,30 +5407,28 @@ async function testConnection(paths, args = {}) {
5343
5407
 
5344
5408
  const config = ensureConfigStructure(readConfig(paths.openclawConfig) || {});
5345
5409
  applyConfigRepairsWithSync(config, paths);
5410
+ applyManagedYunyiOpenClawLayout(config);
5346
5411
 
5347
5412
  if (!config || !config.models) {
5348
5413
  console.log(chalk.yellow('配置文件不存在,请先选择节点'));
5349
5414
  return;
5350
5415
  }
5351
5416
 
5352
- // 检查当前激活的是哪个
5353
- let primary = config.agents?.defaults?.model?.primary || '';
5417
+ const testTarget = resolveOpenClawTestTarget(config, args);
5418
+ const primary = testTarget.primary;
5354
5419
  if (!primary.includes('/')) {
5355
5420
  console.log(chalk.yellow('⚠️ 主模型未设置,请先通过「切换 OpenClaw 模型」或「一键配置」设置主模型'));
5356
5421
  return;
5357
5422
  }
5358
5423
 
5359
- const providerName = primary.split('/')[0];
5360
- const provider = config.models?.providers?.[providerName];
5424
+ const providerName = testTarget.providerName;
5425
+ const provider = testTarget.provider;
5361
5426
  if (!provider) {
5362
5427
  console.log(chalk.yellow(`⚠️ 主模型对应的中转站不存在: ${providerName}`));
5363
5428
  return;
5364
5429
  }
5365
5430
 
5366
- const apiType = provider.api || '';
5367
- const typeLabel = apiType.startsWith('anthropic')
5368
- ? 'Claude'
5369
- : (apiType.startsWith('openai') ? 'Codex' : '模型');
5431
+ const typeLabel = testTarget.typeLabel;
5370
5432
 
5371
5433
  if (!provider.apiKey) {
5372
5434
  console.log(chalk.yellow(`⚠️ ${typeLabel} API Key 未设置`));
@@ -5376,7 +5438,13 @@ async function testConnection(paths, args = {}) {
5376
5438
  // 获取 Gateway 配置
5377
5439
  const gatewayPort = config.gateway?.port || 18789;
5378
5440
 
5379
- console.log(chalk.gray(`当前激活: ${typeLabel}`));
5441
+ console.log(chalk.gray(`当前测试: ${typeLabel}`));
5442
+ if (testTarget.agentId) {
5443
+ console.log(chalk.gray(`测试入口: ${testTarget.agentId}${testTarget.agentName ? ` (${testTarget.agentName})` : ''}`));
5444
+ }
5445
+ if (testTarget.agentId && testTarget.defaultPrimary && testTarget.defaultPrimary !== primary) {
5446
+ console.log(chalk.gray(`默认主入口: ${testTarget.defaultPrimary}`));
5447
+ }
5380
5448
  console.log(chalk.gray(`中转节点: ${provider.baseUrl}`));
5381
5449
  console.log(chalk.gray(`模型: ${primary}`));
5382
5450
  console.log(chalk.gray(`Gateway: http://127.0.0.1:${gatewayPort}\n`));
@@ -5452,7 +5520,7 @@ async function testConnection(paths, args = {}) {
5452
5520
  console.log(chalk.cyan(`\n步骤 2/2: 测试 Gateway API 端点...`));
5453
5521
 
5454
5522
  try {
5455
- const cliResult = await testGatewayViaAgent(primary);
5523
+ const cliResult = await testGatewayViaAgent(primary, testTarget.agentId);
5456
5524
  let cliPassed = false;
5457
5525
 
5458
5526
  if (cliResult.usedCli) {
@@ -5477,7 +5545,7 @@ async function testConnection(paths, args = {}) {
5477
5545
  console.log(chalk.red(` 期望: ${primary}`));
5478
5546
  console.log(chalk.cyan(` 实际: ${actualModelKey}`));
5479
5547
  console.log(chalk.gray(` 这意味着 ${primary} 无法正常工作,请检查该模型的中转配置`));
5480
- const configuredFallbacks = config.agents?.defaults?.model?.fallbacks || [];
5548
+ const configuredFallbacks = testTarget.fallbacks || [];
5481
5549
  if (configuredFallbacks.length > 0 && !configuredFallbacks.includes(actualModelKey)) {
5482
5550
  console.log(chalk.yellow(` ⚠️ 实际回退模型不在当前配置的 fallbacks 中,疑似读到了另一份配置`));
5483
5551
  console.log(chalk.gray(` 当前 fallbacks: ${configuredFallbacks.join(', ')}`));
@@ -5968,7 +6036,7 @@ function testGatewayApi(port, token, model, endpoint = '/v1/chat/completions') {
5968
6036
  });
5969
6037
  }
5970
6038
 
5971
- function testGatewayViaAgent(model) {
6039
+ function testGatewayViaAgent(model, agentId = '') {
5972
6040
  return new Promise((resolve) => {
5973
6041
  const gwEnv = detectGatewayEnv();
5974
6042
  const sessionId = `yymaxapi-test-${Date.now()}`;
@@ -5979,11 +6047,12 @@ function testGatewayViaAgent(model) {
5979
6047
  if (gwEnv === 'wsl') {
5980
6048
  // Gateway 在 WSL 中,agent 也要在 WSL 中执行
5981
6049
  const wslCli = getWslCliBinary();
6050
+ const subcommand = buildGatewayAgentSubcommand({ sessionId, agentId });
5982
6051
  if (wslCli) {
5983
- const agentCmd = `${wslCli} agent --session-id ${sessionId} --message "请回复你的模型名称" --json --timeout 120`;
6052
+ const agentCmd = `${wslCli} ${subcommand}`;
5984
6053
  cmd = `wsl -- bash -c '${agentCmd.replace(/'/g, "'\\''")}'`;
5985
6054
  } else {
5986
- const agentCmd = `openclaw agent --session-id ${sessionId} --message "请回复你的模型名称" --json --timeout 120 2>/dev/null || clawdbot agent --session-id ${sessionId} --message "请回复你的模型名称" --json --timeout 120 2>/dev/null || moltbot agent --session-id ${sessionId} --message "请回复你的模型名称" --json --timeout 120`;
6055
+ const agentCmd = `openclaw ${subcommand} 2>/dev/null || clawdbot ${subcommand} 2>/dev/null || moltbot ${subcommand}`;
5987
6056
  cmd = `wsl -- bash -lc '${agentCmd.replace(/'/g, "'\\''")}'`;
5988
6057
  }
5989
6058
  execOpts = { timeout: 120000 };
@@ -6001,9 +6070,13 @@ function testGatewayViaAgent(model) {
6001
6070
  delete env.OPENAI_API_KEY;
6002
6071
  delete env.OPENCLAW_CODEX_KEY;
6003
6072
  const useNode = nodeInfo && isNodeShebang(cliBinary);
6004
- cmd = useNode
6005
- ? `"${nodeInfo.path}" "${cliBinary}" agent --session-id ${sessionId} --message "请回复你的模型名称" --json --timeout 120`
6006
- : `"${cliBinary}" agent --session-id ${sessionId} --message "请回复你的模型名称" --json --timeout 120`;
6073
+ cmd = buildGatewayAgentCliCommand({
6074
+ cliBinary,
6075
+ nodeInfo,
6076
+ useNode,
6077
+ sessionId,
6078
+ agentId
6079
+ });
6007
6080
  execOpts = { timeout: 120000, env };
6008
6081
  }
6009
6082
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yymaxapi",
3
- "version": "1.0.85",
3
+ "version": "1.0.86",
4
4
  "description": "跨平台 OpenClaw/Clawdbot 配置管理工具 - 管理中转地址、模型切换、API Keys、测速优化",
5
5
  "main": "bin/yymaxapi.js",
6
6
  "bin": {