exovault-mcp-server 1.4.0 → 1.5.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/db.d.ts +49 -2
- package/dist/db.js +102 -26
- package/dist/default-documents.d.ts +22 -0
- package/dist/default-documents.js +261 -0
- package/dist/embedding-config.js +1 -1
- package/dist/episodic-headline.d.ts +5 -2
- package/dist/episodic-headline.js +15 -7
- package/dist/extraction-prompt.js +4 -4
- package/dist/gateway-client.d.ts +82 -0
- package/dist/gateway-client.js +106 -0
- package/dist/gateway-init.d.ts +1 -1
- package/dist/gateway-init.js +56 -6
- package/dist/graph-extraction.d.ts +44 -0
- package/dist/graph-extraction.js +211 -0
- package/dist/index.js +169 -5
- package/dist/rlm/verify.js +6 -6
- package/dist/rlm/writeback.js +10 -10
- package/dist/scripts/backfill-memory-embeddings.js +1 -1
- package/dist/session-buffer.js +29 -11
- package/dist/stopwords.d.ts +6 -0
- package/dist/stopwords.js +9 -0
- package/dist/tools/adversarial-context.d.ts +18 -0
- package/dist/tools/adversarial-context.js +45 -0
- package/dist/tools/agent-cards.d.ts +26 -0
- package/dist/tools/agent-cards.js +9 -0
- package/dist/tools/agent-pipelines.d.ts +37 -0
- package/dist/tools/agent-pipelines.js +9 -0
- package/dist/tools/contradiction-detection.d.ts +18 -0
- package/dist/tools/contradiction-detection.js +33 -0
- package/dist/tools/entity-extraction-utils.d.ts +9 -0
- package/dist/tools/entity-extraction-utils.js +35 -0
- package/dist/tools/explore-graph.d.ts +10 -0
- package/dist/tools/explore-graph.js +17 -0
- package/dist/tools/intent-detection.d.ts +8 -0
- package/dist/tools/intent-detection.js +50 -0
- package/dist/tools/knowledge-links.js +1 -0
- package/dist/tools/llm-call.d.ts +20 -0
- package/dist/tools/llm-call.js +44 -0
- package/dist/tools/llm-reranker.d.ts +39 -0
- package/dist/tools/llm-reranker.js +130 -0
- package/dist/tools/multi-step-retrieval.d.ts +28 -0
- package/dist/tools/multi-step-retrieval.js +39 -0
- package/dist/tools/pipeline-router.d.ts +32 -0
- package/dist/tools/pipeline-router.js +97 -0
- package/dist/tools/query-classifier.d.ts +43 -0
- package/dist/tools/query-classifier.js +321 -0
- package/dist/tools/search-memories.d.ts +4 -0
- package/dist/tools/search-memories.js +386 -21
- package/dist/tools/session-start.d.ts +1 -0
- package/dist/tools/session-start.js +66 -13
- package/dist/tools/synthesize.d.ts +27 -0
- package/dist/tools/synthesize.js +100 -0
- package/dist/tools/update-memory.d.ts +1 -0
- package/dist/tools/update-memory.js +4 -0
- package/dist/tools/write-memory.d.ts +10 -1
- package/dist/tools/write-memory.js +288 -19
- package/package.json +1 -1
package/dist/db.d.ts
CHANGED
|
@@ -62,6 +62,12 @@ export interface MemoryRow {
|
|
|
62
62
|
source_note_ids: string[] | null;
|
|
63
63
|
superseded_by_id: string | null;
|
|
64
64
|
entities: string[] | null;
|
|
65
|
+
entity_descriptions: Array<{
|
|
66
|
+
name: string;
|
|
67
|
+
type: string;
|
|
68
|
+
description: string;
|
|
69
|
+
}> | null;
|
|
70
|
+
community_id: number | null;
|
|
65
71
|
created_at: string;
|
|
66
72
|
updated_at: string;
|
|
67
73
|
}
|
|
@@ -97,6 +103,8 @@ export declare function getMemories(supabase: SupabaseClient, userId: string, op
|
|
|
97
103
|
includeArchived?: boolean;
|
|
98
104
|
limit?: number;
|
|
99
105
|
orderBy?: "updated_at" | "importance";
|
|
106
|
+
/** Use lightweight columns (no encrypted content/summary). Default: false. */
|
|
107
|
+
lightweight?: boolean;
|
|
100
108
|
}): Promise<MemoryRow[]>;
|
|
101
109
|
export declare function getMemory(supabase: SupabaseClient, userId: string, memoryId: string): Promise<MemoryRow | null>;
|
|
102
110
|
export declare function getMemoryByExternalWriteId(supabase: SupabaseClient, userId: string, externalWriteId: string): Promise<MemoryRow | null>;
|
|
@@ -123,6 +131,11 @@ export declare function insertMemory(supabase: SupabaseClient, data: {
|
|
|
123
131
|
source_note_ids?: string[] | null;
|
|
124
132
|
superseded_by_id?: string | null;
|
|
125
133
|
entities?: string[] | null;
|
|
134
|
+
entity_descriptions?: Array<{
|
|
135
|
+
name: string;
|
|
136
|
+
type: string;
|
|
137
|
+
description: string;
|
|
138
|
+
}> | null;
|
|
126
139
|
blind_tokens?: string[] | null;
|
|
127
140
|
indexing_status?: string;
|
|
128
141
|
}): Promise<MemoryRow>;
|
|
@@ -169,7 +182,7 @@ export interface MemoryEmbeddingMatch {
|
|
|
169
182
|
importance: number;
|
|
170
183
|
}
|
|
171
184
|
export declare function matchNoteEmbeddings(supabase: SupabaseClient, embedding: number[], userId: string, threshold?: number, count?: number): Promise<EmbeddingMatch[]>;
|
|
172
|
-
export declare function matchMemoryEmbeddings(supabase: SupabaseClient, embedding: number[], userId: string, threshold?: number, count?: number): Promise<MemoryEmbeddingMatch[]>;
|
|
185
|
+
export declare function matchMemoryEmbeddings(supabase: SupabaseClient, embedding: number[], userId: string, threshold?: number, count?: number, vaultIds?: string[] | null): Promise<MemoryEmbeddingMatch[]>;
|
|
173
186
|
export interface BlindTokenMatch {
|
|
174
187
|
memory_id: string;
|
|
175
188
|
match_count: number;
|
|
@@ -223,6 +236,16 @@ export interface MemoryHealthStats {
|
|
|
223
236
|
}
|
|
224
237
|
export declare function getMemoryHealthStats(supabase: SupabaseClient, userId: string, vaultId?: string): Promise<MemoryHealthStats>;
|
|
225
238
|
export declare function searchMemoriesByEntity(supabase: SupabaseClient, userId: string, entity: string, limit?: number): Promise<MemoryRow[]>;
|
|
239
|
+
/**
|
|
240
|
+
* Fetch memory IDs that belong to any of the given community clusters.
|
|
241
|
+
* Used by community routing signal in search.
|
|
242
|
+
*/
|
|
243
|
+
export declare function getMemoryIdsByCommunityIds(supabase: SupabaseClient, userId: string, communityIds: number[], limit?: number, vaultId?: string): Promise<string[]>;
|
|
244
|
+
/**
|
|
245
|
+
* Fetch community_ids for a set of memory IDs. Used to resolve
|
|
246
|
+
* which communities the entity signal hits belong to.
|
|
247
|
+
*/
|
|
248
|
+
export declare function getCommunityIdsForMemories(supabase: SupabaseClient, userId: string, memoryIds: string[]): Promise<number[]>;
|
|
226
249
|
export declare function getRelatedMemoriesById(supabase: SupabaseClient, userId: string, memoryId: string, limit?: number): Promise<{
|
|
227
250
|
source: MemoryRow | null;
|
|
228
251
|
related: MemoryRow[];
|
|
@@ -242,6 +265,7 @@ export interface KnowledgeLinkRow {
|
|
|
242
265
|
relation_type: LinkRelationType;
|
|
243
266
|
encrypted_label: string | null;
|
|
244
267
|
label_iv: string | null;
|
|
268
|
+
confidence: number;
|
|
245
269
|
is_pending: boolean;
|
|
246
270
|
pending_target_hash: string | null;
|
|
247
271
|
created_at: string;
|
|
@@ -256,6 +280,7 @@ export declare function insertKnowledgeLink(supabase: SupabaseClient, data: {
|
|
|
256
280
|
relation_type: LinkRelationType;
|
|
257
281
|
encrypted_label?: string | null;
|
|
258
282
|
label_iv?: string | null;
|
|
283
|
+
confidence?: number;
|
|
259
284
|
is_pending?: boolean;
|
|
260
285
|
pending_target_hash?: string | null;
|
|
261
286
|
created_by?: string | null;
|
|
@@ -276,10 +301,13 @@ export declare function bulkInsertKnowledgeLinks(supabase: SupabaseClient, links
|
|
|
276
301
|
relation_type: LinkRelationType;
|
|
277
302
|
encrypted_label?: string | null;
|
|
278
303
|
label_iv?: string | null;
|
|
304
|
+
confidence?: number;
|
|
279
305
|
is_pending?: boolean;
|
|
280
306
|
pending_target_hash?: string | null;
|
|
281
307
|
created_by?: string | null;
|
|
282
|
-
}>): Promise<
|
|
308
|
+
}>): Promise<Array<{
|
|
309
|
+
id: string;
|
|
310
|
+
}>>;
|
|
283
311
|
/**
|
|
284
312
|
* Resolves pending wiki-links by matching stored SHA-256 hashes against
|
|
285
313
|
* candidate note names. Caller provides a map of hash → noteId.
|
|
@@ -295,6 +323,25 @@ export declare function getKnowledgeGraph(supabase: SupabaseClient, userId: stri
|
|
|
295
323
|
from_id: string;
|
|
296
324
|
relation: LinkRelationType;
|
|
297
325
|
}>>;
|
|
326
|
+
export declare function insertRelationshipEmbedding(supabase: SupabaseClient, data: {
|
|
327
|
+
user_id: string;
|
|
328
|
+
link_id: string;
|
|
329
|
+
source_entity: string;
|
|
330
|
+
target_entity: string;
|
|
331
|
+
keywords: string;
|
|
332
|
+
encrypted_description?: string | null;
|
|
333
|
+
description_iv?: string | null;
|
|
334
|
+
embedding_model: string;
|
|
335
|
+
embedding: number[];
|
|
336
|
+
}): Promise<void>;
|
|
337
|
+
export declare function matchRelationshipEmbeddings(supabase: SupabaseClient, queryEmbedding: number[], userId: string, threshold?: number, matchCount?: number): Promise<Array<{
|
|
338
|
+
id: string;
|
|
339
|
+
link_id: string;
|
|
340
|
+
source_entity: string;
|
|
341
|
+
target_entity: string;
|
|
342
|
+
keywords: string;
|
|
343
|
+
similarity: number;
|
|
344
|
+
}>>;
|
|
298
345
|
export interface AgentMessageRow {
|
|
299
346
|
id: string;
|
|
300
347
|
user_id: string;
|
package/dist/db.js
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import { sanitizeDbError } from "./error-sanitizer.js";
|
|
2
|
+
// ─── Column lists (explicit to avoid SELECT * egress overhead) ───────────────
|
|
3
|
+
const VAULT_COLUMNS = "id, user_id, encrypted_name, name_iv, icon, color, sort_order, created_at, updated_at";
|
|
4
|
+
const NOTE_COLUMNS = "id, user_id, vault_id, encrypted_title, title_iv, encrypted_content, content_iv, content_type, encrypted_tags, tags_iv, embedding_status, import_source, import_source_id, is_trashed, created_at, updated_at";
|
|
5
|
+
const LINK_COLUMNS = "id, user_id, source_type, source_id, target_type, target_id, relation_type, encrypted_label, label_iv, confidence, is_pending, pending_target_hash, created_at, created_by";
|
|
6
|
+
const MESSAGE_COLUMNS = "id, user_id, vault_id, sender_type, sender_id, target_type, target_id, category, priority, subject, encrypted_content, content_iv, status, delivered_at, acknowledged_at, parent_message_id, thread_id, expires_at, metadata, created_at, updated_at";
|
|
2
7
|
// ─── Query helpers ────────────────────────────────────────────────────────────
|
|
3
8
|
export async function getVaults(supabase, userId) {
|
|
4
9
|
const { data, error } = await supabase
|
|
5
10
|
.from("vaults")
|
|
6
|
-
.select(
|
|
11
|
+
.select(VAULT_COLUMNS)
|
|
7
12
|
.eq("user_id", userId)
|
|
8
13
|
.order("sort_order", { ascending: true });
|
|
9
14
|
if (error)
|
|
@@ -13,7 +18,7 @@ export async function getVaults(supabase, userId) {
|
|
|
13
18
|
export async function getNotes(supabase, userId, vaultId, limit = 20) {
|
|
14
19
|
let query = supabase
|
|
15
20
|
.from("notes")
|
|
16
|
-
.select(
|
|
21
|
+
.select(NOTE_COLUMNS)
|
|
17
22
|
.eq("user_id", userId)
|
|
18
23
|
.eq("is_trashed", false)
|
|
19
24
|
.order("updated_at", { ascending: false })
|
|
@@ -29,7 +34,7 @@ export async function getNotes(supabase, userId, vaultId, limit = 20) {
|
|
|
29
34
|
export async function getNote(supabase, userId, noteId) {
|
|
30
35
|
const { data, error } = await supabase
|
|
31
36
|
.from("notes")
|
|
32
|
-
.select(
|
|
37
|
+
.select(NOTE_COLUMNS)
|
|
33
38
|
.eq("id", noteId)
|
|
34
39
|
.eq("user_id", userId)
|
|
35
40
|
.single();
|
|
@@ -43,7 +48,7 @@ export async function getNote(supabase, userId, noteId) {
|
|
|
43
48
|
export async function getVault(supabase, userId, vaultId) {
|
|
44
49
|
const { data, error } = await supabase
|
|
45
50
|
.from("vaults")
|
|
46
|
-
.select(
|
|
51
|
+
.select(VAULT_COLUMNS)
|
|
47
52
|
.eq("id", vaultId)
|
|
48
53
|
.eq("user_id", userId)
|
|
49
54
|
.single();
|
|
@@ -102,9 +107,15 @@ export async function getMemories(supabase, userId, options) {
|
|
|
102
107
|
const includeArchived = options?.includeArchived ?? false;
|
|
103
108
|
const limit = options?.limit ?? 50;
|
|
104
109
|
const orderBy = options?.orderBy ?? "updated_at";
|
|
110
|
+
// Lightweight mode: select only metadata columns (no encrypted content/summary) to reduce egress.
|
|
111
|
+
// Supabase's TS type parser can't handle long literal strings, so we build the query separately.
|
|
112
|
+
const columns = options?.lightweight
|
|
113
|
+
? "id,user_id,vault_id,memory_type,agent_id,agent_type,model_id,agent_run_id,importance,confidence,access_count,is_archived,entities,superseded_by_id,created_at,updated_at"
|
|
114
|
+
: "*";
|
|
105
115
|
let query = supabase
|
|
106
116
|
.from("memories")
|
|
107
|
-
|
|
117
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
118
|
+
.select(columns)
|
|
108
119
|
.eq("user_id", userId)
|
|
109
120
|
.order(orderBy, { ascending: false })
|
|
110
121
|
.limit(limit);
|
|
@@ -277,21 +288,23 @@ export async function getEmbeddingsForMemories(supabase, userId, memoryIds) {
|
|
|
277
288
|
}
|
|
278
289
|
export async function matchNoteEmbeddings(supabase, embedding, userId, threshold = 0.5, count = 20) {
|
|
279
290
|
const { data, error } = await supabase.rpc("match_note_embeddings", {
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
291
|
+
p_embedding: JSON.stringify(embedding),
|
|
292
|
+
p_match_threshold: threshold,
|
|
293
|
+
p_match_count: count,
|
|
283
294
|
p_user_id: userId,
|
|
295
|
+
p_vault_ids: null,
|
|
284
296
|
});
|
|
285
297
|
if (error)
|
|
286
298
|
throw new Error(sanitizeDbError("match note embeddings", error.message));
|
|
287
299
|
return (data ?? []);
|
|
288
300
|
}
|
|
289
|
-
export async function matchMemoryEmbeddings(supabase, embedding, userId, threshold = 0.5, count = 20) {
|
|
301
|
+
export async function matchMemoryEmbeddings(supabase, embedding, userId, threshold = 0.5, count = 20, vaultIds) {
|
|
290
302
|
const { data, error } = await supabase.rpc("match_memory_embeddings", {
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
303
|
+
p_embedding: JSON.stringify(embedding),
|
|
304
|
+
p_match_threshold: threshold,
|
|
305
|
+
p_match_count: count,
|
|
294
306
|
p_user_id: userId,
|
|
307
|
+
p_vault_ids: vaultIds ?? null,
|
|
295
308
|
});
|
|
296
309
|
if (error)
|
|
297
310
|
throw new Error(sanitizeDbError("match memory embeddings", error.message));
|
|
@@ -310,6 +323,7 @@ export async function matchMemoriesByBlindTokens(supabase, tokenHashes, userId,
|
|
|
310
323
|
p_vault_id: vaultId ?? null,
|
|
311
324
|
p_match_count: count,
|
|
312
325
|
p_include_archived: includeArchived,
|
|
326
|
+
p_vault_ids: null,
|
|
313
327
|
});
|
|
314
328
|
if (error)
|
|
315
329
|
throw new Error(sanitizeDbError("match memories by blind tokens", error.message));
|
|
@@ -328,6 +342,7 @@ export async function matchNotesByBlindTokens(supabase, tokenHashes, userId, vau
|
|
|
328
342
|
p_vault_id: vaultId ?? null,
|
|
329
343
|
p_match_count: count,
|
|
330
344
|
p_include_trashed: includeTrashed,
|
|
345
|
+
p_vault_ids: null,
|
|
331
346
|
});
|
|
332
347
|
if (error)
|
|
333
348
|
throw new Error(sanitizeDbError("match notes by blind tokens", error.message));
|
|
@@ -339,7 +354,7 @@ export async function getNotesByIds(supabase, userId, noteIds) {
|
|
|
339
354
|
return [];
|
|
340
355
|
const { data, error } = await supabase
|
|
341
356
|
.from("notes")
|
|
342
|
-
.select(
|
|
357
|
+
.select(NOTE_COLUMNS)
|
|
343
358
|
.eq("user_id", userId)
|
|
344
359
|
.eq("is_trashed", false)
|
|
345
360
|
.in("id", noteIds);
|
|
@@ -350,7 +365,7 @@ export async function getNotesByIds(supabase, userId, noteIds) {
|
|
|
350
365
|
export async function getNoteByImportSource(supabase, userId, vaultId, importSource, importSourceId) {
|
|
351
366
|
const { data, error } = await supabase
|
|
352
367
|
.from("notes")
|
|
353
|
-
.select(
|
|
368
|
+
.select(NOTE_COLUMNS)
|
|
354
369
|
.eq("user_id", userId)
|
|
355
370
|
.eq("vault_id", vaultId)
|
|
356
371
|
.eq("import_source", importSource)
|
|
@@ -492,6 +507,46 @@ export async function searchMemoriesByEntity(supabase, userId, entity, limit = 2
|
|
|
492
507
|
throw new Error(sanitizeDbError("search memories by entity", error.message));
|
|
493
508
|
return (data ?? []);
|
|
494
509
|
}
|
|
510
|
+
/**
|
|
511
|
+
* Fetch memory IDs that belong to any of the given community clusters.
|
|
512
|
+
* Used by community routing signal in search.
|
|
513
|
+
*/
|
|
514
|
+
export async function getMemoryIdsByCommunityIds(supabase, userId, communityIds, limit = 30, vaultId) {
|
|
515
|
+
if (communityIds.length === 0)
|
|
516
|
+
return [];
|
|
517
|
+
let query = supabase
|
|
518
|
+
.from("memories")
|
|
519
|
+
.select("id")
|
|
520
|
+
.eq("user_id", userId)
|
|
521
|
+
.eq("is_archived", false)
|
|
522
|
+
.in("community_id", communityIds);
|
|
523
|
+
if (vaultId) {
|
|
524
|
+
query = query.eq("vault_id", vaultId);
|
|
525
|
+
}
|
|
526
|
+
const { data, error } = await query
|
|
527
|
+
.order("updated_at", { ascending: false })
|
|
528
|
+
.limit(limit);
|
|
529
|
+
if (error)
|
|
530
|
+
throw new Error(sanitizeDbError("community routing", error.message));
|
|
531
|
+
return (data ?? []).map((r) => r.id);
|
|
532
|
+
}
|
|
533
|
+
/**
|
|
534
|
+
* Fetch community_ids for a set of memory IDs. Used to resolve
|
|
535
|
+
* which communities the entity signal hits belong to.
|
|
536
|
+
*/
|
|
537
|
+
export async function getCommunityIdsForMemories(supabase, userId, memoryIds) {
|
|
538
|
+
if (memoryIds.length === 0)
|
|
539
|
+
return [];
|
|
540
|
+
const { data, error } = await supabase
|
|
541
|
+
.from("memories")
|
|
542
|
+
.select("community_id")
|
|
543
|
+
.eq("user_id", userId)
|
|
544
|
+
.in("id", memoryIds.slice(0, 50))
|
|
545
|
+
.not("community_id", "is", null);
|
|
546
|
+
if (error)
|
|
547
|
+
throw new Error(sanitizeDbError("community id lookup", error.message));
|
|
548
|
+
return [...new Set((data ?? []).map((r) => r.community_id))];
|
|
549
|
+
}
|
|
495
550
|
export async function getRelatedMemoriesById(supabase, userId, memoryId, limit = 20) {
|
|
496
551
|
// Fetch the source memory
|
|
497
552
|
const source = await getMemory(supabase, userId, memoryId);
|
|
@@ -580,10 +635,11 @@ export async function insertKnowledgeLink(supabase, data) {
|
|
|
580
635
|
encrypted_label: data.encrypted_label ?? null,
|
|
581
636
|
label_iv: data.label_iv ?? null,
|
|
582
637
|
is_pending: data.is_pending ?? false,
|
|
638
|
+
confidence: data.confidence ?? 0.8,
|
|
583
639
|
pending_target_hash: data.pending_target_hash ?? null,
|
|
584
640
|
created_by: data.created_by ?? null,
|
|
585
641
|
})
|
|
586
|
-
.select()
|
|
642
|
+
.select(LINK_COLUMNS)
|
|
587
643
|
.single();
|
|
588
644
|
if (error)
|
|
589
645
|
throw new Error(sanitizeDbError("insert knowledge link", error.message));
|
|
@@ -604,7 +660,7 @@ export async function getLinksForNode(supabase, userId, nodeType, nodeId, option
|
|
|
604
660
|
if (direction === "outgoing") {
|
|
605
661
|
const { data, error } = await supabase
|
|
606
662
|
.from("knowledge_links")
|
|
607
|
-
.select()
|
|
663
|
+
.select(LINK_COLUMNS)
|
|
608
664
|
.eq("user_id", userId)
|
|
609
665
|
.eq("source_type", nodeType)
|
|
610
666
|
.eq("source_id", nodeId)
|
|
@@ -617,7 +673,7 @@ export async function getLinksForNode(supabase, userId, nodeType, nodeId, option
|
|
|
617
673
|
if (direction === "incoming") {
|
|
618
674
|
const { data, error } = await supabase
|
|
619
675
|
.from("knowledge_links")
|
|
620
|
-
.select()
|
|
676
|
+
.select(LINK_COLUMNS)
|
|
621
677
|
.eq("user_id", userId)
|
|
622
678
|
.eq("target_type", nodeType)
|
|
623
679
|
.eq("target_id", nodeId)
|
|
@@ -631,7 +687,7 @@ export async function getLinksForNode(supabase, userId, nodeType, nodeId, option
|
|
|
631
687
|
const [outgoing, incoming] = await Promise.all([
|
|
632
688
|
supabase
|
|
633
689
|
.from("knowledge_links")
|
|
634
|
-
.select()
|
|
690
|
+
.select(LINK_COLUMNS)
|
|
635
691
|
.eq("user_id", userId)
|
|
636
692
|
.eq("source_type", nodeType)
|
|
637
693
|
.eq("source_id", nodeId)
|
|
@@ -639,7 +695,7 @@ export async function getLinksForNode(supabase, userId, nodeType, nodeId, option
|
|
|
639
695
|
.limit(limit),
|
|
640
696
|
supabase
|
|
641
697
|
.from("knowledge_links")
|
|
642
|
-
.select()
|
|
698
|
+
.select(LINK_COLUMNS)
|
|
643
699
|
.eq("user_id", userId)
|
|
644
700
|
.eq("target_type", nodeType)
|
|
645
701
|
.eq("target_id", nodeId)
|
|
@@ -690,7 +746,7 @@ export async function deleteLinksForNode(supabase, userId, nodeType, nodeId) {
|
|
|
690
746
|
}
|
|
691
747
|
export async function bulkInsertKnowledgeLinks(supabase, links) {
|
|
692
748
|
if (links.length === 0)
|
|
693
|
-
return
|
|
749
|
+
return [];
|
|
694
750
|
const rows = links.map((l) => ({
|
|
695
751
|
user_id: l.user_id,
|
|
696
752
|
source_type: l.source_type,
|
|
@@ -700,6 +756,7 @@ export async function bulkInsertKnowledgeLinks(supabase, links) {
|
|
|
700
756
|
relation_type: l.relation_type,
|
|
701
757
|
encrypted_label: l.encrypted_label ?? null,
|
|
702
758
|
label_iv: l.label_iv ?? null,
|
|
759
|
+
confidence: l.confidence ?? 0.8,
|
|
703
760
|
is_pending: l.is_pending ?? false,
|
|
704
761
|
pending_target_hash: l.pending_target_hash ?? null,
|
|
705
762
|
created_by: l.created_by ?? null,
|
|
@@ -711,7 +768,7 @@ export async function bulkInsertKnowledgeLinks(supabase, links) {
|
|
|
711
768
|
.select("id");
|
|
712
769
|
if (error)
|
|
713
770
|
throw new Error(sanitizeDbError("bulk insert knowledge links", error.message));
|
|
714
|
-
return data
|
|
771
|
+
return (data ?? []);
|
|
715
772
|
}
|
|
716
773
|
/**
|
|
717
774
|
* Resolves pending wiki-links by matching stored SHA-256 hashes against
|
|
@@ -724,7 +781,7 @@ export async function resolvePendingLinks(supabase, userId, hashToNoteId) {
|
|
|
724
781
|
// Fetch all pending links for this user
|
|
725
782
|
const { data: pending, error } = await supabase
|
|
726
783
|
.from("knowledge_links")
|
|
727
|
-
.select()
|
|
784
|
+
.select(LINK_COLUMNS)
|
|
728
785
|
.eq("user_id", userId)
|
|
729
786
|
.eq("is_pending", true)
|
|
730
787
|
.limit(10_000);
|
|
@@ -766,6 +823,25 @@ export async function getKnowledgeGraph(supabase, userId, nodeType, nodeId, maxH
|
|
|
766
823
|
throw new Error(sanitizeDbError("traverse knowledge graph", error.message));
|
|
767
824
|
return (data ?? []);
|
|
768
825
|
}
|
|
826
|
+
// ─── Relationship Embeddings ─────────────────────────────────────────────────
|
|
827
|
+
export async function insertRelationshipEmbedding(supabase, data) {
|
|
828
|
+
const { error } = await supabase
|
|
829
|
+
.from("relationship_embeddings")
|
|
830
|
+
.upsert(data, { onConflict: "user_id,link_id,embedding_model" });
|
|
831
|
+
if (error)
|
|
832
|
+
throw new Error(sanitizeDbError("upsert relationship embedding", error.message));
|
|
833
|
+
}
|
|
834
|
+
export async function matchRelationshipEmbeddings(supabase, queryEmbedding, userId, threshold = 0.4, matchCount = 10) {
|
|
835
|
+
const { data, error } = await supabase.rpc("match_relationship_embeddings", {
|
|
836
|
+
p_user_id: userId,
|
|
837
|
+
p_query_embedding: JSON.stringify(queryEmbedding),
|
|
838
|
+
p_match_threshold: threshold,
|
|
839
|
+
p_match_count: matchCount,
|
|
840
|
+
});
|
|
841
|
+
if (error)
|
|
842
|
+
throw new Error(sanitizeDbError("match relationship embeddings", error.message));
|
|
843
|
+
return data ?? [];
|
|
844
|
+
}
|
|
769
845
|
export async function insertAgentMessage(supabase, data) {
|
|
770
846
|
const { data: row, error } = await supabase
|
|
771
847
|
.from("agent_messages")
|
|
@@ -786,7 +862,7 @@ export async function insertAgentMessage(supabase, data) {
|
|
|
786
862
|
parent_message_id: data.parent_message_id ?? null,
|
|
787
863
|
thread_id: data.thread_id ?? null,
|
|
788
864
|
})
|
|
789
|
-
.select(
|
|
865
|
+
.select(MESSAGE_COLUMNS)
|
|
790
866
|
.single();
|
|
791
867
|
if (error)
|
|
792
868
|
throw new Error(sanitizeDbError("insert agent message", error.message));
|
|
@@ -799,7 +875,7 @@ export async function insertAgentMessage(supabase, data) {
|
|
|
799
875
|
export async function getPendingMessages(supabase, userId, targetId, limit = 5) {
|
|
800
876
|
const { data, error } = await supabase
|
|
801
877
|
.from("agent_messages")
|
|
802
|
-
.select(
|
|
878
|
+
.select(MESSAGE_COLUMNS)
|
|
803
879
|
.eq("user_id", userId)
|
|
804
880
|
.eq("status", "pending")
|
|
805
881
|
.or(`target_id.eq.${targetId},target_id.eq.*`)
|
|
@@ -819,7 +895,7 @@ export async function getAgentMessages(supabase, userId, targetId, options) {
|
|
|
819
895
|
const includeBroadcast = options?.includeBroadcast ?? true;
|
|
820
896
|
let query = supabase
|
|
821
897
|
.from("agent_messages")
|
|
822
|
-
.select(
|
|
898
|
+
.select(MESSAGE_COLUMNS)
|
|
823
899
|
.eq("user_id", userId)
|
|
824
900
|
.order("priority", { ascending: false })
|
|
825
901
|
.order("created_at", { ascending: false })
|
|
@@ -890,7 +966,7 @@ export async function resolveThreadId(supabase, userId, parentMessageId) {
|
|
|
890
966
|
export async function getThread(supabase, userId, threadId) {
|
|
891
967
|
const { data, error } = await supabase
|
|
892
968
|
.from("agent_messages")
|
|
893
|
-
.select(
|
|
969
|
+
.select(MESSAGE_COLUMNS)
|
|
894
970
|
.eq("user_id", userId)
|
|
895
971
|
.eq("thread_id", threadId)
|
|
896
972
|
.order("created_at", { ascending: true });
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* System default documents for direct/stdio mode.
|
|
3
|
+
*
|
|
4
|
+
* In gateway mode, the HTTP API loads user-customized documents from the database.
|
|
5
|
+
* In direct mode, we serve these system defaults since we don't have access to
|
|
6
|
+
* the vault settings infrastructure. Users who customize documents should use
|
|
7
|
+
* gateway mode (recommended).
|
|
8
|
+
*
|
|
9
|
+
* NOTE: Keep in sync with src/lib/settings/default-documents.ts in the main app.
|
|
10
|
+
*/
|
|
11
|
+
export declare const DOCUMENT_TYPES: readonly ["soul", "instructions", "skills", "checks"];
|
|
12
|
+
export type DocumentType = (typeof DOCUMENT_TYPES)[number];
|
|
13
|
+
export interface DefaultDocumentTemplate {
|
|
14
|
+
content: string;
|
|
15
|
+
version: number;
|
|
16
|
+
inheritMode: "replace" | "append" | "none";
|
|
17
|
+
agentEditable: boolean;
|
|
18
|
+
appendOnly: boolean;
|
|
19
|
+
}
|
|
20
|
+
export declare const CURRENT_TEMPLATE_VERSION = 5;
|
|
21
|
+
/** Get default plaintext for a specific document type */
|
|
22
|
+
export declare function getDefaultDocumentContent(type: DocumentType): DefaultDocumentTemplate;
|