mr-memory 2.9.13 → 2.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.ts +76 -5
- package/package.json +1 -1
package/index.ts
CHANGED
|
@@ -48,6 +48,63 @@ function stripOldMemory(text: string): string {
|
|
|
48
48
|
return text.replace(MEMORY_TAG_RE, "").replace(LEGACY_TAG_RE, "").trim();
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
+
// ── Ingest sanitization: strip system noise so only real conversations get stored
|
|
52
|
+
// Patterns that indicate system-generated messages (not user conversations)
|
|
53
|
+
const SYSTEM_NOISE_PATTERNS = [
|
|
54
|
+
// Heartbeat prompts and responses
|
|
55
|
+
/^Read HEARTBEAT\.md if it exists/,
|
|
56
|
+
/^HEARTBEAT_OK\s*$/,
|
|
57
|
+
// Pre-compaction flush prompts
|
|
58
|
+
/^Pre-compaction memory flush\./,
|
|
59
|
+
// Post-compaction audit warnings
|
|
60
|
+
/⚠️ Post-Compaction Audit:/,
|
|
61
|
+
// Silent reply ack
|
|
62
|
+
/^NO_REPLY\s*$/,
|
|
63
|
+
// Agent abort notices
|
|
64
|
+
/^Note: The previous agent run was aborted/,
|
|
65
|
+
// Queued message headers
|
|
66
|
+
/^\[Queued messages while agent was busy\]/,
|
|
67
|
+
// Media reference placeholders
|
|
68
|
+
/^\[media reference removed\]\s*$/,
|
|
69
|
+
// System event timestamps (cron fires, exec failures, etc.)
|
|
70
|
+
/^System: \[\d{4}-\d{2}-\d{2}/,
|
|
71
|
+
/^\[\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} [A-Z]{2,4}\] ⚠️/,
|
|
72
|
+
// Memory flush with date pattern
|
|
73
|
+
/^Store durable memories now/,
|
|
74
|
+
// Current time system lines (injected by OpenClaw into system events)
|
|
75
|
+
/^Current time: .+\(America\//,
|
|
76
|
+
];
|
|
77
|
+
|
|
78
|
+
/** Strip OpenClaw envelope metadata from user messages */
|
|
79
|
+
const ENVELOPE_METADATA_RE = /Conversation info \(untrusted metadata\):\s*```json\s*\{[^}]*\}\s*```\s*/g;
|
|
80
|
+
const SENDER_METADATA_RE = /Sender \(untrusted metadata\):\s*```json\s*\{[^}]*\}\s*```\s*/g;
|
|
81
|
+
const REPLY_CONTEXT_RE = /Replied message \(untrusted, for context\):\s*```json\s*\{[^}]*\}\s*```\s*/g;
|
|
82
|
+
const MEMORY_INSTRUCTION_RE = /The above are retrieved memories from past conversations[^\n]*\n*/g;
|
|
83
|
+
const IMPORTANT_MEMORY_RE = /IMPORTANT: The above (?:are retrieved memories|block contains retrieved memories)[^\n]*\n*/g;
|
|
84
|
+
|
|
85
|
+
/** Sanitize text before storing in memory — removes system noise and envelope metadata */
|
|
86
|
+
function sanitizeForIngest(text: string): string {
|
|
87
|
+
// 1. Strip our own memory injection wrapper (already exists as stripOldMemory)
|
|
88
|
+
let cleaned = stripOldMemory(text);
|
|
89
|
+
// 2. Strip envelope metadata blocks
|
|
90
|
+
cleaned = cleaned
|
|
91
|
+
.replace(ENVELOPE_METADATA_RE, "")
|
|
92
|
+
.replace(SENDER_METADATA_RE, "")
|
|
93
|
+
.replace(REPLY_CONTEXT_RE, "")
|
|
94
|
+
.replace(MEMORY_INSTRUCTION_RE, "")
|
|
95
|
+
.replace(IMPORTANT_MEMORY_RE, "");
|
|
96
|
+
// 3. Collapse excessive whitespace from removals
|
|
97
|
+
cleaned = cleaned.replace(/\n{3,}/g, "\n\n").trim();
|
|
98
|
+
return cleaned;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/** Check if a message is system noise that should not be stored */
|
|
102
|
+
function isSystemNoise(text: string): boolean {
|
|
103
|
+
const trimmed = text.trim();
|
|
104
|
+
if (!trimmed) return true;
|
|
105
|
+
return SYSTEM_NOISE_PATTERNS.some(pattern => pattern.test(trimmed));
|
|
106
|
+
}
|
|
107
|
+
|
|
51
108
|
// Workspace files OpenClaw loads into the system prompt
|
|
52
109
|
const WORKSPACE_FILES = [
|
|
53
110
|
"IDENTITY.md", "USER.md", "MEMORY.md", "HEARTBEAT.md",
|
|
@@ -413,11 +470,17 @@ const memoryRouterPlugin = {
|
|
|
413
470
|
|
|
414
471
|
const toStore: Array<{ role: string; content: string }> = [];
|
|
415
472
|
|
|
416
|
-
// Add the user message
|
|
473
|
+
// Add the user message (sanitized)
|
|
417
474
|
if (lastUserIdx >= 0) {
|
|
418
475
|
const userMsg = msgs[lastUserIdx] as { content?: unknown };
|
|
419
|
-
|
|
420
|
-
if (userText)
|
|
476
|
+
let userText = extractText(userMsg.content);
|
|
477
|
+
if (userText) {
|
|
478
|
+
// Sanitize: strip memory injections, envelope metadata, and system noise
|
|
479
|
+
userText = sanitizeForIngest(stripMediaReferences(userText));
|
|
480
|
+
if (userText && !isSystemNoise(userText)) {
|
|
481
|
+
toStore.push({ role: "user", content: userText });
|
|
482
|
+
}
|
|
483
|
+
}
|
|
421
484
|
}
|
|
422
485
|
|
|
423
486
|
// Collect ALL assistant messages after the last user message
|
|
@@ -431,10 +494,18 @@ const memoryRouterPlugin = {
|
|
|
431
494
|
}
|
|
432
495
|
if (assistantParts.length > 0) {
|
|
433
496
|
// Strip media refs so image paths don't get stored and re-injected
|
|
434
|
-
|
|
497
|
+
let assistantText = stripMediaReferences(assistantParts.join("\n\n"));
|
|
498
|
+
// Skip storing system noise responses (HEARTBEAT_OK, NO_REPLY, etc.)
|
|
499
|
+
if (!isSystemNoise(assistantText)) {
|
|
500
|
+
toStore.push({ role: "assistant", content: assistantText });
|
|
501
|
+
}
|
|
435
502
|
}
|
|
436
503
|
|
|
437
|
-
if (
|
|
504
|
+
// Skip if nothing meaningful to store (both messages were system noise)
|
|
505
|
+
if (toStore.length === 0) {
|
|
506
|
+
log("memoryrouter: skipped ingest — system noise filtered out");
|
|
507
|
+
return;
|
|
508
|
+
}
|
|
438
509
|
|
|
439
510
|
// Await the fetch so OpenClaw's runVoidHook keeps the event loop alive.
|
|
440
511
|
try {
|