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.
- package/bin/gateway-persistence-linux.mjs +15 -4
- package/bin/installer-step-engine.mjs +39 -20
- package/bin/openclaw-trader.mjs +136 -12
- 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
|
}
|
|
@@ -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
|
-
|
|
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
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
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
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
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" };
|
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";
|
|
@@ -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", () =>
|
|
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
|
|
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
|
|
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
|
-
|
|
4459
|
-
|
|
4460
|
-
|
|
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
|
-
|
|
4464
|
-
|
|
4465
|
-
|
|
4466
|
-
|
|
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.
|
|
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.
|
|
20
|
+
"solana-traderclaw": "^1.0.104"
|
|
21
21
|
},
|
|
22
22
|
"keywords": [
|
|
23
23
|
"traderclaw",
|