cortex-mcp 2.8.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (202) hide show
  1. package/CHANGELOG.md +305 -58
  2. package/README.md +394 -227
  3. package/dist/cli/setup.js +58 -60
  4. package/dist/cli/setup.js.map +1 -1
  5. package/dist/config/config.js +2 -2
  6. package/dist/config/config.js.map +1 -1
  7. package/dist/db/database.d.ts +8 -0
  8. package/dist/db/database.d.ts.map +1 -1
  9. package/dist/db/database.js +35 -54
  10. package/dist/db/database.js.map +1 -1
  11. package/dist/db/event-log.d.ts +4 -0
  12. package/dist/db/event-log.d.ts.map +1 -1
  13. package/dist/db/event-log.js +14 -10
  14. package/dist/db/event-log.js.map +1 -1
  15. package/dist/db/memory-store.d.ts +30 -3
  16. package/dist/db/memory-store.d.ts.map +1 -1
  17. package/dist/db/memory-store.js +153 -55
  18. package/dist/db/memory-store.js.map +1 -1
  19. package/dist/embedding-worker.js +1 -1
  20. package/dist/embedding-worker.js.map +1 -1
  21. package/dist/hooks/git-capture.js +3 -3
  22. package/dist/hooks/git-hooks.js +5 -2
  23. package/dist/mcp-stdio.js +70 -15
  24. package/dist/mcp-stdio.js.map +1 -1
  25. package/dist/memory/access-pattern-tracker.d.ts +51 -0
  26. package/dist/memory/access-pattern-tracker.d.ts.map +1 -0
  27. package/dist/memory/access-pattern-tracker.js +92 -0
  28. package/dist/memory/access-pattern-tracker.js.map +1 -0
  29. package/dist/memory/anticipation-engine.d.ts.map +1 -1
  30. package/dist/memory/anticipation-engine.js +18 -10
  31. package/dist/memory/anticipation-engine.js.map +1 -1
  32. package/dist/memory/auto-learner.d.ts.map +1 -1
  33. package/dist/memory/auto-learner.js +192 -45
  34. package/dist/memory/auto-learner.js.map +1 -1
  35. package/dist/memory/completion-resolver.d.ts +38 -0
  36. package/dist/memory/completion-resolver.d.ts.map +1 -0
  37. package/dist/memory/completion-resolver.js +127 -0
  38. package/dist/memory/completion-resolver.js.map +1 -0
  39. package/dist/memory/confidence-decay.d.ts.map +1 -1
  40. package/dist/memory/confidence-decay.js +13 -9
  41. package/dist/memory/confidence-decay.js.map +1 -1
  42. package/dist/memory/convention-detector.d.ts +11 -0
  43. package/dist/memory/convention-detector.d.ts.map +1 -0
  44. package/dist/memory/convention-detector.js +294 -0
  45. package/dist/memory/convention-detector.js.map +1 -0
  46. package/dist/memory/correction-detector.d.ts +33 -0
  47. package/dist/memory/correction-detector.d.ts.map +1 -0
  48. package/dist/memory/correction-detector.js +129 -0
  49. package/dist/memory/correction-detector.js.map +1 -0
  50. package/dist/memory/cross-memory-linker.d.ts +18 -0
  51. package/dist/memory/cross-memory-linker.d.ts.map +1 -0
  52. package/dist/memory/cross-memory-linker.js +115 -0
  53. package/dist/memory/cross-memory-linker.js.map +1 -0
  54. package/dist/memory/daily-diary.d.ts +30 -0
  55. package/dist/memory/daily-diary.d.ts.map +1 -0
  56. package/dist/memory/daily-diary.js +159 -0
  57. package/dist/memory/daily-diary.js.map +1 -0
  58. package/dist/memory/embedding-cache.d.ts +32 -0
  59. package/dist/memory/embedding-cache.d.ts.map +1 -0
  60. package/dist/memory/embedding-cache.js +76 -0
  61. package/dist/memory/embedding-cache.js.map +1 -0
  62. package/dist/memory/embedding-manager.d.ts.map +1 -1
  63. package/dist/memory/embedding-manager.js +6 -4
  64. package/dist/memory/embedding-manager.js.map +1 -1
  65. package/dist/memory/error-learner.d.ts +26 -0
  66. package/dist/memory/error-learner.d.ts.map +1 -0
  67. package/dist/memory/error-learner.js +145 -0
  68. package/dist/memory/error-learner.js.map +1 -0
  69. package/dist/memory/export-import.js +2 -2
  70. package/dist/memory/export-import.js.map +1 -1
  71. package/dist/memory/file-relationships.d.ts +47 -0
  72. package/dist/memory/file-relationships.d.ts.map +1 -0
  73. package/dist/memory/file-relationships.js +130 -0
  74. package/dist/memory/file-relationships.js.map +1 -0
  75. package/dist/memory/git-memory.d.ts.map +1 -1
  76. package/dist/memory/git-memory.js +20 -26
  77. package/dist/memory/git-memory.js.map +1 -1
  78. package/dist/memory/impact-analyzer.d.ts +16 -0
  79. package/dist/memory/impact-analyzer.d.ts.map +1 -0
  80. package/dist/memory/impact-analyzer.js +189 -0
  81. package/dist/memory/impact-analyzer.js.map +1 -0
  82. package/dist/memory/instructions-generator.d.ts +30 -0
  83. package/dist/memory/instructions-generator.d.ts.map +1 -0
  84. package/dist/memory/instructions-generator.js +117 -0
  85. package/dist/memory/instructions-generator.js.map +1 -0
  86. package/dist/memory/learning-rate.js +8 -7
  87. package/dist/memory/learning-rate.js.map +1 -1
  88. package/dist/memory/llm-enhancer.d.ts +2 -14
  89. package/dist/memory/llm-enhancer.d.ts.map +1 -1
  90. package/dist/memory/llm-enhancer.js +66 -46
  91. package/dist/memory/llm-enhancer.js.map +1 -1
  92. package/dist/memory/memory-cache.d.ts.map +1 -1
  93. package/dist/memory/memory-cache.js +10 -0
  94. package/dist/memory/memory-cache.js.map +1 -1
  95. package/dist/memory/memory-consolidator.d.ts.map +1 -1
  96. package/dist/memory/memory-consolidator.js +20 -14
  97. package/dist/memory/memory-consolidator.js.map +1 -1
  98. package/dist/memory/memory-decay.d.ts.map +1 -1
  99. package/dist/memory/memory-decay.js +82 -52
  100. package/dist/memory/memory-decay.js.map +1 -1
  101. package/dist/memory/memory-export-md.d.ts +12 -0
  102. package/dist/memory/memory-export-md.d.ts.map +1 -0
  103. package/dist/memory/memory-export-md.js +188 -0
  104. package/dist/memory/memory-export-md.js.map +1 -0
  105. package/dist/memory/memory-quality.d.ts +1 -1
  106. package/dist/memory/memory-quality.d.ts.map +1 -1
  107. package/dist/memory/memory-quality.js +13 -27
  108. package/dist/memory/memory-quality.js.map +1 -1
  109. package/dist/memory/memory-ranker.d.ts.map +1 -1
  110. package/dist/memory/memory-ranker.js +12 -3
  111. package/dist/memory/memory-ranker.js.map +1 -1
  112. package/dist/memory/meta-memory.js +3 -3
  113. package/dist/memory/meta-memory.js.map +1 -1
  114. package/dist/memory/mmr-reranker.d.ts +39 -0
  115. package/dist/memory/mmr-reranker.d.ts.map +1 -0
  116. package/dist/memory/mmr-reranker.js +115 -0
  117. package/dist/memory/mmr-reranker.js.map +1 -0
  118. package/dist/memory/pre-flight.d.ts +24 -0
  119. package/dist/memory/pre-flight.d.ts.map +1 -0
  120. package/dist/memory/pre-flight.js +121 -0
  121. package/dist/memory/pre-flight.js.map +1 -0
  122. package/dist/memory/preference-learner.d.ts +28 -0
  123. package/dist/memory/preference-learner.d.ts.map +1 -0
  124. package/dist/memory/preference-learner.js +144 -0
  125. package/dist/memory/preference-learner.js.map +1 -0
  126. package/dist/memory/query-expansion.d.ts +28 -0
  127. package/dist/memory/query-expansion.d.ts.map +1 -0
  128. package/dist/memory/query-expansion.js +140 -0
  129. package/dist/memory/query-expansion.js.map +1 -0
  130. package/dist/memory/regression-guard.d.ts +35 -0
  131. package/dist/memory/regression-guard.d.ts.map +1 -0
  132. package/dist/memory/regression-guard.js +90 -0
  133. package/dist/memory/regression-guard.js.map +1 -0
  134. package/dist/memory/resume-work.d.ts +37 -0
  135. package/dist/memory/resume-work.d.ts.map +1 -0
  136. package/dist/memory/resume-work.js +141 -0
  137. package/dist/memory/resume-work.js.map +1 -0
  138. package/dist/memory/session-tracker.d.ts +2 -0
  139. package/dist/memory/session-tracker.d.ts.map +1 -1
  140. package/dist/memory/session-tracker.js +26 -8
  141. package/dist/memory/session-tracker.js.map +1 -1
  142. package/dist/memory/soul-manager.d.ts +30 -0
  143. package/dist/memory/soul-manager.d.ts.map +1 -0
  144. package/dist/memory/soul-manager.js +171 -0
  145. package/dist/memory/soul-manager.js.map +1 -0
  146. package/dist/memory/success-tracker.d.ts +33 -0
  147. package/dist/memory/success-tracker.d.ts.map +1 -0
  148. package/dist/memory/success-tracker.js +75 -0
  149. package/dist/memory/success-tracker.js.map +1 -0
  150. package/dist/memory/temporal-engine.d.ts.map +1 -1
  151. package/dist/memory/temporal-engine.js +9 -13
  152. package/dist/memory/temporal-engine.js.map +1 -1
  153. package/dist/memory/tool-recommender.d.ts +29 -0
  154. package/dist/memory/tool-recommender.d.ts.map +1 -0
  155. package/dist/memory/tool-recommender.js +117 -0
  156. package/dist/memory/tool-recommender.js.map +1 -0
  157. package/dist/memory/usage-stats.d.ts +98 -0
  158. package/dist/memory/usage-stats.d.ts.map +1 -0
  159. package/dist/memory/usage-stats.js +345 -0
  160. package/dist/memory/usage-stats.js.map +1 -0
  161. package/dist/retrieval/hybrid-retriever.d.ts +0 -2
  162. package/dist/retrieval/hybrid-retriever.d.ts.map +1 -1
  163. package/dist/retrieval/hybrid-retriever.js +3 -13
  164. package/dist/retrieval/hybrid-retriever.js.map +1 -1
  165. package/dist/scanners/architecture-graph.js +2 -2
  166. package/dist/scanners/architecture-graph.js.map +1 -1
  167. package/dist/scanners/code-verifier.d.ts +1 -0
  168. package/dist/scanners/code-verifier.d.ts.map +1 -1
  169. package/dist/scanners/code-verifier.js +14 -14
  170. package/dist/scanners/code-verifier.js.map +1 -1
  171. package/dist/scanners/context-builder.d.ts.map +1 -1
  172. package/dist/scanners/context-builder.js +33 -45
  173. package/dist/scanners/context-builder.js.map +1 -1
  174. package/dist/scanners/export-map.js +2 -2
  175. package/dist/scanners/export-map.js.map +1 -1
  176. package/dist/scanners/project-scanner.js +2 -2
  177. package/dist/scanners/project-scanner.js.map +1 -1
  178. package/dist/security/encryption.js +1 -1
  179. package/dist/security/encryption.js.map +1 -1
  180. package/dist/security/feature-gate.d.ts.map +1 -1
  181. package/dist/security/feature-gate.js +62 -20
  182. package/dist/security/feature-gate.js.map +1 -1
  183. package/dist/security/license.js +282 -35
  184. package/dist/security/license.js.map +1 -1
  185. package/dist/security/rate-limiter.d.ts +4 -3
  186. package/dist/security/rate-limiter.d.ts.map +1 -1
  187. package/dist/security/rate-limiter.js +11 -29
  188. package/dist/security/rate-limiter.js.map +1 -1
  189. package/dist/server/dashboard.js +166 -327
  190. package/dist/server/dashboard.js.map +1 -1
  191. package/dist/server/mcp-handler.d.ts.map +1 -1
  192. package/dist/server/mcp-handler.js +991 -1019
  193. package/dist/server/mcp-handler.js.map +1 -1
  194. package/dist/utils/extract-tags.d.ts +16 -0
  195. package/dist/utils/extract-tags.d.ts.map +1 -0
  196. package/dist/utils/extract-tags.js +40 -0
  197. package/dist/utils/extract-tags.js.map +1 -0
  198. package/package.json +18 -8
  199. package/dist/core/event-bus.d.ts +0 -19
  200. package/dist/core/event-bus.d.ts.map +0 -1
  201. package/dist/core/event-bus.js +0 -51
  202. package/dist/core/event-bus.js.map +0 -1
