traderclaw-cli 1.0.102 → 1.0.103
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.
- package/bin/gateway-persistence-linux.mjs +15 -4
- package/bin/openclaw-trader.mjs +122 -11
- package/package.json +2 -2
|
@@ -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
|
}
|
package/bin/openclaw-trader.mjs
CHANGED
|
@@ -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";
|
|
@@ -65,6 +65,9 @@ try {
|
|
|
65
65
|
const VERSION = CLI_VERSION || PLUGIN_VERSION;
|
|
66
66
|
const PLUGIN_ID = "solana-trader";
|
|
67
67
|
const LEGACY_PLUGIN_IDS = ["traderclaw-v1", "solana-traderclaw-v1", "solana-traderclaw"];
|
|
68
|
+
const KAYBA_TRACING_PLUGIN_ID = "kayba-tracing";
|
|
69
|
+
const KAYBA_TRACING_NPM_PACKAGE = "@kayba_ai/openclaw-tracing";
|
|
70
|
+
const KAYBA_TRACING_FOLDER_DEFAULT = "traderclaw-agent";
|
|
68
71
|
const CONFIG_DIR = join(homedir(), ".openclaw");
|
|
69
72
|
const CONFIG_FILE = join(CONFIG_DIR, "openclaw.json");
|
|
70
73
|
const WALLET_PRIVATE_KEY_ENV = "TRADERCLAW_WALLET_PRIVATE_KEY";
|
|
@@ -469,6 +472,48 @@ function setPluginConfig(config, pluginConfig) {
|
|
|
469
472
|
};
|
|
470
473
|
}
|
|
471
474
|
|
|
475
|
+
function setKaybaTracingPluginConfig(config, kaybaApiKey, folder) {
|
|
476
|
+
normalizePluginConfigShape(config);
|
|
477
|
+
if (!config.plugins) config.plugins = {};
|
|
478
|
+
if (!config.plugins.entries) config.plugins.entries = {};
|
|
479
|
+
if (!Array.isArray(config.plugins.allow)) config.plugins.allow = [];
|
|
480
|
+
if (!config.plugins.allow.includes(KAYBA_TRACING_PLUGIN_ID)) {
|
|
481
|
+
config.plugins.allow.push(KAYBA_TRACING_PLUGIN_ID);
|
|
482
|
+
}
|
|
483
|
+
const prev = config.plugins.entries[KAYBA_TRACING_PLUGIN_ID];
|
|
484
|
+
const prevConfig = prev && typeof prev.config === "object" && prev.config !== null ? prev.config : {};
|
|
485
|
+
config.plugins.entries[KAYBA_TRACING_PLUGIN_ID] = {
|
|
486
|
+
enabled: true,
|
|
487
|
+
hooks: { allowConversationAccess: true },
|
|
488
|
+
config: {
|
|
489
|
+
...prevConfig,
|
|
490
|
+
apiKey: kaybaApiKey,
|
|
491
|
+
folder: prevConfig.folder || folder || KAYBA_TRACING_FOLDER_DEFAULT,
|
|
492
|
+
},
|
|
493
|
+
};
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
async function installAndEnableKaybaTracingPlugin() {
|
|
497
|
+
// Best-effort: openclaw plugins install <pkg> + enable <id>. Returns null on success, error message on failure.
|
|
498
|
+
try {
|
|
499
|
+
await execFileAsync("openclaw", ["plugins", "install", KAYBA_TRACING_NPM_PACKAGE], { env: NO_COLOR_ENV });
|
|
500
|
+
} catch (err) {
|
|
501
|
+
const text = `${err?.message || ""}\n${err?.stderr || ""}`.toLowerCase();
|
|
502
|
+
if (!text.includes("already exists") && !text.includes("already installed")) {
|
|
503
|
+
return err instanceof Error ? err.message : String(err);
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
try {
|
|
507
|
+
await execFileAsync("openclaw", ["plugins", "enable", KAYBA_TRACING_PLUGIN_ID], { env: NO_COLOR_ENV });
|
|
508
|
+
} catch (err) {
|
|
509
|
+
const text = `${err?.message || ""}\n${err?.stderr || ""}`.toLowerCase();
|
|
510
|
+
if (!text.includes("already enabled")) {
|
|
511
|
+
return err instanceof Error ? err.message : String(err);
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
return null;
|
|
515
|
+
}
|
|
516
|
+
|
|
472
517
|
function getGatewayConfig(config) {
|
|
473
518
|
if (!config || typeof config !== "object") return {};
|
|
474
519
|
if (!config.gateway || typeof config.gateway !== "object") return {};
|
|
@@ -829,6 +874,7 @@ async function cmdSetup(args) {
|
|
|
829
874
|
let forwardTelegramRecipientArg = "";
|
|
830
875
|
let referralCodeArg = "";
|
|
831
876
|
let referralInvalidRetries = 0;
|
|
877
|
+
let kaybaApiKeyArg = "";
|
|
832
878
|
|
|
833
879
|
for (let i = 0; i < args.length; i++) {
|
|
834
880
|
if ((args[i] === "--api-key" || args[i] === "-k") && args[i + 1]) {
|
|
@@ -878,6 +924,9 @@ async function cmdSetup(args) {
|
|
|
878
924
|
if ((args[i] === "--referral-code" || args[i] === "-r") && args[i + 1]) {
|
|
879
925
|
referralCodeArg = args[++i];
|
|
880
926
|
}
|
|
927
|
+
if ((args[i] === "--kayba-key" || args[i] === "--kayba-api-key") && args[i + 1]) {
|
|
928
|
+
kaybaApiKeyArg = args[++i];
|
|
929
|
+
}
|
|
881
930
|
}
|
|
882
931
|
const runtimeWalletPrivateKey = getRuntimeWalletPrivateKey(walletPrivateKey);
|
|
883
932
|
|
|
@@ -1216,12 +1265,30 @@ async function cmdSetup(args) {
|
|
|
1216
1265
|
}
|
|
1217
1266
|
}
|
|
1218
1267
|
|
|
1268
|
+
let kaybaApiKey = (kaybaApiKeyArg || process.env.KAYBA_API_KEY || prevPlugin?.kaybaApiKey || "").trim();
|
|
1269
|
+
if (!kaybaApiKey) {
|
|
1270
|
+
print("\nKayba tracing (optional)...\n");
|
|
1271
|
+
printInfo(" Capture every agent turn — full LLM prompts, tool calls, replies — for observability.");
|
|
1272
|
+
printInfo(" Get a key at https://use.kayba.ai/settings/api-keys, or use one provided by your operator.");
|
|
1273
|
+
kaybaApiKey = (await prompt("Kayba API key (kayba_ak_..., Enter to skip)", "")).trim();
|
|
1274
|
+
} else {
|
|
1275
|
+
printInfo(`\n Reusing Kayba API key: ${maskKey(kaybaApiKey)}`);
|
|
1276
|
+
}
|
|
1277
|
+
if (kaybaApiKey) {
|
|
1278
|
+
pluginConfig.kaybaApiKey = kaybaApiKey;
|
|
1279
|
+
if (!pluginConfig.kaybaFolder) pluginConfig.kaybaFolder = "traderclaw";
|
|
1280
|
+
}
|
|
1281
|
+
|
|
1219
1282
|
print("\nWriting configuration...\n");
|
|
1220
1283
|
|
|
1221
1284
|
const existingConfig = readConfig();
|
|
1222
1285
|
removeLegacyWalletPrivateKey(pluginConfig);
|
|
1223
1286
|
setPluginConfig(existingConfig, pluginConfig);
|
|
1224
1287
|
|
|
1288
|
+
if (kaybaApiKey) {
|
|
1289
|
+
setKaybaTracingPluginConfig(existingConfig, kaybaApiKey, KAYBA_TRACING_FOLDER_DEFAULT);
|
|
1290
|
+
}
|
|
1291
|
+
|
|
1225
1292
|
if (!existingConfig.agents || typeof existingConfig.agents !== "object") {
|
|
1226
1293
|
existingConfig.agents = {};
|
|
1227
1294
|
}
|
|
@@ -1251,6 +1318,17 @@ async function cmdSetup(args) {
|
|
|
1251
1318
|
|
|
1252
1319
|
printSuccess(` Config written to ${CONFIG_FILE}`);
|
|
1253
1320
|
|
|
1321
|
+
if (kaybaApiKey) {
|
|
1322
|
+
print(`\nInstalling ${KAYBA_TRACING_PLUGIN_ID} plugin (one-time)...\n`);
|
|
1323
|
+
const installErr = await installAndEnableKaybaTracingPlugin();
|
|
1324
|
+
if (installErr) {
|
|
1325
|
+
printWarn(` Plugin install failed: ${installErr}`);
|
|
1326
|
+
printWarn(` Finish manually: openclaw plugins install ${KAYBA_TRACING_NPM_PACKAGE} && openclaw plugins enable ${KAYBA_TRACING_PLUGIN_ID}`);
|
|
1327
|
+
} else {
|
|
1328
|
+
printSuccess(` ${KAYBA_TRACING_PLUGIN_ID} installed and enabled (folder: ${KAYBA_TRACING_FOLDER_DEFAULT})`);
|
|
1329
|
+
}
|
|
1330
|
+
}
|
|
1331
|
+
|
|
1254
1332
|
if (!skipGatewayRegistration) {
|
|
1255
1333
|
print("\nGateway forwarding setup (required for event-driven wakeups)...\n");
|
|
1256
1334
|
|
|
@@ -4242,15 +4320,17 @@ Setup options:
|
|
|
4242
4320
|
--gateway-token, -t Gateway bearer token (defaults to API key)
|
|
4243
4321
|
--telegram-recipient Telegram @username or chat id (aliases: --forward-telegram-chat-id, --telegram-chat-id)
|
|
4244
4322
|
--referral-code, -r Optional referral code for new signups (extra trial time when valid)
|
|
4323
|
+
--kayba-key Kayba API key (kayba_ak_...) — captures every agent turn to your Kayba dashboard.
|
|
4324
|
+
Aliases: --kayba-api-key. Env fallback: KAYBA_API_KEY. Skip with empty value.
|
|
4245
4325
|
--skip-gateway-registration Skip gateway URL registration with orchestrator
|
|
4246
4326
|
--show-api-key Extra hint after signup (full key is always shown once; confirm with API_KEY_STORED)
|
|
4247
4327
|
--show-wallet-private-key Reveal full wallet private key in setup output
|
|
4248
4328
|
--signup Force signup flow (create new account)
|
|
4249
4329
|
--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
|
|
4330
|
+
--no-ensure-gateway-persistent Skip automatic Linux loginctl linger + systemctl --user enable --now after setup
|
|
4251
4331
|
|
|
4252
4332
|
Gateway subcommands:
|
|
4253
|
-
gateway ensure-persistent Linux: enable loginctl linger and
|
|
4333
|
+
gateway ensure-persistent Linux: enable loginctl linger and systemctl --user enable --now for OpenClaw gateway
|
|
4254
4334
|
|
|
4255
4335
|
Login options:
|
|
4256
4336
|
--wallet-private-key <k> Base58 key for wallet proof (runtime only, never saved). Optional in a
|
|
@@ -4287,6 +4367,8 @@ Examples:
|
|
|
4287
4367
|
traderclaw setup --api-key oc_xxx --url https://api.traderclaw.ai
|
|
4288
4368
|
traderclaw setup --gateway-base-url https://gateway.myhost.ts.net
|
|
4289
4369
|
traderclaw setup --telegram-recipient @myusername
|
|
4370
|
+
traderclaw setup --kayba-key kayba_ak_xxx # one-shot Kayba tracing setup (installs kayba-tracing plugin)
|
|
4371
|
+
KAYBA_API_KEY=kayba_ak_xxx traderclaw setup # same via env var
|
|
4290
4372
|
traderclaw login
|
|
4291
4373
|
traderclaw login --force-reauth --wallet-private-key <base58_key>
|
|
4292
4374
|
traderclaw logout
|
|
@@ -4453,17 +4535,46 @@ async function cmdUpdate(args) {
|
|
|
4453
4535
|
}
|
|
4454
4536
|
|
|
4455
4537
|
if (dryRun) {
|
|
4456
|
-
print(`\n [dry-run] Would run: openclaw gateway restart\n`);
|
|
4538
|
+
print(`\n [dry-run] Would run: systemctl --user enable --now + restart (Linux) or openclaw gateway restart\n`);
|
|
4457
4539
|
} else {
|
|
4458
|
-
|
|
4459
|
-
|
|
4460
|
-
|
|
4540
|
+
const { isLinuxGatewayPersistenceEligible, ensureLinuxGatewayPersistence, resolveGatewayUnitNameFromStatusJson, readOpenclawGatewayStatusJson } = await import("./gateway-persistence-linux.mjs");
|
|
4541
|
+
if (isLinuxGatewayPersistenceEligible()) {
|
|
4542
|
+
print("\n Gateway persistence (Linux)...\n");
|
|
4543
|
+
let unitName = "openclaw-gateway.service";
|
|
4544
|
+
try {
|
|
4545
|
+
const statusJson = readOpenclawGatewayStatusJson();
|
|
4546
|
+
unitName = resolveGatewayUnitNameFromStatusJson(statusJson);
|
|
4547
|
+
await ensureLinuxGatewayPersistence({
|
|
4548
|
+
emitLog: (level, text) => {
|
|
4549
|
+
if (level === "warn") printWarn(` ${text}`);
|
|
4550
|
+
else printInfo(` ${text}`);
|
|
4551
|
+
},
|
|
4552
|
+
});
|
|
4553
|
+
} catch (err) {
|
|
4554
|
+
printWarn(` Gateway persistence (optional): ${err.message || err}`);
|
|
4555
|
+
}
|
|
4461
4556
|
print("\n Restarting gateway...\n");
|
|
4462
4557
|
try {
|
|
4463
|
-
|
|
4464
|
-
|
|
4465
|
-
|
|
4466
|
-
|
|
4558
|
+
const r = spawnSync("systemctl", ["--user", "restart", unitName], { stdio: "inherit" });
|
|
4559
|
+
if (r.status === 0) {
|
|
4560
|
+
printSuccess(` Gateway restarted (systemctl --user restart ${unitName}).`);
|
|
4561
|
+
} else {
|
|
4562
|
+
printWarn(` systemctl --user restart returned ${r.status}. Try: systemctl --user restart ${unitName}`);
|
|
4563
|
+
}
|
|
4564
|
+
} catch (err) {
|
|
4565
|
+
printWarn(` systemctl --user restart: ${err.message || err}. Try manually: systemctl --user restart ${unitName}`);
|
|
4566
|
+
}
|
|
4567
|
+
} else {
|
|
4568
|
+
if (!commandExists("openclaw")) {
|
|
4569
|
+
printWarn("\n Skipping gateway restart: openclaw not in PATH. After fixing PATH: openclaw gateway restart");
|
|
4570
|
+
} else {
|
|
4571
|
+
print("\n Restarting gateway...\n");
|
|
4572
|
+
try {
|
|
4573
|
+
execFileSync("openclaw", ["gateway", "restart"], { stdio: "inherit" });
|
|
4574
|
+
printSuccess(" Gateway restarted.");
|
|
4575
|
+
} catch {
|
|
4576
|
+
printWarn(" Gateway restart returned non-zero. Try manually: openclaw gateway restart");
|
|
4577
|
+
}
|
|
4467
4578
|
}
|
|
4468
4579
|
}
|
|
4469
4580
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "traderclaw-cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.103",
|
|
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.
|
|
20
|
+
"solana-traderclaw": "^1.0.103"
|
|
21
21
|
},
|
|
22
22
|
"keywords": [
|
|
23
23
|
"traderclaw",
|