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.
- package/index.ts +74 -3
- 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
|
-
|
|
294
|
+
|
|
224
295
|
}),
|
|
225
296
|
});
|
|
226
297
|
|