@xdarkicex/openclaw-memory-libravdb 1.6.16 → 1.6.18

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.
@@ -12,10 +12,12 @@ type OpenClawCompatibleMessage = {
12
12
  id?: string;
13
13
  [key: string]: unknown;
14
14
  };
15
+ type OpenClawCompatiblePromptAuthority = "preassembly_may_overflow";
15
16
  type OpenClawCompatibleAssembleResult = {
16
17
  messages: OpenClawCompatibleMessage[];
17
18
  estimatedTokens: number;
18
19
  systemPromptAddition: string;
20
+ promptAuthority: OpenClawCompatiblePromptAuthority;
19
21
  debug?: AssembleContextInternalResponse["debug"];
20
22
  };
21
23
  type OpenClawCompatibleCompactResult = {
@@ -1,6 +1,7 @@
1
1
  import { resolveIdentity } from "./identity.js";
2
2
  import { resolveUserCollection } from "./memory-scopes.js";
3
3
  const APPROX_CHARS_PER_TOKEN = 4;
4
+ const PROMPT_AUTHORITY_PREASSEMBLY_MAY_OVERFLOW = "preassembly_may_overflow";
4
5
  const ASSEMBLE_BUDGET_HEADROOM_TOKENS = 256;
5
6
  const ASSEMBLE_BUDGET_HEADROOM_FRACTION = 0.2;
6
7
  const DEFAULT_COMPACTION_THRESHOLD_FRACTION = 0.8;
@@ -10,6 +11,7 @@ const QUOTED_PHRASE_RE = /"([^"]{4,})"|'([^']{4,})'/g;
10
11
  const EXACT_RECALL_SEARCH_K = 32;
11
12
  const EXACT_RECALL_MAX_TOKENS = 4;
12
13
  const RESERVED_CURRENT_TURN_TOKENS = 150;
