@opentrust/cli 7.3.33 → 7.3.34

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.
@@ -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,29 @@ 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
- const cmds = await client.fetchPendingCommands();
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 may be unreachable
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
+ let result;
174
+ try {
175
+ result = executeHostCommand(cmd);
176
+ }
177
+ catch (err) {
178
+ log(`Command ${cmd.id} threw unexpectedly: ${err.message ?? err}`);
179
+ result = { success: false, error: `Unexpected error: ${(err.message ?? String(err)).slice(0, 500)}` };
180
+ }
181
+ const status = result.success ? "completed" : "failed";
182
+ await client
183
+ .ackCommand(cmd.id, status, { output: result.output, error: result.error })
184
+ .catch((e) => log(`Failed to ack command ${cmd.id}: ${e.message}`));
185
+ log(`Command ${cmd.id}: ${status}`);
179
186
  }
180
187
  };
181
188
  const pollTimer = setInterval(poll, POLL_INTERVAL);
@@ -13,9 +13,9 @@ const SCAFFOLD_PKG = {
13
13
  status: "opentrust status",
14
14
  },
15
15
  dependencies: {
16
- "@opentrust/core": "^7.3.33",
17
- "@opentrust/gateway": "^7.3.33",
18
- "@opentrust/dashboard": "^7.3.33",
16
+ "@opentrust/core": "^7.3.34",
17
+ "@opentrust/gateway": "^7.3.34",
18
+ "@opentrust/dashboard": "^7.3.34",
19
19
  },
20
20
  };
