yymaxapi 1.0.119 → 1.0.121

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 +121 -9
  2. package/package.json +1 -1
package/bin/yymaxapi.js CHANGED
@@ -337,6 +337,12 @@ function resolveHermesModelType(modelId, preferredType = '') {
337
337
  return requestedType || 'claude';
338
338
  }
339
339
 
340
+ function getKnownModelName(modelId) {
341
+ const normalized = String(modelId || '').trim();
342
+ const model = [...CLAUDE_MODELS, ...CODEX_MODELS].find(item => item.id === normalized);
343
+ return model?.name || normalized || '未选择模型';
344
+ }
345
+
340
346
  async function promptHermesModelSelection(args = {}, message = '选择 Hermes 默认模型:') {
341
347
  const requestedModel = (args['model-id'] || args.model || '').toString().trim();
342
348
  const requestedType = normalizeHermesModelType(
@@ -3846,7 +3852,7 @@ function scoreHermesWslCandidate(candidate) {
3846
3852
  }
3847
3853
 
3848
3854
  function getHermesWslMirrorInfo(options = {}) {
3849
- if (process.platform !== 'win32' || !isWslAvailable()) {
3855
+ if (process.platform !== 'win32') {
3850
3856
  return {
3851
3857
  dataDir: null,
3852
3858
  sourceConfigPath: null,
@@ -3892,7 +3898,8 @@ function getHermesWslMirrorInfo(options = {}) {
3892
3898
  sourceConfigPath,
3893
3899
  configPath: candidate.configPath,
3894
3900
  envPath: candidate.envPath,
3895
- target: candidate.target
3901
+ target: candidate.target,
3902
+ commandPath: selected?.commandPath || probeHermesWslCommand(candidate.target)
3896
3903
  };
3897
3904
  }
3898
3905
 
@@ -4115,6 +4122,36 @@ function readHermesCliConfig() {
4115
4122
  };
4116
4123
  }
4117
4124
 
4125
+ function buildHermesCliConfigFromRaw(configRaw, envRaw, configPath = '', envPath = '') {
4126
+ const parsed = parseSimpleYamlConfig(configRaw);
4127
+ const envEntries = parseEnvFile(envRaw);
4128
+ const modelConfig = parsed?.model && typeof parsed.model === 'object' ? parsed.model : {};
4129
+ const modelId = String(modelConfig.default || '').trim() || getDefaultClaudeModel().id;
4130
+ const provider = String(modelConfig.provider || '').trim().toLowerCase();
4131
+ const type = resolveHermesModelType(modelId, provider);
4132
+ const apiKey = type === 'codex'
4133
+ ? (envEntries.OPENAI_API_KEY || '')
4134
+ : (envEntries.ANTHROPIC_API_KEY || envEntries.ANTHROPIC_TOKEN || '');
4135
+
4136
+ return {
4137
+ configPath,
4138
+ envPath,
4139
+ configured: !!configRaw || !!envRaw,
4140
+ modelId,
4141
+ provider,
4142
+ type,
4143
+ baseUrl: String(modelConfig.base_url || '').trim(),
4144
+ apiKey
4145
+ };
4146
+ }
4147
+
4148
+ function readHermesWslCliConfig(wslMirror = getHermesWslMirrorInfo()) {
4149
+ const configPath = wslMirror.sourceConfigPath || wslMirror.configPath;
4150
+ const configRaw = readWslTextFile(configPath, wslMirror.target);
4151
+ const envRaw = readWslTextFile(wslMirror.envPath, wslMirror.target);
4152
+ return buildHermesCliConfigFromRaw(configRaw, envRaw, configPath, wslMirror.envPath);
4153
+ }
4154
+
4118
4155
  function getOpencodeConfigPath() {
4119
4156
  const home = os.homedir();
4120
4157
  return process.platform === 'win32'
@@ -4374,6 +4411,9 @@ function testCodexCliConnection() {
4374
4411
 
4375
4412
  function testHermesCliConnection() {
4376
4413
  const cliBinary = resolveCommandBinary('hermes');
4414
+ if (!cliBinary && process.platform === 'win32') {
4415
+ return testHermesWslCliConnection();
4416
+ }
4377
4417
  if (!cliBinary) return { name: 'Hermes CLI', status: 'skipped', detail: '未安装 hermes 命令' };
4378
4418
 
4379
4419
  const config = readHermesCliConfig();
@@ -4419,6 +4459,40 @@ function testHermesCliConnection() {
4419
4459
  };
4420
4460
  }
4421
4461
 
4462
+ function testHermesWslCliConnection() {
4463
+ const wslMirror = getHermesWslMirrorInfo();
4464
+ const commandPath = wslMirror.commandPath || probeHermesWslCommand(wslMirror.target || {});
4465
+ if (!commandPath) return { name: 'Hermes CLI (WSL)', status: 'skipped', detail: '未检测到 WSL 内 hermes 命令' };
4466
+
4467
+ const config = readHermesWslCliConfig(wslMirror);
4468
+ if (!config.configured) return { name: 'Hermes CLI (WSL)', status: 'skipped', detail: '未检测到 WSL ~/.hermes/config.yaml 或 ~/.hermes/.env' };
4469
+ if (!config.apiKey) return { name: 'Hermes CLI (WSL)', status: 'failed', detail: 'Hermes 配置缺少 API Key' };
4470
+
4471
+ const providerArg = config.provider === 'anthropic' ? ' --provider anthropic' : '';
4472
+ const command = [
4473
+ `export HERMES_HOME=${shellQuote(wslMirror.dataDir)}`,
4474
+ 'export NODE_TLS_REJECT_UNAUTHORIZED=0',
4475
+ 'export NODE_NO_WARNINGS=1',
4476
+ 'set -a',
4477
+ `[ -f "$HERMES_HOME/.env" ] && . "$HERMES_HOME/.env"`,
4478
+ 'set +a',
4479
+ `${shellQuote(commandPath)} chat -Q -q ${shellQuote('请只回复 OK')}${providerArg}`
4480
+ ].join('; ');
4481
+ const result = runWslCommand(command, { timeout: 120000, maxBuffer: 1024 * 1024 }, { ...(wslMirror.target || {}), login: true });
4482
+ const combined = cleanCliTestOutput(`${result.output || ''}\n${result.stdout || ''}\n${result.stderr || ''}`);
4483
+ const reply = extractHermesCliReply(combined);
4484
+
4485
+ if (result.ok && /^OK$/i.test(reply) && !looksLikeCliTestError(combined)) {
4486
+ return { name: 'Hermes CLI (WSL)', status: 'success', detail: 'OK' };
4487
+ }
4488
+
4489
+ return {
4490
+ name: 'Hermes CLI (WSL)',
4491
+ status: 'failed',
4492
+ detail: reply || summarizeCliTestOutput(combined) || result.error || '命令执行失败'
4493
+ };
4494
+ }
4495
+
4422
4496
  async function testAdditionalCliConnections(args = {}, options = {}) {
4423
4497
  if (args['no-app-test'] || args.noAppTest) return;
4424
4498
 
@@ -5889,10 +5963,11 @@ async function activateHermes(paths, args = {}) {
5889
5963
  async function main() {
5890
5964
  console.clear();
5891
5965
 
5892
- console.log(chalk.cyan.bold('\n🔧 OpenClaw API 配置工具\n'));
5966
+ console.log(chalk.cyan.bold('\n🔧 yymaxapi 配置工具\n'));
5893
5967
 
5894
5968
  const paths = getConfigPath();
5895
- console.log(chalk.gray(`配置文件: ${paths.openclawConfig}\n`));
5969
+ console.log(chalk.gray(`OpenClaw 配置: ${paths.openclawConfig}`));
5970
+ console.log(chalk.gray(`Hermes 配置: ${getHermesConfigPath()}\n`));
5896
5971
 
5897
5972
  // 首次运行备份
5898
5973
  if (backupOriginalConfig(paths.openclawConfig, paths.configDir)) {
@@ -5931,10 +6006,15 @@ async function main() {
5931
6006
 
5932
6007
  while (true) {
5933
6008
  // 显示当前状态
5934
- const statusLine = getConfigStatusLine(paths);
5935
- if (statusLine) {
6009
+ const statusLines = [
6010
+ getConfigStatusLine(paths),
6011
+ getHermesStatusLine()
6012
+ ].filter(Boolean);
6013
+ if (statusLines.length > 0) {
5936
6014
  console.log(chalk.gray('─'.repeat(40)));
5937
- console.log(statusLine);
6015
+ for (const statusLine of statusLines) {
6016
+ console.log(statusLine);
6017
+ }
5938
6018
  console.log(chalk.gray('─'.repeat(40)) + '\n');
5939
6019
  }
5940
6020
 
@@ -6057,7 +6137,7 @@ function getConfigStatusLine(paths) {
6057
6137
  }
6058
6138
 
6059
6139
  if (parts.length === 0 && otherCount === 0) {
6060
- return chalk.gray('当前状态: 未配置任何模型');
6140
+ return chalk.gray('OpenClaw: 未配置任何模型');
6061
6141
  }
6062
6142
 
6063
6143
  const primaryModelId = primary.split('/')[1] || '';
@@ -6065,7 +6145,39 @@ function getConfigStatusLine(paths) {
6065
6145
 
6066
6146
  const gwEnv = detectGatewayEnv();
6067
6147
  const envTag = gwEnv === 'wsl' ? chalk.cyan(' [WSL]') : '';
6068
- return chalk.gray('当前状态: ') + parts.join(' ') + chalk.gray(' (✓ 主模型 ○ 已配置)') + modelTag + envTag;
6148
+ return chalk.gray('OpenClaw: ') + parts.join(' ') + chalk.gray(' (✓ 主模型 ○ 已配置)') + modelTag + envTag;
6149
+ } catch {
6150
+ return null;
6151
+ }
6152
+ }
6153
+
6154
+ function getHermesStatusLine() {
6155
+ try {
6156
+ let config = readHermesCliConfig();
6157
+ let wslMirror = null;
6158
+
6159
+ if (process.platform === 'win32') {
6160
+ wslMirror = getHermesWslMirrorInfo();
6161
+ if (!config.configured && (wslMirror.configPath || wslMirror.envPath)) {
6162
+ config = readHermesWslCliConfig(wslMirror);
6163
+ }
6164
+ }
6165
+
6166
+ if (!config.configured) return null;
6167
+
6168
+ const modelName = getKnownModelName(config.modelId);
6169
+ const readyMark = config.apiKey ? chalk.green('✓') : chalk.yellow('○');
6170
+ const modelTag = config.modelId ? chalk.cyan(` [模型: ${config.modelId}]`) : '';
6171
+ const protocolTag = config.type === 'codex' ? chalk.cyan(' [GPT]') : chalk.cyan(' [Claude]');
6172
+ const hasWslTarget = !!(wslMirror?.sourceConfigPath || wslMirror?.commandPath);
6173
+ let envTag = '';
6174
+ if (hasWslTarget && wslMirror?.target?.user) {
6175
+ envTag = chalk.cyan(` [WSL ${wslMirror.target.user}]`);
6176
+ } else if (hasWslTarget) {
6177
+ envTag = chalk.cyan(' [WSL]');
6178
+ }
6179
+
6180
+ return chalk.gray('Hermes-Agent: ') + chalk.green(`${modelName} ${readyMark}`) + protocolTag + modelTag + envTag;
6069
6181
  } catch {
6070
6182
  return null;
6071
6183
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yymaxapi",
3
- "version": "1.0.119",
3
+ "version": "1.0.121",
4
4
  "description": "跨平台 OpenClaw/Clawdbot 配置管理工具 - 管理中转地址、模型切换、API Keys、测速优化",
5
5
  "main": "bin/yymaxapi.js",
6
6
  "bin": {