sensorium-mcp 2.17.28 → 3.0.1

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 (207) hide show
  1. package/Install-Sensorium.ps1 +351 -0
  2. package/README.md +14 -0
  3. package/dist/config.d.ts +16 -1
  4. package/dist/config.d.ts.map +1 -1
  5. package/dist/config.js +39 -2
  6. package/dist/config.js.map +1 -1
  7. package/dist/daily-session.d.ts +2 -1
  8. package/dist/daily-session.d.ts.map +1 -1
  9. package/dist/daily-session.js +23 -26
  10. package/dist/daily-session.js.map +1 -1
  11. package/dist/dashboard/routes/settings.d.ts +4 -0
  12. package/dist/dashboard/routes/settings.d.ts.map +1 -1
  13. package/dist/dashboard/routes/settings.js +57 -1
  14. package/dist/dashboard/routes/settings.js.map +1 -1
  15. package/dist/dashboard/routes/threads.d.ts +1 -0
  16. package/dist/dashboard/routes/threads.d.ts.map +1 -1
  17. package/dist/dashboard/routes/threads.js +23 -25
  18. package/dist/dashboard/routes/threads.js.map +1 -1
  19. package/dist/dashboard/routes.d.ts.map +1 -1
  20. package/dist/dashboard/routes.js +7 -2
  21. package/dist/dashboard/routes.js.map +1 -1
  22. package/dist/dashboard/spa.html +11 -11
  23. package/dist/data/interfaces.d.ts +36 -0
  24. package/dist/data/interfaces.d.ts.map +1 -0
  25. package/dist/data/interfaces.js +2 -0
  26. package/dist/data/interfaces.js.map +1 -0
  27. package/dist/data/memory/bootstrap.d.ts +36 -16
  28. package/dist/data/memory/bootstrap.d.ts.map +1 -1
  29. package/dist/data/memory/bootstrap.js +71 -217
  30. package/dist/data/memory/bootstrap.js.map +1 -1
  31. package/dist/data/memory/consolidation.d.ts +35 -34
  32. package/dist/data/memory/consolidation.d.ts.map +1 -1
  33. package/dist/data/memory/consolidation.js +43 -554
  34. package/dist/data/memory/consolidation.js.map +1 -1
  35. package/dist/data/memory/migration-runner.d.ts +5 -0
  36. package/dist/data/memory/migration-runner.d.ts.map +1 -0
  37. package/dist/data/memory/migration-runner.js +403 -0
  38. package/dist/data/memory/migration-runner.js.map +1 -0
  39. package/dist/data/memory/reflection.js +1 -1
  40. package/dist/data/memory/schema-ddl.d.ts +4 -0
  41. package/dist/data/memory/schema-ddl.d.ts.map +1 -0
  42. package/dist/data/memory/schema-ddl.js +194 -0
  43. package/dist/data/memory/schema-ddl.js.map +1 -0
  44. package/dist/data/memory/schema-guard.d.ts +3 -0
  45. package/dist/data/memory/schema-guard.d.ts.map +1 -0
  46. package/dist/data/memory/schema-guard.js +184 -0
  47. package/dist/data/memory/schema-guard.js.map +1 -0
  48. package/dist/data/memory/schema.d.ts +2 -5
  49. package/dist/data/memory/schema.d.ts.map +1 -1
  50. package/dist/data/memory/schema.js +6 -834
  51. package/dist/data/memory/schema.js.map +1 -1
  52. package/dist/data/memory/synthesis.js +2 -2
  53. package/dist/data/memory/synthesis.js.map +1 -1
  54. package/dist/data/memory/thread-registry.d.ts +18 -4
  55. package/dist/data/memory/thread-registry.d.ts.map +1 -1
  56. package/dist/data/memory/thread-registry.js +25 -0
  57. package/dist/data/memory/thread-registry.js.map +1 -1
  58. package/dist/data/sent-message.repository.d.ts +12 -0
  59. package/dist/data/sent-message.repository.d.ts.map +1 -0
  60. package/dist/data/sent-message.repository.js +31 -0
  61. package/dist/data/sent-message.repository.js.map +1 -0
  62. package/dist/http-server.d.ts.map +1 -1
  63. package/dist/http-server.js +23 -2
  64. package/dist/http-server.js.map +1 -1
  65. package/dist/index.js +27 -48
  66. package/dist/index.js.map +1 -1
  67. package/dist/logger.d.ts +7 -2
  68. package/dist/logger.d.ts.map +1 -1
  69. package/dist/logger.js +89 -12
  70. package/dist/logger.js.map +1 -1
  71. package/dist/scheduler.d.ts +8 -0
  72. package/dist/scheduler.d.ts.map +1 -1
  73. package/dist/scheduler.js +15 -0
  74. package/dist/scheduler.js.map +1 -1
  75. package/dist/server/factory.d.ts +2 -1
  76. package/dist/server/factory.d.ts.map +1 -1
  77. package/dist/server/factory.js +11 -4
  78. package/dist/server/factory.js.map +1 -1
  79. package/dist/services/agent-spawn.service.d.ts +39 -0
  80. package/dist/services/agent-spawn.service.d.ts.map +1 -0
  81. package/dist/services/agent-spawn.service.js +348 -0
  82. package/dist/services/agent-spawn.service.js.map +1 -0
  83. package/dist/services/background-runner.d.ts +26 -0
  84. package/dist/services/background-runner.d.ts.map +1 -0
  85. package/dist/services/background-runner.js +71 -0
  86. package/dist/services/background-runner.js.map +1 -0
  87. package/dist/services/consolidation.service.d.ts +16 -0
  88. package/dist/services/consolidation.service.d.ts.map +1 -0
  89. package/dist/services/consolidation.service.js +508 -0
  90. package/dist/services/consolidation.service.js.map +1 -0
  91. package/dist/services/dispatcher/broker.d.ts +2 -0
  92. package/dist/services/dispatcher/broker.d.ts.map +1 -1
  93. package/dist/services/dispatcher/broker.js +5 -10
  94. package/dist/services/dispatcher/broker.js.map +1 -1
  95. package/dist/services/dispatcher/index.d.ts +1 -1
  96. package/dist/services/dispatcher/index.d.ts.map +1 -1
  97. package/dist/services/dispatcher/index.js +1 -1
  98. package/dist/services/dispatcher/index.js.map +1 -1
  99. package/dist/services/dispatcher/lock.d.ts.map +1 -1
  100. package/dist/services/dispatcher/lock.js +7 -11
  101. package/dist/services/dispatcher/lock.js.map +1 -1
  102. package/dist/services/maintenance-signal.d.ts +18 -0
  103. package/dist/services/maintenance-signal.d.ts.map +1 -0
  104. package/dist/services/maintenance-signal.js +48 -0
  105. package/dist/services/maintenance-signal.js.map +1 -0
  106. package/dist/services/memory-briefing.service.d.ts +4 -0
  107. package/dist/services/memory-briefing.service.d.ts.map +1 -0
  108. package/dist/services/memory-briefing.service.js +143 -0
  109. package/dist/services/memory-briefing.service.js.map +1 -0
  110. package/dist/services/process.service.d.ts +31 -0
  111. package/dist/services/process.service.d.ts.map +1 -0
  112. package/dist/services/process.service.js +100 -0
  113. package/dist/services/process.service.js.map +1 -0
  114. package/dist/services/thread-health.service.d.ts +18 -0
  115. package/dist/services/thread-health.service.d.ts.map +1 -0
  116. package/dist/services/thread-health.service.js +118 -0
  117. package/dist/services/thread-health.service.js.map +1 -0
  118. package/dist/services/thread-lifecycle.service.d.ts +52 -0
  119. package/dist/services/thread-lifecycle.service.d.ts.map +1 -0
  120. package/dist/services/thread-lifecycle.service.js +174 -0
  121. package/dist/services/thread-lifecycle.service.js.map +1 -0
  122. package/dist/services/topic.service.d.ts +25 -0
  123. package/dist/services/topic.service.d.ts.map +1 -0
  124. package/dist/services/topic.service.js +65 -0
  125. package/dist/services/topic.service.js.map +1 -0
  126. package/dist/services/worker-cleanup.service.d.ts +8 -0
  127. package/dist/services/worker-cleanup.service.d.ts.map +1 -0
  128. package/dist/services/worker-cleanup.service.js +82 -0
  129. package/dist/services/worker-cleanup.service.js.map +1 -0
  130. package/dist/sessions.d.ts +14 -0
  131. package/dist/sessions.d.ts.map +1 -1
  132. package/dist/sessions.js +55 -0
  133. package/dist/sessions.js.map +1 -1
  134. package/dist/telegram.d.ts +13 -6
  135. package/dist/telegram.d.ts.map +1 -1
  136. package/dist/telegram.js +43 -14
  137. package/dist/telegram.js.map +1 -1
  138. package/dist/tools/delegate-tool.d.ts +4 -0
  139. package/dist/tools/delegate-tool.d.ts.map +1 -1
  140. package/dist/tools/delegate-tool.js +48 -109
  141. package/dist/tools/delegate-tool.js.map +1 -1
  142. package/dist/tools/memory-tools.d.ts.map +1 -1
  143. package/dist/tools/memory-tools.js +1 -1
  144. package/dist/tools/memory-tools.js.map +1 -1
  145. package/dist/tools/shared-agent-utils.d.ts +9 -1
  146. package/dist/tools/shared-agent-utils.d.ts.map +1 -1
  147. package/dist/tools/shared-agent-utils.js +21 -38
  148. package/dist/tools/shared-agent-utils.js.map +1 -1
  149. package/dist/tools/start-session-tool.d.ts +2 -0
  150. package/dist/tools/start-session-tool.d.ts.map +1 -1
  151. package/dist/tools/start-session-tool.js +68 -118
  152. package/dist/tools/start-session-tool.js.map +1 -1
  153. package/dist/tools/thread-lifecycle.d.ts +5 -127
  154. package/dist/tools/thread-lifecycle.d.ts.map +1 -1
  155. package/dist/tools/thread-lifecycle.js +5 -1167
  156. package/dist/tools/thread-lifecycle.js.map +1 -1
  157. package/dist/tools/utility-tools.js +5 -2
  158. package/dist/tools/utility-tools.js.map +1 -1
  159. package/dist/tools/wait/drive-handler.d.ts +0 -1
  160. package/dist/tools/wait/drive-handler.d.ts.map +1 -1
  161. package/dist/tools/wait/drive-handler.js +5 -22
  162. package/dist/tools/wait/drive-handler.js.map +1 -1
  163. package/dist/tools/wait/message-delivery.js +1 -1
  164. package/dist/tools/wait/message-delivery.js.map +1 -1
  165. package/dist/tools/wait/message-processing.d.ts.map +1 -1
  166. package/dist/tools/wait/message-processing.js +9 -8
  167. package/dist/tools/wait/message-processing.js.map +1 -1
  168. package/dist/tools/wait/poll-loop.d.ts +2 -0
  169. package/dist/tools/wait/poll-loop.d.ts.map +1 -1
  170. package/dist/tools/wait/poll-loop.js +27 -29
  171. package/dist/tools/wait/poll-loop.js.map +1 -1
  172. package/dist/tools/wait/task-handler.d.ts +0 -3
  173. package/dist/tools/wait/task-handler.d.ts.map +1 -1
  174. package/dist/tools/wait/task-handler.js +3 -2
  175. package/dist/tools/wait/task-handler.js.map +1 -1
  176. package/dist/types.d.ts +0 -1
  177. package/dist/types.d.ts.map +1 -1
  178. package/package.json +4 -8
  179. package/supervisor/config.go +182 -69
  180. package/supervisor/config_test.go +78 -0
  181. package/supervisor/go.mod +12 -0
  182. package/supervisor/go.sum +20 -0
  183. package/supervisor/health.go +24 -6
  184. package/supervisor/keeper.go +15 -10
  185. package/supervisor/log.go +109 -28
  186. package/supervisor/log_test.go +86 -6
  187. package/supervisor/main.go +146 -19
  188. package/supervisor/main_test.go +130 -0
  189. package/supervisor/process.go +47 -4
  190. package/supervisor/process_test.go +14 -0
  191. package/supervisor/secrets.go +95 -0
  192. package/supervisor/secrets_securevault_test.go +98 -0
  193. package/supervisor/secrets_test.go +119 -0
  194. package/supervisor/self_update.go +282 -0
  195. package/supervisor/self_update_test.go +177 -0
  196. package/supervisor/service_restart_stub.go +9 -0
  197. package/supervisor/service_restart_windows.go +63 -0
  198. package/supervisor/service_stub.go +15 -0
  199. package/supervisor/service_windows.go +216 -0
  200. package/supervisor/update_state.go +264 -0
  201. package/supervisor/update_state_test.go +306 -0
  202. package/supervisor/updater.go +341 -10
  203. package/supervisor/updater_test.go +64 -0
  204. package/scripts/install-supervisor.ps1 +0 -67
  205. package/scripts/install-supervisor.sh +0 -43
  206. package/scripts/start-supervisor.ps1 +0 -46
  207. package/scripts/start-supervisor.sh +0 -20
