openclaw-cortex-memory 0.1.0-Alpha.3 → 0.1.0-Alpha.31
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 +296 -203
- package/SIGNATURE.md +7 -0
- package/SKILL.md +92 -268
- package/dist/index.d.ts +100 -22
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1249 -1252
- package/dist/index.js.map +1 -1
- package/dist/openclaw.plugin.json +501 -16
- package/dist/src/dedup/three_stage_deduplicator.d.ts +25 -0
- package/dist/src/dedup/three_stage_deduplicator.d.ts.map +1 -0
- package/dist/src/dedup/three_stage_deduplicator.js +224 -0
- package/dist/src/dedup/three_stage_deduplicator.js.map +1 -0
- package/dist/src/engine/memory_engine.d.ts +6 -1
- package/dist/src/engine/memory_engine.d.ts.map +1 -1
- package/dist/src/engine/ts_engine.d.ts +242 -0
- package/dist/src/engine/ts_engine.d.ts.map +1 -1
- package/dist/src/engine/ts_engine.js +1468 -52
- package/dist/src/engine/ts_engine.js.map +1 -1
- package/dist/src/engine/types.d.ts +29 -0
- package/dist/src/engine/types.d.ts.map +1 -1
- package/dist/src/graph/ontology.d.ts +125 -0
- package/dist/src/graph/ontology.d.ts.map +1 -0
- package/dist/src/graph/ontology.js +1237 -0
- package/dist/src/graph/ontology.js.map +1 -0
- 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 +66 -0
- package/dist/src/quality/llm_output_validator.d.ts.map +1 -0
- package/dist/src/quality/llm_output_validator.js +659 -0
- package/dist/src/quality/llm_output_validator.js.map +1 -0
- package/dist/src/reflect/reflector.d.ts +7 -0
- package/dist/src/reflect/reflector.d.ts.map +1 -1
- package/dist/src/reflect/reflector.js +352 -8
- 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 +33 -0
- package/dist/src/session/session_end.d.ts.map +1 -1
- package/dist/src/session/session_end.js +67 -64
- package/dist/src/session/session_end.js.map +1 -1
- package/dist/src/store/archive_store.d.ts +136 -0
- package/dist/src/store/archive_store.d.ts.map +1 -0
- package/dist/src/store/archive_store.js +635 -0
- package/dist/src/store/archive_store.js.map +1 -0
- package/dist/src/store/embedding_utils.d.ts +32 -0
- package/dist/src/store/embedding_utils.d.ts.map +1 -0
- package/dist/src/store/embedding_utils.js +173 -0
- package/dist/src/store/embedding_utils.js.map +1 -0
- package/dist/src/store/graph_memory_store.d.ts +114 -0
- package/dist/src/store/graph_memory_store.d.ts.map +1 -0
- package/dist/src/store/graph_memory_store.js +841 -0
- package/dist/src/store/graph_memory_store.js.map +1 -0
- package/dist/src/store/read_store.d.ts +89 -0
- package/dist/src/store/read_store.d.ts.map +1 -1
- package/dist/src/store/read_store.js +2459 -28
- package/dist/src/store/read_store.js.map +1 -1
- package/dist/src/store/vector_store.d.ts +45 -0
- package/dist/src/store/vector_store.d.ts.map +1 -0
- package/dist/src/store/vector_store.js +202 -0
- package/dist/src/store/vector_store.js.map +1 -0
- package/dist/src/store/write_store.d.ts +54 -0
- package/dist/src/store/write_store.d.ts.map +1 -1
- package/dist/src/store/write_store.js +284 -6
- package/dist/src/store/write_store.js.map +1 -1
- package/dist/src/sync/session_sync.d.ts +119 -2
- package/dist/src/sync/session_sync.d.ts.map +1 -1
- package/dist/src/sync/session_sync.js +2377 -31
- package/dist/src/sync/session_sync.js.map +1 -1
- package/dist/src/utils/runtime_env.d.ts +4 -0
- package/dist/src/utils/runtime_env.d.ts.map +1 -0
- package/dist/src/utils/runtime_env.js +51 -0
- package/dist/src/utils/runtime_env.js.map +1 -0
- package/dist/src/wiki/wiki_linter.d.ts +25 -0
- package/dist/src/wiki/wiki_linter.d.ts.map +1 -0
- package/dist/src/wiki/wiki_linter.js +268 -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 +36 -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 +33 -0
- package/dist/src/wiki/wiki_projector.d.ts.map +1 -0
- package/dist/src/wiki/wiki_projector.js +633 -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 +501 -16
- package/package.json +58 -7
- package/schema/graph.schema.yaml +330 -0
- package/scripts/cli.js +19 -14
- package/scripts/repair-memory.js +321 -0
- package/scripts/uninstall.js +22 -5
- package/skills/cortex-memory/SKILL.md +49 -0
- package/skills/cortex-memory/references/agent-manual.md +115 -0
- package/skills/cortex-memory/references/configuration.md +92 -0
- package/skills/cortex-memory/references/publish-checklist.md +46 -0
- package/skills/cortex-memory/references/system-prompt-template.md +27 -0
- package/skills/cortex-memory/references/tools.md +181 -0
- package/skills/cortex-memory/scripts/smoke-check.ps1 +56 -0
- package/index.ts +0 -2142
|
@@ -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);
|
package/scripts/uninstall.js
CHANGED
|
@@ -17,14 +17,20 @@ function findProjectRoot() {
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
function findOpenClawConfig() {
|
|
20
|
+
const explicitConfigPath = process.env.OPENCLAW_CONFIG_PATH || '';
|
|
21
|
+
const stateDir = process.env.OPENCLAW_STATE_DIR || '';
|
|
22
|
+
const basePath = process.env.OPENCLAW_BASE_PATH || '';
|
|
23
|
+
const homePath = process.env.USERPROFILE || process.env.HOME || '';
|
|
20
24
|
const possiblePaths = [
|
|
25
|
+
explicitConfigPath,
|
|
26
|
+
stateDir ? path.join(stateDir, 'openclaw.json') : '',
|
|
27
|
+
basePath ? path.join(basePath, 'openclaw.json') : '',
|
|
21
28
|
path.join(process.cwd(), 'openclaw.json'),
|
|
22
|
-
path.join(
|
|
23
|
-
path.join(process.env.OPENCLAW_BASE_PATH || '', 'openclaw.json'),
|
|
29
|
+
homePath ? path.join(homePath, '.openclaw', 'openclaw.json') : '',
|
|
24
30
|
];
|
|
25
31
|
|
|
26
32
|
for (const p of possiblePaths) {
|
|
27
|
-
if (fs.existsSync(p)) {
|
|
33
|
+
if (p && fs.existsSync(p)) {
|
|
28
34
|
return p;
|
|
29
35
|
}
|
|
30
36
|
}
|
|
@@ -114,15 +120,20 @@ function removeFromConfig() {
|
|
|
114
120
|
const content = fs.readFileSync(configPath, 'utf-8');
|
|
115
121
|
const config = JSON.parse(content);
|
|
116
122
|
|
|
123
|
+
if (Array.isArray(config.plugins?.allow)) {
|
|
124
|
+
config.plugins.allow = config.plugins.allow.filter((item) => item !== PLUGIN_NAME);
|
|
125
|
+
}
|
|
117
126
|
if (config.plugins?.entries?.[PLUGIN_NAME]) {
|
|
118
127
|
delete config.plugins.entries[PLUGIN_NAME];
|
|
119
|
-
|
|
120
128
|
if (config.plugins.slots?.memory === PLUGIN_NAME) {
|
|
121
129
|
delete config.plugins.slots.memory;
|
|
122
130
|
}
|
|
123
131
|
|
|
124
132
|
fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
125
133
|
console.log(`Removed plugin from config: ${configPath}`);
|
|
134
|
+
} else if (Array.isArray(config.plugins?.allow)) {
|
|
135
|
+
fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
136
|
+
console.log(`Removed plugin allowlist entry from config: ${configPath}`);
|
|
126
137
|
} else {
|
|
127
138
|
console.log('Plugin not found in config.');
|
|
128
139
|
}
|
|
@@ -209,4 +220,10 @@ function main() {
|
|
|
209
220
|
}
|
|
210
221
|
}
|
|
211
222
|
|
|
212
|
-
|
|
223
|
+
module.exports = {
|
|
224
|
+
uninstall,
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
if (require.main === module) {
|
|
228
|
+
main();
|
|
229
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: cortex-memory
|
|
3
|
+
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.
|
|
4
|
+
homepage: https://github.com/deki18/openclaw-cortex-memory
|
|
5
|
+
metadata: { "openclaw": { "os": ["darwin", "linux", "win32"], "primaryEnv": "EMBEDDING_API_KEY" } }
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Cortex Memory
|
|
9
|
+
|
|
10
|
+
This is an independent skill, not a plugin-embedded skill.
|
|
11
|
+
|
|
12
|
+
Use this runtime flow:
|
|
13
|
+
|
|
14
|
+
1. Check whether plugin `openclaw-cortex-memory` is available.
|
|
15
|
+
2. If missing or disabled, run the install bootstrap guide in `{baseDir}/references/agent-manual.md` with README-consistent install order.
|
|
16
|
+
3. After plugin is enabled, run memory retrieval or write operations.
|
|
17
|
+
|
|
18
|
+
After plugin is ready, use this default workflow:
|
|
19
|
+
|
|
20
|
+
1. Retrieve candidate memory with `search_memory`.
|
|
21
|
+
2. If the user asks about entity links or dependency paths, use `query_graph`.
|
|
22
|
+
3. If `query_graph` returns `conflict_hint`, use `list_graph_conflicts` and ask user confirmation before `resolve_graph_conflict`.
|
|
23
|
+
4. For graph status snapshots or projection consistency checks, use `export_graph_view` and `lint_memory_wiki`.
|
|
24
|
+
5. Answer with retrieved evidence first, then add reasoning.
|
|
25
|
+
6. If the turn introduces durable new information, persist it with `store_event`.
|
|
26
|
+
7. For maintenance windows or session wrap-up, run `sync_memory` and optionally `reflect_memory`.
|
|
27
|
+
|
|
28
|
+
If tool calls fail:
|
|
29
|
+
|
|
30
|
+
1. Run `diagnostics`.
|
|
31
|
+
2. Tell the user the plugin is unavailable or misconfigured.
|
|
32
|
+
3. Continue with a normal answer without fabricating memory hits.
|
|
33
|
+
|
|
34
|
+
Do not use this skill for:
|
|
35
|
+
|
|
36
|
+
- Real-time web facts (weather, stock, breaking news).
|
|
37
|
+
- One-off temporary context that should not be persisted.
|
|
38
|
+
|
|
39
|
+
Use these local references when needed:
|
|
40
|
+
|
|
41
|
+
- Install and bootstrap playbook: `{baseDir}/references/agent-manual.md`
|
|
42
|
+
- System prompt template: `{baseDir}/references/system-prompt-template.md`
|
|
43
|
+
- Tool details: `{baseDir}/references/tools.md`
|
|
44
|
+
- Config and dependency setup: `{baseDir}/references/configuration.md`
|
|
45
|
+
- Publish and validation checklist: `{baseDir}/references/publish-checklist.md`
|
|
46
|
+
|
|
47
|
+
Use this script for a quick environment preflight:
|
|
48
|
+
|
|
49
|
+
- `{baseDir}/scripts/smoke-check.ps1 -Json`
|
|
@@ -0,0 +1,115 @@
|
|
|
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.30
|
|
33
|
+
openclaw plugins install ./openclaw-cortex-memory-0.1.0-Alpha.30.tgz
|
|
34
|
+
openclaw plugins enable openclaw-cortex-memory
|
|
35
|
+
rm ./openclaw-cortex-memory-0.1.0-Alpha.30.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
|
+
If the user asks for "system prompt rules", use `{baseDir}/references/system-prompt-template.md`.
|
|
48
|
+
|
|
49
|
+
## Phase 3: Runtime Workflow
|
|
50
|
+
|
|
51
|
+
### Retrieval-first answers
|
|
52
|
+
|
|
53
|
+
1. `search_memory` with the user query.
|
|
54
|
+
2. `query_graph` when relationship/path reasoning is needed.
|
|
55
|
+
3. If `query_graph` returns `conflict_hint`, run `list_graph_conflicts` and confirm with user before `resolve_graph_conflict`.
|
|
56
|
+
4. Respond with evidence first, reasoning second.
|
|
57
|
+
|
|
58
|
+
### Persistence
|
|
59
|
+
|
|
60
|
+
Use `store_event` only for durable information:
|
|
61
|
+
|
|
62
|
+
- stable preferences
|
|
63
|
+
- project decisions
|
|
64
|
+
- long-lived constraints
|
|
65
|
+
|
|
66
|
+
Avoid persisting ephemeral chatter.
|
|
67
|
+
|
|
68
|
+
### Maintenance
|
|
69
|
+
|
|
70
|
+
- `sync_memory` for historical import
|
|
71
|
+
- `reflect_memory` for rule extraction
|
|
72
|
+
- `backfill_embeddings` for vector repair
|
|
73
|
+
- `export_graph_view` for status-aware graph snapshots
|
|
74
|
+
- `lint_memory_wiki` for projection consistency checks
|
|
75
|
+
- `diagnostics` when anything looks inconsistent
|
|
76
|
+
|
|
77
|
+
## Failure Handling
|
|
78
|
+
|
|
79
|
+
If plugin tools are unavailable:
|
|
80
|
+
|
|
81
|
+
1. Run `diagnostics`.
|
|
82
|
+
2. Explain the issue clearly (plugin disabled, config incomplete, endpoint unavailable, or API key missing).
|
|
83
|
+
3. Provide immediate next action with exact command.
|
|
84
|
+
|
|
85
|
+
If install or enable flow reports a `memory-lancedb` config requirement, add this block under `plugins.entries` in `openclaw.json`:
|
|
86
|
+
|
|
87
|
+
```json
|
|
88
|
+
"memory-lancedb": {
|
|
89
|
+
"enabled": false,
|
|
90
|
+
"config": {
|
|
91
|
+
"embedding": {
|
|
92
|
+
"apiKey": "${MEMORY_LANCEDB_API_KEY}",
|
|
93
|
+
"model": "text-embedding-3-small"
|
|
94
|
+
},
|
|
95
|
+
"dbPath": "~/.openclaw/memory/lancedb",
|
|
96
|
+
"autoRecall": true,
|
|
97
|
+
"autoCapture": false,
|
|
98
|
+
"captureMaxChars": 500
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Operator Commands Cheat Sheet
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
openclaw plugins install clawhub:openclaw-cortex-memory
|
|
107
|
+
openclaw plugins enable openclaw-cortex-memory
|
|
108
|
+
openclaw plugins inspect openclaw-cortex-memory
|
|
109
|
+
npm pack openclaw-cortex-memory@0.1.0-Alpha.30
|
|
110
|
+
openclaw plugins install ./openclaw-cortex-memory-0.1.0-Alpha.30.tgz
|
|
111
|
+
openclaw plugins enable openclaw-cortex-memory
|
|
112
|
+
rm ./openclaw-cortex-memory-0.1.0-Alpha.30.tgz
|
|
113
|
+
openclaw skills info cortex-memory
|
|
114
|
+
openclaw skills check
|
|
115
|
+
```
|
|
@@ -0,0 +1,92 @@
|
|
|
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
|
+
"openclaw-cortex-memory": {
|
|
16
|
+
"enabled": true,
|
|
17
|
+
"config": {
|
|
18
|
+
"autoSync": true,
|
|
19
|
+
"autoReflect": false,
|
|
20
|
+
"graphQualityMode": "warn",
|
|
21
|
+
"wikiProjection": {
|
|
22
|
+
"enabled": true,
|
|
23
|
+
"mode": "incremental",
|
|
24
|
+
"maxBatch": 100
|
|
25
|
+
},
|
|
26
|
+
"embedding": {
|
|
27
|
+
"provider": "api",
|
|
28
|
+
"model": "text-embedding-3-large",
|
|
29
|
+
"apiKey": "${EMBEDDING_API_KEY}",
|
|
30
|
+
"baseURL": "https://your-embedding-endpoint/v1",
|
|
31
|
+
"dimensions": 3072
|
|
32
|
+
},
|
|
33
|
+
"llm": {
|
|
34
|
+
"provider": "api",
|
|
35
|
+
"model": "gpt-4",
|
|
36
|
+
"apiKey": "${LLM_API_KEY}",
|
|
37
|
+
"baseURL": "https://your-llm-endpoint/v1"
|
|
38
|
+
},
|
|
39
|
+
"reranker": {
|
|
40
|
+
"provider": "api",
|
|
41
|
+
"model": "BAAI/bge-reranker-v2-m3",
|
|
42
|
+
"apiKey": "${RERANKER_API_KEY}",
|
|
43
|
+
"baseURL": "https://your-reranker-endpoint/v1/rerank"
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Required Environment Variables
|
|
53
|
+
|
|
54
|
+
- `EMBEDDING_API_KEY`
|
|
55
|
+
- `LLM_API_KEY`
|
|
56
|
+
- `RERANKER_API_KEY`
|
|
57
|
+
|
|
58
|
+
## Required Endpoints
|
|
59
|
+
|
|
60
|
+
- Embedding: OpenAI-compatible `/embeddings`
|
|
61
|
+
- LLM: OpenAI-compatible `/chat/completions`
|
|
62
|
+
- Reranker: `/rerank`
|
|
63
|
+
|
|
64
|
+
## Troubleshooting: memory-lancedb Requirement
|
|
65
|
+
|
|
66
|
+
If `openclaw plugins install/enable` reports a `memory-lancedb` config requirement, add this entry under `plugins.entries`:
|
|
67
|
+
|
|
68
|
+
```json
|
|
69
|
+
"memory-lancedb": {
|
|
70
|
+
"enabled": false,
|
|
71
|
+
"config": {
|
|
72
|
+
"embedding": {
|
|
73
|
+
"apiKey": "${MEMORY_LANCEDB_API_KEY}",
|
|
74
|
+
"model": "text-embedding-3-small"
|
|
75
|
+
},
|
|
76
|
+
"dbPath": "~/.openclaw/memory/lancedb",
|
|
77
|
+
"autoRecall": true,
|
|
78
|
+
"autoCapture": false,
|
|
79
|
+
"captureMaxChars": 500
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Recommended Validation Commands
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
openclaw plugins list
|
|
88
|
+
openclaw plugins inspect openclaw-cortex-memory
|
|
89
|
+
openclaw skills list
|
|
90
|
+
openclaw skills info cortex-memory
|
|
91
|
+
openclaw skills check
|
|
92
|
+
```
|
|
@@ -0,0 +1,46 @@
|
|
|
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 skill 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`.
|
|
46
|
+
|