openclaw-cortex-memory 0.1.0-Alpha.9 → 0.1.1
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/LICENSE +21 -0
- package/README.md +347 -290
- package/SIGNATURE.md +7 -0
- package/SKILL.md +96 -345
- package/dist/index.d.ts +69 -23
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1130 -1330
- package/dist/index.js.map +1 -1
- package/dist/openclaw.plugin.json +397 -18
- package/dist/src/dedup/three_stage_deduplicator.d.ts.map +1 -1
- package/dist/src/dedup/three_stage_deduplicator.js +13 -3
- package/dist/src/dedup/three_stage_deduplicator.js.map +1 -1
- package/dist/src/engine/memory_engine.d.ts +5 -1
- package/dist/src/engine/memory_engine.d.ts.map +1 -1
- package/dist/src/engine/ts_engine.d.ts +149 -0
- package/dist/src/engine/ts_engine.d.ts.map +1 -1
- package/dist/src/engine/ts_engine.js +863 -203
- package/dist/src/engine/ts_engine.js.map +1 -1
- package/dist/src/engine/types.d.ts +20 -0
- package/dist/src/engine/types.d.ts.map +1 -1
- package/dist/src/graph/ontology.d.ts +87 -15
- package/dist/src/graph/ontology.d.ts.map +1 -1
- package/dist/src/graph/ontology.js +999 -12
- package/dist/src/graph/ontology.js.map +1 -1
- package/dist/src/net/http_post.d.ts +17 -0
- package/dist/src/net/http_post.d.ts.map +1 -0
- package/dist/src/net/http_post.js +56 -0
- package/dist/src/net/http_post.js.map +1 -0
- package/dist/src/quality/llm_output_validator.d.ts +65 -0
- package/dist/src/quality/llm_output_validator.d.ts.map +1 -0
- package/dist/src/quality/llm_output_validator.js +635 -0
- package/dist/src/quality/llm_output_validator.js.map +1 -0
- package/dist/src/reflect/reflector.d.ts.map +1 -1
- package/dist/src/reflect/reflector.js +296 -26
- package/dist/src/reflect/reflector.js.map +1 -1
- package/dist/src/rules/rule_store.d.ts.map +1 -1
- package/dist/src/rules/rule_store.js +75 -16
- package/dist/src/rules/rule_store.js.map +1 -1
- package/dist/src/session/session_end.d.ts +20 -42
- package/dist/src/session/session_end.d.ts.map +1 -1
- package/dist/src/session/session_end.js +21 -218
- package/dist/src/session/session_end.js.map +1 -1
- package/dist/src/store/archive_store.d.ts +28 -7
- package/dist/src/store/archive_store.d.ts.map +1 -1
- package/dist/src/store/archive_store.js +367 -130
- package/dist/src/store/archive_store.js.map +1 -1
- package/dist/src/store/graph_memory_store.d.ts +115 -0
- package/dist/src/store/graph_memory_store.d.ts.map +1 -0
- package/dist/src/store/graph_memory_store.js +1061 -0
- package/dist/src/store/graph_memory_store.js.map +1 -0
- package/dist/src/store/read_store.d.ts +75 -0
- package/dist/src/store/read_store.d.ts.map +1 -1
- package/dist/src/store/read_store.js +1837 -312
- package/dist/src/store/read_store.js.map +1 -1
- package/dist/src/store/vector_store.d.ts +2 -0
- package/dist/src/store/vector_store.d.ts.map +1 -1
- package/dist/src/store/vector_store.js +19 -3
- package/dist/src/store/vector_store.js.map +1 -1
- package/dist/src/store/write_store.d.ts +11 -0
- package/dist/src/store/write_store.d.ts.map +1 -1
- package/dist/src/store/write_store.js +242 -42
- package/dist/src/store/write_store.js.map +1 -1
- package/dist/src/sync/session_sync.d.ts +72 -1
- package/dist/src/sync/session_sync.d.ts.map +1 -1
- package/dist/src/sync/session_sync.js +2246 -126
- package/dist/src/sync/session_sync.js.map +1 -1
- package/dist/src/wiki/wiki_linter.d.ts +26 -0
- package/dist/src/wiki/wiki_linter.d.ts.map +1 -0
- package/dist/src/wiki/wiki_linter.js +339 -0
- package/dist/src/wiki/wiki_linter.js.map +1 -0
- package/dist/src/wiki/wiki_logger.d.ts +10 -0
- package/dist/src/wiki/wiki_logger.d.ts.map +1 -0
- package/dist/src/wiki/wiki_logger.js +78 -0
- package/dist/src/wiki/wiki_logger.js.map +1 -0
- package/dist/src/wiki/wiki_maintainer.d.ts +39 -0
- package/dist/src/wiki/wiki_maintainer.d.ts.map +1 -0
- package/dist/src/wiki/wiki_maintainer.js +38 -0
- package/dist/src/wiki/wiki_maintainer.js.map +1 -0
- package/dist/src/wiki/wiki_projector.d.ts +35 -0
- package/dist/src/wiki/wiki_projector.d.ts.map +1 -0
- package/dist/src/wiki/wiki_projector.js +1151 -0
- package/dist/src/wiki/wiki_projector.js.map +1 -0
- package/dist/src/wiki/wiki_queue.d.ts +29 -0
- package/dist/src/wiki/wiki_queue.d.ts.map +1 -0
- package/dist/src/wiki/wiki_queue.js +137 -0
- package/dist/src/wiki/wiki_queue.js.map +1 -0
- package/openclaw.plugin.json +397 -18
- package/package.json +51 -5
- package/schema/graph.schema.yaml +330 -0
- package/scripts/cli.js +67 -13
- package/scripts/repair-memory.js +321 -0
- package/skills/cortex-memory/SKILL.md +83 -0
- package/skills/cortex-memory/references/agent-manual.md +127 -0
- package/skills/cortex-memory/references/configuration.md +109 -0
- package/skills/cortex-memory/references/publish-checklist.md +45 -0
- package/skills/cortex-memory/references/system-prompt-template.md +27 -0
- package/skills/cortex-memory/references/tools.md +191 -0
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
|
|
6
|
+
const args = process.argv.slice(2);
|
|
7
|
+
const isDryRun = args.includes('--dry-run');
|
|
8
|
+
const isFix = args.includes('--fix');
|
|
9
|
+
const targetArg = args.find(a => a.startsWith('--target='));
|
|
10
|
+
const target = targetArg ? targetArg.split('=')[1] : 'all';
|
|
11
|
+
|
|
12
|
+
const PROJECT_ROOT = process.cwd();
|
|
13
|
+
const MEMORY_ROOT = path.join(PROJECT_ROOT, 'data', 'memory');
|
|
14
|
+
|
|
15
|
+
const VALID_TARGETS = ['all', 'archive', 'active', 'vector'];
|
|
16
|
+
|
|
17
|
+
function printUsage() {
|
|
18
|
+
console.log(`
|
|
19
|
+
Memory Data Repair Tool
|
|
20
|
+
|
|
21
|
+
Usage: node scripts/repair-memory.js [options]
|
|
22
|
+
|
|
23
|
+
Options:
|
|
24
|
+
--dry-run Scan and report issues without making changes
|
|
25
|
+
--fix Remove invalid records and create quarantine file
|
|
26
|
+
--target=<target> Specify target: all, archive, active, vector (default: all)
|
|
27
|
+
|
|
28
|
+
Examples:
|
|
29
|
+
node scripts/repair-memory.js --dry-run
|
|
30
|
+
node scripts/repair-memory.js --fix --target=archive
|
|
31
|
+
`);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (!VALID_TARGETS.includes(target)) {
|
|
35
|
+
console.error(`Invalid target: ${target}. Valid targets: ${VALID_TARGETS.join(', ')}`);
|
|
36
|
+
printUsage();
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (!isDryRun && !isFix) {
|
|
41
|
+
printUsage();
|
|
42
|
+
process.exit(0);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function validateJsonlLine(line, lineNumber) {
|
|
46
|
+
const errors = [];
|
|
47
|
+
if (!line || !line.trim()) {
|
|
48
|
+
return { valid: true, errors: [], record: null };
|
|
49
|
+
}
|
|
50
|
+
let record;
|
|
51
|
+
try {
|
|
52
|
+
record = JSON.parse(line);
|
|
53
|
+
} catch (e) {
|
|
54
|
+
errors.push(`JSON parse error: ${e.message}`);
|
|
55
|
+
return { valid: false, errors, record: null };
|
|
56
|
+
}
|
|
57
|
+
if (!record || typeof record !== 'object') {
|
|
58
|
+
errors.push('Record is not an object');
|
|
59
|
+
return { valid: false, errors, record: null };
|
|
60
|
+
}
|
|
61
|
+
if (typeof record.id !== 'string' || !record.id.trim()) {
|
|
62
|
+
errors.push('Missing or invalid id field');
|
|
63
|
+
}
|
|
64
|
+
if (typeof record.timestamp !== 'string' || !record.timestamp.trim()) {
|
|
65
|
+
errors.push('Missing or invalid timestamp field');
|
|
66
|
+
}
|
|
67
|
+
if (record.layer !== 'active' && record.layer !== 'archive') {
|
|
68
|
+
errors.push('Missing or invalid layer field');
|
|
69
|
+
}
|
|
70
|
+
const anomalyPatterns = [
|
|
71
|
+
/\d+\.\d+,\s*"[^"]+"/,
|
|
72
|
+
/"[^"]+"\s+\d+\.\d+/,
|
|
73
|
+
/,\s*\d+\.\d+,/,
|
|
74
|
+
/"\w+\.\w+\.\w+"/,
|
|
75
|
+
/\d+\.\w+\.\d+/,
|
|
76
|
+
];
|
|
77
|
+
const lineStr = JSON.stringify(record);
|
|
78
|
+
for (const pattern of anomalyPatterns) {
|
|
79
|
+
if (pattern.test(lineStr)) {
|
|
80
|
+
errors.push('Anomaly pattern detected in record');
|
|
81
|
+
break;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return { valid: errors.length === 0, errors, record };
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function scanJsonlFile(filePath) {
|
|
88
|
+
const results = {
|
|
89
|
+
path: filePath,
|
|
90
|
+
exists: false,
|
|
91
|
+
totalLines: 0,
|
|
92
|
+
validLines: 0,
|
|
93
|
+
invalidLines: 0,
|
|
94
|
+
emptyLines: 0,
|
|
95
|
+
issues: [],
|
|
96
|
+
};
|
|
97
|
+
if (!fs.existsSync(filePath)) {
|
|
98
|
+
return results;
|
|
99
|
+
}
|
|
100
|
+
results.exists = true;
|
|
101
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
102
|
+
const lines = content.split(/\r?\n/);
|
|
103
|
+
for (let i = 0; i < lines.length; i++) {
|
|
104
|
+
const line = lines[i];
|
|
105
|
+
if (!line.trim()) {
|
|
106
|
+
results.emptyLines++;
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
results.totalLines++;
|
|
110
|
+
const validation = validateJsonlLine(line, i + 1);
|
|
111
|
+
if (validation.valid) {
|
|
112
|
+
results.validLines++;
|
|
113
|
+
} else {
|
|
114
|
+
results.invalidLines++;
|
|
115
|
+
results.issues.push({
|
|
116
|
+
lineNumber: i + 1,
|
|
117
|
+
errors: validation.errors,
|
|
118
|
+
preview: line.slice(0, 100) + (line.length > 100 ? '...' : ''),
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return results;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function repairJsonlFile(filePath, dryRun) {
|
|
126
|
+
const results = {
|
|
127
|
+
path: filePath,
|
|
128
|
+
exists: false,
|
|
129
|
+
totalLines: 0,
|
|
130
|
+
validLines: 0,
|
|
131
|
+
removedLines: 0,
|
|
132
|
+
quarantineLines: [],
|
|
133
|
+
};
|
|
134
|
+
if (!fs.existsSync(filePath)) {
|
|
135
|
+
return results;
|
|
136
|
+
}
|
|
137
|
+
results.exists = true;
|
|
138
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
139
|
+
const lines = content.split(/\r?\n/);
|
|
140
|
+
const validRecords = [];
|
|
141
|
+
for (let i = 0; i < lines.length; i++) {
|
|
142
|
+
const line = lines[i];
|
|
143
|
+
if (!line.trim()) {
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
results.totalLines++;
|
|
147
|
+
const validation = validateJsonlLine(line, i + 1);
|
|
148
|
+
if (validation.valid) {
|
|
149
|
+
results.validLines++;
|
|
150
|
+
validRecords.push(line);
|
|
151
|
+
} else {
|
|
152
|
+
results.removedLines++;
|
|
153
|
+
results.quarantineLines.push({
|
|
154
|
+
lineNumber: i + 1,
|
|
155
|
+
content: line,
|
|
156
|
+
errors: validation.errors,
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
if (!dryRun && results.removedLines > 0) {
|
|
161
|
+
const newContent = validRecords.join('\n') + (validRecords.length > 0 ? '\n' : '');
|
|
162
|
+
fs.writeFileSync(filePath, newContent, 'utf-8');
|
|
163
|
+
const quarantinePath = filePath + '.quarantine.jsonl';
|
|
164
|
+
const quarantineContent = results.quarantineLines.map(q =>
|
|
165
|
+
JSON.stringify({ lineNumber: q.lineNumber, errors: q.errors, content: q.content })
|
|
166
|
+
).join('\n');
|
|
167
|
+
fs.writeFileSync(quarantinePath, quarantineContent + '\n', 'utf-8');
|
|
168
|
+
}
|
|
169
|
+
return results;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function scanVectorFallback(filePath) {
|
|
173
|
+
const results = {
|
|
174
|
+
path: filePath,
|
|
175
|
+
exists: false,
|
|
176
|
+
totalRecords: 0,
|
|
177
|
+
validRecords: 0,
|
|
178
|
+
orphanRecords: 0,
|
|
179
|
+
issues: [],
|
|
180
|
+
};
|
|
181
|
+
if (!fs.existsSync(filePath)) {
|
|
182
|
+
return results;
|
|
183
|
+
}
|
|
184
|
+
results.exists = true;
|
|
185
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
186
|
+
const lines = content.split(/\r?\n/);
|
|
187
|
+
for (let i = 0; i < lines.length; i++) {
|
|
188
|
+
const line = lines[i];
|
|
189
|
+
if (!line.trim()) continue;
|
|
190
|
+
results.totalRecords++;
|
|
191
|
+
try {
|
|
192
|
+
const record = JSON.parse(line);
|
|
193
|
+
if (!record.id || !record.embedding) {
|
|
194
|
+
results.issues.push({
|
|
195
|
+
lineNumber: i + 1,
|
|
196
|
+
error: 'Missing id or embedding',
|
|
197
|
+
});
|
|
198
|
+
} else {
|
|
199
|
+
results.validRecords++;
|
|
200
|
+
}
|
|
201
|
+
} catch (e) {
|
|
202
|
+
results.issues.push({
|
|
203
|
+
lineNumber: i + 1,
|
|
204
|
+
error: `JSON parse error: ${e.message}`,
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
return results;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
console.log('='.repeat(60));
|
|
212
|
+
console.log('Memory Data Repair Tool');
|
|
213
|
+
console.log('='.repeat(60));
|
|
214
|
+
console.log(`Mode: ${isDryRun ? 'DRY RUN (no changes)' : 'FIX (will modify files)'}`);
|
|
215
|
+
console.log(`Target: ${target}`);
|
|
216
|
+
console.log(`Memory Root: ${MEMORY_ROOT}`);
|
|
217
|
+
console.log('='.repeat(60));
|
|
218
|
+
|
|
219
|
+
const archivePath = path.join(MEMORY_ROOT, 'sessions', 'archive', 'archive.jsonl');
|
|
220
|
+
const activePath = path.join(MEMORY_ROOT, 'sessions', 'active', 'sessions.jsonl');
|
|
221
|
+
const vectorFallbackPath = path.join(MEMORY_ROOT, 'vector', 'lancedb_events.jsonl');
|
|
222
|
+
|
|
223
|
+
let totalIssues = 0;
|
|
224
|
+
const report = {
|
|
225
|
+
archive: null,
|
|
226
|
+
active: null,
|
|
227
|
+
vector: null,
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
if (target === 'all' || target === 'archive') {
|
|
231
|
+
console.log('\n[Archive Layer]');
|
|
232
|
+
if (isDryRun) {
|
|
233
|
+
report.archive = scanJsonlFile(archivePath);
|
|
234
|
+
} else {
|
|
235
|
+
report.archive = repairJsonlFile(archivePath, false);
|
|
236
|
+
}
|
|
237
|
+
if (!report.archive.exists) {
|
|
238
|
+
console.log(' File does not exist');
|
|
239
|
+
} else {
|
|
240
|
+
console.log(` Total lines: ${report.archive.totalLines}`);
|
|
241
|
+
console.log(` Valid lines: ${report.archive.validLines}`);
|
|
242
|
+
console.log(` Invalid lines: ${report.archive.invalidLines || report.archive.removedLines}`);
|
|
243
|
+
if (report.archive.issues && report.archive.issues.length > 0) {
|
|
244
|
+
console.log(' Issues found:');
|
|
245
|
+
report.archive.issues.slice(0, 5).forEach(issue => {
|
|
246
|
+
console.log(` Line ${issue.lineNumber}: ${issue.errors.join(', ')}`);
|
|
247
|
+
});
|
|
248
|
+
if (report.archive.issues.length > 5) {
|
|
249
|
+
console.log(` ... and ${report.archive.issues.length - 5} more`);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
totalIssues += report.archive.invalidLines || report.archive.removedLines || 0;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
if (target === 'all' || target === 'active') {
|
|
257
|
+
console.log('\n[Active Layer]');
|
|
258
|
+
if (isDryRun) {
|
|
259
|
+
report.active = scanJsonlFile(activePath);
|
|
260
|
+
} else {
|
|
261
|
+
report.active = repairJsonlFile(activePath, false);
|
|
262
|
+
}
|
|
263
|
+
if (!report.active.exists) {
|
|
264
|
+
console.log(' File does not exist');
|
|
265
|
+
} else {
|
|
266
|
+
console.log(` Total lines: ${report.active.totalLines}`);
|
|
267
|
+
console.log(` Valid lines: ${report.active.validLines}`);
|
|
268
|
+
console.log(` Invalid lines: ${report.active.invalidLines || report.active.removedLines}`);
|
|
269
|
+
if (report.active.issues && report.active.issues.length > 0) {
|
|
270
|
+
console.log(' Issues found:');
|
|
271
|
+
report.active.issues.slice(0, 5).forEach(issue => {
|
|
272
|
+
console.log(` Line ${issue.lineNumber}: ${issue.errors.join(', ')}`);
|
|
273
|
+
});
|
|
274
|
+
if (report.active.issues.length > 5) {
|
|
275
|
+
console.log(` ... and ${report.active.issues.length - 5} more`);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
totalIssues += report.active.invalidLines || report.active.removedLines || 0;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
if (target === 'all' || target === 'vector') {
|
|
283
|
+
console.log('\n[Vector Fallback]');
|
|
284
|
+
report.vector = scanVectorFallback(vectorFallbackPath);
|
|
285
|
+
if (!report.vector.exists) {
|
|
286
|
+
console.log(' File does not exist');
|
|
287
|
+
} else {
|
|
288
|
+
console.log(` Total records: ${report.vector.totalRecords}`);
|
|
289
|
+
console.log(` Valid records: ${report.vector.validRecords}`);
|
|
290
|
+
console.log(` Issues: ${report.vector.issues.length}`);
|
|
291
|
+
if (report.vector.issues.length > 0) {
|
|
292
|
+
console.log(' Issues found:');
|
|
293
|
+
report.vector.issues.slice(0, 5).forEach(issue => {
|
|
294
|
+
console.log(` Line ${issue.lineNumber}: ${issue.error}`);
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
totalIssues += report.vector.issues.length;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
console.log('\n' + '='.repeat(60));
|
|
302
|
+
console.log('Summary');
|
|
303
|
+
console.log('='.repeat(60));
|
|
304
|
+
console.log(`Total issues found: ${totalIssues}`);
|
|
305
|
+
|
|
306
|
+
if (isDryRun) {
|
|
307
|
+
if (totalIssues > 0) {
|
|
308
|
+
console.log('\nRun with --fix to repair these issues.');
|
|
309
|
+
} else {
|
|
310
|
+
console.log('\nNo issues found. Memory data is healthy.');
|
|
311
|
+
}
|
|
312
|
+
} else {
|
|
313
|
+
if (totalIssues > 0) {
|
|
314
|
+
console.log('\nRepair completed. Invalid records have been quarantined.');
|
|
315
|
+
console.log('Check .quarantine.jsonl files for removed records.');
|
|
316
|
+
} else {
|
|
317
|
+
console.log('\nNo repairs needed. Memory data is healthy.');
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
process.exit(totalIssues > 0 && isDryRun ? 1 : 0);
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Openclaw Cortex Memory
|
|
2
|
+
|
|
3
|
+
OpenClaw 长期记忆插件,专为 OpenClaw AI 助手设计的智能记忆系统。
|
|
4
|
+
|
|
5
|
+
面向 OpenClaw 的长期记忆插件,集成多路检索、事件归档、图谱关系、向量化与反衰减排序,支持历史增量导入、规则反思和可观测诊断,可以将会话中零碎的记忆去噪整理、分层存储,支持对话中自动搜索回忆,吸收了 LLM wiki 的概念,帮助 Agent 在跨会话中持续积累并稳定调用高价值记忆。
|
|
6
|
+
|
|
7
|
+
## 核心能力
|
|
8
|
+
|
|
9
|
+
### 1) 语义检索
|
|
10
|
+
- 多路召回:`keyword / BM25 / vector / graph` 混合检索
|
|
11
|
+
- 排序融合:加权打分 + RRF + 可选 reranker
|
|
12
|
+
- 结果融合:可选 `readFusion`,支持权威融合返回
|
|
13
|
+
- 时序建模:`memoryDecay` + 命中反衰减(anti-decay)
|
|
14
|
+
|
|
15
|
+
### 2) 事件存储
|
|
16
|
+
- 分层写入:`active`(会话)与 `archive`(结构化事件)
|
|
17
|
+
- 摘要优先:归档记录保留 `summary` 与 `source_text`
|
|
18
|
+
- 向量分块:支持 summary/evidence 双通道向量记录
|
|
19
|
+
- 增量同步:按状态文件增量导入历史会话
|
|
20
|
+
|
|
21
|
+
### 3) 图谱关系
|
|
22
|
+
- 图谱独立层:`graph/memory.jsonl` 独立于 archive 文本层
|
|
23
|
+
- 关系追溯:每条关系可追溯 `source_event_id`
|
|
24
|
+
- 关系查询:`query_graph` 支持方向、关系类型、路径搜索
|
|
25
|
+
- 冲突治理:单值事实冲突进入队列,支持人工 `accept/reject` 闭环
|
|
26
|
+
- 可视化导出:`export_graph_view` 输出状态化图谱快照(含来源证据)
|
|
27
|
+
- 质量门禁:全局 `graphQualityMode` 支持 `off/warn/strict`;历史导入可用 `syncPolicy.graphQualityMode` 单独收紧
|
|
28
|
+
|
|
29
|
+
### 4) 规则演进
|
|
30
|
+
- 反思沉淀:`reflect_memory` 将事件抽象为规则
|
|
31
|
+
- 去重治理:规则与事件均有去重控制,避免污染
|
|
32
|
+
- 规则复用:规则写入 `CORTEX_RULES.md` 供后续任务复用
|
|
33
|
+
|
|
34
|
+
### 5) 运维诊断
|
|
35
|
+
- `cortex_diagnostics`:模型连通、层级状态、字段对齐检查
|
|
36
|
+
- `backfill_embeddings`:支持 `incremental / vector_only / full`
|
|
37
|
+
- `lint_memory_wiki`:Wiki/图谱一致性、证据完整性与知识页质量巡检
|
|
38
|
+
- 完整状态文件:便于快速定位同步、回填、质量问题
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
name: cortex-memory
|
|
42
|
+
description: Independent skill for Cortex Memory operations in OpenClaw. Use when users ask for cross-session memory continuity, prior decisions, preferences, relationship tracing, or memory maintenance. If the memory plugin is not installed, guide users to install and enable openclaw-cortex-memory first, then continue with normal memory workflows.
|
|
43
|
+
homepage: https://github.com/deki18/openclaw-cortex-memory
|
|
44
|
+
metadata: { "openclaw": { "os": ["darwin", "linux", "win32"], "primaryEnv": "EMBEDDING_API_KEY" } }
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
Use this runtime flow:
|
|
48
|
+
|
|
49
|
+
1. Check whether plugin `openclaw-cortex-memory` is available.
|
|
50
|
+
2. If missing or disabled, run the install bootstrap guide in `{baseDir}/references/agent-manual.md` with README-consistent install order.
|
|
51
|
+
3. After plugin is enabled, run memory retrieval or write operations.
|
|
52
|
+
|
|
53
|
+
After plugin is ready, use this default workflow:
|
|
54
|
+
|
|
55
|
+
1. Retrieve candidate memory with `search_memory`.
|
|
56
|
+
2. If the user asks about entity links or dependency paths, use `query_graph`.
|
|
57
|
+
3. If `query_graph` returns `conflict_hint`, use `list_graph_conflicts` and ask user confirmation before `resolve_graph_conflict`.
|
|
58
|
+
4. For graph status snapshots or projection consistency checks, use `export_graph_view` and `lint_memory_wiki`.
|
|
59
|
+
5. Answer with retrieved evidence first, then add reasoning.
|
|
60
|
+
6. If the turn introduces durable new information, persist it with `store_event`.
|
|
61
|
+
7. For maintenance windows or session wrap-up, run `sync_memory` and optionally `reflect_memory`.
|
|
62
|
+
|
|
63
|
+
If tool calls fail:
|
|
64
|
+
|
|
65
|
+
1. Check plugin availability first (`openclaw plugins list` / `openclaw plugins inspect openclaw-cortex-memory`).
|
|
66
|
+
2. If visible, run `cortex_diagnostics` (or legacy alias `diagnostics`).
|
|
67
|
+
3. Tell the user the plugin is unavailable or misconfigured.
|
|
68
|
+
4. Continue with a normal answer without fabricating memory hits.
|
|
69
|
+
|
|
70
|
+
Do not use this skill for:
|
|
71
|
+
|
|
72
|
+
- Real-time web facts (weather, stock, breaking news).
|
|
73
|
+
- One-off temporary context that should not be persisted.
|
|
74
|
+
|
|
75
|
+
Use these local references when needed:
|
|
76
|
+
|
|
77
|
+
- Install and bootstrap playbook: `{baseDir}/references/agent-manual.md`
|
|
78
|
+
- System prompt template: `{baseDir}/references/system-prompt-template.md`
|
|
79
|
+
- Tool details: `{baseDir}/references/tools.md`
|
|
80
|
+
- Config and dependency setup: `{baseDir}/references/configuration.md`
|
|
81
|
+
- Publish and validation checklist: `{baseDir}/references/publish-checklist.md`
|
|
82
|
+
|
|
83
|
+
For environment preflight, use `{baseDir}/references/publish-checklist.md`.
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# Cortex Memory Agent Manual
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
|
|
5
|
+
Use Cortex Memory as a long-term memory layer in OpenClaw. This manual is for agents operating from the independent `cortex-memory` skill folder.
|
|
6
|
+
|
|
7
|
+
## Phase 1: Plugin Availability Check
|
|
8
|
+
|
|
9
|
+
Run:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
openclaw plugins list
|
|
13
|
+
openclaw plugins inspect openclaw-cortex-memory
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
If plugin exists and is enabled, continue to Phase 3.
|
|
17
|
+
|
|
18
|
+
If plugin is missing or disabled, go to Phase 2.
|
|
19
|
+
|
|
20
|
+
## Phase 2: Install and Enable Plugin
|
|
21
|
+
|
|
22
|
+
Preferred install path (README default):
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
openclaw plugins install clawhub:openclaw-cortex-memory
|
|
26
|
+
openclaw plugins enable openclaw-cortex-memory
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Fallback install path:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npm pack openclaw-cortex-memory@0.1.0-Alpha.34
|
|
33
|
+
openclaw plugins install ./openclaw-cortex-memory-0.1.0-Alpha.34.tgz
|
|
34
|
+
openclaw plugins enable openclaw-cortex-memory
|
|
35
|
+
rm ./openclaw-cortex-memory-0.1.0-Alpha.34.tgz
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Then verify:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
openclaw plugins list
|
|
42
|
+
openclaw plugins inspect openclaw-cortex-memory
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
If config is not ready, apply the baseline from `configuration.md`.
|
|
46
|
+
|
|
47
|
+
Exclusive memory mode pre-install check (must be completed before running install commands, including `openclaw plugins install ./openclaw-cortex-memory-0.1.0-Alpha.34.tgz`):
|
|
48
|
+
|
|
49
|
+
- Before install, do not manually set `plugins.slots.memory` to `openclaw-cortex-memory`.
|
|
50
|
+
- Before install, disable `memory-core` and `memory-lancedb` under `plugins.entries` to avoid mixed backends.
|
|
51
|
+
- After install, the installer may set `plugins.slots.memory` to `openclaw-cortex-memory` automatically; this is expected.
|
|
52
|
+
|
|
53
|
+
If the user asks for "system prompt rules", use `{baseDir}/references/system-prompt-template.md`.
|
|
54
|
+
|
|
55
|
+
## Phase 3: Runtime Workflow
|
|
56
|
+
|
|
57
|
+
### Retrieval-first answers
|
|
58
|
+
|
|
59
|
+
1. `search_memory` with the user query.
|
|
60
|
+
2. `query_graph` when relationship/path reasoning is needed.
|
|
61
|
+
3. If `query_graph` returns `conflict_hint`, run `list_graph_conflicts` and confirm with user before `resolve_graph_conflict`.
|
|
62
|
+
4. Respond with evidence first, reasoning second.
|
|
63
|
+
|
|
64
|
+
For retrieval debugging, call `search_memory` with `fusion_mode: "candidates"` to keep ranked candidates alongside fusion output. For benchmarks or diagnostics, set `track_hits: false` so the read does not update anti-decay hit statistics.
|
|
65
|
+
|
|
66
|
+
Wiki pages are graph projections, not a second memory store. Treat `wiki_ref` / `wiki_refs` from `search_memory` or `query_graph` as display links; use graph/evidence ids as the fact source.
|
|
67
|
+
|
|
68
|
+
### Persistence
|
|
69
|
+
|
|
70
|
+
Use `store_event` only for durable information:
|
|
71
|
+
|
|
72
|
+
- stable preferences
|
|
73
|
+
- project decisions
|
|
74
|
+
- long-lived constraints
|
|
75
|
+
|
|
76
|
+
Avoid persisting ephemeral chatter.
|
|
77
|
+
|
|
78
|
+
### Maintenance
|
|
79
|
+
|
|
80
|
+
- `sync_memory` for historical import
|
|
81
|
+
- `reflect_memory` for rule extraction
|
|
82
|
+
- `backfill_embeddings` for vector repair
|
|
83
|
+
- `export_graph_view` for status-aware graph snapshots
|
|
84
|
+
- `lint_memory_wiki` for projection consistency checks
|
|
85
|
+
- `cortex_diagnostics` (or `diagnostics` alias) when anything looks inconsistent
|
|
86
|
+
|
|
87
|
+
## Failure Handling
|
|
88
|
+
|
|
89
|
+
If plugin tools are unavailable:
|
|
90
|
+
|
|
91
|
+
1. Run `openclaw plugins inspect openclaw-cortex-memory` and `openclaw plugins list`.
|
|
92
|
+
2. If `cortex_diagnostics` is visible, run it for detailed checks.
|
|
93
|
+
3. Explain the issue clearly (plugin disabled, config incomplete, endpoint unavailable, or API key missing).
|
|
94
|
+
4. Provide immediate next action with exact command.
|
|
95
|
+
|
|
96
|
+
If install or enable flow reports `memory-core` / `memory-lancedb` requirements, keep both disabled in `plugins.entries`.
|
|
97
|
+
If the host still requests a `memory-lancedb` schema block, add:
|
|
98
|
+
|
|
99
|
+
```json
|
|
100
|
+
"memory-lancedb": {
|
|
101
|
+
"enabled": false,
|
|
102
|
+
"config": {
|
|
103
|
+
"embedding": {
|
|
104
|
+
"apiKey": "${MEMORY_LANCEDB_API_KEY}",
|
|
105
|
+
"model": "text-embedding-3-small"
|
|
106
|
+
},
|
|
107
|
+
"dbPath": "~/.openclaw/memory/lancedb",
|
|
108
|
+
"autoRecall": true,
|
|
109
|
+
"autoCapture": false,
|
|
110
|
+
"captureMaxChars": 500
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Operator Commands Cheat Sheet
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
openclaw plugins install clawhub:openclaw-cortex-memory
|
|
119
|
+
openclaw plugins enable openclaw-cortex-memory
|
|
120
|
+
openclaw plugins inspect openclaw-cortex-memory
|
|
121
|
+
npm pack openclaw-cortex-memory@0.1.0-Alpha.34
|
|
122
|
+
openclaw plugins install ./openclaw-cortex-memory-0.1.0-Alpha.34.tgz
|
|
123
|
+
openclaw plugins enable openclaw-cortex-memory
|
|
124
|
+
rm ./openclaw-cortex-memory-0.1.0-Alpha.34.tgz
|
|
125
|
+
openclaw skills info cortex-memory
|
|
126
|
+
openclaw skills check
|
|
127
|
+
```
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# Configuration Reference
|
|
2
|
+
|
|
3
|
+
## Minimum OpenClaw Config
|
|
4
|
+
|
|
5
|
+
Use this as the baseline in `openclaw.json`.
|
|
6
|
+
|
|
7
|
+
```json
|
|
8
|
+
{
|
|
9
|
+
"plugins": {
|
|
10
|
+
"allow": ["openclaw-cortex-memory"],
|
|
11
|
+
"slots": {
|
|
12
|
+
"memory": "none"
|
|
13
|
+
},
|
|
14
|
+
"entries": {
|
|
15
|
+
"memory-core": {
|
|
16
|
+
"enabled": false
|
|
17
|
+
},
|
|
18
|
+
"memory-lancedb": {
|
|
19
|
+
"enabled": false
|
|
20
|
+
},
|
|
21
|
+
"openclaw-cortex-memory": {
|
|
22
|
+
"enabled": true,
|
|
23
|
+
"config": {
|
|
24
|
+
"autoSync": true,
|
|
25
|
+
"autoReflect": false,
|
|
26
|
+
"graphQualityMode": "warn",
|
|
27
|
+
"syncPolicy": {
|
|
28
|
+
"includeLocalActiveInput": false,
|
|
29
|
+
"graphQualityMode": "strict"
|
|
30
|
+
},
|
|
31
|
+
"wikiProjection": {
|
|
32
|
+
"enabled": true,
|
|
33
|
+
"mode": "incremental",
|
|
34
|
+
"maxBatch": 100
|
|
35
|
+
},
|
|
36
|
+
"embedding": {
|
|
37
|
+
"provider": "api",
|
|
38
|
+
"model": "text-embedding-3-small",
|
|
39
|
+
"apiKey": "${EMBEDDING_API_KEY}",
|
|
40
|
+
"baseURL": "https://your-embedding-endpoint/v1",
|
|
41
|
+
"dimensions": 1536
|
|
42
|
+
},
|
|
43
|
+
"llm": {
|
|
44
|
+
"provider": "api",
|
|
45
|
+
"model": "gpt-4",
|
|
46
|
+
"apiKey": "${LLM_API_KEY}",
|
|
47
|
+
"baseURL": "https://your-llm-endpoint/v1"
|
|
48
|
+
},
|
|
49
|
+
"reranker": {
|
|
50
|
+
"provider": "api",
|
|
51
|
+
"model": "BAAI/bge-reranker-v2-m3",
|
|
52
|
+
"apiKey": "${RERANKER_API_KEY}",
|
|
53
|
+
"baseURL": "https://your-reranker-endpoint/v1/rerank"
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Exclusive Mode Rules
|
|
63
|
+
|
|
64
|
+
- Do not set `plugins.slots.memory` to `openclaw-cortex-memory`.
|
|
65
|
+
- Keep `plugins.entries.memory-core.enabled = false`.
|
|
66
|
+
- Keep `plugins.entries.memory-lancedb.enabled = false`.
|
|
67
|
+
|
|
68
|
+
## Required Environment Variables
|
|
69
|
+
|
|
70
|
+
- `EMBEDDING_API_KEY`
|
|
71
|
+
- `LLM_API_KEY`
|
|
72
|
+
- `RERANKER_API_KEY`
|
|
73
|
+
|
|
74
|
+
## Required Endpoints
|
|
75
|
+
|
|
76
|
+
- Embedding: OpenAI-compatible `/embeddings`
|
|
77
|
+
- LLM: OpenAI-compatible `/chat/completions`
|
|
78
|
+
- Reranker: `/rerank`
|
|
79
|
+
|
|
80
|
+
## Troubleshooting: memory backend requirement
|
|
81
|
+
|
|
82
|
+
If `openclaw plugins install/enable` reports `memory-core` or `memory-lancedb` requirement errors, keep both disabled under `plugins.entries`.
|
|
83
|
+
If your host still requires a `memory-lancedb` shape check even when disabled, use:
|
|
84
|
+
|
|
85
|
+
```json
|
|
86
|
+
"memory-lancedb": {
|
|
87
|
+
"enabled": false,
|
|
88
|
+
"config": {
|
|
89
|
+
"embedding": {
|
|
90
|
+
"apiKey": "${MEMORY_LANCEDB_API_KEY}",
|
|
91
|
+
"model": "text-embedding-3-small"
|
|
92
|
+
},
|
|
93
|
+
"dbPath": "~/.openclaw/memory/lancedb",
|
|
94
|
+
"autoRecall": true,
|
|
95
|
+
"autoCapture": false,
|
|
96
|
+
"captureMaxChars": 500
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Recommended Validation Commands
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
openclaw plugins list
|
|
105
|
+
openclaw plugins inspect openclaw-cortex-memory
|
|
106
|
+
openclaw skills list
|
|
107
|
+
openclaw skills info cortex-memory
|
|
108
|
+
openclaw skills check
|
|
109
|
+
```
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# ClawHub Publish Checklist
|
|
2
|
+
|
|
3
|
+
## Preflight
|
|
4
|
+
|
|
5
|
+
1. Confirm skill root contains `SKILL.md`.
|
|
6
|
+
2. Confirm frontmatter includes:
|
|
7
|
+
- `name`
|
|
8
|
+
- `description`
|
|
9
|
+
3. Confirm no secret values are hardcoded in skill files.
|
|
10
|
+
|
|
11
|
+
## Local Validation
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
openclaw skills list
|
|
15
|
+
openclaw skills info cortex-memory
|
|
16
|
+
openclaw skills check
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Optional plugin validation:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
openclaw plugins list
|
|
23
|
+
openclaw plugins inspect openclaw-cortex-memory
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Publish
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
clawhub login
|
|
30
|
+
clawhub whoami
|
|
31
|
+
clawhub publish ./skills/cortex-memory --slug cortex-memory --name "Cortex Memory" --version 0.1.0 --changelog "Initial ClawHub release" --tags latest
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Install Test (Clean Workspace)
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
openclaw skills install cortex-memory
|
|
38
|
+
openclaw skills info cortex-memory
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Post Publish
|
|
42
|
+
|
|
43
|
+
1. Start a new session.
|
|
44
|
+
2. Trigger retrieval workflow with a memory-related prompt.
|
|
45
|
+
3. Verify skill appears and is eligible in `openclaw skills list --eligible`.
|