@@ -0,0 +1,194 @@
1
+ import { errorMessage } from "../../utils.js";
2
+ import { log } from "../../logger.js";
3
+ export const SCHEMA_SQL = `
4
+ CREATE TABLE IF NOT EXISTS episodes (
5
+ episode_id TEXT PRIMARY KEY,
6
+ session_id TEXT NOT NULL,
7
+ thread_id INTEGER NOT NULL,
8
+ timestamp TEXT NOT NULL,
9
+ type TEXT NOT NULL CHECK(type IN ('operator_message','agent_action','system_event','operator_reaction')),
10
+ modality TEXT NOT NULL CHECK(modality IN ('text','voice','photo','video_note','document','mixed','reaction')),
11
+ content TEXT NOT NULL,
12
+ topic_tags TEXT,
13
+ importance REAL NOT NULL DEFAULT 0.5,
14
+ consolidated INTEGER DEFAULT 0,
15
+ accessed_count INTEGER DEFAULT 0,
16
+ last_accessed TEXT,
17
+ created_at TEXT NOT NULL
18
+ );
19
+
20
+ CREATE INDEX IF NOT EXISTS idx_ep_thread_time ON episodes(thread_id, timestamp DESC);
21
+ CREATE INDEX IF NOT EXISTS idx_ep_importance ON episodes(importance DESC);
22
+ CREATE INDEX IF NOT EXISTS idx_ep_uncons ON episodes(consolidated) WHERE consolidated = 0;
23
+
24
+ CREATE TABLE IF NOT EXISTS semantic_notes (
25
+ note_id TEXT PRIMARY KEY,
26
+ type TEXT NOT NULL CHECK(type IN ('fact','preference','pattern','entity','relationship')),
27
+ content TEXT NOT NULL,
28
+ keywords TEXT NOT NULL,
29
+ confidence REAL NOT NULL DEFAULT 0.5,
30
+ source_episodes TEXT,
31
+ linked_notes TEXT,
32
+ link_reasons TEXT,
33
+ valid_from TEXT NOT NULL,
34
+ valid_to TEXT,
35
+ superseded_by TEXT,
36
+ access_count INTEGER DEFAULT 0,
37
+ last_accessed TEXT,
38
+ priority INTEGER NOT NULL DEFAULT 0,
39
+ thread_id INTEGER,
40
+ is_guardrail INTEGER NOT NULL DEFAULT 0,
41
+ pinned INTEGER NOT NULL DEFAULT 0,
42
+ created_at TEXT NOT NULL,
43
+ updated_at TEXT NOT NULL
44
+ );
45
+
46
+ CREATE INDEX IF NOT EXISTS idx_sem_type ON semantic_notes(type);
47
+ CREATE INDEX IF NOT EXISTS idx_sem_conf ON semantic_notes(confidence DESC);
48
+ CREATE INDEX IF NOT EXISTS idx_sem_valid ON semantic_notes(valid_to) WHERE valid_to IS NULL;
49
+ CREATE INDEX IF NOT EXISTS idx_sem_priority ON semantic_notes(priority DESC) WHERE valid_to IS NULL;
50
+ CREATE INDEX IF NOT EXISTS idx_sem_thread ON semantic_notes(thread_id) WHERE valid_to IS NULL;
51
+ CREATE INDEX IF NOT EXISTS idx_sem_guardrail ON semantic_notes(is_guardrail) WHERE is_guardrail = 1 AND valid_to IS NULL;
52
+ CREATE INDEX IF NOT EXISTS idx_sem_pinned ON semantic_notes(pinned) WHERE pinned = 1 AND valid_to IS NULL;
53
+
54
+ CREATE TABLE IF NOT EXISTS procedures (
55
+ procedure_id TEXT PRIMARY KEY,
56
+ name TEXT NOT NULL,
57
+ type TEXT NOT NULL CHECK(type IN ('workflow','habit','tool_pattern','template')),
58
+ description TEXT NOT NULL,
59
+ steps TEXT,
60
+ trigger_conditions TEXT,
61
+ success_rate REAL DEFAULT 0.5,
62
+ times_executed INTEGER DEFAULT 0,
63
+ last_executed_at TEXT,
64
+ learned_from TEXT,
65
+ corrections TEXT,
66
+ related_procedures TEXT,
67
+ confidence REAL DEFAULT 0.5,
68
+ created_at TEXT NOT NULL,
69
+ updated_at TEXT NOT NULL
70
+ );
71
+
72
+ CREATE INDEX IF NOT EXISTS idx_proc_name ON procedures(name);
73
+ CREATE INDEX IF NOT EXISTS idx_proc_type ON procedures(type);
74
+
75
+ CREATE TABLE IF NOT EXISTS meta_topic_index (
76
+ topic TEXT PRIMARY KEY,
77
+ semantic_count INTEGER DEFAULT 0,
78
+ procedural_count INTEGER DEFAULT 0,
79
+ last_updated TEXT,
80
+ avg_confidence REAL DEFAULT 0.5,
81
+ total_accesses INTEGER DEFAULT 0
82
+ );
83
+
84
+ CREATE TABLE IF NOT EXISTS meta_consolidation_log (
85
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
86
+ run_at TEXT NOT NULL,
87
+ episodes_processed INTEGER,
88
+ notes_created INTEGER,
89
+ duration_ms INTEGER
90
+ );
91
+
92
+ CREATE TABLE IF NOT EXISTS voice_signatures (
93
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
94
+ episode_id TEXT NOT NULL,
95
+ emotion TEXT,
96
+ arousal REAL,
97
+ dominance REAL,
98
+ valence REAL,
99
+ speech_rate REAL,
100
+ mean_pitch_hz REAL,
101
+ pitch_std_hz REAL,
102
+ jitter REAL,
103
+ shimmer REAL,
104
+ hnr_db REAL,
105
+ audio_events TEXT,
106
+ duration_sec REAL,
107
+ created_at TEXT NOT NULL
108
+ );
109
+
110
+ CREATE INDEX IF NOT EXISTS idx_voice_ep ON voice_signatures(episode_id);
111
+ CREATE INDEX IF NOT EXISTS idx_voice_time ON voice_signatures(created_at DESC);
112
+
113
+ CREATE TABLE IF NOT EXISTS note_embeddings (
114
+ note_id TEXT PRIMARY KEY,
115
+ embedding BLOB NOT NULL,
116
+ model TEXT NOT NULL DEFAULT 'text-embedding-3-small',
117
+ created_at TEXT NOT NULL
118
+ );
119
+
120
+ CREATE INDEX IF NOT EXISTS idx_emb_note ON note_embeddings(note_id);
121
+
122
+ CREATE TABLE IF NOT EXISTS sent_messages (
123
+ message_id INTEGER PRIMARY KEY,
124
+ thread_id INTEGER NOT NULL,
125
+ created_at TEXT DEFAULT (datetime('now'))
126
+ );
127
+
128
+ CREATE INDEX IF NOT EXISTS idx_sent_messages_thread ON sent_messages(thread_id);
129
+
130
+ CREATE TABLE IF NOT EXISTS topic_registry (
131
+ chat_id TEXT NOT NULL,
132
+ name TEXT NOT NULL COLLATE NOCASE,
133
+ thread_id INTEGER NOT NULL,
134
+ registered_at TEXT NOT NULL DEFAULT (datetime('now')),
135
+ PRIMARY KEY (chat_id, name)
136
+ );
137
+
138
+ CREATE TABLE IF NOT EXISTS temporal_narratives (
139
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
140
+ thread_id INTEGER NOT NULL,
141
+ resolution TEXT NOT NULL CHECK(resolution IN ('day', 'week', 'month', 'quarter', 'half_year')),
142
+ period_start TEXT NOT NULL,
143
+ period_end TEXT NOT NULL,
144
+ narrative TEXT NOT NULL,
145
+ source_episode_count INTEGER NOT NULL DEFAULT 0,
146
+ source_note_count INTEGER NOT NULL DEFAULT 0,
147
+ model TEXT,
148
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
149
+ UNIQUE(thread_id, resolution, period_start)
150
+ );
151
+ CREATE INDEX IF NOT EXISTS idx_narrative_thread_res ON temporal_narratives(thread_id, resolution, created_at DESC);
152
+
153
+ CREATE TABLE IF NOT EXISTS thread_registry (
154
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
155
+ thread_id INTEGER NOT NULL UNIQUE,
156
+ name TEXT NOT NULL,
157
+ type TEXT NOT NULL CHECK(type IN ('root','daily','branch','worker')),
158
+ root_thread_id INTEGER,
159
+ badge TEXT NOT NULL DEFAULT 'root',
160
+ client TEXT DEFAULT 'claude',
161
+ max_retries INTEGER DEFAULT 5,
162
+ cooldown_ms INTEGER DEFAULT 300000,
163
+ keep_alive INTEGER DEFAULT 0,
164
+ created_at TEXT NOT NULL,
165
+ last_active_at TEXT,
166
+ session_reset_at TEXT,
167
+ status TEXT NOT NULL DEFAULT 'active' CHECK(status IN ('active','archived','expired','exited')),
168
+ daily_rotation INTEGER NOT NULL DEFAULT 0,
169
+ autonomous_mode INTEGER NOT NULL DEFAULT 0,
170
+ telegram_topic_id INTEGER,
171
+ identity_prompt TEXT,
172
+ working_directory TEXT
173
+ );
174
+ CREATE INDEX IF NOT EXISTS idx_thread_reg_type ON thread_registry(type);
175
+ CREATE INDEX IF NOT EXISTS idx_thread_reg_root ON thread_registry(root_thread_id);
176
+ CREATE INDEX IF NOT EXISTS idx_thread_reg_status ON thread_registry(status);
177
+
178
+ CREATE TABLE IF NOT EXISTS schema_version (
179
+ version INTEGER PRIMARY KEY,
180
+ applied_at TEXT NOT NULL
181
+ );
182
+ `;
183
+ export function cleanupOldSentMessages(db) {
184
+ try {
185
+ const result = db.prepare(`DELETE FROM sent_messages WHERE created_at < datetime('now', '-7 days')`).run();
186
+ if (result.changes > 0) {
187
+ log.info(`[memory] Cleaned up ${result.changes} old sent_messages entries.`);
188
+ }
189
+ }
190
+ catch (err) {
191
+ log.warn(`[memory] sent_messages cleanup failed: ${errorMessage(err)}`);
192
+ }
193
+ }
194
+ //# sourceMappingURL=schema-ddl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-ddl.js","sourceRoot":"","sources":["../../../src/data/memory/schema-ddl.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AAEtC,MAAM,CAAC,MAAM,UAAU,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmLzB,CAAC;AAEF,MAAM,UAAU,sBAAsB,CAAC,EAAY;IACjD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,EAAE,CAAC,OAAO,CACvB,yEAAyE,CAC1E,CAAC,GAAG,EAAE,CAAC;QACR,IAAI,MAAM,CAAC,OAAO,GAAG,CAAC,EAAE,CAAC;YACvB,GAAG,CAAC,IAAI,CAAC,uBAAuB,MAAM,CAAC,OAAO,6BAA6B,CAAC,CAAC;QAC/E,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,GAAG,CAAC,IAAI,CAAC,0CAA0C,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC1E,CAAC;AACH,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Database } from "./schema.js";
2
+ export declare function ensureSchemaIntegrity(db: Database): void;
3
+ //# sourceMappingURL=schema-guard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-guard.d.ts","sourceRoot":"","sources":["../../../src/data/memory/schema-guard.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,wBAAgB,qBAAqB,CAAC,EAAE,EAAE,QAAQ,GAAG,IAAI,CAsNxD"}
@@ -0,0 +1,184 @@
1
+ import { log } from "../../logger.js";
2
+ import { rebuildThreadRegistryWithExitedStatus } from "./migration-runner.js";
3
+ import { nowISO } from "./utils.js";
4
+ export function ensureSchemaIntegrity(db) {
5
+ const stampVersion = (v) => {
6
+ try {
7
+ db.prepare("INSERT OR REPLACE INTO schema_version (version, applied_at) VALUES (?, ?)").run(v, nowISO());
8
+ }
9
+ catch { }
10
+ };
11
+ const getTableSql = (tableName) => {
12
+ const row = db.prepare("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = ?").get(tableName);
13
+ return row?.sql ?? "";
14
+ };
15
+ const semanticNoteCols = db
16
+ .prepare("PRAGMA table_info(semantic_notes)")
17
+ .all()
18
+ .map((r) => r.name);
19
+ if (!semanticNoteCols.includes("is_guardrail")) {
20
+ log.info("[memory] Self-heal: adding missing is_guardrail column");
21
+ db.exec("ALTER TABLE semantic_notes ADD COLUMN is_guardrail INTEGER NOT NULL DEFAULT 0");
22
+ db.exec("CREATE INDEX IF NOT EXISTS idx_sem_guardrail ON semantic_notes(is_guardrail) WHERE is_guardrail = 1 AND valid_to IS NULL");
23
+ stampVersion(8);
24
+ }
25
+ if (!semanticNoteCols.includes("pinned")) {
26
+ log.info("[memory] Self-heal: adding missing pinned column");
27
+ db.exec("ALTER TABLE semantic_notes ADD COLUMN pinned INTEGER NOT NULL DEFAULT 0");
28
+ db.exec("CREATE INDEX IF NOT EXISTS idx_sem_pinned ON semantic_notes(pinned) WHERE pinned = 1 AND valid_to IS NULL");
29
+ stampVersion(10);
30
+ }
31
+ if (!semanticNoteCols.includes("thread_id")) {
32
+ log.info("[memory] Self-heal: adding missing thread_id column to semantic_notes");
33
+ db.exec("ALTER TABLE semantic_notes ADD COLUMN thread_id INTEGER");
34
+ db.exec("CREATE INDEX IF NOT EXISTS idx_sem_thread ON semantic_notes(thread_id) WHERE valid_to IS NULL");
35
+ stampVersion(4);
36
+ }
37
+ if (!semanticNoteCols.includes("priority")) {
38
+ log.info("[memory] Self-heal: adding missing priority column to semantic_notes");
39
+ db.exec("ALTER TABLE semantic_notes ADD COLUMN priority INTEGER NOT NULL DEFAULT 0");
40
+ db.exec("CREATE INDEX IF NOT EXISTS idx_sem_priority ON semantic_notes(priority DESC) WHERE valid_to IS NULL");
41
+ stampVersion(3);
42
+ }
43
+ const episodeCols = db
44
+ .prepare("PRAGMA table_info(episodes)")
45
+ .all()
46
+ .map((r) => r.name);
47
+ if (!episodeCols.includes("thread_id")) {
48
+ log.info("[memory] Self-heal: adding missing thread_id column to episodes");
49
+ db.exec("ALTER TABLE episodes ADD COLUMN thread_id INTEGER");
50
+ }
51
+ const hasTemporalNarratives = db
52
+ .prepare("SELECT COUNT(*) as cnt FROM sqlite_master WHERE type='table' AND name='temporal_narratives'")
53
+ .get();
54
+ if (hasTemporalNarratives.cnt === 0) {
55
+ log.info("[memory] Self-heal: creating missing temporal_narratives table");
56
+ db.exec(`
57
+ CREATE TABLE IF NOT EXISTS temporal_narratives (
58
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
59
+ thread_id INTEGER NOT NULL,
60
+ resolution TEXT NOT NULL CHECK(resolution IN ('day', 'week', 'month', 'quarter', 'half_year')),
61
+ period_start TEXT NOT NULL,
62
+ period_end TEXT NOT NULL,
63
+ narrative TEXT NOT NULL,
64
+ source_episode_count INTEGER NOT NULL DEFAULT 0,
65
+ source_note_count INTEGER NOT NULL DEFAULT 0,
66
+ model TEXT,
67
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
68
+ UNIQUE(thread_id, resolution, period_start)
69
+ );
70
+ CREATE INDEX IF NOT EXISTS idx_narrative_thread_res ON temporal_narratives(thread_id, resolution, created_at DESC);
71
+ `);
72
+ stampVersion(11);
73
+ }
74
+ else {
75
+ const temporalNarrativesSql = getTableSql("temporal_narratives");
76
+ const hasExpandedNarrativeResolution = temporalNarrativesSql.includes("'quarter'") &&
77
+ temporalNarrativesSql.includes("'half_year'");
78
+ if (!hasExpandedNarrativeResolution) {
79
+ log.info("[memory] Self-heal: widening temporal_narratives resolution CHECK");
80
+ db.exec(`
81
+ CREATE TABLE IF NOT EXISTS temporal_narratives_new (
82
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
83
+ thread_id INTEGER NOT NULL,
84
+ resolution TEXT NOT NULL CHECK(resolution IN ('day', 'week', 'month', 'quarter', 'half_year')),
85
+ period_start TEXT NOT NULL,
86
+ period_end TEXT NOT NULL,
87
+ narrative TEXT NOT NULL,
88
+ source_episode_count INTEGER NOT NULL DEFAULT 0,
89
+ source_note_count INTEGER NOT NULL DEFAULT 0,
90
+ model TEXT,
91
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
92
+ UNIQUE(thread_id, resolution, period_start)
93
+ );
94
+ INSERT OR IGNORE INTO temporal_narratives_new SELECT * FROM temporal_narratives;
95
+ DROP TABLE temporal_narratives;
96
+ ALTER TABLE temporal_narratives_new RENAME TO temporal_narratives;
97
+ CREATE INDEX IF NOT EXISTS idx_narrative_thread_res ON temporal_narratives(thread_id, resolution, created_at DESC);
98
+ `);
99
+ stampVersion(14);
100
+ }
101
+ }
102
+ const hasThreadRegistry = db
103
+ .prepare("SELECT COUNT(*) as cnt FROM sqlite_master WHERE type='table' AND name='thread_registry'")
104
+ .get();
105
+ if (hasThreadRegistry.cnt === 0) {
106
+ log.info("[memory] Self-heal: creating missing thread_registry table");
107
+ db.exec(`
108
+ CREATE TABLE IF NOT EXISTS thread_registry (
109
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
110
+ thread_id INTEGER NOT NULL UNIQUE,
111
+ name TEXT NOT NULL,
112
+ type TEXT NOT NULL CHECK(type IN ('root','daily','branch','worker')),
113
+ root_thread_id INTEGER,
114
+ badge TEXT NOT NULL DEFAULT 'root',
115
+ client TEXT DEFAULT 'claude',
116
+ max_retries INTEGER DEFAULT 5,
117
+ cooldown_ms INTEGER DEFAULT 300000,
118
+ keep_alive INTEGER DEFAULT 0,
119
+ created_at TEXT NOT NULL,
120
+ last_active_at TEXT,
121
+ session_reset_at TEXT,
122
+ status TEXT NOT NULL DEFAULT 'active' CHECK(status IN ('active','archived','expired','exited')),
123
+ daily_rotation INTEGER NOT NULL DEFAULT 0,
124
+ autonomous_mode INTEGER NOT NULL DEFAULT 0,
125
+ telegram_topic_id INTEGER,
126
+ identity_prompt TEXT,
127
+ working_directory TEXT
128
+ );
129
+ CREATE INDEX IF NOT EXISTS idx_thread_reg_type ON thread_registry(type);
130
+ CREATE INDEX IF NOT EXISTS idx_thread_reg_root ON thread_registry(root_thread_id);
131
+ CREATE INDEX IF NOT EXISTS idx_thread_reg_status ON thread_registry(status);
132
+ `);
133
+ stampVersion(12);
134
+ stampVersion(13);
135
+ stampVersion(15);
136
+ stampVersion(16);
137
+ stampVersion(17);
138
+ stampVersion(19);
139
+ stampVersion(20);
140
+ stampVersion(21);
141
+ return;
142
+ }
143
+ const threadRegistryCols = db
144
+ .prepare("PRAGMA table_info(thread_registry)")
145
+ .all()
146
+ .map((r) => r.name);
147
+ if (!threadRegistryCols.includes("session_reset_at")) {
148
+ log.info("[memory] Self-heal: adding missing session_reset_at column to thread_registry");
149
+ db.exec("ALTER TABLE thread_registry ADD COLUMN session_reset_at TEXT");
150
+ stampVersion(13);
151
+ }
152
+ const threadRegistrySql = getTableSql("thread_registry");
153
+ if (!threadRegistrySql.includes("'exited'")) {
154
+ log.info("[memory] Self-heal: widening thread_registry status CHECK");
155
+ rebuildThreadRegistryWithExitedStatus(db, threadRegistryCols);
156
+ stampVersion(15);
157
+ }
158
+ if (!threadRegistryCols.includes("daily_rotation")) {
159
+ log.info("[memory] Self-heal: adding missing daily_rotation column to thread_registry");
160
+ db.exec("ALTER TABLE thread_registry ADD COLUMN daily_rotation INTEGER NOT NULL DEFAULT 0");
161
+ stampVersion(16);
162
+ }
163
+ if (!threadRegistryCols.includes("autonomous_mode")) {
164
+ log.info("[memory] Self-heal: adding missing autonomous_mode column to thread_registry");
165
+ db.exec("ALTER TABLE thread_registry ADD COLUMN autonomous_mode INTEGER NOT NULL DEFAULT 0");
166
+ stampVersion(17);
167
+ }
168
+ if (!threadRegistryCols.includes("telegram_topic_id")) {
169
+ log.info("[memory] Self-heal: adding missing telegram_topic_id column to thread_registry");
170
+ db.exec("ALTER TABLE thread_registry ADD COLUMN telegram_topic_id INTEGER");
171
+ stampVersion(19);
172
+ }
173
+ if (!threadRegistryCols.includes("identity_prompt")) {
174
+ log.info("[memory] Self-heal: adding missing identity_prompt column to thread_registry");
175
+ db.exec("ALTER TABLE thread_registry ADD COLUMN identity_prompt TEXT");
176
+ stampVersion(20);
177
+ }
178
+ if (!threadRegistryCols.includes("working_directory")) {
179
+ log.info("[memory] Self-heal: adding missing working_directory column to thread_registry");
180
+ db.exec("ALTER TABLE thread_registry ADD COLUMN working_directory TEXT");
181
+ stampVersion(21);
182
+ }
183
+ }
184
+ //# sourceMappingURL=schema-guard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-guard.js","sourceRoot":"","sources":["../../../src/data/memory/schema-guard.ts"],"names":[],"mappings":"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"}
@@ -6,11 +6,8 @@
6
6
  * `initMemoryDb()` to obtain the singleton handle.
