lobstakit-cloud 1.3.8 → 1.3.9

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/lib/gateway.js +40 -24
  2. package/package.json +1 -1
package/lib/gateway.js CHANGED
@@ -40,40 +40,56 @@ function isSystemdAvailable() {
40
40
  return _systemdAvailable;
41
41
  }
42
42
 
43
- // PM2 fallback for non-systemd environments
44
- const PM2_NAME = 'openclaw-gateway';
45
- function pm2Start() {
43
+ // Detached-spawn fallback for non-systemd/container environments (no PM2 needed)
44
+ const { spawn } = require('child_process');
45
+ const GATEWAY_PID_FILE = path.join(os.homedir(), '.openclaw', 'gateway.pid');
46
+ const GATEWAY_LOG_FILE = path.join(os.homedir(), '.openclaw', 'gateway-spawn.log');
47
+
48
+ function spawnedStart() {
46
49
  try {
47
- // Stop any existing instance first
48
- try { execSync(`pm2 delete ${PM2_NAME} 2>/dev/null`, { encoding: 'utf8', timeout: 10000 }); } catch {}
49
- execSync(`pm2 start openclaw --name ${PM2_NAME} -- gateway`, { encoding: 'utf8', timeout: 30000 });
50
- execSync('pm2 save', { encoding: 'utf8', timeout: 10000 });
50
+ // Kill any previously spawned gateway
51
+ spawnedStop();
52
+ // Resolve openclaw binary
53
+ let bin = 'openclaw';
54
+ try { bin = execSync('which openclaw', { encoding: 'utf8', timeout: 3000 }).trim(); } catch {}
55
+ const logFd = require('fs').openSync(GATEWAY_LOG_FILE, 'a');
56
+ const child = spawn(bin, ['gateway'], {
57
+ detached: true,
58
+ stdio: ['ignore', logFd, logFd],
59
+ env: { ...process.env },
60
+ });
61
+ child.unref();
62
+ fs.writeFileSync(GATEWAY_PID_FILE, String(child.pid));
63
+ console.log(`[gateway] Spawned gateway PID ${child.pid} (no-systemd mode)`);
51
64
  return { success: true };
52
65
  } catch (err) {
53
66
  return { success: false, error: err.message };
54
67
  }
55
68
  }
56
- function pm2Stop() {
69
+ function spawnedStop() {
57
70
  try {
58
- execSync(`pm2 stop ${PM2_NAME}`, { encoding: 'utf8', timeout: 10000 });
71
+ if (!fs.existsSync(GATEWAY_PID_FILE)) return { success: true };
72
+ const pid = parseInt(fs.readFileSync(GATEWAY_PID_FILE, 'utf8').trim(), 10);
73
+ if (pid) {
74
+ try { process.kill(pid, 'SIGTERM'); } catch {}
75
+ }
76
+ fs.unlinkSync(GATEWAY_PID_FILE);
59
77
  return { success: true };
60
78
  } catch (err) {
61
79
  return { success: false, error: err.message };
62
80
  }
63
81
  }
64
- function pm2Restart() {
65
- try {
66
- try { execSync(`pm2 restart ${PM2_NAME}`, { encoding: 'utf8', timeout: 15000 }); }
67
- catch { pm2Start(); } // restart fails if not running — start fresh
68
- return { success: true };
69
- } catch (err) {
70
- return { success: false, error: err.message };
71
- }
82
+ function spawnedRestart() {
83
+ spawnedStop();
84
+ return spawnedStart();
72
85
  }
73
- function pm2IsRunning() {
86
+ function spawnedIsRunning() {
74
87
  try {
75
- const out = execSync(`pm2 list 2>/dev/null`, { encoding: 'utf8', timeout: 5000 });
76
- return out.includes(PM2_NAME) && out.includes('online');
88
+ if (!fs.existsSync(GATEWAY_PID_FILE)) return false;
89
+ const pid = parseInt(fs.readFileSync(GATEWAY_PID_FILE, 'utf8').trim(), 10);
90
+ if (!pid) return false;
91
+ process.kill(pid, 0); // throws if process doesn't exist
92
+ return true;
77
93
  } catch { return false; }
78
94
  }
79
95
 
@@ -168,7 +184,7 @@ function pingGateway(token) {
168
184
  function isGatewayRunning() {
169
185
  // Primary: systemctl --user (accurate for user services) OR PM2 in container envs
170
186
  if (!isSystemdAvailable()) {
171
- if (pm2IsRunning()) return true;
187
+ if (spawnedIsRunning()) return true;
172
188
  // Fall through to HTTP check
173
189
  } else {
174
190
  try {
@@ -247,7 +263,7 @@ function startGateway() {
247
263
  ensureUserSession();
248
264
  if (!isSystemdAvailable()) {
249
265
  console.log('[gateway] systemd unavailable — using PM2 fallback');
250
- const result = pm2Start();
266
+ const result = spawnedStart();
251
267
  if (result.success) setTimeout(() => syncGatewayToken(), 4000);
252
268
  return result;
253
269
  }
@@ -272,7 +288,7 @@ function startGateway() {
272
288
  function stopGateway() {
273
289
  if (!isSystemdAvailable()) {
274
290
  console.log('[gateway] systemd unavailable — using PM2 fallback');
275
- return pm2Stop();
291
+ return spawnedStop();
276
292
  }
277
293
  try {
278
294
  execSync(`systemctl --user stop ${SERVICE_NAME}`, { encoding: 'utf8', timeout: 15000, env: userEnv() });
@@ -288,7 +304,7 @@ function restartGateway() {
288
304
  ensureUserSession();
289
305
  if (!isSystemdAvailable()) {
290
306
  console.log('[gateway] systemd unavailable — using PM2 fallback');
291
- const result = pm2Restart();
307
+ const result = spawnedRestart();
292
308
  if (result.success) setTimeout(() => syncGatewayToken(), 4000);
293
309
  return result;
294
310
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lobstakit-cloud",
3
- "version": "1.3.8",
3
+ "version": "1.3.9",
4
4
  "description": "LobstaKit Cloud — Setup wizard and management for LobstaCloud gateways",
5
5
  "main": "server.js",
6
6
  "bin": {