openclaw-utils 0.2.1 → 0.3.0

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/index.js CHANGED
@@ -4,23 +4,22 @@ import {
4
4
  DISPLAY_NAME,
5
5
  DOCTOR_LOG_DIR,
6
6
  PID_FILE,
7
+ RestartThrottle,
7
8
  __require,
8
- addRestartRecord,
9
9
  checkHealth,
10
10
  detectOpenClaw,
11
11
  ensureDoctorHome,
12
- getRestartCommand,
13
- getStartCommand,
14
- getStopCommand,
15
12
  initLogger,
16
13
  loadConfig,
17
14
  log,
15
+ restartGateway,
18
16
  runOpenClawCmd,
19
- startDashboard
20
- } from "./chunk-FUWKRMIF.js";
17
+ startDashboard,
18
+ startGateway,
19
+ stopGateway
20
+ } from "./chunk-BM3MY6H6.js";
21
21
 
22
22
  // src/index.ts
23
- import { createRequire } from "module";
24
23
  import { spawnSync } from "child_process";
25
24
  import { Command } from "commander";
26
25
 
@@ -28,72 +27,6 @@ import { Command } from "commander";
28
27
  import { spawn } from "child_process";
29
28
  import { writeFileSync, readFileSync, existsSync, unlinkSync, openSync } from "fs";
30
29
  import chalk from "chalk";
31
-
32
- // src/core/process-manager.ts
33
- import { exec } from "child_process";
34
- import { promisify } from "util";
35
- var execAsync = promisify(exec);
36
- async function runShell(command) {
37
- try {
38
- const { stdout } = await execAsync(command, { timeout: 12e4 });
39
- return { success: true, output: stdout.trim() };
40
- } catch (err) {
41
- const error = err instanceof Error ? err.message : String(err);
42
- return { success: false, error };
43
- }
44
- }
45
- async function restartGateway(info) {
46
- const cmd = getRestartCommand(info);
47
- log("warn", `Restarting gateway: ${cmd}`);
48
- const result = await runShell(cmd);
49
- if (result.success) {
50
- log("success", "Gateway restarted");
51
- } else {
52
- log("error", `Gateway restart failed: ${result.error}`);
53
- }
54
- addRestartRecord({
55
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
56
- reason: "health check failed",
57
- success: result.success
58
- });
59
- return result;
60
- }
61
- async function startGateway(info) {
62
- const cmd = getStartCommand(info);
63
- log("info", `Starting gateway: ${cmd}`);
64
- const result = await runShell(cmd);
65
- if (result.success) log("success", "Gateway started");
66
- else log("error", `Gateway start failed: ${result.error}`);
67
- return result;
68
- }
69
- async function stopGateway(info) {
70
- const cmd = getStopCommand(info);
71
- log("info", `Stopping gateway: ${cmd}`);
72
- const result = await runShell(cmd);
73
- if (result.success) log("success", "Gateway stopped");
74
- else log("error", `Gateway stop failed: ${result.error}`);
75
- return result;
76
- }
77
- var RestartThrottle = class {
78
- constructor(maxPerHour) {
79
- this.maxPerHour = maxPerHour;
80
- }
81
- timestamps = [];
82
- canRestart() {
83
- const oneHourAgo = Date.now() - 36e5;
84
- this.timestamps = this.timestamps.filter((t) => t > oneHourAgo);
85
- return this.timestamps.length < this.maxPerHour;
86
- }
87
- record() {
88
- this.timestamps.push(Date.now());
89
- }
90
- recentCount() {
91
- const oneHourAgo = Date.now() - 36e5;
92
- return this.timestamps.filter((t) => t > oneHourAgo).length;
93
- }
94
- };
95
-
96
- // src/commands/watch.ts
97
30
  import { join } from "path";
