@xdarkicex/openclaw-memory-libravdb 1.4.12 → 1.4.13
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/context-engine.js +107 -52
- package/dist/types.d.ts +1 -0
- package/openclaw.plugin.json +6 -1
- package/package.json +1 -1
package/dist/context-engine.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const APPROX_CHARS_PER_TOKEN = 4;
|
|
2
2
|
const ASSEMBLE_BUDGET_HEADROOM_TOKENS = 256;
|
|
3
|
+
const DEFAULT_COMPACTION_THRESHOLD_FRACTION = 0.8;
|
|
3
4
|
function requireSessionId(sessionId, operation) {
|
|
4
5
|
const normalized = typeof sessionId === "string" ? sessionId.trim() : "";
|
|
5
6
|
if (normalized.length > 0) {
|
|
@@ -100,6 +101,33 @@ function approximateMessageTokens(message) {
|
|
|
100
101
|
function approximateMessagesTokens(messages) {
|
|
101
102
|
return messages.reduce((sum, message) => sum + approximateMessageTokens(message), 0);
|
|
102
103
|
}
|
|
104
|
+
function normalizeTokenBudget(tokenBudget) {
|
|
105
|
+
if (typeof tokenBudget !== "number" || !Number.isFinite(tokenBudget) || tokenBudget <= 0) {
|
|
106
|
+
return undefined;
|
|
107
|
+
}
|
|
108
|
+
return Math.max(1, Math.floor(tokenBudget));
|
|
109
|
+
}
|
|
110
|
+
function resolveEffectiveAssembleBudget(tokenBudget) {
|
|
111
|
+
const normalized = normalizeTokenBudget(tokenBudget) ?? 1;
|
|
112
|
+
return Math.max(1, normalized - ASSEMBLE_BUDGET_HEADROOM_TOKENS);
|
|
113
|
+
}
|
|
114
|
+
function normalizeThresholdFraction(fraction) {
|
|
115
|
+
if (typeof fraction !== "number" || !Number.isFinite(fraction)) {
|
|
116
|
+
return DEFAULT_COMPACTION_THRESHOLD_FRACTION;
|
|
117
|
+
}
|
|
118
|
+
return Math.min(0.99, Math.max(0.05, fraction));
|
|
119
|
+
}
|
|
120
|
+
function resolveDynamicCompactThreshold(tokenBudget, compactThreshold, compactionThresholdFraction) {
|
|
121
|
+
if (typeof compactThreshold === "number" && Number.isFinite(compactThreshold) && compactThreshold > 0) {
|
|
122
|
+
return Math.max(1, Math.floor(compactThreshold));
|
|
123
|
+
}
|
|
124
|
+
const normalizedBudget = normalizeTokenBudget(tokenBudget);
|
|
125
|
+
if (normalizedBudget == null) {
|
|
126
|
+
return undefined;
|
|
127
|
+
}
|
|
128
|
+
const fraction = normalizeThresholdFraction(compactionThresholdFraction);
|
|
129
|
+
return Math.max(1, Math.floor(normalizedBudget * fraction));
|
|
130
|
+
}
|
|
103
131
|
function truncateContentToTokenBudget(content, tokenBudget) {
|
|
104
132
|
if (tokenBudget <= 0)
|
|
105
133
|
return "";
|
|
@@ -140,7 +168,7 @@ function enforceTokenBudgetInvariant(result, tokenBudget) {
|
|
|
140
168
|
return result;
|
|
141
169
|
}
|
|
142
170
|
const hardBudget = Math.max(1, Math.floor(tokenBudget));
|
|
143
|
-
const effectiveBudget =
|
|
171
|
+
const effectiveBudget = resolveEffectiveAssembleBudget(hardBudget);
|
|
144
172
|
const estimated = typeof result.estimatedTokens === "number" ? result.estimatedTokens : 0;
|
|
145
173
|
const approxFromMessages = approximateMessagesTokens(result.messages);
|
|
146
174
|
if (estimated <= effectiveBudget && approxFromMessages <= effectiveBudget) {
|
|
@@ -154,6 +182,15 @@ function enforceTokenBudgetInvariant(result, tokenBudget) {
|
|
|
154
182
|
estimatedTokens: Math.min(effectiveBudget, trimmedEstimate),
|
|
155
183
|
};
|
|
156
184
|
}
|
|
185
|
+
function buildBudgetFallbackContext(messages, tokenBudget) {
|
|
186
|
+
const effectiveBudget = resolveEffectiveAssembleBudget(tokenBudget);
|
|
187
|
+
const fallbackMessages = trimMessagesToBudget(messages.map((message) => ({ ...message })), effectiveBudget);
|
|
188
|
+
return {
|
|
189
|
+
messages: fallbackMessages,
|
|
190
|
+
estimatedTokens: approximateMessagesTokens(fallbackMessages),
|
|
191
|
+
systemPromptAddition: "",
|
|
192
|
+
};
|
|
193
|
+
}
|
|
157
194
|
export function normalizeKernelMessage(message) {
|
|
158
195
|
return {
|
|
159
196
|
role: message.role,
|
|
@@ -184,6 +221,38 @@ export function normalizeAssembleResult(result) {
|
|
|
184
221
|
};
|
|
185
222
|
}
|
|
186
223
|
export function buildContextEngineFactory(runtime, cfg, recallCache, logger = console) {
|
|
224
|
+
const getDynamicCompactThreshold = (tokenBudget) => resolveDynamicCompactThreshold(tokenBudget, cfg.compactThreshold, cfg.compactionThresholdFraction);
|
|
225
|
+
const buildAssemblyConfig = (tokenBudget) => ({
|
|
226
|
+
useSessionRecallProjection: cfg.useSessionRecallProjection,
|
|
227
|
+
useSessionSummarySearchExperiment: cfg.useSessionSummarySearchExperiment,
|
|
228
|
+
tokenBudgetFraction: cfg.tokenBudgetFraction,
|
|
229
|
+
authoredHardBudgetFraction: cfg.authoredHardBudgetFraction,
|
|
230
|
+
authoredSoftBudgetFraction: cfg.authoredSoftBudgetFraction,
|
|
231
|
+
elevatedGuidanceBudgetFraction: cfg.elevatedGuidanceBudgetFraction,
|
|
232
|
+
topK: cfg.topK,
|
|
233
|
+
continuityMinTurns: cfg.continuityMinTurns,
|
|
234
|
+
continuityTailBudgetTokens: cfg.continuityTailBudgetTokens,
|
|
235
|
+
continuityPriorContextTokens: cfg.continuityPriorContextTokens,
|
|
236
|
+
compactThreshold: getDynamicCompactThreshold(tokenBudget),
|
|
237
|
+
compactSessionTokenBudget: cfg.compactSessionTokenBudget,
|
|
238
|
+
section7Theta1: cfg.section7Theta1,
|
|
239
|
+
section7Kappa: cfg.section7Kappa,
|
|
240
|
+
section7HopEta: cfg.section7HopEta,
|
|
241
|
+
section7HopThreshold: cfg.section7HopThreshold,
|
|
242
|
+
section7CoarseTopK: cfg.section7CoarseTopK,
|
|
243
|
+
section7SecondPassTopK: cfg.section7SecondPassTopK,
|
|
244
|
+
section7AuthorityRecencyLambda: cfg.section7AuthorityRecencyLambda,
|
|
245
|
+
section7AuthorityRecencyWeight: cfg.section7AuthorityRecencyWeight,
|
|
246
|
+
section7AuthorityFrequencyWeight: cfg.section7AuthorityFrequencyWeight,
|
|
247
|
+
section7AuthorityAuthoredWeight: cfg.section7AuthorityAuthoredWeight,
|
|
248
|
+
recoveryFloorScore: cfg.recoveryFloorScore,
|
|
249
|
+
recoveryMinTopK: cfg.recoveryMinTopK,
|
|
250
|
+
recoveryMinConfidenceMean: cfg.recoveryMinConfidenceMean,
|
|
251
|
+
recencyLambdaSession: cfg.recencyLambdaSession,
|
|
252
|
+
recencyLambdaUser: cfg.recencyLambdaUser,
|
|
253
|
+
recencyLambdaGlobal: cfg.recencyLambdaGlobal,
|
|
254
|
+
ingestionGateThreshold: cfg.ingestionGateThreshold,
|
|
255
|
+
});
|
|
187
256
|
function buildCompactSessionRequest(args) {
|
|
188
257
|
// OpenClaw core now requests budget-style compaction using tokenBudget,
|
|
189
258
|
// but the current LibraVDB compact_session wire contract still expects
|
|
@@ -205,6 +274,24 @@ export function buildContextEngineFactory(runtime, cfg, recallCache, logger = co
|
|
|
205
274
|
: {}),
|
|
206
275
|
};
|
|
207
276
|
}
|
|
277
|
+
async function runCompaction(args) {
|
|
278
|
+
const request = buildCompactSessionRequest(args);
|
|
279
|
+
const kernel = runtime.getKernel();
|
|
280
|
+
try {
|
|
281
|
+
if (kernel) {
|
|
282
|
+
return normalizeCompactResult(await kernel.compactSession(request));
|
|
283
|
+
}
|
|
284
|
+
const rpc = await runtime.getRpc();
|
|
285
|
+
return normalizeCompactResult(await rpc.call("compact_session", request));
|
|
286
|
+
}
|
|
287
|
+
catch (error) {
|
|
288
|
+
return {
|
|
289
|
+
ok: false,
|
|
290
|
+
compacted: false,
|
|
291
|
+
reason: error instanceof Error ? error.message : String(error),
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
}
|
|
208
295
|
return {
|
|
209
296
|
info: { id: "libravdb-memory", name: "LibraVDB Memory", ownsCompaction: true },
|
|
210
297
|
ownsCompaction: true,
|
|
@@ -249,6 +336,20 @@ export function buildContextEngineFactory(runtime, cfg, recallCache, logger = co
|
|
|
249
336
|
},
|
|
250
337
|
async assemble(args) {
|
|
251
338
|
const messages = normalizeKernelMessages(args.messages);
|
|
339
|
+
const currentContextTokens = approximateMessagesTokens(messages) + approximateTokenCount(args.prompt ?? "");
|
|
340
|
+
const dynamicCompactThreshold = getDynamicCompactThreshold(args.tokenBudget);
|
|
341
|
+
if (dynamicCompactThreshold != null &&
|
|
342
|
+
currentContextTokens >= dynamicCompactThreshold) {
|
|
343
|
+
const compactionResult = await runCompaction({
|
|
344
|
+
sessionId: args.sessionId,
|
|
345
|
+
tokenBudget: args.tokenBudget,
|
|
346
|
+
force: true,
|
|
347
|
+
});
|
|
348
|
+
if (!compactionResult.ok || !compactionResult.compacted) {
|
|
349
|
+
logger.warn?.(`LibraVDB predictive compaction blocked assemble path at ${currentContextTokens} tokens (threshold=${dynamicCompactThreshold}): ${compactionResult.reason ?? "compaction declined"}`);
|
|
350
|
+
return buildBudgetFallbackContext(messages, args.tokenBudget);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
252
353
|
const kernel = runtime.getKernel();
|
|
253
354
|
if (kernel) {
|
|
254
355
|
try {
|
|
@@ -259,18 +360,13 @@ export function buildContextEngineFactory(runtime, cfg, recallCache, logger = co
|
|
|
259
360
|
queryText: args.prompt ?? "",
|
|
260
361
|
visibleMessages: messages,
|
|
261
362
|
tokenBudget: args.tokenBudget,
|
|
262
|
-
config:
|
|
363
|
+
config: buildAssemblyConfig(args.tokenBudget),
|
|
263
364
|
emitDebug: true
|
|
264
365
|
})), args.tokenBudget);
|
|
265
366
|
}
|
|
266
367
|
catch (error) {
|
|
267
368
|
logger.warn?.(`LibraVDB assemble kernel failed, using budget-clamped fallback context: ${error instanceof Error ? error.message : String(error)}`);
|
|
268
|
-
|
|
269
|
-
return {
|
|
270
|
-
messages: fallbackMessages,
|
|
271
|
-
estimatedTokens: approximateMessagesTokens(fallbackMessages),
|
|
272
|
-
systemPromptAddition: "",
|
|
273
|
-
};
|
|
369
|
+
return buildBudgetFallbackContext(messages, args.tokenBudget);
|
|
274
370
|
}
|
|
275
371
|
}
|
|
276
372
|
const rpc = await runtime.getRpc();
|
|
@@ -283,58 +379,17 @@ export function buildContextEngineFactory(runtime, cfg, recallCache, logger = co
|
|
|
283
379
|
tokenBudget: args.tokenBudget,
|
|
284
380
|
prompt: args.prompt,
|
|
285
381
|
emitDebug: true,
|
|
286
|
-
config:
|
|
287
|
-
useSessionRecallProjection: cfg.useSessionRecallProjection,
|
|
288
|
-
useSessionSummarySearchExperiment: cfg.useSessionSummarySearchExperiment,
|
|
289
|
-
tokenBudgetFraction: cfg.tokenBudgetFraction,
|
|
290
|
-
authoredHardBudgetFraction: cfg.authoredHardBudgetFraction,
|
|
291
|
-
authoredSoftBudgetFraction: cfg.authoredSoftBudgetFraction,
|
|
292
|
-
elevatedGuidanceBudgetFraction: cfg.elevatedGuidanceBudgetFraction,
|
|
293
|
-
topK: cfg.topK,
|
|
294
|
-
continuityMinTurns: cfg.continuityMinTurns,
|
|
295
|
-
continuityTailBudgetTokens: cfg.continuityTailBudgetTokens,
|
|
296
|
-
continuityPriorContextTokens: cfg.continuityPriorContextTokens,
|
|
297
|
-
compactThreshold: cfg.compactThreshold,
|
|
298
|
-
compactSessionTokenBudget: cfg.compactSessionTokenBudget,
|
|
299
|
-
section7Theta1: cfg.section7Theta1,
|
|
300
|
-
section7Kappa: cfg.section7Kappa,
|
|
301
|
-
section7HopEta: cfg.section7HopEta,
|
|
302
|
-
section7HopThreshold: cfg.section7HopThreshold,
|
|
303
|
-
section7CoarseTopK: cfg.section7CoarseTopK,
|
|
304
|
-
section7SecondPassTopK: cfg.section7SecondPassTopK,
|
|
305
|
-
section7AuthorityRecencyLambda: cfg.section7AuthorityRecencyLambda,
|
|
306
|
-
section7AuthorityRecencyWeight: cfg.section7AuthorityRecencyWeight,
|
|
307
|
-
section7AuthorityFrequencyWeight: cfg.section7AuthorityFrequencyWeight,
|
|
308
|
-
section7AuthorityAuthoredWeight: cfg.section7AuthorityAuthoredWeight,
|
|
309
|
-
recoveryFloorScore: cfg.recoveryFloorScore,
|
|
310
|
-
recoveryMinTopK: cfg.recoveryMinTopK,
|
|
311
|
-
recoveryMinConfidenceMean: cfg.recoveryMinConfidenceMean,
|
|
312
|
-
recencyLambdaSession: cfg.recencyLambdaSession,
|
|
313
|
-
recencyLambdaUser: cfg.recencyLambdaUser,
|
|
314
|
-
recencyLambdaGlobal: cfg.recencyLambdaGlobal,
|
|
315
|
-
ingestionGateThreshold: cfg.ingestionGateThreshold,
|
|
316
|
-
},
|
|
382
|
+
config: buildAssemblyConfig(args.tokenBudget),
|
|
317
383
|
});
|
|
318
384
|
return enforceTokenBudgetInvariant(normalizeAssembleResult(resp), args.tokenBudget);
|
|
319
385
|
}
|
|
320
386
|
catch (error) {
|
|
321
387
|
logger.warn?.(`LibraVDB assemble sidecar failed, using budget-clamped fallback context: ${error instanceof Error ? error.message : String(error)}`);
|
|
322
|
-
|
|
323
|
-
return {
|
|
324
|
-
messages: fallbackMessages,
|
|
325
|
-
estimatedTokens: approximateMessagesTokens(fallbackMessages),
|
|
326
|
-
systemPromptAddition: "",
|
|
327
|
-
};
|
|
388
|
+
return buildBudgetFallbackContext(messages, args.tokenBudget);
|
|
328
389
|
}
|
|
329
390
|
},
|
|
330
391
|
async compact(args) {
|
|
331
|
-
|
|
332
|
-
const kernel = runtime.getKernel();
|
|
333
|
-
if (kernel) {
|
|
334
|
-
return normalizeCompactResult(await kernel.compactSession(request));
|
|
335
|
-
}
|
|
336
|
-
const rpc = await runtime.getRpc();
|
|
337
|
-
return normalizeCompactResult(await rpc.call("compact_session", request));
|
|
392
|
+
return await runCompaction(args);
|
|
338
393
|
},
|
|
339
394
|
async afterTurn(args) {
|
|
340
395
|
const messages = normalizeKernelMessages(args.messages);
|
package/dist/types.d.ts
CHANGED
|
@@ -63,6 +63,7 @@ export interface PluginConfig {
|
|
|
63
63
|
continuityTailBudgetTokens?: number;
|
|
64
64
|
continuityPriorContextTokens?: number;
|
|
65
65
|
compactThreshold?: number;
|
|
66
|
+
compactionThresholdFraction?: number;
|
|
66
67
|
compactSessionTokenBudget?: number;
|
|
67
68
|
section7CoarseTopK?: number;
|
|
68
69
|
section7SecondPassTopK?: number;
|
package/openclaw.plugin.json
CHANGED
|
@@ -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.
|
|
5
|
+
"version": "1.4.13",
|
|
6
6
|
"kind": [
|
|
7
7
|
"memory",
|
|
8
8
|
"context-engine"
|
|
@@ -237,6 +237,11 @@
|
|
|
237
237
|
"compactThreshold": {
|
|
238
238
|
"type": "number"
|
|
239
239
|
},
|
|
240
|
+
"compactionThresholdFraction": {
|
|
241
|
+
"type": "number",
|
|
242
|
+
"default": 0.8,
|
|
243
|
+
"description": "Dynamic predictive compaction trigger ratio against the active token budget. Used when compactThreshold is not explicitly set."
|
|
244
|
+
},
|
|
240
245
|
"compactSessionTokenBudget": {
|
|
241
246
|
"type": "number",
|
|
242
247
|
"default": 2000,
|