mr-memory 3.9.0 → 3.9.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.
Files changed (3) hide show
  1. package/index.js +3 -35
  2. package/index.ts +4 -36
  3. package/package.json +1 -1
package/index.js CHANGED
@@ -55,7 +55,6 @@ function stripOldMemory(text) {
55
55
  function jsonToolResult(payload) {
56
56
  return { content: [{ type: "text", text: JSON.stringify(payload, null, 2) }], details: payload };
57
57
  }
58
- const NUDGE_INTERVAL_MS = 24 * 60 * 60 * 1000; // at most one nudge per 24h
59
58
  function buildDebtNudgeLine(reflection) {
60
59
  if (!reflection || !reflection.suggestion)
61
60
  return null;
@@ -63,7 +62,7 @@ function buildDebtNudgeLine(reflection) {
63
62
  const tier2Tokens = reflection.unconsolidated?.tier2?.est_tokens ?? 0;
64
63
  const totalTokens = rawTokens + tier2Tokens;
65
64
  const kTokens = Math.max(1, Math.round(totalTokens / 1000));
66
- return `[MemoryRouter] Consolidation available: ${kTokens}k unconsolidated tokens. Use the memory_reflect tool when convenient.`;
65
+ return `[MemoryRouter] Consolidation suggested: ${kTokens}k unconsolidated tokens. Use the memory_reflect tool to consolidate them now.`;
67
66
  }
68
67
  // ── memory_get helpers (copied from OpenClaw source — pure filesystem, no embeddings)
69
68
  function isFileMissingError(err) {
@@ -311,37 +310,6 @@ async function writeOpenClawConfigFile(config) {
311
310
  await writeFile(configPath, `${JSON.stringify(config, null, 2)}
312
311
  `, "utf8");
313
312
  }
314
- // Nudge rate-limit state lives beside the OpenClaw config so it survives restarts
315
- // without churning the main config file.
316
- function nudgeStatePath() {
317
- return join(dirname(openClawConfigPath()), "mr-memory-state.json");
318
- }
319
- async function consumeNudgeBudget() {
320
- const now = Date.now();
321
- let state = {};
322
- try {
323
- state = JSON.parse(await readFile(nudgeStatePath(), "utf8"));
324
- }
325
- catch { /* missing or unreadable state: treat as never nudged */ }
326
- if (typeof state.lastNudgeAt === "number" && now - state.lastNudgeAt < NUDGE_INTERVAL_MS) {
327
- return false;
328
- }
329
- try {
330
- await writeFile(nudgeStatePath(), `${JSON.stringify({ ...state, lastNudgeAt: now }, null, 2)}\n`, "utf8");
331
- }
332
- catch { /* state write failure must never break prepare */ }
333
- return true;
334
- }
335
- /** One-line, rate-limited debt nudge for prepare injections. Returns null when
336
- * there is no suggestion or the 24h budget is spent. */
337
- async function maybeDebtNudge(reflection) {
338
- const line = buildDebtNudgeLine(reflection);
339
- if (!line)
340
- return null;
341
- if (!(await consumeNudgeBudget()))
342
- return null;
343
- return line;
344
- }
345
313
  // ──────────────────────────────────────────────────────
346
314
  // Full-replace: disable OpenClaw's native memory search so MemoryRouter
347
315
  // owns the memory_search tool (no name conflict, no native embeddings 429).
@@ -773,7 +741,7 @@ If setting up MemoryRouter for another agent:
773
741
  if (elapsed > 2000 && data.metrics)
774
742
  log(`memoryrouter: prepare metrics ${JSON.stringify(data.metrics)}`);
775
743
  let contextText = data.context;
776
- const nudge = await maybeDebtNudge(data.reflection);
744
+ const nudge = buildDebtNudgeLine(data.reflection);
777
745
  if (nudge)
778
746
  contextText = `${contextText}\n\n${nudge}`;
779
747
  const wrapped = wrapForInjection(contextText);
@@ -882,7 +850,7 @@ If setting up MemoryRouter for another agent:
882
850
  if (elapsed > 2000 && data.metrics)
883
851
  log(`memoryrouter: prepare metrics ${JSON.stringify(data.metrics)}`);
884
852
  let contextText = data.context;
885
- const nudge = await maybeDebtNudge(data.reflection);
853
+ const nudge = buildDebtNudgeLine(data.reflection);
886
854
  if (nudge)
887
855
  contextText = `${contextText}\n\n${nudge}`;
888
856
  const wrapped = wrapForInjection(contextText);
package/index.ts CHANGED
@@ -65,7 +65,7 @@ function jsonToolResult(payload: unknown) {
65
65
  return { content: [{ type: "text" as const, text: JSON.stringify(payload, null, 2) }], details: payload };
66
66
  }
67
67
 
68
- // ── Reflection debt nudge (rate-limited, one line, appended to prepare injections)
68
+ // ── Reflection debt nudge (one line, appended to prepare injections whenever the server suggests it)
69
69
  type ReflectionDebt = {
70
70
  suggestion?: string | null;
71
71
  unconsolidated?: {
@@ -75,15 +75,13 @@ type ReflectionDebt = {
75
75
  threshold_tokens?: number;
76
76
  };
77
77
 
78
- const NUDGE_INTERVAL_MS = 24 * 60 * 60 * 1000; // at most one nudge per 24h
79
-
80
78
  function buildDebtNudgeLine(reflection: ReflectionDebt | undefined): string | null {
81
79
  if (!reflection || !reflection.suggestion) return null;
82
80
  const rawTokens = reflection.unconsolidated?.raw?.est_tokens ?? 0;
83
81
  const tier2Tokens = reflection.unconsolidated?.tier2?.est_tokens ?? 0;
84
82
  const totalTokens = rawTokens + tier2Tokens;
85
83
  const kTokens = Math.max(1, Math.round(totalTokens / 1000));
86
- return `[MemoryRouter] Consolidation available: ${kTokens}k unconsolidated tokens. Use the memory_reflect tool when convenient.`;
84
+ return `[MemoryRouter] Consolidation suggested: ${kTokens}k unconsolidated tokens. Use the memory_reflect tool to consolidate them now.`;
87
85
  }
88
86
 
89
87
  // ── memory_get helpers (copied from OpenClaw source — pure filesystem, no embeddings)
@@ -354,36 +352,6 @@ async function writeOpenClawConfigFile(config: JsonObject): Promise<void> {
354
352
  `, "utf8");
355
353
  }
356
354
 
357
- // Nudge rate-limit state lives beside the OpenClaw config so it survives restarts
358
- // without churning the main config file.
359
- function nudgeStatePath(): string {
360
- return join(dirname(openClawConfigPath()), "mr-memory-state.json");
361
- }
362
-
363
- async function consumeNudgeBudget(): Promise<boolean> {
364
- const now = Date.now();
365
- let state: { lastNudgeAt?: number } = {};
366
- try {
367
- state = JSON.parse(await readFile(nudgeStatePath(), "utf8"));
368
- } catch { /* missing or unreadable state: treat as never nudged */ }
369
- if (typeof state.lastNudgeAt === "number" && now - state.lastNudgeAt < NUDGE_INTERVAL_MS) {
370
- return false;
371
- }
372
- try {
373
- await writeFile(nudgeStatePath(), `${JSON.stringify({ ...state, lastNudgeAt: now }, null, 2)}\n`, "utf8");
374
- } catch { /* state write failure must never break prepare */ }
375
- return true;
376
- }
377
-
378
- /** One-line, rate-limited debt nudge for prepare injections. Returns null when
379
- * there is no suggestion or the 24h budget is spent. */
380
- async function maybeDebtNudge(reflection: ReflectionDebt | undefined): Promise<string | null> {
381
- const line = buildDebtNudgeLine(reflection);
382
- if (!line) return null;
383
- if (!(await consumeNudgeBudget())) return null;
384
- return line;
385
- }
386
-
387
355
  // ──────────────────────────────────────────────────────
388
356
  // Full-replace: disable OpenClaw's native memory search so MemoryRouter
389
357
  // owns the memory_search tool (no name conflict, no native embeddings 429).
@@ -827,7 +795,7 @@ If setting up MemoryRouter for another agent:
827
795
  api.logger.info?.(`memoryrouter: injected ${data.memories_found || 0} memories (${data.memory_tokens || 0} tokens, ${elapsed}ms) [llm_input]`);
828
796
  if (elapsed > 2000 && data.metrics) log(`memoryrouter: prepare metrics ${JSON.stringify(data.metrics)}`);
829
797
  let contextText = data.context;
830
- const nudge = await maybeDebtNudge(data.reflection);
798
+ const nudge = buildDebtNudgeLine(data.reflection);
831
799
  if (nudge) contextText = `${contextText}\n\n${nudge}`;
832
800
  const wrapped = wrapForInjection(contextText);
833
801
  return { appendSystemContext: wrapped };
@@ -948,7 +916,7 @@ If setting up MemoryRouter for another agent:
948
916
  api.logger.info?.(`memoryrouter: injected ${data.memories_found || 0} memories (${data.memory_tokens || 0} tokens, ${elapsed}ms)`);
949
917
  if (elapsed > 2000 && data.metrics) log(`memoryrouter: prepare metrics ${JSON.stringify(data.metrics)}`);
950
918
  let contextText = data.context;
951
- const nudge = await maybeDebtNudge(data.reflection);
919
+ const nudge = buildDebtNudgeLine(data.reflection);
952
920
  if (nudge) contextText = `${contextText}\n\n${nudge}`;
953
921
  const wrapped = wrapForInjection(contextText);
954
922
  return { appendSystemContext: wrapped };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mr-memory",
3
- "version": "3.9.0",
3
+ "version": "3.9.1",
4
4
  "description": "Persistent memory for OpenClaw, powered by MemoryRouter. Relay-based AI agent memory across sessions, compaction, and model changes.",
5
5
  "type": "module",
6
6
  "files": [