traderclaw-cli 1.0.126 → 1.0.127

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.
@@ -342,6 +342,7 @@ function buildCommandString(cmd, args = []) {
342
342
 
343
343
  function isPrivilegeError(err) {
344
344
  const text = `${err?.message || ""}\n${err?.stderr || ""}\n${err?.stdout || ""}`.toLowerCase();
345
+ // Do not match bare "sudo" — OpenClaw prints "try sudo loginctl" in hints; that is not a priv-denied signal.
345
346
  return (
346
347
  text.includes("permission denied")
347
348
  || text.includes("eacces")
@@ -349,7 +350,8 @@ function isPrivilegeError(err) {
349
350
  || text.includes("operation not permitted")
350
351
  || text.includes("must be root")
351
352
  || text.includes("requires root")
352
- || text.includes("sudo")
353
+ || text.includes("sudo: a password is required")
354
+ || text.includes("a terminal is required to read the password")
353
355
  || text.includes("authentication is required")
354
356
  );
355
357
  }
@@ -367,6 +369,16 @@ function canUseSudoWithoutPrompt() {
367
369
  }
368
370
  }
369
371
 
372
+ /** User systemd (openclaw gateway) expects XDG_RUNTIME_DIR under /run/user/<uid> once linger is on. */
373
+ function primeLinuxUserRuntimeEnv() {
374
+ if (process.platform !== "linux" || typeof process.getuid !== "function") return;
375
+ const uid = process.getuid();
376
+ if (uid === 0) return;
377
+ if (!process.env.XDG_RUNTIME_DIR) {
378
+ process.env.XDG_RUNTIME_DIR = `/run/user/${uid}`;
379
+ }
380
+ }
381
+
370
382
  function tailscalePermissionRemediation() {
371
383
  return [
372
384
  "Tailscale requires elevated permissions on this host.",
@@ -2307,11 +2319,33 @@ export class InstallerStepEngine {
2307
2319
  }
2308
2320
 
2309
2321
  async runWithPrivilegeGuidance(stepId, cmd, args = [], customLines = []) {
2322
+ primeLinuxUserRuntimeEnv();
2323
+ const onEvent = (evt) =>
2324
+ this.emitLog(stepId, evt.type === "stderr" ? "warn" : "info", evt.text, evt.urls || []);
2325
+ const tryRun = (c, a) => runCommandWithEvents(c, a, { onEvent });
2326
+
2310
2327
  try {
2311
- return await runCommandWithEvents(cmd, args, {
2312
- onEvent: (evt) => this.emitLog(stepId, evt.type === "stderr" ? "warn" : "info", evt.text, evt.urls || []),
2313
- });
2328
+ return await tryRun(cmd, args);
2314
2329
  } catch (err) {
2330
+ const sudoOpenclawGateway =
2331
+ cmd === "openclaw" &&
2332
+ Array.isArray(args) &&
2333
+ args[0] === "gateway" &&
2334
+ !isRootUser() &&
2335
+ canUseSudoWithoutPrompt();
2336
+ if (sudoOpenclawGateway) {
2337
+ const bin = getCommandOutput("command -v openclaw")?.trim();
2338
+ if (bin) {
2339
+ try {
2340
+ return await tryRun("sudo", ["-n", bin, ...args]);
2341
+ } catch (e2) {
2342
+ if (isPrivilegeError(e2)) {
2343
+ throw new Error(privilegeRemediationMessage(cmd, args, customLines));
2344
+ }
2345
+ throw e2;
2346
+ }
2347
+ }
2348
+ }
2315
2349
  if (isPrivilegeError(err)) {
2316
2350
  throw new Error(privilegeRemediationMessage(cmd, args, customLines));
2317
2351
  }
@@ -2490,7 +2524,18 @@ export class InstallerStepEngine {
2490
2524
  // best effort; gateway install may still surface a clearer error
2491
2525
  }
2492
2526
  }
2527
+ if (!isRootUser() && canUseSudoWithoutPrompt() && typeof process.getuid === "function") {
2528
+ const uid = process.getuid();
2529
+ try {
2530
+ await runCommandWithEvents("sudo", ["-n", "systemctl", "start", `user@${uid}.service`], {
2531
+ onEvent: (evt) => this.emitLog(stepId, evt.type === "stderr" ? "warn" : "info", evt.text, evt.urls || []),
2532
+ });
2533
+ } catch {
2534
+ // best effort
2535
+ }
2536
+ }
2493
2537
  }
2538
+ primeLinuxUserRuntimeEnv();
2494
2539
 
2495
2540
  try {
2496
2541
  await this.runWithPrivilegeGuidance(stepId, "openclaw", ["gateway", "stop"]);
@@ -2862,7 +2907,29 @@ export class InstallerStepEngine {
2862
2907
  lingerSnap.username,
2863
2908
  ]);
2864
2909
  }
2910
+ // Linger alone does not always create /run/user/<uid> until user@uid.service runs (SSH-less bootstrap).
2911
+ if (!isRootUser() && canUseSudoWithoutPrompt() && typeof process.getuid === "function") {
2912
+ const uid = process.getuid();
2913
+ try {
2914
+ await runCommandWithEvents("sudo", ["-n", "systemctl", "start", `user@${uid}.service`], {
2915
+ onEvent: (evt) =>
2916
+ this.emitLog(
2917
+ "gateway_bootstrap",
2918
+ evt.type === "stderr" ? "warn" : "info",
2919
+ evt.text,
2920
+ evt.urls || [],
2921
+ ),
2922
+ });
2923
+ } catch {
2924
+ this.emitLog(
2925
+ "gateway_bootstrap",
2926
+ "warn",
2927
+ `Could not start user@${uid}.service (non-fatal); gateway install may still work if session exists.`,
2928
+ );
2929
+ }
2930
+ }
2865
2931
  }
2932
+ primeLinuxUserRuntimeEnv();
2866
2933
  await this.runWithPrivilegeGuidance("gateway_bootstrap", "openclaw", ["gateway", "install"]);
2867
2934
  await this.runWithPrivilegeGuidance("gateway_bootstrap", "openclaw", ["gateway", "restart"]);
2868
2935
  if (this.options.skipFunnel) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "traderclaw-cli",
3
- "version": "1.0.126",
3
+ "version": "1.0.127",
4
4
  "description": "Global TraderClaw CLI (install --wizard, setup, precheck). Installs solana-traderclaw as a dependency for OpenClaw plugin files.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -17,7 +17,7 @@
17
17
  "node": ">=22"
18
18
  },
19
19
  "dependencies": {
20
- "solana-traderclaw": "^1.0.126"
20
+ "solana-traderclaw": "^1.0.127"
21
21
  },
22
22
  "keywords": [
23
23
  "traderclaw",