@telora/daemon 0.19.27 → 0.19.31

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 (37) hide show
  1. package/build-info.json +2 -2
  2. package/dist/config-hot-reload.d.ts +91 -0
  3. package/dist/config-hot-reload.d.ts.map +1 -0
  4. package/dist/config-hot-reload.js +121 -0
  5. package/dist/config-hot-reload.js.map +1 -0
  6. package/dist/config-reconcile.d.ts +114 -0
  7. package/dist/config-reconcile.d.ts.map +1 -0
  8. package/dist/config-reconcile.js +187 -0
  9. package/dist/config-reconcile.js.map +1 -0
  10. package/dist/drain-teardown.d.ts +66 -0
  11. package/dist/drain-teardown.d.ts.map +1 -0
  12. package/dist/drain-teardown.js +56 -0
  13. package/dist/drain-teardown.js.map +1 -0
  14. package/dist/focus-engine.d.ts.map +1 -1
  15. package/dist/focus-engine.js +28 -0
  16. package/dist/focus-engine.js.map +1 -1
  17. package/dist/focus-executor.d.ts.map +1 -1
  18. package/dist/focus-executor.js +20 -0
  19. package/dist/focus-executor.js.map +1 -1
  20. package/dist/index.js +66 -4
  21. package/dist/index.js.map +1 -1
  22. package/dist/stop-request.d.ts +54 -0
  23. package/dist/stop-request.d.ts.map +1 -0
  24. package/dist/stop-request.js +89 -0
  25. package/dist/stop-request.js.map +1 -0
  26. package/dist/unified-engine-lifecycle.d.ts +68 -10
  27. package/dist/unified-engine-lifecycle.d.ts.map +1 -1
  28. package/dist/unified-engine-lifecycle.js +177 -71
  29. package/dist/unified-engine-lifecycle.js.map +1 -1
  30. package/dist/unified-shell.d.ts.map +1 -1
  31. package/dist/unified-shell.js +73 -8
  32. package/dist/unified-shell.js.map +1 -1
  33. package/dist/worker-pidfile.d.ts +77 -0
  34. package/dist/worker-pidfile.d.ts.map +1 -0
  35. package/dist/worker-pidfile.js +161 -0
  36. package/dist/worker-pidfile.js.map +1 -0
  37. package/package.json +2 -2
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Persisted team-lead pid registry -- closes the hard-kill orphan gap.
3
+ *
4
+ * Team leads are spawned detached (their own process group; focus-executor
5
+ * spawnCrashIsolated). The daemon's graceful shutdown reaps them via
6
+ * reapWorkerFleet, but a HARD kill (stop --force, a stop timeout, or an
7
+ * external `kill -9` on the daemon PID) tears the daemon down WITHOUT running
8
+ * that reap -- and because the leads are detached, they survive and orphan to
9
+ * init.
10
+ *
11
+ * The in-memory activeTeams map dies with the daemon, so a separate process
12
+ * (the `telora-daemon stop` CLI, or the NEXT daemon at boot) has no way to find
13
+ * those orphans. This module persists each live lead pid to a small JSON file
14
+ * in the global state dir so:
15
+ *
16
+ * - the CLI stop --force / timeout path can group-kill (`kill(-pid)`) every
17
+ * recorded lead after it SIGKILLs the daemon, and
18
+ * - the next daemon boot can reap any lead left alive by a prior hard kill
19
+ * (the only closure available for a bare external `kill -9 <daemon>`, which
20
+ * no in-process handler can intercept).
21
+ *
22
+ * All file ops are best-effort and never throw: a missing/corrupt file yields
23
+ * an empty fleet, and a write failure is swallowed (orphan prevention is a
24
+ * backstop, never a blocker on the spawn/exit hot path). One daemon per host
25
+ * (PID lock) makes read-modify-write races a non-issue.
26
+ */
27
+ /** A persisted live team lead: its pid and a human label for reap logging. */
28
+ export interface WorkerPidEntry {
29
+ pid: number;
30
+ label: string;
31
+ }
32
+ /** Resolve the worker pidfile path in the global state dir (~/.telora/). */
33
+ export declare function resolveWorkerPidfilePath(): string;
34
+ /**
35
+ * Read the persisted worker fleet. Tolerant: a missing, unreadable, or
36
+ * malformed file returns []. Only well-formed { pid, label } entries with a
37
+ * real pid (> 1) survive parsing.
38
+ */
39
+ export declare function readWorkerPidfile(path?: string): WorkerPidEntry[];
40
+ /**
41
+ * Record a live team lead. Idempotent per pid (a re-record updates the label).
42
+ * No-op for an invalid/init pid (<= 1).
43
+ */
44
+ export declare function recordWorkerPid(pid: number, label: string, path?: string): void;
45
+ /** Remove a lead pid on its exit. No-op when absent. */
46
+ export declare function removeWorkerPid(pid: number, path?: string): void;
47
+ /** Delete the pidfile entirely (graceful shutdown clears it after reaping). */
48
+ export declare function clearWorkerPidfile(path?: string): void;
49
+ /** Injectable seams for {@link reapPersistedWorkerGroups} (test without procs). */
50
+ export interface ReapPersistedDeps {
51
+ /** Signal sender. Defaults to process.kill. */
52
+ kill?: (pid: number, signal: NodeJS.Signals) => void;
53
+ /** Liveness probe. Defaults to a kill(pid, 0) existence check. */
54
+ isAlive?: (pid: number) => boolean;
55
+ }
56
+ /** Outcome of a persisted-fleet reap, for logging + tests. */
57
+ export interface ReapPersistedResult {
58
+ /** Pids that were alive and got a group SIGKILL. */
59
+ reaped: number[];
60
+ /** Pids skipped because they were already dead (or invalid). */
61
+ skipped: number[];
62
+ }
63
+ /**
64
+ * Group-SIGKILL every still-alive persisted lead. Because leads are spawned
65
+ * detached (own group, pgid == lead pid), `kill(-pid)` reaps the lead AND any
66
+ * host children it sub-spawned in one signal; a bare-pid fallback covers a lead
67
+ * that somehow is not a group leader. Pure over the injected seams. Never throws
68
+ * (a vanished process is success).
69
+ */
70
+ export declare function reapPersistedWorkerGroups(entries: WorkerPidEntry[], deps?: ReapPersistedDeps): ReapPersistedResult;
71
+ /**
72
+ * Read + reap the persisted fleet, then clear the file. Used by the CLI hard
73
+ * stop (after SIGKILLing the daemon) and by the next daemon boot (to reap leads
74
+ * a prior hard kill orphaned). Returns the reap result for logging.
75
+ */
76
+ export declare function reapAndClearWorkerPidfile(path?: string, deps?: ReapPersistedDeps): ReapPersistedResult;
77
+ //# sourceMappingURL=worker-pidfile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker-pidfile.d.ts","sourceRoot":"","sources":["../src/worker-pidfile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAMH,8EAA8E;AAC9E,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACf;AAED,4EAA4E;AAC5E,wBAAgB,wBAAwB,IAAI,MAAM,CAEjD;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,GAAE,MAAmC,GAAG,cAAc,EAAE,CAoB7F;AAWD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,GAAE,MAAmC,GAAG,IAAI,CAK3G;AAED,wDAAwD;AACxD,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,GAAE,MAAmC,GAAG,IAAI,CAS5F;AAED,+EAA+E;AAC/E,wBAAgB,kBAAkB,CAAC,IAAI,GAAE,MAAmC,GAAG,IAAI,CAMlF;AAED,mFAAmF;AACnF,MAAM,WAAW,iBAAiB;IAChC,+CAA+C;IAC/C,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,KAAK,IAAI,CAAC;IACrD,kEAAkE;IAClE,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;CACpC;AAED,8DAA8D;AAC9D,MAAM,WAAW,mBAAmB;IAClC,oDAAoD;IACpD,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,gEAAgE;IAChE,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAYD;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,cAAc,EAAE,EACzB,IAAI,GAAE,iBAAsB,GAC3B,mBAAmB,CA4BrB;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CACvC,IAAI,GAAE,MAAmC,EACzC,IAAI,GAAE,iBAAsB,GAC3B,mBAAmB,CAKrB"}
@@ -0,0 +1,161 @@
1
+ /**
2
+ * Persisted team-lead pid registry -- closes the hard-kill orphan gap.
3
+ *
4
+ * Team leads are spawned detached (their own process group; focus-executor
5
+ * spawnCrashIsolated). The daemon's graceful shutdown reaps them via
6
+ * reapWorkerFleet, but a HARD kill (stop --force, a stop timeout, or an
7
+ * external `kill -9` on the daemon PID) tears the daemon down WITHOUT running
8
+ * that reap -- and because the leads are detached, they survive and orphan to
9
+ * init.
10
+ *
11
+ * The in-memory activeTeams map dies with the daemon, so a separate process
12
+ * (the `telora-daemon stop` CLI, or the NEXT daemon at boot) has no way to find
13
+ * those orphans. This module persists each live lead pid to a small JSON file
14
+ * in the global state dir so:
15
+ *
16
+ * - the CLI stop --force / timeout path can group-kill (`kill(-pid)`) every
17
+ * recorded lead after it SIGKILLs the daemon, and
18
+ * - the next daemon boot can reap any lead left alive by a prior hard kill
19
+ * (the only closure available for a bare external `kill -9 <daemon>`, which
20
+ * no in-process handler can intercept).
21
+ *
22
+ * All file ops are best-effort and never throw: a missing/corrupt file yields
23
+ * an empty fleet, and a write failure is swallowed (orphan prevention is a
24
+ * backstop, never a blocker on the spawn/exit hot path). One daemon per host
25
+ * (PID lock) makes read-modify-write races a non-issue.
26
+ */
27
+ import { existsSync, readFileSync, writeFileSync, unlinkSync } from 'node:fs';
28
+ import { resolve } from 'node:path';
29
+ import { resolveGlobalStateDir } from './daemon-process.js';
30
+ /** Resolve the worker pidfile path in the global state dir (~/.telora/). */
31
+ export function resolveWorkerPidfilePath() {
32
+ return resolve(resolveGlobalStateDir(), 'daemon.workers.json');
33
+ }
34
+ /**
35
+ * Read the persisted worker fleet. Tolerant: a missing, unreadable, or
36
+ * malformed file returns []. Only well-formed { pid, label } entries with a
37
+ * real pid (> 1) survive parsing.
38
+ */
39
+ export function readWorkerPidfile(path = resolveWorkerPidfilePath()) {
40
+ if (!existsSync(path))
41
+ return [];
42
+ try {
43
+ const raw = JSON.parse(readFileSync(path, 'utf-8'));
44
+ if (!Array.isArray(raw))
45
+ return [];
46
+ const out = [];
47
+ for (const e of raw) {
48
+ if (typeof e === 'object' && e !== null &&
49
+ typeof e.pid === 'number' &&
50
+ e.pid > 1) {
51
+ const entry = e;
52
+ out.push({ pid: entry.pid, label: typeof entry.label === 'string' ? entry.label : 'unknown' });
53
+ }
54
+ }
55
+ return out;
56
+ }
57
+ catch {
58
+ return [];
59
+ }
60
+ }
61
+ /** Best-effort write of the fleet. Swallows all errors. */
62
+ function writeWorkerPidfile(entries, path) {
63
+ try {
64
+ writeFileSync(path, JSON.stringify(entries), { mode: 0o600 });
65
+ }
66
+ catch {
67
+ // Orphan prevention is a backstop -- never fail a spawn/exit on this.
68
+ }
69
+ }
70
+ /**
71
+ * Record a live team lead. Idempotent per pid (a re-record updates the label).
72
+ * No-op for an invalid/init pid (<= 1).
73
+ */
74
+ export function recordWorkerPid(pid, label, path = resolveWorkerPidfilePath()) {
75
+ if (!Number.isInteger(pid) || pid <= 1)
76
+ return;
77
+ const entries = readWorkerPidfile(path).filter((e) => e.pid !== pid);
78
+ entries.push({ pid, label });
79
+ writeWorkerPidfile(entries, path);
80
+ }
81
+ /** Remove a lead pid on its exit. No-op when absent. */
82
+ export function removeWorkerPid(pid, path = resolveWorkerPidfilePath()) {
83
+ const entries = readWorkerPidfile(path);
84
+ const next = entries.filter((e) => e.pid !== pid);
85
+ if (next.length === entries.length)
86
+ return;
87
+ if (next.length === 0) {
88
+ clearWorkerPidfile(path);
89
+ return;
90
+ }
91
+ writeWorkerPidfile(next, path);
92
+ }
93
+ /** Delete the pidfile entirely (graceful shutdown clears it after reaping). */
94
+ export function clearWorkerPidfile(path = resolveWorkerPidfilePath()) {
95
+ try {
96
+ if (existsSync(path))
97
+ unlinkSync(path);
98
+ }
99
+ catch {
100
+ // Best effort.
101
+ }
102
+ }
103
+ /** Default liveness: kill(pid, 0) throws iff the process does not exist. */
104
+ function defaultIsAlive(pid) {
105
+ try {
106
+ process.kill(pid, 0);
107
+ return true;
108
+ }
109
+ catch {
110
+ return false;
111
+ }
112
+ }
113
+ /**
114
+ * Group-SIGKILL every still-alive persisted lead. Because leads are spawned
115
+ * detached (own group, pgid == lead pid), `kill(-pid)` reaps the lead AND any
116
+ * host children it sub-spawned in one signal; a bare-pid fallback covers a lead
117
+ * that somehow is not a group leader. Pure over the injected seams. Never throws
118
+ * (a vanished process is success).
119
+ */
120
+ export function reapPersistedWorkerGroups(entries, deps = {}) {
121
+ const kill = deps.kill ?? ((pid, signal) => { process.kill(pid, signal); });
122
+ const isAlive = deps.isAlive ?? defaultIsAlive;
123
+ const result = { reaped: [], skipped: [] };
124
+ for (const entry of entries) {
125
+ const { pid } = entry;
126
+ if (!Number.isInteger(pid) || pid <= 1) {
127
+ result.skipped.push(pid);
128
+ continue;
129
+ }
130
+ if (!isAlive(pid)) {
131
+ result.skipped.push(pid);
132
+ continue;
133
+ }
134
+ // Group-first (detached lead => pgid == pid), bare-pid fallback.
135
+ try {
136
+ kill(-pid, 'SIGKILL');
137
+ }
138
+ catch {
139
+ try {
140
+ kill(pid, 'SIGKILL');
141
+ }
142
+ catch {
143
+ // Already gone.
144
+ }
145
+ }
146
+ result.reaped.push(pid);
147
+ }
148
+ return result;
149
+ }
150
+ /**
151
+ * Read + reap the persisted fleet, then clear the file. Used by the CLI hard
152
+ * stop (after SIGKILLing the daemon) and by the next daemon boot (to reap leads
153
+ * a prior hard kill orphaned). Returns the reap result for logging.
154
+ */
155
+ export function reapAndClearWorkerPidfile(path = resolveWorkerPidfilePath(), deps = {}) {
156
+ const entries = readWorkerPidfile(path);
157
+ const result = reapPersistedWorkerGroups(entries, deps);
158
+ clearWorkerPidfile(path);
159
+ return result;
160
+ }
161
+ //# sourceMappingURL=worker-pidfile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker-pidfile.js","sourceRoot":"","sources":["../src/worker-pidfile.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@telora/daemon",
3
- "version": "0.19.27",
3
+ "version": "0.19.31",
4
4
  "description": "Agent orchestration daemon for Telora - spawns and manages Claude Code instances",
5
5
  "type": "module",
6
6
  "bin": {
@@ -37,7 +37,7 @@
37
37
  "//testRunner": "Uses Node.js built-in test runner (node:test) via tsx for TypeScript support. The root package uses Vitest; this is a deliberate choice for the daemon package to avoid framework dependencies. See src/__tests__/ for test files.",
38
38
  "dependencies": {
39
39
  "@telora/daemon": "^0.19.2",
40
- "@telora/daemon-core": "^0.2.56",
40
+ "@telora/daemon-core": "^0.2.57",
41
41
  "@telora/mcp-products": "^0.22.88",
42
42
  "commander": "^14.0.3",
43
43
  "yaml": "^2.4.0",