sensorium-mcp 3.0.4 → 3.0.5
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/dashboard/routes/data.d.ts.map +1 -1
- package/dist/dashboard/routes/data.js +2 -1
- package/dist/dashboard/routes/data.js.map +1 -1
- package/dist/dashboard/routes/threads.js +1 -1
- package/dist/dashboard/routes/threads.js.map +1 -1
- package/dist/dashboard/routes.d.ts.map +1 -1
- package/dist/dashboard/routes.js +1 -3
- package/dist/dashboard/routes.js.map +1 -1
- package/dist/data/memory/migration-runner.d.ts +1 -1
- package/dist/data/memory/migration-runner.d.ts.map +1 -1
- package/dist/data/memory/migration-runner.js +59 -3
- package/dist/data/memory/migration-runner.js.map +1 -1
- package/dist/data/memory/schema-ddl.d.ts +1 -1
- package/dist/data/memory/schema-ddl.d.ts.map +1 -1
- package/dist/data/memory/schema-ddl.js +2 -1
- package/dist/data/memory/schema-ddl.js.map +1 -1
- package/dist/data/memory/thread-registry.js +1 -1
- package/dist/data/memory/thread-registry.js.map +1 -1
- package/dist/http-server.d.ts.map +1 -1
- package/dist/http-server.js +1 -9
- package/dist/http-server.js.map +1 -1
- package/dist/index.js +3 -6
- package/dist/index.js.map +1 -1
- package/dist/server/factory.js +1 -1
- package/dist/server/factory.js.map +1 -1
- package/dist/services/agent-spawn.service.d.ts +7 -1
- package/dist/services/agent-spawn.service.d.ts.map +1 -1
- package/dist/services/agent-spawn.service.js +69 -45
- package/dist/services/agent-spawn.service.js.map +1 -1
- package/dist/services/consolidation.service.d.ts.map +1 -1
- package/dist/services/consolidation.service.js +49 -35
- package/dist/services/consolidation.service.js.map +1 -1
- package/dist/services/keeper.service.d.ts +21 -0
- package/dist/services/keeper.service.d.ts.map +1 -0
- package/dist/services/keeper.service.js +195 -0
- package/dist/services/keeper.service.js.map +1 -0
- package/dist/services/maintenance-signal.d.ts +2 -0
- package/dist/services/maintenance-signal.d.ts.map +1 -1
- package/dist/services/maintenance-signal.js +7 -1
- package/dist/services/maintenance-signal.js.map +1 -1
- package/dist/services/process.service.d.ts +19 -2
- package/dist/services/process.service.d.ts.map +1 -1
- package/dist/services/process.service.js +104 -10
- package/dist/services/process.service.js.map +1 -1
- package/dist/services/thread-lifecycle.service.d.ts +5 -0
- package/dist/services/thread-lifecycle.service.d.ts.map +1 -1
- package/dist/services/thread-lifecycle.service.js +33 -8
- package/dist/services/thread-lifecycle.service.js.map +1 -1
- package/dist/services/worker-cleanup.service.d.ts +14 -1
- package/dist/services/worker-cleanup.service.d.ts.map +1 -1
- package/dist/services/worker-cleanup.service.js +36 -38
- package/dist/services/worker-cleanup.service.js.map +1 -1
- package/dist/sessions.d.ts +0 -5
- package/dist/sessions.d.ts.map +1 -1
- package/dist/sessions.js +0 -7
- package/dist/sessions.js.map +1 -1
- package/dist/stdio-server.d.ts.map +1 -1
- package/dist/stdio-server.js +1 -7
- package/dist/stdio-server.js.map +1 -1
- package/dist/tools/delegate-tool.d.ts.map +1 -1
- package/dist/tools/delegate-tool.js +2 -2
- package/dist/tools/delegate-tool.js.map +1 -1
- package/dist/tools/session-tools.js +1 -1
- package/dist/tools/session-tools.js.map +1 -1
- package/dist/tools/start-session-tool.d.ts.map +1 -1
- package/dist/tools/start-session-tool.js +8 -9
- package/dist/tools/start-session-tool.js.map +1 -1
- package/dist/tools/wait/message-processing.d.ts.map +1 -1
- package/dist/tools/wait/message-processing.js +28 -0
- package/dist/tools/wait/message-processing.js.map +1 -1
- package/dist/tools/wait/poll-loop.js +1 -1
- package/dist/tools/wait/poll-loop.js.map +1 -1
- package/package.json +1 -1
- package/dist/tools/thread-lifecycle.d.ts +0 -6
- package/dist/tools/thread-lifecycle.d.ts.map +0 -1
- package/dist/tools/thread-lifecycle.js +0 -6
- package/dist/tools/thread-lifecycle.js.map +0 -1
- package/supervisor/config.go +0 -253
- package/supervisor/config_test.go +0 -78
- package/supervisor/go.mod +0 -15
- package/supervisor/go.sum +0 -20
- package/supervisor/health.go +0 -433
- package/supervisor/health_test.go +0 -93
- package/supervisor/keeper.go +0 -309
- package/supervisor/keeper_test.go +0 -27
- package/supervisor/lock.go +0 -57
- package/supervisor/lock_test.go +0 -54
- package/supervisor/log.go +0 -195
- package/supervisor/log_test.go +0 -125
- package/supervisor/main.go +0 -475
- package/supervisor/main_test.go +0 -130
- package/supervisor/notify.go +0 -53
- package/supervisor/process.go +0 -294
- package/supervisor/process_test.go +0 -108
- package/supervisor/process_unix.go +0 -14
- package/supervisor/process_windows.go +0 -15
- package/supervisor/secrets.go +0 -95
- package/supervisor/secrets_securevault_test.go +0 -98
- package/supervisor/secrets_test.go +0 -119
- package/supervisor/self_update.go +0 -282
- package/supervisor/self_update_test.go +0 -177
- package/supervisor/service_restart_stub.go +0 -9
- package/supervisor/service_restart_windows.go +0 -63
- package/supervisor/service_stub.go +0 -15
- package/supervisor/service_windows.go +0 -194
- package/supervisor/update_state.go +0 -264
- package/supervisor/update_state_test.go +0 -306
- package/supervisor/updater.go +0 -613
- package/supervisor/updater_test.go +0 -64
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import { log } from "../logger.js";
|
|
2
|
+
import { findAliveThreadViaPidFile, killProcessTree } from "./process.service.js";
|
|
3
|
+
import { readThreadHeartbeat } from "../data/file-storage.js";
|
|
4
|
+
import { dispatchSpawn } from "./agent-spawn.service.js";
|
|
5
|
+
import { getKeepAliveThreads, getThread } from "../data/memory/thread-registry.js";
|
|
6
|
+
import { ThreadState } from "./thread-lifecycle.service.js";
|
|
7
|
+
import { errorMessage } from "../utils.js";
|
|
8
|
+
const KEEPER_CHECK_INTERVAL_MS = 120_000; // 2 min
|
|
9
|
+
const KEEPER_MAX_RETRIES = 5;
|
|
10
|
+
const KEEPER_COOLDOWN_MS = 300_000; // 5 min
|
|
11
|
+
const FAST_EXIT_THRESHOLD_MS = 60_000; // 60s
|
|
12
|
+
const FAST_EXIT_MAX_COUNT = 3;
|
|
13
|
+
const FAST_EXIT_BASE_COOLDOWN_MS = 600_000; // 10 min
|
|
14
|
+
const FAST_EXIT_MAX_COOLDOWN_MS = 14_400_000; // 4 hours
|
|
15
|
+
const STUCK_THRESHOLD_MS = 1_800_000; // 30 min
|
|
16
|
+
export class KeeperService {
|
|
17
|
+
deps;
|
|
18
|
+
keepers = new Map();
|
|
19
|
+
syncTimer = null;
|
|
20
|
+
constructor(deps) {
|
|
21
|
+
this.deps = deps;
|
|
22
|
+
}
|
|
23
|
+
start() {
|
|
24
|
+
if (this.syncTimer !== null)
|
|
25
|
+
return;
|
|
26
|
+
this.syncKeepers();
|
|
27
|
+
this.syncTimer = setInterval(() => this.syncKeepers(), KEEPER_CHECK_INTERVAL_MS);
|
|
28
|
+
}
|
|
29
|
+
stop() {
|
|
30
|
+
if (this.syncTimer !== null) {
|
|
31
|
+
clearInterval(this.syncTimer);
|
|
32
|
+
this.syncTimer = null;
|
|
33
|
+
}
|
|
34
|
+
for (const entry of this.keepers.values()) {
|
|
35
|
+
entry.stopped = true;
|
|
36
|
+
}
|
|
37
|
+
this.keepers.clear();
|
|
38
|
+
}
|
|
39
|
+
syncKeepers() {
|
|
40
|
+
let threads;
|
|
41
|
+
try {
|
|
42
|
+
const db = this.deps.getMemoryDb();
|
|
43
|
+
threads = getKeepAliveThreads(db);
|
|
44
|
+
}
|
|
45
|
+
catch (err) {
|
|
46
|
+
log.warn(`[keeper] Failed to fetch keepAlive threads: ${errorMessage(err)}`);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
const wanted = new Set(threads.map((t) => t.threadId));
|
|
50
|
+
// Remove keepers no longer in the keepAlive list
|
|
51
|
+
for (const [threadId, entry] of this.keepers.entries()) {
|
|
52
|
+
if (!wanted.has(threadId)) {
|
|
53
|
+
entry.stopped = true;
|
|
54
|
+
this.keepers.delete(threadId);
|
|
55
|
+
log.info(`[keeper] Stopped keeper for removed thread ${threadId}`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// Add new keepers
|
|
59
|
+
for (const thread of threads) {
|
|
60
|
+
if (!this.keepers.has(thread.threadId)) {
|
|
61
|
+
this.keepers.set(thread.threadId, {
|
|
62
|
+
threadId: thread.threadId,
|
|
63
|
+
retryCount: 0,
|
|
64
|
+
fastExitCount: 0,
|
|
65
|
+
fastExitEscalation: 0,
|
|
66
|
+
lastStartTime: 0,
|
|
67
|
+
cooldownUntil: 0,
|
|
68
|
+
stopped: false,
|
|
69
|
+
checking: false,
|
|
70
|
+
});
|
|
71
|
+
log.info(`[keeper] Started keeper for thread ${thread.threadId} ('${thread.name}')`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// Check all active keepers (skip if already in-flight to prevent duplicate spawns)
|
|
75
|
+
for (const entry of this.keepers.values()) {
|
|
76
|
+
if (!entry.stopped && !entry.checking) {
|
|
77
|
+
entry.checking = true;
|
|
78
|
+
this.checkAndRestart(entry)
|
|
79
|
+
.catch((err) => {
|
|
80
|
+
log.warn(`[keeper] checkAndRestart error for thread ${entry.threadId}: ${errorMessage(err)}`);
|
|
81
|
+
})
|
|
82
|
+
.finally(() => { entry.checking = false; });
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
async checkAndRestart(entry) {
|
|
87
|
+
const now = Date.now();
|
|
88
|
+
// 1. Check cooldown
|
|
89
|
+
if (entry.cooldownUntil > now) {
|
|
90
|
+
log.debug(`[keeper] Thread ${entry.threadId} in cooldown for ${Math.round((entry.cooldownUntil - now) / 1000)}s`);
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
// 2. Check if thread is running — reads PID file directly (authoritative OS evidence)
|
|
94
|
+
const alivePid = findAliveThreadViaPidFile(entry.threadId);
|
|
95
|
+
if (alivePid !== undefined) {
|
|
96
|
+
// 3. Check if stuck via heartbeat
|
|
97
|
+
const heartbeat = readThreadHeartbeat(entry.threadId);
|
|
98
|
+
if (heartbeat !== null && (now - heartbeat) > STUCK_THRESHOLD_MS) {
|
|
99
|
+
log.warn(`[keeper] Thread ${entry.threadId} is stuck (no heartbeat for ${Math.round((now - heartbeat) / 60000)}m) — killing`);
|
|
100
|
+
try {
|
|
101
|
+
const stuckDb = this.deps.getMemoryDb();
|
|
102
|
+
this.deps.threadLifecycle.transitionThread(stuckDb, entry.threadId, ThreadState.Stuck);
|
|
103
|
+
}
|
|
104
|
+
catch (err) {
|
|
105
|
+
log.warn(`[keeper] Active→Stuck transition failed for ${entry.threadId}: ${errorMessage(err)}`);
|
|
106
|
+
}
|
|
107
|
+
killProcessTree(alivePid, entry.threadId);
|
|
108
|
+
entry.retryCount = 0;
|
|
109
|
+
// Fall through to restart
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
// Healthy — reset counters
|
|
113
|
+
if (entry.retryCount > 0) {
|
|
114
|
+
log.info(`[keeper] Thread ${entry.threadId} is healthy again (was at retry ${entry.retryCount})`);
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
log.debug(`[keeper] Thread ${entry.threadId} is healthy`);
|
|
118
|
+
}
|
|
119
|
+
entry.retryCount = 0;
|
|
120
|
+
entry.fastExitCount = 0;
|
|
121
|
+
entry.fastExitEscalation = 0;
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
// Thread is not running (or was stuck and killed)
|
|
126
|
+
// 4. Fast-exit detection
|
|
127
|
+
if (entry.lastStartTime > 0 && (now - entry.lastStartTime) < FAST_EXIT_THRESHOLD_MS) {
|
|
128
|
+
entry.fastExitCount++;
|
|
129
|
+
if (entry.fastExitCount >= FAST_EXIT_MAX_COUNT) {
|
|
130
|
+
const cooldown = Math.min(FAST_EXIT_BASE_COOLDOWN_MS * Math.pow(2, entry.fastExitEscalation), FAST_EXIT_MAX_COOLDOWN_MS);
|
|
131
|
+
entry.cooldownUntil = now + cooldown;
|
|
132
|
+
entry.fastExitEscalation++;
|
|
133
|
+
log.warn(`[keeper] Thread ${entry.threadId}: ${entry.fastExitCount} consecutive fast exits — backing off ${Math.round(cooldown / 60000)}m`);
|
|
134
|
+
await this.notifyDeath(entry.threadId, "repeated fast exits — check credits/API key", cooldown);
|
|
135
|
+
entry.fastExitCount = 0;
|
|
136
|
+
entry.retryCount = 0;
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
else if (entry.lastStartTime > 0) {
|
|
141
|
+
// Previous start was long ago — not a fast exit pattern
|
|
142
|
+
entry.fastExitCount = 0;
|
|
143
|
+
entry.fastExitEscalation = 0;
|
|
144
|
+
}
|
|
145
|
+
// 5. Max retries check
|
|
146
|
+
if (entry.retryCount >= KEEPER_MAX_RETRIES) {
|
|
147
|
+
entry.cooldownUntil = now + KEEPER_COOLDOWN_MS;
|
|
148
|
+
log.warn(`[keeper] Thread ${entry.threadId}: max retries (${KEEPER_MAX_RETRIES}) exceeded — cooling down for ${KEEPER_COOLDOWN_MS / 60000}m`);
|
|
149
|
+
await this.notifyDeath(entry.threadId, "max retries exceeded", KEEPER_COOLDOWN_MS);
|
|
150
|
+
entry.retryCount = 0;
|
|
151
|
+
entry.fastExitCount = 0;
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
// 6. Restart: re-check stopped (may have been set by syncKeepers while in-flight)
|
|
155
|
+
if (entry.stopped)
|
|
156
|
+
return;
|
|
157
|
+
// Re-verify keepAlive before restarting
|
|
158
|
+
const db = this.deps.getMemoryDb();
|
|
159
|
+
const thread = getThread(db, entry.threadId);
|
|
160
|
+
if (!thread || !thread.keepAlive) {
|
|
161
|
+
log.info(`[keeper] Thread ${entry.threadId} no longer has keepAlive=true — will stop at next sync`);
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
log.info(`[keeper] Thread ${entry.threadId} not running — restarting (attempt ${entry.retryCount + 1}/${KEEPER_MAX_RETRIES})`);
|
|
165
|
+
const result = dispatchSpawn((thread.client || "claude"), thread.name, entry.threadId, this.deps.threadLifecycle, thread.workingDirectory ?? undefined);
|
|
166
|
+
if ("pid" in result) {
|
|
167
|
+
entry.lastStartTime = Date.now();
|
|
168
|
+
entry.retryCount = 0;
|
|
169
|
+
log.info(`[keeper] Thread ${entry.threadId} restarted successfully (PID=${result.pid})`);
|
|
170
|
+
try {
|
|
171
|
+
this.deps.threadLifecycle.activateThread(db, entry.threadId);
|
|
172
|
+
}
|
|
173
|
+
catch (err) {
|
|
174
|
+
log.warn(`[keeper] activateThread failed for ${entry.threadId}: ${errorMessage(err)}`);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
entry.retryCount++;
|
|
179
|
+
log.warn(`[keeper] Thread ${entry.threadId} restart failed (attempt ${entry.retryCount}/${KEEPER_MAX_RETRIES}): ${result.error}`);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
async notifyDeath(threadId, reason, cooldownMs) {
|
|
183
|
+
try {
|
|
184
|
+
const db = this.deps.getMemoryDb();
|
|
185
|
+
const thread = getThread(db, threadId);
|
|
186
|
+
const name = thread?.name ?? `Thread ${threadId}`;
|
|
187
|
+
const suffix = cooldownMs ? `cooling down for ${Math.round(cooldownMs / 60000)}m` : "will retry";
|
|
188
|
+
await this.deps.telegram.sendMessage(this.deps.chatId, `💀 <b>${name}</b> session died (${reason}) — ${suffix}`, "HTML", threadId);
|
|
189
|
+
}
|
|
190
|
+
catch (err) {
|
|
191
|
+
log.warn(`[keeper] notifyDeath failed for thread ${threadId}: ${errorMessage(err)}`);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
//# sourceMappingURL=keeper.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keeper.service.js","sourceRoot":"","sources":["../../src/services/keeper.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
* requiring callers to poll. The exported emitMaintenanceSignal() is
|
|
8
8
|
* available for manual/test triggering.
|
|
9
9
|
*/
|
|
10
|
+
/** Close the filesystem watcher (call during shutdown). */
|
|
11
|
+
export declare function closeMaintenanceWatcher(): void;
|
|
10
12
|
/** Manually fire the maintenance signal (e.g. from tests or from code that
|
|
11
13
|
* writes the flag directly without going through the file system watcher). */
|
|
12
14
|
export declare function emitMaintenanceSignal(): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"maintenance-signal.d.ts","sourceRoot":"","sources":["../../src/services/maintenance-signal.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;
|
|
1
|
+
{"version":3,"file":"maintenance-signal.d.ts","sourceRoot":"","sources":["../../src/services/maintenance-signal.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA+BH,2DAA2D;AAC3D,wBAAgB,uBAAuB,IAAI,IAAI,CAG9C;AAED;+EAC+E;AAC/E,wBAAgB,qBAAqB,IAAI,IAAI,CAE5C;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAG9D"}
|
|
@@ -20,8 +20,9 @@ emitter.setMaxListeners(500);
|
|
|
20
20
|
// Watch the data directory for maintenance.flag creation / modification.
|
|
21
21
|
// On Windows, fs.watch fires "rename" when files are created or deleted;
|
|
22
22
|
// on Linux/macOS it fires "rename" on creation and "change" on modification.
|
|
23
|
+
let watcher = null;
|
|
23
24
|
try {
|
|
24
|
-
watch(DATA_DIR, (_eventType, filename) => {
|
|
25
|
+
watcher = watch(DATA_DIR, (_eventType, filename) => {
|
|
25
26
|
if (filename === FLAG_NAME) {
|
|
26
27
|
emitter.emit("maintenance");
|
|
27
28
|
}
|
|
@@ -32,6 +33,11 @@ catch (err) {
|
|
|
32
33
|
// won't fire from the watcher — emitMaintenanceSignal() still works.
|
|
33
34
|
log.warn(`[maintenance-signal] Could not watch ${DATA_DIR}: ${err}`);
|
|
34
35
|
}
|
|
36
|
+
/** Close the filesystem watcher (call during shutdown). */
|
|
37
|
+
export function closeMaintenanceWatcher() {
|
|
38
|
+
watcher?.close();
|
|
39
|
+
watcher = null;
|
|
40
|
+
}
|
|
35
41
|
/** Manually fire the maintenance signal (e.g. from tests or from code that
|
|
36
42
|
* writes the flag directly without going through the file system watcher). */
|
|
37
43
|
export function emitMaintenanceSignal() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"maintenance-signal.js","sourceRoot":"","sources":["../../src/services/maintenance-signal.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAEnC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,qBAAqB,CAAC,CAAC;AACxD,MAAM,SAAS,GAAG,kBAAkB,CAAC;AAErC,MAAM,OAAO,GAAG,IAAI,YAAY,EAAE,CAAC;AACnC,wEAAwE;AACxE,OAAO,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;AAE7B,yEAAyE;AACzE,yEAAyE;AACzE,6EAA6E;AAC7E,IAAI,CAAC;IACH,KAAK,CAAC,QAAQ,EAAE,CAAC,UAAU,EAAE,QAAQ,EAAE,EAAE;
|
|
1
|
+
{"version":3,"file":"maintenance-signal.js","sourceRoot":"","sources":["../../src/services/maintenance-signal.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAEnC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,qBAAqB,CAAC,CAAC;AACxD,MAAM,SAAS,GAAG,kBAAkB,CAAC;AAErC,MAAM,OAAO,GAAG,IAAI,YAAY,EAAE,CAAC;AACnC,wEAAwE;AACxE,OAAO,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;AAE7B,yEAAyE;AACzE,yEAAyE;AACzE,6EAA6E;AAC7E,IAAI,OAAO,GAAoC,IAAI,CAAC;AACpD,IAAI,CAAC;IACH,OAAO,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC,UAAU,EAAE,QAAQ,EAAE,EAAE;QACjD,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC3B,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC;AAAC,OAAO,GAAG,EAAE,CAAC;IACb,uEAAuE;IACvE,qEAAqE;IACrE,GAAG,CAAC,IAAI,CAAC,wCAAwC,QAAQ,KAAK,GAAG,EAAE,CAAC,CAAC;AACvE,CAAC;AAED,2DAA2D;AAC3D,MAAM,UAAU,uBAAuB;IACrC,OAAO,EAAE,KAAK,EAAE,CAAC;IACjB,OAAO,GAAG,IAAI,CAAC;AACjB,CAAC;AAED;+EAC+E;AAC/E,MAAM,UAAU,qBAAqB;IACnC,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;AAC9B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,EAAc;IAChD,OAAO,CAAC,EAAE,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;IAC9B,OAAO,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;AAC9C,CAAC"}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { Database } from "../data/memory/schema.js";
|
|
2
|
+
import type { ThreadLifecycleService } from "./thread-lifecycle.service.js";
|
|
1
3
|
export declare const PENDING_TASKS_DIR: string;
|
|
2
4
|
export declare const PROCESS_BASE_DIR: string;
|
|
3
5
|
export declare const PROCESS_LOGS_DIR: string;
|
|
@@ -24,8 +26,23 @@ export declare function isProcessAlive(pid: number): boolean;
|
|
|
24
26
|
export declare function readPidFiles(): PidFileEntry[];
|
|
25
27
|
export declare function findAliveThread(threadId: number): SpawnedThread | undefined;
|
|
26
28
|
export declare const isThreadRunning: (threadId: number) => boolean;
|
|
29
|
+
export declare function getActiveThreadIds(): number[];
|
|
27
30
|
export declare function ensureDirs(): void;
|
|
28
|
-
|
|
29
|
-
|
|
31
|
+
/**
|
|
32
|
+
* Check liveness of a thread directly via its PID file, bypassing the
|
|
33
|
+
* spawnedThreads[] in-memory cache. Returns the live PID, or undefined
|
|
34
|
+
* if no PID file exists or the process is dead (stale file is deleted).
|
|
35
|
+
*/
|
|
36
|
+
export declare function findAliveThreadViaPidFile(threadId: number): number | undefined;
|
|
37
|
+
/**
|
|
38
|
+
* Reconcile in-memory state (spawnedThreads[]) with the two authoritative
|
|
39
|
+
* sources of truth at startup:
|
|
40
|
+
* - SQLite thread_registry (intent / configuration)
|
|
41
|
+
* - PID files on disk (OS evidence of running processes)
|
|
42
|
+
*
|
|
43
|
+
* Replaces the old restoreFromPidFiles() + cleanupStalePidFiles() pair.
|
|
44
|
+
*/
|
|
45
|
+
export declare function reconcileState(db: Database, threadLifecycle: ThreadLifecycleService): void;
|
|
46
|
+
export declare function killProcessTree(pid: number, threadId: number): void;
|
|
30
47
|
export {};
|
|
31
48
|
//# sourceMappingURL=process.service.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"process.service.d.ts","sourceRoot":"","sources":["../../src/services/process.service.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"process.service.d.ts","sourceRoot":"","sources":["../../src/services/process.service.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAEzD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AAM5E,eAAO,MAAM,iBAAiB,QAAkC,CAAC;AACjE,eAAO,MAAM,gBAAgB,QAAW,CAAC;AACzC,eAAO,MAAM,gBAAgB,QAAW,CAAC;AACzC,eAAO,MAAM,gBAAgB,QAAW,CAAC;AAEzC,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,UAAU,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;CAClC;AAED,UAAU,YAAY;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,eAAO,MAAM,cAAc,EAAE,aAAa,EAAO,CAAC;AAElD,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAOnD;AAED,wBAAgB,YAAY,IAAI,YAAY,EAAE,CAqB7C;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAuB3E;AAED,eAAO,MAAM,eAAe,GAAI,UAAU,MAAM,KAAG,OAAkD,CAAC;AAEtG,wBAAgB,kBAAkB,IAAI,MAAM,EAAE,CAE7C;AAED,wBAAgB,UAAU,IAAI,IAAI,CAIjC;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAQ9E;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,QAAQ,EAAE,eAAe,EAAE,sBAAsB,GAAG,IAAI,CAqD1F;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAanE"}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { execSync } from "node:child_process";
|
|
2
|
-
import {
|
|
2
|
+
import { mkdirSync, readdirSync, readFileSync, unlinkSync } from "node:fs";
|
|
3
3
|
import { homedir } from "node:os";
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
import { log } from "../logger.js";
|
|
6
|
+
import { errorMessage } from "../utils.js";
|
|
7
|
+
import { getAllThreads } from "../data/memory/thread-registry.js";
|
|
6
8
|
const BASE_DIR = join(homedir(), ".remote-copilot-mcp");
|
|
7
9
|
const LOGS_DIR = join(BASE_DIR, "logs");
|
|
8
10
|
const PIDS_DIR = join(BASE_DIR, "pids");
|
|
@@ -79,22 +81,114 @@ export function findAliveThread(threadId) {
|
|
|
79
81
|
return restored;
|
|
80
82
|
}
|
|
81
83
|
export const isThreadRunning = (threadId) => findAliveThread(threadId) !== undefined;
|
|
84
|
+
export function getActiveThreadIds() {
|
|
85
|
+
return spawnedThreads.filter(t => isProcessAlive(t.pid)).map(t => t.threadId);
|
|
86
|
+
}
|
|
82
87
|
export function ensureDirs() {
|
|
83
88
|
mkdirSync(PENDING_TASKS_DIR, { recursive: true });
|
|
84
89
|
mkdirSync(LOGS_DIR, { recursive: true });
|
|
85
90
|
mkdirSync(PIDS_DIR, { recursive: true });
|
|
86
91
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
92
|
+
/**
|
|
93
|
+
* Check liveness of a thread directly via its PID file, bypassing the
|
|
94
|
+
* spawnedThreads[] in-memory cache. Returns the live PID, or undefined
|
|
95
|
+
* if no PID file exists or the process is dead (stale file is deleted).
|
|
96
|
+
*/
|
|
97
|
+
export function findAliveThreadViaPidFile(threadId) {
|
|
98
|
+
const entry = readPidFiles().find((e) => e.threadId === threadId);
|
|
99
|
+
if (!entry)
|
|
100
|
+
return undefined;
|
|
101
|
+
if (!isProcessAlive(entry.pid)) {
|
|
102
|
+
try {
|
|
103
|
+
unlinkSync(entry.filePath);
|
|
104
|
+
}
|
|
105
|
+
catch { }
|
|
106
|
+
return undefined;
|
|
107
|
+
}
|
|
108
|
+
return entry.pid;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Reconcile in-memory state (spawnedThreads[]) with the two authoritative
|
|
112
|
+
* sources of truth at startup:
|
|
113
|
+
* - SQLite thread_registry (intent / configuration)
|
|
114
|
+
* - PID files on disk (OS evidence of running processes)
|
|
115
|
+
*
|
|
116
|
+
* Replaces the old restoreFromPidFiles() + cleanupStalePidFiles() pair.
|
|
117
|
+
*/
|
|
118
|
+
export function reconcileState(db, threadLifecycle) {
|
|
119
|
+
const pidEntries = readPidFiles();
|
|
120
|
+
const dbThreadMap = new Map(getAllThreads(db)
|
|
121
|
+
.filter((t) => ["active", "exited", "exiting", "spawning", "stuck"].includes(t.status))
|
|
122
|
+
.map((t) => [t.threadId, t]));
|
|
123
|
+
// 1. Process each PID file: alive → populate spawnedThreads[], dead → clean up
|
|
124
|
+
for (const pidEntry of pidEntries) {
|
|
125
|
+
const dbThread = dbThreadMap.get(pidEntry.threadId);
|
|
126
|
+
if (!dbThread) {
|
|
127
|
+
// PID file references a thread with no DB record (very old orphan) — remove it
|
|
128
|
+
log.warn(`[reconcileState] PID file for thread ${pidEntry.threadId} has no DB record — removing`);
|
|
129
|
+
try {
|
|
130
|
+
unlinkSync(pidEntry.filePath);
|
|
131
|
+
}
|
|
132
|
+
catch { }
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
if (isProcessAlive(pidEntry.pid)) {
|
|
136
|
+
// Alive: populate spawnedThreads[] if not already present
|
|
137
|
+
if (!spawnedThreads.some((t) => t.threadId === pidEntry.threadId)) {
|
|
138
|
+
spawnedThreads.push({
|
|
139
|
+
pid: pidEntry.pid,
|
|
140
|
+
threadId: pidEntry.threadId,
|
|
141
|
+
name: pidEntry.name ?? dbThread.name,
|
|
142
|
+
startedAt: Date.now(),
|
|
143
|
+
createdAt: Date.now(),
|
|
144
|
+
logFile: "",
|
|
145
|
+
});
|
|
146
|
+
log.info(`[reconcileState] Restored thread ${pidEntry.threadId} PID=${pidEntry.pid} from PID file`);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
// Dead: clean up stale PID file and mark thread exited in DB if active
|
|
94
151
|
try {
|
|
95
|
-
unlinkSync(filePath);
|
|
152
|
+
unlinkSync(pidEntry.filePath);
|
|
96
153
|
}
|
|
97
154
|
catch { }
|
|
155
|
+
log.info(`[reconcileState] Cleaned stale PID file for thread ${pidEntry.threadId} (PID=${pidEntry.pid} dead)`);
|
|
156
|
+
if (["active", "exiting", "spawning", "stuck"].includes(dbThread.status)) {
|
|
157
|
+
try {
|
|
158
|
+
threadLifecycle.markExited(db, pidEntry.threadId);
|
|
159
|
+
}
|
|
160
|
+
catch (err) {
|
|
161
|
+
log.warn(`[reconcileState] markExited failed for thread ${pidEntry.threadId}: ${errorMessage(err)}`);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
// 2. Remove spawnedThreads[] entries that have no DB record
|
|
167
|
+
for (let i = spawnedThreads.length - 1; i >= 0; i--) {
|
|
168
|
+
const thread = spawnedThreads[i];
|
|
169
|
+
if (!dbThreadMap.has(thread.threadId)) {
|
|
170
|
+
log.warn(`[reconcileState] spawnedThreads has thread ${thread.threadId} with no DB record — removing`);
|
|
171
|
+
spawnedThreads.splice(i, 1);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
export function killProcessTree(pid, threadId) {
|
|
176
|
+
try {
|
|
177
|
+
if (process.platform === "win32") {
|
|
178
|
+
execSync(`taskkill /F /T /PID ${pid}`, { timeout: 10000 });
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
process.kill(pid, "SIGTERM");
|
|
182
|
+
}
|
|
183
|
+
log.info(`[process] Killed process tree for thread ${threadId} PID=${pid}`);
|
|
184
|
+
}
|
|
185
|
+
catch (err) {
|
|
186
|
+
log.debug(`[process] Kill process ${pid} (thread ${threadId}): ${errorMessage(err)}`);
|
|
187
|
+
}
|
|
188
|
+
const pidFile = join(PROCESS_PIDS_DIR, `${threadId}.pid`);
|
|
189
|
+
try {
|
|
190
|
+
unlinkSync(pidFile);
|
|
191
|
+
}
|
|
192
|
+
catch { }
|
|
98
193
|
}
|
|
99
|
-
export const pidDirExists = () => existsSync(PIDS_DIR);
|
|
100
194
|
//# sourceMappingURL=process.service.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"process.service.js","sourceRoot":"","sources":["../../src/services/process.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"process.service.js","sourceRoot":"","sources":["../../src/services/process.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import type { Database } from "../data/memory/schema.js";
|
|
2
2
|
import type { IThreadRepository, ISessionRepository } from "../data/interfaces.js";
|
|
3
3
|
export declare enum ThreadState {
|
|
4
|
+
Created = "created",
|
|
5
|
+
Spawning = "spawning",
|
|
4
6
|
Active = "active",
|
|
5
7
|
Dormant = "dormant",
|
|
8
|
+
Stuck = "stuck",
|
|
9
|
+
Exiting = "exiting",
|
|
6
10
|
Exited = "exited",
|
|
7
11
|
Archived = "archived",
|
|
8
12
|
Expired = "expired"
|
|
@@ -42,6 +46,7 @@ export declare class ThreadLifecycleService {
|
|
|
42
46
|
archiveThread(db: Database, threadId: number): ThreadRecord;
|
|
43
47
|
remapTopic(db: Database, input: RemapTopicInput): ThreadRecord;
|
|
44
48
|
getThreadState(db: Database, threadId: number): ThreadState | null;
|
|
49
|
+
transitionThread(db: Database, threadId: number, targetState: ThreadState): ThreadRecord;
|
|
45
50
|
private requireThread;
|
|
46
51
|
private assertTransition;
|
|
47
52
|
private syncTopicMappings;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"thread-lifecycle.service.d.ts","sourceRoot":"","sources":["../../src/services/thread-lifecycle.service.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,KAAK,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAEnF,oBAAY,WAAW;IACrB,MAAM,WAAW;IACjB,OAAO,YAAY;IACnB,MAAM,WAAW;IACjB,QAAQ,aAAa;IACrB,OAAO,YAAY;CACpB;AAED,KAAK,YAAY,GAAG,WAAW,CAAC,UAAU,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;AAG5E,KAAK,mBAAmB,GAAG,UAAU,CAAC,iBAAiB,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG;IAC9E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC,CAAC;AAEF,KAAK,mBAAmB,GAAG,OAAO,CAChC,IAAI,CACF,YAAY,EACZ,QAAQ,GAAG,WAAW,GAAG,cAAc,GAAG,iBAAiB,GAAG,kBAAkB,CACjF,CACF,CAAC;AAEF,KAAK,gBAAgB,GAAG,OAAO,CAC7B,IAAI,CAAC,YAAY,EAAE,cAAc,GAAG,iBAAiB,CAAC,CACvD,CAAC;AAEF,KAAK,eAAe,GAAG;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB,CAAC;AAEF,MAAM,WAAW,8BAA8B;IAC7C,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACpG;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;
|
|
1
|
+
{"version":3,"file":"thread-lifecycle.service.d.ts","sourceRoot":"","sources":["../../src/services/thread-lifecycle.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,15 +3,23 @@ import { homedir } from "node:os";
|
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
export var ThreadState;
|
|
5
5
|
(function (ThreadState) {
|
|
6
|
+
ThreadState["Created"] = "created";
|
|
7
|
+
ThreadState["Spawning"] = "spawning";
|
|
6
8
|
ThreadState["Active"] = "active";
|
|
7
9
|
ThreadState["Dormant"] = "dormant";
|
|
10
|
+
ThreadState["Stuck"] = "stuck";
|
|
11
|
+
ThreadState["Exiting"] = "exiting";
|
|
8
12
|
ThreadState["Exited"] = "exited";
|
|
9
13
|
ThreadState["Archived"] = "archived";
|
|
10
14
|
ThreadState["Expired"] = "expired";
|
|
11
15
|
})(ThreadState || (ThreadState = {}));
|
|
12
16
|
const VALID_TRANSITIONS = {
|
|
13
|
-
[ThreadState.
|
|
14
|
-
[ThreadState.
|
|
17
|
+
[ThreadState.Created]: new Set([ThreadState.Spawning, ThreadState.Active, ThreadState.Archived]),
|
|
18
|
+
[ThreadState.Spawning]: new Set([ThreadState.Active, ThreadState.Exited, ThreadState.Archived]),
|
|
19
|
+
[ThreadState.Active]: new Set([ThreadState.Active, ThreadState.Stuck, ThreadState.Exiting, ThreadState.Exited, ThreadState.Archived, ThreadState.Expired]),
|
|
20
|
+
[ThreadState.Dormant]: new Set([]), // Not persisted — no transitions until persistence is added
|
|
21
|
+
[ThreadState.Stuck]: new Set([ThreadState.Exiting, ThreadState.Exited, ThreadState.Active, ThreadState.Archived]),
|
|
22
|
+
[ThreadState.Exiting]: new Set([ThreadState.Exited, ThreadState.Archived]),
|
|
15
23
|
[ThreadState.Exited]: new Set([ThreadState.Active, ThreadState.Archived, ThreadState.Expired]),
|
|
16
24
|
[ThreadState.Archived]: new Set([ThreadState.Active]),
|
|
17
25
|
[ThreadState.Expired]: new Set([ThreadState.Archived]),
|
|
@@ -19,7 +27,7 @@ const VALID_TRANSITIONS = {
|
|
|
19
27
|
function cleanupThreadFiles(threadId) {
|
|
20
28
|
const base = join(homedir(), ".remote-copilot-mcp");
|
|
21
29
|
for (const filePath of [
|
|
22
|
-
join(base, "heartbeats", `${threadId}
|
|
30
|
+
join(base, "heartbeats", `${threadId}`),
|
|
23
31
|
join(base, "schedules", `${threadId}.json`),
|
|
24
32
|
join(base, "threads", `${threadId}.jsonl`),
|
|
25
33
|
]) {
|
|
@@ -83,7 +91,10 @@ export class ThreadLifecycleService {
|
|
|
83
91
|
}
|
|
84
92
|
markExited(db, threadId) {
|
|
85
93
|
const current = this.requireThread(db, threadId, "markExited");
|
|
86
|
-
|
|
94
|
+
// keepAlive threads transition back to Active so KeeperService detects them
|
|
95
|
+
// as dead on its next check interval and restarts them automatically.
|
|
96
|
+
// Non-keepAlive threads (any type) transition to Exited for final cleanup.
|
|
97
|
+
const nextState = !current.keepAlive
|
|
87
98
|
? ThreadState.Exited
|
|
88
99
|
: ThreadState.Active;
|
|
89
100
|
this.assertTransition(current.status, nextState, "markExited");
|
|
@@ -92,7 +103,10 @@ export class ThreadLifecycleService {
|
|
|
92
103
|
lastActiveAt: new Date().toISOString(),
|
|
93
104
|
});
|
|
94
105
|
const updated = this.requireThread(db, threadId, "markExited");
|
|
95
|
-
|
|
106
|
+
// Only clean up files for non-keepAlive threads; keepAlive threads will be
|
|
107
|
+
// restarted by KeeperService which needs a clean slate, not stale files.
|
|
108
|
+
if (!current.keepAlive)
|
|
109
|
+
cleanupThreadFiles(threadId);
|
|
96
110
|
this.logger.info(`[thread-lifecycle] markExited -> ${nextState} (${threadId})`);
|
|
97
111
|
return updated;
|
|
98
112
|
}
|
|
@@ -130,6 +144,17 @@ export class ThreadLifecycleService {
|
|
|
130
144
|
const thread = this.threadRepository.getThread(db, threadId);
|
|
131
145
|
return thread ? this.toLifecycleState(thread.status) : null;
|
|
132
146
|
}
|
|
147
|
+
transitionThread(db, threadId, targetState) {
|
|
148
|
+
const current = this.requireThread(db, threadId, "transitionThread");
|
|
149
|
+
this.assertTransition(current.status, targetState, "transitionThread");
|
|
150
|
+
this.threadRepository.updateThread(db, threadId, {
|
|
151
|
+
status: this.toPersistedState(targetState),
|
|
152
|
+
lastActiveAt: new Date().toISOString(),
|
|
153
|
+
});
|
|
154
|
+
const updated = this.requireThread(db, threadId, "transitionThread");
|
|
155
|
+
this.logger.info(`[thread-lifecycle] transitionThread -> ${targetState} (${threadId})`);
|
|
156
|
+
return updated;
|
|
157
|
+
}
|
|
133
158
|
requireThread(db, threadId, action) {
|
|
134
159
|
const thread = this.threadRepository.getThread(db, threadId);
|
|
135
160
|
if (!thread) {
|
|
@@ -139,8 +164,8 @@ export class ThreadLifecycleService {
|
|
|
139
164
|
}
|
|
140
165
|
assertTransition(current, next, action) {
|
|
141
166
|
if (current === undefined) {
|
|
142
|
-
if (next !== ThreadState.Active) {
|
|
143
|
-
throw new Error(`${action}: unregistered threads can only transition to active`);
|
|
167
|
+
if (next !== ThreadState.Active && next !== ThreadState.Created) {
|
|
168
|
+
throw new Error(`${action}: unregistered threads can only transition to active or created`);
|
|
144
169
|
}
|
|
145
170
|
return;
|
|
146
171
|
}
|
|
@@ -166,7 +191,7 @@ export class ThreadLifecycleService {
|
|
|
166
191
|
}
|
|
167
192
|
toPersistedState(state) {
|
|
168
193
|
if (state === ThreadState.Dormant) {
|
|
169
|
-
throw new Error("dormant is defined in the lifecycle model but is not
|
|
194
|
+
throw new Error("dormant is defined in the lifecycle model but is not persisted in thread_registry");
|
|
170
195
|
}
|
|
171
196
|
return state;
|
|
172
197
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"thread-lifecycle.service.js","sourceRoot":"","sources":["../../src/services/thread-lifecycle.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAIjC,MAAM,CAAN,IAAY,
|
|
1
|
+
{"version":3,"file":"thread-lifecycle.service.js","sourceRoot":"","sources":["../../src/services/thread-lifecycle.service.ts"],"names":[],"mappings":"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"}
|