traderclaw-cli 1.0.102 → 1.0.104

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.
@@ -198,23 +198,34 @@ export async function ensureLinuxGatewayPersistence(options = {}) {
198
198
  let unitEnabled = false;
199
199
  try {
200
200
  await runSpawn("systemctl", ["--user", "daemon-reload"]);
201
- await runSpawn("systemctl", ["--user", "enable", unitName]);
201
+ await runSpawn("systemctl", ["--user", "enable", "--now", unitName]);
202
202
  unitEnabled = true;
203
- emit("info", `systemd user unit enabled: ${unitName}`);
203
+ emit("info", `systemd user unit enabled and started: ${unitName}`);
204
204
  } catch (err) {
205
205
  const msg = err?.stderr || err?.message || String(err);
206
- errors.push(`systemctl --user enable: ${msg}`);
206
+ errors.push(`systemctl --user enable --now: ${msg}`);
207
207
  emit(
208
208
  "warn",
209
- `Could not enable user unit ${unitName} (${msg.trim()}). If the gateway was installed, try: systemctl --user enable ${unitName}`,
209
+ `Could not enable/start user unit ${unitName} (${msg.trim()}). If the gateway was installed, try: systemctl --user enable --now ${unitName}`,
210
210
  );
211
211
  }
212
212
 
213
+ let unitActive = false;
214
+ try {
215
+ await runSpawn("systemctl", ["--user", "is-active", unitName]);
216
+ unitActive = true;
217
+ emit("info", `${unitName} is active.`);
218
+ } catch {
219
+ // is-active exits non-zero when inactive; not a hard error
220
+ emit("info", `${unitName} is not yet active (may need: openclaw gateway restart).`);
221
+ }
222
+
213
223
  return {
214
224
  skipped: false,
215
225
  linger: lingerOk,
216
226
  unitName,
217
227
  unitEnabled,
228
+ unitActive,
218
229
  errors: errors.length ? errors : undefined,
219
230
  };
220
231
  }
@@ -1533,6 +1533,7 @@ function fallbackModelForProvider(provider) {
1533
1533
  if (provider === "moonshot") return "moonshot/kimi-k2";
1534
1534
  if (provider === "cerebras") return "cerebras/llama-4-scout-17b-16e-instruct";
1535
1535
  if (provider === "qwen") return "qwen/qwen3-235b-a22b";
1536
+ if (provider === "cli-cloud") return "cli-cloud/gemma-e4b";
1536
1537
  return `${provider}/default`;
1537
1538
  }
1538
1539
 
@@ -1552,6 +1553,7 @@ function providerEnvKey(provider) {
1552
1553
  if (provider === "moonshot") return "MOONSHOT_API_KEY";
1553
1554
  if (provider === "cerebras") return "CEREBRAS_API_KEY";
1554
1555
  if (provider === "qwen") return "DASHSCOPE_API_KEY";
1556
+ if (provider === "cli-cloud") return "CLI_CLOUD_API_KEY";
1555
1557
  return "";
1556
1558
  }
1557
1559
 
