@xdarkicex/openclaw-memory-libravdb 1.9.10-beta.10 → 1.9.10-beta.11

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.
@@ -16,6 +16,10 @@ const EXACT_RECALL_MAX_TOKENS = 4;
16
16
  const RESERVED_CURRENT_TURN_TOKENS = 150;
17
17
  const AFTER_TURN_INGEST_MAX_TOKENS = 2048;
18
18
  const OPENCLAW_LEADING_TIMESTAMP_PREFIX_RE = /^\[[A-Za-z]{3} \d{4}-\d{2}-\d{2} \d{2}:\d{2}[^\]]*\] */;
19
+ const SELECTED_CONTEXT_HEADER = "Conversation context (untrusted, chronological, selected for current message):";
20
+ const RETRIEVAL_QUERY_MAX_CHARS = 1000;
21
+ const SELECTED_CONTEXT_TURN_RE = /^#\d+\s+[A-Za-z]{3}\s+\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}(?::\d{2})?\s+\S+\s+([^:\n]{1,80}):\s*(.*)$/;
22
+ const ASSISTANT_SPEAKER_RE = /\b(?:assistant|openclaw|z3robot|bot)\b/i;
19
23
  const OPENCLAW_METADATA_HEADERS = [
20
24
  "Conversation info (untrusted metadata):",
21
25
  "Sender (untrusted metadata):",
@@ -196,6 +200,54 @@ function normalizeKernelContent(content, options = {}) {
196
200
  retainContext: options.retainOpenClawContext === true,
197
201
  });
198
202
  }
203
+ function normalizeRetrievalQuery(primaryText, fallbackText = "") {
204
+ const primary = normalizeRetrievalCandidate(primaryText);
205
+ if (primary)
206
+ return primary;
207
+ return normalizeRetrievalCandidate(fallbackText);
208
+ }
209
+ function normalizeRetrievalCandidate(text) {
210
+ const normalized = text
211
+ .replace(OPENCLAW_LEADING_TIMESTAMP_PREFIX_RE, "")
212
+ .replace(/\r\n/g, "\n")
213
+ .trim();
214
+ if (!normalized)
215
+ return "";
216
+ const selected = extractLatestSelectedContextUtterance(normalized);
217
+ const candidate = selected || normalized;
218
+ return capRetrievalQuery(candidate.replace(/\s+/g, " ").trim());
219
+ }
220
+ function extractLatestSelectedContextUtterance(text) {
221
+ if (!text.startsWith(SELECTED_CONTEXT_HEADER))
222
+ return "";
223
+ const turns = [];
224
+ for (const rawLine of text.slice(SELECTED_CONTEXT_HEADER.length).split("\n")) {
225
+ const line = rawLine.trim();
226
+ if (!line)
227
+ continue;
228
+ const match = line.match(SELECTED_CONTEXT_TURN_RE);
229
+ if (match) {
230
+ turns.push({ speaker: match[1].trim(), text: [match[2].trim()] });
231
+ continue;
232
+ }
233
+ if (turns.length > 0) {
234
+ turns[turns.length - 1].text.push(line);
235
+ }
236
+ }
237
+ for (let i = turns.length - 1; i >= 0; i--) {
238
+ const turn = turns[i];
239
+ const content = turn.text.join(" ").trim();
240
+ if (content && !ASSISTANT_SPEAKER_RE.test(turn.speaker)) {
241
+ return content;
242
+ }
243
+ }
244
+ return "";
245
+ }
246
+ function capRetrievalQuery(text) {
247
+ if (text.length <= RETRIEVAL_QUERY_MAX_CHARS)
248
+ return text;
249
+ return text.slice(text.length - RETRIEVAL_QUERY_MAX_CHARS);
250
+ }
199
251
  /**
200
252
  * Symbol-keyed hook that drains all pending async ingestion queues.
201
253
  * Tests import this symbol to access the drain function. Using a
@@ -1721,6 +1773,8 @@ export function buildContextEngineFactory(runtime, cfg, logger = console) {
1721
1773
  const isPostToolContinuation = lastUserIndex >= 0 && lastUserIndex < messages.length - 1
1722
1774
  && hasLiveToolProtocolAfterLastUser(messages, lastUserIndex);
1723
1775
  const lastUserMessage = findLastReplaySafeUserMessage(messages);
1776
+ const latestUserContent = typeof lastUserMessage?.content === "string" ? lastUserMessage.content : "";
1777
+ const retrievalQuery = normalizeRetrievalQuery(strippedPrompt, latestUserContent);
1724
1778
  const reservedCurrentTurnTokens = lastUserMessage
1725
1779
  ? approximateMessageTokens(lastUserMessage)
1726
1780
  : RESERVED_CURRENT_TURN_TOKENS;
@@ -1856,7 +1910,7 @@ export function buildContextEngineFactory(runtime, cfg, logger = console) {
1856
1910
  ]);
1857
1911
  const maxMemories = cfg.beforeTurnMaxMemories ?? 5;
1858
1912
  const clamped = btResult.predictions && btResult.predictions.length > maxMemories
1859
- ? selectTopByRelevance(btResult.predictions, strippedPrompt, maxMemories)
1913
+ ? selectTopByRelevance(btResult.predictions, retrievalQuery, maxMemories)
1860
1914
  : btResult.predictions;
1861
1915
  turnCache.set(sessionId, `${messages.length}:${beforeTurnQueryHint}`, { predictions: clamped });
1862
1916
  beforeTurnPredictions = clamped;
@@ -1873,7 +1927,7 @@ export function buildContextEngineFactory(runtime, cfg, logger = console) {
1873
1927
  sessionId,
1874
1928
  sessionKey: args.sessionKey,
1875
1929
  userId,
1876
- prompt: strippedPrompt,
1930
+ prompt: retrievalQuery,
1877
1931
  messages,
1878
1932
  tokenBudget: args.tokenBudget,
1879
1933
  config: buildAssemblyConfig(args.tokenBudget),
@@ -1894,7 +1948,7 @@ export function buildContextEngineFactory(runtime, cfg, logger = console) {
1894
1948
  ? { ...assembled, systemPromptAddition: appendSystemPromptAddition(assembled.systemPromptAddition, continuityContext) }
1895
1949
  : assembled;
1896
1950
  enforced = enforceTokenBudgetInvariant(await augmentWithExactRecall(withContinuity, {
1897
- queryText: strippedPrompt || (messages[messages.length - 1]?.content ?? ""),
1951
+ queryText: retrievalQuery,
1898
1952
  userId,
1899
1953
  sessionId,
1900
1954
  tokenBudget: args.tokenBudget,
package/dist/index.js CHANGED
@@ -35491,6 +35491,10 @@ var EXACT_RECALL_MAX_TOKENS = 4;
35491
35491
  var RESERVED_CURRENT_TURN_TOKENS = 150;
35492
35492
  var AFTER_TURN_INGEST_MAX_TOKENS = 2048;
35493
35493
  var OPENCLAW_LEADING_TIMESTAMP_PREFIX_RE = /^\[[A-Za-z]{3} \d{4}-\d{2}-\d{2} \d{2}:\d{2}[^\]]*\] */;
