sensorium-mcp 2.17.28 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Install-Sensorium.ps1 +327 -0
- package/README.md +14 -0
- package/dist/config.d.ts +16 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +39 -2
- package/dist/config.js.map +1 -1
- package/dist/daily-session.d.ts +2 -1
- package/dist/daily-session.d.ts.map +1 -1
- package/dist/daily-session.js +23 -26
- package/dist/daily-session.js.map +1 -1
- package/dist/dashboard/routes/settings.d.ts +4 -0
- package/dist/dashboard/routes/settings.d.ts.map +1 -1
- package/dist/dashboard/routes/settings.js +57 -1
- package/dist/dashboard/routes/settings.js.map +1 -1
- package/dist/dashboard/routes/threads.d.ts +1 -0
- package/dist/dashboard/routes/threads.d.ts.map +1 -1
- package/dist/dashboard/routes/threads.js +23 -25
- package/dist/dashboard/routes/threads.js.map +1 -1
- package/dist/dashboard/routes.d.ts.map +1 -1
- package/dist/dashboard/routes.js +7 -2
- package/dist/dashboard/routes.js.map +1 -1
- package/dist/dashboard/spa.html +11 -11
- package/dist/data/interfaces.d.ts +36 -0
- package/dist/data/interfaces.d.ts.map +1 -0
- package/dist/data/interfaces.js +2 -0
- package/dist/data/interfaces.js.map +1 -0
- package/dist/data/memory/bootstrap.d.ts +36 -16
- package/dist/data/memory/bootstrap.d.ts.map +1 -1
- package/dist/data/memory/bootstrap.js +71 -217
- package/dist/data/memory/bootstrap.js.map +1 -1
- package/dist/data/memory/consolidation.d.ts +35 -34
- package/dist/data/memory/consolidation.d.ts.map +1 -1
- package/dist/data/memory/consolidation.js +43 -554
- package/dist/data/memory/consolidation.js.map +1 -1
- package/dist/data/memory/migration-runner.d.ts +5 -0
- package/dist/data/memory/migration-runner.d.ts.map +1 -0
- package/dist/data/memory/migration-runner.js +403 -0
- package/dist/data/memory/migration-runner.js.map +1 -0
- package/dist/data/memory/reflection.js +1 -1
- package/dist/data/memory/schema-ddl.d.ts +4 -0
- package/dist/data/memory/schema-ddl.d.ts.map +1 -0
- package/dist/data/memory/schema-ddl.js +194 -0
- package/dist/data/memory/schema-ddl.js.map +1 -0
- package/dist/data/memory/schema-guard.d.ts +3 -0
- package/dist/data/memory/schema-guard.d.ts.map +1 -0
- package/dist/data/memory/schema-guard.js +184 -0
- package/dist/data/memory/schema-guard.js.map +1 -0
- package/dist/data/memory/schema.d.ts +2 -5
- package/dist/data/memory/schema.d.ts.map +1 -1
- package/dist/data/memory/schema.js +6 -834
- package/dist/data/memory/schema.js.map +1 -1
- package/dist/data/memory/synthesis.js +2 -2
- package/dist/data/memory/synthesis.js.map +1 -1
- package/dist/data/memory/thread-registry.d.ts +18 -4
- package/dist/data/memory/thread-registry.d.ts.map +1 -1
- package/dist/data/memory/thread-registry.js +25 -0
- package/dist/data/memory/thread-registry.js.map +1 -1
- package/dist/data/sent-message.repository.d.ts +12 -0
- package/dist/data/sent-message.repository.d.ts.map +1 -0
- package/dist/data/sent-message.repository.js +31 -0
- package/dist/data/sent-message.repository.js.map +1 -0
- package/dist/http-server.d.ts.map +1 -1
- package/dist/http-server.js +23 -2
- package/dist/http-server.js.map +1 -1
- package/dist/index.js +27 -48
- package/dist/index.js.map +1 -1
- package/dist/logger.d.ts +7 -2
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +89 -12
- package/dist/logger.js.map +1 -1
- package/dist/scheduler.d.ts +8 -0
- package/dist/scheduler.d.ts.map +1 -1
- package/dist/scheduler.js +15 -0
- package/dist/scheduler.js.map +1 -1
- package/dist/server/factory.d.ts +2 -1
- package/dist/server/factory.d.ts.map +1 -1
- package/dist/server/factory.js +11 -4
- package/dist/server/factory.js.map +1 -1
- package/dist/services/agent-spawn.service.d.ts +39 -0
- package/dist/services/agent-spawn.service.d.ts.map +1 -0
- package/dist/services/agent-spawn.service.js +348 -0
- package/dist/services/agent-spawn.service.js.map +1 -0
- package/dist/services/background-runner.d.ts +26 -0
- package/dist/services/background-runner.d.ts.map +1 -0
- package/dist/services/background-runner.js +71 -0
- package/dist/services/background-runner.js.map +1 -0
- package/dist/services/consolidation.service.d.ts +16 -0
- package/dist/services/consolidation.service.d.ts.map +1 -0
- package/dist/services/consolidation.service.js +508 -0
- package/dist/services/consolidation.service.js.map +1 -0
- package/dist/services/dispatcher/broker.d.ts +2 -0
- package/dist/services/dispatcher/broker.d.ts.map +1 -1
- package/dist/services/dispatcher/broker.js +5 -10
- package/dist/services/dispatcher/broker.js.map +1 -1
- package/dist/services/dispatcher/index.d.ts +1 -1
- package/dist/services/dispatcher/index.d.ts.map +1 -1
- package/dist/services/dispatcher/index.js +1 -1
- package/dist/services/dispatcher/index.js.map +1 -1
- package/dist/services/dispatcher/lock.d.ts.map +1 -1
- package/dist/services/dispatcher/lock.js +7 -11
- package/dist/services/dispatcher/lock.js.map +1 -1
- package/dist/services/maintenance-signal.d.ts +18 -0
- package/dist/services/maintenance-signal.d.ts.map +1 -0
- package/dist/services/maintenance-signal.js +48 -0
- package/dist/services/maintenance-signal.js.map +1 -0
- package/dist/services/memory-briefing.service.d.ts +4 -0
- package/dist/services/memory-briefing.service.d.ts.map +1 -0
- package/dist/services/memory-briefing.service.js +143 -0
- package/dist/services/memory-briefing.service.js.map +1 -0
- package/dist/services/process.service.d.ts +31 -0
- package/dist/services/process.service.d.ts.map +1 -0
- package/dist/services/process.service.js +100 -0
- package/dist/services/process.service.js.map +1 -0
- package/dist/services/thread-health.service.d.ts +18 -0
- package/dist/services/thread-health.service.d.ts.map +1 -0
- package/dist/services/thread-health.service.js +118 -0
- package/dist/services/thread-health.service.js.map +1 -0
- package/dist/services/thread-lifecycle.service.d.ts +52 -0
- package/dist/services/thread-lifecycle.service.d.ts.map +1 -0
- package/dist/services/thread-lifecycle.service.js +174 -0
- package/dist/services/thread-lifecycle.service.js.map +1 -0
- package/dist/services/topic.service.d.ts +25 -0
- package/dist/services/topic.service.d.ts.map +1 -0
- package/dist/services/topic.service.js +65 -0
- package/dist/services/topic.service.js.map +1 -0
- package/dist/services/worker-cleanup.service.d.ts +8 -0
- package/dist/services/worker-cleanup.service.d.ts.map +1 -0
- package/dist/services/worker-cleanup.service.js +82 -0
- package/dist/services/worker-cleanup.service.js.map +1 -0
- package/dist/sessions.d.ts +14 -0
- package/dist/sessions.d.ts.map +1 -1
- package/dist/sessions.js +55 -0
- package/dist/sessions.js.map +1 -1
- package/dist/telegram.d.ts +13 -6
- package/dist/telegram.d.ts.map +1 -1
- package/dist/telegram.js +43 -14
- package/dist/telegram.js.map +1 -1
- package/dist/tools/delegate-tool.d.ts +4 -0
- package/dist/tools/delegate-tool.d.ts.map +1 -1
- package/dist/tools/delegate-tool.js +48 -109
- package/dist/tools/delegate-tool.js.map +1 -1
- package/dist/tools/memory-tools.d.ts.map +1 -1
- package/dist/tools/memory-tools.js +1 -1
- package/dist/tools/memory-tools.js.map +1 -1
- package/dist/tools/shared-agent-utils.d.ts +9 -1
- package/dist/tools/shared-agent-utils.d.ts.map +1 -1
- package/dist/tools/shared-agent-utils.js +21 -38
- package/dist/tools/shared-agent-utils.js.map +1 -1
- package/dist/tools/start-session-tool.d.ts +2 -0
- package/dist/tools/start-session-tool.d.ts.map +1 -1
- package/dist/tools/start-session-tool.js +66 -106
- package/dist/tools/start-session-tool.js.map +1 -1
- package/dist/tools/thread-lifecycle.d.ts +5 -127
- package/dist/tools/thread-lifecycle.d.ts.map +1 -1
- package/dist/tools/thread-lifecycle.js +5 -1167
- package/dist/tools/thread-lifecycle.js.map +1 -1
- package/dist/tools/utility-tools.js +5 -2
- package/dist/tools/utility-tools.js.map +1 -1
- package/dist/tools/wait/drive-handler.d.ts +0 -1
- package/dist/tools/wait/drive-handler.d.ts.map +1 -1
- package/dist/tools/wait/drive-handler.js +5 -22
- package/dist/tools/wait/drive-handler.js.map +1 -1
- package/dist/tools/wait/message-delivery.js +1 -1
- package/dist/tools/wait/message-delivery.js.map +1 -1
- package/dist/tools/wait/message-processing.d.ts.map +1 -1
- package/dist/tools/wait/message-processing.js +9 -8
- package/dist/tools/wait/message-processing.js.map +1 -1
- package/dist/tools/wait/poll-loop.d.ts +2 -0
- package/dist/tools/wait/poll-loop.d.ts.map +1 -1
- package/dist/tools/wait/poll-loop.js +27 -29
- package/dist/tools/wait/poll-loop.js.map +1 -1
- package/dist/tools/wait/task-handler.d.ts +0 -3
- package/dist/tools/wait/task-handler.d.ts.map +1 -1
- package/dist/tools/wait/task-handler.js +3 -2
- package/dist/tools/wait/task-handler.js.map +1 -1
- package/dist/types.d.ts +0 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +4 -8
- package/supervisor/config.go +182 -69
- package/supervisor/config_test.go +78 -0
- package/supervisor/go.mod +12 -0
- package/supervisor/go.sum +20 -0
- package/supervisor/health.go +56 -6
- package/supervisor/health_test.go +29 -0
- package/supervisor/keeper.go +15 -10
- package/supervisor/log.go +109 -28
- package/supervisor/log_test.go +86 -6
- package/supervisor/main.go +150 -19
- package/supervisor/main_test.go +130 -0
- package/supervisor/process.go +47 -4
- package/supervisor/process_test.go +14 -0
- package/supervisor/secrets.go +95 -0
- package/supervisor/secrets_securevault_test.go +98 -0
- package/supervisor/secrets_test.go +119 -0
- package/supervisor/self_update.go +282 -0
- package/supervisor/self_update_test.go +177 -0
- package/supervisor/service_restart_stub.go +9 -0
- package/supervisor/service_restart_windows.go +63 -0
- package/supervisor/service_stub.go +15 -0
- package/supervisor/service_windows.go +216 -0
- package/supervisor/update_state.go +264 -0
- package/supervisor/update_state_test.go +306 -0
- package/supervisor/updater.go +311 -10
- package/supervisor/updater_test.go +64 -0
- package/scripts/install-supervisor.ps1 +0 -67
- package/scripts/install-supervisor.sh +0 -43
- package/scripts/start-supervisor.ps1 +0 -46
- package/scripts/start-supervisor.sh +0 -20
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
* Barrel re-export for the dispatcher subsystem.
|
|
3
3
|
*/
|
|
4
4
|
export type { StoredReaction, StoredMessage } from "./broker.js";
|
|
5
|
-
export { readPendingReaction, readThreadMessages, peekThreadMessages, appendToThread, setBrokerDb, resolveThreadForTopic } from "./broker.js";
|
|
5
|
+
export { readPendingReaction, readThreadMessages, peekThreadMessages, appendToThread, setBrokerDb, setBrokerSentMessageRepository, resolveThreadForTopic, } from "./broker.js";
|
|
6
6
|
export { startDispatcher } from "./poller.js";
|
|
7
7
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/dispatcher/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/dispatcher/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,kBAAkB,EAClB,cAAc,EACd,WAAW,EACX,8BAA8B,EAC9B,qBAAqB,GACtB,MAAM,aAAa,CAAC;AAGrB,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Barrel re-export for the dispatcher subsystem.
|
|
3
3
|
*/
|
|
4
|
-
export { readPendingReaction, readThreadMessages, peekThreadMessages, appendToThread, setBrokerDb, resolveThreadForTopic } from "./broker.js";
|
|
4
|
+
export { readPendingReaction, readThreadMessages, peekThreadMessages, appendToThread, setBrokerDb, setBrokerSentMessageRepository, resolveThreadForTopic, } from "./broker.js";
|
|
5
5
|
// Poller — startup entry point
|
|
6
6
|
export { startDispatcher } from "./poller.js";
|
|
7
7
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/services/dispatcher/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/services/dispatcher/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,kBAAkB,EAClB,cAAc,EACd,WAAW,EACX,8BAA8B,EAC9B,qBAAqB,GACtB,MAAM,aAAa,CAAC;AAErB,+BAA+B;AAC/B,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lock.d.ts","sourceRoot":"","sources":["../../../src/services/dispatcher/lock.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;
|
|
1
|
+
{"version":3,"file":"lock.d.ts","sourceRoot":"","sources":["../../../src/services/dispatcher/lock.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAgCH,0CAA0C;AAC1C,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAO/C;AAMD,wBAAgB,QAAQ,IAAI;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAW7D;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,IAAI,OAAO,CAiBrC;AAED,wBAAgB,UAAU,IAAI,IAAI,CAMjC;AAMD,wBAAgB,cAAc,IAAI,OAAO,CA0BxC"}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* a file-system–based lock (with stale-lock detection via PID check) so
|
|
6
6
|
* multiple instances can coordinate without conflicts.
|
|
7
7
|
*/
|
|
8
|
-
import { existsSync, readFileSync, unlinkSync, writeFileSync, } from "node:fs";
|
|
8
|
+
import { existsSync, readFileSync, renameSync, unlinkSync, writeFileSync, } from "node:fs";
|
|
9
9
|
import { homedir } from "node:os";
|
|
10
10
|
import { join } from "node:path";
|
|
11
11
|
// ---------------------------------------------------------------------------
|
|
@@ -60,21 +60,17 @@ export function readLock() {
|
|
|
60
60
|
*/
|
|
61
61
|
export function refreshLock() {
|
|
62
62
|
const current = readLock();
|
|
63
|
-
if (current
|
|
64
|
-
return false; //
|
|
63
|
+
if (!current || current.pid !== process.pid) {
|
|
64
|
+
return false; // Lock missing or owned by someone else.
|
|
65
65
|
}
|
|
66
|
-
// Use exclusive create (wx) to prevent overwriting another process's lock.
|
|
67
|
-
// Delete our own lock first, then atomically re-create it.
|
|
68
66
|
try {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
try {
|
|
73
|
-
writeFileSync(LOCK_FILE, JSON.stringify({ pid: process.pid, ts: Date.now() }), { encoding: "utf8", flag: "wx" });
|
|
67
|
+
const tmp = LOCK_FILE + ".tmp." + process.pid;
|
|
68
|
+
writeFileSync(tmp, JSON.stringify({ pid: process.pid, ts: Date.now() }), "utf8");
|
|
69
|
+
renameSync(tmp, LOCK_FILE);
|
|
74
70
|
return true;
|
|
75
71
|
}
|
|
76
72
|
catch {
|
|
77
|
-
return false;
|
|
73
|
+
return false;
|
|
78
74
|
}
|
|
79
75
|
}
|
|
80
76
|
export function removeLock() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lock.js","sourceRoot":"","sources":["../../../src/services/dispatcher/lock.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACH,UAAU,EACV,YAAY,EACZ,UAAU,EACV,aAAa,GAChB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,8EAA8E;AAC9E,oBAAoB;AACpB,8EAA8E;AAE9E,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,qBAAqB,CAAC,CAAC;AACxD,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;AAEhD;;;;;;GAMG;AACH,MAAM,aAAa,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,aAAa;AAE9C,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E,0CAA0C;AAC1C,MAAM,UAAU,UAAU,CAAC,GAAW;IAClC,IAAI,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,6CAA6C;QACnE,OAAO,IAAI,CAAC;IAChB,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,KAAK,CAAC;IACjB,CAAC;AACL,CAAC;AAED,8EAA8E;AAC9E,6BAA6B;AAC7B,8EAA8E;AAE9E,MAAM,UAAU,QAAQ;IACpB,IAAI,CAAC;QACD,MAAM,GAAG,GAAG,YAAY,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QAC5C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAgC,CAAC;QAC9D,IAAI,OAAO,MAAM,CAAC,GAAG,KAAK,QAAQ,IAAI,OAAO,MAAM,CAAC,EAAE,KAAK,QAAQ,EAAE,CAAC;YAClE,OAAO,MAAM,CAAC;QAClB,CAAC;QACD,OAAO,IAAI,CAAC;IAChB,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,IAAI,CAAC;IAChB,CAAC;AACL,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,WAAW;IACvB,MAAM,OAAO,GAAG,QAAQ,EAAE,CAAC;IAC3B,IAAI,OAAO,IAAI,OAAO,CAAC,GAAG,KAAK,OAAO,CAAC,GAAG,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"lock.js","sourceRoot":"","sources":["../../../src/services/dispatcher/lock.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Maintenance signal — notifies active poll loops immediately when the
|
|
3
|
+
* maintenance flag file is written, so they can return the maintenance
|
|
4
|
+
* response before the server process is killed.
|
|
5
|
+
*
|
|
6
|
+
* Uses fs.watch() on the data directory to detect flag creation without
|
|
7
|
+
* requiring callers to poll. The exported emitMaintenanceSignal() is
|
|
8
|
+
* available for manual/test triggering.
|
|
9
|
+
*/
|
|
10
|
+
/** Manually fire the maintenance signal (e.g. from tests or from code that
|
|
11
|
+
* writes the flag directly without going through the file system watcher). */
|
|
12
|
+
export declare function emitMaintenanceSignal(): void;
|
|
13
|
+
/**
|
|
14
|
+
* Subscribe to the maintenance signal.
|
|
15
|
+
* @returns An unsubscribe function — call it to remove the listener.
|
|
16
|
+
*/
|
|
17
|
+
export declare function onMaintenanceSignal(cb: () => void): () => void;
|
|
18
|
+
//# sourceMappingURL=maintenance-signal.d.ts.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Maintenance signal — notifies active poll loops immediately when the
|
|
3
|
+
* maintenance flag file is written, so they can return the maintenance
|
|
4
|
+
* response before the server process is killed.
|
|
5
|
+
*
|
|
6
|
+
* Uses fs.watch() on the data directory to detect flag creation without
|
|
7
|
+
* requiring callers to poll. The exported emitMaintenanceSignal() is
|
|
8
|
+
* available for manual/test triggering.
|
|
9
|
+
*/
|
|
10
|
+
import { EventEmitter } from "node:events";
|
|
11
|
+
import { watch } from "node:fs";
|
|
12
|
+
import { homedir } from "node:os";
|
|
13
|
+
import { join } from "node:path";
|
|
14
|
+
import { log } from "../logger.js";
|
|
15
|
+
const DATA_DIR = join(homedir(), ".remote-copilot-mcp");
|
|
16
|
+
const FLAG_NAME = "maintenance.flag";
|
|
17
|
+
const emitter = new EventEmitter();
|
|
18
|
+
// Many poll loops (one per active thread) may subscribe simultaneously.
|
|
19
|
+
emitter.setMaxListeners(500);
|
|
20
|
+
// Watch the data directory for maintenance.flag creation / modification.
|
|
21
|
+
// On Windows, fs.watch fires "rename" when files are created or deleted;
|
|
22
|
+
// on Linux/macOS it fires "rename" on creation and "change" on modification.
|
|
23
|
+
try {
|
|
24
|
+
watch(DATA_DIR, (_eventType, filename) => {
|
|
25
|
+
if (filename === FLAG_NAME) {
|
|
26
|
+
emitter.emit("maintenance");
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
catch (err) {
|
|
31
|
+
// DATA_DIR might not exist yet at module load time. The signal simply
|
|
32
|
+
// won't fire from the watcher — emitMaintenanceSignal() still works.
|
|
33
|
+
log.warn(`[maintenance-signal] Could not watch ${DATA_DIR}: ${err}`);
|
|
34
|
+
}
|
|
35
|
+
/** Manually fire the maintenance signal (e.g. from tests or from code that
|
|
36
|
+
* writes the flag directly without going through the file system watcher). */
|
|
37
|
+
export function emitMaintenanceSignal() {
|
|
38
|
+
emitter.emit("maintenance");
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Subscribe to the maintenance signal.
|
|
42
|
+
* @returns An unsubscribe function — call it to remove the listener.
|
|
43
|
+
*/
|
|
44
|
+
export function onMaintenanceSignal(cb) {
|
|
45
|
+
emitter.on("maintenance", cb);
|
|
46
|
+
return () => emitter.off("maintenance", cb);
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=maintenance-signal.js.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { Database } from "../data/memory/schema.js";
|
|
2
|
+
export declare function assembleBootstrap(db: Database, threadId: number, memorySourceThreadId?: number): string;
|
|
3
|
+
export declare function assembleCompactRefresh(db: Database, threadId: number): string;
|
|
4
|
+
//# sourceMappingURL=memory-briefing.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-briefing.service.d.ts","sourceRoot":"","sources":["../../src/services/memory-briefing.service.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAEzD,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,oBAAoB,CAAC,EAAE,MAAM,GAAG,MAAM,CA+IvG;AAED,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAS7E"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { getBootstrapContext, getCompactRefreshNotes, MAX_BOOTSTRAP_CONVERSATION_CHARS, MAX_MESSAGE_CONTENT_CHARS, } from "../data/memory/bootstrap.js";
|
|
2
|
+
export function assembleBootstrap(db, threadId, memorySourceThreadId) {
|
|
3
|
+
const context = getBootstrapContext(db, threadId, memorySourceThreadId);
|
|
4
|
+
const lines = [];
|
|
5
|
+
if (context.identityPrompt) {
|
|
6
|
+
lines.push(context.identityPrompt);
|
|
7
|
+
lines.push("");
|
|
8
|
+
}
|
|
9
|
+
lines.push("# Memory Briefing");
|
|
10
|
+
if (memorySourceThreadId !== undefined) {
|
|
11
|
+
lines.push(`> **Ghost thread** — memory sourced from parent thread ${memorySourceThreadId}. Runtime memory ops use thread ${threadId}.`);
|
|
12
|
+
if (context.recentEpisodes.length === 0
|
|
13
|
+
&& context.pinnedNotes.length === 0
|
|
14
|
+
&& context.keyKnowledge.length === 0
|
|
15
|
+
&& context.procedures.length === 0) {
|
|
16
|
+
lines.push(`> ⚠️ No memory found for source thread ${memorySourceThreadId}. The ghost thread will start without parent context.`);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
lines.push("");
|
|
20
|
+
if (context.recentEpisodes.length > 0) {
|
|
21
|
+
lines.push("## Recent Conversation");
|
|
22
|
+
const conversationLines = [];
|
|
23
|
+
let totalChars = 0;
|
|
24
|
+
for (const episode of context.recentEpisodes) {
|
|
25
|
+
const raw = typeof episode.content === "object" && episode.content !== null
|
|
26
|
+
? (episode.content.text ?? episode.content.caption ?? null)
|
|
27
|
+
: null;
|
|
28
|
+
const fullText = typeof raw === "string" ? raw : JSON.stringify(episode.content);
|
|
29
|
+
const textContent = fullText.length > MAX_MESSAGE_CONTENT_CHARS
|
|
30
|
+
? fullText.slice(0, MAX_MESSAGE_CONTENT_CHARS) + "…"
|
|
31
|
+
: fullText;
|
|
32
|
+
let line;
|
|
33
|
+
if (episode.type === "operator_message") {
|
|
34
|
+
line = `**Operator** (${episode.timestamp}): ${textContent}`;
|
|
35
|
+
}
|
|
36
|
+
else if (episode.type === "agent_action") {
|
|
37
|
+
line = `**You** (${episode.timestamp}): ${textContent}`;
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
line = `[${episode.type}] ${textContent} (${episode.timestamp})`;
|
|
41
|
+
}
|
|
42
|
+
totalChars += line.length;
|
|
43
|
+
conversationLines.push(line);
|
|
44
|
+
}
|
|
45
|
+
while (totalChars > MAX_BOOTSTRAP_CONVERSATION_CHARS && conversationLines.length > 1) {
|
|
46
|
+
const removed = conversationLines.shift();
|
|
47
|
+
totalChars -= removed.length;
|
|
48
|
+
}
|
|
49
|
+
lines.push(...conversationLines);
|
|
50
|
+
lines.push("");
|
|
51
|
+
}
|
|
52
|
+
if (context.guardrails.length > 0) {
|
|
53
|
+
lines.push("## Active Decisions (always enforced)");
|
|
54
|
+
for (const guardrail of context.guardrails) {
|
|
55
|
+
const line = guardrail.content.length > 120 ? guardrail.content.slice(0, 117) + "..." : guardrail.content;
|
|
56
|
+
lines.push(`- ${line}`);
|
|
57
|
+
}
|
|
58
|
+
lines.push("");
|
|
59
|
+
}
|
|
60
|
+
if (context.narratives) {
|
|
61
|
+
lines.push("## Temporal Context");
|
|
62
|
+
if (context.narratives.half_year) {
|
|
63
|
+
lines.push("### This Half-Year");
|
|
64
|
+
lines.push(context.narratives.half_year);
|
|
65
|
+
lines.push("");
|
|
66
|
+
}
|
|
67
|
+
if (context.narratives.quarter) {
|
|
68
|
+
lines.push("### This Quarter");
|
|
69
|
+
lines.push(context.narratives.quarter);
|
|
70
|
+
lines.push("");
|
|
71
|
+
}
|
|
72
|
+
if (context.narratives.month) {
|
|
73
|
+
lines.push("### This Month");
|
|
74
|
+
lines.push(context.narratives.month);
|
|
75
|
+
lines.push("");
|
|
76
|
+
}
|
|
77
|
+
if (context.narratives.week) {
|
|
78
|
+
lines.push("### This Week");
|
|
79
|
+
lines.push(context.narratives.week);
|
|
80
|
+
lines.push("");
|
|
81
|
+
}
|
|
82
|
+
if (context.narratives.day) {
|
|
83
|
+
lines.push("### Today");
|
|
84
|
+
lines.push(context.narratives.day);
|
|
85
|
+
lines.push("");
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (context.pinnedNotes.length > 0) {
|
|
89
|
+
lines.push("## Pinned (Long-Term Context)");
|
|
90
|
+
for (const note of context.pinnedNotes) {
|
|
91
|
+
lines.push(`- **[${note.type}]** ${note.content} _(conf: ${note.confidence.toFixed(2)})_`);
|
|
92
|
+
}
|
|
93
|
+
lines.push("");
|
|
94
|
+
}
|
|
95
|
+
if (context.keyKnowledge.length > 0) {
|
|
96
|
+
lines.push("## Key Knowledge");
|
|
97
|
+
for (const note of context.keyKnowledge) {
|
|
98
|
+
lines.push(`- **[${note.type}]** ${note.content} (conf: ${note.confidence.toFixed(2)}, accessed: ${note.accessCount}x)`);
|
|
99
|
+
}
|
|
100
|
+
lines.push("");
|
|
101
|
+
}
|
|
102
|
+
if (context.procedures.length > 0) {
|
|
103
|
+
lines.push("## Active Procedures");
|
|
104
|
+
for (const procedure of context.procedures) {
|
|
105
|
+
lines.push(`- **${procedure.name}** (${procedure.type}) — success: ${(procedure.successRate * 100).toFixed(0)}%, used ${procedure.timesExecuted}x`);
|
|
106
|
+
if (procedure.steps.length > 0) {
|
|
107
|
+
lines.push(` Steps: ${procedure.steps.join(" → ")}`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
lines.push("");
|
|
111
|
+
}
|
|
112
|
+
if (context.baseline && context.baseline.sampleCount > 0) {
|
|
113
|
+
lines.push("## Operator Voice Profile");
|
|
114
|
+
const parts = [`${context.baseline.sampleCount} samples`];
|
|
115
|
+
if (context.baseline.avgValence !== null)
|
|
116
|
+
parts.push(`valence ${context.baseline.avgValence.toFixed(2)}`);
|
|
117
|
+
if (context.baseline.avgArousal !== null)
|
|
118
|
+
parts.push(`arousal ${context.baseline.avgArousal.toFixed(2)}`);
|
|
119
|
+
if (context.baseline.avgSpeechRate !== null)
|
|
120
|
+
parts.push(`speech rate ${context.baseline.avgSpeechRate.toFixed(1)}`);
|
|
121
|
+
lines.push(parts.join(" · "));
|
|
122
|
+
lines.push("");
|
|
123
|
+
}
|
|
124
|
+
if (context.reflections.length > 0) {
|
|
125
|
+
lines.push("## Recent Reflections");
|
|
126
|
+
for (const reflection of context.reflections) {
|
|
127
|
+
lines.push(`- ${reflection.content.slice(0, 300)} _(conf: ${reflection.confidence.toFixed(2)}, ${reflection.createdAt.slice(0, 10)})_`);
|
|
128
|
+
}
|
|
129
|
+
lines.push("");
|
|
130
|
+
}
|
|
131
|
+
return lines.join("\n");
|
|
132
|
+
}
|
|
133
|
+
export function assembleCompactRefresh(db, threadId) {
|
|
134
|
+
const topNotes = getCompactRefreshNotes(db, threadId);
|
|
135
|
+
if (topNotes.length === 0)
|
|
136
|
+
return "";
|
|
137
|
+
const lines = ["## Memory Refresh"];
|
|
138
|
+
for (const note of topNotes) {
|
|
139
|
+
lines.push(`- **[${note.type}]** ${note.content}`);
|
|
140
|
+
}
|
|
141
|
+
return lines.join("\n");
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=memory-briefing.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-briefing.service.js","sourceRoot":"","sources":["../../src/services/memory-briefing.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export declare const PENDING_TASKS_DIR: string;
|
|
2
|
+
export declare const PROCESS_BASE_DIR: string;
|
|
3
|
+
export declare const PROCESS_LOGS_DIR: string;
|
|
4
|
+
export declare const PROCESS_PIDS_DIR: string;
|
|
5
|
+
export interface SpawnedThread {
|
|
6
|
+
pid: number;
|
|
7
|
+
threadId: number;
|
|
8
|
+
name: string;
|
|
9
|
+
startedAt: number;
|
|
10
|
+
createdAt: number;
|
|
11
|
+
logFile: string;
|
|
12
|
+
memorySourceThreadId?: number;
|
|
13
|
+
memoryTargetThreadId?: number;
|
|
14
|
+
threadType?: "worker" | "branch";
|
|
15
|
+
}
|
|
16
|
+
interface PidFileEntry {
|
|
17
|
+
threadId: number;
|
|
18
|
+
pid: number;
|
|
19
|
+
filePath: string;
|
|
20
|
+
name?: string;
|
|
21
|
+
}
|
|
22
|
+
export declare const spawnedThreads: SpawnedThread[];
|
|
23
|
+
export declare function isProcessAlive(pid: number): boolean;
|
|
24
|
+
export declare function readPidFiles(): PidFileEntry[];
|
|
25
|
+
export declare function findAliveThread(threadId: number): SpawnedThread | undefined;
|
|
26
|
+
export declare const isThreadRunning: (threadId: number) => boolean;
|
|
27
|
+
export declare function ensureDirs(): void;
|
|
28
|
+
export declare function cleanupStalePidFiles(): void;
|
|
29
|
+
export declare const pidDirExists: () => boolean;
|
|
30
|
+
export {};
|
|
31
|
+
//# sourceMappingURL=process.service.d.ts.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { execSync } from "node:child_process";
|
|
2
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, unlinkSync } from "node:fs";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { log } from "../logger.js";
|
|
6
|
+
const BASE_DIR = join(homedir(), ".remote-copilot-mcp");
|
|
7
|
+
const LOGS_DIR = join(BASE_DIR, "logs");
|
|
8
|
+
const PIDS_DIR = join(BASE_DIR, "pids");
|
|
9
|
+
export const PENDING_TASKS_DIR = join(BASE_DIR, "pending-tasks");
|
|
10
|
+
export const PROCESS_BASE_DIR = BASE_DIR;
|
|
11
|
+
export const PROCESS_LOGS_DIR = LOGS_DIR;
|
|
12
|
+
export const PROCESS_PIDS_DIR = PIDS_DIR;
|
|
13
|
+
export const spawnedThreads = [];
|
|
14
|
+
export function isProcessAlive(pid) {
|
|
15
|
+
try {
|
|
16
|
+
process.kill(pid, 0);
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
catch (err) {
|
|
20
|
+
return err.code === "EPERM";
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
export function readPidFiles() {
|
|
24
|
+
const entries = [];
|
|
25
|
+
try {
|
|
26
|
+
for (const file of readdirSync(PIDS_DIR)) {
|
|
27
|
+
if (!file.endsWith(".pid"))
|
|
28
|
+
continue;
|
|
29
|
+
try {
|
|
30
|
+
const threadId = Number(file.replace(".pid", ""));
|
|
31
|
+
const filePath = join(PIDS_DIR, file);
|
|
32
|
+
const raw = readFileSync(filePath, "utf-8").trim();
|
|
33
|
+
let pid;
|
|
34
|
+
let name;
|
|
35
|
+
try {
|
|
36
|
+
({ pid, name } = JSON.parse(raw));
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
pid = Number(raw);
|
|
40
|
+
}
|
|
41
|
+
if (Number.isFinite(threadId) && Number.isFinite(pid))
|
|
42
|
+
entries.push({ threadId, pid, filePath, name });
|
|
43
|
+
}
|
|
44
|
+
catch { }
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
catch { }
|
|
48
|
+
return entries;
|
|
49
|
+
}
|
|
50
|
+
export function findAliveThread(threadId) {
|
|
51
|
+
for (let i = spawnedThreads.length - 1; i >= 0; i--) {
|
|
52
|
+
const thread = spawnedThreads[i];
|
|
53
|
+
if (thread.threadId !== threadId)
|
|
54
|
+
continue;
|
|
55
|
+
if (isProcessAlive(thread.pid))
|
|
56
|
+
return thread;
|
|
57
|
+
log.warn(`[findAliveThread] Thread ${threadId} PID ${thread.pid} stale in spawnedThreads - removing`);
|
|
58
|
+
spawnedThreads.splice(i, 1);
|
|
59
|
+
}
|
|
60
|
+
const pidEntry = readPidFiles().find((entry) => entry.threadId === threadId && isProcessAlive(entry.pid));
|
|
61
|
+
if (!pidEntry)
|
|
62
|
+
return undefined;
|
|
63
|
+
if (process.platform === "win32") {
|
|
64
|
+
try {
|
|
65
|
+
const out = execSync(`tasklist /FI "PID eq ${pidEntry.pid}" /NH`, { encoding: "utf-8", timeout: 5000 });
|
|
66
|
+
if (!out.includes(String(pidEntry.pid))) {
|
|
67
|
+
try {
|
|
68
|
+
unlinkSync(pidEntry.filePath);
|
|
69
|
+
}
|
|
70
|
+
catch { }
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
catch { }
|
|
75
|
+
}
|
|
76
|
+
const restored = { pid: pidEntry.pid, threadId, name: pidEntry.name ?? `Thread ${threadId}`, startedAt: Date.now(), createdAt: Date.now(), logFile: "" };
|
|
77
|
+
spawnedThreads.push(restored);
|
|
78
|
+
log.info(`[findAliveThread] Restored thread ${threadId} PID=${pidEntry.pid} from PID file`);
|
|
79
|
+
return restored;
|
|
80
|
+
}
|
|
81
|
+
export const isThreadRunning = (threadId) => findAliveThread(threadId) !== undefined;
|
|
82
|
+
export function ensureDirs() {
|
|
83
|
+
mkdirSync(PENDING_TASKS_DIR, { recursive: true });
|
|
84
|
+
mkdirSync(LOGS_DIR, { recursive: true });
|
|
85
|
+
mkdirSync(PIDS_DIR, { recursive: true });
|
|
86
|
+
}
|
|
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))
|
|
94
|
+
try {
|
|
95
|
+
unlinkSync(filePath);
|
|
96
|
+
}
|
|
97
|
+
catch { }
|
|
98
|
+
}
|
|
99
|
+
export const pidDirExists = () => existsSync(PIDS_DIR);
|
|
100
|
+
//# sourceMappingURL=process.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"process.service.js","sourceRoot":"","sources":["../../src/services/process.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
type ThreadStatus = "running" | "dormant" | "dead" | "unknown";
|
|
2
|
+
interface CollectedThread {
|
|
3
|
+
threadId: number;
|
|
4
|
+
name: string;
|
|
5
|
+
pid: number | undefined;
|
|
6
|
+
alive: boolean;
|
|
7
|
+
hasActiveSession: boolean;
|
|
8
|
+
hasRecentWait: boolean;
|
|
9
|
+
sessionCount: number;
|
|
10
|
+
lastActivity: number | undefined;
|
|
11
|
+
spawnedStartedAt: number | undefined;
|
|
12
|
+
registryStatus: string | undefined;
|
|
13
|
+
keepAlive: boolean;
|
|
14
|
+
}
|
|
15
|
+
export declare function classifyThreadHealth(t: CollectedThread): ThreadStatus;
|
|
16
|
+
export declare function getThreadsHealth(): string;
|
|
17
|
+
export {};
|
|
18
|
+
//# sourceMappingURL=thread-health.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"thread-health.service.d.ts","sourceRoot":"","sources":["../../src/services/thread-health.service.ts"],"names":[],"mappings":"AAKA,KAAK,YAAY,GAAG,SAAS,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAAC;AAE/D,UAAU,eAAe;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;IACxB,KAAK,EAAE,OAAO,CAAC;IACf,gBAAgB,EAAE,OAAO,CAAC;IAC1B,aAAa,EAAE,OAAO,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,gBAAgB,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,cAAc,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,SAAS,EAAE,OAAO,CAAC;CACpB;AAoED,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,eAAe,GAAG,YAAY,CAOrE;AAED,wBAAgB,gBAAgB,IAAI,MAAM,CAwBzC"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { getAllRegisteredTopics, getDashboardSessions, WAIT_LIVENESS_MS } from "../sessions.js";
|
|
2
|
+
import { getAllThreads } from "../data/memory/thread-registry.js";
|
|
3
|
+
import { initMemoryDb } from "../data/memory/schema.js";
|
|
4
|
+
import { isProcessAlive, readPidFiles, spawnedThreads } from "./process.service.js";
|
|
5
|
+
const formatRelativeTime = (ms) => ms < 0 ? "just now" : ms < 60_000 ? `${Math.floor(ms / 1000)}s ago` : ms < 3_600_000 ? `${Math.floor(ms / 60_000)}m ago` : ms < 86_400_000 ? `${Math.floor(ms / 3_600_000)}h ago` : `${Math.floor(ms / 86_400_000)}d ago`;
|
|
6
|
+
const formatUptime = (startedAt) => {
|
|
7
|
+
const seconds = Math.floor((Date.now() - startedAt) / 1000);
|
|
8
|
+
if (seconds < 60)
|
|
9
|
+
return `${seconds}s`;
|
|
10
|
+
const minutes = Math.floor(seconds / 60);
|
|
11
|
+
if (minutes < 60)
|
|
12
|
+
return `${minutes}m`;
|
|
13
|
+
const hours = Math.floor(minutes / 60);
|
|
14
|
+
return hours < 24 ? `${hours}h ${minutes % 60}m` : `${Math.floor(hours / 24)}d ${hours % 24}h`;
|
|
15
|
+
};
|
|
16
|
+
function collectThreadData() {
|
|
17
|
+
const topicsByChat = getAllRegisteredTopics();
|
|
18
|
+
const sessions = getDashboardSessions();
|
|
19
|
+
const pidFiles = readPidFiles();
|
|
20
|
+
const now = Date.now();
|
|
21
|
+
const registryByThread = new Map();
|
|
22
|
+
try {
|
|
23
|
+
for (const entry of getAllThreads(initMemoryDb()))
|
|
24
|
+
registryByThread.set(entry.threadId, entry);
|
|
25
|
+
}
|
|
26
|
+
catch { }
|
|
27
|
+
const spawnedByThread = new Map(spawnedThreads.map((s) => [s.threadId, s]));
|
|
28
|
+
const pidByThread = new Map(pidFiles.map((p) => [p.threadId, p.pid]));
|
|
29
|
+
const threadNames = new Map();
|
|
30
|
+
const allThreadIds = new Set();
|
|
31
|
+
for (const chatTopics of Object.values(topicsByChat)) {
|
|
32
|
+
for (const [name, threadId] of Object.entries(chatTopics)) {
|
|
33
|
+
threadNames.set(threadId, name);
|
|
34
|
+
allThreadIds.add(threadId);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
for (const session of sessions)
|
|
38
|
+
if (session.threadId != null)
|
|
39
|
+
allThreadIds.add(session.threadId);
|
|
40
|
+
for (const s of spawnedThreads)
|
|
41
|
+
allThreadIds.add(s.threadId);
|
|
42
|
+
for (const p of pidFiles)
|
|
43
|
+
allThreadIds.add(p.threadId);
|
|
44
|
+
for (const [id, entry] of registryByThread) {
|
|
45
|
+
allThreadIds.add(id);
|
|
46
|
+
if (!threadNames.has(id) && entry.name)
|
|
47
|
+
threadNames.set(id, entry.name);
|
|
48
|
+
}
|
|
49
|
+
const sessionsByThread = new Map();
|
|
50
|
+
for (const session of sessions) {
|
|
51
|
+
if (session.threadId == null)
|
|
52
|
+
continue;
|
|
53
|
+
const arr = sessionsByThread.get(session.threadId) ?? [];
|
|
54
|
+
arr.push(session);
|
|
55
|
+
sessionsByThread.set(session.threadId, arr);
|
|
56
|
+
}
|
|
57
|
+
return [...allThreadIds].map((threadId) => {
|
|
58
|
+
const spawnedEntry = spawnedByThread.get(threadId);
|
|
59
|
+
const pid = spawnedEntry?.pid ?? pidByThread.get(threadId);
|
|
60
|
+
const threadSessions = sessionsByThread.get(threadId) ?? [];
|
|
61
|
+
const activeSession = threadSessions.find((s) => s.status === "active");
|
|
62
|
+
const anySession = activeSession ?? threadSessions[0];
|
|
63
|
+
const regEntry = registryByThread.get(threadId);
|
|
64
|
+
return {
|
|
65
|
+
threadId,
|
|
66
|
+
name: threadNames.get(threadId) ?? regEntry?.name ?? "unnamed",
|
|
67
|
+
pid,
|
|
68
|
+
alive: pid !== undefined && isProcessAlive(pid),
|
|
69
|
+
hasActiveSession: !!activeSession,
|
|
70
|
+
hasRecentWait: anySession?.lastWaitCallAt != null && now - anySession.lastWaitCallAt < WAIT_LIVENESS_MS,
|
|
71
|
+
sessionCount: threadSessions.length,
|
|
72
|
+
lastActivity: anySession?.lastActivity ?? (regEntry?.lastActiveAt ? new Date(regEntry.lastActiveAt).getTime() : undefined),
|
|
73
|
+
spawnedStartedAt: spawnedEntry?.startedAt,
|
|
74
|
+
registryStatus: regEntry?.status,
|
|
75
|
+
keepAlive: regEntry?.keepAlive ?? false,
|
|
76
|
+
};
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
export function classifyThreadHealth(t) {
|
|
80
|
+
if ((t.alive && t.hasActiveSession && t.hasRecentWait) || (t.hasActiveSession && t.hasRecentWait))
|
|
81
|
+
return "running";
|
|
82
|
+
if (t.hasActiveSession || t.alive)
|
|
83
|
+
return "dormant";
|
|
84
|
+
if (t.pid !== undefined && !t.alive)
|
|
85
|
+
return "dead";
|
|
86
|
+
if (t.registryStatus === "archived" || t.registryStatus === "expired" || t.registryStatus === "exited")
|
|
87
|
+
return "dead";
|
|
88
|
+
if (t.registryStatus === "active" || t.keepAlive)
|
|
89
|
+
return "dormant";
|
|
90
|
+
return "unknown";
|
|
91
|
+
}
|
|
92
|
+
export function getThreadsHealth() {
|
|
93
|
+
const threads = collectThreadData();
|
|
94
|
+
if (threads.length === 0)
|
|
95
|
+
return "No threads found. No topics registered, no active sessions, no PID files.";
|
|
96
|
+
const now = Date.now();
|
|
97
|
+
const rows = threads.map((t) => ({
|
|
98
|
+
threadId: t.threadId,
|
|
99
|
+
name: t.name.replace(/\|/g, "\\|"),
|
|
100
|
+
status: classifyThreadHealth(t),
|
|
101
|
+
pid: t.pid !== undefined ? String(t.pid) : "-",
|
|
102
|
+
lastActivity: t.lastActivity ? formatRelativeTime(now - t.lastActivity) : "-",
|
|
103
|
+
session: t.hasActiveSession ? "active" : t.sessionCount > 0 ? "disconnected" : "-",
|
|
104
|
+
uptime: t.spawnedStartedAt && t.alive ? formatUptime(t.spawnedStartedAt) : "-",
|
|
105
|
+
}));
|
|
106
|
+
const statusOrder = { running: 0, dormant: 1, dead: 2, unknown: 3 };
|
|
107
|
+
rows.sort((a, b) => (statusOrder[a.status] ?? 9) - (statusOrder[b.status] ?? 9));
|
|
108
|
+
return [
|
|
109
|
+
"## Thread Health Report",
|
|
110
|
+
"",
|
|
111
|
+
"| Thread ID | Name | Status | PID | Last Activity | Session | Uptime |",
|
|
112
|
+
"|-----------|------|--------|-----|---------------|---------|--------|",
|
|
113
|
+
...rows.map((r) => `| ${r.threadId} | ${r.name} | ${r.status} | ${r.pid} | ${r.lastActivity} | ${r.session} | ${r.uptime} |`),
|
|
114
|
+
"",
|
|
115
|
+
`**Summary:** ${rows.length} threads -- ${rows.filter((r) => r.status === "running").length} running, ${rows.filter((r) => r.status === "dormant").length} dormant, ${rows.filter((r) => r.status === "dead").length} dead, ${rows.filter((r) => r.status === "unknown").length} unknown`,
|
|
116
|
+
].join("\n");
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=thread-health.service.js.map
|