openclaw-memory-alibaba-local 1.0.9 → 1.0.11
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 +49 -31
- package/package.json +1 -1
- package/prompts.ts +7 -5
package/index.ts
CHANGED
|
@@ -843,47 +843,60 @@ async function extractWorldImageWithLLM(
|
|
|
843
843
|
}>;
|
|
844
844
|
};
|
|
845
845
|
const list = Array.isArray(parsed.actions) ? parsed.actions : [];
|
|
846
|
-
|
|
846
|
+
// Per-index: accumulate deletes separately from the final action (insert/update/skip)
|
|
847
|
+
const deleteMap = new Map<number, WorldImageAction[]>(); // delete actions per index
|
|
848
|
+
const finalMap = new Map<number, WorldImageAction>(); // final action per index (insert/update/skip)
|
|
847
849
|
// Default: insert for each index
|
|
848
850
|
for (let i = 0; i < newItems.length; i++) {
|
|
849
|
-
|
|
851
|
+
finalMap.set(i, {
|
|
850
852
|
action: "insert" as const,
|
|
851
853
|
text: newItems[i]!.text,
|
|
852
854
|
importance: newItems[i]!.importance,
|
|
853
|
-
}
|
|
855
|
+
});
|
|
854
856
|
}
|
|
855
857
|
|
|
856
858
|
for (const a of list) {
|
|
857
859
|
const idx = typeof a.index === "number" ? a.index : -1;
|
|
858
860
|
if (idx < 0 || idx >= newItems.length) continue;
|
|
859
861
|
|
|
860
|
-
if (a.action === "
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
862
|
+
if (a.action === "delete" && typeof a.memoryId === "string" && existingIdSet.has(a.memoryId)) {
|
|
863
|
+
// Accumulate deletes — they don't replace the final action
|
|
864
|
+
const dels = deleteMap.get(idx) ?? [];
|
|
865
|
+
dels.push({ action: "delete", memoryId: a.memoryId });
|
|
866
|
+
deleteMap.set(idx, dels);
|
|
867
|
+
} else if (a.action === "skip") {
|
|
868
|
+
finalMap.set(idx, { action: "skip" });
|
|
865
869
|
} else if (a.action === "update" && typeof a.memoryId === "string" && existingIdSet.has(a.memoryId)) {
|
|
866
870
|
const text = typeof a.text === "string" ? a.text.trim() : "";
|
|
867
871
|
if (text.length < 10) continue;
|
|
868
|
-
|
|
872
|
+
finalMap.set(idx, {
|
|
869
873
|
action: "update",
|
|
870
874
|
memoryId: a.memoryId,
|
|
871
875
|
text,
|
|
872
876
|
importance: clampImportance(a.importance ?? newItems[idx]!.importance),
|
|
873
|
-
}
|
|
877
|
+
});
|
|
874
878
|
} else if (a.action === "insert") {
|
|
875
879
|
const text = typeof a.text === "string" ? a.text.trim() : "";
|
|
876
880
|
const finalText = text.length >= 10 ? text : newItems[idx]!.text;
|
|
877
|
-
|
|
881
|
+
finalMap.set(idx, {
|
|
878
882
|
action: "insert",
|
|
879
883
|
text: finalText,
|
|
880
884
|
importance: clampImportance(a.importance ?? newItems[idx]!.importance),
|
|
881
|
-
}
|
|
885
|
+
});
|
|
882
886
|
}
|
|
883
887
|
}
|
|
888
|
+
// Assemble: deletes first, then final action per index
|
|
884
889
|
const result: WorldImageAction[] = [];
|
|
885
890
|
for (let i = 0; i < newItems.length; i++) {
|
|
886
|
-
|
|
891
|
+
const dels = deleteMap.get(i);
|
|
892
|
+
const final = finalMap.get(i);
|
|
893
|
+
// If SKIP + deletes for same index: honor SKIP (don't delete), per user rule
|
|
894
|
+
if (final?.action === "skip") {
|
|
895
|
+
result.push(final);
|
|
896
|
+
} else {
|
|
897
|
+
if (dels) result.push(...dels);
|
|
898
|
+
if (final) result.push(final);
|
|
899
|
+
}
|
|
887
900
|
}
|
|
888
901
|
return result;
|
|
889
902
|
} catch (err: unknown) {
|
|
@@ -1337,6 +1350,7 @@ async function captureUserMemoryFromInboundTexts(
|
|
|
1337
1350
|
|
|
1338
1351
|
// 4. Execute actions
|
|
1339
1352
|
let insertCount = 0;
|
|
1353
|
+
let deleteCount = 0;
|
|
1340
1354
|
for (const action of worldActions) {
|
|
1341
1355
|
if (action.action === "skip") continue;
|
|
1342
1356
|
|
|
@@ -1344,6 +1358,7 @@ async function captureUserMemoryFromInboundTexts(
|
|
|
1344
1358
|
const hit = existingCandidates.find((c) => c.entry.id === action.memoryId);
|
|
1345
1359
|
if (hit) {
|
|
1346
1360
|
await deleteSimilarLogicalMemory(db, agentId, hit.entry.sessionId, hit);
|
|
1361
|
+
deleteCount++;
|
|
1347
1362
|
}
|
|
1348
1363
|
continue;
|
|
1349
1364
|
}
|
|
@@ -1352,6 +1367,7 @@ async function captureUserMemoryFromInboundTexts(
|
|
|
1352
1367
|
const hit = existingCandidates.find((c) => c.entry.id === action.memoryId);
|
|
1353
1368
|
if (hit) {
|
|
1354
1369
|
await deleteSimilarLogicalMemory(db, agentId, hit.entry.sessionId, hit);
|
|
1370
|
+
deleteCount++;
|
|
1355
1371
|
}
|
|
1356
1372
|
const { vectors } = await backend.encodeForStorage(action.text);
|
|
1357
1373
|
const rows = buildChunkRows(
|
|
@@ -1373,7 +1389,8 @@ async function captureUserMemoryFromInboundTexts(
|
|
|
1373
1389
|
insertCount++;
|
|
1374
1390
|
}
|
|
1375
1391
|
}
|
|
1376
|
-
|
|
1392
|
+
|
|
1393
|
+
console.log(`[openclaw-memory-alibaba-local] worldImageExtraction done: ${worldActions.length} actions, ${insertCount} stored, ${deleteCount} deleted`);
|
|
1377
1394
|
|
|
1378
1395
|
// 5. World fact LRU GC: every 10 insertions
|
|
1379
1396
|
if (insertCount > 0) {
|
|
@@ -1597,13 +1614,11 @@ function buildChunkRows(
|
|
|
1597
1614
|
async function deleteSimilarLogicalMemory(
|
|
1598
1615
|
db: MemoryDB,
|
|
1599
1616
|
agentId: string,
|
|
1600
|
-
|
|
1617
|
+
_sessionId: string | null | undefined,
|
|
1601
1618
|
hit: MemorySearchResult,
|
|
1602
1619
|
): Promise<void> {
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
await db.deleteByAgentSessionCategoryText(agentId, sessionId, hit.entry.category, hit.entry.text);
|
|
1606
|
-
await db.delete(agentId, hit.entry.id).catch(() => {});
|
|
1620
|
+
console.log(`[openclaw-memory-alibaba-local] deleteSimilarLogicalMemory id=${hit.entry.id} agentId=${agentId} text=${hit.entry.text.slice(0, 60)}`);
|
|
1621
|
+
await db.delete(agentId, hit.entry.id);
|
|
1607
1622
|
}
|
|
1608
1623
|
|
|
1609
1624
|
async function storeOneCaptureItem(
|
|
@@ -2177,19 +2192,22 @@ const memoryPlugin = {
|
|
|
2177
2192
|
const isUserTrigger = trigger === "user";
|
|
2178
2193
|
|
|
2179
2194
|
// Skip memory extraction for system/bootstrap sessions (/new, /reset).
|
|
2180
|
-
// Check
|
|
2195
|
+
// Check ANY user message for known bootstrap patterns (not just last).
|
|
2181
2196
|
if (isUserTrigger) {
|
|
2182
|
-
const
|
|
2183
|
-
(m
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2197
|
+
const isBootstrapSession = event.messages.some((m: any) => {
|
|
2198
|
+
if (!m || typeof m !== "object") return false;
|
|
2199
|
+
const text = typeof (m as Record<string, unknown>).content === "string"
|
|
2200
|
+
? ((m as Record<string, unknown>).content as string).toLowerCase()
|
|
2201
|
+
: "";
|
|
2202
|
+
return (
|
|
2203
|
+
text.includes("a new session was started") ||
|
|
2204
|
+
text.includes("session startup sequence") ||
|
|
2205
|
+
text.includes("/new or /reset") ||
|
|
2206
|
+
text.startsWith("system:") ||
|
|
2207
|
+
text.startsWith("run your session")
|
|
2208
|
+
);
|
|
2209
|
+
});
|
|
2210
|
+
if (isBootstrapSession) {
|
|
2193
2211
|
console.log("[openclaw-memory-alibaba-local] agent_end skip capture (system/bootstrap session)");
|
|
2194
2212
|
return;
|
|
2195
2213
|
}
|
package/package.json
CHANGED
package/prompts.ts
CHANGED
|
@@ -267,7 +267,7 @@ Only INSERT or UPDATE information that captures a concrete, verifiable fact or e
|
|
|
267
267
|
- Purely conversational filler with no informational content
|
|
268
268
|
|
|
269
269
|
# Reconciliation Principles
|
|
270
|
-
1. **Prefer the richer version**: When a batch item and a Store item describe the same topic, keep whichever has the most information. If the batch
|
|
270
|
+
1. **Prefer the richer version**: When a batch item and a Store item describe the same topic, keep whichever has the most information. If the batch is richer, DELETE the old Store item and INSERT the batch item. If they are roughly equal, UPDATE to merge details.
|
|
271
271
|
2. **Preserve temporal markers**: Keep [as of ...] or [date] prefixes — world facts are time-sensitive.
|
|
272
272
|
3. **High cohesion**: Only merge entries about the exact same event or fact. Different events stay separate even if related.
|
|
273
273
|
4. **Contradiction = replace**: If a batch item directly contradicts a Store item (e.g. different outcome), DELETE the old item and INSERT the new one.
|
|
@@ -275,8 +275,8 @@ Only INSERT or UPDATE information that captures a concrete, verifiable fact or e
|
|
|
275
275
|
# Actions (one per batch index)
|
|
276
276
|
- **INSERT**: New world fact not in Store.
|
|
277
277
|
- **UPDATE** (memoryId): Store item covers the same event/fact; merge to produce the richer version.
|
|
278
|
-
- **SKIP**: Already fully covered by Store,
|
|
279
|
-
- **DELETE** (memoryId)
|
|
278
|
+
- **SKIP**: Already fully covered by a Store item (old is sufficient). Do NOT combine SKIP with DELETE for the same index — if you skip the new item, you are keeping the old one.
|
|
279
|
+
- **DELETE** (memoryId) + **INSERT**: Batch item supersedes or contradicts a Store item. You MUST delete the old item AND insert the replacement. A single index may list one or more DELETE actions followed by one INSERT.
|
|
280
280
|
|
|
281
281
|
# Output
|
|
282
282
|
Reply with ONLY a JSON object:
|
|
@@ -284,9 +284,11 @@ Reply with ONLY a JSON object:
|
|
|
284
284
|
{"index":0,"action":"insert","text":"[2026-04-01] Project X launched v2.0","importance":0.5},
|
|
285
285
|
{"index":1,"action":"skip"},
|
|
286
286
|
{"index":2,"action":"update","memoryId":"uuid","text":"[2026-03-28] Company Y acquired Z for $2B, deal finalized","importance":0.5},
|
|
287
|
-
{"index":3,"action":"delete","memoryId":"
|
|
287
|
+
{"index":3,"action":"delete","memoryId":"uuid1"},
|
|
288
|
+
{"index":3,"action":"delete","memoryId":"uuid2"},
|
|
289
|
+
{"index":3,"action":"insert","text":"[2026-04-02] Replacement fact","importance":0.5}
|
|
288
290
|
]}
|
|
289
|
-
Every batch index must appear.
|
|
291
|
+
Every batch index must appear exactly once as the primary action. When replacing, list DELETE(s) first then INSERT for that index.
|
|
290
292
|
`;
|
|
291
293
|
|
|
292
294
|
export function buildWorldImageExtractionPrompt(
|