yymaxapi 1.0.11 → 1.0.12

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 +107 -1
  2. package/package.json +1 -1
package/bin/yymaxapi.js CHANGED
@@ -552,6 +552,70 @@ function syncClawdbotConfigs(paths, config) {
552
552
  function writeConfigWithSync(paths, config) {
553
553
  writeConfig(paths.openclawConfig, config);
554
554
  syncClawdbotConfigs(paths, config);
555
+ syncToWsl(paths.openclawConfig);
556
+ }
557
+
558
+ // ============ WSL 检测与同步 ============
559
+ let _wslDetected = null;
560
+
561
+ function isWslAvailable() {
562
+ if (process.platform !== 'win32') return false;
563
+ if (_wslDetected !== null) return _wslDetected;
564
+ try {
565
+ const r = execFileSync('wsl', ['--status'], { encoding: 'utf8', timeout: 5000, stdio: 'pipe' });
566
+ _wslDetected = true;
567
+ } catch {
568
+ // wsl --status 可能返回非零但 WSL 仍可用,检查 wsl.exe 是否存在
569
+ try {
570
+ execFileSync('wsl', ['echo', 'ok'], { encoding: 'utf8', timeout: 5000, stdio: 'pipe' });
571
+ _wslDetected = true;
572
+ } catch {
573
+ _wslDetected = false;
574
+ }
575
+ }
576
+ return _wslDetected;
577
+ }
578
+
579
+ function getWslHome() {
580
+ try {
581
+ const home = execFileSync('wsl', ['bash', '-c', 'echo $HOME'], { encoding: 'utf8', timeout: 5000 }).trim();
582
+ return home || null;
583
+ } catch { return null; }
584
+ }
585
+
586
+ function isGatewayInWsl(port = 18789) {
587
+ if (!isWslAvailable()) return false;
588
+ try {
589
+ // 检查占用 gateway 端口的进程是否是 wslrelay
590
+ const r = safeExec(`netstat -ano | findstr ":${port}"`, { timeout: 5000 });
591
+ if (!r.ok || !r.output) return false;
592
+ const lines = r.output.split('\n').filter(l => l.includes('LISTENING'));
593
+ for (const line of lines) {
594
+ const pid = line.trim().split(/\s+/).pop();
595
+ if (pid) {
596
+ const taskR = safeExec(`tasklist /FI "PID eq ${pid}" /FO CSV /NH`, { timeout: 5000 });
597
+ if (taskR.ok && taskR.output && taskR.output.toLowerCase().includes('wslrelay')) {
598
+ return true;
599
+ }
600
+ }
601
+ }
602
+ } catch {}
603
+ return false;
604
+ }
605
+
606
+ function syncToWsl(windowsConfigPath) {
607
+ if (!isWslAvailable()) return;
608
+ try {
609
+ const wslHome = getWslHome();
610
+ if (!wslHome) return;
611
+ // 将 Windows 路径转为 WSL /mnt/c/ 路径
612
+ const winNorm = windowsConfigPath.replace(/\\/g, '/');
613
+ const match = winNorm.match(/^([A-Za-z]):\/(.*)/);
614
+ if (!match) return;
615
+ const wslSrc = `/mnt/${match[1].toLowerCase()}/${match[2]}`;
616
+ const wslDest = `${wslHome}/.openclaw/openclaw.json`;
617
+ execFileSync('wsl', ['bash', '-c', `mkdir -p "${wslHome}/.openclaw" && cp "${wslSrc}" "${wslDest}"`], { timeout: 10000, stdio: 'ignore' });
618
+ } catch { /* ignore - WSL sync is best-effort */ }
555
619
  }
556
620
 
557
621
  function coerceModelsRecord(value) {
@@ -2220,6 +2284,12 @@ async function testConnection(paths, args = {}) {
2220
2284
  try {
2221
2285
  execSync('taskkill /F /FI "IMAGENAME eq node.exe" /FI "STATUS eq Not Responding" 2>nul', { stdio: 'ignore' });
2222
2286
  } catch { /* ignore */ }
2287
+ // WSL 内的 agent 进程也要清理
2288
+ if (isWslAvailable()) {
2289
+ try {
2290
+ execSync('wsl -- bash -c "pkill -f \'openclaw.*agent\' 2>/dev/null; pkill -f \'clawdbot.*agent\' 2>/dev/null; pkill -f \'moltbot.*agent\' 2>/dev/null; true"', { stdio: 'ignore', timeout: 10000 });
2291
+ } catch { /* ignore */ }
2292
+ }
2223
2293
  } else {
2224
2294
  // Unix: 杀掉所有 openclaw/clawdbot/moltbot agent 子进程(排除 gateway)
2225
2295
  for (const name of ['openclaw', 'clawdbot', 'moltbot']) {
@@ -2371,8 +2441,44 @@ async function testConnection(paths, args = {}) {
2371
2441
 
2372
2442
  // ============ 重启 Gateway ============
2373
2443
  async function restartGateway() {
2374
- console.log(chalk.cyan('\n🔄 正在重启 OpenClaw Gateway...'));
2444
+ console.log(chalk.cyan('\n正在重启 OpenClaw Gateway...'));
2445
+
2446
+ const gatewayPort = 18789;
2447
+ const gwInWsl = isGatewayInWsl(gatewayPort);
2448
+
2449
+ // 如果 Gateway 在 WSL 里,优先用 wsl -- 重启
2450
+ if (gwInWsl) {
2451
+ console.log(chalk.gray(' [检测] Gateway 运行在 WSL 中'));
2452
+ return new Promise((resolve) => {
2453
+ const wslCmds = [
2454
+ 'wsl -- bash -c "openclaw gateway restart"',
2455
+ 'wsl -- bash -c "clawdbot gateway restart"',
2456
+ 'wsl -- bash -c "moltbot gateway restart"',
2457
+ ];
2458
+ let tried = 0;
2459
+ const tryNext = () => {
2460
+ if (tried >= wslCmds.length) {
2461
+ console.log(chalk.yellow('⚠ WSL 内 Gateway 重启失败,尝试 Windows 原生重启...'));
2462
+ restartGatewayNative().then(resolve);
2463
+ return;
2464
+ }
2465
+ const cmd = wslCmds[tried++];
2466
+ exec(cmd, { timeout: 30000 }, (error) => {
2467
+ if (error) { tryNext(); }
2468
+ else {
2469
+ console.log(chalk.green('✅ Gateway 已重启 (WSL)'));
2470
+ resolve();
2471
+ }
2472
+ });
2473
+ };
2474
+ tryNext();
2475
+ });
2476
+ }
2477
+
2478
+ return restartGatewayNative();
2479
+ }
2375
2480
 
2481
+ async function restartGatewayNative() {
2376
2482
  const { cliBinary: resolved, nodeMajor } = getCliMeta();
2377
2483
  const nodeInfo = findCompatibleNode(nodeMajor);
2378
2484
  const env = { ...process.env, PATH: extendPathEnv(nodeInfo ? nodeInfo.path : null) };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yymaxapi",
3
- "version": "1.0.11",
3
+ "version": "1.0.12",
4
4
  "description": "跨平台 OpenClaw/Clawdbot 配置管理工具 - 管理中转地址、模型切换、API Keys、测速优化",
5
5
  "main": "bin/yymaxapi.js",
6
6
  "bin": {