cortex-mcp 2.5.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/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/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 +10 -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 +103 -48
- package/dist/server/mcp-handler.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.cleanupMemories = cleanupMemories;
|
|
4
|
-
const types_1 = require("../types");
|
|
5
4
|
const config_1 = require("../config/config");
|
|
6
5
|
const memory_cache_1 = require("./memory-cache");
|
|
7
6
|
function cleanupMemories(memoryStore) {
|
|
@@ -23,16 +22,21 @@ function cleanupMemories(memoryStore) {
|
|
|
23
22
|
}
|
|
24
23
|
}
|
|
25
24
|
}
|
|
26
|
-
// 1.
|
|
27
|
-
|
|
25
|
+
// 1. Two-tier OpenClaw-style decay:
|
|
26
|
+
// TRANSACTIONAL (high volume, decays fast): INSIGHT, CONVERSATION
|
|
27
|
+
// OPERATIONAL (low volume, persists): DECISION, CORRECTION, CONVENTION, BUG_FIX
|
|
28
|
+
const OPERATIONAL_TYPES = new Set(['DECISION', 'CORRECTION', 'CONVENTION', 'BUG_FIX', 'PROVEN_PATTERN']);
|
|
29
|
+
const TRANSACTIONAL_MAX_AGE = 5 * DAY; // 5 days for junk
|
|
30
|
+
const OPERATIONAL_MAX_AGE = 60 * DAY; // 60 days for gold (if 0 access)
|
|
31
|
+
const staleInsights = memoryStore.getStaleMemories(TRANSACTIONAL_MAX_AGE, 500);
|
|
28
32
|
for (const m of staleInsights) {
|
|
29
|
-
if (m.type
|
|
33
|
+
if (!OPERATIONAL_TYPES.has(m.type)) {
|
|
30
34
|
memoryStore.deactivate(m.id);
|
|
31
35
|
cleaned++;
|
|
32
36
|
}
|
|
33
37
|
}
|
|
34
|
-
// 2. Deactivate
|
|
35
|
-
const staleAll = memoryStore.getStaleMemories(
|
|
38
|
+
// 2. Deactivate operational memories > 60 days with 0 access (very old, never used)
|
|
39
|
+
const staleAll = memoryStore.getStaleMemories(OPERATIONAL_MAX_AGE, 500);
|
|
36
40
|
for (const m of staleAll) {
|
|
37
41
|
memoryStore.deactivate(m.id);
|
|
38
42
|
cleaned++;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory-decay.js","sourceRoot":"","sources":["../../src/memory/memory-decay.ts"],"names":[],"mappings":";;AAYA,
|
|
1
|
+
{"version":3,"file":"memory-decay.js","sourceRoot":"","sources":["../../src/memory/memory-decay.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { MemoryStore } from '../db/memory-store';
|
|
2
|
+
/**
|
|
3
|
+
* Generate MEMORY.md from the top memories in the store.
|
|
4
|
+
* Only includes high-importance, frequently-accessed, active memories.
|
|
5
|
+
*/
|
|
6
|
+
export declare function generateMemoryMd(memoryStore: MemoryStore, workspaceRoot: string): string;
|
|
7
|
+
/**
|
|
8
|
+
* Import user-edited MEMORY.md back into the memory store.
|
|
9
|
+
* Only imports NEW lines that don't already exist in the store.
|
|
10
|
+
*/
|
|
11
|
+
export declare function importMemoryMd(workspaceRoot: string, memoryStore: MemoryStore): number;
|
|
12
|
+
//# sourceMappingURL=memory-export-md.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-export-md.d.ts","sourceRoot":"","sources":["../../src/memory/memory-export-md.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEjD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CAkExF;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,aAAa,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,GAAG,MAAM,CA2DtF"}
|
|
@@ -0,0 +1,188 @@
|
|
|
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.generateMemoryMd = generateMemoryMd;
|
|
37
|
+
exports.importMemoryMd = importMemoryMd;
|
|
38
|
+
/**
|
|
39
|
+
* Memory Export MD — OpenClaw-style human-readable knowledge base.
|
|
40
|
+
*
|
|
41
|
+
* Auto-generates a MEMORY.md file with curated, high-value memories.
|
|
42
|
+
* Users can read and edit this file — changes are imported back on next startup.
|
|
43
|
+
*
|
|
44
|
+
* Like OpenClaw's MEMORY.md: the "truth" the agent carries across sessions,
|
|
45
|
+
* stored in plain Markdown that any human can read.
|
|
46
|
+
*
|
|
47
|
+
* Stored in: .cortex/MEMORY.md
|
|
48
|
+
*/
|
|
49
|
+
const fs = __importStar(require("fs"));
|
|
50
|
+
const path = __importStar(require("path"));
|
|
51
|
+
/**
|
|
52
|
+
* Generate MEMORY.md from the top memories in the store.
|
|
53
|
+
* Only includes high-importance, frequently-accessed, active memories.
|
|
54
|
+
*/
|
|
55
|
+
function generateMemoryMd(memoryStore, workspaceRoot) {
|
|
56
|
+
const outPath = path.join(workspaceRoot, '.cortex', 'MEMORY.md');
|
|
57
|
+
try {
|
|
58
|
+
const dir = path.dirname(outPath);
|
|
59
|
+
if (!fs.existsSync(dir))
|
|
60
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
61
|
+
const all = memoryStore.getActive(200);
|
|
62
|
+
// Sort by importance * access count (most valuable first)
|
|
63
|
+
const ranked = all
|
|
64
|
+
.filter(m => m.importance >= 0.6 || (m.accessCount || 0) >= 2)
|
|
65
|
+
.sort((a, b) => {
|
|
66
|
+
const scoreA = (a.importance || 0.5) * (1 + (a.accessCount || 0) * 0.2);
|
|
67
|
+
const scoreB = (b.importance || 0.5) * (1 + (b.accessCount || 0) * 0.2);
|
|
68
|
+
return scoreB - scoreA;
|
|
69
|
+
})
|
|
70
|
+
.slice(0, 50);
|
|
71
|
+
// Group by type
|
|
72
|
+
const groups = {};
|
|
73
|
+
for (const m of ranked) {
|
|
74
|
+
if (!groups[m.type])
|
|
75
|
+
groups[m.type] = [];
|
|
76
|
+
groups[m.type].push(m);
|
|
77
|
+
}
|
|
78
|
+
// Build markdown
|
|
79
|
+
const lines = [
|
|
80
|
+
'# 🧠 Cortex Memory — Curated Knowledge',
|
|
81
|
+
'',
|
|
82
|
+
'> Auto-generated by Cortex. You can edit this file — changes will be imported back.',
|
|
83
|
+
`> Last updated: ${new Date().toISOString().split('T')[0]}`,
|
|
84
|
+
`> Total memories: ${all.length} active, ${ranked.length} shown here`,
|
|
85
|
+
'',
|
|
86
|
+
];
|
|
87
|
+
const typeEmoji = {
|
|
88
|
+
DECISION: '📌',
|
|
89
|
+
CORRECTION: '🔴',
|
|
90
|
+
BUG_FIX: '🐛',
|
|
91
|
+
CONVENTION: '📏',
|
|
92
|
+
INSIGHT: '💡',
|
|
93
|
+
PROVEN_PATTERN: '✅',
|
|
94
|
+
FAILED_SUGGESTION: '❌',
|
|
95
|
+
CONVERSATION: '💬',
|
|
96
|
+
};
|
|
97
|
+
for (const [type, memories] of Object.entries(groups)) {
|
|
98
|
+
const emoji = typeEmoji[type] || '📝';
|
|
99
|
+
lines.push(`## ${emoji} ${type}`);
|
|
100
|
+
lines.push('');
|
|
101
|
+
for (const m of memories) {
|
|
102
|
+
const reason = m.reason && !m.reason.startsWith('Auto-detected')
|
|
103
|
+
? ` — _${m.reason}_` : '';
|
|
104
|
+
const age = formatAge(m.timestamp);
|
|
105
|
+
lines.push(`- ${m.intent}${reason} _(${age})_`);
|
|
106
|
+
}
|
|
107
|
+
lines.push('');
|
|
108
|
+
}
|
|
109
|
+
const content = lines.join('\n');
|
|
110
|
+
fs.writeFileSync(outPath, content, 'utf-8');
|
|
111
|
+
return content;
|
|
112
|
+
}
|
|
113
|
+
catch (err) {
|
|
114
|
+
return `Error generating MEMORY.md: ${err.message}`;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Import user-edited MEMORY.md back into the memory store.
|
|
119
|
+
* Only imports NEW lines that don't already exist in the store.
|
|
120
|
+
*/
|
|
121
|
+
function importMemoryMd(workspaceRoot, memoryStore) {
|
|
122
|
+
const mdPath = path.join(workspaceRoot, '.cortex', 'MEMORY.md');
|
|
123
|
+
let imported = 0;
|
|
124
|
+
try {
|
|
125
|
+
if (!fs.existsSync(mdPath))
|
|
126
|
+
return 0;
|
|
127
|
+
const content = fs.readFileSync(mdPath, 'utf-8');
|
|
128
|
+
const lines = content.split('\n');
|
|
129
|
+
let currentType = 'INSIGHT';
|
|
130
|
+
const typeMap = {
|
|
131
|
+
'DECISION': 'DECISION',
|
|
132
|
+
'CORRECTION': 'CORRECTION',
|
|
133
|
+
'BUG_FIX': 'BUG_FIX',
|
|
134
|
+
'CONVENTION': 'CONVENTION',
|
|
135
|
+
'INSIGHT': 'INSIGHT',
|
|
136
|
+
'PROVEN_PATTERN': 'PROVEN_PATTERN',
|
|
137
|
+
};
|
|
138
|
+
for (const line of lines) {
|
|
139
|
+
// Detect section headers
|
|
140
|
+
const headerMatch = line.match(/^## .+ (.+)$/);
|
|
141
|
+
if (headerMatch) {
|
|
142
|
+
const typeName = headerMatch[1].trim();
|
|
143
|
+
if (typeMap[typeName])
|
|
144
|
+
currentType = typeMap[typeName];
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
// Only process bullet lines
|
|
148
|
+
if (!line.startsWith('- '))
|
|
149
|
+
continue;
|
|
150
|
+
// Extract intent (before the reason/age markers)
|
|
151
|
+
let intent = line.slice(2).trim();
|
|
152
|
+
intent = intent.replace(/\s*—\s*_.+?_\s*/g, '').replace(/\s*\(_\d+[dhm]\s+ago_\)\s*/g, '').trim();
|
|
153
|
+
if (intent.length < 10)
|
|
154
|
+
continue;
|
|
155
|
+
// Check if already exists
|
|
156
|
+
const existing = memoryStore.searchFTS(intent.slice(0, 50), 3);
|
|
157
|
+
const isDuplicate = existing.some(e => e.memory.intent.toLowerCase().includes(intent.toLowerCase().slice(0, 30)));
|
|
158
|
+
if (!isDuplicate) {
|
|
159
|
+
try {
|
|
160
|
+
memoryStore.add({
|
|
161
|
+
type: currentType,
|
|
162
|
+
intent: intent.slice(0, 300),
|
|
163
|
+
action: `Imported from MEMORY.md`,
|
|
164
|
+
importance: 0.8,
|
|
165
|
+
confidence: 0.9,
|
|
166
|
+
});
|
|
167
|
+
imported++;
|
|
168
|
+
}
|
|
169
|
+
catch { /* duplicate or quality gate */ }
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
catch { /* file not found or parse error */ }
|
|
174
|
+
return imported;
|
|
175
|
+
}
|
|
176
|
+
// ─── Helpers ──────────────────────────────────────────────────────────────────
|
|
177
|
+
function formatAge(timestamp) {
|
|
178
|
+
const diff = Date.now() - timestamp;
|
|
179
|
+
const mins = Math.floor(diff / 60000);
|
|
180
|
+
if (mins < 60)
|
|
181
|
+
return `${mins}m ago`;
|
|
182
|
+
const hours = Math.floor(mins / 60);
|
|
183
|
+
if (hours < 24)
|
|
184
|
+
return `${hours}h ago`;
|
|
185
|
+
const days = Math.floor(hours / 24);
|
|
186
|
+
return `${days}d ago`;
|
|
187
|
+
}
|
|
188
|
+
//# sourceMappingURL=memory-export-md.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-export-md.js","sourceRoot":"","sources":["../../src/memory/memory-export-md.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory-ranker.d.ts","sourceRoot":"","sources":["../../src/memory/memory-ranker.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"memory-ranker.d.ts","sourceRoot":"","sources":["../../src/memory/memory-ranker.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAE7C,MAAM,WAAW,YAAY;IACzB,MAAM,EAAE,GAAG,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,wBAAgB,WAAW,CACvB,UAAU,EAAE,YAAY,EAAE,EAC1B,aAAa,EAAE,YAAY,EAAE,EAC7B,UAAU,EAAE,MAAM,EAClB,WAAW,CAAC,EAAE,MAAM,GACrB,YAAY,EAAE,CA4DhB;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,YAAY,EAAE,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAQ/E"}
|
|
@@ -10,6 +10,7 @@ exports.formatResults = formatResults;
|
|
|
10
10
|
* NEW: File-aware ranking — if query mentions a file, related memories boost.
|
|
11
11
|
*/
|
|
12
12
|
const config_1 = require("../config/config");
|
|
13
|
+
const access_pattern_tracker_1 = require("./access-pattern-tracker");
|
|
13
14
|
/**
|
|
14
15
|
* Merge FTS + Vector results, deduplicate, boost by type + recency + access.
|
|
15
16
|
*/
|
|
@@ -31,9 +32,11 @@ function rankResults(ftsResults, vectorResults, maxResults, currentFile) {
|
|
|
31
32
|
const fileBoost = currentFile && r.memory.relatedFiles?.some((f) => f.includes(currentFile) || currentFile.includes(f)) ? 1.5 : 1.0;
|
|
32
33
|
// NEW: Resolved penalty — completed/resolved memories score much lower
|
|
33
34
|
const resolvedPenalty = r.memory.tags?.includes('resolved') ? 0.15 : 1.0;
|
|
35
|
+
// NEW: Personal boost — types the user accesses most get 1.0-1.8x
|
|
36
|
+
const personalBoost = (0, access_pattern_tracker_1.getPersonalBoost)(r.memory.type);
|
|
34
37
|
merged.push({
|
|
35
38
|
memory: r.memory,
|
|
36
|
-
score: r.score * boost * accessBoost * recencyBoost * fileBoost * resolvedPenalty,
|
|
39
|
+
score: r.score * boost * accessBoost * recencyBoost * fileBoost * resolvedPenalty * personalBoost,
|
|
37
40
|
});
|
|
38
41
|
}
|
|
39
42
|
for (const r of vectorResults) {
|
|
@@ -47,9 +50,11 @@ function rankResults(ftsResults, vectorResults, maxResults, currentFile) {
|
|
|
47
50
|
const fileBoost = currentFile && r.memory.relatedFiles?.some((f) => f.includes(currentFile) || currentFile.includes(f)) ? 1.5 : 1.0;
|
|
48
51
|
// Resolved penalty (same as FTS block)
|
|
49
52
|
const resolvedPenalty = r.memory.tags?.includes('resolved') ? 0.15 : 1.0;
|
|
53
|
+
// Personal boost (same as FTS block)
|
|
54
|
+
const personalBoost = (0, access_pattern_tracker_1.getPersonalBoost)(r.memory.type);
|
|
50
55
|
merged.push({
|
|
51
56
|
memory: r.memory,
|
|
52
|
-
score: r.score * boost * accessBoost * recencyBoost * fileBoost * resolvedPenalty,
|
|
57
|
+
score: r.score * boost * accessBoost * recencyBoost * fileBoost * resolvedPenalty * personalBoost,
|
|
53
58
|
});
|
|
54
59
|
}
|
|
55
60
|
merged.sort((a, b) => b.score - a.score);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory-ranker.js","sourceRoot":"","sources":["../../src/memory/memory-ranker.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"memory-ranker.js","sourceRoot":"","sources":["../../src/memory/memory-ranker.ts"],"names":[],"mappings":"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"}
|
|
@@ -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"}
|