7
7
  */
8
8
  import BetterSqlite3 from "better-sqlite3";
9
+ import { cleanupOldSentMessages } from "./schema-ddl.js";
9
10
  export type Database = BetterSqlite3.Database;
11
+ export { cleanupOldSentMessages };
10
12
  export declare function initMemoryDb(): Database;
11
- /**
12
- * Delete sent_messages entries older than 7 days.
13
- * Safe to call periodically (e.g. during consolidation).
14
- */
15
- export declare function cleanupOldSentMessages(db: Database): void;
16
13
  //# sourceMappingURL=schema.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/data/memory/schema.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,aAAa,MAAM,gBAAgB,CAAC;AAS3C,MAAM,MAAM,QAAQ,GAAG,aAAa,CAAC,QAAQ,CAAC;AA02B9C,wBAAgB,YAAY,IAAI,QAAQ,CAkDvC;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,QAAQ,GAAG,IAAI,CAWzD"}
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/data/memory/schema.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,aAAa,MAAM,gBAAgB,CAAC;AAK3C,OAAO,EAAc,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAKrE,MAAM,MAAM,QAAQ,GAAG,aAAa,CAAC,QAAQ,CAAC;AAC9C,OAAO,EAAE,sBAAsB,EAAE,CAAC;AAuBlC,wBAAgB,YAAY,IAAI,QAAQ,CAiCvC"}