itwillsync 1.6.1 → 1.7.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.
@@ -3649,11 +3649,11 @@ var require_websocket_server = __commonJS({
3649
3649
  });
3650
3650
 
3651
3651
  // src/daemon.ts
3652
- import { writeFileSync as writeFileSync3, mkdirSync as mkdirSync3, unlinkSync, existsSync as existsSync3, readdirSync, statSync } from "fs";
3653
- import { homedir as homedir4 } from "os";
3654
- import { join as join4, dirname as dirname3 } from "path";
3652
+ import { writeFileSync as writeFileSync4, mkdirSync as mkdirSync3, unlinkSync as unlinkSync2, existsSync as existsSync4, readdirSync, statSync } from "fs";
3653
+ import { homedir as homedir5 } from "os";
3654
+ import { join as join5, dirname as dirname3 } from "path";
3655
3655
  import { fileURLToPath } from "url";
3656
- import { spawn } from "child_process";
3656
+ import { spawn as spawn2 } from "child_process";
3657
3657
 
3658
3658
  // src/auth.ts
3659
3659
  import { randomBytes, timingSafeEqual } from "crypto";
@@ -4127,8 +4127,8 @@ function createInternalApi(options) {
4127
4127
  }
4128
4128
  let memoryKB = 0;
4129
4129
  try {
4130
- const { execFileSync } = await import("child_process");
4131
- const output = execFileSync("ps", ["-o", "rss=", "-p", String(session.pid)], {
4130
+ const { execFileSync: execFileSync2 } = await import("child_process");
4131
+ const output = execFileSync2("ps", ["-o", "rss=", "-p", String(session.pid)], {
4132
4132
  encoding: "utf-8",
4133
4133
  timeout: 2e3
4134
4134
  });
@@ -4201,7 +4201,7 @@ var MIME_TYPES = {
4201
4201
  var COMPRESSIBLE = /* @__PURE__ */ new Set([".html", ".js", ".css", ".json", ".svg"]);
4202
4202
  var PING_INTERVAL_MS = 3e4;
4203
4203
  function createDashboardServer(options) {
4204
- const { registry, masterToken, dashboardPath, host, port, previewCollector, toolHistory, onCreateSession } = options;
4204
+ const { registry, masterToken, dashboardPath, host, port, previewCollector, toolHistory, sleepPrevention, onCreateSession } = options;
4205
4205
  const homeDir = homedir3();
4206
4206
  const clients = /* @__PURE__ */ new Set();
4207
4207
  const aliveMap = /* @__PURE__ */ new WeakMap();
@@ -4358,6 +4358,9 @@ function createDashboardServer(options) {
4358
4358
  aliveMap.set(ws, true);
4359
4359
  const sessions = registry.getAll();
4360
4360
  ws.send(JSON.stringify({ type: "sessions", sessions }));
4361
+ if (sleepPrevention) {
4362
+ ws.send(JSON.stringify({ type: "sleep-state", state: sleepPrevention.getState() }));
4363
+ }
4361
4364
  if (previewCollector) {
4362
4365
  const previews = previewCollector.getAllPreviews();
4363
4366
  for (const [sessionId, lines] of previews) {
@@ -4423,6 +4426,30 @@ function createDashboardServer(options) {
4423
4426
  }
4424
4427
  break;
4425
4428
  }
4429
+ case "enable-sleep-prevention": {
4430
+ if (!sleepPrevention) {
4431
+ ws.send(JSON.stringify({ type: "sleep-error", error: "Sleep prevention not available" }));
4432
+ break;
4433
+ }
4434
+ const password = typeof msg.password === "string" ? msg.password : "";
4435
+ if (!password) {
4436
+ ws.send(JSON.stringify({ type: "sleep-error", error: "Password is required" }));
4437
+ break;
4438
+ }
4439
+ const enableResult = await sleepPrevention.enable(password);
4440
+ if (enableResult.success) {
4441
+ broadcast({ type: "sleep-state", state: sleepPrevention.getState() });
4442
+ } else {
4443
+ ws.send(JSON.stringify({ type: "sleep-error", error: enableResult.error }));
4444
+ }
4445
+ break;
4446
+ }
4447
+ case "disable-sleep-prevention": {
4448
+ if (!sleepPrevention) break;
4449
+ await sleepPrevention.disable(true);
4450
+ broadcast({ type: "sleep-state", state: sleepPrevention.getState() });
4451
+ break;
4452
+ }
4426
4453
  case "get-metadata": {
4427
4454
  const session = registry.getById(msg.sessionId);
4428
4455
  if (!session) {
@@ -4431,8 +4458,8 @@ function createDashboardServer(options) {
4431
4458
  }
4432
4459
  let memoryKB = 0;
4433
4460
  try {
4434
- const { execFileSync } = await import("child_process");
4435
- const output = execFileSync("ps", ["-o", "rss=", "-p", String(session.pid)], {
4461
+ const { execFileSync: execFileSync2 } = await import("child_process");
4462
+ const output = execFileSync2("ps", ["-o", "rss=", "-p", String(session.pid)], {
4436
4463
  encoding: "utf-8",
4437
4464
  timeout: 2e3
4438
4465
  });
@@ -4687,24 +4714,360 @@ var PreviewCollector = class extends EventEmitter2 {
4687
4714
  }
4688
4715
  };
4689
4716
 
4717
+ // src/sleep-prevention.ts
4718
+ import { spawn, execFileSync } from "child_process";
4719
+ import { writeFileSync as writeFileSync3, readFileSync as readFileSync3, unlinkSync, existsSync as existsSync3 } from "fs";
4720
+ import { join as join4 } from "path";
4721
+ import { homedir as homedir4 } from "os";
4722
+ var SUPPORTED_PLATFORMS = /* @__PURE__ */ new Set(["darwin", "win32", "linux"]);
4723
+ var COMMAND_TIMEOUT_MS = 1e4;
4724
+ var SYNC_TIMEOUT_MS = 5e3;
4725
+ function getHubDir() {
4726
+ return process.env.ITWILLSYNC_CONFIG_DIR || join4(homedir4(), ".itwillsync");
4727
+ }
4728
+ var SleepPrevention = class {
4729
+ enabled = false;
4730
+ enabledAt = null;
4731
+ error = null;
4732
+ busy = false;
4733
+ flagFilePath;
4734
+ platform;
4735
+ constructor() {
4736
+ this.platform = process.platform;
4737
+ this.flagFilePath = join4(getHubDir(), "sleep-prevention.json");
4738
+ this.checkOrphanedFlag();
4739
+ }
4740
+ getState() {
4741
+ return {
4742
+ enabled: this.enabled,
4743
+ platform: this.platform,
4744
+ enabledAt: this.enabledAt,
4745
+ error: this.error,
4746
+ supported: SUPPORTED_PLATFORMS.has(this.platform)
4747
+ };
4748
+ }
4749
+ async enable(password) {
4750
+ if (this.busy) {
4751
+ return { success: false, error: "Operation in progress" };
4752
+ }
4753
+ if (!SUPPORTED_PLATFORMS.has(this.platform)) {
4754
+ return { success: false, error: `Sleep prevention is not supported on ${this.platform}` };
4755
+ }
4756
+ if (this.enabled) {
4757
+ return { success: true };
4758
+ }
4759
+ this.busy = true;
4760
+ try {
4761
+ let result;
4762
+ switch (this.platform) {
4763
+ case "darwin":
4764
+ result = await this.runSudo(["pmset", "-a", "disablesleep", "1"], password);
4765
+ break;
4766
+ case "win32":
4767
+ result = await this.enableWindows();
4768
+ break;
4769
+ case "linux":
4770
+ result = await this.enableLinux(password);
4771
+ break;
4772
+ default:
4773
+ result = { success: false, error: "Unsupported platform" };
4774
+ }
4775
+ if (result.success) {
4776
+ this.enabled = true;
4777
+ this.enabledAt = Date.now();
4778
+ this.error = null;
4779
+ this.writeFlagFile();
4780
+ } else {
4781
+ this.error = result.error || "Unknown error";
4782
+ }
4783
+ return result;
4784
+ } finally {
4785
+ this.busy = false;
4786
+ }
4787
+ }
4788
+ /**
4789
+ * Disable sleep prevention. When `force` is true (user-initiated), the flag
4790
+ * file is always deleted. When false (orphan revert), the flag file persists
4791
+ * if the system command fails so the next restart can retry.
4792
+ */
4793
+ async disable(force = false) {
4794
+ if (this.busy) {
4795
+ return { success: false, error: "Operation in progress" };
4796
+ }
4797
+ if (!this.enabled) {
4798
+ return { success: true };
4799
+ }
4800
+ this.busy = true;
4801
+ try {
4802
+ let reverted = false;
4803
+ switch (this.platform) {
4804
+ case "darwin":
4805
+ reverted = (await this.runCommand("sudo", ["-n", "pmset", "-a", "disablesleep", "0"])).exitCode === 0;
4806
+ break;
4807
+ case "win32":
4808
+ await this.disableWindows();
4809
+ reverted = true;
4810
+ break;
4811
+ case "linux":
4812
+ reverted = await this.disableLinux();
4813
+ break;
4814
+ }
4815
+ this.enabled = false;
4816
+ this.enabledAt = null;
4817
+ this.error = null;
4818
+ if (reverted || force) {
4819
+ this.deleteFlagFile();
4820
+ }
4821
+ return { success: true };
4822
+ } finally {
4823
+ this.busy = false;
4824
+ }
4825
+ }
4826
+ /** Synchronous cleanup for SIGTERM/SIGINT handlers. Best-effort. */
4827
+ cleanupSync() {
4828
+ if (!this.enabled) return;
4829
+ try {
4830
+ switch (this.platform) {
4831
+ case "darwin":
4832
+ execFileSync("sudo", ["-n", "pmset", "-a", "disablesleep", "0"], {
4833
+ timeout: SYNC_TIMEOUT_MS,
4834
+ stdio: "ignore"
4835
+ });
4836
+ break;
4837
+ case "win32":
4838
+ execFileSync("powercfg", ["/setacvalueindex", "SCHEME_CURRENT", "SUB_BUTTONS", "LIDACTION", "1"], { timeout: SYNC_TIMEOUT_MS, stdio: "ignore" });
4839
+ execFileSync("powercfg", ["/setdcvalueindex", "SCHEME_CURRENT", "SUB_BUTTONS", "LIDACTION", "1"], { timeout: SYNC_TIMEOUT_MS, stdio: "ignore" });
4840
+ execFileSync("powercfg", ["/s", "SCHEME_CURRENT"], { timeout: SYNC_TIMEOUT_MS, stdio: "ignore" });
4841
+ break;
4842
+ case "linux":
4843
+ this.revertLogindConfSync();
4844
+ execFileSync("sudo", ["-n", "systemctl", "restart", "systemd-logind"], {
4845
+ timeout: SYNC_TIMEOUT_MS,
4846
+ stdio: "ignore"
4847
+ });
4848
+ break;
4849
+ }
4850
+ } catch {
4851
+ }
4852
+ this.enabled = false;
4853
+ this.enabledAt = null;
4854
+ this.deleteFlagFile();
4855
+ }
4856
+ // --- Windows ---
4857
+ async enableWindows() {
4858
+ const commands = [
4859
+ ["powercfg", ["/setacvalueindex", "SCHEME_CURRENT", "SUB_BUTTONS", "LIDACTION", "0"]],
4860
+ ["powercfg", ["/setdcvalueindex", "SCHEME_CURRENT", "SUB_BUTTONS", "LIDACTION", "0"]],
4861
+ ["powercfg", ["/s", "SCHEME_CURRENT"]]
4862
+ ];
4863
+ for (const [cmd, args] of commands) {
4864
+ const result = await this.runCommand(cmd, args);
4865
+ if (result.exitCode !== 0) {
4866
+ return { success: false, error: `powercfg failed: ${result.stderr || "requires admin privileges"}` };
4867
+ }
4868
+ }
4869
+ return { success: true };
4870
+ }
4871
+ async disableWindows() {
4872
+ await this.runCommand("powercfg", ["/setacvalueindex", "SCHEME_CURRENT", "SUB_BUTTONS", "LIDACTION", "1"]);
4873
+ await this.runCommand("powercfg", ["/setdcvalueindex", "SCHEME_CURRENT", "SUB_BUTTONS", "LIDACTION", "1"]);
4874
+ await this.runCommand("powercfg", ["/s", "SCHEME_CURRENT"]);
4875
+ }
4876
+ // --- Linux ---
4877
+ async enableLinux(password) {
4878
+ const confPath = "/etc/systemd/logind.conf";
4879
+ const backupPath = join4(getHubDir(), "logind.conf.backup");
4880
+ try {
4881
+ const readResult = await this.runSudo(["cat", confPath], password, { captureStdout: true });
4882
+ if (!readResult.success) {
4883
+ return { success: false, error: readResult.error || "Failed to read logind.conf" };
4884
+ }
4885
+ const original = readResult.stdout;
4886
+ writeFileSync3(backupPath, original, "utf-8");
4887
+ let modified = original;
4888
+ const settings = {
4889
+ HandleLidSwitch: "ignore",
4890
+ HandleLidSwitchExternalPower: "ignore",
4891
+ HandleLidSwitchDocked: "ignore"
4892
+ };
4893
+ for (const [key, value] of Object.entries(settings)) {
4894
+ const regex = new RegExp(`^#?\\s*${key}\\s*=.*$`, "m");
4895
+ if (regex.test(modified)) {
4896
+ modified = modified.replace(regex, `${key}=${value}`);
4897
+ } else {
4898
+ modified = modified.replace(/^\[Login\]/m, `[Login]
4899
+ ${key}=${value}`);
4900
+ }
4901
+ }
4902
+ const writeResult = await this.runSudo(["tee", confPath], password, { stdin: modified });
4903
+ if (!writeResult.success) {
4904
+ return { success: false, error: "Failed to write logind.conf" };
4905
+ }
4906
+ const restartResult = await this.runSudo(["systemctl", "restart", "systemd-logind"], password);
4907
+ if (!restartResult.success) {
4908
+ try {
4909
+ const backup = readFileSync3(backupPath, "utf-8");
4910
+ await this.runSudo(["tee", confPath], password, { stdin: backup });
4911
+ await this.runSudo(["systemctl", "restart", "systemd-logind"], password);
4912
+ } catch {
4913
+ }
4914
+ return { success: false, error: "Failed to restart systemd-logind" };
4915
+ }
4916
+ return { success: true };
4917
+ } catch (err) {
4918
+ return { success: false, error: err.message };
4919
+ }
4920
+ }
4921
+ async disableLinux() {
4922
+ const backupPath = join4(getHubDir(), "logind.conf.backup");
4923
+ if (!existsSync3(backupPath)) return true;
4924
+ try {
4925
+ const backup = readFileSync3(backupPath, "utf-8");
4926
+ const teeResult = await this.runCommand("sudo", ["-n", "tee", "/etc/systemd/logind.conf"], { stdin: backup });
4927
+ const restartResult = await this.runCommand("sudo", ["-n", "systemctl", "restart", "systemd-logind"]);
4928
+ const ok = teeResult.exitCode === 0 && restartResult.exitCode === 0;
4929
+ if (ok) unlinkSync(backupPath);
4930
+ return ok;
4931
+ } catch {
4932
+ return false;
4933
+ }
4934
+ }
4935
+ revertLogindConfSync() {
4936
+ const backupPath = join4(getHubDir(), "logind.conf.backup");
4937
+ if (!existsSync3(backupPath)) return;
4938
+ try {
4939
+ const backup = readFileSync3(backupPath, "utf-8");
4940
+ execFileSync("sudo", ["-n", "tee", "/etc/systemd/logind.conf"], {
4941
+ input: backup,
4942
+ timeout: SYNC_TIMEOUT_MS,
4943
+ stdio: ["pipe", "ignore", "ignore"]
4944
+ });
4945
+ unlinkSync(backupPath);
4946
+ } catch {
4947
+ }
4948
+ }
4949
+ // --- Helpers ---
4950
+ /** Run a command via sudo -S (password on stdin). Optionally pipe extra stdin or capture stdout. */
4951
+ runSudo(args, password, opts) {
4952
+ return new Promise((resolve) => {
4953
+ const capture = opts?.captureStdout ?? false;
4954
+ const proc = spawn("sudo", ["-S", ...args], {
4955
+ stdio: ["pipe", capture ? "pipe" : "ignore", "pipe"]
4956
+ });
4957
+ let stdout = "";
4958
+ let stderr = "";
4959
+ if (capture) proc.stdout.on("data", (d) => {
4960
+ stdout += d.toString();
4961
+ });
4962
+ proc.stderr.on("data", (d) => {
4963
+ stderr += d.toString();
4964
+ });
4965
+ const timer = setTimeout(() => {
4966
+ proc.kill("SIGKILL");
4967
+ resolve({ success: false, error: "Command timed out" });
4968
+ }, COMMAND_TIMEOUT_MS);
4969
+ proc.on("close", (code) => {
4970
+ clearTimeout(timer);
4971
+ if (code === 0) {
4972
+ resolve({ success: true, ...capture && { stdout } });
4973
+ } else {
4974
+ const msg = stderr.toLowerCase().includes("incorrect password") ? "Incorrect password" : stderr.trim() || `Command failed with exit code ${code}`;
4975
+ resolve({ success: false, error: msg });
4976
+ }
4977
+ });
4978
+ proc.on("error", (err) => {
4979
+ clearTimeout(timer);
4980
+ resolve({ success: false, error: err.message });
4981
+ });
4982
+ proc.stdin.write(password + "\n");
4983
+ if (opts?.stdin) proc.stdin.write(opts.stdin);
4984
+ proc.stdin.end();
4985
+ });
4986
+ }
4987
+ /** Run a command without sudo password. Optionally pipe stdin. */
4988
+ runCommand(cmd, args, opts) {
4989
+ return new Promise((resolve) => {
4990
+ const hasStdin = opts?.stdin != null;
4991
+ const proc = spawn(cmd, args, {
4992
+ stdio: [hasStdin ? "pipe" : "ignore", "ignore", "pipe"]
4993
+ });
4994
+ let stderr = "";
4995
+ proc.stderr.on("data", (d) => {
4996
+ stderr += d.toString();
4997
+ });
4998
+ const timer = setTimeout(() => {
4999
+ proc.kill("SIGKILL");
5000
+ resolve({ exitCode: 1, stderr: "Command timed out" });
5001
+ }, COMMAND_TIMEOUT_MS);
5002
+ proc.on("close", (code) => {
5003
+ clearTimeout(timer);
5004
+ resolve({ exitCode: code ?? 1, stderr });
5005
+ });
5006
+ proc.on("error", (err) => {
5007
+ clearTimeout(timer);
5008
+ resolve({ exitCode: 1, stderr: err.message });
5009
+ });
5010
+ if (hasStdin) {
5011
+ proc.stdin.write(opts.stdin);
5012
+ proc.stdin.end();
5013
+ }
5014
+ });
5015
+ }
5016
+ writeFlagFile() {
5017
+ const data = {
5018
+ enabled: true,
5019
+ platform: this.platform,
5020
+ enabledAt: this.enabledAt || Date.now()
5021
+ };
5022
+ try {
5023
+ writeFileSync3(this.flagFilePath, JSON.stringify(data, null, 2) + "\n", "utf-8");
5024
+ } catch {
5025
+ }
5026
+ }
5027
+ deleteFlagFile() {
5028
+ try {
5029
+ if (existsSync3(this.flagFilePath)) {
5030
+ unlinkSync(this.flagFilePath);
5031
+ }
5032
+ } catch {
5033
+ }
5034
+ }
5035
+ checkOrphanedFlag() {
5036
+ try {
5037
+ if (!existsSync3(this.flagFilePath)) return;
5038
+ const raw = readFileSync3(this.flagFilePath, "utf-8");
5039
+ const data = JSON.parse(raw);
5040
+ if (data.enabled) {
5041
+ console.log("Reverting orphaned sleep prevention setting...");
5042
+ this.enabled = true;
5043
+ this.enabledAt = data.enabledAt;
5044
+ this.disable().catch(() => {
5045
+ });
5046
+ }
5047
+ } catch {
5048
+ this.deleteFlagFile();
5049
+ }
5050
+ }
5051
+ };
5052
+
4690
5053
  // src/daemon.ts
4691
5054
  var HUB_EXTERNAL_PORT = 7962;
4692
5055
  var HUB_INTERNAL_PORT = 7963;
4693
5056
  var AUTO_SHUTDOWN_DELAY_MS = 3e4;
4694
- function getHubDir() {
4695
- return process.env.ITWILLSYNC_CONFIG_DIR || join4(homedir4(), ".itwillsync");
5057
+ function getHubDir2() {
5058
+ return process.env.ITWILLSYNC_CONFIG_DIR || join5(homedir5(), ".itwillsync");
4696
5059
  }
4697
5060
  function getPidPath() {
4698
- return join4(getHubDir(), "hub.pid");
5061
+ return join5(getHubDir2(), "hub.pid");
4699
5062
  }
4700
5063
  function getHubConfigPath() {
4701
- return join4(getHubDir(), "hub.json");
5064
+ return join5(getHubDir2(), "hub.json");
4702
5065
  }
4703
5066
  function isValidToolName(tool) {
4704
5067
  return /^[a-zA-Z0-9._-]+$/.test(tool) && tool.length > 0 && tool.length <= 100;
4705
5068
  }
4706
5069
  function spawnSession(tool, cwd, cliEntryPath) {
4707
- const child = spawn(process.execPath, [cliEntryPath, "--headless", "--", tool], {
5070
+ const child = spawn2(process.execPath, [cliEntryPath, "--headless", "--", tool], {
4708
5071
  cwd,
4709
5072
  stdio: "ignore",
4710
5073
  detached: true,
@@ -4714,11 +5077,11 @@ function spawnSession(tool, cwd, cliEntryPath) {
4714
5077
  return child;
4715
5078
  }
4716
5079
  async function main() {
4717
- const hubDir = getHubDir();
5080
+ const hubDir = getHubDir2();
4718
5081
  mkdirSync3(hubDir, { recursive: true });
4719
5082
  const masterToken = generateToken();
4720
5083
  const startedAt = Date.now();
4721
- writeFileSync3(getPidPath(), String(process.pid), "utf-8");
5084
+ writeFileSync4(getPidPath(), String(process.pid), "utf-8");
4722
5085
  const hubConfig = {
4723
5086
  masterToken,
4724
5087
  externalPort: HUB_EXTERNAL_PORT,
@@ -4726,21 +5089,22 @@ async function main() {
4726
5089
  pid: process.pid,
4727
5090
  startedAt
4728
5091
  };
4729
- writeFileSync3(getHubConfigPath(), JSON.stringify(hubConfig, null, 2) + "\n", "utf-8");
5092
+ writeFileSync4(getHubConfigPath(), JSON.stringify(hubConfig, null, 2) + "\n", "utf-8");
4730
5093
  const sessionStore = new SessionStore();
4731
5094
  const registry = new SessionRegistry({ store: sessionStore });
4732
5095
  registry.startHealthChecks();
4733
5096
  const toolHistory = new ToolHistory();
4734
- const logsDir = join4(hubDir, "logs");
4735
- if (existsSync3(logsDir)) {
5097
+ const sleepPrevention = new SleepPrevention();
5098
+ const logsDir = join5(hubDir, "logs");
5099
+ if (existsSync4(logsDir)) {
4736
5100
  const retentionMs = 30 * 864e5;
4737
5101
  const cutoff = Date.now() - retentionMs;
4738
5102
  try {
4739
5103
  for (const file of readdirSync(logsDir)) {
4740
- const filePath = join4(logsDir, file);
5104
+ const filePath = join5(logsDir, file);
4741
5105
  try {
4742
5106
  const stat2 = statSync(filePath);
4743
- if (stat2.mtimeMs < cutoff) unlinkSync(filePath);
5107
+ if (stat2.mtimeMs < cutoff) unlinkSync2(filePath);
4744
5108
  } catch {
4745
5109
  }
4746
5110
  }
@@ -4748,8 +5112,8 @@ async function main() {
4748
5112
  }
4749
5113
  }
4750
5114
  const __dirname = dirname3(fileURLToPath(import.meta.url));
4751
- const dashboardPath = join4(__dirname, "dashboard");
4752
- const cliEntryPath = join4(__dirname, "..", "index.js");
5115
+ const dashboardPath = join5(__dirname, "dashboard");
5116
+ const cliEntryPath = join5(__dirname, "..", "index.js");
4753
5117
  const internalApi = createInternalApi({
4754
5118
  registry,
4755
5119
  port: HUB_INTERNAL_PORT
@@ -4763,6 +5127,7 @@ async function main() {
4763
5127
  port: HUB_EXTERNAL_PORT,
4764
5128
  previewCollector,
4765
5129
  toolHistory,
5130
+ sleepPrevention,
4766
5131
  onCreateSession: (tool, cwd) => {
4767
5132
  if (!isValidToolName(tool)) {
4768
5133
  throw new Error(`Invalid tool name: ${tool}`);
@@ -4802,6 +5167,7 @@ async function main() {
4802
5167
  });
4803
5168
  scheduleShutdown();
4804
5169
  function cleanup() {
5170
+ sleepPrevention.cleanupSync();
4805
5171
  previewCollector.close();
4806
5172
  registry.stopHealthChecks();
4807
5173
  sessionStore.flush();
@@ -4809,11 +5175,11 @@ async function main() {
4809
5175
  internalApi.close();
4810
5176
  dashboardServer.close();
4811
5177
  try {
4812
- unlinkSync(getPidPath());
5178
+ unlinkSync2(getPidPath());
4813
5179
  } catch {
4814
5180
  }
4815
5181
  try {
4816
- unlinkSync(getHubConfigPath());
5182
+ unlinkSync2(getHubConfigPath());
4817
5183
  } catch {
4818
5184
  }
4819
5185
  }