21
21
  const ENV_TEMPLATE = `# OpenTrust Configuration
@@ -1,7 +1,8 @@
1
- import type { HostCommand } from "./dashboard-client.js";
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 declare function setCommandLogger(fn: (msg: string) => void): void;
7
8
  export declare function executeHostCommand(cmd: HostCommand): CommandResult;
@@ -4,6 +4,11 @@ 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
+ function cmdLog(msg) { if (_logger)
11
+ _logger(msg); }
7
12
  const SERVICE_KEYS = Object.keys(SERVICES);
8
13
  const OPENCLAW_HOME = process.env.OPENCLAW_HOME || path.join(os.homedir(), ".openclaw");
9
14
  function clawExecOpts(timeoutMs = 120_000) {
@@ -289,51 +294,108 @@ function handleUpgradeGuards(payload) {
289
294
  };
290
295
  }
291
296
  // ── OpenClaw installation ────────────────────────────
297
+ function findOpenclawBin() {
298
+ const candidates = [
299
+ path.join(os.homedir(), ".local", "bin", "openclaw"),
300
+ "/usr/local/bin/openclaw",
301
+ path.join(os.homedir(), ".openclaw", "bin", "openclaw"),
302
+ ];
303
+ for (const p of candidates) {
304
+ if (fs.existsSync(p))
305
+ return p;
306
+ }
307
+ return "openclaw";
308
+ }
292
309
  function handleInstallOpenclaw(payload) {
293
310
  const config = payload.config;
294
311
  if (!config)
295
312
  return { success: false, error: "Missing config in payload. Configure OpenClaw template in Settings first." };
296
313
  const results = [];
314
+ // Override Guards plugin URLs with the CLI's own connection URL
315
+ const cliConfig = loadConfig();
316
+ if (cliConfig?.dashboardUrl) {
317
+ const guardEntry = config?.plugins?.entries?.["opentrust-guard"];
318
+ if (guardEntry?.config) {
319
+ guardEntry.config.dashboardUrl = cliConfig.dashboardUrl;
320
+ guardEntry.config.coreUrl = cliConfig.dashboardUrl.replace(/:53667/, ":53666");
321
+ cmdLog(` Guards URLs → dashboardUrl=${guardEntry.config.dashboardUrl}, coreUrl=${guardEntry.config.coreUrl}`);
322
+ }
323
+ }
297
324
  // Step 1: Install OpenClaw via curl
325
+ cmdLog(" [1/3] Installing OpenClaw (curl -fsSL https://openclaw.ai/install.sh | bash)...");
298
326
  try {
299
- const output = execSync("curl -fsSL https://openclaw.ai/install.sh | bash", {
327
+ execSync("curl -fsSL https://openclaw.ai/install.sh | bash", {
300
328
  encoding: "utf-8",
301
- timeout: 300_000,
302
- stdio: ["pipe", "pipe", "pipe"],
329
+ timeout: 180_000,
330
+ stdio: ["pipe", "inherit", "inherit"],
303
331
  cwd: os.homedir(),
304
332
  env: { ...process.env, HOME: os.homedir() },
305
333
  shell: "/bin/bash",
306
334
  });
307
- results.push(`Install script: ${output.trim().split("\n").slice(-3).join(" | ")}`);
335
+ results.push("Install script: completed");
336
+ cmdLog(" [1/3] OpenClaw install script completed");
308
337
  }
309
338
  catch (err) {
310
- const stderr = err.stderr?.toString() || "";
311
- const stdout = err.stdout?.toString() || "";
312
- if (stdout.toLowerCase().includes("already installed") || stdout.toLowerCase().includes("openclaw")) {
313
- results.push(`Install script: ${stdout.trim().split("\n").slice(-2).join(" | ")} (may already be installed)`);
339
+ const code = err.status;
340
+ if (code === 0 || code === null) {
341
+ results.push("Install script: completed (non-zero might be ok)");
342
+ cmdLog(" [1/3] OpenClaw install script finished (exit code ignored)");
314
343
  }
315
344
  else {
316
- return { success: false, error: `Install script failed: ${(stderr || err.message || String(err)).slice(0, 500)}` };
345
+ const msg = `Install script exited with code ${code}`;
346
+ cmdLog(` [1/3] ${msg}`);
347
+ results.push(msg);
348
+ // Don't return failure — the binary may already exist or the error is non-fatal
317
349
  }
318
350
  }
319
351
  // Step 2: Write openclaw.json config
352
+ cmdLog(" [2/3] Writing ~/.openclaw/openclaw.json ...");
320
353
  try {
321
354
  const clawHome = path.join(os.homedir(), ".openclaw");
322
355
  fs.mkdirSync(clawHome, { recursive: true });
323
356
  const configFile = path.join(clawHome, "openclaw.json");
324
357
  fs.writeFileSync(configFile, JSON.stringify(config, null, 2) + "\n", "utf-8");
325
358
  results.push(`Config written to ${configFile}`);
359
+ cmdLog(` [2/3] Config written to ${configFile}`);
326
360
  }
327
361
  catch (err) {
328
- return { success: false, error: `Failed to write config: ${(err.message || String(err)).slice(0, 500)}` };
362
+ const msg = `Failed to write config: ${(err.message || String(err)).slice(0, 500)}`;
363
+ cmdLog(` [2/3] ${msg}`);
364
+ return { success: false, error: msg };
329
365
  }
330
- // Step 3: Auto-install Guards plugin
331
- const guardsResult = runClawPluginCmd("openclaw plugins install @opentrust/guards");
332
- if (guardsResult.success) {
333
- results.push(`Guards plugin: installed${guardsResult.output ? ` (${guardsResult.output.split("\n").pop()})` : ""}`);
366
+ // Step 3: Auto-install Guards plugin — expand PATH to find freshly-installed openclaw
367
+ const clawBin = findOpenclawBin();
368
+ cmdLog(` [3/3] Installing Guards plugin (${clawBin} plugins install @opentrust/guards)...`);
369
+ try {
370
+ const extraPaths = [
371
+ path.join(os.homedir(), ".local", "bin"),
372
+ path.join(os.homedir(), ".openclaw", "bin"),
373
+ "/usr/local/bin",
374
+ ].join(":");
375
+ const { OPENCLAW_HOME: _, ...restEnv } = process.env;
376
+ const output = execSync(`${clawBin} plugins install @opentrust/guards`, {
377
+ encoding: "utf-8",
378
+ timeout: 180_000,
379
+ stdio: ["pipe", "pipe", "pipe"],
380
+ cwd: os.homedir(),
381
+ env: { ...restEnv, HOME: os.homedir(), PATH: `${extraPaths}:${process.env.PATH ?? ""}` },
382
+ });
383
+ results.push(`Guards plugin: installed`);
384
+ cmdLog(` [3/3] Guards plugin installed successfully`);
334
385
  }
335
- else {
336
- results.push(`Guards plugin: install failed — ${guardsResult.error?.slice(0, 200) ?? "unknown error"}`);
386
+ catch (err) {
387
+ const stderr = err.stderr?.toString() || "";
388
+ const stdout = err.stdout?.toString() || "";
389
+ if (isOnlyWarnings(stderr) || isOnlyWarnings(stdout + stderr)) {
390
+ results.push("Guards plugin: installed (with warnings)");
391
+ cmdLog(" [3/3] Guards plugin installed (with warnings)");
392
+ }
393
+ else {
394
+ const errMsg = (stderr || err.message || String(err)).slice(0, 300);
395
+ results.push(`Guards plugin: install failed — ${errMsg}`);
396
+ cmdLog(` [3/3] Guards plugin install failed: ${errMsg}`);
397
+ }
337
398
  }
399
+ cmdLog(" install_openclaw complete");
338
400
  return { success: true, output: results.join("\n") };
339
401
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opentrust/cli",
3
- "version": "7.3.33",
3
+ "version": "7.3.34",
4
4
  "description": "CLI tool to manage OpenTrust AI Agent Runtime Security Platform — setup, start, stop, status, logs",
5
5
  "type": "module",
6
6
  "bin": {