@@ -1702,8 +1704,9 @@ function configureOpenClawLlmProvider({ provider, model, credential }, configPat
1702
1704
  if (!config.env || typeof config.env !== "object") config.env = {};
1703
1705
  config.env[envKey] = credential;
1704
1706
 
1705
- // Clean stale/broken provider objects from previous buggy writes.
1706
- if (config.models && config.models.providers && config.models.providers[provider]) {
1707
+ // Clean stale/broken provider objects from previous buggy writes (skip custom providers that need their entry).
1708
+ const CUSTOM_PROVIDERS_WITH_BASEURL = ["cli-cloud"];
1709
+ if (!CUSTOM_PROVIDERS_WITH_BASEURL.includes(provider) && config.models && config.models.providers && config.models.providers[provider]) {
1707
1710
  delete config.models.providers[provider];
1708
1711
  if (Object.keys(config.models.providers).length === 0) {
1709
1712
  delete config.models.providers;
@@ -1713,6 +1716,13 @@ function configureOpenClawLlmProvider({ provider, model, credential }, configPat
1713
1716
  }
1714
1717
  }
1715
1718
 
1719
+ // Write baseUrl for custom OpenAI-compatible providers.
1720
+ if (provider === "cli-cloud") {
1721
+ if (!config.models) config.models = {};
1722
+ if (!config.models.providers) config.models.providers = {};
1723
+ config.models.providers["cli-cloud"] = { baseUrl: "https://app.cli.cloud/llm/v1" };
1724
+ }
1725
+
1716
1726
  if (!config.agents) config.agents = {};
1717
1727
  if (!config.agents.defaults) config.agents.defaults = {};
1718
1728
  ensureAgentsDefaultsSchemaCompat(config);
@@ -2224,6 +2234,7 @@ export class InstallerStepEngine {
2224
2234
  }
2225
2235
 
2226
2236
  async configureLlmStep() {
2237
+ const CUSTOM_PROVIDERS_NO_PROBE = ["cli-cloud"];
2227
2238
  const provider = String(this.options.llmProvider || "").trim();
2228
2239
  const requestedModel = String(this.options.llmModel || "").trim();
2229
2240
  const credential = String(this.options.llmCredential || "").trim();
@@ -2293,15 +2304,19 @@ export class InstallerStepEngine {
2293
2304
  onEvent: (evt) => this.emitLog("configure_llm", evt.type === "stderr" ? "warn" : "info", evt.text, evt.urls || []),
2294
2305
  });
2295
2306
 
2296
- try {
2297
- await runCommandWithEvents("openclaw", ["models", "status", "--check", "--probe-provider", provider], {
2298
- onEvent: (evt) => this.emitLog("configure_llm", evt.type === "stderr" ? "warn" : "info", evt.text, evt.urls || []),
2299
- });
2300
- } catch (err) {
2301
- const details = `${err?.stderr || ""}\n${err?.stdout || ""}\n${err?.message || ""}`.trim();
2302
- throw new Error(
2303
- `LLM provider validation failed for '${provider}'. Check OAuth login and model, then retry.\n${details}`,
2304
- );
2307
+ if (CUSTOM_PROVIDERS_NO_PROBE.includes(provider)) {
2308
+ this.emitLog("configure_llm", "info", `Skipping openclaw provider probe for custom provider '${provider}'.`);
2309
+ } else {
2310
+ try {
2311
+ await runCommandWithEvents("openclaw", ["models", "status", "--check", "--probe-provider", provider], {
2312
+ onEvent: (evt) => this.emitLog("configure_llm", evt.type === "stderr" ? "warn" : "info", evt.text, evt.urls || []),
2313
+ });
2314
+ } catch (err) {
2315
+ const details = `${err?.stderr || ""}\n${err?.stdout || ""}\n${err?.message || ""}`.trim();
2316
+ throw new Error(
2317
+ `LLM provider validation failed for '${provider}'. Check OAuth login and model, then retry.\n${details}`,
2318
+ );
2319
+ }
2305
2320
  }
2306
2321
 
2307
2322
  return { configured: true, provider, model, configPath: saved.configPath, authMode: "oauth" };
@@ -2326,15 +2341,19 @@ export class InstallerStepEngine {
2326
2341
  onEvent: (evt) => this.emitLog("configure_llm", evt.type === "stderr" ? "warn" : "info", evt.text, evt.urls || []),
2327
2342
  });
2328
2343
 
2329
- try {
2330
- await runCommandWithEvents("openclaw", ["models", "status", "--check", "--probe-provider", provider], {
2331
- onEvent: (evt) => this.emitLog("configure_llm", evt.type === "stderr" ? "warn" : "info", evt.text, evt.urls || []),
2332
- });
2333
- } catch (err) {
2334
- const details = `${err?.stderr || ""}\n${err?.stdout || ""}\n${err?.message || ""}`.trim();
2335
- throw new Error(
2336
- `LLM provider validation failed for '${provider}'. Check credential/model and retry.\n${details}`,
2337
- );
2344
+ if (CUSTOM_PROVIDERS_NO_PROBE.includes(provider)) {
2345
+ this.emitLog("configure_llm", "info", `Skipping openclaw provider probe for custom provider '${provider}'.`);
2346
+ } else {
2347
+ try {
2348
+ await runCommandWithEvents("openclaw", ["models", "status", "--check", "--probe-provider", provider], {
2349
+ onEvent: (evt) => this.emitLog("configure_llm", evt.type === "stderr" ? "warn" : "info", evt.text, evt.urls || []),
2350
+ });
2351
+ } catch (err) {
2352
+ const details = `${err?.stderr || ""}\n${err?.stdout || ""}\n${err?.message || ""}`.trim();
2353
+ throw new Error(
2354
+ `LLM provider validation failed for '${provider}'. Check credential/model and retry.\n${details}`,
2355
+ );
2356
+ }
2338
2357
  }
2339
2358
 
2340
2359
  return { configured: true, provider, model, configPath: saved.configPath, authMode: "api_key" };
@@ -6,7 +6,7 @@ import { dirname, join } from "path";
6
6
  import { fileURLToPath, pathToFileURL } from "url";
7
7
  import { homedir } from "os";
8
8
  import { randomUUID, createPrivateKey, sign as cryptoSign } from "crypto";
9
- import { execFile, execFileSync, execSync } from "child_process";
9
+ import { execFile, execFileSync, execSync, spawnSync } from "child_process";
10
10
  import { promisify } from "util";
11
11
  import { createServer } from "http";
12
12
  import { resolvePluginPackageRoot } from "./resolve-plugin-root.mjs";
@@ -38,6 +38,7 @@ const WIZARD_PROVIDER_PRIORITY = [
38
38
  "qwen",
39
39
  "cerebras",
40
40
  "minimax",
41
+ "cli-cloud",
41
42
  ];
42
43
  let wizardLlmCatalogPromise = null;
43
44
 
@@ -65,6 +66,9 @@ try {
65
66
  const VERSION = CLI_VERSION || PLUGIN_VERSION;
66
67
  const PLUGIN_ID = "solana-trader";
67
68
  const LEGACY_PLUGIN_IDS = ["traderclaw-v1", "solana-traderclaw-v1", "solana-traderclaw"];
69
+ const KAYBA_TRACING_PLUGIN_ID = "kayba-tracing";
70
+ const KAYBA_TRACING_NPM_PACKAGE = "@kayba_ai/openclaw-tracing";
71
+ const KAYBA_TRACING_FOLDER_DEFAULT = "traderclaw-agent";
68
72
  const CONFIG_DIR = join(homedir(), ".openclaw");
69
73
  const CONFIG_FILE = join(CONFIG_DIR, "openclaw.json");
70
74
  const WALLET_PRIVATE_KEY_ENV = "TRADERCLAW_WALLET_PRIVATE_KEY";
@@ -469,6 +473,48 @@ function setPluginConfig(config, pluginConfig) {
469
473
  };
470
474
  }
471
475
 
476
+ function setKaybaTracingPluginConfig(config, kaybaApiKey, folder) {
477
+ normalizePluginConfigShape(config);
478
+ if (!config.plugins) config.plugins = {};
479
+ if (!config.plugins.entries) config.plugins.entries = {};
480
+ if (!Array.isArray(config.plugins.allow)) config.plugins.allow = [];
481
+ if (!config.plugins.allow.includes(KAYBA_TRACING_PLUGIN_ID)) {
482
+ config.plugins.allow.push(KAYBA_TRACING_PLUGIN_ID);
483
+ }
484
+ const prev = config.plugins.entries[KAYBA_TRACING_PLUGIN_ID];
485
+ const prevConfig = prev && typeof prev.config === "object" && prev.config !== null ? prev.config : {};
486
+ config.plugins.entries[KAYBA_TRACING_PLUGIN_ID] = {
487
+ enabled: true,
488
+ hooks: { allowConversationAccess: true },
489
+ config: {
490
+ ...prevConfig,
491
+ apiKey: kaybaApiKey,
492
+ folder: prevConfig.folder || folder || KAYBA_TRACING_FOLDER_DEFAULT,
493
+ },
494
+ };
495
+ }
496
+
497
+ async function installAndEnableKaybaTracingPlugin() {
498
+ // Best-effort: openclaw plugins install <pkg> + enable <id>. Returns null on success, error message on failure.
499
+ try {
500
+ await execFileAsync("openclaw", ["plugins", "install", KAYBA_TRACING_NPM_PACKAGE], { env: NO_COLOR_ENV });
501
+ } catch (err) {
502
+ const text = `${err?.message || ""}\n${err?.stderr || ""}`.toLowerCase();
503
+ if (!text.includes("already exists") && !text.includes("already installed")) {
504
+ return err instanceof Error ? err.message : String(err);
505
+ }
506
+ }
507
+ try {
508
+ await execFileAsync("openclaw", ["plugins", "enable", KAYBA_TRACING_PLUGIN_ID], { env: NO_COLOR_ENV });
509
+ } catch (err) {
510
+ const text = `${err?.message || ""}\n${err?.stderr || ""}`.toLowerCase();
511
+ if (!text.includes("already enabled")) {
512
+ return err instanceof Error ? err.message : String(err);
513
+ }
514
+ }
515
+ return null;
516
+ }
517
+
472
518
  function getGatewayConfig(config) {
473
519
  if (!config || typeof config !== "object") return {};
474
520
  if (!config.gateway || typeof config.gateway !== "object") return {};
@@ -829,6 +875,7 @@ async function cmdSetup(args) {
829
875
  let forwardTelegramRecipientArg = "";
830
876
  let referralCodeArg = "";
831
877
  let referralInvalidRetries = 0;
878
+ let kaybaApiKeyArg = "";
832
879
 
833
880
  for (let i = 0; i < args.length; i++) {
834
881
  if ((args[i] === "--api-key" || args[i] === "-k") && args[i + 1]) {
@@ -878,6 +925,9 @@ async function cmdSetup(args) {
878
925
  if ((args[i] === "--referral-code" || args[i] === "-r") && args[i + 1]) {
879
926
  referralCodeArg = args[++i];
880
927
  }
928
+ if ((args[i] === "--kayba-key" || args[i] === "--kayba-api-key") && args[i + 1]) {
929
+ kaybaApiKeyArg = args[++i];
930
+ }
881
931
  }
882
932
  const runtimeWalletPrivateKey = getRuntimeWalletPrivateKey(walletPrivateKey);
883
933
 
@@ -1216,12 +1266,30 @@ async function cmdSetup(args) {
1216
1266
  }
1217
1267
  }
1218
1268
 
1269
+ let kaybaApiKey = (kaybaApiKeyArg || process.env.KAYBA_API_KEY || prevPlugin?.kaybaApiKey || "").trim();
1270
+ if (!kaybaApiKey) {
1271
+ print("\nKayba tracing (optional)...\n");
1272
+ printInfo(" Capture every agent turn — full LLM prompts, tool calls, replies — for observability.");
1273
+ printInfo(" Get a key at https://use.kayba.ai/settings/api-keys, or use one provided by your operator.");
1274
+ kaybaApiKey = (await prompt("Kayba API key (kayba_ak_..., Enter to skip)", "")).trim();
1275
+ } else {
1276
+ printInfo(`\n Reusing Kayba API key: ${maskKey(kaybaApiKey)}`);
1277
+ }
1278
+ if (kaybaApiKey) {
1279
+ pluginConfig.kaybaApiKey = kaybaApiKey;
1280
+ if (!pluginConfig.kaybaFolder) pluginConfig.kaybaFolder = "traderclaw";
1281
+ }
1282
+
1219
1283
  print("\nWriting configuration...\n");
1220
1284
 
1221
1285
  const existingConfig = readConfig();
1222
1286
  removeLegacyWalletPrivateKey(pluginConfig);
1223
1287
  setPluginConfig(existingConfig, pluginConfig);
1224
1288
 
1289
+ if (kaybaApiKey) {
1290
+ setKaybaTracingPluginConfig(existingConfig, kaybaApiKey, KAYBA_TRACING_FOLDER_DEFAULT);
1291
+ }
1292
+
1225
1293
  if (!existingConfig.agents || typeof existingConfig.agents !== "object") {
1226
1294
  existingConfig.agents = {};
1227
1295
  }
@@ -1251,6 +1319,17 @@ async function cmdSetup(args) {
1251
1319
 
1252
1320
  printSuccess(` Config written to ${CONFIG_FILE}`);
1253
1321
 
1322
+ if (kaybaApiKey) {
1323
+ print(`\nInstalling ${KAYBA_TRACING_PLUGIN_ID} plugin (one-time)...\n`);
1324
+ const installErr = await installAndEnableKaybaTracingPlugin();
1325
+ if (installErr) {
1326
+ printWarn(` Plugin install failed: ${installErr}`);
1327
+ printWarn(` Finish manually: openclaw plugins install ${KAYBA_TRACING_NPM_PACKAGE} && openclaw plugins enable ${KAYBA_TRACING_PLUGIN_ID}`);
1328
+ } else {
1329
+ printSuccess(` ${KAYBA_TRACING_PLUGIN_ID} installed and enabled (folder: ${KAYBA_TRACING_FOLDER_DEFAULT})`);
1330
+ }
1331
+ }
1332
+
1254
1333
  if (!skipGatewayRegistration) {
1255
1334
  print("\nGateway forwarding setup (required for event-driven wakeups)...\n");
1256
1335
 
@@ -2155,6 +2234,10 @@ async function loadWizardLlmCatalogAsync() {
2155
2234
  id: "moonshot",
2156
2235
  models: [{ id: "moonshot/kimi-k2", name: "Kimi K2" }],
2157
2236
  },
2237
+ {
2238
+ id: "cli-cloud",
2239
+ models: [{ id: "cli-cloud/gemma-e4b", name: "Gemma E4B (personal partner endpoint)" }],
2240
+ },
2158
2241
  ],
2159
2242
  generatedAt: new Date().toISOString(),
2160
2243
  };
@@ -2265,6 +2348,7 @@ function wizardHtml(defaults) {
2265
2348
  <label>LLM API key or token (required)</label>
2266
2349
  <input id="llmCredential" type="password" placeholder="Paste the credential for the selected provider/model" />
2267
2350
  <p class="muted">Written to OpenClaw <code>config.env</code> for the selected provider. If you do not choose a model manually, the installer picks a safe default.</p>
2351
+ <p class="muted hidden" id="llmCliCloudHint">Routes to <code>https://app.cli.cloud/llm/v1</code> — paste your personal CLI Cloud API key above.</p>
2268
2352
  </div>
2269
2353
  <div style="margin-top:12px;" id="llmOauthBlock" class="hidden">
2270
2354
  <p class="muted" style="margin-bottom:12px;">
@@ -2442,6 +2526,7 @@ function wizardHtml(defaults) {
2442
2526
  const llmAuthModeOauth = document.getElementById("llmAuthModeOauth");
2443
2527
  const llmProviderWrap = document.getElementById("llmProviderWrap");
2444
2528
  const llmOauthProviderNote = document.getElementById("llmOauthProviderNote");
2529
+ const llmCliCloudHint = document.getElementById("llmCliCloudHint");
2445
2530
  const llmApiKeyBlock = document.getElementById("llmApiKeyBlock");
2446
2531
  const llmOauthBlock = document.getElementById("llmOauthBlock");
2447
2532
  const telegramTokenEl = document.getElementById("telegramToken");
@@ -3217,7 +3302,13 @@ function wizardHtml(defaults) {
3217
3302
  await copyWithFeedback(copyRestartBtn, restartCommandEl.textContent || "");
3218
3303
  });
3219
3304
  finishWizardBtn.addEventListener("click", finishWizardServer);
3220
- llmProviderEl.addEventListener("change", () => refreshModelOptions(""));
3305
+ llmProviderEl.addEventListener("change", () => {
3306
+ refreshModelOptions("");
3307
+ if (llmCliCloudHint) {
3308
+ if (llmProviderEl.value === "cli-cloud") llmCliCloudHint.classList.remove("hidden");
3309
+ else llmCliCloudHint.classList.add("hidden");
3310
+ }
3311
+ });
3221
3312
  llmModelManualEl.addEventListener("change", () => {
3222
3313
  llmModelEl.disabled = !llmModelManualEl.checked;
3223
3314
  updateStartButtonState();
@@ -4242,15 +4333,17 @@ Setup options:
4242
4333
  --gateway-token, -t Gateway bearer token (defaults to API key)
4243
4334
  --telegram-recipient Telegram @username or chat id (aliases: --forward-telegram-chat-id, --telegram-chat-id)
4244
4335
  --referral-code, -r Optional referral code for new signups (extra trial time when valid)
4336
+ --kayba-key Kayba API key (kayba_ak_...) — captures every agent turn to your Kayba dashboard.
4337
+ Aliases: --kayba-api-key. Env fallback: KAYBA_API_KEY. Skip with empty value.
4245
4338
  --skip-gateway-registration Skip gateway URL registration with orchestrator
4246
4339
  --show-api-key Extra hint after signup (full key is always shown once; confirm with API_KEY_STORED)
4247
4340
  --show-wallet-private-key Reveal full wallet private key in setup output
4248
4341
  --signup Force signup flow (create new account)
4249
4342
  --write-gateway-env Write TRADERCLAW_WALLET_PRIVATE_KEY to a systemd EnvironmentFile for the user gateway (Linux)
4250
- --no-ensure-gateway-persistent Skip automatic Linux loginctl linger + user unit enable after setup
4343
+ --no-ensure-gateway-persistent Skip automatic Linux loginctl linger + systemctl --user enable --now after setup
4251
4344
 
4252
4345
  Gateway subcommands:
4253
- gateway ensure-persistent Linux: enable loginctl linger and systemd --user unit for OpenClaw gateway
4346
+ gateway ensure-persistent Linux: enable loginctl linger and systemctl --user enable --now for OpenClaw gateway
4254
4347
 
4255
4348
  Login options:
4256
4349
  --wallet-private-key <k> Base58 key for wallet proof (runtime only, never saved). Optional in a
@@ -4287,6 +4380,8 @@ Examples:
4287
4380
  traderclaw setup --api-key oc_xxx --url https://api.traderclaw.ai
4288
4381
  traderclaw setup --gateway-base-url https://gateway.myhost.ts.net
4289
4382
  traderclaw setup --telegram-recipient @myusername
4383
+ traderclaw setup --kayba-key kayba_ak_xxx # one-shot Kayba tracing setup (installs kayba-tracing plugin)
4384
+ KAYBA_API_KEY=kayba_ak_xxx traderclaw setup # same via env var
4290
4385
  traderclaw login
4291
4386
  traderclaw login --force-reauth --wallet-private-key <base58_key>
4292
4387
  traderclaw logout
@@ -4453,17 +4548,46 @@ async function cmdUpdate(args) {
4453
4548
  }
4454
4549
 
4455
4550
  if (dryRun) {
4456
- print(`\n [dry-run] Would run: openclaw gateway restart\n`);
4551
+ print(`\n [dry-run] Would run: systemctl --user enable --now + restart (Linux) or openclaw gateway restart\n`);
4457
4552
  } else {
4458
- if (!commandExists("openclaw")) {
4459
- printWarn("\n Skipping gateway restart: openclaw not in PATH. After fixing PATH: openclaw gateway restart");
4460
- } else {
4553
+ const { isLinuxGatewayPersistenceEligible, ensureLinuxGatewayPersistence, resolveGatewayUnitNameFromStatusJson, readOpenclawGatewayStatusJson } = await import("./gateway-persistence-linux.mjs");
4554
+ if (isLinuxGatewayPersistenceEligible()) {
4555
+ print("\n Gateway persistence (Linux)...\n");
4556
+ let unitName = "openclaw-gateway.service";
4557
+ try {
4558
+ const statusJson = readOpenclawGatewayStatusJson();
4559
+ unitName = resolveGatewayUnitNameFromStatusJson(statusJson);
4560
+ await ensureLinuxGatewayPersistence({
4561
+ emitLog: (level, text) => {
4562
+ if (level === "warn") printWarn(` ${text}`);
4563
+ else printInfo(` ${text}`);
4564
+ },
4565
+ });
4566
+ } catch (err) {
4567
+ printWarn(` Gateway persistence (optional): ${err.message || err}`);
4568
+ }
4461
4569
  print("\n Restarting gateway...\n");
4462
4570
  try {
4463
- execFileSync("openclaw", ["gateway", "restart"], { stdio: "inherit" });
4464
- printSuccess(" Gateway restarted.");
4465
- } catch {
4466
- printWarn(" Gateway restart returned non-zero. Try manually: openclaw gateway restart");
4571
+ const r = spawnSync("systemctl", ["--user", "restart", unitName], { stdio: "inherit" });
4572
+ if (r.status === 0) {
4573
+ printSuccess(` Gateway restarted (systemctl --user restart ${unitName}).`);
4574
+ } else {
4575
+ printWarn(` systemctl --user restart returned ${r.status}. Try: systemctl --user restart ${unitName}`);
4576
+ }
4577
+ } catch (err) {
4578
+ printWarn(` systemctl --user restart: ${err.message || err}. Try manually: systemctl --user restart ${unitName}`);
4579
+ }
4580
+ } else {
4581
+ if (!commandExists("openclaw")) {
4582
+ printWarn("\n Skipping gateway restart: openclaw not in PATH. After fixing PATH: openclaw gateway restart");
4583
+ } else {
4584
+ print("\n Restarting gateway...\n");
4585
+ try {
4586
+ execFileSync("openclaw", ["gateway", "restart"], { stdio: "inherit" });
4587
+ printSuccess(" Gateway restarted.");
4588
+ } catch {
4589
+ printWarn(" Gateway restart returned non-zero. Try manually: openclaw gateway restart");
4590
+ }
4467
4591
  }
4468
4592
  }
4469
4593
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "traderclaw-cli",
3
- "version": "1.0.102",
3
+ "version": "1.0.104",
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.102"
20
+ "solana-traderclaw": "^1.0.104"
21
21
  },
22
22
  "keywords": [
23
23
  "traderclaw",