sensorium-mcp 3.0.3 → 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.
Files changed (112) hide show
  1. package/dist/dashboard/routes/data.d.ts.map +1 -1
  2. package/dist/dashboard/routes/data.js +2 -1
  3. package/dist/dashboard/routes/data.js.map +1 -1
  4. package/dist/dashboard/routes/threads.js +1 -1
  5. package/dist/dashboard/routes/threads.js.map +1 -1
  6. package/dist/dashboard/routes.d.ts.map +1 -1
  7. package/dist/dashboard/routes.js +1 -3
  8. package/dist/dashboard/routes.js.map +1 -1
  9. package/dist/data/memory/migration-runner.d.ts +1 -1
  10. package/dist/data/memory/migration-runner.d.ts.map +1 -1
  11. package/dist/data/memory/migration-runner.js +59 -3
  12. package/dist/data/memory/migration-runner.js.map +1 -1
  13. package/dist/data/memory/schema-ddl.d.ts +1 -1
  14. package/dist/data/memory/schema-ddl.d.ts.map +1 -1
  15. package/dist/data/memory/schema-ddl.js +2 -1
  16. package/dist/data/memory/schema-ddl.js.map +1 -1
  17. package/dist/data/memory/thread-registry.js +1 -1
  18. package/dist/data/memory/thread-registry.js.map +1 -1
  19. package/dist/http-server.d.ts.map +1 -1
  20. package/dist/http-server.js +1 -9
  21. package/dist/http-server.js.map +1 -1
  22. package/dist/index.js +3 -6
  23. package/dist/index.js.map +1 -1
  24. package/dist/server/factory.js +1 -1
  25. package/dist/server/factory.js.map +1 -1
  26. package/dist/services/agent-spawn.service.d.ts +7 -1
  27. package/dist/services/agent-spawn.service.d.ts.map +1 -1
  28. package/dist/services/agent-spawn.service.js +69 -45
  29. package/dist/services/agent-spawn.service.js.map +1 -1
  30. package/dist/services/consolidation.service.d.ts.map +1 -1
  31. package/dist/services/consolidation.service.js +49 -35
  32. package/dist/services/consolidation.service.js.map +1 -1
  33. package/dist/services/keeper.service.d.ts +21 -0
  34. package/dist/services/keeper.service.d.ts.map +1 -0
  35. package/dist/services/keeper.service.js +195 -0
  36. package/dist/services/keeper.service.js.map +1 -0
  37. package/dist/services/maintenance-signal.d.ts +2 -0
  38. package/dist/services/maintenance-signal.d.ts.map +1 -1
  39. package/dist/services/maintenance-signal.js +7 -1
  40. package/dist/services/maintenance-signal.js.map +1 -1
  41. package/dist/services/process.service.d.ts +19 -2
  42. package/dist/services/process.service.d.ts.map +1 -1
  43. package/dist/services/process.service.js +104 -10
  44. package/dist/services/process.service.js.map +1 -1
  45. package/dist/services/reconnect-snapshot.service.d.ts.map +1 -1
  46. package/dist/services/reconnect-snapshot.service.js +20 -3
  47. package/dist/services/reconnect-snapshot.service.js.map +1 -1
  48. package/dist/services/thread-lifecycle.service.d.ts +5 -0
  49. package/dist/services/thread-lifecycle.service.d.ts.map +1 -1
  50. package/dist/services/thread-lifecycle.service.js +33 -8
  51. package/dist/services/thread-lifecycle.service.js.map +1 -1
  52. package/dist/services/worker-cleanup.service.d.ts +14 -1
  53. package/dist/services/worker-cleanup.service.d.ts.map +1 -1
  54. package/dist/services/worker-cleanup.service.js +48 -27
  55. package/dist/services/worker-cleanup.service.js.map +1 -1
  56. package/dist/sessions.d.ts +0 -5
  57. package/dist/sessions.d.ts.map +1 -1
  58. package/dist/sessions.js +0 -7
  59. package/dist/sessions.js.map +1 -1
  60. package/dist/stdio-server.d.ts.map +1 -1
  61. package/dist/stdio-server.js +1 -7
  62. package/dist/stdio-server.js.map +1 -1
  63. package/dist/tools/delegate-tool.d.ts.map +1 -1
  64. package/dist/tools/delegate-tool.js +2 -2
  65. package/dist/tools/delegate-tool.js.map +1 -1
  66. package/dist/tools/session-tools.js +1 -1
  67. package/dist/tools/session-tools.js.map +1 -1
  68. package/dist/tools/start-session-tool.d.ts.map +1 -1
  69. package/dist/tools/start-session-tool.js +8 -9
  70. package/dist/tools/start-session-tool.js.map +1 -1
  71. package/dist/tools/wait/message-processing.d.ts.map +1 -1
  72. package/dist/tools/wait/message-processing.js +28 -0
  73. package/dist/tools/wait/message-processing.js.map +1 -1
  74. package/dist/tools/wait/poll-loop.js +1 -1
  75. package/dist/tools/wait/poll-loop.js.map +1 -1
  76. package/package.json +1 -1
  77. package/dist/tools/thread-lifecycle.d.ts +0 -6
  78. package/dist/tools/thread-lifecycle.d.ts.map +0 -1
  79. package/dist/tools/thread-lifecycle.js +0 -6
  80. package/dist/tools/thread-lifecycle.js.map +0 -1
  81. package/supervisor/config.go +0 -253
  82. package/supervisor/config_test.go +0 -78
  83. package/supervisor/go.mod +0 -15
  84. package/supervisor/go.sum +0 -20
  85. package/supervisor/health.go +0 -433
  86. package/supervisor/health_test.go +0 -93
  87. package/supervisor/keeper.go +0 -309
  88. package/supervisor/keeper_test.go +0 -27
  89. package/supervisor/lock.go +0 -57
  90. package/supervisor/lock_test.go +0 -54
  91. package/supervisor/log.go +0 -195
  92. package/supervisor/log_test.go +0 -125
  93. package/supervisor/main.go +0 -461
  94. package/supervisor/main_test.go +0 -130
  95. package/supervisor/notify.go +0 -53
  96. package/supervisor/process.go +0 -294
  97. package/supervisor/process_test.go +0 -108
  98. package/supervisor/process_unix.go +0 -14
  99. package/supervisor/process_windows.go +0 -15
  100. package/supervisor/secrets.go +0 -95
  101. package/supervisor/secrets_securevault_test.go +0 -98
  102. package/supervisor/secrets_test.go +0 -119
  103. package/supervisor/self_update.go +0 -282
  104. package/supervisor/self_update_test.go +0 -177
  105. package/supervisor/service_restart_stub.go +0 -9
  106. package/supervisor/service_restart_windows.go +0 -63
  107. package/supervisor/service_stub.go +0 -15
  108. package/supervisor/service_windows.go +0 -194
  109. package/supervisor/update_state.go +0 -264
  110. package/supervisor/update_state_test.go +0 -306
  111. package/supervisor/updater.go +0 -613
  112. 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;AA8BH;+EAC+E;AAC/E,wBAAgB,qBAAqB,IAAI,IAAI,CAE5C;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAG9D"}
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;QACvC,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;+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
+ {"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
- export declare function cleanupStalePidFiles(): void;
29
- export declare const pidDirExists: () => boolean;
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":"AAUA,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,UAAU,IAAI,IAAI,CAIjC;AAED,wBAAgB,oBAAoB,IAAI,IAAI,CAK3C;AAED,eAAO,MAAM,YAAY,QAAO,OAA+B,CAAC"}
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 { existsSync, mkdirSync, readdirSync, readFileSync, unlinkSync } from "node:fs";
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
- export function cleanupStalePidFiles() {
88
- const entries = readPidFiles();
89
- if (entries.length === 0)
90
- return;
91
- const alive = new Set(entries.map((e) => e.pid).filter((pid) => isProcessAlive(pid)));
92
- for (const { pid, filePath } of entries)
93
- if (!alive.has(pid))
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":"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"}
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,SAAS,EAAE,WAAW,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC3E,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAGlE,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,qBAAqB,CAAC,CAAC;AACxD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;AACxC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;AAExC,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAC;AACjE,MAAM,CAAC,MAAM,gBAAgB,GAAG,QAAQ,CAAC;AACzC,MAAM,CAAC,MAAM,gBAAgB,GAAG,QAAQ,CAAC;AACzC,MAAM,CAAC,MAAM,gBAAgB,GAAG,QAAQ,CAAC;AAqBzC,MAAM,CAAC,MAAM,cAAc,GAAoB,EAAE,CAAC;AAElD,MAAM,UAAU,cAAc,CAAC,GAAW;IACxC,IAAI,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACrB,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,OAAQ,GAA6B,CAAC,IAAI,KAAK,OAAO,CAAC;IACzD,CAAC;AACH,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,MAAM,OAAO,GAAmB,EAAE,CAAC;IACnC,IAAI,CAAC;QACH,KAAK,MAAM,IAAI,IAAI,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC;YACzC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;gBAAE,SAAS;YACrC,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC;gBAClD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;gBACtC,MAAM,GAAG,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;gBACnD,IAAI,GAAW,CAAC;gBAChB,IAAI,IAAwB,CAAC;gBAC7B,IAAI,CAAC;oBACH,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAmC,CAAC,CAAC;gBACtE,CAAC;gBAAC,MAAM,CAAC;oBACP,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;gBACpB,CAAC;gBACD,IAAI,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC;oBAAE,OAAO,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;YACzG,CAAC;YAAC,MAAM,CAAC,CAAA,CAAC;QACZ,CAAC;IACH,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;IACV,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,QAAgB;IAC9C,KAAK,IAAI,CAAC,GAAG,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QACpD,MAAM,MAAM,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC;QACjC,IAAI,MAAM,CAAC,QAAQ,KAAK,QAAQ;YAAE,SAAS;QAC3C,IAAI,cAAc,CAAC,MAAM,CAAC,GAAG,CAAC;YAAE,OAAO,MAAM,CAAC;QAC9C,GAAG,CAAC,IAAI,CAAC,4BAA4B,QAAQ,QAAQ,MAAM,CAAC,GAAG,qCAAqC,CAAC,CAAC;QACtG,cAAc,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC9B,CAAC;IACD,MAAM,QAAQ,GAAG,YAAY,EAAE,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,KAAK,QAAQ,IAAI,cAAc,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1G,IAAI,CAAC,QAAQ;QAAE,OAAO,SAAS,CAAC;IAChC,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QACjC,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,QAAQ,CAAC,wBAAwB,QAAQ,CAAC,GAAG,OAAO,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;YACxG,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;gBACxC,IAAI,CAAC;oBAAC,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;gBAAC,CAAC;gBAAC,MAAM,CAAC,CAAA,CAAC;gBAC/C,OAAO,SAAS,CAAC;YACnB,CAAC;QACH,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;IACZ,CAAC;IACD,MAAM,QAAQ,GAAG,EAAE,GAAG,EAAE,QAAQ,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,IAAI,UAAU,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IACzJ,cAAc,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC9B,GAAG,CAAC,IAAI,CAAC,qCAAqC,QAAQ,QAAQ,QAAQ,CAAC,GAAG,gBAAgB,CAAC,CAAC;IAC5F,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,QAAgB,EAAW,EAAE,CAAC,eAAe,CAAC,QAAQ,CAAC,KAAK,SAAS,CAAC;AAEtG,MAAM,UAAU,kBAAkB;IAChC,OAAO,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;AAChF,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,SAAS,CAAC,iBAAiB,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAClD,SAAS,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACzC,SAAS,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AAC3C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,yBAAyB,CAAC,QAAgB;IACxD,MAAM,KAAK,GAAG,YAAY,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC;IAClE,IAAI,CAAC,KAAK;QAAE,OAAO,SAAS,CAAC;IAC7B,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QAC/B,IAAI,CAAC;YAAC,UAAU,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;QAC5C,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,KAAK,CAAC,GAAG,CAAC;AACnB,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAAC,EAAY,EAAE,eAAuC;IAClF,MAAM,UAAU,GAAG,YAAY,EAAE,CAAC;IAClC,MAAM,WAAW,GAAG,IAAI,GAAG,CACzB,aAAa,CAAC,EAAE,CAAC;SACd,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;SACtF,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAC/B,CAAC;IAEF,+EAA+E;IAC/E,KAAK,MAAM,QAAQ,IAAI,UAAU,EAAE,CAAC;QAClC,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACpD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,+EAA+E;YAC/E,GAAG,CAAC,IAAI,CAAC,wCAAwC,QAAQ,CAAC,QAAQ,8BAA8B,CAAC,CAAC;YAClG,IAAI,CAAC;gBAAC,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAA,CAAC;YAC/C,SAAS;QACX,CAAC;QAED,IAAI,cAAc,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YACjC,0DAA0D;YAC1D,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAClE,cAAc,CAAC,IAAI,CAAC;oBAClB,GAAG,EAAE,QAAQ,CAAC,GAAG;oBACjB,QAAQ,EAAE,QAAQ,CAAC,QAAQ;oBAC3B,IAAI,EAAE,QAAQ,CAAC,IAAI,IAAI,QAAQ,CAAC,IAAI;oBACpC,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;oBACrB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;oBACrB,OAAO,EAAE,EAAE;iBACZ,CAAC,CAAC;gBACH,GAAG,CAAC,IAAI,CAAC,oCAAoC,QAAQ,CAAC,QAAQ,QAAQ,QAAQ,CAAC,GAAG,gBAAgB,CAAC,CAAC;YACtG,CAAC;QACH,CAAC;aAAM,CAAC;YACN,uEAAuE;YACvE,IAAI,CAAC;gBAAC,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAA,CAAC;YAC/C,GAAG,CAAC,IAAI,CAAC,sDAAsD,QAAQ,CAAC,QAAQ,SAAS,QAAQ,CAAC,GAAG,QAAQ,CAAC,CAAC;YAC/G,IAAI,CAAC,QAAQ,EAAE,SAAS,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;gBACzE,IAAI,CAAC;oBACH,eAAe,CAAC,UAAU,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC;gBACpD,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,GAAG,CAAC,IAAI,CAAC,iDAAiD,QAAQ,CAAC,QAAQ,KAAK,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gBACvG,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,4DAA4D;IAC5D,KAAK,IAAI,CAAC,GAAG,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QACpD,MAAM,MAAM,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC;QACjC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;YACtC,GAAG,CAAC,IAAI,CAAC,8CAA8C,MAAM,CAAC,QAAQ,+BAA+B,CAAC,CAAC;YACvG,cAAc,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,GAAW,EAAE,QAAgB;IAC3D,IAAI,CAAC;QACH,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;YACjC,QAAQ,CAAC,uBAAuB,GAAG,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QAC7D,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QAC/B,CAAC;QACD,GAAG,CAAC,IAAI,CAAC,4CAA4C,QAAQ,QAAQ,GAAG,EAAE,CAAC,CAAC;IAC9E,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,GAAG,CAAC,KAAK,CAAC,0BAA0B,GAAG,YAAY,QAAQ,MAAM,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACxF,CAAC;IACD,MAAM,OAAO,GAAG,IAAI,CAAC,gBAAgB,EAAE,GAAG,QAAQ,MAAM,CAAC,CAAC;IAC1D,IAAI,CAAC;QAAC,UAAU,CAAC,OAAO,CAAC,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;AACvC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"reconnect-snapshot.service.d.ts","sourceRoot":"","sources":["../../src/services/reconnect-snapshot.service.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAgBH;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,IAAI,CAchE;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAuB9D;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,IAAI,IAAI,CAS7C"}
1
+ {"version":3,"file":"reconnect-snapshot.service.d.ts","sourceRoot":"","sources":["../../src/services/reconnect-snapshot.service.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAuBH;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,IAAI,CAchE;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAgC9D;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,IAAI,IAAI,CAS7C"}
@@ -6,13 +6,19 @@
6
6
  * The snapshot is valid for 10 minutes. After that it is either deleted
7
7
  * by the auto-cleanup timer or ignored (too old) by isReconnectCandidate.
8
8
  */
9
- import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
9
+ import { existsSync, mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
10
10
  import { homedir } from "node:os";
11
11
  import { join } from "node:path";
12
12
  import { log } from "../logger.js";
13
13
  const DATA_DIR = join(homedir(), ".remote-copilot-mcp");
14
14
  const SNAPSHOT_PATH = join(DATA_DIR, "active-sessions.json");
15
15
  const SNAPSHOT_MAX_AGE_MS = 10 * 60 * 1000; // 10 minutes
16
+ /** Write via temp file + rename to prevent partial reads from concurrent access. */
17
+ function atomicWriteSnapshot(data) {
18
+ const tmp = `${SNAPSHOT_PATH}.tmp.${process.pid}`;
19
+ writeFileSync(tmp, data, "utf-8");
20
+ renameSync(tmp, SNAPSHOT_PATH);
21
+ }
16
22
  /**
17
23
  * Write the set of active thread IDs to the reconnect snapshot file.
18
24
  * Called just before the server process exits.
@@ -24,7 +30,7 @@ export function writeReconnectSnapshot(threadIds) {
24
30
  threadIds,
25
31
  timestamp: new Date().toISOString(),
26
32
  };
27
- writeFileSync(SNAPSHOT_PATH, JSON.stringify(snapshot, null, 2), "utf-8");
33
+ atomicWriteSnapshot(JSON.stringify(snapshot, null, 2));
28
34
  log.info(`[reconnect-snapshot] Wrote snapshot with ${threadIds.length} thread(s): ${threadIds.join(", ")}`);
29
35
  }
30
36
  catch (err) {
@@ -56,7 +62,18 @@ export function isReconnectCandidate(threadId) {
56
62
  }
57
63
  // Consume: remove this threadId so it can't match again
58
64
  snapshot.threadIds = snapshot.threadIds.filter(id => id !== threadId);
59
- writeFileSync(SNAPSHOT_PATH, JSON.stringify(snapshot, null, 2), "utf-8");
65
+ try {
66
+ if (snapshot.threadIds.length === 0) {
67
+ unlinkSync(SNAPSHOT_PATH);
68
+ }
69
+ else {
70
+ atomicWriteSnapshot(JSON.stringify(snapshot, null, 2));
71
+ }
72
+ }
73
+ catch (writeErr) {
74
+ log.warn(`[reconnect-snapshot] Matched thread ${threadId} but failed to persist consume: ${writeErr}`);
75
+ // Still return true — the match was valid, and the 10-min TTL bounds the risk
76
+ }
60
77
  log.info(`[reconnect-snapshot] Consumed reconnect slot for thread ${threadId}.`);
61
78
  return true;
62
79
  }
@@ -1 +1 @@
1
- {"version":3,"file":"reconnect-snapshot.service.js","sourceRoot":"","sources":["../../src/services/reconnect-snapshot.service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"reconnect-snapshot.service.js","sourceRoot":"","sources":["../../src/services/reconnect-snapshot.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;AAyBD,qBAAa,sBAAsB;IAE/B,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IACjC,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAHN,gBAAgB,EAAE,iBAAiB,EACnC,iBAAiB,EAAE,kBAAkB,EACrC,eAAe,EAAE,8BAA8B,EAC/C,MAAM,EAAE,qBAAqB;IAGhD,cAAc,CAAC,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,mBAAmB,GAAG,YAAY;IAmBtE,cAAc,CAAC,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,mBAAwB,GAAG,YAAY;IAe/F,WAAW,CAAC,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,gBAAqB,GAAG,YAAY;IAezF,UAAU,CAAC,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,GAAG,YAAY;IAkBxD,aAAa,CAAC,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,GAAG,YAAY;IAe3D,UAAU,CAAC,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,eAAe,GAAG,YAAY;IA6B9D,cAAc,CAAC,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI;IAKlE,OAAO,CAAC,aAAa;IAQrB,OAAO,CAAC,gBAAgB;IAkBxB,OAAO,CAAC,iBAAiB;IAgBzB,OAAO,CAAC,gBAAgB;IAIxB,OAAO,CAAC,gBAAgB;CAMzB"}
1
+ {"version":3,"file":"thread-lifecycle.service.d.ts","sourceRoot":"","sources":["../../src/services/thread-lifecycle.service.ts"],"names":[],"mappings":"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"}