@@ -0,0 +1,129 @@
1
+ "use strict";
2
+ /**
3
+ * Correction Detector — Catches user corrections automatically.
4
+ *
5
+ * The #1 gap in Cortex: when a user says "no, use X instead of Y",
6
+ * that correction is LOST when the conversation ends.
7
+ *
8
+ * This module scans text (both AI responses and user context) for
9
+ * correction patterns and auto-stores them as high-importance CORRECTION memories.
10
+ *
11
+ * Examples it catches:
12
+ * - "no, use vectors not vectorCache"
13
+ * - "that's wrong, it should be const"
14
+ * - "actually the file is in src/db/"
15
+ * - "I meant to use path.join"
16
+ */
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.detectUserCorrections = detectUserCorrections;
19
+ exports.detectAIAcknowledgments = detectAIAcknowledgments;
20
+ // ─── Correction Patterns ─────────────────────────────────────────────────────
21
+ const USER_CORRECTION_PATTERNS = [
22
+ // "no, use X not Y" / "no use X instead of Y"
23
+ {
24
+ regex: /\bno[,.]?\s+(use|it'?s|it should be|should be|change to|switch to)\s+(.{3,50}?)(?:\s+(?:not|instead of|rather than)\s+(.{3,50}))?[.!]?\s*$/gim,
25
+ extractGroups: (m) => ({ corrected: m[2]?.trim(), original: m[3]?.trim() }),
26
+ confidence: 0.90,
27
+ },
28
+ // "that's wrong" / "that's incorrect" / "that's not right"
29
+ {
30
+ regex: /\b(that'?s|this is)\s+(wrong|incorrect|not right|not correct|a mistake)\b.{0,80}/gi,
31
+ extractGroups: () => ({}),
32
+ confidence: 0.85,
33
+ },
34
+ // "actually, X" / "actually it should be X"
35
+ {
36
+ regex: /\bactually[,.]?\s+(it\s+)?(should be|is|use|the\s+\w+\s+is)\s+(.{5,80})/gi,
37
+ extractGroups: (m) => ({ corrected: m[3]?.trim() }),
38
+ confidence: 0.80,
39
+ },
40
+ // "I meant X" / "I mean X"
41
+ {
42
+ regex: /\bI\s+mean[t]?\s+(.{5,80})/gi,
43
+ extractGroups: (m) => ({ corrected: m[1]?.trim() }),
44
+ confidence: 0.75,
45
+ },
46
+ // "not X, but Y" / "not X, Y"
47
+ {
48
+ regex: /\bnot\s+(.{3,40}?)[,]\s*(but\s+)?(.{3,40})/gi,
49
+ extractGroups: (m) => ({ original: m[1]?.trim(), corrected: m[3]?.trim() }),
50
+ confidence: 0.70,
51
+ },
52
+ // "X is wrong" / "X is incorrect"
53
+ {
54
+ regex: /\b(.{5,40})\s+is\s+(wrong|incorrect|broken|outdated|deprecated)/gi,
55
+ extractGroups: (m) => ({ original: m[1]?.trim() }),
56
+ confidence: 0.75,
57
+ },
58
+ ];
59
+ // AI acknowledgment patterns — when the AI itself admits a mistake
60
+ const AI_ACKNOWLEDGMENT_PATTERNS = [
61
+ { regex: /\b(I apologize|sorry|my mistake|my bad|you'?re right|good catch)\b/gi, confidence: 0.85 },
62
+ { regex: /\b(let me fix that|let me correct|I was wrong|I made an error)\b/gi, confidence: 0.90 },
63
+ { regex: /\b(should have (used|been|done)|instead of .{3,30} I should)\b/gi, confidence: 0.85 },
64
+ { regex: /\b(the (correct|right|actual|proper) (way|approach|method|answer) is)\b/gi, confidence: 0.80 },
65
+ ];
66
+ // ─── Main Detector ───────────────────────────────────────────────────────────
67
+ /**
68
+ * Detect corrections from user context text.
69
+ * Call this when auto_learn receives context about what the user said.
70
+ */
71
+ function detectUserCorrections(userText) {
72
+ if (!userText || userText.length < 10)
73
+ return [];
74
+ const results = [];
75
+ const sentences = splitIntoSentences(userText);
76
+ for (const sentence of sentences) {
77
+ for (const pattern of USER_CORRECTION_PATTERNS) {
78
+ pattern.regex.lastIndex = 0;
79
+ const match = pattern.regex.exec(sentence);
80
+ if (match) {
81
+ const groups = pattern.extractGroups(match);
82
+ results.push({
83
+ original: groups.original || '',
84
+ corrected: groups.corrected || '',
85
+ fullContext: sentence.trim().slice(0, 200),
86
+ confidence: pattern.confidence,
87
+ source: 'user_correction',
88
+ });
89
+ break; // One match per sentence
90
+ }
91
+ }
92
+ }
93
+ return results;
94
+ }
95
+ /**
96
+ * Detect when the AI acknowledges a mistake in its own response.
97
+ * Call this from auto_learn on the AI's response text.
98
+ */
99
+ function detectAIAcknowledgments(aiText) {
100
+ if (!aiText || aiText.length < 15)
101
+ return [];
102
+ const results = [];
103
+ const sentences = splitIntoSentences(aiText);
104
+ for (const sentence of sentences) {
105
+ for (const pattern of AI_ACKNOWLEDGMENT_PATTERNS) {
106
+ pattern.regex.lastIndex = 0;
107
+ if (pattern.regex.test(sentence)) {
108
+ results.push({
109
+ original: '',
110
+ corrected: '',
111
+ fullContext: sentence.trim().slice(0, 200),
112
+ confidence: pattern.confidence,
113
+ source: 'ai_acknowledgment',
114
+ });
115
+ break;
116
+ }
117
+ }
118
+ }
119
+ return results;
120
+ }
121
+ // ─── Helper ──────────────────────────────────────────────────────────────────
122
+ function splitIntoSentences(text) {
123
+ return text
124
+ .replace(/\n+/g, '. ')
125
+ .split(/(?<=[.!?])\s+/)
126
+ .map(s => s.trim())
127
+ .filter(s => s.length > 8 && s.length < 300);
128
+ }
129
+ //# sourceMappingURL=correction-detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"correction-detector.js","sourceRoot":"","sources":["../../src/memory/correction-detector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Cross-Memory Linker — Automatically creates edges between related memories.
3
+ *
4
+ * When a new memory is stored, this module finds existing memories that share
5
+ * topics, files, or keywords and creates graph edges between them.
6
+ *
7
+ * This transforms isolated memories into a connected knowledge graph.
8
+ * When the user asks "tell me about auth", they get a connected story
9
+ * instead of random fragments.
10
+ */
11
+ import { MemoryStore } from '../db/memory-store';
12
+ import type { MemoryUnit } from '../types';
13
+ /**
14
+ * After storing a new memory, auto-link it to related existing memories.
15
+ * Uses 3 signals: shared files, shared tags, and word overlap.
16
+ */
17
+ export declare function autoLinkMemory(memoryStore: MemoryStore, newMemory: MemoryUnit): number;
18
+ //# sourceMappingURL=cross-memory-linker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cross-memory-linker.d.ts","sourceRoot":"","sources":["../../src/memory/cross-memory-linker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,KAAK,EAAE,UAAU,EAAa,MAAM,UAAU,CAAC;AAEtD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,WAAW,EAAE,WAAW,EAAE,SAAS,EAAE,UAAU,GAAG,MAAM,CAyEtF"}
@@ -0,0 +1,115 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.autoLinkMemory = autoLinkMemory;
4
+ /**
5
+ * After storing a new memory, auto-link it to related existing memories.
6
+ * Uses 3 signals: shared files, shared tags, and word overlap.
7
+ */
8
+ function autoLinkMemory(memoryStore, newMemory) {
9
+ let linksCreated = 0;
10
+ try {
11
+ // 1. Find memories sharing the same files
12
+ const fileRelated = [];
13
+ if (newMemory.relatedFiles && newMemory.relatedFiles.length > 0) {
14
+ for (const file of newMemory.relatedFiles.slice(0, 3)) {
15
+ const basename = file.split(/[/\\]/).pop() || file;
16
+ const related = memoryStore.getByFile(basename, 10);
17
+ for (const m of related) {
18
+ if (m.id !== newMemory.id && m.isActive) {
19
+ fileRelated.push(m);
20
+ }
21
+ }
22
+ }
23
+ }
24
+ // 2. Find memories sharing tags
25
+ const tagRelated = [];
26
+ const newTags = parseTags(newMemory.tags);
27
+ if (newTags.length > 0) {
28
+ for (const tag of newTags.slice(0, 3)) {
29
+ try {
30
+ const tagged = memoryStore.findByTag(tag, 10);
31
+ for (const m of tagged) {
32
+ if (m.id !== newMemory.id && m.isActive) {
33
+ tagRelated.push(m);
34
+ }
35
+ }
36
+ }
37
+ catch { /* tag search might fail */ }
38
+ }
39
+ }
40
+ // 3. Compute word overlap with recent memories
41
+ const newWords = extractKeywords(newMemory.intent);
42
+ const recentMemories = memoryStore.getActive(50);
43
+ const wordRelated = [];
44
+ for (const m of recentMemories) {
45
+ if (m.id === newMemory.id)
46
+ continue;
47
+ const mWords = extractKeywords(m.intent);
48
+ const overlap = wordOverlap(newWords, mWords);
49
+ if (overlap >= 0.3) { // 30%+ word overlap → related
50
+ wordRelated.push(m);
51
+ }
52
+ }
53
+ // Deduplicate and create edges
54
+ const seen = new Set();
55
+ const candidates = [...fileRelated, ...tagRelated, ...wordRelated];
56
+ for (const related of candidates) {
57
+ if (seen.has(related.id))
58
+ continue;
59
+ seen.add(related.id);
60
+ if (linksCreated >= 5)
61
+ break; // Max 5 links per memory
62
+ const edgeType = fileRelated.includes(related) ? 'same_file' :
63
+ tagRelated.includes(related) ? 'same_topic' : 'similar';
64
+ try {
65
+ memoryStore.addEdge({
66
+ sourceId: newMemory.id,
67
+ targetId: related.id,
68
+ edgeType,
69
+ weight: edgeType === 'same_file' ? 0.9 :
70
+ edgeType === 'same_topic' ? 0.7 : 0.5,
71
+ });
72
+ linksCreated++;
73
+ }
74
+ catch { /* edge might already exist */ }
75
+ }
76
+ }
77
+ catch { /* don't break memory storage if linking fails */ }
78
+ return linksCreated;
79
+ }
80
+ // ─── Helpers ──────────────────────────────────────────────────────────────────
81
+ function parseTags(tags) {
82
+ if (!tags)
83
+ return [];
84
+ if (Array.isArray(tags))
85
+ return tags;
86
+ if (typeof tags === 'string') {
87
+ try {
88
+ return JSON.parse(tags);
89
+ }
90
+ catch {
91
+ return [];
92
+ }
93
+ }
94
+ return [];
95
+ }
96
+ function extractKeywords(text) {
97
+ const STOP = new Set(['the', 'a', 'an', 'is', 'are', 'was', 'were', 'to', 'of', 'in',
98
+ 'for', 'on', 'with', 'at', 'by', 'from', 'use', 'always', 'never', 'should',
99
+ 'must', 'not', 'do', 'be', 'it', 'this', 'that', 'and', 'or', 'but', 'we', 'i']);
100
+ return new Set(text.toLowerCase()
101
+ .replace(/[^a-z0-9\s]/g, ' ')
102
+ .split(/\s+/)
103
+ .filter(w => w.length > 2 && !STOP.has(w)));
104
+ }
105
+ function wordOverlap(a, b) {
106
+ if (a.size === 0 || b.size === 0)
107
+ return 0;
108
+ let shared = 0;
109
+ for (const word of a) {
110
+ if (b.has(word))
111
+ shared++;
112
+ }
113
+ return shared / Math.min(a.size, b.size);
114
+ }
115
+ //# sourceMappingURL=cross-memory-linker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cross-memory-linker.js","sourceRoot":"","sources":["../../src/memory/cross-memory-linker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ export interface DiaryEntry {
2
+ type: 'decision' | 'correction' | 'bug_fix' | 'convention' | 'insight' | 'task' | 'file_change';
3
+ content: string;
4
+ file?: string;
5
+ }
6
+ /**
7
+ * Append an entry to today's diary.
8
+ */
9
+ export declare function appendDiaryEntry(entry: DiaryEntry): void;
10
+ /**
11
+ * Get diary content for a specific date.
12
+ */
13
+ export declare function getDiaryForDate(date: string): string | null;
14
+ /**
15
+ * Get the last N days of diary entries combined.
16
+ */
17
+ export declare function getRecentDiary(days?: number): string;
18
+ /**
19
+ * Format diary context for injection into force_recall.
20
+ * Returns last 2 days of diary, condensed.
21
+ */
22
+ export declare function formatDiaryContext(): string;
23
+ /**
24
+ * Get diary stats for dashboard.
25
+ */
26
+ export declare function getDiaryStats(): {
27
+ totalDays: number;
28
+ todayEntries: number;
29
+ };
30
+ //# sourceMappingURL=daily-diary.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daily-diary.d.ts","sourceRoot":"","sources":["../../src/memory/daily-diary.ts"],"names":[],"mappings":"AAmBA,MAAM,WAAW,UAAU;IACvB,IAAI,EAAE,UAAU,GAAG,YAAY,GAAG,SAAS,GAAG,YAAY,GAAG,SAAS,GAAG,MAAM,GAAG,aAAa,CAAC;IAChG,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACjB;AAID;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAoBxD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQ3D;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,GAAE,MAAU,GAAG,MAAM,CAevD;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAU3C;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,CAY3E"}
@@ -0,0 +1,159 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.appendDiaryEntry = appendDiaryEntry;
37
+ exports.getDiaryForDate = getDiaryForDate;
38
+ exports.getRecentDiary = getRecentDiary;
39
+ exports.formatDiaryContext = formatDiaryContext;
40
+ exports.getDiaryStats = getDiaryStats;
41
+ /**
42
+ * Daily Diary — OpenClaw-style daily Markdown logs.
43
+ *
44
+ * Writes append-only daily notes like OpenClaw's memory/YYYY-MM-DD.md.
45
+ * Each day gets its own file with timestamped entries:
46
+ * - What was learned
47
+ * - What files changed
48
+ * - What decisions were made
49
+ * - What bugs were fixed
50
+ *
51
+ * This gives the AI a "running journal" of recent work.
52
+ * Injected into force_recall as Layer 7.5 (recent context).
53
+ *
54
+ * Stored in: ~/.cortex-memory/diary/YYYY-MM-DD.md
55
+ */
56
+ const fs = __importStar(require("fs"));
57
+ const path = __importStar(require("path"));
58
+ const os = __importStar(require("os"));
59
+ const DIARY_DIR = path.join(os.homedir(), '.cortex-memory', 'diary');
60
+ /**
61
+ * Append an entry to today's diary.
62
+ */
63
+ function appendDiaryEntry(entry) {
64
+ try {
65
+ if (!fs.existsSync(DIARY_DIR))
66
+ fs.mkdirSync(DIARY_DIR, { recursive: true });
67
+ const today = getDateString();
68
+ const diaryPath = path.join(DIARY_DIR, `${today}.md`);
69
+ const time = new Date().toLocaleTimeString('en-US', { hour12: false, hour: '2-digit', minute: '2-digit' });
70
+ const icon = ICONS[entry.type] || '📝';
71
+ const fileSuffix = entry.file ? ` _(${path.basename(entry.file)})_` : '';
72
+ const line = `- ${time} ${icon} **${entry.type.toUpperCase()}**: ${entry.content}${fileSuffix}\n`;
73
+ // Create header if new file
74
+ if (!fs.existsSync(diaryPath)) {
75
+ const header = `# 📔 Cortex Diary — ${today}\n\n`;
76
+ fs.writeFileSync(diaryPath, header, 'utf-8');
77
+ }
78
+ fs.appendFileSync(diaryPath, line, 'utf-8');
79
+ }
80
+ catch { /* diary is non-critical */ }
81
+ }
82
+ /**
83
+ * Get diary content for a specific date.
84
+ */
85
+ function getDiaryForDate(date) {
86
+ try {
87
+ const diaryPath = path.join(DIARY_DIR, `${date}.md`);
88
+ if (fs.existsSync(diaryPath)) {
89
+ return fs.readFileSync(diaryPath, 'utf-8');
90
+ }
91
+ }
92
+ catch { /* */ }
93
+ return null;
94
+ }
95
+ /**
96
+ * Get the last N days of diary entries combined.
97
+ */
98
+ function getRecentDiary(days = 3) {
99
+ const entries = [];
100
+ const now = Date.now();
101
+ const DAY = 24 * 60 * 60 * 1000;
102
+ for (let i = 0; i < days; i++) {
103
+ const date = new Date(now - i * DAY);
104
+ const dateStr = formatDate(date);
105
+ const content = getDiaryForDate(dateStr);
106
+ if (content && content.trim().length > 50) {
107
+ entries.push(content.trim());
108
+ }
109
+ }
110
+ return entries.join('\n\n---\n\n');
111
+ }
112
+ /**
113
+ * Format diary context for injection into force_recall.
114
+ * Returns last 2 days of diary, condensed.
115
+ */
116
+ function formatDiaryContext() {
117
+ const diary = getRecentDiary(2);
118
+ if (!diary || diary.length < 50)
119
+ return '';
120
+ // Truncate to last 20 entries to avoid flooding context
121
+ const lines = diary.split('\n').filter(l => l.startsWith('- '));
122
+ const recent = lines.slice(-20);
123
+ if (recent.length === 0)
124
+ return '';
125
+ return `\n## 📔 Recent Diary (last 2 days)\n${recent.join('\n')}`;
126
+ }
127
+ /**
128
+ * Get diary stats for dashboard.
129
+ */
130
+ function getDiaryStats() {
131
+ try {
132
+ if (!fs.existsSync(DIARY_DIR))
133
+ return { totalDays: 0, todayEntries: 0 };
134
+ const files = fs.readdirSync(DIARY_DIR).filter(f => f.endsWith('.md'));
135
+ const today = getDiaryForDate(getDateString());
136
+ const todayEntries = today ? today.split('\n').filter(l => l.startsWith('- ')).length : 0;
137
+ return { totalDays: files.length, todayEntries };
138
+ }
139
+ catch {
140
+ return { totalDays: 0, todayEntries: 0 };
141
+ }
142
+ }
143
+ // ─── Helpers ──────────────────────────────────────────────────────────────────
144
+ const ICONS = {
145
+ decision: '📌',
146
+ correction: '🔴',
147
+ bug_fix: '🐛',
148
+ convention: '📏',
149
+ insight: '💡',
150
+ task: '📋',
151
+ file_change: '📁',
152
+ };
153
+ function getDateString() {
154
+ return formatDate(new Date());
155
+ }
156
+ function formatDate(d) {
157
+ return d.toISOString().split('T')[0]; // YYYY-MM-DD
158
+ }
159
+ //# sourceMappingURL=daily-diary.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daily-diary.js","sourceRoot":"","sources":["../../src/memory/daily-diary.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Embedding Cache — Avoids re-computing embeddings for identical text.
3
+ *
4
+ * Extracted from OpenClaw's embedding_cache table architecture.
5
+ *
6
+ * Problem: Every recall re-embeds the query, even if it's the exact same text.
7
+ * With MiniLM this takes ~50ms per embedding — adds up fast.
8
+ *
9
+ * Solution: Cache embeddings in memory with an LRU eviction policy.
10
+ * Cache key = hash of the text content.
11
+ */
12
+ /**
13
+ * Get a cached embedding for text, or null if not cached.
14
+ */
15
+ export declare function getCachedEmbedding(text: string): number[] | null;
16
+ /**
17
+ * Store an embedding in the cache.
18
+ * Uses LRU eviction when cache is full.
19
+ */
20
+ export declare function cacheEmbedding(text: string, embedding: number[]): void;
21
+ /**
22
+ * Clear the entire embedding cache.
23
+ */
24
+ export declare function clearEmbeddingCache(): void;
25
+ /**
26
+ * Get cache stats for debugging/dashboard.
27
+ */
28
+ export declare function getEmbeddingCacheStats(): {
29
+ size: number;
30
+ maxSize: number;
31
+ };
32
+ //# sourceMappingURL=embedding-cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embedding-cache.d.ts","sourceRoot":"","sources":["../../src/memory/embedding-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAuBH;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,CAQhE;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,IAAI,CAiBtE;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,IAAI,CAE1C;AAED;;GAEG;AACH,wBAAgB,sBAAsB,IAAI;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAE1E"}
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ /**
3
+ * Embedding Cache — Avoids re-computing embeddings for identical text.
4
+ *
5
+ * Extracted from OpenClaw's embedding_cache table architecture.
6
+ *
7
+ * Problem: Every recall re-embeds the query, even if it's the exact same text.
8
+ * With MiniLM this takes ~50ms per embedding — adds up fast.
9
+ *
10
+ * Solution: Cache embeddings in memory with an LRU eviction policy.
11
+ * Cache key = hash of the text content.
12
+ */
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.getCachedEmbedding = getCachedEmbedding;
15
+ exports.cacheEmbedding = cacheEmbedding;
16
+ exports.clearEmbeddingCache = clearEmbeddingCache;
17
+ exports.getEmbeddingCacheStats = getEmbeddingCacheStats;
18
+ const CACHE_MAX = 256;
19
+ const cache = new Map();
20
+ /**
21
+ * Simple FNV-1a hash — fast and good enough for cache keys.
22
+ */
23
+ function hashText(text) {
24
+ let hash = 0x811c9dc5;
25
+ for (let i = 0; i < text.length; i++) {
26
+ hash ^= text.charCodeAt(i);
27
+ hash = (hash * 0x01000193) >>> 0;
28
+ }
29
+ return hash.toString(36);
30
+ }
31
+ /**
32
+ * Get a cached embedding for text, or null if not cached.
33
+ */
34
+ function getCachedEmbedding(text) {
35
+ const key = hashText(text);
36
+ const entry = cache.get(key);
37
+ if (entry) {
38
+ entry.timestamp = Date.now(); // Touch for LRU
39
+ return entry.embedding;
40
+ }
41
+ return null;
42
+ }
43
+ /**
44
+ * Store an embedding in the cache.
45
+ * Uses LRU eviction when cache is full.
46
+ */
47
+ function cacheEmbedding(text, embedding) {
48
+ const key = hashText(text);
49
+ // LRU eviction if full
50
+ if (cache.size >= CACHE_MAX && !cache.has(key)) {
51
+ let oldestKey = '';
52
+ let oldestTime = Infinity;
53
+ for (const [k, v] of cache) {
54
+ if (v.timestamp < oldestTime) {
55
+ oldestTime = v.timestamp;
56
+ oldestKey = k;
57
+ }
58
+ }
59
+ if (oldestKey)
60
+ cache.delete(oldestKey);
61
+ }
62
+ cache.set(key, { embedding, timestamp: Date.now() });
63
+ }
64
+ /**
65
+ * Clear the entire embedding cache.
66
+ */
67
+ function clearEmbeddingCache() {
68
+ cache.clear();
69
+ }
70
+ /**
71
+ * Get cache stats for debugging/dashboard.
72
+ */
73
+ function getEmbeddingCacheStats() {
74
+ return { size: cache.size, maxSize: CACHE_MAX };
75
+ }
76
+ //# sourceMappingURL=embedding-cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embedding-cache.js","sourceRoot":"","sources":["../../src/memory/embedding-cache.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;;AA0BH,gDAQC;AAMD,wCAiBC;AAKD,kDAEC;AAKD,wDAEC;AArED,MAAM,SAAS,GAAG,GAAG,CAAC;AAOtB,MAAM,KAAK,GAAG,IAAI,GAAG,EAAsB,CAAC;AAE5C;;GAEG;AACH,SAAS,QAAQ,CAAC,IAAY;IAC1B,IAAI,IAAI,GAAG,UAAU,CAAC;IACtB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACnC,IAAI,IAAI,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QAC3B,IAAI,GAAG,CAAC,IAAI,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IACrC,CAAC;IACD,OAAO,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC7B,CAAC;AAED;;GAEG;AACH,SAAgB,kBAAkB,CAAC,IAAY;IAC3C,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC3B,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC7B,IAAI,KAAK,EAAE,CAAC;QACR,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,gBAAgB;QAC9C,OAAO,KAAK,CAAC,SAAS,CAAC;IAC3B,CAAC;IACD,OAAO,IAAI,CAAC;AAChB,CAAC;AAED;;;GAGG;AACH,SAAgB,cAAc,CAAC,IAAY,EAAE,SAAmB;IAC5D,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IAE3B,uBAAuB;IACvB,IAAI,KAAK,CAAC,IAAI,IAAI,SAAS,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;QAC7C,IAAI,SAAS,GAAG,EAAE,CAAC;QACnB,IAAI,UAAU,GAAG,QAAQ,CAAC;QAC1B,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,CAAC,CAAC,SAAS,GAAG,UAAU,EAAE,CAAC;gBAC3B,UAAU,GAAG,CAAC,CAAC,SAAS,CAAC;gBACzB,SAAS,GAAG,CAAC,CAAC;YAClB,CAAC;QACL,CAAC;QACD,IAAI,SAAS;YAAE,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IAC3C,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;AACzD,CAAC;AAED;;GAEG;AACH,SAAgB,mBAAmB;IAC/B,KAAK,CAAC,KAAK,EAAE,CAAC;AAClB,CAAC;AAED;;GAEG;AACH,SAAgB,sBAAsB;IAClC,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;AACpD,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"embedding-manager.d.ts","sourceRoot":"","sources":["../../src/memory/embedding-manager.ts"],"names":[],"mappings":"AAeA,wBAAgB,oBAAoB,IAAI,IAAI,CAG3C;AAiED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CA4BzD;AAED,wBAAgB,aAAa,IAAI,OAAO,CAEvC;AAED,wBAAgB,eAAe,IAAI,IAAI,CAMtC"}
1
+ {"version":3,"file":"embedding-manager.d.ts","sourceRoot":"","sources":["../../src/memory/embedding-manager.ts"],"names":[],"mappings":"AAeA,wBAAgB,oBAAoB,IAAI,IAAI,CAK3C;AAiED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CA4BzD;AAED,wBAAgB,aAAa,IAAI,OAAO,CAEvC;AAED,wBAAgB,eAAe,IAAI,IAAI,CAMtC"}
@@ -50,8 +50,10 @@ let workerReady = false;
50
50
  const pendingEmbeddings = new Map();
51
51
  let workerFailed = false;
52
52
  function startEmbeddingWorker() {
53
- // Lazy: just mark that we want embedding. Actual worker starts on first use.
54
- console.log(' [cortex-mcp] Embedding worker registered (lazy — starts on first use)');
53
+ // Eagerly boot worker on startup to avoid 5-10s latency on first use
54
+ if (!ensureWorkerStarted()) {
55
+ console.log(' [cortex-mcp] Embedding worker unavailable, running FTS-only mode');
56
+ }
55
57
  }
56
58
  function ensureWorkerStarted() {
57
59
  if (embeddingWorker)
@@ -98,7 +100,7 @@ function ensureWorkerStarted() {
98
100
  workerFailed = true;
99
101
  embeddingWorker = null;
100
102
  // Reject all pending embeddings
101
- for (const [id, pending] of pendingEmbeddings) {
103
+ for (const [_id, pending] of pendingEmbeddings) {
102
104
  pending.reject(new Error('Worker crashed'));
103
105
  }
104
106
  pendingEmbeddings.clear();
@@ -110,7 +112,7 @@ function ensureWorkerStarted() {
110
112
  workerFailed = true;
111
113
  embeddingWorker = null;
112
114
  // Reject all pending embeddings
113
- for (const [id, pending] of pendingEmbeddings) {
115
+ for (const [_id, pending] of pendingEmbeddings) {
114
116
  pending.reject(new Error('Worker exited'));
115
117
  }
116
118
  pendingEmbeddings.clear();