98
31
  async function watchDaemon(options) {
99
32
  if (options.daemon) {
@@ -110,7 +43,7 @@ async function watchDaemon(options) {
110
43
  log("info", `Check interval: ${config.checkInterval}s`);
111
44
  log("info", `PID: ${process.pid}`);
112
45
  if (options.dashboard) {
113
- const { startDashboard: startDashboard2 } = await import("./server-PP5Y3LAF.js");
46
+ const { startDashboard: startDashboard2 } = await import("./server-OTKIWZJK.js");
114
47
  startDashboard2({ config: options.config });
115
48
  }
116
49
  const throttle = new RestartThrottle(config.maxRestartsPerHour);
@@ -395,6 +328,24 @@ async function runDoctor(options) {
395
328
  } else {
396
329
  console.log(chalk3.yellow(" Could not run openclaw doctor"));
397
330
  }
331
+ if (options.fix) {
332
+ console.log(chalk3.gray("\n [5/5] Auto-repair"));
333
+ if (!result.healthy) {
334
+ console.log(chalk3.yellow(" Gateway unhealthy \u2014 running openclaw doctor --repair --non-interactive"));
335
+ const repairOutput = await runOpenClawCmd(info, "doctor --repair --non-interactive");
336
+ if (repairOutput) {
337
+ const lines = repairOutput.split("\n");
338
+ for (const line of lines.slice(0, 30)) {
339
+ if (line.trim()) console.log(` ${line}`);
340
+ }
341
+ console.log(chalk3.green(" Repair completed"));
342
+ } else {
343
+ console.log(chalk3.yellow(" Could not run repair (openclaw CLI unavailable)"));
344
+ }
345
+ } else {
346
+ console.log(chalk3.green(" Gateway healthy \u2014 no repair needed"));
347
+ }
348
+ }
398
349
  console.log();
399
350
  }
400
351
 
@@ -433,7 +384,7 @@ function showLogs(options) {
433
384
  }
434
385
  function showDoctorLogs(maxLines) {
435
386
  const { readdirSync } = __require("fs");
436
- const { join: join2 } = __require("path");
387
+ const { join: join3 } = __require("path");
437
388
  if (!existsSync3(DOCTOR_LOG_DIR)) {
438
389
  console.log(chalk4.yellow("No doctor logs found."));
439
390
  return;
@@ -445,9 +396,9 @@ function showDoctorLogs(maxLines) {
445
396
  }
446
397
  const latest = files[0];
447
398
  console.log(chalk4.blue.bold(`
448
- ${join2(DOCTOR_LOG_DIR, latest)}
399
+ ${join3(DOCTOR_LOG_DIR, latest)}
449
400
  `));
450
- const content = readFileSync3(join2(DOCTOR_LOG_DIR, latest), "utf-8");
401
+ const content = readFileSync3(join3(DOCTOR_LOG_DIR, latest), "utf-8");
451
402
  const lines = content.trim().split("\n");
452
403
  const tail = lines.slice(-maxLines);
453
404
  for (const line of tail) {
@@ -503,9 +454,65 @@ async function gatewayRestart(options) {
503
454
  }
504
455
  }
505
456
 
457
+ // src/commands/memory.ts
458
+ import chalk6 from "chalk";
459
+ import { existsSync as existsSync4, statSync } from "fs";
460
+ import { join as join2 } from "path";
461
+ import { homedir } from "os";
462
+ function expandHome(p) {
463
+ return p.startsWith("~/") ? join2(homedir(), p.slice(2)) : p;
464
+ }
465
+ async function memoryStatus(options) {
466
+ const config = loadConfig(options.config);
467
+ const info = detectOpenClaw(options.profile ?? config.openclawProfile);
468
+ console.log(chalk6.bold("\n Memory Status\n"));
469
+ for (const agent of info.agents) {
470
+ const ws = agent.workspace;
471
+ if (!ws) continue;
472
+ const wsPath = expandHome(ws);
473
+ const memPath = join2(wsPath, "MEMORY.md");
474
+ const exists = existsSync4(memPath);
475
+ const sizeKB = exists ? Math.round(statSync(memPath).size / 1024) : 0;
476
+ const warn = sizeKB > 50;
477
+ const indicator = warn ? chalk6.yellow("\u26A0") : chalk6.green("\u2713");
478
+ const sizeStr = warn ? chalk6.yellow(`${sizeKB}KB`) : chalk6.gray(`${sizeKB}KB`);
479
+ console.log(` ${indicator} ${agent.name.padEnd(16)} MEMORY.md: ${sizeStr}${warn ? chalk6.yellow(" \u2014 exceeds 50KB, may waste tokens") : ""}`);
480
+ }
481
+ console.log();
482
+ }
483
+ async function memorySearch(query, options) {
484
+ const config = loadConfig(options.config);
485
+ const info = detectOpenClaw(options.profile ?? config.openclawProfile);
486
+ console.log(chalk6.bold(`
487
+ Searching memory: "${query}"
488
+ `));
489
+ const output = await runOpenClawCmd(info, `memory search "${query}"`);
490
+ if (output) {
491
+ console.log(output);
492
+ } else {
493
+ console.log(chalk6.yellow(" No results or openclaw memory search unavailable"));
494
+ }
495
+ console.log();
496
+ }
497
+ async function memoryCompact(options) {
498
+ const config = loadConfig(options.config);
499
+ const info = detectOpenClaw(options.profile ?? config.openclawProfile);
500
+ const flag = options.dryRun ? "--dry-run" : "";
501
+ console.log(chalk6.bold(`
502
+ Memory Compact${options.dryRun ? " (dry run)" : ""}
503
+ `));
504
+ const output = await runOpenClawCmd(info, `memory compact ${flag}`);
505
+ if (output) {
506
+ console.log(output);
507
+ } else {
508
+ console.log(chalk6.yellow(" openclaw memory compact not available"));
509
+ }
510
+ console.log();
511
+ }
512
+
506
513
  // src/index.ts
507
- var require2 = createRequire(import.meta.url);
508
- var { version } = require2("../package.json");
514
+ var _PKG_VER = true ? "0.3.0" : "0.2.1";
515
+ var version = _PKG_VER;
509
516
  var program = new Command();
510
517
  program.name(BINARY_NAME).description(`${DISPLAY_NAME} \u2014 health monitor and management for OpenClaw services`).version(version);
511
518
  var addGlobalOpts = (cmd) => cmd.option("-c, --config <path>", "Path to config file").option("--profile <name>", "OpenClaw profile (default, dev, ...)", "default");
@@ -528,6 +535,14 @@ var gw = program.command("gateway").description("Manage the OpenClaw gateway ser
528
535
  addGlobalOpts(gw.command("start").description("Start the gateway")).action(gatewayStart);
529
536
  addGlobalOpts(gw.command("stop").description("Stop the gateway")).action(gatewayStop);
530
537
  addGlobalOpts(gw.command("restart").description("Restart the gateway")).action(gatewayRestart);
538
+ var mem = program.command("memory").description("Memory file health and management");
539
+ addGlobalOpts(mem.command("status").description("Show MEMORY.md size and health per agent")).action(memoryStatus);
540
+ addGlobalOpts(
541
+ mem.command("search").description("Search agent memory files").argument("<query>", "Search query")
542
+ ).action((query, options) => memorySearch(query, options));
543
+ addGlobalOpts(
544
+ mem.command("compact").description("Compact agent memory (proxies to openclaw memory compact)").option("--dry-run", "Preview without applying")
545
+ ).action(memoryCompact);
531
546
  addGlobalOpts(
532
547
  program.command("logs").description("View logs (proxies to openclaw logs; use --doctor for our own logs)").option("-n, --lines <count>", "Number of lines to show", "50").option("--error", "Show gateway error logs").option("--doctor", "Show our own event logs").option("--tail", "Follow logs in real time").allowUnknownOption()
533
548
  ).action((options, cmd) => {
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  startDashboard
4
- } from "./chunk-FUWKRMIF.js";
4
+ } from "./chunk-BM3MY6H6.js";
5
5
  export {
6
6
  startDashboard
7
7
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openclaw-utils",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "description": "Health check and auto-restart daemon for local OpenClaw services",
5
5
  "type": "module",
6
6
  "bin": {