@xdarkicex/openclaw-memory-libravdb 1.6.15 → 1.6.17

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/README.md CHANGED
@@ -33,6 +33,19 @@ brew install libravdbd
33
33
  brew services start libravdbd
34
34
  ```
35
35
 
36
+ > **After upgrades:** Always restart the daemon so the newly installed binary takes effect:
37
+ > ```bash
38
+ > # macOS (Homebrew)
39
+ > brew services restart libravdbd
40
+ >
41
+ > # Linux (systemd)
42
+ > systemctl --user restart libravdbd
43
+ >
44
+ > # Linux (no systemd — kill and restart manually)
45
+ > killall libravdbd && libravdbd &
46
+ > ```
47
+ > Failing to restart leaves the old process running — it will not auto-replace a live background service. If you see "Protocol error" or connection failures after an upgrade, this is almost always the cause.
48
+
36
49
  **Linux (APT)**
37
50
 
38
51
  ```bash
@@ -99,5 +99,6 @@ export declare function buildContextEngineFactory(runtime: PluginRuntime, cfg: P
99
99
  tokenBudget?: number;
100
100
  runtimeContext?: Record<string, unknown>;
101
101
  }): Promise<import("@xdarkicex/libravdb-contracts").AfterTurnKernelResponse>;
102
+ dispose(): Promise<void>;
102
103
  };
103
104
  export {};
@@ -521,6 +521,7 @@ export function normalizeAssembleResult(result) {
521
521
  }
522
522
  export function buildContextEngineFactory(runtime, cfg, logger = console) {
523
523
  const predictiveContextCache = new Map();
524
+ const PREDICTIVE_CACHE_MAX_SIZE = 100;
524
525
  let cachedIdentity = null;
525
526
  let cachedSessionKey;
526
527
  function resolveUserId(args) {
@@ -743,6 +744,7 @@ export function buildContextEngineFactory(runtime, cfg, logger = console) {
743
744
  ownsCompaction: true,
744
745
  async bootstrap(args) {
745
746
  const sessionId = requireSessionId(args.sessionId, "bootstrap");
747
+ predictiveContextCache.delete(sessionId);
746
748
  const userId = resolveUserId({
747
749
  userIdOverride: args.userId,
748
750
  sessionKey: args.sessionKey,
@@ -925,6 +927,11 @@ export function buildContextEngineFactory(runtime, cfg, logger = console) {
925
927
  });
926
928
  const predictions = result.predictions;
927
929
  if (Array.isArray(predictions) && predictions.length > 0) {
930
+ if (predictiveContextCache.size >= PREDICTIVE_CACHE_MAX_SIZE) {
931
+ const oldest = predictiveContextCache.keys().next().value;
932
+ if (oldest !== undefined)
933
+ predictiveContextCache.delete(oldest);
934
+ }
928
935
  predictiveContextCache.set(sessionId, predictions);
929
936
  }
930
937
  return result;
@@ -934,6 +941,9 @@ export function buildContextEngineFactory(runtime, cfg, logger = console) {
934
941
  `${error instanceof Error ? error.message : String(error)}`);
935
942
  throw error;
936
943
  }
937
- }
944
+ },
945
+ async dispose() {
946
+ predictiveContextCache.clear();
947
+ },
938
948
  };
939
949
  }
package/dist/index.js CHANGED
@@ -27036,6 +27036,7 @@ function normalizeAssembleResult(result) {
27036
27036
  }
27037
27037
  function buildContextEngineFactory(runtime, cfg, logger = console) {
27038
27038
  const predictiveContextCache = /* @__PURE__ */ new Map();
27039
+ const PREDICTIVE_CACHE_MAX_SIZE = 100;
27039
27040
  let cachedIdentity = null;
27040
27041
  let cachedSessionKey;
27041
27042
  function resolveUserId(args) {
@@ -27245,6 +27246,7 @@ function buildContextEngineFactory(runtime, cfg, logger = console) {
27245
27246
  ownsCompaction: true,
27246
27247
  async bootstrap(args) {
27247
27248
  const sessionId = requireSessionId(args.sessionId, "bootstrap");
27249
+ predictiveContextCache.delete(sessionId);
27248
27250
  const userId = resolveUserId({
27249
27251
  userIdOverride: args.userId,
27250
27252
  sessionKey: args.sessionKey
@@ -27438,6 +27440,10 @@ function buildContextEngineFactory(runtime, cfg, logger = console) {
27438
27440
  });
27439
27441
  const predictions = result.predictions;
27440
27442
  if (Array.isArray(predictions) && predictions.length > 0) {
27443
+ if (predictiveContextCache.size >= PREDICTIVE_CACHE_MAX_SIZE) {
27444
+ const oldest = predictiveContextCache.keys().next().value;
27445
+ if (oldest !== void 0) predictiveContextCache.delete(oldest);
27446
+ }
27441
27447
  predictiveContextCache.set(sessionId, predictions);
27442
27448
  }
27443
27449
  return result;
@@ -27447,6 +27453,9 @@ function buildContextEngineFactory(runtime, cfg, logger = console) {
27447
27453
  );
27448
27454
  throw error2;
27449
27455
  }
27456
+ },
27457
+ async dispose() {
27458
+ predictiveContextCache.clear();
27450
27459
  }
27451
27460
  };
27452
27461
  }
@@ -36569,6 +36578,55 @@ function resolveClientEndpoint(configuredEndpoint) {
36569
36578
  }
36570
36579
  return `unix:${path3.join(os3.homedir(), ".libravdbd", "run", sockName)}`;
36571
36580
  }
