traderclaw-cli 1.0.92 → 1.0.93

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.
@@ -530,6 +530,42 @@ async function installOpenClawPlatform() {
530
530
  };
531
531
  }
532
532
 
533
+ /**
534
+ * Check whether the OpenClaw CLI has any devices stuck in a pending-approval or
535
+ * repair state. This can happen when the gateway version >= 1.0.93-beta.0 starts
536
+ * treating every CLI invocation as a "device" that must be explicitly approved
537
+ * before it gets operator-write scope. Without that scope all trading RPCs fail
538
+ * silently (read-only).
539
+ *
540
+ * Returns:
541
+ * { ran: false } – openclaw not on PATH or devices subcommand not supported
542
+ * { ran: true, pendingIds: string[], – list ran OK; ids needing approval
543
+ * repairDetected: boolean, – current device is in repair/read-only state
544
+ * envTokenSet: boolean } – OPENCLAW_GATEWAY_TOKEN env var already present (fallback)
545
+ */
546
+ function checkOpenClawDeviceApproval() {
547
+ if (!commandExists("openclaw")) return { ran: false };
548
+ const raw = getCommandOutput("openclaw devices list");
549
+ if (!raw) return { ran: false };
550
+
551
+ const lower = raw.toLowerCase();
552
+ const envTokenSet = !!process.env.OPENCLAW_GATEWAY_TOKEN;
553
+
554
+ // Detect devices that are waiting for approval ("pending" requestId lines).
555
+ const pendingIds = [];
556
+ for (const line of raw.split("\n")) {
557
+ // Lines typically look like: d4fcdbe8-5176-422b-... pending
558
+ const m = line.match(/([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})/i);
559
+ if (m && (line.toLowerCase().includes("pending") || line.toLowerCase().includes("repair"))) {
560
+ pendingIds.push(m[1]);
561
+ }
562
+ }
563
+
564
+ const repairDetected = lower.includes("repair");
565
+
566
+ return { ran: true, pendingIds, repairDetected, envTokenSet, raw };
567
+ }
568
+
533
569
  function isNpmGlobalBinConflict(err, cliName) {
534
570
  const text = `${err?.message || ""}\n${err?.stderr || ""}\n${err?.stdout || ""}`.toLowerCase();
535
571
  return (
@@ -1019,9 +1055,9 @@ function configureGatewayScheduling(modeConfig, configPath = CONFIG_FILE) {
1019
1055
  prompt: heartbeatPrompt,
1020
1056
  };
1021
1057
 
1022
- const v1Agents = [{ id: "main", default: true, heartbeat: { ...defaultHeartbeat } }];
1058
+ const v1Agents = [{ id: "main", default: true, identity: { name: "AgentZERO" }, heartbeat: { ...defaultHeartbeat } }];
1023
1059
  const v2Agents = [
1024
- { id: "cto", default: true, heartbeat: { ...defaultHeartbeat } },
1060
+ { id: "cto", default: true, identity: { name: "AgentZERO" }, heartbeat: { ...defaultHeartbeat } },
1025
1061
  { id: "execution-specialist", heartbeat: { ...defaultHeartbeat } },
1026
1062
  { id: "alpha-signal-analyst", heartbeat: { ...defaultHeartbeat } },
1027
1063
  { id: "onchain-analyst" },
@@ -1048,6 +1084,9 @@ function configureGatewayScheduling(modeConfig, configPath = CONFIG_FILE) {
1048
1084
  if (agent.default) {
1049
1085
  existing.default = true;
1050
1086
  }
1087
+ if (agent.identity && (!existing.identity || typeof existing.identity !== "object")) {
1088
+ existing.identity = agent.identity;
1089
+ }
1051
1090
  } else {
1052
1091
  config.agents.list.push(agent);
1053
1092
  }
@@ -1111,6 +1150,21 @@ function configureGatewayScheduling(modeConfig, configPath = CONFIG_FILE) {
1111
1150
  if (config.channels.defaults.heartbeat.showOk === undefined) {
1112
1151
  config.channels.defaults.heartbeat.showOk = true;
1113
1152
  }
1153
+ if (config.channels.defaults.heartbeat.showAlerts === undefined) {
1154
+ config.channels.defaults.heartbeat.showAlerts = true;
1155
+ }
1156
+
1157
+ if (!config.channels.telegram || typeof config.channels.telegram !== "object") {
1158
+ config.channels.telegram = {};
1159
+ }
1160
+ if (config.channels.telegram.streaming === undefined) {
1161
+ config.channels.telegram.streaming = "partial";
1162
+ }
1163
+
1164
+ if (!config.commands || typeof config.commands !== "object") config.commands = {};
1165
+ if (config.commands.native === undefined) config.commands.native = "auto";
1166
+ if (config.commands.restart === undefined) config.commands.restart = true;
1167
+ if (!config.commands.ownerDisplay) config.commands.ownerDisplay = "raw";
1114
1168
 
1115
1169
  if (!config.agents.defaults || typeof config.agents.defaults !== "object") {
1116
1170
  config.agents.defaults = {};
@@ -2329,6 +2383,40 @@ export class InstallerStepEngine {
2329
2383
  if (!this.options.skipInstallOpenClaw) {
2330
2384
  await this.runStep("install_openclaw", "Installing or upgrading OpenClaw platform", async () => installOpenClawPlatform());
2331
2385
  }
2386
+
2387
+ // Non-fatal: warn when the CLI has devices in pending-approval or repair state.
2388
+ // Gateway >= 1.0.93-beta.0 requires explicit device approval for operator-write scope;
2389
+ // without it, agent trading RPCs silently fail (device gets read-only "repair" state).
2390
+ await this.runStep("device_approval_check", "Checking OpenClaw device approval status", async () => {
2391
+ const check = checkOpenClawDeviceApproval();
2392
+ if (!check.ran) {
2393
+ this.emitLog("device_approval_check", "info", "Device approval check skipped (openclaw CLI not available or devices subcommand not supported).");
2394
+ return { ran: false };
2395
+ }
2396
+ const needsAction = check.pendingIds.length > 0 || check.repairDetected;
2397
+ if (!needsAction) {
2398
+ this.emitLog("device_approval_check", "info", "No pending or repair-state devices found. Device approval OK.");
2399
+ return { ran: true, ok: true };
2400
+ }
2401
+ const lines = [
2402
+ "ACTION REQUIRED — OpenClaw device approval needed.",
2403
+ "The gateway requires explicit device approval for operator-write scope.",
2404
+ "Without it, trading RPCs will fail silently (read-only / repair state).",
2405
+ "",
2406
+ "Run in your VPS shell:",
2407
+ " openclaw devices list",
2408
+ ...(check.pendingIds.length > 0
2409
+ ? check.pendingIds.map((id) => ` openclaw devices approve ${id}`)
2410
+ : [" openclaw devices approve <requestId> # use the id shown above"]),
2411
+ "",
2412
+ check.envTokenSet
2413
+ ? "OPENCLAW_GATEWAY_TOKEN env var is already set — env-first auth will work as a fallback."
2414
+ : "Optionally set: export OPENCLAW_GATEWAY_TOKEN=\"<token>\" # bypasses device auth entirely",
2415
+ ];
2416
+ this.emitLog("device_approval_check", "warn", lines.join("\n"));
2417
+ return { ran: true, ok: false, pendingIds: check.pendingIds, repairDetected: check.repairDetected, envTokenSet: check.envTokenSet };
2418
+ });
2419
+
2332
2420
  await this.runStep("configure_llm", "Configuring required OpenClaw LLM provider", async () => this.configureLlmStep());
2333
2421
  if (!this.options.skipInstallPlugin) {
2334
2422
  await this.runStep("install_plugin_package", "Installing TraderClaw CLI package", async () =>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "traderclaw-cli",
3
- "version": "1.0.92",
3
+ "version": "1.0.93",
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.92"
20
+ "solana-traderclaw": "^1.0.93"
21
21
  },
22
22
  "keywords": [
23
23
  "traderclaw",