traderclaw-cli 1.0.117 → 1.0.120
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/installer-step-engine.mjs +77 -11
- package/package.json +2 -2
|
@@ -284,6 +284,47 @@ function getCommandOutput(cmd, { timeoutMs = 0 } = {}) {
|
|
|
284
284
|
}
|
|
285
285
|
}
|
|
286
286
|
|
|
287
|
+
/**
|
|
288
|
+
* First existing `skills/solana-trader` directory: local package → OpenClaw extension → global npm.
|
|
289
|
+
* @param {{ pluginId: string, pluginPackage: string }} modeConfig
|
|
290
|
+
* @returns {string|null}
|
|
291
|
+
*/
|
|
292
|
+
export function resolveSolanaTraderPackagedRoot(modeConfig) {
|
|
293
|
+
const candidates = [
|
|
294
|
+
join(PLUGIN_PACKAGE_ROOT, "skills", "solana-trader"),
|
|
295
|
+
join(homedir(), ".openclaw", "extensions", modeConfig.pluginId, "skills", "solana-trader"),
|
|
296
|
+
];
|
|
297
|
+
const npmRoot = getCommandOutput("npm root -g");
|
|
298
|
+
if (npmRoot) {
|
|
299
|
+
candidates.push(join(npmRoot, modeConfig.pluginPackage, "skills", "solana-trader"));
|
|
300
|
+
}
|
|
301
|
+
for (const dir of candidates) {
|
|
302
|
+
if (existsSync(dir)) return dir;
|
|
303
|
+
}
|
|
304
|
+
return null;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* First existing gateway template file under `config/{filename}`.
|
|
309
|
+
* @param {{ pluginId: string, pluginPackage: string }} modeConfig
|
|
310
|
+
* @param {string} gatewayConfigFilename
|
|
311
|
+
* @returns {string|null}
|
|
312
|
+
*/
|
|
313
|
+
function resolveGatewayConfigSourcePath(modeConfig, gatewayConfigFilename) {
|
|
314
|
+
const candidates = [
|
|
315
|
+
join(PLUGIN_PACKAGE_ROOT, "config", gatewayConfigFilename),
|
|
316
|
+
join(homedir(), ".openclaw", "extensions", modeConfig.pluginId, "config", gatewayConfigFilename),
|
|
317
|
+
];
|
|
318
|
+
const npmRoot = getCommandOutput("npm root -g");
|
|
319
|
+
if (npmRoot) {
|
|
320
|
+
candidates.push(join(npmRoot, modeConfig.pluginPackage, "config", gatewayConfigFilename));
|
|
321
|
+
}
|
|
322
|
+
for (const p of candidates) {
|
|
323
|
+
if (existsSync(p)) return p;
|
|
324
|
+
}
|
|
325
|
+
return null;
|
|
326
|
+
}
|
|
327
|
+
|
|
287
328
|
function extractUrls(text = "") {
|
|
288
329
|
const matches = text.match(/https?:\/\/[^\s"')]+/g);
|
|
289
330
|
return matches ? [...new Set(matches)] : [];
|
|
@@ -757,6 +798,31 @@ async function installAndEnableOpenClawPlugin(modeConfig, onEvent, orchestratorU
|
|
|
757
798
|
};
|
|
758
799
|
}
|
|
759
800
|
|
|
801
|
+
/**
|
|
802
|
+
* Idempotent: ensure OpenClaw discovers skills under ~/.openclaw/extensions/<pluginId>/skills (extraDirs).
|
|
803
|
+
* See OpenClaw workspace skill loader: config.skills.load.extraDirs → openclaw-extra.
|
|
804
|
+
* @param {Record<string, unknown>} config
|
|
805
|
+
* @param {string} pluginId
|
|
806
|
+
*/
|
|
807
|
+
function ensureTraderSkillsExtraDir(config, pluginId) {
|
|
808
|
+
const marker = `.openclaw/extensions/${pluginId}/skills`;
|
|
809
|
+
const tildeEntry = `~/.openclaw/extensions/${pluginId}/skills`;
|
|
810
|
+
if (!config.skills || typeof config.skills !== "object") config.skills = {};
|
|
811
|
+
if (!config.skills.load || typeof config.skills.load !== "object") config.skills.load = {};
|
|
812
|
+
const raw = config.skills.load.extraDirs;
|
|
813
|
+
const dirs = Array.isArray(raw) ? [...raw] : [];
|
|
814
|
+
const normalized = (d) => (typeof d === "string" ? d.replace(/\\/g, "/") : "");
|
|
815
|
+
const needle = normalized(tildeEntry);
|
|
816
|
+
const hasMarker = dirs.some((d) => {
|
|
817
|
+
const n = normalized(d);
|
|
818
|
+
return n.includes(marker) || n === needle;
|
|
819
|
+
});
|
|
820
|
+
if (!hasMarker) {
|
|
821
|
+
dirs.push(tildeEntry);
|
|
822
|
+
config.skills.load.extraDirs = dirs;
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
|
|
760
826
|
function seedPluginConfig(modeConfig, orchestratorUrl, configPath = CONFIG_FILE) {
|
|
761
827
|
const defaultUrl = orchestratorUrl || "https://api.traderclaw.ai";
|
|
762
828
|
|
|
@@ -794,6 +860,8 @@ function seedPluginConfig(modeConfig, orchestratorUrl, configPath = CONFIG_FILE)
|
|
|
794
860
|
|
|
795
861
|
mergeOrchestratorForId(modeConfig.pluginId);
|
|
796
862
|
|
|
863
|
+
ensureTraderSkillsExtraDir(config, modeConfig.pluginId);
|
|
864
|
+
|
|
797
865
|
// Do not set plugins.allow here: OpenClaw validates allow[] against the plugin registry, and
|
|
798
866
|
// the id is not registered until after `openclaw plugins install`. Pre-seeding allow caused:
|
|
799
867
|
// "plugins.allow: plugin not found: <id>".
|
|
@@ -1316,10 +1384,8 @@ function deployGatewayConfig(modeConfig) {
|
|
|
1316
1384
|
const gatewayDir = join(CONFIG_DIR, "gateway");
|
|
1317
1385
|
mkdirSync(gatewayDir, { recursive: true });
|
|
1318
1386
|
const destFile = join(gatewayDir, modeConfig.gatewayConfig);
|
|
1319
|
-
const
|
|
1320
|
-
if (!
|
|
1321
|
-
const src = join(npmRoot, modeConfig.pluginPackage, "config", modeConfig.gatewayConfig);
|
|
1322
|
-
if (!existsSync(src)) return { deployed: false, dest: destFile };
|
|
1387
|
+
const src = resolveGatewayConfigSourcePath(modeConfig, modeConfig.gatewayConfig);
|
|
1388
|
+
if (!src) return { deployed: false, dest: destFile };
|
|
1323
1389
|
writeFileSync(destFile, readFileSync(src));
|
|
1324
1390
|
return { deployed: true, source: src, dest: destFile };
|
|
1325
1391
|
}
|
|
@@ -1356,13 +1422,13 @@ export function resolveAgentWorkspaceDir(configPath = CONFIG_FILE) {
|
|
|
1356
1422
|
}
|
|
1357
1423
|
|
|
1358
1424
|
/**
|
|
1359
|
-
* Copy skills/solana-trader/HEARTBEAT.md from the
|
|
1425
|
+
* Copy skills/solana-trader/HEARTBEAT.md from the plugin package, OpenClaw extension, or global npm into the workspace root.
|
|
1360
1426
|
* Skips overwrite if a non-empty file already exists (user may have customized it).
|
|
1361
1427
|
*/
|
|
1362
1428
|
export function deployWorkspaceHeartbeat(modeConfig) {
|
|
1363
|
-
const
|
|
1364
|
-
if (!
|
|
1365
|
-
const src = join(
|
|
1429
|
+
const skillRoot = resolveSolanaTraderPackagedRoot(modeConfig);
|
|
1430
|
+
if (!skillRoot) return { deployed: false, reason: "source_missing" };
|
|
1431
|
+
const src = join(skillRoot, "HEARTBEAT.md");
|
|
1366
1432
|
if (!existsSync(src)) return { deployed: false, reason: "source_missing", src };
|
|
1367
1433
|
|
|
1368
1434
|
const workspaceDir = resolveAgentWorkspaceDir(CONFIG_FILE);
|
|
@@ -1389,10 +1455,10 @@ export function deployWorkspaceHeartbeat(modeConfig) {
|
|
|
1389
1455
|
* Skips files that already exist and are non-empty so user customisations are preserved.
|
|
1390
1456
|
*/
|
|
1391
1457
|
export function deployWorkspaceBootstrapFiles(modeConfig) {
|
|
1392
|
-
const
|
|
1393
|
-
if (!
|
|
1458
|
+
const skillRoot = resolveSolanaTraderPackagedRoot(modeConfig);
|
|
1459
|
+
if (!skillRoot) return { deployed: [], skipped: [], failed: [], reason: "source_dir_missing" };
|
|
1394
1460
|
|
|
1395
|
-
const srcDir = join(
|
|
1461
|
+
const srcDir = join(skillRoot, "workspace");
|
|
1396
1462
|
if (!existsSync(srcDir)) return { deployed: [], skipped: [], failed: [], reason: "source_dir_missing", srcDir };
|
|
1397
1463
|
|
|
1398
1464
|
const workspaceDir = resolveAgentWorkspaceDir(CONFIG_FILE);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "traderclaw-cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.120",
|
|
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.120"
|
|
21
21
|
},
|
|
22
22
|
"keywords": [
|
|
23
23
|
"traderclaw",
|