openclawsetup 2.8.0 → 2.8.2

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/README.md CHANGED
@@ -100,7 +100,7 @@ npx openclawsetup@latest --check --strong
100
100
  - 官方 `doctor --fix` + onboard 深度回收
101
101
  - 模型连通性探测(检测到异常会给出明确修复入口)
102
102
 
103
- 管理菜单也提供 `9. 强力检查修复`。
103
+ 管理菜单也提供 `3. 强力检查修复`。
104
104
 
105
105
  ## Token 优化(降低每次输入 token)
106
106
 
package/bin/cli.mjs CHANGED
@@ -83,6 +83,9 @@ const log = {
83
83
 
84
84
  const DEFAULT_GATEWAY_PORT = 18789;
85
85
  const STRONG_FIX_MAX_PASSES = 3;
86
+ const STATUS_CMD_TIMEOUT_MS = platform() === 'win32' ? 8000 : 5000;
87
+ const PORT_CHECK_TIMEOUT_MS = platform() === 'win32' ? 6000 : 4000;
88
+ const MODEL_CHAT_TIMEOUT_MS = platform() === 'win32' ? 25000 : 18000;
86
89
  const STRONG_PORT_CANDIDATES = [
87
90
  18789,
88
91
  18790,
@@ -863,18 +866,18 @@ function parseStatusOutput(statusOutput) {
863
866
  return 'unknown';
864
867
  }
865
868
 
866
- function getPortCheckOutput(port) {
869
+ function getPortCheckOutput(port, timeout = PORT_CHECK_TIMEOUT_MS) {
867
870
  const cmd = platform() === 'win32'
868
871
  ? `netstat -ano | findstr :${port}`
869
872
  : `lsof -nP -iTCP:${port} -sTCP:LISTEN 2>/dev/null || netstat -tlnp 2>/dev/null | grep :${port}`;
870
- return safeExec(cmd);
873
+ return safeExec(cmd, { timeout });
871
874
  }
872
875
 
873
- function getPortConflictDetail(port) {
876
+ function getPortConflictDetail(port, timeout = PORT_CHECK_TIMEOUT_MS) {
874
877
  const cmd = platform() === 'win32'
875
878
  ? `netstat -ano | findstr :${port} | findstr LISTENING`
876
879
  : `lsof -nP -iTCP:${port} -sTCP:LISTEN 2>/dev/null | head -8`;
877
- return safeExec(cmd);
880
+ return safeExec(cmd, { timeout });
878
881
  }
879
882
 
880
883
  function isLikelyOpenClawProcess(output = '') {
@@ -2288,10 +2291,12 @@ async function runHealthCheck(cliName, autoFix = false, strongMode = false) {
2288
2291
 
2289
2292
  // ============ 交互式菜单 ============
2290
2293
 
2291
- function testModelChat(cliName) {
2294
+ function testModelChat(cliName, timeoutMs = MODEL_CHAT_TIMEOUT_MS) {
2292
2295
  return new Promise((resolve) => {
2293
- const cmd = `${cliName} agent --session-id openclawsetup-test --message "请用一句话回复你的模型名称" --json --timeout 60`;
2294
- exec(cmd, { timeout: 65000 }, (error, stdout, stderr) => {
2296
+ const agentTimeoutSec = Math.max(12, Math.floor(timeoutMs / 1000));
2297
+ const execTimeoutMs = Math.max(15000, timeoutMs + 5000);
2298
+ const cmd = `${cliName} agent --session-id openclawsetup-test --message "请用一句话回复你的模型名称" --json --timeout ${agentTimeoutSec}`;
2299
+ exec(cmd, { timeout: execTimeoutMs }, (error, stdout, stderr) => {
2295
2300
  if (error) {
2296
2301
  const errMsg = (stderr || stdout || error.message || '').trim();
2297
2302
  // 提取关键错误信息
@@ -2337,25 +2342,57 @@ async function showStatusInfo(cliName) {
2337
2342
  const dashboardUrl = `http://127.0.0.1:${port}/?token=${token}`;
2338
2343
 
2339
2344
  console.log(colors.bold(colors.cyan('\n📊 OpenClaw 状态信息\n')));
2345
+ console.log(colors.gray(' … 正在检查服务状态(超时自动跳过)...'));
2340
2346
 
2341
- // 服务状态
2342
- const statusResult = safeExec(`${cliName} status`);
2343
- const output = statusResult.ok ? statusResult.output : '';
2344
- const isRunning = output.toLowerCase().includes('running') || output.toLowerCase().includes('active');
2347
+ // 服务状态(兼容不同 CLI 版本,避免 Windows 下误判)
2348
+ const statusAttempts = [
2349
+ { cmd: `${cliName} status`, label: 'status' },
2350
+ { cmd: `${cliName} gateway status`, label: 'gateway status' },
2351
+ ];
2352
+ let statusState = 'unknown';
2353
+ let statusOutput = '';
2354
+ let statusTimedOut = false;
2355
+
2356
+ for (const attempt of statusAttempts) {
2357
+ const statusResult = safeExec(attempt.cmd, { timeout: STATUS_CMD_TIMEOUT_MS });
2358
+ if (!statusResult.ok && /timed out|etimedout|SIGTERM|killed/i.test(`${statusResult.error || ''} ${statusResult.stderr || ''}`)) {
2359
+ statusTimedOut = true;
2360
+ continue;
2361
+ }
2362
+ if (!statusResult.ok || !statusResult.output) continue;
2363
+ statusOutput = statusResult.output;
2364
+ const parsed = parseStatusOutput(statusResult.output);
2365
+ if (parsed === 'running') {
2366
+ statusState = 'running';
2367
+ break;
2368
+ }
2369
+ if (parsed === 'stopped') {
2370
+ statusState = 'stopped';
2371
+ }
2372
+ }
2373
+
2374
+ // 端口检查(作为状态命令兜底)
2375
+ const portResult = getPortCheckOutput(port, PORT_CHECK_TIMEOUT_MS);
2376
+ const portListening = Boolean(portResult.ok && portResult.output);
2345
2377
 
2346
- if (isRunning) {
2378
+ if (statusTimedOut) {
2379
+ console.log(colors.yellow(' ⚠ 状态命令超时,已自动切换端口探测模式'));
2380
+ }
2381
+
2382
+ if (statusState === 'running') {
2347
2383
  console.log(colors.green(' ✓ Gateway 服务正在运行'));
2384
+ } else if (portListening) {
2385
+ console.log(colors.yellow(' ⚠ 状态命令显示未运行,但端口可访问'));
2386
+ console.log(colors.gray(' 兼容模式判定:Gateway 可能正在运行(常见于旧版/Windows)'));
2348
2387
  } else {
2349
2388
  console.log(colors.red(' ✗ Gateway 服务未运行'));
2389
+ if (statusOutput) {
2390
+ console.log(colors.gray(` 状态输出: ${statusOutput.split('\n')[0].slice(0, 100)}`));
2391
+ }
2350
2392
  console.log(colors.yellow(' → 请先选择「检查修复」自动修复此问题\n'));
2351
2393
  return;
2352
2394
  }
2353
2395
 
2354
- // 端口检查
2355
- const portCmd = platform() === 'win32'
2356
- ? `netstat -an | findstr :${port}`
2357
- : `lsof -i :${port} 2>/dev/null || netstat -tlnp 2>/dev/null | grep :${port}`;
2358
- const portResult = safeExec(portCmd);
2359
2396
  if (portResult.ok && portResult.output) {
2360
2397
  console.log(colors.green(` ✓ 端口 ${port} 正在监听`));
2361
2398
  } else {
@@ -2391,8 +2428,8 @@ async function showStatusInfo(cliName) {
2391
2428
 
2392
2429
  // 模型对话测试
2393
2430
  if (primaryModel) {
2394
- console.log(colors.gray('正在测试模型对话...'));
2395
- const testResult = await testModelChat(cliName);
2431
+ console.log(colors.gray(`正在测试模型对话(最长 ${Math.floor(MODEL_CHAT_TIMEOUT_MS / 1000)} 秒)...`));
2432
+ const testResult = await testModelChat(cliName, MODEL_CHAT_TIMEOUT_MS);
2396
2433
  if (testResult.success) {
2397
2434
  console.log(colors.green(' ✓ 模型对话正常'));
2398
2435
  if (testResult.message) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openclawsetup",
3
- "version": "2.8.0",
3
+ "version": "2.8.2",
4
4
  "description": "OpenClaw 安装向导 - 智能安装、诊断、自动修复",
5
5
  "type": "module",
6
6
  "bin": {
@@ -141,7 +141,7 @@ npx openclawsetup@latest
141
141
  进入菜单后可直接选择:
142
142
 
143
143
  ```text
144
- 9. 强力检查修复(多轮深度修复)
144
+ 3. 强力检查修复(多轮深度修复)
145
145
  ```
146
146
 
147
147
  也可在菜单选择: