openclaw-memory-alibaba-local 1.0.0 → 1.0.2

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 CHANGED
@@ -1119,21 +1119,21 @@ async function captureUserMemoryFromInboundTexts(
1119
1119
  });
1120
1120
  if (extractions.length === 0) return;
1121
1121
 
1122
- // ---- Batch merge path (when conflict_process enabled) ----
1123
- if (cfg.memory_duplication_conflict_process && cfg.llm) {
1124
- // Split: only User-related items go through merge; event/fact items insert directly
1125
- const userItems: LLMExtractionItem[] = [];
1126
- const eventItems: LLMExtractionItem[] = [];
1127
- for (const item of extractions) {
1128
- if (/\bUser\b/.test(item.text)) {
1129
- userItems.push(item);
1130
- } else {
1131
- eventItems.push(item);
1132
- }
1122
+ // ---- Always split: User-related items vs event items ----
1123
+ const userItems: LLMExtractionItem[] = [];
1124
+ const eventItems: LLMExtractionItem[] = [];
1125
+ for (const item of extractions) {
1126
+ if (/\bUser\b/.test(item.text)) {
1127
+ userItems.push(item);
1128
+ } else {
1129
+ eventItems.push(item);
1133
1130
  }
1131
+ }
1134
1132
 
1135
- // Direct-insert event items with similarity clustering (max 3 per cluster)
1136
- if (eventItems.length > 0) {
1133
+ // ---- Parallel: event-item pipeline & user-item pipeline ----
1134
+ const eventPipeline = async () => {
1135
+ if (eventItems.length === 0) return;
1136
+ if (cfg.memory_duplication_conflict_process) {
1137
1137
  type EmbeddedItem = { item: LLMExtractionItem; vectors: number[][]; primary: number[] };
1138
1138
  const embedded: EmbeddedItem[] = [];
1139
1139
  for (const item of eventItems) {
@@ -1147,7 +1147,6 @@ async function captureUserMemoryFromInboundTexts(
1147
1147
  for (const cluster of clusters) {
1148
1148
  const text = concatDedupeDate(cluster.map((e) => e.item.text));
1149
1149
  const importance = Math.max(...cluster.map((e) => e.item.importance));
1150
- // Re-embed the concatenated text for accurate storage vector
1151
1150
  const { vectors } = await backend.encodeForStorage(text);
1152
1151
  const rows = buildChunkRows(
1153
1152
  { category: WORLD_FACT as MemoryCategory, text, importance },
@@ -1156,7 +1155,7 @@ async function captureUserMemoryFromInboundTexts(
1156
1155
  );
1157
1156
  await db.storeMany(agentId, rows);
1158
1157
  }
1159
- console.log(`[openclaw-memory-alibaba-local] clustered ${eventItems.length} event items ${clusters.length} entries (max 3 per cluster, threshold 0.83)`);
1158
+ console.log(`[openclaw-memory-alibaba-local] clustered ${eventItems.length} event items \u2192 ${clusters.length} entries (max 3 per cluster, threshold 0.85)`);
1160
1159
 
1161
1160
  // World fact LRU GC: every 10 insertions
1162
1161
  worldFactGcCounter++;
@@ -1166,10 +1165,38 @@ async function captureUserMemoryFromInboundTexts(
1166
1165
  console.warn(`[openclaw-memory-alibaba-local] gcWorldFact failed: ${err}`),
1167
1166
  );
1168
1167
  }
1168
+ } else {
1169
+ // Simple dedup path for event items
1170
+ for (const e of eventItems) {
1171
+ const text = truncateForCapture(e.text, cfg.captureMaxChars);
1172
+ if (await db.existsSemanticDuplicate(agentId, sessionKey, e.category, text)) {
1173
+ continue;
1174
+ }
1175
+ await storeOneCaptureItem(agentId, { category: e.category, text, importance: e.importance }, cfg, db, backend, {
1176
+ userId,
1177
+ sessionId: sessionKey,
1178
+ });
1179
+ }
1180
+ }
1181
+ };
1182
+
1183
+ const userPipeline = async () => {
1184
+ if (userItems.length === 0) return;
1185
+ if (!cfg.llm) {
1186
+ console.warn(`[openclaw-memory-alibaba-local] no LLM configured, user items bypass UserImageExtraction`);
1187
+ for (const e of userItems) {
1188
+ const text = truncateForCapture(e.text, cfg.captureMaxChars);
1189
+ if (await db.existsSemanticDuplicate(agentId, sessionKey, e.category, text)) {
1190
+ continue;
1191
+ }
1192
+ await storeOneCaptureItem(agentId, { category: e.category, text, importance: e.importance }, cfg, db, backend, {
1193
+ userId,
1194
+ sessionId: sessionKey,
1195
+ });
1196
+ }
1197
+ return;
1169
1198
  }
1170
1199
 
1171
- // User image extraction: refine User-related items
1172
- if (userItems.length > 0) {
1173
1200
  // 1. Batch embed all new extractions
1174
1201
  const embeddingResults: { item: LLMExtractionItem; vectors: number[][] }[] = [];
1175
1202
  for (const item of userItems) {
@@ -1192,7 +1219,6 @@ async function captureUserMemoryFromInboundTexts(
1192
1219
  embeddingResults.map((r) => r.item),
1193
1220
  existingCandidates,
1194
1221
  ).catch((err: unknown) => {
1195
- // Fallback: insert all
1196
1222
  console.warn(`[openclaw-memory-alibaba-local] userImageExtraction LLM failed, fallback insert all: ${err}`);
1197
1223
  return embeddingResults.map((r): UserImageAction => ({
1198
1224
  action: "insert" as const,
@@ -1208,7 +1234,6 @@ async function captureUserMemoryFromInboundTexts(
1208
1234
  if (action.action === "skip") continue;
1209
1235
 
1210
1236
  if (action.action === "delete") {
1211
- // Delete outdated memory
1212
1237
  const hit = existingCandidates.find((c) => c.entry.id === action.memoryId);
1213
1238
  if (hit) {
1214
1239
  await deleteSimilarLogicalMemory(db, agentId, sessionKey, hit);
@@ -1217,7 +1242,6 @@ async function captureUserMemoryFromInboundTexts(
1217
1242
  }
1218
1243
 
1219
1244
  if (action.action === "update") {
1220
- // Delete the old memory, then insert merged text
1221
1245
  const hit = existingCandidates.find((c) => c.entry.id === action.memoryId);
1222
1246
  if (hit) {
1223
1247
  await deleteSimilarLogicalMemory(db, agentId, sessionKey, hit);
@@ -1240,21 +1264,9 @@ async function captureUserMemoryFromInboundTexts(
1240
1264
  await db.storeMany(agentId, rows);
1241
1265
  }
1242
1266
  }
1243
- } // end if userItems.length > 0
1244
- return;
1245
- }
1267
+ };
1246
1268
 
1247
- // ---- Simple dedup path (no conflict_process) ----
1248
- for (const e of extractions) {
1249
- const text = truncateForCapture(e.text, cfg.captureMaxChars);
1250
- if (await db.existsSemanticDuplicate(agentId, sessionKey, e.category, text)) {
1251
- continue;
1252
- }
1253
- await storeOneCaptureItem(agentId, { category: e.category, text, importance: e.importance }, cfg, db, backend, {
1254
- userId,
1255
- sessionId: sessionKey,
1256
- });
1257
- }
1269
+ await Promise.all([eventPipeline(), userPipeline()]);
1258
1270
  }
1259
1271
 
1260
1272
  /** Self-improving from batched user+assistant lines (agent_end delta). */
@@ -62,7 +62,7 @@
62
62
  "default": "llm",
63
63
  "description": "regex or llm; llm needs apiKey+model (plugin llm and/or openclaw.json bailian + agents.defaults.model)."
64
64
  },
65
- "autoRecall": { "type": "boolean", "default": false },
65
+ "autoRecall": { "type": "boolean", "default": true },
66
66
  "autoCapture": { "type": "boolean", "default": true },
67
67
  "captureMaxChars": { "type": "number", "default": 50000 },
68
68
  "enableMemoryDecay": {
@@ -206,7 +206,7 @@
206
206
  },
207
207
  "autoRecall": {
208
208
  "label": "Auto Recall",
209
- "help": "When true: inject memories before each prompt and register memory_recall / memory_store / memory_forget. When false (default): no auto recall and no those tools; agent_end capture still follows autoCapture."
209
+ "help": "When true (default): inject memories before each prompt and register memory_recall / memory_store / memory_forget. When false: no auto recall and no those tools; agent_end capture still follows autoCapture."
210
210
  },
211
211
  "autoCapture": {
212
212
  "label": "Auto Capture",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openclaw-memory-alibaba-local",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "OpenClaw memory plugin: local LanceDB + DashScope-compatible embeddings",
5
5
  "type": "module",
6
6
  "engines": {