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.
- package/dist/auth.d.ts +41 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +236 -0
- package/dist/auth.js.map +1 -0
- package/dist/auto-session.d.ts +39 -0
- package/dist/auto-session.d.ts.map +1 -0
- package/dist/auto-session.js +128 -0
- package/dist/auto-session.js.map +1 -0
- package/dist/buffer-persistence.d.ts +35 -0
- package/dist/buffer-persistence.d.ts.map +1 -0
- package/dist/buffer-persistence.js +110 -0
- package/dist/buffer-persistence.js.map +1 -0
- package/dist/coerce-params.d.ts +36 -0
- package/dist/coerce-params.d.ts.map +1 -0
- package/dist/coerce-params.js +120 -0
- package/dist/coerce-params.js.map +1 -0
- package/dist/crypto.d.ts +39 -0
- package/dist/crypto.d.ts.map +1 -0
- package/dist/crypto.js +119 -0
- package/dist/crypto.js.map +1 -0
- package/dist/db.d.ts +350 -0
- package/dist/db.d.ts.map +1 -0
- package/dist/db.js +866 -0
- package/dist/db.js.map +1 -0
- package/dist/embedding-config.d.ts +11 -0
- package/dist/embedding-config.d.ts.map +1 -0
- package/dist/embedding-config.js +24 -0
- package/dist/embedding-config.js.map +1 -0
- package/dist/entity-extraction.d.ts +22 -0
- package/dist/entity-extraction.d.ts.map +1 -0
- package/dist/entity-extraction.js +140 -0
- package/dist/entity-extraction.js.map +1 -0
- package/dist/episodic-headline.d.ts +6 -0
- package/dist/episodic-headline.d.ts.map +1 -0
- package/dist/episodic-headline.js +62 -0
- package/dist/episodic-headline.js.map +1 -0
- package/dist/error-sanitizer.d.ts +20 -0
- package/dist/error-sanitizer.d.ts.map +1 -0
- package/dist/error-sanitizer.js +54 -0
- package/dist/error-sanitizer.js.map +1 -0
- package/dist/extraction-budget.d.ts +39 -0
- package/dist/extraction-budget.d.ts.map +1 -0
- package/dist/extraction-budget.js +122 -0
- package/dist/extraction-budget.js.map +1 -0
- package/dist/extraction-llm.d.ts +22 -0
- package/dist/extraction-llm.d.ts.map +1 -0
- package/dist/extraction-llm.js +32 -0
- package/dist/extraction-llm.js.map +1 -0
- package/dist/extraction-prompt.d.ts +40 -0
- package/dist/extraction-prompt.d.ts.map +1 -0
- package/dist/extraction-prompt.js +176 -0
- package/dist/extraction-prompt.js.map +1 -0
- package/dist/gateway-client.d.ts +303 -0
- package/dist/gateway-client.d.ts.map +1 -0
- package/dist/gateway-client.js +285 -0
- package/dist/gateway-client.js.map +1 -0
- package/dist/gateway-init.d.ts +32 -0
- package/dist/gateway-init.d.ts.map +1 -0
- package/dist/gateway-init.js +71 -0
- package/dist/gateway-init.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1242 -0
- package/dist/index.js.map +1 -0
- package/dist/infer-task-status.d.ts +7 -0
- package/dist/infer-task-status.d.ts.map +1 -0
- package/dist/infer-task-status.js +23 -0
- package/dist/infer-task-status.js.map +1 -0
- package/dist/normalize-agent-id.d.ts +21 -0
- package/dist/normalize-agent-id.d.ts.map +1 -0
- package/dist/normalize-agent-id.js +54 -0
- package/dist/normalize-agent-id.js.map +1 -0
- package/dist/openai.d.ts +14 -0
- package/dist/openai.d.ts.map +1 -0
- package/dist/openai.js +43 -0
- package/dist/openai.js.map +1 -0
- package/dist/rlm/actions.d.ts +31 -0
- package/dist/rlm/actions.d.ts.map +1 -0
- package/dist/rlm/actions.js +241 -0
- package/dist/rlm/actions.js.map +1 -0
- package/dist/rlm/benchmark.d.ts +2 -0
- package/dist/rlm/benchmark.d.ts.map +1 -0
- package/dist/rlm/benchmark.js +215 -0
- package/dist/rlm/benchmark.js.map +1 -0
- package/dist/rlm/execute.d.ts +13 -0
- package/dist/rlm/execute.d.ts.map +1 -0
- package/dist/rlm/execute.js +366 -0
- package/dist/rlm/execute.js.map +1 -0
- package/dist/rlm/index.d.ts +6 -0
- package/dist/rlm/index.d.ts.map +1 -0
- package/dist/rlm/index.js +147 -0
- package/dist/rlm/index.js.map +1 -0
- package/dist/rlm/profiles.d.ts +9 -0
- package/dist/rlm/profiles.d.ts.map +1 -0
- package/dist/rlm/profiles.js +46 -0
- package/dist/rlm/profiles.js.map +1 -0
- package/dist/rlm/types.d.ts +98 -0
- package/dist/rlm/types.d.ts.map +1 -0
- package/dist/rlm/types.js +6 -0
- package/dist/rlm/types.js.map +1 -0
- package/dist/rlm/verify.d.ts +13 -0
- package/dist/rlm/verify.d.ts.map +1 -0
- package/dist/rlm/verify.js +58 -0
- package/dist/rlm/verify.js.map +1 -0
- package/dist/rlm/writeback.d.ts +7 -0
- package/dist/rlm/writeback.d.ts.map +1 -0
- package/dist/rlm/writeback.js +77 -0
- package/dist/rlm/writeback.js.map +1 -0
- package/dist/scripts/backfill-memory-embeddings.d.ts +2 -0
- package/dist/scripts/backfill-memory-embeddings.d.ts.map +1 -0
- package/dist/scripts/backfill-memory-embeddings.js +153 -0
- package/dist/scripts/backfill-memory-embeddings.js.map +1 -0
- package/dist/session-buffer.d.ts +104 -0
- package/dist/session-buffer.d.ts.map +1 -0
- package/dist/session-buffer.js +466 -0
- package/dist/session-buffer.js.map +1 -0
- package/dist/session-dedup.d.ts +30 -0
- package/dist/session-dedup.d.ts.map +1 -0
- package/dist/session-dedup.js +67 -0
- package/dist/session-dedup.js.map +1 -0
- package/dist/session-flush.d.ts +81 -0
- package/dist/session-flush.d.ts.map +1 -0
- package/dist/session-flush.js +169 -0
- package/dist/session-flush.js.map +1 -0
- package/dist/session-lifecycle.d.ts +72 -0
- package/dist/session-lifecycle.d.ts.map +1 -0
- package/dist/session-lifecycle.js +247 -0
- package/dist/session-lifecycle.js.map +1 -0
- package/dist/setup.d.ts +2 -0
- package/dist/setup.d.ts.map +1 -0
- package/dist/setup.js +260 -0
- package/dist/setup.js.map +1 -0
- package/dist/stopwords.d.ts +2 -0
- package/dist/stopwords.d.ts.map +1 -0
- package/dist/stopwords.js +20 -0
- package/dist/stopwords.js.map +1 -0
- package/dist/strip-html.d.ts +5 -0
- package/dist/strip-html.d.ts.map +1 -0
- package/dist/strip-html.js +35 -0
- package/dist/strip-html.js.map +1 -0
- package/dist/task-completion-flush.d.ts +36 -0
- package/dist/task-completion-flush.d.ts.map +1 -0
- package/dist/task-completion-flush.js +97 -0
- package/dist/task-completion-flush.js.map +1 -0
- package/dist/task-lifecycle-types.d.ts +13 -0
- package/dist/task-lifecycle-types.d.ts.map +1 -0
- package/dist/task-lifecycle-types.js +12 -0
- package/dist/task-lifecycle-types.js.map +1 -0
- package/dist/task-lifecycle.d.ts +78 -0
- package/dist/task-lifecycle.d.ts.map +1 -0
- package/dist/task-lifecycle.js +256 -0
- package/dist/task-lifecycle.js.map +1 -0
- package/dist/tools/agent-messages.d.ts +26 -0
- package/dist/tools/agent-messages.d.ts.map +1 -0
- package/dist/tools/agent-messages.js +123 -0
- package/dist/tools/agent-messages.js.map +1 -0
- package/dist/tools/agent-tasks.d.ts +24 -0
- package/dist/tools/agent-tasks.d.ts.map +1 -0
- package/dist/tools/agent-tasks.js +162 -0
- package/dist/tools/agent-tasks.js.map +1 -0
- package/dist/tools/archive-memory.d.ts +2 -0
- package/dist/tools/archive-memory.d.ts.map +1 -0
- package/dist/tools/archive-memory.js +19 -0
- package/dist/tools/archive-memory.js.map +1 -0
- package/dist/tools/blind-index.d.ts +29 -0
- package/dist/tools/blind-index.d.ts.map +1 -0
- package/dist/tools/blind-index.js +53 -0
- package/dist/tools/blind-index.js.map +1 -0
- package/dist/tools/cleanup-memories.d.ts +44 -0
- package/dist/tools/cleanup-memories.d.ts.map +1 -0
- package/dist/tools/cleanup-memories.js +126 -0
- package/dist/tools/cleanup-memories.js.map +1 -0
- package/dist/tools/context-checkpoint.d.ts +28 -0
- package/dist/tools/context-checkpoint.d.ts.map +1 -0
- package/dist/tools/context-checkpoint.js +140 -0
- package/dist/tools/context-checkpoint.js.map +1 -0
- package/dist/tools/context-profiles.d.ts +67 -0
- package/dist/tools/context-profiles.d.ts.map +1 -0
- package/dist/tools/context-profiles.js +30 -0
- package/dist/tools/context-profiles.js.map +1 -0
- package/dist/tools/create-note.d.ts +2 -0
- package/dist/tools/create-note.d.ts.map +1 -0
- package/dist/tools/create-note.js +60 -0
- package/dist/tools/create-note.js.map +1 -0
- package/dist/tools/create-vault.d.ts +5 -0
- package/dist/tools/create-vault.d.ts.map +1 -0
- package/dist/tools/create-vault.js +121 -0
- package/dist/tools/create-vault.js.map +1 -0
- package/dist/tools/decrypt-helpers.d.ts +31 -0
- package/dist/tools/decrypt-helpers.d.ts.map +1 -0
- package/dist/tools/decrypt-helpers.js +33 -0
- package/dist/tools/decrypt-helpers.js.map +1 -0
- package/dist/tools/delete-note.d.ts +2 -0
- package/dist/tools/delete-note.d.ts.map +1 -0
- package/dist/tools/delete-note.js +21 -0
- package/dist/tools/delete-note.js.map +1 -0
- package/dist/tools/explore-graph.d.ts +11 -0
- package/dist/tools/explore-graph.d.ts.map +1 -0
- package/dist/tools/explore-graph.js +169 -0
- package/dist/tools/explore-graph.js.map +1 -0
- package/dist/tools/get-related-memories.d.ts +2 -0
- package/dist/tools/get-related-memories.d.ts.map +1 -0
- package/dist/tools/get-related-memories.js +59 -0
- package/dist/tools/get-related-memories.js.map +1 -0
- package/dist/tools/knowledge-links.d.ts +17 -0
- package/dist/tools/knowledge-links.d.ts.map +1 -0
- package/dist/tools/knowledge-links.js +102 -0
- package/dist/tools/knowledge-links.js.map +1 -0
- package/dist/tools/list-active-agents.d.ts +5 -0
- package/dist/tools/list-active-agents.d.ts.map +1 -0
- package/dist/tools/list-active-agents.js +15 -0
- package/dist/tools/list-active-agents.js.map +1 -0
- package/dist/tools/list-notes.d.ts +2 -0
- package/dist/tools/list-notes.d.ts.map +1 -0
- package/dist/tools/list-notes.js +19 -0
- package/dist/tools/list-notes.js.map +1 -0
- package/dist/tools/list-vaults.d.ts +2 -0
- package/dist/tools/list-vaults.d.ts.map +1 -0
- package/dist/tools/list-vaults.js +19 -0
- package/dist/tools/list-vaults.js.map +1 -0
- package/dist/tools/mmr.d.ts +18 -0
- package/dist/tools/mmr.d.ts.map +1 -0
- package/dist/tools/mmr.js +67 -0
- package/dist/tools/mmr.js.map +1 -0
- package/dist/tools/read-memories.d.ts +2 -0
- package/dist/tools/read-memories.d.ts.map +1 -0
- package/dist/tools/read-memories.js +46 -0
- package/dist/tools/read-memories.js.map +1 -0
- package/dist/tools/read-note.d.ts +2 -0
- package/dist/tools/read-note.d.ts.map +1 -0
- package/dist/tools/read-note.js +35 -0
- package/dist/tools/read-note.js.map +1 -0
- package/dist/tools/read-notes.d.ts +6 -0
- package/dist/tools/read-notes.d.ts.map +1 -0
- package/dist/tools/read-notes.js +45 -0
- package/dist/tools/read-notes.js.map +1 -0
- package/dist/tools/resolve-vault-id.d.ts +6 -0
- package/dist/tools/resolve-vault-id.d.ts.map +1 -0
- package/dist/tools/resolve-vault-id.js +7 -0
- package/dist/tools/resolve-vault-id.js.map +1 -0
- package/dist/tools/rrf.d.ts +28 -0
- package/dist/tools/rrf.d.ts.map +1 -0
- package/dist/tools/rrf.js +19 -0
- package/dist/tools/rrf.js.map +1 -0
- package/dist/tools/search-and-read.d.ts +11 -0
- package/dist/tools/search-and-read.d.ts.map +1 -0
- package/dist/tools/search-and-read.js +208 -0
- package/dist/tools/search-and-read.js.map +1 -0
- package/dist/tools/search-memories.d.ts +13 -0
- package/dist/tools/search-memories.d.ts.map +1 -0
- package/dist/tools/search-memories.js +272 -0
- package/dist/tools/search-memories.js.map +1 -0
- package/dist/tools/search-notes.d.ts +2 -0
- package/dist/tools/search-notes.d.ts.map +1 -0
- package/dist/tools/search-notes.js +94 -0
- package/dist/tools/search-notes.js.map +1 -0
- package/dist/tools/semantic-search.d.ts +7 -0
- package/dist/tools/semantic-search.d.ts.map +1 -0
- package/dist/tools/semantic-search.js +85 -0
- package/dist/tools/semantic-search.js.map +1 -0
- package/dist/tools/session-start.d.ts +24 -0
- package/dist/tools/session-start.d.ts.map +1 -0
- package/dist/tools/session-start.js +256 -0
- package/dist/tools/session-start.js.map +1 -0
- package/dist/tools/stale-tasks.d.ts +22 -0
- package/dist/tools/stale-tasks.d.ts.map +1 -0
- package/dist/tools/stale-tasks.js +39 -0
- package/dist/tools/stale-tasks.js.map +1 -0
- package/dist/tools/temporal-decay.d.ts +21 -0
- package/dist/tools/temporal-decay.d.ts.map +1 -0
- package/dist/tools/temporal-decay.js +32 -0
- package/dist/tools/temporal-decay.js.map +1 -0
- package/dist/tools/update-memory.d.ts +19 -0
- package/dist/tools/update-memory.d.ts.map +1 -0
- package/dist/tools/update-memory.js +230 -0
- package/dist/tools/update-memory.js.map +1 -0
- package/dist/tools/update-note.d.ts +2 -0
- package/dist/tools/update-note.d.ts.map +1 -0
- package/dist/tools/update-note.js +79 -0
- package/dist/tools/update-note.js.map +1 -0
- package/dist/tools/vault-instruction-template.d.ts +17 -0
- package/dist/tools/vault-instruction-template.d.ts.map +1 -0
- package/dist/tools/vault-instruction-template.js +77 -0
- package/dist/tools/vault-instruction-template.js.map +1 -0
- package/dist/tools/wiki-link-sync.d.ts +34 -0
- package/dist/tools/wiki-link-sync.d.ts.map +1 -0
- package/dist/tools/wiki-link-sync.js +132 -0
- package/dist/tools/wiki-link-sync.js.map +1 -0
- package/dist/tools/wrap-tool-handler.d.ts +8 -0
- package/dist/tools/wrap-tool-handler.d.ts.map +1 -0
- package/dist/tools/wrap-tool-handler.js +32 -0
- package/dist/tools/wrap-tool-handler.js.map +1 -0
- package/dist/tools/write-memory.d.ts +34 -0
- package/dist/tools/write-memory.d.ts.map +1 -0
- package/dist/tools/write-memory.js +359 -0
- package/dist/tools/write-memory.js.map +1 -0
- package/dist/usage.d.ts +11 -0
- package/dist/usage.d.ts.map +1 -0
- package/dist/usage.js +38 -0
- package/dist/usage.js.map +1 -0
- package/dist/wiki-link-parser.d.ts +27 -0
- package/dist/wiki-link-parser.d.ts.map +1 -0
- package/dist/wiki-link-parser.js +93 -0
- package/dist/wiki-link-parser.js.map +1 -0
- 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 @@
|
|
|
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"}
|