openclawsetup 2.8.13 → 2.8.15

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 +63 -12
  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 };
@@ -936,10 +969,7 @@ function getDashboardToken(config) {
936
969
  }
937
970
 
938
971
  function maskToken(token = '') {
939
- if (!token || token === '<未配置>' || token === '<你的token>') return token;
940
- const text = String(token);
941
- if (text.length <= 8) return '***';
942
- return `${text.slice(0, 4)}...${text.slice(-4)}`;
972
+ return token;
943
973
  }
944
974
 
945
975
  function parseStatusOutput(statusOutput) {
@@ -1110,13 +1140,34 @@ function hasListeningState(output = '') {
1110
1140
 
1111
1141
  function gatewayHealthRequest(port, path = '/health') {
1112
1142
  const endpoint = `http://127.0.0.1:${port}${path}`;
1143
+ // Try Node.js native fetch first (available in Node 18+), then fall back to curl
1144
+ try {
1145
+ const result = execSync(
1146
+ `node -e "fetch('${endpoint}',{signal:AbortSignal.timeout(4000)}).then(r=>r.text()).then(t=>process.stdout.write(t)).catch(()=>process.exit(1))"`,
1147
+ { timeout: 7000, encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'] },
1148
+ );
1149
+ if (result) return { ok: true, output: result };
1150
+ } catch { /* fall through to curl */ }
1113
1151
  const curlCmd = `curl -sS --max-time 5 --connect-timeout 2 ${endpoint}`;
1114
1152
  return safeExec(curlCmd, { timeout: 7000 });
1115
1153
  }
1116
1154
 
1117
1155
  function gatewayHttpStatusProbe(port, path = '/v1/responses') {
1118
1156
  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}`;
1157
+ // Try Node.js native fetch first (avoids Windows cmd.exe % escaping issues with curl)
1158
+ try {
1159
+ const result = execSync(
1160
+ `node -e "fetch('${endpoint}',{signal:AbortSignal.timeout(4000)}).then(r=>{process.stdout.write(String(r.status));process.exit(0)}).catch(()=>process.exit(1))"`,
1161
+ { timeout: 7000, encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'] },
1162
+ );
1163
+ const status = Number(result);
1164
+ if (Number.isInteger(status) && status > 0) {
1165
+ return { ok: true, status };
1166
+ }
1167
+ } catch { /* fall through to curl */ }
1168
+ // Fallback: curl (on Windows, escape % for cmd.exe)
1169
+ const fmt = platform() === 'win32' ? '%%{http_code}' : '%{http_code}';
1170
+ const cmd = `curl -sS -o ${platform() === 'win32' ? 'NUL' : '/dev/null'} -w "${fmt}" --max-time 5 --connect-timeout 2 ${endpoint}`;
1120
1171
  const result = safeExec(cmd, { timeout: 7000 });
1121
1172
  if (!result.ok || !result.output) {
1122
1173
  return { ok: false, status: 0 };
@@ -1824,7 +1875,7 @@ function buildOnboardArgsFromHelp(helpText, options) {
1824
1875
  return { args, enabled, autoCapable };
1825
1876
  }
1826
1877
 
1827
- function getOnboardCommand(cliName, onboardArgs = ['onboard', '--install-daemon']) {
1878
+ function getOnboardCommand(cliName, onboardArgs = ['onboard']) {
1828
1879
  if (platform() === 'win32') {
1829
1880
  return { file: 'cmd.exe', args: ['/c', cliName, ...onboardArgs] };
1830
1881
  }
@@ -2324,7 +2375,7 @@ function showDashboardAccessInfo(cliName) {
2324
2375
  console.log(colors.gray(' 将 "bind": "loopback" 改为 "bind": "all"'));
2325
2376
  console.log(colors.gray(` 2. 在云服务器控制台开放端口 ${port}`));
2326
2377
  console.log(colors.gray(` 3. 重启 Gateway:${activeCli} gateway restart`));
2327
- console.log(colors.gray(` 4. 访问:http://${serverIp}:${port}/?token=...`));
2378
+ console.log(colors.gray(` 4. 访问:http://${serverIp}:${port}/?token=${tokenRaw}`));
2328
2379
  } else {
2329
2380
  console.log(colors.cyan('\nDashboard 访问:'));
2330
2381
  console.log(` ${colors.yellow(dashboardUrl)}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openclawsetup",
3
- "version": "2.8.13",
3
+ "version": "2.8.15",
4
4
  "description": "OpenClaw 安装向导 - 智能安装、诊断、自动修复",
5
5
  "type": "module",
6
6
  "bin": {