safeclaw 0.1.2 → 0.1.3

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.
Files changed (2) hide show
  1. package/dist/main.js +82 -79
  2. package/package.json +1 -1
package/dist/main.js CHANGED
@@ -8,15 +8,16 @@ var __export = (target, all) => {
8
8
  import { Command } from "commander";
9
9
 
10
10
  // src/lib/version.ts
11
- var VERSION = "0.1.2";
11
+ var VERSION = "0.1.3";
12
12
 
13
13
  // src/server/index.ts
14
14
  import Fastify from "fastify";
15
15
  import fastifyStatic from "@fastify/static";
16
16
  import fastifyCors from "@fastify/cors";
17
- import fs7 from "fs";
17
+ import fs8 from "fs";
18
18
 
19
19
  // src/lib/paths.ts
20
+ import fs from "fs";
20
21
  import path from "path";
21
22
  import os from "os";
22
23
  var HOME = os.homedir();
@@ -33,7 +34,9 @@ var OPENCLAW_DEVICE_AUTH_JSON = path.join(OPENCLAW_IDENTITY_DIR, "device-auth.js
33
34
  var OPENCLAW_EXEC_APPROVALS_PATH = path.join(OPENCLAW_DIR, "exec-approvals.json");
34
35
  function getPublicDir() {
35
36
  const currentDir = path.dirname(new URL(import.meta.url).pathname);
36
- return path.resolve(currentDir, "..", "..", "public");
37
+ const bundledPath = path.resolve(currentDir, "..", "public");
38
+ const devPath = path.resolve(currentDir, "..", "..", "public");
39
+ return fs.existsSync(bundledPath) ? bundledPath : devPath;
37
40
  }
38
41
 
39
42
  // src/server/socket.ts
@@ -44,7 +47,7 @@ import Database from "better-sqlite3";
44
47
  import { drizzle } from "drizzle-orm/better-sqlite3";
45
48
 
46
49
  // src/lib/config.ts
47
- import fs from "fs";
50
+ import fs2 from "fs";
48
51
 
49
52
  // ../../packages/shared/dist/schemas.js
50
53
  import { z } from "zod";
@@ -279,25 +282,25 @@ var DEFAULT_CONFIG = {
279
282
  userId: null
280
283
  };
281
284
  function ensureDataDir() {
282
- if (!fs.existsSync(SAFECLAW_DIR)) {
283
- fs.mkdirSync(SAFECLAW_DIR, { recursive: true });
285
+ if (!fs2.existsSync(SAFECLAW_DIR)) {
286
+ fs2.mkdirSync(SAFECLAW_DIR, { recursive: true });
284
287
  }
285
- if (!fs.existsSync(LOGS_DIR)) {
286
- fs.mkdirSync(LOGS_DIR, { recursive: true });
288
+ if (!fs2.existsSync(LOGS_DIR)) {
289
+ fs2.mkdirSync(LOGS_DIR, { recursive: true });
287
290
  }
288
291
  }
289
292
  function readConfig() {
290
293
  ensureDataDir();
291
- if (!fs.existsSync(CONFIG_PATH)) {
292
- fs.writeFileSync(CONFIG_PATH, JSON.stringify(DEFAULT_CONFIG, null, 2));
294
+ if (!fs2.existsSync(CONFIG_PATH)) {
295
+ fs2.writeFileSync(CONFIG_PATH, JSON.stringify(DEFAULT_CONFIG, null, 2));
293
296
  return DEFAULT_CONFIG;
294
297
  }
295
- const raw = JSON.parse(fs.readFileSync(CONFIG_PATH, "utf-8"));
298
+ const raw = JSON.parse(fs2.readFileSync(CONFIG_PATH, "utf-8"));
296
299
  return safeClawConfigSchema.parse(raw);
297
300
  }
298
301
  function writeConfig(config) {
299
302
  ensureDataDir();
300
- fs.writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2));
303
+ fs2.writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2));
301
304
  }
302
305
  function resetConfig() {
303
306
  writeConfig(DEFAULT_CONFIG);
@@ -423,9 +426,9 @@ import { eq as eq4, desc as desc3 } from "drizzle-orm";
423
426
 
424
427
  // src/lib/logger.ts
425
428
  import pino from "pino";
426
- import fs2 from "fs";
427
- if (!fs2.existsSync(LOGS_DIR)) {
428
- fs2.mkdirSync(LOGS_DIR, { recursive: true });
429
+ import fs3 from "fs";
430
+ if (!fs3.existsSync(LOGS_DIR)) {
431
+ fs3.mkdirSync(LOGS_DIR, { recursive: true });
429
432
  }
430
433
  function createLogger(consoleLevel = "info") {
431
434
  return pino({
@@ -454,19 +457,19 @@ function setVerbose(verbose) {
454
457
  }
455
458
 
456
459
  // src/lib/openclaw-config.ts
457
- import fs3 from "fs";
460
+ import fs4 from "fs";
458
461
  function readOpenClawConfig() {
459
- if (!fs3.existsSync(OPENCLAW_CONFIG_PATH)) {
462
+ if (!fs4.existsSync(OPENCLAW_CONFIG_PATH)) {
460
463
  return null;
461
464
  }
462
- const raw = JSON.parse(fs3.readFileSync(OPENCLAW_CONFIG_PATH, "utf-8"));
465
+ const raw = JSON.parse(fs4.readFileSync(OPENCLAW_CONFIG_PATH, "utf-8"));
463
466
  return openClawConfigSchema.parse(raw);
464
467
  }
465
468
  function writeOpenClawConfig(updates) {
466
469
  const current = readOpenClawConfig();
467
470
  if (!current) return null;
468
471
  const merged = deepMerge(current, updates);
469
- fs3.writeFileSync(OPENCLAW_CONFIG_PATH, JSON.stringify(merged, null, 2));
472
+ fs4.writeFileSync(OPENCLAW_CONFIG_PATH, JSON.stringify(merged, null, 2));
470
473
  return merged;
471
474
  }
472
475
  function deepMerge(target, source) {
@@ -486,11 +489,11 @@ function deepMerge(target, source) {
486
489
  // src/lib/openclaw-client.ts
487
490
  import { EventEmitter } from "events";
488
491
  import crypto from "crypto";
489
- import fs4 from "fs";
492
+ import fs5 from "fs";
490
493
  import { WebSocket } from "ws";
491
494
  function readDeviceIdentity() {
492
495
  try {
493
- const raw = fs4.readFileSync(OPENCLAW_DEVICE_JSON, "utf-8");
496
+ const raw = fs5.readFileSync(OPENCLAW_DEVICE_JSON, "utf-8");
494
497
  const data = JSON.parse(raw);
495
498
  if (!data.deviceId || !data.publicKeyPem || !data.privateKeyPem) return null;
496
499
  return {
@@ -1008,7 +1011,7 @@ var OpenClawClient = class extends EventEmitter {
1008
1011
 
1009
1012
  // src/services/session-watcher.ts
1010
1013
  import { EventEmitter as EventEmitter2 } from "events";
1011
- import fs5 from "fs";
1014
+ import fs6 from "fs";
1012
1015
  import path2 from "path";
1013
1016
  var MAX_CONTENT_PREVIEW = 10 * 1024;
1014
1017
  var SessionWatcher = class extends EventEmitter2 {
@@ -1027,7 +1030,7 @@ var SessionWatcher = class extends EventEmitter2 {
1027
1030
  start() {
1028
1031
  if (this.destroyed) return;
1029
1032
  const agentsDir = path2.join(OPENCLAW_DIR, "agents");
1030
- if (!fs5.existsSync(agentsDir)) {
1033
+ if (!fs6.existsSync(agentsDir)) {
1031
1034
  logger.debug("OpenClaw agents directory not found, will retry");
1032
1035
  }
1033
1036
  this.scanForSessions();
@@ -1035,8 +1038,8 @@ var SessionWatcher = class extends EventEmitter2 {
1035
1038
  if (!this.destroyed) this.scanForSessions();
1036
1039
  }, 1e4);
1037
1040
  try {
1038
- if (fs5.existsSync(agentsDir)) {
1039
- this.agentsDirWatcher = fs5.watch(agentsDir, { recursive: true }, () => {
1041
+ if (fs6.existsSync(agentsDir)) {
1042
+ this.agentsDirWatcher = fs6.watch(agentsDir, { recursive: true }, () => {
1040
1043
  if (!this.destroyed) this.scanForSessions();
1041
1044
  });
1042
1045
  }
@@ -1064,10 +1067,10 @@ var SessionWatcher = class extends EventEmitter2 {
1064
1067
  }
1065
1068
  scanForSessions() {
1066
1069
  const agentsDir = path2.join(OPENCLAW_DIR, "agents");
1067
- if (!fs5.existsSync(agentsDir)) return;
1070
+ if (!fs6.existsSync(agentsDir)) return;
1068
1071
  try {
1069
- const agentNames = fs5.readdirSync(agentsDir).filter((name) => {
1070
- const stat = fs5.statSync(path2.join(agentsDir, name));
1072
+ const agentNames = fs6.readdirSync(agentsDir).filter((name) => {
1073
+ const stat = fs6.statSync(path2.join(agentsDir, name));
1071
1074
  return stat.isDirectory();
1072
1075
  });
1073
1076
  for (const agentName of agentNames) {
@@ -1079,11 +1082,11 @@ var SessionWatcher = class extends EventEmitter2 {
1079
1082
  }
1080
1083
  discoverSessionFiles(agentName) {
1081
1084
  const sessionsDir = path2.join(OPENCLAW_DIR, "agents", agentName, "sessions");
1082
- if (!fs5.existsSync(sessionsDir)) return;
1085
+ if (!fs6.existsSync(sessionsDir)) return;
1083
1086
  const sessionsJsonPath = path2.join(sessionsDir, "sessions.json");
1084
- if (fs5.existsSync(sessionsJsonPath)) {
1087
+ if (fs6.existsSync(sessionsJsonPath)) {
1085
1088
  try {
1086
- const raw = fs5.readFileSync(sessionsJsonPath, "utf-8");
1089
+ const raw = fs6.readFileSync(sessionsJsonPath, "utf-8");
1087
1090
  const sessionsData = JSON.parse(raw);
1088
1091
  const sessions2 = sessionsData.sessions ?? [];
1089
1092
  for (const session of sessions2) {
@@ -1095,7 +1098,7 @@ var SessionWatcher = class extends EventEmitter2 {
1095
1098
  }
1096
1099
  }
1097
1100
  try {
1098
- const files = fs5.readdirSync(sessionsDir).filter((f) => f.endsWith(".jsonl"));
1101
+ const files = fs6.readdirSync(sessionsDir).filter((f) => f.endsWith(".jsonl"));
1099
1102
  for (const file of files) {
1100
1103
  const filePath = path2.join(sessionsDir, file);
1101
1104
  const sessionId = path2.basename(file, ".jsonl");
@@ -1106,8 +1109,8 @@ var SessionWatcher = class extends EventEmitter2 {
1106
1109
  }
1107
1110
  watchSessionFile(filePath, sessionId, agentName) {
1108
1111
  if (this.watchedFiles.has(filePath)) return;
1109
- if (!fs5.existsSync(filePath)) return;
1110
- const stat = fs5.statSync(filePath);
1112
+ if (!fs6.existsSync(filePath)) return;
1113
+ const stat = fs6.statSync(filePath);
1111
1114
  const watched = {
1112
1115
  path: filePath,
1113
1116
  position: stat.size,
@@ -1117,7 +1120,7 @@ var SessionWatcher = class extends EventEmitter2 {
1117
1120
  agentName
1118
1121
  };
1119
1122
  try {
1120
- watched.watcher = fs5.watch(filePath, () => {
1123
+ watched.watcher = fs6.watch(filePath, () => {
1121
1124
  if (!this.destroyed) {
1122
1125
  this.readNewEntries(watched);
1123
1126
  }
@@ -1131,13 +1134,13 @@ var SessionWatcher = class extends EventEmitter2 {
1131
1134
  }
1132
1135
  readNewEntries(watched) {
1133
1136
  try {
1134
- const stat = fs5.statSync(watched.path);
1137
+ const stat = fs6.statSync(watched.path);
1135
1138
  if (stat.size <= watched.position) return;
1136
- const fd = fs5.openSync(watched.path, "r");
1139
+ const fd = fs6.openSync(watched.path, "r");
1137
1140
  const bufferSize = stat.size - watched.position;
1138
1141
  const buffer = Buffer.alloc(bufferSize);
1139
- fs5.readSync(fd, buffer, 0, bufferSize, watched.position);
1140
- fs5.closeSync(fd);
1142
+ fs6.readSync(fd, buffer, 0, bufferSize, watched.position);
1143
+ fs6.closeSync(fd);
1141
1144
  watched.position = stat.size;
1142
1145
  const text2 = buffer.toString("utf-8");
1143
1146
  const lines = text2.split("\n").filter((l) => l.trim());
@@ -1691,11 +1694,11 @@ function createExecApprovalService(client, io2, timeoutMs) {
1691
1694
  }
1692
1695
 
1693
1696
  // src/lib/exec-approvals-config.ts
1694
- import fs6 from "fs";
1697
+ import fs7 from "fs";
1695
1698
  function readExecApprovalsConfig() {
1696
1699
  try {
1697
- if (!fs6.existsSync(OPENCLAW_EXEC_APPROVALS_PATH)) return null;
1698
- const raw = fs6.readFileSync(OPENCLAW_EXEC_APPROVALS_PATH, "utf-8");
1700
+ if (!fs7.existsSync(OPENCLAW_EXEC_APPROVALS_PATH)) return null;
1701
+ const raw = fs7.readFileSync(OPENCLAW_EXEC_APPROVALS_PATH, "utf-8");
1699
1702
  return JSON.parse(raw);
1700
1703
  } catch (err) {
1701
1704
  logger.warn({ err }, "Failed to read exec-approvals.json");
@@ -1703,7 +1706,7 @@ function readExecApprovalsConfig() {
1703
1706
  }
1704
1707
  }
1705
1708
  function writeExecApprovalsConfig(config) {
1706
- fs6.writeFileSync(
1709
+ fs7.writeFileSync(
1707
1710
  OPENCLAW_EXEC_APPROVALS_PATH,
1708
1711
  JSON.stringify(config, null, 2)
1709
1712
  );
@@ -3423,7 +3426,7 @@ async function createAppServer(port) {
3423
3426
  await app.register(fastifyCors, { origin: "*" });
3424
3427
  await registerRoutes(app);
3425
3428
  const publicDir = getPublicDir();
3426
- if (fs7.existsSync(publicDir) && fs7.readdirSync(publicDir).filter((f) => f !== ".gitkeep").length > 0) {
3429
+ if (fs8.existsSync(publicDir) && fs8.readdirSync(publicDir).filter((f) => f !== ".gitkeep").length > 0) {
3427
3430
  await app.register(fastifyStatic, {
3428
3431
  root: publicDir,
3429
3432
  prefix: "/",
@@ -3685,7 +3688,7 @@ Permission denied for port ${port}.
3685
3688
  }
3686
3689
 
3687
3690
  // src/commands/reset.ts
3688
- import fs8 from "fs";
3691
+ import fs9 from "fs";
3689
3692
  import readline from "readline/promises";
3690
3693
  import pc3 from "picocolors";
3691
3694
  async function resetCommand(options) {
@@ -3704,12 +3707,12 @@ async function resetCommand(options) {
3704
3707
  }
3705
3708
  }
3706
3709
  console.log(pc3.bold("Resetting SafeClaw..."));
3707
- if (fs8.existsSync(DB_PATH)) {
3708
- fs8.unlinkSync(DB_PATH);
3710
+ if (fs9.existsSync(DB_PATH)) {
3711
+ fs9.unlinkSync(DB_PATH);
3709
3712
  const walPath = DB_PATH + "-wal";
3710
3713
  const shmPath = DB_PATH + "-shm";
3711
- if (fs8.existsSync(walPath)) fs8.unlinkSync(walPath);
3712
- if (fs8.existsSync(shmPath)) fs8.unlinkSync(shmPath);
3714
+ if (fs9.existsSync(walPath)) fs9.unlinkSync(walPath);
3715
+ if (fs9.existsSync(shmPath)) fs9.unlinkSync(shmPath);
3713
3716
  console.log(pc3.green(" Database deleted."));
3714
3717
  } else {
3715
3718
  console.log(pc3.dim(" No database found, skipping."));
@@ -3722,11 +3725,11 @@ async function resetCommand(options) {
3722
3725
  }
3723
3726
 
3724
3727
  // src/commands/status.ts
3725
- import fs9 from "fs";
3728
+ import fs10 from "fs";
3726
3729
  import Database3 from "better-sqlite3";
3727
3730
  import pc4 from "picocolors";
3728
3731
  async function statusCommand(options) {
3729
- const exists = fs9.existsSync(SAFECLAW_DIR);
3732
+ const exists = fs10.existsSync(SAFECLAW_DIR);
3730
3733
  if (!exists) {
3731
3734
  if (options.json) {
3732
3735
  console.log(JSON.stringify({ initialized: false }, null, 2));
@@ -3740,7 +3743,7 @@ async function statusCommand(options) {
3740
3743
  const config = readConfig();
3741
3744
  let logCount = 0;
3742
3745
  let activityCount = 0;
3743
- const dbExists = fs9.existsSync(DB_PATH);
3746
+ const dbExists = fs10.existsSync(DB_PATH);
3744
3747
  if (dbExists) {
3745
3748
  try {
3746
3749
  const sqlite = new Database3(DB_PATH, { readonly: true });
@@ -3754,14 +3757,14 @@ async function statusCommand(options) {
3754
3757
  activityCount = -1;
3755
3758
  }
3756
3759
  }
3757
- const openclawConfigExists = fs9.existsSync(OPENCLAW_CONFIG_PATH);
3760
+ const openclawConfigExists = fs10.existsSync(OPENCLAW_CONFIG_PATH);
3758
3761
  if (options.json) {
3759
3762
  const data = {
3760
3763
  version: VERSION,
3761
3764
  initialized: true,
3762
3765
  dataDir: SAFECLAW_DIR,
3763
3766
  database: dbExists ? "exists" : "not_found",
3764
- config: fs9.existsSync(CONFIG_PATH) ? "exists" : "not_found",
3767
+ config: fs10.existsSync(CONFIG_PATH) ? "exists" : "not_found",
3765
3768
  port: config.port,
3766
3769
  autoOpenBrowser: config.autoOpenBrowser,
3767
3770
  premium: config.premium,
@@ -3779,7 +3782,7 @@ async function statusCommand(options) {
3779
3782
  ` ${pc4.dim("Database:")} ${dbExists ? pc4.green("exists") : pc4.red("not found")}`
3780
3783
  );
3781
3784
  console.log(
3782
- ` ${pc4.dim("Config:")} ${fs9.existsSync(CONFIG_PATH) ? pc4.green("exists") : pc4.red("not found")}`
3785
+ ` ${pc4.dim("Config:")} ${fs10.existsSync(CONFIG_PATH) ? pc4.green("exists") : pc4.red("not found")}`
3783
3786
  );
3784
3787
  console.log(` ${pc4.dim("Port:")} ${config.port}`);
3785
3788
  console.log(` ${pc4.dim("Auto-open:")} ${config.autoOpenBrowser ? "Yes" : "No"}`);
@@ -3797,7 +3800,7 @@ async function statusCommand(options) {
3797
3800
  }
3798
3801
 
3799
3802
  // src/commands/doctor.ts
3800
- import fs10 from "fs";
3803
+ import fs11 from "fs";
3801
3804
  import net from "net";
3802
3805
  import Database4 from "better-sqlite3";
3803
3806
  import pc5 from "picocolors";
@@ -3819,7 +3822,7 @@ function checkNodeVersion() {
3819
3822
  function checkDataDir() {
3820
3823
  try {
3821
3824
  ensureDataDir();
3822
- fs10.accessSync(SAFECLAW_DIR, fs10.constants.W_OK);
3825
+ fs11.accessSync(SAFECLAW_DIR, fs11.constants.W_OK);
3823
3826
  return {
3824
3827
  name: "Data directory writable",
3825
3828
  status: "pass",
@@ -3834,7 +3837,7 @@ function checkDataDir() {
3834
3837
  }
3835
3838
  }
3836
3839
  function checkDatabase() {
3837
- if (!fs10.existsSync(DB_PATH)) {
3840
+ if (!fs11.existsSync(DB_PATH)) {
3838
3841
  return {
3839
3842
  name: "Database",
3840
3843
  status: "warn",
@@ -3877,7 +3880,7 @@ function checkDatabase() {
3877
3880
  }
3878
3881
  }
3879
3882
  function checkConfig() {
3880
- if (!fs10.existsSync(CONFIG_PATH)) {
3883
+ if (!fs11.existsSync(CONFIG_PATH)) {
3881
3884
  return {
3882
3885
  name: "Config file",
3883
3886
  status: "warn",
@@ -3919,14 +3922,14 @@ async function checkPort() {
3919
3922
  };
3920
3923
  }
3921
3924
  function checkOpenClawConfig() {
3922
- if (!fs10.existsSync(OPENCLAW_DIR)) {
3925
+ if (!fs11.existsSync(OPENCLAW_DIR)) {
3923
3926
  return {
3924
3927
  name: "OpenClaw directory",
3925
3928
  status: "warn",
3926
3929
  message: `${OPENCLAW_DIR} not found`
3927
3930
  };
3928
3931
  }
3929
- if (!fs10.existsSync(OPENCLAW_CONFIG_PATH)) {
3932
+ if (!fs11.existsSync(OPENCLAW_CONFIG_PATH)) {
3930
3933
  return {
3931
3934
  name: "OpenClaw config",
3932
3935
  status: "warn",
@@ -3958,7 +3961,7 @@ function isPortInUse(port) {
3958
3961
  });
3959
3962
  }
3960
3963
  async function checkOpenClawGateway() {
3961
- if (!fs10.existsSync(OPENCLAW_CONFIG_PATH)) {
3964
+ if (!fs11.existsSync(OPENCLAW_CONFIG_PATH)) {
3962
3965
  return {
3963
3966
  name: "OpenClaw gateway",
3964
3967
  status: "warn",
@@ -3966,7 +3969,7 @@ async function checkOpenClawGateway() {
3966
3969
  };
3967
3970
  }
3968
3971
  try {
3969
- const raw = JSON.parse(fs10.readFileSync(OPENCLAW_CONFIG_PATH, "utf-8"));
3972
+ const raw = JSON.parse(fs11.readFileSync(OPENCLAW_CONFIG_PATH, "utf-8"));
3970
3973
  const port = raw?.gateway?.port ?? 18789;
3971
3974
  const reachable = await isPortInUse(port);
3972
3975
  if (reachable) {
@@ -3991,10 +3994,10 @@ async function checkOpenClawGateway() {
3991
3994
  }
3992
3995
  function checkLogDir() {
3993
3996
  try {
3994
- if (!fs10.existsSync(LOGS_DIR)) {
3995
- fs10.mkdirSync(LOGS_DIR, { recursive: true });
3997
+ if (!fs11.existsSync(LOGS_DIR)) {
3998
+ fs11.mkdirSync(LOGS_DIR, { recursive: true });
3996
3999
  }
3997
- fs10.accessSync(LOGS_DIR, fs10.constants.W_OK);
4000
+ fs11.accessSync(LOGS_DIR, fs11.constants.W_OK);
3998
4001
  return {
3999
4002
  name: "Log directory writable",
4000
4003
  status: "pass",
@@ -4136,14 +4139,14 @@ async function configSetCommand(key, value) {
4136
4139
  }
4137
4140
 
4138
4141
  // src/commands/logs.ts
4139
- import fs11 from "fs";
4142
+ import fs12 from "fs";
4140
4143
  import pc7 from "picocolors";
4141
4144
  async function logsCommand(options) {
4142
4145
  if (options.clear) {
4143
4146
  await clearLogs();
4144
4147
  return;
4145
4148
  }
4146
- if (!fs11.existsSync(DEBUG_LOG_PATH)) {
4149
+ if (!fs12.existsSync(DEBUG_LOG_PATH)) {
4147
4150
  console.log(
4148
4151
  pc7.yellow("No log file found.") + " Run " + pc7.cyan("safeclaw start") + " to generate logs."
4149
4152
  );
@@ -4156,7 +4159,7 @@ async function logsCommand(options) {
4156
4159
  }
4157
4160
  }
4158
4161
  async function tailLogs(lineCount) {
4159
- const content = fs11.readFileSync(DEBUG_LOG_PATH, "utf-8");
4162
+ const content = fs12.readFileSync(DEBUG_LOG_PATH, "utf-8");
4160
4163
  const lines = content.split("\n").filter(Boolean);
4161
4164
  const tail = lines.slice(-lineCount);
4162
4165
  if (tail.length === 0) {
@@ -4174,23 +4177,23 @@ async function tailLogs(lineCount) {
4174
4177
  async function followLogs() {
4175
4178
  console.log(pc7.dim(`Following ${DEBUG_LOG_PATH} (Ctrl+C to stop)
4176
4179
  `));
4177
- if (fs11.existsSync(DEBUG_LOG_PATH)) {
4178
- const content = fs11.readFileSync(DEBUG_LOG_PATH, "utf-8");
4180
+ if (fs12.existsSync(DEBUG_LOG_PATH)) {
4181
+ const content = fs12.readFileSync(DEBUG_LOG_PATH, "utf-8");
4179
4182
  const lines = content.split("\n").filter(Boolean);
4180
4183
  const tail = lines.slice(-20);
4181
4184
  for (const line of tail) {
4182
4185
  process.stdout.write(line + "\n");
4183
4186
  }
4184
4187
  }
4185
- let position = fs11.existsSync(DEBUG_LOG_PATH) ? fs11.statSync(DEBUG_LOG_PATH).size : 0;
4186
- const watcher = fs11.watch(DEBUG_LOG_PATH, () => {
4188
+ let position = fs12.existsSync(DEBUG_LOG_PATH) ? fs12.statSync(DEBUG_LOG_PATH).size : 0;
4189
+ const watcher = fs12.watch(DEBUG_LOG_PATH, () => {
4187
4190
  try {
4188
- const stat = fs11.statSync(DEBUG_LOG_PATH);
4191
+ const stat = fs12.statSync(DEBUG_LOG_PATH);
4189
4192
  if (stat.size > position) {
4190
- const fd = fs11.openSync(DEBUG_LOG_PATH, "r");
4193
+ const fd = fs12.openSync(DEBUG_LOG_PATH, "r");
4191
4194
  const buffer = Buffer.alloc(stat.size - position);
4192
- fs11.readSync(fd, buffer, 0, buffer.length, position);
4193
- fs11.closeSync(fd);
4195
+ fs12.readSync(fd, buffer, 0, buffer.length, position);
4196
+ fs12.closeSync(fd);
4194
4197
  process.stdout.write(buffer.toString("utf-8"));
4195
4198
  position = stat.size;
4196
4199
  } else if (stat.size < position) {
@@ -4208,11 +4211,11 @@ async function followLogs() {
4208
4211
  });
4209
4212
  }
4210
4213
  async function clearLogs() {
4211
- if (!fs11.existsSync(DEBUG_LOG_PATH)) {
4214
+ if (!fs12.existsSync(DEBUG_LOG_PATH)) {
4212
4215
  console.log(pc7.dim("No log file to clear."));
4213
4216
  return;
4214
4217
  }
4215
- fs11.writeFileSync(DEBUG_LOG_PATH, "");
4218
+ fs12.writeFileSync(DEBUG_LOG_PATH, "");
4216
4219
  console.log(pc7.green("Log file cleared."));
4217
4220
  }
4218
4221
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "safeclaw",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Security management dashboard for AI agents – intercept, monitor, and control what AI agents can do on your system",
5
5
  "type": "module",
6
6
  "license": "AGPL-3.0-only",