yymaxapi 1.0.82 → 1.0.84

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 +57 -22
  2. package/package.json +1 -1
package/bin/yymaxapi.js CHANGED
@@ -636,6 +636,28 @@ function getWslMirrorInfo() {
636
636
  return { configPath, authProfiles };
637
637
  }
638
638
 
639
+ function getGatewayListenOwner(port = 18789) {
640
+ if (process.platform === 'win32') return null;
641
+
642
+ const lsofResult = safeExec(`lsof -nP -iTCP:${port} -sTCP:LISTEN -F u 2>/dev/null`, { timeout: 3000 });
643
+ const lsofOutput = [lsofResult.output, lsofResult.stdout, lsofResult.stderr].filter(Boolean).join('\n');
644
+ const userLine = lsofOutput
645
+ .split('\n')
646
+ .map(line => line.trim())
647
+ .find(line => line.startsWith('u'));
648
+ if (userLine && userLine.length > 1) {
649
+ return userLine.slice(1).trim() || null;
650
+ }
651
+
652
+ const pidResult = safeExec(`lsof -ti :${port} 2>/dev/null | head -n1`, { timeout: 3000 });
653
+ const pid = pidResult.ok ? pidResult.output.trim().split('\n')[0] : '';
654
+ if (!/^\d+$/.test(pid)) return null;
655
+
656
+ const ownerResult = safeExec(`ps -o user= -p ${pid} 2>/dev/null`, { timeout: 3000 });
657
+ if (!ownerResult.ok || !ownerResult.output) return null;
658
+ return ownerResult.output.trim().split(/\s+/)[0] || null;
659
+ }
660
+
639
661
  function getConfigPath() {
640
662
  const homeDir = os.homedir();
641
663
  const openclawStateDir = process.env.OPENCLAW_STATE_DIR || path.join(homeDir, '.openclaw');
@@ -664,23 +686,34 @@ function getConfigPath() {
664
686
 
665
687
  const candidates = [];
666
688
  if (envConfig) candidates.push(envConfig);
667
- if (preferMoltbot) {
668
- candidates.push(...moltbotCandidates, ...openclawCandidates);
669
- } else {
670
- candidates.push(...openclawCandidates, ...moltbotCandidates);
671
- }
689
+ const rootCandidates = [];
690
+ let preferRootConfig = false;
691
+
692
+ const preferredCandidates = preferMoltbot
693
+ ? [...moltbotCandidates, ...openclawCandidates]
694
+ : [...openclawCandidates, ...moltbotCandidates];
672
695
 
673
696
  // Fallback: 当前用户非 root 时,也检查 /root 下的配置(OpenClaw 常以 root 安装)
674
697
  if (process.platform !== 'win32' && homeDir !== '/root') {
675
698
  const rootOpenclawDir = '/root/.openclaw';
676
699
  const rootClawdbotDir = '/root/.clawdbot';
677
- candidates.push(
700
+ rootCandidates.push(
678
701
  path.join(rootOpenclawDir, 'openclaw.json'),
679
702
  path.join(rootOpenclawDir, 'moltbot.json'),
680
703
  path.join(rootClawdbotDir, 'openclaw.json'),
681
704
  path.join(rootClawdbotDir, 'clawdbot.json'),
682
705
  path.join(rootClawdbotDir, 'moltbot.json')
683
706
  );
707
+
708
+ const rootConfigExists = rootCandidates.some(p => p && fs.existsSync(p));
709
+ const gatewayOwner = getGatewayListenOwner();
710
+ preferRootConfig = rootConfigExists && gatewayOwner === 'root';
711
+ }
712
+
713
+ if (preferRootConfig) {
714
+ candidates.push(...rootCandidates, ...preferredCandidates);
715
+ } else {
716
+ candidates.push(...preferredCandidates, ...rootCandidates);
684
717
  }
685
718
 
686
719
  // Windows + WSL: 尝试读取 WSL 内的配置文件
@@ -714,18 +747,6 @@ function getConfigPath() {
714
747
 
715
748
  const configDir = path.dirname(openclawConfig);
716
749
 
717
- const baseAuthCandidates = buildAuthCandidates([openclawStateDir, clawdbotStateDir]);
718
- const moltbotAuthCandidates = buildAuthCandidates(moltbotStateDirs);
719
-
720
- const authCandidates = preferMoltbot
721
- ? [...moltbotAuthCandidates, ...baseAuthCandidates]
722
- : [...baseAuthCandidates, ...moltbotAuthCandidates];
723
-
724
- const authProfiles = authCandidates.find(p => fs.existsSync(p)) || authCandidates[0];
725
- const authSyncTargets = process.platform === 'win32'
726
- ? [...new Set(buildAuthCandidates([openclawStateDir, clawdbotStateDir]))].filter(p => p !== authProfiles)
727
- : [];
728
-
729
750
  const syncTargets = [];
730
751
  if (openclawConfig.startsWith(openclawStateDir) && fs.existsSync(clawdbotStateDir)) {
731
752
  syncTargets.push(
@@ -734,6 +755,20 @@ function getConfigPath() {
734
755
  );
735
756
  }
736
757
 
758
+ const primaryAuthBases = [configDir];
759
+ const secondaryAuthBases = preferMoltbot
760
+ ? [...moltbotStateDirs, openclawStateDir, clawdbotStateDir]
761
+ : [openclawStateDir, clawdbotStateDir, ...moltbotStateDirs];
762
+ const authCandidates = [...new Set(buildAuthCandidates([...primaryAuthBases, ...secondaryAuthBases]))];
763
+
764
+ const authProfiles = authCandidates.find(p => fs.existsSync(p)) || authCandidates[0];
765
+
766
+ const authSyncBaseDirs = syncTargets.map(target => path.dirname(target));
767
+ if (process.platform === 'win32') {
768
+ authSyncBaseDirs.push(openclawStateDir, clawdbotStateDir);
769
+ }
770
+ const authSyncTargets = [...new Set(buildAuthCandidates(authSyncBaseDirs))].filter(p => p !== authProfiles);
771
+
737
772
  return { openclawConfig, authProfiles, configDir, syncTargets, authSyncTargets, wslConfigPath, wslAuthProfiles };
738
773
  }
739
774
 
@@ -3826,7 +3861,7 @@ async function autoActivate(paths, args = {}) {
3826
3861
  const gwToken = config.gateway?.auth?.token;
3827
3862
  if (gwToken) {
3828
3863
  console.log(chalk.green(`\n🌐 Web Dashboard:`));
3829
- console.log(chalk.cyan(` http://127.0.0.1:${gwPort}/?token=${gwToken}`));
3864
+ console.log(chalk.cyan(` http://127.0.0.1:${gwPort}/#token=${gwToken}`));
3830
3865
  }
3831
3866
 
3832
3867
  // ---- 配置完成后:测试连接 or 退出 ----
@@ -5070,7 +5105,7 @@ async function testConnection(paths, args = {}) {
5070
5105
  console.log(chalk.cyan(` CLI 对话正常,Gateway 可达`));
5071
5106
  console.log(chalk.gray(` 注: Gateway Dashboard 通过 WebSocket 通信,REST 端点返回 405 属正常现象`));
5072
5107
  console.log(chalk.green(`\n🌐 Web Dashboard 访问地址:`));
5073
- console.log(chalk.cyan(` http://127.0.0.1:${gatewayPort}/?token=${gatewayToken}`));
5108
+ console.log(chalk.cyan(` http://127.0.0.1:${gatewayPort}/#token=${gatewayToken}`));
5074
5109
  } else if (result.success) {
5075
5110
  console.log(chalk.green(`\n✅ Gateway 测试成功!Web Dashboard 可正常使用`));
5076
5111
  console.log(chalk.cyan(` 响应时间: ${latency}ms`));
@@ -5081,7 +5116,7 @@ async function testConnection(paths, args = {}) {
5081
5116
  });
5082
5117
  console.log(chalk.yellow(` 模型回复: ${reply}`));
5083
5118
  console.log(chalk.green(`\n🌐 Web Dashboard 访问地址:`));
5084
- console.log(chalk.cyan(` http://127.0.0.1:${gatewayPort}/?token=${gatewayToken}`));
5119
+ console.log(chalk.cyan(` http://127.0.0.1:${gatewayPort}/#token=${gatewayToken}`));
5085
5120
  } else {
5086
5121
  if (result.reachable) {
5087
5122
  console.log(chalk.yellow(`\n⚠ Gateway HTTP 可达,但接口返回限制`));
@@ -5095,7 +5130,7 @@ async function testConnection(paths, args = {}) {
5095
5130
  console.log(chalk.yellow(` 这通常会导致 Dashboard 网页对话返回 401。`));
5096
5131
  console.log(chalk.gray(`\n 建议操作:`));
5097
5132
  console.log(chalk.gray(` 1) 复制最新地址并重新打开浏览器(不要用旧书签)`));
5098
- console.log(chalk.cyan(` http://127.0.0.1:${gatewayPort}/?token=${gatewayToken}`));
5133
+ console.log(chalk.cyan(` http://127.0.0.1:${gatewayPort}/#token=${gatewayToken}`));
5099
5134
  console.log(chalk.gray(` 2) 执行 Gateway 重启:openclaw gateway restart / clawdbot gateway restart`));
5100
5135
  console.log(chalk.gray(` 3) 若仍 401,检查是否存在多个配置目录(.openclaw 与 .clawdbot)`));
5101
5136
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yymaxapi",
3
- "version": "1.0.82",
3
+ "version": "1.0.84",
4
4
  "description": "跨平台 OpenClaw/Clawdbot 配置管理工具 - 管理中转地址、模型切换、API Keys、测速优化",
5
5
  "main": "bin/yymaxapi.js",
6
6
  "bin": {