@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,174 @@
1
+ const DEDUP_THRESHOLD = 0.92;
2
+ // Decision/pattern signal words for local scoring
3
+ const DECISION_WORDS = ['decided', 'chose', 'chosen', 'because', 'reason', 'why', 'opted', 'selected', 'agreed'];
4
+ const PATTERN_WORDS = ['always', 'never', 'convention', 'standard', 'rule', 'pattern', 'practice', 'approach'];
5
+ const TECHNICAL_WORDS = [
6
+ 'api', 'service', 'database', 'cache', 'queue', 'module', 'component',
7
+ 'function', 'class', 'interface', 'config', 'deploy', 'migration',
8
+ 'auth', 'token', 'endpoint', 'schema', 'model', 'query',
9
+ ];
10
+ const AUTO_EXTRACTION_SYSTEM_PROMPT = `You are analyzing a series of tool calls from a development session. Extract any new knowledge worth remembering.
11
+
12
+ For each piece of knowledge, return:
13
+ - content: a clear, standalone statement of the knowledge
14
+ - type: one of insight, decision, pattern, snippet, fact, note
15
+ - tags: relevant tags
16
+ - entities: technical entity names (snake_case)
17
+ - confidence: 0-1 how confident you are this is worth remembering
18
+ - relationships: any entity relationships discovered (from, relation, to)
19
+
20
+ Only extract genuinely useful information. Skip trivial operations.
21
+ Recent memories already stored (do not duplicate): {recentContext}
22
+
23
+ Return JSON only:
24
+ {
25
+ "memories": [
26
+ {
27
+ "content": "string",
28
+ "type": "insight|decision|pattern|snippet|fact|note",
29
+ "tags": ["string"],
30
+ "entities": ["string"],
31
+ "confidence": number,
32
+ "relationships": [{"from": "string", "relation": "DEPENDS_ON|USES|PART_OF|RELATED_TO|IMPLEMENTS|CALLS", "to": "string"}]
33
+ }
34
+ ]
35
+ }`;
36
+ export async function extractWithLLM(events, recentContext, llmClient) {
37
+ const eventsText = events
38
+ .map(e => `[${e.tool}] Input: ${JSON.stringify(e.input)}\nOutput: ${JSON.stringify(e.output)}`)
39
+ .join('\n\n');
40
+ const systemPrompt = AUTO_EXTRACTION_SYSTEM_PROMPT.replace('{recentContext}', recentContext);
41
+ const response = await llmClient.extractJSON(systemPrompt, eventsText);
42
+ if (!response?.memories)
43
+ return [];
44
+ const validTypes = new Set(['insight', 'decision', 'pattern', 'snippet', 'fact', 'note']);
45
+ const project = events[0]?.project ?? null;
46
+ return response.memories
47
+ .filter(m => m.content && validTypes.has(m.type) && m.confidence > 0.3)
48
+ .map(m => ({
49
+ content: m.content,
50
+ type: m.type,
51
+ tags: m.tags || [],
52
+ entities: m.entities || [],
53
+ project,
54
+ source: 'auto-extraction',
55
+ confidence: m.confidence,
56
+ relationships: (m.relationships || []).map(r => ({
57
+ from: r.from,
58
+ relation: r.relation,
59
+ to: r.to,
60
+ })),
61
+ }));
62
+ }
63
+ export async function extractLocally(events, recentMemories, extractor, embedder, qdrant) {
64
+ // 1. Concatenate all tool inputs/outputs into text
65
+ const textParts = [];
66
+ let project = null;
67
+ for (const event of events) {
68
+ if (event.project && !project)
69
+ project = event.project;
70
+ // Extract text from inputs
71
+ const inputText = extractTextFromObject(event.input);
72
+ if (inputText)
73
+ textParts.push(inputText);
74
+ // Extract text from outputs
75
+ const outputText = extractTextFromObject(event.output);
76
+ if (outputText)
77
+ textParts.push(outputText);
78
+ }
79
+ const fullText = textParts.join('\n');
80
+ if (!fullText.trim())
81
+ return [];
82
+ // 2. Run entity extraction on the full text
83
+ const extraction = await extractor.extract(fullText, project ?? undefined);
84
+ // 3. Split into sentences and score them
85
+ const sentences = fullText
86
+ .split(/[.!?\n]+/)
87
+ .map(s => s.trim())
88
+ .filter(s => s.length > 20);
89
+ const scoredSentences = sentences.map(sentence => ({
90
+ sentence,
91
+ score: scoreSentence(sentence),
92
+ type: inferMemoryType(sentence),
93
+ }));
94
+ // 4. Keep top-scoring sentences (above threshold)
95
+ const candidates = scoredSentences
96
+ .filter(s => s.score > 0.3)
97
+ .sort((a, b) => b.score - a.score)
98
+ .slice(0, 5);
99
+ // 5. Dedup against existing memories
100
+ const memories = [];
101
+ for (const candidate of candidates) {
102
+ const isDuplicate = await checkDuplicate(candidate.sentence, embedder, qdrant);
103
+ if (isDuplicate)
104
+ continue;
105
+ memories.push({
106
+ content: candidate.sentence,
107
+ type: candidate.type,
108
+ tags: [],
109
+ entities: extraction.entities.map(e => e.name),
110
+ project,
111
+ source: 'auto-extraction',
112
+ confidence: candidate.score,
113
+ relationships: extraction.relationships.map(r => ({
114
+ from: r.from,
115
+ relation: r.relation,
116
+ to: r.to,
117
+ })),
118
+ });
119
+ }
120
+ return memories;
121
+ }
122
+ function extractTextFromObject(obj) {
123
+ const parts = [];
124
+ for (const value of Object.values(obj)) {
125
+ if (typeof value === 'string' && value.length > 10) {
126
+ parts.push(value);
127
+ }
128
+ else if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
129
+ parts.push(extractTextFromObject(value));
130
+ }
131
+ }
132
+ return parts.join('\n');
133
+ }
134
+ function scoreSentence(sentence) {
135
+ const lower = sentence.toLowerCase();
136
+ let score = 0;
137
+ // Technical term density
138
+ const techCount = TECHNICAL_WORDS.filter(w => lower.includes(w)).length;
139
+ score += Math.min(techCount * 0.1, 0.3);
140
+ // Decision signals
141
+ const decisionCount = DECISION_WORDS.filter(w => lower.includes(w)).length;
142
+ score += Math.min(decisionCount * 0.15, 0.3);
143
+ // Pattern signals
144
+ const patternCount = PATTERN_WORDS.filter(w => lower.includes(w)).length;
145
+ score += Math.min(patternCount * 0.15, 0.3);
146
+ // Length bonus (longer sentences tend to be more informative, up to a point)
147
+ if (sentence.length > 50 && sentence.length < 300) {
148
+ score += 0.1;
149
+ }
150
+ return Math.min(score, 1.0);
151
+ }
152
+ function inferMemoryType(sentence) {
153
+ const lower = sentence.toLowerCase();
154
+ if (DECISION_WORDS.some(w => lower.includes(w)))
155
+ return 'decision';
156
+ if (PATTERN_WORDS.some(w => lower.includes(w)))
157
+ return 'pattern';
158
+ if (lower.includes('bug') || lower.includes('fix') || lower.includes('issue'))
159
+ return 'insight';
160
+ if (lower.includes('function') || lower.includes('class') || lower.includes('code'))
161
+ return 'snippet';
162
+ return 'fact';
163
+ }
164
+ async function checkDuplicate(text, embedder, qdrant) {
165
+ try {
166
+ const vector = await embedder.embed(text);
167
+ const results = await qdrant.search(vector, undefined, 1);
168
+ return results.length > 0 && results[0].score > DEDUP_THRESHOLD;
169
+ }
170
+ catch {
171
+ return false;
172
+ }
173
+ }
174
+ //# sourceMappingURL=auto-extractor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auto-extractor.js","sourceRoot":"","sources":["../../src/extraction/auto-extractor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import type { BufferedEvent } from '../types/index.js';
2
+ export declare class ConversationBuffer {
3
+ private buffer;
4
+ private maxSize;
5
+ private debounceMs;
6
+ private debounceTimer;
7
+ private extractionCallback;
8
+ private flushing;
9
+ constructor(maxSize: number, debounceMs: number, extractionCallback: (events: BufferedEvent[]) => Promise<void>);
10
+ push(event: BufferedEvent): void;
11
+ flush(): Promise<void>;
12
+ getBufferSize(): number;
13
+ stop(): void;
14
+ }
15
+ //# sourceMappingURL=conversation-buffer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conversation-buffer.d.ts","sourceRoot":"","sources":["../../src/extraction/conversation-buffer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEvD,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,aAAa,CAA8C;IACnE,OAAO,CAAC,kBAAkB,CAA6C;IACvE,OAAO,CAAC,QAAQ,CAAS;gBAGvB,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,kBAAkB,EAAE,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC;IAOhE,IAAI,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI;IAmB1B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAqB5B,aAAa,IAAI,MAAM;IAIvB,IAAI,IAAI,IAAI;CAMb"}
@@ -0,0 +1,60 @@
1
+ export class ConversationBuffer {
2
+ buffer = [];
3
+ maxSize;
4
+ debounceMs;
5
+ debounceTimer = null;
6
+ extractionCallback;
7
+ flushing = false;
8
+ constructor(maxSize, debounceMs, extractionCallback) {
9
+ this.maxSize = maxSize;
10
+ this.debounceMs = debounceMs;
11
+ this.extractionCallback = extractionCallback;
12
+ }
13
+ push(event) {
14
+ this.buffer.push(event);
15
+ // Reset debounce timer
16
+ if (this.debounceTimer) {
17
+ clearTimeout(this.debounceTimer);
18
+ }
19
+ if (this.buffer.length >= this.maxSize) {
20
+ // Buffer full — extract immediately
21
+ void this.flush();
22
+ }
23
+ else {
24
+ // Schedule debounced extraction
25
+ this.debounceTimer = setTimeout(() => {
26
+ void this.flush();
27
+ }, this.debounceMs);
28
+ }
29
+ }
30
+ async flush() {
31
+ if (this.buffer.length === 0 || this.flushing)
32
+ return;
33
+ this.flushing = true;
34
+ if (this.debounceTimer) {
35
+ clearTimeout(this.debounceTimer);
36
+ this.debounceTimer = null;
37
+ }
38
+ const events = [...this.buffer];
39
+ this.buffer = [];
40
+ try {
41
+ await this.extractionCallback(events);
42
+ }
43
+ catch (error) {
44
+ console.error(`[cortex] Auto-extraction failed: ${error}`);
45
+ }
46
+ finally {
47
+ this.flushing = false;
48
+ }
49
+ }
50
+ getBufferSize() {
51
+ return this.buffer.length;
52
+ }
53
+ stop() {
54
+ if (this.debounceTimer) {
55
+ clearTimeout(this.debounceTimer);
56
+ this.debounceTimer = null;
57
+ }
58
+ }
59
+ }
60
+ //# sourceMappingURL=conversation-buffer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conversation-buffer.js","sourceRoot":"","sources":["../../src/extraction/conversation-buffer.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,kBAAkB;IACrB,MAAM,GAAoB,EAAE,CAAC;IAC7B,OAAO,CAAS;IAChB,UAAU,CAAS;IACnB,aAAa,GAAyC,IAAI,CAAC;IAC3D,kBAAkB,CAA6C;IAC/D,QAAQ,GAAG,KAAK,CAAC;IAEzB,YACE,OAAe,EACf,UAAkB,EAClB,kBAA8D;QAE9D,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,kBAAkB,GAAG,kBAAkB,CAAC;IAC/C,CAAC;IAED,IAAI,CAAC,KAAoB;QACvB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAExB,uBAAuB;QACvB,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACvB,YAAY,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QACnC,CAAC;QAED,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACvC,oCAAoC;YACpC,KAAK,IAAI,CAAC,KAAK,EAAE,CAAC;QACpB,CAAC;aAAM,CAAC;YACN,gCAAgC;YAChC,IAAI,CAAC,aAAa,GAAG,UAAU,CAAC,GAAG,EAAE;gBACnC,KAAK,IAAI,CAAC,KAAK,EAAE,CAAC;YACpB,CAAC,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,QAAQ;YAAE,OAAO;QAEtD,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACvB,YAAY,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YACjC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;QAC5B,CAAC;QAED,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;QAChC,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC;QAEjB,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC;QACxC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,oCAAoC,KAAK,EAAE,CAAC,CAAC;QAC7D,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;QACxB,CAAC;IACH,CAAC;IAED,aAAa;QACX,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;IAC5B,CAAC;IAED,IAAI;QACF,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACvB,YAAY,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YACjC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;QAC5B,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,23 @@
1
+ import type { ExtractionResult, ExtractionTier } from '../types/index.js';
2
+ import { Tier1Regex } from './tier1-regex.js';
3
+ import { Tier2NLP } from './tier2-nlp.js';
4
+ import type { Tier3LLM } from './tier3-llm.js';
5
+ export declare class EntityExtractor {
6
+ private tier1;
7
+ private tier2;
8
+ private tier3;
9
+ private extractionTier;
10
+ private cache;
11
+ private cacheOrder;
12
+ constructor(tier1: Tier1Regex, tier2: Tier2NLP, tier3: Tier3LLM | null, extractionTier: ExtractionTier);
13
+ setExtractionTier(tier: ExtractionTier): void;
14
+ setTier3(tier3: Tier3LLM | null): void;
15
+ getActiveTier(): 1 | 2 | 3;
16
+ extract(text: string, project?: string): Promise<ExtractionResult>;
17
+ private selectTier;
18
+ private runWithFallback;
19
+ private getCacheKey;
20
+ private getFromCache;
21
+ private putInCache;
22
+ }
23
+ //# sourceMappingURL=extractor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extractor.d.ts","sourceRoot":"","sources":["../../src/extraction/extractor.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAC1E,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAU/C,qBAAa,eAAe;IAC1B,OAAO,CAAC,KAAK,CAAa;IAC1B,OAAO,CAAC,KAAK,CAAW;IACxB,OAAO,CAAC,KAAK,CAAkB;IAC/B,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,KAAK,CAAsC;IACnD,OAAO,CAAC,UAAU,CAAgB;gBAGhC,KAAK,EAAE,UAAU,EACjB,KAAK,EAAE,QAAQ,EACf,KAAK,EAAE,QAAQ,GAAG,IAAI,EACtB,cAAc,EAAE,cAAc;IAQhC,iBAAiB,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI;IAI7C,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI,GAAG,IAAI;IAItC,aAAa,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;IAIpB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAyBxE,OAAO,CAAC,UAAU;YAUJ,eAAe;IAuB7B,OAAO,CAAC,WAAW;IAKnB,OAAO,CAAC,YAAY;IAiBpB,OAAO,CAAC,UAAU;CAUnB"}
@@ -0,0 +1,108 @@
1
+ import { createHash } from 'node:crypto';
2
+ const CACHE_TTL_MS = 5 * 60 * 1000; // 5 minutes
3
+ const CACHE_MAX_SIZE = 500;
4
+ export class EntityExtractor {
5
+ tier1;
6
+ tier2;
7
+ tier3;
8
+ extractionTier;
9
+ cache = new Map();
10
+ cacheOrder = []; // LRU tracking
11
+ constructor(tier1, tier2, tier3, extractionTier) {
12
+ this.tier1 = tier1;
13
+ this.tier2 = tier2;
14
+ this.tier3 = tier3;
15
+ this.extractionTier = extractionTier;
16
+ }
17
+ setExtractionTier(tier) {
18
+ this.extractionTier = tier;
19
+ }
20
+ setTier3(tier3) {
21
+ this.tier3 = tier3;
22
+ }
23
+ getActiveTier() {
24
+ return this.selectTier();
25
+ }
26
+ async extract(text, project) {
27
+ // Check cache
28
+ const cacheKey = this.getCacheKey(text, project);
29
+ const cached = this.getFromCache(cacheKey);
30
+ if (cached)
31
+ return cached;
32
+ const tier = this.selectTier();
33
+ let result;
34
+ switch (tier) {
35
+ case 3:
36
+ result = await this.runWithFallback(text, project, 3);
37
+ break;
38
+ case 2:
39
+ result = await this.runWithFallback(text, project, 2);
40
+ break;
41
+ default:
42
+ result = this.tier1.extract(text, project);
43
+ break;
44
+ }
45
+ this.putInCache(cacheKey, result);
46
+ return result;
47
+ }
48
+ selectTier() {
49
+ if (this.extractionTier === 'local-only')
50
+ return 2;
51
+ if (this.extractionTier === 'llm-preferred' && this.tier3?.isAvailable())
52
+ return 3;
53
+ if (this.extractionTier === 'auto') {
54
+ if (this.tier3?.isAvailable())
55
+ return 3;
56
+ return 2;
57
+ }
58
+ return 2;
59
+ }
60
+ async runWithFallback(text, project, startTier) {
61
+ if (startTier === 3 && this.tier3) {
62
+ try {
63
+ const result = await this.tier3.extract(text, project);
64
+ if (result)
65
+ return result;
66
+ }
67
+ catch (error) {
68
+ console.error(`[cortex] Tier 3 extraction failed, falling back: ${error}`);
69
+ }
70
+ // Fall back to Tier 2
71
+ }
72
+ try {
73
+ return await this.tier2.extract(text, project);
74
+ }
75
+ catch (error) {
76
+ console.error(`[cortex] Tier 2 extraction failed, falling back to Tier 1: ${error}`);
77
+ return this.tier1.extract(text, project);
78
+ }
79
+ }
80
+ getCacheKey(text, project) {
81
+ const input = `${text}|${project ?? ''}`;
82
+ return createHash('sha256').update(input).digest('hex');
83
+ }
84
+ getFromCache(key) {
85
+ const entry = this.cache.get(key);
86
+ if (!entry)
87
+ return null;
88
+ if (Date.now() - entry.timestamp > CACHE_TTL_MS) {
89
+ this.cache.delete(key);
90
+ this.cacheOrder = this.cacheOrder.filter(k => k !== key);
91
+ return null;
92
+ }
93
+ // Move to end of LRU
94
+ this.cacheOrder = this.cacheOrder.filter(k => k !== key);
95
+ this.cacheOrder.push(key);
96
+ return entry.result;
97
+ }
98
+ putInCache(key, result) {
99
+ // Evict LRU if at capacity
100
+ while (this.cache.size >= CACHE_MAX_SIZE && this.cacheOrder.length > 0) {
101
+ const evictKey = this.cacheOrder.shift();
102
+ this.cache.delete(evictKey);
103
+ }
104
+ this.cache.set(key, { result, timestamp: Date.now() });
105
+ this.cacheOrder.push(key);
106
+ }
107
+ }
108
+ //# sourceMappingURL=extractor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extractor.js","sourceRoot":"","sources":["../../src/extraction/extractor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { ExtractionResult } from '../types/index.js';
2
+ export declare class Tier1Regex {
3
+ extract(text: string, _project?: string): ExtractionResult;
4
+ private extractEntities;
5
+ private extractRelationships;
6
+ }
7
+ //# sourceMappingURL=tier1-regex.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tier1-regex.d.ts","sourceRoot":"","sources":["../../src/extraction/tier1-regex.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAsD,MAAM,mBAAmB,CAAC;AA8B9G,qBAAa,UAAU;IACrB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,gBAAgB;IAW1D,OAAO,CAAC,eAAe;IA0CvB,OAAO,CAAC,oBAAoB;CAoB7B"}
@@ -0,0 +1,119 @@
1
+ const VERB_PATTERNS = [
2
+ { pattern: /(\w+)\s+depends\s+on\s+(\w+)/gi, relation: 'DEPENDS_ON' },
3
+ { pattern: /(\w+)\s+uses\s+(\w+)/gi, relation: 'USES' },
4
+ { pattern: /(\w+)\s+implements\s+(\w+)/gi, relation: 'IMPLEMENTS' },
5
+ { pattern: /(\w+)\s+calls\s+(\w+)/gi, relation: 'CALLS' },
6
+ { pattern: /(\w+)\s+is\s+part\s+of\s+(\w+)/gi, relation: 'PART_OF' },
7
+ { pattern: /(\w+)\s+relates?\s+to\s+(\w+)/gi, relation: 'RELATED_TO' },
8
+ { pattern: /(\w+)\s+extends\s+(\w+)/gi, relation: 'DEPENDS_ON' },
9
+ { pattern: /(\w+)\s+imports?\s+(\w+)/gi, relation: 'USES' },
10
+ { pattern: /(\w+)\s+connects?\s+to\s+(\w+)/gi, relation: 'RELATED_TO' },
11
+ ];
12
+ const ENTITY_PATTERNS = [
13
+ /[a-z][a-z0-9]*(?:_[a-z0-9]+)+/g, // snake_case
14
+ /[a-z]+(?:[A-Z][a-z0-9]+)+/g, // camelCase
15
+ /[A-Z][a-z0-9]+(?:[A-Z][a-z0-9]+)+/g, // PascalCase
16
+ ];
17
+ // Match quoted strings that look like identifiers
18
+ const QUOTED_PATTERN = /"([a-z][a-z0-9\s_-]{1,40})"/gi;
19
+ // Stop words to filter out false positives
20
+ const STOP_WORDS = new Set([
21
+ 'the', 'this', 'that', 'with', 'from', 'into', 'when', 'then',
22
+ 'each', 'some', 'every', 'should', 'could', 'would', 'about',
23
+ 'before', 'after', 'between', 'through', 'during',
24
+ ]);
25
+ export class Tier1Regex {
26
+ extract(text, _project) {
27
+ const entities = this.extractEntities(text);
28
+ const relationships = this.extractRelationships(text);
29
+ return {
30
+ entities,
31
+ relationships,
32
+ tier: 1,
33
+ };
34
+ }
35
+ extractEntities(text) {
36
+ const seen = new Set();
37
+ const entities = [];
38
+ // Code-style identifiers
39
+ for (const pattern of ENTITY_PATTERNS) {
40
+ const regex = new RegExp(pattern.source, pattern.flags);
41
+ let match;
42
+ while ((match = regex.exec(text)) !== null) {
43
+ const original = match[0];
44
+ const name = toSnakeCase(original);
45
+ if (seen.has(name) || name.length < 3)
46
+ continue;
47
+ seen.add(name);
48
+ entities.push({
49
+ name,
50
+ original,
51
+ type: inferEntityType(original),
52
+ confidence: 0.4,
53
+ });
54
+ }
55
+ }
56
+ // Quoted identifiers
57
+ let match;
58
+ const quotedRegex = new RegExp(QUOTED_PATTERN.source, QUOTED_PATTERN.flags);
59
+ while ((match = quotedRegex.exec(text)) !== null) {
60
+ const original = match[1].trim();
61
+ if (STOP_WORDS.has(original.toLowerCase()))
62
+ continue;
63
+ const name = toSnakeCase(original);
64
+ if (seen.has(name) || name.length < 3)
65
+ continue;
66
+ seen.add(name);
67
+ entities.push({
68
+ name,
69
+ original,
70
+ type: 'other',
71
+ confidence: 0.4,
72
+ });
73
+ }
74
+ return entities;
75
+ }
76
+ extractRelationships(text) {
77
+ const relationships = [];
78
+ const seen = new Set();
79
+ for (const { pattern, relation } of VERB_PATTERNS) {
80
+ const regex = new RegExp(pattern.source, pattern.flags);
81
+ let match;
82
+ while ((match = regex.exec(text)) !== null) {
83
+ const from = toSnakeCase(match[1]);
84
+ const to = toSnakeCase(match[2]);
85
+ if (from.length < 2 || to.length < 2)
86
+ continue;
87
+ const key = `${from}:${relation}:${to}`;
88
+ if (seen.has(key))
89
+ continue;
90
+ seen.add(key);
91
+ relationships.push({ from, relation, to, confidence: 0.3 });
92
+ }
93
+ }
94
+ return relationships;
95
+ }
96
+ }
97
+ function toSnakeCase(str) {
98
+ return str
99
+ // Insert underscore before uppercase letters (camelCase/PascalCase)
100
+ .replace(/([a-z0-9])([A-Z])/g, '$1_$2')
101
+ // Replace spaces and hyphens with underscores
102
+ .replace(/[\s-]+/g, '_')
103
+ .toLowerCase()
104
+ // Collapse multiple underscores
105
+ .replace(/_+/g, '_')
106
+ // Trim leading/trailing underscores
107
+ .replace(/^_|_$/g, '');
108
+ }
109
+ function inferEntityType(name) {
110
+ const lower = name.toLowerCase();
111
+ if (lower.includes('service') || lower.includes('server') || lower.includes('api'))
112
+ return 'service';
113
+ if (lower.includes('component') || lower.includes('module') || lower.includes('widget'))
114
+ return 'component';
115
+ if (lower.includes('lib') || lower.includes('package') || lower.includes('sdk'))
116
+ return 'library';
117
+ return 'other';
118
+ }
119
+ //# sourceMappingURL=tier1-regex.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tier1-regex.js","sourceRoot":"","sources":["../../src/extraction/tier1-regex.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { ExtractionResult } from '../types/index.js';
2
+ import type { Embedder } from '../embedding/embedder.js';
3
+ import type { QdrantStore } from '../storage/qdrant.js';
4
+ export declare class Tier2NLP {
5
+ private embedder;
6
+ private qdrant;
7
+ constructor(embedder?: Embedder | null, qdrant?: QdrantStore | null);
8
+ extract(text: string, _project?: string): Promise<ExtractionResult>;
9
+ private extractEntities;
10
+ private extractRelationships;
11
+ private dedupEntities;
12
+ }
13
+ //# sourceMappingURL=tier2-nlp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tier2-nlp.d.ts","sourceRoot":"","sources":["../../src/extraction/tier2-nlp.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAsD,MAAM,mBAAmB,CAAC;AAC9G,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAaxD,qBAAa,QAAQ;IACnB,OAAO,CAAC,QAAQ,CAAkB;IAClC,OAAO,CAAC,MAAM,CAAqB;gBAEvB,QAAQ,GAAE,QAAQ,GAAG,IAAW,EAAE,MAAM,GAAE,WAAW,GAAG,IAAW;IAKzE,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAgBzE,OAAO,CAAC,eAAe;IA+EvB,OAAO,CAAC,oBAAoB;YA+Bd,aAAa;CAmC5B"}