@opentrust/cli 7.3.33 → 7.3.35
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/dist/commands/connect.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DashboardClient, loadConfig, saveConfig, clearConfig, } from "../lib/dashboard-client.js";
|
|
2
2
|
import { getHostInfo, getServicesSnapshot, getSystemMetadata } from "../lib/host-reporter.js";
|
|
3
|
-
import { executeHostCommand } from "../lib/command-handler.js";
|
|
3
|
+
import { executeHostCommand, setCommandLogger } from "../lib/command-handler.js";
|
|
4
4
|
import { projectMode, projectRoot } from "../lib/paths.js";
|
|
5
5
|
import fs from "node:fs";
|
|
6
6
|
import path from "node:path";
|
|
@@ -124,6 +124,7 @@ function stopDaemon() {
|
|
|
124
124
|
async function runDaemon(config) {
|
|
125
125
|
const client = new DashboardClient(config);
|
|
126
126
|
const log = (msg) => console.log(`[${new Date().toISOString()}] ${msg}`);
|
|
127
|
+
setCommandLogger(log);
|
|
127
128
|
// Register
|
|
128
129
|
log("Registering with Dashboard...");
|
|
129
130
|
const hostInfo = getHostInfo();
|
|
@@ -159,23 +160,32 @@ async function runDaemon(config) {
|
|
|
159
160
|
const heartbeatTimer = setInterval(heartbeat, HEARTBEAT_INTERVAL);
|
|
160
161
|
// Command polling
|
|
161
162
|
const poll = async () => {
|
|
163
|
+
let cmds;
|
|
162
164
|
try {
|
|
163
|
-
|
|
164
|
-
for (const cmd of cmds) {
|
|
165
|
-
log(`Executing command: ${cmd.type} (${cmd.id})`);
|
|
166
|
-
await client.ackCommand(cmd.id, "running").catch(() => { });
|
|
167
|
-
const result = executeHostCommand(cmd);
|
|
168
|
-
await client
|
|
169
|
-
.ackCommand(cmd.id, result.success ? "completed" : "failed", {
|
|
170
|
-
output: result.output,
|
|
171
|
-
error: result.error,
|
|
172
|
-
})
|
|
173
|
-
.catch(() => { });
|
|
174
|
-
log(`Command ${cmd.id}: ${result.success ? "completed" : "failed"}`);
|
|
175
|
-
}
|
|
165
|
+
cmds = await client.fetchPendingCommands();
|
|
176
166
|
}
|
|
177
167
|
catch {
|
|
178
|
-
// Dashboard
|
|
168
|
+
return; // Dashboard unreachable
|
|
169
|
+
}
|
|
170
|
+
for (const cmd of cmds) {
|
|
171
|
+
log(`Executing command: ${cmd.type} (${cmd.id})`);
|
|
172
|
+
await client.ackCommand(cmd.id, "running").catch(() => { });
|
|
173
|
+
const progressFn = async (output) => {
|
|
174
|
+
await client.ackCommand(cmd.id, "running", { output }).catch(() => { });
|
|
175
|
+
};
|
|
176
|
+
let result;
|
|
177
|
+
try {
|
|
178
|
+
result = await executeHostCommand(cmd, progressFn);
|
|
179
|
+
}
|
|
180
|
+
catch (err) {
|
|
181
|
+
log(`Command ${cmd.id} threw unexpectedly: ${err.message ?? err}`);
|
|
182
|
+
result = { success: false, error: `Unexpected error: ${(err.message ?? String(err)).slice(0, 500)}` };
|
|
183
|
+
}
|
|
184
|
+
const status = result.success ? "completed" : "failed";
|
|
185
|
+
await client
|
|
186
|
+
.ackCommand(cmd.id, status, { output: result.output, error: result.error })
|
|
187
|
+
.catch((e) => log(`Failed to ack command ${cmd.id}: ${e.message}`));
|
|
188
|
+
log(`Command ${cmd.id}: ${status}`);
|
|
179
189
|
}
|
|
180
190
|
};
|
|
181
191
|
const pollTimer = setInterval(poll, POLL_INTERVAL);
|
package/dist/commands/init.js
CHANGED
|
@@ -13,9 +13,9 @@ const SCAFFOLD_PKG = {
|
|
|
13
13
|
status: "opentrust status",
|
|
14
14
|
},
|
|
15
15
|
dependencies: {
|
|
16
|
-
"@opentrust/core": "^7.3.
|
|
17
|
-
"@opentrust/gateway": "^7.3.
|
|
18
|
-
"@opentrust/dashboard": "^7.3.
|
|
16
|
+
"@opentrust/core": "^7.3.35",
|
|
17
|
+
"@opentrust/gateway": "^7.3.35",
|
|
18
|
+
"@opentrust/dashboard": "^7.3.35",
|
|
19
19
|
},
|
|
20
20
|
};
|
|
21
21
|
const ENV_TEMPLATE = `# OpenTrust Configuration
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type HostCommand } from "./dashboard-client.js";
|
|
2
2
|
export interface CommandResult {
|
|
3
3
|
success: boolean;
|
|
4
4
|
output?: string;
|
|
5
5
|
error?: string;
|
|
6
6
|
}
|
|
7
|
-
export
|
|
7
|
+
export type ProgressFn = (output: string) => Promise<void>;
|
|
8
|
+
export declare function setCommandLogger(fn: (msg: string) => void): void;
|
|
9
|
+
export declare function executeHostCommand(cmd: HostCommand, progress?: ProgressFn): Promise<CommandResult>;
|
|
@@ -4,6 +4,15 @@ import path from "node:path";
|
|
|
4
4
|
import os from "node:os";
|
|
5
5
|
import { startService, stopService, getStatus, SERVICES } from "./process-manager.js";
|
|
6
6
|
import { paths, projectRoot, projectMode } from "./paths.js";
|
|
7
|
+
import { loadConfig } from "./dashboard-client.js";
|
|
8
|
+
let _logger = null;
|
|
9
|
+
export function setCommandLogger(fn) { _logger = fn; }
|
|
10
|
+
let _cmdOutput = [];
|
|
11
|
+
function cmdLog(msg) {
|
|
12
|
+
if (_logger)
|
|
13
|
+
_logger(msg);
|
|
14
|
+
_cmdOutput.push(msg);
|
|
15
|
+
}
|
|
7
16
|
const SERVICE_KEYS = Object.keys(SERVICES);
|
|
8
17
|
const OPENCLAW_HOME = process.env.OPENCLAW_HOME || path.join(os.homedir(), ".openclaw");
|
|
9
18
|
function clawExecOpts(timeoutMs = 120_000) {
|
|
@@ -16,7 +25,8 @@ function clawExecOpts(timeoutMs = 120_000) {
|
|
|
16
25
|
env: { ...restEnv, HOME: os.homedir() },
|
|
17
26
|
};
|
|
18
27
|
}
|
|
19
|
-
export function executeHostCommand(cmd) {
|
|
28
|
+
export async function executeHostCommand(cmd, progress) {
|
|
29
|
+
_cmdOutput = [];
|
|
20
30
|
const payload = cmd.payload ?? {};
|
|
21
31
|
switch (cmd.type) {
|
|
22
32
|
case "start_service":
|
|
@@ -48,7 +58,7 @@ export function executeHostCommand(cmd) {
|
|
|
48
58
|
case "upgrade_guards":
|
|
49
59
|
return handleUpgradeGuards(payload);
|
|
50
60
|
case "install_openclaw":
|
|
51
|
-
return handleInstallOpenclaw(payload);
|
|
61
|
+
return handleInstallOpenclaw(payload, progress);
|
|
52
62
|
default:
|
|
53
63
|
return { success: false, error: `Unknown command type: ${cmd.type}` };
|
|
54
64
|
}
|
|
@@ -289,51 +299,116 @@ function handleUpgradeGuards(payload) {
|
|
|
289
299
|
};
|
|
290
300
|
}
|
|
291
301
|
// ── OpenClaw installation ────────────────────────────
|
|
292
|
-
function
|
|
302
|
+
function findOpenclawBin() {
|
|
303
|
+
const candidates = [
|
|
304
|
+
path.join(os.homedir(), ".local", "bin", "openclaw"),
|
|
305
|
+
"/usr/local/bin/openclaw",
|
|
306
|
+
path.join(os.homedir(), ".openclaw", "bin", "openclaw"),
|
|
307
|
+
];
|
|
308
|
+
for (const p of candidates) {
|
|
309
|
+
if (fs.existsSync(p))
|
|
310
|
+
return p;
|
|
311
|
+
}
|
|
312
|
+
return "openclaw";
|
|
313
|
+
}
|
|
314
|
+
async function handleInstallOpenclaw(payload, progress) {
|
|
293
315
|
const config = payload.config;
|
|
294
316
|
if (!config)
|
|
295
317
|
return { success: false, error: "Missing config in payload. Configure OpenClaw template in Settings first." };
|
|
296
|
-
const
|
|
318
|
+
const sendProgress = async () => {
|
|
319
|
+
if (progress)
|
|
320
|
+
await progress(_cmdOutput.join("\n")).catch(() => { });
|
|
321
|
+
};
|
|
322
|
+
// Override Guards plugin URLs with the CLI's own connection URL
|
|
323
|
+
const cliConfig = loadConfig();
|
|
324
|
+
if (cliConfig?.dashboardUrl) {
|
|
325
|
+
if (!config.plugins)
|
|
326
|
+
config.plugins = {};
|
|
327
|
+
if (!config.plugins.entries)
|
|
328
|
+
config.plugins.entries = {};
|
|
329
|
+
if (!config.plugins.entries["opentrust-guard"])
|
|
330
|
+
config.plugins.entries["opentrust-guard"] = { enabled: true, config: {} };
|
|
331
|
+
if (!config.plugins.entries["opentrust-guard"].config)
|
|
332
|
+
config.plugins.entries["opentrust-guard"].config = {};
|
|
333
|
+
const gc = config.plugins.entries["opentrust-guard"].config;
|
|
334
|
+
gc.dashboardUrl = cliConfig.dashboardUrl;
|
|
335
|
+
gc.coreUrl = cliConfig.dashboardUrl.replace(/:(\d+)$/, (_, port) => {
|
|
336
|
+
return `:${Number(port) === 53667 ? 53666 : Number(port) - 1}`;
|
|
337
|
+
});
|
|
338
|
+
cmdLog(`Guards URLs → dashboardUrl=${gc.dashboardUrl}, coreUrl=${gc.coreUrl}`);
|
|
339
|
+
}
|
|
297
340
|
// Step 1: Install OpenClaw via curl
|
|
341
|
+
cmdLog("[1/3] Installing OpenClaw (curl -fsSL https://openclaw.ai/install.sh | bash)...");
|
|
342
|
+
await sendProgress();
|
|
298
343
|
try {
|
|
299
|
-
|
|
344
|
+
execSync("curl -fsSL https://openclaw.ai/install.sh | bash", {
|
|
300
345
|
encoding: "utf-8",
|
|
301
|
-
timeout:
|
|
302
|
-
stdio: ["pipe", "
|
|
346
|
+
timeout: 180_000,
|
|
347
|
+
stdio: ["pipe", "inherit", "inherit"],
|
|
303
348
|
cwd: os.homedir(),
|
|
304
349
|
env: { ...process.env, HOME: os.homedir() },
|
|
305
350
|
shell: "/bin/bash",
|
|
306
351
|
});
|
|
307
|
-
|
|
352
|
+
cmdLog("[1/3] OpenClaw install script completed");
|
|
308
353
|
}
|
|
309
354
|
catch (err) {
|
|
310
|
-
const
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
results.push(`Install script: ${stdout.trim().split("\n").slice(-2).join(" | ")} (may already be installed)`);
|
|
355
|
+
const code = err.status;
|
|
356
|
+
if (code === 0 || code === null) {
|
|
357
|
+
cmdLog("[1/3] OpenClaw install script finished (exit code ignored)");
|
|
314
358
|
}
|
|
315
359
|
else {
|
|
316
|
-
|
|
360
|
+
cmdLog(`[1/3] Install script exited with code ${code}`);
|
|
317
361
|
}
|
|
318
362
|
}
|
|
363
|
+
await sendProgress();
|
|
319
364
|
// Step 2: Write openclaw.json config
|
|
365
|
+
cmdLog("[2/3] Writing ~/.openclaw/openclaw.json ...");
|
|
366
|
+
await sendProgress();
|
|
320
367
|
try {
|
|
321
368
|
const clawHome = path.join(os.homedir(), ".openclaw");
|
|
322
369
|
fs.mkdirSync(clawHome, { recursive: true });
|
|
323
370
|
const configFile = path.join(clawHome, "openclaw.json");
|
|
324
371
|
fs.writeFileSync(configFile, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
325
|
-
|
|
372
|
+
cmdLog(`[2/3] Config written to ${configFile}`);
|
|
326
373
|
}
|
|
327
374
|
catch (err) {
|
|
328
|
-
|
|
375
|
+
const msg = `Failed to write config: ${(err.message || String(err)).slice(0, 500)}`;
|
|
376
|
+
cmdLog(`[2/3] ${msg}`);
|
|
377
|
+
await sendProgress();
|
|
378
|
+
return { success: false, output: _cmdOutput.join("\n"), error: msg };
|
|
329
379
|
}
|
|
380
|
+
await sendProgress();
|
|
330
381
|
// Step 3: Auto-install Guards plugin
|
|
331
|
-
const
|
|
332
|
-
|
|
333
|
-
|
|
382
|
+
const clawBin = findOpenclawBin();
|
|
383
|
+
cmdLog(`[3/3] Installing Guards plugin (${clawBin} plugins install @opentrust/guards)...`);
|
|
384
|
+
await sendProgress();
|
|
385
|
+
try {
|
|
386
|
+
const extraPaths = [
|
|
387
|
+
path.join(os.homedir(), ".local", "bin"),
|
|
388
|
+
path.join(os.homedir(), ".openclaw", "bin"),
|
|
389
|
+
"/usr/local/bin",
|
|
390
|
+
].join(":");
|
|
391
|
+
const { OPENCLAW_HOME: _, ...restEnv } = process.env;
|
|
392
|
+
execSync(`${clawBin} plugins install @opentrust/guards`, {
|
|
393
|
+
encoding: "utf-8",
|
|
394
|
+
timeout: 180_000,
|
|
395
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
396
|
+
cwd: os.homedir(),
|
|
397
|
+
env: { ...restEnv, HOME: os.homedir(), PATH: `${extraPaths}:${process.env.PATH ?? ""}` },
|
|
398
|
+
});
|
|
399
|
+
cmdLog("[3/3] Guards plugin installed successfully");
|
|
334
400
|
}
|
|
335
|
-
|
|
336
|
-
|
|
401
|
+
catch (err) {
|
|
402
|
+
const stderr = err.stderr?.toString() || "";
|
|
403
|
+
const stdout = err.stdout?.toString() || "";
|
|
404
|
+
if (isOnlyWarnings(stderr) || isOnlyWarnings(stdout + stderr)) {
|
|
405
|
+
cmdLog("[3/3] Guards plugin installed (with warnings)");
|
|
406
|
+
}
|
|
407
|
+
else {
|
|
408
|
+
const errMsg = (stderr || err.message || String(err)).slice(0, 300);
|
|
409
|
+
cmdLog(`[3/3] Guards plugin install failed: ${errMsg}`);
|
|
410
|
+
}
|
|
337
411
|
}
|
|
338
|
-
|
|
412
|
+
cmdLog("install_openclaw complete");
|
|
413
|
+
return { success: true, output: _cmdOutput.join("\n") };
|
|
339
414
|
}
|