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
@@ -0,0 +1,230 @@
1
+ import { getMemoriesByIds, updateMemory as dbUpdateMemory, bulkInsertKnowledgeLinks, deleteLinksForNode, } from "../db.js";
2
+ import { encrypt, decrypt } from "../crypto.js";
3
+ import { extractEntities } from "../entity-extraction.js";
4
+ import { generateBlindTokens } from "./blind-index.js";
5
+ import { generateEmbeddings } from "../openai.js";
6
+ import { logMcpUsageEvent } from "../usage.js";
7
+ import { resolveEmbeddingConfig } from "../embedding-config.js";
8
+ import { syncWikiLinks, deleteWikiLinksForNode } from "./wiki-link-sync.js";
9
+ const VECTOR_DIMS = 1536;
10
+ const CHARS_PER_TOKEN = 4;
11
+ const CHUNK_TARGET_CHARS = 2400;
12
+ const CHUNK_OVERLAP_CHARS = 400;
13
+ function estimateTokens(text) {
14
+ return Math.ceil(text.length / CHARS_PER_TOKEN);
15
+ }
16
+ function chunkText(plaintext) {
17
+ const text = plaintext.trim();
18
+ if (!text)
19
+ return [];
20
+ if (text.length <= CHUNK_TARGET_CHARS)
21
+ return [{ text, index: 0 }];
22
+ const chunks = [];
23
+ let start = 0;
24
+ let idx = 0;
25
+ while (start < text.length) {
26
+ const end = Math.min(start + CHUNK_TARGET_CHARS, text.length);
27
+ chunks.push({ text: text.slice(start, end).trim(), index: idx++ });
28
+ if (end >= text.length)
29
+ break;
30
+ start = Math.max(0, end - CHUNK_OVERLAP_CHARS);
31
+ }
32
+ return chunks;
33
+ }
34
+ export async function updateMemoryTool(ctx, input) {
35
+ // Fetch existing memory to verify ownership
36
+ const [existing] = await getMemoriesByIds(ctx.supabase, ctx.userId, [input.memoryId]);
37
+ if (!existing) {
38
+ throw new Error("Memory not found");
39
+ }
40
+ const updates = {};
41
+ let contentChanged = false;
42
+ // Encrypt new content if provided
43
+ if (input.content !== undefined) {
44
+ const enc = await encrypt(input.content, ctx.masterKey);
45
+ updates.encrypted_content = enc.ciphertext;
46
+ updates.content_iv = enc.iv;
47
+ contentChanged = true;
48
+ }
49
+ // Encrypt new summary if provided
50
+ if (input.summary !== undefined) {
51
+ if (input.summary) {
52
+ const enc = await encrypt(input.summary, ctx.masterKey);
53
+ updates.encrypted_summary = enc.ciphertext;
54
+ updates.summary_iv = enc.iv;
55
+ }
56
+ else {
57
+ // Empty string = clear summary
58
+ updates.encrypted_summary = null;
59
+ updates.summary_iv = null;
60
+ }
61
+ contentChanged = true;
62
+ }
63
+ if (input.memoryType !== undefined)
64
+ updates.memory_type = input.memoryType;
65
+ if (input.importance !== undefined)
66
+ updates.importance = input.importance;
67
+ if (input.confidence !== undefined)
68
+ updates.confidence = input.confidence;
69
+ if (input.relatedMemoryIds !== undefined)
70
+ updates.related_memory_ids = input.relatedMemoryIds;
71
+ if (input.sourceNoteIds !== undefined)
72
+ updates.source_note_ids = input.sourceNoteIds;
73
+ if (input.isArchived !== undefined)
74
+ updates.is_archived = input.isArchived;
75
+ // Merge metadata (task-specific fields like taskStatus, assignedAgentId)
76
+ if (input.metadata !== undefined) {
77
+ const existingMeta = (existing.metadata ?? {});
78
+ updates.metadata = { ...existingMeta, ...input.metadata };
79
+ }
80
+ // Auto-extract entities if content changed and no explicit entities provided
81
+ if (input.entities !== undefined) {
82
+ updates.entities = input.entities;
83
+ }
84
+ else if (contentChanged && input.content) {
85
+ const extracted = await extractEntities(ctx, input.content, input.summary);
86
+ if (extracted)
87
+ updates.entities = extracted;
88
+ }
89
+ // Regenerate blind index tokens when content changes
90
+ if (contentChanged && input.content) {
91
+ const blindTokens = generateBlindTokens(input.content, ctx.mekHex);
92
+ if (blindTokens.length > 0)
93
+ updates.blind_tokens = blindTokens;
94
+ }
95
+ // Mark for re-indexing if content changed
96
+ if (contentChanged) {
97
+ updates.indexing_status = "pending";
98
+ }
99
+ if (Object.keys(updates).length === 0) {
100
+ return JSON.stringify({ memoryId: input.memoryId, updated: false, reason: "no_changes" });
101
+ }
102
+ const updated = await dbUpdateMemory(ctx.supabase, input.memoryId, ctx.userId, updates);
103
+ // Dual-write: sync knowledge_links when relationship params change
104
+ if (input.relatedMemoryIds !== undefined || input.sourceNoteIds !== undefined) {
105
+ try {
106
+ await deleteLinksForNode(ctx.supabase, ctx.userId, "memory", input.memoryId);
107
+ const links = [];
108
+ const relIds = input.relatedMemoryIds ?? existing.related_memory_ids;
109
+ if (relIds?.length) {
110
+ for (const rel of relIds) {
111
+ links.push({
112
+ user_id: ctx.userId,
113
+ source_type: "memory",
114
+ source_id: input.memoryId,
115
+ target_type: "memory",
116
+ target_id: rel.memoryId,
117
+ relation_type: rel.relationType,
118
+ created_by: "agent",
119
+ });
120
+ }
121
+ }
122
+ const noteIds = input.sourceNoteIds ?? existing.source_note_ids;
123
+ if (noteIds?.length) {
124
+ for (const noteId of noteIds) {
125
+ links.push({
126
+ user_id: ctx.userId,
127
+ source_type: "memory",
128
+ source_id: input.memoryId,
129
+ target_type: "note",
130
+ target_id: noteId,
131
+ relation_type: "source_of",
132
+ created_by: "agent",
133
+ });
134
+ }
135
+ }
136
+ if (links.length > 0) {
137
+ await bulkInsertKnowledgeLinks(ctx.supabase, links);
138
+ }
139
+ }
140
+ catch (err) {
141
+ process.stderr.write(`[update-memory] knowledge_links sync failed: ${err instanceof Error ? err.message : String(err)}\n`);
142
+ }
143
+ }
144
+ // Re-sync wiki-links when content changes
145
+ if (contentChanged && input.content) {
146
+ await deleteWikiLinksForNode(ctx.supabase, ctx.userId, "memory", input.memoryId);
147
+ await syncWikiLinks(ctx.supabase, "memory", input.memoryId, ctx.userId, input.content, updated.vault_id ?? null, ctx.masterKey);
148
+ }
149
+ // Re-index embeddings if content changed
150
+ let indexed = false;
151
+ let embeddingCount = 0;
152
+ let indexingReason;
153
+ if (contentChanged) {
154
+ const plainContent = input.content
155
+ ?? await decrypt(existing.encrypted_content, existing.content_iv, ctx.masterKey);
156
+ const plainSummary = input.summary !== undefined
157
+ ? input.summary || undefined
158
+ : existing.encrypted_summary && existing.summary_iv
159
+ ? await decrypt(existing.encrypted_summary, existing.summary_iv, ctx.masterKey).catch(() => undefined)
160
+ : undefined;
161
+ const embeddingConfig = resolveEmbeddingConfig(ctx);
162
+ if (embeddingConfig) {
163
+ const base = plainSummary
164
+ ? `Summary: ${plainSummary.trim()}\n\n${plainContent.trim()}`
165
+ : plainContent.trim();
166
+ const chunks = chunkText(base);
167
+ if (chunks.length > 0) {
168
+ try {
169
+ const vectors = await generateEmbeddings(chunks.map((c) => c.text), embeddingConfig.apiKey, { baseUrl: embeddingConfig.baseUrl, model: embeddingConfig.model });
170
+ const badVector = vectors.find((v) => v.length !== VECTOR_DIMS);
171
+ if (badVector) {
172
+ throw new Error(`embedding_dimensions_mismatch expected=${VECTOR_DIMS} got=${badVector.length}`);
173
+ }
174
+ // Import replaceMemoryEmbeddings lazily to avoid circular dependency risk
175
+ const { replaceMemoryEmbeddings } = await import("../db.js");
176
+ const { createHash } = await import("node:crypto");
177
+ const contentHash = createHash("sha256")
178
+ .update(chunks.map((c) => c.text).join("\n\n"), "utf8")
179
+ .digest("hex");
180
+ await replaceMemoryEmbeddings(ctx.supabase, {
181
+ memoryId: input.memoryId,
182
+ userId: ctx.userId,
183
+ embeddingModel: embeddingConfig.model,
184
+ contentHash,
185
+ rows: vectors.map((embedding, i) => ({
186
+ chunkIndex: chunks[i]?.index ?? i,
187
+ embedding,
188
+ tokenCount: estimateTokens(chunks[i]?.text ?? ""),
189
+ })),
190
+ });
191
+ await dbUpdateMemory(ctx.supabase, input.memoryId, ctx.userId, {
192
+ indexing_status: "ready",
193
+ last_indexed_at: new Date().toISOString(),
194
+ indexing_error: null,
195
+ });
196
+ indexed = true;
197
+ embeddingCount = vectors.length;
198
+ }
199
+ catch (error) {
200
+ const message = error instanceof Error ? error.message.slice(0, 2000) : "embedding_failed";
201
+ await dbUpdateMemory(ctx.supabase, input.memoryId, ctx.userId, {
202
+ indexing_status: "failed",
203
+ indexing_error: message,
204
+ });
205
+ indexingReason = message;
206
+ }
207
+ }
208
+ }
209
+ else {
210
+ indexingReason = "missing_embedding_api_key";
211
+ }
212
+ }
213
+ const payload = JSON.stringify({
214
+ memoryId: updated.id,
215
+ updated: true,
216
+ contentChanged,
217
+ indexed,
218
+ embeddingCount,
219
+ indexingReason: indexingReason ?? null,
220
+ });
221
+ await logMcpUsageEvent({
222
+ supabase: ctx.supabase,
223
+ userId: ctx.userId,
224
+ vaultId: updated.vault_id ?? undefined,
225
+ operationType: "mcp_update_memory",
226
+ inputText: input.content,
227
+ outputText: payload,
228
+ });
229
+ return payload;
230
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update-memory.js","sourceRoot":"","sources":["../../src/tools/update-memory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { McpContext } from "../auth.js";
2
+ export declare function updateNote(ctx: McpContext, noteId: string, title?: string, content?: string, tags?: string[]): Promise<string>;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update-note.d.ts","sourceRoot":"","sources":["../../src/tools/update-note.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAM7C,wBAAsB,UAAU,CAC9B,GAAG,EAAE,UAAU,EACf,MAAM,EAAE,MAAM,EACd,KAAK,CAAC,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,MAAM,EAChB,IAAI,CAAC,EAAE,MAAM,EAAE,GACd,OAAO,CAAC,MAAM,CAAC,CAmFjB"}
@@ -0,0 +1,79 @@
1
+ import { getNote, updateNote as dbUpdateNote, resolvePendingLinks } from "../db.js";
2
+ import { encrypt, decrypt, hashPendingTarget } from "../crypto.js";
3
+ import { generateBlindTokens } from "./blind-index.js";
4
+ import { syncWikiLinks, deleteWikiLinksForNode } from "./wiki-link-sync.js";
5
+ export async function updateNote(ctx, noteId, title, content, tags) {
6
+ // Verify note exists and belongs to user
7
+ const note = await getNote(ctx.supabase, ctx.userId, noteId);
8
+ if (!note) {
9
+ return JSON.stringify({ success: false, error: "Note not found" });
10
+ }
11
+ const updates = {};
12
+ if (title !== undefined) {
13
+ const enc = await encrypt(title, ctx.masterKey);
14
+ updates.encrypted_title = enc.ciphertext;
15
+ updates.title_iv = enc.iv;
16
+ }
17
+ if (content !== undefined) {
18
+ const htmlContent = content.includes("<")
19
+ ? content
20
+ : `<p>${content}</p>`;
21
+ const enc = await encrypt(htmlContent, ctx.masterKey);
22
+ updates.encrypted_content = enc.ciphertext;
23
+ updates.content_iv = enc.iv;
24
+ updates.embedding_status = "stale";
25
+ }
26
+ if (tags !== undefined) {
27
+ const enc = await encrypt(JSON.stringify(tags), ctx.masterKey);
28
+ updates.encrypted_tags = enc.ciphertext;
29
+ updates.tags_iv = enc.iv;
30
+ // Tags change also makes embeddings stale
31
+ if (!updates.embedding_status) {
32
+ updates.embedding_status = "stale";
33
+ }
34
+ }
35
+ if (Object.keys(updates).length === 0) {
36
+ return JSON.stringify({ success: true, message: "No changes provided" });
37
+ }
38
+ // Regenerate blind tokens from all fields (current + updated)
39
+ if (ctx.mekHex && (title !== undefined || content !== undefined || tags !== undefined)) {
40
+ try {
41
+ const currentTitle = title ?? await decrypt(note.encrypted_title, note.title_iv, ctx.masterKey);
42
+ const currentContent = content ?? await decrypt(note.encrypted_content, note.content_iv, ctx.masterKey);
43
+ let currentTags = [];
44
+ if (tags !== undefined) {
45
+ currentTags = tags;
46
+ }
47
+ else if (note.encrypted_tags && note.tags_iv) {
48
+ try {
49
+ currentTags = JSON.parse(await decrypt(note.encrypted_tags, note.tags_iv, ctx.masterKey));
50
+ }
51
+ catch { /* ignore */ }
52
+ }
53
+ const searchableText = [currentTitle, currentContent, ...currentTags].join(" ");
54
+ const blindTokens = generateBlindTokens(searchableText, ctx.mekHex);
55
+ if (blindTokens.length > 0) {
56
+ updates.blind_tokens = blindTokens;
57
+ }
58
+ }
59
+ catch { /* blind token generation is best-effort */ }
60
+ }
61
+ await dbUpdateNote(ctx.supabase, noteId, ctx.userId, updates);
62
+ // Re-sync wiki-links when content changes
63
+ if (content !== undefined) {
64
+ await deleteWikiLinksForNode(ctx.supabase, ctx.userId, "note", noteId);
65
+ await syncWikiLinks(ctx.supabase, "note", noteId, ctx.userId, content, note.vault_id, ctx.masterKey);
66
+ }
67
+ // Resolve pending wiki-links when title changes
68
+ if (title !== undefined) {
69
+ try {
70
+ const titleHash = hashPendingTarget(title);
71
+ const hashMap = new Map([[titleHash, noteId]]);
72
+ await resolvePendingLinks(ctx.supabase, ctx.userId, hashMap);
73
+ }
74
+ catch {
75
+ // Best-effort
76
+ }
77
+ }
78
+ return JSON.stringify({ success: true });
79
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update-note.js","sourceRoot":"","sources":["../../src/tools/update-note.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ export declare const VAULT_INSTRUCTION_VERSION = 4;
2
+ export interface VaultInstructionTemplate {
3
+ noteTitle: string;
4
+ noteContent: string;
5
+ noteTags: string[];
6
+ memoryType: string;
7
+ memorySummary: string;
8
+ memoryContent: string;
9
+ importance: number;
10
+ confidence: number;
11
+ }
12
+ export declare function getVaultInstructionTemplate(vaultName?: string): VaultInstructionTemplate;
13
+ export declare function getVaultInstructionIds(vaultId: string): {
14
+ noteImportSource: string;
15
+ noteImportSourceId: string;
16
+ memoryExternalWriteId: string;
17
+ };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vault-instruction-template.d.ts","sourceRoot":"","sources":["../../src/tools/vault-instruction-template.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,yBAAyB,IAAI,CAAC;AAE3C,MAAM,WAAW,wBAAwB;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,2BAA2B,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,wBAAwB,CAqExF;AAED,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM;;;;EAOrD"}
@@ -0,0 +1,77 @@
1
+ // SYNC NOTE: Keep this file in sync with src/lib/memory/vault-instruction-template.ts
2
+ export const VAULT_INSTRUCTION_VERSION = 4;
3
+ export function getVaultInstructionTemplate(vaultName) {
4
+ const scopeLabel = vaultName?.trim() ? `for vault "${vaultName.trim()}"` : "for this vault";
5
+ const noteTitle = "Agent Memory Instructions";
6
+ const memorySummary = `System instructions v${VAULT_INSTRUCTION_VERSION} ${scopeLabel}.`;
7
+ // v4: Slimmed to core protocol only. Detailed reference (memory types, relationship
8
+ // fields, importance guide, etc.) moved to instructions.md default document, which
9
+ // is returned once per session via session_start instead of on every tool call.
10
+ const memoryContent = [
11
+ `ExoVault Memory Protocol v${VAULT_INSTRUCTION_VERSION}`,
12
+ "",
13
+ "## Core Protocol",
14
+ "1. Scope all memory operations to the relevant vaultId.",
15
+ "2. SEARCH FIRST: Run search_memories before writing to check for existing entries.",
16
+ "3. Use externalWriteId for idempotency on every write.",
17
+ "4. Set importance (1-5) and confidence (1-5) on every write.",
18
+ "5. Extract entities (people, projects, tools) and include them in the entities field.",
19
+ "6. Link related memories using relatedMemoryIds with appropriate relation types.",
20
+ "7. When correcting knowledge, create a new memory with supersededById pointing to the old one.",
21
+ "",
22
+ "Memory types: fact, skill, preference, constraint, task, episodic, correction.",
23
+ "Set dedup: true for server-side semantic dedup. Use compact: true on search, then read_memories for full content.",
24
+ "Include agentId and agentRunId on every write. See instructions.md for full type reference and examples.",
25
+ "",
26
+ "## Episodic Memory Quality",
27
+ "End-of-session episodic memories must capture WHAT was discussed, decided, and accomplished — not tool call stats.",
28
+ "Good: \"Discussed auth architecture. Decided on JWT with refresh tokens over session cookies. Created Auth Design note and planned OAuth implementation.\"",
29
+ "Bad: \"Session: 16min, 8 tool calls. Searched: auth. Wrote 2 items.\"",
30
+ "Include: topics explored, decisions made, outcomes/artifacts produced, unresolved questions for next session.",
31
+ ].join("\n");
32
+ const noteContent = [
33
+ "# Agent Memory Instructions",
34
+ "",
35
+ `Instruction version: ${VAULT_INSTRUCTION_VERSION}`,
36
+ "",
37
+ "Use this protocol whenever an agent reads or writes long-term memory:",
38
+ "",
39
+ "1. Set `vaultId` on every memory call.",
40
+ "2. Read-first workflow:",
41
+ " - run semantic/keyword memory search for the task",
42
+ " - use entity search to find related knowledge",
43
+ " - read the top matching memory entries before planning actions",
44
+ "3. Write workflow:",
45
+ " - use the correct memoryType (fact, skill, preference, constraint, task, episodic, correction)",
46
+ " - include `externalWriteId` for idempotency",
47
+ " - set `importance` and `confidence` explicitly (1-5)",
48
+ " - extract and include `entities` for cross-linking",
49
+ " - link to related memories with `relatedMemoryIds`",
50
+ " - track source notes with `sourceNoteIds`",
51
+ "4. Correction workflow:",
52
+ " - when knowledge changes, create a new memory with type `correction`",
53
+ " - set `supersededById` on the new memory to point to the old one",
54
+ " - the system will automatically archive the old memory",
55
+ "5. Exploration workflow:",
56
+ " - use `get_related_memories` to traverse the knowledge graph",
57
+ " - use entity search to find all memories about a topic",
58
+ ].join("\n");
59
+ return {
60
+ noteTitle,
61
+ noteContent,
62
+ noteTags: ["system", "instruction", "memory-protocol", `v${VAULT_INSTRUCTION_VERSION}`],
63
+ memoryType: "instruction",
64
+ memorySummary,
65
+ memoryContent,
66
+ importance: 5,
67
+ confidence: 5,
68
+ };
69
+ }
70
+ export function getVaultInstructionIds(vaultId) {
71
+ const base = `system:vault:${vaultId}:instruction:v${VAULT_INSTRUCTION_VERSION}`;
72
+ return {
73
+ noteImportSource: "system_seed",
74
+ noteImportSourceId: `${base}:note`,
75
+ memoryExternalWriteId: `${base}:memory`,
76
+ };
77
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vault-instruction-template.js","sourceRoot":"","sources":["../../src/tools/vault-instruction-template.ts"],"names":[],"mappings":"AAAA,sFAAsF;AAEtF,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,CAAC;AAa3C,MAAM,UAAU,2BAA2B,CAAC,SAAkB;IAC5D,MAAM,UAAU,GAAG,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,cAAc,SAAS,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,gBAAgB,CAAC;IAC5F,MAAM,SAAS,GAAG,2BAA2B,CAAC;IAC9C,MAAM,aAAa,GAAG,wBAAwB,yBAAyB,IAAI,UAAU,GAAG,CAAC;IAEzF,oFAAoF;IACpF,mFAAmF;IACnF,gFAAgF;IAChF,MAAM,aAAa,GAAG;QACpB,6BAA6B,yBAAyB,EAAE;QACxD,EAAE;QACF,kBAAkB;QAClB,yDAAyD;QACzD,oFAAoF;QACpF,wDAAwD;QACxD,8DAA8D;QAC9D,uFAAuF;QACvF,kFAAkF;QAClF,gGAAgG;QAChG,EAAE;QACF,gFAAgF;QAChF,mHAAmH;QACnH,0GAA0G;QAC1G,EAAE;QACF,4BAA4B;QAC5B,oHAAoH;QACpH,4JAA4J;QAC5J,uEAAuE;QACvE,+GAA+G;KAChH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEb,MAAM,WAAW,GAAG;QAClB,6BAA6B;QAC7B,EAAE;QACF,wBAAwB,yBAAyB,EAAE;QACnD,EAAE;QACF,uEAAuE;QACvE,EAAE;QACF,wCAAwC;QACxC,yBAAyB;QACzB,sDAAsD;QACtD,kDAAkD;QAClD,mEAAmE;QACnE,oBAAoB;QACpB,mGAAmG;QACnG,gDAAgD;QAChD,yDAAyD;QACzD,uDAAuD;QACvD,uDAAuD;QACvD,8CAA8C;QAC9C,yBAAyB;QACzB,yEAAyE;QACzE,qEAAqE;QACrE,2DAA2D;QAC3D,0BAA0B;QAC1B,iEAAiE;QACjE,2DAA2D;KAC5D,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEb,OAAO;QACL,SAAS;QACT,WAAW;QACX,QAAQ,EAAE,CAAC,QAAQ,EAAE,aAAa,EAAE,iBAAiB,EAAE,IAAI,yBAAyB,EAAE,CAAC;QACvF,UAAU,EAAE,aAAa;QACzB,aAAa;QACb,aAAa;QACb,UAAU,EAAE,CAAC;QACb,UAAU,EAAE,CAAC;KACd,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,OAAe;IACpD,MAAM,IAAI,GAAG,gBAAgB,OAAO,iBAAiB,yBAAyB,EAAE,CAAC;IACjF,OAAO;QACL,gBAAgB,EAAE,aAAa;QAC/B,kBAAkB,EAAE,GAAG,IAAI,OAAO;QAClC,qBAAqB,EAAE,GAAG,IAAI,SAAS;KACxC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Write-time wiki-link parsing for memories and notes.
3
+ *
4
+ * Extracts [[wiki-links]] from plaintext content and creates knowledge_links
5
+ * entries. Resolved links point to existing notes; unresolved links are stored
6
+ * as pending with a SHA-256 hash for later resolution.
7
+ *
8
+ * Best-effort: errors are logged but never fail the parent write operation.
9
+ */
10
+ import type { SupabaseClient } from "@supabase/supabase-js";
11
+ type NodeType = "note" | "memory";
12
+ export interface WikiLinkSyncResult {
13
+ resolved: number;
14
+ pending: number;
15
+ }
16
+ /**
17
+ * Parse [[wiki-links]] from plaintext content and create knowledge_links rows.
18
+ *
19
+ * @param supabase - Supabase client (authenticated)
20
+ * @param sourceType - "note" or "memory"
21
+ * @param sourceId - ID of the source node
22
+ * @param userId - Owner user ID
23
+ * @param plaintext - Decrypted content to parse for wiki-links
24
+ * @param vaultId - Vault scope for note title resolution (null = all vaults)
25
+ * @param masterKey - CryptoKey for decrypting note titles; if undefined, all links become pending
26
+ */
27
+ export declare function syncWikiLinks(supabase: SupabaseClient, sourceType: NodeType, sourceId: string, userId: string, plaintext: string, vaultId?: string | null, masterKey?: CryptoKey): Promise<WikiLinkSyncResult>;
28
+ /**
29
+ * Delete only wiki_link-type outgoing links for a node.
30
+ * Used before re-syncing when content changes (update operations).
31
+ * Best-effort: errors are logged but do not propagate.
32
+ */
33
+ export declare function deleteWikiLinksForNode(supabase: SupabaseClient, userId: string, nodeType: NodeType, nodeId: string): Promise<void>;
34
+ export {};
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wiki-link-sync.d.ts","sourceRoot":"","sources":["../../src/tools/wiki-link-sync.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAK5D,KAAK,QAAQ,GAAG,MAAM,GAAG,QAAQ,CAAC;AAQlC,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,aAAa,CACjC,QAAQ,EAAE,cAAc,EACxB,UAAU,EAAE,QAAQ,EACpB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,EACvB,SAAS,CAAC,EAAE,SAAS,GACpB,OAAO,CAAC,kBAAkB,CAAC,CAsF7B;AAED;;;;GAIG;AACH,wBAAsB,sBAAsB,CAC1C,QAAQ,EAAE,cAAc,EACxB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CAmBf"}
@@ -0,0 +1,132 @@
1
+ /**
2
+ * Write-time wiki-link parsing for memories and notes.
3
+ *
4
+ * Extracts [[wiki-links]] from plaintext content and creates knowledge_links
5
+ * entries. Resolved links point to existing notes; unresolved links are stored
6
+ * as pending with a SHA-256 hash for later resolution.
7
+ *
8
+ * Best-effort: errors are logged but never fail the parent write operation.
9
+ */
10
+ import { extractWikiLinks, normalizeWikiLinkTarget } from "../wiki-link-parser.js";
11
+ import { decrypt, hashPendingTarget } from "../crypto.js";
12
+ import { getNotes, bulkInsertKnowledgeLinks } from "../db.js";
13
+ /** Placeholder UUID for pending links (target not yet resolved). */
14
+ const PENDING_TARGET_ID = "00000000-0000-0000-0000-000000000000";
15
+ /** Maximum number of note titles to load for resolution. */
16
+ const NOTE_TITLE_LIMIT = 500;
17
+ /**
18
+ * Parse [[wiki-links]] from plaintext content and create knowledge_links rows.
19
+ *
20
+ * @param supabase - Supabase client (authenticated)
21
+ * @param sourceType - "note" or "memory"
22
+ * @param sourceId - ID of the source node
23
+ * @param userId - Owner user ID
24
+ * @param plaintext - Decrypted content to parse for wiki-links
25
+ * @param vaultId - Vault scope for note title resolution (null = all vaults)
26
+ * @param masterKey - CryptoKey for decrypting note titles; if undefined, all links become pending
27
+ */
28
+ export async function syncWikiLinks(supabase, sourceType, sourceId, userId, plaintext, vaultId, masterKey) {
29
+ const wikiLinks = extractWikiLinks(plaintext);
30
+ if (wikiLinks.length === 0)
31
+ return { resolved: 0, pending: 0 };
32
+ // Deduplicate by normalized target name
33
+ const seen = new Set();
34
+ const uniqueTargets = [];
35
+ for (const wl of wikiLinks) {
36
+ const normalized = normalizeWikiLinkTarget(wl.target);
37
+ if (!normalized || seen.has(normalized))
38
+ continue;
39
+ seen.add(normalized);
40
+ uniqueTargets.push(normalized);
41
+ }
42
+ if (uniqueTargets.length === 0)
43
+ return { resolved: 0, pending: 0 };
44
+ // Build a normalized-title → noteId map by decrypting existing note titles
45
+ const titleMap = new Map();
46
+ if (masterKey) {
47
+ try {
48
+ const noteRows = await getNotes(supabase, userId, vaultId ?? undefined, NOTE_TITLE_LIMIT);
49
+ for (const note of noteRows) {
50
+ try {
51
+ const title = await decrypt(note.encrypted_title, note.title_iv, masterKey);
52
+ const normalized = normalizeWikiLinkTarget(title);
53
+ if (normalized) {
54
+ titleMap.set(normalized, note.id);
55
+ }
56
+ }
57
+ catch {
58
+ // Skip notes that fail to decrypt
59
+ }
60
+ }
61
+ }
62
+ catch {
63
+ // If note fetch fails entirely, all links become pending — that's fine
64
+ }
65
+ }
66
+ // Resolve each unique wiki-link target
67
+ const links = [];
68
+ let resolved = 0;
69
+ let pending = 0;
70
+ for (const normalized of uniqueTargets) {
71
+ const noteId = titleMap.get(normalized);
72
+ if (noteId) {
73
+ links.push({
74
+ user_id: userId,
75
+ source_type: sourceType,
76
+ source_id: sourceId,
77
+ target_type: "note",
78
+ target_id: noteId,
79
+ relation_type: "wiki_link",
80
+ is_pending: false,
81
+ created_by: "wiki-link-sync",
82
+ });
83
+ resolved++;
84
+ }
85
+ else {
86
+ // Find the original target name for hashing (before normalization)
87
+ const originalTarget = wikiLinks.find((wl) => normalizeWikiLinkTarget(wl.target) === normalized)?.target ?? normalized;
88
+ links.push({
89
+ user_id: userId,
90
+ source_type: sourceType,
91
+ source_id: sourceId,
92
+ target_type: "note",
93
+ target_id: PENDING_TARGET_ID,
94
+ relation_type: "wiki_link",
95
+ is_pending: true,
96
+ pending_target_hash: hashPendingTarget(originalTarget),
97
+ created_by: "wiki-link-sync",
98
+ });
99
+ pending++;
100
+ }
101
+ }
102
+ try {
103
+ await bulkInsertKnowledgeLinks(supabase, links);
104
+ }
105
+ catch (err) {
106
+ process.stderr.write(`[wiki-link-sync] bulkInsert failed: ${err instanceof Error ? err.message : String(err)}\n`);
107
+ return { resolved: 0, pending: 0 };
108
+ }
109
+ return { resolved, pending };
110
+ }
111
+ /**
112
+ * Delete only wiki_link-type outgoing links for a node.
113
+ * Used before re-syncing when content changes (update operations).
114
+ * Best-effort: errors are logged but do not propagate.
115
+ */
116
+ export async function deleteWikiLinksForNode(supabase, userId, nodeType, nodeId) {
117
+ try {
118
+ const { error } = await supabase
119
+ .from("knowledge_links")
120
+ .delete()
121
+ .eq("user_id", userId)
122
+ .eq("source_type", nodeType)
123
+ .eq("source_id", nodeId)
124
+ .eq("relation_type", "wiki_link");
125
+ if (error) {
126
+ process.stderr.write(`[wiki-link-sync] deleteWikiLinks failed: ${error.message}\n`);
127
+ }
128
+ }
129
+ catch (err) {
130
+ process.stderr.write(`[wiki-link-sync] deleteWikiLinks error: ${err instanceof Error ? err.message : String(err)}\n`);
131
+ }
132
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wiki-link-sync.js","sourceRoot":"","sources":["../../src/tools/wiki-link-sync.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { ToolResponse } from "../auto-session.js";
2
+ /**
3
+ * Wraps a tool handler that returns a plain string result.
4
+ * Handles try/catch and ok/err wrapping so tool handlers can focus on logic.
5
+ *
6
+ * Composes with `auto.wrap()` — both accept and return `(T) => Promise<ToolResponse>`.
7
+ */
8
+ export declare function wrapToolHandler<T>(handler: (args: T) => Promise<string>): (args: T) => Promise<ToolResponse>;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wrap-tool-handler.d.ts","sourceRoot":"","sources":["../../src/tools/wrap-tool-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAC/B,OAAO,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC,MAAM,CAAC,GACpC,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC,YAAY,CAAC,CAapC"}