yymaxapi 1.0.82 → 1.0.83

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 +53 -18
  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
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yymaxapi",
3
- "version": "1.0.82",
3
+ "version": "1.0.83",
4
4
  "description": "跨平台 OpenClaw/Clawdbot 配置管理工具 - 管理中转地址、模型切换、API Keys、测速优化",
5
5
  "main": "bin/yymaxapi.js",
6
6
  "bin": {