14
+ const AFTER_TURN_INGEST_MAX_TOKENS = 2048;
13
15
  const COMMON_QUERY_WORDS = new Set([
14
16
  "what", "does", "mean", "remember", "recall", "about", "this", "that",
15
17
  "the", "and", "for", "with", "from", "your", "have", "been", "were",
@@ -226,6 +228,18 @@ function trimMessagesToBudget(messages, tokenBudget) {
226
228
  }
227
229
  return [{ ...last, content: truncated }];
228
230
  }
231
+ function boundAfterTurnMessagesForIngest(messages, logger, sessionId) {
232
+ const estimatedTokens = approximateMessagesTokens(messages);
233
+ if (estimatedTokens <= AFTER_TURN_INGEST_MAX_TOKENS) {
234
+ return messages;
235
+ }
236
+ const bounded = trimMessagesToBudget(messages, AFTER_TURN_INGEST_MAX_TOKENS)
237
+ .map((message) => normalizeKernelMessage(message));
238
+ logger.warn?.(`LibraVDB afterTurn trimmed oversized ingest payload sessionId=${sessionId} ` +
239
+ `estimatedTokens=${estimatedTokens} maxTokens=${AFTER_TURN_INGEST_MAX_TOKENS} ` +
240
+ `forwardedMessages=${bounded.length}`);
241
+ return bounded;
242
+ }
229
243
  function enforceTokenBudgetInvariant(result, tokenBudget) {
230
244
  if (typeof tokenBudget !== "number" || !Number.isFinite(tokenBudget) || tokenBudget <= 0) {
231
245
  return result;
@@ -262,11 +276,19 @@ function buildBudgetFallbackContext(messages, tokenBudget) {
262
276
  messages: fallbackMessages,
263
277
  estimatedTokens: approximateMessagesTokens(fallbackMessages),
264
278
  systemPromptAddition: "",
279
+ promptAuthority: PROMPT_AUTHORITY_PREASSEMBLY_MAY_OVERFLOW,
265
280
  };
266
281
  }
267
282
  function resolvePredictiveCompactionTokenCount(args) {
268
- return (normalizeCurrentTokenCount(args.currentTokenCount) ??
269
- approximateMessagesTokens(args.messages) + approximateTokenCount(args.prompt ?? ""));
283
+ const currentTokenCount = normalizeCurrentTokenCount(args.currentTokenCount);
284
+ const sourcePressureEstimate = normalizeCurrentTokenCount(approximateMessagesTokens(args.messages) + approximateTokenCount(args.prompt ?? ""));
285
+ if (currentTokenCount == null) {
286
+ return sourcePressureEstimate ?? 1;
287
+ }
288
+ if (sourcePressureEstimate == null) {
289
+ return currentTokenCount;
290
+ }
291
+ return Math.max(currentTokenCount, sourcePressureEstimate);
270
292
  }
271
293
  function resolveAfterTurnPredictiveCompactionTokenCount(args) {
272
294
  const currentTokenCount = normalizeCurrentTokenCount(args.currentTokenCount);
@@ -516,6 +538,7 @@ export function normalizeAssembleResult(result) {
516
538
  messages,
517
539
  estimatedTokens: typeof result.estimatedTokens === "number" ? result.estimatedTokens : 0,
518
540
  systemPromptAddition: typeof result.systemPromptAddition === "string" ? result.systemPromptAddition : "",
541
+ promptAuthority: PROMPT_AUTHORITY_PREASSEMBLY_MAY_OVERFLOW,
519
542
  ...(result.debug != null ? { debug: result.debug } : {}),
520
543
  };
521
544
  }
@@ -902,6 +925,7 @@ export function buildContextEngineFactory(runtime, cfg, logger = console) {
902
925
  });
903
926
  const afterTurnMessages = selectAfterTurnMessages(args.messages, args.prePromptMessageCount, logger);
904
927
  const messages = normalizeKernelMessages(afterTurnMessages);
928
+ const ingestMessages = boundAfterTurnMessagesForIngest(messages, logger, sessionId);
905
929
  const msgCount = messages.length;
906
930
  logger.info?.(`LibraVDB afterTurn sessionId=${sessionId} userId=${userId} ` +
907
931
  `messageCount=${msgCount} totalMessages=${args.messages.length} ` +
@@ -916,7 +940,7 @@ export function buildContextEngineFactory(runtime, cfg, logger = console) {
916
940
  sessionId,
917
941
  sessionKey: args.sessionKey,
918
942
  userId,
919
- messages,
943
+ messages: ingestMessages,
920
944
  isHeartbeat: args.isHeartbeat,
921
945
  });
922
946
  await performAfterTurnPredictiveCompaction({
package/dist/index.js CHANGED
@@ -26516,6 +26516,7 @@ function resolveCliMemoryOperationScope(opts) {
26516
26516
 
26517
26517
  // src/context-engine.ts
26518
26518
  var APPROX_CHARS_PER_TOKEN = 4;
26519
+ var PROMPT_AUTHORITY_PREASSEMBLY_MAY_OVERFLOW = "preassembly_may_overflow";
26519
26520
  var ASSEMBLE_BUDGET_HEADROOM_TOKENS = 256;
26520
26521
  var ASSEMBLE_BUDGET_HEADROOM_FRACTION = 0.2;
26521
26522
  var DEFAULT_COMPACTION_THRESHOLD_FRACTION = 0.8;
@@ -26525,6 +26526,7 @@ var QUOTED_PHRASE_RE = /"([^"]{4,})"|'([^']{4,})'/g;
26525
26526
  var EXACT_RECALL_SEARCH_K = 32;
26526
26527
  var EXACT_RECALL_MAX_TOKENS = 4;
26527
26528
  var RESERVED_CURRENT_TURN_TOKENS = 150;
26529
+ var AFTER_TURN_INGEST_MAX_TOKENS = 2048;
26528
26530
  var COMMON_QUERY_WORDS = /* @__PURE__ */ new Set([
26529
26531
  "what",
26530
26532
  "does",
@@ -26749,6 +26751,17 @@ function trimMessagesToBudget(messages, tokenBudget) {
26749
26751
  }
26750
26752
  return [{ ...last, content: truncated }];
26751
26753
  }
26754
+ function boundAfterTurnMessagesForIngest(messages, logger, sessionId) {
26755
+ const estimatedTokens = approximateMessagesTokens(messages);
26756
+ if (estimatedTokens <= AFTER_TURN_INGEST_MAX_TOKENS) {
26757
+ return messages;
26758
+ }
26759
+ const bounded = trimMessagesToBudget(messages, AFTER_TURN_INGEST_MAX_TOKENS).map((message) => normalizeKernelMessage(message));
26760
+ logger.warn?.(
26761
+ `LibraVDB afterTurn trimmed oversized ingest payload sessionId=${sessionId} estimatedTokens=${estimatedTokens} maxTokens=${AFTER_TURN_INGEST_MAX_TOKENS} forwardedMessages=${bounded.length}`
26762
+ );
26763
+ return bounded;
26764
+ }
26752
26765
  function enforceTokenBudgetInvariant(result, tokenBudget) {
26753
26766
  if (typeof tokenBudget !== "number" || !Number.isFinite(tokenBudget) || tokenBudget <= 0) {
26754
26767
  return result;
@@ -26787,11 +26800,22 @@ function buildBudgetFallbackContext(messages, tokenBudget) {
26787
26800
  return {
26788
26801
  messages: fallbackMessages,
26789
26802
  estimatedTokens: approximateMessagesTokens(fallbackMessages),
26790
- systemPromptAddition: ""
26803
+ systemPromptAddition: "",
26804
+ promptAuthority: PROMPT_AUTHORITY_PREASSEMBLY_MAY_OVERFLOW
26791
26805
  };
26792
26806
  }
26793
26807
  function resolvePredictiveCompactionTokenCount(args) {
26794
- return normalizeCurrentTokenCount(args.currentTokenCount) ?? approximateMessagesTokens(args.messages) + approximateTokenCount(args.prompt ?? "");
26808
+ const currentTokenCount = normalizeCurrentTokenCount(args.currentTokenCount);
26809
+ const sourcePressureEstimate = normalizeCurrentTokenCount(
26810
+ approximateMessagesTokens(args.messages) + approximateTokenCount(args.prompt ?? "")
26811
+ );
26812
+ if (currentTokenCount == null) {
26813
+ return sourcePressureEstimate ?? 1;
26814
+ }
26815
+ if (sourcePressureEstimate == null) {
26816
+ return currentTokenCount;
26817
+ }
26818
+ return Math.max(currentTokenCount, sourcePressureEstimate);
26795
26819
  }
26796
26820
  function resolveAfterTurnPredictiveCompactionTokenCount(args) {
26797
26821
  const currentTokenCount = normalizeCurrentTokenCount(args.currentTokenCount);
@@ -27031,6 +27055,7 @@ function normalizeAssembleResult(result) {
27031
27055
  messages,
27032
27056
  estimatedTokens: typeof result.estimatedTokens === "number" ? result.estimatedTokens : 0,
27033
27057
  systemPromptAddition: typeof result.systemPromptAddition === "string" ? result.systemPromptAddition : "",
27058
+ promptAuthority: PROMPT_AUTHORITY_PREASSEMBLY_MAY_OVERFLOW,
27034
27059
  ...result.debug != null ? { debug: result.debug } : {}
27035
27060
  };
27036
27061
  }
@@ -27416,6 +27441,7 @@ function buildContextEngineFactory(runtime, cfg, logger = console) {
27416
27441
  });
27417
27442
  const afterTurnMessages = selectAfterTurnMessages(args.messages, args.prePromptMessageCount, logger);
27418
27443
  const messages = normalizeKernelMessages(afterTurnMessages);
27444
+ const ingestMessages = boundAfterTurnMessagesForIngest(messages, logger, sessionId);
27419
27445
  const msgCount = messages.length;
27420
27446
  logger.info?.(
27421
27447
  `LibraVDB afterTurn sessionId=${sessionId} userId=${userId} messageCount=${msgCount} totalMessages=${args.messages.length} prePromptMessageCount=${args.prePromptMessageCount ?? "unknown"} heartbeat=${args.isHeartbeat ?? false}`
@@ -27429,7 +27455,7 @@ function buildContextEngineFactory(runtime, cfg, logger = console) {
27429
27455
  sessionId,
27430
27456
  sessionKey: args.sessionKey,
27431
27457
  userId,
27432
- messages,
27458
+ messages: ingestMessages,
27433
27459
  isHeartbeat: args.isHeartbeat
27434
27460
  });
27435
27461
  await performAfterTurnPredictiveCompaction({
@@ -36578,6 +36604,55 @@ function resolveClientEndpoint(configuredEndpoint) {
36578
36604
  }
36579
36605
  return `unix:${path3.join(os3.homedir(), ".libravdbd", "run", sockName)}`;
36580
36606
  }
36607
+ function isLegacyJsonRpcHealthResponse(payload) {
36608
+ try {
36609
+ const parsed = JSON.parse(payload.trim());
36610
+ return parsed.jsonrpc === "2.0" && parsed.result?.ok === true;
36611
+ } catch {
36612
+ return false;
36613
+ }
36614
+ }
36615
+ async function detectLegacyJsonRpcDaemon(endpoint, timeoutMs = 500) {
36616
+ if (!endpoint.startsWith("unix:")) {
36617
+ return false;
36618
+ }
36619
+ const socketPath = endpoint.slice(5);
36620
+ if (!socketPath) {
36621
+ return false;
36622
+ }
36623
+ return await new Promise((resolve) => {
36624
+ let settled = false;
36625
+ let response = "";
36626
+ const socket = net.createConnection(socketPath);
36627
+ const finish = (value) => {
36628
+ if (settled) {
36629
+ return;
36630
+ }
36631
+ settled = true;
36632
+ clearTimeout(timer);
36633
+ socket.removeAllListeners();
36634
+ socket.destroy();
36635
+ resolve(value);
36636
+ };
36637
+ const timer = setTimeout(() => finish(false), Math.max(1, timeoutMs));
36638
+ timer.unref?.();
36639
+ socket.setEncoding("utf8");
36640
+ socket.on("connect", () => {
36641
+ socket.write('{"jsonrpc":"2.0","id":1,"method":"health","params":{}}\n');
36642
+ });
36643
+ socket.on("data", (chunk) => {
36644
+ response += chunk;
36645
+ if (isLegacyJsonRpcHealthResponse(response)) {
36646
+ finish(true);
36647
+ } else if (response.length > 4096) {
36648
+ finish(false);
36649
+ }
36650
+ });
36651
+ socket.on("end", () => finish(isLegacyJsonRpcHealthResponse(response)));
36652
+ socket.on("close", () => finish(isLegacyJsonRpcHealthResponse(response)));
36653
+ socket.on("error", () => finish(false));
36654
+ });
36655
+ }
36581
36656
  function createRpcMutex() {
36582
36657
  return {
36583
36658
  current: Promise.resolve(),
@@ -36636,11 +36711,15 @@ function createAuthInterceptor(state) {
36636
36711
  var LibravDBClient = class {
36637
36712
  client;
36638
36713
  secret;
36714
+ endpoint;
36715
+ legacyProbeTimeoutMs;
36639
36716
  nonceHex;
36640
36717
  closed = false;
36641
36718
  constructor(options = {}) {
36642
36719
  this.secret = options.secret ?? loadSecretFromEnv();
36643
36720
  const rawEndpoint = resolveClientEndpoint(options.endpoint);
36721
+ this.endpoint = rawEndpoint;
36722
+ this.legacyProbeTimeoutMs = Math.min(options.timeoutMs ?? 3e4, 1e3);
36644
36723
  const isUnix = rawEndpoint.startsWith("unix:");
36645
36724
  const socketPath = isUnix ? rawEndpoint.slice(5) : void 0;
36646
36725
  const credMode = resolveCredentialMode(rawEndpoint, options.tlsMode);
@@ -36696,8 +36775,14 @@ var LibravDBClient = class {
36696
36775
  }
36697
36776
  );
36698
36777
  } catch (error2) {
36778
+ const detail = error2 instanceof Error ? error2.message : String(error2);
36779
+ if (detail.includes("Protocol error") && await detectLegacyJsonRpcDaemon(this.endpoint, this.legacyProbeTimeoutMs)) {
36780
+ throw new Error(
36781
+ `LibraVDB: failed to handshake with daemon: ${detail}. The endpoint answered legacy JSON-RPC health; this plugin requires a gRPC-compatible libravdbd daemon. Update or restart libravdbd with gRPC support, or pin the plugin to a daemon-compatible release.`
36782
+ );
36783
+ }
36699
36784
  throw new Error(
36700
- `LibraVDB: failed to handshake with daemon: ${error2 instanceof Error ? error2.message : String(error2)}`
36785
+ `LibraVDB: failed to handshake with daemon: ${detail}`
36701
36786
  );
36702
36787
  }
36703
36788
  }
@@ -12,6 +12,8 @@ export interface LibravDBClientOptions {
12
12
  tlsClientKeyPath?: string;
13
13
  }
14
14
  export declare function resolveClientEndpoint(configuredEndpoint?: string): string;
15
+ export declare function isLegacyJsonRpcHealthResponse(payload: string): boolean;
16
+ export declare function detectLegacyJsonRpcDaemon(endpoint: string, timeoutMs?: number): Promise<boolean>;
15
17
  interface RpcMutex {
16
18
  current: Promise<void>;
17
19
  lock(): Promise<() => void>;
@@ -26,6 +28,8 @@ export declare function createAuthInterceptor(state: AuthInterceptorState): Inte
26
28
  export declare class LibravDBClient {
27
29
  private client;
28
30
  private readonly secret;
31
+ private readonly endpoint;
32
+ private readonly legacyProbeTimeoutMs;
29
33
  private nonceHex;
30
34
  private closed;
31
35
  constructor(options?: LibravDBClientOptions);
@@ -27,6 +27,57 @@ export function resolveClientEndpoint(configuredEndpoint) {
27
27
  }
28
28
  return `unix:${path.join(os.homedir(), ".libravdbd", "run", sockName)}`;
29
29
  }
30
+ export function isLegacyJsonRpcHealthResponse(payload) {
31
+ try {
32
+ const parsed = JSON.parse(payload.trim());
33
+ return parsed.jsonrpc === "2.0" && parsed.result?.ok === true;
34
+ }
35
+ catch {
36
+ return false;
37
+ }
38
+ }
39
+ export async function detectLegacyJsonRpcDaemon(endpoint, timeoutMs = 500) {
40
+ if (!endpoint.startsWith("unix:")) {
41
+ return false;
42
+ }
43
+ const socketPath = endpoint.slice(5);
44
+ if (!socketPath) {
45
+ return false;
46
+ }
47
+ return await new Promise((resolve) => {
48
+ let settled = false;
49
+ let response = "";
50
+ const socket = net.createConnection(socketPath);
51
+ const finish = (value) => {
52
+ if (settled) {
53
+ return;
54
+ }
55
+ settled = true;
56
+ clearTimeout(timer);
57
+ socket.removeAllListeners();
58
+ socket.destroy();
59
+ resolve(value);
60
+ };
61
+ const timer = setTimeout(() => finish(false), Math.max(1, timeoutMs));
62
+ timer.unref?.();
63
+ socket.setEncoding("utf8");
64
+ socket.on("connect", () => {
65
+ socket.write('{"jsonrpc":"2.0","id":1,"method":"health","params":{}}\n');
66
+ });
67
+ socket.on("data", (chunk) => {
68
+ response += chunk;
69
+ if (isLegacyJsonRpcHealthResponse(response)) {
70
+ finish(true);
71
+ }
72
+ else if (response.length > 4096) {
73
+ finish(false);
74
+ }
75
+ });
76
+ socket.on("end", () => finish(isLegacyJsonRpcHealthResponse(response)));
77
+ socket.on("close", () => finish(isLegacyJsonRpcHealthResponse(response)));
78
+ socket.on("error", () => finish(false));
79
+ });
80
+ }
30
81
  function createRpcMutex() {
31
82
  return {
32
83
  current: Promise.resolve(),
@@ -92,11 +143,15 @@ export function createAuthInterceptor(state) {
92
143
  export class LibravDBClient {
93
144
  client;
94
145
  secret;
146
+ endpoint;
147
+ legacyProbeTimeoutMs;
95
148
  nonceHex;
96
149
  closed = false;
97
150
  constructor(options = {}) {
98
151
  this.secret = options.secret ?? loadSecretFromEnv();
99
152
  const rawEndpoint = resolveClientEndpoint(options.endpoint);
153
+ this.endpoint = rawEndpoint;
154
+ this.legacyProbeTimeoutMs = Math.min(options.timeoutMs ?? 30000, 1000);
100
155
  const isUnix = rawEndpoint.startsWith("unix:");
101
156
  const socketPath = isUnix ? rawEndpoint.slice(5) : undefined;
102
157
  const credMode = resolveCredentialMode(rawEndpoint, options.tlsMode);
@@ -151,7 +206,13 @@ export class LibravDBClient {
151
206
  });
152
207
  }
153
208
  catch (error) {
154
- throw new Error(`LibraVDB: failed to handshake with daemon: ${error instanceof Error ? error.message : String(error)}`);
209
+ const detail = error instanceof Error ? error.message : String(error);
210
+ if (detail.includes("Protocol error") && await detectLegacyJsonRpcDaemon(this.endpoint, this.legacyProbeTimeoutMs)) {
211
+ throw new Error(`LibraVDB: failed to handshake with daemon: ${detail}. ` +
212
+ "The endpoint answered legacy JSON-RPC health; this plugin requires a gRPC-compatible libravdbd daemon. " +
213
+ "Update or restart libravdbd with gRPC support, or pin the plugin to a daemon-compatible release.");
214
+ }
215
+ throw new Error(`LibraVDB: failed to handshake with daemon: ${detail}`);
155
216
  }
156
217
  }
157
218
  guardOpen() {
@@ -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.6.16",
5
+ "version": "1.6.18",
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.6.16",
3
+ "version": "1.6.18",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",