mr-memory 2.5.2 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.ts +22 -7
- package/package.json +1 -1
package/index.ts
CHANGED
|
@@ -15,6 +15,19 @@ import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
|
|
|
15
15
|
|
|
16
16
|
const DEFAULT_ENDPOINT = "https://api.memoryrouter.ai";
|
|
17
17
|
|
|
18
|
+
/** Wrap raw memory context in XML tags with a strong instruction */
|
|
19
|
+
function wrapMemoryContext(context: string): string {
|
|
20
|
+
return `<memory_context>\n${context}\n</memory_context>\n\nThe above are retrieved memories from past conversations — not current events. Reference them as background context with appropriate temporal framing. Do not treat them as part of the current message or present moment.`;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** Strip previous memory injections from message text to prevent stacking.
|
|
24
|
+
* prependContext persists in conversation history — without stripping,
|
|
25
|
+
* each turn accumulates another full injection (~20K tokens). */
|
|
26
|
+
const MEMORY_TAG_RE = /<memory_context>[\s\S]*?<\/memory_context>\s*The above are retrieved memories from past conversations[^\n]*\n*/g;
|
|
27
|
+
function stripOldMemory(text: string): string {
|
|
28
|
+
return text.replace(MEMORY_TAG_RE, "").trim();
|
|
29
|
+
}
|
|
30
|
+
|
|
18
31
|
// Workspace files OpenClaw loads into the system prompt
|
|
19
32
|
const WORKSPACE_FILES = [
|
|
20
33
|
"IDENTITY.md", "USER.md", "MEMORY.md", "HEARTBEAT.md",
|
|
@@ -181,10 +194,11 @@ const memoryRouterPlugin = {
|
|
|
181
194
|
.map(b => b.text!)
|
|
182
195
|
.join("\n");
|
|
183
196
|
}
|
|
184
|
-
|
|
197
|
+
// Strip old memory injections to prevent stacking
|
|
198
|
+
if (text) contextPayload.push({ role: m.role, content: m.role === "user" ? stripOldMemory(text) : text });
|
|
185
199
|
}
|
|
186
200
|
}
|
|
187
|
-
contextPayload.push({ role: "user", content: prompt });
|
|
201
|
+
contextPayload.push({ role: "user", content: stripOldMemory(prompt) });
|
|
188
202
|
|
|
189
203
|
|
|
190
204
|
const res = await fetch(`${endpoint}/v1/memory/prepare`, {
|
|
@@ -213,7 +227,7 @@ const memoryRouterPlugin = {
|
|
|
213
227
|
api.logger.info?.(
|
|
214
228
|
`memoryrouter: injected ${data.memories_found || 0} memories on tool iteration (${data.tokens_billed || 0} tokens billed)`,
|
|
215
229
|
);
|
|
216
|
-
return { prependContext: data.context };
|
|
230
|
+
return { prependContext: wrapMemoryContext(data.context) };
|
|
217
231
|
}
|
|
218
232
|
} catch {
|
|
219
233
|
// Silent fail on tool iterations — don't block the agent
|
|
@@ -271,15 +285,16 @@ const memoryRouterPlugin = {
|
|
|
271
285
|
}
|
|
272
286
|
|
|
273
287
|
if (text) {
|
|
274
|
-
|
|
288
|
+
// Strip old memory injections to prevent stacking
|
|
289
|
+
contextPayload.push({ role: m.role, content: m.role === "user" ? stripOldMemory(text) : text });
|
|
275
290
|
} else {
|
|
276
291
|
skipped++;
|
|
277
292
|
}
|
|
278
293
|
}
|
|
279
294
|
}
|
|
280
295
|
|
|
281
|
-
// Add current user prompt
|
|
282
|
-
contextPayload.push({ role: "user", content: prompt });
|
|
296
|
+
// Add current user prompt (strip any residual memory tags)
|
|
297
|
+
contextPayload.push({ role: "user", content: stripOldMemory(prompt) });
|
|
283
298
|
|
|
284
299
|
// 4. Call /v1/memory/prepare
|
|
285
300
|
|
|
@@ -312,7 +327,7 @@ const memoryRouterPlugin = {
|
|
|
312
327
|
api.logger.info?.(
|
|
313
328
|
`memoryrouter: injected ${data.memories_found || 0} memories (${data.tokens_billed || 0} tokens billed)`,
|
|
314
329
|
);
|
|
315
|
-
return { prependContext: data.context };
|
|
330
|
+
return { prependContext: wrapMemoryContext(data.context) };
|
|
316
331
|
}
|
|
317
332
|
} catch (err) {
|
|
318
333
|
api.logger.warn?.(
|