@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.
Files changed (125) hide show
  1. package/CHANGELOG.md +62 -0
  2. package/LICENSE +21 -0
  3. package/README.md +183 -0
  4. package/dist/cli.d.ts +3 -0
  5. package/dist/cli.d.ts.map +1 -0
  6. package/dist/cli.js +278 -0
  7. package/dist/cli.js.map +1 -0
  8. package/dist/config-store.d.ts +15 -0
  9. package/dist/config-store.d.ts.map +1 -0
  10. package/dist/config-store.js +86 -0
  11. package/dist/config-store.js.map +1 -0
  12. package/dist/config.d.ts +28 -0
  13. package/dist/config.d.ts.map +1 -0
  14. package/dist/config.js +39 -0
  15. package/dist/config.js.map +1 -0
  16. package/dist/consolidation/cluster-finder.d.ts +5 -0
  17. package/dist/consolidation/cluster-finder.d.ts.map +1 -0
  18. package/dist/consolidation/cluster-finder.js +43 -0
  19. package/dist/consolidation/cluster-finder.js.map +1 -0
  20. package/dist/consolidation/consolidator.d.ts +29 -0
  21. package/dist/consolidation/consolidator.d.ts.map +1 -0
  22. package/dist/consolidation/consolidator.js +296 -0
  23. package/dist/consolidation/consolidator.js.map +1 -0
  24. package/dist/embedding/embedder.d.ts +9 -0
  25. package/dist/embedding/embedder.d.ts.map +1 -0
  26. package/dist/embedding/embedder.js +89 -0
  27. package/dist/embedding/embedder.js.map +1 -0
  28. package/dist/extraction/auto-extractor.d.ts +7 -0
  29. package/dist/extraction/auto-extractor.d.ts.map +1 -0
  30. package/dist/extraction/auto-extractor.js +174 -0
  31. package/dist/extraction/auto-extractor.js.map +1 -0
  32. package/dist/extraction/conversation-buffer.d.ts +15 -0
  33. package/dist/extraction/conversation-buffer.d.ts.map +1 -0
  34. package/dist/extraction/conversation-buffer.js +60 -0
  35. package/dist/extraction/conversation-buffer.js.map +1 -0
  36. package/dist/extraction/extractor.d.ts +23 -0
  37. package/dist/extraction/extractor.d.ts.map +1 -0
  38. package/dist/extraction/extractor.js +108 -0
  39. package/dist/extraction/extractor.js.map +1 -0
  40. package/dist/extraction/tier1-regex.d.ts +7 -0
  41. package/dist/extraction/tier1-regex.d.ts.map +1 -0
  42. package/dist/extraction/tier1-regex.js +119 -0
  43. package/dist/extraction/tier1-regex.js.map +1 -0
  44. package/dist/extraction/tier2-nlp.d.ts +13 -0
  45. package/dist/extraction/tier2-nlp.d.ts.map +1 -0
  46. package/dist/extraction/tier2-nlp.js +195 -0
  47. package/dist/extraction/tier2-nlp.js.map +1 -0
  48. package/dist/extraction/tier3-llm.d.ts +8 -0
  49. package/dist/extraction/tier3-llm.d.ts.map +1 -0
  50. package/dist/extraction/tier3-llm.js +57 -0
  51. package/dist/extraction/tier3-llm.js.map +1 -0
  52. package/dist/index.d.ts +2 -0
  53. package/dist/index.d.ts.map +1 -0
  54. package/dist/index.js +398 -0
  55. package/dist/index.js.map +1 -0
  56. package/dist/llm/anthropic-client.d.ts +18 -0
  57. package/dist/llm/anthropic-client.d.ts.map +1 -0
  58. package/dist/llm/anthropic-client.js +116 -0
  59. package/dist/llm/anthropic-client.js.map +1 -0
  60. package/dist/orchestration/ranker.d.ts +18 -0
  61. package/dist/orchestration/ranker.d.ts.map +1 -0
  62. package/dist/orchestration/ranker.js +124 -0
  63. package/dist/orchestration/ranker.js.map +1 -0
  64. package/dist/orchestration/scope.d.ts +15 -0
  65. package/dist/orchestration/scope.d.ts.map +1 -0
  66. package/dist/orchestration/scope.js +28 -0
  67. package/dist/orchestration/scope.js.map +1 -0
  68. package/dist/storage/neo4j.d.ts +19 -0
  69. package/dist/storage/neo4j.d.ts.map +1 -0
  70. package/dist/storage/neo4j.js +246 -0
  71. package/dist/storage/neo4j.js.map +1 -0
  72. package/dist/storage/qdrant.d.ts +21 -0
  73. package/dist/storage/qdrant.d.ts.map +1 -0
  74. package/dist/storage/qdrant.js +125 -0
  75. package/dist/storage/qdrant.js.map +1 -0
  76. package/dist/storage/sqlite.d.ts +23 -0
  77. package/dist/storage/sqlite.d.ts.map +1 -0
  78. package/dist/storage/sqlite.js +162 -0
  79. package/dist/storage/sqlite.js.map +1 -0
  80. package/dist/templates/claude-instructions.d.ts +11 -0
  81. package/dist/templates/claude-instructions.d.ts.map +1 -0
  82. package/dist/templates/claude-instructions.js +110 -0
  83. package/dist/templates/claude-instructions.js.map +1 -0
  84. package/dist/tools/config.d.ts +21 -0
  85. package/dist/tools/config.d.ts.map +1 -0
  86. package/dist/tools/config.js +96 -0
  87. package/dist/tools/config.js.map +1 -0
  88. package/dist/tools/consolidate.d.ts +4 -0
  89. package/dist/tools/consolidate.d.ts.map +1 -0
  90. package/dist/tools/consolidate.js +16 -0
  91. package/dist/tools/consolidate.js.map +1 -0
  92. package/dist/tools/context.d.ts +8 -0
  93. package/dist/tools/context.d.ts.map +1 -0
  94. package/dist/tools/context.js +84 -0
  95. package/dist/tools/context.js.map +1 -0
  96. package/dist/tools/forget.d.ts +7 -0
  97. package/dist/tools/forget.d.ts.map +1 -0
  98. package/dist/tools/forget.js +49 -0
  99. package/dist/tools/forget.js.map +1 -0
  100. package/dist/tools/graph-query.d.ts +5 -0
  101. package/dist/tools/graph-query.d.ts.map +1 -0
  102. package/dist/tools/graph-query.js +35 -0
  103. package/dist/tools/graph-query.js.map +1 -0
  104. package/dist/tools/ingest.d.ts +8 -0
  105. package/dist/tools/ingest.d.ts.map +1 -0
  106. package/dist/tools/ingest.js +101 -0
  107. package/dist/tools/ingest.js.map +1 -0
  108. package/dist/tools/relate.d.ts +4 -0
  109. package/dist/tools/relate.d.ts.map +1 -0
  110. package/dist/tools/relate.js +10 -0
  111. package/dist/tools/relate.js.map +1 -0
  112. package/dist/tools/search.d.ts +6 -0
  113. package/dist/tools/search.d.ts.map +1 -0
  114. package/dist/tools/search.js +43 -0
  115. package/dist/tools/search.js.map +1 -0
  116. package/dist/tools/store.d.ts +8 -0
  117. package/dist/tools/store.d.ts.map +1 -0
  118. package/dist/tools/store.js +64 -0
  119. package/dist/tools/store.js.map +1 -0
  120. package/dist/types/index.d.ts +289 -0
  121. package/dist/types/index.d.ts.map +1 -0
  122. package/dist/types/index.js +3 -0
  123. package/dist/types/index.js.map +1 -0
  124. package/docker-compose.yml +27 -0
  125. 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":"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"}
@@ -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"}