openclawsetup 2.8.13 → 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 +60 -6
  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';
@@ -818,11 +819,43 @@ function detectExistingInstall() {
818
819
  const clawdbotDir = join(home, '.clawdbot');
819
820
 
820
821
  if (existsSync(openclawDir) || existsSync(clawdbotDir)) {
821
- // Prefer the CLI that matches the config directory to avoid cross-config issues
822
- // e.g. if config is in ~/.clawdbot, prefer 'clawdbot' CLI (reads ~/.clawdbot/clawdbot.json)
823
- // if config is in ~/.openclaw, prefer 'openclaw' CLI (reads ~/.openclaw/openclaw.json)
824
- const configDir = existsSync(openclawDir) ? openclawDir : clawdbotDir;
825
- const preferredCli = existsSync(openclawDir) ? 'openclaw' : 'clawdbot';
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
+
826
859
  const cliName = findWorkingCliName(preferredCli);
827
860
  if (cliName) {
828
861
  return { installed: true, configDir, name: cliName };
@@ -1110,13 +1143,34 @@ function hasListeningState(output = '') {
1110
1143
 
1111
1144
  function gatewayHealthRequest(port, path = '/health') {
1112
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 */ }
1113
1154
  const curlCmd = `curl -sS --max-time 5 --connect-timeout 2 ${endpoint}`;
1114
1155
  return safeExec(curlCmd, { timeout: 7000 });
1115
1156
  }
1116
1157
 
1117
1158
  function gatewayHttpStatusProbe(port, path = '/v1/responses') {
1118
1159
  const endpoint = `http://127.0.0.1:${port}${path}`;
1119
- 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}`;
1120
1174
  const result = safeExec(cmd, { timeout: 7000 });
1121
1175
  if (!result.ok || !result.output) {
1122
1176
  return { ok: false, status: 0 };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openclawsetup",
3
- "version": "2.8.13",
3
+ "version": "2.8.14",
4
4
  "description": "OpenClaw 安装向导 - 智能安装、诊断、自动修复",
5
5
  "type": "module",
6
6
  "bin": {