@londer/cortex 0.1.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/CHANGELOG.md +62 -0
- package/LICENSE +21 -0
- package/README.md +183 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +278 -0
- package/dist/cli.js.map +1 -0
- package/dist/config-store.d.ts +15 -0
- package/dist/config-store.d.ts.map +1 -0
- package/dist/config-store.js +86 -0
- package/dist/config-store.js.map +1 -0
- package/dist/config.d.ts +28 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +39 -0
- package/dist/config.js.map +1 -0
- package/dist/consolidation/cluster-finder.d.ts +5 -0
- package/dist/consolidation/cluster-finder.d.ts.map +1 -0
- package/dist/consolidation/cluster-finder.js +43 -0
- package/dist/consolidation/cluster-finder.js.map +1 -0
- package/dist/consolidation/consolidator.d.ts +29 -0
- package/dist/consolidation/consolidator.d.ts.map +1 -0
- package/dist/consolidation/consolidator.js +296 -0
- package/dist/consolidation/consolidator.js.map +1 -0
- package/dist/embedding/embedder.d.ts +9 -0
- package/dist/embedding/embedder.d.ts.map +1 -0
- package/dist/embedding/embedder.js +89 -0
- package/dist/embedding/embedder.js.map +1 -0
- package/dist/extraction/auto-extractor.d.ts +7 -0
- package/dist/extraction/auto-extractor.d.ts.map +1 -0
- package/dist/extraction/auto-extractor.js +174 -0
- package/dist/extraction/auto-extractor.js.map +1 -0
- package/dist/extraction/conversation-buffer.d.ts +15 -0
- package/dist/extraction/conversation-buffer.d.ts.map +1 -0
- package/dist/extraction/conversation-buffer.js +60 -0
- package/dist/extraction/conversation-buffer.js.map +1 -0
- package/dist/extraction/extractor.d.ts +23 -0
- package/dist/extraction/extractor.d.ts.map +1 -0
- package/dist/extraction/extractor.js +108 -0
- package/dist/extraction/extractor.js.map +1 -0
- package/dist/extraction/tier1-regex.d.ts +7 -0
- package/dist/extraction/tier1-regex.d.ts.map +1 -0
- package/dist/extraction/tier1-regex.js +119 -0
- package/dist/extraction/tier1-regex.js.map +1 -0
- package/dist/extraction/tier2-nlp.d.ts +13 -0
- package/dist/extraction/tier2-nlp.d.ts.map +1 -0
- package/dist/extraction/tier2-nlp.js +195 -0
- package/dist/extraction/tier2-nlp.js.map +1 -0
- package/dist/extraction/tier3-llm.d.ts +8 -0
- package/dist/extraction/tier3-llm.d.ts.map +1 -0
- package/dist/extraction/tier3-llm.js +57 -0
- package/dist/extraction/tier3-llm.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +398 -0
- package/dist/index.js.map +1 -0
- package/dist/llm/anthropic-client.d.ts +18 -0
- package/dist/llm/anthropic-client.d.ts.map +1 -0
- package/dist/llm/anthropic-client.js +116 -0
- package/dist/llm/anthropic-client.js.map +1 -0
- package/dist/orchestration/ranker.d.ts +18 -0
- package/dist/orchestration/ranker.d.ts.map +1 -0
- package/dist/orchestration/ranker.js +124 -0
- package/dist/orchestration/ranker.js.map +1 -0
- package/dist/orchestration/scope.d.ts +15 -0
- package/dist/orchestration/scope.d.ts.map +1 -0
- package/dist/orchestration/scope.js +28 -0
- package/dist/orchestration/scope.js.map +1 -0
- package/dist/storage/neo4j.d.ts +19 -0
- package/dist/storage/neo4j.d.ts.map +1 -0
- package/dist/storage/neo4j.js +246 -0
- package/dist/storage/neo4j.js.map +1 -0
- package/dist/storage/qdrant.d.ts +21 -0
- package/dist/storage/qdrant.d.ts.map +1 -0
- package/dist/storage/qdrant.js +125 -0
- package/dist/storage/qdrant.js.map +1 -0
- package/dist/storage/sqlite.d.ts +23 -0
- package/dist/storage/sqlite.d.ts.map +1 -0
- package/dist/storage/sqlite.js +162 -0
- package/dist/storage/sqlite.js.map +1 -0
- package/dist/templates/claude-instructions.d.ts +11 -0
- package/dist/templates/claude-instructions.d.ts.map +1 -0
- package/dist/templates/claude-instructions.js +110 -0
- package/dist/templates/claude-instructions.js.map +1 -0
- package/dist/tools/config.d.ts +21 -0
- package/dist/tools/config.d.ts.map +1 -0
- package/dist/tools/config.js +96 -0
- package/dist/tools/config.js.map +1 -0
- package/dist/tools/consolidate.d.ts +4 -0
- package/dist/tools/consolidate.d.ts.map +1 -0
- package/dist/tools/consolidate.js +16 -0
- package/dist/tools/consolidate.js.map +1 -0
- package/dist/tools/context.d.ts +8 -0
- package/dist/tools/context.d.ts.map +1 -0
- package/dist/tools/context.js +84 -0
- package/dist/tools/context.js.map +1 -0
- package/dist/tools/forget.d.ts +7 -0
- package/dist/tools/forget.d.ts.map +1 -0
- package/dist/tools/forget.js +49 -0
- package/dist/tools/forget.js.map +1 -0
- package/dist/tools/graph-query.d.ts +5 -0
- package/dist/tools/graph-query.d.ts.map +1 -0
- package/dist/tools/graph-query.js +35 -0
- package/dist/tools/graph-query.js.map +1 -0
- package/dist/tools/ingest.d.ts +8 -0
- package/dist/tools/ingest.d.ts.map +1 -0
- package/dist/tools/ingest.js +101 -0
- package/dist/tools/ingest.js.map +1 -0
- package/dist/tools/relate.d.ts +4 -0
- package/dist/tools/relate.d.ts.map +1 -0
- package/dist/tools/relate.js +10 -0
- package/dist/tools/relate.js.map +1 -0
- package/dist/tools/search.d.ts +6 -0
- package/dist/tools/search.d.ts.map +1 -0
- package/dist/tools/search.js +43 -0
- package/dist/tools/search.js.map +1 -0
- package/dist/tools/store.d.ts +8 -0
- package/dist/tools/store.d.ts.map +1 -0
- package/dist/tools/store.js +64 -0
- package/dist/tools/store.js.map +1 -0
- package/dist/types/index.d.ts +289 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -0
- package/docker-compose.yml +27 -0
- package/package.json +71 -0
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { inferScopeTier } from './scope.js';
|
|
2
|
+
const GRAPH_CONNECTION_BONUS = 0.15;
|
|
3
|
+
const RECENCY_BONUS_MAX = 0.1;
|
|
4
|
+
const RECENCY_WINDOW_MS = 7 * 24 * 60 * 60 * 1000; // 7 days
|
|
5
|
+
/**
|
|
6
|
+
* Merge results from semantic search, graph traversal, and recent memories.
|
|
7
|
+
* Deduplicates by memory ID, applies scope boosting, and truncates to token budget.
|
|
8
|
+
*/
|
|
9
|
+
export function mergeAndRank(semanticResults, graphMemories, recentMemories, currentProject, relatedProjects, maxTokens = 2000) {
|
|
10
|
+
const seen = new Map();
|
|
11
|
+
// Process semantic results
|
|
12
|
+
for (const mem of semanticResults) {
|
|
13
|
+
const boost = inferScopeTier(mem.project, currentProject, relatedProjects);
|
|
14
|
+
const entry = {
|
|
15
|
+
id: mem.id,
|
|
16
|
+
content: mem.content,
|
|
17
|
+
type: mem.type,
|
|
18
|
+
score: mem.score * boost.weight,
|
|
19
|
+
sourceType: 'semantic',
|
|
20
|
+
project: mem.project,
|
|
21
|
+
tags: mem.tags,
|
|
22
|
+
entities: mem.entities,
|
|
23
|
+
created_at: mem.created_at,
|
|
24
|
+
};
|
|
25
|
+
updateBest(seen, entry);
|
|
26
|
+
}
|
|
27
|
+
// Process graph-related memories
|
|
28
|
+
for (const mem of graphMemories) {
|
|
29
|
+
const existing = seen.get(mem.id);
|
|
30
|
+
if (existing) {
|
|
31
|
+
// Boost existing entry with graph bonus
|
|
32
|
+
existing.score += GRAPH_CONNECTION_BONUS;
|
|
33
|
+
if (existing.sourceType === 'semantic') {
|
|
34
|
+
// Keep as semantic but note the graph boost was applied
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
// We don't have full metadata from graph results, use defaults
|
|
39
|
+
const entry = {
|
|
40
|
+
id: mem.id,
|
|
41
|
+
content: mem.content,
|
|
42
|
+
type: 'fact', // Default; caller should enrich from SQLite
|
|
43
|
+
score: mem.score + GRAPH_CONNECTION_BONUS,
|
|
44
|
+
sourceType: 'graph',
|
|
45
|
+
project: null,
|
|
46
|
+
tags: [],
|
|
47
|
+
entities: [],
|
|
48
|
+
created_at: new Date().toISOString(),
|
|
49
|
+
};
|
|
50
|
+
updateBest(seen, entry);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
// Process recent memories
|
|
54
|
+
const now = Date.now();
|
|
55
|
+
for (const mem of recentMemories) {
|
|
56
|
+
const age = now - new Date(mem.created_at).getTime();
|
|
57
|
+
const recencyBoost = age < RECENCY_WINDOW_MS
|
|
58
|
+
? RECENCY_BONUS_MAX * (1 - age / RECENCY_WINDOW_MS)
|
|
59
|
+
: 0;
|
|
60
|
+
const boost = inferScopeTier(mem.project, currentProject, relatedProjects);
|
|
61
|
+
const existing = seen.get(mem.id);
|
|
62
|
+
if (existing) {
|
|
63
|
+
existing.score += recencyBoost;
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
const entry = {
|
|
67
|
+
id: mem.id,
|
|
68
|
+
content: mem.content,
|
|
69
|
+
type: mem.type,
|
|
70
|
+
score: 0.3 * boost.weight + recencyBoost, // Base score for recent-only results
|
|
71
|
+
sourceType: 'recent',
|
|
72
|
+
project: mem.project,
|
|
73
|
+
tags: mem.tags,
|
|
74
|
+
entities: mem.entities,
|
|
75
|
+
created_at: mem.created_at,
|
|
76
|
+
};
|
|
77
|
+
updateBest(seen, entry);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
// Content-based dedup: merge entries with same content but different IDs
|
|
81
|
+
const byContent = new Map();
|
|
82
|
+
for (const entry of seen.values()) {
|
|
83
|
+
const existing = byContent.get(entry.content);
|
|
84
|
+
if (!existing || entry.score > existing.score) {
|
|
85
|
+
byContent.set(entry.content, entry);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
// Sort by score descending
|
|
89
|
+
const ranked = Array.from(byContent.values()).sort((a, b) => b.score - a.score);
|
|
90
|
+
// Truncate to token budget (rough estimate: 1 token ≈ 4 chars)
|
|
91
|
+
const charBudget = maxTokens * 4;
|
|
92
|
+
let totalChars = 0;
|
|
93
|
+
let cutoffIndex = ranked.length;
|
|
94
|
+
let truncated = false;
|
|
95
|
+
for (let i = 0; i < ranked.length; i++) {
|
|
96
|
+
totalChars += ranked[i].content.length;
|
|
97
|
+
if (totalChars > charBudget) {
|
|
98
|
+
cutoffIndex = i + 1; // Include the one that pushed us over
|
|
99
|
+
truncated = true;
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return { ranked: ranked.slice(0, cutoffIndex), truncated };
|
|
104
|
+
}
|
|
105
|
+
function updateBest(map, entry) {
|
|
106
|
+
const existing = map.get(entry.id);
|
|
107
|
+
if (!existing || entry.score > existing.score) {
|
|
108
|
+
map.set(entry.id, entry);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Format ranked results into a coherent context block.
|
|
113
|
+
*/
|
|
114
|
+
export function formatContext(ranked) {
|
|
115
|
+
if (ranked.length === 0)
|
|
116
|
+
return '';
|
|
117
|
+
return ranked
|
|
118
|
+
.map((r, i) => {
|
|
119
|
+
const meta = [r.type, r.project ?? 'global'].filter(Boolean).join(' | ');
|
|
120
|
+
return `[${i + 1}] (${meta}, score: ${r.score.toFixed(3)})\n${r.content}`;
|
|
121
|
+
})
|
|
122
|
+
.join('\n\n');
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=ranker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ranker.js","sourceRoot":"","sources":["../../src/orchestration/ranker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAG5C,MAAM,sBAAsB,GAAG,IAAI,CAAC;AACpC,MAAM,iBAAiB,GAAG,GAAG,CAAC;AAC9B,MAAM,iBAAiB,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,SAAS;AAE5D;;;GAGG;AACH,MAAM,UAAU,YAAY,CAC1B,eAA+B,EAC/B,aAAoE,EACpE,cAAwB,EACxB,cAA6B,EAC7B,eAA0B,EAC1B,YAAoB,IAAI;IAExB,MAAM,IAAI,GAAG,IAAI,GAAG,EAAwB,CAAC;IAE7C,2BAA2B;IAC3B,KAAK,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;QAClC,MAAM,KAAK,GAAG,cAAc,CAAC,GAAG,CAAC,OAAO,EAAE,cAAc,EAAE,eAAe,CAAC,CAAC;QAC3E,MAAM,KAAK,GAAiB;YAC1B,EAAE,EAAE,GAAG,CAAC,EAAE;YACV,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,KAAK,EAAE,GAAG,CAAC,KAAK,GAAG,KAAK,CAAC,MAAM;YAC/B,UAAU,EAAE,UAAU;YACtB,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,QAAQ,EAAE,GAAG,CAAC,QAAQ;YACtB,UAAU,EAAE,GAAG,CAAC,UAAU;SAC3B,CAAC;QACF,UAAU,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC1B,CAAC;IAED,iCAAiC;IACjC,KAAK,MAAM,GAAG,IAAI,aAAa,EAAE,CAAC;QAChC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAClC,IAAI,QAAQ,EAAE,CAAC;YACb,wCAAwC;YACxC,QAAQ,CAAC,KAAK,IAAI,sBAAsB,CAAC;YACzC,IAAI,QAAQ,CAAC,UAAU,KAAK,UAAU,EAAE,CAAC;gBACvC,wDAAwD;YAC1D,CAAC;QACH,CAAC;aAAM,CAAC;YACN,+DAA+D;YAC/D,MAAM,KAAK,GAAiB;gBAC1B,EAAE,EAAE,GAAG,CAAC,EAAE;gBACV,OAAO,EAAE,GAAG,CAAC,OAAO;gBACpB,IAAI,EAAE,MAAM,EAAE,4CAA4C;gBAC1D,KAAK,EAAE,GAAG,CAAC,KAAK,GAAG,sBAAsB;gBACzC,UAAU,EAAE,OAAO;gBACnB,OAAO,EAAE,IAAI;gBACb,IAAI,EAAE,EAAE;gBACR,QAAQ,EAAE,EAAE;gBACZ,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;aACrC,CAAC;YACF,UAAU,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,0BAA0B;IAC1B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,KAAK,MAAM,GAAG,IAAI,cAAc,EAAE,CAAC;QACjC,MAAM,GAAG,GAAG,GAAG,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,OAAO,EAAE,CAAC;QACrD,MAAM,YAAY,GAAG,GAAG,GAAG,iBAAiB;YAC1C,CAAC,CAAC,iBAAiB,GAAG,CAAC,CAAC,GAAG,GAAG,GAAG,iBAAiB,CAAC;YACnD,CAAC,CAAC,CAAC,CAAC;QACN,MAAM,KAAK,GAAG,cAAc,CAAC,GAAG,CAAC,OAAO,EAAE,cAAc,EAAE,eAAe,CAAC,CAAC;QAE3E,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAClC,IAAI,QAAQ,EAAE,CAAC;YACb,QAAQ,CAAC,KAAK,IAAI,YAAY,CAAC;QACjC,CAAC;aAAM,CAAC;YACN,MAAM,KAAK,GAAiB;gBAC1B,EAAE,EAAE,GAAG,CAAC,EAAE;gBACV,OAAO,EAAE,GAAG,CAAC,OAAO;gBACpB,IAAI,EAAE,GAAG,CAAC,IAAI;gBACd,KAAK,EAAE,GAAG,GAAG,KAAK,CAAC,MAAM,GAAG,YAAY,EAAE,qCAAqC;gBAC/E,UAAU,EAAE,QAAQ;gBACpB,OAAO,EAAE,GAAG,CAAC,OAAO;gBACpB,IAAI,EAAE,GAAG,CAAC,IAAI;gBACd,QAAQ,EAAE,GAAG,CAAC,QAAQ;gBACtB,UAAU,EAAE,GAAG,CAAC,UAAU;aAC3B,CAAC;YACF,UAAU,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,yEAAyE;IACzE,MAAM,SAAS,GAAG,IAAI,GAAG,EAAwB,CAAC;IAClD,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;QAClC,MAAM,QAAQ,GAAG,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC9C,IAAI,CAAC,QAAQ,IAAI,KAAK,CAAC,KAAK,GAAG,QAAQ,CAAC,KAAK,EAAE,CAAC;YAC9C,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QACtC,CAAC;IACH,CAAC;IAED,2BAA2B;IAC3B,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;IAEhF,+DAA+D;IAC/D,MAAM,UAAU,GAAG,SAAS,GAAG,CAAC,CAAC;IACjC,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,IAAI,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC;IAChC,IAAI,SAAS,GAAG,KAAK,CAAC;IAEtB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,UAAU,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;QACvC,IAAI,UAAU,GAAG,UAAU,EAAE,CAAC;YAC5B,WAAW,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,sCAAsC;YAC3D,SAAS,GAAG,IAAI,CAAC;YACjB,MAAM;QACR,CAAC;IACH,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,WAAW,CAAC,EAAE,SAAS,EAAE,CAAC;AAC7D,CAAC;AAED,SAAS,UAAU,CAAC,GAA8B,EAAE,KAAmB;IACrE,MAAM,QAAQ,GAAG,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACnC,IAAI,CAAC,QAAQ,IAAI,KAAK,CAAC,KAAK,GAAG,QAAQ,CAAC,KAAK,EAAE,CAAC;QAC9C,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;IAC3B,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,MAAsB;IAClD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAEnC,OAAO,MAAM;SACV,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACZ,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,OAAO,IAAI,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACzE,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM,IAAI,YAAY,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,CAAC;IAC5E,CAAC,CAAC;SACD,IAAI,CAAC,MAAM,CAAC,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ScopeBoost } from '../types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Infer scope tier and boost weight for a memory relative to the current context.
|
|
4
|
+
*
|
|
5
|
+
* - If the memory's project matches the current project → PROJECT_LOCAL
|
|
6
|
+
* - If a relationship exists between projects → RELATED_PROJECT (caller must supply related projects)
|
|
7
|
+
* - Otherwise → GLOBAL
|
|
8
|
+
*/
|
|
9
|
+
export declare function inferScopeTier(memoryProject: string | null, currentProject: string | null, relatedProjects?: string[]): ScopeBoost;
|
|
10
|
+
/**
|
|
11
|
+
* Infer the effective project from explicit input or context.
|
|
12
|
+
* Returns null for global scope.
|
|
13
|
+
*/
|
|
14
|
+
export declare function resolveProject(explicitProject?: string, contextProject?: string): string | null;
|
|
15
|
+
//# sourceMappingURL=scope.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scope.d.ts","sourceRoot":"","sources":["../../src/orchestration/scope.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAa,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/D;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,aAAa,EAAE,MAAM,GAAG,IAAI,EAC5B,cAAc,EAAE,MAAM,GAAG,IAAI,EAC7B,eAAe,CAAC,EAAE,MAAM,EAAE,GACzB,UAAU,CAeZ;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,eAAe,CAAC,EAAE,MAAM,EACxB,cAAc,CAAC,EAAE,MAAM,GACtB,MAAM,GAAG,IAAI,CAEf"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { SCOPE_BOOST } from '../config.js';
|
|
2
|
+
/**
|
|
3
|
+
* Infer scope tier and boost weight for a memory relative to the current context.
|
|
4
|
+
*
|
|
5
|
+
* - If the memory's project matches the current project → PROJECT_LOCAL
|
|
6
|
+
* - If a relationship exists between projects → RELATED_PROJECT (caller must supply related projects)
|
|
7
|
+
* - Otherwise → GLOBAL
|
|
8
|
+
*/
|
|
9
|
+
export function inferScopeTier(memoryProject, currentProject, relatedProjects) {
|
|
10
|
+
if (currentProject && memoryProject === currentProject) {
|
|
11
|
+
return { tier: 'project_local', weight: SCOPE_BOOST.PROJECT_LOCAL };
|
|
12
|
+
}
|
|
13
|
+
if (currentProject &&
|
|
14
|
+
memoryProject &&
|
|
15
|
+
relatedProjects &&
|
|
16
|
+
relatedProjects.includes(memoryProject)) {
|
|
17
|
+
return { tier: 'related_project', weight: SCOPE_BOOST.RELATED_PROJECT };
|
|
18
|
+
}
|
|
19
|
+
return { tier: 'global', weight: SCOPE_BOOST.GLOBAL };
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Infer the effective project from explicit input or context.
|
|
23
|
+
* Returns null for global scope.
|
|
24
|
+
*/
|
|
25
|
+
export function resolveProject(explicitProject, contextProject) {
|
|
26
|
+
return explicitProject ?? contextProject ?? null;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=scope.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scope.js","sourceRoot":"","sources":["../../src/orchestration/scope.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAG3C;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAC5B,aAA4B,EAC5B,cAA6B,EAC7B,eAA0B;IAE1B,IAAI,cAAc,IAAI,aAAa,KAAK,cAAc,EAAE,CAAC;QACvD,OAAO,EAAE,IAAI,EAAE,eAAe,EAAE,MAAM,EAAE,WAAW,CAAC,aAAa,EAAE,CAAC;IACtE,CAAC;IAED,IACE,cAAc;QACd,aAAa;QACb,eAAe;QACf,eAAe,CAAC,QAAQ,CAAC,aAAa,CAAC,EACvC,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,iBAAiB,EAAE,MAAM,EAAE,WAAW,CAAC,eAAe,EAAE,CAAC;IAC1E,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,CAAC;AACxD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAC5B,eAAwB,EACxB,cAAuB;IAEvB,OAAO,eAAe,IAAI,cAAc,IAAI,IAAI,CAAC;AACnD,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { GraphResult } from '../types/index.js';
|
|
2
|
+
import { type CortexConfig } from '../config.js';
|
|
3
|
+
export declare class Neo4jStore {
|
|
4
|
+
private driver;
|
|
5
|
+
constructor(config?: CortexConfig);
|
|
6
|
+
init(): Promise<void>;
|
|
7
|
+
createEntity(name: string, project?: string): Promise<void>;
|
|
8
|
+
createRelation(from: string, relation: string, to: string, project?: string, properties?: Record<string, string>): Promise<void>;
|
|
9
|
+
linkMemoryToEntities(memoryId: string, entityNames: string[]): Promise<void>;
|
|
10
|
+
traverse(entity: string, depth?: number, relationTypes?: string[], project?: string): Promise<GraphResult>;
|
|
11
|
+
private extractConnections;
|
|
12
|
+
findMemoriesByEntity(entityName: string): Promise<string[]>;
|
|
13
|
+
findEntitiesForMemory(memoryId: string): Promise<string[]>;
|
|
14
|
+
unlinkMemory(memoryId: string): Promise<void>;
|
|
15
|
+
deleteEntitiesByProject(projects: string[]): Promise<void>;
|
|
16
|
+
healthCheck(): Promise<boolean>;
|
|
17
|
+
close(): Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=neo4j.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"neo4j.d.ts","sourceRoot":"","sources":["../../src/storage/neo4j.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAmB,MAAM,mBAAmB,CAAC;AACtE,OAAO,EAAc,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AAE7D,qBAAa,UAAU;IACrB,OAAO,CAAC,MAAM,CAAS;gBAEX,MAAM,CAAC,EAAE,YAAY;IAQ3B,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAgBrB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAa3D,cAAc,CAClB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,EAAE,EAAE,MAAM,EACV,OAAO,CAAC,EAAE,MAAM,EAChB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAClC,OAAO,CAAC,IAAI,CAAC;IA4BV,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAiB5E,QAAQ,CACZ,MAAM,EAAE,MAAM,EACd,KAAK,GAAE,MAAU,EACjB,aAAa,CAAC,EAAE,MAAM,EAAE,EACxB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,WAAW,CAAC;IA2EvB,OAAO,CAAC,kBAAkB;IAuDpB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAa3D,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAa1D,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgB7C,uBAAuB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAY1D,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAY/B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAG7B"}
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
import neo4j from 'neo4j-driver';
|
|
2
|
+
import { loadConfig } from '../config.js';
|
|
3
|
+
export class Neo4jStore {
|
|
4
|
+
driver;
|
|
5
|
+
constructor(config) {
|
|
6
|
+
const cfg = config ?? loadConfig();
|
|
7
|
+
this.driver = neo4j.driver(cfg.neo4jUri, neo4j.auth.basic(cfg.neo4jUser, cfg.neo4jPassword));
|
|
8
|
+
}
|
|
9
|
+
async init() {
|
|
10
|
+
const session = this.driver.session();
|
|
11
|
+
try {
|
|
12
|
+
await session.run('CREATE INDEX entity_name IF NOT EXISTS FOR (e:Entity) ON (e.name)');
|
|
13
|
+
await session.run('CREATE INDEX entity_project IF NOT EXISTS FOR (e:Entity) ON (e.project)');
|
|
14
|
+
await session.run('CREATE INDEX memory_id IF NOT EXISTS FOR (m:Memory) ON (m.id)');
|
|
15
|
+
console.error('[cortex] Neo4j indexes ensured.');
|
|
16
|
+
}
|
|
17
|
+
catch (error) {
|
|
18
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
19
|
+
console.error(`[cortex] Neo4j init error: ${message}`);
|
|
20
|
+
throw new Error(`Failed to initialise Neo4j: ${message}`);
|
|
21
|
+
}
|
|
22
|
+
finally {
|
|
23
|
+
await session.close();
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
async createEntity(name, project) {
|
|
27
|
+
const session = this.driver.session();
|
|
28
|
+
try {
|
|
29
|
+
await session.run(`MERGE (e:Entity {name: $name})
|
|
30
|
+
ON CREATE SET e.project = $project, e.created_at = datetime()`, { name, project: project ?? null });
|
|
31
|
+
}
|
|
32
|
+
finally {
|
|
33
|
+
await session.close();
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
async createRelation(from, relation, to, project, properties) {
|
|
37
|
+
const session = this.driver.session();
|
|
38
|
+
try {
|
|
39
|
+
// Validate relation type to prevent injection through dynamic relationship type
|
|
40
|
+
const validRelations = ['DEPENDS_ON', 'USES', 'PART_OF', 'RELATED_TO', 'IMPLEMENTS', 'CALLS'];
|
|
41
|
+
const safeRelation = validRelations.includes(relation.toUpperCase())
|
|
42
|
+
? relation.toUpperCase()
|
|
43
|
+
: 'RELATED_TO';
|
|
44
|
+
await session.run(`MERGE (a:Entity {name: $from})
|
|
45
|
+
ON CREATE SET a.project = $project, a.created_at = datetime()
|
|
46
|
+
MERGE (b:Entity {name: $to})
|
|
47
|
+
ON CREATE SET b.project = $project, b.created_at = datetime()
|
|
48
|
+
MERGE (a)-[r:${safeRelation}]->(b)
|
|
49
|
+
SET r.project = $project, r.created_at = datetime(), r.properties = $properties`, {
|
|
50
|
+
from,
|
|
51
|
+
to,
|
|
52
|
+
project: project ?? null,
|
|
53
|
+
properties: properties ? JSON.stringify(properties) : null,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
finally {
|
|
57
|
+
await session.close();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
async linkMemoryToEntities(memoryId, entityNames) {
|
|
61
|
+
if (entityNames.length === 0)
|
|
62
|
+
return;
|
|
63
|
+
const session = this.driver.session();
|
|
64
|
+
try {
|
|
65
|
+
await session.run(`MERGE (m:Memory {id: $memoryId})
|
|
66
|
+
WITH m
|
|
67
|
+
UNWIND $entities AS entityName
|
|
68
|
+
MERGE (e:Entity {name: entityName})
|
|
69
|
+
MERGE (m)-[:MENTIONS]->(e)`, { memoryId, entities: entityNames });
|
|
70
|
+
}
|
|
71
|
+
finally {
|
|
72
|
+
await session.close();
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
async traverse(entity, depth = 2, relationTypes, project) {
|
|
76
|
+
const safeDepth = Math.min(Math.max(depth, 1), 4);
|
|
77
|
+
const session = this.driver.session();
|
|
78
|
+
try {
|
|
79
|
+
let relFilter = '';
|
|
80
|
+
if (relationTypes && relationTypes.length > 0) {
|
|
81
|
+
const validRelations = ['DEPENDS_ON', 'USES', 'PART_OF', 'RELATED_TO', 'IMPLEMENTS', 'CALLS'];
|
|
82
|
+
const safe = relationTypes
|
|
83
|
+
.map(r => r.toUpperCase())
|
|
84
|
+
.filter(r => validRelations.includes(r));
|
|
85
|
+
if (safe.length > 0) {
|
|
86
|
+
relFilter = ':' + safe.join('|');
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
const query = `
|
|
90
|
+
MATCH (start:Entity {name: $entity})
|
|
91
|
+
CALL apoc.path.subgraphAll(start, {
|
|
92
|
+
maxLevel: $depth,
|
|
93
|
+
relationshipFilter: $relFilterStr
|
|
94
|
+
}) YIELD nodes, relationships
|
|
95
|
+
UNWIND relationships AS rel
|
|
96
|
+
WITH start, rel, startNode(rel) AS sn, endNode(rel) AS en
|
|
97
|
+
RETURN
|
|
98
|
+
sn.name AS fromEntity,
|
|
99
|
+
type(rel) AS relation,
|
|
100
|
+
en.name AS toEntity,
|
|
101
|
+
rel.properties AS properties,
|
|
102
|
+
CASE WHEN sn = start THEN 1
|
|
103
|
+
ELSE length(shortestPath((start)-[*]-(sn))) + 1
|
|
104
|
+
END AS depth
|
|
105
|
+
`;
|
|
106
|
+
// Fallback: use simple variable-length path if APOC is not available
|
|
107
|
+
const fallbackQuery = `
|
|
108
|
+
MATCH path = (start:Entity {name: $entity})-[${relFilter}*1..${safeDepth}]-(connected:Entity)
|
|
109
|
+
${project ? 'WHERE all(rel in relationships(path) WHERE rel.project IS NULL OR rel.project = $project)' : ''}
|
|
110
|
+
WITH path, connected, length(path) AS d
|
|
111
|
+
UNWIND range(0, size(relationships(path)) - 1) AS idx
|
|
112
|
+
WITH relationships(path)[idx] AS rel,
|
|
113
|
+
nodes(path)[idx] AS sn,
|
|
114
|
+
nodes(path)[idx + 1] AS en,
|
|
115
|
+
idx + 1 AS d
|
|
116
|
+
RETURN DISTINCT
|
|
117
|
+
sn.name AS fromEntity,
|
|
118
|
+
type(rel) AS relation,
|
|
119
|
+
en.name AS toEntity,
|
|
120
|
+
rel.properties AS properties,
|
|
121
|
+
d AS depth
|
|
122
|
+
ORDER BY depth
|
|
123
|
+
`;
|
|
124
|
+
let connections = [];
|
|
125
|
+
try {
|
|
126
|
+
const result = await session.run(query, {
|
|
127
|
+
entity,
|
|
128
|
+
depth: neo4j.int(safeDepth),
|
|
129
|
+
relFilterStr: relFilter ? relFilter.slice(1) : '', // Remove leading ':'
|
|
130
|
+
});
|
|
131
|
+
connections = this.extractConnections(result, entity);
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
// APOC not available, fall back to variable-length paths
|
|
135
|
+
const result = await session.run(fallbackQuery, {
|
|
136
|
+
entity,
|
|
137
|
+
project: project ?? null,
|
|
138
|
+
});
|
|
139
|
+
connections = this.extractConnections(result, entity);
|
|
140
|
+
}
|
|
141
|
+
return { entity, connections };
|
|
142
|
+
}
|
|
143
|
+
finally {
|
|
144
|
+
await session.close();
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
extractConnections(result, rootEntity) {
|
|
148
|
+
const seen = new Set();
|
|
149
|
+
const connections = [];
|
|
150
|
+
for (const record of result.records) {
|
|
151
|
+
const fromEntity = record.get('fromEntity');
|
|
152
|
+
const toEntity = record.get('toEntity');
|
|
153
|
+
const relation = record.get('relation');
|
|
154
|
+
const rawProps = record.get('properties');
|
|
155
|
+
const depth = neo4j.isInt(record.get('depth'))
|
|
156
|
+
? record.get('depth').toNumber()
|
|
157
|
+
: record.get('depth');
|
|
158
|
+
// Determine direction relative to root and which entity to report
|
|
159
|
+
const direction = fromEntity === rootEntity ? 'outgoing'
|
|
160
|
+
: toEntity === rootEntity ? 'incoming'
|
|
161
|
+
: 'outgoing';
|
|
162
|
+
// Report the entity that is NOT the root; for edges between two
|
|
163
|
+
// non-root entities, report toEntity (the further endpoint)
|
|
164
|
+
const connectedEntity = toEntity === rootEntity ? fromEntity : toEntity;
|
|
165
|
+
// Deduplicate by connected entity name
|
|
166
|
+
const key = `${connectedEntity}:${relation}`;
|
|
167
|
+
if (seen.has(key))
|
|
168
|
+
continue;
|
|
169
|
+
seen.add(key);
|
|
170
|
+
let properties;
|
|
171
|
+
if (typeof rawProps === 'string') {
|
|
172
|
+
try {
|
|
173
|
+
const parsed = JSON.parse(rawProps);
|
|
174
|
+
if (parsed && typeof parsed === 'object' && Object.keys(parsed).length > 0) {
|
|
175
|
+
properties = Object.fromEntries(Object.entries(parsed).map(([k, v]) => [k, String(v)]));
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
catch { /* not valid JSON, ignore */ }
|
|
179
|
+
}
|
|
180
|
+
connections.push({
|
|
181
|
+
entity: connectedEntity,
|
|
182
|
+
relation,
|
|
183
|
+
direction,
|
|
184
|
+
depth,
|
|
185
|
+
...(properties && Object.keys(properties).length > 0 ? { properties } : {}),
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
return connections;
|
|
189
|
+
}
|
|
190
|
+
async findMemoriesByEntity(entityName) {
|
|
191
|
+
const session = this.driver.session();
|
|
192
|
+
try {
|
|
193
|
+
const result = await session.run('MATCH (m:Memory)-[:MENTIONS]->(e:Entity {name: $name}) RETURN m.id AS id', { name: entityName });
|
|
194
|
+
return result.records.map(r => r.get('id'));
|
|
195
|
+
}
|
|
196
|
+
finally {
|
|
197
|
+
await session.close();
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
async findEntitiesForMemory(memoryId) {
|
|
201
|
+
const session = this.driver.session();
|
|
202
|
+
try {
|
|
203
|
+
const result = await session.run('MATCH (m:Memory {id: $memoryId})-[:MENTIONS]->(e:Entity) RETURN e.name AS name', { memoryId });
|
|
204
|
+
return result.records.map(r => r.get('name'));
|
|
205
|
+
}
|
|
206
|
+
finally {
|
|
207
|
+
await session.close();
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
async unlinkMemory(memoryId) {
|
|
211
|
+
const session = this.driver.session();
|
|
212
|
+
try {
|
|
213
|
+
await session.run('MATCH (m:Memory {id: $memoryId})-[r:MENTIONS]->() DELETE r', { memoryId });
|
|
214
|
+
await session.run('MATCH (m:Memory {id: $memoryId}) DELETE m', { memoryId });
|
|
215
|
+
}
|
|
216
|
+
finally {
|
|
217
|
+
await session.close();
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
async deleteEntitiesByProject(projects) {
|
|
221
|
+
const session = this.driver.session();
|
|
222
|
+
try {
|
|
223
|
+
await session.run('MATCH (e:Entity) WHERE e.project IN $projects DETACH DELETE e', { projects });
|
|
224
|
+
}
|
|
225
|
+
finally {
|
|
226
|
+
await session.close();
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
async healthCheck() {
|
|
230
|
+
const session = this.driver.session();
|
|
231
|
+
try {
|
|
232
|
+
await session.run('RETURN 1');
|
|
233
|
+
return true;
|
|
234
|
+
}
|
|
235
|
+
catch {
|
|
236
|
+
return false;
|
|
237
|
+
}
|
|
238
|
+
finally {
|
|
239
|
+
await session.close();
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
async close() {
|
|
243
|
+
await this.driver.close();
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
//# sourceMappingURL=neo4j.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"neo4j.js","sourceRoot":"","sources":["../../src/storage/neo4j.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { MemoryPayload, ScoredMemory } from '../types/index.js';
|
|
2
|
+
import { type CortexConfig } from '../config.js';
|
|
3
|
+
export interface QdrantFilter {
|
|
4
|
+
project?: string;
|
|
5
|
+
type?: string;
|
|
6
|
+
tags?: string[];
|
|
7
|
+
}
|
|
8
|
+
export declare class QdrantStore {
|
|
9
|
+
private client;
|
|
10
|
+
private collectionName;
|
|
11
|
+
private vectorDimensions;
|
|
12
|
+
constructor(config?: CortexConfig);
|
|
13
|
+
init(): Promise<void>;
|
|
14
|
+
private ensurePayloadIndex;
|
|
15
|
+
upsert(id: string, vector: number[], payload: MemoryPayload): Promise<void>;
|
|
16
|
+
search(vector: number[], filter?: QdrantFilter, limit?: number): Promise<ScoredMemory[]>;
|
|
17
|
+
delete(id: string): Promise<void>;
|
|
18
|
+
healthCheck(): Promise<boolean>;
|
|
19
|
+
private buildFilter;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=qdrant.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qdrant.d.ts","sourceRoot":"","sources":["../../src/storage/qdrant.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAc,MAAM,mBAAmB,CAAC;AACjF,OAAO,EAAc,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AAE7D,MAAM,WAAW,YAAY;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,gBAAgB,CAAS;gBAErB,MAAM,CAAC,EAAE,YAAY;IAO3B,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;YA2Bb,kBAAkB;IAW1B,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAY3E,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,MAAM,CAAC,EAAE,YAAY,EAAE,KAAK,GAAE,MAAW,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAyB5F,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMjC,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IASrC,OAAO,CAAC,WAAW;CA+BpB"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { QdrantClient } from '@qdrant/js-client-rest';
|
|
2
|
+
import { loadConfig } from '../config.js';
|
|
3
|
+
export class QdrantStore {
|
|
4
|
+
client;
|
|
5
|
+
collectionName;
|
|
6
|
+
vectorDimensions;
|
|
7
|
+
constructor(config) {
|
|
8
|
+
const cfg = config ?? loadConfig();
|
|
9
|
+
this.client = new QdrantClient({ url: cfg.qdrantUrl });
|
|
10
|
+
this.collectionName = cfg.collectionName;
|
|
11
|
+
this.vectorDimensions = cfg.vectorDimensions;
|
|
12
|
+
}
|
|
13
|
+
async init() {
|
|
14
|
+
try {
|
|
15
|
+
const collections = await this.client.getCollections();
|
|
16
|
+
const exists = collections.collections.some(c => c.name === this.collectionName);
|
|
17
|
+
if (!exists) {
|
|
18
|
+
await this.client.createCollection(this.collectionName, {
|
|
19
|
+
vectors: {
|
|
20
|
+
size: this.vectorDimensions,
|
|
21
|
+
distance: 'Cosine',
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
console.error(`[cortex] Created Qdrant collection: ${this.collectionName}`);
|
|
25
|
+
}
|
|
26
|
+
// Create payload indexes
|
|
27
|
+
await this.ensurePayloadIndex('project', 'keyword');
|
|
28
|
+
await this.ensurePayloadIndex('type', 'keyword');
|
|
29
|
+
await this.ensurePayloadIndex('tags', 'keyword');
|
|
30
|
+
await this.ensurePayloadIndex('created_at', 'integer');
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
34
|
+
console.error(`[cortex] Qdrant init error: ${message}`);
|
|
35
|
+
throw new Error(`Failed to initialise Qdrant: ${message}`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
async ensurePayloadIndex(field, type) {
|
|
39
|
+
try {
|
|
40
|
+
await this.client.createPayloadIndex(this.collectionName, {
|
|
41
|
+
field_name: field,
|
|
42
|
+
field_schema: type,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
// Index may already exist — that's fine
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
async upsert(id, vector, payload) {
|
|
50
|
+
await this.client.upsert(this.collectionName, {
|
|
51
|
+
points: [
|
|
52
|
+
{
|
|
53
|
+
id,
|
|
54
|
+
vector,
|
|
55
|
+
payload: payload,
|
|
56
|
+
},
|
|
57
|
+
],
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
async search(vector, filter, limit = 10) {
|
|
61
|
+
const qdrantFilter = this.buildFilter(filter);
|
|
62
|
+
const results = await this.client.search(this.collectionName, {
|
|
63
|
+
vector,
|
|
64
|
+
limit,
|
|
65
|
+
with_payload: true,
|
|
66
|
+
...(qdrantFilter ? { filter: qdrantFilter } : {}),
|
|
67
|
+
});
|
|
68
|
+
return results.map(result => {
|
|
69
|
+
const payload = result.payload;
|
|
70
|
+
return {
|
|
71
|
+
id: payload.id,
|
|
72
|
+
content: '', // Content comes from SQLite — we only store metadata in Qdrant
|
|
73
|
+
type: payload.type,
|
|
74
|
+
score: result.score,
|
|
75
|
+
project: payload.project ?? null,
|
|
76
|
+
tags: payload.tags ?? [],
|
|
77
|
+
entities: payload.entities ?? [],
|
|
78
|
+
created_at: new Date(payload.created_at * 1000).toISOString(),
|
|
79
|
+
};
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
async delete(id) {
|
|
83
|
+
await this.client.delete(this.collectionName, {
|
|
84
|
+
points: [id],
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
async healthCheck() {
|
|
88
|
+
try {
|
|
89
|
+
await this.client.getCollections();
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
buildFilter(filter) {
|
|
97
|
+
if (!filter)
|
|
98
|
+
return undefined;
|
|
99
|
+
const must = [];
|
|
100
|
+
if (filter.project) {
|
|
101
|
+
must.push({
|
|
102
|
+
key: 'project',
|
|
103
|
+
match: { value: filter.project },
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
if (filter.type) {
|
|
107
|
+
must.push({
|
|
108
|
+
key: 'type',
|
|
109
|
+
match: { value: filter.type },
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
if (filter.tags && filter.tags.length > 0) {
|
|
113
|
+
for (const tag of filter.tags) {
|
|
114
|
+
must.push({
|
|
115
|
+
key: 'tags',
|
|
116
|
+
match: { value: tag },
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
if (must.length === 0)
|
|
121
|
+
return undefined;
|
|
122
|
+
return { must };
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=qdrant.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qdrant.js","sourceRoot":"","sources":["../../src/storage/qdrant.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Memory, ConsolidationLogEntry } from '../types/index.js';
|
|
2
|
+
export declare class SQLiteStore {
|
|
3
|
+
private db;
|
|
4
|
+
constructor(dbPath?: string);
|
|
5
|
+
init(): void;
|
|
6
|
+
private migratePhase2;
|
|
7
|
+
insertMemory(memory: Memory): void;
|
|
8
|
+
getMemory(id: string): Memory | null;
|
|
9
|
+
getMemoriesByIds(ids: string[]): Memory[];
|
|
10
|
+
getRecentMemories(project: string | null, limit: number): Memory[];
|
|
11
|
+
searchByProject(project: string, limit: number): Memory[];
|
|
12
|
+
softDelete(id: string): void;
|
|
13
|
+
deleteByProject(project: string): void;
|
|
14
|
+
getStats(): {
|
|
15
|
+
totalMemories: number;
|
|
16
|
+
totalEntities: number;
|
|
17
|
+
totalRelationships: number;
|
|
18
|
+
};
|
|
19
|
+
insertConsolidationLog(entry: ConsolidationLogEntry): void;
|
|
20
|
+
close(): void;
|
|
21
|
+
private rowToMemory;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=sqlite.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sqlite.d.ts","sourceRoot":"","sources":["../../src/storage/sqlite.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAGvE,qBAAa,WAAW;IACtB,OAAO,CAAC,EAAE,CAAoB;gBAElB,MAAM,CAAC,EAAE,MAAM;IAM3B,IAAI,IAAI,IAAI;IAmCZ,OAAO,CAAC,aAAa;IAgCrB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAwBlC,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAQpC,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE;IAUzC,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;IAalE,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;IAOzD,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAO5B,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAKtC,QAAQ,IAAI;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAC;QAAC,kBAAkB,EAAE,MAAM,CAAA;KAAE;IAyBxF,sBAAsB,CAAC,KAAK,EAAE,qBAAqB,GAAG,IAAI;IAgB1D,KAAK,IAAI,IAAI;IAIb,OAAO,CAAC,WAAW;CAkBpB"}
|