openclaw-cortex-memory 0.1.0-Alpha.1 → 0.1.0-Alpha.10
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/README.md +119 -27
- package/SKILL.md +112 -30
- package/dist/index.d.ts +47 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +356 -19
- package/dist/index.js.map +1 -1
- package/dist/openclaw.plugin.json +157 -5
- 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 +225 -0
- package/dist/src/dedup/three_stage_deduplicator.js.map +1 -0
- package/dist/src/engine/memory_engine.d.ts +2 -1
- package/dist/src/engine/memory_engine.d.ts.map +1 -1
- package/dist/src/engine/ts_engine.d.ts +95 -0
- package/dist/src/engine/ts_engine.d.ts.map +1 -1
- package/dist/src/engine/ts_engine.js +849 -33
- package/dist/src/engine/ts_engine.js.map +1 -1
- package/dist/src/engine/types.d.ts +11 -0
- package/dist/src/engine/types.d.ts.map +1 -1
- package/dist/src/graph/ontology.d.ts +53 -0
- package/dist/src/graph/ontology.d.ts.map +1 -0
- package/dist/src/graph/ontology.js +252 -0
- package/dist/src/graph/ontology.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 +75 -1
- package/dist/src/reflect/reflector.js.map +1 -1
- package/dist/src/session/session_end.d.ts +55 -0
- package/dist/src/session/session_end.d.ts.map +1 -1
- package/dist/src/session/session_end.js +255 -55
- package/dist/src/session/session_end.js.map +1 -1
- package/dist/src/store/archive_store.d.ts +115 -0
- package/dist/src/store/archive_store.d.ts.map +1 -0
- package/dist/src/store/archive_store.js +446 -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/read_store.d.ts +59 -0
- package/dist/src/store/read_store.d.ts.map +1 -1
- package/dist/src/store/read_store.js +1114 -17
- package/dist/src/store/read_store.js.map +1 -1
- package/dist/src/store/vector_store.d.ts +43 -0
- package/dist/src/store/vector_store.d.ts.map +1 -0
- package/dist/src/store/vector_store.js +186 -0
- package/dist/src/store/vector_store.js.map +1 -0
- package/dist/src/store/write_store.d.ts +45 -0
- package/dist/src/store/write_store.d.ts.map +1 -1
- package/dist/src/store/write_store.js +230 -0
- package/dist/src/store/write_store.js.map +1 -1
- package/dist/src/sync/session_sync.d.ts +51 -2
- package/dist/src/sync/session_sync.d.ts.map +1 -1
- package/dist/src/sync/session_sync.js +465 -22
- 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/openclaw.plugin.json +157 -5
- package/package.json +21 -6
- package/scripts/cli.js +19 -14
- package/scripts/uninstall.js +22 -5
- package/index.ts +0 -2071
- package/scripts/install.js +0 -27
package/dist/index.js
CHANGED
|
@@ -46,10 +46,14 @@ const net = __importStar(require("net"));
|
|
|
46
46
|
const ts_engine_1 = require("./src/engine/ts_engine");
|
|
47
47
|
const read_store_1 = require("./src/store/read_store");
|
|
48
48
|
const write_store_1 = require("./src/store/write_store");
|
|
49
|
+
const archive_store_1 = require("./src/store/archive_store");
|
|
50
|
+
const vector_store_1 = require("./src/store/vector_store");
|
|
49
51
|
const session_sync_1 = require("./src/sync/session_sync");
|
|
50
52
|
const session_end_1 = require("./src/session/session_end");
|
|
51
53
|
const rule_store_1 = require("./src/rules/rule_store");
|
|
52
54
|
const reflector_1 = require("./src/reflect/reflector");
|
|
55
|
+
const three_stage_deduplicator_1 = require("./src/dedup/three_stage_deduplicator");
|
|
56
|
+
const runtime_env_1 = require("./src/utils/runtime_env");
|
|
53
57
|
const ERROR_CODES = {
|
|
54
58
|
CONNECTION_REFUSED: {
|
|
55
59
|
code: "E001",
|
|
@@ -89,6 +93,64 @@ const MAX_OPENCLAW_VERSION = "2027.0.0";
|
|
|
89
93
|
const defaultConfig = {
|
|
90
94
|
autoSync: true,
|
|
91
95
|
autoReflect: false,
|
|
96
|
+
autoReflectIntervalMinutes: 30,
|
|
97
|
+
readFusion: {
|
|
98
|
+
enabled: true,
|
|
99
|
+
maxCandidates: 10,
|
|
100
|
+
authoritative: true,
|
|
101
|
+
channelWeights: {
|
|
102
|
+
rules: 1,
|
|
103
|
+
archive: 1.15,
|
|
104
|
+
vector: 1.2,
|
|
105
|
+
graph: 1,
|
|
106
|
+
},
|
|
107
|
+
channelTopK: {
|
|
108
|
+
rules: 8,
|
|
109
|
+
archive: 20,
|
|
110
|
+
vector: 20,
|
|
111
|
+
graph: 12,
|
|
112
|
+
},
|
|
113
|
+
minLexicalHits: 1,
|
|
114
|
+
minSemanticHits: 1,
|
|
115
|
+
lengthNorm: {
|
|
116
|
+
enabled: true,
|
|
117
|
+
pivotChars: 1200,
|
|
118
|
+
strength: 0.75,
|
|
119
|
+
minFactor: 0.45,
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
vectorChunking: {
|
|
123
|
+
chunkSize: 600,
|
|
124
|
+
chunkOverlap: 100,
|
|
125
|
+
},
|
|
126
|
+
memoryDecay: {
|
|
127
|
+
enabled: true,
|
|
128
|
+
minFloor: 0.15,
|
|
129
|
+
defaultHalfLifeDays: 90,
|
|
130
|
+
antiDecay: {
|
|
131
|
+
enabled: true,
|
|
132
|
+
maxBoost: 1.6,
|
|
133
|
+
hitWeight: 0.08,
|
|
134
|
+
recentWindowDays: 30,
|
|
135
|
+
},
|
|
136
|
+
halfLifeByEventType: {
|
|
137
|
+
issue: 30,
|
|
138
|
+
fix: 30,
|
|
139
|
+
action_item: 30,
|
|
140
|
+
blocker: 30,
|
|
141
|
+
plan: 60,
|
|
142
|
+
milestone: 60,
|
|
143
|
+
follow_up: 60,
|
|
144
|
+
decision: 120,
|
|
145
|
+
insight: 120,
|
|
146
|
+
retrospective: 120,
|
|
147
|
+
preference: 240,
|
|
148
|
+
constraint: 240,
|
|
149
|
+
requirement: 240,
|
|
150
|
+
dependency: 240,
|
|
151
|
+
assumption: 240,
|
|
152
|
+
},
|
|
153
|
+
},
|
|
92
154
|
enabled: true,
|
|
93
155
|
fallbackToBuiltin: true,
|
|
94
156
|
engineMode: "ts",
|
|
@@ -96,6 +158,7 @@ const defaultConfig = {
|
|
|
96
158
|
let autoSearchCacheBySession = new Map();
|
|
97
159
|
const AUTO_SEARCH_CACHE_TTL = 60000;
|
|
98
160
|
const MAX_AUTO_SEARCH_CACHE_SESSIONS = 200;
|
|
161
|
+
const HOOK_GUARD_TIMEOUT_MS = 2000;
|
|
99
162
|
let config = null;
|
|
100
163
|
let logger;
|
|
101
164
|
let pythonProcess = null;
|
|
@@ -150,6 +213,33 @@ function getSessionCachedAutoSearch(sessionId) {
|
|
|
150
213
|
ageSeconds: Math.floor((Date.now() - cache.timestamp) / 1000),
|
|
151
214
|
};
|
|
152
215
|
}
|
|
216
|
+
function isInternalSession(sessionId) {
|
|
217
|
+
if (!sessionId)
|
|
218
|
+
return false;
|
|
219
|
+
return sessionId.startsWith("slug-generator-") || sessionId.startsWith("fallback:");
|
|
220
|
+
}
|
|
221
|
+
async function runWithTimeout(task, timeoutMs, label) {
|
|
222
|
+
let timeoutHandle = null;
|
|
223
|
+
try {
|
|
224
|
+
const timeoutPromise = new Promise((resolve) => {
|
|
225
|
+
timeoutHandle = setTimeout(() => resolve(null), timeoutMs);
|
|
226
|
+
});
|
|
227
|
+
const result = await Promise.race([task, timeoutPromise]);
|
|
228
|
+
if (result === null) {
|
|
229
|
+
logger.warn(`${label} timed out after ${timeoutMs}ms; skipped to protect gateway responsiveness`);
|
|
230
|
+
}
|
|
231
|
+
return result;
|
|
232
|
+
}
|
|
233
|
+
catch (error) {
|
|
234
|
+
logger.warn(`${label} failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
235
|
+
return null;
|
|
236
|
+
}
|
|
237
|
+
finally {
|
|
238
|
+
if (timeoutHandle) {
|
|
239
|
+
clearTimeout(timeoutHandle);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
153
243
|
function resolveEngine() {
|
|
154
244
|
if (!config) {
|
|
155
245
|
throw new Error("Configuration not loaded");
|
|
@@ -164,16 +254,43 @@ function resolveEngine() {
|
|
|
164
254
|
projectRoot,
|
|
165
255
|
dbPath: config.dbPath,
|
|
166
256
|
logger,
|
|
257
|
+
embedding: config.embedding,
|
|
258
|
+
reranker: config.reranker,
|
|
259
|
+
llm: config.llm,
|
|
260
|
+
fusion: config.readFusion,
|
|
261
|
+
memoryDecay: config.memoryDecay,
|
|
262
|
+
});
|
|
263
|
+
const vectorStore = (0, vector_store_1.createVectorStore)({
|
|
264
|
+
memoryRoot,
|
|
265
|
+
logger,
|
|
167
266
|
});
|
|
168
267
|
const writeStore = (0, write_store_1.createWriteStore)({
|
|
169
268
|
projectRoot,
|
|
170
269
|
dbPath: config.dbPath,
|
|
171
270
|
logger,
|
|
271
|
+
embedding: config.embedding,
|
|
272
|
+
vectorChunking: config.vectorChunking,
|
|
273
|
+
vectorStore,
|
|
274
|
+
});
|
|
275
|
+
const deduplicator = (0, three_stage_deduplicator_1.createThreeStageDeduplicator)({
|
|
276
|
+
memoryRoot,
|
|
277
|
+
logger,
|
|
278
|
+
});
|
|
279
|
+
const archiveStore = (0, archive_store_1.createArchiveStore)({
|
|
280
|
+
projectRoot,
|
|
281
|
+
memoryRoot,
|
|
282
|
+
logger,
|
|
283
|
+
embedding: config.embedding,
|
|
284
|
+
vectorChunking: config.vectorChunking,
|
|
285
|
+
deduplicator,
|
|
286
|
+
vectorStore,
|
|
172
287
|
});
|
|
173
288
|
const sessionSync = (0, session_sync_1.createSessionSync)({
|
|
174
289
|
projectRoot,
|
|
175
290
|
dbPath: config.dbPath,
|
|
176
291
|
logger,
|
|
292
|
+
llm: config.llm,
|
|
293
|
+
archiveStore,
|
|
177
294
|
writeStore,
|
|
178
295
|
});
|
|
179
296
|
const sessionEnd = (0, session_end_1.createSessionEnd)({
|
|
@@ -181,6 +298,9 @@ function resolveEngine() {
|
|
|
181
298
|
dbPath: config.dbPath,
|
|
182
299
|
logger,
|
|
183
300
|
syncMemory: sessionSync.syncMemory,
|
|
301
|
+
syncDailySummaries: sessionSync.syncDailySummaries,
|
|
302
|
+
archiveStore,
|
|
303
|
+
llm: config.llm,
|
|
184
304
|
});
|
|
185
305
|
const ruleStore = (0, rule_store_1.createRuleStore)({
|
|
186
306
|
projectRoot,
|
|
@@ -192,14 +312,22 @@ function resolveEngine() {
|
|
|
192
312
|
dbPath: config.dbPath,
|
|
193
313
|
logger,
|
|
194
314
|
ruleStore,
|
|
315
|
+
llm: config.llm,
|
|
195
316
|
});
|
|
196
317
|
memoryEngine = (0, ts_engine_1.createTsEngine)({
|
|
197
318
|
readStore,
|
|
198
319
|
writeStore,
|
|
320
|
+
vectorStore,
|
|
321
|
+
archiveStore,
|
|
199
322
|
sessionSync,
|
|
200
323
|
sessionEnd,
|
|
201
324
|
reflector,
|
|
202
325
|
memoryRoot,
|
|
326
|
+
projectRoot,
|
|
327
|
+
embedding: config.embedding,
|
|
328
|
+
llm: config.llm,
|
|
329
|
+
reranker: config.reranker,
|
|
330
|
+
vectorChunking: config.vectorChunking,
|
|
203
331
|
getCachedAutoSearch: getSessionCachedAutoSearch,
|
|
204
332
|
resolveSessionId: (context, payload) => resolveSessionId(context, payload),
|
|
205
333
|
normalizeIncomingMessage,
|
|
@@ -257,6 +385,15 @@ function sanitizeForLogging(obj) {
|
|
|
257
385
|
}
|
|
258
386
|
return sanitized;
|
|
259
387
|
}
|
|
388
|
+
function logLifecycle(event, details = {}) {
|
|
389
|
+
const payload = sanitizeForLogging({
|
|
390
|
+
event,
|
|
391
|
+
plugin: PLUGIN_ID,
|
|
392
|
+
ts: new Date().toISOString(),
|
|
393
|
+
...details,
|
|
394
|
+
});
|
|
395
|
+
logger.info(`[Lifecycle] ${JSON.stringify(payload)}`);
|
|
396
|
+
}
|
|
260
397
|
function asRecord(value) {
|
|
261
398
|
if (typeof value === "object" && value !== null) {
|
|
262
399
|
return value;
|
|
@@ -381,7 +518,7 @@ function compareVersions(a, b) {
|
|
|
381
518
|
}
|
|
382
519
|
async function checkOpenClawVersion() {
|
|
383
520
|
try {
|
|
384
|
-
const version =
|
|
521
|
+
const version = (0, runtime_env_1.getEnvValue)("OPENCLAW_VERSION");
|
|
385
522
|
if (version) {
|
|
386
523
|
if (compareVersions(version, MIN_OPENCLAW_VERSION) < 0) {
|
|
387
524
|
throw new Error(`Incompatible OpenClaw version: ${version}. Minimum required: ${MIN_OPENCLAW_VERSION}`);
|
|
@@ -415,13 +552,19 @@ function findProjectRoot() {
|
|
|
415
552
|
throw new Error("Cannot find project root directory");
|
|
416
553
|
}
|
|
417
554
|
function findOpenClawConfig() {
|
|
555
|
+
const explicitConfigPath = (0, runtime_env_1.getEnvValue)("OPENCLAW_CONFIG_PATH");
|
|
556
|
+
const stateDir = (0, runtime_env_1.getEnvValue)("OPENCLAW_STATE_DIR");
|
|
557
|
+
const basePath = (0, runtime_env_1.getEnvValue)("OPENCLAW_BASE_PATH");
|
|
558
|
+
const homePath = (0, runtime_env_1.getHomeDir)();
|
|
418
559
|
const possiblePaths = [
|
|
560
|
+
explicitConfigPath,
|
|
561
|
+
stateDir ? path.join(stateDir, "openclaw.json") : "",
|
|
562
|
+
basePath ? path.join(basePath, "openclaw.json") : "",
|
|
419
563
|
path.join(process.cwd(), "openclaw.json"),
|
|
420
|
-
path.join(
|
|
421
|
-
path.join(process.env.OPENCLAW_BASE_PATH || "", "openclaw.json"),
|
|
564
|
+
homePath ? path.join(homePath, ".openclaw", "openclaw.json") : "",
|
|
422
565
|
];
|
|
423
566
|
for (const p of possiblePaths) {
|
|
424
|
-
if (fs.existsSync(p)) {
|
|
567
|
+
if (p && fs.existsSync(p)) {
|
|
425
568
|
return p;
|
|
426
569
|
}
|
|
427
570
|
}
|
|
@@ -476,6 +619,8 @@ function startAutoReflectScheduler() {
|
|
|
476
619
|
if (!config?.autoReflect || autoReflectInterval) {
|
|
477
620
|
return;
|
|
478
621
|
}
|
|
622
|
+
const intervalMinutes = Math.max(5, Math.floor(config.autoReflectIntervalMinutes ?? 30));
|
|
623
|
+
const intervalMs = intervalMinutes * 60 * 1000;
|
|
479
624
|
autoReflectInterval = setInterval(() => {
|
|
480
625
|
if (!isEnabled) {
|
|
481
626
|
return;
|
|
@@ -492,7 +637,7 @@ function startAutoReflectScheduler() {
|
|
|
492
637
|
if (marker === lastAutoReflectArchiveMarker) {
|
|
493
638
|
return;
|
|
494
639
|
}
|
|
495
|
-
if (now - lastAutoReflectRunAt <
|
|
640
|
+
if (now - lastAutoReflectRunAt < intervalMs) {
|
|
496
641
|
return;
|
|
497
642
|
}
|
|
498
643
|
resolveEngine().reflectMemory({}, schedulerContext)
|
|
@@ -507,7 +652,7 @@ function startAutoReflectScheduler() {
|
|
|
507
652
|
}
|
|
508
653
|
})
|
|
509
654
|
.catch(error => logger.warn(`Auto-reflect failed: ${String(error)}`));
|
|
510
|
-
},
|
|
655
|
+
}, intervalMs);
|
|
511
656
|
}
|
|
512
657
|
function stopAutoReflectScheduler() {
|
|
513
658
|
if (autoReflectInterval) {
|
|
@@ -523,6 +668,12 @@ function validateConfig(cfg) {
|
|
|
523
668
|
if (!cfg.embedding?.apiKey || !cfg.embedding?.baseURL) {
|
|
524
669
|
errors.push("embedding.apiKey and embedding.baseURL are required. Please configure third-party embedding endpoint credentials.");
|
|
525
670
|
}
|
|
671
|
+
if (typeof cfg.embedding?.timeoutMs === "number" && (!Number.isFinite(cfg.embedding.timeoutMs) || cfg.embedding.timeoutMs < 1000)) {
|
|
672
|
+
errors.push("embedding.timeoutMs must be a number >= 1000.");
|
|
673
|
+
}
|
|
674
|
+
if (typeof cfg.embedding?.maxRetries === "number" && (!Number.isFinite(cfg.embedding.maxRetries) || cfg.embedding.maxRetries < 1 || cfg.embedding.maxRetries > 8)) {
|
|
675
|
+
errors.push("embedding.maxRetries must be between 1 and 8.");
|
|
676
|
+
}
|
|
526
677
|
if (!cfg.llm?.provider || !cfg.llm?.model) {
|
|
527
678
|
errors.push("llm.provider and llm.model are required. Please configure them in openclaw.json");
|
|
528
679
|
}
|
|
@@ -535,6 +686,88 @@ function validateConfig(cfg) {
|
|
|
535
686
|
if (!cfg.reranker?.apiKey || !cfg.reranker?.baseURL) {
|
|
536
687
|
errors.push("reranker.apiKey and reranker.baseURL are required. Please configure third-party reranker endpoint credentials.");
|
|
537
688
|
}
|
|
689
|
+
if (typeof cfg.autoReflectIntervalMinutes === "number" && (!Number.isFinite(cfg.autoReflectIntervalMinutes) || cfg.autoReflectIntervalMinutes < 5)) {
|
|
690
|
+
errors.push("autoReflectIntervalMinutes must be a number >= 5.");
|
|
691
|
+
}
|
|
692
|
+
if (cfg.readFusion && typeof cfg.readFusion.maxCandidates === "number" && (!Number.isFinite(cfg.readFusion.maxCandidates) || cfg.readFusion.maxCandidates < 2)) {
|
|
693
|
+
errors.push("readFusion.maxCandidates must be a number >= 2.");
|
|
694
|
+
}
|
|
695
|
+
if (cfg.readFusion?.channelWeights) {
|
|
696
|
+
for (const [key, value] of Object.entries(cfg.readFusion.channelWeights)) {
|
|
697
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
|
|
698
|
+
errors.push(`readFusion.channelWeights.${key} must be a number > 0.`);
|
|
699
|
+
break;
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
if (cfg.readFusion?.channelTopK) {
|
|
704
|
+
for (const [key, value] of Object.entries(cfg.readFusion.channelTopK)) {
|
|
705
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value < 1) {
|
|
706
|
+
errors.push(`readFusion.channelTopK.${key} must be a number >= 1.`);
|
|
707
|
+
break;
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
if (typeof cfg.readFusion?.minLexicalHits === "number" && (!Number.isFinite(cfg.readFusion.minLexicalHits) || cfg.readFusion.minLexicalHits < 0)) {
|
|
712
|
+
errors.push("readFusion.minLexicalHits must be a number >= 0.");
|
|
713
|
+
}
|
|
714
|
+
if (typeof cfg.readFusion?.minSemanticHits === "number" && (!Number.isFinite(cfg.readFusion.minSemanticHits) || cfg.readFusion.minSemanticHits < 0)) {
|
|
715
|
+
errors.push("readFusion.minSemanticHits must be a number >= 0.");
|
|
716
|
+
}
|
|
717
|
+
if (cfg.readFusion?.lengthNorm) {
|
|
718
|
+
const ln = cfg.readFusion.lengthNorm;
|
|
719
|
+
if (typeof ln.pivotChars === "number" && (!Number.isFinite(ln.pivotChars) || ln.pivotChars <= 0)) {
|
|
720
|
+
errors.push("readFusion.lengthNorm.pivotChars must be > 0.");
|
|
721
|
+
}
|
|
722
|
+
if (typeof ln.strength === "number" && (!Number.isFinite(ln.strength) || ln.strength <= 0)) {
|
|
723
|
+
errors.push("readFusion.lengthNorm.strength must be > 0.");
|
|
724
|
+
}
|
|
725
|
+
if (typeof ln.minFactor === "number" && (!Number.isFinite(ln.minFactor) || ln.minFactor <= 0 || ln.minFactor > 1)) {
|
|
726
|
+
errors.push("readFusion.lengthNorm.minFactor must be within (0,1].");
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
if (cfg.vectorChunking) {
|
|
730
|
+
if (typeof cfg.vectorChunking.chunkSize === "number" && (!Number.isFinite(cfg.vectorChunking.chunkSize) || cfg.vectorChunking.chunkSize < 200)) {
|
|
731
|
+
errors.push("vectorChunking.chunkSize must be >= 200.");
|
|
732
|
+
}
|
|
733
|
+
if (typeof cfg.vectorChunking.chunkOverlap === "number" && (!Number.isFinite(cfg.vectorChunking.chunkOverlap) || cfg.vectorChunking.chunkOverlap < 0)) {
|
|
734
|
+
errors.push("vectorChunking.chunkOverlap must be >= 0.");
|
|
735
|
+
}
|
|
736
|
+
if (typeof cfg.vectorChunking.chunkSize === "number" &&
|
|
737
|
+
typeof cfg.vectorChunking.chunkOverlap === "number" &&
|
|
738
|
+
cfg.vectorChunking.chunkOverlap >= cfg.vectorChunking.chunkSize) {
|
|
739
|
+
errors.push("vectorChunking.chunkOverlap must be smaller than chunkSize.");
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
if (cfg.memoryDecay) {
|
|
743
|
+
if (typeof cfg.memoryDecay.minFloor === "number" && (!Number.isFinite(cfg.memoryDecay.minFloor) || cfg.memoryDecay.minFloor < 0 || cfg.memoryDecay.minFloor > 1)) {
|
|
744
|
+
errors.push("memoryDecay.minFloor must be within [0,1].");
|
|
745
|
+
}
|
|
746
|
+
if (typeof cfg.memoryDecay.defaultHalfLifeDays === "number" && (!Number.isFinite(cfg.memoryDecay.defaultHalfLifeDays) || cfg.memoryDecay.defaultHalfLifeDays <= 0)) {
|
|
747
|
+
errors.push("memoryDecay.defaultHalfLifeDays must be > 0.");
|
|
748
|
+
}
|
|
749
|
+
const mapping = cfg.memoryDecay.halfLifeByEventType;
|
|
750
|
+
if (mapping && typeof mapping === "object") {
|
|
751
|
+
for (const [key, value] of Object.entries(mapping)) {
|
|
752
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
|
|
753
|
+
errors.push(`memoryDecay.halfLifeByEventType.${key} must be > 0.`);
|
|
754
|
+
break;
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
const anti = cfg.memoryDecay.antiDecay;
|
|
759
|
+
if (anti) {
|
|
760
|
+
if (typeof anti.maxBoost === "number" && (!Number.isFinite(anti.maxBoost) || anti.maxBoost < 1)) {
|
|
761
|
+
errors.push("memoryDecay.antiDecay.maxBoost must be >= 1.");
|
|
762
|
+
}
|
|
763
|
+
if (typeof anti.hitWeight === "number" && (!Number.isFinite(anti.hitWeight) || anti.hitWeight < 0)) {
|
|
764
|
+
errors.push("memoryDecay.antiDecay.hitWeight must be >= 0.");
|
|
765
|
+
}
|
|
766
|
+
if (typeof anti.recentWindowDays === "number" && (!Number.isFinite(anti.recentWindowDays) || anti.recentWindowDays <= 0)) {
|
|
767
|
+
errors.push("memoryDecay.antiDecay.recentWindowDays must be > 0.");
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
}
|
|
538
771
|
return errors;
|
|
539
772
|
}
|
|
540
773
|
function getApiHostAndPort() {
|
|
@@ -720,14 +953,14 @@ async function startPythonServiceInternal() {
|
|
|
720
953
|
}
|
|
721
954
|
logger.info("Starting Cortex Memory Python service...");
|
|
722
955
|
const env = {
|
|
723
|
-
...
|
|
956
|
+
...(0, runtime_env_1.getProcessEnvCopy)(),
|
|
724
957
|
CORTEX_MEMORY_EMBEDDING_PROVIDER: config.embedding.provider,
|
|
725
958
|
CORTEX_MEMORY_EMBEDDING_MODEL: config.embedding.model,
|
|
726
959
|
CORTEX_MEMORY_LLM_PROVIDER: config.llm.provider,
|
|
727
960
|
CORTEX_MEMORY_LLM_MODEL: config.llm.model,
|
|
728
961
|
CORTEX_MEMORY_RERANKER_PROVIDER: config.reranker.provider || "",
|
|
729
962
|
CORTEX_MEMORY_RERANKER_MODEL: config.reranker.model,
|
|
730
|
-
CORTEX_MEMORY_DB_PATH: config.dbPath || path.join(
|
|
963
|
+
CORTEX_MEMORY_DB_PATH: config.dbPath || path.join((0, runtime_env_1.getHomeDir)(), ".openclaw", "agents", "main", "lancedb_store"),
|
|
731
964
|
};
|
|
732
965
|
if (config.embedding.apiKey) {
|
|
733
966
|
env.CORTEX_MEMORY_EMBEDDING_API_KEY = config.embedding.apiKey;
|
|
@@ -870,7 +1103,7 @@ function stopPythonService() {
|
|
|
870
1103
|
stopPythonServiceAsync();
|
|
871
1104
|
}
|
|
872
1105
|
function getBaseUrl() {
|
|
873
|
-
return config?.apiUrl ?? "http://
|
|
1106
|
+
return config?.apiUrl ?? "http://localhost:8765";
|
|
874
1107
|
}
|
|
875
1108
|
async function waitForService(maxAttempts = 30) {
|
|
876
1109
|
const apiUrl = getBaseUrl();
|
|
@@ -1365,10 +1598,18 @@ async function onTimerPythonHandler(payload, _context) {
|
|
|
1365
1598
|
}
|
|
1366
1599
|
}
|
|
1367
1600
|
async function onMessageHandler(payload, context) {
|
|
1368
|
-
|
|
1601
|
+
const sessionId = resolveSessionId(context, payload);
|
|
1602
|
+
if (isInternalSession(sessionId)) {
|
|
1603
|
+
return;
|
|
1604
|
+
}
|
|
1605
|
+
await runWithTimeout(resolveEngine().onMessage(payload, context), HOOK_GUARD_TIMEOUT_MS, "onMessage hook");
|
|
1369
1606
|
}
|
|
1370
1607
|
async function onSessionEndHandler(payload, context) {
|
|
1371
|
-
|
|
1608
|
+
const sessionId = resolveSessionId(context, payload);
|
|
1609
|
+
if (isInternalSession(sessionId)) {
|
|
1610
|
+
return;
|
|
1611
|
+
}
|
|
1612
|
+
await runWithTimeout(resolveEngine().onSessionEnd(payload, context), HOOK_GUARD_TIMEOUT_MS, "onSessionEnd hook");
|
|
1372
1613
|
}
|
|
1373
1614
|
async function onTimerHandler(payload, context) {
|
|
1374
1615
|
await resolveEngine().onTimer(payload, context);
|
|
@@ -1497,6 +1738,26 @@ function registerTools() {
|
|
|
1497
1738
|
return resolveEngine().syncMemory(args, params.context);
|
|
1498
1739
|
},
|
|
1499
1740
|
},
|
|
1741
|
+
{
|
|
1742
|
+
name: "backfill_embeddings",
|
|
1743
|
+
description: "Backfill missing embeddings for active/archive records",
|
|
1744
|
+
parameters: {
|
|
1745
|
+
type: "object",
|
|
1746
|
+
properties: {
|
|
1747
|
+
layer: { type: "string", enum: ["active", "archive", "all"], description: "Target layer to backfill" },
|
|
1748
|
+
batch_size: { type: "integer", description: "Batch size per processing window" },
|
|
1749
|
+
max_retries: { type: "integer", description: "Max retry count for failed records" },
|
|
1750
|
+
retry_failed_only: { type: "boolean", description: "Only retry failed records" },
|
|
1751
|
+
rebuild_mode: { type: "string", enum: ["incremental", "vector_only", "full"], description: "Rebuild mode" },
|
|
1752
|
+
},
|
|
1753
|
+
required: [],
|
|
1754
|
+
additionalProperties: false,
|
|
1755
|
+
},
|
|
1756
|
+
execute: async (params) => {
|
|
1757
|
+
const args = params.args || params;
|
|
1758
|
+
return resolveEngine().backfillEmbeddings(args, params.context);
|
|
1759
|
+
},
|
|
1760
|
+
},
|
|
1500
1761
|
{
|
|
1501
1762
|
name: "delete_memory",
|
|
1502
1763
|
description: "Delete a memory by ID",
|
|
@@ -1529,10 +1790,39 @@ function registerTools() {
|
|
|
1529
1790
|
},
|
|
1530
1791
|
];
|
|
1531
1792
|
for (const tool of tools) {
|
|
1532
|
-
|
|
1793
|
+
registerToolCompat(tool);
|
|
1533
1794
|
registeredTools.push(tool.name);
|
|
1534
1795
|
}
|
|
1535
1796
|
}
|
|
1797
|
+
function registerToolCompat(tool) {
|
|
1798
|
+
if (!api)
|
|
1799
|
+
return;
|
|
1800
|
+
const execute = async (params) => tool.execute({
|
|
1801
|
+
args: params?.args || {},
|
|
1802
|
+
context: params.context,
|
|
1803
|
+
});
|
|
1804
|
+
const handler = async (...params) => {
|
|
1805
|
+
const first = params[0];
|
|
1806
|
+
const second = params[1];
|
|
1807
|
+
if (first && typeof first === "object" && "context" in first) {
|
|
1808
|
+
return execute({
|
|
1809
|
+
args: first.args || {},
|
|
1810
|
+
context: first.context,
|
|
1811
|
+
});
|
|
1812
|
+
}
|
|
1813
|
+
return execute({
|
|
1814
|
+
args: first || {},
|
|
1815
|
+
context: (second || {}),
|
|
1816
|
+
});
|
|
1817
|
+
};
|
|
1818
|
+
api.registerTool({
|
|
1819
|
+
name: tool.name,
|
|
1820
|
+
description: tool.description,
|
|
1821
|
+
parameters: tool.parameters,
|
|
1822
|
+
execute,
|
|
1823
|
+
handler,
|
|
1824
|
+
});
|
|
1825
|
+
}
|
|
1536
1826
|
function unregisterTools() {
|
|
1537
1827
|
if (!api || !api.unregisterTool)
|
|
1538
1828
|
return;
|
|
@@ -1637,6 +1927,7 @@ async function enable() {
|
|
|
1637
1927
|
return;
|
|
1638
1928
|
}
|
|
1639
1929
|
logger.info("Enabling Cortex Memory plugin...");
|
|
1930
|
+
logLifecycle("enable_start");
|
|
1640
1931
|
try {
|
|
1641
1932
|
unregisterFallbackTools();
|
|
1642
1933
|
if (shouldUsePythonRuntime()) {
|
|
@@ -1648,10 +1939,12 @@ async function enable() {
|
|
|
1648
1939
|
registerHooks();
|
|
1649
1940
|
startAutoReflectScheduler();
|
|
1650
1941
|
logger.info("Cortex Memory plugin enabled successfully");
|
|
1942
|
+
logLifecycle("enable_success", { registeredTools: registeredTools.length, registeredHooks: registeredHooks.length });
|
|
1651
1943
|
}
|
|
1652
1944
|
catch (error) {
|
|
1653
1945
|
const message = error instanceof Error ? error.message : String(error);
|
|
1654
1946
|
logger.error(`Failed to enable Cortex Memory plugin: ${message}`);
|
|
1947
|
+
logLifecycle("enable_failed", { error: message });
|
|
1655
1948
|
throw error;
|
|
1656
1949
|
}
|
|
1657
1950
|
}
|
|
@@ -1661,6 +1954,7 @@ async function disable() {
|
|
|
1661
1954
|
return;
|
|
1662
1955
|
}
|
|
1663
1956
|
logger.info("Disabling Cortex Memory plugin...");
|
|
1957
|
+
logLifecycle("disable_start");
|
|
1664
1958
|
unregisterHooks();
|
|
1665
1959
|
unregisterTools();
|
|
1666
1960
|
unregisterFallbackTools();
|
|
@@ -1673,13 +1967,15 @@ async function disable() {
|
|
|
1673
1967
|
if (config?.fallbackToBuiltin && builtinMemory) {
|
|
1674
1968
|
logger.info("Falling back to OpenClaw builtin memory system");
|
|
1675
1969
|
registerFallbackTools();
|
|
1970
|
+
logLifecycle("fallback_enabled", { fallbackTools: registeredFallbackTools.length });
|
|
1676
1971
|
}
|
|
1677
1972
|
logger.info("Cortex Memory plugin disabled successfully");
|
|
1973
|
+
logLifecycle("disable_success", { fallbackEnabled: registeredFallbackTools.length > 0 });
|
|
1678
1974
|
}
|
|
1679
1975
|
function registerFallbackTools() {
|
|
1680
1976
|
if (!api || !builtinMemory)
|
|
1681
1977
|
return;
|
|
1682
|
-
|
|
1978
|
+
registerToolCompat({
|
|
1683
1979
|
name: "search_memory",
|
|
1684
1980
|
description: "Search memory (using builtin system - Cortex Memory disabled)",
|
|
1685
1981
|
parameters: {
|
|
@@ -1691,10 +1987,10 @@ function registerFallbackTools() {
|
|
|
1691
1987
|
required: ["query"],
|
|
1692
1988
|
additionalProperties: false,
|
|
1693
1989
|
},
|
|
1694
|
-
execute: async ({ args, context }) => searchMemoryWithFallback(args, context),
|
|
1990
|
+
execute: async ({ args, context }) => searchMemoryWithFallback((args || {}), context),
|
|
1695
1991
|
});
|
|
1696
1992
|
registeredFallbackTools.push("search_memory");
|
|
1697
|
-
|
|
1993
|
+
registerToolCompat({
|
|
1698
1994
|
name: "store_event",
|
|
1699
1995
|
description: "Store event (using builtin system - Cortex Memory disabled)",
|
|
1700
1996
|
parameters: {
|
|
@@ -1705,10 +2001,10 @@ function registerFallbackTools() {
|
|
|
1705
2001
|
required: ["summary"],
|
|
1706
2002
|
additionalProperties: false,
|
|
1707
2003
|
},
|
|
1708
|
-
execute: async ({ args, context }) => storeEventWithFallback(args, context),
|
|
2004
|
+
execute: async ({ args, context }) => storeEventWithFallback((args || {}), context),
|
|
1709
2005
|
});
|
|
1710
2006
|
registeredFallbackTools.push("store_event");
|
|
1711
|
-
|
|
2007
|
+
registerToolCompat({
|
|
1712
2008
|
name: "cortex_memory_status",
|
|
1713
2009
|
description: "Get the current status of the Cortex Memory plugin",
|
|
1714
2010
|
parameters: {
|
|
@@ -1717,7 +2013,7 @@ function registerFallbackTools() {
|
|
|
1717
2013
|
required: [],
|
|
1718
2014
|
additionalProperties: false,
|
|
1719
2015
|
},
|
|
1720
|
-
execute: async ({ args, context }) => getPluginStatus(args, context),
|
|
2016
|
+
execute: async ({ args, context }) => getPluginStatus(args || {}, context),
|
|
1721
2017
|
});
|
|
1722
2018
|
registeredFallbackTools.push("cortex_memory_status");
|
|
1723
2019
|
}
|
|
@@ -1742,6 +2038,7 @@ function getStatus() {
|
|
|
1742
2038
|
}
|
|
1743
2039
|
async function unregister() {
|
|
1744
2040
|
logger.info("Unregistering Cortex Memory plugin...");
|
|
2041
|
+
logLifecycle("unregister_start");
|
|
1745
2042
|
stopConfigWatcher();
|
|
1746
2043
|
stopAutoReflectScheduler();
|
|
1747
2044
|
unregisterHooks();
|
|
@@ -1768,6 +2065,7 @@ async function unregister() {
|
|
|
1768
2065
|
stopAutoReflectScheduler();
|
|
1769
2066
|
configPath = null;
|
|
1770
2067
|
logger.info("Cortex Memory plugin unregistered successfully");
|
|
2068
|
+
logLifecycle("unregister_success");
|
|
1771
2069
|
}
|
|
1772
2070
|
function register(pluginApi, userConfig) {
|
|
1773
2071
|
if (isInitializing || isRegistered) {
|
|
@@ -1803,9 +2101,41 @@ function register(pluginApi, userConfig) {
|
|
|
1803
2101
|
dbPath: effectiveConfig.dbPath,
|
|
1804
2102
|
autoSync: effectiveConfig.autoSync ?? defaultConfig.autoSync,
|
|
1805
2103
|
autoReflect: effectiveConfig.autoReflect ?? defaultConfig.autoReflect,
|
|
2104
|
+
autoReflectIntervalMinutes: effectiveConfig.autoReflectIntervalMinutes ?? defaultConfig.autoReflectIntervalMinutes,
|
|
2105
|
+
readFusion: {
|
|
2106
|
+
enabled: effectiveConfig.readFusion?.enabled ?? defaultConfig.readFusion?.enabled,
|
|
2107
|
+
maxCandidates: effectiveConfig.readFusion?.maxCandidates ?? defaultConfig.readFusion?.maxCandidates,
|
|
2108
|
+
authoritative: effectiveConfig.readFusion?.authoritative ?? defaultConfig.readFusion?.authoritative,
|
|
2109
|
+
channelWeights: effectiveConfig.readFusion?.channelWeights ?? defaultConfig.readFusion?.channelWeights,
|
|
2110
|
+
channelTopK: effectiveConfig.readFusion?.channelTopK ?? defaultConfig.readFusion?.channelTopK,
|
|
2111
|
+
minLexicalHits: effectiveConfig.readFusion?.minLexicalHits ?? defaultConfig.readFusion?.minLexicalHits,
|
|
2112
|
+
minSemanticHits: effectiveConfig.readFusion?.minSemanticHits ?? defaultConfig.readFusion?.minSemanticHits,
|
|
2113
|
+
lengthNorm: {
|
|
2114
|
+
enabled: effectiveConfig.readFusion?.lengthNorm?.enabled ?? defaultConfig.readFusion?.lengthNorm?.enabled,
|
|
2115
|
+
pivotChars: effectiveConfig.readFusion?.lengthNorm?.pivotChars ?? defaultConfig.readFusion?.lengthNorm?.pivotChars,
|
|
2116
|
+
strength: effectiveConfig.readFusion?.lengthNorm?.strength ?? defaultConfig.readFusion?.lengthNorm?.strength,
|
|
2117
|
+
minFactor: effectiveConfig.readFusion?.lengthNorm?.minFactor ?? defaultConfig.readFusion?.lengthNorm?.minFactor,
|
|
2118
|
+
},
|
|
2119
|
+
},
|
|
2120
|
+
vectorChunking: {
|
|
2121
|
+
chunkSize: effectiveConfig.vectorChunking?.chunkSize ?? defaultConfig.vectorChunking?.chunkSize,
|
|
2122
|
+
chunkOverlap: effectiveConfig.vectorChunking?.chunkOverlap ?? defaultConfig.vectorChunking?.chunkOverlap,
|
|
2123
|
+
},
|
|
2124
|
+
memoryDecay: {
|
|
2125
|
+
enabled: effectiveConfig.memoryDecay?.enabled ?? defaultConfig.memoryDecay?.enabled,
|
|
2126
|
+
minFloor: effectiveConfig.memoryDecay?.minFloor ?? defaultConfig.memoryDecay?.minFloor,
|
|
2127
|
+
defaultHalfLifeDays: effectiveConfig.memoryDecay?.defaultHalfLifeDays ?? defaultConfig.memoryDecay?.defaultHalfLifeDays,
|
|
2128
|
+
halfLifeByEventType: effectiveConfig.memoryDecay?.halfLifeByEventType ?? defaultConfig.memoryDecay?.halfLifeByEventType,
|
|
2129
|
+
antiDecay: {
|
|
2130
|
+
enabled: effectiveConfig.memoryDecay?.antiDecay?.enabled ?? defaultConfig.memoryDecay?.antiDecay?.enabled,
|
|
2131
|
+
maxBoost: effectiveConfig.memoryDecay?.antiDecay?.maxBoost ?? defaultConfig.memoryDecay?.antiDecay?.maxBoost,
|
|
2132
|
+
hitWeight: effectiveConfig.memoryDecay?.antiDecay?.hitWeight ?? defaultConfig.memoryDecay?.antiDecay?.hitWeight,
|
|
2133
|
+
recentWindowDays: effectiveConfig.memoryDecay?.antiDecay?.recentWindowDays ?? defaultConfig.memoryDecay?.antiDecay?.recentWindowDays,
|
|
2134
|
+
},
|
|
2135
|
+
},
|
|
1806
2136
|
enabled: effectiveConfig.enabled ?? defaultConfig.enabled,
|
|
1807
2137
|
fallbackToBuiltin: effectiveConfig.fallbackToBuiltin ?? defaultConfig.fallbackToBuiltin,
|
|
1808
|
-
apiUrl: effectiveConfig.apiUrl ?? "http://
|
|
2138
|
+
apiUrl: effectiveConfig.apiUrl ?? "http://localhost:8765",
|
|
1809
2139
|
engineMode: "ts",
|
|
1810
2140
|
};
|
|
1811
2141
|
memoryEngine = null;
|
|
@@ -1840,6 +2170,11 @@ function register(pluginApi, userConfig) {
|
|
|
1840
2170
|
isRegistered = true;
|
|
1841
2171
|
logger.info("Cortex Memory plugin registered successfully");
|
|
1842
2172
|
logger.info(`Cortex Memory engine mode: ${resolveEngine().mode}`);
|
|
2173
|
+
logLifecycle("register_success", {
|
|
2174
|
+
engineMode: config.engineMode,
|
|
2175
|
+
enabled: isEnabled,
|
|
2176
|
+
hasBuiltinFallback: Boolean(builtinMemory),
|
|
2177
|
+
});
|
|
1843
2178
|
if (isEnabled) {
|
|
1844
2179
|
registerTools();
|
|
1845
2180
|
registerHooks();
|
|
@@ -1853,11 +2188,13 @@ function register(pluginApi, userConfig) {
|
|
|
1853
2188
|
logger.info("Falling back to builtin memory");
|
|
1854
2189
|
isEnabled = false;
|
|
1855
2190
|
registerFallbackTools();
|
|
2191
|
+
logLifecycle("fallback_after_init_error", { fallbackTools: registeredFallbackTools.length, error: message });
|
|
1856
2192
|
}
|
|
1857
2193
|
});
|
|
1858
2194
|
}
|
|
1859
2195
|
else if (config?.fallbackToBuiltin && builtinMemory) {
|
|
1860
2196
|
registerFallbackTools();
|
|
2197
|
+
logLifecycle("fallback_registered_on_start", { fallbackTools: registeredFallbackTools.length });
|
|
1861
2198
|
}
|
|
1862
2199
|
}
|
|
1863
2200
|
async function initializeAsync() {
|