@opentrust/cli 7.3.34 → 7.3.36

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.
@@ -170,9 +170,12 @@ async function runDaemon(config) {
170
170
  for (const cmd of cmds) {
171
171
  log(`Executing command: ${cmd.type} (${cmd.id})`);
172
172
  await client.ackCommand(cmd.id, "running").catch(() => { });
173
+ const progressFn = async (output) => {
174
+ await client.ackCommand(cmd.id, "running", { output }).catch(() => { });
175
+ };
173
176
  let result;
174
177
  try {
175
- result = executeHostCommand(cmd);
178
+ result = await executeHostCommand(cmd, progressFn);
176
179
  }
177
180
  catch (err) {
178
181
  log(`Command ${cmd.id} threw unexpectedly: ${err.message ?? err}`);
@@ -13,9 +13,9 @@ const SCAFFOLD_PKG = {
13
13
  status: "opentrust status",
14
14
  },
15
15
  dependencies: {
16
- "@opentrust/core": "^7.3.34",
17
- "@opentrust/gateway": "^7.3.34",
18
- "@opentrust/dashboard": "^7.3.34",
16
+ "@opentrust/core": "^7.3.36",
17
+ "@opentrust/gateway": "^7.3.36",
18
+ "@opentrust/dashboard": "^7.3.36",
19
19
  },
20
20
  };
21
21
  const ENV_TEMPLATE = `# OpenTrust Configuration
@@ -4,5 +4,6 @@ export interface CommandResult {
4
4
  output?: string;
5
5
  error?: string;
6
6
  }
7
+ export type ProgressFn = (output: string) => Promise<void>;
7
8
  export declare function setCommandLogger(fn: (msg: string) => void): void;
8
- export declare function executeHostCommand(cmd: HostCommand): CommandResult;
9
+ export declare function executeHostCommand(cmd: HostCommand, progress?: ProgressFn): Promise<CommandResult>;
@@ -7,8 +7,12 @@ import { paths, projectRoot, projectMode } from "./paths.js";
7
7
  import { loadConfig } from "./dashboard-client.js";
8
8
  let _logger = null;
9
9
  export function setCommandLogger(fn) { _logger = fn; }
10
- function cmdLog(msg) { if (_logger)
11
- _logger(msg); }
10
+ let _cmdOutput = [];
11
+ function cmdLog(msg) {
12
+ if (_logger)
13
+ _logger(msg);
14
+ _cmdOutput.push(msg);
15
+ }
12
16
  const SERVICE_KEYS = Object.keys(SERVICES);
13
17
  const OPENCLAW_HOME = process.env.OPENCLAW_HOME || path.join(os.homedir(), ".openclaw");
14
18
  function clawExecOpts(timeoutMs = 120_000) {
@@ -21,7 +25,8 @@ function clawExecOpts(timeoutMs = 120_000) {
21
25
  env: { ...restEnv, HOME: os.homedir() },
22
26
  };
23
27
  }
24
- export function executeHostCommand(cmd) {
28
+ export async function executeHostCommand(cmd, progress) {
29
+ _cmdOutput = [];
25
30
  const payload = cmd.payload ?? {};
26
31
  switch (cmd.type) {
27
32
  case "start_service":
@@ -53,7 +58,7 @@ export function executeHostCommand(cmd) {
53
58
  case "upgrade_guards":
54
59
  return handleUpgradeGuards(payload);
55
60
  case "install_openclaw":
56
- return handleInstallOpenclaw(payload);
61
+ return handleInstallOpenclaw(payload, progress);
57
62
  default:
58
63
  return { success: false, error: `Unknown command type: ${cmd.type}` };
59
64
  }
@@ -300,102 +305,145 @@ function findOpenclawBin() {
300
305
  "/usr/local/bin/openclaw",
301
306
  path.join(os.homedir(), ".openclaw", "bin", "openclaw"),
302
307
  ];
308
+ // Try npm global bin path
309
+ try {
310
+ const npmPrefix = execSync("npm config get prefix", { encoding: "utf-8", timeout: 5_000 }).trim();
311
+ if (npmPrefix)
312
+ candidates.push(path.join(npmPrefix, "bin", "openclaw"));
313
+ }
314
+ catch { }
303
315
  for (const p of candidates) {
304
316
  if (fs.existsSync(p))
305
317
  return p;
306
318
  }
319
+ // Last resort: try `which openclaw`
320
+ try {
321
+ const w = execSync("which openclaw", { encoding: "utf-8", timeout: 5_000 }).trim();
322
+ if (w)
323
+ return w;
324
+ }
325
+ catch { }
307
326
  return "openclaw";
308
327
  }
309
- function handleInstallOpenclaw(payload) {
328
+ async function handleInstallOpenclaw(payload, progress) {
310
329
  const config = payload.config;
311
330
  if (!config)
312
331
  return { success: false, error: "Missing config in payload. Configure OpenClaw template in Settings first." };
313
- const results = [];
332
+ const sendProgress = async () => {
333
+ if (progress)
334
+ await progress(_cmdOutput.join("\n")).catch(() => { });
335
+ };
314
336
  // Override Guards plugin URLs with the CLI's own connection URL
315
337
  const cliConfig = loadConfig();
316
338
  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
- }
339
+ if (!config.plugins)
340
+ config.plugins = {};
341
+ if (!config.plugins.entries)
342
+ config.plugins.entries = {};
343
+ if (!config.plugins.entries["opentrust-guard"])
344
+ config.plugins.entries["opentrust-guard"] = { enabled: true, config: {} };
345
+ if (!config.plugins.entries["opentrust-guard"].config)
346
+ config.plugins.entries["opentrust-guard"].config = {};
347
+ const gc = config.plugins.entries["opentrust-guard"].config;
348
+ gc.dashboardUrl = cliConfig.dashboardUrl;
349
+ gc.coreUrl = cliConfig.dashboardUrl.replace(/:(\d+)$/, (_, port) => {
350
+ return `:${Number(port) === 53667 ? 53666 : Number(port) - 1}`;
351
+ });
352
+ cmdLog(`Guards URLs → dashboardUrl=${gc.dashboardUrl}, coreUrl=${gc.coreUrl}`);
353
+ }
354
+ // Step 1: Write openclaw.json config FIRST (so install script detects it and skips onboarding)
355
+ cmdLog("[1/3] Writing ~/.openclaw/openclaw.json ...");
356
+ await sendProgress();
357
+ try {
358
+ const clawHome = path.join(os.homedir(), ".openclaw");
359
+ fs.mkdirSync(clawHome, { recursive: true });
360
+ const configFile = path.join(clawHome, "openclaw.json");
361
+ fs.writeFileSync(configFile, JSON.stringify(config, null, 2) + "\n", "utf-8");
362
+ cmdLog(`[1/3] Config written to ${configFile}`);
363
+ }
364
+ catch (err) {
365
+ const msg = `Failed to write config: ${(err.message || String(err)).slice(0, 500)}`;
366
+ cmdLog(`[1/3] ${msg}`);
367
+ await sendProgress();
368
+ return { success: false, output: _cmdOutput.join("\n"), error: msg };
323
369
  }
324
- // Step 1: Install OpenClaw via curl
325
- cmdLog(" [1/3] Installing OpenClaw (curl -fsSL https://openclaw.ai/install.sh | bash)...");
370
+ await sendProgress();
371
+ // Step 2: Install OpenClaw via curl (non-interactive: CI=1, pipe stdin to /dev/null)
372
+ cmdLog("[2/3] Installing OpenClaw (curl -fsSL https://openclaw.ai/install.sh | bash)...");
373
+ await sendProgress();
326
374
  try {
327
375
  execSync("curl -fsSL https://openclaw.ai/install.sh | bash", {
328
376
  encoding: "utf-8",
329
- timeout: 180_000,
330
- stdio: ["pipe", "inherit", "inherit"],
377
+ timeout: 300_000,
378
+ stdio: ["ignore", "inherit", "inherit"],
331
379
  cwd: os.homedir(),
332
- env: { ...process.env, HOME: os.homedir() },
380
+ env: {
381
+ ...process.env,
382
+ HOME: os.homedir(),
383
+ CI: "1",
384
+ NONINTERACTIVE: "1",
385
+ OPENCLAW_ACCEPT_TOS: "1",
386
+ },
333
387
  shell: "/bin/bash",
334
388
  });
335
- results.push("Install script: completed");
336
- cmdLog(" [1/3] OpenClaw install script completed");
389
+ cmdLog("[2/3] OpenClaw install script completed");
337
390
  }
338
391
  catch (err) {
339
392
  const code = err.status;
340
393
  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)");
394
+ cmdLog("[2/3] OpenClaw install script finished (exit code ignored)");
343
395
  }
344
396
  else {
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
397
+ cmdLog(`[2/3] Install script exited with code ${code}`);
349
398
  }
350
399
  }
351
- // Step 2: Write openclaw.json config
352
- cmdLog(" [2/3] Writing ~/.openclaw/openclaw.json ...");
400
+ await sendProgress();
401
+ // Re-write config (install script may have overwritten it during setup)
353
402
  try {
354
- const clawHome = path.join(os.homedir(), ".openclaw");
355
- fs.mkdirSync(clawHome, { recursive: true });
356
- const configFile = path.join(clawHome, "openclaw.json");
403
+ const configFile = path.join(os.homedir(), ".openclaw", "openclaw.json");
357
404
  fs.writeFileSync(configFile, JSON.stringify(config, null, 2) + "\n", "utf-8");
358
- results.push(`Config written to ${configFile}`);
359
- cmdLog(` [2/3] Config written to ${configFile}`);
360
- }
361
- catch (err) {
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 };
405
+ cmdLog("[2/3] Config re-written (ensuring our template is used)");
365
406
  }
366
- // Step 3: Auto-install Guards plugin — expand PATH to find freshly-installed openclaw
407
+ catch { }
408
+ await sendProgress();
409
+ // Step 3: Auto-install Guards plugin — resolve openclaw binary from multiple locations
367
410
  const clawBin = findOpenclawBin();
368
- cmdLog(` [3/3] Installing Guards plugin (${clawBin} plugins install @opentrust/guards)...`);
411
+ cmdLog(`[3/3] Installing Guards plugin (${clawBin} plugins install @opentrust/guards)...`);
412
+ await sendProgress();
369
413
  try {
370
414
  const extraPaths = [
371
415
  path.join(os.homedir(), ".local", "bin"),
372
416
  path.join(os.homedir(), ".openclaw", "bin"),
373
417
  "/usr/local/bin",
374
- ].join(":");
418
+ ];
419
+ // Also discover npm global bin directory
420
+ try {
421
+ const npmBin = execSync("npm config get prefix", { encoding: "utf-8", timeout: 5_000 }).trim();
422
+ if (npmBin)
423
+ extraPaths.push(path.join(npmBin, "bin"));
424
+ }
425
+ catch { }
375
426
  const { OPENCLAW_HOME: _, ...restEnv } = process.env;
376
- const output = execSync(`${clawBin} plugins install @opentrust/guards`, {
427
+ execSync(`${clawBin} plugins install @opentrust/guards`, {
377
428
  encoding: "utf-8",
378
429
  timeout: 180_000,
379
430
  stdio: ["pipe", "pipe", "pipe"],
380
431
  cwd: os.homedir(),
381
- env: { ...restEnv, HOME: os.homedir(), PATH: `${extraPaths}:${process.env.PATH ?? ""}` },
432
+ env: { ...restEnv, HOME: os.homedir(), PATH: `${extraPaths.join(":")}:${process.env.PATH ?? ""}` },
382
433
  });
383
- results.push(`Guards plugin: installed`);
384
- cmdLog(` [3/3] Guards plugin installed successfully`);
434
+ cmdLog("[3/3] Guards plugin installed successfully");
385
435
  }
386
436
  catch (err) {
387
437
  const stderr = err.stderr?.toString() || "";
388
438
  const stdout = err.stdout?.toString() || "";
389
439
  if (isOnlyWarnings(stderr) || isOnlyWarnings(stdout + stderr)) {
390
- results.push("Guards plugin: installed (with warnings)");
391
- cmdLog(" [3/3] Guards plugin installed (with warnings)");
440
+ cmdLog("[3/3] Guards plugin installed (with warnings)");
392
441
  }
393
442
  else {
394
443
  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}`);
444
+ cmdLog(`[3/3] Guards plugin install failed: ${errMsg}`);
397
445
  }
398
446
  }
399
- cmdLog(" install_openclaw complete");
400
- return { success: true, output: results.join("\n") };
447
+ cmdLog("install_openclaw complete");
448
+ return { success: true, output: _cmdOutput.join("\n") };
401
449
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opentrust/cli",
3
- "version": "7.3.34",
3
+ "version": "7.3.36",
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": {