shadok-ai 0.3.111 → 0.4.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/lock.d.ts CHANGED
@@ -9,14 +9,34 @@
9
9
  */
10
10
  /** The lock file for the instance launched in `cwd` (default: process.cwd()). */
11
11
  export declare function instanceLockPath(cwd?: string): string;
12
- /** Whether a process with `pid` is currently running. */
13
- export declare function pidAlive(pid: number): boolean;
12
+ /**
13
+ * Pure: the process state letter from a `/proc/<pid>/stat` line, or null when
14
+ * the line is unusable.
15
+ *
16
+ * Read from the LAST `)`: the second field is the command name, parenthesised
17
+ * and arbitrary, so it may itself contain spaces and brackets. Splitting from
18
+ * the left mis-parses every process whose name has one.
19
+ */
20
+ export declare function stateFromProcStat(contents: string): string | null;
21
+ /** How `pidAlive` looks a process up; injected in tests. */
22
+ export type ProcStatReader = (pid: number) => string | null;
23
+ /**
24
+ * Whether a process with `pid` is currently running.
25
+ *
26
+ * A **zombie** answers signal 0: it has exited, but nobody has reaped it, so
27
+ * its pid entry survives. That is the normal case in a container, where pid 1
28
+ * is the application rather than an init that reaps — so a stopped instance
29
+ * held its launch directory's lock forever, and every later start was refused
30
+ * while naming a pid that no longer existed. `/proc` is Linux-only; where it is
31
+ * absent the signal's answer stands.
32
+ */
33
+ export declare function pidAlive(pid: number, procStat?: ProcStatReader): boolean;
14
34
  /**
15
35
  * Try to become the single instance for this launch dir. Returns { ok: true }
16
36
  * when the lock is held, or { ok: false, pid } when a LIVE instance already
17
37
  * holds it. A stale lock (dead holder) is reclaimed.
18
38
  */
19
- export declare function acquireInstanceLock(lockPath?: string): {
39
+ export declare function acquireInstanceLock(lockPath?: string, procStat?: ProcStatReader): {
20
40
  ok: true;
21
41
  } | {
22
42
  ok: false;
package/dist/lock.js CHANGED
@@ -15,24 +15,57 @@ export function instanceLockPath(cwd = process.cwd()) {
15
15
  const enc = cwd.replace(/[^a-zA-Z0-9]/g, "-");
16
16
  return path.join(os.homedir(), ".shadok-ai", "locks", enc + ".lock");
17
17
  }
18
- /** Whether a process with `pid` is currently running. */
19
- export function pidAlive(pid) {
18
+ /**
19
+ * Pure: the process state letter from a `/proc/<pid>/stat` line, or null when
20
+ * the line is unusable.
21
+ *
22
+ * Read from the LAST `)`: the second field is the command name, parenthesised
23
+ * and arbitrary, so it may itself contain spaces and brackets. Splitting from
24
+ * the left mis-parses every process whose name has one.
25
+ */
26
+ export function stateFromProcStat(contents) {
27
+ const close = contents.lastIndexOf(")");
28
+ if (close < 0)
29
+ return null;
30
+ const [state] = contents.slice(close + 1).trim().split(/\s+/);
31
+ return state || null;
32
+ }
33
+ const readProcStat = (pid) => {
34
+ try {
35
+ return fs.readFileSync(`/proc/${pid}/stat`, "utf8");
36
+ }
37
+ catch {
38
+ return null; // no /proc (macOS), or the process just vanished
39
+ }
40
+ };
41
+ /**
42
+ * Whether a process with `pid` is currently running.
43
+ *
44
+ * A **zombie** answers signal 0: it has exited, but nobody has reaped it, so
45
+ * its pid entry survives. That is the normal case in a container, where pid 1
46
+ * is the application rather than an init that reaps — so a stopped instance
47
+ * held its launch directory's lock forever, and every later start was refused
48
+ * while naming a pid that no longer existed. `/proc` is Linux-only; where it is
49
+ * absent the signal's answer stands.
50
+ */
51
+ export function pidAlive(pid, procStat = readProcStat) {
20
52
  if (!pid || pid <= 0)
21
53
  return false;
22
54
  try {
23
55
  process.kill(pid, 0); // signal 0 = existence check, doesn't kill
24
- return true;
25
56
  }
26
57
  catch (e) {
27
58
  return e?.code === "EPERM"; // exists but owned by another user → still alive
28
59
  }
60
+ const stat = procStat(pid);
61
+ return stat === null ? true : stateFromProcStat(stat) !== "Z";
29
62
  }
30
63
  /**
31
64
  * Try to become the single instance for this launch dir. Returns { ok: true }
32
65
  * when the lock is held, or { ok: false, pid } when a LIVE instance already
33
66
  * holds it. A stale lock (dead holder) is reclaimed.
34
67
  */
35
- export function acquireInstanceLock(lockPath = instanceLockPath()) {
68
+ export function acquireInstanceLock(lockPath = instanceLockPath(), procStat = readProcStat) {
36
69
  fs.mkdirSync(path.dirname(lockPath), { recursive: true });
37
70
  for (let i = 0; i < 3; i++) {
38
71
  try {
@@ -49,7 +82,7 @@ export function acquireInstanceLock(lockPath = instanceLockPath()) {
49
82
  pid = parseInt(fs.readFileSync(lockPath, "utf8").trim(), 10) || 0;
50
83
  }
51
84
  catch { /* unreadable */ }
52
- if (pid && pid !== process.pid && pidAlive(pid))
85
+ if (pid && pid !== process.pid && pidAlive(pid, procStat))
53
86
  return { ok: false, pid };
54
87
  try {
55
88
  fs.rmSync(lockPath);
package/dist/lock.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"lock.js","sourceRoot":"","sources":["../src/lock.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"lock.js","sourceRoot":"","sources":["../src/lock.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shadok-ai",
3
- "version": "0.3.111",
3
+ "version": "0.4.0",
4
4
  "main": "dist/session.js",
5
5
  "scripts": {
6
6
  "test": "node --import tsx --test test/*.ts .claude/skills/shadok-ai-agents/test/*.test.mjs context/*/test/*.test.mjs",