mr-memory 2.2.0 → 2.3.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 (2) hide show
  1. package/index.ts +74 -3
  2. package/package.json +1 -1
package/index.ts CHANGED
@@ -147,8 +147,81 @@ const memoryRouterPlugin = {
147
147
  if (memoryKey) {
148
148
  // Track whether we've already fired for this prompt (dedup double-fire)
149
149
  let lastPreparedPrompt = "";
150
+ // Track whether before_prompt_build already handled the first call in this run
151
+ let promptBuildFiredThisRun = false;
152
+
153
+ // ── llm_input: fires on EVERY LLM call (tool iterations, cron, sub-agents)
154
+ // On stock OpenClaw, the return value is ignored (fire-and-forget).
155
+ // When PR #24122 merges, OpenClaw will use the returned prependContext.
156
+ // This gives forward compatibility — no plugin update needed.
157
+ api.on("llm_input", async (event, ctx) => {
158
+ // Skip the first call — before_prompt_build already handled it
159
+ // (before_prompt_build includes workspace+tools+skills for accurate billing)
160
+ if (promptBuildFiredThisRun) {
161
+ promptBuildFiredThisRun = false; // reset so subsequent calls go through
162
+ return;
163
+ }
164
+
165
+ try {
166
+ const prompt = event.prompt;
167
+ if (prompt === lastPreparedPrompt && lastPreparedPrompt !== "") return;
168
+ lastPreparedPrompt = prompt;
169
+
170
+ // Build lightweight context (no workspace/tools — just history + prompt)
171
+ const contextPayload: Array<{ role: string; content: string }> = [];
172
+ if (event.historyMessages && Array.isArray(event.historyMessages)) {
173
+ for (const msg of event.historyMessages) {
174
+ const m = msg as { role?: string; content?: unknown };
175
+ if (!m.role) continue;
176
+ let text = "";
177
+ if (typeof m.content === "string") text = m.content;
178
+ else if (Array.isArray(m.content)) {
179
+ text = (m.content as Array<{ type?: string; text?: string }>)
180
+ .filter(b => b.type === "text" && b.text)
181
+ .map(b => b.text!)
182
+ .join("\n");
183
+ }
184
+ if (text) contextPayload.push({ role: m.role, content: text });
185
+ }
186
+ }
187
+ contextPayload.push({ role: "user", content: prompt });
188
+
189
+
190
+ const res = await fetch(`${endpoint}/v1/memory/prepare`, {
191
+ method: "POST",
192
+ headers: {
193
+ "Content-Type": "application/json",
194
+ Authorization: `Bearer ${memoryKey}`,
195
+ },
196
+ body: JSON.stringify({
197
+ messages: contextPayload,
198
+ density,
199
+
200
+ }),
201
+ });
202
+
203
+ if (!res.ok) return;
204
+
205
+ const data = (await res.json()) as {
206
+ context?: string;
207
+ memories_found?: number;
208
+ tokens_billed?: number;
209
+ };
210
+
211
+ if (data.context) {
212
+ api.logger.info?.(
213
+ `memoryrouter: injected ${data.memories_found || 0} memories on tool iteration (${data.tokens_billed || 0} tokens billed)`,
214
+ );
215
+ return { prependContext: data.context };
216
+ }
217
+ } catch {
218
+ // Silent fail on tool iterations — don't block the agent
219
+ }
220
+ });
150
221
 
222
+ // ── before_prompt_build: fires once per run (primary, includes full billing context)
151
223
  api.on("before_prompt_build", async (event, ctx) => {
224
+ promptBuildFiredThisRun = true;
152
225
  try {
153
226
  const prompt = event.prompt;
154
227
 
@@ -208,8 +281,6 @@ const memoryRouterPlugin = {
208
281
  contextPayload.push({ role: "user", content: prompt });
209
282
 
210
283
  // 4. Call /v1/memory/prepare
211
- const densityMap: Record<string, number> = { low: 40, high: 80, xhigh: 160 };
212
- const contextLimit = densityMap[density] || 80;
213
284
 
214
285
  const res = await fetch(`${endpoint}/v1/memory/prepare`, {
215
286
  method: "POST",
@@ -220,7 +291,7 @@ const memoryRouterPlugin = {
220
291
  body: JSON.stringify({
221
292
  messages: contextPayload,
222
293
  density,
223
- context_limit: contextLimit,
294
+
224
295
  }),
225
296
  });
226
297
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mr-memory",
3
- "version": "2.2.0",
3
+ "version": "2.3.1",
4
4
  "description": "MemoryRouter persistent memory plugin for OpenClaw — your AI remembers every conversation",
5
5
  "type": "module",
6
6
  "files": [