openclawsetup 2.8.12 → 2.8.14

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/cli.mjs +85 -16
  2. package/package.json +1 -1
package/bin/cli.mjs CHANGED
@@ -21,6 +21,7 @@ import {
21
21
  renameSync,
22
22
  mkdirSync,
23
23
  writeFileSync,
24
+ statSync,
24
25
  } from 'fs';
25
26
  import { createServer } from 'net';
26
27
  import { homedir, platform, arch, release, hostname } from 'os';
@@ -521,7 +522,7 @@ async function collectEvidencePackage(options = {}) {
521
522
 
522
523
  const snapshot = gatherEnvironmentSnapshot();
523
524
  const tokenOptimizationPreview = createTokenOptimizationPlan();
524
- const cliName = snapshot.openclaw.detectedInstall?.name || findWorkingCliName() || 'openclaw';
525
+ const cliName = snapshot.openclaw.detectedInstall?.name || findWorkingCliName(snapshot.openclaw.configDir?.includes('.clawdbot') ? 'clawdbot' : undefined) || 'openclaw';
525
526
 
526
527
  const captures = {
527
528
  doctor: runCmdCapture(`${cliName} doctor`, quick ? 20000 : 90000),
@@ -697,9 +698,9 @@ ${colors.cyan('安装后配置模型:')}
697
698
  npx openclawapi@latest # 交互式配置
698
699
 
699
700
  ${colors.cyan('常见问题快速修复:')}
700
- Gateway 未启动: openclaw gateway start
701
+ Gateway 未启动: openclaw gateway start (或 clawdbot gateway start)
701
702
  端口被占用: openclaw config set gateway.port 18790
702
- 配置文件损坏: rm ~/.openclaw/openclaw.json && openclaw onboard
703
+ 配置文件损坏: 重新运行 npx openclawsetup@latest
703
704
  `);
704
705
  }
705
706
 
@@ -796,8 +797,17 @@ function isRealGatewayCli(name) {
796
797
  return true;
797
798
  }
798
799
 
799
- function findWorkingCliName() {
800
- for (const name of ['openclaw', 'clawdbot', 'moltbot']) {
800
+ function findWorkingCliName(preferredName) {
801
+ const candidates = ['openclaw', 'clawdbot', 'moltbot'];
802
+ // If a preferred name is given (e.g. matching the config dir), check it first
803
+ if (preferredName) {
804
+ const reordered = [preferredName, ...candidates.filter(n => n !== preferredName)];
805
+ for (const name of reordered) {
806
+ if (isRealGatewayCli(name)) return name;
807
+ }
808
+ return null;
809
+ }
810
+ for (const name of candidates) {
801
811
  if (isRealGatewayCli(name)) return name;
802
812
  }
803
813
  return null;
@@ -809,13 +819,49 @@ function detectExistingInstall() {
809
819
  const clawdbotDir = join(home, '.clawdbot');
810
820
 
811
821
  if (existsSync(openclawDir) || existsSync(clawdbotDir)) {
812
- const configDir = existsSync(openclawDir) ? openclawDir : clawdbotDir;
813
- const cliName = findWorkingCliName();
822
+ // Determine which config dir has an actual config file (not just an empty directory)
823
+ const hasOpenclawConfig = existsSync(join(openclawDir, 'openclaw.json'));
824
+ const hasClawdbotConfig = existsSync(join(clawdbotDir, 'clawdbot.json'));
825
+
826
+ let configDir;
827
+ let preferredCli;
828
+
829
+ if (hasClawdbotConfig && !hasOpenclawConfig) {
830
+ // Only clawdbot has a real config — prefer clawdbot
831
+ configDir = clawdbotDir;
832
+ preferredCli = 'clawdbot';
833
+ } else if (hasOpenclawConfig && !hasClawdbotConfig) {
834
+ // Only openclaw has a real config — prefer openclaw
835
+ configDir = openclawDir;
836
+ preferredCli = 'openclaw';
837
+ } else if (hasClawdbotConfig && hasOpenclawConfig) {
838
+ // Both have configs — prefer the one modified more recently
839
+ try {
840
+ const ocStat = statSync(join(openclawDir, 'openclaw.json'));
841
+ const cbStat = statSync(join(clawdbotDir, 'clawdbot.json'));
842
+ if (cbStat.mtimeMs >= ocStat.mtimeMs) {
843
+ configDir = clawdbotDir;
844
+ preferredCli = 'clawdbot';
845
+ } else {
846
+ configDir = openclawDir;
847
+ preferredCli = 'openclaw';
848
+ }
849
+ } catch {
850
+ configDir = clawdbotDir;
851
+ preferredCli = 'clawdbot';
852
+ }
853
+ } else {
854
+ // Neither has a config file — just pick whichever dir exists
855
+ configDir = existsSync(openclawDir) ? openclawDir : clawdbotDir;
856
+ preferredCli = existsSync(openclawDir) ? 'openclaw' : 'clawdbot';
857
+ }
858
+
859
+ const cliName = findWorkingCliName(preferredCli);
814
860
  if (cliName) {
815
861
  return { installed: true, configDir, name: cliName };
816
862
  }
817
863
  // Config dir exists but no working CLI found
818
- return { installed: true, configDir, name: existsSync(openclawDir) ? 'openclaw' : 'clawdbot', cliMissing: true };
864
+ return { installed: true, configDir, name: preferredCli, cliMissing: true };
819
865
  }
820
866
 
821
867
  const cliName = findWorkingCliName();
@@ -1097,13 +1143,34 @@ function hasListeningState(output = '') {
1097
1143
 
1098
1144
  function gatewayHealthRequest(port, path = '/health') {
1099
1145
  const endpoint = `http://127.0.0.1:${port}${path}`;
1146
+ // Try Node.js native fetch first (available in Node 18+), then fall back to curl
1147
+ try {
1148
+ const result = execSync(
1149
+ `node -e "fetch('${endpoint}',{signal:AbortSignal.timeout(4000)}).then(r=>r.text()).then(t=>process.stdout.write(t)).catch(()=>process.exit(1))"`,
1150
+ { timeout: 7000, encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'] },
1151
+ );
1152
+ if (result) return { ok: true, output: result };
1153
+ } catch { /* fall through to curl */ }
1100
1154
  const curlCmd = `curl -sS --max-time 5 --connect-timeout 2 ${endpoint}`;
1101
1155
  return safeExec(curlCmd, { timeout: 7000 });
1102
1156
  }
1103
1157
 
1104
1158
  function gatewayHttpStatusProbe(port, path = '/v1/responses') {
1105
1159
  const endpoint = `http://127.0.0.1:${port}${path}`;
1106
- const cmd = `curl -sS -o /dev/null -w "%{http_code}" --max-time 5 --connect-timeout 2 ${endpoint}`;
1160
+ // Try Node.js native fetch first (avoids Windows cmd.exe % escaping issues with curl)
1161
+ try {
1162
+ const result = execSync(
1163
+ `node -e "fetch('${endpoint}',{signal:AbortSignal.timeout(4000)}).then(r=>{process.stdout.write(String(r.status));process.exit(0)}).catch(()=>process.exit(1))"`,
1164
+ { timeout: 7000, encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'] },
1165
+ );
1166
+ const status = Number(result);
1167
+ if (Number.isInteger(status) && status > 0) {
1168
+ return { ok: true, status };
1169
+ }
1170
+ } catch { /* fall through to curl */ }
1171
+ // Fallback: curl (on Windows, escape % for cmd.exe)
1172
+ const fmt = platform() === 'win32' ? '%%{http_code}' : '%{http_code}';
1173
+ const cmd = `curl -sS -o ${platform() === 'win32' ? 'NUL' : '/dev/null'} -w "${fmt}" --max-time 5 --connect-timeout 2 ${endpoint}`;
1107
1174
  const result = safeExec(cmd, { timeout: 7000 });
1108
1175
  if (!result.ok || !result.output) {
1109
1176
  return { ok: false, status: 0 };
@@ -1696,7 +1763,7 @@ function showInstallGuide() {
1696
1763
  console.log(colors.bold(colors.cyan(' 📖 OpenClaw 安装指引')));
1697
1764
  console.log(colors.bold(colors.cyan('='.repeat(60))));
1698
1765
 
1699
- console.log(colors.yellow('\n接下来会运行官方 openclaw onboard 命令'));
1766
+ console.log(colors.yellow('\n接下来会运行官方 onboard 命令'));
1700
1767
  console.log(colors.yellow('自动模式会按以下推荐选择(可随时接管):\n'));
1701
1768
 
1702
1769
  console.log(colors.cyan('┌─────────────────────────────────────────────────────────┐'));
@@ -1910,7 +1977,7 @@ async function runOnboard(cliName) {
1910
1977
  console.log(colors.bold(colors.cyan('\n[2/2] 运行配置向导\n')));
1911
1978
 
1912
1979
  console.log(colors.gray('-'.repeat(60)));
1913
- console.log(colors.gray('以下是官方 openclaw onboard 界面:'));
1980
+ console.log(colors.gray('以下是官方 onboard 界面:'));
1914
1981
  console.log(colors.gray('-'.repeat(60) + '\n'));
1915
1982
 
1916
1983
  const manualResult = runOnboardManual(cliName);
@@ -2269,7 +2336,7 @@ function showCompletionInfo(cliName) {
2269
2336
  console.log(colors.cyan('\n下一步 - 配置 AI 模型(必须):'));
2270
2337
  console.log(` ${colors.yellow('npx openclawapi@latest preset-claude')}`);
2271
2338
 
2272
- showDashboardAccessInfo();
2339
+ showDashboardAccessInfo(cliName);
2273
2340
 
2274
2341
  console.log(colors.cyan('\n常用命令:'));
2275
2342
  console.log(` 查看状态: ${colors.yellow(`${cliName} status`)}`);
@@ -2284,12 +2351,14 @@ function showCompletionInfo(cliName) {
2284
2351
  console.log('');
2285
2352
  }
2286
2353
 
2287
- function showDashboardAccessInfo() {
2354
+ function showDashboardAccessInfo(cliName) {
2288
2355
  const config = getConfigInfo();
2289
2356
  const port = config.port || 18789;
2290
2357
  const tokenRaw = getDashboardToken(config) || '<你的token>';
2291
2358
  const tokenMasked = maskToken(tokenRaw);
2292
2359
  const dashboardUrl = `http://127.0.0.1:${port}/?token=${tokenMasked}`;
2360
+ const activeCli = cliName || (config.configPath?.includes('.clawdbot') ? 'clawdbot' : 'openclaw');
2361
+ const configFileName = config.configPath || `~/.${activeCli}/${activeCli}.json`;
2293
2362
 
2294
2363
  if (detectVps()) {
2295
2364
  const serverIp = getServerIp() || '<服务器IP>';
@@ -2305,10 +2374,10 @@ function showDashboardAccessInfo() {
2305
2374
  console.log(` ${colors.green(dashboardUrl)}`);
2306
2375
  console.log('');
2307
2376
  console.log(colors.yellow(' 方式二:直接暴露端口(不推荐,有安全风险)'));
2308
- console.log(colors.gray(' 1. 修改配置文件 ~/.openclaw/openclaw.json'));
2377
+ console.log(colors.gray(` 1. 修改配置文件 ${configFileName}`));
2309
2378
  console.log(colors.gray(' 将 "bind": "loopback" 改为 "bind": "all"'));
2310
2379
  console.log(colors.gray(` 2. 在云服务器控制台开放端口 ${port}`));
2311
- console.log(colors.gray(' 3. 重启 Gateway:openclaw gateway restart'));
2380
+ console.log(colors.gray(` 3. 重启 Gateway:${activeCli} gateway restart`));
2312
2381
  console.log(colors.gray(` 4. 访问:http://${serverIp}:${port}/?token=...`));
2313
2382
  } else {
2314
2383
  console.log(colors.cyan('\nDashboard 访问:'));
@@ -2960,7 +3029,7 @@ async function showInteractiveMenu(existing) {
2960
3029
  console.log(colors.bold(colors.cyan(' 🦞 OpenClaw 管理菜单')));
2961
3030
  console.log(colors.bold(colors.cyan('='.repeat(50))));
2962
3031
 
2963
- showDashboardAccessInfo();
3032
+ showDashboardAccessInfo(cliName);
2964
3033
 
2965
3034
  console.log(colors.cyan('\n请选择操作:'));
2966
3035
  console.log(` ${colors.yellow('1')}. 状态信息`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openclawsetup",
3
- "version": "2.8.12",
3
+ "version": "2.8.14",
4
4
  "description": "OpenClaw 安装向导 - 智能安装、诊断、自动修复",
5
5
  "type": "module",
6
6
  "bin": {