@xdarkicex/openclaw-memory-libravdb 1.4.38 → 1.4.40

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/dist/cli.js CHANGED
@@ -276,13 +276,22 @@ async function runSearch(runtime, cfg, queryArg, opts, logger) {
276
276
  process.exitCode = 1;
277
277
  return;
278
278
  }
279
+ let maxResults;
280
+ let explicitMinScore;
281
+ try {
282
+ maxResults = normalizeCliLimit(opts?.maxResults ?? opts?.limit, "--max-results");
283
+ explicitMinScore = normalizeCliScore(opts?.minScore, "--min-score");
284
+ }
285
+ catch (validationError) {
286
+ logger.error(formatError(validationError));
287
+ process.exitCode = 1;
288
+ return;
289
+ }
279
290
  try {
280
291
  const bridge = buildMemoryRuntimeBridge(runtime.getRpc, cfg);
281
292
  const { manager } = await bridge.getMemorySearchManager({
282
293
  agentId: opts?.agent,
283
294
  });
284
- const maxResults = normalizeLimit(opts?.maxResults ?? opts?.limit);
285
- const explicitMinScore = normalizeNumber(opts?.minScore);
286
295
  const minScore = explicitMinScore ?? resolveDefaultSearchMinScore(manager.status(), cfg);
287
296
  const results = (await manager.search({
288
297
  query,
@@ -336,10 +345,16 @@ async function runFlush(runtime, opts, logger) {
336
345
  }
337
346
  }
338
347
  async function runExport(runtime, opts, logger) {
348
+ const namespace = resolveCliNamespace(opts);
349
+ if (!namespace) {
350
+ logger.error("LibraVDB export requires a namespace. Provide --user-id or --session-key.");
351
+ process.exitCode = 1;
352
+ return;
353
+ }
339
354
  try {
340
355
  const rpc = await runtime.getRpc();
341
356
  const result = await rpc.call("export_memory", {
342
- namespace: resolveCliNamespace(opts),
357
+ namespace,
343
358
  });
344
359
  for (const record of result.records ?? []) {
345
360
  stdout.write(`${JSON.stringify(record)}\n`);
@@ -351,11 +366,20 @@ async function runExport(runtime, opts, logger) {
351
366
  }
352
367
  }
353
368
  async function runJournal(runtime, opts, logger) {
369
+ let limit;
370
+ try {
371
+ limit = normalizeCliLimit(opts?.limit, "--limit");
372
+ }
373
+ catch (validationError) {
374
+ logger.error(formatError(validationError));
375
+ process.exitCode = 1;
376
+ return;
377
+ }
354
378
  try {
355
379
  const rpc = await runtime.getRpc();
356
380
  const result = await rpc.call("list_lifecycle_journal", {
357
381
  sessionId: opts?.sessionId?.trim() || undefined,
358
- limit: normalizeLimit(opts?.limit),
382
+ limit,
359
383
  });
360
384
  for (const record of result.results ?? []) {
361
385
  stdout.write(`${JSON.stringify(record)}\n`);
@@ -400,17 +424,30 @@ function formatError(error) {
400
424
  }
401
425
  return String(error);
402
426
  }
403
- function normalizeLimit(limit) {
404
- if (typeof limit === "number" && Number.isFinite(limit) && limit > 0) {
405
- return Math.floor(limit);
427
+ function normalizeCliLimit(limit, optionName) {
428
+ if (limit === undefined)
429
+ return undefined;
430
+ const parsed = parseStrictNumber(limit);
431
+ if (Number.isFinite(parsed) && Number.isInteger(parsed) && parsed > 0) {
432
+ return parsed;
406
433
  }
407
- if (typeof limit === "string") {
408
- const parsed = Number.parseInt(limit, 10);
409
- if (Number.isFinite(parsed) && parsed > 0) {
410
- return parsed;
411
- }
434
+ throw new Error(`Invalid value for ${optionName}: must be a positive integer`);
435
+ }
436
+ function normalizeCliScore(value, optionName) {
437
+ if (value === undefined)
438
+ return undefined;
439
+ const parsed = parseStrictNumber(value);
440
+ if (Number.isFinite(parsed) && parsed >= 0 && parsed <= 1) {
441
+ return parsed;
412
442
  }
413
- return undefined;
443
+ throw new Error(`Invalid value for ${optionName}: must be a number between 0 and 1`);
444
+ }
445
+ function parseStrictNumber(value) {
446
+ if (typeof value === "number") {
447
+ return value;
448
+ }
449
+ const trimmed = value.trim();
450
+ return trimmed === "" ? NaN : Number(trimmed);
414
451
  }
415
452
  function normalizeNumber(value) {
416
453
  if (typeof value === "number" && Number.isFinite(value)) {
@@ -8,8 +8,9 @@ type KernelCompatibleMessage = {
8
8
  };
9
9
  type OpenClawCompatibleMessage = {
10
10
  role: string;
11
- content: string;
11
+ content: string | unknown[];
12
12
  id?: string;
13
+ [key: string]: unknown;
13
14
  };
14
15
  type OpenClawCompatibleAssembleResult = {
15
16
  messages: OpenClawCompatibleMessage[];
@@ -76,11 +77,7 @@ export declare function buildContextEngineFactory(runtime: PluginRuntime, cfg: P
76
77
  sessionId: string;
77
78
  sessionKey?: string;
78
79
  userId?: string;
79
- messages: Array<{
80
- role: string;
81
- content: unknown;
82
- id?: string;
83
- }>;
80
+ messages: OpenClawCompatibleMessage[];
84
81
  tokenBudget: number;
85
82
  prompt?: string;
86
83
  currentTokenCount?: number;
@@ -96,11 +93,7 @@ export declare function buildContextEngineFactory(runtime: PluginRuntime, cfg: P
96
93
  sessionId: string;
97
94
  sessionKey?: string;
98
95
  userId?: string;
99
- messages: Array<{
100
- role: string;
101
- content: unknown;
102
- id?: string;
103
- }>;
96
+ messages: OpenClawCompatibleMessage[];
104
97
  prePromptMessageCount?: number;
105
98
  isHeartbeat?: boolean;
106
99
  tokenBudget?: number;
@@ -85,9 +85,13 @@ function normalizeKernelContent(content) {
85
85
  return content.map(stringifyKernelBlock).filter((part) => part.length > 0).join("\n");
86
86
  }
87
87
  function approximateTokenCount(text) {
88
- if (!text)
88
+ if (typeof text === "string") {
89
+ return Math.ceil(text.length / APPROX_CHARS_PER_TOKEN);
90
+ }
91
+ if (!Array.isArray(text)) {
89
92
  return 0;
90
- return Math.ceil(text.length / APPROX_CHARS_PER_TOKEN);
93
+ }
94
+ return Math.ceil(normalizeKernelContent(text).length / APPROX_CHARS_PER_TOKEN);
91
95
  }
92
96
  function approximateMessageTokens(message) {
93
97
  // Approximate per-message wrapper overhead so trimming is conservative.
@@ -162,10 +166,11 @@ function truncateContentToTokenBudget(content, tokenBudget) {
162
166
  if (tokenBudget <= 0)
163
167
  return "";
164
168
  const maxChars = Math.max(1, tokenBudget * APPROX_CHARS_PER_TOKEN);
165
- if (content.length <= maxChars)
166
- return content;
169
+ const normalized = normalizeKernelContent(content);
170
+ if (normalized.length <= maxChars)
171
+ return normalized;
167
172
  // Keep the tail so recent tool output / latest answer content is preserved.
168
- return content.slice(content.length - maxChars);
173
+ return normalized.slice(normalized.length - maxChars);
169
174
  }
170
175
  function trimMessagesToBudget(messages, tokenBudget) {
171
176
  if (tokenBudget <= 0 || messages.length === 0) {
@@ -399,7 +404,7 @@ export function buildContextEngineFactory(runtime, cfg, logger = console) {
399
404
  return assembled;
400
405
  const existingBlocks = [
401
406
  assembled.systemPromptAddition,
402
- ...assembled.messages.map((message) => message.content),
407
+ ...assembled.messages.map((message) => normalizeKernelContent(message.content)),
403
408
  ]
404
409
  .flatMap((block) => block.split(/\n+/))
405
410
  .map((block) => block.trim())
@@ -657,7 +662,7 @@ export function buildContextEngineFactory(runtime, cfg, logger = console) {
657
662
  if (!compactionResult.ok) {
658
663
  logger.warn?.(`LibraVDB predictive compaction blocked assemble path at ${currentContextTokens} tokens ` +
659
664
  `(threshold=${dynamicCompactThreshold}): ${compactionResult.reason ?? "compaction failed"}`);
660
- return buildBudgetFallbackContext(messages, args.tokenBudget);
665
+ return buildBudgetFallbackContext(args.messages, args.tokenBudget);
661
666
  }
662
667
  }
663
668
  const kernel = await getKernelOrNull("assemble");
@@ -682,7 +687,7 @@ export function buildContextEngineFactory(runtime, cfg, logger = console) {
682
687
  }
683
688
  catch (error) {
684
689
  logger.warn?.(`LibraVDB assemble kernel failed, using budget-clamped fallback context: ${error instanceof Error ? error.message : String(error)}`);
685
- return buildBudgetFallbackContext(messages, args.tokenBudget);
690
+ return buildBudgetFallbackContext(args.messages, args.tokenBudget);
686
691
  }
687
692
  }
688
693
  const rpc = await runtime.getRpc();
@@ -707,7 +712,7 @@ export function buildContextEngineFactory(runtime, cfg, logger = console) {
707
712
  }
708
713
  catch (error) {
709
714
  logger.warn?.(`LibraVDB assemble sidecar failed, using budget-clamped fallback context: ${error instanceof Error ? error.message : String(error)}`);
710
- return buildBudgetFallbackContext(messages, args.tokenBudget);
715
+ return buildBudgetFallbackContext(args.messages, args.tokenBudget);
711
716
  }
712
717
  },
713
718
  async compact(args) {
package/dist/index.js CHANGED
@@ -33354,13 +33354,21 @@ async function runSearch(runtime, cfg, queryArg, opts, logger) {
33354
33354
  process.exitCode = 1;
33355
33355
  return;
33356
33356
  }
33357
+ let maxResults;
33358
+ let explicitMinScore;
33359
+ try {
33360
+ maxResults = normalizeCliLimit(opts?.maxResults ?? opts?.limit, "--max-results");
33361
+ explicitMinScore = normalizeCliScore(opts?.minScore, "--min-score");
33362
+ } catch (validationError) {
33363
+ logger.error(formatError2(validationError));
33364
+ process.exitCode = 1;
33365
+ return;
33366
+ }
33357
33367
  try {
33358
33368
  const bridge = buildMemoryRuntimeBridge(runtime.getRpc, cfg);
33359
33369
  const { manager } = await bridge.getMemorySearchManager({
33360
33370
  agentId: opts?.agent
33361
33371
  });
33362
- const maxResults = normalizeLimit(opts?.maxResults ?? opts?.limit);
33363
- const explicitMinScore = normalizeNumber2(opts?.minScore);
33364
33372
  const minScore = explicitMinScore ?? resolveDefaultSearchMinScore(manager.status(), cfg);
33365
33373
  const results = await manager.search(
33366
33374
  {
@@ -33414,10 +33422,16 @@ async function runFlush(runtime, opts, logger) {
33414
33422
  }
33415
33423
  }
33416
33424
  async function runExport(runtime, opts, logger) {
33425
+ const namespace = resolveCliNamespace(opts);
33426
+ if (!namespace) {
33427
+ logger.error("LibraVDB export requires a namespace. Provide --user-id or --session-key.");
33428
+ process.exitCode = 1;
33429
+ return;
33430
+ }
33417
33431
  try {
33418
33432
  const rpc = await runtime.getRpc();
33419
33433
  const result = await rpc.call("export_memory", {
33420
- namespace: resolveCliNamespace(opts)
33434
+ namespace
33421
33435
  });
33422
33436
  for (const record of result.records ?? []) {
33423
33437
  stdout.write(`${JSON.stringify(record)}
@@ -33429,11 +33443,19 @@ async function runExport(runtime, opts, logger) {
33429
33443
  }
33430
33444
  }
33431
33445
  async function runJournal(runtime, opts, logger) {
33446
+ let limit;
33447
+ try {
33448
+ limit = normalizeCliLimit(opts?.limit, "--limit");
33449
+ } catch (validationError) {
33450
+ logger.error(formatError2(validationError));
33451
+ process.exitCode = 1;
33452
+ return;
33453
+ }
33432
33454
  try {
33433
33455
  const rpc = await runtime.getRpc();
33434
33456
  const result = await rpc.call("list_lifecycle_journal", {
33435
33457
  sessionId: opts?.sessionId?.trim() || void 0,
33436
- limit: normalizeLimit(opts?.limit)
33458
+ limit
33437
33459
  });
33438
33460
  for (const record of result.results ?? []) {
33439
33461
  stdout.write(`${JSON.stringify(record)}
@@ -33478,17 +33500,28 @@ function formatError2(error) {
33478
33500
  }
33479
33501
  return String(error);
33480
33502
  }
33481
- function normalizeLimit(limit) {
33482
- if (typeof limit === "number" && Number.isFinite(limit) && limit > 0) {
33483
- return Math.floor(limit);
33503
+ function normalizeCliLimit(limit, optionName) {
33504
+ if (limit === void 0) return void 0;
33505
+ const parsed = parseStrictNumber(limit);
33506
+ if (Number.isFinite(parsed) && Number.isInteger(parsed) && parsed > 0) {
33507
+ return parsed;
33484
33508
  }
33485
- if (typeof limit === "string") {
33486
- const parsed = Number.parseInt(limit, 10);
33487
- if (Number.isFinite(parsed) && parsed > 0) {
33488
- return parsed;
33489
- }
33509
+ throw new Error(`Invalid value for ${optionName}: must be a positive integer`);
33510
+ }
33511
+ function normalizeCliScore(value, optionName) {
33512
+ if (value === void 0) return void 0;
33513
+ const parsed = parseStrictNumber(value);
33514
+ if (Number.isFinite(parsed) && parsed >= 0 && parsed <= 1) {
33515
+ return parsed;
33490
33516
  }
33491
- return void 0;
33517
+ throw new Error(`Invalid value for ${optionName}: must be a number between 0 and 1`);
33518
+ }
33519
+ function parseStrictNumber(value) {
33520
+ if (typeof value === "number") {
33521
+ return value;
33522
+ }
33523
+ const trimmed = value.trim();
33524
+ return trimmed === "" ? NaN : Number(trimmed);
33492
33525
  }
33493
33526
  function normalizeNumber2(value) {
33494
33527
  if (typeof value === "number" && Number.isFinite(value)) {
@@ -33631,8 +33664,13 @@ function normalizeKernelContent(content) {
33631
33664
  return content.map(stringifyKernelBlock).filter((part) => part.length > 0).join("\n");
33632
33665
  }
33633
33666
  function approximateTokenCount(text) {
33634
- if (!text) return 0;
33635
- return Math.ceil(text.length / APPROX_CHARS_PER_TOKEN);
33667
+ if (typeof text === "string") {
33668
+ return Math.ceil(text.length / APPROX_CHARS_PER_TOKEN);
33669
+ }
33670
+ if (!Array.isArray(text)) {
33671
+ return 0;
33672
+ }
33673
+ return Math.ceil(normalizeKernelContent(text).length / APPROX_CHARS_PER_TOKEN);
33636
33674
  }
33637
33675
  function approximateMessageTokens(message) {
33638
33676
  return approximateTokenCount(message.content) + 8;
@@ -33698,8 +33736,9 @@ function logPredictiveCompactionOutcome(params) {
33698
33736
  function truncateContentToTokenBudget(content, tokenBudget) {
33699
33737
  if (tokenBudget <= 0) return "";
33700
33738
  const maxChars = Math.max(1, tokenBudget * APPROX_CHARS_PER_TOKEN);
33701
- if (content.length <= maxChars) return content;
33702
- return content.slice(content.length - maxChars);
33739
+ const normalized = normalizeKernelContent(content);
33740
+ if (normalized.length <= maxChars) return normalized;
33741
+ return normalized.slice(normalized.length - maxChars);
33703
33742
  }
33704
33743
  function trimMessagesToBudget(messages, tokenBudget) {
33705
33744
  if (tokenBudget <= 0 || messages.length === 0) {
@@ -33919,7 +33958,7 @@ function buildContextEngineFactory(runtime, cfg, logger = console) {
33919
33958
  if (tokens.length === 0) return assembled;
33920
33959
  const existingBlocks = [
33921
33960
  assembled.systemPromptAddition,
33922
- ...assembled.messages.map((message) => message.content)
33961
+ ...assembled.messages.map((message) => normalizeKernelContent(message.content))
33923
33962
  ].flatMap((block) => block.split(/\n+/)).map((block) => block.trim()).filter((block) => block.length > 0);
33924
33963
  const missingTokens = tokens.filter(
33925
33964
  (token) => !existingBlocks.some((block) => isExactRecallFact(block, token))
@@ -34161,7 +34200,7 @@ function buildContextEngineFactory(runtime, cfg, logger = console) {
34161
34200
  logger.warn?.(
34162
34201
  `LibraVDB predictive compaction blocked assemble path at ${currentContextTokens} tokens (threshold=${dynamicCompactThreshold}): ${compactionResult.reason ?? "compaction failed"}`
34163
34202
  );
34164
- return buildBudgetFallbackContext(messages, args.tokenBudget);
34203
+ return buildBudgetFallbackContext(args.messages, args.tokenBudget);
34165
34204
  }
34166
34205
  }
34167
34206
  const kernel = await getKernelOrNull("assemble");
@@ -34190,7 +34229,7 @@ function buildContextEngineFactory(runtime, cfg, logger = console) {
34190
34229
  logger.warn?.(
34191
34230
  `LibraVDB assemble kernel failed, using budget-clamped fallback context: ${error instanceof Error ? error.message : String(error)}`
34192
34231
  );
34193
- return buildBudgetFallbackContext(messages, args.tokenBudget);
34232
+ return buildBudgetFallbackContext(args.messages, args.tokenBudget);
34194
34233
  }
34195
34234
  }
34196
34235
  const rpc = await runtime.getRpc();
@@ -34219,7 +34258,7 @@ function buildContextEngineFactory(runtime, cfg, logger = console) {
34219
34258
  logger.warn?.(
34220
34259
  `LibraVDB assemble sidecar failed, using budget-clamped fallback context: ${error instanceof Error ? error.message : String(error)}`
34221
34260
  );
34222
- return buildBudgetFallbackContext(messages, args.tokenBudget);
34261
+ return buildBudgetFallbackContext(args.messages, args.tokenBudget);
34223
34262
  }
34224
34263
  },
34225
34264
  async compact(args) {
@@ -39552,7 +39591,7 @@ function formatError5(error) {
39552
39591
  function enrichStartupError(error, healthMessage) {
39553
39592
  const rawMessage = error instanceof Error ? error.message : String(error);
39554
39593
  const message = rawMessage.trim() || "LibraVDB daemon startup failed";
39555
- if (message.includes("install and start libravdbd separately") || message.includes("package does not provision the daemon binary")) {
39594
+ if (message.includes("package does not provision the daemon binary")) {
39556
39595
  return error instanceof Error ? error : new Error(message);
39557
39596
  }
39558
39597
  const shouldHint = /health check|daemon unavailable|connection refused|ECONNREFUSED|ENOENT|fallback mode|ONNX Runtime|embedder/i.test(
@@ -133,7 +133,7 @@ function formatError(error) {
133
133
  export function enrichStartupError(error, healthMessage) {
134
134
  const rawMessage = error instanceof Error ? error.message : String(error);
135
135
  const message = rawMessage.trim() || "LibraVDB daemon startup failed";
136
- if (message.includes("install and start libravdbd separately") || message.includes("package does not provision the daemon binary")) {
136
+ if (message.includes("package does not provision the daemon binary")) {
137
137
  return error instanceof Error ? error : new Error(message);
138
138
  }
139
139
  const shouldHint = /health check|daemon unavailable|connection refused|ECONNREFUSED|ENOENT|fallback mode|ONNX Runtime|embedder/i.test(`${message} ${healthMessage ?? ""}`);
@@ -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.38",
5
+ "version": "1.4.40",
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.38",
3
+ "version": "1.4.40",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",