@xdarkicex/openclaw-memory-libravdb 1.4.14 → 1.4.16

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.
@@ -83,6 +83,7 @@ export declare function buildContextEngineFactory(runtime: PluginRuntime, cfg: P
83
83
  }>;
84
84
  tokenBudget: number;
85
85
  prompt?: string;
86
+ currentTokenCount?: number;
86
87
  }): Promise<OpenClawCompatibleAssembleResult>;
87
88
  compact(args: {
88
89
  sessionId: string;
@@ -30,15 +30,6 @@ function normalizeCompactResult(response) {
30
30
  },
31
31
  };
32
32
  }
33
- function describeUnexpectedContent(value) {
34
- try {
35
- const serialized = JSON.stringify(value);
36
- return serialized === undefined ? String(value) : serialized;
37
- }
38
- catch {
39
- return String(value);
40
- }
41
- }
42
33
  function stringifyKernelBlock(block) {
43
34
  if (!block || typeof block !== "object") {
44
35
  return "";
@@ -69,10 +60,6 @@ function stringifyKernelBlock(block) {
69
60
  case "image":
70
61
  return "[image omitted]";
71
62
  default:
72
- console.warn("[libravdb] unsupported kernel content block", {
73
- type: record.type,
74
- block: describeUnexpectedContent(record),
75
- });
76
63
  return typeof record.text === "string" ? record.text : "";
77
64
  }
78
65
  }
@@ -81,10 +68,6 @@ function normalizeKernelContent(content) {
81
68
  return content;
82
69
  }
83
70
  if (!Array.isArray(content)) {
84
- console.warn("[libravdb] unexpected kernel content shape", {
85
- kind: typeof content,
86
- value: describeUnexpectedContent(content),
87
- });
88
71
  return "";
89
72
  }
90
73
  return content.map(stringifyKernelBlock).filter((part) => part.length > 0).join("\n");
@@ -101,6 +84,14 @@ function approximateMessageTokens(message) {
101
84
  function approximateMessagesTokens(messages) {
102
85
  return messages.reduce((sum, message) => sum + approximateMessageTokens(message), 0);
103
86
  }
87
+ function normalizeCurrentTokenCount(currentTokenCount) {
88
+ if (typeof currentTokenCount !== "number" ||
89
+ !Number.isFinite(currentTokenCount) ||
90
+ currentTokenCount <= 0) {
91
+ return undefined;
92
+ }
93
+ return Math.max(1, Math.floor(currentTokenCount));
94
+ }
104
95
  function normalizeTokenBudget(tokenBudget) {
105
96
  if (typeof tokenBudget !== "number" || !Number.isFinite(tokenBudget) || tokenBudget <= 0) {
106
97
  return undefined;
@@ -128,6 +119,33 @@ function resolveDynamicCompactThreshold(tokenBudget, compactThreshold, compactio
128
119
  const fraction = normalizeThresholdFraction(compactionThresholdFraction);
129
120
  return Math.max(1, Math.floor(normalizedBudget * fraction));
130
121
  }
122
+ function resolvePredictiveCompactionTarget(params) {
123
+ const currentTokenCount = normalizeCurrentTokenCount(params.currentTokenCount);
124
+ const threshold = normalizeTokenBudget(params.threshold);
125
+ if (currentTokenCount == null || threshold == null || currentTokenCount < threshold) {
126
+ return undefined;
127
+ }
128
+ const belowThresholdTarget = Math.max(1, threshold - 1);
129
+ return belowThresholdTarget < currentTokenCount
130
+ ? belowThresholdTarget
131
+ : Math.max(1, currentTokenCount - 1);
132
+ }
133
+ function logPredictiveCompactionAttempt(params) {
134
+ params.logger.info?.(`LibraVDB predictive compaction trigger phase=${params.phase} sessionId=${params.sessionId} ` +
135
+ `currentTokenCount=${params.currentTokenCount} threshold=${params.threshold} ` +
136
+ `targetSize=${params.targetSize} tokenBudget=${params.tokenBudget ?? "unknown"}`);
137
+ }
138
+ function logPredictiveCompactionOutcome(params) {
139
+ const message = `LibraVDB predictive compaction ${params.compacted ? "completed" : "did not compact"} ` +
140
+ `phase=${params.phase} sessionId=${params.sessionId} currentTokenCount=${params.currentTokenCount} ` +
141
+ `threshold=${params.threshold} targetSize=${params.targetSize} tokenBudget=${params.tokenBudget ?? "unknown"}` +
142
+ (params.reason ? ` reason=${params.reason}` : "");
143
+ if (params.compacted) {
144
+ params.logger.info?.(message);
145
+ return;
146
+ }
147
+ params.logger.warn?.(message);
148
+ }
131
149
  function truncateContentToTokenBudget(content, tokenBudget) {
132
150
  if (tokenBudget <= 0)
133
151
  return "";
@@ -191,6 +209,10 @@ function buildBudgetFallbackContext(messages, tokenBudget) {
191
209
  systemPromptAddition: "",
192
210
  };
193
211
  }
212
+ function resolvePredictiveCompactionTokenCount(args) {
213
+ return (normalizeCurrentTokenCount(args.currentTokenCount) ??
214
+ approximateMessagesTokens(args.messages) + approximateTokenCount(args.prompt ?? ""));
215
+ }
194
216
  export function normalizeKernelMessage(message) {
195
217
  return {
196
218
  role: message.role,
@@ -263,7 +285,12 @@ export function buildContextEngineFactory(runtime, cfg, recallCache, logger = co
263
285
  sessionId: requireSessionId(args.sessionId, "compact"),
264
286
  force: args.force,
265
287
  ...(typeof targetSize === "number" ? { targetSize } : {}),
266
- ...(typeof args.currentTokenCount === "number" ? { currentTokenCount: args.currentTokenCount } : {}),
288
+ ...(() => {
289
+ const normalizedCurrentTokenCount = normalizeCurrentTokenCount(args.currentTokenCount);
290
+ return normalizedCurrentTokenCount != null
291
+ ? { currentTokenCount: normalizedCurrentTokenCount }
292
+ : {};
293
+ })(),
267
294
  ...(typeof cfg.continuityMinTurns === "number"
268
295
  ? { continuityMinTurns: cfg.continuityMinTurns }
269
296
  : {}),
@@ -293,6 +320,45 @@ export function buildContextEngineFactory(runtime, cfg, recallCache, logger = co
293
320
  };
294
321
  }
295
322
  }
323
+ async function performAfterTurnPredictiveCompaction(args) {
324
+ const dynamicCompactThreshold = getDynamicCompactThreshold(args.tokenBudget);
325
+ const predictiveTargetSize = resolvePredictiveCompactionTarget({
326
+ currentTokenCount: args.currentTokenCount,
327
+ threshold: dynamicCompactThreshold,
328
+ });
329
+ if (args.currentTokenCount == null ||
330
+ dynamicCompactThreshold == null ||
331
+ predictiveTargetSize == null) {
332
+ return;
333
+ }
334
+ logPredictiveCompactionAttempt({
335
+ logger,
336
+ phase: "afterTurn",
337
+ sessionId: args.sessionId,
338
+ currentTokenCount: args.currentTokenCount,
339
+ threshold: dynamicCompactThreshold,
340
+ targetSize: predictiveTargetSize,
341
+ tokenBudget: args.tokenBudget,
342
+ });
343
+ const compactionResult = await runCompaction({
344
+ sessionId: args.sessionId,
345
+ targetSize: predictiveTargetSize,
346
+ tokenBudget: args.tokenBudget,
347
+ force: true,
348
+ currentTokenCount: args.currentTokenCount,
349
+ });
350
+ logPredictiveCompactionOutcome({
351
+ logger,
352
+ phase: "afterTurn",
353
+ sessionId: args.sessionId,
354
+ currentTokenCount: args.currentTokenCount,
355
+ threshold: dynamicCompactThreshold,
356
+ targetSize: predictiveTargetSize,
357
+ tokenBudget: args.tokenBudget,
358
+ compacted: compactionResult.compacted,
359
+ reason: compactionResult.reason,
360
+ });
361
+ }
296
362
  return {
297
363
  info: { id: "libravdb-memory", name: "LibraVDB Memory", ownsCompaction: true },
298
364
  ownsCompaction: true,
@@ -337,18 +403,47 @@ export function buildContextEngineFactory(runtime, cfg, recallCache, logger = co
337
403
  },
338
404
  async assemble(args) {
339
405
  const messages = normalizeKernelMessages(args.messages);
340
- const currentContextTokens = approximateMessagesTokens(messages) + approximateTokenCount(args.prompt ?? "");
406
+ const currentContextTokens = resolvePredictiveCompactionTokenCount({
407
+ currentTokenCount: args.currentTokenCount,
408
+ messages,
409
+ prompt: args.prompt,
410
+ });
341
411
  const dynamicCompactThreshold = getDynamicCompactThreshold(args.tokenBudget);
342
- if (dynamicCompactThreshold != null &&
343
- currentContextTokens >= dynamicCompactThreshold) {
412
+ const predictiveTargetSize = resolvePredictiveCompactionTarget({
413
+ currentTokenCount: currentContextTokens,
414
+ threshold: dynamicCompactThreshold,
415
+ });
416
+ if (dynamicCompactThreshold != null && predictiveTargetSize != null) {
417
+ logPredictiveCompactionAttempt({
418
+ logger,
419
+ phase: "assemble",
420
+ sessionId: args.sessionId,
421
+ currentTokenCount: currentContextTokens,
422
+ threshold: dynamicCompactThreshold,
423
+ targetSize: predictiveTargetSize,
424
+ tokenBudget: args.tokenBudget,
425
+ });
344
426
  const compactionResult = await runCompaction({
345
427
  sessionId: args.sessionId,
428
+ targetSize: predictiveTargetSize,
346
429
  tokenBudget: args.tokenBudget,
347
430
  force: true,
348
431
  currentTokenCount: currentContextTokens,
349
432
  });
350
- if (!compactionResult.ok || !compactionResult.compacted) {
351
- logger.warn?.(`LibraVDB predictive compaction blocked assemble path at ${currentContextTokens} tokens (threshold=${dynamicCompactThreshold}): ${compactionResult.reason ?? "compaction declined"}`);
433
+ logPredictiveCompactionOutcome({
434
+ logger,
435
+ phase: "assemble",
436
+ sessionId: args.sessionId,
437
+ currentTokenCount: currentContextTokens,
438
+ threshold: dynamicCompactThreshold,
439
+ targetSize: predictiveTargetSize,
440
+ tokenBudget: args.tokenBudget,
441
+ compacted: compactionResult.compacted,
442
+ reason: compactionResult.reason,
443
+ });
444
+ if (!compactionResult.ok) {
445
+ logger.warn?.(`LibraVDB predictive compaction blocked assemble path at ${currentContextTokens} tokens ` +
446
+ `(threshold=${dynamicCompactThreshold}): ${compactionResult.reason ?? "compaction failed"}`);
352
447
  return buildBudgetFallbackContext(messages, args.tokenBudget);
353
448
  }
354
449
  }
@@ -396,8 +491,11 @@ export function buildContextEngineFactory(runtime, cfg, recallCache, logger = co
396
491
  async afterTurn(args) {
397
492
  const messages = normalizeKernelMessages(args.messages);
398
493
  const kernel = runtime.getKernel();
494
+ const currentTokenCount = normalizeCurrentTokenCount(typeof args.runtimeContext?.currentTokenCount === "number"
495
+ ? args.runtimeContext.currentTokenCount
496
+ : undefined);
399
497
  if (kernel) {
400
- return await kernel.afterTurn({
498
+ const result = await kernel.afterTurn({
401
499
  sessionId: args.sessionId,
402
500
  sessionKey: args.sessionKey,
403
501
  userId: args.userId,
@@ -405,12 +503,24 @@ export function buildContextEngineFactory(runtime, cfg, recallCache, logger = co
405
503
  prePromptMessageCount: args.prePromptMessageCount,
406
504
  isHeartbeat: args.isHeartbeat,
407
505
  });
506
+ await performAfterTurnPredictiveCompaction({
507
+ sessionId: args.sessionId,
508
+ tokenBudget: args.tokenBudget,
509
+ currentTokenCount,
510
+ });
511
+ return result;
408
512
  }
409
513
  const rpc = await runtime.getRpc();
410
- return await rpc.call("after_turn_kernel", {
514
+ const result = await rpc.call("after_turn_kernel", {
411
515
  ...args,
412
516
  messages,
413
517
  });
518
+ await performAfterTurnPredictiveCompaction({
519
+ sessionId: args.sessionId,
520
+ tokenBudget: args.tokenBudget,
521
+ currentTokenCount,
522
+ });
523
+ return result;
414
524
  }
415
525
  };
416
526
  }
@@ -2,7 +2,7 @@
2
2
  "id": "libravdb-memory",
3
3
  "name": "LibraVDB Memory",
4
4
  "description": "Persistent vector memory with three-tier hybrid scoring",
5
- "version": "1.4.14",
5
+ "version": "1.4.16",
6
6
  "kind": [
7
7
  "memory",
8
8
  "context-engine"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xdarkicex/openclaw-memory-libravdb",
3
- "version": "1.4.14",
3
+ "version": "1.4.16",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",