35494
+ var SELECTED_CONTEXT_HEADER = "Conversation context (untrusted, chronological, selected for current message):";
35495
+ var RETRIEVAL_QUERY_MAX_CHARS = 1e3;
35496
+ var SELECTED_CONTEXT_TURN_RE = /^#\d+\s+[A-Za-z]{3}\s+\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}(?::\d{2})?\s+\S+\s+([^:\n]{1,80}):\s*(.*)$/;
35497
+ var ASSISTANT_SPEAKER_RE = /\b(?:assistant|openclaw|z3robot|bot)\b/i;
35494
35498
  var OPENCLAW_METADATA_HEADERS = [
35495
35499
  "Conversation info (untrusted metadata):",
35496
35500
  "Sender (untrusted metadata):",
@@ -35656,6 +35660,46 @@ function normalizeKernelContent(content, options = {}) {
35656
35660
  retainContext: options.retainOpenClawContext === true
35657
35661
  });
35658
35662
  }
35663
+ function normalizeRetrievalQuery(primaryText, fallbackText = "") {
35664
+ const primary = normalizeRetrievalCandidate(primaryText);
35665
+ if (primary) return primary;
35666
+ return normalizeRetrievalCandidate(fallbackText);
35667
+ }
35668
+ function normalizeRetrievalCandidate(text) {
35669
+ const normalized = text.replace(OPENCLAW_LEADING_TIMESTAMP_PREFIX_RE, "").replace(/\r\n/g, "\n").trim();
35670
+ if (!normalized) return "";
35671
+ const selected = extractLatestSelectedContextUtterance(normalized);
35672
+ const candidate = selected || normalized;
35673
+ return capRetrievalQuery(candidate.replace(/\s+/g, " ").trim());
35674
+ }
35675
+ function extractLatestSelectedContextUtterance(text) {
35676
+ if (!text.startsWith(SELECTED_CONTEXT_HEADER)) return "";
35677
+ const turns = [];
35678
+ for (const rawLine of text.slice(SELECTED_CONTEXT_HEADER.length).split("\n")) {
35679
+ const line = rawLine.trim();
35680
+ if (!line) continue;
35681
+ const match = line.match(SELECTED_CONTEXT_TURN_RE);
35682
+ if (match) {
35683
+ turns.push({ speaker: match[1].trim(), text: [match[2].trim()] });
35684
+ continue;
35685
+ }
35686
+ if (turns.length > 0) {
35687
+ turns[turns.length - 1].text.push(line);
35688
+ }
35689
+ }
35690
+ for (let i = turns.length - 1; i >= 0; i--) {
35691
+ const turn = turns[i];
35692
+ const content = turn.text.join(" ").trim();
35693
+ if (content && !ASSISTANT_SPEAKER_RE.test(turn.speaker)) {
35694
+ return content;
35695
+ }
35696
+ }
35697
+ return "";
35698
+ }
35699
+ function capRetrievalQuery(text) {
35700
+ if (text.length <= RETRIEVAL_QUERY_MAX_CHARS) return text;
35701
+ return text.slice(text.length - RETRIEVAL_QUERY_MAX_CHARS);
35702
+ }
35659
35703
  var FLUSH_ASYNC_INGESTION = /* @__PURE__ */ Symbol("flushAsyncIngestion");
