@eleboucher/pi-memini 0.5.7 → 0.5.8
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/dist/index.js +33 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -348,6 +348,28 @@ export default function meminiExtension(pi) {
|
|
|
348
348
|
// Assistant message ids already captured, so a re-fired agent_end never writes
|
|
349
349
|
// a duplicate turn.
|
|
350
350
|
const captured = new Set();
|
|
351
|
+
// Memory ids each session has already been shown (mirrors the openclaw
|
|
352
|
+
// plugin): the recall injection is a persistent context message, so
|
|
353
|
+
// re-injecting an unchanged match every turn stacks identical blocks in the
|
|
354
|
+
// prompt. Bounded so long-lived hosts can't grow the map without limit.
|
|
355
|
+
const injectedBySession = new Map();
|
|
356
|
+
const MAX_TRACKED_SESSIONS = 200;
|
|
357
|
+
const rememberInjected = (session, ids) => {
|
|
358
|
+
let seen = injectedBySession.get(session);
|
|
359
|
+
if (!seen) {
|
|
360
|
+
seen = new Set();
|
|
361
|
+
injectedBySession.set(session, seen);
|
|
362
|
+
while (injectedBySession.size > MAX_TRACKED_SESSIONS) {
|
|
363
|
+
const oldest = injectedBySession.keys().next().value;
|
|
364
|
+
if (oldest === undefined)
|
|
365
|
+
break;
|
|
366
|
+
injectedBySession.delete(oldest);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
for (const id of ids)
|
|
370
|
+
if (id)
|
|
371
|
+
seen.add(id);
|
|
372
|
+
};
|
|
351
373
|
// Recall before the turn: search for the user's prompt and inject the matches
|
|
352
374
|
// as a persistent context message. Buffer the prompt for capture at agent_end.
|
|
353
375
|
pi.on("before_agent_start", async (event, ctx) => {
|
|
@@ -366,7 +388,14 @@ export default function meminiExtension(pi) {
|
|
|
366
388
|
body.min_score = cfg.recall_min_score;
|
|
367
389
|
const result = await client.postJson("/v1/search", body);
|
|
368
390
|
const floor = cfg.recall_min_score > 0 ? cfg.recall_min_score : 0;
|
|
369
|
-
|
|
391
|
+
let rawHits = Array.isArray(result?.results) ? result.results : [];
|
|
392
|
+
// Suppress memories this session has already been shown — the injected
|
|
393
|
+
// message persists in context, so a repeat adds nothing but noise.
|
|
394
|
+
if (sid) {
|
|
395
|
+
const seen = injectedBySession.get(sid);
|
|
396
|
+
if (seen?.size)
|
|
397
|
+
rawHits = rawHits.filter((r) => !seen.has(r?.memory?.id));
|
|
398
|
+
}
|
|
370
399
|
const filtered = floor > 0
|
|
371
400
|
? rawHits.filter((r) => (typeof r?.score === "number" ? r.score : 0) >= floor)
|
|
372
401
|
: rawHits;
|
|
@@ -376,6 +405,9 @@ export default function meminiExtension(pi) {
|
|
|
376
405
|
const fit = fitByTokens(hits, cfg.recall_max_tokens);
|
|
377
406
|
if (fit.items.length === 0)
|
|
378
407
|
return;
|
|
408
|
+
if (sid) {
|
|
409
|
+
rememberInjected(sid, filtered.map((r) => r?.memory?.id).filter(Boolean));
|
|
410
|
+
}
|
|
379
411
|
const lines = [
|
|
380
412
|
"Relevant long-term memory from memini (background context — prefer " +
|
|
381
413
|
"current workspace state and the user's instructions):",
|