36581
+ function isLegacyJsonRpcHealthResponse(payload) {
36582
+ try {
36583
+ const parsed = JSON.parse(payload.trim());
36584
+ return parsed.jsonrpc === "2.0" && parsed.result?.ok === true;
36585
+ } catch {
36586
+ return false;
36587
+ }
36588
+ }
36589
+ async function detectLegacyJsonRpcDaemon(endpoint, timeoutMs = 500) {
36590
+ if (!endpoint.startsWith("unix:")) {
36591
+ return false;
36592
+ }
36593
+ const socketPath = endpoint.slice(5);
36594
+ if (!socketPath) {
36595
+ return false;
36596
+ }
36597
+ return await new Promise((resolve) => {
36598
+ let settled = false;
36599
+ let response = "";
36600
+ const socket = net.createConnection(socketPath);
36601
+ const finish = (value) => {
36602
+ if (settled) {
36603
+ return;
36604
+ }
36605
+ settled = true;
36606
+ clearTimeout(timer);
36607
+ socket.removeAllListeners();
36608
+ socket.destroy();
36609
+ resolve(value);
36610
+ };
36611
+ const timer = setTimeout(() => finish(false), Math.max(1, timeoutMs));
36612
+ timer.unref?.();
36613
+ socket.setEncoding("utf8");
36614
+ socket.on("connect", () => {
36615
+ socket.write('{"jsonrpc":"2.0","id":1,"method":"health","params":{}}\n');
36616
+ });
36617
+ socket.on("data", (chunk) => {
36618
+ response += chunk;
36619
+ if (isLegacyJsonRpcHealthResponse(response)) {
36620
+ finish(true);
36621
+ } else if (response.length > 4096) {
36622
+ finish(false);
36623
+ }
36624
+ });
36625
+ socket.on("end", () => finish(isLegacyJsonRpcHealthResponse(response)));
36626
+ socket.on("close", () => finish(isLegacyJsonRpcHealthResponse(response)));
36627
+ socket.on("error", () => finish(false));
36628
+ });
36629
+ }
36572
36630
  function createRpcMutex() {
36573
36631
  return {
36574
36632
  current: Promise.resolve(),
@@ -36627,11 +36685,15 @@ function createAuthInterceptor(state) {
36627
36685
  var LibravDBClient = class {
36628
36686
  client;
36629
36687
  secret;
36688
+ endpoint;
36689
+ legacyProbeTimeoutMs;
36630
36690
  nonceHex;
36631
36691
  closed = false;
36632
36692
  constructor(options = {}) {
36633
36693
  this.secret = options.secret ?? loadSecretFromEnv();
36634
36694
  const rawEndpoint = resolveClientEndpoint(options.endpoint);
36695
+ this.endpoint = rawEndpoint;
36696
+ this.legacyProbeTimeoutMs = Math.min(options.timeoutMs ?? 3e4, 1e3);
36635
36697
  const isUnix = rawEndpoint.startsWith("unix:");
36636
36698
  const socketPath = isUnix ? rawEndpoint.slice(5) : void 0;
36637
36699
  const credMode = resolveCredentialMode(rawEndpoint, options.tlsMode);
@@ -36687,8 +36749,14 @@ var LibravDBClient = class {
36687
36749
  }
36688
36750
  );
36689
36751
  } catch (error2) {
36752
+ const detail = error2 instanceof Error ? error2.message : String(error2);
36753
+ if (detail.includes("Protocol error") && await detectLegacyJsonRpcDaemon(this.endpoint, this.legacyProbeTimeoutMs)) {
36754
+ throw new Error(
36755
+ `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.`
36756
+ );
36757
+ }
36690
36758
  throw new Error(
36691
- `LibraVDB: failed to handshake with daemon: ${error2 instanceof Error ? error2.message : String(error2)}`
36759
+ `LibraVDB: failed to handshake with daemon: ${detail}`
36692
36760
  );
36693
36761
  }
36694
36762
  }
@@ -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.15",
5
+ "version": "1.6.17",
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.15",
3
+ "version": "1.6.17",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",