traderclaw-cli 1.0.128 → 1.0.129

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.
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import { createInterface } from "readline";
4
- import { readFileSync, writeFileSync, mkdirSync, appendFileSync, existsSync } from "fs";
4
+ import { readFileSync, writeFileSync, mkdirSync, appendFileSync, existsSync, renameSync } from "fs";
5
5
  import { dirname, join } from "path";
6
6
  import { fileURLToPath, pathToFileURL } from "url";
7
7
  import { homedir } from "os";
@@ -74,6 +74,86 @@ const CONFIG_DIR = join(homedir(), ".openclaw");
74
74
  const CONFIG_FILE = join(CONFIG_DIR, "openclaw.json");
75
75
  const WALLET_PRIVATE_KEY_ENV = "TRADERCLAW_WALLET_PRIVATE_KEY";
76
76
 
77
+ /** Session sidecar directory: explicit plugins.entries.solana-trader.config.dataDir or ~/.traderclaw-v1-data */
78
+ function resolveTraderClawDataDir(pluginConfig) {
79
+ const raw =
80
+ pluginConfig && typeof pluginConfig.dataDir === "string" ? pluginConfig.dataDir.trim() : "";
81
+ if (raw.length > 0) {
82
+ return raw.replace(/^~(?=$|[/\\])/, homedir());
83
+ }
84
+ return join(homedir(), ".traderclaw-v1-data");
85
+ }
86
+
87
+ function ensureExplicitPluginDataDir(pluginConfig) {
88
+ if (!pluginConfig || typeof pluginConfig !== "object") return;
89
+ const raw = typeof pluginConfig.dataDir === "string" ? pluginConfig.dataDir.trim() : "";
90
+ if (raw.length > 0) {
91
+ pluginConfig.dataDir = raw.replace(/^~(?=$|[/\\])/, homedir());
92
+ } else {
93
+ pluginConfig.dataDir = join(homedir(), ".traderclaw-v1-data");
94
+ }
95
+ }
96
+
97
+ function persistSessionSidecar(pluginConfig, tokens) {
98
+ if (!tokens || typeof tokens.refreshToken !== "string" || tokens.refreshToken.length === 0) {
99
+ return;
100
+ }
101
+ const dataDir = resolveTraderClawDataDir(pluginConfig);
102
+ const sessionTokensPath = join(dataDir, "session-tokens.json");
103
+ mkdirSync(dataDir, { recursive: true });
104
+ let existingSidecar = {};
105
+ try {
106
+ if (existsSync(sessionTokensPath)) {
107
+ existingSidecar = JSON.parse(readFileSync(sessionTokensPath, "utf-8")) || {};
108
+ }
109
+ } catch {
110
+ /* ignore */
111
+ }
112
+ const ttlSec =
113
+ typeof tokens.accessTokenTtlSeconds === "number" && Number.isFinite(tokens.accessTokenTtlSeconds)
114
+ ? tokens.accessTokenTtlSeconds
115
+ : 900;
116
+ const accessTokenExpiresAt = Date.now() + ttlSec * 1000;
117
+ const walletEntry =
118
+ pluginConfig.walletPublicKey && String(pluginConfig.walletPublicKey).trim()
119
+ ? { walletPublicKey: String(pluginConfig.walletPublicKey).trim() }
120
+ : {};
121
+ const recoveryEntry =
122
+ typeof pluginConfig.recoverySecret === "string" && pluginConfig.recoverySecret.trim().length > 0
123
+ ? { recoverySecret: pluginConfig.recoverySecret.trim() }
124
+ : {};
125
+ const payload = {
126
+ ...existingSidecar,
127
+ refreshToken: tokens.refreshToken,
128
+ accessToken: tokens.accessToken,
129
+ accessTokenExpiresAt,
130
+ ...walletEntry,
131
+ ...recoveryEntry,
132
+ };
133
+ const tmp = `${sessionTokensPath}.${process.pid}.${Date.now()}.tmp`;
134
+ writeFileSync(tmp, JSON.stringify(payload, null, 2) + "\n", "utf-8");
135
+ renameSync(tmp, sessionTokensPath);
136
+ }
137
+
138
+ function clearSessionSidecarSessionFields(pluginConfig) {
139
+ const dataDir = resolveTraderClawDataDir(pluginConfig);
140
+ const sessionTokensPath = join(dataDir, "session-tokens.json");
141
+ if (!existsSync(sessionTokensPath)) return;
142
+ try {
143
+ const raw = JSON.parse(readFileSync(sessionTokensPath, "utf-8"));
144
+ if (!raw || typeof raw !== "object") return;
145
+ const next = { ...raw };
146
+ delete next.refreshToken;
147
+ delete next.accessToken;
148
+ delete next.accessTokenExpiresAt;
149
+ const tmp = `${sessionTokensPath}.${process.pid}.${Date.now()}.tmp`;
150
+ writeFileSync(tmp, JSON.stringify(next, null, 2) + "\n", "utf-8");
151
+ renameSync(tmp, sessionTokensPath);
152
+ } catch {
153
+ /* ignore */
154
+ }
155
+ }
156
+
77
157
  /** Linked from CLI errors and setup — keep in sync with SKILL / README. */
