openclaw-memory-alibaba-local 0.1.9-beta.21 → 0.1.9-beta.22

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/capture-state.ts CHANGED
@@ -166,7 +166,6 @@ function getMessageRoleRaw(msg: unknown): string {
166
166
  export function resolveRoleCountsForSession(
167
167
  entry: CursorFileEntry | undefined,
168
168
  messages: unknown[],
169
- log: { info: (m: string) => void },
170
169
  ): { roleCounts: Record<string, number>; lastMessagesLength: number } {
171
170
  if (isV2Entry(entry)) {
172
171
  return {
@@ -176,7 +175,7 @@ export function resolveRoleCountsForSession(
176
175
  }
177
176
  if (isLegacyEntry(entry)) {
178
177
  const end = Math.min(Math.max(0, entry.lastEndExclusive), messages.length);
179
- log.info("openclaw-memory-alibaba-local: migrated legacy full-context cursor to per-role counts");
178
+ console.log("[openclaw-memory-alibaba-local] migrated legacy full-context cursor to per-role counts");
180
179
  return {
181
180
  roleCounts: countRolesInMessagesPrefix(messages, end),
182
181
  lastMessagesLength: end,
package/db.ts CHANGED
@@ -1328,7 +1328,6 @@ export class MemoryDB {
1328
1328
  agentId: string,
1329
1329
  maxRows: number,
1330
1330
  maxAgeMs: number,
1331
- log?: { info: (m: string) => void },
1332
1331
  ): Promise<void> {
1333
1332
  await this.ensureInitialized();
1334
1333
  const a = sqlEscapeLiteral(agentId);
@@ -1343,7 +1342,7 @@ export class MemoryDB {
1343
1342
  // 2. Count remaining; if over maxRows, trim oldest
1344
1343
  const remaining = await this.table!.countRows(base);
1345
1344
  if (remaining <= maxRows) {
1346
- log?.info(`openclaw-memory-alibaba-local: gcFullContext agent=${agentId} remaining=${remaining} (within limit)`);
1345
+ console.log(`[openclaw-memory-alibaba-local] gcFullContext agent=${agentId} remaining=${remaining} (within limit)`);
1347
1346
  return;
1348
1347
  }
1349
1348
  const excess = remaining - maxRows;
@@ -1357,6 +1356,6 @@ export class MemoryDB {
1357
1356
  const cutoff = Number(oldest[excess - 1]!.createdAt);
1358
1357
  await this.table!.delete(`${base} AND createdAt <= ${Math.floor(cutoff)}`);
1359
1358
  }
1360
- log?.info(`openclaw-memory-alibaba-local: gcFullContext agent=${agentId} deleted ${excess} excess rows (was ${remaining}, cap ${maxRows})`);
1359
+ console.log(`[openclaw-memory-alibaba-local] gcFullContext agent=${agentId} deleted ${excess} excess rows (was ${remaining}, cap ${maxRows})`);
1361
1360
  }
1362
1361
  }
package/index.ts CHANGED
@@ -175,26 +175,22 @@ function getThresholdForCategory(cfg: MemoryConfig, category: MemoryCategory): n
175
175
  return cfg.similarityThresholdSelfImproving;
176
176
  }
177
177
 
178
- /** 可选:给 LLM / 衰减诊断日志(与 OpenClaw api.logger 兼容,仅用 info)。 */
179
- type MemoryDiagnosticLog = { info: (m: string) => void } | undefined;
180
-
181
178
  /** 精简日志:仅记录 tag + prompt 字符数,不贴原文。 */
182
- function logLlmCall(tag: string, promptChars: number, log: MemoryDiagnosticLog): void {
183
- log?.info(`openclaw-memory-alibaba-local: llm ${tag} prompt (${promptChars} chars)`);
179
+ function logLlmCall(tag: string, promptChars: number): void {
180
+ console.log(`[openclaw-memory-alibaba-local] llm ${tag} prompt (${promptChars} chars)`);
184
181
  }
185
182
 
186
183
  /** 记录 merge 结果统计。 */
187
- function logMergeResult(total: number, actions: ReadonlyArray<{ action: string }>, log: MemoryDiagnosticLog): void {
188
- if (!log) return;
184
+ function logMergeResult(total: number, actions: ReadonlyArray<{ action: string }>): void {
189
185
  const counts: Record<string, number> = {};
190
186
  for (const a of actions) counts[a.action] = (counts[a.action] ?? 0) + 1;
191
187
  const parts = Object.entries(counts).map(([k, v]) => `${v} ${k}`).join(", ");
192
- log.info(`openclaw-memory-alibaba-local: batchMerge result: ${total} items → ${parts}`);
188
+ console.log(`[openclaw-memory-alibaba-local] batchMerge result: ${total} items → ${parts}`);
193
189
  }
194
190
 
195
191
  /** 记忆衰减为纯公式,不向模型发提示词;仍打日志避免与「冲突检测 LLM」混淆。 */
196
- function logMemoryDecayNoLlm(phase: string, log: MemoryDiagnosticLog, detail: string): void {
197
- log?.info(`openclaw-memory-alibaba-local: memoryDecay ${phase} (no LLM; formula-only) ${detail}`);
192
+ function logMemoryDecayNoLlm(phase: string, detail: string): void {
193
+ console.log(`[openclaw-memory-alibaba-local] memoryDecay ${phase} (no LLM; formula-only) ${detail}`);
198
194
  }
199
195
 
200
196
  /** Apply time decay to recall results: effectiveScore = score * decay(createdAt). Returns new array sorted by effectiveScore desc. */
@@ -234,7 +230,6 @@ async function runRecall(
234
230
  agentId: string,
235
231
  queryVectors: number[][],
236
232
  options: { limitUser: number; limitSelf: number; minScore: number },
237
- log?: MemoryDiagnosticLog,
238
233
  ): Promise<MemorySearchResult[]> {
239
234
  if (queryVectors.length === 0) {
240
235
  return [];
@@ -271,7 +266,6 @@ async function runRecall(
271
266
  );
272
267
  logMemoryDecayNoLlm(
273
268
  "vectorRecall",
274
- log,
275
269
  `strategy=${cfg.memoryDecayStrategy} halfLifeDays=${cfg.memoryDecayHalfLifeDays} agentId=${agentId} inputRows=${decayIn}`,
276
270
  );
277
271
  }
@@ -288,7 +282,6 @@ async function bm25SupplementRecall(
288
282
  queryText: string,
289
283
  vectorResults: MemorySearchResult[],
290
284
  maxAdd: number,
291
- log?: MemoryDiagnosticLog,
292
285
  ): Promise<MemorySearchResult[]> {
293
286
  const q = queryText.trim();
294
287
  if (q.length < 2 || maxAdd <= 0) {
@@ -353,7 +346,6 @@ async function bm25SupplementRecall(
353
346
  ranked = applyMemoryDecay(ranked, Date.now(), cfg.memoryDecayStrategy, cfg.memoryDecayHalfLifeDays);
354
347
  logMemoryDecayNoLlm(
355
348
  "bm25Pool",
356
- log,
357
349
  `strategy=${cfg.memoryDecayStrategy} halfLifeDays=${cfg.memoryDecayHalfLifeDays} agentId=${agentId} inputRows=${decayIn}`,
358
350
  );
359
351
  }
@@ -379,12 +371,11 @@ async function runHybridRecall(
379
371
  queryText: string,
380
372
  queryVectors: number[][],
381
373
  options: { limitUser: number; limitSelf: number; minScore: number },
382
- log?: MemoryDiagnosticLog,
383
374
  ): Promise<MemorySearchResult[]> {
384
- const vector = await runRecall(db, cfg, agentId, queryVectors, options, log);
375
+ const vector = await runRecall(db, cfg, agentId, queryVectors, options);
385
376
  const extra =
386
377
  queryText.trim().length >= 2
387
- ? await bm25SupplementRecall(db, cfg, agentId, queryText, vector, RECALL_BM25_MAX, log)
378
+ ? await bm25SupplementRecall(db, cfg, agentId, queryText, vector, RECALL_BM25_MAX)
388
379
  : [];
389
380
  return [...vector, ...extra].slice(0, RECALL_FINAL_MAX);
390
381
  }
@@ -434,7 +425,6 @@ async function extractUserMemoriesWithLLM(
434
425
  llmConfig: LLMConfig,
435
426
  userMessages: string[],
436
427
  _maxExtractions = Infinity,
437
- log?: MemoryDiagnosticLog,
438
428
  ): Promise<LLMExtractionItem[]> {
439
429
  if (userMessages.length === 0) return [];
440
430
  const combined = userMessages
@@ -444,7 +434,7 @@ async function extractUserMemoriesWithLLM(
444
434
 
445
435
  const extractionPrompt = buildMemoryExtractionPrompt() + combined;
446
436
 
447
- logLlmCall("memoryExtraction", extractionPrompt.length, log);
437
+ logLlmCall("memoryExtraction", extractionPrompt.length);
448
438
 
449
439
  const openai = new OpenAI({
450
440
  apiKey: llmConfig.apiKey,
@@ -468,7 +458,7 @@ async function extractUserMemoriesWithLLM(
468
458
  }
469
459
  return out;
470
460
  } catch (err: unknown) {
471
- log?.info(`openclaw-memory-alibaba-local: memoryExtraction JSON parse failed: ${err}`);
461
+ console.warn(`[openclaw-memory-alibaba-local] memoryExtraction JSON parse failed: ${err}`);
472
462
  return [];
473
463
  }
474
464
  };
@@ -479,13 +469,13 @@ async function extractUserMemoriesWithLLM(
479
469
  temperature: 0,
480
470
  max_tokens: 8192,
481
471
  }).catch((err: unknown) => {
482
- log?.info(`openclaw-memory-alibaba-local: memoryExtraction LLM call failed: ${err}`);
472
+ console.warn(`[openclaw-memory-alibaba-local] memoryExtraction LLM call failed: ${err}`);
483
473
  return null;
484
474
  });
485
475
 
486
476
  const raw = completion?.choices[0]?.message?.content?.trim() ?? "";
487
477
  const items = parseExtractions(raw);
488
- log?.info(`openclaw-memory-alibaba-local: memoryExtraction extracted ${items.length} items`);
478
+ console.log(`[openclaw-memory-alibaba-local] memoryExtraction extracted ${items.length} items`);
489
479
  return items;
490
480
  }
491
481
 
@@ -534,11 +524,10 @@ async function extractSelfImprovingWithLLM(
534
524
  llmConfig: LLMConfig,
535
525
  conversationText: string,
536
526
  maxExtractions = MAX_AUTO_CAPTURE_SELF_IMPROVING,
537
- log?: MemoryDiagnosticLog,
538
527
  ): Promise<SelfImprovingExtractionItem[]> {
539
528
  if (conversationText.length < 20) return [];
540
529
  const prompt = SELF_IMPROVING_EXTRACTION_INSTRUCTIONS + "\n" + conversationText;
541
- logLlmCall("selfImprovingExtraction", prompt.length, log);
530
+ logLlmCall("selfImprovingExtraction", prompt.length);
542
531
  const openai = new OpenAI({
543
532
  apiKey: llmConfig.apiKey,
544
533
  baseURL: llmConfig.baseUrl,
@@ -574,7 +563,7 @@ async function extractSelfImprovingWithLLM(
574
563
  }
575
564
  return out;
576
565
  } catch (err: unknown) {
577
- log?.info(`openclaw-memory-alibaba-local: selfImprovingExtraction JSON parse failed: ${err}`);
566
+ console.warn(`[openclaw-memory-alibaba-local] selfImprovingExtraction JSON parse failed: ${err}`);
578
567
  return [];
579
568
  }
580
569
  }
@@ -597,7 +586,6 @@ async function mergeMemoriesWithLLM(
597
586
  llmConfig: LLMConfig,
598
587
  newItems: LLMExtractionItem[],
599
588
  existingCandidates: MemorySearchResult[],
600
- log?: MemoryDiagnosticLog,
601
589
  ): Promise<MergeAction[]> {
602
590
  if (newItems.length === 0) return [];
603
591
 
@@ -624,7 +612,7 @@ async function mergeMemoriesWithLLM(
624
612
  }));
625
613
 
626
614
  const prompt = buildMemoryMergePrompt(newForPrompt, existingForPrompt);
627
- logLlmCall("batchMerge", prompt.length, log);
615
+ logLlmCall("batchMerge", prompt.length);
628
616
 
629
617
  const openai = new OpenAI({
630
618
  apiKey: llmConfig.apiKey,
@@ -714,7 +702,7 @@ async function mergeMemoriesWithLLM(
714
702
  return result;
715
703
  } catch (err: unknown) {
716
704
  // On parse failure, fallback: insert everything
717
- log?.info(`openclaw-memory-alibaba-local: batchMerge JSON parse failed, fallback insert all: ${err}`);
705
+ console.warn(`[openclaw-memory-alibaba-local] batchMerge JSON parse failed, fallback insert all: ${err}`);
718
706
  return newItems.map((item) => ({
719
707
  action: "insert" as const,
720
708
  text: item.text,
@@ -899,7 +887,6 @@ async function runAgentEndCapture(
899
887
  userId: string | null,
900
888
  messages: unknown[],
901
889
  lancedbDir: string,
902
- log: { info: (m: string) => void; warn: (m: string) => void },
903
890
  ): Promise<void> {
904
891
  if (messages.length === 0) {
905
892
  return;
@@ -908,10 +895,10 @@ async function runAgentEndCapture(
908
895
  const key = getFullContextCursorKey(agentId, sessionKey);
909
896
  const map = loadAgentEndCursorMap(lancedbDir);
910
897
  const entry = map[key];
911
- let { roleCounts: saved, lastMessagesLength } = resolveRoleCountsForSession(entry, messages, log);
898
+ let { roleCounts: saved, lastMessagesLength } = resolveRoleCountsForSession(entry, messages);
912
899
 
913
900
  if (messages.length < lastMessagesLength) {
914
- log.info("openclaw-memory-alibaba-local: transcript shrank; reset per-role capture cursors");
901
+ console.log("[openclaw-memory-alibaba-local] transcript shrank; reset per-role capture cursors");
915
902
  saved = {};
916
903
  }
917
904
 
@@ -971,7 +958,7 @@ async function runAgentEndCapture(
971
958
  const batchId = randomUUID();
972
959
  const sid = sessionKey;
973
960
 
974
- log.info(`openclaw-memory-alibaba-local: agentEndCapture fullRows=${fullRows.length} userTexts=${userRawTexts.length} uaLines=${uaLines.length}`);
961
+ console.log(`[openclaw-memory-alibaba-local] agentEndCapture fullRows=${fullRows.length} userTexts=${userRawTexts.length} uaLines=${uaLines.length}`);
975
962
 
976
963
  if (fullRows.length > 0) {
977
964
  await db.storeMany(
@@ -989,12 +976,12 @@ async function runAgentEndCapture(
989
976
  })),
990
977
  );
991
978
  // GC: 删除超过 50000 条或超过 1 个月的全文记忆
992
- await db.gcFullContext(agentId, 50_000, 30 * 24 * 60 * 60 * 1000, log);
979
+ await db.gcFullContext(agentId, 50_000, 30 * 24 * 60 * 60 * 1000);
993
980
  }
994
981
 
995
982
  await Promise.all([
996
- captureUserMemoryFromInboundTexts(cfg, db, backend, agentId, sid, userId, userRawTexts, log),
997
- captureSelfImprovingFromLines(cfg, db, backend, agentId, sid, userId, uaLines, log),
983
+ captureUserMemoryFromInboundTexts(cfg, db, backend, agentId, sid, userId, userRawTexts),
984
+ captureSelfImprovingFromLines(cfg, db, backend, agentId, sid, userId, uaLines),
998
985
  ]);
999
986
 
1000
987
  map[key] = {
@@ -1014,7 +1001,6 @@ async function captureUserMemoryFromInboundTexts(
1014
1001
  sessionKey: string,
1015
1002
  userId: string | null,
1016
1003
  inboundTexts: string[],
1017
- log: { info: (m: string) => void },
1018
1004
  ): Promise<void> {
1019
1005
  if (inboundTexts.length === 0) {
1020
1006
  return;
@@ -1044,7 +1030,6 @@ async function captureUserMemoryFromInboundTexts(
1044
1030
  await storeOneCaptureItem(agentId, { ...item, text }, cfg, db, backend, {
1045
1031
  userId,
1046
1032
  sessionId: sessionKey,
1047
- log,
1048
1033
  });
1049
1034
  }
1050
1035
  return;
@@ -1058,9 +1043,8 @@ async function captureUserMemoryFromInboundTexts(
1058
1043
  cfg.llm,
1059
1044
  toSend,
1060
1045
  MAX_AUTO_CAPTURE_LLM,
1061
- log,
1062
1046
  ).catch((err: unknown) => {
1063
- log?.info(`openclaw-memory-alibaba-local: memoryExtraction pipeline failed: ${err}`);
1047
+ console.warn(`[openclaw-memory-alibaba-local] memoryExtraction pipeline failed: ${err}`);
1064
1048
  return [] as LLMExtractionItem[];
1065
1049
  });
1066
1050
  if (extractions.length === 0) return;
@@ -1083,15 +1067,14 @@ async function captureUserMemoryFromInboundTexts(
1083
1067
  : [];
1084
1068
 
1085
1069
  // 3. Call batch merge LLM
1086
- log?.info(`openclaw-memory-alibaba-local: batchMerge input: ${extractions.length} extractions, ${existingCandidates.length} existing candidates`);
1070
+ console.log(`[openclaw-memory-alibaba-local] batchMerge input: ${extractions.length} extractions, ${existingCandidates.length} existing candidates`);
1087
1071
  const mergeActions = await mergeMemoriesWithLLM(
1088
1072
  cfg.llm,
1089
1073
  embeddingResults.map((r) => r.item),
1090
1074
  existingCandidates,
1091
- log,
1092
1075
  ).catch((err: unknown) => {
1093
1076
  // Fallback: insert all
1094
- log?.info(`openclaw-memory-alibaba-local: batchMerge LLM failed, fallback insert all: ${err}`);
1077
+ console.warn(`[openclaw-memory-alibaba-local] batchMerge LLM failed, fallback insert all: ${err}`);
1095
1078
  return embeddingResults.map((r): MergeAction => ({
1096
1079
  action: "insert" as const,
1097
1080
  text: r.item.text,
@@ -1101,7 +1084,7 @@ async function captureUserMemoryFromInboundTexts(
1101
1084
  });
1102
1085
 
1103
1086
  // 4. Log & execute merge actions
1104
- logMergeResult(extractions.length, mergeActions, log);
1087
+ logMergeResult(extractions.length, mergeActions);
1105
1088
  for (const action of mergeActions) {
1106
1089
  if (action.action === "skip") continue;
1107
1090
 
@@ -1150,7 +1133,6 @@ async function captureUserMemoryFromInboundTexts(
1150
1133
  await storeOneCaptureItem(agentId, { category: e.category, text, importance: e.importance }, cfg, db, backend, {
1151
1134
  userId,
1152
1135
  sessionId: sessionKey,
1153
- log,
1154
1136
  });
1155
1137
  }
1156
1138
  }
@@ -1164,7 +1146,6 @@ async function captureSelfImprovingFromLines(
1164
1146
  sessionKey: string,
1165
1147
  userId: string | null,
1166
1148
  lines: string[],
1167
- log: { info: (m: string) => void },
1168
1149
  ): Promise<void> {
1169
1150
  if (!cfg.enableSelfImprovingMemory || lines.length === 0) {
1170
1151
  return;
@@ -1185,9 +1166,8 @@ async function captureSelfImprovingFromLines(
1185
1166
  cfg.llm,
1186
1167
  combined,
1187
1168
  MAX_AUTO_CAPTURE_SELF_IMPROVING,
1188
- log,
1189
1169
  ).catch((err: unknown) => {
1190
- log.info(`openclaw-memory-alibaba-local: selfImprovingExtraction pipeline failed: ${err}`);
1170
+ console.warn(`[openclaw-memory-alibaba-local] selfImprovingExtraction pipeline failed: ${err}`);
1191
1171
  return [] as SelfImprovingExtractionItem[];
1192
1172
  });
1193
1173
  for (const e of extractions) {
@@ -1215,7 +1195,6 @@ async function captureSelfImprovingFromLines(
1215
1195
  await storeOneCaptureItem(agentId, item, cfg, db, backend, {
1216
1196
  userId,
1217
1197
  sessionId: sessionKey,
1218
- log,
1219
1198
  });
1220
1199
  }
1221
1200
  }
@@ -1294,7 +1273,6 @@ async function storeOneCaptureItem(
1294
1273
  sessionId?: string | null;
1295
1274
  batchId?: string | null;
1296
1275
  seqInBatch?: number | null;
1297
- log?: { info: (m: string) => void };
1298
1276
  },
1299
1277
  ): Promise<StoreOneResult> {
1300
1278
  if (isFullContextStoredWithoutEmbedding(item.category)) {
@@ -1511,7 +1489,6 @@ const memoryPlugin = {
1511
1489
  limitSelf,
1512
1490
  minScore: RECALL_MIN_SCORE_RELAXED,
1513
1491
  },
1514
- api.logger,
1515
1492
  );
1516
1493
 
1517
1494
  // Respect the user-requested limit after hybrid recall (vector + BM25 may exceed it).
@@ -1627,7 +1604,6 @@ const memoryPlugin = {
1627
1604
  const { action, entry } = await storeOneCaptureItem(agentId, item, cfg, db, backend, {
1628
1605
  userId,
1629
1606
  sessionId,
1630
- log: api.logger,
1631
1607
  });
1632
1608
  const preview = text.length > 100 ? text.slice(0, 100) + "..." : text;
1633
1609
  return {
@@ -1778,7 +1754,6 @@ const memoryPlugin = {
1778
1754
  limitSelf: cfg.enableSelfImprovingMemory ? RECALL_LIMIT_SELF : 0,
1779
1755
  minScore: RECALL_MIN_SCORE_HOOK,
1780
1756
  },
1781
- api.logger,
1782
1757
  );
1783
1758
  const searchMs = Date.now() - tSearch0;
1784
1759
  const totalMs = Date.now() - tRecall0;
@@ -1852,7 +1827,6 @@ const memoryPlugin = {
1852
1827
  userId,
1853
1828
  event.messages,
1854
1829
  resolvedDbPath,
1855
- api.logger,
1856
1830
  );
1857
1831
  api.logger.info(
1858
1832
  `openclaw-memory-alibaba-local: agent_end capture done totalHookMs=${Date.now() - tCap0} messages=${event.messages.length}`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openclaw-memory-alibaba-local",
3
- "version": "0.1.9-beta.21",
3
+ "version": "0.1.9-beta.22",
4
4
  "description": "OpenClaw memory plugin: local LanceDB + DashScope-compatible embeddings",
5
5
  "type": "module",
6
6
  "engines": {
package/prompts.ts CHANGED
@@ -193,7 +193,7 @@ Do NOT merge items that merely share the same person but cover different topics.
193
193
  - **DELETE** (memoryId): A batch item directly contradicts and fully replaces a Store item. Delete the Store item; handle the batch item as INSERT.
194
194
  - Only when info DIRECTLY contradicts (e.g. "moved to Shanghai" vs stored "lives in Beijing").
195
195
 
196
- # Category Evolution
196
+ # Category & Relevance Filter
197
197
 
198
198
  For every INSERT or UPDATE, assign a category based on content:
199
199
  - **profile**: User identity (name, age, location, job, relationships, background)
@@ -203,6 +203,10 @@ For every INSERT or UPDATE, assign a category based on content:
203
203
 
204
204
  Only memories about "User" → profile/preferences/decisions. Others → "fact".
205
205
 
206
+ **User-category filter**: For profile/preferences/decisions, only keep **durable personal information** — identity, traits, relationships, beliefs, preferences, life events, long-term goals. SKIP one-time operational requests, transient commands, debugging queries, or ephemeral task instructions (e.g. "User asked to run command X", "User requested to search logs", "User asked which files were viewed"). These reveal nothing lasting about the person.
207
+
208
+ **Fact-category**: ZERO information loss. All events, activities, and third-party info must be kept.
209
+
206
210
  # Output format
207
211
 
208
212
  Reply with ONLY a JSON object: