agent-afk 2.22.2 → 2.24.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.
@@ -11,6 +11,9 @@
11
11
  */
12
12
 
13
13
  import { execSync } from 'node:child_process';
14
+ import { readFileSync } from 'node:fs';
15
+ import { homedir } from 'node:os';
16
+ import { join } from 'node:path';
14
17
 
15
18
  /**
16
19
  * Pure function. Determines whether the npm bin directory is on PATH.
@@ -27,6 +30,26 @@ export function detectPathGap(prefix, pathEnv) {
27
30
  return { onPath, binDir };
28
31
  }
29
32
 
33
+ /**
34
+ * Pure function. Attempts to SIGTERM a daemon whose PID is written in the
35
+ * given file. All errors are silently discarded — this is best-effort cleanup
36
+ * that must never fail an install.
37
+ *
38
+ * @param {string} pidFilePath - Full path to the PID file to read.
39
+ * @param {function} [killFn] - Injectable kill function; defaults to process.kill.
40
+ * Pass a stub in tests to avoid needing process.kill.
41
+ */
42
+ export function killStaleDaemon(pidFilePath, killFn = process.kill) {
43
+ try {
44
+ const raw = readFileSync(pidFilePath, 'utf8').trim();
45
+ const pid = parseInt(raw, 10);
46
+ if (!Number.isFinite(pid) || pid <= 0) return;
47
+ killFn(pid, 'SIGTERM');
48
+ } catch {
49
+ // File missing, non-numeric PID, ESRCH, EPERM, any other error — discard.
50
+ }
51
+ }
52
+
30
53
  // ─── Main block ─────────────────────────────────────────────────────────────
31
54
  // Guard: only run when executed directly (not when imported by tests).
32
55
  const isMain =
@@ -83,5 +106,16 @@ if (isMain) {
83
106
  // execSync failed (npm not found, timeout, etc.) — silently ignore.
84
107
  }
85
108
 
109
+ // Kill any stale daemon left over from the previous version so the
110
+ // updated binary takes over on next launch rather than the old process
111
+ // continuing to field requests.
112
+ try {
113
+ const afkHome = process.env['AFK_HOME'] ?? join(homedir(), '.afk');
114
+ const pidFilePath = join(afkHome, 'state', 'telegram', 'bot.pid');
115
+ killStaleDaemon(pidFilePath);
116
+ } catch {
117
+ // Belt-and-suspenders: killStaleDaemon already swallows all errors internally.
118
+ }
119
+
86
120
  process.exit(0);
87
121
  }