solana-traderclaw 1.0.25 → 1.0.27
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 +48 -17
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { execSync, spawn } from "child_process";
|
|
2
2
|
import { randomBytes } from "crypto";
|
|
3
|
-
import { existsSync, mkdirSync, readFileSync, renameSync, statSync, writeFileSync } from "fs";
|
|
3
|
+
import { existsSync, mkdirSync, mkdtempSync, readFileSync, renameSync, statSync, writeFileSync } from "fs";
|
|
4
4
|
import { homedir, tmpdir } from "os";
|
|
5
5
|
import { dirname, join } from "path";
|
|
6
6
|
import { fileURLToPath } from "url";
|
|
@@ -13,16 +13,48 @@ const CONFIG_FILE = join(CONFIG_DIR, "openclaw.json");
|
|
|
13
13
|
/** Directory containing this package when running from a git checkout or global npm install. */
|
|
14
14
|
const PLUGIN_PACKAGE_ROOT = join(dirname(fileURLToPath(import.meta.url)), "..");
|
|
15
15
|
|
|
16
|
-
function
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
16
|
+
function readPluginPackageVersion() {
|
|
17
|
+
const pkgJsonPath = join(PLUGIN_PACKAGE_ROOT, "package.json");
|
|
18
|
+
if (!existsSync(pkgJsonPath)) return null;
|
|
19
|
+
try {
|
|
20
|
+
const pkg = JSON.parse(readFileSync(pkgJsonPath, "utf-8"));
|
|
21
|
+
return typeof pkg.version === "string" && pkg.version.trim().length ? pkg.version.trim() : null;
|
|
22
|
+
} catch {
|
|
23
|
+
return null;
|
|
21
24
|
}
|
|
22
|
-
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Spec for `npm install -g` and `openclaw plugins install`.
|
|
29
|
+
* Prefer explicit registry coordinates (`package@version`) so npm never resolves a bare name or `file:`
|
|
30
|
+
* relative to cwd (e.g. /root when TMPDIR or shadow folders break resolution).
|
|
31
|
+
* Local directory install is opt-in for dev/offline: TRADERCLAW_INSTALLER_USE_LOCAL_PACKAGE=1.
|
|
32
|
+
*/
|
|
33
|
+
function resolveRegistryPluginInstallSpec(modeConfig) {
|
|
34
|
+
if (process.env.TRADERCLAW_INSTALLER_USE_LOCAL_PACKAGE === "1") {
|
|
35
|
+
const manifest = join(PLUGIN_PACKAGE_ROOT, "openclaw.plugin.json");
|
|
36
|
+
const pkgJson = join(PLUGIN_PACKAGE_ROOT, "package.json");
|
|
37
|
+
if (existsSync(manifest) && existsSync(pkgJson)) {
|
|
38
|
+
return PLUGIN_PACKAGE_ROOT;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
const v = readPluginPackageVersion();
|
|
42
|
+
if (v) return `${modeConfig.pluginPackage}@${v}`;
|
|
23
43
|
return `${modeConfig.pluginPackage}@latest`;
|
|
24
44
|
}
|
|
25
45
|
|
|
46
|
+
/** Empty per-invocation cwd for npm global installs — avoids TMPDIR=/root and stray ./solana-traderclaw shadowing. */
|
|
47
|
+
function getNpmGlobalInstallCwd() {
|
|
48
|
+
if (process.platform === "win32") {
|
|
49
|
+
return mkdtempSync(join(tmpdir(), "tc-npm-"));
|
|
50
|
+
}
|
|
51
|
+
try {
|
|
52
|
+
return mkdtempSync(join("/tmp", "tc-npm-"));
|
|
53
|
+
} catch {
|
|
54
|
+
return mkdtempSync(join(tmpdir(), "tc-npm-"));
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
26
58
|
/** Older `plugins.entries` keys / npm-era ids to merge orchestrator URL for. */
|
|
27
59
|
const LEGACY_TRADER_PLUGIN_IDS = ["traderclaw-v1", "solana-traderclaw-v1", "solana-trader"];
|
|
28
60
|
|
|
@@ -172,16 +204,17 @@ function gatewayModeUnsetRemediation() {
|
|
|
172
204
|
|
|
173
205
|
function runCommandWithEvents(cmd, args = [], opts = {}) {
|
|
174
206
|
return new Promise((resolve, reject) => {
|
|
207
|
+
const { onEvent, ...spawnOpts } = opts;
|
|
175
208
|
const child = spawn(cmd, args, {
|
|
176
209
|
stdio: "pipe",
|
|
177
210
|
shell: true,
|
|
178
|
-
...
|
|
211
|
+
...spawnOpts,
|
|
179
212
|
});
|
|
180
213
|
|
|
181
214
|
let stdout = "";
|
|
182
215
|
let stderr = "";
|
|
183
|
-
const
|
|
184
|
-
const emit = (event) =>
|
|
216
|
+
const emitFn = typeof onEvent === "function" ? onEvent : null;
|
|
217
|
+
const emit = (event) => emitFn && emitFn(event);
|
|
185
218
|
|
|
186
219
|
child.stdout?.on("data", (d) => {
|
|
187
220
|
const text = d.toString();
|
|
@@ -253,7 +286,7 @@ function npmGlobalInstallArgs(spec, { force = false } = {}) {
|
|
|
253
286
|
}
|
|
254
287
|
|
|
255
288
|
async function installPlugin(modeConfig, onEvent) {
|
|
256
|
-
const spec =
|
|
289
|
+
const spec = resolveRegistryPluginInstallSpec(modeConfig);
|
|
257
290
|
const isLocalPluginRoot =
|
|
258
291
|
typeof spec === "string" &&
|
|
259
292
|
existsSync(join(spec, "openclaw.plugin.json")) &&
|
|
@@ -265,7 +298,7 @@ async function installPlugin(modeConfig, onEvent) {
|
|
|
265
298
|
urls: [],
|
|
266
299
|
});
|
|
267
300
|
}
|
|
268
|
-
const npmCwd =
|
|
301
|
+
const npmCwd = getNpmGlobalInstallCwd();
|
|
269
302
|
if (typeof onEvent === "function") {
|
|
270
303
|
onEvent({
|
|
271
304
|
type: "stdout",
|
|
@@ -322,7 +355,7 @@ async function installAndEnableOpenClawPlugin(modeConfig, onEvent, orchestratorU
|
|
|
322
355
|
|
|
323
356
|
seedPluginConfig(modeConfig, orchestratorUrl || "https://api.traderclaw.ai");
|
|
324
357
|
|
|
325
|
-
const pluginInstallSpec =
|
|
358
|
+
const pluginInstallSpec = resolveRegistryPluginInstallSpec(modeConfig);
|
|
326
359
|
let recoveredExistingDir = null;
|
|
327
360
|
try {
|
|
328
361
|
await runCommandWithEvents("openclaw", ["plugins", "install", pluginInstallSpec], { onEvent });
|
|
@@ -781,8 +814,7 @@ function deployGatewayConfig(modeConfig) {
|
|
|
781
814
|
const destFile = join(gatewayDir, modeConfig.gatewayConfig);
|
|
782
815
|
const npmRoot = getCommandOutput("npm root -g");
|
|
783
816
|
if (!npmRoot) return { deployed: false, dest: destFile };
|
|
784
|
-
const
|
|
785
|
-
const src = join(npmRoot, spec, "config", modeConfig.gatewayConfig);
|
|
817
|
+
const src = join(npmRoot, modeConfig.pluginPackage, "config", modeConfig.gatewayConfig);
|
|
786
818
|
if (!existsSync(src)) return { deployed: false, dest: destFile };
|
|
787
819
|
writeFileSync(destFile, readFileSync(src));
|
|
788
820
|
return { deployed: true, source: src, dest: destFile };
|
|
@@ -826,8 +858,7 @@ export function resolveAgentWorkspaceDir(configPath = CONFIG_FILE) {
|
|
|
826
858
|
export function deployWorkspaceHeartbeat(modeConfig) {
|
|
827
859
|
const npmRoot = getCommandOutput("npm root -g");
|
|
828
860
|
if (!npmRoot) return { deployed: false, reason: "npm_root_g_failed" };
|
|
829
|
-
const
|
|
830
|
-
const src = join(npmRoot, spec, "skills", "solana-trader", "HEARTBEAT.md");
|
|
861
|
+
const src = join(npmRoot, modeConfig.pluginPackage, "skills", "solana-trader", "HEARTBEAT.md");
|
|
831
862
|
if (!existsSync(src)) return { deployed: false, reason: "source_missing", src };
|
|
832
863
|
|
|
833
864
|
const workspaceDir = resolveAgentWorkspaceDir(CONFIG_FILE);
|
package/package.json
CHANGED