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 +46 -34
- package/openclaw.plugin.json +2 -2
- package/package.json +1 -1
package/index.ts
CHANGED
|
@@ -1119,21 +1119,21 @@ async function captureUserMemoryFromInboundTexts(
|
|
|
1119
1119
|
});
|
|
1120
1120
|
if (extractions.length === 0) return;
|
|
1121
1121
|
|
|
1122
|
-
// ----
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
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
|
-
|
|
1136
|
-
|
|
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
|
|
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
|
-
|
|
1244
|
-
return;
|
|
1245
|
-
}
|
|
1267
|
+
};
|
|
1246
1268
|
|
|
1247
|
-
|
|
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). */
|
package/openclaw.plugin.json
CHANGED
|
@@ -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":
|
|
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
|
|
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",
|