exovault-mcp-server 1.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.
Files changed (305) hide show
  1. package/dist/auth.d.ts +41 -0
  2. package/dist/auth.d.ts.map +1 -0
  3. package/dist/auth.js +236 -0
  4. package/dist/auth.js.map +1 -0
  5. package/dist/auto-session.d.ts +39 -0
  6. package/dist/auto-session.d.ts.map +1 -0
  7. package/dist/auto-session.js +128 -0
  8. package/dist/auto-session.js.map +1 -0
  9. package/dist/buffer-persistence.d.ts +35 -0
  10. package/dist/buffer-persistence.d.ts.map +1 -0
  11. package/dist/buffer-persistence.js +110 -0
  12. package/dist/buffer-persistence.js.map +1 -0
  13. package/dist/coerce-params.d.ts +36 -0
  14. package/dist/coerce-params.d.ts.map +1 -0
  15. package/dist/coerce-params.js +120 -0
  16. package/dist/coerce-params.js.map +1 -0
  17. package/dist/crypto.d.ts +39 -0
  18. package/dist/crypto.d.ts.map +1 -0
  19. package/dist/crypto.js +119 -0
  20. package/dist/crypto.js.map +1 -0
  21. package/dist/db.d.ts +350 -0
  22. package/dist/db.d.ts.map +1 -0
  23. package/dist/db.js +866 -0
  24. package/dist/db.js.map +1 -0
  25. package/dist/embedding-config.d.ts +11 -0
  26. package/dist/embedding-config.d.ts.map +1 -0
  27. package/dist/embedding-config.js +24 -0
  28. package/dist/embedding-config.js.map +1 -0
  29. package/dist/entity-extraction.d.ts +22 -0
  30. package/dist/entity-extraction.d.ts.map +1 -0
  31. package/dist/entity-extraction.js +140 -0
  32. package/dist/entity-extraction.js.map +1 -0
  33. package/dist/episodic-headline.d.ts +6 -0
  34. package/dist/episodic-headline.d.ts.map +1 -0
  35. package/dist/episodic-headline.js +62 -0
  36. package/dist/episodic-headline.js.map +1 -0
  37. package/dist/error-sanitizer.d.ts +20 -0
  38. package/dist/error-sanitizer.d.ts.map +1 -0
  39. package/dist/error-sanitizer.js +54 -0
  40. package/dist/error-sanitizer.js.map +1 -0
  41. package/dist/extraction-budget.d.ts +39 -0
  42. package/dist/extraction-budget.d.ts.map +1 -0
  43. package/dist/extraction-budget.js +122 -0
  44. package/dist/extraction-budget.js.map +1 -0
  45. package/dist/extraction-llm.d.ts +22 -0
  46. package/dist/extraction-llm.d.ts.map +1 -0
  47. package/dist/extraction-llm.js +32 -0
  48. package/dist/extraction-llm.js.map +1 -0
  49. package/dist/extraction-prompt.d.ts +40 -0
  50. package/dist/extraction-prompt.d.ts.map +1 -0
  51. package/dist/extraction-prompt.js +176 -0
  52. package/dist/extraction-prompt.js.map +1 -0
  53. package/dist/gateway-client.d.ts +303 -0
  54. package/dist/gateway-client.d.ts.map +1 -0
  55. package/dist/gateway-client.js +285 -0
  56. package/dist/gateway-client.js.map +1 -0
  57. package/dist/gateway-init.d.ts +32 -0
  58. package/dist/gateway-init.d.ts.map +1 -0
  59. package/dist/gateway-init.js +71 -0
  60. package/dist/gateway-init.js.map +1 -0
  61. package/dist/index.d.ts +2 -0
  62. package/dist/index.d.ts.map +1 -0
  63. package/dist/index.js +1242 -0
  64. package/dist/index.js.map +1 -0
  65. package/dist/infer-task-status.d.ts +7 -0
  66. package/dist/infer-task-status.d.ts.map +1 -0
  67. package/dist/infer-task-status.js +23 -0
  68. package/dist/infer-task-status.js.map +1 -0
  69. package/dist/normalize-agent-id.d.ts +21 -0
  70. package/dist/normalize-agent-id.d.ts.map +1 -0
  71. package/dist/normalize-agent-id.js +54 -0
  72. package/dist/normalize-agent-id.js.map +1 -0
  73. package/dist/openai.d.ts +14 -0
  74. package/dist/openai.d.ts.map +1 -0
  75. package/dist/openai.js +43 -0
  76. package/dist/openai.js.map +1 -0
  77. package/dist/rlm/actions.d.ts +31 -0
  78. package/dist/rlm/actions.d.ts.map +1 -0
  79. package/dist/rlm/actions.js +241 -0
  80. package/dist/rlm/actions.js.map +1 -0
  81. package/dist/rlm/benchmark.d.ts +2 -0
  82. package/dist/rlm/benchmark.d.ts.map +1 -0
  83. package/dist/rlm/benchmark.js +215 -0
  84. package/dist/rlm/benchmark.js.map +1 -0
  85. package/dist/rlm/execute.d.ts +13 -0
  86. package/dist/rlm/execute.d.ts.map +1 -0
  87. package/dist/rlm/execute.js +366 -0
  88. package/dist/rlm/execute.js.map +1 -0
  89. package/dist/rlm/index.d.ts +6 -0
  90. package/dist/rlm/index.d.ts.map +1 -0
  91. package/dist/rlm/index.js +147 -0
  92. package/dist/rlm/index.js.map +1 -0
  93. package/dist/rlm/profiles.d.ts +9 -0
  94. package/dist/rlm/profiles.d.ts.map +1 -0
  95. package/dist/rlm/profiles.js +46 -0
  96. package/dist/rlm/profiles.js.map +1 -0
  97. package/dist/rlm/types.d.ts +98 -0
  98. package/dist/rlm/types.d.ts.map +1 -0
  99. package/dist/rlm/types.js +6 -0
  100. package/dist/rlm/types.js.map +1 -0
  101. package/dist/rlm/verify.d.ts +13 -0
  102. package/dist/rlm/verify.d.ts.map +1 -0
  103. package/dist/rlm/verify.js +58 -0
  104. package/dist/rlm/verify.js.map +1 -0
  105. package/dist/rlm/writeback.d.ts +7 -0
  106. package/dist/rlm/writeback.d.ts.map +1 -0
  107. package/dist/rlm/writeback.js +77 -0
  108. package/dist/rlm/writeback.js.map +1 -0
  109. package/dist/scripts/backfill-memory-embeddings.d.ts +2 -0
  110. package/dist/scripts/backfill-memory-embeddings.d.ts.map +1 -0
  111. package/dist/scripts/backfill-memory-embeddings.js +153 -0
  112. package/dist/scripts/backfill-memory-embeddings.js.map +1 -0
  113. package/dist/session-buffer.d.ts +104 -0
  114. package/dist/session-buffer.d.ts.map +1 -0
  115. package/dist/session-buffer.js +466 -0
  116. package/dist/session-buffer.js.map +1 -0
  117. package/dist/session-dedup.d.ts +30 -0
  118. package/dist/session-dedup.d.ts.map +1 -0
  119. package/dist/session-dedup.js +67 -0
  120. package/dist/session-dedup.js.map +1 -0
  121. package/dist/session-flush.d.ts +81 -0
  122. package/dist/session-flush.d.ts.map +1 -0
  123. package/dist/session-flush.js +169 -0
  124. package/dist/session-flush.js.map +1 -0
  125. package/dist/session-lifecycle.d.ts +72 -0
  126. package/dist/session-lifecycle.d.ts.map +1 -0
  127. package/dist/session-lifecycle.js +247 -0
  128. package/dist/session-lifecycle.js.map +1 -0
  129. package/dist/setup.d.ts +2 -0
  130. package/dist/setup.d.ts.map +1 -0
  131. package/dist/setup.js +260 -0
  132. package/dist/setup.js.map +1 -0
  133. package/dist/stopwords.d.ts +2 -0
  134. package/dist/stopwords.d.ts.map +1 -0
  135. package/dist/stopwords.js +20 -0
  136. package/dist/stopwords.js.map +1 -0
  137. package/dist/strip-html.d.ts +5 -0
  138. package/dist/strip-html.d.ts.map +1 -0
  139. package/dist/strip-html.js +35 -0
  140. package/dist/strip-html.js.map +1 -0
  141. package/dist/task-completion-flush.d.ts +36 -0
  142. package/dist/task-completion-flush.d.ts.map +1 -0
  143. package/dist/task-completion-flush.js +97 -0
  144. package/dist/task-completion-flush.js.map +1 -0
  145. package/dist/task-lifecycle-types.d.ts +13 -0
  146. package/dist/task-lifecycle-types.d.ts.map +1 -0
  147. package/dist/task-lifecycle-types.js +12 -0
  148. package/dist/task-lifecycle-types.js.map +1 -0
  149. package/dist/task-lifecycle.d.ts +78 -0
  150. package/dist/task-lifecycle.d.ts.map +1 -0
  151. package/dist/task-lifecycle.js +256 -0
  152. package/dist/task-lifecycle.js.map +1 -0
  153. package/dist/tools/agent-messages.d.ts +26 -0
  154. package/dist/tools/agent-messages.d.ts.map +1 -0
  155. package/dist/tools/agent-messages.js +123 -0
  156. package/dist/tools/agent-messages.js.map +1 -0
  157. package/dist/tools/agent-tasks.d.ts +24 -0
  158. package/dist/tools/agent-tasks.d.ts.map +1 -0
  159. package/dist/tools/agent-tasks.js +162 -0
  160. package/dist/tools/agent-tasks.js.map +1 -0
  161. package/dist/tools/archive-memory.d.ts +2 -0
  162. package/dist/tools/archive-memory.d.ts.map +1 -0
  163. package/dist/tools/archive-memory.js +19 -0
  164. package/dist/tools/archive-memory.js.map +1 -0
  165. package/dist/tools/blind-index.d.ts +29 -0
  166. package/dist/tools/blind-index.d.ts.map +1 -0
  167. package/dist/tools/blind-index.js +53 -0
  168. package/dist/tools/blind-index.js.map +1 -0
  169. package/dist/tools/cleanup-memories.d.ts +44 -0
  170. package/dist/tools/cleanup-memories.d.ts.map +1 -0
  171. package/dist/tools/cleanup-memories.js +126 -0
  172. package/dist/tools/cleanup-memories.js.map +1 -0
  173. package/dist/tools/context-checkpoint.d.ts +28 -0
  174. package/dist/tools/context-checkpoint.d.ts.map +1 -0
  175. package/dist/tools/context-checkpoint.js +140 -0
  176. package/dist/tools/context-checkpoint.js.map +1 -0
  177. package/dist/tools/context-profiles.d.ts +67 -0
  178. package/dist/tools/context-profiles.d.ts.map +1 -0
  179. package/dist/tools/context-profiles.js +30 -0
  180. package/dist/tools/context-profiles.js.map +1 -0
  181. package/dist/tools/create-note.d.ts +2 -0
  182. package/dist/tools/create-note.d.ts.map +1 -0
  183. package/dist/tools/create-note.js +60 -0
  184. package/dist/tools/create-note.js.map +1 -0
  185. package/dist/tools/create-vault.d.ts +5 -0
  186. package/dist/tools/create-vault.d.ts.map +1 -0
  187. package/dist/tools/create-vault.js +121 -0
  188. package/dist/tools/create-vault.js.map +1 -0
  189. package/dist/tools/decrypt-helpers.d.ts +31 -0
  190. package/dist/tools/decrypt-helpers.d.ts.map +1 -0
  191. package/dist/tools/decrypt-helpers.js +33 -0
  192. package/dist/tools/decrypt-helpers.js.map +1 -0
  193. package/dist/tools/delete-note.d.ts +2 -0
  194. package/dist/tools/delete-note.d.ts.map +1 -0
  195. package/dist/tools/delete-note.js +21 -0
  196. package/dist/tools/delete-note.js.map +1 -0
  197. package/dist/tools/explore-graph.d.ts +11 -0
  198. package/dist/tools/explore-graph.d.ts.map +1 -0
  199. package/dist/tools/explore-graph.js +169 -0
  200. package/dist/tools/explore-graph.js.map +1 -0
  201. package/dist/tools/get-related-memories.d.ts +2 -0
  202. package/dist/tools/get-related-memories.d.ts.map +1 -0
  203. package/dist/tools/get-related-memories.js +59 -0
  204. package/dist/tools/get-related-memories.js.map +1 -0
  205. package/dist/tools/knowledge-links.d.ts +17 -0
  206. package/dist/tools/knowledge-links.d.ts.map +1 -0
  207. package/dist/tools/knowledge-links.js +102 -0
  208. package/dist/tools/knowledge-links.js.map +1 -0
  209. package/dist/tools/list-active-agents.d.ts +5 -0
  210. package/dist/tools/list-active-agents.d.ts.map +1 -0
  211. package/dist/tools/list-active-agents.js +15 -0
  212. package/dist/tools/list-active-agents.js.map +1 -0
  213. package/dist/tools/list-notes.d.ts +2 -0
  214. package/dist/tools/list-notes.d.ts.map +1 -0
  215. package/dist/tools/list-notes.js +19 -0
  216. package/dist/tools/list-notes.js.map +1 -0
  217. package/dist/tools/list-vaults.d.ts +2 -0
  218. package/dist/tools/list-vaults.d.ts.map +1 -0
  219. package/dist/tools/list-vaults.js +19 -0
  220. package/dist/tools/list-vaults.js.map +1 -0
  221. package/dist/tools/mmr.d.ts +18 -0
  222. package/dist/tools/mmr.d.ts.map +1 -0
  223. package/dist/tools/mmr.js +67 -0
  224. package/dist/tools/mmr.js.map +1 -0
  225. package/dist/tools/read-memories.d.ts +2 -0
  226. package/dist/tools/read-memories.d.ts.map +1 -0
  227. package/dist/tools/read-memories.js +46 -0
  228. package/dist/tools/read-memories.js.map +1 -0
  229. package/dist/tools/read-note.d.ts +2 -0
  230. package/dist/tools/read-note.d.ts.map +1 -0
  231. package/dist/tools/read-note.js +35 -0
  232. package/dist/tools/read-note.js.map +1 -0
  233. package/dist/tools/read-notes.d.ts +6 -0
  234. package/dist/tools/read-notes.d.ts.map +1 -0
  235. package/dist/tools/read-notes.js +45 -0
  236. package/dist/tools/read-notes.js.map +1 -0
  237. package/dist/tools/resolve-vault-id.d.ts +6 -0
  238. package/dist/tools/resolve-vault-id.d.ts.map +1 -0
  239. package/dist/tools/resolve-vault-id.js +7 -0
  240. package/dist/tools/resolve-vault-id.js.map +1 -0
  241. package/dist/tools/rrf.d.ts +28 -0
  242. package/dist/tools/rrf.d.ts.map +1 -0
  243. package/dist/tools/rrf.js +19 -0
  244. package/dist/tools/rrf.js.map +1 -0
  245. package/dist/tools/search-and-read.d.ts +11 -0
  246. package/dist/tools/search-and-read.d.ts.map +1 -0
  247. package/dist/tools/search-and-read.js +208 -0
  248. package/dist/tools/search-and-read.js.map +1 -0
  249. package/dist/tools/search-memories.d.ts +13 -0
  250. package/dist/tools/search-memories.d.ts.map +1 -0
  251. package/dist/tools/search-memories.js +272 -0
  252. package/dist/tools/search-memories.js.map +1 -0
  253. package/dist/tools/search-notes.d.ts +2 -0
  254. package/dist/tools/search-notes.d.ts.map +1 -0
  255. package/dist/tools/search-notes.js +94 -0
  256. package/dist/tools/search-notes.js.map +1 -0
  257. package/dist/tools/semantic-search.d.ts +7 -0
  258. package/dist/tools/semantic-search.d.ts.map +1 -0
  259. package/dist/tools/semantic-search.js +85 -0
  260. package/dist/tools/semantic-search.js.map +1 -0
  261. package/dist/tools/session-start.d.ts +24 -0
  262. package/dist/tools/session-start.d.ts.map +1 -0
  263. package/dist/tools/session-start.js +256 -0
  264. package/dist/tools/session-start.js.map +1 -0
  265. package/dist/tools/stale-tasks.d.ts +22 -0
  266. package/dist/tools/stale-tasks.d.ts.map +1 -0
  267. package/dist/tools/stale-tasks.js +39 -0
  268. package/dist/tools/stale-tasks.js.map +1 -0
  269. package/dist/tools/temporal-decay.d.ts +21 -0
  270. package/dist/tools/temporal-decay.d.ts.map +1 -0
  271. package/dist/tools/temporal-decay.js +32 -0
  272. package/dist/tools/temporal-decay.js.map +1 -0
  273. package/dist/tools/update-memory.d.ts +19 -0
  274. package/dist/tools/update-memory.d.ts.map +1 -0
  275. package/dist/tools/update-memory.js +230 -0
  276. package/dist/tools/update-memory.js.map +1 -0
  277. package/dist/tools/update-note.d.ts +2 -0
  278. package/dist/tools/update-note.d.ts.map +1 -0
  279. package/dist/tools/update-note.js +79 -0
  280. package/dist/tools/update-note.js.map +1 -0
  281. package/dist/tools/vault-instruction-template.d.ts +17 -0
  282. package/dist/tools/vault-instruction-template.d.ts.map +1 -0
  283. package/dist/tools/vault-instruction-template.js +77 -0
  284. package/dist/tools/vault-instruction-template.js.map +1 -0
  285. package/dist/tools/wiki-link-sync.d.ts +34 -0
  286. package/dist/tools/wiki-link-sync.d.ts.map +1 -0
  287. package/dist/tools/wiki-link-sync.js +132 -0
  288. package/dist/tools/wiki-link-sync.js.map +1 -0
  289. package/dist/tools/wrap-tool-handler.d.ts +8 -0
  290. package/dist/tools/wrap-tool-handler.d.ts.map +1 -0
  291. package/dist/tools/wrap-tool-handler.js +32 -0
  292. package/dist/tools/wrap-tool-handler.js.map +1 -0
  293. package/dist/tools/write-memory.d.ts +34 -0
  294. package/dist/tools/write-memory.d.ts.map +1 -0
  295. package/dist/tools/write-memory.js +359 -0
  296. package/dist/tools/write-memory.js.map +1 -0
  297. package/dist/usage.d.ts +11 -0
  298. package/dist/usage.d.ts.map +1 -0
  299. package/dist/usage.js +38 -0
  300. package/dist/usage.js.map +1 -0
  301. package/dist/wiki-link-parser.d.ts +27 -0
  302. package/dist/wiki-link-parser.d.ts.map +1 -0
  303. package/dist/wiki-link-parser.js +93 -0
  304. package/dist/wiki-link-parser.js.map +1 -0
  305. package/package.json +38 -0