35660
35704
  var maxOptimizationMemoCacheSize = 5e4;
35661
35705
  var metadataEnvelopeCache = /* @__PURE__ */ new Map();
@@ -36950,6 +36994,8 @@ function buildContextEngineFactory(runtime, cfg, logger = console) {
36950
36994
  const lastUserIndex = findLastUserMessageIndex(messages);
36951
36995
  const isPostToolContinuation = lastUserIndex >= 0 && lastUserIndex < messages.length - 1 && hasLiveToolProtocolAfterLastUser(messages, lastUserIndex);
36952
36996
  const lastUserMessage = findLastReplaySafeUserMessage(messages);
36997
+ const latestUserContent = typeof lastUserMessage?.content === "string" ? lastUserMessage.content : "";
36998
+ const retrievalQuery = normalizeRetrievalQuery(strippedPrompt, latestUserContent);
36953
36999
  const reservedCurrentTurnTokens = lastUserMessage ? approximateMessageTokens(lastUserMessage) : RESERVED_CURRENT_TURN_TOKENS;
36954
37000
  const currentContextTokens = resolvePredictiveCompactionTokenCount({
36955
37001
  currentTokenCount: args.currentTokenCount,
@@ -37084,7 +37130,7 @@ function buildContextEngineFactory(runtime, cfg, logger = console) {
37084
37130
  )
37085
37131
  ]);
37086
37132
  const maxMemories = cfg.beforeTurnMaxMemories ?? 5;
37087
- const clamped = btResult.predictions && btResult.predictions.length > maxMemories ? selectTopByRelevance(btResult.predictions, strippedPrompt, maxMemories) : btResult.predictions;
37133
+ const clamped = btResult.predictions && btResult.predictions.length > maxMemories ? selectTopByRelevance(btResult.predictions, retrievalQuery, maxMemories) : btResult.predictions;
37088
37134
  turnCache.set(sessionId, `${messages.length}:${beforeTurnQueryHint}`, { predictions: clamped });
37089
37135
  beforeTurnPredictions = clamped;
37090
37136
  clearBeforeTurnCircuit(sessionId);
@@ -37101,7 +37147,7 @@ function buildContextEngineFactory(runtime, cfg, logger = console) {
37101
37147
  sessionId,
37102
37148
  sessionKey: args.sessionKey,
37103
37149
  userId,
37104
- prompt: strippedPrompt,
37150
+ prompt: retrievalQuery,
37105
37151
  messages,
37106
37152
  tokenBudget: args.tokenBudget,
37107
37153
  config: buildAssemblyConfig(args.tokenBudget),
@@ -37123,7 +37169,7 @@ function buildContextEngineFactory(runtime, cfg, logger = console) {
37123
37169
  const withContinuity = continuityContext ? { ...assembled, systemPromptAddition: appendSystemPromptAddition(assembled.systemPromptAddition, continuityContext) } : assembled;
37124
37170
  enforced = enforceTokenBudgetInvariant(
37125
37171
  await augmentWithExactRecall(withContinuity, {
37126
- queryText: strippedPrompt || (messages[messages.length - 1]?.content ?? ""),
37172
+ queryText: retrievalQuery,
37127
37173
  userId,
37128
37174
  sessionId,
37129
37175
  tokenBudget: args.tokenBudget,
@@ -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.9.10-beta.10",
5
+ "version": "1.9.10-beta.11",
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.9.10-beta.10",
3
+ "version": "1.9.10-beta.11",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",