@londer/cortex 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +62 -0
- package/LICENSE +21 -0
- package/README.md +183 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +278 -0
- package/dist/cli.js.map +1 -0
- package/dist/config-store.d.ts +15 -0
- package/dist/config-store.d.ts.map +1 -0
- package/dist/config-store.js +86 -0
- package/dist/config-store.js.map +1 -0
- package/dist/config.d.ts +28 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +39 -0
- package/dist/config.js.map +1 -0
- package/dist/consolidation/cluster-finder.d.ts +5 -0
- package/dist/consolidation/cluster-finder.d.ts.map +1 -0
- package/dist/consolidation/cluster-finder.js +43 -0
- package/dist/consolidation/cluster-finder.js.map +1 -0
- package/dist/consolidation/consolidator.d.ts +29 -0
- package/dist/consolidation/consolidator.d.ts.map +1 -0
- package/dist/consolidation/consolidator.js +296 -0
- package/dist/consolidation/consolidator.js.map +1 -0
- package/dist/embedding/embedder.d.ts +9 -0
- package/dist/embedding/embedder.d.ts.map +1 -0
- package/dist/embedding/embedder.js +89 -0
- package/dist/embedding/embedder.js.map +1 -0
- package/dist/extraction/auto-extractor.d.ts +7 -0
- package/dist/extraction/auto-extractor.d.ts.map +1 -0
- package/dist/extraction/auto-extractor.js +174 -0
- package/dist/extraction/auto-extractor.js.map +1 -0
- package/dist/extraction/conversation-buffer.d.ts +15 -0
- package/dist/extraction/conversation-buffer.d.ts.map +1 -0
- package/dist/extraction/conversation-buffer.js +60 -0
- package/dist/extraction/conversation-buffer.js.map +1 -0
- package/dist/extraction/extractor.d.ts +23 -0
- package/dist/extraction/extractor.d.ts.map +1 -0
- package/dist/extraction/extractor.js +108 -0
- package/dist/extraction/extractor.js.map +1 -0
- package/dist/extraction/tier1-regex.d.ts +7 -0
- package/dist/extraction/tier1-regex.d.ts.map +1 -0
- package/dist/extraction/tier1-regex.js +119 -0
- package/dist/extraction/tier1-regex.js.map +1 -0
- package/dist/extraction/tier2-nlp.d.ts +13 -0
- package/dist/extraction/tier2-nlp.d.ts.map +1 -0
- package/dist/extraction/tier2-nlp.js +195 -0
- package/dist/extraction/tier2-nlp.js.map +1 -0
- package/dist/extraction/tier3-llm.d.ts +8 -0
- package/dist/extraction/tier3-llm.d.ts.map +1 -0
- package/dist/extraction/tier3-llm.js +57 -0
- package/dist/extraction/tier3-llm.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +398 -0
- package/dist/index.js.map +1 -0
- package/dist/llm/anthropic-client.d.ts +18 -0
- package/dist/llm/anthropic-client.d.ts.map +1 -0
- package/dist/llm/anthropic-client.js +116 -0
- package/dist/llm/anthropic-client.js.map +1 -0
- package/dist/orchestration/ranker.d.ts +18 -0
- package/dist/orchestration/ranker.d.ts.map +1 -0
- package/dist/orchestration/ranker.js +124 -0
- package/dist/orchestration/ranker.js.map +1 -0
- package/dist/orchestration/scope.d.ts +15 -0
- package/dist/orchestration/scope.d.ts.map +1 -0
- package/dist/orchestration/scope.js +28 -0
- package/dist/orchestration/scope.js.map +1 -0
- package/dist/storage/neo4j.d.ts +19 -0
- package/dist/storage/neo4j.d.ts.map +1 -0
- package/dist/storage/neo4j.js +246 -0
- package/dist/storage/neo4j.js.map +1 -0
- package/dist/storage/qdrant.d.ts +21 -0
- package/dist/storage/qdrant.d.ts.map +1 -0
- package/dist/storage/qdrant.js +125 -0
- package/dist/storage/qdrant.js.map +1 -0
- package/dist/storage/sqlite.d.ts +23 -0
- package/dist/storage/sqlite.d.ts.map +1 -0
- package/dist/storage/sqlite.js +162 -0
- package/dist/storage/sqlite.js.map +1 -0
- package/dist/templates/claude-instructions.d.ts +11 -0
- package/dist/templates/claude-instructions.d.ts.map +1 -0
- package/dist/templates/claude-instructions.js +110 -0
- package/dist/templates/claude-instructions.js.map +1 -0
- package/dist/tools/config.d.ts +21 -0
- package/dist/tools/config.d.ts.map +1 -0
- package/dist/tools/config.js +96 -0
- package/dist/tools/config.js.map +1 -0
- package/dist/tools/consolidate.d.ts +4 -0
- package/dist/tools/consolidate.d.ts.map +1 -0
- package/dist/tools/consolidate.js +16 -0
- package/dist/tools/consolidate.js.map +1 -0
- package/dist/tools/context.d.ts +8 -0
- package/dist/tools/context.d.ts.map +1 -0
- package/dist/tools/context.js +84 -0
- package/dist/tools/context.js.map +1 -0
- package/dist/tools/forget.d.ts +7 -0
- package/dist/tools/forget.d.ts.map +1 -0
- package/dist/tools/forget.js +49 -0
- package/dist/tools/forget.js.map +1 -0
- package/dist/tools/graph-query.d.ts +5 -0
- package/dist/tools/graph-query.d.ts.map +1 -0
- package/dist/tools/graph-query.js +35 -0
- package/dist/tools/graph-query.js.map +1 -0
- package/dist/tools/ingest.d.ts +8 -0
- package/dist/tools/ingest.d.ts.map +1 -0
- package/dist/tools/ingest.js +101 -0
- package/dist/tools/ingest.js.map +1 -0
- package/dist/tools/relate.d.ts +4 -0
- package/dist/tools/relate.d.ts.map +1 -0
- package/dist/tools/relate.js +10 -0
- package/dist/tools/relate.js.map +1 -0
- package/dist/tools/search.d.ts +6 -0
- package/dist/tools/search.d.ts.map +1 -0
- package/dist/tools/search.js +43 -0
- package/dist/tools/search.js.map +1 -0
- package/dist/tools/store.d.ts +8 -0
- package/dist/tools/store.d.ts.map +1 -0
- package/dist/tools/store.js +64 -0
- package/dist/tools/store.js.map +1 -0
- package/dist/types/index.d.ts +289 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -0
- package/docker-compose.yml +27 -0
- package/package.json +71 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-store.js","sourceRoot":"","sources":["../src/config-store.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { ExtractionTier } from './types/index.js';
|
|
2
|
+
export interface CortexConfig {
|
|
3
|
+
qdrantUrl: string;
|
|
4
|
+
neo4jUri: string;
|
|
5
|
+
neo4jUser: string;
|
|
6
|
+
neo4jPassword: string;
|
|
7
|
+
sqlitePath: string;
|
|
8
|
+
embeddingModel: string;
|
|
9
|
+
transformersCache: string;
|
|
10
|
+
collectionName: string;
|
|
11
|
+
vectorDimensions: number;
|
|
12
|
+
anthropicApiKey: string;
|
|
13
|
+
llmModel: string;
|
|
14
|
+
extractionTier: ExtractionTier;
|
|
15
|
+
autoExtract: boolean;
|
|
16
|
+
extractBufferSize: number;
|
|
17
|
+
extractDebounceMs: number;
|
|
18
|
+
consolidationEnabled: boolean;
|
|
19
|
+
consolidationIntervalMs: number;
|
|
20
|
+
consolidationBatchSize: number;
|
|
21
|
+
}
|
|
22
|
+
export declare function loadConfig(): CortexConfig;
|
|
23
|
+
export declare const SCOPE_BOOST: {
|
|
24
|
+
readonly PROJECT_LOCAL: 1.5;
|
|
25
|
+
readonly RELATED_PROJECT: 1.1;
|
|
26
|
+
readonly GLOBAL: 1;
|
|
27
|
+
};
|
|
28
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AASvD,MAAM,WAAW,YAAY;IAE3B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;IAEzB,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,cAAc,CAAC;IAC/B,WAAW,EAAE,OAAO,CAAC;IACrB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,oBAAoB,EAAE,OAAO,CAAC;IAC9B,uBAAuB,EAAE,MAAM,CAAC;IAChC,sBAAsB,EAAE,MAAM,CAAC;CAChC;AAED,wBAAgB,UAAU,IAAI,YAAY,CAuBzC;AAGD,eAAO,MAAM,WAAW;;;;CAId,CAAC"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { homedir } from 'node:os';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
function resolvePath(p) {
|
|
4
|
+
if (p.startsWith('~')) {
|
|
5
|
+
return join(homedir(), p.slice(1));
|
|
6
|
+
}
|
|
7
|
+
return p;
|
|
8
|
+
}
|
|
9
|
+
export function loadConfig() {
|
|
10
|
+
return {
|
|
11
|
+
// Phase 1
|
|
12
|
+
qdrantUrl: process.env.QDRANT_URL ?? 'http://localhost:16333',
|
|
13
|
+
neo4jUri: process.env.NEO4J_URI ?? 'bolt://localhost:17687',
|
|
14
|
+
neo4jUser: process.env.NEO4J_USER ?? 'neo4j',
|
|
15
|
+
neo4jPassword: process.env.NEO4J_PASSWORD ?? 'cortex-dev',
|
|
16
|
+
sqlitePath: resolvePath(process.env.SQLITE_PATH ?? '~/.cortex/cortex.db'),
|
|
17
|
+
embeddingModel: process.env.EMBEDDING_MODEL ?? 'Xenova/all-MiniLM-L6-v2',
|
|
18
|
+
transformersCache: resolvePath(process.env.TRANSFORMERS_CACHE ?? '~/.cache/huggingface'),
|
|
19
|
+
collectionName: 'cortex_memories',
|
|
20
|
+
vectorDimensions: 384,
|
|
21
|
+
// Phase 2
|
|
22
|
+
anthropicApiKey: process.env.ANTHROPIC_API_KEY ?? '',
|
|
23
|
+
llmModel: process.env.CORTEX_LLM_MODEL ?? 'claude-sonnet-4-20250514',
|
|
24
|
+
extractionTier: process.env.CORTEX_EXTRACTION_TIER ?? 'auto',
|
|
25
|
+
autoExtract: process.env.CORTEX_AUTO_EXTRACT !== 'false',
|
|
26
|
+
extractBufferSize: parseInt(process.env.CORTEX_EXTRACT_BUFFER_SIZE ?? '5', 10),
|
|
27
|
+
extractDebounceMs: parseInt(process.env.CORTEX_EXTRACT_DEBOUNCE_MS ?? '30000', 10),
|
|
28
|
+
consolidationEnabled: process.env.CORTEX_CONSOLIDATION_ENABLED !== 'false',
|
|
29
|
+
consolidationIntervalMs: parseInt(process.env.CORTEX_CONSOLIDATION_INTERVAL_MS ?? '3600000', 10),
|
|
30
|
+
consolidationBatchSize: parseInt(process.env.CORTEX_CONSOLIDATION_BATCH_SIZE ?? '50', 10),
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
// Scope boost weights (from spec Section 4)
|
|
34
|
+
export const SCOPE_BOOST = {
|
|
35
|
+
PROJECT_LOCAL: 1.5,
|
|
36
|
+
RELATED_PROJECT: 1.1,
|
|
37
|
+
GLOBAL: 1.0,
|
|
38
|
+
};
|
|
39
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC,SAAS,WAAW,CAAC,CAAS;IAC5B,IAAI,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACtB,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACrC,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAyBD,MAAM,UAAU,UAAU;IACxB,OAAO;QACL,UAAU;QACV,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,wBAAwB;QAC7D,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,wBAAwB;QAC3D,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,OAAO;QAC5C,aAAa,EAAE,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,YAAY;QACzD,UAAU,EAAE,WAAW,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,qBAAqB,CAAC;QACzE,cAAc,EAAE,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,yBAAyB;QACxE,iBAAiB,EAAE,WAAW,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,sBAAsB,CAAC;QACxF,cAAc,EAAE,iBAAiB;QACjC,gBAAgB,EAAE,GAAG;QACrB,UAAU;QACV,eAAe,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,EAAE;QACpD,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,0BAA0B;QACpE,cAAc,EAAG,OAAO,CAAC,GAAG,CAAC,sBAAyC,IAAI,MAAM;QAChF,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,mBAAmB,KAAK,OAAO;QACxD,iBAAiB,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,0BAA0B,IAAI,GAAG,EAAE,EAAE,CAAC;QAC9E,iBAAiB,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,0BAA0B,IAAI,OAAO,EAAE,EAAE,CAAC;QAClF,oBAAoB,EAAE,OAAO,CAAC,GAAG,CAAC,4BAA4B,KAAK,OAAO;QAC1E,uBAAuB,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,gCAAgC,IAAI,SAAS,EAAE,EAAE,CAAC;QAChG,sBAAsB,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,+BAA+B,IAAI,IAAI,EAAE,EAAE,CAAC;KAC1F,CAAC;AACJ,CAAC;AAED,4CAA4C;AAC5C,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,aAAa,EAAE,GAAG;IAClB,eAAe,EAAE,GAAG;IACpB,MAAM,EAAE,GAAG;CACH,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Memory, MemoryCluster } from '../types/index.js';
|
|
2
|
+
import type { Embedder } from '../embedding/embedder.js';
|
|
3
|
+
import type { QdrantStore } from '../storage/qdrant.js';
|
|
4
|
+
export declare function findClusters(memories: Memory[], embedder: Embedder, qdrant: QdrantStore, similarityThreshold?: number): Promise<MemoryCluster[]>;
|
|
5
|
+
//# sourceMappingURL=cluster-finder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cluster-finder.d.ts","sourceRoot":"","sources":["../../src/consolidation/cluster-finder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAIxD,wBAAsB,YAAY,CAChC,QAAQ,EAAE,MAAM,EAAE,EAClB,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,WAAW,EACnB,mBAAmB,GAAE,MAAqC,GACzD,OAAO,CAAC,aAAa,EAAE,CAAC,CA4C1B"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
const DEFAULT_SIMILARITY_THRESHOLD = 0.85;
|
|
2
|
+
export async function findClusters(memories, embedder, qdrant, similarityThreshold = DEFAULT_SIMILARITY_THRESHOLD) {
|
|
3
|
+
if (memories.length < 2)
|
|
4
|
+
return [];
|
|
5
|
+
// Embed all memory contents
|
|
6
|
+
const texts = memories.map(m => m.content);
|
|
7
|
+
const vectors = await embedder.embedBatch(texts);
|
|
8
|
+
const clustered = new Set();
|
|
9
|
+
const clusters = [];
|
|
10
|
+
for (let i = 0; i < memories.length; i++) {
|
|
11
|
+
if (clustered.has(memories[i].id))
|
|
12
|
+
continue;
|
|
13
|
+
const anchor = memories[i];
|
|
14
|
+
const similar = [];
|
|
15
|
+
// Search Qdrant for similar vectors
|
|
16
|
+
const results = await qdrant.search(vectors[i], undefined, 20);
|
|
17
|
+
for (const result of results) {
|
|
18
|
+
if (result.id === anchor.id)
|
|
19
|
+
continue;
|
|
20
|
+
if (clustered.has(result.id))
|
|
21
|
+
continue;
|
|
22
|
+
if (result.score < similarityThreshold)
|
|
23
|
+
continue;
|
|
24
|
+
// Find the memory object
|
|
25
|
+
const memMatch = memories.find(m => m.id === result.id);
|
|
26
|
+
if (!memMatch)
|
|
27
|
+
continue;
|
|
28
|
+
similar.push({
|
|
29
|
+
memory: memMatch,
|
|
30
|
+
similarity: result.score,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
if (similar.length > 0) {
|
|
34
|
+
clustered.add(anchor.id);
|
|
35
|
+
for (const s of similar) {
|
|
36
|
+
clustered.add(s.memory.id);
|
|
37
|
+
}
|
|
38
|
+
clusters.push({ anchor, similar });
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return clusters;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=cluster-finder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cluster-finder.js","sourceRoot":"","sources":["../../src/consolidation/cluster-finder.ts"],"names":[],"mappings":"AAIA,MAAM,4BAA4B,GAAG,IAAI,CAAC;AAE1C,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,QAAkB,EAClB,QAAkB,EAClB,MAAmB,EACnB,sBAA8B,4BAA4B;IAE1D,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,EAAE,CAAC;IAEnC,4BAA4B;IAC5B,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;IAC3C,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;IAEjD,MAAM,SAAS,GAAG,IAAI,GAAG,EAAU,CAAC;IACpC,MAAM,QAAQ,GAAoB,EAAE,CAAC;IAErC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACzC,IAAI,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAAE,SAAS;QAE5C,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;QAC3B,MAAM,OAAO,GAA6B,EAAE,CAAC;QAE7C,oCAAoC;QACpC,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC;QAE/D,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC7B,IAAI,MAAM,CAAC,EAAE,KAAK,MAAM,CAAC,EAAE;gBAAE,SAAS;YACtC,IAAI,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;gBAAE,SAAS;YACvC,IAAI,MAAM,CAAC,KAAK,GAAG,mBAAmB;gBAAE,SAAS;YAEjD,yBAAyB;YACzB,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC,EAAE,CAAC,CAAC;YACxD,IAAI,CAAC,QAAQ;gBAAE,SAAS;YAExB,OAAO,CAAC,IAAI,CAAC;gBACX,MAAM,EAAE,QAAQ;gBAChB,UAAU,EAAE,MAAM,CAAC,KAAK;aACzB,CAAC,CAAC;QACL,CAAC;QAED,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvB,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YACzB,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;gBACxB,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YAC7B,CAAC;YACD,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;QACrC,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { ConsolidationResult, LLMClient } from '../types/index.js';
|
|
2
|
+
import type { Embedder } from '../embedding/embedder.js';
|
|
3
|
+
import type { SQLiteStore } from '../storage/sqlite.js';
|
|
4
|
+
import type { QdrantStore } from '../storage/qdrant.js';
|
|
5
|
+
import type { Neo4jStore } from '../storage/neo4j.js';
|
|
6
|
+
export declare class Consolidator {
|
|
7
|
+
private embedder;
|
|
8
|
+
private sqlite;
|
|
9
|
+
private qdrant;
|
|
10
|
+
private neo4j;
|
|
11
|
+
private llmClient;
|
|
12
|
+
private autoTimer;
|
|
13
|
+
private batchSize;
|
|
14
|
+
constructor(embedder: Embedder, sqlite: SQLiteStore, qdrant: QdrantStore, neo4j: Neo4jStore, llmClient: LLMClient | null, batchSize?: number);
|
|
15
|
+
setLLMClient(client: LLMClient | null): void;
|
|
16
|
+
run(project?: string, maxClusters?: number, dryRun?: boolean): Promise<ConsolidationResult & {
|
|
17
|
+
details?: Array<{
|
|
18
|
+
action: string;
|
|
19
|
+
reason: string;
|
|
20
|
+
memories: string[];
|
|
21
|
+
}>;
|
|
22
|
+
}>;
|
|
23
|
+
private consolidateWithLLM;
|
|
24
|
+
private executeLLMAction;
|
|
25
|
+
private consolidateLocally;
|
|
26
|
+
startAutoConsolidation(intervalMs: number): void;
|
|
27
|
+
stopAutoConsolidation(): void;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=consolidator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consolidator.d.ts","sourceRoot":"","sources":["../../src/consolidation/consolidator.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAGV,mBAAmB,EACnB,SAAS,EAEV,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAqCtD,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,KAAK,CAAa;IAC1B,OAAO,CAAC,SAAS,CAAmB;IACpC,OAAO,CAAC,SAAS,CAA+C;IAChE,OAAO,CAAC,SAAS,CAAS;gBAGxB,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,WAAW,EACnB,KAAK,EAAE,UAAU,EACjB,SAAS,EAAE,SAAS,GAAG,IAAI,EAC3B,SAAS,GAAE,MAAW;IAUxB,YAAY,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,GAAG,IAAI;IAItC,GAAG,CACP,OAAO,CAAC,EAAE,MAAM,EAChB,WAAW,GAAE,MAAW,EACxB,MAAM,GAAE,OAAe,GACtB,OAAO,CAAC,mBAAmB,GAAG;QAAE,OAAO,CAAC,EAAE,KAAK,CAAC;YAAE,MAAM,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAC;YAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;SAAE,CAAC,CAAA;KAAE,CAAC;YAkE/F,kBAAkB;YAiClB,gBAAgB;IA0G9B,OAAO,CAAC,kBAAkB;IA4D1B,sBAAsB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAUhD,qBAAqB,IAAI,IAAI;CAM9B"}
|
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
2
|
+
import { findClusters } from './cluster-finder.js';
|
|
3
|
+
const LLM_CONSOLIDATION_PROMPT = `You are a knowledge base maintenance system. Review the following cluster of similar memories and decide what to do.
|
|
4
|
+
|
|
5
|
+
Actions:
|
|
6
|
+
- MERGE: Combine into a single memory. Provide merged content.
|
|
7
|
+
- KEEP_ALL: Distinct enough to keep separately. Explain why.
|
|
8
|
+
- ARCHIVE: Outdated/stale. List which ones.
|
|
9
|
+
- CONTRADICTION: Memories contradict. Keep most recent, archive rest.
|
|
10
|
+
|
|
11
|
+
Cluster:
|
|
12
|
+
{cluster_json}
|
|
13
|
+
|
|
14
|
+
Respond with only valid JSON:
|
|
15
|
+
{
|
|
16
|
+
"action": "MERGE|KEEP_ALL|ARCHIVE|CONTRADICTION",
|
|
17
|
+
"reason": "string",
|
|
18
|
+
"merged_content": "string|null",
|
|
19
|
+
"merged_type": "string|null",
|
|
20
|
+
"merged_tags": ["string"]|null,
|
|
21
|
+
"merged_entities": ["string"]|null,
|
|
22
|
+
"archive_ids": ["string"],
|
|
23
|
+
"keep_ids": ["string"]
|
|
24
|
+
}`;
|
|
25
|
+
export class Consolidator {
|
|
26
|
+
embedder;
|
|
27
|
+
sqlite;
|
|
28
|
+
qdrant;
|
|
29
|
+
neo4j;
|
|
30
|
+
llmClient;
|
|
31
|
+
autoTimer = null;
|
|
32
|
+
batchSize;
|
|
33
|
+
constructor(embedder, sqlite, qdrant, neo4j, llmClient, batchSize = 50) {
|
|
34
|
+
this.embedder = embedder;
|
|
35
|
+
this.sqlite = sqlite;
|
|
36
|
+
this.qdrant = qdrant;
|
|
37
|
+
this.neo4j = neo4j;
|
|
38
|
+
this.llmClient = llmClient;
|
|
39
|
+
this.batchSize = batchSize;
|
|
40
|
+
}
|
|
41
|
+
setLLMClient(client) {
|
|
42
|
+
this.llmClient = client;
|
|
43
|
+
}
|
|
44
|
+
async run(project, maxClusters = 10, dryRun = false) {
|
|
45
|
+
const startTime = Date.now();
|
|
46
|
+
const useLLM = this.llmClient?.isAvailable() ?? false;
|
|
47
|
+
const mode = useLLM ? 'llm' : 'local';
|
|
48
|
+
// Get memories to consolidate
|
|
49
|
+
const memories = project
|
|
50
|
+
? this.sqlite.searchByProject(project, this.batchSize)
|
|
51
|
+
: this.sqlite.getRecentMemories(null, this.batchSize);
|
|
52
|
+
if (memories.length < 2) {
|
|
53
|
+
return {
|
|
54
|
+
merged: 0, archived: 0, contradictions: 0, flagged: 0,
|
|
55
|
+
unchanged: memories.length, duration_ms: Date.now() - startTime, mode,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
// Find clusters
|
|
59
|
+
const clusters = await findClusters(memories, this.embedder, this.qdrant);
|
|
60
|
+
const activeClusters = clusters.slice(0, maxClusters);
|
|
61
|
+
let merged = 0;
|
|
62
|
+
let archived = 0;
|
|
63
|
+
let contradictions = 0;
|
|
64
|
+
let flagged = 0;
|
|
65
|
+
let unchanged = 0;
|
|
66
|
+
const details = [];
|
|
67
|
+
for (const cluster of activeClusters) {
|
|
68
|
+
const allIds = [cluster.anchor.id, ...cluster.similar.map(s => s.memory.id)];
|
|
69
|
+
if (useLLM) {
|
|
70
|
+
const result = await this.consolidateWithLLM(cluster, dryRun);
|
|
71
|
+
if (result) {
|
|
72
|
+
details.push({ action: result.action, reason: result.reason, memories: allIds });
|
|
73
|
+
switch (result.action) {
|
|
74
|
+
case 'MERGE':
|
|
75
|
+
merged++;
|
|
76
|
+
break;
|
|
77
|
+
case 'ARCHIVE':
|
|
78
|
+
archived += result.archivedCount;
|
|
79
|
+
break;
|
|
80
|
+
case 'CONTRADICTION':
|
|
81
|
+
contradictions++;
|
|
82
|
+
break;
|
|
83
|
+
case 'KEEP_ALL':
|
|
84
|
+
unchanged += allIds.length;
|
|
85
|
+
break;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
const result = this.consolidateLocally(cluster, dryRun);
|
|
91
|
+
details.push({ action: result.action, reason: result.reason, memories: allIds });
|
|
92
|
+
switch (result.action) {
|
|
93
|
+
case 'MERGE_SIMPLE':
|
|
94
|
+
merged++;
|
|
95
|
+
break;
|
|
96
|
+
case 'FLAG_REVIEW':
|
|
97
|
+
flagged++;
|
|
98
|
+
break;
|
|
99
|
+
case 'KEEP_ALL':
|
|
100
|
+
unchanged += allIds.length;
|
|
101
|
+
break;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
const consolidationResult = {
|
|
106
|
+
merged, archived, contradictions, flagged, unchanged,
|
|
107
|
+
duration_ms: Date.now() - startTime,
|
|
108
|
+
mode,
|
|
109
|
+
};
|
|
110
|
+
if (dryRun) {
|
|
111
|
+
consolidationResult.details = details;
|
|
112
|
+
}
|
|
113
|
+
return consolidationResult;
|
|
114
|
+
}
|
|
115
|
+
async consolidateWithLLM(cluster, dryRun) {
|
|
116
|
+
if (!this.llmClient)
|
|
117
|
+
return null;
|
|
118
|
+
const clusterJson = JSON.stringify({
|
|
119
|
+
anchor: { id: cluster.anchor.id, content: cluster.anchor.content, type: cluster.anchor.type, created_at: cluster.anchor.created_at },
|
|
120
|
+
similar: cluster.similar.map(s => ({
|
|
121
|
+
id: s.memory.id, content: s.memory.content, type: s.memory.type,
|
|
122
|
+
created_at: s.memory.created_at, similarity: s.similarity,
|
|
123
|
+
})),
|
|
124
|
+
});
|
|
125
|
+
const prompt = LLM_CONSOLIDATION_PROMPT.replace('{cluster_json}', clusterJson);
|
|
126
|
+
const response = await this.llmClient.extractJSON(prompt, 'Review this cluster and decide the action.');
|
|
127
|
+
if (!response)
|
|
128
|
+
return null;
|
|
129
|
+
if (!dryRun) {
|
|
130
|
+
await this.executeLLMAction(response, cluster);
|
|
131
|
+
}
|
|
132
|
+
return {
|
|
133
|
+
action: response.action,
|
|
134
|
+
reason: response.reason,
|
|
135
|
+
archivedCount: response.archive_ids?.length ?? 0,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
async executeLLMAction(response, cluster) {
|
|
139
|
+
const allMemories = [cluster.anchor, ...cluster.similar.map(s => s.memory)];
|
|
140
|
+
switch (response.action) {
|
|
141
|
+
case 'MERGE': {
|
|
142
|
+
if (!response.merged_content)
|
|
143
|
+
break;
|
|
144
|
+
// Create new merged memory
|
|
145
|
+
const newId = uuidv4();
|
|
146
|
+
const now = new Date().toISOString();
|
|
147
|
+
const sourceIds = allMemories.map(m => m.id);
|
|
148
|
+
const mergedMemory = {
|
|
149
|
+
id: newId,
|
|
150
|
+
content: response.merged_content,
|
|
151
|
+
type: response.merged_type ?? cluster.anchor.type,
|
|
152
|
+
project: cluster.anchor.project,
|
|
153
|
+
tags: response.merged_tags ?? cluster.anchor.tags,
|
|
154
|
+
entities: response.merged_entities ?? cluster.anchor.entities,
|
|
155
|
+
source: 'consolidation',
|
|
156
|
+
created_at: now,
|
|
157
|
+
updated_at: now,
|
|
158
|
+
is_deleted: 0,
|
|
159
|
+
source_type: 'consolidated',
|
|
160
|
+
consolidated_from: JSON.stringify(sourceIds),
|
|
161
|
+
};
|
|
162
|
+
this.sqlite.insertMemory(mergedMemory);
|
|
163
|
+
// Embed and store in Qdrant
|
|
164
|
+
const vector = await this.embedder.embed(response.merged_content);
|
|
165
|
+
const payload = {
|
|
166
|
+
id: newId,
|
|
167
|
+
project: cluster.anchor.project,
|
|
168
|
+
type: mergedMemory.type,
|
|
169
|
+
tags: mergedMemory.tags,
|
|
170
|
+
entities: mergedMemory.entities,
|
|
171
|
+
created_at: Math.floor(Date.now() / 1000),
|
|
172
|
+
};
|
|
173
|
+
await this.qdrant.upsert(newId, vector, payload);
|
|
174
|
+
// Link entities in Neo4j
|
|
175
|
+
if (mergedMemory.entities.length > 0) {
|
|
176
|
+
await this.neo4j.linkMemoryToEntities(newId, mergedMemory.entities);
|
|
177
|
+
}
|
|
178
|
+
// Archive old memories
|
|
179
|
+
for (const mem of allMemories) {
|
|
180
|
+
this.sqlite.softDelete(mem.id);
|
|
181
|
+
await this.qdrant.delete(mem.id);
|
|
182
|
+
}
|
|
183
|
+
// Log consolidation
|
|
184
|
+
this.sqlite.insertConsolidationLog({
|
|
185
|
+
id: uuidv4(),
|
|
186
|
+
action: 'MERGE',
|
|
187
|
+
reason: response.reason,
|
|
188
|
+
source_ids: sourceIds,
|
|
189
|
+
result_id: newId,
|
|
190
|
+
mode: 'llm',
|
|
191
|
+
created_at: now,
|
|
192
|
+
});
|
|
193
|
+
break;
|
|
194
|
+
}
|
|
195
|
+
case 'ARCHIVE': {
|
|
196
|
+
for (const id of response.archive_ids ?? []) {
|
|
197
|
+
this.sqlite.softDelete(id);
|
|
198
|
+
await this.qdrant.delete(id);
|
|
199
|
+
}
|
|
200
|
+
this.sqlite.insertConsolidationLog({
|
|
201
|
+
id: uuidv4(),
|
|
202
|
+
action: 'ARCHIVE',
|
|
203
|
+
reason: response.reason,
|
|
204
|
+
source_ids: response.archive_ids ?? [],
|
|
205
|
+
result_id: null,
|
|
206
|
+
mode: 'llm',
|
|
207
|
+
created_at: new Date().toISOString(),
|
|
208
|
+
});
|
|
209
|
+
break;
|
|
210
|
+
}
|
|
211
|
+
case 'CONTRADICTION': {
|
|
212
|
+
// Keep most recent, archive rest
|
|
213
|
+
for (const id of response.archive_ids ?? []) {
|
|
214
|
+
this.sqlite.softDelete(id);
|
|
215
|
+
await this.qdrant.delete(id);
|
|
216
|
+
}
|
|
217
|
+
this.sqlite.insertConsolidationLog({
|
|
218
|
+
id: uuidv4(),
|
|
219
|
+
action: 'CONTRADICTION',
|
|
220
|
+
reason: response.reason,
|
|
221
|
+
source_ids: allMemories.map(m => m.id),
|
|
222
|
+
result_id: response.keep_ids?.[0] ?? null,
|
|
223
|
+
mode: 'llm',
|
|
224
|
+
created_at: new Date().toISOString(),
|
|
225
|
+
});
|
|
226
|
+
break;
|
|
227
|
+
}
|
|
228
|
+
// KEEP_ALL: do nothing
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
consolidateLocally(cluster, dryRun) {
|
|
232
|
+
const maxSimilarity = Math.max(...cluster.similar.map(s => s.similarity));
|
|
233
|
+
if (maxSimilarity > 0.95) {
|
|
234
|
+
// Near-identical: keep the longest, archive rest
|
|
235
|
+
if (!dryRun) {
|
|
236
|
+
const allMemories = [cluster.anchor, ...cluster.similar.map(s => s.memory)];
|
|
237
|
+
const keepMemory = allMemories.reduce((best, current) => current.content.length > best.content.length ? current : best);
|
|
238
|
+
const archiveIds = [];
|
|
239
|
+
for (const mem of allMemories) {
|
|
240
|
+
if (mem.id !== keepMemory.id) {
|
|
241
|
+
this.sqlite.softDelete(mem.id);
|
|
242
|
+
void this.qdrant.delete(mem.id);
|
|
243
|
+
archiveIds.push(mem.id);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
this.sqlite.insertConsolidationLog({
|
|
247
|
+
id: uuidv4(),
|
|
248
|
+
action: 'MERGE_SIMPLE',
|
|
249
|
+
reason: `Near-identical memories (similarity > 0.95). Kept most detailed.`,
|
|
250
|
+
source_ids: allMemories.map(m => m.id),
|
|
251
|
+
result_id: keepMemory.id,
|
|
252
|
+
mode: 'local',
|
|
253
|
+
created_at: new Date().toISOString(),
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
return {
|
|
257
|
+
action: 'MERGE_SIMPLE',
|
|
258
|
+
reason: `Near-identical memories (max similarity: ${maxSimilarity.toFixed(3)})`,
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
if (maxSimilarity > 0.90) {
|
|
262
|
+
if (!dryRun) {
|
|
263
|
+
this.sqlite.insertConsolidationLog({
|
|
264
|
+
id: uuidv4(),
|
|
265
|
+
action: 'FLAG_REVIEW',
|
|
266
|
+
reason: 'Memories are similar but may contain distinct information',
|
|
267
|
+
source_ids: [cluster.anchor.id, ...cluster.similar.map(s => s.memory.id)],
|
|
268
|
+
result_id: null,
|
|
269
|
+
mode: 'local',
|
|
270
|
+
created_at: new Date().toISOString(),
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
return {
|
|
274
|
+
action: 'FLAG_REVIEW',
|
|
275
|
+
reason: 'Memories are similar but may contain distinct information',
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
return { action: 'KEEP_ALL', reason: 'Memories are sufficiently distinct' };
|
|
279
|
+
}
|
|
280
|
+
startAutoConsolidation(intervalMs) {
|
|
281
|
+
this.stopAutoConsolidation();
|
|
282
|
+
console.error(`[cortex] Auto-consolidation started (interval: ${intervalMs / 1000}s)`);
|
|
283
|
+
this.autoTimer = setInterval(() => {
|
|
284
|
+
void this.run().catch(err => {
|
|
285
|
+
console.error(`[cortex] Auto-consolidation error: ${err}`);
|
|
286
|
+
});
|
|
287
|
+
}, intervalMs);
|
|
288
|
+
}
|
|
289
|
+
stopAutoConsolidation() {
|
|
290
|
+
if (this.autoTimer) {
|
|
291
|
+
clearInterval(this.autoTimer);
|
|
292
|
+
this.autoTimer = null;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
//# sourceMappingURL=consolidator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consolidator.js","sourceRoot":"","sources":["../../src/consolidation/consolidator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export interface Embedder {
|
|
2
|
+
init(): Promise<void>;
|
|
3
|
+
embed(text: string): Promise<number[]>;
|
|
4
|
+
embedBatch(texts: string[]): Promise<number[][]>;
|
|
5
|
+
getDimensions(): number;
|
|
6
|
+
isReady(): boolean;
|
|
7
|
+
}
|
|
8
|
+
export declare function getEmbedder(): Promise<Embedder>;
|
|
9
|
+
//# sourceMappingURL=embedder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embedder.d.ts","sourceRoot":"","sources":["../../src/embedding/embedder.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,QAAQ;IACvB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACvC,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACjD,aAAa,IAAI,MAAM,CAAC;IACxB,OAAO,IAAI,OAAO,CAAC;CACpB;AA0FD,wBAAsB,WAAW,IAAI,OAAO,CAAC,QAAQ,CAAC,CAKrD"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { pipeline } from '@huggingface/transformers';
|
|
2
|
+
import { loadConfig } from '../config.js';
|
|
3
|
+
function l2Normalise(vector) {
|
|
4
|
+
let magnitude = 0;
|
|
5
|
+
for (const v of vector) {
|
|
6
|
+
magnitude += v * v;
|
|
7
|
+
}
|
|
8
|
+
magnitude = Math.sqrt(magnitude);
|
|
9
|
+
if (magnitude === 0)
|
|
10
|
+
return vector;
|
|
11
|
+
return vector.map(v => v / magnitude);
|
|
12
|
+
}
|
|
13
|
+
class EmbedderImpl {
|
|
14
|
+
pipe = null;
|
|
15
|
+
initPromise = null;
|
|
16
|
+
modelName;
|
|
17
|
+
dimensions;
|
|
18
|
+
constructor() {
|
|
19
|
+
const config = loadConfig();
|
|
20
|
+
this.modelName = config.embeddingModel;
|
|
21
|
+
this.dimensions = config.vectorDimensions;
|
|
22
|
+
}
|
|
23
|
+
async init() {
|
|
24
|
+
if (this.pipe)
|
|
25
|
+
return;
|
|
26
|
+
if (this.initPromise) {
|
|
27
|
+
await this.initPromise;
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
this.initPromise = this.loadModel();
|
|
31
|
+
await this.initPromise;
|
|
32
|
+
}
|
|
33
|
+
async loadModel() {
|
|
34
|
+
console.error(`[cortex] Loading embedding model: ${this.modelName}...`);
|
|
35
|
+
try {
|
|
36
|
+
// Type assertion needed: pipeline() union type is too complex for TS to represent
|
|
37
|
+
this.pipe = await pipeline('feature-extraction', this.modelName, {
|
|
38
|
+
dtype: 'fp32',
|
|
39
|
+
});
|
|
40
|
+
console.error(`[cortex] Embedding model loaded successfully.`);
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
this.initPromise = null;
|
|
44
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
45
|
+
throw new Error(`Failed to load embedding model "${this.modelName}": ${message}`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
async ensureReady() {
|
|
49
|
+
if (!this.pipe) {
|
|
50
|
+
await this.init();
|
|
51
|
+
}
|
|
52
|
+
return this.pipe;
|
|
53
|
+
}
|
|
54
|
+
async embed(text) {
|
|
55
|
+
const pipe = await this.ensureReady();
|
|
56
|
+
const output = await pipe(text, { pooling: 'mean', normalize: true });
|
|
57
|
+
const raw = Array.from(output.data).slice(0, this.dimensions);
|
|
58
|
+
return l2Normalise(raw);
|
|
59
|
+
}
|
|
60
|
+
async embedBatch(texts) {
|
|
61
|
+
if (texts.length === 0)
|
|
62
|
+
return [];
|
|
63
|
+
const pipe = await this.ensureReady();
|
|
64
|
+
const output = await pipe(texts, { pooling: 'mean', normalize: true });
|
|
65
|
+
const data = output.data;
|
|
66
|
+
const results = [];
|
|
67
|
+
for (let i = 0; i < texts.length; i++) {
|
|
68
|
+
const start = i * this.dimensions;
|
|
69
|
+
const raw = Array.from(data.slice(start, start + this.dimensions));
|
|
70
|
+
results.push(l2Normalise(raw));
|
|
71
|
+
}
|
|
72
|
+
return results;
|
|
73
|
+
}
|
|
74
|
+
getDimensions() {
|
|
75
|
+
return this.dimensions;
|
|
76
|
+
}
|
|
77
|
+
isReady() {
|
|
78
|
+
return this.pipe !== null;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
// Singleton
|
|
82
|
+
let instance = null;
|
|
83
|
+
export async function getEmbedder() {
|
|
84
|
+
if (!instance) {
|
|
85
|
+
instance = new EmbedderImpl();
|
|
86
|
+
}
|
|
87
|
+
return instance;
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=embedder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embedder.js","sourceRoot":"","sources":["../../src/embedding/embedder.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { BufferedEvent, ExtractedMemory, LLMClient, Memory } from '../types/index.js';
|
|
2
|
+
import type { EntityExtractor } from './extractor.js';
|
|
3
|
+
import type { Embedder } from '../embedding/embedder.js';
|
|
4
|
+
import type { QdrantStore } from '../storage/qdrant.js';
|
|
5
|
+
export declare function extractWithLLM(events: BufferedEvent[], recentContext: string, llmClient: LLMClient): Promise<ExtractedMemory[]>;
|
|
6
|
+
export declare function extractLocally(events: BufferedEvent[], recentMemories: Memory[], extractor: EntityExtractor, embedder: Embedder, qdrant: QdrantStore): Promise<ExtractedMemory[]>;
|
|
7
|
+
//# sourceMappingURL=auto-extractor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto-extractor.d.ts","sourceRoot":"","sources":["../../src/extraction/auto-extractor.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,aAAa,EACb,eAAe,EAEf,SAAS,EACT,MAAM,EACP,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAmDxD,wBAAsB,cAAc,CAClC,MAAM,EAAE,aAAa,EAAE,EACvB,aAAa,EAAE,MAAM,EACrB,SAAS,EAAE,SAAS,GACnB,OAAO,CAAC,eAAe,EAAE,CAAC,CAiC5B;AAED,wBAAsB,cAAc,CAClC,MAAM,EAAE,aAAa,EAAE,EACvB,cAAc,EAAE,MAAM,EAAE,EACxB,SAAS,EAAE,eAAe,EAC1B,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC,eAAe,EAAE,CAAC,CAgE5B"}
|