package/dist/auth.d.ts ADDED
@@ -0,0 +1,41 @@
1
+ import { type SupabaseClient } from "@supabase/supabase-js";
2
+ export interface McpConfig {
3
+ supabaseUrl: string;
4
+ supabaseAnonKey: string;
5
+ accessToken: string;
6
+ refreshToken: string;
7
+ mekHex: string;
8
+ openaiApiKey?: string;
9
+ defaultVaultId?: string;
10
+ allowGlobalMemoryWrite?: boolean;
11
+ llmApiKey?: string;
12
+ llmBaseUrl?: string;
13
+ llmModelId?: string;
14
+ /** Agent key for gateway mode (exv_...) */
15
+ agentKey?: string;
16
+ /** Gateway base URL (default: https://exovault.co) */
17
+ apiUrl?: string;
18
+ }
19
+ export interface LlmConfig {
20
+ apiKey: string;
21
+ baseUrl: string;
22
+ modelId: string;
23
+ }
24
+ export interface McpContext {
25
+ supabase: SupabaseClient;
26
+ userId: string;
27
+ masterKey: CryptoKey;
28
+ /** Raw MEK hex for blind index key derivation (HMAC-SHA256). */
29
+ mekHex: string;
30
+ openaiApiKey?: string;
31
+ defaultVaultId?: string;
32
+ allowGlobalMemoryWrite: boolean;
33
+ /** Server-side LLM config for entity extraction and other server operations. */
34
+ llmConfig?: LlmConfig;
35
+ }
36
+ export declare function readConfig(): Promise<McpConfig>;
37
+ /**
38
+ * Reads stored config, refreshes Supabase session (with cross-process lock),
39
+ * and imports the MEK. Called once on MCP server startup.
40
+ */
41
+ export declare function initialize(): Promise<McpContext>;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAiB1E,MAAM,WAAW,SAAS;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uDAAuD;IACvD,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,cAAc,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,SAAS,CAAC;IACrB,gEAAgE;IAChE,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,sBAAsB,EAAE,OAAO,CAAC;IAChC,gFAAgF;IAChF,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB;AAgED,wBAAsB,UAAU,IAAI,OAAO,CAAC,SAAS,CAAC,CAmBrD;AAoHD;;;GAGG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,UAAU,CAAC,CAkFtD"}
package/dist/auth.js ADDED
@@ -0,0 +1,236 @@
1
+ import { createClient } from "@supabase/supabase-js";
2
+ import { readFile, writeFile, rename, open, unlink, stat } from "node:fs/promises";
3
+ import { join } from "node:path";
4
+ import { homedir } from "node:os";
5
+ import { hexToBuffer, importMasterKey } from "./crypto.js";
6
+ const CONFIG_DIR = join(homedir(), ".exovault-mcp");
7
+ const CONFIG_FILE = join(CONFIG_DIR, "config.json");
8
+ const LOCK_FILE = join(CONFIG_DIR, "refresh.lock");
9
+ /** Max age (ms) before a lock is considered stale (crashed process). */
10
+ const LOCK_STALE_MS = 10_000;
11
+ /** How long to wait between lock-retry attempts (ms). */
12
+ const LOCK_POLL_MS = 200;
13
+ /** Max total time to wait for a lock before giving up (ms). */
14
+ const LOCK_TIMEOUT_MS = 15_000;
15
+ // ── Lock helpers ──────────────────────────────────────────────────────
16
+ async function acquireLock() {
17
+ try {
18
+ // O_EXCL fails atomically if the file already exists
19
+ const handle = await open(LOCK_FILE, "wx");
20
+ await handle.writeFile(String(process.pid));
21
+ await handle.close();
22
+ return true;
23
+ }
24
+ catch (err) {
25
+ if (err instanceof Error && "code" in err && err.code === "EEXIST") {
26
+ return false;
27
+ }
28
+ throw err;
29
+ }
30
+ }
31
+ async function releaseLock() {
32
+ try {
33
+ await unlink(LOCK_FILE);
34
+ }
35
+ catch {
36
+ // Already removed — not a problem
37
+ }
38
+ }
39
+ async function isLockStale() {
40
+ try {
41
+ const info = await stat(LOCK_FILE);
42
+ return Date.now() - info.mtimeMs > LOCK_STALE_MS;
43
+ }
44
+ catch {
45
+ // Lock file gone — treat as stale so caller can proceed
46
+ return true;
47
+ }
48
+ }
49
+ /**
50
+ * Wait until we either acquire the lock or the other holder finishes.
51
+ * Returns `"acquired"` if we own the lock (caller must refresh + release),
52
+ * or `"waited"` if another process already refreshed (caller should re-read config).
53
+ */
54
+ async function waitForLock() {
55
+ const deadline = Date.now() + LOCK_TIMEOUT_MS;
56
+ while (Date.now() < deadline) {
57
+ if (await acquireLock())
58
+ return "acquired";
59
+ // Check for stale lock from a crashed process
60
+ if (await isLockStale()) {
61
+ await releaseLock();
62
+ if (await acquireLock())
63
+ return "acquired";
64
+ }
65
+ await new Promise((r) => setTimeout(r, LOCK_POLL_MS));
66
+ }
67
+ // Timeout — another process held the lock long enough that it likely refreshed
68
+ // Re-read config to get the new tokens
69
+ return "waited";
70
+ }
71
+ // ── Read config helper ────────────────────────────────────────────────
72
+ export async function readConfig() {
73
+ let configRaw;
74
+ try {
75
+ configRaw = await readFile(CONFIG_FILE, "utf-8");
76
+ }
77
+ catch {
78
+ throw new Error(`Config not found at ${CONFIG_FILE}. Run 'npx exovault-mcp setup --url <url> --key <key>' first.`);
79
+ }
80
+ const config = JSON.parse(configRaw);
81
+ // Gateway mode only needs agentKey — skip Supabase credential check
82
+ if (!config.agentKey && (!config.supabaseUrl || !config.supabaseAnonKey)) {
83
+ throw new Error(`Config is missing Supabase credentials. Re-run 'npx exovault-mcp setup --url <url> --key <key>'.`);
84
+ }
85
+ return config;
86
+ }
87
+ function isRefreshTokenAlreadyUsed(message) {
88
+ if (!message)
89
+ return false;
90
+ const normalized = message.toLowerCase();
91
+ return normalized.includes("refresh token") && normalized.includes("already used");
92
+ }
93
+ async function fallbackWithAccessToken(config) {
94
+ const supabase = createClient(config.supabaseUrl, config.supabaseAnonKey, {
95
+ auth: {
96
+ persistSession: false,
97
+ autoRefreshToken: false,
98
+ },
99
+ global: {
100
+ headers: {
101
+ Authorization: `Bearer ${config.accessToken}`,
102
+ },
103
+ },
104
+ });
105
+ const { data, error } = await supabase.auth.getUser(config.accessToken);
106
+ if (error || !data.user) {
107
+ throw new Error(`Session expired or invalid. Re-run 'npx exovault-mcp setup --url <url> --key <key>'. ${error?.message ?? ""}`);
108
+ }
109
+ return { supabase, userId: data.user.id };
110
+ }
111
+ async function setSessionWithConfig(supabase, config) {
112
+ return supabase.auth.setSession({
113
+ refresh_token: config.refreshToken,
114
+ access_token: config.accessToken,
115
+ });
116
+ }
117
+ // ── Token persistence ─────────────────────────────────────────────────
118
+ async function persistTokens(accessToken, refreshToken) {
119
+ const config = await readConfig();
120
+ const content = JSON.stringify({ ...config, accessToken, refreshToken }, null, 2);
121
+ // Atomic write: write to temp file then rename to prevent corruption on crash
122
+ const tmpFile = `${CONFIG_FILE}.tmp`;
123
+ await writeFile(tmpFile, content, { encoding: "utf-8", mode: 0o600 });
124
+ await rename(tmpFile, CONFIG_FILE);
125
+ }
126
+ // ── Refresh session (called only by lock holder) ──────────────────────
127
+ async function refreshSession(config) {
128
+ const supabase = createClient(config.supabaseUrl, config.supabaseAnonKey);
129
+ let { data: setData, error: setError } = await setSessionWithConfig(supabase, config);
130
+ // Another process may have rotated refresh token just before we acquired the lock.
131
+ // Re-read config once and retry with newest tokens.
132
+ if ((setError || !setData.session) && isRefreshTokenAlreadyUsed(setError?.message)) {
133
+ const latest = await readConfig();
134
+ ({ data: setData, error: setError } = await setSessionWithConfig(supabase, latest));
135
+ config = latest;
136
+ }
137
+ if (setError || !setData.session) {
138
+ if (isRefreshTokenAlreadyUsed(setError?.message)) {
139
+ const accessFallback = await fallbackWithAccessToken(config);
140
+ return {
141
+ supabase: accessFallback.supabase,
142
+ session: { user: { id: accessFallback.userId } },
143
+ };
144
+ }
145
+ throw new Error(`Session expired or invalid. Re-run 'npx exovault-mcp setup --url <url> --key <key>'. ${setError?.message ?? ""}`);
146
+ }
147
+ // Persist refreshed tokens so subsequent startups (or other agents) use valid tokens
148
+ await persistTokens(setData.session.access_token, setData.session.refresh_token);
149
+ return { supabase, session: setData.session };
150
+ }
151
+ // ── Public API ────────────────────────────────────────────────────────
152
+ function buildLlmConfig(config) {
153
+ const apiKey = config.llmApiKey ?? config.openaiApiKey;
154
+ if (!apiKey)
155
+ return undefined;
156
+ return {
157
+ apiKey,
158
+ baseUrl: config.llmBaseUrl ?? "https://api.openai.com/v1",
159
+ modelId: config.llmModelId ?? "gpt-4o-mini",
160
+ };
161
+ }
162
+ /**
163
+ * Reads stored config, refreshes Supabase session (with cross-process lock),
164
+ * and imports the MEK. Called once on MCP server startup.
165
+ */
166
+ export async function initialize() {
167
+ const lockResult = await waitForLock();
168
+ let config = await readConfig();
169
+ let supabase;
170
+ let userId;
171
+ if (lockResult === "acquired") {
172
+ try {
173
+ const result = await refreshSession(config);
174
+ supabase = result.supabase;
175
+ userId = result.session.user.id;
176
+ }
177
+ finally {
178
+ await releaseLock();
179
+ }
180
+ }
181
+ else {
182
+ // Another process already refreshed — re-read config with fresh tokens
183
+ config = await readConfig();
184
+ supabase = createClient(config.supabaseUrl, config.supabaseAnonKey);
185
+ let { data, error } = await setSessionWithConfig(supabase, config);
186
+ if ((error || !data.session) && isRefreshTokenAlreadyUsed(error?.message)) {
187
+ await new Promise((r) => setTimeout(r, 300));
188
+ config = await readConfig();
189
+ ({ data, error } = await setSessionWithConfig(supabase, config));
190
+ }
191
+ if (error || !data.session) {
192
+ if (isRefreshTokenAlreadyUsed(error?.message)) {
193
+ const accessFallback = await fallbackWithAccessToken(config);
194
+ userId = accessFallback.userId;
195
+ supabase = accessFallback.supabase;
196
+ // Continue using current access token for this process.
197
+ // Future startups can still refresh after setup or next token persistence cycle.
198
+ const mekBytes = hexToBuffer(config.mekHex);
199
+ const masterKey = await importMasterKey(mekBytes);
200
+ return {
201
+ supabase,
202
+ userId,
203
+ masterKey,
204
+ mekHex: config.mekHex,
205
+ openaiApiKey: config.openaiApiKey,
206
+ defaultVaultId: config.defaultVaultId,
207
+ allowGlobalMemoryWrite: config.allowGlobalMemoryWrite === true,
208
+ llmConfig: buildLlmConfig(config),
209
+ };
210
+ }
211
+ throw new Error(`Session expired after waiting for lock. Re-run 'npx exovault-mcp setup --url <url> --key <key>'. ${error?.message ?? ""}`);
212
+ }
213
+ userId = data.session.user.id;
214
+ }
215
+ // Import MEK
216
+ const mekBytes = hexToBuffer(config.mekHex);
217
+ const masterKey = await importMasterKey(mekBytes);
218
+ // Persist tokens whenever the Supabase client auto-refreshes mid-session.
219
+ // Without this, config.json goes stale and future restarts / other processes
220
+ // see expired tokens, causing silent auth failures (RLS returns empty sets).
221
+ supabase.auth.onAuthStateChange((event, session) => {
222
+ if (event === "TOKEN_REFRESHED" && session) {
223
+ persistTokens(session.access_token, session.refresh_token).then(() => process.stderr.write("[exovault-mcp] Token auto-refreshed and persisted\n"), (err) => process.stderr.write(`[exovault-mcp] Failed to persist refreshed token: ${err.message}\n`));
224
+ }
225
+ });
226
+ return {
227
+ supabase,
228
+ userId,
229
+ masterKey,
230
+ mekHex: config.mekHex,
231
+ openaiApiKey: config.openaiApiKey,
232
+ defaultVaultId: config.defaultVaultId,
233
+ allowGlobalMemoryWrite: config.allowGlobalMemoryWrite === true,
234
+ llmConfig: buildLlmConfig(config),
235
+ };
236
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Auto-session inject: ensures session context is loaded on the first tool call,
3
+ * even if the agent doesn't explicitly call `session_start`.
4
+ *
5
+ * Also tracks tool call count and appends checkpoint reminders at configurable
6
+ * thresholds, coaching agents toward better memory habits.
7
+ *
8
+ * Usage in index.ts:
9
+ * const auto = createAutoSession(() => runSessionStart());
10
+ * server.registerTool("some_tool", opts, auto.wrap(handler));
11
+ * // For session_start itself: call auto.markInjected() inside its handler
12
+ */
13
+ export type ToolResponse = {
14
+ content: {
15
+ type: "text";
16
+ text: string;
17
+ }[];
18
+ isError?: true;
19
+ };
20
+ export type SessionStartFn = () => Promise<string>;
21
+ export type LogFn = (msg: string) => void;
22
+ /**
23
+ * Callback fired on every tool call for session tracking.
24
+ * Called fire-and-forget — errors are swallowed.
25
+ */
26
+ export type TrackFn = (toolName: string) => void;
27
+ export interface AutoSessionOptions {
28
+ /** Tool call counts at which to append checkpoint reminders. Default: [25, 50, 75]. */
29
+ reminderThresholds?: number[];
30
+ /** Called on every tool call for session tracking (fire-and-forget). */
31
+ onToolCall?: TrackFn;
32
+ }
33
+ export declare function createAutoSession(runSessionStart: SessionStartFn, log?: LogFn, options?: AutoSessionOptions): {
34
+ markInjected: () => void;
35
+ isInjected: () => boolean;
36
+ getPrefix: () => Promise<string | null>;
37
+ getToolCallCount: () => number;
38
+ wrap: <T>(handler: (args: T) => Promise<ToolResponse>, toolName?: string) => (args: T) => Promise<ToolResponse>;
39
+ };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auto-session.d.ts","sourceRoot":"","sources":["../src/auto-session.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,MAAM,MAAM,YAAY,GAAG;IACzB,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC1C,OAAO,CAAC,EAAE,IAAI,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;AACnD,MAAM,MAAM,KAAK,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;AAE1C;;;GAGG;AACH,MAAM,MAAM,OAAO,GAAG,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;AAEjD,MAAM,WAAW,kBAAkB;IACjC,uFAAuF;IACvF,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC9B,wEAAwE;IACxE,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAID,wBAAgB,iBAAiB,CAC/B,eAAe,EAAE,cAAc,EAC/B,GAAG,GAAE,KAAgB,EACrB,OAAO,GAAE,kBAAuB;wBASP,IAAI;sBAKN,OAAO;qBAaF,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;4BARrB,MAAM;WAqDrB,CAAC,WACJ,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC,YAAY,CAAC,aAChC,MAAM,KAChB,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC,YAAY,CAAC;EAsDtC"}
@@ -0,0 +1,128 @@
1
+ /**
2
+ * Auto-session inject: ensures session context is loaded on the first tool call,
3
+ * even if the agent doesn't explicitly call `session_start`.
4
+ *
5
+ * Also tracks tool call count and appends checkpoint reminders at configurable
6
+ * thresholds, coaching agents toward better memory habits.
7
+ *
8
+ * Usage in index.ts:
9
+ * const auto = createAutoSession(() => runSessionStart());
10
+ * server.registerTool("some_tool", opts, auto.wrap(handler));
11
+ * // For session_start itself: call auto.markInjected() inside its handler
12
+ */
13
+ const DEFAULT_REMINDER_THRESHOLDS = [10, 25, 50];
14
+ export function createAutoSession(runSessionStart, log = () => { }, options = {}) {
15
+ let injected = false;
16
+ let toolCallCount = 0;
17
+ const thresholds = options.reminderThresholds ?? DEFAULT_REMINDER_THRESHOLDS;
18
+ const firedThresholds = new Set();
19
+ const onToolCall = options.onToolCall;
20
+ /** Mark session context as already loaded (e.g. when session_start is called explicitly). */
21
+ function markInjected() {
22
+ injected = true;
23
+ }
24
+ /** Check whether session context has been loaded (either auto or explicit). */
25
+ function isInjected() {
26
+ return injected;
27
+ }
28
+ /** Get the current tool call count (for testing/monitoring). */
29
+ function getToolCallCount() {
30
+ return toolCallCount;
31
+ }
32
+ /**
33
+ * Attempt to load session context. Returns the context string on first call,
34
+ * null on subsequent calls. Errors are swallowed — the original tool must still work.
35
+ */
36
+ async function getPrefix() {
37
+ if (injected)
38
+ return null;
39
+ injected = true;
40
+ try {
41
+ log("[exovault-mcp] Auto-injecting session context (agent did not call session_start)");
42
+ const result = await runSessionStart();
43
+ log("[exovault-mcp] Auto-session context loaded successfully");
44
+ return result;
45
+ }
46
+ catch (e) {
47
+ log(`[exovault-mcp] Auto-session context failed: ${e.message}`);
48
+ return null;
49
+ }
50
+ }
51
+ /**
52
+ * Build a checkpoint reminder suffix if the current tool call count
53
+ * just crossed a threshold. Returns null if no reminder is due.
54
+ */
55
+ function getCheckpointReminder() {
56
+ for (const threshold of thresholds) {
57
+ if (toolCallCount >= threshold && !firedThresholds.has(threshold)) {
58
+ firedThresholds.add(threshold);
59
+ return (`\n\n---\n**ExoVault Reminder** (${toolCallCount} tool calls this session): ` +
60
+ `Have you saved what you've learned? Check these triggers:\n` +
61
+ `- Preference/rule stated by user? → \`write_memory\`(preference/constraint)\n` +
62
+ `- Non-obvious fact discovered? → \`write_memory\`(fact)\n` +
63
+ `- Decision made? → \`write_memory\`(fact, importance 4-5)\n` +
64
+ `- Problem solved or procedure learned? → \`write_memory\`(skill)\n` +
65
+ `- Previous knowledge wrong? → \`write_memory\`(correction + supersededById)\n` +
66
+ `If the session is winding down, call \`context_checkpoint\` to preserve session context.`);
67
+ }
68
+ }
69
+ return null;
70
+ }
71
+ /**
72
+ * Wrap a tool handler so that the first successful tool call in this connection
73
+ * gets session context prepended to its response. Also tracks tool call count
74
+ * and appends checkpoint reminders at thresholds.
75
+ *
76
+ * @param handler - The original tool handler function.
77
+ * @param toolName - Optional tool name for session tracking (passed to onToolCall).
78
+ */
79
+ function wrap(handler, toolName) {
80
+ return async (args) => {
81
+ const prefix = await getPrefix();
82
+ const result = await handler(args);
83
+ toolCallCount++;
84
+ // Fire session tracking callback (fire-and-forget)
85
+ if (onToolCall && toolName) {
86
+ try {
87
+ onToolCall(toolName);
88
+ }
89
+ catch {
90
+ // Never fail the tool call because of tracking
91
+ }
92
+ }
93
+ // Only modify successful responses
94
+ if (result.isError)
95
+ return result;
96
+ // Auto-inject takes priority — don't also append a reminder on the same call
97
+ if (prefix) {
98
+ return {
99
+ content: [
100
+ {
101
+ type: "text",
102
+ text: `## Session Context (auto-loaded)\n\n` +
103
+ `The following context was automatically loaded because \`session_start\` was not called explicitly. ` +
104
+ `You should still follow the instructions and documents below.\n\n` +
105
+ `${prefix}\n\n` +
106
+ `---\n\n` +
107
+ `## Tool Result\n\n${result.content[0].text}`,
108
+ },
109
+ ],
110
+ };
111
+ }
112
+ // Check for checkpoint reminder
113
+ const reminder = getCheckpointReminder();
114
+ if (reminder) {
115
+ return {
116
+ content: [
117
+ {
118
+ type: "text",
119
+ text: result.content[0].text + reminder,
120
+ },
121
+ ],
122
+ };
123
+ }
124
+ return result;
125
+ };
126
+ }
127
+ return { markInjected, isInjected, getPrefix, getToolCallCount, wrap };
128
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auto-session.js","sourceRoot":"","sources":["../src/auto-session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Buffer disk persistence — crash recovery for session buffers.
3
+ *
4
+ * Writes session buffer data to disk periodically so that if the MCP process
5
+ * crashes or is killed without a clean flush, the orphaned buffer can be
6
+ * recovered on the next startup.
7
+ *
8
+ * Files: ~/.exovault-mcp/sessions/session-{agentRunId}.json
9
+ */
10
+ import type { SessionBufferData } from "./session-buffer.js";
11
+ /**
12
+ * Write session buffer data to disk for crash recovery.
13
+ * Creates the sessions directory if it doesn't exist.
14
+ */
15
+ export declare function writeBufferToDisk(data: SessionBufferData): Promise<void>;
16
+ /**
17
+ * Read a session buffer from disk by agentRunId.
18
+ * Returns null if file doesn't exist, is corrupt, or is invalid.
19
+ */
20
+ export declare function readBufferFromDisk(agentRunId: string): Promise<SessionBufferData | null>;
21
+ /**
22
+ * Delete a session buffer file after successful flush.
23
+ * Silently ignores ENOENT (file already gone).
24
+ */
25
+ export declare function deleteBuffer(agentRunId: string): Promise<void>;
26
+ /**
27
+ * Scan for orphaned session buffers that are stale and unflushed.
28
+ *
29
+ * Returns buffers where:
30
+ * - lastActivityAt is older than staleMinutes
31
+ * - lastFlushedAt is null (never flushed)
32
+ *
33
+ * Skips invalid files silently.
34
+ */
35
+ export declare function scanOrphanedBuffers(staleMinutes?: number): Promise<SessionBufferData[]>;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"buffer-persistence.d.ts","sourceRoot":"","sources":["../src/buffer-persistence.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAW7D;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAO9E;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAY9F;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CASpE;AAED;;;;;;;;GAQG;AACH,wBAAsB,mBAAmB,CACvC,YAAY,GAAE,MAA8B,GAC3C,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAgD9B"}
@@ -0,0 +1,110 @@
1
+ /**
2
+ * Buffer disk persistence — crash recovery for session buffers.
3
+ *
4
+ * Writes session buffer data to disk periodically so that if the MCP process
5
+ * crashes or is killed without a clean flush, the orphaned buffer can be
6
+ * recovered on the next startup.
7
+ *
8
+ * Files: ~/.exovault-mcp/sessions/session-{agentRunId}.json
9
+ */
10
+ import { readFile, writeFile, mkdir, unlink, readdir } from "node:fs/promises";
11
+ import { join } from "node:path";
12
+ import { homedir } from "node:os";
13
+ const CONFIG_DIR = join(homedir(), ".exovault-mcp");
14
+ const SESSIONS_DIR = join(CONFIG_DIR, "sessions");
15
+ const DEFAULT_STALE_MINUTES = 10;
16
+ function bufferPath(agentRunId) {
17
+ return join(SESSIONS_DIR, `session-${agentRunId}.json`);
18
+ }
19
+ /**
20
+ * Write session buffer data to disk for crash recovery.
21
+ * Creates the sessions directory if it doesn't exist.
22
+ */
23
+ export async function writeBufferToDisk(data) {
24
+ await mkdir(SESSIONS_DIR, { recursive: true, mode: 0o700 });
25
+ await writeFile(bufferPath(data.agentRunId), JSON.stringify(data, null, 2), { encoding: "utf-8", mode: 0o600 });
26
+ }
27
+ /**
28
+ * Read a session buffer from disk by agentRunId.
29
+ * Returns null if file doesn't exist, is corrupt, or is invalid.
30
+ */
31
+ export async function readBufferFromDisk(agentRunId) {
32
+ try {
33
+ const raw = await readFile(bufferPath(agentRunId), "utf-8");
34
+ const parsed = JSON.parse(raw);
35
+ // Basic validation — must have agentRunId
36
+ if (!parsed || typeof parsed.agentRunId !== "string") {
37
+ return null;
38
+ }
39
+ return parsed;
40
+ }
41
+ catch {
42
+ return null;
43
+ }
44
+ }
45
+ /**
46
+ * Delete a session buffer file after successful flush.
47
+ * Silently ignores ENOENT (file already gone).
48
+ */
49
+ export async function deleteBuffer(agentRunId) {
50
+ try {
51
+ await unlink(bufferPath(agentRunId));
52
+ }
53
+ catch (e) {
54
+ if (e && typeof e === "object" && "code" in e && e.code === "ENOENT") {
55
+ return; // Already deleted — fine
56
+ }
57
+ throw e;
58
+ }
59
+ }
60
+ /**
61
+ * Scan for orphaned session buffers that are stale and unflushed.
62
+ *
63
+ * Returns buffers where:
64
+ * - lastActivityAt is older than staleMinutes
65
+ * - lastFlushedAt is null (never flushed)
66
+ *
67
+ * Skips invalid files silently.
68
+ */
69
+ export async function scanOrphanedBuffers(staleMinutes = DEFAULT_STALE_MINUTES) {
70
+ // Ensure directory exists
71
+ await mkdir(SESSIONS_DIR, { recursive: true, mode: 0o700 });
72
+ let files;
73
+ try {
74
+ files = (await readdir(SESSIONS_DIR));
75
+ }
76
+ catch {
77
+ return [];
78
+ }
79
+ const staleThreshold = Date.now() - staleMinutes * 60_000;
80
+ const orphans = [];
81
+ for (const file of files) {
82
+ // Only process session-*.json files
83
+ if (!file.startsWith("session-") || !file.endsWith(".json")) {
84
+ continue;
85
+ }
86
+ try {
87
+ const raw = await readFile(join(SESSIONS_DIR, file), "utf-8");
88
+ const parsed = JSON.parse(raw);
89
+ // Validate basic shape
90
+ if (!parsed || typeof parsed.agentRunId !== "string") {
91
+ continue;
92
+ }
93
+ const data = parsed;
94
+ // Skip already flushed
95
+ if (data.lastFlushedAt) {
96
+ continue;
97
+ }
98
+ // Check staleness
99
+ const lastActivity = new Date(data.lastActivityAt).getTime();
100
+ if (lastActivity < staleThreshold) {
101
+ orphans.push(data);
102
+ }
103
+ }
104
+ catch {
105
+ // Invalid file — skip silently
106
+ continue;
107
+ }
108
+ }
109
+ return orphans;
110
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"buffer-persistence.js","sourceRoot":"","sources":["../src/buffer-persistence.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC/E,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAGlC,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,eAAe,CAAC,CAAC;AACpD,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;AAElD,MAAM,qBAAqB,GAAG,EAAE,CAAC;AAEjC,SAAS,UAAU,CAAC,UAAkB;IACpC,OAAO,IAAI,CAAC,YAAY,EAAE,WAAW,UAAU,OAAO,CAAC,CAAC;AAC1D,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,IAAuB;IAC7D,MAAM,KAAK,CAAC,YAAY,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC5D,MAAM,SAAS,CACb,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,EAC3B,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAC7B,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CACnC,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,UAAkB;IACzD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC,CAAC;QAC5D,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC/B,0CAA0C;QAC1C,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,CAAC,UAAU,KAAK,QAAQ,EAAE,CAAC;YACrD,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,MAA2B,CAAC;IACrC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,UAAkB;IACnD,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC;IACvC,CAAC;IAAC,OAAO,CAAU,EAAE,CAAC;QACpB,IAAI,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACrE,OAAO,CAAC,yBAAyB;QACnC,CAAC;QACD,MAAM,CAAC,CAAC;IACV,CAAC;AACH,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,eAAuB,qBAAqB;IAE5C,0BAA0B;IAC1B,MAAM,KAAK,CAAC,YAAY,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAE5D,IAAI,KAAe,CAAC;IACpB,IAAI,CAAC;QACH,KAAK,GAAG,CAAC,MAAM,OAAO,CAAC,YAAY,CAAC,CAAwB,CAAC;IAC/D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,YAAY,GAAG,MAAM,CAAC;IAC1D,MAAM,OAAO,GAAwB,EAAE,CAAC;IAExC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,oCAAoC;QACpC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;YAC5D,SAAS;QACX,CAAC;QAED,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC;YAC9D,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAE/B,uBAAuB;YACvB,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,CAAC,UAAU,KAAK,QAAQ,EAAE,CAAC;gBACrD,SAAS;YACX,CAAC;YAED,MAAM,IAAI,GAAG,MAA2B,CAAC;YAEzC,uBAAuB;YACvB,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;gBACvB,SAAS;YACX,CAAC;YAED,kBAAkB;YAClB,MAAM,YAAY,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,OAAO,EAAE,CAAC;YAC7D,IAAI,YAAY,GAAG,cAAc,EAAE,CAAC;gBAClC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACrB,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,+BAA+B;YAC/B,SAAS;QACX,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC"}