cortex-mcp 2.4.0 → 2.6.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 +49 -1
- package/README.md +35 -39
- package/dist/memory/access-pattern-tracker.d.ts +51 -0
- package/dist/memory/access-pattern-tracker.d.ts.map +1 -0
- package/dist/memory/access-pattern-tracker.js +92 -0
- package/dist/memory/access-pattern-tracker.js.map +1 -0
- package/dist/memory/auto-learner.d.ts.map +1 -1
- package/dist/memory/auto-learner.js +33 -2
- package/dist/memory/auto-learner.js.map +1 -1
- package/dist/memory/cross-memory-linker.d.ts +18 -0
- package/dist/memory/cross-memory-linker.d.ts.map +1 -0
- package/dist/memory/cross-memory-linker.js +115 -0
- package/dist/memory/cross-memory-linker.js.map +1 -0
- package/dist/memory/daily-diary.d.ts +30 -0
- package/dist/memory/daily-diary.d.ts.map +1 -0
- package/dist/memory/daily-diary.js +159 -0
- package/dist/memory/daily-diary.js.map +1 -0
- package/dist/memory/embedding-cache.d.ts +32 -0
- package/dist/memory/embedding-cache.d.ts.map +1 -0
- package/dist/memory/embedding-cache.js +76 -0
- package/dist/memory/embedding-cache.js.map +1 -0
- package/dist/memory/memory-decay.d.ts.map +1 -1
- package/dist/memory/memory-decay.js +23 -6
- package/dist/memory/memory-decay.js.map +1 -1
- package/dist/memory/memory-export-md.d.ts +12 -0
- package/dist/memory/memory-export-md.d.ts.map +1 -0
- package/dist/memory/memory-export-md.js +188 -0
- package/dist/memory/memory-export-md.js.map +1 -0
- package/dist/memory/memory-ranker.d.ts.map +1 -1
- package/dist/memory/memory-ranker.js +7 -2
- package/dist/memory/memory-ranker.js.map +1 -1
- package/dist/memory/mmr-reranker.d.ts +39 -0
- package/dist/memory/mmr-reranker.d.ts.map +1 -0
- package/dist/memory/mmr-reranker.js +115 -0
- package/dist/memory/mmr-reranker.js.map +1 -0
- package/dist/memory/query-expansion.d.ts +28 -0
- package/dist/memory/query-expansion.d.ts.map +1 -0
- package/dist/memory/query-expansion.js +140 -0
- package/dist/memory/query-expansion.js.map +1 -0
- package/dist/memory/soul-manager.d.ts +30 -0
- package/dist/memory/soul-manager.d.ts.map +1 -0
- package/dist/memory/soul-manager.js +171 -0
- package/dist/memory/soul-manager.js.map +1 -0
- package/dist/server/mcp-handler.d.ts.map +1 -1
- package/dist/server/mcp-handler.js +119 -48
- package/dist/server/mcp-handler.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MMR Re-ranking — Maximal Marginal Relevance.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from OpenClaw's mmr.ts architecture.
|
|
5
|
+
*
|
|
6
|
+
* Problem: Without MMR, recall might return 5 memories all saying
|
|
7
|
+
* "use TypeScript strict mode." That's redundant.
|
|
8
|
+
*
|
|
9
|
+
* Solution: MMR balances RELEVANCE (how well it matches the query)
|
|
10
|
+
* with DIVERSITY (how different it is from already-selected results).
|
|
11
|
+
*
|
|
12
|
+
* Formula: MMR(d) = λ * relevance(d) - (1-λ) * max_similarity(d, selected)
|
|
13
|
+
* Where λ = 0.7 means "70% relevance, 30% diversity"
|
|
14
|
+
*/
|
|
15
|
+
export interface MMRConfig {
|
|
16
|
+
enabled: boolean;
|
|
17
|
+
lambda: number;
|
|
18
|
+
diversityWeight: number;
|
|
19
|
+
}
|
|
20
|
+
export declare const DEFAULT_MMR_CONFIG: MMRConfig;
|
|
21
|
+
export interface ScoredItem {
|
|
22
|
+
score: number;
|
|
23
|
+
memory: {
|
|
24
|
+
id: string;
|
|
25
|
+
intent: string;
|
|
26
|
+
type: string;
|
|
27
|
+
tags?: string[];
|
|
28
|
+
files?: string[];
|
|
29
|
+
};
|
|
30
|
+
matchMethod: string;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Apply MMR re-ranking to search results.
|
|
34
|
+
* Keeps the top result unchanged, then iteratively picks
|
|
35
|
+
* the next result that maximizes relevance while being
|
|
36
|
+
* different from already-selected results.
|
|
37
|
+
*/
|
|
38
|
+
export declare function applyMMR<T extends ScoredItem>(results: T[], config?: Partial<MMRConfig>): T[];
|
|
39
|
+
//# sourceMappingURL=mmr-reranker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mmr-reranker.d.ts","sourceRoot":"","sources":["../../src/memory/mmr-reranker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,MAAM,WAAW,SAAS;IACtB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,MAAM,CAAC;CAC3B;AAED,eAAO,MAAM,kBAAkB,EAAE,SAIhC,CAAC;AAEF,MAAM,WAAW,UAAU;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE;QACJ,EAAE,EAAE,MAAM,CAAC;QACX,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;KACpB,CAAC;IACF,WAAW,EAAE,MAAM,CAAC;CACvB;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,UAAU,EACzC,OAAO,EAAE,CAAC,EAAE,EACZ,MAAM,GAAE,OAAO,CAAC,SAAS,CAAM,GAChC,CAAC,EAAE,CAuCL"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* MMR Re-ranking — Maximal Marginal Relevance.
|
|
4
|
+
*
|
|
5
|
+
* Extracted from OpenClaw's mmr.ts architecture.
|
|
6
|
+
*
|
|
7
|
+
* Problem: Without MMR, recall might return 5 memories all saying
|
|
8
|
+
* "use TypeScript strict mode." That's redundant.
|
|
9
|
+
*
|
|
10
|
+
* Solution: MMR balances RELEVANCE (how well it matches the query)
|
|
11
|
+
* with DIVERSITY (how different it is from already-selected results).
|
|
12
|
+
*
|
|
13
|
+
* Formula: MMR(d) = λ * relevance(d) - (1-λ) * max_similarity(d, selected)
|
|
14
|
+
* Where λ = 0.7 means "70% relevance, 30% diversity"
|
|
15
|
+
*/
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.DEFAULT_MMR_CONFIG = void 0;
|
|
18
|
+
exports.applyMMR = applyMMR;
|
|
19
|
+
exports.DEFAULT_MMR_CONFIG = {
|
|
20
|
+
enabled: true,
|
|
21
|
+
lambda: 0.7, // OpenClaw default: 70% relevance, 30% diversity
|
|
22
|
+
diversityWeight: 0.3,
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Apply MMR re-ranking to search results.
|
|
26
|
+
* Keeps the top result unchanged, then iteratively picks
|
|
27
|
+
* the next result that maximizes relevance while being
|
|
28
|
+
* different from already-selected results.
|
|
29
|
+
*/
|
|
30
|
+
function applyMMR(results, config = {}) {
|
|
31
|
+
const cfg = { ...exports.DEFAULT_MMR_CONFIG, ...config };
|
|
32
|
+
if (!cfg.enabled || results.length <= 2)
|
|
33
|
+
return results;
|
|
34
|
+
const lambda = cfg.lambda;
|
|
35
|
+
const selected = [];
|
|
36
|
+
const remaining = [...results];
|
|
37
|
+
// Always pick the top result first
|
|
38
|
+
selected.push(remaining.shift());
|
|
39
|
+
while (remaining.length > 0 && selected.length < results.length) {
|
|
40
|
+
let bestIdx = 0;
|
|
41
|
+
let bestMMR = -Infinity;
|
|
42
|
+
for (let i = 0; i < remaining.length; i++) {
|
|
43
|
+
const candidate = remaining[i];
|
|
44
|
+
// Relevance score (normalized)
|
|
45
|
+
const relevance = candidate.score;
|
|
46
|
+
// Max similarity to any already-selected result
|
|
47
|
+
const maxSim = Math.max(...selected.map(s => computeSimilarity(candidate, s)));
|
|
48
|
+
// MMR formula
|
|
49
|
+
const mmrScore = lambda * relevance - (1 - lambda) * maxSim;
|
|
50
|
+
if (mmrScore > bestMMR) {
|
|
51
|
+
bestMMR = mmrScore;
|
|
52
|
+
bestIdx = i;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
selected.push(remaining.splice(bestIdx, 1)[0]);
|
|
56
|
+
}
|
|
57
|
+
return selected;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Compute similarity between two memories.
|
|
61
|
+
* Uses a combination of:
|
|
62
|
+
* 1. Word overlap (Jaccard similarity on intent words)
|
|
63
|
+
* 2. Type match (same type = more similar)
|
|
64
|
+
* 3. File overlap (shared files = more similar)
|
|
65
|
+
*/
|
|
66
|
+
function computeSimilarity(a, b) {
|
|
67
|
+
let sim = 0;
|
|
68
|
+
// 1. Word overlap (Jaccard) — main signal
|
|
69
|
+
const wordsA = new Set(extractWords(a.memory.intent));
|
|
70
|
+
const wordsB = new Set(extractWords(b.memory.intent));
|
|
71
|
+
if (wordsA.size > 0 && wordsB.size > 0) {
|
|
72
|
+
let intersection = 0;
|
|
73
|
+
for (const w of wordsA) {
|
|
74
|
+
if (wordsB.has(w))
|
|
75
|
+
intersection++;
|
|
76
|
+
}
|
|
77
|
+
const union = wordsA.size + wordsB.size - intersection;
|
|
78
|
+
sim += (intersection / union) * 0.6; // 60% weight on word overlap
|
|
79
|
+
}
|
|
80
|
+
// 2. Same type = similar
|
|
81
|
+
if (a.memory.type === b.memory.type) {
|
|
82
|
+
sim += 0.2;
|
|
83
|
+
}
|
|
84
|
+
// 3. File overlap
|
|
85
|
+
const filesA = new Set(a.memory.files || []);
|
|
86
|
+
const filesB = new Set(b.memory.files || []);
|
|
87
|
+
if (filesA.size > 0 && filesB.size > 0) {
|
|
88
|
+
let fileOverlap = 0;
|
|
89
|
+
for (const f of filesA) {
|
|
90
|
+
if (filesB.has(f))
|
|
91
|
+
fileOverlap++;
|
|
92
|
+
}
|
|
93
|
+
if (fileOverlap > 0) {
|
|
94
|
+
sim += 0.2 * (fileOverlap / Math.max(filesA.size, filesB.size));
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return Math.min(sim, 1.0);
|
|
98
|
+
}
|
|
99
|
+
// Stop words to ignore in similarity computation
|
|
100
|
+
const STOP_WORDS = new Set([
|
|
101
|
+
'the', 'a', 'an', 'is', 'are', 'was', 'were', 'be', 'been', 'being',
|
|
102
|
+
'have', 'has', 'had', 'do', 'does', 'did', 'will', 'would', 'could',
|
|
103
|
+
'should', 'may', 'might', 'can', 'shall', 'to', 'of', 'in', 'for',
|
|
104
|
+
'on', 'with', 'at', 'by', 'from', 'as', 'into', 'through', 'during',
|
|
105
|
+
'use', 'used', 'using', 'this', 'that', 'these', 'those', 'it', 'its',
|
|
106
|
+
'not', 'no', 'nor', 'but', 'or', 'and', 'if', 'then', 'else', 'when',
|
|
107
|
+
'up', 'out', 'about', 'so', 'all', 'each', 'every', 'both', 'few',
|
|
108
|
+
]);
|
|
109
|
+
function extractWords(text) {
|
|
110
|
+
return text.toLowerCase()
|
|
111
|
+
.replace(/[^a-z0-9\s]/g, ' ')
|
|
112
|
+
.split(/\s+/)
|
|
113
|
+
.filter(w => w.length > 2 && !STOP_WORDS.has(w));
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=mmr-reranker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mmr-reranker.js","sourceRoot":"","sources":["../../src/memory/mmr-reranker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Query Expansion — Smarter search like OpenClaw's query-expansion.ts.
|
|
3
|
+
*
|
|
4
|
+
* Problem: User searches for "authentication bug" but the memory
|
|
5
|
+
* says "login issue with JWT tokens." Raw search misses it.
|
|
6
|
+
*
|
|
7
|
+
* Solution: Expand the query with synonyms and related terms:
|
|
8
|
+
* "authentication bug" → "authentication auth login bug error issue fix"
|
|
9
|
+
*
|
|
10
|
+
* This is OpenClaw's approach — extract keywords and add related terms
|
|
11
|
+
* so both FTS and vector search find more relevant results.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Expand a query with synonyms and related programming terms.
|
|
15
|
+
* Returns the original query plus expanded terms.
|
|
16
|
+
*/
|
|
17
|
+
export declare function expandQuery(query: string): string;
|
|
18
|
+
/**
|
|
19
|
+
* Extract key technical terms from a query for targeted search.
|
|
20
|
+
* Filters out stop words and generic terms, keeping only meaningful tokens.
|
|
21
|
+
*/
|
|
22
|
+
export declare function extractKeyTerms(query: string): string[];
|
|
23
|
+
/**
|
|
24
|
+
* Generate alternative search queries for better recall.
|
|
25
|
+
* Returns the original plus 1-2 reformulated queries.
|
|
26
|
+
*/
|
|
27
|
+
export declare function generateAlternativeQueries(query: string): string[];
|
|
28
|
+
//# sourceMappingURL=query-expansion.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query-expansion.d.ts","sourceRoot":"","sources":["../../src/memory/query-expansion.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAcjD;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAKvD;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAsBlE"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Query Expansion — Smarter search like OpenClaw's query-expansion.ts.
|
|
4
|
+
*
|
|
5
|
+
* Problem: User searches for "authentication bug" but the memory
|
|
6
|
+
* says "login issue with JWT tokens." Raw search misses it.
|
|
7
|
+
*
|
|
8
|
+
* Solution: Expand the query with synonyms and related terms:
|
|
9
|
+
* "authentication bug" → "authentication auth login bug error issue fix"
|
|
10
|
+
*
|
|
11
|
+
* This is OpenClaw's approach — extract keywords and add related terms
|
|
12
|
+
* so both FTS and vector search find more relevant results.
|
|
13
|
+
*/
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.expandQuery = expandQuery;
|
|
16
|
+
exports.extractKeyTerms = extractKeyTerms;
|
|
17
|
+
exports.generateAlternativeQueries = generateAlternativeQueries;
|
|
18
|
+
/**
|
|
19
|
+
* Expand a query with synonyms and related programming terms.
|
|
20
|
+
* Returns the original query plus expanded terms.
|
|
21
|
+
*/
|
|
22
|
+
function expandQuery(query) {
|
|
23
|
+
const words = query.toLowerCase().split(/\s+/).filter(w => w.length > 1);
|
|
24
|
+
const expanded = new Set(words);
|
|
25
|
+
for (const word of words) {
|
|
26
|
+
const synonyms = SYNONYM_MAP[word];
|
|
27
|
+
if (synonyms) {
|
|
28
|
+
for (const syn of synonyms) {
|
|
29
|
+
expanded.add(syn);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return Array.from(expanded).join(' ');
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Extract key technical terms from a query for targeted search.
|
|
37
|
+
* Filters out stop words and generic terms, keeping only meaningful tokens.
|
|
38
|
+
*/
|
|
39
|
+
function extractKeyTerms(query) {
|
|
40
|
+
return query.toLowerCase()
|
|
41
|
+
.replace(/[^a-z0-9\s_-]/g, ' ')
|
|
42
|
+
.split(/\s+/)
|
|
43
|
+
.filter(w => w.length > 2 && !STOP_WORDS.has(w));
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Generate alternative search queries for better recall.
|
|
47
|
+
* Returns the original plus 1-2 reformulated queries.
|
|
48
|
+
*/
|
|
49
|
+
function generateAlternativeQueries(query) {
|
|
50
|
+
const queries = [query];
|
|
51
|
+
const lower = query.toLowerCase();
|
|
52
|
+
// If asking "how to X" → also search for "X implementation"
|
|
53
|
+
const howToMatch = lower.match(/how\s+to\s+(.+)/);
|
|
54
|
+
if (howToMatch) {
|
|
55
|
+
queries.push(`${howToMatch[1]} implementation`);
|
|
56
|
+
queries.push(`${howToMatch[1]} pattern`);
|
|
57
|
+
}
|
|
58
|
+
// If asking about "error" → also search for "bug fix"
|
|
59
|
+
if (lower.includes('error') || lower.includes('bug')) {
|
|
60
|
+
queries.push(lower.replace(/error|bug/g, 'fix correction'));
|
|
61
|
+
}
|
|
62
|
+
// If asking about "why" → search for decisions
|
|
63
|
+
if (lower.startsWith('why')) {
|
|
64
|
+
queries.push(lower.replace('why', 'decision reason'));
|
|
65
|
+
}
|
|
66
|
+
return queries.slice(0, 3); // Max 3 alternatives
|
|
67
|
+
}
|
|
68
|
+
// ─── Synonym Map for Programming Terms ──────────────────────────────────────
|
|
69
|
+
const SYNONYM_MAP = {
|
|
70
|
+
// Authentication
|
|
71
|
+
'auth': ['authentication', 'login', 'signin', 'jwt', 'token', 'session'],
|
|
72
|
+
'authentication': ['auth', 'login', 'signin', 'jwt'],
|
|
73
|
+
'login': ['auth', 'authentication', 'signin'],
|
|
74
|
+
'logout': ['signout', 'session'],
|
|
75
|
+
// Database
|
|
76
|
+
'database': ['db', 'sql', 'query', 'schema', 'migration'],
|
|
77
|
+
'db': ['database', 'sql', 'query'],
|
|
78
|
+
'sql': ['database', 'query', 'schema'],
|
|
79
|
+
'migration': ['database', 'schema', 'alter'],
|
|
80
|
+
'schema': ['database', 'model', 'table'],
|
|
81
|
+
// API
|
|
82
|
+
'api': ['endpoint', 'route', 'rest', 'request', 'response'],
|
|
83
|
+
'endpoint': ['api', 'route', 'handler'],
|
|
84
|
+
'route': ['api', 'endpoint', 'path', 'handler'],
|
|
85
|
+
'request': ['req', 'http', 'fetch'],
|
|
86
|
+
'response': ['res', 'http', 'reply'],
|
|
87
|
+
// Errors & Debugging
|
|
88
|
+
'error': ['bug', 'issue', 'exception', 'crash', 'failure', 'fix'],
|
|
89
|
+
'bug': ['error', 'issue', 'defect', 'fix', 'correction'],
|
|
90
|
+
'fix': ['repair', 'correction', 'patch', 'resolve'],
|
|
91
|
+
'crash': ['error', 'exception', 'failure', 'abort'],
|
|
92
|
+
'debug': ['troubleshoot', 'diagnose', 'inspect', 'trace'],
|
|
93
|
+
// Testing
|
|
94
|
+
'test': ['testing', 'spec', 'unit', 'jest', 'mocha', 'vitest'],
|
|
95
|
+
'testing': ['test', 'spec', 'assertion', 'mock'],
|
|
96
|
+
'mock': ['stub', 'fake', 'spy', 'test'],
|
|
97
|
+
// Architecture
|
|
98
|
+
'component': ['module', 'widget', 'element'],
|
|
99
|
+
'module': ['component', 'package', 'library'],
|
|
100
|
+
'pattern': ['architecture', 'design', 'structure'],
|
|
101
|
+
'refactor': ['restructure', 'cleanup', 'reorganize'],
|
|
102
|
+
// Frontend
|
|
103
|
+
'style': ['css', 'styling', 'theme', 'design'],
|
|
104
|
+
'css': ['style', 'stylesheet', 'tailwind'],
|
|
105
|
+
'ui': ['interface', 'frontend', 'view', 'component'],
|
|
106
|
+
'layout': ['grid', 'flex', 'responsive', 'design'],
|
|
107
|
+
// State
|
|
108
|
+
'state': ['store', 'context', 'redux', 'zustand'],
|
|
109
|
+
'cache': ['memo', 'memoize', 'store', 'buffer'],
|
|
110
|
+
// Config
|
|
111
|
+
'config': ['configuration', 'settings', 'options', 'env'],
|
|
112
|
+
'env': ['environment', 'config', 'dotenv', 'variable'],
|
|
113
|
+
// Performance
|
|
114
|
+
'performance': ['speed', 'optimize', 'fast', 'slow', 'latency'],
|
|
115
|
+
'optimize': ['performance', 'improve', 'speed', 'efficient'],
|
|
116
|
+
'slow': ['performance', 'latency', 'bottleneck', 'optimize'],
|
|
117
|
+
// Security
|
|
118
|
+
'security': ['auth', 'encryption', 'vulnerability', 'xss', 'csrf'],
|
|
119
|
+
'encrypt': ['hash', 'security', 'cipher', 'bcrypt'],
|
|
120
|
+
// TypeScript
|
|
121
|
+
'type': ['interface', 'typescript', 'generic', 'typing'],
|
|
122
|
+
'interface': ['type', 'contract', 'shape', 'typescript'],
|
|
123
|
+
'generic': ['type', 'template', 'parameterized'],
|
|
124
|
+
// Deployment
|
|
125
|
+
'deploy': ['deployment', 'release', 'publish', 'ship'],
|
|
126
|
+
'ci': ['pipeline', 'github-actions', 'workflow', 'build'],
|
|
127
|
+
};
|
|
128
|
+
const STOP_WORDS = new Set([
|
|
129
|
+
'the', 'a', 'an', 'is', 'are', 'was', 'were', 'be', 'been', 'being',
|
|
130
|
+
'have', 'has', 'had', 'do', 'does', 'did', 'will', 'would', 'could',
|
|
131
|
+
'should', 'may', 'might', 'can', 'shall', 'to', 'of', 'in', 'for',
|
|
132
|
+
'on', 'with', 'at', 'by', 'from', 'as', 'into', 'through', 'during',
|
|
133
|
+
'this', 'that', 'these', 'those', 'it', 'its', 'not', 'no', 'but',
|
|
134
|
+
'or', 'and', 'if', 'then', 'else', 'when', 'up', 'out', 'about',
|
|
135
|
+
'so', 'all', 'each', 'every', 'both', 'few', 'more', 'most', 'other',
|
|
136
|
+
'some', 'such', 'only', 'own', 'same', 'than', 'too', 'very',
|
|
137
|
+
'just', 'because', 'before', 'after', 'above', 'below', 'between',
|
|
138
|
+
'what', 'which', 'who', 'whom', 'how', 'where', 'there', 'here',
|
|
139
|
+
]);
|
|
140
|
+
//# sourceMappingURL=query-expansion.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query-expansion.js","sourceRoot":"","sources":["../../src/memory/query-expansion.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export interface SoulEntry {
|
|
2
|
+
category: string;
|
|
3
|
+
content: string;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Load SOUL.md from workspace. Returns content or null.
|
|
7
|
+
*/
|
|
8
|
+
export declare function loadSoul(workspaceRoot: string): string | null;
|
|
9
|
+
/**
|
|
10
|
+
* Initialize SOUL.md with default template if it doesn't exist.
|
|
11
|
+
*/
|
|
12
|
+
export declare function initSoul(workspaceRoot: string): string;
|
|
13
|
+
/**
|
|
14
|
+
* Update soul by appending a new entry under the right category.
|
|
15
|
+
*/
|
|
16
|
+
export declare function updateSoul(workspaceRoot: string, entry: SoulEntry): void;
|
|
17
|
+
/**
|
|
18
|
+
* Format soul content for injection into force_recall (Layer 0).
|
|
19
|
+
*/
|
|
20
|
+
export declare function formatSoul(workspaceRoot: string): string;
|
|
21
|
+
/**
|
|
22
|
+
* Auto-learn from memories to build soul entries.
|
|
23
|
+
* Called periodically — extracts strong conventions and rules.
|
|
24
|
+
*/
|
|
25
|
+
export declare function autoLearnSoul(workspaceRoot: string, memories: Array<{
|
|
26
|
+
type: string;
|
|
27
|
+
intent: string;
|
|
28
|
+
accessCount?: number;
|
|
29
|
+
}>): void;
|
|
30
|
+
//# sourceMappingURL=soul-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"soul-manager.d.ts","sourceRoot":"","sources":["../../src/memory/soul-manager.ts"],"names":[],"mappings":"AAgBA,MAAM,WAAW,SAAS;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACnB;AAuBD;;GAEG;AACH,wBAAgB,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQ7D;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAWtD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,aAAa,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,GAAG,IAAI,CAoBxE;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CASxD;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,aAAa,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG,IAAI,CAelI"}
|
|
@@ -0,0 +1,171 @@
|
|
|
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.loadSoul = loadSoul;
|
|
37
|
+
exports.initSoul = initSoul;
|
|
38
|
+
exports.updateSoul = updateSoul;
|
|
39
|
+
exports.formatSoul = formatSoul;
|
|
40
|
+
exports.autoLearnSoul = autoLearnSoul;
|
|
41
|
+
/**
|
|
42
|
+
* Soul Manager — OpenClaw-style persistent identity layer.
|
|
43
|
+
*
|
|
44
|
+
* Creates and maintains a SOUL.md file in the workspace that stores:
|
|
45
|
+
* - User's coding preferences ("always use TypeScript strict mode")
|
|
46
|
+
* - Project conventions ("we use PostgreSQL, never MongoDB")
|
|
47
|
+
* - Identity ("Senior Backend Engineer working on e-commerce platform")
|
|
48
|
+
*
|
|
49
|
+
* This is injected as Layer 0 in force_recall — the very first thing the AI sees.
|
|
50
|
+
* Unlike transient memories, the Soul NEVER decays.
|
|
51
|
+
*
|
|
52
|
+
* Inspired by OpenClaw's SOUL.md / IDENTITY.md architecture.
|
|
53
|
+
*/
|
|
54
|
+
const fs = __importStar(require("fs"));
|
|
55
|
+
const path = __importStar(require("path"));
|
|
56
|
+
const DEFAULT_SOUL = `# 🧠 Cortex Soul — Who I Am
|
|
57
|
+
|
|
58
|
+
> This file is your AI's persistent identity. Edit it freely.
|
|
59
|
+
> Cortex reads this at the start of every session.
|
|
60
|
+
|
|
61
|
+
## Identity
|
|
62
|
+
- (Add your role: e.g., "Senior TypeScript developer")
|
|
63
|
+
- (Add your project: e.g., "Building an e-commerce platform")
|
|
64
|
+
|
|
65
|
+
## Conventions
|
|
66
|
+
- (Add team rules: e.g., "Always use strict TypeScript, never \`any\`")
|
|
67
|
+
- (Add stack: e.g., "PostgreSQL, Redis, Next.js 14")
|
|
68
|
+
|
|
69
|
+
## Preferences
|
|
70
|
+
- (Add style: e.g., "Prefer functional over OOP")
|
|
71
|
+
- (Add tools: e.g., "Use pnpm, not npm")
|
|
72
|
+
|
|
73
|
+
## Rules (Never Break)
|
|
74
|
+
- (Add hard rules: e.g., "Never delete user data without confirmation")
|
|
75
|
+
`;
|
|
76
|
+
/**
|
|
77
|
+
* Load SOUL.md from workspace. Returns content or null.
|
|
78
|
+
*/
|
|
79
|
+
function loadSoul(workspaceRoot) {
|
|
80
|
+
const soulPath = getSoulPath(workspaceRoot);
|
|
81
|
+
try {
|
|
82
|
+
if (fs.existsSync(soulPath)) {
|
|
83
|
+
return fs.readFileSync(soulPath, 'utf-8').trim();
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
catch { /* file not readable */ }
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Initialize SOUL.md with default template if it doesn't exist.
|
|
91
|
+
*/
|
|
92
|
+
function initSoul(workspaceRoot) {
|
|
93
|
+
const soulPath = getSoulPath(workspaceRoot);
|
|
94
|
+
try {
|
|
95
|
+
const dir = path.dirname(soulPath);
|
|
96
|
+
if (!fs.existsSync(dir))
|
|
97
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
98
|
+
if (!fs.existsSync(soulPath)) {
|
|
99
|
+
fs.writeFileSync(soulPath, DEFAULT_SOUL, 'utf-8');
|
|
100
|
+
return DEFAULT_SOUL;
|
|
101
|
+
}
|
|
102
|
+
return fs.readFileSync(soulPath, 'utf-8').trim();
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
return '';
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Update soul by appending a new entry under the right category.
|
|
110
|
+
*/
|
|
111
|
+
function updateSoul(workspaceRoot, entry) {
|
|
112
|
+
const soulPath = getSoulPath(workspaceRoot);
|
|
113
|
+
try {
|
|
114
|
+
let content = loadSoul(workspaceRoot) || DEFAULT_SOUL;
|
|
115
|
+
const sectionMap = {
|
|
116
|
+
'identity': '## Identity',
|
|
117
|
+
'convention': '## Conventions',
|
|
118
|
+
'preference': '## Preferences',
|
|
119
|
+
'rule': '## Rules (Never Break)',
|
|
120
|
+
};
|
|
121
|
+
const header = sectionMap[entry.category] || '## Preferences';
|
|
122
|
+
const idx = content.indexOf(header);
|
|
123
|
+
if (idx >= 0) {
|
|
124
|
+
const insertAt = content.indexOf('\n', idx) + 1;
|
|
125
|
+
content = content.slice(0, insertAt) + `- ${entry.content}\n` + content.slice(insertAt);
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
content += `\n${header}\n- ${entry.content}\n`;
|
|
129
|
+
}
|
|
130
|
+
fs.writeFileSync(soulPath, content, 'utf-8');
|
|
131
|
+
}
|
|
132
|
+
catch { /* non-fatal */ }
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Format soul content for injection into force_recall (Layer 0).
|
|
136
|
+
*/
|
|
137
|
+
function formatSoul(workspaceRoot) {
|
|
138
|
+
const soul = loadSoul(workspaceRoot);
|
|
139
|
+
if (!soul || soul.includes('(Add your role'))
|
|
140
|
+
return ''; // Still default template
|
|
141
|
+
// Strip the header explanation, keep only the actual content
|
|
142
|
+
const lines = soul.split('\n').filter(l => l.trim() && !l.startsWith('>') && !l.includes('(Add your'));
|
|
143
|
+
if (lines.length <= 1)
|
|
144
|
+
return '';
|
|
145
|
+
return `\n## 🧬 Soul (Persistent Identity)\n${lines.join('\n')}`;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Auto-learn from memories to build soul entries.
|
|
149
|
+
* Called periodically — extracts strong conventions and rules.
|
|
150
|
+
*/
|
|
151
|
+
function autoLearnSoul(workspaceRoot, memories) {
|
|
152
|
+
try {
|
|
153
|
+
const soul = loadSoul(workspaceRoot) || '';
|
|
154
|
+
const strongConventions = memories.filter(m => (m.type === 'CONVENTION' || m.type === 'DECISION') &&
|
|
155
|
+
(m.accessCount || 0) >= 3 && // Accessed multiple times = important
|
|
156
|
+
!soul.includes(m.intent.slice(0, 40)) // Not already in soul
|
|
157
|
+
);
|
|
158
|
+
for (const m of strongConventions.slice(0, 3)) {
|
|
159
|
+
updateSoul(workspaceRoot, {
|
|
160
|
+
category: m.type === 'CONVENTION' ? 'convention' : 'preference',
|
|
161
|
+
content: m.intent.slice(0, 150),
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
catch { /* non-fatal */ }
|
|
166
|
+
}
|
|
167
|
+
// ─── Helpers ──────────────────────────────────────────────────────────────────
|
|
168
|
+
function getSoulPath(workspaceRoot) {
|
|
169
|
+
return path.join(workspaceRoot, '.cortex', 'SOUL.md');
|
|
170
|
+
}
|
|
171
|
+
//# sourceMappingURL=soul-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"soul-manager.js","sourceRoot":"","sources":["../../src/memory/soul-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-handler.d.ts","sourceRoot":"","sources":["../../src/server/mcp-handler.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"mcp-handler.d.ts","sourceRoot":"","sources":["../../src/server/mcp-handler.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAsS3C,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,aAAa,CAAC,EAAE,MAAM;4BAC5D,GAAG,KAAG,OAAO,CAAC,GAAG,CAAC;EA88D1D"}
|