78
158
  const TRADERCLAW_SESSION_TROUBLESHOOTING_URL =
79
159
  "https://docs.traderclaw.ai/docs/installation#troubleshooting-session-expired-auth-errors-or-the-agent-logged-out";
@@ -1290,6 +1370,8 @@ async function cmdSetup(args) {
1290
1370
  if (!pluginConfig.kaybaFolder) pluginConfig.kaybaFolder = "traderclaw";
1291
1371
  }
1292
1372
 
1373
+ ensureExplicitPluginDataDir(pluginConfig);
1374
+
1293
1375
  print("\nWriting configuration...\n");
1294
1376
 
1295
1377
  const existingConfig = readConfig();
@@ -1327,6 +1409,8 @@ async function cmdSetup(args) {
1327
1409
 
1328
1410
  writeConfig(existingConfig);
1329
1411
 
1412
+ persistSessionSidecar(pluginConfig, sessionTokens);
1413
+
1330
1414
  printSuccess(` Config written to ${CONFIG_FILE}`);
1331
1415
 
1332
1416
  if (kaybaApiKey) {
@@ -1657,7 +1741,9 @@ async function cmdLogin(args) {
1657
1741
  const removedLegacyKey = removeLegacyWalletPrivateKey(pluginConfig);
1658
1742
 
1659
1743
  try {
1660
- await establishSession(orchestratorUrl, pluginConfig, walletPrivateKeyArg);
1744
+ const tokens = await establishSession(orchestratorUrl, pluginConfig, walletPrivateKeyArg);
1745
+ ensureExplicitPluginDataDir(pluginConfig);
1746
+ persistSessionSidecar(pluginConfig, tokens);
1661
1747
  setPluginConfig(config, pluginConfig);
1662
1748
  writeConfig(config);
1663
1749
  printSuccess("\n Session established and saved.");
@@ -1706,6 +1792,7 @@ async function cmdLogout() {
1706
1792
  const removedLegacyKey = removeLegacyWalletPrivateKey(pluginConfig);
1707
1793
  setPluginConfig(config, pluginConfig);
1708
1794
  writeConfig(config);
1795
+ clearSessionSidecarSessionFields(pluginConfig);
1709
1796
 
1710
1797
  printSuccess(" Local session cleared.");
1711
1798
  if (removedLegacyKey) {
@@ -4481,7 +4568,7 @@ async function cmdTestSession(args) {
4481
4568
  process.exit(1);
4482
4569
  }
4483
4570
 
4484
- const dataDir = pluginConfig.dataDir || join(process.cwd(), ".traderclaw-v1-data");
4571
+ const dataDir = resolveTraderClawDataDir(pluginConfig);
4485
4572
  const sessionTokensPath = join(dataDir, "session-tokens.json");
4486
4573
 
4487
4574
  let sidecar = null;
@@ -4666,7 +4753,6 @@ async function cmdTestSession(args) {
4666
4753
  };
4667
4754
  const tmp = `${sessionTokensPath}.${process.pid}.${Date.now()}.tmp`;
4668
4755
  writeFileSync(tmp, JSON.stringify(payload, null, 2) + "\n", "utf-8");
4669
- const { renameSync } = await import("fs");
4670
4756
  renameSync(tmp, sessionTokensPath);
4671
4757
  printSuccess(` OK — written to ${sessionTokensPath}`);
4672
4758
  results.push({ test: "persist_sidecar", status: "ok" });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "traderclaw-cli",
3
- "version": "1.0.128",
3
+ "version": "1.0.129",
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.128"
20
+ "solana-traderclaw": "^1.0.129"
21
21
  },
22
22
  "keywords": [
23
23
  "traderclaw",