yymaxapi 1.0.10 → 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.
- package/bin/yymaxapi.js +120 -9
- 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) {
|
|
@@ -874,16 +938,21 @@ function resolveCliBinary() {
|
|
|
874
938
|
}
|
|
875
939
|
|
|
876
940
|
const candidates = ['openclaw', 'clawdbot', 'moltbot'];
|
|
941
|
+
const isWin = process.platform === 'win32';
|
|
877
942
|
const searchDirs = (process.env.PATH || '').split(path.delimiter).concat(EXTRA_BIN_DIRS);
|
|
878
943
|
for (const name of candidates) {
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
if (
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
944
|
+
// Windows: 优先找 .cmd 版本(原生可执行),再找无扩展名版本
|
|
945
|
+
const nameVariants = isWin ? [`${name}.cmd`, name] : [name];
|
|
946
|
+
for (const variant of nameVariants) {
|
|
947
|
+
for (const dir of searchDirs) {
|
|
948
|
+
if (!dir) continue;
|
|
949
|
+
const full = path.join(dir, variant);
|
|
950
|
+
try {
|
|
951
|
+
if (fs.existsSync(full) && fs.statSync(full).isFile() && isRealCli(full)) {
|
|
952
|
+
return full;
|
|
953
|
+
}
|
|
954
|
+
} catch {}
|
|
955
|
+
}
|
|
887
956
|
}
|
|
888
957
|
}
|
|
889
958
|
|
|
@@ -2215,6 +2284,12 @@ async function testConnection(paths, args = {}) {
|
|
|
2215
2284
|
try {
|
|
2216
2285
|
execSync('taskkill /F /FI "IMAGENAME eq node.exe" /FI "STATUS eq Not Responding" 2>nul', { stdio: 'ignore' });
|
|
2217
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
|
+
}
|
|
2218
2293
|
} else {
|
|
2219
2294
|
// Unix: 杀掉所有 openclaw/clawdbot/moltbot agent 子进程(排除 gateway)
|
|
2220
2295
|
for (const name of ['openclaw', 'clawdbot', 'moltbot']) {
|
|
@@ -2366,8 +2441,44 @@ async function testConnection(paths, args = {}) {
|
|
|
2366
2441
|
|
|
2367
2442
|
// ============ 重启 Gateway ============
|
|
2368
2443
|
async function restartGateway() {
|
|
2369
|
-
console.log(chalk.cyan('\n
|
|
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
|
+
}
|
|
2370
2480
|
|
|
2481
|
+
async function restartGatewayNative() {
|
|
2371
2482
|
const { cliBinary: resolved, nodeMajor } = getCliMeta();
|
|
2372
2483
|
const nodeInfo = findCompatibleNode(nodeMajor);
|
|
2373
2484
|
const env = { ...process.env, PATH: extendPathEnv(nodeInfo ? nodeInfo.path : null) };
|